diff --git a/.github/actions/0_setup/action.yml b/.github/actions/0_setup/action.yml new file mode 100644 index 000000000..24bcf9db8 --- /dev/null +++ b/.github/actions/0_setup/action.yml @@ -0,0 +1,23 @@ +name: 'Setup Environment' +description: 'Setup Environment' + +inputs: + qt-version: + description: 'Qt Version' + required: false + default: '5.15.2' + +runs: + using: "composite" + steps: + - name: Setup MSVC + uses: ilammy/msvc-dev-cmd@v1 + - name: Install Qt + uses: jurplel/install-qt-action@v3 + with: + cache: true + version: ${{ inputs.qt-version }} + - name: Install dependencies + shell: bash + run: | + bash scripts/${{ runner.os }}/0_setup_env.sh --dont_install_qt \ No newline at end of file diff --git a/.github/actions/1_build/action.yml b/.github/actions/1_build/action.yml new file mode 100644 index 000000000..e0d0f7b0a --- /dev/null +++ b/.github/actions/1_build/action.yml @@ -0,0 +1,56 @@ +name: 'Build' +description: 'Build' + +inputs: + cache-path: + description: 'Directory to cache after build' + required: false + default: '' + cache-key: + description: 'Cache key' + required: false + default: '' + build-option: + description: 'Build option' + required: false + default: '' + nightly: + description: 'Nightly build' + required: false + type: boolean + default: false + +runs: + using: "composite" + steps: + - name: Setup env variables + id: envs + shell: bash + run: | + if [ "${{ inputs.build-option }}" != "" ]; then + echo "build_option=--${{ inputs.build-option }}" >> $GITHUB_OUTPUT + echo "artifact_suffix=_${{ inputs.build-option }}" >> $GITHUB_OUTPUT + else + echo "build_option=" >> $GITHUB_OUTPUT + echo "artifact_suffix=" >> $GITHUB_OUTPUT + fi + if [ "${{ inputs.nightly }}" = "true" ]; then + echo "nightly=--nightly" >> $GITHUB_OUTPUT + else + echo "nightly=" >> $GITHUB_OUTPUT + fi + - name: Cache external libraries sources + id: cache-ext-libs + if: ${{ inputs.cache-path != '' }} + uses: actions/cache@v3 + with: + path: ${{ inputs.cache-path }} + key: ${{ runner.os }}-${{ inputs.cache-key }} + - name: Ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ runner.os }}-${{ github.ref }}-${{ inputs.build-option }} + - name: Configure and Build + shell: bash + run: | + bash scripts/${{ runner.os }}/1_build.sh ${{ steps.envs.outputs.build_option }} ${{ steps.envs.outputs.nightly }} --ccache \ No newline at end of file diff --git a/.github/actions/2_deploy/action.yml b/.github/actions/2_deploy/action.yml new file mode 100644 index 000000000..69b582081 --- /dev/null +++ b/.github/actions/2_deploy/action.yml @@ -0,0 +1,65 @@ +name: 'Deploy' +description: 'Deploy' + +inputs: + mac-certificate: + description: 'MacOS Certificate' + required: false + default: '' + mac-certificate-id: + description: 'MacOS Certificate ID' + required: false + default: '' + mac-certificate-pssw: + description: 'MacOS Certificate Password' + required: false + mac-notarization-user: + description: 'MacOS Notarization User' + required: false + default: '' + mac-notarization-team: + description: 'MacOS Notarization Team' + required: false + default: '' + mac-notarization-pssw: + description: 'MacOS Notarization Password' + required: false + default: '' + win-certificate: + description: 'Windows Certificate' + required: false + default: '' + win-certificate-pssw: + description: 'Windows Certificate Password' + required: false + default: '' + +runs: + using: "composite" + steps: + - name: Set Notarization settings + id: notarization + shell: bash + run: | + if [ "${{ inputs.mac-notarization-user }}" != "" ]; then + echo "not_setting=--notarization_user='${{ inputs.mac-notarization-user }}' --notarization_team='${{ inputs.mac-notarization-team }}' --notarization_pssw='${{ inputs.mac-notarization-pssw }}'" >> $GITHUB_OUTPUT + else + echo "not_setting=" >> $GITHUB_OUTPUT + fi + - name: Set CodeSign Certificate macOS + if: ${{ runner.os == 'macOS' && inputs.mac-certificate != ''}} + uses: apple-actions/import-codesign-certs@v2 + with: + p12-file-base64: ${{ inputs.mac-certificate }} + p12-password: ${{ inputs.mac-certificate-pssw }} + - name: Set CodeSign Certificate Windows + shell: powershell + if: ${{ runner.os == 'Windows' && inputs.win-certificate != '' }} + run: | + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ inputs.win-certificate }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + - name: Deploy + shell: bash + run: | + bash scripts/${{ runner.os }}/2_deploy.sh --cert_pssw='${{ inputs.win-certificate-pssw }}' --cert_id='${{ inputs.mac-certificate-id }}' ${{ steps.notarization.outputs.not_setting }} \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..7f7a2f929 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,10 @@ +## Thank you for sending a Pull Request to MeshLab! + +On this repository, we keep two relevant branches: + +- `main`: we keep here the **last release version of MeshLab**, with just bugfixes. In case of serious bugs caught after a release, this branch is used to publish "post-releases". +- `devel`: we add here new features and functionalities of the software that are going to appear in the next release of MeshLab. Bugfixes pushed in `main` are automatically merged on the `devel` branch. + +Before submitting a PR, please check which branch suits better for your contribution! + +**PLEASE REMOVE THIS BEFORE SUBMITTING** diff --git a/.github/stale.yml b/.github/stale.yml index 2c77dc1c0..a985a99e7 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -34,9 +34,10 @@ staleLabel: wontfix # Comment to post when marking as stale. Set to `false` to disable markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. + This issue has been automatically marked as stale because it has not had recent activity. The resources of the VCLab team are limited, and so we are asking for your help. + If this is a bug and you can still reproduce this error on the last release of MeshLab, please reply with all of the information you have about it in order to keep the issue open. + If this is a feature request, and you feel that it is still relevant and valuable, please tell us why. + This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions. # Comment to post when removing the stale label. # unmarkComment: > @@ -50,7 +51,7 @@ markComment: > limitPerRun: 10 # Limit to only `issues` or `pulls` -# only: issues +only: issues # Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': # pulls: diff --git a/.github/workflows/AutoMergeMainOnDevel.yml b/.github/workflows/AutoMergeMainOnDevel.yml new file mode 100644 index 000000000..1800f780e --- /dev/null +++ b/.github/workflows/AutoMergeMainOnDevel.yml @@ -0,0 +1,22 @@ +name: AutoMergeMainOnDevel + +on: + push: + branches: + - 'main' + +jobs: + auto_merge: + if: github.repository == 'cnr-isti-vclab/meshlab' + name: Automatic Merge Main On Devel + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Merge main -> devel + uses: devmasx/merge-branch@master + with: + type: now + target_branch: devel + message: "Automatic merge branch 'main' into 'devel'" + github_token: ${{ github.token }} diff --git a/.github/workflows/BuildMeshLab.yml b/.github/workflows/BuildMeshLab.yml new file mode 100644 index 000000000..97333163c --- /dev/null +++ b/.github/workflows/BuildMeshLab.yml @@ -0,0 +1,60 @@ +name: BuildMeshLab + +on: + [push, pull_request] + +env: + QT_VERSION: 5.15.2 + MAC_CERT: ${{secrets.MACOS_CERT_ID}} + MAC_CERT_PSSW: ${{secrets.MACOS_CERTIFICATE_PSSW}} + WIN_CERT: ${{secrets.WIN_CERTIFICATE}} + +jobs: + meshlab_build: + name: Build MeshLab + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ['ubuntu-20.04', 'macos-latest', 'windows-latest'] + precision: [single_precision, double_precision] + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Setup Environment + uses: ./.github/actions/0_setup + - name: Setup env variables + id: envs + shell: bash + run: | + if [ "${{matrix.precision}}" == "double_precision" ]; then + echo "artifact_suffix=_double" >> $GITHUB_OUTPUT + else + echo "artifact_suffix=" >> $GITHUB_OUTPUT + fi + - name: Build + uses: ./.github/actions/1_build + with: + cache-path: src/external/downloads/* + cache-key: external-libraries + build-option: ${{matrix.precision}} + nightly: true + - name: Deploy + uses: ./.github/actions/2_deploy + with: + mac-certificate: ${{ secrets.MACOS_CERTIFICATE }} + mac-certificate-id: ${{ secrets.MACOS_CERT_ID }} + mac-certificate-pssw: ${{ secrets.MACOS_CERTIFICATE_PSSW }} + win-certificate: ${{ secrets.WIN_CERTIFICATE }} + win-certificate-pssw: ${{ secrets.WIN_CERTIFICATE_PSSW }} + - name: Upload MeshLab Portable + uses: actions/upload-artifact@v3 + with: + name: MeshLab_${{ runner.os }}_portable${{steps.envs.outputs.artifact_suffix}} + path: install/ + - name: Upload MeshLab Packages + uses: actions/upload-artifact@v3 + with: + name: MeshLab_${{ runner.os }}_packages${{steps.envs.outputs.artifact_suffix}} + path: packages/MeshLab* \ No newline at end of file diff --git a/.github/workflows/CreateRelease.yml b/.github/workflows/CreateRelease.yml index 9890bc663..ea091dc19 100644 --- a/.github/workflows/CreateRelease.yml +++ b/.github/workflows/CreateRelease.yml @@ -9,413 +9,213 @@ on: required: true default: 'YYYY.MM' +env: + QT_VERSION: 5.15.2 jobs: update_ml_version: - name: Update ML_VERSION, snapcraft.yaml and Info.plist - runs-on: macos-latest + name: Update ML_VERSION + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - name: Update MeshLab version run : | echo ${{ github.event.inputs.version }} | tr -d '\n'> ML_VERSION - - name: Update Info.plist - run: | - /usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString ${{ github.event.inputs.version }}" src/meshlab/Info.plist - /usr/libexec/PlistBuddy -c "Set CFBundleVersion ${{ github.event.inputs.version }}" src/meshlab/Info.plist - - name: Update Snap file - run: | - sed "s%MESHLAB_VERSION%$(cat ML_VERSION)%g" scripts/Linux/resources/snap/snap_noversion.yaml > snapcraft.yaml - - name: commit ML_VERSION, snapcraft.yaml and Info.plist change - uses: stefanzweifel/git-auto-commit-action@v4.1.1 + - name: commit ML_VERSION change + uses: stefanzweifel/git-auto-commit-action@v4 with: - commit_message: Apply automatic ML_VERSION, snapcraft.yaml and Info.plist change + commit_message: Set MeshLab version to ${{ github.event.inputs.version }} - linux_build: + meshlab_build: needs: [update_ml_version] - name: Build MeshLab (Linux) - runs-on: ubuntu-16.04 #in order to deploy, need to use oldest supported version + name: Build MeshLab + runs-on: ${{ matrix.os }} strategy: matrix: + os: ['ubuntu-20.04', 'macos-latest', 'windows-latest'] precision: [single_precision, double_precision] - steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: - ref: master - submodules: true - - name: Install Qt - uses: jurplel/install-qt-action@v2 - - name: Install dependencies - run: | - sudo apt-get install -y mesa-common-dev libglu1-mesa-dev libgmp-dev - #needed by qt 5.15 on linux - sudo apt-get install libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-render-util0-dev libxcb-xinerama0-dev + submodules: recursive + ref: main + - name: Setup Environment + uses: ./.github/actions/0_setup - name: Setup env variables id: envs shell: bash run: | if [ "${{matrix.precision}}" == "double_precision" ]; then - echo ::set-output name=version::"$(cat ML_VERSION)d" - echo ::set-output name=artifact_suffix::"_double" + echo "artifact_suffix=_double" >> $GITHUB_OUTPUT else - echo ::set-output name=version::"$(cat ML_VERSION)" - echo ::set-output name=artifact_suffix::"" + echo "artifact_suffix=" >> $GITHUB_OUTPUT fi - - name: Configure and Build - run: | - sh scripts/${{ runner.os }}/1_build.sh --${{ matrix.precision }} + - name: Build + uses: ./.github/actions/1_build + with: + cache-path: src/external/downloads/* + cache-key: external-libraries + build-option: ${{matrix.precision}} - name: Deploy - run: | - sh scripts/${{ runner.os }}/2_deploy.sh - - name: Build MeshLab AppImage - run : | - sh scripts/${{ runner.os }}/3_appimage.sh --${{ matrix.precision }} - - name: Upload Meshlab Portable - uses: actions/upload-artifact@v1 + uses: ./.github/actions/2_deploy with: - name: meshlab_linux_portable${{steps.envs.outputs.artifact_suffix}} - path: src/install/ - - name: Upload Meshlab AppImage - uses: actions/upload-artifact@v1 - with: - name: meshlab_linux_appimage${{steps.envs.outputs.artifact_suffix}} - path: src/MeshLab${{steps.envs.outputs.version}}-linux.AppImage - - macos_build: - needs: [update_ml_version] - name: Build MeshLab (MacOS) - runs-on: macos-latest - strategy: - matrix: - precision: [single_precision, double_precision] - - steps: - - uses: actions/checkout@v2 - with: - ref: master - submodules: true - - name: Install dependencies - run: | - brew install libomp - npm install -g appdmg - - name: Install Qt - uses: jurplel/install-qt-action@v2 - - name: Setup env variables - id: envs - shell: bash - run: | - if [ "${{matrix.precision}}" == "double_precision" ]; then - echo ::set-output name=version::"$(cat ML_VERSION)d" - echo ::set-output name=artifact_suffix::"_double" - else - echo ::set-output name=version::"$(cat ML_VERSION)" - echo ::set-output name=artifact_suffix::"" - fi - - name: Configure and Build - run: | - sh scripts/${{ runner.os }}/1_build.sh --${{ matrix.precision }} - - name: Deploy - run: | - sh scripts/${{ runner.os }}/2_deploy.sh - - name: Create MeshLab DMG - run: | - sh scripts/${{ runner.os }}/3_dmg.sh --${{ matrix.precision }} - mv src/install/MeshLab${{steps.envs.outputs.version}}.dmg src/install/MeshLab${{steps.envs.outputs.version}}-macos.dmg + mac-certificate: ${{ secrets.MACOS_CERTIFICATE }} + mac-certificate-id: ${{ secrets.MACOS_CERT_ID }} + mac-certificate-pssw: ${{ secrets.MACOS_CERTIFICATE_PSSW }} + mac-notarization-user: ${{ secrets.MACOS_NOTARIZATION_USER }} + mac-notarization-team: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }} + mac-notarization-pssw: ${{ secrets.MACOS_NOTARIZATION_PSSW }} + win-certificate: ${{ secrets.WIN_CERTIFICATE }} + win-certificate-pssw: ${{ secrets.WIN_CERTIFICATE_PSSW }} - name: Upload MeshLab Portable - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v3 with: - name: meshlab_macos_portable${{steps.envs.outputs.artifact_suffix}} - path: src/install/meshlab.app - - name: Upload DMG - uses: actions/upload-artifact@v1 + name: MeshLab_${{ runner.os }}_portable${{steps.envs.outputs.artifact_suffix}} + path: install/ + - name: Upload MeshLab Packages + uses: actions/upload-artifact@v3 with: - name: meshlab_macos_dmg${{steps.envs.outputs.artifact_suffix}} - path: src/install/MeshLab${{steps.envs.outputs.version}}-macos.dmg - - windows_build: - needs: [update_ml_version] - name: Build MeshLab (Windows) - runs-on: windows-latest - strategy: - matrix: - precision: [single_precision, double_precision] - - steps: - - uses: actions/checkout@v2 - with: - ref: master - submodules: true - - name: Download Jom - run: | - Invoke-WebRequest -Uri "http://download.qt.io/official_releases/jom/jom_1_1_3.zip" -OutFile "jom_1_1_3.zip" - New-Item -Name "jom" -ItemType "directory" - Expand-Archive -Path jom_1_1_3.zip -DestinationPath .\jom - echo "$(Get-Location)\jom" >> GITHUB_PATH - - name: Setup MSVC - uses: ilammy/msvc-dev-cmd@v1 - - name: Install Qt - uses: jurplel/install-qt-action@v2 - - name: Setup env variables - shell: bash - id: envs - run: | - if [ "${{matrix.precision}}" == "double_precision" ]; then - echo ::set-output name=version::"$(cat ML_VERSION)d" - echo ::set-output name=artifact_suffix::"_double" - else - echo ::set-output name=version::"$(cat ML_VERSION)" - echo ::set-output name=artifact_suffix::"" - fi - echo "VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC" >> $GITHUB_ENV - - name: Configure and Build - shell: bash - run: | - sh scripts/${{ runner.os }}/1_build.sh --${{ matrix.precision }} - - name: Deploy - shell: bash - run: | - sh scripts/${{ runner.os }}/2_deploy.sh - - name: NSIS script - shell: bash - run: | - sh scripts/${{ runner.os }}/resources/nsis_script.sh --${{ matrix.precision }} - - name: Create Installer - uses: joncloud/makensis-action@v1 - with: - script-file: "src/install/meshlab_final.nsi" - - name: Rename Installer - shell: bash - run: | - mv src/install/MeshLab${{steps.envs.outputs.version}}.exe src/MeshLab${{steps.envs.outputs.version}}-windows.exe - - name: Uploading MeshLab Portable - uses: actions/upload-artifact@v1 - with: - name: meshlab_windows_portable${{steps.envs.outputs.artifact_suffix}} - path: src/install - - name: Upload Meshlab Installer - uses: actions/upload-artifact@v1 - with: - name: meshlab_windows_installer${{steps.envs.outputs.artifact_suffix}} - path: src/MeshLab${{steps.envs.outputs.version}}-windows.exe + name: MeshLab_${{ runner.os }}_packages${{steps.envs.outputs.artifact_suffix}} + path: packages/MeshLab* #after building MeshLab for the three platforms, we create a release in github create_release: name: Create Release - needs: [linux_build, macos_build, windows_build] + needs: [meshlab_build] runs-on: ubuntu-latest steps: #Download Linux Packages - name: Download Linux ZIP - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: - name: meshlab_linux_portable + name: MeshLab_Linux_portable + path: meshlab_linux_portable - name: Download Linux ZIP-d - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: - name: meshlab_linux_portable_double + name: MeshLab_Linux_portable_double + path: meshlab_linux_portable_double - name: Download Linux AppImage - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: - name: meshlab_linux_appimage + name: MeshLab_Linux_packages + path: meshlab_linux_appimage - name: Download Linux AppImage-d - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: - name: meshlab_linux_appimage_double + name: MeshLab_Linux_packages_double + path: meshlab_linux_appimage_double - name: Change Permissions run: | chmod +x meshlab_linux_portable/usr/bin/meshlab chmod +x meshlab_linux_portable/AppRun chmod +x meshlab_linux_portable_double/usr/bin/meshlab chmod +x meshlab_linux_portable_double/AppRun + - name: Setup env variables + id: envs + shell: bash + run: | + #get version of meshlab + IFS=' ' #space delimiter + STR_VERSION=$(meshlab_linux_portable/usr/bin/meshlab --version) + read -a strarr <<< "$STR_VERSION" + ML_VERSION=${strarr[1]} #get the meshlab version from the string + echo "ml_version=$ML_VERSION" >> $GITHUB_OUTPUT + STR_VERSION=$(meshlab_linux_portable_double/usr/bin/meshlab --version) + read -a strarrd <<< "$STR_VERSION" + ML_VERSION_D=${strarrd[1]} #get the meshlab version from the string + echo "ml_version_d=$ML_VERSION_D" >> $GITHUB_OUTPUT + #access to this variable using ${{steps.envs.outputs.ml_version}} or ${{steps.envs.outputs.ml_version_d}} - name: Create MeshLab Portable Linux Archive run: | - tar -cvzf MeshLab${{ github.event.inputs.version }}-linux.tar.gz meshlab_linux_portable/ - tar -cvzf MeshLab${{ github.event.inputs.version }}d-linux.tar.gz meshlab_linux_portable_double/ - + cd meshlab_linux_portable + tar -cvzf ../MeshLab${{steps.envs.outputs.ml_version}}-linux.tar.gz * + cd ../meshlab_linux_portable_double + tar -cvzf ../MeshLab${{steps.envs.outputs.ml_version_d}}-linux.tar.gz * + cd .. #Download MacOS Package - name: Download MacOS DMG - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: - name: meshlab_macos_dmg + name: MeshLab_macOS_packages + path: meshlab_macos_dmg - name: Download MacOS DMG-d - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: - name: meshlab_macos_dmg_double + name: MeshLab_macOS_packages_double + path: meshlab_macos_dmg_double - name: Download MacOS Portable - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: - name: meshlab_macos_portable + name: MeshLab_macOS_portable + path: meshlab_macos_portable - name: Download MacOS Portable-d - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: - name: meshlab_macos_portable_double + name: MeshLab_macOS_portable_double + path: meshlab_macos_portable_double + - name: Change Permissions + run: | + chmod +x meshlab_macos_portable/MeshLab*.app/Contents/MacOS/meshlab + chmod +x meshlab_macos_portable_double/MeshLab*.app/Contents/MacOS/meshlab - name: Create MeshLab Portable MacOS run: | - mv meshlab_macos_portable meshlab.app - zip -r MeshLab${{ github.event.inputs.version }}-macos.zip meshlab.app/ - rm -r meshlab.app - mv meshlab_macos_portable_double meshlab.app - zip -r MeshLab${{ github.event.inputs.version }}d-macos.zip meshlab.app/ + cd meshlab_macos_portable + tar -cvzf ../MeshLab${{steps.envs.outputs.ml_version}}-macos.tar.gz * + cd ../meshlab_macos_portable_double + tar -cvzf ../MeshLab${{steps.envs.outputs.ml_version_d}}-macos.tar.gz * + cd .. #Download Windows Packages - name: Download Windows ZIP - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: - name: meshlab_windows_portable + name: MeshLab_Windows_portable + path: meshlab_windows_portable - name: Download Windows ZIP-d - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: - name: meshlab_windows_portable_double + name: MeshLab_Windows_portable_double + path: meshlab_windows_portable_double - name: Download Windows Installer - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: - name: meshlab_windows_installer + name: MeshLab_Windows_packages + path: meshlab_windows_installer - name: Download Windows Installer-d - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v3 with: - name: meshlab_windows_installer_double + name: MeshLab_Windows_packages_double + path: meshlab_windows_installer_double - name: Create MeshLab Portable Windows Archive run: | - zip -r MeshLab${{ github.event.inputs.version }}-windows.zip meshlab_windows_portable/ - zip -r MeshLab${{ github.event.inputs.version }}d-windows.zip meshlab_windows_portable_double/ - + cd meshlab_windows_portable + zip -r ../MeshLab${{steps.envs.outputs.ml_version}}-windows.zip * + cd ../meshlab_windows_portable_double + zip -r ../MeshLab${{steps.envs.outputs.ml_version_d}}-windows.zip * + cd .. #Create release and upload - - name: Publish Release - id: create_release - uses: actions/create-release@v1.0.0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: "marvinpinto/action-automatic-releases@6273874b61ebc8c71f1a61b2d98e234cf389b303" with: - tag_name: Meshlab-${{ github.event.inputs.version }} - release_name: MeshLab-${{ github.event.inputs.version }} - draft: false - prerelease: false - #Linux - - name: Upload ReleaseLinuxPortable - id: upload-release-linux-portable - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: MeshLab${{ github.event.inputs.version }}-linux.tar.gz - asset_name: MeshLab${{ github.event.inputs.version }}-linux.tar.gz - asset_content_type: MeshLab Portable for Linux - - name: Upload ReleaseLinuxPortable-d - id: upload-release-linux-portable-d - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: MeshLab${{ github.event.inputs.version }}d-linux.tar.gz - asset_name: MeshLab${{ github.event.inputs.version }}d-linux.tar.gz - asset_content_type: MeshLab Portable for Linux - - name: Upload ReleaseLinuxAppImage - id: upload-release-linux-appimage - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: meshlab_linux_appimage/MeshLab${{ github.event.inputs.version }}-linux.AppImage - asset_name: MeshLab${{ github.event.inputs.version }}-linux.AppImage - asset_content_type: MeshLab AppImage for Linux - - name: Upload ReleaseLinuxAppImage-d - id: upload-release-linux-appimage-d - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: meshlab_linux_appimage_double/MeshLab${{ github.event.inputs.version }}d-linux.AppImage - asset_name: MeshLab${{ github.event.inputs.version }}d-linux.AppImage - asset_content_type: MeshLab AppImage for Linux - #MacOS - - name: Upload ReleaseMacOSDMG - id: upload-release-macos - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: meshlab_macos_dmg/MeshLab${{ github.event.inputs.version }}-macos.dmg - asset_name: MeshLab${{ github.event.inputs.version }}-macos.dmg - asset_content_type: MeshLab DMG for MacOS - - name: Upload ReleaseMacOSDMG-d - id: upload-release-macos-d - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: meshlab_macos_dmg_double/MeshLab${{ github.event.inputs.version }}d-macos.dmg - asset_name: MeshLab${{ github.event.inputs.version }}d-macos.dmg - asset_content_type: MeshLab DMG for MacOS - - name: Upload ReleaseMacOSPortable - id: upload-release-macos-portable - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: MeshLab${{ github.event.inputs.version }}-macos.zip - asset_name: MeshLab${{ github.event.inputs.version }}-macos.zip - asset_content_type: MeshLab Portable for MacOS - - name: Upload ReleaseMacOSPortable-d - id: upload-release-macos-portable-d - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: MeshLab${{ github.event.inputs.version }}d-macos.zip - asset_name: MeshLab${{ github.event.inputs.version }}d-macos.zip - asset_content_type: MeshLab Portable for MacOS - #Windows - - name: Upload ReleaseWindowsPortable - id: upload-release-windows-portable - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: MeshLab${{ github.event.inputs.version }}-windows.zip - asset_name: MeshLab${{ github.event.inputs.version }}-windows.zip - asset_content_type: MeshLab Portable for Windows - - name: Upload ReleaseWindowsPortable-d - id: upload-release-windows-portable-d - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: MeshLab${{ github.event.inputs.version }}d-windows.zip - asset_name: MeshLab${{ github.event.inputs.version }}d-windows.zip - asset_content_type: MeshLab Portable for Windows - - name: Upload ReleaseWindowsInstaller - id: upload-release-windows-installer - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: meshlab_windows_installer/MeshLab${{ github.event.inputs.version }}-windows.exe - asset_name: MeshLab${{ github.event.inputs.version }}-windows.exe - asset_content_type: MeshLab Portable for Windows - - name: Upload ReleaseWindowsInstaller-d - id: upload-release-windows-installer-d - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: meshlab_windows_installer_double/MeshLab${{ github.event.inputs.version }}d-windows.exe - asset_name: MeshLab${{ github.event.inputs.version }}d-windows.exe - asset_content_type: MeshLab Portable for Windows + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: "MeshLab-${{steps.envs.outputs.ml_version}}" + prerelease: false #${{ github.event.inputs.release_candidate }} + title: "MeshLab-${{steps.envs.outputs.ml_version}}" + files: | + MeshLab${{steps.envs.outputs.ml_version}}-linux.tar.gz + MeshLab${{steps.envs.outputs.ml_version_d}}-linux.tar.gz + meshlab_linux_appimage/MeshLab${{steps.envs.outputs.ml_version}}-linux.AppImage + meshlab_linux_appimage_double/MeshLab${{steps.envs.outputs.ml_version_d}}-linux.AppImage + MeshLab${{steps.envs.outputs.ml_version}}-macos.tar.gz + MeshLab${{steps.envs.outputs.ml_version_d}}-macos.tar.gz + meshlab_macos_dmg/MeshLab${{steps.envs.outputs.ml_version}}-macos.dmg + meshlab_macos_dmg_double/MeshLab${{steps.envs.outputs.ml_version_d}}-macos.dmg + MeshLab${{steps.envs.outputs.ml_version}}-windows.zip + MeshLab${{steps.envs.outputs.ml_version_d}}-windows.zip + meshlab_windows_installer/MeshLab${{steps.envs.outputs.ml_version}}-windows.exe + meshlab_windows_installer_double/MeshLab${{steps.envs.outputs.ml_version_d}}-windows.exe diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml deleted file mode 100644 index bba54dbc3..000000000 --- a/.github/workflows/Linux.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Linux - -on: - [push, pull_request] - -jobs: - linux_build: - name: Build MeshLab (Linux) - runs-on: ubuntu-16.04 #in order to deploy, need to use oldest supported version - strategy: - matrix: - precision: [single_precision, double_precision] - - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - name: Install Qt - uses: jurplel/install-qt-action@v2 - - name: Install dependencies - run: | - sudo apt-get install -y mesa-common-dev libglu1-mesa-dev libgmp-dev - #needed by qt 5.15 on linux - sudo apt-get install libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-render-util0-dev libxcb-xinerama0-dev - - name: Setup env variables - id: envs - shell: bash - run: | - if [ "${{matrix.precision}}" == "double_precision" ]; then - echo ::set-output name=version::"$(cat ML_VERSION)d" - echo ::set-output name=artifact_suffix::"_double" - else - echo ::set-output name=version::"$(cat ML_VERSION)" - echo ::set-output name=artifact_suffix::"" - fi - - name: Configure and Build - run: | - sh scripts/${{ runner.os }}/1_build.sh --${{ matrix.precision }} - - name: Deploy - run: | - sh scripts/${{ runner.os }}/2_deploy.sh - - name: Build MeshLab AppImage - run : | - sh scripts/${{ runner.os }}/3_appimage.sh --${{ matrix.precision }} - - name: Upload Meshlab Portable - uses: actions/upload-artifact@v1 - with: - name: meshlab_linux_portable${{steps.envs.outputs.artifact_suffix}} - path: src/install/ - - name: Upload Meshlab AppImage - uses: actions/upload-artifact@v1 - with: - name: meshlab_linux_appimage${{steps.envs.outputs.artifact_suffix}} - path: src/MeshLab${{steps.envs.outputs.version}}-linux.AppImage diff --git a/.github/workflows/LinuxSnap.yml b/.github/workflows/LinuxSnap.yml deleted file mode 100644 index c03a08c80..000000000 --- a/.github/workflows/LinuxSnap.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: LinuxSnap - -on: - workflow_dispatch - -jobs: - linux_build_snap: - name: Build MeshLab (Linux - Snap) - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - name: Install dependencies - run: | - #needed for some reason... - curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add - - sudo apt update - sudo apt-get install -y snapcraft - - name: Setup env variables - id: envs - run: | - echo ::set-output name=date::"$(cat ML_VERSION)" - - name: Build MeshLab Snap - run: | - snapcraft - - name: Rename Snap - run: | - mv ./meshlab*.snap ./MeshLab${{steps.envs.outputs.date}}-linux.snap - - name: Upload Meshlab Snap - uses: actions/upload-artifact@v1 - with: - name: meshlab_linux_snap - path: MeshLab${{steps.envs.outputs.date}}-linux.snap diff --git a/.github/workflows/MacOS.yml b/.github/workflows/MacOS.yml deleted file mode 100644 index 10aaf5ebe..000000000 --- a/.github/workflows/MacOS.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: MacOS - -on: - [push, pull_request] - -jobs: - macos_build: - name: Build MeshLab (MacOS) - runs-on: macos-latest - strategy: - matrix: - precision: [single_precision, double_precision] - - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - name: Install dependencies - run: | - brew install libomp - npm install -g appdmg - - name: Install Qt - uses: jurplel/install-qt-action@v2 - - name: Setup env variables - id: envs - shell: bash - run: | - if [ "${{matrix.precision}}" == "double_precision" ]; then - echo ::set-output name=version::"$(cat ML_VERSION)d" - echo ::set-output name=artifact_suffix::"_double" - else - echo ::set-output name=version::"$(cat ML_VERSION)" - echo ::set-output name=artifact_suffix::"" - fi - - name: Configure and Build - run: | - sh scripts/${{ runner.os }}/1_build.sh --${{ matrix.precision }} - - name: Deploy - run: | - sh scripts/${{ runner.os }}/2_deploy.sh - - name: Create DMG - run: | - sh scripts/${{ runner.os }}/3_dmg.sh --${{ matrix.precision }} - mv src/install/MeshLab${{steps.envs.outputs.version}}.dmg src/install/MeshLab${{steps.envs.outputs.version}}-macos.dmg - - name: Upload MeshLab Portable - uses: actions/upload-artifact@v1 - with: - name: meshlab_macos_portable${{steps.envs.outputs.artifact_suffix}} - path: src/install/meshlab.app - - name: Upload DMG - uses: actions/upload-artifact@v1 - with: - name: meshlab_macos_dmg${{steps.envs.outputs.artifact_suffix}} - path: src/install/MeshLab${{steps.envs.outputs.version}}-macos.dmg diff --git a/.github/workflows/QmakeBuilds.yml b/.github/workflows/QmakeBuilds.yml deleted file mode 100644 index 4fad13b4b..000000000 --- a/.github/workflows/QmakeBuilds.yml +++ /dev/null @@ -1,139 +0,0 @@ -name: Qmake builds - -on: [push, pull_request] - -jobs: - ubuntu_build: - name: Build MeshLab (Ubuntu - QMake) - runs-on: ubuntu-16.04 #in order to deploy, need to use oldest supported version - - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - name: Install Qt - uses: jurplel/install-qt-action@v2 - - name: Install dependencies - run: | - sudo apt-get install -y mesa-common-dev libglu1-mesa-dev libglew-dev libeigen3-dev libgmp-dev - sudo apt-get install -y libxkbcommon-x11-0 patchelf - #needed by qt 5.15 on linux - sudo apt-get install libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-render-util0-dev libxcb-xinerama0-dev - - name: Setup env variables - id: envs - run: | - echo ::set-output name=date::"$(cat ML_VERSION)" - - name: Build MeshLab - run: | - sh scripts/${{ runner.os }}/qmake/linux_build.sh - - name: Make MeshLab Bundle - run: | - sh scripts/${{ runner.os }}/qmake/linux_make_bundle.sh - - name: Deploy MeshLab and MeshLabServer - run : | - sh scripts/${{ runner.os }}/qmake/linux_deploy.sh - - name: Build MeshLab and MeshLabServer AppImages - run : | - sh scripts/${{ runner.os }}/qmake/linux_appimages.sh - - name: Upload Meshlab Portable - uses: actions/upload-artifact@v1 - with: - name: meshlab_linux_portable - path: distrib/ - - name: Upload MeshlabServer AppImage - uses: actions/upload-artifact@v1 - with: - name: meshlabserver_linux_appimage - path: MeshLabServer${{steps.envs.outputs.date}}-linux.AppImage - - name: Upload Meshlab AppImage - uses: actions/upload-artifact@v1 - with: - name: meshlab_linux_appimage - path: MeshLab${{steps.envs.outputs.date}}-linux.AppImage - - macos_build_qmake: - name: Build MeshLab (MacOS - QMake) - runs-on: macos-latest - - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - name: Install dependencies - run: | - brew install libomp - npm install -g appdmg - - name: Install Qt - uses: jurplel/install-qt-action@v2 - - name: Setup env variables - id: envs - shell: bash - run: | - echo ::set-output name=date::"$(cat ML_VERSION)" - - name: Build MeshLab - run: | - sh scripts/${{ runner.os }}/qmake/macos_build.sh - - name: Deploy MeshLab - run: | - sh scripts/${{ runner.os }}/qmake/macos_deploy.sh - - name: Create DMG - run: | - sh scripts/${{ runner.os }}/qmake/macos_dmg.sh - mv distrib/MeshLab${{steps.envs.outputs.date}}.dmg distrib/MeshLab${{steps.envs.outputs.date}}-macos.dmg - - name: Upload DMG - uses: actions/upload-artifact@v1 - with: - name: meshlab_macos_dmg - path: distrib/MeshLab${{steps.envs.outputs.date}}-macos.dmg - - windows_build_qmake: - name: Build MeshLab (Windows - QMake) - runs-on: windows-latest - - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - name: Download Jom - run: | - Invoke-WebRequest -Uri "http://download.qt.io/official_releases/jom/jom_1_1_3.zip" -OutFile "jom_1_1_3.zip" - New-Item -Name "jom" -ItemType "directory" - Expand-Archive -Path jom_1_1_3.zip -DestinationPath .\jom - echo "$(Get-Location)\jom" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - #echo "$(Get-Location)\jom" >> GITHUB_PATH - - name: Setup env variables - id: envs - run: | - echo "VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC" >> $GITHUB_ENV - #echo '::set-env name=VCINSTALLDIR::C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC' - echo "::set-output name=date::$(type ML_VERSION)" - - name: Setup MSVC - uses: ilammy/msvc-dev-cmd@v1 - - name: Install Qt - uses: jurplel/install-qt-action@v2 - - name: Build MeshLab - run: | - .\scripts\${{ runner.os }}\qmake\windows_build.ps1 - - name: Deploy MeshLab - run: | - .\scripts\${{ runner.os }}\qmake\windows_deploy.ps1 - - name: NSIS script - run: | - .\scripts\${{ runner.os }}\resources\windows_nsis_script.ps1 - - name: Create Installer - uses: joncloud/makensis-action@v1 - with: - script-file: "scripts/windows/resources/meshlab_final.nsi" - - name: Rename Installer - run: | - Rename-Item -Path scripts\windows\resources\MeshLab${{steps.envs.outputs.date}}.exe -NewName MeshLab${{steps.envs.outputs.date}}-windows.exe - - name: Upload Meshlab Portable - uses: actions/upload-artifact@v1 - with: - name: meshlab_windows_portable - path: distrib - - name: Upload Meshlab Installer - uses: actions/upload-artifact@v1 - with: - name: meshlab_windows_installer - path: scripts/windows/resources/MeshLab${{steps.envs.outputs.date}}-windows.exe diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml deleted file mode 100644 index c95a262a2..000000000 --- a/.github/workflows/Windows.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: Windows - -on: [push, pull_request] - -jobs: - windows_build: - name: Build MeshLab (Windows) - runs-on: windows-latest - strategy: - matrix: - precision: [single_precision, double_precision] - - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - name: Download Jom - run: | - Invoke-WebRequest -Uri "http://download.qt.io/official_releases/jom/jom_1_1_3.zip" -OutFile "jom_1_1_3.zip" - New-Item -Name "jom" -ItemType "directory" - Expand-Archive -Path jom_1_1_3.zip -DestinationPath .\jom - echo "$(Get-Location)\jom" >> GITHUB_PATH - - name: Setup MSVC - uses: ilammy/msvc-dev-cmd@v1 - - name: Install Qt - uses: jurplel/install-qt-action@v2 - - name: Setup env variables - shell: bash - id: envs - run: | - if [ "${{matrix.precision}}" == "double_precision" ]; then - echo ::set-output name=version::"$(cat ML_VERSION)d" - echo ::set-output name=artifact_suffix::"_double" - else - echo ::set-output name=version::"$(cat ML_VERSION)" - echo ::set-output name=artifact_suffix::"" - fi - echo "VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC" >> $GITHUB_ENV - - name: Configure and Build - shell: bash - run: | - sh scripts/${{ runner.os }}/1_build.sh --${{ matrix.precision }} - - name: Deploy - shell: bash - run: | - sh scripts/${{ runner.os }}/2_deploy.sh - - name: NSIS script - shell: bash - run: | - sh scripts/${{ runner.os }}/resources/nsis_script.sh --${{ matrix.precision }} - - name: Create Installer - uses: joncloud/makensis-action@v1 - with: - script-file: "src/install/meshlab_final.nsi" - - name: Rename Installer - shell: bash - run: | - mv src/install/MeshLab${{steps.envs.outputs.version}}.exe src/MeshLab${{steps.envs.outputs.version}}-windows.exe - - name: Uploading MeshLab Portable - uses: actions/upload-artifact@v1 - with: - name: meshlab_windows_portable${{steps.envs.outputs.artifact_suffix}} - path: src/install - - name: Upload Meshlab Installer - uses: actions/upload-artifact@v1 - with: - name: meshlab_windows_installer${{steps.envs.outputs.artifact_suffix}} - path: src/MeshLab${{steps.envs.outputs.version}}-windows.exe diff --git a/.gitignore b/.gitignore index 47f65c5ce..fb5625a04 100644 --- a/.gitignore +++ b/.gitignore @@ -17,16 +17,24 @@ *.db-wal *.AppImage .DS_Store -distrib* -src/install/* + +# build and install directories +build/* +install/* + +# external libraries automatically downloaded by cmake +src/external/easyexif*/test-images/* +src/external/glew*/auto/* +src/external/glew*/build/* +src/external/glew*/config/* +src/external/glew*/doc/* +src/external/downloads/* +src/external/tmp.zip + +# files created/modified during deploy stage install/macos/resources/meshlab_dmg_final.json install/windows/resources/meshlab_final.nsi install/windows/resources/MeshLab*.exe -#install/snap20????/prime -#install/snap20????/parts -#install/snap20????/stage -#install/snap20????/*.snap -src/common/generated_version_header.h ##Standard cmake gitignore## CMakeLists.txt.user @@ -95,7 +103,7 @@ target_wrapper.* # QtCreator CMake CMakeLists.txt.user* -# QtCreator 4.8< compilation database +# QtCreator 4.8< compilation database compile_commands.json # QtCreator local machine specific files for imported projects diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..83f0e0fb4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright 2019, 2020, Collabora, Ltd. +# Copyright 2019, 2021, Visual Computing Lab, ISTI - Italian National Research Council +# SPDX-License-Identifier: BSL-1.0 + +cmake_minimum_required(VERSION 3.18) +project(MeshLab) + +### Build options +option(MESHLAB_BUILD_MINI "Build only common and meshlab - other plugin targets must be set manually" OFF) +option(MESHLAB_BUILD_STRICT "Strictly enforce resolution of all symbols" ON) +option(MESHLAB_BUILD_WITH_DOUBLE_SCALAR "Use double type instead of float type for scalars" OFF) +option(MESHLAB_ENABLE_DEBUG_LOG_FILE "If enabled, all the logs of MeshLab will be also saved into a log file" OFF) + +option(MESHLAB_BUILD_ONLY_LIBRARIES "Build only meshlab-common and plugins, excluding executables" OFF) +option(MESHLAB_USE_DEFAULT_BUILD_AND_INSTALL_DIRS "If set to OFF, it expects that you set manually the binary and install directories" ON) + +option(MESHLAB_IS_NIGHTLY_VERSION "Nightly version of meshlab will be used instead of ML_VERSION" OFF) + +add_subdirectory(src) \ No newline at end of file diff --git a/ML_VERSION b/ML_VERSION index ee102115d..19b29e818 100644 --- a/ML_VERSION +++ b/ML_VERSION @@ -1 +1 @@ -2020.12 \ No newline at end of file +2022.02 \ No newline at end of file diff --git a/README.md b/README.md index abc325d41..30deb5677 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,48 @@ # ![MeshLab Logo](src/meshlab/images/eye64.png) MeshLab -![Linux](https://github.com/cnr-isti-vclab/meshlab/workflows/Linux/badge.svg) -![MacOS](https://github.com/cnr-isti-vclab/meshlab/workflows/MacOS/badge.svg) -![Windows](https://github.com/cnr-isti-vclab/meshlab/workflows/Windows/badge.svg) +[![BuildMeshLab](https://github.com/cnr-isti-vclab/meshlab/actions/workflows/BuildMeshLab.yml/badge.svg)](https://github.com/cnr-isti-vclab/meshlab/actions/workflows/BuildMeshLab.yml) + +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5114037.svg)](https://doi.org/10.5281/zenodo.5114037) This is the official repository for the source and the binaries of [MeshLab](https://www.MeshLab.net). -MeshLab is an open source, portable, and extensible system for the processing and editing of unstructured large 3D triangular meshes. It is aimed to help the processing of the typical not-so-small unstructured models arising in 3D scanning, providing a set of tools for editing, cleaning, healing, inspecting, rendering and converting this kind of meshes. These tools include MeshLab proper, a versatile program with a graphical user interface, and [meshlabserver](https://github.com/cnr-isti-vclab/meshlab/blob/master/src/meshlabserver/README.md), a program that can perform mesh processing tasks in batch mode, without a GUI. +MeshLab is an open source, portable, and extensible system for the processing and editing of unstructured large 3D triangular meshes. It is aimed to help the processing of the typical not-so-small unstructured models arising in 3D scanning, providing a set of tools for editing, cleaning, healing, inspecting, rendering and converting this kind of meshes. MeshLab is mostly based on the open source C++ mesh processing library [VCGlib](http://www.vcglib.net) developed at the [Visual Computing Lab](http://vcg.isti.cnr.it) of [ISTI - CNR](http://www.isti.cnr.it). VCG can be used as a stand-alone large-scale automated mesh processing pipeline, while MeshLab makes it easy to experiment with its algorithms interactively. -MeshLab is available for Windows, MacOS, and Linux. +MeshLab is available for Windows, macOS, and Linux. # Releases You can find the last MeshLab release in the [Releases Tab](https://github.com/cnr-isti-vclab/meshlab/releases) for your favourite platform. -You can also test a built version of MeshLab generated by the last commit pushed in this repository, by downloading the artifacts of the last [Github Actions](https://github.com/cnr-isti-vclab/meshlab/actions) workflow. +You can also test the last nightly version of MeshLab, by downloading the artifacts of the last [Github Actions](https://github.com/cnr-isti-vclab/meshlab/actions) workflow. You can find a guide on how to download it [here](https://github.com/cnr-isti-vclab/meshlab/wiki/How-to-install-the-last-nightly-version). # Build instructions -We provide a set of scripts that build and deploy MeshLab automatically. All the scripts can be found in the [scripts](https://github.com/cnr-isti-vclab/meshlab/tree/master/scripts) folder. -For specific build instructions see the [src](https://github.com/cnr-isti-vclab/meshlab/blob/master/src/README.md) folder. +We provide a set of scripts that build and deploy MeshLab automatically. All the scripts can be found in the [scripts](https://github.com/cnr-isti-vclab/meshlab/tree/main/scripts) folder. +For specific build instructions see the [src](https://github.com/cnr-isti-vclab/meshlab/blob/main/src/README.md) folder. + +# Branches and Pull Requests + +On this repository, we keep two relevant branches: + +- `main`: we keep here the **last release version of MeshLab**, with just bugfixes, optimizations and changes that do not affect the last released MeshLab binary. In case of bugs caught after a release, this branch is used to publish "post-releases". +- `devel`: we add here new features and functionalities of the software that are going to appear in the next release of MeshLab. Bugfixes pushed in `main` are automatically merged into the `devel` branch. + +Before committing a new change, or sending a pull request, please choose the branch that better suits for your change. +If it is just a bugfix, or an edit that does not modify the software (e.g. documentation typos, changes to the deploy system, ...), use the `main` branch. +If it is a new feature that will change the behaviour or the usage of the software, use the `devel` branch. # Structure of the Repository The MeshLab repository is organized as follows: -* `distrib`: this folder contains a set of prebuilt libraries and shaders that will be used by MeshLab once it is compiled. For more details, check the readme [here](https://github.com/cnr-isti-vclab/meshlab/tree/master/distrib/README.md); * `docs`: doxygen scripts for generating MeshLab documentation. For more details, check the readme [here](https://github.com/cnr-isti-vclab/meshlab/tree/master/docs); * `sample` and `textures`: a set of files (meshes, images) used for tests; +* `resources`: contains a set of files used by the software and by the deploy system to produce the final MeshLab binary; * `scripts`: in this folder there is a set of platform-dependent scripts to build and deploy MeshLab. For more details, check the readme [here](https://github.com/cnr-isti-vclab/meshlab/tree/master/scripts/README.md); -* `src`: this folder contains all the source code of MeshLab, its plugins and the external libraries that it requires. For more details, check the readme [here](https://github.com/cnr-isti-vclab/meshlab/blob/master/src/README.md); +* `src`: this folder contains all the source code of MeshLab and its plugins. For more details, check the readme [here](https://github.com/cnr-isti-vclab/meshlab/blob/master/src/README.md); * `unsupported`: this folder contains a set of old and unsupported MeshLab plugins that are no longer included and built under MeshLab. # License @@ -51,28 +62,33 @@ The MeshLab repository is organized as follows: Paolo Cignoni \/)\/ Visual Computing Lab http://vcg.isti.cnr.it /\/| ISTI - Italian National Research Council | - Copyright(C) 2005-2018 \ + Copyright(C) 2005-2021 \ ``` # References +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5114037.svg)](https://doi.org/10.5281/zenodo.5114037) + + Please, when using this tool, cite the references listed in the official web page https://www.meshlab.net/#references according to you needs, or if you are lazy just cite: -Meshlab: an open-source mesh processing tool. P. Cignoni, M. Callieri, M. Corsini, M. Dellepiane, F. Ganovelli, G. Ranzuglia -Proceedings of the 2008 Eurographics Italian Chapter Conference, ISBN: 978-3-905673-68-5, pp. 129-136, DOI: 10.2312/LocalChapterEvents/ItalChap/ItalianChapConf2008/129-136 - -BibTeX format: - ``` +@software{meshlab, + author = {Paolo Cignoni, Alessandro Muntoni, Guido Ranzuglia, Marco Callieri}, + title = {{MeshLab}}, + publisher = {Zenodo}, + doi = {10.5281/zenodo.5114037} +} + @inproceedings {LocalChapterEvents:ItalChap:ItalianChapConf2008:129-136, -booktitle = {Eurographics Italian Chapter Conference}, -editor = {Vittorio Scarano and Rosario De Chiara and Ugo Erra}, -title = {{MeshLab: an Open-Source Mesh Processing Tool}}, -author = {Cignoni, Paolo and Callieri, Marco and Corsini, Massimiliano and Dellepiane, Matteo and Ganovelli, Fabio and Ranzuglia, Guido}, -year = {2008}, -publisher = {The Eurographics Association}, -ISBN = {978-3-905673-68-5}, -DOI = {10.2312/LocalChapterEvents/ItalChap/ItalianChapConf2008/129-136} + booktitle = {Eurographics Italian Chapter Conference}, + editor = {Vittorio Scarano and Rosario De Chiara and Ugo Erra}, + title = {{MeshLab: an Open-Source Mesh Processing Tool}}, + author = {Cignoni, Paolo and Callieri, Marco and Corsini, Massimiliano and Dellepiane, Matteo and Ganovelli, Fabio and Ranzuglia, Guido}, + year = {2008}, + publisher = {The Eurographics Association}, + ISBN = {978-3-905673-68-5}, + DOI = {10.2312/LocalChapterEvents/ItalChap/ItalianChapConf2008/129-136} } ``` @@ -86,6 +102,3 @@ DOI = {10.2312/LocalChapterEvents/ItalChap/ItalianChapConf2008/129-136} For documented and repeatable bugs, feature requests, etc., please use the [GitHub issues](https://github.com/cnr-isti-vclab/meshlab/issues). For general questions use [StackOverflow](http://stackoverflow.com/questions/tagged/meshlab). - - - diff --git a/distrib/README.md b/distrib/README.md deleted file mode 100644 index def256882..000000000 --- a/distrib/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# distrib folder - -The distrib folder contains a set of pre-built libraries and shaders that MeshLab needs to properly run, plus some other txt files and icons. \ No newline at end of file diff --git a/distrib/meshlab.png b/distrib/meshlab.png deleted file mode 100644 index 2f787916d..000000000 Binary files a/distrib/meshlab.png and /dev/null differ diff --git a/distrib/readme.txt b/distrib/readme.txt deleted file mode 100644 index 75a236787..000000000 --- a/distrib/readme.txt +++ /dev/null @@ -1,56 +0,0 @@ - MeshLab - http://www.meshlab.net - All rights reserved. - - VCGLib http://www.vcglib.net o o - Visual and Computer Graphics Library o o - _ O _ - Paolo Cignoni \/)\/ - Visual Computing Lab http://vcg.isti.cnr.it /\/| - ISTI - Italian National Research Council | - Copyright(C) 2005-2018 \ - - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License V 3.0 as published by the Free -Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -(http://www.gnu.org/licenses/gpl.txt) for more details. - ---- Windows Note --- - -If you are running MeshLab portable and you are getting the error “MSVCP140.dll not found” -or related, please install Visual C++ Redist by executing the vc_redist.exe file contained -in the meshlab portable archive. - ---- References ---- - -Please, when using this tool, cite the following reference: - -Meshlab: an open-source mesh processing tool. -P. Cignoni, M. Callieri, M. Corsini, M. Dellepiane, F. Ganovelli, G. Ranzuglia -Proceedings of the 2008 Eurographics Italian Chapter Conference, -ISBN: 978-3-905673-68-5, pp. 129-136, DOI: 10.2312/LocalChapterEvents/ItalChap/ItalianChapConf2008/129-136 - -@inproceedings {LocalChapterEvents:ItalChap:ItalianChapConf2008:129-136, -booktitle = {Eurographics Italian Chapter Conference}, -editor = {Vittorio Scarano and Rosario De Chiara and Ugo Erra}, -title = {{MeshLab: an Open-Source Mesh Processing Tool}}, -author = {Cignoni, Paolo and Callieri, Marco and Corsini, Massimiliano and Dellepiane, Matteo and Ganovelli, Fabio and Ranzuglia, Guido}, -year = {2008}, -publisher = {The Eurographics Association}, -ISBN = {978-3-905673-68-5}, -DOI = {10.2312/LocalChapterEvents/ItalChap/ItalianChapConf2008/129-136} -} - -Paolo Cignoni (p.cignoni (at) isti.cnr.it) -Guido Ranzuglia (g.ranzuglia (at) isti.cnr.it) - -For documented and repeatable bugs, reasonable feature requests and grounded issues, please use the GitHub services -https://github.com/cnr-isti-vclab/meshlab/issues - -For general questions use StackOverflow -http://stackoverflow.com/questions/tagged/meshlab diff --git a/docs/dox/filter.dox b/docs/dox/filter.dox index cd70bfab9..e9629f972 100644 --- a/docs/dox/filter.dox +++ b/docs/dox/filter.dox @@ -13,9 +13,9 @@ Simulates the aging effects due to small collisions or various chipping events \c Int Fractal Octaves The number of octaves that are used in the generation of the
fractal noise using Perlin noise; reasonalble values are in the
1..8 range. Setting it to 1 means using a simple Perlin Noise. --
\c AbsPerc Noise frequency scale Changes the noise frequency scale: this affects chip dimensions and
the distance between chips. The value denotes the average values
between two dents. Smaller number means small and frequent chips. --
\c Float Noise clamp threshold [0..1] All the noise values smaller than this parameter will be
considered as 0. --
- \c Float Displacement steps The whole displacement process is performed as a sequence of small
offsets applyed on each vertex. This parameter represents the number
of steps into which the displacement process will be splitted.
Useful to avoid the introduction of self intersections.
Bigger number means better accuracy. --
+ \c Float Displacement steps The whole displacement process is performed as a sequence of small
offsets applied on each vertex. This parameter represents the number
of steps into which the displacement process will be split.
Useful to avoid the introduction of self intersections.
Bigger number means better accuracy. --
\c Bool Affect only selected faces The aging procedure will be applied to the selected faces only. -- - \c Bool Store erosion informations Select this option if you want to store the erosion informations
over the mesh. A new attribute will be added to each vertex
to contain the displacement offset applied to that vertex. --
+ \c Bool Store erosion information Select this option if you want to store the erosion information
over the mesh. A new attribute will be added to each vertex
to contain the displacement offset applied to that vertex. --
\section f1 Ambient Occlusion - Per Vertex @@ -46,12 +46,12 @@ Generates environment occlusions values for the loaded mesh \c Int Depth texture size(should be 2^n) Defines the depth texture size used to compute occlusion from each point of view. Higher values means better accuracy usually with low impact on performance -- -\section f3 Automatic pair Alignement +\section f3 Automatic pair Alignment Automatic Rough Alignment of two meshes. Based on the paper 4-Points Congruent Sets for Robust Pairwise Surface Registration, by Aiger,Mitra, Cohen-Or. Siggraph 2008

Parameters

- + @@ -66,7 +66,7 @@ Reconstruct a surface using the Ball Pivoting Algorithm (Bernardini et al - +
\c Mesh First Mesh The mesh were the coplanar bases are sampled (it will contain the trasformation) --
\c Mesh First Mesh The mesh were the coplanar bases are sampled (it will contain the transformation) --
\c Mesh Second Mesh The mesh were similar coplanar based are searched. --
\c Float Estimated fraction of the first mesh overlapped by the second --
\c AbsPerc Pivoting Ball radius (0 autoguess) The radius of the ball pivoting (rolling) over the set of points. Gaps that are larger than the ball radius will not be filled; similarly the small pits that are smaller than the ball radius will be filled. --
\c Float Clustering radius (% of ball radius) To avoid the creation of too small triangles, if a vertex is found too close to a previous one, it is clustered/merged with it. --
\c Float Angle Threshold (degrees) If we encounter a crease angle that is too large we should stop the ball rolling --
\c Bool Delete intial set of faces if true all the initial faces of the mesh are deleted and the whole surface is rebuilt from scratch, other wise the current faces are used as a starting point. Useful if you run multiple times the algorithm with an incrasing ball radius. --
\c Bool Delete initial set of faces if true all the initial faces of the mesh are deleted and the whole surface is rebuilt from scratch, other wise the current faces are used as a starting point. Useful if you run multiple times the algorithm with an incrasing ball radius. --
\section f5 Remove vertices wrt quality @@ -102,9 +102,9 @@ Align this mesh with another that has corresponding picked points. \c Float Minimal Starting Distance For all the chosen sample on one mesh we consider for ICP only the samples nearer than this value.If MSD is too large outliers could be included, if it is too small convergence will be very slow. A good guess is needed here, suggested values are in the range of 10-100 times of the device scanning error.This value is also dynamically changed by the 'Reduce Distance Factor' -- \c Float Target Distance When 50% of the chosen samples are below this distance we consider the two mesh aligned. Usually it should be a value lower than the error of the scanning device. -- \c Int Max Iteration Num The maximum number of iteration that the ICP is allowed to perform. -- - \c Bool Normal Equalized Sampling if true (default) the sample points of icp are choosen with a distribution uniform with respect to the normals of the surface. Otherwise they are distributed in a spatially uniform way. -- + \c Bool Normal Equalized Sampling if true (default) the sample points of icp are chosen with a distribution uniform with respect to the normals of the surface. Otherwise they are distributed in a spatially uniform way. -- \c Float MSD Reduce Factor At each ICP iteration the Minimal Starting Distance is reduced to be 5 times the percentile of the sample distances (e.g. if RF is 0.9 the new Minimal Starting Distance is 5 times the value such that 90% of the sample lies at a distance lower than . -- - \c Bool Rigid matching If true the ICP is cosntrained to perform matching only throug roto-translations (no scaling allowed). If false a more relaxed transformation matrix is allowed (scaling and shearing can appear). -- + \c Bool Rigid matching If true the ICP is constrained to perform matching only through roto-translations (no scaling allowed). If false a more relaxed transformation matrix is allowed (scaling and shearing can appear). -- \c Bool Use Markers for Alignment if true (default), then use the user picked markers to do an alignment (or pre alignment if you also use ICP). -- \c Bool Scale the mesh if true (false by default), in addition to the alignment, scale the mesh based on the points picked -- \c Bool Use ICP for Alignment if true (default), then use the ICP to align the two meshes. -- @@ -143,7 +143,7 @@ Removes t-vertices from the mesh by collapsing the shortest of the incident edge \section f12 Remove Duplicate Faces -Remove all the duplicate faces. Two faces are considered equal if they are composed by the same set of verticies, regardless of the order of the vertices. +Remove all the duplicate faces. Two faces are considered equal if they are composed by the same set of vertices, regardless of the order of the vertices.

Parameters

No parameters.
\section f13 Remove Isolated folded face by edge flip @@ -153,10 +153,10 @@ Remove all the single folded faces. A face is considered folded if its normal is No parameters.
\section f14 Merge Close Vertices -Merge togheter all the vertices that are nearer than the speicified threshold. Like a unify duplicated vertices but with some tolerance. +Merge together all the vertices that are nearer than the specified threshold. Like a unify duplicated vertices but with some tolerance.

Parameters

- +
\c AbsPerc Merging distance All the vertices that closer than this threshold are merged toghether. Use very small values, default values is 1/10000 of bounding box diagonal. --
\c AbsPerc Merging distance All the vertices that closer than this threshold are merged together. Use very small values, default values is 1/10000 of bounding box diagonal. --
\section f15 Clamp Vertex Quality @@ -167,7 +167,7 @@ Clamp vertex quality values to a given range according to specific values or to \c Float Min The value that will be mapped with the lower end of the scale (blue) -- \c Float Max The value that will be mapped with the upper end of the scale (red) -- \c DynamicFloat Percentile Crop [0..100] If not zero this value will be used for a percentile cropping of the quality values.
If this parameter is set to P the value V for which P% of the vertices have a quality lower(greater) than V is used as min (max) value.

The automated percentile cropping is very useful for automatically discarding outliers. --
- \c Bool Zero Simmetric If true the min max range will be enlarged to be symmertic (so that green is always Zero) -- + \c Bool Zero Symmetric If true the min max range will be enlarged to be symmertic (so that green is always Zero) -- \section f16 Saturate Vertex Quality @@ -176,7 +176,7 @@ Saturate vertex quality, so that for each vertex the gradient of the quality is The saturation is done in a conservative way (quality is always decreased and never increased)

Parameters

- +
\c Float Gradient Threshold The maximum value admitted for the quality gradient (in absolute valu) --
\c Float Gradient Threshold The maximum value admitted for the quality gradient (in absolute value) --
\c Bool Update ColorMap if true the color ramp is computed again --
@@ -188,7 +188,7 @@ Color vertices depending on their quality field (manually equalized). \c Float Min The value that will be mapped with the lower end of the scale (blue) -- \c Float Max The value that will be mapped with the upper end of the scale (red) -- \c DynamicFloat Percentile Crop [0..100] If not zero this value will be used for a percentile cropping of the quality values.
If this parameter is set to P the value V for which P% of the vertices have a quality lower(greater) than V is used as min (max) value.

The automated percentile cropping is very useful for automatically discarding outliers. --
- \c Bool Zero Simmetric If true the min max range will be enlarged to be symmertic (so that green is always Zero) -- + \c Bool Zero Symmetric If true the min max range will be enlarged to be symmertic (so that green is always Zero) -- \section f18 Colorize by face Quality @@ -199,7 +199,7 @@ Color faces depending on their quality field (manually equalized). \c Float Min The value that will be mapped with the lower end of the scale (blue) -- \c Float Max The value that will be mapped with the upper end of the scale (red) -- \c DynamicFloat Percentile Crop [0..100] If not zero this value will be used for a percentile cropping of the quality values.
If this parameter is set to P the value V for which P% of the vertices have a quality lower(greater) than V is used as min (max) value.

The automated percentile cropping is very useful for automatically discarding outliers. --
- \c Bool Zero Simmetric If true the min max range will be enlarged to be symmertic (so that green is always Zero) -- + \c Bool Zero Symmetric If true the min max range will be enlarged to be symmertic (so that green is always Zero) -- \section f19 Discrete Curvatures @@ -256,7 +256,7 @@ Colorize Faces randomly. If internal edges are present they are used No parameters.
\section f27 Vertex Color Filling -Fills the color of the vertexes of the mesh with a color choosed by the user. +Fills the color of the vertexes of the mesh with a color chosen by the user.

Parameters

@@ -416,71 +416,71 @@ Create a Cone \section f47 Fractal Terrain -Generates a fractal terrain perturbation with five different algorithms.
-Some good parameter values to start with are:
-
\c DynamicFloat Red: Sets the red component of the color. --
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Seed Octaves Lacunarity Fractal increment Offset Gain
fBM11021.2--
Standard multifractal1820.90.9-
Heterogeneous multifractal1830.90.4-
Hybrid multifractal1840.10.3-
Ridged multifractal2840.50.92
-

-Detailed algorithms descriptions can be found in:

-Ebert, D.S., Musgrave, F.K., Peachey, D., Perlin, K., and Worley, S.
-Texturing and Modeling: A Procedural Approach.
-Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 2002. - - +Generates a fractal terrain perturbation with five different algorithms.
+Some good parameter values to start with are:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Seed Octaves Lacunarity Fractal increment Offset Gain
fBM11021.2--
Standard multifractal1820.90.9-
Heterogeneous multifractal1830.90.4-
Hybrid multifractal1840.10.3-
Ridged multifractal2840.50.92
+

+Detailed algorithms descriptions can be found in:

+Ebert, D.S., Musgrave, F.K., Peachey, D., Perlin, K., and Worley, S.
+Texturing and Modeling: A Procedural Approach.
+Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 2002. + +

Parameters

@@ -500,71 +500,71 @@ Don't change the seed if you want to refine the current terrain morphology by ch \section f48 Fractal Displacement -Generates a fractal terrain perturbation with five different algorithms.
-Some good parameter values to start with are:
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Seed Octaves Lacunarity Fractal increment Offset Gain
fBM11021.2--
Standard multifractal1820.90.9-
Heterogeneous multifractal1830.90.4-
Hybrid multifractal1840.10.3-
Ridged multifractal2840.50.92
-

-Detailed algorithms descriptions can be found in:

-Ebert, D.S., Musgrave, F.K., Peachey, D., Perlin, K., and Worley, S.
-Texturing and Modeling: A Procedural Approach.
-Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 2002. - - +Generates a fractal terrain perturbation with five different algorithms.
+Some good parameter values to start with are:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Seed Octaves Lacunarity Fractal increment Offset Gain
fBM11021.2--
Standard multifractal1820.90.9-
Heterogeneous multifractal1830.90.4-
Hybrid multifractal1840.10.3-
Ridged multifractal2840.50.92
+

+Detailed algorithms descriptions can be found in:

+Ebert, D.S., Musgrave, F.K., Peachey, D., Perlin, K., and Worley, S.
+Texturing and Modeling: A Procedural Approach.
+Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 2002. + +

Hint: search a good compromise between offset and height factor parameter.

Parameters

@@ -584,18 +584,18 @@ Don't change the seed if you want to refine the current terrain morphology by ch \section f49 Craters Generation -Generates craters onto a mesh using radial functions.
-There must be at least two layers to apply this filter:
- - -There are three radial functions available to generate craters, two of which are Gaussian and Multiquadric, -and the third is a variant of multiquadric. Blending functions are also provided to blend -the crater elevation towards the mesh surface. -If you want the preview to work, be sure to select the target mesh layer before launching the -filter. You can select this layer by clicking on it in the layer dialog. +Generates craters onto a mesh using radial functions.
+There must be at least two layers to apply this filter:
+ + +There are three radial functions available to generate craters, two of which are Gaussian and Multiquadric, +and the third is a variant of multiquadric. Blending functions are also provided to blend +the crater elevation towards the mesh surface. +If you want the preview to work, be sure to select the target mesh layer before launching the +filter. You can select this layer by clicking on it in the layer dialog.

Parameters

@@ -619,7 +619,7 @@ filter. You can select this layer by clicking on it in the layer dialog. \section f50 Conditional Vertex Selection -Boolean function using muparser lib to perform vertex selection over current mesh.
It's possibile to use parenthesis, per-vertex variables and boolean operator:
(,),and,or,<>,=
It's possibile to use the following per-vertex variables in the expression:
x, y, z, nx, ny, nz (normal), r, g, b (color), q (quality), rad, vi,
and all custom vertex attributes already defined by user.
+Boolean function using muparser lib to perform vertex selection over current mesh.
It's possible to use parenthesis, per-vertex variables and boolean operator:
(,),and,or,<>,=
It's possible to use the following per-vertex variables in the expression:
x, y, z, nx, ny, nz (normal), r, g, b (color), q (quality), rad, vi,
and all custom vertex attributes already defined by user.

Parameters

@@ -628,7 +628,7 @@ Boolean function using muparser lib to perform vertex selection over current mes \section f51 Conditional Face Selection -Boolean function using muparser lib to perform faces selection over current mesh.
It's possibile to use parenthesis, per-vertex variables and boolean operator:
(,),and,or,<>,=
It's possibile to use per-face variables like attributes associated to the three vertex of every face.
x0,y0,z0 for first vertex; x1,y1,z1 for second vertex; x2,y2,z2 for third vertex.
and also nx0,ny0,nz0 nx1,ny1,nz1 etc. for normals and r0,g0,b0 for color,q0,q1,q2 for quality.
+Boolean function using muparser lib to perform faces selection over current mesh.
It's possible to use parenthesis, per-vertex variables and boolean operator:
(,),and,or,<>,=
It's possible to use per-face variables like attributes associated to the three vertex of every face.
x0,y0,z0 for first vertex; x1,y1,z1 for second vertex; x2,y2,z2 for third vertex.
and also nx0,ny0,nz0 nx1,ny1,nz1 etc. for normals and r0,g0,b0 for color,q0,q1,q2 for quality.

Parameters

\c String boolean function type a boolean function that will be evaluated in order to select a subset of vertices
example: (y > 0) and (ny > 0) --
@@ -636,7 +636,7 @@ Boolean function using muparser lib to perform faces selection over current mesh \section f52 Geometric Function -Geometric function using muparser lib to generate new Coord
You can change x,y,z for every vertex according to the function specified.
It's possibile to use the following per-vertex variables in the expression:
x, y, z, nx, ny, nz (normal), r, g, b (color), q (quality), rad, vi,
and all custom vertex attributes already defined by user.
+Geometric function using muparser lib to generate new Coord
You can change x,y,z for every vertex according to the function specified.
It's possible to use the following per-vertex variables in the expression:
x, y, z, nx, ny, nz (normal), r, g, b (color), q (quality), rad, vi,
and all custom vertex attributes already defined by user.

Parameters

\c String boolean function type a boolean function that will be evaluated in order to select a subset of faces
--
@@ -646,7 +646,7 @@ Geometric function using muparser lib to generate new Coord
You can change x, \section f53 Per Face Color Function -Color function using muparser lib to generate new RGB color for every face
Insert three function each one for red, green and blue channel respectively.
It's possibile to use per-face variables like attributes associated to the three vertex of every face.
x0,y0,z0 for first vertex; x1,y1,z1 for second vertex; x2,y2,z2 for third vertex.
and also nx0,ny0,nz0 nx1,ny1,nz1 etc. for normals and r0,g0,b0 for color,q0,q1,q2 for quality.
+Color function using muparser lib to generate new RGB color for every face
Insert three function each one for red, green and blue channel respectively.
It's possible to use per-face variables like attributes associated to the three vertex of every face.
x0,y0,z0 for first vertex; x1,y1,z1 for second vertex; x2,y2,z2 for third vertex.
and also nx0,ny0,nz0 nx1,ny1,nz1 etc. for normals and r0,g0,b0 for color,q0,q1,q2 for quality.

Parameters

\c String func x = insert function to generate new coord for x --
@@ -656,7 +656,7 @@ Color function using muparser lib to generate new RGB color for every face
In \section f54 Per Vertex Color Function -Color function using muparser lib to generate new RGB color for every vertex
Insert three function each one for red, green and blue channel respectively.
It's possibile to use the following per-vertex variables in the expression:
x, y, z, nx, ny, nz (normal), r, g, b (color), q (quality), rad, vi,
and all custom vertex attributes already defined by user.
+Color function using muparser lib to generate new RGB color for every vertex
Insert three function each one for red, green and blue channel respectively.
It's possible to use the following per-vertex variables in the expression:
x, y, z, nx, ny, nz (normal), r, g, b (color), q (quality), rad, vi,
and all custom vertex attributes already defined by user.

Parameters

\c String func r = function to generate Red component. Expected Range 0-255 --
@@ -666,7 +666,7 @@ Color function using muparser lib to generate new RGB color for every vertex
\section f55 Per Vertex Quality Function -Quality function using muparser to generate new Quality for every vertex
It's possibile to use the following per-vertex variables in the expression:
x, y, z, nx, ny, nz (normal), r, g, b (color), q (quality), rad, vi,
and all custom vertex attributes already defined by user.
+Quality function using muparser to generate new Quality for every vertex
It's possible to use the following per-vertex variables in the expression:
x, y, z, nx, ny, nz (normal), r, g, b (color), q (quality), rad, vi,
and all custom vertex attributes already defined by user.

Parameters

\c String func r = function to generate Red component. Expected Range 0-255 --
@@ -676,7 +676,7 @@ Quality function using muparser to generate new Quality for every vertex
It's \section f56 Per Face Quality Function -Quality function using muparser to generate new Quality for every face
Insert three function each one for quality of the three vertex of a face
It's possibile to use per-face variables like attributes associated to the three vertex of every face.
x0,y0,z0 for first vertex; x1,y1,z1 for second vertex; x2,y2,z2 for third vertex.
and also nx0,ny0,nz0 nx1,ny1,nz1 etc. for normals and r0,g0,b0 for color,q0,q1,q2 for quality.
+Quality function using muparser to generate new Quality for every face
Insert three function each one for quality of the three vertex of a face
It's possible to use per-face variables like attributes associated to the three vertex of every face.
x0,y0,z0 for first vertex; x1,y1,z1 for second vertex; x2,y2,z2 for third vertex.
and also nx0,ny0,nz0 nx1,ny1,nz1 etc. for normals and r0,g0,b0 for color,q0,q1,q2 for quality.

Parameters

\c String func q = function to generate new Quality for every vertex --
@@ -686,7 +686,7 @@ Quality function using muparser to generate new Quality for every face
Insert \section f57 Define New Per Vertex Attribute -Add a new Per-Vertex scalar attribute to current mesh and fill it with the defined function.
The name specified below can be used in other filter functionIt's possibile to use the following per-vertex variables in the expression:
x, y, z, nx, ny, nz (normal), r, g, b (color), q (quality), rad, vi,
and all custom vertex attributes already defined by user.
+Add a new Per-Vertex scalar attribute to current mesh and fill it with the defined function.
The name specified below can be used in other filter functionIt's possible to use the following per-vertex variables in the expression:
x, y, z, nx, ny, nz (normal), r, g, b (color), q (quality), rad, vi,
and all custom vertex attributes already defined by user.

Parameters

\c String func q0 = function to generate new Quality foreach face --
@@ -748,7 +748,7 @@ The filter build the abstract Isoparameterization of a two-manifold triangular m - +
\c String Name the name of new attribute. you can access attribute in other filters through this name --
\c Int Abstract Min Mesh Size This number and the following one indicate the range face number of the abstract mesh that is used for the parametrization process.
The algorithm will choose the best abstract mesh with the number of triangles within the specified interval.
If the mesh has a very simple structure this range can be very low and strict;for a roughly spherical object if you can specify a range of [8,8] faces you get a octahedral abstract mesh, e.g. a geometry image.
Large numbers (greater than 400) are usually not of practical use. --
\c Int Abstract Max Mesh Size See above. --
\c Enum Optimization Criteria Choose a metric to stop the parametrization within the interval
1: Best Heuristic : stop considering both isometry and number of faces of base domain
2: Area + Angle : stop at minimum area and angle distorsion
3: Regularity : stop at minimum number of irregular vertices
4: L2 : stop at minimum OneWay L2 Stretch Eff --
\c Int Convergence Precision This parameter controls the convergence speed/precision of the optimization of the texture coordinates. Larger the number slower the processing and ,eventually, slighly better results --
\c Int Convergence Precision This parameter controls the convergence speed/precision of the optimization of the texture coordinates. Larger the number slower the processing and, eventually, slightly better results --
\c Bool Double Step Use this bool to divide the parameterization in 2 steps. Double step makes the overall process faster and robust, but it may increase the distorsion --
@@ -765,7 +765,7 @@ Remeshing based on an Abstract Isoparameterization, each triangle of the domain The filter build a new mesh with a standard atlased per wedge texture. The atlas is simply done by splitting each triangle of the abstract domain
For more details see:
Pietroni, Tarini and Cignoni, 'Almost isometric mesh parameterization through abstract domains'
IEEE Transaction of Visualization and Computer Graphics 2010

Parameters

- +
\c DynamicFloat BorderSize ratio This parameter controls the amount of space that must be left between each diamond when building the atlas.It directly affects how many triangle are splitted during this conversion.
In abstract parametrization mesh triangles can naturally cross the triangles of the abstract domain, so when converting to a standard parametrization we must cut all the triangles that protrudes outside each diamond more than the specified threshold.The unit of the threshold is in percentage of the size of the diamond,The bigger the threshold the less triangles are splitted, but the more UV space is used (wasted). --
\c DynamicFloat BorderSize ratio This parameter controls the amount of space that must be left between each diamond when building the atlas.It directly affects how many triangle are split during this conversion.
In abstract parametrization mesh triangles can naturally cross the triangles of the abstract domain, so when converting to a standard parametrization we must cut all the triangles that protrudes outside each diamond more than the specified threshold.The unit of the threshold is in percentage of the size of the diamond,The bigger the threshold the less triangles are split, but the more UV space is used (wasted). --
\section f65 Iso Parametrization Load Abstract Domain @@ -881,7 +881,7 @@ Removes null faces (the one with area equal to zero) No parameters.
\section f81 Select Faces with edges longer than... -Select all triangles having an edge with lenght greater or equal than a given threshold +Select all triangles having an edge with length greater or equal than a given threshold

Parameters

@@ -944,7 +944,7 @@ If disabled edges are collapsed onto one of the two original vertices and the fi \section f85 Subdivision Surfaces: Midpoint -Apply a plain subdivision scheme where every edge is splitted on its midpoint +Apply a plain subdivision scheme where every edge is split on its midpoint

Parameters

\c DynamicFloat Edge Threshold All the faces with an edge longer than this threshold will be deleted. Useful for removing long skinny faces obtained by bad triangulation of range maps. --
@@ -978,8 +978,8 @@ Generate a matrix transformation that rotates the mesh. The mesh can be rotated
\c Int Iterations Number of time the model is subdivided. --
- - + + @@ -1010,7 +1010,7 @@ Generate a matrix transformation that scale the mesh. The mesh can be also autom - +
\c Enum Rotation on: Choose a method --
\c Enum Center of rotation: Choose a method --
\c DynamicFloat Rotation Angle Angle of rotation (in degree). If snapping is enable this vaule is rounded according to the snap value --
\c Bool Snap angle If selected, before starting the filter will remove anyy unreference vertex (for which curvature values are not defined) --
\c DynamicFloat Rotation Angle Angle of rotation (in degree). If snapping is enable this value is rounded according to the snap value --
\c Bool Snap angle If selected, before starting the filter will remove any unreference vertex (for which curvature values are not defined) --
\c Point3f Custom axis This rotation axis is used only if the 'custom axis' option is chosen. --
\c Point3f Custom center This rotation center is used only if the 'custom point' option is chosen. --
\c Float Snapping Value This value is used to snap the rotation angle. --
\c Bool Uniform Scaling If selected an uniform scaling (the same for all the three axis) is applied (the X axis value is used) --
\c Enum Center of rotation: Choose a method --
\c Point3f Custom center This rotation center is used only if the 'custom point' option is chosen. --
\c Bool Scale to Unit bbox If selected, the object is scaled to a box whose sides are at most 1 unit lenght --
\c Bool Scale to Unit bbox If selected, the object is scaled to a box whose sides are at most 1 unit length --
\c Bool Freeze Matrix The transformation is explicitly applied and the vertex coords are actually changed --
@@ -1022,7 +1022,7 @@ Generate a matrix transformation that translate the mesh. The mesh can be transl \c DynamicFloat X Axis Absolute translation amount along the X axis -- \c DynamicFloat Y Axis Absolute translation amount along the Y axis -- \c DynamicFloat Z Axis Absolute translation amount along the Z axis -- - \c Bool translate center of bbox to the origin If selected, the object is scaled to a box whose sides are at most 1 unit lenght -- + \c Bool translate center of bbox to the origin If selected, the object is scaled to a box whose sides are at most 1 unit length -- \c Bool Freeze Matrix The transformation is explicitly applied and the vertex coords are actually changed -- @@ -1036,7 +1036,7 @@ No parameters.
Compute the normals of the vertices of a mesh without exploiting the triangle connectivity, useful for dataset with no faces

Parameters

- +
\c Int Number of neigbors The number of neighbors used to estimate and propagate normals. --
\c Int Number of neighbors The number of neighbors used to estimate and propagate normals. --
\section f95 Compute curvature principal directions @@ -1045,7 +1045,7 @@ Compute the principal directions of curvature with several algorithms

Parameters

- +
\c Enum Method: Choose a method --
\c Bool Remove Unreferenced Vertices If selected, before starting the filter will remove anyy unreference vertex (for which curvature values are not defined) --
\c Bool Remove Unreferenced Vertices If selected, before starting the filter will remove any unreference vertex (for which curvature values are not defined) --
\section f96 Close Holes @@ -1158,7 +1158,7 @@ It is relative to the radius (local point spacing) of the vertices. -- \c Float Projection - Accuracy (adv) Threshold value used to stop the projections. This value is scaled by the mean point spacing to get the actual threshold. -- \c Int Projection - Max iterations (adv) Max number of iterations for the projection. -- - \c Float MLS - Spherical parameter Control the curvature of the fitted spheres: 0 is equivalent to a pure plane fit,1 to a pure spherical fit, values between 0 and 1 gives intermediate results,while others real values might give interresting results, but take care with extremesettings ! -- + \c Float MLS - Spherical parameter Control the curvature of the fitted spheres: 0 is equivalent to a pure plane fit,1 to a pure spherical fit, values between 0 and 1 gives intermediate results,while others real values might give interesting results, but take care with extremesettings ! -- \c Bool Accurate normals If checked, use the accurate MLS gradient instead of the local approximationto compute the normals. -- \c Int Refinement - Max subdivisions Max number of subdivisions. -- \c Float Refinement - Crease angle (degree) Threshold angle between two faces controlling the refinement. -- @@ -1189,7 +1189,7 @@ It is relative to the radius (local point spacing) of the vertices. -- \c Float Projection - Accuracy (adv) Threshold value used to stop the projections. This value is scaled by the mean point spacing to get the actual threshold. -- \c Int Projection - Max iterations (adv) Max number of iterations for the projection. -- - \c Float MLS - Spherical parameter Control the curvature of the fitted spheres: 0 is equivalent to a pure plane fit,1 to a pure spherical fit, values between 0 and 1 gives intermediate results,while others real values might give interresting results, but take care with extremesettings ! -- + \c Float MLS - Spherical parameter Control the curvature of the fitted spheres: 0 is equivalent to a pure plane fit,1 to a pure spherical fit, values between 0 and 1 gives intermediate results,while others real values might give interesting results, but take care with extremesettings ! -- \c Bool Accurate normals If checked, use the accurate MLS gradient instead of the local approximationto compute the normals. -- \c Int Grid Resolution The resolution of the grid on which we run the marching cubes.This marching cube is memory friendly, so you can safely set large values up to 1000 or even more. -- @@ -1221,7 +1221,7 @@ It is relative to the radius (local point spacing) of the vertices. -- \c Float Projection - Accuracy (adv) Threshold value used to stop the projections. This value is scaled by the mean point spacing to get the actual threshold. -- \c Int Projection - Max iterations (adv) Max number of iterations for the projection. -- - \c Float MLS - Spherical parameter Control the curvature of the fitted spheres: 0 is equivalent to a pure plane fit,1 to a pure spherical fit, values between 0 and 1 gives intermediate results,while others real values might give interresting results, but take care with extremesettings ! -- + \c Float MLS - Spherical parameter Control the curvature of the fitted spheres: 0 is equivalent to a pure plane fit,1 to a pure spherical fit, values between 0 and 1 gives intermediate results,while others real values might give interesting results, but take care with extremesettings ! -- \c Enum Curvature type The type of the curvature to plot.
ApproxMean uses the radius of the fitted sphere as an approximation of the mean curvature. --
@@ -1259,7 +1259,7 @@ The surface reconstrction algorithm that have been used for a long time inside t \section f115 Simplfication: MC Edge Collapse -A simplification/cleaning algoritm tailored for meshes generated by Marching Cubes algorithm. +A simplification/cleaning algorithm tailored for meshes generated by Marching Cubes algorithm.

Parameters

No parameters.
\section f116 Surface Reconstruction: Poisson @@ -1315,7 +1315,7 @@ Calculate the Alpha Shape of the mesh(Edelsbrunner and P.Mucke 1994) with \section f121 Select Visible Points -Select the visible points in a point cloud, as viewed from a given viewpoint.
It uses the Qhull library (http://www.qhull.org/

The algorithm used (Katz, Tal and Basri 2007) determines visibility without reconstructing a surface or estimating normals.A point is considered visible if its transformed point lies on the convex hull of a trasformed points cloud from the original mesh points. +Select the visible points in a point cloud, as viewed from a given viewpoint.
It uses the Qhull library (http://www.qhull.org/

The algorithm used (Katz, Tal and Basri 2007) determines visibility without reconstructing a surface or estimating normals.A point is considered visible if its transformed point lies on the convex hull of a transformed points cloud from the original mesh points.

Parameters

@@ -1332,8 +1332,8 @@ Select the visible points in a point cloud, as viewed from a given viewpo The filter maps quality levels into colors using a colorband built from a transfer function (may be loaded from an external file) and colorizes the mesh vertexes. The minimum, medium and maximum quality values can be set by user to obtain a custom quality range for mapping

Parameters

\c DynamicFloat radius threshold Bounds the radius of the sphere used to select visible points.It is used to adjust the radius of the sphere (calculated as distance between the center and the farthest point from it) according to the following equation:
radius = radius * pow(10,threshold);
As the radius increases more points are marked as visible.Use a big threshold for dense point clouds, a small one for sparse clouds. --
- - + + @@ -1342,7 +1342,7 @@ The filter maps quality levels into colors using a colorband built from a transf \section f123 Mesh Element Subsampling -Create a new layer populated with a point sampling of the current mesh, At most one sample for each element of the mesh is created. Samples are taking in a uniform way, one for each element (vertex/edge/face); all the elements have the same probabilty of being choosen. +Create a new layer populated with a point sampling of the current mesh, At most one sample for each element of the mesh is created. Samples are taking in a uniform way, one for each element (vertex/edge/face); all the elements have the same probability of being chosen.

Parameters

\c Float Minimum mesh quality The specified quality value is mapped in the lower end of the choosen color scale. Default value: the minumum quality value found on the mesh. --
\c Float Maximum mesh quality The specified quality value is mapped in the upper end of the choosen color scale. Default value: the maximum quality value found on the mesh. --
\c Float Minimum mesh quality The specified quality value is mapped in the lower end of the chosen color scale. Default value: the minimum quality value found on the mesh. --
\c Float Maximum mesh quality The specified quality value is mapped in the upper end of the chosen color scale. Default value: the maximum quality value found on the mesh. --
\c Float Gamma biasing (0..100) Defines a gamma compression of the quality values, by setting the position of the middle of the color scale. Value is defined as a percentage (0..100). Default value is 50, that corresponds to a linear mapping. --
\c Float Mesh brightness must be between 0 and 2. 0 represents a completely dark mesh, 1 represents a mesh colorized with original colors, 2 represents a completely bright mesh --
\c Enum Transfer Function type to apply to filter Choose the Transfer Function to apply to the filter --
@@ -1354,7 +1354,7 @@ Create a new layer populated with a point sampling of the current mesh, At most Create a new layer populated with a point sampling of the current mesh; samples are generated in a randomly uniform way, or with a distribution biased by the per-vertex quality values of the mesh.

Parameters

\c Enum Element to sample: Choose what mesh element has to be used for the subsampling. At most one point sample will be added for each one of the chosen elements --
- +
\c Int Number of samples The desired number of samples. It can be smaller or larger than the mesh size, and according to the choosed sampling strategy it will try to adapt. --
\c Int Number of samples The desired number of samples. It can be smaller or larger than the mesh size, and according to the chosen sampling strategy it will try to adapt. --
\c Bool Quality Weighted Sampling Use per vertex quality to drive the vertex sampling. The number of samples falling in each face is proportional to the face area multiplied by the average quality of the face vertices. --
\c Bool Exact Sample Num If the required total number of samples is not a strict exact requirement we can exploit a different algorithmbased on the choice of the number of samples inside each triangle by a random Poisson-distributed number with mean equal to the expected number of samples times the area of the triangle over the surface of the whole mesh. --
@@ -1364,7 +1364,7 @@ Create a new layer populated with a point sampling of the current mesh; samples Create a new layer populated with a point sampling of the current mesh; to generate multiple samples inside a triangle each triangle is subdivided according to various stratified strategies. Distribution is often biased by triangle shape.

Parameters

- +
\c Int Number of samples The desired number of samples. It can be smaller or larger than the mesh size, and according to the choosed sampling strategy it will try to adapt. --
\c Int Number of samples The desired number of samples. It can be smaller or larger than the mesh size, and according to the chosen sampling strategy it will try to adapt. --
\c Enum Element to sample: Similar Triangle: each triangle is subdivided into similar triangles and the internal vertices of these triangles are considered. This sampling leave space around edges and vertices for separate sampling of these entities.
Dual Similar Triangle: each triangle is subdivided into similar triangles and the internal vertices of these triangles are considered.
Long Edge Subdiv each triangle is recursively subdivided along the longest edge.
Sample Edges Only the edges of the mesh are uniformly sampled.
Sample NonFaux Edges Only the non-faux edges of the mesh are uniformly sampled. --
\c Bool Random Sampling if true, for each (virtual) face we draw a random point, otherwise we pick the face midpoint. --
@@ -1375,7 +1375,7 @@ Create a new layer populated with a subsampling of the vertexes of the current

Parameters

- +
\c AbsPerc Cell Size The size of the cell of the clustering grid. Smaller the cell finer the resulting mesh. For obtaining a very coarse mesh use larger values. --
\c Enum Representative Strataegy: Average: for each cell we take the average of the sample falling into. The resulting point is a new point.
Closes to center: for each cell we take the sample that is closest to the center of the cell. Choosen vertices are a subset of the original ones. --
\c Enum Representative Strataegy: Average: for each cell we take the average of the sample falling into. The resulting point is a new point.
Closes to center: for each cell we take the sample that is closest to the center of the cell. Chosen vertices are a subset of the original ones. --
\c Bool Selected If true only for the filter is applied only on the selected subset of the mesh. --
@@ -1386,7 +1386,7 @@ Create a new layer populated with a point sampling of the current mesh; samples - + @@ -1400,7 +1400,7 @@ Create a new layer populated with a point sampling of the current mesh; samples - +
\c Int Number of samples The desired number of samples. The ray of the disk is calculated according to the sampling density. --
\c AbsPerc Explicit Radius If not zero this parameter override the previous parameter to allow exact radius specification --
\c Int MonterCarlo OverSampling The over-sampling rate that is used to generate the intial Montecarlo samples (e.g. if this parameter is K means thatK x poisson sample points will be used). The generated Poisson-disk samples are a subset of these initial Montecarlo samples. Larger this number slows the process but make it a bit more accurate. --
\c Int MonterCarlo OverSampling The over-sampling rate that is used to generate the initial Montecarlo samples (e.g. if this parameter is K means thatK x poisson sample points will be used). The generated Poisson-disk samples are a subset of these initial Montecarlo samples. Larger this number slows the process but make it a bit more accurate. --
\c Bool Base Mesh Subsampling If true the original vertices of the base mesh are used as base set of points. In this case the SampleNum should be obviously much smaller than the original vertex number.
Note that this option is very useful in the case you want to subsample a dense point cloud. --
\c Bool Refine Existing Samples If true the vertices of the below mesh are used as starting vertices, and they will utterly refined by adding more and more points until possible. --
\c Mesh Samples to be refined Used only if the above option is checked. --
\c Int Number of samples The desired number of samples. The ray of the disk is calculated according to the sampling density. --
\c AbsPerc Explicit Radius If not zero this parameter override the previous parameter to allow exact radius specification --
\c Float Radius Variance The radius of the disk is allowed to vary between r/var and r*var. If this parameter is 1 the sampling is the same of the Poisson Disk Sampling --
\c Int MonterCarlo OverSampling The over-sampling rate that is used to generate the intial Montecarlo samples (e.g. if this parameter is x means that x * poisson sample points will be used). The generated Poisson-disk samples are a subset of these initial Montecarlo samples. Larger this number slows the process but make it a bit more accurate. --
\c Int MonterCarlo OverSampling The over-sampling rate that is used to generate the initial Montecarlo samples (e.g. if this parameter is x means that x * poisson sample points will be used). The generated Poisson-disk samples are a subset of these initial Montecarlo samples. Larger this number slows the process but make it a bit more accurate. --
\c Bool Base Mesh Subsampling If true the original vertices of the base mesh are used as base set of points. In this case the SampleNum should be obviously much smaller than the original vertex number. --
@@ -1416,8 +1416,8 @@ Compute the Hausdorff Distance between two meshes, sampling one of the two and f \c Bool Sample Edges See the above comment. -- \c Bool Sample FauxEdge See the above comment. -- \c Bool Sample Faces See the above comment. -- - \c Int Number of samples The desired number of samples. It can be smaller or larger than the mesh size, and according to the choosed sampling strategy it will try to adapt. -- - \c AbsPerc Max Distance Sample points for which we do not find anything whithin this distance are rejected and not considered neither for averaging nor for max. -- + \c Int Number of samples The desired number of samples. It can be smaller or larger than the mesh size, and according to the chosen sampling strategy it will try to adapt. -- + \c AbsPerc Max Distance Sample points for which we do not find anything within this distance are rejected and not considered neither for averaging nor for max. -- \section f130 Texel Sampling @@ -1426,7 +1426,7 @@ Create a new layer with a point sampling of the current mesh, a sample for each

Parameters

+ Setting this param to 256 means that you get at most 256x256 = 65536 samples).
If this parameter is 0 the size of the current texture is chosen. -- @@ -1435,7 +1435,7 @@ Create a new layer with a point sampling of the current mesh, a sample for each \section f131 Vertex Attribute Transfer -Transfer the choosen per-vertex attributes from one mesh to another. Useful to transfer attributes to different representations of a same object.
For each vertex of the target mesh the closest point (not vertex!) on the source mesh is computed, and the requested interpolated attributes from that source point are copied into the target vertex.
The algorithm assumes that the two meshes are reasonably similar and aligned. +Transfer the chosen per-vertex attributes from one mesh to another. Useful to transfer attributes to different representations of a same object.
For each vertex of the target mesh the closest point (not vertex!) on the source mesh is computed, and the requested interpolated attributes from that source point are copied into the target vertex.
The algorithm assumes that the two meshes are reasonably similar and aligned.

Parameters

\c Int Texture Width A sample for each texel is generated, so the desired texture size is need, only samples for the texels falling inside some faces are generated. - Setting this param to 256 means that you get at most 256x256 = 65536 samples).
If this parameter is 0 the size of the current texture is choosen. --
\c Int Texture Height A sample for each texel is generated, so the desired texture size is need, only samples for the texels falling inside some faces are generated. Setting this param to 256 means that you get at most 256x256 = 65536 samples) --
\c Bool UV Space Sampling The generated texel samples have their UV coords as point positions. The resulting point set is has a square domain, the texels/points, even if on a flat domain retain the original vertex normal to help a better perception of the original provenience. --
@@ -1445,7 +1445,7 @@ Transfer the choosen per-vertex attributes from one mesh to another. Useful to t - +
\c Mesh Source Mesh The mesh that contains the source data that we want to transfer. --
\c Bool Transfer Color if enabled, the color of each vertex of the target mesh will become the color of the corresponding closest point on the source mesh --
\c Bool Transfer quality if enabled, the quality of each vertex of the target mesh will become the quality of the corresponding closest point on the source mesh --
\c Bool Store dist. as quality if enabled, we store the distance of the transferred value as in the vertex quality --
\c AbsPerc Max Dist Search Sample points for which we do not find anything whithin this distance are rejected and not considered for recovering attributes. --
\c AbsPerc Max Dist Search Sample points for which we do not find anything within this distance are rejected and not considered for recovering attributes. --
\section f132 Uniform Mesh Resampling @@ -1458,7 +1458,7 @@ Create a new mesh that is a resampled version of the current one.
The resampl \c Bool Clean Vertices If true the mesh generated by MC will be cleaned by unifying vertices that are almost coincident -- \c Bool Discretize If true the position of the intersected edge of the marching cube grid is not computed by linear interpolation, but it is placed in fixed middle position. As a consequence the resampled object will look severely aliased by a stairstep appearance.
Useful only for simulating the output of 3D printing devices. --
\c Bool Multisample If true the distance field is more accurately compute by multisampling the volume (7 sample for each voxel). Much slower but less artifacts. -- - \c Bool Absolute Distance If true a not signed distance field is computed. In this case you have to choose a not zero Offset and a double surface is built around the original surface, inside and outside. Is useful to convrt thin floating surfaces into solid, thick meshes.. t -- + \c Bool Absolute Distance If true a not signed distance field is computed. In this case you have to choose a not zero Offset and a double surface is built around the original surface, inside and outside. Is useful to convert thin floating surfaces into solid, thick meshes.. t -- \section f133 Voronoi Vertex Clustering @@ -1494,7 +1494,7 @@ Given a Mesh M and a Pointset P, The filter project each vertex of \section f136 Regular Recursive Sampling -The bbox is recrusively partitioned in a octree style, center of bbox are considered, when the center is nearer to the surface than a given thr it is projected on it. It works also for building ofsetted samples. +The bbox is recursively partitioned in a octree style, center of bbox are considered, when the center is nearer to the surface than a given thr it is projected on it. It works also for building offsetted samples.

Parameters

@@ -1672,7 +1672,7 @@ Structure Synth mesh creation based on Eisen Script.
\c AbsPerc Precision Size of the cell, the default is 1/50 of the box diag. Smaller cells give better precision at a higher computational cost. Remember that halving the cell size means that you build a volume 8 times larger. --
- +
\c String Eisen Script grammar Write a grammar according to Eisen Script specification and using the primitives box, sphere, mesh, dot and triangle --
\c Int seed for random construction Seed needed to build the mesh --
\c Int set maximum resolution of sphere primitves, it must be included between 1 and 4 increasing the resolution of the spheres will improve the quality of the mesh --
\c Int set maximum resolution of sphere primitives, it must be included between 1 and 4 increasing the resolution of the spheres will improve the quality of the mesh --
\section f160 UV to Color @@ -1729,7 +1729,7 @@ Transfer texture/vertex color from one mesh to another's texture. \c Mesh Source Mesh The mesh that contains the source data that we want to transfer -- \c Mesh Target Mesh The mesh whose texture will be filled according to source mesh texture or vertex color -- \c Enum Color Data Source Choose to transfer color information from source mesh texture or vertex color -- - \c AbsPerc Max Dist Search Sample points for which we do not find anything whithin this distance are rejected and not considered for recovering data -- + \c AbsPerc Max Dist Search Sample points for which we do not find anything within this distance are rejected and not considered for recovering data -- \c String Texture file The texture file to be created -- \c Int Texture width (px) The texture width -- \c Int Texture height (px) The texture height -- @@ -1744,7 +1744,7 @@ Generates Vertex Color values picking color from another mesh texture. - +
\c Mesh Source Mesh The mesh with associated texture that we want to sample from --
\c Mesh Target Mesh The mesh whose vertex color will be filled according to source mesh texture --
\c AbsPerc Max Dist Search Sample points for which we do not find anything whithin this distance are rejected and not considered for recovering color --
\c AbsPerc Max Dist Search Sample points for which we do not find anything within this distance are rejected and not considered for recovering color --
\section f167 Planar flipping optimization @@ -1813,7 +1813,7 @@ Scale Dependent Laplacian Smoothing, extended version of Laplacian Smoothing, ba \section f174 TwoStep Smooth -Two Step Smoothing, a feature preserving/enhancing fairing filter. It is based on a Normal Smoothing step where similar normals are averaged toghether and a step where the vertexes are fitted on the new normals +Two Step Smoothing, a feature preserving/enhancing fairing filter. It is based on a Normal Smoothing step where similar normals are averaged together and a step where the vertexes are fitted on the new normals

Parameters

@@ -1932,12 +1932,12 @@ Recompute face normals as the normal of the average of the normals of the triang No parameters.
\section f189 Normalize Face Normals -Normalize Face Normal Lenghts +Normalize Face Normal Lengths

Parameters

No parameters.
\section f190 Normalize Vertex Normals -Normalize Vertex Normal Lenghts +Normalize Vertex Normal Lengths

Parameters

No parameters.
\section f191 Vertex Linear Morphing diff --git a/distrib/LICENSE.txt b/resources/LICENSE.txt similarity index 100% rename from distrib/LICENSE.txt rename to resources/LICENSE.txt diff --git a/resources/README.md b/resources/README.md new file mode 100644 index 000000000..8b30715fe --- /dev/null +++ b/resources/README.md @@ -0,0 +1,10 @@ +# MeshLab resources + +The `resources` folder contains a set of files, binaries and shaders that MeshLab needs to be correctly built, deployed and packaged. + +Examples of contained files: + - icons; + - deployment software binaries; + - configuration files for packaging; + - shaders; + - license, privacy and readme files that are bundled in the final MeshLab packages. \ No newline at end of file diff --git a/resources/icons/eye_cropped.png b/resources/icons/eye_cropped.png new file mode 100644 index 000000000..86c32af84 Binary files /dev/null and b/resources/icons/eye_cropped.png differ diff --git a/resources/icons/meshlab.icns b/resources/icons/meshlab.icns new file mode 100644 index 000000000..395517331 Binary files /dev/null and b/resources/icons/meshlab.icns differ diff --git a/resources/icons/meshlab.ico b/resources/icons/meshlab.ico new file mode 100644 index 000000000..5f6e6866e Binary files /dev/null and b/resources/icons/meshlab.ico differ diff --git a/resources/icons/meshlab.png b/resources/icons/meshlab.png new file mode 100644 index 000000000..717a4e670 Binary files /dev/null and b/resources/icons/meshlab.png differ diff --git a/resources/icons/meshlab100.png b/resources/icons/meshlab100.png new file mode 100644 index 000000000..f3d692466 Binary files /dev/null and b/resources/icons/meshlab100.png differ diff --git a/resources/icons/meshlab16.png b/resources/icons/meshlab16.png new file mode 100644 index 000000000..7a063f194 Binary files /dev/null and b/resources/icons/meshlab16.png differ diff --git a/resources/icons/meshlab200.png b/resources/icons/meshlab200.png new file mode 100644 index 000000000..411f27cd7 Binary files /dev/null and b/resources/icons/meshlab200.png differ diff --git a/resources/icons/meshlab22.png b/resources/icons/meshlab22.png new file mode 100644 index 000000000..055fcbbda Binary files /dev/null and b/resources/icons/meshlab22.png differ diff --git a/resources/icons/meshlab24.png b/resources/icons/meshlab24.png new file mode 100644 index 000000000..6bc65bb05 Binary files /dev/null and b/resources/icons/meshlab24.png differ diff --git a/resources/icons/meshlab256.png b/resources/icons/meshlab256.png new file mode 100644 index 000000000..76b593fb1 Binary files /dev/null and b/resources/icons/meshlab256.png differ diff --git a/resources/icons/meshlab32.png b/resources/icons/meshlab32.png new file mode 100644 index 000000000..c60e0d2c0 Binary files /dev/null and b/resources/icons/meshlab32.png differ diff --git a/resources/icons/meshlab44.png b/resources/icons/meshlab44.png new file mode 100644 index 000000000..575560b58 Binary files /dev/null and b/resources/icons/meshlab44.png differ diff --git a/resources/icons/meshlab48.png b/resources/icons/meshlab48.png new file mode 100644 index 000000000..2dea6465c Binary files /dev/null and b/resources/icons/meshlab48.png differ diff --git a/resources/icons/meshlab50.png b/resources/icons/meshlab50.png new file mode 100644 index 000000000..9f3a13a47 Binary files /dev/null and b/resources/icons/meshlab50.png differ diff --git a/resources/icons/meshlab512.png b/resources/icons/meshlab512.png new file mode 100644 index 000000000..d6b23b44e Binary files /dev/null and b/resources/icons/meshlab512.png differ diff --git a/resources/icons/meshlab63.png b/resources/icons/meshlab63.png new file mode 100644 index 000000000..759bc78f5 Binary files /dev/null and b/resources/icons/meshlab63.png differ diff --git a/resources/icons/meshlab64.png b/resources/icons/meshlab64.png new file mode 100644 index 000000000..f3f2ac07c Binary files /dev/null and b/resources/icons/meshlab64.png differ diff --git a/resources/icons/meshlab75.png b/resources/icons/meshlab75.png new file mode 100644 index 000000000..272e379a6 Binary files /dev/null and b/resources/icons/meshlab75.png differ diff --git a/resources/icons/meshlab8.png b/resources/icons/meshlab8.png new file mode 100644 index 000000000..c2bc18d24 Binary files /dev/null and b/resources/icons/meshlab8.png differ diff --git a/resources/icons/meshlab96.png b/resources/icons/meshlab96.png new file mode 100644 index 000000000..9e74dee0e Binary files /dev/null and b/resources/icons/meshlab96.png differ diff --git a/resources/linux/linuxdeploy b/resources/linux/linuxdeploy new file mode 100755 index 000000000..718019250 Binary files /dev/null and b/resources/linux/linuxdeploy differ diff --git a/resources/linux/linuxdeploy-plugin-appimage b/resources/linux/linuxdeploy-plugin-appimage new file mode 100755 index 000000000..3ff825d6a Binary files /dev/null and b/resources/linux/linuxdeploy-plugin-appimage differ diff --git a/scripts/Linux/resources/linuxdeployqt b/resources/linux/linuxdeploy-plugin-qt similarity index 59% rename from scripts/Linux/resources/linuxdeployqt rename to resources/linux/linuxdeploy-plugin-qt index 917645b94..e66624fc0 100755 Binary files a/scripts/Linux/resources/linuxdeployqt and b/resources/linux/linuxdeploy-plugin-qt differ diff --git a/scripts/Linux/resources/meshlab.desktop b/resources/linux/meshlab.desktop similarity index 86% rename from scripts/Linux/resources/meshlab.desktop rename to resources/linux/meshlab.desktop index 44b5a09d7..426e820b8 100644 --- a/scripts/Linux/resources/meshlab.desktop +++ b/resources/linux/meshlab.desktop @@ -1,13 +1,12 @@ [Desktop Entry] Version=1.0 -Name=MeshLab -Name[en_GB]=MeshLab -GenericName=Mesh processing -GenericName[en_GB]=Mesh processing -Comment=View and process meshes Type=Application +Name=MeshLab +GenericName=Mesh processing +Comment=View and process meshes Exec=meshlab %F -Icon=/usr/share/pixmaps/meshlab.png +Icon=meshlab Terminal=false MimeType=model/mesh;application/x-3ds;image/x-3ds;model/x-ply;application/sla;model/x-quad-object;model/x-geomview-off;application/x-cyclone-ptx;application/x-vmi;application/x-bre;model/vnd.collada+xml;model/openctm;application/x-expe-binary;application/x-expe-ascii;application/x-xyz;application/x-gts;chemical/x-pdb;application/x-tri;application/x-asc;model/x3d+xml;model/x3d+vrml;model/vrml;model/u3d;model/idtf; Categories=Graphics;3DGraphics;Viewer;Qt; +Name[en_US]=MeshLab diff --git a/scripts/macOS/resources/dmg-background.svg b/resources/macos/dmg-background.svg similarity index 100% rename from scripts/macOS/resources/dmg-background.svg rename to resources/macos/dmg-background.svg diff --git a/scripts/macOS/resources/meshlab_dmg_background.png b/resources/macos/meshlab_dmg_background.png similarity index 100% rename from scripts/macOS/resources/meshlab_dmg_background.png rename to resources/macos/meshlab_dmg_background.png diff --git a/scripts/macOS/resources/meshlab_dmg_background@2x.png b/resources/macos/meshlab_dmg_background@2x.png similarity index 100% rename from scripts/macOS/resources/meshlab_dmg_background@2x.png rename to resources/macos/meshlab_dmg_background@2x.png diff --git a/scripts/macOS/resources/meshlab_dmg_latest.json b/resources/macos/meshlab_dmg_latest.json similarity index 54% rename from scripts/macOS/resources/meshlab_dmg_latest.json rename to resources/macos/meshlab_dmg_latest.json index bf15e06a2..996163d97 100644 --- a/scripts/macOS/resources/meshlab_dmg_latest.json +++ b/resources/macos/meshlab_dmg_latest.json @@ -1,12 +1,12 @@ { "title": "MeshLab", - "icon": "SOURCE_PATH/meshlab/images/meshlab.icns", + "icon": "RESOURCES_PATH/icons/meshlab.icns", "background": "meshlab_dmg_background.png", "window" : { "size" : { "width" : 500, "height" : 400 } }, "contents": [ - { "x": 112, "y": 100, "type": "file", "path": "DISTRIB_PATH/meshlab.app" }, + { "x": 112, "y": 100, "type": "file", "path": "DISTRIB_PATH/MeshLabML_VERSION.app" }, { "x": 385, "y": 100, "type": "link", "path": "/Applications" }, - { "x": 250, "y": 280, "type": "file", "path": "LICENSE.txt" }, - { "x": 385, "y": 280, "type": "file", "path": "readme.txt" } + { "x": 250, "y": 280, "type": "file", "path": "RESOURCES_PATH/LICENSE.txt" }, + { "x": 385, "y": 280, "type": "file", "path": "RESOURCES_PATH/readme.txt" } ] } diff --git a/distrib/privacy.txt b/resources/privacy.txt similarity index 56% rename from distrib/privacy.txt rename to resources/privacy.txt index 57b1204d9..5c76e07f2 100644 --- a/distrib/privacy.txt +++ b/resources/privacy.txt @@ -2,8 +2,8 @@ Privacy Disclaimer Please read it carefully. -MeshLab will automatically check for the availability of updated versions and will notify the need of upgrading the software to the users. For this reason, from time to time, MeshLab will issue a http network connection. If you prefer that MeshLab does not communicate in any way with its developers, simply use a plain firewall and prevent any MeshLab access to the network. This will not limit in any way the normal behaviour of MeshLab. When using MeshLab some aggregated statistical data about only the specific usage of MeshLab are collected: the number and size of the opened/saved meshes; nothing more. Periodically this information is sent back to the developers. This data will be used for statistical analysis only. -Paranoids can also look at the sources for seeing what is transmitted. +MeshLab will automatically check for the availability of updated versions and will notify the need of upgrading the software to the users. For this reason, from time to time, MeshLab will issue a http network connection. If you prefer that MeshLab does not communicate in any way with its developers, simply use a plain firewall and prevent any MeshLab access to the network, or disable the update check in the system preferences. This will not limit in any way the normal behaviour of MeshLab apart from getting notified when new releases are distributed. +Important: when using MeshLab the following aggregated statistical data are collected: the number of opened meshes, the number of saved meshes, and the total sum of the number of vertices opened by the user. This statistically aggregated information (three integers) is sent back to the developer when checking for updates. Disabling the check for updates also disable this data collection. We would like to remark that the kind of aggregated information collected by MeshLab is probably by far less sensitive than the information that is silently collected by most web sites when you surf them: ip address, visited pages, frequency of return. We would also like to stress that we really need this information in order to assess how diffusely MeshLab is used and what is its impact on the 3D community. diff --git a/scripts/macOS/resources/readme.txt b/resources/readme.txt similarity index 87% rename from scripts/macOS/resources/readme.txt rename to resources/readme.txt index 75a236787..2bc4b75d7 100644 --- a/scripts/macOS/resources/readme.txt +++ b/resources/readme.txt @@ -2,13 +2,13 @@ http://www.meshlab.net All rights reserved. - VCGLib http://www.vcglib.net o o + VCGLib http://www.vcglib.net o o Visual and Computer Graphics Library o o _ O _ Paolo Cignoni \/)\/ Visual Computing Lab http://vcg.isti.cnr.it /\/| ISTI - Italian National Research Council | - Copyright(C) 2005-2018 \ + Copyright(C) 2005-2022 \ This program is free software; you can redistribute it and/or modify it @@ -22,9 +22,9 @@ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --- Windows Note --- -If you are running MeshLab portable and you are getting the error “MSVCP140.dll not found” -or related, please install Visual C++ Redist by executing the vc_redist.exe file contained -in the meshlab portable archive. +If you are running MeshLab portable and you are getting the error “MSVCP140.dll not found” +or related, please install Visual C++ Redist by executing the vc_redist.exe file contained +in the meshlab portable archive. --- References ---- @@ -32,7 +32,7 @@ Please, when using this tool, cite the following reference: Meshlab: an open-source mesh processing tool. P. Cignoni, M. Callieri, M. Corsini, M. Dellepiane, F. Ganovelli, G. Ranzuglia -Proceedings of the 2008 Eurographics Italian Chapter Conference, +Proceedings of the 2008 Eurographics Italian Chapter Conference, ISBN: 978-3-905673-68-5, pp. 129-136, DOI: 10.2312/LocalChapterEvents/ItalChap/ItalianChapConf2008/129-136 @inproceedings {LocalChapterEvents:ItalChap:ItalianChapConf2008:129-136, @@ -46,11 +46,11 @@ ISBN = {978-3-905673-68-5}, DOI = {10.2312/LocalChapterEvents/ItalChap/ItalianChapConf2008/129-136} } -Paolo Cignoni (p.cignoni (at) isti.cnr.it) -Guido Ranzuglia (g.ranzuglia (at) isti.cnr.it) +Paolo Cignoni (paolo.cignoni (at) isti.cnr.it) +Alessandro Muntoni (alessandro.muntoni (at) isti.cnr.it) For documented and repeatable bugs, reasonable feature requests and grounded issues, please use the GitHub services https://github.com/cnr-isti-vclab/meshlab/issues -For general questions use StackOverflow +For general questions use StackOverflow http://stackoverflow.com/questions/tagged/meshlab diff --git a/distrib/shaders/3Dlabs-license.txt b/resources/shaders/3Dlabs-license.txt similarity index 100% rename from distrib/shaders/3Dlabs-license.txt rename to resources/shaders/3Dlabs-license.txt diff --git a/distrib/shaders/Cook-Torrance.frag b/resources/shaders/Cook-Torrance.frag similarity index 97% rename from distrib/shaders/Cook-Torrance.frag rename to resources/shaders/Cook-Torrance.frag index 82c5a42da..2c0fbd929 100644 --- a/distrib/shaders/Cook-Torrance.frag +++ b/resources/shaders/Cook-Torrance.frag @@ -40,7 +40,7 @@ uniform float ni; void main() { - // the material propertise are embedded in the shader (for now) + // the material properties are embedded in the shader (for now) vec4 mat_ambient = vec4(1.0, 1.0, 1.0, 1.0); vec4 mat_diffuse = gl_Color;//vec4(1.0, 1.0, 1.0, 1.0); vec4 mat_specular= vec4(1.0, 1.0, 1.0, 1.0); diff --git a/distrib/shaders/Cook-Torrance.gdp b/resources/shaders/Cook-Torrance.gdp similarity index 100% rename from distrib/shaders/Cook-Torrance.gdp rename to resources/shaders/Cook-Torrance.gdp diff --git a/distrib/shaders/Cook-Torrance.vert b/resources/shaders/Cook-Torrance.vert similarity index 100% rename from distrib/shaders/Cook-Torrance.vert rename to resources/shaders/Cook-Torrance.vert diff --git a/distrib/shaders/Hatch.frag b/resources/shaders/Hatch.frag similarity index 100% rename from distrib/shaders/Hatch.frag rename to resources/shaders/Hatch.frag diff --git a/distrib/shaders/Hatch.gdp b/resources/shaders/Hatch.gdp similarity index 100% rename from distrib/shaders/Hatch.gdp rename to resources/shaders/Hatch.gdp diff --git a/distrib/shaders/Hatch.vert b/resources/shaders/Hatch.vert similarity index 100% rename from distrib/shaders/Hatch.vert rename to resources/shaders/Hatch.vert diff --git a/distrib/shaders/LightworkDesign-license.txt b/resources/shaders/LightworkDesign-license.txt similarity index 100% rename from distrib/shaders/LightworkDesign-license.txt rename to resources/shaders/LightworkDesign-license.txt diff --git a/distrib/shaders/Oren-Nayar.frag b/resources/shaders/Oren-Nayar.frag similarity index 100% rename from distrib/shaders/Oren-Nayar.frag rename to resources/shaders/Oren-Nayar.frag diff --git a/distrib/shaders/Oren-Nayar.gdp b/resources/shaders/Oren-Nayar.gdp similarity index 100% rename from distrib/shaders/Oren-Nayar.gdp rename to resources/shaders/Oren-Nayar.gdp diff --git a/distrib/shaders/Oren-Nayar.vert b/resources/shaders/Oren-Nayar.vert similarity index 100% rename from distrib/shaders/Oren-Nayar.vert rename to resources/shaders/Oren-Nayar.vert diff --git a/distrib/shaders/SEM.frag b/resources/shaders/SEM.frag similarity index 100% rename from distrib/shaders/SEM.frag rename to resources/shaders/SEM.frag diff --git a/distrib/shaders/SEM.vert b/resources/shaders/SEM.vert similarity index 100% rename from distrib/shaders/SEM.vert rename to resources/shaders/SEM.vert diff --git a/distrib/shaders/ambient_occlusion.vert b/resources/shaders/ambient_occlusion.vert similarity index 100% rename from distrib/shaders/ambient_occlusion.vert rename to resources/shaders/ambient_occlusion.vert diff --git a/distrib/shaders/ambient_occlusion4.frag b/resources/shaders/ambient_occlusion4.frag similarity index 100% rename from distrib/shaders/ambient_occlusion4.frag rename to resources/shaders/ambient_occlusion4.frag diff --git a/distrib/shaders/ambient_occlusion8.frag b/resources/shaders/ambient_occlusion8.frag similarity index 100% rename from distrib/shaders/ambient_occlusion8.frag rename to resources/shaders/ambient_occlusion8.frag diff --git a/distrib/shaders/decorate_shadow/sm/depth.frag b/resources/shaders/decorate_shadow/sm/depth.frag similarity index 100% rename from distrib/shaders/decorate_shadow/sm/depth.frag rename to resources/shaders/decorate_shadow/sm/depth.frag diff --git a/distrib/shaders/decorate_shadow/sm/depth.vert b/resources/shaders/decorate_shadow/sm/depth.vert similarity index 100% rename from distrib/shaders/decorate_shadow/sm/depth.vert rename to resources/shaders/decorate_shadow/sm/depth.vert diff --git a/distrib/shaders/decorate_shadow/sm/object.frag b/resources/shaders/decorate_shadow/sm/object.frag similarity index 100% rename from distrib/shaders/decorate_shadow/sm/object.frag rename to resources/shaders/decorate_shadow/sm/object.frag diff --git a/distrib/shaders/decorate_shadow/sm/object.vert b/resources/shaders/decorate_shadow/sm/object.vert similarity index 100% rename from distrib/shaders/decorate_shadow/sm/object.vert rename to resources/shaders/decorate_shadow/sm/object.vert diff --git a/distrib/shaders/decorate_shadow/ssao/blur.frag b/resources/shaders/decorate_shadow/ssao/blur.frag similarity index 100% rename from distrib/shaders/decorate_shadow/ssao/blur.frag rename to resources/shaders/decorate_shadow/ssao/blur.frag diff --git a/distrib/shaders/decorate_shadow/ssao/blur.vert b/resources/shaders/decorate_shadow/ssao/blur.vert similarity index 100% rename from distrib/shaders/decorate_shadow/ssao/blur.vert rename to resources/shaders/decorate_shadow/ssao/blur.vert diff --git a/distrib/shaders/decorate_shadow/ssao/normalMap.frag b/resources/shaders/decorate_shadow/ssao/normalMap.frag similarity index 100% rename from distrib/shaders/decorate_shadow/ssao/normalMap.frag rename to resources/shaders/decorate_shadow/ssao/normalMap.frag diff --git a/distrib/shaders/decorate_shadow/ssao/normalMap.vert b/resources/shaders/decorate_shadow/ssao/normalMap.vert similarity index 100% rename from distrib/shaders/decorate_shadow/ssao/normalMap.vert rename to resources/shaders/decorate_shadow/ssao/normalMap.vert diff --git a/distrib/shaders/decorate_shadow/ssao/ssao.frag b/resources/shaders/decorate_shadow/ssao/ssao.frag similarity index 100% rename from distrib/shaders/decorate_shadow/ssao/ssao.frag rename to resources/shaders/decorate_shadow/ssao/ssao.frag diff --git a/distrib/shaders/decorate_shadow/ssao/ssao.vert b/resources/shaders/decorate_shadow/ssao/ssao.vert similarity index 100% rename from distrib/shaders/decorate_shadow/ssao/ssao.vert rename to resources/shaders/decorate_shadow/ssao/ssao.vert diff --git a/distrib/shaders/decorate_shadow/vsm/depthVSM.frag b/resources/shaders/decorate_shadow/vsm/depthVSM.frag similarity index 100% rename from distrib/shaders/decorate_shadow/vsm/depthVSM.frag rename to resources/shaders/decorate_shadow/vsm/depthVSM.frag diff --git a/distrib/shaders/decorate_shadow/vsm/depthVSM.vert b/resources/shaders/decorate_shadow/vsm/depthVSM.vert similarity index 100% rename from distrib/shaders/decorate_shadow/vsm/depthVSM.vert rename to resources/shaders/decorate_shadow/vsm/depthVSM.vert diff --git a/distrib/shaders/decorate_shadow/vsm/objectVSM.frag b/resources/shaders/decorate_shadow/vsm/objectVSM.frag similarity index 93% rename from distrib/shaders/decorate_shadow/vsm/objectVSM.frag rename to resources/shaders/decorate_shadow/vsm/objectVSM.frag index 452481f3b..d1c8513b6 100644 --- a/distrib/shaders/decorate_shadow/vsm/objectVSM.frag +++ b/resources/shaders/decorate_shadow/vsm/objectVSM.frag @@ -6,7 +6,7 @@ uniform float shadowIntensity; // 1.0 black, 0, transparent vec4 shadowCoordPostW; float chebyshevUpperBound( float distance) { - // We retrive the two moments previously stored (depth and depth*depth) + // We retrieve the two moments previously stored (depth and depth*depth) vec2 moments = texture2D(shadowMap,shadowCoordPostW.xy).rb; // Surface is fully lit. as the current fragment is before the light occluder if (distance <= moments.x) diff --git a/distrib/shaders/decorate_shadow/vsm/objectVSM.vert b/resources/shaders/decorate_shadow/vsm/objectVSM.vert similarity index 100% rename from distrib/shaders/decorate_shadow/vsm/objectVSM.vert rename to resources/shaders/decorate_shadow/vsm/objectVSM.vert diff --git a/distrib/shaders/decorate_shadow/vsmb/blurVSM.frag b/resources/shaders/decorate_shadow/vsmb/blurVSM.frag similarity index 100% rename from distrib/shaders/decorate_shadow/vsmb/blurVSM.frag rename to resources/shaders/decorate_shadow/vsmb/blurVSM.frag diff --git a/distrib/shaders/decorate_shadow/vsmb/blurVSM.vert b/resources/shaders/decorate_shadow/vsmb/blurVSM.vert similarity index 100% rename from distrib/shaders/decorate_shadow/vsmb/blurVSM.vert rename to resources/shaders/decorate_shadow/vsmb/blurVSM.vert diff --git a/distrib/shaders/decorate_shadow/vsmb/depthVSM.frag b/resources/shaders/decorate_shadow/vsmb/depthVSM.frag similarity index 100% rename from distrib/shaders/decorate_shadow/vsmb/depthVSM.frag rename to resources/shaders/decorate_shadow/vsmb/depthVSM.frag diff --git a/distrib/shaders/decorate_shadow/vsmb/depthVSM.vert b/resources/shaders/decorate_shadow/vsmb/depthVSM.vert similarity index 100% rename from distrib/shaders/decorate_shadow/vsmb/depthVSM.vert rename to resources/shaders/decorate_shadow/vsmb/depthVSM.vert diff --git a/distrib/shaders/decorate_shadow/vsmb/objectVSM.frag b/resources/shaders/decorate_shadow/vsmb/objectVSM.frag similarity index 94% rename from distrib/shaders/decorate_shadow/vsmb/objectVSM.frag rename to resources/shaders/decorate_shadow/vsmb/objectVSM.frag index 264f142a3..e021c958e 100644 --- a/distrib/shaders/decorate_shadow/vsmb/objectVSM.frag +++ b/resources/shaders/decorate_shadow/vsmb/objectVSM.frag @@ -7,7 +7,7 @@ uniform float shadowIntensity; // 1.0 black, 0, transparent vec4 shadowCoordPostW; float chebyshevUpperBound( float distance) { - // We retrive the two moments previously stored (depth and depth*depth) + // We retrieve the two moments previously stored (depth and depth*depth) vec2 moments = texture2D(shadowMap,shadowCoordPostW.xy).rb; // Surface is fully lit. as the current fragment is before the light occluder if (distance <= moments.x) diff --git a/distrib/shaders/decorate_shadow/vsmb/objectVSM.vert b/resources/shaders/decorate_shadow/vsmb/objectVSM.vert similarity index 100% rename from distrib/shaders/decorate_shadow/vsmb/objectVSM.vert rename to resources/shaders/decorate_shadow/vsmb/objectVSM.vert diff --git a/distrib/shaders/depthmap.frag b/resources/shaders/depthmap.frag similarity index 100% rename from distrib/shaders/depthmap.frag rename to resources/shaders/depthmap.frag diff --git a/distrib/shaders/depthmap.gdp b/resources/shaders/depthmap.gdp similarity index 100% rename from distrib/shaders/depthmap.gdp rename to resources/shaders/depthmap.gdp diff --git a/distrib/shaders/depthmap.vert b/resources/shaders/depthmap.vert similarity index 100% rename from distrib/shaders/depthmap.vert rename to resources/shaders/depthmap.vert diff --git a/distrib/shaders/dimple.frag b/resources/shaders/dimple.frag similarity index 100% rename from distrib/shaders/dimple.frag rename to resources/shaders/dimple.frag diff --git a/distrib/shaders/dimple.gdp b/resources/shaders/dimple.gdp similarity index 100% rename from distrib/shaders/dimple.gdp rename to resources/shaders/dimple.gdp diff --git a/distrib/shaders/dimple.vert b/resources/shaders/dimple.vert similarity index 100% rename from distrib/shaders/dimple.vert rename to resources/shaders/dimple.vert diff --git a/distrib/shaders/electronic microscope.gdp b/resources/shaders/electronic microscope.gdp similarity index 100% rename from distrib/shaders/electronic microscope.gdp rename to resources/shaders/electronic microscope.gdp diff --git a/distrib/shaders/envmap.frag b/resources/shaders/envmap.frag similarity index 100% rename from distrib/shaders/envmap.frag rename to resources/shaders/envmap.frag diff --git a/distrib/shaders/envmap.gdp b/resources/shaders/envmap.gdp similarity index 100% rename from distrib/shaders/envmap.gdp rename to resources/shaders/envmap.gdp diff --git a/distrib/shaders/envmap.vert b/resources/shaders/envmap.vert similarity index 100% rename from distrib/shaders/envmap.vert rename to resources/shaders/envmap.vert diff --git a/distrib/shaders/glass.frag b/resources/shaders/glass.frag similarity index 100% rename from distrib/shaders/glass.frag rename to resources/shaders/glass.frag diff --git a/distrib/shaders/glass.gdp b/resources/shaders/glass.gdp similarity index 100% rename from distrib/shaders/glass.gdp rename to resources/shaders/glass.gdp diff --git a/distrib/shaders/glass.vert b/resources/shaders/glass.vert similarity index 100% rename from distrib/shaders/glass.vert rename to resources/shaders/glass.vert diff --git a/distrib/shaders/gooch.frag b/resources/shaders/gooch.frag similarity index 100% rename from distrib/shaders/gooch.frag rename to resources/shaders/gooch.frag diff --git a/distrib/shaders/gooch.gdp b/resources/shaders/gooch.gdp similarity index 100% rename from distrib/shaders/gooch.gdp rename to resources/shaders/gooch.gdp diff --git a/distrib/shaders/gooch.vert b/resources/shaders/gooch.vert similarity index 100% rename from distrib/shaders/gooch.vert rename to resources/shaders/gooch.vert diff --git a/distrib/shaders/lattice.frag b/resources/shaders/lattice.frag similarity index 100% rename from distrib/shaders/lattice.frag rename to resources/shaders/lattice.frag diff --git a/distrib/shaders/lattice.gdp b/resources/shaders/lattice.gdp similarity index 100% rename from distrib/shaders/lattice.gdp rename to resources/shaders/lattice.gdp diff --git a/distrib/shaders/lattice.vert b/resources/shaders/lattice.vert similarity index 100% rename from distrib/shaders/lattice.vert rename to resources/shaders/lattice.vert diff --git a/distrib/shaders/minnaert.frag b/resources/shaders/minnaert.frag similarity index 100% rename from distrib/shaders/minnaert.frag rename to resources/shaders/minnaert.frag diff --git a/distrib/shaders/minnaert.gdp b/resources/shaders/minnaert.gdp similarity index 100% rename from distrib/shaders/minnaert.gdp rename to resources/shaders/minnaert.gdp diff --git a/distrib/shaders/minnaert.vert b/resources/shaders/minnaert.vert similarity index 100% rename from distrib/shaders/minnaert.vert rename to resources/shaders/minnaert.vert diff --git a/distrib/shaders/normalmap.frag b/resources/shaders/normalmap.frag similarity index 100% rename from distrib/shaders/normalmap.frag rename to resources/shaders/normalmap.frag diff --git a/distrib/shaders/normalmap.gdp b/resources/shaders/normalmap.gdp similarity index 100% rename from distrib/shaders/normalmap.gdp rename to resources/shaders/normalmap.gdp diff --git a/distrib/shaders/normalmap.vert b/resources/shaders/normalmap.vert similarity index 100% rename from distrib/shaders/normalmap.vert rename to resources/shaders/normalmap.vert diff --git a/distrib/shaders/phong.frag b/resources/shaders/phong.frag similarity index 100% rename from distrib/shaders/phong.frag rename to resources/shaders/phong.frag diff --git a/distrib/shaders/phong.gdp b/resources/shaders/phong.gdp similarity index 100% rename from distrib/shaders/phong.gdp rename to resources/shaders/phong.gdp diff --git a/distrib/shaders/phong.vert b/resources/shaders/phong.vert similarity index 100% rename from distrib/shaders/phong.vert rename to resources/shaders/phong.vert diff --git a/distrib/shaders/polkadot3d.frag b/resources/shaders/polkadot3d.frag similarity index 100% rename from distrib/shaders/polkadot3d.frag rename to resources/shaders/polkadot3d.frag diff --git a/distrib/shaders/polkadot3d.gdp b/resources/shaders/polkadot3d.gdp similarity index 100% rename from distrib/shaders/polkadot3d.gdp rename to resources/shaders/polkadot3d.gdp diff --git a/distrib/shaders/polkadot3d.vert b/resources/shaders/polkadot3d.vert similarity index 100% rename from distrib/shaders/polkadot3d.vert rename to resources/shaders/polkadot3d.vert diff --git a/distrib/shaders/reflexion_lines.frag b/resources/shaders/reflexion_lines.frag similarity index 100% rename from distrib/shaders/reflexion_lines.frag rename to resources/shaders/reflexion_lines.frag diff --git a/distrib/shaders/reflexion_lines.gdp b/resources/shaders/reflexion_lines.gdp similarity index 100% rename from distrib/shaders/reflexion_lines.gdp rename to resources/shaders/reflexion_lines.gdp diff --git a/distrib/shaders/reflexion_lines.vert b/resources/shaders/reflexion_lines.vert similarity index 100% rename from distrib/shaders/reflexion_lines.vert rename to resources/shaders/reflexion_lines.vert diff --git a/distrib/shaders/shadersrm/NormalMapping.rfx b/resources/shaders/shadersrm/NormalMapping.rfx similarity index 100% rename from distrib/shaders/shadersrm/NormalMapping.rfx rename to resources/shaders/shadersrm/NormalMapping.rfx diff --git a/distrib/shaders/shadersrm/PhongUntextured.rfx b/resources/shaders/shadersrm/PhongUntextured.rfx similarity index 100% rename from distrib/shaders/shadersrm/PhongUntextured.rfx rename to resources/shaders/shadersrm/PhongUntextured.rfx diff --git a/distrib/shaders/shadersrm/QualityContour.rfx b/resources/shaders/shadersrm/QualityContour.rfx similarity index 100% rename from distrib/shaders/shadersrm/QualityContour.rfx rename to resources/shaders/shadersrm/QualityContour.rfx diff --git a/distrib/shaders/shadersrm/ZBrush.rfx b/resources/shaders/shadersrm/ZBrush.rfx similarity index 100% rename from distrib/shaders/shadersrm/ZBrush.rfx rename to resources/shaders/shadersrm/ZBrush.rfx diff --git a/distrib/shaders/shadersrm/cartoon.rfx b/resources/shaders/shadersrm/cartoon.rfx similarity index 100% rename from distrib/shaders/shadersrm/cartoon.rfx rename to resources/shaders/shadersrm/cartoon.rfx diff --git a/distrib/shaders/shadersrm/old/Depth of Field.rfx b/resources/shaders/shadersrm/old/Depth of Field.rfx similarity index 100% rename from distrib/shaders/shadersrm/old/Depth of Field.rfx rename to resources/shaders/shadersrm/old/Depth of Field.rfx diff --git a/distrib/shaders/shadersrm/old/GlyphBomb.rfx b/resources/shaders/shadersrm/old/GlyphBomb.rfx similarity index 100% rename from distrib/shaders/shadersrm/old/GlyphBomb.rfx rename to resources/shaders/shadersrm/old/GlyphBomb.rfx diff --git a/distrib/shaders/shadersrm/old/ImageBasedLighting.rfx b/resources/shaders/shadersrm/old/ImageBasedLighting.rfx similarity index 100% rename from distrib/shaders/shadersrm/old/ImageBasedLighting.rfx rename to resources/shaders/shadersrm/old/ImageBasedLighting.rfx diff --git a/distrib/shaders/shadersrm/old/Plastic.rfx b/resources/shaders/shadersrm/old/Plastic.rfx similarity index 100% rename from distrib/shaders/shadersrm/old/Plastic.rfx rename to resources/shaders/shadersrm/old/Plastic.rfx diff --git a/distrib/shaders/shadersrm/old/RenderToTexture.rfx b/resources/shaders/shadersrm/old/RenderToTexture.rfx similarity index 100% rename from distrib/shaders/shadersrm/old/RenderToTexture.rfx rename to resources/shaders/shadersrm/old/RenderToTexture.rfx diff --git a/distrib/shaders/shadersrm/old/cubeenvmap.rfx b/resources/shaders/shadersrm/old/cubeenvmap.rfx similarity index 100% rename from distrib/shaders/shadersrm/old/cubeenvmap.rfx rename to resources/shaders/shadersrm/old/cubeenvmap.rfx diff --git a/distrib/shaders/shadersrm/old/fur.rfx b/resources/shaders/shadersrm/old/fur.rfx similarity index 100% rename from distrib/shaders/shadersrm/old/fur.rfx rename to resources/shaders/shadersrm/old/fur.rfx diff --git a/distrib/shaders/shadersrm/old/hatching.rfx b/resources/shaders/shadersrm/old/hatching.rfx similarity index 100% rename from distrib/shaders/shadersrm/old/hatching.rfx rename to resources/shaders/shadersrm/old/hatching.rfx diff --git a/distrib/shaders/slicingplane.frag b/resources/shaders/slicingplane.frag similarity index 100% rename from distrib/shaders/slicingplane.frag rename to resources/shaders/slicingplane.frag diff --git a/distrib/shaders/slicingplane.gdp b/resources/shaders/slicingplane.gdp similarity index 100% rename from distrib/shaders/slicingplane.gdp rename to resources/shaders/slicingplane.gdp diff --git a/distrib/shaders/slicingplane.vert b/resources/shaders/slicingplane.vert similarity index 100% rename from distrib/shaders/slicingplane.vert rename to resources/shaders/slicingplane.vert diff --git a/distrib/shaders/splatpyramid/shader_analysis.frag b/resources/shaders/splatpyramid/shader_analysis.frag similarity index 98% rename from distrib/shaders/splatpyramid/shader_analysis.frag rename to resources/shaders/splatpyramid/shader_analysis.frag index 21480aba7..75341c433 100644 --- a/distrib/shaders/splatpyramid/shader_analysis.frag +++ b/resources/shaders/splatpyramid/shader_analysis.frag @@ -143,7 +143,7 @@ void main (void) { } // average values if there are any valid ellipses - // otherwise the pixel will be writen as unspecified + // otherwise the pixel will be written as unspecified if (valid_pixels > 0.0) { diff --git a/distrib/shaders/splatpyramid/shader_analysis.vert b/resources/shaders/splatpyramid/shader_analysis.vert similarity index 100% rename from distrib/shaders/splatpyramid/shader_analysis.vert rename to resources/shaders/splatpyramid/shader_analysis.vert diff --git a/distrib/shaders/splatpyramid/shader_analysis_color.frag b/resources/shaders/splatpyramid/shader_analysis_color.frag similarity index 98% rename from distrib/shaders/splatpyramid/shader_analysis_color.frag rename to resources/shaders/splatpyramid/shader_analysis_color.frag index 76be6a1bf..34bc40cbe 100644 --- a/distrib/shaders/splatpyramid/shader_analysis_color.frag +++ b/resources/shaders/splatpyramid/shader_analysis_color.frag @@ -143,7 +143,7 @@ void main (void) { } // average values if there are any valid ellipses - // otherwise the pixel will be writen as unspecified + // otherwise the pixel will be written as unspecified if (valid_pixels > 0.0) { bufferA /= valid_pixels; diff --git a/distrib/shaders/splatpyramid/shader_analysis_color.vert b/resources/shaders/splatpyramid/shader_analysis_color.vert similarity index 100% rename from distrib/shaders/splatpyramid/shader_analysis_color.vert rename to resources/shaders/splatpyramid/shader_analysis_color.vert diff --git a/distrib/shaders/splatpyramid/shader_copy.frag b/resources/shaders/splatpyramid/shader_copy.frag similarity index 100% rename from distrib/shaders/splatpyramid/shader_copy.frag rename to resources/shaders/splatpyramid/shader_copy.frag diff --git a/distrib/shaders/splatpyramid/shader_copy.vert b/resources/shaders/splatpyramid/shader_copy.vert similarity index 100% rename from distrib/shaders/splatpyramid/shader_copy.vert rename to resources/shaders/splatpyramid/shader_copy.vert diff --git a/distrib/shaders/splatpyramid/shader_copy_color.frag b/resources/shaders/splatpyramid/shader_copy_color.frag similarity index 100% rename from distrib/shaders/splatpyramid/shader_copy_color.frag rename to resources/shaders/splatpyramid/shader_copy_color.frag diff --git a/distrib/shaders/splatpyramid/shader_copy_color.vert b/resources/shaders/splatpyramid/shader_copy_color.vert similarity index 100% rename from distrib/shaders/splatpyramid/shader_copy_color.vert rename to resources/shaders/splatpyramid/shader_copy_color.vert diff --git a/distrib/shaders/splatpyramid/shader_phong.frag b/resources/shaders/splatpyramid/shader_phong.frag similarity index 100% rename from distrib/shaders/splatpyramid/shader_phong.frag rename to resources/shaders/splatpyramid/shader_phong.frag diff --git a/distrib/shaders/splatpyramid/shader_phong.vert b/resources/shaders/splatpyramid/shader_phong.vert similarity index 100% rename from distrib/shaders/splatpyramid/shader_phong.vert rename to resources/shaders/splatpyramid/shader_phong.vert diff --git a/distrib/shaders/splatpyramid/shader_phong_color.frag b/resources/shaders/splatpyramid/shader_phong_color.frag similarity index 100% rename from distrib/shaders/splatpyramid/shader_phong_color.frag rename to resources/shaders/splatpyramid/shader_phong_color.frag diff --git a/distrib/shaders/splatpyramid/shader_phong_color.vert b/resources/shaders/splatpyramid/shader_phong_color.vert similarity index 100% rename from distrib/shaders/splatpyramid/shader_phong_color.vert rename to resources/shaders/splatpyramid/shader_phong_color.vert diff --git a/distrib/shaders/splatpyramid/shader_point_projection.frag b/resources/shaders/splatpyramid/shader_point_projection.frag similarity index 100% rename from distrib/shaders/splatpyramid/shader_point_projection.frag rename to resources/shaders/splatpyramid/shader_point_projection.frag diff --git a/distrib/shaders/splatpyramid/shader_point_projection.vert b/resources/shaders/splatpyramid/shader_point_projection.vert similarity index 94% rename from distrib/shaders/splatpyramid/shader_point_projection.vert rename to resources/shaders/splatpyramid/shader_point_projection.vert index deb54cc0d..e75391e09 100644 --- a/distrib/shaders/splatpyramid/shader_point_projection.vert +++ b/resources/shaders/splatpyramid/shader_point_projection.vert @@ -23,7 +23,7 @@ void main(void) radius_depth_w.x = 0.0; - // for some reason seting the vector to vec4(0.0) drops + // for some reason setting the vector to vec4(0.0) drops // the performance significantly, at least on the GeForce8800 -- RM 2007-10-19 gl_Position = vec4(1.0); } diff --git a/distrib/shaders/splatpyramid/shader_point_projection_color.frag b/resources/shaders/splatpyramid/shader_point_projection_color.frag similarity index 92% rename from distrib/shaders/splatpyramid/shader_point_projection_color.frag rename to resources/shaders/splatpyramid/shader_point_projection_color.frag index d4d3f4c19..8ebdc9e25 100644 --- a/distrib/shaders/splatpyramid/shader_point_projection_color.frag +++ b/resources/shaders/splatpyramid/shader_point_projection_color.frag @@ -31,7 +31,7 @@ void main(void) gl_FragData[1] = vec4 (radius_depth_w.y, 2.0*depth_interval, screen_pos); gl_FragData[2] = gl_Color; - // avoids point with low quality overwritting point with high quality + // avoids point with low quality overwriting point with high quality // during depth test //gl_FragDepth = gl_FragCoord.z - gl_Color.a*0.05; } diff --git a/distrib/shaders/splatpyramid/shader_point_projection_color.vert b/resources/shaders/splatpyramid/shader_point_projection_color.vert similarity index 94% rename from distrib/shaders/splatpyramid/shader_point_projection_color.vert rename to resources/shaders/splatpyramid/shader_point_projection_color.vert index 52146ddc1..710d5dc56 100644 --- a/distrib/shaders/splatpyramid/shader_point_projection_color.vert +++ b/resources/shaders/splatpyramid/shader_point_projection_color.vert @@ -22,7 +22,7 @@ void main(void) if ( (back_face_culling == 1) && ((dot < -0.0 ))) { radius_depth_w.x = 0.0; - // for some reason seting the vector to vec4(0.0) drops + // for some reason setting the vector to vec4(0.0) drops // the performance significantly, at least on the GeForce8800 -- RM 2007-10-19 gl_Position = vec4(1.0); } diff --git a/distrib/shaders/splatpyramid/shader_synthesis.frag b/resources/shaders/splatpyramid/shader_synthesis.frag similarity index 100% rename from distrib/shaders/splatpyramid/shader_synthesis.frag rename to resources/shaders/splatpyramid/shader_synthesis.frag diff --git a/distrib/shaders/splatpyramid/shader_synthesis.vert b/resources/shaders/splatpyramid/shader_synthesis.vert similarity index 100% rename from distrib/shaders/splatpyramid/shader_synthesis.vert rename to resources/shaders/splatpyramid/shader_synthesis.vert diff --git a/distrib/shaders/splatpyramid/shader_synthesis_color.frag b/resources/shaders/splatpyramid/shader_synthesis_color.frag similarity index 100% rename from distrib/shaders/splatpyramid/shader_synthesis_color.frag rename to resources/shaders/splatpyramid/shader_synthesis_color.frag diff --git a/distrib/shaders/splatpyramid/shader_synthesis_color.vert b/resources/shaders/splatpyramid/shader_synthesis_color.vert similarity index 100% rename from distrib/shaders/splatpyramid/shader_synthesis_color.vert rename to resources/shaders/splatpyramid/shader_synthesis_color.vert diff --git a/distrib/shaders/stripes2.frag b/resources/shaders/stripes2.frag similarity index 100% rename from distrib/shaders/stripes2.frag rename to resources/shaders/stripes2.frag diff --git a/distrib/shaders/stripes2.gdp b/resources/shaders/stripes2.gdp similarity index 100% rename from distrib/shaders/stripes2.gdp rename to resources/shaders/stripes2.gdp diff --git a/distrib/shaders/stripes2.vert b/resources/shaders/stripes2.vert similarity index 100% rename from distrib/shaders/stripes2.vert rename to resources/shaders/stripes2.vert diff --git a/distrib/shaders/toon.frag b/resources/shaders/toon.frag similarity index 100% rename from distrib/shaders/toon.frag rename to resources/shaders/toon.frag diff --git a/distrib/shaders/toon.gdp b/resources/shaders/toon.gdp similarity index 100% rename from distrib/shaders/toon.gdp rename to resources/shaders/toon.gdp diff --git a/distrib/shaders/toon.vert b/resources/shaders/toon.vert similarity index 100% rename from distrib/shaders/toon.vert rename to resources/shaders/toon.vert diff --git a/distrib/shaders/xray.frag b/resources/shaders/xray.frag similarity index 100% rename from distrib/shaders/xray.frag rename to resources/shaders/xray.frag diff --git a/distrib/shaders/xray.gdp b/resources/shaders/xray.gdp similarity index 100% rename from distrib/shaders/xray.gdp rename to resources/shaders/xray.gdp diff --git a/distrib/shaders/xray.vert b/resources/shaders/xray.vert similarity index 100% rename from distrib/shaders/xray.vert rename to resources/shaders/xray.vert diff --git a/scripts/Windows/resources/ExecWaitJob.nsh b/resources/windows/ExecWaitJob.nsh similarity index 100% rename from scripts/Windows/resources/ExecWaitJob.nsh rename to resources/windows/ExecWaitJob.nsh diff --git a/scripts/Windows/resources/FileAssociation.nsh b/resources/windows/FileAssociation.nsh similarity index 100% rename from scripts/Windows/resources/FileAssociation.nsh rename to resources/windows/FileAssociation.nsh diff --git a/scripts/Windows/resources/meshlab.nsi b/resources/windows/meshlab.nsi similarity index 95% rename from scripts/Windows/resources/meshlab.nsi rename to resources/windows/meshlab.nsi index 3f13d9b7c..f50256ed4 100644 --- a/scripts/Windows/resources/meshlab.nsi +++ b/resources/windows/meshlab.nsi @@ -8,7 +8,6 @@ !define PRODUCT_PUBLISHER "Paolo Cignoni - VCG - ISTI - CNR" !define PRODUCT_WEB_SITE "http://www.meshlab.net" !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\meshlab.exe" -;!define PRODUCT_DIR_REGKEY_S "Software\Microsoft\Windows\CurrentVersion\App Paths\meshlabserver.exe" !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" !define PRODUCT_UNINST_ROOT_KEY "HKLM" !define DISTRIB_FOLDER "DISTRIB_PATH" @@ -47,7 +46,7 @@ !define /date NOW "%Y_%m_%d" Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" -OutFile "MeshLab${PRODUCT_VERSION}.exe" +OutFile "MeshLab${PRODUCT_VERSION}-windows.exe" InstallDir "${MAINDIR}\VCG\MeshLab" ShowInstDetails show ShowUnInstDetails show diff --git a/sample/TextureSingle.ply b/sample/TextureSingle.ply new file mode 100644 index 000000000..a5ecc7cd5 --- /dev/null +++ b/sample/TextureSingle.ply @@ -0,0 +1,19 @@ +ply +format ascii 1.0 +comment VCGLIB generated +comment TextureFile TextureDouble_A.png +element vertex 4 +property float x +property float y +property float z +element face 2 +property list uchar int vertex_indices +property list uchar float texcoord +property int texnumber +end_header +0 0 0 +1 0 0 +1 1 0 +0 1 0 +3 0 1 2 6 0 0 2 0 2 2 0 +3 0 2 3 6 0 0 2 2 0 2 0 diff --git a/sample/furniture.3ds b/sample/furniture.3ds new file mode 100644 index 000000000..ea39757e0 Binary files /dev/null and b/sample/furniture.3ds differ diff --git a/sample/gltf/CesiumMan/CesiumMan.gltf b/sample/gltf/CesiumMan/CesiumMan.gltf new file mode 100644 index 000000000..f474e54a7 --- /dev/null +++ b/sample/gltf/CesiumMan/CesiumMan.gltf @@ -0,0 +1,2715 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "scene": 0, + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 0, + -1, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 1 + ], + "name": "Z_UP" + }, + { + "children": [ + 3, + 2 + ], + "matrix": [ + -4.371139894487897e-8, + -1, + 0, + 0, + 1, + -4.371139894487897e-8, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "name": "Armature" + }, + { + "mesh": 0, + "skin": 0, + "name": "Cesium_Man" + }, + { + "children": [ + 12, + 8, + 4 + ], + "translation": [ + 1.57554005397742e-8, + 0.004999836906790733, + 0.6789999008178711 + ], + "rotation": [ + 0, + -0.0378035344183445, + 0, + -0.9992852210998536 + ], + "name": "Skeleton_torso_joint_1", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 5 + ], + "translation": [ + 0.02855719067156315, + -0.06803914159536362, + -0.06295864284038544 + ], + "rotation": [ + 0, + -0.6898291707038879, + 0, + -0.7239722013473511 + ], + "name": "leg_joint_R_1", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 6 + ], + "translation": [ + 0.26089081168174744, + -0.009026050567626951, + 0.05167089030146599 + ], + "rotation": [ + 0, + -0.0941137745976448, + 0, + -0.9955614805221558 + ], + "scale": [ + 1.0000001192092896, + 1, + 1.0000001192092896 + ], + "name": "leg_joint_R_2" + }, + { + "children": [ + 7 + ], + "translation": [ + 0.27546030282974243, + -0.0014317259192466736, + -0.014104830101132391 + ], + "rotation": [ + 0, + 0.8666408061981201, + 0, + 0.4989325702190399 + ], + "name": "leg_joint_R_3", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "translation": [ + -0.06681963056325912, + -0.001072264974936843, + 0.026351310312747955 + ], + "rotation": [ + 0, + 0.3269147574901581, + 0, + -0.9450538158416748 + ], + "name": "leg_joint_R_5", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 9 + ], + "translation": [ + 0.028519999235868457, + 0.06803944706916809, + -0.06295935809612274 + ], + "rotation": [ + 0, + -0.32463353872299194, + 0, + -0.9458398818969728 + ], + "name": "leg_joint_L_1", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 10 + ], + "translation": [ + 0.20916390419006348, + 0.009055502712726591, + -0.16426950693130493 + ], + "rotation": [ + 0, + -0.5294369459152222, + 0, + -0.8483493328094482 + ], + "scale": [ + 1.0000001192092896, + 1, + 1.0000001192092896 + ], + "name": "leg_joint_L_2" + }, + { + "children": [ + 11 + ], + "translation": [ + 0.27579009532928467, + 0.0013972519664093852, + 0.004122479818761349 + ], + "rotation": [ + 0, + -0.8377647399902344, + 0, + -0.5460314750671387 + ], + "scale": [ + 1, + 0.9999999403953552, + 1 + ], + "name": "leg_joint_L_3" + }, + { + "translation": [ + -0.06558381021022797, + 0.001090653007850051, + 0.02929146029055119 + ], + "rotation": [ + 0, + 0.3130458891391754, + 0, + -0.9497380256652832 + ], + "name": "leg_joint_L_5", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 13 + ], + "translation": [ + 0.0000133617004394182, + -0.000013373800356930587, + 0.14541690051555634 + ], + "rotation": [ + 0, + -0.6573964357376099, + 0, + -0.7535448670387268 + ], + "name": "Skeleton_torso_joint_2", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 20, + 17, + 14 + ], + "translation": [ + -0.2505168914794922, + 6.072219775887788e-7, + -0.00007290810026461259 + ], + "rotation": [ + 0, + 0.6227028965950012, + 0, + -0.7824583649635315 + ], + "name": "torso_joint_3", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 15 + ], + "translation": [ + -0.00003830249988823198, + -0.09098774939775468, + -0.000062032304413151 + ], + "rotation": [ + 0, + 0.9909319281578064, + 0, + -0.13436488807201385 + ], + "name": "Skeleton_arm_joint_R", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 16 + ], + "translation": [ + -0.03554634004831314, + -0.2154989987611771, + 0.10423289984464645 + ], + "rotation": [ + 0, + 0.8961479663848877, + 0, + 0.4437553286552429 + ], + "scale": [ + 0.9999999403953552, + 1, + 0.9999999403953552 + ], + "name": "Skeleton_arm_joint_R__2_" + }, + { + "translation": [ + 0.03137021884322167, + -0.1430010050535202, + -0.11761169880628586 + ], + "rotation": [ + 0, + 0.3792171180248261, + 0, + -0.9253078103065492 + ], + "scale": [ + 1.0000001192092896, + 1, + 1.0000001192092896 + ], + "name": "Skeleton_arm_joint_R__3_" + }, + { + "children": [ + 18 + ], + "translation": [ + -0.00003837469921563752, + 0.091013602912426, + -0.00006143339851405472 + ], + "rotation": [ + 0, + 0.9959768652915956, + 0, + 0.08961082249879837 + ], + "name": "Skeleton_arm_joint_L__4_", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 19 + ], + "translation": [ + 0.01322161965072155, + 0.21549950540065768, + 0.10933209955692293 + ], + "rotation": [ + 0, + -0.0711694285273552, + 0, + -0.9974642395973206 + ], + "name": "Skeleton_arm_joint_L__3_", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "translation": [ + -0.09332461655139924, + 0.1430000960826874, + 0.07814791053533554 + ], + "rotation": [ + 0, + -0.02254222705960274, + 0, + -0.9997459053993224 + ], + "name": "Skeleton_arm_joint_L__2_", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "children": [ + 21 + ], + "translation": [ + -0.000002366030003031483, + 0.000002413989932392724, + 0.06483621150255203 + ], + "rotation": [ + 0, + -0.660634458065033, + 0, + -0.750707745552063 + ], + "name": "Skeleton_neck_joint_1", + "scale": [ + 1, + 1, + 1 + ] + }, + { + "translation": [ + -0.05204017087817192, + -3.3993298842460724e-8, + -0.0000026607899599184748 + ], + "rotation": [ + 0, + 0.9996904730796814, + 0, + 0.024879230186343193 + ], + "scale": [ + 1.0000001192092896, + 1, + 1.0000001192092896 + ], + "name": "Skeleton_neck_joint_2" + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "JOINTS_0": 1, + "NORMAL": 2, + "POSITION": 3, + "TEXCOORD_0": 4, + "WEIGHTS_0": 5 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Cesium_Man" + } + ], + "animations": [ + { + "channels": [ + { + "sampler": 0, + "target": { + "node": 3, + "path": "translation" + } + }, + { + "sampler": 1, + "target": { + "node": 3, + "path": "rotation" + } + }, + { + "sampler": 2, + "target": { + "node": 3, + "path": "scale" + } + }, + { + "sampler": 3, + "target": { + "node": 12, + "path": "translation" + } + }, + { + "sampler": 4, + "target": { + "node": 12, + "path": "rotation" + } + }, + { + "sampler": 5, + "target": { + "node": 12, + "path": "scale" + } + }, + { + "sampler": 6, + "target": { + "node": 13, + "path": "translation" + } + }, + { + "sampler": 7, + "target": { + "node": 13, + "path": "rotation" + } + }, + { + "sampler": 8, + "target": { + "node": 13, + "path": "scale" + } + }, + { + "sampler": 9, + "target": { + "node": 20, + "path": "translation" + } + }, + { + "sampler": 10, + "target": { + "node": 20, + "path": "rotation" + } + }, + { + "sampler": 11, + "target": { + "node": 20, + "path": "scale" + } + }, + { + "sampler": 12, + "target": { + "node": 21, + "path": "translation" + } + }, + { + "sampler": 13, + "target": { + "node": 21, + "path": "rotation" + } + }, + { + "sampler": 14, + "target": { + "node": 21, + "path": "scale" + } + }, + { + "sampler": 15, + "target": { + "node": 17, + "path": "translation" + } + }, + { + "sampler": 16, + "target": { + "node": 17, + "path": "rotation" + } + }, + { + "sampler": 17, + "target": { + "node": 17, + "path": "scale" + } + }, + { + "sampler": 18, + "target": { + "node": 18, + "path": "translation" + } + }, + { + "sampler": 19, + "target": { + "node": 18, + "path": "rotation" + } + }, + { + "sampler": 20, + "target": { + "node": 18, + "path": "scale" + } + }, + { + "sampler": 21, + "target": { + "node": 19, + "path": "translation" + } + }, + { + "sampler": 22, + "target": { + "node": 19, + "path": "rotation" + } + }, + { + "sampler": 23, + "target": { + "node": 19, + "path": "scale" + } + }, + { + "sampler": 24, + "target": { + "node": 14, + "path": "translation" + } + }, + { + "sampler": 25, + "target": { + "node": 14, + "path": "rotation" + } + }, + { + "sampler": 26, + "target": { + "node": 14, + "path": "scale" + } + }, + { + "sampler": 27, + "target": { + "node": 15, + "path": "translation" + } + }, + { + "sampler": 28, + "target": { + "node": 15, + "path": "rotation" + } + }, + { + "sampler": 29, + "target": { + "node": 15, + "path": "scale" + } + }, + { + "sampler": 30, + "target": { + "node": 16, + "path": "translation" + } + }, + { + "sampler": 31, + "target": { + "node": 16, + "path": "rotation" + } + }, + { + "sampler": 32, + "target": { + "node": 16, + "path": "scale" + } + }, + { + "sampler": 33, + "target": { + "node": 8, + "path": "translation" + } + }, + { + "sampler": 34, + "target": { + "node": 8, + "path": "rotation" + } + }, + { + "sampler": 35, + "target": { + "node": 8, + "path": "scale" + } + }, + { + "sampler": 36, + "target": { + "node": 9, + "path": "translation" + } + }, + { + "sampler": 37, + "target": { + "node": 9, + "path": "rotation" + } + }, + { + "sampler": 38, + "target": { + "node": 9, + "path": "scale" + } + }, + { + "sampler": 39, + "target": { + "node": 10, + "path": "translation" + } + }, + { + "sampler": 40, + "target": { + "node": 10, + "path": "rotation" + } + }, + { + "sampler": 41, + "target": { + "node": 10, + "path": "scale" + } + }, + { + "sampler": 42, + "target": { + "node": 11, + "path": "translation" + } + }, + { + "sampler": 43, + "target": { + "node": 11, + "path": "rotation" + } + }, + { + "sampler": 44, + "target": { + "node": 11, + "path": "scale" + } + }, + { + "sampler": 45, + "target": { + "node": 4, + "path": "translation" + } + }, + { + "sampler": 46, + "target": { + "node": 4, + "path": "rotation" + } + }, + { + "sampler": 47, + "target": { + "node": 4, + "path": "scale" + } + }, + { + "sampler": 48, + "target": { + "node": 5, + "path": "translation" + } + }, + { + "sampler": 49, + "target": { + "node": 5, + "path": "rotation" + } + }, + { + "sampler": 50, + "target": { + "node": 5, + "path": "scale" + } + }, + { + "sampler": 51, + "target": { + "node": 6, + "path": "translation" + } + }, + { + "sampler": 52, + "target": { + "node": 6, + "path": "rotation" + } + }, + { + "sampler": 53, + "target": { + "node": 6, + "path": "scale" + } + }, + { + "sampler": 54, + "target": { + "node": 7, + "path": "translation" + } + }, + { + "sampler": 55, + "target": { + "node": 7, + "path": "rotation" + } + }, + { + "sampler": 56, + "target": { + "node": 7, + "path": "scale" + } + } + ], + "samplers": [ + { + "input": 6, + "interpolation": "LINEAR", + "output": 7 + }, + { + "input": 6, + "interpolation": "LINEAR", + "output": 8 + }, + { + "input": 6, + "interpolation": "LINEAR", + "output": 9 + }, + { + "input": 10, + "interpolation": "LINEAR", + "output": 11 + }, + { + "input": 10, + "interpolation": "LINEAR", + "output": 12 + }, + { + "input": 10, + "interpolation": "LINEAR", + "output": 13 + }, + { + "input": 14, + "interpolation": "LINEAR", + "output": 15 + }, + { + "input": 14, + "interpolation": "LINEAR", + "output": 16 + }, + { + "input": 14, + "interpolation": "LINEAR", + "output": 17 + }, + { + "input": 18, + "interpolation": "LINEAR", + "output": 19 + }, + { + "input": 18, + "interpolation": "LINEAR", + "output": 20 + }, + { + "input": 18, + "interpolation": "LINEAR", + "output": 21 + }, + { + "input": 22, + "interpolation": "LINEAR", + "output": 23 + }, + { + "input": 22, + "interpolation": "LINEAR", + "output": 24 + }, + { + "input": 22, + "interpolation": "LINEAR", + "output": 25 + }, + { + "input": 26, + "interpolation": "LINEAR", + "output": 27 + }, + { + "input": 26, + "interpolation": "LINEAR", + "output": 28 + }, + { + "input": 26, + "interpolation": "LINEAR", + "output": 29 + }, + { + "input": 30, + "interpolation": "LINEAR", + "output": 31 + }, + { + "input": 30, + "interpolation": "LINEAR", + "output": 32 + }, + { + "input": 30, + "interpolation": "LINEAR", + "output": 33 + }, + { + "input": 34, + "interpolation": "LINEAR", + "output": 35 + }, + { + "input": 34, + "interpolation": "LINEAR", + "output": 36 + }, + { + "input": 34, + "interpolation": "LINEAR", + "output": 37 + }, + { + "input": 38, + "interpolation": "LINEAR", + "output": 39 + }, + { + "input": 38, + "interpolation": "LINEAR", + "output": 40 + }, + { + "input": 38, + "interpolation": "LINEAR", + "output": 41 + }, + { + "input": 42, + "interpolation": "LINEAR", + "output": 43 + }, + { + "input": 42, + "interpolation": "LINEAR", + "output": 44 + }, + { + "input": 42, + "interpolation": "LINEAR", + "output": 45 + }, + { + "input": 46, + "interpolation": "LINEAR", + "output": 47 + }, + { + "input": 46, + "interpolation": "LINEAR", + "output": 48 + }, + { + "input": 46, + "interpolation": "LINEAR", + "output": 49 + }, + { + "input": 50, + "interpolation": "LINEAR", + "output": 51 + }, + { + "input": 50, + "interpolation": "LINEAR", + "output": 52 + }, + { + "input": 50, + "interpolation": "LINEAR", + "output": 53 + }, + { + "input": 54, + "interpolation": "LINEAR", + "output": 55 + }, + { + "input": 54, + "interpolation": "LINEAR", + "output": 56 + }, + { + "input": 54, + "interpolation": "LINEAR", + "output": 57 + }, + { + "input": 58, + "interpolation": "LINEAR", + "output": 59 + }, + { + "input": 58, + "interpolation": "LINEAR", + "output": 60 + }, + { + "input": 58, + "interpolation": "LINEAR", + "output": 61 + }, + { + "input": 62, + "interpolation": "LINEAR", + "output": 63 + }, + { + "input": 62, + "interpolation": "LINEAR", + "output": 64 + }, + { + "input": 62, + "interpolation": "LINEAR", + "output": 65 + }, + { + "input": 66, + "interpolation": "LINEAR", + "output": 67 + }, + { + "input": 66, + "interpolation": "LINEAR", + "output": 68 + }, + { + "input": 66, + "interpolation": "LINEAR", + "output": 69 + }, + { + "input": 70, + "interpolation": "LINEAR", + "output": 71 + }, + { + "input": 70, + "interpolation": "LINEAR", + "output": 72 + }, + { + "input": 70, + "interpolation": "LINEAR", + "output": 73 + }, + { + "input": 74, + "interpolation": "LINEAR", + "output": 75 + }, + { + "input": 74, + "interpolation": "LINEAR", + "output": 76 + }, + { + "input": 74, + "interpolation": "LINEAR", + "output": 77 + }, + { + "input": 78, + "interpolation": "LINEAR", + "output": 79 + }, + { + "input": 78, + "interpolation": "LINEAR", + "output": 80 + }, + { + "input": 78, + "interpolation": "LINEAR", + "output": 81 + } + ] + } + ], + "skins": [ + { + "inverseBindMatrices": 82, + "skeleton": 3, + "joints": [ + 3, + 12, + 13, + 20, + 21, + 17, + 14, + 18, + 15, + 19, + 16, + 8, + 4, + 9, + 5, + 10, + 6, + 11, + 7 + ], + "name": "Armature" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 14016, + "max": [ + 3272 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5123, + "count": 3273, + "max": [ + 18, + 18, + 18, + 18 + ], + "min": [ + 0, + 0, + 0, + 0 + ], + "type": "VEC4" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 3273, + "max": [ + 1, + 0.9999808073043824, + 0.9944415092468262 + ], + "min": [ + -1, + -0.9999808073043824, + -1 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 39276, + "componentType": 5126, + "count": 3273, + "max": [ + 0.1809539943933487, + 0.569136917591095, + 1.5065499544143677 + ], + "min": [ + -0.13100001215934753, + -0.5691370964050293, + 0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 26184, + "componentType": 5126, + "count": 3273, + "max": [ + 0.990805983543396, + 0.9880298972129822 + ], + "min": [ + 0.014079390093684196, + 0.008445978164672852 + ], + "type": "VEC2" + }, + { + "bufferView": 3, + "byteOffset": 0, + "componentType": 5126, + "count": 3273, + "max": [ + 1, + 0.989919900894165, + 0.9510763883590698, + 0.9196179509162904 + ], + "min": [ + 0.010080089792609217, + 0, + 0, + 0 + ], + "type": "VEC4" + }, + { + "bufferView": 4, + "byteOffset": 0, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 0, + "componentType": 5126, + "count": 48, + "max": [ + 3.880559873437051e-8, + -0.02000010944902897, + 0.7110069990158081 + ], + "min": [ + 2.716890046272624e-9, + -0.030000129714608192, + 0.6399999856948853 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 0, + "componentType": 5126, + "count": 48, + "max": [ + 0.0001435002632206306, + -0.02146764844655991, + -0.000009948204024112783, + -0.9980905055999756 + ], + "min": [ + -0.012384946458041668, + -0.06042621284723282, + -0.0041049933061003685, + -0.9997026920318604 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 576, + "componentType": 5126, + "count": 48, + "max": [ + 1.0000004768371584, + 1.0000001192092896, + 1.000000238418579 + ], + "min": [ + 0.9999999403953552, + 0.9999998211860656, + 0.9999997615814208 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 192, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 1152, + "componentType": 5126, + "count": 48, + "max": [ + 0.000013520900211005937, + 0.0009866129839792848, + 0.1454171985387802 + ], + "min": [ + 0.000013436199878924528, + 0.0009865909814834597, + 0.145416796207428 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 768, + "componentType": 5126, + "count": 48, + "max": [ + 0.011148878373205662, + -0.7106494903564453, + 0.0006393495132215321, + -0.6787928938865662 + ], + "min": [ + -0.008564536459743977, + -0.7339289784431458, + -0.025856714695692062, + -0.7034341096878052 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 1728, + "componentType": 5126, + "count": 48, + "max": [ + 1.0000004768371584, + 1.000000238418579, + 0.9999998211860656 + ], + "min": [ + 0.9999999403953552, + 0.9999998807907104, + 0.9999989867210388 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 384, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 2304, + "componentType": 5126, + "count": 48, + "max": [ + -0.25051650404930115, + 5.923209869251878e-7, + -0.00007277730037458241 + ], + "min": [ + -0.25051701068878174, + 5.58793999516638e-7, + -0.00007287789776455611 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 1536, + "componentType": 5126, + "count": 48, + "max": [ + 0.13804565370082855, + 0.6359269618988037, + -0.003375347936525941, + -0.7641801238059998 + ], + "min": [ + -0.06163197010755539, + 0.6225405335426331, + -0.0653248131275177, + -0.7825579643249512 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 2880, + "componentType": 5126, + "count": 48, + "max": [ + 1.000001072883606, + 1.0000003576278689, + 1 + ], + "min": [ + 1.0000004768371584, + 0.9999999403953552, + 0.999999463558197 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 576, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 3456, + "componentType": 5126, + "count": 48, + "max": [ + -0.000002384189883741783, + 0.000002458690005369135, + 0.06483876705169678 + ], + "min": [ + -0.000002536919964768458, + 0.000002384189883741783, + 0.06483828276395798 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 2304, + "componentType": 5126, + "count": 48, + "max": [ + 0.0364987850189209, + -0.6325404644012451, + 0.04193282127380371, + -0.749859094619751 + ], + "min": [ + -0.02474863827228546, + -0.6592763066291809, + -0.03008362464606762, + -0.7735469341278076 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 4032, + "componentType": 5126, + "count": 48, + "max": [ + 1, + 1.000000238418579, + 1.000000238418579 + ], + "min": [ + 0.9999996423721313, + 0.9999995231628418, + 0.9999995827674866 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 768, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 4608, + "componentType": 5126, + "count": 48, + "max": [ + -0.0520395003259182, + 7.450579708745408e-9, + -0.000002585350102890516 + ], + "min": [ + -0.05204005911946297, + -5.96045985901128e-8, + -0.0000026747600259113824 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 3072, + "componentType": 5126, + "count": 48, + "max": [ + 0.04680187255144119, + 0.999507486820221, + 0.002036086050793529, + 0.09058715403079988 + ], + "min": [ + -0.093629889190197, + 0.9950671792030336, + -0.00258980062790215, + 0.0184526015073061 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 5184, + "componentType": 5126, + "count": 48, + "max": [ + 1.0000003576278689, + 1.000000238418579, + 1.0000009536743164 + ], + "min": [ + 0.9999998807907104, + 0.9999996423721313, + 1.000000238418579 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 960, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 5760, + "componentType": 5126, + "count": 48, + "max": [ + -0.00003742050103028305, + 0.08800023794174194, + -0.00005880460230400786 + ], + "min": [ + -0.000037621699448209256, + 0.08799994736909866, + -0.000059304802562110126 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 3840, + "componentType": 5126, + "count": 48, + "max": [ + 0.2951536476612091, + 0.9301012754440308, + -0.2815393805503845, + 0.3835828900337219 + ], + "min": [ + -0.13552021980285645, + 0.8065234422683716, + -0.4443180561065674, + -0.17752912640571597 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 6336, + "componentType": 5126, + "count": 48, + "max": [ + 1.0000005960464478, + 1.0000001192092896, + 1.0000003576278689 + ], + "min": [ + 0.9999999403953552, + 0.9999996423721313, + 0.9999998211860656 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 1152, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 6912, + "componentType": 5126, + "count": 48, + "max": [ + 0.013221889734268188, + 0.215499609708786, + 0.10933230072259904 + ], + "min": [ + 0.01322161965072155, + 0.2154994010925293, + 0.10933209955692293 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 4608, + "componentType": 5126, + "count": 48, + "max": [ + 0.023567700758576393, + 0.02101488783955574, + 0.176296666264534, + -0.971515953540802 + ], + "min": [ + -0.0574759915471077, + -0.18002526462078097, + -0.15063291788101196, + -0.998132348060608 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 7488, + "componentType": 5126, + "count": 48, + "max": [ + 0.9999998211860656, + 0.9999998211860656, + 0.9999999403953552 + ], + "min": [ + 0.9999991059303284, + 0.9999993443489076, + 0.9999994039535524 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 1344, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 8064, + "componentType": 5126, + "count": 48, + "max": [ + -0.09332455694675446, + 0.1430000960826874, + 0.07814794778823853 + ], + "min": [ + -0.09332473576068878, + 0.14299990236759189, + 0.07814773917198181 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 5376, + "componentType": 5126, + "count": 48, + "max": [ + 0.03372078761458397, + 0.0026474546175450087, + 0.207317128777504, + -0.9705979824066162 + ], + "min": [ + 0.006105833686888218, + -0.12215615808963776, + 0.003784916130825877, + -0.9994208216667176 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 8640, + "componentType": 5126, + "count": 48, + "max": [ + 1.0000007152557373, + 1.0000003576278689, + 1.0000008344650269 + ], + "min": [ + 1.0000001192092896, + 0.9999998211860656, + 1.000000238418579 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 1536, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 9216, + "componentType": 5126, + "count": 48, + "max": [ + -0.00003894419933203608, + -0.0879998430609703, + -0.00005919210161664523 + ], + "min": [ + -0.0000392795009247493, + -0.08800008893013, + -0.00005960090129519813 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 6144, + "componentType": 5126, + "count": 48, + "max": [ + 0.2377220243215561, + 0.942186713218689, + 0.37760788202285767, + 0.2007839232683182 + ], + "min": [ + -0.2700891792774201, + 0.8732703924179077, + 0.2710656225681305, + -0.2673804461956024 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 9792, + "componentType": 5126, + "count": 48, + "max": [ + 1.000000238418579, + 1.0000003576278689, + 1.0000001192092896 + ], + "min": [ + 0.999999701976776, + 0.9999997615814208, + 0.9999997615814208 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 1728, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 10368, + "componentType": 5126, + "count": 48, + "max": [ + -0.035546209663152695, + -0.21549880504608157, + 0.10423330217599867 + ], + "min": [ + -0.03554638102650643, + -0.21549910306930545, + 0.10423299670219421 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 6912, + "componentType": 5126, + "count": 48, + "max": [ + -0.00792065542191267, + 0.9315358996391296, + 0.0024673622101545334, + 0.41479358077049255 + ], + "min": [ + -0.15234939754009247, + 0.9063802361488342, + -0.08167753368616104, + 0.3280625641345978 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 10944, + "componentType": 5126, + "count": 48, + "max": [ + 1.0000005960464478, + 1.0000001192092896, + 1.000000238418579 + ], + "min": [ + 1, + 0.9999996423721313, + 0.9999996423721313 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 1920, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 11520, + "componentType": 5126, + "count": 48, + "max": [ + 0.03137049078941345, + -0.1430007964372635, + -0.11761150509119034 + ], + "min": [ + 0.03137030825018883, + -0.1430010050535202, + -0.11761169880628586 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 7680, + "componentType": 5126, + "count": 48, + "max": [ + 0.22148266434669495, + 0.3926030695438385, + 0.08952529728412628, + -0.9178923964500428 + ], + "min": [ + 0.055695075541734695, + 0.277910977602005, + -0.015314305201172829, + -0.9438881278038024 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 12096, + "componentType": 5126, + "count": 48, + "max": [ + 1.0000004768371584, + 1.0000004768371584, + 1.0000004768371584 + ], + "min": [ + 0.9999997615814208, + 0.9999997615814208, + 0.9999998807907104 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 2112, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 12672, + "componentType": 5126, + "count": 48, + "max": [ + 0.028520189225673676, + 0.06762184202671051, + -0.06295985728502274 + ], + "min": [ + 0.028520019724965096, + 0.06762173771858215, + -0.06296010315418243 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 8448, + "componentType": 5126, + "count": 48, + "max": [ + 0.013129070401191711, + 0.10440785437822342, + 0.004284336231648922, + -0.7728573679924011 + ], + "min": [ + -0.013805897906422617, + -0.6344362497329712, + -0.03212129324674606, + -0.9994977116584778 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 13248, + "componentType": 5126, + "count": 48, + "max": [ + 1.0000001192092896, + 1.0000004768371584, + 1.000000238418579 + ], + "min": [ + 0.9999995231628418, + 1, + 0.9999995827674866 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 2304, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 13824, + "componentType": 5126, + "count": 48, + "max": [ + 0.209164097905159, + 0.009055494330823421, + -0.16426970064640045 + ], + "min": [ + 0.20916390419006348, + 0.009055464528501034, + -0.1642698049545288 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 9216, + "componentType": 5126, + "count": 48, + "max": [ + 0.009955321438610554, + -0.2965533435344696, + 0.003957682754844427, + -0.1911347657442093 + ], + "min": [ + -0.00983923487365246, + -0.9813112020492554, + -0.02193812094628811, + -0.9549583792686462 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 14400, + "componentType": 5126, + "count": 48, + "max": [ + 1.000000238418579, + 0.999999463558197, + 1.0000001192092896 + ], + "min": [ + 0.999999463558197, + 0.999998927116394, + 0.9999993443489076 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 2496, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 14976, + "componentType": 5126, + "count": 48, + "max": [ + 0.2757900059223175, + 0.0013972820015624166, + 0.004122554790228605 + ], + "min": [ + 0.27578991651535034, + 0.0013972449814900756, + 0.004122436046600342 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 9984, + "componentType": 5126, + "count": 48, + "max": [ + 0.01264618057757616, + -0.8448027968406677, + 0.03285584971308708, + -0.15347692370414737 + ], + "min": [ + -0.045710742473602295, + -0.9879721403121948, + 0.007757793180644512, + -0.5345877408981323 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 15552, + "componentType": 5126, + "count": 48, + "max": [ + 1.0000008344650269, + 1.0000009536743164, + 1.0000004768371584 + ], + "min": [ + 1.000000238418579, + 1.0000003576278689, + 0.9999997615814208 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 2688, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 16128, + "componentType": 5126, + "count": 48, + "max": [ + -0.06558377295732498, + 0.00109061598777771, + 0.029291389510035515 + ], + "min": [ + -0.06558384746313095, + 0.001090570935048163, + 0.029291240498423576 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 10752, + "componentType": 5126, + "count": 48, + "max": [ + 0.022798636928200725, + 0.5332140922546387, + -0.003377946326509118, + -0.844382643699646 + ], + "min": [ + 0.007516560610383749, + 0.22626954317092896, + -0.04913739487528801, + -0.972984254360199 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 16704, + "componentType": 5126, + "count": 48, + "max": [ + 1.0000008344650269, + 1.0000003576278689, + 1.0000003576278689 + ], + "min": [ + 0.9999998211860656, + 0.999999701976776, + 0.9999995231628418 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 2880, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 17280, + "componentType": 5126, + "count": 48, + "max": [ + 0.028557300567626953, + -0.0684543326497078, + -0.06295845657587051 + ], + "min": [ + 0.028557060286402702, + -0.06845436990261078, + -0.0629587471485138 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 11520, + "componentType": 5126, + "count": 48, + "max": [ + 0.04037770628929138, + -0.2803998589515686, + 0.02151232957839966, + -0.32386553287506104 + ], + "min": [ + -0.009615562856197357, + -0.9458208084106444, + -0.006491139996796846, + -0.9590301513671876 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 17856, + "componentType": 5126, + "count": 48, + "max": [ + 1.000000238418579, + 1.0000005960464478, + 1.0000005960464478 + ], + "min": [ + 0.9999994039535524, + 0.9999999403953552, + 0.9999998211860656 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 3072, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 18432, + "componentType": 5126, + "count": 48, + "max": [ + 0.2608909010887146, + -0.00902603566646576, + 0.05167100951075554 + ], + "min": [ + 0.2608906924724579, + -0.009026064537465572, + 0.05167080089449883 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 12288, + "componentType": 5126, + "count": 48, + "max": [ + 0.02468797937035561, + 0.19154119491577148, + 0.017835097387433052, + -0.6250466108322144 + ], + "min": [ + -0.013421673327684404, + -0.7804162502288818, + -0.031287722289562225, + -0.9999792575836182 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 19008, + "componentType": 5126, + "count": 48, + "max": [ + 1.0000003576278689, + 1.0000007152557373, + 1.000001072883606 + ], + "min": [ + 0.999999463558197, + 1, + 0.999999701976776 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 3264, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 19584, + "componentType": 5126, + "count": 48, + "max": [ + 0.2754603922367096, + -0.0014316890155896544, + -0.014104750007390976 + ], + "min": [ + 0.27546021342277527, + -0.0014317409368231893, + -0.014104840345680714 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 13056, + "componentType": 5126, + "count": 48, + "max": [ + 0.022092316299676895, + 0.9990847110748292, + 0.04779285565018654, + 0.4428757429122925 + ], + "min": [ + -0.001671039150096476, + 0.8965795040130615, + 0.002310338197275996, + 0.0384783074259758 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 20160, + "componentType": 5126, + "count": 48, + "max": [ + 0.9999999403953552, + 0.9999996423721313, + 1.000000238418579 + ], + "min": [ + 0.9999994039535524, + 0.9999991655349731, + 0.9999996423721313 + ], + "type": "VEC3" + }, + { + "bufferView": 4, + "byteOffset": 3456, + "componentType": 5126, + "count": 48, + "max": [ + 2 + ], + "min": [ + 0.04166661947965622 + ], + "type": "SCALAR" + }, + { + "bufferView": 5, + "byteOffset": 20736, + "componentType": 5126, + "count": 48, + "max": [ + -0.06681966781616211, + -0.0010721459984779358, + 0.026351390406489372 + ], + "min": [ + -0.06681978702545166, + -0.001072190934792161, + 0.02635126002132893 + ], + "type": "VEC3" + }, + { + "bufferView": 6, + "byteOffset": 13824, + "componentType": 5126, + "count": 48, + "max": [ + 0.003402489935979247, + 0.4966025054454804, + 0.1101396307349205, + -0.8675833940505981 + ], + "min": [ + -0.027623889967799187, + 0.26874634623527527, + -0.02591408602893353, + -0.9565747380256652 + ], + "type": "VEC4" + }, + { + "bufferView": 5, + "byteOffset": 21312, + "componentType": 5126, + "count": 48, + "max": [ + 1.0000004768371584, + 0.9999998211860656, + 0.9999994039535524 + ], + "min": [ + 0.9999995231628418, + 0.999999225139618, + 0.9999986886978148 + ], + "type": "VEC3" + }, + { + "bufferView": 7, + "byteOffset": 0, + "componentType": 5126, + "count": 19, + "max": [ + 0.9971418380737304, + -4.371139894487897e-8, + 0.9996265172958374, + 0, + 4.3586464215650273e-8, + 1, + 4.3695074225524884e-8, + 0, + 0.9999366402626038, + 0, + 0.9971418380737304, + 0, + 1.1374080181121828, + 0.44450080394744873, + 1.0739599466323853, + 1 + ], + "min": [ + -0.9999089241027832, + -4.371139894487897e-8, + -0.9999366402626038, + 0, + -4.3707416352845037e-8, + 1, + -4.37086278282095e-8, + 0, + -0.9996265172958374, + 0, + -0.9999089241027832, + 0, + -1.189831018447876, + -0.45450031757354736, + -1.058603048324585, + 1 + ], + "type": "MAT4" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0, + "texCoord": 0 + }, + "metallicFactor": 0, + "baseColorFactor": [ + 1, + 1, + 1, + 1 + ], + "roughnessFactor": 1 + }, + "emissiveFactor": [ + 0, + 0, + 0 + ], + "name": "Cesium_Man-effect", + "alphaMode": "OPAQUE", + "doubleSided": false + } + ], + "textures": [ + { + "sampler": 0, + "source": 0 + } + ], + "images": [ + { + "uri": "CesiumMan_img0.jpg" + } + ], + "samplers": [ + { + "magFilter": 9729, + "minFilter": 9986, + "wrapS": 10497, + "wrapT": 10497 + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 28032, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 28032, + "byteLength": 52368, + "byteStride": 8, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 80400, + "byteLength": 78552, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 158952, + "byteLength": 52368, + "byteStride": 16, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 211320, + "byteLength": 3648 + }, + { + "buffer": 0, + "byteOffset": 214968, + "byteLength": 21888 + }, + { + "buffer": 0, + "byteOffset": 236856, + "byteLength": 14592 + }, + { + "buffer": 0, + "byteOffset": 251448, + "byteLength": 1216 + } + ], + "buffers": [ + { + "uri": "CesiumMan_data.bin", + "byteLength": 252664 + } + ] +} \ No newline at end of file diff --git a/sample/gltf/CesiumMan/CesiumMan_data.bin b/sample/gltf/CesiumMan/CesiumMan_data.bin new file mode 100644 index 000000000..d78b75cfb Binary files /dev/null and b/sample/gltf/CesiumMan/CesiumMan_data.bin differ diff --git a/sample/gltf/CesiumMan/CesiumMan_img0.jpg b/sample/gltf/CesiumMan/CesiumMan_img0.jpg new file mode 100644 index 000000000..ab1b72445 Binary files /dev/null and b/sample/gltf/CesiumMan/CesiumMan_img0.jpg differ diff --git a/sample/gltf/CesiumMan/README.md b/sample/gltf/CesiumMan/README.md new file mode 100644 index 000000000..20bd6ed63 --- /dev/null +++ b/sample/gltf/CesiumMan/README.md @@ -0,0 +1,10 @@ +# Cesium Man +## Screenshot + +![screenshot](screenshot/screenshot.gif) + +## License Information + +Donated by Cesium for glTF testing. Please follow the [Cesium Trademark Terms and Conditions](https://github.com/AnalyticalGraphicsInc/cesium/wiki/CesiumTrademark.pdf). + +This model is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/). diff --git a/sample/gltf/CesiumMilkTruck/CesiumMilkTruck.gltf b/sample/gltf/CesiumMilkTruck/CesiumMilkTruck.gltf new file mode 100644 index 000000000..0b46a38c7 --- /dev/null +++ b/sample/gltf/CesiumMilkTruck/CesiumMilkTruck.gltf @@ -0,0 +1,489 @@ +{ + "asset": { + "generator": "Khronos glTF Blender I/O v1.0.5", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "name": "Scene", + "nodes": [ + 5 + ] + } + ], + "nodes": [ + { + "mesh": 0, + "name": "Wheels", + "rotation": [ + 0, + 0.08848588913679123, + 0, + -0.9960774183273315 + ] + }, + { + "children": [ + 0 + ], + "name": "Node", + "translation": [ + 1.432669997215271, + 0, + -0.4277220070362091 + ] + }, + { + "mesh": 0, + "name": "Wheels.001", + "rotation": [ + 0, + 0.08848588913679123, + 0, + -0.9960774183273315 + ] + }, + { + "children": [ + 2 + ], + "name": "Node.001", + "translation": [ + -1.352329969406128, + 0, + -0.4277220070362091 + ] + }, + { + "children": [ + 1, + 3 + ], + "mesh": 1, + "name": "Cesium_Milk_Truck" + }, + { + "children": [ + 4 + ], + "name": "Yup2Zup", + "rotation": [ + 0.4999999701976776, + -0.5, + 0.5, + 0.4999999701976776 + ] + } + ], + "animations": [ + { + "channels": [ + { + "sampler": 0, + "target": { + "node": 0, + "path": "rotation" + } + }, + { + "sampler": 1, + "target": { + "node": 2, + "path": "rotation" + } + } + ], + "name": "Wheels", + "samplers": [ + { + "input": 16, + "interpolation": "LINEAR", + "output": 17 + }, + { + "input": 16, + "interpolation": "LINEAR", + "output": 18 + } + ] + } + ], + "materials": [ + { + "name": "wheels", + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0, + "texCoord": 0 + }, + "metallicFactor": 0, + "roughnessFactor": 1 + } + }, + { + "name": "truck", + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 1, + "texCoord": 0 + }, + "metallicFactor": 0, + "roughnessFactor": 1 + } + }, + { + "name": "glass", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0, + 0.04050629958510399, + 0.021240700036287308, + 1 + ], + "metallicFactor": 0, + "roughnessFactor": 1 + } + }, + { + "name": "window_trim", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.06400000303983688, + 0.06400000303983688, + 0.06400000303983688, + 1 + ], + "metallicFactor": 0, + "roughnessFactor": 1 + } + } + ], + "meshes": [ + { + "name": "Wheels", + "primitives": [ + { + "attributes": { + "POSITION": 0, + "NORMAL": 1, + "TEXCOORD_0": 2 + }, + "indices": 3, + "material": 0 + } + ] + }, + { + "name": "Cesium_Milk_Truck", + "primitives": [ + { + "attributes": { + "POSITION": 4, + "NORMAL": 5, + "TEXCOORD_0": 6 + }, + "indices": 7, + "material": 1 + }, + { + "attributes": { + "POSITION": 8, + "NORMAL": 9, + "TEXCOORD_0": 10 + }, + "indices": 11, + "material": 2 + }, + { + "attributes": { + "POSITION": 12, + "NORMAL": 13, + "TEXCOORD_0": 14 + }, + "indices": 15, + "material": 3 + } + ] + } + ], + "textures": [ + { + "source": 0 + }, + { + "source": 0 + } + ], + "images": [ + { + "name": "CesiumMilkTruck.jpg", + "uri": "CesiumMilkTruck.jpg" + } + ], + "accessors": [ + { + "bufferView": 0, + "componentType": 5126, + "count": 828, + "max": [ + 0.4277999997138977, + 1.0579999685287476, + 0.4277999997138977 + ], + "min": [ + -0.4277999997138977, + -1.0579999685287476, + -0.4277999997138977 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "componentType": 5126, + "count": 828, + "type": "VEC3" + }, + { + "bufferView": 2, + "componentType": 5126, + "count": 828, + "type": "VEC2" + }, + { + "bufferView": 3, + "componentType": 5123, + "count": 2304, + "type": "SCALAR" + }, + { + "bufferView": 4, + "componentType": 5126, + "count": 2366, + "max": [ + 2.437999963760376, + 1.3960000276565552, + -0.2667999863624573 + ], + "min": [ + -2.430910110473633, + -1.3960000276565552, + -2.5843698978424072 + ], + "type": "VEC3" + }, + { + "bufferView": 5, + "componentType": 5126, + "count": 2366, + "type": "VEC3" + }, + { + "bufferView": 6, + "componentType": 5126, + "count": 2366, + "type": "VEC2" + }, + { + "bufferView": 7, + "componentType": 5123, + "count": 5232, + "type": "SCALAR" + }, + { + "bufferView": 8, + "componentType": 5126, + "count": 151, + "max": [ + 1.6011799573898315, + 1.3960000276565552, + -1.631850004196167 + ], + "min": [ + 0.22885000705718994, + -1.3960000276565552, + -2.3545401096343994 + ], + "type": "VEC3" + }, + { + "bufferView": 9, + "componentType": 5126, + "count": 151, + "type": "VEC3" + }, + { + "bufferView": 10, + "componentType": 5126, + "count": 151, + "type": "VEC2" + }, + { + "bufferView": 11, + "componentType": 5123, + "count": 168, + "type": "SCALAR" + }, + { + "bufferView": 12, + "componentType": 5126, + "count": 650, + "max": [ + 1.62267005443573, + 1.100000023841858, + -1.5961999893188477 + ], + "min": [ + 0.1932000070810318, + -1.1100000143051147, + -2.3919999599456787 + ], + "type": "VEC3" + }, + { + "bufferView": 13, + "componentType": 5126, + "count": 650, + "type": "VEC3" + }, + { + "bufferView": 14, + "componentType": 5126, + "count": 650, + "type": "VEC2" + }, + { + "bufferView": 15, + "componentType": 5123, + "count": 864, + "type": "SCALAR" + }, + { + "bufferView": 16, + "componentType": 5126, + "count": 31, + "max": [ + 1.25 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 17, + "componentType": 5126, + "count": 31, + "type": "VEC4" + }, + { + "bufferView": 18, + "componentType": 5126, + "count": 31, + "type": "VEC4" + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteLength": 9936, + "byteOffset": 0 + }, + { + "buffer": 0, + "byteLength": 9936, + "byteOffset": 9936 + }, + { + "buffer": 0, + "byteLength": 6624, + "byteOffset": 19872 + }, + { + "buffer": 0, + "byteLength": 4608, + "byteOffset": 26496 + }, + { + "buffer": 0, + "byteLength": 28392, + "byteOffset": 31104 + }, + { + "buffer": 0, + "byteLength": 28392, + "byteOffset": 59496 + }, + { + "buffer": 0, + "byteLength": 18928, + "byteOffset": 87888 + }, + { + "buffer": 0, + "byteLength": 10464, + "byteOffset": 106816 + }, + { + "buffer": 0, + "byteLength": 1812, + "byteOffset": 117280 + }, + { + "buffer": 0, + "byteLength": 1812, + "byteOffset": 119092 + }, + { + "buffer": 0, + "byteLength": 1208, + "byteOffset": 120904 + }, + { + "buffer": 0, + "byteLength": 336, + "byteOffset": 122112 + }, + { + "buffer": 0, + "byteLength": 7800, + "byteOffset": 122448 + }, + { + "buffer": 0, + "byteLength": 7800, + "byteOffset": 130248 + }, + { + "buffer": 0, + "byteLength": 5200, + "byteOffset": 138048 + }, + { + "buffer": 0, + "byteLength": 1728, + "byteOffset": 143248 + }, + { + "buffer": 0, + "byteLength": 124, + "byteOffset": 144976 + }, + { + "buffer": 0, + "byteLength": 496, + "byteOffset": 145100 + }, + { + "buffer": 0, + "byteLength": 496, + "byteOffset": 145596 + } + ], + "buffers": [ + { + "uri": "CesiumMilkTruck_data.bin", + "byteLength": 146092 + } + ] +} diff --git a/sample/gltf/CesiumMilkTruck/CesiumMilkTruck.jpg b/sample/gltf/CesiumMilkTruck/CesiumMilkTruck.jpg new file mode 100644 index 000000000..0bebaadc1 Binary files /dev/null and b/sample/gltf/CesiumMilkTruck/CesiumMilkTruck.jpg differ diff --git a/sample/gltf/CesiumMilkTruck/CesiumMilkTruck_data.bin b/sample/gltf/CesiumMilkTruck/CesiumMilkTruck_data.bin new file mode 100644 index 000000000..51e364673 Binary files /dev/null and b/sample/gltf/CesiumMilkTruck/CesiumMilkTruck_data.bin differ diff --git a/sample/gltf/CesiumMilkTruck/README.md b/sample/gltf/CesiumMilkTruck/README.md new file mode 100644 index 000000000..0c6bafdda --- /dev/null +++ b/sample/gltf/CesiumMilkTruck/README.md @@ -0,0 +1,10 @@ +# Cesium Milk Truck +## Screenshot + +![screenshot](screenshot/screenshot.gif) + +## License Information + +Donated by Cesium for glTF testing. Please follow the [Cesium Trademark Terms and Conditions](https://github.com/AnalyticalGraphicsInc/cesium/wiki/CesiumTrademark.pdf). + +This model is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/). diff --git a/sample/gltf/DamagedHelmet/DamagedHelmet.bin b/sample/gltf/DamagedHelmet/DamagedHelmet.bin new file mode 100644 index 000000000..662eacc1d Binary files /dev/null and b/sample/gltf/DamagedHelmet/DamagedHelmet.bin differ diff --git a/sample/gltf/DamagedHelmet/DamagedHelmet.gltf b/sample/gltf/DamagedHelmet/DamagedHelmet.gltf new file mode 100644 index 000000000..c61145a01 --- /dev/null +++ b/sample/gltf/DamagedHelmet/DamagedHelmet.gltf @@ -0,0 +1,204 @@ +{ + "accessors" : [ + { + "bufferView" : 0, + "componentType" : 5123, + "count" : 46356, + "max" : [ + 14555 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 1, + "componentType" : 5126, + "count" : 14556, + "max" : [ + 0.9424954056739807, + 0.8128451108932495, + 0.900973916053772 + ], + "min" : [ + -0.9474585652351379, + -1.18715500831604, + -0.9009949564933777 + ], + "type" : "VEC3" + }, + { + "bufferView" : 2, + "componentType" : 5126, + "count" : 14556, + "max" : [ + 1.0, + 1.0, + 1.0 + ], + "min" : [ + -1.0, + -1.0, + -1.0 + ], + "type" : "VEC3" + }, + { + "bufferView" : 3, + "componentType" : 5126, + "count" : 14556, + "max" : [ + 0.9999759793281555, + 1.998665988445282 + ], + "min" : [ + 0.002448640065267682, + 1.0005531199858524 + ], + "type" : "VEC2" + } + ], + "asset" : { + "generator" : "Khronos Blender glTF 2.0 exporter", + "version" : "2.0" + }, + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 92712, + "byteOffset" : 0, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 174672, + "byteOffset" : 92712, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 174672, + "byteOffset" : 267384, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 116448, + "byteOffset" : 442056, + "target" : 34962 + } + ], + "buffers" : [ + { + "byteLength" : 558504, + "uri" : "DamagedHelmet.bin" + } + ], + "images" : [ + { + "uri" : "Default_albedo.jpg" + }, + { + "uri" : "Default_metalRoughness.jpg" + }, + { + "uri" : "Default_emissive.jpg" + }, + { + "uri" : "Default_AO.jpg" + }, + { + "uri" : "Default_normal.jpg" + } + ], + "materials" : [ + { + "emissiveFactor" : [ + 1.0, + 1.0, + 1.0 + ], + "emissiveTexture" : { + "index" : 2 + }, + "name" : "Material_MR", + "normalTexture" : { + "index" : 4 + }, + "occlusionTexture" : { + "index" : 3 + }, + "pbrMetallicRoughness" : { + "baseColorTexture" : { + "index" : 0 + }, + "metallicRoughnessTexture" : { + "index" : 1 + } + } + } + ], + "meshes" : [ + { + "name" : "mesh_helmet_LP_13930damagedHelmet", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 2, + "POSITION" : 1, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0 + } + ] + } + ], + "nodes" : [ + { + "mesh" : 0, + "name" : "node_damagedHelmet_-6514", + "rotation" : [ + 0.7071068286895752, + 0.0, + -0.0, + 0.7071068286895752 + ] + } + ], + "samplers" : [ + {} + ], + "scene" : 0, + "scenes" : [ + { + "name" : "Scene", + "nodes" : [ + 0 + ] + } + ], + "textures" : [ + { + "sampler" : 0, + "source" : 0 + }, + { + "sampler" : 0, + "source" : 1 + }, + { + "sampler" : 0, + "source" : 2 + }, + { + "sampler" : 0, + "source" : 3 + }, + { + "sampler" : 0, + "source" : 4 + } + ] +} diff --git a/sample/gltf/DamagedHelmet/Default_AO.jpg b/sample/gltf/DamagedHelmet/Default_AO.jpg new file mode 100644 index 000000000..419f62840 Binary files /dev/null and b/sample/gltf/DamagedHelmet/Default_AO.jpg differ diff --git a/sample/gltf/DamagedHelmet/Default_albedo.jpg b/sample/gltf/DamagedHelmet/Default_albedo.jpg new file mode 100644 index 000000000..15d64855c Binary files /dev/null and b/sample/gltf/DamagedHelmet/Default_albedo.jpg differ diff --git a/sample/gltf/DamagedHelmet/Default_emissive.jpg b/sample/gltf/DamagedHelmet/Default_emissive.jpg new file mode 100644 index 000000000..2de59e897 Binary files /dev/null and b/sample/gltf/DamagedHelmet/Default_emissive.jpg differ diff --git a/sample/gltf/DamagedHelmet/Default_metalRoughness.jpg b/sample/gltf/DamagedHelmet/Default_metalRoughness.jpg new file mode 100644 index 000000000..04874cb6e Binary files /dev/null and b/sample/gltf/DamagedHelmet/Default_metalRoughness.jpg differ diff --git a/sample/gltf/DamagedHelmet/Default_normal.jpg b/sample/gltf/DamagedHelmet/Default_normal.jpg new file mode 100644 index 000000000..94ca20a2d Binary files /dev/null and b/sample/gltf/DamagedHelmet/Default_normal.jpg differ diff --git a/sample/gltf/DamagedHelmet/README.md b/sample/gltf/DamagedHelmet/README.md new file mode 100644 index 000000000..7c75445de --- /dev/null +++ b/sample/gltf/DamagedHelmet/README.md @@ -0,0 +1,15 @@ +# Damaged Helmet + +## Screenshot + +![screenshot](screenshot/screenshot.png) + +## License Information + +Battle Damaged Sci-fi Helmet - PBR by [theblueturtle_](https://sketchfab.com/theblueturtle_), published under a Creative Commons Attribution-NonCommercial license + +https://sketchfab.com/models/b81008d513954189a063ff901f7abfe4 + +## Modifications + +The original model was built on an early draft of glTF 2.0 that did not become final. This new model has been imported and re-exported from Blender to bring it into alignment with the final release glTF 2.0 specification. diff --git a/sample/gltf/Duck/Duck.gltf b/sample/gltf/Duck/Duck.gltf new file mode 100644 index 000000000..b80c842ce --- /dev/null +++ b/sample/gltf/Duck/Duck.gltf @@ -0,0 +1,219 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 2, + 1 + ], + "matrix": [ + 0.009999999776482582, + 0.0, + 0.0, + 0.0, + 0.0, + 0.009999999776482582, + 0.0, + 0.0, + 0.0, + 0.0, + 0.009999999776482582, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "matrix": [ + -0.7289686799049377, + 0.0, + -0.6845470666885376, + 0.0, + -0.4252049028873444, + 0.7836934328079224, + 0.4527972936630249, + 0.0, + 0.5364750623703003, + 0.6211478114128113, + -0.571287989616394, + 0.0, + 400.1130065917969, + 463.2640075683594, + -431.0780334472656, + 1.0 + ], + "camera": 0 + }, + { + "mesh": 0 + } + ], + "cameras": [ + { + "perspective": { + "aspectRatio": 1.5, + "yfov": 0.6605925559997559, + "zfar": 10000.0, + "znear": 1.0 + }, + "type": "perspective" + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "LOD3spShape" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 12636, + "max": [ + 2398 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 2399, + "max": [ + 0.9995989799499512, + 0.999580979347229, + 0.9984359741210938 + ], + "min": [ + -0.9990839958190918, + -1.0, + -0.9998319745063782 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 28788, + "componentType": 5126, + "count": 2399, + "max": [ + 96.17990112304688, + 163.97000122070313, + 53.92519760131836 + ], + "min": [ + -69.29850006103516, + 9.929369926452637, + -61.32819747924805 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 2399, + "max": [ + 0.9833459854125976, + 0.9800369739532472 + ], + "min": [ + 0.026409000158309938, + 0.01996302604675293 + ], + "type": "VEC2" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0 + }, + "metallicFactor": 0.0 + }, + "emissiveFactor": [ + 0.0, + 0.0, + 0.0 + ], + "name": "blinn3-fx" + } + ], + "textures": [ + { + "sampler": 0, + "source": 0 + } + ], + "images": [ + { + "uri": "DuckCM.png" + } + ], + "samplers": [ + { + "magFilter": 9729, + "minFilter": 9986, + "wrapS": 10497, + "wrapT": 10497 + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 76768, + "byteLength": 25272, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 57576, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 57576, + "byteLength": 19192, + "byteStride": 8, + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 102040, + "uri": "Duck0.bin" + } + ] +} diff --git a/sample/gltf/Duck/Duck0.bin b/sample/gltf/Duck/Duck0.bin new file mode 100644 index 000000000..5f01f88ac Binary files /dev/null and b/sample/gltf/Duck/Duck0.bin differ diff --git a/sample/gltf/Duck/DuckCM.png b/sample/gltf/Duck/DuckCM.png new file mode 100644 index 000000000..9fa2dd4cc Binary files /dev/null and b/sample/gltf/Duck/DuckCM.png differ diff --git a/sample/gltf/Duck/README.md b/sample/gltf/Duck/README.md new file mode 100644 index 000000000..9cbe72301 --- /dev/null +++ b/sample/gltf/Duck/README.md @@ -0,0 +1,14 @@ +# Duck +## Screenshot + +![screenshot](screenshot/screenshot.png) + +## License Information + +Copyright 2006 Sony Computer Entertainment Inc. + +Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: + +https://web.archive.org/web/20160320123355/http://research.scea.com/scea_shared_source_license.html + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/scripts/Linux/0_setup_env.sh b/scripts/Linux/0_setup_env.sh new file mode 100644 index 000000000..f61a4bb0d --- /dev/null +++ b/scripts/Linux/0_setup_env.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# this is a script shell sets up an ubuntu (18.04, 20.04 and 22.04) environment where +# MeshLab can be compiled. +# +# Run this script if you never installed any of the MeshLab dependencies. + +DONT_INSTALL_QT=false +DONT_INSTALL_CGAL_BOOST=false + +#checking for parameters +for i in "$@" +do +case $i in + --dont_install_qt) + DONT_INSTALL_QT=true + shift # past argument=value + ;; + --dont_install_cgal_and_boost) + DONT_INSTALL_CGAL_BOOST=true + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +sudo apt-get update +echo "=== installing mesa packages..." +sudo apt-get install -y mesa-common-dev libglu1-mesa-dev + +echo "=== installing cmake, patchelf, gmp, mpfr and xcerces-c..." +sudo apt-get install -y cmake ninja-build patchelf libgmp-dev libmpfr-dev libxerces-c-dev + +if [ "$DONT_INSTALL_QT" = false ] ; then + echo "=== installing qt packages..." + sudo apt-get install -y qt5-default qttools5-dev-tools qtdeclarative5-dev +else + echo "=== jumping installation of qt packages..." +fi + +# libraries that qt requires in any case +echo "=== intalling libraries required for qt deployment..." +sudo apt-get install -y libxkbcommon-x11-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-render-util0-dev libxcb-xinerama0-dev + +# possibility to use always system libraries starting from ubuntu 20.04, since cgal is header only +if [ "$DONT_INSTALL_CGAL_BOOST" = false ] ; then + echo "=== installing cgal and boost..." + sudo apt-get install -y libcgal-dev libboost-all-dev +else + echo "=== jumping installation of cgal and boost packages..." +fi diff --git a/scripts/Linux/0_setup_env_ubuntu.sh b/scripts/Linux/0_setup_env_ubuntu.sh deleted file mode 100644 index 080a136ae..000000000 --- a/scripts/Linux/0_setup_env_ubuntu.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -# this is a script shell sets up an ubuntu (16.04, 18.04, 20.04) environment where -# MeshLab can be compiled. -# -# Run this script if you never installed any of the MeshLab dependencies. - -sudo apt-get update -sudo apt-get install -y qt5-default qttools5-dev-tools qtdeclarative5-dev -sudo apt-get install -y mesa-common-dev libglu1-mesa-dev libglew-dev lib3ds-dev libeigen3-dev -sudo apt-get install -y libopenctm-dev libgmp-dev libqhull-dev patchelf cmake diff --git a/scripts/Linux/1_build.sh b/scripts/Linux/1_build.sh index 3c3e685f2..d85b751fb 100644 --- a/scripts/Linux/1_build.sh +++ b/scripts/Linux/1_build.sh @@ -1,47 +1,50 @@ #!/bin/bash -# this is a script shell for compiling meshlab in a Linux environment. -# Requires a Qt environment which is set-up properly, and an accessible -# cmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src/build -# directory, and installed in $BUILD_PATH/../install. -# -# You can give as argument the BUILD_PATH and the INSTALL_PATH in the -# following way: -# sh linux_build.sh --build_path=/path/to/build --install_path=/path/to/install -# -b and -i arguments are also supported. #default paths wrt the script folder SCRIPTS_PATH="$(dirname "$(realpath "$0")")" -SOURCE_PATH=$SCRIPTS_PATH/../../src +SOURCE_PATH=$SCRIPTS_PATH/../.. BUILD_PATH=$SOURCE_PATH/build INSTALL_PATH=$SOURCE_PATH/install/usr/ -CORES="-j4" DOUBLE_PRECISION_OPTION="" +NIGHTLY_OPTION="" +QT_DIR="" +CCACHE="" #check parameters for i in "$@" do case $i in + -s=*|--source_path=*) + SOURCE_PATH="${i#*=}" + shift # past argument=value + ;; -b=*|--build_path=*) - BUILD_PATH="${i#*=}" - shift # past argument=value - ;; + BUILD_PATH="${i#*=}" + shift # past argument=value + ;; -i=*|--install_path=*) - INSTALL_PATH="${i#*=}"/usr/ - shift # past argument=value - ;; - -j*) - CORES=$i - shift # past argument=value - ;; - --double_precision) - DOUBLE_PRECISION_OPTION="-DBUILD_WITH_DOUBLE_SCALAR=ON" - shift # past argument=value - ;; + INSTALL_PATH="${i#*=}"/usr/ + shift # past argument=value + ;; + -d|--double_precision) + DOUBLE_PRECISION_OPTION="-DMESHLAB_BUILD_WITH_DOUBLE_SCALAR=ON" + shift # past argument=value + ;; + -n|--nightly) + NIGHTLY_OPTION="-DMESHLAB_IS_NIGHTLY_VERSION=ON" + shift # past argument=value + ;; + -qt=*|--qt_dir=*) + QT_DIR=${i#*=} + shift # past argument=value + ;; + --ccache) + CCACHE="-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" + shift # past argument=value + ;; *) - # unknown option - ;; + # unknown option + ;; esac done @@ -60,7 +63,13 @@ fi BUILD_PATH=$(realpath $BUILD_PATH) INSTALL_PATH=$(realpath $INSTALL_PATH) +if [ ! -z "$QT_DIR" ] +then + export Qt5_DIR=$QT_DIR +fi + cd $BUILD_PATH -cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH $DOUBLE_PRECISION_OPTION $SOURCE_PATH -make $CORES -make install +export NINJA_STATUS="[%p (%f/%t) ] " +cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH $CCACHE $DOUBLE_PRECISION_OPTION $NIGHTLY_OPTION $SOURCE_PATH +ninja +ninja install diff --git a/scripts/Linux/2_deploy.sh b/scripts/Linux/2_deploy.sh index aa89e5100..56e788482 100644 --- a/scripts/Linux/2_deploy.sh +++ b/scripts/Linux/2_deploy.sh @@ -1,48 +1,47 @@ #!/bin/bash -# This is a script shell for deploying a meshlab-portable folder. -# Requires a properly built MeshLab (see 1_build.sh). -# -# This script can be run only in the oldest supported linux distro -# due to linuxdeployqt tool choice (see https://github.com/probonopd/linuxdeployqt/issues/340). -# -# Without given arguments, the folder that will be deployed is meshlab/src/install, which -# should be the path where MeshLab has been installed (default output of 1_build.sh). -# -# You can give as argument the path where you installed MeshLab. SCRIPTS_PATH="$(dirname "$(realpath "$0")")" -INSTALL_PATH=$SCRIPTS_PATH/../../src/install +INSTALL_PATH=$SCRIPTS_PATH/../../install +QT_DIR_OPTION="" +PACKAGES_PATH=$SCRIPTS_PATH/../../packages #checking for parameters for i in "$@" do case $i in -i=*|--install_path=*) - INSTALL_PATH="${i#*=}" - shift # past argument=value - ;; + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -qt=*|--qt_dir=*) + QT_DIR_OPTION=-qt=${i#*=} + shift # past argument=value + ;; + -p=*|--packages_path=*) + PACKAGES_PATH="${i#*=}" + shift # past argument=value + ;; *) - # unknown option - ;; + # unknown option + ;; esac done -bash $SCRIPTS_PATH/resources/make_bundle.sh $INSTALL_PATH +# The script will terminate after the first line that fails +set -e -export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$INSTALL_PATH/usr/lib/meshlab -$SCRIPTS_PATH/resources/linuxdeployqt $INSTALL_PATH/usr/share/applications/meshlab.desktop \ - -bundle-non-qt-libs \ - -executable=$INSTALL_PATH/usr/lib/meshlab/plugins/libfilter_sketchfab.so \ - -executable=$INSTALL_PATH/usr/lib/meshlab/plugins/libio_3ds.so \ - -executable=$INSTALL_PATH/usr/lib/meshlab/plugins/libio_ctm.so +bash $SCRIPTS_PATH/internal/2a_make_bundle.sh -i=$INSTALL_PATH +echo "======= Bundle created =======" -chmod +x $INSTALL_PATH/usr/bin/meshlab -rm $INSTALL_PATH/AppRun +bash $SCRIPTS_PATH/internal/2b_deb.sh -i=$INSTALL_PATH -p=$PACKAGES_PATH -cp $SCRIPTS_PATH/resources/AppRunMeshLab $INSTALL_PATH/ -mv $INSTALL_PATH/AppRunMeshLab $INSTALL_PATH/AppRun -chmod +x $INSTALL_PATH/AppRun +echo "======= Deb Created =======" -#at this point, distrib folder contains all the files necessary to execute meshlab -echo "$INSTALL_PATH is now a self contained meshlab application" +bash $SCRIPTS_PATH/internal/2c_portable.sh -i=$INSTALL_PATH $QT_DIR_OPTION + +echo "======= Portable Version Created =======" + +bash $SCRIPTS_PATH/internal/2d_appimage.sh -i=$INSTALL_PATH -p=$PACKAGES_PATH + +echo "======= AppImage Created =======" diff --git a/scripts/Linux/3_appimage.sh b/scripts/Linux/3_appimage.sh deleted file mode 100644 index c4155f16e..000000000 --- a/scripts/Linux/3_appimage.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -# This is a script shell for setting up the AppImage bundle for linux -# Requires a properly built meshlab, boundled and deployed (see linux_deploy.sh) -# inside the directory given as argument -# -# Without given arguments, MeshLab AppImage will be placed in the src -# directory. -# -# You can give as argument the path of the bundle (default is src/install), -# and the AppImage will be placed in the parent directory (src) - -SCRIPTS_PATH="$(dirname "$(realpath "$0")")" -INSTALL_PATH=$SCRIPTS_PATH/../../src/install -ML_VERSION=$(cat $SCRIPTS_PATH/../../ML_VERSION) - - -#checking for parameters -for i in "$@" -do -case $i in - -i=*|--install_path=*) - INSTALL_PATH="${i#*=}" - shift # past argument=value - ;; - --double_precision) - ML_VERSION=${ML_VERSION}d - shift # past argument=value - ;; - *) - # unknown option - ;; -esac -done - -PARENT_NAME="$(dirname $INSTALL_PATH)" - -export VERSION=$ML_VERSION - -$SCRIPTS_PATH/resources/appimagetool $INSTALL_PATH -mv MeshLab-$VERSION*.AppImage $PARENT_NAME/MeshLab$VERSION-linux.AppImage - -#at this point, distrib folder contains all the files necessary to execute meshlab -echo MeshLab$VERSION-linux.AppImage generated diff --git a/scripts/Linux/README.md b/scripts/Linux/README.md index e83989bab..fe6ea23d4 100644 --- a/scripts/Linux/README.md +++ b/scripts/Linux/README.md @@ -1,39 +1,40 @@ # Linux Scripts -This folder contains a series of scripts to build and deploy MeshLab under a Linux environment (tested on Ubuntu 16.04, 18.04 and 20.04). +This folder contains a series of scripts to build and deploy MeshLab under a Linux environment (tested on Ubuntu 18.04, 20.04 and 22.04). -* `0_setup_env_ubuntu.sh`: this script installs all the required dependencies that are necessary to build MeshLab in an Ubuntu distro (tested in 16.04, 18.04 and 20.04). If you never installed Qt and other libraries, you should run it before any other script; -* `1_build.sh`: this script builds MeshLab in a Linux environment: - * it requires a properly set Qt environment (see `0_setup_env_ubuntu.sh`); - * takes as arguments: - * the build directory (default: `src/build`): `--build_path=path/to/build` - * the install directory (default: `src/install`): `--install_path=path/to/install` - * the number of cores used to build MeshLab (default: `-j4`)` - * the possibility to build MeshLab with double precision scalar: `--double_precision` -* `2_deploy.sh`: this script makes the given path a portable version of MeshLab. Takes as arguments: - * the path where the output install path of the `1_build.sh` script is placed (default: `src/install`): `--install_path=path/to/install` -* `3_appimage.sh`: this script computes, starting from the portable folder of MeshLab, an [AppImage](https://appimage.org/) that can be run in a Linux Environment without dependencies. Takes as arguments: - * the path where the output install path of the `2_deploy.sh` script is placed (default: `src/install`): `--install_path=path/to/install` - * if MeshLab has been built with double precision scalar, add: `--double_precision` -* `make_it.sh`: this script builds, deploys and generates an [AppImage](https://appimage.org/) that can be run in a Linux Environment without dependencies. Arguments are the same of the `1_build.sh` script. +## Note about Qt -__NOTE__: `linux_deploy.sh`and `linux_make_it.sh` use [LinuxDeployQt](https://github.com/probonopd/linuxdeployqt), which allows to deploy applications **only running the oldest supported linux distro** (see [this](https://github.com/probonopd/linuxdeployqt/issues/340)) in order to guarantee the largest support possible. Therefore, before running these scripts, be sure that your Linux distribution is the oldest supported one. +Old versions of Ubuntu (< than 22.04) are shipped with old versions of Qt, but MeshLab requires Qt 5.15. +Therefore, you must install manually Qt separatelly in your system. You can then give the path of the Qt installation +directory to the various scripts, or you can add Qt to your `LD_LIBRARY_PATH`. -## Examples +The `0_setup_env.sh` script won't install qt from apt if you pass the argument `dont_install_qt`. -Building MeshLab on a clean Linux environment (build placed in `meshlab/src/build`): +## Dependencies - git clone --recursive https://github.com/cnr-isti-vclab/meshlab - bash meshlab/scripts/Linux/0_setup_env_ubuntu.sh - bash meshlab/scripts/Linux/1_build.sh +Dependencies are automatically installed by the `0_setup_env.sh` script, which uses [`apt-get`](https://linux.die.net/man/8/apt-get) as package manager. +Be sure to have `apt-get` installed before running this script. -Building and generating AppImage on a clean Ubuntu 16.04 (last supported distro) environment: -* build directory: `./meshlab-build` -* install directory: `./meshlab-install` -* AppImage path: `./` +Libraries installed by the `0_setup_env.sh` are the following: + - Required by MeshLab: + - `mesa-common-dev` + - `libglu1-mesa-dev` + - `cmake` + - `ninja-build` + - `patchelf` (for deploy stage) + - Required by Qt5: + - `libxcb-icccm4-dev` + - `libxcb-image0-dev` + - `libxcb-keysyms1-dev` + - `libxcb-render-util0-dev` + - `libxcb-xinerama0-dev` + - Optional: + - `libgmp-dev` and `libmpfr-dev` (required by cgal) + - `libxerces-c-dev` (required by libe57) + - `libcgal-dev` and `libboost-all-dev` (required by several MeshLab plugins) -``` -git clone --recursive https://github.com/cnr-isti-vclab/meshlab -bash meshlab/scripts/Linux/0_setup_env_ubuntu.sh -bash meshlab/scripts/Linux/make_it.sh --build_path="./meshlab-build" --install_path="./meshlab-install" -``` +The script won't install `cgal` and `boost` (and then they will be downloaded by `cmake` during configuration) if you pass the argument `--dont_install_cgal_and_boost`. + +## Note about deployment and AppImage packaging on Linux + +To deploy MeshLab and make it portable, we use the tool [linuxdeploy](https://github.com/linuxdeploy/linuxdeploy). The authors of this tool suggest to use the last still-supported LTS version of Linux when deploying and generating an AppImage, in order to provide wide support of the application. \ No newline at end of file diff --git a/scripts/Linux/internal/2a_make_bundle.sh b/scripts/Linux/internal/2a_make_bundle.sh new file mode 100644 index 000000000..f0aa31bd6 --- /dev/null +++ b/scripts/Linux/internal/2a_make_bundle.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/../ +RESOURCES_PATH=$SCRIPTS_PATH/../../resources +SOURCE_PATH=$SCRIPTS_PATH/../../src +INSTALL_PATH=$SOURCE_PATH/../install + +#check parameters +for i in "$@" +do +case $i in + -i=*|--install_path=*) + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +#check if we have an exec in distrib +if ! [ -f $INSTALL_PATH/usr/bin/meshlab ] +then + echo "ERROR: meshlab bin not found inside $INSTALL_PATH/usr/bin/" + exit 1 +fi + +mkdir -p $INSTALL_PATH/usr/share/doc/meshlab +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/256x256@2x/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/256x256/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/48x48@2x/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/48x48/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/32x32@2x/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/32x32/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/24x24@2x/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/24x24/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/22x22@2x/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/22x22/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/16x16@2x/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/16x16/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/8x8@2x/apps/ +mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/8x8/apps/ + +cp $RESOURCES_PATH/linux/meshlab.desktop $INSTALL_PATH/usr/share/applications/meshlab.desktop +cp $RESOURCES_PATH/icons/meshlab512.png $INSTALL_PATH/usr/share/icons/Yaru/256x256@2x/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab256.png $INSTALL_PATH/usr/share/icons/Yaru/256x256/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab96.png $INSTALL_PATH/usr/share/icons/Yaru/48x48@2x/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab48.png $INSTALL_PATH/usr/share/icons/Yaru/48x48/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab64.png $INSTALL_PATH/usr/share/icons/Yaru/32x32@2x/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab32.png $INSTALL_PATH/usr/share/icons/Yaru/32x32/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab48.png $INSTALL_PATH/usr/share/icons/Yaru/24x24@2x/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab24.png $INSTALL_PATH/usr/share/icons/Yaru/24x24/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab44.png $INSTALL_PATH/usr/share/icons/Yaru/22x22@2x/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab22.png $INSTALL_PATH/usr/share/icons/Yaru/22x22/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab32.png $INSTALL_PATH/usr/share/icons/Yaru/16x16@2x/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab16.png $INSTALL_PATH/usr/share/icons/Yaru/16x16/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab16.png $INSTALL_PATH/usr/share/icons/Yaru/8x8@2x/apps/meshlab.png +cp $RESOURCES_PATH/icons/meshlab8.png $INSTALL_PATH/usr/share/icons/Yaru/8x8/apps/meshlab.png +cp $RESOURCES_PATH/LICENSE.txt $INSTALL_PATH/usr/share/doc/meshlab/ +cp $RESOURCES_PATH/privacy.txt $INSTALL_PATH/usr/share/doc/meshlab/ +cp $RESOURCES_PATH/readme.txt $INSTALL_PATH/usr/share/doc/meshlab/ + +for plugin in $INSTALL_PATH/usr/lib/meshlab/plugins/*.so +do + # allow plugins to find linked libraries in usr/lib, usr/lib/meshlab and usr/lib/meshlab/plugins + patchelf --set-rpath '$ORIGIN/../../:$ORIGIN/../:$ORIGIN' $plugin +done + +chmod +x $INSTALL_PATH/usr/bin/meshlab \ No newline at end of file diff --git a/scripts/Linux/internal/2b_deb.sh b/scripts/Linux/internal/2b_deb.sh new file mode 100644 index 000000000..f566465bc --- /dev/null +++ b/scripts/Linux/internal/2b_deb.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/.. +RESOURCES_PATH=$SCRIPTS_PATH/../../resources +INSTALL_PATH=$SCRIPTS_PATH/../../install +PACKAGES_PATH=$SCRIPTS_PATH/../../packages + +#checking for parameters +for i in "$@" +do +case $i in + -i=*|--install_path=*) + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -p=*|--packages_path=*) + PACKAGES_PATH="${i#*=}" + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +mkdir $PACKAGES_PATH diff --git a/scripts/Linux/internal/2c_portable.sh b/scripts/Linux/internal/2c_portable.sh new file mode 100644 index 000000000..4cc5f2df1 --- /dev/null +++ b/scripts/Linux/internal/2c_portable.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +shopt -s extglob + +SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/.. +RESOURCES_PATH=$SCRIPTS_PATH/../../resources +INSTALL_PATH=$SCRIPTS_PATH/../../install +QT_DIR="" + +#checking for parameters +for i in "$@" +do +case $i in + -i=*|--install_path=*) + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -qt=*|--qt_dir=*) + QT_DIR=${i#*=} + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +if [ ! -z "$QT_DIR" ] +then + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$QT_DIR/lib + export QMAKE=$QT_DIR/bin/qmake +fi + +# Make sure that deploy succeeds before we start deleting files +if $RESOURCES_PATH/linux/linuxdeploy --appdir=$INSTALL_PATH --plugin qt; then + # after deploy, all required libraries are placed into usr/lib, therefore we can remove the ones in + # usr/lib/meshlab (except for the ones that are loaded at runtime) + cd $INSTALL_PATH/usr/lib/meshlab + rm -v !("libIFXCore.so"|"libIFXExporting.so"|"libIFXScheduling.so") + + echo "$INSTALL_PATH is now a self contained meshlab application" + +else + echo "linuxdeploy failed with error code $?. Script was not completed successfully." + exit 1 +fi diff --git a/scripts/Linux/internal/2d_appimage.sh b/scripts/Linux/internal/2d_appimage.sh new file mode 100644 index 000000000..5dd05a7cd --- /dev/null +++ b/scripts/Linux/internal/2d_appimage.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/.. +RESOURCES_PATH=$SCRIPTS_PATH/../../resources +INSTALL_PATH=$SCRIPTS_PATH/../../install +PACKAGES_PATH=$SCRIPTS_PATH/../../packages + +#checking for parameters +for i in "$@" +do +case $i in + -i=*|--install_path=*) + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -p=*|--packages_path=*) + PACKAGES_PATH="${i#*=}" + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +$RESOURCES_PATH/linux/linuxdeploy --appdir=$INSTALL_PATH \ + --output appimage + +#get version +IFS=' ' #space delimiter +STR_VERSION=$($INSTALL_PATH/AppRun --version) +read -a strarr <<< "$STR_VERSION" +ML_VERSION=${strarr[1]} #get the meshlab version from the string + +mkdir $PACKAGES_PATH +mv MeshLab-*.AppImage $PACKAGES_PATH/MeshLab$ML_VERSION-linux.AppImage \ No newline at end of file diff --git a/scripts/Linux/resources/snap/README.md b/scripts/Linux/internal/snap/README.md similarity index 100% rename from scripts/Linux/resources/snap/README.md rename to scripts/Linux/internal/snap/README.md diff --git a/scripts/Linux/resources/snap/meshlab.desktop b/scripts/Linux/internal/snap/meshlab.desktop similarity index 100% rename from scripts/Linux/resources/snap/meshlab.desktop rename to scripts/Linux/internal/snap/meshlab.desktop diff --git a/scripts/Linux/resources/snap/snap_noversion.yaml b/scripts/Linux/internal/snap/snap_noversion.yaml similarity index 90% rename from scripts/Linux/resources/snap/snap_noversion.yaml rename to scripts/Linux/internal/snap/snap_noversion.yaml index 014fd9b3b..9478e7862 100644 --- a/scripts/Linux/resources/snap/snap_noversion.yaml +++ b/scripts/Linux/internal/snap/snap_noversion.yaml @@ -18,9 +18,14 @@ apps: meshlab: command: AppRun extensions: [kde-neon] - plugs: [home, opengl, removable-media] desktop: usr/share/applications/meshlab.desktop - + environment: + DISABLE_WAYLAND: 1 + plugs: + - home + - opengl + - removable-media + - mount-observe parts: meshlab: @@ -43,6 +48,9 @@ parts: - patchelf - rsync - libqt5opengl5-dev + - libcgal-dev + - libboost-all-dev + - libxerces-c-dev stage-packages: - lib3ds-1-3 - libgomp1 diff --git a/scripts/Linux/make_it.sh b/scripts/Linux/make_it.sh index 08e35e971..51a3121f3 100644 --- a/scripts/Linux/make_it.sh +++ b/scripts/Linux/make_it.sh @@ -1,57 +1,53 @@ #!/bin/bash -# This is a script shell for compiling and deploying MeshLab in a Linux environment. -# -# This script can be run only in the oldest supported linux distro -# due to linuxdeployqt tool choice (see https://github.com/probonopd/linuxdeployqt/issues/340). -# -# Requires a Qt environment which is set-up properly, and an accessible -# cmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src/build, -# the folder meshlab/src/install will be a portable version of MeshLab and -# the AppImage will be placed in meshlab/src. -# -# You can give as argument the build path, the install path (that will contain -# the portable version of MeshLab), and the number of cores to use to build MeshLab -# (default: 4). -# The AppImage will be placed in the parent directory of the install path. -# -# Example of call: -# bash make_it.sh --build_path=path/to/build --install_path=path/to/install -j8 SCRIPTS_PATH="$(dirname "$(realpath "$0")")" -SOURCE_PATH=$SCRIPTS_PATH/../../src -BUILD_PATH=$SOURCE_PATH/build -INSTALL_PATH=$SOURCE_PATH/install -CORES="-j4" +SOURCE_PATH=$SCRIPTS_PATH/../.. +BUILD_PATH=$SOURCE_PATH/../build +INSTALL_PATH=$SOURCE_PATH/../install +PACKAGE_PATH=$SOURCE_PATH/../packages + DOUBLE_PRECISION_OPTION="" +NIGHTLY_OPTION="" +QT_DIR_OPTION="" +CCACHE_OPTION="" #check parameters for i in "$@" do case $i in -b=*|--build_path=*) - BUILD_PATH="${i#*=}" - shift # past argument=value - ;; + BUILD_PATH="${i#*=}" + shift # past argument=value + ;; -i=*|--install_path=*) - INSTALL_PATH="${i#*=}"/usr/ - shift # past argument=value - ;; - -j*) - CORES=$i - shift # past argument=value - ;; + INSTALL_PATH="${i#*=}"/usr/ + shift # past argument=value + ;; + -p=*|--package_path=*) + PACKAGE_PATH="${i#*=}" + shift # past argument=value + ;; --double_precision) - DOUBLE_PRECISION_OPTION="--double_precision" - shift # past argument=value - ;; + DOUBLE_PRECISION_OPTION="--double_precision" + shift # past argument=value + ;; + -n|--nightly) + NIGHTLY_OPTION="--nightly" + shift # past argument=value + ;; + -qt=*|--qt_dir=*) + QT_DIR_OPTION=-qt=${i#*=} + shift # past argument=value + ;; + --ccache) + CCACHE_OPTION="--ccache" + shift # past argument=value + ;; *) - # unknown option - ;; + # unknown option + ;; esac done -sh $SCRIPTS_PATH/1_build.sh -b=$BUILD_PATH -i=$INSTALL_PATH $DOUBLE_PRECISION_OPTION $CORES -sh $SCRIPTS_PATH/2_deploy.sh -i=$INSTALL_PATH -sh $SCRIPTS_PATH/3_appimage.sh -i=$INSTALL_PATH $DOUBLE_PRECISION_OPTION +bash $SCRIPTS_PATH/1_build.sh -b=$BUILD_PATH -i=$INSTALL_PATH $NIGHTLY_OPTION $DOUBLE_PRECISION_OPTION $QT_DIR_OPTION $CCACHE_OPTION +bash $SCRIPTS_PATH/2_deploy.sh -i=$INSTALL_PATH -p=$PACKAGE_PATH $QT_DIR_OPTION diff --git a/scripts/Linux/qmake/linux_appimages.sh b/scripts/Linux/qmake/linux_appimages.sh deleted file mode 100644 index 795f52c62..000000000 --- a/scripts/Linux/qmake/linux_appimages.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash -# This is a script shell for setting up the AppImage bundle for linux -# Requires a properly built meshlab, boundled and deployed (see linux_deploy.sh) -# inside the directory given as argument -# -# Without given arguments, MeshLab AppImage(s) will be placed in the meshlab -# directory. -# -# You can give as argument the DISTRIB_PATH. - -#checking for parameters -if [ "$#" -eq 0 ] -then - DISTRIB_PATH="../../../distrib" -else - DISTRIB_PATH=$(realpath $1) -fi - -cd "$(dirname "$(realpath "$0")")"; #move to script directory -INSTALL_PATH=$(pwd)/../ - -cd $DISTRIB_PATH -PARENT_NAME="$(basename $DISTRIB_PATH)" - -export VERSION=$(cat $INSTALL_PATH/../../ML_VERSION) - -cd .. - -#mv $PARENT_NAME/usr/share/applications/meshlab.desktop . - -mv $PARENT_NAME/AppRun $PARENT_NAME/AppRunMeshLab -mv $PARENT_NAME/AppRunMeshLabServer $PARENT_NAME/AppRun -rm $PARENT_NAME/*.desktop -cp $PARENT_NAME/usr/share/applications/meshlab_server.desktop $PARENT_NAME/ - -$INSTALL_PATH/resources/appimagetool $PARENT_NAME -mv MeshLabServer-$VERSION*.AppImage MeshLabServer$VERSION-linux.AppImage -#chmod +x MeshLabServer$VERSION-linux.AppImage - -#mv $PARENT_NAME/usr/share/applications/meshlab_server.desktop . -#mv meshlab.desktop $PARENT_NAME/usr/share/applications/ -mv $PARENT_NAME/AppRun $PARENT_NAME/AppRunMeshLabServer -mv $PARENT_NAME/AppRunMeshLab $PARENT_NAME/AppRun -rm $PARENT_NAME/*.desktop -cp $PARENT_NAME/usr/share/applications/meshlab.desktop $PARENT_NAME/ - -$INSTALL_PATH/resources/appimagetool $PARENT_NAME -mv MeshLab-$VERSION*.AppImage MeshLab$VERSION-linux.AppImage -#chmod +x MeshLab$VERSION-linux.AppImage - -#at this point, distrib folder contains all the files necessary to execute meshlab -echo MeshLab$VERSION-linux.AppImage and MeshLabServer$VERSION-linux.AppImage generated diff --git a/scripts/Linux/qmake/linux_build.sh b/scripts/Linux/qmake/linux_build.sh deleted file mode 100644 index a4196bb45..000000000 --- a/scripts/Linux/qmake/linux_build.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -# this is a script shell for compiling meshlab in a Linux environment. -# Requires a Qt environment which is set-up properly, and an accessible -# qmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src -# directory, and binaries will be placed in meshlab/distrib. -# -# You can give as argument the BUILD_PATH, and meshlab binaries will be -# then placed inside BUILD_PATH/distrib. - -#checking for parameters -if [ "$#" -eq 0 ] -then - BUILD_PATH="../../../src" -else - BUILD_PATH=$(realpath $1) -fi - -cd "$(dirname "$(realpath "$0")")"; #move to script directory - -if ! [ -d $BUILD_PATH ] -then - mkdir $BUILD_PATH -fi - -echo "Build path is: " $BUILD_PATH -SOURCE_PATH=$PWD/../../../src - -cd $BUILD_PATH -qmake $SOURCE_PATH/meshlab.pro -make -j4 diff --git a/scripts/Linux/qmake/linux_build_debug.sh b/scripts/Linux/qmake/linux_build_debug.sh deleted file mode 100644 index 678ef6155..000000000 --- a/scripts/Linux/qmake/linux_build_debug.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -# this is a script shell for compiling meshlab in a Linux environment. -# Requires a Qt environment which is set-up properly, and an accessible -# qmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src -# directory, and binaries will be placed in meshlab/distrib. -# -# You can give as argument the BUILD_PATH, and meshlab binaries will be -# then placed inside BUILD_PATH/distrib. - -#checking for parameters -if [ "$#" -eq 0 ] -then - BUILD_PATH="../../../src" -else - BUILD_PATH=$(realpath $1) -fi - -cd "$(dirname "$(realpath "$0")")"; #move to script directory - -if ! [ -d $BUILD_PATH ] -then - mkdir $BUILD_PATH -fi - -echo "Build path is: " $BUILD_PATH -SOURCE_PATH=$PWD/../../../src - -cd $BUILD_PATH -qmake $SOURCE_PATH/meshlab.pro CONFIG+=debug -make -j4 diff --git a/scripts/Linux/qmake/linux_build_meshlab_mini.sh b/scripts/Linux/qmake/linux_build_meshlab_mini.sh deleted file mode 100644 index 83afbc2ca..000000000 --- a/scripts/Linux/qmake/linux_build_meshlab_mini.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -# this is a script shell for compiling meshlab in a Linux environment. -# Requires a Qt environment which is set-up properly, and an accessible -# qmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src -# directory, and binaries will be placed in meshlab/distrib. -# -# You can give as argument the BUILD_PATH, and meshlab binaries will be -# then placed inside BUILD_PATH/distrib. - -#checking for parameters -if [ "$#" -eq 0 ] -then - BUILD_PATH="../../../src" -else - BUILD_PATH=$(realpath $1) -fi - -cd "$(dirname "$(realpath "$0")")"; #move to script directory - -if ! [ -d $BUILD_PATH ] -then - mkdir $BUILD_PATH -fi - -echo "Build path is: " $BUILD_PATH -SOURCE_PATH=$PWD/../../../src - -cd $BUILD_PATH -qmake $SOURCE_PATH/meshlab.pro "CONFIG+=meshlab_mini" -make -j4 diff --git a/scripts/Linux/qmake/linux_deploy.sh b/scripts/Linux/qmake/linux_deploy.sh deleted file mode 100644 index 80c416de2..000000000 --- a/scripts/Linux/qmake/linux_deploy.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -# This is a script shell for deploying a meshlab-portable folder. -# Requires a properly built meshlab boundle (see linux_make_boundle.sh). -# -# This script can be run only in the oldest supported linux distro that you are using -# due to linuxdeployqt tool choice (see https://github.com/probonopd/linuxdeployqt/issues/340). -# -# Without given arguments, the folder that will be deployed is meshlab/distrib. -# -# You can give as argument the DISTRIB_PATH. - -#checking for parameters -if [ "$#" -eq 0 ] -then - DISTRIB_PATH="../../../distrib" -else - DISTRIB_PATH=$(realpath $1) -fi - -cd "$(dirname "$(realpath "$0")")"; #move to script directory -INSTALL_PATH=$(pwd)/../ - -cd $DISTRIB_PATH - -$INSTALL_PATH/resources/linuxdeployqt usr/share/applications/meshlab.desktop -bundle-non-qt-libs -executable=usr/bin/meshlabserver - -chmod +x usr/bin/meshlab -chmod +x usr/bin/meshlabserver -rm AppRun - -cp $INSTALL_PATH/resources/AppRunMeshLab . -mv AppRunMeshLab AppRun -cp $INSTALL_PATH/resources/AppRunMeshLabServer . -chmod +x AppRun -chmod +x AppRunMeshLabServer - -#at this point, distrib folder contains all the files necessary to execute meshlab -echo "distrib folder is now a self contained meshlab application" \ No newline at end of file diff --git a/scripts/Linux/qmake/linux_make_bundle.sh b/scripts/Linux/qmake/linux_make_bundle.sh deleted file mode 100644 index 73f30fd8a..000000000 --- a/scripts/Linux/qmake/linux_make_bundle.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -# this is a script shell for setting up the application bundle for linux -# Requires a properly built meshlab. -# -# Without given arguments, the application boundle will be placed in the meshlab/distrib -# directory. -# -# You can give as argument the DISTRIB_PATH. - -#checking for parameters -if [ "$#" -eq 0 ] -then - DISTRIB_PATH="../../../distrib" -else - DISTRIB_PATH=$(realpath $1) -fi - -cd "$(dirname "$(realpath "$0")")"; #move to script directory - -SOURCE_PATH=$PWD/../../../src - -INSTALL_PATH=$(pwd)/../ -cd $DISTRIB_PATH -LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd) - -#check if we have an exec in distrib -if ! [ -f meshlab ] -then - echo "ERROR: meshlab bin not found inside distrib" - exit 1 -fi - -mkdir -p usr/bin -mkdir -p usr/lib/meshlab -mkdir -p usr/share/applications -mkdir -p usr/share/meshlab -mkdir -p usr/share/doc/meshlab -mkdir -p usr/share/icons/hicolor/512x512/apps/ -mkdir -p usr/share/icons/Yaru/512x512/apps/ - -cp $INSTALL_PATH/resources/meshlab_appimage.desktop usr/share/applications/meshlab.desktop -cp $INSTALL_PATH/resources/meshlab_server_appimage.desktop usr/share/applications/meshlab_server.desktop -cp meshlab.png usr/share/icons/hicolor/512x512/apps/meshlab.png -mv meshlab.png usr/share/icons/Yaru/512x512/apps/meshlab.png -mv meshlab usr/bin -mv meshlabserver usr/bin -mv LICENSE.txt usr/share/doc/meshlab/ -mv privacy.txt usr/share/doc/meshlab/ -mv readme.txt usr/share/doc/meshlab/ -mv lib/libmeshlab-common* usr/lib/ -mv plugins/ usr/lib/meshlab/ -mv lib/meshlab/* usr/lib/meshlab/ -#patchelf --set-rpath '$ORIGIN/..' usr/lib/meshlab/plugins/*.so -mv shaders/ usr/share/meshlab/ -rm -r lib - -patchelf --set-rpath '$ORIGIN/../lib/meshlab/' usr/bin/meshlab -patchelf --set-rpath '$ORIGIN/../lib/meshlab/' usr/bin/meshlabserver diff --git a/scripts/Linux/qmake/linux_make_it.sh b/scripts/Linux/qmake/linux_make_it.sh deleted file mode 100644 index 5be497153..000000000 --- a/scripts/Linux/qmake/linux_make_it.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# this is a script shell for compiling and deploying meshlab in a Linux environment. -# -# This script can be run only in the oldest supported linux distro that you are using -# due to linuxdeployqt tool choice (see https://github.com/probonopd/linuxdeployqt/issues/340). -# -# Requires a Qt environment which is set-up properly, and an accessible -# qmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src -# directory, and binaries and AppImage will be placed in meshlab/distrib. -# -# You can give as argument the BUILD_PATH, and meshlab binaries and -# AppImage will be then placed inside BUILD_PATH/distrib. - -#checking for parameters -if [ "$#" -eq 0 ] -then - BUILD_PATH="../../../src" - DISTRIB_PATH="../../../distrib" -else - BUILD_PATH=$(realpath $1) - BUILD_PATH=$BUILD_PATH/distrib -fi - -cd "$(dirname "$(realpath "$0")")"; #move to script directory - -sh linux_build.sh $BUILD_PATH -sh linux_make_bundle.sh $DISTRIB_PATH -sh linux_deploy.sh $DISTRIB_PATH -sh linux_appimages.sh $DISTRIB_PATH diff --git a/scripts/Linux/resources/AppRunMeshLab b/scripts/Linux/resources/AppRunMeshLab deleted file mode 100644 index c4116b94d..000000000 --- a/scripts/Linux/resources/AppRunMeshLab +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -#this script is necessary only for the u3d exporter. -#libIFX has its own library loader, which does not consider -#the runpath set in the meshlab binary. It looks only the -#LD_LIBRARY_PATH variable. - -HERE="$(dirname "$(readlink -f "${0}")")" -export LD_LIBRARY_PATH=${HERE}/usr/lib/meshlab:$LD_LIBRARY_PATH -exec "${HERE}/usr/bin/meshlab" "$@" diff --git a/scripts/Linux/resources/AppRunMeshLabServer b/scripts/Linux/resources/AppRunMeshLabServer deleted file mode 100644 index 213271445..000000000 --- a/scripts/Linux/resources/AppRunMeshLabServer +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -#this script is necessary only for the u3d exporter. -#libIFX has its own library loader, which does not consider -#the runpath set in the meshlab binary. It looks only the -#LD_LIBRARY_PATH variable. - -HERE="$(dirname "$(readlink -f "${0}")")" -export LD_LIBRARY_PATH=${HERE}/usr/lib/meshlab:$LD_LIBRARY_PATH -exec "${HERE}/usr/bin/meshlabserver" "$@" diff --git a/scripts/Linux/resources/appimagetool b/scripts/Linux/resources/appimagetool deleted file mode 100755 index 872c650bc..000000000 Binary files a/scripts/Linux/resources/appimagetool and /dev/null differ diff --git a/scripts/Linux/resources/make_bundle.sh b/scripts/Linux/resources/make_bundle.sh deleted file mode 100644 index 7dafa6980..000000000 --- a/scripts/Linux/resources/make_bundle.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash -# this is a script shell for setting up the application bundle for linux -# Requires a properly built meshlab. -# -# Without given arguments, the application boundle will be placed in the meshlab/src/install -# directory. -# -# You can give as argument the path were meshlab has been installed. - -SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/../ -SOURCE_PATH=$SCRIPTS_PATH/../../src -DISTRIB_PATH=$SCRIPTS_PATH/../../distrib - - -#checking for parameters -if [ "$#" -eq 0 ] -then - INSTALL_PATH=$SOURCE_PATH/install -else - INSTALL_PATH=$(realpath $1) -fi - -LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$INSTALL_PATH - -#check if we have an exec in distrib -if ! [ -f $INSTALL_PATH/usr/bin/meshlab ] -then - echo "ERROR: meshlab bin not found inside $INSTALL_PATH/usr/bin/" - exit 1 -fi - -mkdir -p $INSTALL_PATH/usr/share/doc/meshlab -mkdir -p $INSTALL_PATH/usr/share/icons/hicolor/512x512/apps/ -mkdir -p $INSTALL_PATH/usr/share/icons/Yaru/512x512/apps/ - -cp $SCRIPTS_PATH/resources/meshlab_appimage.desktop $INSTALL_PATH/usr/share/applications/meshlab.desktop -cp $DISTRIB_PATH/meshlab.png $INSTALL_PATH/usr/share/icons/hicolor/512x512/apps/meshlab.png -cp $DISTRIB_PATH/meshlab.png $INSTALL_PATH/usr/share/icons/Yaru/512x512/apps/meshlab.png -cp $DISTRIB_PATH/LICENSE.txt $INSTALL_PATH/usr/share/doc/meshlab/ -cp $DISTRIB_PATH/privacy.txt $INSTALL_PATH/usr/share/doc/meshlab/ -cp $DISTRIB_PATH/readme.txt $INSTALL_PATH/usr/share/doc/meshlab/ - -for filename in $INSTALL_PATH/usr/lib/meshlab/plugins/*.so; do - patchelf --set-rpath '$ORIGIN/../' $filename -done diff --git a/scripts/Linux/resources/meshlab_appimage.desktop b/scripts/Linux/resources/meshlab_appimage.desktop deleted file mode 100644 index de7fff193..000000000 --- a/scripts/Linux/resources/meshlab_appimage.desktop +++ /dev/null @@ -1,11 +0,0 @@ -[Desktop Entry] -Version=1.0 -Type=Application -Name=MeshLab -GenericName=Mesh processing -Comment=View and process meshes -Exec=usr/bin/meshlab %F -Icon=meshlab -Terminal=false -MimeType=model/mesh;application/x-3ds;image/x-3ds;model/x-ply;application/sla;model/x-quad-object;model/x-geomview-off;application/x-cyclone-ptx;application/x-vmi;application/x-bre;model/vnd.collada+xml;model/openctm;application/x-expe-binary;application/x-expe-ascii;application/x-xyz;application/x-gts;chemical/x-pdb;application/x-tri;application/x-asc;model/x3d+xml;model/x3d+vrml;model/vrml;model/u3d;model/idtf; -Categories=Graphics;3DGraphics;Viewer;Qt; diff --git a/scripts/Linux/resources/meshlab_server_appimage.desktop b/scripts/Linux/resources/meshlab_server_appimage.desktop deleted file mode 100644 index 2327a0298..000000000 --- a/scripts/Linux/resources/meshlab_server_appimage.desktop +++ /dev/null @@ -1,11 +0,0 @@ -[Desktop Entry] -Version=1.0 -Type=Application -Name=MeshLabServer -GenericName=Batch mesh processing -Comment=Batch Processor MeshLab -Exec=usr/bin/meshlabserver -Icon=meshlab -Terminal=false -MimeType=model/mesh;application/x-3ds;image/x-3ds;model/x-ply;application/sla;model/x-quad-object;model/x-geomview-off;application/x-cyclone-ptx;application/x-vmi;application/x-bre;model/vnd.collada+xml;model/openctm;application/x-expe-binary;application/x-expe-ascii;application/x-xyz;application/x-gts;chemical/x-pdb;application/x-tri;application/x-asc;model/x3d+xml;model/x3d+vrml;model/vrml;model/u3d;model/idtf; -Categories=Graphics;3DGraphics;Qt; diff --git a/scripts/README.md b/scripts/README.md index 3da38854e..d90f054ed 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,16 +1,140 @@ -#scripts folder +# MeshLab scripts -This folder contains a series of platform-dependent scripts to build and deploy MeshLab. +This folder contains a series of platform-dependent bash scripts to build and deploy MeshLab. Every platform folder contains: -* `1_build.sh`: a script that builds MeshLab. Requires a Qt environment properly set, with `cmake` accessible. Takes as inputh the build directory (default: `src/build`), the install directory (default: `src/install`) and the number of cores used to build MeshLab (default: `-j4`). Example of call: `bash 1_build.sh --build_path=path/to/build --install_path=path/to/install -j8` -* `2_deploy.sh`: a script that deploys MeshLab, making sure that the folder will be a self-contained MeshLab, without Qt library dependencies. Requires a properly built MeshLab in the directory passed as an argument (default: `src/install`). Example of call: `bash 2_deploy.sh --install_path=path/to/deploy` -* `3_$installer$.sh`: a script that computes a platform-dependent self-contained package/installer of MeshLab. Requires a properly deployed MeshLab in the directory passed as an argument (default: `src/install`). The result will be saved in the parent directory of the given argument. -* `make_it.sh`: a script that computes all the three previous scripts: starting from the source code, it will produce a self-contained package/installer of MeshLab (arguments are the same of `1_build.sh`). Example of call: `bash makeit.sh --build_path=path/to/build --install_path=path/to/install -j8` +* `0_setup_env.sh`: a script that installs automatically the required dependencies; +* `1_build.sh`: a script that builds MeshLab; +* `2_deploy.sh`: a script that deploys MeshLab; +* `3_pack.sh`: a script that computes a platform-dependent self-contained package/installer of MeshLab; +* `make_it.sh`: a script that computes all the three previous scripts; Note for Windows: scripts are written in bash, therefore they should be run in a linux subsystem environment. + See in each platform subfolder for details and other platform-dependent requirements: -- [Linux](https://github.com/cnr-isti-vclab/meshlab/tree/master/scripts/Linux) -- [MaxOS](https://github.com/cnr-isti-vclab/meshlab/tree/master/scripts/macOS) -- [Windows](https://github.com/cnr-isti-vclab/meshlab/tree/master/scripts/Windows) +- [Linux](https://github.com/cnr-isti-vclab/meshlab/tree/main/scripts/Linux) +- [MaxOS](https://github.com/cnr-isti-vclab/meshlab/tree/main/scripts/macOS) +- [Windows](https://github.com/cnr-isti-vclab/meshlab/tree/main/scripts/Windows) + +## `0_setup_env.sh` + +This script installs automatically the required dependencies of MeshLab. Common dependencies are Qt and `cmake`. + +The script uses a system package manager to install dependencies, which is: + - [`apt-get`](https://linux.die.net/man/8/apt-get) on Linux; + - [`brew`](https://brew.sh/) on macOS; + - [`choco`](https://community.chocolatey.org/) on Windows. + +Please be sure to have these package managers before running this script. + +It takes as input the `--dont_install_qt` option, that allows the user to choose whether to install or not qt using the system package manager. It could be useful if Qt is installed using other sources. For example, in our GitHub actions workflows we use a specific action step to install Qt, in order to choose a specific version. + +Please see the readme inside the desired platform folder for system dependent additional arguments and further details. + +## `1_build.sh` + +This script builds MeshLab. It assumes that the script `0_setup_env.sh` has been already executed and all the dependencies are correctly installed and accessible by the script. + +It takes the following input arguments: + - `--build_path`: the directory where will be placed the build files; + - default: `[meshlab_repo]/build` + - example: `--build_path=path/to/build` + - `--install_path`: the directory where final MeshLab binaries, libraries and files will be placed; + - default: `[meshlab_repo]/install` + - example: `--install_path=path/to/install` + - `--double_precision`: if present, this argument will tell to build MeshLab with double floating point precision; + - `--nighly`: if present, this argument will tell to build MeshLab with a nightly version; + - `--qt_dir`: the directory where to find Qt, useful when Qt is not in the `PATH`; + - example: `--qt_dir=path/to/qt` + - `--ccache`: if present, this argument will tell to use the `ccache` tool to speed up build time (useful for CI builds, be sure to have `ccache` installed). + +Example of call: +``` +bash 1_build.sh --build_path=path/to/build --install_path=path/to/install --double_precision +``` + +## `2_deploy.sh` + +This script deploys MeshLab, making sure that the folder will be a self-contained MeshLab, without Qt or any other system libraries dependencies. It assumes that the scripts `0_setup_env.sh` and `1_build.sh` have been already executed and there is a directory where all the final MeshLab files are placed. + +It takes the following input arguments: + - `--install_path`: the directory where final MeshLab binaries, libraries and files are placed; this will be the path where MeshLab will be deployed. It should be the same argument given to the `1_build.sh` script; + - default: `[meshlab_repo]/install` + - example: `--install_path=path/to/install` + - `--qt_dir`: the directory where to find Qt, useful when Qt is not in the `PATH`; it should be the same argument given to the `1_build.sh` script; + - example: `--qt_dir=path/to/qt` + +Example of call: +``` +bash 2_deploy.sh --install_path=path/to/install +``` + +## `3_pack.sh` + +This script generates a platform-dependent self-contained package/installer of MeshLab. It assumes that the scripts `0_setup_env.sh`, `1_build.sh` and `2_deploy.sh` have been already executed, and there is a directory where MeshLab has been deployed. + +It takes the following input arguments: + - `--install_path`: the directory containing MeshLab deployed; it should be the same argument given to the `2_deploy.sh` script; + - default: `[meshlab_repo]/install` + - example: `--install_path=path/to/install` + - `--packages_path`: the directory where the output package(s) will be placed; + - default: `[meshlab_repo]/packages` + - example: `--packages_path=path/to/packages` + +Example of call: +``` +bash 3_pack.sh --install_path=path/to/install --package_path=path/to/packages +``` + +## `make_it.sh` + +This script computes all the three previous scripts: starting from the source code, it will produce a self-contained package/installer of MeshLab. Input arguments are a union of all the arguments of the previous scripts. + +# Examples + +The following examples can be run on Linux, macOS and Windows (using linux subsystem). + +### Building MeshLab on a clean environment + +The build directory will be placed in `meshlab/build`: + + git clone --recursive https://github.com/cnr-isti-vclab/meshlab + bash meshlab/scripts/[platform]/0_setup_env.sh + bash meshlab/scripts/[platform]/1_build.sh + +### Building, deploying and packaging MeshLab using a custom Qt installation + +For example, let assume that Qt 5.15.2 is installed in the path `/opt/Qt`. We assume also that the compiler/architecture used by Qt is `gcc_64` (you can check yours in the directory `path/to/Qt/5.15.2/`). + +* build directory: `meshlab/build` +* AppDir/portable version: `meshlab/install` +* package (installer, dmg, AppImage) path: `meshlab/packages` + +``` +git clone --recursive https://github.com/cnr-isti-vclab/meshlab +bash meshlab/scripts/[platform]/0_setup_env.sh --dont_install_qt +bash meshlab/scripts/[platform]/1_build.sh --qt_dir=/opt/Qt/5.15.2/gcc_64 +bash meshlab/scripts/[platform]/2_deploy.sh --qt_dir=/opt/Qt/5.15.2/gcc_64 +bash meshlab/scripts/[plarform]/3_pack.sh +``` + +Or, alternatively: + +``` +git clone --recursive https://github.com/cnr-isti-vclab/meshlab +bash meshlab/scripts/[platform]/0_setup_env.sh --dont_install_qt +bash meshlab/scripts/[platform]/make_it.sh --qt_dir=/opt/Qt/5.15.2/gcc_64 +``` + +### Building, deploying and packaging MeshLab using custom directories + +* build directory: `/my/meshlab/build` +* AppDir/portable version: `/my/meshlab/install` +* AppImage path: `/my/meshlab/packages` + +``` +git clone --recursive https://github.com/cnr-isti-vclab/meshlab +bash meshlab/scripts/[platform]/0_setup_env.sh +bash meshlab/scripts/[platform]/make_it.sh --build_path="/my/meshlab/build" --install_path="/my/meshlab/install" --package_path="/my/meshlab/packages" +``` diff --git a/scripts/Windows/0_setup_env.sh b/scripts/Windows/0_setup_env.sh new file mode 100644 index 000000000..1f27e3654 --- /dev/null +++ b/scripts/Windows/0_setup_env.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# this is a script shell sets up a Windows environment where +# MeshLab can be compiled, deployed and packaged. +# +# Run this script if you never installed any of the MeshLab dependencies. +# +# Requires: choco + +DONT_INSTALL_QT=false + +#checking for parameters +for i in "$@" +do +case $i in + --dont_install_qt) + DONT_INSTALL_QT=true + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +choco install cmake ninja ccache wget nsis + +if [ "$DONT_INSTALL_QT" = false ] ; then + echo "=== installing qt packages..." + + choco install qt5-default +else + echo "=== jumping installation of qt packages..." +fi diff --git a/scripts/Windows/1_build.sh b/scripts/Windows/1_build.sh index 4c6541f4f..e345e8fba 100644 --- a/scripts/Windows/1_build.sh +++ b/scripts/Windows/1_build.sh @@ -1,47 +1,50 @@ #!/bin/bash -# this is a script shell for compiling meshlab in a windows environment. -# Requires a VS >= 2017 and Qt environments which are set-up properly, -# and an accessible cmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src/build -# directory, and installed in $BUILD_PATH/../install. -# -# You can give as argument the BUILD_PATH and the INSTALL_PATH in the -# following way: -# sh linux_build.sh --build_path=/path/to/build --install_path=/path/to/install -# -b and -i arguments are also supported. #default paths wrt the script folder SCRIPTS_PATH="$(dirname "$(realpath "$0")")" -SOURCE_PATH=$SCRIPTS_PATH/../../src +SOURCE_PATH=$SCRIPTS_PATH/../.. BUILD_PATH=$SOURCE_PATH/build INSTALL_PATH=$SOURCE_PATH/install -CORES="-j4" DOUBLE_PRECISION_OPTION="" +NIGHTLY_OPTION="" +QT_DIR="" +CCACHE="" #check parameters for i in "$@" do case $i in + -s=*|--source_path=*) + SOURCE_PATH="${i#*=}" + shift # past argument=value + ;; -b=*|--build_path=*) - BUILD_PATH="${i#*=}" - shift # past argument=value - ;; + BUILD_PATH="${i#*=}" + shift # past argument=value + ;; -i=*|--install_path=*) - INSTALL_PATH="${i#*=}" - shift # past argument=value - ;; - -j*) - CORES=$i - shift # past argument=value - ;; - --double_precision) - DOUBLE_PRECISION_OPTION="-DBUILD_WITH_DOUBLE_SCALAR=ON" - shift # past argument=value - ;; + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -d|--double_precision) + DOUBLE_PRECISION_OPTION="-DMESHLAB_BUILD_WITH_DOUBLE_SCALAR=ON" + shift # past argument=value + ;; + -n|--nightly) + NIGHTLY_OPTION="-DMESHLAB_IS_NIGHTLY_VERSION=ON" + shift # past argument=value + ;; + -qt=*|--qt_dir=*) + QT_DIR=${i#*=} + shift # past argument=value + ;; + --ccache) + CCACHE="-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" + shift # past argument=value + ;; *) - # unknown option - ;; + # unknown option + ;; esac done @@ -60,11 +63,13 @@ fi BUILD_PATH=$(realpath $BUILD_PATH) INSTALL_PATH=$(realpath $INSTALL_PATH) -echo "BUILD PATH: "$BUILD_PATH -echo "INSTALL PATH: "$INSTALL_PATH -echo "SCRIPTS PATH: "$SCRIPTS_PATH +if [ ! -z "$QT_DIR" ] +then + export Qt5_DIR=$QT_DIR +fi cd $BUILD_PATH -cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH $DOUBLE_PRECISION_OPTION $SOURCE_PATH -jom $CORES #Qt nmake for parallel build -nmake install +export NINJA_STATUS="[%p (%f/%t) ] " +cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH $CCACHE $DOUBLE_PRECISION_OPTION $NIGHTLY_OPTION $SOURCE_PATH +ninja +ninja install diff --git a/scripts/Windows/2_deploy.sh b/scripts/Windows/2_deploy.sh index 8059d30bb..54e6371d2 100644 --- a/scripts/Windows/2_deploy.sh +++ b/scripts/Windows/2_deploy.sh @@ -1,37 +1,63 @@ #!/bin/bash -# This is a script shell for deploying a meshlab-portable folder. -# Requires a properly built meshlab (see windows_build.sh). -# -# Without given arguments, the folder that will be deployed is meshlab/src/install. -# -# You can give as argument the path where meshlab is installed. SCRIPTS_PATH="$(dirname "$(realpath "$0")")" -DISTRIB_PATH=$SCRIPTS_PATH/../../distrib -INSTALL_PATH=$SCRIPTS_PATH/../../src/install +RESOURCES_PATH=$SCRIPTS_PATH/../../resources +INSTALL_PATH=$SCRIPTS_PATH/../../install +QT_DIR_OPTION="" +PACKAGES_PATH=$SCRIPTS_PATH/../../packages +SIGN=false +CERT_FILE_OPTION="" +CERT_PSSW="" #checking for parameters for i in "$@" do case $i in -i=*|--install_path=*) - INSTALL_PATH="${i#*=}" - shift # past argument=value - ;; + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -qt=*|--qt_dir=*) + QT_DIR_OPTION=qt="${i#*=}" + shift # past argument=value + ;; + -p=*|--packages_path=*) + PACKAGES_PATH="${i#*=}" + shift # past argument=value + ;; + -cf=*|--cert_file=*) + CERT_FILE_OPTION=cf="${i#*=}" + shift # past argument=value + ;; + -cp=*|--cert_pssw=*) + CERT_PSSW="${i#*=}" + if [ -n "$CERT_PSSW" ]; then + SIGN=true + fi + shift # past argument=value + ;; *) - # unknown option - ;; + # unknown option + ;; esac done -windeployqt $INSTALL_PATH/meshlab.exe +bash $SCRIPTS_PATH/internal/2a_portable.sh -i=$INSTALL_PATH $QT_DIR_OPTION -windeployqt $INSTALL_PATH/plugins/filter_sketchfab.dll --libdir $INSTALL_PATH/ +echo "======= Portable Version Created =======" -mv $INSTALL_PATH/lib/meshlab/IFX* $INSTALL_PATH -cp $INSTALL_PATH/IFXCoreStatic.lib $INSTALL_PATH/lib/meshlab/ -cp $DISTRIB_PATH/LICENSE.txt $INSTALL_PATH/ -cp $DISTRIB_PATH/privacy.txt $INSTALL_PATH/ +if [ "$SIGN" = true ] ; then + bash $SCRIPTS_PATH/internal/2b_sign_dlls.sh -i=$INSTALL_PATH $CERT_FILE_OPTION -cp=$CERT_PSSW -#at this point, distrib folder contains all the files necessary to execute meshlab -echo "$INSTALL_PATH is now a self contained meshlab application" + echo "======= Portable Version Signed =======" +fi + +bash $SCRIPTS_PATH/internal/2c_installer.sh -i=$INSTALL_PATH -p=$PACKAGES_PATH + +echo "======= Installer Created =======" + +if [ "$SIGN" = true ] ; then + bash $SCRIPTS_PATH/internal/2b_sign_dlls.sh -i=$PACKAGES_PATH $CERT_FILE_OPTION -cp=$CERT_PSSW + + echo "======= Installer Signed =======" +fi diff --git a/scripts/Windows/3_installer.sh b/scripts/Windows/3_installer.sh deleted file mode 100644 index 363bfd290..000000000 --- a/scripts/Windows/3_installer.sh +++ /dev/null @@ -1,39 +0,0 @@ -# This is a powershell script for computing an installer for MeshLab. -# Requires: -# - a properly deployed meshlab (see windows_deploy.ps1); -# - the env variable PATH containing the NSIS folder (makensis.exe must be directly accessible) -# -# Without given arguments, the folder that will be deployed is meshlab/distrib. -# -# You can give as argument the DISTRIB_PATH. -# -# After running this script, the installer can be found inside the resources folder. - -SCRIPTS_PATH="$(dirname "$(realpath "$0")")" -INSTALL_PATH=$SCRIPTS_PATH/../../src/install -DOUBLE_PRECISION_OPTION="" - - -#checking for parameters -for i in "$@" -do -case $i in - -i=*|--install_path=*) - INSTALL_PATH="${i#*=}" - shift # past argument=value - ;; - --double_precision) - DOUBLE_PRECISION_OPTION="--double_precision" - shift # past argument=value - ;; - *) - # unknown option - ;; -esac -done - -sh $SCRIPTS_PATH/resources/nsis_script.sh -i=$INSTALL_PATH $DOUBLE_PRECISION_OPTION - -makensis.exe $SCRIPTS_PATH/resources/meshlab_final.nsi - -rm $SCRIPTS_PATH/resources/meshlab_final.nsi diff --git a/scripts/Windows/README.md b/scripts/Windows/README.md index 31b92c38d..28aa46950 100644 --- a/scripts/Windows/README.md +++ b/scripts/Windows/README.md @@ -1,28 +1,29 @@ # Windows Scripts This folder contains a series of scripts to build and deploy MeshLab under a Windows environment. -**Note**: scripts are written in bash, therefore they should be run in a linux subsystem environment. -* `1_build.sh`: this script builds MeshLab in a Windows environment: - * it requires a properly set Visual Studio (>=2015) and MSVC compiler; - * it requires a properly set Qt environment; - * `cmake` in the PATH env variable; - * takes as arguments: - * the build directory (default: `src/build`): `--build_path=path/to/build` - * the install directory (default: `src/install`): `--install_path=path/to/install` - * the number of cores used to build MeshLab (default: `-j4`)` - * the possibility to build MeshLab with double precision scalar: `--double_precision` -* `2_deploy.sh`: this script makes the given path a portable version of MeshLab. Takes as arguments: - * the path where the output install path of the `1_build.sh` script is placed (default: `src/install`): `--install_path=path/to/install` -* `3_installer.sh`: this script computes, starting from the portable folder of MeshLab, an NSIS installer. Takes as arguments: - * the path where the output install path of the `2_deploy.sh` script is placed (default: `src/install`): `--install_path=path/to/install` - * if MeshLab has been built with double precision scalar, add: `--double_precision` - * it requires `makensis.exe` in the PATH env variable. +## Note about the compiler +On Windows, we use MSVC compiler to build MeshLab. Before trying to build MeshLab, you should download and install VisualStudio with the C++ developer package, which contains the MSVC compiler. -## Examples +Other compilers are not tested. -Building MeshLab on Windows, having VisualStudio, MSVC and Qt installed, cmake in the PATH (build placed in `meshlab/src/build`): +## Note about Qt - git clone --recursive https://github.com/cnr-isti-vclab/meshlab - sh meshlab/scripts/Windows/1_build.sh \ No newline at end of file +MeshLab requires Qt 5.15. You can both install Qt5 using `choco` or manually in your system. +If you install Qt manually. you can then give the path of the Qt installation directory to the various scripts, or you can add Qt to your `PATH`. + +The `0_setup_env.sh` script won't install qt from `choco` if you pass the argument `dont_install_qt`. + +## Dependencies + +Dependencies are automatically installed by the `0_setup_env.sh` script, which uses [`choco`](https://community.chocolatey.org/) as package manager. +Be sure to have `choco` installed before running this script. + +Libraries installed by the `0_setup_env.sh` are the following: + - Required by MeshLab: + - `wget` (required by these scripts) + - `ccache` (required by github actions) + - `cmake` + - `ninja` + - `nsis` (for package stage) \ No newline at end of file diff --git a/scripts/Windows/internal/2a_portable.sh b/scripts/Windows/internal/2a_portable.sh new file mode 100644 index 000000000..49ca551c7 --- /dev/null +++ b/scripts/Windows/internal/2a_portable.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/.. +RESOURCES_PATH=$SCRIPTS_PATH/../../resources +INSTALL_PATH=$SCRIPTS_PATH/../../install +QT_DIR="" + +#checking for parameters +for i in "$@" +do +case $i in + -i=*|--install_path=*) + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -qt=*|--qt_dir=*) + QT_DIR=${i#*=}/bin/ + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +${QT_DIR}windeployqt $INSTALL_PATH/meshlab.exe + +${QT_DIR}windeployqt $INSTALL_PATH/plugins/filter_sketchfab.dll --libdir $INSTALL_PATH/ + +mv $INSTALL_PATH/lib/meshlab/IFX* $INSTALL_PATH +cp $INSTALL_PATH/IFXCoreStatic.lib $INSTALL_PATH/lib/meshlab/ +cp $RESOURCES_PATH/LICENSE.txt $INSTALL_PATH/ +cp $RESOURCES_PATH/privacy.txt $INSTALL_PATH/ + +# remove all .lib files +for file in $(find $INSTALL_PATH -name '*.lib'); +do + rm $file +done + +if [ ! -f $INSTALL_PATH/vc_redist.x64.exe ] +then + echo "Downloading vc_redist because it was missing..." + wget https://aka.ms/vs/17/release/vc_redist.x64.exe --output-document=$INSTALL_PATH/vc_redist.x64.exe +fi \ No newline at end of file diff --git a/scripts/Windows/internal/2b_sign_dlls.sh b/scripts/Windows/internal/2b_sign_dlls.sh new file mode 100644 index 000000000..6f570d694 --- /dev/null +++ b/scripts/Windows/internal/2b_sign_dlls.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/.. +INSTALL_PATH=$SCRIPTS_PATH/../../install +CERT_FILE=$SCRIPTS_PATH/../../certificate/certificate.pfx +CERT_PSSW="" + +#checking for parameters +for i in "$@" +do +case $i in + -i=*|--install_path=*) + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -cf=*|--cert_file=*) + CERT_FILE="${i#*=}" + shift # past argument=value + ;; + -cp=*|--cert_pssw=*) + CERT_PSSW=${i#*=} + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +cd $INSTALL_PATH + + +CERT_REL=$(realpath --relative-to=$INSTALL_PATH $CERT_FILE) # get relative path of the cert file +CERT_WIN=$(echo "$CERT_REL" | sed 's/^\///' | sed 's/\//\\/g') # get windows relative path (with backslashes) of the cert + +# will sign all dll and exe files inside INSTALL_PATH, recursively +for file in $(find $INSTALL_PATH -name '*.dll' -or -name '*.exe'); +do + FILE_REL=$(realpath --relative-to=$INSTALL_PATH $file) # relative path + FILE_WIN=$(echo "$FILE_REL" | sed 's/^\///' | sed 's/\//\\/g') # win relative path + signtool.exe sign //fd SHA256 //f $CERT_WIN //p $CERT_PSSW //t http://timestamp.comodoca.com/authenticode $FILE_WIN +done \ No newline at end of file diff --git a/scripts/Windows/internal/2c_installer.sh b/scripts/Windows/internal/2c_installer.sh new file mode 100644 index 000000000..529314ac2 --- /dev/null +++ b/scripts/Windows/internal/2c_installer.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/.. +RESOURCES_PATH=$SCRIPTS_PATH/../../resources +INSTALL_PATH=$SCRIPTS_PATH/../../install +PACKAGES_PATH=$SCRIPTS_PATH/../../packages + +#checking for parameters +for i in "$@" +do +case $i in + -i=*|--install_path=*) + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -p=*|--packages_path=*) + PACKAGES_PATH="${i#*=}" + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +# Make nsis script + +#get version +IFS=' ' #space delimiter +STR_VERSION=$($INSTALL_PATH/meshlab.exe --version) +read -a strarr <<< "$STR_VERSION" +ML_VERSION=${strarr[1]} #get the meshlab version from the string + +sed "s%MESHLAB_VERSION%$ML_VERSION%g" $RESOURCES_PATH/windows/meshlab.nsi > $RESOURCES_PATH/windows/meshlab_final.nsi +sed -i "s%DISTRIB_PATH%.%g" $RESOURCES_PATH/windows/meshlab_final.nsi + +mv $RESOURCES_PATH/windows/meshlab_final.nsi $INSTALL_PATH/ +cp $RESOURCES_PATH/windows/ExecWaitJob.nsh $INSTALL_PATH/ +cp $RESOURCES_PATH/windows/FileAssociation.nsh $INSTALL_PATH/ + +# Make Installer + +makensis.exe $INSTALL_PATH/meshlab_final.nsi + +rm $INSTALL_PATH/meshlab_final.nsi +rm $INSTALL_PATH/ExecWaitJob.nsh +rm $INSTALL_PATH/FileAssociation.nsh + +mkdir $PACKAGES_PATH +mv $INSTALL_PATH/MeshLab*-windows.exe $PACKAGES_PATH \ No newline at end of file diff --git a/scripts/Windows/make_it.sh b/scripts/Windows/make_it.sh index 5775da5a7..01863dfe9 100644 --- a/scripts/Windows/make_it.sh +++ b/scripts/Windows/make_it.sh @@ -4,51 +4,66 @@ # Requires MSVC and Qt environment which is set-up properly, and accessible # cmake and makensis binaries. # -# Without given arguments, MeshLab will be built in the meshlab/src/build, -# the folder meshlab/src/install will be a portable version of MeshLab and -# the AppImage will be placed in meshlab/src. +# Without given arguments, MeshLab will be built in the meshlab/build, +# the folder meshlab/install will be a portable version of MeshLab and +# the Installer will be placed in meshlab/install. # # You can give as argument the build path, the install path (that will contain # the portable version of MeshLab), and the number of cores to use to build MeshLab # (default: 4). -# The installer will be placed in the parent directory of the install path. # # Example of call: # bash make_it.sh --build_path=path/to/build --install_path=path/to/install -j8 SCRIPTS_PATH="$(dirname "$(realpath "$0")")" -SOURCE_PATH=$SCRIPTS_PATH/../../src +SOURCE_PATH=$SCRIPTS_PATH/../.. BUILD_PATH=$SOURCE_PATH/build INSTALL_PATH=$SOURCE_PATH/install -CORES="-j4" +PACKAGES_PATH=$SOURCE_PATH/packages + DOUBLE_PRECISION_OPTION="" +NIGHTLY_OPTION="" +QT_DIR_OPTION="" +CCACHE_OPTION="" #check parameters for i in "$@" do case $i in -b=*|--build_path=*) - BUILD_PATH="${i#*=}" - shift # past argument=value - ;; + BUILD_PATH="${i#*=}" + shift # past argument=value + ;; -i=*|--install_path=*) - INSTALL_PATH="${i#*=}"/usr/ - shift # past argument=value - ;; - -j*) - CORES=$i - shift # past argument=value - ;; + INSTALL_PATH="${i#*=}"/usr/ + shift # past argument=value + ;; + -p=*|--packages_path=*) + PACKAGES_PATH="${i#*=}" + shift # past argument=value + ;; --double_precision) - DOUBLE_PRECISION_OPTION="--double_precision" - shift # past argument=value - ;; + DOUBLE_PRECISION_OPTION="--double_precision" + shift # past argument=value + ;; + -n|--nightly) + NIGHTLY_OPTION="--nightly" + shift # past argument=value + ;; + -qt=*|--qt_dir=*) + QT_DIR_OPTION=-qt=${i#*=} + shift # past argument=value + ;; + --ccache) + CCACHE_OPTION="--ccache" + shift # past argument=value + ;; *) - # unknown option - ;; + # unknown option + ;; esac done -sh $SCRIPTS_PATH/1_build.sh -b=$BUILD_PATH -i=$INSTALL_PATH $DOUBLE_PRECISION_OPTION $CORES -sh $SCRIPTS_PATH/2_deploy.sh -i=$INSTALL_PATH -sh $SCRIPTS_PATH/3_installer.sh -i=$INSTALL_PATH $DOUBLE_PRECISION_OPTION +bash $SCRIPTS_PATH/1_build.sh -b=$BUILD_PATH -i=$INSTALL_PATH $NIGHTLY_OPTION $DOUBLE_PRECISION_OPTION $QT_DIR_OPTION $CCACHE_OPTION +bash $SCRIPTS_PATH/2_deploy.sh -i=$INSTALL_PATH -p=$PACKAGES_PATH $QT_DIR_OPTION + diff --git a/scripts/Windows/qmake/windows_build.ps1 b/scripts/Windows/qmake/windows_build.ps1 deleted file mode 100644 index ea6eec7c3..000000000 --- a/scripts/Windows/qmake/windows_build.ps1 +++ /dev/null @@ -1,34 +0,0 @@ -# This is a powershell script compiling meshlab in a Windows environment. -# Requires: -# - MSVC installed; -# - Qt installed, and qmake and jom binaries directly accessible -# -# # Without given arguments, MeshLab will be built in the meshlab/src -# directory, and binaries will be placed in meshlab/distrib. -# -# You can give as argument the BUILD_PATH, and meshlab binaries will be -# then placed inside BUILD_PATH/distrib. - -#saving location where script has been run - -write-host "N of arguments: $($args.count)" - -$DIR = Get-Location -$SOURCE_PATH = Join-Path $PSScriptRoot ..\..\..\src - -if ($args.Count -gt 0){ - $BUILD_PATH = Resolve-Path -Path $args[0] -} else { - $BUILD_PATH = $SOURCE_PATH #default build -} - -New-Item -ItemType Directory -Force -Path $BUILD_PATH -cd $BUILD_PATH - -write-host "Build path is: $($BUILD_PATH)" - -qmake $SOURCE_PATH\meshlab.pro -jom -j4 #Qt nmake for parallel build - -#going back to original location -cd $DIR diff --git a/scripts/Windows/qmake/windows_build_debug.ps1 b/scripts/Windows/qmake/windows_build_debug.ps1 deleted file mode 100644 index b391293fb..000000000 --- a/scripts/Windows/qmake/windows_build_debug.ps1 +++ /dev/null @@ -1,34 +0,0 @@ -# This is a powershell script compiling meshlab in a Windows environment. -# Requires: -# - MSVC installed; -# - Qt installed, and qmake and jom binaries directly accessible -# -# # Without given arguments, MeshLab will be built in the meshlab/src -# directory, and binaries will be placed in meshlab/distrib. -# -# You can give as argument the BUILD_PATH, and meshlab binaries will be -# then placed inside BUILD_PATH/distrib. - -#saving location where script has been run - -write-host "N of arguments: $($args.count)" - -$DIR = Get-Location -$SOURCE_PATH = Join-Path $PSScriptRoot ..\..\..\src - -if ($args.Count -gt 0){ - $BUILD_PATH = Resolve-Path -Path $args[0] -} else { - $BUILD_PATH = $SOURCE_PATH #default build -} - -New-Item -ItemType Directory -Force -Path $BUILD_PATH -cd $BUILD_PATH - -write-host "Build path is: $($BUILD_PATH)" - -qmake $SOURCE_PATH\meshlab.pro CONFIG+=debug -jom -j4 #Qt nmake for parallel build - -#going back to original location -cd $DIR diff --git a/scripts/Windows/qmake/windows_deploy.ps1 b/scripts/Windows/qmake/windows_deploy.ps1 deleted file mode 100644 index a76742244..000000000 --- a/scripts/Windows/qmake/windows_deploy.ps1 +++ /dev/null @@ -1,45 +0,0 @@ -# This is a powershell script for deploying a meshlab-portable app. -# Requires: -# - a properly built meshlab; -# - the env variable PATH containing the bin folder of QT (windeployqt.exe must be directly accessible) -# - the env variable VCINSTALLDIR set to the VC of Visual Studio (example: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC) -# -# Without given arguments, the folder that will be deployed is meshlab/distrib. -# -# You can give as argument the DISTRIB_PATH. -# -# After running this script, $DISTRIB_PATH will be a portable meshlab folder. -# -# To be run in a windows environment without Visual Studio installed, -# vc_redist.exe must be installed before. - -#saving location where script has been run - -write-host "N of arguments: $($args.count)" - -$DIR = Get-Location -$SOURCE_PATH = Join-Path $PSScriptRoot ..\..\..\src - -if ($args.Count -gt 0){ - $DISTRIB_PATH = $args[0] -} else { - $DISTRIB_PATH = Join-Path $PSScriptRoot ..\..\..\distrib #default distrib -} - -cd $DISTRIB_PATH - -if(! (Test-Path meshlab.exe)){ #meshlab.exe not found inside $DISTRIB_PATH - cd $DIR - throw 'meshlab.exe not found in ' + ($DISTRIB_PATH) + '. Exiting.' -} - -windeployqt --no-translations meshlab.exe - -Move-Item .\lib\meshlab\IFX* . -Copy-Item IFXCoreStatic.lib .\lib\meshlab\ - -#at this point, distrib folder contains all the files necessary to execute meshlab -echo "distrib folder is now a self contained meshlab application" - -#going back to original location -cd $DIR diff --git a/scripts/Windows/qmake/windows_nsis_installer.ps1 b/scripts/Windows/qmake/windows_nsis_installer.ps1 deleted file mode 100644 index 222b99512..000000000 --- a/scripts/Windows/qmake/windows_nsis_installer.ps1 +++ /dev/null @@ -1,32 +0,0 @@ -# This is a powershell script for computing an installer for MeshLab. -# Requires: -# - a properly deployed meshlab (see windows_deploy.ps1); -# - the env variable PATH containing the NSIS folder (makensis.exe must be directly accessible) -# -# Without given arguments, the folder that will be deployed is meshlab/distrib. -# -# You can give as argument the DISTRIB_PATH. -# -# After running this script, the installer can be found inside the resources folder. - -#saving location where script has been run -$DIR = Get-Location - -$SCRIPTS_PATH = Join-Path $PSScriptRoot ..\ - -if ($args.Count -gt 0){ - $DISTRIB_PATH = $args[0] -} else { - $DISTRIB_PATH = Join-Path $PSScriptRoot ..\..\..\distrib #default distrib -} - -.\..\resources\windows_nsis_script.ps1 $DISTRIB_PATH - -cd $SCRIPTS_PATH - -makensis.exe .\..\resources\meshlab_final.nsi - -Remove-Item .\..\resources\meshlab_final.nsi - -#going back to original location -cd $DIR diff --git a/scripts/Windows/resources/nsis_script.sh b/scripts/Windows/resources/nsis_script.sh deleted file mode 100644 index 51c271806..000000000 --- a/scripts/Windows/resources/nsis_script.sh +++ /dev/null @@ -1,40 +0,0 @@ -# This is a powershell script for computing the meshlab_final.nsi script. -# Requires: -# - a properly deployed meshlab (see windows_deploy.ps1); -# -# Without given arguments, the folder that will be deployed is meshlab/distrib. -# -# You can give as argument the DISTRIB_PATH. -# -# After running this script, a meshlab_final.script can be found in the resources folder. -# This script is ready to be run by makensis.exe - -SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/.. -SOURCE_PATH=$SCRIPTS_PATH/../../src -ML_VERSION=$(cat $SOURCE_PATH/../ML_VERSION) -INSTALL_PATH=$SOURCE_PATH/install - -#check parameters -for i in "$@" -do -case $i in - -i=*|--install_path=*) - INSTALL_PATH="${i#*=}" - shift # past argument=value - ;; - --double_precision) - ML_VERSION=${ML_VERSION}d - shift # past argument=value - ;; - *) - # unknown option - ;; -esac -done - -sed "s%MESHLAB_VERSION%$ML_VERSION%g" $SCRIPTS_PATH/resources/meshlab.nsi > $SCRIPTS_PATH/resources/meshlab_final.nsi -sed -i "s%DISTRIB_PATH%.%g" $SCRIPTS_PATH/resources/meshlab_final.nsi - -mv $SCRIPTS_PATH/resources/meshlab_final.nsi $INSTALL_PATH/ -cp $SCRIPTS_PATH/resources/ExecWaitJob.nsh $INSTALL_PATH/ -cp $SCRIPTS_PATH/resources/FileAssociation.nsh $INSTALL_PATH/ diff --git a/scripts/Windows/resources/windows_nsis_script.ps1 b/scripts/Windows/resources/windows_nsis_script.ps1 deleted file mode 100644 index d8560d022..000000000 --- a/scripts/Windows/resources/windows_nsis_script.ps1 +++ /dev/null @@ -1,41 +0,0 @@ -# This is a powershell script for computing the meshlab_final.nsi script. -# Requires: -# - a properly deployed meshlab (see windows_deploy.ps1); -# -# Without given arguments, the folder that will be deployed is meshlab/distrib. -# -# You can give as argument the DISTRIB_PATH. -# -# After running this script, a meshlab_final.script can be found in the resources folder. -# This script is ready to be run by makensis.exe - -#saving location where script has been run -$DIR = Get-Location - -$INSTALL_PATH = Join-Path $PSScriptRoot ..\ -$SOURCE_PATH = Join-Path $PSScriptRoot ..\..\..\src - -if ($args.Count -gt 0){ - $DISTRIB_PATH = $args[0] -} else { - $DISTRIB_PATH = Join-Path $PSScriptRoot ..\..\..\distrib #default distrib -} - -cd $DISTRIB_PATH - -if(! (Test-Path meshlab.exe)){ #meshlab.exe not found inside $DISTRIB_PATH - cd $DIR - throw 'meshlab.exe not found in ' + ($DISTRIB_PATH) + '. Exiting.' -} - -$VERSION = type (Join-Path $SOURCE_PATH ..\ML_VERSION) - -cd $INSTALL_PATH - -cat resources\meshlab.nsi | %{$_ -replace "MESHLAB_VERSION",$VERSION} > resources\meshlab_tmp.nsi -cat resources\meshlab_tmp.nsi | %{$_ -replace "DISTRIB_PATH",$DISTRIB_PATH} > resources\meshlab_final.nsi - -Remove-Item resources\meshlab_tmp.nsi - -#going back to original location -cd $DIR diff --git a/scripts/macOS/0_setup_env.sh b/scripts/macOS/0_setup_env.sh index 70a796376..6bc5d3d8c 100644 --- a/scripts/macOS/0_setup_env.sh +++ b/scripts/macOS/0_setup_env.sh @@ -6,11 +6,35 @@ # # Requires: homebrew -brew install libomp qt +DONT_INSTALL_QT=false + +#checking for parameters +for i in "$@" +do +case $i in + --dont_install_qt) + DONT_INSTALL_QT=true + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +brew install coreutils node cmake ninja libomp cgal xerces-c npm install -g appdmg -echo "export QTDIR=/usr/local/opt/qt" >> ~/.bash_profile -echo "export PATH=$QTDIR/bin:$PATH" >> ~/.bash_profile -echo "export LD_LIBRARY_PATH=/usr/local/opt/qt/lib:$LD_LIBRARY_PATH" >> ~/.bash_profile -echo "export PKG_CONFIG_PATH=/usr/local/opt/qt/lib:$PKG_CONFIG_PATH" >> ~/.bash_profile -. ~/.bash_profile +if [ "$DONT_INSTALL_QT" = false ] ; then + echo "=== installing qt packages..." + + brew install qt + + echo "export QTDIR=/usr/local/opt/qt" >> ~/.bash_profile + echo "export PATH=$QTDIR/bin:$PATH" >> ~/.bash_profile + echo "export LD_LIBRARY_PATH=/usr/local/opt/qt/lib:$LD_LIBRARY_PATH" >> ~/.bash_profile + echo "export PKG_CONFIG_PATH=/usr/local/opt/qt/lib:$PKG_CONFIG_PATH" >> ~/.bash_profile + . ~/.bash_profile +else + echo "=== jumping installation of qt packages..." +fi diff --git a/scripts/macOS/1_build.sh b/scripts/macOS/1_build.sh index 5d561e4f4..daa31b451 100644 --- a/scripts/macOS/1_build.sh +++ b/scripts/macOS/1_build.sh @@ -1,52 +1,50 @@ #!/bin/bash -# this is a script shell for compiling meshlab in a MacOS environment. -# Requires a Qt environment which is set-up properly, and an accessible -# cmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src/build -# directory, and installed in $BUILD_PATH/../install. -# -# You can give as argument the BUILD_PATH and the INSTALL_PATH in the -# following way: -# sh macos_build.sh --build_path=/path/to/build --install_path=/path/to/install -# -b and -i arguments are also supported. - -#realpath function -#realpath() { -# [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" -#} #default paths wrt the script folder SCRIPTS_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -SOURCE_PATH=$SCRIPTS_PATH/../../src +SOURCE_PATH=$SCRIPTS_PATH/../.. BUILD_PATH=$SOURCE_PATH/build INSTALL_PATH=$SOURCE_PATH/install -CORES="-j4" DOUBLE_PRECISION_OPTION="" +NIGHTLY_OPTION="" +QT_DIR="" +CCACHE="" #check parameters for i in "$@" do case $i in + -s=*|--source_path=*) + SOURCE_PATH="${i#*=}" + shift # past argument=value + ;; -b=*|--build_path=*) - BUILD_PATH="${i#*=}" - shift # past argument=value - ;; + BUILD_PATH="${i#*=}" + shift # past argument=value + ;; -i=*|--install_path=*) - INSTALL_PATH="${i#*=}" - shift # past argument=value - ;; - -j*) - CORES=$i - shift # past argument=value - ;; - --double_precision) - DOUBLE_PRECISION_OPTION="-DBUILD_WITH_DOUBLE_SCALAR=ON" - shift # past argument=value - ;; + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -d|--double_precision) + DOUBLE_PRECISION_OPTION="-DMESHLAB_BUILD_WITH_DOUBLE_SCALAR=ON" + shift # past argument=value + ;; + -n|--nightly) + NIGHTLY_OPTION="-DMESHLAB_IS_NIGHTLY_VERSION=ON" + shift # past argument=value + ;; + -qt=*|--qt_dir=*) + QT_DIR=${i#*=} + shift # past argument=value + ;; + --ccache) + CCACHE="-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" + shift # past argument=value + ;; *) - # unknown option - ;; + # unknown option + ;; esac done @@ -62,7 +60,16 @@ then mkdir -p $INSTALL_PATH fi +if [ ! -z "$QT_DIR" ] +then + export Qt5_DIR=$QT_DIR +fi + +BUILD_PATH=$(realpath $BUILD_PATH) +INSTALL_PATH=$(realpath $INSTALL_PATH) + cd $BUILD_PATH -cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH $DOUBLE_PRECISION_OPTION $SOURCE_PATH -make $CORES -make install +export NINJA_STATUS="[%p (%f/%t) ] " +cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH $CCACHE $DOUBLE_PRECISION_OPTION $NIGHTLY_OPTION $SOURCE_PATH +ninja +ninja install diff --git a/scripts/macOS/2_deploy.sh b/scripts/macOS/2_deploy.sh index 230b2cd93..f359e86e6 100755 --- a/scripts/macOS/2_deploy.sh +++ b/scripts/macOS/2_deploy.sh @@ -1,48 +1,77 @@ #!/bin/bash -# this is a script shell for deploying a meshlab-portable app. -# Requires a properly built meshlab. -# -# Without given arguments, the folder that will be deployed is meshlab/distrib. -# -# You can give as argument the DISTRIB_PATH. -# -# After running this script, $DISTRIB_PATH/meshlab.app will be a portable meshlab application. -#realpath function -realpath() { - [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" -} +SCRIPTS_PATH="$(dirname "$(realpath "$0")")" -SCRIPTS_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -INSTALL_PATH=$SCRIPTS_PATH/../../src/install -APPNAME="meshlab.app" +INSTALL_PATH=$SCRIPTS_PATH/../../install +QT_DIR_OPTION="" +PACKAGES_PATH=$SCRIPTS_PATH/../../packages +SIGN=false +NOTARIZE=false +CERT_ID="" +NOTAR_USER="" +NOTAR_TEAM_ID="" +NOTAR_PASSWORD="" #checking for parameters for i in "$@" do case $i in -i=*|--install_path=*) - INSTALL_PATH="${i#*=}" - shift # past argument=value - ;; + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -qt=*|--qt_dir=*) + QT_DIR_OPTION=-qt=${i#*=} + shift # past argument=value + ;; + -p=*|--packages_path=*) + PACKAGES_PATH="${i#*=}" + shift # past argument=value + ;; + -ci=*|--cert_id=*) + CERT_ID="${i#*=}" + if [ -n "$CERT_ID" ]; then + SIGN=true + fi + shift # past argument=value + ;; + -nu=*|--notarization_user=*) + NOTAR_USER="${i#*=}" + if [ -n "$NOTAR_USER" ]; then + NOTARIZE=true + fi + shift # past argument=value + ;; + -np=*|--notarization_pssw=*) + NOTAR_PASSWORD="${i#*=}" + shift # past argument=value + ;; + -nt=*|--notarization_team=*) + NOTAR_TEAM_ID="${i#*=}" + shift # past argument=value + ;; *) - # unknown option - ;; + # unknown option + ;; esac done -echo "Hopefully I should find " $INSTALL_PATH/$APPNAME +bash $SCRIPTS_PATH/internal/2a_appbundle.sh -i=$INSTALL_PATH $QT_DIR_OPTION -if ! [ -e $INSTALL_PATH/$APPNAME -a -d $INSTALL_PATH/$APPNAME ] -then - echo "Started in the wrong dir: I have not found the meshlab.app" - exit -1 +echo "======= AppBundle Created =======" + +if [ "$SIGN" = true ] ; then + bash $SCRIPTS_PATH/internal/2b_sign_appbundle.sh -i=$INSTALL_PATH -ci=$CERT_ID + + echo "======= AppBundle Signed =======" fi -if [ -e $QTDIR/bin/macdeployqt ] -then - $QTDIR/bin/macdeployqt $INSTALL_PATH/$APPNAME -executable=$INSTALL_PATH/$APPNAME/Contents/PlugIns/libfilter_csg.so -executable=$INSTALL_PATH/$APPNAME/Contents/PlugIns/libfilter_globalregistration.so -executable=$INSTALL_PATH/$APPNAME/Contents/PlugIns/libfilter_isoparametrization.so -executable=$INSTALL_PATH/$APPNAME/Contents/PlugIns/libfilter_screened_poisson.so -executable=$INSTALL_PATH/$APPNAME/Contents/PlugIns/libfilter_sketchfab.so - -else - macdeployqt $INSTALL_PATH/$APPNAME -executable=$INSTALL_PATH/$APPNAME/Contents/PlugIns/libfilter_csg.so -executable=$INSTALL_PATH/$APPNAME/Contents/PlugIns/libfilter_globalregistration.so -executable=$INSTALL_PATH/$APPNAME/Contents/PlugIns/libfilter_isoparametrization.so -executable=$INSTALL_PATH/$APPNAME/Contents/PlugIns/libfilter_screened_poisson.so -executable=$INSTALL_PATH/$APPNAME/Contents/PlugIns/libfilter_sketchfab.so +if [ "$NOTARIZE" = true ] ; then + bash $SCRIPTS_PATH/internal/2c_notarize_appbundle.sh -i=$INSTALL_PATH -nu=$NOTAR_USER -nt=$NOTAR_TEAM_ID -np=$NOTAR_PASSWORD + + echo "======= AppBundle Notarized =======" fi + +bash $SCRIPTS_PATH/internal/2d_dmg.sh -i=$INSTALL_PATH -p=$PACKAGES_PATH + +echo "======= DMG Created =======" \ No newline at end of file diff --git a/scripts/macOS/3_dmg.sh b/scripts/macOS/3_dmg.sh deleted file mode 100755 index 328886a08..000000000 --- a/scripts/macOS/3_dmg.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash -# this is a script shell for setting up the application DMG for MacOS. -# Requires a properly built and deployed meshlab (requires to run the -# macos_deploy.sh script first). -# -# Without given arguments, meshlab.app will be looked for in meshlab/distrib -# folder. MeshLab DMG will be placed in the same directory of meshlab.app. -# -# You can give as argument the DISTRIB_PATH containing meshlab.app. - -#realpath function -realpath() { - [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" -} - -SCRIPTS_PATH=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) -INSTALL_PATH=$SCRIPTS_PATH/../../src/install -ML_VERSION=$(cat $SCRIPTS_PATH/../../ML_VERSION) - -#checking for parameters -for i in "$@" -do -case $i in - -i=*|--install_path=*) - INSTALL_PATH="${i#*=}" - shift # past argument=value - ;; - --double_precision) - ML_VERSION=${ML_VERSION}d - shift # past argument=value - ;; - *) - # unknown option - ;; -esac -done - -if ! [ -e $INSTALL_PATH/meshlab.app -a -d $INSTALL_PATH/meshlab.app ] -then - echo "Started in the wrong dir: I have not found the meshlab.app" - exit -1 -fi - -SOURCE_PATH=$SCRIPTS_PATH/../../src - -# final step create the dmg using appdmg -# appdmg is installed with 'npm install -g appdmg'", -sed "s%DISTRIB_PATH%$INSTALL_PATH%g" $SCRIPTS_PATH/resources/meshlab_dmg_latest.json > $SCRIPTS_PATH/resources/meshlab_dmg_final.json -sed -i '' "s%SOURCE_PATH%$SOURCE_PATH%g" $SCRIPTS_PATH/resources/meshlab_dmg_final.json - -rm -f $INSTALL_PATH/*.dmg - -echo "Running appdmg" -appdmg $SCRIPTS_PATH/resources/meshlab_dmg_final.json $INSTALL_PATH/MeshLab$ML_VERSION.dmg - -rm $SCRIPTS_PATH/resources/meshlab_dmg_final.json - -#at this point, distrib folder contains a DMG MeshLab file -echo "distrib folder now contains a DMG file" diff --git a/scripts/macOS/README.md b/scripts/macOS/README.md index 6eb41a14e..b571b3258 100644 --- a/scripts/macOS/README.md +++ b/scripts/macOS/README.md @@ -1,37 +1,27 @@ # MacOS Scripts -This folder contains a series of scripts to build and deploy MeshLab under a MacOS environment. +This folder contains a series of scripts to build and deploy MeshLab under a MacOS x86_64 environment. -* `0_setup_env.sh`: this script installs all the required dependencies that are necessary to build MeshLab and to create its DMG in a MacOS machine (tested in 10.15 Catalina). It requires [homebrew](https://brew.sh/) installed; -* `1_build.sh`: this script builds MeshLab in a MacOS environment: - * it requires a properly set Qt environment (see `0_setup_env.sh`); - * takes as arguments: - * the build directory (default: `src/build`): `--build_path=path/to/build` - * the install directory (default: `src/install`): `--install_path=path/to/install` - * the number of cores used to build MeshLab (default: `-j4`)` - * the possibility to build MeshLab with double precision scalar: `--double_precision` -* `2_deploy.sh`: this script makes portable a `meshlab.app` appdir. Takes as arguments: - * the path where the output install path of the `1_build.sh` script is placed (default: `src/install`): `--install_path=path/to/install` -* `3_dmg.sh`: this script generates a [DMG](https://en.wikipedia.org/wiki/Apple_Disk_Image) that can be used to install MeshLab. Takes as arguments: - * the path where the install path of the `2_deploy.sh` script is placed (default: `src/install`): `--install_path=path/to/install` - * if MeshLab has been built with double precision scalar, add: `--double_precision` -* `make_it.sh`: this script builds, deploys and generates a [DMG](https://en.wikipedia.org/wiki/Apple_Disk_Image) that can be used to install MeshLab. Arguments are the same of the `1_build.sh` script. +Arm (Apple M1) is still not supported. It will be supported soon. +## Note about Qt -## Examples +MeshLab requires Qt 5.15. You can both install Qt5 using `brew` or manually in your system. +If you install Qt manually. you can then give the path of the Qt installation directory to the various scripts, or you can add Qt to your `LD_LIBRARY_PATH`. -Building MeshLab on a clean MacOS environment (build placed in `meshlab/src/build`): +The `0_setup_env.sh` script won't install qt from `brew` if you pass the argument `dont_install_qt`. - git clone --recursive https://github.com/cnr-isti-vclab/meshlab - sh meshlab/scripts/macOS/0_setup_env.sh - sh meshlab/scripts/macOS/1_build.sh +## Dependencies -Building and generating a DMG on a clean MacOS environment: -* build directory: `./meshlab-build` -* install directory: `./meshlab-install` -* DMG path: `./` +Dependencies are automatically installed by the `0_setup_env.sh` script, which uses [`brew`](https://brew.sh/) as package manager. +Be sure to have `brew` installed before running this script. -``` -git clone --recursive https://github.com/cnr-isti-vclab/meshlab -sh meshlab/scripts/macOS/0_setup_env.sh -sh meshlab/scripts/macOS/make_it.sh --build_path="./meshlab-build" --install_path="./meshlab-install" -``` +Libraries installed by the `0_setup_env.sh` are the following: + - Required by MeshLab: + - `coreutils` (required by these scripts) + - `cmake` + - `ninja` + - `libomp` + - `node` (for package stage, to download appdmg) + - Optional: + - `xerces-c` (required by libe57) + - `cgal` (required by several MeshLab plugins) \ No newline at end of file diff --git a/scripts/macOS/internal/2a_appbundle.sh b/scripts/macOS/internal/2a_appbundle.sh new file mode 100644 index 000000000..fb3dfb4c7 --- /dev/null +++ b/scripts/macOS/internal/2a_appbundle.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/.. + +INSTALL_PATH=$SCRIPTS_PATH/../../install +QT_DIR="" +APPNAME="meshlab.app" + +#checking for parameters +for i in "$@" +do +case $i in + -i=*|--install_path=*) + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -qt=*|--qt_dir=*) + QT_DIR=${i#*=}/bin/ + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +ARGUMENTS="" + +for plugin in $INSTALL_PATH/$APPNAME/Contents/PlugIns/*.so +do + ARGUMENTS="${ARGUMENTS} -executable=${plugin}" +done + +${QT_DIR}macdeployqt $INSTALL_PATH/$APPNAME \ + $ARGUMENTS + +# remove everything from install path, except the appbundle +cd $INSTALL_PATH +ls | grep -xv "${APPNAME}" | xargs rm \ No newline at end of file diff --git a/scripts/macOS/internal/2b_sign_appbundle.sh b/scripts/macOS/internal/2b_sign_appbundle.sh new file mode 100644 index 000000000..268d6c456 --- /dev/null +++ b/scripts/macOS/internal/2b_sign_appbundle.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/.. + +INSTALL_PATH=$SCRIPTS_PATH/../../install +CERT_ID="" + +#checking for parameters +for i in "$@" +do +case $i in + -i=*|--install_path=*) + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -ci=*|--cert_id=*) + CERT_ID="${i#*=}" + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +codesign --options "runtime" --timestamp --force --deep --sign $CERT_ID $INSTALL_PATH/meshlab.app + +spctl -a -vvv $INSTALL_PATH/meshlab.app \ No newline at end of file diff --git a/scripts/macOS/internal/2c_notarize_appbundle.sh b/scripts/macOS/internal/2c_notarize_appbundle.sh new file mode 100644 index 000000000..3eb6346ca --- /dev/null +++ b/scripts/macOS/internal/2c_notarize_appbundle.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/.. + +INSTALL_PATH=$SCRIPTS_PATH/../../install +NOTAR_USER="" +NOTAR_PASSWORD="" +NOTAR_TEAM_ID="" + +#checking for parameters +for i in "$@" +do +case $i in + -i=*|--install_path=*) + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -nu=*|--notarization_user=*) + NOTAR_USER="${i#*=}" + shift # past argument=value + ;; + -nt=*|--notarization_team=*) + NOTAR_TEAM_ID="${i#*=}" + shift # past argument=value + ;; + -np=*|--notarization_pssw=*) + NOTAR_PASSWORD="${i#*=}" + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +xcrun notarytool store-credentials "notarytool-profile" --apple-id $NOTAR_USER --team-id $NOTAR_TEAM_ID --password $NOTAR_PASSWORD + +ditto -c -k --keepParent "$INSTALL_PATH/meshlab.app" "$INSTALL_PATH/notarization.zip" + +xcrun notarytool submit "install/notarization.zip" --keychain-profile "notarytool-profile" --wait + +xcrun stapler staple "$INSTALL_PATH/meshlab.app" + +rm -rf $INSTALL_PATH/notarization.zip \ No newline at end of file diff --git a/scripts/macOS/internal/2d_dmg.sh b/scripts/macOS/internal/2d_dmg.sh new file mode 100644 index 000000000..7a5495d15 --- /dev/null +++ b/scripts/macOS/internal/2d_dmg.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +SCRIPTS_PATH="$(dirname "$(realpath "$0")")"/.. +RESOURCES_PATH=$SCRIPTS_PATH/../../resources +INSTALL_PATH=$SCRIPTS_PATH/../../install +PACKAGES_PATH=$SCRIPTS_PATH/../../packages + +#checking for parameters +for i in "$@" +do +case $i in + -i=*|--install_path=*) + INSTALL_PATH="${i#*=}" + shift # past argument=value + ;; + -p=*|--packages_path=*) + PACKAGES_PATH="${i#*=}" + shift # past argument=value + ;; + *) + # unknown option + ;; +esac +done + +if ! [ -e $INSTALL_PATH/meshlab.app -a -d $INSTALL_PATH/meshlab.app ] +then + echo "Started in the wrong dir: I have not found the meshlab.app" + exit -1 +fi + +#get version +IFS=' ' #space delimiter +STR_VERSION=$($INSTALL_PATH/meshlab.app/Contents/MacOS/meshlab --version) +read -a strarr <<< "$STR_VERSION" +ML_VERSION=${strarr[1]} #get the meshlab version from the string + +# final step create the dmg using appdmg +# appdmg is installed with 'npm install -g appdmg'", +sed "s%DISTRIB_PATH%$INSTALL_PATH%g" $RESOURCES_PATH/macos/meshlab_dmg_latest.json > $RESOURCES_PATH/macos/meshlab_dmg_final.json +sed -i '' "s%ML_VERSION%$ML_VERSION%g" $RESOURCES_PATH/macos/meshlab_dmg_final.json +sed -i '' "s%RESOURCES_PATH%$RESOURCES_PATH%g" $RESOURCES_PATH/macos/meshlab_dmg_final.json + +rm -f $INSTALL_PATH/*.dmg + +mv $INSTALL_PATH/meshlab.app $INSTALL_PATH/MeshLab$ML_VERSION.app + +mkdir $PACKAGES_PATH + +appdmg $RESOURCES_PATH/macos/meshlab_dmg_final.json $PACKAGES_PATH/MeshLab$ML_VERSION-macos.dmg + +rm $RESOURCES_PATH/macos/meshlab_dmg_final.json \ No newline at end of file diff --git a/scripts/macOS/make_it.sh b/scripts/macOS/make_it.sh index 3311f222f..a28a311ff 100644 --- a/scripts/macOS/make_it.sh +++ b/scripts/macOS/make_it.sh @@ -1,54 +1,54 @@ #!/bin/bash -# This is a script shell for compiling and deploying MeshLab in a MacOS environment. -# -# Requires a Qt environment which is set-up properly, and an accessible -# cmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src/build, -# the folder meshlab/src/install will contain meshlab.app and -# the DMG will be placed in meshlab/src. -# -# You can give as argument the build path, the install path (that will contain -# the portable version of MeshLab), and the number of cores to use to build MeshLab -# (default: 4). -# The DMG will be placed in the parent directory of the install path. -# -# Example of call: -# bash make_it.sh --build_path=path/to/build --install_path=path/to/install -j8 SCRIPTS_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -SOURCE_PATH=$SCRIPTS_PATH/../../src +SOURCE_PATH=$SCRIPTS_PATH/../.. BUILD_PATH=$SOURCE_PATH/build INSTALL_PATH=$SOURCE_PATH/install -CORES="-j4" +PACKAGES_PATH=$SOURCE_PATH/packages + DOUBLE_PRECISION_OPTION="" +NIGHTLY_OPTION="" +QT_DIR_OPTION="" +CCACHE_OPTION="" #check parameters for i in "$@" do case $i in -b=*|--build_path=*) - BUILD_PATH="${i#*=}" - shift # past argument=value - ;; + BUILD_PATH="${i#*=}" + shift # past argument=value + ;; -i=*|--install_path=*) - INSTALL_PATH="${i#*=}"/usr/ - shift # past argument=value - ;; - -j*) - CORES=$i - shift # past argument=value - ;; + INSTALL_PATH="${i#*=}"/usr/ + shift # past argument=value + ;; + -p=*|--packages_path=*) + PACKAGES_PATH="${i#*=}" + shift # past argument=value + ;; --double_precision) - DOUBLE_PRECISION_OPTION="--double_precision" - shift # past argument=value - ;; + DOUBLE_PRECISION_OPTION="--double_precision" + shift # past argument=value + ;; + -n|--nightly) + NIGHTLY_OPTION="--nightly" + shift # past argument=value + ;; + -qt=*|--qt_dir=*) + QT_DIR_OPTION=-qt=${i#*=} + shift # past argument=value + ;; + --ccache) + CCACHE_OPTION="--ccache" + shift # past argument=value + ;; *) - # unknown option - ;; + # unknown option + ;; esac done -sh $SCRIPTS_PATH/1_build.sh -b=$BUILD_PATH -i=$INSTALL_PATH $DOUBLE_PRECISION_OPTION $CORES -sh $SCRIPTS_PATH/2_deploy.sh -i=$INSTALL_PATH -sh $SCRIPTS_PATH/3_dmg.sh -i=$INSTALL_PATH $DOUBLE_PRECISION_OPTION +bash $SCRIPTS_PATH/1_build.sh -b=$BUILD_PATH -i=$INSTALL_PATH $NIGHTLY_OPTION $DOUBLE_PRECISION_OPTION $QT_DIR_OPTION $CCACHE_OPTION +bash $SCRIPTS_PATH/2_deploy.sh -i=$INSTALL_PATH -p=$PACKAGES_PATH $QT_DIR_OPTION + diff --git a/scripts/macOS/qmake/macos_build.sh b/scripts/macOS/qmake/macos_build.sh deleted file mode 100644 index 1e1560566..000000000 --- a/scripts/macOS/qmake/macos_build.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -# this is a script shell for compiling meshlab in a MacOS environment. -# Requires a Qt environment which is set-up properly from brew, and an accessible -# qmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src -# directory, and binaries will be placed in meshlab/distrib. -# -# You can give as argument the BUILD_PATH, and meshlab binaries will be -# then placed inside BUILD_PATH/distrib. - -#realpath function -realpath() { - [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" -} - -#checking for parameters -if [ "$#" -eq 0 ] -then - BUILD_PATH="../../../src" -else - BUILD_PATH=$( realpath $1 ) -fi - -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -cd $DIR #move to script directory - -if ! [ -d $BUILD_PATH ] -then - mkdir $BUILD_PATH -fi - -echo "Build path is: " $(realpath $BUILD_PATH) -SOURCE_PATH=$PWD/../../../src - -cd $BUILD_PATH -qmake $SOURCE_PATH/meshlab.pro -make -j4 diff --git a/scripts/macOS/qmake/macos_build_debug.sh b/scripts/macOS/qmake/macos_build_debug.sh deleted file mode 100644 index 8e0aa622c..000000000 --- a/scripts/macOS/qmake/macos_build_debug.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -# this is a script shell for compiling meshlab in a MacOS environment. -# Requires a Qt environment which is set-up properly from brew, and an accessible -# qmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src -# directory, and binaries will be placed in meshlab/distrib. -# -# You can give as argument the BUILD_PATH, and meshlab binaries will be -# then placed inside BUILD_PATH/distrib. - -#realpath function -realpath() { - [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" -} - -#checking for parameters -if [ "$#" -eq 0 ] -then - BUILD_PATH="../../../src" -else - BUILD_PATH=$( realpath $1 ) -fi - -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -cd $DIR #move to script directory - -if ! [ -d $BUILD_PATH ] -then - mkdir $BUILD_PATH -fi - -echo "Build path is: " $(realpath $BUILD_PATH) -SOURCE_PATH=$PWD/../../../src - -cd $BUILD_PATH -qmake $SOURCE_PATH/meshlab.pro CONFIG+=debug -make -j4 diff --git a/scripts/macOS/qmake/macos_build_meshlab_mini.sh b/scripts/macOS/qmake/macos_build_meshlab_mini.sh deleted file mode 100644 index 8e4f89c0f..000000000 --- a/scripts/macOS/qmake/macos_build_meshlab_mini.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -# this is a script shell for compiling meshlab in a MacOS environment. -# Requires a Qt environment which is set-up properly from brew, and an accessible -# qmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src -# directory, and binaries will be placed in meshlab/distrib. -# -# You can give as argument the BUILD_PATH, and meshlab binaries will be -# then placed inside BUILD_PATH/distrib. - -#realpath function -realpath() { - [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" -} - -#checking for parameters -if [ "$#" -eq 0 ] -then - BUILD_PATH="../../../src" -else - BUILD_PATH=$( realpath $1 ) -fi - -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -cd $DIR #move to script directory - -if ! [ -d $BUILD_PATH ] -then - mkdir $BUILD_PATH -fi - -echo "Build path is: " $(realpath $BUILD_PATH) -SOURCE_PATH=$PWD/../../../src - -cd $BUILD_PATH -qmake $SOURCE_PATH/meshlab.pro "CONFIG+=meshlab_mini" -make -j4 diff --git a/scripts/macOS/qmake/macos_deploy.sh b/scripts/macOS/qmake/macos_deploy.sh deleted file mode 100755 index 1306a1389..000000000 --- a/scripts/macOS/qmake/macos_deploy.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash -# this is a script shell for deploying a meshlab-portable app. -# Requires a properly built meshlab. -# -# Without given arguments, the folder that will be deployed is meshlab/distrib. -# -# You can give as argument the DISTRIB_PATH. -# -# After running this script, $DISTRIB_PATH/meshlab.app will be a portable meshlab application. - -#realpath function -realpath() { - [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" -} - -#checking for parameters -if [ "$#" -eq 0 ] -then - DISTRIB_PATH="../../../distrib" -else - DISTRIB_PATH=$( realpath $1 ) -fi - -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -cd $DIR #move to script directory - -SOURCE_PATH=$PWD/../../../src - -APPNAME="meshlab.app" - -echo "Hopefully I should find" $DISTRIB_PATH/$APPNAME - -if ! [ -e $DISTRIB_PATH/$APPNAME -a -d $DISTRIB_PATH/$APPNAME ] -then - echo "Started in the wrong dir: I have not found the meshlab.app" - exit -1 -fi - -echo "Copying the built app into the bundle" -mkdir $DISTRIB_PATH/$APPNAME/Contents/PlugIns -# copy the files icons into the app. -cp $SOURCE_PATH/meshlab/images/meshlab_obj.icns $DISTRIB_PATH/$APPNAME/Contents/Resources - -for x in $DISTRIB_PATH/plugins/*.dylib -do -cp $x $DISTRIB_PATH/$APPNAME/Contents/PlugIns/ -done - -#copy libIFX libraries and change rpath u3d plugin -cp -a $DISTRIB_PATH/lib/meshlab/libIFX* $DISTRIB_PATH/$APPNAME/Contents/Frameworks -rm $DISTRIB_PATH/$APPNAME/Contents/Frameworks/libIFXCoreStatic.a -install_name_tool -change libIFXCore.1.so @rpath/libIFXCore.1.so $DISTRIB_PATH/$APPNAME/Contents/PlugIns/libio_u3d.dylib -install_name_tool -change libIFXExporting.1.so @rpath/libIFXExporting.1.so $DISTRIB_PATH/$APPNAME/Contents/PlugIns/libio_u3d.dylib -install_name_tool -change libIFXScheduling.1.so @rpath/libIFXScheduling.1.so $DISTRIB_PATH/$APPNAME/Contents/PlugIns/libio_u3d.dylib - -echo 'Copying other files' - -#shaders -mkdir $DISTRIB_PATH/$APPNAME/Contents/shaders -cp -r $DISTRIB_PATH/shaders/*.gdp $DISTRIB_PATH/shaders/*.vert $DISTRIB_PATH/shaders/*.frag $DISTRIB_PATH/shaders/*.txt $DISTRIB_PATH/$APPNAME/Contents/shaders - -#added rendermonkey shaders -mkdir $DISTRIB_PATH/$APPNAME/Contents/shaders/shadersrm -cp $DISTRIB_PATH/shaders/shadersrm/*.rfx $DISTRIB_PATH/$APPNAME/Contents/shaders/shadersrm -#added shadowmapping shaders -cp -r $DISTRIB_PATH/shaders/decorate_shadow $DISTRIB_PATH/$APPNAME/Contents/shaders - -echo "Changing the paths of the qt component frameworks using the qt tool macdeployqt" - -if [ -e $QTDIR/bin/macdeployqt ] -then - $QTDIR/bin/macdeployqt $DISTRIB_PATH/$APPNAME -executable=$DISTRIB_PATH/$APPNAME/Contents/MacOS/meshlabserver -else - macdeployqt $DISTRIB_PATH/$APPNAME -executable=$DISTRIB_PATH/$APPNAME/Contents/MacOS/meshlabserver -fi diff --git a/scripts/macOS/qmake/macos_dmg.sh b/scripts/macOS/qmake/macos_dmg.sh deleted file mode 100755 index e59d97fb2..000000000 --- a/scripts/macOS/qmake/macos_dmg.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash -# this is a script shell for setting up the application DMG for MacOS. -# Requires a properly built and deployed meshlab (requires to run the -# macos_deploy.sh script first). -# -# Without given arguments, meshlab.app will be looked for in meshlab/distrib -# folder. MeshLab DMG will be placed in the same directory of meshlab.app. -# -# You can give as argument the DISTRIB_PATH containing meshlab.app. - -#realpath function -realpath() { - [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" -} - -#checking for parameters -if [ "$#" -eq 0 ] -then - DISTRIB_PATH="../../../distrib" -else - DISTRIB_PATH=$( realpath $1 ) -fi - -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -cd $DIR #move to script directory - -DISTRIB_PATH=$( realpath $DISTRIB_PATH) - -if ! [ -e $DISTRIB_PATH/meshlab.app -a -d $DISTRIB_PATH/meshlab.app ] -then - echo "Started in the wrong dir: I have not found the meshlab.app" - exit -1 -fi - -SOURCE_PATH=$DIR/../../../src - -# final step create the dmg using appdmg -# appdmg is installed with 'npm install -g appdmg'", -sed "s%DISTRIB_PATH%$DISTRIB_PATH%g" ../resources/meshlab_dmg_latest.json > ../resources/meshlab_dmg_final.json -sed -i '' "s%SOURCE_PATH%$SOURCE_PATH%g" ../resources/meshlab_dmg_final.json - -rm -f $DISTRIB_PATH/*.dmg - -echo "Running appdmg" -appdmg ../resources/meshlab_dmg_final.json $DISTRIB_PATH/MeshLab$(cat ../../../ML_VERSION).dmg - -#at this point, distrib folder contains a DMG MeshLab file -echo "distrib folder now contains a DMG file" diff --git a/scripts/macOS/qmake/macos_make_it.sh b/scripts/macOS/qmake/macos_make_it.sh deleted file mode 100644 index 6d5814bdd..000000000 --- a/scripts/macOS/qmake/macos_make_it.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -# this is a script shell for compiling and deploying meshlab in a MacOS environment. -# -# Requires a Qt environment which is set-up properly, and an accessible -# qmake binary. -# -# Without given arguments, MeshLab will be built in the meshlab/src -# directory, and binaries and AppImage will be placed in meshlab/distrib. -# -# You can give as argument the BUILD_PATH, and meshlab binaries and -# AppImage will be then placed inside BUILD_PATH/distrib. - -#realpath function -realpath() { - [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" -} - -#checking for parameters -if [ "$#" -eq 0 ] -then - BUILD_PATH="../../../src" - DISTRIB_PATH="../../../distrib" -else - BUILD_PATH=$( realpath $1 ) - DISTRIB_PATH=$BUILD_PATH/distrib -fi - -DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -cd $DIR #move to script directory - -sh macos_build.sh $BUILD_PATH -sh macos_deploy.sh $DISTRIB_PATH -sh macos_dmg.sh $DISTRIB_PATH diff --git a/scripts/meshlab.png b/scripts/meshlab.png deleted file mode 100644 index 2f787916d..000000000 Binary files a/scripts/meshlab.png and /dev/null differ diff --git a/scripts/qt.conf b/scripts/qt.conf deleted file mode 100644 index 1c7b73536..000000000 --- a/scripts/qt.conf +++ /dev/null @@ -1,2 +0,0 @@ -[Paths] -Plugins = plugins diff --git a/snapcraft.yaml b/snapcraft.yaml index 53e7ff4e1..30dabb63d 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -1,7 +1,7 @@ # Known to build in Ubuntu 18.04, 20.04 name: meshlab base: core18 -version: '2020.12' +version: '2022.02' summary: MeshLab description: | The open source system for processing and editing 3D triangular meshes. @@ -18,9 +18,14 @@ apps: meshlab: command: AppRun extensions: [kde-neon] - plugs: [home, opengl, removable-media] desktop: usr/share/applications/meshlab.desktop - + environment: + DISABLE_WAYLAND: 1 + plugs: + - home + - opengl + - removable-media + - mount-observe parts: meshlab: @@ -43,6 +48,9 @@ parts: - patchelf - rsync - libqt5opengl5-dev + - libcgal-dev + - libboost-all-dev + - libxerces-c-dev stage-packages: - lib3ds-1-3 - libgomp1 diff --git a/src/.clang-format b/src/.clang-format new file mode 100644 index 000000000..57e9e430c --- /dev/null +++ b/src/.clang-format @@ -0,0 +1,75 @@ +--- +BasedOnStyle: LLVM +AccessModifierOffset: -4 +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: DontAlign +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: InlineOnly +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterClass: true + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: false +BreakConstructorInitializers: AfterColon +BreakInheritanceList: AfterColon +BreakStringLiterals: true +ColumnLimit: 100 +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 8 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +ExperimentalAutoDetectBinPacking: false +ForEachMacros: + [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeBlocks: Preserve +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +Language: Cpp +NamespaceIndentation: None +PointerAlignment: Left +ReflowComments: true +SpaceAfterCStyleCast: true +SpaceAfterTemplateKeyword: false +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: ForContinuationAndIndentation diff --git a/src/.qmake.conf b/src/.qmake.conf deleted file mode 100644 index b3d5125df..000000000 --- a/src/.qmake.conf +++ /dev/null @@ -1,17 +0,0 @@ -MESHLAB_SOURCE_DIRECTORY=$$PWD -MESHLAB_BUILD_DIRECTORY=$$shadowed($$PWD) -MESHLAB_EXTERNAL_DIRECTORY=$$MESHLAB_SOURCE_DIRECTORY/external - -#if we are using shadow build, distrib will be inside the shadow build -!equals(MESHLAB_BUILD_DIRECTORY, $$PWD) { - MESHLAB_DISTRIB_DIRECTORY=$$shadowed($$PWD)/distrib -} - -#if we are not using shadow build, distrib will be at the same level of -#src directory -equals(MESHLAB_BUILD_DIRECTORY, $$PWD) { - MESHLAB_DISTRIB_DIRECTORY=$$MESHLAB_SOURCE_DIRECTORY/../distrib -} - -MESHLAB_DISTRIB_EXT_DIRECTORY=$$MESHLAB_DISTRIB_DIRECTORY/lib/meshlab -MESHLAB_DISTRIB_PLUGINS_DIRECTORY=$$MESHLAB_DISTRIB_DIRECTORY/plugins diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 48428d4ac..87d461de4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,115 +1,93 @@ # Copyright 2019, 2020, Collabora, Ltd. -# Copyright 2019, 2020, Visual Computing Lab, ISTI - Italian National Research Council +# Copyright 2019, 2021, Visual Computing Lab, ISTI - Italian National Research Council # SPDX-License-Identifier: BSL-1.0 -cmake_minimum_required(VERSION 3.9) -project(MeshLab) - -# Prefer GLVND -if(POLICY CMP0072) - cmake_policy(SET CMP0072 NEW) -endif() - -### Build options -option(BUILD_MINI "Build only a minimal set of plugins" OFF) -option(BUILD_SERVER "Build a command-line server application" OFF) -option(BUILD_STRICT "Strictly enforce resolution of all symbols" ON) -option(BUILD_WITH_DOUBLE_SCALAR "Use double type instead of float type for scalars" OFF) - ### Dependencies list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") -message(STATUS "Searching for required components") +include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/meshlab_global_settings.cmake" NO_POLICY_SCOPE) +include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/meshlab_tools.cmake") + +#message(STATUS "Searching for required components") find_package(OpenGL REQUIRED) find_package( Qt5 COMPONENTS OpenGL Xml Network REQUIRED) -find_package(OpenMP) -if (NOT BUILD_MINI) - find_package(Qt5Qml) +if (Qt5_VERSION VERSION_LESS 5.15.0) + message(FATAL_ERROR "Minimum supported Qt5 version is 5.15!") endif() +find_package(OpenMP) +find_package(Threads) message(STATUS "Searching for required components with bundled fallback") find_package(GLEW) find_package(Eigen3) +set(MESHLAB_RESOURCES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../resources) + ### Build directories -set(MESHLAB_BUILD_DISTRIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/distrib) -set(MESHLAB_LIB_OUTPUT_DIR ${MESHLAB_BUILD_DISTRIB_DIR}) -set(MESHLAB_PLUGIN_OUTPUT_DIR ${MESHLAB_BUILD_DISTRIB_DIR}/plugins) -set(MESHLAB_SHADER_OUTPUT_DIR ${MESHLAB_BUILD_DISTRIB_DIR}/shaders) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${MESHLAB_BUILD_DISTRIB_DIR}) +if (MESHLAB_USE_DEFAULT_BUILD_AND_INSTALL_DIRS) # otherwise, we assume that all these dirs are defined in parent dir + set(MESHLAB_BUILD_DISTRIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/distrib) + set(MESHLAB_LIB_OUTPUT_DIR ${MESHLAB_BUILD_DISTRIB_DIR}) + set(MESHLAB_PLUGIN_OUTPUT_DIR ${MESHLAB_BUILD_DISTRIB_DIR}/plugins) + set(MESHLAB_SHADER_OUTPUT_DIR ${MESHLAB_BUILD_DISTRIB_DIR}/shaders) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${MESHLAB_BUILD_DISTRIB_DIR}) -### Build settings -set(CMAKE_C_STANDARD 99) -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -set(CMAKE_OSX_DEPLOYMENT_TARGET "10.11" CACHE STRING "Minimum OS X deployment version" FORCE) - -### Settings needed for both "external" and internal code -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set_property(GLOBAL PROPERTY USE_FOLDERS ON) - -### Build Settings -if (BUILD_WITH_DOUBLE_SCALAR) - message(STATUS "Building with double precision") - add_definitions(-DMESHLAB_SCALAR=double) -else() - message(STATUS "Building with single precision") - add_definitions(-DMESHLAB_SCALAR=float) -endif() - -if(WIN32) - add_definitions(-DNOMINMAX) - if(MSVC) - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + ### Install directories + if(WIN32 OR APPLE) + set(INSTALL_TO_UNIX_LAYOUT OFF) + else() + set(INSTALL_TO_UNIX_LAYOUT ON) + endif() + include(GNUInstallDirs) + if(INSTALL_TO_UNIX_LAYOUT) + set(MESHLAB_BIN_INSTALL_DIR ${CMAKE_INSTALL_BINDIR}) + set(MESHLAB_LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/meshlab) + set(MESHLAB_PLUGIN_INSTALL_DIR ${MESHLAB_LIB_INSTALL_DIR}/plugins) + set(MESHLAB_SHADER_INSTALL_DIR ${CMAKE_INSTALL_DATAROOTDIR}/meshlab/shaders) + elseif(APPLE) + set(MESHLAB_BIN_INSTALL_DIR .) + set(MESHLAB_LIB_INSTALL_DIR meshlab.app/Contents/Frameworks) + set(MESHLAB_PLUGIN_INSTALL_DIR meshlab.app/Contents/PlugIns) + set(MESHLAB_SHADER_INSTALL_DIR meshlab.app/Contents/shaders) + else() + set(MESHLAB_BIN_INSTALL_DIR .) + set(MESHLAB_LIB_INSTALL_DIR .) + set(MESHLAB_PLUGIN_INSTALL_DIR plugins) + set(MESHLAB_SHADER_INSTALL_DIR shaders) endif() -endif() -if(BUILD_STRICT AND NOT MSVC AND NOT APPLE) - # Make sure that our shared libraries were appropriately linked - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined") -endif() + ### Install Settings + if (NOT APPLE) + set(CMAKE_INSTALL_RPATH $ORIGIN/../${MESHLAB_LIB_INSTALL_DIR}) + else() + SET(CMAKE_INSTALL_RPATH @executable_path/../Frameworks) + endif() -### Install directories -if(WIN32 OR APPLE) - set(INSTALL_TO_UNIX_LAYOUT OFF) -else() - set(INSTALL_TO_UNIX_LAYOUT ON) -endif() -include(GNUInstallDirs) -if(INSTALL_TO_UNIX_LAYOUT) - set(MESHLAB_BIN_INSTALL_DIR ${CMAKE_INSTALL_BINDIR}) - set(MESHLAB_LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/meshlab) - set(MESHLAB_PLUGIN_INSTALL_DIR ${MESHLAB_LIB_INSTALL_DIR}/plugins) - set(MESHLAB_SHADER_INSTALL_DIR ${CMAKE_INSTALL_DATAROOTDIR}/meshlab/shaders) -elseif(APPLE) - set(MESHLAB_BIN_INSTALL_DIR .) - set(MESHLAB_LIB_INSTALL_DIR meshlab.app/Contents/Frameworks) - set(MESHLAB_PLUGIN_INSTALL_DIR meshlab.app/Contents/PlugIns) - set(MESHLAB_SHADER_INSTALL_DIR meshlab.app/Contents/shaders) -else() - set(MESHLAB_BIN_INSTALL_DIR .) - set(MESHLAB_LIB_INSTALL_DIR .) - set(MESHLAB_PLUGIN_INSTALL_DIR plugins) - set(MESHLAB_SHADER_INSTALL_DIR shaders) -endif() - -### Install Settings -if (NOT APPLE) - set(CMAKE_INSTALL_RPATH $ORIGIN/../${MESHLAB_LIB_INSTALL_DIR};$ORIGIN/../${CMAKE_INSTALL_LIBDIR}) -else() - SET(CMAKE_INSTALL_RPATH $ORIGIN/../Frameworks) + get_directory_property(hasParent PARENT_DIRECTORY) + if(hasParent) + set(MESHLAB_PLUGIN_OUTPUT_DIR ${MESHLAB_PLUGIN_OUTPUT_DIR} PARENT_SCOPE) + set(MESHLAB_PLUGIN_INSTALL_DIR ${MESHLAB_PLUGIN_INSTALL_DIR} PARENT_SCOPE) + endif() endif() ### Enter subdirectories # VCGLib -- required -if(NOT VCGDIR) +if (VCGDIR) # VCGDIR exists - using custom user vcglib path + if(EXISTS ${VCGDIR}) + add_subdirectory(${VCGDIR} {CMAKE_CURRENT_BINARY_DIR}/vcglib) + message(STATUS "- VCGLib - using custom VCGDIR path library") + else() + set(VCGDIR NOTFOUND) + endif() +else() get_filename_component(VCGDIR "${CMAKE_CURRENT_LIST_DIR}/vcglib" ABSOLUTE) - if(NOT EXISTS ${VCGDIR}) + if(EXISTS ${VCGDIR}) + add_subdirectory(${VCGDIR}) + message(STATUS "- VCGLib - using bundled source") + else() set(VCGDIR NOTFOUND) endif() endif() @@ -117,48 +95,41 @@ set(VCGDIR "${VCGDIR}") if(NOT VCGDIR) message(FATAL_ERROR "VCGLib not found. Please clone recursively the MeshLab repo.") +else () + message(STATUS "- VCGLib directory: " ${VCGDIR}) endif() - # External set(EXTERNAL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external) -include(${EXTERNAL_DIR}/external_common.cmake) add_subdirectory(${EXTERNAL_DIR}) -# Start automoc/autouic/autorcc -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTORCC ON) - add_subdirectory(common) -add_subdirectory(meshlab) -if(BUILD_SERVER) - add_subdirectory(meshlabserver) -endif() -if(WIN32 AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/use_cpu_opengl") - add_subdirectory(use_cpu_opengl) +add_subdirectory(common_gui) + +if (NOT MESHLAB_BUILD_ONLY_LIBRARIES) + add_subdirectory(meshlab) + if(WIN32 AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/use_cpu_opengl") + add_subdirectory(use_cpu_opengl) + endif() + + # Clear RPATH before adding plugins + set(CMAKE_INSTALL_RPATH) endif() -# Clear RPATH before adding plugins -set(CMAKE_INSTALL_RPATH) + ### Plugin subdirectories -if(BUILD_MINI) +if(NOT DEFINED MESHLAB_PLUGINS) # it may be already defined in parent directory set(MESHLAB_PLUGINS - meshlabplugins/io_base - meshlabplugins/filter_meshing - meshlabplugins/decorate_base - meshlabplugins/filter_measure - ) -else() - set(MESHLAB_PLUGINS - # IOMesh plugins + # IO plugins meshlabplugins/io_3ds meshlabplugins/io_base meshlabplugins/io_bre meshlabplugins/io_collada meshlabplugins/io_ctm + meshlabplugins/io_e57 meshlabplugins/io_expe + meshlabplugins/io_gltf meshlabplugins/io_json meshlabplugins/io_pdb meshlabplugins/io_tri @@ -166,12 +137,8 @@ else() meshlabplugins/io_u3d meshlabplugins/io_x3d - # IORaster plugins - meshlabplugins/ioraster_base - # Filter plugins meshlabplugins/filter_sample - meshlabplugins/filter_sample_dyn meshlabplugins/filter_createiso meshlabplugins/filter_geodesic meshlabplugins/filter_sample_gpu @@ -181,19 +148,23 @@ else() meshlabplugins/filter_color_projection meshlabplugins/filter_colorproc meshlabplugins/filter_create - meshlabplugins/filter_csg + meshlabplugins/filter_cubization + meshlabplugins/filter_developability meshlabplugins/filter_dirt meshlabplugins/filter_fractal - meshlabplugins/filter_func - meshlabplugins/filter_globalregistration + meshlabplugins/filter_func meshlabplugins/filter_img_patch_param + meshlabplugins/filter_icp + meshlabplugins/filter_io_nxs meshlabplugins/filter_isoparametrization meshlabplugins/filter_layer meshlabplugins/filter_measure + meshlabplugins/filter_mesh_booleans meshlabplugins/filter_meshing meshlabplugins/filter_mls meshlabplugins/filter_mutualglobal meshlabplugins/filter_mutualinfo + meshlabplugins/filter_parametrization meshlabplugins/filter_plymc meshlabplugins/filter_qhull meshlabplugins/filter_quality @@ -204,6 +175,7 @@ else() meshlabplugins/filter_sketchfab meshlabplugins/filter_ssynth meshlabplugins/filter_texture + meshlabplugins/filter_texture_defragmentation meshlabplugins/filter_trioptimize meshlabplugins/filter_unsharp meshlabplugins/filter_voronoi @@ -248,45 +220,58 @@ endforeach() # This variable keeps track of the output filenames that need to be copied at build time set(COPIED_FILES) -# shaders -set(SHADER_BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../distrib/shaders") -file( - GLOB_RECURSE SHADERS - LIST_DIRECTORIES false - "${SHADER_BASE_DIR}/*.vert" - "${SHADER_BASE_DIR}/*.frag" - "${SHADER_BASE_DIR}/*.gdp") -foreach(FN ${SHADERS}) - get_filename_component(SRC_PATH ${FN} DIRECTORY) - get_filename_component(NAME_ONLY ${FN} NAME) - file(RELATIVE_PATH REL_DIR "${SHADER_BASE_DIR}" "${SRC_PATH}") - set(OUTFN "${MESHLAB_SHADER_OUTPUT_DIR}/${REL_DIR}/${NAME_ONLY}") - if(REL_DIR) - set(REL_DIR_MESSAGE "${REL_DIR} in ") - else() - set(REL_DIR_MESSAGE "") +if (NOT MESHLAB_BUILD_ONLY_LIBRARIES) + # shaders + set(SHADER_BASE_DIR "${MESHLAB_RESOURCES_DIR}/shaders") + file( + GLOB_RECURSE SHADERS + LIST_DIRECTORIES false + "${SHADER_BASE_DIR}/*.vert" + "${SHADER_BASE_DIR}/*.frag" + "${SHADER_BASE_DIR}/*.gdp") + foreach(FN ${SHADERS}) + get_filename_component(SRC_PATH ${FN} DIRECTORY) + get_filename_component(NAME_ONLY ${FN} NAME) + file(RELATIVE_PATH REL_DIR "${SHADER_BASE_DIR}" "${SRC_PATH}") + set(OUTFN "${MESHLAB_SHADER_OUTPUT_DIR}/${REL_DIR}/${NAME_ONLY}") + if(REL_DIR) + set(REL_DIR_MESSAGE "${REL_DIR} in ") + else() + set(REL_DIR_MESSAGE "") + endif() + add_custom_command( + OUTPUT ${OUTFN} + COMMAND ${CMAKE_COMMAND} -E make_directory "${MESHLAB_SHADER_OUTPUT_DIR}/${REL_DIR}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${FN}" "${OUTFN}" + COMMENT "Copying ${NAME_ONLY} to ${REL_DIR_MESSAGE}shader build directory" + VERBATIM + ) + install( + FILES ${FN} + DESTINATION ${MESHLAB_SHADER_INSTALL_DIR}/${REL_DIR} + COMPONENT Shaders + ) + list(APPEND COPIED_FILES "${OUTFN}") + endforeach() + + # Custom target - to trigger the execution of the custom commands above. + add_custom_target(copy-distrib-files ALL DEPENDS ${COPIED_FILES}) + + set_property(TARGET copy-distrib-files PROPERTY FOLDER Core) + + # be sure to remove all plugins (also old one that are not target anymore) when clean + set_property( + TARGET copy-distrib-files + APPEND + PROPERTY ADDITIONAL_CLEAN_FILES ${MESHLAB_PLUGIN_OUTPUT_DIR} + ) + + if(NOT WIN32 AND NOT APPLE) + install(FILES "${MESHLAB_RESOURCES_DIR}/linux/meshlab.desktop" DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications) + install(FILES "${MESHLAB_RESOURCES_DIR}/icons/meshlab.png" DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps) + endif() + if(WIN32) + install(FILES "${MESHLAB_RESOURCES_DIR}/icons/meshlab.png" DESTINATION ${MESHLAB_BIN_INSTALL_DIR}/) + install(FILES "${MESHLAB_RESOURCES_DIR}/icons/meshlab.ico" DESTINATION ${MESHLAB_BIN_INSTALL_DIR}/) endif() - add_custom_command( - OUTPUT ${OUTFN} - COMMAND ${CMAKE_COMMAND} -E make_directory "${MESHLAB_SHADER_OUTPUT_DIR}/${REL_DIR}" - COMMAND ${CMAKE_COMMAND} -E copy_if_different "${FN}" "${OUTFN}" - COMMENT "Copying ${NAME_ONLY} to ${REL_DIR_MESSAGE}shader build directory" - VERBATIM - ) - install( - FILES ${FN} - DESTINATION ${MESHLAB_SHADER_INSTALL_DIR}/${REL_DIR} - COMPONENT Shaders - ) - list(APPEND COPIED_FILES "${OUTFN}") -endforeach() - - -# Custom target - to trigger the execution of the custom commands above. -add_custom_target(copy-distrib-files ALL DEPENDS ${COPIED_FILES}) -set_property(TARGET copy-distrib-files PROPERTY FOLDER Core) - -if(NOT WIN32 AND NOT APPLE) - install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/Linux/resources/meshlab.desktop" DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications) - install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/meshlab.png" DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pixmaps) endif() diff --git a/src/README.md b/src/README.md index 9810e861a..6094a192c 100644 --- a/src/README.md +++ b/src/README.md @@ -5,44 +5,54 @@ In the `src` directory there are several folders containing all the source code The source code of MeshLab is structured in the following directories: * cmake: it contains a series of cmake scripts used to find external libraries; - * [external](https://github.com/cnr-isti-vclab/meshlab/tree/master/src/external): it contains a series of external libraries needed by several plugins. Some of these libraries are compiled before the compilation of meshlab, if a corresponding system library is not found and then linked; other are header-only libraries that are just included; + * [external](https://github.com/cnr-isti-vclab/meshlab/tree/master/src/external): it contains a series of cmake configuration files that will download external libraries needed by MeshLab and several plugins; * [common](https://github.com/cnr-isti-vclab/meshlab/tree/master/src/common): a series of utility classes and functions used by MeshLab and its plugins; * [meshlab](https://github.com/cnr-isti-vclab/meshlab/tree/master/src/meshlab): GUI and core of MeshLab; - * [meshlabserver](https://github.com/cnr-isti-vclab/meshlab/tree/master/src/meshlabserver): a tool that allows to compute mesh operations through command line; * [meshlabplugins](https://github.com/cnr-isti-vclab/meshlab/tree/master/src/meshlabplugins): all the plugins that can be added to MeshLab; - * [use_cpu_opengl](https://github.com/cnr-isti-vclab/meshlab/tree/master/src/use_cpu_opengl): a tool compiled only under windows that allows to use non-GPU accelerated OpenGL calls; + * [use_cpu_opengl](https://github.com/cnr-isti-vclab/meshlab/tree/master/src/use_cpu_opengl): a tool compiled only under windows that allows to use non-GPU accelerated OpenGL functions; * [vcglib](https://github.com/cnr-isti-vclab/meshlab/tree/master/src/vcglib): submodule containing the vcglib. ## Build MeshLab -MeshLab builds with the three major compilers: `gcc`, `clang`, and `msvc`. It requires [Qt](https://www.qt.io/) >= 5.12. +MeshLab builds with the three major compilers: `gcc`, `clang`, and `msvc`. It requires [Qt](https://www.qt.io/) 5.15, cmake and optionally ninja (required on windows). Only 64 bit is supported. After setting up the Qt environment: - git clone --recursive https://github.com/cnr-isti-vclab/meshlab - mkdir meshlab/src/build - cd meshlab/src/build - cmake .. - make +``` +git clone --recursive https://github.com/cnr-isti-vclab/meshlab +mkdir meshlab/build +cd meshlab/build +cmake .. +make +``` +or, using ninja (supported also on Windows): -You can also use [QtCreator](https://www.qt.io/product) to build meshlab: +``` +cmake -GNinja .. +ninja +``` -1. Install QtCreator and Qt >= 5.12; -2. Open `CMakeLists.txt` inside `src`; -3. Select your favourite shadow build directory; -4. Build meshlab. +You can also use [QtCreator](https://www.qt.io/product) to build MeshLab: -MeshLab has a plugin architecture and therefore all the plugins are compiled separately; some of them are harder to be compiled. Don't worry: if a plugin fails to compile, just remove it and you lose just that functionality. +1. Install QtCreator and Qt 5.15; +2. Open `CMakeLists.txt`; +4. Configure and build MeshLab. + +### External libraries + +External libraries required by plugins, if not found, are automatically downloaded by `cmake` during the configuration, and placed into `src/external/downloads`. ### Platform specific notes On __osx__ some plugins exploit openmp parallelism (screened poisson, isoparametrization) so you need a compiler supporting it and the clang provided by xcode does not support openmp. You can install all the required libraries by running the following command in a terminal: - brew install llvm libomp +``` +brew install libomp +``` -On __Windows__, we suggest to build meshlab using QtCreator. Before trying to build, you should: +On __Windows__, we suggest to build MeshLab using QtCreator. Before trying to build, you should: - * install VisualStudio >= 2017 with the C++ developement package; - * install Qt >= 5.12 and QtCreator. + * install VisualStudio >= 2017 with the C++ development package; + * install Qt 5.15 and QtCreator. -then, open the CMakeLists.txt file and try to build MeshLab. +then, open the CMakeLists.txt file and build MeshLab. diff --git a/src/cmake/FindQhull.cmake b/src/cmake/FindQhull.cmake deleted file mode 100644 index 07b1c8784..000000000 --- a/src/cmake/FindQhull.cmake +++ /dev/null @@ -1,141 +0,0 @@ -# - Find Qhull -# Find the Qhull library -# -# Specify components: -# -# :: -# libqhull = Deprecated interface: use imported target Qhull::libqhull -# qhullstatic = Recommended alternative to re-entrant interface: use imported target Qhull::qhullstatic -# qhull_r = Recommended (re-entrant) interface: use imported target Qhull::qhull_r -# qhullstatic_r = Recommended (re-entrant) interface: use imported target Qhull::qhullstatic_r -# qhullcpp = C++ interface: use imported target Qhull::libqhullcpp -# -# QHULL_FOUND - True if Qhull was found. -# -# Original Author: -# 2019 Ryan Pavlik -# -# Copyright 2019, Collabora, Ltd. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) -# -# SPDX-License-Identifier: BSL-1.0 - -set(QHULL_ROOT_DIR - "${QHULL_ROOT_DIR}" - CACHE PATH "Directory to search for Qhull") - -# Look for a CMake config file -find_package(Qhull QUIET NO_MODULE) -set(_qh_found_any FALSE) -foreach(_qh libqhull qhullstatic qhull_r qhullstatic_r qhullcpp) - if(TARGET Qhull::${_qh}) - set(Qhull_${_qh}_FOUND TRUE) - set(_qh_found_any TRUE) - endif() -endforeach() - -include(FindPackageHandleStandardArgs) -if(_qh_found_any) - # Populate QHULL_bla_INCLUDE_DIR from imported targets - foreach(_qh libqhull qhull_r qhullcpp) - if(TARGET Qhull::${_qh}) - get_target_property(QHULL_${_qh}_INCLUDE_DIR Qhull::${_qh} INTERFACE_INCLUDE_DIRECTORIES) - endif() - endforeach() - find_package_handle_standard_args(Qhull REQUIRED_VARS _qh_found_any HANDLE_COMPONENTS CONFIG_MODE) - -else() - find_path( - QHULL_libqhull_INCLUDE_DIR - NAMES libqhull/libqhull.h - PATHS "${QHULL_ROOT_DIR}") - find_path( - QHULL_qhull_r_INCLUDE_DIR - NAMES libqhull_r/libqhull_r.h - PATHS "${QHULL_ROOT_DIR}") - find_path( - QHULL_qhullcpp_INCLUDE_DIR - NAMES libqhullcpp/Qhull.h - PATHS "${QHULL_ROOT_DIR}") - foreach(_qh_lib libqhull qhull_r qhullstatic qhullstatic_r qhullcpp) - find_library( - QHULL_${_qh_lib}_LIBRARY - NAMES ${_qh_lib} lib${_qh_lib} - PATHS "${QHULL_ROOT_DIR}") - endforeach() - - # Manually search for qhullstatic as a libqhull library with a static library suffix - # (The extra condition is to avoid confusing a .dll import library with a static library) - if(NOT QHULL_qhullstatic_LIBRARY AND NOT "${CMAKE_LINK_LIBRARY_SUFFIX}" STREQUAL "${CMAKE_STATIC_LIBRARY_SUFFIX}") - set(_qh_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) - find_library( - QHULL_qhullstatic_LIBRARY - NAMES qhullstatic libqhullstatic libqhull - PATHS "${QHULL_ROOT_DIR}") - set(CMAKE_FIND_LIBRARY_SUFFIXES ${_qh_CMAKE_FIND_LIBRARY_SUFFIXES}) - unset(_qh_CMAKE_FIND_LIBRARY_SUFFIXES) - endif() - if(NOT Qhull_FIND_COMPONENTS) - set(Qhull_FIND_COMPONENTS qhull_r) - endif() - - set(_qh_required_vars) - foreach(component ${Qhull_FIND_COMPONENTS}) - foreach(candidate libqhull qhull_r qhullstatic qhullstatic_r qhullcpp) - if("${component}" STREQUAL "${candidate}") - string(REPLACE "static" "" candidate_nonstatic "${candidate}") - list(APPEND _qh_required_vars QHULL_${candidate}_LIBRARY QHULL_${candidate_nonstatic}_INCLUDE_DIR) - if(QHULL_${candidate}_LIBRARY AND QHULL_${candidate_nonstatic}_INCLUDE_DIR) - set(Qhull_${candidate}_FOUND TRUE) - endif() - endif() - endforeach() - endforeach() - - find_package_handle_standard_args(Qhull REQUIRED_VARS ${_qh_required_vars} HANDLE_COMPONENTS) - - if(Qhull_qhull_FOUND AND NOT TARGET Qhull::libqhull) - add_library(Qhull::libqhull SHARED IMPORTED) - set_target_properties(Qhull::libqhull PROPERTIES IMPORTED_LOCATION "${QHULL_libqhull_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${QHULL_libqhull_INCLUDE_DIR}") - endif() - if(Qhull_qhullstatic_FOUND AND NOT TARGET Qhull::qhullstatic) - add_library(Qhull::qhullstatic STATIC IMPORTED) - set_target_properties(Qhull::qhullstatic PROPERTIES IMPORTED_LOCATION "${QHULL_qhullstatic_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${QHULL_libqhull_INCLUDE_DIR}") - endif() - if(Qhull_qhull_r_FOUND AND NOT TARGET Qhull::qhull_r) - add_library(Qhull::qhull_r SHARED IMPORTED) - set_target_properties(Qhull::qhull_r PROPERTIES IMPORTED_LOCATION "${QHULL_qhull_r_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${QHULL_qhull_r_INCLUDE_DIR}") - endif() - if(Qhull_qhullstatic_r_FOUND AND NOT TARGET Qhull::qhullstatic_r) - add_library(Qhull::qhullstatic_r STATIC IMPORTED) - set_target_properties( - Qhull::qhullstatic_r PROPERTIES IMPORTED_LOCATION "${QHULL_qhullstatic_r_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${QHULL_qhull_r_INCLUDE_DIR}") - endif() - if(Qhull_qhullcpp_FOUND AND NOT TARGET Qhull::qhullcpp) - add_library(Qhull::qhullcpp STATIC IMPORTED) - set_target_properties(Qhull::qhullcpp PROPERTIES IMPORTED_LOCATION "${QHULL_qhullcpp_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${QHULL_qhullcpp_INCLUDE_DIR}") - endif() - -endif() - -if(QHULL_FOUND) - mark_as_advanced(QHULL_ROOT_DIR) -endif() - -mark_as_advanced( - QHULL_libqhull_INCLUDE_DIR - QHULL_libqhull_LIBRARY - QHULL_qhull_r_INCLUDE_DIR - QHULL_qhull_r_LIBRARY - QHULL_qhullcpp_INCLUDE_DIR - QHULL_qhullcpp_LIBRARY - QHULL_qhullstatic_LIBRARY - QHULL_qhullstatic_r_LIBRARY) diff --git a/src/cmake/meshlab_global_settings.cmake b/src/cmake/meshlab_global_settings.cmake new file mode 100644 index 000000000..20aa94f1e --- /dev/null +++ b/src/cmake/meshlab_global_settings.cmake @@ -0,0 +1,50 @@ +# Copyright 2019-2020, Collabora, Ltd. +# Copyright 2019, 2020, Visual Computing Lab, ISTI - Italian National Research Council +# SPDX-License-Identifier: BSL-1.0 + +# OpenGL legacy is preferred because GLVND links libOpenGL.so +# which cannot be bundled into AppImages and is not provided by +# default into distros: +# https://github.com/AppImage/pkg2appimage/issues/477 +# https://github.com/probonopd/linuxdeployqt/issues/486 + +set(OpenGL_GL_PREFERENCE LEGACY) # OpenGL legacy + +# Enable setting options with SET cmake command +set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) + +### Build settings +set(CMAKE_C_STANDARD 99) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "Minimum OS X deployment version" FORCE) + +### Settings needed for both "external" and internal code +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +### Build Settings +if(WIN32) + add_definitions(-DNOMINMAX) + if(MSVC) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_compile_options(/bigobj) + endif() +endif() +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + +if(APPLE) + add_definitions(-DGL_SILENCE_DEPRECATION) +endif() + +if(MESHLAB_BUILD_STRICT AND NOT MSVC AND NOT APPLE) + # Make sure that our shared libraries were appropriately linked + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined") +endif() + +# Start automoc/autouic/autorcc +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) diff --git a/src/cmake/meshlab_tools.cmake b/src/cmake/meshlab_tools.cmake new file mode 100644 index 000000000..4df1f2d4d --- /dev/null +++ b/src/cmake/meshlab_tools.cmake @@ -0,0 +1,137 @@ +# Copyright 2019-2020, Collabora, Ltd. +# Copyright 2019, 2020, Visual Computing Lab, ISTI - Italian National Research Council +# SPDX-License-Identifier: BSL-1.0 + +#function used to add plugins +function(add_meshlab_plugin target_name) + set(EXCLUDE_ALL_ARG "") + if (MESHLAB_BUILD_MINI) + set(EXCLUDE_ALL_ARG "EXCLUDE_FROM_ALL") + endif() + + cmake_parse_arguments(ARG "" "" "" ${ARGN}) + + add_library(${target_name} MODULE ${EXCLUDE_ALL_ARG} ${ARG_UNPARSED_ARGUMENTS}) + + target_include_directories(${target_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(${target_name} PUBLIC meshlab-common) + + set_property(TARGET ${target_name} PROPERTY FOLDER Plugins) + + set_property(TARGET ${target_name} + PROPERTY RUNTIME_OUTPUT_DIRECTORY ${MESHLAB_PLUGIN_OUTPUT_DIR}) + + set_property(TARGET ${target_name} + PROPERTY LIBRARY_OUTPUT_DIRECTORY ${MESHLAB_PLUGIN_OUTPUT_DIR}) + + install( + TARGETS ${target_name} + DESTINATION ${MESHLAB_PLUGIN_INSTALL_DIR} + COMPONENT Plugins) +endfunction() + +# function that dowloads and unzips an archive +# params: +# - link: download link +# - dir: directory where the archive will be extracted +# - name: a name used only for log +function(download_and_unzip) + set(download_and_unzip_SUCCESS FALSE PARENT_SCOPE) + set(options) + set(oneValueArgs MD5 NAME DIR) + set(multiValueArgs LINK) + cmake_parse_arguments(DAU + "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN}) + + list(LENGTH DAU_LINK NUMBER_OF_LINKS) + if(NUMBER_OF_LINKS LESS 1) + message(FATAL_ERROR "Need to specify at least a download link.") + endif() + + set(ZIP ${CMAKE_CURRENT_LIST_DIR}/tmp.zip) + + foreach(LINK ${DAU_LINK}) + message(STATUS "Downloading ${DAU_NAME} from ${LINK}") + + file(DOWNLOAD ${LINK} ${ZIP}) + + file(MD5 ${ZIP} MD5SUM) + + # no md5 argument given, no checksum needed... + if (NOT DEFINED DAU_MD5) + set(DAU_MD5 ${MD5SUM}) + endif() + + # manual md5 check, avoid to fail when a download fails + if(MD5SUM STREQUAL ${DAU_MD5}) # download successful + message(STATUS "${DAU_NAME} downloaded.") + message(STATUS "Extracting ${DAU_NAME} archive...") + file(ARCHIVE_EXTRACT + INPUT ${ZIP} + DESTINATION ${DAU_DIR}) + message(STATUS "${DAU_NAME} archive extracted.") + file(REMOVE ${ZIP}) + set(download_and_unzip_SUCCESS TRUE PARENT_SCOPE) + break() # done + else() + file(REMOVE ${ZIP}) + message(STATUS "${DAU_NAME} download failed...") + # next link in DAU_LINK list... + endif() + endforeach() +endfunction() + +# make quiet some portions of cmake +# usage +# +# set(MESSAGE_QUIET ON) +# #everything here will be quiet +# unset(MESSAGE_QUIET) +function(message) + if (NOT MESSAGE_QUIET) + _message(${ARGN}) + endif() +endfunction() + +function(add_file_format_info_plist) + cmake_parse_arguments(ARG "" "TARGET;FILE;FORMAT" "" ${ARGN}) + + string(TOUPPER ${ARG_FORMAT} FORMAT_UPPER) + string(TOLOWER ${ARG_FORMAT} FORMAT_LOWER) + + add_custom_command( + TARGET ${ARG_TARGET} + POST_BUILD + COMMAND plutil -insert CFBundleDocumentTypes.0 -xml 'CFBundleTypeName${FORMAT_UPPER} 3D FileCFBundleTypeIconFilemeshlab.icnsCFBundleTypeRoleEditorLSHandlerRankDefault' ${ARG_FILE} + COMMAND plutil -insert CFBundleDocumentTypes.0.CFBundleTypeExtensions -xml '' ${ARG_FILE} + COMMAND plutil -insert CFBundleDocumentTypes.0.CFBundleTypeExtensions.0 -xml '${FORMAT_LOWER}' ${ARG_FILE} + COMMAND plutil -insert CFBundleDocumentTypes.0.CFBundleTypeOSTypes -xml '' ${ARG_FILE} + COMMAND plutil -insert CFBundleDocumentTypes.0.CFBundleTypeOSTypes.0 -xml '${FORMAT_UPPER}' ${ARG_FILE} + ) +endfunction() + +function(set_additional_settings_info_plist) + cmake_parse_arguments(ARG "" "TARGET;FILE" "" ${ARGN}) + add_custom_command( + TARGET ${ARG_TARGET} + POST_BUILD + COMMAND plutil -replace NSHighResolutionCapable -bool True ${ARG_FILE} + COMMAND plutil -replace CFBundleDocumentTypes -xml '' ${ARG_FILE} + COMMAND plutil -replace CFBundleIdentifier -string 'com.vcg.meshlab' ${ARG_FILE} + COMMAND plutil -insert NSRequiresAquaSystemAppearance -bool True ${ARG_FILE} || (exit 0) + ) + + add_file_format_info_plist( + TARGET ${ARG_TARGET} + FILE ${ARG_FILE} + FORMAT OBJ) + add_file_format_info_plist( + TARGET ${ARG_TARGET} + FILE ${ARG_FILE} + FORMAT STL) + add_file_format_info_plist( + TARGET ${ARG_TARGET} + FILE ${ARG_FILE} + FORMAT PLY) +endfunction() diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index f3265648e..0e640fdd4 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,24 +1,48 @@ -if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../ML_VERSION") - file(READ "${CMAKE_CURRENT_SOURCE_DIR}/../../ML_VERSION" MESHLAB_VERSION) - if (BUILD_WITH_DOUBLE_SCALAR) - set(MESHLAB_VERSION "${MESHLAB_VERSION}d") +#version management +string(TIMESTAMP MESHLAB_VERSION "%Y.%m") + +if (MESHLAB_IS_NIGHTLY_VERSION) + # nightly version is in the form: + # YYYY.mm[d]_nightly_GIT_SHA1 + # YYYY and mm are computed by cmake and not read from file + # the GIT_SHA1 is stored in file, which will be read at runtime + find_package(Git) + execute_process(COMMAND + "${GIT_EXECUTABLE}" describe --match=NeVeRmAtCh --always --abbrev=7 + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + OUTPUT_VARIABLE GIT_SHA1 + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/resources/git_sha.txt ${GIT_SHA1}) +else() + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../ML_VERSION") + # YYYY and mm are read from file + file(READ "${CMAKE_CURRENT_SOURCE_DIR}/../../ML_VERSION" MESHLAB_VERSION) endif() - add_definitions(-DMESHLAB_VERSION=${MESHLAB_VERSION}) +endif() + +if (MESHLAB_BUILD_WITH_DOUBLE_SCALAR) + set(MESHLAB_VERSION "${MESHLAB_VERSION}d") +endif() + + +set(MESHLAB_VERSION ${MESHLAB_VERSION} PARENT_SCOPE) +if (MESHLAB_IS_NIGHTLY_VERSION) + message(STATUS "MeshLab version: ${MESHLAB_VERSION}_nightly_${GIT_SHA1}") +else() message(STATUS "MeshLab version: ${MESHLAB_VERSION}") endif() +if (MESHLAB_BUILD_WITH_DOUBLE_SCALAR) + message(STATUS "Building with double precision") + set(MESHLAB_SCALAR "double") +else() + message(STATUS "Building with single precision") + set(MESHLAB_SCALAR "float") +endif() + set(HEADERS - parameters/rich_parameter.h - parameters/rich_parameter_list.h - parameters/value.h - interfaces/decorate_plugin_interface.h - interfaces/edit_plugin_interface.h - interfaces/filter_plugin_interface.h - interfaces/iomesh_plugin_interface.h - interfaces/ioraster_plugin_interface.h - interfaces/mainwindow_interface.h - interfaces/plugin_interface.h - interfaces/render_plugin_interface.h + filter_history/filter.h + filter_history/filter_history.h ml_document/helpers/mesh_document_state_data.h ml_document/helpers/mesh_model_state_data.h ml_document/base_types.h @@ -28,27 +52,72 @@ set(HEADERS ml_document/mesh_model_state.h ml_document/raster_model.h ml_document/render_raster.h + ml_shared_data_context/ml_plugin_gl_context.h + ml_shared_data_context/ml_scene_gl_shared_data_context.h + ml_shared_data_context/ml_shared_data_context.h + parameters/rich_parameters.h + parameters/values.h + parameters/rich_parameter_list.h + parameters/rich_parameter/rich_bool.h + parameters/rich_parameter/rich_color.h + parameters/rich_parameter/rich_direction.h + parameters/rich_parameter/rich_dynamic_float.h + parameters/rich_parameter/rich_enum.h + parameters/rich_parameter/rich_file_open.h + parameters/rich_parameter/rich_file_save.h + parameters/rich_parameter/rich_float.h + parameters/rich_parameter/rich_int.h + parameters/rich_parameter/rich_matrix44.h + parameters/rich_parameter/rich_mesh.h + parameters/rich_parameter/rich_parameter.h + parameters/rich_parameter/rich_percentage.h + parameters/rich_parameter/rich_position.h + parameters/rich_parameter/rich_shot.h + parameters/rich_parameter/rich_string.h + parameters/value/bool_value.h + parameters/value/color_value.h + parameters/value/float_value.h + parameters/value/int_value.h + parameters/value/matrix44_value.h + parameters/value/point3_value.h + parameters/value/shot_value.h + parameters/value/string_value.h + parameters/value/value.h + plugins/containers/generic_container_iterator.h + plugins/containers/decorate_plugin_container.h + plugins/containers/edit_plugin_container.h + plugins/containers/filter_plugin_container.h + plugins/containers/io_plugin_container.h + plugins/containers/render_plugin_container.h + plugins/interfaces/meshlab_plugin.h + plugins/interfaces/meshlab_plugin_logger.h + plugins/interfaces/decorate_plugin.h + plugins/interfaces/edit_plugin.h + plugins/interfaces/filter_plugin.h + plugins/interfaces/io_plugin.h + plugins/interfaces/render_plugin.h + plugins/action_searcher.h + plugins/meshlab_plugin_type.h + plugins/plugin_manager.h + python/function.h + python/function_parameter.h + python/function_set.h + python/python_utils.h + utilities/eigen_mesh_conversions.h utilities/file_format.h + utilities/load_save.h + globals.h GLExtensionsManager.h GLLogStream.h filterscript.h - meshlabdocumentbundler.h - meshlabdocumentxml.h ml_selection_buffers.h - ml_shared_data_context.h ml_thread_safe_memory_info.h mlapplication.h - mlexception.h - pluginmanager.h - searcher.h) + mlexception.h) set(SOURCES - parameters/rich_parameter.cpp - parameters/rich_parameter_list.cpp - parameters/value.cpp - interfaces/decorate_plugin_interface.cpp - interfaces/filter_plugin_interface.cpp - interfaces/plugin_interface.cpp + filter_history/filter.cpp + filter_history/filter_history.cpp ml_document/helpers/mesh_document_state_data.cpp ml_document/cmesh.cpp ml_document/mesh_document.cpp @@ -56,41 +125,92 @@ set(SOURCES ml_document/mesh_model_state.cpp ml_document/raster_model.cpp ml_document/render_raster.cpp + ml_shared_data_context/ml_plugin_gl_context.cpp + ml_shared_data_context/ml_scene_gl_shared_data_context.cpp + ml_shared_data_context/ml_shared_data_context.cpp + parameters/rich_parameters.cpp + parameters/rich_parameter_list.cpp + parameters/rich_parameter/rich_bool.cpp + parameters/rich_parameter/rich_color.cpp + parameters/rich_parameter/rich_direction.cpp + parameters/rich_parameter/rich_dynamic_float.cpp + parameters/rich_parameter/rich_enum.cpp + parameters/rich_parameter/rich_file_open.cpp + parameters/rich_parameter/rich_file_save.cpp + parameters/rich_parameter/rich_float.cpp + parameters/rich_parameter/rich_int.cpp + parameters/rich_parameter/rich_matrix44.cpp + parameters/rich_parameter/rich_mesh.cpp + parameters/rich_parameter/rich_parameter.cpp + parameters/rich_parameter/rich_percentage.cpp + parameters/rich_parameter/rich_position.cpp + parameters/rich_parameter/rich_shot.cpp + parameters/rich_parameter/rich_string.cpp + parameters/value/bool_value.cpp + parameters/value/color_value.cpp + parameters/value/float_value.cpp + parameters/value/int_value.cpp + parameters/value/matrix44_value.cpp + parameters/value/point3_value.cpp + parameters/value/shot_value.cpp + parameters/value/string_value.cpp + plugins/containers/decorate_plugin_container.cpp + plugins/containers/edit_plugin_container.cpp + plugins/containers/filter_plugin_container.cpp + plugins/containers/io_plugin_container.cpp + plugins/containers/render_plugin_container.cpp + plugins/interfaces/meshlab_plugin_logger.cpp + plugins/interfaces/decorate_plugin.cpp + plugins/interfaces/filter_plugin.cpp + plugins/interfaces/io_plugin.cpp + plugins/action_searcher.cpp + plugins/meshlab_plugin_type.cpp + plugins/plugin_manager.cpp + python/function.cpp + python/function_parameter.cpp + python/function_set.cpp + python/python_utils.cpp + utilities/eigen_mesh_conversions.cpp + utilities/load_save.cpp + globals.cpp GLExtensionsManager.cpp GLLogStream.cpp filterscript.cpp - meshlabdocumentbundler.cpp - meshlabdocumentxml.cpp ml_selection_buffers.cpp - ml_shared_data_context.cpp ml_thread_safe_memory_info.cpp - mlapplication.cpp - pluginmanager.cpp - searcher.cpp - ${EXTERNAL_DIR}/easyexif/exif.cpp) + mlapplication.cpp) + +set(RESOURCES meshlab-common.qrc) set(TARGET_TYPE SHARED) -if(WIN32) - set(TARGET_TYPE STATIC) -endif() add_library(meshlab-common ${TARGET_TYPE} ${SOURCES} ${HEADERS} ${RESOURCES}) -target_include_directories(meshlab-common - PRIVATE - ${EXTERNAL_DIR}/easyexif/ +target_compile_definitions(meshlab-common + PUBLIC + MESHLAB_VERSION=${MESHLAB_VERSION} + MESHLAB_SCALAR=${MESHLAB_SCALAR}) + +if (MESHLAB_IS_NIGHTLY_VERSION) + target_compile_definitions(meshlab-common + PUBLIC + MESHLAB_IS_NIGHTLY) +endif() + +target_include_directories(meshlab-common PUBLIC - ${VCGDIR} - ${EIGEN_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/..) target_link_libraries( meshlab-common - PUBLIC + PUBLIC Qt5::Core Qt5::OpenGL Qt5::Widgets Qt5::Xml + Qt5::Network + vcglib external-glew + external-easyexif ) set_property(TARGET meshlab-common PROPERTY FOLDER Core) @@ -102,9 +222,16 @@ set_property(TARGET meshlab-common PROPERTY LIBRARY_OUTPUT_DIRECTORY ${MESHLAB_LIB_OUTPUT_DIR}) if (WIN32) + target_compile_definitions(meshlab-common PRIVATE ML_EXPORT_SYMBOLS) set_property(TARGET meshlab-common PROPERTY ARCHIVE_OUTPUT_DIRECTORY ${MESHLAB_LIB_OUTPUT_DIR}) endif() -install(TARGETS meshlab-common DESTINATION ${MESHLAB_LIB_INSTALL_DIR}) +if(MESHLAB_ENABLE_DEBUG_LOG_FILE) + target_compile_definitions(meshlab-common PUBLIC MESHLAB_LOG_FILE_ENABLED) +endif() +set_target_properties(meshlab-common PROPERTIES + INSTALL_RPATH "$ORIGIN") + +install(TARGETS meshlab-common DESTINATION ${MESHLAB_LIB_INSTALL_DIR}) diff --git a/src/common/GLExtensionsManager.cpp b/src/common/GLExtensionsManager.cpp index 985260d56..0cb2092b4 100644 --- a/src/common/GLExtensionsManager.cpp +++ b/src/common/GLExtensionsManager.cpp @@ -36,19 +36,19 @@ void GLExtensionsManager::init() */ bool GLExtensionsManager::initializeGLextensions_notThrowing() { - GLenum err = GLEW_OK; if (!glewInitialized) { glewExperimental = GL_TRUE; - err = glewInit(); - if (err != GLEW_OK) { + GLenum err = glewInit(); + if ((err == GLEW_OK) || + (err == GLEW_ERROR_NO_GLX_DISPLAY)) { + glewInitialized = true; + } + else { qWarning("GLEW initialization failed: %s", (const char *)glewGetErrorString(err)); } - else { - glewInitialized = true; - } } - return err == GLEW_OK; + return glewInitialized; } @@ -61,12 +61,13 @@ void GLExtensionsManager::initializeGLextensions() if (!glewInitialized) { glewExperimental = GL_TRUE; GLenum err = glewInit(); - if (err != GLEW_OK && err != GLEW_ERROR_NO_GLX_DISPLAY) { + if ((err == GLEW_OK) || + (err == GLEW_ERROR_NO_GLX_DISPLAY)) { + glewInitialized = true; + } + else { throw MLException(QString("GLEW initialization failed: %1\n") .arg((const char *)glewGetErrorString(err))); } - else { - glewInitialized = true; - } } } diff --git a/src/common/GLLogStream.cpp b/src/common/GLLogStream.cpp index 8267950e5..98e6d000f 100644 --- a/src/common/GLLogStream.cpp +++ b/src/common/GLLogStream.cpp @@ -25,92 +25,103 @@ #include #include +#ifdef MESHLAB_LOG_FILE_ENABLED +#include +#include +#include +#include "globals.h" +#endif + #include "GLLogStream.h" using namespace std; -GLLogStream::GLLogStream() - :QObject() +GLLogStream::GLLogStream() : + QObject(), bookmark(-1) { - ClearBookmark(); } -void GLLogStream::RealTimeLog(const QString& Id, const QString &meshName, const QString& text) +void GLLogStream::realTimeLog(const QString& Id, const QString &meshName, const QString& text) { - this->RealTimeLogText.insert(Id,qMakePair(meshName,text) ); + this->realTimeLogText.insert(Id,qMakePair(meshName,text) ); } -void GLLogStream::Save(int /*Level*/, const char * filename ) +void GLLogStream::save(int /*Level*/, const char * filename ) { FILE *fp=fopen(filename,"wb"); QList > ::iterator li; - for(li=S.begin();li!=S.end();++li) + for(li=logTextList.begin();li!=logTextList.end();++li) fprintf(fp,"%s", qUtf8Printable((*li).second)); } -void GLLogStream::ClearBookmark() +void GLLogStream::clearBookmark() { bookmark = -1; } -void GLLogStream::SetBookmark() +void GLLogStream::setBookmark() { - bookmark=S.size(); + bookmark=logTextList.size(); } -void GLLogStream::BackToBookmark() +void GLLogStream::backToBookmark() { if(bookmark<0) return; - while(S.size() > bookmark ) - S.removeLast(); + while(logTextList.size() > bookmark ) + logTextList.removeLast(); } const QList >& GLLogStream::logStringList() const { - return S; + return logTextList; } const QMultiMap >& GLLogStream::realTimeLogMultiMap() const { - return RealTimeLogText; + return realTimeLogText; } void GLLogStream::clearRealTimeLog() { - RealTimeLogText.clear(); + realTimeLogText.clear(); } void GLLogStream::print(QStringList &out) const { out.clear(); - for (const pair & p : S) + for (const pair & p : logTextList) out.push_back(p.second); } -void GLLogStream::Clear() +void GLLogStream::clear() { - S.clear(); + logTextList.clear(); } -void GLLogStream::Log(int Level, const char * buf ) +void GLLogStream::log(int level, const char * buf ) { QString tmp(buf); - S.push_back(std::make_pair(Level,tmp)); - qDebug("LOG: %i %s",Level,buf); + logTextList.push_back(std::make_pair(level,tmp)); + qDebug("LOG: %i %s",level,buf); +#ifdef MESHLAB_LOG_FILE_ENABLED + QThread::msleep(100); + QFile f(meshlab::logDebugFileName()); + f.open(QIODevice::Append); + QTextStream stream(&f); + stream << "LOG: [" + QString::number(level) + "] " + QString(buf) + "\n"; + stream.flush(); + f.close(); +#endif emit logUpdated(); } -void GLLogStream::Log(int Level, const string& logMessage) +void GLLogStream::log(int level, const string& logMessage) { - S.push_back(std::make_pair(Level, QString::fromStdString(logMessage))); - qDebug("LOG: %i %s",Level, logMessage.c_str()); - emit logUpdated(); + log(level, logMessage.c_str()); } -void GLLogStream::Log(int Level, const QString& logMessage) +void GLLogStream::log(int level, const QString& logMessage) { - S.push_back(std::make_pair(Level, logMessage)); - qDebug("LOG: %i %s",Level, logMessage.toStdString().c_str()); - emit logUpdated(); + log(level, logMessage.toStdString().c_str()); } diff --git a/src/common/GLLogStream.h b/src/common/GLLogStream.h index 5cfc03345..26b7bba0b 100644 --- a/src/common/GLLogStream.h +++ b/src/common/GLLogStream.h @@ -31,11 +31,23 @@ #include #include #include + +#ifdef WIN32 +#ifdef ML_EXPORT_SYMBOLS +#define ML_DLL_EXPORT Q_DECL_EXPORT +#else +#define ML_DLL_EXPORT Q_DECL_IMPORT +#endif +#else //WIN32 +#define ML_DLL_EXPORT +#endif + /** This is the logging class. One for each document. Responsible of getting an history of the logging message printed out by filters. */ -class GLLogStream : public QObject +class ML_DLL_EXPORT + GLLogStream : public QObject { Q_OBJECT public: @@ -52,56 +64,56 @@ public: GLLogStream(); ~GLLogStream() {} void print(QStringList &list) const; // Fills a QStringList with the log entries - void Save(int Level, const char *filename); - void Clear(); + void save(int Level, const char *filename); + void clear(); template - void Logf(int Level, const char * f, Ts&&... ts ) + void logf(int Level, const char * f, Ts&&... ts ) { char buf[buf_size]; int chars_written = snprintf(buf, buf_size, f, std::forward(ts)...); - Log(Level, buf); + log(Level, buf); if(chars_written >= static_cast(buf_size)){ - Log(Level, "Log message truncated."); + log(Level, "Log message truncated."); } } - void Log(int Level, const char * buf); - void Log(int Level, const std::string& logMessage); - void Log(int Level, const QString& logMessage); - void SetBookmark(); - void ClearBookmark(); - void BackToBookmark(); + void log(int level, const char * buf); + void log(int level, const std::string& logMessage); + void log(int level, const QString& logMessage); + void setBookmark(); + void clearBookmark(); + void backToBookmark(); const QList >& logStringList() const; const QMultiMap >& realTimeLogMultiMap() const; void clearRealTimeLog(); template - void RealTimeLogf(const QString& Id, const QString &meshName, const char * f, Ts&&... ts ) + void realTimeLogf(const QString& Id, const QString &meshName, const char * f, Ts&&... ts ) { char buf[buf_size]; int chars_written = snprintf(buf, buf_size, f, std::forward(ts)...); - RealTimeLog(Id, meshName, buf); + realTimeLog(Id, meshName, buf); if(chars_written >= static_cast(buf_size)){ - RealTimeLog(Id, meshName, "Log message truncated."); + realTimeLog(Id, meshName, "Log message truncated."); } } - void RealTimeLog(const QString& Id, const QString &meshName, const QString& text); + void realTimeLog(const QString& Id, const QString &meshName, const QString& text); signals: void logUpdated(); private: int bookmark; /// this field is used to place a bookmark for restoring the log. Useful for previeweing - QList > S; + QList > logTextList; // The list of strings used in realtime display of info over the mesh. // Each box is identified by the title, name of the mesh and text. // the name of the mesh is shown only if two or more box with the same title are shown. - QMultiMap > RealTimeLogText; + QMultiMap > realTimeLogText; }; #endif //GLLOGSTREAM_H diff --git a/src/common/common.pro b/src/common/common.pro deleted file mode 100644 index c88d60d2e..000000000 --- a/src/common/common.pro +++ /dev/null @@ -1,122 +0,0 @@ -include (../general.pri) - -QT += opengl -QT += xml -QT += network - -TEMPLATE = lib -TARGET = meshlab-common -DEPENDPATH += . - -DESTDIR = $$MESHLAB_DISTRIB_DIRECTORY/lib - -win32-msvc:CONFIG += staticlib -win32-g++:DLLDESTDIR = $$MESHLAB_DISTRIB_DIRECTORY/lib - -linux:CONFIG += dll - -INCLUDEPATH *= \ - ../.. \ - $$$$MESHLAB_EXTERNAL_DIRECTORY/easyexif \ - $$VCGDIR \ - $$EIGENDIR - -!CONFIG(system_glew) { - INCLUDEPATH *= $$GLEWDIR/include - GLEWCODE = $$GLEWDIR/src/glew.c -} - -!CONFIG(system_glew) { - SOURCES += $$GLEWCODE - DEFINES += GLEW_STATIC -} - -# defining meshlab version -exists(../../ML_VERSION){ - MESHLAB_VERSION = $$cat(../../ML_VERSION) - message(MeshLab Version: $$MESHLAB_VERSION) - DEFINES += "MESHLAB_VERSION=$$MESHLAB_VERSION" -} - -# Input -HEADERS += \ - GLExtensionsManager.h \ - parameters/rich_parameter_list.h \ - parameters/value.h \ - parameters/rich_parameter.h \ - filterscript.h \ - GLLogStream.h \ - interfaces/decorate_plugin_interface.h \ - interfaces/edit_plugin_interface.h \ - interfaces/filter_plugin_interface.h \ - interfaces/iomesh_plugin_interface.h \ - interfaces/mainwindow_interface.h \ - interfaces/plugin_interface.h \ - interfaces/render_plugin_interface.h \ - ml_document/helpers/mesh_document_state_data.h \ - ml_document/helpers/mesh_model_state_data.h \ - ml_document/base_types.h \ - ml_document/cmesh.h \ - ml_document/mesh_model.h \ - ml_document/mesh_model_state.h \ - ml_document/mesh_document.h \ - ml_document/raster_model.h \ - ml_document/render_raster.h \ - utilities/file_format.h \ - pluginmanager.h \ - mlexception.h \ - mlapplication.h \ - meshlabdocumentxml.h \ - ml_shared_data_context.h \ - ml_selection_buffers.h \ - meshlabdocumentxml.h - -SOURCES += \ - GLExtensionsManager.cpp \ - parameters/rich_parameter.cpp \ - parameters/rich_parameter_list.cpp \ - parameters/value.cpp \ - filterscript.cpp \ - GLLogStream.cpp \ - interfaces/decorate_plugin_interface.cpp \ - interfaces/filter_plugin_interface.cpp \ - interfaces/plugin_interface.cpp \ - ml_document/helpers/mesh_document_state_data.cpp \ - ml_document/cmesh.cpp \ - ml_document/mesh_model.cpp \ - ml_document/mesh_model_state.cpp \ - ml_document/mesh_document.cpp \ - ml_document/raster_model.cpp \ - ml_document/render_raster.cpp \ - pluginmanager.cpp \ - mlapplication.cpp \ - searcher.cpp \ - meshlabdocumentxml.cpp \ - meshlabdocumentbundler.cpp \ - ml_shared_data_context.cpp \ - ml_selection_buffers.cpp \ - $$MESHLAB_EXTERNAL_DIRECTORY/easyexif/exif.cpp - -macx:QMAKE_POST_LINK = "\ - if [ -d $$MESHLAB_DISTRIB_DIRECTORY/meshlab.app/Contents/Frameworks/ ]; \ - then \ - echo "Copying"; \ - else \ - mkdir -p $$MESHLAB_DISTRIB_DIRECTORY/meshlab.app/Contents/Frameworks; \ - fi; \ - cp $$MESHLAB_DISTRIB_DIRECTORY/lib/libmeshlab-common.* $$MESHLAB_DISTRIB_DIRECTORY/meshlab.app/Contents/Frameworks/ ;\ -# if [ -d ../external/ ];\ -# then \ -# echo "ok external dir exists"; \ -# else \ -# ln -s ../../meshlab/src/external ../external;\ -# echo "linked external dir"; \ -# fi;\ -# if [ -d $$MESHLAB_DISTRIB_DIRECTORY/shaders/ ];\ -# then \ -# echo "ok shader dir exists"; \ -# else \ -# ln -s ../../../meshlab/src/distrib/shaders ../distrib/shaders ;\ -# echo "linked shader dir"; \ -# fi;\ - " diff --git a/src/common/filter_history/filter.cpp b/src/common/filter_history/filter.cpp new file mode 100644 index 000000000..f77c6f4d5 --- /dev/null +++ b/src/common/filter_history/filter.cpp @@ -0,0 +1,136 @@ +/***************************************************************************** + * MeshLab o o * + * An extendible mesh processor o o * + * _ O _ * + * Copyright(C) 2005-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "filter.h" + +Filter::Filter() +{ +} + +Filter::Filter( + const FilterPlugin* plugin, + const QAction* filter, + const RichParameterList& paramList) : + plugin(plugin), + filter(filter), + paramList(paramList) +{ +} + +void Filter::setParameterValue(const std::string ¶meter, const Value &value) +{ + RichParameter& rp = paramList.getParameterByName(QString::fromStdString(parameter)); + rp.setValue(value); +} + +/** + * @brief returns a string containing a pymeshlab python call of the filter with the current + * parameters set. + * @param meshSetName: the name of the MeshSet object. + * @return + */ +std::string Filter::pyMeshLabCall(std::string meshSetName) const +{ + bool first = true; + std::string call = meshSetName + "." + plugin->pythonFilterName(filter).toStdString() + "("; + for (const RichParameter& p : paramList) { + // parameter must be added only if its value is not default + if (!p.isValueDefault()) { + if (!p.isOfType()) { // RichShot not yet supported by pymeshlab + // if it is not the first parameter we are adding, we put the comma after the last + // parameter, because we are going to add another one + if (first) { + first = false; + } + else { + call += ", "; + } + call += p.pythonName().toStdString() + " = "; + if (p.isOfType()) { + if (p.value().getBool()) { + call += "True"; + } + else { + call += "False"; + } + } + else if (p.isOfType()) { + QColor c = p.value().getColor(); + call += "pymeshlab.Color("; + call += std::to_string(c.red()) + ", "; + call += std::to_string(c.green()) + ", "; + call += std::to_string(c.blue()) + ", "; + call += std::to_string(c.alpha()) + ")"; + } + else if (p.isOfType() || p.isOfType()) { + Point3m pp = p.value().getPoint3(); + call += "numpy.array(["; + call += std::to_string(pp[0]) + ", "; + call += std::to_string(pp[1]) + ", "; + call += std::to_string(pp[2]) + "])"; + } + else if (p.isOfType() || p.isOfType()) { + call += std::to_string(p.value().getFloat()); + } + else if ( + p.isOfType() || p.isOfType() || p.isOfType()) { + call += std::to_string(p.value().getInt()); + } + else if ( + p.isOfType() || p.isOfType() || + p.isOfType()) { + call += "'" + p.value().getString().toStdString() + "'"; + } + else if (p.isOfType()) { + Matrix44m m = p.value().getMatrix44(); + call += "numpy.array(["; + bool firstRow = true; + for (unsigned int i = 0; i < 4 ; i++) { + if (firstRow) + firstRow = false; + else + call += ", "; + call += "["; + bool firstCol = true; + for (unsigned int j = 0; j < 4 ; j++) { + if (firstCol) + firstCol = false; + else + call += ", "; + call += std::to_string(m.ElementAt(i,j)); + } + call += "]"; + } + call += "])"; + } + else if (p.isOfType()) { + const RichPercentage& rp = dynamic_cast(p); + float per = (p.value().getFloat() / (rp.max - rp.min) ) * 100; + call += "pymeshlab.PercentageValue(" + std::to_string(per) + ")"; + } + } + } + } + call += ")"; + return call; +} diff --git a/src/common/filter_history/filter.h b/src/common/filter_history/filter.h new file mode 100644 index 000000000..5acc728a7 --- /dev/null +++ b/src/common/filter_history/filter.h @@ -0,0 +1,49 @@ +/***************************************************************************** + * MeshLab o o * + * An extendible mesh processor o o * + * _ O _ * + * Copyright(C) 2005-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef FILTER_H +#define FILTER_H + +#include +#include + +class Filter +{ +public: + Filter(); + Filter( + const FilterPlugin* plugin, + const QAction* filter, + const RichParameterList& paramList); + + void setParameterValue(const std::string& parameter, const Value& value); + + std::string pyMeshLabCall(std::string meshSetName = "ms") const; + +private: + const FilterPlugin* plugin; + const QAction* filter; + RichParameterList paramList; +}; + +#endif // FILTER_H diff --git a/src/common/filter_history/filter_history.cpp b/src/common/filter_history/filter_history.cpp new file mode 100644 index 000000000..ef2d395fd --- /dev/null +++ b/src/common/filter_history/filter_history.cpp @@ -0,0 +1,44 @@ +/***************************************************************************** + * MeshLab o o * + * An extendible mesh processor o o * + * _ O _ * + * Copyright(C) 2005-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "filter_history.h" + +FilterHistory::iterator FilterHistory::begin() +{ + return history.begin(); +} + +FilterHistory::iterator FilterHistory::end() +{ + return history.end(); +} + +FilterHistory::const_iterator FilterHistory::begin() const +{ + return history.begin(); +} + +FilterHistory::const_iterator FilterHistory::end() const +{ + return history.end(); +} diff --git a/src/common/filter_history/filter_history.h b/src/common/filter_history/filter_history.h new file mode 100644 index 000000000..4df36ebfc --- /dev/null +++ b/src/common/filter_history/filter_history.h @@ -0,0 +1,45 @@ +/***************************************************************************** + * MeshLab o o * + * An extendible mesh processor o o * + * _ O _ * + * Copyright(C) 2005-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_FILTER_HISTORY_H +#define MESHLAB_FILTER_HISTORY_H + +#include + +#include "filter.h" + +class FilterHistory +{ + using iterator = std::list::iterator; + using const_iterator = std::list::const_iterator; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + +private: + std::list history; +}; + +#endif // MESHLAB_FILTER_HISTORY_H diff --git a/src/common/globals.cpp b/src/common/globals.cpp new file mode 100644 index 000000000..c83afc3e3 --- /dev/null +++ b/src/common/globals.cpp @@ -0,0 +1,168 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2005-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "globals.h" + +#include +#include +#include + +#include "parameters/rich_parameter_list.h" +#include "plugins/plugin_manager.h" +#include "plugins/action_searcher.h" +#include "python/function_set.h" + +QString basePath() +{ + QDir baseDir(qApp->applicationDirPath()); + +#ifdef Q_OS_WIN + // Windows: + // during development with visual studio binary could be in the debug/release subdir. + // once deployed plugins dir is in the application directory, so + if (baseDir.dirName() == "debug" || baseDir.dirName() == "release") + baseDir.cdUp(); +#endif + +#ifdef Q_OS_MAC + // Mac: during developmentwith xcode and well deployed the binary is well buried. + for (int i = 0; i < 6; ++i) { + if (baseDir.exists("plugins") || baseDir.exists("PlugIns")) + break; + baseDir.cdUp(); + } +#endif + return baseDir.absolutePath(); +} + +QString meshlab::defaultPluginPath() +{ + QDir pluginsDir(basePath()); +#ifdef Q_OS_WIN + QString d = pluginsDir.dirName(); + QString dLower = d.toLower(); + if (dLower == "release" || dLower == "relwithdebinfo" || dLower == "debug" || + dLower == "minsizerel") { + // This is a configuration directory for MS Visual Studio. + pluginsDir.cdUp(); + } + else { + d.clear(); + } +#endif + if (pluginsDir.exists("PlugIns")) { + pluginsDir.cd("PlugIns"); + return pluginsDir.absolutePath(); + } + + if (pluginsDir.exists("plugins")) { + pluginsDir.cd("plugins"); + +#ifdef Q_OS_WIN + // Re-apply the configuration dir, if any. + if (!d.isEmpty() && pluginsDir.exists(d)) { + pluginsDir.cd(d); + } +#endif + + return pluginsDir.absolutePath(); + } +#ifdef Q_OS_LINUX + else if (pluginsDir.dirName() == "bin") { + pluginsDir.cdUp(); + pluginsDir.cd("lib"); + pluginsDir.cd("meshlab"); + if (pluginsDir.exists("plugins")) { + pluginsDir.cd("plugins"); + return pluginsDir.absolutePath(); + } + } +#endif + qDebug("Meshlab Initialization: Serious error. Unable to find the plugins directory."); + return {}; +} + +QString meshlab::defaultShadersPath() +{ + QDir dir(basePath()); +#ifdef Q_OS_MAC // TODO: check that this works as expected + return dir.path() + "/shaders"; +#endif +#ifdef Q_OS_LINUX + dir.cdUp(); + bool res = dir.cd("share/meshlab/shaders"); + if (res) { + return dir.path(); + } + else { // reset and return default + dir.setPath(basePath()); + } +#endif + return dir.path() + "/shaders"; +} + +QString meshlab::logDebugFileName() +{ + static QString filename = QDir::homePath() + "/MeshLab" + + QString::fromStdString(meshlab::meshlabCompleteVersion()) + " " + + QDateTime::currentDateTime().toString() + ".log"; + return filename; +} + +RichParameterList& meshlab::defaultGlobalParameterList() +{ + static RichParameterList globalRPS; + return globalRPS; +} + +PluginManager& meshlab::pluginManagerInstance() +{ + static PluginManager pm; + return pm; +} + +ActionSearcher& meshlab::actionSearcherInstance() +{ + static ActionSearcher as; + return as; +} + +std::string meshlab::meshlabCompleteVersion() +{ + std::string ver = meshlabVersion(); +#ifdef MESHLAB_IS_NIGHTLY + QFile f(":/resources/git_sha.txt"); + if (f.open(QFile::ReadOnly | QFile::Text)) { + QTextStream in(&f); + ver += "_nightly_" + in.readAll().toStdString(); + f.close(); + } +#endif + return ver; +} + +pymeshlab::FunctionSet& pymeshlab::functionSetInstance() +{ + static FunctionSet fs(meshlab::pluginManagerInstance()); + return fs; +} diff --git a/src/common/globals.h b/src/common/globals.h new file mode 100644 index 000000000..daa86fd8b --- /dev/null +++ b/src/common/globals.h @@ -0,0 +1,80 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2005-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_GLOBALS_H +#define MESHLAB_GLOBALS_H + +#define meshlab_xstr(a) mlstringify(a) +#define mlstringify(a) #a + +#include +#ifdef MESHLAB_IS_NIGHTLY +#include +#include +#endif + +#ifndef MESHLAB_VERSION +#error "MESHLAB_VERSION needs to be defined!" +#endif +#ifndef MESHLAB_SCALAR +#error "MESHLAB_SCALAR needs to be defined!" +#endif + +class RichParameterList; +class PluginManager; +class ActionSearcher; + +namespace meshlab { + +QString defaultPluginPath(); +QString defaultShadersPath(); +QString logDebugFileName(); + +RichParameterList& defaultGlobalParameterList(); +PluginManager& pluginManagerInstance(); +ActionSearcher& actionSearcherInstance(); + +// keep these functions inlined please +// each plugin that uses them need to have their own definition +// plugins cannot link them!! +inline std::string meshlabVersion() +{ + return std::string(meshlab_xstr(MESHLAB_VERSION)); +} + +std::string meshlabCompleteVersion(); + +inline bool builtWithDoublePrecision() +{ + return std::string(meshlab_xstr(MESHLAB_SCALAR)) == std::string("double"); +} + +} // namespace meshlab + +namespace pymeshlab { +class FunctionSet; + +FunctionSet& functionSetInstance(); +} // namespace pymeshlab + +#endif // MESHLAB_GLOBALS_H diff --git a/src/common/interfaces/iomesh_plugin_interface.h b/src/common/interfaces/iomesh_plugin_interface.h deleted file mode 100644 index 0246e8844..000000000 --- a/src/common/interfaces/iomesh_plugin_interface.h +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************** -* MeshLab o o * -* A versatile mesh processing toolbox o o * -* _ O _ * -* Copyright(C) 2005-2020 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ - -#ifndef MESHLAB_IOMESH_PLUGIN_INTERFACE_H -#define MESHLAB_IOMESH_PLUGIN_INTERFACE_H - -#include - -#include "plugin_interface.h" -#include "../utilities/file_format.h" - -/** \brief The IOPluginInterface is the base class for all the single mesh loading plugins. -*/ -class IOMeshPluginInterface : public PluginInterface -{ -public: - IOMeshPluginInterface() : PluginInterface() { } - virtual ~IOMeshPluginInterface() {} - - virtual QList importFormats() const = 0; - virtual QList exportFormats() const = 0; - - // This function is called to initialize the list of additional parameters that a OPENING filter could require - // it is called by the framework BEFORE the actual mesh loading to perform to determine how parse the input file - // The instanced parameters are then passed to the open at the loading time. - // Typical example of use to decide what subportion of a mesh you have to load. - // If you do not need any additional processing simply do not override this and ignore the parameterSet in the open - virtual void initPreOpenParameter(const QString &/*format*/, const QString &/*fileName*/, RichParameterList & /*par*/) {} - - // This function is called to initialize the list of additional parameters that a OPENING filter could require - // it is called by the framework AFTER the mesh is already loaded to perform more or less standard processing on the mesh. - // typical example: unifying vertices in stl models. - // If you do not need any additional processing do nothing. - virtual void initOpenParameter(const QString &/*format*/, MeshModel &/*m*/, RichParameterList & /*par*/) {} - - // This is the corresponding function that is called after the mesh is loaded with the initialized parameters - virtual void applyOpenParameter(const QString &/*format*/, MeshModel &/*m*/, const RichParameterList &/*par*/) {} - - // This function is called to initialize the list of additional parameters that a SAVING filter could require - // it is called by the framework after the mesh is loaded to perform more or less standard processing on the mesh. - // typical example: ascii or binary format for ply or stl - // If you do not need any additional parameter simply do nothing. - virtual void initSaveParameter(const QString &/*format*/, MeshModel &/*m*/, RichParameterList & /*par*/) {} - - - virtual void GetExportMaskCapability(const QString &format, int &capability, int &defaultBits) const = 0; - - /// callback used to actually load a mesh from a file - virtual bool open( - const QString &format, /// the extension of the format e.g. "PLY" - const QString &fileName, /// The name of the file to be opened - MeshModel &m, /// The mesh that is filled with the file content - int &mask, /// a bit mask that will be filled reporting what kind of data we have found in the file (per vertex color, texture coords etc) - const RichParameterList & par, /// The parameters that have been set up in the initPreOpenParameter() - vcg::CallBackPos *cb = nullptr, /// standard callback for reporting progress in the loading - QWidget *parent = nullptr) = 0; /// you should not use this... - - virtual bool save( - const QString &format, // the extension of the format e.g. "PLY" - const QString &fileName, - MeshModel &m, - const int mask,// a bit mask indicating what kind of the data present in the mesh should be saved (e.g. you could not want to save normals in ply files) - const RichParameterList & par, - vcg::CallBackPos *cb = 0, - QWidget *parent = 0) = 0; - - /// This function is invoked by the framework when the import/export plugin fails to give some info to the user about the failure - /// io plugins should avoid using QMessageBox for reporting errors. - /// Failure should put some meaningful information inside the errorMessage string. - const QString& errorMsg() const - { - return this->errorMessage; - } - void clearErrorString() - { - errorMessage.clear(); - } - -protected: - // this string is used to pass back to the framework error messages in case of failure of a filter apply. - // NEVER EVER use a msgbox to say something to the user. - QString errorMessage; - -}; - -#define MESHLAB_PLUGIN_IID_EXPORTER(x) Q_PLUGIN_METADATA(IID x) -#define MESHLAB_PLUGIN_NAME_EXPORTER(x) - -#define IOMESH_PLUGIN_INTERFACE_IID "vcg.meshlab.IOMeshPluginInterface/1.0" -Q_DECLARE_INTERFACE(IOMeshPluginInterface, IOMESH_PLUGIN_INTERFACE_IID) - -#endif // MESHLAB_IOMESH_PLUGIN_INTERFACE_H diff --git a/src/common/interfaces/plugin_interface.cpp b/src/common/interfaces/plugin_interface.cpp deleted file mode 100644 index 7161c8049..000000000 --- a/src/common/interfaces/plugin_interface.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "plugin_interface.h" - -PluginInterface::PluginInterface() : - logstream(nullptr) -{ -} - -void PluginInterface::setLog(GLLogStream* log) -{ - this->logstream = log; -} - -void PluginInterface::log(const char* s) -{ - if(logstream != nullptr) { - logstream->Log(GLLogStream::FILTER, s); - } -} - -void PluginInterface::log(const std::string& s) -{ - if(logstream != nullptr) { - logstream->Log(GLLogStream::FILTER, s); - } -} - -void PluginInterface::log(GLLogStream::Levels level, const char* s) -{ - if(logstream != nullptr) { - logstream->Log(level, s); - } -} - -void PluginInterface::log(GLLogStream::Levels level, const std::string& s) -{ - if(logstream != nullptr) { - logstream->Log(level, s); - } -} - -void PluginInterface::realTimeLog(QString Id, const QString& meshName, const char* f) -{ - if(logstream != nullptr) { - logstream->RealTimeLog(Id, meshName, f); - } -} diff --git a/src/common/meshlab-common.qrc b/src/common/meshlab-common.qrc new file mode 100644 index 000000000..2d3c3292e --- /dev/null +++ b/src/common/meshlab-common.qrc @@ -0,0 +1,6 @@ + + + resources/images/dummy.png + resources/git_sha.txt + + diff --git a/src/common/meshlabdocumentbundler.cpp b/src/common/meshlabdocumentbundler.cpp deleted file mode 100644 index 6244c706b..000000000 --- a/src/common/meshlabdocumentbundler.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "ml_document/mesh_document.h" -#include -#include "meshlabdocumentbundler.h" - -#include - -#include -#include - -bool MeshDocumentFromBundler(MeshDocument &md, QString filename_out,QString image_list_filename, QString model_filename) -{ - md.addNewMesh(model_filename,QString("model")); - std::vector shots; - const QString path = QFileInfo(filename_out).absolutePath(); - const QString path_im = QFileInfo(image_list_filename).absolutePath()+QString("/"); - - std::vector image_filenames; - vcg::tri::io::ImporterOUT::Open(md.mm()->cm,shots,image_filenames, qUtf8Printable(filename_out), qUtf8Printable(image_list_filename)); - md.mm()->updateDataMask(MeshModel::MM_VERTCOLOR); - - QString curr_path = QDir::currentPath(); - QFileInfo imi(image_list_filename); - - // - QStringList image_filenames_q; - for(unsigned int i = 0; i < image_filenames.size(); ++i) - { - QImageReader sizeImg(QString::fromStdString(image_filenames[i])); - if(sizeImg.size()==QSize(-1,-1)) - image_filenames_q.push_back(path_im+QString::fromStdString(image_filenames[i])); - else - image_filenames_q.push_back(QString::fromStdString(image_filenames[i])); - } - QDir::setCurrent(imi.absoluteDir().absolutePath()); - - for(size_t i=0 ; iaddPlane(new RasterPlane(fullpath_image_filename,RasterPlane::RGBA)); - int count=fullpath_image_filename.count('\\'); - if (count==0) - { - count=fullpath_image_filename.count('/'); - md.rm()->setLabel(fullpath_image_filename.section('/',count,1)); - } - else - md.rm()->setLabel(fullpath_image_filename.section('\\',count,1)); - md.rm()->shot = shots[i]; - } - QDir::setCurrent(curr_path); - - return true; -} - -bool MeshDocumentFromNvm(MeshDocument &md, QString filename_nvm, QString model_filename) -{ - md.addNewMesh(model_filename,QString("model")); - std::vector shots; - const QString path = QFileInfo(filename_nvm).absolutePath(); - //const QString path_im = QFileInfo(image_list_filename).absolutePath()+QString("/"); - - std::vector image_filenames; - vcg::tri::io::ImporterNVM::Open(md.mm()->cm,shots,image_filenames, qUtf8Printable(filename_nvm)); - md.mm()->updateDataMask(MeshModel::MM_VERTCOLOR); - - QString curr_path = QDir::currentPath(); - //QFileInfo imi(image_list_filename); - - //QDir::setCurrent(imi.absoluteDir().absolutePath()); - QStringList image_filenames_q; - for(size_t i = 0; i < image_filenames.size(); ++i) - image_filenames_q.push_back(QString::fromStdString(image_filenames[int(i)])); - - for(size_t i=0 ; iaddPlane(new RasterPlane(fullpath_image_filename,RasterPlane::RGBA)); - md.rm()->setLabel(image_filenames_q[int(i)].section('/',1,2)); - md.rm()->shot = shots[int(i)]; - /*md.rm()->shot.Intrinsics.ViewportPx[0]=md.rm()->currentPlane->image.width(); - md.rm()->shot.Intrinsics.ViewportPx[1]=md.rm()->currentPlane->image.height(); - md.rm()->shot.Intrinsics.CenterPx[0]=(int)((double)md.rm()->shot.Intrinsics.ViewportPx[0]/2.0f); - md.rm()->shot.Intrinsics.CenterPx[1]=(int)((double)md.rm()->shot.Intrinsics.ViewportPx[1]/2.0f);*/ - - } - QDir::setCurrent(curr_path); - - return true; -} diff --git a/src/common/meshlabdocumentbundler.h b/src/common/meshlabdocumentbundler.h deleted file mode 100644 index 5d0db63b2..000000000 --- a/src/common/meshlabdocumentbundler.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __MESHLABDOC_BUNDLER_H -#define __MESHLABDOC_BUNDLER_H - -#include "ml_document/mesh_model.h" - -bool MeshDocumentFromBundler(MeshDocument &md, QString filename_out, QString image_list_filename, QString model_filename); -bool MeshDocumentFromNvm(MeshDocument &md, QString filename_nvm, QString model_filename); - -#endif // __MESHLABDOC_BUNDLER_H diff --git a/src/common/meshlabdocumentxml.cpp b/src/common/meshlabdocumentxml.cpp deleted file mode 100644 index 2f2bd1681..000000000 --- a/src/common/meshlabdocumentxml.cpp +++ /dev/null @@ -1,281 +0,0 @@ -#include -#include -#include -#include - -#include "meshlabdocumentxml.h" -#include - -bool MeshDocumentToXMLFile(MeshDocument &md, QString filename, bool onlyVisibleLayers, bool saveViewState, bool binary, const std::map& rendOpt) -{ - md.setFileName(filename); - QFileInfo fi(filename); - QDir tmpDir = QDir::current(); - QDir::setCurrent(fi.absoluteDir().absolutePath()); - QDomDocument doc = MeshDocumentToXML(md, onlyVisibleLayers, saveViewState, binary, rendOpt); - QFile file(filename); - file.open(QIODevice::WriteOnly); - QTextStream qstream(&file); - doc.save(qstream, 1); - file.close(); - QDir::setCurrent(tmpDir.absolutePath()); - return true; -} - -QDomElement Matrix44mToXML(Matrix44m &m, QDomDocument &doc) -{ - QDomElement matrixElem = doc.createElement("MLMatrix44"); - QString Row[4]; - for (int i = 0; i < 4; ++i) - Row[i] = QString("%1 %2 %3 %4 \n").arg(m[i][0]).arg(m[i][1]).arg(m[i][2]).arg(m[i][3]); - - QDomText nd = doc.createTextNode("\n" + Row[0] + Row[1] + Row[2] + Row[3]); - matrixElem.appendChild(nd); - - return matrixElem; -} - -QDomElement Matrix44mToBinaryXML(Matrix44m &m, QDomDocument &doc) -{ - QDomElement matrixElem = doc.createElement("MLMatrix44"); - QByteArray value = QByteArray::fromRawData((char *)m.V(), sizeof(Matrix44m::ScalarType) * 16).toBase64(); - QDomText nd = doc.createTextNode(QString(value)); - matrixElem.appendChild(nd); - return matrixElem; -} - -bool MeshDocumentFromXML(MeshDocument &md, QString filename, bool binary, std::map& rendOpt) -{ - QFile qf(filename); - QFileInfo qfInfo(filename); - QDir tmpDir = QDir::current(); - QDir::setCurrent(qfInfo.absoluteDir().absolutePath()); - if (!qf.open(QIODevice::ReadOnly)) - return false; - - QString project_path = qfInfo.absoluteFilePath(); - - QDomDocument doc("MeshLabDocument"); //It represents the XML document - if (!doc.setContent(&qf)) - return false; - - QDomElement root = doc.documentElement(); - - QDomNode node; - - node = root.firstChild(); - - //Devices - while (!node.isNull()) { - if (QString::compare(node.nodeName(), "MeshGroup") == 0) - { - QDomNode mesh; QString filen, label; - mesh = node.firstChild(); - while (!mesh.isNull()) { - //return true; - filen = mesh.attributes().namedItem("filename").nodeValue(); - label = mesh.attributes().namedItem("label").nodeValue(); - bool visible = true; - if (mesh.attributes().contains("visible")) - visible = (mesh.attributes().namedItem("visible").nodeValue().toInt() == 1); - MeshModel* mm = md.addNewMesh(filen, label); - mm->visible = visible; - QDomNode tr = mesh.firstChildElement("MLMatrix44"); - - if (!tr.isNull()) - { - vcg::Matrix44f trm; - if (tr.childNodes().size() == 1) - { - if (!binary) - { - QStringList values = tr.firstChild().nodeValue().split(" ", QString::SkipEmptyParts); - for (int y = 0; y < 4; y++) - for (int x = 0; x < 4; x++) - md.mm()->cm.Tr[y][x] = values[x + 4 * y].toFloat(); - } - else - { - QString str = tr.firstChild().nodeValue(); - QByteArray value = QByteArray::fromBase64(str.toLocal8Bit()); - memcpy(md.mm()->cm.Tr.V(), value.data(), sizeof(Matrix44m::ScalarType) * 16); - } - } - } - - QDomNode renderingOpt = mesh.firstChildElement("RenderingOption"); - if (!renderingOpt.isNull()) - { - QString value = renderingOpt.firstChild().nodeValue(); - MLRenderingData::GLOptionsType opt; - if (renderingOpt.attributes().contains("pointSize")) - opt._perpoint_pointsize = renderingOpt.attributes().namedItem("pointSize").nodeValue().toFloat(); - if (renderingOpt.attributes().contains("wireWidth")) - opt._perwire_wirewidth = renderingOpt.attributes().namedItem("wireWidth").nodeValue().toFloat(); - if (renderingOpt.attributes().contains("boxColor")) - { - QStringList values = renderingOpt.attributes().namedItem("boxColor").nodeValue().split(" ", QString::SkipEmptyParts); - opt._perbbox_fixed_color = vcg::Color4b(values[0].toInt(), values[1].toInt(), values[2].toInt(), values[3].toInt()); - } - if (renderingOpt.attributes().contains("pointColor")) - { - QStringList values = renderingOpt.attributes().namedItem("pointColor").nodeValue().split(" ", QString::SkipEmptyParts); - opt._perpoint_fixed_color = vcg::Color4b(values[0].toInt(), values[1].toInt(), values[2].toInt(), values[3].toInt()); - } - if (renderingOpt.attributes().contains("wireColor")) - { - QStringList values = renderingOpt.attributes().namedItem("wireColor").nodeValue().split(" ", QString::SkipEmptyParts); - opt._perwire_fixed_color = vcg::Color4b(values[0].toInt(), values[1].toInt(), values[2].toInt(), values[3].toInt()); - } - if (renderingOpt.attributes().contains("solidColor")) - { - QStringList values = renderingOpt.attributes().namedItem("solidColor").nodeValue().split(" ", QString::SkipEmptyParts); - opt._persolid_fixed_color = vcg::Color4b(values[0].toInt(), values[1].toInt(), values[2].toInt(), values[3].toInt()); - } - MLRenderingData data; - data.set(opt); - if (data.deserialize(value.toStdString())) - rendOpt.insert(std::pair(mm->id(), data)); - } - - mesh = mesh.nextSibling(); - } - } - // READ IN POINT CORRESPONDECES INCOMPLETO!! - else if (QString::compare(node.nodeName(), "RasterGroup") == 0) - { - QDomNode raster; QString filen, label; - raster = node.firstChild(); - while (!raster.isNull()) - { - //return true; - md.addNewRaster(); - QString labelRaster = raster.attributes().namedItem("label").nodeValue(); - md.rm()->setLabel(labelRaster); - QDomNode sh = raster.firstChild(); - ReadShotFromQDomNode(md.rm()->shot, sh); - - QDomElement el = raster.firstChildElement("Plane"); - while (!el.isNull()) - { - QString filen = el.attribute("fileName"); - QFileInfo fi(filen); - QString sem = el.attribute("semantic"); - QString nm = fi.absoluteFilePath(); - md.rm()->addPlane(new RasterPlane(fi.absoluteFilePath(), RasterPlane::RGBA)); - el = node.nextSiblingElement("Plane"); - } - raster = raster.nextSibling(); - } - } - node = node.nextSibling(); - } - - QDir::setCurrent(tmpDir.absolutePath()); - qf.close(); - return true; -} - -QDomElement MeshModelToXML(MeshModel *mp, QDomDocument &doc, bool binary, bool saveViewState, const MLRenderingData& rendOpt = MLRenderingData()) -{ - QDomElement meshElem = doc.createElement("MLMesh"); - meshElem.setAttribute("label", mp->label()); - meshElem.setAttribute("filename", mp->relativePathName()); - meshElem.setAttribute("visible", saveViewState?mp->isVisible():true); - if (binary) - meshElem.appendChild(Matrix44mToBinaryXML(mp->cm.Tr, doc)); - else - meshElem.appendChild(Matrix44mToXML(mp->cm.Tr, doc)); - - if (saveViewState) - { - QDomElement renderingElem = doc.createElement("RenderingOption"); - std::string text; - rendOpt.serialize(text); - QDomText nd = doc.createTextNode(QString(text.c_str())); - renderingElem.appendChild(nd); - MLRenderingData::GLOptionsType opt; - if (rendOpt.get(opt)) - { - renderingElem.setAttribute("boxColor", QString("%1 %2 %3 %4").arg(opt._perbbox_fixed_color[0]).arg(opt._perbbox_fixed_color[1]).arg(opt._perbbox_fixed_color[2]).arg(opt._perbbox_fixed_color[3])); - renderingElem.setAttribute("pointColor", QString("%1 %2 %3 %4").arg(opt._perpoint_fixed_color[0]).arg(opt._perpoint_fixed_color[1]).arg(opt._perpoint_fixed_color[2]).arg(opt._perpoint_fixed_color[3])); - renderingElem.setAttribute("wireColor", QString("%1 %2 %3 %4").arg(opt._perwire_fixed_color[0]).arg(opt._perwire_fixed_color[1]).arg(opt._perwire_fixed_color[2]).arg(opt._perwire_fixed_color[3])); - renderingElem.setAttribute("solidColor", QString("%1 %2 %3 %4").arg(opt._persolid_fixed_color[0]).arg(opt._persolid_fixed_color[1]).arg(opt._persolid_fixed_color[2]).arg(opt._persolid_fixed_color[3])); - renderingElem.setAttribute("pointSize", opt._perpoint_pointsize); - renderingElem.setAttribute("wireWidth", opt._perwire_wirewidth); - } - meshElem.appendChild(renderingElem); - } - - return meshElem; -} - -QDomElement RasterModelToXML(RasterModel *mp, QDomDocument &doc, bool binary) -{ - QDomElement rasterElem = doc.createElement("MLRaster"); - rasterElem.setAttribute("label", mp->label()); - if (binary) - rasterElem.appendChild(WriteShotToQDomNodeBinary(mp->shot, doc)); - else - rasterElem.appendChild(WriteShotToQDomNode(mp->shot, doc)); - for (int ii = 0; ii < mp->planeList.size(); ++ii) - rasterElem.appendChild(PlaneToXML(mp->planeList[ii], mp->par->pathName(), doc)); - return rasterElem; -} - -QDomElement PlaneToXML(RasterPlane* pl, const QString& basePath, QDomDocument& doc) -{ - QDomElement planeElem = doc.createElement("Plane"); - QDir dir(basePath); - planeElem.setAttribute("fileName", dir.relativeFilePath(pl->fullPathFileName)); - planeElem.setAttribute("semantic", pl->semantic); - return planeElem; -} - -QDomDocument MeshDocumentToXML(MeshDocument &md, bool onlyVisibleLayers, bool saveViewState, bool binary, const std::map& rendOpt) -{ - QDomDocument ddoc("MeshLabDocument"); - - QDomElement root = ddoc.createElement("MeshLabProject"); - ddoc.appendChild(root); - QDomElement mgroot = ddoc.createElement("MeshGroup"); - - foreach(MeshModel *mmp, md.meshList) - { - if ((!onlyVisibleLayers) || (mmp->visible)) - { - QDomElement meshElem; - if (rendOpt.find(mmp->id()) != rendOpt.end()) - meshElem = MeshModelToXML(mmp, ddoc, binary, saveViewState, rendOpt.at(mmp->id())); - else - meshElem = MeshModelToXML(mmp, ddoc, binary, saveViewState); - mgroot.appendChild(meshElem); - } - } - root.appendChild(mgroot); - - QDomElement rgroot = ddoc.createElement("RasterGroup"); - - foreach(RasterModel *rmp, md.rasterList) - { - QDomElement rasterElem = RasterModelToXML(rmp, ddoc, binary); - rgroot.appendChild(rasterElem); - } - - root.appendChild(rgroot); - - // tag.setAttribute(QString("name"),(*ii).first); - // RichParameterSet &par=(*ii).second; - // QList::iterator jj; - // RichParameterXMLVisitor v(doc); - // for(jj=par.paramList.begin();jj!=par.paramList.end();++jj) - // { - // (*jj)->accept(v); - // tag.appendChild(v.parElem); - // } - // root.appendChild(tag); - // } - // - return ddoc; -} - diff --git a/src/common/meshlabdocumentxml.h b/src/common/meshlabdocumentxml.h deleted file mode 100644 index fef8e123e..000000000 --- a/src/common/meshlabdocumentxml.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __MESHLABDOC_XML_H -#define __MESHLABDOC_XML_H - -#include - -#include "ml_shared_data_context.h" -#include "ml_document/mesh_document.h" -#include - - -QDomDocument MeshDocumentToXML(MeshDocument &md, bool onlyVisibleLayers, bool saveViewState, bool binary, const std::map& rendOpt = std::map()); -bool MeshDocumentToXMLFile(MeshDocument &md, QString filename, bool onlyVisibleLayers, bool saveViewState, bool binary, const std::map& rendOpt = std::map()); -bool MeshDocumentFromXML(MeshDocument &md, QString filename, bool binary, std::map& rendOpt); -QDomElement RasterModelToXML(RasterModel *mp,QDomDocument &doc, bool binary); -QDomElement PlaneToXML(RasterPlane* pl,const QString& basePath,QDomDocument& doc); -#endif // __MESHLABDOC_XML_H diff --git a/src/common/ml_document/cmesh.cpp b/src/common/ml_document/cmesh.cpp index 8f5625af4..522c5eaf3 100644 --- a/src/common/ml_document/cmesh.cpp +++ b/src/common/ml_document/cmesh.cpp @@ -25,7 +25,7 @@ CMeshO::CMeshO() : vcgTriMesh(), - sfn(0), svn(0), pvn(0), pfn(0) + sfn(0), svn(0), pvn(0), pfn(0), Tr(Matrix44m::Identity()) { } @@ -33,30 +33,27 @@ CMeshO::CMeshO(const CMeshO& oth) : vcgTriMesh(), sfn(oth.sfn), svn(oth.svn), pvn(oth.pvn), pfn(oth.pfn), Tr(oth.Tr) { + enableComponentsFromOtherMesh(oth); vcg::tri::Append::MeshAppendConst(*this, oth); + textures = oth.textures; + normalmaps = oth.normalmaps; + imark = oth.imark; } -/// TODO: make a proper implementation of a move constructor. -/// Even if almost never used, this is very inefficient. -CMeshO::CMeshO(CMeshO&& oth): - vcgTriMesh(), sfn(oth.sfn), svn(oth.svn), - pvn(oth.pvn), pfn(oth.pfn), Tr(oth.Tr) +CMeshO::CMeshO(CMeshO&& oth) + : CMeshO() { - //I could take everything from oth and place it in - //this mesh - vcg::tri::Append::Mesh(*this, oth); + swap(*this, oth); } -/// TODO: change this and use the copy&swap idiom -CMeshO& CMeshO::operator=(const CMeshO& oth) +CMeshO::~CMeshO() { - Clear(); - vcg::tri::Append::MeshCopyConst(*this, oth); - sfn = oth.sfn; - svn = oth.svn; - pvn = oth.pvn; - pfn = oth.pfn; - Tr = oth.Tr; + //no need to call base class destructor. It is called automatically +} + +CMeshO& CMeshO::operator=(CMeshO oth) +{ + swap(*this, oth); return *this; } @@ -67,4 +64,55 @@ Box3m CMeshO::trBB() const return bb; } +/** + * @brief When copying a vcg mesh, it is first necessary to enable + * all the optional fields that are enabled on the other mesh, otherwise + * they won't be copied on this mesh........... + */ +void CMeshO::enableComponentsFromOtherMesh(const CMeshO& oth) +{ + //vertex + if (oth.vert.IsVFAdjacencyEnabled()) + this->vert.EnableVFAdjacency(); + if (oth.vert.IsMarkEnabled()) + this->vert.EnableMark(); + if (oth.vert.IsTexCoordEnabled()) + this->vert.EnableTexCoord(); + if (oth.vert.IsCurvatureDirEnabled()) + this->vert.EnableCurvatureDir(); + if (oth.vert.IsRadiusEnabled()) + this->vert.EnableRadius(); + //face + if (oth.face.IsQualityEnabled()) + this->face.EnableQuality(); + if (oth.face.IsMarkEnabled()) + this->face.EnableMark(); + if (oth.face.IsColorEnabled()) + this->face.EnableColor(); + if (oth.face.IsFFAdjacencyEnabled()) + this->face.EnableFFAdjacency(); + if (oth.face.IsVFAdjacencyEnabled()) + this->face.EnableVFAdjacency(); + if (oth.face.IsCurvatureDirEnabled()) + this->face.EnableCurvatureDir(); + if (oth.face.IsWedgeTexCoordEnabled()) + this->face.EnableWedgeTexCoord(); + + std::vector perVScalarAttrs, perVPointAttrs; + std::vector perFScalarAttrs, perFPointAttrs; + + vcg::tri::Allocator::GetAllPerVertexAttribute(oth, perVScalarAttrs); + vcg::tri::Allocator::GetAllPerVertexAttribute(oth, perVPointAttrs); + vcg::tri::Allocator::GetAllPerFaceAttribute(oth, perFScalarAttrs); + vcg::tri::Allocator::GetAllPerFaceAttribute(oth, perFPointAttrs); + + for(const std::string& attr : perVScalarAttrs) + vcg::tri::Allocator::AddPerVertexAttribute(*this, attr); + for(const std::string& attr : perVPointAttrs) + vcg::tri::Allocator::AddPerVertexAttribute(*this, attr); + for(const std::string& attr : perFScalarAttrs) + vcg::tri::Allocator::AddPerFaceAttribute(*this, attr); + for(const std::string& attr : perFPointAttrs) + vcg::tri::Allocator::AddPerFaceAttribute(*this, attr); +} diff --git a/src/common/ml_document/cmesh.h b/src/common/ml_document/cmesh.h index d262298bb..5245c51d5 100644 --- a/src/common/ml_document/cmesh.h +++ b/src/common/ml_document/cmesh.h @@ -42,11 +42,6 @@ template class Qualitym: public Quality { public: static void Name(std::vector & name){name.push_back(std::string("Qualitym"));T::Name(name);} }; -template class CurvaturemOcf: public CurvatureOcf { -public: static void Name(std::vector & name){name.push_back(std::string("CurvaturemOcf"));T::Name(name);} -}; - - template class CurvatureDirmOcf: public CurvatureDirOcf, T> { public: static void Name(std::vector & name){name.push_back(std::string("CurvatureDirmOcf"));T::Name(name);} }; @@ -99,7 +94,6 @@ class CVertexO : public vcg::Vertex< CUsedTypesO, vcg::vertex::VFAdjOcf, /* 0b */ vcg::vertex::MarkOcf, /* 0b */ vcg::vertex::TexCoordfOcf, /* 0b */ - vcg::vertex::CurvaturemOcf, /* 0b */ vcg::vertex::CurvatureDirmOcf, /* 0b */ vcg::vertex::RadiusmOcf /* 0b */ >{ @@ -139,8 +133,12 @@ public : CMeshO(const CMeshO& oth); CMeshO(CMeshO&& oth); + + virtual ~CMeshO(); - CMeshO& operator=(const CMeshO& oth); + CMeshO& operator=(CMeshO oth); + + friend void swap(CMeshO& m1, CMeshO& m2); Box3m trBB() const; @@ -151,6 +149,41 @@ public : int pfn; //the number of the polygonal faces Matrix44m Tr; // Usually it is the identity. It is applied in rendering and filters can or cannot use it. (most of the filter will ignore this) + +private: + void enableComponentsFromOtherMesh(const CMeshO& oth); }; +//must be inlined +inline void swap(CMeshO& m1, CMeshO& m2) +{ + using std::swap; + swap(m1.vn, m2.vn); + swap(m1.vert, m2.vert); + m1.vert._updateOVP(m1.vert.begin(), m1.vert.end()); + m2.vert._updateOVP(m2.vert.begin(), m2.vert.end()); + swap(m1.en, m2.en); + swap(m1.edge, m2.edge); + swap(m1.fn, m2.fn); + swap(m1.face, m2.face); + m1.face._updateOVP(m1.face.begin(), m1.face.end()); + m2.face._updateOVP(m2.face.begin(), m2.face.end()); + swap(m1.hn, m2.hn); + swap(m1.hedge, m2.hedge); + swap(m1.tn, m2.tn); + swap(m1.tetra, m2.tetra); + swap(m1.bbox, m2.bbox); + swap(m1.textures, m2.textures); + swap(m1.normalmaps, m2.normalmaps); + swap(m1.attrn, m2.attrn); + swap(m1.vert_attr, m2.vert_attr); + swap(m1.edge_attr, m2.edge_attr); + swap(m1.face_attr, m2.face_attr); + swap(m1.mesh_attr, m2.mesh_attr); + swap(m1.tetra_attr, m2.tetra_attr); + swap(m1.shot, m2.shot); + swap(m1.imark, m2.imark); +} + + #endif //CMESH_H diff --git a/src/common/ml_document/helpers/mesh_document_state_data.cpp b/src/common/ml_document/helpers/mesh_document_state_data.cpp index 9a60edc0c..83b6cf1d5 100644 --- a/src/common/ml_document/helpers/mesh_document_state_data.cpp +++ b/src/common/ml_document/helpers/mesh_document_state_data.cpp @@ -16,11 +16,8 @@ MeshDocumentStateData::~MeshDocumentStateData() void MeshDocumentStateData::create(MeshDocument& md) { QWriteLocker locker(&_lock); - for (int ii = 0; ii < md.meshList.size(); ++ii) - { - MeshModel* mm = md.meshList[ii]; - if (mm != NULL) - insert(mm->id(), MeshModelStateData(mm->dataMask(), mm->cm.VN(), mm->cm.FN(), mm->cm.EN())); + for (MeshModel& mm : md.meshIterator()) { + insert(mm.id(), MeshModelStateData(mm.dataMask(), mm.cm.VN(), mm.cm.FN(), mm.cm.EN())); } } diff --git a/src/common/ml_document/mesh_document.cpp b/src/common/ml_document/mesh_document.cpp index d35aca151..4f8330e29 100644 --- a/src/common/ml_document/mesh_document.cpp +++ b/src/common/ml_document/mesh_document.cpp @@ -2,7 +2,7 @@ * MeshLab o o * * Visual and Computer Graphics Library o o * * _ O _ * -* Copyright(C) 2004-2020 \/)\/ * +* Copyright(C) 2004-2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -24,51 +24,49 @@ #include "mesh_document.h" template -QString NameDisambiguator(QList &elemList, QString meshLabel ) +QString nameDisambiguator(std::list &elemList, QString meshLabel) { QString newName=std::move(meshLabel); - typename QList::iterator mmi; - + typename std::list::iterator mmi; + for(mmi=elemList.begin(); mmi!=elemList.end(); ++mmi) { - if((*mmi)->label() == newName) // if duplicated name found + if((*mmi).label() == newName) // if duplicated name found { - QFileInfo fi((*mmi)->label()); + QFileInfo fi((*mmi).label()); QString baseName = fi.baseName(); // all characters in the file up to the first '.' Eg "/tmp/archive.tar.gz" -> "archive" QString suffix = fi.suffix(); bool ok; - + // if name ends with a number between parenthesis (XXX), // it was himself a duplicated name, and we need to // just increase the number between parenthesis int numDisamb; int startDisamb; int endDisamb; - + startDisamb = baseName.lastIndexOf("("); endDisamb = baseName.lastIndexOf(")"); if((startDisamb!=-1)&&(endDisamb!=-1)) - numDisamb = (baseName.mid((startDisamb+1),(endDisamb-startDisamb-1))).toInt(&ok); + numDisamb = baseName.midRef((startDisamb+1),(endDisamb-startDisamb-1)).toInt(&ok); else numDisamb = 0; - + if(startDisamb!=-1) newName = baseName.left(startDisamb)+ "(" + QString::number(numDisamb+1) + ")"; else newName = baseName + "(" + QString::number(numDisamb+1) + ")"; - + if (suffix != QString("")) newName = newName + "." + suffix; - + // now recurse to see if the new name is free - newName = NameDisambiguator(elemList, newName); + newName = nameDisambiguator(elemList, newName); } } return newName; } - - MeshDocument::MeshDocument() { meshIdCounter=0; @@ -78,25 +76,15 @@ MeshDocument::MeshDocument() busy=false; } -//deletes each meshModel MeshDocument::~MeshDocument() { - for(MeshModel *mmp : meshList) - delete mmp; - for(RasterModel* rmp : rasterList) - delete rmp; } void MeshDocument::clear() { - for(MeshModel *mmp : meshList) - delete mmp; meshList.clear(); - - for(RasterModel* rmp :rasterList) - delete rmp; rasterList.clear(); - + meshIdCounter=0; rasterIdCounter=0; currentMesh = nullptr; @@ -108,28 +96,28 @@ void MeshDocument::clear() meshDocStateData().clear(); } -const MeshModel* MeshDocument::getMesh(int id) const +const MeshModel* MeshDocument::getMesh(unsigned int id) const { - for (const MeshModel* m : meshList) - if (m->id() == id) - return m; + for (const MeshModel& m : meshList) + if ((unsigned int)m.id() == id) + return &m; return nullptr; } -//returns the mesh ata given position in the list -MeshModel* MeshDocument::getMesh(int id) +MeshModel* MeshDocument::getMesh(unsigned int id) { - for (MeshModel* m : meshList) - if (m->id() == id) - return m; + for (MeshModel& m : meshList) { + if ((unsigned int)m.id() == id) { + return &m; + } + } return nullptr; } void MeshDocument::setCurrentMesh(int new_curr_id) { - if(new_curr_id<0) - { - currentMesh=0; + if(new_curr_id<0) { + currentMesh = nullptr; return; } currentMesh = getMesh(new_curr_id); @@ -137,35 +125,32 @@ void MeshDocument::setCurrentMesh(int new_curr_id) assert(currentMesh); } -//returns the raster at a given position in the list -RasterModel *MeshDocument::getRaster(int i) +void MeshDocument::setVisible(int meshId, bool val) { - foreach(RasterModel *rmp, rasterList) - { - if(rmp->id() == i) return rmp; - } - //assert(0); - return 0; + getMesh(meshId)->setVisible(val); + emit meshSetChanged(); } -//if i is <0 it means that no currentRaster is set -void MeshDocument::setCurrentRaster( int new_curr_id) +//returns the raster at a given position in the list +RasterModel *MeshDocument::getRaster(unsigned int i) { - if(new_curr_id<0) - { - currentRaster=0; - return; - } - - foreach(RasterModel *rmp, rasterList) - { - if(rmp->id() == new_curr_id) - { - currentRaster = rmp; - return; + for(RasterModel& rmp : rasterList) { + if(rmp.id() == i) { + return &rmp; } } - assert(0); + return nullptr; +} + +void MeshDocument::setCurrentRaster(int new_curr_id) +{ + if(new_curr_id<0) { + currentRaster = nullptr; + return; + } + + currentRaster = getRaster(new_curr_id); + assert(currentRaster); } void MeshDocument::setCurrent(MeshModel* newCur) @@ -183,7 +168,7 @@ MeshModel* MeshDocument::nextVisibleMesh(MeshModel* _m) MeshModel *newM = nextMesh(_m); if(newM==0) return newM; - + if(newM->isVisible()) return newM; else @@ -192,27 +177,32 @@ MeshModel* MeshDocument::nextVisibleMesh(MeshModel* _m) MeshModel* MeshDocument::nextMesh(MeshModel* _m) { - if(_m==0 && meshList.size()>0) - return meshList.at(0); - for (int i = 0; i < meshList.size(); ++i) { - if (meshList.at(i) == _m) { - if(i+1 < meshList.size()) - return meshList.at(i+1); + if(_m == nullptr && meshList.size()>0) + return &meshList.front(); + for (auto it = meshList.begin(); it != meshList.end(); ++it) { + if (&(*it) == _m) { + auto next = it; + next++; + if(next != meshList.end()) + return &(*next); } } - return 0; + return nullptr; } RasterModel* MeshDocument::nextRaster(RasterModel* _rm) { - for (int i = 0; i < rasterList.size(); ++i) { - if (rasterList.at(i) == _rm) - { - if(i+1 < rasterList.size()) - return rasterList.at(i+1); + if(_rm == nullptr && rasterList.size()>0) + return &rasterList.front(); + for (auto it = rasterList.begin(); it != rasterList.end(); ++it) { + if (&(*it) == _rm) { + auto next = it; + next++; + if(next != rasterList.end()) + return &(*next); } } - return 0; + return nullptr; } MeshModel* MeshDocument::mm() @@ -230,18 +220,13 @@ RasterModel* MeshDocument::rm() return currentRaster; } -unsigned int MeshDocument::newMeshId() +const RasterModel* MeshDocument::rm() const { - return meshIdCounter++; -} - -unsigned int MeshDocument::newRasterId() -{ - return rasterIdCounter++; + return currentRaster; } void MeshDocument::requestUpdatingPerMeshDecorators(int mesh_id) -{ +{ emit updateDecorators(mesh_id); } @@ -271,12 +256,12 @@ void MeshDocument::setFileName(const QString& newFileName) fullPathFilename = newFileName; } -int MeshDocument::size() const +unsigned int MeshDocument::meshNumber() const { return meshList.size(); } -int MeshDocument::sizeRasters() const +unsigned int MeshDocument::rasterNumber() const { return rasterList.size(); } @@ -291,137 +276,260 @@ void MeshDocument::setBusy(bool _busy) busy=_busy; } -MeshModel * MeshDocument::addNewMesh(QString fullPath, QString label, bool setAsCurrent) +/** + * @brief Adds a new mesh to the MeshDocument. The added mesh is a COPY of the mesh + * passed as parameter. + */ +MeshModel* MeshDocument::addNewMesh( + const CMeshO& mesh, + const QString& label, + bool setAsCurrent) { - QString newlabel = NameDisambiguator(this->meshList,std::move(label)); - + MeshModel* m = addNewMesh("", label, setAsCurrent); + m->cm = mesh; + m->updateBoxAndNormals(); + m->updateDataMask(); + return m; +} + +MeshModel* MeshDocument::addNewMesh( + QString fullPath, + const QString& label, + bool setAsCurrent) +{ + QString newlabel = nameDisambiguator(this->meshList, label); + if(!fullPath.isEmpty()) { QFileInfo fi(fullPath); fullPath = fi.absoluteFilePath(); } - - MeshModel *newMesh = new MeshModel(this, newMeshId(), fullPath,newlabel); - meshList.push_back(newMesh); - + + meshList.push_back(MeshModel(newMeshId(), fullPath,newlabel)); + MeshModel& newMesh = meshList.back(); + if(setAsCurrent) - this->setCurrentMesh(newMesh->id()); - + this->setCurrentMesh(newMesh.id()); + emit meshSetChanged(); - emit meshAdded(newMesh->id()); - return newMesh; + emit meshAdded(newMesh.id()); + return &newMesh; } -MeshModel * MeshDocument::addOrGetMesh(QString fullPath, const QString& label, bool setAsCurrent) +MeshModel* MeshDocument::addOrGetMesh( + const QString& fullPath, + const QString& label, + bool setAsCurrent) { - MeshModel *newMesh = nullptr; - for (MeshModel* m : meshList) - if (m->shortName() == label) - newMesh = m; + MeshModel* newMesh = nullptr; + for (MeshModel& m : meshList) + if (m.shortName() == label) + newMesh = &m; if(newMesh) { if(setAsCurrent) this->setCurrentMesh(newMesh->id()); return newMesh; } - return addNewMesh(std::move(fullPath),label,setAsCurrent); + return addNewMesh(fullPath,label,setAsCurrent); } -bool MeshDocument::delMesh(MeshModel *mmToDel) +/** + * Returns the ordered list of the meshes loaded from the same + * file in which has been loaded the model mm. + */ +std::list MeshDocument::getMeshesLoadedFromSameFile(MeshModel& mm) { - if(!meshList.removeOne(mmToDel)) + std::list ml; + if (mm.idInFile() == -1){ + ml.push_back(&mm); + } + else { + if (!mm.fullName().isEmpty()){ + for (MeshModel& m : meshList){ + if (m.fullName() == mm.fullName()) + ml.push_back(&m); + } + } + } + return ml; +} + +bool MeshDocument::delMesh(unsigned int id) +{ + auto pos = meshList.end(); + for (auto it = meshList.begin(); it != meshList.end(); ++it) + if ((unsigned int)it->id() == id) + pos = it; + if (pos == meshList.end()) return false; - if((currentMesh == mmToDel) && (!meshList.empty())) - setCurrentMesh(this->meshList.at(0)->id()); - else if (meshList.empty()) - setCurrentMesh(-1); - - int index = mmToDel->id(); - delete mmToDel; - - emit meshSetChanged(); - emit meshRemoved(index); + + eraseMesh(pos); return true; } +MeshDocument::MeshIterator MeshDocument::eraseMesh(MeshIterator it) +{ + if (it != meshList.end()) { + int id = it->id(); + // no other meshes, therefore no current mesh after deleting this one + if (meshList.size() == 1) { + setCurrentMesh(-1); + } + else { // other meshes, I need to choose which one will become the current mesh + auto next = it; + next++; + if (next != meshList.end()) // if there is a next, will be the next one + setCurrentMesh(next->id()); + else // no next, I set the first mesh as current + setCurrentMesh(this->meshList.front().id()); + } + + it = meshList.erase(it); + + emit meshSetChanged(); + emit meshRemoved(id); + } + + return it; +} + RasterModel * MeshDocument::addNewRaster(/*QString fullPathFilename*/) { QFileInfo info(fullPathFilename); QString newLabel=info.fileName(); - QString newName = NameDisambiguator(this->rasterList, newLabel); - - RasterModel *newRaster=new RasterModel(this, newRasterId(), newLabel); - rasterList.push_back(newRaster); - - //Add new plane - //Plane *plane = new Plane(newRaster, fullPathFilename, QString()); - //newRaster->addPlane(plane); - - this->setCurrentRaster(newRaster->id()); - + + rasterList.push_back(RasterModel(newRasterId(), newLabel)); + RasterModel& newRaster = rasterList.back(); + + this->setCurrentRaster(newRaster.id()); + emit rasterSetChanged(); - return newRaster; + return &newRaster; } -bool MeshDocument::delRaster(RasterModel *rasterToDel) +bool MeshDocument::delRaster(unsigned int id) { - QMutableListIterator i(rasterList); - - while (i.hasNext()) - { - RasterModel *r = i.next(); - - if (r==rasterToDel) - { - i.remove(); - delete rasterToDel; - } - } - - if(currentRaster == rasterToDel) - { - if (!rasterList.empty()) - setCurrentRaster(rasterList.at(0)->id()); - else - setCurrentRaster(-1); - } + auto pos = rasterList.end(); + for (auto it = rasterList.begin(); it != rasterList.end(); ++it) + if (it->id() == id) + pos = it; + if (pos == rasterList.end()) + return false; + + if((currentRaster == &(*pos)) && (!rasterList.empty())) + setCurrentRaster(rasterList.front().id()); + else if (rasterList.empty()) + setCurrentRaster(-1); + + rasterList.erase(pos); + emit rasterSetChanged(); - + return true; } -int MeshDocument::vn() +MeshDocument::RasterIterator MeshDocument::eraseRaster(RasterIterator it) +{ + return rasterList.erase(it); +} + +int MeshDocument::vn() const { int tot=0; - for(MeshModel* mmp : meshList) - tot+= mmp->cm.vn; + for(const MeshModel& mmp : meshList) + tot+= mmp.cm.vn; return tot; } -int MeshDocument::fn() +int MeshDocument::fn() const { int tot=0; - for(MeshModel *mmp : meshList) - tot+= mmp->cm.fn; + for(const MeshModel& mmp : meshList) + tot+= mmp.cm.fn; return tot; } -Box3m MeshDocument::bbox() +Box3m MeshDocument::bbox() const { Box3m FullBBox; - for(MeshModel * mp : meshList) - FullBBox.Add(mp->cm.Tr,mp->cm.bbox); + for(const MeshModel& mp : meshList) + FullBBox.Add(mp.cm.Tr,mp.cm.bbox); return FullBBox; } -bool MeshDocument::hasBeenModified() +bool MeshDocument::hasBeenModified() const { - for(MeshModel *m : meshList) - if(m->meshModified()) return true; + for(const MeshModel& m : meshList) + if(m.meshModified()) return true; return false; } +MeshDocument::MeshIterator MeshDocument::meshBegin() +{ + return meshList.begin(); +} + +MeshDocument::MeshIterator MeshDocument::meshEnd() +{ + return meshList.end(); +} + +MeshDocument::RasterIterator MeshDocument::rasterBegin() +{ + return rasterList.begin(); +} + +MeshDocument::RasterIterator MeshDocument::rasterEnd() +{ + return rasterList.end(); +} + +MeshDocument::ConstMeshIterator MeshDocument::meshBegin() const +{ + return meshList.begin(); +} + +MeshDocument::ConstMeshIterator MeshDocument::meshEnd() const +{ + return meshList.end(); +} + +MeshDocument::ConstRasterIterator MeshDocument::rasterBegin() const +{ + return rasterList.begin(); +} + +MeshDocument::ConstRasterIterator MeshDocument::rasterEnd() const +{ + return rasterList.end(); +} + MeshDocument::MeshRangeIterator MeshDocument::meshIterator() { - return MeshRangeIterator(this); + return MeshRangeIterator(*this); } +MeshDocument::ConstMeshRangeIterator MeshDocument::meshIterator() const +{ + return ConstMeshRangeIterator(*this); +} + +MeshDocument::RasterRangeIterator MeshDocument::rasterIterator() +{ + return RasterRangeIterator(*this); +} + +MeshDocument::ConstRasterRangeIterator MeshDocument::rasterIterator() const +{ + return ConstRasterRangeIterator(*this); +} + +unsigned int MeshDocument::newMeshId() +{ + return meshIdCounter++; +} + +unsigned int MeshDocument::newRasterId() +{ + return rasterIdCounter++; +} diff --git a/src/common/ml_document/mesh_document.h b/src/common/ml_document/mesh_document.h index 67d45bcc4..11d8a0f57 100644 --- a/src/common/ml_document/mesh_document.h +++ b/src/common/ml_document/mesh_document.h @@ -2,7 +2,7 @@ * MeshLab o o * * Visual and Computer Graphics Library o o * * _ O _ * -* Copyright(C) 2004-2020 \/)\/ * +* Copyright(C) 2004-2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -32,149 +32,205 @@ class MeshDocument : public QObject { Q_OBJECT - + public: + + // Iterators + typedef std::list::iterator MeshIterator; + typedef std::list::const_iterator ConstMeshIterator; + typedef std::list::iterator RasterIterator; + typedef std::list::const_iterator ConstRasterIterator; + + class MeshRangeIterator + { + friend class MeshDocument; + public: + MeshIterator begin() {return md.meshBegin();} + MeshIterator end() {return md.meshEnd();} + private: + MeshRangeIterator(MeshDocument& md) : md(md){} + MeshDocument& md; + }; + + class ConstMeshRangeIterator + { + friend class MeshDocument; + public: + ConstMeshIterator begin() {return md.meshBegin();} + ConstMeshIterator end() {return md.meshEnd();} + private: + ConstMeshRangeIterator(const MeshDocument& md) : md(md){} + const MeshDocument& md; + }; + + class RasterRangeIterator + { + friend class MeshDocument; + public: + RasterIterator begin() {return md.rasterBegin();} + RasterIterator end() {return md.rasterEnd();} + private: + RasterRangeIterator(MeshDocument& md) : md(md){} + MeshDocument& md; + }; + + class ConstRasterRangeIterator + { + friend class MeshDocument; + public: + ConstRasterIterator begin() {return md.rasterBegin();} + ConstRasterIterator end() {return md.rasterEnd();} + private: + ConstRasterRangeIterator(const MeshDocument& md) : md(md){} + const MeshDocument& md; + }; + MeshDocument(); - + //deletes each meshModel ~MeshDocument(); - + void clear(); - + ///returns the mesh with the given unique id - const MeshModel* getMesh(int id) const; - MeshModel* getMesh(int id); - + const MeshModel* getMesh(unsigned int id) const; + MeshModel* getMesh(unsigned int id); + //set the current mesh to be the one with the given ID void setCurrentMesh( int new_curr_id ); void setVisible(int meshId, bool val); - + /// returns the raster with the given unique id - RasterModel *getRaster(int i); - + RasterModel *getRaster(unsigned int i); + //set the current raster to be the one with the given ID void setCurrentRaster( int new_curr_id ); void setCurrent(MeshModel *newCur); void setCurrent(RasterModel *newCur); - + /// methods to access the set of Meshes in a ordered fashion. MeshModel *nextVisibleMesh(MeshModel *_m = nullptr); - + MeshModel *nextMesh(MeshModel *_m = nullptr); /// methods to access the set of Meshes in a ordered fashion. RasterModel *nextRaster(RasterModel *_rm = nullptr); - + MeshModel* mm(); - + const MeshModel* mm() const; - + //Could return 0 if no raster has been selected RasterModel *rm(); + const RasterModel* rm() const; void requestUpdatingPerMeshDecorators(int mesh_id); - + MeshDocumentStateData& meshDocStateData(); void setDocLabel(const QString& docLb); QString docLabel() const; QString pathName() const; void setFileName(const QString& newFileName); - - - int size() const; - int sizeRasters() const; + + unsigned int meshNumber() const; + unsigned int rasterNumber() const; + bool isBusy(); // used in processing. To disable access to the mesh by the rendering thread void setBusy(bool _busy); ///add a new mesh with the given name - MeshModel *addNewMesh(QString fullPath, QString Label, bool setAsCurrent=true); - MeshModel *addOrGetMesh(QString fullPath, const QString& Label, bool setAsCurrent=true); - - + MeshModel* addNewMesh(const CMeshO& mesh, const QString& Label, bool setAsCurrent=true); + MeshModel *addNewMesh(QString fullPath, const QString& Label, bool setAsCurrent=true); + MeshModel *addOrGetMesh(const QString& fullPath, const QString& Label, bool setAsCurrent=true); + std::list getMeshesLoadedFromSameFile(MeshModel& mm); + ///remove the mesh from the list and delete it from memory - bool delMesh(MeshModel *mmToDel); - + bool delMesh(unsigned int id); + MeshIterator eraseMesh(MeshIterator it); + ///add a new raster model RasterModel *addNewRaster(/*QString rasterName*/); - - ///remove the raster from the list and delete it from memory - bool delRaster(RasterModel *rasterToDel); - - int vn(); /// Sum of all the vertices of all the meshes - int fn(); - - Box3m bbox(); - - bool hasBeenModified(); - - class MeshRangeIterator - { - friend class MeshDocument; - public: - QList::iterator begin() {return md->meshList.begin();} - QList::iterator end() {return md->meshList.end();} - private: - MeshRangeIterator(MeshDocument* md) : md(md){} - MeshDocument* md; - }; - + ///remove the raster from the list and delete it from memory + bool delRaster(unsigned int id); + RasterIterator eraseRaster(RasterIterator it); + + int vn() const; /// Sum of all the vertices of all the meshes + + int fn() const; + + Box3m bbox() const; + + bool hasBeenModified() const; + + //iterator member functions + MeshIterator meshBegin(); + MeshIterator meshEnd(); + RasterIterator rasterBegin(); + RasterIterator rasterEnd(); + ConstMeshIterator meshBegin() const; + ConstMeshIterator meshEnd() const; + ConstRasterIterator rasterBegin() const; + ConstRasterIterator rasterEnd() const; + MeshRangeIterator meshIterator(); - + ConstMeshRangeIterator meshIterator() const; + RasterRangeIterator rasterIterator(); + ConstRasterRangeIterator rasterIterator() const; + GLLogStream Log; FilterScript filterHistory; - + +private: /// The very important member: /// The list of MeshModels. - QList meshList; + std::list meshList; /// The list of the raster models of the project - QList rasterList; - -private: + std::list rasterList; + int meshIdCounter; int rasterIdCounter; - + /** All the files referred in a document are relative to the folder containing the project file. this is the full path to the document. */ QString fullPathFilename; - + //it is the label of the document. it should only be something like Project_n (a temporary name for a new empty document) or the fullPathFilename. QString documentLabel; - + MeshDocumentStateData mdstate; - + bool busy; - - MeshModel *currentMesh; + + MeshModel* currentMesh; //the current raster model RasterModel* currentRaster; - + unsigned int newMeshId(); unsigned int newRasterId(); - + signals: ///whenever the current mesh is changed (e.g. the user click on a different mesh) // this signal will send out with the index of the newest mesh void currentMeshChanged(int index); - + /// whenever the document (or even a single mesh) is modified by a filter void meshDocumentModified(); - + ///whenever the meshList is changed void meshSetChanged(); - + void meshAdded(int index); void meshRemoved(int index); - + ///whenever the rasterList is changed void rasterSetChanged(); - + //this signal is emitted when a filter request to update the mesh in the renderingState void documentUpdated(); void updateDecorators(int mesh_id); - };// end class MeshDocument diff --git a/src/common/ml_document/mesh_model.cpp b/src/common/ml_document/mesh_model.cpp index 75e942201..2a4841a1f 100644 --- a/src/common/ml_document/mesh_model.cpp +++ b/src/common/ml_document/mesh_model.cpp @@ -2,7 +2,7 @@ * MeshLab o o * * Visual and Computer Graphics Library o o * * _ O _ * -* Copyright(C) 2004-2020 \/)\/ * +* Copyright(C) 2004-2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -21,13 +21,12 @@ * * ****************************************************************************/ - #include #include #include #include "mesh_model.h" -#include "mesh_document.h" +#include "../utilities/load_save.h" #include @@ -36,177 +35,351 @@ using namespace vcg; -void MeshModel::Clear() +MeshModel::MeshModel(int id, const QString& fullFileName, const QString& labelName) : + visible(true) +{ + /*glw.m = &(cm);*/ + clear(); + _id=id; + if(!fullFileName.isEmpty()) this->fullPathFileName=fullFileName; + if(!labelName.isEmpty()) this->_label=labelName; +} + +void MeshModel::clear() { setMeshModified(false); - // These data are always active on the mesh - currentDataMask = MM_NONE; - currentDataMask |= MM_VERTCOORD | MM_VERTNORMAL | MM_VERTFLAG ; - currentDataMask |= MM_FACEVERT | MM_FACENORMAL | MM_FACEFLAG ; + // These data are always active on the mesh + currentDataMask = MM_NONE; + currentDataMask |= MM_VERTCOORD | MM_VERTNORMAL | MM_VERTFLAG ; + currentDataMask |= MM_FACEVERT | MM_FACENORMAL | MM_FACEFLAG ; - visible=true; - cm.Tr.SetIdentity(); - cm.sfn=0; - cm.svn=0; + visible=true; + cm.Tr.SetIdentity(); + cm.sfn=0; + cm.svn=0; } -void MeshModel::UpdateBoxAndNormals() +void MeshModel::updateBoxAndNormals() { - tri::UpdateBounding::Box(cm); - if(cm.fn>0) { - tri::UpdateNormal::PerFaceNormalized(cm); - tri::UpdateNormal::PerVertexAngleWeighted(cm); - } + tri::UpdateBounding::Box(cm); + if(cm.fn>0) { + tri::UpdateNormal::PerFaceNormalized(cm); + tri::UpdateNormal::PerVertexAngleWeighted(cm); + } } -MeshModel::MeshModel(MeshDocument *_parent, unsigned int id, const QString& fullFileName, const QString& labelName) +QString MeshModel::relativePathName(const QString& path) const { - /*glw.m = &(cm);*/ - Clear(); - parent=_parent; - _id=id; - if(!fullFileName.isEmpty()) this->fullPathFileName=fullFileName; - if(!labelName.isEmpty()) this->_label=labelName; + QDir documentDir (path); + QString relPath=documentDir.relativeFilePath(this->fullPathFileName); + + //if(relPath.size()>1 && relPath[0]=='.' && relPath[1]=='.') + // qDebug("Error we have a mesh that is not in the same folder of the project: %s ", qUtf8Printable(relPath)); + + return relPath; } -QString MeshModel::relativePathName() const +/** + * @brief Starting from the (still unloaded) textures contained in the contained + * CMeshO, loads the textures in the map of QImages contained in the MeshModel. + * + * The contained CMeshO will have a list of texture names like "filename.png", + * and these names will be mapped with the actual loaded image in the map + * "textures". + * + * When a texture is not found, a dummy texture will be used (":/resources/images/dummy.png"). + * + * Returns the list of non-loaded textures that have been modified with + * ":/img/dummy.png" in the contained mesh. + */ +std::list MeshModel::loadTextures( + GLLogStream* log, + vcg::CallBackPos* cb) { - QDir documentDir (documentPathName()); - QString relPath=documentDir.relativeFilePath(this->fullPathFileName); - - if(relPath.size()>1 && relPath[0]=='.' && relPath[1]=='.') - qDebug("Error we have a mesh that is not in the same folder of the project: %s ", qUtf8Printable(relPath)); - - return relPath; + std::list unloadedTextures; + for (std::string& textName : cm.textures){ + if (textures.find(textName) == textures.end()){ + QImage img(":/resources/images/dummy.png"); + QFileInfo finfo(QString::fromStdString(textName)); + try { + img = meshlab::loadImage(finfo.absoluteFilePath(), log, cb); + textName = finfo.fileName().toStdString(); + } catch (const MLException& e) { + try { //could be relative to the meshmodel + QFileInfo mfi(fullName()); + QString fn2 = mfi.absolutePath() + "/" + finfo.filePath(); + img = meshlab::loadImage(fn2, log, cb); + textName = finfo.filePath().toStdString(); + } catch (const MLException& e) { + if (log){ + log->log( + GLLogStream::WARNING, "Failed loading " + textName + + "; using a dummy texture"); + } + else { + std::cerr << + "Failed loading " + textName + "; using a dummy texture\n"; + } + unloadedTextures.push_back(textName); + textName = "dummy.png"; + } + } + textures[textName] = img; + } + } + return unloadedTextures; } -QString MeshModel::documentPathName() const +void MeshModel::saveTextures( + const QString& basePath, + int quality, + GLLogStream* log, + CallBackPos* cb) { - return parent->pathName(); + for (const std::string& tname : cm.textures){ + meshlab::saveImage( + basePath + "/" + QString::fromStdString(tname), + textures.at(tname), quality, log, cb); + } +} + +QImage MeshModel::getTexture(const std::string& tn) const +{ + auto it = textures.find(tn); + if (it != textures.end()) + return it->second; + else + return QImage(); +} + +const std::map& MeshModel::getTextures() const +{ + return textures; +} + +void MeshModel::clearTextures() +{ + textures.clear(); + cm.textures.clear(); +} + +void MeshModel::addTexture(std::string name, const QImage& txt) +{ + if (textures.find(name) == textures.end()){ + // just to be sure to not make duplicates in the contained mesh list of textures + if (std::find(cm.textures.begin(), cm.textures.end(), name) == cm.textures.end()) + cm.textures.push_back(name); + textures[name]=txt; + } +} + +void MeshModel::setTexture(std::string name, const QImage& txt) +{ + auto it = textures.find(name); + if (it != textures.end()) + it->second = txt; +} + +void MeshModel::changeTextureName( + const std::string& oldName, + std::string newName) +{ + if (oldName != newName) { + auto mit = textures.find(oldName); + auto tit = std::find(cm.textures.begin(), cm.textures.end(), oldName); + if (mit != textures.end() && tit != cm.textures.end()){ + *tit = newName; + + textures[newName] = mit->second; + textures.erase(mit); + } + } } int MeshModel::io2mm(int single_iobit) { - switch(single_iobit) - { - case tri::io::Mask::IOM_NONE : return MM_NONE; - case tri::io::Mask::IOM_VERTCOORD : return MM_VERTCOORD; - case tri::io::Mask::IOM_VERTCOLOR : return MM_VERTCOLOR; - case tri::io::Mask::IOM_VERTFLAGS : return MM_VERTFLAG; - case tri::io::Mask::IOM_VERTQUALITY : return MM_VERTQUALITY; - case tri::io::Mask::IOM_VERTNORMAL : return MM_VERTNORMAL; - case tri::io::Mask::IOM_VERTTEXCOORD : return MM_VERTTEXCOORD; - case tri::io::Mask::IOM_VERTRADIUS : return MM_VERTRADIUS; + switch(single_iobit) + { + case tri::io::Mask::IOM_NONE : return MM_NONE; + case tri::io::Mask::IOM_VERTCOORD : return MM_VERTCOORD; + case tri::io::Mask::IOM_VERTCOLOR : return MM_VERTCOLOR; + case tri::io::Mask::IOM_VERTFLAGS : return MM_VERTFLAG; + case tri::io::Mask::IOM_VERTQUALITY : return MM_VERTQUALITY; + case tri::io::Mask::IOM_VERTNORMAL : return MM_VERTNORMAL; + case tri::io::Mask::IOM_VERTTEXCOORD : return MM_VERTTEXCOORD; + case tri::io::Mask::IOM_VERTRADIUS : return MM_VERTRADIUS; - case tri::io::Mask::IOM_FACEINDEX : return MM_FACEVERT ; - case tri::io::Mask::IOM_FACEFLAGS : return MM_FACEFLAG ; - case tri::io::Mask::IOM_FACECOLOR : return MM_FACECOLOR ; - case tri::io::Mask::IOM_FACEQUALITY : return MM_FACEQUALITY; - case tri::io::Mask::IOM_FACENORMAL : return MM_FACENORMAL ; + case tri::io::Mask::IOM_FACEINDEX : return MM_FACEVERT ; + case tri::io::Mask::IOM_FACEFLAGS : return MM_FACEFLAG ; + case tri::io::Mask::IOM_FACECOLOR : return MM_FACECOLOR ; + case tri::io::Mask::IOM_FACEQUALITY : return MM_FACEQUALITY; + case tri::io::Mask::IOM_FACENORMAL : return MM_FACENORMAL ; - case tri::io::Mask::IOM_WEDGTEXCOORD : return MM_WEDGTEXCOORD; - case tri::io::Mask::IOM_WEDGCOLOR : return MM_WEDGCOLOR; - case tri::io::Mask::IOM_WEDGNORMAL : return MM_WEDGNORMAL ; + case tri::io::Mask::IOM_WEDGTEXCOORD : return MM_WEDGTEXCOORD; + case tri::io::Mask::IOM_WEDGCOLOR : return MM_WEDGCOLOR; + case tri::io::Mask::IOM_WEDGNORMAL : return MM_WEDGNORMAL ; - case tri::io::Mask::IOM_BITPOLYGONAL : return MM_POLYGONAL ; + case tri::io::Mask::IOM_BITPOLYGONAL : return MM_POLYGONAL ; - default: - assert(0); - return MM_NONE; // FIXME: Returning this is not the best solution (!) - break; - } ; + default: + assert(0); + return MM_NONE; // FIXME: Returning this is not the best solution (!) + break; + } ; } /**** DATAMASK STUFF ****/ -void MeshDocument::setVisible(int meshId, bool val) -{ - getMesh(meshId)->visible=val; - emit meshSetChanged(); -} - bool MeshModel::hasDataMask(const int maskToBeTested) const { - return ((currentDataMask & maskToBeTested)!= 0); + return ((currentDataMask & maskToBeTested)!= 0); } -void MeshModel::updateDataMask(MeshModel *m) + +bool MeshModel::hasPerVertexColor() const { - updateDataMask(m->currentDataMask); + return currentDataMask & MM_VERTCOLOR; +} + +bool MeshModel::hasPerVertexQuality() const +{ + return currentDataMask & MM_VERTQUALITY; +} + +bool MeshModel::hasPerVertexTexCoord() const +{ + return currentDataMask & MM_VERTTEXCOORD; +} + +bool MeshModel::hasPerFaceColor() const +{ + return currentDataMask & MM_FACECOLOR; +} + +bool MeshModel::hasPerFaceQuality() const +{ + return currentDataMask & MM_FACEQUALITY; +} + +bool MeshModel::hasPerFaceWedgeTexCoords() const +{ + return currentDataMask & MM_WEDGTEXCOORD; +} + +void MeshModel::updateDataMask() +{ + currentDataMask = MM_NONE; + currentDataMask |= + MM_VERTCOORD | MM_VERTNORMAL | MM_VERTFLAG | + MM_VERTQUALITY | MM_VERTCOLOR; + currentDataMask |= + MM_FACEVERT | MM_FACENORMAL | MM_FACEFLAG ; + if (cm.vert.IsVFAdjacencyEnabled()) + currentDataMask |= MM_VERTFACETOPO; + if (cm.vert.IsMarkEnabled()) + currentDataMask |= MM_VERTMARK; + if (cm.vert.IsTexCoordEnabled()) + currentDataMask |= MM_VERTTEXCOORD; + if (cm.vert.IsCurvatureDirEnabled()) + currentDataMask |= MM_VERTCURVDIR; + if (cm.vert.IsRadiusEnabled()) + currentDataMask |= MM_VERTRADIUS; + if (cm.face.IsQualityEnabled()) + currentDataMask |= MM_FACEQUALITY; + if (cm.face.IsMarkEnabled()) + currentDataMask |= MM_FACEMARK; + if (cm.face.IsColorEnabled()) + currentDataMask |= MM_FACECOLOR; + if (cm.face.IsFFAdjacencyEnabled()) + currentDataMask |= MM_FACEFACETOPO; + if (cm.face.IsVFAdjacencyEnabled()) + currentDataMask |= MM_VERTFACETOPO; + if (cm.face.IsCurvatureDirEnabled()) + currentDataMask |= MM_FACECURVDIR; + if (cm.face.IsWedgeTexCoordEnabled()) + currentDataMask |= MM_WEDGTEXCOORD; +} + +void MeshModel::updateDataMask(const MeshModel *m) +{ + updateDataMask(m->currentDataMask); } void MeshModel::updateDataMask(int neededDataMask) { - if((neededDataMask & MM_FACEFACETOPO)!=0) - { - cm.face.EnableFFAdjacency(); - tri::UpdateTopology::FaceFace(cm); - } - if((neededDataMask & MM_VERTFACETOPO)!=0) - { - cm.vert.EnableVFAdjacency(); - cm.face.EnableVFAdjacency(); - tri::UpdateTopology::VertexFace(cm); - } + if((neededDataMask & MM_FACEFACETOPO)!=0) + { + cm.face.EnableFFAdjacency(); + tri::UpdateTopology::FaceFace(cm); + } + if((neededDataMask & MM_VERTFACETOPO)!=0) + { + cm.vert.EnableVFAdjacency(); + cm.face.EnableVFAdjacency(); + tri::UpdateTopology::VertexFace(cm); + } - if((neededDataMask & MM_WEDGTEXCOORD)!=0) - cm.face.EnableWedgeTexCoord(); - if((neededDataMask & MM_FACECOLOR)!=0) - cm.face.EnableColor(); - if((neededDataMask & MM_FACEQUALITY)!=0) - cm.face.EnableQuality(); - if((neededDataMask & MM_FACECURVDIR)!=0) - cm.face.EnableCurvatureDir(); - if((neededDataMask & MM_FACEMARK)!=0) - cm.face.EnableMark(); - if((neededDataMask & MM_VERTMARK)!=0) - cm.vert.EnableMark(); - if((neededDataMask & MM_VERTCURV)!=0) - cm.vert.EnableCurvature(); - if((neededDataMask & MM_VERTCURVDIR)!=0) - cm.vert.EnableCurvatureDir(); - if((neededDataMask & MM_VERTRADIUS)!=0) - cm.vert.EnableRadius(); - if((neededDataMask & MM_VERTTEXCOORD)!=0) - cm.vert.EnableTexCoord(); + if((neededDataMask & MM_WEDGTEXCOORD)!=0) + cm.face.EnableWedgeTexCoord(); + if((neededDataMask & MM_FACECOLOR)!=0) + cm.face.EnableColor(); + if((neededDataMask & MM_FACEQUALITY)!=0) + cm.face.EnableQuality(); + if((neededDataMask & MM_FACECURVDIR)!=0) + cm.face.EnableCurvatureDir(); + if((neededDataMask & MM_FACEMARK)!=0) + cm.face.EnableMark(); + if((neededDataMask & MM_VERTMARK)!=0) + cm.vert.EnableMark(); + if((neededDataMask & MM_VERTCURVDIR)!=0) + cm.vert.EnableCurvatureDir(); + if((neededDataMask & MM_VERTRADIUS)!=0) + cm.vert.EnableRadius(); + if((neededDataMask & MM_VERTTEXCOORD)!=0) + cm.vert.EnableTexCoord(); - currentDataMask |= neededDataMask; + currentDataMask |= neededDataMask; } void MeshModel::clearDataMask(int unneededDataMask) { - if( ( (unneededDataMask & MM_VERTFACETOPO)!=0) && hasDataMask(MM_VERTFACETOPO)) {cm.face.DisableVFAdjacency(); - cm.vert.DisableVFAdjacency(); } - if( ( (unneededDataMask & MM_FACEFACETOPO)!=0) && hasDataMask(MM_FACEFACETOPO)) cm.face.DisableFFAdjacency(); + if( ( (unneededDataMask & MM_VERTFACETOPO)!=0) && hasDataMask(MM_VERTFACETOPO)) {cm.face.DisableVFAdjacency(); + cm.vert.DisableVFAdjacency(); } + if( ( (unneededDataMask & MM_FACEFACETOPO)!=0) && hasDataMask(MM_FACEFACETOPO)) cm.face.DisableFFAdjacency(); - if( ( (unneededDataMask & MM_WEDGTEXCOORD)!=0) && hasDataMask(MM_WEDGTEXCOORD)) cm.face.DisableWedgeTexCoord(); - if( ( (unneededDataMask & MM_FACECOLOR)!=0) && hasDataMask(MM_FACECOLOR)) cm.face.DisableColor(); - if( ( (unneededDataMask & MM_FACEQUALITY)!=0) && hasDataMask(MM_FACEQUALITY)) cm.face.DisableQuality(); - if( ( (unneededDataMask & MM_FACEMARK)!=0) && hasDataMask(MM_FACEMARK)) cm.face.DisableMark(); - if( ( (unneededDataMask & MM_VERTMARK)!=0) && hasDataMask(MM_VERTMARK)) cm.vert.DisableMark(); - if( ( (unneededDataMask & MM_VERTCURV)!=0) && hasDataMask(MM_VERTCURV)) cm.vert.DisableCurvature(); - if( ( (unneededDataMask & MM_VERTCURVDIR)!=0) && hasDataMask(MM_VERTCURVDIR)) cm.vert.DisableCurvatureDir(); - if( ( (unneededDataMask & MM_VERTRADIUS)!=0) && hasDataMask(MM_VERTRADIUS)) cm.vert.DisableRadius(); - if( ( (unneededDataMask & MM_VERTTEXCOORD)!=0) && hasDataMask(MM_VERTTEXCOORD)) cm.vert.DisableTexCoord(); + if( ( (unneededDataMask & MM_WEDGTEXCOORD)!=0) && hasDataMask(MM_WEDGTEXCOORD)) cm.face.DisableWedgeTexCoord(); + if( ( (unneededDataMask & MM_FACECOLOR)!=0) && hasDataMask(MM_FACECOLOR)) cm.face.DisableColor(); + if( ( (unneededDataMask & MM_FACEQUALITY)!=0) && hasDataMask(MM_FACEQUALITY)) cm.face.DisableQuality(); + if( ( (unneededDataMask & MM_FACEMARK)!=0) && hasDataMask(MM_FACEMARK)) cm.face.DisableMark(); + if( ( (unneededDataMask & MM_VERTMARK)!=0) && hasDataMask(MM_VERTMARK)) cm.vert.DisableMark(); + if( ( (unneededDataMask & MM_VERTCURV)!=0) && hasDataMask(MM_VERTCURV)) cm.vert.DisableCurvature(); + if( ( (unneededDataMask & MM_VERTCURVDIR)!=0) && hasDataMask(MM_VERTCURVDIR)) cm.vert.DisableCurvatureDir(); + if( ( (unneededDataMask & MM_VERTRADIUS)!=0) && hasDataMask(MM_VERTRADIUS)) cm.vert.DisableRadius(); + if( ( (unneededDataMask & MM_VERTTEXCOORD)!=0) && hasDataMask(MM_VERTTEXCOORD)) cm.vert.DisableTexCoord(); - currentDataMask = currentDataMask & (~unneededDataMask); + currentDataMask = currentDataMask & (~unneededDataMask); } -void MeshModel::Enable(int openingFileMask) +void MeshModel::enable(int openingFileMask) { - if( openingFileMask & tri::io::Mask::IOM_VERTTEXCOORD ) - updateDataMask(MM_VERTTEXCOORD); - if( openingFileMask & tri::io::Mask::IOM_WEDGTEXCOORD ) - updateDataMask(MM_WEDGTEXCOORD); - if( openingFileMask & tri::io::Mask::IOM_VERTCOLOR ) - updateDataMask(MM_VERTCOLOR); - if( openingFileMask & tri::io::Mask::IOM_FACECOLOR ) - updateDataMask(MM_FACECOLOR); - if( openingFileMask & tri::io::Mask::IOM_VERTRADIUS ) updateDataMask(MM_VERTRADIUS); - if( openingFileMask & tri::io::Mask::IOM_CAMERA ) updateDataMask(MM_CAMERA); - if( openingFileMask & tri::io::Mask::IOM_VERTQUALITY ) updateDataMask(MM_VERTQUALITY); - if( openingFileMask & tri::io::Mask::IOM_FACEQUALITY ) updateDataMask(MM_FACEQUALITY); - if( openingFileMask & tri::io::Mask::IOM_BITPOLYGONAL ) updateDataMask(MM_POLYGONAL); + if( openingFileMask & tri::io::Mask::IOM_VERTTEXCOORD ) + updateDataMask(MM_VERTTEXCOORD); + if( openingFileMask & tri::io::Mask::IOM_WEDGTEXCOORD ) + updateDataMask(MM_WEDGTEXCOORD); + if( openingFileMask & tri::io::Mask::IOM_VERTCOLOR ) + updateDataMask(MM_VERTCOLOR); + if( openingFileMask & tri::io::Mask::IOM_FACECOLOR ) + updateDataMask(MM_FACECOLOR); + if( openingFileMask & tri::io::Mask::IOM_VERTRADIUS ) + updateDataMask(MM_VERTRADIUS); + if( openingFileMask & tri::io::Mask::IOM_CAMERA ) + updateDataMask(MM_CAMERA); + if( openingFileMask & tri::io::Mask::IOM_VERTQUALITY ) + updateDataMask(MM_VERTQUALITY); + if( openingFileMask & tri::io::Mask::IOM_FACEQUALITY ) + updateDataMask(MM_FACEQUALITY); + if( openingFileMask & tri::io::Mask::IOM_BITPOLYGONAL ) + updateDataMask(MM_POLYGONAL); } bool MeshModel::meshModified() const @@ -221,5 +394,5 @@ void MeshModel::setMeshModified(bool b) int MeshModel::dataMask() const { - return currentDataMask; + return currentDataMask; } diff --git a/src/common/ml_document/mesh_model.h b/src/common/ml_document/mesh_model.h index 4d7e92612..5f2baaabe 100644 --- a/src/common/ml_document/mesh_model.h +++ b/src/common/ml_document/mesh_model.h @@ -2,7 +2,7 @@ * MeshLab o o * * Visual and Computer Graphics Library o o * * _ O _ * -* Copyright(C) 2004-2020 \/)\/ * +* Copyright(C) 2004-2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -21,8 +21,8 @@ * * ****************************************************************************/ -#ifndef MESHMODEL_H -#define MESHMODEL_H +#ifndef MESH_MODEL_H +#define MESH_MODEL_H #include #include @@ -30,6 +30,9 @@ #include #include "cmesh.h" +#include "../GLLogStream.h" +#include "../filterscript.h" +#include "../ml_shared_data_context/ml_plugin_gl_context.h" #include #include @@ -40,11 +43,6 @@ #include #include - -//#include - - - #include #include #include @@ -56,10 +54,6 @@ #include #include #include -#include "../GLLogStream.h" -#include "../filterscript.h" -#include "../ml_shared_data_context.h" - /* MeshModel Class The base class for representing a single mesh. @@ -71,161 +65,159 @@ class MeshDocument; class MeshModel { public: - /* - This enum specify the various simplex components - It is used in various parts of the framework: - - to know what elements are currently active and therefore can be saved on a file - - to know what elements are required by a filter and therefore should be made ready before starting the filter (e.g. if a - - to know what elements are changed by a filter and therefore should be saved/restored in case of dynamic filters with a preview - */ - enum MeshElement{ - MM_NONE = 0x00000000, - MM_VERTCOORD = 0x00000001, - MM_VERTNORMAL = 0x00000002, - MM_VERTFLAG = 0x00000004, - MM_VERTCOLOR = 0x00000008, - MM_VERTQUALITY = 0x00000010, - MM_VERTMARK = 0x00000020, - MM_VERTFACETOPO = 0x00000040, - MM_VERTCURV = 0x00000080, - MM_VERTCURVDIR = 0x00000100, - MM_VERTRADIUS = 0x00000200, - MM_VERTTEXCOORD = 0x00000400, - MM_VERTNUMBER = 0x00000800, + /* + This enum specify the various simplex components + It is used in various parts of the framework: + - to know what elements are currently active and therefore can be saved on a file + - to know what elements are required by a filter and therefore should be made ready before starting the filter (e.g. if a + - to know what elements are changed by a filter and therefore should be saved/restored in case of dynamic filters with a preview + */ + enum MeshElement{ + MM_NONE = 0x00000000, + MM_VERTCOORD = 0x00000001, + MM_VERTNORMAL = 0x00000002, + MM_VERTFLAG = 0x00000004, + MM_VERTCOLOR = 0x00000008, + MM_VERTQUALITY = 0x00000010, + MM_VERTMARK = 0x00000020, + MM_VERTFACETOPO = 0x00000040, + MM_VERTCURV = 0x00000080, + MM_VERTCURVDIR = 0x00000100, + MM_VERTRADIUS = 0x00000200, + MM_VERTTEXCOORD = 0x00000400, + MM_VERTNUMBER = 0x00000800, - MM_FACEVERT = 0x00001000, - MM_FACENORMAL = 0x00002000, - MM_FACEFLAG = 0x00004000, - MM_FACECOLOR = 0x00008000, - MM_FACEQUALITY = 0x00010000, - MM_FACEMARK = 0x00020000, - MM_FACEFACETOPO = 0x00040000, - MM_FACENUMBER = 0x00080000, - MM_FACECURVDIR = 0x00100000, + MM_FACEVERT = 0x00001000, + MM_FACENORMAL = 0x00002000, + MM_FACEFLAG = 0x00004000, + MM_FACECOLOR = 0x00008000, + MM_FACEQUALITY = 0x00010000, + MM_FACEMARK = 0x00020000, + MM_FACEFACETOPO = 0x00040000, + MM_FACENUMBER = 0x00080000, + MM_FACECURVDIR = 0x00100000, - MM_WEDGTEXCOORD = 0x00200000, - MM_WEDGNORMAL = 0x00400000, - MM_WEDGCOLOR = 0x00800000, + MM_WEDGTEXCOORD = 0x00200000, + MM_WEDGNORMAL = 0x00400000, + MM_WEDGCOLOR = 0x00800000, - // Selection - MM_VERTFLAGSELECT = 0x01000000, - MM_FACEFLAGSELECT = 0x02000000, + // Selection + MM_VERTFLAGSELECT = 0x01000000, + MM_FACEFLAGSELECT = 0x02000000, - // Per Mesh Stuff.... - MM_CAMERA = 0x08000000, - MM_TRANSFMATRIX = 0x10000000, - MM_COLOR = 0x20000000, - MM_POLYGONAL = 0x40000000, + // Per Mesh Stuff.... + MM_CAMERA = 0x08000000, + MM_TRANSFMATRIX = 0x10000000, + MM_COLOR = 0x20000000, + MM_POLYGONAL = 0x40000000, // unknown - will raise exceptions, to be avoided, here just for compatibility - MM_UNKNOWN = 0x80000000, + MM_UNKNOWN = 0x80000000, // geometry change (for filters that remove stuff or modify geometry or topology, but not touch face/vertex color or face/vertex quality) - MM_GEOMETRY_AND_TOPOLOGY_CHANGE = 0x431e7be7, + MM_GEOMETRY_AND_TOPOLOGY_CHANGE = 0x431e7be7, // everything - dangerous, will add unwanted data to layer (e.g. if you use MM_ALL it could means that it could add even color or quality) - MM_ALL = 0xffffffff - }; + MM_ALL = 0xffffffff + }; - MeshModel(MeshDocument *parent, unsigned int id, const QString& fullFileName, const QString& labelName); - ~MeshModel() - { - } + MeshModel(int id, const QString& fullFileName, const QString& labelName); + ~MeshModel() + { + } - MeshDocument *parent; + void clear(); + void updateBoxAndNormals(); // This is the STANDARD method that you should call after changing coords. + inline int id() const {return _id;} - CMeshO cm; + int idInFile() const {return idInsideFile;} + void setIdInFile(int id) {idInsideFile = id;} + // Some notes about the files and naming. + // Each mesh when shown in the layer dialog has a label. + // By default the label is just the name of the file, but the + // in a future the path should be moved outside the meshmodel into the meshdocument (and assume that all the meshes resides in a common subtree) + // currently we just fix the interface and make the pathname private for avoiding future hassles. + QString label() const { if(_label.isEmpty()) return shortName(); else return _label;} - /*vcg::GlTrimesh glw;*/ - - - - /* - Bitmask denoting what fields are currently used in the mesh - it is composed by MeshElement enums. - it should be changed by only mean the following functions: + /// The whole full path name of the mesh + QString fullName() const {return fullPathFileName;} - updateDataMask(neededStuff) - clearDataMask(no_needed_stuff) - hasDataMask(stuff) + /// just the name of the file + QString shortName() const { return QFileInfo(fullPathFileName).fileName(); } - Note that if an element is active means that is also allocated - Some unactive elements (vertex color) are usually already allocated - other elements (FFAdj or curvature data) not necessarily. + /// the full path without the name of the file (e.g. the dir where the mesh and often its textures are) + QString pathName() const {QFileInfo fi(fullName()); return fi.absolutePath();} - */ + /// just the extension. + QString suffixName() const {QFileInfo fi(fullName()); return fi.suffix();} -private: - int currentDataMask; - QString fullPathFileName; - QString _label; - unsigned int _id; - bool modified; + /// the relative path with respect to the current project + QString relativePathName(const QString& path) const; -public: - void Clear(); - void UpdateBoxAndNormals(); // This is the STANDARD method that you should call after changing coords. - inline int id() const {return _id;} - - - // Some notes about the files and naming. - // Each mesh when shown in the layer dialog has a label. - // By default the label is just the name of the file, but the + void setFileName(QString newFileName) { + QFileInfo fi(newFileName); + if(!fi.isAbsolute()) qWarning("Someone is trying to put a non relative filename"); + fullPathFileName = fi.absoluteFilePath(); + } + void setLabel(QString newName) {_label=newName;} - // in a future the path should be moved outside the meshmodel into the meshdocument (and assume that all the meshes resides in a common subtree) - // currently we just fix the interface and make the pathname private for avoiding future hassles. - - QString label() const { if(_label.isEmpty()) return shortName(); else return _label;} - - /// The whole full path name of the mesh - QString fullName() const {return fullPathFileName;} - - /// just the name of the file - QString shortName() const { return QFileInfo(fullPathFileName).fileName(); } - - /// the full path without the name of the file (e.g. the dir where the mesh and often its textures are) - QString pathName() const {QFileInfo fi(fullName()); return fi.absolutePath();} - - /// just the extension. - QString suffixName() const {QFileInfo fi(fullName()); return fi.suffix();} - - /// the relative path with respect to the current project - QString relativePathName() const; - - /// the absolute path of the current project - QString documentPathName() const; - - void setFileName(QString newFileName) { - QFileInfo fi(newFileName); - if(!fi.isAbsolute()) qWarning("Someone is trying to put a non relative filename"); - fullPathFileName = fi.absoluteFilePath(); - } - void setLabel(QString newName) {_label=newName;} - - bool visible; // used in rendering; Needed for toggling on and off the meshes bool isVisible() const { return visible; } + void setVisible(bool vis = true) { visible = vis;} - // This function is roughly equivalent to the updateDataMask, - // but it takes in input a mask coming from a filetype instead of a filter requirement (like topology etc) - void Enable(int openingFileMask); + std::list loadTextures(GLLogStream* log = nullptr, vcg::CallBackPos* cb = nullptr); + void saveTextures(const QString& basePath, int quality = -1, GLLogStream* log = nullptr, vcg::CallBackPos* cb = nullptr); - bool hasDataMask(const int maskToBeTested) const; - void updateDataMask(MeshModel *m); - void updateDataMask(int neededDataMask); - void clearDataMask(int unneededDataMask); - int dataMask() const; + QImage getTexture(const std::string& tn) const; + const std::map& getTextures() const; + void clearTextures(); + void addTexture(std::string name, const QImage& txt); + void setTexture(std::string name, const QImage& txt); + void changeTextureName(const std::string& oldName, std::string newName); + + // This function is roughly equivalent to the updateDataMask, + // but it takes in input a mask coming from a filetype instead of a filter requirement (like topology etc) + void enable(int openingFileMask); + + bool hasDataMask(const int maskToBeTested) const; + + bool hasPerVertexColor() const; + bool hasPerVertexQuality() const; + bool hasPerVertexTexCoord() const; + bool hasPerFaceColor() const; + bool hasPerFaceQuality() const; + bool hasPerFaceWedgeTexCoords() const; + + void updateDataMask(); + void updateDataMask(const MeshModel* m); + void updateDataMask(int neededDataMask); + void clearDataMask(int unneededDataMask); + int dataMask() const; bool meshModified() const; void setMeshModified(bool b = true); - static int io2mm(int single_iobit); + static int io2mm(int single_iobit); + + CMeshO cm; + +private: + int currentDataMask; + bool visible; // used in rendering; Needed for toggling on and off the meshes + QString fullPathFileName; + QString _label; + int _id; + bool modified; + + //this is an id used for meshes that are loaded from files + //that can store more than one mesh. For meshes loaded from + //files containing just this mesh, this id will be -1. + int idInsideFile = -1; + + //textures associated to mesh + std::map textures; };// end class MeshModel - - - - #endif diff --git a/src/common/ml_document/raster_model.cpp b/src/common/ml_document/raster_model.cpp index e353facb5..dee1558ac 100644 --- a/src/common/ml_document/raster_model.cpp +++ b/src/common/ml_document/raster_model.cpp @@ -29,10 +29,9 @@ RasterModel::RasterModel() { } -RasterModel::RasterModel(MeshDocument *parent, unsigned int id, QString _rasterName) +RasterModel::RasterModel(unsigned int id, const QString& _rasterName) : + visible(true), + _id(id), + _label(_rasterName) { - _id=id; - par = parent; - this->_label= std::move(_rasterName); - visible=true; } diff --git a/src/common/ml_document/raster_model.h b/src/common/ml_document/raster_model.h index 334e9b09c..e51a3719a 100644 --- a/src/common/ml_document/raster_model.h +++ b/src/common/ml_document/raster_model.h @@ -39,11 +39,12 @@ class RasterModel : public MeshLabRenderRaster { public: RasterModel(); - RasterModel(MeshDocument *parent, unsigned int id, QString _rasterName=QString()); + RasterModel(unsigned int id, const QString& _rasterName=QString()); - MeshDocument* par; - bool visible; - inline int id() const {return _id;} + + bool isVisible() const {return visible;} + void setVisible(bool vis = true) {visible = vis;}; + inline unsigned int id() const {return _id;} void setLabel(QString newLabel) {_label = newLabel;} @@ -60,7 +61,8 @@ public: }; private: - int _id; + bool visible; + unsigned int _id; QString _label; };// end class RasterModel diff --git a/src/common/ml_document/render_raster.cpp b/src/common/ml_document/render_raster.cpp index 99de191f9..0f60ace4a 100644 --- a/src/common/ml_document/render_raster.cpp +++ b/src/common/ml_document/render_raster.cpp @@ -38,6 +38,16 @@ RasterPlane::RasterPlane(const QString& pathName, const int _semantic) image = QImage(pathName); } +RasterPlane::RasterPlane( + const QImage& img, + const QString& pathName, + const int _semantic) +{ + semantic =_semantic; + fullPathFileName = pathName; + image = img; +} + MeshLabRenderRaster::MeshLabRenderRaster() { diff --git a/src/common/ml_document/render_raster.h b/src/common/ml_document/render_raster.h index 9ab1cde26..0678c7dbd 100644 --- a/src/common/ml_document/render_raster.h +++ b/src/common/ml_document/render_raster.h @@ -58,8 +58,6 @@ public: int semantic; QString fullPathFileName; QImage image; - QImage thumb; - float *buf; bool IsInCore() { return !image.isNull(); } void Load(); @@ -72,6 +70,7 @@ public: RasterPlane(const RasterPlane& pl); RasterPlane(const QString& pathName, const int _semantic); + RasterPlane(const QImage& image, const QString& pathName, const int _semantic); }; //end class Plane diff --git a/src/common/ml_shared_data_context.cpp b/src/common/ml_shared_data_context.cpp deleted file mode 100644 index ad83f8509..000000000 --- a/src/common/ml_shared_data_context.cpp +++ /dev/null @@ -1,1005 +0,0 @@ -#include "ml_shared_data_context.h" -#include "GLExtensionsManager.h" -#include "mlexception.h" -#include -#include - -#include "ml_document/mesh_document.h" - -MLSceneGLSharedDataContext::MLSceneGLSharedDataContext(MeshDocument& md,vcg::QtThreadSafeMemoryInfo& gpumeminfo,bool highprecision,size_t perbatchtriangles, size_t minfacespersmoothrendering) - :QGLWidget(),_md(md),_gpumeminfo(gpumeminfo),_perbatchtriangles(perbatchtriangles), _minfacessmoothrendering(minfacespersmoothrendering),_highprecision(highprecision) -{ - //if (md.size() != 0) - // throw MLException(QString("MLSceneGLSharedDataContext: MeshDocument is not empty when MLSceneGLSharedDataContext is constructed.")); - - _timer = new QTimer(this); - connect(_timer,SIGNAL(timeout()),this,SLOT(updateGPUMemInfo())); - - /*connection intended for the plugins living in another thread*/ - connect(this,SIGNAL(initPerMeshViewRequestMT(int,QGLContext*,const MLRenderingData&)),this,SLOT(initPerMeshViewRequested(int,QGLContext*,const MLRenderingData&)),Qt::BlockingQueuedConnection); - connect(this,SIGNAL(removePerMeshViewRequestMT(QGLContext*)),this,SLOT(removePerMeshViewRequested(QGLContext*)),Qt::BlockingQueuedConnection); - connect(this,SIGNAL(setPerMeshViewRenderingDataRequestMT(int,QGLContext*,const MLRenderingData&)),this,SLOT(setPerMeshViewRenderingDataRequested(int,QGLContext*,const MLRenderingData&)),Qt::BlockingQueuedConnection); - connect(this,SIGNAL(meshAttributesUpdatedRequestMT(int,bool,const MLRenderingData::RendAtts&)),this,SLOT(meshAttributesUpdatedRequested(int,bool,const MLRenderingData::RendAtts&)),Qt::BlockingQueuedConnection); - /****************************************************************/ - - ///*connection intended for the plugins living in the same thread*/ - //connect(this,SIGNAL(initPerMeshViewRequestST(int,QGLContext*,const MLRenderingData&)),this,SLOT(initPerMeshViewRequested(int,QGLContext*,const MLRenderingData&)),Qt::DirectConnection); - //connect(this,SIGNAL(removePerMeshViewRequestST(QGLContext*)),this,SLOT(removePerMeshViewRequested(QGLContext*)),Qt::DirectConnection); - //connect(this,SIGNAL(setPerMeshViewRenderingDataRequestST(int,QGLContext*,const MLRenderingData&)),this,SLOT(setPerMeshViewRenderingDataRequested(int,QGLContext*,const MLRenderingData&)),Qt::DirectConnection); - ///****************************************************************/ - - _timer->start(1000); - updateGPUMemInfo(); -} - -MLSceneGLSharedDataContext::~MLSceneGLSharedDataContext() -{ -} - -void MLSceneGLSharedDataContext::setMinFacesForSmoothRendering(size_t fcnum) -{ - _minfacessmoothrendering = fcnum; -} - -MLSceneGLSharedDataContext::PerMeshMultiViewManager* MLSceneGLSharedDataContext::meshAttributesMultiViewerManager( int mmid ) const -{ - MeshIDManMap::const_iterator it = _meshboman.find(mmid); - if (it == _meshboman.end()) - return NULL; - return it.value(); -} - -void MLSceneGLSharedDataContext::initializeGL() -{ - QGLContext *ctx = makeCurrentGLContext(); - GLExtensionsManager::initializeGLextensions(); - doneCurrentGLContext(ctx); -} - -void MLSceneGLSharedDataContext::setRenderingDataPerMeshView( int mmid,QGLContext* viewerid,const MLRenderingData& perviewdata ) -{ - MeshModel* mm = _md.getMesh(mmid); - if (mm == NULL) - return; - MLSceneGLSharedDataContext::PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - if (man != NULL) - man->setPerViewInfo(viewerid,perviewdata); -} - -void MLSceneGLSharedDataContext::setRenderingDataPerAllMeshViews(int mmid, const MLRenderingData& perviewdata) -{ - MeshModel* mm = _md.getMesh(mmid); - if (mm == NULL) - return; - MLSceneGLSharedDataContext::PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - if (man != NULL) - man->setPerAllViewsInfo(perviewdata); -} - -//void MLSceneGLSharedDataContext::setRequestedAttributesPerMeshViews( int mmid,const QList& viewerid,const MLRenderingData& perviewdata ) -//{ -// MeshModel* mm = _md.getMesh(mmid); -// if (mm == NULL) -// return; -// -// PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); -// if (man != NULL) -// { -// MLRenderingData outdt; -// MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMesh(mm,perviewdata,outdt); -// foreach(QGLContext* vid,viewerid) -// { -// setRequestedAttributesPerMeshView(mmid,vid,outdt); -// } -// } -//} - - -void MLSceneGLSharedDataContext::deAllocateTexturesPerMesh( int mmid ) -{ - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - if (man != NULL) - { - QGLContext* ctx = makeCurrentGLContext(); - std::vector texids; - for(size_t ii = 0;ii < man->textureIDContainer().size();++ii) - { - texids.push_back(man->textureIDContainer()[ii]); - } - - for (auto tex : texids) - man->textureIDContainer().remove(tex); - - glDeleteTextures(texids.size(), texids.data()); - doneCurrentGLContext(ctx); - } -} - -GLuint MLSceneGLSharedDataContext::getTextureId(int meshid, size_t position) const -{ - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(meshid); - if ((man != NULL) && (position < man->textureIDContainer().size())) - { - return man->textureIDContainer()[position]; - } - return 0; -} - -int roundUpToTheNextHighestPowerOf2(unsigned int v) -{ - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - return v; -} - -GLuint MLSceneGLSharedDataContext::allocateTexturePerMesh( int meshid,const QImage& img,size_t maxdimtextmpx) -{ - GLuint res = 0; - PerMeshMultiViewManager* meshfeed = meshAttributesMultiViewerManager(meshid); - if (meshfeed != NULL) - { - int singlemaxtexturesize = roundUpToTheNextHighestPowerOf2(int(sqrt(float(maxdimtextmpx))*1024.0))/2; - QImage imgscaled; - QImage imggl; - - QGLContext* ctx = makeCurrentGLContext(); - GLint maxtexturesize; - glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxtexturesize); - - if(maxtexturesize < singlemaxtexturesize) - maxtexturesize = singlemaxtexturesize; - - int bestW=roundUpToTheNextHighestPowerOf2(img.width() ); - int bestH=roundUpToTheNextHighestPowerOf2(img.height()); - while(bestW>maxtexturesize) bestW /=2; - while(bestH>maxtexturesize) bestH /=2; - //Logf(GLLogStream::SYSTEM," Texture[ %3i ] = '%s' ( %6i x %6i ) -> ( %6i x %6i )", i,mp->cm.textures[i].c_str(), img.width(), img.height(),bestW,bestH); - imgscaled=img.scaled(bestW,bestH,Qt::IgnoreAspectRatio,Qt::SmoothTransformation); - imggl=convertToGLFormat(imgscaled); - - vcg::QtThreadSafeTextureNamesContainer& txtcont = meshfeed->textureIDContainer(); - - - GLuint tmpid; - glGenTextures( 1, (GLuint*)&(tmpid) ); - glBindTexture( GL_TEXTURE_2D, tmpid ); - //qDebug(" will be loaded as GL texture id %i ( %i x %i )",txtcont[txtcont.size() - 1] ,imgGL.width(), imgGL.height()); - glTexImage2D( GL_TEXTURE_2D, 0, 3, imggl.width(), imggl.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, imggl.bits() ); - //gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imggl.width(), imggl.height(), GL_RGBA, GL_UNSIGNED_BYTE, imggl.bits() ); - glGenerateMipmap(GL_TEXTURE_2D); - txtcont.push_back(tmpid); - res = tmpid; - - doneCurrentGLContext(ctx); - } - return res; -} - - -void MLSceneGLSharedDataContext::meshInserted( int mmid ) -{ - MeshModel* mesh = _md.getMesh(mmid); - if (mesh != NULL) - { - _meshboman[mmid] = new PerMeshMultiViewManager(mesh->cm,_gpumeminfo,_perbatchtriangles); - _meshboman[mmid]->setDebugMode(true); - } -} - -void MLSceneGLSharedDataContext::meshRemoved(int mmid) -{ - MeshIDManMap::iterator it = _meshboman.find(mmid); - if (it == _meshboman.end()) - return; - - PerMeshMultiViewManager* man = it.value(); - if (man != NULL) - { - QGLContext* ctx = makeCurrentGLContext(); - man->removeAllViewsAndDeallocateBO(); - doneCurrentGLContext(ctx); - delete man; - } - _meshboman.erase(it); -} - -void MLSceneGLSharedDataContext::setMeshTransformationMatrix( int mmid,const Matrix44m& m ) -{ - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - if (man != NULL) - man->setTrMatrix(m); -} - -void MLSceneGLSharedDataContext::setSceneTransformationMatrix( const Matrix44m& /*m*/ ) -{ - -} - -void MLSceneGLSharedDataContext::setGLOptions( int mmid,QGLContext* viewid,const MLPerViewGLOptions& opts ) -{ - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - if (man != NULL) - man->setGLOptions(viewid,opts); -} - -void MLSceneGLSharedDataContext::draw( int mmid,QGLContext* viewid ) const -{ - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - if (man != NULL) - man->draw(viewid); -} - -void MLSceneGLSharedDataContext::drawAllocatedAttributesSubset(int mmid, QGLContext * viewid, const MLRenderingData & dt) -{ - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - if (man != NULL) - man->drawAllocatedAttributesSubset(viewid,dt); -} - -void MLSceneGLSharedDataContext::removeView( QGLContext* viewerid ) -{ - QGLContext* ctx = makeCurrentGLContext(); - for(MeshIDManMap::iterator it = _meshboman.begin();it != _meshboman.end();++it) - { - PerMeshMultiViewManager* man = it.value(); - if (man != NULL) - { - man->removeView(viewerid); - man->manageBuffers(); - } - } - doneCurrentGLContext(ctx); -} - -void MLSceneGLSharedDataContext::addView( QGLContext* viewerid,MLRenderingData& dt) -{ - for(MeshIDManMap::iterator it = _meshboman.begin();it != _meshboman.end();++it) - { - MeshModel* mesh = _md.getMesh(it.key()); - if (mesh != NULL) - { - MLPoliciesStandAloneFunctions::suggestedDefaultPerViewRenderingData(mesh,dt, _minfacessmoothrendering); - setRenderingDataPerMeshView(it.key(),viewerid,dt); - manageBuffers(it.key()); - } - } -} - -void MLSceneGLSharedDataContext::addView(QGLContext* viewerid) -{ - for(MeshIDManMap::iterator it = _meshboman.begin();it != _meshboman.end();++it) - { - MeshModel* mesh = _md.getMesh(it.key()); - if (mesh != NULL) - { - MLRenderingData dt; - setRenderingDataPerMeshView(it.key(),viewerid,dt); - //manageBuffers(it.key()); - } - } -} - -void MLSceneGLSharedDataContext::deAllocateGPUSharedData() -{ - QGLContext* ctx = makeCurrentGLContext(); - for(MeshIDManMap::iterator it = _meshboman.begin();it != _meshboman.end();++it) - { - PerMeshMultiViewManager* man = it.value(); - deAllocateTexturesPerMesh(it.key()); - man->removeAllViewsAndDeallocateBO(); - } - doneCurrentGLContext(ctx); -} - -void MLSceneGLSharedDataContext::meshAttributesUpdated(int mmid,bool conntectivitychanged,const MLRenderingData::RendAtts& atts) -{ - MeshModel* mm = _md.getMesh(mmid); - if (mm == NULL) - return; - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - if (man != NULL) - man->meshAttributesUpdated(conntectivitychanged,atts); -} - -void MLSceneGLSharedDataContext::meshDeallocated( int /*mmid*/ ) -{ - -} - -void MLSceneGLSharedDataContext::getRenderInfoPerMeshView( int mmid,QGLContext* ctx,MLRenderingData& dt ) -{ - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - if (man != NULL) - man->getPerViewInfo(ctx,dt); -} - -void MLSceneGLSharedDataContext::getRenderInfoPerMeshView( QGLContext* ctx,PerMeshRenderingDataMap& map ) -{ - map.clear(); - for(MeshIDManMap::iterator it = _meshboman.begin();it != _meshboman.end();++it) - { - MLRenderingData dt; - int meshid = it.key(); - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(meshid); - if (man != NULL) - man->getPerViewInfo(ctx,dt); - map.insert(meshid,dt); - } -} - -bool MLSceneGLSharedDataContext::manageBuffers( int mmid ) -{ - bool didsomething = false; - MeshModel* mm = _md.getMesh(mmid); - - if (mm == NULL) - return didsomething; - - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - - if (man != NULL) - { - QGLContext* ctx = makeCurrentGLContext(); - man->manageBuffers(); - doneCurrentGLContext(ctx); - } - return didsomething; -} - -void MLSceneGLSharedDataContext::setDebugMode(int mmid,bool activatedebugmodality ) -{ - MeshModel* mm = _md.getMesh(mmid); - if (mm == NULL) - return; - - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - if (man != NULL) - man->setDebugMode(activatedebugmodality); -} - -void MLSceneGLSharedDataContext::getLog( int mmid,MLRenderingData::DebugInfo& info) -{ - MeshModel* mm = _md.getMesh(mmid); - if (mm == NULL) - return; - - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - if (man != NULL) - man->getLog(info); - return; -} - -bool MLSceneGLSharedDataContext::isBORenderingAvailable( int mmid ) -{ - MeshModel* mm = _md.getMesh(mmid); - if (mm == NULL) - return false; - - PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); - if (man != NULL) - return man->isBORenderingAvailable(); - return false; -} - -#define GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 -#define GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 -#define VBO_FREE_MEMORY_ATI 0x87FB -#define TEXTURE_FREE_MEMORY_ATI 0x87FC -#define RENDERBUFFER_FREE_MEMORY_ATI 0x87FD - -void MLSceneGLSharedDataContext::updateGPUMemInfo() -{ - initializeGL(); - QGLContext* ctx = makeCurrentGLContext(); - GLint allmem = 0; - glGetIntegerv(GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &allmem); - GLint currentallocated = 0; - glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, ¤tallocated); - /*GLenum errorNV =*/ glGetError(); // purge errors - - GLint ATI_vbo[4] = { 0, 0, 0, 0 }; - glGetIntegerv(VBO_FREE_MEMORY_ATI, ATI_vbo); - GLint ATI_tex[4] = { 0, 0, 0, 0 }; - glGetIntegerv(TEXTURE_FREE_MEMORY_ATI, ATI_tex); - /*GLenum errorATI =*/ glGetError(); // purge errors - - doneCurrentGLContext(ctx); - emit currentAllocatedGPUMem((int)allmem, (int)currentallocated, (int)ATI_tex[0], (int)ATI_vbo[0]); -} - -//void MLSceneGLSharedDataContext::updateRequested( int meshid,MLRenderingData::ATT_NAMES name ) -//{ -// MLRenderingData::RendAtts att; -// att[name] = true; -// meshAttributesUpdated(meshid,false,att); -// manageBuffers(meshid); -// -//} - -void MLSceneGLSharedDataContext::initPerMeshViewRequested( int meshid,QGLContext* cont,const MLRenderingData& dt) -{ - addView(cont); - setRenderingDataPerMeshView(meshid,cont,dt); - manageBuffers(meshid); -} - -void MLSceneGLSharedDataContext::setPerMeshViewRenderingDataRequested( int meshid,QGLContext* cont,const MLRenderingData& dt ) -{ - setRenderingDataPerMeshView(meshid,cont,dt); - manageBuffers(meshid); -} - -void MLSceneGLSharedDataContext::removePerMeshViewRequested(QGLContext* cont ) -{ - removeView(cont); -} - -void MLSceneGLSharedDataContext::meshAttributesUpdatedRequested( int meshid,bool connectivitychanged,const MLRenderingData::RendAtts& dt ) -{ - meshAttributesUpdated(meshid,connectivitychanged,dt); - manageBuffers(meshid); -} - -void MLSceneGLSharedDataContext::requestInitPerMeshView(QThread* callingthread,int meshid,QGLContext* cont,const MLRenderingData& dt ) -{ - QThread* tt = thread(); - if (callingthread != tt) - emit initPerMeshViewRequestMT(meshid,cont,dt); - else - //emit initPerMeshViewRequestST(meshid,cont,dt); - initPerMeshViewRequested(meshid,cont,dt); -} - -void MLSceneGLSharedDataContext::requestRemovePerMeshView(QThread* callingthread,QGLContext* cont ) -{ - QThread* tt = thread(); - if (callingthread != tt) - emit removePerMeshViewRequestMT(cont); - else - removeView(cont); -} - -void MLSceneGLSharedDataContext::requestSetPerMeshViewRenderingData(QThread* callingthread,int meshid,QGLContext* cont,const MLRenderingData& dt ) -{ - QThread* tt = thread(); - if (callingthread != tt) - emit setPerMeshViewRenderingDataRequestMT(meshid,cont,dt); - else - //emit setPerMeshViewRenderingDataRequestST(meshid,cont,dt); - setPerMeshViewRenderingDataRequested(meshid,cont,dt); -} - -void MLSceneGLSharedDataContext::requestMeshAttributesUpdated(QThread* callingthread,int meshid,bool connectivitychanged,const MLRenderingData::RendAtts& dt ) -{ - QThread* tt = thread(); - if (callingthread != tt) - emit meshAttributesUpdatedRequestMT(meshid,connectivitychanged,dt); - else - //emit setPerMeshViewRenderingDataRequestST(meshid,cont,dt); - meshAttributesUpdated(meshid,connectivitychanged,dt); -} - - - - -QGLContext* MLSceneGLSharedDataContext::makeCurrentGLContext() -{ - QGLContext* ctx = const_cast(QGLContext::currentContext()); - makeCurrent(); - return ctx; -} - -void MLSceneGLSharedDataContext::doneCurrentGLContext( QGLContext* oldone /*= NULL*/ ) -{ - doneCurrent(); - if (oldone != NULL) - oldone->makeCurrent(); -} - -void MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMeshSameGLOpts(MeshModel* meshmodel, const MLRenderingData& inputdt, MLRenderingData& outputdt) -{ - MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMeshCommonCode(meshmodel, inputdt, outputdt); - MLPerViewGLOptions opts; - inputdt.get(opts); - outputdt.set(opts); -} - -void MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMesh( MeshModel* meshmodel,const MLRenderingData& inputdt,MLRenderingData& outputdt) -{ - MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMeshCommonCode(meshmodel, inputdt, outputdt); - MLPoliciesStandAloneFunctions::setPerViewGLOptionsAccordindToWireModality(meshmodel, outputdt); - MLPoliciesStandAloneFunctions::setPerViewGLOptionsPriorities(outputdt); - MLPerViewGLOptions opts; - outputdt.get(opts); - MLPoliciesStandAloneFunctions::suggestedDefaultPerViewGLOptions(opts); - outputdt.set(opts); -} - -void MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMeshCommonCode(MeshModel* meshmodel, const MLRenderingData& inputdt, MLRenderingData& outputdt) -{ - if (meshmodel == NULL) - return; - CMeshO& mesh = meshmodel->cm; - if (mesh.VN() == 0) - { - outputdt.reset(false); - return; - } - bool validfaces = (mesh.FN() > 0); - -// MLRenderingData::PRIMITIVE_MODALITY_MASK tmpoutputpm = inputdt.getPrimitiveModalityMask(); - for (size_t pmind = 0; pmind < size_t(MLRenderingData::PR_ARITY); ++pmind) - { - MLRenderingData::PRIMITIVE_MODALITY pmc = MLRenderingData::PRIMITIVE_MODALITY(pmind); - - - MLRenderingData::RendAtts tmpoutputatts; - if (inputdt.get(MLRenderingData::PRIMITIVE_MODALITY(pmind), tmpoutputatts)) - { - tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] &= meshmodel->hasDataMask(MeshModel::MM_VERTCOORD); - tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] &= meshmodel->hasDataMask(MeshModel::MM_VERTNORMAL); - tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] &= validfaces && meshmodel->hasDataMask(MeshModel::MM_FACENORMAL); - tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] &= meshmodel->hasDataMask(MeshModel::MM_VERTCOLOR); - tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] &= validfaces && meshmodel->hasDataMask(MeshModel::MM_FACECOLOR); - - //horrible trick caused by MeshLab GUI. In MeshLab exists just a button turning on/off the texture visualization. - //Unfortunately the RenderMode::textureMode member field is not just a boolean value but and enum one. - //The enum-value depends from the enabled attributes of input mesh. - bool wedgetexture = meshmodel->hasDataMask(MeshModel::MM_WEDGTEXCOORD); - tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] &= (meshmodel->hasDataMask(MeshModel::MM_VERTTEXCOORD) && (!wedgetexture)); - tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] &= validfaces && wedgetexture; - if (MLPoliciesStandAloneFunctions::isPrimitiveModalityCompatibleWithMesh(meshmodel, pmc)) - outputdt.set(pmc, tmpoutputatts); - } - else - throw MLException(QString("MLPoliciesStandAloneFunctions: trying to access to a non defined PRIMITIVE_MODALITY!")); - } -} - -void MLPoliciesStandAloneFunctions::fromMeshModelMaskToMLRenderingAtts( int meshmodelmask,MLRenderingData::RendAtts& atts) -{ - atts.reset(); - //connectivitychanged = bool(meshmodelmask | MeshModel::MM_FACEFACETOPO) || bool(meshmodelmask | MeshModel::MM_VERTFACETOPO) || bool(meshmodelmask | MeshModel::MM_VERTNUMBER) || bool(meshmodelmask | MeshModel::MM_FACENUMBER); - atts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = bool(meshmodelmask & MeshModel::MM_VERTCOORD); - atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = bool(meshmodelmask & MeshModel::MM_VERTNORMAL); - atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = bool(meshmodelmask & MeshModel::MM_FACENORMAL); - atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] = bool(meshmodelmask & MeshModel::MM_VERTCOLOR); - atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] = bool(meshmodelmask & MeshModel::MM_FACECOLOR); - //atts[MLRenderingData::ATT_NAMES::ATT_FIXEDCOLOR] = bool(meshmodelmask & MeshModel::MM_COLOR); - atts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] = bool(meshmodelmask & MeshModel::MM_VERTTEXCOORD); - atts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] = bool(meshmodelmask & MeshModel::MM_WEDGTEXCOORD); -} - -void MLPoliciesStandAloneFunctions::maskMeaninglessAttributesPerPrimitiveModality( MLRenderingData::PRIMITIVE_MODALITY pm,MLRenderingData::RendAtts& atts ) -{ - switch(pm) - { - case (MLRenderingData::PR_POINTS): - { - atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = false; - atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] = false; - atts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] = false; - return; - } - case (MLRenderingData::PR_WIREFRAME_EDGES): - case (MLRenderingData::PR_WIREFRAME_TRIANGLES): - { - atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = false; - atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] = false; - atts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] = false; - atts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] = false; - return; - } - case (MLRenderingData::PR_SOLID): - { - return; - } - case (MLRenderingData::PR_ARITY): - { - throw MLException("PR_ARITY passed as parameter!"); - } - } -} - -void MLPoliciesStandAloneFunctions::updatedRendAttsAccordingToPriorities(const MLRenderingData::PRIMITIVE_MODALITY pm,const MLRenderingData::RendAtts& updated,const MLRenderingData::RendAtts& current,MLRenderingData::RendAtts& result) -{ - MLRenderingData::RendAtts filteredupdated = updated; - MLRenderingData::RendAtts tmp = current; - tmp[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] |= filteredupdated[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION]; - if ((pm == MLRenderingData::PR_WIREFRAME_TRIANGLES) || (pm == MLRenderingData::PR_WIREFRAME_EDGES)) - { - tmp[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = false; - tmp[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = false; - } - else - { - tmp[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] |= filteredupdated[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]; - tmp[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = (tmp[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] || filteredupdated[MLRenderingData::ATT_NAMES::ATT_FACENORMAL]) && !(filteredupdated[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]); - } - - tmp[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] |= filteredupdated[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR]; - tmp[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] = (tmp[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] || filteredupdated[MLRenderingData::ATT_NAMES::ATT_FACECOLOR]) && !(filteredupdated[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR]); - tmp[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] |= filteredupdated[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE]; - tmp[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] = (tmp[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] || filteredupdated[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE]) && !(filteredupdated[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE]); - result = tmp; -} - -void MLPoliciesStandAloneFunctions::suggestedDefaultPerViewRenderingData(MeshModel* meshmodel,MLRenderingData& dtout, size_t minpolnumpersmoothshading) -{ - MLRenderingData dt; - if (meshmodel == NULL) - return; - if (meshmodel->cm.VN() == 0) - { - dt.reset(); - } - else - { - MLRenderingData::RendAtts tmpatts; - tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true; - tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true; - tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] = true; - tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] = true; - - dt.set(MLRenderingData::PR_POINTS,tmpatts); - - if (meshmodel->cm.FN() > 0) - { - dt.set(MLRenderingData::PR_POINTS,false); - tmpatts.reset(); - tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true; - tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = (size_t(meshmodel->cm.FN()) > minpolnumpersmoothshading); - tmpatts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = !(tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]); - tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] = true; - if (meshmodel != NULL) - tmpatts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] = (meshmodel->hasDataMask(MeshModel::MM_FACECOLOR) && !meshmodel->hasDataMask(MeshModel::MM_VERTCOLOR)); - tmpatts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] = true; - tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] = true; - dt.set(MLRenderingData::PR_SOLID,tmpatts); - } - - if (((meshmodel->cm.FN() == 0) && (meshmodel->cm.EN() > 0)) || (meshmodel->hasDataMask(MeshModel::MM_POLYGONAL))) - { - //dt.reset(); - tmpatts.reset(); - tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true; - tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true; - tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] = true; - MLPerViewGLOptions opts; - dt.get(opts); - opts._peredge_wire_enabled = true; - opts._peredge_fauxwire_enabled = true; - dt.set(opts); - //dt.set(MLRenderingData::PR_SOLID, false); - } - - } - MLPoliciesStandAloneFunctions::setBestWireModality(meshmodel, dt); - MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMesh(meshmodel,dt,dtout); -} - - -void MLPoliciesStandAloneFunctions::disableRedundatRenderingDataAccordingToPriorities(MLRenderingData& dt) -{ - for (MLRenderingData::PRIMITIVE_MODALITY pr = MLRenderingData::PRIMITIVE_MODALITY(0); pr < MLRenderingData::PR_ARITY; pr = MLRenderingData::next(pr)) - { - MLRenderingData::RendAtts atts; - dt.get(pr, atts); - MLPoliciesStandAloneFunctions::setAttributePriorities(atts); - dt.set(pr, atts); - } - - //setPerViewGLOptionsPriorities(dt); -} - - -bool MLPoliciesStandAloneFunctions::isPrimitiveModalityCompatibleWithMesh(MeshModel* m,const MLRenderingData::PRIMITIVE_MODALITY pm) -{ - bool validvert = (m->cm.VN() > 0); - bool validfaces = (m->cm.FN() > 0); - bool validedges = (m->cm.EN() > 0); - return MLPoliciesStandAloneFunctions::isPrimitiveModalityCompatibleWithMeshInfo(validvert,validfaces,validedges,m->dataMask(),pm); -} - -bool MLPoliciesStandAloneFunctions::isPrimitiveModalityCompatibleWithMeshInfo(bool validvert,bool validfaces,bool validedges,int meshmask,const MLRenderingData::PRIMITIVE_MODALITY pm) -{ - switch(pm) - { - case(MLRenderingData::PR_POINTS): - { - return validvert; - } - case(MLRenderingData::PR_WIREFRAME_EDGES): - { - return (validvert) && ((meshmask & MeshModel::MM_POLYGONAL) || ((!validfaces) && (validedges))); - } - case(MLRenderingData::PR_WIREFRAME_TRIANGLES): - case(MLRenderingData::PR_SOLID): - { - return validvert && validfaces; - } - case (MLRenderingData::PR_ARITY): - { - throw MLException("PR_ARITY passed as parameter!"); - } - } - return false; -} - -bool MLPoliciesStandAloneFunctions::isPrimitiveModalityWorthToBeActivated(MLRenderingData::PRIMITIVE_MODALITY pm,bool wasvisualized,bool wasmeanigful,bool ismeaningful) -{ - (void) pm; - if ((!wasmeanigful) && (ismeaningful)) - return true; - if (wasmeanigful && ismeaningful && wasvisualized) - return true; - return false; -} - -void MLPoliciesStandAloneFunctions::setAttributePriorities(MLRenderingData::RendAtts& atts ) -{ - atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] &= !(atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]); - atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] &= !(atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR]); - atts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] &= !(atts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE]); -} - -//void MLPoliciesStandAloneFunctions::setPerViewRenderingDataPriorities( MeshModel* mm,MLRenderingData& dt ) -//{ -// if (mm == NULL) -// return; -// -//} - -void MLPoliciesStandAloneFunctions::setPerViewGLOptionsPriorities(MLRenderingData& dt ) -{ - //if (mm == NULL) - // return; - //bool permeshcolor = mm->hasDataMask(MeshModel::MM_COLOR); - MLPerViewGLOptions glopts; - if (!dt.get(glopts)) - return; - /*if (permeshcolor) - glopts._perpoint_mesh_color_enabled = true;*/ - - for(MLRenderingData::PRIMITIVE_MODALITY pm = MLRenderingData::PRIMITIVE_MODALITY(0);pm < MLRenderingData::PR_ARITY;pm = MLRenderingData::next(pm)) - { - MLRenderingData::RendAtts atts; - if (dt.get(pm,atts)) - { - switch(pm) - { - case (MLRenderingData::PR_POINTS): - { - glopts._perpoint_noshading = !atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]; - glopts._perpoint_mesh_color_enabled &= !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR]; - glopts._perpoint_fixed_color_enabled = !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] && !glopts._perpoint_mesh_color_enabled; - - break; - } - case (MLRenderingData::PR_WIREFRAME_EDGES): - case (MLRenderingData::PR_WIREFRAME_TRIANGLES): - { - glopts._perwire_noshading = !atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]; - glopts._perwire_mesh_color_enabled &= !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR]; - glopts._perwire_fixed_color_enabled = !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] && !atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] && !glopts._perwire_mesh_color_enabled; - break; - } - case (MLRenderingData::PR_SOLID): - { - glopts._persolid_noshading = (!atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]) && (!atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL]); - glopts._persolid_mesh_color_enabled &= !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] && !atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR]; - glopts._persolid_fixed_color_enabled = !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] && !atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] && !glopts._persolid_mesh_color_enabled; - break; - } - case (MLRenderingData::PR_ARITY): - { - throw MLException("PR_ARITY passed as parameter!"); - } - - } - } - } - dt.set(glopts); -} - -void MLPoliciesStandAloneFunctions::filterUselessUdpateAccordingToMeshMask( MeshModel* m,MLRenderingData::RendAtts& atts ) -{ - if (m == NULL) - return; - atts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] &= m->hasDataMask(MeshModel::MM_VERTCOORD); - atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] &= m->hasDataMask(MeshModel::MM_VERTNORMAL); - atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] &= m->hasDataMask(MeshModel::MM_FACENORMAL); - atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] &= m->hasDataMask(MeshModel::MM_VERTCOLOR); - atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] &= m->hasDataMask(MeshModel::MM_FACECOLOR); - //atts[MLRenderingData::ATT_NAMES::ATT_FIXEDCOLOR] - atts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] &= m->hasDataMask(MeshModel::MM_WEDGTEXCOORD); - atts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] &= m->hasDataMask(MeshModel::MM_VERTTEXCOORD); -} - -void MLPoliciesStandAloneFunctions::setBestWireModality(MeshModel* mm, MLRenderingData& dt) -{ - if (mm == NULL) - return; - MLPerViewGLOptions opts; - dt.get(opts); - - if ((mm->cm.VN() > 0) && (mm->cm.FN() == 0) && (mm->cm.EN() > 0)) - { - dt.set(MLRenderingData::PR_WIREFRAME_EDGES,true && opts._peredge_wire_enabled); - dt.set(MLRenderingData::PR_WIREFRAME_TRIANGLES, false); - return; - } - - if (opts._peredge_wire_enabled) - { - if (opts._peredge_fauxwire_enabled) - { - dt.set(MLRenderingData::PR_WIREFRAME_EDGES, true); - dt.set(MLRenderingData::PR_WIREFRAME_TRIANGLES, false); - } - else - { - dt.set(MLRenderingData::PR_WIREFRAME_TRIANGLES, true); - dt.set(MLRenderingData::PR_WIREFRAME_EDGES, false); - } - } - else - { - dt.set(MLRenderingData::PR_WIREFRAME_TRIANGLES, false); - dt.set(MLRenderingData::PR_WIREFRAME_EDGES, false); - } -} - - -void MLPoliciesStandAloneFunctions::setPerViewGLOptionsAccordindToWireModality(MeshModel* mm, MLRenderingData& dt) -{ - if (mm == NULL) - return; - MLPerViewGLOptions glopts; - dt.get(glopts); - glopts._peredge_fauxwire_enabled = dt.isPrimitiveActive(MLRenderingData::PR_WIREFRAME_EDGES); - glopts._peredge_wire_enabled = (dt.isPrimitiveActive(MLRenderingData::PR_WIREFRAME_EDGES) || dt.isPrimitiveActive(MLRenderingData::PR_WIREFRAME_TRIANGLES) || (glopts._peredge_wire_enabled && (mm->cm.VN() > 0) && (mm->cm.FN() > 0))); - dt.set(glopts); -} - -MLRenderingData::PRIMITIVE_MODALITY MLPoliciesStandAloneFunctions::bestPrimitiveModalityAccordingToMesh( MeshModel* m ) -{ - if (m != NULL) - { - if (m->cm.FN() > 0) - return MLRenderingData::PR_SOLID; - else - if ((m->cm.VN() > 0) && (m->cm.EN() > 0)) - return MLRenderingData::PR_WIREFRAME_EDGES; - else - if (m->cm.VN() > 0) - return MLRenderingData::PR_POINTS; - } - return MLRenderingData::PR_ARITY; -} - -void MLPoliciesStandAloneFunctions::suggestedDefaultPerViewGLOptions( MLPerViewGLOptions& tmp ) -{ - tmp._perbbox_fixed_color = vcg::Color4b(0xffeaeaea); - tmp._perpoint_fixed_color = vcg::Color4b(0xff459583); - tmp._perwire_fixed_color = vcg::Color4b(vcg::Color4b::DarkGray); - tmp._persolid_fixed_color = vcg::Color4b(vcg::Color4b::LightGray); - tmp._sel_enabled = true; - tmp._peredge_extra_enabled = true; -} - -//void MLPoliciesStandAloneFunctions::bestPrimitiveModalityMaskAfterUpdate( MeshModel* meshmodel,int meshmodelmask,const MLRenderingData::PRIMITIVE_MODALITY_MASK& inputpm,MLRenderingData::PRIMITIVE_MODALITY_MASK& outputpm ) -//{ -// MLRenderingData::PRIMITIVE_MODALITY_MASK tmpmask = 0; -// if (meshmodel->cm.VN() == 0) -// { -// outputpm = MLRenderingData::PR_NONE; -// return; -// } -// -// tmpmask = (inputpm -//} - -MLRenderingData::MLRenderingData() - :PerViewData() -{ - _glopts = new MLPerViewGLOptions(); -} - -//MLRenderingData::MLRenderingData( const MLRenderingData& dt ) -// :PerViewData(dt) -//{ -//} - -bool MLRenderingData::set( MLRenderingData::PRIMITIVE_MODALITY pm,const MLRenderingData::RendAtts& atts ) -{ - MLRenderingData::RendAtts tmp(atts); - MLPoliciesStandAloneFunctions::maskMeaninglessAttributesPerPrimitiveModality(pm,tmp); - //MLPoliciesStandAloneFunctions::setAttributePriorities(tmp); - return PerViewData::set(pm,tmp); -} - -bool MLRenderingData::set( MLRenderingData::PRIMITIVE_MODALITY pm,MLRenderingData::ATT_NAMES att,bool onoff ) -{ - MLRenderingData::RendAtts tmp; - bool valid = this->get(pm,tmp); - if (valid) - { - tmp[att] = onoff; - return set(pm,tmp); - } - return false; -} - -bool MLRenderingData::set( MLRenderingData::PRIMITIVE_MODALITY pm,bool onoff ) -{ - return vcg::PerViewData::set(pm,onoff); -} - -void MLRenderingData::set( const MLPerViewGLOptions& opts ) -{ - vcg::PerViewData::set(opts); -} - - -MLPluginGLContext::MLPluginGLContext(const QGLFormat& frmt,QPaintDevice* dvc,MLSceneGLSharedDataContext& cont ) - :QGLContext(frmt,dvc),_shared(cont) -{ - -} - -MLPluginGLContext::~MLPluginGLContext() -{ -} - -void MLPluginGLContext::drawMeshModel( int meshid) const -{ - MLPluginGLContext* id = const_cast(this); - _shared.draw(meshid,id); -} - -void MLPluginGLContext::setRenderingData( int meshid,MLRenderingData& dt ) -{ - _shared.requestSetPerMeshViewRenderingData(QThread::currentThread(),meshid,this,dt); -} - -void MLPluginGLContext::initPerViewRenderingData(int meshid,MLRenderingData& dt) -{ - _shared.requestInitPerMeshView(QThread::currentThread(),meshid,this,dt); -} - -void MLPluginGLContext::removePerViewRenderindData() -{ - _shared.requestRemovePerMeshView(QThread::currentThread(),this); -} - - -void MLPluginGLContext::meshAttributesUpdated( int meshid,bool conntectivitychanged,const MLRenderingData::RendAtts& dt ) -{ - _shared.requestMeshAttributesUpdated(QThread::currentThread(),meshid,conntectivitychanged,dt); -} - - -void MLPluginGLContext::smoothModalitySuggestedRenderingData( MLRenderingData& dt ) -{ - MLRenderingData::RendAtts att; - att[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true; - att[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true; - dt.set(MLRenderingData::PRIMITIVE_MODALITY::PR_SOLID,att); -} - -void MLPluginGLContext::pointModalitySuggestedRenderingData( MLRenderingData& dt ) -{ - MLRenderingData::RendAtts att; - att[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true; - att[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true; - dt.set(MLRenderingData::PRIMITIVE_MODALITY::PR_POINTS,att); -} - - - diff --git a/src/common/ml_shared_data_context/ml_plugin_gl_context.cpp b/src/common/ml_shared_data_context/ml_plugin_gl_context.cpp new file mode 100644 index 000000000..e9bec9a69 --- /dev/null +++ b/src/common/ml_shared_data_context/ml_plugin_gl_context.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "ml_plugin_gl_context.h" + +#include + +MLPluginGLContext::MLPluginGLContext(const QGLFormat& frmt,QPaintDevice* dvc,MLSceneGLSharedDataContext& cont ) + :QGLContext(frmt,dvc),_shared(cont) +{ +} + +MLPluginGLContext::~MLPluginGLContext() +{ +} + +void MLPluginGLContext::drawMeshModel( int meshid) const +{ + MLPluginGLContext* id = const_cast(this); + _shared.draw(meshid,id); +} + +void MLPluginGLContext::setRenderingData( int meshid,MLRenderingData& dt ) +{ + _shared.requestSetPerMeshViewRenderingData(QThread::currentThread(),meshid,this,dt); +} + +void MLPluginGLContext::initPerViewRenderingData(int meshid,MLRenderingData& dt) +{ + _shared.requestInitPerMeshView(QThread::currentThread(),meshid,this,dt); +} + +void MLPluginGLContext::removePerViewRenderindData() +{ + _shared.requestRemovePerMeshView(QThread::currentThread(),this); +} + + +void MLPluginGLContext::meshAttributesUpdated( int meshid,bool conntectivitychanged,const MLRenderingData::RendAtts& dt ) +{ + _shared.requestMeshAttributesUpdated(QThread::currentThread(),meshid,conntectivitychanged,dt); +} + + +void MLPluginGLContext::smoothModalitySuggestedRenderingData( MLRenderingData& dt ) +{ + MLRenderingData::RendAtts att; + att[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true; + att[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true; + dt.set(MLRenderingData::PRIMITIVE_MODALITY::PR_SOLID,att); +} + +void MLPluginGLContext::pointModalitySuggestedRenderingData( MLRenderingData& dt ) +{ + MLRenderingData::RendAtts att; + att[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true; + att[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true; + dt.set(MLRenderingData::PRIMITIVE_MODALITY::PR_POINTS,att); +} diff --git a/src/meshlabplugins/filter_globalregistration/globalregistration.h b/src/common/ml_shared_data_context/ml_plugin_gl_context.h similarity index 60% rename from src/meshlabplugins/filter_globalregistration/globalregistration.h rename to src/common/ml_shared_data_context/ml_plugin_gl_context.h index f07c4928e..d6f172e49 100644 --- a/src/meshlabplugins/filter_globalregistration/globalregistration.h +++ b/src/common/ml_shared_data_context/ml_plugin_gl_context.h @@ -2,7 +2,7 @@ * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * -* Copyright(C) 2005 \/)\/ * +* Copyright(C) 2005-2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -21,32 +21,33 @@ * * ****************************************************************************/ -#ifndef SAMPLEFILTERSPLUGIN_H -#define SAMPLEFILTERSPLUGIN_H +#ifndef ML_PLUGIN_GL_CONTEXT_H +#define ML_PLUGIN_GL_CONTEXT_H -#include +#include "ml_scene_gl_shared_data_context.h" -class GlobalRegistrationPlugin : public QObject, public FilterPluginInterface +class MLPluginGLContext : public QGLContext { - Q_OBJECT - MESHLAB_PLUGIN_IID_EXPORTER(FILTER_PLUGIN_INTERFACE_IID) - Q_INTERFACES(FilterPluginInterface) - public: - enum { FP_GLOBAL_REGISTRATION } ; + MLPluginGLContext( + const QGLFormat& frmt, + QPaintDevice* dvc, + MLSceneGLSharedDataContext& shared); + ~MLPluginGLContext(); - GlobalRegistrationPlugin(); + void initPerViewRenderingData(int meshid, MLRenderingData& dt); + void removePerViewRenderindData(); + void setRenderingData(int meshid, MLRenderingData& dt); + void drawMeshModel(int meshid) const; + void meshAttributesUpdated( + int meshid, + bool conntectivitychanged, + const MLRenderingData::RendAtts& dt); - QString pluginName() const; - - QString filterName(FilterIDType filter) const; - QString filterInfo(FilterIDType filter) const; - void initParameterList(const QAction*, MeshDocument &/*m*/, RichParameterList & /*parent*/); - bool applyFilter(const QAction* filter, MeshDocument &md, std::map& outputValues, unsigned int& postConditionMask, const RichParameterList & /*parent*/, vcg::CallBackPos * cb) ; - int postCondition(const QAction* ) const {return MeshModel::MM_VERTCOORD; } - FilterClass getClass(const QAction* a) const; - FILTER_ARITY filterArity(const QAction *) const {return SINGLE_MESH;} + static void smoothModalitySuggestedRenderingData(MLRenderingData& dt); + static void pointModalitySuggestedRenderingData(MLRenderingData& dt); +private: + MLSceneGLSharedDataContext& _shared; }; - -#endif +#endif // ML_PLUGIN_GL_CONTEXT_H diff --git a/src/common/ml_shared_data_context/ml_scene_gl_shared_data_context.cpp b/src/common/ml_shared_data_context/ml_scene_gl_shared_data_context.cpp new file mode 100644 index 000000000..624e64ad1 --- /dev/null +++ b/src/common/ml_shared_data_context/ml_scene_gl_shared_data_context.cpp @@ -0,0 +1,538 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "ml_scene_gl_shared_data_context.h" +#include "../ml_document/mesh_document.h" +#include "../GLExtensionsManager.h" + + +MLSceneGLSharedDataContext::MLSceneGLSharedDataContext(MeshDocument& md,vcg::QtThreadSafeMemoryInfo& gpumeminfo,bool highprecision,size_t perbatchtriangles, size_t minfacespersmoothrendering) + :QGLWidget(),_md(md),_gpumeminfo(gpumeminfo),_perbatchtriangles(perbatchtriangles), _minfacessmoothrendering(minfacespersmoothrendering),_highprecision(highprecision),_timer(this) +{ + //if (md.size() != 0) + // throw MLException(QString("MLSceneGLSharedDataContext: MeshDocument is not empty when MLSceneGLSharedDataContext is constructed.")); + + connect(&_timer,SIGNAL(timeout()),this,SLOT(updateGPUMemInfo())); + + /*connection intended for the plugins living in another thread*/ + connect(this,SIGNAL(initPerMeshViewRequestMT(int,QGLContext*,const MLRenderingData&)),this,SLOT(initPerMeshViewRequested(int,QGLContext*,const MLRenderingData&)),Qt::BlockingQueuedConnection); + connect(this,SIGNAL(removePerMeshViewRequestMT(QGLContext*)),this,SLOT(removePerMeshViewRequested(QGLContext*)),Qt::BlockingQueuedConnection); + connect(this,SIGNAL(setPerMeshViewRenderingDataRequestMT(int,QGLContext*,const MLRenderingData&)),this,SLOT(setPerMeshViewRenderingDataRequested(int,QGLContext*,const MLRenderingData&)),Qt::BlockingQueuedConnection); + connect(this,SIGNAL(meshAttributesUpdatedRequestMT(int,bool,const MLRenderingData::RendAtts&)),this,SLOT(meshAttributesUpdatedRequested(int,bool,const MLRenderingData::RendAtts&)),Qt::BlockingQueuedConnection); + /****************************************************************/ + + ///*connection intended for the plugins living in the same thread*/ + //connect(this,SIGNAL(initPerMeshViewRequestST(int,QGLContext*,const MLRenderingData&)),this,SLOT(initPerMeshViewRequested(int,QGLContext*,const MLRenderingData&)),Qt::DirectConnection); + //connect(this,SIGNAL(removePerMeshViewRequestST(QGLContext*)),this,SLOT(removePerMeshViewRequested(QGLContext*)),Qt::DirectConnection); + //connect(this,SIGNAL(setPerMeshViewRenderingDataRequestST(int,QGLContext*,const MLRenderingData&)),this,SLOT(setPerMeshViewRenderingDataRequested(int,QGLContext*,const MLRenderingData&)),Qt::DirectConnection); + ///****************************************************************/ + + _timer.start(1000); + updateGPUMemInfo(); + + // Print OpenGL version + const auto format = this->format(); + std::cout << "Using OpenGL " << format.majorVersion() << "." << format.minorVersion() << std::endl; + + //if in the document there are already some meshes, we insert them here.... + MeshModel* mm = _md.nextMesh(); + do { + if (mm != nullptr) + meshInserted(mm->id()); + mm = _md.nextMesh(mm); + } while (mm != nullptr); +} + +MLSceneGLSharedDataContext::~MLSceneGLSharedDataContext() +{ + for (auto& p : _meshboman) + delete p.second; +} + +void MLSceneGLSharedDataContext::setMinFacesForSmoothRendering(size_t fcnum) +{ + _minfacessmoothrendering = fcnum; +} + +MLSceneGLSharedDataContext::PerMeshMultiViewManager* MLSceneGLSharedDataContext::meshAttributesMultiViewerManager( int mmid ) const +{ + MeshIDManMap::const_iterator it = _meshboman.find(mmid); + if (it == _meshboman.end()) + return NULL; + return it->second; +} + +void MLSceneGLSharedDataContext::initializeGL() +{ + QGLContext *ctx = makeCurrentGLContext(); + GLExtensionsManager::initializeGLextensions(); + doneCurrentGLContext(ctx); +} + +void MLSceneGLSharedDataContext::setRenderingDataPerMeshView( int mmid,QGLContext* viewerid,const MLRenderingData& perviewdata ) +{ + MeshModel* mm = _md.getMesh(mmid); + if (mm == NULL) + return; + MLSceneGLSharedDataContext::PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + if (man != NULL) + man->setPerViewInfo(viewerid,perviewdata); +} + +void MLSceneGLSharedDataContext::setRenderingDataPerAllMeshViews(int mmid, const MLRenderingData& perviewdata) +{ + MeshModel* mm = _md.getMesh(mmid); + if (mm == NULL) + return; + MLSceneGLSharedDataContext::PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + if (man != NULL) + man->setPerAllViewsInfo(perviewdata); +} + +//void MLSceneGLSharedDataContext::setRequestedAttributesPerMeshViews( int mmid,const QList& viewerid,const MLRenderingData& perviewdata ) +//{ +// MeshModel* mm = _md.getMesh(mmid); +// if (mm == NULL) +// return; +// +// PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); +// if (man != NULL) +// { +// MLRenderingData outdt; +// MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMesh(mm,perviewdata,outdt); +// foreach(QGLContext* vid,viewerid) +// { +// setRequestedAttributesPerMeshView(mmid,vid,outdt); +// } +// } +//} + + +void MLSceneGLSharedDataContext::deAllocateTexturesPerMesh( int mmid ) +{ + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + if (man != NULL) + { + QGLContext* ctx = makeCurrentGLContext(); + std::vector texids; + for(size_t ii = 0;ii < man->textureIDContainer().size();++ii) + { + texids.push_back(man->textureIDContainer()[ii]); + } + + for (auto tex : texids) + man->textureIDContainer().remove(tex); + + glDeleteTextures(texids.size(), texids.data()); + doneCurrentGLContext(ctx); + } +} + +GLuint MLSceneGLSharedDataContext::getTextureId(int meshid, size_t position) const +{ + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(meshid); + if ((man != NULL) && (position < man->textureIDContainer().size())) + { + return man->textureIDContainer()[position]; + } + return 0; +} + +int roundUpToTheNextHighestPowerOf2(unsigned int v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v; +} + +GLuint MLSceneGLSharedDataContext::allocateTexturePerMesh( int meshid,const QImage& img,size_t maxdimtextmpx) +{ + GLuint res = 0; + PerMeshMultiViewManager* meshfeed = meshAttributesMultiViewerManager(meshid); + if (meshfeed != NULL) + { + int singlemaxtexturesize = roundUpToTheNextHighestPowerOf2(int(sqrt(float(maxdimtextmpx))*1024.0))/2; + QImage imgscaled; + QImage imggl; + + QGLContext* ctx = makeCurrentGLContext(); + GLint maxtexturesize; + glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxtexturesize); + + if(maxtexturesize < singlemaxtexturesize) + maxtexturesize = singlemaxtexturesize; + + int bestW=roundUpToTheNextHighestPowerOf2(img.width() ); + int bestH=roundUpToTheNextHighestPowerOf2(img.height()); + while(bestW>maxtexturesize) bestW /=2; + while(bestH>maxtexturesize) bestH /=2; + //Logf(GLLogStream::SYSTEM," Texture[ %3i ] = '%s' ( %6i x %6i ) -> ( %6i x %6i )", i,mp->cm.textures[i].c_str(), img.width(), img.height(),bestW,bestH); + imgscaled=img.scaled(bestW,bestH,Qt::IgnoreAspectRatio,Qt::SmoothTransformation); + imggl=convertToGLFormat(imgscaled); + + vcg::QtThreadSafeTextureNamesContainer& txtcont = meshfeed->textureIDContainer(); + + + GLuint tmpid; + glGenTextures( 1, (GLuint*)&(tmpid) ); + glBindTexture( GL_TEXTURE_2D, tmpid ); + //qDebug(" will be loaded as GL texture id %i ( %i x %i )",txtcont[txtcont.size() - 1] ,imgGL.width(), imgGL.height()); + glTexImage2D( GL_TEXTURE_2D, 0, 3, imggl.width(), imggl.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, imggl.bits() ); + glGenerateMipmap(GL_TEXTURE_2D); + txtcont.push_back(tmpid); + res = tmpid; + + // ensure mipmaps are computed + glFinish(); + + doneCurrentGLContext(ctx); + } + return res; +} + + +void MLSceneGLSharedDataContext::meshInserted( int mmid ) +{ + MeshModel* mesh = _md.getMesh(mmid); + if (mesh != NULL) + { + _meshboman[mmid] = new PerMeshMultiViewManager(mesh->cm,_gpumeminfo,_perbatchtriangles); + _meshboman[mmid]->setDebugMode(true); + } +} + +void MLSceneGLSharedDataContext::meshRemoved(int mmid) +{ + MeshIDManMap::iterator it = _meshboman.find(mmid); + if (it == _meshboman.end()) + return; + + PerMeshMultiViewManager* man = it->second; + if (man != NULL) + { + QGLContext* ctx = makeCurrentGLContext(); + man->removeAllViewsAndDeallocateBO(); + doneCurrentGLContext(ctx); + delete man; + } + _meshboman.erase(it); +} + +void MLSceneGLSharedDataContext::setMeshTransformationMatrix( int mmid,const Matrix44m& m ) +{ + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + if (man != NULL) + man->setTrMatrix(m); +} + +void MLSceneGLSharedDataContext::setSceneTransformationMatrix( const Matrix44m& /*m*/ ) +{ + +} + +void MLSceneGLSharedDataContext::setGLOptions( int mmid,QGLContext* viewid,const MLPerViewGLOptions& opts ) +{ + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + if (man != NULL) + man->setGLOptions(viewid,opts); +} + +void MLSceneGLSharedDataContext::draw( int mmid,QGLContext* viewid ) const +{ + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + if (man != NULL) + man->draw(viewid); +} + +void MLSceneGLSharedDataContext::drawAllocatedAttributesSubset(int mmid, QGLContext * viewid, const MLRenderingData & dt) +{ + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + if (man != NULL) + man->drawAllocatedAttributesSubset(viewid,dt); +} + +void MLSceneGLSharedDataContext::removeView( QGLContext* viewerid ) +{ + QGLContext* ctx = makeCurrentGLContext(); + for(MeshIDManMap::iterator it = _meshboman.begin();it != _meshboman.end();++it) + { + PerMeshMultiViewManager* man = it->second; + if (man != NULL) + { + man->removeView(viewerid); + man->manageBuffers(); + } + } + doneCurrentGLContext(ctx); +} + +void MLSceneGLSharedDataContext::addView( QGLContext* viewerid,MLRenderingData& dt) +{ + for(MeshIDManMap::iterator it = _meshboman.begin();it != _meshboman.end();++it) + { + MeshModel* mesh = _md.getMesh(it->first); + if (mesh != NULL) + { + MLPoliciesStandAloneFunctions::suggestedDefaultPerViewRenderingData(mesh,dt, _minfacessmoothrendering); + setRenderingDataPerMeshView(it->first,viewerid,dt); + manageBuffers(it->first); + } + } +} + +void MLSceneGLSharedDataContext::addView(QGLContext* viewerid) +{ + for(MeshIDManMap::iterator it = _meshboman.begin();it != _meshboman.end();++it) + { + MeshModel* mesh = _md.getMesh(it->first); + if (mesh != NULL) + { + MLRenderingData dt; + setRenderingDataPerMeshView(it->first,viewerid,dt); + //manageBuffers(it.key()); + } + } +} + +void MLSceneGLSharedDataContext::deAllocateGPUSharedData() +{ + QGLContext* ctx = makeCurrentGLContext(); + for(MeshIDManMap::iterator it = _meshboman.begin();it != _meshboman.end();++it) + { + PerMeshMultiViewManager* man = it->second; + deAllocateTexturesPerMesh(it->first); + man->removeAllViewsAndDeallocateBO(); + } + doneCurrentGLContext(ctx); +} + +void MLSceneGLSharedDataContext::meshAttributesUpdated(int mmid,bool conntectivitychanged,const MLRenderingData::RendAtts& atts) +{ + MeshModel* mm = _md.getMesh(mmid); + if (mm == NULL) + return; + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + if (man != NULL) + man->meshAttributesUpdated(conntectivitychanged,atts); +} + +void MLSceneGLSharedDataContext::meshDeallocated( int /*mmid*/ ) +{ + +} + +void MLSceneGLSharedDataContext::getRenderInfoPerMeshView( int mmid,QGLContext* ctx,MLRenderingData& dt ) +{ + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + if (man != NULL) + man->getPerViewInfo(ctx,dt); +} + +void MLSceneGLSharedDataContext::getRenderInfoPerMeshView( QGLContext* ctx,PerMeshRenderingDataMap& map ) +{ + map.clear(); + for(MeshIDManMap::iterator it = _meshboman.begin();it != _meshboman.end();++it) + { + MLRenderingData dt; + int meshid = it->first; + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(meshid); + if (man != NULL) + man->getPerViewInfo(ctx,dt); + map.insert(meshid,dt); + } +} + +bool MLSceneGLSharedDataContext::manageBuffers( int mmid ) +{ + bool didsomething = false; + MeshModel* mm = _md.getMesh(mmid); + + if (mm == NULL) + return didsomething; + + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + + if (man != NULL) + { + QGLContext* ctx = makeCurrentGLContext(); + man->manageBuffers(); + doneCurrentGLContext(ctx); + } + return didsomething; +} + +void MLSceneGLSharedDataContext::setDebugMode(int mmid,bool activatedebugmodality ) +{ + MeshModel* mm = _md.getMesh(mmid); + if (mm == NULL) + return; + + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + if (man != NULL) + man->setDebugMode(activatedebugmodality); +} + +void MLSceneGLSharedDataContext::getLog( int mmid,MLRenderingData::DebugInfo& info) +{ + MeshModel* mm = _md.getMesh(mmid); + if (mm == NULL) + return; + + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + if (man != NULL) + man->getLog(info); + return; +} + +bool MLSceneGLSharedDataContext::isBORenderingAvailable( int mmid ) +{ + MeshModel* mm = _md.getMesh(mmid); + if (mm == NULL) + return false; + + PerMeshMultiViewManager* man = meshAttributesMultiViewerManager(mmid); + if (man != NULL) + return man->isBORenderingAvailable(); + return false; +} + +#define GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 +#define GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 +#define VBO_FREE_MEMORY_ATI 0x87FB +#define TEXTURE_FREE_MEMORY_ATI 0x87FC +#define RENDERBUFFER_FREE_MEMORY_ATI 0x87FD + +void MLSceneGLSharedDataContext::updateGPUMemInfo() +{ + initializeGL(); + QGLContext* ctx = makeCurrentGLContext(); + GLint allmem = 0; + glGetIntegerv(GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &allmem); + GLint currentallocated = 0; + glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, ¤tallocated); + /*GLenum errorNV =*/ glGetError(); // purge errors + + GLint ATI_vbo[4] = { 0, 0, 0, 0 }; + glGetIntegerv(VBO_FREE_MEMORY_ATI, ATI_vbo); + GLint ATI_tex[4] = { 0, 0, 0, 0 }; + glGetIntegerv(TEXTURE_FREE_MEMORY_ATI, ATI_tex); + /*GLenum errorATI =*/ glGetError(); // purge errors + + doneCurrentGLContext(ctx); + emit currentAllocatedGPUMem((int)allmem, (int)currentallocated, (int)ATI_tex[0], (int)ATI_vbo[0]); +} + +//void MLSceneGLSharedDataContext::updateRequested( int meshid,MLRenderingData::ATT_NAMES name ) +//{ +// MLRenderingData::RendAtts att; +// att[name] = true; +// meshAttributesUpdated(meshid,false,att); +// manageBuffers(meshid); +// +//} + +void MLSceneGLSharedDataContext::initPerMeshViewRequested( int meshid,QGLContext* cont,const MLRenderingData& dt) +{ + addView(cont); + setRenderingDataPerMeshView(meshid,cont,dt); + manageBuffers(meshid); +} + +void MLSceneGLSharedDataContext::setPerMeshViewRenderingDataRequested( int meshid,QGLContext* cont,const MLRenderingData& dt ) +{ + setRenderingDataPerMeshView(meshid,cont,dt); + manageBuffers(meshid); +} + +void MLSceneGLSharedDataContext::removePerMeshViewRequested(QGLContext* cont ) +{ + removeView(cont); +} + +void MLSceneGLSharedDataContext::meshAttributesUpdatedRequested( int meshid,bool connectivitychanged,const MLRenderingData::RendAtts& dt ) +{ + meshAttributesUpdated(meshid,connectivitychanged,dt); + manageBuffers(meshid); +} + +void MLSceneGLSharedDataContext::requestInitPerMeshView(QThread* callingthread,int meshid,QGLContext* cont,const MLRenderingData& dt ) +{ + QThread* tt = thread(); + if (callingthread != tt) + emit initPerMeshViewRequestMT(meshid,cont,dt); + else + //emit initPerMeshViewRequestST(meshid,cont,dt); + initPerMeshViewRequested(meshid,cont,dt); +} + +void MLSceneGLSharedDataContext::requestRemovePerMeshView(QThread* callingthread,QGLContext* cont ) +{ + QThread* tt = thread(); + if (callingthread != tt) + emit removePerMeshViewRequestMT(cont); + else + removeView(cont); +} + +void MLSceneGLSharedDataContext::requestSetPerMeshViewRenderingData(QThread* callingthread,int meshid,QGLContext* cont,const MLRenderingData& dt ) +{ + QThread* tt = thread(); + if (callingthread != tt) + emit setPerMeshViewRenderingDataRequestMT(meshid,cont,dt); + else + //emit setPerMeshViewRenderingDataRequestST(meshid,cont,dt); + setPerMeshViewRenderingDataRequested(meshid,cont,dt); +} + +void MLSceneGLSharedDataContext::requestMeshAttributesUpdated(QThread* callingthread,int meshid,bool connectivitychanged,const MLRenderingData::RendAtts& dt ) +{ + QThread* tt = thread(); + if (callingthread != tt) + emit meshAttributesUpdatedRequestMT(meshid,connectivitychanged,dt); + else + //emit setPerMeshViewRenderingDataRequestST(meshid,cont,dt); + meshAttributesUpdated(meshid,connectivitychanged,dt); +} + + + + +QGLContext* MLSceneGLSharedDataContext::makeCurrentGLContext() +{ + QGLContext* ctx = const_cast(QGLContext::currentContext()); + makeCurrent(); + return ctx; +} + +void MLSceneGLSharedDataContext::doneCurrentGLContext( QGLContext* oldone /*= NULL*/ ) +{ + doneCurrent(); + if (oldone != NULL) + oldone->makeCurrent(); +} + diff --git a/src/common/ml_shared_data_context/ml_scene_gl_shared_data_context.h b/src/common/ml_shared_data_context/ml_scene_gl_shared_data_context.h new file mode 100644 index 000000000..2a45dce0e --- /dev/null +++ b/src/common/ml_shared_data_context/ml_scene_gl_shared_data_context.h @@ -0,0 +1,141 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef ML_SCENE_GL_SHARED_DATA_CONTEXT_H +#define ML_SCENE_GL_SHARED_DATA_CONTEXT_H + +#include "ml_shared_data_context.h" + +class MLSceneGLSharedDataContext : public QGLWidget +{ + Q_OBJECT +public: + //parent is set to NULL in order to avoid QT bug on MAC (business as usual...). + //The QGLWidget are destroyed by hand in the MainWindow destructor... + MLSceneGLSharedDataContext(MeshDocument& md, vcg::QtThreadSafeMemoryInfo& gpumeminfo, bool highprecision, size_t perbatchtriangles, size_t minfacespersmoothrendering = 0); + + ~MLSceneGLSharedDataContext(); + + void setMinFacesForSmoothRendering(size_t fcnum); + + vcg::QtThreadSafeMemoryInfo& memoryInfoManager() const + { + return _gpumeminfo; + } + + inline bool highPrecisionRendering() const + { + return _highprecision; + } + + //Given a QGLContext the PerMeshRenderingDataMap contains the rendering data per each mesh contained in the MeshDocument (eg. flat/smooth shading? pervertex/perface/permesh color?) + //and the 'meaningful' gl parameters used by the rendering system + typedef QMap PerMeshRenderingDataMap; + + MeshDocument& meshDoc() { return _md; } + + void initializeGL(); + void deAllocateGPUSharedData(); + + void draw(int mmid, QGLContext* viewid) const; + void drawAllocatedAttributesSubset(int mmid, QGLContext* viewid, const MLRenderingData& dt); + void setSceneTransformationMatrix(const Matrix44m& m); + void setMeshTransformationMatrix(int mmid, const Matrix44m& m); + + GLuint allocateTexturePerMesh(int mmid, const QImage& img, size_t maxdimtextmb); + void deAllocateTexturesPerMesh(int mmid); + GLuint getTextureId(int meshid, size_t position) const; + + + void getRenderInfoPerMeshView(QGLContext* ctx, PerMeshRenderingDataMap& map); + void getRenderInfoPerMeshView(int mmid, QGLContext* ctx, MLRenderingData& dt); + void meshInserted(int mmid); + void meshRemoved(int mmid); + bool manageBuffers(int mmid); + void setDebugMode(int mmid, bool activatedebugmodality); + void getLog(int mmid, MLRenderingData::DebugInfo& debug); + bool isBORenderingAvailable(int mmid); + + + /*functions intended for the plugins (they emit different signals according if the calling thread is different from the one where the MLSceneGLSharedDataContext object lives)*/ + void requestInitPerMeshView(QThread* callingthread, int meshid, QGLContext* cont, const MLRenderingData& dt); + void requestRemovePerMeshView(QThread* callingthread, QGLContext* cont); + void requestSetPerMeshViewRenderingData(QThread* callingthread, int meshid, QGLContext* cont, const MLRenderingData& dt); + void requestMeshAttributesUpdated(QThread* callingthread, int meshid, bool connectivitychanged, const MLRenderingData::RendAtts& dt); + /***************************************/ + public slots: + void meshDeallocated(int mmid); + void setRenderingDataPerMeshView(int mmid, QGLContext* viewerid, const MLRenderingData& perviewdata); + void setRenderingDataPerAllMeshViews(int mmid, const MLRenderingData& perviewdata); + void setGLOptions(int mmid, QGLContext* viewid, const MLPerViewGLOptions& opts); + + void addView(QGLContext* viewerid); + void addView(QGLContext* viewerid, MLRenderingData& dt); + + + void removeView(QGLContext* viewerid); + void meshAttributesUpdated(int mmid, bool conntectivitychanged, const MLRenderingData::RendAtts& dt); + void updateGPUMemInfo(); + //void updateRequested(int meshid,MLRenderingData::ATT_NAMES name); + + private slots: + /*slots intended for the plugins living in another thread*/ + void initPerMeshViewRequested(int meshid, QGLContext* cont, const MLRenderingData& dt); + void removePerMeshViewRequested(QGLContext* cont); + void setPerMeshViewRenderingDataRequested(int meshid, QGLContext* cont, const MLRenderingData& dt); + void meshAttributesUpdatedRequested(int meshid, bool connectivitychanged, const MLRenderingData::RendAtts& dt); + /***************************************/ +private: + typedef vcg::QtThreadSafeGLMeshAttributesMultiViewerBOManager PerMeshMultiViewManager; + PerMeshMultiViewManager* meshAttributesMultiViewerManager(int mmid) const; + QGLContext* makeCurrentGLContext(); + void doneCurrentGLContext(QGLContext* oldone = NULL); + + MeshDocument& _md; + typedef std::map MeshIDManMap; + MeshIDManMap _meshboman; + vcg::QtThreadSafeMemoryInfo& _gpumeminfo; + size_t _perbatchtriangles; + size_t _minfacessmoothrendering; + bool _highprecision; + QTimer _timer; + +signals: + + void currentAllocatedGPUMem(int nv_all, int nv_current, int ati_tex, int ati_vbo); + + ///*signals intended for the plugins living in the same thread*/ + //void initPerMeshViewRequestST(int,QGLContext*,const MLRenderingData&); + //void removePerMeshViewRequestST(QGLContext*); + //void setPerMeshViewRenderingDataRequestST(int,QGLContext*,const MLRenderingData&); + ///***************************************/ + + /*signals intended for the plugins living in another thread*/ + void initPerMeshViewRequestMT(int, QGLContext*, const MLRenderingData&); + void removePerMeshViewRequestMT(QGLContext*); + void setPerMeshViewRenderingDataRequestMT(int, QGLContext*, const MLRenderingData&); + void meshAttributesUpdatedRequestMT(int, bool, const MLRenderingData::RendAtts&); + /***************************************/ +}; + +#endif // ML_SCENE_GL_SHARED_DATA_CONTEXT_H diff --git a/src/common/ml_shared_data_context/ml_shared_data_context.cpp b/src/common/ml_shared_data_context/ml_shared_data_context.cpp new file mode 100644 index 000000000..1d2317b69 --- /dev/null +++ b/src/common/ml_shared_data_context/ml_shared_data_context.cpp @@ -0,0 +1,482 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "ml_shared_data_context.h" +#include "../GLExtensionsManager.h" +#include "../mlexception.h" +#include +#include + +#include "../ml_document/mesh_document.h" + +void MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMeshSameGLOpts(MeshModel* meshmodel, const MLRenderingData& inputdt, MLRenderingData& outputdt) +{ + MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMeshCommonCode(meshmodel, inputdt, outputdt); + MLPerViewGLOptions opts; + inputdt.get(opts); + outputdt.set(opts); +} + +void MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMesh( MeshModel* meshmodel,const MLRenderingData& inputdt,MLRenderingData& outputdt) +{ + MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMeshCommonCode(meshmodel, inputdt, outputdt); + MLPoliciesStandAloneFunctions::setPerViewGLOptionsAccordindToWireModality(meshmodel, outputdt); + MLPoliciesStandAloneFunctions::setPerViewGLOptionsPriorities(outputdt); + MLPerViewGLOptions opts; + outputdt.get(opts); + MLPoliciesStandAloneFunctions::suggestedDefaultPerViewGLOptions(opts); + outputdt.set(opts); +} + +void MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMeshCommonCode(MeshModel* meshmodel, const MLRenderingData& inputdt, MLRenderingData& outputdt) +{ + if (meshmodel == NULL) + return; + CMeshO& mesh = meshmodel->cm; + if (mesh.VN() == 0) + { + outputdt.reset(false); + return; + } + bool validfaces = (mesh.FN() > 0); + +// MLRenderingData::PRIMITIVE_MODALITY_MASK tmpoutputpm = inputdt.getPrimitiveModalityMask(); + for (size_t pmind = 0; pmind < size_t(MLRenderingData::PR_ARITY); ++pmind) + { + MLRenderingData::PRIMITIVE_MODALITY pmc = MLRenderingData::PRIMITIVE_MODALITY(pmind); + + + MLRenderingData::RendAtts tmpoutputatts; + if (inputdt.get(MLRenderingData::PRIMITIVE_MODALITY(pmind), tmpoutputatts)) + { + tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] &= meshmodel->hasDataMask(MeshModel::MM_VERTCOORD); + tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] &= meshmodel->hasDataMask(MeshModel::MM_VERTNORMAL); + tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] &= validfaces && meshmodel->hasDataMask(MeshModel::MM_FACENORMAL); + tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] &= meshmodel->hasDataMask(MeshModel::MM_VERTCOLOR); + tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] &= validfaces && meshmodel->hasDataMask(MeshModel::MM_FACECOLOR); + + //horrible trick caused by MeshLab GUI. In MeshLab exists just a button turning on/off the texture visualization. + //Unfortunately the RenderMode::textureMode member field is not just a boolean value but and enum one. + //The enum-value depends from the enabled attributes of input mesh. + bool wedgetexture = meshmodel->hasDataMask(MeshModel::MM_WEDGTEXCOORD); + tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] &= (meshmodel->hasDataMask(MeshModel::MM_VERTTEXCOORD) && (!wedgetexture)); + tmpoutputatts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] &= validfaces && wedgetexture; + if (MLPoliciesStandAloneFunctions::isPrimitiveModalityCompatibleWithMesh(meshmodel, pmc)) + outputdt.set(pmc, tmpoutputatts); + } + else + throw MLException(QString("MLPoliciesStandAloneFunctions: trying to access to a non defined PRIMITIVE_MODALITY!")); + } +} + +void MLPoliciesStandAloneFunctions::fromMeshModelMaskToMLRenderingAtts( int meshmodelmask,MLRenderingData::RendAtts& atts) +{ + atts.reset(); + //connectivitychanged = bool(meshmodelmask | MeshModel::MM_FACEFACETOPO) || bool(meshmodelmask | MeshModel::MM_VERTFACETOPO) || bool(meshmodelmask | MeshModel::MM_VERTNUMBER) || bool(meshmodelmask | MeshModel::MM_FACENUMBER); + atts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = bool(meshmodelmask & MeshModel::MM_VERTCOORD); + atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = bool(meshmodelmask & MeshModel::MM_VERTNORMAL); + atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = bool(meshmodelmask & MeshModel::MM_FACENORMAL); + atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] = bool(meshmodelmask & MeshModel::MM_VERTCOLOR); + atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] = bool(meshmodelmask & MeshModel::MM_FACECOLOR); + //atts[MLRenderingData::ATT_NAMES::ATT_FIXEDCOLOR] = bool(meshmodelmask & MeshModel::MM_COLOR); + atts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] = bool(meshmodelmask & MeshModel::MM_VERTTEXCOORD); + atts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] = bool(meshmodelmask & MeshModel::MM_WEDGTEXCOORD); +} + +void MLPoliciesStandAloneFunctions::maskMeaninglessAttributesPerPrimitiveModality( MLRenderingData::PRIMITIVE_MODALITY pm,MLRenderingData::RendAtts& atts ) +{ + switch(pm) + { + case (MLRenderingData::PR_POINTS): + { + atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = false; + atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] = false; + atts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] = false; + return; + } + case (MLRenderingData::PR_WIREFRAME_EDGES): + case (MLRenderingData::PR_WIREFRAME_TRIANGLES): + { + atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = false; + atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] = false; + atts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] = false; + atts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] = false; + return; + } + case (MLRenderingData::PR_SOLID): + { + return; + } + case (MLRenderingData::PR_ARITY): + { + throw MLException("PR_ARITY passed as parameter!"); + } + } +} + +void MLPoliciesStandAloneFunctions::updatedRendAttsAccordingToPriorities( + const MLRenderingData::PRIMITIVE_MODALITY pm, + const MLRenderingData::RendAtts& updated, //from the result of the filter + const MLRenderingData::RendAtts& current, //from the current model + MLRenderingData::RendAtts& result) //returned final result +{ + MLRenderingData::RendAtts filteredupdated = updated; + MLRenderingData::RendAtts tmp = current; // tmp will be then saved in returned + tmp[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] |= filteredupdated[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION]; + if ((pm == MLRenderingData::PR_WIREFRAME_TRIANGLES) || (pm == MLRenderingData::PR_WIREFRAME_EDGES)) + { + tmp[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = false; + tmp[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = false; + } + else + { + //vert normal shading if in current or in updated + tmp[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] |= filteredupdated[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]; + //face normal shading if in current or in updated + tmp[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] |= filteredupdated[MLRenderingData::ATT_NAMES::ATT_FACENORMAL]; + } + + tmp[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] |= filteredupdated[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR]; + tmp[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] = (tmp[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] || filteredupdated[MLRenderingData::ATT_NAMES::ATT_FACECOLOR]) && !(filteredupdated[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR]); + tmp[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] |= filteredupdated[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE]; + tmp[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] = (tmp[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] || filteredupdated[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE]) && !(filteredupdated[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE]); + result = tmp; +} + +void MLPoliciesStandAloneFunctions::suggestedDefaultPerViewRenderingData(MeshModel* meshmodel,MLRenderingData& dtout, size_t minpolnumpersmoothshading) +{ + MLRenderingData dt; + if (meshmodel == NULL) + return; + if (meshmodel->cm.VN() == 0) + { + dt.reset(); + } + else + { + MLRenderingData::RendAtts tmpatts; + tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true; + tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true; + tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] = true; + tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] = true; + + dt.set(MLRenderingData::PR_POINTS,tmpatts); + + if (meshmodel->cm.FN() > 0) + { + dt.set(MLRenderingData::PR_POINTS,false); + tmpatts.reset(); + tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true; + tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = (size_t(meshmodel->cm.FN()) > minpolnumpersmoothshading); + tmpatts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = !(tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]); + tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] = true; + if (meshmodel != NULL) + tmpatts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] = (meshmodel->hasDataMask(MeshModel::MM_FACECOLOR) && !meshmodel->hasDataMask(MeshModel::MM_VERTCOLOR)); + tmpatts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] = true; + tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] = true; + dt.set(MLRenderingData::PR_SOLID,tmpatts); + } + + if (((meshmodel->cm.FN() == 0) && (meshmodel->cm.EN() > 0)) || (meshmodel->hasDataMask(MeshModel::MM_POLYGONAL))) + { + //dt.reset(); + tmpatts.reset(); + tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true; + tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true; + tmpatts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] = true; + MLPerViewGLOptions opts; + dt.get(opts); + opts._peredge_wire_enabled = true; + opts._peredge_fauxwire_enabled = true; + dt.set(opts); + //dt.set(MLRenderingData::PR_SOLID, false); + } + + } + MLPoliciesStandAloneFunctions::setBestWireModality(meshmodel, dt); + MLPoliciesStandAloneFunctions::computeRequestedRenderingDataCompatibleWithMesh(meshmodel,dt,dtout); +} + + +void MLPoliciesStandAloneFunctions::disableRedundatRenderingDataAccordingToPriorities(MLRenderingData& dt) +{ + for (MLRenderingData::PRIMITIVE_MODALITY pr = MLRenderingData::PRIMITIVE_MODALITY(0); pr < MLRenderingData::PR_ARITY; pr = MLRenderingData::next(pr)) + { + MLRenderingData::RendAtts atts; + dt.get(pr, atts); + MLPoliciesStandAloneFunctions::setAttributePriorities(atts); + dt.set(pr, atts); + } + + //setPerViewGLOptionsPriorities(dt); +} + + +bool MLPoliciesStandAloneFunctions::isPrimitiveModalityCompatibleWithMesh(MeshModel* m,const MLRenderingData::PRIMITIVE_MODALITY pm) +{ + bool validvert = (m->cm.VN() > 0); + bool validfaces = (m->cm.FN() > 0); + bool validedges = (m->cm.EN() > 0); + return MLPoliciesStandAloneFunctions::isPrimitiveModalityCompatibleWithMeshInfo(validvert,validfaces,validedges,m->dataMask(),pm); +} + +bool MLPoliciesStandAloneFunctions::isPrimitiveModalityCompatibleWithMeshInfo(bool validvert,bool validfaces,bool validedges,int meshmask,const MLRenderingData::PRIMITIVE_MODALITY pm) +{ + switch(pm) + { + case(MLRenderingData::PR_POINTS): + { + return validvert; + } + case(MLRenderingData::PR_WIREFRAME_EDGES): + { + return (validvert) && ((meshmask & MeshModel::MM_POLYGONAL) || ((!validfaces) && (validedges))); + } + case(MLRenderingData::PR_WIREFRAME_TRIANGLES): + case(MLRenderingData::PR_SOLID): + { + return validvert && validfaces; + } + case (MLRenderingData::PR_ARITY): + { + throw MLException("PR_ARITY passed as parameter!"); + } + } + return false; +} + +bool MLPoliciesStandAloneFunctions::isPrimitiveModalityWorthToBeActivated(MLRenderingData::PRIMITIVE_MODALITY pm,bool wasvisualized,bool wasmeanigful,bool ismeaningful) +{ + (void) pm; + if ((!wasmeanigful) && (ismeaningful)) + return true; + if (wasmeanigful && ismeaningful && wasvisualized) + return true; + return false; +} + +void MLPoliciesStandAloneFunctions::setAttributePriorities(MLRenderingData::RendAtts& atts ) +{ + atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] &= !(atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]); + atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] &= !(atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR]); + atts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] &= !(atts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE]); +} + +//void MLPoliciesStandAloneFunctions::setPerViewRenderingDataPriorities( MeshModel* mm,MLRenderingData& dt ) +//{ +// if (mm == NULL) +// return; +// +//} + +void MLPoliciesStandAloneFunctions::setPerViewGLOptionsPriorities(MLRenderingData& dt ) +{ + //if (mm == NULL) + // return; + //bool permeshcolor = mm->hasDataMask(MeshModel::MM_COLOR); + MLPerViewGLOptions glopts; + if (!dt.get(glopts)) + return; + /*if (permeshcolor) + glopts._perpoint_mesh_color_enabled = true;*/ + + for(MLRenderingData::PRIMITIVE_MODALITY pm = MLRenderingData::PRIMITIVE_MODALITY(0);pm < MLRenderingData::PR_ARITY;pm = MLRenderingData::next(pm)) + { + MLRenderingData::RendAtts atts; + if (dt.get(pm,atts)) + { + switch(pm) + { + case (MLRenderingData::PR_POINTS): + { + glopts._perpoint_noshading = !atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]; + glopts._perpoint_mesh_color_enabled &= !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR]; + glopts._perpoint_fixed_color_enabled = !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] && !glopts._perpoint_mesh_color_enabled; + + break; + } + case (MLRenderingData::PR_WIREFRAME_EDGES): + case (MLRenderingData::PR_WIREFRAME_TRIANGLES): + { + glopts._perwire_noshading = !atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]; + glopts._perwire_mesh_color_enabled &= !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR]; + glopts._perwire_fixed_color_enabled = !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] && !atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] && !glopts._perwire_mesh_color_enabled; + break; + } + case (MLRenderingData::PR_SOLID): + { + glopts._persolid_noshading = (!atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL]) && (!atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL]); + glopts._persolid_mesh_color_enabled &= !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] && !atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR]; + glopts._persolid_fixed_color_enabled = !atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] && !atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] && !glopts._persolid_mesh_color_enabled; + break; + } + case (MLRenderingData::PR_ARITY): + { + throw MLException("PR_ARITY passed as parameter!"); + } + + } + } + } + dt.set(glopts); +} + +void MLPoliciesStandAloneFunctions::filterUselessUdpateAccordingToMeshMask( MeshModel* m,MLRenderingData::RendAtts& atts ) +{ + if (m == NULL) + return; + atts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] &= m->hasDataMask(MeshModel::MM_VERTCOORD); + atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] &= m->hasDataMask(MeshModel::MM_VERTNORMAL); + atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] &= m->hasDataMask(MeshModel::MM_FACENORMAL); + atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] &= m->hasDataMask(MeshModel::MM_VERTCOLOR); + atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] &= m->hasDataMask(MeshModel::MM_FACECOLOR); + //atts[MLRenderingData::ATT_NAMES::ATT_FIXEDCOLOR] + atts[MLRenderingData::ATT_NAMES::ATT_WEDGETEXTURE] &= m->hasDataMask(MeshModel::MM_WEDGTEXCOORD); + atts[MLRenderingData::ATT_NAMES::ATT_VERTTEXTURE] &= m->hasDataMask(MeshModel::MM_VERTTEXCOORD); +} + +void MLPoliciesStandAloneFunctions::setBestWireModality(MeshModel* mm, MLRenderingData& dt) +{ + if (mm == NULL) + return; + MLPerViewGLOptions opts; + dt.get(opts); + + if ((mm->cm.VN() > 0) && (mm->cm.FN() == 0) && (mm->cm.EN() > 0)) + { + dt.set(MLRenderingData::PR_WIREFRAME_EDGES,true && opts._peredge_wire_enabled); + dt.set(MLRenderingData::PR_WIREFRAME_TRIANGLES, false); + return; + } + + if (opts._peredge_wire_enabled) + { + if (opts._peredge_fauxwire_enabled) + { + dt.set(MLRenderingData::PR_WIREFRAME_EDGES, true); + dt.set(MLRenderingData::PR_WIREFRAME_TRIANGLES, false); + } + else + { + dt.set(MLRenderingData::PR_WIREFRAME_TRIANGLES, true); + dt.set(MLRenderingData::PR_WIREFRAME_EDGES, false); + } + } + else + { + dt.set(MLRenderingData::PR_WIREFRAME_TRIANGLES, false); + dt.set(MLRenderingData::PR_WIREFRAME_EDGES, false); + } +} + + +void MLPoliciesStandAloneFunctions::setPerViewGLOptionsAccordindToWireModality(MeshModel* mm, MLRenderingData& dt) +{ + if (mm == NULL) + return; + MLPerViewGLOptions glopts; + dt.get(glopts); + glopts._peredge_fauxwire_enabled = dt.isPrimitiveActive(MLRenderingData::PR_WIREFRAME_EDGES); + glopts._peredge_wire_enabled = (dt.isPrimitiveActive(MLRenderingData::PR_WIREFRAME_EDGES) || dt.isPrimitiveActive(MLRenderingData::PR_WIREFRAME_TRIANGLES) || (glopts._peredge_wire_enabled && (mm->cm.VN() > 0) && (mm->cm.FN() > 0))); + dt.set(glopts); +} + +MLRenderingData::PRIMITIVE_MODALITY MLPoliciesStandAloneFunctions::bestPrimitiveModalityAccordingToMesh(const MeshModel* m ) +{ + if (m != NULL) + { + if (m->cm.FN() > 0) + return MLRenderingData::PR_SOLID; + else + if ((m->cm.VN() > 0) && (m->cm.EN() > 0)) + return MLRenderingData::PR_WIREFRAME_EDGES; + else + if (m->cm.VN() > 0) + return MLRenderingData::PR_POINTS; + } + return MLRenderingData::PR_ARITY; +} + +void MLPoliciesStandAloneFunctions::suggestedDefaultPerViewGLOptions( MLPerViewGLOptions& tmp ) +{ + tmp._perbbox_fixed_color = vcg::Color4b(0xffeaeaea); + tmp._perpoint_fixed_color = vcg::Color4b(252, 233, 79, 255); + tmp._perwire_fixed_color = vcg::Color4b(vcg::Color4b::DarkGray); + tmp._persolid_fixed_color = vcg::Color4b(vcg::Color4b::LightGray); + tmp._sel_enabled = true; + tmp._peredge_extra_enabled = true; +} + +//void MLPoliciesStandAloneFunctions::bestPrimitiveModalityMaskAfterUpdate( MeshModel* meshmodel,int meshmodelmask,const MLRenderingData::PRIMITIVE_MODALITY_MASK& inputpm,MLRenderingData::PRIMITIVE_MODALITY_MASK& outputpm ) +//{ +// MLRenderingData::PRIMITIVE_MODALITY_MASK tmpmask = 0; +// if (meshmodel->cm.VN() == 0) +// { +// outputpm = MLRenderingData::PR_NONE; +// return; +// } +// +// tmpmask = (inputpm +//} + +MLRenderingData::MLRenderingData() + :PerViewData() +{ + _glopts = new MLPerViewGLOptions(); +} + +//MLRenderingData::MLRenderingData( const MLRenderingData& dt ) +// :PerViewData(dt) +//{ +//} + +bool MLRenderingData::set( MLRenderingData::PRIMITIVE_MODALITY pm,const MLRenderingData::RendAtts& atts ) +{ + MLRenderingData::RendAtts tmp(atts); + MLPoliciesStandAloneFunctions::maskMeaninglessAttributesPerPrimitiveModality(pm,tmp); + //MLPoliciesStandAloneFunctions::setAttributePriorities(tmp); + return PerViewData::set(pm,tmp); +} + +bool MLRenderingData::set( MLRenderingData::PRIMITIVE_MODALITY pm,MLRenderingData::ATT_NAMES att,bool onoff ) +{ + MLRenderingData::RendAtts tmp; + bool valid = this->get(pm,tmp); + if (valid) + { + tmp[att] = onoff; + return set(pm,tmp); + } + return false; +} + +bool MLRenderingData::set( MLRenderingData::PRIMITIVE_MODALITY pm,bool onoff ) +{ + return vcg::PerViewData::set(pm,onoff); +} + +void MLRenderingData::set( const MLPerViewGLOptions& opts ) +{ + vcg::PerViewData::set(opts); +} + diff --git a/src/common/ml_shared_data_context.h b/src/common/ml_shared_data_context/ml_shared_data_context.h similarity index 66% rename from src/common/ml_shared_data_context.h rename to src/common/ml_shared_data_context/ml_shared_data_context.h index 3029a2511..943874418 100644 --- a/src/common/ml_shared_data_context.h +++ b/src/common/ml_shared_data_context/ml_shared_data_context.h @@ -2,7 +2,7 @@ * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * -* Copyright(C) 2005 \/)\/ * +* Copyright(C) 2005-2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -27,11 +27,12 @@ #include #include -#include "ml_document/cmesh.h" +#include "../ml_document/cmesh.h" #include #include +#include #include class MeshModel; @@ -318,7 +319,7 @@ struct MLPoliciesStandAloneFunctions static bool isPrimitiveModalityWorthToBeActivated(MLRenderingData::PRIMITIVE_MODALITY pm, bool wasvisualized, bool wasmeanigful, bool ismeaningful); - static MLRenderingData::PRIMITIVE_MODALITY bestPrimitiveModalityAccordingToMesh(MeshModel* m); + static MLRenderingData::PRIMITIVE_MODALITY bestPrimitiveModalityAccordingToMesh(const MeshModel* m); static void filterUselessUdpateAccordingToMeshMask(MeshModel* m, MLRenderingData::RendAtts& atts); @@ -327,135 +328,4 @@ struct MLPoliciesStandAloneFunctions static void setPerViewGLOptionsAccordindToWireModality(MeshModel* mm, MLRenderingData& dt); }; - -class MLSceneGLSharedDataContext : public QGLWidget -{ - Q_OBJECT -public: - //parent is set to NULL in order to avoid QT bug on MAC (business as usual...). - //The QGLWidget are destroyed by hand in the MainWindow destructor... - MLSceneGLSharedDataContext(MeshDocument& md, vcg::QtThreadSafeMemoryInfo& gpumeminfo, bool highprecision, size_t perbatchtriangles, size_t minfacespersmoothrendering = 0); - - ~MLSceneGLSharedDataContext(); - - void setMinFacesForSmoothRendering(size_t fcnum); - - vcg::QtThreadSafeMemoryInfo& memoryInfoManager() const - { - return _gpumeminfo; - } - - inline bool highPrecisionRendering() const - { - return _highprecision; - } - - //Given a QGLContext the PerMeshRenderingDataMap contains the rendering data per each mesh contained in the MeshDocument (eg. flat/smooth shading? pervertex/perface/permesh color?) - //and the 'meaningful' gl parameters used by the rendering system - typedef QMap PerMeshRenderingDataMap; - - MeshDocument& meshDoc() { return _md; } - - void initializeGL(); - void deAllocateGPUSharedData(); - - void draw(int mmid, QGLContext* viewid) const; - void drawAllocatedAttributesSubset(int mmid, QGLContext* viewid, const MLRenderingData& dt); - void setSceneTransformationMatrix(const Matrix44m& m); - void setMeshTransformationMatrix(int mmid, const Matrix44m& m); - - GLuint allocateTexturePerMesh(int mmid, const QImage& img, size_t maxdimtextmb); - void deAllocateTexturesPerMesh(int mmid); - GLuint getTextureId(int meshid, size_t position) const; - - - void getRenderInfoPerMeshView(QGLContext* ctx, PerMeshRenderingDataMap& map); - void getRenderInfoPerMeshView(int mmid, QGLContext* ctx, MLRenderingData& dt); - void meshInserted(int mmid); - void meshRemoved(int mmid); - bool manageBuffers(int mmid); - void setDebugMode(int mmid, bool activatedebugmodality); - void getLog(int mmid, MLRenderingData::DebugInfo& debug); - bool isBORenderingAvailable(int mmid); - - - /*functions intended for the plugins (they emit different signals according if the calling thread is different from the one where the MLSceneGLSharedDataContext object lives)*/ - void requestInitPerMeshView(QThread* callingthread, int meshid, QGLContext* cont, const MLRenderingData& dt); - void requestRemovePerMeshView(QThread* callingthread, QGLContext* cont); - void requestSetPerMeshViewRenderingData(QThread* callingthread, int meshid, QGLContext* cont, const MLRenderingData& dt); - void requestMeshAttributesUpdated(QThread* callingthread, int meshid, bool connectivitychanged, const MLRenderingData::RendAtts& dt); - /***************************************/ - public slots: - void meshDeallocated(int mmid); - void setRenderingDataPerMeshView(int mmid, QGLContext* viewerid, const MLRenderingData& perviewdata); - void setRenderingDataPerAllMeshViews(int mmid, const MLRenderingData& perviewdata); - void setGLOptions(int mmid, QGLContext* viewid, const MLPerViewGLOptions& opts); - - void addView(QGLContext* viewerid); - void addView(QGLContext* viewerid, MLRenderingData& dt); - - - void removeView(QGLContext* viewerid); - void meshAttributesUpdated(int mmid, bool conntectivitychanged, const MLRenderingData::RendAtts& dt); - void updateGPUMemInfo(); - //void updateRequested(int meshid,MLRenderingData::ATT_NAMES name); - - private slots: - /*slots intended for the plugins living in another thread*/ - void initPerMeshViewRequested(int meshid, QGLContext* cont, const MLRenderingData& dt); - void removePerMeshViewRequested(QGLContext* cont); - void setPerMeshViewRenderingDataRequested(int meshid, QGLContext* cont, const MLRenderingData& dt); - void meshAttributesUpdatedRequested(int meshid, bool connectivitychanged, const MLRenderingData::RendAtts& dt); - /***************************************/ -private: - typedef vcg::QtThreadSafeGLMeshAttributesMultiViewerBOManager PerMeshMultiViewManager; - PerMeshMultiViewManager* meshAttributesMultiViewerManager(int mmid) const; - QGLContext* makeCurrentGLContext(); - void doneCurrentGLContext(QGLContext* oldone = NULL); - - MeshDocument& _md; - typedef QMap MeshIDManMap; - MeshIDManMap _meshboman; - vcg::QtThreadSafeMemoryInfo& _gpumeminfo; - size_t _perbatchtriangles; - size_t _minfacessmoothrendering; - bool _highprecision; - QTimer* _timer; - -signals: - - void currentAllocatedGPUMem(int nv_all, int nv_current, int ati_tex, int ati_vbo); - - ///*signals intended for the plugins living in the same thread*/ - //void initPerMeshViewRequestST(int,QGLContext*,const MLRenderingData&); - //void removePerMeshViewRequestST(QGLContext*); - //void setPerMeshViewRenderingDataRequestST(int,QGLContext*,const MLRenderingData&); - ///***************************************/ - - /*signals intended for the plugins living in another thread*/ - void initPerMeshViewRequestMT(int, QGLContext*, const MLRenderingData&); - void removePerMeshViewRequestMT(QGLContext*); - void setPerMeshViewRenderingDataRequestMT(int, QGLContext*, const MLRenderingData&); - void meshAttributesUpdatedRequestMT(int, bool, const MLRenderingData::RendAtts&); - /***************************************/ -}; - -class MLPluginGLContext : public QGLContext -{ -public: - MLPluginGLContext(const QGLFormat& frmt, QPaintDevice* dvc, MLSceneGLSharedDataContext& shared); - ~MLPluginGLContext(); - - void initPerViewRenderingData(int meshid, MLRenderingData& dt); - void removePerViewRenderindData(); - void setRenderingData(int meshid, MLRenderingData& dt); - void drawMeshModel(int meshid) const; - void meshAttributesUpdated(int meshid, bool conntectivitychanged, const MLRenderingData::RendAtts& dt); - - static void smoothModalitySuggestedRenderingData(MLRenderingData& dt); - static void pointModalitySuggestedRenderingData(MLRenderingData& dt); -private: - MLSceneGLSharedDataContext& _shared; -}; - #endif diff --git a/src/common/mlapplication.cpp b/src/common/mlapplication.cpp index 45aecef8b..ecd1af201 100644 --- a/src/common/mlapplication.cpp +++ b/src/common/mlapplication.cpp @@ -1,10 +1,9 @@ #include "mlapplication.h" #include "mlexception.h" #include - -#ifndef MESHLAB_VERSION -#define MESHLAB_VERSION 2020.09 -#endif +#include +#include +#include "globals.h" #if defined(__clang__) #define ML_COMPILER "Clang" @@ -20,9 +19,6 @@ #define ML_COMPILER_VER std::string() #endif -#define xstr(a) stringify(a) -#define stringify(a) #a - #ifdef NDEBUG bool MeshLabApplication::notify( QObject * rec, QEvent * ev ) { @@ -46,7 +42,7 @@ bool MeshLabApplication::notify( QObject * rec, QEvent * ev ) const QString MeshLabApplication::appVer() { - return QString(xstr(MESHLAB_VERSION)); + return QString::fromStdString(meshlab::meshlabCompleteVersion()); } const QString MeshLabApplication::compilerVersion() @@ -59,6 +55,36 @@ const QString MeshLabApplication::qtVersion() return QString(QT_VERSION_STR); } +const QString MeshLabApplication::extraPluginsLocation() +{ + QDir appDir(QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).first()); + appDir.mkpath(appDir.absolutePath()); + + appDir.mkdir("MeshLabExtraPlugins"); + appDir.cd("MeshLabExtraPlugins"); + + //QString major = appVer().left(4); + //appDir.mkdir(major); + //appDir.cd(major); + + //just for first versions, compatibility of plugins is fixed for same version of meshlab + appDir.mkdir(appVer()); + appDir.cd(appVer()); + + return appDir.absolutePath(); +} + +const QString MeshLabApplication::extraShadersLocation() +{ + QDir appDir(QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).first()); + appDir.mkpath(appDir.absolutePath()); + + appDir.mkdir("MeshLabExtraShaders"); + appDir.cd("MeshLabExtraShaders"); + + return appDir.absolutePath(); +} + std::string MeshLabApplication::versionString(int a, int b, int c) { std::ostringstream ss; diff --git a/src/common/mlapplication.h b/src/common/mlapplication.h index ade1a44be..b97c998b4 100644 --- a/src/common/mlapplication.h +++ b/src/common/mlapplication.h @@ -34,6 +34,9 @@ public: static const QString versionRegisterKeyName() {return tr("version");} static const QString wordSizeKeyName() {return tr("wordSize");} + static const QString extraPluginsLocation(); + static const QString extraShadersLocation(); + private: static std::string versionString(int a, int b, int c); }; diff --git a/src/common/mlexception.h b/src/common/mlexception.h index 0d0ec5a37..c2e972efa 100644 --- a/src/common/mlexception.h +++ b/src/common/mlexception.h @@ -19,61 +19,6 @@ protected: }; -class ParsingException : public MLException -{ -public: - ParsingException(const QString& text) - :MLException(QString("Parsing Error: ") + text){} - - ~ParsingException() throw() {} -}; - -class ValueNotFoundException : public MLException -{ -public: - ValueNotFoundException(const QString& valName) - :MLException(QString("Value Name: ") + valName + QString(" has not been defined in current environment.")){} - - ~ValueNotFoundException() throw() {} -}; - -class NotConstException : public MLException -{ -public: - NotConstException(const QString& exp) - :MLException(QString("Expression: ") + exp + QString(" is not a const expression. Expression contains an assignment operator \"=\".")){} - - ~NotConstException() throw() {} -}; - - -class QueryException : public MLException -{ -public: - QueryException(const QString& syntaxError) - :MLException(QString("Query Error: ") + syntaxError){} - - ~QueryException() throw() {} -}; - -class JavaScriptException : public MLException -{ -public: - JavaScriptException(const QString& syntaxError) - :MLException(QString("JavaScript Error: ") + syntaxError){} - - ~JavaScriptException() throw() {} -}; - -class ExpressionHasNotThisTypeException : public MLException -{ -public: - ExpressionHasNotThisTypeException(const QString& expectedType,const QString& exp) - :MLException(QString("Expression: ") + exp + " cannot be evaluated to a " + expectedType + "'s value."){} - - ~ExpressionHasNotThisTypeException() throw() {} -}; - class InvalidInvariantException : public MLException { public: @@ -82,4 +27,14 @@ public: ~InvalidInvariantException() throw() {} }; + +class InvalidPluginException: public MLException +{ +public: + InvalidPluginException(const QString& error) + :MLException(QString("Invalid Plugin Exception: ") + error){} + + ~InvalidPluginException() throw() {} +}; + #endif diff --git a/src/common/parameters/rich_parameter.cpp b/src/common/parameters/rich_parameter.cpp deleted file mode 100644 index 2dc3f67fd..000000000 --- a/src/common/parameters/rich_parameter.cpp +++ /dev/null @@ -1,768 +0,0 @@ -#include "rich_parameter.h" -#include "../ml_document/mesh_document.h" - -/**** RichParameter Class ****/ - -RichParameter::RichParameter(const RichParameter& rp) : - pName(rp.pName), val(rp.value().clone()), fieldDesc(rp.fieldDesc), tooltip(rp.tooltip) -{ -} - -RichParameter::RichParameter(RichParameter&& rp) : - pName(std::move(rp.pName)), fieldDesc(std::move(rp.fieldDesc)), tooltip(std::move(rp.tooltip)) -{ - val = rp.val; - rp.val = nullptr; -} - -RichParameter::RichParameter( - const QString& nm, - const Value& v, - const QString& desc, - const QString& tltip) : - pName(nm), val(v.clone()), fieldDesc(desc), tooltip(tltip) -{ -} - -RichParameter::~RichParameter() -{ - delete val; -} - -const QString& RichParameter::name() const -{ - return pName; -} - -const Value& RichParameter::value() const -{ - return *val; -} - -const QString& RichParameter::fieldDescription() const -{ - return fieldDesc; -} - -const QString& RichParameter::toolTip() const -{ - return tooltip; -} - -void RichParameter::setValue(const Value& ov) -{ - assert(val->typeName() == ov.typeName()); - delete val; - val = ov.clone(); -} - -QDomElement RichParameter::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = doc.createElement("Param"); - parElem.setAttribute("name", pName); - parElem.setAttribute("type", stringType()); - if (saveDescriptionAndTooltip) { - parElem.setAttribute("description", fieldDesc); - parElem.setAttribute("tooltip",tooltip); - } - val->fillToXMLElement(parElem); - return parElem; -} - -RichParameter& RichParameter::operator=(const RichParameter& rp) -{ - if (&rp != this){ - delete val; - val = rp.value().clone(); - pName = rp.pName; - fieldDesc = rp.fieldDesc; - tooltip = rp.tooltip; - } - return *this; -} - -RichParameter& RichParameter::operator=(RichParameter&& rp) -{ - assert(&rp != this); - val = rp.val; - rp.val = nullptr; - pName = std::move(rp.pName); - fieldDesc = std::move(rp.fieldDesc); - tooltip = std::move(rp.tooltip); - return *this; -} - -/**** RichBool Class ****/ - -RichBool::RichBool( - const QString& nm, - const bool defval, - const QString& desc, - const QString& tltip) : - RichParameter(nm, BoolValue(defval), desc, tltip) -{ -} - -RichBool::~RichBool() -{ -} - -QString RichBool::stringType() const -{ - return "RichBool"; -} - -RichBool* RichBool::clone() const -{ - return new RichBool(*this); -} - -bool RichBool::operator==( const RichParameter& rb ) -{ - return (rb.value().isBool() && (pName == rb.name()) && (value().getBool() == rb.value().getBool())); -} - -/**** RichInt Class ****/ - -RichInt::RichInt( - const QString& nm, - const int defval, - const QString& desc, - const QString& tltip) : - RichParameter(nm, IntValue(defval),desc, tltip) -{ -} - -RichInt::~RichInt() -{ -} - -QString RichInt::stringType() const -{ - return "RichInt"; -} - -RichInt* RichInt::clone() const -{ - return new RichInt(*this); -} - -bool RichInt::operator==( const RichParameter& rb ) -{ - return (rb.value().isInt() &&(pName == rb.name()) && (value().getInt() == rb.value().getInt())); -} - -/**** RichFloat Class ****/ - -RichFloat::RichFloat( - const QString& nm, - const Scalarm defval, - const QString& desc, - const QString& tltip) : - RichParameter(nm, FloatValue(defval),desc, tltip) -{ -} - -RichFloat::~RichFloat() -{ -} - -QString RichFloat::stringType() const -{ - return "RichFloat"; -} - -RichFloat* RichFloat::clone() const -{ - return new RichFloat(*this); -} - -bool RichFloat::operator==( const RichParameter& rb ) -{ - return (rb.value().isFloat() &&(pName == rb.name()) && (value().getFloat() == rb.value().getFloat())); -} - -/**** RichString Class ****/ - -RichString::RichString( - const QString& nm, - const QString& defval, - const QString& desc, - const QString& tltip) : - RichParameter(nm, StringValue(defval),desc,tltip) -{ -} - -RichString::~RichString() -{ -} - -QString RichString::stringType() const -{ - return "RichString"; -} - -RichString* RichString::clone() const -{ - return new RichString(*this); -} - -bool RichString::operator==( const RichParameter& rb ) -{ - return (rb.value().isString() &&(pName == rb.name()) && (value().getString() == rb.value().getString())); -} - -/**** RichMatrix44f Class ****/ - -RichMatrix44f::RichMatrix44f( - const QString& nm, - const Matrix44m& defval, - const QString& desc, - const QString& tltip ) : - RichParameter(nm, Matrix44fValue(defval),desc, tltip) -{ -} - -RichMatrix44f::~RichMatrix44f() -{ -} - -QString RichMatrix44f::stringType() const -{ - return "RichMatrix44f"; -} - -RichMatrix44f* RichMatrix44f::clone() const -{ - return new RichMatrix44f(*this); -} - -bool RichMatrix44f::operator==( const RichParameter& rb ) -{ - return (rb.value().isMatrix44f() &&(pName == rb.name()) && (value().getMatrix44f() == rb.value().getMatrix44f())); -} - -/**** RichPoint3f Class ****/ - -RichPoint3f::RichPoint3f( - const QString& nm, - const Point3m& defval, - const QString& desc, - const QString& tltip ) : - RichParameter(nm, Point3fValue(defval),desc, tltip) -{ -} - -RichPoint3f::~RichPoint3f() -{ -} - -QString RichPoint3f::stringType() const -{ - return "RichPoint3f"; -} - -RichPoint3f* RichPoint3f::clone() const -{ - return new RichPoint3f(*this); -} - -bool RichPoint3f::operator==( const RichParameter& rb ) -{ - return (rb.value().isPoint3f() &&(pName == rb.name()) && (value().getPoint3f() == rb.value().getPoint3f())); -} - -/**** RichShotf Class ****/ - -RichShotf::RichShotf( const QString& nm,const Shotm& defval,const QString& desc,const QString& tltip ) : - RichParameter(nm, ShotfValue(defval),desc, tltip) -{ -} - -RichShotf::~RichShotf() -{ -} - -QString RichShotf::stringType() const -{ - return "RichShotf"; -} - -RichShotf* RichShotf::clone() const -{ - return new RichShotf(*this); -} - -bool RichShotf::operator==( const RichParameter& rb ) -{ - return (rb.value().isShotf() &&(pName == rb.name()) ); - // TODO REAL TEST OF EQUALITY // && (value().getShotf() == rb.value().getShotf())); -} - -/**** RichColor Class ****/ - -RichColor::RichColor( - const QString& nm, - const QColor& defval, - const QString& desc, - const QString& tltip ) : - RichParameter(nm, ColorValue(defval),desc, tltip) -{ -} - -RichColor::~RichColor() -{ -} - -QString RichColor::stringType() const -{ - return "RichColor"; -} - -RichColor* RichColor::clone() const -{ - return new RichColor(*this); -} - -bool RichColor::operator==( const RichParameter& rb ) -{ - return (rb.value().isColor() &&(pName == rb.name()) && (value().getColor() == rb.value().getColor())); -} - -/**** RichAbsPerc Class ****/ - -RichAbsPerc::RichAbsPerc( - const QString& nm, - const Scalarm defval, - const Scalarm minval, - const Scalarm maxval, - const QString& desc, - const QString& tltip) : - RichParameter(nm, AbsPercValue(defval), desc, tltip), min(minval), max(maxval) -{ -} - -RichAbsPerc::~RichAbsPerc() -{ -} - -QString RichAbsPerc::stringType() const -{ - return "RichAbsPerc"; -} - -QDomElement RichAbsPerc::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); - parElem.setAttribute("min",QString::number(min)); - parElem.setAttribute("max",QString::number(max)); - return parElem; -} - -RichAbsPerc* RichAbsPerc::clone() const -{ - return new RichAbsPerc(*this); -} - -bool RichAbsPerc::operator==( const RichParameter& rb ) -{ - return (rb.value().isAbsPerc() &&(pName == rb.name()) && (value().getAbsPerc() == rb.value().getAbsPerc())); -} - -/**** RichEnum Class ****/ - -RichEnum::RichEnum( - const QString& nm, - const int defval, - const QStringList& values, - const QString& desc, - const QString& tltip) : - RichParameter(nm, EnumValue(defval),desc, tltip), enumvalues(values) -{ -} - -RichEnum::~RichEnum() -{ -} - -QString RichEnum::stringType() const -{ - return "RichEnum"; -} - -QDomElement RichEnum::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); - parElem.setAttribute("enum_cardinality", enumvalues.size()); - for(int ii = 0; ii < enumvalues.size(); ++ii) - parElem.setAttribute(QString("enum_val")+QString::number(ii), enumvalues.at(ii)); - return parElem; -} - -RichEnum* RichEnum::clone() const -{ - return new RichEnum(*this); -} - -bool RichEnum::operator==( const RichParameter& rb ) -{ - return (rb.value().isEnum() &&(pName == rb.name()) && (value().getEnum() == rb.value().getEnum())); -} - -/**** RichDynamicFloat Class ****/ - -RichDynamicFloat::RichDynamicFloat( - const QString& nm, - const Scalarm defval, - const Scalarm minval, - const Scalarm maxval, - const QString& desc, - const QString& tltip ) : - RichParameter(nm, DynamicFloatValue(defval),desc, tltip), min(minval), max(maxval) -{ -} - -RichDynamicFloat::~RichDynamicFloat() -{ -} - -QString RichDynamicFloat::stringType() const -{ - return "RichDynamicFloat"; -} - -QDomElement RichDynamicFloat::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); - parElem.setAttribute("min",QString::number(min)); - parElem.setAttribute("max",QString::number(max)); - return parElem; -} - -RichDynamicFloat* RichDynamicFloat::clone() const -{ - return new RichDynamicFloat(*this); -} - -bool RichDynamicFloat::operator==( const RichParameter& rb ) -{ - return (rb.value().isDynamicFloat() &&(pName == rb.name()) && (value().getDynamicFloat() == rb.value().getDynamicFloat())); -} - -/**** RichOpenFile Class ****/ - -RichOpenFile::RichOpenFile( - const QString& nm, - const QString& directorydefval, - const QStringList& exts, - const QString& desc, - const QString& tltip) : - RichParameter(nm, FileValue(directorydefval), desc, tltip), exts(exts) -{ -} - -RichOpenFile::~RichOpenFile() -{ -} - -QString RichOpenFile::stringType() const -{ - return "RichOpenFile"; -} - -QDomElement RichOpenFile::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); - parElem.setAttribute("exts_cardinality", exts.size()); - for(int ii = 0; ii < exts.size(); ++ii) - parElem.setAttribute(QString("ext_val")+QString::number(ii), exts[ii]); - return parElem; -} - -RichOpenFile* RichOpenFile::clone() const -{ - return new RichOpenFile(*this); -} - -bool RichOpenFile::operator==( const RichParameter& rb ) -{ - return (rb.value().isFileName() &&(pName == rb.name()) && (value().getFileName() == rb.value().getFileName())); -} - -/**** RichSaveFile Class ****/ - -RichSaveFile::RichSaveFile( - const QString& nm, - const QString& filedefval, - const QString& ext, - const QString& desc, - const QString& tltip) : - RichParameter(nm, FileValue(filedefval), desc, tltip), ext(ext) -{ -} - -RichSaveFile::~RichSaveFile() -{ -} - -QString RichSaveFile::stringType() const -{ - return "RichSaveFile"; -} - -QDomElement RichSaveFile::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); - parElem.setAttribute("ext", ext); - return parElem; -} - -RichSaveFile* RichSaveFile::clone() const -{ - return new RichSaveFile(*this); -} - -bool RichSaveFile::operator==( const RichParameter& rb ) -{ - return (rb.value().isFileName() &&(pName == rb.name()) && (value().getFileName() == rb.value().getFileName())); -} - -/**** RichMesh Class ****/ - -RichMesh::RichMesh( - const QString& nm, - MeshModel* defval, - MeshDocument* doc, - const QString& desc, - const QString& tltip ): - RichParameter(nm, MeshValue(defval), desc, tltip), meshdoc(doc) -{ - meshindex = -1; - if (meshdoc != nullptr) - meshindex = meshdoc->meshList.indexOf(defval); - assert((meshindex != -1) || (meshdoc == nullptr)); -} - -RichMesh::RichMesh( - const QString& nm, - int meshind, - MeshDocument* doc, - const QString& desc, - const QString& tltip ): - RichParameter(nm,MeshValue(doc, meshind), desc, tltip), meshdoc(doc) -{ - assert(meshind < meshdoc->size() && meshind >= 0); - meshindex = meshind; - if (meshdoc != nullptr) - val = new MeshValue(meshdoc->meshList.at(meshindex)); - else - val = nullptr; -} - -RichMesh::RichMesh(const QString& nm, int meshind, const QString& desc, const QString& tltip): - RichParameter(nm, MeshValue(nullptr), desc, tltip) -{ - meshdoc = nullptr; - meshindex = meshind; -} - -RichMesh::~RichMesh() -{ -} - -QString RichMesh::stringType() const -{ - return "RichMesh"; -} - -QDomElement RichMesh::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); - parElem.setAttribute("value", QString::number(meshindex)); - return parElem; -} - -RichMesh* RichMesh::clone() const -{ - return new RichMesh(*this); -} - -bool RichMesh::operator==( const RichParameter& rb ) -{ - return (rb.value().isMesh() &&(pName == rb.name()) && (value().getMesh() == rb.value().getMesh())); -} - -/**** RichParameterAdapter Class ****/ - -bool RichParameterAdapter::create( const QDomElement& np,RichParameter** par ) -{ - QString name=np.attribute("name"); - QString type=np.attribute("type"); - QString desc=np.attribute("description"); - QString tooltip=np.attribute("tooltip"); - - // qDebug(" Reading Param with name %s : %s", qUtf8Printable(name), qUtf8Printable(type)); - - bool corrconv = false; - if(type=="RichBool") { - QString val = np.attribute("value").toLower(); - if ((val != QString("true")) && (val != QString("false"))) - return false; - *par = new RichBool(name,np.attribute("value")!=QString("false"),desc,tooltip); - return true; - } - - if(type=="RichInt") { - int val = np.attribute("value").toInt(&corrconv); - if (!corrconv) - return false; - *par = new RichInt(name,val,desc,tooltip); - return true; - } - - if(type=="RichFloat") { - float val = np.attribute("value").toFloat(&corrconv); - if (!corrconv) - return false; - *par = new RichFloat(name,val,desc,tooltip); - return true; - } - - if(type=="RichString") { - *par = new RichString(name,np.attribute("value"),desc,tooltip); - return true; - } - - if(type=="RichAbsPerc") { - float val = np.attribute("value").toFloat(&corrconv); - if ((!corrconv) && (val >= 0.0f) && (val <= 100.0f)) - return false; - float min = np.attribute("min").toFloat(&corrconv); - if (!corrconv) - return false; - float max = np.attribute("max").toFloat(&corrconv); - if (!corrconv) - return false; - *par = new RichAbsPerc(name,val,min,max,desc,tooltip); - return true; - } - - if(type=="RichColor") { - unsigned int r = np.attribute("r").toUInt(&corrconv); - if ((!corrconv) && (r <= 255)) - return false; - unsigned int g = np.attribute("g").toUInt(&corrconv); - if ((!corrconv) && (g <= 255)) - return false; - unsigned int b = np.attribute("b").toUInt(&corrconv); - if ((!corrconv) && (b <= 255)) - return false; - unsigned int a = np.attribute("a").toUInt(&corrconv); - if ((!corrconv) && (a <= 255)) - return false; - QColor col(r,g,b,a); - *par= new RichColor(name,col,desc,tooltip); - return true; - } - - if(type=="RichMatrix44f") { - Matrix44m mm; - for(int i=0;i<16;++i) - { - Scalarm val = np.attribute(QString("val")+QString::number(i)).toFloat(&corrconv); - if (!corrconv) - return false; - mm.V()[i]=val; - } - *par = new RichMatrix44f(name,mm,desc,tooltip); - return true; - } - - if(type=="RichEnum") { - QStringList list; - int enum_card = np.attribute(QString("enum_cardinality")).toUInt(&corrconv); - if (!corrconv) - return false; - - for(int i=0;i=0) && (val < enum_card)) - return false; - *par = new RichEnum(name,val,list,desc,tooltip); - return true; - } - - if(type == "RichMesh") { - int val = np.attribute("value").toInt(&corrconv); - - if (!corrconv) - return false; - - *par = new RichMesh(name, val,desc,tooltip); - return true; - } - - if(type == "RichDynamicFloat") { - float min = np.attribute("min").toFloat(&corrconv); - if (!corrconv) - return false; - float max = np.attribute("max").toFloat(&corrconv); - if (!corrconv) - return false; - - float val = np.attribute("value").toFloat(&corrconv); - if ((!corrconv) && (val >= min) && (val <= max)) - return false; - - *par = new RichDynamicFloat(name, val, min, max, desc, tooltip); - return true; - } - - if(type == "RichOpenFile") { - QStringList list; - int exts_card = np.attribute(QString("exts_cardinality")).toUInt(&corrconv); - if (!corrconv) - return false; - - for(int i=0;i - -class MeshDocument; - -/** - * @brief The RichParameter class - * - * The RichParameter class is a representation of a MeshLab parameter that contains - * a value of a certain type (see the Value class and its specializations) plus - * some other decorators, like a parameter description and a tooltip. - * - * All these decorators allow MeshLab to automatically design GUI interfaces for - * every RichParameter spcialization. - * - * Every specialization must implement the following member functions: - * - QString stringType() const : returns a string representation of the type of the RichParameter - * - RichParameter* clone() const : returns a *new* object which is a clone of the RichParameter - * - bool operator==(const RichParameter& rp): returns true if the two RichParameter are the same - */ -class RichParameter -{ -public: - RichParameter(const RichParameter& rp); - RichParameter(RichParameter&& rp); - RichParameter(const QString& nm, const Value& v, const QString& desc = QString(), const QString& tltip = QString()); - virtual ~RichParameter(); - - const QString& name() const; - const Value& value() const; - const QString& fieldDescription() const; - const QString& toolTip() const; - - virtual QString stringType() const = 0; - - void setValue(const Value& ov); - - virtual QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - virtual RichParameter* clone() const = 0; - RichParameter& operator=(const RichParameter& rp); - RichParameter& operator=(RichParameter&& rp); - virtual bool operator==(const RichParameter& rp) = 0; - -protected: - QString pName; - Value* val; - QString fieldDesc; - QString tooltip; -}; - - -class RichBool : public RichParameter -{ -public: - RichBool(const QString& nm, const bool defval, const QString& desc = QString(), const QString& tltip = QString()); - ~RichBool(); - - QString stringType() const; - - RichBool* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichInt : public RichParameter -{ -public: - RichInt(const QString& nm, const int defval, const QString& desc = QString(), const QString& tltip = QString()); - ~RichInt(); - - QString stringType() const; - - RichInt* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichFloat : public RichParameter -{ -public: - RichFloat(const QString& nm, const Scalarm defval, const QString& desc = QString(), const QString& tltip = QString()); - ~RichFloat(); - - QString stringType() const; - - RichFloat* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichString : public RichParameter -{ -public: - RichString(const QString& nm, const QString& defval, const QString& desc = QString(), const QString& tltip = QString()); - ~RichString(); - - QString stringType() const; - - RichString* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichMatrix44f : public RichParameter -{ -public: - RichMatrix44f(const QString& nm, const Matrix44m& defval, const QString& desc = QString(), const QString& tltip = QString()); - ~RichMatrix44f(); - - QString stringType() const; - - RichMatrix44f* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichPoint3f : public RichParameter -{ -public: - RichPoint3f(const QString& nm, const Point3m& defval, const QString& desc = QString(), const QString& tltip = QString()); - ~RichPoint3f(); - - QString stringType() const; - - RichPoint3f* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichShotf : public RichParameter -{ -public: - RichShotf(const QString& nm, const Shotm& defval, const QString& desc = QString(), const QString& tltip = QString()); - ~RichShotf(); - - QString stringType() const; - - RichShotf* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichColor : public RichParameter -{ -public: - RichColor(const QString& nm, const QColor& defval, const QString& desc = QString(), const QString& tltip = QString()); - ~RichColor(); - - QString stringType() const; - - RichColor* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichAbsPerc : public RichParameter -{ -public: - RichAbsPerc(const QString& nm, const Scalarm defval, const Scalarm minval, const Scalarm maxval, const QString& desc = QString(), const QString& tltip = QString()); - ~RichAbsPerc(); - - QString stringType() const; - QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - RichAbsPerc* clone() const; - bool operator==(const RichParameter& rb); - Scalarm min; - Scalarm max; -}; - -class RichEnum : public RichParameter -{ -public: - RichEnum(const QString& nm, const int defval, const QStringList& values, const QString& desc = QString(), const QString& tltip = QString()); - ~RichEnum(); - - QString stringType() const; - QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - RichEnum* clone() const; - bool operator==(const RichParameter& rb); - QStringList enumvalues; -}; - -class RichDynamicFloat : public RichParameter -{ -public: - RichDynamicFloat(const QString& nm, const Scalarm defval, const Scalarm minval, const Scalarm maxval, const QString& desc = QString(), const QString& tltip = QString()); - ~RichDynamicFloat(); - - QString stringType() const; - QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - RichDynamicFloat* clone() const; - bool operator==(const RichParameter& rb); - Scalarm min; - Scalarm max; -}; - -class RichOpenFile : public RichParameter -{ -public: - RichOpenFile(const QString& nm, const QString& directorydefval, const QStringList& exts, const QString& desc = QString(), const QString& tltip = QString()); - ~RichOpenFile(); - - QString stringType() const; - QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - RichOpenFile* clone() const; - bool operator==(const RichParameter& rb); - QStringList exts; -}; - -class RichSaveFile : public RichParameter -{ -public: - RichSaveFile(const QString& nm, const QString& filedefval, const QString& ext, const QString& desc = QString(), const QString& tltip = QString()); - ~RichSaveFile(); - - QString stringType() const; - QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - RichSaveFile* clone() const; - bool operator==(const RichParameter& rb); - QString ext; -}; - -class RichMesh : public RichParameter -{ -public: - RichMesh(const QString& nm, MeshModel* defval, MeshDocument* doc, const QString& desc = QString(), const QString& tltip = QString()); - RichMesh(const QString& nm, int meshindex, MeshDocument* doc, const QString& desc = QString(), const QString& tltip = QString()); - //WARNING: IT SHOULD BE USED ONLY BY MESHLABSERVER!!!!!!! - RichMesh(const QString& nm, int meshind, const QString& desc = QString(), const QString& tltip = QString()); - ~RichMesh(); - - QString stringType() const; - QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - RichMesh* clone() const; - bool operator==(const RichParameter& rb); - MeshDocument* meshdoc; - int meshindex; -}; - -class RichParameterAdapter -{ -public: - static bool create(const QDomElement& np, RichParameter** par); -}; - -#endif // MESHLAB_RICH_PARAMETER_H diff --git a/src/common/parameters/rich_parameter/rich_bool.cpp b/src/common/parameters/rich_parameter/rich_bool.cpp new file mode 100644 index 000000000..e68135e7c --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_bool.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_bool.h" + +RichBool::RichBool( + const QString& nm, + const bool defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, BoolValue(defval), desc, tltip, hidden, category) +{ +} + +RichBool::~RichBool() +{ +} + +QString RichBool::stringType() const +{ + return "RichBool"; +} + +RichBool* RichBool::clone() const +{ + return new RichBool(*this); +} + +bool RichBool::operator==( const RichParameter& rb ) +{ + return (rb.value().isBool() && (pName == rb.name()) && (value().getBool() == rb.value().getBool())); +} diff --git a/src/common/parameters/rich_parameter/rich_bool.h b/src/common/parameters/rich_parameter/rich_bool.h new file mode 100644 index 000000000..ea51f70db --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_bool.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_BOOL_H +#define MESHLAB_RICH_BOOL_H + +#include "rich_parameter.h" + +class RichBool : public RichParameter +{ +public: + RichBool( + const QString& nm, + const bool defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichBool(); + + QString stringType() const; + + RichBool* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_BOOL_H diff --git a/src/common/parameters/rich_parameter/rich_color.cpp b/src/common/parameters/rich_parameter/rich_color.cpp new file mode 100644 index 000000000..263ad923f --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_color.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_color.h" + +RichColor::RichColor( + const QString& nm, + const QColor& defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, ColorValue(defval),desc, tltip, hidden, category) +{ +} + +RichColor::~RichColor() +{ +} + +QString RichColor::stringType() const +{ + return "RichColor"; +} + +RichColor* RichColor::clone() const +{ + return new RichColor(*this); +} + +bool RichColor::operator==( const RichParameter& rb ) +{ + return (rb.value().isColor() &&(pName == rb.name()) && (value().getColor() == rb.value().getColor())); +} diff --git a/src/common/parameters/rich_parameter/rich_color.h b/src/common/parameters/rich_parameter/rich_color.h new file mode 100644 index 000000000..2c247e806 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_color.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_COLOR_H +#define MESHLAB_RICH_COLOR_H + +#include "rich_parameter.h" + +class RichColor : public RichParameter +{ +public: + RichColor( + const QString& nm, + const QColor& defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichColor(); + + QString stringType() const; + + RichColor* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_COLOR_H diff --git a/src/common/parameters/rich_parameter/rich_direction.cpp b/src/common/parameters/rich_parameter/rich_direction.cpp new file mode 100644 index 000000000..0fc89ee6e --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_direction.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_direction.h" + +RichDirection::RichDirection( + const QString& nm, + const Point3m& defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, Point3Value(defval), desc, tltip, hidden, category) +{ +} + +RichDirection::~RichDirection() +{ +} + +QString RichDirection::stringType() const +{ + return "RichDirection"; +} + +RichDirection* RichDirection::clone() const +{ + return new RichDirection(*this); +} + +bool RichDirection::operator==(const RichParameter& rb) +{ + return (rb.value().isPoint3() &&(pName == rb.name()) && (value().getPoint3() == rb.value().getPoint3())); +} diff --git a/src/common/parameters/rich_parameter/rich_direction.h b/src/common/parameters/rich_parameter/rich_direction.h new file mode 100644 index 000000000..40e0daa2a --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_direction.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_DIRECTION_H +#define MESHLAB_RICH_DIRECTION_H + +#include "rich_parameter.h" + +class RichDirection : public RichParameter +{ +public: + RichDirection( + const QString& nm, + const Point3m& defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichDirection(); + + QString stringType() const; + + RichDirection* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_DIRECTION_H diff --git a/src/common/parameters/rich_parameter/rich_dynamic_float.cpp b/src/common/parameters/rich_parameter/rich_dynamic_float.cpp new file mode 100644 index 000000000..44c1ccf6c --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_dynamic_float.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_dynamic_float.h" + +RichDynamicFloat::RichDynamicFloat( + const QString& nm, + const Scalarm defval, + const Scalarm minval, + const Scalarm maxval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, FloatValue(defval),desc, tltip, hidden, category), min(minval), max(maxval) +{ +} + +RichDynamicFloat::~RichDynamicFloat() +{ +} + +QString RichDynamicFloat::stringType() const +{ + return "RichDynamicFloat"; +} + +QDomElement RichDynamicFloat::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const +{ + QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); + parElem.setAttribute("min",QString::number(min)); + parElem.setAttribute("max",QString::number(max)); + return parElem; +} + +RichDynamicFloat* RichDynamicFloat::clone() const +{ + return new RichDynamicFloat(*this); +} + +bool RichDynamicFloat::operator==( const RichParameter& rb ) +{ + return (rb.isOfType() &&(pName == rb.name()) && (value().getFloat() == rb.value().getFloat())); +} diff --git a/src/common/parameters/rich_parameter/rich_dynamic_float.h b/src/common/parameters/rich_parameter/rich_dynamic_float.h new file mode 100644 index 000000000..521076100 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_dynamic_float.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_DYNAMIC_FLOAT_H +#define MESHLAB_RICH_DYNAMIC_FLOAT_H + +#include "rich_parameter.h" + +class RichDynamicFloat : public RichParameter +{ +public: + RichDynamicFloat( + const QString& nm, + const Scalarm defval, + const Scalarm minval, + const Scalarm maxval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichDynamicFloat(); + + QString stringType() const; + QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; + + RichDynamicFloat* clone() const; + bool operator==(const RichParameter& rb); + Scalarm min; + Scalarm max; +}; + +#endif // MESHLAB_RICH_DYNAMIC_FLOAT_H diff --git a/src/common/parameters/rich_parameter/rich_enum.cpp b/src/common/parameters/rich_parameter/rich_enum.cpp new file mode 100644 index 000000000..48a14f632 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_enum.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_enum.h" + +RichEnum::RichEnum( + const QString& nm, + const int defval, + const QStringList& values, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, IntValue(defval),desc, tltip, hidden, category), enumvalues(values) +{ +} + +RichEnum::~RichEnum() +{ +} + +QString RichEnum::stringType() const +{ + return "RichEnum"; +} + +QDomElement RichEnum::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const +{ + QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); + parElem.setAttribute("enum_cardinality", enumvalues.size()); + for(int ii = 0; ii < enumvalues.size(); ++ii) + parElem.setAttribute(QString("enum_val")+QString::number(ii), enumvalues.at(ii)); + return parElem; +} + +RichEnum* RichEnum::clone() const +{ + return new RichEnum(*this); +} + +bool RichEnum::operator==( const RichParameter& rb ) +{ + return (rb.isOfType() &&(pName == rb.name()) && (value().getInt() == rb.value().getInt())); +} + diff --git a/src/common/parameters/rich_parameter/rich_enum.h b/src/common/parameters/rich_parameter/rich_enum.h new file mode 100644 index 000000000..b9090a463 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_enum.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_ENUM_H +#define MESHLAB_RICH_ENUM_H + +#include "rich_parameter.h" + +class RichEnum : public RichParameter +{ +public: + RichEnum( + const QString& nm, + const int defval, + const QStringList& values, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichEnum(); + + QString stringType() const; + QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; + + RichEnum* clone() const; + bool operator==(const RichParameter& rb); + QStringList enumvalues; +}; + +#endif // MESHLAB_RICH_ENUM_H diff --git a/src/common/parameters/rich_parameter/rich_file_open.cpp b/src/common/parameters/rich_parameter/rich_file_open.cpp new file mode 100644 index 000000000..a811f190e --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_file_open.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_file_open.h" + +RichFileOpen::RichFileOpen( + const QString& nm, + const QString& directorydefval, + const QStringList& exts, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, StringValue(directorydefval), desc, tltip, hidden, category), exts(exts) +{ +} + +RichFileOpen::~RichFileOpen() +{ +} + +QString RichFileOpen::stringType() const +{ + return "RichOpenFile"; +} + +QDomElement RichFileOpen::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const +{ + QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); + parElem.setAttribute("exts_cardinality", exts.size()); + for(int ii = 0; ii < exts.size(); ++ii) + parElem.setAttribute(QString("ext_val")+QString::number(ii), exts[ii]); + return parElem; +} + +RichFileOpen* RichFileOpen::clone() const +{ + return new RichFileOpen(*this); +} + +bool RichFileOpen::operator==( const RichParameter& rb ) +{ + return (rb.isOfType() &&(pName == rb.name()) && (value().getString() == rb.value().getString())); +} diff --git a/src/common/parameters/rich_parameter/rich_file_open.h b/src/common/parameters/rich_parameter/rich_file_open.h new file mode 100644 index 000000000..e65535542 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_file_open.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_FILE_OPEN_H +#define MESHLAB_RICH_FILE_OPEN_H + +#include "rich_parameter.h" + +class RichFileOpen : public RichParameter +{ +public: + RichFileOpen( + const QString& nm, + const QString& directorydefval, + const QStringList& exts, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichFileOpen(); + + QString stringType() const; + QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; + + RichFileOpen* clone() const; + bool operator==(const RichParameter& rb); + QStringList exts; +}; + +#endif // MESHLAB_RICH_FILE_OPEN_H diff --git a/src/common/parameters/rich_parameter/rich_file_save.cpp b/src/common/parameters/rich_parameter/rich_file_save.cpp new file mode 100644 index 000000000..c5fd62854 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_file_save.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_file_save.h" + +RichFileSave::RichFileSave( + const QString& nm, + const QString& filedefval, + const QString& ext, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, StringValue(filedefval), desc, tltip, hidden, category), ext(ext) +{ +} + +RichFileSave::~RichFileSave() +{ +} + +QString RichFileSave::stringType() const +{ + return "RichSaveFile"; +} + +QDomElement RichFileSave::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const +{ + QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); + parElem.setAttribute("ext", ext); + return parElem; +} + +RichFileSave* RichFileSave::clone() const +{ + return new RichFileSave(*this); +} + +bool RichFileSave::operator==( const RichParameter& rb ) +{ + return (rb.isOfType() &&(pName == rb.name()) && (value().getString() == rb.value().getString())); +} diff --git a/src/common/parameters/rich_parameter/rich_file_save.h b/src/common/parameters/rich_parameter/rich_file_save.h new file mode 100644 index 000000000..09faf757c --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_file_save.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_FILE_SAVE_H +#define MESHLAB_RICH_FILE_SAVE_H + +#include "rich_parameter.h" + +class RichFileSave : public RichParameter +{ +public: + RichFileSave( + const QString& nm, + const QString& filedefval, + const QString& ext, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichFileSave(); + + QString stringType() const; + QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; + + RichFileSave* clone() const; + bool operator==(const RichParameter& rb); + QString ext; +}; + +#endif // MESHLAB_RICH_FILE_SAVE_H diff --git a/src/common/parameters/rich_parameter/rich_float.cpp b/src/common/parameters/rich_parameter/rich_float.cpp new file mode 100644 index 000000000..14dedb117 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_float.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_float.h" + +RichFloat::RichFloat( + const QString& nm, + const Scalarm defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, FloatValue(defval),desc, tltip, hidden, category) +{ +} + +RichFloat::~RichFloat() +{ +} + +QString RichFloat::stringType() const +{ + return "RichFloat"; +} + +RichFloat* RichFloat::clone() const +{ + return new RichFloat(*this); +} + +bool RichFloat::operator==( const RichParameter& rb ) +{ + return (rb.value().isFloat() &&(pName == rb.name()) && (value().getFloat() == rb.value().getFloat())); +} + diff --git a/src/common/parameters/rich_parameter/rich_float.h b/src/common/parameters/rich_parameter/rich_float.h new file mode 100644 index 000000000..0ae4eecdb --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_float.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_FLOAT_H +#define MESHLAB_RICH_FLOAT_H + +#include "rich_parameter.h" + +class RichFloat : public RichParameter +{ +public: + RichFloat( + const QString& nm, + const Scalarm defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichFloat(); + + QString stringType() const; + + RichFloat* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_FLOAT_H diff --git a/src/common/parameters/rich_parameter/rich_int.cpp b/src/common/parameters/rich_parameter/rich_int.cpp new file mode 100644 index 000000000..6b5b4aa40 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_int.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_int.h" + +RichInt::RichInt( + const QString& nm, + const int defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, IntValue(defval),desc, tltip, hidden, category) +{ +} + +RichInt::~RichInt() +{ +} + +QString RichInt::stringType() const +{ + return "RichInt"; +} + +RichInt* RichInt::clone() const +{ + return new RichInt(*this); +} + +bool RichInt::operator==( const RichParameter& rb ) +{ + return (rb.value().isInt() &&(pName == rb.name()) && (value().getInt() == rb.value().getInt())); +} + diff --git a/src/common/parameters/rich_parameter/rich_int.h b/src/common/parameters/rich_parameter/rich_int.h new file mode 100644 index 000000000..ed5f3320a --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_int.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_INT_H +#define MESHLAB_RICH_INT_H + +#include "rich_parameter.h" + +class RichInt : public RichParameter +{ +public: + RichInt( + const QString& nm, + const int defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichInt(); + + QString stringType() const; + + RichInt* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_INT_H diff --git a/src/common/parameters/rich_parameter/rich_matrix44.cpp b/src/common/parameters/rich_parameter/rich_matrix44.cpp new file mode 100644 index 000000000..3b324d0a2 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_matrix44.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_matrix44.h" + +RichMatrix44::RichMatrix44( + const QString& nm, + const Matrix44m& defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, Matrix44Value(defval),desc, tltip, hidden, category) +{ +} + +RichMatrix44::~RichMatrix44() +{ +} + +QString RichMatrix44::stringType() const +{ + return "RichMatrix44f"; +} + +RichMatrix44* RichMatrix44::clone() const +{ + return new RichMatrix44(*this); +} + +bool RichMatrix44::operator==( const RichParameter& rb ) +{ + return (rb.value().isMatrix44() &&(pName == rb.name()) && (value().getMatrix44() == rb.value().getMatrix44())); +} + diff --git a/src/common/parameters/rich_parameter/rich_matrix44.h b/src/common/parameters/rich_parameter/rich_matrix44.h new file mode 100644 index 000000000..997de4be3 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_matrix44.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_MATRIX44_H +#define MESHLAB_RICH_MATRIX44_H + +#include "rich_parameter.h" + +class RichMatrix44 : public RichParameter +{ +public: + RichMatrix44( + const QString& nm, + const Matrix44m& defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichMatrix44(); + + QString stringType() const; + + RichMatrix44* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_MATRIX44_H diff --git a/src/common/parameters/rich_parameter/rich_mesh.cpp b/src/common/parameters/rich_parameter/rich_mesh.cpp new file mode 100644 index 000000000..6d2c9e604 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_mesh.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_mesh.h" + +RichMesh::RichMesh( + const QString& nm, + unsigned int meshind, + const MeshDocument* doc, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category): + RichParameter(nm,IntValue(meshind), desc, tltip, hidden, category), meshdoc(doc) +{ +} + +RichMesh::~RichMesh() +{ +} + +QString RichMesh::stringType() const +{ + return "RichMesh"; +} + +RichMesh* RichMesh::clone() const +{ + return new RichMesh(*this); +} + +bool RichMesh::operator==( const RichParameter& rb ) +{ + return (rb.isOfType() &&(pName == rb.name()) && (value().getInt() == rb.value().getInt())); +} + diff --git a/src/common/parameters/rich_parameter/rich_mesh.h b/src/common/parameters/rich_parameter/rich_mesh.h new file mode 100644 index 000000000..48b1f106b --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_mesh.h @@ -0,0 +1,49 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_MESH_H +#define MESHLAB_RICH_MESH_H + +#include "rich_parameter.h" + +class RichMesh : public RichParameter +{ +public: + RichMesh( + const QString& nm, + unsigned int meshindex, + const MeshDocument* doc, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichMesh(); + + QString stringType() const; + + RichMesh* clone() const; + bool operator==(const RichParameter& rb); + const MeshDocument* meshdoc; +}; + +#endif // MESHLAB_RICH_MESH_H diff --git a/src/common/parameters/rich_parameter/rich_parameter.cpp b/src/common/parameters/rich_parameter/rich_parameter.cpp new file mode 100644 index 000000000..3010c5909 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_parameter.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_parameter.h" + +#include +#include + +RichParameter::RichParameter(const RichParameter& rp) : + pName(rp.pName), + val(rp.value().clone()), + fieldDesc(rp.fieldDesc), + tooltip(rp.tooltip), + advanced(rp.advanced), + defaultValue(rp.defaultValue), + pCategory(rp.pCategory) +{ +} + +RichParameter::RichParameter(RichParameter&& rp) +{ + swap(rp); +} + +RichParameter::RichParameter( + const QString& nm, + const Value& v, + const QString& desc, + const QString& tltip, + bool isAdvanced, + const QString& category) : + pName(nm), + val(v.clone()), + fieldDesc(desc), + tooltip(tltip), + advanced(isAdvanced), + defaultValue(true), + pCategory(category) +{ +} + +RichParameter::~RichParameter() +{ + delete val; +} + +const QString& RichParameter::name() const +{ + return pName; +} + +const Value& RichParameter::value() const +{ + return *val; +} + +const QString& RichParameter::fieldDescription() const +{ + return fieldDesc; +} + +const QString& RichParameter::toolTip() const +{ + return tooltip; +} + +bool RichParameter::isAdvanced() const +{ + return advanced; +} + +bool RichParameter::isValueDefault() const +{ + return defaultValue; +} + +const QString& RichParameter::category() const +{ + return pCategory; +} + +void RichParameter::setName(const QString& newName) +{ + pName = newName; +} + +void RichParameter::setValue(const Value& ov, bool isDefault) +{ + assert(val->typeName() == ov.typeName()); + delete val; + val = ov.clone(); + defaultValue = isDefault; +} + +void RichParameter::setDefaultValue(bool isDefault) +{ + defaultValue = isDefault; +} + +QDomElement RichParameter::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const +{ + QDomElement parElem = doc.createElement("Param"); + parElem.setAttribute("name", pName); + parElem.setAttribute("type", stringType()); + if (saveDescriptionAndTooltip) { + parElem.setAttribute("description", fieldDesc); + parElem.setAttribute("tooltip",tooltip); + } + val->fillToXMLElement(parElem); + return parElem; +} + +/** + * @brief returns the name of the parameter used in python (for pymeshlab) + */ +QString RichParameter::pythonName() const +{ + return pymeshlab::computePythonName(pName); +} + +/** + * @brief returns the type if the parameter (as a string) used in python + * (for pymeshlab) + */ +QString RichParameter::pythonType() const +{ + return pymeshlab::computePythonTypeString(*this); +} + +RichParameter& RichParameter::operator=(const RichParameter& rp) +{ + if (&rp != this){ + delete val; + val = rp.value().clone(); + pName = rp.pName; + fieldDesc = rp.fieldDesc; + tooltip = rp.tooltip; + advanced = rp.advanced; + defaultValue = rp.defaultValue; + pCategory = rp.pCategory; + } + return *this; +} + +RichParameter& RichParameter::operator=(RichParameter&& rp) +{ + ::swap(*this, rp); + return *this; +} + +void RichParameter::swap(RichParameter &rp) +{ + ::swap(*this, rp); +} + +void swap(RichParameter &rp1, RichParameter &rp2) +{ + using std::swap; + swap(rp1.pName, rp2.pName); + swap(rp1.val, rp2.val); + swap(rp1.fieldDesc, rp2.fieldDesc); + swap(rp1.tooltip, rp2.tooltip); + swap(rp1.advanced, rp2.advanced); + swap(rp1.defaultValue, rp2.defaultValue); + swap(rp1.pCategory, rp2.pCategory); +} diff --git a/src/common/parameters/rich_parameter/rich_parameter.h b/src/common/parameters/rich_parameter/rich_parameter.h new file mode 100644 index 000000000..6621495c9 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_parameter.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_PARAMETER_H +#define MESHLAB_RICH_PARAMETER_H + +#include + +#include + +class MeshDocument; + +/** + * @brief The RichParameter class + * + * The RichParameter class is a representation of a MeshLab parameter that contains + * a value of a certain type (see the Value class and its specializations) plus + * some other decorators, like a parameter description and a tooltip. + * + * All these decorators allow MeshLab to automatically design GUI interfaces for + * every RichParameter spcialization. + * + * Every specialization must implement the following member functions: + * - QString stringType() const : returns a string representation of the type of the RichParameter + * - RichParameter* clone() const : returns a *new* object which is a clone of the RichParameter + * - bool operator==(const RichParameter& rp): returns true if the two RichParameter are the same + */ +class RichParameter +{ +public: + RichParameter(const RichParameter& rp); + RichParameter(RichParameter&& rp); + RichParameter( + const QString& nm, + const Value& v, + const QString& desc = QString(), + const QString& tltip = QString(), + bool isAdvanced = false, + const QString& category = QString()); + virtual ~RichParameter(); + + const QString& name() const; + const Value& value() const; + const QString& fieldDescription() const; + const QString& toolTip() const; + bool isAdvanced() const; + bool isValueDefault() const; + const QString& category() const; + + template + bool isOfType() const + { + const RichParam* t = dynamic_cast(this); + return (t != nullptr); + } + + void setName(const QString& newName); + void setValue(const Value& ov, bool isDefault = false); + void setDefaultValue(bool isDefault = true); + + virtual QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; + + //python names of paraeter + QString pythonName() const; + QString pythonType() const; + + RichParameter& operator=(const RichParameter& rp); + RichParameter& operator=(RichParameter&& rp); + + virtual RichParameter* clone() const = 0; + virtual QString stringType() const = 0; + virtual bool operator==(const RichParameter& rp) = 0; + + friend void swap(RichParameter& rp1, RichParameter& rp2); + void swap(RichParameter& rp); + +protected: + QString pName; + Value* val; + QString fieldDesc; + QString tooltip; + bool advanced; + bool defaultValue; + QString pCategory; +}; + +void swap(RichParameter& rp1, RichParameter& rp2); + +#endif // MESHLAB_RICH_PARAMETER_H diff --git a/src/common/parameters/rich_parameter/rich_percentage.cpp b/src/common/parameters/rich_parameter/rich_percentage.cpp new file mode 100644 index 000000000..689fcd224 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_percentage.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_percentage.h" + +RichPercentage::RichPercentage( + const QString& nm, + const Scalarm defval, + const Scalarm minval, + const Scalarm maxval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, FloatValue(defval), desc, tltip, hidden, category), min(minval), max(maxval) +{ +} + +RichPercentage::~RichPercentage() +{ +} + +QString RichPercentage::stringType() const +{ + return "RichAbsPerc"; +} + +QDomElement RichPercentage::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const +{ + QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); + parElem.setAttribute("min",QString::number(min)); + parElem.setAttribute("max",QString::number(max)); + return parElem; +} + +RichPercentage* RichPercentage::clone() const +{ + return new RichPercentage(*this); +} + +bool RichPercentage::operator==( const RichParameter& rb ) +{ + return (rb.isOfType() &&(pName == rb.name()) && (value().getFloat() == rb.value().getFloat())); +} diff --git a/src/common/parameters/rich_parameter/rich_percentage.h b/src/common/parameters/rich_parameter/rich_percentage.h new file mode 100644 index 000000000..23b8659b1 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_percentage.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_PERCENTAGE_H +#define MESHLAB_RICH_PERCENTAGE_H + +#include "rich_parameter.h" + +class RichPercentage : public RichParameter +{ +public: + RichPercentage( + const QString& nm, + const Scalarm defval, + const Scalarm minval, + const Scalarm maxval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichPercentage(); + + QString stringType() const; + QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; + + RichPercentage* clone() const; + bool operator==(const RichParameter& rb); + Scalarm min; + Scalarm max; +}; + +#endif // MESHLAB_RICH_PERCENTAGE_H diff --git a/src/common/parameters/rich_parameter/rich_position.cpp b/src/common/parameters/rich_parameter/rich_position.cpp new file mode 100644 index 000000000..cb23a4f16 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_position.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_position.h" + +RichPosition::RichPosition( + const QString& nm, + const Point3m& defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, Point3Value(defval),desc, tltip, hidden, category) +{ +} + +RichPosition::~RichPosition() +{ +} + +QString RichPosition::stringType() const +{ + return "RichPosition"; +} + +RichPosition* RichPosition::clone() const +{ + return new RichPosition(*this); +} + +bool RichPosition::operator==( const RichParameter& rb ) +{ + return (rb.value().isPoint3() &&(pName == rb.name()) && (value().getPoint3() == rb.value().getPoint3())); +} + diff --git a/src/common/parameters/rich_parameter/rich_position.h b/src/common/parameters/rich_parameter/rich_position.h new file mode 100644 index 000000000..3daa6db0c --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_position.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_POSITION_H +#define MESHLAB_RICH_POSITION_H + +#include "rich_parameter.h" + +class RichPosition : public RichParameter +{ +public: + RichPosition( + const QString& nm, + const Point3m& defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichPosition(); + + QString stringType() const; + + RichPosition* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_POSITION_H diff --git a/src/common/parameters/rich_parameter/rich_shot.cpp b/src/common/parameters/rich_parameter/rich_shot.cpp new file mode 100644 index 000000000..c6144000a --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_shot.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_shot.h" + +RichShot::RichShot( + const QString& nm, + const Shotm& defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, ShotValue(defval),desc, tltip, hidden, category) +{ +} + +RichShot::~RichShot() +{ +} + +QString RichShot::stringType() const +{ + return "RichShotf"; +} + +RichShot* RichShot::clone() const +{ + return new RichShot(*this); +} + +bool RichShot::operator==( const RichParameter& rb ) +{ + return (rb.value().isShot() &&(pName == rb.name()) ); + // TODO REAL TEST OF EQUALITY // && (value().getShotf() == rb.value().getShotf())); +} + diff --git a/src/common/parameters/rich_parameter/rich_shot.h b/src/common/parameters/rich_parameter/rich_shot.h new file mode 100644 index 000000000..a6b9a4a0e --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_shot.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_SHOT_H +#define MESHLAB_RICH_SHOT_H + +#include "rich_parameter.h" + +class RichShot : public RichParameter +{ +public: + RichShot( + const QString& nm, + const Shotm& defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichShot(); + + QString stringType() const; + + RichShot* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_SHOT_H diff --git a/src/common/parameters/rich_parameter/rich_string.cpp b/src/common/parameters/rich_parameter/rich_string.cpp new file mode 100644 index 000000000..fec0ea3df --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_string.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_string.h" + +RichString::RichString( + const QString& nm, + const QString& defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, StringValue(defval),desc,tltip, hidden, category) +{ +} + +RichString::~RichString() +{ +} + +QString RichString::stringType() const +{ + return "RichString"; +} + +RichString* RichString::clone() const +{ + return new RichString(*this); +} + +bool RichString::operator==( const RichParameter& rb ) +{ + return (rb.value().isString() &&(pName == rb.name()) && (value().getString() == rb.value().getString())); +} + diff --git a/src/common/parameters/rich_parameter/rich_string.h b/src/common/parameters/rich_parameter/rich_string.h new file mode 100644 index 000000000..f02771a67 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_string.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_STRING_H +#define MESHLAB_RICH_STRING_H + +#include "rich_parameter.h" + +class RichString : public RichParameter +{ +public: + RichString( + const QString& nm, + const QString& defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichString(); + + QString stringType() const; + + RichString* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_STRING_H diff --git a/src/common/parameters/rich_parameter_list.cpp b/src/common/parameters/rich_parameter_list.cpp index cfb639070..7b249849e 100644 --- a/src/common/parameters/rich_parameter_list.cpp +++ b/src/common/parameters/rich_parameter_list.cpp @@ -1,6 +1,30 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2004-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + #include "rich_parameter_list.h" #include "../mlexception.h" +#include "../ml_document/mesh_document.h" #include #include @@ -128,7 +152,7 @@ QString RichParameterList::getString(const QString& name) const */ Matrix44m RichParameterList::getMatrix44(const QString& name) const { - return getParameterByName(name).value().getMatrix44f(); + return getParameterByName(name).value().getMatrix44(); } /** @@ -137,7 +161,7 @@ Matrix44m RichParameterList::getMatrix44(const QString& name) const */ Point3m RichParameterList::getPoint3m(const QString& name) const { - return getParameterByName(name).value().getPoint3f(); + return getParameterByName(name).value().getPoint3(); } /** @@ -146,7 +170,7 @@ Point3m RichParameterList::getPoint3m(const QString& name) const */ Shot RichParameterList::getShotf(const QString& name) const { - return Shot::Construct(getParameterByName(name).value().getShotf()); + return Shot::Construct(getParameterByName(name).value().getShot()); } /** @@ -155,7 +179,7 @@ Shot RichParameterList::getShotf(const QString& name) const */ Scalarm RichParameterList::getAbsPerc(const QString& name) const { - return getParameterByName(name).value().getAbsPerc(); + return getParameterByName(name).value().getFloat(); } /** @@ -164,16 +188,16 @@ Scalarm RichParameterList::getAbsPerc(const QString& name) const */ int RichParameterList::getEnum(const QString& name) const { - return getParameterByName(name).value().getEnum(); + return getParameterByName(name).value().getInt(); } /** * @return the mesh of the RichParameter having the given name. * @throws an MLException if the name is not found in the list */ -MeshModel * RichParameterList::getMesh(const QString& name) const +unsigned int RichParameterList::getMeshId(const QString& name) const { - return getParameterByName(name).value().getMesh(); + return getParameterByName(name).value().getInt(); } /** @@ -182,7 +206,7 @@ MeshModel * RichParameterList::getMesh(const QString& name) const */ Scalarm RichParameterList::getDynamicFloat(const QString& name) const { - return getParameterByName(name).value().getDynamicFloat(); + return getParameterByName(name).value().getFloat(); } /** @@ -191,7 +215,7 @@ Scalarm RichParameterList::getDynamicFloat(const QString& name) const */ QString RichParameterList::getOpenFileName(const QString& name) const { - return getParameterByName(name).value().getFileName(); + return getParameterByName(name).value().getString(); } /** @@ -200,7 +224,7 @@ QString RichParameterList::getOpenFileName(const QString& name) const */ QString RichParameterList::getSaveFileName(const QString& name) const { - return getParameterByName(name).value().getFileName(); + return getParameterByName(name).value().getString(); } /** @@ -292,6 +316,16 @@ const RichParameter& RichParameterList::at(unsigned int i) const return **it; } +unsigned int RichParameterList::numberAdvancedParameters() const +{ + unsigned int n = 0; + for (const RichParameter& rp : *this){ + if (rp.isAdvanced()) + ++n; + } + return n; +} + /** * @brief sets the value of the RichParameter having the given name. * @throws an MLException if the name is not found in the list @@ -301,6 +335,13 @@ void RichParameterList::setValue(const QString& name,const Value& newval) getParameterByName(name).setValue(newval); } +void RichParameterList::setAllValuesAsDefault() +{ + for (auto& p : paramList) { + p->setDefaultValue(); + } +} + /** * @brief adds a RichParameter to the list. * @return a reference to the added parameter @@ -330,7 +371,7 @@ void RichParameterList::join( const RichParameterList& rps ) void RichParameterList::pushFromQDomElement(QDomElement np) { RichParameter* rp = nullptr; - bool b = RichParameterAdapter::create(np, &rp); + bool b = RichParameterAdapter::create(np, rp); if (b) paramList.push_back(rp); } diff --git a/src/common/parameters/rich_parameter_list.h b/src/common/parameters/rich_parameter_list.h index 5c5c29929..4c3177614 100644 --- a/src/common/parameters/rich_parameter_list.h +++ b/src/common/parameters/rich_parameter_list.h @@ -2,7 +2,7 @@ * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * -* Copyright(C) 2004-2020 \/)\/ * +* Copyright(C) 2004-2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -24,7 +24,7 @@ #ifndef MESHLAB_RICH_PARAMETER_LIST_H #define MESHLAB_RICH_PARAMETER_LIST_H -#include "rich_parameter.h" +#include "rich_parameters.h" /** * @brief The RichParameterList class @@ -108,7 +108,7 @@ public: vcg::Color4b getColor4b(const QString& name) const; Scalarm getAbsPerc(const QString& name) const; int getEnum(const QString& name) const; - MeshModel* getMesh(const QString& name) const; + unsigned int getMeshId(const QString& name) const; Scalarm getDynamicFloat(const QString& name) const; QString getOpenFileName(const QString& name) const; QString getSaveFileName(const QString& name) const; @@ -120,8 +120,10 @@ public: const_iterator findParameter(const QString& name) const; RichParameter& at(unsigned int i); const RichParameter& at(unsigned int i) const; + unsigned int numberAdvancedParameters() const; void setValue(const QString& name, const Value& val); + void setAllValuesAsDefault(); RichParameter& addParam(const RichParameter& pd); void join(const RichParameterList& rps); diff --git a/src/common/parameters/rich_parameters.cpp b/src/common/parameters/rich_parameters.cpp new file mode 100644 index 000000000..43580fcd1 --- /dev/null +++ b/src/common/parameters/rich_parameters.cpp @@ -0,0 +1,227 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_parameters.h" + +bool RichParameterAdapter::create( const QDomElement& np,RichParameter*& par ) +{ + QString name=np.attribute("name"); + QString type=np.attribute("type"); + QString desc=np.attribute("description"); + QString tooltip=np.attribute("tooltip"); + + // qDebug(" Reading Param with name %s : %s", qUtf8Printable(name), qUtf8Printable(type)); + + bool corrconv = false; + if(type=="RichBool") { + QString val = np.attribute("value").toLower(); + if ((val != QString("true")) && (val != QString("false"))) + return false; + par = new RichBool(name,np.attribute("value")!=QString("false"),desc,tooltip); + return true; + } + + if(type=="RichInt") { + int val = np.attribute("value").toInt(&corrconv); + if (!corrconv) + return false; + par = new RichInt(name,val,desc,tooltip); + return true; + } + + if(type=="RichFloat") { + float val = np.attribute("value").toFloat(&corrconv); + if (!corrconv) + return false; + par = new RichFloat(name,val,desc,tooltip); + return true; + } + + if(type=="RichString") { + par = new RichString(name,np.attribute("value"),desc,tooltip); + return true; + } + + if(type=="RichAbsPerc") { + float val = np.attribute("value").toFloat(&corrconv); + if ((!corrconv) && (val >= 0.0f) && (val <= 100.0f)) + return false; + float min = np.attribute("min").toFloat(&corrconv); + if (!corrconv) + return false; + float max = np.attribute("max").toFloat(&corrconv); + if (!corrconv) + return false; + par = new RichPercentage(name,val,min,max,desc,tooltip); + return true; + } + + if(type=="RichColor") { + unsigned int r = np.attribute("r").toUInt(&corrconv); + if ((!corrconv) && (r <= 255)) + return false; + unsigned int g = np.attribute("g").toUInt(&corrconv); + if ((!corrconv) && (g <= 255)) + return false; + unsigned int b = np.attribute("b").toUInt(&corrconv); + if ((!corrconv) && (b <= 255)) + return false; + unsigned int a = np.attribute("a").toUInt(&corrconv); + if ((!corrconv) && (a <= 255)) + return false; + QColor col(r,g,b,a); + par= new RichColor(name,col,desc,tooltip); + return true; + } + + if(type=="RichMatrix44f") { + Matrix44m mm; + for(int i=0;i<16;++i) + { + Scalarm val = np.attribute(QString("val")+QString::number(i)).toFloat(&corrconv); + if (!corrconv) + return false; + mm.V()[i]=val; + } + par = new RichMatrix44(name,mm,desc,tooltip); + return true; + } + + if(type=="RichEnum") { + QStringList list; + int enum_card = np.attribute(QString("enum_cardinality")).toUInt(&corrconv); + if (!corrconv) + return false; + + for(int i=0;i=0) && (val < enum_card)) + return false; + par = new RichEnum(name,val,list,desc,tooltip); + return true; + } + + if(type == "RichMesh") { + int val = np.attribute("value").toInt(&corrconv); + + if (!corrconv) + return false; + + par = new RichMesh(name, val, nullptr, desc,tooltip); + return true; + } + + if(type == "RichDynamicFloat") { + float min = np.attribute("min").toFloat(&corrconv); + if (!corrconv) + return false; + float max = np.attribute("max").toFloat(&corrconv); + if (!corrconv) + return false; + + float val = np.attribute("value").toFloat(&corrconv); + if ((!corrconv) && (val >= min) && (val <= max)) + return false; + + par = new RichDynamicFloat(name, val, min, max, desc, tooltip); + return true; + } + + if(type == "RichOpenFile") { + QStringList list; + int exts_card = np.attribute(QString("exts_cardinality")).toUInt(&corrconv); + if (!corrconv) + return false; + + for(int i=0;imeshList.at(meshind); - else - pval = nullptr; -} - -void IntValue::fillToXMLElement(QDomElement& element) const -{ - element.setAttribute("value", QString::number(pval)); -} - -void FloatValue::fillToXMLElement(QDomElement& element) const -{ - element.setAttribute("value", QString::number(pval)); -} - -void StringValue::fillToXMLElement(QDomElement& element) const -{ - element.setAttribute("value", pval); -} - -void Matrix44fValue::fillToXMLElement(QDomElement& element) const -{ - for(unsigned int ii = 0;ii < 16;++ii) - element.setAttribute(QString("val")+QString::number(ii),QString::number(pval.V()[ii])); -} - -void Point3fValue::fillToXMLElement(QDomElement& element) const -{ - element.setAttribute("x",QString::number(pval.X())); - element.setAttribute("y",QString::number(pval.Y())); - element.setAttribute("z",QString::number(pval.Z())); -} - -void ShotfValue::fillToXMLElement(QDomElement&) const -{ - assert(0); - //TODO!!! -} - -void ColorValue::fillToXMLElement(QDomElement& element) const -{ - element.setAttribute("r",QString::number(pval.red())); - element.setAttribute("g",QString::number(pval.green())); - element.setAttribute("b",QString::number(pval.blue())); - element.setAttribute("a",QString::number(pval.alpha())); -} - -void FileValue::fillToXMLElement(QDomElement& element) const -{ - element.setAttribute("value", pval); -} - -void MeshValue::fillToXMLElement(QDomElement&) const -{ - //nothing to do on this side... Everything is done on RichMesh side - //maybe breaking retrocompatibility for mlx and do something here - //could be a good idea. -} - diff --git a/src/common/parameters/value.h b/src/common/parameters/value.h deleted file mode 100644 index 09c0fd551..000000000 --- a/src/common/parameters/value.h +++ /dev/null @@ -1,293 +0,0 @@ -/**************************************************************************** -* MeshLab o o * -* A versatile mesh processing toolbox o o * -* _ O _ * -* Copyright(C) 2004-2020 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ - -#ifndef MESHLAB_VALUE_H -#define MESHLAB_VALUE_H - -#include -#include -#include "../ml_document/cmesh.h" -class MeshModel; -class MeshDocument; -class QDomElement; - -/** - * @brief The Value class - * - * Represents a generic parameter value for meshlab. - * Specializations inherit from this class, depending on the type of the - * value. Value class is an attribute of the RichParameter class. - */ -class Value -{ -public: - virtual ~Value() {} - - virtual bool getBool() const { assert(0); return bool(); } - virtual int getInt() const { assert(0); return int(); } - virtual Scalarm getFloat() const { assert(0); return Scalarm(); } - virtual QString getString() const { assert(0); return QString(); } - virtual Matrix44m getMatrix44f() const { assert(0); return Matrix44m(); } - virtual Point3m getPoint3f() const { assert(0); return Point3m(); } - virtual Shotm getShotf() const { assert(0); return Shotm(); } - virtual QColor getColor() const { assert(0); return QColor(); } - virtual Scalarm getAbsPerc() const { assert(0); return Scalarm(); } - virtual int getEnum() const { assert(0); return int(); } - virtual MeshModel* getMesh() const { assert(0); return NULL; } - virtual Scalarm getDynamicFloat() const { assert(0); return Scalarm(); } - virtual QString getFileName() const { assert(0); return QString(); } - - virtual bool isBool() const { return false; } - virtual bool isInt() const { return false; } - virtual bool isFloat() const { return false; } - virtual bool isString() const { return false; } - virtual bool isMatrix44f() const { return false; } - virtual bool isPoint3f() const { return false; } - virtual bool isShotf() const { return false; } - virtual bool isColor() const { return false; } - virtual bool isAbsPerc() const { return false; } - virtual bool isEnum() const { return false; } - virtual bool isMesh() const { return false; } - virtual bool isDynamicFloat() const { return false; } - virtual bool isFileName() const { return false; } - - virtual QString typeName() const = 0; - virtual void set(const Value& p) = 0; - virtual Value* clone() const = 0; - virtual void fillToXMLElement(QDomElement& element) const = 0; -}; - -class BoolValue : public Value -{ -public: - BoolValue(const bool val) : pval(val) {}; - ~BoolValue() {} - - inline bool getBool() const { return pval; } - inline bool isBool() const { return true; } - inline QString typeName() const { return QString("Bool"); } - inline void set(const Value& p) { pval = p.getBool(); } - inline BoolValue* clone() const {return new BoolValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - bool pval; -}; - -class IntValue : public Value -{ -public: - IntValue(const int val) : pval(val) {} - ~IntValue() {} - - inline int getInt() const { return pval; } - inline bool isInt() const { return true; } - inline QString typeName() const { return QString("Int"); } - inline void set(const Value& p) { pval = p.getInt(); } - inline IntValue* clone() const {return new IntValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - int pval; -}; - -class FloatValue : public Value -{ -public: - FloatValue(const float val) :pval(val) {} - ~FloatValue() {} - - inline Scalarm getFloat() const { return pval; } - inline bool isFloat() const { return true; } - inline QString typeName() const { return QString("Float"); } - inline void set(const Value& p) { pval = p.getFloat(); } - inline FloatValue* clone() const {return new FloatValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - Scalarm pval; -}; - -class StringValue : public Value -{ -public: - StringValue(const QString& val) :pval(val) {} - ~StringValue() {} - - inline QString getString() const { return pval; } - inline bool isString() const { return true; } - inline QString typeName() const { return QString("String"); } - inline void set(const Value& p) { pval = p.getString(); } - inline StringValue* clone() const {return new StringValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - QString pval; -}; - -class Matrix44fValue : public Value -{ -public: - Matrix44fValue(const Matrix44m& val) :pval(val) {} - //Matrix44fValue(const vcg::Matrix44d& val) :pval(vcg::Matrix44f::Construct(val)) {} - ~Matrix44fValue() {} - - inline Matrix44m getMatrix44f() const { return pval; } - inline bool isMatrix44f() const { return true; } - inline QString typeName() const { return QString("Matrix44f"); } - inline void set(const Value& p) { pval = p.getMatrix44f(); } - inline Matrix44fValue* clone() const {return new Matrix44fValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - Matrix44m pval; -}; - -class Point3fValue : public Value -{ -public: - Point3fValue(const Point3m& val) : pval(val) {} - ~Point3fValue() {} - - inline Point3m getPoint3f() const { return pval; } - inline bool isPoint3f() const { return true; } - inline QString typeName() const { return QString("Point3f"); } - inline void set(const Value& p) { pval = p.getPoint3f(); } - inline Point3fValue* clone() const {return new Point3fValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - Point3m pval; -}; - -class ShotfValue : public Value -{ -public: - ShotfValue(const Shotm& val) : pval(val) {} - ~ShotfValue() {} - - inline Shotm getShotf() const { return pval; } - inline bool isShotf() const { return true; } - inline QString typeName() const { return QString("Shotf"); } - inline void set(const Value& p) { pval = p.getShotf(); } - inline ShotfValue* clone() const {return new ShotfValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - Shotm pval; -}; - -class ColorValue : public Value -{ -public: - ColorValue(QColor val) :pval(val) {} - ~ColorValue() {} - - inline QColor getColor() const { return pval; } - inline bool isColor() const { return true; } - inline QString typeName() const { return QString("Color"); } - inline void set(const Value& p) { pval = p.getColor(); } - inline ColorValue* clone() const {return new ColorValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - QColor pval; -}; - -class AbsPercValue : public FloatValue -{ -public: - AbsPercValue(const float val) :FloatValue(val) {} - ~AbsPercValue() {} - - inline Scalarm getAbsPerc() const { return getFloat(); } - inline QString typeName() const { return QString("AbsPerc"); } - inline bool isAbsPerc() const { return true; } - inline AbsPercValue* clone() const {return new AbsPercValue(*this);} - using FloatValue::fillToXMLElement; - -}; - -class EnumValue : public IntValue -{ -public: - EnumValue(const int val) :IntValue(val) {} - ~EnumValue() {} - - inline int getEnum() const { return getInt(); } - inline bool isEnum() const { return true; } - inline QString typeName() const { return QString("Enum"); } - inline EnumValue* clone() const {return new EnumValue(*this);} - using IntValue::fillToXMLElement; -}; - -class DynamicFloatValue : public FloatValue -{ -public: - DynamicFloatValue(const float val) :FloatValue(val) {} - ~DynamicFloatValue() {} - - inline Scalarm getDynamicFloat() const { return getFloat(); } - inline bool isDynamicFloat() const { return true; } - inline QString typeName() const { return QString("DynamicFloat"); } - inline DynamicFloatValue* clone() const {return new DynamicFloatValue(*this);} - using FloatValue::fillToXMLElement; - -}; - -class FileValue : public Value -{ -public: - FileValue(const QString& filename) :pval(filename) {} - ~FileValue() {} - - inline QString getFileName() const { return pval; } - inline bool isFileName() const { return true; } - inline QString typeName() const { return QString("FileName"); } - inline void set(const Value& p) { pval = p.getFileName(); } - inline FileValue* clone() const {return new FileValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - QString pval; -}; - -class MeshValue : public Value -{ -public: - MeshValue(MeshModel* mesh) : pval(mesh) {} - MeshValue(MeshDocument* doc, int meshind); - ~MeshValue() {} - - inline MeshModel* getMesh() const { return pval; } - inline bool isMesh() const { return true; } - inline QString typeName() const { return QString("Mesh"); } - inline void set(const Value& p) { pval = p.getMesh(); } - inline MeshValue* clone() const {return new MeshValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - MeshModel* pval; -}; - -#endif //MESHLAB_VALUE_H diff --git a/src/common/parameters/value/bool_value.cpp b/src/common/parameters/value/bool_value.cpp new file mode 100644 index 000000000..833fc4f47 --- /dev/null +++ b/src/common/parameters/value/bool_value.cpp @@ -0,0 +1,69 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "bool_value.h" + +#include + +BoolValue::BoolValue(const bool val) : pval(val) +{ +} + +bool BoolValue::getBool() const +{ + return pval; +} + +bool BoolValue::isBool() const +{ + return true; +} + +QString BoolValue::typeName() const +{ + return QString("Bool"); +} + +void BoolValue::set(const Value &p) +{ + pval = p.getBool(); +} + +BoolValue *BoolValue::clone() const +{ + return new BoolValue(*this); +} + +bool BoolValue::operator==(const Value &p) const +{ + if (p.isBool()) + return pval == p.getBool(); + else + return false; +} + +void BoolValue::fillToXMLElement(QDomElement& element) const +{ + QString v = pval ? "true" : "false"; + element.setAttribute("value", v); +} diff --git a/src/common/parameters/value/bool_value.h b/src/common/parameters/value/bool_value.h new file mode 100644 index 000000000..b5c934128 --- /dev/null +++ b/src/common/parameters/value/bool_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_BOOL_VALUE_H +#define MESHLAB_BOOL_VALUE_H + +#include "value.h" + +class BoolValue : public Value +{ +public: + BoolValue(const bool val); + ~BoolValue() {} + + bool getBool() const; + bool isBool() const; + QString typeName() const; + void set(const Value& p); + BoolValue* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + bool pval; +}; + +#endif // MESHLAB_BOOL_VALUE_H diff --git a/src/common/parameters/value/color_value.cpp b/src/common/parameters/value/color_value.cpp new file mode 100644 index 000000000..f40b3decb --- /dev/null +++ b/src/common/parameters/value/color_value.cpp @@ -0,0 +1,71 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "color_value.h" + +#include + +ColorValue::ColorValue(QColor val) : pval(val) +{ +} + +QColor ColorValue::getColor() const +{ + return pval; +} + +bool ColorValue::isColor() const +{ + return true; +} + +QString ColorValue::typeName() const +{ + return QString("Color"); +} + +void ColorValue::set(const Value& p) +{ + pval = p.getColor(); +} + +ColorValue* ColorValue::clone() const +{ + return new ColorValue(*this); +} + +bool ColorValue::operator==(const Value& p) const +{ + if (p.isColor()) + return pval == p.getColor(); + else + return false; +} + +void ColorValue::fillToXMLElement(QDomElement& element) const +{ + element.setAttribute("r", QString::number(pval.red())); + element.setAttribute("g", QString::number(pval.green())); + element.setAttribute("b", QString::number(pval.blue())); + element.setAttribute("a", QString::number(pval.alpha())); +} diff --git a/src/common/parameters/value/color_value.h b/src/common/parameters/value/color_value.h new file mode 100644 index 000000000..c497c8e2a --- /dev/null +++ b/src/common/parameters/value/color_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_COLOR_VALUE_H +#define MESHLAB_COLOR_VALUE_H + +#include "value.h" + +class ColorValue : public Value +{ +public: + ColorValue(QColor val); + ~ColorValue() {} + + QColor getColor() const; + bool isColor() const; + QString typeName() const; + void set(const Value& p); + ColorValue* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + QColor pval; +}; + +#endif // MESHLAB_COLOR_VALUE_H diff --git a/src/common/parameters/value/float_value.cpp b/src/common/parameters/value/float_value.cpp new file mode 100644 index 000000000..406642fda --- /dev/null +++ b/src/common/parameters/value/float_value.cpp @@ -0,0 +1,68 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "float_value.h" + +#include + +FloatValue::FloatValue(const float val) : pval(val) +{ +} + +Scalarm FloatValue::getFloat() const +{ + return pval; +} + +bool FloatValue::isFloat() const +{ + return true; +} + +QString FloatValue::typeName() const +{ + return QString("Float"); +} + +void FloatValue::set(const Value& p) +{ + pval = p.getFloat(); +} + +FloatValue* FloatValue::clone() const +{ + return new FloatValue(*this); +} + +bool FloatValue::operator==(const Value& p) const +{ + if (p.isFloat()) + return pval == p.getFloat(); + else + return false; +} + +void FloatValue::fillToXMLElement(QDomElement& element) const +{ + element.setAttribute("value", QString::number(pval)); +} diff --git a/src/common/parameters/value/float_value.h b/src/common/parameters/value/float_value.h new file mode 100644 index 000000000..93530b568 --- /dev/null +++ b/src/common/parameters/value/float_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_FLOAT_VALUE_H +#define MESHLAB_FLOAT_VALUE_H + +#include "value.h" + +class FloatValue : public Value +{ +public: + FloatValue(const float val); + ~FloatValue() {} + + Scalarm getFloat() const; + bool isFloat() const; + QString typeName() const; + void set(const Value& p); + FloatValue* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + Scalarm pval; +}; + +#endif // MESHLAB_FLOAT_VALUE_H diff --git a/src/common/parameters/value/int_value.cpp b/src/common/parameters/value/int_value.cpp new file mode 100644 index 000000000..43ccf594f --- /dev/null +++ b/src/common/parameters/value/int_value.cpp @@ -0,0 +1,63 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "int_value.h" + +#include + +IntValue::IntValue(const int val) : pval(val) +{ +} + +int IntValue::getInt() const +{ + return pval; +} + +QString IntValue::typeName() const +{ + return QString("Int"); +} + +void IntValue::set(const Value& p) +{ + pval = p.getInt(); +} + +IntValue* IntValue::clone() const +{ + return new IntValue(*this); +} + +bool IntValue::operator==(const Value& p) const +{ + if (p.isInt()) + return pval == p.getInt(); + else + return false; +} + +void IntValue::fillToXMLElement(QDomElement& element) const +{ + element.setAttribute("value", QString::number(pval)); +} diff --git a/src/common/parameters/value/int_value.h b/src/common/parameters/value/int_value.h new file mode 100644 index 000000000..8d3479bda --- /dev/null +++ b/src/common/parameters/value/int_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_INT_VALUE_H +#define MESHLAB_INT_VALUE_H + +#include "value.h" + +class IntValue : public Value +{ +public: + IntValue(const int val); + ~IntValue() {} + + int getInt() const; + inline bool isInt() const { return true; } + QString typeName() const; + void set(const Value& p); + IntValue* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + int pval; +}; + +#endif // MESHLAB_INT_VALUE_H diff --git a/src/common/parameters/value/matrix44_value.cpp b/src/common/parameters/value/matrix44_value.cpp new file mode 100644 index 000000000..202cb4d8e --- /dev/null +++ b/src/common/parameters/value/matrix44_value.cpp @@ -0,0 +1,69 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "matrix44_value.h" + +#include + +Matrix44Value::Matrix44Value(const Matrix44m& val) : pval(val) +{ +} + +Matrix44m Matrix44Value::getMatrix44() const +{ + return pval; +} + +bool Matrix44Value::isMatrix44() const +{ + return true; +} + +QString Matrix44Value::typeName() const +{ + return QString("Matrix44"); +} + +void Matrix44Value::set(const Value& p) +{ + pval = p.getMatrix44(); +} + +Matrix44Value* Matrix44Value::clone() const +{ + return new Matrix44Value(*this); +} + +bool Matrix44Value::operator==(const Value& p) const +{ + if (p.isMatrix44()) + return pval == p.getMatrix44(); + else + return false; +} + +void Matrix44Value::fillToXMLElement(QDomElement& element) const +{ + for (unsigned int ii = 0; ii < 16; ++ii) + element.setAttribute(QString("val") + QString::number(ii), QString::number(pval.V()[ii])); +} diff --git a/src/common/parameters/value/matrix44_value.h b/src/common/parameters/value/matrix44_value.h new file mode 100644 index 000000000..b5e75695b --- /dev/null +++ b/src/common/parameters/value/matrix44_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_MATRIX44_VALUE_H +#define MESHLAB_MATRIX44_VALUE_H + +#include "value.h" + +class Matrix44Value : public Value +{ +public: + Matrix44Value(const Matrix44m& val); + ~Matrix44Value() {} + + Matrix44m getMatrix44() const; + bool isMatrix44() const; + QString typeName() const; + void set(const Value& p); + Matrix44Value* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + Matrix44m pval; +}; + +#endif // MESHLAB_MATRIX44_VALUE_H diff --git a/src/common/parameters/value/point3_value.cpp b/src/common/parameters/value/point3_value.cpp new file mode 100644 index 000000000..e8cb906c6 --- /dev/null +++ b/src/common/parameters/value/point3_value.cpp @@ -0,0 +1,70 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "point3_value.h" + +#include + +Point3Value::Point3Value(const Point3m& val) : pval(val) +{ +} + +Point3m Point3Value::getPoint3() const +{ + return pval; +} + +bool Point3Value::isPoint3() const +{ + return true; +} + +QString Point3Value::typeName() const +{ + return QString("Point3"); +} + +void Point3Value::set(const Value& p) +{ + pval = p.getPoint3(); +} + +Point3Value* Point3Value::clone() const +{ + return new Point3Value(*this); +} + +bool Point3Value::operator==(const Value& p) const +{ + if (p.isPoint3()) + return pval == p.getPoint3(); + else + return false; +} + +void Point3Value::fillToXMLElement(QDomElement& element) const +{ + element.setAttribute("x", QString::number(pval.X())); + element.setAttribute("y", QString::number(pval.Y())); + element.setAttribute("z", QString::number(pval.Z())); +} diff --git a/src/common/parameters/value/point3_value.h b/src/common/parameters/value/point3_value.h new file mode 100644 index 000000000..bdfab998e --- /dev/null +++ b/src/common/parameters/value/point3_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_POINT3_VALUE_H +#define MESHLAB_POINT3_VALUE_H + +#include "value.h" + +class Point3Value : public Value +{ +public: + Point3Value(const Point3m& val); + ~Point3Value() {} + + Point3m getPoint3() const; + bool isPoint3() const; + QString typeName() const; + void set(const Value& p); + Point3Value* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + Point3m pval; +}; + +#endif // MESHLAB_POINT3_VALUE_H diff --git a/src/common/parameters/value/shot_value.cpp b/src/common/parameters/value/shot_value.cpp new file mode 100644 index 000000000..379db5236 --- /dev/null +++ b/src/common/parameters/value/shot_value.cpp @@ -0,0 +1,69 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "shot_value.h" + +#include + +ShotValue::ShotValue(const Shotm& val) : pval(val) +{ +} + +Shotm ShotValue::getShot() const +{ + return pval; +} + +bool ShotValue::isShot() const +{ + return true; +} + +QString ShotValue::typeName() const +{ + return QString("Shot"); +} + +void ShotValue::set(const Value& p) +{ + pval = p.getShot(); +} + +ShotValue* ShotValue::clone() const +{ + return new ShotValue(*this); +} + +bool ShotValue::operator==(const Value& p) const +{ + if (p.isShot()) + return pval == p.getShot(); + else + return false; +} + +void ShotValue::fillToXMLElement(QDomElement&) const +{ + assert(0); + // TODO!!! +} diff --git a/src/common/parameters/value/shot_value.h b/src/common/parameters/value/shot_value.h new file mode 100644 index 000000000..c6b3f8e43 --- /dev/null +++ b/src/common/parameters/value/shot_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_SHOT_VALUE_H +#define MESHLAB_SHOT_VALUE_H + +#include "value.h" + +class ShotValue : public Value +{ +public: + ShotValue(const Shotm& val); + ~ShotValue() {} + + Shotm getShot() const; + bool isShot() const; + QString typeName() const; + void set(const Value& p); + ShotValue* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + Shotm pval; +}; + +#endif // MESHLAB_SHOT_VALUE_H diff --git a/src/common/parameters/value/string_value.cpp b/src/common/parameters/value/string_value.cpp new file mode 100644 index 000000000..c5005678e --- /dev/null +++ b/src/common/parameters/value/string_value.cpp @@ -0,0 +1,68 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "string_value.h" + +#include + +StringValue::StringValue(const QString& val) : pval(val) +{ +} + +QString StringValue::getString() const +{ + return pval; +} + +bool StringValue::isString() const +{ + return true; +} + +QString StringValue::typeName() const +{ + return QString("String"); +} + +void StringValue::set(const Value& p) +{ + pval = p.getString(); +} + +StringValue* StringValue::clone() const +{ + return new StringValue(*this); +} + +bool StringValue::operator==(const Value& p) const +{ + if (p.isString()) + return pval == p.getString(); + else + return false; +} + +void StringValue::fillToXMLElement(QDomElement& element) const +{ + element.setAttribute("value", pval); +} diff --git a/src/common/parameters/value/string_value.h b/src/common/parameters/value/string_value.h new file mode 100644 index 000000000..a814d1703 --- /dev/null +++ b/src/common/parameters/value/string_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_STRING_VALUE_H +#define MESHLAB_STRING_VALUE_H + +#include "value.h" + +class StringValue : public Value +{ +public: + StringValue(const QString& val); + ~StringValue() {} + + QString getString() const; + bool isString() const; + QString typeName() const; + void set(const Value& p); + StringValue* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + QString pval; +}; + +#endif // MESHLAB_STRING_VALUE_H diff --git a/src/common/parameters/value/value.h b/src/common/parameters/value/value.h new file mode 100644 index 000000000..3aad13b68 --- /dev/null +++ b/src/common/parameters/value/value.h @@ -0,0 +1,110 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_VALUE_H +#define MESHLAB_VALUE_H + +#include "../../ml_document/cmesh.h" +#include +#include +class MeshModel; +class MeshDocument; +class QDomElement; + +/** + * @brief The Value class + * + * Represents a generic parameter value for meshlab. + * Specializations inherit from this class, depending on the type of the + * value. Value class is an attribute of the RichParameter class. + */ +class Value +{ +public: + virtual ~Value() {} + + virtual bool getBool() const + { + assert(0); + return bool(); + } + virtual int getInt() const + { + assert(0); + return int(); + } + virtual Scalarm getFloat() const + { + assert(0); + return Scalarm(); + } + virtual QString getString() const + { + assert(0); + return QString(); + } + virtual Matrix44m getMatrix44() const + { + assert(0); + return Matrix44m(); + } + virtual Point3m getPoint3() const + { + assert(0); + return Point3m(); + } + virtual Shotm getShot() const + { + assert(0); + return Shotm(); + } + virtual QColor getColor() const + { + assert(0); + return QColor(); + } + + virtual bool isBool() const { return false; } + virtual bool isInt() const { return false; } + virtual bool isFloat() const { return false; } + virtual bool isString() const { return false; } + virtual bool isMatrix44() const { return false; } + virtual bool isPoint3() const { return false; } + virtual bool isShot() const { return false; } + virtual bool isColor() const { return false; } + + virtual QString typeName() const = 0; + virtual void set(const Value& p) = 0; + virtual Value* clone() const = 0; + virtual bool operator==(const Value& p) const = 0; + virtual void fillToXMLElement(QDomElement& element) const = 0; + + template + bool isOfType() const + { + const Val* t = dynamic_cast(this); + return (t != nullptr); + } +}; + +#endif //MESHLAB_VALUE_H diff --git a/src/common/parameters/values.h b/src/common/parameters/values.h new file mode 100644 index 000000000..43c41dafa --- /dev/null +++ b/src/common/parameters/values.h @@ -0,0 +1,36 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_VALUES_H +#define MESHLAB_VALUES_H + +#include "value/bool_value.h" +#include "value/color_value.h" +#include "value/float_value.h" +#include "value/int_value.h" +#include "value/matrix44_value.h" +#include "value/point3_value.h" +#include "value/shot_value.h" +#include "value/string_value.h" + +#endif // MESHLAB_VALUES_H diff --git a/src/common/pluginmanager.cpp b/src/common/pluginmanager.cpp deleted file mode 100644 index 465e963aa..000000000 --- a/src/common/pluginmanager.cpp +++ /dev/null @@ -1,377 +0,0 @@ -#include "pluginmanager.h" -#include -#include -#include -#include -#include - -#include "mlexception.h" - -static QStringList fileNamePluginDLLs() { - QStringList l; -#if defined(Q_OS_WIN) - l.push_back("*.dll"); - return l; -#elif defined(Q_OS_MAC) - l.push_back("*.dylib"); - l.push_back("*.so"); - return l; -#else //linux - l.push_back("*.so"); - return l; -#endif -} - -static QString fileNamePrefixPluginDLLs() { -#if defined(Q_OS_WIN) - return QString(""); -#else //macos and linux - return QString("lib"); -#endif -} - -PluginManager::PluginManager() -{ - //pluginsDir=QDir(getPluginDirPath()); - //without adding the correct library path in the mac the loading of jpg (done via qt plugins) fails - //qApp->addLibraryPath(getPluginDirPath()); - //qApp->addLibraryPath(getBaseDirPath()); -} - -PluginManager::~PluginManager() -{ - ioMeshPlugins.clear(); - meshFilterPlug.clear(); - meshRenderPlug.clear(); - meshDecoratePlug.clear(); - for (PluginInterface* plugin : ownerPlug) - delete plugin; - ownerPlug.clear(); - - for (int ii = 0; ii < meshEditInterfacePlug.size(); ++ii) - delete meshEditInterfacePlug[ii]; - meshEditInterfacePlug.clear(); -} - - - -void PluginManager::loadPlugins(RichParameterList& defaultGlobal) -{ - loadPlugins(defaultGlobal, QDir(getDefaultPluginDirPath())); -} - -void PluginManager::loadPlugins(RichParameterList& defaultGlobal, const QDir& pluginsDirectory) -{ - pluginsDir = pluginsDirectory; - // without adding the correct library path in the mac the loading of jpg (done via qt plugins) fails - qApp->addLibraryPath(getDefaultPluginDirPath()); - qApp->addLibraryPath(getBaseDirPath()); - QStringList nameFiltersPlugins = fileNamePluginDLLs(); - - //only the file with extension pluginfilters will be listed by function entryList() - pluginsDir.setNameFilters(nameFiltersPlugins); - - qDebug("Current Plugins Dir is: %s ", qUtf8Printable(pluginsDir.absolutePath())); - for(QString fileName : pluginsDir.entryList(QDir::Files)) - { - // qDebug() << fileName; - QString absfilepath = pluginsDir.absoluteFilePath(fileName); - QFileInfo fin(absfilepath); - QPluginLoader loader(absfilepath); - QObject *plugin = loader.instance(); - if (plugin) - { - pluginsLoaded.push_back(fileName); - PluginInterface *iCommon = nullptr; - FilterPluginInterface *iFilter = qobject_cast(plugin); - if (iFilter) - { - iCommon = iFilter; - bool loadFilterOK = true; - for(QAction *filterAction : iFilter->actions()) { - if(iFilter->getClass(filterAction)==FilterPluginInterface::Generic){ - qDebug() << "Missing class for " +fileName + " " + filterAction->text(); - loadFilterOK = false; - } - if(iFilter->getRequirements(filterAction) == int(MeshModel::MM_UNKNOWN)){ - qDebug() << "Missing requirements for " +fileName + " " + filterAction->text(); - loadFilterOK = false; - } - if(iFilter->getPreConditions(filterAction) == int(MeshModel::MM_UNKNOWN)){ - qDebug() << "Missing preconditions for "+fileName + " " + filterAction->text(); - loadFilterOK = false; - } - if(iFilter->postCondition(filterAction) == int(MeshModel::MM_UNKNOWN )) { - qDebug() << "Missing postcondition for "+fileName + " " + filterAction->text(); - loadFilterOK = false; - } - if(iFilter->filterArity(filterAction) == FilterPluginInterface::UNKNOWN_ARITY ) { - qDebug() << "Missing Arity for " +fileName + " " + filterAction->text(); - loadFilterOK = false; - } - - } - if (loadFilterOK) { - for(QAction *filterAction : iFilter->actions()) { - filterAction->setData(QVariant(fileName)); - actionFilterMap.insert(filterAction->text(), filterAction); - stringFilterMap.insert(filterAction->text(), iFilter); - } - meshFilterPlug.push_back(iFilter); - } - } - IOMeshPluginInterface *iIOMesh = qobject_cast(plugin); - if (iIOMesh) - { - iCommon = iIOMesh; - ioMeshPlugins.push_back(iIOMesh); - } - - IORasterPluginInterface* iIORaster = qobject_cast(plugin); - if (iIORaster){ - iCommon = iIORaster; - ioRasterPlugins.push_back(iIORaster); - } - - DecoratePluginInterface *iDecorator = qobject_cast(plugin); - if (iDecorator) - { - iCommon = iDecorator; - meshDecoratePlug.push_back(iDecorator); - for(QAction *decoratorAction : iDecorator->actions()) - { - decoratorActionList.push_back(decoratorAction); - iDecorator->initGlobalParameterList(decoratorAction, defaultGlobal); - } - } - - RenderPluginInterface *iRender = qobject_cast(plugin); - if (iRender) - { - iCommon = iRender; - meshRenderPlug.push_back(iRender); - } - - EditPluginInterfaceFactory *iEditFactory = qobject_cast(plugin); - if (iEditFactory) - { - meshEditInterfacePlug.push_back(iEditFactory); - foreach(QAction* editAction, iEditFactory->actions()) - editActionList.push_back(editAction); - } - else if (iCommon) - { - ownerPlug.push_back(iCommon); - } else { - // qDebug("Plugin %s was loaded, but could not be casted to any known type.", qUtf8Printable(fileName)); - } - } - else - qDebug() << loader.errorString(); - } - fillKnownIOFormats(); -} - -int PluginManager::numberIOPlugins() const -{ - return ioMeshPlugins.size(); -} - -unsigned int PluginManager::size() const -{ - return ownerPlug.size(); -} - -// Search among all the decorator plugins the one that contains a decoration with the given name -DecoratePluginInterface *PluginManager::getDecoratorInterfaceByName(const QString& name) -{ - foreach(DecoratePluginInterface *tt, this->meshDecoratePlugins()) - { - foreach( QAction *ac, tt->actions()) - if( name == tt->decorationName(ac) ) return tt; - } - assert(0); - return 0; -} - -PluginManager::PluginRangeIterator PluginManager::pluginIterator() -{ - return PluginRangeIterator(this); -} - -/* -This function create a map from filtername to dummy RichParameterSet. -containing for each filtername the set of parameter that it uses. -*/ -QMap PluginManager::generateFilterParameterMap() -{ - QMap FPM; - MeshDocument md; - MeshModel* mm = md.addNewMesh("", "dummy", true); - vcg::tri::Tetrahedron(mm->cm); - mm->updateDataMask(MeshModel::MM_ALL); - QMap::iterator ai; - for (ai = this->actionFilterMap.begin(); ai != this->actionFilterMap.end(); ++ai) - { - QString filterName = ai.key();// ->filterName(); - //QAction act(filterName,NULL); - RichParameterList rp; - stringFilterMap[filterName]->initParameterList(ai.value(), md, rp); - FPM[filterName] = rp; - } - return FPM; -} - -QString PluginManager::getBaseDirPath() -{ - QDir baseDir(qApp->applicationDirPath()); - -#if defined(Q_OS_WIN) - // Windows: - // during development with visual studio binary could be in the debug/release subdir. - // once deployed plugins dir is in the application directory, so - if (baseDir.dirName() == "debug" || baseDir.dirName() == "release") baseDir.cdUp(); -#endif - -#if defined(Q_OS_MAC) - // Mac: during developmentwith xcode and well deployed the binary is well buried. - for(int i=0;i<6;++i){ - if(baseDir.exists("plugins")) break; - baseDir.cdUp(); - } - qDebug("The base dir is %s", qUtf8Printable(baseDir.absolutePath())); -#endif - return baseDir.absolutePath(); -} - -QString PluginManager::getDefaultPluginDirPath() -{ - QDir pluginsDir(getBaseDirPath()); -#if defined(Q_OS_WIN) - QString d = pluginsDir.dirName(); - QString dLower = d.toLower(); - if (dLower == "release" || dLower == "relwithdebinfo" || dLower == "debug" || - dLower == "minsizerel") { - // This is a configuration directory for MS Visual Studio. - pluginsDir.cdUp(); - } else { - d.clear(); - } -#endif - if (pluginsDir.exists("plugins")) { - pluginsDir.cd("plugins"); - -#if defined(Q_OS_WIN) - // Re-apply the configuration dir, if any. - if (!d.isEmpty() && pluginsDir.exists(d)) { - pluginsDir.cd(d); - } -#endif - - return pluginsDir.absolutePath(); - } -#if !defined(Q_OS_MAC) && !defined(Q_OS_WIN) - else if (pluginsDir.dirName() == "bin") { - pluginsDir.cdUp(); - pluginsDir.cd("lib"); - pluginsDir.cd("meshlab"); - if (pluginsDir.exists("plugins")) { - pluginsDir.cd("plugins"); - return pluginsDir.absolutePath(); - } - } -#endif - //QMessageBox::warning(0,"Meshlab Initialization","Serious error. Unable to find the plugins directory."); - qDebug("Meshlab Initialization: Serious error. Unable to find the plugins directory."); - return {}; -} - - - -void PluginManager::fillKnownIOFormats() -{ - QString allKnownFormatsFilter = QObject::tr("All known formats ("); - for (IOMeshPluginInterface* pMeshIOPlugin: ioMeshPlugins) { - allKnownFormatsFilter += addPluginMeshFormats(allKnowInputMeshFormats, inpMeshFilters, pMeshIOPlugin, pMeshIOPlugin->importFormats()); - } - allKnownFormatsFilter.append(')'); - inpMeshFilters.push_front(allKnownFormatsFilter); - - for (IOMeshPluginInterface* pMeshIOPlugin: ioMeshPlugins) { - addPluginMeshFormats(allKnowOutputFormats, outFilters, pMeshIOPlugin, pMeshIOPlugin->exportFormats()); - } - - allKnownFormatsFilter = QObject::tr("All known formats ("); - - for (IORasterPluginInterface* pRasterIOPlugin : ioRasterPlugins){ - allKnownFormatsFilter += addPluginRasterFormats(allKnownInputRasterFormats, inpRasterFilters, pRasterIOPlugin, pRasterIOPlugin->importFormats()); - } - - allKnownFormatsFilter.append(')'); - inpRasterFilters.push_front(allKnownFormatsFilter); -} - -QString PluginManager::addPluginRasterFormats( - QMap& map, - QStringList& formatFilters, - IORasterPluginInterface* pRasterIOPlugin, - const QList& format) -{ - QString allKnownFormatsFilter; - for (const FileFormat& currentFormat : format) { - QString currentFilterEntry = currentFormat.description + " ("; - - //a particular file format could be associated with more than one file extension - QStringListIterator itExtension(currentFormat.extensions); - for (QString currentExtension : currentFormat.extensions) { - currentExtension = currentExtension.toLower(); - if (!map.contains(currentExtension)) { - map.insert(currentExtension, pRasterIOPlugin); - allKnownFormatsFilter.append(QObject::tr(" *.")); - allKnownFormatsFilter.append(currentExtension); - } - currentFilterEntry.append(QObject::tr(" *.")); - currentFilterEntry.append(currentExtension); - } - currentFilterEntry.append(')'); - formatFilters.append(currentFilterEntry); - } - return allKnownFormatsFilter; -} - -QString PluginManager::addPluginMeshFormats( - QMap& map, - QStringList& formatFilters, - IOMeshPluginInterface* pMeshIOPlugin, - const QList& format) -{ - QString allKnownFormatsFilter; - for (const FileFormat& currentFormat : format) { - QString currentFilterEntry = currentFormat.description + " ("; - - //a particular file format could be associated with more than one file extension - QStringListIterator itExtension(currentFormat.extensions); - for (QString currentExtension : currentFormat.extensions) { - currentExtension = currentExtension.toLower(); - if (!map.contains(currentExtension)) { - map.insert(currentExtension, pMeshIOPlugin); - allKnownFormatsFilter.append(QObject::tr(" *.")); - allKnownFormatsFilter.append(currentExtension); - } - currentFilterEntry.append(QObject::tr(" *.")); - currentFilterEntry.append(currentExtension); - } - currentFilterEntry.append(')'); - formatFilters.append(currentFilterEntry); - } - return allKnownFormatsFilter; -} - -QString PluginManager::osIndependentPluginName(const QString& plname) -{ - QFileInfo fi(plname); - QString res = fi.baseName(); - QString pref = fileNamePrefixPluginDLLs(); - return res.remove(0, pref.size()); -} - diff --git a/src/common/pluginmanager.h b/src/common/pluginmanager.h deleted file mode 100644 index 4164cba52..000000000 --- a/src/common/pluginmanager.h +++ /dev/null @@ -1,125 +0,0 @@ -/**************************************************************************** -* MeshLab o o * -* A versatile mesh processing toolbox o o * -* _ O _ * -* Copyright(C) 2005 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ - -#ifndef PLUGINMANAGER_H -#define PLUGINMANAGER_H - -#include "interfaces/filter_plugin_interface.h" -#include "interfaces/iomesh_plugin_interface.h" -#include "interfaces/ioraster_plugin_interface.h" -#include "interfaces/render_plugin_interface.h" -#include "interfaces/decorate_plugin_interface.h" -#include "interfaces/edit_plugin_interface.h" - -//#include "scriptsyntax.h" - -#include -#include -#include - -/** -\brief This class provides the basic tools for managing all the plugins. It is used by both meshlab and meshlab server. -*/ -class PluginManager -{ -public: - PluginManager(); - ~PluginManager(); - void loadPlugins(RichParameterList& defaultGlobal); - void loadPlugins(RichParameterList& defaultGlobal, const QDir& pluginsDirectory); - QString pluginsCode() const; - - int numberIOPlugins() const; - unsigned int size() const; - inline QVector& meshFilterPlugins() {return meshFilterPlug;} - inline QVector& meshRenderPlugins() {return meshRenderPlug;} - inline QVector& meshDecoratePlugins() {return meshDecoratePlug;} - inline QVector& meshEditFactoryPlugins() {return meshEditInterfacePlug;} - - static QString getDefaultPluginDirPath(); - static QString getBaseDirPath(); - - QMap generateFilterParameterMap(); - - DecoratePluginInterface* getDecoratorInterfaceByName(const QString& name); - - class PluginRangeIterator - { - friend class PluginManager; - public: - QVector::iterator begin() {return pm->ownerPlug.begin();} - QVector::iterator end() {return pm->ownerPlug.end();} - private: - PluginRangeIterator(PluginManager* pm) : pm(pm) {} - PluginManager* pm; - }; - - PluginRangeIterator pluginIterator(); - - static QString osIndependentPluginName(const QString& plname); - - QMap actionFilterMap; - QMap stringFilterMap; - QMap allKnowInputMeshFormats; - QMap allKnowOutputFormats; - QMap allKnownInputRasterFormats; - QStringList inpMeshFilters; - QStringList inpRasterFilters; - QStringList outFilters; - - - QVector meshFilterPlug; - QVector meshRenderPlug; - QVector meshDecoratePlug; - QVector meshEditInterfacePlug; - QVector editActionList; - QVector decoratorActionList; - // Used for unique destruction - this "owns" all IO, Filter, Render, and Decorate plugins - - QStringList pluginsLoaded; - - - -private: - QVector ownerPlug; - QVector ioMeshPlugins; - QVector ioRasterPlugins; - QDir pluginsDir; - - - void fillKnownIOFormats(); - - QString addPluginRasterFormats( - QMap& map, - QStringList& formatFilters, - IORasterPluginInterface* pRasterIOPlugin, - const QList& format); - - QString addPluginMeshFormats( - QMap& map, - QStringList& formatFilters, - IOMeshPluginInterface* pMeshIOPlugin, - const QList& format); -}; - -#endif // PLUGINMANAGER_H diff --git a/src/common/plugins/action_searcher.cpp b/src/common/plugins/action_searcher.cpp new file mode 100644 index 000000000..1799de16c --- /dev/null +++ b/src/common/plugins/action_searcher.cpp @@ -0,0 +1,175 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2005-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "action_searcher.h" + +#include +#include + +#include "interfaces/filter_plugin.h" + +ActionSearcher::ActionSearcher() +{ +} + +void ActionSearcher::clear() +{ + titleActionsMap.clear(); +} + +/** + * @brief Adds the given action to the ActionSearcher, allowing queries to it. + * @param action + */ +void ActionSearcher::addAction(QAction *action, bool usePythonFilterNames) +{ + if (action != nullptr) { + + // add title to the action map + QString title = action->text(); + title = title.toLower(); + title.remove(ignexp); + QStringList res = title.split(sepexp, Qt::SkipEmptyParts); + res.removeDuplicates(); + addSubStrings(res); + for (const QString& str : qAsConst(res)) { + titleActionsMap[str].push_back(action); + } + if (usePythonFilterNames) { + // if the action is a filter, we should add also the python name to the search + QObject* parent = action->parent(); + FilterPlugin* fp = qobject_cast(parent); + if (fp) { + QString title = fp->pythonFilterName(action); + title.replace("_", " "); + title.remove(ignexp); + QStringList res = title.split(sepexp, Qt::SkipEmptyParts); + res.removeDuplicates(); + addSubStrings(res); + for (const QString& str : qAsConst(res)) { + titleActionsMap[str].push_back(action); + } + } + } + + // add info to the action map + QString info = action->toolTip(); + info = info.toLower(); + info.remove(ignexp); + res = info.split(sepexp, Qt::SkipEmptyParts); + res.removeDuplicates(); + addSubStrings(res); + for (const QString& str : qAsConst(res)) { + infoActionsMap[str].push_back(action); + } + } +} + +/** + * @brief Performs a query using the inputString and returns an array containing the best matching + * actions matching to the input string. + * + * The array will have maximum size equal to maxNumberactions. + * @param inputString: query string + * @param maxNumberActions: maximum size of the output array + * @return array containing the best matching actions + */ +std::vector ActionSearcher::bestMatchingActions(QString inputString, int maxNumberActions) const +{ + std::vector res; + + // clean the input string + inputString = inputString.toLower(); + inputString.replace("_", " "); // to allow python search + inputString.remove(ignexp); + + // split the input string + QStringList inputList = inputString.split(sepexp, Qt::SkipEmptyParts); + inputList.removeDuplicates(); + + const float bonuspertitleword = 1.0f / std::pow(10,inputList.size()); + + // store the ranking for each action + std::map actionRanking; + + // for each input string + for (const QString& str : qAsConst(inputList)) { + auto it = titleActionsMap.find(str); + // if matches in a title of an action + if (it != titleActionsMap.end()) { + for (QAction* act : it->second) { // for each matching action, increment its ranking + actionRanking[act] += bonuspertitleword; + } + } + it = infoActionsMap.find(str); + // if matches in a info of an action + if (it != infoActionsMap.end()) { + for (QAction* act : it->second) { // for each matching action, increment its ranking + actionRanking[act]++; + } + } + } + + std::map> rankingMap; // flipped map of actionRanking + // populate the flipped map + for (const auto& p : actionRanking) { + // for each ranking, push another action havint that ranking + rankingMap[p.second].push_back(p.first); + } + // at the end, the map will store the actions stored by ranking + + int count = 0; // used to stop the number of inserted actions in the resulting vector + + // reverse iteration: start from the biggest ranking + for (auto it = rankingMap.rbegin(); it != rankingMap.rend() && count < maxNumberActions; ++it) { + auto v1 = it->second; + // need to sort properly actions having the same ranking, since they would be sorted using + // memory addresses, that are not deterministic: we use action titles + std::sort(v1.begin(), v1.end(), ActionComparator()); + // insert the sorted actions to the result vector + res.insert(res.end(), v1.begin(), v1.end()); + count += it->second.size(); + } + // if at the end the number exceeded the maximum number, we truncate the array + if (count >= maxNumberActions) { + res.resize(maxNumberActions); + } + return res; +} + +void ActionSearcher::addSubStrings(QStringList &res) +{ + QStringList resWithPrefix; + foreach(QString str, res) + { + QString strPref = str; + resWithPrefix.push_back(strPref); + for(int i=0;i +#include +#include +#include + +class ActionSearcher +{ +public: + ActionSearcher(); + + void clear(); + void addAction(QAction* action, bool usePythonFilterNames = false); + + std::vector bestMatchingActions(QString inputString, int maxNumberActions) const; + +private: + const QRegExp sepexp = QRegExp("\\W+"); + const QRegExp ignexp = QRegExp( + "\\b(an|the|of|it|as|in|by|and|or|for)\\b|\\b[a-z]\\b|'s\\b|\\.|<[^>]*>"); + + // map that stores, for each string, all the actions that store that string in their titles + std::map> titleActionsMap; + + // map that stores, for each string, all the actions that store that string in their info + std::map> infoActionsMap; + + struct ActionComparator { + bool operator()(QAction* a1, QAction* a2) { + return a1->text() < a2->text(); + } + }; + + static void addSubStrings(QStringList& res); +}; + +#endif // ACTION_SEARCHER_H diff --git a/src/common/plugins/containers/decorate_plugin_container.cpp b/src/common/plugins/containers/decorate_plugin_container.cpp new file mode 100644 index 000000000..2689ef77c --- /dev/null +++ b/src/common/plugins/containers/decorate_plugin_container.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "decorate_plugin_container.h" + +DecoratePluginContainer::DecoratePluginContainer() +{ +} + +void DecoratePluginContainer::clear() +{ + decoratePlugins.clear(); +} + +void DecoratePluginContainer::pushDecoratePlugin(DecoratePlugin* iDecorate) +{ + decoratePlugins.push_back(iDecorate); +} + +void DecoratePluginContainer::eraseDecoratePlugin(DecoratePlugin* iDecorate) +{ + decoratePlugins.erase(std::find(decoratePlugins.begin(), decoratePlugins.end(), iDecorate)); +} + +DecoratePlugin* DecoratePluginContainer::decoratePlugin(const QString& name) +{ + for(DecoratePlugin *tt : decoratePlugins) { + for( QAction *ac: tt->actions()) + if( name == tt->decorationName(ac) ) return tt; + } + return nullptr; +} + +DecoratePluginContainer::DecoratePluginRangeIterator DecoratePluginContainer::decoratePluginIterator(bool iterateAlsoDisabledPlugins) const +{ + return DecoratePluginRangeIterator(this, iterateAlsoDisabledPlugins); +} diff --git a/src/common/plugins/containers/decorate_plugin_container.h b/src/common/plugins/containers/decorate_plugin_container.h new file mode 100644 index 000000000..5cc034324 --- /dev/null +++ b/src/common/plugins/containers/decorate_plugin_container.h @@ -0,0 +1,67 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef MESHLAB_DECORATE_PLUGIN_CONTAINER_H +#define MESHLAB_DECORATE_PLUGIN_CONTAINER_H + +#include "../interfaces/decorate_plugin.h" +#include "generic_container_iterator.h" + +/** + * @brief The DecoratePluginContainer class allows to organize + * all the decorate plugins contained in the PluginManager. + * + * Note: plugins are not owned by this container, but by the PluginManager, + * since each plugin can inherit from more than one PluginInterface. + */ +class DecoratePluginContainer +{ +public: + class DecoratePluginRangeIterator; + DecoratePluginContainer(); + + void clear(); + void pushDecoratePlugin(DecoratePlugin* iDecorate); + void eraseDecoratePlugin(DecoratePlugin* iDecorate); + + DecoratePlugin* decoratePlugin(const QString& name); + + DecoratePluginRangeIterator decoratePluginIterator(bool iterateAlsoDisabledPlugins = false) const; + +private: + std::vector decoratePlugins; +}; + +class DecoratePluginContainer::DecoratePluginRangeIterator +{ + friend class DecoratePluginContainer; +public: + ConstPluginIterator begin() {return ConstPluginIterator(pm->decoratePlugins, pm->decoratePlugins.begin(), b);} + ConstPluginIterator end() {return ConstPluginIterator(pm->decoratePlugins, pm->decoratePlugins.end(), b);} +private: + DecoratePluginRangeIterator(const DecoratePluginContainer* pm, bool iterateAlsoDisabledPlugins = false) : pm(pm), b(iterateAlsoDisabledPlugins) {} + const DecoratePluginContainer* pm; + bool b; +}; + +#endif // MESHLAB_DECORATE_PLUGIN_CONTAINER_H diff --git a/src/common/plugins/containers/edit_plugin_container.cpp b/src/common/plugins/containers/edit_plugin_container.cpp new file mode 100644 index 000000000..44be6e233 --- /dev/null +++ b/src/common/plugins/containers/edit_plugin_container.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "edit_plugin_container.h" + +EditPluginContainer::EditPluginContainer() +{ +} + +void EditPluginContainer::clear() +{ + editPlugins.clear(); +} + +void EditPluginContainer::pushEditPlugin(EditPlugin* iEditFactory) +{ + editPlugins.push_back(iEditFactory); +} + +void EditPluginContainer::eraseEditPlugin(EditPlugin* iEditFactory) +{ + editPlugins.erase(std::find(editPlugins.begin(), editPlugins.end(), iEditFactory)); +} + +EditPluginContainer::EditPluginFactoryRangeIterator EditPluginContainer::editPluginIterator(bool iterateAlsoDisabledPlugins) const +{ + return EditPluginFactoryRangeIterator(this, iterateAlsoDisabledPlugins); +} + +ConstPluginIterator EditPluginContainer::EditPluginFactoryRangeIterator::begin() +{ + return ConstPluginIterator(pm->editPlugins, pm->editPlugins.begin(), b); +} + +ConstPluginIterator EditPluginContainer::EditPluginFactoryRangeIterator::end() +{ + return ConstPluginIterator(pm->editPlugins, pm->editPlugins.end(), b); +} + +EditPluginContainer::EditPluginFactoryRangeIterator::EditPluginFactoryRangeIterator( + const EditPluginContainer* pm, + bool iterateAlsoDisabledPlugins) : + pm(pm), b(iterateAlsoDisabledPlugins) +{ +} diff --git a/src/common/plugins/containers/edit_plugin_container.h b/src/common/plugins/containers/edit_plugin_container.h new file mode 100644 index 000000000..9122b0abd --- /dev/null +++ b/src/common/plugins/containers/edit_plugin_container.h @@ -0,0 +1,64 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef MESHLAB_EDIT_PLUGIN_CONTAINER_H +#define MESHLAB_EDIT_PLUGIN_CONTAINER_H + +#include "../interfaces/edit_plugin.h" +#include "generic_container_iterator.h" + +/** + * @brief The EditPluginContainer class allows to organize + * all the edit plugins contained in the PluginManager. + * + * Note: plugins are not owned by this container, but by the PluginManager, + * since each plugin can inherit from more than one PluginInterface. + */ +class EditPluginContainer +{ +public: + class EditPluginFactoryRangeIterator; + EditPluginContainer(); + + void clear(); + void pushEditPlugin(EditPlugin* iEditFactory); + void eraseEditPlugin(EditPlugin* iEditFactory); + + EditPluginFactoryRangeIterator editPluginIterator(bool iterateAlsoDisabledPlugins = false) const; +private: + std::vector editPlugins; +}; + +class EditPluginContainer::EditPluginFactoryRangeIterator +{ + friend class EditPluginContainer; +public: + ConstPluginIterator begin(); + ConstPluginIterator end(); +private: + EditPluginFactoryRangeIterator(const EditPluginContainer* pm, bool iterateAlsoDisabledPlugins = false); + const EditPluginContainer* pm; + bool b; +}; + +#endif // MESHLAB_EDIT_PLUGIN_CONTAINER_H diff --git a/src/common/plugins/containers/filter_plugin_container.cpp b/src/common/plugins/containers/filter_plugin_container.cpp new file mode 100644 index 000000000..a0244fc53 --- /dev/null +++ b/src/common/plugins/containers/filter_plugin_container.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "filter_plugin_container.h" + +FilterPluginContainer::FilterPluginContainer() +{ +} + +void FilterPluginContainer::clear() +{ + filterPlugins.clear(); + actionFilterMap.clear(); +} + +void FilterPluginContainer::pushFilterPlugin( + FilterPlugin* iFilter) +{ + for(QAction *filterAction : iFilter->actions()) { + filterAction->setData(QVariant(iFilter->pluginName())); + actionFilterMap.insert(filterAction->text(), filterAction); + } + filterPlugins.push_back(iFilter); +} + +void FilterPluginContainer::eraseFilterPlugin( + FilterPlugin* iFilter) +{ + for(QAction *filterAction : iFilter->actions()) { + actionFilterMap.remove(filterAction->text()); + } + filterPlugins.erase(std::find(filterPlugins.begin(), filterPlugins.end(), iFilter)); +} + +QAction* FilterPluginContainer::filterAction(const QString& name) +{ + auto it = actionFilterMap.find(name); + if (it != actionFilterMap.end()) + return it.value(); + else + return nullptr; +} + +FilterPlugin *FilterPluginContainer::pluginOfFilter(const QAction *action) const +{ + for (FilterPlugin* fp : filterPlugins) { + std::list al = fp->actions(); + auto it = std::find(al.begin(), al.end(), action); + if (it != al.end()) + return fp; + } + return nullptr; +} + +FilterPluginContainer::FilterPluginRangeIterator FilterPluginContainer::filterPluginIterator(bool iterateAlsoDisabledPlugins) const +{ + return FilterPluginRangeIterator(this, iterateAlsoDisabledPlugins); +} + +ConstPluginIterator FilterPluginContainer::FilterPluginRangeIterator::begin() +{ + return ConstPluginIterator(pm->filterPlugins, pm->filterPlugins.begin(), b); +} + +ConstPluginIterator FilterPluginContainer::FilterPluginRangeIterator::end() +{ + return ConstPluginIterator(pm->filterPlugins, pm->filterPlugins.end(), b); +} + +FilterPluginContainer::FilterPluginRangeIterator::FilterPluginRangeIterator( + const FilterPluginContainer* pm, + bool iterateAlsoDisabledPlugins) : + pm(pm), b(iterateAlsoDisabledPlugins) +{ +} diff --git a/src/common/plugins/containers/filter_plugin_container.h b/src/common/plugins/containers/filter_plugin_container.h new file mode 100644 index 000000000..b6c684f66 --- /dev/null +++ b/src/common/plugins/containers/filter_plugin_container.h @@ -0,0 +1,71 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef MESHLAB_FILTER_PLUGIN_CONTAINER_H +#define MESHLAB_FILTER_PLUGIN_CONTAINER_H + +#include "../interfaces/filter_plugin.h" +#include "generic_container_iterator.h" + +/** + * @brief The FilterPluginContainer class allows to organize + * all the filter plugins contained in the PluginManager. + * + * Note: plugins are not owned by this container, but by the PluginManager, + * since each plugin can inherit from more than one PluginInterface. + */ +class FilterPluginContainer +{ +public: + class FilterPluginRangeIterator; + FilterPluginContainer(); + + void clear(); + void pushFilterPlugin(FilterPlugin* iFilter); + void eraseFilterPlugin(FilterPlugin* iFilter); + + QAction* filterAction(const QString& name); + FilterPlugin* pluginOfFilter(const QAction* action) const; + + FilterPluginRangeIterator filterPluginIterator(bool iterateAlsoDisabledPlugins = false) const; + +private: + std::vector filterPlugins; + QMap actionFilterMap; +}; + +class FilterPluginContainer::FilterPluginRangeIterator +{ + friend class FilterPluginContainer; +public: + ConstPluginIterator begin(); + ConstPluginIterator end(); +private: + FilterPluginRangeIterator( + const FilterPluginContainer* pm, + bool iterateAlsoDisabledPlugins = false); + const FilterPluginContainer* pm; + bool b; +}; + +#endif // MESHLAB_FILTER_PLUGIN_CONTAINER_H diff --git a/src/common/interfaces/ioraster_plugin_interface.h b/src/common/plugins/containers/generic_container_iterator.h similarity index 52% rename from src/common/interfaces/ioraster_plugin_interface.h rename to src/common/plugins/containers/generic_container_iterator.h index a68dde221..40a761a27 100644 --- a/src/common/interfaces/ioraster_plugin_interface.h +++ b/src/common/plugins/containers/generic_container_iterator.h @@ -2,7 +2,7 @@ * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * -* Copyright(C) 2005-2020 \/)\/ * +* Copyright(C) 2005-2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -21,48 +21,51 @@ * * ****************************************************************************/ -#ifndef MESHLAB_IORASTER_PLUGIN_INTERFACE_H -#define MESHLAB_IORASTER_PLUGIN_INTERFACE_H +#ifndef MESHLAB_GENERIC_CONTAINER_ITERATOR_H +#define MESHLAB_GENERIC_CONTAINER_ITERATOR_H -#include "plugin_interface.h" -#include "../utilities/file_format.h" -#include "../ml_document/raster_model.h" +#include -class IORasterPluginInterface : public PluginInterface +template +class ConstPluginIterator { public: - IORasterPluginInterface() : PluginInterface() {} - virtual ~IORasterPluginInterface() {} - - virtual QList importFormats() const = 0; - - virtual bool open( - const QString& format, - const QString& filename, - RasterModel& rm, - vcg::CallBackPos* cb = nullptr) = 0; + using Container = std::vector; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = PluginType*; + using pointer = typename Container::const_iterator; + using reference = PluginType*&; - /// This function is invoked by the framework when the import/export plugin fails to give some info to the user about the failure - /// io plugins should avoid using QMessageBox for reporting errors. - /// Failure should put some meaningful information inside the errorMessage string. - const QString& errorMsg() const + ConstPluginIterator( + const Container& c, + const pointer& it, + bool iterateAlsoDisabledPlugins = false) + : c(c), m_ptr(it), iterateAlsoDisabledPlugins(iterateAlsoDisabledPlugins) { - return errorMessage; + if (m_ptr != c.end() && !iterateAlsoDisabledPlugins && !(*m_ptr)->isEnabled()) + ++(*this); } - void clearErrorString() - { - errorMessage.clear(); + value_type operator*() const {return *m_ptr; } + pointer operator->() { return m_ptr; } + ConstPluginIterator& operator++() { + if (iterateAlsoDisabledPlugins) + m_ptr++; + else { + do { + m_ptr++; + } while((m_ptr != c.end()) && !(*m_ptr)->isEnabled()); + } + return *this; } -protected: - // this string is used to pass back to the framework error messages in case of failure of a filter apply. - // NEVER EVER use a msgbox to say something to the user. - QString errorMessage; + ConstPluginIterator operator++(int) {ConstPluginIterator tmp = *this; ++(*this); return tmp; } + friend bool operator== (const ConstPluginIterator& a, const ConstPluginIterator& b) { return a.m_ptr == b.m_ptr; }; + friend bool operator!= (const ConstPluginIterator& a, const ConstPluginIterator& b) { return a.m_ptr != b.m_ptr; }; + +private: + const Container& c; + pointer m_ptr; + bool iterateAlsoDisabledPlugins; }; -#define MESHLAB_PLUGIN_IID_EXPORTER(x) Q_PLUGIN_METADATA(IID x) -#define MESHLAB_PLUGIN_NAME_EXPORTER(x) - -#define IORASTER_PLUGIN_INTERFACE_IID "vcg.meshlab.IORasterPluginInterface/1.0" -Q_DECLARE_INTERFACE(IORasterPluginInterface, IORASTER_PLUGIN_INTERFACE_IID) - -#endif // MESHLAB_IORASTER_PLUGIN_INTERFACE_H +#endif // MESHLAB_GENERIC_CONTAINER_ITERATOR_H diff --git a/src/common/plugins/containers/io_plugin_container.cpp b/src/common/plugins/containers/io_plugin_container.cpp new file mode 100644 index 000000000..f320b7181 --- /dev/null +++ b/src/common/plugins/containers/io_plugin_container.cpp @@ -0,0 +1,227 @@ +#include "io_plugin_container.h" + +IOPluginContainer::IOPluginContainer() +{ +} + +size_t IOPluginContainer::size() const +{ + return ioPlugins.size(); +} + +void IOPluginContainer::clear() +{ + ioPlugins.clear(); + inputMeshFormatToPluginMap.clear(); + outputMeshFormatToPluginMap.clear(); + inputImageFormatToPluginMap.clear(); +} + +void IOPluginContainer::pushIOPlugin(IOPlugin* iIO) +{ + ioPlugins.push_back(iIO); + + //add input formats to inputFormatMap + for (const FileFormat& ff : iIO->importFormats()){ + for (const QString& currentExtension : ff.extensions) { + if (! inputMeshFormatToPluginMap.contains(currentExtension.toLower())) { + inputMeshFormatToPluginMap.insert(currentExtension.toLower(), iIO); + } + } + } + + //add output formats to outputFormatMap + for (const FileFormat& ff : iIO->exportFormats()){ + for (const QString& currentExtension : ff.extensions) { + if (! outputMeshFormatToPluginMap.contains(currentExtension.toLower())) { + outputMeshFormatToPluginMap.insert(currentExtension.toLower(), iIO); + } + } + } + + //add input image formats to inputFormatMap + for (const FileFormat& ff : iIO->importImageFormats()){ + for (const QString& currentExtension : ff.extensions) { + if (! inputImageFormatToPluginMap.contains(currentExtension.toLower())) { + inputImageFormatToPluginMap.insert(currentExtension.toLower(), iIO); + } + } + } + + //add output image formats to inputFormatMap + for (const FileFormat& ff : iIO->exportImageFormats()){ + for (const QString& currentExtension : ff.extensions) { + if (! outputImageFormatToPluginMap.contains(currentExtension.toLower())) { + outputImageFormatToPluginMap.insert(currentExtension.toLower(), iIO); + } + } + } + + //add input project formats to inputFormatMap + for (const FileFormat& ff : iIO->importProjectFormats()){ + for (const QString& currentExtension : ff.extensions) { + if (! inputProjectFormatToPluginMap.contains(currentExtension.toLower())) { + inputProjectFormatToPluginMap.insert(currentExtension.toLower(), iIO); + } + } + } + + //add output project formats to inputFormatMap + for (const FileFormat& ff : iIO->exportProjectFormats()){ + for (const QString& currentExtension : ff.extensions) { + if (! outputProjectFormatToPluginMap.contains(currentExtension.toLower())) { + outputProjectFormatToPluginMap.insert(currentExtension.toLower(), iIO); + } + } + } +} + +void IOPluginContainer::eraseIOPlugin(IOPlugin* iIO) +{ + ioPlugins.erase(std::find(ioPlugins.begin(), ioPlugins.end(), iIO)); + for (const FileFormat& ff : iIO->importFormats()){ + for (const QString& currentExtension : ff.extensions) { + inputMeshFormatToPluginMap.remove(currentExtension.toLower()); + } + } + for (const FileFormat& ff : iIO->exportFormats()){ + for (const QString& currentExtension : ff.extensions) { + outputMeshFormatToPluginMap.remove(currentExtension.toLower()); + } + } + for (const FileFormat& ff : iIO->importImageFormats()){ + for (const QString& currentExtension : ff.extensions) { + inputImageFormatToPluginMap.remove(currentExtension.toLower()); + } + } +} + +bool IOPluginContainer::isInputMeshFormatSupported(const QString& inputFormat) const +{ + return inputMeshFormatToPluginMap.find(inputFormat.toLower()) != inputMeshFormatToPluginMap.end(); +} + +bool IOPluginContainer::isOutputMeshFormatSupported(const QString& outputFormat) const +{ + return outputMeshFormatToPluginMap.find(outputFormat.toLower()) != outputMeshFormatToPluginMap.end(); +} + +bool IOPluginContainer::isInputImageFormatSupported(const QString& inputFormat) const +{ + return inputImageFormatToPluginMap.find(inputFormat.toLower()) != inputImageFormatToPluginMap.end(); +} + +bool IOPluginContainer::isOutputImageFormatSupported(const QString& outputFormat) const +{ + return outputImageFormatToPluginMap.find(outputFormat.toLower()) != outputImageFormatToPluginMap.end(); +} + +bool IOPluginContainer::isInputProjectFormatSupported(const QString& inputFormat) const +{ + return inputProjectFormatToPluginMap.find(inputFormat.toLower()) != inputProjectFormatToPluginMap.end(); +} + +bool IOPluginContainer::isOutputProjectFormatSupported(const QString& outputFormat) const +{ + return outputImageFormatToPluginMap.find(outputFormat.toLower()) != outputProjectFormatToPluginMap.end(); +} + +IOPlugin* IOPluginContainer::inputMeshPlugin(const QString& inputFormat) const +{ + auto it = inputMeshFormatToPluginMap.find(inputFormat.toLower()); + if (it != inputMeshFormatToPluginMap.end()) + return *it; + return nullptr; +} + +IOPlugin* IOPluginContainer::outputMeshPlugin(const QString& outputFormat) const +{ + auto it = outputMeshFormatToPluginMap.find(outputFormat.toLower()); + if (it != outputMeshFormatToPluginMap.end()) + return *it; + return nullptr; +} + +IOPlugin* IOPluginContainer::inputImagePlugin(const QString& inputFormat) const +{ + auto it = inputImageFormatToPluginMap.find(inputFormat.toLower()); + if (it != inputImageFormatToPluginMap.end()) + return *it; + return nullptr; +} + +IOPlugin* IOPluginContainer::outputImagePlugin(const QString& outputFormat) const +{ + auto it = outputImageFormatToPluginMap.find(outputFormat.toLower()); + if (it != outputImageFormatToPluginMap.end()) + return *it; + return nullptr; +} + +IOPlugin* IOPluginContainer::inputProjectPlugin(const QString& inputFormat) const +{ + auto it = inputProjectFormatToPluginMap.find(inputFormat.toLower()); + if (it != inputProjectFormatToPluginMap.end()) + return *it; + return nullptr; +} + +IOPlugin* IOPluginContainer::outputProjectPlugin(const QString& outputFormat) const +{ + auto it = outputProjectFormatToPluginMap.find(outputFormat.toLower()); + if (it != outputProjectFormatToPluginMap.end()) + return *it; + return nullptr; +} + +QStringList IOPluginContainer::inputMeshFormatList() const +{ + return inputMeshFormatToPluginMap.keys(); +} + +QStringList IOPluginContainer::outputMeshFormatList() const +{ + return outputMeshFormatToPluginMap.keys(); +} + +QStringList IOPluginContainer::inputImageFormatList() const +{ + return inputImageFormatToPluginMap.keys(); +} + +QStringList IOPluginContainer::outputImageFormatList() const +{ + return outputImageFormatToPluginMap.keys(); +} + +QStringList IOPluginContainer::inputProjectFormatList() const +{ + return inputProjectFormatToPluginMap.keys(); +} + +QStringList IOPluginContainer::outputProjectFormatList() const +{ + return outputProjectFormatToPluginMap.keys(); +} + +IOPluginContainer::IOPluginRangeIterator IOPluginContainer::ioPluginIterator(bool iterateAlsoDisabledPlugins) const +{ + return IOPluginRangeIterator(this, iterateAlsoDisabledPlugins); +} + +ConstPluginIterator IOPluginContainer::IOPluginRangeIterator::begin() +{ + return ConstPluginIterator(pm->ioPlugins, pm->ioPlugins.begin(), b); +} + +ConstPluginIterator IOPluginContainer::IOPluginRangeIterator::end() +{ + return ConstPluginIterator(pm->ioPlugins, pm->ioPlugins.end(), b); +} + +IOPluginContainer::IOPluginRangeIterator::IOPluginRangeIterator( + const IOPluginContainer* pm, + bool iterateAlsoDisabledPlugins) : + pm(pm), b(iterateAlsoDisabledPlugins) +{ +} diff --git a/src/common/plugins/containers/io_plugin_container.h b/src/common/plugins/containers/io_plugin_container.h new file mode 100644 index 000000000..d9266a429 --- /dev/null +++ b/src/common/plugins/containers/io_plugin_container.h @@ -0,0 +1,95 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef MESHLAB_IO_PLUGIN_CONTAINER_H +#define MESHLAB_IO_PLUGIN_CONTAINER_H + +#include "../interfaces/io_plugin.h" +#include "generic_container_iterator.h" + +/** + * @brief The IOPluginContainer class allows to organize + * all the IO plugins contained in the PluginManager. + * + * Note: plugins are not owned by this container, but by the PluginManager, + * since each plugin can inherit from more than one PluginInterface. + */ +class IOPluginContainer +{ +public: + class IOPluginRangeIterator; + IOPluginContainer(); + + size_t size() const; + void clear(); + void pushIOPlugin(IOPlugin* iIO); + void eraseIOPlugin(IOPlugin* iIO); + + bool isInputMeshFormatSupported(const QString& inputFormat) const; + bool isOutputMeshFormatSupported(const QString& outputFormat) const; + bool isInputImageFormatSupported(const QString& inputFormat) const; + bool isOutputImageFormatSupported(const QString& outputFormat) const; + bool isInputProjectFormatSupported(const QString& inputFormat) const; + bool isOutputProjectFormatSupported(const QString& outputFormat) const; + IOPlugin* inputMeshPlugin(const QString& inputFormat) const; + IOPlugin* outputMeshPlugin(const QString& outputFormat) const; + IOPlugin* inputImagePlugin(const QString& inputFormat) const; + IOPlugin* outputImagePlugin(const QString& outputFormat) const; + IOPlugin* inputProjectPlugin(const QString& inputFormat) const; + IOPlugin* outputProjectPlugin(const QString& outputFormat) const; + + + QStringList inputMeshFormatList() const; + QStringList outputMeshFormatList() const; + QStringList inputImageFormatList() const; + QStringList outputImageFormatList() const; + QStringList inputProjectFormatList() const; + QStringList outputProjectFormatList() const; + + IOPluginRangeIterator ioPluginIterator(bool iterateAlsoDisabledPlugins = false) const; + +private: + std::vector ioPlugins; + QMap inputMeshFormatToPluginMap; + QMap outputMeshFormatToPluginMap; + QMap inputImageFormatToPluginMap; + QMap outputImageFormatToPluginMap; + QMap inputProjectFormatToPluginMap; + QMap outputProjectFormatToPluginMap; +}; + +class IOPluginContainer::IOPluginRangeIterator +{ + friend class IOPluginContainer; +public: + ConstPluginIterator begin(); + ConstPluginIterator end(); +private: + IOPluginRangeIterator( + const IOPluginContainer* pm, + bool iterateAlsoDisabledPlugins = false); + const IOPluginContainer* pm; + bool b; +}; + +#endif // MESHLAB_IO_PLUGIN_CONTAINER_H diff --git a/src/common/plugins/containers/render_plugin_container.cpp b/src/common/plugins/containers/render_plugin_container.cpp new file mode 100644 index 000000000..143b7ff21 --- /dev/null +++ b/src/common/plugins/containers/render_plugin_container.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "render_plugin_container.h" + +RenderPluginContainer::RenderPluginContainer() +{ +} + +void RenderPluginContainer::clear() +{ + renderPlugins.clear(); +} + +void RenderPluginContainer::pushRenderPlugin(RenderPlugin* iRender) +{ + renderPlugins.push_back(iRender); +} + +void RenderPluginContainer::eraseRenderPlugin(RenderPlugin* iRender) +{ + renderPlugins.erase(std::find(renderPlugins.begin(), renderPlugins.end(), iRender)); +} + +RenderPluginContainer::RenderPluginRangeIterator RenderPluginContainer::renderPluginIterator(bool iterateAlsoDisabledPlugins) const +{ + return RenderPluginRangeIterator(this, iterateAlsoDisabledPlugins); +} + +ConstPluginIterator RenderPluginContainer::RenderPluginRangeIterator::begin() +{ + return ConstPluginIterator(pm->renderPlugins, pm->renderPlugins.begin(), b); +} + +ConstPluginIterator RenderPluginContainer::RenderPluginRangeIterator::end() +{ + return ConstPluginIterator(pm->renderPlugins, pm->renderPlugins.end(), b); +} + +RenderPluginContainer::RenderPluginRangeIterator::RenderPluginRangeIterator( + const RenderPluginContainer* pm, + bool iterateAlsoDisabledPlugins) : + pm(pm), b(iterateAlsoDisabledPlugins) +{ +} diff --git a/src/common/plugins/containers/render_plugin_container.h b/src/common/plugins/containers/render_plugin_container.h new file mode 100644 index 000000000..333d8578a --- /dev/null +++ b/src/common/plugins/containers/render_plugin_container.h @@ -0,0 +1,66 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef MESHLAB_RENDER_PLUGIN_CONTAINER_H +#define MESHLAB_RENDER_PLUGIN_CONTAINER_H + +#include "../interfaces/render_plugin.h" +#include "generic_container_iterator.h" + +/** + * @brief The RenderPluginContainer class allows to organize + * all the render plugins contained in the PluginManager. + * + * Note: plugins are not owned by this container, but by the PluginManager, + * since each plugin can inherit from more than one PluginInterface. + */ +class RenderPluginContainer +{ +public: + class RenderPluginRangeIterator; + RenderPluginContainer(); + + void clear(); + void pushRenderPlugin(RenderPlugin* iRender); + void eraseRenderPlugin(RenderPlugin* iRender); + + RenderPluginRangeIterator renderPluginIterator(bool iterateAlsoDisabledPlugins = false) const; +private: + std::vector renderPlugins; +}; + +class RenderPluginContainer::RenderPluginRangeIterator +{ + friend class RenderPluginContainer; +public: + ConstPluginIterator begin(); + ConstPluginIterator end(); +private: + RenderPluginRangeIterator( + const RenderPluginContainer* pm, + bool iterateAlsoDisabledPlugins = false); + const RenderPluginContainer* pm; + bool b; +}; + +#endif // MESHLAB_RENDER_PLUGIN_CONTAINER_H diff --git a/src/common/interfaces/decorate_plugin_interface.cpp b/src/common/plugins/interfaces/decorate_plugin.cpp similarity index 82% rename from src/common/interfaces/decorate_plugin_interface.cpp rename to src/common/plugins/interfaces/decorate_plugin.cpp index 69b07a0a4..b4288f19f 100644 --- a/src/common/interfaces/decorate_plugin_interface.cpp +++ b/src/common/plugins/interfaces/decorate_plugin.cpp @@ -1,4 +1,4 @@ -#include "decorate_plugin_interface.h" +#include "decorate_plugin.h" /** \brief * This function is called by the framework, for each plugin that has global parameters (e.g. \ref MeshDecorateInterface) at the start of the application. @@ -26,30 +26,30 @@ * At the start up the initGlobalParameterList function is called with an empty RichParameterList (to collect the default values) * If a filter wants to save some permanent stuff should set the permanent default values. */ -void DecoratePluginInterface::initGlobalParameterList(const QAction* /*format*/, RichParameterList& /*globalparam*/) +void DecoratePlugin::initGlobalParameterList(const QAction* /*format*/, RichParameterList& /*globalparam*/) { } -QAction* DecoratePluginInterface::action(QString name) const +QAction* DecoratePlugin::action(QString name) const { QString n = name; - foreach(QAction *tt, actions()) + for(QAction *tt : actions()) if (name == this->decorationName(ID(tt))) return tt; n.replace("&",""); - foreach(QAction *tt, actions()) + for(QAction *tt : actions()) if (n == this->decorationName(ID(tt))) return tt; qDebug("unable to find the id corresponding to action '%s'", qUtf8Printable(name)); return 0; } -PluginInterface::FilterIDType DecoratePluginInterface::ID(const QAction* a) const +MeshLabPlugin::ActionIDType DecoratePlugin::ID(const QAction* a) const { QString aa=a->text(); - foreach(FilterIDType tt, types()) + foreach(ActionIDType tt, types()) if (a->text() == this->decorationName(tt)) return tt; aa.replace("&",""); - foreach(FilterIDType tt, types()) + foreach(ActionIDType tt, types()) if (aa == this->decorationName(tt)) return tt; qDebug("unable to find the id corresponding to action '%s'", qUtf8Printable(a->text())); @@ -57,13 +57,13 @@ PluginInterface::FilterIDType DecoratePluginInterface::ID(const QAction* a) cons return -1; } -PluginInterface::FilterIDType DecoratePluginInterface::ID(QString name) const +MeshLabPlugin::ActionIDType DecoratePlugin::ID(QString name) const { QString n = name; - foreach(FilterIDType tt, types()) + foreach(ActionIDType tt, types()) if (name == this->decorationName(tt)) return tt; n.replace("&",""); - foreach(FilterIDType tt, types()) + foreach(ActionIDType tt, types()) if (n == this->decorationName(tt)) return tt; qDebug("unable to find the id corresponding to action '%s'", qUtf8Printable(name)); diff --git a/src/common/interfaces/decorate_plugin_interface.h b/src/common/plugins/interfaces/decorate_plugin.h similarity index 72% rename from src/common/interfaces/decorate_plugin_interface.h rename to src/common/plugins/interfaces/decorate_plugin.h index bc99ac34a..6c456af02 100644 --- a/src/common/interfaces/decorate_plugin_interface.h +++ b/src/common/plugins/interfaces/decorate_plugin.h @@ -21,39 +21,39 @@ * * ****************************************************************************/ -#ifndef MESHLAB_DECORATE_PLUGIN_INTERFACE_H -#define MESHLAB_DECORATE_PLUGIN_INTERFACE_H +#ifndef MESHLAB_DECORATE_PLUGIN_H +#define MESHLAB_DECORATE_PLUGIN_H -#include "plugin_interface.h" +#include "meshlab_plugin_logger.h" +#include "meshlab_plugin.h" class GLArea; /** -MeshDecorateInterface is the base class of all decorators -Decorators are 'read-only' visualization aids that helps to show some data about a document. -Decorators can make some permesh precomputation but the rendering has to be efficient. -Decorators should save the additional data into per-mesh attribute. + * @class The DecoratePlugin is the base class of all decorators + * Decorators are 'read-only' visualization aids that helps to show some data about a document. + * Decorators can make some permesh precomputation but the rendering has to be efficient. + * Decorators should save the additional data into per-mesh attribute. + * There are two classes of Decorations + * - PerMesh + * - PerDocument -There are two classes of Decorations -- PerMesh -- PerDocument + * PerMesh Decorators are associated to each mesh/view + * Some example of PerDocument Decorations + * - backgrounds + * - trackball icon + * - axis + * - shadows + * - screen space Ambient occlusion (think it as a generic 'darkner') -PerMesh Decorators are associated to each mesh/view -Some example of PerDocument Decorations -- backgrounds -- trackball icon -- axis -- shadows -- screen space Ambient occlusion (think it as a generic 'darkner') + * Some example of PerMesh Decorations + * - coloring of selected vertex/face + * - displaying of normals/curvature directions + * - display of specific tagging + **/ -Some example of PerMesh Decorations -- coloring of selected vertex/face -- displaying of normals/curvature directions -- display of specific tagging -*/ - -class DecoratePluginInterface : public PluginInterface +class DecoratePlugin : virtual public MeshLabPlugin, public MeshLabPluginLogger { public: @@ -69,13 +69,13 @@ public: PostRendering = 0x00008 /*!< Decoration that are applied after the rendering of the document/mesh */ }; - DecoratePluginInterface() : PluginInterface() {} - virtual ~DecoratePluginInterface() {} + DecoratePlugin() : MeshLabPluginLogger() {} + virtual ~DecoratePlugin() {} /** The very short string (a few words) describing each filtering action // This string is used also to define the menu entry */ - virtual QString decorationName(FilterIDType) const = 0; - virtual QString decorationInfo(FilterIDType) const = 0; + virtual QString decorationName(ActionIDType) const = 0; + virtual QString decorationInfo(ActionIDType) const = 0; virtual QString decorationName(const QAction *a) const { return decorationName(ID(a)); } virtual QString decorationInfo(const QAction *a) const { return decorationInfo(ID(a)); } @@ -101,21 +101,18 @@ public: virtual int getDecorationClass(const QAction *) const = 0; virtual QList actions() const { return actionList; } - virtual QList types() const { return typeList; } + virtual QList types() const { return typeList; } virtual QAction *action(QString name) const; protected: QList actionList; - QList typeList; - virtual FilterIDType ID(const QAction *a) const; - virtual FilterIDType ID(QString name) const; + QList typeList; + virtual ActionIDType ID(const QAction *a) const; + virtual ActionIDType ID(QString name) const; }; -#define MESHLAB_PLUGIN_IID_EXPORTER(x) Q_PLUGIN_METADATA(IID x) -#define MESHLAB_PLUGIN_NAME_EXPORTER(x) +#define DECORATE_PLUGIN_IID "vcg.meshlab.DecoratePlugin/1.0" +Q_DECLARE_INTERFACE(DecoratePlugin, DECORATE_PLUGIN_IID) -#define DECORATE_PLUGIN_INTERFACE_IID "vcg.meshlab.MeshDecorateInterface/1.0" -Q_DECLARE_INTERFACE(DecoratePluginInterface, DECORATE_PLUGIN_INTERFACE_IID) - -#endif // MESHLAB_DECORATE_PLUGIN_INTERFACE_H +#endif // MESHLAB_DECORATE_PLUGIN_H diff --git a/src/common/interfaces/edit_plugin_interface.h b/src/common/plugins/interfaces/edit_plugin.h similarity index 64% rename from src/common/interfaces/edit_plugin_interface.h rename to src/common/plugins/interfaces/edit_plugin.h index 7ad9a6606..af8d29f18 100644 --- a/src/common/interfaces/edit_plugin_interface.h +++ b/src/common/plugins/interfaces/edit_plugin.h @@ -21,46 +21,47 @@ * * ****************************************************************************/ -#ifndef MESHLAB_EDIT_PLUGIN_INTERFACE_H -#define MESHLAB_EDIT_PLUGIN_INTERFACE_H +#ifndef MESHLAB_EDIT_PLUGIN_H +#define MESHLAB_EDIT_PLUGIN_H #include -#include "plugin_interface.h" -#include "../ml_document/mesh_document.h" +#include "meshlab_plugin_logger.h" +#include "meshlab_plugin.h" +#include "../../ml_document/mesh_document.h" class GLArea; -/* -EditPluginInterface -Used to provide tools that needs some kind of interaction with the mesh. -Editing tools are exclusive (only one at a time) and can grab the mouse events and customize the rendering process. -*/ +/** + * @brief The EditTool class is used to provide tools that needs some kind of + * interaction with the mesh. Editing tools are exclusive (only one at a time) + * and can grab the mouse events and customize the rendering process. + **/ -class EditPluginInterface : public PluginInterface +class EditTool : public MeshLabPluginLogger { public: - EditPluginInterface() : PluginInterface() {} - virtual ~EditPluginInterface() {} + EditTool() : MeshLabPluginLogger() {} + virtual ~EditTool() {} //should return a sentence describing what the editing tool does - static const QString Info(); + static const QString info(); virtual void suggestedRenderingData(MeshModel &/*m*/, MLRenderingData& /*dt*/) {} // Called when the user press the first time the button - virtual bool StartEdit(MeshModel &/*m*/, GLArea * /*parent*/, MLSceneGLSharedDataContext* /*cont*/) { return true; } - virtual bool StartEdit(MeshDocument &md, GLArea *parent, MLSceneGLSharedDataContext* cont) + virtual bool startEdit(MeshModel &/*m*/, GLArea * /*parent*/, MLSceneGLSharedDataContext* /*cont*/) { return true; } + virtual bool startEdit(MeshDocument &md, GLArea *parent, MLSceneGLSharedDataContext* cont) { //assert(NULL != md.mm()); if (md.mm() != NULL) - return (StartEdit(*(md.mm()), parent, cont)); + return (startEdit(*(md.mm()), parent, cont)); else return false; } // Called when the user press the second time the button - virtual void EndEdit(MeshModel &/*m*/, GLArea * /*parent*/, MLSceneGLSharedDataContext* /*cont*/) {} - virtual void EndEdit(MeshDocument &/*m*/, GLArea * /*parent*/, MLSceneGLSharedDataContext* /*cont*/) {} + virtual void endEdit(MeshModel &/*m*/, GLArea * /*parent*/, MLSceneGLSharedDataContext* /*cont*/) {} + virtual void endEdit(MeshDocument &/*m*/, GLArea * /*parent*/, MLSceneGLSharedDataContext* /*cont*/) {} // There are two classes of editing tools, the one that works on a single layer at a time // and the ones that works on all layers and have to manage in a correct way the action of changing the current layer. @@ -72,15 +73,15 @@ public: //selected. This ensures that plugins who don't support layers do not get sent pointers to meshes //they are not expecting. // If your editing plugins is not singleMesh you MUST reimplement this to correctly handle the change of layer. - virtual void LayerChanged(MeshDocument &md, MeshModel &oldMeshModel, GLArea *parent, MLSceneGLSharedDataContext* cont) + virtual void layerChanged(MeshDocument &md, MeshModel &oldMeshModel, GLArea *parent, MLSceneGLSharedDataContext* cont) { assert(this->isSingleMeshEdit()); - EndEdit(oldMeshModel, parent, cont); - StartEdit(md, parent, cont); + endEdit(oldMeshModel, parent, cont); + startEdit(md, parent, cont); } - virtual void Decorate(MeshModel &m, GLArea *parent, QPainter * /*p*/) { Decorate(m, parent); } - virtual void Decorate(MeshModel &/*m*/, GLArea * /*parent*/) {} + virtual void decorate(MeshModel &m, GLArea *parent, QPainter * /*p*/) { decorate(m, parent); } + virtual void decorate(MeshModel &/*m*/, GLArea * /*parent*/) {} virtual void mousePressEvent(QMouseEvent *event, MeshModel &/*m*/, GLArea *) = 0; virtual void mouseMoveEvent(QMouseEvent *event, MeshModel &/*m*/, GLArea *) = 0; @@ -92,36 +93,36 @@ public: }; -/** MeshEditInterfaceFactory -\short The MeshEditInterfaceFactory class is a factory is used to generate a object for each starting of an editing filter. - -This is needed because editing filters have a internal state, so if you want to have an editing tool for two different documents you have to instance two objects. -This class is used by the framework to generate an independent MeshEditInterface for each document. -*/ -class EditPluginInterfaceFactory +/** + * @brief The EditPlugin class is used to generate an action for each + * starting of an editing tool. + * + * This is needed because editing tools have a internal state, so if you want + * to have an editing tool for two different documents you have to instance + * two objects. This class is used by the framework to generate an independent + * EditTool for each document. + */ +class EditPlugin : public MeshLabPlugin { public: - virtual ~EditPluginInterfaceFactory() {} + EditPlugin() {} + virtual ~EditPlugin() {} //gets a list of actions available from this plugin - virtual QList actions() const = 0; + virtual std::list actions() const {return actionList;}; //get the edit tool for the given action - virtual EditPluginInterface* getMeshEditInterface(const QAction *) = 0; + virtual EditTool* getEditTool(const QAction *) = 0; //get the description for the given action virtual QString getEditToolDescription(const QAction *) = 0; +protected: + std::list actionList; }; -#define MESHLAB_PLUGIN_IID_EXPORTER(x) Q_PLUGIN_METADATA(IID x) -#define MESHLAB_PLUGIN_NAME_EXPORTER(x) - -#define EDIT_PLUGIN_INTERFACE_IID "vcg.meshlab.EditPluginInterface/1.0" -#define EDIT_PLUGIN_INTERFACE_FACTORY_IID "vcg.meshlab.EditPluginInterfaceFactory/1.0" - -Q_DECLARE_INTERFACE(EditPluginInterface, EDIT_PLUGIN_INTERFACE_IID) -Q_DECLARE_INTERFACE(EditPluginInterfaceFactory, EDIT_PLUGIN_INTERFACE_FACTORY_IID) +#define EDIT_PLUGIN_IID "vcg.meshlab.EditPlugin/1.0" +Q_DECLARE_INTERFACE(EditPlugin, EDIT_PLUGIN_IID) -#endif // MESHLAB_EDIT_PLUGIN_INTERFACE_H +#endif // MESHLAB_EDIT_PLUGIN_H diff --git a/src/common/interfaces/filter_plugin_interface.cpp b/src/common/plugins/interfaces/filter_plugin.cpp similarity index 78% rename from src/common/interfaces/filter_plugin_interface.cpp rename to src/common/plugins/interfaces/filter_plugin.cpp index 18fd66e3e..5c153245f 100644 --- a/src/common/interfaces/filter_plugin_interface.cpp +++ b/src/common/plugins/interfaces/filter_plugin.cpp @@ -1,6 +1,14 @@ -#include "filter_plugin_interface.h" +#include "filter_plugin.h" +#include "../../python/python_utils.h" -bool FilterPluginInterface::isFilterApplicable(const QAction* act, const MeshModel& m, QStringList &MissingItems) const +#include + +QString FilterPlugin::pythonFilterName(ActionIDType f) const +{ + return pymeshlab::computePythonName(filterName(f)); +} + +bool FilterPlugin::isFilterApplicable(const QAction* act, const MeshModel& m, QStringList &MissingItems) const { int preMask = getPreConditions(act); MissingItems.clear(); @@ -39,13 +47,13 @@ bool FilterPluginInterface::isFilterApplicable(const QAction* act, const MeshMod return MissingItems.isEmpty(); } -PluginInterface::FilterIDType FilterPluginInterface::ID(const QAction* a) const +MeshLabPlugin::ActionIDType FilterPlugin::ID(const QAction* a) const { QString aa=a->text(); - for(FilterIDType tt : types()) + for(ActionIDType tt : typeList) if (a->text() == this->filterName(tt)) return tt; aa.replace("&",""); - for(FilterIDType tt : types()) + for(ActionIDType tt : typeList) if (aa == this->filterName(tt)) return tt; qDebug("unable to find the id corresponding to action '%s'", qUtf8Printable(a->text())); @@ -53,13 +61,13 @@ PluginInterface::FilterIDType FilterPluginInterface::ID(const QAction* a) const return -1; } -QAction* FilterPluginInterface::getFilterAction(PluginInterface::FilterIDType filterID) +QAction* FilterPlugin::getFilterAction(ActionIDType filterID) { QString idName = this->filterName(filterID); return getFilterAction(idName); } -QAction* FilterPluginInterface::getFilterAction(const QString& idName) +QAction* FilterPlugin::getFilterAction(const QString& idName) { QString i=idName; for(QAction *tt : actionList) @@ -73,7 +81,12 @@ QAction* FilterPluginInterface::getFilterAction(const QString& idName) return 0; } -int FilterPluginInterface::previewOnCreatedAttributes(const QAction* act, const MeshModel& mm ) const +void FilterPlugin::wrongActionCalled(const QAction* action) +{ + throw MLException("Internal error: unknown action filter " + action->text() + " to this plugin."); +} + +int FilterPlugin::previewOnCreatedAttributes(const QAction* act, const MeshModel& mm ) const { int changedIfCalled = postCondition(act); int createdIfCalled = MeshModel::MM_NONE; @@ -98,7 +111,7 @@ int FilterPluginInterface::previewOnCreatedAttributes(const QAction* act, const if ((changedIfCalled & MeshModel::MM_VERTRADIUS) && !mm.hasDataMask(MeshModel::MM_VERTRADIUS)) createdIfCalled = createdIfCalled | MeshModel::MM_VERTRADIUS; - if ((getClass(act) == FilterPluginInterface::MeshCreation) && (mm.cm.vn == 0)) + if ((getClass(act) == FilterPlugin::MeshCreation) && (mm.cm.vn == 0)) createdIfCalled = createdIfCalled | MeshModel::MM_VERTCOORD; return createdIfCalled; diff --git a/src/common/interfaces/filter_plugin_interface.h b/src/common/plugins/interfaces/filter_plugin.h similarity index 71% rename from src/common/interfaces/filter_plugin_interface.h rename to src/common/plugins/interfaces/filter_plugin.h index 6b064ce47..15fc16611 100644 --- a/src/common/interfaces/filter_plugin_interface.h +++ b/src/common/plugins/interfaces/filter_plugin.h @@ -21,17 +21,26 @@ * * ****************************************************************************/ -#ifndef MESHLAB_FILTER_PLUGIN_INTERFACE_H -#define MESHLAB_FILTER_PLUGIN_INTERFACE_H +#ifndef MESHLAB_FILTER_PLUGIN_H +#define MESHLAB_FILTER_PLUGIN_H -#include "plugin_interface.h" -#include "../ml_document/mesh_document.h" +#include "meshlab_plugin_logger.h" +#include "meshlab_plugin.h" +#include "../../ml_document/mesh_document.h" + +//declaring types to be used as QVariants + +Q_DECLARE_METATYPE(Point2m) +Q_DECLARE_METATYPE(Point3m) +Q_DECLARE_METATYPE(Box3m) +Q_DECLARE_METATYPE(Matrix33m) +Q_DECLARE_METATYPE(Matrix44m) +Q_DECLARE_METATYPE(Eigen::VectorXd) /** - *\brief The FilterPluginInterface class provide the interface of the filter plugins. - * + * @brief The FilterPlugin class provide the interface of the filter plugins. */ -class FilterPluginInterface : public PluginInterface +class FilterPlugin : virtual public MeshLabPlugin, virtual public MeshLabPluginLogger { public: /** @@ -59,29 +68,39 @@ public: PointSet = 0x08000, Measure = 0x10000, /*!< Filters that compute measures and information on meshes.*/ Polygonal = 0x20000, /*!< Filters that works on polygonal and quad meshes.*/ - Camera = 0x40000 /*!< Filters that works on shot of mesh and raster.*/ + Camera = 0x40000, /*!< Filters that works on shot of mesh and raster.*/ + Other = 0x80000 }; - FilterPluginInterface() : PluginInterface(), glContext(nullptr) + FilterPlugin() : MeshLabPluginLogger(), glContext(nullptr) { } - virtual ~FilterPluginInterface() {} + virtual ~FilterPlugin() {} /** * @brief The very short string (a few words) describing each filtering action * This string is used also to define the menu entry */ - virtual QString filterName(FilterIDType) const = 0; + virtual QString filterName(ActionIDType) const = 0; + + /** + * @brief This function returns the name of each filter in python (pymeshlab). + * If not reimplemented, computes the name starting from the filterName output + * and making it compliant to python style name convention: + * python.org/dev/peps/pep-0008/ + */ + virtual QString pythonFilterName(ActionIDType f) const; /** * @brief The long, formatted string describing each filtering action. * This string is printed in the top of the parameter window * so it should be at least one or two paragraphs long. The more the better. * you can use simple html formatting tags (like "
" "" and "") to improve readability. - * This string is used in the 'About plugin' dialog and by meshlabserver to create the filter list wiki page and the doxygen documentation of the filters. + * This string is used in the 'About plugin' dialog and by pymeshlab to create + * the filter list documentation page of the filters. * Here is the place where you should put you bibliographic references in a form like this: *
* See:
@@ -91,14 +110,14 @@ public: *
* e.g. italic for authors, bold for title (quoted) and plain for bib ref. */ - virtual QString filterInfo(FilterIDType filter) const = 0; + virtual QString filterInfo(ActionIDType filter) const = 0; /** * @brief The FilterClass describes in which generic class of filters it fits. * This choice affect the submenu in which each filter will be placed * For example filters that perform an action only on the selection will be placed in the Selection Class */ - virtual FilterClass getClass(const QAction*) const { return FilterPluginInterface::Generic; } + virtual FilterClass getClass(const QAction*) const { return FilterPlugin::Generic; } /** * @brief The filters can have some additional requirements on the mesh capabiliteis. @@ -111,11 +130,11 @@ public: * to MeshModel::updateDataMask(...) */ virtual int getRequirements(const QAction*) { return MeshModel::MM_NONE; } - + /** * @brief This function should require true if the glContext is used by the * filter. Without this, the glContext will remain set to nullptr on non-GUI - * softwares that will use the filter (E.G. PyMeshLab). + * software that will use the filter (E.G. PyMeshLab). * Note: every filter that uses the glContext should first check if * glContext != nullptr. */ @@ -139,19 +158,44 @@ public: */ virtual int postCondition(const QAction*) const { return MeshModel::MM_ALL; } - /** + /** + * @brief This function is called to initialized the list of parameters. + * If a filter does not need parameters, do not implement this function and + * the framework will not create a dialog (unless for previewing). + * You can implement the one which takes the MeshModel or the one that + * takes the MeshDocument, depending of your needings, but do not re-implement + * both the functions. + */ + virtual RichParameterList initParameterList(const QAction*, const MeshModel &/*m*/) + { + return RichParameterList(); + } + virtual RichParameterList initParameterList(const QAction* filter, const MeshDocument &md) + { + return initParameterList(filter, *(md.mm())); + } + + /** * @brief applies the selected filter with the already stabilished parameters - * This function is called by the framework after getting values for the parameters specified in the \ref InitParameterSet + * This function is called by the framework after getting values for the parameters specified in the \ref initParameterList * NO GUI interaction should be done here. No dialog asking, no messagebox errors. * Think that his function will also be called by the commandline framework. - * If you want report errors, use the \ref errorMsg() string. It will displayed in case of filters returning false. + * If you want to report warnings **TODO - still not possible but could be useful** + * If you want report errors, throw a MLException with the message of the error. * When implementing your applyFilter, you should use the cb function to report to the framework the current state of the processing. * During your (long) processing you should call from time to time cb(perc,descriptiveString), where perc is an int (0..100) * saying what you are doing and at what point of the computation you currently are. + * The function returns a map of [string-value] pairs, that will be output of command-line calls of the filter. + * If your filter does not return nothing, just return an empty map. * @sa errorMsg * @sa initParameterSet */ - virtual bool applyFilter(const QAction* filter, MeshDocument& md, std::map& outputValues, unsigned int& postConditionMask, const RichParameterList& par, vcg::CallBackPos* cb) = 0; + virtual std::map applyFilter( + const QAction* filter, + const RichParameterList& par, + MeshDocument& md, + unsigned int& postConditionMask, + vcg::CallBackPos* cb) = 0; /** * \brief tests if a filter is applicable to a mesh. @@ -162,7 +206,7 @@ public: bool isFilterApplicable(const QAction* act, const MeshModel& m, QStringList &MissingItems) const; - enum FILTER_ARITY { NONE = 0, SINGLE_MESH = 1, FIXED = 2, VARIABLE = 3, UNKNOWN_ARITY = 4 }; + enum FilterArity { NONE = 0, SINGLE_MESH = 1, FIXED = 2, VARIABLE = 3, UNKNOWN_ARITY = 4 }; /** * @brief this function informs the MeshLab core on how many meshes the filter will work on. @@ -171,43 +215,32 @@ public: * - FIXED: the number (and the names) of the meshes involved in the filter computation is determined by the parameters selected in the filter's parameters form * - VARIABLE: the filter works on a not predetermined number of meshes. The meshes involved are typically selected by the user checking on the correspondent layer on the layer dialog */ - virtual FILTER_ARITY filterArity(const QAction *act) const = 0; + virtual FilterArity filterArity(const QAction *act) const = 0; - /** - * @brief This function is called to initialized the list of parameters. - * it is always called. If a filter does not need parameter it leave it empty and the framework - * will not create a dialog (unless for previewing) - */ - virtual void initParameterList(const QAction*, MeshModel &/*m*/, RichParameterList & /*par*/) {} - virtual void initParameterList(const QAction* filter, MeshDocument &md, RichParameterList &par) - { - initParameterList(filter, *(md.mm()), par); - } - - /** - * @brief is invoked by the framework when the applyFilter fails to give some info to the user about the filter failure - * Filters \b must never use QMessageBox for reporting errors. - * Failing filters should put some meaningful information inside the errorMessage string and return false with the \ref applyFilter - */ - const QString& errorMsg() const { return this->errorMessage; } virtual QString filterInfo(const QAction* a) const { return this->filterInfo(ID(a)); } virtual QString filterName(const QAction* a) const { return this->filterName(ID(a)); } - virtual QString filterScriptFunctionName(FilterIDType /*filterID*/) { return ""; } + virtual QString pythonFilterName(const QAction* a) const {return this->pythonFilterName(ID(a)); } + virtual QString filterScriptFunctionName(ActionIDType /*filterID*/) { return ""; } - virtual FilterIDType ID(const QAction *a) const; + virtual ActionIDType ID(const QAction *a) const; - virtual QAction* getFilterAction(FilterIDType filterID); + virtual QAction* getFilterAction(ActionIDType filterID); virtual QAction* getFilterAction(const QString& idName); - virtual QList actions() const { return actionList; } - virtual QList types() const { return typeList; } + virtual std::list actions() const { return actionList; } + virtual std::list types() const { return typeList; } + + /** + * @brief wrongActionCalled throws a MLException. Call this function whenever + * you receive an unknown action as parameter. + */ + static void wrongActionCalled(const QAction*); /** * Generate the mask of attributes would be created IF the MeshFilterInterface filt would has been called on MeshModel mm * BE CAREFUL! this function does NOT change in anyway the state of the MeshModel!!!! */ int previewOnCreatedAttributes(const QAction* act, const MeshModel& mm) const; - QString generatedScriptCode; MLPluginGLContext* glContext; protected: @@ -216,18 +249,12 @@ protected: // // The list of actions exported by the plugin. Each actions strictly corresponds to - QList actionList; + std::list actionList; - QList typeList; - - // this string is used to pass back to the framework error messages in case of failure of a filter apply. - QString errorMessage; + std::list typeList; }; -#define MESHLAB_PLUGIN_IID_EXPORTER(x) Q_PLUGIN_METADATA(IID x) -#define MESHLAB_PLUGIN_NAME_EXPORTER(x) +#define FILTER_PLUGIN_IID "vcg.meshlab.FilterPlugin/1.0" +Q_DECLARE_INTERFACE(FilterPlugin, FILTER_PLUGIN_IID) -#define FILTER_PLUGIN_INTERFACE_IID "vcg.meshlab.FilterPluginInterface/1.0" -Q_DECLARE_INTERFACE(FilterPluginInterface, FILTER_PLUGIN_INTERFACE_IID) - -#endif // MESHLAB_FILTER_PLUGIN_INTERFACE_H +#endif // MESHLAB_FILTER_PLUGIN_H diff --git a/src/common/plugins/interfaces/io_plugin.cpp b/src/common/plugins/interfaces/io_plugin.cpp new file mode 100644 index 000000000..416d9e951 --- /dev/null +++ b/src/common/plugins/interfaces/io_plugin.cpp @@ -0,0 +1,54 @@ +#include "io_plugin.h" +#include "../../ml_document/mesh_document.h" + +unsigned int IOPlugin::numberMeshesContainedInFile( + const QString&, + const QString&, + const RichParameterList&) const +{ + return 1; +} + +void IOPlugin::open( + const QString& format, + const QString& fileName, + const std::list& meshModelList, + std::list& maskList, + const RichParameterList& par, + vcg::CallBackPos* cb) +{ + // This implementation assumes that the number of meshes contained in + // the file is 1, and will call the open function that takes a single + // MeshModel* as parameter. + assert(meshModelList.size() == 1); + maskList.clear(); + MeshModel *mm = meshModelList.front(); + int mask = 0; + open(format, fileName, *mm, mask, par, cb); + maskList.push_back(mask); +} + +void IOPlugin::reportWarning(const QString& warningMessage) const +{ + if (!warningMessage.isEmpty()){ + MeshLabPluginLogger::log(GLLogStream::WARNING, warningMessage.toStdString()); + warnString += "\n" + warningMessage; + } +} + +void IOPlugin::wrongOpenFormat(const QString& format) const +{ + throw MLException("Internal error: unknown open format " + format + " to " + pluginName() + " plugin."); +} + +void IOPlugin::wrongSaveFormat(const QString& format) const +{ + throw MLException("Internal error: unknown save format " + format + " to " + pluginName() + " plugin."); +} + +QString IOPlugin::warningMessageString() const +{ + QString tmp = warnString; + warnString.clear(); + return tmp; +} diff --git a/src/common/plugins/interfaces/io_plugin.h b/src/common/plugins/interfaces/io_plugin.h new file mode 100644 index 000000000..cde872599 --- /dev/null +++ b/src/common/plugins/interfaces/io_plugin.h @@ -0,0 +1,442 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2020 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef MESHLAB_IO_PLUGIN_H +#define MESHLAB_IO_PLUGIN_H + +#include + +#include "meshlab_plugin_logger.h" +#include "meshlab_plugin.h" +#include "../../utilities/file_format.h" +#include "../../ml_document/raster_model.h" + +class MLRenderingData; + +/** + * @brief The IOPlugin is the base class for meshes, images and projects loading + * and saving. + * + * Provides the base functions to open: + * - a mesh file (open); + * - a project file (openProject); + * - an image file (openImage); + * + * and the base functions to save: + * - a mesh file (save); + * - a project file (saveProject); + * - an image file (saveImage); + * + * You can tell which formats your plugin will be able to open or save by + * re-implementing the following functions + * - importFormats() + * - exportFormats() + * where can be [todo] Mesh, Image or Project. + */ +class IOPlugin : virtual public MeshLabPlugin, virtual public MeshLabPluginLogger +{ +public: + IOPlugin() : MeshLabPluginLogger() { } + virtual ~IOPlugin() { } + + /*********************** + * Open Mesh Functions * + ***********************/ + + /** + * @brief The importFormats function returns a list of all the + * input file formats supported by the plugin. + * This function must be implemented on any IO plugin. + * If yout plugin does not import any mesh format, just return an + * empty list. + */ + virtual std::list importFormats() const = 0; + + /** + * @brief The initPreOpenParameter function is called to initialize the list + * of additional parameters that opening a mesh format could require. It is + * called by the framework BEFORE the actual mesh loading to determine how + * to parse the input file. The instanced parameters are then passed to the + * open at the loading time. + * Typical example of use to decide what subportion of a mesh you have to + * load. If you do not need any additional processing simply do not override + * this and ignore the parameterList in the open member function + */ + virtual RichParameterList initPreOpenParameter( + const QString& /*format*/) const + { + return RichParameterList(); + } + + /** + * @brief this function returns the number of meshes that the open function + * is going to load from the file given as parameter. Default value is 1. + * If the file format can contain just one mesh per file, you don't need to + * re-implement this function. + * If your plugin could load more than one mesh from a single file, you + * should re-implement this function and return the actual number of meshes + * that are present in the file. + * The number returned by this function will be the number of MeshModel* + * contained in the meshModelList parameter passed to the open function + * that allows to open multiple meshes. + * + * Note: you MUST reimplement the open function that takes a list of + * MeshModel* as parameter ONLY if this function may return a value != 1. + * + * @param format + * @param fileName + * @return + */ + virtual unsigned int numberMeshesContainedInFile( + const QString& format, + const QString& fileName, + const RichParameterList& preParams) const; + + /** + * @brief The open function is called by the framework everytime a mesh is + * loaded. + * If the file format can contain just one mesh per file, you don't need to + * re-implement this function, but you can implement just the next "open" + * function. + * Re-implement this function if your plugin supports loading format + * file that could load more than one mesh layer. + * @param format: the extension of the format e.g. "PLY" + * @param fileName: the name of the file to be opened (including its path) + * @param meshModelList: the list of meshes that is filled with the file content + * the number of meshes in the list is given by the + * numberMeshesContainedInFile() function. + * @param maskList: a list of bit masks that will be filled reporting what kind of data + * we have found in each mesh present in the file (per vertex color, + * texture coords etc). the number of meshes in the list is given by + * the numberMeshesContainedInFile() function. + * @param par: the parameters that have been set up in the + * initPreOpenParameter() + * @param cb: standard callback for reporting progress in the loading + */ + virtual void open( + const QString &format, + const QString &fileName, + const std::list& meshModelList, + std::list& maskList, + const RichParameterList & par, + vcg::CallBackPos *cb = nullptr); + + /** + * @brief The open function is called by the framework everytime a mesh is + * loaded. Re-implement this function if the format file you want to open + * can contain just one mesh. If your file can contain more than one mesh, + * re-implement the "open" function that takes as input the MeshDocument + * instead of the MeshModel (see the function above). + * @param format: the extension of the format e.g. "PLY" + * @param fileName: the name of the file to be opened (including its path) + * @param m: the mesh that is filled with the file content + * @param mask: a bit mask that will be filled reporting what kind of data + * we have found in the file (per vertex color, texture coords etc) + * @param par: the parameters that have been set up in the + * initPreOpenParameter() + * @param cb: standard callback for reporting progress in the loading + */ + virtual void open( + const QString &format, + const QString &fileName, + MeshModel &m, + int &mask, + const RichParameterList & par, + vcg::CallBackPos *cb = nullptr) = 0; + + /*********************** + * Save Mesh Functions * + ***********************/ + + /** + * @brief The exportFormats function returns a list of all the + * output file formats supported by the plugin. + * This function must be implemented on any IO plugin. + * If yout plugin does not export any mesh format, just return an + * empty list. + */ + virtual std::list exportFormats() const = 0; + + /** + * @brief The exportMaskCapability function tells to the framework which + * export capabilities are supported by the given format (e.g. if the format + * supports saving face colors, vertex quality...). + * It also tells to the framework which of these export capabilities are + * set by default. + */ + virtual void exportMaskCapability( + const QString &format, + int& capability, + int& defaultBits) const = 0; + + /** + * @brief The initSaveParameter function is called to initialize the list + * of additional parameters that saving a mesh could require. It is called + * by the framework after the output format is selected by the user. + * typical example: ascii or binary format for ply or stl + * If you do not need any additional parameters, simply do not implement + * this function. + */ + virtual RichParameterList initSaveParameter( + const QString& /*format*/, + const MeshModel& /*m*/) const + { + return RichParameterList(); + } + + /** + * @brief The save function is called by the framework everytime a mesh is + * saved. + * @param format: the extension of the format e.g. "PLY" + * @param fileName: the name of the file on which save the mesh m + * (including its path) + * @param m: the mesh to be saved in the file + * @param mask: a bit mask indicating what kind of the data present in the + * mesh should be saved (e.g. you could not want to save normals in + * ply files) + * @param par: the parameters that have been set up in the initSaveParameter() + * @param cb: standard callback for reporting progress in the saving + */ + virtual void save( + const QString &format, + const QString &fileName, + MeshModel &m, /** NOTE: this is going to be const MeshModel&: try to use only const functions!! **/ + const int mask, + const RichParameterList & par, + vcg::CallBackPos* cb = nullptr) = 0; + + /************************ + * Open Image Functions * + ************************/ + + /** + * @brief If your plugin supports loading also images, re-implement + * this function, returning the list of image formats supported by + * your openImage function. + */ + virtual std::list importImageFormats() const + { + return std::list(); + } + + /** + * @brief The openImage function is called by the framework everytime an image + * needs to be loaded. Could be called when loading textures or rasters. + * @param format: the extension of the format, e.g. "PNG" + * @param fileName: the name of the file from which load the image (including its path) + * @param cb: standard callback for reporting progresso in the loading + * @return the loaded QImage + */ + virtual QImage openImage( + const QString& format, + const QString& /*fileName*/, + vcg::CallBackPos* /*cb*/ = nullptr) + { + wrongOpenFormat(format); + return QImage(); + }; + + /************************ + * Save Image Functions * + ************************/ + + /** + * @brief If your plugin supports saving also images, re-implement + * this function, returning the list of image formats supported by + * your saveImage function. + */ + virtual std::list exportImageFormats() const + { + return std::list(); + } + + /** + * @brief The saveImage function is called by the framework everytime an image + * needs to be saved (e.g. when saving a texture). + * @param format: the extension of the format, e.g. "PNG" + * @param fileName: the name of the file on which save the image (including its path) + * @param image: the image to save in the given fileName + * @param cb: standard callback for reporting progresso in the loading + */ + virtual void saveImage( + const QString& format, + const QString& /*fileName*/, + const QImage& /*image*/, + int /*quality*/ = -1, + vcg::CallBackPos* /*cb*/ = nullptr) + { + wrongSaveFormat(format); + } + + /************************** + * Open Project Functions * + **************************/ + + /** + * @brief If your plugin supports loading also projects, re-implement + * this function, returning the list of project formats supported by + * your openProject function. + */ + virtual std::list importProjectFormats() const + { + return std::list(); + } + + /** + * @brief some project file formats require the load of more than one file + * (e.g. bundler.out requires also a txt containing raster infos). + * + * If this is your case, you should implement this returning a list of + * *FileFormats* for each additional file that should be loaded. + * Then, the framework will ask the user to select the additional required + * files. Leaving the returned list empty means that the format of the + * project does not need additional files to be loaded. + * + * The list of files will then passed to the user in the openProject. + * + * @return + */ + virtual std::list projectFileRequiresAdditionalFiles( + const QString& /*format*/, + const QString& /*filename*/) + { + return std::list(); + }; + + /** + * @brief The openProject function is called by the framework everytime a + * project needs to be loaded. + * + * The function takes an list of filenames because some project files + * are composed by more than one file. In this specific case, you should + * re-implement the function projectFileRequiresAdditionalFiles. + * The number of filenames contained in the input list will be + * 1 + number of elements in the list returned by the function + * projectFileRequiresAdditionalFiles (default: 0). + * + * If the meshes contained in the project are saved in separate files and not + * into the project, you should use the functions provided into the file + * "common/utilities/load_save.h". These functions will take care to load + * a mesh with any of the formats supported by meshlab. + * + * @param format: the extension of the format, e.g. "MLP" + * @param fileName: the name of the file from which load the project (including its path) + * @param md: MeshDocument on which store the content of the loaded project + * note: the document could not be empty! + * @param rendOpt: rendering options that may be loaded from the project file, + * if it supports them. They are not required. If you can support + * rendering options, the rendOpt vector must have the same size of + * the MeshModel vector returned by the openProject function. + * @param cb: standard callback for reporting progresso in the loading + * @return the list of MeshModel that have been loaded from the given project + */ + virtual std::vector openProject( + const QString& format, + const QStringList& /*filenames*/, + MeshDocument& /*md*/, + std::vector& /*rendOpt*/, + vcg::CallBackPos* /*cb*/ = nullptr) + { + wrongOpenFormat(format); + return std::vector(); + } + + /************************** + * Save Project Functions * + **************************/ + + /** + * @brief If your plugin supports saving also projects, re-implement + * this function, returning the list of project formats supported by + * your saveProject function. + */ + virtual std::list exportProjectFormats() const + { + return std::list(); + } + + /** + * @brief The saveProject function is called by the framework everytime a + * project is saved. + * @param format: the extension of the format e.g. "MLP" + * @param fileName: the name of the file on which save the project md + * (including its path) + * @param md: the MeshDocument to be saved in the file + * @param onlyVisibleMesh: if this parameter is set to true, only the meshes + * marked visible should be saved into the project + * @param cb: standard callback for reporting progress in the saving + */ + virtual void saveProject( + const QString& format, + const QString& /*fileName*/, + const MeshDocument& /*md*/, + bool /*onlyVisibleMeshes*/, + const std::vector& /*rendOpt*/, + vcg::CallBackPos* /*cb*/ = nullptr) + { + wrongSaveFormat(format); + } + + /*************************** + * Other utility Functions * + ***************************/ + + /** + * @brief The reportWarning function should be used everytime that a + * non-critical error while loading or saving a file happens. This function + * appends the warning message passed as parameter to a string that will be + * shown by the framework at the end of the execution of the load/save + * function + * @param warningMessage + */ + void reportWarning(const QString& warningMessage) const; + + /** + * @brief call this function in any of the import functions + * (initPreOpenParameters, load...) whenever you receive as parameter a + * format that is not supported by your plugin + */ + void wrongOpenFormat(const QString& format) const; + + /** + * @brief call this function in any of the export functions + * (exportMaskCapability, save...) whenever you receive as parameter a + * format that is not supported by your plugin + */ + void wrongSaveFormat(const QString& format) const; + + /** + * @brief The warningMessageString is invoked by the framework after the + * execution of load/save functions. It returns the warning string containing + * all the warnings produced by the function, and it clears the string. + */ + QString warningMessageString() const; + +private: + mutable QString warnString; +}; + +#define IO_PLUGIN_IID "vcg.meshlab.IOPlugin/1.0" +Q_DECLARE_INTERFACE(IOPlugin, IO_PLUGIN_IID) + +#endif // MESHLAB_IO_PLUGIN_H diff --git a/src/common/plugins/interfaces/meshlab_plugin.h b/src/common/plugins/interfaces/meshlab_plugin.h new file mode 100644 index 000000000..6f2197e5a --- /dev/null +++ b/src/common/plugins/interfaces/meshlab_plugin.h @@ -0,0 +1,104 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef MESHLAB_PLUGIN_H +#define MESHLAB_PLUGIN_H + +#include +#include +#include +#include "../../mlexception.h" + +/** + * @brief The MeshLabPlugin class is the base of all MeshLab plugin classes, + * and represents the library file of the plugin. + * + * The main idea common to all the framework is that each plugin export a set + * of actions, internally each action is associated to an ActionIDType, and for + * each action a name and a formatted INFO is defined. + * + * For coding easyness ID are more practical (you can use them in switches). + * Using action on the other hand is practical because it simplify their + * management in menus/toolbars and it allows to define icons and other things + * in a automatic way. + * Moreover ID are UNSAFE (different plugin can have same id) so they should be + * used only INTERNALLY. + */ +class MeshLabPlugin +{ +public: + friend class PluginManager; + + MeshLabPlugin() : enabled(true) {}; + virtual ~MeshLabPlugin() {} + + /** + * @brief the type used to identify plugin actions; + * there is a one-to-one relation between an ID and an Action. + */ + typedef int ActionIDType; + + /** + * This function will be automatically defined in your plugin class + * when you use the MESHLAB_PLUGIN_IID_EXPORTER macro. + * The only exception is for the Edit plugins (not EditFactory!): + * in this case, this function is defined by the macro + * MESHLAB_EDIT_PLUGIN + **/ + virtual std::pair getMLVersion() const = 0; + + /** + * @brief This function returns the name of the current plugin. + * Must be implemented in every plugin. + * @return + */ + virtual QString pluginName() const = 0; + + /** + * @brief This function returns the vendor (developer or organization) + * of the plugin. + * @return + */ + virtual QString vendor() const {return "CNR-ISTI VCLab";}; + + bool isEnabled() const {return enabled;} + + QFileInfo pluginFileInfo() const {return plugFileInfo;} + +private: + void enable() {enabled = true;} + void disable() {enabled = false;} + bool enabled; + QFileInfo plugFileInfo; +}; + +#define MESHLAB_PLUGIN_IID_EXPORTER(x) \ + Q_PLUGIN_METADATA(IID x) \ + public: \ + virtual std::pair getMLVersion() const { \ + return std::make_pair(meshlab::meshlabVersion(), meshlab::builtWithDoublePrecision()); \ + } \ + private: +#define MESHLAB_PLUGIN_NAME_EXPORTER(x) + +#endif // MESHLAB_PLUGIN_H diff --git a/src/common/plugins/interfaces/meshlab_plugin_logger.cpp b/src/common/plugins/interfaces/meshlab_plugin_logger.cpp new file mode 100644 index 000000000..2f56f34f4 --- /dev/null +++ b/src/common/plugins/interfaces/meshlab_plugin_logger.cpp @@ -0,0 +1,46 @@ +#include "meshlab_plugin_logger.h" + +MeshLabPluginLogger::MeshLabPluginLogger() : + logstream(nullptr) +{ +} + +void MeshLabPluginLogger::setLog(GLLogStream* log) +{ + this->logstream = log; +} + +void MeshLabPluginLogger::log(const char* s) const +{ + if(logstream != nullptr) { + logstream->log(GLLogStream::FILTER, s); + } +} + +void MeshLabPluginLogger::log(const std::string& s) const +{ + if(logstream != nullptr) { + logstream->log(GLLogStream::FILTER, s); + } +} + +void MeshLabPluginLogger::log(GLLogStream::Levels level, const char* s) const +{ + if(logstream != nullptr) { + logstream->log(level, s); + } +} + +void MeshLabPluginLogger::log(GLLogStream::Levels level, const std::string& s) const +{ + if(logstream != nullptr) { + logstream->log(level, s); + } +} + +void MeshLabPluginLogger::realTimeLog(QString id, const QString& meshName, const char* f) const +{ + if(logstream != nullptr) { + logstream->realTimeLog(id, meshName, f); + } +} diff --git a/src/common/interfaces/plugin_interface.h b/src/common/plugins/interfaces/meshlab_plugin_logger.h similarity index 53% rename from src/common/interfaces/plugin_interface.h rename to src/common/plugins/interfaces/meshlab_plugin_logger.h index ecaed63e3..9283f2d54 100644 --- a/src/common/interfaces/plugin_interface.h +++ b/src/common/plugins/interfaces/meshlab_plugin_logger.h @@ -2,7 +2,7 @@ * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * -* Copyright(C) 2005-2020 \/)\/ * +* Copyright(C) 2005-2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -21,44 +21,31 @@ * * ****************************************************************************/ -#ifndef MESHLAB_PLUGIN_INTERFACE_H -#define MESHLAB_PLUGIN_INTERFACE_H +#ifndef MESHLAB_PLUGIN_LOGGER_H +#define MESHLAB_PLUGIN_LOGGER_H #include - -#include "../GLLogStream.h" -#include "../parameters/rich_parameter_list.h" +#include "meshlab_plugin.h" +#include "../../GLLogStream.h" +#include "../../parameters/rich_parameter_list.h" +#include "../../globals.h" /** - * \brief The PluginInterface class is the base of all the plugin interfaces. + * @brief The MeshLabPluginLogger provides some common log functionalities that are + * used by MeshLab. * - * The main idea common to all the framework is that each plugin export a set of actions, - * internally each action is associated to a FilterIDType, and for each action a name and a formatted INFO is defined. - * - * For coding easyness ID are more practical (you can use them in switches). - * Using action on the other hand is practical because it simplify their management in menus/toolbars and it allows to define icons and other things in a automatic way. - * Moreover ID are UNSAFE (different plugin can have same id) so they should be used only INTERNALLY - * - * \todo There is inconsistency in the usage of ID and actions for retrieving particular filters. Remove. + * Each MeshLab abstract plugin class inherits from this class in order to make + * available log member functions to plugins. + * The only exception is the EditPlugin class, since it is not the Edit plugin + * that should be able to log, but the EditTool class (the EditPlugin class is a + * "container" of EditTools). */ -class PluginInterface +class MeshLabPluginLogger { public: - typedef int FilterIDType; - - /** the type used to identify plugin actions; there is a one-to-one relation between an ID and an Action. - \todo To be renamed as ActionIDType - */ - PluginInterface(); - virtual ~PluginInterface() {} - - /** - * @brief This functions returns the name of the current plugin. - * Must be implemented in every plugin. - * @return - */ - virtual QString pluginName() const = 0; + MeshLabPluginLogger(); + virtual ~MeshLabPluginLogger() {} /// Standard stuff that usually should not be redefined. void setLog(GLLogStream* log); @@ -66,25 +53,27 @@ public: // This function must be used to communicate useful information collected in the parsing/saving of the files. // NEVER EVER use a msgbox to say something to the user. template - void log(const char* f, Ts&&... ts); + void log(const char* f, Ts&&... ts) const; + template + void log(const std::string& s, Ts&&... ts) const; - void log(const char* s); - void log(const std::string& s); + void log(const char* s) const; + void log(const std::string& s) const; template - void log(GLLogStream::Levels Level, const char* f, Ts&&... ts); + void log(GLLogStream::Levels level, const char* f, Ts&&... ts) const; - void log(GLLogStream::Levels level, const char* s); + void log(GLLogStream::Levels level, const char* s) const; - void log(GLLogStream::Levels level, const std::string& s); + void log(GLLogStream::Levels level, const std::string& s) const; - void realTimeLog(QString Id, const QString& meshName, const char* f); + void realTimeLog(QString Id, const QString& meshName, const char* f) const; template - void realTimeLog(QString Id, const QString &meshName, const char * f, Ts&&... ts ); + void realTimeLog(QString Id, const QString &meshName, const char * f, Ts&&... ts ) const; private: - GLLogStream *logstream; + mutable GLLogStream *logstream; }; /************************ @@ -92,27 +81,35 @@ private: ************************/ template -void PluginInterface::log(const char* f, Ts&&... ts) +void MeshLabPluginLogger::log(const char* f, Ts&&... ts) const { if(logstream != nullptr) { - logstream->Logf(GLLogStream::FILTER, f, std::forward(ts)...); + logstream->logf(GLLogStream::FILTER, f, std::forward(ts)...); + } +} + +template +void MeshLabPluginLogger::log(const std::string& s, Ts&&... ts) const +{ + if(logstream != nullptr) { + logstream->logf(GLLogStream::FILTER, s.c_str(), std::forward(ts)...); } } template -void PluginInterface::log(GLLogStream::Levels Level, const char* f, Ts&&... ts) +void MeshLabPluginLogger::log(GLLogStream::Levels level, const char* f, Ts&&... ts) const { if(logstream != nullptr) { - logstream->Logf(Level, f, std::forward(ts)...); + logstream->logf(level, f, std::forward(ts)...); } } template -void PluginInterface::realTimeLog(QString Id, const QString& meshName, const char* f, Ts&&... ts) +void MeshLabPluginLogger::realTimeLog(QString id, const QString& meshName, const char* f, Ts&&... ts) const { if(logstream != nullptr) { - logstream->RealTimeLogf(Id, meshName, f, std::forward(ts)...); + logstream->realTimeLogf(id, meshName, f, std::forward(ts)...); } } -#endif // MESHLAB_PLUGIN_INTERFACE_H +#endif // MESHLAB_PLUGIN_LOGGER_H diff --git a/src/common/interfaces/render_plugin_interface.h b/src/common/plugins/interfaces/render_plugin.h similarity index 53% rename from src/common/interfaces/render_plugin_interface.h rename to src/common/plugins/interfaces/render_plugin.h index de760aad8..8d7ddf2f6 100644 --- a/src/common/interfaces/render_plugin_interface.h +++ b/src/common/plugins/interfaces/render_plugin.h @@ -21,51 +21,59 @@ * * ****************************************************************************/ -#ifndef MESHLAB_RENDER_PLUGIN_INTERFACE_H -#define MESHLAB_RENDER_PLUGIN_INTERFACE_H +#ifndef MESHLAB_RENDER_PLUGIN_H +#define MESHLAB_RENDER_PLUGIN_H -#include "plugin_interface.h" -#include "../ml_shared_data_context.h" +#include "meshlab_plugin_logger.h" +#include "meshlab_plugin.h" +#include "../../ml_shared_data_context/ml_scene_gl_shared_data_context.h" /** -RenderPluginInterface -Used to customized the rendering process. -Rendering plugins are now responsible of the rendering of the whole MeshDocument and not only of a single MeshModel. - -The Render function is called in with the ModelView and Projection Matrices already set up, screen cleared and background drawn. -After the Render call the MeshLab frawework draw on the opengl context other decorations and the trackball, so it there is the -requirement for a rendering plugin is that it should leave the z-buffer in a coherent state. - -The typical rendering loop of a Render plugin is something like, : - - - -foreach(MeshModel * mp, meshDoc.meshList) -{ -if(mp->visible) mp->Render(rm.drawMode,rm.colorMode,rm.textureMode); -} - -*/ + * @brief The RenderPlugin class is used to customize the rendering + * process of the whole MeshDocument. + * + * The Render function is called in with the ModelView and Projection Matrices + * already set up, screen cleared and background drawn. + * After the Render call the MeshLab frawework draw on the opengl context other + * decorations and the trackball, so it there is the requirement for a rendering + * plugin is that it should leave the z-buffer in a coherent state. + * + * The typical rendering loop of a Render plugin is something like, : + * + * + * + * foreach(MeshModel * mp, meshDoc.meshList) + * { + * if(mp->visible) mp->Render(rm.drawMode,rm.colorMode,rm.textureMode); + * } + */ class GLArea; -class RenderPluginInterface : public PluginInterface +class RenderPlugin : virtual public MeshLabPlugin, virtual public MeshLabPluginLogger { public: - RenderPluginInterface() :PluginInterface() {} - virtual ~RenderPluginInterface() {} + RenderPlugin() :MeshLabPluginLogger() {} + virtual ~RenderPlugin() {} - virtual void Init(QAction *, MeshDocument &, MLSceneGLSharedDataContext::PerMeshRenderingDataMap& /*mp*/, GLArea *) {} - virtual void Render(QAction *, MeshDocument &, MLSceneGLSharedDataContext::PerMeshRenderingDataMap& mp, GLArea *) = 0; - virtual void Finalize(QAction *, MeshDocument *, GLArea *) {} virtual bool isSupported() = 0; virtual QList actions() = 0; + + virtual void init(QAction *, MeshDocument &, MLSceneGLSharedDataContext::PerMeshRenderingDataMap& /*mp*/, GLArea *) {} + virtual void render(QAction *, MeshDocument &, MLSceneGLSharedDataContext::PerMeshRenderingDataMap& mp, GLArea *) = 0; + virtual void finalize(QAction *, MeshDocument *, GLArea *) {} + + /** + * this function is called whenever MeshLab should update GUI's menus filled + * with the actions of your plugin. + * Reimplement this if your actions depend on something that may change during + * a MeshLab session (e.g. new shader files have been loaded and need to be + * added to the MeshLab interface) + */ + virtual void refreshActions() {} }; -#define MESHLAB_PLUGIN_IID_EXPORTER(x) Q_PLUGIN_METADATA(IID x) -#define MESHLAB_PLUGIN_NAME_EXPORTER(x) - -#define RENDER_PLUGIN_INTERFACE_IID "vcg.meshlab.RenderPluginInterface/1.0" -Q_DECLARE_INTERFACE(RenderPluginInterface, RENDER_PLUGIN_INTERFACE_IID) +#define RENDER_PLUGIN_IID "vcg.meshlab.RenderPlugin/1.0" +Q_DECLARE_INTERFACE(RenderPlugin, RENDER_PLUGIN_IID) #endif // MESHLAB_RENDER_PLUGIN_INTERFACE_H diff --git a/src/common/plugins/meshlab_plugin_type.cpp b/src/common/plugins/meshlab_plugin_type.cpp new file mode 100644 index 000000000..49c48f32e --- /dev/null +++ b/src/common/plugins/meshlab_plugin_type.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "meshlab_plugin_type.h" + +#include "interfaces/decorate_plugin.h" +#include "interfaces/edit_plugin.h" +#include "interfaces/filter_plugin.h" +#include "interfaces/io_plugin.h" +#include "interfaces/render_plugin.h" + +MeshLabPluginType::MeshLabPluginType(const MeshLabPlugin* fpi) : type(0) +{ + //Decorate + const DecoratePlugin *iDecorator = dynamic_cast(fpi); + if (iDecorator) { + type |= DECORATE; + } + //EditFactory + const EditPlugin* efp = dynamic_cast(fpi); + if (efp) { //EditFactory Plugin + type |= EDIT; + } + //Filter + const FilterPlugin *iFilter = dynamic_cast(fpi); + if (iFilter){ + type |= FILTER; + } + //IO + const IOPlugin *iIO = dynamic_cast(fpi); + if (iIO) { + type |= IO; + } + + //Render + const RenderPlugin *iRender = dynamic_cast(fpi); + if (iRender) { + type |= RENDER; + } + + if (type == 0) + type = UNKNOWN; +} + +bool MeshLabPluginType::isValid() const +{ + return !(type & UNKNOWN); +} + +bool MeshLabPluginType::isDecoratePlugin() const +{ + return type & DECORATE; +} + +bool MeshLabPluginType::isEditPlugin() const +{ + return type & EDIT; +} + +bool MeshLabPluginType::isFilterPlugin() const +{ + return type & FILTER; +} + +bool MeshLabPluginType::isIOPlugin() const +{ + return type & IO; +} + +bool MeshLabPluginType::isRenderPlugin() const +{ + return type & RENDER; +} + +bool MeshLabPluginType::isMultipleTypePlugin() const +{ + if (type == UNKNOWN) return false; + return ((type & (type - 1)) != 0); //true if not power of 2 +} + +/** + * @brief Returns a string representing the type of the plugin. + * Note: + * - returns "Unknown" it the type is not valid; + * - returns a String of the type "Type1|Type2" if the plugin + * has multiple types. + * @return + */ +QString MeshLabPluginType::pluginTypeString() const +{ + QString type = ""; + if (!isValid()) + return "Unknown"; + + if (isDecoratePlugin()){ + type += "Decorate"; + } + if (isEditPlugin()){ + if (!type.isEmpty()) type += "|"; + type += "Edit"; + } + if (isFilterPlugin()){ + if (!type.isEmpty()) type += "|"; + type += "Filter"; + } + if (isIOPlugin()){ + if (!type.isEmpty()) type += "|"; + type += "IO"; + } + if (isRenderPlugin()){ + if (!type.isEmpty()) type += "|"; + type += "Render"; + } + return type; +} diff --git a/src/common/interfaces/mainwindow_interface.h b/src/common/plugins/meshlab_plugin_type.h similarity index 69% rename from src/common/interfaces/mainwindow_interface.h rename to src/common/plugins/meshlab_plugin_type.h index 777b9ebeb..52b262cf4 100644 --- a/src/common/interfaces/mainwindow_interface.h +++ b/src/common/plugins/meshlab_plugin_type.h @@ -2,7 +2,7 @@ * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * -* Copyright(C) 2005-2020 \/)\/ * +* Copyright(C) 2005-2021 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -21,22 +21,39 @@ * * ****************************************************************************/ -#ifndef MESHLAB_MAINWINDOW_INTERFACE_H -#define MESHLAB_MAINWINDOW_INTERFACE_H +#ifndef MESHLAB_PLUGIN_TYPE_H +#define MESHLAB_PLUGIN_TYPE_H -#include -#include "../parameters/rich_parameter_list.h" +class QString; -/** The MainWindowInterface class defines just the executeFilter() callback function -that is invoked by the standard parameter input dialog. -It is used as base class of the MainWindow. -*/ -class MainWindowInterface +class MeshLabPlugin; + +class MeshLabPluginType { public: - virtual void executeFilter(const QAction *, RichParameterList &, bool = false) {} - //parexpval is a string map containing the parameter expression values set in the filter's dialog. - //These parameter expression values will be evaluated when the filter will start. + MeshLabPluginType(const MeshLabPlugin* fpi); + + bool isValid() const; + bool isDecoratePlugin() const; + bool isEditPlugin() const; + bool isFilterPlugin() const; + bool isIOPlugin() const; + bool isRenderPlugin() const; + + bool isMultipleTypePlugin() const; + QString pluginTypeString() const; + +private: + enum MLPType { + UNKNOWN = 1<<0, //1 + DECORATE = 1<<1, //2 + EDIT = 1<<2, //4 + FILTER = 1<<3, //8 + IO = 1<<4, //16 + RENDER = 1<<5 //32 + }; + + int type; }; -#endif // MESHLAB_MAINWINDOW_INTERFACE_H +#endif // MESHLAB_PLUGIN_TYPE_H diff --git a/src/common/plugins/plugin_manager.cpp b/src/common/plugins/plugin_manager.cpp new file mode 100644 index 000000000..4d98c807b --- /dev/null +++ b/src/common/plugins/plugin_manager.cpp @@ -0,0 +1,599 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "plugin_manager.h" + +#include +#include +#include + +#include + +#include "../mlexception.h" +#include "../globals.h" + +static QStringList fileNamePluginDLLs() { + QStringList l; +#if defined(Q_OS_WIN) + l.push_back("*.dll"); + return l; +#elif defined(Q_OS_MAC) + l.push_back("*.dylib"); + l.push_back("*.so"); + return l; +#else //linux + l.push_back("*.so"); + return l; +#endif +} + +PluginManager::PluginManager() +{ +} + +PluginManager::~PluginManager() +{ + for (auto& plugin : allPluginLoaders){ + plugin->unload(); + delete plugin; + } +} + +/** + * @brief Checks if the given file is a valid MeshLab plugin. + * It does not add the plugin to the plugin manager. + * + * Note: this function is called automatically before loading a plugin. + * + * Throws a MLException if the file is not a valid MeshLab plugin. + */ +MeshLabPluginType PluginManager::checkPlugin(const QString& filename) +{ + QFileInfo fin(filename); + if (!fin.exists()){ + throw MLException(filename + " does not exists."); + } + QPluginLoader loader(fin.absoluteFilePath()); + QObject *plugin = loader.instance(); + if (!plugin) { + throw MLException(fin.fileName() + " does not seem to be a Qt Plugin.\n\n" + loader.errorString()); + } + + MeshLabPlugin* ifp = dynamic_cast(plugin); + if (!ifp){ + throw MLException(fin.fileName() + " is not a MeshLab plugin."); + } + + //check floating point precision of the plugin + if (ifp->getMLVersion().second != MeshLabScalarTest::doublePrecision()) { + throw MLException(fin.fileName() + " has different floating point precision from the running MeshLab version."); + } + + std::string mlVersionPlug = ifp->getMLVersion().first; + /** Rules for the future: **/ + // check version of the plugin + // - needs to be the same major version and + // <= minor version wrt MeshLab version + // example: 2021.01 plugin can run on 2021.03 MeshLab + // 2021.03 plugin cannot run on 2021.01 MeshLab + // 2021.12 plugin cannot run on 2022.01 MeshLab +// std::string majorVersionPlug = mlVersionPlug.substr(0, 4); //4 is the position of '.' in meshlab version +// std::string majorVersionML = meshlab::meshlabVersion().substr(0, 4); +// if (majorVersionML != majorVersionPlug){ +// throw MLException(fin.fileName() + " has different major version from the running MeshLab version."); +// } +// std::string minorVersionPlug = mlVersionPlug.substr(5, mlVersionPlug.size()); +// std::string minorVersionML = meshlab::meshlabVersion().substr(5, meshlab::meshlabVersion().size()); +// if (std::stoi(minorVersionPlug) > std::stoi(minorVersionML)){ +// throw MLException(fin.fileName() + " has greater version from the running MeshLab version. Please update MeshLab to use it."); +// } + + /** Rules for now: plugin needs to have same version of meshlab **/ + if (mlVersionPlug.substr(0, 6) != meshlab::meshlabVersion().substr(0, 6)){ + throw MLException(fin.fileName() + " has different version from the running MeshLab version."); + } + + MeshLabPluginType type(ifp); + + if (!type.isValid()){ + throw MLException(fin.fileName() + " has none of the known plugin types known by this MeshLab version."); + } + + //ToDo: proper checks also for other plugin types... + if (type.isFilterPlugin()){ + checkFilterPlugin(qobject_cast(plugin)); + } + + loader.unload(); + return type; +} + +/** + * @brief Loads the plugins contained in the default meshlab plugin directory. + * + * If at least one plugin fails to be loaded, a MLException is thrown. + * In any case, all the other valid plugins contained in the directory are loaded. + */ +void PluginManager::loadPlugins() +{ + // without adding the correct library path in the mac the loading of jpg (done via qt plugins) fails + // ToDo: get rid of any qApp here + qApp->addLibraryPath(meshlab::defaultPluginPath()); + loadPlugins(QDir(meshlab::defaultPluginPath())); +} + +/** + * @brief Loads the plugins contained in the given directory. + * + * If at least one plugin fails to be loaded, a MLException is thrown. + * In any case, all the other valid plugins contained in the directory are loaded. + */ +void PluginManager::loadPlugins(QDir pluginsDirectory) +{ + if (pluginsDirectory.exists()){ + QStringList nameFiltersPlugins = fileNamePluginDLLs(); + + //only the file with extension pluginfilters will be listed by function entryList() + pluginsDirectory.setNameFilters(nameFiltersPlugins); + + //qDebug("Current Plugins Dir is: %s ", qUtf8Printable(pluginsDirectory.absolutePath())); + std::list> errors; + for(QString fileName : pluginsDirectory.entryList(QDir::Files)) { + try { + loadPlugin(pluginsDirectory.absoluteFilePath(fileName)); + } + catch(const MLException& e){ + errors.push_back(std::make_pair(fileName, e.what())); + } + } + if (errors.size() > 0){ + QString singleError = "Unable to load the following plugins:\n\n"; + for (const auto& p : errors){ + singleError += "\t" + p.first + ": " + p.second + "\n"; + } + throw MLException(singleError); + } + } +} + +/** + * @brief Loads the plugin specified in the given file and adds the plugin into the + * PluginManager. + * + * Note: better to give the absolute path of the plugin file. + * + * Throws a MLException if the load of the plugin fails. + */ +MeshLabPlugin* PluginManager::loadPlugin(const QString& fileName) +{ + QFileInfo fin(fileName); + if (pluginFiles.find(fin.absoluteFilePath()) != pluginFiles.end()) + throw MLException(fin.fileName() + " has been already loaded."); + + checkPlugin(fileName); + + //load the plugin depending on the type (can be more than one type!) + QPluginLoader* loader = new QPluginLoader(fin.absoluteFilePath()); + QObject *plugin = loader->instance(); + MeshLabPlugin* ifp = dynamic_cast(plugin); + MeshLabPluginType type(ifp); + + if (type.isDecoratePlugin()){ + decoratePlugins.pushDecoratePlugin(qobject_cast(plugin)); + } + if (type.isEditPlugin()){ + editPlugins.pushEditPlugin(qobject_cast(plugin)); + } + if (type.isFilterPlugin()){ + filterPlugins.pushFilterPlugin(qobject_cast(plugin)); + } + if (type.isIOPlugin()){ + ioPlugins.pushIOPlugin(qobject_cast(plugin)); + } + if (type.isRenderPlugin()){ + renderPlugins.pushRenderPlugin(qobject_cast(plugin)); + } + + //set the QFileInfo to the plugin, and add it to the continer + //of all plugins + ifp->plugFileInfo = fin; + allPlugins.push_back(ifp); + allPluginLoaders.push_back(loader); + pluginFiles.insert(fin.absoluteFilePath()); + return ifp; +} + +void PluginManager::unloadPlugin(MeshLabPlugin* ifp) +{ + auto it = std::find(allPlugins.begin(), allPlugins.end(), ifp); + if (it != allPlugins.end()){ + unsigned int index = it - allPlugins.begin(); + MeshLabPluginType type(ifp); + if (type.isDecoratePlugin()){ + decoratePlugins.eraseDecoratePlugin(dynamic_cast(ifp)); + } + if (type.isEditPlugin()){ + editPlugins.eraseEditPlugin(dynamic_cast(ifp)); + } + if (type.isFilterPlugin()){ + filterPlugins.eraseFilterPlugin(dynamic_cast(ifp)); + } + if (type.isIOPlugin()){ + ioPlugins.eraseIOPlugin(dynamic_cast(ifp)); + } + if (type.isRenderPlugin()){ + renderPlugins.eraseRenderPlugin(dynamic_cast(ifp)); + } + QPluginLoader* l = allPluginLoaders[index]; + allPluginLoaders.erase(allPluginLoaders.begin() + index); + allPlugins.erase(it); + l->unload(); + delete l; + } +} + +void PluginManager::enablePlugin(MeshLabPlugin* ifp) +{ + auto it = std::find(allPlugins.begin(), allPlugins.end(), ifp); + if (it != allPlugins.end() && !ifp->isEnabled()){ + ifp->enable(); + //ToDo other checks... + } +} + +void PluginManager::disablePlugin(MeshLabPlugin* ifp) +{ + auto it = std::find(allPlugins.begin(), allPlugins.end(), ifp); + if (it != allPlugins.end() && ifp->isEnabled()){ + ifp->disable(); + //ToDo other checks... + } +} + +unsigned int PluginManager::size() const +{ + return allPlugins.size(); +} + +int PluginManager::numberIOPlugins() const +{ + return ioPlugins.size(); +} + +// Search among all the decorator plugins the one that contains a decoration with the given name +DecoratePlugin *PluginManager::getDecoratePlugin(const QString& name) +{ + return decoratePlugins.decoratePlugin(name); +} + +QAction* PluginManager::filterAction(const QString& name) +{ + return filterPlugins.filterAction(name); +} + +FilterPlugin* PluginManager::getFilterPluginFromAction(const QAction *action) const +{ + return filterPlugins.pluginOfFilter(action); +} + +IOPlugin* PluginManager::inputMeshPlugin(const QString& inputFormat) const +{ + return ioPlugins.inputMeshPlugin(inputFormat); +} + +IOPlugin* PluginManager::outputMeshPlugin(const QString& outputFormat) const +{ + return ioPlugins.outputMeshPlugin(outputFormat); +} + +IOPlugin* PluginManager::inputImagePlugin(const QString inputFormat) const +{ + return ioPlugins.inputImagePlugin(inputFormat); +} + +IOPlugin* PluginManager::outputImagePlugin(const QString& outputFormat) const +{ + return ioPlugins.outputImagePlugin(outputFormat); +} + +IOPlugin* PluginManager::inputProjectPlugin(const QString& inputFormat) const +{ + return ioPlugins.inputProjectPlugin(inputFormat); +} + +IOPlugin* PluginManager::outputProjectPlugin(const QString& outputFormat) const +{ + return ioPlugins.outputProjectPlugin(outputFormat); +} + +bool PluginManager::isInputMeshFormatSupported(const QString inputFormat) const +{ + return ioPlugins.isInputMeshFormatSupported(inputFormat); +} + +bool PluginManager::isOutputMeshFormatSupported(const QString outputFormat) const +{ + return ioPlugins.isOutputMeshFormatSupported(outputFormat); +} + +bool PluginManager::isInputImageFormatSupported(const QString inputFormat) const +{ + return ioPlugins.isInputImageFormatSupported(inputFormat); +} + +bool PluginManager::isOutputImageFormatSupported(const QString outputFormat) const +{ + return ioPlugins.isOutputImageFormatSupported(outputFormat); +} + +bool PluginManager::isInputProjectFormatSupported(const QString inputFormat) const +{ + return ioPlugins.isInputProjectFormatSupported(inputFormat); +} + +bool PluginManager::isOutputProjectFormatSupported(const QString outputFormat) const +{ + return ioPlugins.isOutputProjectFormatSupported(outputFormat); +} + +QStringList PluginManager::inputMeshFormatList() const +{ + return ioPlugins.inputMeshFormatList(); +} + +QStringList PluginManager::outputMeshFormatList() const +{ + return ioPlugins.outputMeshFormatList(); +} + +QStringList PluginManager::inputImageFormatList() const +{ + return ioPlugins.inputImageFormatList(); +} + +QStringList PluginManager::outputImageFormatList() const +{ + return ioPlugins.outputImageFormatList(); +} + +QStringList PluginManager::inputProjectFormatList() const +{ + return ioPlugins.inputProjectFormatList(); +} + +QStringList PluginManager::outputProjectFormatList() const +{ + return ioPlugins.outputProjectFormatList(); +} + +QStringList PluginManager::inputMeshFormatListDialog() const +{ + return inputFormatListDialog(ioPluginIterator()); +} + +QStringList PluginManager::outputMeshFormatListDialog() const +{ + return outputFormatListDialog(ioPluginIterator()); +} + +QStringList PluginManager::inputImageFormatListDialog() const +{ + return inputImageFormatListDialog(ioPluginIterator()); +} + +QStringList PluginManager::inputProjectFormatListDialog() const +{ + return inputProjectFormatListDialog(ioPluginIterator()); +} + +QStringList PluginManager::outputProjectFormatListDialog() const +{ + return outputProjectFormatListDialog(ioPluginIterator()); +} + +MeshLabPlugin* PluginManager::operator[](unsigned int i) const +{ + return allPlugins[i]; +} + +PluginManager::PluginRangeIterator PluginManager::pluginIterator(bool iterateAlsoDisabledPlugins) const +{ + return PluginRangeIterator(this, iterateAlsoDisabledPlugins); +} + +FilterPluginContainer::FilterPluginRangeIterator PluginManager::filterPluginIterator(bool iterateAlsoDisabledPlugins) const +{ + return filterPlugins.filterPluginIterator(iterateAlsoDisabledPlugins); +} + +IOPluginContainer::IOPluginRangeIterator PluginManager::ioPluginIterator(bool iterateAlsoDisabledPlugins) const +{ + return ioPlugins.ioPluginIterator(iterateAlsoDisabledPlugins); +} + +RenderPluginContainer::RenderPluginRangeIterator PluginManager::renderPluginIterator(bool iterateAlsoDisabledPlugins) const +{ + return renderPlugins.renderPluginIterator(iterateAlsoDisabledPlugins); +} + +DecoratePluginContainer::DecoratePluginRangeIterator PluginManager::decoratePluginIterator(bool iterateAlsoDisabledPlugins) const +{ + return decoratePlugins.decoratePluginIterator(iterateAlsoDisabledPlugins); +} + +EditPluginContainer::EditPluginFactoryRangeIterator PluginManager::editPluginFactoryIterator(bool iterateAlsoDisabledPlugins) const +{ + return editPlugins.editPluginIterator(iterateAlsoDisabledPlugins); +} + +void PluginManager::checkFilterPlugin(FilterPlugin* iFilter) +{ + for(QAction *filterAction : iFilter->actions()) { + if(iFilter->getClass(filterAction)==FilterPlugin::Generic){ + throw MLException("Missing class for " + iFilter->pluginName() + " " + filterAction->text()); + } + if(iFilter->getRequirements(filterAction) == int(MeshModel::MM_UNKNOWN)){ + throw MLException("Missing requirements for " + iFilter->pluginName() + " " + filterAction->text()); + } + if(iFilter->getPreConditions(filterAction) == int(MeshModel::MM_UNKNOWN)){ + throw MLException("Missing preconditions for "+ iFilter->pluginName() + " " + filterAction->text()); + } + if(iFilter->postCondition(filterAction) == int(MeshModel::MM_UNKNOWN)) { + throw MLException("Missing postcondition for "+ iFilter->pluginName() + " " + filterAction->text()); + } + if(iFilter->filterArity(filterAction) == FilterPlugin::UNKNOWN_ARITY) { + throw MLException("Missing Arity for " + iFilter->pluginName() + " " + filterAction->text()); + } + } +} + +template +QStringList PluginManager::inputFormatListDialog(RangeIterator iterator) +{ + QString allKnownFormats = QObject::tr("All known formats ("); + QStringList inputFormatsDialogStringList; + for (auto io : iterator){ + QString allKnownFormatsFilter; + for (const FileFormat& currentFormat : io->importFormats()){ + QString currentFilterEntry = currentFormat.description + " ("; + for (QString currentExtension : currentFormat.extensions) { + currentExtension = currentExtension.toLower(); + allKnownFormatsFilter.append(QObject::tr(" *.")); + allKnownFormatsFilter.append(currentExtension); + currentFilterEntry.append(QObject::tr(" *.")); + currentFilterEntry.append(currentExtension); + } + currentFilterEntry.append(')'); + inputFormatsDialogStringList.append(currentFilterEntry); + } + allKnownFormats += allKnownFormatsFilter; + } + allKnownFormats.append(')'); + inputFormatsDialogStringList.push_front(allKnownFormats); + return inputFormatsDialogStringList; +} + +template +QStringList PluginManager::outputFormatListDialog(RangeIterator iterator) +{ + QStringList outputFormatsDialogStringList; + for (auto io : iterator){ + for (const FileFormat& currentFormat : io->exportFormats()){ + QString currentFilterEntry = currentFormat.description + " ("; + for (QString currentExtension : currentFormat.extensions) { + currentExtension = currentExtension.toLower(); + currentFilterEntry.append(QObject::tr(" *.")); + currentFilterEntry.append(currentExtension); + } + currentFilterEntry.append(')'); + outputFormatsDialogStringList.append(currentFilterEntry); + } + } + return outputFormatsDialogStringList; +} + +template +QStringList PluginManager::inputImageFormatListDialog(RangeIterator iterator) +{ + QString allKnownFormats = QObject::tr("All known formats ("); + QStringList inputImageFormatsDialogStringList; + for (auto io : iterator){ + QString allKnownFormatsFilter; + for (const FileFormat& currentFormat : io->importImageFormats()){ + QString currentFilterEntry = currentFormat.description + " ("; + for (QString currentExtension : currentFormat.extensions) { + currentExtension = currentExtension.toLower(); + allKnownFormatsFilter.append(QObject::tr(" *.")); + allKnownFormatsFilter.append(currentExtension); + currentFilterEntry.append(QObject::tr(" *.")); + currentFilterEntry.append(currentExtension); + } + currentFilterEntry.append(')'); + inputImageFormatsDialogStringList.append(currentFilterEntry); + } + allKnownFormats += allKnownFormatsFilter; + } + allKnownFormats.append(')'); + inputImageFormatsDialogStringList.push_front(allKnownFormats); + return inputImageFormatsDialogStringList; +} + +template +QStringList PluginManager::inputProjectFormatListDialog(RangeIterator iterator) +{ + QString allKnownFormats = QObject::tr("All known formats ("); + QStringList inputProjectFormatsDialogStringList; + for (auto io : iterator){ + QString allKnownFormatsFilter; + for (const FileFormat& currentFormat : io->importProjectFormats()){ + QString currentFilterEntry = currentFormat.description + " ("; + for (QString currentExtension : currentFormat.extensions) { + currentExtension = currentExtension.toLower(); + allKnownFormatsFilter.append(QObject::tr(" *.")); + allKnownFormatsFilter.append(currentExtension); + currentFilterEntry.append(QObject::tr(" *.")); + currentFilterEntry.append(currentExtension); + } + currentFilterEntry.append(')'); + inputProjectFormatsDialogStringList.append(currentFilterEntry); + } + allKnownFormats += allKnownFormatsFilter; + } + allKnownFormats.append(')'); + inputProjectFormatsDialogStringList.push_front(allKnownFormats); + return inputProjectFormatsDialogStringList; +} + +template +QStringList PluginManager::outputProjectFormatListDialog(RangeIterator iterator) +{ + QStringList outputProjectFormatsDialogStringList; + for (auto io : iterator){ + for (const FileFormat& currentFormat : io->exportProjectFormats()){ + QString currentFilterEntry = currentFormat.description + " ("; + for (QString currentExtension : currentFormat.extensions) { + currentExtension = currentExtension.toLower(); + currentFilterEntry.append(QObject::tr(" *.")); + currentFilterEntry.append(currentExtension); + } + currentFilterEntry.append(')'); + outputProjectFormatsDialogStringList.append(currentFilterEntry); + } + } + return outputProjectFormatsDialogStringList; +} + +ConstPluginIterator PluginManager::PluginRangeIterator::begin() +{ + return ConstPluginIterator(pm->allPlugins, pm->allPlugins.begin(), b); +} + +ConstPluginIterator PluginManager::PluginRangeIterator::end() +{ + return ConstPluginIterator(pm->allPlugins, pm->allPlugins.end(), b); +} + +PluginManager::PluginRangeIterator::PluginRangeIterator(const PluginManager* pm, bool iterateAlsoDisabledPlugins) : + pm(pm), b(iterateAlsoDisabledPlugins) +{ +} diff --git a/src/common/plugins/plugin_manager.h b/src/common/plugins/plugin_manager.h new file mode 100644 index 000000000..1bb1769c5 --- /dev/null +++ b/src/common/plugins/plugin_manager.h @@ -0,0 +1,145 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef MESHLAB_PLUGIN_MANAGER_H +#define MESHLAB_PLUGIN_MANAGER_H + +#include "containers/decorate_plugin_container.h" +#include "containers/edit_plugin_container.h" +#include "containers/filter_plugin_container.h" +#include "containers/io_plugin_container.h" +#include "containers/render_plugin_container.h" +#include "meshlab_plugin_type.h" + +#include +#include + +/** + * @brief The PluginManager class provides the basic tools for managing all the plugins. + */ +class PluginManager +{ +public: + PluginManager(); + ~PluginManager(); + + class PluginRangeIterator; + + /** Member functions **/ + static MeshLabPluginType checkPlugin(const QString& filename); + + void loadPlugins(); + void loadPlugins(QDir pluginsDirectory); + MeshLabPlugin* loadPlugin(const QString& filename); + void unloadPlugin(MeshLabPlugin* ifp); + + void enablePlugin(MeshLabPlugin* ifp); + void disablePlugin(MeshLabPlugin* ifp); + + unsigned int size() const; + int numberIOPlugins() const; + + DecoratePlugin* getDecoratePlugin(const QString& name); + + QAction* filterAction(const QString& name); + FilterPlugin* getFilterPluginFromAction(const QAction* action) const; + + IOPlugin* inputMeshPlugin(const QString& inputFormat) const; + IOPlugin* outputMeshPlugin(const QString& outputFormat) const; + IOPlugin* inputImagePlugin(const QString inputFormat) const; + IOPlugin* outputImagePlugin(const QString& outputFormat) const; + IOPlugin* inputProjectPlugin(const QString& inputFormat) const; + IOPlugin* outputProjectPlugin(const QString& outputFormat) const; + bool isInputMeshFormatSupported(const QString inputFormat) const; + bool isOutputMeshFormatSupported(const QString outputFormat) const; + bool isInputImageFormatSupported(const QString inputFormat) const; + bool isOutputImageFormatSupported(const QString outputFormat) const; + bool isInputProjectFormatSupported(const QString inputFormat) const; + bool isOutputProjectFormatSupported(const QString outputFormat) const; + QStringList inputMeshFormatList() const; + QStringList outputMeshFormatList() const; + QStringList inputImageFormatList() const; + QStringList outputImageFormatList() const; + QStringList inputProjectFormatList() const; + QStringList outputProjectFormatList() const; + QStringList inputMeshFormatListDialog() const; + QStringList outputMeshFormatListDialog() const; + QStringList inputImageFormatListDialog() const; + QStringList inputProjectFormatListDialog() const; + QStringList outputProjectFormatListDialog() const; + + MeshLabPlugin* operator [](unsigned int i) const; + + /** Member functions for range iterators **/ + PluginRangeIterator pluginIterator(bool iterateAlsoDisabledPlugins = false) const; + FilterPluginContainer::FilterPluginRangeIterator filterPluginIterator(bool iterateAlsoDisabledPlugins = false) const; + IOPluginContainer::IOPluginRangeIterator ioPluginIterator(bool iterateAlsoDisabledPlugins = false) const; + RenderPluginContainer::RenderPluginRangeIterator renderPluginIterator(bool iterateAlsoDisabledPlugins = false) const; + DecoratePluginContainer::DecoratePluginRangeIterator decoratePluginIterator(bool iterateAlsoDisabledPlugins = false) const; + EditPluginContainer::EditPluginFactoryRangeIterator editPluginFactoryIterator(bool iterateAlsoDisabledPlugins = false) const; + +private: + //all plugins + std::vector allPlugins; + std::vector allPluginLoaders; + std::set pluginFiles; //used to check if a plugin file has been already loaded + + //Plugin containers: used for better organization of each type of plugin + // note: these containers do not own any plugin. Plugins are owned by the PluginManager + IOPluginContainer ioPlugins; + FilterPluginContainer filterPlugins; + RenderPluginContainer renderPlugins; + DecoratePluginContainer decoratePlugins; + EditPluginContainer editPlugins; + + static void checkFilterPlugin(FilterPlugin* iFilter); + + template + static QStringList inputFormatListDialog(RangeIterator iterator); + + template + static QStringList outputFormatListDialog(RangeIterator iterator); + + template + static QStringList inputImageFormatListDialog(RangeIterator iterator); + + template + static QStringList inputProjectFormatListDialog(RangeIterator iterator); + + template + static QStringList outputProjectFormatListDialog(RangeIterator iterator); +}; + +class PluginManager::PluginRangeIterator +{ + friend class PluginManager; +public: + ConstPluginIterator begin(); + ConstPluginIterator end(); +private: + PluginRangeIterator(const PluginManager* pm, bool iterateAlsoDisabledPlugins = false); + const PluginManager* pm; + bool b; +}; + +#endif // MESHLAB_PLUGIN_MANAGER_H diff --git a/src/common/python/function.cpp b/src/common/python/function.cpp new file mode 100644 index 000000000..5679f9b0f --- /dev/null +++ b/src/common/python/function.cpp @@ -0,0 +1,122 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#include "function.h" + +#include +#include + +pymeshlab::Function::Function() +{ +} + +pymeshlab::Function::Function( + const QString pythonFunctionName, + const QString meshlabFilterName, + const QString description) : + pythonFunName(pythonFunctionName), meshlabFunName(meshlabFilterName), funDescription(description) +{ +} + +void pymeshlab::Function::addParameter(const pymeshlab::FunctionParameter& p) +{ + parameters.push_back(p); +} + +QString pymeshlab::Function::pythonFunctionName() const +{ + return pythonFunName; +} + +QString pymeshlab::Function::meshlabFunctionName() const +{ + return meshlabFunName; +} + +QString pymeshlab::Function::description() const +{ + return funDescription; +} + +void pymeshlab::Function::setPythonFunctionName(const QString& newName) +{ + pythonFunName = newName; +} + +void pymeshlab::Function::setDescription(const QString& newDescription) +{ + funDescription = newDescription; +} + +unsigned int pymeshlab::Function::parametersNumber() const +{ + return parameters.size(); +} + +QStringList pymeshlab::Function::pythonFunctionParameters() const +{ + QStringList list; + for (const FunctionParameter& p : parameters) + list.push_back(p.pythonName()); + return list; +} + +bool pymeshlab::Function::contains(const QString& pythonParameter) const +{ + iterator it = std::find_if(parameters.begin(), parameters.end(), + [&pythonParameter](const FunctionParameter& x) + { + return x.pythonName() == pythonParameter; + }); + return it != parameters.end(); +} + +const pymeshlab::FunctionParameter& pymeshlab::Function::getFilterFunctionParameter( + const QString& pythonParameter) const +{ + iterator it = std::find_if(parameters.begin(), parameters.end(), + [&pythonParameter](const FunctionParameter& x) + { + return x.pythonName() == pythonParameter; + }); + return *it; +} + +bool pymeshlab::Function::isDeprecated() const +{ + return !deprecatedMessage.empty(); +} + +std::string pymeshlab::Function::deprecatedString() const +{ + return deprecatedMessage; +} + +void pymeshlab::Function::setDeprecated(const std::string& message) +{ + deprecatedMessage = message; +} + +bool pymeshlab::Function::operator<(const pymeshlab::Function& oth) const +{ + return pythonFunName < oth.pythonFunName; +} diff --git a/src/common/python/function.h b/src/common/python/function.h new file mode 100644 index 000000000..972ce81c7 --- /dev/null +++ b/src/common/python/function.h @@ -0,0 +1,75 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#ifndef PYMESHLAB_FUNCTION_H +#define PYMESHLAB_FUNCTION_H + +#include "function_parameter.h" + +#include +#include +#include + +namespace pymeshlab { + +/** + * @brief The Function class represents a python function that can be binded with + * a plugin action. A function has its python name, its meshlab name, its description + * and a list of parameters. + */ +class Function +{ +public: + Function(); + Function(const QString pythonFunName, const QString meshlabFunName, const QString description); + void addParameter(const FunctionParameter& p); + QString pythonFunctionName() const; + QString meshlabFunctionName() const; + QString description() const; + void setPythonFunctionName(const QString& newName); + void setDescription(const QString& newDescription); + unsigned int parametersNumber() const; + QStringList pythonFunctionParameters() const; + bool contains(const QString& pythonParameter) const; + const FunctionParameter& getFilterFunctionParameter(const QString& pythonParameter) const; + bool isDeprecated() const; + std::string deprecatedString() const; + void setDeprecated(const std::string& message); + + bool operator< (const Function& oth) const; + + using iterator = std::list::const_iterator; + + iterator begin() const {return parameters.begin();} + iterator end() const {return parameters.end();} + +private: + QString pythonFunName; + QString meshlabFunName; + QString funDescription; + std::list parameters; + std::string deprecatedMessage; +}; + +} + +#endif // PYMESHLAB_FUNCTION_H diff --git a/src/common/python/function_parameter.cpp b/src/common/python/function_parameter.cpp new file mode 100644 index 000000000..685b812ba --- /dev/null +++ b/src/common/python/function_parameter.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#include "function_parameter.h" + +#include "python_utils.h" +#include "../parameters/rich_parameter_list.h" + +pymeshlab::FunctionParameter::FunctionParameter(const RichParameter& parameter) : + parameter(parameter.clone()) +{ +} + +pymeshlab::FunctionParameter::FunctionParameter( + const pymeshlab::FunctionParameter& oth): + parameter(oth.parameter->clone()) +{ +} + +pymeshlab::FunctionParameter::FunctionParameter(pymeshlab::FunctionParameter&& oth) +{ + parameter = oth.parameter; + oth.parameter = nullptr; +} + +pymeshlab::FunctionParameter::~FunctionParameter() +{ + delete parameter; +} + +QString pymeshlab::FunctionParameter::pythonName() const +{ + return parameter->pythonName(); +} + +QString pymeshlab::FunctionParameter::meshlabName() const +{ + return parameter->name(); +} + +QString pymeshlab::FunctionParameter::pythonTypeString() const +{ + return parameter->pythonType(); +} + +QString pymeshlab::FunctionParameter::meshlabTypeString() const +{ + return parameter->stringType(); +} + +QString pymeshlab::FunctionParameter::description() const +{ + if (parameter){ + return parameter->fieldDescription(); + } + return QString(); +} + +QString pymeshlab::FunctionParameter::longDescription() const +{ + if (parameter){ + return parameter->toolTip(); + } + return QString(); +} + +const Value& pymeshlab::FunctionParameter::defaultValue() const +{ + return parameter->value(); +} + +const RichParameter& pymeshlab::FunctionParameter::richParameter() const +{ + return *parameter; +} + +void pymeshlab::FunctionParameter::printDefaultValue(std::ostream& o) const +{ + if (!parameter) { + o << "no_value"; + return; + } + if (parameter->isOfType()) { + o << (parameter->value().getBool() ? "True" : "False"); + return; + } + if (parameter->isOfType()) { + o << parameter->value().getInt(); + return; + } + if (parameter->isOfType()){ + o << parameter->value().getFloat(); + return; + } + if (parameter->isOfType()){ + o << "'" << parameter->value().getString().toStdString() << "'"; + return; + } + if (parameter->isOfType()) { + RichEnum* ren = dynamic_cast(parameter); + o << "'" << ren->enumvalues.at(ren->value().getInt()).toStdString() << "'"; + return; + } + if (parameter->isOfType()) { + RichPercentage* rabs = dynamic_cast(parameter); + float abs = parameter->value().getFloat(); + float perc = (abs - rabs->min) / (rabs->max - rabs->min) * 100; + o << perc << "%"; + return; + } + if (parameter->isOfType()) { + RichDynamicFloat* rdyn = dynamic_cast(parameter); + o << parameter->value().getFloat() << + " [min: " << rdyn->min << "; max: " << rdyn->max << "]"; + return; + } + if (parameter->isOfType()){ + const MESHLAB_SCALAR* v = parameter->value().getMatrix44().V(); + o << "[[" << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << "]," + << "[" << v[4] << ", " << v[5] << ", " << v[6] << ", " << v[7] << "]," + << "[" << v[8] << ", " << v[9] << ", " << v[10] << ", " << v[11] << "]," + << "[" << v[12] << ", " << v[13] << ", " << v[14] << ", " << v[15] << "]]"; + return; + } + if (parameter->isOfType() || parameter->isOfType()) { + o << "[" << parameter->value().getPoint3().X() << ", " + << parameter->value().getPoint3().Y() << ", " + << parameter->value().getPoint3().Z() << "]"; + return; + } + if (parameter->isOfType()) { + o << "None"; + return; + } + if (parameter->isOfType()) { + QColor c = parameter->value().getColor(); + o << + "[" + std::to_string(c.red()) + "; " + + std::to_string(c.green()) + "; " + + std::to_string(c.blue()) + "; " + + std::to_string(c.alpha()) + "]"; + return; + } + if (parameter->isOfType()){ + const RichMesh* rm = dynamic_cast(parameter); + o << rm->value().getInt(); + return; + } + if (parameter->isOfType() || parameter->isOfType()){ + o << "'" << parameter->value().getString().toStdString() << "'"; + return; + } +} + +QString pymeshlab::FunctionParameter::defaultValueString() const +{ + std::stringstream ss; + printDefaultValue(ss); + return QString::fromStdString(ss.str()); +} + +pymeshlab::FunctionParameter& pymeshlab::FunctionParameter::operator=(pymeshlab::FunctionParameter oth) +{ + this->swap(oth); + return *this; +} + +bool pymeshlab::FunctionParameter::operator<(const pymeshlab::FunctionParameter& oth) const +{ + return parameter->pythonName() < oth.parameter->pythonName(); +} + +bool pymeshlab::FunctionParameter::operator==(const pymeshlab::FunctionParameter& oth) const +{ + return parameter->pythonName() == oth.parameter->pythonName(); +} + +void pymeshlab::FunctionParameter::swap(pymeshlab::FunctionParameter& oth) +{ + std::swap(parameter, oth.parameter); +} diff --git a/src/common/python/function_parameter.h b/src/common/python/function_parameter.h new file mode 100644 index 000000000..d8faa8405 --- /dev/null +++ b/src/common/python/function_parameter.h @@ -0,0 +1,61 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#ifndef PYMESHLAB_FUNCTION_PARAMETER_H +#define PYMESHLAB_FUNCTION_PARAMETER_H + +#include + +class Value; +class RichParameter; + +namespace pymeshlab { + +class FunctionParameter +{ +public: + FunctionParameter(const RichParameter& parameter); + FunctionParameter(const FunctionParameter& oth); + FunctionParameter(FunctionParameter&& oth); + virtual ~FunctionParameter(); + QString pythonName() const; + QString meshlabName() const; + QString pythonTypeString() const; + QString meshlabTypeString() const; + QString description() const; + QString longDescription() const; + const Value& defaultValue() const; + const RichParameter& richParameter() const; + void printDefaultValue(std::ostream& o) const; + QString defaultValueString() const; + + FunctionParameter& operator=(FunctionParameter oth); + bool operator< (const FunctionParameter& oth) const; + bool operator==(const FunctionParameter& oth) const; + void swap(FunctionParameter& oth); +private: + RichParameter* parameter; +}; + +} + +#endif // PYMESHLAB_FUNCTION_PARAMETER_H diff --git a/src/common/python/function_set.cpp b/src/common/python/function_set.cpp new file mode 100644 index 000000000..f7fbf522a --- /dev/null +++ b/src/common/python/function_set.cpp @@ -0,0 +1,268 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#include "function_set.h" + +#include +#include "../mlexception.h" +#include +#include "python_utils.h" +#include + +pymeshlab::FunctionSet::FunctionSet() +{ +} + +pymeshlab::FunctionSet::FunctionSet(const PluginManager& pm) +{ + //dummy MeshDocument use to compute default value parameters + //the mesh used is a 1x1x1 cube (with extremes [-0.5; 0.5]) + initDummyMeshDocument(); + + for (IOPlugin* iop : pm.ioPluginIterator()){ + loadIOPlugin(iop); + } + + for (FilterPlugin* fp : pm.filterPluginIterator()){ + loadFilterPlugin(fp); + } +} + +void pymeshlab::FunctionSet::loadFilterPlugin(FilterPlugin* fp) +{ + for (QAction* act : fp->actions()) { + QString originalFilterName = fp->filterName(act); + QString description = fp->filterInfo(act); + QString pythonFilterName = fp->pythonFilterName(act); + Function f(pythonFilterName, originalFilterName, description); + + RichParameterList rps = fp->initParameterList(act, dummyMeshDocument); + + for (const RichParameter& rp : rps){ + FunctionParameter par(rp); + f.addParameter(par); + } + filterSet.insert(f); + } +} + +void pymeshlab::FunctionSet::loadIOPlugin(IOPlugin* iop) +{ + for (const FileFormat& ff : iop->importFormats()){ + for (const QString& inputFormat : ff.extensions){ + QString originalFilterName = inputFormat.toLower(); + QString pythonFilterName = inputFormat.toLower(); + Function f(pythonFilterName, originalFilterName, "Load " + inputFormat + " format."); + RichParameterList rps = iop->initPreOpenParameter(inputFormat); + + //filename parameter + QString sv = "file_name." + inputFormat; + QStringList sl(inputFormat); + RichFileOpen of("file_name", sv, sl, "File Name", "The name of the file to load"); + FunctionParameter par(of); + f.addParameter(par); + + for (const RichParameter& rp : rps){ + FunctionParameter par(rp); + f.addParameter(par); + } + loadMeshSet.insert(f); + } + } + + for (const FileFormat& ff : iop->exportFormats()){ + for (const QString& outputFormat : ff.extensions){ + QString originalFilterName = outputFormat.toLower(); + QString pythonFilterName = outputFormat.toLower(); + Function f(pythonFilterName, originalFilterName, "Save " + outputFormat + " format."); + RichParameterList rps = iop->initSaveParameter(outputFormat, *dummyMeshDocument.mm()); + if (outputFormat.toUpper() == "PLY"){ + f.setDescription( + "Save PLY format.


Ply exporter also support saving custom attributes. " + "You'll need to add an " + "additional boolean parameter for each one of that you want to save, and use " + "only non-capital letters for parameter names. These parameters have a prefix " + "for each type of custom attribute:
" + "
    " + "
  • __ca_vs__: Custom Attribute Vertex Scalar;
  • " + "
  • __ca_vp__: Custom Attribute Vertex Point;
  • " + "
  • __ca_fs__: Custom Attribute Face Scalar;
  • " + "
  • __ca_fp__: Custom Attribute Face Point;
  • " + "
For example, if your mesh has a custom per vertex scalar attribute " + "called MyAttribute, you can save it in a ply file by " + "calling:
" + "ms.save_current_mesh(file_name='myfile.ply', __ca_vs__myattribute=True)" + "
You can check the parameters available on a mesh by calling the " + "MeshSet method MeshSet.filter_parameter_values, with first " + "parameter 'ply'."); + } + //filename parameter + QString sv = "file_name." + outputFormat; + RichFileSave of("file_name", sv, outputFormat, "File Name", "The name of the file to save"); + FunctionParameter par(of); + f.addParameter(par); + + for (const RichParameter& rp : rps){ + FunctionParameter par(rp); + f.addParameter(par); + } + + //data to save + updateSaveParameters(iop, outputFormat, f); + + saveMeshSet.insert(f); + } + } + + for (const FileFormat& ff : iop->importImageFormats()){ + for (const QString& inputImageFormat : ff.extensions){ + QString originalFilterName = inputImageFormat; + QString pythonFilterName = inputImageFormat.toLower(); + Function f(pythonFilterName, originalFilterName, "Load " + inputImageFormat + " format."); + + //filename parameter + QString sv = "file_name." + inputImageFormat; + QStringList sl(inputImageFormat); + RichFileOpen of("file_name", sv, sl, "File Name", "The name of the file to load"); + FunctionParameter par(of); + f.addParameter(par); + + loadImageSet.insert(f); + } + } +} + +std::list pymeshlab::FunctionSet::pythonFilterFunctionNames() const +{ + std::list fnames; + for (const Function& f: filterSet){ + fnames.push_back(f.pythonFunctionName().toStdString()); + } + return fnames; +} + +const pymeshlab::Function& pymeshlab::FunctionSet::filterFunction(const QString& pythonFunctionName) const +{ + auto it = filterSet.find(Function(pythonFunctionName, "", "")); + if (it == filterSet.end()) + throw MLException(pythonFunctionName + " filter not found."); + return *it; +} + +bool pymeshlab::FunctionSet::containsFilterFunction(const QString& pythonFunctionName) const +{ + return filterSet.find(Function(pythonFunctionName, "", "")) != filterSet.end(); +} + +const pymeshlab::Function& pymeshlab::FunctionSet::loadMeshFunction(const QString& pythonFunctionName) const +{ + auto it = loadMeshSet.find(Function(pythonFunctionName, "", "")); + if (it == loadMeshSet.end()) + throw MLException(pythonFunctionName + " format for loading mesh not found."); + return *it; +} + +bool pymeshlab::FunctionSet::containsLoadMeshFunction(const QString& pythonFunctionName) const +{ + return loadMeshSet.find(Function(pythonFunctionName, "", "")) != loadMeshSet.end(); +} + +const pymeshlab::Function& pymeshlab::FunctionSet::saveMeshFunction(const QString& pythonFunctionName) const +{ + auto it = saveMeshSet.find(Function(pythonFunctionName, "", "")); + if (it == saveMeshSet.end()) + throw MLException(pythonFunctionName + " format for saving mesh not found."); + return *it; +} + +bool pymeshlab::FunctionSet::containsSaveMeshFunction(const QString& pythonFunctionName) const +{ + return saveMeshSet.find(Function(pythonFunctionName, "", "")) != saveMeshSet.end(); +} + +const pymeshlab::Function& pymeshlab::FunctionSet::loadRasterFunction(const QString& pythonFunctionName) const +{ + auto it = loadImageSet.find(Function(pythonFunctionName, "", "")); + if (it == loadImageSet.end()) + throw MLException(pythonFunctionName + " format for loading raster not found."); + return *it; +} + +bool pymeshlab::FunctionSet::containsLoadRasterFunction(const QString& pythonFunctionName) const +{ + return loadImageSet.find(Function(pythonFunctionName, "", "")) != loadImageSet.end(); +} + +pymeshlab::FunctionSet::FunctionRangeIterator pymeshlab::FunctionSet::filterFunctionIterator() const +{ + return FunctionRangeIterator(filterSet); +} + +pymeshlab::FunctionSet::FunctionRangeIterator pymeshlab::FunctionSet::loadMeshFunctionIterator() const +{ + return FunctionRangeIterator(loadMeshSet); +} + +pymeshlab::FunctionSet::FunctionRangeIterator pymeshlab::FunctionSet::saveMeshFunctionIterator() const +{ + return FunctionRangeIterator(saveMeshSet); +} + +pymeshlab::FunctionSet::FunctionRangeIterator pymeshlab::FunctionSet::loadRasterFunctionIterator() const +{ + return FunctionRangeIterator(loadImageSet); +} + +void pymeshlab::FunctionSet::updateSaveParameters(IOPlugin* plugin, + const QString& outputFormat, + pymeshlab::Function& f) +{ + int capabilityBits, defaultBits; + plugin->exportMaskCapability(outputFormat, capabilityBits, defaultBits); + + for (unsigned int i = 0; i < capabilitiesBits.size(); ++i){ + if (capabilityBits & capabilitiesBits[i]){ + bool def = defaultBits & capabilitiesBits[i]; + RichBool rb( + saveCapabilitiesStrings[i], def, + saveCapabilitiesStrings[i], saveCapabilitiesStrings[i]); + FunctionParameter par(rb); + f.addParameter(par); + + } + } + + +} + +void pymeshlab::FunctionSet::initDummyMeshDocument() +{ + dummyMeshDocument.clear(); + Box3m b(Point3m(-0.5,-0.5,-0.5),Point3m(0.5,0.5,0.5)); + CMeshO dummyMesh; + vcg::tri::Box(dummyMesh,b); + dummyMeshDocument.addNewMesh(dummyMesh, "cube"); + int mask = 0; + mask |= vcg::tri::io::Mask::IOM_VERTQUALITY; + mask |= vcg::tri::io::Mask::IOM_FACEQUALITY; + dummyMeshDocument.mm()->enable(mask); +} diff --git a/src/common/python/function_set.h b/src/common/python/function_set.h new file mode 100644 index 000000000..94390d00d --- /dev/null +++ b/src/common/python/function_set.h @@ -0,0 +1,106 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#ifndef PYMESHLAB_FUNCTION_SET_H +#define PYMESHLAB_FUNCTION_SET_H + +#include "../plugins/plugin_manager.h" +#include "function.h" + +namespace pymeshlab { + +/** + * @brief The FunctionSet class represents a container of "python function names". + * Each one of these function is binded with a particular action of a plugin, + * which can be a filter action, an input/output mesh format or an input raster + * format. Therefore, given a PluginManager, a FunctionSet will be constructed + * from it considering only Filter and IO type of plugins. + * + * Note: there is not the actual link between the function and the action here. + * This container is meant just as a container of *names*, therefore from here + * you can check if a particular function exists, if it has some parameters and + * the parameter types, and get the *name* of the binded action in meshlab. + * + * This cointainer just allows to access and iterate through all the contained + * Functions. Please refer to the pymeshlab::Function class to see how to manage + * a Function. + */ +class FunctionSet +{ +public: + FunctionSet(); + FunctionSet(const PluginManager& pm); + + //load plugins + void loadFilterPlugin(FilterPlugin* fp); + void loadIOPlugin(IOPlugin* iop); + + std::list pythonFilterFunctionNames() const; + + const Function& filterFunction(const QString& pythonFunctionName) const; + bool containsFilterFunction(const QString& pythonFunctionName) const; + + const Function& loadMeshFunction(const QString& pythonFunctionName) const; + bool containsLoadMeshFunction(const QString& pythonFunctionName) const; + + const Function& saveMeshFunction(const QString& pythonFunctionName) const; + bool containsSaveMeshFunction(const QString& pythonFunctionName) const; + + const Function& loadRasterFunction(const QString& pythonFunctionName) const; + bool containsLoadRasterFunction(const QString& pythonFunctionName) const; + + //iterators + class FunctionRangeIterator + { + friend class FunctionSet; + public: + std::set::const_iterator begin() { return s.begin();} + std::set::const_iterator end() {return s.end();} + private: + FunctionRangeIterator(const std::set& s) : s(s) {}; + const std::set& s; + }; + + FunctionRangeIterator filterFunctionIterator() const; + FunctionRangeIterator loadMeshFunctionIterator() const; + FunctionRangeIterator saveMeshFunctionIterator() const; + FunctionRangeIterator loadRasterFunctionIterator() const; + +private: + void updateSaveParameters( + IOPlugin* plugin, + const QString& outputFormat, + Function& f); + + void initDummyMeshDocument(); + + MeshDocument dummyMeshDocument; + + std::set filterSet; + std::set loadMeshSet; + std::set saveMeshSet; + std::set loadImageSet; +}; + +} + +#endif // PYMESHLAB_FUNCTION_SET_H diff --git a/src/common/python/python_utils.cpp b/src/common/python/python_utils.cpp new file mode 100644 index 000000000..20429a91c --- /dev/null +++ b/src/common/python/python_utils.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2004-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "python_utils.h" + +#include + +#include + +QString pymeshlab::computePythonTypeString(const RichParameter& par) +{ + if (par.isOfType()) + return PYTHON_TYPE_ENUM; + if (par.isOfType()) + return PYTHON_TYPE_ABSPERC; + if (par.isOfType()) + return PYTHON_TYPE_DYNAMIC_FLOAT; + if (par.isOfType()) + return PYTHON_TYPE_BOOL; + if (par.isOfType()) + return PYTHON_TYPE_INT; + if (par.isOfType()) + return PYTHON_TYPE_FLOAT; + if (par.isOfType()) + return PYTHON_TYPE_STRING; + if (par.isOfType()) + return PYTHON_TYPE_MATRIX44F; + if (par.isOfType()) + return PYTHON_TYPE_POINT3F; + if (par.isOfType()) + return PYTHON_TYPE_POINT3F; + if (par.isOfType()) + return PYTHON_TYPE_SHOTF; + if (par.isOfType()) + return PYTHON_TYPE_COLOR; + if (par.isOfType()) + return PYTHON_TYPE_MESH; + if (par.isOfType() || par.isOfType()) + return PYTHON_TYPE_FILENAME; + return "still_unsupported"; +} + +QString pymeshlab::computePythonName(const QString& name) +{ + static const QRegularExpression rgexp("[().,'\":+]+"); + QString pythonName = name.toLower(); + pythonName.replace(' ', '_'); + pythonName.replace('/', '_'); + pythonName.replace('-', '_'); + pythonName.remove(rgexp); + + if (pythonKeywords.contains(pythonName)) + pythonName += "_"; + return pythonName; +} + +void pymeshlab::printSaveMask(int mask) +{ + for (uint i = 0; i < 14; i++){ + if (mask & capabilitiesBits[i]) + std::cout << saveCapabilitiesStrings[i].toStdString() << "\n"; + } +} diff --git a/src/common/python/python_utils.h b/src/common/python/python_utils.h new file mode 100644 index 000000000..7344b88db --- /dev/null +++ b/src/common/python/python_utils.h @@ -0,0 +1,100 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2004-2021 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef PYMESHLAB_PYTHON_UTILS_H +#define PYMESHLAB_PYTHON_UTILS_H + +#include +#include +#include + +class RichParameter; + +namespace pymeshlab { + +const static std::array capabilitiesBits= { + vcg::tri::io::Mask::IOM_VERTQUALITY, + vcg::tri::io::Mask::IOM_VERTFLAGS, + vcg::tri::io::Mask::IOM_VERTCOLOR, + vcg::tri::io::Mask::IOM_VERTTEXCOORD, + vcg::tri::io::Mask::IOM_VERTNORMAL, + vcg::tri::io::Mask::IOM_VERTRADIUS, + vcg::tri::io::Mask::IOM_FACEQUALITY, + vcg::tri::io::Mask::IOM_FACEFLAGS, + vcg::tri::io::Mask::IOM_FACECOLOR, + vcg::tri::io::Mask::IOM_FACENORMAL, + vcg::tri::io::Mask::IOM_WEDGCOLOR, + vcg::tri::io::Mask::IOM_WEDGTEXCOORD, + vcg::tri::io::Mask::IOM_WEDGNORMAL, + vcg::tri::io::Mask::IOM_BITPOLYGONAL +}; + +const static std::array saveCapabilitiesStrings = { + "Save Vertex Quality", + "Save Vertex Flag", + "Save Vertex Color", + "Save Vertex Coord", + "Save Vertex Normal", + "Save Vertex Radius", + "Save Face Quality", + "Save Face Flag", + "Save Face Color", + "Save Face Normal", + "Save Wedge Color", + "Save Wedge TexCoord", + "Save Wedge Normal", + "Save Polygonal" +}; + +const char PYTHON_TYPE_ENUM[] = "str"; +const char PYTHON_TYPE_ABSPERC[] = "Percentage"; +const char PYTHON_TYPE_DYNAMIC_FLOAT[] = "float (bounded)"; +const char PYTHON_TYPE_BOOL[] = "bool"; +const char PYTHON_TYPE_INT[] = "int"; +const char PYTHON_TYPE_FLOAT[] = "float"; +const char PYTHON_TYPE_STRING[] = "str"; +const char PYTHON_TYPE_MATRIX44F[] = "numpy.ndarray[numpy.float64[4, 4]]"; +const char PYTHON_TYPE_POINT3F[] = "numpy.ndarray[numpy.float64[3]]"; +const char PYTHON_TYPE_SHOTF[] = "Shotf [still unsupported]"; +const char PYTHON_TYPE_COLOR[] = "Color"; +const char PYTHON_TYPE_MESH[] = "int"; +const char PYTHON_TYPE_FILENAME[] = "str"; + +const static QStringList pythonKeywords = { + "False", "await", "else", "import", "pass", + "None", "break", "except", "in", "raise", + "True", "class", "finally", "is", "return", + "and", "continue", "for", "lambda", "try", + "as", "def from", "nonlocal", "while", + "assert", "del", "global", "not", "with", + "async", "elif", "if", "or", "yield" +}; + +/** Utilities **/ +QString computePythonTypeString(const RichParameter& par); +QString computePythonName(const QString& name); +void printSaveMask(int mask); + +} + +#endif // PYMESHLAB_PYTHON_UTILS_H diff --git a/src/external/OpenGR/demos/CGalWrapper/CMakelists.txt b/src/common/resources/git_sha.txt similarity index 100% rename from src/external/OpenGR/demos/CGalWrapper/CMakelists.txt rename to src/common/resources/git_sha.txt diff --git a/src/external/OpenGR/assets/textured_cube.png b/src/common/resources/images/dummy.png similarity index 100% rename from src/external/OpenGR/assets/textured_cube.png rename to src/common/resources/images/dummy.png diff --git a/src/common/searcher.cpp b/src/common/searcher.cpp deleted file mode 100644 index 88eb3a7ba..000000000 --- a/src/common/searcher.cpp +++ /dev/null @@ -1,146 +0,0 @@ -#include "searcher.h" -#include "mlexception.h" - -#include - -WordActionsMap::WordActionsMap() -:wordacts() -{ - -} - -void WordActionsMap::addWordsPerAction(QAction& act,const QStringList& words) -{ - foreach(QString word,words) - wordacts[word].push_back(&act); -} - -void WordActionsMap::removeActionReferences(QAction& act ) -{ - for(QMap >::iterator it = wordacts.begin();it != wordacts.end();++it) - it.value().removeAll(&act); -} - -bool WordActionsMap::getActionsPerWord( const QString& word,QList& res ) const -{ - QMap< QString,QList >::const_iterator it = wordacts.find(word); - if (it != wordacts.end()) - { - res = it.value(); - return true; - } - return false; -} - -WordActionsMapAccessor::WordActionsMapAccessor() -:map(),sepexp(),ignexp() -{ - sepexp.setPattern("\\W+"); - ignexp.setPattern("\\b(an|the|of|it|as|in|by|and|or|for)\\b|\\b[a-z]\\b|'s\\b|\\.|<[^>]*>"); -} - -void WordActionsMapAccessor::addWordsPerAction(QAction& act,const QString& st ) -{ - QStringList wlist; - purifiedSplit(st,wlist); - addSubStrings(wlist); - map.addWordsPerAction(act,wlist); -} - -int WordActionsMapAccessor::rankedMatchesPerInputString( const QString& input,RankedMatches& rm ) const -{ - QStringList inputlist; - purifiedSplit(input,inputlist); - return rm.computeRankedMatches(inputlist,map); -} - -void WordActionsMapAccessor::purifiedSplit( const QString& input,QStringList& res ) const -{ - res.clear(); - QString tmp = input; - tmp = tmp.toLower(); - tmp.remove(ignexp); - res = tmp.split(sepexp,QString::SkipEmptyParts); - res.removeDuplicates(); -} - -void WordActionsMapAccessor::addSubStrings( QStringList& res ) const -{ - QStringList resWithPrefix; - foreach(QString str, res) - { - QString strPref = str; - resWithPrefix.push_back(strPref); - for(int i=0;i wordmatchesperaction; - ranking.clear(); - int inputstsize = inputst.size(); - ranking.resize(inputstsize); - float bonuspertitleword = 0.0f; - if (matchesontitlearemoreimportant) - bonuspertitleword = 1.0f / std::pow(10,inputstsize); - foreach(const QString& st,inputst) - { - QList res; - bool found = map.getActionsPerWord(st,res); - if (found) - { - foreach(QAction* act, res) - { - ++wordmatchesperaction[act]; - QString title = act->text().toLower().trimmed(); - if (title.contains(st)) - wordmatchesperaction[act] = wordmatchesperaction[act] + bonuspertitleword; - } - } - } - - QMap > rankedmatches; - for (QMap::iterator it = wordmatchesperaction.begin(); it != wordmatchesperaction.end(); ++it) - rankedmatches[it.value()].push_back(it.key()); - - int maxindex = -1; - for(QMap >::iterator it = rankedmatches.end() - 1;it != rankedmatches.begin() - 1;--it) - { - int index = std::floor(it.key()) - 1; - if (index >= ranking.size()) - { - throw InvalidInvariantException("WARNING! Index contained in wordmatchesperaction it's out-of-bound."); - return 0; - } - if (index > maxindex) - maxindex = index; - ranking[index].append(it.value()); - } - return maxindex + 1; -} - -void RankedMatches::getActionsWithNMatches( const int n,QList& res ) -{ - res.clear(); - int index = n -1; - if ((index >= ranking.size()) || (n < 1)) - { - throw InvalidInvariantException(QString("WARNING! Parameter n MUST be in the range [1..") + QString::number(ranking.size()) + "]."); - return; - } - res = ranking[index]; -} - - diff --git a/src/common/searcher.h b/src/common/searcher.h deleted file mode 100644 index eb25dea4d..000000000 --- a/src/common/searcher.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef SEARCHER_H -#define SEARCHER_H - -#include -#include -#include -#include -#include -#include -#include - -class WordActionsMap -{ -public: - WordActionsMap(); - void addWordsPerAction(QAction& act,const QStringList& words); - void removeActionReferences(QAction& act); - bool getActionsPerWord( const QString& word,QList& res ) const; -private: - QMap > wordacts; -}; - -class RankedMatches; - -class WordActionsMapAccessor -{ -public: - WordActionsMapAccessor(); - void addWordsPerAction(QAction& act,const QString& st); - inline void removeActionReferences(QAction& act) {map.removeActionReferences(act);} - inline void setSeparator(const QRegExp& sep) {sepexp = sep;} - inline void setIgnoredWords(const QRegExp& ign) {ignexp = ign;} - int rankedMatchesPerInputString(const QString& input,RankedMatches& rm) const; - inline QRegExp separtor() const {return sepexp;} - inline QRegExp ignored() const {return ignexp;} - -private: - void purifiedSplit(const QString& input,QStringList& res) const; - void addSubStrings(QStringList& res) const; - WordActionsMap map; - QRegExp sepexp; - QRegExp ignexp; -}; - -class RankedMatches -{ -public: - RankedMatches(); - void getActionsWithNMatches(const int n,QList& res); -private: - friend int WordActionsMapAccessor::rankedMatchesPerInputString(const QString& input,RankedMatches& rm) const; - int computeRankedMatches(const QStringList& inputst,const WordActionsMap& map,bool matchesontitlearemoreimportant = true); - QVector > ranking; -}; - -#endif diff --git a/src/common/utilities/eigen_mesh_conversions.cpp b/src/common/utilities/eigen_mesh_conversions.cpp new file mode 100644 index 000000000..5291d52cb --- /dev/null +++ b/src/common/utilities/eigen_mesh_conversions.cpp @@ -0,0 +1,1322 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2005-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "eigen_mesh_conversions.h" +#include "../mlexception.h" +#include + +namespace vcg { +class PEdge; +class PFace; +class PVertex; +struct PUsedTypes : + public UsedTypes::AsVertexType, Use::AsEdgeType, Use::AsFaceType> +{ +}; + +class PVertex : + public Vertex< + PUsedTypes, + vertex::Coord3f, + vertex::Normal3f, + vertex::Qualityf, + vertex::Color4b, + vertex::BitFlags> +{ +}; +class PEdge : public Edge +{ +}; +class PFace : + public vcg::Face< + PUsedTypes, + face::PolyInfo, // this is necessary if you use component in + // vcg/simplex/face/component_polygon.h + face::PFVAdj, // Pointer to the vertices (just like FVAdj ) + face::Qualityf, + face::Color4b, + face::BitFlags, // bit flags + face::Normal3f, // normal + face::WedgeTexCoord2f> +{ +}; + +} // namespace vcg + +class PolyMesh : + public vcg::tri:: + TriMesh, std::vector, std::vector> +{ +}; + +/** + * @brief Creates a CMeshO mesh from the data contained in the given matrices. + * The only matrix required to be non-empty is the 'vertices' matrix. + * Other matrices may be empty. + * + * If normals and quality matrices are given, their sizes must be coherent with + * the sizes of vertex and face matrices. If this requirement is not satisfied, + * a MLException will be thrown. + * + * @param vertices: #V×3 matrix of scalars (vertex coordinates) + * @param faces: #F×3 matrix of integers (vertex indices composing the faces) + * @param vertexNormals: #V×3 matrix of scalars (vertex normals) + * @param faceNormals: #F×3 matrix of scalars (face normals) + * @param vertexQuality: #V vector of scalars (vertex quality) + * @param faceQuality: #F vector of scalars (face quality) + * @param vertexColor: #V*4 vector of scalars (RGBA vertex colors in interval [0-1]) + * @param faceColor: #F*4 vector of scalars (RGBA face colors in interval [0-1]) + * @param vertexTexCoords: #V×2 matrix of scalars (vertex texture coordinates) + * @param wedgeTexCoords: #F*3×2 matrix scalars (texture coordinates for each face edge) + * @return a CMeshO made of the given components + */ +CMeshO meshlab::meshFromMatrices( + const EigenMatrixX3m& vertices, + const Eigen::MatrixX3i& faces, + const Eigen::MatrixX2i& edges, + const EigenMatrixX3m& vertexNormals, + const EigenMatrixX3m& faceNormals, + const EigenVectorXm& vertexQuality, + const EigenVectorXm& faceQuality, + const EigenMatrixX4m& vertexColor, + const EigenMatrixX4m& faceColor, + const EigenMatrixX2m& vertexTexCoords, + const EigenMatrixX2m& wedgeTexCoords) +{ + CMeshO m; + if (vertices.rows() > 0) { + // add vertices and their associated normals and quality if any + std::vector ivp(vertices.rows()); + + bool hasVNormals = vertexNormals.rows() > 0; + bool hasVQuality = vertexQuality.rows() > 0; + bool hasVColors = vertexColor.rows() > 0; + bool hasVTexCoords = vertexTexCoords.rows() > 0; + if (hasVNormals && (vertices.rows() != vertexNormals.rows())) { + throw MLException( + "Error while creating mesh: the number of vertex normals " + "is different from the number of vertices."); + } + if (hasVQuality && (vertices.rows() != vertexQuality.size())) { + throw MLException( + "Error while creating mesh: the number of vertex quality " + "values is different from the number of vertices."); + } + if (hasVColors && (vertices.rows() != vertexColor.rows())) { + throw MLException( + "Error while creating mesh: the number of vertex colors " + "is different from the number of vertices."); + } + if (hasVTexCoords) { + if ((vertices.rows() != vertexTexCoords.rows())) { + throw MLException( + "Error while creating mesh: the number of vertex texture coordinates " + "is different from the number of vertices."); + } + m.vert.EnableTexCoord(); + } + CMeshO::VertexIterator vi = vcg::tri::Allocator::AddVertices(m, vertices.rows()); + for (unsigned int i = 0; i < vertices.rows(); ++i, ++vi) { + ivp[i] = &*vi; + vi->P() = CMeshO::CoordType(vertices(i, 0), vertices(i, 1), vertices(i, 2)); + if (hasVNormals) { + vi->N() = CMeshO::CoordType( + vertexNormals(i, 0), vertexNormals(i, 1), vertexNormals(i, 2)); + } + if (hasVQuality) { + vi->Q() = vertexQuality(i); + } + if (hasVColors) { + vi->C().Construct(CMeshO::VertexType::ColorType( + vertexColor(i, 0) * 255, + vertexColor(i, 1) * 255, + vertexColor(i, 2) * 255, + vertexColor(i, 3) * 255)); + } + if (hasVTexCoords) { + vi->T() = CMeshO::VertexType::TexCoordType( + vertexTexCoords(i, 0), + vertexTexCoords(i, 1)); + } + } + + // add faces and their associated normals and quality if any + + bool hasFNormals = faceNormals.rows() > 0; + bool hasFQuality = faceQuality.rows() > 0; + bool hasFColors = faceColor.rows() > 0; + bool hasFWedgeTexCoords = wedgeTexCoords.rows() > 0; + if (hasFNormals && (faces.rows() != faceNormals.rows())) { + throw MLException( + "Error while creating mesh: the number of face normals " + "is different from the number of faces."); + } + if (hasFQuality) { + if (faces.rows() != faceQuality.size()) { + throw MLException( + "Error while creating mesh: the number of face quality " + "values is different from the number of faces."); + } + m.face.EnableQuality(); + } + if (hasFColors) { + if (faces.rows() != faceColor.rows()) { + throw MLException( + "Error while creating mesh: the number of face colors " + "is different from the number of faces."); + } + m.face.EnableColor(); + } + if (hasFWedgeTexCoords) { + if (faces.rows() * 3 != wedgeTexCoords.rows()) { + throw MLException( + "Error while creating mesh: the number of wedge texture coords " + "is different from three times the number of faces (a texture coordinate for " + "each edge of a face."); + } + m.face.EnableWedgeTexCoord(); + } + CMeshO::FaceIterator fi = vcg::tri::Allocator::AddFaces(m, faces.rows()); + for (unsigned int i = 0; i < faces.rows(); ++i, ++fi) { + for (unsigned int j = 0; j < 3; j++) { + if ((unsigned int) faces(i, j) >= ivp.size()) { + throw MLException( + "Error while creating mesh: bad vertex index " + + QString::number(faces(i, j)) + " in face " + QString::number(i) + + "; vertex " + QString::number(j) + "."); + } + } + fi->V(0) = ivp[faces(i, 0)]; + fi->V(1) = ivp[faces(i, 1)]; + fi->V(2) = ivp[faces(i, 2)]; + + if (hasFNormals) { + fi->N() = + CMeshO::CoordType(faceNormals(i, 0), faceNormals(i, 1), faceNormals(i, 2)); + } + if (hasFQuality) { + fi->Q() = faceQuality(i); + } + if (hasFColors) { + fi->C().Construct(CMeshO::FaceType::ColorType( + faceColor(i, 0) * 255, + faceColor(i, 1) * 255, + faceColor(i, 2) * 255, + faceColor(i, 3) * 255)); + } + if (hasFWedgeTexCoords) { + for (uint j = 0; j < 3; j++) { + fi->WT(j).U() = wedgeTexCoords(i*3 + j, 0); + fi->WT(j).V() = wedgeTexCoords(i*3 + j, 1); + } + } + } + + // add edges + + CMeshO::EdgeIterator ei = vcg::tri::Allocator::AddEdges(m, edges.rows()); + for (unsigned int i = 0; i < edges.rows(); ++i, ++ei) { + for (unsigned int j = 0; j < 2; j++) { + if ((unsigned int) edges(i, j) >= ivp.size()) { + throw MLException( + "Error while creating mesh: bad vertex index " + + QString::number(edges(i, j)) + " in edge " + QString::number(i) + + "; vertex " + QString::number(j) + "."); + } + } + ei->V(0) = ivp[edges(i, 0)]; + ei->V(1) = ivp[edges(i, 1)]; + } + + if (!hasFNormals) { + vcg::tri::UpdateNormal::PerFace(m); + } + if (!hasVNormals) { + vcg::tri::UpdateNormal::PerVertex(m); + } + } + else { + throw MLException("Error while creating mesh: Vertex matrix is empty."); + } + + return m; +} + +/** + * @brief Creates a CMeshO mesh from the data contained in the given matrices, + * which may describe also a polygonal mesh. + * At least vertices and faces parameters are required. + * + * If normals and quality matrices are give, their sizes must be coherent with + * the sizes of vertex and face matrix/list. If this requirement is not satisfied, + * a MLException will be thrown. + * + * This function stores in the returned mesh a custom per face scalar attribute + * called 'poly_birth_faces', which stores for each triangle of the mesh, the id + * of its polygonal birth face of the polygon mesh given in input. + * + * @param vertices: #V×3 matrix of scalars (vertex coordinates) + * @param faces: #F list of vector of integers (vertex indices composing the faces) + * @param vertexNormals: #V×3 matrix of scalars (vertex normals) + * @param faceNormals: #F×3 matrix of scalars (face normals) + * @param vertexQuality: #V vector of scalars (vertex quality) + * @param faceQuality: #F vector of scalars (face quality) + * @param vertexColor: #V*4 vector of scalars (RGBA vertex colors in interval [0-1]) + * @param faceColor: #F*4 vector of scalars (RGBA face colors in interval [0-1]) + * @param vertexTexCoords: #V×2 matrix of scalars (vertex texture coordinates) + * @return a CMeshO made of the given components + */ +CMeshO meshlab::polyMeshFromMatrices( + const EigenMatrixX3m& vertices, + const std::list& faces, + const EigenMatrixX3m& vertexNormals, + const EigenMatrixX3m& faceNormals, + const EigenVectorXm& vertexQuality, + const EigenVectorXm& faceQuality, + const EigenMatrixX4m& vertexColor, + const EigenMatrixX4m& faceColor, + const EigenMatrixX2m& vertexTexCoords) +{ + PolyMesh pm; + CMeshO m; + if (vertices.rows() > 0) { + // add vertices and their associated normals and quality if any + std::vector ivp(vertices.rows()); + + bool hasVNormals = vertexNormals.rows() > 0; + bool hasVQuality = vertexQuality.rows() > 0; + bool hasVColors = vertexColor.rows() > 0; + bool hasVTexCoords = vertexTexCoords.rows() > 0; + if (hasVNormals && (vertices.rows() != vertexNormals.rows())) { + throw MLException( + "Error while creating mesh: the number of vertex normals " + "is different from the number of vertices."); + } + if (hasVQuality && (vertices.rows() != vertexQuality.size())) { + throw MLException( + "Error while creating mesh: the number of vertex quality " + "values is different from the number of vertices."); + } + if (hasVColors && (vertices.rows() != vertexColor.rows())) { + throw MLException( + "Error while creating mesh: the number of vertex colors " + "is different from the number of vertices."); + } + if (hasVTexCoords) { + if ((vertices.rows() != vertexTexCoords.rows())) { + throw MLException( + "Error while creating mesh: the number of vertex texture coordinates " + "is different from the number of vertices."); + } + m.vert.EnableTexCoord(); + } + PolyMesh::VertexIterator vi = + vcg::tri::Allocator::AddVertices(pm, vertices.rows()); + for (unsigned int i = 0; i < vertices.rows(); ++i, ++vi) { + ivp[i] = &*vi; + vi->P() = PolyMesh::CoordType(vertices(i, 0), vertices(i, 1), vertices(i, 2)); + if (hasVNormals) { + vi->N() = PolyMesh::CoordType( + vertexNormals(i, 0), vertexNormals(i, 1), vertexNormals(i, 2)); + } + if (hasVQuality) { + vi->Q() = vertexQuality(i); + } + if (hasVColors) { + vi->C().Construct(CMeshO::VertexType::ColorType( + vertexColor(i, 0) * 255, + vertexColor(i, 1) * 255, + vertexColor(i, 2) * 255, + vertexColor(i, 3) * 255)); + } + if (hasVTexCoords) { + vi->T() = CMeshO::VertexType::TexCoordType( + vertexTexCoords(i, 0), + vertexTexCoords(i, 1)); + } + } + + // add faces and their associated normals and quality if any + + bool hasFNormals = faceNormals.rows() > 0; + bool hasFQuality = faceQuality.rows() > 0; + bool hasFColors = faceColor.rows() > 0; + if (hasFNormals && (faces.size() != (size_t) faceNormals.rows())) { + throw MLException( + "Error while creating mesh: the number of face normals " + "is different from the number of faces."); + } + if (hasFQuality) { + if (faces.size() != (size_t) faceQuality.size()) { + throw MLException( + "Error while creating mesh: the number of face quality " + "values is different from the number of faces."); + } + m.face.EnableQuality(); + } + if (hasFColors) { + if (faces.size() != (size_t) faceColor.rows()) { + throw MLException( + "Error while creating mesh: the number of face colors " + "is different from the number of faces."); + } + m.face.EnableColor(); + } + PolyMesh::FaceIterator fi = vcg::tri::Allocator::AddFaces(pm, faces.size()); + auto it = faces.begin(); + for (unsigned int i = 0; i < faces.size(); ++i, ++fi, ++it) { + fi->Alloc(it->size()); + const EigenVectorXui& iface = *it; + for (unsigned int j = 0; j < iface.size(); ++j) { + if ((unsigned int) iface(j) >= ivp.size()) { + throw MLException( + "Error while creating mesh: bad vertex index " + QString::number(iface(j)) + + " in face " + QString::number(i) + "; vertex " + QString::number(j) + "."); + } + fi->V(j) = ivp[iface(j)]; + } + if (hasFNormals) { + fi->N() = + PolyMesh::CoordType(faceNormals(i, 0), faceNormals(i, 1), faceNormals(i, 2)); + } + if (hasFQuality) { + fi->Q() = faceQuality(i); + } + if (hasFColors) { + fi->C().Construct(CMeshO::FaceType::ColorType( + faceColor(i, 0) * 255, + faceColor(i, 1) * 255, + faceColor(i, 2) * 255, + faceColor(i, 3) * 255)); + } + } + + std::vector birthFaces; + vcg::tri::PolygonSupport::ImportFromPolyMesh(m, pm, birthFaces); + + auto h = vcg::tri::Allocator::AddPerFaceAttribute(m, "poly_birth_faces"); + for (unsigned int i = 0; i < m.face.size(); ++i) + h[i] = birthFaces[i]; + + if (!hasFNormals) { + vcg::tri::UpdateNormal::PerFace(m); + } + if (!hasVNormals) { + vcg::tri::UpdateNormal::PerVertex(m); + } + } + else { + throw MLException("Error while creating mesh: Vertex matrix is empty."); + } + + return m; +} + +/** + * @brief Adds a new custom vertex attribute of scalars to the given mesh. + * + * The vector of values must have the same size of the number of vertices of the + * mesh, and if an attribute with the give name already exists, a MLException + * will be raised. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: the input mesh + * @param attributeValues: #V vector of values + * @param attributeName: the name of the new attribute + */ +void meshlab::addVertexScalarAttribute( + CMeshO& mesh, + const EigenVectorXm& attributeValues, + const std::string& attributeName) +{ + if (mesh.VN() != attributeValues.size()) + throw MLException( + "The given vector has different number of elements than the number of vertices of the " + "mesh."); + auto h = vcg::tri::Allocator::FindPerVertexAttribute(mesh, attributeName); + if (vcg::tri::Allocator::IsValidHandle(mesh, h)) { + throw MLException( + "The mesh already has a custom attribute with the name " + + QString::fromStdString(attributeName)); + } + h = vcg::tri::Allocator::AddPerVertexAttribute(mesh, attributeName); + for (unsigned int i = 0; i < attributeValues.size(); ++i) { + h[i] = attributeValues(i); + } +} + +/** + * @brief Adds a new custom face attribute of scalars to the given mesh. + * + * The vector of values must have the same size of the number of faces of the + * mesh, and if an attribute with the give name already exists, a MLException + * will be raised. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: the input mesh + * @param attributeValues: #F vector of values + * @param attributeName: the name of the new attribute + */ +void meshlab::addFaceScalarAttribute( + CMeshO& mesh, + const EigenVectorXm& attributeValues, + const std::string& attributeName) +{ + if (mesh.FN() != attributeValues.size()) + throw MLException( + "The given vector has different number of elements than the number of faces of the " + "mesh."); + auto h = vcg::tri::Allocator::FindPerFaceAttribute(mesh, attributeName); + if (vcg::tri::Allocator::IsValidHandle(mesh, h)) { + throw MLException( + "The mesh already has a custom attribute with the name " + + QString::fromStdString(attributeName)); + } + h = vcg::tri::Allocator::AddPerFaceAttribute(mesh, attributeName); + for (unsigned int i = 0; i < attributeValues.size(); ++i) { + h[i] = attributeValues(i); + } +} + +/** + * @brief Adds a new custom vertex attribute of vectors to the given mesh. + * + * The matrix of values must have the same number of rows of the number of vertices of the + * mesh (and 3 columns), and if an attribute with the give name already exists, a MLException + * will be raised. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: the input mesh + * @param attributeValues: #V*3 matrix of values + * @param attributeName: the name of the new attribute + */ +void meshlab::addVertexVectorAttribute( + CMeshO& mesh, + const EigenMatrixX3m& attributeValues, + const std::string& attributeName) +{ + if (mesh.VN() != attributeValues.rows()) + throw MLException( + "The given vector has different number of rows than the number of vertices of the " + "mesh."); + auto h = vcg::tri::Allocator::FindPerVertexAttribute(mesh, attributeName); + if (vcg::tri::Allocator::IsValidHandle(mesh, h)) { + throw MLException( + "The mesh already has a custom attribute with the name " + + QString::fromStdString(attributeName)); + } + h = vcg::tri::Allocator::AddPerVertexAttribute(mesh, attributeName); + for (unsigned int i = 0; i < attributeValues.size(); ++i) { + h[i][0] = attributeValues(i, 0); + h[i][1] = attributeValues(i, 1); + h[i][2] = attributeValues(i, 2); + } +} + +/** + * @brief Adds a new custom faces attribute of vectors to the given mesh. + * + * The matrix of values must have the same number of rows of the number of faces of the + * mesh (and 3 columns), and if an attribute with the give name already exists, a MLException + * will be raised. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: the input mesh + * @param attributeValues: #F*3 matrix of values + * @param attributeName: the name of the new attribute + */ +void meshlab::addFaceVectorAttribute( + CMeshO& mesh, + const EigenMatrixX3m& attributeValues, + const std::string& attributeName) +{ + if (mesh.FN() != attributeValues.rows()) + throw MLException( + "The given vector has different number of rows than the number of faces of the mesh."); + auto h = vcg::tri::Allocator::FindPerFaceAttribute(mesh, attributeName); + if (vcg::tri::Allocator::IsValidHandle(mesh, h)) { + throw MLException( + "The mesh already has a custom attribute with the name " + + QString::fromStdString(attributeName)); + } + h = vcg::tri::Allocator::AddPerFaceAttribute(mesh, attributeName); + for (unsigned int i = 0; i < attributeValues.size(); ++i) { + h[i][0] = attributeValues(i, 0); + h[i][1] = attributeValues(i, 1); + h[i][2] = attributeValues(i, 2); + } +} + +/** + * @brief Get a #V*3 Eigen matrix of scalars containing the coordinates of the + * vertices of a CMeshO. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V*3 matrix of scalars (vertex coordinates) + */ +EigenMatrixX3m meshlab::vertexMatrix(const CMeshO& mesh) +{ + vcg::tri::RequireVertexCompactness(mesh); + + // create eigen matrix of vertices + EigenMatrixX3m vert(mesh.VN(), 3); + + // copy vertices + for (int i = 0; i < mesh.VN(); i++) { + for (int j = 0; j < 3; j++) { + vert(i, j) = mesh.vert[i].P()[j]; + } + } + + return vert; +} + +/** + * @brief Get a #V*3 Eigen matrix of scalars containing the coordinates of the + * vertices of a CMeshO, to which has been applied the transform matrix of the mesh. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V*3 matrix of scalars (transformed vertex coordinates) + */ +EigenMatrixX3m meshlab::transformedVertexMatrix(const CMeshO &mesh) +{ + vcg::tri::RequireVertexCompactness(mesh); + + // create eigen matrix of vertices + EigenMatrixX3m vert(mesh.VN(), 3); + + // copy vertices + for (int i = 0; i < mesh.VN(); i++) { + CMeshO::CoordType p = mesh.Tr * mesh.vert[i].P(); + for (int j = 0; j < 3; j++) { + vert(i, j) = p[j]; + } + } + + return vert; +} + +/** + * @brief Get a #F*3 Eigen matrix of integers containing the vertex indices of + * a CMeshO. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #F*3 matrix of integers (vertex indices composing the faces) + */ +Eigen::MatrixX3i meshlab::faceMatrix(const CMeshO& mesh) +{ + vcg::tri::RequireFaceCompactness(mesh); + + // create eigen matrix of faces + Eigen::MatrixXi faces(mesh.FN(), 3); + + // copy faces + for (int i = 0; i < mesh.FN(); i++) { + for (int j = 0; j < 3; j++) { + faces(i, j) = (int) vcg::tri::Index(mesh, mesh.face[i].V(j)); + } + } + + return faces; +} + +/** + * @brief Get a #E*2 Eigen matrix of integers containing the vertex indices of + * the edges of a CMeshO. + * The edges in the mesh must be compact (no deleted edges). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #E*2 matrix of integers (vertex indices composing the edges) + */ +Eigen::MatrixX2i meshlab::edgeMatrix(const CMeshO& mesh) +{ + vcg::tri::RequireEdgeCompactness(mesh); + + // create eigen matrix of edges + Eigen::MatrixXi edges(mesh.EN(), 2); + + // copy faces + for (int i = 0; i < mesh.EN(); i++) { + for (int j = 0; j < 2; j++) { + edges(i, j) = (int) vcg::tri::Index(mesh, mesh.edge[i].V(j)); + } + } + + return edges; +} + +/** + * @brief Get a #F list of Eigen vectors of integers containing the vertex indices of + * the polygonal mesh contained in the CMeshO mesh. + * + * @todo This method first makes a COPY of the mesh, because ImportFromTriMesh cannot + * take const meshes as input -> manage visited flags for const meshes!! + * + * @param mesh: input mesh + * @return Get a #F list of vectors of integers (vertex indices composing the faces) + */ +std::list meshlab::polygonalFaceList(const CMeshO& mesh) +{ + std::list listIndices; + PolyMesh pm; + CMeshO tm = mesh; + tm.face.EnableFFAdjacency(); + vcg::tri::UpdateTopology::FaceFace(tm); + vcg::tri::PolygonSupport::ImportFromTriMesh(pm, tm); + for (unsigned int i = 0; i < pm.face.size(); ++i) { + unsigned int nv = pm.face[i].VN(); + EigenVectorXui vi(nv); + for (unsigned int j = 0; j < nv; j++) + vi(j) = vcg::tri::Index(pm, pm.face[i].V(j)); + listIndices.push_back(vi); + } + return listIndices; +} + +/** + * @brief Get a #V*3 Eigen matrix of scalars containing the values of the + * vertex normals of a CMeshO. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V*3 matrix of scalars (vertex normals) + */ +EigenMatrixX3m meshlab::vertexNormalMatrix(const CMeshO& mesh) +{ + vcg::tri::RequireVertexCompactness(mesh); + + // create eigen matrix of vertex normals + EigenMatrixX3m vertexNormals(mesh.VN(), 3); + + // per vertices normals + for (int i = 0; i < mesh.VN(); i++) { + for (int j = 0; j < 3; j++) { + vertexNormals(i, j) = mesh.vert[i].N()[j]; + } + } + + return vertexNormals; +} + +/** + * @brief Get a #V*3 Eigen matrix of scalars containing the values of the + * vertex normals of a CMeshO, to which has been applied the transform matrix of the mesh. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V*3 matrix of scalars (transformed vertex normals) + */ +EigenMatrixX3m meshlab::transformedVertexNormalMatrix(const CMeshO &mesh) +{ + vcg::tri::RequireVertexCompactness(mesh); + + CMeshO::ScalarType scale; + + vcg::Matrix33 mat33(mesh.Tr,3); + scale = pow(mat33.Determinant(),(CMeshO::ScalarType)(1.0/3.0)); + CMeshO::CoordType scaleV(scale,scale,scale); + vcg::Matrix33 S; + S.SetDiagonal(scaleV.V()); + mat33*=S; + + // create eigen matrix of vertex normals + EigenMatrixX3m vertexNormals(mesh.VN(), 3); + + // per vertices normals + for (int i = 0; i < mesh.VN(); i++) { + CMeshO::CoordType n = mat33 * mesh.vert[i].N(); + for (int j = 0; j < 3; j++) { + vertexNormals(i, j) = n[j]; + } + } + + return vertexNormals; +} + +/** + * @brief Get a #F*3 Eigen matrix of scalars containing the values of the + * face normals of a CMeshO. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #F*3 matrix of scalars (face normals) + */ +EigenMatrixX3m meshlab::faceNormalMatrix(const CMeshO& mesh) +{ + vcg::tri::RequireFaceCompactness(mesh); + + CMeshO::ScalarType scale; + + vcg::Matrix33 mat33(mesh.Tr,3); + scale = pow(mat33.Determinant(),(CMeshO::ScalarType)(1.0/3.0)); + CMeshO::CoordType scaleV(scale,scale,scale); + vcg::Matrix33 S; + S.SetDiagonal(scaleV.V()); + mat33*=S; + + // create eigen matrix of face normals + EigenMatrixX3m faceNormals(mesh.FN(), 3); + + // per face normals + for (int i = 0; i < mesh.FN(); i++) { + CMeshO::CoordType n = mat33 * mesh.face[i].N(); + for (int j = 0; j < 3; j++) { + faceNormals(i, j) = n[j]; + } + } + + return faceNormals; +} + +/** + * @brief Get a #F*3 Eigen matrix of scalars containing the values of the + * face normals of a CMeshO, to which has been applied the transform matrix of the mesh. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #F*3 matrix of scalars (transformed face normals) + */ +EigenMatrixX3m meshlab::transformedFaceNormalMatrix(const CMeshO &mesh) +{ + vcg::tri::RequireFaceCompactness(mesh); + + // create eigen matrix of face normals + EigenMatrixX3m faceNormals(mesh.FN(), 3); + + // per face normals + for (int i = 0; i < mesh.FN(); i++) { + for (int j = 0; j < 3; j++) { + faceNormals(i, j) = mesh.face[i].N()[j]; + } + } + + return faceNormals; +} + + +/** + * @brief Get a #V*4 Eigen matrix of scalars containing the values of the + * vertex colors of a CMeshO, each value in an interval [0, 1]. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V*4 matrix of scalars (vertex colors) + */ +EigenMatrixX4m meshlab::vertexColorMatrix(const CMeshO& mesh) +{ + vcg::tri::RequireVertexCompactness(mesh); + EigenMatrixX4m vertexColors(mesh.VN(), 4); + + for (int i = 0; i < mesh.VN(); i++) { + for (int j = 0; j < 4; j++) { + vertexColors(i, j) = mesh.vert[i].C()[j] / 255.0; + } + } + + return vertexColors; +} + +/** + * @brief Get a #F*4 Eigen matrix of scalars containing the values of the + * face colors of a CMeshO, each value in an interval [0, 1]. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #F*4 matrix of scalars (face colors) + */ +EigenMatrixX4m meshlab::faceColorMatrix(const CMeshO& mesh) +{ + vcg::tri::RequireFaceCompactness(mesh); + vcg::tri::RequirePerFaceColor(mesh); + + EigenMatrixX4m faceColors(mesh.FN(), 4); + + for (int i = 0; i < mesh.FN(); i++) { + for (int j = 0; j < 4; j++) { + faceColors(i, j) = mesh.face[i].C()[j] / 255.0; + } + } + + return faceColors; +} + +/** + * @brief Get a #V Eigen vector of unsigned integers containing the values of the + * vertex colors of a CMeshO. Each value is a packed ARGB color in a 32 bit + * unsigned int (8 bits per component). + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V vector of unsigned integers (vertex colors) + */ +EigenVectorXui meshlab::vertexColorArray(const CMeshO& mesh) +{ + vcg::tri::RequireVertexCompactness(mesh); + EigenVectorXui vertexColors(mesh.VN()); + + for (int i = 0; i < mesh.VN(); i++) { + vertexColors(i) = vcg::Color4::ToUnsignedA8R8G8B8(mesh.vert[i].C()); + } + + return vertexColors; +} + +/** + * @brief Get a #F Eigen vector of unsigned integers containing the values of the + * face colors of a CMeshO. Each value is a packed ARGB color in a 32 bit + * unsigned int (8 bits per component). + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #F vector of unsigned integers (face colors) + */ +EigenVectorXui meshlab::faceColorArray(const CMeshO& mesh) +{ + vcg::tri::RequireFaceCompactness(mesh); + vcg::tri::RequirePerFaceColor(mesh); + + EigenVectorXui faceColors(mesh.FN()); + + for (int i = 0; i < mesh.FN(); i++) { + faceColors(i) = vcg::Color4::ToUnsignedA8R8G8B8(mesh.face[i].C()); + } + + return faceColors; +} + +/** + * @brief Get a #V Eigen vector of scalars containing the values of the + * vertex quality of a CMeshO. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V matrix of scalars (vertex quality) + */ +EigenVectorXm meshlab::vertexQualityArray(const CMeshO& mesh) +{ + vcg::tri::RequireVertexCompactness(mesh); + vcg::tri::RequirePerVertexQuality(mesh); + + EigenVectorXm qv(mesh.VN()); + for (int i = 0; i < mesh.VN(); i++) { + qv(i) = mesh.vert[i].Q(); + } + return qv; +} + +/** + * @brief Get a #F Eigen vector of scalars containing the values of the + * face quality of a CMeshO. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #F matrix of scalars (face quality) + */ +EigenVectorXm meshlab::faceQualityArray(const CMeshO& mesh) +{ + vcg::tri::RequireFaceCompactness(mesh); + vcg::tri::RequirePerFaceQuality(mesh); + + EigenVectorXm qf(mesh.FN()); + for (int i = 0; i < mesh.FN(); i++) { + qf(i) = mesh.face[i].Q(); + } + return qf; +} + +/** + * @brief Get a #V*2 Eigen matrix of scalars containing the values of the + * vertex texture coordinates of a CMeshO. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V*2 matrix of scalars (vertex texture coordinates) + */ +EigenMatrixX2m meshlab::vertexTexCoordMatrix(const CMeshO& mesh) +{ + vcg::tri::RequireVertexCompactness(mesh); + vcg::tri::RequirePerVertexTexCoord(mesh); + + EigenMatrixX2m uv(mesh.VN(), 2); + + // per vertices uv + for (int i = 0; i < mesh.VN(); i++) { + uv(i, 0) = mesh.vert[i].T().U(); + uv(i, 1) = mesh.vert[i].T().V(); + } + + return uv; +} + +/** + * @brief Get a (#F*3)*2 Eigen matrix of scalars containing the values of the + * wedge texture coordinates of a CMeshO. The matrix is organized as consecutive + * #F triplets of uv coordinates. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #(#F*3)*2 matrix of scalars (wedge texture coordinates) + */ +EigenMatrixX2m meshlab::wedgeTexCoordMatrix(const CMeshO& mesh) +{ + vcg::tri::RequireFaceCompactness(mesh); + vcg::tri::RequirePerFaceWedgeTexCoord(mesh); + EigenMatrixX2m m(mesh.FN() * 3, 2); + + for (int i = 0; i < mesh.FN(); i++) { + int base = i * 3; + for (int j = 0; j < 3; j++) { + m(base + j, 0) = mesh.face[i].WT(j).u(); + m(base + j, 1) = mesh.face[i].WT(j).v(); + } + } + return m; +} + +/** + * @brief Get a #V Eigen vector of booleans which are true if the corresponding + * vertex is selected, false otherwise + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V vector of booleans + */ +EigenVectorXb meshlab::vertexSelectionArray(const CMeshO& mesh) +{ + vcg::tri::RequireVertexCompactness(mesh); + + EigenVectorXb sel(mesh.VN()); + + // per vertex selection + for (int i = 0; i < mesh.VN(); i++) { + sel(i) = mesh.vert[i].IsS(); + } + + return sel; +} + +/** + * @brief Get a #F Eigen vector of booleans which are true if the corresponding + * face is selected, false otherwise + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #F vector of booleans + */ +EigenVectorXb meshlab::faceSelectionArray(const CMeshO& mesh) +{ + vcg::tri::RequireVertexCompactness(mesh); + + EigenVectorXb sel(mesh.FN()); + + // per face selection + for (int i = 0; i < mesh.FN(); i++) { + sel(i) = mesh.face[i].IsS(); + } + + return sel; +} + +/** + * @brief Get a #V*3 Eigen matrix of scalars containing the values of the + * vertex principal direction 1 curvature of a CMeshO. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V*3 matrix of scalars (vertex principal direction 1 curvature) + */ +EigenMatrixX3m meshlab::vertexCurvaturePD1Matrix(const CMeshO& mesh) +{ + vcg::tri::RequireVertexCompactness(mesh); + vcg::tri::RequirePerVertexCurvatureDir(mesh); + + // create eigen matrix + EigenMatrixX3m vertexCurv(mesh.VN(), 3); + + // per vertices min curvature dir + for (int i = 0; i < mesh.VN(); i++) { + for (int j = 0; j < 3; j++) { + vertexCurv(i, j) = mesh.vert[i].PD1()[j]; + } + } + + return vertexCurv; +} + +/** + * @brief Get a #V*3 Eigen matrix of scalars containing the values of the + * vertex principal direction 2 curvature of a CMeshO. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V*3 matrix of scalars (vertex principal direction 2 curvature) + */ +EigenMatrixX3m meshlab::vertexCurvaturePD2Matrix(const CMeshO& mesh) +{ + vcg::tri::RequireVertexCompactness(mesh); + vcg::tri::RequirePerVertexCurvatureDir(mesh); + + // create eigen matrix + EigenMatrixX3m vertexCurv(mesh.VN(), 3); + + // per vertices min curvature dir + for (int i = 0; i < mesh.VN(); i++) { + for (int j = 0; j < 3; j++) { + vertexCurv(i, j) = mesh.vert[i].PD2()[j]; + } + } + + return vertexCurv; +} + +/** + * @brief Get a #F*3 Eigen matrix of scalars containing the values of the + * face principal direction 1 curvature of a CMeshO. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #F*3 matrix of scalars (face principal direction 1 curvature) + */ +EigenMatrixX3m meshlab::faceCurvaturePD1Matrix(const CMeshO& mesh) +{ + vcg::tri::RequireFaceCompactness(mesh); + vcg::tri::RequirePerFaceCurvatureDir(mesh); + + // create eigen matrix + EigenMatrixX3m faceCurv(mesh.FN(), 3); + + // per face min curvature dir + for (int i = 0; i < mesh.FN(); i++) { + for (int j = 0; j < 3; j++) { + faceCurv(i, j) = mesh.face[i].PD1()[j]; + } + } + + return faceCurv; +} + +/** + * @brief Get a #F*3 Eigen matrix of scalars containing the values of the + * face principal direction 2 curvature of a CMeshO. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #F*3 matrix of scalars (face principal direction 2 curvature) + */ +EigenMatrixX3m meshlab::faceCurvaturePD2Matrix(const CMeshO& mesh) +{ + vcg::tri::RequireFaceCompactness(mesh); + vcg::tri::RequirePerFaceCurvatureDir(mesh); + + // create eigen matrix + EigenMatrixX3m faceCurv(mesh.FN(), 3); + + // per face min curvature dir + for (int i = 0; i < mesh.FN(); i++) { + for (int j = 0; j < 3; j++) { + faceCurv(i, j) = mesh.face[i].PD2()[j]; + } + } + + return faceCurv; +} + +/** + * @brief Get a #F*3 Eigen matrix of integers containing the indices of the + * adjacent faces for each face in a CMeshO. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #F*3 matrix of integers (face-face adjacency) + */ +Eigen::MatrixX3i meshlab::faceFaceAdjacencyMatrix(const CMeshO& mesh) +{ + vcg::tri::RequireFaceCompactness(mesh); + vcg::tri::RequireFFAdjacency(mesh); + + Eigen::MatrixX3i faceFaceMatrix(mesh.FN(), 3); + + for (int i = 0; i < mesh.FN(); i++) { + for (int j = 0; j < 3; j++) { + auto AdjF = mesh.face[i].FFp(j); + if (AdjF == &mesh.face[i]) { + faceFaceMatrix(i, j) = -1; + } + else { + faceFaceMatrix(i, j) = mesh.face[i].FFi(j); + } + } + } + + return faceFaceMatrix; +} + +/** + * @brief Get a #V Eigen vector of scalars containing the values of the + * custom per-vertex attribute having the given name. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V vector of scalars (custom scalar vertex attribute) + */ +EigenVectorXm +meshlab::vertexScalarAttributeArray(const CMeshO& mesh, const std::string& attributeName) +{ + vcg::tri::RequireVertexCompactness(mesh); + CMeshO::ConstPerVertexAttributeHandle attributeHandle = + vcg::tri::Allocator::GetPerVertexAttribute(mesh, attributeName); + if (vcg::tri::Allocator::IsValidHandle(mesh, attributeHandle)) { + EigenVectorXm attrVector(mesh.VN()); + for (unsigned int i = 0; i < (unsigned int) mesh.VN(); ++i) { + attrVector[i] = attributeHandle[i]; + } + return attrVector; + } + else { + throw MLException( + "No valid per vertex scalar attribute named " + QString::fromStdString(attributeName) + + " was found."); + } +} + +/** + * @brief Get a #V*3 Eigen matrix of scalars containing the values of the + * custom per-vertex attribute having the given name. + * The vertices in the mesh must be compact (no deleted vertices). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #V*3 matrix of scalars (custom Point3 vertex attribute) + */ +EigenMatrixX3m +meshlab::vertexVectorAttributeMatrix(const CMeshO& mesh, const std::string& attributeName) +{ + vcg::tri::RequireVertexCompactness(mesh); + CMeshO::ConstPerVertexAttributeHandle attributeHandle = + vcg::tri::Allocator::GetPerVertexAttribute(mesh, attributeName); + if (vcg::tri::Allocator::IsValidHandle(mesh, attributeHandle)) { + EigenMatrixX3m attrMatrix(mesh.VN(), 3); + for (unsigned int i = 0; i < (unsigned int) mesh.VN(); ++i) { + attrMatrix(i, 0) = attributeHandle[i][0]; + attrMatrix(i, 1) = attributeHandle[i][1]; + attrMatrix(i, 2) = attributeHandle[i][2]; + } + return attrMatrix; + } + else { + throw MLException( + "No valid per vertex vector attribute named " + QString::fromStdString(attributeName) + + " was found."); + } +} + +/** + * @brief Get a #F Eigen vector of scalars containing the values of the + * custom per-face attribute having the given name. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #F vector of scalars (custom scalar face attribute) + */ +EigenVectorXm +meshlab::faceScalarAttributeArray(const CMeshO& mesh, const std::string& attributeName) +{ + vcg::tri::RequireFaceCompactness(mesh); + CMeshO::ConstPerFaceAttributeHandle attributeHandle = + vcg::tri::Allocator::GetPerFaceAttribute(mesh, attributeName); + if (vcg::tri::Allocator::IsValidHandle(mesh, attributeHandle)) { + EigenVectorXm attrMatrix(mesh.FN()); + for (unsigned int i = 0; i < (unsigned int) mesh.FN(); ++i) { + attrMatrix[i] = attributeHandle[i]; + } + return attrMatrix; + } + else { + throw MLException( + "No valid per face scalar attribute named " + QString::fromStdString(attributeName) + + " was found."); + } +} + +/** + * @brief Get a #F*3 Eigen matrix of scalars containing the values of the + * custom per-face attribute having the given name. + * The faces in the mesh must be compact (no deleted faces). + * If the mesh is not compact, a vcg::MissingCompactnessException will be thrown. + * + * @param mesh: input mesh + * @return #F*3 matrix of scalars (custom Point3 face attribute) + */ +EigenMatrixX3m +meshlab::faceVectorAttributeMatrix(const CMeshO& mesh, const std::string& attributeName) +{ + vcg::tri::RequireFaceCompactness(mesh); + CMeshO::ConstPerFaceAttributeHandle attributeHandle = + vcg::tri::Allocator::GetPerFaceAttribute(mesh, attributeName); + if (vcg::tri::Allocator::IsValidHandle(mesh, attributeHandle)) { + EigenMatrixX3m attrMatrix(mesh.FN(), 3); + for (unsigned int i = 0; i < (unsigned int) mesh.FN(); ++i) { + attrMatrix(i, 0) = attributeHandle[i][0]; + attrMatrix(i, 1) = attributeHandle[i][1]; + attrMatrix(i, 2) = attributeHandle[i][2]; + } + return attrMatrix; + } + else { + throw MLException( + "No valid per face vector attribute named " + QString::fromStdString(attributeName) + + " was found."); + } +} diff --git a/src/common/utilities/eigen_mesh_conversions.h b/src/common/utilities/eigen_mesh_conversions.h new file mode 100644 index 000000000..70eeacc72 --- /dev/null +++ b/src/common/utilities/eigen_mesh_conversions.h @@ -0,0 +1,122 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2005-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_EIGEN_MESH_CONVERSIONS_H +#define MESHLAB_EIGEN_MESH_CONVERSIONS_H + +#include "../ml_document/cmesh.h" +#include +#include + +typedef Eigen::Matrix EigenVectorXm; +typedef Eigen::Matrix EigenVectorXb; +typedef Eigen::Matrix EigenVectorXui; + +typedef Eigen::Matrix EigenMatrixX2m; +typedef Eigen::Matrix EigenMatrixX3m; +typedef Eigen::Matrix EigenMatrixX4m; + +typedef Eigen::Matrix EigenMatrixXm; + +namespace meshlab { + +// From eigen to CMeshO +CMeshO meshFromMatrices( + const EigenMatrixX3m& vertices, + const Eigen::MatrixX3i& faces = Eigen::MatrixX3i(), + const Eigen::MatrixX2i& edges = Eigen::MatrixX2i(), + const EigenMatrixX3m& vertexNormals = EigenMatrixX3m(), + const EigenMatrixX3m& faceNormals = EigenMatrixX3m(), + const EigenVectorXm& vertexQuality = EigenVectorXm(), + const EigenVectorXm& faceQuality = EigenVectorXm(), + const EigenMatrixX4m& vertexColor = EigenMatrixX4m(), + const EigenMatrixX4m& faceColor = EigenMatrixX4m(), + const EigenMatrixX2m& vertexTexCoords = EigenMatrixX2m(), + const EigenMatrixX2m& wedgeTexCoords = EigenMatrixX2m()); + +// From eigen to polygonal CMeshO +CMeshO polyMeshFromMatrices( + const EigenMatrixX3m& vertices, + const std::list& faces, + const EigenMatrixX3m& vertexNormals = EigenMatrixX3m(), + const EigenMatrixX3m& faceNormals = EigenMatrixX3m(), + const EigenVectorXm& vertexQuality = EigenVectorXm(), + const EigenVectorXm& faceQuality = EigenVectorXm(), + const EigenMatrixX4m& vertexColor = EigenMatrixX4m(), + const EigenMatrixX4m& faceColor = EigenMatrixX4m(), + const EigenMatrixX2m& vertexTexCoords = EigenMatrixX2m()); + +void addVertexScalarAttribute( + CMeshO& mesh, + const EigenVectorXm& attributeValues, + const std::string& attributeName); + +void addFaceScalarAttribute( + CMeshO& mesh, + const EigenVectorXm& attributeValues, + const std::string& attributeName); + +void addVertexVectorAttribute( + CMeshO& mesh, + const EigenMatrixX3m& attributeValues, + const std::string& attributeName); + +void addFaceVectorAttribute( + CMeshO& mesh, + const EigenMatrixX3m& attributeValues, + const std::string& attributeName); + +// From CMeshO to Eigen +EigenMatrixX3m vertexMatrix(const CMeshO& mesh); +EigenMatrixX3m transformedVertexMatrix(const CMeshO& mesh); +Eigen::MatrixX3i faceMatrix(const CMeshO& mesh); +Eigen::MatrixX2i edgeMatrix(const CMeshO& mesh); +std::list polygonalFaceList(const CMeshO& mesh); +EigenMatrixX3m vertexNormalMatrix(const CMeshO& mesh); +EigenMatrixX3m transformedVertexNormalMatrix(const CMeshO& mesh); +EigenMatrixX3m faceNormalMatrix(const CMeshO& mesh); +EigenMatrixX3m transformedFaceNormalMatrix(const CMeshO& mesh); +EigenMatrixX4m vertexColorMatrix(const CMeshO& mesh); +EigenMatrixX4m faceColorMatrix(const CMeshO& mesh); +EigenVectorXui vertexColorArray(const CMeshO& mesh); +EigenVectorXui faceColorArray(const CMeshO& mesh); +EigenVectorXm vertexQualityArray(const CMeshO& mesh); +EigenVectorXm faceQualityArray(const CMeshO& mesh); +EigenMatrixX2m vertexTexCoordMatrix(const CMeshO& mesh); +EigenMatrixX2m wedgeTexCoordMatrix(const CMeshO& mesh); +EigenVectorXb vertexSelectionArray(const CMeshO& mesh); +EigenVectorXb faceSelectionArray(const CMeshO& mesh); +EigenMatrixX3m vertexCurvaturePD1Matrix(const CMeshO& mesh); +EigenMatrixX3m vertexCurvaturePD2Matrix(const CMeshO& mesh); +EigenMatrixX3m faceCurvaturePD1Matrix(const CMeshO& mesh); +EigenMatrixX3m faceCurvaturePD2Matrix(const CMeshO& mesh); + +Eigen::MatrixX3i faceFaceAdjacencyMatrix(const CMeshO& mesh); + +EigenVectorXm vertexScalarAttributeArray(const CMeshO& mesh, const std::string& attributeName); +EigenMatrixX3m vertexVectorAttributeMatrix(const CMeshO& mesh, const std::string& attributeName); +EigenVectorXm faceScalarAttributeArray(const CMeshO& mesh, const std::string& attributeName); +EigenMatrixX3m faceVectorAttributeMatrix(const CMeshO& mesh, const std::string& attributeName); +} // namespace meshlab + +#endif // MESHLAB_EIGEN_MESH_CONVERSIONS_H diff --git a/src/common/utilities/file_format.h b/src/common/utilities/file_format.h index e8d053a55..e7244ec3c 100644 --- a/src/common/utilities/file_format.h +++ b/src/common/utilities/file_format.h @@ -30,6 +30,7 @@ class FileFormat { public: FileFormat(QString description, QString ex) : description(description), extensions(ex){} + FileFormat(QString description, QStringList ex) : description(description), extensions(ex){} QString description; QStringList extensions; }; diff --git a/src/common/utilities/load_save.cpp b/src/common/utilities/load_save.cpp new file mode 100644 index 000000000..5ce951f8c --- /dev/null +++ b/src/common/utilities/load_save.cpp @@ -0,0 +1,510 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2005-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "load_save.h" + +#include +#include + +#include "../globals.h" +#include "../plugins/plugin_manager.h" + +#include + +namespace meshlab { + +/** + * @brief This function assumes that you already have the following data: + * - the plugin that is needed to load the mesh + * - the number of meshes that will be loaded from the file + * - the list of MeshModel(s) that will contain the loaded mesh(es) + * - the open parameters that will be used to load the mesh(es) + * + * The function will take care to load the mesh, load textures if needed + * and make all the clean operations after loading the meshes. + * If load fails, throws a MLException. + * + * @param[i] fileName: the filename + * @param[i] ioPlugin: the plugin that supports the file format to load + * @param[i] prePar: the pre open parameters + * @param[i/o] meshList: the list of meshes that will be loaded from the file + * @param[o] maskList: masks of loaded components for each loaded mesh + * @param cb: callback + * @return the list of texture names that could not be loaded + */ +std::list loadMesh( + const QString& fileName, + IOPlugin* ioPlugin, + const RichParameterList& prePar, + const std::list& meshList, + std::list& maskList, + vcg::CallBackPos* cb) +{ + std::list unloadedTextures; + QFileInfo fi(fileName); + QString extension = fi.suffix(); + + QDir oldDir = QDir::current(); + QDir::setCurrent(fi.absolutePath()); + ioPlugin->open(extension, fi.fileName(), meshList, maskList, prePar, cb); + QDir::setCurrent(oldDir.absolutePath()); + + auto itmesh = meshList.begin(); + auto itmask = maskList.begin(); + for (unsigned int i = 0; i < meshList.size(); ++i) { + MeshModel* mm = *itmesh; + int mask = *itmask; + + std::list tmp = mm->loadTextures(nullptr, cb); + unloadedTextures.insert(unloadedTextures.end(), tmp.begin(), tmp.end()); + + int delVertNum = vcg::tri::Clean::RemoveDegenerateVertex(mm->cm); + int delFaceNum = vcg::tri::Clean::RemoveDegenerateFace(mm->cm); + vcg::tri::Allocator::CompactEveryVector(mm->cm); + if (delVertNum > 0 || delFaceNum > 0) + ioPlugin->reportWarning(QString("Warning mesh contains %1 vertices with NAN coords and " + "%2 degenerated faces.\nCorrected.") + .arg(delVertNum) + .arg(delFaceNum)); + + // In case of polygonal meshes the normal should be updated accordingly + if (mask & vcg::tri::io::Mask::IOM_BITPOLYGONAL) { + mm->updateDataMask(MeshModel::MM_POLYGONAL); // just to be sure. Hopefully it should be + // done in the plugin... + mm->updateDataMask(MeshModel::MM_FACEFACETOPO); + vcg::tri::UpdateNormal::PerBitQuadFaceNormalized(mm->cm); + vcg::tri::UpdateNormal::PerVertexFromCurrentFaceNormal(mm->cm); + } // standard case + else { + vcg::tri::UpdateNormal::PerFaceNormalized(mm->cm); + if (!(mask & vcg::tri::io::Mask::IOM_VERTNORMAL)) + vcg::tri::UpdateNormal::PerVertexAngleWeighted(mm->cm); + } + + vcg::tri::UpdateBounding::Box(mm->cm); + if (mm->cm.fn == 0 && mm->cm.en == 0) { + if (mask & vcg::tri::io::Mask::IOM_VERTNORMAL) + mm->updateDataMask(MeshModel::MM_VERTNORMAL); + } + + // updateMenus(); + + // computeRenderingDataOnLoading(mm,isareload, rendOpt); + ++itmesh; + ++itmask; + } + return unloadedTextures; +} + +/** + * @brief loads the given filename and puts the loaded mesh(es) into the + * given MeshDocument. Returns the list of loaded meshes. + * + * If you already know the open parameters that could be used to load the mesh, + * you can pass a RichParameterList containing them. + * Note: only parameters of your RPL that are actually required by the plugin + * will be given as input to the load function. + * If you don't know any parameter, leave the RichParameterList parameter empty. + * + * The function takes care to: + * - find the plugin that loads the format of the file + * - create the required MeshModels into the MeshDocument + * - load the meshes and their textures, with standard parameters + * + * if an error occurs, an exception will be thrown, and MeshDocument won't + * contain new meshes. + */ +std::list loadMeshWithStandardParameters( + const QString& filename, + MeshDocument& md, + vcg::CallBackPos* cb, + RichParameterList prePar) +{ + QFileInfo fi(filename); + QString extension = fi.suffix(); + PluginManager& pm = meshlab::pluginManagerInstance(); + IOPlugin* ioPlugin = pm.inputMeshPlugin(extension); + + if (ioPlugin == nullptr) + throw MLException( + "Mesh " + filename + + " cannot be opened. Your MeshLab version " + "has not plugin to read " + + extension + " file format"); + + ioPlugin->setLog(&md.Log); + + // get the open parameters for the given extension + RichParameterList openParams = ioPlugin->initPreOpenParameter(extension); + + // if some parameters were given in the prePar, then set their values into + // openParams. + // we need to be sure that openParams contains only parameters allowed by the plugin + for (RichParameter& rp : prePar) { + auto it = openParams.findParameter(rp.name()); + if (it != openParams.end()) { + it->setValue(rp.value()); + } + } + openParams.join(meshlab::defaultGlobalParameterList()); + // openParams now contains: + // - if not specified in prePar, default parameter values + // - if specified in prePar, the values into prePar + + unsigned int nMeshes = ioPlugin->numberMeshesContainedInFile(extension, filename, openParams); + std::list meshList; + for (unsigned int i = 0; i < nMeshes; i++) { + MeshModel* mm = md.addNewMesh(filename, fi.fileName()); + if (nMeshes != 1) { + // if the file contains more than one mesh, this id will be + // != -1 + mm->setIdInFile(i); + } + meshList.push_back(mm); + } + + std::list masks; + + try { + loadMesh(filename, ioPlugin, openParams, meshList, masks, cb); + } + catch (const MLException& e) { + for (const MeshModel* mm : meshList) + md.delMesh(mm->id()); + throw e; + } + + return meshList; +} + +void reloadMesh( + const QString& filename, + const std::list& meshList, + GLLogStream* log, + vcg::CallBackPos* cb) +{ + QFileInfo fi(filename); + QString extension = fi.suffix(); + PluginManager& pm = meshlab::pluginManagerInstance(); + IOPlugin* ioPlugin = pm.inputMeshPlugin(extension); + + if (ioPlugin == nullptr) { + throw MLException( + "Mesh " + filename + + " cannot be opened. Your MeshLab " + "version has not plugin to read " + + extension + " file format"); + } + + ioPlugin->setLog(log); + RichParameterList prePar = ioPlugin->initPreOpenParameter(extension); + prePar.join(meshlab::defaultGlobalParameterList()); + + unsigned int nMeshes = ioPlugin->numberMeshesContainedInFile(extension, filename, prePar); + + if (meshList.size() != nMeshes) { + throw MLException( + "Cannot reload " + filename + + ": expected number layers is " + "different from the number of meshes contained in th file."); + } + + std::list masks; + for (MeshModel* mm : meshList) { + mm->clear(); + } + loadMesh(filename, ioPlugin, prePar, meshList, masks, cb); +} + +void saveMeshWithStandardParameters( + const QString& fileName, + MeshModel& m, + GLLogStream* log, + vcg::CallBackPos* cb) +{ + QFileInfo fi(fileName); + QString extension = fi.suffix().toLower(); + + PluginManager& pm = meshlab::pluginManagerInstance(); + IOPlugin* ioPlugin = pm.outputMeshPlugin(extension); + if (ioPlugin == nullptr) { + throw MLException( + "Mesh " + fileName + + " cannot be saved. Your MeshLab " + "version has not plugin to save " + + extension + " file format"); + } + ioPlugin->setLog(log); + int capability = 0, defaultBits = 0; + ioPlugin->exportMaskCapability(extension, capability, defaultBits); + RichParameterList saveParams = ioPlugin->initSaveParameter(extension, m); + + if (defaultBits & vcg::tri::io::Mask::IOM_BITPOLYGONAL) + m.updateDataMask(MeshModel::MM_FACEFACETOPO); + ioPlugin->save(extension, fileName, m, defaultBits, saveParams, cb); + m.setFileName(fileName); + m.saveTextures(fi.absolutePath(), -1, log, cb); +} + +void saveAllMeshes( + const QString& basePath, + MeshDocument& md, + bool onlyVisible, + GLLogStream* log, + vcg::CallBackPos* cb) +{ + PluginManager& pm = meshlab::pluginManagerInstance(); + + for (MeshModel& m : md.meshIterator()) { + if (m.isVisible() || !onlyVisible) { + QString filename, extension; + if (m.fullName().isEmpty()) { + if (m.label().contains('.')) { + extension = QFileInfo(m.label()).suffix(); + filename = QFileInfo(m.label()).baseName(); + } + else { + extension = "ply"; + filename = m.label(); + } + } + else { + QFileInfo fi(m.fullName()); + extension = fi.suffix(); + filename = fi.baseName(); + } + filename.replace(QRegExp("[" + QRegExp::escape("\\/:*?\"<>|") + "]"), QString("_")); + IOPlugin* ioPlugin = pm.outputMeshPlugin(extension); + if (ioPlugin == nullptr) { + std::cerr << "Warning: extension " + extension.toStdString() + + " not supported. Saving " + filename.toStdString() + ".ply."; + filename += ".ply"; + } + else { + filename += ("." + extension.toLower()); + } + filename = basePath + "/" + filename; + saveMeshWithStandardParameters(filename, m, log, cb); + } + } +} + +QImage loadImage(const QString& filename, GLLogStream* log, vcg::CallBackPos* cb) +{ + QFileInfo fi(filename); + QString extension = fi.suffix(); + PluginManager& pm = meshlab::pluginManagerInstance(); + IOPlugin* ioPlugin = pm.inputImagePlugin(extension); + + if (ioPlugin != nullptr) { + ioPlugin->setLog(log); + return ioPlugin->openImage(extension, filename, cb); + } + else { // fallback: try to load the file using QImage::load + QImage img(filename); + if (img.isNull()) { // also QImage::load failed + throw MLException( + "Image " + filename + + " cannot be opened. Your MeshLab version " + "has not plugin to read " + + extension + " file format."); + } + return img; + } +} + +QImage getDummyTexture() +{ + return QImage(":/resources/images/dummy.png"); +} + +void saveImage( + const QString& filename, + const QImage& image, + int quality, + GLLogStream* log, + vcg::CallBackPos* cb) +{ + QFileInfo fi(filename); + QString extension = fi.suffix(); + PluginManager& pm = meshlab::pluginManagerInstance(); + IOPlugin* ioPlugin = pm.outputImagePlugin(extension); + + std::cerr << "Path: " << fi.path().toStdString() << "\n"; + + if (!fi.path().isEmpty()) { + if (!QDir(fi.path()).exists()) { + QDir().mkdir(fi.path()); + } + } + + if (ioPlugin == nullptr) + throw MLException( + "Image " + filename + + " cannot be saved. Your MeshLab version " + "has not plugin to save " + + extension + " file format."); + + ioPlugin->setLog(log); + ioPlugin->saveImage(extension, filename, image, quality, cb); +} + +void loadRaster(const QString& filename, RasterModel& rm, GLLogStream* log, vcg::CallBackPos* cb) +{ + QImage loadedImage = loadImage(filename, log, cb); + rm.setLabel(filename); + rm.addPlane(new RasterPlane(loadedImage, filename, RasterPlane::RGBA)); + + // Read the file into a buffer + FILE* fp = fopen(qUtf8Printable(filename), "rb"); + if (!fp) { + QString errorMsgFormat = + "Exif Parsing: Unable to open file:\n\"%1\"\n\nError details: file %1 is not readable."; + throw MLException(errorMsgFormat.arg(filename)); + } + fseek(fp, 0, SEEK_END); + unsigned long fsize = ftell(fp); + rewind(fp); + unsigned char* buf = new unsigned char[fsize]; + if (fread(buf, 1, fsize, fp) != fsize) { + QString errorMsgFormat = + "Exif Parsing: Unable to read the content of the opened file:\n\"%1\"\n\nError " + "details: file %1 is not readable."; + delete[] buf; + fclose(fp); + throw MLException(errorMsgFormat.arg(filename)); + } + fclose(fp); + + // Parse EXIF + easyexif::EXIFInfo ImageInfo; + int code = ImageInfo.parseFrom(buf, fsize); + delete[] buf; + if (!code) { + log->log(GLLogStream::FILTER, "Warning: unable to parse exif for file " + filename); + } + + if (code || ImageInfo.FocalLengthIn35mm == 0.0f) { + rm.shot.Intrinsics.ViewportPx = + vcg::Point2i(rm.currentPlane->image.width(), rm.currentPlane->image.height()); + rm.shot.Intrinsics.CenterPx = Point2m( + float(rm.currentPlane->image.width() / 2.0), + float(rm.currentPlane->image.width() / 2.0)); + rm.shot.Intrinsics.PixelSizeMm[0] = 36.0f / (float) rm.currentPlane->image.width(); + rm.shot.Intrinsics.PixelSizeMm[1] = rm.shot.Intrinsics.PixelSizeMm[0]; + rm.shot.Intrinsics.FocalMm = 50.0f; + } + else { + rm.shot.Intrinsics.ViewportPx = vcg::Point2i(ImageInfo.ImageWidth, ImageInfo.ImageHeight); + rm.shot.Intrinsics.CenterPx = + Point2m(float(ImageInfo.ImageWidth / 2.0), float(ImageInfo.ImageHeight / 2.0)); + float ratioFocal = ImageInfo.FocalLength / ImageInfo.FocalLengthIn35mm; + rm.shot.Intrinsics.PixelSizeMm[0] = (36.0f * ratioFocal) / (float) ImageInfo.ImageWidth; + rm.shot.Intrinsics.PixelSizeMm[1] = (24.0f * ratioFocal) / (float) ImageInfo.ImageHeight; + rm.shot.Intrinsics.FocalMm = ImageInfo.FocalLength; + } + // End of EXIF reading +} + +std::vector loadProject( + const QStringList& filenames, + IOPlugin* ioPlugin, + MeshDocument& md, + std::vector& rendOpt, + GLLogStream* log, + vcg::CallBackPos* cb) +{ + QFileInfo fi(filenames.first()); + QString extension = fi.suffix(); + + ioPlugin->setLog(log); + return ioPlugin->openProject(extension, filenames, md, rendOpt, cb); +} + +std::vector +loadProject(const QStringList& filenames, MeshDocument& md, GLLogStream* log, vcg::CallBackPos* cb) +{ + QFileInfo fi(filenames.first()); + QString extension = fi.suffix(); + PluginManager& pm = meshlab::pluginManagerInstance(); + IOPlugin* ioPlugin = pm.inputProjectPlugin(extension); + + if (ioPlugin == nullptr) + throw MLException( + "Project " + filenames.first() + + " cannot be loaded. Your MeshLab version " + "has not plugin to load " + + extension + " file format."); + + std::list additionalFiles = + ioPlugin->projectFileRequiresAdditionalFiles(extension, filenames.first()); + + if (additionalFiles.size() + 1 != (unsigned int) filenames.size()) { + throw MLException( + "The number of input files given (" + QString::number(filenames.size()) + + ") is different from the expected one (" + QString::number(additionalFiles.size() + 1)); + } + std::vector rendOpt; + return loadProject(filenames, ioPlugin, md, rendOpt, log, cb); +} + +std::vector +loadProject(const QString& filename, MeshDocument& md, GLLogStream* log, vcg::CallBackPos* cb) +{ + QStringList fnms; + fnms.push_back(filename); + return loadProject(fnms, md, log, cb); +} + +void saveProject( + const QString& filename, + const MeshDocument& md, + bool onlyVisibleMeshes, + std::vector renderData) +{ + QFileInfo fi(filename); + QString extension = fi.suffix(); + + PluginManager& pm = meshlab::pluginManagerInstance(); + IOPlugin* ioPlugin = pm.outputProjectPlugin(extension); + + if (ioPlugin == nullptr) + throw MLException( + "Project " + filename + + " cannot be loaded. Your MeshLab version " + "has not plugin to load " + + extension + " file format."); + + if (renderData.size() != 0 && md.meshNumber() != renderData.size()) { + std::cerr << "Warning: renderData vector has different size from " + "MeshDocument number meshes. Ignoring render data when saving " + + filename.toStdString() + << " project."; + renderData.clear(); + } + + RichParameterList rpl; + ioPlugin->saveProject(extension, filename, md, onlyVisibleMeshes, renderData); +} + +} // namespace meshlab diff --git a/src/common/utilities/load_save.h b/src/common/utilities/load_save.h new file mode 100644 index 000000000..cfc28a28f --- /dev/null +++ b/src/common/utilities/load_save.h @@ -0,0 +1,116 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2005-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_LOAD_SAVE_H +#define MESHLAB_LOAD_SAVE_H + +#include "../ml_shared_data_context/ml_shared_data_context.h" +#include "../plugins/interfaces/io_plugin.h" + +/** + * Utility functions to load/save meshes using plugins loaded in the plugin + * manager. + */ + +namespace meshlab { + +std::list loadMesh( + const QString& fileName, + IOPlugin* ioPlugin, + const RichParameterList& prePar, + const std::list& meshList, + std::list& maskList, + vcg::CallBackPos* cb); + +std::list loadMeshWithStandardParameters( + const QString& filename, + MeshDocument& md, + vcg::CallBackPos* cb = nullptr, + RichParameterList prePar = RichParameterList()); + +void reloadMesh( + const QString& filename, + const std::list& meshList, + GLLogStream* log = nullptr, + vcg::CallBackPos* cb = nullptr); + +void saveMeshWithStandardParameters( + const QString& fileName, + MeshModel& m, + GLLogStream* log = nullptr, + vcg::CallBackPos* cb = nullptr); + +void saveAllMeshes( + const QString& basePath, + MeshDocument& md, + bool onlyVisible = false, + GLLogStream* log = nullptr, + vcg::CallBackPos* cb = nullptr); + +QImage +loadImage(const QString& filename, GLLogStream* log = nullptr, vcg::CallBackPos* cb = nullptr); + +QImage getDummyTexture(); + +void saveImage( + const QString& filename, + const QImage& image, + int quality = -1, + GLLogStream* log = nullptr, + vcg::CallBackPos* cb = nullptr); + +void loadRaster( + const QString& filename, + RasterModel& rm, + GLLogStream* log = nullptr, + vcg::CallBackPos* cb = nullptr); + +std::vector loadProject( + const QStringList& filenames, + IOPlugin* ioPlugin, + MeshDocument& md, + std::vector& rendOpt, + GLLogStream* log = nullptr, + vcg::CallBackPos* cb = nullptr); + +std::vector loadProject( + const QStringList& filenames, + MeshDocument& md, + GLLogStream* log = nullptr, + vcg::CallBackPos* cb = nullptr); + +std::vector loadProject( + const QString& filename, + MeshDocument& md, + GLLogStream* log = nullptr, + vcg::CallBackPos* cb = nullptr); + +void saveProject( + const QString& filename, + const MeshDocument& md, + bool onlyVisibleMeshes, + std::vector renderData = std::vector()); + +} // namespace meshlab + +#endif // MESHLAB_LOAD_SAVE_H diff --git a/src/common_gui/CMakeLists.txt b/src/common_gui/CMakeLists.txt new file mode 100644 index 000000000..1af96d5be --- /dev/null +++ b/src/common_gui/CMakeLists.txt @@ -0,0 +1,85 @@ +set(HEADERS + gui_utils/clickable_label.h + gui_utils/vertical_scroll_area.h + + rich_parameter/widgets/bool_widget.h + rich_parameter/widgets/color_widget.h + rich_parameter/widgets/combo_widget.h + rich_parameter/widgets/direction_widget.h + rich_parameter/widgets/dynamic_float_widget.h + rich_parameter/widgets/enum_widget.h + rich_parameter/widgets/float_widget.h + rich_parameter/widgets/int_widget.h + rich_parameter/widgets/io_file_widget.h + rich_parameter/widgets/line_edit_widget.h + rich_parameter/widgets/matrix44_widget.h + rich_parameter/widgets/mesh_widget.h + rich_parameter/widgets/open_file_widget.h + rich_parameter/widgets/percentage_widget.h + rich_parameter/widgets/point3_widget.h + rich_parameter/widgets/position_widget.h + rich_parameter/widgets/rich_parameter_widget.h + rich_parameter/widgets/rich_parameter_widgets.h + rich_parameter/widgets/save_file_widget.h + rich_parameter/widgets/shot_widget.h + rich_parameter/widgets/string_widget.h + + rich_parameter/richparameterlistdialog.h + rich_parameter/rich_parameter_list_frame.h +) + +set(SOURCES + gui_utils/clickable_label.cpp + gui_utils/vertical_scroll_area.cpp + + rich_parameter/widgets/bool_widget.cpp + rich_parameter/widgets/color_widget.cpp + rich_parameter/widgets/combo_widget.cpp + rich_parameter/widgets/direction_widget.cpp + rich_parameter/widgets/dynamic_float_widget.cpp + rich_parameter/widgets/enum_widget.cpp + rich_parameter/widgets/float_widget.cpp + rich_parameter/widgets/int_widget.cpp + rich_parameter/widgets/io_file_widget.cpp + rich_parameter/widgets/line_edit_widget.cpp + rich_parameter/widgets/matrix44_widget.cpp + rich_parameter/widgets/mesh_widget.cpp + rich_parameter/widgets/open_file_widget.cpp + rich_parameter/widgets/percentage_widget.cpp + rich_parameter/widgets/point3_widget.cpp + rich_parameter/widgets/position_widget.cpp + rich_parameter/widgets/rich_parameter_widget.cpp + rich_parameter/widgets/save_file_widget.cpp + rich_parameter/widgets/shot_widget.cpp + rich_parameter/widgets/string_widget.cpp + + rich_parameter/richparameterlistdialog.cpp + rich_parameter/rich_parameter_list_frame.cpp +) + +set(RESOURCES ) + +set(TARGET_TYPE SHARED) +add_library(meshlab-common-gui ${TARGET_TYPE} ${SOURCES} ${HEADERS} ${RESOURCES}) + +target_link_libraries( + meshlab-common-gui + PUBLIC + meshlab-common +) + +set_property(TARGET meshlab-common-gui PROPERTY FOLDER Core) + +set_property(TARGET meshlab-common-gui + PROPERTY RUNTIME_OUTPUT_DIRECTORY ${MESHLAB_LIB_OUTPUT_DIR}) + +set_property(TARGET meshlab-common-gui + PROPERTY LIBRARY_OUTPUT_DIRECTORY ${MESHLAB_LIB_OUTPUT_DIR}) + +set_target_properties(meshlab-common-gui PROPERTIES + INSTALL_RPATH "${MESHLAB_LIB_INSTALL_DIR}:${INSTALL_RPATH}") + +set_target_properties(meshlab-common-gui PROPERTIES + INSTALL_RPATH "$ORIGIN") + +install(TARGETS meshlab-common-gui DESTINATION ${MESHLAB_LIB_INSTALL_DIR}) diff --git a/src/common_gui/gui_utils/clickable_label.cpp b/src/common_gui/gui_utils/clickable_label.cpp new file mode 100644 index 000000000..4b46d8416 --- /dev/null +++ b/src/common_gui/gui_utils/clickable_label.cpp @@ -0,0 +1,41 @@ +/***************************************************************************** + * VCGLib o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ +#include "clickable_label.h" + +ClickableLabel::ClickableLabel(QWidget* parent, Qt::WindowFlags f) : QLabel(parent, f) +{ +} + +ClickableLabel::ClickableLabel(const QString& description, QWidget* parent, Qt::WindowFlags f) : + QLabel(description, parent, f) +{ +} + +ClickableLabel::~ClickableLabel() +{ +} + +void ClickableLabel::mousePressEvent(QMouseEvent*) +{ + emit clicked(); +} diff --git a/src/common_gui/gui_utils/clickable_label.h b/src/common_gui/gui_utils/clickable_label.h new file mode 100644 index 000000000..eede28963 --- /dev/null +++ b/src/common_gui/gui_utils/clickable_label.h @@ -0,0 +1,51 @@ +/***************************************************************************** + * VCGLib o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ +#ifndef CLICKABLELABEL_H +#define CLICKABLELABEL_H + +#include +#include +#include + +/** + * @brief A QLabel class with clicked signal + * + * https://wiki.qt.io/Clickable_QLabel + */ +class ClickableLabel : public QLabel +{ + Q_OBJECT + +public: + explicit ClickableLabel(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); + explicit ClickableLabel(const QString& description, QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); + ~ClickableLabel(); + +signals: + void clicked(); + +protected: + void mousePressEvent(QMouseEvent* event); +}; + +#endif // CLICKABLELABEL_H diff --git a/src/common_gui/gui_utils/vertical_scroll_area.cpp b/src/common_gui/gui_utils/vertical_scroll_area.cpp new file mode 100644 index 000000000..91a1b2997 --- /dev/null +++ b/src/common_gui/gui_utils/vertical_scroll_area.cpp @@ -0,0 +1,45 @@ +/***************************************************************************** + * VCGLib o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ +#include "vertical_scroll_area.h" + +#include +#include +#include + +#include "vertical_scroll_area.h" + +VerticalScrollArea::VerticalScrollArea(QWidget* parent) : QScrollArea(parent) +{ + setWidgetResizable(true); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); +} + +bool VerticalScrollArea::eventFilter(QObject* o, QEvent* e) +{ + // This works because QScrollArea::setWidget installs an eventFilter on the widget + if (o && o == widget() && e->type() == QEvent::Resize) + setMinimumWidth(widget()->minimumSizeHint().width() + verticalScrollBar()->width()); + + return QScrollArea::eventFilter(o, e); +} diff --git a/src/common_gui/gui_utils/vertical_scroll_area.h b/src/common_gui/gui_utils/vertical_scroll_area.h new file mode 100644 index 000000000..a7d207cfe --- /dev/null +++ b/src/common_gui/gui_utils/vertical_scroll_area.h @@ -0,0 +1,48 @@ +/***************************************************************************** + * VCGLib o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ +#ifndef VERTICAL_SCROLL_AREA_H +#define VERTICAL_SCROLL_AREA_H + +#include + +/** + * @brief The VerticalScrollArea class + * + * This class is necessary because Qt does not provide a pure Vertical Scroll Area, + * that behaves as a normal qwidget horizontally. + * + * @see https://forum.qt.io/topic/13374/solved-qscrollarea-vertical-scroll-only + */ +class VerticalScrollArea : public QScrollArea +{ + Q_OBJECT +public: + explicit VerticalScrollArea(QWidget* parent = 0); + + virtual bool eventFilter(QObject* o, QEvent* e); + +private: + QWidget* m_scrollAreaWidgetContents; +}; + +#endif // VERTICAL_SCROLL_AREA_H diff --git a/src/common_gui/rich_parameter/rich_parameter_list_frame.cpp b/src/common_gui/rich_parameter/rich_parameter_list_frame.cpp new file mode 100644 index 000000000..51cfe5b7f --- /dev/null +++ b/src/common_gui/rich_parameter/rich_parameter_list_frame.cpp @@ -0,0 +1,305 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_parameter_list_frame.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace vcg; + +RichParameterListFrame::RichParameterListFrame(QWidget* parent) : + QFrame(parent), isHelpVisible(false), gla(nullptr) +{ +} + +RichParameterListFrame::RichParameterListFrame( + const RichParameterList& parameterList, + const RichParameterList& defaultValuesList, + QWidget* p, + QWidget* gla) : + QFrame(p), isHelpVisible(false), gla(gla) +{ + loadFrameContent(parameterList, defaultValuesList); +} + +RichParameterListFrame::RichParameterListFrame( + const RichParameterList& parameterList, + QWidget* p, + QWidget* gla) : + QFrame(p), isHelpVisible(false), gla(gla) +{ + loadFrameContent(parameterList, parameterList); +} + +RichParameterListFrame::RichParameterListFrame( + const RichParameter& parameter, + const RichParameter& defaultValue, + QWidget* p, + QWidget* gla) : + QFrame(p), isHelpVisible(false), gla(gla) +{ + RichParameterList crpl; + crpl.addParam(parameter); + RichParameterList drpl; + drpl.addParam(defaultValue); + loadFrameContent(crpl, drpl); +} + +RichParameterListFrame::~RichParameterListFrame() +{ +} + +void RichParameterListFrame::initParams( + const RichParameterList& curParSet, + const RichParameterList& defParSet, + QWidget* gla) +{ + if (gla != nullptr) + this->gla = gla; + loadFrameContent(curParSet, defParSet); +} + +/** + * @brief RichParameterListFrame::readValues + * From GUI to RichParameterList + * @param curParSet + */ +void RichParameterListFrame::writeValuesOnParameterList(RichParameterList& curParSet) +{ + assert(curParSet.size() == (unsigned int) stdfieldwidgets.size()); + for (auto& p : stdfieldwidgets) { + curParSet.setValue(p.first, *(p.second)->getWidgetValue()); + } +} + +void RichParameterListFrame::resetValues() +{ + for (auto& p : stdfieldwidgets) { + p.second->resetWidgetToDefaultValue(); + rpl.getParameterByName(p.first).setValue(*p.second->getWidgetValue(), true); + } +} + +void RichParameterListFrame::toggleHelp() +{ + isHelpVisible = !isHelpVisible; + for (auto& p : stdfieldwidgets) { + p.second->setHelpVisible(isHelpVisible); + } + adjustSize(); + updateGeometry(); +} + +unsigned int RichParameterListFrame::size() const +{ + return stdfieldwidgets.size(); +} + +RichParameterList RichParameterListFrame::currentRichParameterList() const +{ + for (const auto& w : *this) { + if (w.second->hasBeenChanged()) { + rpl.getParameterByName(w.first).setValue(*w.second->getWidgetValue()); + } + } + return rpl; +} + +RichParameterListFrame::iterator RichParameterListFrame::begin() +{ + return stdfieldwidgets.begin(); +} + +RichParameterListFrame::iterator RichParameterListFrame::end() +{ + return stdfieldwidgets.end(); +} + +RichParameterListFrame::const_iterator RichParameterListFrame::begin() const +{ + return stdfieldwidgets.begin(); +} + +RichParameterListFrame::const_iterator RichParameterListFrame::end() const +{ + return stdfieldwidgets.end(); +} + +void RichParameterListFrame::toggleAdvancedParameters() +{ + if (areAdvancedParametersVisible) { + showHiddenFramePushButton->setText("▼"); + showHiddenFramePushButton->setToolTip("Show advanced parameters"); + } + else { + showHiddenFramePushButton->setText("▲"); + showHiddenFramePushButton->setToolTip("Hide advanced parameters"); + } + areAdvancedParametersVisible = !areAdvancedParametersVisible; + for (const QString& name : advancedParameters) { + stdfieldwidgets[name]->setVisible(areAdvancedParametersVisible); + } +} + +void RichParameterListFrame::loadFrameContent( + const RichParameterList& curParSet, + const RichParameterList& defParSet) +{ + if (layout()) + delete layout(); + QGridLayout* glay = new QGridLayout(); + + // collect parameters per category + std::map> parameters; + + for (const RichParameter& fpi : curParSet) { + parameters[fpi.category()].push_back(&fpi); + if (fpi.isAdvanced()) { + advancedParameters.insert(fpi.name()); + } + } + + int i = 0; + // parameters are organized into categories + for (const auto& p : parameters) { + // if not the default category, the category name must be printed in the dialog + // before the list of parameter widgets + if (!p.first.isEmpty()) { + QString labltext = "

" + p.first + ":

"; + QLabel* l = new QLabel(labltext, this); + l->setAlignment(Qt::AlignRight); + glay->addWidget(l, i++, 0); + } + // put the parameter widgets into the grid layout + for (const RichParameter* fpi : p.second) { + const RichParameter& defrp = defParSet.getParameterByName(fpi->name()); + RichParameterWidget* wd = createWidgetFromRichParameter(this, *fpi, defrp.value()); + stdfieldwidgets[fpi->name()] = wd; + wd->addWidgetToGridLayout(glay, i++); + } + } + if (advancedParameters.size() > 0) { + showHiddenFramePushButton = new QPushButton("", this); + showHiddenFramePushButton->setFlat(true); + glay->addWidget(showHiddenFramePushButton, i++, 0, 1, 3); + connect( + showHiddenFramePushButton, SIGNAL(clicked()), this, SLOT(toggleAdvancedParameters())); + // set first advanced params visible, and then toggle them in order to + // initialize the button and then set the visibility correctly to all the elements + areAdvancedParametersVisible = true; + toggleAdvancedParameters(); + } + + QSpacerItem* spacer = new QSpacerItem(40, 20, QSizePolicy::Minimum, QSizePolicy::Expanding); + glay->addItem(spacer, i++, 0); + setLayout(glay); + rpl = curParSet; + rpl.setAllValuesAsDefault(); +} + +RichParameterWidget* RichParameterListFrame::createWidgetFromRichParameter( + RichParameterListFrame* parent, + const RichParameter& pd, + const Value& defaultValue) +{ + RichParameterWidget* w = nullptr; + if (pd.isOfType() && defaultValue.isOfType()) { + w = new PercentageWidget( + parent, (const RichPercentage&) pd, (const FloatValue&) defaultValue); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new DynamicFloatWidget( + parent, (const RichDynamicFloat&) pd, (const FloatValue&) defaultValue); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new EnumWidget(parent, (const RichEnum&) pd, (const IntValue&) defaultValue); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new BoolWidget(parent, (const RichBool&) pd, (const BoolValue&) defaultValue); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new IntWidget(parent, (const RichInt&) pd, (const IntValue&) defaultValue); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new FloatWidget(parent, (const RichFloat&) pd, (const FloatValue&) defaultValue); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new StringWidget(parent, (const RichString&) pd, (const StringValue&) defaultValue); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new Matrix44Widget( + parent, + (const RichMatrix44&) pd, + (const Matrix44Value&) defaultValue, + reinterpret_cast(parent)->gla); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new PositionWidget( + parent, + (const RichPosition&) pd, + (const Point3Value&) defaultValue, + reinterpret_cast(parent)->gla); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new DirectionWidget( + parent, + (const RichDirection&) pd, + (const Point3Value&) defaultValue, + reinterpret_cast(parent)->gla); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new ShotWidget( + parent, + (const RichShot&) pd, + (const ShotValue&) defaultValue, + reinterpret_cast(parent)->gla); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new ColorWidget(parent, (const RichColor&) pd, (const ColorValue&) defaultValue); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new OpenFileWidget( + parent, (const RichFileOpen&) pd, (const StringValue&) defaultValue); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new SaveFileWidget( + parent, (const RichFileSave&) pd, (const StringValue&) defaultValue); + } + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new MeshWidget(parent, (const RichMesh&) pd, (const IntValue&) defaultValue); + } + else { + std::cerr << "RichParameter type not supported for widget creation.\n"; + assert(0); + return nullptr; + } + connect(w, SIGNAL(parameterChanged()), parent, SIGNAL(parameterChanged())); + return w; +} diff --git a/src/common_gui/rich_parameter/rich_parameter_list_frame.h b/src/common_gui/rich_parameter/rich_parameter_list_frame.h new file mode 100644 index 000000000..087599abb --- /dev/null +++ b/src/common_gui/rich_parameter/rich_parameter_list_frame.h @@ -0,0 +1,117 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef RICH_PARAMETER_LIST_FRAME_H +#define RICH_PARAMETER_LIST_FRAME_H + +#include "widgets/rich_parameter_widgets.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +/*---------------------------------*/ + +/** + * This class is used to automatically create a frame from a set of parameters. + * it is used mostly for creating the main dialog of the filters, but it is used also + * in the creation of the additional saving options, post and pre opening processing + * and for general parameter setting in edit plugins (e.g. look at the alignment parameters) + */ +class RichParameterListFrame : public QFrame +{ + Q_OBJECT +public: + typedef std::map::iterator iterator; + typedef std::map::const_iterator const_iterator; + + RichParameterListFrame(QWidget* parent); + RichParameterListFrame( + const RichParameterList& parameterList, + const RichParameterList& defaultValuesList, + QWidget* p, + QWidget* gla = 0); + RichParameterListFrame(const RichParameterList& parameterList, QWidget* p, QWidget* gla = 0); + RichParameterListFrame( + const RichParameter& curPar, + const RichParameter& defPar, + QWidget* p, + QWidget* gla = 0); + ~RichParameterListFrame(); + + void initParams( + const RichParameterList& curParSet, + const RichParameterList& defParSet, + QWidget* gla = nullptr); + + // The curParSet that is passed must be 'compatible' with the RichParameterSet that have been + // used to create the frame. This function updates the RichParameterSet used to create the frame + // AND fill also the passed + void writeValuesOnParameterList(RichParameterList& curParSet); + void resetValues(); + + void toggleHelp(); + + unsigned int size() const; + + RichParameterList currentRichParameterList() const; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + +signals: + void parameterChanged(); + +public slots: + void toggleAdvancedParameters(); + +private: + void loadFrameContent(const RichParameterList& curParSet, const RichParameterList& defParSet); + + static RichParameterWidget* createWidgetFromRichParameter( + RichParameterListFrame *parent, + const RichParameter& pd, + const Value& defaultValue); + + mutable RichParameterList rpl; // a list containing all the parameters in the frame. + // the list does not contain updated values. + // it is updated just when someone asks a list containing the current values of the frame + + std::map stdfieldwidgets; + bool isHelpVisible; + + QWidget* gla; // used for having a link to the glarea that spawned the parameter asking. + bool areAdvancedParametersVisible; + std::set advancedParameters; + QPushButton* showHiddenFramePushButton; +}; + +#endif // RICH_PARAMETER_LIST_FRAME_H diff --git a/src/meshlab/rich_parameter_gui/richparameterlistdialog.cpp b/src/common_gui/rich_parameter/richparameterlistdialog.cpp similarity index 79% rename from src/meshlab/rich_parameter_gui/richparameterlistdialog.cpp rename to src/common_gui/rich_parameter/richparameterlistdialog.cpp index 128b63c91..987fe8ba5 100644 --- a/src/meshlab/rich_parameter_gui/richparameterlistdialog.cpp +++ b/src/common_gui/rich_parameter/richparameterlistdialog.cpp @@ -72,11 +72,33 @@ void RichParameterListDialog::createFrame() connect(resetButton, SIGNAL(clicked()), this, SLOT(resetValues())); setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); +} - //set the minimum size so it will shrink down to the right size after the help is toggled - this->setMinimumSize(stdParFrame->sizeHint()); - this->showNormal(); - this->adjustSize(); +void RichParameterListDialog::addVerticalSpacer() +{ + QGridLayout* lay = (QGridLayout*)stdParFrame->layout(); + QSpacerItem *spacer = new QSpacerItem(0, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + lay->addItem(spacer, lay->rowCount(), 0); + lay->setRowMinimumHeight(lay->rowCount(), 10); +} + +void RichParameterListDialog::addCheckBox(const QString& name, bool checked) +{ + QLabel* l = new QLabel(stdParFrame); + l->setText(name); + l->setAlignment(Qt::AlignRight); + QCheckBox* cb = new QCheckBox(stdParFrame); + cb->setText(""); + cb->setChecked(checked); + QGridLayout* lay = (QGridLayout*)stdParFrame->layout(); + lay->addWidget(l,lay->rowCount(), 0); + lay->addWidget(cb,lay->rowCount()-1, 1); + additionalCheckBoxes[name] = cb; +} + +bool RichParameterListDialog::isCheckBoxChecked(const QString& name) +{ + return additionalCheckBoxes.at(name)->isChecked(); } diff --git a/src/common_gui/rich_parameter/richparameterlistdialog.h b/src/common_gui/rich_parameter/richparameterlistdialog.h new file mode 100644 index 000000000..de8160073 --- /dev/null +++ b/src/common_gui/rich_parameter/richparameterlistdialog.h @@ -0,0 +1,69 @@ +/**************************************************************************** + * VCGLib o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2021 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef RICHPARAMETERLISTDIALOG_H +#define RICHPARAMETERLISTDIALOG_H + +#include + +#include +#include "rich_parameter_list_frame.h" + +/** + * @brief This class provide a modal dialog box for asking a generic parameter list + * It can be used by anyone needing for some values in a structured form and having some integrated help + * + * When the user clicks ok, the dialog will apply the modified values in the RichParameterList given + * as input in the Dialog constructor. + * Used by some I/O and Edit plugins + * + */ +class RichParameterListDialog: public QDialog +{ + Q_OBJECT +public: + RichParameterListDialog(QWidget *p, RichParameterList& curParList, const QString& title=QString()); + ~RichParameterListDialog(); + + void createFrame(); + + void addVerticalSpacer(); + void addCheckBox(const QString& name, bool checked); + bool isCheckBoxChecked(const QString& name); + +public slots: + void getAccept(); + void toggleHelp(); + + //reset the values on the gui back to the ones originally given to the dialog + void resetValues(); + +private: + RichParameterList& curParList; + RichParameterListFrame *stdParFrame; + + std::map additionalCheckBoxes; + +}; + +#endif // RICHPARAMETERLISTDIALOG_H diff --git a/src/common_gui/rich_parameter/widgets/bool_widget.cpp b/src/common_gui/rich_parameter/widgets/bool_widget.cpp new file mode 100644 index 000000000..ec5e801a0 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/bool_widget.cpp @@ -0,0 +1,58 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "bool_widget.h" + +BoolWidget::BoolWidget(QWidget* p, const RichBool& param, const BoolValue& defaultValue) : + RichParameterWidget(p, param, defaultValue) +{ + cb = new QCheckBox("", this); + cb->setToolTip(param.toolTip()); + cb->setChecked(param.value().getBool()); + widgets.push_back(cb); + + connect(cb, SIGNAL(stateChanged(int)), this, SLOT(setParameterChanged())); + connect(descriptionLabel, SIGNAL(clicked()), cb, SLOT(toggle())); +} + +BoolWidget::~BoolWidget() +{ +} + +void BoolWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addWidget(cb, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr BoolWidget::getWidgetValue() const +{ + return std::make_shared(cb->isChecked()); +} + +void BoolWidget::setWidgetValue(const Value& nv) +{ + cb->setChecked(nv.getBool()); +} diff --git a/src/common_gui/rich_parameter/widgets/bool_widget.h b/src/common_gui/rich_parameter/widgets/bool_widget.h new file mode 100644 index 000000000..80beb3daa --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/bool_widget.h @@ -0,0 +1,43 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_BOOL_WIDGET_H +#define MESHLAB_BOOL_WIDGET_H + +#include "rich_parameter_widget.h" + +class BoolWidget : public RichParameterWidget +{ +public: + BoolWidget(QWidget* p, const RichBool& param, const BoolValue& defaultValue); + ~BoolWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + +private: + QCheckBox* cb; +}; + +#endif // MESHLAB_BOOL_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/color_widget.cpp b/src/common_gui/rich_parameter/widgets/color_widget.cpp new file mode 100644 index 000000000..20ef45764 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/color_widget.cpp @@ -0,0 +1,102 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "color_widget.h" + +#include + +ColorWidget::ColorWidget(QWidget* p, const RichColor& param, const ColorValue& defaultValue) : + RichParameterWidget(p, param, defaultValue), pickcol(defaultValue.getColor()) +{ + colorLabel = new QLabel(this); + colorButton = new QPushButton(this); + colorButton->setAutoFillBackground(true); + colorButton->setFlat(true); + colorButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + QColor cl = param.value().getColor(); + pickcol = cl; + updateColorInfo(cl); + + vlay = new QHBoxLayout(); + QFontMetrics met(colorLabel->font()); + QColor black(Qt::black); + QString blackname = "(" + black.name() + ")"; + QSize sz = met.size(Qt::TextSingleLine, blackname); + colorLabel->setMaximumWidth(sz.width()); + colorLabel->setMinimumWidth(sz.width()); + vlay->addWidget(colorLabel, 0, Qt::AlignRight); + vlay->addWidget(colorButton); + widgets.push_back(colorLabel); + widgets.push_back(colorButton); + + connect(colorButton, SIGNAL(clicked()), this, SLOT(pickColor())); + connect(this, SIGNAL(dialogParamChanged()), this, SLOT(setParameterChanged())); +} + +ColorWidget::~ColorWidget() +{ + delete colorButton; + delete colorLabel; +} + +void ColorWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(vlay, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr ColorWidget::getWidgetValue() const +{ + return std::make_shared(pickcol); +} + +void ColorWidget::setWidgetValue(const Value& nv) +{ + QColor cl = nv.getColor(); + pickcol = cl; + updateColorInfo(cl); +} + +void ColorWidget::updateColorInfo(const ColorValue& newColor) +{ + QColor col = newColor.getColor(); + colorLabel->setText("(" + col.name() + ")"); + QPalette palette(col); + colorButton->setPalette(palette); +} + +void ColorWidget::pickColor() +{ + QColor tmp = pickcol; + auto dialogParam = QColorDialog::DontUseNativeDialog | QColorDialog::ShowAlphaChannel; + pickcol = QColorDialog::getColor(pickcol, this->parentWidget(), "Pick a Color", dialogParam); + if (pickcol.isValid()) { + updateColorInfo(ColorValue(pickcol)); + emit dialogParamChanged(); + } + else { + pickcol = tmp; + } +} diff --git a/src/common_gui/rich_parameter/widgets/color_widget.h b/src/common_gui/rich_parameter/widgets/color_widget.h new file mode 100644 index 000000000..62f41fcf7 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/color_widget.h @@ -0,0 +1,56 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_COLOR_WIDGET_H +#define MESHLAB_COLOR_WIDGET_H + +#include "rich_parameter_widget.h" + +class ColorWidget : public RichParameterWidget +{ + Q_OBJECT +public: + ColorWidget(QWidget* p, const RichColor& param, const ColorValue& defaultValue); + ~ColorWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + +private: + void updateColorInfo(const ColorValue& newColor); +private slots: + void pickColor(); +signals: + void dialogParamChanged(); + +protected: + QHBoxLayout* vlay; + +private: + QPushButton* colorButton; + QLabel* colorLabel; + QColor pickcol; +}; + +#endif // MESHLAB_COLOR_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/combo_widget.cpp b/src/common_gui/rich_parameter/widgets/combo_widget.cpp new file mode 100644 index 000000000..7f4f9ce3d --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/combo_widget.cpp @@ -0,0 +1,71 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "combo_widget.h" + +ComboWidget::ComboWidget(QWidget* p, const RichParameter& param, const Value& defaultValue) : + RichParameterWidget(p, param, defaultValue), enumCombo(new QComboBox(this)) +{ +} + +ComboWidget::ComboWidget( + QWidget* p, + const RichParameter& rpar, + const Value& defaultValue, + const QStringList& values, + int defaultEnum) : + RichParameterWidget(p, rpar, defaultValue), enumCombo(new QComboBox(this)) +{ + init(defaultEnum, values); +} + +ComboWidget::~ComboWidget() +{ +} + +void ComboWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addWidget(enumCombo, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +void ComboWidget::setIndex(int newEnum) +{ + enumCombo->setCurrentIndex(newEnum); +} + +int ComboWidget::getIndex() +{ + return enumCombo->currentIndex(); +} + +void ComboWidget::init(int defaultEnum, QStringList values) +{ + enumCombo->addItems(values); + widgets.push_back(enumCombo); + setIndex(defaultEnum); + connect(enumCombo, SIGNAL(activated(int)), this, SIGNAL(dialogParamChanged())); + connect(this, SIGNAL(dialogParamChanged()), this, SLOT(setParameterChanged())); +} diff --git a/src/common_gui/rich_parameter/widgets/combo_widget.h b/src/common_gui/rich_parameter/widgets/combo_widget.h new file mode 100644 index 000000000..4bf48d837 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/combo_widget.h @@ -0,0 +1,59 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_COMBO_WIDGET_H +#define MESHLAB_COMBO_WIDGET_H + +#include "rich_parameter_widget.h" + +class ComboWidget : public RichParameterWidget +{ + Q_OBJECT +protected: + QComboBox* enumCombo; + +public: + ComboWidget(QWidget* p, const RichParameter& param, const Value& defaultValue); + ComboWidget( + QWidget* p, + const RichParameter& rpar, + const Value& defaultValue, + const QStringList& values, + int defaultEnum); + ~ComboWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + virtual std::shared_ptr getWidgetValue() const = 0; + virtual void setWidgetValue(const Value& nv) = 0; + + int getIndex(); + void setIndex(int newEnum); + +signals: + void dialogParamChanged(); + +protected: + void init(int newEnum, QStringList values); +}; + +#endif // MESHLAB_COMBO_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/direction_widget.cpp b/src/common_gui/rich_parameter/widgets/direction_widget.cpp new file mode 100644 index 000000000..2463ec02c --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/direction_widget.cpp @@ -0,0 +1,67 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "direction_widget.h" + +DirectionWidget::DirectionWidget( + QWidget* p, + const RichDirection& param, + const Point3Value& defaultValue, + QWidget* gla) : + Point3Widget(p, param, defaultValue, gla) +{ + // if we have a connection to the current glarea we can setup the additional + // button for getting the current view direction. + if (gla) { + QStringList names; + names << "View Dir."; + names << "Raster Camera Dir."; + + getPoint3Combo->addItems(names); + + connect( + gla, SIGNAL(transmitViewDir(QString, Point3m)), this, SLOT(setValue(QString, Point3m))); + connect( + gla, SIGNAL(transmitShot(QString, Shotm)), this, SLOT(setShotValue(QString, Shotm))); + connect(this, SIGNAL(askViewDir(QString)), gla, SLOT(sendViewDir(QString))); + connect(this, SIGNAL(askCameraDir(QString)), gla, SLOT(sendRasterShot(QString))); + + connect(getPoint3Button, SIGNAL(clicked()), this, SLOT(getPoint())); + } +} + +DirectionWidget::~DirectionWidget() +{ + this->disconnect(); +} + +void DirectionWidget::getPoint() +{ + int index = getPoint3Combo->currentIndex(); + switch (index) { + case 0: emit askViewDir(paramName); break; + case 1: emit askCameraDir(paramName); break; + + default: assert(0); + } +} diff --git a/src/common_gui/rich_parameter/widgets/direction_widget.h b/src/common_gui/rich_parameter/widgets/direction_widget.h new file mode 100644 index 000000000..06adb03aa --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/direction_widget.h @@ -0,0 +1,48 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_DIRECTION_WIDGET_H +#define MESHLAB_DIRECTION_WIDGET_H + +#include "point3_widget.h" + +class DirectionWidget : public Point3Widget +{ + Q_OBJECT +public: + DirectionWidget( + QWidget* p, + const RichDirection& param, + const Point3Value& defaultValue, + QWidget* gla); + ~DirectionWidget(); + +public slots: + void getPoint(); + +signals: + void askViewDir(QString); + void askCameraDir(QString); +}; + +#endif // MESHLAB_DIRECTION_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/dynamic_float_widget.cpp b/src/common_gui/rich_parameter/widgets/dynamic_float_widget.cpp new file mode 100644 index 000000000..dbb08fdce --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/dynamic_float_widget.cpp @@ -0,0 +1,117 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "dynamic_float_widget.h" + +DynamicFloatWidget::DynamicFloatWidget( + QWidget* p, + const RichDynamicFloat& param, + const FloatValue& defaultValue) : + RichParameterWidget(p, param, defaultValue) +{ + int numbdecimaldigit = 4; + minVal = param.min; + maxVal = param.max; + valueLE = new QLineEdit(this); + valueLE->setAlignment(Qt::AlignRight); + + valueSlider = new QSlider(Qt::Horizontal, this); + valueSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + valueSlider->setMinimum(0); + valueSlider->setMaximum(100); + valueSlider->setValue(floatToInt(param.value().getFloat())); + QFontMetrics fm(valueLE->font()); + QSize sz = fm.size(Qt::TextSingleLine, QString::number(0)); + valueLE->setValidator(new QDoubleValidator(param.min, param.max, numbdecimaldigit, valueLE)); + valueLE->setText(QString::number(param.value().getFloat())); + valueLE->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + + hlay = new QHBoxLayout(); + hlay->addWidget(valueLE); + hlay->addWidget(valueSlider); + widgets.push_back(valueLE); + widgets.push_back(valueSlider); + int maxlenghtplusdot = 8; // numbmaxvaluedigit + numbdecimaldigit + 1; + valueLE->setMaxLength(maxlenghtplusdot); + valueLE->setMaximumWidth(sz.width() * maxlenghtplusdot); + + connect(valueLE, SIGNAL(textChanged(const QString&)), this, SLOT(setValueFromTextBox())); + connect(valueSlider, SIGNAL(valueChanged(int)), this, SLOT(setValue(int))); + connect(this, SIGNAL(dialogParamChanged()), this, SLOT(setParameterChanged())); +} + +DynamicFloatWidget::~DynamicFloatWidget() +{ +} + +void DynamicFloatWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(hlay, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr DynamicFloatWidget::getWidgetValue() const +{ + return std::make_shared(valueLE->text().toFloat()); +} + +void DynamicFloatWidget::setWidgetValue(const Value& nv) +{ + valueLE->setText(QString::number(nv.getFloat())); +} + +float DynamicFloatWidget::getValue() +{ + return float(valueLE->text().toDouble()); +} + +void DynamicFloatWidget::setValue(int newVal) +{ + if (floatToInt(float(valueLE->text().toDouble())) != newVal) { + valueLE->setText(QString::number(intToFloat(newVal))); + } +} + +void DynamicFloatWidget::setValueFromTextBox() +{ + float newValLE = float(valueLE->text().toDouble()); + valueSlider->setValue(floatToInt(newValLE)); + emit dialogParamChanged(); +} + +void DynamicFloatWidget::setValue(float newVal) +{ + if (QString::number(intToFloat(newVal)) != valueLE->text()) + valueLE->setText(QString::number(intToFloat(newVal))); +} + +float DynamicFloatWidget::intToFloat(int val) +{ + return minVal + float(val) / 100.0f * (maxVal - minVal); +} +int DynamicFloatWidget::floatToInt(float val) +{ + return int(100.0f * (val - minVal) / (maxVal - minVal)); +} diff --git a/src/common_gui/rich_parameter/widgets/dynamic_float_widget.h b/src/common_gui/rich_parameter/widgets/dynamic_float_widget.h new file mode 100644 index 000000000..ae6caa253 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/dynamic_float_widget.h @@ -0,0 +1,63 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_DYNAMIC_FLOAT_WIDGET_H +#define MESHLAB_DYNAMIC_FLOAT_WIDGET_H + +#include "rich_parameter_widget.h" + +class DynamicFloatWidget : public RichParameterWidget +{ + Q_OBJECT + +public: + DynamicFloatWidget(QWidget* p, const RichDynamicFloat& param, const FloatValue& defaultValue); + ~DynamicFloatWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + + float getValue(); + +public slots: + void setValue(int newv); + void setValueFromTextBox(); + void setValue(float newValue); + +signals: + // void valueChanged(int mask); + void dialogParamChanged(); + +private: + QLineEdit* valueLE; + QSlider* valueSlider; + float minVal; + float maxVal; + QHBoxLayout* hlay; + + float intToFloat(int val); + int floatToInt(float val); +}; + +#endif // MESHLAB_DYNAMIC_FLOAT_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/enum_widget.cpp b/src/common_gui/rich_parameter/widgets/enum_widget.cpp new file mode 100644 index 000000000..8c5155674 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/enum_widget.cpp @@ -0,0 +1,43 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "enum_widget.h" + +EnumWidget::EnumWidget(QWidget* p, const RichEnum& param, const IntValue& defaultValue) : + ComboWidget(p, param, defaultValue, param.enumvalues, param.value().getInt()) +{ +} + +EnumWidget::~EnumWidget() +{ +} + +std::shared_ptr EnumWidget::getWidgetValue() const +{ + return std::make_shared(enumCombo->currentIndex()); +} + +void EnumWidget::setWidgetValue(const Value& nv) +{ + enumCombo->setCurrentIndex(nv.getInt()); +} diff --git a/src/common_gui/rich_parameter/widgets/enum_widget.h b/src/common_gui/rich_parameter/widgets/enum_widget.h new file mode 100644 index 000000000..65ebdb752 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/enum_widget.h @@ -0,0 +1,39 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_ENUM_WIDGET_H +#define MESHLAB_ENUM_WIDGET_H + +#include "combo_widget.h" + +class EnumWidget : public ComboWidget +{ +public: + EnumWidget(QWidget* p, const RichEnum& param, const IntValue& defaultValue); + ~EnumWidget();; + + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); +}; + +#endif // MESHLAB_ENUM_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/float_widget.cpp b/src/common_gui/rich_parameter/widgets/float_widget.cpp new file mode 100644 index 000000000..9bb6049ab --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/float_widget.cpp @@ -0,0 +1,44 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "float_widget.h" + +FloatWidget::FloatWidget(QWidget* p, const RichFloat& param, const FloatValue& defaultValue) : + LineEditWidget(p, param, defaultValue) +{ + lned->setText(QString::number(param.value().getFloat(), 'g', 3)); +} + +FloatWidget::~FloatWidget() +{ +} + +std::shared_ptr FloatWidget::getWidgetValue() const +{ + return std::make_shared(lned->text().toFloat()); +} + +void FloatWidget::setWidgetValue(const Value& nv) +{ + lned->setText(QString::number(nv.getFloat(), 'g', 3)); +} diff --git a/src/common_gui/rich_parameter/widgets/float_widget.h b/src/common_gui/rich_parameter/widgets/float_widget.h new file mode 100644 index 000000000..610f06385 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/float_widget.h @@ -0,0 +1,39 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_FLOAT_WIDGET_H +#define MESHLAB_FLOAT_WIDGET_H + +#include "line_edit_widget.h" + +class FloatWidget : public LineEditWidget +{ +public: + FloatWidget(QWidget* p, const RichFloat& param, const FloatValue& defaultValue); + ~FloatWidget(); + + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); +}; + +#endif // MESHLAB_FLOAT_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/int_widget.cpp b/src/common_gui/rich_parameter/widgets/int_widget.cpp new file mode 100644 index 000000000..280002313 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/int_widget.cpp @@ -0,0 +1,44 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "int_widget.h" + +IntWidget::IntWidget(QWidget* p, const RichInt& param, const IntValue& defaultValue) : + LineEditWidget(p, param, defaultValue) +{ + lned->setText(QString::number(param.value().getInt())); +} + +IntWidget::~IntWidget() +{ +} + +std::shared_ptr IntWidget::getWidgetValue() const +{ + return std::make_shared(lned->text().toInt()); +} + +void IntWidget::setWidgetValue(const Value& nv) +{ + lned->setText(QString::number(nv.getInt())); +} diff --git a/src/common_gui/rich_parameter/widgets/int_widget.h b/src/common_gui/rich_parameter/widgets/int_widget.h new file mode 100644 index 000000000..2434594e8 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/int_widget.h @@ -0,0 +1,39 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_INT_WIDGET_H +#define MESHLAB_INT_WIDGET_H + +#include "line_edit_widget.h" + +class IntWidget : public LineEditWidget +{ +public: + IntWidget(QWidget* p, const RichInt& param, const IntValue& defaultValue); + ~IntWidget(); + + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); +}; + +#endif // MESHLAB_INT_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/io_file_widget.cpp b/src/common_gui/rich_parameter/widgets/io_file_widget.cpp new file mode 100644 index 000000000..3f8af8aab --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/io_file_widget.cpp @@ -0,0 +1,76 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "io_file_widget.h" + +#include + +IOFileWidget::IOFileWidget( + QWidget* p, + const RichParameter& param, + const StringValue& defaultValue) : + RichParameterWidget(p, param, defaultValue) +{ + filename = new QLineEdit(this); + filename->setText(param.value().getString()); + browse = new QPushButton(this); + browse->setText("..."); + hlay = new QHBoxLayout(); + hlay->addWidget(filename, 2); + hlay->addWidget(browse); + widgets.push_back(filename); + widgets.push_back(browse); + + connect(browse, SIGNAL(clicked()), this, SLOT(selectFile())); + connect(this, SIGNAL(dialogParamChanged()), this, SLOT(setParameterChanged())); +} + +IOFileWidget::~IOFileWidget() +{ + delete filename; + delete browse; +} + +void IOFileWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(hlay, r, 1, Qt::AlignTop); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr IOFileWidget::getWidgetValue() const +{ + return std::make_shared(filename->text()); +} + +void IOFileWidget::setWidgetValue(const Value& nv) +{ + QString fle = nv.getString(); + updateFileName(fle); +} + +void IOFileWidget::updateFileName(const StringValue& file) +{ + filename->setText(file.getString()); +} diff --git a/src/common_gui/rich_parameter/widgets/io_file_widget.h b/src/common_gui/rich_parameter/widgets/io_file_widget.h new file mode 100644 index 000000000..8313fea94 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/io_file_widget.h @@ -0,0 +1,56 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_IO_FILE_WIDGET_H +#define MESHLAB_IO_FILE_WIDGET_H + +#include "rich_parameter_widget.h" + +class IOFileWidget : public RichParameterWidget +{ + Q_OBJECT + +protected: + IOFileWidget(QWidget* p, const RichParameter& param, const StringValue& defaultValue); + ~IOFileWidget(); + +public: + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + +protected slots: + virtual void selectFile() = 0; + +signals: + void dialogParamChanged(); + +protected: + void updateFileName(const StringValue& file); + + QLineEdit* filename; + QPushButton* browse; + QHBoxLayout* hlay; +}; + +#endif // MESHLAB_IO_FILE_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/line_edit_widget.cpp b/src/common_gui/rich_parameter/widgets/line_edit_widget.cpp new file mode 100644 index 000000000..ee9baaaf7 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/line_edit_widget.cpp @@ -0,0 +1,56 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "line_edit_widget.h" + +LineEditWidget::LineEditWidget(QWidget* p, const RichParameter& param, const Value& defaultValue) : + RichParameterWidget(p, param, defaultValue) +{ + lned = new QLineEdit(this); + + connect(lned, SIGNAL(editingFinished()), this, SLOT(changeChecker())); + connect(this, SIGNAL(lineEditChanged()), this, SLOT(setParameterChanged())); + lned->setAlignment(Qt::AlignLeft); + widgets.push_back(lned); +} + +LineEditWidget::~LineEditWidget() +{ +} + +void LineEditWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addWidget(lned, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +void LineEditWidget::changeChecker() +{ + if (lned->text() != this->lastVal) { + this->lastVal = lned->text(); + if (!this->lastVal.isEmpty()) + emit lineEditChanged(); + } +} diff --git a/src/common_gui/rich_parameter/widgets/line_edit_widget.h b/src/common_gui/rich_parameter/widgets/line_edit_widget.h new file mode 100644 index 000000000..f3f934b75 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/line_edit_widget.h @@ -0,0 +1,51 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_LINE_EDIT_WIDGET_H +#define MESHLAB_LINE_EDIT_WIDGET_H + +#include "rich_parameter_widget.h" + +class LineEditWidget : public RichParameterWidget +{ + Q_OBJECT + +public: + LineEditWidget(QWidget* p, const RichParameter& param, const Value& defaultValue); + ~LineEditWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const = 0; + virtual void setWidgetValue(const Value& nv) = 0; + +private slots: + void changeChecker(); +signals: + void lineEditChanged(); + +protected: + QLineEdit* lned; + QString lastVal; +}; + +#endif // MESHLAB_LINE_EDIT_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/matrix44_widget.cpp b/src/common_gui/rich_parameter/widgets/matrix44_widget.cpp new file mode 100644 index 000000000..46054d8dd --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/matrix44_widget.cpp @@ -0,0 +1,180 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "matrix44_widget.h" + +#include +#include + +Matrix44Widget::Matrix44Widget( + QWidget* p, + const RichMatrix44& param, + const Matrix44Value& defaultValue, + QWidget* gla) : + RichParameterWidget(p, param, defaultValue) +{ + valid = false; + m.SetIdentity(); + paramName = param.name(); + + vlay = new QVBoxLayout(); + lay44 = new QGridLayout(); + + for (int i = 0; i < 16; ++i) { + coordSB[i] = new QLineEdit(p); + QFont baseFont = coordSB[i]->font(); + if (baseFont.pixelSize() != -1) + baseFont.setPixelSize(baseFont.pixelSize() * 3 / 4); + else + baseFont.setPointSize(baseFont.pointSize() * 3 / 4); + coordSB[i]->setFont(baseFont); + coordSB[i]->setMinimumWidth(coordSB[i]->sizeHint().width() / 4); + coordSB[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + coordSB[i]->setValidator(new QDoubleValidator(p)); + lay44->addWidget(coordSB[i], i / 4, i % 4); + widgets.push_back(coordSB[i]); + connect( + coordSB[i], + SIGNAL(textChanged(const QString&)), + this, + SLOT(invalidateMatrix(const QString&))); + connect(coordSB[i], SIGNAL(editingFinished()), this, SLOT(setParameterChanged())); + } + this->setValue(paramName, param.value().getMatrix44()); + + QLabel* headerL = new QLabel("Matrix:", this); + vlay->addWidget(headerL, 0, Qt::AlignTop); + widgets.push_back(headerL); + + vlay->addLayout(lay44); + + QPushButton* getMatrixButton = new QPushButton("Read from current layer"); + vlay->addWidget(getMatrixButton); + widgets.push_back(getMatrixButton); + + QPushButton* pasteMatrixButton = new QPushButton("Paste from clipboard"); + vlay->addWidget(pasteMatrixButton); + widgets.push_back(pasteMatrixButton); + + // gridLay->addLayout(vlay,row,1,Qt::AlignTop); + + connect( + gla, SIGNAL(transmitMatrix(QString, Matrix44m)), this, SLOT(setValue(QString, Matrix44m))); + connect(getMatrixButton, SIGNAL(clicked()), this, SLOT(getMatrix())); + connect(pasteMatrixButton, SIGNAL(clicked()), this, SLOT(pasteMatrix())); + connect(this, SIGNAL(askMeshMatrix(QString)), gla, SLOT(sendMeshMatrix(QString))); +} + +Matrix44Widget::~Matrix44Widget() +{ +} + +void Matrix44Widget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(vlay, r, 1, Qt::AlignTop); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr Matrix44Widget::getWidgetValue() const +{ + if (!valid) { + Matrix44m tempM; + for (unsigned int i = 0; i < 16; ++i) + tempM[i / 4][i % 4] = coordSB[i]->text().toFloat(); + return std::make_shared(tempM); + } + else { + return std::make_shared(m); + } +} + +void Matrix44Widget::setWidgetValue(const Value& nv) +{ + valid = true; + m = nv.getMatrix44(); + for (unsigned int ii = 0; ii < 16; ++ii) + coordSB[ii]->setText(QString::number(nv.getMatrix44()[ii / 4][ii % 4], 'g', 3)); +} + +Matrix44m Matrix44Widget::getValue() +{ + if (!valid) { + Scalarm val[16]; + for (unsigned int i = 0; i < 16; ++i) + val[i] = coordSB[i]->text().toFloat(); + return Matrix44m(val); + } + return m; +} + +void Matrix44Widget::setValue(QString name, Matrix44m newVal) +{ + if (name == paramName) { + for (int i = 0; i < 16; ++i) + coordSB[i]->setText(QString::number(newVal[i / 4][i % 4], 'g', 4)); + valid = true; + m = newVal; + } +} + +void Matrix44Widget::getMatrix() +{ + emit askMeshMatrix(QString("TransformMatrix")); +} + +void Matrix44Widget::pasteMatrix() +{ + QClipboard* clipboard = QApplication::clipboard(); + QString shotString = clipboard->text().trimmed(); + if (shotString.contains(' ')) { + QStringList list1 = shotString.split(" "); + if (list1.size() != 16) + return; + valid = false; + int id = 0; + for (QStringList::iterator i = list1.begin(); i != list1.end(); ++i, ++id) { + bool ok = true; + (*i).toFloat(&ok); + if (!ok) + return; + } + id = 0; + for (QStringList::iterator i = list1.begin(); i != list1.end(); ++i, ++id) { + coordSB[id]->setText(*i); + } + } + else { + QByteArray value = QByteArray::fromBase64(shotString.toLocal8Bit()); + memcpy(m.V(), value.data(), sizeof(Matrix44m::ScalarType) * 16); + int id = 0; + for (int i = 0; i < 16; ++i, ++id) + coordSB[id]->setText(QString::number(m.V()[i])); + } +} + +void Matrix44Widget::invalidateMatrix(const QString& /*s*/) +{ + valid = false; +} diff --git a/src/common_gui/rich_parameter/widgets/matrix44_widget.h b/src/common_gui/rich_parameter/widgets/matrix44_widget.h new file mode 100644 index 000000000..6d363a6b5 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/matrix44_widget.h @@ -0,0 +1,65 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_MATRIX44_WIDGET_H +#define MESHLAB_MATRIX44_WIDGET_H + +#include "rich_parameter_widget.h" + +class Matrix44Widget : public RichParameterWidget +{ + Q_OBJECT + +public: + Matrix44Widget( + QWidget* p, + const RichMatrix44& param, + const Matrix44Value& defaultValue, + QWidget* gla); + ~Matrix44Widget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + + Matrix44m getValue(); + +public slots: + void setValue(QString name, Matrix44m val); + void getMatrix(); + void pasteMatrix(); + void invalidateMatrix(const QString& s); +signals: + void askMeshMatrix(QString); + +private: + QString paramName; + QLineEdit* coordSB[16]; + QPushButton* getPoint3Button; + QGridLayout* lay44; + QVBoxLayout* vlay; + Matrix44m m; + bool valid; +}; + +#endif // MESHLAB_MATRIX44_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/mesh_widget.cpp b/src/common_gui/rich_parameter/widgets/mesh_widget.cpp new file mode 100644 index 000000000..2f154dd25 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/mesh_widget.cpp @@ -0,0 +1,73 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "mesh_widget.h" + +#include + +MeshWidget::MeshWidget(QWidget* p, const RichMesh& param, const IntValue& defaultValue) : + ComboWidget(p, param, defaultValue) +{ + md = param.meshdoc; + + QStringList meshNames; + + if (md) { + int currentmeshindex = -1; + unsigned int i = 0; + for (const MeshModel& mm : md->meshIterator()) { + QString shortName = mm.label(); + meshNames.push_back(shortName); + if (mm.id() == (unsigned int) param.value().getInt()) { + currentmeshindex = i; + } + ++i; + } + + init(currentmeshindex, meshNames); + } +} + +MeshWidget::~MeshWidget() +{ +} + +std::shared_ptr MeshWidget::getWidgetValue() const +{ + auto it = md->meshBegin(); + std::advance(it, enumCombo->currentIndex()); + return std::make_shared((*it).id()); +} + +void MeshWidget::setWidgetValue(const Value& nv) +{ + int meshindex = -1; + unsigned int i = 0; + for (const MeshModel& mm : md->meshIterator()) { + if (mm.id() == (unsigned int) nv.getInt()) { + meshindex = i; + } + ++i; + } + enumCombo->setCurrentIndex(meshindex); +} diff --git a/src/common_gui/rich_parameter/widgets/mesh_widget.h b/src/common_gui/rich_parameter/widgets/mesh_widget.h new file mode 100644 index 000000000..32fe4f287 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/mesh_widget.h @@ -0,0 +1,43 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_MESH_WIDGET_H +#define MESHLAB_MESH_WIDGET_H + +#include "combo_widget.h" + +class MeshWidget : public ComboWidget +{ +public: + MeshWidget(QWidget* p, const RichMesh& param, const IntValue& defaultValue); + ~MeshWidget(); + ; + + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + +private: + const MeshDocument* md; +}; + +#endif // MESHLAB_MESH_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/open_file_widget.cpp b/src/common_gui/rich_parameter/widgets/open_file_widget.cpp new file mode 100644 index 000000000..eade04c6a --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/open_file_widget.cpp @@ -0,0 +1,50 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "open_file_widget.h" + +#include + +OpenFileWidget::OpenFileWidget( + QWidget* p, + const RichFileOpen& param, + const StringValue& defaultValue) : + IOFileWidget(p, param, defaultValue), extensions(param.exts.join(";;")) +{ +} + +OpenFileWidget::~OpenFileWidget() +{ +} + +void OpenFileWidget::selectFile() +{ + QString path = QDir::homePath(); + if (!filename->text().isEmpty()) + path = filename->text(); + QString fl = QFileDialog::getOpenFileName(this, tr("Open"), path, extensions); + if (!fl.isEmpty()) { + updateFileName(fl); + emit dialogParamChanged(); + } +} diff --git a/src/common_gui/rich_parameter/widgets/open_file_widget.h b/src/common_gui/rich_parameter/widgets/open_file_widget.h new file mode 100644 index 000000000..1d979d573 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/open_file_widget.h @@ -0,0 +1,43 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_OPEN_FILE_WIDGET_H +#define MESHLAB_OPEN_FILE_WIDGET_H + +#include "io_file_widget.h" + +class OpenFileWidget : public IOFileWidget +{ + Q_OBJECT +public: + OpenFileWidget(QWidget* p, const RichFileOpen& param, const StringValue& defaultValue); + ~OpenFileWidget(); + +protected slots: + void selectFile(); + +private: + QString extensions; +}; + +#endif // MESHLAB_OPEN_FILE_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/percentage_widget.cpp b/src/common_gui/rich_parameter/widgets/percentage_widget.cpp new file mode 100644 index 000000000..5bc8b8d31 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/percentage_widget.cpp @@ -0,0 +1,121 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "percentage_widget.h" + +PercentageWidget::PercentageWidget( + QWidget* p, + const RichPercentage& param, + const FloatValue& defaultValue) : + RichParameterWidget(p, param, defaultValue), m_min(param.min), m_max(param.max) +{ + descriptionLabel->setText(descriptionLabel->text() + " (abs and %)"); + + absSB = new QDoubleSpinBox(this); + percSB = new QDoubleSpinBox(this); + + absSB->setMinimum(m_min - (m_max - m_min)); + absSB->setMaximum(m_max * 2); + absSB->setAlignment(Qt::AlignRight); + + int decimals = 7 - ceil(log10(fabs(m_max - m_min))); + absSB->setDecimals(decimals); + absSB->setSingleStep((m_max - m_min) / 100.0); + float initVal = param.value().getFloat(); + absSB->setValue(initVal); + absSB->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + + percSB->setMinimum(-200); + percSB->setMaximum(200); + percSB->setAlignment(Qt::AlignRight); + percSB->setSingleStep(0.5); + percSB->setValue((100 * (initVal - m_min)) / (m_max - m_min)); + percSB->setDecimals(3); + percSB->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + QLabel* absLab = new QLabel(" world unit"); + QLabel* percLab = new QLabel( + " perc on" + QString("(%1 .. %2)").arg(m_min).arg(m_max) + ""); + + vlay = new QGridLayout(); + vlay->addWidget(absLab, 0, 0, Qt::AlignHCenter); + vlay->addWidget(percLab, 0, 1, Qt::AlignHCenter); + + vlay->addWidget(absSB, 1, 0, Qt::AlignTop); + vlay->addWidget(percSB, 1, 1, Qt::AlignTop); + + widgets.push_back(absLab); + widgets.push_back(percLab); + widgets.push_back(absSB); + widgets.push_back(percSB); + + connect(absSB, SIGNAL(valueChanged(double)), this, SLOT(on_absSB_valueChanged(double))); + connect(percSB, SIGNAL(valueChanged(double)), this, SLOT(on_percSB_valueChanged(double))); + connect(this, SIGNAL(dialogParamChanged()), this, SLOT(setParameterChanged())); +} + +PercentageWidget::~PercentageWidget() +{ + delete absSB; + delete percSB; +} + +void PercentageWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(vlay, r, 1, Qt::AlignTop); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr PercentageWidget::getWidgetValue() const +{ + return std::make_shared(absSB->value()); +} + +void PercentageWidget::setWidgetValue(const Value& nv) +{ + setValue(nv.getFloat(), m_min, m_max); +} + +void PercentageWidget::setValue(float val, float minV, float maxV) +{ + absSB->setValue(val); + m_min = minV; + m_max = maxV; +} + +void PercentageWidget::on_absSB_valueChanged(double newv) +{ + disconnect(percSB, SIGNAL(valueChanged(double)), this, SLOT(on_percSB_valueChanged(double))); + percSB->setValue((100 * (newv - m_min)) / (m_max - m_min)); + connect(percSB, SIGNAL(valueChanged(double)), this, SLOT(on_percSB_valueChanged(double))); + emit dialogParamChanged(); +} + +void PercentageWidget::on_percSB_valueChanged(double newv) +{ + disconnect(absSB, SIGNAL(valueChanged(double)), this, SLOT(on_absSB_valueChanged(double))); + absSB->setValue((m_max - m_min) * 0.01 * newv + m_min); + connect(absSB, SIGNAL(valueChanged(double)), this, SLOT(on_absSB_valueChanged(double))); + emit dialogParamChanged(); +} diff --git a/src/common_gui/rich_parameter/widgets/percentage_widget.h b/src/common_gui/rich_parameter/widgets/percentage_widget.h new file mode 100644 index 000000000..89d13f6b5 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/percentage_widget.h @@ -0,0 +1,58 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_PERCENTAGE_WIDGET_H +#define MESHLAB_PERCENTAGE_WIDGET_H + +#include "rich_parameter_widget.h" + +class PercentageWidget : public RichParameterWidget +{ + Q_OBJECT +public: + PercentageWidget(QWidget* p, const RichPercentage& param, const FloatValue& defaultValue); + ~PercentageWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + +private: + void setValue(float val, float minV, float maxV); + +public slots: + + void on_absSB_valueChanged(double newv); + void on_percSB_valueChanged(double newv); +signals: + void dialogParamChanged(); + +protected: + QDoubleSpinBox* absSB; + QDoubleSpinBox* percSB; + float m_min; + float m_max; + QGridLayout* vlay; +}; + +#endif // MESHLAB_PERCENTAGE_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/point3_widget.cpp b/src/common_gui/rich_parameter/widgets/point3_widget.cpp new file mode 100644 index 000000000..2e36c5432 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/point3_widget.cpp @@ -0,0 +1,119 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "point3_widget.h" + +Point3Widget::Point3Widget( + QWidget* p, + const RichParameter& param, + const Point3Value& defaultValue, + QWidget* gla) : + RichParameterWidget(p, param, defaultValue) +{ + assert(param.value().isPoint3()); + + paramName = param.name(); + + vlay = new QHBoxLayout(); + vlay->setSpacing(0); + const Point3Value& p3v = param.value().getPoint3(); + for (unsigned int i = 0; i < 3; ++i) { + coordSB[i] = new QLineEdit(this); + QFont baseFont = coordSB[i]->font(); + if (baseFont.pixelSize() != -1) + baseFont.setPixelSize(baseFont.pixelSize() * 3 / 4); + else + baseFont.setPointSize(baseFont.pointSize() * 3 / 4); + coordSB[i]->setFont(baseFont); + coordSB[i]->setMinimumWidth(coordSB[i]->sizeHint().width() / 4); + coordSB[i]->setValidator(new QDoubleValidator()); + coordSB[i]->setAlignment(Qt::AlignRight); + coordSB[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + vlay->addWidget(coordSB[i]); + widgets.push_back(coordSB[i]); + } + setValue(paramName, param.value().getPoint3()); + // connects must be made AFTER setValue + for (unsigned int i = 0; i < 3 ; i++) { + connect(coordSB[i], SIGNAL(textChanged(QString)), this, SLOT(setParameterChanged())); + } + // if we have a connection to the current glarea we can setup the additional + // button for getting the current view direction. + if (gla) { + getPoint3Combo = new QComboBox(this); + getPoint3Combo->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + vlay->addWidget(getPoint3Combo); + widgets.push_back(getPoint3Combo); + + getPoint3Button = new QPushButton("Get", this); + getPoint3Button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + vlay->addWidget(getPoint3Button); + widgets.push_back(getPoint3Button); + } +} + +Point3Widget::~Point3Widget() +{ + this->disconnect(); +} + +void Point3Widget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(vlay, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr Point3Widget::getWidgetValue() const +{ + return std::make_shared(Point3m( + coordSB[0]->text().toFloat(), coordSB[1]->text().toFloat(), coordSB[2]->text().toFloat())); +} + +void Point3Widget::setWidgetValue(const Value& nv) +{ + for (unsigned int ii = 0; ii < 3; ++ii) + coordSB[ii]->setText(QString::number(nv.getPoint3()[ii], 'g', 3)); +} + +vcg::Point3f Point3Widget::getValue() +{ + return vcg::Point3f( + coordSB[0]->text().toFloat(), coordSB[1]->text().toFloat(), coordSB[2]->text().toFloat()); +} + +void Point3Widget::setValue(QString name, Point3m newVal) +{ + if (name == paramName) { + for (int i = 0; i < 3; ++i) + coordSB[i]->setText(QString::number(newVal[i], 'g', 4)); + } +} + +void Point3Widget::setShotValue(QString name, Shotm newValShot) +{ + vcg::Point3f p = newValShot.GetViewPoint(); + setValue(name, p); +} diff --git a/src/common_gui/rich_parameter/widgets/point3_widget.h b/src/common_gui/rich_parameter/widgets/point3_widget.h new file mode 100644 index 000000000..b35ac1ed8 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/point3_widget.h @@ -0,0 +1,58 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_POINT3_WIDGET_H +#define MESHLAB_POINT3_WIDGET_H + +#include "rich_parameter_widget.h" + +class Point3Widget : public RichParameterWidget +{ + Q_OBJECT +public: + Point3Widget( + QWidget* p, + const RichParameter& rpf, + const Point3Value& defaultValue, + QWidget* gla); + ~Point3Widget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + + vcg::Point3f getValue(); + +public slots: + void setValue(QString name, Point3m val); + void setShotValue(QString name, Shotm val); + +protected: + QString paramName; + QLineEdit* coordSB[3]; + QComboBox* getPoint3Combo; + QPushButton* getPoint3Button; + QHBoxLayout* vlay; +}; + +#endif // MESHLAB_POINT3_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/position_widget.cpp b/src/common_gui/rich_parameter/widgets/position_widget.cpp new file mode 100644 index 000000000..93ff03324 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/position_widget.cpp @@ -0,0 +1,85 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "position_widget.h" + +PositionWidget::PositionWidget( + QWidget* p, + const RichPosition& param, + const Point3Value& defaultValue, + QWidget* gla) : + Point3Widget(p, param, defaultValue, gla) +{ + // if we have a connection to the current glarea we can setup the additional + // button for getting the current view direction. + if (gla) { + QStringList names; + names << "View Pos."; + names << "Surf. Pos."; + names << "Raster Camera Pos."; + names << "Trackball Center"; + + getPoint3Combo->addItems(names); + + connect( + gla, + SIGNAL(transmitSurfacePos(QString, Point3m)), + this, + SLOT(setValue(QString, Point3m))); + connect( + gla, + SIGNAL(transmitCameraPos(QString, Point3m)), + this, + SLOT(setValue(QString, Point3m))); + connect( + gla, SIGNAL(transmitShot(QString, Shotm)), this, SLOT(setShotValue(QString, Shotm))); + connect( + gla, + SIGNAL(transmitTrackballPos(QString, Point3m)), + this, + SLOT(setValue(QString, Point3m))); + connect(this, SIGNAL(askViewPos(QString)), gla, SLOT(sendViewerShot(QString))); + connect(this, SIGNAL(askSurfacePos(QString)), gla, SLOT(sendSurfacePos(QString))); + connect(this, SIGNAL(askCameraPos(QString)), gla, SLOT(sendRasterShot(QString))); + connect(this, SIGNAL(askTrackballPos(QString)), gla, SLOT(sendTrackballPos(QString))); + + connect(getPoint3Button, SIGNAL(clicked()), this, SLOT(getPoint())); + } +} + +PositionWidget::~PositionWidget() +{ + this->disconnect(); +} + +void PositionWidget::getPoint() +{ + int index = getPoint3Combo->currentIndex(); + switch (index) { + case 0: emit askViewPos(paramName); break; + case 1: emit askSurfacePos(paramName); break; + case 2: emit askCameraPos(paramName); break; + case 3: emit askTrackballPos(paramName); break; + default: assert(0); + } +} diff --git a/src/common_gui/rich_parameter/widgets/position_widget.h b/src/common_gui/rich_parameter/widgets/position_widget.h new file mode 100644 index 000000000..8e75ff845 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/position_widget.h @@ -0,0 +1,50 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_POSITION_WIDGET_H +#define MESHLAB_POSITION_WIDGET_H + +#include "point3_widget.h" + +class PositionWidget : public Point3Widget +{ + Q_OBJECT +public: + PositionWidget( + QWidget* p, + const RichPosition& param, + const Point3Value& defaultValue, + QWidget* gla); + ~PositionWidget(); + +public slots: + void getPoint(); + +signals: + void askViewPos(QString); + void askSurfacePos(QString); + void askCameraPos(QString); + void askTrackballPos(QString); +}; + +#endif // MESHLAB_POSITION_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/rich_parameter_widget.cpp b/src/common_gui/rich_parameter/widgets/rich_parameter_widget.cpp new file mode 100644 index 000000000..49bec051d --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/rich_parameter_widget.cpp @@ -0,0 +1,93 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_parameter_widget.h" + +#include "../rich_parameter_list_frame.h" + +RichParameterWidget::RichParameterWidget( + QWidget* p, + const RichParameter& param, + const Value& defaultValue) : + QWidget(p), defaultValue(defaultValue.clone()), visible(true), helpVisible(false) +{ + descriptionLabel = new ClickableLabel(param.fieldDescription(), this); + descriptionLabel->setToolTip(param.toolTip()); + descriptionLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + + helpLabel = new QLabel("" + param.toolTip() + "", this); + helpLabel->setTextFormat(Qt::RichText); + helpLabel->setWordWrap(true); + helpLabel->setVisible(false); + helpLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + helpLabel->setMinimumWidth(250); +} + +RichParameterWidget::~RichParameterWidget() +{ + delete defaultValue; +} + +void RichParameterWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != NULL) { + lay->addWidget(descriptionLabel, r, 0, 1, 1, Qt::AlignRight); + lay->addWidget(helpLabel, r, 2); + } +} + +void RichParameterWidget::setVisible(bool b) +{ + visible = b; + descriptionLabel->setVisible(b); + for (QWidget* w : widgets) + w->setVisible(b); + if (b && helpVisible) + helpLabel->setVisible(true); + else if (!b) + helpLabel->setVisible(false); + QWidget::setVisible(b); +} + +void RichParameterWidget::resetWidgetToDefaultValue() +{ + setWidgetValue(*defaultValue); + parameterValueChanged = false; +} + +void RichParameterWidget::setHelpVisible(bool b) +{ + helpVisible = b; + helpLabel->setVisible(visible && helpVisible); +} + +bool RichParameterWidget::hasBeenChanged() const +{ + return parameterValueChanged; +} + +void RichParameterWidget::setParameterChanged() +{ + parameterValueChanged = true; + emit parameterChanged(); +} diff --git a/src/common_gui/rich_parameter/widgets/rich_parameter_widget.h b/src/common_gui/rich_parameter/widgets/rich_parameter_widget.h new file mode 100644 index 000000000..310b3f9c2 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/rich_parameter_widget.h @@ -0,0 +1,82 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_PARAMETER_WIDGET_H +#define MESHLAB_RICH_PARAMETER_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "../../gui_utils/clickable_label.h" + +class RichParameterWidget : public QWidget +{ + Q_OBJECT +public: + RichParameterWidget(QWidget* p, const RichParameter& param, const Value& defaultValue); + virtual ~RichParameterWidget(); + + virtual std::shared_ptr getWidgetValue() const = 0; + virtual void setWidgetValue(const Value& nv) = 0; + + virtual void addWidgetToGridLayout(QGridLayout* lay, const int r) = 0; + + void setVisible(bool b); + + void resetWidgetToDefaultValue(); + void setHelpVisible(bool b); + + bool hasBeenChanged() const; + +signals: + void parameterChanged(); + +protected slots: + void setParameterChanged(); + +protected: + ClickableLabel* descriptionLabel; + QLabel* helpLabel; + std::vector widgets; // will contain all the other widgets of this widget + + Value* defaultValue; + + bool parameterValueChanged = false; + + bool visible; + bool helpVisible; +}; + +#endif // MESHLAB_RICH_PARAMETER_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/rich_parameter_widgets.h b/src/common_gui/rich_parameter/widgets/rich_parameter_widgets.h new file mode 100644 index 000000000..6f1e0fc10 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/rich_parameter_widgets.h @@ -0,0 +1,43 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_PARAMETER_WIDGETS_H +#define MESHLAB_RICH_PARAMETER_WIDGETS_H + +#include "bool_widget.h" +#include "color_widget.h" +#include "direction_widget.h" +#include "dynamic_float_widget.h" +#include "enum_widget.h" +#include "float_widget.h" +#include "int_widget.h" +#include "matrix44_widget.h" +#include "mesh_widget.h" +#include "open_file_widget.h" +#include "percentage_widget.h" +#include "position_widget.h" +#include "save_file_widget.h" +#include "shot_widget.h" +#include "string_widget.h" + +#endif // MESHLAB_RICH_PARAMETER_WIDGETS_H diff --git a/src/common_gui/rich_parameter/widgets/save_file_widget.cpp b/src/common_gui/rich_parameter/widgets/save_file_widget.cpp new file mode 100644 index 000000000..7f3ebec33 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/save_file_widget.cpp @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "save_file_widget.h" + +#include + +SaveFileWidget::SaveFileWidget( + QWidget* p, + const RichFileSave& param, + const StringValue& defaultValue) : + IOFileWidget(p, param, defaultValue), extension(param.ext) +{ +} + +SaveFileWidget::~SaveFileWidget() +{ +} + +void SaveFileWidget::selectFile() +{ + QString fl = QFileDialog::getSaveFileName(this, tr("Save"), filename->text(), extension); + if (!fl.isEmpty()) { + updateFileName(fl); + emit dialogParamChanged(); + } +} diff --git a/src/common_gui/rich_parameter/widgets/save_file_widget.h b/src/common_gui/rich_parameter/widgets/save_file_widget.h new file mode 100644 index 000000000..fc2b58267 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/save_file_widget.h @@ -0,0 +1,43 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_SAVE_FILE_WIDGET_H +#define MESHLAB_SAVE_FILE_WIDGET_H + +#include "io_file_widget.h" + +class SaveFileWidget : public IOFileWidget +{ + Q_OBJECT +public: + SaveFileWidget(QWidget* p, const RichFileSave& param, const StringValue& defaultValue); + ~SaveFileWidget(); + +protected slots: + void selectFile(); + +private: + QString extension; +}; + +#endif // MESHLAB_SAVE_FILE_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/shot_widget.cpp b/src/common_gui/rich_parameter/widgets/shot_widget.cpp new file mode 100644 index 000000000..a4d53c31e --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/shot_widget.cpp @@ -0,0 +1,128 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "shot_widget.h" + +#include + +ShotWidget::ShotWidget( + QWidget* p, + const RichShot& param, + const ShotValue& defaultValue, + QWidget* gla) : + RichParameterWidget(p, param, defaultValue) +{ + paramName = param.name(); + + hlay = new QHBoxLayout(); + + this->setShotValue(paramName, param.value().getShot()); + // if we have a connection to the current glarea we can setup the additional + // button for getting the current view direction. + if (gla) { + getShotButton = new QPushButton("Get shot", this); + getShotButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + hlay->addWidget(getShotButton); + widgets.push_back(getShotButton); + + QStringList names; + names << "Current Trackball"; + names << "Current Mesh"; + names << "Current Raster"; + names << "From File"; + + getShotCombo = new QComboBox(this); + getShotCombo->addItems(names); + hlay->addWidget(getShotCombo); + widgets.push_back(getShotCombo); + connect(getShotCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(getShot())); + connect(getShotButton, SIGNAL(clicked()), this, SLOT(getShot())); + connect( + gla, SIGNAL(transmitShot(QString, Shotm)), this, SLOT(setShotValue(QString, Shotm))); + connect(this, SIGNAL(askViewerShot(QString)), gla, SLOT(sendViewerShot(QString))); + connect(this, SIGNAL(askMeshShot(QString)), gla, SLOT(sendMeshShot(QString))); + connect(this, SIGNAL(askRasterShot(QString)), gla, SLOT(sendRasterShot(QString))); + } +} + +ShotWidget::~ShotWidget() +{ +} + +void ShotWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(hlay, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr ShotWidget::getWidgetValue() const +{ + return std::make_shared(curShot); +} + +void ShotWidget::setWidgetValue(const Value& nv) +{ + curShot = nv.getShot(); +} + +Shotm ShotWidget::getValue() +{ + return curShot; +} + +void ShotWidget::getShot() +{ + int index = getShotCombo->currentIndex(); + switch (index) { + case 0: emit askViewerShot(paramName); break; + case 1: emit askMeshShot(paramName); break; + case 2: emit askRasterShot(paramName); break; + case 3: { + QString filename = QFileDialog::getOpenFileName( + this, tr("Load xml camera"), "./", tr("Xml Files (*.xml)")); + QFile qf(filename); + QFileInfo qfInfo(filename); + + if (!qf.open(QIODevice::ReadOnly)) + return; + + QDomDocument doc("XmlDocument"); // It represents the XML document + if (!doc.setContent(&qf)) + return; + qf.close(); + + QString type = doc.doctype().name(); + + } break; + default: assert(0); + } +} + +void ShotWidget::setShotValue(QString name, Shotm newVal) +{ + if (name == paramName) { + curShot = newVal; + } +} diff --git a/src/common_gui/rich_parameter/widgets/shot_widget.h b/src/common_gui/rich_parameter/widgets/shot_widget.h new file mode 100644 index 000000000..d8e3f7e15 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/shot_widget.h @@ -0,0 +1,60 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_SHOT_WIDGET_H +#define MESHLAB_SHOT_WIDGET_H + +#include "rich_parameter_widget.h" + +class ShotWidget : public RichParameterWidget +{ + Q_OBJECT + +public: + ShotWidget(QWidget* p, const RichShot& param, const ShotValue& defaultValue, QWidget* gla); + ~ShotWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + + Shotm getValue(); + +public slots: + void getShot(); + void setShotValue(QString name, Shotm val); +signals: + void askRasterShot(QString); + void askMeshShot(QString); + void askViewerShot(QString); + +private: + QString paramName; + Shotm curShot; + QLineEdit* shotLE; + QPushButton* getShotButton; + QComboBox* getShotCombo; + QHBoxLayout* hlay; +}; + +#endif // MESHLAB_SHOT_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/string_widget.cpp b/src/common_gui/rich_parameter/widgets/string_widget.cpp new file mode 100644 index 000000000..7d32dc21a --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/string_widget.cpp @@ -0,0 +1,44 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "string_widget.h" + +StringWidget::StringWidget(QWidget* p, const RichString& param, const StringValue& defaultValue) : + LineEditWidget(p, param, defaultValue) +{ + lned->setText(param.value().getString()); +} + +StringWidget::~StringWidget() +{ +} + +std::shared_ptr StringWidget::getWidgetValue() const +{ + return std::make_shared(lned->text()); +} + +void StringWidget::setWidgetValue(const Value& nv) +{ + lned->setText(nv.getString()); +} diff --git a/src/common_gui/rich_parameter/widgets/string_widget.h b/src/common_gui/rich_parameter/widgets/string_widget.h new file mode 100644 index 000000000..981bc7629 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/string_widget.h @@ -0,0 +1,39 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_STRING_WIDGET_H +#define MESHLAB_STRING_WIDGET_H + +#include "line_edit_widget.h" + +class StringWidget : public LineEditWidget +{ +public: + StringWidget(QWidget* p, const RichString& param, const StringValue& defaultValue); + ~StringWidget(); + + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); +}; + +#endif // MESHLAB_STRING_WIDGET_H diff --git a/src/external.pro b/src/external.pro deleted file mode 100644 index c8c453b31..000000000 --- a/src/external.pro +++ /dev/null @@ -1,9 +0,0 @@ -#this project file builds just the external libraries - -TEMPLATE = subdirs - -message("MeshLab External") -message("DISTRIB_DIRECTORY: "$$MESHLAB_DISTRIB_DIRECTORY) - -SUBDIRS = \ - external diff --git a/src/external/CMakeLists.txt b/src/external/CMakeLists.txt index fe3e0c10c..16f840bc5 100644 --- a/src/external/CMakeLists.txt +++ b/src/external/CMakeLists.txt @@ -2,10 +2,86 @@ # Copyright 2019, 2020, Visual Computing Lab, ISTI - Italian National Research Council # SPDX-License-Identifier: BSL-1.0 -# GLEW - required -include(${EXTERNAL_DIR}/glew.cmake) +option( + MESHLAB_ALLOW_OPTIONAL_EXTERNAL_LIBRARIES + "Allow to use/build optional external libraries" + ON) -if(NOT BUILD_MINI) - message(STATUS "Searching for optional components") - include(${EXTERNAL_DIR}/external.cmake) +option( + MESHLAB_BUILD_EXTERNAL_SOURCES_WITHOUT_WARNINGS + "Should warnings be disabled on external libraries code?" + ON) + +set(MESHLAB_EXTERNAL_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/downloads") +set(MESHLAB_EXTERNAL_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(MESHLAB_EXTERNAL_DOWNLOAD_DIR "${MESHLAB_EXTERNAL_DIR}/downloads") + +add_library(external-disable-warnings INTERFACE) +if(MESHLAB_BUILD_EXTERNAL_SOURCES_WITHOUT_WARNINGS) + if(MSVC) + # TODO + elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + target_compile_options(external-disable-warnings INTERFACE -w) + endif() +endif() + +## REQUIRED EXTERNAL LIBS ## + +# GLEW - required +include(${CMAKE_CURRENT_SOURCE_DIR}/glew.cmake) + +# EasyExif - required +include(${CMAKE_CURRENT_SOURCE_DIR}/easyexif.cmake) + + +## OPTIONAL EXTERNAL LIBS ## + +if ((NOT MESHLAB_BUILD_MINI) AND MESHLAB_ALLOW_OPTIONAL_EXTERNAL_LIBRARIES) + + message(STATUS "Searching for optional components") + + # boost - optional for filter_mesh_booleans + include(${CMAKE_CURRENT_SOURCE_DIR}/boost.cmake) + + # cgal - optional for filter_mesh_booleans + include(${CMAKE_CURRENT_SOURCE_DIR}/cgal.cmake) + + # levmar - optional, for several plugins + include(${CMAKE_CURRENT_SOURCE_DIR}/levmar.cmake) + + # lib3ds - optional, for io_3ds + include(${CMAKE_CURRENT_SOURCE_DIR}/lib3ds.cmake) + + # libigl - optional for filter_mesh_booleans + include(${CMAKE_CURRENT_SOURCE_DIR}/libigl.cmake) + + # muparser - optional, for filter_func + include(${CMAKE_CURRENT_SOURCE_DIR}/muparser.cmake) + + # nexus - optional. for io_nxs + include(${CMAKE_CURRENT_SOURCE_DIR}/nexus.cmake) + + # newuoa - optional and header-only, for several plugins including all that use levmar + include(${CMAKE_CURRENT_SOURCE_DIR}/newuoa.cmake) + + # OpenCTM - optional, for io_ctm + include(${CMAKE_CURRENT_SOURCE_DIR}/openctm.cmake) + + # qhull - optional, for filter_qhull + include(${CMAKE_CURRENT_SOURCE_DIR}/qhull.cmake) + + # structure-synth - optional, for filter_ssynth + include(${CMAKE_CURRENT_SOURCE_DIR}/ssynth.cmake) + + # tiny glTF - optional, for io_gltf + include(${CMAKE_CURRENT_SOURCE_DIR}/tinygltf.cmake) + + # u3d - optional, for io_u3d + include(${CMAKE_CURRENT_SOURCE_DIR}/u3d.cmake) + + # xerces library - optional, needed by libe57 + include(${CMAKE_CURRENT_SOURCE_DIR}/xerces.cmake) + + # libe57Format - optional, for io_e57 + include(${CMAKE_CURRENT_SOURCE_DIR}/e57.cmake) endif() diff --git a/src/external/OpenCTM-1.0.3/COMPILING.txt b/src/external/OpenCTM-1.0.3/COMPILING.txt deleted file mode 100644 index 065e932fc..000000000 --- a/src/external/OpenCTM-1.0.3/COMPILING.txt +++ /dev/null @@ -1,100 +0,0 @@ -1. PREREQUISITES -================ - -In order to compile the OpenCTM shared library, all you need is a supported -compiler and it should compile right out of the box. - -In order to compile the entire OpenCTM package, including documentation and the -tools, there are some extra dependencies: - -- To build all the tools, you need GLUT, and for Un*x/X11 you also need - GTK+ 2.0 (Ubuntu: sudo apt-get install libgtk2.0-dev). - -- To build the documentation you need Doxygen (www.doxygen.org), a full - LaTeX installation (see TeX Live - http://www.tug.org/texlive/), and Groff - (Windows: http://gnuwin32.sourceforge.net/packages/groff.htm, - Mac OS X: preinstalled, Ubuntu: sudo apt-get install groff). - - -2. COMPILING -============ - -There are a few makefiles for different systems and compilers. Just pick the -one that fits your system, and run "make" on the corresponding file. Here are -a few specific instructions: - - -2.1 Windows, MinGW32 --------------------- - -mingw32-make -f Makefile.mingw - - -2.2 Windows, MS Visual Studio (Express) 2008 --------------------------------------------- - -nmake /f Makefile.msvc - - -2.3 Mac OS X ------------- - -make -f Makefile.macosx - - -2.4 Linux ---------- - -make -f Makefile.linux - - -2.5 OpenSolaris ---------------- - -gmake -f Makefile.linux - - -3. BUILD TARGETS -================ - -By default, the OpenCTM shared library and the OpenCTM tools are compiled when -make is run. To select what is built, use one of the following build targets -(just append it to the end of the make command line): - - openctm (the shared library) - toolset (the tools) - documentation (the HTML and PDF documentation) - all (openctm + toolset + documentation) - clean (clean all the built files - start from scratch) - -For instance, to just build the OpenCTM shared library under Windows with -MS Visual Studio, type: - - nmake /f Makefile.msvc openctm - - -4. INSTALLATION -=============== - -For Linux and Mac OS X, it is possible to make a system wide installation by -using the "install" build target. The installation process will install the -following: - - - OpenCTM shared library - - OpenCTM C/C++ headers (inlcude files) - - ctmconv and ctmviewer tools - - Man pages - -Just make sure that the Makefile contains the correct (and desired) -installation paths. Also, you need to have root privileges to make a system -wide installation. - -For instance, to compile and install OpenCTM under Ubuntu, do: - -make -f Makefile.linux -sudo make -f Makefile.linux install - -...and to compile and install OpenCTM under Mac OS X, do: - -make -f Makefile.macosx -sudo make -f Makefile.macosx install diff --git a/src/external/OpenCTM-1.0.3/LICENSE.txt b/src/external/OpenCTM-1.0.3/LICENSE.txt deleted file mode 100644 index 0e66fa76e..000000000 --- a/src/external/OpenCTM-1.0.3/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2009-2010 Marcus Geelnard - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not - be misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. diff --git a/src/external/OpenCTM-1.0.3/Makefile.linux b/src/external/OpenCTM-1.0.3/Makefile.linux deleted file mode 100644 index 24ca13753..000000000 --- a/src/external/OpenCTM-1.0.3/Makefile.linux +++ /dev/null @@ -1,65 +0,0 @@ -############################################################################### -# Product: OpenCTM -# File: Makefile.linux -# Description: Top level makefile for Linux systems (should work on most -# Un*x-like systems with gcc, e.g. OpenSolaris). -############################################################################### -# Copyright (c) 2009 Marcus Geelnard -# -# This software is provided 'as-is', without any express or implied -# warranty. In no event will the authors be held liable for any damages -# arising from the use of this software. -# -# Permission is granted to anyone to use this software for any purpose, -# including commercial applications, and to alter it and redistribute it -# freely, subject to the following restrictions: -# -# 1. The origin of this software must not be misrepresented; you must not -# claim that you wrote the original software. If you use this software -# in a product, an acknowledgment in the product documentation would be -# appreciated but is not required. -# -# 2. Altered source versions must be plainly marked as such, and must not -# be misrepresented as being the original software. -# -# 3. This notice may not be removed or altered from any source -# distribution. -############################################################################### - -.phony: default all openctm toolset documentation install clean - -default: openctm toolset -all: openctm toolset documentation - -clean: - cd lib && $(MAKE) -f Makefile.linux clean && cd .. - cd tools && $(MAKE) -f Makefile.linux clean && cd .. - cd doc && $(MAKE) -f Makefile.linux clean && cd .. - -openctm: - cd lib && $(MAKE) -f Makefile.linux -j2 && cd .. - -toolset: - cd tools && $(MAKE) -f Makefile.linux -j2 && cd .. - -documentation: - cd doc && $(MAKE) -f Makefile.linux -j2 && cd .. - - -# Installation settings -LIBDIR = /usr/lib/ -INCDIR = /usr/local/include/ -BINDIR = /usr/local/bin/ -MAN1DIR = /usr/local/share/man/man1/ -CP = cp -MKDIR = mkdir -p - -install: - $(CP) lib/libopenctm.so $(LIBDIR) - $(CP) lib/openctm.h $(INCDIR) - $(CP) lib/openctmpp.h $(INCDIR) - $(CP) tools/ctmconv $(BINDIR) - $(CP) tools/ctmviewer $(BINDIR) - $(MKDIR) $(MAN1DIR) - $(CP) doc/ctmconv.1 $(MAN1DIR) - $(CP) doc/ctmviewer.1 $(MAN1DIR) diff --git a/src/external/OpenCTM-1.0.3/Makefile.macosx b/src/external/OpenCTM-1.0.3/Makefile.macosx deleted file mode 100644 index 16c804b99..000000000 --- a/src/external/OpenCTM-1.0.3/Makefile.macosx +++ /dev/null @@ -1,64 +0,0 @@ -############################################################################### -# Product: OpenCTM -# File: Makefile.macosx -# Description: Top level makefile for Mac OS X. -############################################################################### -# Copyright (c) 2009 Marcus Geelnard -# -# This software is provided 'as-is', without any express or implied -# warranty. In no event will the authors be held liable for any damages -# arising from the use of this software. -# -# Permission is granted to anyone to use this software for any purpose, -# including commercial applications, and to alter it and redistribute it -# freely, subject to the following restrictions: -# -# 1. The origin of this software must not be misrepresented; you must not -# claim that you wrote the original software. If you use this software -# in a product, an acknowledgment in the product documentation would be -# appreciated but is not required. -# -# 2. Altered source versions must be plainly marked as such, and must not -# be misrepresented as being the original software. -# -# 3. This notice may not be removed or altered from any source -# distribution. -############################################################################### - -.phony: default all openctm toolset documentation clean - -default: openctm toolset -all: openctm toolset documentation - -clean: - cd lib && $(MAKE) -f Makefile.macosx clean && cd .. - cd tools && $(MAKE) -f Makefile.macosx clean && cd .. - cd doc && $(MAKE) -f Makefile.macosx clean && cd .. - -openctm: - cd lib && $(MAKE) -f Makefile.macosx -j2 && cd .. - -toolset: - cd tools && $(MAKE) -f Makefile.macosx -j2 && cd .. - -documentation: - cd doc && $(MAKE) -f Makefile.macosx -j2 && cd .. - - -# Installation settings -LIBDIR = /usr/local/lib/ -INCDIR = /usr/local/include/ -BINDIR = /usr/local/bin/ -MAN1DIR = /usr/local/share/man/man1/ -CP = cp -MKDIR = mkdir -p - -install: - $(CP) lib/libopenctm.dylib $(LIBDIR) - $(CP) lib/openctm.h $(INCDIR) - $(CP) lib/openctmpp.h $(INCDIR) - $(CP) tools/ctmconv $(BINDIR) - $(CP) tools/ctmviewer $(BINDIR) - $(MKDIR) $(MAN1DIR) - $(CP) doc/ctmconv.1 $(MAN1DIR) - $(CP) doc/ctmviewer.1 $(MAN1DIR) diff --git a/src/external/OpenCTM-1.0.3/Makefile.mingw b/src/external/OpenCTM-1.0.3/Makefile.mingw deleted file mode 100644 index bf67cdced..000000000 --- a/src/external/OpenCTM-1.0.3/Makefile.mingw +++ /dev/null @@ -1,45 +0,0 @@ -############################################################################### -# Product: OpenCTM -# File: Makefile.mingw -# Description: Top level makefile for Windows / MinGW32. -############################################################################### -# Copyright (c) 2009 Marcus Geelnard -# -# This software is provided 'as-is', without any express or implied -# warranty. In no event will the authors be held liable for any damages -# arising from the use of this software. -# -# Permission is granted to anyone to use this software for any purpose, -# including commercial applications, and to alter it and redistribute it -# freely, subject to the following restrictions: -# -# 1. The origin of this software must not be misrepresented; you must not -# claim that you wrote the original software. If you use this software -# in a product, an acknowledgment in the product documentation would be -# appreciated but is not required. -# -# 2. Altered source versions must be plainly marked as such, and must not -# be misrepresented as being the original software. -# -# 3. This notice may not be removed or altered from any source -# distribution. -############################################################################### - -.phony: default all openctm toolset documentation clean - -default: openctm toolset -all: openctm toolset documentation - -clean: - cd lib && $(MAKE) -f Makefile.mingw clean && cd .. - cd tools && $(MAKE) -f Makefile.mingw clean && cd .. - cd doc && $(MAKE) -f Makefile.win clean && cd .. - -openctm: - cd lib && $(MAKE) -f Makefile.mingw -j2 && cd .. - -toolset: - cd tools && $(MAKE) -f Makefile.mingw -j2 && cd .. - -documentation: - cd doc && $(MAKE) -f Makefile.win -j2 && cd .. diff --git a/src/external/OpenCTM-1.0.3/Makefile.msvc b/src/external/OpenCTM-1.0.3/Makefile.msvc deleted file mode 100644 index ad3cbfae7..000000000 --- a/src/external/OpenCTM-1.0.3/Makefile.msvc +++ /dev/null @@ -1,45 +0,0 @@ -############################################################################### -# Product: OpenCTM -# File: Makefile.msvc -# Description: Top level makefile for Windows / MS Visual Studio 2008. -############################################################################### -# Copyright (c) 2009 Marcus Geelnard -# -# This software is provided 'as-is', without any express or implied -# warranty. In no event will the authors be held liable for any damages -# arising from the use of this software. -# -# Permission is granted to anyone to use this software for any purpose, -# including commercial applications, and to alter it and redistribute it -# freely, subject to the following restrictions: -# -# 1. The origin of this software must not be misrepresented; you must not -# claim that you wrote the original software. If you use this software -# in a product, an acknowledgment in the product documentation would be -# appreciated but is not required. -# -# 2. Altered source versions must be plainly marked as such, and must not -# be misrepresented as being the original software. -# -# 3. This notice may not be removed or altered from any source -# distribution. -############################################################################### - -.PHONY: default all openctm toolset documentation clean - -default: openctm toolset -all: openctm toolset documentation - -clean: - cd lib && $(MAKE) /nologo /f Makefile.msvc clean && cd .. - cd tools && $(MAKE) /nologo /f Makefile.msvc clean && cd .. - cd doc && $(MAKE) /nologo /f Makefile.win clean && cd .. - -openctm: - cd lib && $(MAKE) /nologo /f Makefile.msvc && cd .. - -toolset: - cd tools && $(MAKE) /nologo /f Makefile.msvc && cd .. - -documentation: - cd doc && $(MAKE) /nologo /f Makefile.win && cd .. diff --git a/src/external/OpenCTM-1.0.3/README.txt b/src/external/OpenCTM-1.0.3/README.txt deleted file mode 100644 index f7d1429c4..000000000 --- a/src/external/OpenCTM-1.0.3/README.txt +++ /dev/null @@ -1,152 +0,0 @@ -1. INTRODUCTION -=============== - -Welcome to OpenCTM! - -OpenCTM is a file format, a software library and a tool set for compression of -3D triangle meshes. The geometry is compressed to a fraction of comparable file -formats (3DS, STL, COLLADA, VRML...), and the format is easily accessible -through a simple, portable API. - -The library is written in portable C (C99), and should compile nicely on any -32/64-bit system regardless of endianity (big endian or little endian). - - -2. LICENSE -========== - -The OpenCTM API and the OpenCTM tools are released under the zlib/libpng -license (see LICENSE.txt). - -3. CREDITS -========== - -Many people have helped out in the development process of OpenCTM, with -valuable feedback, programming efforts, test models and conceptual ideas. -Also, OpenCTM relies heavily on many other open source projects. - -Here is an incomplete list of persons that deserve credit: - -- Igor Pavlov (LZMA library) -- Jonas Innala (COLLADA importer, Maya exporter plugin) -- Ilian Dinev (help with the OpenCTM file format design and the LWO loader) -- Lee Thomason (TinyXML) -- Diego Nehab (RPly - for loading PLY files) -- Lev Povalahev, Marcelo E. Magallon, Milan Ikits (GLEW) -- Thomas G. Lane, Guido Vollbeding (libjpeg) -- Jean-loup Gailly, Mark Adler (zlib) -- Daniel Karling (pnglite) - -During the development of OpenCTM, the following software has been used -extensively: - -- Ubuntu (www.ubuntu.com) -- Blender (www.blender.org) -- GCC (gcc.gnu.org) -- SciTE (www.scintilla.org/SciTE.html) -- Notepad++ (notepad-plus.sourceforge.net) -- Smultron (smultron.sourceforge.net) - -Legal notices: - -- This software is based in part on the work of the Independent JPEG Group. - - -4. CHANGES -========== - -v1.0.3 - 2010.01.15 -------------------- -- Added support for PNG format textures (ctmviewer). - -- Added support for LightWave LWO files (ctmconv and ctmviewer). - -- Added support for Geomview OFF files, e.g. as used by the Princeton Shape - Benchmark (ctmconv and ctmviewer). - -- Improved the OBJ file loader (ctmviewer and ctmconv). - -- Experimental support for VRML 2.0 files - export only (ctmconv and ctmviewer). - -- Made it possible to run ctmviewer without command line arguments. - -- Improved the normal calculation algorithm (ctmviewer and ctmconv). - -- Normals are no longer exported if no normals were present in the input file - (ctmviewer). - - -v1.0.2 - 2009.12.13 -------------------- -- Added an OpenCTM exporter plugin for Maya [Jonas Innala]. - -- Added the possiblity to save and load files from ctmviewer, effectively - turning it into a quick and simple converter tool (without all the options - in the ctmconv program, though). - -- Added a function to load texture files from ctmviewer. - -- Improved the camera control in ctmviewer (panning with the right mouse - button, zooming with the middle mouse button and the mouse wheel, feature - focusing by double clicking, Y/Z up axis selection and "fit to screen" - function). - -- Added a GUI dialog for showing errors in ctmviewer (this is especially useful - under Windows, where console output is disabeled). - -- Added an option for calculating the normals in ctmconv (if the input file - does not have normals). - -- Added options for turning off normals, texture coordinates and/or vertex - colors for the output file in ctmconv. - -- Added manuals for ctmviewer and ctmconv (man pages). - -- Added a "make install" build target for Mac OS X and Linux for simple system - wide installation (see COMPILING.txt). - -- NOTE: The Linux/X11 version of ctmviewer now reqires GTK+ 2.0. - - -v1.0.1 - 2009.11.15 -------------------- -- Notable reduction of the memory footprint by tuning of the LZMA compression - parameters. - -- Added a Wavefront OBJ file importer/exporter. - -- Some improvements to ctmviewer and ctmconv. - -- Some directory structure and build system cleanups. - - -v1.0 - 2009.11.09 ------------------ -- Added a COLLADA converter module to the ctmconv program [Jonas Innala]. - -- Added Python bindings and a demo Python program. - -- Improved the internal mesh integrity checking, to minimize the risk of invalid - data processing. - -- Improved the file format specification document. - - -v0.8 (beta) - 2009.09.14 ------------------------- -- Introduced a new API function for controlling the compression level - (ctmCompressionLevel), and set the default compression level to 5 (rather - than 9, which would eat a lot of memory, usally without much difference). - -- Changed the name "texture map" in the API to "UV map" (and all - corresponding constant and function names). This is more in line with - the nomenclature of most 3D authoring software, and avoids the confusion - with the term texture mapping in 3D hardware (which is not limited to - 2D UV mapping coordinates). - -- A few updates to the documentation. - - -v0.7 (beta) - 2009.08.29 ------------------------- -- This was the first public release of OpenCTM. diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/annotated.html b/src/external/OpenCTM-1.0.3/doc/APIReference/annotated.html deleted file mode 100644 index 3658d4522..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/annotated.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - -OpenCTM: Class List - - - - - - -
-

Class List

Here are the classes, structs, unions and interfaces with brief descriptions:
\c Int Smoothing steps The number of times that the whole algorithm (normal smoothing + vertex fitting) is iterated. --
- - - -
ctm_errorOpenCTM exception
CTMexporterOpenCTM exporter class
CTMimporterOpenCTM importer class
- -
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMexporter-members.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMexporter-members.html deleted file mode 100644 index dacb9434c..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMexporter-members.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - -OpenCTM: Member List - - - - - - -
-

CTMexporter Member List

This is the complete list of members for CTMexporter, including all inherited members. - - - - - - - - - - - - - - - - - -
AddAttribMap(const CTMfloat *aAttribValues, const char *aName)CTMexporter [inline]
AddUVMap(const CTMfloat *aUVCoords, const char *aName, const char *aFileName)CTMexporter [inline]
AttribPrecision(CTMenum aAttribMap, CTMfloat aPrecision)CTMexporter [inline]
CompressionLevel(CTMuint aLevel)CTMexporter [inline]
CompressionMethod(CTMenum aMethod)CTMexporter [inline]
CTMexporter()CTMexporter [inline]
CTMexporter(const CTMexporter &v)CTMexporter
DefineMesh(const CTMfloat *aVertices, CTMuint aVertexCount, const CTMuint *aIndices, CTMuint aTriangleCount, const CTMfloat *aNormals)CTMexporter [inline]
FileComment(const char *aFileComment)CTMexporter [inline]
NormalPrecision(CTMfloat aPrecision)CTMexporter [inline]
operator=(const CTMexporter &v)CTMexporter
Save(const char *aFileName)CTMexporter [inline]
SaveCustom(CTMwritefn aWriteFn, void *aUserData)CTMexporter [inline]
UVCoordPrecision(CTMenum aUVMap, CTMfloat aPrecision)CTMexporter [inline]
VertexPrecision(CTMfloat aPrecision)CTMexporter [inline]
VertexPrecisionRel(CTMfloat aRelPrecision)CTMexporter [inline]
~CTMexporter()CTMexporter [inline]
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMexporter.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMexporter.html deleted file mode 100644 index f97cfa5a2..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMexporter.html +++ /dev/null @@ -1,508 +0,0 @@ - - - - -OpenCTM: CTMexporter Class Reference - - - - - - -
-

CTMexporter Class Reference

-

OpenCTM exporter class. -More...

- -

#include <openctmpp.h>

- -

List of all members.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Public Member Functions

 CTMexporter ()
 Constructor.
 ~CTMexporter ()
 Destructor.
void CompressionMethod (CTMenum aMethod)
 Wrapper for ctmCompressionMethod().
void CompressionLevel (CTMuint aLevel)
 Wrapper for ctmCompressionLevel().
void VertexPrecision (CTMfloat aPrecision)
 Wrapper for ctmVertexPrecision().
void VertexPrecisionRel (CTMfloat aRelPrecision)
 Wrapper for ctmVertexPrecisionRel().
void NormalPrecision (CTMfloat aPrecision)
 Wrapper for ctmNormalPrecision().
void UVCoordPrecision (CTMenum aUVMap, CTMfloat aPrecision)
 Wrapper for ctmUVCoordPrecision().
void AttribPrecision (CTMenum aAttribMap, CTMfloat aPrecision)
 Wrapper for ctmAttribPrecision().
void FileComment (const char *aFileComment)
 Wrapper for ctmFileComment().
void DefineMesh (const CTMfloat *aVertices, CTMuint aVertexCount, const CTMuint *aIndices, CTMuint aTriangleCount, const CTMfloat *aNormals)
 Wrapper for ctmDefineMesh().
CTMenum AddUVMap (const CTMfloat *aUVCoords, const char *aName, const char *aFileName)
 Wrapper for ctmAddUVMap().
CTMenum AddAttribMap (const CTMfloat *aAttribValues, const char *aName)
 Wrapper for ctmAddAttribMap().
void Save (const char *aFileName)
 Wrapper for ctmSave().
void SaveCustom (CTMwritefn aWriteFn, void *aUserData)
 Wrapper for ctmSaveCustom().
 CTMexporter (const CTMexporter &v)
CTMexporteroperator= (const CTMexporter &v)
-

Detailed Description

-

OpenCTM exporter class.

-

This is a C++ wrapper class for an OpenCTM export context. Usage example:

-
 void MySaveFile(CTMuint aVertCount, CTMuint aTriCount, CTMfloat * aVertices,
-   CTMuint * aIndices, const char * aFileName)
- {
-   // Create a new OpenCTM exporter object
-   CTMexporter ctm;
-
-   // Define our mesh representation to OpenCTM (store references to it in
-   // the context)
-   ctm.DefineMesh(aVertices, aVertCount, aIndices, aTriCount, NULL);
-
-   // Save the OpenCTM file
-   ctm.Save(aFileName);
- }
-

Constructor & Destructor Documentation

- -
-
- - - - - - - - -
CTMexporter::CTMexporter ( )  [inline]
-
-
- -

Constructor.

- -
-
- -
-
- - - - - - - - -
CTMexporter::~CTMexporter ( )  [inline]
-
-
- -

Destructor.

- -
-
- -
-
- - - - - - - - - -
CTMexporter::CTMexporter (const CTMexporter v ) 
-
-
- -
-
-

Member Function Documentation

- -
-
- - - - - - - - - - - - - - - - - - -
CTMenum CTMexporter::AddAttribMap (const CTMfloat aAttribValues,
const char *  aName 
) [inline]
-
-
- -

Wrapper for ctmAddAttribMap().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
CTMenum CTMexporter::AddUVMap (const CTMfloat aUVCoords,
const char *  aName,
const char *  aFileName 
) [inline]
-
-
- -

Wrapper for ctmAddUVMap().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
void CTMexporter::AttribPrecision (CTMenum  aAttribMap,
CTMfloat  aPrecision 
) [inline]
-
-
- -

Wrapper for ctmAttribPrecision().

- -
-
- -
-
- - - - - - - - - -
void CTMexporter::CompressionLevel (CTMuint  aLevel )  [inline]
-
-
- -

Wrapper for ctmCompressionLevel().

- -
-
- -
-
- - - - - - - - - -
void CTMexporter::CompressionMethod (CTMenum  aMethod )  [inline]
-
-
- -

Wrapper for ctmCompressionMethod().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CTMexporter::DefineMesh (const CTMfloat aVertices,
CTMuint  aVertexCount,
const CTMuint aIndices,
CTMuint  aTriangleCount,
const CTMfloat aNormals 
) [inline]
-
-
- -

Wrapper for ctmDefineMesh().

- -
-
- -
-
- - - - - - - - - -
void CTMexporter::FileComment (const char *  aFileComment )  [inline]
-
-
- -

Wrapper for ctmFileComment().

- -
-
- -
-
- - - - - - - - - -
void CTMexporter::NormalPrecision (CTMfloat  aPrecision )  [inline]
-
-
- -

Wrapper for ctmNormalPrecision().

- -
-
- -
-
- - - - - - - - - -
CTMexporter& CTMexporter::operator= (const CTMexporter v ) 
-
-
- -
-
- -
-
- - - - - - - - - -
void CTMexporter::Save (const char *  aFileName )  [inline]
-
-
- -

Wrapper for ctmSave().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
void CTMexporter::SaveCustom (CTMwritefn  aWriteFn,
void *  aUserData 
) [inline]
-
-
- -

Wrapper for ctmSaveCustom().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
void CTMexporter::UVCoordPrecision (CTMenum  aUVMap,
CTMfloat  aPrecision 
) [inline]
-
-
- -

Wrapper for ctmUVCoordPrecision().

- -
-
- -
-
- - - - - - - - - -
void CTMexporter::VertexPrecision (CTMfloat  aPrecision )  [inline]
-
-
- -

Wrapper for ctmVertexPrecision().

- -
-
- -
-
- - - - - - - - - -
void CTMexporter::VertexPrecisionRel (CTMfloat  aRelPrecision )  [inline]
-
-
- -

Wrapper for ctmVertexPrecisionRel().

- -
-
-
The documentation for this class was generated from the following file: -
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMimporter-members.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMimporter-members.html deleted file mode 100644 index 2b2b0769e..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMimporter-members.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - -OpenCTM: Member List - - - - - - -
-

CTMimporter Member List

This is the complete list of members for CTMimporter, including all inherited members. - - - - - - - - - - - - - - - - - -
CTMimporter()CTMimporter [inline]
CTMimporter(const CTMimporter &v)CTMimporter
GetAttribMapFloat(CTMenum aAttribMap, CTMenum aProperty)CTMimporter [inline]
GetAttribMapString(CTMenum aAttribMap, CTMenum aProperty)CTMimporter [inline]
GetFloat(CTMenum aProperty)CTMimporter [inline]
GetFloatArray(CTMenum aProperty)CTMimporter [inline]
GetInteger(CTMenum aProperty)CTMimporter [inline]
GetIntegerArray(CTMenum aProperty)CTMimporter [inline]
GetNamedAttribMap(const char *aName)CTMimporter [inline]
GetNamedUVMap(const char *aName)CTMimporter [inline]
GetString(CTMenum aProperty)CTMimporter [inline]
GetUVMapFloat(CTMenum aUVMap, CTMenum aProperty)CTMimporter [inline]
GetUVMapString(CTMenum aUVMap, CTMenum aProperty)CTMimporter [inline]
Load(const char *aFileName)CTMimporter [inline]
LoadCustom(CTMreadfn aReadFn, void *aUserData)CTMimporter [inline]
operator=(const CTMimporter &v)CTMimporter
~CTMimporter()CTMimporter [inline]
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMimporter.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMimporter.html deleted file mode 100644 index 19bfa2aba..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMimporter.html +++ /dev/null @@ -1,476 +0,0 @@ - - - - -OpenCTM: CTMimporter Class Reference - - - - - - -
-

CTMimporter Class Reference

-

OpenCTM importer class. -More...

- -

#include <openctmpp.h>

- -

List of all members.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Public Member Functions

 CTMimporter ()
 Constructor.
 ~CTMimporter ()
 Destructor.
CTMuint GetInteger (CTMenum aProperty)
 Wrapper for ctmGetInteger().
CTMfloat GetFloat (CTMenum aProperty)
 Wrapper for ctmGetFloat().
const CTMuintGetIntegerArray (CTMenum aProperty)
 Wrapper for ctmGetIntegerArray().
const CTMfloatGetFloatArray (CTMenum aProperty)
 Wrapper for ctmGetFloatArray().
CTMenum GetNamedUVMap (const char *aName)
 Wrapper for ctmGetNamedUVMap().
const char * GetUVMapString (CTMenum aUVMap, CTMenum aProperty)
 Wrapper for ctmGetUVMapString().
CTMfloat GetUVMapFloat (CTMenum aUVMap, CTMenum aProperty)
 Wrapper for ctmGetUVMapFloat().
CTMenum GetNamedAttribMap (const char *aName)
 Wrapper for ctmGetNamedAttribMap().
const char * GetAttribMapString (CTMenum aAttribMap, CTMenum aProperty)
 Wrapper for ctmGetAttribMapString().
CTMfloat GetAttribMapFloat (CTMenum aAttribMap, CTMenum aProperty)
 Wrapper for ctmGetAttribMapFloat().
const char * GetString (CTMenum aProperty)
 Wrapper for ctmGetString().
void Load (const char *aFileName)
 Wrapper for ctmLoad().
void LoadCustom (CTMreadfn aReadFn, void *aUserData)
 Wrapper for ctmLoadCustom().
 CTMimporter (const CTMimporter &v)
CTMimporteroperator= (const CTMimporter &v)
-

Detailed Description

-

OpenCTM importer class.

-

This is a C++ wrapper class for an OpenCTM import context. Usage example:

-
   // Create a new OpenCTM importer object
-   CTMimporter ctm;
-
-   // Load the OpenCTM file
-   ctm.Load("mymesh.ctm");
-
-   // Access the mesh data
-   vertCount = ctm.GetInteger(CTM_VERTEX_COUNT);
-   vertices = ctm.GetFloatArray(CTM_VERTICES);
-   triCount = ctm.GetInteger(CTM_TRIANGLE_COUNT);
-   indices = ctm.GetIntegerArray(CTM_INDICES);
-
-   // Deal with the mesh (e.g. transcode it to our internal representation)
-   // ...
-

Constructor & Destructor Documentation

- -
-
- - - - - - - - -
CTMimporter::CTMimporter ( )  [inline]
-
-
- -

Constructor.

- -
-
- -
-
- - - - - - - - -
CTMimporter::~CTMimporter ( )  [inline]
-
-
- -

Destructor.

- -
-
- -
-
- - - - - - - - - -
CTMimporter::CTMimporter (const CTMimporter v ) 
-
-
- -
-
-

Member Function Documentation

- -
-
- - - - - - - - - - - - - - - - - - -
CTMfloat CTMimporter::GetAttribMapFloat (CTMenum  aAttribMap,
CTMenum  aProperty 
) [inline]
-
-
- -

Wrapper for ctmGetAttribMapFloat().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
const char* CTMimporter::GetAttribMapString (CTMenum  aAttribMap,
CTMenum  aProperty 
) [inline]
-
-
- -

Wrapper for ctmGetAttribMapString().

- -
-
- -
-
- - - - - - - - - -
CTMfloat CTMimporter::GetFloat (CTMenum  aProperty )  [inline]
-
-
- -

Wrapper for ctmGetFloat().

- -
-
- -
-
- - - - - - - - - -
const CTMfloat* CTMimporter::GetFloatArray (CTMenum  aProperty )  [inline]
-
-
- -

Wrapper for ctmGetFloatArray().

- -
-
- -
-
- - - - - - - - - -
CTMuint CTMimporter::GetInteger (CTMenum  aProperty )  [inline]
-
-
- -

Wrapper for ctmGetInteger().

- -
-
- -
-
- - - - - - - - - -
const CTMuint* CTMimporter::GetIntegerArray (CTMenum  aProperty )  [inline]
-
-
- -

Wrapper for ctmGetIntegerArray().

- -
-
- -
-
- - - - - - - - - -
CTMenum CTMimporter::GetNamedAttribMap (const char *  aName )  [inline]
-
-
- -

Wrapper for ctmGetNamedAttribMap().

- -
-
- -
-
- - - - - - - - - -
CTMenum CTMimporter::GetNamedUVMap (const char *  aName )  [inline]
-
-
- -

Wrapper for ctmGetNamedUVMap().

- -
-
- -
-
- - - - - - - - - -
const char* CTMimporter::GetString (CTMenum  aProperty )  [inline]
-
-
- -

Wrapper for ctmGetString().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMfloat CTMimporter::GetUVMapFloat (CTMenum  aUVMap,
CTMenum  aProperty 
) [inline]
-
-
- -

Wrapper for ctmGetUVMapFloat().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
const char* CTMimporter::GetUVMapString (CTMenum  aUVMap,
CTMenum  aProperty 
) [inline]
-
-
- -

Wrapper for ctmGetUVMapString().

- -
-
- -
-
- - - - - - - - - -
void CTMimporter::Load (const char *  aFileName )  [inline]
-
-
- -

Wrapper for ctmLoad().

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
void CTMimporter::LoadCustom (CTMreadfn  aReadFn,
void *  aUserData 
) [inline]
-
-
- -

Wrapper for ctmLoadCustom().

- -
-
- -
-
- - - - - - - - - -
CTMimporter& CTMimporter::operator= (const CTMimporter v ) 
-
-
- -
-
-
The documentation for this class was generated from the following file: -
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classctm__error-members.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classctm__error-members.html deleted file mode 100644 index 808972cb9..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/classctm__error-members.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - -OpenCTM: Member List - - - - - - -
-

ctm_error Member List

This is the complete list of members for ctm_error, including all inherited members. - - - -
ctm_error(CTMenum aError)ctm_error [inline, explicit]
error_code() const ctm_error [inline]
what() const ctm_error [inline, virtual]
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classctm__error.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classctm__error.html deleted file mode 100644 index c75b0790a..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/classctm__error.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - -OpenCTM: ctm_error Class Reference - - - - - - -
-

ctm_error Class Reference

-

OpenCTM exception. -More...

- -

#include <openctmpp.h>

- -

List of all members.

- - - - - -

Public Member Functions

 ctm_error (CTMenum aError)
virtual const char * what () const throw ()
CTMenum error_code () const throw ()
-

Detailed Description

-

OpenCTM exception.

-

When an error occurs, a ctm_error exception is thrown. Its what() function returns the name of the OpenCTM error code (for instance "CTM_INVALID_OPERATION").

-

Constructor & Destructor Documentation

- -
-
- - - - - - - - - -
ctm_error::ctm_error (CTMenum  aError )  [inline, explicit]
-
-
- -
-
-

Member Function Documentation

- -
-
- - - - - - - - -
CTMenum ctm_error::error_code ( )  const throw () [inline]
-
-
- -
-
- -
-
- - - - - - - - -
virtual const char* ctm_error::what ( )  const throw () [inline, virtual]
-
-
- -
-
-
The documentation for this class was generated from the following file: -
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classes.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classes.html deleted file mode 100644 index 866996cc7..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/classes.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - -OpenCTM: Alphabetical List - - - - - - -
-

Class Index

- -
  C  
-
ctm_error   CTMexporter   CTMimporter   
-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/doxygen.css b/src/external/OpenCTM-1.0.3/doc/APIReference/doxygen.css deleted file mode 100644 index 9ca3cafbc..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/doxygen.css +++ /dev/null @@ -1,498 +0,0 @@ -/* The standard CSS for doxygen */ - -body, table, div, p, dl { - font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; - font-size: 12px; -} - -/* @group Heading Levels */ - -h1 { - text-align: center; - font-size: 150%; -} - -h2 { - font-size: 120%; -} - -h3 { - font-size: 100%; -} - -dt { - font-weight: bold; -} - -div.multicol { - -moz-column-gap: 1em; - -webkit-column-gap: 1em; - -moz-column-count: 3; - -webkit-column-count: 3; -} - -p.startli, p.startdd { - margin-top: 2px; -} - -p.endli { - margin-bottom: 0px; -} - -p.enddd { - margin-bottom: 4px; -} - -/* @end */ - -caption { - font-weight: bold; -} - -span.legend { - font-size: 70%; - text-align: center; -} - -div.qindex, div.navtab{ - background-color: #e8eef2; - border: 1px solid #84b0c7; - text-align: center; - margin: 2px; - padding: 2px; -} - -div.qindex, div.navpath { - width: 100%; - line-height: 140%; -} - -div.navtab { - margin-right: 15px; -} - -/* @group Link Styling */ - -a { - color: #153788; - font-weight: normal; - text-decoration: none; -} - -.contents a:visited { - color: #1b77c5; -} - -a:hover { - text-decoration: underline; -} - -a.qindex { - font-weight: bold; -} - -a.qindexHL { - font-weight: bold; - background-color: #6666cc; - color: #ffffff; - border: 1px double #9295C2; -} - -.contents a.qindexHL:visited { - color: #ffffff; -} - -a.el { - font-weight: bold; -} - -a.elRef { -} - -a.code { -} - -a.codeRef { -} - -/* @end */ - -dl.el { - margin-left: -1cm; -} - -.fragment { - font-family: monospace, fixed; - font-size: 105%; -} - -pre.fragment { - border: 1px solid #CCCCCC; - background-color: #f5f5f5; - padding: 4px 6px; - margin: 4px 8px 4px 2px; -} - -div.ah { - background-color: black; - font-weight: bold; - color: #ffffff; - margin-bottom: 3px; - margin-top: 3px -} - -div.groupHeader { - margin-left: 16px; - margin-top: 12px; - margin-bottom: 6px; - font-weight: bold; -} - -div.groupText { - margin-left: 16px; - font-style: italic; -} - -body { - background: white; - color: black; - margin-right: 20px; - margin-left: 20px; -} - -td.indexkey { - background-color: #e8eef2; - font-weight: bold; - border: 1px solid #CCCCCC; - margin: 2px 0px 2px 0; - padding: 2px 10px; -} - -td.indexvalue { - background-color: #e8eef2; - border: 1px solid #CCCCCC; - padding: 2px 10px; - margin: 2px 0px; -} - -tr.memlist { - background-color: #f0f0f0; -} - -p.formulaDsp { - text-align: center; -} - -img.formulaDsp { - -} - -img.formulaInl { - vertical-align: middle; -} - -div.center { - text-align: center; - margin-top: 0px; - margin-bottom: 0px; - padding: 0px; -} - -div.center img { - border: 0px; -} - -img.footer { - border: 0px; - vertical-align: middle; -} - -/* @group Code Colorization */ - -span.keyword { - color: #008000 -} - -span.keywordtype { - color: #604020 -} - -span.keywordflow { - color: #e08000 -} - -span.comment { - color: #800000 -} - -span.preprocessor { - color: #806020 -} - -span.stringliteral { - color: #002080 -} - -span.charliteral { - color: #008080 -} - -span.vhdldigit { - color: #ff00ff -} - -span.vhdlchar { - color: #000000 -} - -span.vhdlkeyword { - color: #700070 -} - -span.vhdllogic { - color: #ff0000 -} - -/* @end */ - -.search { - color: #003399; - font-weight: bold; -} - -form.search { - margin-bottom: 0px; - margin-top: 0px; -} - -input.search { - font-size: 75%; - color: #000080; - font-weight: normal; - background-color: #e8eef2; -} - -td.tiny { - font-size: 75%; -} - -.dirtab { - padding: 4px; - border-collapse: collapse; - border: 1px solid #84b0c7; -} - -th.dirtab { - background: #e8eef2; - font-weight: bold; -} - -hr { - height: 0; - border: none; - border-top: 1px solid #666; -} - -/* @group Member Descriptions */ - -.mdescLeft, .mdescRight, -.memItemLeft, .memItemRight, -.memTemplItemLeft, .memTemplItemRight, .memTemplParams { - background-color: #FAFAFA; - border: none; - margin: 4px; - padding: 1px 0 0 8px; -} - -.mdescLeft, .mdescRight { - padding: 0px 8px 4px 8px; - color: #555; -} - -.memItemLeft, .memItemRight, .memTemplParams { - border-top: 1px solid #ccc; -} - -.memItemLeft, .memTemplItemLeft { - white-space: nowrap; -} - -.memTemplParams { - color: #606060; - white-space: nowrap; -} - -/* @end */ - -/* @group Member Details */ - -/* Styles for detailed member documentation */ - -.memtemplate { - font-size: 80%; - color: #606060; - font-weight: normal; - margin-left: 3px; -} - -.memnav { - background-color: #e8eef2; - border: 1px solid #84b0c7; - text-align: center; - margin: 2px; - margin-right: 15px; - padding: 2px; -} - -.memitem { - padding: 0; - margin-bottom: 10px; -} - -.memname { - white-space: nowrap; - font-weight: bold; -} - -.memproto, .memdoc { - border: 1px solid #84b0c7; -} - -.memproto { - padding: 0; - background-color: #d5e1e8; - font-weight: bold; - -webkit-border-top-left-radius: 8px; - -webkit-border-top-right-radius: 8px; - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - -moz-border-radius-topleft: 8px; - -moz-border-radius-topright: 8px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - -} - -.memdoc { - padding: 2px 5px; - background-color: #eef3f5; - border-top-width: 0; - -webkit-border-bottom-left-radius: 8px; - -webkit-border-bottom-right-radius: 8px; - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - -moz-border-radius-bottomleft: 8px; - -moz-border-radius-bottomright: 8px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; -} - -.paramkey { - text-align: right; -} - -.paramtype { - white-space: nowrap; -} - -.paramname { - color: #602020; - white-space: nowrap; -} -.paramname em { - font-style: normal; -} - -/* @end */ - -/* @group Directory (tree) */ - -/* for the tree view */ - -.ftvtree { - font-family: sans-serif; - margin: 0.5em; -} - -/* these are for tree view when used as main index */ - -.directory { - font-size: 9pt; - font-weight: bold; -} - -.directory h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; -} - -/* -The following two styles can be used to replace the root node title -with an image of your choice. Simply uncomment the next two styles, -specify the name of your image and be sure to set 'height' to the -proper pixel height of your image. -*/ - -/* -.directory h3.swap { - height: 61px; - background-repeat: no-repeat; - background-image: url("yourimage.gif"); -} -.directory h3.swap span { - display: none; -} -*/ - -.directory > h3 { - margin-top: 0; -} - -.directory p { - margin: 0px; - white-space: nowrap; -} - -.directory div { - display: none; - margin: 0px; -} - -.directory img { - vertical-align: -30%; -} - -/* these are for tree view when not used as main index */ - -.directory-alt { - font-size: 100%; - font-weight: bold; -} - -.directory-alt h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; -} - -.directory-alt > h3 { - margin-top: 0; -} - -.directory-alt p { - margin: 0px; - white-space: nowrap; -} - -.directory-alt div { - display: none; - margin: 0px; -} - -.directory-alt img { - vertical-align: -30%; -} - -/* @end */ - -address { - font-style: normal; - color: #333; -} diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/doxygen.png b/src/external/OpenCTM-1.0.3/doc/APIReference/doxygen.png deleted file mode 100644 index f0a274bba..000000000 Binary files a/src/external/OpenCTM-1.0.3/doc/APIReference/doxygen.png and /dev/null differ diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/files.html b/src/external/OpenCTM-1.0.3/doc/APIReference/files.html deleted file mode 100644 index 3d4691c98..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/files.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - -OpenCTM: File Index - - - - - - -
-

File List

Here is a list of all files with brief descriptions: - - -
openctm.h [code]
openctmpp.h [code]
-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/functions.html b/src/external/OpenCTM-1.0.3/doc/APIReference/functions.html deleted file mode 100644 index 2dd69a021..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/functions.html +++ /dev/null @@ -1,216 +0,0 @@ - - - - -OpenCTM: Class Members - - - - - - -
-Here is a list of all class members with links to the classes they belong to: - -

- a -

- - -

- c -

- - -

- d -

- - -

- e -

- - -

- f -

- - -

- g -

- - -

- l -

- - -

- n -

- - -

- o -

- - -

- s -

- - -

- u -

- - -

- v -

- - -

- w -

- - -

- ~ -

-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/functions_func.html b/src/external/OpenCTM-1.0.3/doc/APIReference/functions_func.html deleted file mode 100644 index df20fa4f7..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/functions_func.html +++ /dev/null @@ -1,216 +0,0 @@ - - - - -OpenCTM: Class Members - Functions - - - - - - -
-  - -

- a -

- - -

- c -

- - -

- d -

- - -

- e -

- - -

- f -

- - -

- g -

- - -

- l -

- - -

- n -

- - -

- o -

- - -

- s -

- - -

- u -

- - -

- v -

- - -

- w -

- - -

- ~ -

-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/globals.html b/src/external/OpenCTM-1.0.3/doc/APIReference/globals.html deleted file mode 100644 index e0bc7b0b6..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/globals.html +++ /dev/null @@ -1,313 +0,0 @@ - - - - -OpenCTM: Class Members - - - - - - -
-Here is a list of all file members with links to the files they belong to: - -

- c -

-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_defs.html b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_defs.html deleted file mode 100644 index 3c5815d65..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_defs.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - -OpenCTM: Class Members - - - - - - -
-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_enum.html b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_enum.html deleted file mode 100644 index bf3d826bd..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_enum.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - -OpenCTM: Class Members - - - - - - -
-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_eval.html b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_eval.html deleted file mode 100644 index 9f23a4d95..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_eval.html +++ /dev/null @@ -1,193 +0,0 @@ - - - - -OpenCTM: Class Members - - - - - - -
-  - -

- c -

-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_func.html b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_func.html deleted file mode 100644 index da41c09e8..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_func.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - -OpenCTM: Class Members - - - - - - -
-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_type.html b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_type.html deleted file mode 100644 index 1986f7f44..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_type.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - -OpenCTM: Class Members - - - - - - -
-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/index.html b/src/external/OpenCTM-1.0.3/doc/APIReference/index.html deleted file mode 100644 index 72eba302c..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/index.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - -OpenCTM: OpenCTM API Reference - - - - - - -
-

OpenCTM API Reference

1.0.3

-Introduction

-

OpenCTM is an open file format for storing compressed triangle meshes. In order to easily read and write OpenCTM files (usually suffixed .ctm) an API (Application Program Interface) is provided that can easily be used from most modern programming languages.

-

The OpenCTM functionality itself is written in highly portable standard C (C99).

-

-Usage

-

For information about how to use the OpenCTM API, see openctm.h.

-

For information about the C++ wrapper classes, see CTMimporter and CTMexporter.

-

-Example usage

-

-Loading a CTM file

-

Here is a simple example of loading a CTM file:

-
   CTMcontext context;
-   CTMuint    vertCount, triCount, * indices;
-   CTMfloat   * vertices;
-
-   // Create a new context
-   context = ctmNewContext(CTM_IMPORT);
-
-   // Load the OpenCTM file
-   ctmLoad(context, "mymesh.ctm");
-   if(ctmGetError(context) == CTM_NONE)
-   {
-     // Access the mesh data
-     vertCount = ctmGetInteger(context, CTM_VERTEX_COUNT);
-     vertices = ctmGetFloatArray(context, CTM_VERTICES);
-     triCount = ctmGetInteger(context, CTM_TRIANGLE_COUNT);
-     indices = ctmGetIntegerArray(context, CTM_INDICES);
-
-     // Deal with the mesh (e.g. transcode it to our internal representation)
-     // ...
-   }
-
-   // Free the context
-   ctmFreeContext(context);
-

-Creating a CTM file

-

Here is a simple example of creating a CTM file:

-
   CTMcontext context;
-   CTMuint    vertCount, triCount, * indices;
-   CTMfloat   * vertices;
-
-   // Create our mesh in memory
-   vertCount = 100;
-   triCount = 120;
-   vertices = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * vertCount);
-   indices = (CTMuint *) malloc(3 * sizeof(CTMuint) * triCount);
-   // ...
-
-   // Create a new context
-   context = ctmNewContext(CTM_EXPORT);
-
-   // Define our mesh representation to OpenCTM (store references to it in
-   // the context)
-   ctmDefineMesh(context, vertices, vertCount, indices, triCount, NULL);
-
-   // Save the OpenCTM file
-   ctmSave(context, "mymesh.ctm");
-
-   // Free the context
-   ctmFreeContext(context);
-
-   // Free our mesh
-   free(indices);
-   free(vertices);
-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/openctm_8h.html b/src/external/OpenCTM-1.0.3/doc/APIReference/openctm_8h.html deleted file mode 100644 index d6711fceb..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/openctm_8h.html +++ /dev/null @@ -1,1738 +0,0 @@ - - - - -OpenCTM: openctm.h File Reference - - - - - - -
-

openctm.h File Reference

#include <stdint.h>
- -

Go to the source code of this file.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Defines

#define CTM_API_VERSION   0x00000100
 OpenCTM API version (1.0).
#define CTM_TRUE   1
 Boolean TRUE.
#define CTM_FALSE   0
 Boolean FALSE.

Typedefs

typedef float CTMfloat
 Single precision floating point type (IEEE 754 32 bits wide).
typedef int32_t CTMint
 Signed integer (32 bits wide).
typedef uint32_t CTMuint
 Unsigned integer (32 bits wide).
typedef void * CTMcontext
 OpenCTM context handle.
typedef CTMuint(CTMCALL * CTMreadfn )(void *aBuf, CTMuint aCount, void *aUserData)
 Stream read() function pointer.
typedef CTMuint(CTMCALL * CTMwritefn )(const void *aBuf, CTMuint aCount, void *aUserData)
 Stream write() function pointer.

Enumerations

enum  CTMenum {
-  CTM_NONE = 0x0000, -
-  CTM_INVALID_CONTEXT = 0x0001, -
-  CTM_INVALID_ARGUMENT = 0x0002, -
-  CTM_INVALID_OPERATION = 0x0003, -
-  CTM_INVALID_MESH = 0x0004, -
-  CTM_OUT_OF_MEMORY = 0x0005, -
-  CTM_FILE_ERROR = 0x0006, -
-  CTM_BAD_FORMAT = 0x0007, -
-  CTM_LZMA_ERROR = 0x0008, -
-  CTM_INTERNAL_ERROR = 0x0009, -
-  CTM_UNSUPPORTED_FORMAT_VERSION = 0x000A, -
-  CTM_IMPORT = 0x0101, -
-  CTM_EXPORT = 0x0102, -
-  CTM_METHOD_RAW = 0x0201, -
-  CTM_METHOD_MG1 = 0x0202, -
-  CTM_METHOD_MG2 = 0x0203, -
-  CTM_VERTEX_COUNT = 0x0301, -
-  CTM_TRIANGLE_COUNT = 0x0302, -
-  CTM_HAS_NORMALS = 0x0303, -
-  CTM_UV_MAP_COUNT = 0x0304, -
-  CTM_ATTRIB_MAP_COUNT = 0x0305, -
-  CTM_VERTEX_PRECISION = 0x0306, -
-  CTM_NORMAL_PRECISION = 0x0307, -
-  CTM_COMPRESSION_METHOD = 0x0308, -
-  CTM_FILE_COMMENT = 0x0309, -
-  CTM_NAME = 0x0501, -
-  CTM_FILE_NAME = 0x0502, -
-  CTM_PRECISION = 0x0503, -
-  CTM_INDICES = 0x0601, -
-  CTM_VERTICES = 0x0602, -
-  CTM_NORMALS = 0x0603, -
-  CTM_UV_MAP_1 = 0x0700, -
-  CTM_UV_MAP_2 = 0x0701, -
-  CTM_UV_MAP_3 = 0x0702, -
-  CTM_UV_MAP_4 = 0x0703, -
-  CTM_UV_MAP_5 = 0x0704, -
-  CTM_UV_MAP_6 = 0x0705, -
-  CTM_UV_MAP_7 = 0x0706, -
-  CTM_UV_MAP_8 = 0x0707, -
-  CTM_ATTRIB_MAP_1 = 0x0800, -
-  CTM_ATTRIB_MAP_2 = 0x0801, -
-  CTM_ATTRIB_MAP_3 = 0x0802, -
-  CTM_ATTRIB_MAP_4 = 0x0803, -
-  CTM_ATTRIB_MAP_5 = 0x0804, -
-  CTM_ATTRIB_MAP_6 = 0x0805, -
-  CTM_ATTRIB_MAP_7 = 0x0806, -
-  CTM_ATTRIB_MAP_8 = 0x0807 -
- }
 

OpenCTM specific enumerators.

- More...

Functions

CTMEXPORT CTMcontext CTMCALL ctmNewContext (CTMenum aMode)
 Create a new OpenCTM context.
CTMEXPORT void CTMCALL ctmFreeContext (CTMcontext aContext)
 Free an OpenCTM context.
CTMEXPORT CTMenum CTMCALL ctmGetError (CTMcontext aContext)
 Returns the latest error.
CTMEXPORT const char *CTMCALL ctmErrorString (CTMenum aError)
 Converts an OpenCTM error code to a zero-terminated string.
CTMEXPORT CTMuint CTMCALL ctmGetInteger (CTMcontext aContext, CTMenum aProperty)
 Get information about an OpenCTM context.
CTMEXPORT CTMfloat CTMCALL ctmGetFloat (CTMcontext aContext, CTMenum aProperty)
 Get information about an OpenCTM context.
CTMEXPORT const CTMuint *CTMCALL ctmGetIntegerArray (CTMcontext aContext, CTMenum aProperty)
 Get an integer array from an OpenCTM context.
CTMEXPORT const CTMfloat *CTMCALL ctmGetFloatArray (CTMcontext aContext, CTMenum aProperty)
 Get a floating point array from an OpenCTM context.
CTMEXPORT CTMenum CTMCALL ctmGetNamedUVMap (CTMcontext aContext, const char *aName)
 Get a reference to the named UV map.
CTMEXPORT const char *CTMCALL ctmGetUVMapString (CTMcontext aContext, CTMenum aUVMap, CTMenum aProperty)
 Get information about a UV map.
CTMEXPORT CTMfloat CTMCALL ctmGetUVMapFloat (CTMcontext aContext, CTMenum aUVMap, CTMenum aProperty)
 Get information about a UV map.
CTMEXPORT CTMenum CTMCALL ctmGetNamedAttribMap (CTMcontext aContext, const char *aName)
 Get a reference to the named vertex attribute map.
CTMEXPORT const char *CTMCALL ctmGetAttribMapString (CTMcontext aContext, CTMenum aAttribMap, CTMenum aProperty)
 Get information about a vertex attribute map.
CTMEXPORT CTMfloat CTMCALL ctmGetAttribMapFloat (CTMcontext aContext, CTMenum aAttribMap, CTMenum aProperty)
 Get information about a vertex attribute map.
CTMEXPORT const char *CTMCALL ctmGetString (CTMcontext aContext, CTMenum aProperty)
 Get information about an OpenCTM context.
CTMEXPORT void CTMCALL ctmCompressionMethod (CTMcontext aContext, CTMenum aMethod)
 Set which compression method to use for the given OpenCTM context.
CTMEXPORT void CTMCALL ctmCompressionLevel (CTMcontext aContext, CTMuint aLevel)
 Set which LZMA compression level to use for the given OpenCTM context.
CTMEXPORT void CTMCALL ctmVertexPrecision (CTMcontext aContext, CTMfloat aPrecision)
 Set the vertex coordinate precision (only used by the MG2 compression method).
CTMEXPORT void CTMCALL ctmVertexPrecisionRel (CTMcontext aContext, CTMfloat aRelPrecision)
 Set the vertex coordinate precision, relative to the mesh dimensions (only used by the MG2 compression method).
CTMEXPORT void CTMCALL ctmNormalPrecision (CTMcontext aContext, CTMfloat aPrecision)
 Set the normal precision (only used by the MG2 compression method).
CTMEXPORT void CTMCALL ctmUVCoordPrecision (CTMcontext aContext, CTMenum aUVMap, CTMfloat aPrecision)
 Set the coordinate precision for the specified UV map (only used by the MG2 compression method).
CTMEXPORT void CTMCALL ctmAttribPrecision (CTMcontext aContext, CTMenum aAttribMap, CTMfloat aPrecision)
 Set the attribute value precision for the specified attribute map (only used by the MG2 compression method).
CTMEXPORT void CTMCALL ctmFileComment (CTMcontext aContext, const char *aFileComment)
 Set the file comment for the given OpenCTM context.
CTMEXPORT void CTMCALL ctmDefineMesh (CTMcontext aContext, const CTMfloat *aVertices, CTMuint aVertexCount, const CTMuint *aIndices, CTMuint aTriangleCount, const CTMfloat *aNormals)
 Define a triangle mesh.
CTMEXPORT CTMenum CTMCALL ctmAddUVMap (CTMcontext aContext, const CTMfloat *aUVCoords, const char *aName, const char *aFileName)
 Define a UV map.
CTMEXPORT CTMenum CTMCALL ctmAddAttribMap (CTMcontext aContext, const CTMfloat *aAttribValues, const char *aName)
 Define a custom vertex attribute map.
CTMEXPORT void CTMCALL ctmLoad (CTMcontext aContext, const char *aFileName)
 Load an OpenCTM format file into the context.
CTMEXPORT void CTMCALL ctmLoadCustom (CTMcontext aContext, CTMreadfn aReadFn, void *aUserData)
 Load an OpenCTM format file using a custom stream read function.
CTMEXPORT void CTMCALL ctmSave (CTMcontext aContext, const char *aFileName)
 Save an OpenCTM format file.
CTMEXPORT void CTMCALL ctmSaveCustom (CTMcontext aContext, CTMwritefn aWriteFn, void *aUserData)
 Save an OpenCTM format file using a custom stream write function.
-

Define Documentation

- -
-
- - - - -
#define CTM_API_VERSION   0x00000100
-
-
- -

OpenCTM API version (1.0).

- -
-
- -
-
- - - - -
#define CTM_FALSE   0
-
-
- -

Boolean FALSE.

- -
-
- -
-
- - - - -
#define CTM_TRUE   1
-
-
- -

Boolean TRUE.

- -
-
-

Typedef Documentation

- -
-
- - - - -
typedef void* CTMcontext
-
-
- -

OpenCTM context handle.

- -
-
- -
-
- - - - -
typedef float CTMfloat
-
-
- -

Single precision floating point type (IEEE 754 32 bits wide).

- -
-
- -
-
- - - - -
typedef int32_t CTMint
-
-
- -

Signed integer (32 bits wide).

- -
-
- -
-
- - - - -
typedef CTMuint(CTMCALL * CTMreadfn)(void *aBuf, CTMuint aCount, void *aUserData)
-
-
- -

Stream read() function pointer.

-
Parameters:
- - - - -
[in] aBuf Pointer to the memory buffer to which data should be read.
[in] aCount The number of bytes to read.
[in] aUserData The custom user data that was passed to the ctmLoadCustom() function.
-
-
-
Returns:
The number of bytes actually read (if this is less than aCount, it indicates that an error occured or the end of file was reached before all bytes were read).
- -
-
- -
-
- - - - -
typedef uint32_t CTMuint
-
-
- -

Unsigned integer (32 bits wide).

- -
-
- -
-
- - - - -
typedef CTMuint(CTMCALL * CTMwritefn)(const void *aBuf, CTMuint aCount, void *aUserData)
-
-
- -

Stream write() function pointer.

-
Parameters:
- - - - -
[in] aBuf Pointer to the memory buffer from which data should be written.
[in] aCount The number of bytes to write.
[in] aUserData The custom user data that was passed to the ctmSaveCustom() function.
-
-
-
Returns:
The number of bytes actually written (if this is less than aCount, it indicates that an error occured).
- -
-
-

Enumeration Type Documentation

- -
-
- - - - -
enum CTMenum
-
-
- -

OpenCTM specific enumerators.

-
Note:
For the information query functions, it is an error to query a value of the wrong type (e.g. to query a string value with the ctmGetInteger() function).
-
Enumerator:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CTM_NONE  -

No error has occured (everything is OK).

-

Also used as an error return value for functions that should return a CTMenum value.

-
CTM_INVALID_CONTEXT  -

The OpenCTM context was invalid (e.g. NULL).

-
CTM_INVALID_ARGUMENT  -

A function argument was invalid.

-
CTM_INVALID_OPERATION  -

The operation is not allowed.

-
CTM_INVALID_MESH  -

The mesh was invalid (e.g. no vertices).

-
CTM_OUT_OF_MEMORY  -

Not enough memory to proceed.

-
CTM_FILE_ERROR  -

File I/O error.

-
CTM_BAD_FORMAT  -

File format error (e.g. unrecognized format or corrupted file).

-
CTM_LZMA_ERROR  -

An error occured within the LZMA library.

-
CTM_INTERNAL_ERROR  -

An internal error occured (indicates a bug).

-
CTM_UNSUPPORTED_FORMAT_VERSION  -

Unsupported file format version.

-
CTM_IMPORT  -

The OpenCTM context will be used for importing data.

-
CTM_EXPORT  -

The OpenCTM context will be used for exporting data.

-
CTM_METHOD_RAW  -

Just store the raw data.

-
CTM_METHOD_MG1  -

Lossless compression (floating point).

-
CTM_METHOD_MG2  -

Lossless compression (fixed point).

-
CTM_VERTEX_COUNT  -

Number of vertices in the mesh (integer).

-
CTM_TRIANGLE_COUNT  -

Number of triangles in the mesh (integer).

-
CTM_HAS_NORMALS  -

CTM_TRUE if the mesh has normals (integer).

-
CTM_UV_MAP_COUNT  -

Number of UV coordinate sets (integer).

-
CTM_ATTRIB_MAP_COUNT  -

Number of custom attribute sets (integer).

-
CTM_VERTEX_PRECISION  -

Vertex precision - for MG2 (float).

-
CTM_NORMAL_PRECISION  -

Normal precision - for MG2 (float).

-
CTM_COMPRESSION_METHOD  -

Compression method (integer).

-
CTM_FILE_COMMENT  -

File comment (string).

-
CTM_NAME  -

Unique name (UV/attrib map string).

-
CTM_FILE_NAME  -

File name reference (UV map string).

-
CTM_PRECISION  -

Value precision (UV/attrib map float).

-
CTM_INDICES  -

Triangle indices (integer array).

-
CTM_VERTICES  -

Vertex point coordinates (float array).

-
CTM_NORMALS  -

Per vertex normals (float array).

-
CTM_UV_MAP_1  -

Per vertex UV map 1 (float array).

-
CTM_UV_MAP_2  -

Per vertex UV map 2 (float array).

-
CTM_UV_MAP_3  -

Per vertex UV map 3 (float array).

-
CTM_UV_MAP_4  -

Per vertex UV map 4 (float array).

-
CTM_UV_MAP_5  -

Per vertex UV map 5 (float array).

-
CTM_UV_MAP_6  -

Per vertex UV map 6 (float array).

-
CTM_UV_MAP_7  -

Per vertex UV map 7 (float array).

-
CTM_UV_MAP_8  -

Per vertex UV map 8 (float array).

-
CTM_ATTRIB_MAP_1  -

Per vertex attribute map 1 (float array).

-
CTM_ATTRIB_MAP_2  -

Per vertex attribute map 2 (float array).

-
CTM_ATTRIB_MAP_3  -

Per vertex attribute map 3 (float array).

-
CTM_ATTRIB_MAP_4  -

Per vertex attribute map 4 (float array).

-
CTM_ATTRIB_MAP_5  -

Per vertex attribute map 5 (float array).

-
CTM_ATTRIB_MAP_6  -

Per vertex attribute map 6 (float array).

-
CTM_ATTRIB_MAP_7  -

Per vertex attribute map 7 (float array).

-
CTM_ATTRIB_MAP_8  -

Per vertex attribute map 8 (float array).

-
-
-
- -
-
-

Function Documentation

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
CTMEXPORT CTMenum CTMCALL ctmAddAttribMap (CTMcontext  aContext,
const CTMfloat aAttribValues,
const char *  aName 
)
-
-
- -

Define a custom vertex attribute map.

-

Custom vertex attributes can be used for defining special per-vertex attributes, such as color, weight, ambient occlusion factor, etc.

-
Parameters:
- - - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aAttribValues An array of attribute values. Each attribute value is made up by four consecutive floats, and there must be as many values as there are vertices in the mesh.
[in] aName A unique name for this attribute map (zero terminated UTF-8 string).
-
-
-
Returns:
A attribute map index (CTM_ATTRIB_MAP_1 and higher). If the function failed, it will return the zero valued CTM_NONE (use ctmGetError() to determine the cause of the error).
-
Note:
A triangle mesh must have been defined before calling this function, since the number of vertices is defined by the triangle mesh.
-
See also:
ctmDefineMesh().
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CTMEXPORT CTMenum CTMCALL ctmAddUVMap (CTMcontext  aContext,
const CTMfloat aUVCoords,
const char *  aName,
const char *  aFileName 
)
-
-
- -

Define a UV map.

-

There can be several UV maps in a mesh. A UV map is typically used for 2D texture mapping.

-
Parameters:
- - - - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aUVCoords An array of UV coordinates. Each UV coordinate is made up by two consecutive floats, and there must be as many coordinates as there are vertices in the mesh.
[in] aName A unique name for this UV map (zero terminated UTF-8 string).
[in] aFileName A reference to a image file (zero terminated UTF-8 string). If no file name reference exists, pass NULL.
-
-
-
Returns:
A UV map index (CTM_UV_MAP_1 and higher). If the function failed, it will return the zero valued CTM_NONE (use ctmGetError() to determine the cause of the error).
-
Note:
A triangle mesh must have been defined before calling this function, since the number of vertices is defined by the triangle mesh.
-
See also:
ctmDefineMesh().
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmAttribPrecision (CTMcontext  aContext,
CTMenum  aAttribMap,
CTMfloat  aPrecision 
)
-
-
- -

Set the attribute value precision for the specified attribute map (only used by the MG2 compression method).

-
Parameters:
- - - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aAttribMap An attribute map specifier for a defined attribute map (CTM_ATTRIB_MAP_1, ...).
[in] aPrecision Fixed point precision. For instance, if this value is 0.001, all attribute values will be rounded to three decimals. If the attributes represent integer values, set the precision to 1.0. The default attribute precision is 2^-8 ~= 0.0039.
-
-
-
See also:
ctmAddAttribMap().
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmCompressionLevel (CTMcontext  aContext,
CTMuint  aLevel 
)
-
-
- -

Set which LZMA compression level to use for the given OpenCTM context.

-

The compression level can be between 0 (fastest) and 9 (best). The higher the compression level, the more memory is required for compression and decompression. The default compression level is 1.

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aLevel Which compression level to use (0 to 9).
-
-
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmCompressionMethod (CTMcontext  aContext,
CTMenum  aMethod 
)
-
-
- -

Set which compression method to use for the given OpenCTM context.

-

The selected compression method will be used when calling the ctmSave() function.

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aMethod Which compression method to use: CTM_METHOD_RAW, CTM_METHOD_MG1 or CTM_METHOD_MG2 (the default method is CTM_METHOD_MG1).
-
-
-
See also:
CTM_METHOD_RAW, CTM_METHOD_MG1, CTM_METHOD_MG2
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmDefineMesh (CTMcontext  aContext,
const CTMfloat aVertices,
CTMuint  aVertexCount,
const CTMuint aIndices,
CTMuint  aTriangleCount,
const CTMfloat aNormals 
)
-
-
- -

Define a triangle mesh.

-
Parameters:
- - - - - - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aVertices An array of vertices (three consecutive floats make one vertex).
[in] aVertexCount The number of vertices in aVertices (and optionally aTexCoords).
[in] aIndices An array of vertex indices (three consecutive integers make one triangle).
[in] aTriangleCount The number of triangles in aIndices (there must be exactly 3 x aTriangleCount indices in aIndices).
[in] aNormals An array of per-vertex normals (or NULL if there are no normals). Each normal is made up by three consecutive floats, and there must be aVertexCount normals.
-
-
-
See also:
ctmAddUVMap(), ctmAddAttribMap(), ctmSave(), ctmSaveCustom().
- -
-
- -
-
- - - - - - - - - -
CTMEXPORT const char* CTMCALL ctmErrorString (CTMenum  aError ) 
-
-
- -

Converts an OpenCTM error code to a zero-terminated string.

-
Parameters:
- - -
[in] aError An OpenCTM error code, as returned by ctmGetError().
-
-
-
Returns:
A zero terminated string that describes the error. For instance, if aError is CTM_INVALID_OPERATION, then the return value will be "CTM_INVALID_OPERATION".
-
See also:
CTMenum
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmFileComment (CTMcontext  aContext,
const char *  aFileComment 
)
-
-
- -

Set the file comment for the given OpenCTM context.

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aFileComment The file comment (zero terminated UTF-8 string).
-
-
- -
-
- -
-
- - - - - - - - - -
CTMEXPORT void CTMCALL ctmFreeContext (CTMcontext  aContext ) 
-
-
- -

Free an OpenCTM context.

-
Parameters:
- - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
-
-
-
See also:
ctmNewContext()
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
CTMEXPORT CTMfloat CTMCALL ctmGetAttribMapFloat (CTMcontext  aContext,
CTMenum  aAttribMap,
CTMenum  aProperty 
)
-
-
- -

Get information about a vertex attribute map.

-
Parameters:
- - - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aAttribMap Which vertex attribute map to query (CTM_ATTRIB_MAP_1 or higher).
[in] aProperty Which vertex attribute map property to return.
-
-
-
Returns:
A floating point value, representing the vertex attribute map property given by aProperty.
-
See also:
CTMenum
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
CTMEXPORT const char* CTMCALL ctmGetAttribMapString (CTMcontext  aContext,
CTMenum  aAttribMap,
CTMenum  aProperty 
)
-
-
- -

Get information about a vertex attribute map.

-
Parameters:
- - - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aAttribMap Which vertex attribute map to query (CTM_ATTRIB_MAP_1 or higher).
[in] aProperty Which vertex attribute map property to return.
-
-
-
Returns:
A string value, representing the vertex attribute map property given by aProperty.
-
Note:
The string is only valid as long as the vertex attribute map within the OpenCTM context is valid. Trying to access an invalid string will result in undefined behaviour. Therefor it is recommended that the string is copied to a new variable if it is to be used other than directly after the call to ctmGetAttribMapString().
-
See also:
CTMenum
- -
-
- -
-
- - - - - - - - - -
CTMEXPORT CTMenum CTMCALL ctmGetError (CTMcontext  aContext ) 
-
-
- -

Returns the latest error.

-

Calling this function will return the last produced error code, or CTM_NO_ERROR (zero) if no error has occured since the last call to ctmGetError(). When this function is called, the internal error varibale will be reset to CTM_NONE.

-
Parameters:
- - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
-
-
-
Returns:
An OpenCTM error code.
-
See also:
CTMenum
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT CTMfloat CTMCALL ctmGetFloat (CTMcontext  aContext,
CTMenum  aProperty 
)
-
-
- -

Get information about an OpenCTM context.

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aProperty Which property to return.
-
-
-
Returns:
A floating point value, representing the OpenCTM context property given by aProperty.
-
See also:
CTMenum
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT const CTMfloat* CTMCALL ctmGetFloatArray (CTMcontext  aContext,
CTMenum  aProperty 
)
-
-
- -

Get a floating point array from an OpenCTM context.

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aProperty Which array to return.
-
-
-
Returns:
A floating point array. If the requested array does not exist, or if aProperty does not indicate a float array, the function returns NULL.
-
Note:
The array is only valid as long as the OpenCTM context is valid, or until the corresponding array changes within the OpenCTM context. Trying to access an invalid array will result in undefined behaviour. Therefor it is recommended that the array is copied to a new variable if it is to be used other than directly after the call to ctmGetFloatArray().
-
See also:
CTMenum
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT CTMuint CTMCALL ctmGetInteger (CTMcontext  aContext,
CTMenum  aProperty 
)
-
-
- -

Get information about an OpenCTM context.

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aProperty Which property to return.
-
-
-
Returns:
An integer value, representing the OpenCTM context property given by aProperty.
-
See also:
CTMenum
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT const CTMuint* CTMCALL ctmGetIntegerArray (CTMcontext  aContext,
CTMenum  aProperty 
)
-
-
- -

Get an integer array from an OpenCTM context.

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aProperty Which array to return.
-
-
-
Returns:
An integer array. If the requested array does not exist, or if aProperty does not indicate an integer array, the function returns NULL.
-
Note:
The array is only valid as long as the OpenCTM context is valid, or until the corresponding array changes within the OpenCTM context. Trying to access an invalid array will result in undefined behaviour. Therefor it is recommended that the array is copied to a new variable if it is to be used other than directly after the call to ctmGetIntegerArray().
-
See also:
CTMenum
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT CTMenum CTMCALL ctmGetNamedAttribMap (CTMcontext  aContext,
const char *  aName 
)
-
-
- -

Get a reference to the named vertex attribute map.

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aName The name of the attribute map that should be returned.
-
-
-
Returns:
A reference to an attribute map. If the attribute map was found, a value of CTM_ATTRIB_MAP_1 or higher is returned, otherwise CTM_NONE is returned.
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT CTMenum CTMCALL ctmGetNamedUVMap (CTMcontext  aContext,
const char *  aName 
)
-
-
- -

Get a reference to the named UV map.

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aName The name of the UV map that should be returned.
-
-
-
Returns:
A reference to a UV map. If the UV map was found, a value of CTM_UV_MAP_1 or higher is returned, otherwise CTM_NONE is returned.
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT const char* CTMCALL ctmGetString (CTMcontext  aContext,
CTMenum  aProperty 
)
-
-
- -

Get information about an OpenCTM context.

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aProperty Which property to return.
-
-
-
Returns:
A string value, representing the OpenCTM context property given by aProperty.
-
Note:
The string is only valid as long as the OpenCTM context is valid, or until the corresponding string changes within the OpenCTM context (e.g. calling ctmFileComment() invalidates the CTM_FILE_COMMENT string). Trying to access an invalid string will result in undefined behaviour. Therefor it is recommended that the string is copied to a new variable if it is to be used other than directly after the call to ctmGetString().
-
See also:
CTMenum
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
CTMEXPORT CTMfloat CTMCALL ctmGetUVMapFloat (CTMcontext  aContext,
CTMenum  aUVMap,
CTMenum  aProperty 
)
-
-
- -

Get information about a UV map.

-
Parameters:
- - - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aUVMap Which UV map to query (CTM_UV_MAP_1 or higher).
[in] aProperty Which UV map property to return.
-
-
-
Returns:
A floating point value, representing the UV map property given by aProperty.
-
See also:
CTMenum
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
CTMEXPORT const char* CTMCALL ctmGetUVMapString (CTMcontext  aContext,
CTMenum  aUVMap,
CTMenum  aProperty 
)
-
-
- -

Get information about a UV map.

-
Parameters:
- - - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aUVMap Which UV map to query (CTM_UV_MAP_1 or higher).
[in] aProperty Which UV map property to return.
-
-
-
Returns:
A string value, representing the UV map property given by aProperty.
-
Note:
The string is only valid as long as the UV map within the OpenCTM context is valid. Trying to access an invalid string will result in undefined behaviour. Therefor it is recommended that the string is copied to a new variable if it is to be used other than directly after the call to ctmGetUVMapString().
-
See also:
CTMenum
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmLoad (CTMcontext  aContext,
const char *  aFileName 
)
-
-
- -

Load an OpenCTM format file into the context.

-

The mesh data can be retrieved with the various ctmGet functions.

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aFileName The name of the file to be loaded.
-
-
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmLoadCustom (CTMcontext  aContext,
CTMreadfn  aReadFn,
void *  aUserData 
)
-
-
- -

Load an OpenCTM format file using a custom stream read function.

-

The mesh data can be retrieved with the various ctmGet functions.

-
Parameters:
- - - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aReadFn Pointer to a custom stream read function.
[in] aUserData Custom user data, which can be a C language FILE handle, C++ istream object, or a custom object pointer of any type. The user data pointer will be passed to the custom stream read function.
-
-
-
See also:
CTMreadfn.
- -
-
- -
-
- - - - - - - - - -
CTMEXPORT CTMcontext CTMCALL ctmNewContext (CTMenum  aMode ) 
-
-
- -

Create a new OpenCTM context.

-

The context is used for all subsequent OpenCTM function calls. Several contexts can coexist at the same time.

-
Parameters:
- - -
[in] aMode An OpenCTM context mode. Set this to CTM_IMPORT if the context will be used for importing data, or set it to CTM_EXPORT if it will be used for exporting data.
-
-
-
Returns:
An OpenCTM context handle (or NULL if no context could be created).
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmNormalPrecision (CTMcontext  aContext,
CTMfloat  aPrecision 
)
-
-
- -

Set the normal precision (only used by the MG2 compression method).

-

The normal is represented in spherical coordinates in the MG2 compression method, and the normal precision controls the angular and radial resolution.

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aPrecision Fixed point precision. For the angular information, this value represents the angular precision. For the radial information, this value is the linear resolution. For instance, 0.01 means that the circle is divided into 100 steps, and the normal magnitude is rounded to 2 decimals. The default normal precision is 2^-8 ~= 0.0039.
-
-
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmSave (CTMcontext  aContext,
const char *  aFileName 
)
-
-
- -

Save an OpenCTM format file.

-

The mesh must have been defined by ctmDefineMesh().

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aFileName The name of the file to be saved.
-
-
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmSaveCustom (CTMcontext  aContext,
CTMwritefn  aWriteFn,
void *  aUserData 
)
-
-
- -

Save an OpenCTM format file using a custom stream write function.

-

The mesh must have been defined by ctmDefineMesh().

-
Parameters:
- - - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aWriteFn Pointer to a custom stream write function.
[in] aUserData Custom user data, which can be a C language FILE handle, C++ ostream object, or a custom object pointer of any type. The user data pointer will be passed to the custom stream write function.
-
-
-
See also:
CTMwritefn.
- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmUVCoordPrecision (CTMcontext  aContext,
CTMenum  aUVMap,
CTMfloat  aPrecision 
)
-
-
- -

Set the coordinate precision for the specified UV map (only used by the MG2 compression method).

-
Parameters:
- - - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aUVMap A UV map specifier for a defined UV map (CTM_UV_MAP_1, ...).
[in] aPrecision Fixed point precision. For instance, if this value is 0.001, all UV coordinates will be rounded to three decimals. The default UV coordinate precision is 2^-12 ~= 0.00024.
-
-
-
See also:
ctmAddUVMap().
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmVertexPrecision (CTMcontext  aContext,
CTMfloat  aPrecision 
)
-
-
- -

Set the vertex coordinate precision (only used by the MG2 compression method).

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aPrecision Fixed point precision. For instance, if this value is 0.001, all vertex coordinates will be rounded to three decimals. The default vertex coordinate precision is 2^-10 ~= 0.00098.
-
-
- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
CTMEXPORT void CTMCALL ctmVertexPrecisionRel (CTMcontext  aContext,
CTMfloat  aRelPrecision 
)
-
-
- -

Set the vertex coordinate precision, relative to the mesh dimensions (only used by the MG2 compression method).

-
Parameters:
- - - -
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aRelPrecision Relative precision. This factor is multiplied by the average triangle edge length in the mesh in order to obtain the final, fixed point precision. For instance, if aRelPrecision is 0.01, and the average edge length is 3.7, then the fixed point precision is set to 0.037.
-
-
-
Note:
The mesh must have been defined using the ctmDefineMesh() function before calling this function.
-
See also:
ctmVertexPrecision().
- -
-
-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/openctm_8h_source.html b/src/external/OpenCTM-1.0.3/doc/APIReference/openctm_8h_source.html deleted file mode 100644 index 740225adf..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/openctm_8h_source.html +++ /dev/null @@ -1,287 +0,0 @@ - - - - -OpenCTM: openctm.h Source File - - - - - - -
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/openctmpp_8h.html b/src/external/OpenCTM-1.0.3/doc/APIReference/openctmpp_8h.html deleted file mode 100644 index fc52a74d6..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/openctmpp_8h.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - -OpenCTM: openctmpp.h File Reference - - - - - - -
-

openctmpp.h File Reference

#include "openctm.h"
-#include <exception>
- -

Go to the source code of this file.

- - - - - - - - -

Classes

class  ctm_error
 OpenCTM exception. More...
class  CTMimporter
 OpenCTM importer class. More...
class  CTMexporter
 OpenCTM exporter class. More...
-
-
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/openctmpp_8h_source.html b/src/external/OpenCTM-1.0.3/doc/APIReference/openctmpp_8h_source.html deleted file mode 100644 index 24c8c2703..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/openctmpp_8h_source.html +++ /dev/null @@ -1,333 +0,0 @@ - - - - -OpenCTM: openctmpp.h Source File - - - - - - -
-

Copyright © 2009-2010 Marcus Geelnard — - openctm.sourceforge.net

-
- - diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/tab_b.gif b/src/external/OpenCTM-1.0.3/doc/APIReference/tab_b.gif deleted file mode 100644 index 0d623483f..000000000 Binary files a/src/external/OpenCTM-1.0.3/doc/APIReference/tab_b.gif and /dev/null differ diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/tab_l.gif b/src/external/OpenCTM-1.0.3/doc/APIReference/tab_l.gif deleted file mode 100644 index 9b1e6337c..000000000 Binary files a/src/external/OpenCTM-1.0.3/doc/APIReference/tab_l.gif and /dev/null differ diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/tab_r.gif b/src/external/OpenCTM-1.0.3/doc/APIReference/tab_r.gif deleted file mode 100644 index ce9dd9f53..000000000 Binary files a/src/external/OpenCTM-1.0.3/doc/APIReference/tab_r.gif and /dev/null differ diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/tabs.css b/src/external/OpenCTM-1.0.3/doc/APIReference/tabs.css deleted file mode 100644 index a44416341..000000000 --- a/src/external/OpenCTM-1.0.3/doc/APIReference/tabs.css +++ /dev/null @@ -1,105 +0,0 @@ -/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */ - -DIV.tabs -{ - float : left; - width : 100%; - background : url("tab_b.gif") repeat-x bottom; - margin-bottom : 4px; -} - -DIV.tabs UL -{ - margin : 0px; - padding-left : 10px; - list-style : none; -} - -DIV.tabs LI, DIV.tabs FORM -{ - display : inline; - margin : 0px; - padding : 0px; -} - -DIV.tabs FORM -{ - float : right; -} - -DIV.tabs A -{ - float : left; - background : url("tab_r.gif") no-repeat right top; - border-bottom : 1px solid #84B0C7; - font-size : 80%; - font-weight : bold; - text-decoration : none; -} - -DIV.tabs A:hover -{ - background-position: 100% -150px; -} - -DIV.tabs A:link, DIV.tabs A:visited, -DIV.tabs A:active, DIV.tabs A:hover -{ - color: #1A419D; -} - -DIV.tabs SPAN -{ - float : left; - display : block; - background : url("tab_l.gif") no-repeat left top; - padding : 5px 9px; - white-space : nowrap; -} - -DIV.tabs #MSearchBox -{ - float : right; - display : inline; - font-size : 1em; -} - -DIV.tabs TD -{ - font-size : 80%; - font-weight : bold; - text-decoration : none; -} - - - -/* Commented Backslash Hack hides rule from IE5-Mac \*/ -DIV.tabs SPAN {float : none;} -/* End IE5-Mac hack */ - -DIV.tabs A:hover SPAN -{ - background-position: 0% -150px; -} - -DIV.tabs LI.current A -{ - background-position: 100% -150px; - border-width : 0px; -} - -DIV.tabs LI.current SPAN -{ - background-position: 0% -150px; - padding-bottom : 6px; -} - -DIV.navpath -{ - background : none; - border : none; - border-bottom : 1px solid #84B0C7; - text-align : center; - margin : 2px; - padding : 2px; -} diff --git a/src/external/OpenCTM-1.0.3/doc/DevelopersManual.pdf b/src/external/OpenCTM-1.0.3/doc/DevelopersManual.pdf deleted file mode 100644 index d280b66f6..000000000 Binary files a/src/external/OpenCTM-1.0.3/doc/DevelopersManual.pdf and /dev/null differ diff --git a/src/external/OpenCTM-1.0.3/doc/FormatSpecification.pdf b/src/external/OpenCTM-1.0.3/doc/FormatSpecification.pdf deleted file mode 100644 index fa8ce84c8..000000000 Binary files a/src/external/OpenCTM-1.0.3/doc/FormatSpecification.pdf and /dev/null differ diff --git a/src/external/OpenCTM-1.0.3/doc/ctmconv.1 b/src/external/OpenCTM-1.0.3/doc/ctmconv.1 deleted file mode 100644 index ad76f0745..000000000 --- a/src/external/OpenCTM-1.0.3/doc/ctmconv.1 +++ /dev/null @@ -1,92 +0,0 @@ -.TH ctmconv 1 -.SH NAME -.B ctmconv -- file format converter for 3D models -.SH SYNOPSIS -.B ctmconv -.I infile outfile [options] -.SH DESCRIPTION -.B ctmconv -is a 3D file converter that can convert 3D model files to and from several -different formats. -.PP -The file -.I infile -is loaded, and then saved as -.I outfile -in the target file format. -.PP -The input and output file formats are determined from the file endings. -.SH OPTIONS -The following options are available: -.TP 16 -.B --scale arg -Scale the mesh by a scalar factor. -.TP -.B --upaxis arg -Set up axis (X, Y, Z, -X, -Y, -Z). If != Z, the mesh will be flipped. -.TP -.B --flip -Flip triangle orientation. -.TP -.B --calc-normals -If the source file does not contain any normals, calculate them. -.TP -.B --no-normals -Do not export normals. -.TP -.B --no-texcoords -Do not export texture coordinates. -.TP -.B --no-colors -Do not export vertex colors. -.TP -.B --comment arg -Set the file comment (default is to use the comment from the input file, if -any). -.TP -.B --texfile arg -Set the texture file name reference for the texture (default is to use the -texture file name reference from the input file, if any). -.PP -When exporting an OpenCTM file, the following options are also -available: -.TP 16 -.B --method arg -Select compression method (RAW, MG1, MG2). -.TP -.B --level arg -Set the compression level (0 - 9). -.TP -.B --vprec arg -Set vertex precision (only for MG2). -.TP -.B --vprecrel arg -Set vertex precision, relative method (only for MG2). -.TP -.B --nprec arg -Set normal precision (only for MG2). -.TP -.B --tprec arg -Set texture map precision (only for MG2). -.TP -.B --cprec arg -Set color precision (only for MG2). -.SH FILE FORMATS -The following 3D model file formats are supported: -OpenCTM (.ctm), -Stanford triangle format (.ply), -Stereolitography (.stl), -3D Studio (.3ds), -COLLADA 1.4/1.5 (.dae), -Wavefront geometry file (.obj), -LightWave object (.lwo), -Geomview object file format (.off), -VRML 2.0 - export only (.wrl). -.SH AVAILABILITY -.B ctmconv -is designed to be portable, and is available for several different systems, -including (but not limited to): Windows, Mac OS X (10.3+), Linux and -OpenSolaris. -.SH SEE ALSO -ctmviewer(1) diff --git a/src/external/OpenCTM-1.0.3/doc/ctmviewer.1 b/src/external/OpenCTM-1.0.3/doc/ctmviewer.1 deleted file mode 100644 index d06dce48d..000000000 --- a/src/external/OpenCTM-1.0.3/doc/ctmviewer.1 +++ /dev/null @@ -1,86 +0,0 @@ -.TH ctmviewer 1 -.SH NAME -.B ctmviewer -- 3D viewer for models of various file formats -.SH SYNOPSIS -.B ctmviewer -.I [modelfile [texturefile]] -.SH DESCRIPTION -.B ctmviewer -is a 3D file viewer that can load, show and save 3D model files in several -different formats. -.PP -The program displays an interactive 3D view of the model, which can be operated -with the mouse (e.g. for rotating and zooming). -.PP -If the selected model file contains texture coordinate information, it is -possible to specify which 2D image file to use as a texture with the additional -.I texturefile -argument. If no texture file is given (either by the 3D model file, or by the -.I texturefile -argument), a standard 2D grid is used as a texture. -.SH GUI OPERATIONS -In addition to the command line arguments, -.B ctmviewer -offers several operations that can be performed from the 3D GUI display. For -help, press the F1 key. -.SS Loading and Saving -It is possible to load and save 3D model files from the program by either -using the buttons in the upper left corner of the 3D display, or by using the -keyboard shortcuts CTRL+O (open) and CTRL+S (save). -.PP -It is also possible to load a texture file from the program by using the -Open Texture button. -.SS Rendering -To toggle between a normal filled surface view (default) and a wire frame view, -press the 'w' key. -.SS Camera Control -By holding down the left mouse button and moving the mouse, the camera is -rotated around the 3D model. -.PP -By holding down the right mouse button and moving the mouse, the camera will -pan left/right and up/down. -.PP -By holding down the middle mouse button and moving the mouse, the camera will -zoom in and out. It is also possible to use the mouse wheel (not supported on -all systems) or the +/- keys to zoom in and out. -.PP -Double click the left mouse button on a point on the model to focus the camera -on that point. -.PP -Press the 'f' key to fit the model into the screen view (re-center and re-zoom). -.PP -Press the 'y' key to change the camera up direction to the Y axis (may be -necessary if the model was designed in or for an environment where the Y axis -is considered the up direction). -.PP -Press the 'z' key to change the camera up direction to the Z axis (default). -.SH FILE FORMATS -The following 3D model file formats are supported: -OpenCTM (.ctm), -Stanford triangle format (.ply), -Stereolitography (.stl), -3D Studio (.3ds), -COLLADA 1.4/1.5 (.dae), -Wavefront geometry file (.obj), -LightWave object (.lwo), -Geomview object file format (.off), -VRML 2.0 - export only (.wrl). -.PP -The following 2D image file formats are supported (texture): -JPEG (.jpg), PNG (.png). -.SH AVAILABILITY -.B ctmviewer -is designed to be portable, and is available for several different systems, -including (but not limited to): Windows, Mac OS X (10.3+), Linux and -OpenSolaris. -.PP -.B ctmviewer -uses OpenGL for its accelerated 3D display. When the OpenGL implementation -supports it, -.B ctmviewer -will use per pixel Phong shading for improved visual appearance. Otherwise -.B ctmviewer -will fall back to classic per vertex shading. -.SH SEE ALSO -ctmconv(1) diff --git a/src/external/OpenCTM-1.0.3/lib/Makefile.linux b/src/external/OpenCTM-1.0.3/lib/Makefile.linux deleted file mode 100644 index 9e270e517..000000000 --- a/src/external/OpenCTM-1.0.3/lib/Makefile.linux +++ /dev/null @@ -1,81 +0,0 @@ -############################################################################### -# Product: OpenCTM -# File: Makefile.linux -# Description: Makefile for Linux systems (should work on most Un*x-like -# systems with gcc, e.g. OpenSolaris). -############################################################################### -# Copyright (c) 2009-2010 Marcus Geelnard -# -# This software is provided 'as-is', without any express or implied -# warranty. In no event will the authors be held liable for any damages -# arising from the use of this software. -# -# Permission is granted to anyone to use this software for any purpose, -# including commercial applications, and to alter it and redistribute it -# freely, subject to the following restrictions: -# -# 1. The origin of this software must not be misrepresented; you must not -# claim that you wrote the original software. If you use this software -# in a product, an acknowledgment in the product documentation would be -# appreciated but is not required. -# -# 2. Altered source versions must be plainly marked as such, and must not -# be misrepresented as being the original software. -# -# 3. This notice may not be removed or altered from any source -# distribution. -############################################################################### - -LZMADIR = liblzma -CC = gcc -CFLAGS = -O3 -W -Wall -c -fPIC -DOPENCTM_BUILD -I$(LZMADIR) -DLZMA_PREFIX_CTM -std=c99 -pedantic -CFLAGS_LZMA = -O3 -W -Wall -c -fPIC -DLZMA_PREFIX_CTM -std=c99 -pedantic -RM = rm -f -DEPEND = $(CPP) -MM - -DYNAMICLIB = libopenctm.so - -OBJS = openctm.o \ - stream.o \ - compressRAW.o \ - compressMG1.o \ - compressMG2.o - -LZMA_OBJS = Alloc.o \ - LzFind.o \ - LzmaDec.o \ - LzmaEnc.o \ - LzmaLib.o - -SRCS = openctm.c \ - stream.c \ - compressRAW.c \ - compressMG1.c \ - compressMG2.c - -LZMA_SRCS = $(LZMADIR)/Alloc.c \ - $(LZMADIR)/LzFind.c \ - $(LZMADIR)/LzmaDec.c \ - $(LZMADIR)/LzmaEnc.c \ - $(LZMADIR)/LzmaLib.c - -.phony: all clean depend - -all: $(DYNAMICLIB) - -clean: - $(RM) $(DYNAMICLIB) $(OBJS) $(LZMA_OBJS) - -$(DYNAMICLIB): $(OBJS) $(LZMA_OBJS) - gcc -shared -s -Wl,-soname,$@ -o $@ $(OBJS) $(LZMA_OBJS) -lm - -%.o: %.c - $(CC) $(CFLAGS) $< - -%.o: $(LZMADIR)/%.c - $(CC) $(CFLAGS_LZMA) $< - -depend: - $(DEPEND) $(SRCS) $(LZMA_SRCS) > make.depend - --include make.depend diff --git a/src/external/OpenCTM-1.0.3/lib/Makefile.macosx b/src/external/OpenCTM-1.0.3/lib/Makefile.macosx deleted file mode 100644 index d1685a0c6..000000000 --- a/src/external/OpenCTM-1.0.3/lib/Makefile.macosx +++ /dev/null @@ -1,86 +0,0 @@ -############################################################################### -# Product: OpenCTM -# File: Makefile.macosx -# Description: Makefile for Mac OS X. -############################################################################### -# Copyright (c) 2009-2010 Marcus Geelnard -# -# This software is provided 'as-is', without any express or implied -# warranty. In no event will the authors be held liable for any damages -# arising from the use of this software. -# -# Permission is granted to anyone to use this software for any purpose, -# including commercial applications, and to alter it and redistribute it -# freely, subject to the following restrictions: -# -# 1. The origin of this software must not be misrepresented; you must not -# claim that you wrote the original software. If you use this software -# in a product, an acknowledgment in the product documentation would be -# appreciated but is not required. -# -# 2. Altered source versions must be plainly marked as such, and must not -# be misrepresented as being the original software. -# -# 3. This notice may not be removed or altered from any source -# distribution. -############################################################################### - -LZMADIR = liblzma -CC = gcc -CFLAGS = -arch i386 -O3 -W -Wall -c -fvisibility=hidden -DOPENCTM_BUILD -I$(LZMADIR) -DLZMA_PREFIX_CTM -std=c99 -pedantic -CFLAGS_LZMA = -arch i386 -O3 -W -Wall -c -fvisibility=hidden -DLZMA_PREFIX_CTM -std=c99 -pedantic -RM = rm -f -DEPEND = $(CPP) -MM - -DYNAMICLIB = libopenctm.dylib -STATICLIB = libopenctm.a - - -OBJS = openctm.o \ - stream.o \ - compressRAW.o \ - compressMG1.o \ - compressMG2.o - -LZMA_OBJS = Alloc.o \ - LzFind.o \ - LzmaDec.o \ - LzmaEnc.o \ - LzmaLib.o - -SRCS = openctm.c \ - stream.c \ - compressRAW.c \ - compressMG1.c \ - compressMG2.c - -LZMA_SRCS = $(LZMADIR)/Alloc.c \ - $(LZMADIR)/LzFind.c \ - $(LZMADIR)/LzmaDec.c \ - $(LZMADIR)/LzmaEnc.c \ - $(LZMADIR)/LzmaLib.c - -.phony: all clean depend - -#all: $(DYNAMICLIB) -all: $(STATICLIB) - -clean: - $(RM) $(DYNAMICLIB) $(OBJS) $(LZMA_OBJS) - -$(DYNAMICLIB): $(OBJS) $(LZMA_OBJS) - gcc -dynamiclib -o $@ $(OBJS) $(LZMA_OBJS) - -$(STATICLIB): $(OBJS) $(LZMA_OBJS) - ar rcs $@ $(OBJS) $(LZMA_OBJS) - -%.o: %.c - $(CC) $(CFLAGS) $< - -%.o: $(LZMADIR)/%.c - $(CC) $(CFLAGS_LZMA) $< - -depend: - $(DEPEND) $(SRCS) $(LZMA_SRCS) > make.depend - --include make.depend diff --git a/src/external/OpenCTM-1.0.3/lib/Makefile.mingw b/src/external/OpenCTM-1.0.3/lib/Makefile.mingw deleted file mode 100644 index 8606be77e..000000000 --- a/src/external/OpenCTM-1.0.3/lib/Makefile.mingw +++ /dev/null @@ -1,87 +0,0 @@ -############################################################################### -# Product: OpenCTM -# File: Makefile.mingw -# Description: Makefile for MinGW32 for Windows. -############################################################################### -# Copyright (c) 2009-2010 Marcus Geelnard -# -# This software is provided 'as-is', without any express or implied -# warranty. In no event will the authors be held liable for any damages -# arising from the use of this software. -# -# Permission is granted to anyone to use this software for any purpose, -# including commercial applications, and to alter it and redistribute it -# freely, subject to the following restrictions: -# -# 1. The origin of this software must not be misrepresented; you must not -# claim that you wrote the original software. If you use this software -# in a product, an acknowledgment in the product documentation would be -# appreciated but is not required. -# -# 2. Altered source versions must be plainly marked as such, and must not -# be misrepresented as being the original software. -# -# 3. This notice may not be removed or altered from any source -# distribution. -############################################################################### - -LZMADIR = liblzma -CC = gcc -CFLAGS = -O3 -W -Wall -c -DOPENCTM_BUILD -I$(LZMADIR) -DLZMA_PREFIX_CTM -std=c99 -pedantic -CFLAGS_LZMA = -O3 -W -Wall -c -DLZMA_PREFIX_CTM -std=c99 -pedantic -RM = del /Q -DEPEND = $(CC) -MM -RC = windres - -DYNAMICLIB = openctm.dll -LINKLIB = libopenctm.a - -OBJS = openctm.o \ - stream.o \ - compressRAW.o \ - compressMG1.o \ - compressMG2.o - -LZMA_OBJS = Alloc.o \ - LzFind.o \ - LzmaDec.o \ - LzmaEnc.o \ - LzmaLib.o - -SRCS = openctm.c \ - stream.c \ - compressRAW.c \ - compressMG1.c \ - compressMG2.c - -LZMA_SRCS = $(LZMADIR)/Alloc.c \ - $(LZMADIR)/LzFind.c \ - $(LZMADIR)/LzmaDec.c \ - $(LZMADIR)/LzmaEnc.c \ - $(LZMADIR)/LzmaLib.c - -.phony: all clean depend - -all: $(DYNAMICLIB) - -clean: - $(RM) $(DYNAMICLIB) $(LINKLIB) $(OBJS) $(LZMA_OBJS) openctm-res.o - -$(DYNAMICLIB): $(OBJS) $(LZMA_OBJS) openctm-mingw1.def openctm-mingw2.def openctm-res.o - dllwrap --def openctm-mingw1.def -o $@ $(OBJS) $(LZMA_OBJS) openctm-res.o - strip $@ - dlltool --kill-at --output-lib $(LINKLIB) --def openctm-mingw2.def - -openctm-res.o: openctm.rc - $(RC) $< $@ - -%.o: %.c - $(CC) $(CFLAGS) $< - -%.o: $(LZMADIR)/%.c - $(CC) $(CFLAGS_LZMA) $< - -depend: - $(DEPEND) $(SRCS) $(LZMA_SRCS) > make.depend - --include make.depend diff --git a/src/external/OpenCTM-1.0.3/lib/Makefile.msvc b/src/external/OpenCTM-1.0.3/lib/Makefile.msvc deleted file mode 100644 index 70818d553..000000000 --- a/src/external/OpenCTM-1.0.3/lib/Makefile.msvc +++ /dev/null @@ -1,103 +0,0 @@ -############################################################################### -# Product: OpenCTM -# File: Makefile.msvc -# Description: Makefile for MS Visual Studio 2008 for Windows. -############################################################################### -# Copyright (c) 2009-2010 Marcus Geelnard -# -# This software is provided 'as-is', without any express or implied -# warranty. In no event will the authors be held liable for any damages -# arising from the use of this software. -# -# Permission is granted to anyone to use this software for any purpose, -# including commercial applications, and to alter it and redistribute it -# freely, subject to the following restrictions: -# -# 1. The origin of this software must not be misrepresented; you must not -# claim that you wrote the original software. If you use this software -# in a product, an acknowledgment in the product documentation would be -# appreciated but is not required. -# -# 2. Altered source versions must be plainly marked as such, and must not -# be misrepresented as being the original software. -# -# 3. This notice may not be removed or altered from any source -# distribution. -############################################################################### - -LZMADIR = liblzma -CC = cl -CFLAGS = /nologo /Ox /W3 /c /DOPENCTM_BUILD /I$(LZMADIR) /DLZMA_PREFIX_CTM /D_CRT_SECURE_NO_WARNINGS -CFLAGS_LZMA = /nologo /Ox /W3 /c /DLZMA_PREFIX_CTM -RM = del /Q -RC = rc - -DYNAMICLIB = openctm.dll -LINKLIB = openctm.lib - -OBJS = openctm.obj \ - stream.obj \ - compressRAW.obj \ - compressMG1.obj \ - compressMG2.obj - -LZMA_OBJS = Alloc.obj \ - LzFind.obj \ - LzmaDec.obj \ - LzmaEnc.obj \ - LzmaLib.obj - -SRCS = openctm.c \ - stream.c \ - compressRAW.c \ - compressMG1.c \ - compressMG2.c - -LZMA_SRCS = $(LZMADIR)\Alloc.c \ - $(LZMADIR)\LzFind.c \ - $(LZMADIR)\LzmaDec.c \ - $(LZMADIR)\LzmaEnc.c \ - $(LZMADIR)\LzmaLib.c - -all: $(DYNAMICLIB) - -.PHONY: clean - -clean: - $(RM) $(DYNAMICLIB) $(LINKLIB) $(OBJS) $(LZMA_OBJS) openctm.res - -$(DYNAMICLIB): $(OBJS) $(LZMA_OBJS) openctm-msvc.def openctm.res - link /nologo /out:$@ /dll /implib:$(LINKLIB) /def:openctm-msvc.def $(OBJS) $(LZMA_OBJS) openctm.res - -openctm.res: openctm.rc - $(RC) openctm.rc - -openctm.obj: openctm.c openctm.h internal.h - $(CC) $(CFLAGS) openctm.c - -stream.obj: stream.c openctm.h internal.h - $(CC) $(CFLAGS) stream.c - -compressRAW.obj: compressRAW.c openctm.h internal.h - $(CC) $(CFLAGS) compressRAW.c - -compressMG1.obj: compressMG1.c openctm.h internal.h - $(CC) $(CFLAGS) compressMG1.c - -compressMG2.obj: compressMG2.c openctm.h internal.h - $(CC) $(CFLAGS) compressMG2.c - -Alloc.obj: $(LZMADIR)\Alloc.c $(LZMADIR)\Alloc.h - $(CC) $(CFLAGS_LZMA) $(LZMADIR)\Alloc.c - -LzFind.obj: $(LZMADIR)\LzFind.c $(LZMADIR)\LzFind.h $(LZMADIR)\Types.h $(LZMADIR)\LzHash.h $(LZMADIR)\NameMangle.h - $(CC) $(CFLAGS_LZMA) $(LZMADIR)\LzFind.c - -LzmaDec.obj: $(LZMADIR)\LzmaDec.c $(LZMADIR)\LzmaDec.h $(LZMADIR)\Types.h $(LZMADIR)\NameMangle.h - $(CC) $(CFLAGS_LZMA) $(LZMADIR)\LzmaDec.c - -LzmaEnc.obj: $(LZMADIR)\LzmaEnc.c $(LZMADIR)\LzmaEnc.h $(LZMADIR)\Types.h $(LZMADIR)\LzFind.h $(LZMADIR)\NameMangle.h - $(CC) $(CFLAGS_LZMA) $(LZMADIR)\LzmaEnc.c - -LzmaLib.obj: $(LZMADIR)\LzmaLib.c $(LZMADIR)\LzmaEnc.h $(LZMADIR)\Types.h $(LZMADIR)\LzmaDec.h $(LZMADIR)\Alloc.h $(LZMADIR)\LzmaLib.h $(LZMADIR)\NameMangle.h - $(CC) $(CFLAGS_LZMA) $(LZMADIR)\LzmaLib.c diff --git a/src/external/OpenCTM-1.0.3/lib/compressMG1.c b/src/external/OpenCTM-1.0.3/lib/compressMG1.c deleted file mode 100644 index e4ca1b747..000000000 --- a/src/external/OpenCTM-1.0.3/lib/compressMG1.c +++ /dev/null @@ -1,324 +0,0 @@ -//----------------------------------------------------------------------------- -// Product: OpenCTM -// File: compressMG1.c -// Description: Implementation of the MG1 compression method. -//----------------------------------------------------------------------------- -// Copyright (c) 2009-2010 Marcus Geelnard -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -//----------------------------------------------------------------------------- - -#include -#include -#include "openctm.h" -#include "internal.h" - -#ifdef __DEBUG_ -#include -#endif - - -//----------------------------------------------------------------------------- -// _compareTriangle() - Comparator for the triangle sorting. -//----------------------------------------------------------------------------- -static int _compareTriangle(const void * elem1, const void * elem2) -{ - CTMuint * tri1 = (CTMuint *) elem1; - CTMuint * tri2 = (CTMuint *) elem2; - if(tri1[0] != tri2[0]) - return tri1[0] - tri2[0]; - else - return tri1[1] - tri2[1]; -} - -//----------------------------------------------------------------------------- -// _ctmReArrangeTriangles() - Re-arrange all triangles for optimal -// compression. -//----------------------------------------------------------------------------- -static void _ctmReArrangeTriangles(_CTMcontext * self, CTMuint * aIndices) -{ - CTMuint * tri, tmp, i; - - // Step 1: Make sure that the first index of each triangle is the smallest - // one (rotate triangle nodes if necessary) - for(i = 0; i < self->mTriangleCount; ++ i) - { - tri = &aIndices[i * 3]; - if((tri[1] < tri[0]) && (tri[1] < tri[2])) - { - tmp = tri[0]; - tri[0] = tri[1]; - tri[1] = tri[2]; - tri[2] = tmp; - } - else if((tri[2] < tri[0]) && (tri[2] < tri[1])) - { - tmp = tri[0]; - tri[0] = tri[2]; - tri[2] = tri[1]; - tri[1] = tmp; - } - } - - // Step 2: Sort the triangles based on the first triangle index - qsort((void *) aIndices, self->mTriangleCount, sizeof(CTMuint) * 3, _compareTriangle); -} - -//----------------------------------------------------------------------------- -// _ctmMakeIndexDeltas() - Calculate various forms of derivatives in order to -// reduce data entropy. -//----------------------------------------------------------------------------- -static void _ctmMakeIndexDeltas(_CTMcontext * self, CTMuint * aIndices) -{ - CTMint i; - for(i = self->mTriangleCount - 1; i >= 0; -- i) - { - // Step 1: Calculate delta from second triangle index to the previous - // second triangle index, if the previous triangle shares the same first - // index, otherwise calculate the delta to the first triangle index - if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3])) - aIndices[i * 3 + 1] -= aIndices[(i - 1) * 3 + 1]; - else - aIndices[i * 3 + 1] -= aIndices[i * 3]; - - // Step 2: Calculate delta from third triangle index to the first triangle - // index - aIndices[i * 3 + 2] -= aIndices[i * 3]; - - // Step 3: Calculate derivative of the first triangle index - if(i >= 1) - aIndices[i * 3] -= aIndices[(i - 1) * 3]; - } -} - -//----------------------------------------------------------------------------- -// _ctmRestoreIndices() - Restore original indices (inverse derivative -// operation). -//----------------------------------------------------------------------------- -static void _ctmRestoreIndices(_CTMcontext * self, CTMuint * aIndices) -{ - CTMuint i; - - for(i = 0; i < self->mTriangleCount; ++ i) - { - // Step 1: Reverse derivative of the first triangle index - if(i >= 1) - aIndices[i * 3] += aIndices[(i - 1) * 3]; - - // Step 2: Reverse delta from third triangle index to the first triangle - // index - aIndices[i * 3 + 2] += aIndices[i * 3]; - - // Step 3: Reverse delta from second triangle index to the previous - // second triangle index, if the previous triangle shares the same first - // index, otherwise reverse the delta to the first triangle index - if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3])) - aIndices[i * 3 + 1] += aIndices[(i - 1) * 3 + 1]; - else - aIndices[i * 3 + 1] += aIndices[i * 3]; - } -} - -//----------------------------------------------------------------------------- -// _ctmCompressMesh_MG1() - Compress the mesh that is stored in the CTM -// context, and write it the the output stream in the CTM context. -//----------------------------------------------------------------------------- -int _ctmCompressMesh_MG1(_CTMcontext * self) -{ - CTMuint * indices; - _CTMfloatmap * map; - CTMuint i; - -#ifdef __DEBUG_ - printf("COMPRESSION METHOD: MG1\n"); -#endif - - // Perpare (sort) indices - indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3); - if(!indices) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - for(i = 0; i < self->mTriangleCount * 3; ++ i) - indices[i] = self->mIndices[i]; - _ctmReArrangeTriangles(self, indices); - - // Calculate index deltas (entropy-reduction) - _ctmMakeIndexDeltas(self, indices); - - // Write triangle indices -#ifdef __DEBUG_ - printf("Inidices: "); -#endif - _ctmStreamWrite(self, (void *) "INDX", 4); - if(!_ctmStreamWritePackedInts(self, (CTMint *) indices, self->mTriangleCount, 3, CTM_FALSE)) - { - free((void *) indices); - return CTM_FALSE; - } - - // Free temporary resources - free((void *) indices); - - // Write vertices -#ifdef __DEBUG_ - printf("Vertices: "); -#endif - _ctmStreamWrite(self, (void *) "VERT", 4); - if(!_ctmStreamWritePackedFloats(self, self->mVertices, self->mVertexCount * 3, 1)) - { - free((void *) indices); - return CTM_FALSE; - } - - // Write normals - if(self->mNormals) - { -#ifdef __DEBUG_ - printf("Normals: "); -#endif - _ctmStreamWrite(self, (void *) "NORM", 4); - if(!_ctmStreamWritePackedFloats(self, self->mNormals, self->mVertexCount, 3)) - return CTM_FALSE; - } - - // Write UV maps - map = self->mUVMaps; - while(map) - { -#ifdef __DEBUG_ - printf("UV coordinates (%s): ", map->mName ? map->mName : "no name"); -#endif - _ctmStreamWrite(self, (void *) "TEXC", 4); - _ctmStreamWriteSTRING(self, map->mName); - _ctmStreamWriteSTRING(self, map->mFileName); - if(!_ctmStreamWritePackedFloats(self, map->mValues, self->mVertexCount, 2)) - return CTM_FALSE; - map = map->mNext; - } - - // Write attribute maps - map = self->mAttribMaps; - while(map) - { -#ifdef __DEBUG_ - printf("Vertex attributes (%s): ", map->mName ? map->mName : "no name"); -#endif - _ctmStreamWrite(self, (void *) "ATTR", 4); - _ctmStreamWriteSTRING(self, map->mName); - if(!_ctmStreamWritePackedFloats(self, map->mValues, self->mVertexCount, 4)) - return CTM_FALSE; - map = map->mNext; - } - - return CTM_TRUE; -} - -//----------------------------------------------------------------------------- -// _ctmUncompressMesh_MG1() - Uncmpress the mesh from the input stream in the -// CTM context, and store the resulting mesh in the CTM context. -//----------------------------------------------------------------------------- -int _ctmUncompressMesh_MG1(_CTMcontext * self) -{ - CTMuint * indices; - _CTMfloatmap * map; - CTMuint i; - - // Allocate memory for the indices - indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3); - if(!indices) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - - // Read triangle indices - if(_ctmStreamReadUINT(self) != FOURCC("INDX")) - { - self->mError = CTM_BAD_FORMAT; - free(indices); - return CTM_FALSE; - } - if(!_ctmStreamReadPackedInts(self, (CTMint *) indices, self->mTriangleCount, 3, CTM_FALSE)) - return CTM_FALSE; - - // Restore indices - _ctmRestoreIndices(self, indices); - for(i = 0; i < self->mTriangleCount * 3; ++ i) - self->mIndices[i] = indices[i]; - - // Free temporary resources - free(indices); - - // Read vertices - if(_ctmStreamReadUINT(self) != FOURCC("VERT")) - { - self->mError = CTM_BAD_FORMAT; - return CTM_FALSE; - } - if(!_ctmStreamReadPackedFloats(self, self->mVertices, self->mVertexCount * 3, 1)) - return CTM_FALSE; - - // Read normals - if(self->mNormals) - { - if(_ctmStreamReadUINT(self) != FOURCC("NORM")) - { - self->mError = CTM_BAD_FORMAT; - return CTM_FALSE; - } - if(!_ctmStreamReadPackedFloats(self, self->mNormals, self->mVertexCount, 3)) - return CTM_FALSE; - } - - // Read UV maps - map = self->mUVMaps; - while(map) - { - if(_ctmStreamReadUINT(self) != FOURCC("TEXC")) - { - self->mError = CTM_BAD_FORMAT; - return 0; - } - _ctmStreamReadSTRING(self, &map->mName); - _ctmStreamReadSTRING(self, &map->mFileName); - if(!_ctmStreamReadPackedFloats(self, map->mValues, self->mVertexCount, 2)) - return CTM_FALSE; - map = map->mNext; - } - - // Read vertex attribute maps - map = self->mAttribMaps; - while(map) - { - if(_ctmStreamReadUINT(self) != FOURCC("ATTR")) - { - self->mError = CTM_BAD_FORMAT; - return 0; - } - _ctmStreamReadSTRING(self, &map->mName); - if(!_ctmStreamReadPackedFloats(self, map->mValues, self->mVertexCount, 4)) - return CTM_FALSE; - map = map->mNext; - } - - return CTM_TRUE; -} diff --git a/src/external/OpenCTM-1.0.3/lib/compressMG2.c b/src/external/OpenCTM-1.0.3/lib/compressMG2.c deleted file mode 100644 index d993fef65..000000000 --- a/src/external/OpenCTM-1.0.3/lib/compressMG2.c +++ /dev/null @@ -1,1319 +0,0 @@ -//----------------------------------------------------------------------------- -// Product: OpenCTM -// File: compressMG2.c -// Description: Implementation of the MG2 compression method. -//----------------------------------------------------------------------------- -// Copyright (c) 2009-2010 Marcus Geelnard -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -//----------------------------------------------------------------------------- - -#include -#include -#include "openctm.h" -#include "internal.h" - -#ifdef __DEBUG_ -#include -#endif - -// We need PI -#ifndef PI -#define PI 3.141592653589793238462643f -#endif - - -//----------------------------------------------------------------------------- -// _CTMgrid - 3D space subdivision grid. -//----------------------------------------------------------------------------- -typedef struct { - // Axis-aligned boudning box for the grid. - CTMfloat mMin[3]; - CTMfloat mMax[3]; - - // How many divisions per axis (minimum 1). - CTMuint mDivision[3]; - - // Size of each grid box. - CTMfloat mSize[3]; -} _CTMgrid; - -//----------------------------------------------------------------------------- -// _CTMsortvertex - Vertex information. -//----------------------------------------------------------------------------- -typedef struct { - // Vertex X coordinate (used for sorting). - CTMfloat x; - - // Grid index. This is the index into the 3D space subdivision grid. - CTMuint mGridIndex; - - // Original index (before sorting). - CTMuint mOriginalIndex; -} _CTMsortvertex; - -//----------------------------------------------------------------------------- -// _ctmSetupGrid() - Setup the 3D space subdivision grid. -//----------------------------------------------------------------------------- -static void _ctmSetupGrid(_CTMcontext * self, _CTMgrid * aGrid) -{ - CTMuint i; - CTMfloat factor[3], sum, wantedGrids; - - // Calculate the mesh bounding box - aGrid->mMin[0] = aGrid->mMax[0] = self->mVertices[0]; - aGrid->mMin[1] = aGrid->mMax[1] = self->mVertices[1]; - aGrid->mMin[2] = aGrid->mMax[2] = self->mVertices[2]; - for(i = 1; i < self->mVertexCount; ++ i) - { - if(self->mVertices[i * 3] < aGrid->mMin[0]) - aGrid->mMin[0] = self->mVertices[i * 3]; - else if(self->mVertices[i * 3] > aGrid->mMax[0]) - aGrid->mMax[0] = self->mVertices[i * 3]; - if(self->mVertices[i * 3 + 1] < aGrid->mMin[1]) - aGrid->mMin[1] = self->mVertices[i * 3 + 1]; - else if(self->mVertices[i * 3 + 1] > aGrid->mMax[1]) - aGrid->mMax[1] = self->mVertices[i * 3 + 1]; - if(self->mVertices[i * 3 + 2] < aGrid->mMin[2]) - aGrid->mMin[2] = self->mVertices[i * 3 + 2]; - else if(self->mVertices[i * 3 + 2] > aGrid->mMax[2]) - aGrid->mMax[2] = self->mVertices[i * 3 + 2]; - } - - // Determine optimal grid resolution, based on the number of vertices and - // the bounding box. - // NOTE: This algorithm is quite crude, and could very well be optimized for - // better compression levels in the future without affecting the file format - // or backward compatibility at all. - for(i = 0; i < 3; ++ i) - factor[i] = aGrid->mMax[i] - aGrid->mMin[i]; - sum = factor[0] + factor[1] + factor[2]; - if(sum > 1e-30f) - { - sum = 1.0f / sum; - for(i = 0; i < 3; ++ i) - factor[i] *= sum; - wantedGrids = powf(100.0f * self->mVertexCount, 1.0f / 3.0f); - for(i = 0; i < 3; ++ i) - { - aGrid->mDivision[i] = (CTMuint) ceilf(wantedGrids * factor[i]); - if(aGrid->mDivision[i] < 1) - aGrid->mDivision[i] = 1; - } - } - else - { - aGrid->mDivision[0] = 4; - aGrid->mDivision[1] = 4; - aGrid->mDivision[2] = 4; - } -#ifdef __DEBUG_ - printf("Division: (%d %d %d)\n", aGrid->mDivision[0], aGrid->mDivision[1], aGrid->mDivision[2]); -#endif - - // Calculate grid sizes - for(i = 0; i < 3; ++ i) - aGrid->mSize[i] = (aGrid->mMax[i] - aGrid->mMin[i]) / aGrid->mDivision[i]; -} - -//----------------------------------------------------------------------------- -// _ctmPointToGridIdx() - Convert a point to a grid index. -//----------------------------------------------------------------------------- -static CTMuint _ctmPointToGridIdx(_CTMgrid * aGrid, CTMfloat * aPoint) -{ - CTMuint i, idx[3]; - - for(i = 0; i < 3; ++ i) - { - idx[i] = (CTMuint) floorf((aPoint[i] - aGrid->mMin[i]) / aGrid->mSize[i]); - if(idx[i] >= aGrid->mDivision[i]) - idx[i] = aGrid->mDivision[i] - 1; - } - - return idx[0] + aGrid->mDivision[0] * (idx[1] + aGrid->mDivision[1] * idx[2]); -} - -//----------------------------------------------------------------------------- -// _ctmGridIdxToPoint() - Convert a grid index to a point (the min x/y/z for -// the given grid box). -//----------------------------------------------------------------------------- -static void _ctmGridIdxToPoint(_CTMgrid * aGrid, CTMuint aIdx, CTMfloat * aPoint) -{ - CTMuint gridIdx[3], zdiv, ydiv, i; - - zdiv = aGrid->mDivision[0] * aGrid->mDivision[1]; - ydiv = aGrid->mDivision[0]; - - gridIdx[2] = aIdx / zdiv; - aIdx -= gridIdx[2] * zdiv; - gridIdx[1] = aIdx / ydiv; - aIdx -= gridIdx[1] * ydiv; - gridIdx[0] = aIdx; - - for(i = 0; i < 3; ++ i) - aPoint[i] = gridIdx[i] * aGrid->mSize[i] + aGrid->mMin[i]; -} - -//----------------------------------------------------------------------------- -// _compareVertex() - Comparator for the vertex sorting. -//----------------------------------------------------------------------------- -static int _compareVertex(const void * elem1, const void * elem2) -{ - _CTMsortvertex * v1 = (_CTMsortvertex *) elem1; - _CTMsortvertex * v2 = (_CTMsortvertex *) elem2; - if(v1->mGridIndex != v2->mGridIndex) - return v1->mGridIndex - v2->mGridIndex; - else if(v1->x < v2->x) - return -1; - else if(v1->x > v2->x) - return 1; - else - return 0; -} - -//----------------------------------------------------------------------------- -// _ctmSortVertices() - Setup the vertex array. Assign each vertex to a grid -// box, and sort all vertices. -//----------------------------------------------------------------------------- -static void _ctmSortVertices(_CTMcontext * self, _CTMsortvertex * aSortVertices, - _CTMgrid * aGrid) -{ - CTMuint i; - - // Prepare sort vertex array - for(i = 0; i < self->mVertexCount; ++ i) - { - // Store vertex properties in the sort vertex array - aSortVertices[i].x = self->mVertices[i * 3]; - aSortVertices[i].mGridIndex = _ctmPointToGridIdx(aGrid, &self->mVertices[i * 3]); - aSortVertices[i].mOriginalIndex = i; - } - - // Sort vertices. The elements are first sorted by their grid indices, and - // scondly by their x coordinates. - qsort((void *) aSortVertices, self->mVertexCount, sizeof(_CTMsortvertex), _compareVertex); -} - -//----------------------------------------------------------------------------- -// _ctmReIndexIndices() - Re-index all indices, based on the sorted vertices. -//----------------------------------------------------------------------------- -static int _ctmReIndexIndices(_CTMcontext * self, _CTMsortvertex * aSortVertices, - CTMuint * aIndices) -{ - CTMuint i, * indexLUT; - - // Create temporary lookup-array, O(n) - indexLUT = (CTMuint *) malloc(sizeof(CTMuint) * self->mVertexCount); - if(!indexLUT) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - for(i = 0; i < self->mVertexCount; ++ i) - indexLUT[aSortVertices[i].mOriginalIndex] = i; - - // Convert old indices to new indices, O(n) - for(i = 0; i < self->mTriangleCount * 3; ++ i) - aIndices[i] = indexLUT[self->mIndices[i]]; - - // Free temporary lookup-array - free((void *) indexLUT); - - return CTM_TRUE; -} - -//----------------------------------------------------------------------------- -// _compareTriangle() - Comparator for the triangle sorting. -//----------------------------------------------------------------------------- -static int _compareTriangle(const void * elem1, const void * elem2) -{ - CTMuint * tri1 = (CTMuint *) elem1; - CTMuint * tri2 = (CTMuint *) elem2; - if(tri1[0] != tri2[0]) - return tri1[0] - tri2[0]; - else - return tri1[1] - tri2[1]; -} - -//----------------------------------------------------------------------------- -// _ctmReArrangeTriangles() - Re-arrange all triangles for optimal -// compression. -//----------------------------------------------------------------------------- -static void _ctmReArrangeTriangles(_CTMcontext * self, CTMuint * aIndices) -{ - CTMuint * tri, tmp, i; - - // Step 1: Make sure that the first index of each triangle is the smallest - // one (rotate triangle nodes if necessary) - for(i = 0; i < self->mTriangleCount; ++ i) - { - tri = &aIndices[i * 3]; - if((tri[1] < tri[0]) && (tri[1] < tri[2])) - { - tmp = tri[0]; - tri[0] = tri[1]; - tri[1] = tri[2]; - tri[2] = tmp; - } - else if((tri[2] < tri[0]) && (tri[2] < tri[1])) - { - tmp = tri[0]; - tri[0] = tri[2]; - tri[2] = tri[1]; - tri[1] = tmp; - } - } - - // Step 2: Sort the triangles based on the first triangle index - qsort((void *) aIndices, self->mTriangleCount, sizeof(CTMuint) * 3, _compareTriangle); -} - -//----------------------------------------------------------------------------- -// _ctmMakeIndexDeltas() - Calculate various forms of derivatives in order to -// reduce data entropy. -//----------------------------------------------------------------------------- -static void _ctmMakeIndexDeltas(_CTMcontext * self, CTMuint * aIndices) -{ - CTMint i; - for(i = self->mTriangleCount - 1; i >= 0; -- i) - { - // Step 1: Calculate delta from second triangle index to the previous - // second triangle index, if the previous triangle shares the same first - // index, otherwise calculate the delta to the first triangle index - if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3])) - aIndices[i * 3 + 1] -= aIndices[(i - 1) * 3 + 1]; - else - aIndices[i * 3 + 1] -= aIndices[i * 3]; - - // Step 2: Calculate delta from third triangle index to the first triangle - // index - aIndices[i * 3 + 2] -= aIndices[i * 3]; - - // Step 3: Calculate derivative of the first triangle index - if(i >= 1) - aIndices[i * 3] -= aIndices[(i - 1) * 3]; - } -} - -//----------------------------------------------------------------------------- -// _ctmRestoreIndices() - Restore original indices (inverse derivative -// operation). -//----------------------------------------------------------------------------- -static void _ctmRestoreIndices(_CTMcontext * self, CTMuint * aIndices) -{ - CTMuint i; - - for(i = 0; i < self->mTriangleCount; ++ i) - { - // Step 1: Reverse derivative of the first triangle index - if(i >= 1) - aIndices[i * 3] += aIndices[(i - 1) * 3]; - - // Step 2: Reverse delta from third triangle index to the first triangle - // index - aIndices[i * 3 + 2] += aIndices[i * 3]; - - // Step 3: Reverse delta from second triangle index to the previous - // second triangle index, if the previous triangle shares the same first - // index, otherwise reverse the delta to the first triangle index - if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3])) - aIndices[i * 3 + 1] += aIndices[(i - 1) * 3 + 1]; - else - aIndices[i * 3 + 1] += aIndices[i * 3]; - } -} - -//----------------------------------------------------------------------------- -// _ctmMakeVertexDeltas() - Calculate various forms of derivatives in order to -// reduce data entropy. -//----------------------------------------------------------------------------- -static void _ctmMakeVertexDeltas(_CTMcontext * self, CTMint * aIntVertices, - _CTMsortvertex * aSortVertices, _CTMgrid * aGrid) -{ - CTMuint i, gridIdx, prevGridIndex, oldIdx; - CTMfloat gridOrigin[3], scale; - CTMint deltaX, prevDeltaX; - - // Vertex scaling factor - scale = 1.0f / self->mVertexPrecision; - - prevGridIndex = 0x7fffffff; - prevDeltaX = 0; - for(i = 0; i < self->mVertexCount; ++ i) - { - // Get grid box origin - gridIdx = aSortVertices[i].mGridIndex; - _ctmGridIdxToPoint(aGrid, gridIdx, gridOrigin); - - // Get old vertex coordinate index (before vertex sorting) - oldIdx = aSortVertices[i].mOriginalIndex; - - // Store delta to the grid box origin in the integer vertex array. For the - // X axis (which is sorted) we also do the delta to the previous coordinate - // in the box. - deltaX = (CTMint) floorf(scale * (self->mVertices[oldIdx * 3] - gridOrigin[0]) + 0.5f); - if(gridIdx == prevGridIndex) - aIntVertices[i * 3] = deltaX - prevDeltaX; - else - aIntVertices[i * 3] = deltaX; - aIntVertices[i * 3 + 1] = (CTMint) floorf(scale * (self->mVertices[oldIdx * 3 + 1] - gridOrigin[1]) + 0.5f); - aIntVertices[i * 3 + 2] = (CTMint) floorf(scale * (self->mVertices[oldIdx * 3 + 2] - gridOrigin[2]) + 0.5f); - - prevGridIndex = gridIdx; - prevDeltaX = deltaX; - } -} - -//----------------------------------------------------------------------------- -// _ctmRestoreVertices() - Calculate inverse derivatives of the vertices. -//----------------------------------------------------------------------------- -static void _ctmRestoreVertices(_CTMcontext * self, CTMint * aIntVertices, - CTMuint * aGridIndices, _CTMgrid * aGrid, CTMfloat * aVertices) -{ - CTMuint i, gridIdx, prevGridIndex; - CTMfloat gridOrigin[3], scale; - CTMint deltaX, prevDeltaX; - - scale = self->mVertexPrecision; - - prevGridIndex = 0x7fffffff; - prevDeltaX = 0; - for(i = 0; i < self->mVertexCount; ++ i) - { - // Get grid box origin - gridIdx = aGridIndices[i]; - _ctmGridIdxToPoint(aGrid, gridIdx, gridOrigin); - - // Restore original point - deltaX = aIntVertices[i * 3]; - if(gridIdx == prevGridIndex) - deltaX += prevDeltaX; - aVertices[i * 3] = scale * deltaX + gridOrigin[0]; - aVertices[i * 3 + 1] = scale * aIntVertices[i * 3 + 1] + gridOrigin[1]; - aVertices[i * 3 + 2] = scale * aIntVertices[i * 3 + 2] + gridOrigin[2]; - - prevGridIndex = gridIdx; - prevDeltaX = deltaX; - } -} - -//----------------------------------------------------------------------------- -// _ctmCalcSmoothNormals() - Calculate the smooth normals for a given mesh. -// These are used as the nominal normals for normal deltas & reconstruction. -//----------------------------------------------------------------------------- -static void _ctmCalcSmoothNormals(_CTMcontext * self, CTMfloat * aVertices, - CTMuint * aIndices, CTMfloat * aSmoothNormals) -{ - CTMuint i, j, k, tri[3]; - CTMfloat len; - CTMfloat v1[3], v2[3], n[3]; - - // Clear smooth normals array - for(i = 0; i < 3 * self->mVertexCount; ++ i) - aSmoothNormals[i] = 0.0f; - - // Calculate sums of all neigbouring triangle normals for each vertex - for(i = 0; i < self->mTriangleCount; ++ i) - { - // Get triangle corner indices - for(j = 0; j < 3; ++ j) - tri[j] = aIndices[i * 3 + j]; - - // Calculate the normalized cross product of two triangle edges (i.e. the - // flat triangle normal) - for(j = 0; j < 3; ++ j) - { - v1[j] = aVertices[tri[1] * 3 + j] - aVertices[tri[0] * 3 + j]; - v2[j] = aVertices[tri[2] * 3 + j] - aVertices[tri[0] * 3 + j]; - } - n[0] = v1[1] * v2[2] - v1[2] * v2[1]; - n[1] = v1[2] * v2[0] - v1[0] * v2[2]; - n[2] = v1[0] * v2[1] - v1[1] * v2[0]; - len = sqrtf(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]); - if(len > 1e-10f) - len = 1.0f / len; - else - len = 1.0f; - for(j = 0; j < 3; ++ j) - n[j] *= len; - - // Add the flat normal to all three triangle vertices - for(k = 0; k < 3; ++ k) - for(j = 0; j < 3; ++ j) - aSmoothNormals[tri[k] * 3 + j] += n[j]; - } - - // Normalize the normal sums, which gives the unit length smooth normals - for(i = 0; i < self->mVertexCount; ++ i) - { - len = sqrtf(aSmoothNormals[i * 3] * aSmoothNormals[i * 3] + - aSmoothNormals[i * 3 + 1] * aSmoothNormals[i * 3 + 1] + - aSmoothNormals[i * 3 + 2] * aSmoothNormals[i * 3 + 2]); - if(len > 1e-10f) - len = 1.0f / len; - else - len = 1.0f; - for(j = 0; j < 3; ++ j) - aSmoothNormals[i * 3 + j] *= len; - } -} - -//----------------------------------------------------------------------------- -// _ctmMakeNormalCoordSys() - Create an ortho-normalized coordinate system -// where the Z-axis is aligned with the given normal. -// Note 1: This function is central to how the compressed normal data is -// interpreted, and it can not be changed (mathematically) without making the -// coder/decoder incompatible with other versions of the library! -// Note 2: Since we do this for every single normal, this routine needs to be -// fast. The current implementation uses: 12 MUL, 1 DIV, 1 SQRT, ~6 ADD. -//----------------------------------------------------------------------------- -static void _ctmMakeNormalCoordSys(CTMfloat * aNormal, CTMfloat * aBasisAxes) -{ - CTMfloat len, * x, * y, * z; - CTMuint i; - - // Pointers to the basis axes (aBasisAxes is a 3x3 matrix) - x = aBasisAxes; - y = &aBasisAxes[3]; - z = &aBasisAxes[6]; - - // Z = normal (must be unit length!) - for(i = 0; i < 3; ++ i) - z[i] = aNormal[i]; - - // Calculate a vector that is guaranteed to be orthogonal to the normal, non- - // zero, and a continuous function of the normal (no discrete jumps): - // X = (0,0,1) x normal + (1,0,0) x normal - x[0] = -aNormal[1]; - x[1] = aNormal[0] - aNormal[2]; - x[2] = aNormal[1]; - - // Normalize the new X axis (note: |x[2]| = |x[0]|) - len = sqrtf(2.0 * x[0] * x[0] + x[1] * x[1]); - if(len > 1.0e-20f) - { - len = 1.0f / len; - x[0] *= len; - x[1] *= len; - x[2] *= len; - } - - // Let Y = Z x X (no normalization needed, since |Z| = |X| = 1) - y[0] = z[1] * x[2] - z[2] * x[1]; - y[1] = z[2] * x[0] - z[0] * x[2]; - y[2] = z[0] * x[1] - z[1] * x[0]; -} - -//----------------------------------------------------------------------------- -// _ctmMakeNormalDeltas() - Convert the normals to a new coordinate system: -// magnitude, phi, theta (relative to predicted smooth normals). -//----------------------------------------------------------------------------- -static CTMint _ctmMakeNormalDeltas(_CTMcontext * self, CTMint * aIntNormals, - CTMfloat * aVertices, CTMuint * aIndices, _CTMsortvertex * aSortVertices) -{ - CTMuint i, j, oldIdx, intPhi; - CTMfloat magn, phi, theta, scale, thetaScale; - CTMfloat * smoothNormals, n[3], n2[3], basisAxes[9]; - - // Allocate temporary memory for the nominal vertex normals - smoothNormals = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * self->mVertexCount); - if(!smoothNormals) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - - // Calculate smooth normals (Note: aVertices and aIndices use the sorted - // index space, so smoothNormals will too) - _ctmCalcSmoothNormals(self, aVertices, aIndices, smoothNormals); - - // Normal scaling factor - scale = 1.0f / self->mNormalPrecision; - - for(i = 0; i < self->mVertexCount; ++ i) - { - // Get old normal index (before vertex sorting) - oldIdx = aSortVertices[i].mOriginalIndex; - - // Calculate normal magnitude (should always be 1.0 for unit length normals) - magn = sqrtf(self->mNormals[oldIdx * 3] * self->mNormals[oldIdx * 3] + - self->mNormals[oldIdx * 3 + 1] * self->mNormals[oldIdx * 3 + 1] + - self->mNormals[oldIdx * 3 + 2] * self->mNormals[oldIdx * 3 + 2]); - if(magn < 1e-10f) - magn = 1.0f; - - // Invert magnitude if the normal is negative compared to the predicted - // smooth normal - if((smoothNormals[i * 3] * self->mNormals[oldIdx * 3] + - smoothNormals[i * 3 + 1] * self->mNormals[oldIdx * 3 + 1] + - smoothNormals[i * 3 + 2] * self->mNormals[oldIdx * 3 + 2]) < 0.0f) - magn = -magn; - - // Store the magnitude in the first element of the three normal elements - aIntNormals[i * 3] = (CTMint) floorf(scale * magn + 0.5f); - - // Normalize the normal (1 / magn) - and flip it if magn < 0 - magn = 1.0f / magn; - for(j = 0; j < 3; ++ j) - n[j] = self->mNormals[oldIdx * 3 + j] * magn; - - // Convert the normal to angular representation (phi, theta) in a coordinate - // system where the nominal (smooth) normal is the Z-axis - _ctmMakeNormalCoordSys(&smoothNormals[i * 3], basisAxes); - for(j = 0; j < 3; ++ j) - n2[j] = basisAxes[j * 3] * n[0] + - basisAxes[j * 3 + 1] * n[1] + - basisAxes[j * 3 + 2] * n[2]; - if(n2[2] >= 1.0f) - phi = 0.0f; - else - phi = acosf(n2[2]); - theta = atan2f(n2[1], n2[0]); - - // Round phi and theta (spherical coordinates) to integers. Note: We let the - // theta resolution vary with the x/y circumference (roughly phi). - intPhi = (CTMint) floorf(phi * (scale / (0.5f * PI)) + 0.5f); - if(intPhi == 0) - thetaScale = 0.0f; - else if(intPhi <= 4) - thetaScale = 2.0f / PI; - else - thetaScale = ((CTMfloat) intPhi) / (2.0f * PI); - aIntNormals[i * 3 + 1] = intPhi; - aIntNormals[i * 3 + 2] = (CTMint) floorf((theta + PI) * thetaScale + 0.5f); - } - - // Free temporary resources - free(smoothNormals); - - return CTM_TRUE; -} - -//----------------------------------------------------------------------------- -// _ctmRestoreNormals() - Convert the normals back to cartesian coordinates. -//----------------------------------------------------------------------------- -static CTMint _ctmRestoreNormals(_CTMcontext * self, CTMint * aIntNormals) -{ - CTMuint i, j, intPhi; - CTMfloat magn, phi, theta, scale, thetaScale; - CTMfloat * smoothNormals, n[3], n2[3], basisAxes[9]; - - // Allocate temporary memory for the nominal vertex normals - smoothNormals = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * self->mVertexCount); - if(!smoothNormals) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - - // Calculate smooth normals (nominal normals) - _ctmCalcSmoothNormals(self, self->mVertices, self->mIndices, smoothNormals); - - // Normal scaling factor - scale = self->mNormalPrecision; - - for(i = 0; i < self->mVertexCount; ++ i) - { - // Get the normal magnitude from the first of the three normal elements - magn = aIntNormals[i * 3] * scale; - - // Get phi and theta (spherical coordinates, relative to the smooth normal). - intPhi = aIntNormals[i * 3 + 1]; - phi = intPhi * (0.5f * PI) * scale; - if(intPhi == 0) - thetaScale = 0.0f; - else if(intPhi <= 4) - thetaScale = PI / 2.0f; - else - thetaScale = (2.0f * PI) / ((CTMfloat) intPhi); - theta = aIntNormals[i * 3 + 2] * thetaScale - PI; - - // Convert the normal from the angular representation (phi, theta) back to - // cartesian coordinates - n2[0] = sinf(phi) * cosf(theta); - n2[1] = sinf(phi) * sinf(theta); - n2[2] = cosf(phi); - _ctmMakeNormalCoordSys(&smoothNormals[i * 3], basisAxes); - for(j = 0; j < 3; ++ j) - n[j] = basisAxes[j] * n2[0] + - basisAxes[3 + j] * n2[1] + - basisAxes[6 + j] * n2[2]; - - // Apply normal magnitude, and output to the normals array - for(j = 0; j < 3; ++ j) - self->mNormals[i * 3 + j] = n[j] * magn; - } - - // Free temporary resources - free(smoothNormals); - - return CTM_TRUE; -} - -//----------------------------------------------------------------------------- -// _ctmMakeUVCoordDeltas() - Calculate various forms of derivatives in order -// to reduce data entropy. -//----------------------------------------------------------------------------- -static void _ctmMakeUVCoordDeltas(_CTMcontext * self, _CTMfloatmap * aMap, - CTMint * aIntUVCoords, _CTMsortvertex * aSortVertices) -{ - CTMuint i, oldIdx; - CTMint u, v, prevU, prevV; - CTMfloat scale; - - // UV coordinate scaling factor - scale = 1.0f / aMap->mPrecision; - - prevU = prevV = 0; - for(i = 0; i < self->mVertexCount; ++ i) - { - // Get old UV coordinate index (before vertex sorting) - oldIdx = aSortVertices[i].mOriginalIndex; - - // Convert to fixed point - u = (CTMint) floorf(scale * aMap->mValues[oldIdx * 2] + 0.5f); - v = (CTMint) floorf(scale * aMap->mValues[oldIdx * 2 + 1] + 0.5f); - - // Calculate delta and store it in the converted array. NOTE: Here we rely - // on the fact that vertices are sorted, and usually close to each other, - // which means that UV coordinates should also be close to each other... - aIntUVCoords[i * 2] = u - prevU; - aIntUVCoords[i * 2 + 1] = v - prevV; - - prevU = u; - prevV = v; - } -} - -//----------------------------------------------------------------------------- -// _ctmRestoreUVCoords() - Calculate inverse derivatives of the UV -// coordinates. -//----------------------------------------------------------------------------- -static void _ctmRestoreUVCoords(_CTMcontext * self, _CTMfloatmap * aMap, - CTMint * aIntUVCoords) -{ - CTMuint i; - CTMint u, v, prevU, prevV; - CTMfloat scale; - - // UV coordinate scaling factor - scale = aMap->mPrecision; - - prevU = prevV = 0; - for(i = 0; i < self->mVertexCount; ++ i) - { - // Calculate inverse delta - u = aIntUVCoords[i * 2] + prevU; - v = aIntUVCoords[i * 2 + 1] + prevV; - - // Convert to floating point - aMap->mValues[i * 2] = (CTMfloat) u * scale; - aMap->mValues[i * 2 + 1] = (CTMfloat) v * scale; - - prevU = u; - prevV = v; - } -} - -//----------------------------------------------------------------------------- -// _ctmMakeAttribDeltas() - Calculate various forms of derivatives in order -// to reduce data entropy. -//----------------------------------------------------------------------------- -static void _ctmMakeAttribDeltas(_CTMcontext * self, _CTMfloatmap * aMap, - CTMint * aIntAttribs, _CTMsortvertex * aSortVertices) -{ - CTMuint i, j, oldIdx; - CTMint value[4], prev[4]; - CTMfloat scale; - - // Attribute scaling factor - scale = 1.0f / aMap->mPrecision; - - for(j = 0; j < 4; ++ j) - prev[j] = 0; - - for(i = 0; i < self->mVertexCount; ++ i) - { - // Get old attribute index (before vertex sorting) - oldIdx = aSortVertices[i].mOriginalIndex; - - // Convert to fixed point, and calculate delta and store it in the converted - // array. NOTE: Here we rely on the fact that vertices are sorted, and - // usually close to each other, which means that attributes should also - // be close to each other (and we assume that they somehow vary slowly with - // the geometry)... - for(j = 0; j < 4; ++ j) - { - value[j] = (CTMint) floorf(scale * aMap->mValues[oldIdx * 4 + j] + 0.5f); - aIntAttribs[i * 4 + j] = value[j] - prev[j]; - prev[j] = value[j]; - } - } -} - -//----------------------------------------------------------------------------- -// _ctmRestoreAttribs() - Calculate inverse derivatives of the vertex -// attributes. -//----------------------------------------------------------------------------- -static void _ctmRestoreAttribs(_CTMcontext * self, _CTMfloatmap * aMap, - CTMint * aIntAttribs) -{ - CTMuint i, j; - CTMint value[4], prev[4]; - CTMfloat scale; - - // Attribute scaling factor - scale = aMap->mPrecision; - - for(j = 0; j < 4; ++ j) - prev[j] = 0; - - for(i = 0; i < self->mVertexCount; ++ i) - { - // Calculate inverse delta, and convert to floating point - for(j = 0; j < 4; ++ j) - { - value[j] = aIntAttribs[i * 4 + j] + prev[j]; - aMap->mValues[i * 4 + j] = (CTMfloat) value[j] * scale; - prev[j] = value[j]; - } - } -} - -//----------------------------------------------------------------------------- -// _ctmCompressMesh_MG2() - Compress the mesh that is stored in the CTM -// context, and write it the the output stream in the CTM context. -//----------------------------------------------------------------------------- -int _ctmCompressMesh_MG2(_CTMcontext * self) -{ - _CTMgrid grid; - _CTMsortvertex * sortVertices; - _CTMfloatmap * map; - CTMuint * indices, * deltaIndices, * gridIndices; - CTMint * intVertices, * intNormals, * intUVCoords, * intAttribs; - CTMfloat * restoredVertices; - CTMuint i; - -#ifdef __DEBUG_ - printf("COMPRESSION METHOD: MG2\n"); -#endif - - // Setup 3D space subdivision grid - _ctmSetupGrid(self, &grid); - - // Write MG2-specific header information to the stream - _ctmStreamWrite(self, (void *) "MG2H", 4); - _ctmStreamWriteFLOAT(self, self->mVertexPrecision); - _ctmStreamWriteFLOAT(self, self->mNormalPrecision); - _ctmStreamWriteFLOAT(self, grid.mMin[0]); - _ctmStreamWriteFLOAT(self, grid.mMin[1]); - _ctmStreamWriteFLOAT(self, grid.mMin[2]); - _ctmStreamWriteFLOAT(self, grid.mMax[0]); - _ctmStreamWriteFLOAT(self, grid.mMax[1]); - _ctmStreamWriteFLOAT(self, grid.mMax[2]); - _ctmStreamWriteUINT(self, grid.mDivision[0]); - _ctmStreamWriteUINT(self, grid.mDivision[1]); - _ctmStreamWriteUINT(self, grid.mDivision[2]); - - // Prepare (sort) vertices - sortVertices = (_CTMsortvertex *) malloc(sizeof(_CTMsortvertex) * self->mVertexCount); - if(!sortVertices) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - _ctmSortVertices(self, sortVertices, &grid); - - // Convert vertices to integers and calculate vertex deltas (entropy-reduction) - intVertices = (CTMint *) malloc(sizeof(CTMint) * 3 * self->mVertexCount); - if(!intVertices) - { - self->mError = CTM_OUT_OF_MEMORY; - free((void *) sortVertices); - return CTM_FALSE; - } - _ctmMakeVertexDeltas(self, intVertices, sortVertices, &grid); - - // Write vertices -#ifdef __DEBUG_ - printf("Vertices: "); -#endif - _ctmStreamWrite(self, (void *) "VERT", 4); - if(!_ctmStreamWritePackedInts(self, intVertices, self->mVertexCount, 3, CTM_FALSE)) - { - free((void *) intVertices); - free((void *) sortVertices); - return CTM_FALSE; - } - - // Prepare grid indices (deltas) - gridIndices = (CTMuint *) malloc(sizeof(CTMuint) * self->mVertexCount); - if(!gridIndices) - { - self->mError = CTM_OUT_OF_MEMORY; - free((void *) intVertices); - free((void *) sortVertices); - return CTM_FALSE; - } - gridIndices[0] = sortVertices[0].mGridIndex; - for(i = 1; i < self->mVertexCount; ++ i) - gridIndices[i] = sortVertices[i].mGridIndex - sortVertices[i - 1].mGridIndex; - - // Write grid indices -#ifdef __DEBUG_ - printf("Grid indices: "); -#endif - _ctmStreamWrite(self, (void *) "GIDX", 4); - if(!_ctmStreamWritePackedInts(self, (CTMint *) gridIndices, self->mVertexCount, 1, CTM_FALSE)) - { - free((void *) gridIndices); - free((void *) intVertices); - free((void *) sortVertices); - return CTM_FALSE; - } - - // Calculate the result of the compressed -> decompressed vertices, in order - // to use the same vertex data for calculating nominal normals as the - // decompression routine (i.e. compensate for the vertex error when - // calculating the normals) - restoredVertices = (CTMfloat *) malloc(sizeof(CTMfloat) * 3 * self->mVertexCount); - if(!restoredVertices) - { - self->mError = CTM_OUT_OF_MEMORY; - free((void *) gridIndices); - free((void *) intVertices); - free((void *) sortVertices); - return CTM_FALSE; - } - for(i = 1; i < self->mVertexCount; ++ i) - gridIndices[i] += gridIndices[i - 1]; - _ctmRestoreVertices(self, intVertices, gridIndices, &grid, restoredVertices); - - // Free temporary resources - free((void *) gridIndices); - free((void *) intVertices); - - // Perpare (sort) indices - indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3); - if(!indices) - { - self->mError = CTM_OUT_OF_MEMORY; - free((void *) restoredVertices); - free((void *) sortVertices); - return CTM_FALSE; - } - if(!_ctmReIndexIndices(self, sortVertices, indices)) - { - free((void *) indices); - free((void *) restoredVertices); - free((void *) sortVertices); - return CTM_FALSE; - } - _ctmReArrangeTriangles(self, indices); - - // Calculate index deltas (entropy-reduction) - deltaIndices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3); - if(!indices) - { - self->mError = CTM_OUT_OF_MEMORY; - free((void *) indices); - free((void *) restoredVertices); - free((void *) sortVertices); - return CTM_FALSE; - } - for(i = 0; i < self->mTriangleCount * 3; ++ i) - deltaIndices[i] = indices[i]; - _ctmMakeIndexDeltas(self, deltaIndices); - - // Write triangle indices -#ifdef __DEBUG_ - printf("Indices: "); -#endif - _ctmStreamWrite(self, (void *) "INDX", 4); - if(!_ctmStreamWritePackedInts(self, (CTMint *) deltaIndices, self->mTriangleCount, 3, CTM_FALSE)) - { - free((void *) deltaIndices); - free((void *) indices); - free((void *) restoredVertices); - free((void *) sortVertices); - return CTM_FALSE; - } - - // Free temporary data for the indices - free((void *) deltaIndices); - - if(self->mNormals) - { - // Convert normals to integers and calculate deltas (entropy-reduction) - intNormals = (CTMint *) malloc(sizeof(CTMint) * 3 * self->mVertexCount); - if(!intNormals) - { - self->mError = CTM_OUT_OF_MEMORY; - free((void *) indices); - free((void *) restoredVertices); - free((void *) sortVertices); - return CTM_FALSE; - } - if(!_ctmMakeNormalDeltas(self, intNormals, restoredVertices, indices, sortVertices)) - { - free((void *) indices); - free((void *) intNormals); - free((void *) restoredVertices); - free((void *) sortVertices); - return CTM_FALSE; - } - - // Write normals -#ifdef __DEBUG_ - printf("Normals: "); -#endif - _ctmStreamWrite(self, (void *) "NORM", 4); - if(!_ctmStreamWritePackedInts(self, intNormals, self->mVertexCount, 3, CTM_FALSE)) - { - free((void *) indices); - free((void *) intNormals); - free((void *) restoredVertices); - free((void *) sortVertices); - return CTM_FALSE; - } - - // Free temporary normal data - free((void *) intNormals); - } - - // Free restored indices and vertices - free((void *) indices); - free((void *) restoredVertices); - - // Write UV maps - map = self->mUVMaps; - while(map) - { - // Convert UV coordinates to integers and calculate deltas (entropy-reduction) - intUVCoords = (CTMint *) malloc(sizeof(CTMint) * 2 * self->mVertexCount); - if(!intUVCoords) - { - self->mError = CTM_OUT_OF_MEMORY; - free((void *) sortVertices); - return CTM_FALSE; - } - _ctmMakeUVCoordDeltas(self, map, intUVCoords, sortVertices); - - // Write UV coordinates -#ifdef __DEBUG_ - printf("Texture coordinates (%s): ", map->mName ? map->mName : "no name"); -#endif - _ctmStreamWrite(self, (void *) "TEXC", 4); - _ctmStreamWriteSTRING(self, map->mName); - _ctmStreamWriteSTRING(self, map->mFileName); - _ctmStreamWriteFLOAT(self, map->mPrecision); - if(!_ctmStreamWritePackedInts(self, intUVCoords, self->mVertexCount, 2, CTM_TRUE)) - { - free((void *) intUVCoords); - free((void *) sortVertices); - return CTM_FALSE; - } - - // Free temporary UV coordinate data - free((void *) intUVCoords); - - map = map->mNext; - } - - // Write vertex attribute maps - map = self->mAttribMaps; - while(map) - { - // Convert vertex attributes to integers and calculate deltas (entropy-reduction) - intAttribs = (CTMint *) malloc(sizeof(CTMint) * 4 * self->mVertexCount); - if(!intAttribs) - { - self->mError = CTM_OUT_OF_MEMORY; - free((void *) sortVertices); - return CTM_FALSE; - } - _ctmMakeAttribDeltas(self, map, intAttribs, sortVertices); - - // Write vertex attributes -#ifdef __DEBUG_ - printf("Vertex attributes (%s): ", map->mName ? map->mName : "no name"); -#endif - _ctmStreamWrite(self, (void *) "ATTR", 4); - _ctmStreamWriteSTRING(self, map->mName); - _ctmStreamWriteFLOAT(self, map->mPrecision); - if(!_ctmStreamWritePackedInts(self, intAttribs, self->mVertexCount, 4, CTM_TRUE)) - { - free((void *) intAttribs); - free((void *) sortVertices); - return CTM_FALSE; - } - - // Free temporary vertex attribute data - free((void *) intAttribs); - - map = map->mNext; - } - - // Free temporary data - free((void *) sortVertices); - - return CTM_TRUE; -} - -//----------------------------------------------------------------------------- -// _ctmUncompressMesh_MG2() - Uncmpress the mesh from the input stream in the -// CTM context, and store the resulting mesh in the CTM context. -//----------------------------------------------------------------------------- -int _ctmUncompressMesh_MG2(_CTMcontext * self) -{ - CTMuint * gridIndices, i; - CTMint * intVertices, * intNormals, * intUVCoords, * intAttribs; - _CTMfloatmap * map; - _CTMgrid grid; - - // Read MG2-specific header information from the stream - if(_ctmStreamReadUINT(self) != FOURCC("MG2H")) - { - self->mError = CTM_BAD_FORMAT; - return CTM_FALSE; - } - self->mVertexPrecision = _ctmStreamReadFLOAT(self); - if(self->mVertexPrecision <= 0.0f) - { - self->mError = CTM_BAD_FORMAT; - return CTM_FALSE; - } - self->mNormalPrecision = _ctmStreamReadFLOAT(self); - if(self->mNormalPrecision <= 0.0f) - { - self->mError = CTM_BAD_FORMAT; - return CTM_FALSE; - } - grid.mMin[0] = _ctmStreamReadFLOAT(self); - grid.mMin[1] = _ctmStreamReadFLOAT(self); - grid.mMin[2] = _ctmStreamReadFLOAT(self); - grid.mMax[0] = _ctmStreamReadFLOAT(self); - grid.mMax[1] = _ctmStreamReadFLOAT(self); - grid.mMax[2] = _ctmStreamReadFLOAT(self); - if((grid.mMax[0] < grid.mMin[0]) || - (grid.mMax[1] < grid.mMin[1]) || - (grid.mMax[2] < grid.mMin[2])) - { - self->mError = CTM_BAD_FORMAT; - return CTM_FALSE; - } - grid.mDivision[0] = _ctmStreamReadUINT(self); - grid.mDivision[1] = _ctmStreamReadUINT(self); - grid.mDivision[2] = _ctmStreamReadUINT(self); - if((grid.mDivision[0] < 1) || (grid.mDivision[1] < 1) || (grid.mDivision[2] < 1)) - { - self->mError = CTM_BAD_FORMAT; - return CTM_FALSE; - } - - // Initialize 3D space subdivision grid - for(i = 0; i < 3; ++ i) - grid.mSize[i] = (grid.mMax[i] - grid.mMin[i]) / grid.mDivision[i]; - - // Read vertices - if(_ctmStreamReadUINT(self) != FOURCC("VERT")) - { - self->mError = CTM_BAD_FORMAT; - return CTM_FALSE; - } - intVertices = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 3); - if(!intVertices) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - if(!_ctmStreamReadPackedInts(self, intVertices, self->mVertexCount, 3, CTM_FALSE)) - { - free((void *) intVertices); - return CTM_FALSE; - } - - // Read grid indices - if(_ctmStreamReadUINT(self) != FOURCC("GIDX")) - { - free((void *) intVertices); - self->mError = CTM_BAD_FORMAT; - return CTM_FALSE; - } - gridIndices = (CTMuint *) malloc(sizeof(CTMuint) * self->mVertexCount); - if(!gridIndices) - { - self->mError = CTM_OUT_OF_MEMORY; - free((void *) intVertices); - return CTM_FALSE; - } - if(!_ctmStreamReadPackedInts(self, (CTMint *) gridIndices, self->mVertexCount, 1, CTM_FALSE)) - { - free((void *) gridIndices); - free((void *) intVertices); - return CTM_FALSE; - } - - // Restore grid indices (deltas) - for(i = 1; i < self->mVertexCount; ++ i) - gridIndices[i] += gridIndices[i - 1]; - - // Restore vertices - _ctmRestoreVertices(self, intVertices, gridIndices, &grid, self->mVertices); - - // Free temporary resources - free((void *) gridIndices); - free((void *) intVertices); - - // Read triangle indices - if(_ctmStreamReadUINT(self) != FOURCC("INDX")) - { - self->mError = CTM_BAD_FORMAT; - return CTM_FALSE; - } - if(!_ctmStreamReadPackedInts(self, (CTMint *) self->mIndices, self->mTriangleCount, 3, CTM_FALSE)) - return CTM_FALSE; - - // Restore indices - _ctmRestoreIndices(self, self->mIndices); - - // Check that all indices are within range - for(i = 0; i < (self->mTriangleCount * 3); ++ i) - { - if(self->mIndices[i] >= self->mVertexCount) - { - self->mError = CTM_INVALID_MESH; - return CTM_FALSE; - } - } - - // Read normals - if(self->mNormals) - { - intNormals = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 3); - if(!intNormals) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - if(_ctmStreamReadUINT(self) != FOURCC("NORM")) - { - self->mError = CTM_BAD_FORMAT; - free((void *) intNormals); - return CTM_FALSE; - } - if(!_ctmStreamReadPackedInts(self, intNormals, self->mVertexCount, 3, CTM_FALSE)) - { - free((void *) intNormals); - return CTM_FALSE; - } - - // Restore normals - if(!_ctmRestoreNormals(self, intNormals)) - { - free((void *) intNormals); - return CTM_FALSE; - } - - // Free temporary normals data - free((void *) intNormals); - } - - // Read UV maps - map = self->mUVMaps; - while(map) - { - intUVCoords = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 2); - if(!intUVCoords) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - if(_ctmStreamReadUINT(self) != FOURCC("TEXC")) - { - self->mError = CTM_BAD_FORMAT; - free((void *) intUVCoords); - return CTM_FALSE; - } - _ctmStreamReadSTRING(self, &map->mName); - _ctmStreamReadSTRING(self, &map->mFileName); - map->mPrecision = _ctmStreamReadFLOAT(self); - if(map->mPrecision <= 0.0f) - { - self->mError = CTM_BAD_FORMAT; - free((void *) intUVCoords); - return CTM_FALSE; - } - if(!_ctmStreamReadPackedInts(self, intUVCoords, self->mVertexCount, 2, CTM_TRUE)) - { - free((void *) intUVCoords); - return CTM_FALSE; - } - - // Restore UV coordinates - _ctmRestoreUVCoords(self, map, intUVCoords); - - // Free temporary UV coordinate data - free((void *) intUVCoords); - - map = map->mNext; - } - - // Read vertex attribute maps - map = self->mAttribMaps; - while(map) - { - intAttribs = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 4); - if(!intAttribs) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - if(_ctmStreamReadUINT(self) != FOURCC("ATTR")) - { - self->mError = CTM_BAD_FORMAT; - free((void *) intAttribs); - return CTM_FALSE; - } - _ctmStreamReadSTRING(self, &map->mName); - map->mPrecision = _ctmStreamReadFLOAT(self); - if(map->mPrecision <= 0.0f) - { - self->mError = CTM_BAD_FORMAT; - free((void *) intAttribs); - return CTM_FALSE; - } - if(!_ctmStreamReadPackedInts(self, intAttribs, self->mVertexCount, 4, CTM_TRUE)) - { - free((void *) intAttribs); - return CTM_FALSE; - } - - // Restore vertex attributes - _ctmRestoreAttribs(self, map, intAttribs); - - // Free temporary vertex attribute data - free((void *) intAttribs); - - map = map->mNext; - } - - return CTM_TRUE; -} diff --git a/src/external/OpenCTM-1.0.3/lib/compressRAW.c b/src/external/OpenCTM-1.0.3/lib/compressRAW.c deleted file mode 100644 index b3c781102..000000000 --- a/src/external/OpenCTM-1.0.3/lib/compressRAW.c +++ /dev/null @@ -1,181 +0,0 @@ -//----------------------------------------------------------------------------- -// Product: OpenCTM -// File: compressRAW.c -// Description: Implementation of the RAW compression method. -//----------------------------------------------------------------------------- -// Copyright (c) 2009-2010 Marcus Geelnard -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -//----------------------------------------------------------------------------- - -#include "openctm.h" -#include "internal.h" - -#ifdef __DEBUG_ -#include -#endif - - -//----------------------------------------------------------------------------- -// _ctmCompressMesh_RAW() - Compress the mesh that is stored in the CTM -// context using the RAW method, and write it the the output stream in the CTM -// context. -//----------------------------------------------------------------------------- -int _ctmCompressMesh_RAW(_CTMcontext * self) -{ - CTMuint i; - _CTMfloatmap * map; - -#ifdef __DEBUG_ - printf("COMPRESSION METHOD: RAW\n"); -#endif - - // Write triangle indices -#ifdef __DEBUG_ - printf("Inidices: %d bytes\n", (CTMuint)(self->mTriangleCount * 3 * sizeof(CTMuint))); -#endif - _ctmStreamWrite(self, (void *) "INDX", 4); - for(i = 0; i < self->mTriangleCount * 3; ++ i) - _ctmStreamWriteUINT(self, self->mIndices[i]); - - // Write vertices -#ifdef __DEBUG_ - printf("Vertices: %d bytes\n", (CTMuint)(self->mVertexCount * 3 * sizeof(CTMfloat))); -#endif - _ctmStreamWrite(self, (void *) "VERT", 4); - for(i = 0; i < self->mVertexCount * 3; ++ i) - _ctmStreamWriteFLOAT(self, self->mVertices[i]); - - // Write normals - if(self->mNormals) - { -#ifdef __DEBUG_ - printf("Normals: %d bytes\n", (CTMuint)(self->mVertexCount * 3 * sizeof(CTMfloat))); -#endif - _ctmStreamWrite(self, (void *) "NORM", 4); - for(i = 0; i < self->mVertexCount * 3; ++ i) - _ctmStreamWriteFLOAT(self, self->mNormals[i]); - } - - // Write UV maps - map = self->mUVMaps; - while(map) - { -#ifdef __DEBUG_ - printf("UV coordinates (%s): %d bytes\n", map->mName ? map->mName : "no name", (CTMuint)(self->mVertexCount * 2 * sizeof(CTMfloat))); -#endif - _ctmStreamWrite(self, (void *) "TEXC", 4); - _ctmStreamWriteSTRING(self, map->mName); - _ctmStreamWriteSTRING(self, map->mFileName); - for(i = 0; i < self->mVertexCount * 2; ++ i) - _ctmStreamWriteFLOAT(self, map->mValues[i]); - map = map->mNext; - } - - // Write attribute maps - map = self->mAttribMaps; - while(map) - { -#ifdef __DEBUG_ - printf("Vertex attributes (%s): %d bytes\n", map->mName ? map->mName : "no name", (CTMuint)(self->mVertexCount * 4 * sizeof(CTMfloat))); -#endif - _ctmStreamWrite(self, (void *) "ATTR", 4); - _ctmStreamWriteSTRING(self, map->mName); - for(i = 0; i < self->mVertexCount * 4; ++ i) - _ctmStreamWriteFLOAT(self, map->mValues[i]); - map = map->mNext; - } - - return 1; -} - -//----------------------------------------------------------------------------- -// _ctmUncompressMesh_RAW() - Uncmpress the mesh from the input stream in the -// CTM context using the RAW method, and store the resulting mesh in the CTM -// context. -//----------------------------------------------------------------------------- -int _ctmUncompressMesh_RAW(_CTMcontext * self) -{ - CTMuint i; - _CTMfloatmap * map; - - // Read triangle indices - if(_ctmStreamReadUINT(self) != FOURCC("INDX")) - { - self->mError = CTM_BAD_FORMAT; - return 0; - } - for(i = 0; i < self->mTriangleCount * 3; ++ i) - self->mIndices[i] = _ctmStreamReadUINT(self); - - // Read vertices - if(_ctmStreamReadUINT(self) != FOURCC("VERT")) - { - self->mError = CTM_BAD_FORMAT; - return 0; - } - for(i = 0; i < self->mVertexCount * 3; ++ i) - self->mVertices[i] = _ctmStreamReadFLOAT(self); - - // Read normals - if(self->mNormals) - { - if(_ctmStreamReadUINT(self) != FOURCC("NORM")) - { - self->mError = CTM_BAD_FORMAT; - return 0; - } - for(i = 0; i < self->mVertexCount * 3; ++ i) - self->mNormals[i] = _ctmStreamReadFLOAT(self); - } - - // Read UV maps - map = self->mUVMaps; - while(map) - { - if(_ctmStreamReadUINT(self) != FOURCC("TEXC")) - { - self->mError = CTM_BAD_FORMAT; - return 0; - } - _ctmStreamReadSTRING(self, &map->mName); - _ctmStreamReadSTRING(self, &map->mFileName); - for(i = 0; i < self->mVertexCount * 2; ++ i) - map->mValues[i] = _ctmStreamReadFLOAT(self); - map = map->mNext; - } - - // Read attribute maps - map = self->mAttribMaps; - while(map) - { - if(_ctmStreamReadUINT(self) != FOURCC("ATTR")) - { - self->mError = CTM_BAD_FORMAT; - return 0; - } - _ctmStreamReadSTRING(self, &map->mName); - for(i = 0; i < self->mVertexCount * 4; ++ i) - map->mValues[i] = _ctmStreamReadFLOAT(self); - map = map->mNext; - } - - return 1; -} diff --git a/src/external/OpenCTM-1.0.3/lib/internal.h b/src/external/OpenCTM-1.0.3/lib/internal.h deleted file mode 100644 index 2e65c86ba..000000000 --- a/src/external/OpenCTM-1.0.3/lib/internal.h +++ /dev/null @@ -1,147 +0,0 @@ -//----------------------------------------------------------------------------- -// Product: OpenCTM -// File: internal.h -// Description: Internal (private) declarations, types and function prototypes. -//----------------------------------------------------------------------------- -// Copyright (c) 2009-2010 Marcus Geelnard -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -//----------------------------------------------------------------------------- - -#ifndef __OPENCTM_INTERNAL_H_ -#define __OPENCTM_INTERNAL_H_ - -//----------------------------------------------------------------------------- -// Constants -//----------------------------------------------------------------------------- -// OpenCTM file format version (v5). -#define _CTM_FORMAT_VERSION 0x00000005 - -// Flags for the Mesh flags field of the file header -#define _CTM_HAS_NORMALS_BIT 0x00000001 - -//----------------------------------------------------------------------------- -// _CTMfloatmap - Internal representation of a floating point based vertex map -// (used for UV maps and attribute maps). -//----------------------------------------------------------------------------- -typedef struct _CTMfloatmap_struct _CTMfloatmap; -struct _CTMfloatmap_struct { - char * mName; // Unique name - char * mFileName; // File name reference (used only for UV maps) - CTMfloat mPrecision; // Precision for this map - CTMfloat * mValues; // Attribute/UV coordinate values (per vertex) - _CTMfloatmap * mNext; // Pointer to the next map in the list (linked list) -}; - -//----------------------------------------------------------------------------- -// _CTMcontext - Internal CTM context structure. -//----------------------------------------------------------------------------- -typedef struct { - // Context mode (import or export) - CTMenum mMode; - - // Vertices - CTMfloat * mVertices; - CTMuint mVertexCount; - - // Indices - CTMuint * mIndices; - CTMuint mTriangleCount; - - // Normals (optional) - CTMfloat * mNormals; - - // Multiple sets of UV coordinate maps (optional) - CTMuint mUVMapCount; - _CTMfloatmap * mUVMaps; - - // Multiple sets of custom vertex attribute maps (optional) - CTMuint mAttribMapCount; - _CTMfloatmap * mAttribMaps; - - // Last error code - CTMenum mError; - - // The selected compression method - CTMenum mMethod; - - // The selected compression level - CTMuint mCompressionLevel; - - // Vertex coordinate precision - CTMfloat mVertexPrecision; - - // Normal precision (angular + magnitude) - CTMfloat mNormalPrecision; - - // File comment - char * mFileComment; - - // Read() function pointer - CTMreadfn mReadFn; - - // Write() function pointer - CTMwritefn mWriteFn; - - // User data (for stream read/write - usually the stream handle) - void * mUserData; -} _CTMcontext; - -//----------------------------------------------------------------------------- -// Macros -//----------------------------------------------------------------------------- -#define FOURCC(str) (((CTMuint) str[0]) | (((CTMuint) str[1]) << 8) | \ - (((CTMuint) str[2]) << 16) | (((CTMuint) str[3]) << 24)) - -//----------------------------------------------------------------------------- -// Funcion prototypes for stream.c -//----------------------------------------------------------------------------- -CTMuint _ctmStreamRead(_CTMcontext * self, void * aBuf, CTMuint aCount); -CTMuint _ctmStreamWrite(_CTMcontext * self, void * aBuf, CTMuint aCount); -CTMuint _ctmStreamReadUINT(_CTMcontext * self); -void _ctmStreamWriteUINT(_CTMcontext * self, CTMuint aValue); -CTMfloat _ctmStreamReadFLOAT(_CTMcontext * self); -void _ctmStreamWriteFLOAT(_CTMcontext * self, CTMfloat aValue); -void _ctmStreamReadSTRING(_CTMcontext * self, char ** aValue); -void _ctmStreamWriteSTRING(_CTMcontext * self, const char * aValue); -int _ctmStreamReadPackedInts(_CTMcontext * self, CTMint * aData, CTMuint aCount, CTMuint aSize, CTMint aSignedInts); -int _ctmStreamWritePackedInts(_CTMcontext * self, CTMint * aData, CTMuint aCount, CTMuint aSize, CTMint aSignedInts); -int _ctmStreamReadPackedFloats(_CTMcontext * self, CTMfloat * aData, CTMuint aCount, CTMuint aSize); -int _ctmStreamWritePackedFloats(_CTMcontext * self, CTMfloat * aData, CTMuint aCount, CTMuint aSize); - -//----------------------------------------------------------------------------- -// Funcion prototypes for compressRAW.c -//----------------------------------------------------------------------------- -int _ctmCompressMesh_RAW(_CTMcontext * self); -int _ctmUncompressMesh_RAW(_CTMcontext * self); - -//----------------------------------------------------------------------------- -// Funcion prototypes for compressMG1.c -//----------------------------------------------------------------------------- -int _ctmCompressMesh_MG1(_CTMcontext * self); -int _ctmUncompressMesh_MG1(_CTMcontext * self); - -//----------------------------------------------------------------------------- -// Funcion prototypes for compressMG2.c -//----------------------------------------------------------------------------- -int _ctmCompressMesh_MG2(_CTMcontext * self); -int _ctmUncompressMesh_MG2(_CTMcontext * self); - -#endif // __OPENCTM_INTERNAL_H_ diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/Alloc.c b/src/external/OpenCTM-1.0.3/lib/liblzma/Alloc.c deleted file mode 100644 index 358a7b526..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/Alloc.c +++ /dev/null @@ -1,127 +0,0 @@ -/* Alloc.c -- Memory allocation functions -2008-09-24 -Igor Pavlov -Public domain */ - -#ifdef _WIN32 -#include -#endif -#include - -#include "Alloc.h" - -/* #define _SZ_ALLOC_DEBUG */ - -/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ -#ifdef _SZ_ALLOC_DEBUG -#include -int g_allocCount = 0; -int g_allocCountMid = 0; -int g_allocCountBig = 0; -#endif - -void *MyAlloc(size_t size) -{ - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - { - void *p = malloc(size); - fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); - return p; - } - #else - return malloc(size); - #endif -} - -void MyFree(void *address) -{ - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); - #endif - free(address); -} - -#ifdef _WIN32 - -void *MidAlloc(size_t size) -{ - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); - #endif - return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); -} - -void MidFree(void *address) -{ - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); - #endif - if (address == 0) - return; - VirtualFree(address, 0, MEM_RELEASE); -} - -#ifndef MEM_LARGE_PAGES -#undef _7ZIP_LARGE_PAGES -#endif - -#ifdef _7ZIP_LARGE_PAGES -SIZE_T g_LargePageSize = 0; -typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); -#endif - -void SetLargePageSize() -{ - #ifdef _7ZIP_LARGE_PAGES - SIZE_T size = 0; - GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) - GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); - if (largePageMinimum == 0) - return; - size = largePageMinimum(); - if (size == 0 || (size & (size - 1)) != 0) - return; - g_LargePageSize = size; - #endif -} - - -void *BigAlloc(size_t size) -{ - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); - #endif - - #ifdef _7ZIP_LARGE_PAGES - if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) - { - void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), - MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); - if (res != 0) - return res; - } - #endif - return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); -} - -void BigFree(void *address) -{ - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); - #endif - - if (address == 0) - return; - VirtualFree(address, 0, MEM_RELEASE); -} - -#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/Alloc.h b/src/external/OpenCTM-1.0.3/lib/liblzma/Alloc.h deleted file mode 100644 index 510d18e4d..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/Alloc.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Alloc.h -- Memory allocation functions -2008-03-13 -Igor Pavlov -Public domain */ - -#ifndef __COMMON_ALLOC_H -#define __COMMON_ALLOC_H - -#include - -#include "NameMangle.h" - -void *MyAlloc(size_t size); -void MyFree(void *address); - -#ifdef _WIN32 - -void SetLargePageSize(); - -void *MidAlloc(size_t size); -void MidFree(void *address); -void *BigAlloc(size_t size); -void BigFree(void *address); - -#else - -#define MidAlloc(size) MyAlloc(size) -#define MidFree(address) MyFree(address) -#define BigAlloc(size) MyAlloc(size) -#define BigFree(address) MyFree(address) - -#endif - -#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzFind.c b/src/external/OpenCTM-1.0.3/lib/liblzma/LzFind.c deleted file mode 100644 index 34f4f09ea..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/LzFind.c +++ /dev/null @@ -1,751 +0,0 @@ -/* LzFind.c -- Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ - -#include - -#include "LzFind.h" -#include "LzHash.h" - -#define kEmptyHashValue 0 -#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) -#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ -#define kNormalizeMask (~(kNormalizeStepMin - 1)) -#define kMaxHistorySize ((UInt32)3 << 30) - -#define kStartMaxLen 3 - -static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) -{ - if (!p->directInput) - { - alloc->Free(alloc, p->bufferBase); - p->bufferBase = 0; - } -} - -/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ - -static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) -{ - UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; - if (p->directInput) - { - p->blockSize = blockSize; - return 1; - } - if (p->bufferBase == 0 || p->blockSize != blockSize) - { - LzInWindow_Free(p, alloc); - p->blockSize = blockSize; - p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); - } - return (p->bufferBase != 0); -} - -Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } -Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } - -UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } - -void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) -{ - p->posLimit -= subValue; - p->pos -= subValue; - p->streamPos -= subValue; -} - -static void MatchFinder_ReadBlock(CMatchFinder *p) -{ - if (p->streamEndWasReached || p->result != SZ_OK) - return; - for (;;) - { - Byte *dest = p->buffer + (p->streamPos - p->pos); - size_t size = (p->bufferBase + p->blockSize - dest); - if (size == 0) - return; - p->result = p->stream->Read(p->stream, dest, &size); - if (p->result != SZ_OK) - return; - if (size == 0) - { - p->streamEndWasReached = 1; - return; - } - p->streamPos += (UInt32)size; - if (p->streamPos - p->pos > p->keepSizeAfter) - return; - } -} - -void MatchFinder_MoveBlock(CMatchFinder *p) -{ - memmove(p->bufferBase, - p->buffer - p->keepSizeBefore, - (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); - p->buffer = p->bufferBase + p->keepSizeBefore; -} - -int MatchFinder_NeedMove(CMatchFinder *p) -{ - /* if (p->streamEndWasReached) return 0; */ - return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); -} - -void MatchFinder_ReadIfRequired(CMatchFinder *p) -{ - if (p->streamEndWasReached) - return; - if (p->keepSizeAfter >= p->streamPos - p->pos) - MatchFinder_ReadBlock(p); -} - -static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) -{ - if (MatchFinder_NeedMove(p)) - MatchFinder_MoveBlock(p); - MatchFinder_ReadBlock(p); -} - -static void MatchFinder_SetDefaultSettings(CMatchFinder *p) -{ - p->cutValue = 32; - p->btMode = 1; - p->numHashBytes = 4; - /* p->skipModeBits = 0; */ - p->directInput = 0; - p->bigHash = 0; -} - -#define kCrcPoly 0xEDB88320 - -void MatchFinder_Construct(CMatchFinder *p) -{ - UInt32 i; - p->bufferBase = 0; - p->directInput = 0; - p->hash = 0; - MatchFinder_SetDefaultSettings(p); - - for (i = 0; i < 256; i++) - { - UInt32 r = i; - int j; - for (j = 0; j < 8; j++) - r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); - p->crc[i] = r; - } -} - -static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->hash); - p->hash = 0; -} - -void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) -{ - MatchFinder_FreeThisClassMemory(p, alloc); - LzInWindow_Free(p, alloc); -} - -static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) -{ - size_t sizeInBytes = (size_t)num * sizeof(CLzRef); - if (sizeInBytes / sizeof(CLzRef) != num) - return 0; - return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); -} - -int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, - UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, - ISzAlloc *alloc) -{ - UInt32 sizeReserv; - if (historySize > kMaxHistorySize) - { - MatchFinder_Free(p, alloc); - return 0; - } - sizeReserv = historySize >> 1; - if (historySize > ((UInt32)2 << 30)) - sizeReserv = historySize >> 2; - sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); - - p->keepSizeBefore = historySize + keepAddBufferBefore + 1; - p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; - /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ - if (LzInWindow_Create(p, sizeReserv, alloc)) - { - UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; - UInt32 hs; - p->matchMaxLen = matchMaxLen; - { - p->fixedHashSize = 0; - if (p->numHashBytes == 2) - hs = (1 << 16) - 1; - else - { - hs = historySize - 1; - hs |= (hs >> 1); - hs |= (hs >> 2); - hs |= (hs >> 4); - hs |= (hs >> 8); - hs >>= 1; - /* hs >>= p->skipModeBits; */ - hs |= 0xFFFF; /* don't change it! It's required for Deflate */ - if (hs > (1 << 24)) - { - if (p->numHashBytes == 3) - hs = (1 << 24) - 1; - else - hs >>= 1; - } - } - p->hashMask = hs; - hs++; - if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; - if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; - if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; - hs += p->fixedHashSize; - } - - { - UInt32 prevSize = p->hashSizeSum + p->numSons; - UInt32 newSize; - p->historySize = historySize; - p->hashSizeSum = hs; - p->cyclicBufferSize = newCyclicBufferSize; - p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); - newSize = p->hashSizeSum + p->numSons; - if (p->hash != 0 && prevSize == newSize) - return 1; - MatchFinder_FreeThisClassMemory(p, alloc); - p->hash = AllocRefs(newSize, alloc); - if (p->hash != 0) - { - p->son = p->hash + p->hashSizeSum; - return 1; - } - } - } - MatchFinder_Free(p, alloc); - return 0; -} - -static void MatchFinder_SetLimits(CMatchFinder *p) -{ - UInt32 limit = kMaxValForNormalize - p->pos; - UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; - if (limit2 < limit) - limit = limit2; - limit2 = p->streamPos - p->pos; - if (limit2 <= p->keepSizeAfter) - { - if (limit2 > 0) - limit2 = 1; - } - else - limit2 -= p->keepSizeAfter; - if (limit2 < limit) - limit = limit2; - { - UInt32 lenLimit = p->streamPos - p->pos; - if (lenLimit > p->matchMaxLen) - lenLimit = p->matchMaxLen; - p->lenLimit = lenLimit; - } - p->posLimit = p->pos + limit; -} - -void MatchFinder_Init(CMatchFinder *p) -{ - UInt32 i; - for (i = 0; i < p->hashSizeSum; i++) - p->hash[i] = kEmptyHashValue; - p->cyclicBufferPos = 0; - p->buffer = p->bufferBase; - p->pos = p->streamPos = p->cyclicBufferSize; - p->result = SZ_OK; - p->streamEndWasReached = 0; - MatchFinder_ReadBlock(p); - MatchFinder_SetLimits(p); -} - -static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) -{ - return (p->pos - p->historySize - 1) & kNormalizeMask; -} - -void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) -{ - UInt32 i; - for (i = 0; i < numItems; i++) - { - UInt32 value = items[i]; - if (value <= subValue) - value = kEmptyHashValue; - else - value -= subValue; - items[i] = value; - } -} - -static void MatchFinder_Normalize(CMatchFinder *p) -{ - UInt32 subValue = MatchFinder_GetSubValue(p); - MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); - MatchFinder_ReduceOffsets(p, subValue); -} - -static void MatchFinder_CheckLimits(CMatchFinder *p) -{ - if (p->pos == kMaxValForNormalize) - MatchFinder_Normalize(p); - if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) - MatchFinder_CheckAndMoveAndRead(p); - if (p->cyclicBufferPos == p->cyclicBufferSize) - p->cyclicBufferPos = 0; - MatchFinder_SetLimits(p); -} - -static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, - UInt32 *distances, UInt32 maxLen) -{ - son[_cyclicBufferPos] = curMatch; - for (;;) - { - UInt32 delta = pos - curMatch; - if (cutValue-- == 0 || delta >= _cyclicBufferSize) - return distances; - { - const Byte *pb = cur - delta; - curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; - if (pb[maxLen] == cur[maxLen] && *pb == *cur) - { - UInt32 len = 0; - while (++len != lenLimit) - if (pb[len] != cur[len]) - break; - if (maxLen < len) - { - *distances++ = maxLen = len; - *distances++ = delta - 1; - if (len == lenLimit) - return distances; - } - } - } - } -} - -UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, - UInt32 *distances, UInt32 maxLen) -{ - CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; - CLzRef *ptr1 = son + (_cyclicBufferPos << 1); - UInt32 len0 = 0, len1 = 0; - for (;;) - { - UInt32 delta = pos - curMatch; - if (cutValue-- == 0 || delta >= _cyclicBufferSize) - { - *ptr0 = *ptr1 = kEmptyHashValue; - return distances; - } - { - CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); - const Byte *pb = cur - delta; - UInt32 len = (len0 < len1 ? len0 : len1); - if (pb[len] == cur[len]) - { - if (++len != lenLimit && pb[len] == cur[len]) - while (++len != lenLimit) - if (pb[len] != cur[len]) - break; - if (maxLen < len) - { - *distances++ = maxLen = len; - *distances++ = delta - 1; - if (len == lenLimit) - { - *ptr1 = pair[0]; - *ptr0 = pair[1]; - return distances; - } - } - } - if (pb[len] < cur[len]) - { - *ptr1 = curMatch; - ptr1 = pair + 1; - curMatch = *ptr1; - len1 = len; - } - else - { - *ptr0 = curMatch; - ptr0 = pair; - curMatch = *ptr0; - len0 = len; - } - } - } -} - -static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) -{ - CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; - CLzRef *ptr1 = son + (_cyclicBufferPos << 1); - UInt32 len0 = 0, len1 = 0; - for (;;) - { - UInt32 delta = pos - curMatch; - if (cutValue-- == 0 || delta >= _cyclicBufferSize) - { - *ptr0 = *ptr1 = kEmptyHashValue; - return; - } - { - CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); - const Byte *pb = cur - delta; - UInt32 len = (len0 < len1 ? len0 : len1); - if (pb[len] == cur[len]) - { - while (++len != lenLimit) - if (pb[len] != cur[len]) - break; - { - if (len == lenLimit) - { - *ptr1 = pair[0]; - *ptr0 = pair[1]; - return; - } - } - } - if (pb[len] < cur[len]) - { - *ptr1 = curMatch; - ptr1 = pair + 1; - curMatch = *ptr1; - len1 = len; - } - else - { - *ptr0 = curMatch; - ptr0 = pair; - curMatch = *ptr0; - len0 = len; - } - } - } -} - -#define MOVE_POS \ - ++p->cyclicBufferPos; \ - p->buffer++; \ - if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); - -#define MOVE_POS_RET MOVE_POS return offset; - -static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } - -#define GET_MATCHES_HEADER2(minLen, ret_op) \ - UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ - lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ - cur = p->buffer; - -#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) -#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) - -#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue - -#define GET_MATCHES_FOOTER(offset, maxLen) \ - offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ - distances + offset, maxLen) - distances); MOVE_POS_RET; - -#define SKIP_FOOTER \ - SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; - -static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -{ - UInt32 offset; - GET_MATCHES_HEADER(2) - HASH2_CALC; - curMatch = p->hash[hashValue]; - p->hash[hashValue] = p->pos; - offset = 0; - GET_MATCHES_FOOTER(offset, 1) -} - -UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -{ - UInt32 offset; - GET_MATCHES_HEADER(3) - HASH_ZIP_CALC; - curMatch = p->hash[hashValue]; - p->hash[hashValue] = p->pos; - offset = 0; - GET_MATCHES_FOOTER(offset, 2) -} - -static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -{ - UInt32 hash2Value, delta2, maxLen, offset; - GET_MATCHES_HEADER(3) - - HASH3_CALC; - - delta2 = p->pos - p->hash[hash2Value]; - curMatch = p->hash[kFix3HashSize + hashValue]; - - p->hash[hash2Value] = - p->hash[kFix3HashSize + hashValue] = p->pos; - - - maxLen = 2; - offset = 0; - if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) - { - for (; maxLen != lenLimit; maxLen++) - if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) - break; - distances[0] = maxLen; - distances[1] = delta2 - 1; - offset = 2; - if (maxLen == lenLimit) - { - SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); - MOVE_POS_RET; - } - } - GET_MATCHES_FOOTER(offset, maxLen) -} - -static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -{ - UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; - GET_MATCHES_HEADER(4) - - HASH4_CALC; - - delta2 = p->pos - p->hash[ hash2Value]; - delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; - curMatch = p->hash[kFix4HashSize + hashValue]; - - p->hash[ hash2Value] = - p->hash[kFix3HashSize + hash3Value] = - p->hash[kFix4HashSize + hashValue] = p->pos; - - maxLen = 1; - offset = 0; - if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) - { - distances[0] = maxLen = 2; - distances[1] = delta2 - 1; - offset = 2; - } - if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) - { - maxLen = 3; - distances[offset + 1] = delta3 - 1; - offset += 2; - delta2 = delta3; - } - if (offset != 0) - { - for (; maxLen != lenLimit; maxLen++) - if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) - break; - distances[offset - 2] = maxLen; - if (maxLen == lenLimit) - { - SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); - MOVE_POS_RET; - } - } - if (maxLen < 3) - maxLen = 3; - GET_MATCHES_FOOTER(offset, maxLen) -} - -static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -{ - UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; - GET_MATCHES_HEADER(4) - - HASH4_CALC; - - delta2 = p->pos - p->hash[ hash2Value]; - delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; - curMatch = p->hash[kFix4HashSize + hashValue]; - - p->hash[ hash2Value] = - p->hash[kFix3HashSize + hash3Value] = - p->hash[kFix4HashSize + hashValue] = p->pos; - - maxLen = 1; - offset = 0; - if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) - { - distances[0] = maxLen = 2; - distances[1] = delta2 - 1; - offset = 2; - } - if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) - { - maxLen = 3; - distances[offset + 1] = delta3 - 1; - offset += 2; - delta2 = delta3; - } - if (offset != 0) - { - for (; maxLen != lenLimit; maxLen++) - if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) - break; - distances[offset - 2] = maxLen; - if (maxLen == lenLimit) - { - p->son[p->cyclicBufferPos] = curMatch; - MOVE_POS_RET; - } - } - if (maxLen < 3) - maxLen = 3; - offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), - distances + offset, maxLen) - (distances)); - MOVE_POS_RET -} - -UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) -{ - UInt32 offset; - GET_MATCHES_HEADER(3) - HASH_ZIP_CALC; - curMatch = p->hash[hashValue]; - p->hash[hashValue] = p->pos; - offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), - distances, 2) - (distances)); - MOVE_POS_RET -} - -static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -{ - do - { - SKIP_HEADER(2) - HASH2_CALC; - curMatch = p->hash[hashValue]; - p->hash[hashValue] = p->pos; - SKIP_FOOTER - } - while (--num != 0); -} - -void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -{ - do - { - SKIP_HEADER(3) - HASH_ZIP_CALC; - curMatch = p->hash[hashValue]; - p->hash[hashValue] = p->pos; - SKIP_FOOTER - } - while (--num != 0); -} - -static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -{ - do - { - UInt32 hash2Value; - SKIP_HEADER(3) - HASH3_CALC; - curMatch = p->hash[kFix3HashSize + hashValue]; - p->hash[hash2Value] = - p->hash[kFix3HashSize + hashValue] = p->pos; - SKIP_FOOTER - } - while (--num != 0); -} - -static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -{ - do - { - UInt32 hash2Value, hash3Value; - SKIP_HEADER(4) - HASH4_CALC; - curMatch = p->hash[kFix4HashSize + hashValue]; - p->hash[ hash2Value] = - p->hash[kFix3HashSize + hash3Value] = p->pos; - p->hash[kFix4HashSize + hashValue] = p->pos; - SKIP_FOOTER - } - while (--num != 0); -} - -static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -{ - do - { - UInt32 hash2Value, hash3Value; - SKIP_HEADER(4) - HASH4_CALC; - curMatch = p->hash[kFix4HashSize + hashValue]; - p->hash[ hash2Value] = - p->hash[kFix3HashSize + hash3Value] = - p->hash[kFix4HashSize + hashValue] = p->pos; - p->son[p->cyclicBufferPos] = curMatch; - MOVE_POS - } - while (--num != 0); -} - -void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) -{ - do - { - SKIP_HEADER(3) - HASH_ZIP_CALC; - curMatch = p->hash[hashValue]; - p->hash[hashValue] = p->pos; - p->son[p->cyclicBufferPos] = curMatch; - MOVE_POS - } - while (--num != 0); -} - -void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) -{ - vTable->Init = (Mf_Init_Func)MatchFinder_Init; - vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; - vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; - vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; - if (!p->btMode) - { - vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; - vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; - } - else if (p->numHashBytes == 2) - { - vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; - vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; - } - else if (p->numHashBytes == 3) - { - vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; - vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; - } - else - { - vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; - vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; - } -} diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzFind.h b/src/external/OpenCTM-1.0.3/lib/liblzma/LzFind.h deleted file mode 100644 index 5b9cebfdf..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/LzFind.h +++ /dev/null @@ -1,107 +0,0 @@ -/* LzFind.h -- Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __LZFIND_H -#define __LZFIND_H - -#include "Types.h" - -typedef UInt32 CLzRef; - -typedef struct _CMatchFinder -{ - Byte *buffer; - UInt32 pos; - UInt32 posLimit; - UInt32 streamPos; - UInt32 lenLimit; - - UInt32 cyclicBufferPos; - UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ - - UInt32 matchMaxLen; - CLzRef *hash; - CLzRef *son; - UInt32 hashMask; - UInt32 cutValue; - - Byte *bufferBase; - ISeqInStream *stream; - int streamEndWasReached; - - UInt32 blockSize; - UInt32 keepSizeBefore; - UInt32 keepSizeAfter; - - UInt32 numHashBytes; - int directInput; - int btMode; - /* int skipModeBits; */ - int bigHash; - UInt32 historySize; - UInt32 fixedHashSize; - UInt32 hashSizeSum; - UInt32 numSons; - SRes result; - UInt32 crc[256]; -} CMatchFinder; - -#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) -#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) - -#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) - -int MatchFinder_NeedMove(CMatchFinder *p); -Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); -void MatchFinder_MoveBlock(CMatchFinder *p); -void MatchFinder_ReadIfRequired(CMatchFinder *p); - -void MatchFinder_Construct(CMatchFinder *p); - -/* Conditions: - historySize <= 3 GB - keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB -*/ -int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, - UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, - ISzAlloc *alloc); -void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); -void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); -void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); - -UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, - UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, - UInt32 *distances, UInt32 maxLen); - -/* -Conditions: - Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. - Mf_GetPointerToCurrentPos_Func's result must be used only before any other function -*/ - -typedef void (*Mf_Init_Func)(void *object); -typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); -typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); -typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); -typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); -typedef void (*Mf_Skip_Func)(void *object, UInt32); - -typedef struct _IMatchFinder -{ - Mf_Init_Func Init; - Mf_GetIndexByte_Func GetIndexByte; - Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; - Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; - Mf_GetMatches_Func GetMatches; - Mf_Skip_Func Skip; -} IMatchFinder; - -void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); - -void MatchFinder_Init(CMatchFinder *p); -UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); -UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); -void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); -void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); - -#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzHash.h b/src/external/OpenCTM-1.0.3/lib/liblzma/LzHash.h deleted file mode 100644 index 9f4173e7e..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/LzHash.h +++ /dev/null @@ -1,54 +0,0 @@ -/* LzHash.h -- HASH functions for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __LZHASH_H -#define __LZHASH_H - -#define kHash2Size (1 << 10) -#define kHash3Size (1 << 16) -#define kHash4Size (1 << 20) - -#define kFix3HashSize (kHash2Size) -#define kFix4HashSize (kHash2Size + kHash3Size) -#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) - -#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); - -#define HASH3_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - hash2Value = temp & (kHash2Size - 1); \ - hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } - -#define HASH4_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - hash2Value = temp & (kHash2Size - 1); \ - hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ - hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } - -#define HASH5_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - hash2Value = temp & (kHash2Size - 1); \ - hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ - hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ - hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ - hash4Value &= (kHash4Size - 1); } - -/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ -#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; - - -#define MT_HASH2_CALC \ - hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); - -#define MT_HASH3_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - hash2Value = temp & (kHash2Size - 1); \ - hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } - -#define MT_HASH4_CALC { \ - UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ - hash2Value = temp & (kHash2Size - 1); \ - hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ - hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } - -#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaDec.c b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaDec.c deleted file mode 100644 index d87eb1914..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaDec.c +++ /dev/null @@ -1,1007 +0,0 @@ -/* LzmaDec.c -- LZMA Decoder -2008-11-06 : Igor Pavlov : Public domain */ - -#include "LzmaDec.h" - -#include - -#define kNumTopBits 24 -#define kTopValue ((UInt32)1 << kNumTopBits) - -#define kNumBitModelTotalBits 11 -#define kBitModelTotal (1 << kNumBitModelTotalBits) -#define kNumMoveBits 5 - -#define RC_INIT_SIZE 5 - -#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } - -#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) -#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); -#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); -#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ - { UPDATE_0(p); i = (i + i); A0; } else \ - { UPDATE_1(p); i = (i + i) + 1; A1; } -#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) - -#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } -#define TREE_DECODE(probs, limit, i) \ - { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } - -/* #define _LZMA_SIZE_OPT */ - -#ifdef _LZMA_SIZE_OPT -#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) -#else -#define TREE_6_DECODE(probs, i) \ - { i = 1; \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - i -= 0x40; } -#endif - -#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } - -#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) -#define UPDATE_0_CHECK range = bound; -#define UPDATE_1_CHECK range -= bound; code -= bound; -#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ - { UPDATE_0_CHECK; i = (i + i); A0; } else \ - { UPDATE_1_CHECK; i = (i + i) + 1; A1; } -#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) -#define TREE_DECODE_CHECK(probs, limit, i) \ - { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } - - -#define kNumPosBitsMax 4 -#define kNumPosStatesMax (1 << kNumPosBitsMax) - -#define kLenNumLowBits 3 -#define kLenNumLowSymbols (1 << kLenNumLowBits) -#define kLenNumMidBits 3 -#define kLenNumMidSymbols (1 << kLenNumMidBits) -#define kLenNumHighBits 8 -#define kLenNumHighSymbols (1 << kLenNumHighBits) - -#define LenChoice 0 -#define LenChoice2 (LenChoice + 1) -#define LenLow (LenChoice2 + 1) -#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) -#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) -#define kNumLenProbs (LenHigh + kLenNumHighSymbols) - - -#define kNumStates 12 -#define kNumLitStates 7 - -#define kStartPosModelIndex 4 -#define kEndPosModelIndex 14 -#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) - -#define kNumPosSlotBits 6 -#define kNumLenToPosStates 4 - -#define kNumAlignBits 4 -#define kAlignTableSize (1 << kNumAlignBits) - -#define kMatchMinLen 2 -#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) - -#define IsMatch 0 -#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) -#define IsRepG0 (IsRep + kNumStates) -#define IsRepG1 (IsRepG0 + kNumStates) -#define IsRepG2 (IsRepG1 + kNumStates) -#define IsRep0Long (IsRepG2 + kNumStates) -#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) -#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) -#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) -#define LenCoder (Align + kAlignTableSize) -#define RepLenCoder (LenCoder + kNumLenProbs) -#define Literal (RepLenCoder + kNumLenProbs) - -#define LZMA_BASE_SIZE 1846 -#define LZMA_LIT_SIZE 768 - -#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) - -#if Literal != LZMA_BASE_SIZE -StopCompilingDueBUG -#endif - -static const Byte kLiteralNextStates[kNumStates * 2] = -{ - 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, - 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 -}; - -#define LZMA_DIC_MIN (1 << 12) - -/* First LZMA-symbol is always decoded. -And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization -Out: - Result: - SZ_OK - OK - SZ_ERROR_DATA - Error - p->remainLen: - < kMatchSpecLenStart : normal remain - = kMatchSpecLenStart : finished - = kMatchSpecLenStart + 1 : Flush marker - = kMatchSpecLenStart + 2 : State Init Marker -*/ - -static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) -{ - CLzmaProb *probs = p->probs; - - unsigned state = p->state; - UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; - unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; - unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; - unsigned lc = p->prop.lc; - - Byte *dic = p->dic; - SizeT dicBufSize = p->dicBufSize; - SizeT dicPos = p->dicPos; - - UInt32 processedPos = p->processedPos; - UInt32 checkDicSize = p->checkDicSize; - unsigned len = 0; - - const Byte *buf = p->buf; - UInt32 range = p->range; - UInt32 code = p->code; - - do - { - CLzmaProb *prob; - UInt32 bound; - unsigned ttt; - unsigned posState = processedPos & pbMask; - - prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; - IF_BIT_0(prob) - { - unsigned symbol; - UPDATE_0(prob); - prob = probs + Literal; - if (checkDicSize != 0 || processedPos != 0) - prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + - (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); - - if (state < kNumLitStates) - { - symbol = 1; - do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); - } - else - { - unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; - unsigned offs = 0x100; - symbol = 1; - do - { - unsigned bit; - CLzmaProb *probLit; - matchByte <<= 1; - bit = (matchByte & offs); - probLit = prob + offs + bit + symbol; - GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) - } - while (symbol < 0x100); - } - dic[dicPos++] = (Byte)symbol; - processedPos++; - - state = kLiteralNextStates[state]; - /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ - continue; - } - else - { - UPDATE_1(prob); - prob = probs + IsRep + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - state += kNumStates; - prob = probs + LenCoder; - } - else - { - UPDATE_1(prob); - if (checkDicSize == 0 && processedPos == 0) - return SZ_ERROR_DATA; - prob = probs + IsRepG0 + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; - IF_BIT_0(prob) - { - UPDATE_0(prob); - dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; - dicPos++; - processedPos++; - state = state < kNumLitStates ? 9 : 11; - continue; - } - UPDATE_1(prob); - } - else - { - UInt32 distance; - UPDATE_1(prob); - prob = probs + IsRepG1 + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - distance = rep1; - } - else - { - UPDATE_1(prob); - prob = probs + IsRepG2 + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - distance = rep2; - } - else - { - UPDATE_1(prob); - distance = rep3; - rep3 = rep2; - } - rep2 = rep1; - } - rep1 = rep0; - rep0 = distance; - } - state = state < kNumLitStates ? 8 : 11; - prob = probs + RepLenCoder; - } - { - unsigned limit, offset; - CLzmaProb *probLen = prob + LenChoice; - IF_BIT_0(probLen) - { - UPDATE_0(probLen); - probLen = prob + LenLow + (posState << kLenNumLowBits); - offset = 0; - limit = (1 << kLenNumLowBits); - } - else - { - UPDATE_1(probLen); - probLen = prob + LenChoice2; - IF_BIT_0(probLen) - { - UPDATE_0(probLen); - probLen = prob + LenMid + (posState << kLenNumMidBits); - offset = kLenNumLowSymbols; - limit = (1 << kLenNumMidBits); - } - else - { - UPDATE_1(probLen); - probLen = prob + LenHigh; - offset = kLenNumLowSymbols + kLenNumMidSymbols; - limit = (1 << kLenNumHighBits); - } - } - TREE_DECODE(probLen, limit, len); - len += offset; - } - - if (state >= kNumStates) - { - UInt32 distance; - prob = probs + PosSlot + - ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); - TREE_6_DECODE(prob, distance); - if (distance >= kStartPosModelIndex) - { - unsigned posSlot = (unsigned)distance; - int numDirectBits = (int)(((distance >> 1) - 1)); - distance = (2 | (distance & 1)); - if (posSlot < kEndPosModelIndex) - { - distance <<= numDirectBits; - prob = probs + SpecPos + distance - posSlot - 1; - { - UInt32 mask = 1; - unsigned i = 1; - do - { - GET_BIT2(prob + i, i, ; , distance |= mask); - mask <<= 1; - } - while (--numDirectBits != 0); - } - } - else - { - numDirectBits -= kNumAlignBits; - do - { - NORMALIZE - range >>= 1; - - { - UInt32 t; - code -= range; - t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ - distance = (distance << 1) + (t + 1); - code += range & t; - } - /* - distance <<= 1; - if (code >= range) - { - code -= range; - distance |= 1; - } - */ - } - while (--numDirectBits != 0); - prob = probs + Align; - distance <<= kNumAlignBits; - { - unsigned i = 1; - GET_BIT2(prob + i, i, ; , distance |= 1); - GET_BIT2(prob + i, i, ; , distance |= 2); - GET_BIT2(prob + i, i, ; , distance |= 4); - GET_BIT2(prob + i, i, ; , distance |= 8); - } - if (distance == (UInt32)0xFFFFFFFF) - { - len += kMatchSpecLenStart; - state -= kNumStates; - break; - } - } - } - rep3 = rep2; - rep2 = rep1; - rep1 = rep0; - rep0 = distance + 1; - if (checkDicSize == 0) - { - if (distance >= processedPos) - return SZ_ERROR_DATA; - } - else if (distance >= checkDicSize) - return SZ_ERROR_DATA; - state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; - /* state = kLiteralNextStates[state]; */ - } - - len += kMatchMinLen; - - if (limit == dicPos) - return SZ_ERROR_DATA; - { - SizeT rem = limit - dicPos; - unsigned curLen = ((rem < len) ? (unsigned)rem : len); - SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); - - processedPos += curLen; - - len -= curLen; - if (pos + curLen <= dicBufSize) - { - Byte *dest = dic + dicPos; - ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; - const Byte *lim = dest + curLen; - dicPos += curLen; - do - *(dest) = (Byte)*(dest + src); - while (++dest != lim); - } - else - { - do - { - dic[dicPos++] = dic[pos]; - if (++pos == dicBufSize) - pos = 0; - } - while (--curLen != 0); - } - } - } - } - while (dicPos < limit && buf < bufLimit); - NORMALIZE; - p->buf = buf; - p->range = range; - p->code = code; - p->remainLen = len; - p->dicPos = dicPos; - p->processedPos = processedPos; - p->reps[0] = rep0; - p->reps[1] = rep1; - p->reps[2] = rep2; - p->reps[3] = rep3; - p->state = state; - - return SZ_OK; -} - -static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) -{ - if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) - { - Byte *dic = p->dic; - SizeT dicPos = p->dicPos; - SizeT dicBufSize = p->dicBufSize; - unsigned len = p->remainLen; - UInt32 rep0 = p->reps[0]; - if (limit - dicPos < len) - len = (unsigned)(limit - dicPos); - - if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) - p->checkDicSize = p->prop.dicSize; - - p->processedPos += len; - p->remainLen -= len; - while (len-- != 0) - { - dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; - dicPos++; - } - p->dicPos = dicPos; - } -} - -static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) -{ - do - { - SizeT limit2 = limit; - if (p->checkDicSize == 0) - { - UInt32 rem = p->prop.dicSize - p->processedPos; - if (limit - p->dicPos > rem) - limit2 = p->dicPos + rem; - } - RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); - if (p->processedPos >= p->prop.dicSize) - p->checkDicSize = p->prop.dicSize; - LzmaDec_WriteRem(p, limit); - } - while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); - - if (p->remainLen > kMatchSpecLenStart) - { - p->remainLen = kMatchSpecLenStart; - } - return 0; -} - -typedef enum -{ - DUMMY_ERROR, /* unexpected end of input stream */ - DUMMY_LIT, - DUMMY_MATCH, - DUMMY_REP -} ELzmaDummy; - -static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) -{ - UInt32 range = p->range; - UInt32 code = p->code; - const Byte *bufLimit = buf + inSize; - CLzmaProb *probs = p->probs; - unsigned state = p->state; - ELzmaDummy res; - - { - CLzmaProb *prob; - UInt32 bound; - unsigned ttt; - unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); - - prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK - - /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ - - prob = probs + Literal; - if (p->checkDicSize != 0 || p->processedPos != 0) - prob += (LZMA_LIT_SIZE * - ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + - (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); - - if (state < kNumLitStates) - { - unsigned symbol = 1; - do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); - } - else - { - unsigned matchByte = p->dic[p->dicPos - p->reps[0] + - ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; - unsigned offs = 0x100; - unsigned symbol = 1; - do - { - unsigned bit; - CLzmaProb *probLit; - matchByte <<= 1; - bit = (matchByte & offs); - probLit = prob + offs + bit + symbol; - GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) - } - while (symbol < 0x100); - } - res = DUMMY_LIT; - } - else - { - unsigned len; - UPDATE_1_CHECK; - - prob = probs + IsRep + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - state = 0; - prob = probs + LenCoder; - res = DUMMY_MATCH; - } - else - { - UPDATE_1_CHECK; - res = DUMMY_REP; - prob = probs + IsRepG0 + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - NORMALIZE_CHECK; - return DUMMY_REP; - } - else - { - UPDATE_1_CHECK; - } - } - else - { - UPDATE_1_CHECK; - prob = probs + IsRepG1 + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - } - else - { - UPDATE_1_CHECK; - prob = probs + IsRepG2 + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - } - else - { - UPDATE_1_CHECK; - } - } - } - state = kNumStates; - prob = probs + RepLenCoder; - } - { - unsigned limit, offset; - CLzmaProb *probLen = prob + LenChoice; - IF_BIT_0_CHECK(probLen) - { - UPDATE_0_CHECK; - probLen = prob + LenLow + (posState << kLenNumLowBits); - offset = 0; - limit = 1 << kLenNumLowBits; - } - else - { - UPDATE_1_CHECK; - probLen = prob + LenChoice2; - IF_BIT_0_CHECK(probLen) - { - UPDATE_0_CHECK; - probLen = prob + LenMid + (posState << kLenNumMidBits); - offset = kLenNumLowSymbols; - limit = 1 << kLenNumMidBits; - } - else - { - UPDATE_1_CHECK; - probLen = prob + LenHigh; - offset = kLenNumLowSymbols + kLenNumMidSymbols; - limit = 1 << kLenNumHighBits; - } - } - TREE_DECODE_CHECK(probLen, limit, len); - len += offset; - } - - if (state < 4) - { - unsigned posSlot; - prob = probs + PosSlot + - ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << - kNumPosSlotBits); - TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); - if (posSlot >= kStartPosModelIndex) - { - int numDirectBits = ((posSlot >> 1) - 1); - - /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ - - if (posSlot < kEndPosModelIndex) - { - prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; - } - else - { - numDirectBits -= kNumAlignBits; - do - { - NORMALIZE_CHECK - range >>= 1; - code -= range & (((code - range) >> 31) - 1); - /* if (code >= range) code -= range; */ - } - while (--numDirectBits != 0); - prob = probs + Align; - numDirectBits = kNumAlignBits; - } - { - unsigned i = 1; - do - { - GET_BIT_CHECK(prob + i, i); - } - while (--numDirectBits != 0); - } - } - } - } - } - NORMALIZE_CHECK; - return res; -} - - -static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) -{ - p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); - p->range = 0xFFFFFFFF; - p->needFlush = 0; -} - -void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) -{ - p->needFlush = 1; - p->remainLen = 0; - p->tempBufSize = 0; - - if (initDic) - { - p->processedPos = 0; - p->checkDicSize = 0; - p->needInitState = 1; - } - if (initState) - p->needInitState = 1; -} - -void LzmaDec_Init(CLzmaDec *p) -{ - p->dicPos = 0; - LzmaDec_InitDicAndState(p, True, True); -} - -static void LzmaDec_InitStateReal(CLzmaDec *p) -{ - UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); - UInt32 i; - CLzmaProb *probs = p->probs; - for (i = 0; i < numProbs; i++) - probs[i] = kBitModelTotal >> 1; - p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; - p->state = 0; - p->needInitState = 0; -} - -SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, - ELzmaFinishMode finishMode, ELzmaStatus *status) -{ - SizeT inSize = *srcLen; - (*srcLen) = 0; - LzmaDec_WriteRem(p, dicLimit); - - *status = LZMA_STATUS_NOT_SPECIFIED; - - while (p->remainLen != kMatchSpecLenStart) - { - int checkEndMarkNow; - - if (p->needFlush != 0) - { - for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) - p->tempBuf[p->tempBufSize++] = *src++; - if (p->tempBufSize < RC_INIT_SIZE) - { - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; - } - if (p->tempBuf[0] != 0) - return SZ_ERROR_DATA; - - LzmaDec_InitRc(p, p->tempBuf); - p->tempBufSize = 0; - } - - checkEndMarkNow = 0; - if (p->dicPos >= dicLimit) - { - if (p->remainLen == 0 && p->code == 0) - { - *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; - return SZ_OK; - } - if (finishMode == LZMA_FINISH_ANY) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_OK; - } - if (p->remainLen != 0) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; - } - checkEndMarkNow = 1; - } - - if (p->needInitState) - LzmaDec_InitStateReal(p); - - if (p->tempBufSize == 0) - { - SizeT processed; - const Byte *bufLimit; - if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) - { - int dummyRes = LzmaDec_TryDummy(p, src, inSize); - if (dummyRes == DUMMY_ERROR) - { - memcpy(p->tempBuf, src, inSize); - p->tempBufSize = (unsigned)inSize; - (*srcLen) += inSize; - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; - } - if (checkEndMarkNow && dummyRes != DUMMY_MATCH) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; - } - bufLimit = src; - } - else - bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; - p->buf = src; - if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) - return SZ_ERROR_DATA; - processed = (SizeT)(p->buf - src); - (*srcLen) += processed; - src += processed; - inSize -= processed; - } - else - { - unsigned rem = p->tempBufSize, lookAhead = 0; - while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) - p->tempBuf[rem++] = src[lookAhead++]; - p->tempBufSize = rem; - if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) - { - int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); - if (dummyRes == DUMMY_ERROR) - { - (*srcLen) += lookAhead; - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; - } - if (checkEndMarkNow && dummyRes != DUMMY_MATCH) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; - } - } - p->buf = p->tempBuf; - if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) - return SZ_ERROR_DATA; - lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); - (*srcLen) += lookAhead; - src += lookAhead; - inSize -= lookAhead; - p->tempBufSize = 0; - } - } - if (p->code == 0) - *status = LZMA_STATUS_FINISHED_WITH_MARK; - return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; -} - -SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) -{ - SizeT outSize = *destLen; - SizeT inSize = *srcLen; - *srcLen = *destLen = 0; - for (;;) - { - SizeT inSizeCur = inSize, outSizeCur, dicPos; - ELzmaFinishMode curFinishMode; - SRes res; - if (p->dicPos == p->dicBufSize) - p->dicPos = 0; - dicPos = p->dicPos; - if (outSize > p->dicBufSize - dicPos) - { - outSizeCur = p->dicBufSize; - curFinishMode = LZMA_FINISH_ANY; - } - else - { - outSizeCur = dicPos + outSize; - curFinishMode = finishMode; - } - - res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); - src += inSizeCur; - inSize -= inSizeCur; - *srcLen += inSizeCur; - outSizeCur = p->dicPos - dicPos; - memcpy(dest, p->dic + dicPos, outSizeCur); - dest += outSizeCur; - outSize -= outSizeCur; - *destLen += outSizeCur; - if (res != 0) - return res; - if (outSizeCur == 0 || outSize == 0) - return SZ_OK; - } -} - -void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->probs); - p->probs = 0; -} - -static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->dic); - p->dic = 0; -} - -void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) -{ - LzmaDec_FreeProbs(p, alloc); - LzmaDec_FreeDict(p, alloc); -} - -SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) -{ - UInt32 dicSize; - Byte d; - - if (size < LZMA_PROPS_SIZE) - return SZ_ERROR_UNSUPPORTED; - else - dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); - - if (dicSize < LZMA_DIC_MIN) - dicSize = LZMA_DIC_MIN; - p->dicSize = dicSize; - - d = data[0]; - if (d >= (9 * 5 * 5)) - return SZ_ERROR_UNSUPPORTED; - - p->lc = d % 9; - d /= 9; - p->pb = d / 5; - p->lp = d % 5; - - return SZ_OK; -} - -static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) -{ - UInt32 numProbs = LzmaProps_GetNumProbs(propNew); - if (p->probs == 0 || numProbs != p->numProbs) - { - LzmaDec_FreeProbs(p, alloc); - p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); - p->numProbs = numProbs; - if (p->probs == 0) - return SZ_ERROR_MEM; - } - return SZ_OK; -} - -SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) -{ - CLzmaProps propNew; - RINOK(LzmaProps_Decode(&propNew, props, propsSize)); - RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); - p->prop = propNew; - return SZ_OK; -} - -SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) -{ - CLzmaProps propNew; - SizeT dicBufSize; - RINOK(LzmaProps_Decode(&propNew, props, propsSize)); - RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); - dicBufSize = propNew.dicSize; - if (p->dic == 0 || dicBufSize != p->dicBufSize) - { - LzmaDec_FreeDict(p, alloc); - p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); - if (p->dic == 0) - { - LzmaDec_FreeProbs(p, alloc); - return SZ_ERROR_MEM; - } - } - p->dicBufSize = dicBufSize; - p->prop = propNew; - return SZ_OK; -} - -SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, - const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, - ELzmaStatus *status, ISzAlloc *alloc) -{ - CLzmaDec p; - SRes res; - SizeT inSize = *srcLen; - SizeT outSize = *destLen; - *srcLen = *destLen = 0; - if (inSize < RC_INIT_SIZE) - return SZ_ERROR_INPUT_EOF; - - LzmaDec_Construct(&p); - res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); - if (res != 0) - return res; - p.dic = dest; - p.dicBufSize = outSize; - - LzmaDec_Init(&p); - - *srcLen = inSize; - res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); - - if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) - res = SZ_ERROR_INPUT_EOF; - - (*destLen) = p.dicPos; - LzmaDec_FreeProbs(&p, alloc); - return res; -} diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaDec.h b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaDec.h deleted file mode 100644 index 98cdbe949..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaDec.h +++ /dev/null @@ -1,223 +0,0 @@ -/* LzmaDec.h -- LZMA Decoder -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __LZMADEC_H -#define __LZMADEC_H - -#include "Types.h" - -/* #define _LZMA_PROB32 */ -/* _LZMA_PROB32 can increase the speed on some CPUs, - but memory usage for CLzmaDec::probs will be doubled in that case */ - -#ifdef _LZMA_PROB32 -#define CLzmaProb UInt32 -#else -#define CLzmaProb UInt16 -#endif - - -/* ---------- LZMA Properties ---------- */ - -#define LZMA_PROPS_SIZE 5 - -typedef struct _CLzmaProps -{ - unsigned lc, lp, pb; - UInt32 dicSize; -} CLzmaProps; - -/* LzmaProps_Decode - decodes properties -Returns: - SZ_OK - SZ_ERROR_UNSUPPORTED - Unsupported properties -*/ - -SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); - - -/* ---------- LZMA Decoder state ---------- */ - -/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. - Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ - -#define LZMA_REQUIRED_INPUT_MAX 20 - -typedef struct -{ - CLzmaProps prop; - CLzmaProb *probs; - Byte *dic; - const Byte *buf; - UInt32 range, code; - SizeT dicPos; - SizeT dicBufSize; - UInt32 processedPos; - UInt32 checkDicSize; - unsigned state; - UInt32 reps[4]; - unsigned remainLen; - int needFlush; - int needInitState; - UInt32 numProbs; - unsigned tempBufSize; - Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; -} CLzmaDec; - -#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } - -void LzmaDec_Init(CLzmaDec *p); - -/* There are two types of LZMA streams: - 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. - 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ - -typedef enum -{ - LZMA_FINISH_ANY, /* finish at any point */ - LZMA_FINISH_END /* block must be finished at the end */ -} ELzmaFinishMode; - -/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! - - You must use LZMA_FINISH_END, when you know that current output buffer - covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. - - If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, - and output value of destLen will be less than output buffer size limit. - You can check status result also. - - You can use multiple checks to test data integrity after full decompression: - 1) Check Result and "status" variable. - 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. - 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. - You must use correct finish mode in that case. */ - -typedef enum -{ - LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ - LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ - LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ - LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ -} ELzmaStatus; - -/* ELzmaStatus is used only as output value for function call */ - - -/* ---------- Interfaces ---------- */ - -/* There are 3 levels of interfaces: - 1) Dictionary Interface - 2) Buffer Interface - 3) One Call Interface - You can select any of these interfaces, but don't mix functions from different - groups for same object. */ - - -/* There are two variants to allocate state for Dictionary Interface: - 1) LzmaDec_Allocate / LzmaDec_Free - 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs - You can use variant 2, if you set dictionary buffer manually. - For Buffer Interface you must always use variant 1. - -LzmaDec_Allocate* can return: - SZ_OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties -*/ - -SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); -void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); - -SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); -void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); - -/* ---------- Dictionary Interface ---------- */ - -/* You can use it, if you want to eliminate the overhead for data copying from - dictionary to some other external buffer. - You must work with CLzmaDec variables directly in this interface. - - STEPS: - LzmaDec_Constr() - LzmaDec_Allocate() - for (each new stream) - { - LzmaDec_Init() - while (it needs more decompression) - { - LzmaDec_DecodeToDic() - use data from CLzmaDec::dic and update CLzmaDec::dicPos - } - } - LzmaDec_Free() -*/ - -/* LzmaDec_DecodeToDic - - The decoding to internal dictionary buffer (CLzmaDec::dic). - You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! - -finishMode: - It has meaning only if the decoding reaches output limit (dicLimit). - LZMA_FINISH_ANY - Decode just dicLimit bytes. - LZMA_FINISH_END - Stream must be finished after dicLimit. - -Returns: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_NEEDS_MORE_INPUT - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error -*/ - -SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); - - -/* ---------- Buffer Interface ---------- */ - -/* It's zlib-like interface. - See LzmaDec_DecodeToDic description for information about STEPS and return results, - but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need - to work with CLzmaDec variables manually. - -finishMode: - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). -*/ - -SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); - - -/* ---------- One Call Interface ---------- */ - -/* LzmaDecode - -finishMode: - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). - -Returns: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). -*/ - -SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, - const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, - ELzmaStatus *status, ISzAlloc *alloc); - -#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaEnc.c b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaEnc.c deleted file mode 100644 index 492b78510..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaEnc.c +++ /dev/null @@ -1,2281 +0,0 @@ -/* LzmaEnc.c -- LZMA Encoder -2009-02-02 : Igor Pavlov : Public domain */ - -#include - -/* #define SHOW_STAT */ -/* #define SHOW_STAT2 */ - -#if defined(SHOW_STAT) || defined(SHOW_STAT2) -#include -#endif - -#include "LzmaEnc.h" - -#include "LzFind.h" -#ifdef COMPRESS_MF_MT -#include "LzFindMt.h" -#endif - -#ifdef SHOW_STAT -static int ttt = 0; -#endif - -#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) - -#define kBlockSize (9 << 10) -#define kUnpackBlockSize (1 << 18) -#define kMatchArraySize (1 << 21) -#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) - -#define kNumMaxDirectBits (31) - -#define kNumTopBits 24 -#define kTopValue ((UInt32)1 << kNumTopBits) - -#define kNumBitModelTotalBits 11 -#define kBitModelTotal (1 << kNumBitModelTotalBits) -#define kNumMoveBits 5 -#define kProbInitValue (kBitModelTotal >> 1) - -#define kNumMoveReducingBits 4 -#define kNumBitPriceShiftBits 4 -#define kBitPrice (1 << kNumBitPriceShiftBits) - -void LzmaEncProps_Init(CLzmaEncProps *p) -{ - p->level = 5; - p->dictSize = p->mc = 0; - p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; - p->writeEndMark = 0; -} - -void LzmaEncProps_Normalize(CLzmaEncProps *p) -{ - int level = p->level; - if (level < 0) level = 5; - p->level = level; - if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); - if (p->lc < 0) p->lc = 3; - if (p->lp < 0) p->lp = 0; - if (p->pb < 0) p->pb = 2; - if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); - if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); - if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); - if (p->numHashBytes < 0) p->numHashBytes = 4; - if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); - if (p->numThreads < 0) - p->numThreads = - #ifdef COMPRESS_MF_MT - ((p->btMode && p->algo) ? 2 : 1); - #else - 1; - #endif -} - -UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) -{ - CLzmaEncProps props = *props2; - LzmaEncProps_Normalize(&props); - return props.dictSize; -} - -/* #define LZMA_LOG_BSR */ -/* Define it for Intel's CPU */ - - -#ifdef LZMA_LOG_BSR - -#define kDicLogSizeMaxCompress 30 - -#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } - -static UInt32 GetPosSlot1(UInt32 pos) -{ - UInt32 res; - BSR2_RET(pos, res); - return res; -} -#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } -#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } - -#else - -#define kNumLogBits (9 + (int)sizeof(size_t) / 2) -#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) - -void LzmaEnc_FastPosInit(Byte *g_FastPos) -{ - int c = 2, slotFast; - g_FastPos[0] = 0; - g_FastPos[1] = 1; - - for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) - { - UInt32 k = (1 << ((slotFast >> 1) - 1)); - UInt32 j; - for (j = 0; j < k; j++, c++) - g_FastPos[c] = (Byte)slotFast; - } -} - -#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ - (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ - res = p->g_FastPos[pos >> i] + (i * 2); } -/* -#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ - p->g_FastPos[pos >> 6] + 12 : \ - p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } -*/ - -#define GetPosSlot1(pos) p->g_FastPos[pos] -#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } -#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } - -#endif - - -#define LZMA_NUM_REPS 4 - -typedef unsigned CState; - -typedef struct _COptimal -{ - UInt32 price; - - CState state; - int prev1IsChar; - int prev2; - - UInt32 posPrev2; - UInt32 backPrev2; - - UInt32 posPrev; - UInt32 backPrev; - UInt32 backs[LZMA_NUM_REPS]; -} COptimal; - -#define kNumOpts (1 << 12) - -#define kNumLenToPosStates 4 -#define kNumPosSlotBits 6 -#define kDicLogSizeMin 0 -#define kDicLogSizeMax 32 -#define kDistTableSizeMax (kDicLogSizeMax * 2) - - -#define kNumAlignBits 4 -#define kAlignTableSize (1 << kNumAlignBits) -#define kAlignMask (kAlignTableSize - 1) - -#define kStartPosModelIndex 4 -#define kEndPosModelIndex 14 -#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) - -#define kNumFullDistances (1 << (kEndPosModelIndex / 2)) - -#ifdef _LZMA_PROB32 -#define CLzmaProb UInt32 -#else -#define CLzmaProb UInt16 -#endif - -#define LZMA_PB_MAX 4 -#define LZMA_LC_MAX 8 -#define LZMA_LP_MAX 4 - -#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) - - -#define kLenNumLowBits 3 -#define kLenNumLowSymbols (1 << kLenNumLowBits) -#define kLenNumMidBits 3 -#define kLenNumMidSymbols (1 << kLenNumMidBits) -#define kLenNumHighBits 8 -#define kLenNumHighSymbols (1 << kLenNumHighBits) - -#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) - -#define LZMA_MATCH_LEN_MIN 2 -#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) - -#define kNumStates 12 - -typedef struct -{ - CLzmaProb choice; - CLzmaProb choice2; - CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; - CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; - CLzmaProb high[kLenNumHighSymbols]; -} CLenEnc; - -typedef struct -{ - CLenEnc p; - UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; - UInt32 tableSize; - UInt32 counters[LZMA_NUM_PB_STATES_MAX]; -} CLenPriceEnc; - -typedef struct _CRangeEnc -{ - UInt32 range; - Byte cache; - UInt64 low; - UInt64 cacheSize; - Byte *buf; - Byte *bufLim; - Byte *bufBase; - ISeqOutStream *outStream; - UInt64 processed; - SRes res; -} CRangeEnc; - -typedef struct _CSeqInStreamBuf -{ - ISeqInStream funcTable; - const Byte *data; - SizeT rem; -} CSeqInStreamBuf; - -static SRes MyRead(void *pp, void *data, size_t *size) -{ - size_t curSize = *size; - CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; - if (p->rem < curSize) - curSize = p->rem; - memcpy(data, p->data, curSize); - p->rem -= curSize; - p->data += curSize; - *size = curSize; - return SZ_OK; -} - -typedef struct -{ - CLzmaProb *litProbs; - - CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; - CLzmaProb isRep[kNumStates]; - CLzmaProb isRepG0[kNumStates]; - CLzmaProb isRepG1[kNumStates]; - CLzmaProb isRepG2[kNumStates]; - CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; - - CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; - CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; - CLzmaProb posAlignEncoder[1 << kNumAlignBits]; - - CLenPriceEnc lenEnc; - CLenPriceEnc repLenEnc; - - UInt32 reps[LZMA_NUM_REPS]; - UInt32 state; -} CSaveState; - -typedef struct _CLzmaEnc -{ - IMatchFinder matchFinder; - void *matchFinderObj; - - #ifdef COMPRESS_MF_MT - Bool mtMode; - CMatchFinderMt matchFinderMt; - #endif - - CMatchFinder matchFinderBase; - - #ifdef COMPRESS_MF_MT - Byte pad[128]; - #endif - - UInt32 optimumEndIndex; - UInt32 optimumCurrentIndex; - - UInt32 longestMatchLength; - UInt32 numPairs; - UInt32 numAvail; - COptimal opt[kNumOpts]; - - #ifndef LZMA_LOG_BSR - Byte g_FastPos[1 << kNumLogBits]; - #endif - - UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; - UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; - UInt32 numFastBytes; - UInt32 additionalOffset; - UInt32 reps[LZMA_NUM_REPS]; - UInt32 state; - - UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; - UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; - UInt32 alignPrices[kAlignTableSize]; - UInt32 alignPriceCount; - - UInt32 distTableSize; - - unsigned lc, lp, pb; - unsigned lpMask, pbMask; - - CLzmaProb *litProbs; - - CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; - CLzmaProb isRep[kNumStates]; - CLzmaProb isRepG0[kNumStates]; - CLzmaProb isRepG1[kNumStates]; - CLzmaProb isRepG2[kNumStates]; - CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; - - CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; - CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; - CLzmaProb posAlignEncoder[1 << kNumAlignBits]; - - CLenPriceEnc lenEnc; - CLenPriceEnc repLenEnc; - - unsigned lclp; - - Bool fastMode; - - CRangeEnc rc; - - Bool writeEndMark; - UInt64 nowPos64; - UInt32 matchPriceCount; - Bool finished; - Bool multiThread; - - SRes result; - UInt32 dictSize; - UInt32 matchFinderCycles; - - ISeqInStream *inStream; - CSeqInStreamBuf seqBufInStream; - - CSaveState saveState; -} CLzmaEnc; - -void LzmaEnc_SaveState(CLzmaEncHandle pp) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - CSaveState *dest = &p->saveState; - int i; - dest->lenEnc = p->lenEnc; - dest->repLenEnc = p->repLenEnc; - dest->state = p->state; - - for (i = 0; i < kNumStates; i++) - { - memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); - memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); - } - for (i = 0; i < kNumLenToPosStates; i++) - memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); - memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); - memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); - memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); - memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); - memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); - memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); - memcpy(dest->reps, p->reps, sizeof(p->reps)); - memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); -} - -void LzmaEnc_RestoreState(CLzmaEncHandle pp) -{ - CLzmaEnc *dest = (CLzmaEnc *)pp; - const CSaveState *p = &dest->saveState; - int i; - dest->lenEnc = p->lenEnc; - dest->repLenEnc = p->repLenEnc; - dest->state = p->state; - - for (i = 0; i < kNumStates; i++) - { - memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); - memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); - } - for (i = 0; i < kNumLenToPosStates; i++) - memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); - memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); - memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); - memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); - memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); - memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); - memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); - memcpy(dest->reps, p->reps, sizeof(p->reps)); - memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); -} - -SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - CLzmaEncProps props = *props2; - LzmaEncProps_Normalize(&props); - - if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || - props.dictSize > (1U << kDicLogSizeMaxCompress) || props.dictSize > (1U << 30)) - return SZ_ERROR_PARAM; - p->dictSize = props.dictSize; - p->matchFinderCycles = props.mc; - { - unsigned fb = props.fb; - if (fb < 5) - fb = 5; - if (fb > LZMA_MATCH_LEN_MAX) - fb = LZMA_MATCH_LEN_MAX; - p->numFastBytes = fb; - } - p->lc = props.lc; - p->lp = props.lp; - p->pb = props.pb; - p->fastMode = (props.algo == 0); - p->matchFinderBase.btMode = props.btMode; - { - UInt32 numHashBytes = 4; - if (props.btMode) - { - if (props.numHashBytes < 2) - numHashBytes = 2; - else if (props.numHashBytes < 4) - numHashBytes = props.numHashBytes; - } - p->matchFinderBase.numHashBytes = numHashBytes; - } - - p->matchFinderBase.cutValue = props.mc; - - p->writeEndMark = props.writeEndMark; - - #ifdef COMPRESS_MF_MT - /* - if (newMultiThread != _multiThread) - { - ReleaseMatchFinder(); - _multiThread = newMultiThread; - } - */ - p->multiThread = (props.numThreads > 1); - #endif - - return SZ_OK; -} - -static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; -static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; -static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; -static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; - -#define IsCharState(s) ((s) < 7) - -#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) - -#define kInfinityPrice (1 << 30) - -static void RangeEnc_Construct(CRangeEnc *p) -{ - p->outStream = 0; - p->bufBase = 0; -} - -#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) - -#define RC_BUF_SIZE (1 << 16) -static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) -{ - if (p->bufBase == 0) - { - p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); - if (p->bufBase == 0) - return 0; - p->bufLim = p->bufBase + RC_BUF_SIZE; - } - return 1; -} - -static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->bufBase); - p->bufBase = 0; -} - -static void RangeEnc_Init(CRangeEnc *p) -{ - /* Stream.Init(); */ - p->low = 0; - p->range = 0xFFFFFFFF; - p->cacheSize = 1; - p->cache = 0; - - p->buf = p->bufBase; - - p->processed = 0; - p->res = SZ_OK; -} - -static void RangeEnc_FlushStream(CRangeEnc *p) -{ - size_t num; - if (p->res != SZ_OK) - return; - num = p->buf - p->bufBase; - if (num != p->outStream->Write(p->outStream, p->bufBase, num)) - p->res = SZ_ERROR_WRITE; - p->processed += num; - p->buf = p->bufBase; -} - -static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) -{ - if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) - { - Byte temp = p->cache; - do - { - Byte *buf = p->buf; - *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); - p->buf = buf; - if (buf == p->bufLim) - RangeEnc_FlushStream(p); - temp = 0xFF; - } - while (--p->cacheSize != 0); - p->cache = (Byte)((UInt32)p->low >> 24); - } - p->cacheSize++; - p->low = (UInt32)p->low << 8; -} - -static void RangeEnc_FlushData(CRangeEnc *p) -{ - int i; - for (i = 0; i < 5; i++) - RangeEnc_ShiftLow(p); -} - -static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) -{ - do - { - p->range >>= 1; - p->low += p->range & (0 - ((value >> --numBits) & 1)); - if (p->range < kTopValue) - { - p->range <<= 8; - RangeEnc_ShiftLow(p); - } - } - while (numBits != 0); -} - -static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) -{ - UInt32 ttt = *prob; - UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; - if (symbol == 0) - { - p->range = newBound; - ttt += (kBitModelTotal - ttt) >> kNumMoveBits; - } - else - { - p->low += newBound; - p->range -= newBound; - ttt -= ttt >> kNumMoveBits; - } - *prob = (CLzmaProb)ttt; - if (p->range < kTopValue) - { - p->range <<= 8; - RangeEnc_ShiftLow(p); - } -} - -static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) -{ - symbol |= 0x100; - do - { - RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); - symbol <<= 1; - } - while (symbol < 0x10000); -} - -static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) -{ - UInt32 offs = 0x100; - symbol |= 0x100; - do - { - matchByte <<= 1; - RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); - symbol <<= 1; - offs &= ~(matchByte ^ symbol); - } - while (symbol < 0x10000); -} - -void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) -{ - UInt32 i; - for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) - { - const int kCyclesBits = kNumBitPriceShiftBits; - UInt32 w = i; - UInt32 bitCount = 0; - int j; - for (j = 0; j < kCyclesBits; j++) - { - w = w * w; - bitCount <<= 1; - while (w >= ((UInt32)1 << 16)) - { - w >>= 1; - bitCount++; - } - } - ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); - } -} - - -#define GET_PRICE(prob, symbol) \ - p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; - -#define GET_PRICEa(prob, symbol) \ - ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; - -#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] -#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] - -#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] -#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] - -static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) -{ - UInt32 price = 0; - symbol |= 0x100; - do - { - price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); - symbol <<= 1; - } - while (symbol < 0x10000); - return price; -} - -static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) -{ - UInt32 price = 0; - UInt32 offs = 0x100; - symbol |= 0x100; - do - { - matchByte <<= 1; - price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); - symbol <<= 1; - offs &= ~(matchByte ^ symbol); - } - while (symbol < 0x10000); - return price; -} - - -static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) -{ - UInt32 m = 1; - int i; - for (i = numBitLevels; i != 0;) - { - UInt32 bit; - i--; - bit = (symbol >> i) & 1; - RangeEnc_EncodeBit(rc, probs + m, bit); - m = (m << 1) | bit; - } -} - -static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) -{ - UInt32 m = 1; - int i; - for (i = 0; i < numBitLevels; i++) - { - UInt32 bit = symbol & 1; - RangeEnc_EncodeBit(rc, probs + m, bit); - m = (m << 1) | bit; - symbol >>= 1; - } -} - -static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) -{ - UInt32 price = 0; - symbol |= (1 << numBitLevels); - while (symbol != 1) - { - price += GET_PRICEa(probs[symbol >> 1], symbol & 1); - symbol >>= 1; - } - return price; -} - -static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) -{ - UInt32 price = 0; - UInt32 m = 1; - int i; - for (i = numBitLevels; i != 0; i--) - { - UInt32 bit = symbol & 1; - symbol >>= 1; - price += GET_PRICEa(probs[m], bit); - m = (m << 1) | bit; - } - return price; -} - - -static void LenEnc_Init(CLenEnc *p) -{ - unsigned i; - p->choice = p->choice2 = kProbInitValue; - for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) - p->low[i] = kProbInitValue; - for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) - p->mid[i] = kProbInitValue; - for (i = 0; i < kLenNumHighSymbols; i++) - p->high[i] = kProbInitValue; -} - -static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) -{ - if (symbol < kLenNumLowSymbols) - { - RangeEnc_EncodeBit(rc, &p->choice, 0); - RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); - } - else - { - RangeEnc_EncodeBit(rc, &p->choice, 1); - if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) - { - RangeEnc_EncodeBit(rc, &p->choice2, 0); - RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); - } - else - { - RangeEnc_EncodeBit(rc, &p->choice2, 1); - RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); - } - } -} - -static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) -{ - UInt32 a0 = GET_PRICE_0a(p->choice); - UInt32 a1 = GET_PRICE_1a(p->choice); - UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); - UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); - UInt32 i = 0; - for (i = 0; i < kLenNumLowSymbols; i++) - { - if (i >= numSymbols) - return; - prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); - } - for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) - { - if (i >= numSymbols) - return; - prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); - } - for (; i < numSymbols; i++) - prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); -} - -static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) -{ - LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); - p->counters[posState] = p->tableSize; -} - -static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) -{ - UInt32 posState; - for (posState = 0; posState < numPosStates; posState++) - LenPriceEnc_UpdateTable(p, posState, ProbPrices); -} - -static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) -{ - LenEnc_Encode(&p->p, rc, symbol, posState); - if (updatePrice) - if (--p->counters[posState] == 0) - LenPriceEnc_UpdateTable(p, posState, ProbPrices); -} - - - - -static void MovePos(CLzmaEnc *p, UInt32 num) -{ - #ifdef SHOW_STAT - ttt += num; - printf("\n MovePos %d", num); - #endif - if (num != 0) - { - p->additionalOffset += num; - p->matchFinder.Skip(p->matchFinderObj, num); - } -} - -static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) -{ - UInt32 lenRes = 0, numPairs; - p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); - numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); - #ifdef SHOW_STAT - printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); - ttt++; - { - UInt32 i; - for (i = 0; i < numPairs; i += 2) - printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); - } - #endif - if (numPairs > 0) - { - lenRes = p->matches[numPairs - 2]; - if (lenRes == p->numFastBytes) - { - const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; - UInt32 distance = p->matches[numPairs - 1] + 1; - UInt32 numAvail = p->numAvail; - if (numAvail > LZMA_MATCH_LEN_MAX) - numAvail = LZMA_MATCH_LEN_MAX; - { - const Byte *pby2 = pby - distance; - for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); - } - } - } - p->additionalOffset++; - *numDistancePairsRes = numPairs; - return lenRes; -} - - -#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; -#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; -#define IsShortRep(p) ((p)->backPrev == 0) - -static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) -{ - return - GET_PRICE_0(p->isRepG0[state]) + - GET_PRICE_0(p->isRep0Long[state][posState]); -} - -static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) -{ - UInt32 price; - if (repIndex == 0) - { - price = GET_PRICE_0(p->isRepG0[state]); - price += GET_PRICE_1(p->isRep0Long[state][posState]); - } - else - { - price = GET_PRICE_1(p->isRepG0[state]); - if (repIndex == 1) - price += GET_PRICE_0(p->isRepG1[state]); - else - { - price += GET_PRICE_1(p->isRepG1[state]); - price += GET_PRICE(p->isRepG2[state], repIndex - 2); - } - } - return price; -} - -static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) -{ - return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + - GetPureRepPrice(p, repIndex, state, posState); -} - -static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) -{ - UInt32 posMem = p->opt[cur].posPrev; - UInt32 backMem = p->opt[cur].backPrev; - p->optimumEndIndex = cur; - do - { - if (p->opt[cur].prev1IsChar) - { - MakeAsChar(&p->opt[posMem]) - p->opt[posMem].posPrev = posMem - 1; - if (p->opt[cur].prev2) - { - p->opt[posMem - 1].prev1IsChar = False; - p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; - p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; - } - } - { - UInt32 posPrev = posMem; - UInt32 backCur = backMem; - - backMem = p->opt[posPrev].backPrev; - posMem = p->opt[posPrev].posPrev; - - p->opt[posPrev].backPrev = backCur; - p->opt[posPrev].posPrev = cur; - cur = posPrev; - } - } - while (cur != 0); - *backRes = p->opt[0].backPrev; - p->optimumCurrentIndex = p->opt[0].posPrev; - return p->optimumCurrentIndex; -} - -#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) - -static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) -{ - UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; - UInt32 matchPrice, repMatchPrice, normalMatchPrice; - UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; - UInt32 *matches; - const Byte *data; - Byte curByte, matchByte; - if (p->optimumEndIndex != p->optimumCurrentIndex) - { - const COptimal *opt = &p->opt[p->optimumCurrentIndex]; - UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; - *backRes = opt->backPrev; - p->optimumCurrentIndex = opt->posPrev; - return lenRes; - } - p->optimumCurrentIndex = p->optimumEndIndex = 0; - - if (p->additionalOffset == 0) - mainLen = ReadMatchDistances(p, &numPairs); - else - { - mainLen = p->longestMatchLength; - numPairs = p->numPairs; - } - - numAvail = p->numAvail; - if (numAvail < 2) - { - *backRes = (UInt32)(-1); - return 1; - } - if (numAvail > LZMA_MATCH_LEN_MAX) - numAvail = LZMA_MATCH_LEN_MAX; - - data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; - repMaxIndex = 0; - for (i = 0; i < LZMA_NUM_REPS; i++) - { - UInt32 lenTest; - const Byte *data2; - reps[i] = p->reps[i]; - data2 = data - (reps[i] + 1); - if (data[0] != data2[0] || data[1] != data2[1]) - { - repLens[i] = 0; - continue; - } - for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); - repLens[i] = lenTest; - if (lenTest > repLens[repMaxIndex]) - repMaxIndex = i; - } - if (repLens[repMaxIndex] >= p->numFastBytes) - { - UInt32 lenRes; - *backRes = repMaxIndex; - lenRes = repLens[repMaxIndex]; - MovePos(p, lenRes - 1); - return lenRes; - } - - matches = p->matches; - if (mainLen >= p->numFastBytes) - { - *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; - MovePos(p, mainLen - 1); - return mainLen; - } - curByte = *data; - matchByte = *(data - (reps[0] + 1)); - - if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) - { - *backRes = (UInt32)-1; - return 1; - } - - p->opt[0].state = (CState)p->state; - - posState = (position & p->pbMask); - - { - const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); - p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + - (!IsCharState(p->state) ? - LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : - LitEnc_GetPrice(probs, curByte, p->ProbPrices)); - } - - MakeAsChar(&p->opt[1]); - - matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); - repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); - - if (matchByte == curByte) - { - UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); - if (shortRepPrice < p->opt[1].price) - { - p->opt[1].price = shortRepPrice; - MakeAsShortRep(&p->opt[1]); - } - } - lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); - - if (lenEnd < 2) - { - *backRes = p->opt[1].backPrev; - return 1; - } - - p->opt[1].posPrev = 0; - for (i = 0; i < LZMA_NUM_REPS; i++) - p->opt[0].backs[i] = reps[i]; - - len = lenEnd; - do - p->opt[len--].price = kInfinityPrice; - while (len >= 2); - - for (i = 0; i < LZMA_NUM_REPS; i++) - { - UInt32 repLen = repLens[i]; - UInt32 price; - if (repLen < 2) - continue; - price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); - do - { - UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; - COptimal *opt = &p->opt[repLen]; - if (curAndLenPrice < opt->price) - { - opt->price = curAndLenPrice; - opt->posPrev = 0; - opt->backPrev = i; - opt->prev1IsChar = False; - } - } - while (--repLen >= 2); - } - - normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); - - len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); - if (len <= mainLen) - { - UInt32 offs = 0; - while (len > matches[offs]) - offs += 2; - for (; ; len++) - { - COptimal *opt; - UInt32 distance = matches[offs + 1]; - - UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; - UInt32 lenToPosState = GetLenToPosState(len); - if (distance < kNumFullDistances) - curAndLenPrice += p->distancesPrices[lenToPosState][distance]; - else - { - UInt32 slot; - GetPosSlot2(distance, slot); - curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; - } - opt = &p->opt[len]; - if (curAndLenPrice < opt->price) - { - opt->price = curAndLenPrice; - opt->posPrev = 0; - opt->backPrev = distance + LZMA_NUM_REPS; - opt->prev1IsChar = False; - } - if (len == matches[offs]) - { - offs += 2; - if (offs == numPairs) - break; - } - } - } - - cur = 0; - - #ifdef SHOW_STAT2 - if (position >= 0) - { - unsigned i; - printf("\n pos = %4X", position); - for (i = cur; i <= lenEnd; i++) - printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); - } - #endif - - for (;;) - { - UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; - UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; - Bool nextIsChar; - Byte curByte, matchByte; - const Byte *data; - COptimal *curOpt; - COptimal *nextOpt; - - cur++; - if (cur == lenEnd) - return Backward(p, backRes, cur); - - newLen = ReadMatchDistances(p, &numPairs); - if (newLen >= p->numFastBytes) - { - p->numPairs = numPairs; - p->longestMatchLength = newLen; - return Backward(p, backRes, cur); - } - position++; - curOpt = &p->opt[cur]; - posPrev = curOpt->posPrev; - if (curOpt->prev1IsChar) - { - posPrev--; - if (curOpt->prev2) - { - state = p->opt[curOpt->posPrev2].state; - if (curOpt->backPrev2 < LZMA_NUM_REPS) - state = kRepNextStates[state]; - else - state = kMatchNextStates[state]; - } - else - state = p->opt[posPrev].state; - state = kLiteralNextStates[state]; - } - else - state = p->opt[posPrev].state; - if (posPrev == cur - 1) - { - if (IsShortRep(curOpt)) - state = kShortRepNextStates[state]; - else - state = kLiteralNextStates[state]; - } - else - { - UInt32 pos; - const COptimal *prevOpt; - if (curOpt->prev1IsChar && curOpt->prev2) - { - posPrev = curOpt->posPrev2; - pos = curOpt->backPrev2; - state = kRepNextStates[state]; - } - else - { - pos = curOpt->backPrev; - if (pos < LZMA_NUM_REPS) - state = kRepNextStates[state]; - else - state = kMatchNextStates[state]; - } - prevOpt = &p->opt[posPrev]; - if (pos < LZMA_NUM_REPS) - { - UInt32 i; - reps[0] = prevOpt->backs[pos]; - for (i = 1; i <= pos; i++) - reps[i] = prevOpt->backs[i - 1]; - for (; i < LZMA_NUM_REPS; i++) - reps[i] = prevOpt->backs[i]; - } - else - { - UInt32 i; - reps[0] = (pos - LZMA_NUM_REPS); - for (i = 1; i < LZMA_NUM_REPS; i++) - reps[i] = prevOpt->backs[i - 1]; - } - } - curOpt->state = (CState)state; - - curOpt->backs[0] = reps[0]; - curOpt->backs[1] = reps[1]; - curOpt->backs[2] = reps[2]; - curOpt->backs[3] = reps[3]; - - curPrice = curOpt->price; - nextIsChar = False; - data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; - curByte = *data; - matchByte = *(data - (reps[0] + 1)); - - posState = (position & p->pbMask); - - curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); - { - const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); - curAnd1Price += - (!IsCharState(state) ? - LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : - LitEnc_GetPrice(probs, curByte, p->ProbPrices)); - } - - nextOpt = &p->opt[cur + 1]; - - if (curAnd1Price < nextOpt->price) - { - nextOpt->price = curAnd1Price; - nextOpt->posPrev = cur; - MakeAsChar(nextOpt); - nextIsChar = True; - } - - matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); - repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); - - if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) - { - UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); - if (shortRepPrice <= nextOpt->price) - { - nextOpt->price = shortRepPrice; - nextOpt->posPrev = cur; - MakeAsShortRep(nextOpt); - nextIsChar = True; - } - } - numAvailFull = p->numAvail; - { - UInt32 temp = kNumOpts - 1 - cur; - if (temp < numAvailFull) - numAvailFull = temp; - } - - if (numAvailFull < 2) - continue; - numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); - - if (!nextIsChar && matchByte != curByte) /* speed optimization */ - { - /* try Literal + rep0 */ - UInt32 temp; - UInt32 lenTest2; - const Byte *data2 = data - (reps[0] + 1); - UInt32 limit = p->numFastBytes + 1; - if (limit > numAvailFull) - limit = numAvailFull; - - for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); - lenTest2 = temp - 1; - if (lenTest2 >= 2) - { - UInt32 state2 = kLiteralNextStates[state]; - UInt32 posStateNext = (position + 1) & p->pbMask; - UInt32 nextRepMatchPrice = curAnd1Price + - GET_PRICE_1(p->isMatch[state2][posStateNext]) + - GET_PRICE_1(p->isRep[state2]); - /* for (; lenTest2 >= 2; lenTest2--) */ - { - UInt32 curAndLenPrice; - COptimal *opt; - UInt32 offset = cur + 1 + lenTest2; - while (lenEnd < offset) - p->opt[++lenEnd].price = kInfinityPrice; - curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); - opt = &p->opt[offset]; - if (curAndLenPrice < opt->price) - { - opt->price = curAndLenPrice; - opt->posPrev = cur + 1; - opt->backPrev = 0; - opt->prev1IsChar = True; - opt->prev2 = False; - } - } - } - } - - startLen = 2; /* speed optimization */ - { - UInt32 repIndex; - for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) - { - UInt32 lenTest; - UInt32 lenTestTemp; - UInt32 price; - const Byte *data2 = data - (reps[repIndex] + 1); - if (data[0] != data2[0] || data[1] != data2[1]) - continue; - for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); - while (lenEnd < cur + lenTest) - p->opt[++lenEnd].price = kInfinityPrice; - lenTestTemp = lenTest; - price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); - do - { - UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; - COptimal *opt = &p->opt[cur + lenTest]; - if (curAndLenPrice < opt->price) - { - opt->price = curAndLenPrice; - opt->posPrev = cur; - opt->backPrev = repIndex; - opt->prev1IsChar = False; - } - } - while (--lenTest >= 2); - lenTest = lenTestTemp; - - if (repIndex == 0) - startLen = lenTest + 1; - - /* if (_maxMode) */ - { - UInt32 lenTest2 = lenTest + 1; - UInt32 limit = lenTest2 + p->numFastBytes; - UInt32 nextRepMatchPrice; - if (limit > numAvailFull) - limit = numAvailFull; - for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); - lenTest2 -= lenTest + 1; - if (lenTest2 >= 2) - { - UInt32 state2 = kRepNextStates[state]; - UInt32 posStateNext = (position + lenTest) & p->pbMask; - UInt32 curAndLenCharPrice = - price + p->repLenEnc.prices[posState][lenTest - 2] + - GET_PRICE_0(p->isMatch[state2][posStateNext]) + - LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), - data[lenTest], data2[lenTest], p->ProbPrices); - state2 = kLiteralNextStates[state2]; - posStateNext = (position + lenTest + 1) & p->pbMask; - nextRepMatchPrice = curAndLenCharPrice + - GET_PRICE_1(p->isMatch[state2][posStateNext]) + - GET_PRICE_1(p->isRep[state2]); - - /* for (; lenTest2 >= 2; lenTest2--) */ - { - UInt32 curAndLenPrice; - COptimal *opt; - UInt32 offset = cur + lenTest + 1 + lenTest2; - while (lenEnd < offset) - p->opt[++lenEnd].price = kInfinityPrice; - curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); - opt = &p->opt[offset]; - if (curAndLenPrice < opt->price) - { - opt->price = curAndLenPrice; - opt->posPrev = cur + lenTest + 1; - opt->backPrev = 0; - opt->prev1IsChar = True; - opt->prev2 = True; - opt->posPrev2 = cur; - opt->backPrev2 = repIndex; - } - } - } - } - } - } - /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ - if (newLen > numAvail) - { - newLen = numAvail; - for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); - matches[numPairs] = newLen; - numPairs += 2; - } - if (newLen >= startLen) - { - UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); - UInt32 offs, curBack, posSlot; - UInt32 lenTest; - while (lenEnd < cur + newLen) - p->opt[++lenEnd].price = kInfinityPrice; - - offs = 0; - while (startLen > matches[offs]) - offs += 2; - curBack = matches[offs + 1]; - GetPosSlot2(curBack, posSlot); - for (lenTest = /*2*/ startLen; ; lenTest++) - { - UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; - UInt32 lenToPosState = GetLenToPosState(lenTest); - COptimal *opt; - if (curBack < kNumFullDistances) - curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; - else - curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; - - opt = &p->opt[cur + lenTest]; - if (curAndLenPrice < opt->price) - { - opt->price = curAndLenPrice; - opt->posPrev = cur; - opt->backPrev = curBack + LZMA_NUM_REPS; - opt->prev1IsChar = False; - } - - if (/*_maxMode && */lenTest == matches[offs]) - { - /* Try Match + Literal + Rep0 */ - const Byte *data2 = data - (curBack + 1); - UInt32 lenTest2 = lenTest + 1; - UInt32 limit = lenTest2 + p->numFastBytes; - UInt32 nextRepMatchPrice; - if (limit > numAvailFull) - limit = numAvailFull; - for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); - lenTest2 -= lenTest + 1; - if (lenTest2 >= 2) - { - UInt32 state2 = kMatchNextStates[state]; - UInt32 posStateNext = (position + lenTest) & p->pbMask; - UInt32 curAndLenCharPrice = curAndLenPrice + - GET_PRICE_0(p->isMatch[state2][posStateNext]) + - LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), - data[lenTest], data2[lenTest], p->ProbPrices); - state2 = kLiteralNextStates[state2]; - posStateNext = (posStateNext + 1) & p->pbMask; - nextRepMatchPrice = curAndLenCharPrice + - GET_PRICE_1(p->isMatch[state2][posStateNext]) + - GET_PRICE_1(p->isRep[state2]); - - /* for (; lenTest2 >= 2; lenTest2--) */ - { - UInt32 offset = cur + lenTest + 1 + lenTest2; - UInt32 curAndLenPrice; - COptimal *opt; - while (lenEnd < offset) - p->opt[++lenEnd].price = kInfinityPrice; - curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); - opt = &p->opt[offset]; - if (curAndLenPrice < opt->price) - { - opt->price = curAndLenPrice; - opt->posPrev = cur + lenTest + 1; - opt->backPrev = 0; - opt->prev1IsChar = True; - opt->prev2 = True; - opt->posPrev2 = cur; - opt->backPrev2 = curBack + LZMA_NUM_REPS; - } - } - } - offs += 2; - if (offs == numPairs) - break; - curBack = matches[offs + 1]; - if (curBack >= kNumFullDistances) - GetPosSlot2(curBack, posSlot); - } - } - } - } -} - -#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) - -static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) -{ - UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; - const Byte *data; - const UInt32 *matches; - - if (p->additionalOffset == 0) - mainLen = ReadMatchDistances(p, &numPairs); - else - { - mainLen = p->longestMatchLength; - numPairs = p->numPairs; - } - - numAvail = p->numAvail; - *backRes = (UInt32)-1; - if (numAvail < 2) - return 1; - if (numAvail > LZMA_MATCH_LEN_MAX) - numAvail = LZMA_MATCH_LEN_MAX; - data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; - - repLen = repIndex = 0; - for (i = 0; i < LZMA_NUM_REPS; i++) - { - UInt32 len; - const Byte *data2 = data - (p->reps[i] + 1); - if (data[0] != data2[0] || data[1] != data2[1]) - continue; - for (len = 2; len < numAvail && data[len] == data2[len]; len++); - if (len >= p->numFastBytes) - { - *backRes = i; - MovePos(p, len - 1); - return len; - } - if (len > repLen) - { - repIndex = i; - repLen = len; - } - } - - matches = p->matches; - if (mainLen >= p->numFastBytes) - { - *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; - MovePos(p, mainLen - 1); - return mainLen; - } - - mainDist = 0; /* for GCC */ - if (mainLen >= 2) - { - mainDist = matches[numPairs - 1]; - while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) - { - if (!ChangePair(matches[numPairs - 3], mainDist)) - break; - numPairs -= 2; - mainLen = matches[numPairs - 2]; - mainDist = matches[numPairs - 1]; - } - if (mainLen == 2 && mainDist >= 0x80) - mainLen = 1; - } - - if (repLen >= 2 && ( - (repLen + 1 >= mainLen) || - (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || - (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) - { - *backRes = repIndex; - MovePos(p, repLen - 1); - return repLen; - } - - if (mainLen < 2 || numAvail <= 2) - return 1; - - p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); - if (p->longestMatchLength >= 2) - { - UInt32 newDistance = matches[p->numPairs - 1]; - if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || - (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || - (p->longestMatchLength > mainLen + 1) || - (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) - return 1; - } - - data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; - for (i = 0; i < LZMA_NUM_REPS; i++) - { - UInt32 len, limit; - const Byte *data2 = data - (p->reps[i] + 1); - if (data[0] != data2[0] || data[1] != data2[1]) - continue; - limit = mainLen - 1; - for (len = 2; len < limit && data[len] == data2[len]; len++); - if (len >= limit) - return 1; - } - *backRes = mainDist + LZMA_NUM_REPS; - MovePos(p, mainLen - 2); - return mainLen; -} - -static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) -{ - UInt32 len; - RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); - RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); - p->state = kMatchNextStates[p->state]; - len = LZMA_MATCH_LEN_MIN; - LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); - RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); - RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); - RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); -} - -static SRes CheckErrors(CLzmaEnc *p) -{ - if (p->result != SZ_OK) - return p->result; - if (p->rc.res != SZ_OK) - p->result = SZ_ERROR_WRITE; - if (p->matchFinderBase.result != SZ_OK) - p->result = SZ_ERROR_READ; - if (p->result != SZ_OK) - p->finished = True; - return p->result; -} - -static SRes Flush(CLzmaEnc *p, UInt32 nowPos) -{ - /* ReleaseMFStream(); */ - p->finished = True; - if (p->writeEndMark) - WriteEndMarker(p, nowPos & p->pbMask); - RangeEnc_FlushData(&p->rc); - RangeEnc_FlushStream(&p->rc); - return CheckErrors(p); -} - -static void FillAlignPrices(CLzmaEnc *p) -{ - UInt32 i; - for (i = 0; i < kAlignTableSize; i++) - p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); - p->alignPriceCount = 0; -} - -static void FillDistancesPrices(CLzmaEnc *p) -{ - UInt32 tempPrices[kNumFullDistances]; - UInt32 i, lenToPosState; - for (i = kStartPosModelIndex; i < kNumFullDistances; i++) - { - UInt32 posSlot = GetPosSlot1(i); - UInt32 footerBits = ((posSlot >> 1) - 1); - UInt32 base = ((2 | (posSlot & 1)) << footerBits); - tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); - } - - for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) - { - UInt32 posSlot; - const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; - UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; - for (posSlot = 0; posSlot < p->distTableSize; posSlot++) - posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); - for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) - posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); - - { - UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; - UInt32 i; - for (i = 0; i < kStartPosModelIndex; i++) - distancesPrices[i] = posSlotPrices[i]; - for (; i < kNumFullDistances; i++) - distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; - } - } - p->matchPriceCount = 0; -} - -void LzmaEnc_Construct(CLzmaEnc *p) -{ - RangeEnc_Construct(&p->rc); - MatchFinder_Construct(&p->matchFinderBase); - #ifdef COMPRESS_MF_MT - MatchFinderMt_Construct(&p->matchFinderMt); - p->matchFinderMt.MatchFinder = &p->matchFinderBase; - #endif - - { - CLzmaEncProps props; - LzmaEncProps_Init(&props); - LzmaEnc_SetProps(p, &props); - } - - #ifndef LZMA_LOG_BSR - LzmaEnc_FastPosInit(p->g_FastPos); - #endif - - LzmaEnc_InitPriceTables(p->ProbPrices); - p->litProbs = 0; - p->saveState.litProbs = 0; -} - -CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) -{ - void *p; - p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); - if (p != 0) - LzmaEnc_Construct((CLzmaEnc *)p); - return p; -} - -void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->litProbs); - alloc->Free(alloc, p->saveState.litProbs); - p->litProbs = 0; - p->saveState.litProbs = 0; -} - -void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) -{ - #ifdef COMPRESS_MF_MT - MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); - #endif - MatchFinder_Free(&p->matchFinderBase, allocBig); - LzmaEnc_FreeLits(p, alloc); - RangeEnc_Free(&p->rc, alloc); -} - -void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) -{ - LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); - alloc->Free(alloc, p); -} - -static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) -{ - UInt32 nowPos32, startPos32; - if (p->inStream != 0) - { - p->matchFinderBase.stream = p->inStream; - p->matchFinder.Init(p->matchFinderObj); - p->inStream = 0; - } - - if (p->finished) - return p->result; - RINOK(CheckErrors(p)); - - nowPos32 = (UInt32)p->nowPos64; - startPos32 = nowPos32; - - if (p->nowPos64 == 0) - { - UInt32 numPairs; - Byte curByte; - if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) - return Flush(p, nowPos32); - ReadMatchDistances(p, &numPairs); - RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); - p->state = kLiteralNextStates[p->state]; - curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); - LitEnc_Encode(&p->rc, p->litProbs, curByte); - p->additionalOffset--; - nowPos32++; - } - - if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) - for (;;) - { - UInt32 pos, len, posState; - - if (p->fastMode) - len = GetOptimumFast(p, &pos); - else - len = GetOptimum(p, nowPos32, &pos); - - #ifdef SHOW_STAT2 - printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); - #endif - - posState = nowPos32 & p->pbMask; - if (len == 1 && pos == (UInt32)-1) - { - Byte curByte; - CLzmaProb *probs; - const Byte *data; - - RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); - data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; - curByte = *data; - probs = LIT_PROBS(nowPos32, *(data - 1)); - if (IsCharState(p->state)) - LitEnc_Encode(&p->rc, probs, curByte); - else - LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); - p->state = kLiteralNextStates[p->state]; - } - else - { - RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); - if (pos < LZMA_NUM_REPS) - { - RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); - if (pos == 0) - { - RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); - RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); - } - else - { - UInt32 distance = p->reps[pos]; - RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); - if (pos == 1) - RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); - else - { - RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); - RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); - if (pos == 3) - p->reps[3] = p->reps[2]; - p->reps[2] = p->reps[1]; - } - p->reps[1] = p->reps[0]; - p->reps[0] = distance; - } - if (len == 1) - p->state = kShortRepNextStates[p->state]; - else - { - LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); - p->state = kRepNextStates[p->state]; - } - } - else - { - UInt32 posSlot; - RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); - p->state = kMatchNextStates[p->state]; - LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); - pos -= LZMA_NUM_REPS; - GetPosSlot(pos, posSlot); - RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); - - if (posSlot >= kStartPosModelIndex) - { - UInt32 footerBits = ((posSlot >> 1) - 1); - UInt32 base = ((2 | (posSlot & 1)) << footerBits); - UInt32 posReduced = pos - base; - - if (posSlot < kEndPosModelIndex) - RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); - else - { - RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); - RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); - p->alignPriceCount++; - } - } - p->reps[3] = p->reps[2]; - p->reps[2] = p->reps[1]; - p->reps[1] = p->reps[0]; - p->reps[0] = pos; - p->matchPriceCount++; - } - } - p->additionalOffset -= len; - nowPos32 += len; - if (p->additionalOffset == 0) - { - UInt32 processed; - if (!p->fastMode) - { - if (p->matchPriceCount >= (1 << 7)) - FillDistancesPrices(p); - if (p->alignPriceCount >= kAlignTableSize) - FillAlignPrices(p); - } - if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) - break; - processed = nowPos32 - startPos32; - if (useLimits) - { - if (processed + kNumOpts + 300 >= maxUnpackSize || - RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) - break; - } - else if (processed >= (1 << 15)) - { - p->nowPos64 += nowPos32 - startPos32; - return CheckErrors(p); - } - } - } - p->nowPos64 += nowPos32 - startPos32; - return Flush(p, nowPos32); -} - -#define kBigHashDicLimit ((UInt32)1 << 24) - -static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) -{ - UInt32 beforeSize = kNumOpts; - Bool btMode; - if (!RangeEnc_Alloc(&p->rc, alloc)) - return SZ_ERROR_MEM; - btMode = (p->matchFinderBase.btMode != 0); - #ifdef COMPRESS_MF_MT - p->mtMode = (p->multiThread && !p->fastMode && btMode); - #endif - - { - unsigned lclp = p->lc + p->lp; - if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) - { - LzmaEnc_FreeLits(p, alloc); - p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); - p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); - if (p->litProbs == 0 || p->saveState.litProbs == 0) - { - LzmaEnc_FreeLits(p, alloc); - return SZ_ERROR_MEM; - } - p->lclp = lclp; - } - } - - p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); - - if (beforeSize + p->dictSize < keepWindowSize) - beforeSize = keepWindowSize - p->dictSize; - - #ifdef COMPRESS_MF_MT - if (p->mtMode) - { - RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); - p->matchFinderObj = &p->matchFinderMt; - MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); - } - else - #endif - { - if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) - return SZ_ERROR_MEM; - p->matchFinderObj = &p->matchFinderBase; - MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); - } - return SZ_OK; -} - -void LzmaEnc_Init(CLzmaEnc *p) -{ - UInt32 i; - p->state = 0; - for (i = 0 ; i < LZMA_NUM_REPS; i++) - p->reps[i] = 0; - - RangeEnc_Init(&p->rc); - - - for (i = 0; i < kNumStates; i++) - { - UInt32 j; - for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) - { - p->isMatch[i][j] = kProbInitValue; - p->isRep0Long[i][j] = kProbInitValue; - } - p->isRep[i] = kProbInitValue; - p->isRepG0[i] = kProbInitValue; - p->isRepG1[i] = kProbInitValue; - p->isRepG2[i] = kProbInitValue; - } - - { - UInt32 num = 0x300 << (p->lp + p->lc); - for (i = 0; i < num; i++) - p->litProbs[i] = kProbInitValue; - } - - { - for (i = 0; i < kNumLenToPosStates; i++) - { - CLzmaProb *probs = p->posSlotEncoder[i]; - UInt32 j; - for (j = 0; j < (1 << kNumPosSlotBits); j++) - probs[j] = kProbInitValue; - } - } - { - for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) - p->posEncoders[i] = kProbInitValue; - } - - LenEnc_Init(&p->lenEnc.p); - LenEnc_Init(&p->repLenEnc.p); - - for (i = 0; i < (1 << kNumAlignBits); i++) - p->posAlignEncoder[i] = kProbInitValue; - - p->optimumEndIndex = 0; - p->optimumCurrentIndex = 0; - p->additionalOffset = 0; - - p->pbMask = (1 << p->pb) - 1; - p->lpMask = (1 << p->lp) - 1; -} - -void LzmaEnc_InitPrices(CLzmaEnc *p) -{ - if (!p->fastMode) - { - FillDistancesPrices(p); - FillAlignPrices(p); - } - - p->lenEnc.tableSize = - p->repLenEnc.tableSize = - p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; - LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); - LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); -} - -static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) -{ - UInt32 i; - for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) - if (p->dictSize <= ((UInt32)1 << i)) - break; - p->distTableSize = i * 2; - - p->finished = False; - p->result = SZ_OK; - RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); - LzmaEnc_Init(p); - LzmaEnc_InitPrices(p); - p->nowPos64 = 0; - return SZ_OK; -} - -static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, - ISzAlloc *alloc, ISzAlloc *allocBig) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - p->inStream = inStream; - p->rc.outStream = outStream; - return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); -} - -SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, - ISeqInStream *inStream, UInt32 keepWindowSize, - ISzAlloc *alloc, ISzAlloc *allocBig) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - p->inStream = inStream; - return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); -} - -static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) -{ - p->seqBufInStream.funcTable.Read = MyRead; - p->seqBufInStream.data = src; - p->seqBufInStream.rem = srcLen; -} - -SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, - UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - LzmaEnc_SetInputBuf(p, src, srcLen); - p->inStream = &p->seqBufInStream.funcTable; - return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); -} - -void LzmaEnc_Finish(CLzmaEncHandle pp) -{ - #ifdef COMPRESS_MF_MT - CLzmaEnc *p = (CLzmaEnc *)pp; - if (p->mtMode) - MatchFinderMt_ReleaseStream(&p->matchFinderMt); - #else - pp = pp; - #endif -} - -typedef struct _CSeqOutStreamBuf -{ - ISeqOutStream funcTable; - Byte *data; - SizeT rem; - Bool overflow; -} CSeqOutStreamBuf; - -static size_t MyWrite(void *pp, const void *data, size_t size) -{ - CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; - if (p->rem < size) - { - size = p->rem; - p->overflow = True; - } - memcpy(p->data, data, size); - p->rem -= size; - p->data += size; - return size; -} - - -UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) -{ - const CLzmaEnc *p = (CLzmaEnc *)pp; - return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); -} - -const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) -{ - const CLzmaEnc *p = (CLzmaEnc *)pp; - return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; -} - -SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, - Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - UInt64 nowPos64; - SRes res; - CSeqOutStreamBuf outStream; - - outStream.funcTable.Write = MyWrite; - outStream.data = dest; - outStream.rem = *destLen; - outStream.overflow = False; - - p->writeEndMark = False; - p->finished = False; - p->result = SZ_OK; - - if (reInit) - LzmaEnc_Init(p); - LzmaEnc_InitPrices(p); - nowPos64 = p->nowPos64; - RangeEnc_Init(&p->rc); - p->rc.outStream = &outStream.funcTable; - - res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); - - *unpackSize = (UInt32)(p->nowPos64 - nowPos64); - *destLen -= outStream.rem; - if (outStream.overflow) - return SZ_ERROR_OUTPUT_EOF; - - return res; -} - -SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, - ISzAlloc *alloc, ISzAlloc *allocBig) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - SRes res = SZ_OK; - - #ifdef COMPRESS_MF_MT - Byte allocaDummy[0x300]; - int i = 0; - for (i = 0; i < 16; i++) - allocaDummy[i] = (Byte)i; - #endif - - RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); - - for (;;) - { - res = LzmaEnc_CodeOneBlock(p, False, 0, 0); - if (res != SZ_OK || p->finished != 0) - break; - if (progress != 0) - { - res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); - if (res != SZ_OK) - { - res = SZ_ERROR_PROGRESS; - break; - } - } - } - LzmaEnc_Finish(pp); - return res; -} - -SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - int i; - UInt32 dictSize = p->dictSize; - if (*size < LZMA_PROPS_SIZE) - return SZ_ERROR_PARAM; - *size = LZMA_PROPS_SIZE; - props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); - - for (i = 11; i <= 30; i++) - { - if (dictSize <= ((UInt32)2 << i)) - { - dictSize = (2 << i); - break; - } - if (dictSize <= ((UInt32)3 << i)) - { - dictSize = (3 << i); - break; - } - } - - for (i = 0; i < 4; i++) - props[1 + i] = (Byte)(dictSize >> (8 * i)); - return SZ_OK; -} - -SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, - int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) -{ - SRes res; - CLzmaEnc *p = (CLzmaEnc *)pp; - - CSeqOutStreamBuf outStream; - - LzmaEnc_SetInputBuf(p, src, srcLen); - - outStream.funcTable.Write = MyWrite; - outStream.data = dest; - outStream.rem = *destLen; - outStream.overflow = False; - - p->writeEndMark = writeEndMark; - res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, - progress, alloc, allocBig); - - *destLen -= outStream.rem; - if (outStream.overflow) - return SZ_ERROR_OUTPUT_EOF; - return res; -} - -SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, - const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, - ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) -{ - CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); - SRes res; - if (p == 0) - return SZ_ERROR_MEM; - - res = LzmaEnc_SetProps(p, props); - if (res == SZ_OK) - { - res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); - if (res == SZ_OK) - res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, - writeEndMark, progress, alloc, allocBig); - } - - LzmaEnc_Destroy(p, alloc, allocBig); - return res; -} diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaEnc.h b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaEnc.h deleted file mode 100644 index bfbc7d2b9..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaEnc.h +++ /dev/null @@ -1,72 +0,0 @@ -/* LzmaEnc.h -- LZMA Encoder -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __LZMAENC_H -#define __LZMAENC_H - -#include "Types.h" - -#define LZMA_PROPS_SIZE 5 - -typedef struct _CLzmaEncProps -{ - int level; /* 0 <= level <= 9 */ - UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version - (1 << 12) <= dictSize <= (1 << 30) for 64-bit version - default = (1 << 24) */ - int lc; /* 0 <= lc <= 8, default = 3 */ - int lp; /* 0 <= lp <= 4, default = 0 */ - int pb; /* 0 <= pb <= 4, default = 2 */ - int algo; /* 0 - fast, 1 - normal, default = 1 */ - int fb; /* 5 <= fb <= 273, default = 32 */ - int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ - int numHashBytes; /* 2, 3 or 4, default = 4 */ - UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ - unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ - int numThreads; /* 1 or 2, default = 2 */ -} CLzmaEncProps; - -void LzmaEncProps_Init(CLzmaEncProps *p); -void LzmaEncProps_Normalize(CLzmaEncProps *p); -UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); - - -/* ---------- CLzmaEncHandle Interface ---------- */ - -/* LzmaEnc_* functions can return the following exit codes: -Returns: - SZ_OK - OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_PARAM - Incorrect paramater in props - SZ_ERROR_WRITE - Write callback error. - SZ_ERROR_PROGRESS - some break from progress callback - SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) -*/ - -typedef void * CLzmaEncHandle; - -CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); -void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); -SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); -SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); -SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, - ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); -SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, - int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); - -/* ---------- One Call Interface ---------- */ - -/* LzmaEncode -Return code: - SZ_OK - OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_PARAM - Incorrect paramater - SZ_ERROR_OUTPUT_EOF - output buffer overflow - SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) -*/ - -SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, - const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, - ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); - -#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaLib.c b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaLib.c deleted file mode 100644 index 6cc29da23..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaLib.c +++ /dev/null @@ -1,48 +0,0 @@ -/* LzmaLib.c -- LZMA library wrapper -2008-08-05 -Igor Pavlov -Public domain */ - -#include "LzmaEnc.h" -#include "LzmaDec.h" -#include "Alloc.h" -#include "LzmaLib.h" - -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - -MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, - unsigned char *outProps, size_t *outPropsSize, - int level, /* 0 <= level <= 9, default = 5 */ - unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ - int lc, /* 0 <= lc <= 8, default = 3 */ - int lp, /* 0 <= lp <= 4, default = 0 */ - int pb, /* 0 <= pb <= 4, default = 2 */ - int fb, /* 5 <= fb <= 273, default = 32 */ - int numThreads, /* 1 or 2, default = 2 */ - int algo /* 0 = fast, 1 = normal */ -) -{ - CLzmaEncProps props; - LzmaEncProps_Init(&props); - props.level = level; - props.dictSize = dictSize; - props.lc = lc; - props.lp = lp; - props.pb = pb; - props.fb = fb; - props.numThreads = numThreads; - props.algo = algo; - - return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, - NULL, &g_Alloc, &g_Alloc); -} - - -MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, - const unsigned char *props, size_t propsSize) -{ - ELzmaStatus status; - return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); -} diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaLib.h b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaLib.h deleted file mode 100644 index 8ace8bd75..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaLib.h +++ /dev/null @@ -1,136 +0,0 @@ -/* LzmaLib.h -- LZMA library interface -2008-08-05 -Igor Pavlov -Public domain */ - -#ifndef __LZMALIB_H -#define __LZMALIB_H - -#include "Types.h" - -#ifdef __cplusplus - #define MY_EXTERN_C extern "C" -#else - #define MY_EXTERN_C extern -#endif - -#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL - -#define LZMA_PROPS_SIZE 5 - -/* -RAM requirements for LZMA: - for compression: (dictSize * 11.5 + 6 MB) + state_size - for decompression: dictSize + state_size - state_size = (4 + (1.5 << (lc + lp))) KB - by default (lc=3, lp=0), state_size = 16 KB. - -LZMA properties (5 bytes) format - Offset Size Description - 0 1 lc, lp and pb in encoded form. - 1 4 dictSize (little endian). -*/ - -/* -LzmaCompress ------------- - -outPropsSize - - In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. - Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. - - LZMA Encoder will use defult values for any parameter, if it is - -1 for any from: level, loc, lp, pb, fb, numThreads - 0 for dictSize - -level - compression level: 0 <= level <= 9; - - level dictSize algo fb - 0: 16 KB 0 32 - 1: 64 KB 0 32 - 2: 256 KB 0 32 - 3: 1 MB 0 32 - 4: 4 MB 0 32 - 5: 16 MB 1 32 - 6: 32 MB 1 32 - 7+: 64 MB 1 64 - - The default value for "level" is 5. - - algo = 0 means fast method - algo = 1 means normal method - -dictSize - The dictionary size in bytes. The maximum value is - 128 MB = (1 << 27) bytes for 32-bit version - 1 GB = (1 << 30) bytes for 64-bit version - The default value is 16 MB = (1 << 24) bytes. - It's recommended to use the dictionary that is larger than 4 KB and - that can be calculated as (1 << N) or (3 << N) sizes. - -lc - The number of literal context bits (high bits of previous literal). - It can be in the range from 0 to 8. The default value is 3. - Sometimes lc=4 gives the gain for big files. - -lp - The number of literal pos bits (low bits of current position for literals). - It can be in the range from 0 to 4. The default value is 0. - The lp switch is intended for periodical data when the period is equal to 2^lp. - For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's - better to set lc=0, if you change lp switch. - -pb - The number of pos bits (low bits of current position). - It can be in the range from 0 to 4. The default value is 2. - The pb switch is intended for periodical data when the period is equal 2^pb. - -fb - Word size (the number of fast bytes). - It can be in the range from 5 to 273. The default value is 32. - Usually, a big number gives a little bit better compression ratio and - slower compression process. - -numThreads - The number of thereads. 1 or 2. The default value is 2. - Fast mode (algo = 0) can use only 1 thread. - -Out: - destLen - processed output size -Returns: - SZ_OK - OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_PARAM - Incorrect paramater - SZ_ERROR_OUTPUT_EOF - output buffer overflow - SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) -*/ - -MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, - unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ - int level, /* 0 <= level <= 9, default = 5 */ - unsigned dictSize, /* default = (1 << 24) */ - int lc, /* 0 <= lc <= 8, default = 3 */ - int lp, /* 0 <= lp <= 4, default = 0 */ - int pb, /* 0 <= pb <= 4, default = 2 */ - int fb, /* 5 <= fb <= 273, default = 32 */ - int numThreads, /* 1 or 2, default = 2 */ - int algo /* 0 = fast, 1 = normal, default = 0 for level < 5, 1 for level >= 5 */ - ); - -/* -LzmaUncompress --------------- -In: - dest - output data - destLen - output data size - src - input data - srcLen - input data size -Out: - destLen - processed output size - srcLen - processed input size -Returns: - SZ_OK - OK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation arror - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) -*/ - -MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, - const unsigned char *props, size_t propsSize); - -#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/NameMangle.h b/src/external/OpenCTM-1.0.3/lib/liblzma/NameMangle.h deleted file mode 100644 index 669d3c4ac..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/NameMangle.h +++ /dev/null @@ -1,84 +0,0 @@ -/* NameMangle.h -- Name mangling to avoid linking conflicts -2009-04-15 : Marcus Geelnard : Public domain */ - -#ifndef __7Z_NAMEMANGLE_H -#define __7Z_NAMEMANGLE_H - -#ifdef LZMA_PREFIX_CTM - -/* Alloc.c */ -#define MyAlloc _ctm_MyAlloc -#define MyFree _ctm_MyFree -#ifdef _WIN32 -#define MidAlloc _ctm_MidAlloc -#define MidFree _ctm_MidFree -#define SetLargePageSize _ctm_SetLargePageSize -#define BigAlloc _ctm_BigAlloc -#define BigFree _ctm_BigFree -#endif /* _WIN32 */ - -/* LzFind.c */ -#define MatchFinder_GetPointerToCurrentPos _ctm_MatchFinder_GetPointerToCurrentPos -#define MatchFinder_GetIndexByte _ctm_MatchFinder_GetIndexByte -#define MatchFinder_GetNumAvailableBytes _ctm_MatchFinder_GetNumAvailableBytes -#define MatchFinder_ReduceOffsets _ctm_MatchFinder_ReduceOffsets -#define MatchFinder_MoveBlock _ctm_MatchFinder_MoveBlock -#define MatchFinder_NeedMove _ctm_MatchFinder_NeedMove -#define MatchFinder_ReadIfRequired _ctm_MatchFinder_ReadIfRequired -#define MatchFinder_Construct _ctm_MatchFinder_Construct -#define MatchFinder_Free _ctm_MatchFinder_Free -#define MatchFinder_Create _ctm_MatchFinder_Create -#define MatchFinder_Init _ctm_MatchFinder_Init -#define MatchFinder_Normalize3 _ctm_MatchFinder_Normalize3 -#define GetMatchesSpec1 _ctm_GetMatchesSpec1 -#define Bt3Zip_MatchFinder_GetMatches _ctm_Bt3Zip_MatchFinder_GetMatches -#define Hc3Zip_MatchFinder_GetMatches _ctm_Hc3Zip_MatchFinder_GetMatches -#define Bt3Zip_MatchFinder_Skip _ctm_Bt3Zip_MatchFinder_Skip -#define Hc3Zip_MatchFinder_Skip _ctm_Hc3Zip_MatchFinder_Skip -#define MatchFinder_CreateVTable _ctm_MatchFinder_CreateVTable - -/* LzmaDec.c */ -#define LzmaDec_InitDicAndState _ctm_LzmaDec_InitDicAndState -#define LzmaDec_Init _ctm_LzmaDec_Init -#define LzmaDec_DecodeToDic _ctm_LzmaDec_DecodeToDic -#define LzmaDec_DecodeToBuf _ctm_LzmaDec_DecodeToBuf -#define LzmaDec_FreeProbs _ctm_LzmaDec_FreeProbs -#define LzmaDec_Free _ctm_LzmaDec_Free -#define LzmaProps_Decode _ctm_LzmaProps_Decode -#define LzmaDec_AllocateProbs _ctm_LzmaDec_AllocateProbs -#define LzmaDec_Allocate _ctm_LzmaDec_Allocate -#define LzmaDecode _ctm_LzmaDecode - -/* LzmaEnc.c */ -#define LzmaEncProps_Init _ctm_LzmaEncProps_Init -#define LzmaEncProps_Normalize _ctm_LzmaEncProps_Normalize -#define LzmaEncProps_GetDictSize _ctm_LzmaEncProps_GetDictSize -#define LzmaEnc_FastPosInit _ctm_LzmaEnc_FastPosInit -#define LzmaEnc_SaveState _ctm_LzmaEnc_SaveState -#define LzmaEnc_RestoreState _ctm_LzmaEnc_RestoreState -#define LzmaEnc_SetProps _ctm_LzmaEnc_SetProps -#define LzmaEnc_InitPriceTables _ctm_LzmaEnc_InitPriceTables -#define LzmaEnc_Construct _ctm_LzmaEnc_Construct -#define LzmaEnc_Create _ctm_LzmaEnc_Create -#define LzmaEnc_FreeLits _ctm_LzmaEnc_FreeLits -#define LzmaEnc_Destruct _ctm_LzmaEnc_Destruct -#define LzmaEnc_Destroy _ctm_LzmaEnc_Destroy -#define LzmaEnc_Init _ctm_LzmaEnc_Init -#define LzmaEnc_InitPrices _ctm_LzmaEnc_InitPrices -#define LzmaEnc_PrepareForLzma2 _ctm_LzmaEnc_PrepareForLzma2 -#define LzmaEnc_MemPrepare _ctm_LzmaEnc_MemPrepare -#define LzmaEnc_Finish _ctm_LzmaEnc_Finish -#define LzmaEnc_GetNumAvailableBytes _ctm_LzmaEnc_GetNumAvailableBytes -#define LzmaEnc_GetCurBuf _ctm_LzmaEnc_GetCurBuf -#define LzmaEnc_CodeOneMemBlock _ctm_LzmaEnc_CodeOneMemBlock -#define LzmaEnc_Encode _ctm_LzmaEnc_Encode -#define LzmaEnc_WriteProperties _ctm_LzmaEnc_WriteProperties -#define LzmaEnc_MemEncode _ctm_LzmaEnc_MemEncode - -/* LzmaLib.c */ -#define LzmaCompress _ctm_LzmaCompress -#define LzmaUncompress _ctm_LzmaUncompress - -#endif /* LZMA_PREFIX_CTM */ - -#endif /* __7Z_NAMEMANGLE_H */ diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/Types.h b/src/external/OpenCTM-1.0.3/lib/liblzma/Types.h deleted file mode 100644 index ea00a9f8a..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/Types.h +++ /dev/null @@ -1,210 +0,0 @@ -/* Types.h -- Basic types -2008-11-23 : Igor Pavlov : Public domain */ - -#ifndef __7Z_TYPES_H -#define __7Z_TYPES_H - -#include - -#ifdef _WIN32 -#include -#endif - -#include "NameMangle.h" - -#define SZ_OK 0 - -#define SZ_ERROR_DATA 1 -#define SZ_ERROR_MEM 2 -#define SZ_ERROR_CRC 3 -#define SZ_ERROR_UNSUPPORTED 4 -#define SZ_ERROR_PARAM 5 -#define SZ_ERROR_INPUT_EOF 6 -#define SZ_ERROR_OUTPUT_EOF 7 -#define SZ_ERROR_READ 8 -#define SZ_ERROR_WRITE 9 -#define SZ_ERROR_PROGRESS 10 -#define SZ_ERROR_FAIL 11 -#define SZ_ERROR_THREAD 12 - -#define SZ_ERROR_ARCHIVE 16 -#define SZ_ERROR_NO_ARCHIVE 17 - -typedef int SRes; - -#ifdef _WIN32 -typedef DWORD WRes; -#else -typedef int WRes; -#endif - -#ifndef RINOK -#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } -#endif - -typedef unsigned char Byte; -typedef short Int16; -typedef unsigned short UInt16; - -#ifdef _LZMA_UINT32_IS_ULONG -typedef long Int32; -typedef unsigned long UInt32; -#else -typedef int Int32; -typedef unsigned int UInt32; -#endif - -#ifdef _SZ_NO_INT_64 - -/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. - NOTES: Some code will work incorrectly in that case! */ - -typedef long Int64; -typedef unsigned long UInt64; - -#else - -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef __int64 Int64; -typedef unsigned __int64 UInt64; -#else -typedef long long int Int64; -typedef unsigned long long int UInt64; -#endif - -#endif - -#ifdef _LZMA_NO_SYSTEM_SIZE_T -typedef UInt32 SizeT; -#else -typedef size_t SizeT; -#endif - -typedef int Bool; -#define True 1 -#define False 0 - - -#ifdef _MSC_VER - -#if _MSC_VER >= 1300 -#define MY_NO_INLINE __declspec(noinline) -#else -#define MY_NO_INLINE -#endif - -#define MY_CDECL __cdecl -#define MY_STD_CALL __stdcall -#define MY_FAST_CALL MY_NO_INLINE __fastcall - -#else - -#define MY_CDECL -#define MY_STD_CALL -#define MY_FAST_CALL - -#endif - - -/* The following interfaces use first parameter as pointer to structure */ - -typedef struct -{ - SRes (*Read)(void *p, void *buf, size_t *size); - /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. - (output(*size) < input(*size)) is allowed */ -} ISeqInStream; - -/* it can return SZ_ERROR_INPUT_EOF */ -SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); -SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); -SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); - -typedef struct -{ - size_t (*Write)(void *p, const void *buf, size_t size); - /* Returns: result - the number of actually written bytes. - (result < size) means error */ -} ISeqOutStream; - -typedef enum -{ - SZ_SEEK_SET = 0, - SZ_SEEK_CUR = 1, - SZ_SEEK_END = 2 -} ESzSeek; - -typedef struct -{ - SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ - SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); -} ISeekInStream; - -typedef struct -{ - SRes (*Look)(void *p, void **buf, size_t *size); - /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. - (output(*size) > input(*size)) is not allowed - (output(*size) < input(*size)) is allowed */ - SRes (*Skip)(void *p, size_t offset); - /* offset must be <= output(*size) of Look */ - - SRes (*Read)(void *p, void *buf, size_t *size); - /* reads directly (without buffer). It's same as ISeqInStream::Read */ - SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); -} ILookInStream; - -SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); -SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); - -/* reads via ILookInStream::Read */ -SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); -SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); - -#define LookToRead_BUF_SIZE (1 << 14) - -typedef struct -{ - ILookInStream s; - ISeekInStream *realStream; - size_t pos; - size_t size; - Byte buf[LookToRead_BUF_SIZE]; -} CLookToRead; - -void LookToRead_CreateVTable(CLookToRead *p, int lookahead); -void LookToRead_Init(CLookToRead *p); - -typedef struct -{ - ISeqInStream s; - ILookInStream *realStream; -} CSecToLook; - -void SecToLook_CreateVTable(CSecToLook *p); - -typedef struct -{ - ISeqInStream s; - ILookInStream *realStream; -} CSecToRead; - -void SecToRead_CreateVTable(CSecToRead *p); - -typedef struct -{ - SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); - /* Returns: result. (result != SZ_OK) means break. - Value (UInt64)(Int64)-1 for size means unknown value. */ -} ICompressProgress; - -typedef struct -{ - void *(*Alloc)(void *p, size_t size); - void (*Free)(void *p, void *address); /* address can be 0 */ -} ISzAlloc; - -#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) -#define IAlloc_Free(p, a) (p)->Free((p), a) - -#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/readme.txt b/src/external/OpenCTM-1.0.3/lib/liblzma/readme.txt deleted file mode 100644 index 8198e6601..000000000 --- a/src/external/OpenCTM-1.0.3/lib/liblzma/readme.txt +++ /dev/null @@ -1,7 +0,0 @@ -This is the C library implementation of LZMA compression/decompression by Igor Pavlov. - -Author: Igor Pavlov -License: Public domain -Version: 4.65 (2009-02-03) - -Some administrative adaptations for integration in OpenCTM were made by Marcus Geelnard. diff --git a/src/external/OpenCTM-1.0.3/lib/openctm-mingw1.def b/src/external/OpenCTM-1.0.3/lib/openctm-mingw1.def deleted file mode 100644 index e3b281070..000000000 --- a/src/external/OpenCTM-1.0.3/lib/openctm-mingw1.def +++ /dev/null @@ -1,32 +0,0 @@ -LIBRARY openctm.dll -EXPORTS - ctmAddAttribMap = ctmAddAttribMap@12 @1 - ctmAddUVMap = ctmAddUVMap@16 @2 - ctmAttribPrecision = ctmAttribPrecision@12 @3 - ctmCompressionLevel = ctmCompressionLevel@8 @4 - ctmCompressionMethod = ctmCompressionMethod@8 @5 - ctmDefineMesh = ctmDefineMesh@24 @6 - ctmFileComment = ctmFileComment@8 @7 - ctmFreeContext = ctmFreeContext@4 @8 - ctmGetAttribMapFloat = ctmGetAttribMapFloat@12 @9 - ctmGetAttribMapString = ctmGetAttribMapString@12 @10 - ctmGetError = ctmGetError@4 @11 - ctmGetFloat = ctmGetFloat@8 @12 - ctmGetFloatArray = ctmGetFloatArray@8 @13 - ctmGetInteger = ctmGetInteger@8 @14 - ctmGetIntegerArray = ctmGetIntegerArray@8 @15 - ctmGetNamedAttribMap = ctmGetNamedAttribMap@8 @16 - ctmGetNamedUVMap = ctmGetNamedUVMap@8 @17 - ctmGetString = ctmGetString@8 @18 - ctmGetUVMapFloat = ctmGetUVMapFloat@12 @19 - ctmGetUVMapString = ctmGetUVMapString@12 @20 - ctmErrorString = ctmErrorString@4 @21 - ctmLoad = ctmLoad@8 @22 - ctmLoadCustom = ctmLoadCustom@12 @23 - ctmNewContext = ctmNewContext@4 @24 - ctmNormalPrecision = ctmNormalPrecision@8 @25 - ctmSave = ctmSave@8 @26 - ctmSaveCustom = ctmSaveCustom@12 @27 - ctmUVCoordPrecision = ctmUVCoordPrecision@12 @28 - ctmVertexPrecision = ctmVertexPrecision@8 @29 - ctmVertexPrecisionRel = ctmVertexPrecisionRel@8 @30 diff --git a/src/external/OpenCTM-1.0.3/lib/openctm-mingw2.def b/src/external/OpenCTM-1.0.3/lib/openctm-mingw2.def deleted file mode 100644 index 8eb12f6fd..000000000 --- a/src/external/OpenCTM-1.0.3/lib/openctm-mingw2.def +++ /dev/null @@ -1,32 +0,0 @@ -LIBRARY openctm.dll -EXPORTS - ctmAddAttribMap@12 @1 - ctmAddUVMap@16 @2 - ctmAttribPrecision@12 @3 - ctmCompressionLevel@8 @4 - ctmCompressionMethod@8 @5 - ctmDefineMesh@24 @6 - ctmFileComment@8 @7 - ctmFreeContext@4 @8 - ctmGetAttribMapFloat@12 @9 - ctmGetAttribMapString@12 @10 - ctmGetError@4 @11 - ctmGetFloat@8 @12 - ctmGetFloatArray@8 @13 - ctmGetInteger@8 @14 - ctmGetIntegerArray@8 @15 - ctmGetNamedAttribMap@8 @16 - ctmGetNamedUVMap@8 @17 - ctmGetString@8 @18 - ctmGetUVMapFloat@12 @19 - ctmGetUVMapString@12 @20 - ctmErrorString@4 @21 - ctmLoad@8 @22 - ctmLoadCustom@12 @23 - ctmNewContext@4 @24 - ctmNormalPrecision@8 @25 - ctmSave@8 @26 - ctmSaveCustom@12 @27 - ctmUVCoordPrecision@12 @28 - ctmVertexPrecision@8 @29 - ctmVertexPrecisionRel@8 @30 diff --git a/src/external/OpenCTM-1.0.3/lib/openctm-msvc.def b/src/external/OpenCTM-1.0.3/lib/openctm-msvc.def deleted file mode 100644 index bb66dbdfe..000000000 --- a/src/external/OpenCTM-1.0.3/lib/openctm-msvc.def +++ /dev/null @@ -1,32 +0,0 @@ -LIBRARY openctm.dll -EXPORTS - ctmAddAttribMap - ctmAddUVMap - ctmAttribPrecision - ctmCompressionLevel - ctmCompressionMethod - ctmDefineMesh - ctmFileComment - ctmFreeContext - ctmGetAttribMapFloat - ctmGetAttribMapString - ctmGetError - ctmGetFloat - ctmGetFloatArray - ctmGetInteger - ctmGetIntegerArray - ctmGetNamedAttribMap - ctmGetNamedUVMap - ctmGetString - ctmGetUVMapFloat - ctmGetUVMapString - ctmErrorString - ctmLoad - ctmLoadCustom - ctmNewContext - ctmNormalPrecision - ctmSave - ctmSaveCustom - ctmUVCoordPrecision - ctmVertexPrecision - ctmVertexPrecisionRel diff --git a/src/external/OpenCTM-1.0.3/lib/openctm.c b/src/external/OpenCTM-1.0.3/lib/openctm.c deleted file mode 100644 index f1b9303ae..000000000 --- a/src/external/OpenCTM-1.0.3/lib/openctm.c +++ /dev/null @@ -1,1423 +0,0 @@ -//----------------------------------------------------------------------------- -// Product: OpenCTM -// File: openctm.c -// Description: API functions. -//----------------------------------------------------------------------------- -// Copyright (c) 2009-2010 Marcus Geelnard -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -//----------------------------------------------------------------------------- - -#include -#include -#include -#include -#include "openctm.h" -#include "internal.h" - - -// The C99 macro isfinite() is not supported on all platforms (specifically, -// MS Visual Studio does not support C99) -#if !defined(isfinite) && defined(_MSC_VER) - #include - #define isfinite(x) _finite(x) -#endif - - -//----------------------------------------------------------------------------- -// _ctmFreeMapList() - Free a float map list. -//----------------------------------------------------------------------------- -static void _ctmFreeMapList(_CTMcontext * self, _CTMfloatmap * aMapList) -{ - _CTMfloatmap * map, * nextMap; - map = aMapList; - while(map) - { - // Free internally allocated array (if we are in import mode) - if((self->mMode == CTM_IMPORT) && map->mValues) - free(map->mValues); - - // Free map name - if(map->mName) - free(map->mName); - - // Free file name - if(map->mFileName) - free(map->mFileName); - - nextMap = map->mNext; - free(map); - map = nextMap; - } -} - -//----------------------------------------------------------------------------- -// _ctmClearMesh() - Clear the mesh in a CTM context. -//----------------------------------------------------------------------------- -static void _ctmClearMesh(_CTMcontext * self) -{ - // Free internally allocated mesh arrays - if(self->mMode == CTM_IMPORT) - { - if(self->mVertices) - free(self->mVertices); - if(self->mIndices) - free(self->mIndices); - if(self->mNormals) - free(self->mNormals); - } - - // Clear externally assigned mesh arrays - self->mVertices = (CTMfloat *) 0; - self->mVertexCount = 0; - self->mIndices = (CTMuint *) 0; - self->mTriangleCount = 0; - self->mNormals = (CTMfloat *) 0; - - // Free UV coordinate map list - _ctmFreeMapList(self, self->mUVMaps); - self->mUVMaps = (_CTMfloatmap *) 0; - self->mUVMapCount = 0; - - // Free attribute map list - _ctmFreeMapList(self, self->mAttribMaps); - self->mAttribMaps = (_CTMfloatmap *) 0; - self->mAttribMapCount = 0; -} - -//----------------------------------------------------------------------------- -// _ctmCheckMeshIntegrity() - Check if a mesh is valid (i.e. is non-empty, and -// contains valid data). -//----------------------------------------------------------------------------- - -static CTMint _ctmCheckMeshIntegrity(_CTMcontext * self) -{ - CTMuint i; - _CTMfloatmap * map; - - // Check that we have all the mandatory data - if(!self->mVertices || !self->mIndices || (self->mVertexCount < 1) || - (self->mTriangleCount < 1)) - { - return CTM_FALSE; - } - - // Check that all indices are within range - for(i = 0; i < (self->mTriangleCount * 3); ++ i) - { - if(self->mIndices[i] >= self->mVertexCount) - { - return CTM_FALSE; - } - } - - // Check that all vertices are finite (non-NaN, non-inf) - for(i = 0; i < self->mVertexCount * 3; ++ i) - { - if(!isfinite(self->mVertices[i])) - { - return CTM_FALSE; - } - } - - // Check that all normals are finite (non-NaN, non-inf) - if(self->mNormals) - { - for(i = 0; i < self->mVertexCount * 3; ++ i) - { - if(!isfinite(self->mNormals[i])) - { - return CTM_FALSE; - } - } - } - - // Check that all UV maps are finite (non-NaN, non-inf) - map = self->mUVMaps; - while(map) - { - for(i = 0; i < self->mVertexCount * 2; ++ i) - { - if(!isfinite(map->mValues[i])) - { - return CTM_FALSE; - } - } - map = map->mNext; - } - - // Check that all attribute maps are finite (non-NaN, non-inf) - map = self->mAttribMaps; - while(map) - { - for(i = 0; i < self->mVertexCount * 4; ++ i) - { - if(!isfinite(map->mValues[i])) - { - return CTM_FALSE; - } - } - map = map->mNext; - } - - return CTM_TRUE; -} - -//----------------------------------------------------------------------------- -// ctmNewContext() -//----------------------------------------------------------------------------- -CTMEXPORT CTMcontext CTMCALL ctmNewContext(CTMenum aMode) -{ - _CTMcontext * self; - - // Allocate memory for the new structure - self = (_CTMcontext *) malloc(sizeof(_CTMcontext)); - - // Initialize structure (set null pointers and zero array lengths) - memset(self, 0, sizeof(_CTMcontext)); - self->mMode = aMode; - self->mError = CTM_NONE; - self->mMethod = CTM_METHOD_MG1; - self->mCompressionLevel = 1; - self->mVertexPrecision = 1.0f / 1024.0f; - self->mNormalPrecision = 1.0f / 256.0f; - - return (CTMcontext) self; -} - -//----------------------------------------------------------------------------- -// ctmFreeContext() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmFreeContext(CTMcontext aContext) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - if(!self) return; - - // Free all mesh resources - _ctmClearMesh(self); - - // Free the file comment - if(self->mFileComment) - free(self->mFileComment); - - // Free the context - free(self); -} - -//----------------------------------------------------------------------------- -// ctmGetError() -//----------------------------------------------------------------------------- -CTMEXPORT CTMenum CTMCALL ctmGetError(CTMcontext aContext) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - CTMenum err; - - if(!self) return CTM_INVALID_CONTEXT; - - // Get error code and reset error state - err = self->mError; - self->mError = CTM_NONE; - return err; -} - -//----------------------------------------------------------------------------- -// ctmErrorString() -//----------------------------------------------------------------------------- -CTMEXPORT const char * CTMCALL ctmErrorString(CTMenum aError) -{ - switch(aError) - { - case CTM_INVALID_CONTEXT: - return "CTM_INVALID_CONTEXT"; - case CTM_INVALID_ARGUMENT: - return "CTM_INVALID_ARGUMENT"; - case CTM_INVALID_OPERATION: - return "CTM_INVALID_OPERATION"; - case CTM_INVALID_MESH: - return "CTM_INVALID_MESH"; - case CTM_OUT_OF_MEMORY: - return "CTM_OUT_OF_MEMORY"; - case CTM_FILE_ERROR: - return "CTM_FILE_ERROR"; - case CTM_BAD_FORMAT: - return "CTM_BAD_FORMAT"; - case CTM_LZMA_ERROR: - return "CTM_LZMA_ERROR"; - case CTM_INTERNAL_ERROR: - return "CTM_INTERNAL_ERROR"; - case CTM_UNSUPPORTED_FORMAT_VERSION: - return "CTM_UNSUPPORTED_FORMAT_VERSION"; - default: - return "Unknown error code"; - } -} - -//----------------------------------------------------------------------------- -// ctmGetInteger() -//----------------------------------------------------------------------------- -CTMEXPORT CTMuint CTMCALL ctmGetInteger(CTMcontext aContext, CTMenum aProperty) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - if(!self) return 0; - - switch(aProperty) - { - case CTM_VERTEX_COUNT: - return self->mVertexCount; - - case CTM_TRIANGLE_COUNT: - return self->mTriangleCount; - - case CTM_UV_MAP_COUNT: - return self->mUVMapCount; - - case CTM_ATTRIB_MAP_COUNT: - return self->mAttribMapCount; - - case CTM_HAS_NORMALS: - return self->mNormals ? CTM_TRUE : CTM_FALSE; - - case CTM_COMPRESSION_METHOD: - return (CTMuint) self->mMethod; - - default: - self->mError = CTM_INVALID_ARGUMENT; - } - - return 0; -} - -//----------------------------------------------------------------------------- -// ctmGetFloat() -//----------------------------------------------------------------------------- -CTMEXPORT CTMfloat CTMCALL ctmGetFloat(CTMcontext aContext, CTMenum aProperty) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - if(!self) return 0.0f; - - switch(aProperty) - { - case CTM_VERTEX_PRECISION: - return self->mVertexPrecision; - - case CTM_NORMAL_PRECISION: - return self->mNormalPrecision; - - default: - self->mError = CTM_INVALID_ARGUMENT; - } - - return 0.0f; -} - -//----------------------------------------------------------------------------- -// ctmGetIntegerArray() -//----------------------------------------------------------------------------- -CTMEXPORT const CTMuint * CTMCALL ctmGetIntegerArray(CTMcontext aContext, - CTMenum aProperty) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - if(!self) return (CTMuint *) 0; - - switch(aProperty) - { - case CTM_INDICES: - return self->mIndices; - - default: - self->mError = CTM_INVALID_ARGUMENT; - } - - return (CTMuint *) 0; -} - -//----------------------------------------------------------------------------- -// ctmGetFloatArray() -//----------------------------------------------------------------------------- -CTMEXPORT const CTMfloat * CTMCALL ctmGetFloatArray(CTMcontext aContext, - CTMenum aProperty) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - _CTMfloatmap * map; - CTMuint i; - if(!self) return (CTMfloat *) 0; - - // Did the user request a UV map? - if((aProperty >= CTM_UV_MAP_1) && - ((CTMuint)(aProperty - CTM_UV_MAP_1) < self->mUVMapCount)) - { - map = self->mUVMaps; - i = CTM_UV_MAP_1; - while(map && (i != aProperty)) - { - map = map->mNext; - ++ i; - } - if(!map) - { - self->mError = CTM_INTERNAL_ERROR; - return (CTMfloat *) 0; - } - return map->mValues; - } - - // Did the user request an attribute map? - if((aProperty >= CTM_ATTRIB_MAP_1) && - ((CTMuint)(aProperty - CTM_ATTRIB_MAP_1) < self->mAttribMapCount)) - { - map = self->mAttribMaps; - i = CTM_ATTRIB_MAP_1; - while(map && (i != aProperty)) - { - map = map->mNext; - ++ i; - } - if(!map) - { - self->mError = CTM_INTERNAL_ERROR; - return (CTMfloat *) 0; - } - return map->mValues; - } - - switch(aProperty) - { - case CTM_VERTICES: - return self->mVertices; - - case CTM_NORMALS: - return self->mNormals; - - default: - self->mError = CTM_INVALID_ARGUMENT; - } - - return (CTMfloat *) 0; -} - -//----------------------------------------------------------------------------- -// ctmGetNamedUVMap() -//----------------------------------------------------------------------------- -CTMEXPORT CTMenum CTMCALL ctmGetNamedUVMap(CTMcontext aContext, - const char * aName) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - _CTMfloatmap * map; - CTMuint result; - if(!self) return CTM_NONE; - - map = self->mUVMaps; - result = CTM_UV_MAP_1; - while(map && (strcmp(aName, map->mName) != 0)) - { - map = map->mNext; - ++ result; - } - if(!map) - { - return CTM_NONE; - } - return result; -} - -//----------------------------------------------------------------------------- -// ctmGetUVMapString() -//----------------------------------------------------------------------------- -CTMEXPORT const char * CTMCALL ctmGetUVMapString(CTMcontext aContext, - CTMenum aUVMap, CTMenum aProperty) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - _CTMfloatmap * map; - CTMuint i; - if(!self) return (const char *) 0; - - // Find the indicated map - map = self->mUVMaps; - i = CTM_UV_MAP_1; - while(map && (i != aUVMap)) - { - ++ i; - map = map->mNext; - } - if(!map) - { - self->mError = CTM_INVALID_ARGUMENT; - return (const char *) 0; - } - - // Get the requested string - switch(aProperty) - { - case CTM_NAME: - return (const char *) map->mName; - - case CTM_FILE_NAME: - return (const char *) map->mFileName; - - default: - self->mError = CTM_INVALID_ARGUMENT; - } - - return (const char *) 0; -} - -//----------------------------------------------------------------------------- -// ctmGetUVMapFloat() -//----------------------------------------------------------------------------- -CTMEXPORT CTMfloat CTMCALL ctmGetUVMapFloat(CTMcontext aContext, - CTMenum aUVMap, CTMenum aProperty) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - _CTMfloatmap * map; - CTMuint i; - if(!self) return 0.0f; - - // Find the indicated map - map = self->mUVMaps; - i = CTM_UV_MAP_1; - while(map && (i != aUVMap)) - { - ++ i; - map = map->mNext; - } - if(!map) - { - self->mError = CTM_INVALID_ARGUMENT; - return 0.0f; - } - - // Get the requested string - switch(aProperty) - { - case CTM_PRECISION: - return map->mPrecision; - - default: - self->mError = CTM_INVALID_ARGUMENT; - } - - return 0.0f; -} - -//----------------------------------------------------------------------------- -// ctmGetAttribMapString() -//----------------------------------------------------------------------------- -CTMEXPORT const char * CTMCALL ctmGetAttribMapString(CTMcontext aContext, - CTMenum aAttribMap, CTMenum aProperty) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - _CTMfloatmap * map; - CTMuint i; - if(!self) return (const char *) 0; - - // Find the indicated map - map = self->mAttribMaps; - i = CTM_ATTRIB_MAP_1; - while(map && (i != aAttribMap)) - { - ++ i; - map = map->mNext; - } - if(!map) - { - self->mError = CTM_INVALID_ARGUMENT; - return (const char *) 0; - } - - // Get the requested string - switch(aProperty) - { - case CTM_NAME: - return (const char *) map->mName; - - default: - self->mError = CTM_INVALID_ARGUMENT; - } - - return (const char *) 0; -} - -//----------------------------------------------------------------------------- -// ctmGetAttribMapFloat() -//----------------------------------------------------------------------------- -CTMEXPORT CTMfloat CTMCALL ctmGetAttribMapFloat(CTMcontext aContext, - CTMenum aAttribMap, CTMenum aProperty) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - _CTMfloatmap * map; - CTMuint i; - if(!self) return 0.0f; - - // Find the indicated map - map = self->mAttribMaps; - i = CTM_ATTRIB_MAP_1; - while(map && (i != aAttribMap)) - { - ++ i; - map = map->mNext; - } - if(!map) - { - self->mError = CTM_INVALID_ARGUMENT; - return 0.0f; - } - - // Get the requested string - switch(aProperty) - { - case CTM_PRECISION: - return map->mPrecision; - - default: - self->mError = CTM_INVALID_ARGUMENT; - } - - return 0.0f; -} - -//----------------------------------------------------------------------------- -// ctmGetNamedAttribMap() -//----------------------------------------------------------------------------- -CTMEXPORT CTMenum CTMCALL ctmGetNamedAttribMap(CTMcontext aContext, - const char * aName) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - _CTMfloatmap * map; - CTMuint result; - if(!self) return CTM_NONE; - - map = self->mAttribMaps; - result = CTM_ATTRIB_MAP_1; - while(map && (strcmp(aName, map->mName) != 0)) - { - map = map->mNext; - ++ result; - } - if(!map) - { - return CTM_NONE; - } - return result; -} - -//----------------------------------------------------------------------------- -// ctmGetString() -//----------------------------------------------------------------------------- -CTMEXPORT const char * CTMCALL ctmGetString(CTMcontext aContext, - CTMenum aProperty) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - if(!self) return 0; - - switch(aProperty) - { - case CTM_FILE_COMMENT: - return (const char *) self->mFileComment; - - default: - self->mError = CTM_INVALID_ARGUMENT; - } - - return (const char *) 0; -} - -//----------------------------------------------------------------------------- -// ctmCompressionMethod() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmCompressionMethod(CTMcontext aContext, - CTMenum aMethod) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - if(!self) return; - - // You are only allowed to change compression attributes in export mode - if(self->mMode != CTM_EXPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Check arguments - if((aMethod != CTM_METHOD_RAW) && (aMethod != CTM_METHOD_MG1) && - (aMethod != CTM_METHOD_MG2)) - { - self->mError = CTM_INVALID_ARGUMENT; - return; - } - - // Set method - self->mMethod = aMethod; -} - -//----------------------------------------------------------------------------- -// ctmCompressionLevel() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmCompressionLevel(CTMcontext aContext, - CTMuint aLevel) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - if(!self) return; - - // You are only allowed to change compression attributes in export mode - if(self->mMode != CTM_EXPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Check arguments - if(aLevel > 9) - { - self->mError = CTM_INVALID_ARGUMENT; - return; - } - - // Set the compression level - self->mCompressionLevel = aLevel; -} - -//----------------------------------------------------------------------------- -// ctmVertexPrecision() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmVertexPrecision(CTMcontext aContext, - CTMfloat aPrecision) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - if(!self) return; - - // You are only allowed to change compression attributes in export mode - if(self->mMode != CTM_EXPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Check arguments - if(aPrecision <= 0.0f) - { - self->mError = CTM_INVALID_ARGUMENT; - return; - } - - // Set precision - self->mVertexPrecision = aPrecision; -} - -//----------------------------------------------------------------------------- -// ctmVertexPrecisionRel() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmVertexPrecisionRel(CTMcontext aContext, - CTMfloat aRelPrecision) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - CTMfloat avgEdgeLength, * p1, * p2; - CTMuint edgeCount, i, j; - if(!self) return; - - // You are only allowed to change compression attributes in export mode - if(self->mMode != CTM_EXPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Check arguments - if(aRelPrecision <= 0.0f) - { - self->mError = CTM_INVALID_ARGUMENT; - return; - } - - // Calculate the average edge length (Note: we actually sum up all the half- - // edges, so in a proper solid mesh all connected edges are counted twice) - avgEdgeLength = 0.0f; - edgeCount = 0; - for(i = 0; i < self->mTriangleCount; ++ i) - { - p1 = &self->mVertices[self->mIndices[i * 3 + 2] * 3]; - for(j = 0; j < 3; ++ j) - { - p2 = &self->mVertices[self->mIndices[i * 3 + j] * 3]; - avgEdgeLength += sqrtf((p2[0] - p1[0]) * (p2[0] - p1[0]) + - (p2[1] - p1[1]) * (p2[1] - p1[1]) + - (p2[2] - p1[2]) * (p2[2] - p1[2])); - p1 = p2; - ++ edgeCount; - } - } - if(edgeCount == 0) - { - self->mError = CTM_INVALID_MESH; - return; - } - avgEdgeLength /= (CTMfloat) edgeCount; - - // Set precision - self->mVertexPrecision = aRelPrecision * avgEdgeLength; -} - -//----------------------------------------------------------------------------- -// ctmNormalPrecision() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmNormalPrecision(CTMcontext aContext, - CTMfloat aPrecision) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - if(!self) return; - - // You are only allowed to change compression attributes in export mode - if(self->mMode != CTM_EXPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Check arguments - if(aPrecision <= 0.0f) - { - self->mError = CTM_INVALID_ARGUMENT; - return; - } - - // Set precision - self->mNormalPrecision = aPrecision; -} - -//----------------------------------------------------------------------------- -// ctmUVCoordPrecision() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmUVCoordPrecision(CTMcontext aContext, - CTMenum aUVMap, CTMfloat aPrecision) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - _CTMfloatmap * map; - CTMuint i; - if(!self) return; - - // You are only allowed to change compression attributes in export mode - if(self->mMode != CTM_EXPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Check arguments - if(aPrecision <= 0.0f) - { - self->mError = CTM_INVALID_ARGUMENT; - return; - } - - // Find the indicated map - map = self->mUVMaps; - i = CTM_UV_MAP_1; - while(map && (i != aUVMap)) - { - ++ i; - map = map->mNext; - } - if(!map) - { - self->mError = CTM_INVALID_ARGUMENT; - return; - } - - // Update the precision - map->mPrecision = aPrecision; -} - -//----------------------------------------------------------------------------- -// ctmAttribPrecision() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmAttribPrecision(CTMcontext aContext, - CTMenum aAttribMap, CTMfloat aPrecision) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - _CTMfloatmap * map; - CTMuint i; - if(!self) return; - - // You are only allowed to change compression attributes in export mode - if(self->mMode != CTM_EXPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Check arguments - if(aPrecision <= 0.0f) - { - self->mError = CTM_INVALID_ARGUMENT; - return; - } - - // Find the indicated map - map = self->mAttribMaps; - i = CTM_ATTRIB_MAP_1; - while(map && (i != aAttribMap)) - { - ++ i; - map = map->mNext; - } - if(!map) - { - self->mError = CTM_INVALID_ARGUMENT; - return; - } - - // Update the precision - map->mPrecision = aPrecision; -} - -//----------------------------------------------------------------------------- -// ctmFileComment() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmFileComment(CTMcontext aContext, - const char * aFileComment) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - int len; - if(!self) return; - - // You are only allowed to change file attributes in export mode - if(self->mMode != CTM_EXPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Free the old comment string, if necessary - if(self->mFileComment) - { - free(self->mFileComment); - self->mFileComment = (char *) 0; - } - - // Get length of string (if empty, do nothing) - if(!aFileComment) - return; - len = strlen(aFileComment); - if(!len) - return; - - // Copy the string - self->mFileComment = (char *) malloc(len + 1); - if(!self->mFileComment) - { - self->mError = CTM_OUT_OF_MEMORY; - return; - } - strcpy(self->mFileComment, aFileComment); -} - -//----------------------------------------------------------------------------- -// ctmDefineMesh() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmDefineMesh(CTMcontext aContext, - const CTMfloat * aVertices, CTMuint aVertexCount, const CTMuint * aIndices, - CTMuint aTriangleCount, const CTMfloat * aNormals) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - if(!self) return; - - // You are only allowed to (re)define the mesh in export mode - if(self->mMode != CTM_EXPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Check arguments - if(!aVertices || !aIndices || !aVertexCount || !aTriangleCount) - { - self->mError = CTM_INVALID_ARGUMENT; - return; - } - - // Clear the old mesh, if any - _ctmClearMesh(self); - - // Set vertex array pointer - self->mVertices = (CTMfloat *) aVertices; - self->mVertexCount = aVertexCount; - - // Set index array pointer - self->mIndices = (CTMuint *) aIndices; - self->mTriangleCount = aTriangleCount; - - // Set normal array pointer - self->mNormals = (CTMfloat *) aNormals; -} - -//----------------------------------------------------------------------------- -// _ctmAddFloatMap() -//----------------------------------------------------------------------------- -static _CTMfloatmap * _ctmAddFloatMap(_CTMcontext * self, - const CTMfloat * aValues, const char * aName, const char * aFileName, - _CTMfloatmap ** aList) -{ - _CTMfloatmap * map; - CTMuint len; - - // Allocate memory for a new map list item and append it to the list - if(!*aList) - { - *aList = (_CTMfloatmap *) malloc(sizeof(_CTMfloatmap)); - map = *aList; - } - else - { - map = *aList; - while(map->mNext) - map = map->mNext; - map->mNext = (_CTMfloatmap *) malloc(sizeof(_CTMfloatmap)); - map = map->mNext; - } - if(!map) - { - self->mError = CTM_OUT_OF_MEMORY; - return (_CTMfloatmap *) 0; - } - - // Init the map item - memset(map, 0, sizeof(_CTMfloatmap)); - map->mPrecision = 1.0f / 1024.0f; - map->mValues = (CTMfloat *) aValues; - - // Set name of the map - if(aName) - { - // Get length of string (if empty, do nothing) - len = strlen(aName); - if(len) - { - // Copy the string - map->mName = (char *) malloc(len + 1); - if(!map->mName) - { - self->mError = CTM_OUT_OF_MEMORY; - free(map); - return (_CTMfloatmap *) 0; - } - strcpy(map->mName, aName); - } - } - - // Set file name reference for the map - if(aFileName) - { - // Get length of string (if empty, do nothing) - len = strlen(aFileName); - if(len) - { - // Copy the string - map->mFileName = (char *) malloc(len + 1); - if(!map->mFileName) - { - self->mError = CTM_OUT_OF_MEMORY; - if(map->mName) - free(map->mName); - free(map); - return (_CTMfloatmap *) 0; - } - strcpy(map->mFileName, aFileName); - } - } - - return map; -} - -//----------------------------------------------------------------------------- -// ctmAddUVMap() -//----------------------------------------------------------------------------- -CTMEXPORT CTMenum CTMCALL ctmAddUVMap(CTMcontext aContext, - const CTMfloat * aUVCoords, const char * aName, const char * aFileName) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - _CTMfloatmap * map; - if(!self) return CTM_NONE; - - // Add a new UV map to the UV map list - map = _ctmAddFloatMap(self, aUVCoords, aName, aFileName, &self->mUVMaps); - if(!map) - return CTM_NONE; - else - { - // The default UV coordinate precision is 2^-12 - map->mPrecision = 1.0f / 4096.0f; - ++ self->mUVMapCount; - return CTM_UV_MAP_1 + self->mUVMapCount - 1; - } -} - -//----------------------------------------------------------------------------- -// ctmAddAttribMap() -//----------------------------------------------------------------------------- -CTMEXPORT CTMenum CTMCALL ctmAddAttribMap(CTMcontext aContext, - const CTMfloat * aAttribValues, const char * aName) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - _CTMfloatmap * map; - if(!self) return CTM_NONE; - - // Add a new attribute map to the attribute map list - map = _ctmAddFloatMap(self, aAttribValues, aName, (const char *) 0, - &self->mAttribMaps); - if(!map) - return CTM_NONE; - else - { - // The default vertex attribute precision is 2^-8 - map->mPrecision = 1.0f / 256.0f; - ++ self->mAttribMapCount; - return CTM_ATTRIB_MAP_1 + self->mAttribMapCount - 1; - } -} - -//----------------------------------------------------------------------------- -// _ctmDefaultRead() -//----------------------------------------------------------------------------- -static CTMuint CTMCALL _ctmDefaultRead(void * aBuf, CTMuint aCount, - void * aUserData) -{ - return (CTMuint) fread(aBuf, 1, (size_t) aCount, (FILE *) aUserData); -} - -//----------------------------------------------------------------------------- -// ctmLoad() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmLoad(CTMcontext aContext, const char * aFileName) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - FILE * f; - if(!self) return; - - // You are only allowed to load data in import mode - if(self->mMode != CTM_IMPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Open file stream - f = fopen(aFileName, "rb"); - if(!f) - { - self->mError = CTM_FILE_ERROR; - return; - } - - // Load the file - ctmLoadCustom(self, _ctmDefaultRead, (void *) f); - - // Close file stream - fclose(f); -} - -//----------------------------------------------------------------------------- -// _ctmAllocateFloatMaps() -//----------------------------------------------------------------------------- -static CTMuint _ctmAllocateFloatMaps(_CTMcontext * self, - _CTMfloatmap ** aMapListPtr, CTMuint aCount, CTMuint aChannels) -{ - _CTMfloatmap ** mapListPtr; - CTMuint i, size; - - mapListPtr = aMapListPtr; - for(i = 0; i < aCount; ++ i) - { - // Allocate & clear memory for this map - *mapListPtr = (_CTMfloatmap *) malloc(sizeof(_CTMfloatmap)); - if(!*mapListPtr) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - memset(*mapListPtr, 0, sizeof(_CTMfloatmap)); - - // Allocate & clear memory for the float array - size = aChannels * sizeof(CTMfloat) * self->mVertexCount; - (*mapListPtr)->mValues = (CTMfloat *) malloc(size); - if(!(*mapListPtr)->mValues) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - memset((*mapListPtr)->mValues, 0, size); - - // Next map... - mapListPtr = &(*mapListPtr)->mNext; - } - - return CTM_TRUE; -} - -//----------------------------------------------------------------------------- -// ctmLoadCustom() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmLoadCustom(CTMcontext aContext, CTMreadfn aReadFn, - void * aUserData) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - CTMuint formatVersion, flags, method; - if(!self) return; - - // You are only allowed to load data in import mode - if(self->mMode != CTM_IMPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Initialize stream - self->mReadFn = aReadFn; - self->mUserData = aUserData; - - // Clear any old mesh arrays - _ctmClearMesh(self); - - // Read header from stream - if(_ctmStreamReadUINT(self) != FOURCC("OCTM")) - { - self->mError = CTM_BAD_FORMAT; - return; - } - formatVersion = _ctmStreamReadUINT(self); - if(formatVersion != _CTM_FORMAT_VERSION) - { - self->mError = CTM_UNSUPPORTED_FORMAT_VERSION; - return; - } - method = _ctmStreamReadUINT(self); - if(method == FOURCC("RAW\0")) - self->mMethod = CTM_METHOD_RAW; - else if(method == FOURCC("MG1\0")) - self->mMethod = CTM_METHOD_MG1; - else if(method == FOURCC("MG2\0")) - self->mMethod = CTM_METHOD_MG2; - else - { - self->mError = CTM_BAD_FORMAT; - return; - } - self->mVertexCount = _ctmStreamReadUINT(self); - if(self->mVertexCount == 0) - { - self->mError = CTM_BAD_FORMAT; - return; - } - self->mTriangleCount = _ctmStreamReadUINT(self); - if(self->mTriangleCount == 0) - { - self->mError = CTM_BAD_FORMAT; - return; - } - self->mUVMapCount = _ctmStreamReadUINT(self); - self->mAttribMapCount = _ctmStreamReadUINT(self); - flags = _ctmStreamReadUINT(self); - _ctmStreamReadSTRING(self, &self->mFileComment); - - // Allocate memory for the mesh arrays - self->mVertices = (CTMfloat *) malloc(self->mVertexCount * sizeof(CTMfloat) * 3); - if(!self->mVertices) - { - self->mError = CTM_OUT_OF_MEMORY; - return; - } - self->mIndices = (CTMuint *) malloc(self->mTriangleCount * sizeof(CTMuint) * 3); - if(!self->mIndices) - { - _ctmClearMesh(self); - self->mError = CTM_OUT_OF_MEMORY; - return; - } - if(flags & _CTM_HAS_NORMALS_BIT) - { - self->mNormals = (CTMfloat *) malloc(self->mVertexCount * sizeof(CTMfloat) * 3); - if(!self->mNormals) - { - _ctmClearMesh(self); - self->mError = CTM_OUT_OF_MEMORY; - return; - } - } - - // Allocate memory for the UV and attribute maps (if any) - if(!_ctmAllocateFloatMaps(self, &self->mUVMaps, self->mUVMapCount, 2)) - { - _ctmClearMesh(self); - self->mError = CTM_OUT_OF_MEMORY; - return; - } - if(!_ctmAllocateFloatMaps(self, &self->mAttribMaps, self->mAttribMapCount, 4)) - { - _ctmClearMesh(self); - self->mError = CTM_OUT_OF_MEMORY; - return; - } - - // Uncompress from stream - switch(self->mMethod) - { - case CTM_METHOD_RAW: - _ctmUncompressMesh_RAW(self); - break; - - case CTM_METHOD_MG1: - _ctmUncompressMesh_MG1(self); - break; - - case CTM_METHOD_MG2: - _ctmUncompressMesh_MG2(self); - break; - - default: - self->mError = CTM_INTERNAL_ERROR; - } - - // Check mesh integrity - if(!_ctmCheckMeshIntegrity(self)) - { - self->mError = CTM_INVALID_MESH; - return; - } -} - -//----------------------------------------------------------------------------- -// _ctmDefaultWrite() -//----------------------------------------------------------------------------- -static CTMuint CTMCALL _ctmDefaultWrite(const void * aBuf, CTMuint aCount, - void * aUserData) -{ - return (CTMuint) fwrite(aBuf, 1, (size_t) aCount, (FILE *) aUserData); -} - -//----------------------------------------------------------------------------- -// ctmSave() -//----------------------------------------------------------------------------- -CTMEXPORT void CTMCALL ctmSave(CTMcontext aContext, const char * aFileName) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - FILE * f; - if(!self) return; - - // You are only allowed to save data in export mode - if(self->mMode != CTM_EXPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Open file stream - f = fopen(aFileName, "wb"); - if(!f) - { - self->mError = CTM_FILE_ERROR; - return; - } - - // Save the file - ctmSaveCustom(self, _ctmDefaultWrite, (void *) f); - - // Close file stream - fclose(f); -} - -//----------------------------------------------------------------------------- -// ctmSaveCustom() -//----------------------------------------------------------------------------- -void CTMCALL ctmSaveCustom(CTMcontext aContext, CTMwritefn aWriteFn, - void * aUserData) -{ - _CTMcontext * self = (_CTMcontext *) aContext; - CTMuint flags; - if(!self) return; - - // You are only allowed to save data in export mode - if(self->mMode != CTM_EXPORT) - { - self->mError = CTM_INVALID_OPERATION; - return; - } - - // Check mesh integrity - if(!_ctmCheckMeshIntegrity(self)) - { - self->mError = CTM_INVALID_MESH; - return; - } - - // Initialize stream - self->mWriteFn = aWriteFn; - self->mUserData = aUserData; - - // Determine flags - flags = 0; - if(self->mNormals) - flags |= _CTM_HAS_NORMALS_BIT; - - // Write header to stream - _ctmStreamWrite(self, (void *) "OCTM", 4); - _ctmStreamWriteUINT(self, _CTM_FORMAT_VERSION); - switch(self->mMethod) - { - case CTM_METHOD_RAW: - _ctmStreamWrite(self, (void *) "RAW\0", 4); - break; - - case CTM_METHOD_MG1: - _ctmStreamWrite(self, (void *) "MG1\0", 4); - break; - - case CTM_METHOD_MG2: - _ctmStreamWrite(self, (void *) "MG2\0", 4); - break; - - default: - self->mError = CTM_INTERNAL_ERROR; - return; - } - _ctmStreamWriteUINT(self, self->mVertexCount); - _ctmStreamWriteUINT(self, self->mTriangleCount); - _ctmStreamWriteUINT(self, self->mUVMapCount); - _ctmStreamWriteUINT(self, self->mAttribMapCount); - _ctmStreamWriteUINT(self, flags); - _ctmStreamWriteSTRING(self, self->mFileComment); - - // Compress to stream - switch(self->mMethod) - { - case CTM_METHOD_RAW: - _ctmCompressMesh_RAW(self); - break; - - case CTM_METHOD_MG1: - _ctmCompressMesh_MG1(self); - break; - - case CTM_METHOD_MG2: - _ctmCompressMesh_MG2(self); - break; - - default: - self->mError = CTM_INTERNAL_ERROR; - return; - } -} diff --git a/src/external/OpenCTM-1.0.3/lib/openctm.h b/src/external/OpenCTM-1.0.3/lib/openctm.h deleted file mode 100644 index c395f93e6..000000000 --- a/src/external/OpenCTM-1.0.3/lib/openctm.h +++ /dev/null @@ -1,655 +0,0 @@ -//----------------------------------------------------------------------------- -// Product: OpenCTM -// File: openctm.h -// Description: OpenCTM API definition. -//----------------------------------------------------------------------------- -// Copyright (c) 2009-2010 Marcus Geelnard -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -//----------------------------------------------------------------------------- - -#ifndef __OPENCTM_H_ -#define __OPENCTM_H_ - -/*! @mainpage OpenCTM API Reference - * - * @section intro_sec Introduction - * - * OpenCTM is an open file format for storing compressed triangle meshes. - * In order to easily read and write OpenCTM files (usually suffixed .ctm) an - * API (Application Program Interface) is provided that can easily be used from - * most modern programming languages. - * - * The OpenCTM functionality itself is written in highly portable standard C - * (C99). - * - * @section usage_sec Usage - * - * For information about how to use the OpenCTM API, see openctm.h. - * - * For information about the C++ wrapper classes, see CTMimporter and - * CTMexporter. - * - * @section example_sec Example usage - * - * @subsection example_load_sec Loading a CTM file - * - * Here is a simple example of loading a CTM file: - * - * @code - * CTMcontext context; - * CTMuint vertCount, triCount, * indices; - * CTMfloat * vertices; - * - * // Create a new context - * context = ctmNewContext(CTM_IMPORT); - * - * // Load the OpenCTM file - * ctmLoad(context, "mymesh.ctm"); - * if(ctmGetError(context) == CTM_NONE) - * { - * // Access the mesh data - * vertCount = ctmGetInteger(context, CTM_VERTEX_COUNT); - * vertices = ctmGetFloatArray(context, CTM_VERTICES); - * triCount = ctmGetInteger(context, CTM_TRIANGLE_COUNT); - * indices = ctmGetIntegerArray(context, CTM_INDICES); - * - * // Deal with the mesh (e.g. transcode it to our internal representation) - * // ... - * } - * - * // Free the context - * ctmFreeContext(context); - * @endcode - * - * @subsection example_create_sec Creating a CTM file - * - * Here is a simple example of creating a CTM file: - * - * @code - * CTMcontext context; - * CTMuint vertCount, triCount, * indices; - * CTMfloat * vertices; - * - * // Create our mesh in memory - * vertCount = 100; - * triCount = 120; - * vertices = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * vertCount); - * indices = (CTMuint *) malloc(3 * sizeof(CTMuint) * triCount); - * // ... - * - * // Create a new context - * context = ctmNewContext(CTM_EXPORT); - * - * // Define our mesh representation to OpenCTM (store references to it in - * // the context) - * ctmDefineMesh(context, vertices, vertCount, indices, triCount, NULL); - * - * // Save the OpenCTM file - * ctmSave(context, "mymesh.ctm"); - * - * // Free the context - * ctmFreeContext(context); - * - * // Free our mesh - * free(indices); - * free(vertices); - * @endcode - */ - -#ifdef __cplusplus -extern "C" { -#endif - - -// Declare calling conventions etc. -#if defined(WIN32) || defined(_WIN32) - // Windows - #if defined(OPENCTM_STATIC) - #define CTMEXPORT - #else - #if defined(OPENCTM_BUILD) - #define CTMEXPORT __declspec(dllexport) - #else - #define CTMEXPORT __declspec(dllimport) - #endif - #endif - #if defined(__MINGW32__) - #define CTMCALL __attribute__ ((__stdcall__)) - #elif (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CTMCALL __stdcall - #else - #define CTMCALL - #endif -#else - // Unix - #if !defined(OPENCTM_STATIC) && !defined(OPENCTM_BUILD) - #define CTMEXPORT extern - #else - #if defined(OPENCTM_BUILD) && defined(__GNUC__) && (__GNUC__ >= 4) - #define CTMEXPORT __attribute__ ((visibility("default"))) - #else - #define CTMEXPORT - #endif - #endif - #define CTMCALL -#endif - - -// Get system specific type definitions for sized integers. We use the C99 -// standard stdint.h for this. -#ifdef _MSC_VER - // MS Visual Studio does not support C99 - typedef int int32_t; - typedef unsigned int uint32_t; -#else - #include -#endif - - -/// OpenCTM API version (1.0). -#define CTM_API_VERSION 0x00000100 - -/// Boolean TRUE. -#define CTM_TRUE 1 - -/// Boolean FALSE. -#define CTM_FALSE 0 - -/// Single precision floating point type (IEEE 754 32 bits wide). -typedef float CTMfloat; - -/// Signed integer (32 bits wide). -typedef int32_t CTMint; - -/// Unsigned integer (32 bits wide). -typedef uint32_t CTMuint; - -/// OpenCTM context handle. -typedef void * CTMcontext; - -/// OpenCTM specific enumerators. -/// @note For the information query functions, it is an error to query a value -/// of the wrong type (e.g. to query a string value with the -/// ctmGetInteger() function). -typedef enum { - // Error codes (see ctmGetError()) - CTM_NONE = 0x0000, ///< No error has occured (everything is OK). - /// Also used as an error return value for - /// functions that should return a CTMenum - /// value. - CTM_INVALID_CONTEXT = 0x0001, ///< The OpenCTM context was invalid (e.g. NULL). - CTM_INVALID_ARGUMENT = 0x0002, ///< A function argument was invalid. - CTM_INVALID_OPERATION = 0x0003, ///< The operation is not allowed. - CTM_INVALID_MESH = 0x0004, ///< The mesh was invalid (e.g. no vertices). - CTM_OUT_OF_MEMORY = 0x0005, ///< Not enough memory to proceed. - CTM_FILE_ERROR = 0x0006, ///< File I/O error. - CTM_BAD_FORMAT = 0x0007, ///< File format error (e.g. unrecognized format or corrupted file). - CTM_LZMA_ERROR = 0x0008, ///< An error occured within the LZMA library. - CTM_INTERNAL_ERROR = 0x0009, ///< An internal error occured (indicates a bug). - CTM_UNSUPPORTED_FORMAT_VERSION = 0x000A, ///< Unsupported file format version. - - // OpenCTM context modes - CTM_IMPORT = 0x0101, ///< The OpenCTM context will be used for importing data. - CTM_EXPORT = 0x0102, ///< The OpenCTM context will be used for exporting data. - - // Compression methods - CTM_METHOD_RAW = 0x0201, ///< Just store the raw data. - CTM_METHOD_MG1 = 0x0202, ///< Lossless compression (floating point). - CTM_METHOD_MG2 = 0x0203, ///< Lossless compression (fixed point). - - // Context queries - CTM_VERTEX_COUNT = 0x0301, ///< Number of vertices in the mesh (integer). - CTM_TRIANGLE_COUNT = 0x0302, ///< Number of triangles in the mesh (integer). - CTM_HAS_NORMALS = 0x0303, ///< CTM_TRUE if the mesh has normals (integer). - CTM_UV_MAP_COUNT = 0x0304, ///< Number of UV coordinate sets (integer). - CTM_ATTRIB_MAP_COUNT = 0x0305, ///< Number of custom attribute sets (integer). - CTM_VERTEX_PRECISION = 0x0306, ///< Vertex precision - for MG2 (float). - CTM_NORMAL_PRECISION = 0x0307, ///< Normal precision - for MG2 (float). - CTM_COMPRESSION_METHOD = 0x0308, ///< Compression method (integer). - CTM_FILE_COMMENT = 0x0309, ///< File comment (string). - - // UV/attribute map queries - CTM_NAME = 0x0501, ///< Unique name (UV/attrib map string). - CTM_FILE_NAME = 0x0502, ///< File name reference (UV map string). - CTM_PRECISION = 0x0503, ///< Value precision (UV/attrib map float). - - // Array queries - CTM_INDICES = 0x0601, ///< Triangle indices (integer array). - CTM_VERTICES = 0x0602, ///< Vertex point coordinates (float array). - CTM_NORMALS = 0x0603, ///< Per vertex normals (float array). - CTM_UV_MAP_1 = 0x0700, ///< Per vertex UV map 1 (float array). - CTM_UV_MAP_2 = 0x0701, ///< Per vertex UV map 2 (float array). - CTM_UV_MAP_3 = 0x0702, ///< Per vertex UV map 3 (float array). - CTM_UV_MAP_4 = 0x0703, ///< Per vertex UV map 4 (float array). - CTM_UV_MAP_5 = 0x0704, ///< Per vertex UV map 5 (float array). - CTM_UV_MAP_6 = 0x0705, ///< Per vertex UV map 6 (float array). - CTM_UV_MAP_7 = 0x0706, ///< Per vertex UV map 7 (float array). - CTM_UV_MAP_8 = 0x0707, ///< Per vertex UV map 8 (float array). - CTM_ATTRIB_MAP_1 = 0x0800, ///< Per vertex attribute map 1 (float array). - CTM_ATTRIB_MAP_2 = 0x0801, ///< Per vertex attribute map 2 (float array). - CTM_ATTRIB_MAP_3 = 0x0802, ///< Per vertex attribute map 3 (float array). - CTM_ATTRIB_MAP_4 = 0x0803, ///< Per vertex attribute map 4 (float array). - CTM_ATTRIB_MAP_5 = 0x0804, ///< Per vertex attribute map 5 (float array). - CTM_ATTRIB_MAP_6 = 0x0805, ///< Per vertex attribute map 6 (float array). - CTM_ATTRIB_MAP_7 = 0x0806, ///< Per vertex attribute map 7 (float array). - CTM_ATTRIB_MAP_8 = 0x0807 ///< Per vertex attribute map 8 (float array). -} CTMenum; - -/// Stream read() function pointer. -/// @param[in] aBuf Pointer to the memory buffer to which data should be read. -/// @param[in] aCount The number of bytes to read. -/// @param[in] aUserData The custom user data that was passed to the -/// ctmLoadCustom() function. -/// @return The number of bytes actually read (if this is less than aCount, it -/// indicates that an error occured or the end of file was reached -/// before all bytes were read). -typedef CTMuint (CTMCALL * CTMreadfn)(void * aBuf, CTMuint aCount, void * aUserData); - -/// Stream write() function pointer. -/// @param[in] aBuf Pointer to the memory buffer from which data should be written. -/// @param[in] aCount The number of bytes to write. -/// @param[in] aUserData The custom user data that was passed to the -/// ctmSaveCustom() function. -/// @return The number of bytes actually written (if this is less than aCount, it -/// indicates that an error occured). -typedef CTMuint (CTMCALL * CTMwritefn)(const void * aBuf, CTMuint aCount, void * aUserData); - -/// Create a new OpenCTM context. The context is used for all subsequent -/// OpenCTM function calls. Several contexts can coexist at the same time. -/// @param[in] aMode An OpenCTM context mode. Set this to CTM_IMPORT if the -/// context will be used for importing data, or set it to CTM_EXPORT -/// if it will be used for exporting data. -/// @return An OpenCTM context handle (or NULL if no context could be created). -CTMEXPORT CTMcontext CTMCALL ctmNewContext(CTMenum aMode); - -/// Free an OpenCTM context. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @see ctmNewContext() -CTMEXPORT void CTMCALL ctmFreeContext(CTMcontext aContext); - -/// Returns the latest error. Calling this function will return the last -/// produced error code, or CTM_NO_ERROR (zero) if no error has occured since -/// the last call to ctmGetError(). When this function is called, the internal -/// error varibale will be reset to CTM_NONE. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @return An OpenCTM error code. -/// @see CTMenum -CTMEXPORT CTMenum CTMCALL ctmGetError(CTMcontext aContext); - -/// Converts an OpenCTM error code to a zero-terminated string. -/// @param[in] aError An OpenCTM error code, as returned by ctmGetError(). -/// @return A zero terminated string that describes the error. For instance, -/// if \c aError is CTM_INVALID_OPERATION, then the return value will -/// be "CTM_INVALID_OPERATION". -/// @see CTMenum -CTMEXPORT const char * CTMCALL ctmErrorString(CTMenum aError); - -/// Get information about an OpenCTM context. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aProperty Which property to return. -/// @return An integer value, representing the OpenCTM context property given -/// by \c aProperty. -/// @see CTMenum -CTMEXPORT CTMuint CTMCALL ctmGetInteger(CTMcontext aContext, CTMenum aProperty); - -/// Get information about an OpenCTM context. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aProperty Which property to return. -/// @return A floating point value, representing the OpenCTM context property -/// given by \c aProperty. -/// @see CTMenum -CTMEXPORT CTMfloat CTMCALL ctmGetFloat(CTMcontext aContext, CTMenum aProperty); - -/// Get an integer array from an OpenCTM context. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aProperty Which array to return. -/// @return An integer array. If the requested array does not exist, or -/// if \c aProperty does not indicate an integer array, the function -/// returns NULL. -/// @note The array is only valid as long as the OpenCTM context is valid, or -/// until the corresponding array changes within the OpenCTM context. -/// Trying to access an invalid array will result in undefined -/// behaviour. Therefor it is recommended that the array is copied to -/// a new variable if it is to be used other than directly after the call -/// to ctmGetIntegerArray(). -/// @see CTMenum -CTMEXPORT const CTMuint * CTMCALL ctmGetIntegerArray(CTMcontext aContext, - CTMenum aProperty); - -/// Get a floating point array from an OpenCTM context. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aProperty Which array to return. -/// @return A floating point array. If the requested array does not exist, or -/// if \c aProperty does not indicate a float array, the function -/// returns NULL. -/// @note The array is only valid as long as the OpenCTM context is valid, or -/// until the corresponding array changes within the OpenCTM context. -/// Trying to access an invalid array will result in undefined -/// behaviour. Therefor it is recommended that the array is copied to -/// a new variable if it is to be used other than directly after the call -/// to ctmGetFloatArray(). -/// @see CTMenum -CTMEXPORT const CTMfloat * CTMCALL ctmGetFloatArray(CTMcontext aContext, - CTMenum aProperty); - -/// Get a reference to the named UV map. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aName The name of the UV map that should be returned. -/// @return A reference to a UV map. If the UV map was found, a value of -/// CTM_UV_MAP_1 or higher is returned, otherwise CTM_NONE is -/// returned. -CTMEXPORT CTMenum CTMCALL ctmGetNamedUVMap(CTMcontext aContext, - const char * aName); - -/// Get information about a UV map. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aUVMap Which UV map to query (CTM_UV_MAP_1 or higher). -/// @param[in] aProperty Which UV map property to return. -/// @return A string value, representing the UV map property given -/// by \c aProperty. -/// @note The string is only valid as long as the UV map within the OpenCTM -/// context is valid. Trying to access an invalid string will result in -/// undefined behaviour. Therefor it is recommended that the string is -/// copied to a new variable if it is to be used other than directly after -/// the call to ctmGetUVMapString(). -/// @see CTMenum -CTMEXPORT const char * CTMCALL ctmGetUVMapString(CTMcontext aContext, - CTMenum aUVMap, CTMenum aProperty); - -/// Get information about a UV map. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aUVMap Which UV map to query (CTM_UV_MAP_1 or higher). -/// @param[in] aProperty Which UV map property to return. -/// @return A floating point value, representing the UV map property given -/// by \c aProperty. -/// @see CTMenum -CTMEXPORT CTMfloat CTMCALL ctmGetUVMapFloat(CTMcontext aContext, - CTMenum aUVMap, CTMenum aProperty); - -/// Get a reference to the named vertex attribute map. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aName The name of the attribute map that should be returned. -/// @return A reference to an attribute map. If the attribute map was found, -/// a value of CTM_ATTRIB_MAP_1 or higher is returned, otherwise -/// CTM_NONE is returned. -CTMEXPORT CTMenum CTMCALL ctmGetNamedAttribMap(CTMcontext aContext, - const char * aName); - -/// Get information about a vertex attribute map. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aAttribMap Which vertex attribute map to query (CTM_ATTRIB_MAP_1 -/// or higher). -/// @param[in] aProperty Which vertex attribute map property to return. -/// @return A string value, representing the vertex attribute map property given -/// by \c aProperty. -/// @note The string is only valid as long as the vertex attribute map within -/// the OpenCTM context is valid. Trying to access an invalid string will -/// result in undefined behaviour. Therefor it is recommended that the -/// string is copied to a new variable if it is to be used other than -/// directly after the call to ctmGetAttribMapString(). -/// @see CTMenum -CTMEXPORT const char * CTMCALL ctmGetAttribMapString(CTMcontext aContext, - CTMenum aAttribMap, CTMenum aProperty); - -/// Get information about a vertex attribute map. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aAttribMap Which vertex attribute map to query (CTM_ATTRIB_MAP_1 -/// or higher). -/// @param[in] aProperty Which vertex attribute map property to return. -/// @return A floating point value, representing the vertex attribute map -/// property given by \c aProperty. -/// @see CTMenum -CTMEXPORT CTMfloat CTMCALL ctmGetAttribMapFloat(CTMcontext aContext, - CTMenum aAttribMap, CTMenum aProperty); - -/// Get information about an OpenCTM context. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aProperty Which property to return. -/// @return A string value, representing the OpenCTM context property given -/// by \c aProperty. -/// @note The string is only valid as long as the OpenCTM context is valid, or -/// until the corresponding string changes within the OpenCTM context -/// (e.g. calling ctmFileComment() invalidates the CTM_FILE_COMMENT -/// string). Trying to access an invalid string will result in undefined -/// behaviour. Therefor it is recommended that the string is copied to -/// a new variable if it is to be used other than directly after the call -/// to ctmGetString(). -/// @see CTMenum -CTMEXPORT const char * CTMCALL ctmGetString(CTMcontext aContext, - CTMenum aProperty); - -/// Set which compression method to use for the given OpenCTM context. -/// The selected compression method will be used when calling the ctmSave() -/// function. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aMethod Which compression method to use: CTM_METHOD_RAW, -/// CTM_METHOD_MG1 or CTM_METHOD_MG2 (the default method is -/// CTM_METHOD_MG1). -/// @see CTM_METHOD_RAW, CTM_METHOD_MG1, CTM_METHOD_MG2 -CTMEXPORT void CTMCALL ctmCompressionMethod(CTMcontext aContext, - CTMenum aMethod); - -/// Set which LZMA compression level to use for the given OpenCTM context. -/// The compression level can be between 0 (fastest) and 9 (best). The higher -/// the compression level, the more memory is required for compression and -/// decompression. The default compression level is 1. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aLevel Which compression level to use (0 to 9). -CTMEXPORT void CTMCALL ctmCompressionLevel(CTMcontext aContext, - CTMuint aLevel); - -/// Set the vertex coordinate precision (only used by the MG2 compression -/// method). -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aPrecision Fixed point precision. For instance, if this value is -/// 0.001, all vertex coordinates will be rounded to three decimals. -/// The default vertex coordinate precision is 2^-10 ~= 0.00098. -CTMEXPORT void CTMCALL ctmVertexPrecision(CTMcontext aContext, - CTMfloat aPrecision); - -/// Set the vertex coordinate precision, relative to the mesh dimensions (only -/// used by the MG2 compression method). -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aRelPrecision Relative precision. This factor is multiplied by the -/// average triangle edge length in the mesh in order to obtain the -/// final, fixed point precision. For instance, if aRelPrecision is -/// 0.01, and the average edge length is 3.7, then the fixed point -/// precision is set to 0.037. -/// @note The mesh must have been defined using the ctmDefineMesh() function -/// before calling this function. -/// @see ctmVertexPrecision(). -CTMEXPORT void CTMCALL ctmVertexPrecisionRel(CTMcontext aContext, - CTMfloat aRelPrecision); - -/// Set the normal precision (only used by the MG2 compression method). The -/// normal is represented in spherical coordinates in the MG2 compression -/// method, and the normal precision controls the angular and radial resolution. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aPrecision Fixed point precision. For the angular information, -/// this value represents the angular precision. For the radial -/// information, this value is the linear resolution. For instance, -/// 0.01 means that the circle is divided into 100 steps, and the -/// normal magnitude is rounded to 2 decimals. The default normal -/// precision is 2^-8 ~= 0.0039. -CTMEXPORT void CTMCALL ctmNormalPrecision(CTMcontext aContext, - CTMfloat aPrecision); - -/// Set the coordinate precision for the specified UV map (only used by the -/// MG2 compression method). -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aUVMap A UV map specifier for a defined UV map -/// (CTM_UV_MAP_1, ...). -/// @param[in] aPrecision Fixed point precision. For instance, if this value is -/// 0.001, all UV coordinates will be rounded to three decimals. -/// The default UV coordinate precision is 2^-12 ~= 0.00024. -/// @see ctmAddUVMap(). -CTMEXPORT void CTMCALL ctmUVCoordPrecision(CTMcontext aContext, - CTMenum aUVMap, CTMfloat aPrecision); - -/// Set the attribute value precision for the specified attribute map (only -/// used by the MG2 compression method). -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aAttribMap An attribute map specifier for a defined attribute map -/// (CTM_ATTRIB_MAP_1, ...). -/// @param[in] aPrecision Fixed point precision. For instance, if this value is -/// 0.001, all attribute values will be rounded to three decimals. -/// If the attributes represent integer values, set the precision -/// to 1.0. The default attribute precision is 2^-8 ~= 0.0039. -/// @see ctmAddAttribMap(). -CTMEXPORT void CTMCALL ctmAttribPrecision(CTMcontext aContext, - CTMenum aAttribMap, CTMfloat aPrecision); - -/// Set the file comment for the given OpenCTM context. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aFileComment The file comment (zero terminated UTF-8 string). -CTMEXPORT void CTMCALL ctmFileComment(CTMcontext aContext, - const char * aFileComment); - -/// Define a triangle mesh. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aVertices An array of vertices (three consecutive floats make -/// one vertex). -/// @param[in] aVertexCount The number of vertices in \c aVertices (and -/// optionally \c aTexCoords). -/// @param[in] aIndices An array of vertex indices (three consecutive integers -/// make one triangle). -/// @param[in] aTriangleCount The number of triangles in \c aIndices (there -/// must be exactly 3 x \c aTriangleCount indices in \c aIndices). -/// @param[in] aNormals An array of per-vertex normals (or NULL if there are -/// no normals). Each normal is made up by three consecutive floats, -/// and there must be \c aVertexCount normals. -/// @see ctmAddUVMap(), ctmAddAttribMap(), ctmSave(), ctmSaveCustom(). -CTMEXPORT void CTMCALL ctmDefineMesh(CTMcontext aContext, - const CTMfloat * aVertices, CTMuint aVertexCount, const CTMuint * aIndices, - CTMuint aTriangleCount, const CTMfloat * aNormals); - -/// Define a UV map. There can be several UV maps in a mesh. A UV map is -/// typically used for 2D texture mapping. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aUVCoords An array of UV coordinates. Each UV coordinate is made -/// up by two consecutive floats, and there must be as many -/// coordinates as there are vertices in the mesh. -/// @param[in] aName A unique name for this UV map (zero terminated UTF-8 -/// string). -/// @param[in] aFileName A reference to a image file (zero terminated -/// UTF-8 string). If no file name reference exists, pass NULL. -/// @return A UV map index (CTM_UV_MAP_1 and higher). If the function -/// failed, it will return the zero valued CTM_NONE (use ctmGetError() -/// to determine the cause of the error). -/// @note A triangle mesh must have been defined before calling this function, -/// since the number of vertices is defined by the triangle mesh. -/// @see ctmDefineMesh(). -CTMEXPORT CTMenum CTMCALL ctmAddUVMap(CTMcontext aContext, - const CTMfloat * aUVCoords, const char * aName, const char * aFileName); - -/// Define a custom vertex attribute map. Custom vertex attributes can be used -/// for defining special per-vertex attributes, such as color, weight, ambient -/// occlusion factor, etc. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aAttribValues An array of attribute values. Each attribute value -/// is made up by four consecutive floats, and there must be as many -/// values as there are vertices in the mesh. -/// @param[in] aName A unique name for this attribute map (zero terminated UTF-8 -/// string). -/// @return A attribute map index (CTM_ATTRIB_MAP_1 and higher). If the function -/// failed, it will return the zero valued CTM_NONE (use ctmGetError() -/// to determine the cause of the error). -/// @note A triangle mesh must have been defined before calling this function, -/// since the number of vertices is defined by the triangle mesh. -/// @see ctmDefineMesh(). -CTMEXPORT CTMenum CTMCALL ctmAddAttribMap(CTMcontext aContext, - const CTMfloat * aAttribValues, const char * aName); - -/// Load an OpenCTM format file into the context. The mesh data can be retrieved -/// with the various ctmGet functions. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aFileName The name of the file to be loaded. -CTMEXPORT void CTMCALL ctmLoad(CTMcontext aContext, const char * aFileName); - -/// Load an OpenCTM format file using a custom stream read function. The mesh -/// data can be retrieved with the various ctmGet functions. -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aReadFn Pointer to a custom stream read function. -/// @param[in] aUserData Custom user data, which can be a C language FILE -/// handle, C++ istream object, or a custom object pointer -/// of any type. The user data pointer will be passed to the -/// custom stream read function. -/// @see CTMreadfn. -CTMEXPORT void CTMCALL ctmLoadCustom(CTMcontext aContext, CTMreadfn aReadFn, - void * aUserData); - -/// Save an OpenCTM format file. The mesh must have been defined by -/// ctmDefineMesh(). -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aFileName The name of the file to be saved. -CTMEXPORT void CTMCALL ctmSave(CTMcontext aContext, const char * aFileName); - -/// Save an OpenCTM format file using a custom stream write function. The mesh -/// must have been defined by ctmDefineMesh(). -/// @param[in] aContext An OpenCTM context that has been created by -/// ctmNewContext(). -/// @param[in] aWriteFn Pointer to a custom stream write function. -/// @param[in] aUserData Custom user data, which can be a C language FILE -/// handle, C++ ostream object, or a custom object pointer -/// of any type. The user data pointer will be passed to the -/// custom stream write function. -/// @see CTMwritefn. -CTMEXPORT void CTMCALL ctmSaveCustom(CTMcontext aContext, CTMwritefn aWriteFn, - void * aUserData); - -#ifdef __cplusplus -} -#endif - - -// C++ extensions to the API (to disable C++ extensions, define OPENCTM_NO_CPP) -#if defined(__cplusplus) && !defined(OPENCTM_NO_CPP) - #include "openctmpp.h" -#endif - -#endif // __OPENCTM_H_ diff --git a/src/external/OpenCTM-1.0.3/lib/openctm.rc b/src/external/OpenCTM-1.0.3/lib/openctm.rc deleted file mode 100644 index 562417e53..000000000 --- a/src/external/OpenCTM-1.0.3/lib/openctm.rc +++ /dev/null @@ -1,26 +0,0 @@ - -1 VERSIONINFO - FILEVERSION 1,0,3,0 - PRODUCTVERSION 1,0,3,0 - FILEOS 0x4 - FILETYPE 0x2 - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "ProductVersion", "1.0.3.0" - VALUE "FileVersion", "1.0.3.0" - VALUE "FileDescription", "OpenCTM API shared library" - VALUE "ProductName", "OpenCTM" - VALUE "OriginalFilename", "openctm.dll" - VALUE "LegalCopyright", " 2009-2010 Marcus Geelnard" - VALUE "License", "This software is released under the zlib/libpng license." - END - END - - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END - END diff --git a/src/external/OpenCTM-1.0.3/lib/openctmpp.h b/src/external/OpenCTM-1.0.3/lib/openctmpp.h deleted file mode 100644 index e2519f202..000000000 --- a/src/external/OpenCTM-1.0.3/lib/openctmpp.h +++ /dev/null @@ -1,377 +0,0 @@ -//----------------------------------------------------------------------------- -// Product: OpenCTM -// File: openctmpp.h -// Description: C++ wrapper for the OpenCTM API. -//----------------------------------------------------------------------------- -// Copyright (c) 2009-2010 Marcus Geelnard -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -//----------------------------------------------------------------------------- - -// To disable C++ extensions, define OPENCTM_NO_CPP -#ifndef OPENCTM_NO_CPP - -#ifndef __OPENCTMPP_H_ -#define __OPENCTMPP_H_ - -// Just in case (if this file was included from outside openctm.h)... -#ifndef __OPENCTM_H_ -#include "openctm.h" -#endif - -#include - -/// OpenCTM exception. When an error occurs, a \c ctm_error exception is -/// thrown. Its what() function returns the name of the OpenCTM error code -/// (for instance "CTM_INVALID_OPERATION"). -class ctm_error: public std::exception -{ - private: - CTMenum mErrorCode; - - public: - explicit ctm_error(CTMenum aError) - { - mErrorCode = aError; - } - - virtual const char* what() const throw() - { - return ctmErrorString(mErrorCode); - } - - CTMenum error_code() const throw() - { - return mErrorCode; - } -}; - - -/// OpenCTM importer class. This is a C++ wrapper class for an OpenCTM import -/// context. Usage example: -/// -/// @code -/// // Create a new OpenCTM importer object -/// CTMimporter ctm; -/// -/// // Load the OpenCTM file -/// ctm.Load("mymesh.ctm"); -/// -/// // Access the mesh data -/// vertCount = ctm.GetInteger(CTM_VERTEX_COUNT); -/// vertices = ctm.GetFloatArray(CTM_VERTICES); -/// triCount = ctm.GetInteger(CTM_TRIANGLE_COUNT); -/// indices = ctm.GetIntegerArray(CTM_INDICES); -/// -/// // Deal with the mesh (e.g. transcode it to our internal representation) -/// // ... -/// @endcode - -class CTMimporter { - private: - /// The OpenCTM context handle. - CTMcontext mContext; - - /// Check for OpenCTM errors, and throw an exception if an error has - /// occured. - void CheckError() - { - CTMenum err = ctmGetError(mContext); - if(err != CTM_NONE) - throw ctm_error(err); - } - - public: - /// Constructor - CTMimporter() - { - mContext = ctmNewContext(CTM_IMPORT); - } - - /// Destructor - ~CTMimporter() - { - ctmFreeContext(mContext); - } - - /// Wrapper for ctmGetInteger() - CTMuint GetInteger(CTMenum aProperty) - { - CTMuint res = ctmGetInteger(mContext, aProperty); - CheckError(); - return res; - } - - /// Wrapper for ctmGetFloat() - CTMfloat GetFloat(CTMenum aProperty) - { - CTMfloat res = ctmGetFloat(mContext, aProperty); - CheckError(); - return res; - } - - /// Wrapper for ctmGetIntegerArray() - const CTMuint * GetIntegerArray(CTMenum aProperty) - { - const CTMuint * res = ctmGetIntegerArray(mContext, aProperty); - CheckError(); - return res; - } - - /// Wrapper for ctmGetFloatArray() - const CTMfloat * GetFloatArray(CTMenum aProperty) - { - const CTMfloat * res = ctmGetFloatArray(mContext, aProperty); - CheckError(); - return res; - } - - /// Wrapper for ctmGetNamedUVMap() - CTMenum GetNamedUVMap(const char * aName) - { - CTMenum res = ctmGetNamedUVMap(mContext, aName); - CheckError(); - return res; - } - - /// Wrapper for ctmGetUVMapString() - const char * GetUVMapString(CTMenum aUVMap, CTMenum aProperty) - { - const char * res = ctmGetUVMapString(mContext, aUVMap, aProperty); - CheckError(); - return res; - } - - /// Wrapper for ctmGetUVMapFloat() - CTMfloat GetUVMapFloat(CTMenum aUVMap, CTMenum aProperty) - { - CTMfloat res = ctmGetUVMapFloat(mContext, aUVMap, aProperty); - CheckError(); - return res; - } - - /// Wrapper for ctmGetNamedAttribMap() - CTMenum GetNamedAttribMap(const char * aName) - { - CTMenum res = ctmGetNamedAttribMap(mContext, aName); - CheckError(); - return res; - } - - /// Wrapper for ctmGetAttribMapString() - const char * GetAttribMapString(CTMenum aAttribMap, CTMenum aProperty) - { - const char * res = ctmGetAttribMapString(mContext, aAttribMap, aProperty); - CheckError(); - return res; - } - - /// Wrapper for ctmGetAttribMapFloat() - CTMfloat GetAttribMapFloat(CTMenum aAttribMap, CTMenum aProperty) - { - CTMfloat res = ctmGetAttribMapFloat(mContext, aAttribMap, aProperty); - CheckError(); - return res; - } - - /// Wrapper for ctmGetString() - const char * GetString(CTMenum aProperty) - { - const char * res = ctmGetString(mContext, aProperty); - CheckError(); - return res; - } - - /// Wrapper for ctmLoad() - void Load(const char * aFileName) - { - ctmLoad(mContext, aFileName); - CheckError(); - } - - /// Wrapper for ctmLoadCustom() - void LoadCustom(CTMreadfn aReadFn, void * aUserData) - { - ctmLoadCustom(mContext, aReadFn, aUserData); - CheckError(); - } - - // You can not copy nor assign from one CTMimporter object to another, since - // the object contains hidden state. By declaring these dummy prototypes - // without an implementation, you will at least get linker errors if you try - // to copy or assign a CTMimporter object. - CTMimporter(const CTMimporter& v); - CTMimporter& operator=(const CTMimporter& v); -}; - - -/// OpenCTM exporter class. This is a C++ wrapper class for an OpenCTM export -/// context. Usage example: -/// @code -/// void MySaveFile(CTMuint aVertCount, CTMuint aTriCount, CTMfloat * aVertices, -/// CTMuint * aIndices, const char * aFileName) -/// { -/// // Create a new OpenCTM exporter object -/// CTMexporter ctm; -/// -/// // Define our mesh representation to OpenCTM (store references to it in -/// // the context) -/// ctm.DefineMesh(aVertices, aVertCount, aIndices, aTriCount, NULL); -/// -/// // Save the OpenCTM file -/// ctm.Save(aFileName); -/// } -/// @endcode - -class CTMexporter { - private: - /// The OpenCTM context handle. - CTMcontext mContext; - - /// Check for OpenCTM errors, and throw an exception if an error has - /// occured. - void CheckError() - { - CTMenum err = ctmGetError(mContext); - if(err != CTM_NONE) - throw ctm_error(err); - } - - public: - /// Constructor - CTMexporter() - { - mContext = ctmNewContext(CTM_EXPORT); - } - - /// Destructor - ~CTMexporter() - { - ctmFreeContext(mContext); - } - - /// Wrapper for ctmCompressionMethod() - void CompressionMethod(CTMenum aMethod) - { - ctmCompressionMethod(mContext, aMethod); - CheckError(); - } - - /// Wrapper for ctmCompressionLevel() - void CompressionLevel(CTMuint aLevel) - { - ctmCompressionLevel(mContext, aLevel); - CheckError(); - } - - /// Wrapper for ctmVertexPrecision() - void VertexPrecision(CTMfloat aPrecision) - { - ctmVertexPrecision(mContext, aPrecision); - CheckError(); - } - - /// Wrapper for ctmVertexPrecisionRel() - void VertexPrecisionRel(CTMfloat aRelPrecision) - { - ctmVertexPrecisionRel(mContext, aRelPrecision); - CheckError(); - } - - /// Wrapper for ctmNormalPrecision() - void NormalPrecision(CTMfloat aPrecision) - { - ctmNormalPrecision(mContext, aPrecision); - CheckError(); - } - - /// Wrapper for ctmUVCoordPrecision() - void UVCoordPrecision(CTMenum aUVMap, CTMfloat aPrecision) - { - ctmUVCoordPrecision(mContext, aUVMap, aPrecision); - CheckError(); - } - - /// Wrapper for ctmAttribPrecision() - void AttribPrecision(CTMenum aAttribMap, CTMfloat aPrecision) - { - ctmAttribPrecision(mContext, aAttribMap, aPrecision); - CheckError(); - } - - /// Wrapper for ctmFileComment() - void FileComment(const char * aFileComment) - { - ctmFileComment(mContext, aFileComment); - CheckError(); - } - - /// Wrapper for ctmDefineMesh() - void DefineMesh(const CTMfloat * aVertices, CTMuint aVertexCount, - const CTMuint * aIndices, CTMuint aTriangleCount, - const CTMfloat * aNormals) - { - ctmDefineMesh(mContext, aVertices, aVertexCount, aIndices, aTriangleCount, - aNormals); - CheckError(); - } - - /// Wrapper for ctmAddUVMap() - CTMenum AddUVMap(const CTMfloat * aUVCoords, const char * aName, - const char * aFileName) - { - CTMenum res = ctmAddUVMap(mContext, aUVCoords, aName, aFileName); - CheckError(); - return res; - } - - /// Wrapper for ctmAddAttribMap() - CTMenum AddAttribMap(const CTMfloat * aAttribValues, const char * aName) - { - CTMenum res = ctmAddAttribMap(mContext, aAttribValues, aName); - CheckError(); - return res; - } - - /// Wrapper for ctmSave() - void Save(const char * aFileName) - { - ctmSave(mContext, aFileName); - CheckError(); - } - - /// Wrapper for ctmSaveCustom() - void SaveCustom(CTMwritefn aWriteFn, void * aUserData) - { - ctmSaveCustom(mContext, aWriteFn, aUserData); - CheckError(); - } - - // You can not copy nor assign from one CTMexporter object to another, since - // the object contains hidden state. By declaring these dummy prototypes - // without an implementation, you will at least get linker errors if you try - // to copy or assign a CTMexporter object. - CTMexporter(const CTMexporter& v); - CTMexporter& operator=(const CTMexporter& v); -}; - -#endif // __OPENCTMPP_H_ - -#endif // OPENCTM_NO_CPP diff --git a/src/external/OpenCTM-1.0.3/lib/stream.c b/src/external/OpenCTM-1.0.3/lib/stream.c deleted file mode 100644 index c67f43779..000000000 --- a/src/external/OpenCTM-1.0.3/lib/stream.c +++ /dev/null @@ -1,512 +0,0 @@ -//----------------------------------------------------------------------------- -// Product: OpenCTM -// File: stream.c -// Description: Stream I/O functions. -//----------------------------------------------------------------------------- -// Copyright (c) 2009-2010 Marcus Geelnard -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -//----------------------------------------------------------------------------- - -#include -#include -#include -#include "openctm.h" -#include "internal.h" - -#ifdef __DEBUG_ -#include -#endif - -//----------------------------------------------------------------------------- -// _ctmStreamRead() - Read data from a stream. -//----------------------------------------------------------------------------- -CTMuint _ctmStreamRead(_CTMcontext * self, void * aBuf, CTMuint aCount) -{ - if(!self->mUserData || !self->mReadFn) - return 0; - - return self->mReadFn(aBuf, aCount, self->mUserData); -} - -//----------------------------------------------------------------------------- -// _ctmStreamWrite() - Write data to a stream. -//----------------------------------------------------------------------------- -CTMuint _ctmStreamWrite(_CTMcontext * self, void * aBuf, CTMuint aCount) -{ - if(!self->mUserData || !self->mWriteFn) - return 0; - - return self->mWriteFn(aBuf, aCount, self->mUserData); -} - -//----------------------------------------------------------------------------- -// _ctmStreamReadUINT() - Read an unsigned integer from a stream in a machine -// endian independent manner (for portability). -//----------------------------------------------------------------------------- -CTMuint _ctmStreamReadUINT(_CTMcontext * self) -{ - unsigned char buf[4]; - _ctmStreamRead(self, (void *) buf, 4); - return ((CTMuint) buf[0]) | - (((CTMuint) buf[1]) << 8) | - (((CTMuint) buf[2]) << 16) | - (((CTMuint) buf[3]) << 24); -} - -//----------------------------------------------------------------------------- -// _ctmStreamWriteUINT() - Write an unsigned integer to a stream in a machine -// endian independent manner (for portability). -//----------------------------------------------------------------------------- -void _ctmStreamWriteUINT(_CTMcontext * self, CTMuint aValue) -{ - unsigned char buf[4]; - buf[0] = aValue & 0x000000ff; - buf[1] = (aValue >> 8) & 0x000000ff; - buf[2] = (aValue >> 16) & 0x000000ff; - buf[3] = (aValue >> 24) & 0x000000ff; - _ctmStreamWrite(self, (void *) buf, 4); -} - -//----------------------------------------------------------------------------- -// _ctmStreamReadFLOAT() - Read a floating point value from a stream in a -// machine endian independent manner (for portability). -//----------------------------------------------------------------------------- -CTMfloat _ctmStreamReadFLOAT(_CTMcontext * self) -{ - union { - CTMfloat f; - CTMuint i; - } u; - u.i = _ctmStreamReadUINT(self); - return u.f; -} - -//----------------------------------------------------------------------------- -// _ctmStreamWriteFLOAT() - Write a floating point value to a stream in a -// machine endian independent manner (for portability). -//----------------------------------------------------------------------------- -void _ctmStreamWriteFLOAT(_CTMcontext * self, CTMfloat aValue) -{ - union { - CTMfloat f; - CTMuint i; - } u; - u.f = aValue; - _ctmStreamWriteUINT(self, u.i); -} - -//----------------------------------------------------------------------------- -// _ctmStreamReadSTRING() - Read a string value from a stream. The format of -// the string in the stream is: an unsigned integer (string length) followed by -// the string (without null termination). -//----------------------------------------------------------------------------- -void _ctmStreamReadSTRING(_CTMcontext * self, char ** aValue) -{ - CTMuint len; - - // Clear the old string - if(*aValue) - { - free(*aValue); - *aValue = (char *) 0; - } - - // Get string length - len = _ctmStreamReadUINT(self); - - // Read string - if(len > 0) - { - *aValue = (char *) malloc(len + 1); - if(*aValue) - { - _ctmStreamRead(self, (void *) *aValue, len); - (*aValue)[len] = 0; - } - } -} - -//----------------------------------------------------------------------------- -// _ctmStreamWriteSTRING() - Write a string value to a stream. The format of -// the string in the stream is: an unsigned integer (string length) followed by -// the string (without null termination). -//----------------------------------------------------------------------------- -void _ctmStreamWriteSTRING(_CTMcontext * self, const char * aValue) -{ - CTMuint len; - - // Get string length - if(aValue) - len = strlen(aValue); - else - len = 0; - - // Write string length - _ctmStreamWriteUINT(self, len); - - // Write string - if(len > 0) - _ctmStreamWrite(self, (void *) aValue, len); -} - -//----------------------------------------------------------------------------- -// _ctmStreamReadPackedInts() - Read an compressed binary integer data array -// from a stream, and uncompress it. -//----------------------------------------------------------------------------- -int _ctmStreamReadPackedInts(_CTMcontext * self, CTMint * aData, - CTMuint aCount, CTMuint aSize, CTMint aSignedInts) -{ - size_t packedSize, unpackedSize; - CTMuint i, k, x; - CTMint value; - unsigned char * packed, * tmp; - unsigned char props[5]; - int lzmaRes; - - // Read packed data size from the stream - packedSize = (size_t) _ctmStreamReadUINT(self); - - // Read LZMA compression props from the stream - _ctmStreamRead(self, (void *) props, 5); - - // Allocate memory and read the packed data from the stream - packed = (unsigned char *) malloc(packedSize); - if(!packed) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - _ctmStreamRead(self, (void *) packed, packedSize); - - // Allocate memory for interleaved array - tmp = (unsigned char *) malloc(aCount * aSize * 4); - if(!tmp) - { - free(packed); - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - - // Uncompress - unpackedSize = aCount * aSize * 4; - lzmaRes = LzmaUncompress(tmp, &unpackedSize, packed, - &packedSize, props, 5); - - // Free the packed array - free(packed); - - // Error? - if((lzmaRes != SZ_OK) || (unpackedSize != aCount * aSize * 4)) - { - self->mError = CTM_LZMA_ERROR; - free(tmp); - return CTM_FALSE; - } - - // Convert interleaved array to integers - for(i = 0; i < aCount; ++ i) - { - for(k = 0; k < aSize; ++ k) - { - value = (CTMint) tmp[i + k * aCount + 3 * aCount * aSize] | - (((CTMint) tmp[i + k * aCount + 2 * aCount * aSize]) << 8) | - (((CTMint) tmp[i + k * aCount + aCount * aSize]) << 16) | - (((CTMint) tmp[i + k * aCount]) << 24); - // Convert signed magnitude to two's complement? - if(aSignedInts) - { - x = (CTMuint) value; - value = (x & 1) ? -(CTMint)((x + 1) >> 1) : (CTMint)(x >> 1); - } - aData[i * aSize + k] = value; - } - } - - // Free the interleaved array - free(tmp); - - return CTM_TRUE; -} - -//----------------------------------------------------------------------------- -// _ctmStreamWritePackedInts() - Compress a binary integer data array, and -// write it to a stream. -//----------------------------------------------------------------------------- -int _ctmStreamWritePackedInts(_CTMcontext * self, CTMint * aData, - CTMuint aCount, CTMuint aSize, CTMint aSignedInts) -{ - int lzmaRes, lzmaAlgo; - CTMuint i, k; - CTMint value; - size_t bufSize, outPropsSize; - unsigned char * packed, outProps[5], *tmp; -#ifdef __DEBUG_ - CTMuint negCount = 0; -#endif - - // Allocate memory for interleaved array - tmp = (unsigned char *) malloc(aCount * aSize * 4); - if(!tmp) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - - // Convert integers to an interleaved array - for(i = 0; i < aCount; ++ i) - { - for(k = 0; k < aSize; ++ k) - { - value = aData[i * aSize + k]; - // Convert two's complement to signed magnitude? - if(aSignedInts) - value = value < 0 ? -1 - (value << 1) : value << 1; -#ifdef __DEBUG_ - else if(value < 0) - ++ negCount; -#endif - tmp[i + k * aCount + 3 * aCount * aSize] = value & 0x000000ff; - tmp[i + k * aCount + 2 * aCount * aSize] = (value >> 8) & 0x000000ff; - tmp[i + k * aCount + aCount * aSize] = (value >> 16) & 0x000000ff; - tmp[i + k * aCount] = (value >> 24) & 0x000000ff; - } - } - - // Allocate memory for the packed data - bufSize = 1000 + aCount * aSize * 4; - packed = (unsigned char *) malloc(bufSize); - if(!packed) - { - free(tmp); - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - - // Call LZMA to compress - outPropsSize = 5; - lzmaAlgo = (self->mCompressionLevel < 1 ? 0 : 1); - lzmaRes = LzmaCompress(packed, - &bufSize, - (const unsigned char *) tmp, - aCount * aSize * 4, - outProps, - &outPropsSize, - self->mCompressionLevel, // Level (0-9) - 0, -1, -1, -1, -1, -1, // Default values (set by level) - lzmaAlgo // Algorithm (0 = fast, 1 = normal) - ); - - // Free temporary array - free(tmp); - - // Error? - if(lzmaRes != SZ_OK) - { - self->mError = CTM_LZMA_ERROR; - free(packed); - return CTM_FALSE; - } - -#ifdef __DEBUG_ - printf("%d->%d bytes (%d negative words)\n", aCount * aSize * 4, (int) bufSize, negCount); -#endif - - // Write packed data size to the stream - _ctmStreamWriteUINT(self, (CTMuint) bufSize); - - // Write LZMA compression props to the stream - _ctmStreamWrite(self, (void *) outProps, 5); - - // Write the packed data to the stream - _ctmStreamWrite(self, (void *) packed, (CTMuint) bufSize); - - // Free the packed data - free(packed); - - return CTM_TRUE; -} - -//----------------------------------------------------------------------------- -// _ctmStreamReadPackedFloats() - Read an compressed binary float data array -// from a stream, and uncompress it. -//----------------------------------------------------------------------------- -int _ctmStreamReadPackedFloats(_CTMcontext * self, CTMfloat * aData, - CTMuint aCount, CTMuint aSize) -{ - CTMuint i, k; - size_t packedSize, unpackedSize; - union { - CTMfloat f; - CTMint i; - } value; - unsigned char * packed, * tmp; - unsigned char props[5]; - int lzmaRes; - - // Read packed data size from the stream - packedSize = (size_t) _ctmStreamReadUINT(self); - - // Read LZMA compression props from the stream - _ctmStreamRead(self, (void *) props, 5); - - // Allocate memory and read the packed data from the stream - packed = (unsigned char *) malloc(packedSize); - if(!packed) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - _ctmStreamRead(self, (void *) packed, packedSize); - - // Allocate memory for interleaved array - tmp = (unsigned char *) malloc(aCount * aSize * 4); - if(!tmp) - { - free(packed); - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - - // Uncompress - unpackedSize = aCount * aSize * 4; - lzmaRes = LzmaUncompress(tmp, &unpackedSize, packed, - &packedSize, props, 5); - - // Free the packed array - free(packed); - - // Error? - if((lzmaRes != SZ_OK) || (unpackedSize != aCount * aSize * 4)) - { - self->mError = CTM_LZMA_ERROR; - free(tmp); - return CTM_FALSE; - } - - // Convert interleaved array to floats - for(i = 0; i < aCount; ++ i) - { - for(k = 0; k < aSize; ++ k) - { - value.i = (CTMint) tmp[i + k * aCount + 3 * aCount * aSize] | - (((CTMint) tmp[i + k * aCount + 2 * aCount * aSize]) << 8) | - (((CTMint) tmp[i + k * aCount + aCount * aSize]) << 16) | - (((CTMint) tmp[i + k * aCount]) << 24); - aData[i * aSize + k] = value.f; - } - } - - // Free the interleaved array - free(tmp); - - return CTM_TRUE; -} - -//----------------------------------------------------------------------------- -// _ctmStreamWritePackedFloats() - Compress a binary float data array, and -// write it to a stream. -//----------------------------------------------------------------------------- -int _ctmStreamWritePackedFloats(_CTMcontext * self, CTMfloat * aData, - CTMuint aCount, CTMuint aSize) -{ - int lzmaRes, lzmaAlgo; - CTMuint i, k; - union { - CTMfloat f; - CTMint i; - } value; - size_t bufSize, outPropsSize; - unsigned char * packed, outProps[5], *tmp; - - // Allocate memory for interleaved array - tmp = (unsigned char *) malloc(aCount * aSize * 4); - if(!tmp) - { - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - - // Convert floats to an interleaved array - for(i = 0; i < aCount; ++ i) - { - for(k = 0; k < aSize; ++ k) - { - value.f = aData[i * aSize + k]; - tmp[i + k * aCount + 3 * aCount * aSize] = value.i & 0x000000ff; - tmp[i + k * aCount + 2 * aCount * aSize] = (value.i >> 8) & 0x000000ff; - tmp[i + k * aCount + aCount * aSize] = (value.i >> 16) & 0x000000ff; - tmp[i + k * aCount] = (value.i >> 24) & 0x000000ff; - } - } - - // Allocate memory for the packed data - bufSize = 1000 + aCount * aSize * 4; - packed = (unsigned char *) malloc(bufSize); - if(!packed) - { - free(tmp); - self->mError = CTM_OUT_OF_MEMORY; - return CTM_FALSE; - } - - // Call LZMA to compress - outPropsSize = 5; - lzmaAlgo = (self->mCompressionLevel < 1 ? 0 : 1); - lzmaRes = LzmaCompress(packed, - &bufSize, - (const unsigned char *) tmp, - aCount * aSize * 4, - outProps, - &outPropsSize, - self->mCompressionLevel, // Level (0-9) - 0, -1, -1, -1, -1, -1, // Default values (set by level) - lzmaAlgo // Algorithm (0 = fast, 1 = normal) - ); - - // Free temporary array - free(tmp); - - // Error? - if(lzmaRes != SZ_OK) - { - self->mError = CTM_LZMA_ERROR; - free(packed); - return CTM_FALSE; - } - -#ifdef __DEBUG_ - printf("%d->%d bytes\n", aCount * aSize * 4, (int) bufSize); -#endif - - // Write packed data size to the stream - _ctmStreamWriteUINT(self, (CTMuint) bufSize); - - // Write LZMA compression props to the stream - _ctmStreamWrite(self, (void *) outProps, 5); - - // Write the packed data to the stream - _ctmStreamWrite(self, (void *) packed, (CTMuint) bufSize); - - // Free the packed data - free(packed); - - return CTM_TRUE; -} diff --git a/src/external/OpenCTM-1.0.3/openctm.pro b/src/external/OpenCTM-1.0.3/openctm.pro deleted file mode 100644 index c66752cab..000000000 --- a/src/external/OpenCTM-1.0.3/openctm.pro +++ /dev/null @@ -1,27 +0,0 @@ -include(../ext_common.pri) -TEMPLATE = lib -TARGET = openctm -CONFIG += staticlib -DEPENDPATH += . -INCLUDEPATH += ./lib ./lib/liblzma - -win32-msvc:QMAKE_CXXFLAGS += /nologo /Ox /c /DOPENCTM_STATIC /D_CRT_SECURE_NO_WARNINGS -win32-msvc:DEFINES += OPENCTM_STATIC - -win32-g++:QMAKE_CXXFLAGS += -O3 -c -std=c99 -pedantic -win32-g++:DEFINES += OPENCTM_STATIC -linux-g++:QMAKE_CXXFLAGS += -O3 -c -std=c99 -pedantic -linux-g++:DEFINES += OPENCTM_STATIC - -# Input -SOURCES += \ - lib/openctm.c \ - lib/stream.c \ - lib/compressRAW.c \ - lib/compressMG1.c \ - lib/compressMG2.c \ - lib/liblzma/Alloc.c \ - lib/liblzma/LzFind.c \ - lib/liblzma/LzmaDec.c \ - lib/liblzma/LzmaEnc.c \ - lib/liblzma/LzmaLib.c diff --git a/src/external/OpenGR/.gitignore b/src/external/OpenGR/.gitignore deleted file mode 100644 index 91402184c..000000000 --- a/src/external/OpenGR/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -build*/ -*.user -assets/demo* diff --git a/src/external/OpenGR/.gitmodules b/src/external/OpenGR/.gitmodules deleted file mode 100644 index d1794518f..000000000 --- a/src/external/OpenGR/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "3rdparty/Eigen"] - path = 3rdparty/Eigen - url = https://github.com/eigenteam/eigen-git-mirror.git -[submodule "3rdparty/stb"] - path = 3rdparty/stb - url = https://github.com/nothings/stb.git diff --git a/src/external/OpenGR/.travis.yml b/src/external/OpenGR/.travis.yml deleted file mode 100644 index 92ae0d9fd..000000000 --- a/src/external/OpenGR/.travis.yml +++ /dev/null @@ -1,186 +0,0 @@ -language: cpp -dist: xenial - -script: - - make -j2 VERBOSE=1 && make install - - if [ "$CHEALPIX" == "Off" ]; then make buildtests && make test; fi - - if [ "$BUILD_DOC" == "On" ]; then make doc; fi - -#cache: -# directories: -# - ${TRAVIS_BUILD_DIR}/deps/cmake - -env: - global: - - DEPS_DIR=${TRAVIS_BUILD_DIR}/deps - - -before_install: - - export CHECKOUT_PATH=`pwd`; - - if [ -n "$GCC_VERSION" ]; then export CXX="g++-${GCC_VERSION}" CC="gcc-${GCC_VERSION}"; fi - - if [ -n "$CLANG_VERSION" ]; then export CXX="clang++-${CLANG_VERSION}" CC="clang-${CLANG_VERSION}"; fi - - export OpenGR_RELEASE_NAME="Super4PCS-${TRAVIS_TAG}-${TRAVIS_OS_NAME}-${CXX}" - - export OpenGR_RELEASE_DIR="${CHECKOUT_PATH}/${OpenGR_RELEASE_NAME}" - - $CXX --version - - cmake --version - - -matrix: - include: - # mac clang Release - - env: BUILD_TYPE=Release BOOST=Off CHEALPIX=Off BUILD_DOC=Off - os: osx - compiler: clang - - - # clang 5.0 Release - - env: CLANG_VERSION=5.0 BUILD_TYPE=Release BOOST=Off CHEALPIX=Off BUILD_DOC=Off - os: linux - addons: &clang50 - apt: - packages: - - util-linux - - clang-5.0 - - g++-7 - - cmake - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-xenial-5.0 - - - # gcc-7 Release - - env: GCC_VERSION=7 BUILD_TYPE=Release BOOST=Off CHEALPIX=Off BUILD_DOC=Off - os: linux - addons: &gcc7 - apt: - packages: - - g++-7 - - cmake - sources: - - ubuntu-toolchain-r-test - - - ############################################################################ - # BOOST - ############################################################################ - # mac clang Release - - env: BUILD_TYPE=Release BOOST=On CHEALPIX=Off - os: osx - compiler: clang - - - # clang 5.0 Release - - env: CLANG_VERSION=5.0 BUILD_TYPE=Release BOOST=On CHEALPIX=Off BUILD_DOC=Off - os: linux - addons: &clang50 - apt: - packages: - - util-linux - - clang-5.0 - - g++-7 - - cmake - - libboost-filesystem-dev - - libboost-system-dev - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-xenial-5.0 - - - # gcc-7 Release - - env: GCC_VERSION=7 BUILD_TYPE=Release BOOST=On CHEALPIX=Off BUILD_DOC=On - os: linux - addons: &gcc7 - apt: - packages: - - g++-7 - - cmake - - libboost-filesystem-dev - - libboost-system-dev - - doxygen - - graphviz - sources: - - ubuntu-toolchain-r-test - - ############################################################################ - # Chealpix - ############################################################################ - # mac clang - - env: BUILD_TYPE=Release BOOST=On CHEALPIX=On - os: osx - compiler: clang - - - # clang 5.0 - - env: CLANG_VERSION=5.0 BUILD_TYPE=Release BOOST=On CHEALPIX=On BUILD_DOC=Off - os: linux - addons: &clang50 - apt: - packages: - - util-linux - - clang-5.0 - - g++-7 - - cmake - - libboost-filesystem-dev - - libboost-system-dev - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-xenial-5.0 - - - # gcc-7 - - env: GCC_VERSION=7 BUILD_TYPE=Release BOOST=On CHEALPIX=On BUILD_DOC=Off - os: linux - addons: &gcc7 - apt: - packages: - - g++-7 - - cmake - - libboost-filesystem-dev - - libboost-system-dev - sources: - - ubuntu-toolchain-r-test - - -install: - - cd $CHECKOUT_PATH - - - - mkdir -p build - - cd build - - if [ "$GCC_VERSION" == "5" ]; then CXX_FLAGS="${CXX_FLAGS} -DRANGES_CXX_CONSTEXPR=RANGES_CXX_CONSTEXPR11"; fi - - if [ -n "$CLANG_VERSION" ]; then CXX_FLAGS="${CXX_FLAGS} -D__extern_always_inline=inline"; fi - - cmake .. -DOpenGR_COMPILE_TESTS=TRUE -DIO_USE_BOOST=$BOOST -DENABLE_TIMING=FALSE -DOpenGR_USE_CHEALPIX=$CHEALPIX -DDL_DATASETS=FALSE -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${OpenGR_RELEASE_DIR}/ - - -# safelist -branches: - except: - - gh-pages - - -deploy: - provider: pages - skip_cleanup: true - local_dir: build/doc/html - github_token: $GITHUB_API_KEY - on: - branch: master - condition: "$BUILD_DOC = On" - - -############################################################################ -# Artifacts creation -############################################################################ -#after_success: -# - zip -r ${OpenGR_RELEASE_NAME}.zip ${OpenGR_RELEASE_DIR} - -#deploy: -# provider: releases -# draft: true -# skip_cleanup: true -# api_key: -# secure: inU1jKE5PfPyhONbz7OvNLggEAQ0RE4CwY+WaWLsteEXkd7jl+IsIsIJ52E8xSma15HZHw9cqTGlQcZ+Hk8fBJBC4b5wVFOvoVauyMGYY/askI9uQqsmhDzmGk7sbDv/RtPoMfEPOJ8Y78M+NqCBbF8j5Xn9K/xpVOCpQKwG8JJB0/3z/NUu6fmcBwFvu2rqcdqX6FpfZSDOYCZJ0pK7JGKgah4DmV7M71emIlj5GOj007rbhq/C4j4hb9/CyWnh65yC5SA9In/DBgX3t2ipjnOX19Ft/7upCjLDq4KlblmGexdSvN8S3HV6Bcr3lqNU2XcOHML7xeR87EVYclioEqz937rav4XEuhMaRlonY6nPPZUeSyFns29m2K194oupRzgf4FwsdmWdpZN51baO+zy2X+nAovrLGBEjr+rMrg6COsno4pKJT+CDG0UbE34DpnyNPx7rF8T++FzS8LUdIWTLZSHQSBlJhWX3EzAAy7KJ+xOiOXswg7T7D9LoErS8wygDw21ssW0z/vgFzvyOKbfT1O6B3SGnL+e5vnc1A9VqXm/Gp8Rs3lRCOilwC5HIWczJaczCJiHR+boImPNZXuhz9e3WIjMlJ/upqbpMnwKPC+pH4d6d6LWZzaDQDXSZ7bqShBvFQCgAkgy+IVPUU7AwKYkXlkNaba9J2xuRaA0= -# file: ${OpenGR_RELEASE_NAME}.zip -# tag_name: $TRAVIS_TAG #https://github.com/travis-ci/travis-ci/issues/6132#issuecomment-303634652 -# on: -# tags: true diff --git a/src/external/OpenGR/3rdparty/cfitsio/CMakeLists.txt b/src/external/OpenGR/3rdparty/cfitsio/CMakeLists.txt deleted file mode 100644 index c22298681..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/CMakeLists.txt +++ /dev/null @@ -1,112 +0,0 @@ -PROJECT(CFITSIO) -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0) - -# Allow the developer to select if Dynamic or Static libraries are built -OPTION (BUILD_SHARED_LIBS "Build Shared Libraries" ON) -OPTION (USE_PTHREADS "Thread-safe build (using pthreads)" OFF) - -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}") -set (LIB_DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}") -set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include/") - -# Define project version -SET(${PROJECT_NAME}_MAJOR_VERSION 3) -SET(${PROJECT_NAME}_MINOR_VERSION 41) -SET(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_MAJOR_VERSION}.${${PROJECT_NAME}_MINOR_VERSION}) -SET(LIB_NAME cfitsio) - -# Microsoft Visual Studio: -IF(MSVC OR BORLAND) - # Define - ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE) - # Need an empty unistd.h in MSVC for flex-generated eval_l.c: - FILE(WRITE ${CMAKE_SOURCE_DIR}/unistd.h "") - INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) -ENDIF() - -IF(BORLAND) - # Suppress spurious Borland compiler warnings about "Suspicious - # pointer arithmetic", "Possibly incorrect assignment", and - # "Comparing signed and unsigned values". - ADD_DEFINITIONS(-w-spa) - ADD_DEFINITIONS(-w-pia) - ADD_DEFINITIONS(-w-csu) -ENDIF() - -#add_subdirectory (src) - -SET (LIB_TYPE STATIC) -IF (BUILD_SHARED_LIBS) - SET (LIB_TYPE SHARED) -ENDIF (BUILD_SHARED_LIBS) - - -FILE(GLOB H_FILES "*.h") - -IF (USE_PTHREADS) - FIND_PACKAGE(pthreads REQUIRED) - INCLUDE_DIRECTORIES(${PTHREADS_INCLUDE_DIR}) - ADD_DEFINITIONS(-D_REENTRANT) -ENDIF() - -# Math library (not available in MSVC or MINGW) -IF (MSVC OR MINGW) - SET(M_LIB "") -ELSE() - FIND_LIBRARY(M_LIB m) -ENDIF() - -SET(SRC_FILES - buffers.c cfileio.c checksum.c drvrfile.c drvrmem.c - drvrnet.c drvrsmem.c drvrgsiftp.c editcol.c edithdu.c eval_l.c - eval_y.c eval_f.c fitscore.c getcol.c getcolb.c getcold.c getcole.c - getcoli.c getcolj.c getcolk.c getcoll.c getcols.c getcolsb.c - getcoluk.c getcolui.c getcoluj.c getkey.c group.c grparser.c - histo.c iraffits.c - modkey.c putcol.c putcolb.c putcold.c putcole.c putcoli.c - putcolj.c putcolk.c putcoluk.c putcoll.c putcols.c putcolsb.c - putcolu.c putcolui.c putcoluj.c putkey.c region.c scalnull.c - swapproc.c wcssub.c wcsutil.c imcompress.c quantize.c ricecomp.c - pliocomp.c fits_hcompress.c fits_hdecompress.c zlib/zuncompress.c - zlib/zcompress.c zlib/adler32.c zlib/crc32.c zlib/inffast.c - zlib/inftrees.c zlib/trees.c zlib/zutil.c zlib/deflate.c - zlib/infback.c zlib/inflate.c zlib/uncompr.c simplerng.c - f77_wrap1.c f77_wrap2.c f77_wrap3.c f77_wrap4.c -) - -ADD_LIBRARY(${LIB_NAME} ${LIB_TYPE} ${H_FILES} ${SRC_FILES}) -TARGET_LINK_LIBRARIES(${LIB_NAME} ${PTHREADS_LIBRARY} ${M_LIB}) - -SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${${PROJECT_NAME}_VERSION} SOVERSION ${${PROJECT_NAME}_MAJOR_VERSION}) -install(TARGETS ${LIB_NAME} DESTINATION ${LIB_DESTINATION}) -install(FILES ${H_FILES} DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel) - -ENABLE_TESTING() - -ADD_EXECUTABLE(TestProg testprog.c) -TARGET_LINK_LIBRARIES(TestProg ${LIB_NAME}) -ADD_TEST(TestProg TestProg) -# Copy testprog.tpt to build directory to allow quick test -# of ./TestProg (or .\Release\TestProg.exe in MSVC): -FILE(COPY ${CMAKE_SOURCE_DIR}/testprog.tpt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - -ADD_EXECUTABLE(cookbook cookbook.c) -TARGET_LINK_LIBRARIES(cookbook ${LIB_NAME}) -ADD_TEST(cookbook cookbook) - -ADD_EXECUTABLE(FPack fpack.c fpackutil.c) -TARGET_LINK_LIBRARIES(FPack ${LIB_NAME}) - -ADD_EXECUTABLE(Funpack funpack.c fpackutil.c) -TARGET_LINK_LIBRARIES(Funpack ${LIB_NAME}) - -ADD_EXECUTABLE(Fitscopy fitscopy.c) -TARGET_LINK_LIBRARIES(Fitscopy ${LIB_NAME}) - -# To expands the command line arguments in Windows, see: -# http://msdn.microsoft.com/en-us/library/8bch7bkk.aspx -if(MSVC) - set_target_properties(FPack Funpack PROPERTIES - LINK_FLAGS "setargv.obj" - ) -endif(MSVC) diff --git a/src/external/OpenGR/3rdparty/cfitsio/FindPthreads.cmake b/src/external/OpenGR/3rdparty/cfitsio/FindPthreads.cmake deleted file mode 100644 index ce591df6b..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/FindPthreads.cmake +++ /dev/null @@ -1,98 +0,0 @@ -# - Find the Pthreads library -# This module searches for the Pthreads library (including the -# pthreads-win32 port). -# -# This module defines these variables: -# -# PTHREADS_FOUND -# True if the Pthreads library was found -# PTHREADS_LIBRARY -# The location of the Pthreads library -# PTHREADS_INCLUDE_DIR -# The include path of the Pthreads library -# PTHREADS_DEFINITIONS -# Preprocessor definitions to define -# -# This module responds to the PTHREADS_EXCEPTION_SCHEME -# variable on Win32 to allow the user to control the -# library linked against. The Pthreads-win32 port -# provides the ability to link against a version of the -# library with exception handling. IT IS NOT RECOMMENDED -# THAT YOU USE THIS because most POSIX thread implementations -# do not support stack unwinding. -# -# PTHREADS_EXCEPTION_SCHEME -# C = no exceptions (default) -# (NOTE: This is the default scheme on most POSIX thread -# implementations and what you should probably be using) -# CE = C++ Exception Handling -# SE = Structure Exception Handling (MSVC only) -# - -# -# Define a default exception scheme to link against -# and validate user choice. -# -IF(NOT DEFINED PTHREADS_EXCEPTION_SCHEME) - # Assign default if needed - SET(PTHREADS_EXCEPTION_SCHEME "C") -ELSE(NOT DEFINED PTHREADS_EXCEPTION_SCHEME) - # Validate - IF(NOT PTHREADS_EXCEPTION_SCHEME STREQUAL "C" AND - NOT PTHREADS_EXCEPTION_SCHEME STREQUAL "CE" AND - NOT PTHREADS_EXCEPTION_SCHEME STREQUAL "SE") - - MESSAGE(FATAL_ERROR "See documentation for FindPthreads.cmake, only C, CE, and SE modes are allowed") - - ENDIF(NOT PTHREADS_EXCEPTION_SCHEME STREQUAL "C" AND - NOT PTHREADS_EXCEPTION_SCHEME STREQUAL "CE" AND - NOT PTHREADS_EXCEPTION_SCHEME STREQUAL "SE") - - IF(NOT MSVC AND PTHREADS_EXCEPTION_SCHEME STREQUAL "SE") - MESSAGE(FATAL_ERROR "Structured Exception Handling is only allowed for MSVC") - ENDIF(NOT MSVC AND PTHREADS_EXCEPTION_SCHEME STREQUAL "SE") - -ENDIF(NOT DEFINED PTHREADS_EXCEPTION_SCHEME) - -# -# Find the header file -# -FIND_PATH(PTHREADS_INCLUDE_DIR pthread.h) - -# -# Find the library -# -SET(names) -IF(MSVC) - SET(names - pthreadV${PTHREADS_EXCEPTION_SCHEME}2 - pthread - ) -ELSEIF(MINGW) - SET(names - pthreadG${PTHREADS_EXCEPTION_SCHEME}2 - pthread - ) -ELSE(MSVC) # Unix / Cygwin / Apple - SET(names pthread) -ENDIF(MSVC) - -FIND_LIBRARY(PTHREADS_LIBRARY ${names} - DOC "The Portable Threads Library") - -IF(PTHREADS_INCLUDE_DIR AND PTHREADS_LIBRARY) - SET(PTHREADS_FOUND true) - SET(PTHREADS_DEFINITIONS -DHAVE_PTHREAD_H) - SET(PTHREADS_INCLUDE_DIRS ${PTHREADS_INCLUDE_DIR}) - SET(PTHREADS_LIBRARIES ${PTHREADS_LIBRARY}) -ENDIF(PTHREADS_INCLUDE_DIR AND PTHREADS_LIBRARY) - -IF(PTHREADS_FOUND) - IF(NOT PTHREADS_FIND_QUIETLY) - MESSAGE(STATUS "Found Pthreads: ${PTHREADS_LIBRARY}") - ENDIF(NOT PTHREADS_FIND_QUIETLY) -ELSE(PTHREADS_FOUND) - IF(PTHREADS_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find the Pthreads Library") - ENDIF(PTHREADS_FIND_REQUIRED) -ENDIF(PTHREADS_FOUND) diff --git a/src/external/OpenGR/3rdparty/cfitsio/License.txt b/src/external/OpenGR/3rdparty/cfitsio/License.txt deleted file mode 100644 index 2f5f48d3d..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/License.txt +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (Unpublished--all rights reserved under the copyright laws of -the United States), U.S. Government as represented by the Administrator -of the National Aeronautics and Space Administration. No copyright is -claimed in the United States under Title 17, U.S. Code. - -Permission to freely use, copy, modify, and distribute this software -and its documentation without fee is hereby granted, provided that this -copyright notice and disclaimer of warranty appears in all copies. - -DISCLAIMER: - -THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, -EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, -ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY -IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE -DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE -SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY -DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR -CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY -CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, -CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY -PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED -FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR -SERVICES PROVIDED HEREUNDER. diff --git a/src/external/OpenGR/3rdparty/cfitsio/README b/src/external/OpenGR/3rdparty/cfitsio/README deleted file mode 100644 index a6682ce06..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/README +++ /dev/null @@ -1,109 +0,0 @@ - CFITSIO Interface Library - -CFITSIO is a library of ANSI C routines for reading and writing FITS -format data files. A set of Fortran-callable wrapper routines are also -included for the convenience of Fortran programmers. This README file -gives a brief summary of how to build and test CFITSIO, but the CFITSIO -User's Guide, found in the files cfitsio.doc (plain text), cfitsio.tex -(LaTeX source file), cfitsio.ps, or cfitsio.pdf should be -referenced for the latest and most complete information. - -BUILDING CFITSIO ----------------- - -The CFITSIO code is contained in about 40 *.c source files and several *.h -header files. CFITSIO should compile and run on most Unix platforms without -modification, except that Cray supercomputers computers are currently not -supported. The CFITSIO library is built on Unix systems by typing: - - > ./configure [--prefix=/target/installation/path] - > make (or 'make shared') - > make install (this step is optional) - -at the operating system prompt. The configure command customizes the -Makefile for the particular system, then the `make' command compiles the -source files and builds the library. Type `./configure' and not simply -`configure' to ensure that the configure script in the current directory -is run and not some other system-wide configure script. The optional -'prefix' argument to configure gives the path to the directory where -the CFITSIO library and include files should be installed via the later -'make install' command. For example, - - > ./configure --prefix=/usr1/local - -will cause the 'make install' command to copy the CFITSIO libcfitsio file -to /usr1/local/lib and the necessary include files to /usr1/local/include -(assuming of course that the process has permission to write to these -directories). - -All the available configure options can be seen by entering the command - - > ./configure --help - -On VAX/VMS and ALPHA/VMS systems the make.com command file may be used -to build the cfitsio.olb object library using the default G-floating -point option for double variables. The make\_dfloat.com and make\_ieee.com -files may be used instead to build the library with the other floating -point options. - -A precompiled DLL version of CFITSIO is available for IBM-PC users of -the Borland or Microsoft Visual C++ compilers in the files -cfitsiodll_xxxx_borland.zip and cfitsiodll_xxxx_vcc.zip, where 'xxxx' -represents the current release number. These zip archives also -contains other files and instructions on how to use the CFITSIO DLL -library. The CFITSIO library may also be built from the source code -using the makefile.bc or makefile.vcc files. Finally, the makepc.bat -file gives an example of building CFITSIO with the Borland C++ v4.5 -compiler using simpler DOS commands. - -Instructions for building CFITSIO on Mac OS can be found in -the README.MacOS file. - -TESTING CFITSIO ---------------- - -The CFITSIO library should be tested by building and running -the testprog.c program that is included with the release. -On Unix systems, type: -- - % make testprog - % testprog > testprog.lis - % diff testprog.lis testprog.out - % cmp testprog.fit testprog.std -- - On VMS systems, -(assuming cc is the name of the C compiler command), type: -- - $ cc testprog.c - $ link testprog, cfitsio/lib - $ run testprog -- -The testprog program should produce a FITS file called `testprog.fit' -that is identical to the testprog.std FITS file included in this -release. The diagnostic messages (which were piped to the file -testprog.lis in the Unix example) should be identical to the listing -contained in the file testprog.out. The 'diff' and 'cmp' commands -shown above should not report any differences in the files. - -USING CFITSIO -------------- - -The CFITSIO User's Guide, contained in the files cfitsio.doc (plain -text file) and cfitsio.ps (postscript file), provides detailed -documentation about how to build and use the CFITSIO library. -It contains a description of every user-callable routine in the -CFITSIO interface. - -The cookbook.c file provides some sample routines for performing common -operations on various types of FITS files. Programmers are urged to -examine these routines for recommended programming practices when using -CFITSIO. Users are free to copy or modify these routines for their own -purposes. - -Any problem reports or suggestions for -improvements are welcome and should be sent to the HEASARC -help desk. - -------------------------------------------------------------------------- -William D. Pence -HEASARC, NASA/GSFC diff --git a/src/external/OpenGR/3rdparty/cfitsio/README.MacOS b/src/external/OpenGR/3rdparty/cfitsio/README.MacOS deleted file mode 100644 index c17928f94..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/README.MacOS +++ /dev/null @@ -1,75 +0,0 @@ -By default, the CFITSIO library will be a "Universal Binary" (i.e. -32- and 64-bit compatible) under Mac OS X when built in the standard -way, i.e. - -- tar xzf cfitsio3370.tar.gz (or whatever version this is) -- cd cfitsio/ - -- ./configure -- make -- make install - ---------------------------------------------------------------------- -To install CFITSIO using MacPorts: ---------------------------------------------------------------------- - -If you have MacPorts installed, you may install CFITSIO simply with -the command - - $ sudo port install cfitsio +universal - -For more information, please visit: - -http://macports.org -https://trac.macports.org/browser/trunk/dports/science/cfitsio/Portfile - ---------------------------------------------------------------------- -To install CFITSIO using Homebrew: ---------------------------------------------------------------------- - -If you have Homebrew installed, you may install CFITSIO simply with -the command - - $ brew install cfitsio - -For more information, please visit: - -http://brew.sh -http://brewformulas.org/Cfitsio - ---------------------------------------------------------------------- -To build CFITSIO using the XCode GUI: ---------------------------------------------------------------------- - -- tar xzf cfitsio3370.tar.gz (or whatever version this is) -- cd cfitsio/ - -- Start Xcode and open cfitsio.xcodeproj/project.pbxproj, - or just "open" the file from a terminal command line, - - $ open cfitsio.xcodeproj/project.pbxproj - - and this will start up XCode for you. - -- Press the Build (or "Play") button in the upper left - corner of the GUI. - ---------------------------------------------------------------------- ---------------------------------------------------------------------- - -Below, are the old (and now obsolete) instructions for building CFITSIO -on classic Mac OS-9 or earlier versions: - -1. Un binhex and unstuff cfitsio_mac.sit.hqx -2. put CFitsioPPC.mcp in the cfitsio directory. -2. Load CFitsioPPC.mcp into CodeWarrior Pro 5 and make. - This builds the cfitsio library for PPC. There are also targets for both - the test program and the speed test program. - -To use the MacOS port you can add Cfitsio PPC.lib to your Codewarrior Pro 5 -project. Note that this only has been tested for the PPC. It probably -won't work on 68k macs. Also note that the fortran bindings aren't -included. I haven't worked with the codewarrior f2c plugin so I don't know -how these would work. If one is interested, please write and I can look -into this. - diff --git a/src/external/OpenGR/3rdparty/cfitsio/README.win b/src/external/OpenGR/3rdparty/cfitsio/README.win deleted file mode 100644 index 934ecb644..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/README.win +++ /dev/null @@ -1,136 +0,0 @@ -Instructions on building and using CFITSIO on Windows platforms -for C programmers using Microsoft Visual Studio or Borland C++. - -These instructions for building the CFITSIO library under Windows use the -CMake build system that is available from http://www.cmake.org. - -=============================================================================== - -1. Build the CFITSIO dll library - -This step will create the cfitsio.dll, and cfitsio.lib files. If you have -downloaded the CFITSIO DLL .zip file that already contains the pre-built -versions of these files, then SKIP THIS STEP. - - a. If CMAKE is not already installed on your machine, download it from - http://www.cmake.org. It is recommended that you choose the - "Add CMake to the system PATH for current user" option during the - installation setup process for convenience when running CMake later on. - - b. Unzip the CFITSIO .zip file (e.g. cfit3360.zip) that was obtained from - the CFITSIO Web site (http://heasarc.gsfc.nasa.gov/fitsio/). This will - create a new \cfitsio subdirectory that contains the source code and - documentation files. It should also contain a CMakeLists.txt file that - will be used during the CMake build process. - - c. Open the Visual Studio Command Prompt window, likely using a - desktop icon with this same name, (or the equivalent Borland command window) - and CD (change directory) into the parent directory that is one level - above the directory containing the CFITSIO source files that was created - in the previous step. - - d. Create a new "cfitsio.build" subdirectory, and CD into it with the - following commands: - - mkdir cfitsio.build - cd cfitsio.build - - When using Visual Studio, all the files that are generated during the - CMake process will be created in or under this subdirectory. - - e. Decide which CMake Generator you will want to use in the following step. - This depends on which C/C++ compiler you are using and will likely have - a name such as: - - "Visual Studio 10" - "Visual Studio 10 Win64" (for 64-bit builds) - "Visual Studio 11" - "Visual Studio 11 Win64" (for 64-bit builds) - "Visual Studio 12" - "Visual Studio 12 Win64" (for 64-bit builds) - "Borland Makefiles" - "NMake Makefiles" - - You can see a list of all the available CMake Generators by executing - the command - - cmake.exe /? - - Note that these names are case-sensitive and must be entered in the - following step exactly as displayed. - - f. Execute the following commands to build the CFITSIO library: - - cmake.exe -G "" ..\cfitsio - cmake.exe --build . --config Release - - Where the string is the string that was selected - in step e. Note that the "..\cfitsio" argument in the first command - gives the path to the directory that contains the CFITSIO source files - and the CMakeLists.txt file. The "." argument in the second command - (following --build) tells CMake to build the files in the current - directory (i.e., the cfitsio.build directory). - - If this process completes successfully, you should find the CFITSIO - library files that were created in the "cfitsio.build\Release" - subdirectory. To verify that CFITSIO is working correctly, execute the - testprog.exe file (in that Release directory). This should generate - a long stream of diagnostic messages ending with the line "Status = 0: - OK - no error". - - g. Other CMake options. - - CMake has many other build options that may be useful in some - situations. Refer to the CMake documentation for more - information. - - For example, one can build a 'debug' version of the CFITSIO library - by executing the command "cmake.exe --build ." instead of the 2nd - command listed above in section f. - - One can also make a thread safe version of CFITSIO using the - pthread library with the following procedure: - - a. Download the precompiled files from the pthread-win32 project - (http://sourceware.org/pthreads-win32/). Put the files for your - specific platform (.h, .lib, .dll) into a folder 'pthread', - parallel to the cfitsio source folder. - - b. For the compilation of cfitsio follow the cmake steps, but use - this change as a replacement for the commands in step f: - - cmake.exe -G "" ..\cfitsio -DUSE_PTHREADS=1 - -DCMAKE_INCLUDE_PATH=..\pthread -DCMAKE_LIBRARY_PATH=..\pthread - - cmake.exe --build . --config Release - - You may need to adapt the paths for the source directory and - the pthread library. - -============================================================================ - -2. Using CFITSIO when compiling and linking application programs - -First, depending on your particular programming environment, it may be -necessary to copy the cfitsio.lib and cfitsio.dll files into another -directory where your compiler expects to find them. Or equivalently, you -may need to specify the directory path to the location of the CFITSIO -library files when creating a project that uses them. You may also need to -copy the fitsio.h and longnam.h include files from the \cfitsio source file -directory to a standard 'include' directory on your system. - -When using the Visual Studio command line window, application programs can -be compiled and linked with CFITSIO using the following command: - - cl /MD your_program.c cfitsio.lib - -The /MD command line switch must be specified to force the compiler/linker -to use the appropriate runtime library. If this switch is omitted, then -the fits_report_error function in CFITSIO will likely crash. - -When building programs in the Visual Studio graphical environment, one can -force the equivalent of the /MD switch by selecting 'Settings...' under the -'Project' menu, then click on the C/C++ tab and select the 'Code Generator' -category. Then under 'User Run-time Library' select 'Multithreaded DLL'. - -=============================================================================== diff --git a/src/external/OpenGR/3rdparty/cfitsio/README_OLD.win b/src/external/OpenGR/3rdparty/cfitsio/README_OLD.win deleted file mode 100644 index ca79c4045..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/README_OLD.win +++ /dev/null @@ -1,83 +0,0 @@ -=============================================================================== -=============================================================================== -= NOTE: This is the old version of the README.win32 file that was distributed -= with CFITSIO up until version 3.35 in 2013. These instruction may still work -= with more recent versions of CFITSIO, however, users are strongly urged to -= use the CMake procedures that are now documented in the new README.win32 file. -=============================================================================== -=============================================================================== - - Instructions on using CFITSIO on Windows platforms for C programmers - -These instructions use a simple DOS-style command window. It is also possible -to build and use CFITSIO within a GUI programming environment such as Visual -Studio, but this is not supported here. - -=============================================================================== -1. Build the CFITSIO dll library - -This step will create the cfitsio.def, cfitsio.dll, and cfitsio.lib files. -(If you downloaded the CFITSIO .zip file that contains the pre-built binary -.dll file, then SKIP THIS STEP). - - A. With Microsoft Visual C++: - - 1. Open a DOS command window and execute the vcvars32.bat file that - is distributed with older versions of Visual C++, or simply open - the Visual C++ command window (e.g., when using Visual Studio 2010). - - 2. Unpack the CFITSIO source files (cfitxxxx.zip) into a new empty directory - - 3. In the DOS command window, cd to that directory and enter the - following commands: - - nmake winDumpExts.mak - nmake makefile.vcc - (ignore the compiler warning messages) - - B: With Borland C++: - - First, follow the instructions provided by Borland to set up - the proper environment variables and configure files for the compiler. - - Unpack the cfitsio.zip source file distribution into a suitable directory. - - In a DOS command window, cd to that directory and then execute the - makepc.bat batch file on the command line to build the CFITSIO library, - and the testprog and cookbook sample programs. - -=============================================================================== -2. Test the CFITSIO library with Visual C++ - - Compile and link the testprog.c test program. When using Visual Studio, - the command is: - - cl /MD testprog.c cfitsio.lib - - - This will create the testprog.exe executable program. Running this - program should print out a long series of diagnostic messages - that should end with "Status = 0; OK - no error" - -=============================================================================== -3. Compile and link an application program that calls CFITSIO routines - with Visual C++ - - Include the fitsio.h and longnam.h header files in the C source code. - - Link the program with the cfitsio.lib file: - - cl /MD your_program.c cfitsio.lib - - - NOTE: The /MD command line switch must be specified on the cl - command line to force the compiler/linker to use the - appropriete runtime library. If this switch is omitted, then - the fits_report_error function in CFITSIO will likely crash. - - When building programs in the Visual Studio environment, one - can force the equivalent of the /MD switch by selecting - 'Settings...' under the 'Project' menu, then click on the C/C++ - tab and select the 'Code Generator' category. Then under 'User - Run-time Library' select 'Multithreaded DLL'. - diff --git a/src/external/OpenGR/3rdparty/cfitsio/buffers.c b/src/external/OpenGR/3rdparty/cfitsio/buffers.c deleted file mode 100644 index ca1c334dd..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/buffers.c +++ /dev/null @@ -1,1377 +0,0 @@ -/* This file, buffers.c, contains the core set of FITSIO routines */ -/* that use or manage the internal set of IO buffers. */ - -/* The FITSIO software was written by William Pence at the High Energy */ -/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ -/* Goddard Space Flight Center. */ - -#include -#include -#include "fitsio2.h" - -/*--------------------------------------------------------------------------*/ -int ffmbyt(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG bytepos, /* I - byte position in file to move to */ - int err_mode, /* I - 1=ignore error, 0 = return error */ - int *status) /* IO - error status */ -{ -/* - Move to the input byte location in the file. When writing to a file, a move - may sometimes be made to a position beyond the current EOF. The err_mode - parameter determines whether such conditions should be returned as an error - or simply ignored. -*/ - long record; - - if (*status > 0) - return(*status); - - if (bytepos < 0) - return(*status = NEG_FILE_POS); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - record = (long) (bytepos / IOBUFLEN); /* zero-indexed record number */ - - /* if this is not the current record, then load it */ - if ( ((fptr->Fptr)->curbuf < 0) || - (record != (fptr->Fptr)->bufrecnum[(fptr->Fptr)->curbuf])) - ffldrc(fptr, record, err_mode, status); - - if (*status <= 0) - (fptr->Fptr)->bytepos = bytepos; /* save new file position */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffpbyt(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG nbytes, /* I - number of bytes to write */ - void *buffer, /* I - buffer containing the bytes to write */ - int *status) /* IO - error status */ -/* - put (write) the buffer of bytes to the output FITS file, starting at - the current file position. Write large blocks of data directly to disk; - write smaller segments to intermediate IO buffers to improve efficiency. -*/ -{ - int ii, nbuff; - LONGLONG filepos; - long recstart, recend; - long ntodo, bufpos, nspace, nwrite; - char *cptr; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - if (nbytes > LONG_MAX) { - ffpmsg("Number of bytes to write is greater than LONG_MAX (ffpbyt)."); - *status = WRITE_ERROR; - return(*status); - } - - ntodo = (long) nbytes; - cptr = (char *)buffer; - - if ((fptr->Fptr)->curbuf < 0) /* no current data buffer for this file */ - { /* so reload the last one that was used */ - ffldrc(fptr, (long) (((fptr->Fptr)->bytepos) / IOBUFLEN), REPORT_EOF, status); - } - - if (nbytes >= MINDIRECT) - { - /* write large blocks of data directly to disk instead of via buffers */ - /* first, fill up the current IO buffer before flushing it to disk */ - - nbuff = (fptr->Fptr)->curbuf; /* current IO buffer number */ - filepos = (fptr->Fptr)->bytepos; /* save the write starting position */ - recstart = (fptr->Fptr)->bufrecnum[nbuff]; /* starting record */ - recend = (long) ((filepos + nbytes - 1) / IOBUFLEN); /* ending record */ - - /* bufpos is the starting position within the IO buffer */ - bufpos = (long) (filepos - ((LONGLONG)recstart * IOBUFLEN)); - nspace = IOBUFLEN - bufpos; /* amount of space left in the buffer */ - - if (nspace) - { /* fill up the IO buffer */ - memcpy((fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN) + bufpos, cptr, nspace); - ntodo -= nspace; /* decrement remaining number of bytes */ - cptr += nspace; /* increment user buffer pointer */ - filepos += nspace; /* increment file position pointer */ - (fptr->Fptr)->dirty[nbuff] = TRUE; /* mark record as having been modified */ - } - - for (ii = 0; ii < NIOBUF; ii++) /* flush any affected buffers to disk */ - { - if ((fptr->Fptr)->bufrecnum[ii] >= recstart - && (fptr->Fptr)->bufrecnum[ii] <= recend ) - { - if ((fptr->Fptr)->dirty[ii]) /* flush modified buffer to disk */ - ffbfwt(fptr->Fptr, ii, status); - - (fptr->Fptr)->bufrecnum[ii] = -1; /* disassociate buffer from the file */ - } - } - - /* move to the correct write position */ - if ((fptr->Fptr)->io_pos != filepos) - ffseek(fptr->Fptr, filepos); - - nwrite = ((ntodo - 1) / IOBUFLEN) * IOBUFLEN; /* don't write last buff */ - - ffwrite(fptr->Fptr, nwrite, cptr, status); /* write the data */ - ntodo -= nwrite; /* decrement remaining number of bytes */ - cptr += nwrite; /* increment user buffer pointer */ - (fptr->Fptr)->io_pos = filepos + nwrite; /* update the file position */ - - if ((fptr->Fptr)->io_pos >= (fptr->Fptr)->filesize) /* at the EOF? */ - { - (fptr->Fptr)->filesize = (fptr->Fptr)->io_pos; /* increment file size */ - - /* initialize the current buffer with the correct fill value */ - if ((fptr->Fptr)->hdutype == ASCII_TBL) - memset((fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), 32, IOBUFLEN); /* blank fill */ - else - memset((fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), 0, IOBUFLEN); /* zero fill */ - } - else - { - /* read next record */ - ffread(fptr->Fptr, IOBUFLEN, (fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), status); - (fptr->Fptr)->io_pos += IOBUFLEN; - } - - /* copy remaining bytes from user buffer into current IO buffer */ - memcpy((fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), cptr, ntodo); - (fptr->Fptr)->dirty[nbuff] = TRUE; /* mark record as having been modified */ - (fptr->Fptr)->bufrecnum[nbuff] = recend; /* record number */ - - (fptr->Fptr)->logfilesize = maxvalue((fptr->Fptr)->logfilesize, - (LONGLONG)(recend + 1) * IOBUFLEN); - (fptr->Fptr)->bytepos = filepos + nwrite + ntodo; - } - else - { - /* bufpos is the starting position in IO buffer */ - bufpos = (long) ((fptr->Fptr)->bytepos - ((LONGLONG)(fptr->Fptr)->bufrecnum[(fptr->Fptr)->curbuf] * - IOBUFLEN)); - nspace = IOBUFLEN - bufpos; /* amount of space left in the buffer */ - - while (ntodo) - { - nwrite = minvalue(ntodo, nspace); - - /* copy bytes from user's buffer to the IO buffer */ - memcpy((fptr->Fptr)->iobuffer + ((fptr->Fptr)->curbuf * IOBUFLEN) + bufpos, cptr, nwrite); - ntodo -= nwrite; /* decrement remaining number of bytes */ - cptr += nwrite; - (fptr->Fptr)->bytepos += nwrite; /* increment file position pointer */ - (fptr->Fptr)->dirty[(fptr->Fptr)->curbuf] = TRUE; /* mark record as modified */ - - if (ntodo) /* load next record into a buffer */ - { - ffldrc(fptr, (long) ((fptr->Fptr)->bytepos / IOBUFLEN), IGNORE_EOF, status); - bufpos = 0; - nspace = IOBUFLEN; - } - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffpbytoff(fitsfile *fptr, /* I - FITS file pointer */ - long gsize, /* I - size of each group of bytes */ - long ngroups, /* I - number of groups to write */ - long offset, /* I - size of gap between groups */ - void *buffer, /* I - buffer to be written */ - int *status) /* IO - error status */ -/* - put (write) the buffer of bytes to the output FITS file, with an offset - between each group of bytes. This function combines ffmbyt and ffpbyt - for increased efficiency. -*/ -{ - int bcurrent; - long ii, bufpos, nspace, nwrite, record; - char *cptr, *ioptr; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - if ((fptr->Fptr)->curbuf < 0) /* no current data buffer for this file */ - { /* so reload the last one that was used */ - ffldrc(fptr, (long) (((fptr->Fptr)->bytepos) / IOBUFLEN), REPORT_EOF, status); - } - - cptr = (char *)buffer; - bcurrent = (fptr->Fptr)->curbuf; /* number of the current IO buffer */ - record = (fptr->Fptr)->bufrecnum[bcurrent]; /* zero-indexed record number */ - bufpos = (long) ((fptr->Fptr)->bytepos - ((LONGLONG)record * IOBUFLEN)); /* start pos */ - nspace = IOBUFLEN - bufpos; /* amount of space left in buffer */ - ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN) + bufpos; - - for (ii = 1; ii < ngroups; ii++) /* write all but the last group */ - { - /* copy bytes from user's buffer to the IO buffer */ - nwrite = minvalue(gsize, nspace); - memcpy(ioptr, cptr, nwrite); - cptr += nwrite; /* increment buffer pointer */ - - if (nwrite < gsize) /* entire group did not fit */ - { - (fptr->Fptr)->dirty[bcurrent] = TRUE; /* mark record as having been modified */ - record++; - ffldrc(fptr, record, IGNORE_EOF, status); /* load next record */ - bcurrent = (fptr->Fptr)->curbuf; - ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN); - - nwrite = gsize - nwrite; - memcpy(ioptr, cptr, nwrite); - cptr += nwrite; /* increment buffer pointer */ - ioptr += (offset + nwrite); /* increment IO buffer pointer */ - nspace = IOBUFLEN - offset - nwrite; /* amount of space left */ - } - else - { - ioptr += (offset + nwrite); /* increment IO bufer pointer */ - nspace -= (offset + nwrite); - } - - if (nspace <= 0) /* beyond current record? */ - { - (fptr->Fptr)->dirty[bcurrent] = TRUE; - record += ((IOBUFLEN - nspace) / IOBUFLEN); /* new record number */ - ffldrc(fptr, record, IGNORE_EOF, status); - bcurrent = (fptr->Fptr)->curbuf; - - bufpos = (-nspace) % IOBUFLEN; /* starting buffer pos */ - nspace = IOBUFLEN - bufpos; - ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN) + bufpos; - } - } - - /* now write the last group */ - nwrite = minvalue(gsize, nspace); - memcpy(ioptr, cptr, nwrite); - cptr += nwrite; /* increment buffer pointer */ - - if (nwrite < gsize) /* entire group did not fit */ - { - (fptr->Fptr)->dirty[bcurrent] = TRUE; /* mark record as having been modified */ - record++; - ffldrc(fptr, record, IGNORE_EOF, status); /* load next record */ - bcurrent = (fptr->Fptr)->curbuf; - ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN); - - nwrite = gsize - nwrite; - memcpy(ioptr, cptr, nwrite); - } - - (fptr->Fptr)->dirty[bcurrent] = TRUE; /* mark record as having been modified */ - (fptr->Fptr)->bytepos = (fptr->Fptr)->bytepos + (ngroups * gsize) - + (ngroups - 1) * offset; - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgbyt(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG nbytes, /* I - number of bytes to read */ - void *buffer, /* O - buffer to read into */ - int *status) /* IO - error status */ -/* - get (read) the requested number of bytes from the file, starting at - the current file position. Read large blocks of data directly from disk; - read smaller segments via intermediate IO buffers to improve efficiency. -*/ -{ - int ii; - LONGLONG filepos; - long recstart, recend, ntodo, bufpos, nspace, nread; - char *cptr; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - cptr = (char *)buffer; - - if (nbytes >= MINDIRECT) - { - /* read large blocks of data directly from disk instead of via buffers */ - filepos = (fptr->Fptr)->bytepos; /* save the read starting position */ - -/* note that in this case, ffmbyt has not been called, and so */ -/* bufrecnum[(fptr->Fptr)->curbuf] does not point to the intended */ -/* output buffer */ - - recstart = (long) (filepos / IOBUFLEN); /* starting record */ - recend = (long) ((filepos + nbytes - 1) / IOBUFLEN); /* ending record */ - - for (ii = 0; ii < NIOBUF; ii++) /* flush any affected buffers to disk */ - { - if ((fptr->Fptr)->dirty[ii] && - (fptr->Fptr)->bufrecnum[ii] >= recstart && (fptr->Fptr)->bufrecnum[ii] <= recend) - { - ffbfwt(fptr->Fptr, ii, status); /* flush modified buffer to disk */ - } - } - - /* move to the correct read position */ - if ((fptr->Fptr)->io_pos != filepos) - ffseek(fptr->Fptr, filepos); - - ffread(fptr->Fptr, (long) nbytes, cptr, status); /* read the data */ - (fptr->Fptr)->io_pos = filepos + nbytes; /* update the file position */ - } - else - { - /* read small chucks of data using the IO buffers for efficiency */ - - if ((fptr->Fptr)->curbuf < 0) /* no current data buffer for this file */ - { /* so reload the last one that was used */ - ffldrc(fptr, (long) (((fptr->Fptr)->bytepos) / IOBUFLEN), REPORT_EOF, status); - } - - /* bufpos is the starting position in IO buffer */ - bufpos = (long) ((fptr->Fptr)->bytepos - ((LONGLONG)(fptr->Fptr)->bufrecnum[(fptr->Fptr)->curbuf] * - IOBUFLEN)); - nspace = IOBUFLEN - bufpos; /* amount of space left in the buffer */ - - ntodo = (long) nbytes; - while (ntodo) - { - nread = minvalue(ntodo, nspace); - - /* copy bytes from IO buffer to user's buffer */ - memcpy(cptr, (fptr->Fptr)->iobuffer + ((fptr->Fptr)->curbuf * IOBUFLEN) + bufpos, nread); - ntodo -= nread; /* decrement remaining number of bytes */ - cptr += nread; - (fptr->Fptr)->bytepos += nread; /* increment file position pointer */ - - if (ntodo) /* load next record into a buffer */ - { - ffldrc(fptr, (long) ((fptr->Fptr)->bytepos / IOBUFLEN), REPORT_EOF, status); - bufpos = 0; - nspace = IOBUFLEN; - } - } - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgbytoff(fitsfile *fptr, /* I - FITS file pointer */ - long gsize, /* I - size of each group of bytes */ - long ngroups, /* I - number of groups to read */ - long offset, /* I - size of gap between groups (may be < 0) */ - void *buffer, /* I - buffer to be filled */ - int *status) /* IO - error status */ -/* - get (read) the requested number of bytes from the file, starting at - the current file position. This function combines ffmbyt and ffgbyt - for increased efficiency. -*/ -{ - int bcurrent; - long ii, bufpos, nspace, nread, record; - char *cptr, *ioptr; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - if ((fptr->Fptr)->curbuf < 0) /* no current data buffer for this file */ - { /* so reload the last one that was used */ - ffldrc(fptr, (long) (((fptr->Fptr)->bytepos) / IOBUFLEN), REPORT_EOF, status); - } - - cptr = (char *)buffer; - bcurrent = (fptr->Fptr)->curbuf; /* number of the current IO buffer */ - record = (fptr->Fptr)->bufrecnum[bcurrent]; /* zero-indexed record number */ - bufpos = (long) ((fptr->Fptr)->bytepos - ((LONGLONG)record * IOBUFLEN)); /* start pos */ - nspace = IOBUFLEN - bufpos; /* amount of space left in buffer */ - ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN) + bufpos; - - for (ii = 1; ii < ngroups; ii++) /* read all but the last group */ - { - /* copy bytes from IO buffer to the user's buffer */ - nread = minvalue(gsize, nspace); - memcpy(cptr, ioptr, nread); - cptr += nread; /* increment buffer pointer */ - - if (nread < gsize) /* entire group did not fit */ - { - record++; - ffldrc(fptr, record, REPORT_EOF, status); /* load next record */ - bcurrent = (fptr->Fptr)->curbuf; - ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN); - - nread = gsize - nread; - memcpy(cptr, ioptr, nread); - cptr += nread; /* increment buffer pointer */ - ioptr += (offset + nread); /* increment IO buffer pointer */ - nspace = IOBUFLEN - offset - nread; /* amount of space left */ - } - else - { - ioptr += (offset + nread); /* increment IO bufer pointer */ - nspace -= (offset + nread); - } - - if (nspace <= 0 || nspace > IOBUFLEN) /* beyond current record? */ - { - if (nspace <= 0) - { - record += ((IOBUFLEN - nspace) / IOBUFLEN); /* new record number */ - bufpos = (-nspace) % IOBUFLEN; /* starting buffer pos */ - } - else - { - record -= ((nspace - 1 ) / IOBUFLEN); /* new record number */ - bufpos = IOBUFLEN - (nspace % IOBUFLEN); /* starting buffer pos */ - } - - ffldrc(fptr, record, REPORT_EOF, status); - bcurrent = (fptr->Fptr)->curbuf; - - nspace = IOBUFLEN - bufpos; - ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN) + bufpos; - } - } - - /* now read the last group */ - nread = minvalue(gsize, nspace); - memcpy(cptr, ioptr, nread); - cptr += nread; /* increment buffer pointer */ - - if (nread < gsize) /* entire group did not fit */ - { - record++; - ffldrc(fptr, record, REPORT_EOF, status); /* load next record */ - bcurrent = (fptr->Fptr)->curbuf; - ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN); - - nread = gsize - nread; - memcpy(cptr, ioptr, nread); - } - - (fptr->Fptr)->bytepos = (fptr->Fptr)->bytepos + (ngroups * gsize) - + (ngroups - 1) * offset; - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffldrc(fitsfile *fptr, /* I - FITS file pointer */ - long record, /* I - record number to be loaded */ - int err_mode, /* I - 1=ignore EOF, 0 = return EOF error */ - int *status) /* IO - error status */ -{ -/* - low-level routine to load a specified record from a file into - a physical buffer, if it is not already loaded. Reset all - pointers to make this the new current record for that file. - Update ages of all the physical buffers. -*/ - int ibuff, nbuff; - LONGLONG rstart; - - /* check if record is already loaded in one of the buffers */ - /* search from youngest to oldest buffer for efficiency */ - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - for (ibuff = NIOBUF - 1; ibuff >= 0; ibuff--) - { - nbuff = (fptr->Fptr)->ageindex[ibuff]; - if (record == (fptr->Fptr)->bufrecnum[nbuff]) { - goto updatebuf; /* use 'goto' for efficiency */ - } - } - - /* record is not already loaded */ - rstart = (LONGLONG)record * IOBUFLEN; - - if ( !err_mode && (rstart >= (fptr->Fptr)->logfilesize) ) /* EOF? */ - return(*status = END_OF_FILE); - - if (ffwhbf(fptr, &nbuff) < 0) /* which buffer should we reuse? */ - return(*status = TOO_MANY_FILES); - - if ((fptr->Fptr)->dirty[nbuff]) - ffbfwt(fptr->Fptr, nbuff, status); /* write dirty buffer to disk */ - - if (rstart >= (fptr->Fptr)->filesize) /* EOF? */ - { - /* initialize an empty buffer with the correct fill value */ - if ((fptr->Fptr)->hdutype == ASCII_TBL) - memset((fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), 32, IOBUFLEN); /* blank fill */ - else - memset((fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), 0, IOBUFLEN); /* zero fill */ - - (fptr->Fptr)->logfilesize = maxvalue((fptr->Fptr)->logfilesize, - rstart + IOBUFLEN); - - (fptr->Fptr)->dirty[nbuff] = TRUE; /* mark record as having been modified */ - } - else /* not EOF, so read record from disk */ - { - if ((fptr->Fptr)->io_pos != rstart) - ffseek(fptr->Fptr, rstart); - - ffread(fptr->Fptr, IOBUFLEN, (fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), status); - (fptr->Fptr)->io_pos = rstart + IOBUFLEN; /* set new IO position */ - } - - (fptr->Fptr)->bufrecnum[nbuff] = record; /* record number contained in buffer */ - -updatebuf: - - (fptr->Fptr)->curbuf = nbuff; /* this is the current buffer for this file */ - - if (ibuff < 0) - { - /* find the current position of the buffer in the age index */ - for (ibuff = 0; ibuff < NIOBUF; ibuff++) - if ((fptr->Fptr)->ageindex[ibuff] == nbuff) - break; - } - - /* increment the age of all the buffers that were younger than it */ - for (ibuff++; ibuff < NIOBUF; ibuff++) - (fptr->Fptr)->ageindex[ibuff - 1] = (fptr->Fptr)->ageindex[ibuff]; - - (fptr->Fptr)->ageindex[NIOBUF - 1] = nbuff; /* this is now the youngest buffer */ - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffwhbf(fitsfile *fptr, /* I - FITS file pointer */ - int *nbuff) /* O - which buffer to use */ -{ -/* - decide which buffer to (re)use to hold a new file record -*/ - return(*nbuff = (fptr->Fptr)->ageindex[0]); /* return oldest buffer */ -} -/*--------------------------------------------------------------------------*/ -int ffflus(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -/* - Flush all the data in the current FITS file to disk. This ensures that if - the program subsequently dies, the disk FITS file will be closed correctly. -*/ -{ - int hdunum, hdutype; - - if (*status > 0) - return(*status); - - ffghdn(fptr, &hdunum); /* get the current HDU number */ - - if (ffchdu(fptr,status) > 0) /* close out the current HDU */ - ffpmsg("ffflus could not close the current HDU."); - - ffflsh(fptr, FALSE, status); /* flush any modified IO buffers to disk */ - - if (ffgext(fptr, hdunum - 1, &hdutype, status) > 0) /* reopen HDU */ - ffpmsg("ffflus could not reopen the current HDU."); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffflsh(fitsfile *fptr, /* I - FITS file pointer */ - int clearbuf, /* I - also clear buffer contents? */ - int *status) /* IO - error status */ -{ -/* - flush all dirty IO buffers associated with the file to disk -*/ - int ii; - -/* - no need to move to a different HDU - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); -*/ - for (ii = 0; ii < NIOBUF; ii++) - { - /* flush modified buffer to disk */ - if ((fptr->Fptr)->bufrecnum[ii] >= 0 &&(fptr->Fptr)->dirty[ii]) - ffbfwt(fptr->Fptr, ii, status); - - if (clearbuf) - (fptr->Fptr)->bufrecnum[ii] = -1; /* set contents of buffer as undefined */ - } - - if (*status != READONLY_FILE) - ffflushx(fptr->Fptr); /* flush system buffers to disk */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffbfeof(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -{ -/* - clear any buffers beyond the end of file -*/ - int ii; - - for (ii = 0; ii < NIOBUF; ii++) - { - if ( (LONGLONG) (fptr->Fptr)->bufrecnum[ii] * IOBUFLEN >= fptr->Fptr->filesize) - { - (fptr->Fptr)->bufrecnum[ii] = -1; /* set contents of buffer as undefined */ - } - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffbfwt(FITSfile *Fptr, /* I - FITS file pointer */ - int nbuff, /* I - which buffer to write */ - int *status) /* IO - error status */ -{ -/* - write contents of buffer to file; If the position of the buffer - is beyond the current EOF, then the file may need to be extended - with fill values, and/or with the contents of some of the other - i/o buffers. -*/ - int ii,ibuff; - long jj, irec, minrec, nloop; - LONGLONG filepos; - - static char zeros[IOBUFLEN]; /* initialized to zero by default */ - - if (!(Fptr->writemode) ) - { - ffpmsg("Error: trying to write to READONLY file."); - if (Fptr->driver == 8) { /* gzip compressed file */ - ffpmsg("Cannot write to a GZIP or COMPRESS compressed file."); - } - Fptr->dirty[nbuff] = FALSE; /* reset buffer status to prevent later probs */ - *status = READONLY_FILE; - return(*status); - } - - filepos = (LONGLONG)Fptr->bufrecnum[nbuff] * IOBUFLEN; - - if (filepos <= Fptr->filesize) - { - /* record is located within current file, so just write it */ - - /* move to the correct write position */ - if (Fptr->io_pos != filepos) - ffseek(Fptr, filepos); - - ffwrite(Fptr, IOBUFLEN, Fptr->iobuffer + (nbuff * IOBUFLEN), status); - Fptr->io_pos = filepos + IOBUFLEN; - - if (filepos == Fptr->filesize) /* appended new record? */ - Fptr->filesize += IOBUFLEN; /* increment the file size */ - - Fptr->dirty[nbuff] = FALSE; - } - - else /* if record is beyond the EOF, append any other records */ - /* and/or insert fill values if necessary */ - { - /* move to EOF */ - if (Fptr->io_pos != Fptr->filesize) - ffseek(Fptr, Fptr->filesize); - - ibuff = NIOBUF; /* initialize to impossible value */ - while(ibuff != nbuff) /* repeat until requested buffer is written */ - { - minrec = (long) (Fptr->filesize / IOBUFLEN); - - /* write lowest record beyond the EOF first */ - - irec = Fptr->bufrecnum[nbuff]; /* initially point to the requested buffer */ - ibuff = nbuff; - - for (ii = 0; ii < NIOBUF; ii++) - { - if (Fptr->bufrecnum[ii] >= minrec && - Fptr->bufrecnum[ii] < irec) - { - irec = Fptr->bufrecnum[ii]; /* found a lower record */ - ibuff = ii; - } - } - - filepos = (LONGLONG)irec * IOBUFLEN; /* byte offset of record in file */ - - /* append 1 or more fill records if necessary */ - if (filepos > Fptr->filesize) - { - nloop = (long) ((filepos - (Fptr->filesize)) / IOBUFLEN); - for (jj = 0; jj < nloop && !(*status); jj++) - ffwrite(Fptr, IOBUFLEN, zeros, status); - -/* -ffseek(Fptr, filepos); -*/ - Fptr->filesize = filepos; /* increment the file size */ - } - - /* write the buffer itself */ - ffwrite(Fptr, IOBUFLEN, Fptr->iobuffer + (ibuff * IOBUFLEN), status); - Fptr->dirty[ibuff] = FALSE; - - Fptr->filesize += IOBUFLEN; /* increment the file size */ - } /* loop back if more buffers need to be written */ - - Fptr->io_pos = Fptr->filesize; /* currently positioned at EOF */ - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgrsz( fitsfile *fptr, /* I - FITS file pionter */ - long *ndata, /* O - optimal amount of data to access */ - int *status) /* IO - error status */ -/* - Returns an optimal value for the number of rows in a binary table - or the number of pixels in an image that should be read or written - at one time for maximum efficiency. Accessing more data than this - may cause excessive flushing and rereading of buffers to/from disk. -*/ -{ - int typecode, bytesperpixel; - - /* There are NIOBUF internal buffers available each IOBUFLEN bytes long. */ - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header to get hdu struct */ - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU ) /* calc pixels per buffer size */ - { - /* image pixels are in column 2 of the 'table' */ - ffgtcl(fptr, 2, &typecode, NULL, NULL, status); - bytesperpixel = typecode / 10; - *ndata = ((NIOBUF - 1) * IOBUFLEN) / bytesperpixel; - } - else /* calc number of rows that fit in buffers */ - { - *ndata = (long) (((NIOBUF - 1) * IOBUFLEN) / maxvalue(1, - (fptr->Fptr)->rowlength)); - *ndata = maxvalue(1, *ndata); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgtbb(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG firstrow, /* I - starting row (1 = first row) */ - LONGLONG firstchar, /* I - starting byte in row (1=first) */ - LONGLONG nchars, /* I - number of bytes to read */ - unsigned char *values, /* I - array of bytes to read */ - int *status) /* IO - error status */ -/* - read a consecutive string of bytes from an ascii or binary table. - This will span multiple rows of the table if nchars + firstchar is - greater than the length of a row. -*/ -{ - LONGLONG bytepos, endrow; - - if (*status > 0 || nchars <= 0) - return(*status); - - else if (firstrow < 1) - return(*status=BAD_ROW_NUM); - - else if (firstchar < 1) - return(*status=BAD_ELEM_NUM); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - /* check that we do not exceed number of rows in the table */ - endrow = ((firstchar + nchars - 2) / (fptr->Fptr)->rowlength) + firstrow; - if (endrow > (fptr->Fptr)->numrows) - { - ffpmsg("attempt to read past end of table (ffgtbb)"); - return(*status=BAD_ROW_NUM); - } - - /* move the i/o pointer to the start of the sequence of characters */ - bytepos = (fptr->Fptr)->datastart + - ((fptr->Fptr)->rowlength * (firstrow - 1)) + - firstchar - 1; - - ffmbyt(fptr, bytepos, REPORT_EOF, status); - ffgbyt(fptr, nchars, values, status); /* read the bytes */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgi1b(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG byteloc, /* I - position within file to start reading */ - long nvals, /* I - number of pixels to read */ - long incre, /* I - byte increment between pixels */ - unsigned char *values, /* O - returned array of values */ - int *status) /* IO - error status */ -/* - get (read) the array of values from the FITS file, doing machine dependent - format conversion (e.g. byte-swapping) if necessary. -*/ -{ - LONGLONG postemp; - - if (incre == 1) /* read all the values at once (contiguous bytes) */ - { - if (nvals < MINDIRECT) /* read normally via IO buffers */ - { - ffmbyt(fptr, byteloc, REPORT_EOF, status); - ffgbyt(fptr, nvals, values, status); - } - else /* read directly from disk, bypassing IO buffers */ - { - postemp = (fptr->Fptr)->bytepos; /* store current file position */ - (fptr->Fptr)->bytepos = byteloc; /* set to the desired position */ - ffgbyt(fptr, nvals, values, status); - (fptr->Fptr)->bytepos = postemp; /* reset to original position */ - } - } - else /* have to read each value individually (not contiguous ) */ - { - ffmbyt(fptr, byteloc, REPORT_EOF, status); - ffgbytoff(fptr, 1, nvals, incre - 1, values, status); - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgi2b(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG byteloc, /* I - position within file to start reading */ - long nvals, /* I - number of pixels to read */ - long incre, /* I - byte increment between pixels */ - short *values, /* O - returned array of values */ - int *status) /* IO - error status */ -/* - get (read) the array of values from the FITS file, doing machine dependent - format conversion (e.g. byte-swapping) if necessary. -*/ -{ - LONGLONG postemp; - - if (incre == 2) /* read all the values at once (contiguous bytes) */ - { - if (nvals * 2 < MINDIRECT) /* read normally via IO buffers */ - { - ffmbyt(fptr, byteloc, REPORT_EOF, status); - ffgbyt(fptr, nvals * 2, values, status); - } - else /* read directly from disk, bypassing IO buffers */ - { - postemp = (fptr->Fptr)->bytepos; /* store current file position */ - (fptr->Fptr)->bytepos = byteloc; /* set to the desired position */ - ffgbyt(fptr, nvals * 2, values, status); - (fptr->Fptr)->bytepos = postemp; /* reset to original position */ - } - } - else /* have to read each value individually (not contiguous ) */ - { - ffmbyt(fptr, byteloc, REPORT_EOF, status); - ffgbytoff(fptr, 2, nvals, incre - 2, values, status); - } - -#if BYTESWAPPED - ffswap2(values, nvals); /* reverse order of bytes in each value */ -#endif - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgi4b(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG byteloc, /* I - position within file to start reading */ - long nvals, /* I - number of pixels to read */ - long incre, /* I - byte increment between pixels */ - INT32BIT *values, /* O - returned array of values */ - int *status) /* IO - error status */ -/* - get (read) the array of values from the FITS file, doing machine dependent - format conversion (e.g. byte-swapping) if necessary. -*/ -{ - LONGLONG postemp; - - if (incre == 4) /* read all the values at once (contiguous bytes) */ - { - if (nvals * 4 < MINDIRECT) /* read normally via IO buffers */ - { - ffmbyt(fptr, byteloc, REPORT_EOF, status); - ffgbyt(fptr, nvals * 4, values, status); - } - else /* read directly from disk, bypassing IO buffers */ - { - postemp = (fptr->Fptr)->bytepos; /* store current file position */ - (fptr->Fptr)->bytepos = byteloc; /* set to the desired position */ - ffgbyt(fptr, nvals * 4, values, status); - (fptr->Fptr)->bytepos = postemp; /* reset to original position */ - } - } - else /* have to read each value individually (not contiguous ) */ - { - ffmbyt(fptr, byteloc, REPORT_EOF, status); - ffgbytoff(fptr, 4, nvals, incre - 4, values, status); - } - -#if BYTESWAPPED - ffswap4(values, nvals); /* reverse order of bytes in each value */ -#endif - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgi8b(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG byteloc, /* I - position within file to start reading */ - long nvals, /* I - number of pixels to read */ - long incre, /* I - byte increment between pixels */ - long *values, /* O - returned array of values */ - int *status) /* IO - error status */ -/* - get (read) the array of values from the FITS file, doing machine dependent - format conversion (e.g. byte-swapping) if necessary. - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - This routine reads 'nvals' 8-byte integers into 'values'. - This works both on platforms that have sizeof(long) = 64, and 32, - as long as 'values' has been allocated to large enough to hold - 8 * nvals bytes of data. - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -*/ -{ - LONGLONG postemp; - - if (incre == 8) /* read all the values at once (contiguous bytes) */ - { - if (nvals * 8 < MINDIRECT) /* read normally via IO buffers */ - { - ffmbyt(fptr, byteloc, REPORT_EOF, status); - ffgbyt(fptr, nvals * 8, values, status); - } - else /* read directly from disk, bypassing IO buffers */ - { - postemp = (fptr->Fptr)->bytepos; /* store current file position */ - (fptr->Fptr)->bytepos = byteloc; /* set to the desired position */ - ffgbyt(fptr, nvals * 8, values, status); - (fptr->Fptr)->bytepos = postemp; /* reset to original position */ - } - } - else /* have to read each value individually (not contiguous ) */ - { - ffmbyt(fptr, byteloc, REPORT_EOF, status); - ffgbytoff(fptr, 8, nvals, incre - 8, values, status); - } - -#if BYTESWAPPED - ffswap8((double *) values, nvals); /* reverse bytes in each value */ -#endif - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgr4b(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG byteloc, /* I - position within file to start reading */ - long nvals, /* I - number of pixels to read */ - long incre, /* I - byte increment between pixels */ - float *values, /* O - returned array of values */ - int *status) /* IO - error status */ -/* - get (read) the array of values from the FITS file, doing machine dependent - format conversion (e.g. byte-swapping) if necessary. -*/ -{ - LONGLONG postemp; - -#if MACHINE == VAXVMS - long ii; - -#elif (MACHINE == ALPHAVMS) && (FLOATTYPE == GFLOAT) - short *sptr; - long ii; - -#endif - - - if (incre == 4) /* read all the values at once (contiguous bytes) */ - { - if (nvals * 4 < MINDIRECT) /* read normally via IO buffers */ - { - ffmbyt(fptr, byteloc, REPORT_EOF, status); - ffgbyt(fptr, nvals * 4, values, status); - } - else /* read directly from disk, bypassing IO buffers */ - { - postemp = (fptr->Fptr)->bytepos; /* store current file position */ - (fptr->Fptr)->bytepos = byteloc; /* set to the desired position */ - ffgbyt(fptr, nvals * 4, values, status); - (fptr->Fptr)->bytepos = postemp; /* reset to original position */ - } - } - else /* have to read each value individually (not contiguous ) */ - { - ffmbyt(fptr, byteloc, REPORT_EOF, status); - ffgbytoff(fptr, 4, nvals, incre - 4, values, status); - } - - -#if MACHINE == VAXVMS - - ii = nvals; /* call VAX macro routine to convert */ - ieevur(values, values, &ii); /* from IEEE float -> F float */ - -#elif (MACHINE == ALPHAVMS) && (FLOATTYPE == GFLOAT) - - ffswap2( (short *) values, nvals * 2); /* swap pairs of bytes */ - - /* convert from IEEE float format to VMS GFLOAT float format */ - sptr = (short *) values; - for (ii = 0; ii < nvals; ii++, sptr += 2) - { - if (!fnan(*sptr) ) /* test for NaN or underflow */ - values[ii] *= 4.0; - } - -#elif BYTESWAPPED - ffswap4((INT32BIT *)values, nvals); /* reverse order of bytes in values */ -#endif - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgr8b(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG byteloc, /* I - position within file to start reading */ - long nvals, /* I - number of pixels to read */ - long incre, /* I - byte increment between pixels */ - double *values, /* O - returned array of values */ - int *status) /* IO - error status */ -/* - get (read) the array of values from the FITS file, doing machine dependent - format conversion (e.g. byte-swapping) if necessary. -*/ -{ - LONGLONG postemp; - -#if MACHINE == VAXVMS - long ii; - -#elif (MACHINE == ALPHAVMS) && (FLOATTYPE == GFLOAT) - short *sptr; - long ii; - -#endif - - if (incre == 8) /* read all the values at once (contiguous bytes) */ - { - if (nvals * 8 < MINDIRECT) /* read normally via IO buffers */ - { - ffmbyt(fptr, byteloc, REPORT_EOF, status); - ffgbyt(fptr, nvals * 8, values, status); - } - else /* read directly from disk, bypassing IO buffers */ - { - postemp = (fptr->Fptr)->bytepos; /* store current file position */ - (fptr->Fptr)->bytepos = byteloc; /* set to the desired position */ - ffgbyt(fptr, nvals * 8, values, status); - (fptr->Fptr)->bytepos = postemp; /* reset to original position */ - } - } - else /* have to read each value individually (not contiguous ) */ - { - ffmbyt(fptr, byteloc, REPORT_EOF, status); - ffgbytoff(fptr, 8, nvals, incre - 8, values, status); - } - -#if MACHINE == VAXVMS - ii = nvals; /* call VAX macro routine to convert */ - ieevud(values, values, &ii); /* from IEEE float -> D float */ - -#elif (MACHINE == ALPHAVMS) && (FLOATTYPE == GFLOAT) - ffswap2( (short *) values, nvals * 4); /* swap pairs of bytes */ - - /* convert from IEEE float format to VMS GFLOAT float format */ - sptr = (short *) values; - for (ii = 0; ii < nvals; ii++, sptr += 4) - { - if (!dnan(*sptr) ) /* test for NaN or underflow */ - values[ii] *= 4.0; - } - -#elif BYTESWAPPED - ffswap8(values, nvals); /* reverse order of bytes in each value */ -#endif - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffptbb(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG firstrow, /* I - starting row (1 = first row) */ - LONGLONG firstchar, /* I - starting byte in row (1=first) */ - LONGLONG nchars, /* I - number of bytes to write */ - unsigned char *values, /* I - array of bytes to write */ - int *status) /* IO - error status */ -/* - write a consecutive string of bytes to an ascii or binary table. - This will span multiple rows of the table if nchars + firstchar is - greater than the length of a row. -*/ -{ - LONGLONG bytepos, endrow, nrows; - char message[81]; - - if (*status > 0 || nchars <= 0) - return(*status); - - else if (firstrow < 1) - return(*status=BAD_ROW_NUM); - - else if (firstchar < 1) - return(*status=BAD_ELEM_NUM); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart < 0) /* rescan header if data undefined */ - ffrdef(fptr, status); - - endrow = ((firstchar + nchars - 2) / (fptr->Fptr)->rowlength) + firstrow; - - /* check if we are writing beyond the current end of table */ - if (endrow > (fptr->Fptr)->numrows) - { - /* if there are more HDUs following the current one, or */ - /* if there is a data heap, then we must insert space */ - /* for the new rows. */ - if ( !((fptr->Fptr)->lasthdu) || (fptr->Fptr)->heapsize > 0) - { - nrows = endrow - ((fptr->Fptr)->numrows); - - /* ffirow also updates the heap address and numrows */ - if (ffirow(fptr, (fptr->Fptr)->numrows, nrows, status) > 0) - { - sprintf(message, - "ffptbb failed to add space for %.0f new rows in table.", - (double) nrows); - ffpmsg(message); - return(*status); - } - } - else - { - /* manally update heap starting address */ - (fptr->Fptr)->heapstart += - ((LONGLONG)(endrow - (fptr->Fptr)->numrows) * - (fptr->Fptr)->rowlength ); - - (fptr->Fptr)->numrows = endrow; /* update number of rows */ - } - } - - /* move the i/o pointer to the start of the sequence of characters */ - bytepos = (fptr->Fptr)->datastart + - ((fptr->Fptr)->rowlength * (firstrow - 1)) + - firstchar - 1; - - ffmbyt(fptr, bytepos, IGNORE_EOF, status); - ffpbyt(fptr, nchars, values, status); /* write the bytes */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffpi1b(fitsfile *fptr, /* I - FITS file pointer */ - long nvals, /* I - number of pixels in the values array */ - long incre, /* I - byte increment between pixels */ - unsigned char *values, /* I - array of values to write */ - int *status) /* IO - error status */ -/* - put (write) the array of values to the FITS file, doing machine dependent - format conversion (e.g. byte-swapping) if necessary. -*/ -{ - if (incre == 1) /* write all the values at once (contiguous bytes) */ - - ffpbyt(fptr, nvals, values, status); - - else /* have to write each value individually (not contiguous ) */ - - ffpbytoff(fptr, 1, nvals, incre - 1, values, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffpi2b(fitsfile *fptr, /* I - FITS file pointer */ - long nvals, /* I - number of pixels in the values array */ - long incre, /* I - byte increment between pixels */ - short *values, /* I - array of values to write */ - int *status) /* IO - error status */ -/* - put (write) the array of values to the FITS file, doing machine dependent - format conversion (e.g. byte-swapping) if necessary. -*/ -{ -#if BYTESWAPPED - ffswap2(values, nvals); /* reverse order of bytes in each value */ -#endif - - if (incre == 2) /* write all the values at once (contiguous bytes) */ - - ffpbyt(fptr, nvals * 2, values, status); - - else /* have to write each value individually (not contiguous ) */ - - ffpbytoff(fptr, 2, nvals, incre - 2, values, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffpi4b(fitsfile *fptr, /* I - FITS file pointer */ - long nvals, /* I - number of pixels in the values array */ - long incre, /* I - byte increment between pixels */ - INT32BIT *values, /* I - array of values to write */ - int *status) /* IO - error status */ -/* - put (write) the array of values to the FITS file, doing machine dependent - format conversion (e.g. byte-swapping) if necessary. -*/ -{ -#if BYTESWAPPED - ffswap4(values, nvals); /* reverse order of bytes in each value */ -#endif - - if (incre == 4) /* write all the values at once (contiguous bytes) */ - - ffpbyt(fptr, nvals * 4, values, status); - - else /* have to write each value individually (not contiguous ) */ - - ffpbytoff(fptr, 4, nvals, incre - 4, values, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffpi8b(fitsfile *fptr, /* I - FITS file pointer */ - long nvals, /* I - number of pixels in the values array */ - long incre, /* I - byte increment between pixels */ - long *values, /* I - array of values to write */ - int *status) /* IO - error status */ -/* - put (write) the array of values to the FITS file, doing machine dependent - format conversion (e.g. byte-swapping) if necessary. - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - This routine writes 'nvals' 8-byte integers from 'values'. - This works both on platforms that have sizeof(long) = 64, and 32, - as long as 'values' has been allocated to large enough to hold - 8 * nvals bytes of data. - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -*/ -{ -#if BYTESWAPPED - ffswap8((double *) values, nvals); /* reverse bytes in each value */ -#endif - - if (incre == 8) /* write all the values at once (contiguous bytes) */ - - ffpbyt(fptr, nvals * 8, values, status); - - else /* have to write each value individually (not contiguous ) */ - - ffpbytoff(fptr, 8, nvals, incre - 8, values, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffpr4b(fitsfile *fptr, /* I - FITS file pointer */ - long nvals, /* I - number of pixels in the values array */ - long incre, /* I - byte increment between pixels */ - float *values, /* I - array of values to write */ - int *status) /* IO - error status */ -/* - put (write) the array of values to the FITS file, doing machine dependent - format conversion (e.g. byte-swapping) if necessary. -*/ -{ -#if MACHINE == VAXVMS - long ii; - - ii = nvals; /* call VAX macro routine to convert */ - ieevpr(values, values, &ii); /* from F float -> IEEE float */ - -#elif (MACHINE == ALPHAVMS) && (FLOATTYPE == GFLOAT) - long ii; - - /* convert from VMS FFLOAT float format to IEEE float format */ - for (ii = 0; ii < nvals; ii++) - values[ii] *= 0.25; - - ffswap2( (short *) values, nvals * 2); /* swap pairs of bytes */ - -#elif BYTESWAPPED - ffswap4((INT32BIT *) values, nvals); /* reverse order of bytes in values */ -#endif - - if (incre == 4) /* write all the values at once (contiguous bytes) */ - - ffpbyt(fptr, nvals * 4, values, status); - - else /* have to write each value individually (not contiguous ) */ - - ffpbytoff(fptr, 4, nvals, incre - 4, values, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffpr8b(fitsfile *fptr, /* I - FITS file pointer */ - long nvals, /* I - number of pixels in the values array */ - long incre, /* I - byte increment between pixels */ - double *values, /* I - array of values to write */ - int *status) /* IO - error status */ -/* - put (write) the array of values to the FITS file, doing machine dependent - format conversion (e.g. byte-swapping) if necessary. -*/ -{ -#if MACHINE == VAXVMS - long ii; - - ii = nvals; /* call VAX macro routine to convert */ - ieevpd(values, values, &ii); /* from D float -> IEEE float */ - -#elif (MACHINE == ALPHAVMS) && (FLOATTYPE == GFLOAT) - long ii; - - /* convert from VMS GFLOAT float format to IEEE float format */ - for (ii = 0; ii < nvals; ii++) - values[ii] *= 0.25; - - ffswap2( (short *) values, nvals * 4); /* swap pairs of bytes */ - -#elif BYTESWAPPED - ffswap8(values, nvals); /* reverse order of bytes in each value */ -#endif - - if (incre == 8) /* write all the values at once (contiguous bytes) */ - - ffpbyt(fptr, nvals * 8, values, status); - - else /* have to write each value individually (not contiguous ) */ - - ffpbytoff(fptr, 8, nvals, incre - 8, values, status); - - return(*status); -} - diff --git a/src/external/OpenGR/3rdparty/cfitsio/cfileio.c b/src/external/OpenGR/3rdparty/cfitsio/cfileio.c deleted file mode 100644 index 09bf8691e..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/cfileio.c +++ /dev/null @@ -1,7334 +0,0 @@ -/* This file, cfileio.c, contains the low-level file access routines. */ - -/* The FITSIO software was written by William Pence at the High Energy */ -/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ -/* Goddard Space Flight Center. */ - -#include -#include -#include -#include -#include -#include /* apparently needed to define size_t */ -#include "fitsio2.h" -#include "group.h" - -#define MAX_PREFIX_LEN 20 /* max length of file type prefix (e.g. 'http://') */ -#define MAX_DRIVERS 24 /* max number of file I/O drivers */ - -typedef struct /* structure containing pointers to I/O driver functions */ -{ char prefix[MAX_PREFIX_LEN]; - int (*init)(void); - int (*shutdown)(void); - int (*setoptions)(int option); - int (*getoptions)(int *options); - int (*getversion)(int *version); - int (*checkfile)(char *urltype, char *infile, char *outfile); - int (*open)(char *filename, int rwmode, int *driverhandle); - int (*create)(char *filename, int *drivehandle); - int (*truncate)(int drivehandle, LONGLONG size); - int (*close)(int drivehandle); - int (*remove)(char *filename); - int (*size)(int drivehandle, LONGLONG *size); - int (*flush)(int drivehandle); - int (*seek)(int drivehandle, LONGLONG offset); - int (*read)(int drivehandle, void *buffer, long nbytes); - int (*write)(int drivehandle, void *buffer, long nbytes); -} fitsdriver; - -fitsdriver driverTable[MAX_DRIVERS]; /* allocate driver tables */ - -FITSfile *FptrTable[NMAXFILES]; /* this table of Fptr pointers is */ - /* used by fits_already_open */ - -int need_to_initialize = 1; /* true if CFITSIO has not been initialized */ -int no_of_drivers = 0; /* number of currently defined I/O drivers */ - -static int pixel_filter_helper(fitsfile **fptr, char *outfile, - char *expr, int *status); -static int find_quote(char **string); -static int find_doublequote(char **string); -static int find_paren(char **string); -static int find_bracket(char **string); -static int find_curlybracket(char **string); -int comma2semicolon(char *string); - -#ifdef _REENTRANT - -pthread_mutex_t Fitsio_InitLock = PTHREAD_MUTEX_INITIALIZER; - -#endif - -/*--------------------------------------------------------------------------*/ -int fitsio_init_lock(void) -{ - int status = 0; - -#ifdef _REENTRANT - - static int need_to_init = 1; - - pthread_mutexattr_t mutex_init; - - FFLOCK1(Fitsio_InitLock); - - if (need_to_init) { - - /* Init the main fitsio lock here since we need a a recursive lock */ - - status = pthread_mutexattr_init(&mutex_init); - if (status) { - ffpmsg("pthread_mutexattr_init failed (fitsio_init_lock)"); - return(status); - } - -#ifdef __GLIBC__ - status = pthread_mutexattr_settype(&mutex_init, - PTHREAD_MUTEX_RECURSIVE_NP); -#else - status = pthread_mutexattr_settype(&mutex_init, - PTHREAD_MUTEX_RECURSIVE); -#endif - if (status) { - ffpmsg("pthread_mutexattr_settype failed (fitsio_init_lock)"); - return(status); - } - - status = pthread_mutex_init(&Fitsio_Lock,&mutex_init); - if (status) { - ffpmsg("pthread_mutex_init failed (fitsio_init_lock)"); - return(status); - } - - need_to_init = 0; - } - - FFUNLOCK1(Fitsio_InitLock); - -#endif - - return(status); -} -/*--------------------------------------------------------------------------*/ -int ffomem(fitsfile **fptr, /* O - FITS file pointer */ - const char *name, /* I - name of file to open */ - int mode, /* I - 0 = open readonly; 1 = read/write */ - void **buffptr, /* I - address of memory pointer */ - size_t *buffsize, /* I - size of buffer, in bytes */ - size_t deltasize, /* I - increment for future realloc's */ - void *(*mem_realloc)(void *p, size_t newsize), /* function */ - int *status) /* IO - error status */ -/* - Open an existing FITS file in core memory. This is a specialized version - of ffopen. -*/ -{ - int ii, driver, handle, hdutyp, slen, movetotype, extvers, extnum; - char extname[FLEN_VALUE]; - LONGLONG filesize; - char urltype[MAX_PREFIX_LEN], infile[FLEN_FILENAME], outfile[FLEN_FILENAME]; - char extspec[FLEN_FILENAME], rowfilter[FLEN_FILENAME]; - char binspec[FLEN_FILENAME], colspec[FLEN_FILENAME]; - char imagecolname[FLEN_VALUE], rowexpress[FLEN_FILENAME]; - char *url, errmsg[FLEN_ERRMSG]; - char *hdtype[3] = {"IMAGE", "TABLE", "BINTABLE"}; - - if (*status > 0) - return(*status); - - *fptr = 0; /* initialize null file pointer */ - - if (need_to_initialize) /* this is called only once */ - { - *status = fits_init_cfitsio(); - - if (*status > 0) - return(*status); - } - - url = (char *) name; - while (*url == ' ') /* ignore leading spaces in the file spec */ - url++; - - /* parse the input file specification */ - fits_parse_input_url(url, urltype, infile, outfile, extspec, - rowfilter, binspec, colspec, status); - - strcpy(urltype, "memkeep://"); /* URL type for pre-existing memory file */ - - *status = urltype2driver(urltype, &driver); - - if (*status > 0) - { - ffpmsg("could not find driver for pre-existing memory file: (ffomem)"); - return(*status); - } - - /* call driver routine to open the memory file */ - FFLOCK; /* lock this while searching for vacant handle */ - *status = mem_openmem( buffptr, buffsize,deltasize, - mem_realloc, &handle); - FFUNLOCK; - - if (*status > 0) - { - ffpmsg("failed to open pre-existing memory file: (ffomem)"); - return(*status); - } - - /* get initial file size */ - *status = (*driverTable[driver].size)(handle, &filesize); - - if (*status > 0) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed get the size of the memory file: (ffomem)"); - return(*status); - } - - /* allocate fitsfile structure and initialize = 0 */ - *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); - - if (!(*fptr)) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate structure for following file: (ffomem)"); - ffpmsg(url); - return(*status = MEMORY_ALLOCATION); - } - - /* allocate FITSfile structure and initialize = 0 */ - (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile)); - - if (!((*fptr)->Fptr)) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate structure for following file: (ffomem)"); - ffpmsg(url); - free(*fptr); - *fptr = 0; - return(*status = MEMORY_ALLOCATION); - } - - slen = strlen(url) + 1; - slen = maxvalue(slen, 32); /* reserve at least 32 chars */ - ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */ - - if ( !(((*fptr)->Fptr)->filename) ) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate memory for filename: (ffomem)"); - ffpmsg(url); - free((*fptr)->Fptr); - free(*fptr); - *fptr = 0; /* return null file pointer */ - return(*status = MEMORY_ALLOCATION); - } - - /* mem for headstart array */ - ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG)); - - if ( !(((*fptr)->Fptr)->headstart) ) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate memory for headstart array: (ffomem)"); - ffpmsg(url); - free( ((*fptr)->Fptr)->filename); - free((*fptr)->Fptr); - free(*fptr); - *fptr = 0; /* return null file pointer */ - return(*status = MEMORY_ALLOCATION); - } - - /* mem for file I/O buffers */ - ((*fptr)->Fptr)->iobuffer = (char *) calloc(NIOBUF, IOBUFLEN); - - if ( !(((*fptr)->Fptr)->iobuffer) ) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate memory for iobuffer array: (ffomem)"); - ffpmsg(url); - free( ((*fptr)->Fptr)->headstart); /* free memory for headstart array */ - free( ((*fptr)->Fptr)->filename); - free((*fptr)->Fptr); - free(*fptr); - *fptr = 0; /* return null file pointer */ - return(*status = MEMORY_ALLOCATION); - } - - /* initialize the ageindex array (relative age of the I/O buffers) */ - /* and initialize the bufrecnum array as being empty */ - for (ii = 0; ii < NIOBUF; ii++) { - ((*fptr)->Fptr)->ageindex[ii] = ii; - ((*fptr)->Fptr)->bufrecnum[ii] = -1; - } - - /* store the parameters describing the file */ - ((*fptr)->Fptr)->MAXHDU = 1000; /* initial size of headstart */ - ((*fptr)->Fptr)->filehandle = handle; /* file handle */ - ((*fptr)->Fptr)->driver = driver; /* driver number */ - strcpy(((*fptr)->Fptr)->filename, url); /* full input filename */ - ((*fptr)->Fptr)->filesize = filesize; /* physical file size */ - ((*fptr)->Fptr)->logfilesize = filesize; /* logical file size */ - ((*fptr)->Fptr)->writemode = mode; /* read-write mode */ - ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */ - ((*fptr)->Fptr)->curbuf = -1; /* undefined current IO buffer */ - ((*fptr)->Fptr)->open_count = 1; /* structure is currently used once */ - ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */ - - ffldrc(*fptr, 0, REPORT_EOF, status); /* load first record */ - - fits_store_Fptr( (*fptr)->Fptr, status); /* store Fptr address */ - - if (ffrhdu(*fptr, &hdutyp, status) > 0) /* determine HDU structure */ - { - ffpmsg( - "ffomem could not interpret primary array header of file: (ffomem)"); - ffpmsg(url); - - if (*status == UNKNOWN_REC) - ffpmsg("This does not look like a FITS file."); - - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - } - - /* ---------------------------------------------------------- */ - /* move to desired extension, if specified as part of the URL */ - /* ---------------------------------------------------------- */ - - imagecolname[0] = '\0'; - rowexpress[0] = '\0'; - - if (*extspec) - { - /* parse the extension specifier into individual parameters */ - ffexts(extspec, &extnum, - extname, &extvers, &movetotype, imagecolname, rowexpress, status); - - - if (*status > 0) - return(*status); - - if (extnum) - { - ffmahd(*fptr, extnum + 1, &hdutyp, status); - } - else if (*extname) /* move to named extension, if specified */ - { - ffmnhd(*fptr, movetotype, extname, extvers, status); - } - - if (*status > 0) - { - ffpmsg("ffomem could not move to the specified extension:"); - if (extnum > 0) - { - sprintf(errmsg, - " extension number %d doesn't exist or couldn't be opened.",extnum); - ffpmsg(errmsg); - } - else - { - sprintf(errmsg, - " extension with EXTNAME = %s,", extname); - ffpmsg(errmsg); - - if (extvers) - { - sprintf(errmsg, - " and with EXTVERS = %d,", extvers); - ffpmsg(errmsg); - } - - if (movetotype != ANY_HDU) - { - sprintf(errmsg, - " and with XTENSION = %s,", hdtype[movetotype]); - ffpmsg(errmsg); - } - - ffpmsg(" doesn't exist or couldn't be opened."); - } - return(*status); - } - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffdkopn(fitsfile **fptr, /* O - FITS file pointer */ - const char *name, /* I - full name of file to open */ - int mode, /* I - 0 = open readonly; 1 = read/write */ - int *status) /* IO - error status */ -/* - Open an existing FITS file on magnetic disk with either readonly or - read/write access. The routine does not support CFITSIO's extended - filename syntax and simply uses the entire input 'name' string as - the name of the file. -*/ -{ - if (*status > 0) - return(*status); - - *status = OPEN_DISK_FILE; - - ffopen(fptr, name, mode, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffdopn(fitsfile **fptr, /* O - FITS file pointer */ - const char *name, /* I - full name of file to open */ - int mode, /* I - 0 = open readonly; 1 = read/write */ - int *status) /* IO - error status */ -/* - Open an existing FITS file with either readonly or read/write access. and - move to the first HDU that contains 'interesting' data, if the primary - array contains a null image (i.e., NAXIS = 0). -*/ -{ - if (*status > 0) - return(*status); - - *status = SKIP_NULL_PRIMARY; - - ffopen(fptr, name, mode, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffeopn(fitsfile **fptr, /* O - FITS file pointer */ - const char *name, /* I - full name of file to open */ - int mode, /* I - 0 = open readonly; 1 = read/write */ - char *extlist, /* I - list of 'good' extensions to move to */ - int *hdutype, /* O - type of extension that is moved to */ - int *status) /* IO - error status */ -/* - Open an existing FITS file with either readonly or read/write access. and - if the primary array contains a null image (i.e., NAXIS = 0) then attempt to - move to the first extension named in the extlist of extension names. If - none are found, then simply move to the 2nd extension. -*/ -{ - int hdunum, naxis, thdutype, gotext=0; - char *ext, *textlist; - char *saveptr; - - if (*status > 0) - return(*status); - - if (ffopen(fptr, name, mode, status) > 0) - return(*status); - - fits_get_hdu_num(*fptr, &hdunum); - fits_get_img_dim(*fptr, &naxis, status); - - if( (hdunum == 1) && (naxis == 0) ){ - /* look through the extension list */ - if( extlist ){ - gotext = 0; - textlist = malloc(strlen(extlist) + 1); - if (!textlist) { - *status = MEMORY_ALLOCATION; - return(*status); - } - - strcpy(textlist, extlist); - for(ext=(char *)ffstrtok(textlist, " ",&saveptr); ext != NULL; - ext=(char *)ffstrtok(NULL," ",&saveptr)){ - fits_movnam_hdu(*fptr, ANY_HDU, ext, 0, status); - if( *status == 0 ){ - gotext = 1; - break; - } else { - *status = 0; - } - } - free(textlist); - } - if( !gotext ){ - /* if all else fails, move to extension #2 and hope for the best */ - fits_movabs_hdu(*fptr, 2, &thdutype, status); - } - } - fits_get_hdu_type(*fptr, hdutype, status); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fftopn(fitsfile **fptr, /* O - FITS file pointer */ - const char *name, /* I - full name of file to open */ - int mode, /* I - 0 = open readonly; 1 = read/write */ - int *status) /* IO - error status */ -/* - Open an existing FITS file with either readonly or read/write access. and - move to the first HDU that contains 'interesting' table (not an image). -*/ -{ - int hdutype; - - if (*status > 0) - return(*status); - - *status = SKIP_IMAGE; - - ffopen(fptr, name, mode, status); - - if (ffghdt(*fptr, &hdutype, status) <= 0) { - if (hdutype == IMAGE_HDU) - *status = NOT_TABLE; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffiopn(fitsfile **fptr, /* O - FITS file pointer */ - const char *name, /* I - full name of file to open */ - int mode, /* I - 0 = open readonly; 1 = read/write */ - int *status) /* IO - error status */ -/* - Open an existing FITS file with either readonly or read/write access. and - move to the first HDU that contains 'interesting' image (not an table). -*/ -{ - int hdutype; - - if (*status > 0) - return(*status); - - *status = SKIP_TABLE; - - ffopen(fptr, name, mode, status); - - if (ffghdt(*fptr, &hdutype, status) <= 0) { - if (hdutype != IMAGE_HDU) - *status = NOT_IMAGE; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffopentest(int soname, /* I - CFITSIO shared library version */ - /* application program (fitsio.h file) */ - fitsfile **fptr, /* O - FITS file pointer */ - const char *name, /* I - full name of file to open */ - int mode, /* I - 0 = open readonly; 1 = read/write */ - int *status) /* IO - error status */ -/* - Open an existing FITS file with either readonly or read/write access. - First test that the SONAME of fitsio.h used to build the CFITSIO library - is the same as was used in compiling the application program that - links to the library. -*/ -{ - if (soname != CFITSIO_SONAME) - { - printf("\nERROR: Mismatch in the CFITSIO_SONAME value in the fitsio.h include file\n"); - printf("that was used to build the CFITSIO library, and the value in the include file\n"); - printf("that was used when compiling the application program:\n"); - printf(" Version used to build the CFITSIO library = %d\n",CFITSIO_SONAME); - printf(" Version included by the application program = %d\n",soname); - printf("\nFix this by recompiling and then relinking this application program \n"); - printf("with the CFITSIO library.\n"); - - *status = FILE_NOT_OPENED; - return(*status); - } - - /* now call the normal file open routine */ - ffopen(fptr, name, mode, status); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffopen(fitsfile **fptr, /* O - FITS file pointer */ - const char *name, /* I - full name of file to open */ - int mode, /* I - 0 = open readonly; 1 = read/write */ - int *status) /* IO - error status */ -/* - Open an existing FITS file with either readonly or read/write access. -*/ -{ - fitsfile *newptr; - int ii, driver, hdutyp, hdunum, slen, writecopy, isopen; - LONGLONG filesize; - long rownum, nrows, goodrows; - int extnum, extvers, handle, movetotype, tstatus = 0, only_one = 0; - char urltype[MAX_PREFIX_LEN], infile[FLEN_FILENAME], outfile[FLEN_FILENAME]; - char origurltype[MAX_PREFIX_LEN], extspec[FLEN_FILENAME]; - char extname[FLEN_VALUE], rowfilter[FLEN_FILENAME], tblname[FLEN_VALUE]; - char imagecolname[FLEN_VALUE], rowexpress[FLEN_FILENAME]; - char binspec[FLEN_FILENAME], colspec[FLEN_FILENAME], pixfilter[FLEN_FILENAME]; - char histfilename[FLEN_FILENAME]; - char filtfilename[FLEN_FILENAME], compspec[FLEN_FILENAME]; - char wtcol[FLEN_VALUE]; - char minname[4][FLEN_VALUE], maxname[4][FLEN_VALUE]; - char binname[4][FLEN_VALUE]; - - char *url; - double minin[4], maxin[4], binsizein[4], weight; - int imagetype, naxis = 1, haxis, recip; - int skip_null = 0, skip_image = 0, skip_table = 0, open_disk_file = 0; - char colname[4][FLEN_VALUE]; - char errmsg[FLEN_ERRMSG]; - char *hdtype[3] = {"IMAGE", "TABLE", "BINTABLE"}; - char *rowselect = 0; - - if (*status > 0) - return(*status); - - if (*status == SKIP_NULL_PRIMARY) - { - /* this special status value is used as a flag by ffdopn to tell */ - /* ffopen to skip over a null primary array when opening the file. */ - - skip_null = 1; - *status = 0; - } - else if (*status == SKIP_IMAGE) - { - /* this special status value is used as a flag by fftopn to tell */ - /* ffopen to move to 1st significant table when opening the file. */ - - skip_image = 1; - *status = 0; - } - else if (*status == SKIP_TABLE) - { - /* this special status value is used as a flag by ffiopn to tell */ - /* ffopen to move to 1st significant image when opening the file. */ - - skip_table = 1; - *status = 0; - } - else if (*status == OPEN_DISK_FILE) - { - /* this special status value is used as a flag by ffdkopn to tell */ - /* ffopen to not interpret the input filename using CFITSIO's */ - /* extended filename syntax, and simply open the specified disk file */ - - open_disk_file = 1; - *status = 0; - } - - *fptr = 0; /* initialize null file pointer */ - writecopy = 0; /* have we made a write-able copy of the input file? */ - - if (need_to_initialize) { /* this is called only once */ - *status = fits_init_cfitsio(); - } - - if (*status > 0) - return(*status); - - url = (char *) name; - while (*url == ' ') /* ignore leading spaces in the filename */ - url++; - - if (*url == '\0') - { - ffpmsg("Name of file to open is blank. (ffopen)"); - return(*status = FILE_NOT_OPENED); - } - - if (open_disk_file) - { - /* treat the input URL literally as the name of the file to open */ - /* and don't try to parse the URL using the extended filename syntax */ - - if (strlen(url) > FLEN_FILENAME - 1) { - ffpmsg("Name of file to open is too long. (ffopen)"); - return(*status = FILE_NOT_OPENED); - } - - strcpy(infile,url); - strcpy(urltype, "file://"); - outfile[0] = '\0'; - extspec[0] = '\0'; - binspec[0] = '\0'; - colspec[0] = '\0'; - rowfilter[0] = '\0'; - pixfilter[0] = '\0'; - compspec[0] = '\0'; - } - else - { - /* parse the input file specification */ - - /* NOTE: This routine tests that all the strings do not */ - /* overflow the standard buffer sizes (FLEN_FILENAME, etc.) */ - /* therefore in general we do not have to worry about buffer */ - /* overflow of any of the returned strings. */ - - /* call the newer version of this parsing routine that supports 'compspec' */ - ffifile2(url, urltype, infile, outfile, extspec, - rowfilter, binspec, colspec, pixfilter, compspec, status); - } - - if (*status > 0) - { - ffpmsg("could not parse the input filename: (ffopen)"); - ffpmsg(url); - return(*status); - } - - imagecolname[0] = '\0'; - rowexpress[0] = '\0'; - - if (*extspec) - { - slen = strlen(extspec); - if (extspec[slen - 1] == '#') { /* special symbol to mean only copy this extension */ - extspec[slen - 1] = '\0'; - only_one = 1; - } - - /* parse the extension specifier into individual parameters */ - ffexts(extspec, &extnum, - extname, &extvers, &movetotype, imagecolname, rowexpress, status); - - if (*status > 0) - return(*status); - } - - /*-------------------------------------------------------------------*/ - /* special cases: */ - /*-------------------------------------------------------------------*/ - - histfilename[0] = '\0'; - filtfilename[0] = '\0'; - if (*outfile && (*binspec || *imagecolname || *pixfilter)) - { - /* if binspec or imagecolumn are specified, then the */ - /* output file name is intended for the final image, */ - /* and not a copy of the input file. */ - - strcpy(histfilename, outfile); - outfile[0] = '\0'; - } - else if (*outfile && (*rowfilter || *colspec)) - { - /* if rowfilter or colspece are specified, then the */ - /* output file name is intended for the filtered file */ - /* and not a copy of the input file. */ - - strcpy(filtfilename, outfile); - outfile[0] = '\0'; - } - - /*-------------------------------------------------------------------*/ - /* check if this same file is already open, and if so, attach to it */ - /*-------------------------------------------------------------------*/ - - FFLOCK; - if (fits_already_open(fptr, url, urltype, infile, extspec, rowfilter, - binspec, colspec, mode, &isopen, status) > 0) - { - FFUNLOCK; - return(*status); - } - FFUNLOCK; - - if (isopen) { - goto move2hdu; - } - - /* get the driver number corresponding to this urltype */ - *status = urltype2driver(urltype, &driver); - - if (*status > 0) - { - ffpmsg("could not find driver for this file: (ffopen)"); - ffpmsg(urltype); - ffpmsg(url); - return(*status); - } - - /*------------------------------------------------------------------- - deal with all those messy special cases which may require that - a different driver be used: - - is disk file compressed? - - are ftp:, gsiftp:, or http: files compressed? - - has user requested that a local copy be made of - the ftp or http file? - -------------------------------------------------------------------*/ - - if (driverTable[driver].checkfile) - { - strcpy(origurltype,urltype); /* Save the urltype */ - - /* 'checkfile' may modify the urltype, infile and outfile strings */ - *status = (*driverTable[driver].checkfile)(urltype, infile, outfile); - - if (*status) - { - ffpmsg("checkfile failed for this file: (ffopen)"); - ffpmsg(url); - return(*status); - } - - if (strcmp(origurltype, urltype)) /* did driver changed on us? */ - { - *status = urltype2driver(urltype, &driver); - if (*status > 0) - { - ffpmsg("could not change driver for this file: (ffopen)"); - ffpmsg(url); - ffpmsg(urltype); - return(*status); - } - } - } - - /* call appropriate driver to open the file */ - if (driverTable[driver].open) - { - FFLOCK; /* lock this while searching for vacant handle */ - *status = (*driverTable[driver].open)(infile, mode, &handle); - FFUNLOCK; - if (*status > 0) - { - ffpmsg("failed to find or open the following file: (ffopen)"); - ffpmsg(url); - return(*status); - } - } - else - { - ffpmsg("cannot open an existing file of this type: (ffopen)"); - ffpmsg(url); - return(*status = FILE_NOT_OPENED); - } - - /* get initial file size */ - *status = (*driverTable[driver].size)(handle, &filesize); - if (*status > 0) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed get the size of the following file: (ffopen)"); - ffpmsg(url); - return(*status); - } - - /* allocate fitsfile structure and initialize = 0 */ - *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); - - if (!(*fptr)) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate structure for following file: (ffopen)"); - ffpmsg(url); - return(*status = MEMORY_ALLOCATION); - } - - /* allocate FITSfile structure and initialize = 0 */ - (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile)); - - if (!((*fptr)->Fptr)) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate structure for following file: (ffopen)"); - ffpmsg(url); - free(*fptr); - *fptr = 0; - return(*status = MEMORY_ALLOCATION); - } - - slen = strlen(url) + 1; - slen = maxvalue(slen, 32); /* reserve at least 32 chars */ - ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */ - - if ( !(((*fptr)->Fptr)->filename) ) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate memory for filename: (ffopen)"); - ffpmsg(url); - free((*fptr)->Fptr); - free(*fptr); - *fptr = 0; /* return null file pointer */ - return(*status = MEMORY_ALLOCATION); - } - - /* mem for headstart array */ - ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG)); - - if ( !(((*fptr)->Fptr)->headstart) ) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate memory for headstart array: (ffopen)"); - ffpmsg(url); - free( ((*fptr)->Fptr)->filename); - free((*fptr)->Fptr); - free(*fptr); - *fptr = 0; /* return null file pointer */ - return(*status = MEMORY_ALLOCATION); - } - - /* mem for file I/O buffers */ - ((*fptr)->Fptr)->iobuffer = (char *) calloc(NIOBUF, IOBUFLEN); - - if ( !(((*fptr)->Fptr)->iobuffer) ) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate memory for iobuffer array: (ffopen)"); - ffpmsg(url); - free( ((*fptr)->Fptr)->headstart); /* free memory for headstart array */ - free( ((*fptr)->Fptr)->filename); - free((*fptr)->Fptr); - free(*fptr); - *fptr = 0; /* return null file pointer */ - return(*status = MEMORY_ALLOCATION); - } - - /* initialize the ageindex array (relative age of the I/O buffers) */ - /* and initialize the bufrecnum array as being empty */ - for (ii = 0; ii < NIOBUF; ii++) { - ((*fptr)->Fptr)->ageindex[ii] = ii; - ((*fptr)->Fptr)->bufrecnum[ii] = -1; - } - - /* store the parameters describing the file */ - ((*fptr)->Fptr)->MAXHDU = 1000; /* initial size of headstart */ - ((*fptr)->Fptr)->filehandle = handle; /* file handle */ - ((*fptr)->Fptr)->driver = driver; /* driver number */ - strcpy(((*fptr)->Fptr)->filename, url); /* full input filename */ - ((*fptr)->Fptr)->filesize = filesize; /* physical file size */ - ((*fptr)->Fptr)->logfilesize = filesize; /* logical file size */ - ((*fptr)->Fptr)->writemode = mode; /* read-write mode */ - ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */ - ((*fptr)->Fptr)->curbuf = -1; /* undefined current IO buffer */ - ((*fptr)->Fptr)->open_count = 1; /* structure is currently used once */ - ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */ - ((*fptr)->Fptr)->only_one = only_one; /* flag denoting only copy single extension */ - - ffldrc(*fptr, 0, REPORT_EOF, status); /* load first record */ - - fits_store_Fptr( (*fptr)->Fptr, status); /* store Fptr address */ - - if (ffrhdu(*fptr, &hdutyp, status) > 0) /* determine HDU structure */ - { - ffpmsg( - "ffopen could not interpret primary array header of file: "); - ffpmsg(url); - - if (*status == UNKNOWN_REC) - ffpmsg("This does not look like a FITS file."); - - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status); - } - - /* ------------------------------------------------------------- */ - /* At this point, the input file has been opened. If outfile was */ - /* specified, then we have opened a copy of the file, not the */ - /* original file so it is safe to modify it if necessary */ - /* ------------------------------------------------------------- */ - - if (*outfile) - writecopy = 1; - -move2hdu: - - /* ---------------------------------------------------------- */ - /* move to desired extension, if specified as part of the URL */ - /* ---------------------------------------------------------- */ - - if (*extspec) - { - if (extnum) /* extension number was specified */ - { - ffmahd(*fptr, extnum + 1, &hdutyp, status); - } - else if (*extname) /* move to named extension, if specified */ - { - ffmnhd(*fptr, movetotype, extname, extvers, status); - } - - if (*status > 0) /* clean up after error */ - { - ffpmsg("ffopen could not move to the specified extension:"); - if (extnum > 0) - { - sprintf(errmsg, - " extension number %d doesn't exist or couldn't be opened.",extnum); - ffpmsg(errmsg); - } - else - { - sprintf(errmsg, - " extension with EXTNAME = %s,", extname); - ffpmsg(errmsg); - - if (extvers) - { - sprintf(errmsg, - " and with EXTVERS = %d,", extvers); - ffpmsg(errmsg); - } - - if (movetotype != ANY_HDU) - { - sprintf(errmsg, - " and with XTENSION = %s,", hdtype[movetotype]); - ffpmsg(errmsg); - } - - ffpmsg(" doesn't exist or couldn't be opened."); - } - - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status); - } - } - else if (skip_null || skip_image || skip_table || - (*imagecolname || *colspec || *rowfilter || *binspec)) - { - /* ------------------------------------------------------------------ - - If no explicit extension specifier is given as part of the file - name, and, if a) skip_null is true (set if ffopen is called by - ffdopn) or b) skip_image or skip_table is true (set if ffopen is - called by fftopn or ffdopn) or c) other file filters are - specified, then CFITSIO will attempt to move to the first - 'interesting' HDU after opening an existing FITS file (or to - first interesting table HDU if skip_image is true); - - An 'interesting' HDU is defined to be either an image with NAXIS - > 0 (i.e., not a null array) or a table which has an EXTNAME - value which does not contain any of the following strings: - 'GTI' - Good Time Interval extension - 'OBSTABLE' - used in Beppo SAX data files - - The main purpose for this is to allow CFITSIO to skip over a null - primary and other non-interesting HDUs when opening an existing - file, and move directly to the first extension that contains - significant data. - ------------------------------------------------------------------ */ - - fits_get_hdu_num(*fptr, &hdunum); - if (hdunum == 1) { - - fits_get_img_dim(*fptr, &naxis, status); - - if (naxis == 0 || skip_image) /* skip primary array */ - { - while(1) - { - /* see if the next HDU is 'interesting' */ - if (fits_movrel_hdu(*fptr, 1, &hdutyp, status)) - { - if (*status == END_OF_FILE) - *status = 0; /* reset expected error */ - - /* didn't find an interesting HDU so move back to beginning */ - fits_movabs_hdu(*fptr, 1, &hdutyp, status); - break; - } - - if (hdutyp == IMAGE_HDU && skip_image) { - - continue; /* skip images */ - - } else if (hdutyp != IMAGE_HDU && skip_table) { - - continue; /* skip tables */ - - } else if (hdutyp == IMAGE_HDU) { - - fits_get_img_dim(*fptr, &naxis, status); - if (naxis > 0) - break; /* found a non-null image */ - - } else { - - tstatus = 0; - tblname[0] = '\0'; - fits_read_key(*fptr, TSTRING, "EXTNAME", tblname, NULL,&tstatus); - - if ( (!strstr(tblname, "GTI") && !strstr(tblname, "gti")) && - fits_strncasecmp(tblname, "OBSTABLE", 8) ) - break; /* found an interesting table */ - } - } /* end while */ - } - } /* end if (hdunum==1) */ - } - - if (*imagecolname) - { - /* ----------------------------------------------------------------- */ - /* we need to open an image contained in a single table cell */ - /* First, determine which row of the table to use. */ - /* ----------------------------------------------------------------- */ - - if (isdigit((int) *rowexpress)) /* is the row specification a number? */ - { - sscanf(rowexpress, "%ld", &rownum); - if (rownum < 1) - { - ffpmsg("illegal rownum for image cell:"); - ffpmsg(rowexpress); - ffpmsg("Could not open the following image in a table cell:"); - ffpmsg(extspec); - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status = BAD_ROW_NUM); - } - } - else if (fits_find_first_row(*fptr, rowexpress, &rownum, status) > 0) - { - ffpmsg("Failed to find row matching this expression:"); - ffpmsg(rowexpress); - ffpmsg("Could not open the following image in a table cell:"); - ffpmsg(extspec); - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status); - } - - if (rownum == 0) - { - ffpmsg("row statisfying this expression doesn't exist::"); - ffpmsg(rowexpress); - ffpmsg("Could not open the following image in a table cell:"); - ffpmsg(extspec); - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status = BAD_ROW_NUM); - } - - /* determine the name of the new file to contain copy of the image */ - if (*histfilename && !(*pixfilter) ) - strcpy(outfile, histfilename); /* the original outfile name */ - else - strcpy(outfile, "mem://_1"); /* create image file in memory */ - - /* Copy the image into new primary array and open it as the current */ - /* fptr. This will close the table that contains the original image. */ - - /* create new empty file to hold copy of the image */ - if (ffinit(&newptr, outfile, status) > 0) - { - ffpmsg("failed to create file for copy of image in table cell:"); - ffpmsg(outfile); - return(*status); - } - - if (fits_copy_cell2image(*fptr, newptr, imagecolname, rownum, - status) > 0) - { - ffpmsg("Failed to copy table cell to new primary array:"); - ffpmsg(extspec); - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status); - } - - /* close the original file and set fptr to the new image */ - ffclos(*fptr, status); - - *fptr = newptr; /* reset the pointer to the new table */ - - writecopy = 1; /* we are now dealing with a copy of the original file */ - - /* add some HISTORY; fits_copy_image_cell also wrote HISTORY keywords */ - -/* disable this; leave it up to calling routine to write any HISTORY keywords - if (*extname) - sprintf(card,"HISTORY in HDU '%.16s' of file '%.36s'",extname,infile); - else - sprintf(card,"HISTORY in HDU %d of file '%.45s'", extnum, infile); - - ffprec(*fptr, card, status); -*/ - } - - /* --------------------------------------------------------------------- */ - /* edit columns (and/or keywords) in the table, if specified in the URL */ - /* --------------------------------------------------------------------- */ - - if (*colspec) - { - /* the column specifier will modify the file, so make sure */ - /* we are already dealing with a copy, or else make a new copy */ - - if (!writecopy) /* Is the current file already a copy? */ - writecopy = fits_is_this_a_copy(urltype); - - if (!writecopy) - { - if (*filtfilename && *outfile == '\0') - strcpy(outfile, filtfilename); /* the original outfile name */ - else - strcpy(outfile, "mem://_1"); /* will create copy in memory */ - - writecopy = 1; - } - else - { - ((*fptr)->Fptr)->writemode = READWRITE; /* we have write access */ - outfile[0] = '\0'; - } - - if (ffedit_columns(fptr, outfile, colspec, status) > 0) - { - ffpmsg("editing columns in input table failed (ffopen)"); - ffpmsg(" while trying to perform the following operation:"); - ffpmsg(colspec); - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status); - } - } - - /* ------------------------------------------------------------------- */ - /* select rows from the table, if specified in the URL */ - /* or select a subimage (if this is an image HDU and not a table) */ - /* ------------------------------------------------------------------- */ - - if (*rowfilter) - { - fits_get_hdu_type(*fptr, &hdutyp, status); /* get type of HDU */ - if (hdutyp == IMAGE_HDU) - { - /* this is an image so 'rowfilter' is an image section specification */ - - if (*filtfilename && *outfile == '\0') - strcpy(outfile, filtfilename); /* the original outfile name */ - else if (*outfile == '\0') /* output file name not already defined? */ - strcpy(outfile, "mem://_2"); /* will create file in memory */ - - /* create new file containing the image section, plus a copy of */ - /* any other HDUs that exist in the input file. This routine */ - /* will close the original image file and return a pointer */ - /* to the new file. */ - - if (fits_select_image_section(fptr, outfile, rowfilter, status) > 0) - { - ffpmsg("on-the-fly selection of image section failed (ffopen)"); - ffpmsg(" while trying to use the following section filter:"); - ffpmsg(rowfilter); - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status); - } - } - else - { - /* this is a table HDU, so the rowfilter is really a row filter */ - - if (*binspec) - { - /* since we are going to make a histogram of the selected rows, */ - /* it would be a waste of time and memory to make a whole copy of */ - /* the selected rows. Instead, just construct an array of TRUE */ - /* or FALSE values that indicate which rows are to be included */ - /* in the histogram and pass that to the histogram generating */ - /* routine */ - - fits_get_num_rows(*fptr, &nrows, status); /* get no. of rows */ - - rowselect = (char *) calloc(nrows, 1); - if (!rowselect) - { - ffpmsg( - "failed to allocate memory for selected columns array (ffopen)"); - ffpmsg(" while trying to select rows with the following filter:"); - ffpmsg(rowfilter); - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status = MEMORY_ALLOCATION); - } - - if (fits_find_rows(*fptr, rowfilter, 1L, nrows, &goodrows, - rowselect, status) > 0) - { - ffpmsg("selection of rows in input table failed (ffopen)"); - ffpmsg(" while trying to select rows with the following filter:"); - ffpmsg(rowfilter); - free(rowselect); - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status); - } - } - else - { - if (!writecopy) /* Is the current file already a copy? */ - writecopy = fits_is_this_a_copy(urltype); - - if (!writecopy) - { - if (*filtfilename && *outfile == '\0') - strcpy(outfile, filtfilename); /* the original outfile name */ - else if (*outfile == '\0') /* output filename not already defined? */ - strcpy(outfile, "mem://_2"); /* will create copy in memory */ - } - else - { - ((*fptr)->Fptr)->writemode = READWRITE; /* we have write access */ - outfile[0] = '\0'; - } - - /* select rows in the table. If a copy of the input file has */ - /* not already been made, then this routine will make a copy */ - /* and then close the input file, so that the modifications will */ - /* only be made on the copy, not the original */ - - if (ffselect_table(fptr, outfile, rowfilter, status) > 0) - { - ffpmsg("on-the-fly selection of rows in input table failed (ffopen)"); - ffpmsg(" while trying to select rows with the following filter:"); - ffpmsg(rowfilter); - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status); - } - - /* write history records */ - ffphis(*fptr, - "CFITSIO used the following filtering expression to create this table:", - status); - ffphis(*fptr, name, status); - - } /* end of no binspec case */ - } /* end of table HDU case */ - } /* end of rowfilter exists case */ - - /* ------------------------------------------------------------------- */ - /* make an image histogram by binning columns, if specified in the URL */ - /* ------------------------------------------------------------------- */ - - if (*binspec) - { - if (*histfilename && !(*pixfilter) ) - strcpy(outfile, histfilename); /* the original outfile name */ - else - strcpy(outfile, "mem://_3"); /* create histogram in memory */ - /* if not already copied the file */ - - /* parse the binning specifier into individual parameters */ - ffbins(binspec, &imagetype, &haxis, colname, - minin, maxin, binsizein, - minname, maxname, binname, - &weight, wtcol, &recip, status); - - /* Create the histogram primary array and open it as the current fptr */ - /* This will close the table that was used to create the histogram. */ - ffhist2(fptr, outfile, imagetype, haxis, colname, minin, maxin, - binsizein, minname, maxname, binname, - weight, wtcol, recip, rowselect, status); - - if (rowselect) - free(rowselect); - - if (*status > 0) - { - ffpmsg("on-the-fly histogramming of input table failed (ffopen)"); - ffpmsg(" while trying to execute the following histogram specification:"); - ffpmsg(binspec); - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status); - } - - /* write history records */ - ffphis(*fptr, - "CFITSIO used the following expression to create this histogram:", - status); - ffphis(*fptr, name, status); - } - - if (*pixfilter) - { - if (*histfilename) - strcpy(outfile, histfilename); /* the original outfile name */ - else - strcpy(outfile, "mem://_4"); /* create in memory */ - /* if not already copied the file */ - - /* Ensure type of HDU is consistent with pixel filtering */ - fits_get_hdu_type(*fptr, &hdutyp, status); /* get type of HDU */ - if (hdutyp == IMAGE_HDU) { - - pixel_filter_helper(fptr, outfile, pixfilter, status); - - if (*status > 0) { - ffpmsg("pixel filtering of input image failed (ffopen)"); - ffpmsg(" while trying to execute the following:"); - ffpmsg(pixfilter); - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - return(*status); - } - - /* write history records */ - ffphis(*fptr, - "CFITSIO used the following expression to create this image:", - status); - ffphis(*fptr, name, status); - } - else - { - ffpmsg("cannot use pixel filter on non-IMAGE HDU"); - ffpmsg(pixfilter); - ffclos(*fptr, status); - *fptr = 0; /* return null file pointer */ - *status = NOT_IMAGE; - return(*status); - } - } - - /* parse and save image compression specification, if given */ - if (*compspec) { - ffparsecompspec(*fptr, compspec, status); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffreopen(fitsfile *openfptr, /* I - FITS file pointer to open file */ - fitsfile **newfptr, /* O - pointer to new re opened file */ - int *status) /* IO - error status */ -/* - Reopen an existing FITS file with either readonly or read/write access. - The reopened file shares the same FITSfile structure but may point to a - different HDU within the file. -*/ -{ - if (*status > 0) - return(*status); - - /* check that the open file pointer is valid */ - if (!openfptr) - return(*status = NULL_INPUT_PTR); - else if ((openfptr->Fptr)->validcode != VALIDSTRUC) /* check magic value */ - return(*status = BAD_FILEPTR); - - /* allocate fitsfile structure and initialize = 0 */ - *newfptr = (fitsfile *) calloc(1, sizeof(fitsfile)); - - (*newfptr)->Fptr = openfptr->Fptr; /* both point to the same structure */ - (*newfptr)->HDUposition = 0; /* set initial position to primary array */ - (((*newfptr)->Fptr)->open_count)++; /* increment the file usage counter */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_store_Fptr(FITSfile *Fptr, /* O - FITS file pointer */ - int *status) /* IO - error status */ -/* - store the new Fptr address for future use by fits_already_open -*/ -{ - int ii; - - if (*status > 0) - return(*status); - - FFLOCK; - for (ii = 0; ii < NMAXFILES; ii++) { - if (FptrTable[ii] == 0) { - FptrTable[ii] = Fptr; - break; - } - } - FFUNLOCK; - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_clear_Fptr(FITSfile *Fptr, /* O - FITS file pointer */ - int *status) /* IO - error status */ -/* - clear the Fptr address from the Fptr Table -*/ -{ - int ii; - - FFLOCK; - for (ii = 0; ii < NMAXFILES; ii++) { - if (FptrTable[ii] == Fptr) { - FptrTable[ii] = 0; - break; - } - } - FFUNLOCK; - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_already_open(fitsfile **fptr, /* I/O - FITS file pointer */ - char *url, - char *urltype, - char *infile, - char *extspec, - char *rowfilter, - char *binspec, - char *colspec, - int mode, /* I - 0 = open readonly; 1 = read/write */ - int *isopen, /* O - 1 = file is already open */ - int *status) /* IO - error status */ -/* - Check if the file to be opened is already open. If so, then attach to it. -*/ - - /* the input strings must not exceed the standard lengths */ - /* of FLEN_FILENAME, MAX_PREFIX_LEN, etc. */ - - /* - this function was changed so that for files of access method FILE:// - the file paths are compared using standard URL syntax and absolute - paths (as opposed to relative paths). This eliminates some instances - where a file is already opened but it is not realized because it - was opened with another file path. For instance, if the CWD is - /a/b/c and I open /a/b/c/foo.fits then open ./foo.fits the previous - version of this function would not have reconized that the two files - were the same. This version does recognize that the two files are - the same. - */ -{ - FITSfile *oldFptr; - int ii; - char oldurltype[MAX_PREFIX_LEN], oldinfile[FLEN_FILENAME]; - char oldextspec[FLEN_FILENAME], oldoutfile[FLEN_FILENAME]; - char oldrowfilter[FLEN_FILENAME]; - char oldbinspec[FLEN_FILENAME], oldcolspec[FLEN_FILENAME]; - char cwd[FLEN_FILENAME]; - char tmpStr[FLEN_FILENAME]; - char tmpinfile[FLEN_FILENAME]; - - *isopen = 0; - -/* When opening a file with readonly access then we simply let - the operating system open the file again, instead of using the CFITSIO - trick of attaching to the previously opened file. This is required - if CFITSIO is running in a multi-threaded environment, because 2 different - threads cannot share the same FITSfile pointer. - - If the file is opened/reopened with write access, then the file MUST - only be physically opened once.. -*/ - if (mode == 0) - return(*status); - - if(fits_strcasecmp(urltype,"FILE://") == 0) - { - fits_path2url(infile,tmpinfile,status); - - if(tmpinfile[0] != '/') - { - fits_get_cwd(cwd,status); - strcat(cwd,"/"); - - if (strlen(cwd) + strlen(tmpinfile) > FLEN_FILENAME-1) { - ffpmsg("File name is too long. (fits_already_open)"); - return(*status = FILE_NOT_OPENED); - } - - strcat(cwd,tmpinfile); - fits_clean_url(cwd,tmpinfile,status); - } - } - else - strcpy(tmpinfile,infile); - - for (ii = 0; ii < NMAXFILES; ii++) /* check every buffer */ - { - if (FptrTable[ii] != 0) - { - oldFptr = FptrTable[ii]; - - fits_parse_input_url(oldFptr->filename, oldurltype, - oldinfile, oldoutfile, oldextspec, oldrowfilter, - oldbinspec, oldcolspec, status); - - if (*status > 0) - { - ffpmsg("could not parse the previously opened filename: (ffopen)"); - ffpmsg(oldFptr->filename); - return(*status); - } - - if(fits_strcasecmp(oldurltype,"FILE://") == 0) - { - fits_path2url(oldinfile,tmpStr,status); - - if(tmpStr[0] != '/') - { - fits_get_cwd(cwd,status); - strcat(cwd,"/"); - - - strcat(cwd,tmpStr); - fits_clean_url(cwd,tmpStr,status); - } - - strcpy(oldinfile,tmpStr); - } - - if (!strcmp(urltype, oldurltype) && !strcmp(tmpinfile, oldinfile) ) - { - /* identical type of file and root file name */ - - if ( (!rowfilter[0] && !oldrowfilter[0] && - !binspec[0] && !oldbinspec[0] && - !colspec[0] && !oldcolspec[0]) - - /* no filtering or binning specs for either file, so */ - /* this is a case where the same file is being reopened. */ - /* It doesn't matter if the extensions are different */ - - || /* or */ - - (!strcmp(rowfilter, oldrowfilter) && - !strcmp(binspec, oldbinspec) && - !strcmp(colspec, oldcolspec) && - !strcmp(extspec, oldextspec) ) ) - - /* filtering specs are given and are identical, and */ - /* the same extension is specified */ - - { - if (mode == READWRITE && oldFptr->writemode == READONLY) - { - /* - cannot assume that a file previously opened with READONLY - can now be written to (e.g., files on CDROM, or over the - the network, or STDIN), so return with an error. - */ - - ffpmsg( - "cannot reopen file READWRITE when previously opened READONLY"); - ffpmsg(url); - return(*status = FILE_NOT_OPENED); - } - - *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); - - if (!(*fptr)) - { - ffpmsg( - "failed to allocate structure for following file: (ffopen)"); - ffpmsg(url); - return(*status = MEMORY_ALLOCATION); - } - - (*fptr)->Fptr = oldFptr; /* point to the structure */ - (*fptr)->HDUposition = 0; /* set initial position */ - (((*fptr)->Fptr)->open_count)++; /* increment usage counter */ - - if (binspec[0]) /* if binning specified, don't move */ - extspec[0] = '\0'; - - /* all the filtering has already been applied, so ignore */ - rowfilter[0] = '\0'; - binspec[0] = '\0'; - colspec[0] = '\0'; - - *isopen = 1; - } - } - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_is_this_a_copy(char *urltype) /* I - type of file */ -/* - specialized routine that returns 1 if the file is known to be a temporary - copy of the originally opened file. Otherwise it returns 0. -*/ -{ - int iscopy; - - if (!strncmp(urltype, "mem", 3) ) - iscopy = 1; /* file copy is in memory */ - else if (!strncmp(urltype, "compress", 8) ) - iscopy = 1; /* compressed diskfile that is uncompressed in memory */ - else if (!strncmp(urltype, "http", 4) ) - iscopy = 1; /* copied file using http protocol */ - else if (!strncmp(urltype, "ftp", 3) ) - iscopy = 1; /* copied file using ftp protocol */ - else if (!strncmp(urltype, "gsiftp", 6) ) - iscopy = 1; /* copied file using gsiftp protocol */ - else if (!strncpy(urltype, "stdin", 5) ) - iscopy = 1; /* piped stdin has been copied to memory */ - else - iscopy = 0; /* file is not known to be a copy */ - - return(iscopy); -} -/*--------------------------------------------------------------------------*/ -static int find_quote(char **string) - -/* - look for the closing single quote character in the input string -*/ -{ - char *tstr; - - tstr = *string; - - while (*tstr) { - if (*tstr == '\'') { /* found the closing quote */ - *string = tstr + 1; /* set pointer to next char */ - return(0); - } else { /* skip over any other character */ - tstr++; - } - } - return(1); /* opps, didn't find the closing character */ -} -/*--------------------------------------------------------------------------*/ -static int find_doublequote(char **string) - -/* - look for the closing double quote character in the input string -*/ -{ - char *tstr; - - tstr = *string; - - while (*tstr) { - if (*tstr == '"') { /* found the closing quote */ - *string = tstr + 1; /* set pointer to next char */ - return(0); - } else { /* skip over any other character */ - tstr++; - } - } - return(1); /* opps, didn't find the closing character */ -} - -/*--------------------------------------------------------------------------*/ -static int find_paren(char **string) - -/* - look for the closing parenthesis character in the input string -*/ -{ - char *tstr; - - tstr = *string; - - while (*tstr) { - - if (*tstr == ')') { /* found the closing parens */ - *string = tstr + 1; /* set pointer to next char */ - return(0); - } else if (*tstr == '(') { /* found another level of parens */ - tstr++; - if (find_paren(&tstr)) return(1); - } else if (*tstr == '[') { - tstr++; - if (find_bracket(&tstr)) return(1); - } else if (*tstr == '{') { - tstr++; - if (find_curlybracket(&tstr)) return(1); - } else if (*tstr == '"') { - tstr++; - if (find_doublequote(&tstr)) return(1); - } else if (*tstr == '\'') { - tstr++; - if (find_quote(&tstr)) return(1); - } else { - tstr++; - } - } - return(1); /* opps, didn't find the closing character */ -} -/*--------------------------------------------------------------------------*/ -static int find_bracket(char **string) - -/* - look for the closing bracket character in the input string -*/ -{ - char *tstr; - - tstr = *string; - - while (*tstr) { - if (*tstr == ']') { /* found the closing bracket */ - *string = tstr + 1; /* set pointer to next char */ - return(0); - } else if (*tstr == '(') { /* found another level of parens */ - tstr++; - if (find_paren(&tstr)) return(1); - } else if (*tstr == '[') { - tstr++; - if (find_bracket(&tstr)) return(1); - } else if (*tstr == '{') { - tstr++; - if (find_curlybracket(&tstr)) return(1); - } else if (*tstr == '"') { - tstr++; - if (find_doublequote(&tstr)) return(1); - } else if (*tstr == '\'') { - tstr++; - if (find_quote(&tstr)) return(1); - } else { - tstr++; - } - } - return(1); /* opps, didn't find the closing character */ -} -/*--------------------------------------------------------------------------*/ -static int find_curlybracket(char **string) - -/* - look for the closing curly bracket character in the input string -*/ -{ - char *tstr; - - tstr = *string; - - while (*tstr) { - if (*tstr == '}') { /* found the closing curly bracket */ - *string = tstr + 1; /* set pointer to next char */ - return(0); - } else if (*tstr == '(') { /* found another level of parens */ - tstr++; - if (find_paren(&tstr)) return(1); - } else if (*tstr == '[') { - tstr++; - if (find_bracket(&tstr)) return(1); - } else if (*tstr == '{') { - tstr++; - if (find_curlybracket(&tstr)) return(1); - } else if (*tstr == '"') { - tstr++; - if (find_doublequote(&tstr)) return(1); - } else if (*tstr == '\'') { - tstr++; - if (find_quote(&tstr)) return(1); - } else { - tstr++; - } - } - return(1); /* opps, didn't find the closing character */ -} -/*--------------------------------------------------------------------------*/ -int comma2semicolon(char *string) - -/* - replace commas with semicolons, unless the comma is within a quoted or bracketed expression -*/ -{ - char *tstr; - - tstr = string; - - while (*tstr) { - - if (*tstr == ',') { /* found a comma */ - *tstr = ';'; - tstr++; - } else if (*tstr == '(') { /* found another level of parens */ - tstr++; - if (find_paren(&tstr)) return(1); - } else if (*tstr == '[') { - tstr++; - if (find_bracket(&tstr)) return(1); - } else if (*tstr == '{') { - tstr++; - if (find_curlybracket(&tstr)) return(1); - } else if (*tstr == '"') { - tstr++; - if (find_doublequote(&tstr)) return(1); - } else if (*tstr == '\'') { - tstr++; - if (find_quote(&tstr)) return(1); - } else { - tstr++; - } - } - return(0); /* reached end of string */ -} -/*--------------------------------------------------------------------------*/ -int ffedit_columns( - fitsfile **fptr, /* IO - pointer to input table; on output it */ - /* points to the new selected rows table */ - char *outfile, /* I - name for output file */ - char *expr, /* I - column edit expression */ - int *status) -/* - modify columns in a table and/or header keywords in the HDU -*/ -{ - fitsfile *newptr; - int ii, hdunum, slen, colnum = -1, testnum, deletecol = 0, savecol = 0; - int numcols = 0, *colindex = 0, tstatus = 0; - char *cptr, *cptr2, *cptr3, *clause = NULL, keyname[FLEN_KEYWORD]; - char colname[FLEN_VALUE], oldname[FLEN_VALUE], colformat[FLEN_VALUE]; - char *file_expr = NULL, testname[FLEN_VALUE], card[FLEN_CARD]; - - if (*outfile) - { - /* create new empty file in to hold the selected rows */ - if (ffinit(&newptr, outfile, status) > 0) - { - ffpmsg("failed to create file for copy (ffedit_columns)"); - return(*status); - } - - fits_get_hdu_num(*fptr, &hdunum); /* current HDU number in input file */ - - /* copy all HDUs to the output copy, if the 'only_one' flag is not set */ - if (!((*fptr)->Fptr)->only_one) { - for (ii = 1; 1; ii++) - { - if (fits_movabs_hdu(*fptr, ii, NULL, status) > 0) - break; - - fits_copy_hdu(*fptr, newptr, 0, status); - } - - if (*status == END_OF_FILE) - { - *status = 0; /* got the expected EOF error; reset = 0 */ - } - else if (*status > 0) - { - ffclos(newptr, status); - ffpmsg("failed to copy all HDUs from input file (ffedit_columns)"); - return(*status); - } - - - } else { - /* only copy the primary array and the designated table extension */ - fits_movabs_hdu(*fptr, 1, NULL, status); - fits_copy_hdu(*fptr, newptr, 0, status); - fits_movabs_hdu(*fptr, hdunum, NULL, status); - fits_copy_hdu(*fptr, newptr, 0, status); - if (*status > 0) - { - ffclos(newptr, status); - ffpmsg("failed to copy all HDUs from input file (ffedit_columns)"); - return(*status); - } - hdunum = 2; - } - - /* close the original file and return ptr to the new image */ - ffclos(*fptr, status); - - *fptr = newptr; /* reset the pointer to the new table */ - - /* move back to the selected table HDU */ - if (fits_movabs_hdu(*fptr, hdunum, NULL, status) > 0) - { - ffpmsg("failed to copy the input file (ffedit_columns)"); - return(*status); - } - } - - /* remove the "col " from the beginning of the column edit expression */ - cptr = expr + 4; - - while (*cptr == ' ') - cptr++; /* skip leading white space */ - - /* Check if need to import expression from a file */ - - if( *cptr=='@' ) { - if( ffimport_file( cptr+1, &file_expr, status ) ) return(*status); - cptr = file_expr; - while (*cptr == ' ') - cptr++; /* skip leading white space... again */ - } - - tstatus = 0; - ffgncl(*fptr, &numcols, &tstatus); /* get initial # of cols */ - - /* as of July 2012, the CFITSIO column filter syntax was modified */ - /* so that commas may be used to separate clauses, as well as semi-colons. */ - /* This was done because users cannot enter the semi-colon in the HEASARC's */ - /* Hera on-line data processing system for computer security reasons. */ - /* Therefore, we must convert those commas back to semi-colons here, but we */ - /* must not convert any columns that occur within parenthesies. */ - - if (comma2semicolon(cptr)) { - ffpmsg("parsing error in column filter expression"); - ffpmsg(cptr); - if( file_expr ) free( file_expr ); - *status = PARSE_SYNTAX_ERR; - return(*status); - } - - /* parse expression and get first clause, if more than 1 */ - while ((slen = fits_get_token2(&cptr, ";", &clause, NULL, status)) > 0 ) - { - if( *cptr==';' ) cptr++; - clause[slen] = '\0'; - - if (clause[0] == '!' || clause[0] == '-') - { - /* ===================================== */ - /* Case I. delete this column or keyword */ - /* ===================================== */ - - if (ffgcno(*fptr, CASEINSEN, &clause[1], &colnum, status) <= 0) - { - /* a column with this name exists, so try to delete it */ - if (ffdcol(*fptr, colnum, status) > 0) - { - ffpmsg("failed to delete column in input file:"); - ffpmsg(clause); - if( colindex ) free( colindex ); - if( file_expr ) free( file_expr ); - if( clause ) free(clause); - return(*status); - } - deletecol = 1; /* set flag that at least one col was deleted */ - numcols--; - colnum = -1; - } - else - { - ffcmsg(); /* clear previous error message from ffgcno */ - /* try deleting a keyword with this name */ - *status = 0; - if (ffdkey(*fptr, &clause[1], status) > 0) - { - ffpmsg("column or keyword to be deleted does not exist:"); - ffpmsg(clause); - if( colindex ) free( colindex ); - if( file_expr ) free( file_expr ); - if( clause ) free(clause); - return(*status); - } - } - } - else - { - /* ===================================================== */ - /* Case II: - this is either a column name, (case 1) - - or a new column name followed by double = ("==") followed - by the old name which is to be renamed. (case 2A) - - or a column or keyword name followed by a single "=" and a - calculation expression (case 2B) */ - /* ===================================================== */ - cptr2 = clause; - slen = fits_get_token(&cptr2, "( =", colname, NULL); - - if (slen == 0) - { - ffpmsg("error: column or keyword name is blank:"); - ffpmsg(clause); - if( colindex ) free( colindex ); - if( file_expr ) free( file_expr ); - if (clause) free(clause); - return(*status= URL_PARSE_ERROR); - } - - /* If this is a keyword of the form - #KEYWORD# - then transform to the form - #KEYWORDn - where n is the previously used column number - */ - if (colname[0] == '#' && - strstr(colname+1, "#") == (colname + strlen(colname) - 1)) - { - if (colnum <= 0) - { - ffpmsg("The keyword name:"); - ffpmsg(colname); - ffpmsg("is invalid unless a column has been previously"); - ffpmsg("created or editted by a calculator command"); - if( file_expr ) free( file_expr ); - if (clause) free(clause); - return(*status = URL_PARSE_ERROR); - } - colname[strlen(colname)-1] = '\0'; - /* Make keyword name and put it in oldname */ - ffkeyn(colname+1, colnum, oldname, status); - if (*status) return (*status); - /* Re-copy back into colname */ - strcpy(colname+1,oldname); - } - else if (strstr(colname, "#") == (colname + strlen(colname) - 1)) - { - /* colname is of the form "NAME#"; if - a) colnum is defined, and - b) a column with literal name "NAME#" does not exist, and - c) a keyword with name "NAMEn" (where n=colnum) exists, then - transfrom the colname string to "NAMEn", otherwise - do nothing. - */ - if (colnum > 0) { /* colnum must be defined */ - tstatus = 0; - ffgcno(*fptr, CASEINSEN, colname, &testnum, &tstatus); - if (tstatus != 0 && tstatus != COL_NOT_UNIQUE) - { - /* OK, column doesn't exist, now see if keyword exists */ - ffcmsg(); /* clear previous error message from ffgcno */ - strcpy(testname, colname); - testname[strlen(testname)-1] = '\0'; - /* Make keyword name and put it in oldname */ - ffkeyn(testname, colnum, oldname, status); - if (*status) { - if( file_expr ) free( file_expr ); - if (clause) free(clause); - return (*status); - } - - tstatus = 0; - if (!fits_read_card(*fptr, oldname, card, &tstatus)) { - /* Keyword does exist; copy real name back into colname */ - strcpy(colname,oldname); - } - } - } - } - - /* if we encountered an opening parenthesis, then we need to */ - /* find the closing parenthesis, and concatinate the 2 strings */ - /* This supports expressions like: - [col #EXTNAME(Extension name)="GTI"] - */ - if (*cptr2 == '(') - { - fits_get_token(&cptr2, ")", oldname, NULL); - strcat(colname, oldname); - strcat(colname, ")"); - cptr2++; - } - - while (*cptr2 == ' ') - cptr2++; /* skip white space */ - - if (*cptr2 != '=') - { - /* ------------------------------------ */ - /* case 1 - simply the name of a column */ - /* ------------------------------------ */ - - /* look for matching column */ - ffgcno(*fptr, CASEINSEN, colname, &testnum, status); - - while (*status == COL_NOT_UNIQUE) - { - /* the column name contained wild cards, and it */ - /* matches more than one column in the table. */ - - colnum = testnum; - - /* keep this column in the output file */ - savecol = 1; - - if (!colindex) - colindex = (int *) calloc(999, sizeof(int)); - - colindex[colnum - 1] = 1; /* flag this column number */ - - /* look for other matching column names */ - ffgcno(*fptr, CASEINSEN, colname, &testnum, status); - - if (*status == COL_NOT_FOUND) - *status = 999; /* temporary status flag value */ - } - - if (*status <= 0) - { - colnum = testnum; - - /* keep this column in the output file */ - savecol = 1; - - if (!colindex) - colindex = (int *) calloc(999, sizeof(int)); - - colindex[colnum - 1] = 1; /* flag this column number */ - } - else if (*status == 999) - { - /* this special flag value does not represent an error */ - *status = 0; - } - else - { - ffpmsg("Syntax error in columns specifier in input URL:"); - ffpmsg(cptr2); - if( colindex ) free( colindex ); - if( file_expr ) free( file_expr ); - if (clause) free(clause); - return(*status = URL_PARSE_ERROR); - } - } - else - { - /* ----------------------------------------------- */ - /* case 2 where the token ends with an equals sign */ - /* ----------------------------------------------- */ - - cptr2++; /* skip over the first '=' */ - - if (*cptr2 == '=') - { - /*................................................. */ - /* Case A: rename a column or keyword; syntax is - "new_name == old_name" */ - /*................................................. */ - - cptr2++; /* skip the 2nd '=' */ - while (*cptr2 == ' ') - cptr2++; /* skip white space */ - - fits_get_token(&cptr2, " ", oldname, NULL); - - /* get column number of the existing column */ - if (ffgcno(*fptr, CASEINSEN, oldname, &colnum, status) <= 0) - { - /* modify the TTYPEn keyword value with the new name */ - ffkeyn("TTYPE", colnum, keyname, status); - - if (ffmkys(*fptr, keyname, colname, NULL, status) > 0) - { - ffpmsg("failed to rename column in input file"); - ffpmsg(" oldname ="); - ffpmsg(oldname); - ffpmsg(" newname ="); - ffpmsg(colname); - if( colindex ) free( colindex ); - if( file_expr ) free( file_expr ); - if (clause) free(clause); - return(*status); - } - /* keep this column in the output file */ - savecol = 1; - if (!colindex) - colindex = (int *) calloc(999, sizeof(int)); - - colindex[colnum - 1] = 1; /* flag this column number */ - } - else - { - /* try renaming a keyword */ - ffcmsg(); /* clear error message stack */ - *status = 0; - if (ffmnam(*fptr, oldname, colname, status) > 0) - { - ffpmsg("column or keyword to be renamed does not exist:"); - ffpmsg(clause); - if( colindex ) free( colindex ); - if( file_expr ) free( file_expr ); - if (clause) free(clause); - return(*status); - } - } - } - else - { - /*...................................................... */ - /* Case B: */ - /* this must be a general column/keyword calc expression */ - /* "name = expression" or "colname(TFORM) = expression" */ - /*...................................................... */ - - /* parse the name and TFORM values, if present */ - colformat[0] = '\0'; - cptr3 = colname; - - fits_get_token(&cptr3, "(", oldname, NULL); - - if (cptr3[0] == '(' ) - { - cptr3++; /* skip the '(' */ - fits_get_token(&cptr3, ")", colformat, NULL); - } - - /* calculate values for the column or keyword */ - /* cptr2 = the expression to be calculated */ - /* oldname = name of the column or keyword */ - /* colformat = column format, or keyword comment string */ - if (fits_calculator(*fptr, cptr2, *fptr, oldname, colformat, - status) > 0) { - - ffpmsg("Unable to calculate expression"); - if( colindex ) free( colindex ); - if( file_expr ) free( file_expr ); - if (clause) free(clause); - return(*status); - } - - /* test if this is a column and not a keyword */ - tstatus = 0; - ffgcno(*fptr, CASEINSEN, oldname, &testnum, &tstatus); - if (tstatus == 0) - { - /* keep this column in the output file */ - colnum = testnum; - savecol = 1; - - if (!colindex) - colindex = (int *) calloc(999, sizeof(int)); - - colindex[colnum - 1] = 1; - if (colnum > numcols)numcols++; - } - else - { - ffcmsg(); /* clear the error message stack */ - } - } - } - } - if (clause) free(clause); /* free old clause before getting new one */ - clause = NULL; - } - - if (savecol && !deletecol) - { - /* need to delete all but the specified columns */ - for (ii = numcols; ii > 0; ii--) - { - if (!colindex[ii-1]) /* delete this column */ - { - if (ffdcol(*fptr, ii, status) > 0) - { - ffpmsg("failed to delete column in input file:"); - ffpmsg(clause); - if( colindex ) free( colindex ); - if( file_expr ) free( file_expr ); - if (clause) free(clause); - return(*status); - } - } - } - } - - if( colindex ) free( colindex ); - if( file_expr ) free( file_expr ); - if (clause) free(clause); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_copy_cell2image( - fitsfile *fptr, /* I - point to input table */ - fitsfile *newptr, /* O - existing output file; new image HDU - will be appended to it */ - char *colname, /* I - column name / number containing the image*/ - long rownum, /* I - number of the row containing the image */ - int *status) /* IO - error status */ - -/* - Copy a table cell of a given row and column into an image extension. - The output file must already have been created. A new image - extension will be created in that file. - - This routine was written by Craig Markwardt, GSFC -*/ - -{ - unsigned char buffer[30000]; - int hdutype, colnum, typecode, bitpix, naxis, maxelem, tstatus; - LONGLONG naxes[9], nbytes, firstbyte, ntodo; - LONGLONG repeat, startpos, elemnum, rowlen, tnull; - long twidth, incre; - double scale, zero; - char tform[20]; - char card[FLEN_CARD]; - char templt[FLEN_CARD] = ""; - - /* Table-to-image keyword translation table */ - /* INPUT OUTPUT */ - /* 01234567 01234567 */ - char *patterns[][2] = {{"TSCALn", "BSCALE" }, /* Standard FITS keywords */ - {"TZEROn", "BZERO" }, - {"TUNITn", "BUNIT" }, - {"TNULLn", "BLANK" }, - {"TDMINn", "DATAMIN" }, - {"TDMAXn", "DATAMAX" }, - {"iCTYPn", "CTYPEi" }, /* Coordinate labels */ - {"iCTYna", "CTYPEia" }, - {"iCUNIn", "CUNITi" }, /* Coordinate units */ - {"iCUNna", "CUNITia" }, - {"iCRVLn", "CRVALi" }, /* WCS keywords */ - {"iCRVna", "CRVALia" }, - {"iCDLTn", "CDELTi" }, - {"iCDEna", "CDELTia" }, - {"iCRPXn", "CRPIXi" }, - {"iCRPna", "CRPIXia" }, - {"ijPCna", "PCi_ja" }, - {"ijCDna", "CDi_ja" }, - {"iVn_ma", "PVi_ma" }, - {"iSn_ma", "PSi_ma" }, - {"iCRDna", "CRDERia" }, - {"iCSYna", "CSYERia" }, - {"iCROTn", "CROTAi" }, - {"WCAXna", "WCSAXESa"}, - {"WCSNna", "WCSNAMEa"}, - - {"LONPna", "LONPOLEa"}, - {"LATPna", "LATPOLEa"}, - {"EQUIna", "EQUINOXa"}, - {"MJDOBn", "MJD-OBS" }, - {"MJDAn", "MJD-AVG" }, - {"RADEna", "RADESYSa"}, - {"iCNAna", "CNAMEia" }, - {"DAVGn", "DATE-AVG"}, - - /* Delete table keywords related to other columns */ - {"T????#a", "-" }, - {"TC??#a", "-" }, - {"TWCS#a", "-" }, - {"TDIM#", "-" }, - {"iCTYPm", "-" }, - {"iCUNIm", "-" }, - {"iCRVLm", "-" }, - {"iCDLTm", "-" }, - {"iCRPXm", "-" }, - {"iCTYma", "-" }, - {"iCUNma", "-" }, - {"iCRVma", "-" }, - {"iCDEma", "-" }, - {"iCRPma", "-" }, - {"ijPCma", "-" }, - {"ijCDma", "-" }, - {"iVm_ma", "-" }, - {"iSm_ma", "-" }, - {"iCRDma", "-" }, - {"iCSYma", "-" }, - {"iCROTm", "-" }, - {"WCAXma", "-" }, - {"WCSNma", "-" }, - - {"LONPma", "-" }, - {"LATPma", "-" }, - {"EQUIma", "-" }, - {"MJDOBm", "-" }, - {"MJDAm", "-" }, - {"RADEma", "-" }, - {"iCNAma", "-" }, - {"DAVGm", "-" }, - - {"EXTNAME", "-" }, /* Remove structural keywords*/ - {"EXTVER", "-" }, - {"EXTLEVEL","-" }, - {"CHECKSUM","-" }, - {"DATASUM", "-" }, - - {"*", "+" }}; /* copy all other keywords */ - int npat; - - if (*status > 0) - return(*status); - - /* get column number */ - if (ffgcno(fptr, CASEINSEN, colname, &colnum, status) > 0) - { - ffpmsg("column containing image in table cell does not exist:"); - ffpmsg(colname); - return(*status); - } - - /*---------------------------------------------------*/ - /* Check input and get parameters about the column: */ - /*---------------------------------------------------*/ - if ( ffgcprll(fptr, colnum, rownum, 1L, 1L, 0, &scale, &zero, - tform, &twidth, &typecode, &maxelem, &startpos, &elemnum, &incre, - &repeat, &rowlen, &hdutype, &tnull, (char *) buffer, status) > 0 ) - return(*status); - - /* get the actual column name, in case a column number was given */ - ffkeyn("", colnum, templt, &tstatus); - ffgcnn(fptr, CASEINSEN, templt, colname, &colnum, &tstatus); - - if (hdutype != BINARY_TBL) - { - ffpmsg("This extension is not a binary table."); - ffpmsg(" Cannot open the image in a binary table cell."); - return(*status = NOT_BTABLE); - } - - if (typecode < 0) - { - /* variable length array */ - typecode *= -1; - - /* variable length arrays are 1-dimensional by default */ - naxis = 1; - naxes[0] = repeat; - } - else - { - /* get the dimensions of the image */ - ffgtdmll(fptr, colnum, 9, &naxis, naxes, status); - } - - if (*status > 0) - { - ffpmsg("Error getting the dimensions of the image"); - return(*status); - } - - /* determine BITPIX value for the image */ - if (typecode == TBYTE) - { - bitpix = BYTE_IMG; - nbytes = repeat; - } - else if (typecode == TSHORT) - { - bitpix = SHORT_IMG; - nbytes = repeat * 2; - } - else if (typecode == TLONG) - { - bitpix = LONG_IMG; - nbytes = repeat * 4; - } - else if (typecode == TFLOAT) - { - bitpix = FLOAT_IMG; - nbytes = repeat * 4; - } - else if (typecode == TDOUBLE) - { - bitpix = DOUBLE_IMG; - nbytes = repeat * 8; - } - else if (typecode == TLONGLONG) - { - bitpix = LONGLONG_IMG; - nbytes = repeat * 8; - } - else if (typecode == TLOGICAL) - { - bitpix = BYTE_IMG; - nbytes = repeat; - } - else - { - ffpmsg("Error: the following image column has invalid datatype:"); - ffpmsg(colname); - ffpmsg(tform); - ffpmsg("Cannot open an image in a single row of this column."); - return(*status = BAD_TFORM); - } - - /* create new image in output file */ - if (ffcrimll(newptr, bitpix, naxis, naxes, status) > 0) - { - ffpmsg("failed to write required primary array keywords in the output file"); - return(*status); - } - - npat = sizeof(patterns)/sizeof(patterns[0][0])/2; - - /* skip over the first 8 keywords, starting just after TFIELDS */ - fits_translate_keywords(fptr, newptr, 9, patterns, npat, - colnum, 0, 0, status); - - /* add some HISTORY */ - sprintf(card,"HISTORY This image was copied from row %ld of column '%s',", - rownum, colname); -/* disable this; leave it up to the caller to write history if needed. - ffprec(newptr, card, status); -*/ - /* the use of ffread routine, below, requires that any 'dirty' */ - /* buffers in memory be flushed back to the file first */ - - ffflsh(fptr, FALSE, status); - - /* finally, copy the data, one buffer size at a time */ - ffmbyt(fptr, startpos, TRUE, status); - firstbyte = 1; - - /* the upper limit on the number of bytes must match the declaration */ - /* read up to the first 30000 bytes in the normal way with ffgbyt */ - - ntodo = minvalue(30000, nbytes); - ffgbyt(fptr, ntodo, buffer, status); - ffptbb(newptr, 1, firstbyte, ntodo, buffer, status); - - nbytes -= ntodo; - firstbyte += ntodo; - - /* read any additional bytes with low-level ffread routine, for speed */ - while (nbytes && (*status <= 0) ) - { - ntodo = minvalue(30000, nbytes); - ffread((fptr)->Fptr, (long) ntodo, buffer, status); - ffptbb(newptr, 1, firstbyte, ntodo, buffer, status); - nbytes -= ntodo; - firstbyte += ntodo; - } - - /* Re-scan the header so that CFITSIO knows about all the new keywords */ - ffrdef(newptr,status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_copy_image2cell( - fitsfile *fptr, /* I - pointer to input image extension */ - fitsfile *newptr, /* I - pointer to output table */ - char *colname, /* I - name of column containing the image */ - long rownum, /* I - number of the row containing the image */ - int copykeyflag, /* I - controls which keywords to copy */ - int *status) /* IO - error status */ - -/* - Copy an image extension into a table cell at a given row and - column. The table must have already been created. If the "colname" - column exists, it will be used, otherwise a new column will be created - in the table. - - The "copykeyflag" parameter controls which keywords to copy from the - input image to the output table header (with any appropriate translation). - - copykeyflag = 0 -- no keywords will be copied - copykeyflag = 1 -- essentially all keywords will be copied - copykeyflag = 2 -- copy only the WCS related keywords - - This routine was written by Craig Markwardt, GSFC - -*/ -{ - tcolumn *colptr; - unsigned char buffer[30000]; - int ii, hdutype, colnum, typecode, bitpix, naxis, ncols, hdunum; - char tformchar, tform[20], card[FLEN_CARD]; - LONGLONG imgstart, naxes[9], nbytes, repeat, ntodo,firstbyte; - char filename[FLEN_FILENAME+20]; - - int npat; - - int naxis1; - LONGLONG naxes1[9] = {0,0,0,0,0,0,0,0,0}, repeat1, width1; - int typecode1; - unsigned char dummy = 0; - - LONGLONG headstart, datastart, dataend; - - /* Image-to-table keyword translation table */ - /* INPUT OUTPUT */ - /* 01234567 01234567 */ - char *patterns[][2] = {{"BSCALE", "TSCALn" }, /* Standard FITS keywords */ - {"BZERO", "TZEROn" }, - {"BUNIT", "TUNITn" }, - {"BLANK", "TNULLn" }, - {"DATAMIN", "TDMINn" }, - {"DATAMAX", "TDMAXn" }, - {"CTYPEi", "iCTYPn" }, /* Coordinate labels */ - {"CTYPEia", "iCTYna" }, - {"CUNITi", "iCUNIn" }, /* Coordinate units */ - {"CUNITia", "iCUNna" }, - {"CRVALi", "iCRVLn" }, /* WCS keywords */ - {"CRVALia", "iCRVna" }, - {"CDELTi", "iCDLTn" }, - {"CDELTia", "iCDEna" }, - {"CRPIXj", "jCRPXn" }, - {"CRPIXja", "jCRPna" }, - {"PCi_ja", "ijPCna" }, - {"CDi_ja", "ijCDna" }, - {"PVi_ma", "iVn_ma" }, - {"PSi_ma", "iSn_ma" }, - {"WCSAXESa","WCAXna" }, - {"WCSNAMEa","WCSNna" }, - {"CRDERia", "iCRDna" }, - {"CSYERia", "iCSYna" }, - {"CROTAi", "iCROTn" }, - - {"LONPOLEa","LONPna"}, - {"LATPOLEa","LATPna"}, - {"EQUINOXa","EQUIna"}, - {"MJD-OBS", "MJDOBn" }, - {"MJD-AVG", "MJDAn" }, - {"RADESYSa","RADEna"}, - {"CNAMEia", "iCNAna" }, - {"DATE-AVG","DAVGn"}, - - {"NAXISi", "-" }, /* Remove structural keywords*/ - {"PCOUNT", "-" }, - {"GCOUNT", "-" }, - {"EXTEND", "-" }, - {"EXTNAME", "-" }, - {"EXTVER", "-" }, - {"EXTLEVEL","-" }, - {"CHECKSUM","-" }, - {"DATASUM", "-" }, - {"*", "+" }}; /* copy all other keywords */ - - - if (*status > 0) - return(*status); - - if (fptr == 0 || newptr == 0) return (*status = NULL_INPUT_PTR); - - if (ffghdt(fptr, &hdutype, status) > 0) { - ffpmsg("could not get input HDU type"); - return (*status); - } - - if (hdutype != IMAGE_HDU) { - ffpmsg("The input extension is not an image."); - ffpmsg(" Cannot open the image."); - return(*status = NOT_IMAGE); - } - - if (ffghdt(newptr, &hdutype, status) > 0) { - ffpmsg("could not get output HDU type"); - return (*status); - } - - if (hdutype != BINARY_TBL) { - ffpmsg("The output extension is not a table."); - return(*status = NOT_BTABLE); - } - - - if (ffgiprll(fptr, 9, &bitpix, &naxis, naxes, status) > 0) { - ffpmsg("Could not read image parameters."); - return (*status); - } - - /* Determine total number of pixels in the image */ - repeat = 1; - for (ii = 0; ii < naxis; ii++) repeat *= naxes[ii]; - - /* Determine the TFORM value for the table cell */ - if (bitpix == BYTE_IMG) { - typecode = TBYTE; - tformchar = 'B'; - nbytes = repeat; - } else if (bitpix == SHORT_IMG) { - typecode = TSHORT; - tformchar = 'I'; - nbytes = repeat*2; - } else if (bitpix == LONG_IMG) { - typecode = TLONG; - tformchar = 'J'; - nbytes = repeat*4; - } else if (bitpix == FLOAT_IMG) { - typecode = TFLOAT; - tformchar = 'E'; - nbytes = repeat*4; - } else if (bitpix == DOUBLE_IMG) { - typecode = TDOUBLE; - tformchar = 'D'; - nbytes = repeat*8; - } else if (bitpix == LONGLONG_IMG) { - typecode = TLONGLONG; - tformchar = 'K'; - nbytes = repeat*8; - } else { - ffpmsg("Error: the image has an invalid datatype."); - return (*status = BAD_BITPIX); - } - - /* get column number */ - ffpmrk(); - ffgcno(newptr, CASEINSEN, colname, &colnum, status); - ffcmrk(); - - /* Column does not exist; create it */ - if (*status) { - - *status = 0; - sprintf(tform, "%.0f%c", (double) repeat, tformchar); - ffgncl(newptr, &ncols, status); - colnum = ncols+1; - fficol(newptr, colnum, colname, tform, status); - ffptdmll(newptr, colnum, naxis, naxes, status); - - if (*status) { - ffpmsg("Could not insert new column into output table."); - return *status; - } - - } else { - - ffgtdmll(newptr, colnum, 9, &naxis1, naxes1, status); - if (*status > 0 || naxis != naxis1) { - ffpmsg("Input image dimensions and output table cell dimensions do not match."); - return (*status = BAD_DIMEN); - } - for (ii=0; ii 0) || (typecode1 != typecode) || (repeat1 != repeat)) { - ffpmsg("Input image data type does not match output table cell type."); - return (*status = BAD_TFORM); - } - } - - /* copy keywords from input image to output table, if required */ - - if (copykeyflag) { - - npat = sizeof(patterns)/sizeof(patterns[0][0])/2; - - if (copykeyflag == 2) { /* copy only the WCS-related keywords */ - patterns[npat-1][1] = "-"; - } - - /* The 3rd parameter value = 5 means skip the first 4 keywords in the image */ - fits_translate_keywords(fptr, newptr, 5, patterns, npat, - colnum, 0, 0, status); - } - - /* Here is all the code to compute offsets: - * * byte offset from start of row to column (dest table) - * * byte offset from start of file to image data (source image) - */ - - /* Force the writing of the row of the table by writing the last byte of - the array, which grows the table, and/or shifts following extensions */ - ffpcl(newptr, TBYTE, colnum, rownum, repeat, 1, &dummy, status); - - /* byte offset within the row to the start of the image column */ - colptr = (newptr->Fptr)->tableptr; /* point to first column */ - colptr += (colnum - 1); /* offset to correct column structure */ - firstbyte = colptr->tbcol + 1; - - /* get starting address of input image to be read */ - ffghadll(fptr, &headstart, &datastart, &dataend, status); - imgstart = datastart; - - sprintf(card, "HISTORY Table column '%s' row %ld copied from image", - colname, rownum); -/* - Don't automatically write History keywords; leave this up to the caller. - ffprec(newptr, card, status); -*/ - - /* write HISTORY keyword with the file name (this is now disabled)*/ - - filename[0] = '\0'; hdunum = 0; - strcpy(filename, "HISTORY "); - ffflnm(fptr, filename+strlen(filename), status); - ffghdn(fptr, &hdunum); - sprintf(filename+strlen(filename),"[%d]", hdunum-1); -/* - ffprec(newptr, filename, status); -*/ - - /* the use of ffread routine, below, requires that any 'dirty' */ - /* buffers in memory be flushed back to the file first */ - - ffflsh(fptr, FALSE, status); - - /* move to the first byte of the input image */ - ffmbyt(fptr, imgstart, TRUE, status); - - ntodo = minvalue(30000L, nbytes); - ffgbyt(fptr, ntodo, buffer, status); /* read input image */ - ffptbb(newptr, rownum, firstbyte, ntodo, buffer, status); /* write to table */ - - nbytes -= ntodo; - firstbyte += ntodo; - - - /* read any additional bytes with low-level ffread routine, for speed */ - while (nbytes && (*status <= 0) ) - { - ntodo = minvalue(30000L, nbytes); - ffread(fptr->Fptr, (long) ntodo, buffer, status); - ffptbb(newptr, rownum, firstbyte, ntodo, buffer, status); - nbytes -= ntodo; - firstbyte += ntodo; - } - - /* Re-scan the header so that CFITSIO knows about all the new keywords */ - ffrdef(newptr,status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_select_image_section( - fitsfile **fptr, /* IO - pointer to input image; on output it */ - /* points to the new subimage */ - char *outfile, /* I - name for output file */ - char *expr, /* I - Image section expression */ - int *status) -{ - /* - copies an image section from the input file to a new output file. - Any HDUs preceding or following the image are also copied to the - output file. - */ - - fitsfile *newptr; - int ii, hdunum; - - /* create new empty file to hold the image section */ - if (ffinit(&newptr, outfile, status) > 0) - { - ffpmsg( - "failed to create output file for image section:"); - ffpmsg(outfile); - return(*status); - } - - fits_get_hdu_num(*fptr, &hdunum); /* current HDU number in input file */ - - /* copy all preceding extensions to the output file, if 'only_one' flag not set */ - if (!(((*fptr)->Fptr)->only_one)) { - for (ii = 1; ii < hdunum; ii++) - { - fits_movabs_hdu(*fptr, ii, NULL, status); - if (fits_copy_hdu(*fptr, newptr, 0, status) > 0) - { - ffclos(newptr, status); - return(*status); - } - } - - /* move back to the original HDU position */ - fits_movabs_hdu(*fptr, hdunum, NULL, status); - } - - if (fits_copy_image_section(*fptr, newptr, expr, status) > 0) - { - ffclos(newptr, status); - return(*status); - } - - /* copy any remaining HDUs to the output file, if 'only_one' flag not set */ - - if (!(((*fptr)->Fptr)->only_one)) { - for (ii = hdunum + 1; 1; ii++) - { - if (fits_movabs_hdu(*fptr, ii, NULL, status) > 0) - break; - - fits_copy_hdu(*fptr, newptr, 0, status); - } - - if (*status == END_OF_FILE) - *status = 0; /* got the expected EOF error; reset = 0 */ - else if (*status > 0) - { - ffclos(newptr, status); - return(*status); - } - } else { - ii = hdunum + 1; /* this value of ii is required below */ - } - - /* close the original file and return ptr to the new image */ - ffclos(*fptr, status); - - *fptr = newptr; /* reset the pointer to the new table */ - - /* move back to the image subsection */ - if (ii - 1 != hdunum) - fits_movabs_hdu(*fptr, hdunum, NULL, status); - else - { - /* may have to reset BSCALE and BZERO pixel scaling, */ - /* since the keywords were previously turned off */ - - if (ffrdef(*fptr, status) > 0) - { - ffclos(*fptr, status); - return(*status); - } - - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_copy_image_section( - fitsfile *fptr, /* I - pointer to input image */ - fitsfile *newptr, /* I - pointer to output image */ - char *expr, /* I - Image section expression */ - int *status) -{ - /* - copies an image section from the input file to a new output HDU - */ - - int bitpix, naxis, numkeys, nkey; - long naxes[] = {1,1,1,1,1,1,1,1,1}, smin, smax, sinc; - long fpixels[] = {1,1,1,1,1,1,1,1,1}; - long lpixels[] = {1,1,1,1,1,1,1,1,1}; - long incs[] = {1,1,1,1,1,1,1,1,1}; - char *cptr, keyname[FLEN_KEYWORD], card[FLEN_CARD]; - int ii, tstatus, anynull; - long minrow, maxrow, minslice, maxslice, mincube, maxcube; - long firstpix; - long ncubeiter, nsliceiter, nrowiter, kiter, jiter, iiter; - int klen, kk, jj; - long outnaxes[9], outsize, buffsize; - double *buffer, crpix, cdelt; - - if (*status > 0) - return(*status); - - /* get the size of the input image */ - fits_get_img_type(fptr, &bitpix, status); - fits_get_img_dim(fptr, &naxis, status); - if (fits_get_img_size(fptr, naxis, naxes, status) > 0) - return(*status); - - if (naxis < 1 || naxis > 4) - { - ffpmsg( - "Input image either had NAXIS = 0 (NULL image) or has > 4 dimensions"); - return(*status = BAD_NAXIS); - } - - /* create output image with same size and type as the input image */ - /* Will update the size later */ - fits_create_img(newptr, bitpix, naxis, naxes, status); - - /* copy all other non-structural keywords from the input to output file */ - fits_get_hdrspace(fptr, &numkeys, NULL, status); - - for (nkey = 4; nkey <= numkeys; nkey++) /* skip the first few keywords */ - { - fits_read_record(fptr, nkey, card, status); - - if (fits_get_keyclass(card) > TYP_CMPRS_KEY) - { - /* write the record to the output file */ - fits_write_record(newptr, card, status); - } - } - - if (*status > 0) - { - ffpmsg("error copying header from input image to output image"); - return(*status); - } - - /* parse the section specifier to get min, max, and inc for each axis */ - /* and the size of each output image axis */ - - cptr = expr; - for (ii=0; ii < naxis; ii++) - { - if (fits_get_section_range(&cptr, &smin, &smax, &sinc, status) > 0) - { - ffpmsg("error parsing the following image section specifier:"); - ffpmsg(expr); - return(*status); - } - - if (smax == 0) - smax = naxes[ii]; /* use whole axis by default */ - else if (smin == 0) - smin = naxes[ii]; /* use inverted whole axis */ - - if (smin > naxes[ii] || smax > naxes[ii]) - { - ffpmsg("image section exceeds dimensions of input image:"); - ffpmsg(expr); - return(*status = BAD_NAXIS); - } - - fpixels[ii] = smin; - lpixels[ii] = smax; - incs[ii] = sinc; - - if (smin <= smax) - outnaxes[ii] = (smax - smin + sinc) / sinc; - else - outnaxes[ii] = (smin - smax + sinc) / sinc; - - /* modify the NAXISn keyword */ - fits_make_keyn("NAXIS", ii + 1, keyname, status); - fits_modify_key_lng(newptr, keyname, outnaxes[ii], NULL, status); - - /* modify the WCS keywords if necessary */ - - if (fpixels[ii] != 1 || incs[ii] != 1) - { - for (kk=-1;kk<26; kk++) /* modify any alternate WCS keywords */ - { - /* read the CRPIXn keyword if it exists in the input file */ - fits_make_keyn("CRPIX", ii + 1, keyname, status); - - if (kk != -1) { - klen = strlen(keyname); - keyname[klen]='A' + kk; - keyname[klen + 1] = '\0'; - } - - tstatus = 0; - if (fits_read_key(fptr, TDOUBLE, keyname, - &crpix, NULL, &tstatus) == 0) - { - /* calculate the new CRPIXn value */ - if (fpixels[ii] <= lpixels[ii]) { - crpix = (crpix - (fpixels[ii])) / incs[ii] + 1.0; - /* crpix = (crpix - (fpixels[ii] - 1.0) - .5) / incs[ii] + 0.5; */ - } else { - crpix = (fpixels[ii] - crpix) / incs[ii] + 1.0; - /* crpix = (fpixels[ii] - (crpix - 1.0) - .5) / incs[ii] + 0.5; */ - } - - /* modify the value in the output file */ - fits_modify_key_dbl(newptr, keyname, crpix, 15, NULL, status); - - if (incs[ii] != 1 || fpixels[ii] > lpixels[ii]) - { - /* read the CDELTn keyword if it exists in the input file */ - fits_make_keyn("CDELT", ii + 1, keyname, status); - - if (kk != -1) { - klen = strlen(keyname); - keyname[klen]='A' + kk; - keyname[klen + 1] = '\0'; - } - - tstatus = 0; - if (fits_read_key(fptr, TDOUBLE, keyname, - &cdelt, NULL, &tstatus) == 0) - { - /* calculate the new CDELTn value */ - if (fpixels[ii] <= lpixels[ii]) - cdelt = cdelt * incs[ii]; - else - cdelt = cdelt * (-incs[ii]); - - /* modify the value in the output file */ - fits_modify_key_dbl(newptr, keyname, cdelt, 15, NULL, status); - } - - /* modify the CDi_j keywords if they exist in the input file */ - - fits_make_keyn("CD1_", ii + 1, keyname, status); - - if (kk != -1) { - klen = strlen(keyname); - keyname[klen]='A' + kk; - keyname[klen + 1] = '\0'; - } - - for (jj=0; jj < 9; jj++) /* look for up to 9 dimensions */ - { - keyname[2] = '1' + jj; - - tstatus = 0; - if (fits_read_key(fptr, TDOUBLE, keyname, - &cdelt, NULL, &tstatus) == 0) - { - /* calculate the new CDi_j value */ - if (fpixels[ii] <= lpixels[ii]) - cdelt = cdelt * incs[ii]; - else - cdelt = cdelt * (-incs[ii]); - - /* modify the value in the output file */ - fits_modify_key_dbl(newptr, keyname, cdelt, 15, NULL, status); - } - } - - } /* end of if (incs[ii]... loop */ - } /* end of fits_read_key loop */ - } /* end of for (kk loop */ - } - } /* end of main NAXIS loop */ - - if (ffrdef(newptr, status) > 0) /* force the header to be scanned */ - { - return(*status); - } - - /* turn off any scaling of the pixel values */ - fits_set_bscale(fptr, 1.0, 0.0, status); - fits_set_bscale(newptr, 1.0, 0.0, status); - - /* to reduce memory foot print, just read/write image 1 row at a time */ - - outsize = outnaxes[0]; - buffsize = (abs(bitpix) / 8) * outsize; - - buffer = (double *) malloc(buffsize); /* allocate memory for the image row */ - if (!buffer) - { - ffpmsg("fits_copy_image_section: no memory for image section"); - return(*status = MEMORY_ALLOCATION); - } - - /* read the image section then write it to the output file */ - - minrow = fpixels[1]; - maxrow = lpixels[1]; - if (minrow > maxrow) { - nrowiter = (minrow - maxrow + incs[1]) / incs[1]; - } else { - nrowiter = (maxrow - minrow + incs[1]) / incs[1]; - } - - minslice = fpixels[2]; - maxslice = lpixels[2]; - if (minslice > maxslice) { - nsliceiter = (minslice - maxslice + incs[2]) / incs[2]; - } else { - nsliceiter = (maxslice - minslice + incs[2]) / incs[2]; - } - - mincube = fpixels[3]; - maxcube = lpixels[3]; - if (mincube > maxcube) { - ncubeiter = (mincube - maxcube + incs[3]) / incs[3]; - } else { - ncubeiter = (maxcube - mincube + incs[3]) / incs[3]; - } - - firstpix = 1; - for (kiter = 0; kiter < ncubeiter; kiter++) - { - if (mincube > maxcube) { - fpixels[3] = mincube - (kiter * incs[3]); - } else { - fpixels[3] = mincube + (kiter * incs[3]); - } - - lpixels[3] = fpixels[3]; - - for (jiter = 0; jiter < nsliceiter; jiter++) - { - if (minslice > maxslice) { - fpixels[2] = minslice - (jiter * incs[2]); - } else { - fpixels[2] = minslice + (jiter * incs[2]); - } - - lpixels[2] = fpixels[2]; - - for (iiter = 0; iiter < nrowiter; iiter++) - { - if (minrow > maxrow) { - fpixels[1] = minrow - (iiter * incs[1]); - } else { - fpixels[1] = minrow + (iiter * incs[1]); - } - - lpixels[1] = fpixels[1]; - - if (bitpix == 8) - { - ffgsvb(fptr, 1, naxis, naxes, fpixels, lpixels, incs, 0, - (unsigned char *) buffer, &anynull, status); - - ffpprb(newptr, 1, firstpix, outsize, (unsigned char *) buffer, status); - } - else if (bitpix == 16) - { - ffgsvi(fptr, 1, naxis, naxes, fpixels, lpixels, incs, 0, - (short *) buffer, &anynull, status); - - ffppri(newptr, 1, firstpix, outsize, (short *) buffer, status); - } - else if (bitpix == 32) - { - ffgsvk(fptr, 1, naxis, naxes, fpixels, lpixels, incs, 0, - (int *) buffer, &anynull, status); - - ffpprk(newptr, 1, firstpix, outsize, (int *) buffer, status); - } - else if (bitpix == -32) - { - ffgsve(fptr, 1, naxis, naxes, fpixels, lpixels, incs, FLOATNULLVALUE, - (float *) buffer, &anynull, status); - - ffppne(newptr, 1, firstpix, outsize, (float *) buffer, FLOATNULLVALUE, status); - } - else if (bitpix == -64) - { - ffgsvd(fptr, 1, naxis, naxes, fpixels, lpixels, incs, DOUBLENULLVALUE, - buffer, &anynull, status); - - ffppnd(newptr, 1, firstpix, outsize, buffer, DOUBLENULLVALUE, - status); - } - else if (bitpix == 64) - { - ffgsvjj(fptr, 1, naxis, naxes, fpixels, lpixels, incs, 0, - (LONGLONG *) buffer, &anynull, status); - - ffpprjj(newptr, 1, firstpix, outsize, (LONGLONG *) buffer, status); - } - - firstpix += outsize; - } - } - } - - free(buffer); /* finished with the memory */ - - if (*status > 0) - { - ffpmsg("fits_copy_image_section: error copying image section"); - return(*status); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_get_section_range(char **ptr, - long *secmin, - long *secmax, - long *incre, - int *status) -/* - Parse the input image section specification string, returning - the min, max and increment values. - Typical string = "1:512:2" or "1:512" -*/ -{ - int slen, isanumber; - char token[FLEN_VALUE]; - - if (*status > 0) - return(*status); - - slen = fits_get_token(ptr, " ,:", token, &isanumber); /* get 1st token */ - - /* support [:2,:2] type syntax, where the leading * is implied */ - if (slen==0) strcpy(token,"*"); - - if (*token == '*') /* wild card means to use the whole range */ - { - *secmin = 1; - *secmax = 0; - } - else if (*token == '-' && *(token+1) == '*' ) /* invert the whole range */ - { - *secmin = 0; - *secmax = 1; - } - else - { - if (slen == 0 || !isanumber || **ptr != ':') - return(*status = URL_PARSE_ERROR); - - /* the token contains the min value */ - *secmin = atol(token); - - (*ptr)++; /* skip the colon between the min and max values */ - slen = fits_get_token(ptr, " ,:", token, &isanumber); /* get token */ - - if (slen == 0 || !isanumber) - return(*status = URL_PARSE_ERROR); - - /* the token contains the max value */ - *secmax = atol(token); - } - - if (**ptr == ':') - { - (*ptr)++; /* skip the colon between the max and incre values */ - slen = fits_get_token(ptr, " ,", token, &isanumber); /* get token */ - - if (slen == 0 || !isanumber) - return(*status = URL_PARSE_ERROR); - - *incre = atol(token); - } - else - *incre = 1; /* default increment if none is supplied */ - - if (**ptr == ',') - (*ptr)++; - - while (**ptr == ' ') /* skip any trailing blanks */ - (*ptr)++; - - if (*secmin < 0 || *secmax < 0 || *incre < 1) - *status = URL_PARSE_ERROR; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffselect_table( - fitsfile **fptr, /* IO - pointer to input table; on output it */ - /* points to the new selected rows table */ - char *outfile, /* I - name for output file */ - char *expr, /* I - Boolean expression */ - int *status) -{ - fitsfile *newptr; - int ii, hdunum; - - if (*outfile) - { - /* create new empty file in to hold the selected rows */ - if (ffinit(&newptr, outfile, status) > 0) - { - ffpmsg( - "failed to create file for selected rows from input table"); - ffpmsg(outfile); - return(*status); - } - - fits_get_hdu_num(*fptr, &hdunum); /* current HDU number in input file */ - - /* copy all preceding extensions to the output file, if the 'only_one' flag is not set */ - if (!((*fptr)->Fptr)->only_one) { - for (ii = 1; ii < hdunum; ii++) - { - fits_movabs_hdu(*fptr, ii, NULL, status); - if (fits_copy_hdu(*fptr, newptr, 0, status) > 0) - { - ffclos(newptr, status); - return(*status); - } - } - } else { - /* just copy the primary array */ - fits_movabs_hdu(*fptr, 1, NULL, status); - if (fits_copy_hdu(*fptr, newptr, 0, status) > 0) - { - ffclos(newptr, status); - return(*status); - } - } - - fits_movabs_hdu(*fptr, hdunum, NULL, status); - - /* copy all the header keywords from the input to output file */ - if (fits_copy_header(*fptr, newptr, status) > 0) - { - ffclos(newptr, status); - return(*status); - } - - /* set number of rows = 0 */ - fits_modify_key_lng(newptr, "NAXIS2", 0, NULL,status); - (newptr->Fptr)->numrows = 0; - (newptr->Fptr)->origrows = 0; - - if (ffrdef(newptr, status) > 0) /* force the header to be scanned */ - { - ffclos(newptr, status); - return(*status); - } - } - else - newptr = *fptr; /* will delete rows in place in the table */ - - /* copy rows which satisfy the selection expression to the output table */ - /* or delete the nonqualifying rows if *fptr = newptr. */ - if (fits_select_rows(*fptr, newptr, expr, status) > 0) - { - if (*outfile) - ffclos(newptr, status); - - return(*status); - } - - if (*outfile) - { - /* copy any remaining HDUs to the output copy */ - - if (!((*fptr)->Fptr)->only_one) { - for (ii = hdunum + 1; 1; ii++) - { - if (fits_movabs_hdu(*fptr, ii, NULL, status) > 0) - break; - - fits_copy_hdu(*fptr, newptr, 0, status); - } - - if (*status == END_OF_FILE) - *status = 0; /* got the expected EOF error; reset = 0 */ - else if (*status > 0) - { - ffclos(newptr, status); - return(*status); - } - } else { - hdunum = 2; - } - - /* close the original file and return ptr to the new image */ - ffclos(*fptr, status); - - *fptr = newptr; /* reset the pointer to the new table */ - - /* move back to the selected table HDU */ - fits_movabs_hdu(*fptr, hdunum, NULL, status); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffparsecompspec(fitsfile *fptr, /* I - FITS file pointer */ - char *compspec, /* I - image compression specification */ - int *status) /* IO - error status */ -/* - Parse the image compression specification that was give in square brackets - following the output FITS file name, as in these examples: - - myfile.fits[compress] - default Rice compression, row by row - myfile.fits[compress TYPE] - the first letter of TYPE defines the - compression algorithm: - R = Rice - G = GZIP - H = HCOMPRESS - HS = HCOMPRESS (with smoothing) - B - BZIP2 - P = PLIO - - myfile.fits[compress TYPE 100,100] - the numbers give the dimensions - of the compression tiles. Default - is NAXIS1, 1, 1, ... - - other optional parameters may be specified following a semi-colon - - myfile.fits[compress; q 8.0] q specifies the floating point - mufile.fits[compress TYPE; q -.0002] quantization level; - myfile.fits[compress TYPE 100,100; q 10, s 25] s specifies the HCOMPRESS - integer scaling parameter - -The compression parameters are saved in the fptr->Fptr structure for use -when writing FITS images. - -*/ -{ - char *ptr1; - - /* initialize with default values */ - int ii, compresstype = RICE_1, smooth = 0; - int quantize_method = SUBTRACTIVE_DITHER_1; - long tilesize[MAX_COMPRESS_DIM] = {0,0,0,0,0,0}; - float qlevel = -99., scale = 0.; - - ptr1 = compspec; - while (*ptr1 == ' ') /* ignore leading blanks */ - ptr1++; - - if (strncmp(ptr1, "compress", 8) && strncmp(ptr1, "COMPRESS", 8) ) - { - /* apparently this string does not specify compression parameters */ - return(*status = URL_PARSE_ERROR); - } - - ptr1 += 8; - while (*ptr1 == ' ') /* ignore leading blanks */ - ptr1++; - - /* ========================= */ - /* look for compression type */ - /* ========================= */ - - if (*ptr1 == 'r' || *ptr1 == 'R') - { - compresstype = RICE_1; - while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') - ptr1++; - } - else if (*ptr1 == 'g' || *ptr1 == 'G') - { - compresstype = GZIP_1; - while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') - ptr1++; - - } -/* - else if (*ptr1 == 'b' || *ptr1 == 'B') - { - compresstype = BZIP2_1; - while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') - ptr1++; - - } -*/ - else if (*ptr1 == 'p' || *ptr1 == 'P') - { - compresstype = PLIO_1; - while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') - ptr1++; - } - else if (*ptr1 == 'h' || *ptr1 == 'H') - { - compresstype = HCOMPRESS_1; - ptr1++; - if (*ptr1 == 's' || *ptr1 == 'S') - smooth = 1; /* apply smoothing when uncompressing HCOMPRESSed image */ - - while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') - ptr1++; - } - - /* ======================== */ - /* look for tile dimensions */ - /* ======================== */ - - while (*ptr1 == ' ') /* ignore leading blanks */ - ptr1++; - - ii = 0; - while (isdigit( (int) *ptr1) && ii < 9) - { - tilesize[ii] = atol(ptr1); /* read the integer value */ - ii++; - - while (isdigit((int) *ptr1)) /* skip over the integer */ - ptr1++; - - if (*ptr1 == ',') - ptr1++; /* skip over the comma */ - - while (*ptr1 == ' ') /* ignore leading blanks */ - ptr1++; - } - - /* ========================================================= */ - /* look for semi-colon, followed by other optional parameters */ - /* ========================================================= */ - - if (*ptr1 == ';') { - ptr1++; - while (*ptr1 == ' ') /* ignore leading blanks */ - ptr1++; - - while (*ptr1 != 0) { /* haven't reached end of string yet */ - - if (*ptr1 == 's' || *ptr1 == 'S') { - /* this should be the HCOMPRESS "scale" parameter; default = 1 */ - - ptr1++; - while (*ptr1 == ' ') /* ignore leading blanks */ - ptr1++; - - scale = (float) strtod(ptr1, &ptr1); - - while (*ptr1 == ' ' || *ptr1 == ',') /* skip over blanks or comma */ - ptr1++; - - } else if (*ptr1 == 'q' || *ptr1 == 'Q') { - /* this should be the floating point quantization parameter */ - - ptr1++; - if (*ptr1 == 'z' || *ptr1 == 'Z') { - /* use the subtractive_dither_2 option */ - quantize_method = SUBTRACTIVE_DITHER_2; - ptr1++; - } else if (*ptr1 == '0') { - /* do not dither */ - quantize_method = NO_DITHER; - ptr1++; - } - - while (*ptr1 == ' ') /* ignore leading blanks */ - ptr1++; - - qlevel = (float) strtod(ptr1, &ptr1); - - while (*ptr1 == ' ' || *ptr1 == ',') /* skip over blanks or comma */ - ptr1++; - - } else { - return(*status = URL_PARSE_ERROR); - } - } - } - - /* ================================= */ - /* finished parsing; save the values */ - /* ================================= */ - - fits_set_compression_type(fptr, compresstype, status); - fits_set_tile_dim(fptr, MAX_COMPRESS_DIM, tilesize, status); - - if (compresstype == HCOMPRESS_1) { - fits_set_hcomp_scale (fptr, scale, status); - fits_set_hcomp_smooth(fptr, smooth, status); - } - - if (qlevel != -99.) { - fits_set_quantize_level(fptr, qlevel, status); - fits_set_quantize_method(fptr, quantize_method, status); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffdkinit(fitsfile **fptr, /* O - FITS file pointer */ - const char *name, /* I - name of file to create */ - int *status) /* IO - error status */ -/* - Create and initialize a new FITS file on disk. This routine differs - from ffinit in that the input 'name' is literally taken as the name - of the disk file to be created, and it does not support CFITSIO's - extended filename syntax. -*/ -{ - *fptr = 0; /* initialize null file pointer, */ - /* regardless of the value of *status */ - if (*status > 0) - return(*status); - - *status = CREATE_DISK_FILE; - - ffinit(fptr, name,status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffinit(fitsfile **fptr, /* O - FITS file pointer */ - const char *name, /* I - name of file to create */ - int *status) /* IO - error status */ -/* - Create and initialize a new FITS file. -*/ -{ - int ii, driver, slen, clobber = 0; - char *url; - char urltype[MAX_PREFIX_LEN], outfile[FLEN_FILENAME]; - char tmplfile[FLEN_FILENAME], compspec[80]; - int handle, create_disk_file = 0; - - *fptr = 0; /* initialize null file pointer, */ - /* regardless of the value of *status */ - if (*status > 0) - return(*status); - - if (*status == CREATE_DISK_FILE) - { - create_disk_file = 1; - *status = 0; - } - - if (need_to_initialize) { /* this is called only once */ - *status = fits_init_cfitsio(); - } - - if (*status > 0) - return(*status); - - url = (char *) name; - while (*url == ' ') /* ignore leading spaces in the filename */ - url++; - - if (*url == '\0') - { - ffpmsg("Name of file to create is blank. (ffinit)"); - return(*status = FILE_NOT_CREATED); - } - - if (create_disk_file) - { - if (strlen(url) > FLEN_FILENAME - 1) - { - ffpmsg("Filename is too long. (ffinit)"); - return(*status = FILE_NOT_CREATED); - } - - strcpy(outfile, url); - strcpy(urltype, "file://"); - tmplfile[0] = '\0'; - compspec[0] = '\0'; - } - else - { - - /* check for clobber symbol, i.e, overwrite existing file */ - if (*url == '!') - { - clobber = TRUE; - url++; - } - else - clobber = FALSE; - - /* parse the output file specification */ - /* this routine checks that the strings will not overflow */ - ffourl(url, urltype, outfile, tmplfile, compspec, status); - - if (*status > 0) - { - ffpmsg("could not parse the output filename: (ffinit)"); - ffpmsg(url); - return(*status); - } - } - - /* find which driver corresponds to the urltype */ - *status = urltype2driver(urltype, &driver); - - if (*status) - { - ffpmsg("could not find driver for this file: (ffinit)"); - ffpmsg(url); - return(*status); - } - - /* delete pre-existing file, if asked to do so */ - if (clobber) - { - if (driverTable[driver].remove) - (*driverTable[driver].remove)(outfile); - } - - /* call appropriate driver to create the file */ - if (driverTable[driver].create) - { - - FFLOCK; /* lock this while searching for vacant handle */ - *status = (*driverTable[driver].create)(outfile, &handle); - FFUNLOCK; - - if (*status) - { - ffpmsg("failed to create new file (already exists?):"); - ffpmsg(url); - return(*status); - } - } - else - { - ffpmsg("cannot create a new file of this type: (ffinit)"); - ffpmsg(url); - return(*status = FILE_NOT_CREATED); - } - - /* allocate fitsfile structure and initialize = 0 */ - *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); - - if (!(*fptr)) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate structure for following file: (ffopen)"); - ffpmsg(url); - return(*status = MEMORY_ALLOCATION); - } - - /* allocate FITSfile structure and initialize = 0 */ - (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile)); - - if (!((*fptr)->Fptr)) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate structure for following file: (ffopen)"); - ffpmsg(url); - free(*fptr); - *fptr = 0; - return(*status = MEMORY_ALLOCATION); - } - - slen = strlen(url) + 1; - slen = maxvalue(slen, 32); /* reserve at least 32 chars */ - ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */ - - if ( !(((*fptr)->Fptr)->filename) ) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate memory for filename: (ffinit)"); - ffpmsg(url); - free((*fptr)->Fptr); - free(*fptr); - *fptr = 0; /* return null file pointer */ - return(*status = FILE_NOT_CREATED); - } - - /* mem for headstart array */ - ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG)); - - if ( !(((*fptr)->Fptr)->headstart) ) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate memory for headstart array: (ffinit)"); - ffpmsg(url); - free( ((*fptr)->Fptr)->filename); - free((*fptr)->Fptr); - free(*fptr); - *fptr = 0; /* return null file pointer */ - return(*status = MEMORY_ALLOCATION); - } - - /* mem for file I/O buffers */ - ((*fptr)->Fptr)->iobuffer = (char *) calloc(NIOBUF, IOBUFLEN); - - if ( !(((*fptr)->Fptr)->iobuffer) ) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate memory for iobuffer array: (ffinit)"); - ffpmsg(url); - free( ((*fptr)->Fptr)->headstart); /* free memory for headstart array */ - free( ((*fptr)->Fptr)->filename); - free((*fptr)->Fptr); - free(*fptr); - *fptr = 0; /* return null file pointer */ - return(*status = MEMORY_ALLOCATION); - } - - /* initialize the ageindex array (relative age of the I/O buffers) */ - /* and initialize the bufrecnum array as being empty */ - for (ii = 0; ii < NIOBUF; ii++) { - ((*fptr)->Fptr)->ageindex[ii] = ii; - ((*fptr)->Fptr)->bufrecnum[ii] = -1; - } - - /* store the parameters describing the file */ - ((*fptr)->Fptr)->MAXHDU = 1000; /* initial size of headstart */ - ((*fptr)->Fptr)->filehandle = handle; /* store the file pointer */ - ((*fptr)->Fptr)->driver = driver; /* driver number */ - strcpy(((*fptr)->Fptr)->filename, url); /* full input filename */ - ((*fptr)->Fptr)->filesize = 0; /* physical file size */ - ((*fptr)->Fptr)->logfilesize = 0; /* logical file size */ - ((*fptr)->Fptr)->writemode = 1; /* read-write mode */ - ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */ - ((*fptr)->Fptr)->curbuf = -1; /* undefined current IO buffer */ - ((*fptr)->Fptr)->open_count = 1; /* structure is currently used once */ - ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */ - - ffldrc(*fptr, 0, IGNORE_EOF, status); /* initialize first record */ - - fits_store_Fptr( (*fptr)->Fptr, status); /* store Fptr address */ - - /* if template file was given, use it to define structure of new file */ - - if (tmplfile[0]) - ffoptplt(*fptr, tmplfile, status); - - /* parse and save image compression specification, if given */ - if (compspec[0]) - ffparsecompspec(*fptr, compspec, status); - - return(*status); /* successful return */ -} -/*--------------------------------------------------------------------------*/ -/* ffimem == fits_create_memfile */ - -int ffimem(fitsfile **fptr, /* O - FITS file pointer */ - void **buffptr, /* I - address of memory pointer */ - size_t *buffsize, /* I - size of buffer, in bytes */ - size_t deltasize, /* I - increment for future realloc's */ - void *(*mem_realloc)(void *p, size_t newsize), /* function */ - int *status) /* IO - error status */ - -/* - Create and initialize a new FITS file in memory -*/ -{ - int ii, driver, slen; - char urltype[MAX_PREFIX_LEN]; - int handle; - - if (*status > 0) - return(*status); - - *fptr = 0; /* initialize null file pointer */ - - if (need_to_initialize) { /* this is called only once */ - *status = fits_init_cfitsio(); - } - - if (*status > 0) - return(*status); - - strcpy(urltype, "memkeep://"); /* URL type for pre-existing memory file */ - - *status = urltype2driver(urltype, &driver); - - if (*status > 0) - { - ffpmsg("could not find driver for pre-existing memory file: (ffimem)"); - return(*status); - } - - /* call driver routine to "open" the memory file */ - FFLOCK; /* lock this while searching for vacant handle */ - *status = mem_openmem( buffptr, buffsize, deltasize, - mem_realloc, &handle); - FFUNLOCK; - - if (*status > 0) - { - ffpmsg("failed to open pre-existing memory file: (ffimem)"); - return(*status); - } - - /* allocate fitsfile structure and initialize = 0 */ - *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); - - if (!(*fptr)) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate structure for memory file: (ffimem)"); - return(*status = MEMORY_ALLOCATION); - } - - /* allocate FITSfile structure and initialize = 0 */ - (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile)); - - if (!((*fptr)->Fptr)) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate structure for memory file: (ffimem)"); - free(*fptr); - *fptr = 0; - return(*status = MEMORY_ALLOCATION); - } - - slen = 32; /* reserve at least 32 chars */ - ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */ - - if ( !(((*fptr)->Fptr)->filename) ) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate memory for filename: (ffimem)"); - free((*fptr)->Fptr); - free(*fptr); - *fptr = 0; /* return null file pointer */ - return(*status = MEMORY_ALLOCATION); - } - - /* mem for headstart array */ - ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG)); - - if ( !(((*fptr)->Fptr)->headstart) ) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate memory for headstart array: (ffimem)"); - free( ((*fptr)->Fptr)->filename); - free((*fptr)->Fptr); - free(*fptr); - *fptr = 0; /* return null file pointer */ - return(*status = MEMORY_ALLOCATION); - } - - /* mem for file I/O buffers */ - ((*fptr)->Fptr)->iobuffer = (char *) calloc(NIOBUF, IOBUFLEN); - - if ( !(((*fptr)->Fptr)->iobuffer) ) - { - (*driverTable[driver].close)(handle); /* close the file */ - ffpmsg("failed to allocate memory for iobuffer array: (ffimem)"); - free( ((*fptr)->Fptr)->headstart); /* free memory for headstart array */ - free( ((*fptr)->Fptr)->filename); - free((*fptr)->Fptr); - free(*fptr); - *fptr = 0; /* return null file pointer */ - return(*status = MEMORY_ALLOCATION); - } - - /* initialize the ageindex array (relative age of the I/O buffers) */ - /* and initialize the bufrecnum array as being empty */ - for (ii = 0; ii < NIOBUF; ii++) { - ((*fptr)->Fptr)->ageindex[ii] = ii; - ((*fptr)->Fptr)->bufrecnum[ii] = -1; - } - - /* store the parameters describing the file */ - ((*fptr)->Fptr)->MAXHDU = 1000; /* initial size of headstart */ - ((*fptr)->Fptr)->filehandle = handle; /* file handle */ - ((*fptr)->Fptr)->driver = driver; /* driver number */ - strcpy(((*fptr)->Fptr)->filename, "memfile"); /* dummy filename */ - ((*fptr)->Fptr)->filesize = *buffsize; /* physical file size */ - ((*fptr)->Fptr)->logfilesize = *buffsize; /* logical file size */ - ((*fptr)->Fptr)->writemode = 1; /* read-write mode */ - ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */ - ((*fptr)->Fptr)->curbuf = -1; /* undefined current IO buffer */ - ((*fptr)->Fptr)->open_count = 1; /* structure is currently used once */ - ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */ - - ffldrc(*fptr, 0, IGNORE_EOF, status); /* initialize first record */ - fits_store_Fptr( (*fptr)->Fptr, status); /* store Fptr address */ - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_init_cfitsio(void) -/* - initialize anything that is required before using the CFITSIO routines -*/ -{ - int status; - - union u_tag { - short ival; - char cval[2]; - } u; - - fitsio_init_lock(); - - FFLOCK; /* lockout other threads while executing this critical */ - /* section of code */ - - if (need_to_initialize == 0) { /* already initialized? */ - FFUNLOCK; - return(0); - } - - /* test for correct byteswapping. */ - - u.ival = 1; - if ((BYTESWAPPED && u.cval[0] != 1) || - (BYTESWAPPED == FALSE && u.cval[1] != 1) ) - { - printf ("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - printf(" Byteswapping is not being done correctly on this system.\n"); - printf(" Check the MACHINE and BYTESWAPPED definitions in fitsio2.h\n"); - printf(" Please report this problem to the CFITSIO developers.\n"); - printf( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - FFUNLOCK; - return(1); - } - - - /* test that LONGLONG is an 8 byte integer */ - - if (sizeof(LONGLONG) != 8) - { - printf ("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - printf(" CFITSIO did not find an 8-byte long integer data type.\n"); - printf(" sizeof(LONGLONG) = %d\n",(int)sizeof(LONGLONG)); - printf(" Please report this problem to the CFITSIO developers.\n"); - printf( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - FFUNLOCK; - return(1); - } - - /* register the standard I/O drivers that are always available */ - - /* 1--------------------disk file driver-----------------------*/ - status = fits_register_driver("file://", - file_init, - file_shutdown, - file_setoptions, - file_getoptions, - file_getversion, - file_checkfile, - file_open, - file_create, -#ifdef HAVE_FTRUNCATE - file_truncate, -#else - NULL, /* no file truncate function */ -#endif - file_close, - file_remove, - file_size, - file_flush, - file_seek, - file_read, - file_write); - - if (status) - { - ffpmsg("failed to register the file:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 2------------ output temporary memory file driver ----------------*/ - status = fits_register_driver("mem://", - mem_init, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - NULL, /* checkfile not needed */ - NULL, /* open function not allowed */ - mem_create, - mem_truncate, - mem_close_free, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - - if (status) - { - ffpmsg("failed to register the mem:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 3--------------input pre-existing memory file driver----------------*/ - status = fits_register_driver("memkeep://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - NULL, /* checkfile not needed */ - NULL, /* file open driver function is not used */ - NULL, /* create function not allowed */ - mem_truncate, - mem_close_keep, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - - if (status) - { - ffpmsg("failed to register the memkeep:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 4-------------------stdin stream driver----------------------*/ - /* the stdin stream is copied to memory then opened in memory */ - - status = fits_register_driver("stdin://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - stdin_checkfile, - stdin_open, - NULL, /* create function not allowed */ - mem_truncate, - mem_close_free, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - if (status) - { - ffpmsg("failed to register the stdin:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 5-------------------stdin file stream driver----------------------*/ - /* the stdin stream is copied to a disk file then the disk file is opened */ - - status = fits_register_driver("stdinfile://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - NULL, /* checkfile not needed */ - stdin_open, - NULL, /* create function not allowed */ -#ifdef HAVE_FTRUNCATE - file_truncate, -#else - NULL, /* no file truncate function */ -#endif - file_close, - file_remove, - file_size, - file_flush, - file_seek, - file_read, - file_write); - - if (status) - { - ffpmsg("failed to register the stdinfile:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - - /* 6-----------------------stdout stream driver------------------*/ - status = fits_register_driver("stdout://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - NULL, /* checkfile not needed */ - NULL, /* open function not required */ - mem_create, - mem_truncate, - stdout_close, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - if (status) - { - ffpmsg("failed to register the stdout:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 7------------------iraf disk file to memory driver -----------*/ - status = fits_register_driver("irafmem://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - NULL, /* checkfile not needed */ - mem_iraf_open, - NULL, /* create function not required */ - mem_truncate, - mem_close_free, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - if (status) - { - ffpmsg("failed to register the irafmem:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 8------------------raw binary file to memory driver -----------*/ - status = fits_register_driver("rawfile://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - NULL, /* checkfile not needed */ - mem_rawfile_open, - NULL, /* create function not required */ - mem_truncate, - mem_close_free, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - if (status) - { - ffpmsg("failed to register the rawfile:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 9------------------compressed disk file to memory driver -----------*/ - status = fits_register_driver("compress://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - NULL, /* checkfile not needed */ - mem_compress_open, - NULL, /* create function not required */ - mem_truncate, - mem_close_free, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - if (status) - { - ffpmsg("failed to register the compress:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 10------------------compressed disk file to memory driver -----------*/ - /* Identical to compress://, except it allows READWRITE access */ - - status = fits_register_driver("compressmem://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - NULL, /* checkfile not needed */ - mem_compress_openrw, - NULL, /* create function not required */ - mem_truncate, - mem_close_free, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - if (status) - { - ffpmsg("failed to register the compressmem:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 11------------------compressed disk file to disk file driver -------*/ - status = fits_register_driver("compressfile://", - NULL, - file_shutdown, - file_setoptions, - file_getoptions, - file_getversion, - NULL, /* checkfile not needed */ - file_compress_open, - file_create, -#ifdef HAVE_FTRUNCATE - file_truncate, -#else - NULL, /* no file truncate function */ -#endif - file_close, - file_remove, - file_size, - file_flush, - file_seek, - file_read, - file_write); - - if (status) - { - ffpmsg("failed to register the compressfile:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 12---create file in memory, then compress it to disk file on close--*/ - status = fits_register_driver("compressoutfile://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - NULL, /* checkfile not needed */ - NULL, /* open function not allowed */ - mem_create_comp, - mem_truncate, - mem_close_comp, - file_remove, /* delete existing compressed disk file */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - - if (status) - { - ffpmsg( - "failed to register the compressoutfile:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* Register Optional drivers */ - -#ifdef HAVE_NET_SERVICES - - /* 13--------------------root driver-----------------------*/ - - status = fits_register_driver("root://", - root_init, - root_shutdown, - root_setoptions, - root_getoptions, - root_getversion, - NULL, /* checkfile not needed */ - root_open, - root_create, - NULL, /* No truncate possible */ - root_close, - NULL, /* No remove possible */ - root_size, /* no size possible */ - root_flush, - root_seek, /* Though will always succeed */ - root_read, - root_write); - - if (status) - { - ffpmsg("failed to register the root:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 14--------------------http driver-----------------------*/ - status = fits_register_driver("http://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - http_checkfile, - http_open, - NULL, /* create function not required */ - mem_truncate, - mem_close_free, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - if (status) - { - ffpmsg("failed to register the http:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 15--------------------http file driver-----------------------*/ - - status = fits_register_driver("httpfile://", - NULL, - file_shutdown, - file_setoptions, - file_getoptions, - file_getversion, - NULL, /* checkfile not needed */ - http_file_open, - file_create, -#ifdef HAVE_FTRUNCATE - file_truncate, -#else - NULL, /* no file truncate function */ -#endif - file_close, - file_remove, - file_size, - file_flush, - file_seek, - file_read, - file_write); - - if (status) - { - ffpmsg("failed to register the httpfile:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 16--------------------http memory driver-----------------------*/ - /* same as http:// driver, except memory file can be opened READWRITE */ - status = fits_register_driver("httpmem://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - http_checkfile, - http_file_open, /* this will simply call http_open */ - NULL, /* create function not required */ - mem_truncate, - mem_close_free, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - if (status) - { - ffpmsg("failed to register the httpmem:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 17--------------------httpcompress file driver-----------------------*/ - - status = fits_register_driver("httpcompress://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - NULL, /* checkfile not needed */ - http_compress_open, - NULL, /* create function not required */ - mem_truncate, - mem_close_free, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - if (status) - { - ffpmsg("failed to register the httpcompress:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - - /* 18--------------------ftp driver-----------------------*/ - status = fits_register_driver("ftp://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - ftp_checkfile, - ftp_open, - NULL, /* create function not required */ - mem_truncate, - mem_close_free, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - if (status) - { - ffpmsg("failed to register the ftp:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 19--------------------ftp file driver-----------------------*/ - status = fits_register_driver("ftpfile://", - NULL, - file_shutdown, - file_setoptions, - file_getoptions, - file_getversion, - NULL, /* checkfile not needed */ - ftp_file_open, - file_create, -#ifdef HAVE_FTRUNCATE - file_truncate, -#else - NULL, /* no file truncate function */ -#endif - file_close, - file_remove, - file_size, - file_flush, - file_seek, - file_read, - file_write); - - if (status) - { - ffpmsg("failed to register the ftpfile:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 20--------------------ftp mem driver-----------------------*/ - /* same as ftp:// driver, except memory file can be opened READWRITE */ - status = fits_register_driver("ftpmem://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - ftp_checkfile, - ftp_file_open, /* this will simply call ftp_open */ - NULL, /* create function not required */ - mem_truncate, - mem_close_free, - NULL, /* remove function not required */ - mem_size, - NULL, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - if (status) - { - ffpmsg("failed to register the ftpmem:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* 21--------------------ftp compressed file driver------------------*/ - status = fits_register_driver("ftpcompress://", - NULL, - mem_shutdown, - mem_setoptions, - mem_getoptions, - mem_getversion, - NULL, /* checkfile not needed */ - ftp_compress_open, - 0, /* create function not required */ - mem_truncate, - mem_close_free, - 0, /* remove function not required */ - mem_size, - 0, /* flush function not required */ - mem_seek, - mem_read, - mem_write); - - if (status) - { - ffpmsg("failed to register the ftpcompress:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - /* === End of net drivers section === */ -#endif - -/* ==================== SHARED MEMORY DRIVER SECTION ======================= */ - -#ifdef HAVE_SHMEM_SERVICES - - /* 22--------------------shared memory driver-----------------------*/ - status = fits_register_driver("shmem://", - smem_init, - smem_shutdown, - smem_setoptions, - smem_getoptions, - smem_getversion, - NULL, /* checkfile not needed */ - smem_open, - smem_create, - NULL, /* truncate file not supported yet */ - smem_close, - smem_remove, - smem_size, - smem_flush, - smem_seek, - smem_read, - smem_write ); - - if (status) - { - ffpmsg("failed to register the shmem:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - -#endif -/* ==================== END OF SHARED MEMORY DRIVER SECTION ================ */ - - -#ifdef HAVE_GSIFTP - /* 23--------------------gsiftp driver-----------------------*/ - status = fits_register_driver("gsiftp://", - gsiftp_init, - gsiftp_shutdown, - gsiftp_setoptions, - gsiftp_getoptions, - gsiftp_getversion, - gsiftp_checkfile, - gsiftp_open, - gsiftp_create, -#ifdef HAVE_FTRUNCATE - gsiftp_truncate, -#else - NULL, -#endif - gsiftp_close, - NULL, /* remove function not yet implemented */ - gsiftp_size, - gsiftp_flush, - gsiftp_seek, - gsiftp_read, - gsiftp_write); - - if (status) - { - ffpmsg("failed to register the gsiftp:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - -#endif - - /* 24---------------stdin and stdout stream driver-------------------*/ - status = fits_register_driver("stream://", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - stream_open, - stream_create, - NULL, /* no stream truncate function */ - stream_close, - NULL, /* no stream remove */ - stream_size, - stream_flush, - stream_seek, - stream_read, - stream_write); - - if (status) - { - ffpmsg("failed to register the stream:// driver (init_cfitsio)"); - FFUNLOCK; - return(status); - } - - /* reset flag. Any other threads will now not need to call this routine */ - need_to_initialize = 0; - - FFUNLOCK; - return(status); -} -/*--------------------------------------------------------------------------*/ -int fits_register_driver(char *prefix, - int (*init)(void), - int (*shutdown)(void), - int (*setoptions)(int option), - int (*getoptions)(int *options), - int (*getversion)(int *version), - int (*checkfile) (char *urltype, char *infile, char *outfile), - int (*open)(char *filename, int rwmode, int *driverhandle), - int (*create)(char *filename, int *driverhandle), - int (*truncate)(int driverhandle, LONGLONG filesize), - int (*close)(int driverhandle), - int (*fremove)(char *filename), - int (*size)(int driverhandle, LONGLONG *sizex), - int (*flush)(int driverhandle), - int (*seek)(int driverhandle, LONGLONG offset), - int (*read) (int driverhandle, void *buffer, long nbytes), - int (*write)(int driverhandle, void *buffer, long nbytes) ) -/* - register all the functions needed to support an I/O driver -*/ -{ - int status; - - if (no_of_drivers < 0 ) { - /* This is bad. looks like memory has been corrupted. */ - ffpmsg("Vital CFITSIO parameters held in memory have been corrupted!!"); - ffpmsg("Fatal condition detected in fits_register_driver."); - return(TOO_MANY_DRIVERS); - } - - if (no_of_drivers + 1 > MAX_DRIVERS) - return(TOO_MANY_DRIVERS); - - if (prefix == NULL) - return(BAD_URL_PREFIX); - - - if (init != NULL) - { - status = (*init)(); /* initialize the driver */ - if (status) - return(status); - } - - /* fill in data in table */ - strncpy(driverTable[no_of_drivers].prefix, prefix, MAX_PREFIX_LEN); - driverTable[no_of_drivers].prefix[MAX_PREFIX_LEN - 1] = 0; - driverTable[no_of_drivers].init = init; - driverTable[no_of_drivers].shutdown = shutdown; - driverTable[no_of_drivers].setoptions = setoptions; - driverTable[no_of_drivers].getoptions = getoptions; - driverTable[no_of_drivers].getversion = getversion; - driverTable[no_of_drivers].checkfile = checkfile; - driverTable[no_of_drivers].open = open; - driverTable[no_of_drivers].create = create; - driverTable[no_of_drivers].truncate = truncate; - driverTable[no_of_drivers].close = close; - driverTable[no_of_drivers].remove = fremove; - driverTable[no_of_drivers].size = size; - driverTable[no_of_drivers].flush = flush; - driverTable[no_of_drivers].seek = seek; - driverTable[no_of_drivers].read = read; - driverTable[no_of_drivers].write = write; - - no_of_drivers++; /* increment the number of drivers */ - return(0); - } -/*--------------------------------------------------------------------------*/ -/* fits_parse_input_url */ -int ffiurl(char *url, /* input filename */ - char *urltype, /* e.g., 'file://', 'http://', 'mem://' */ - char *infilex, /* root filename (may be complete path) */ - char *outfile, /* optional output file name */ - char *extspec, /* extension spec: +n or [extname, extver] */ - char *rowfilterx, /* boolean row filter expression */ - char *binspec, /* histogram binning specifier */ - char *colspec, /* column or keyword modifier expression */ - int *status) -/* - parse the input URL into its basic components. - This routine does not support the pixfilter or compspec components. -*/ -{ - return ffifile2(url, urltype, infilex, outfile, - extspec, rowfilterx, binspec, colspec, 0, 0, status); -} -/*--------------------------------------------------------------------------*/ -/* fits_parse_input_file */ -int ffifile(char *url, /* input filename */ - char *urltype, /* e.g., 'file://', 'http://', 'mem://' */ - char *infilex, /* root filename (may be complete path) */ - char *outfile, /* optional output file name */ - char *extspec, /* extension spec: +n or [extname, extver] */ - char *rowfilterx, /* boolean row filter expression */ - char *binspec, /* histogram binning specifier */ - char *colspec, /* column or keyword modifier expression */ - char *pixfilter, /* pixel filter expression */ - int *status) -/* - fits_parse_input_filename - parse the input URL into its basic components. - This routine does not support the compspec component. -*/ -{ - return ffifile2(url, urltype, infilex, outfile, - extspec, rowfilterx, binspec, colspec, pixfilter, 0, status); - -} -/*--------------------------------------------------------------------------*/ -int ffifile2(char *url, /* input filename */ - char *urltype, /* e.g., 'file://', 'http://', 'mem://' */ - char *infilex, /* root filename (may be complete path) */ - char *outfile, /* optional output file name */ - char *extspec, /* extension spec: +n or [extname, extver] */ - char *rowfilterx, /* boolean row filter expression */ - char *binspec, /* histogram binning specifier */ - char *colspec, /* column or keyword modifier expression */ - char *pixfilter, /* pixel filter expression */ - char *compspec, /* image compression specification */ - int *status) -/* - fits_parse_input_filename - parse the input URL into its basic components. - This routine is big and ugly and should be redesigned someday! -*/ -{ - int ii, jj, slen, infilelen, plus_ext = 0, collen; - char *ptr1, *ptr2, *ptr3, *ptr4, *tmptr; - int hasAt, hasDot, hasOper, followingOper, spaceTerm, rowFilter; - int colStart, binStart, pixStart, compStart; - - - /* must have temporary variable for these, in case inputs are NULL */ - char *infile; - char *rowfilter; - char *tmpstr; - - if (*status > 0) - return(*status); - - /* Initialize null strings */ - if (infilex) *infilex = '\0'; - if (urltype) *urltype = '\0'; - if (outfile) *outfile = '\0'; - if (extspec) *extspec = '\0'; - if (binspec) *binspec = '\0'; - if (colspec) *colspec = '\0'; - if (rowfilterx) *rowfilterx = '\0'; - if (pixfilter) *pixfilter = '\0'; - if (compspec) *compspec = '\0'; - slen = strlen(url); - - if (slen == 0) /* blank filename ?? */ - return(*status); - - /* allocate memory for 3 strings, each as long as the input url */ - infile = (char *) calloc(3, slen + 1); - if (!infile) - return(*status = MEMORY_ALLOCATION); - - rowfilter = &infile[slen + 1]; - tmpstr = &rowfilter[slen + 1]; - - ptr1 = url; - - /* -------------------------------------------------------- */ - /* get urltype (e.g., file://, ftp://, http://, etc.) */ - /* --------------------------------------------------------- */ - - if (*ptr1 == '-' && ( *(ptr1 +1) == 0 || *(ptr1 +1) == ' ' || - *(ptr1 +1) == '[' || *(ptr1 +1) == '(' ) ) - { - /* "-" means read file from stdin. Also support "- ", */ - /* "-[extname]" and '-(outfile.fits)" but exclude disk file */ - /* names that begin with a minus sign, e.g., "-55d33m.fits" */ - - if (urltype) - strcat(urltype, "stdin://"); - ptr1++; - } - else if (!fits_strncasecmp(ptr1, "stdin", 5)) - { - if (urltype) - strcat(urltype, "stdin://"); - ptr1 = ptr1 + 5; - } - else - { - ptr2 = strstr(ptr1, "://"); - ptr3 = strstr(ptr1, "(" ); - - if (ptr3 && (ptr3 < ptr2) ) - { - /* the urltype follows a '(' character, so it must apply */ - /* to the output file, and is not the urltype of the input file */ - ptr2 = 0; /* so reset pointer to zero */ - } - - if (ptr2) /* copy the explicit urltype string */ - { - if (urltype) - strncat(urltype, ptr1, ptr2 - ptr1 + 3); - ptr1 = ptr2 + 3; - } - else if (!strncmp(ptr1, "ftp:", 4) ) - { /* the 2 //'s are optional */ - if (urltype) - strcat(urltype, "ftp://"); - ptr1 += 4; - } - else if (!strncmp(ptr1, "gsiftp:", 7) ) - { /* the 2 //'s are optional */ - if (urltype) - strcat(urltype, "gsiftp://"); - ptr1 += 7; - } - else if (!strncmp(ptr1, "http:", 5) ) - { /* the 2 //'s are optional */ - if (urltype) - strcat(urltype, "http://"); - ptr1 += 5; - } - else if (!strncmp(ptr1, "mem:", 4) ) - { /* the 2 //'s are optional */ - if (urltype) - strcat(urltype, "mem://"); - ptr1 += 4; - } - else if (!strncmp(ptr1, "shmem:", 6) ) - { /* the 2 //'s are optional */ - if (urltype) - strcat(urltype, "shmem://"); - ptr1 += 6; - } - else if (!strncmp(ptr1, "file:", 5) ) - { /* the 2 //'s are optional */ - if (urltype) - strcat(urltype, "file://"); - ptr1 += 5; - } - else /* assume file driver */ - { - if (urltype) - strcat(urltype, "file://"); - } - } - - /* ---------------------------------------------------------- - If this is a http:// type file, then the cgi file name could - include the '[' character, which should not be interpreted - as part of CFITSIO's Extended File Name Syntax. Test for this - case by seeing if the last character is a ']' or ')'. If it - is not, then just treat the whole input string as the file name - and do not attempt to interprete the name using the extended - filename syntax. - ----------------------------------------------------------- */ - - if (urltype && !strncmp(urltype, "http://", 7) ) - { - /* test for opening parenthesis or bracket in the file name */ - if( strchr(ptr1, '(' ) || strchr(ptr1, '[' ) ) - { - slen = strlen(ptr1); - ptr3 = ptr1 + slen - 1; - while (*ptr3 == ' ') /* ignore trailing blanks */ - ptr3--; - - if (*ptr3 != ']' && *ptr3 != ')' ) - { - /* name doesn't end with a ']' or ')' so don't try */ - /* to parse this unusual string (may be cgi string) */ - if (infilex) { - - if (strlen(ptr1) > FLEN_FILENAME - 1) { - ffpmsg("Name of file is too long."); - return(*status = URL_PARSE_ERROR); - } - - strcpy(infilex, ptr1); - } - - free(infile); - return(*status); - } - } - } - - /* ---------------------------------------------------------- - Look for VMS style filenames like: - disk:[directory.subdirectory]filename.ext, or - [directory.subdirectory]filename.ext - - Check if the first character is a '[' and urltype != stdin - or if there is a ':[' string in the remaining url string. If - so, then need to move past this bracket character before - search for the opening bracket of a filter specification. - ----------------------------------------------------------- */ - - tmptr = ptr1; - if (*ptr1 == '[') - { - if (*url != '-') - tmptr = ptr1 + 1; /* this bracket encloses a VMS directory name */ - } - else - { - tmptr = strstr(ptr1, ":["); - if (tmptr) /* these 2 chars are part of the VMS disk and directory */ - tmptr += 2; - else - tmptr = ptr1; - } - - /* ------------------------ */ - /* get the input file name */ - /* ------------------------ */ - - ptr2 = strchr(tmptr, '('); /* search for opening parenthesis ( */ - ptr3 = strchr(tmptr, '['); /* search for opening bracket [ */ - - if (ptr2 == ptr3) /* simple case: no [ or ( in the file name */ - { - strcat(infile, ptr1); - } - else if (!ptr3 || /* no bracket, so () enclose output file name */ - (ptr2 && (ptr2 < ptr3)) ) /* () enclose output name before bracket */ - { - strncat(infile, ptr1, ptr2 - ptr1); - ptr2++; - - ptr1 = strchr(ptr2, ')' ); /* search for closing ) */ - if (!ptr1) - { - free(infile); - return(*status = URL_PARSE_ERROR); /* error, no closing ) */ - } - - if (outfile) { - - if (ptr1 - ptr2 > FLEN_FILENAME - 1) - { - free(infile); - return(*status = URL_PARSE_ERROR); - } - - strncat(outfile, ptr2, ptr1 - ptr2); - } - - /* the opening [ could have been part of output name, */ - /* e.g., file(out[compress])[3][#row > 5] */ - /* so search again for opening bracket following the closing ) */ - ptr3 = strchr(ptr1, '['); - - } - else /* bracket comes first, so there is no output name */ - { - strncat(infile, ptr1, ptr3 - ptr1); - } - - /* strip off any trailing blanks in the names */ - - slen = strlen(infile); - while ( (--slen) > 0 && infile[slen] == ' ') - infile[slen] = '\0'; - - if (outfile) - { - slen = strlen(outfile); - while ( (--slen) > 0 && outfile[slen] == ' ') - outfile[slen] = '\0'; - } - - /* --------------------------------------------- */ - /* check if this is an IRAF file (.imh extension */ - /* --------------------------------------------- */ - - ptr4 = strstr(infile, ".imh"); - - /* did the infile name end with ".imh" ? */ - if (ptr4 && (*(ptr4 + 4) == '\0')) - { - if (urltype) - strcpy(urltype, "irafmem://"); - } - - /* --------------------------------------------- */ - /* check if the 'filename+n' convention has been */ - /* used to specifiy which HDU number to open */ - /* --------------------------------------------- */ - - jj = strlen(infile); - - for (ii = jj - 1; ii >= 0; ii--) - { - if (infile[ii] == '+') /* search backwards for '+' sign */ - break; - } - - if (ii > 0 && (jj - ii) < 7) /* limit extension numbers to 5 digits */ - { - infilelen = ii; - ii++; - ptr1 = infile+ii; /* pointer to start of sequence */ - - for (; ii < jj; ii++) - { - if (!isdigit((int) infile[ii] ) ) /* are all the chars digits? */ - break; - } - - if (ii == jj) - { - /* yes, the '+n' convention was used. Copy */ - /* the digits to the output extspec string. */ - plus_ext = 1; - - if (extspec) { - if (jj - infilelen > FLEN_FILENAME - 1) - { - free(infile); - return(*status = URL_PARSE_ERROR); - } - - strncpy(extspec, ptr1, jj - infilelen); - } - - infile[infilelen] = '\0'; /* delete the extension number */ - } - } - - /* -------------------------------------------------------------------- */ - /* if '*' was given for the output name expand it to the root file name */ - /* -------------------------------------------------------------------- */ - - if (outfile && outfile[0] == '*') - { - /* scan input name backwards to the first '/' character */ - for (ii = jj - 1; ii >= 0; ii--) - { - if (infile[ii] == '/' || ii == 0) - { - if (strlen(&infile[ii + 1]) > FLEN_FILENAME - 1) - { - free(infile); - return(*status = URL_PARSE_ERROR); - } - - strcpy(outfile, &infile[ii + 1]); - break; - } - } - } - - /* ------------------------------------------ */ - /* copy strings from local copy to the output */ - /* ------------------------------------------ */ - if (infilex) { - if (strlen(infile) > FLEN_FILENAME - 1) - { - free(infile); - return(*status = URL_PARSE_ERROR); - } - - strcpy(infilex, infile); - } - /* ---------------------------------------------------------- */ - /* if no '[' character in the input string, then we are done. */ - /* ---------------------------------------------------------- */ - if (!ptr3) - { - free(infile); - return(*status); - } - - /* ------------------------------------------- */ - /* see if [ extension specification ] is given */ - /* ------------------------------------------- */ - - if (!plus_ext) /* extension no. not already specified? Then */ - /* first brackets must enclose extension name or # */ - /* or it encloses a image subsection specification */ - /* or a raw binary image specifier */ - /* or a image compression specifier */ - - /* Or, the extension specification may have been */ - /* omitted and we have to guess what the user intended */ - { - ptr1 = ptr3 + 1; /* pointer to first char after the [ */ - - ptr2 = strchr(ptr1, ']' ); /* search for closing ] */ - if (!ptr2) - { - ffpmsg("input file URL is missing closing bracket ']'"); - free(infile); - return(*status = URL_PARSE_ERROR); /* error, no closing ] */ - } - - /* ---------------------------------------------- */ - /* First, test if this is a rawfile specifier */ - /* which looks something like: '[ib512,512:2880]' */ - /* Test if first character is b,i,j,d,r,f, or u, */ - /* and optional second character is b or l, */ - /* followed by one or more digits, */ - /* finally followed by a ',', ':', or ']' */ - /* ---------------------------------------------- */ - - if (*ptr1 == 'b' || *ptr1 == 'B' || *ptr1 == 'i' || *ptr1 == 'I' || - *ptr1 == 'j' || *ptr1 == 'J' || *ptr1 == 'd' || *ptr1 == 'D' || - *ptr1 == 'r' || *ptr1 == 'R' || *ptr1 == 'f' || *ptr1 == 'F' || - *ptr1 == 'u' || *ptr1 == 'U') - { - /* next optional character may be a b or l (for Big or Little) */ - ptr1++; - if (*ptr1 == 'b' || *ptr1 == 'B' || *ptr1 == 'l' || *ptr1 == 'L') - ptr1++; - - if (isdigit((int) *ptr1)) /* must have at least 1 digit */ - { - while (isdigit((int) *ptr1)) - ptr1++; /* skip over digits */ - - if (*ptr1 == ',' || *ptr1 == ':' || *ptr1 == ']' ) - { - /* OK, this looks like a rawfile specifier */ - - if (urltype) - { - if (strstr(urltype, "stdin") ) - strcpy(urltype, "rawstdin://"); - else - strcpy(urltype, "rawfile://"); - } - - /* append the raw array specifier to infilex */ - if (infilex) - { - - if (strlen(infilex) + strlen(ptr3) > FLEN_FILENAME - 1) - { - free(infile); - return(*status = URL_PARSE_ERROR); - } - - strcat(infilex, ptr3); - ptr1 = strchr(infilex, ']'); /* find the closing ] char */ - if (ptr1) - *(ptr1 + 1) = '\0'; /* terminate string after the ] */ - } - - if (extspec) - strcpy(extspec, "0"); /* the 0 ext number is implicit */ - - tmptr = strchr(ptr2 + 1, '[' ); /* search for another [ char */ - - /* copy any remaining characters into rowfilterx */ - if (tmptr && rowfilterx) - { - - - if (strlen(rowfilterx) + strlen(tmptr + 1) > FLEN_FILENAME -1) - { - free(infile); - return(*status = URL_PARSE_ERROR); - } - - strcat(rowfilterx, tmptr + 1); - - tmptr = strchr(rowfilterx, ']' ); /* search for closing ] */ - if (tmptr) - *tmptr = '\0'; /* overwrite the ] with null terminator */ - } - - free(infile); /* finished parsing, so return */ - return(*status); - } - } - } /* end of rawfile specifier test */ - - /* -------------------------------------------------------- */ - /* Not a rawfile, so next, test if this is an image section */ - /* i.e., an integer followed by a ':' or a '*' or '-*' */ - /* -------------------------------------------------------- */ - - ptr1 = ptr3 + 1; /* reset pointer to first char after the [ */ - tmptr = ptr1; - - while (*tmptr == ' ') - tmptr++; /* skip leading blanks */ - - while (isdigit((int) *tmptr)) - tmptr++; /* skip over leading digits */ - - if (*tmptr == ':' || *tmptr == '*' || *tmptr == '-') - { - /* this is an image section specifier */ - strcat(rowfilter, ptr3); -/* - don't want to assume 0 extension any more; may imply an image extension. - if (extspec) - strcpy(extspec, "0"); -*/ - } - else - { - /* ----------------------------------------------------------------- - Not an image section or rawfile spec so may be an extension spec. - - Examples of valid extension specifiers: - [3] - 3rd extension; 0 = primary array - [events] - events extension - [events, 2] - events extension, with EXTVER = 2 - [events,2] - spaces are optional - [events, 3, b] - same as above, plus XTENSION = 'BINTABLE' - [PICS; colName(12)] - an image in row 12 of the colName column - in the PICS table extension - [PICS; colName(exposure > 1000)] - as above, but find image in - first row with with exposure column value > 1000. - [Rate Table] - extension name can contain spaces! - [Rate Table;colName(exposure>1000)] - - Examples of other types of specifiers (Not extension specifiers) - - [bin] !!! this is ambiguous, and can't be distinguished from - a valid extension specifier - [bini X=1:512:16] (also binb, binj, binr, and bind are allowed) - [binr (X,Y) = 5] - [bin @binfilter.txt] - - [col Time;rate] - [col PI=PHA * 1.1] - [col -Time; status] - - [X > 5] - [X>5] - [@filter.txt] - [StatusCol] !!! this is ambiguous, and can't be distinguished - from a valid extension specifier - [StatusCol==0] - [StatusCol || x>6] - [gtifilter()] - [regfilter("region.reg")] - - [compress Rice] - - There will always be some ambiguity between an extension name and - a boolean row filtering expression, (as in a couple of the above - examples). If there is any doubt, the expression should be treated - as an extension specification; The user can always add an explicit - expression specifier to override this interpretation. - - The following decision logic will be used: - - 1) locate the first token, terminated with a space, comma, - semi-colon, or closing bracket. - - 2) the token is not part of an extension specifier if any of - the following is true: - - - if the token begins with '@' and contains a '.' - - if the token contains an operator: = > < || && - - if the token begins with "gtifilter(" or "regfilter(" - - if the token is terminated by a space and is followed by - additional characters (not a ']') AND any of the following: - - the token is 'col' - - the token is 3 or 4 chars long and begins with 'bin' - - the second token begins with an operator: - ! = < > | & + - * / % - - - 3) otherwise, the string is assumed to be an extension specifier - - ----------------------------------------------------------------- */ - - tmptr = ptr1; - while(*tmptr == ' ') - tmptr++; - - hasAt = 0; - hasDot = 0; - hasOper = 0; - followingOper = 0; - spaceTerm = 0; - rowFilter = 0; - colStart = 0; - binStart = 0; - pixStart = 0; - compStart = 0; - - if (*tmptr == '@') /* test for leading @ symbol */ - hasAt = 1; - - if ( !fits_strncasecmp(tmptr, "col ", 4) ) - colStart = 1; - - if ( !fits_strncasecmp(tmptr, "bin", 3) ) - binStart = 1; - - if ( !fits_strncasecmp(tmptr, "pix", 3) ) - pixStart = 1; - - if ( !fits_strncasecmp(tmptr, "compress ", 9) || - !fits_strncasecmp(tmptr, "compress]", 9) ) - compStart = 1; - - if ( !fits_strncasecmp(tmptr, "gtifilter(", 10) || - !fits_strncasecmp(tmptr, "regfilter(", 10) ) - { - rowFilter = 1; - } - else - { - /* parse the first token of the expression */ - for (ii = 0; ii < ptr2 - ptr1 + 1; ii++, tmptr++) - { - if (*tmptr == '.') - hasDot = 1; - else if (*tmptr == '=' || *tmptr == '>' || *tmptr == '<' || - (*tmptr == '|' && *(tmptr+1) == '|') || - (*tmptr == '&' && *(tmptr+1) == '&') ) - hasOper = 1; - - else if (*tmptr == ',' || *tmptr == ';' || *tmptr == ']') - { - break; - } - else if (*tmptr == ' ') /* a space char? */ - { - while(*tmptr == ' ') /* skip spaces */ - tmptr++; - - if (*tmptr == ']') /* is this the end? */ - break; - - spaceTerm = 1; /* 1st token is terminated by space */ - - /* test if this is a column or binning specifier */ - if (colStart || (ii <= 4 && (binStart || pixStart)) ) - rowFilter = 1; - else - { - - /* check if next character is an operator */ - if (*tmptr == '=' || *tmptr == '>' || *tmptr == '<' || - *tmptr == '|' || *tmptr == '&' || *tmptr == '!' || - *tmptr == '+' || *tmptr == '-' || *tmptr == '*' || - *tmptr == '/' || *tmptr == '%') - followingOper = 1; - } - break; - } - } - } - - /* test if this is NOT an extension specifier */ - if ( rowFilter || (pixStart && spaceTerm) || - (hasAt && hasDot) || - hasOper || - compStart || - (spaceTerm && followingOper) ) - { - /* this is (probably) not an extension specifier */ - /* so copy all chars to filter spec string */ - strcat(rowfilter, ptr3); - } - else - { - /* this appears to be a legit extension specifier */ - /* copy the extension specification */ - if (extspec) { - if (ptr2 - ptr1 > FLEN_FILENAME - 1) { - free(infile); - return(*status = URL_PARSE_ERROR); - } - strncat(extspec, ptr1, ptr2 - ptr1); - } - - /* copy any remaining chars to filter spec string */ - strcat(rowfilter, ptr2 + 1); - } - } - } /* end of if (!plus_ext) */ - else - { - /* ------------------------------------------------------------------ */ - /* already have extension, so this must be a filter spec of some sort */ - /* ------------------------------------------------------------------ */ - - strcat(rowfilter, ptr3); - } - - /* strip off any trailing blanks from filter */ - slen = strlen(rowfilter); - while ( (--slen) >= 0 && rowfilter[slen] == ' ') - rowfilter[slen] = '\0'; - - if (!rowfilter[0]) - { - free(infile); - return(*status); /* nothing left to parse */ - } - - /* ------------------------------------------------ */ - /* does the filter contain a binning specification? */ - /* ------------------------------------------------ */ - - ptr1 = strstr(rowfilter, "[bin"); /* search for "[bin" */ - if (!ptr1) - ptr1 = strstr(rowfilter, "[BIN"); /* search for "[BIN" */ - if (!ptr1) - ptr1 = strstr(rowfilter, "[Bin"); /* search for "[Bin" */ - - if (ptr1) - { - ptr2 = ptr1 + 4; /* end of the '[bin' string */ - if (*ptr2 == 'b' || *ptr2 == 'i' || *ptr2 == 'j' || - *ptr2 == 'r' || *ptr2 == 'd') - ptr2++; /* skip the datatype code letter */ - - - if ( *ptr2 != ' ' && *ptr2 != ']') - ptr1 = NULL; /* bin string must be followed by space or ] */ - } - - if (ptr1) - { - /* found the binning string */ - if (binspec) - { - if (strlen(ptr1 +1) > FLEN_FILENAME - 1) - { - free(infile); - return(*status = URL_PARSE_ERROR); - } - - strcpy(binspec, ptr1 + 1); - ptr2 = strchr(binspec, ']'); - - if (ptr2) /* terminate the binning filter */ - { - *ptr2 = '\0'; - - if ( *(--ptr2) == ' ') /* delete trailing spaces */ - *ptr2 = '\0'; - } - else - { - ffpmsg("input file URL is missing closing bracket ']'"); - ffpmsg(rowfilter); - free(infile); - return(*status = URL_PARSE_ERROR); /* error, no closing ] */ - } - } - - /* delete the binning spec from the row filter string */ - ptr2 = strchr(ptr1, ']'); - strcpy(tmpstr, ptr2+1); /* copy any chars after the binspec */ - strcpy(ptr1, tmpstr); /* overwrite binspec */ - } - - /* --------------------------------------------------------- */ - /* does the filter contain a column selection specification? */ - /* --------------------------------------------------------- */ - - ptr1 = strstr(rowfilter, "[col "); - if (!ptr1) - { - ptr1 = strstr(rowfilter, "[COL "); - - if (!ptr1) - ptr1 = strstr(rowfilter, "[Col "); - } - - if (ptr1) - { /* find the end of the column specifier */ - ptr2 = ptr1 + 5; - while (*ptr2 != ']') - { - if (*ptr2 == '\0') - { - ffpmsg("input file URL is missing closing bracket ']'"); - free(infile); - return(*status = URL_PARSE_ERROR); /* error, no closing ] */ - } - - if (*ptr2 == '\'') /* start of a literal string */ - { - ptr2 = strchr(ptr2 + 1, '\''); /* find closing quote */ - if (!ptr2) - { - ffpmsg - ("literal string in input file URL is missing closing single quote"); - free(infile); - return(*status = URL_PARSE_ERROR); /* error, no closing ] */ - } - } - - if (*ptr2 == '[') /* set of nested square brackets */ - { - ptr2 = strchr(ptr2 + 1, ']'); /* find closing bracket */ - if (!ptr2) - { - ffpmsg - ("nested brackets in input file URL is missing closing bracket"); - free(infile); - return(*status = URL_PARSE_ERROR); /* error, no closing ] */ - } - } - - ptr2++; /* continue search for the closing bracket character */ - } - - collen = ptr2 - ptr1 - 1; - - if (colspec) /* copy the column specifier to output string */ - { - if (collen > FLEN_FILENAME - 1) { - free(infile); - return(*status = URL_PARSE_ERROR); - } - - strncpy(colspec, ptr1 + 1, collen); - colspec[collen] = '\0'; - - while (colspec[--collen] == ' ') - colspec[collen] = '\0'; /* strip trailing blanks */ - } - - /* delete the column selection spec from the row filter string */ - strcpy(tmpstr, ptr2 + 1); /* copy any chars after the colspec */ - strcpy(ptr1, tmpstr); /* overwrite binspec */ - } - - /* --------------------------------------------------------- */ - /* does the filter contain a pixel filter specification? */ - /* --------------------------------------------------------- */ - - ptr1 = strstr(rowfilter, "[pix"); - if (!ptr1) - { - ptr1 = strstr(rowfilter, "[PIX"); - - if (!ptr1) - ptr1 = strstr(rowfilter, "[Pix"); - } - - if (ptr1) - { - ptr2 = ptr1 + 4; /* end of the '[pix' string */ - if (*ptr2 == 'b' || *ptr2 == 'i' || *ptr2 == 'j' || *ptr2 == 'B' || - *ptr2 == 'I' || *ptr2 == 'J' || *ptr2 == 'r' || *ptr2 == 'd' || - *ptr2 == 'R' || *ptr2 == 'D') - ptr2++; /* skip the datatype code letter */ - - if (*ptr2 == '1') - ptr2++; /* skip the single HDU indicator */ - - if ( *ptr2 != ' ') - ptr1 = NULL; /* pix string must be followed by space */ - } - - if (ptr1) - { /* find the end of the pixel filter */ - while (*ptr2 != ']') - { - if (*ptr2 == '\0') - { - ffpmsg("input file URL is missing closing bracket ']'"); - free(infile); - return(*status = URL_PARSE_ERROR); /* error, no closing ] */ - } - - if (*ptr2 == '\'') /* start of a literal string */ - { - ptr2 = strchr(ptr2 + 1, '\''); /* find closing quote */ - if (!ptr2) - { - ffpmsg - ("literal string in input file URL is missing closing single quote"); - free(infile); - return(*status = URL_PARSE_ERROR); /* error, no closing ] */ - } - } - - if (*ptr2 == '[') /* set of nested square brackets */ - { - ptr2 = strchr(ptr2 + 1, ']'); /* find closing bracket */ - if (!ptr2) - { - ffpmsg - ("nested brackets in input file URL is missing closing bracket"); - free(infile); - return(*status = URL_PARSE_ERROR); /* error, no closing ] */ - } - } - - ptr2++; /* continue search for the closing bracket character */ - } - - collen = ptr2 - ptr1 - 1; - - if (pixfilter) /* copy the column specifier to output string */ - { - if (collen > FLEN_FILENAME - 1) { - free(infile); - return(*status = URL_PARSE_ERROR); - } - - strncpy(pixfilter, ptr1 + 1, collen); - pixfilter[collen] = '\0'; - - while (pixfilter[--collen] == ' ') - pixfilter[collen] = '\0'; /* strip trailing blanks */ - } - - /* delete the pixel filter from the row filter string */ - strcpy(tmpstr, ptr2 + 1); /* copy any chars after the pixel filter */ - strcpy(ptr1, tmpstr); /* overwrite binspec */ - } - - /* ------------------------------------------------------------ */ - /* does the filter contain an image compression specification? */ - /* ------------------------------------------------------------ */ - - ptr1 = strstr(rowfilter, "[compress"); - - if (ptr1) - { - ptr2 = ptr1 + 9; /* end of the '[compress' string */ - - if ( *ptr2 != ' ' && *ptr2 != ']') - ptr1 = NULL; /* compress string must be followed by space or ] */ - } - - if (ptr1) - { - /* found the compress string */ - if (compspec) - { - if (strlen(ptr1 +1) > FLEN_FILENAME - 1) - { - free(infile); - return(*status = URL_PARSE_ERROR); - } - - strcpy(compspec, ptr1 + 1); - ptr2 = strchr(compspec, ']'); - - if (ptr2) /* terminate the binning filter */ - { - *ptr2 = '\0'; - - if ( *(--ptr2) == ' ') /* delete trailing spaces */ - *ptr2 = '\0'; - } - else - { - ffpmsg("input file URL is missing closing bracket ']'"); - ffpmsg(rowfilter); - free(infile); - return(*status = URL_PARSE_ERROR); /* error, no closing ] */ - } - } - - /* delete the compression spec from the row filter string */ - ptr2 = strchr(ptr1, ']'); - strcpy(tmpstr, ptr2+1); /* copy any chars after the binspec */ - strcpy(ptr1, tmpstr); /* overwrite binspec */ - } - - /* copy the remaining string to the rowfilter output... should only */ - /* contain a rowfilter expression of the form "[expr]" */ - - if (rowfilterx && rowfilter[0]) { - ptr2 = rowfilter + strlen(rowfilter) - 1; - if( rowfilter[0]=='[' && *ptr2==']' ) { - *ptr2 = '\0'; - - if (strlen(rowfilter + 1) > FLEN_FILENAME - 1) - { - free(infile); - return(*status = URL_PARSE_ERROR); - } - - strcpy(rowfilterx, rowfilter+1); - } else { - ffpmsg("input file URL lacks valid row filter expression"); - *status = URL_PARSE_ERROR; - } - } - - free(infile); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffexist(const char *infile, /* I - input filename or URL */ - int *exists, /* O - 2 = a compressed version of file exists */ - /* 1 = yes, disk file exists */ - /* 0 = no, disk file could not be found */ - /* -1 = infile is not a disk file (could */ - /* be a http, ftp, gsiftp, smem, or stdin file) */ - int *status) /* I/O status */ - -/* - test if the input file specifier is an existing file on disk - If the specified file can't be found, it then searches for a - compressed version of the file. -*/ -{ - FILE *diskfile; - char rootname[FLEN_FILENAME]; - char *ptr1; - - if (*status > 0) - return(*status); - - /* strip off any extname or filters from the name */ - ffrtnm( (char *)infile, rootname, status); - - ptr1 = strstr(rootname, "://"); - - if (ptr1 || *rootname == '-') { - if (!strncmp(rootname, "file", 4) ) { - ptr1 = ptr1 + 3; /* pointer to start of the disk file name */ - } else { - *exists = -1; /* this is not a disk file */ - return (*status); - } - } else { - ptr1 = rootname; - } - - /* see if the disk file exists */ - if (file_openfile(ptr1, 0, &diskfile)) { - - /* no, couldn't open file, so see if there is a compressed version */ - if (file_is_compressed(ptr1) ) { - *exists = 2; /* a compressed version of the file exists */ - } else { - *exists = 0; /* neither file nor compressed version exist */ - } - - } else { - - /* yes, file exists */ - *exists = 1; - fclose(diskfile); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffrtnm(char *url, - char *rootname, - int *status) -/* - parse the input URL, returning the root name (filetype://basename). -*/ - -{ - int ii, jj, slen, infilelen; - char *ptr1, *ptr2, *ptr3; - char urltype[MAX_PREFIX_LEN]; - char infile[FLEN_FILENAME]; - - if (*status > 0) - return(*status); - - ptr1 = url; - *rootname = '\0'; - *urltype = '\0'; - *infile = '\0'; - - /* get urltype (e.g., file://, ftp://, http://, etc.) */ - if (*ptr1 == '-') /* "-" means read file from stdin */ - { - strcat(urltype, "-"); - ptr1++; - } - else if (!strncmp(ptr1, "stdin", 5) || !strncmp(ptr1, "STDIN", 5)) - { - strcat(urltype, "-"); - ptr1 = ptr1 + 5; - } - else - { - ptr2 = strstr(ptr1, "://"); - ptr3 = strstr(ptr1, "(" ); - - if (ptr3 && (ptr3 < ptr2) ) - { - /* the urltype follows a '(' character, so it must apply */ - /* to the output file, and is not the urltype of the input file */ - ptr2 = 0; /* so reset pointer to zero */ - } - - - if (ptr2) /* copy the explicit urltype string */ - { - - if (ptr2 - ptr1 + 3 > MAX_PREFIX_LEN - 1) - { - return(*status = URL_PARSE_ERROR); - } - strncat(urltype, ptr1, ptr2 - ptr1 + 3); - ptr1 = ptr2 + 3; - } - else if (!strncmp(ptr1, "ftp:", 4) ) - { /* the 2 //'s are optional */ - strcat(urltype, "ftp://"); - ptr1 += 4; - } - else if (!strncmp(ptr1, "gsiftp:", 7) ) - { /* the 2 //'s are optional */ - strcat(urltype, "gsiftp://"); - ptr1 += 7; - } - else if (!strncmp(ptr1, "http:", 5) ) - { /* the 2 //'s are optional */ - strcat(urltype, "http://"); - ptr1 += 5; - } - else if (!strncmp(ptr1, "mem:", 4) ) - { /* the 2 //'s are optional */ - strcat(urltype, "mem://"); - ptr1 += 4; - } - else if (!strncmp(ptr1, "shmem:", 6) ) - { /* the 2 //'s are optional */ - strcat(urltype, "shmem://"); - ptr1 += 6; - } - else if (!strncmp(ptr1, "file:", 5) ) - { /* the 2 //'s are optional */ - ptr1 += 5; - } - - /* else assume file driver */ - } - - /* get the input file name */ - ptr2 = strchr(ptr1, '('); /* search for opening parenthesis ( */ - ptr3 = strchr(ptr1, '['); /* search for opening bracket [ */ - - if (ptr2 == ptr3) /* simple case: no [ or ( in the file name */ - { - - if (strlen(ptr1) > FLEN_FILENAME - 1) - { - return(*status = URL_PARSE_ERROR); - } - - strcat(infile, ptr1); - } - else if (!ptr3) /* no bracket, so () enclose output file name */ - { - - if (ptr2 - ptr1 > FLEN_FILENAME - 1) - { - return(*status = URL_PARSE_ERROR); - } - - strncat(infile, ptr1, ptr2 - ptr1); - ptr2++; - - ptr1 = strchr(ptr2, ')' ); /* search for closing ) */ - if (!ptr1) - return(*status = URL_PARSE_ERROR); /* error, no closing ) */ - - } - else if (ptr2 && (ptr2 < ptr3)) /* () enclose output name before bracket */ - { - - if (ptr2 - ptr1 > FLEN_FILENAME - 1) - { - return(*status = URL_PARSE_ERROR); - } - - strncat(infile, ptr1, ptr2 - ptr1); - ptr2++; - - ptr1 = strchr(ptr2, ')' ); /* search for closing ) */ - if (!ptr1) - return(*status = URL_PARSE_ERROR); /* error, no closing ) */ - } - else /* bracket comes first, so there is no output name */ - { - if (ptr3 - ptr1 > FLEN_FILENAME - 1) - { - return(*status = URL_PARSE_ERROR); - } - - strncat(infile, ptr1, ptr3 - ptr1); - } - - /* strip off any trailing blanks in the names */ - slen = strlen(infile); - for (ii = slen - 1; ii > 0; ii--) - { - if (infile[ii] == ' ') - infile[ii] = '\0'; - else - break; - } - - /* --------------------------------------------- */ - /* check if the 'filename+n' convention has been */ - /* used to specifiy which HDU number to open */ - /* --------------------------------------------- */ - - jj = strlen(infile); - - for (ii = jj - 1; ii >= 0; ii--) - { - if (infile[ii] == '+') /* search backwards for '+' sign */ - break; - } - - if (ii > 0 && (jj - ii) < 5) /* limit extension numbers to 4 digits */ - { - infilelen = ii; - ii++; - - - for (; ii < jj; ii++) - { - if (!isdigit((int) infile[ii] ) ) /* are all the chars digits? */ - break; - } - - if (ii == jj) - { - /* yes, the '+n' convention was used. */ - - infile[infilelen] = '\0'; /* delete the extension number */ - } - } - - if (strlen(urltype) + strlen(infile) > FLEN_FILENAME - 1) - { - return(*status = URL_PARSE_ERROR); - } - - strcat(rootname, urltype); /* construct the root name */ - strcat(rootname, infile); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffourl(char *url, /* I - full input URL */ - char *urltype, /* O - url type */ - char *outfile, /* O - base file name */ - char *tpltfile, /* O - template file name, if any */ - char *compspec, /* O - compression specification, if any */ - int *status) -/* - parse the output URL into its basic components. -*/ - -{ - char *ptr1, *ptr2, *ptr3; - - if (*status > 0) - return(*status); - - if (urltype) - *urltype = '\0'; - if (outfile) - *outfile = '\0'; - if (tpltfile) - *tpltfile = '\0'; - if (compspec) - *compspec = '\0'; - - ptr1 = url; - while (*ptr1 == ' ') /* ignore leading blanks */ - ptr1++; - - if ( ( (*ptr1 == '-') && ( *(ptr1 +1) == 0 || *(ptr1 +1) == ' ' ) ) - || !strcmp(ptr1, "stdout") - || !strcmp(ptr1, "STDOUT")) - - /* "-" means write to stdout; also support "- " */ - /* but exclude disk file names that begin with a minus sign */ - /* e.g., "-55d33m.fits" */ - { - if (urltype) - strcpy(urltype, "stdout://"); - } - else - { - /* not writing to stdout */ - /* get urltype (e.g., file://, ftp://, http://, etc.) */ - - ptr2 = strstr(ptr1, "://"); - if (ptr2) /* copy the explicit urltype string */ - { - if (urltype) { - if (ptr2 - ptr1 + 3 > MAX_PREFIX_LEN - 1) - { - return(*status = URL_PARSE_ERROR); - } - - strncat(urltype, ptr1, ptr2 - ptr1 + 3); - } - - ptr1 = ptr2 + 3; - } - else /* assume file driver */ - { - if (urltype) - strcat(urltype, "file://"); - } - - /* look for template file name, enclosed in parenthesis */ - ptr2 = strchr(ptr1, '('); - - /* look for image compression parameters, enclosed in sq. brackets */ - ptr3 = strchr(ptr1, '['); - - if (outfile) - { - if (ptr2) { /* template file was specified */ - if (ptr2 - ptr1 > FLEN_FILENAME - 1) - { - return(*status = URL_PARSE_ERROR); - } - - strncat(outfile, ptr1, ptr2 - ptr1); - } else if (ptr3) { /* compression was specified */ - if (ptr3 - ptr1 > FLEN_FILENAME - 1) - { - return(*status = URL_PARSE_ERROR); - } - strncat(outfile, ptr1, ptr3 - ptr1); - - } else { /* no template file or compression */ - if (strlen(ptr1) > FLEN_FILENAME - 1) - { - return(*status = URL_PARSE_ERROR); - } - strcpy(outfile, ptr1); - } - } - - - if (ptr2) /* template file was specified */ - { - ptr2++; - - ptr1 = strchr(ptr2, ')' ); /* search for closing ) */ - - if (!ptr1) - { - return(*status = URL_PARSE_ERROR); /* error, no closing ) */ - } - - if (tpltfile) { - if (ptr1 - ptr2 > FLEN_FILENAME - 1) - { - return(*status = URL_PARSE_ERROR); - } - strncat(tpltfile, ptr2, ptr1 - ptr2); - } - } - - if (ptr3) /* compression was specified */ - { - ptr3++; - - ptr1 = strchr(ptr3, ']' ); /* search for closing ] */ - - if (!ptr1) - { - return(*status = URL_PARSE_ERROR); /* error, no closing ] */ - } - - if (compspec) { - - if (ptr1 - ptr3 > FLEN_FILENAME - 1) - { - return(*status = URL_PARSE_ERROR); - } - - strncat(compspec, ptr3, ptr1 - ptr3); - } - } - - /* check if a .gz compressed output file is to be created */ - /* by seeing if the filename ends in '.gz' */ - if (urltype && outfile) - { - if (!strcmp(urltype, "file://") ) - { - ptr1 = strstr(outfile, ".gz"); - if (ptr1) - { /* make sure the ".gz" is at the end of the file name */ - ptr1 += 3; - if (*ptr1 == 0 || *ptr1 == ' ' ) - strcpy(urltype, "compressoutfile://"); - } - } - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffexts(char *extspec, - int *extnum, - char *extname, - int *extvers, - int *hdutype, - char *imagecolname, - char *rowexpress, - int *status) -{ -/* - Parse the input extension specification string, returning either the - extension number or the values of the EXTNAME, EXTVERS, and XTENSION - keywords in desired extension. Also return the name of the column containing - an image, and an expression to be used to determine which row to use, - if present. -*/ - char *ptr1, *ptr2; - int slen, nvals; - int notint = 1; /* initially assume specified extname is not an integer */ - char tmpname[FLEN_VALUE], *loc; - - *extnum = 0; - *extname = '\0'; - *extvers = 0; - *hdutype = ANY_HDU; - *imagecolname = '\0'; - *rowexpress = '\0'; - - if (*status > 0) - return(*status); - - ptr1 = extspec; /* pointer to first char */ - - while (*ptr1 == ' ') /* skip over any leading blanks */ - ptr1++; - - if (isdigit((int) *ptr1)) /* is the extension specification a number? */ - { - notint = 0; /* looks like extname may actually be the ext. number */ - errno = 0; /* reset this prior to calling strtol */ - *extnum = strtol(ptr1, &loc, 10); /* read the string as an integer */ - - while (*loc == ' ') /* skip over trailing blanks */ - loc++; - - /* check for read error, or junk following the integer */ - if ((*loc != '\0' && *loc != ';' ) || (errno == ERANGE) ) - { - *extnum = 0; - notint = 1; /* no, extname was not a simple integer after all */ - errno = 0; /* reset error condition flag if it was set */ - } - - if ( *extnum < 0 || *extnum > 99999) - { - *extnum = 0; /* this is not a reasonable extension number */ - ffpmsg("specified extension number is out of range:"); - ffpmsg(extspec); - return(*status = URL_PARSE_ERROR); - } - } - - -/* This logic was too simple, and failed on extnames like '1000TEMP' - where it would try to move to the 1000th extension - - if (isdigit((int) *ptr1)) - { - sscanf(ptr1, "%d", extnum); - if (*extnum < 0 || *extnum > 9999) - { - *extnum = 0; - ffpmsg("specified extension number is out of range:"); - ffpmsg(extspec); - return(*status = URL_PARSE_ERROR); - } - } -*/ - - if (notint) - { - /* not a number, so EXTNAME must be specified, followed by */ - /* optional EXTVERS and XTENSION values */ - - /* don't use space char as end indicator, because there */ - /* may be imbedded spaces in the EXTNAME value */ - slen = strcspn(ptr1, ",:;"); /* length of EXTNAME */ - - if (slen > FLEN_VALUE - 1) - { - return(*status = URL_PARSE_ERROR); - } - - strncat(extname, ptr1, slen); /* EXTNAME value */ - - /* now remove any trailing blanks */ - while (slen > 0 && *(extname + slen -1) == ' ') - { - *(extname + slen -1) = '\0'; - slen--; - } - - ptr1 += slen; - slen = strspn(ptr1, " ,:"); /* skip delimiter characters */ - ptr1 += slen; - - slen = strcspn(ptr1, " ,:;"); /* length of EXTVERS */ - if (slen) - { - nvals = sscanf(ptr1, "%d", extvers); /* EXTVERS value */ - if (nvals != 1) - { - ffpmsg("illegal EXTVER value in input URL:"); - ffpmsg(extspec); - return(*status = URL_PARSE_ERROR); - } - - ptr1 += slen; - slen = strspn(ptr1, " ,:"); /* skip delimiter characters */ - ptr1 += slen; - - slen = strcspn(ptr1, ";"); /* length of HDUTYPE */ - if (slen) - { - if (*ptr1 == 'b' || *ptr1 == 'B') - *hdutype = BINARY_TBL; - else if (*ptr1 == 't' || *ptr1 == 'T' || - *ptr1 == 'a' || *ptr1 == 'A') - *hdutype = ASCII_TBL; - else if (*ptr1 == 'i' || *ptr1 == 'I') - *hdutype = IMAGE_HDU; - else - { - ffpmsg("unknown type of HDU in input URL:"); - ffpmsg(extspec); - return(*status = URL_PARSE_ERROR); - } - } - } - else - { - strcpy(tmpname, extname); - ffupch(tmpname); - if (!strcmp(tmpname, "PRIMARY") || !strcmp(tmpname, "P") ) - *extname = '\0'; /* return extnum = 0 */ - } - } - - ptr1 = strchr(ptr1, ';'); - if (ptr1) - { - /* an image is to be opened; the image is contained in a single */ - /* cell of a binary table. A column name and an expression to */ - /* determine which row to use has been entered. */ - - ptr1++; /* skip over the ';' delimiter */ - while (*ptr1 == ' ') /* skip over any leading blanks */ - ptr1++; - - ptr2 = strchr(ptr1, '('); - if (!ptr2) - { - ffpmsg("illegal specification of image in table cell in input URL:"); - ffpmsg(" did not find a row expression enclosed in ( )"); - ffpmsg(extspec); - return(*status = URL_PARSE_ERROR); - } - - if (ptr2 - ptr1 > FLEN_FILENAME - 1) - { - return(*status = URL_PARSE_ERROR); - } - - strncat(imagecolname, ptr1, ptr2 - ptr1); /* copy column name */ - - ptr2++; /* skip over the '(' delimiter */ - while (*ptr2 == ' ') /* skip over any leading blanks */ - ptr2++; - - - ptr1 = strchr(ptr2, ')'); - if (!ptr2) - { - ffpmsg("illegal specification of image in table cell in input URL:"); - ffpmsg(" missing closing ')' character in row expression"); - ffpmsg(extspec); - return(*status = URL_PARSE_ERROR); - } - - if (ptr1 - ptr2 > FLEN_FILENAME - 1) - { - return(*status = URL_PARSE_ERROR); - } - - strncat(rowexpress, ptr2, ptr1 - ptr2); /* row expression */ - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffextn(char *url, /* I - input filename/URL */ - int *extension_num, /* O - returned extension number */ - int *status) -{ -/* - Parse the input url string and return the number of the extension that - CFITSIO would automatically move to if CFITSIO were to open this input URL. - The extension numbers are one's based, so 1 = the primary array, 2 = the - first extension, etc. - - The extension number that gets returned is determined by the following - algorithm: - - 1. If the input URL includes a binning specification (e.g. - 'myfile.fits[3][bin X,Y]') then the returned extension number - will always = 1, since CFITSIO would create a temporary primary - image on the fly in this case. The same is true if an image - within a single cell of a binary table is opened. - - 2. Else if the input URL specifies an extension number (e.g., - 'myfile.fits[3]' or 'myfile.fits+3') then the specified extension - number (+ 1) is returned. - - 3. Else if the extension name is specified in brackets - (e.g., this 'myfile.fits[EVENTS]') then the file will be opened and searched - for the extension number. If the input URL is '-' (reading from the stdin - file stream) this is not possible and an error will be returned. - - 4. Else if the URL does not specify an extension (e.g. 'myfile.fits') then - a special extension number = -99 will be returned to signal that no - extension was specified. This feature is mainly for compatibility with - existing FTOOLS software. CFITSIO would open the primary array by default - (extension_num = 1) in this case. - -*/ - fitsfile *fptr; - char urltype[20]; - char infile[FLEN_FILENAME]; - char outfile[FLEN_FILENAME]; - char extspec[FLEN_FILENAME]; - char extname[FLEN_FILENAME]; - char rowfilter[FLEN_FILENAME]; - char binspec[FLEN_FILENAME]; - char colspec[FLEN_FILENAME]; - char imagecolname[FLEN_VALUE], rowexpress[FLEN_FILENAME]; - char *cptr; - int extnum, extvers, hdutype, tstatus = 0; - - if (*status > 0) - return(*status); - - /* parse the input URL into its basic components */ - fits_parse_input_url(url, urltype, infile, outfile, - extspec, rowfilter,binspec, colspec, status); - - if (*status > 0) - return(*status); - - if (*binspec) /* is there a binning specification? */ - { - *extension_num = 1; /* a temporary primary array image is created */ - return(*status); - } - - if (*extspec) /* is an extension specified? */ - { - ffexts(extspec, &extnum, - extname, &extvers, &hdutype, imagecolname, rowexpress, status); - - if (*status > 0) - return(*status); - - if (*imagecolname) /* is an image within a table cell being opened? */ - { - *extension_num = 1; /* a temporary primary array image is created */ - return(*status); - } - - if (*extname) - { - /* have to open the file to search for the extension name (curses!) */ - - if (!strcmp(urltype, "stdin://")) - /* opening stdin would destroying it! */ - return(*status = URL_PARSE_ERROR); - - /* First, strip off any filtering specification */ - infile[0] = '\0'; - strncat(infile, url, FLEN_FILENAME -1); - - cptr = strchr(infile, ']'); /* locate the closing bracket */ - if (!cptr) - { - return(*status = URL_PARSE_ERROR); - } - else - { - cptr++; - *cptr = '\0'; /* terminate URl after the extension spec */ - } - - if (ffopen(&fptr, infile, READONLY, status) > 0) /* open the file */ - { - ffclos(fptr, &tstatus); - return(*status); - } - - ffghdn(fptr, &extnum); /* where am I in the file? */ - *extension_num = extnum; - ffclos(fptr, status); - - return(*status); - } - else - { - *extension_num = extnum + 1; /* return the specified number (+ 1) */ - return(*status); - } - } - else - { - *extension_num = -99; /* no specific extension was specified */ - /* defaults to primary array */ - return(*status); - } -} -/*--------------------------------------------------------------------------*/ - -int ffurlt(fitsfile *fptr, char *urlType, int *status) -/* - return the prefix string associated with the driver in use by the - fitsfile pointer fptr -*/ - -{ - strcpy(urlType, driverTable[fptr->Fptr->driver].prefix); - return(*status); -} - -/*--------------------------------------------------------------------------*/ -int ffimport_file( char *filename, /* Text file to read */ - char **contents, /* Pointer to pointer to hold file */ - int *status ) /* CFITSIO error code */ -/* - Read and concatenate all the lines from the given text file. User - must free the pointer returned in contents. Pointer is guaranteed - to hold 2 characters more than the length of the text... allows the - calling routine to append (or prepend) a newline (or quotes?) without - reallocating memory. -*/ -{ - int allocLen, totalLen, llen, eoline = 1; - char *lines,line[256]; - FILE *aFile; - - if( *status > 0 ) return( *status ); - - totalLen = 0; - allocLen = 1024; - lines = (char *)malloc( allocLen * sizeof(char) ); - if( !lines ) { - ffpmsg("Couldn't allocate memory to hold ASCII file contents."); - return(*status = MEMORY_ALLOCATION ); - } - lines[0] = '\0'; - - if( (aFile = fopen( filename, "r" ))==NULL ) { - sprintf(line,"Could not open ASCII file %s.",filename); - ffpmsg(line); - free( lines ); - return(*status = FILE_NOT_OPENED); - } - - while( fgets(line,256,aFile)!=NULL ) { - llen = strlen(line); - if ( eoline && (llen > 1) && (line[0] == '/' && line[1] == '/')) - continue; /* skip comment lines begging with // */ - - eoline = 0; - - /* replace CR and newline chars at end of line with nulls */ - if ((llen > 0) && (line[llen-1]=='\n' || line[llen-1] == '\r')) { - line[--llen] = '\0'; - eoline = 1; /* found an end of line character */ - - if ((llen > 0) && (line[llen-1]=='\n' || line[llen-1] == '\r')) { - line[--llen] = '\0'; - } - } - - if( totalLen + llen + 3 >= allocLen ) { - allocLen += 256; - lines = (char *)realloc(lines, allocLen * sizeof(char) ); - if( ! lines ) { - ffpmsg("Couldn't allocate memory to hold ASCII file contents."); - *status = MEMORY_ALLOCATION; - break; - } - } - strcpy( lines+totalLen, line ); - totalLen += llen; - - if (eoline) { - strcpy( lines+totalLen, " "); /* add a space between lines */ - totalLen += 1; - } - } - fclose(aFile); - - *contents = lines; - return( *status ); -} - -/*--------------------------------------------------------------------------*/ -int fits_get_token(char **ptr, - char *delimiter, - char *token, - int *isanumber) /* O - is this token a number? */ -/* - parse off the next token, delimited by a character in 'delimiter', - from the input ptr string; increment *ptr to the end of the token. - Returns the length of the token, not including the delimiter char; -*/ -{ - char *loc, tval[73]; - int slen; - double dval; - - *token = '\0'; - - while (**ptr == ' ') /* skip over leading blanks */ - (*ptr)++; - - slen = strcspn(*ptr, delimiter); /* length of next token */ - if (slen) - { - strncat(token, *ptr, slen); /* copy token */ - - (*ptr) += slen; /* skip over the token */ - - if (isanumber) /* check if token is a number */ - { - *isanumber = 1; - - if (strchr(token, 'D')) { - strncpy(tval, token, 72); - tval[72] = '\0'; - - /* The C language does not support a 'D'; replace with 'E' */ - if ((loc = strchr(tval, 'D'))) *loc = 'E'; - - dval = strtod(tval, &loc); - } else { - dval = strtod(token, &loc); - } - - /* check for read error, or junk following the value */ - if (*loc != '\0' && *loc != ' ' ) *isanumber = 0; - if (errno == ERANGE) *isanumber = 0; - } - } - - return(slen); -} -/*--------------------------------------------------------------------------*/ -int fits_get_token2(char **ptr, - char *delimiter, - char **token, - int *isanumber, /* O - is this token a number? */ - int *status) - -/* - parse off the next token, delimited by a character in 'delimiter', - from the input ptr string; increment *ptr to the end of the token. - Returns the length of the token, not including the delimiter char; - - This routine allocates the *token string; the calling routine must free it -*/ -{ - char *loc, tval[73]; - int slen; - double dval; - - if (*status) - return(0); - - while (**ptr == ' ') /* skip over leading blanks */ - (*ptr)++; - - slen = strcspn(*ptr, delimiter); /* length of next token */ - if (slen) - { - *token = (char *) calloc(slen + 1, 1); - if (!(*token)) { - ffpmsg("Couldn't allocate memory to hold token string (fits_get_token2)."); - *status = MEMORY_ALLOCATION ; - return(0); - } - - strncat(*token, *ptr, slen); /* copy token */ - (*ptr) += slen; /* skip over the token */ - - if (isanumber) /* check if token is a number */ - { - *isanumber = 1; - - if (strchr(*token, 'D')) { - strncpy(tval, *token, 72); - tval[72] = '\0'; - - /* The C language does not support a 'D'; replace with 'E' */ - if ((loc = strchr(tval, 'D'))) *loc = 'E'; - - dval = strtod(tval, &loc); - } else { - dval = strtod(*token, &loc); - } - - /* check for read error, or junk following the value */ - if (*loc != '\0' && *loc != ' ' ) *isanumber = 0; - if (errno == ERANGE) *isanumber = 0; - } - } - - return(slen); -} -/*---------------------------------------------------------------------------*/ -char *fits_split_names( - char *list) /* I - input list of names */ -{ -/* - A sequence of calls to fits_split_names will split the input string - into name tokens. The string typically contains a list of file or - column names. The names must be delimited by a comma and/or spaces. - This routine ignores spaces and commas that occur within parentheses, - brackets, or curly brackets. It also strips any leading and trailing - blanks from the returned name. - - This routine is similar to the ANSI C 'strtok' function: - - The first call to fits_split_names has a non-null input string. - It finds the first name in the string and terminates it by - overwriting the next character of the string with a '\0' and returns - a pointer to the name. Each subsequent call, indicated by a NULL - value of the input string, returns the next name, searching from - just past the end of the previous name. It returns NULL when no - further names are found. - - The following line illustrates how a string would be split into 3 names: - myfile[1][bin (x,y)=4], file2.fits file3.fits - ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ - 1st name 2nd name 3rd name - - -NOTE: This routine is not thread-safe. -This routine is simply provided as a utility routine for other external -software. It is not used by any CFITSIO routine. - -*/ - int depth = 0; - char *start; - static char *ptr; - - if (list) /* reset ptr if a string is given */ - ptr = list; - - while (*ptr == ' ')ptr++; /* skip leading white space */ - - if (*ptr == '\0')return(0); /* no remaining file names */ - - start = ptr; - - while (*ptr != '\0') { - if ((*ptr == '[') || (*ptr == '(') || (*ptr == '{')) depth ++; - else if ((*ptr == '}') || (*ptr == ')') || (*ptr == ']')) depth --; - else if ((depth == 0) && (*ptr == ',' || *ptr == ' ')) { - *ptr = '\0'; /* terminate the filename here */ - ptr++; /* save pointer to start of next filename */ - break; - } - ptr++; - } - - return(start); -} -/*--------------------------------------------------------------------------*/ -int urltype2driver(char *urltype, int *driver) -/* - compare input URL with list of known drivers, returning the - matching driver numberL. -*/ - -{ - int ii; - - /* find matching driver; search most recent drivers first */ - - for (ii=no_of_drivers - 1; ii >= 0; ii--) - { - if (0 == strcmp(driverTable[ii].prefix, urltype)) - { - *driver = ii; - return(0); - } - } - - return(NO_MATCHING_DRIVER); -} -/*--------------------------------------------------------------------------*/ -int ffclos(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -/* - close the FITS file by completing the current HDU, flushing it to disk, - then calling the system dependent routine to physically close the FITS file -*/ -{ - int tstatus = NO_CLOSE_ERROR, zerostatus = 0; - - if (!fptr) - return(*status = NULL_INPUT_PTR); - else if ((fptr->Fptr)->validcode != VALIDSTRUC) /* check for magic value */ - return(*status = BAD_FILEPTR); - - /* close and flush the current HDU */ - if (*status > 0) - ffchdu(fptr, &tstatus); /* turn off the error message from ffchdu */ - else - ffchdu(fptr, status); - - ((fptr->Fptr)->open_count)--; /* decrement usage counter */ - - if ((fptr->Fptr)->open_count == 0) /* if no other files use structure */ - { - ffflsh(fptr, TRUE, status); /* flush and disassociate IO buffers */ - - /* call driver function to actually close the file */ - if ((*driverTable[(fptr->Fptr)->driver].close)((fptr->Fptr)->filehandle)) - { - if (*status <= 0) - { - *status = FILE_NOT_CLOSED; /* report if no previous error */ - - ffpmsg("failed to close the following file: (ffclos)"); - ffpmsg((fptr->Fptr)->filename); - } - } - - fits_clear_Fptr( fptr->Fptr, status); /* clear Fptr address */ - free((fptr->Fptr)->iobuffer); /* free memory for I/O buffers */ - free((fptr->Fptr)->headstart); /* free memory for headstart array */ - free((fptr->Fptr)->filename); /* free memory for the filename */ - (fptr->Fptr)->filename = 0; - (fptr->Fptr)->validcode = 0; /* magic value to indicate invalid fptr */ - free(fptr->Fptr); /* free memory for the FITS file structure */ - free(fptr); /* free memory for the FITS file structure */ - } - else - { - /* - to minimize the fallout from any previous error (e.g., trying to - open a non-existent extension in a already opened file), - always call ffflsh with status = 0. - */ - /* just flush the buffers, don't disassociate them */ - if (*status > 0) - ffflsh(fptr, FALSE, &zerostatus); - else - ffflsh(fptr, FALSE, status); - - free(fptr); /* free memory for the FITS file structure */ - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffdelt(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -/* - close and DELETE the FITS file. -*/ -{ - char *basename; - int slen, tstatus = NO_CLOSE_ERROR, zerostatus = 0; - - if (!fptr) - return(*status = NULL_INPUT_PTR); - else if ((fptr->Fptr)->validcode != VALIDSTRUC) /* check for magic value */ - return(*status = BAD_FILEPTR); - - if (*status > 0) - ffchdu(fptr, &tstatus); /* turn off the error message from ffchdu */ - else - ffchdu(fptr, status); - - ffflsh(fptr, TRUE, status); /* flush and disassociate IO buffers */ - - /* call driver function to actually close the file */ - if ( (*driverTable[(fptr->Fptr)->driver].close)((fptr->Fptr)->filehandle) ) - { - if (*status <= 0) - { - *status = FILE_NOT_CLOSED; /* report error if no previous error */ - - ffpmsg("failed to close the following file: (ffdelt)"); - ffpmsg((fptr->Fptr)->filename); - } - } - - /* call driver function to actually delete the file */ - if ( (driverTable[(fptr->Fptr)->driver].remove) ) - { - /* parse the input URL to get the base filename */ - slen = strlen((fptr->Fptr)->filename); - basename = (char *) malloc(slen +1); - if (!basename) - return(*status = MEMORY_ALLOCATION); - - fits_parse_input_url((fptr->Fptr)->filename, NULL, basename, NULL, NULL, NULL, NULL, - NULL, &zerostatus); - - if ((*driverTable[(fptr->Fptr)->driver].remove)(basename)) - { - ffpmsg("failed to delete the following file: (ffdelt)"); - ffpmsg((fptr->Fptr)->filename); - if (!(*status)) - *status = FILE_NOT_CLOSED; - } - free(basename); - } - - fits_clear_Fptr( fptr->Fptr, status); /* clear Fptr address */ - free((fptr->Fptr)->iobuffer); /* free memory for I/O buffers */ - free((fptr->Fptr)->headstart); /* free memory for headstart array */ - free((fptr->Fptr)->filename); /* free memory for the filename */ - (fptr->Fptr)->filename = 0; - (fptr->Fptr)->validcode = 0; /* magic value to indicate invalid fptr */ - free(fptr->Fptr); /* free memory for the FITS file structure */ - free(fptr); /* free memory for the FITS file structure */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fftrun( fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG filesize, /* I - size to truncate the file */ - int *status) /* O - error status */ -/* - low level routine to truncate a file to a new smaller size. -*/ -{ - if (driverTable[(fptr->Fptr)->driver].truncate) - { - ffflsh(fptr, FALSE, status); /* flush all the buffers first */ - (fptr->Fptr)->filesize = filesize; - (fptr->Fptr)->io_pos = filesize; - (fptr->Fptr)->logfilesize = filesize; - (fptr->Fptr)->bytepos = filesize; - ffbfeof(fptr, status); /* eliminate any buffers beyond current EOF */ - return (*status = - (*driverTable[(fptr->Fptr)->driver].truncate)((fptr->Fptr)->filehandle, - filesize) ); - } - else - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffflushx( FITSfile *fptr) /* I - FITS file pointer */ -/* - low level routine to flush internal file buffers to the file. -*/ -{ - if (driverTable[fptr->driver].flush) - return ( (*driverTable[fptr->driver].flush)(fptr->filehandle) ); - else - return(0); /* no flush function defined for this driver */ -} -/*--------------------------------------------------------------------------*/ -int ffseek( FITSfile *fptr, /* I - FITS file pointer */ - LONGLONG position) /* I - byte position to seek to */ -/* - low level routine to seek to a position in a file. -*/ -{ - return( (*driverTable[fptr->driver].seek)(fptr->filehandle, position) ); -} -/*--------------------------------------------------------------------------*/ -int ffwrite( FITSfile *fptr, /* I - FITS file pointer */ - long nbytes, /* I - number of bytes to write */ - void *buffer, /* I - buffer to write */ - int *status) /* O - error status */ -/* - low level routine to write bytes to a file. -*/ -{ - if ( (*driverTable[fptr->driver].write)(fptr->filehandle, buffer, nbytes) ) - { - ffpmsg("Error writing data buffer to file:"); - ffpmsg(fptr->filename); - - *status = WRITE_ERROR; - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffread( FITSfile *fptr, /* I - FITS file pointer */ - long nbytes, /* I - number of bytes to read */ - void *buffer, /* O - buffer to read into */ - int *status) /* O - error status */ -/* - low level routine to read bytes from a file. -*/ -{ - int readstatus; - - readstatus = (*driverTable[fptr->driver].read)(fptr->filehandle, - buffer, nbytes); - - if (readstatus == END_OF_FILE) - *status = END_OF_FILE; - else if (readstatus > 0) - { - ffpmsg("Error reading data buffer from file:"); - ffpmsg(fptr->filename); - - *status = READ_ERROR; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fftplt(fitsfile **fptr, /* O - FITS file pointer */ - const char *filename, /* I - name of file to create */ - const char *tempname, /* I - name of template file */ - int *status) /* IO - error status */ -/* - Create and initialize a new FITS file based on a template file. - Uses C fopen and fgets functions. -*/ -{ - *fptr = 0; /* initialize null file pointer, */ - /* regardless of the value of *status */ - if (*status > 0) - return(*status); - - if ( ffinit(fptr, filename, status) ) /* create empty file */ - return(*status); - - ffoptplt(*fptr, tempname, status); /* open and use template */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffoptplt(fitsfile *fptr, /* O - FITS file pointer */ - const char *tempname, /* I - name of template file */ - int *status) /* IO - error status */ -/* - open template file and use it to create new file -*/ -{ - fitsfile *tptr; - int tstatus = 0, nkeys, nadd, ii; - char card[FLEN_CARD]; - - if (*status > 0) - return(*status); - - if (tempname == NULL || *tempname == '\0') /* no template file? */ - return(*status); - - /* try opening template */ - ffopen(&tptr, (char *) tempname, READONLY, &tstatus); - - if (tstatus) /* not a FITS file, so treat it as an ASCII template */ - { - ffxmsg(2, card); /* clear the error message */ - fits_execute_template(fptr, (char *) tempname, status); - - ffmahd(fptr, 1, 0, status); /* move back to the primary array */ - return(*status); - } - else /* template is a valid FITS file */ - { - ffmahd(tptr, 1, NULL, status); /* make sure we are at the beginning */ - while (*status <= 0) - { - ffghsp(tptr, &nkeys, &nadd, status); /* get no. of keywords */ - - for (ii = 1; ii <= nkeys; ii++) /* copy keywords */ - { - ffgrec(tptr, ii, card, status); - - /* must reset the PCOUNT keyword to zero in the new output file */ - if (strncmp(card, "PCOUNT ",8) == 0) { /* the PCOUNT keyword? */ - if (strncmp(card+25, " 0", 5)) { /* non-zero value? */ - strncpy(card, "PCOUNT = 0", 30); - } - } - - ffprec(fptr, card, status); - } - - ffmrhd(tptr, 1, 0, status); /* move to next HDU until error */ - ffcrhd(fptr, status); /* create empty new HDU in output file */ - } - - if (*status == END_OF_FILE) - { - *status = 0; /* expected error condition */ - } - ffclos(tptr, status); /* close the template file */ - } - - ffmahd(fptr, 1, 0, status); /* move to the primary array */ - return(*status); -} -/*--------------------------------------------------------------------------*/ -void ffrprt( FILE *stream, int status) -/* - Print out report of cfitsio error status and messages on the error stack. - Uses C FILE stream. -*/ -{ - char status_str[FLEN_STATUS], errmsg[FLEN_ERRMSG]; - - if (status) - { - - fits_get_errstatus(status, status_str); /* get the error description */ - fprintf(stream, "\nFITSIO status = %d: %s\n", status, status_str); - - while ( fits_read_errmsg(errmsg) ) /* get error stack messages */ - fprintf(stream, "%s\n", errmsg); - } - return; -} -/*--------------------------------------------------------------------------*/ -int pixel_filter_helper( - fitsfile **fptr, /* IO - pointer to input image; on output it */ - /* points to the new image */ - char *outfile, /* I - name for output file */ - char *expr, /* I - Image filter expression */ - int *status) -{ - PixelFilter filter = { 0 }; - char * DEFAULT_TAG = "X"; - int ii, hdunum; - int singleHDU = 0; - - filter.count = 1; - filter.ifptr = fptr; - filter.tag = &DEFAULT_TAG; - - /* create new empty file for result */ - if (ffinit(&filter.ofptr, outfile, status) > 0) - { - ffpmsg("failed to create output file for pixel filter:"); - ffpmsg(outfile); - return(*status); - } - - fits_get_hdu_num(*fptr, &hdunum); /* current HDU number in input file */ - - expr += 3; /* skip 'pix' */ - switch (expr[0]) { - case 'b': - case 'B': filter.bitpix = BYTE_IMG; break; - case 'i': - case 'I': filter.bitpix = SHORT_IMG; break; - case 'j': - case 'J': filter.bitpix = LONG_IMG; break; - case 'r': - case 'R': filter.bitpix = FLOAT_IMG; break; - case 'd': - case 'D': filter.bitpix = DOUBLE_IMG; break; - } - if (filter.bitpix) /* skip bitpix indicator */ - ++expr; - - if (*expr == '1') { - ++expr; - singleHDU = 1; - } - - if (((*fptr)->Fptr)->only_one) - singleHDU = 1; - - if (*expr != ' ') { - ffpmsg("pixel filtering expression not space separated:"); - ffpmsg(expr); - } - while (*expr == ' ') - ++expr; - - /* copy all preceding extensions to the output file */ - for (ii = 1; !singleHDU && ii < hdunum; ii++) - { - fits_movabs_hdu(*fptr, ii, NULL, status); - if (fits_copy_hdu(*fptr, filter.ofptr, 0, status) > 0) - { - ffclos(filter.ofptr, status); - return(*status); - } - } - - /* move back to the original HDU position */ - fits_movabs_hdu(*fptr, hdunum, NULL, status); - - filter.expression = expr; - if (fits_pixel_filter(&filter, status)) { - ffpmsg("failed to execute image filter:"); - ffpmsg(expr); - ffclos(filter.ofptr, status); - return(*status); - } - - - /* copy any remaining HDUs to the output file */ - - for (ii = hdunum + 1; !singleHDU; ii++) - { - if (fits_movabs_hdu(*fptr, ii, NULL, status) > 0) - break; - - fits_copy_hdu(*fptr, filter.ofptr, 0, status); - } - - if (*status == END_OF_FILE) - *status = 0; /* got the expected EOF error; reset = 0 */ - else if (*status > 0) - { - ffclos(filter.ofptr, status); - return(*status); - } - - /* close the original file and return ptr to the new image */ - ffclos(*fptr, status); - - *fptr = filter.ofptr; /* reset the pointer to the new table */ - - /* move back to the image subsection */ - if (ii - 1 != hdunum) - fits_movabs_hdu(*fptr, hdunum, NULL, status); - - return(*status); -} diff --git a/src/external/OpenGR/3rdparty/cfitsio/cfitsio.pc.in b/src/external/OpenGR/3rdparty/cfitsio/cfitsio.pc.in deleted file mode 100644 index 2d884e0ed..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/cfitsio.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: cfitsio -Description: FITS File Subroutine Library -Version: @CFITSIO_MAJOR@.@CFITSIO_MINOR@ -Libs: -L${libdir} -lcfitsio @LIBS@ -Libs.private: -lm -Cflags: -I${includedir} diff --git a/src/external/OpenGR/3rdparty/cfitsio/cfitsio_mac.sit.hqx b/src/external/OpenGR/3rdparty/cfitsio/cfitsio_mac.sit.hqx deleted file mode 100644 index 0a3dbdfb3..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/cfitsio_mac.sit.hqx +++ /dev/null @@ -1 +0,0 @@ -(This file must be converted with BinHex 4.0) :$f0QDA4cD@pIE@&M,R0TG!"6594%8dP8)3#3"%11!*!%4HY6593K!!%!!%11FNa KG3*6!*!$&ZlZ)#!,BfCTG(0TEepYB@-!N"AR#BB"&J!9!U)"eJ#3!`-!N!q'!!! $([q3"!2JYCR`K,@Cp[N!N!8"mK%!N!C$#2r`rrJ!!-0!!!"0Y`!0$N0'DA4cD@p 38%-ZE@0`!*!4Da3*KJ#3$aB!!$i$!*!$&[q3"%e08(*$9dP&!3#[H%fHYCRfmJ# 3"3(U0!#3"Md0!!"9XJ#3"[8H"[LUJEpCRC+&h2,Qp5XR2!PhHq4S2H%,ApKQqmJ LNkpp8AlddNfr[1A)MP#1Tai![I"-haEmadlZiRN5eLh2&pPQYb@hMpc#pMQahU[ MjF@A)`YEb',mbF)EN!#&l)[`r)9RmFZHm#-lbAEK#qr)l6MKLpjbR($&#Ur-Vr0 fK0r#Ma`RA-)l22Q&,13AFTY-&L1cK5jN"9K($6SEG(C1mZ4R0R4JEhDp%a[NjC! $GhCHIV6,b@DM((4ffHR#LbqH!ph[phRj4[C&&ShX)r[YiRdmbHkebmMq[(KN$cV cFa#2l)[X86b,,-plB#b!Vl2VCAikk,fqbH,(bq[*l53meJ,!&[`"jhIkI5f1'd% 3,!Q#dUUJp-!lJY+$p5"BH5ma(bKeP6LDVcDZZdeKNN4a8UiQm9CAbqCLA5QIqP[ XPi0Jl8H#i"hHrpUqXi,J3lqkj2T6Yh"H2r[XNdTd(rB03A$L`5"Bk[dc2RMIZPh "b@rE'34[ackdki2h"FF(`H@c#NqI)P4GS[!F,Pp*9ei&5TqF6!e5'Z+9D"fM`h3 SKb"@J#a`!MD',FIf`[E'9Q$lB2YLqf(lBdr#RS`GJ$d&1a!l&(XDGKKf1,B5HcV f$1`)l*RBNGLcX'GMcm'HKld!Hb&f0$D-(B3GV&F8@iSYXeH9XJm!'S'I``l"RSX p(cX+1aCEK4f((@pf`QYP)SqYmP[j5"8[%qfa(pAKIHX%hY3A6jljZ2T8+l$Y9P+ 9ZSABJ5Ud2KH'fm*+)da6PhC[$C1M&eJq8#d2EIU0kPcTFK1[N!#9EL'@!Z3P+,c -9icR6L[c8`j9I`iR[I25%D#SDkA4H$YaNp&-Gc1XG32c$IHfjC@#kiCLM)K%k9U d0C!!+Y"B$PJ09iKRp+T'ImNm&#%J!p"afpL5RV[@,,R`mrF[ZH#ElqrD[qq5V[h AhHR6KErIYIm6PcaA6"*I""A*,da(Ij9Gqfr-+elX!'`CYKcE#pX2#j!!mKDmMrF f[!P[`aGVCh(5hqLkFX8[lETZ[FY'fki@68BZ'4rrPF(qU1%Ur52RpBmU,(M&e-r [ZMjp9qrk4M`40Y,amE22fMMRMCjalUk29a)ACUirLCZM'DkYiq-#6)e-2)$BNji $[H19,-l5)CG-ZI*`jkGdGbVIp'Te-(q&F1rJqXfekDJZ"VeXY&TjXIkPJR"+B'p X,f`j0LE!&GXAfcq[XZ"cN!$HrL9`cYkY)A1@E%VP'l5+hlRcbk0[mTDf2KX`YaX e[DrL-$5@ED`1G2ZkcR%$Fa@`J+rA8&Ll`)9ePk4(B5"I%%P5e4$j5bD8ZL99"C' %"%)')C`36FJTK2"&@%JPj,)HqlYBb1JU,136iJN"K@"#6L'VI1!b4*@kJP$@BGG L4Gh4a",#Z4rl8L`BHMX@BVS-#r0EJEd4Za,lHpJef*Z`P0R0f&Z`eGL*@0jl&aD -K&[`XMABGGK*f-RBLl$)*TGJT`JBa8l$6XI1`0CLRiqGLGf"[3%,JGq$I3N@rVF HHkYa$AMM[GJAB+r&3Z`KlK"pb2NXib@3!(k)1%)!K2[P15X)"&GM)IQ)!4"pq!T #!&`#-@!$&R5![%2Qlm4HJpf%I4lfaGM0@05cV9J)r6EXE1`Fl+ABZGKjf-Z`ml% ,X*GM&f,"JLZ`,m3ZaYiPU$4)UGRfhGJP@0',!Vq$[4Ul&,YDF#,f+Zc[B+r%hS0 YCr+j6bUTE-2`KTkK[Zkqc5UCjSmUeDA%`6[rejF4)l,TiR`brVA3*Hm,%a+b-,* 3m2Vmm)Grm!5eR`CPMk%khMkK4`-Vr9'@4R'j@Uf8aebD5H$HN!#%3R@q1)AA(!- ,*PeY!S[6i&1kHG`*(+DSEhGqHe)rN3YqQb2j1!RK3Fcr%)dV5eHAPR@*'(UI%,* )f"hrVb$680&UjfB4V1HqC*df[aL&i!5iCF2hhkV$Xr!4rp,Nc`R6Uq!!q&D2TeQ B,2,38L0LY!''CqYC[k2Ei6&eaif6jJX[#J$6`Cm+2mfIND*raNQlmN!cYD6qDhR iehPEAiE`T##&'[YlPQU9DGfVFiN+aG3d"p9Cr"U,Il(jejT5GAfZ@k+UQ[MRfAQ c2FC,l,`Pec"4*3dBEV-mfqdq1r+cj1VIXf&dS&`T9q*@'MGFZEpRl,pCY8HMYE" hS,I"43%j5H+E+PXTX"5C[L@5"*hjT*ck(p+-T'pPA6eAME"lC``ZA"'DN9&,k4l 3V35k$q"r4B!'5-[V2ffqh+G,[2'9A[C+-mQ4Hce6diRfMY3c"p(TcH-lB&51Ndq [$2IfR9iq[EGRV)IMSS(+Q"TA(#UI-kB[e`fL%R@hP1SR6VjaNXdRhjpH,Bp,dX- 85VFXPH*+Ve+iDrm(e&0&Ve"NH8pG[9G[aNDV88Xp2hqKFUUVaZSTqNGXbG"!4Xq 8bTZ'GimiHUU8),CXb,ASJe,U*bV2S1[LSrHS&biT)+AqS0jakVLrZJPI4G4Sb2F KI(e'Ym6dEDP[iqYl396Ar5"4rBELEIL#kKRV6eqQj!ZUEqNNA2)f3I8iREc$9HK &#UVhD8!MdYX%2iA[&-[h-AbRCT8ahLri(A`$XmE&p*Q&T$F-LPS9hLDN(V6"PDa ",eG)Z[q3!%E()H'(e&meY,&XP$Z&e&pfQ[Lcq2i3hl$H*#3qp(Pm`mH5N!#qYG" Am9@Z)&"m2m3RI@k)kQ(eJCh4UMYU+kbqY4'4VK%i6Ve5CrSqeV#8FGk"12VGk!r $pa!(5f(#AqC!2adqDY(fiN@NcG"I4`Pc2VpVrar!jb2U@EXJ1+&1r868mdCr(MR S4k1h$YmIF"MYm5$bjrM'H$b)2)"[V-H$b02iUM`H409R0XlM395pGH-p(N69qcA "id&8Me[Ym5#UrVf*(JqLYq#VmAJ3r5+q54i2SUV,b4i2BY+4,[*i%"0ZAHca)#E "i"+2"c(edNhap4h6@dleH"$6@dlcH"#l(Crdl9&rXDrMQf(jrN8BD2#J4$ed-cd HP+JAF*E(Ja,9j@b2"bAUmC[MmD"%IAQAHM`S89h1pAK3mL9mmc`HP$b+lc+2"k8 5$HCl2#K92b5pGG,69kSq3hVXj+e,e50*Vaep[26@JFY5ck9-Cp#pGb+2P0l"'5b @[X(5KcR6FbFpJDA2F1DY"&r+K$(df8Q2AjNN#RV[D)AQE[4,#T%S8lI3e4Hj5kR 4-Y@Pp!U'`BNbeHAbJ@DEZLN6hUqSELU$ifArJ1rDLi,cHEpb[HA+4PY[@*lhGPD [8FYJZIM%kNEj21URA2fAer@A"lKRZCT**#re9hiG[M8HrmVr'YpDMhrPUX[Vam+ %ZLNAaXM!MNTk+hZT6h$pU-Y)dNYeZD'-8hc8aNBh'X*EHUQ2%8iL$6Qpe)F)&i" Z[)8$[!2I"cR3qiM[#3kf@kUh-'EEijG)[ZNYE"A9X6Fb@1qmVr06Tk9I`3FhZQ& UEINqI25GlR`m&i&k#f0f5C38hr[`lHETjEkpralI(QT,F+Zh4QcFL'STp95KZVa THQd2H&#KZYbl*48Z93J,ETDL+6lHlKDAPDRV#YAPmrhp+X4ME[AhUp#dNaHdfa( [A[(2q&iS495S%lfKYjhILAMR2Z*aq`+5L`pFS2F5HJ@hi!haJ@(dkq*l0`GkGI( "AH"Sq,l,!Ei$(D-h&@k)MjjFqPcaJ5P`,RcdfG)ELZr9(+K(I1!@ICriU(AH&Kr FL$jKB)aq9[J12VJ42Dri`$,H#Kq#*Afdq(kI!p0,m,fI`rhQq`+(9jM[D3k[p,l qkUGpPIRJ%16(4mm`Ei@2IPfCQ+*pVqG!MH0$#RfYq6l2!4c$pkmFb!-9T5rh!I2 "Ym"Y69(PS&[6a8H0[G&m$h*iNrR!@VJN[Up`J"FE1!m%0jZ2AQ[i1$kDcmL2Mcj TX!iIp3b'ib2[@mhh%3j[-aqm"$b"*S0rEcFII2%GjU-Iq*hQJr[#FI"4jqmb(hF $0r"pQ!1F%4riqV$hR5)qqKlc`6RIDcl`'mc%4rr`RjL2HRl%I0bCZXEhF3l`1(` #[`(K#45(RZX2Q)qHG$J&2[UBVAapUM$ecmd(VX%&m&&,F(Cme"rk!ckd"pj6[S' 5T)R&"pHKM["4hr"@I1!([!mI[%dQlfJIZ)$QJ)qhi`haJAr`GhcJabHmEj!!qVi rD6l`$jc("liqEMjkh)@(D"pi*ra%qkM$6jX2[Jk'ii0,`8IN'b`"L9Kmp,6rMIR SdIjEmr&qi"Xqm)Lh`NHGJ+[ii)*Ip,iK`Sm[Q3m0!Nk+$rjNCh)-%Ik"DILS[kq D$hcL,[LS5HS1hcFiJ#(b$C@fK#D!$r`!Zr$4RdiHI25pIp0mF",d%(aJ)PL"MjV mP[QHj2"YlcY0'XChc%G0`hI``5HrCcii#6`,(aJRlGRDalYc&rQ'5926ij6%"ip mbRa`EMJ12ZB4r,2ji#(8*Mk`$#d#(l8"*XJhA'm2VmG(EF&Pm-(RIQ3qCK[)j#E YJdZBKS2!,i06RZ3hR$VaY-&+HR)BCD0pdVR!U!cY%rk[V(HP%TkZE,j&*4LJV21 m%La6[PFR8+BfY1iRhqQ3!"5PZ32iC,k#XZ&"Ti-V5[L-6rLRm[e$J90d*p-E&$K &8kUBJB#21m%aj6Z$'+8q&(`bld'*fq)6,UM8RB42hPjTlJ3qiA)U*d[L%kaAiT, i"&18Y"hj4R"rTEN(q%6c8MD$B!6m@`N(m%R6K4)1ia0m9H+-q)5V+"0J4i#$5V- Em%QY+XePN!$[61+91#!qi@G+I!fID"h+jPbF#6iTm3Km`Tq8G#eme"ED*Ml"%@A khdMH9jRq0e,eD[@rNHKH-J(0q!5cPI!"Rf#U-[e[*&a#L42K%ka4QVdKheR5)Uh qGaEDJM,plbcTY,U[4Ac#GC8d"(c#Se6HkL)q`@@Pq4[bRDekdYd[iT2l+'N#q%5 I8MB)kQc9+0SJ2Z($5[-hm)&2k$Ri")Z9jQl)G`ieVc4r!jr-he$5ar#*0UE`Dap B`P`1I033A!DIm#*Pc86RJ*8UEp!@D96U5QPZ"ci4UT4`(KmD0CS92Z(j5T`&Rr! pC6hIjm)IP'CNb(FH'+5N1H160e,Lb2L%IfZY'jr`HbAZL8riZC)`KSpDK,2J%`k JT2R)GciiSU6riC2l+r%&I05LkB31R)NHSD6ri411UU6ri42HSU6rbAH"-"KHJ%p U3%Nc`3IfS2rK%ae(L8[L%be!5DI&*aa5D9B)2[#-H4hbA3Jf+Fe9`3G1S,AL%`e 'LI2L%ae%5EI%*aa4L8[L!hIYh+C4F!1PH5li`(+d3Aab0bAY!Kpe3lm"2Y%[P$J M2Z'd5[UEI+-e$3JY!TpJNl*T1+1&$I!eI+*Y+G2r4ZXH9[mE$3G@T[q0d6fXrMG '2!$p%"mD-9S%2UN6C3eBBlL2N[D,$fjN1pI(L"m`4`DID!R+QN2'S%FScB("ar[ "fI%*MeALJ2L%[bPV[KX,$e(LFIJ%aj8d0(b#IFSDmmH#"8VD&$jk)Y#kmFPE+-e N`5HkQa*ra`GqfbEqX@J$b[5rX@J0b[5rXA"eCIVI@''`eIr'`L&eMiCm9A!YCIT I&Ca%QIjA*IbcqPq9"K0BrDq+qP5Qre@T&Uhq9i@ZSdcrUd,E8UEr9D'c+02rUX4 6VIih6K1BV2ih$JkM62mETlYDr@mFpDa-raY(,QAkhcLpYpAraSN6@2e[($aFQIi h(XkQ62mE,jjKpEra`L5VrifRaT6TIq24pC6TIq24UT6TIq24!*6TIq09deErQb# 1CI@r#F*1Urp08(eBr@q#kX2UIa1)9kEr64"rYIVI"(36CITIYDCH@[f['JkT62q VKQmSdrqUK3G@rkY@69MpVaTG6jRq9bd-X2TIY6LheImQ`Vf9kAm6iA[+p,q*F!p PqYp%m@1Vrde869[pEb*kRc,pEk,iK0Ar*UVQV2jA)kjMpEmDiBI9rfVJ)FVd[aV a4D[reBMh@2f[4M9YpEmD0#aPqPm01SXbr@q5F06UIj2%JDcq0dPFfHTrNm"LCIV I*1'heImQkAj@rjXNc,$khb6d(@Akhf6a2k[r6BDl+Y2r*N[RX2VIC$#DbCY1Q3r PUGI)m,#a8r0&eSpX0(SE@2U'3ph*@k+**%a%KDVl"`Elb$c1cZ2Y2-(1ARb0R6I Cq@)lAf,R+ADHDZGTGTjZjaPfVVAc6$[2X[0X1mqamk9fRQ[RHADqc-lclEc!cTI EHD'G&pQjbXjAf(Q*RCIDq8SlAfARCADqfXlAf(QjR9IBq9SlVl6c+MZ[Y[0eGUk cmaSlVlAcHMY[X20'R4QRD2eEl,c9cY[X[(fKRS1[ca[ejqI&[%PGB)%ZZdBr1rG I5+G1BX"G+P[)XT6EZCHGbaDbPLe9`a@6MlL#66"J)8(jm[PHGbm&F`R9mMIP+G6 199HAPTr8cMVT@ppq8Y6+bT16mQpH03NBV@I5Bq8CNqdX16B3XA9FTSpccS'T%Dd 6a6TlfeeId-ZiA,F#p%CIKPll'2SfFYB3,HI`iJ#3!-`NXe%!81m40qN5ekU4Bcd c8mf`B!e[$H-fRA!IC'YVU"C)YdX4Y03&l6V*83$Z@a"ea3aSG0B-SN-(%cXH1`& EMDh"EX*HM,d%1`A,hJ(6X01a-l#ef*PBV@1*RB1p&$XA1`pl'ABqGJ(fFZa#l#* X&IB+l",X8Zb9f+Z`bl"ABkr",XHZ`&k,ABPGK9f0[3jEKef$ABYGMpf!hBMG)U! AZ`flAB43E"!E`SDa6F``*bPZAcaQVT!!#f(B[NrMM8l@TEAGAJP@lE`m1'lANU" mmEU6ejkQMR$h,Iph+Fb86idDE*i)l`JB3"QDfphM1@``eKN`"GY&mECQP3(DCC& 5D)qPlCDf@YTMDBZP(CD''0TZDBHPcC!!pN,D#QQ*T4@@&PKDAfPjTG@9&PGD@fP TTC@9'U$eN!#@3eS0D6'N$C2f5pSZDEHNMC-f6GSYDE1N[C)f6pSiDDpNE!MM3KJ 63SXPVC@d90*+53XPVC1d60)U5BXNVC'dJc*+K"%LM!jKC!JYXE6#dJ*,kbXYYE6 -d[T+bbZYVV6FdP*,UbXYN!#d2Y,b5,XVEDkdYp,@5MXVEDbdVp+f5VXUEDUdjY) @56XNEC!!M$pTfN(&@aQ#m3@-,@"F!@-6')[!Z!*[0aA'%M#1J$%%6EZQ-&l!@qH "-3+-9fKDhB(fFpV1D6HRcCcfGGV6D61R[CbfFYVED9rheQI`eQ9)VXS!2D)Yh&[ c)ENq"'h`Y(V6iZfY'q'Y%m+S$'3e2BP8V,GALaf*%Grki0Lq,ibZB'3&SbVS&'0 -"H-T["eJ[,8N''-!@$-@JE%(b48I'*X!BKpDpB%a!i`AS(Z-F3+-%8#@C)3!S`- B'F#S!-E)b2JBhHl2k"K'aL!m-'U'N6'-LQ&8#Qh"Y-VbCV6MmfkdS20fM)TK4)b -2p(M0'3X$+-dp!J0aX)`GS*DCK3-)f!BrF,)&aReSXF2b,JE4Q``@S14'S`BB*` 'Bc4S#kFGR$C`fVpTqkEPR*CbfVjTpkE0QjCd@XYT+DIeR(C[fVaTlkDYQhCZfVK ThkCYQhCY@YTT@DGGQcCYfV0TbkBGQcCXfU0TLkBGQMCSfTpT[DDeQ[CRfTjTGkB eQaCV@UYT`DEYQACRfTaTEkDYQACQfTKTAkCYQGCZ@VGT@kCGQ6CPfT0T5kBGQI% XM'9K(!)M@4M&`SJA4VJ`LS84,)aHB33-ia-BmD&l4aM43#XiidBBad(E-f-!"(F CYm*S$dCk-'k&-5Z-@'$%#U09'+R#+"9'U$#HJ6%bM2aJe!FM2KM"`(J2aRS`KS2 a'icGB0`')cdBfF'i$FCX-&k$N4q-lQ#X"b-f'+h"5!e'D6"#Jp%CM-aJ9!BM-KL 0`8J-4Q%`!S24&ibmB03&Bd)BFm&i#mCD--j#Ml&Jc)q-pp%M*aMY`dJI4J8a#SL 42ScbBB32Sd!BT`'2BI3'A)C4([!B4[N``SIa'A!D'G[$'"BpIS@a2B`'J'm`USI a#Y!#16#+4ir!B2b#m"l'XM#1K6%AM',4)eJB9F#S%PVA'Bh*q!hDj)@6-)U#F4' -L@!m"+-X'%R"+!T'9M!QJ[%3M)@JCB!a%)arB1`$iaiBmm!S$%CG-1D"m3k-G@# F!f-F[2%0MS)2rM2k16(CU!5M$ZalURYfpJNEUH*SqmBHf[c'ai8a"rBp!lkHEL0 b('hI1*(94Pbiim#q*lma1hZhM8&cXRdZXadr4,pU@[Y"cm$pfHF%DFjdKFb`pkU MH5Upr4`8A5*Lk$Uid6E,1l"-95+9lNcSbD1l&hVbk!k(RMad39aEj+&,BQq4Kmk *L88H1JPULMad)H`UmS#TZiXmG#rX+I,3q6#Tb%2Aa13L$jd9&a9jk,kiZ-K$KmB P44kk0kB8HHM`Q&VNS3YN@T%(pA9kNBFZNKP&(MT0DSXmG+2-,2,3XA*VNBHZPPP &(P6&'iSmG-IX,2,33I1#)JmG0V1,2(6Kc#Rbd+PcDC'(ETkj44kkIHB9HHJ)ZUc )3pI3r#)2R88,LMadF&eHj+(lDf'4Kik3!%9&(VU1VLMbd('fZ-K$pp4Y44kkS*B 8HHKkfeINSIYNDC'(lT8VLcaddYeHj+(ElUSL$aej0aGjk0DlXmK$4ppG44kkrZi ZmY!CH-qL!Zpp1)m$k(2,,8VMVYR"bUf`E&rk5br5U1BQAcTK2PdCMSIkG-p8)c- bjAMD2(-r@##5KrlrB88HCJ--,r)`,f$S5hRL%'TA(kdXmM"[B0P,#N3b$l-)4QR 2S)C)rGPamcS2X`Xb(45qdkcjSdUeC*C2I2eV58KIXPRcCmI5+Mh3CXfIG41G+4C b[90jDUXa2G"QcCrYH@Z,@I1RVUd9AS,IiES$rAh-QMm,`MCeDYEmf65c$(ABV2Q M5P&UpaiDCXY4qmfD2lZA9EAbMelcCdCBQfDjd-H8Cee@4CN+D6C"T4YC6aG"Q+H 1VrNcJRZIiHm6*PE2Zj!![[Z`9$lQBB$'c"SC5CjbZcGpj9,cBFhaJ)",$hjBXaA S,qpI+KhhY1@4qSbSpTLE)HH)HX6T-jHHqmJ'lR1"ca04Qa4c0)3$4$5MK(NDV!M %h)l4j)RCIHbD$a(09V"V2N4jUm!j0,a('5GjTZ8KMQi%ZqC$9!SMA5Tb[qK[Fjp URbHUf5,-jC!![[@SjT6B04qLQJNa5H9[lc0jZU3kL!QrQ0NKq@*kViZe"T(N'6C rlfEFNf92jAh#c,[XUcc"rGH[mrH4&GGNKGLeE[N'YhepVpX@eIapYZIe,HjebeN Kad5Z@miU30C9ASNEF9)UYHV+)b[Ul$dRMbJID'ec#@X,LDpda)80bl-Z8jkkLBC EXE&GCmhA4G'-d'9"11d'aK4AbXT%UK6QH(Cp[4)hfkrMjV@0b,@bJGi961rDcCS lXeTCFZQ+8LPeqEh&bIX3*50jBqrUl8X5(N&#PV'5d2C5+9QQ2(YQF1[Vl-iI41T K%I8!CkJ-6JM[,j@@hZTakR+Rp`rZrkMLi5M%rq@K(LQTXbYmrEbalHXRF+IU4ee @ZTcYa9E6ec4HGj-mebQ2HNrT[F69-4,[qHCESac1JPY&JL9[U'JJYpPhNLR"68K !2ekU*mqK32Y5YrCiYEF%U01"(lX%aMBjLp4R*pNh`(30PeNVqUmqGdeMJ92P@c! kd,GbS*@jT-95Al0QfNK(khkiq@VR0pIjY+2FM'e&iecl[[c1GCd,"mD#ffkfMC) 8qiia14*5-KdCH0SC+frl@([P,BpFP8rm(FSSViUK[JdE%D*Z'4dE1CAckk[9@0, C"dHLZPUX2a%kl@SAH)KiE[AerSCfPJXm-6DN84Q"JpSQ9'jBK[Dj#ch[&,@&LAp 8lm!Bm@TYlq#`KV60MQSCpe)M[8QX)@+VMP[B86XFjF-0p8j!iDhj!%1plia#STD MhRp+aTd0+G[H4M,q6-4ZZbr22Se8X$[8l-[($EJS0[6dR@N*mTQ&,ZeH9@khca( )&Fh1,rU-*iM1(j,2lY6PJ2X!"6TZG2q(E"AUT-1&a'E9UmHM9T4&B52Dm6pXmMR GI[8iC(KVe++jcK&4)rqjDh-kU20,l1cUU&J&S'Y,NL-pCA4+Z`+kd`k[e@4fDY9 ITCT'6b33P,D5rpVVblAb49JC)0Qc[@[,$lZfDCD3!,"d,lF$i6[3TY'FiaGhFXj -3XQ0Gfhph#C5KrYfp4Uhh"3qedCcjh-AFYaqhLL9%`q%m4Q2IYS@bTEa'BrqK4E I&CmGRr(S*br4q)bcY1f$Zf4m4T!!@BP#V3bj!PPGCT!!Gq6EQ'AYYDYAEf9)bDL ddqUZaFh9l55ZGfTCZRTVIAVefGeRVkl(YA4ef)jX-A$(b'IQ*0#r`jb%dNAZjL3 X'"eF'fahbA4D(Xh#9Me-kVBjlFf+VD`Q$[cF`Gl!ejF[F'(G*BZ83BQ2#c'2#h@ eiG(bD+IGC[bdbidpq,J3@V4ZVNU*HP30AC!!YQJKMpZQIk*PZd!rIc#!hJ0EG*2 Y8dQSV9aF+Cp66Q28RiZLlr8DKK8Xakl!ASYGL9f&ABfp$PZ(AB0GLef2hB$GL0f #hBVGKQ8VRZkEHTY!R)JJp2SpXXefX*0H[dFZCqX5[pI[NI6HP6Gmqm'hD'GDPhU [RkYQ9T[$p3X1Imhf(T*pJ4CqDpeKIK!F[PGl8l[-2KI[,#Dhh+5q30IVmj9XcI3 $@9+,N!$C!i0p$0,SBqHqkdFfDP012R856DqTE#(,8QlRAREZ[C!!Y@bTfJ2T$Z3 +*'!e06p"qI,4YQ2B!QQm&(+(@&qL8E$KhlIcAIlX[F@*"-,iGaGYLdh6jh`Crfl feVCEDbrS0,)Sk)m54KiXF9009J!-V2AA&'@NFU#Tm8'bfrCP`9"edf(hM,$4L1- @-k@fY)1K6HA+kXUCCrT%bmV9-+f&MGblf1d)URhpKe1R(S#eZH81@q*0FG+SGpH J,22,P@lb92D(Umk0aYI8hpV08qLiaCe@&M8G`5DN,Y[#1CjVp1&FmK`YYf$1L9l AMaa,"SBhEPB@(CYk&aN%%9Kl0++T,NJ5Ih[VY'q29qcdY"PXVJchca@!MN[8Jdj UAiX,aPm[lY@#`2U`jKCH2&N-bDcQ2Ef)KZH63Y22P`UDh6-@V"ebbC3V$a2EN!" 4JJpNE,f'9aT0"4N[1hZa908hKc5PS6UD3jV5m)V0)C12EQMSqldCDC*NpNZ62l) M39)TIE%[QG!2@p1CR+3$9k"Yl54Mf$E&mQadYHQddm5eVKjPYEKKRShe$KiZXPB UcYTJbPQdFDbCmi#9aT0)XfR1ml`jcqBj6q)@2)Eal*P2ZFGbERDAiYJDeleM4mF H`$Ki!12K!Bb("c!HEQ-mA-CiH!$M5Gb#"c!HRYYk%XRe8iM,[!"iZUf6Cpqe2@c $AGILZUQ@GV*)3EZT-JRDJ+ZTiRHT$,R,MYT032r5@U--6QT)mV*Hf!ae(BENlA5 T(LBp#kQfNfCaXhb4Zh4lR066S+G@)j-JrHiYD6!@JTk3!+IG@G5D5Z&5d#Tj*Zf GdBNDGE5mh8QB"VhD%(5$5mSqCm$c"KD`P*ab6HeH&LBYIj'P9Dkic6@#JC(bF"Z XPh9hGJE',q*CV6qHPRHVMHYZ[@[P[TP4UN@rYV,iT54,2#SZ)5,Q[$2HbXUAPV$ B@`Yc5pab3a*hfX+(RHd`59dLZ,SaE)a2(R*S!-0"a@k-+"KG90ZR*l$LZMlCPJM qV'ZV%rEK%Dh6HREj))Y'*0f8K*1UD(&Yi8SEQ9qB`!J5l(468BbN%E$F!JUl1S+ SJeLmYPCl'EhhcXc-KrVS[56Z*$9A(NXF,3,a!VEF5aI2R%Bm33%Q+R46F`&-GM5 L@'jahG!*bAU,5Q!RLhhDU'@p[B1$clrAaM"apHITLeP@T#',af*p)XK9#+'9Ifl ,!MAF5E+YFEB`rm660dl+P3VcbCUSJ59,KYkYPRh@1`ehlEr`9XkX64S*MKr@-Y1 X@LS,C1L2*F'paJ9@5#eTD#eUXk5dV-L[2`4X6`9Kr9E@M1@l&mZJ8li(X$*QS%6 $%Gk,VE#iMf,l((`NU(2q'VE[a&Dj!XpLq`9[r$Xp)rGRK9KmJr,he-0EP0C326R 1%bVT)U`25`i@+QIe9h`XhbdM$A3q9RJG'2bH4LbShm)hU*dV,@SA"ePK9IYHcQ' )q@4PRm#E'r"bmE(dh'RXc5ip)HTfI-0q0MLCqP*I`$GF1l'+lh-F+VQS[*&kc0H DZYV@Lch$"#-'3Bm)lRJ,F8(G8eCFr3&E!J@erLUV`C+$qM[,Vd`De*,KCr[pMi* kVA1#%fqLI64i&Ejc[4i8[)EcHGVi6AbmdrPqilIJjr"GB(Ik,!G@A-A(ficLIP* 6`Ar$0pSM48Je1FDV6b&KJeh*0D5&jKP2MBmPbPNi(jrFd9[*0E5$`i5HUXC5K+l %9leqFideB%-I%,B)S5I(UcR8j*X3"CCSa-3NeB[ihXlC6UB+#4XZ#Zii$8`+I4E IaG5(e&Y)Up8bAS)FRq%`KIH6@JSpM'qUAi3PT(I9qTMiRZ6!Zq%$5eL&&VJ$5r4 VL!p-B@PkI&,EHM&kI+a$5`hL3beP$9amV"2,%[2iZ!q,bZ160pI,b10MZA8@MXF (AK+,$qaKFAKm9"M,`H0l)3I`#KmeEAZ-`X*1&RR(pcS1LmhhS'%b[SFiX*`l2M# *"GcaIB3$li!2!'@4GRaIi-#bl2LqaB&Da[F$$Lbp$J@J2X!FI'!Sq)N2hX##k[M !!TC3adFGk0%KiZ-GHA0ma,!`1Mj'V0Q&Db,##4BrahFA"`hfiJ-EE$Y,4'r-dZI ihX@"2LamImV"$Lk*h-2"-*(!mF)!kJZI`%)!h0'qTcR!Ck!c[+XGp4CP[9h0Ar# "`CBb4B9jGP1qU0E,K52J!hGXNdj8p8mM'6lUdfUe8G@2V!QXIEb['Bm51%&[FC2 jL,'E@dA&NfifhpdFU!YmVq"JPGbS10UYjRXV"pEfaFGUZq!'2M$b0[0pR)-G2K- 94YT9L+1UHcJ1[LFi[-Kmm"+`@VkBq-mGjQ0GAeB3aXGk[#mf(eJ'4Z'MYPRY&aq e4#hMidej6hcFl4lc`32fQimhVMFIY8iX2YB2&PkNIAr&!5k'MbfU`%0m2q4`RrF j,MkNqG%LL(i%[P%(pMh926[lK(%(4pXh&M'Q#4I'(0Mh$$cXG1-@MVC[($*'%bl FF@$INpqBREhli+*ZZ2#bI*ZR"Pai+AcKEE1cepkjL"XU1'G(HTYQ'HI+jjiEkHf H(c9C0fRp@$*UXSl4cmP4NhA@`Z8dqDaZ1NVVVGSb5(kf2dVRS6*HhM@h3'YUXmC i9XP$i,e&([TrlL[bX*lKX0IbR&K4I!kBmI41ZB(6hQJX2F"TmT(KA6CSpT!!"Ki DTqR(0-2fc)3Y%jFFf*@)5)hY5S5PKddP3QfACb+!k9kqemliLNFN*RfCN!$8[#m 6XLaUMHKa8N&lejahj,f)Q$96Fcb+M0p,ABV3YMFM029Q"(L[j$EkJX'*'q,@XI( 3DQLSZJK!ac$MPQ6`90fV$FMpr&bSiaq0,02EEC[RFr`HYF2[YaP"Z8rQI2+`(6P U'qQ2jR8FZXHmVFPN0rECGf@`f)*0&CYRGE`q&Sq1f)bXirGBfVGjV(YLBGHFjLm eCEEYdrIBQ$ArVrMe2CL5r&bpkRX8X*1TZ-9[q8"9Drhm&Mp!i194fqD9(ApA'4& YCeJGVrZGD@)c[SlIJfp8V3&,2[kZqKjk*YlaHaKqcqcE0VScC2%*TV0JD0!Qhq@ qaLR3"epqdH#2%1E`2C`"$'AKq4Iq'$NEaPQhISi+TP2!cY3SlSjlR(rQBJ(hk(b 3!*rHS`1!Ihk2)T)IZBFXd["rY@qBkI&kKERVHa4HSf(UH[ipGM#)f"&`Ml@[[Qc aA4P&k0fM(BPqHSmGVl,6iV['lq%%B1lk(VZF6DEmcHHHB0`bK,KVL%VMV2r@EeI @@56J(RbM+**Rhj@4UVibIc"*E2%*jZkSB+C1!14d+b$9SDpVKTEl3p14Tfelq@F dRG`ph#DUmc%Y*PXG[p"LZZja9)[TZXG4,DEl(NHdQ1)ph!YD60Ylr%U,b6hX-eT -m4j(YCLfDra5LqQkac%YjZ"&A!4D6'F1ZkG(amF5(m@lTKIpD2kF(jT1&SKqSHR N%GmCS1N8aelfV`aZY&Rj[rRSVh&2G&'i!lSIA#IG"PZ1-5rTHU@c+0(lf[$&'BT lSQ[KHUemHI`cpcL1`('QA'$FrriHlT[ZKpf,!Bb'PfE[FHH8&lUbddAp(ia!,Y* 4dFFB3GFpMM+#VRXF4I,ZHaa"mZ)pMQP9EIIiP9D9Hj!!Cj!!XhL2SmMCGSeI)QI A2BjT93F[%Vp(3Bk4HqKT#Zdjc$hd+R,CMdZX5ifmjr1i!638IBr#i'4INFJMQYa $9R&T[mI#LDdr[SGlGUTjFY&!GmVRSTYUIZ)10-f'lCG9[M0B%1@PC('jb4BXPb0 V62mNAeJj##l)8YH6JqdZQ8l,SeRBUSG*rG!+km6+hLakRf`4GkkRdD1ZlT*&bU$ %ai@Sa`AGdV@NdaEAF,Qa"amA3MNZ10b3!+$Kmh%KY[MXp$`VRlK@#Z#%Gf%R@2M !#@E#BUNR[K(kL&kLA$-LGK9hc(d+@0JD4Uh&RUT3aS[%1&ic[d9m5Vq)1b921FH ZEH-PLVNP`iXm[6QH9Z6T`h&SNBFK3*9&R[iFVhiT6hbVHiNkLH10Vp@&5$kIi6# S9'V9e8NY[X&C0@3D6@JP[L%0laZV0icJ8k8P'j3(Rm3a*@EBdVk'DkB-[5*SmhR ,H[XUSkA5H@[bqlcZQT-ICjPLh[BRXrrbR[RhNErXZlH@5YIZprF1RM`lqp4Q3Xr %MX5HK@AKBZEMMH$jcV(h18re+IB-,$1&,X"HL"f&(8fH-CDR#MX11ail!FZFQSR B'ZcTj*PNH5l#ASaP`#*,)c""4pifm'lXD[*iGF'XYKAB99LQK6-CD41@'YK-RLf @"dD`(FXXTaZ`G+%c*BJ"3#[*XmIbh)6GLi9C#Xr81&CLY4NQ6kRP!EGX5@YX!RF UX1"+Ar,dXcc81h8f!(X+pP6X308f45jj"PZHSF)YXFa"C-)4%hpRBDGJTj0RYZ@ j&(X*PL%YFl(cX-`eBi,b![*S("!I`iHZ`#l'-U0a+IC+l&ABUH4CCRQZ`5iAAL5 "5*Vf`cNJbDXE[(MYRH!&G6!02"J[j%TZ0a,2drMa5)(JjV1#kkkrPraPj"'mN6a 5%HSA5mHVU'kE9I`$`L2UMI[GAb*4iMl[2QFbrfl$Ip[Xi92LI4iiDal2IR$l[q2 C!ffl$r([1aS[q9qQr2(h14$r6VZIi1*69j)RD(Pi3M#!HZ(p)PerqYAbrqZ"pN0 acXqHR,jKG!#&EPXD0eajU02)SV@96TV&cI*&lY,YF9*2AdJa[9Cc+(Z,`Qc,Lr& ,3rS!GjG(ACC&VDNA8ma'%U`F#Y[YPa2-k%50HVP[*NYJcFha6!QSMHYZ[@Zp($i c5K%Jec8RT$kfjE"#69[dSL6HkQVCLf@LUA&Fh-aQ@"BQVCIIZ,Cr5+T8Fq6FNI* `1iZDdBlrZ*ZH#E1`Nl8l,ck1$XmrRSkrDZL&8,q68`TmQfZmN!$%m[RfelFTfTq ITX"m#40H,''rVl!Y@MSQXU'j!M(p,,N#N!#qQBlAed*&4`C8`[cMqb*L@l6hH[C FQ52Ur)LpV9-*UpG-(i0d%Z3!RHJ11#G"(X`*cd%jd9NJpi*c'1"PD#N8,lDeb(9 4j!%m%Am3[h4m-hJ6Pi0ZSV2!(3r12PJVD"0BJ'a5G!#fRb$hh&Q`pS)lbc3$e&j X'UEMJCPbb%%dd6Q!*VSGRSR2JV-AR(R+*$#RJZ@e1Q'B"$NB*VS$KNQ3!)GK`R- `6(3@KVhJA(el'9U+`S[0&88HKK2a"h&*acI$-(%j'#Bk#m2ai1b$YF)`J38B*N8 ($2X*FXqGK@%[Z,0--c$XaDCK1"kB+BFF$"1GJf'Lff'Bq#`-Hm'CTmc#m1bHX@- `6))F$"2G!F-Nb--`i6NB*MS,`ej`VVkp$#e&iFAQLL)2`iRiJlLNijYKQ,JF$"1 GKH&iF2E"@Q'B`!)-Nk)$K[d%ZHI1`V!Ah&QQ'4MfBY-`(!r-P%-1KSR1`6$4l6" -I"D'[H$-8ak!i4jCULK-p8K6AH*88CiU#&5(*+T1NDSJ8h8,9Ge598kX+XT9Km@ P(RQT4f!U5%b(4+C1Q5N[0"@NTU,B9*5EHU5IS[M6)rpd#8"&#DJJ!Kf5J6U&S)) 8e#d'GFY"18'S+!NG&R"k**`H%DFJia`5FMUPR,bB8j!!FiU#6P(5kC&ALJ*,Mm6 5*E)8CCD#d(*)DZN8@`Tb5lIJdLfjj%5ASZab@#6TN8PkK*+#9(*),1Q85r+#58% b+BSQ4GQNd-a4E1I)0h4d0bJ8@K3kQa3+E3S&GEbSMqF9mQl&Yk$jGUUq"Gfh)$F @"FHmj0JYS49%Y%iC,5ZN0DmEPqCF,6P5T+XP342VDXR43,YD-U4i9dZ#*2(+a+F )35D*,CG-H%Hp0*!!Veb+1,&T6@(S9dYSLRqe*%K#86Dqp3RR,L33-'T*IS$GY@4 *%V0-I&FKqY3X%`ihbmEQLc6&cPS5T1KC-X&5Pc)IDfFmPB609l%aP5J,N!#T,1d SQ8U8JmT8QLaHTV*N3$1G*&Z`k8c09C[1d9+H$F@9!p,Q2+eSfT!!j`#NTZ+cZ*V +NJ(A!dQk(VJ&CP-*1V%fP5S$Z1NN4iUi$AV61CV`pd##BK&NN6L9*3[(5pU1$@, *e3('ITSX&2XjfS(B6j1$B6p*&S6p("N)ENb4VGh'2-f9fjLKT5b6TC5$hR5@9Z" 0CMN!Zhjd&R6p("R)E8T4H03@Z2A$1m(@6j5"fXB8KiUe$@BE-c5"E&0ijl0R!GE 2NB9AM`l2G"1GU5QAP$dbYZDB29CpK9$VkTXIYUBk)A1m-aPQaV9M[,e40XlRk*! !9aSeYCB859%Y%cpVTZC!,e(6mLr[bfqCm#k@e&jrU83(Lr!!l@bYa(5D6$Nf-,K m6EBNkQEUqHT-jFQ8D$T*4jfQXa@*EkCLI8"YVpFNJ@bYeLE1dPUVM8NbPCSN![N k2C!!TNMVmMAUCmP8D'1+M[TXc0A*PlTVFffYpTp5!CPke!,5("%-b(4)-b"2Mfa !QL0!3kCZMF(,dX0F[93GaHJPkDR(3hT$)P%"Qh5LGY9"ef%"HXR4)dk3!1B35-I cG1JBm5cG*A-%p-Pd60JJea'1i'IU+F9Z[F6,FK4iZP36,dP11)PRk+UH([Q%0$d #*@N1XbB5G4-R,mY4lZ5PkbUFBMr3NVL6e&aj,('-`Zc3LKCh@S$R3E%(AM#R%8m !)Ch0,2J1*q,G1K+P1(cf&3r+,Le2QHjSq1RYZaieV6GdC22jErCG@m5*PPGY&)U 2hE[V44XjHMVAXYlH`F(RRmq%0(&e%jALj5DNLB1EU!DqE@*5h0U%T'ZL-Fc5Da1 9T0+*L"4l5B5e[E62RK-"(ZlDPfpJaFQJ11fb3BEY'ZF"[QILNM`X%G(mDUfeR!K 0[CT(Xha[kJe6p-Q%T+L5#@QN45BS5B%5%@QkN`KYHc1Ip53#@SRIaM"ap9FJe-4 hL%FQ48ie-[%GFT&*NGH*6)+F3'6L1e'q-8H,HQ45C'@M4(L1YLGbG(+$4*i@HTU )cPGYZi58c("3X,!CQN8M%eR38%b5V0#4##q@5MH05Z6*P8UVpZ'(jUSSThDBq*c -BH,Ep3f6)5YX*-)l&Be%RN1&NT%m%Y%(Ud(QDVF6!F)lH3!CmM5!m%i@3)Cf%N" mRJ-3AU!!U45Y$)!-13,J4HG"c8Y4+&8[6@ZPHX'j3Zh!rN5#0ZMA#9U3!*r!)[# 6)iIlAR5K3RT3hdZ6VC!!JjJIMmc@6Kla#Fm$2Z%GH%q#(0ald3@dpp,de%F@kle JV`UF5CqkYUj&(,HQfC&Y*BDcbH-T1iPVh+PS2PXTaK6AZ)1R@XAK(1,BcY(r2[A (@Lc4h#rdMr0aRbG1hd2ZPi`V[B`P"HcpNR'Vf1kap-&QPZpiP0bNmX-FRLD1R3r mZ0$6(#UE@ASNRp*D"[DGN[IVp4AZFN'cR4k*@r)P&MqFhmbQMVa6@&XqpZAH[,G r[jRD&Z,6cDc"HbAM*[`CprZckL$cQ82Iiqhe0TAb$IiDKe(YK+e$3RGp"KpE9FT h$aZaK!Gmh2YlP-2Q1eHA0h%2[4IID"phhkFiR1RMIU)FGLAr)GTUXFc(rGd`2MD [*0rM(1l0im,R2S52E5cPZeml,mccq4l8FMKX)mQ9EeqS*hq,K'dIeM+9YLlpZ-M 0(2CCAITaBH'%9cGqA&5EC`keZ[(MpYdbAamIdhD6GSZ2I3r1emFfE9eTGiLkij6 jqRMdER`,I0aGfJV5eXG,@IBaS+dhLI[#I(eFYaiI'e-5pr@jqJMYH4)I@e6+GlH fac6e%4j66E+GTP6kcSmXe)'r(QL81SlAJ4mArZK#25AcIA#K2[bi'2H,eiFI0dL EE*Vk#&qKQVEiqe%``pC(q'HZ*X$Z$R'UDXM84rJbl49P0h9mA*KNkL0mP6E*[0& i!29UkL0mm4I`X8%RqIjk(Mp'DKm0kJ+mCpF*@aq[%TEFl12k#*pUmVLq2a$'[F4 `p`dFH[Zi4l3Tk*hfVYqIbpG[ac*m$rLiJF*eQqq*hIM),eqrlmlIljZ2iRZ2MqZ [c8C0[RklKB[[pA&pYEQRHHr!pi9re"h[)AK[hcY`81rdQ)ql6(R0H`Iq4MjUJAZ `SjTjlm"REX)((`'R(jkrhkHI`XHpL101jRiUqD3+eF60qrVmrCl8Qhl-lXe@4HC qUNGepR'lamUjq`9M[4re5(f$8qCq`6F+Ym!%q9CqFqjq`HekXdrjZ$fU$h1ri)l 2iK-HT2%*(Q0`)R,5,q$lQ[%RkRb`MhZ0DSLkNqq2`0Q5YSm,kLfqlH2HIJHBGV+ 2Up,Z(YraeiL#0j9rjH0@LdYqeqjh,cEQmH16fZ6dHmEcK'F%l"jVK5AJ!h(ic(Y (hUQY8rr*iUM4#Rq2KiAh6eUp2U6,QlK(YENV03,ZISR$&"rhT,C#IFTi*29XlK' jm6&m2c4FNHeFe8-qVYHr%N#0JarJE#prMbm+qm!Vm!Rq8HAcVEJ0(cRPZi8kL&4 ph$4aPAme(JchXMMp0['-Ic-H`#DTDqcHi-(6aVHNEVckZ&YFlNIfIY5cVBpc2SE [aclZC'fiqL&r[fq)GpUY5%qqKhFGk11qqNrc&,C#m3rkHfb$0hLVcFD%XjCrI"q I-ZifK)e6JeB(Ei&2H#[6KS9h&PGQ82G+'#*IL6BZ+S1AJcXq[jQ+$K%U+epXpkr aCNVEbI*dXMeV++qRf1i9TjVq!-6GKkq[MkZ(@bYK[RbIH"rjq[ZiNm!QTBeQ`8Z iKHB0XGhh8@2+0Q)j9CaEmiEBqjk&HbPY2-XlNIF-Rkm5,&$'ef2S&UEqBVY[)*F b[PkLYp4i'G[p1Ef0jHX$a&%d(XGfGm(2e&NqVPceq6`Ipa%`5)%cZQlJ*b90pLT ,e)Cq*p&[!KpUKNGhAbX4(cEhVYr-9VNUhrK9q,&XH4YHjq1Q28#FfE&CR3l[-$J GfhX&@mFUEE[+m`S1'Cb1lAN%A&6#4[P1S`i-6XIfDQPETHeKjCXcAkreer2f#Vp q$lQIVBrkc@b4Ue4he-dr(-+Rf0irr#*aXTbXcJIqDGb0lGd%cLREb(B''mmDr)l Y$H"-5Y[CNNq`bZ"hE1m0ZJFEfa)(cl6hH#Am4QQ,@qLmE'aVm$Zfjbkp"j[Gb[F DX0$L5[e[`Qf8YYQ&(m#A0*l&pYccF@'-LGXXc$"i8lm6V85*Ji$Im(jlMhI`4SS Dj(XGA-6JI@c2RGmLMXf#jAX6ZSc&TrSEU3QPlAQTErL$a[[BRZpG54akMRbRL0F Ch0Vr-&LSE11AQ2L*`DhpGi%T5TbD1RMPI2fK"5MHAlp6R0r(p[kPhS-YGZ8E*Yc 4r##fG`IF58PMNDm@hF6`JpMH')kUT)2"ekN6c3pLHem(Pe2DJ"IHrm3KIL$i)4L Pa#APfiM@B[L"h%0d,28QidrS$JCIpcm+*e$D(*JiH*jp[dAS@1TYaZGiAiYc`IZ *XlVA32&JJkreTm+TP1PHmm!2Lkre[`kI8kClKD89fAZ-q50mFKGJlA,UfI$Df0j 2#!2Bh&MLVJ)$,&lZ[d[Da'Gph%e`"3m[[k)D%icPQi9qjZ(PD186rBV[IYl9`m[ TUPIi(Hq"eQMIqir&rG!*LB2[fATpC!mqZ$rm$lbf1,G!R"`p3Ei9UN@,Pkq(f`@ NGj%2($&iZIpCm$)JIB!ikX2HBk5`!&iXheid#3m[2kbDrRXIYdFkVF@jkQ[*`CE $8$MZBqYl`+IaIGR(E8AImI"bJIL0h8`iV$UhpbMrAAaImA%28cm@,qY6m@2"+,l h``-p[(`[R&qCRMTEqT("brTedP$J&q#Ik+mHAMi'Pe@fi9G)R0lJCAdGV89*2k3 1@1h-eTr@@RKciQK0X2AhQ',3#H@l9RU"`F[pMdQMK0m"0E)KQBHA&G*DV)Dm5hU (aFYDD3bm!lL1CQ$`X[l0dNVJ0I+pkX[cH$Ri6`K!db$IQqIamR%d+D80RAQR""q Y[dEB)abCEr!#AXj%Te&k%rPZ%kjB[0`RIX`fd2!Ep%',Pj23m*9d@RJ'HN1*jrF 2`1(9Z)rl!,JFbHXlF0a"Z*Db4@0,a31Y(V!6M&#f#QaIEE&XiL)R`&'9l8Sd8"K QimD+hjKGM03PB*9h[he`"LAq+mGedS00A138DPMC)T,$a5[X[GmRhQ#hqjUR,C* Yh2IJR-TfcC`R,,4a6iQAQ&fE9%6GH[Hq(Crb1U[DaqE0hVfMD!E+G0D9iZ[fr5k rN6LVXki8cl$hqaal-bRMlCY9ccEZafJJbVDT'b3F2kNC(qfV#1FiC2@5Z&lqr`d !"8PMEfi0D@p38%-ZE@0`!*!4H$-*KJ#3$iB!!$q)!*!$&J#3"'PMEfj038063!# eQI#%YCR`K!!!!HB!N!B"&3#3""F@!*!)JE)4!!JF[-XKL%Vqkr)IQ(qRr&[Nla6 hDYcMFCFjq"YaTmHeLN[2GdpFcRaEjcXYAk0m21qMq8VPh6[[,ARVj-h+FeLHar* XRZHi20im2E`Aj5RJ6I0HR2Y9EqIFjhU,j8l,I9eZP$XeGilF20HCZF[QV*!!Frm F0q9-c,&GMVGcP-Pa@1aj14V(GSQp1qE4f25BR@-hL'NEFkrRVTMdQ%GLYiSj-,D qXmMT%0kG+6`p!r+B3c"H,b-CF*54$%p[fY"-D$T(Emh-i#$Rk@eK'$HR8'ZQ(!T cYqY-%A+HIQQ%K@(XR2`ZdLmbcpr'-b3U-8II58AYQIfMclTCrUa,aK5GkLJ8DZY dYLC!(J4+k5cqV!ZZX3#3!`d0$&*&384045j0B@028f0`!*!4KZB*KJ#3$Mi$!!" $(J#3!aErN!4849K8G(4iG!%!VZP",E@CpXm!!!'X!!!%5`#3!md!!!*C*YQfB3# 3"M&!%3!)(1ad#')JLFI%1Rb*Jij4$SQpPB0bK,62fc8T)G'Ij216P-l"P'KkQ)V "9!65Xe)GTD5H!!J3)B2Y3fARKLIIKp0[UTHYN!"1TZXCRhC&(mcFBpDR'HL$*'B bTRkDJEjBKM3rJcd9[(l15!U(i9GF#&#aYR)HIf+0dbT$lV2bl"JXUUC$EZHE"al 2iakBaArh`'Q21'8UXp'm)bLH6D%Jj*ZT4*peCGa0ec5-ImP4+,3"j!m%ZqTYqZ6 3G)IlBUBS06Yib'K"cmeeX!8+SJ#!)!1BM"JC-!+`$L,X(*!!!I2)5Sk5@mQapmK 4)jc-'!()lfAi9c`$q#LHiJRk%3`%F23LI'9'RJd))mKJ"$&X*HX$!2R!j-"86Di hP&T,(j5qZD143lS3BL2ThP2PI'XI5AP$NipTUQ[5Y8[4mDG"DGPqH44E5H18D(G GRYhHlZ5J4h+q)$f2NA("kX4KNAR[25[cBc!alGMBre3)MJ2G"UBhKAa3RC@#L!k YLdqqiJYGlkUJ`N*eRJ92AV,"NXVII@4++M3fa6*3F@STdf5#C'1L-A!6e&"Bmk- i@SYrMNqP%#KPLKKmkB3@RNJV6mT!k,10E!"'#$la2"5TmcHT!P5IN3-mIH58Q96 #$lKPhbr8+NLf&J("!%4ND4QlQ0dA*j@UqNA-l&mPQMPd'+DhCae+d4&89pQj2k, C$*%#4#&Sih`6FaYB&mlVIM,@B(82mSImU#!"I(BSTA4f0&K[0Bhpe#"`31l*&!Q GjeQd21Fj9$,cK*Z5-6*A$6f@S"H0)mXXp68BV-T,`8&6,QpI3ZUC1dK"1cN)G&H &59X*!0YIFKAPj&eMT@k&q-$'e8kVj0K(+E'e@DqffpAjf3A41$Y%i#mMa'&E0V( @dUZSC--2ZAjm2YUCDYGEa'#3!%!*lImdGq`IE-J"rMa-*q8HPC2dkekJ#P#K3!U 6KaS80)bpFKkS&H0D+KTFM!Makqek*cDEeIVmVlaVp`MSlqK9EiHF[1p`(jN120# 90cC%kk9BRkifTk[eqXJhZ,jECVAm"V`IMITMrqNXlklhKl[p$@hPqZ48LRmK)3Y MCQPdFfP[AfeKB`#3&JQ'!4B!&3+L!GB!N!-"!!!rL!#3"aB!N!1'!!!$([q3"!2 JYCR`K,@Cp[N!N!8"mK%!N!C#Q2r`rrJ!!-0!!!!3DBZi!!!: \ No newline at end of file diff --git a/src/external/OpenGR/3rdparty/cfitsio/cfortran.h b/src/external/OpenGR/3rdparty/cfitsio/cfortran.h deleted file mode 100644 index 2142b18a7..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/cfortran.h +++ /dev/null @@ -1,2521 +0,0 @@ -/* cfortran.h 4.4 */ -/* http://www-zeus.desy.de/~burow/cfortran/ */ -/* Burkhard Burow burow@desy.de 1990 - 2002. */ - -#ifndef __CFORTRAN_LOADED -#define __CFORTRAN_LOADED - -/* - THIS FILE IS PROPERTY OF BURKHARD BUROW. IF YOU ARE USING THIS FILE YOU - SHOULD ALSO HAVE ACCESS TO CFORTRAN.DOC WHICH PROVIDES TERMS FOR USING, - MODIFYING, COPYING AND DISTRIBUTING THE CFORTRAN.H PACKAGE. -*/ - -/* The following modifications were made by the authors of CFITSIO or by me. - * They are flagged below with CFITSIO, the author's initials, or KMCCARTY. - * PDW = Peter Wilson - * DM = Doug Mink - * LEB = Lee E Brotzman - * MR = Martin Reinecke - * WDP = William D Pence - * -- Kevin McCarty, for Debian (19 Dec. 2005) */ - -/******* - Modifications: - Oct 1997: Changed symbol name extname to appendus (PDW/HSTX) - (Conflicted with a common variable name in FTOOLS) - Nov 1997: If g77Fortran defined, also define f2cFortran (PDW/HSTX) - Feb 1998: Let VMS see the NUM_ELEMS code. Lets programs treat - single strings as vectors with single elements - Nov 1999: If macintoxh defined, also define f2cfortran (for Mac OS-X) - Apr 2000: If WIN32 defined, also define PowerStationFortran and - VISUAL_CPLUSPLUS (Visual C++) - Jun 2000: If __GNUC__ and linux defined, also define f2cFortran - (linux/gcc environment detection) - Apr 2002: If __CYGWIN__ is defined, also define f2cFortran - Nov 2002: If __APPLE__ defined, also define f2cfortran (for Mac OS-X) - - Nov 2003: If __INTEL_COMPILER or INTEL_COMPILER defined, also define - f2cFortran (KMCCARTY) - Dec 2005: If f2cFortran is defined, enforce REAL functions in FORTRAN - returning "double" in C. This was one of the items on - Burkhard's TODO list. (KMCCARTY) - Dec 2005: Modifications to support 8-byte integers. (MR) - USE AT YOUR OWN RISK! - Feb 2006 Added logic to typedef the symbol 'LONGLONG' to an appropriate - intrinsic 8-byte integer datatype (WDP) - Apr 2006: Modifications to support gfortran (and g77 with -fno-f2c flag) - since by default it returns "float" for FORTRAN REAL function. - (KMCCARTY) - May 2008: Revert commenting out of "extern" in COMMON_BLOCK_DEF macro. - Add braces around do-nothing ";" in 3 empty while blocks to - get rid of compiler warnings. Thanks to ROOT developers - Jacek Holeczek and Rene Brun for these suggestions. (KMCCARTY) - Dec 2008 Added typedef for LONGLONG to support Borland compiler (WDP) - *******/ - -/* - Avoid symbols already used by compilers and system *.h: - __ - OSF1 zukal06 V3.0 347 alpha, cc -c -std1 cfortest.c - -*/ - -/* - Determine what 8-byte integer data type is available. - 'long long' is now supported by most compilers, but older - MS Visual C++ compilers before V7.0 use '__int64' instead. (WDP) -*/ - -#ifndef LONGLONG_TYPE /* this may have been previously defined */ -#if defined(_MSC_VER) /* Microsoft Visual C++ */ - -#if (_MSC_VER < 1300) /* versions earlier than V7.0 do not have 'long long' */ - typedef __int64 LONGLONG; -#else /* newer versions do support 'long long' */ - typedef long long LONGLONG; -#endif - -#elif defined( __BORLANDC__) /* (WDP) for the free Borland compiler, in particular */ - typedef __int64 LONGLONG; -#else - typedef long long LONGLONG; -#endif - -#define LONGLONG_TYPE -#endif - -/* Microsoft Visual C++ requires alternate form for static inline. */ -#if defined(_MSC_VER) /* Microsoft Visual C++ */ -#define STIN static __inline -#else -#define STIN static inline -#endif - -/* First prepare for the C compiler. */ - -#ifndef ANSI_C_preprocessor /* i.e. user can override. */ -#ifdef __CF__KnR -#define ANSI_C_preprocessor 0 -#else -#ifdef __STDC__ -#define ANSI_C_preprocessor 1 -#else -#define _cfleft 1 -#define _cfright -#define _cfleft_cfright 0 -#define ANSI_C_preprocessor _cfleft/**/_cfright -#endif -#endif -#endif - -#if ANSI_C_preprocessor -#define _0(A,B) A##B -#define _(A,B) _0(A,B) /* see cat,xcat of K&R ANSI C p. 231 */ -#define _2(A,B) A##B /* K&R ANSI C p.230: .. identifier is not replaced */ -#define _3(A,B,C) _(A,_(B,C)) -#else /* if it turns up again during rescanning. */ -#define _(A,B) A/**/B -#define _2(A,B) A/**/B -#define _3(A,B,C) A/**/B/**/C -#endif - -#if (defined(vax)&&defined(unix)) || (defined(__vax__)&&defined(__unix__)) -#define VAXUltrix -#endif - -#include /* NULL [in all machines stdio.h] */ -#include /* strlen, memset, memcpy, memchr. */ -#if !( defined(VAXUltrix) || defined(sun) || (defined(apollo)&&!defined(__STDCPP__)) ) -#include /* malloc,free */ -#else -#include /* Had to be removed for DomainOS h105 10.4 sys5.3 425t*/ -#ifdef apollo -#define __CF__APOLLO67 /* __STDCPP__ is in Apollo 6.8 (i.e. ANSI) and onwards */ -#endif -#endif - -#if !defined(__GNUC__) && !defined(__sun) && (defined(sun)||defined(VAXUltrix)||defined(lynx)) -#define __CF__KnR /* Sun, LynxOS and VAX Ultrix cc only supports K&R. */ - /* Manually define __CF__KnR for HP if desired/required.*/ -#endif /* i.e. We will generate Kernighan and Ritchie C. */ -/* Note that you may define __CF__KnR before #include cfortran.h, in order to -generate K&R C instead of the default ANSI C. The differences are mainly in the -function prototypes and declarations. All machines, except the Apollo, work -with either style. The Apollo's argument promotion rules require ANSI or use of -the obsolete std_$call which we have not implemented here. Hence on the Apollo, -only C calling FORTRAN subroutines will work using K&R style.*/ - - -/* Remainder of cfortran.h depends on the Fortran compiler. */ - -/* 11/29/2003 (KMCCARTY): add *INTEL_COMPILER symbols here */ -/* 04/05/2006 (KMCCARTY): add gFortran symbol here */ -#if defined(CLIPPERFortran) || defined(pgiFortran) || defined(__INTEL_COMPILER) || defined(INTEL_COMPILER) || defined(gFortran) -#define f2cFortran -#endif - -/* VAX/VMS does not let us \-split long #if lines. */ -/* Split #if into 2 because some HP-UX can't handle long #if */ -#if !(defined(NAGf90Fortran)||defined(f2cFortran)||defined(hpuxFortran)||defined(apolloFortran)||defined(sunFortran)||defined(IBMR2Fortran)||defined(CRAYFortran)) -#if !(defined(mipsFortran)||defined(DECFortran)||defined(vmsFortran)||defined(CONVEXFortran)||defined(PowerStationFortran)||defined(AbsoftUNIXFortran)||defined(AbsoftProFortran)||defined(SXFortran)) -/* If no Fortran compiler is given, we choose one for the machines we know. */ -#if defined(lynx) || defined(VAXUltrix) -#define f2cFortran /* Lynx: Only support f2c at the moment. - VAXUltrix: f77 behaves like f2c. - Support f2c or f77 with gcc, vcc with f2c. - f77 with vcc works, missing link magic for f77 I/O.*/ -#endif -/* 04/13/00 DM (CFITSIO): Add these lines for NT */ -/* with PowerStationFortran and and Visual C++ */ -#if defined(WIN32) && !defined(__CYGWIN__) -#define PowerStationFortran -#define VISUAL_CPLUSPLUS -#endif -#if defined(g77Fortran) /* 11/03/97 PDW (CFITSIO) */ -#define f2cFortran -#endif -#if defined(__CYGWIN__) /* 04/11/02 LEB (CFITSIO) */ -#define f2cFortran -#endif -#if defined(__GNUC__) && defined(linux) /* 06/21/00 PDW (CFITSIO) */ -#define f2cFortran -#endif -#if defined(macintosh) /* 11/1999 (CFITSIO) */ -#define f2cFortran -#endif -#if defined(__APPLE__) /* 11/2002 (CFITSIO) */ -#define f2cFortran -#endif -#if defined(__hpux) /* 921107: Use __hpux instead of __hp9000s300 */ -#define hpuxFortran /* Should also allow hp9000s7/800 use.*/ -#endif -#if defined(apollo) -#define apolloFortran /* __CF__APOLLO67 also defines some behavior. */ -#endif -#if defined(sun) || defined(__sun) -#define sunFortran -#endif -#if defined(_IBMR2) -#define IBMR2Fortran -#endif -#if defined(_CRAY) -#define CRAYFortran /* _CRAYT3E also defines some behavior. */ -#endif -#if defined(_SX) -#define SXFortran -#endif -#if defined(mips) || defined(__mips) -#define mipsFortran -#endif -#if defined(vms) || defined(__vms) -#define vmsFortran -#endif -#if defined(__alpha) && defined(__unix__) -#define DECFortran -#endif -#if defined(__convex__) -#define CONVEXFortran -#endif -#if defined(VISUAL_CPLUSPLUS) -#define PowerStationFortran -#endif -#endif /* ...Fortran */ -#endif /* ...Fortran */ - -/* Split #if into 2 because some HP-UX can't handle long #if */ -#if !(defined(NAGf90Fortran)||defined(f2cFortran)||defined(hpuxFortran)||defined(apolloFortran)||defined(sunFortran)||defined(IBMR2Fortran)||defined(CRAYFortran)) -#if !(defined(mipsFortran)||defined(DECFortran)||defined(vmsFortran)||defined(CONVEXFortran)||defined(PowerStationFortran)||defined(AbsoftUNIXFortran)||defined(AbsoftProFortran)||defined(SXFortran)) -/* If your compiler barfs on ' #error', replace # with the trigraph for # */ - #error "cfortran.h: Can't find your environment among:\ - - GNU gcc (g77) on Linux. \ - - MIPS cc and f77 2.0. (e.g. Silicon Graphics, DECstations, ...) \ - - IBM AIX XL C and FORTRAN Compiler/6000 Version 01.01.0000.0000 \ - - VAX VMS CC 3.1 and FORTRAN 5.4. \ - - Alpha VMS DEC C 1.3 and DEC FORTRAN 6.0. \ - - Alpha OSF DEC C and DEC Fortran for OSF/1 AXP Version 1.2 \ - - Apollo DomainOS 10.2 (sys5.3) with f77 10.7 and cc 6.7. \ - - CRAY \ - - NEC SX-4 SUPER-UX \ - - CONVEX \ - - Sun \ - - PowerStation Fortran with Visual C++ \ - - HP9000s300/s700/s800 Latest test with: HP-UX A.08.07 A 9000/730 \ - - LynxOS: cc or gcc with f2c. \ - - VAXUltrix: vcc,cc or gcc with f2c. gcc or cc with f77. \ - - f77 with vcc works; but missing link magic for f77 I/O. \ - - NO fort. None of gcc, cc or vcc generate required names.\ - - f2c/g77: Use #define f2cFortran, or cc -Df2cFortran \ - - gfortran: Use #define gFortran, or cc -DgFortran \ - (also necessary for g77 with -fno-f2c option) \ - - NAG f90: Use #define NAGf90Fortran, or cc -DNAGf90Fortran \ - - Absoft UNIX F77: Use #define AbsoftUNIXFortran or cc -DAbsoftUNIXFortran \ - - Absoft Pro Fortran: Use #define AbsoftProFortran \ - - Portland Group Fortran: Use #define pgiFortran \ - - Intel Fortran: Use #define INTEL_COMPILER" -/* Compiler must throw us out at this point! */ -#endif -#endif - - -#if defined(VAXC) && !defined(__VAXC) -#define OLD_VAXC -#pragma nostandard /* Prevent %CC-I-PARAMNOTUSED. */ -#endif - -/* Throughout cfortran.h we use: UN = Uppercase Name. LN = Lowercase Name. */ - -/* "extname" changed to "appendus" below (CFITSIO) */ -#if defined(f2cFortran) || defined(NAGf90Fortran) || defined(DECFortran) || defined(mipsFortran) || defined(apolloFortran) || defined(sunFortran) || defined(CONVEXFortran) || defined(SXFortran) || defined(appendus) -#define CFC_(UN,LN) _(LN,_) /* Lowercase FORTRAN symbols. */ -#define orig_fcallsc(UN,LN) CFC_(UN,LN) -#else -#if defined(CRAYFortran) || defined(PowerStationFortran) || defined(AbsoftProFortran) -#ifdef _CRAY /* (UN), not UN, circumvents CRAY preprocessor bug. */ -#define CFC_(UN,LN) (UN) /* Uppercase FORTRAN symbols. */ -#else /* At least VISUAL_CPLUSPLUS barfs on (UN), so need UN. */ -#define CFC_(UN,LN) UN /* Uppercase FORTRAN symbols. */ -#endif -#define orig_fcallsc(UN,LN) CFC_(UN,LN) /* CRAY insists on arg.'s here. */ -#else /* For following machines one may wish to change the fcallsc default. */ -#define CF_SAME_NAMESPACE -#ifdef vmsFortran -#define CFC_(UN,LN) LN /* Either case FORTRAN symbols. */ - /* BUT we usually use UN for C macro to FORTRAN routines, so use LN here,*/ - /* because VAX/VMS doesn't do recursive macros. */ -#define orig_fcallsc(UN,LN) UN -#else /* HP-UX without +ppu or IBMR2 without -qextname. NOT reccomended. */ -#define CFC_(UN,LN) LN /* Lowercase FORTRAN symbols. */ -#define orig_fcallsc(UN,LN) CFC_(UN,LN) -#endif /* vmsFortran */ -#endif /* CRAYFortran PowerStationFortran */ -#endif /* ....Fortran */ - -#define fcallsc(UN,LN) orig_fcallsc(UN,LN) -#define preface_fcallsc(P,p,UN,LN) CFC_(_(P,UN),_(p,LN)) -#define append_fcallsc(P,p,UN,LN) CFC_(_(UN,P),_(LN,p)) - -#define C_FUNCTION(UN,LN) fcallsc(UN,LN) -#define FORTRAN_FUNCTION(UN,LN) CFC_(UN,LN) - -#ifndef COMMON_BLOCK -#ifndef CONVEXFortran -#ifndef CLIPPERFortran -#if !(defined(AbsoftUNIXFortran)||defined(AbsoftProFortran)) -#define COMMON_BLOCK(UN,LN) CFC_(UN,LN) -#else -#define COMMON_BLOCK(UN,LN) _(_C,LN) -#endif /* AbsoftUNIXFortran or AbsoftProFortran */ -#else -#define COMMON_BLOCK(UN,LN) _(LN,__) -#endif /* CLIPPERFortran */ -#else -#define COMMON_BLOCK(UN,LN) _3(_,LN,_) -#endif /* CONVEXFortran */ -#endif /* COMMON_BLOCK */ - -#ifndef DOUBLE_PRECISION -#if defined(CRAYFortran) && !defined(_CRAYT3E) -#define DOUBLE_PRECISION long double -#else -#define DOUBLE_PRECISION double -#endif -#endif - -#ifndef FORTRAN_REAL -#if defined(CRAYFortran) && defined(_CRAYT3E) -#define FORTRAN_REAL double -#else -#define FORTRAN_REAL float -#endif -#endif - -#ifdef CRAYFortran -#ifdef _CRAY -#include -#else -#include "fortran.h" /* i.e. if crosscompiling assume user has file. */ -#endif -#define FLOATVVVVVVV_cfPP (FORTRAN_REAL *) /* Used for C calls FORTRAN. */ -/* CRAY's double==float but CRAY says pointers to doubles and floats are diff.*/ -#define VOIDP (void *) /* When FORTRAN calls C, we don't know if C routine - arg.'s have been declared float *, or double *. */ -#else -#define FLOATVVVVVVV_cfPP -#define VOIDP -#endif - -#ifdef vmsFortran -#if defined(vms) || defined(__vms) -#include -#else -#include "descrip.h" /* i.e. if crosscompiling assume user has file. */ -#endif -#endif - -#ifdef sunFortran -#if defined(sun) || defined(__sun) -#include /* Sun's FLOATFUNCTIONTYPE, ASSIGNFLOAT, RETURNFLOAT. */ -#else -#include "math.h" /* i.e. if crosscompiling assume user has file. */ -#endif -/* At least starting with the default C compiler SC3.0.1 of SunOS 5.3, - * FLOATFUNCTIONTYPE, ASSIGNFLOAT, RETURNFLOAT are not required and not in - * , since sun C no longer promotes C float return values to doubles. - * Therefore, only use them if defined. - * Even if gcc is being used, assume that it exhibits the Sun C compiler - * behavior in order to be able to use *.o from the Sun C compiler. - * i.e. If FLOATFUNCTIONTYPE, etc. are in math.h, they required by gcc. - */ -#endif - -#ifndef apolloFortran -#define COMMON_BLOCK_DEF(DEFINITION, NAME) extern DEFINITION NAME -#define CF_NULL_PROTO -#else /* HP doesn't understand #elif. */ -/* Without ANSI prototyping, Apollo promotes float functions to double. */ -/* Note that VAX/VMS, IBM, Mips choke on 'type function(...);' prototypes. */ -#define CF_NULL_PROTO ... -#ifndef __CF__APOLLO67 -#define COMMON_BLOCK_DEF(DEFINITION, NAME) \ - DEFINITION NAME __attribute((__section(NAME))) -#else -#define COMMON_BLOCK_DEF(DEFINITION, NAME) \ - DEFINITION NAME #attribute[section(NAME)] -#endif -#endif - -#ifdef __cplusplus -#undef CF_NULL_PROTO -#define CF_NULL_PROTO ... -#endif - - -#ifndef USE_NEW_DELETE -#ifdef __cplusplus -#define USE_NEW_DELETE 1 -#else -#define USE_NEW_DELETE 0 -#endif -#endif -#if USE_NEW_DELETE -#define _cf_malloc(N) new char[N] -#define _cf_free(P) delete[] P -#else -#define _cf_malloc(N) (char *)malloc(N) -#define _cf_free(P) free(P) -#endif - -#ifdef mipsFortran -#define CF_DECLARE_GETARG int f77argc; char **f77argv -#define CF_SET_GETARG(ARGC,ARGV) f77argc = ARGC; f77argv = ARGV -#else -#define CF_DECLARE_GETARG -#define CF_SET_GETARG(ARGC,ARGV) -#endif - -#ifdef OLD_VAXC /* Allow %CC-I-PARAMNOTUSED. */ -#pragma standard -#endif - -#define AcfCOMMA , -#define AcfCOLON ; - -/*-------------------------------------------------------------------------*/ - -/* UTILITIES USED WITHIN CFORTRAN.H */ - -#define _cfMIN(A,B) (As) { /* Need this to handle NULL string.*/ - while (e>s && *--e==t) {;} /* Don't follow t's past beginning. */ - e[*e==t?0:1] = '\0'; /* Handle s[0]=t correctly. */ -} return s; } - -/* kill_trailingn(s,t,e) will kill the trailing t's in string s. e normally -points to the terminating '\0' of s, but may actually point to anywhere in s. -s's new '\0' will be placed at e or earlier in order to remove any trailing t's. -If es) { /* Watch out for neg. length string.*/ - while (e>s && *--e==t){;} /* Don't follow t's past beginning. */ - e[*e==t?0:1] = '\0'; /* Handle s[0]=t correctly. */ -} return s; } - -/* Note the following assumes that any element which has t's to be chopped off, -does indeed fill the entire element. */ -#ifndef __CF__KnR -static char *vkill_trailing(char* cstr, int elem_len, int sizeofcstr, char t) -#else -static char *vkill_trailing( cstr, elem_len, sizeofcstr, t) - char* cstr; int elem_len; int sizeofcstr; char t; -#endif -{ int i; -for (i=0; i= 4.3 gives message: - zow35> cc -c -DDECFortran cfortest.c - cfe: Fatal: Out of memory: cfortest.c - zow35> - Old __hpux had the problem, but new 'HP-UX A.09.03 A 9000/735' is fine - if using -Aa, otherwise we have a problem. - */ -#ifndef MAX_PREPRO_ARGS -#if !defined(__GNUC__) && (defined(VAXUltrix) || defined(__CF__APOLLO67) || (defined(sun)&&!defined(__sun)) || defined(_CRAY) || defined(__ultrix__) || (defined(__hpux)&&defined(__CF__KnR))) -#define MAX_PREPRO_ARGS 31 -#else -#define MAX_PREPRO_ARGS 99 -#endif -#endif - -#if defined(AbsoftUNIXFortran) || defined(AbsoftProFortran) -/* In addition to explicit Absoft stuff, only Absoft requires: - - DEFAULT coming from _cfSTR. - DEFAULT could have been called e.g. INT, but keep it for clarity. - - M term in CFARGT14 and CFARGT14FS. - */ -#define ABSOFT_cf1(T0) _(T0,_cfSTR)(0,ABSOFT1,0,0,0,0,0) -#define ABSOFT_cf2(T0) _(T0,_cfSTR)(0,ABSOFT2,0,0,0,0,0) -#define ABSOFT_cf3(T0) _(T0,_cfSTR)(0,ABSOFT3,0,0,0,0,0) -#define DEFAULT_cfABSOFT1 -#define LOGICAL_cfABSOFT1 -#define STRING_cfABSOFT1 ,MAX_LEN_FORTRAN_FUNCTION_STRING -#define DEFAULT_cfABSOFT2 -#define LOGICAL_cfABSOFT2 -#define STRING_cfABSOFT2 ,unsigned D0 -#define DEFAULT_cfABSOFT3 -#define LOGICAL_cfABSOFT3 -#define STRING_cfABSOFT3 ,D0 -#else -#define ABSOFT_cf1(T0) -#define ABSOFT_cf2(T0) -#define ABSOFT_cf3(T0) -#endif - -/* _Z introduced to cicumvent IBM and HP silly preprocessor warning. - e.g. "Macro CFARGT14 invoked with a null argument." - */ -#define _Z - -#define CFARGT14S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - S(T1,1) S(T2,2) S(T3,3) S(T4,4) S(T5,5) S(T6,6) S(T7,7) \ - S(T8,8) S(T9,9) S(TA,10) S(TB,11) S(TC,12) S(TD,13) S(TE,14) -#define CFARGT27S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ - S(T1,1) S(T2,2) S(T3,3) S(T4,4) S(T5,5) S(T6,6) S(T7,7) \ - S(T8,8) S(T9,9) S(TA,10) S(TB,11) S(TC,12) S(TD,13) S(TE,14) \ - S(TF,15) S(TG,16) S(TH,17) S(TI,18) S(TJ,19) S(TK,20) S(TL,21) \ - S(TM,22) S(TN,23) S(TO,24) S(TP,25) S(TQ,26) S(TR,27) - -#define CFARGT14FS(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ - F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ - M CFARGT14S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) -#define CFARGT27FS(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ - F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ - F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ - F(TF,15,1) F(TG,16,1) F(TH,17,1) F(TI,18,1) F(TJ,19,1) F(TK,20,1) F(TL,21,1) \ - F(TM,22,1) F(TN,23,1) F(TO,24,1) F(TP,25,1) F(TQ,26,1) F(TR,27,1) \ - M CFARGT27S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) - -#if !(defined(PowerStationFortran)||defined(hpuxFortran800)) -/* Old CFARGT14 -> CFARGT14FS as seen below, for Absoft cross-compile yields: - SunOS> cc -c -Xa -DAbsoftUNIXFortran c.c - "c.c", line 406: warning: argument mismatch - Haven't checked if this is ANSI C or a SunOS bug. SunOS -Xs works ok. - Behavior is most clearly seen in example: - #define A 1 , 2 - #define C(X,Y,Z) x=X. y=Y. z=Z. - #define D(X,Y,Z) C(X,Y,Z) - D(x,A,z) - Output from preprocessor is: x = x . y = 1 . z = 2 . - #define CFARGT14(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - CFARGT14FS(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) -*/ -#define CFARGT14(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ - F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ - M CFARGT14S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) -#define CFARGT27(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ - F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ - F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ - F(TF,15,1) F(TG,16,1) F(TH,17,1) F(TI,18,1) F(TJ,19,1) F(TK,20,1) F(TL,21,1) \ - F(TM,22,1) F(TN,23,1) F(TO,24,1) F(TP,25,1) F(TQ,26,1) F(TR,27,1) \ - M CFARGT27S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) - -#define CFARGT20(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ - F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ - F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ - F(TF,15,1) F(TG,16,1) F(TH,17,1) F(TI,18,1) F(TJ,19,1) F(TK,20,1) \ - S(T1,1) S(T2,2) S(T3,3) S(T4,4) S(T5,5) S(T6,6) S(T7,7) \ - S(T8,8) S(T9,9) S(TA,10) S(TB,11) S(TC,12) S(TD,13) S(TE,14) \ - S(TF,15) S(TG,16) S(TH,17) S(TI,18) S(TJ,19) S(TK,20) -#define CFARGTA14(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE) \ - F(T1,A1,1,0) F(T2,A2,2,1) F(T3,A3,3,1) F(T4,A4,4,1) F(T5,A5,5,1) F(T6,A6,6,1) \ - F(T7,A7,7,1) F(T8,A8,8,1) F(T9,A9,9,1) F(TA,AA,10,1) F(TB,AB,11,1) F(TC,AC,12,1) \ - F(TD,AD,13,1) F(TE,AE,14,1) S(T1,1) S(T2,2) S(T3,3) S(T4,4) \ - S(T5,5) S(T6,6) S(T7,7) S(T8,8) S(T9,9) S(TA,10) \ - S(TB,11) S(TC,12) S(TD,13) S(TE,14) -#if MAX_PREPRO_ARGS>31 -#define CFARGTA20(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) \ - F(T1,A1,1,0) F(T2,A2,2,1) F(T3,A3,3,1) F(T4,A4,4,1) F(T5,A5,5,1) F(T6,A6,6,1) \ - F(T7,A7,7,1) F(T8,A8,8,1) F(T9,A9,9,1) F(TA,AA,10,1) F(TB,AB,11,1) F(TC,AC,12,1) \ - F(TD,AD,13,1) F(TE,AE,14,1) F(TF,AF,15,1) F(TG,AG,16,1) F(TH,AH,17,1) F(TI,AI,18,1) \ - F(TJ,AJ,19,1) F(TK,AK,20,1) S(T1,1) S(T2,2) S(T3,3) S(T4,4) \ - S(T5,5) S(T6,6) S(T7,7) S(T8,8) S(T9,9) S(TA,10) \ - S(TB,11) S(TC,12) S(TD,13) S(TE,14) S(TF,15) S(TG,16) \ - S(TH,17) S(TI,18) S(TJ,19) S(TK,20) -#define CFARGTA27(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) \ - F(T1,A1,1,0) F(T2,A2,2,1) F(T3,A3,3,1) F(T4,A4,4,1) F(T5,A5,5,1) F(T6,A6,6,1) \ - F(T7,A7,7,1) F(T8,A8,8,1) F(T9,A9,9,1) F(TA,AA,10,1) F(TB,AB,11,1) F(TC,AC,12,1) \ - F(TD,AD,13,1) F(TE,AE,14,1) F(TF,AF,15,1) F(TG,AG,16,1) F(TH,AH,17,1) F(TI,AI,18,1) \ - F(TJ,AJ,19,1) F(TK,AK,20,1) F(TL,AL,21,1) F(TM,AM,22,1) F(TN,AN,23,1) F(TO,AO,24,1) \ - F(TP,AP,25,1) F(TQ,AQ,26,1) F(TR,AR,27,1) S(T1,1) S(T2,2) S(T3,3) \ - S(T4,4) S(T5,5) S(T6,6) S(T7,7) S(T8,8) S(T9,9) \ - S(TA,10) S(TB,11) S(TC,12) S(TD,13) S(TE,14) S(TF,15) \ - S(TG,16) S(TH,17) S(TI,18) S(TJ,19) S(TK,20) S(TL,21) \ - S(TM,22) S(TN,23) S(TO,24) S(TP,25) S(TQ,26) S(TR,27) -#endif -#else -#define CFARGT14(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - F(T1,1,0) S(T1,1) F(T2,2,1) S(T2,2) F(T3,3,1) S(T3,3) F(T4,4,1) S(T4,4) \ - F(T5,5,1) S(T5,5) F(T6,6,1) S(T6,6) F(T7,7,1) S(T7,7) F(T8,8,1) S(T8,8) \ - F(T9,9,1) S(T9,9) F(TA,10,1) S(TA,10) F(TB,11,1) S(TB,11) F(TC,12,1) S(TC,12) \ - F(TD,13,1) S(TD,13) F(TE,14,1) S(TE,14) -#define CFARGT27(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ - F(T1,1,0) S(T1,1) F(T2,2,1) S(T2,2) F(T3,3,1) S(T3,3) F(T4,4,1) S(T4,4) \ - F(T5,5,1) S(T5,5) F(T6,6,1) S(T6,6) F(T7,7,1) S(T7,7) F(T8,8,1) S(T8,8) \ - F(T9,9,1) S(T9,9) F(TA,10,1) S(TA,10) F(TB,11,1) S(TB,11) F(TC,12,1) S(TC,12) \ - F(TD,13,1) S(TD,13) F(TE,14,1) S(TE,14) F(TF,15,1) S(TF,15) F(TG,16,1) S(TG,16) \ - F(TH,17,1) S(TH,17) F(TI,18,1) S(TI,18) F(TJ,19,1) S(TJ,19) F(TK,20,1) S(TK,20) \ - F(TL,21,1) S(TL,21) F(TM,22,1) S(TM,22) F(TN,23,1) S(TN,23) F(TO,24,1) S(TO,24) \ - F(TP,25,1) S(TP,25) F(TQ,26,1) S(TQ,26) F(TR,27,1) S(TR,27) - -#define CFARGT20(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ - F(T1,1,0) S(T1,1) F(T2,2,1) S(T2,2) F(T3,3,1) S(T3,3) F(T4,4,1) S(T4,4) \ - F(T5,5,1) S(T5,5) F(T6,6,1) S(T6,6) F(T7,7,1) S(T7,7) F(T8,8,1) S(T8,8) \ - F(T9,9,1) S(T9,9) F(TA,10,1) S(TA,10) F(TB,11,1) S(TB,11) F(TC,12,1) S(TC,12) \ - F(TD,13,1) S(TD,13) F(TE,14,1) S(TE,14) F(TF,15,1) S(TF,15) F(TG,16,1) S(TG,16) \ - F(TH,17,1) S(TH,17) F(TI,18,1) S(TI,18) F(TJ,19,1) S(TJ,19) F(TK,20,1) S(TK,20) -#define CFARGTA14(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE) \ - F(T1,A1,1,0) S(T1,1) F(T2,A2,2,1) S(T2,2) F(T3,A3,3,1) S(T3,3) \ - F(T4,A4,4,1) S(T4,4) F(T5,A5,5,1) S(T5,5) F(T6,A6,6,1) S(T6,6) \ - F(T7,A7,7,1) S(T7,7) F(T8,A8,8,1) S(T8,8) F(T9,A9,9,1) S(T9,9) \ - F(TA,AA,10,1) S(TA,10) F(TB,AB,11,1) S(TB,11) F(TC,AC,12,1) S(TC,12) \ - F(TD,AD,13,1) S(TD,13) F(TE,AE,14,1) S(TE,14) -#if MAX_PREPRO_ARGS>31 -#define CFARGTA20(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) \ - F(T1,A1,1,0) S(T1,1) F(T2,A2,2,1) S(T2,2) F(T3,A3,3,1) S(T3,3) \ - F(T4,A4,4,1) S(T4,4) F(T5,A5,5,1) S(T5,5) F(T6,A6,6,1) S(T6,6) \ - F(T7,A7,7,1) S(T7,7) F(T8,A8,8,1) S(T8,8) F(T9,A9,9,1) S(T9,9) \ - F(TA,AA,10,1) S(TA,10) F(TB,AB,11,1) S(TB,11) F(TC,AC,12,1) S(TC,12) \ - F(TD,AD,13,1) S(TD,13) F(TE,AE,14,1) S(TE,14) F(TF,AF,15,1) S(TF,15) \ - F(TG,AG,16,1) S(TG,16) F(TH,AH,17,1) S(TH,17) F(TI,AI,18,1) S(TI,18) \ - F(TJ,AJ,19,1) S(TJ,19) F(TK,AK,20,1) S(TK,20) -#define CFARGTA27(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) \ - F(T1,A1,1,0) S(T1,1) F(T2,A2,2,1) S(T2,2) F(T3,A3,3,1) S(T3,3) \ - F(T4,A4,4,1) S(T4,4) F(T5,A5,5,1) S(T5,5) F(T6,A6,6,1) S(T6,6) \ - F(T7,A7,7,1) S(T7,7) F(T8,A8,8,1) S(T8,8) F(T9,A9,9,1) S(T9,9) \ - F(TA,AA,10,1) S(TA,10) F(TB,AB,11,1) S(TB,11) F(TC,AC,12,1) S(TC,12) \ - F(TD,AD,13,1) S(TD,13) F(TE,AE,14,1) S(TE,14) F(TF,AF,15,1) S(TF,15) \ - F(TG,AG,16,1) S(TG,16) F(TH,AH,17,1) S(TH,17) F(TI,AI,18,1) S(TI,18) \ - F(TJ,AJ,19,1) S(TJ,19) F(TK,AK,20,1) S(TK,20) F(TL,AL,21,1) S(TL,21) \ - F(TM,AM,22,1) S(TM,22) F(TN,AN,23,1) S(TN,23) F(TO,AO,24,1) S(TO,24) \ - F(TP,AP,25,1) S(TP,25) F(TQ,AQ,26,1) S(TQ,26) F(TR,AR,27,1) S(TR,27) -#endif -#endif - - -#define PROTOCCALLSFSUB1( UN,LN,T1) \ - PROTOCCALLSFSUB14(UN,LN,T1,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB2( UN,LN,T1,T2) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB3( UN,LN,T1,T2,T3) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB4( UN,LN,T1,T2,T3,T4) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB5( UN,LN,T1,T2,T3,T4,T5) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB6( UN,LN,T1,T2,T3,T4,T5,T6) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB7( UN,LN,T1,T2,T3,T4,T5,T6,T7) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB8( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB9( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB11(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB12(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0) -#define PROTOCCALLSFSUB13(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0) - - -#define PROTOCCALLSFSUB15(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF) \ - PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB16(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG) \ - PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB17(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH) \ - PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB18(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI) \ - PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,CF_0,CF_0) -#define PROTOCCALLSFSUB19(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ) \ - PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,CF_0) - -#define PROTOCCALLSFSUB21(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL) \ - PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB22(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM) \ - PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB23(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN) \ - PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB24(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO) \ - PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,CF_0,CF_0,CF_0) -#define PROTOCCALLSFSUB25(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP) \ - PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,CF_0,CF_0) -#define PROTOCCALLSFSUB26(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ) \ - PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,CF_0) - - -#ifndef FCALLSC_QUALIFIER -#ifdef VISUAL_CPLUSPLUS -#define FCALLSC_QUALIFIER __stdcall -#else -#define FCALLSC_QUALIFIER -#endif -#endif - -#ifdef __cplusplus -#define CFextern extern "C" -#else -#define CFextern extern -#endif - - -#ifdef CFSUBASFUN -#define PROTOCCALLSFSUB0(UN,LN) \ - PROTOCCALLSFFUN0( VOID,UN,LN) -#define PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - PROTOCCALLSFFUN14(VOID,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) -#define PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK)\ - PROTOCCALLSFFUN20(VOID,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) -#define PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR)\ - PROTOCCALLSFFUN27(VOID,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) -#else -/* Note: Prevent compiler warnings, null #define PROTOCCALLSFSUB14/20 after - #include-ing cfortran.h if calling the FORTRAN wrapper within the same - source code where the wrapper is created. */ -#define PROTOCCALLSFSUB0(UN,LN) _(VOID,_cfPU)(CFC_(UN,LN))(); -#ifndef __CF__KnR -#define PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - _(VOID,_cfPU)(CFC_(UN,LN))( CFARGT14(NCF,KCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ); -#define PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK)\ - _(VOID,_cfPU)(CFC_(UN,LN))( CFARGT20(NCF,KCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) ); -#define PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR)\ - _(VOID,_cfPU)(CFC_(UN,LN))( CFARGT27(NCF,KCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) ); -#else -#define PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - PROTOCCALLSFSUB0(UN,LN) -#define PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ - PROTOCCALLSFSUB0(UN,LN) -#define PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ - PROTOCCALLSFSUB0(UN,LN) -#endif -#endif - - -#ifdef OLD_VAXC /* Allow %CC-I-PARAMNOTUSED. */ -#pragma standard -#endif - - -#define CCALLSFSUB1( UN,LN,T1, A1) \ - CCALLSFSUB5 (UN,LN,T1,CF_0,CF_0,CF_0,CF_0,A1,0,0,0,0) -#define CCALLSFSUB2( UN,LN,T1,T2, A1,A2) \ - CCALLSFSUB5 (UN,LN,T1,T2,CF_0,CF_0,CF_0,A1,A2,0,0,0) -#define CCALLSFSUB3( UN,LN,T1,T2,T3, A1,A2,A3) \ - CCALLSFSUB5 (UN,LN,T1,T2,T3,CF_0,CF_0,A1,A2,A3,0,0) -#define CCALLSFSUB4( UN,LN,T1,T2,T3,T4, A1,A2,A3,A4)\ - CCALLSFSUB5 (UN,LN,T1,T2,T3,T4,CF_0,A1,A2,A3,A4,0) -#define CCALLSFSUB5( UN,LN,T1,T2,T3,T4,T5, A1,A2,A3,A4,A5) \ - CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,0,0,0,0,0) -#define CCALLSFSUB6( UN,LN,T1,T2,T3,T4,T5,T6, A1,A2,A3,A4,A5,A6) \ - CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,0,0,0,0) -#define CCALLSFSUB7( UN,LN,T1,T2,T3,T4,T5,T6,T7, A1,A2,A3,A4,A5,A6,A7) \ - CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,0,0,0) -#define CCALLSFSUB8( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8, A1,A2,A3,A4,A5,A6,A7,A8) \ - CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,0,0) -#define CCALLSFSUB9( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,A1,A2,A3,A4,A5,A6,A7,A8,A9)\ - CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,0) -#define CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA)\ - CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,0,0,0,0) -#define CCALLSFSUB11(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB)\ - CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,0,0,0) -#define CCALLSFSUB12(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC)\ - CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,0,0) -#define CCALLSFSUB13(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD)\ - CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,0) - -#ifdef __cplusplus -#define CPPPROTOCLSFSUB0( UN,LN) -#define CPPPROTOCLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) -#define CPPPROTOCLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) -#define CPPPROTOCLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) -#else -#define CPPPROTOCLSFSUB0(UN,LN) \ - PROTOCCALLSFSUB0(UN,LN) -#define CPPPROTOCLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) -#define CPPPROTOCLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ - PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) -#define CPPPROTOCLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ - PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) -#endif - -#ifdef CFSUBASFUN -#define CCALLSFSUB0(UN,LN) CCALLSFFUN0(UN,LN) -#define CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE)\ - CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE) -#else -/* do{...}while(0) allows if(a==b) FORT(); else BORT(); */ -#define CCALLSFSUB0( UN,LN) do{CPPPROTOCLSFSUB0(UN,LN) CFC_(UN,LN)();}while(0) -#define CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE)\ -do{VVCF(T1,A1,B1) VVCF(T2,A2,B2) VVCF(T3,A3,B3) VVCF(T4,A4,B4) VVCF(T5,A5,B5) \ - VVCF(T6,A6,B6) VVCF(T7,A7,B7) VVCF(T8,A8,B8) VVCF(T9,A9,B9) VVCF(TA,AA,B10) \ - VVCF(TB,AB,B11) VVCF(TC,AC,B12) VVCF(TD,AD,B13) VVCF(TE,AE,B14) \ - CPPPROTOCLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - ACF(LN,T1,A1,1) ACF(LN,T2,A2,2) ACF(LN,T3,A3,3) \ - ACF(LN,T4,A4,4) ACF(LN,T5,A5,5) ACF(LN,T6,A6,6) ACF(LN,T7,A7,7) \ - ACF(LN,T8,A8,8) ACF(LN,T9,A9,9) ACF(LN,TA,AA,10) ACF(LN,TB,AB,11) \ - ACF(LN,TC,AC,12) ACF(LN,TD,AD,13) ACF(LN,TE,AE,14) \ - CFC_(UN,LN)( CFARGTA14(AACF,JCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE) );\ - WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) \ - WCF(T6,A6,6) WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,AA,10) \ - WCF(TB,AB,11) WCF(TC,AC,12) WCF(TD,AD,13) WCF(TE,AE,14) }while(0) -#endif - - -#if MAX_PREPRO_ARGS>31 -#define CCALLSFSUB15(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF)\ - CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,0,0,0,0,0) -#define CCALLSFSUB16(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG)\ - CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,0,0,0,0) -#define CCALLSFSUB17(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH)\ - CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,0,0,0) -#define CCALLSFSUB18(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI)\ - CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,0,0) -#define CCALLSFSUB19(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ)\ - CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,0) - -#ifdef CFSUBASFUN -#define CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH, \ - TI,TJ,TK, A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) \ - CCALLSFFUN20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH, \ - TI,TJ,TK, A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) -#else -#define CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH, \ - TI,TJ,TK, A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) \ -do{VVCF(T1,A1,B1) VVCF(T2,A2,B2) VVCF(T3,A3,B3) VVCF(T4,A4,B4) VVCF(T5,A5,B5) \ - VVCF(T6,A6,B6) VVCF(T7,A7,B7) VVCF(T8,A8,B8) VVCF(T9,A9,B9) VVCF(TA,AA,B10) \ - VVCF(TB,AB,B11) VVCF(TC,AC,B12) VVCF(TD,AD,B13) VVCF(TE,AE,B14) VVCF(TF,AF,B15) \ - VVCF(TG,AG,B16) VVCF(TH,AH,B17) VVCF(TI,AI,B18) VVCF(TJ,AJ,B19) VVCF(TK,AK,B20) \ - CPPPROTOCLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ - ACF(LN,T1,A1,1) ACF(LN,T2,A2,2) ACF(LN,T3,A3,3) ACF(LN,T4,A4,4) \ - ACF(LN,T5,A5,5) ACF(LN,T6,A6,6) ACF(LN,T7,A7,7) ACF(LN,T8,A8,8) \ - ACF(LN,T9,A9,9) ACF(LN,TA,AA,10) ACF(LN,TB,AB,11) ACF(LN,TC,AC,12) \ - ACF(LN,TD,AD,13) ACF(LN,TE,AE,14) ACF(LN,TF,AF,15) ACF(LN,TG,AG,16) \ - ACF(LN,TH,AH,17) ACF(LN,TI,AI,18) ACF(LN,TJ,AJ,19) ACF(LN,TK,AK,20) \ - CFC_(UN,LN)( CFARGTA20(AACF,JCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) ); \ - WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) WCF(T6,A6,6) \ - WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,AA,10) WCF(TB,AB,11) WCF(TC,AC,12) \ - WCF(TD,AD,13) WCF(TE,AE,14) WCF(TF,AF,15) WCF(TG,AG,16) WCF(TH,AH,17) WCF(TI,AI,18) \ - WCF(TJ,AJ,19) WCF(TK,AK,20) }while(0) -#endif -#endif /* MAX_PREPRO_ARGS */ - -#if MAX_PREPRO_ARGS>31 -#define CCALLSFSUB21(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL)\ - CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,0,0,0,0,0,0) -#define CCALLSFSUB22(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM)\ - CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,0,0,0,0,0) -#define CCALLSFSUB23(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN)\ - CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,0,0,0,0) -#define CCALLSFSUB24(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO)\ - CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,0,0,0) -#define CCALLSFSUB25(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP)\ - CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,0,0) -#define CCALLSFSUB26(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ)\ - CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,0) - -#ifdef CFSUBASFUN -#define CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR, \ - A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) \ - CCALLSFFUN27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR, \ - A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) -#else -#define CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR, \ - A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) \ -do{VVCF(T1,A1,B1) VVCF(T2,A2,B2) VVCF(T3,A3,B3) VVCF(T4,A4,B4) VVCF(T5,A5,B5) \ - VVCF(T6,A6,B6) VVCF(T7,A7,B7) VVCF(T8,A8,B8) VVCF(T9,A9,B9) VVCF(TA,AA,B10) \ - VVCF(TB,AB,B11) VVCF(TC,AC,B12) VVCF(TD,AD,B13) VVCF(TE,AE,B14) VVCF(TF,AF,B15) \ - VVCF(TG,AG,B16) VVCF(TH,AH,B17) VVCF(TI,AI,B18) VVCF(TJ,AJ,B19) VVCF(TK,AK,B20) \ - VVCF(TL,AL,B21) VVCF(TM,AM,B22) VVCF(TN,AN,B23) VVCF(TO,AO,B24) VVCF(TP,AP,B25) \ - VVCF(TQ,AQ,B26) VVCF(TR,AR,B27) \ - CPPPROTOCLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ - ACF(LN,T1,A1,1) ACF(LN,T2,A2,2) ACF(LN,T3,A3,3) ACF(LN,T4,A4,4) \ - ACF(LN,T5,A5,5) ACF(LN,T6,A6,6) ACF(LN,T7,A7,7) ACF(LN,T8,A8,8) \ - ACF(LN,T9,A9,9) ACF(LN,TA,AA,10) ACF(LN,TB,AB,11) ACF(LN,TC,AC,12) \ - ACF(LN,TD,AD,13) ACF(LN,TE,AE,14) ACF(LN,TF,AF,15) ACF(LN,TG,AG,16) \ - ACF(LN,TH,AH,17) ACF(LN,TI,AI,18) ACF(LN,TJ,AJ,19) ACF(LN,TK,AK,20) \ - ACF(LN,TL,AL,21) ACF(LN,TM,AM,22) ACF(LN,TN,AN,23) ACF(LN,TO,AO,24) \ - ACF(LN,TP,AP,25) ACF(LN,TQ,AQ,26) ACF(LN,TR,AR,27) \ - CFC_(UN,LN)( CFARGTA27(AACF,JCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR,\ - A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) ); \ - WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) WCF(T6,A6,6) \ - WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,AA,10) WCF(TB,AB,11) WCF(TC,AC,12) \ - WCF(TD,AD,13) WCF(TE,AE,14) WCF(TF,AF,15) WCF(TG,AG,16) WCF(TH,AH,17) WCF(TI,AI,18) \ - WCF(TJ,AJ,19) WCF(TK,AK,20) WCF(TL,AL,21) WCF(TM,AM,22) WCF(TN,AN,23) WCF(TO,AO,24) \ - WCF(TP,AP,25) WCF(TQ,AQ,26) WCF(TR,AR,27) }while(0) -#endif -#endif /* MAX_PREPRO_ARGS */ - -/*-------------------------------------------------------------------------*/ - -/* UTILITIES FOR C TO CALL FORTRAN FUNCTIONS */ - -/*N.B. PROTOCCALLSFFUNn(..) generates code, whether or not the FORTRAN - function is called. Therefore, especially for creator's of C header files - for large FORTRAN libraries which include many functions, to reduce - compile time and object code size, it may be desirable to create - preprocessor directives to allow users to create code for only those - functions which they use. */ - -/* The following defines the maximum length string that a function can return. - Of course it may be undefine-d and re-define-d before individual - PROTOCCALLSFFUNn(..) as required. It would also be nice to have this derived - from the individual machines' limits. */ -#define MAX_LEN_FORTRAN_FUNCTION_STRING 0x4FE - -/* The following defines a character used by CFORTRAN.H to flag the end of a - string coming out of a FORTRAN routine. */ -#define CFORTRAN_NON_CHAR 0x7F - -#ifdef OLD_VAXC /* Prevent %CC-I-PARAMNOTUSED. */ -#pragma nostandard -#endif - -#define _SEP_(TN,C,cfCOMMA) _(__SEP_,C)(TN,cfCOMMA) -#define __SEP_0(TN,cfCOMMA) -#define __SEP_1(TN,cfCOMMA) _Icf(2,SEP,TN,cfCOMMA,0) -#define INT_cfSEP(T,B) _(A,B) -#define INTV_cfSEP(T,B) INT_cfSEP(T,B) -#define INTVV_cfSEP(T,B) INT_cfSEP(T,B) -#define INTVVV_cfSEP(T,B) INT_cfSEP(T,B) -#define INTVVVV_cfSEP(T,B) INT_cfSEP(T,B) -#define INTVVVVV_cfSEP(T,B) INT_cfSEP(T,B) -#define INTVVVVVV_cfSEP(T,B) INT_cfSEP(T,B) -#define INTVVVVVVV_cfSEP(T,B) INT_cfSEP(T,B) -#define PINT_cfSEP(T,B) INT_cfSEP(T,B) -#define PVOID_cfSEP(T,B) INT_cfSEP(T,B) -#define ROUTINE_cfSEP(T,B) INT_cfSEP(T,B) -#define SIMPLE_cfSEP(T,B) INT_cfSEP(T,B) -#define VOID_cfSEP(T,B) INT_cfSEP(T,B) /* For FORTRAN calls C subr.s.*/ -#define STRING_cfSEP(T,B) INT_cfSEP(T,B) -#define STRINGV_cfSEP(T,B) INT_cfSEP(T,B) -#define PSTRING_cfSEP(T,B) INT_cfSEP(T,B) -#define PSTRINGV_cfSEP(T,B) INT_cfSEP(T,B) -#define PNSTRING_cfSEP(T,B) INT_cfSEP(T,B) -#define PPSTRING_cfSEP(T,B) INT_cfSEP(T,B) -#define ZTRINGV_cfSEP(T,B) INT_cfSEP(T,B) -#define PZTRINGV_cfSEP(T,B) INT_cfSEP(T,B) - -#if defined(SIGNED_BYTE) || !defined(UNSIGNED_BYTE) -#ifdef OLD_VAXC -#define INTEGER_BYTE char /* Old VAXC barfs on 'signed char' */ -#else -#define INTEGER_BYTE signed char /* default */ -#endif -#else -#define INTEGER_BYTE unsigned char -#endif -#define BYTEVVVVVVV_cfTYPE INTEGER_BYTE -#define DOUBLEVVVVVVV_cfTYPE DOUBLE_PRECISION -#define FLOATVVVVVVV_cfTYPE FORTRAN_REAL -#define INTVVVVVVV_cfTYPE int -#define LOGICALVVVVVVV_cfTYPE int -#define LONGVVVVVVV_cfTYPE long -#define LONGLONGVVVVVVV_cfTYPE LONGLONG /* added by MR December 2005 */ -#define SHORTVVVVVVV_cfTYPE short -#define PBYTE_cfTYPE INTEGER_BYTE -#define PDOUBLE_cfTYPE DOUBLE_PRECISION -#define PFLOAT_cfTYPE FORTRAN_REAL -#define PINT_cfTYPE int -#define PLOGICAL_cfTYPE int -#define PLONG_cfTYPE long -#define PLONGLONG_cfTYPE LONGLONG /* added by MR December 2005 */ -#define PSHORT_cfTYPE short - -#define CFARGS0(A,T,V,W,X,Y,Z) _3(T,_cf,A) -#define CFARGS1(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V) -#define CFARGS2(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V,W) -#define CFARGS3(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V,W,X) -#define CFARGS4(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V,W,X,Y) -#define CFARGS5(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V,W,X,Y,Z) - -#define _Icf(N,T,I,X,Y) _(I,_cfINT)(N,T,I,X,Y,0) -#define _Icf4(N,T,I,X,Y,Z) _(I,_cfINT)(N,T,I,X,Y,Z) -#define BYTE_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) -#define DOUBLE_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INT,B,X,Y,Z,0) -#define FLOAT_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) -#define INT_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) -#define LOGICAL_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) -#define LONG_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) -#define LONGLONG_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ -#define SHORT_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) -#define PBYTE_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) -#define PDOUBLE_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,PINT,B,X,Y,Z,0) -#define PFLOAT_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) -#define PINT_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) -#define PLOGICAL_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) -#define PLONG_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) -#define PLONGLONG_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ -#define PSHORT_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) -#define BYTEV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) -#define BYTEVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) -#define BYTEVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) -#define BYTEVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) -#define BYTEVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) -#define BYTEVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) -#define BYTEVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) -#define DOUBLEV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTV,B,X,Y,Z,0) -#define DOUBLEVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVV,B,X,Y,Z,0) -#define DOUBLEVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVV,B,X,Y,Z,0) -#define DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVVV,B,X,Y,Z,0) -#define DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVVVV,B,X,Y,Z,0) -#define DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVVVVV,B,X,Y,Z,0) -#define DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVVVVVV,B,X,Y,Z,0) -#define FLOATV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) -#define FLOATVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) -#define FLOATVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) -#define FLOATVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) -#define FLOATVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) -#define FLOATVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) -#define FLOATVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) -#define INTV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) -#define INTVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) -#define INTVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) -#define INTVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) -#define INTVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) -#define INTVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) -#define INTVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) -#define LOGICALV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) -#define LOGICALVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) -#define LOGICALVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) -#define LOGICALVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) -#define LOGICALVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) -#define LOGICALVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) -#define LOGICALVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) -#define LONGV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) -#define LONGVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) -#define LONGVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) -#define LONGVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) -#define LONGVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) -#define LONGVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) -#define LONGVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) -#define LONGLONGV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ -#define LONGLONGVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ -#define LONGLONGVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ -#define LONGLONGVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ -#define LONGLONGVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ -#define LONGLONGVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ -#define LONGLONGVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ -#define SHORTV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) -#define SHORTVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) -#define SHORTVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) -#define SHORTVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) -#define SHORTVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) -#define SHORTVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) -#define SHORTVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) -#define PVOID_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,B,B,X,Y,Z,0) -#define ROUTINE_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) -/*CRAY coughs on the first, - i.e. the usual trouble of not being able to - define macros to macros with arguments. - New ultrix is worse, it coughs on all such uses. - */ -/*#define SIMPLE_cfINT PVOID_cfINT*/ -#define SIMPLE_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) -#define VOID_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) -#define STRING_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) -#define STRINGV_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) -#define PSTRING_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) -#define PSTRINGV_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) -#define PNSTRING_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) -#define PPSTRING_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) -#define ZTRINGV_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) -#define PZTRINGV_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) -#define CF_0_cfINT(N,A,B,X,Y,Z) - - -#define UCF(TN,I,C) _SEP_(TN,C,cfCOMMA) _Icf(2,U,TN,_(A,I),0) -#define UUCF(TN,I,C) _SEP_(TN,C,cfCOMMA) _SEP_(TN,1,I) -#define UUUCF(TN,I,C) _SEP_(TN,C,cfCOLON) _Icf(2,U,TN,_(A,I),0) -#define INT_cfU(T,A) _(T,VVVVVVV_cfTYPE) A -#define INTV_cfU(T,A) _(T,VVVVVV_cfTYPE) * A -#define INTVV_cfU(T,A) _(T,VVVVV_cfTYPE) * A -#define INTVVV_cfU(T,A) _(T,VVVV_cfTYPE) * A -#define INTVVVV_cfU(T,A) _(T,VVV_cfTYPE) * A -#define INTVVVVV_cfU(T,A) _(T,VV_cfTYPE) * A -#define INTVVVVVV_cfU(T,A) _(T,V_cfTYPE) * A -#define INTVVVVVVV_cfU(T,A) _(T,_cfTYPE) * A -#define PINT_cfU(T,A) _(T,_cfTYPE) * A -#define PVOID_cfU(T,A) void *A -#define ROUTINE_cfU(T,A) void (*A)(CF_NULL_PROTO) -#define VOID_cfU(T,A) void A /* Needed for C calls FORTRAN sub.s. */ -#define STRING_cfU(T,A) char *A /* via VOID and wrapper. */ -#define STRINGV_cfU(T,A) char *A -#define PSTRING_cfU(T,A) char *A -#define PSTRINGV_cfU(T,A) char *A -#define ZTRINGV_cfU(T,A) char *A -#define PZTRINGV_cfU(T,A) char *A - -/* VOID breaks U into U and UU. */ -#define INT_cfUU(T,A) _(T,VVVVVVV_cfTYPE) A -#define VOID_cfUU(T,A) /* Needed for FORTRAN calls C sub.s. */ -#define STRING_cfUU(T,A) char *A - - -#define BYTE_cfPU(A) CFextern INTEGER_BYTE FCALLSC_QUALIFIER A -#define DOUBLE_cfPU(A) CFextern DOUBLE_PRECISION FCALLSC_QUALIFIER A -#if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) -#if defined (f2cFortran) && ! defined (gFortran) -/* f2c/g77 return double from FORTRAN REAL functions. (KMCCARTY, 2005/12/09) */ -#define FLOAT_cfPU(A) CFextern DOUBLE_PRECISION FCALLSC_QUALIFIER A -#else -#define FLOAT_cfPU(A) CFextern FORTRAN_REAL FCALLSC_QUALIFIER A -#endif -#else -#define FLOAT_cfPU(A) CFextern FLOATFUNCTIONTYPE FCALLSC_QUALIFIER A -#endif -#define INT_cfPU(A) CFextern int FCALLSC_QUALIFIER A -#define LOGICAL_cfPU(A) CFextern int FCALLSC_QUALIFIER A -#define LONG_cfPU(A) CFextern long FCALLSC_QUALIFIER A -#define SHORT_cfPU(A) CFextern short FCALLSC_QUALIFIER A -#define STRING_cfPU(A) CFextern void FCALLSC_QUALIFIER A -#define VOID_cfPU(A) CFextern void FCALLSC_QUALIFIER A - -#define BYTE_cfE INTEGER_BYTE A0; -#define DOUBLE_cfE DOUBLE_PRECISION A0; -#if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) -#define FLOAT_cfE FORTRAN_REAL A0; -#else -#define FLOAT_cfE FORTRAN_REAL AA0; FLOATFUNCTIONTYPE A0; -#endif -#define INT_cfE int A0; -#define LOGICAL_cfE int A0; -#define LONG_cfE long A0; -#define SHORT_cfE short A0; -#define VOID_cfE -#ifdef vmsFortran -#define STRING_cfE static char AA0[1+MAX_LEN_FORTRAN_FUNCTION_STRING]; \ - static fstring A0 = \ - {MAX_LEN_FORTRAN_FUNCTION_STRING,DSC$K_DTYPE_T,DSC$K_CLASS_S,AA0};\ - memset(AA0, CFORTRAN_NON_CHAR, MAX_LEN_FORTRAN_FUNCTION_STRING);\ - *(AA0+MAX_LEN_FORTRAN_FUNCTION_STRING)='\0'; -#else -#ifdef CRAYFortran -#define STRING_cfE static char AA0[1+MAX_LEN_FORTRAN_FUNCTION_STRING]; \ - static _fcd A0; *(AA0+MAX_LEN_FORTRAN_FUNCTION_STRING)='\0';\ - memset(AA0,CFORTRAN_NON_CHAR, MAX_LEN_FORTRAN_FUNCTION_STRING);\ - A0 = _cptofcd(AA0,MAX_LEN_FORTRAN_FUNCTION_STRING); -#else -/* 'cc: SC3.0.1 13 Jul 1994' barfs on char A0[0x4FE+1]; - * char A0[0x4FE +1]; char A0[1+0x4FE]; are both OK. */ -#define STRING_cfE static char A0[1+MAX_LEN_FORTRAN_FUNCTION_STRING]; \ - memset(A0, CFORTRAN_NON_CHAR, \ - MAX_LEN_FORTRAN_FUNCTION_STRING); \ - *(A0+MAX_LEN_FORTRAN_FUNCTION_STRING)='\0'; -#endif -#endif -/* ESTRING must use static char. array which is guaranteed to exist after - function returns. */ - -/* N.B.i) The diff. for 0 (Zero) and >=1 arguments. - ii)That the following create an unmatched bracket, i.e. '(', which - must of course be matched in the call. - iii)Commas must be handled very carefully */ -#define INT_cfGZ(T,UN,LN) A0=CFC_(UN,LN)( -#define VOID_cfGZ(T,UN,LN) CFC_(UN,LN)( -#ifdef vmsFortran -#define STRING_cfGZ(T,UN,LN) CFC_(UN,LN)(&A0 -#else -#if defined(CRAYFortran) || defined(AbsoftUNIXFortran) || defined(AbsoftProFortran) -#define STRING_cfGZ(T,UN,LN) CFC_(UN,LN)( A0 -#else -#define STRING_cfGZ(T,UN,LN) CFC_(UN,LN)( A0,MAX_LEN_FORTRAN_FUNCTION_STRING -#endif -#endif - -#define INT_cfG(T,UN,LN) INT_cfGZ(T,UN,LN) -#define VOID_cfG(T,UN,LN) VOID_cfGZ(T,UN,LN) -#define STRING_cfG(T,UN,LN) STRING_cfGZ(T,UN,LN), /*, is only diff. from _cfG*/ - -#define BYTEVVVVVVV_cfPP -#define INTVVVVVVV_cfPP /* These complement FLOATVVVVVVV_cfPP. */ -#define DOUBLEVVVVVVV_cfPP -#define LOGICALVVVVVVV_cfPP -#define LONGVVVVVVV_cfPP -#define SHORTVVVVVVV_cfPP -#define PBYTE_cfPP -#define PINT_cfPP -#define PDOUBLE_cfPP -#define PLOGICAL_cfPP -#define PLONG_cfPP -#define PSHORT_cfPP -#define PFLOAT_cfPP FLOATVVVVVVV_cfPP - -#define BCF(TN,AN,C) _SEP_(TN,C,cfCOMMA) _Icf(2,B,TN,AN,0) -#define INT_cfB(T,A) (_(T,VVVVVVV_cfTYPE)) A -#define INTV_cfB(T,A) A -#define INTVV_cfB(T,A) (A)[0] -#define INTVVV_cfB(T,A) (A)[0][0] -#define INTVVVV_cfB(T,A) (A)[0][0][0] -#define INTVVVVV_cfB(T,A) (A)[0][0][0][0] -#define INTVVVVVV_cfB(T,A) (A)[0][0][0][0][0] -#define INTVVVVVVV_cfB(T,A) (A)[0][0][0][0][0][0] -#define PINT_cfB(T,A) _(T,_cfPP)&A -#define STRING_cfB(T,A) (char *) A -#define STRINGV_cfB(T,A) (char *) A -#define PSTRING_cfB(T,A) (char *) A -#define PSTRINGV_cfB(T,A) (char *) A -#define PVOID_cfB(T,A) (void *) A -#define ROUTINE_cfB(T,A) (cfCAST_FUNCTION)A -#define ZTRINGV_cfB(T,A) (char *) A -#define PZTRINGV_cfB(T,A) (char *) A - -#define SCF(TN,NAME,I,A) _(TN,_cfSTR)(3,S,NAME,I,A,0,0) -#define DEFAULT_cfS(M,I,A) -#define LOGICAL_cfS(M,I,A) -#define PLOGICAL_cfS(M,I,A) -#define STRING_cfS(M,I,A) ,sizeof(A) -#define STRINGV_cfS(M,I,A) ,( (unsigned)0xFFFF*firstindexlength(A) \ - +secondindexlength(A)) -#define PSTRING_cfS(M,I,A) ,sizeof(A) -#define PSTRINGV_cfS(M,I,A) STRINGV_cfS(M,I,A) -#define ZTRINGV_cfS(M,I,A) -#define PZTRINGV_cfS(M,I,A) - -#define HCF(TN,I) _(TN,_cfSTR)(3,H,cfCOMMA, H,_(C,I),0,0) -#define HHCF(TN,I) _(TN,_cfSTR)(3,H,cfCOMMA,HH,_(C,I),0,0) -#define HHHCF(TN,I) _(TN,_cfSTR)(3,H,cfCOLON, H,_(C,I),0,0) -#define H_CF_SPECIAL unsigned -#define HH_CF_SPECIAL -#define DEFAULT_cfH(M,I,A) -#define LOGICAL_cfH(S,U,B) -#define PLOGICAL_cfH(S,U,B) -#define STRING_cfH(S,U,B) _(A,S) _(U,_CF_SPECIAL) B -#define STRINGV_cfH(S,U,B) STRING_cfH(S,U,B) -#define PSTRING_cfH(S,U,B) STRING_cfH(S,U,B) -#define PSTRINGV_cfH(S,U,B) STRING_cfH(S,U,B) -#define PNSTRING_cfH(S,U,B) STRING_cfH(S,U,B) -#define PPSTRING_cfH(S,U,B) STRING_cfH(S,U,B) -#define ZTRINGV_cfH(S,U,B) -#define PZTRINGV_cfH(S,U,B) - -/* Need VOID_cfSTR because Absoft forced function types go through _cfSTR. */ -/* No spaces inside expansion. They screws up macro catenation kludge. */ -#define VOID_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define BYTE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define DOUBLE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define FLOAT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define INT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LOGICAL_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,LOGICAL,A,B,C,D,E) -#define LONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LONGLONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ -#define SHORT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define BYTEV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define BYTEVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define BYTEVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define BYTEVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define BYTEVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define BYTEVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define BYTEVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define DOUBLEV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define DOUBLEVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define DOUBLEVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define DOUBLEVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define DOUBLEVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define DOUBLEVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define DOUBLEVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define FLOATV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define FLOATVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define FLOATVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define FLOATVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define FLOATVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define FLOATVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define FLOATVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define INTV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define INTVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define INTVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define INTVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define INTVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define INTVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define INTVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LOGICALV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LOGICALVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LOGICALVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LOGICALVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LOGICALVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LOGICALVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LOGICALVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LONGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LONGVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LONGVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LONGVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LONGVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LONGVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LONGVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define LONGLONGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ -#define LONGLONGVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ -#define LONGLONGVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ -#define LONGLONGVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ -#define LONGLONGVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ -#define LONGLONGVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ -#define LONGLONGVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ -#define SHORTV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define SHORTVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define SHORTVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define SHORTVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define SHORTVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define SHORTVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define SHORTVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define PBYTE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define PDOUBLE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define PFLOAT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define PINT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define PLOGICAL_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PLOGICAL,A,B,C,D,E) -#define PLONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define PLONGLONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ -#define PSHORT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define STRING_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,STRING,A,B,C,D,E) -#define PSTRING_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PSTRING,A,B,C,D,E) -#define STRINGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,STRINGV,A,B,C,D,E) -#define PSTRINGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PSTRINGV,A,B,C,D,E) -#define PNSTRING_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PNSTRING,A,B,C,D,E) -#define PPSTRING_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PPSTRING,A,B,C,D,E) -#define PVOID_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define ROUTINE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define SIMPLE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) -#define ZTRINGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,ZTRINGV,A,B,C,D,E) -#define PZTRINGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PZTRINGV,A,B,C,D,E) -#define CF_0_cfSTR(N,T,A,B,C,D,E) - -/* See ACF table comments, which explain why CCF was split into two. */ -#define CCF(NAME,TN,I) _(TN,_cfSTR)(5,C,NAME,I,_(A,I),_(B,I),_(C,I)) -#define DEFAULT_cfC(M,I,A,B,C) -#define LOGICAL_cfC(M,I,A,B,C) A=C2FLOGICAL( A); -#define PLOGICAL_cfC(M,I,A,B,C) *A=C2FLOGICAL(*A); -#ifdef vmsFortran -#define STRING_cfC(M,I,A,B,C) (B.clen=strlen(A),B.f.dsc$a_pointer=A, \ - C==sizeof(char*)||C==(unsigned)(B.clen+1)?B.f.dsc$w_length=B.clen: \ - (memset((A)+B.clen,' ',C-B.clen-1),A[B.f.dsc$w_length=C-1]='\0')); - /* PSTRING_cfC to beware of array A which does not contain any \0. */ -#define PSTRING_cfC(M,I,A,B,C) (B.dsc$a_pointer=A, C==sizeof(char*) ? \ - B.dsc$w_length=strlen(A): (A[C-1]='\0',B.dsc$w_length=strlen(A), \ - memset((A)+B.dsc$w_length,' ',C-B.dsc$w_length-1), B.dsc$w_length=C-1)); -#else -#define STRING_cfC(M,I,A,B,C) (B.nombre=A,B.clen=strlen(A), \ - C==sizeof(char*)||C==(unsigned)(B.clen+1)?B.flen=B.clen: \ - (memset(B.nombre+B.clen,' ',C-B.clen-1),B.nombre[B.flen=C-1]='\0')); -#define PSTRING_cfC(M,I,A,B,C) (C==sizeof(char*)? B=strlen(A): \ - (A[C-1]='\0',B=strlen(A),memset((A)+B,' ',C-B-1),B=C-1)); -#endif - /* For CRAYFortran for (P)STRINGV_cfC, B.fs is set, but irrelevant. */ -#define STRINGV_cfC(M,I,A,B,C) \ - AATRINGV_cfA( A,B,(C/0xFFFF)*(C%0xFFFF),C/0xFFFF,C%0xFFFF) -#define PSTRINGV_cfC(M,I,A,B,C) \ - APATRINGV_cfA( A,B,(C/0xFFFF)*(C%0xFFFF),C/0xFFFF,C%0xFFFF) -#define ZTRINGV_cfC(M,I,A,B,C) \ - AATRINGV_cfA( A,B, (_3(M,_ELEMS_,I))*((_3(M,_ELEMLEN_,I))+1), \ - (_3(M,_ELEMS_,I)), (_3(M,_ELEMLEN_,I))+1 ) -#define PZTRINGV_cfC(M,I,A,B,C) \ - APATRINGV_cfA( A,B, (_3(M,_ELEMS_,I))*((_3(M,_ELEMLEN_,I))+1), \ - (_3(M,_ELEMS_,I)), (_3(M,_ELEMLEN_,I))+1 ) - -#define BYTE_cfCCC(A,B) &A -#define DOUBLE_cfCCC(A,B) &A -#if !defined(__CF__KnR) -#define FLOAT_cfCCC(A,B) &A - /* Although the VAX doesn't, at least the */ -#else /* HP and K&R mips promote float arg.'s of */ -#define FLOAT_cfCCC(A,B) &B /* unprototyped functions to double. Cannot */ -#endif /* use A here to pass the argument to FORTRAN. */ -#define INT_cfCCC(A,B) &A -#define LOGICAL_cfCCC(A,B) &A -#define LONG_cfCCC(A,B) &A -#define SHORT_cfCCC(A,B) &A -#define PBYTE_cfCCC(A,B) A -#define PDOUBLE_cfCCC(A,B) A -#define PFLOAT_cfCCC(A,B) A -#define PINT_cfCCC(A,B) A -#define PLOGICAL_cfCCC(A,B) B=A /* B used to keep a common W table. */ -#define PLONG_cfCCC(A,B) A -#define PSHORT_cfCCC(A,B) A - -#define CCCF(TN,I,M) _SEP_(TN,M,cfCOMMA) _Icf(3,CC,TN,_(A,I),_(B,I)) -#define INT_cfCC(T,A,B) _(T,_cfCCC)(A,B) -#define INTV_cfCC(T,A,B) A -#define INTVV_cfCC(T,A,B) A -#define INTVVV_cfCC(T,A,B) A -#define INTVVVV_cfCC(T,A,B) A -#define INTVVVVV_cfCC(T,A,B) A -#define INTVVVVVV_cfCC(T,A,B) A -#define INTVVVVVVV_cfCC(T,A,B) A -#define PINT_cfCC(T,A,B) _(T,_cfCCC)(A,B) -#define PVOID_cfCC(T,A,B) A -#if defined(apolloFortran) || defined(hpuxFortran800) || defined(AbsoftUNIXFortran) -#define ROUTINE_cfCC(T,A,B) &A -#else -#define ROUTINE_cfCC(T,A,B) A -#endif -#define SIMPLE_cfCC(T,A,B) A -#ifdef vmsFortran -#define STRING_cfCC(T,A,B) &B.f -#define STRINGV_cfCC(T,A,B) &B -#define PSTRING_cfCC(T,A,B) &B -#define PSTRINGV_cfCC(T,A,B) &B -#else -#ifdef CRAYFortran -#define STRING_cfCC(T,A,B) _cptofcd(A,B.flen) -#define STRINGV_cfCC(T,A,B) _cptofcd(B.s,B.flen) -#define PSTRING_cfCC(T,A,B) _cptofcd(A,B) -#define PSTRINGV_cfCC(T,A,B) _cptofcd(A,B.flen) -#else -#define STRING_cfCC(T,A,B) A -#define STRINGV_cfCC(T,A,B) B.fs -#define PSTRING_cfCC(T,A,B) A -#define PSTRINGV_cfCC(T,A,B) B.fs -#endif -#endif -#define ZTRINGV_cfCC(T,A,B) STRINGV_cfCC(T,A,B) -#define PZTRINGV_cfCC(T,A,B) PSTRINGV_cfCC(T,A,B) - -#define BYTE_cfX return A0; -#define DOUBLE_cfX return A0; -#if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) -#define FLOAT_cfX return A0; -#else -#define FLOAT_cfX ASSIGNFLOAT(AA0,A0); return AA0; -#endif -#define INT_cfX return A0; -#define LOGICAL_cfX return F2CLOGICAL(A0); -#define LONG_cfX return A0; -#define SHORT_cfX return A0; -#define VOID_cfX return ; -#if defined(vmsFortran) || defined(CRAYFortran) -#define STRING_cfX return kill_trailing( \ - kill_trailing(AA0,CFORTRAN_NON_CHAR),' '); -#else -#define STRING_cfX return kill_trailing( \ - kill_trailing( A0,CFORTRAN_NON_CHAR),' '); -#endif - -#define CFFUN(NAME) _(__cf__,NAME) - -/* Note that we don't use LN here, but we keep it for consistency. */ -#define CCALLSFFUN0(UN,LN) CFFUN(UN)() - -#ifdef OLD_VAXC /* Allow %CC-I-PARAMNOTUSED. */ -#pragma standard -#endif - -#define CCALLSFFUN1( UN,LN,T1, A1) \ - CCALLSFFUN5 (UN,LN,T1,CF_0,CF_0,CF_0,CF_0,A1,0,0,0,0) -#define CCALLSFFUN2( UN,LN,T1,T2, A1,A2) \ - CCALLSFFUN5 (UN,LN,T1,T2,CF_0,CF_0,CF_0,A1,A2,0,0,0) -#define CCALLSFFUN3( UN,LN,T1,T2,T3, A1,A2,A3) \ - CCALLSFFUN5 (UN,LN,T1,T2,T3,CF_0,CF_0,A1,A2,A3,0,0) -#define CCALLSFFUN4( UN,LN,T1,T2,T3,T4, A1,A2,A3,A4)\ - CCALLSFFUN5 (UN,LN,T1,T2,T3,T4,CF_0,A1,A2,A3,A4,0) -#define CCALLSFFUN5( UN,LN,T1,T2,T3,T4,T5, A1,A2,A3,A4,A5) \ - CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,0,0,0,0,0) -#define CCALLSFFUN6( UN,LN,T1,T2,T3,T4,T5,T6, A1,A2,A3,A4,A5,A6) \ - CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,0,0,0,0) -#define CCALLSFFUN7( UN,LN,T1,T2,T3,T4,T5,T6,T7, A1,A2,A3,A4,A5,A6,A7) \ - CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,0,0,0) -#define CCALLSFFUN8( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8, A1,A2,A3,A4,A5,A6,A7,A8) \ - CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,0,0) -#define CCALLSFFUN9( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,A1,A2,A3,A4,A5,A6,A7,A8,A9)\ - CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,0) -#define CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA)\ - CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,0,0,0,0) -#define CCALLSFFUN11(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB)\ - CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,0,0,0) -#define CCALLSFFUN12(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC)\ - CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,0,0) -#define CCALLSFFUN13(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD)\ - CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,0) - -#define CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE)\ -((CFFUN(UN)( BCF(T1,A1,0) BCF(T2,A2,1) BCF(T3,A3,1) BCF(T4,A4,1) BCF(T5,A5,1) \ - BCF(T6,A6,1) BCF(T7,A7,1) BCF(T8,A8,1) BCF(T9,A9,1) BCF(TA,AA,1) \ - BCF(TB,AB,1) BCF(TC,AC,1) BCF(TD,AD,1) BCF(TE,AE,1) \ - SCF(T1,LN,1,A1) SCF(T2,LN,2,A2) SCF(T3,LN,3,A3) SCF(T4,LN,4,A4) \ - SCF(T5,LN,5,A5) SCF(T6,LN,6,A6) SCF(T7,LN,7,A7) SCF(T8,LN,8,A8) \ - SCF(T9,LN,9,A9) SCF(TA,LN,10,AA) SCF(TB,LN,11,AB) SCF(TC,LN,12,AC) \ - SCF(TD,LN,13,AD) SCF(TE,LN,14,AE)))) - -/* N.B. Create a separate function instead of using (call function, function -value here) because in order to create the variables needed for the input -arg.'s which may be const.'s one has to do the creation within {}, but these -can never be placed within ()'s. Therefore one must create wrapper functions. -gcc, on the other hand may be able to avoid the wrapper functions. */ - -/* Prototypes are needed to correctly handle the value returned correctly. N.B. -Can only have prototype arg.'s with difficulty, a la G... table since FORTRAN -functions returning strings have extra arg.'s. Don't bother, since this only -causes a compiler warning to come up when one uses FCALLSCFUNn and CCALLSFFUNn -for the same function in the same source code. Something done by the experts in -debugging only.*/ - -#define PROTOCCALLSFFUN0(F,UN,LN) \ -_(F,_cfPU)( CFC_(UN,LN))(CF_NULL_PROTO); \ -static _Icf(2,U,F,CFFUN(UN),0)() {_(F,_cfE) _Icf(3,GZ,F,UN,LN) ABSOFT_cf1(F));_(F,_cfX)} - -#define PROTOCCALLSFFUN1( T0,UN,LN,T1) \ - PROTOCCALLSFFUN5 (T0,UN,LN,T1,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFFUN2( T0,UN,LN,T1,T2) \ - PROTOCCALLSFFUN5 (T0,UN,LN,T1,T2,CF_0,CF_0,CF_0) -#define PROTOCCALLSFFUN3( T0,UN,LN,T1,T2,T3) \ - PROTOCCALLSFFUN5 (T0,UN,LN,T1,T2,T3,CF_0,CF_0) -#define PROTOCCALLSFFUN4( T0,UN,LN,T1,T2,T3,T4) \ - PROTOCCALLSFFUN5 (T0,UN,LN,T1,T2,T3,T4,CF_0) -#define PROTOCCALLSFFUN5( T0,UN,LN,T1,T2,T3,T4,T5) \ - PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFFUN6( T0,UN,LN,T1,T2,T3,T4,T5,T6) \ - PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFFUN7( T0,UN,LN,T1,T2,T3,T4,T5,T6,T7) \ - PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0) -#define PROTOCCALLSFFUN8( T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) \ - PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0) -#define PROTOCCALLSFFUN9( T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) \ - PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0) -#define PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) \ - PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0) -#define PROTOCCALLSFFUN11(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) \ - PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0) -#define PROTOCCALLSFFUN12(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) \ - PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0) -#define PROTOCCALLSFFUN13(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) \ - PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0) - -/* HP/UX 9.01 cc requires the blank between '_Icf(3,G,T0,UN,LN) CCCF(T1,1,0)' */ - -#ifndef __CF__KnR -#define PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - _(T0,_cfPU)(CFC_(UN,LN))(CF_NULL_PROTO); static _Icf(2,U,T0,CFFUN(UN),0)( \ - CFARGT14FS(UCF,HCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ) \ -{ CFARGT14S(VCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) _(T0,_cfE) \ - CCF(LN,T1,1) CCF(LN,T2,2) CCF(LN,T3,3) CCF(LN,T4,4) CCF(LN,T5,5) \ - CCF(LN,T6,6) CCF(LN,T7,7) CCF(LN,T8,8) CCF(LN,T9,9) CCF(LN,TA,10) \ - CCF(LN,TB,11) CCF(LN,TC,12) CCF(LN,TD,13) CCF(LN,TE,14) _Icf(3,G,T0,UN,LN) \ - CFARGT14(CCCF,JCF,ABSOFT_cf1(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE)); \ - WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) \ - WCF(T6,A6,6) WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,A10,10) \ - WCF(TB,A11,11) WCF(TC,A12,12) WCF(TD,A13,13) WCF(TE,A14,14) _(T0,_cfX)} -#else -#define PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - _(T0,_cfPU)(CFC_(UN,LN))(CF_NULL_PROTO); static _Icf(2,U,T0,CFFUN(UN),0)( \ - CFARGT14FS(UUCF,HHCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ) \ - CFARGT14FS(UUUCF,HHHCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ; \ -{ CFARGT14S(VCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) _(T0,_cfE) \ - CCF(LN,T1,1) CCF(LN,T2,2) CCF(LN,T3,3) CCF(LN,T4,4) CCF(LN,T5,5) \ - CCF(LN,T6,6) CCF(LN,T7,7) CCF(LN,T8,8) CCF(LN,T9,9) CCF(LN,TA,10) \ - CCF(LN,TB,11) CCF(LN,TC,12) CCF(LN,TD,13) CCF(LN,TE,14) _Icf(3,G,T0,UN,LN) \ - CFARGT14(CCCF,JCF,ABSOFT_cf1(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE)); \ - WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) \ - WCF(T6,A6,6) WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,A10,10) \ - WCF(TB,A11,11) WCF(TC,A12,12) WCF(TD,A13,13) WCF(TE,A14,14) _(T0,_cfX)} -#endif - -/*-------------------------------------------------------------------------*/ - -/* UTILITIES FOR FORTRAN TO CALL C ROUTINES */ - -#ifdef OLD_VAXC /* Prevent %CC-I-PARAMNOTUSED. */ -#pragma nostandard -#endif - -#if defined(vmsFortran) || defined(CRAYFortran) -#define DCF(TN,I) -#define DDCF(TN,I) -#define DDDCF(TN,I) -#else -#define DCF(TN,I) HCF(TN,I) -#define DDCF(TN,I) HHCF(TN,I) -#define DDDCF(TN,I) HHHCF(TN,I) -#endif - -#define QCF(TN,I) _(TN,_cfSTR)(1,Q,_(B,I), 0,0,0,0) -#define DEFAULT_cfQ(B) -#define LOGICAL_cfQ(B) -#define PLOGICAL_cfQ(B) -#define STRINGV_cfQ(B) char *B; unsigned int _(B,N); -#define STRING_cfQ(B) char *B=NULL; -#define PSTRING_cfQ(B) char *B=NULL; -#define PSTRINGV_cfQ(B) STRINGV_cfQ(B) -#define PNSTRING_cfQ(B) char *B=NULL; -#define PPSTRING_cfQ(B) - -#ifdef __sgi /* Else SGI gives warning 182 contrary to its C LRM A.17.7 */ -#define ROUTINE_orig *(void**)& -#else -#define ROUTINE_orig (void *) -#endif - -#define ROUTINE_1 ROUTINE_orig -#define ROUTINE_2 ROUTINE_orig -#define ROUTINE_3 ROUTINE_orig -#define ROUTINE_4 ROUTINE_orig -#define ROUTINE_5 ROUTINE_orig -#define ROUTINE_6 ROUTINE_orig -#define ROUTINE_7 ROUTINE_orig -#define ROUTINE_8 ROUTINE_orig -#define ROUTINE_9 ROUTINE_orig -#define ROUTINE_10 ROUTINE_orig -#define ROUTINE_11 ROUTINE_orig -#define ROUTINE_12 ROUTINE_orig -#define ROUTINE_13 ROUTINE_orig -#define ROUTINE_14 ROUTINE_orig -#define ROUTINE_15 ROUTINE_orig -#define ROUTINE_16 ROUTINE_orig -#define ROUTINE_17 ROUTINE_orig -#define ROUTINE_18 ROUTINE_orig -#define ROUTINE_19 ROUTINE_orig -#define ROUTINE_20 ROUTINE_orig -#define ROUTINE_21 ROUTINE_orig -#define ROUTINE_22 ROUTINE_orig -#define ROUTINE_23 ROUTINE_orig -#define ROUTINE_24 ROUTINE_orig -#define ROUTINE_25 ROUTINE_orig -#define ROUTINE_26 ROUTINE_orig -#define ROUTINE_27 ROUTINE_orig - -#define TCF(NAME,TN,I,M) _SEP_(TN,M,cfCOMMA) _(TN,_cfT)(NAME,I,_(A,I),_(B,I),_(C,I)) -#define BYTE_cfT(M,I,A,B,D) *A -#define DOUBLE_cfT(M,I,A,B,D) *A -#define FLOAT_cfT(M,I,A,B,D) *A -#define INT_cfT(M,I,A,B,D) *A -#define LOGICAL_cfT(M,I,A,B,D) F2CLOGICAL(*A) -#define LONG_cfT(M,I,A,B,D) *A -#define LONGLONG_cfT(M,I,A,B,D) *A /* added by MR December 2005 */ -#define SHORT_cfT(M,I,A,B,D) *A -#define BYTEV_cfT(M,I,A,B,D) A -#define DOUBLEV_cfT(M,I,A,B,D) A -#define FLOATV_cfT(M,I,A,B,D) VOIDP A -#define INTV_cfT(M,I,A,B,D) A -#define LOGICALV_cfT(M,I,A,B,D) A -#define LONGV_cfT(M,I,A,B,D) A -#define LONGLONGV_cfT(M,I,A,B,D) A /* added by MR December 2005 */ -#define SHORTV_cfT(M,I,A,B,D) A -#define BYTEVV_cfT(M,I,A,B,D) (void *)A /* We have to cast to void *,*/ -#define BYTEVVV_cfT(M,I,A,B,D) (void *)A /* since we don't know the */ -#define BYTEVVVV_cfT(M,I,A,B,D) (void *)A /* dimensions of the array. */ -#define BYTEVVVVV_cfT(M,I,A,B,D) (void *)A /* i.e. Unfortunately, can't */ -#define BYTEVVVVVV_cfT(M,I,A,B,D) (void *)A /* check that the type */ -#define BYTEVVVVVVV_cfT(M,I,A,B,D) (void *)A /* matches the prototype. */ -#define DOUBLEVV_cfT(M,I,A,B,D) (void *)A -#define DOUBLEVVV_cfT(M,I,A,B,D) (void *)A -#define DOUBLEVVVV_cfT(M,I,A,B,D) (void *)A -#define DOUBLEVVVVV_cfT(M,I,A,B,D) (void *)A -#define DOUBLEVVVVVV_cfT(M,I,A,B,D) (void *)A -#define DOUBLEVVVVVVV_cfT(M,I,A,B,D) (void *)A -#define FLOATVV_cfT(M,I,A,B,D) (void *)A -#define FLOATVVV_cfT(M,I,A,B,D) (void *)A -#define FLOATVVVV_cfT(M,I,A,B,D) (void *)A -#define FLOATVVVVV_cfT(M,I,A,B,D) (void *)A -#define FLOATVVVVVV_cfT(M,I,A,B,D) (void *)A -#define FLOATVVVVVVV_cfT(M,I,A,B,D) (void *)A -#define INTVV_cfT(M,I,A,B,D) (void *)A -#define INTVVV_cfT(M,I,A,B,D) (void *)A -#define INTVVVV_cfT(M,I,A,B,D) (void *)A -#define INTVVVVV_cfT(M,I,A,B,D) (void *)A -#define INTVVVVVV_cfT(M,I,A,B,D) (void *)A -#define INTVVVVVVV_cfT(M,I,A,B,D) (void *)A -#define LOGICALVV_cfT(M,I,A,B,D) (void *)A -#define LOGICALVVV_cfT(M,I,A,B,D) (void *)A -#define LOGICALVVVV_cfT(M,I,A,B,D) (void *)A -#define LOGICALVVVVV_cfT(M,I,A,B,D) (void *)A -#define LOGICALVVVVVV_cfT(M,I,A,B,D) (void *)A -#define LOGICALVVVVVVV_cfT(M,I,A,B,D) (void *)A -#define LONGVV_cfT(M,I,A,B,D) (void *)A -#define LONGVVV_cfT(M,I,A,B,D) (void *)A -#define LONGVVVV_cfT(M,I,A,B,D) (void *)A -#define LONGVVVVV_cfT(M,I,A,B,D) (void *)A -#define LONGVVVVVV_cfT(M,I,A,B,D) (void *)A -#define LONGVVVVVVV_cfT(M,I,A,B,D) (void *)A -#define LONGLONGVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ -#define LONGLONGVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ -#define LONGLONGVVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ -#define LONGLONGVVVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ -#define LONGLONGVVVVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ -#define LONGLONGVVVVVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ -#define SHORTVV_cfT(M,I,A,B,D) (void *)A -#define SHORTVVV_cfT(M,I,A,B,D) (void *)A -#define SHORTVVVV_cfT(M,I,A,B,D) (void *)A -#define SHORTVVVVV_cfT(M,I,A,B,D) (void *)A -#define SHORTVVVVVV_cfT(M,I,A,B,D) (void *)A -#define SHORTVVVVVVV_cfT(M,I,A,B,D) (void *)A -#define PBYTE_cfT(M,I,A,B,D) A -#define PDOUBLE_cfT(M,I,A,B,D) A -#define PFLOAT_cfT(M,I,A,B,D) VOIDP A -#define PINT_cfT(M,I,A,B,D) A -#define PLOGICAL_cfT(M,I,A,B,D) ((*A=F2CLOGICAL(*A)),A) -#define PLONG_cfT(M,I,A,B,D) A -#define PLONGLONG_cfT(M,I,A,B,D) A /* added by MR December 2005 */ -#define PSHORT_cfT(M,I,A,B,D) A -#define PVOID_cfT(M,I,A,B,D) A -#if defined(apolloFortran) || defined(hpuxFortran800) || defined(AbsoftUNIXFortran) -#define ROUTINE_cfT(M,I,A,B,D) _(ROUTINE_,I) (*A) -#else -#define ROUTINE_cfT(M,I,A,B,D) _(ROUTINE_,I) A -#endif -/* A == pointer to the characters - D == length of the string, or of an element in an array of strings - E == number of elements in an array of strings */ -#define TTSTR( A,B,D) \ - ((B=_cf_malloc(D+1))[D]='\0', memcpy(B,A,D), kill_trailing(B,' ')) -#define TTTTSTR( A,B,D) (!(D<4||A[0]||A[1]||A[2]||A[3]))?NULL: \ - memchr(A,'\0',D) ?A : TTSTR(A,B,D) -#define TTTTSTRV( A,B,D,E) (_(B,N)=E,B=_cf_malloc(_(B,N)*(D+1)), (void *) \ - vkill_trailing(f2cstrv(A,B,D+1, _(B,N)*(D+1)), D+1,_(B,N)*(D+1),' ')) -#ifdef vmsFortran -#define STRING_cfT(M,I,A,B,D) TTTTSTR( A->dsc$a_pointer,B,A->dsc$w_length) -#define STRINGV_cfT(M,I,A,B,D) TTTTSTRV(A->dsc$a_pointer, B, \ - A->dsc$w_length , A->dsc$l_m[0]) -#define PSTRING_cfT(M,I,A,B,D) TTSTR( A->dsc$a_pointer,B,A->dsc$w_length) -#define PPSTRING_cfT(M,I,A,B,D) A->dsc$a_pointer -#else -#ifdef CRAYFortran -#define STRING_cfT(M,I,A,B,D) TTTTSTR( _fcdtocp(A),B,_fcdlen(A)) -#define STRINGV_cfT(M,I,A,B,D) TTTTSTRV(_fcdtocp(A),B,_fcdlen(A), \ - num_elem(_fcdtocp(A),_fcdlen(A),_3(M,_STRV_A,I))) -#define PSTRING_cfT(M,I,A,B,D) TTSTR( _fcdtocp(A),B,_fcdlen(A)) -#define PPSTRING_cfT(M,I,A,B,D) _fcdtocp(A) -#else -#define STRING_cfT(M,I,A,B,D) TTTTSTR( A,B,D) -#define STRINGV_cfT(M,I,A,B,D) TTTTSTRV(A,B,D, num_elem(A,D,_3(M,_STRV_A,I))) -#define PSTRING_cfT(M,I,A,B,D) TTSTR( A,B,D) -#define PPSTRING_cfT(M,I,A,B,D) A -#endif -#endif -#define PNSTRING_cfT(M,I,A,B,D) STRING_cfT(M,I,A,B,D) -#define PSTRINGV_cfT(M,I,A,B,D) STRINGV_cfT(M,I,A,B,D) -#define CF_0_cfT(M,I,A,B,D) - -#define RCF(TN,I) _(TN,_cfSTR)(3,R,_(A,I),_(B,I),_(C,I),0,0) -#define DEFAULT_cfR(A,B,D) -#define LOGICAL_cfR(A,B,D) -#define PLOGICAL_cfR(A,B,D) *A=C2FLOGICAL(*A); -#define STRING_cfR(A,B,D) if (B) _cf_free(B); -#define STRINGV_cfR(A,B,D) _cf_free(B); -/* A and D as defined above for TSTRING(V) */ -#define RRRRPSTR( A,B,D) if (B) memcpy(A,B, _cfMIN(strlen(B),D)), \ - (D>strlen(B)?memset(A+strlen(B),' ', D-strlen(B)):0), _cf_free(B); -#define RRRRPSTRV(A,B,D) c2fstrv(B,A,D+1,(D+1)*_(B,N)), _cf_free(B); -#ifdef vmsFortran -#define PSTRING_cfR(A,B,D) RRRRPSTR( A->dsc$a_pointer,B,A->dsc$w_length) -#define PSTRINGV_cfR(A,B,D) RRRRPSTRV(A->dsc$a_pointer,B,A->dsc$w_length) -#else -#ifdef CRAYFortran -#define PSTRING_cfR(A,B,D) RRRRPSTR( _fcdtocp(A),B,_fcdlen(A)) -#define PSTRINGV_cfR(A,B,D) RRRRPSTRV(_fcdtocp(A),B,_fcdlen(A)) -#else -#define PSTRING_cfR(A,B,D) RRRRPSTR( A,B,D) -#define PSTRINGV_cfR(A,B,D) RRRRPSTRV(A,B,D) -#endif -#endif -#define PNSTRING_cfR(A,B,D) PSTRING_cfR(A,B,D) -#define PPSTRING_cfR(A,B,D) - -#define BYTE_cfFZ(UN,LN) INTEGER_BYTE FCALLSC_QUALIFIER fcallsc(UN,LN)( -#define DOUBLE_cfFZ(UN,LN) DOUBLE_PRECISION FCALLSC_QUALIFIER fcallsc(UN,LN)( -#define INT_cfFZ(UN,LN) int FCALLSC_QUALIFIER fcallsc(UN,LN)( -#define LOGICAL_cfFZ(UN,LN) int FCALLSC_QUALIFIER fcallsc(UN,LN)( -#define LONG_cfFZ(UN,LN) long FCALLSC_QUALIFIER fcallsc(UN,LN)( -#define LONGLONG_cfFZ(UN,LN) LONGLONG FCALLSC_QUALIFIER fcallsc(UN,LN)( /* added by MR December 2005 */ -#define SHORT_cfFZ(UN,LN) short FCALLSC_QUALIFIER fcallsc(UN,LN)( -#define VOID_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)( -#ifndef __CF__KnR -/* The void is req'd by the Apollo, to make this an ANSI function declaration. - The Apollo promotes K&R float functions to double. */ -#if defined (f2cFortran) && ! defined (gFortran) -/* f2c/g77 return double from FORTRAN REAL functions. (KMCCARTY, 2005/12/09) */ -#define FLOAT_cfFZ(UN,LN) DOUBLE_PRECISION FCALLSC_QUALIFIER fcallsc(UN,LN)(void -#else -#define FLOAT_cfFZ(UN,LN) FORTRAN_REAL FCALLSC_QUALIFIER fcallsc(UN,LN)(void -#endif -#ifdef vmsFortran -#define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(fstring *AS -#else -#ifdef CRAYFortran -#define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(_fcd AS -#else -#if defined(AbsoftUNIXFortran) || defined(AbsoftProFortran) -#define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(char *AS -#else -#define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(char *AS, unsigned D0 -#endif -#endif -#endif -#else -#if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) -#if defined (f2cFortran) && ! defined (gFortran) -/* f2c/g77 return double from FORTRAN REAL functions. (KMCCARTY, 2005/12/09) */ -#define FLOAT_cfFZ(UN,LN) DOUBLE_PRECISION FCALLSC_QUALIFIER fcallsc(UN,LN)( -#else -#define FLOAT_cfFZ(UN,LN) FORTRAN_REAL FCALLSC_QUALIFIER fcallsc(UN,LN)( -#endif -#else -#define FLOAT_cfFZ(UN,LN) FLOATFUNCTIONTYPE FCALLSC_QUALIFIER fcallsc(UN,LN)( -#endif -#if defined(vmsFortran) || defined(CRAYFortran) || defined(AbsoftUNIXFortran) -#define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(AS -#else -#define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(AS, D0 -#endif -#endif - -#define BYTE_cfF(UN,LN) BYTE_cfFZ(UN,LN) -#define DOUBLE_cfF(UN,LN) DOUBLE_cfFZ(UN,LN) -#ifndef __CF_KnR -#if defined (f2cFortran) && ! defined (gFortran) -/* f2c/g77 return double from FORTRAN REAL functions. (KMCCARTY, 2005/12/09) */ -#define FLOAT_cfF(UN,LN) DOUBLE_PRECISION FCALLSC_QUALIFIER fcallsc(UN,LN)( -#else -#define FLOAT_cfF(UN,LN) FORTRAN_REAL FCALLSC_QUALIFIER fcallsc(UN,LN)( -#endif -#else -#define FLOAT_cfF(UN,LN) FLOAT_cfFZ(UN,LN) -#endif -#define INT_cfF(UN,LN) INT_cfFZ(UN,LN) -#define LOGICAL_cfF(UN,LN) LOGICAL_cfFZ(UN,LN) -#define LONG_cfF(UN,LN) LONG_cfFZ(UN,LN) -#define LONGLONG_cfF(UN,LN) LONGLONG_cfFZ(UN,LN) /* added by MR December 2005 */ -#define SHORT_cfF(UN,LN) SHORT_cfFZ(UN,LN) -#define VOID_cfF(UN,LN) VOID_cfFZ(UN,LN) -#define STRING_cfF(UN,LN) STRING_cfFZ(UN,LN), - -#define INT_cfFF -#define VOID_cfFF -#ifdef vmsFortran -#define STRING_cfFF fstring *AS; -#else -#ifdef CRAYFortran -#define STRING_cfFF _fcd AS; -#else -#define STRING_cfFF char *AS; unsigned D0; -#endif -#endif - -#define INT_cfL A0= -#define STRING_cfL A0= -#define VOID_cfL - -#define INT_cfK -#define VOID_cfK -/* KSTRING copies the string into the position provided by the caller. */ -#ifdef vmsFortran -#define STRING_cfK \ - memcpy(AS->dsc$a_pointer,A0,_cfMIN(AS->dsc$w_length,(A0==NULL?0:strlen(A0))));\ - AS->dsc$w_length>(A0==NULL?0:strlen(A0))? \ - memset(AS->dsc$a_pointer+(A0==NULL?0:strlen(A0)),' ', \ - AS->dsc$w_length-(A0==NULL?0:strlen(A0))):0; -#else -#ifdef CRAYFortran -#define STRING_cfK \ - memcpy(_fcdtocp(AS),A0, _cfMIN(_fcdlen(AS),(A0==NULL?0:strlen(A0))) ); \ - _fcdlen(AS)>(A0==NULL?0:strlen(A0))? \ - memset(_fcdtocp(AS)+(A0==NULL?0:strlen(A0)),' ', \ - _fcdlen(AS)-(A0==NULL?0:strlen(A0))):0; -#else -#define STRING_cfK memcpy(AS,A0, _cfMIN(D0,(A0==NULL?0:strlen(A0))) ); \ - D0>(A0==NULL?0:strlen(A0))?memset(AS+(A0==NULL?0:strlen(A0)), \ - ' ', D0-(A0==NULL?0:strlen(A0))):0; -#endif -#endif - -/* Note that K.. and I.. can't be combined since K.. has to access data before -R.., in order for functions returning strings which are also passed in as -arguments to work correctly. Note that R.. frees and hence may corrupt the -string. */ -#define BYTE_cfI return A0; -#define DOUBLE_cfI return A0; -#if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) -#define FLOAT_cfI return A0; -#else -#define FLOAT_cfI RETURNFLOAT(A0); -#endif -#define INT_cfI return A0; -#ifdef hpuxFortran800 -/* Incredibly, functions must return true as 1, elsewhere .true.==0x01000000. */ -#define LOGICAL_cfI return ((A0)?1:0); -#else -#define LOGICAL_cfI return C2FLOGICAL(A0); -#endif -#define LONG_cfI return A0; -#define LONGLONG_cfI return A0; /* added by MR December 2005 */ -#define SHORT_cfI return A0; -#define STRING_cfI return ; -#define VOID_cfI return ; - -#ifdef OLD_VAXC /* Allow %CC-I-PARAMNOTUSED. */ -#pragma standard -#endif - -#define FCALLSCSUB0( CN,UN,LN) FCALLSCFUN0(VOID,CN,UN,LN) -#define FCALLSCSUB1( CN,UN,LN,T1) FCALLSCFUN1(VOID,CN,UN,LN,T1) -#define FCALLSCSUB2( CN,UN,LN,T1,T2) FCALLSCFUN2(VOID,CN,UN,LN,T1,T2) -#define FCALLSCSUB3( CN,UN,LN,T1,T2,T3) FCALLSCFUN3(VOID,CN,UN,LN,T1,T2,T3) -#define FCALLSCSUB4( CN,UN,LN,T1,T2,T3,T4) \ - FCALLSCFUN4(VOID,CN,UN,LN,T1,T2,T3,T4) -#define FCALLSCSUB5( CN,UN,LN,T1,T2,T3,T4,T5) \ - FCALLSCFUN5(VOID,CN,UN,LN,T1,T2,T3,T4,T5) -#define FCALLSCSUB6( CN,UN,LN,T1,T2,T3,T4,T5,T6) \ - FCALLSCFUN6(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6) -#define FCALLSCSUB7( CN,UN,LN,T1,T2,T3,T4,T5,T6,T7) \ - FCALLSCFUN7(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7) -#define FCALLSCSUB8( CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) \ - FCALLSCFUN8(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) -#define FCALLSCSUB9( CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) \ - FCALLSCFUN9(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) -#define FCALLSCSUB10(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) \ - FCALLSCFUN10(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) -#define FCALLSCSUB11(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) \ - FCALLSCFUN11(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) -#define FCALLSCSUB12(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) \ - FCALLSCFUN12(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) -#define FCALLSCSUB13(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) \ - FCALLSCFUN13(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) -#define FCALLSCSUB14(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - FCALLSCFUN14(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) -#define FCALLSCSUB15(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF) \ - FCALLSCFUN15(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF) -#define FCALLSCSUB16(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG) \ - FCALLSCFUN16(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG) -#define FCALLSCSUB17(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH) \ - FCALLSCFUN17(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH) -#define FCALLSCSUB18(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI) \ - FCALLSCFUN18(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI) -#define FCALLSCSUB19(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ) \ - FCALLSCFUN19(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ) -#define FCALLSCSUB20(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ - FCALLSCFUN20(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) -#define FCALLSCSUB21(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL) \ - FCALLSCFUN21(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL) -#define FCALLSCSUB22(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM) \ - FCALLSCFUN22(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM) -#define FCALLSCSUB23(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN) \ - FCALLSCFUN23(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN) -#define FCALLSCSUB24(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO) \ - FCALLSCFUN24(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO) -#define FCALLSCSUB25(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP) \ - FCALLSCFUN25(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP) -#define FCALLSCSUB26(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ) \ - FCALLSCFUN26(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ) -#define FCALLSCSUB27(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ - FCALLSCFUN27(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) - - -#define FCALLSCFUN1( T0,CN,UN,LN,T1) \ - FCALLSCFUN5 (T0,CN,UN,LN,T1,CF_0,CF_0,CF_0,CF_0) -#define FCALLSCFUN2( T0,CN,UN,LN,T1,T2) \ - FCALLSCFUN5 (T0,CN,UN,LN,T1,T2,CF_0,CF_0,CF_0) -#define FCALLSCFUN3( T0,CN,UN,LN,T1,T2,T3) \ - FCALLSCFUN5 (T0,CN,UN,LN,T1,T2,T3,CF_0,CF_0) -#define FCALLSCFUN4( T0,CN,UN,LN,T1,T2,T3,T4) \ - FCALLSCFUN5 (T0,CN,UN,LN,T1,T2,T3,T4,CF_0) -#define FCALLSCFUN5( T0,CN,UN,LN,T1,T2,T3,T4,T5) \ - FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0) -#define FCALLSCFUN6( T0,CN,UN,LN,T1,T2,T3,T4,T5,T6) \ - FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0) -#define FCALLSCFUN7( T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7) \ - FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0) -#define FCALLSCFUN8( T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) \ - FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0) -#define FCALLSCFUN9( T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) \ - FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0) -#define FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) \ - FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0) -#define FCALLSCFUN11(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) \ - FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0) -#define FCALLSCFUN12(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) \ - FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0) -#define FCALLSCFUN13(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) \ - FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0) - - -#define FCALLSCFUN15(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF) \ - FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,CF_0,CF_0,CF_0,CF_0,CF_0) -#define FCALLSCFUN16(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG) \ - FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,CF_0,CF_0,CF_0,CF_0) -#define FCALLSCFUN17(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH) \ - FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,CF_0,CF_0,CF_0) -#define FCALLSCFUN18(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI) \ - FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,CF_0,CF_0) -#define FCALLSCFUN19(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ) \ - FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,CF_0) -#define FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ - FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) -#define FCALLSCFUN21(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL) \ - FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) -#define FCALLSCFUN22(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM) \ - FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,CF_0,CF_0,CF_0,CF_0,CF_0) -#define FCALLSCFUN23(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN) \ - FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,CF_0,CF_0,CF_0,CF_0) -#define FCALLSCFUN24(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO) \ - FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,CF_0,CF_0,CF_0) -#define FCALLSCFUN25(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP) \ - FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,CF_0,CF_0) -#define FCALLSCFUN26(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ) \ - FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,CF_0) - - -#ifndef __CF__KnR -#define FCALLSCFUN0(T0,CN,UN,LN) CFextern _(T0,_cfFZ)(UN,LN) ABSOFT_cf2(T0)) \ - {_Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN(); _Icf(0,K,T0,0,0) _(T0,_cfI)} - -#define FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - CFextern _(T0,_cfF)(UN,LN) \ - CFARGT14(NCF,DCF,ABSOFT_cf2(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ) \ - { CFARGT14S(QCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - _Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN( TCF(LN,T1,1,0) TCF(LN,T2,2,1) \ - TCF(LN,T3,3,1) TCF(LN,T4,4,1) TCF(LN,T5,5,1) TCF(LN,T6,6,1) TCF(LN,T7,7,1) \ - TCF(LN,T8,8,1) TCF(LN,T9,9,1) TCF(LN,TA,10,1) TCF(LN,TB,11,1) TCF(LN,TC,12,1) \ - TCF(LN,TD,13,1) TCF(LN,TE,14,1) ); _Icf(0,K,T0,0,0) \ - CFARGT14S(RCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) _(T0,_cfI) } - -#define FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ - CFextern _(T0,_cfF)(UN,LN) \ - CFARGT27(NCF,DCF,ABSOFT_cf2(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) ) \ - { CFARGT27S(QCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ - _Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN( TCF(LN,T1,1,0) TCF(LN,T2,2,1) \ - TCF(LN,T3,3,1) TCF(LN,T4,4,1) TCF(LN,T5,5,1) TCF(LN,T6,6,1) TCF(LN,T7,7,1) \ - TCF(LN,T8,8,1) TCF(LN,T9,9,1) TCF(LN,TA,10,1) TCF(LN,TB,11,1) TCF(LN,TC,12,1) \ - TCF(LN,TD,13,1) TCF(LN,TE,14,1) TCF(LN,TF,15,1) TCF(LN,TG,16,1) TCF(LN,TH,17,1) \ - TCF(LN,TI,18,1) TCF(LN,TJ,19,1) TCF(LN,TK,20,1) TCF(LN,TL,21,1) TCF(LN,TM,22,1) \ - TCF(LN,TN,23,1) TCF(LN,TO,24,1) TCF(LN,TP,25,1) TCF(LN,TQ,26,1) TCF(LN,TR,27,1) ); _Icf(0,K,T0,0,0) \ - CFARGT27S(RCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) _(T0,_cfI) } - -#else -#define FCALLSCFUN0(T0,CN,UN,LN) CFextern _(T0,_cfFZ)(UN,LN) ABSOFT_cf3(T0)) _Icf(0,FF,T0,0,0)\ - {_Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN(); _Icf(0,K,T0,0,0) _(T0,_cfI)} - -#define FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - CFextern _(T0,_cfF)(UN,LN) \ - CFARGT14(NNCF,DDCF,ABSOFT_cf3(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE)) _Icf(0,FF,T0,0,0) \ - CFARGT14FS(NNNCF,DDDCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE); \ - { CFARGT14S(QCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ - _Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN( TCF(LN,T1,1,0) TCF(LN,T2,2,1) \ - TCF(LN,T3,3,1) TCF(LN,T4,4,1) TCF(LN,T5,5,1) TCF(LN,T6,6,1) TCF(LN,T7,7,1) \ - TCF(LN,T8,8,1) TCF(LN,T9,9,1) TCF(LN,TA,10,1) TCF(LN,TB,11,1) TCF(LN,TC,12,1) \ - TCF(LN,TD,13,1) TCF(LN,TE,14,1) ); _Icf(0,K,T0,0,0) \ - CFARGT14S(RCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) _(T0,_cfI)} - -#define FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ - CFextern _(T0,_cfF)(UN,LN) \ - CFARGT27(NNCF,DDCF,ABSOFT_cf3(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR)) _Icf(0,FF,T0,0,0) \ - CFARGT27FS(NNNCF,DDDCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR); \ - { CFARGT27S(QCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ - _Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN( TCF(LN,T1,1,0) TCF(LN,T2,2,1) \ - TCF(LN,T3,3,1) TCF(LN,T4,4,1) TCF(LN,T5,5,1) TCF(LN,T6,6,1) TCF(LN,T7,7,1) \ - TCF(LN,T8,8,1) TCF(LN,T9,9,1) TCF(LN,TA,10,1) TCF(LN,TB,11,1) TCF(LN,TC,12,1) \ - TCF(LN,TD,13,1) TCF(LN,TE,14,1) TCF(LN,TF,15,1) TCF(LN,TG,16,1) TCF(LN,TH,17,1) \ - TCF(LN,TI,18,1) TCF(LN,TJ,19,1) TCF(LN,TK,20,1) TCF(LN,TL,21,1) TCF(LN,TM,22,1) \ - TCF(LN,TN,23,1) TCF(LN,TO,24,1) TCF(LN,TP,25,1) TCF(LN,TQ,26,1) TCF(LN,TR,27,1) ); _Icf(0,K,T0,0,0) \ - CFARGT27S(RCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) _(T0,_cfI)} - -#endif - - -#endif /* __CFORTRAN_LOADED */ diff --git a/src/external/OpenGR/3rdparty/cfitsio/checksum.c b/src/external/OpenGR/3rdparty/cfitsio/checksum.c deleted file mode 100644 index c52b9ef5a..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/checksum.c +++ /dev/null @@ -1,508 +0,0 @@ -/* This file, checksum.c, contains the checksum-related routines in the */ -/* FITSIO library. */ - -/* The FITSIO software was written by William Pence at the High Energy */ -/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ -/* Goddard Space Flight Center. */ - -#include -#include -#include "fitsio2.h" -/*------------------------------------------------------------------------*/ -int ffcsum(fitsfile *fptr, /* I - FITS file pointer */ - long nrec, /* I - number of 2880-byte blocks to sum */ - unsigned long *sum, /* IO - accumulated checksum */ - int *status) /* IO - error status */ -/* - Calculate a 32-bit 1's complement checksum of the FITS 2880-byte blocks. - This routine is based on the C algorithm developed by Rob - Seaman at NOAO that was presented at the 1994 ADASS conference, - published in the Astronomical Society of the Pacific Conference Series. - This uses a 32-bit 1's complement checksum in which the overflow bits - are permuted back into the sum and therefore all bit positions are - sampled evenly. -*/ -{ - long ii, jj; - unsigned short sbuf[1440]; - unsigned long hi, lo, hicarry, locarry; - - if (*status > 0) - return(*status); - /* - Sum the specified number of FITS 2880-byte records. This assumes that - the FITSIO file pointer points to the start of the records to be summed. - Read each FITS block as 1440 short values (do byte swapping if needed). - */ - for (jj = 0; jj < nrec; jj++) - { - ffgbyt(fptr, 2880, sbuf, status); - -#if BYTESWAPPED - - ffswap2( (short *)sbuf, 1440); /* reverse order of bytes in each value */ - -#endif - - hi = (*sum >> 16); - lo = *sum & 0xFFFF; - - for (ii = 0; ii < 1440; ii += 2) - { - hi += sbuf[ii]; - lo += sbuf[ii+1]; - } - - hicarry = hi >> 16; /* fold carry bits in */ - locarry = lo >> 16; - - while (hicarry | locarry) - { - hi = (hi & 0xFFFF) + locarry; - lo = (lo & 0xFFFF) + hicarry; - hicarry = hi >> 16; - locarry = lo >> 16; - } - - *sum = (hi << 16) + lo; - } - return(*status); -} -/*-------------------------------------------------------------------------*/ -void ffesum(unsigned long sum, /* I - accumulated checksum */ - int complm, /* I - = 1 to encode complement of the sum */ - char *ascii) /* O - 16-char ASCII encoded checksum */ -/* - encode the 32 bit checksum by converting every - 2 bits of each byte into an ASCII character (32 bit word encoded - as 16 character string). Only ASCII letters and digits are used - to encode the values (no ASCII punctuation characters). - - If complm=TRUE, then the complement of the sum will be encoded. - - This routine is based on the C algorithm developed by Rob - Seaman at NOAO that was presented at the 1994 ADASS conference, - published in the Astronomical Society of the Pacific Conference Series. -*/ -{ - unsigned int exclude[13] = { 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, - 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60 }; - unsigned long mask[4] = { 0xff000000, 0xff0000, 0xff00, 0xff }; - - int offset = 0x30; /* ASCII 0 (zero) */ - - unsigned long value; - int byte, quotient, remainder, ch[4], check, ii, jj, kk; - char asc[32]; - - if (complm) - value = 0xFFFFFFFF - sum; /* complement each bit of the value */ - else - value = sum; - - for (ii = 0; ii < 4; ii++) - { - byte = (value & mask[ii]) >> (24 - (8 * ii)); - quotient = byte / 4 + offset; - remainder = byte % 4; - for (jj = 0; jj < 4; jj++) - ch[jj] = quotient; - - ch[0] += remainder; - - for (check = 1; check;) /* avoid ASCII punctuation */ - for (check = 0, kk = 0; kk < 13; kk++) - for (jj = 0; jj < 4; jj += 2) - if ((unsigned char) ch[jj] == exclude[kk] || - (unsigned char) ch[jj+1] == exclude[kk]) - { - ch[jj]++; - ch[jj+1]--; - check++; - } - - for (jj = 0; jj < 4; jj++) /* assign the bytes */ - asc[4*jj+ii] = ch[jj]; - } - - for (ii = 0; ii < 16; ii++) /* shift the bytes 1 to the right */ - ascii[ii] = asc[(ii+15)%16]; - - ascii[16] = '\0'; -} -/*-------------------------------------------------------------------------*/ -unsigned long ffdsum(char *ascii, /* I - 16-char ASCII encoded checksum */ - int complm, /* I - =1 to decode complement of the */ - unsigned long *sum) /* O - 32-bit checksum */ -/* - decode the 16-char ASCII encoded checksum into an unsigned 32-bit long. - If complm=TRUE, then the complement of the sum will be decoded. - - This routine is based on the C algorithm developed by Rob - Seaman at NOAO that was presented at the 1994 ADASS conference, - published in the Astronomical Society of the Pacific Conference Series. -*/ -{ - char cbuf[16]; - unsigned long hi = 0, lo = 0, hicarry, locarry; - int ii; - - /* remove the permuted FITS byte alignment and the ASCII 0 offset */ - for (ii = 0; ii < 16; ii++) - { - cbuf[ii] = ascii[(ii+1)%16]; - cbuf[ii] -= 0x30; - } - - for (ii = 0; ii < 16; ii += 4) - { - hi += (cbuf[ii] << 8) + cbuf[ii+1]; - lo += (cbuf[ii+2] << 8) + cbuf[ii+3]; - } - - hicarry = hi >> 16; - locarry = lo >> 16; - while (hicarry || locarry) - { - hi = (hi & 0xFFFF) + locarry; - lo = (lo & 0xFFFF) + hicarry; - hicarry = hi >> 16; - locarry = lo >> 16; - } - - *sum = (hi << 16) + lo; - if (complm) - *sum = 0xFFFFFFFF - *sum; /* complement each bit of the value */ - - return(*sum); -} -/*------------------------------------------------------------------------*/ -int ffpcks(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -/* - Create or update the checksum keywords in the CHDU. These keywords - provide a checksum verification of the FITS HDU based on the ASCII - coded 1's complement checksum algorithm developed by Rob Seaman at NOAO. -*/ -{ - char datestr[20], checksum[FLEN_VALUE], datasum[FLEN_VALUE]; - char comm[FLEN_COMMENT], chkcomm[FLEN_COMMENT], datacomm[FLEN_COMMENT]; - int tstatus; - long nrec; - LONGLONG headstart, datastart, dataend; - unsigned long dsum, olddsum, sum; - double tdouble; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - /* generate current date string and construct the keyword comments */ - ffgstm(datestr, NULL, status); - strcpy(chkcomm, "HDU checksum updated "); - strcat(chkcomm, datestr); - strcpy(datacomm, "data unit checksum updated "); - strcat(datacomm, datestr); - - /* write the CHECKSUM keyword if it does not exist */ - tstatus = *status; - if (ffgkys(fptr, "CHECKSUM", checksum, comm, status) == KEY_NO_EXIST) - { - *status = tstatus; - strcpy(checksum, "0000000000000000"); - ffpkys(fptr, "CHECKSUM", checksum, chkcomm, status); - } - - /* write the DATASUM keyword if it does not exist */ - tstatus = *status; - if (ffgkys(fptr, "DATASUM", datasum, comm, status) == KEY_NO_EXIST) - { - *status = tstatus; - olddsum = 0; - ffpkys(fptr, "DATASUM", " 0", datacomm, status); - - /* set the CHECKSUM keyword as undefined, if it isn't already */ - if (strcmp(checksum, "0000000000000000") ) - { - strcpy(checksum, "0000000000000000"); - ffmkys(fptr, "CHECKSUM", checksum, chkcomm, status); - } - } - else - { - /* decode the datasum into an unsigned long variable */ - - /* olddsum = strtoul(datasum, 0, 10); doesn't work on SUN OS */ - - tdouble = atof(datasum); - olddsum = (unsigned long) tdouble; - } - - /* close header: rewrite END keyword and following blank fill */ - /* and re-read the required keywords to determine the structure */ - if (ffrdef(fptr, status) > 0) - return(*status); - - if ((fptr->Fptr)->heapsize > 0) - ffuptf(fptr, status); /* update the variable length TFORM values */ - - /* write the correct data fill values, if they are not already correct */ - if (ffpdfl(fptr, status) > 0) - return(*status); - - /* calc size of data unit, in FITS 2880-byte blocks */ - if (ffghadll(fptr, &headstart, &datastart, &dataend, status) > 0) - return(*status); - - nrec = (long) ((dataend - datastart) / 2880); - dsum = 0; - - if (nrec > 0) - { - /* accumulate the 32-bit 1's complement checksum */ - ffmbyt(fptr, datastart, REPORT_EOF, status); - if (ffcsum(fptr, nrec, &dsum, status) > 0) - return(*status); - } - - if (dsum != olddsum) - { - /* update the DATASUM keyword with the correct value */ - sprintf(datasum, "%lu", dsum); - ffmkys(fptr, "DATASUM", datasum, datacomm, status); - - /* set the CHECKSUM keyword as undefined, if it isn't already */ - if (strcmp(checksum, "0000000000000000") ) - { - strcpy(checksum, "0000000000000000"); - ffmkys(fptr, "CHECKSUM", checksum, chkcomm, status); - } - } - - if (strcmp(checksum, "0000000000000000") ) - { - /* check if CHECKSUM is still OK; move to the start of the header */ - ffmbyt(fptr, headstart, REPORT_EOF, status); - - /* accumulate the header checksum into the previous data checksum */ - nrec = (long) ((datastart - headstart) / 2880); - sum = dsum; - if (ffcsum(fptr, nrec, &sum, status) > 0) - return(*status); - - if (sum == 0 || sum == 0xFFFFFFFF) - return(*status); /* CHECKSUM is correct */ - - /* Zero the CHECKSUM and recompute the new value */ - ffmkys(fptr, "CHECKSUM", "0000000000000000", chkcomm, status); - } - - /* move to the start of the header */ - ffmbyt(fptr, headstart, REPORT_EOF, status); - - /* accumulate the header checksum into the previous data checksum */ - nrec = (long) ((datastart - headstart) / 2880); - sum = dsum; - if (ffcsum(fptr, nrec, &sum, status) > 0) - return(*status); - - /* encode the COMPLEMENT of the checksum into a 16-character string */ - ffesum(sum, TRUE, checksum); - - /* update the CHECKSUM keyword value with the new string */ - ffmkys(fptr, "CHECKSUM", checksum, "&", status); - - return(*status); -} -/*------------------------------------------------------------------------*/ -int ffupck(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -/* - Update the CHECKSUM keyword value. This assumes that the DATASUM - keyword exists and has the correct value. -*/ -{ - char datestr[20], chkcomm[FLEN_COMMENT], comm[FLEN_COMMENT]; - char checksum[FLEN_VALUE], datasum[FLEN_VALUE]; - int tstatus; - long nrec; - LONGLONG headstart, datastart, dataend; - unsigned long sum, dsum; - double tdouble; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - /* generate current date string and construct the keyword comments */ - ffgstm(datestr, NULL, status); - strcpy(chkcomm, "HDU checksum updated "); - strcat(chkcomm, datestr); - - /* get the DATASUM keyword and convert it to a unsigned long */ - if (ffgkys(fptr, "DATASUM", datasum, comm, status) == KEY_NO_EXIST) - { - ffpmsg("DATASUM keyword not found (ffupck"); - return(*status); - } - - tdouble = atof(datasum); /* read as a double as a workaround */ - dsum = (unsigned long) tdouble; - - /* get size of the HDU */ - if (ffghadll(fptr, &headstart, &datastart, &dataend, status) > 0) - return(*status); - - /* get the checksum keyword, if it exists */ - tstatus = *status; - if (ffgkys(fptr, "CHECKSUM", checksum, comm, status) == KEY_NO_EXIST) - { - *status = tstatus; - strcpy(checksum, "0000000000000000"); - ffpkys(fptr, "CHECKSUM", checksum, chkcomm, status); - } - else - { - /* check if CHECKSUM is still OK */ - /* rewrite END keyword and following blank fill */ - if (ffwend(fptr, status) > 0) - return(*status); - - /* move to the start of the header */ - ffmbyt(fptr, headstart, REPORT_EOF, status); - - /* accumulate the header checksum into the previous data checksum */ - nrec = (long) ((datastart - headstart) / 2880); - sum = dsum; - if (ffcsum(fptr, nrec, &sum, status) > 0) - return(*status); - - if (sum == 0 || sum == 0xFFFFFFFF) - return(*status); /* CHECKSUM is already correct */ - - /* Zero the CHECKSUM and recompute the new value */ - ffmkys(fptr, "CHECKSUM", "0000000000000000", chkcomm, status); - } - - /* move to the start of the header */ - ffmbyt(fptr, headstart, REPORT_EOF, status); - - /* accumulate the header checksum into the previous data checksum */ - nrec = (long) ((datastart - headstart) / 2880); - sum = dsum; - if (ffcsum(fptr, nrec, &sum, status) > 0) - return(*status); - - /* encode the COMPLEMENT of the checksum into a 16-character string */ - ffesum(sum, TRUE, checksum); - - /* update the CHECKSUM keyword value with the new string */ - ffmkys(fptr, "CHECKSUM", checksum, "&", status); - - return(*status); -} -/*------------------------------------------------------------------------*/ -int ffvcks(fitsfile *fptr, /* I - FITS file pointer */ - int *datastatus, /* O - data checksum status */ - int *hdustatus, /* O - hdu checksum status */ - /* 1 verification is correct */ - /* 0 checksum keyword is not present */ - /* -1 verification not correct */ - int *status) /* IO - error status */ -/* - Verify the HDU by comparing the value of the computed checksums against - the values of the DATASUM and CHECKSUM keywords if they are present. -*/ -{ - int tstatus; - double tdouble; - unsigned long datasum, hdusum, olddatasum; - char chksum[FLEN_VALUE], comm[FLEN_COMMENT]; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - *datastatus = -1; - *hdustatus = -1; - - tstatus = *status; - if (ffgkys(fptr, "CHECKSUM", chksum, comm, status) == KEY_NO_EXIST) - { - *hdustatus = 0; /* CHECKSUM keyword does not exist */ - *status = tstatus; - } - if (chksum[0] == '\0') - *hdustatus = 0; /* all blank checksum means it is undefined */ - - if (ffgkys(fptr, "DATASUM", chksum, comm, status) == KEY_NO_EXIST) - { - *datastatus = 0; /* DATASUM keyword does not exist */ - *status = tstatus; - } - if (chksum[0] == '\0') - *datastatus = 0; /* all blank checksum means it is undefined */ - - if ( *status > 0 || (!(*hdustatus) && !(*datastatus)) ) - return(*status); /* return if neither keywords exist */ - - /* convert string to unsigned long */ - - /* olddatasum = strtoul(chksum, 0, 10); doesn't work w/ gcc on SUN OS */ - /* sscanf(chksum, "%u", &olddatasum); doesn't work w/ cc on VAX/VMS */ - - tdouble = atof(chksum); /* read as a double as a workaround */ - olddatasum = (unsigned long) tdouble; - - /* calculate the data checksum and the HDU checksum */ - if (ffgcks(fptr, &datasum, &hdusum, status) > 0) - return(*status); - - if (*datastatus) - if (datasum == olddatasum) - *datastatus = 1; - - if (*hdustatus) - if (hdusum == 0 || hdusum == 0xFFFFFFFF) - *hdustatus = 1; - - return(*status); -} -/*------------------------------------------------------------------------*/ -int ffgcks(fitsfile *fptr, /* I - FITS file pointer */ - unsigned long *datasum, /* O - data checksum */ - unsigned long *hdusum, /* O - hdu checksum */ - int *status) /* IO - error status */ - - /* calculate the checksums of the data unit and the total HDU */ -{ - long nrec; - LONGLONG headstart, datastart, dataend; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - /* get size of the HDU */ - if (ffghadll(fptr, &headstart, &datastart, &dataend, status) > 0) - return(*status); - - nrec = (long) ((dataend - datastart) / 2880); - - *datasum = 0; - - if (nrec > 0) - { - /* accumulate the 32-bit 1's complement checksum */ - ffmbyt(fptr, datastart, REPORT_EOF, status); - if (ffcsum(fptr, nrec, datasum, status) > 0) - return(*status); - } - - /* move to the start of the header and calc. size of header */ - ffmbyt(fptr, headstart, REPORT_EOF, status); - nrec = (long) ((datastart - headstart) / 2880); - - /* accumulate the header checksum into the previous data checksum */ - *hdusum = *datasum; - ffcsum(fptr, nrec, hdusum, status); - - return(*status); -} - diff --git a/src/external/OpenGR/3rdparty/cfitsio/config.guess b/src/external/OpenGR/3rdparty/cfitsio/config.guess deleted file mode 100644 index d622a44e5..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/config.guess +++ /dev/null @@ -1,1530 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. - -timestamp='2012-02-10' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner. Please send patches (context -# diff format) to and include a ChangeLog -# entry. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH="x86_64" - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-gnu - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-gnueabi - else - echo ${UNAME_MACHINE}-unknown-linux-gnueabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu - exit ;; - crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu - exit ;; - frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - i*86:Linux:*:*) - LIBC=gnu - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-gnu - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu - exit ;; - x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - i386) - eval $set_cc_for_build - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - UNAME_PROCESSOR="x86_64" - fi - fi ;; - unknown) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-?:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; - x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx - exit ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/src/external/OpenGR/3rdparty/cfitsio/config.sub b/src/external/OpenGR/3rdparty/cfitsio/config.sub deleted file mode 100644 index 59bb593f1..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/config.sub +++ /dev/null @@ -1,1779 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. - -timestamp='2012-04-18' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Please send patches to . Submit a context -# diff and a properly formatted GNU ChangeLog entry. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | be32 | be64 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 \ - | ns16k | ns32k \ - | open8 \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze) - basic_machine=microblaze-xilinx - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i386-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/src/external/OpenGR/3rdparty/cfitsio/configure b/src/external/OpenGR/3rdparty/cfitsio/configure deleted file mode 100644 index 924518c46..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/configure +++ /dev/null @@ -1,7470 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69. -# -# -# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. -# -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# Use a proper internal environment variable to ensure we don't fall - # into an infinite loop, continuously re-executing ourselves. - if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then - _as_can_reexec=no; export _as_can_reexec; - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -as_fn_exit 255 - fi - # We don't want this to propagate to other subprocesses. - { _as_can_reexec=; unset _as_can_reexec;} -if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi -" - as_required="as_fn_return () { (exit \$1); } -as_fn_success () { as_fn_return 0; } -as_fn_failure () { as_fn_return 1; } -as_fn_ret_success () { return 0; } -as_fn_ret_failure () { return 1; } - -exitcode=0 -as_fn_success || { exitcode=1; echo as_fn_success failed.; } -as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } -as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } -as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : - -else - exitcode=1; echo positional parameters were not saved. -fi -test x\$exitcode = x0 || exit 1 -test -x / || exit 1" - as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO - as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO - eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && - test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 -test \$(( 1 + 1 )) = 2 || exit 1" - if (eval "$as_required") 2>/dev/null; then : - as_have_required=yes -else - as_have_required=no -fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : - -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_found=false -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - as_found=: - case $as_dir in #( - /*) - for as_base in sh bash ksh sh5; do - # Try only shells that exist, to save several forks. - as_shell=$as_dir/$as_base - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : - CONFIG_SHELL=$as_shell as_have_required=yes - if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : - break 2 -fi -fi - done;; - esac - as_found=false -done -$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi; } -IFS=$as_save_IFS - - - if test "x$CONFIG_SHELL" != x; then : - export CONFIG_SHELL - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -exit 255 -fi - - if test x$as_have_required = xno; then : - $as_echo "$0: This script requires a shell more modern than all" - $as_echo "$0: the shells that I found on your system." - if test x${ZSH_VERSION+set} = xset ; then - $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" - $as_echo "$0: be upgraded to zsh 4.3.4 or later." - else - $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, -$0: including any error possibly output before this -$0: message. Then install a modern shell, or manually run -$0: the script under such a shell if you do have one." - fi - exit 1 -fi -fi -fi -SHELL=${CONFIG_SHELL-/bin/sh} -export SHELL -# Unset more variables known to interfere with behavior of common tools. -CLICOLOR_FORCE= GREP_OPTIONS= -unset CLICOLOR_FORCE GREP_OPTIONS - -## --------------------- ## -## M4sh Shell Functions. ## -## --------------------- ## -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - - - as_lineno_1=$LINENO as_lineno_1a=$LINENO - as_lineno_2=$LINENO as_lineno_2a=$LINENO - eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && - test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { - # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } - - # If we had to re-execute with $CONFIG_SHELL, we're ensured to have - # already done that, so ensure we don't try to do so again and fall - # in an infinite loop. This has already happened in practice. - _as_can_reexec=no; export _as_can_reexec - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -test -n "$DJDIR" || exec 7<&0 &1 - -# Name of the host. -# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_clean_files= -ac_config_libobj_dir=. -LIBOBJS= -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= - -# Identity of this package. -PACKAGE_NAME= -PACKAGE_TARNAME= -PACKAGE_VERSION= -PACKAGE_STRING= -PACKAGE_BUGREPORT= -PACKAGE_URL= - -ac_unique_file="fitscore.c" -# Factoring default headers for most tests. -ac_includes_default="\ -#include -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_STRING_H -# if !defined STDC_HEADERS && defined HAVE_MEMORY_H -# include -# endif -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#ifdef HAVE_INTTYPES_H -# include -#endif -#ifdef HAVE_STDINT_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif" - -ac_default_prefix=`pwd` -ac_subst_vars='LTLIBOBJS -LIBOBJS -my_shmem -LDFLAGS_BIN -F77_WRAPPERS -CFITSIO_SHLIB_SONAME -CFITSIO_SHLIB -SHLIB_SUFFIX -SHLIB_LD -LIBPRE -ARCH -GCCVERSION -SSE_FLAGS -RANLIB -ARCHIVE -AR -FC -INSTALL_ROOT -EGREP -GREP -CPP -OBJEXT -EXEEXT -ac_ct_CC -CPPFLAGS -LDFLAGS -CFLAGS -CC -CFITSIO_SONAME -CFITSIO_MINOR -CFITSIO_MAJOR -target_os -target_vendor -target_cpu -target -host_os -host_vendor -host_cpu -host -build_os -build_vendor -build_cpu -build -target_alias -host_alias -build_alias -LIBS -ECHO_T -ECHO_N -ECHO_C -DEFS -mandir -localedir -libdir -psdir -pdfdir -dvidir -htmldir -infodir -docdir -oldincludedir -includedir -localstatedir -sharedstatedir -sysconfdir -datadir -datarootdir -libexecdir -sbindir -bindir -program_transform_name -prefix -exec_prefix -PACKAGE_URL -PACKAGE_BUGREPORT -PACKAGE_STRING -PACKAGE_VERSION -PACKAGE_TARNAME -PACKAGE_NAME -PATH_SEPARATOR -SHELL' -ac_subst_files='' -ac_user_opts=' -enable_option_checking -enable_reentrant -enable_sse2 -enable_ssse3 -enable_hera -with_gsiftp_flavour -with_gsiftp -with_bzip2 -' - ac_precious_vars='build_alias -host_alias -target_alias -CC -CFLAGS -LDFLAGS -LIBS -CPPFLAGS -CPP' - - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -ac_unrecognized_opts= -ac_unrecognized_sep= -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -# (The list follows the same order as the GNU Coding Standards.) -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datarootdir='${prefix}/share' -datadir='${datarootdir}' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -includedir='${prefix}/include' -oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE}' -infodir='${datarootdir}/info' -htmldir='${docdir}' -dvidir='${docdir}' -pdfdir='${docdir}' -psdir='${docdir}' -libdir='${exec_prefix}/lib' -localedir='${datarootdir}/locale' -mandir='${datarootdir}/man' - -ac_prev= -ac_dashdash= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval $ac_prev=\$ac_option - ac_prev= - continue - fi - - case $ac_option in - *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *=) ac_optarg= ;; - *) ac_optarg=yes ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_dashdash$ac_option in - --) - ac_dashdash=yes ;; - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=*) - datadir=$ac_optarg ;; - - -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ - | --dataroo | --dataro | --datar) - ac_prev=datarootdir ;; - -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ - | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) - datarootdir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=no ;; - - -docdir | --docdir | --docdi | --doc | --do) - ac_prev=docdir ;; - -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) - docdir=$ac_optarg ;; - - -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) - ac_prev=dvidir ;; - -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) - dvidir=$ac_optarg ;; - - -enable-* | --enable-*) - ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=\$ac_optarg ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) - ac_prev=htmldir ;; - -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ - | --ht=*) - htmldir=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localedir | --localedir | --localedi | --localed | --locale) - ac_prev=localedir ;; - -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) - localedir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst | --locals) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) - ac_prev=pdfdir ;; - -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) - pdfdir=$ac_optarg ;; - - -psdir | --psdir | --psdi | --psd | --ps) - ac_prev=psdir ;; - -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) - psdir=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=\$ac_optarg ;; - - -without-* | --without-*) - ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=no ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) as_fn_error $? "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information" - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - case $ac_envvar in #( - '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; - esac - eval $ac_envvar=\$ac_optarg - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error $? "missing argument to $ac_option" -fi - -if test -n "$ac_unrecognized_opts"; then - case $enable_option_checking in - no) ;; - fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; - *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; - esac -fi - -# Check all directory arguments for consistency. -for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir -do - eval ac_val=\$$ac_var - # Remove trailing slashes. - case $ac_val in - */ ) - ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` - eval $ac_var=\$ac_val;; - esac - # Be sure to have absolute directory names. - case $ac_val in - [\\/$]* | ?:[\\/]* ) continue;; - NONE | '' ) case $ac_var in *prefix ) continue;; esac;; - esac - as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -ac_pwd=`pwd` && test -n "$ac_pwd" && -ac_ls_di=`ls -di .` && -ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error $? "working directory cannot be determined" -test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error $? "pwd does not report name of working directory" - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$as_myself" || -$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_myself" : 'X\(//\)[^/]' \| \ - X"$as_myself" : 'X\(//\)$' \| \ - X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_myself" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r "$srcdir/$ac_unique_file"; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r "$srcdir/$ac_unique_file"; then - test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" -fi -ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" -ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" - pwd)` -# When building in place, set srcdir=. -if test "$ac_abs_confdir" = "$ac_pwd"; then - srcdir=. -fi -# Remove unnecessary trailing slashes from srcdir. -# Double slashes in file names in object file debugging info -# mess up M-x gdb in Emacs. -case $srcdir in -*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; -esac -for ac_var in $ac_precious_vars; do - eval ac_env_${ac_var}_set=\${${ac_var}+set} - eval ac_env_${ac_var}_value=\$${ac_var} - eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} - eval ac_cv_env_${ac_var}_value=\$${ac_var} -done - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures this package to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking ...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -_ACEOF - - cat <<\_ACEOF - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] - --target=TARGET configure for building compilers for TARGET [HOST] -_ACEOF -fi - -if test -n "$ac_init_help"; then - - cat <<\_ACEOF - -Optional Features: - --disable-option-checking ignore unrecognized --enable/--with options - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-reentrant Enable reentrant multithreading - --enable-sse2 Enable use of instructions in the SSE2 extended - instruction set - --enable-ssse3 Enable use of instructions in the SSSE3 extended - instruction set - --enable-hera Build for HERA (ASD use only) - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-gsiftp-flavour[=PATH] - Enable Globus Toolkit gsiftp protocol support - --with-gsiftp[=PATH] Enable Globus Toolkit gsiftp protocol support - --with-bzip2[=PATH] Enable bzip2 support. Optional path to the location - of include/bzlib.h and lib/libbz2 - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - LIBS libraries to pass to the linker, e.g. -l - CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if - you have headers in a nonstandard directory - CPP C preprocessor - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -Report bugs to the package provider. -_ACEOF -ac_status=$? -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || - { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || - continue - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. - if test -f "$ac_srcdir/configure.gnu"; then - echo && - $SHELL "$ac_srcdir/configure.gnu" --help=recursive - elif test -f "$ac_srcdir/configure"; then - echo && - $SHELL "$ac_srcdir/configure" --help=recursive - else - $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi || ac_status=$? - cd "$ac_pwd" || { ac_status=$?; break; } - done -fi - -test -n "$ac_init_help" && exit $ac_status -if $ac_init_version; then - cat <<\_ACEOF -configure -generated by GNU Autoconf 2.69 - -Copyright (C) 2012 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit -fi - -## ------------------------ ## -## Autoconf initialization. ## -## ------------------------ ## - -# ac_fn_c_try_compile LINENO -# -------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_compile - -# ac_fn_c_try_cpp LINENO -# ---------------------- -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_cpp - -# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists, giving a warning if it cannot be compiled using -# the include files in INCLUDES and setting the cache variable VAR -# accordingly. -ac_fn_c_check_header_mongrel () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if eval \${$3+:} false; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -else - # Is the header compilable? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 -$as_echo_n "checking $2 usability... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_header_compiler=yes -else - ac_header_compiler=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 -$as_echo "$ac_header_compiler" >&6; } - -# Is the header present? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 -$as_echo_n "checking $2 presence... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <$2> -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - ac_header_preproc=yes -else - ac_header_preproc=no -fi -rm -f conftest.err conftest.i conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 -$as_echo "$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( - yes:no: ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 -$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; - no:yes:* ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 -$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 -$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 -$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 -$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=\$ac_header_compiler" -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_header_mongrel - -# ac_fn_c_try_run LINENO -# ---------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes -# that executables *can* be run. -ac_fn_c_try_run () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then : - ac_retval=0 -else - $as_echo "$as_me: program exited with status $ac_status" >&5 - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=$ac_status -fi - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_run - -# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists and can be compiled using the include files in -# INCLUDES, setting the cache variable VAR accordingly. -ac_fn_c_check_header_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_header_compile - -# ac_fn_c_try_link LINENO -# ----------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - test -x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_link -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by $as_me, which was -generated by GNU Autoconf 2.69. Invocation command line was - - $ $0 $@ - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" - done -IFS=$as_save_IFS - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *\'*) - ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; - 2) - as_fn_append ac_configure_args1 " '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - as_fn_append ac_configure_args " '$ac_arg'" - ;; - esac - done -done -{ ac_configure_args0=; unset ac_configure_args0;} -{ ac_configure_args1=; unset ac_configure_args1;} - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Use '\'' to represent an apostrophe within the trap. -# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - $as_echo "## ---------------- ## -## Cache variables. ## -## ---------------- ##" - echo - # The following way of writing the cache mishandles newlines in values, -( - for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - (set) 2>&1 | - case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - sed -n \ - "s/'\''/'\''\\\\'\'''\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" - ;; #( - *) - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) - echo - - $as_echo "## ----------------- ## -## Output variables. ## -## ----------------- ##" - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## -## File substitutions. ## -## ------------------- ##" - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - $as_echo "## ----------- ## -## confdefs.h. ## -## ----------- ##" - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - $as_echo "$as_me: caught signal $ac_signal" - $as_echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core core.conftest.* && - rm -f -r conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status -' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -f -r conftest* confdefs.h - -$as_echo "/* confdefs.h */" > confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_URL "$PACKAGE_URL" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer an explicitly selected file to automatically selected ones. -ac_site_file1=NONE -ac_site_file2=NONE -if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac -elif test "x$prefix" != xNONE; then - ac_site_file1=$prefix/share/config.site - ac_site_file2=$prefix/etc/config.site -else - ac_site_file1=$ac_default_prefix/share/config.site - ac_site_file2=$ac_default_prefix/etc/config.site -fi -for ac_site_file in "$ac_site_file1" "$ac_site_file2" -do - test "x$ac_site_file" = xNONE && continue - if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -$as_echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5; } - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special files - # actually), so we avoid doing that. DJGPP emulates it as a regular file. - if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -$as_echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -$as_echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - # differences in whitespace do not lead to failure. - ac_old_val_w=`echo x $ac_old_val` - ac_new_val_w=`echo x $ac_new_val` - if test "$ac_old_val_w" != "$ac_new_val_w"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) as_fn_append ac_configure_args " '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 -fi -## -------------------- ## -## Main body of script. ## -## -------------------- ## - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -ac_aux_dir= -for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if ${ac_cv_build+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` -test "x$ac_build_alias" = x && - as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if ${ac_cv_host+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build -else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 -$as_echo_n "checking target system type... " >&6; } -if ${ac_cv_target+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "x$target_alias" = x; then - ac_cv_target=$ac_cv_host -else - ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 -$as_echo "$ac_cv_target" >&6; } -case $ac_cv_target in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; -esac -target=$ac_cv_target -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_target -shift -target_cpu=$1 -target_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -target_os=$* -IFS=$ac_save_IFS -case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac - - -# The aliases save the names the user supplied, while $host etc. -# will get canonicalized. -test -n "$target_alias" && - test "$program_prefix$program_suffix$program_transform_name" = \ - NONENONEs,x,x, && - program_prefix=${target_alias}- - -#-------------------------------------------------------------------- -# CFITSIO Version Numbers: -#-------------------------------------------------------------------- -CFITSIO_MAJOR=3 - -CFITSIO_MINOR=41 - -# Increment soname each time the interface changes: -CFITSIO_SONAME=5 - - -#-------------------------------------------------------------------- -# Command options -#-------------------------------------------------------------------- - -# Check whether --enable-reentrant was given. -if test "${enable_reentrant+set}" = set; then : - enableval=$enable_reentrant; if test $enableval = yes; then BUILD_REENTRANT=yes; fi - -fi - - -SSE_FLAGS="" -# Check whether --enable-sse2 was given. -if test "${enable_sse2+set}" = set; then : - enableval=$enable_sse2; if test $enableval = yes; then SSE_FLAGS="-msse2"; fi - -fi - - -# Check whether --enable-ssse3 was given. -if test "${enable_ssse3+set}" = set; then : - enableval=$enable_ssse3; if test $enableval = yes; then SSE_FLAGS="$SSE_FLAGS -mssse3"; fi - -fi - - -# Define BUILD_HERA when building for HERA project to activate code in -# drvrfile.c (by way of fitsio2.h): -# Check whether --enable-hera was given. -if test "${enable_hera+set}" = set; then : - enableval=$enable_hera; if test $enableval = yes; then BUILD_HERA=yes; fi - -fi - -if test "x$BUILD_HERA" = xyes; then - $as_echo "#define BUILD_HERA 1" >>confdefs.h - -fi - - -# Check whether --with-gsiftp-flavour was given. -if test "${with_gsiftp_flavour+set}" = set; then : - withval=$with_gsiftp_flavour; if test "x$withval" != "xno"; then - if test "x$withval" != "xyes" ; then - GSIFTP_FLAVOUR=${withval} - fi - -$as_echo "#define GSIFTP_FLAVOUR 1" >>confdefs.h - - fi - - -fi - - - -# Check whether --with-gsiftp was given. -if test "${with_gsiftp+set}" = set; then : - withval=$with_gsiftp; if test "x$withval" != "xno"; then - if test "x$withval" != "xyes" ; then - GSIFTP_PATH=${withval} - HAVE_GSIFTP=yes - fi - -$as_echo "#define HAVE_GSIFTP 1" >>confdefs.h - - fi - - -fi - - -# Enable support for bzip2 compression (disabled by default): -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5; } - -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 -$as_echo_n "checking whether the C compiler works... " >&6; } -ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` - -# The possible output files: -ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" - -ac_rmfiles= -for ac_file in $ac_files -do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - * ) ac_rmfiles="$ac_rmfiles $ac_file";; - esac -done -rm -f $ac_rmfiles - -if { { ac_try="$ac_link_default" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link_default") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. -# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' -# in a Makefile. We should not override ac_cv_exeext if it was cached, -# so that the user can short-circuit this test for compilers unknown to -# Autoconf. -for ac_file in $ac_files '' -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; - then :; else - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - fi - # We set ac_cv_exeext here because the later test for it is not - # safe: cross compilers may not add the suffix if given an `-o' - # argument, so we may need to know it at that point already. - # Even if this section looks crufty: it has the advantage of - # actually working. - break;; - * ) - break;; - esac -done -test "$ac_cv_exeext" = no && ac_cv_exeext= - -else - ac_file='' -fi -if test -z "$ac_file"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -$as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "C compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 -$as_echo_n "checking for C compiler default output file name... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 -$as_echo "$ac_file" >&6; } -ac_exeext=$ac_cv_exeext - -rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 -$as_echo_n "checking for suffix of executables... " >&6; } -if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - break;; - * ) break;; - esac -done -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5; } -fi -rm -f conftest conftest$ac_cv_exeext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 -$as_echo "$ac_cv_exeext" >&6; } - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -FILE *f = fopen ("conftest.out", "w"); - return ferror (f) || fclose (f) != 0; - - ; - return 0; -} -_ACEOF -ac_clean_files="$ac_clean_files conftest.out" -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 -$as_echo_n "checking whether we are cross compiling... " >&6; } -if test "$cross_compiling" != yes; then - { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if { ac_try='./conftest$ac_cv_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5; } - fi - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 -$as_echo "$cross_compiling" >&6; } - -rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 -$as_echo_n "checking for suffix of object files... " >&6; } -if ${ac_cv_objext+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - for ac_file in conftest.o conftest.obj conftest.*; do - test -f "$ac_file" || continue; - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5; } -fi -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 -$as_echo "$ac_cv_objext" >&6; } -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -struct stat; -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_c89=$ac_arg -fi -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : - -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -$as_echo_n "checking how to run the C preprocessor... " >&6; } -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if ${ac_cv_prog_CPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -$as_echo "$CPP" >&6; } -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 -$as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if ${ac_cv_path_GREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$GREP"; then - ac_path_GREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_GREP" || continue -# Check for GNU ac_path_GREP and select it if it is found. - # Check for GNU $ac_path_GREP -case `"$ac_path_GREP" --version 2>&1` in -*GNU*) - ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'GREP' >> "conftest.nl" - "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_GREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_GREP="$ac_path_GREP" - ac_path_GREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_GREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_GREP"; then - as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_GREP=$GREP -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 -$as_echo "$ac_cv_path_GREP" >&6; } - GREP="$ac_cv_path_GREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -$as_echo_n "checking for egrep... " >&6; } -if ${ac_cv_path_EGREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - if test -z "$EGREP"; then - ac_path_EGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_EGREP" || continue -# Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_EGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_EGREP"; then - as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_EGREP=$EGREP -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -$as_echo "$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - - -# Check whether --with-bzip2 was given. -if test "${with_bzip2+set}" = set; then : - withval=$with_bzip2; if test "x$withval" != "xno"; then - if test "x$withval" = "xyes" ; then - for ac_header in bzlib.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default" -if test "x$ac_cv_header_bzlib_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_BZLIB_H 1 -_ACEOF - -$as_echo "#define HAVE_BZIP2 1" >>confdefs.h - - -fi - -done - - else - BZIP2_PATH=${withval} - fi - fi - - -fi - - -#-------------------------------------------------------------------- -# Check for install location prefix -#-------------------------------------------------------------------- - - - -# make will complain about duplicate targets for the install directories -# if prefix == exec_prefix -INSTALL_ROOT='${prefix}' - -test "$exec_prefix" != NONE -a "$prefix" != "$exec_prefix" \ - && INSTALL_ROOT="$INSTALL_ROOT "'${exec_prefix}' - - -#-------------------------------------------------------------------- -# System type -#-------------------------------------------------------------------- - -case $host in - *cygwin*) - ARCH="cygwin" - EXT="cygwin" - ;; - *apple-darwin*) - # Darwin can be powerpc, i386, or x86_64 - ARCH=`uname -p` - EXT="darwin" - ;; - *freebsd*) - ARCH="linux" - EXT="lnx" - ;; - *hpux*) - ARCH="hp" - EXT="hpu" - ;; - *irix*) - ARCH="sgi" - EXT="sgi" - ;; - *linux*) - ARCH="linux" - EXT="lnx" - ;; - *mingw32*) - #ARCH="" - EXT="mingw32" - ;; - *osf1*) - ARCH="alpha" - EXT="osf" - ;; - *solaris*) - ARCH="solaris" - EXT="sol" - ;; - *ultrix*) - ARCH="dec" - EXT="dec" - ;; - *) - echo "cfitsio: == Don't know what do do with $host" - ;; -esac - - - -# Try first to find a proprietary C compiler, then gcc -if test "x$EXT" != xcygwin && test "x$EXT" != xdarwin && test "x$EXT" != xlnx && test "x$EXT" != xmingw32; then - if test "x$CC" = x; then - for ac_prog in cc -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break -done - - fi -fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5; } - -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -struct stat; -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_c89=$ac_arg -fi -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : - -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -LDFLAGS="$CFLAGS" -LDFLAGS_BIN="$LDFLAGS" - -if test "x$FC" = "xnone" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: cfitsio: == Fortran compiler search has been overridden" >&5 -$as_echo "$as_me: cfitsio: == Fortran compiler search has been overridden" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: cfitsio: == Cfitsio will be built without Fortran wrapper support" >&5 -$as_echo "$as_me: cfitsio: == Cfitsio will be built without Fortran wrapper support" >&6;} - FC= - F77_WRAPPERS= -else - for ac_prog in gfortran g95 g77 f77 ifort f95 f90 xlf cf77 gf77 af77 ncf f2c -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_FC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$FC"; then - ac_cv_prog_FC="$FC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_FC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -FC=$ac_cv_prog_FC -if test -n "$FC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FC" >&5 -$as_echo "$FC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$FC" && break -done -test -n "$FC" || FC="notfound" - - if test $FC = 'notfound' ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cfitsio: == No acceptable Fortran compiler found in \$PATH" >&5 -$as_echo "$as_me: WARNING: cfitsio: == No acceptable Fortran compiler found in \$PATH" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: cfitsio: == Adding wrapper support for GNU Fortran by default" >&5 -$as_echo "$as_me: cfitsio: == Adding wrapper support for GNU Fortran by default" >&6;} - CFORTRANFLAGS="-Dg77Fortran" - F77_WRAPPERS="\${FITSIO_SRC}" - else - CFORTRANFLAGS= - F77_WRAPPERS="\${FITSIO_SRC}" - echo $ac_n "checking whether we are using GNU Fortran""... $ac_c" 1>&6 - if test `$FC --version -c < /dev/null 2> /dev/null | grep -c GNU` -gt 0 -o \ - `$FC --version -c < /dev/null 2> /dev/null | grep -ic egcs` -gt 0 - then - echo "$ac_t""yes" 1>&6 - echo $ac_n "cfitsio: == Adding wrapper support for GNU Fortran""... $ac_c" 1>&6 - CFORTRANFLAGS="-Dg77Fortran" - echo "$ac_t"" done" 1>&6 - else - echo "$ac_t""no" 1>&6 - if test $FC = 'f2c' ; then - echo $ac_n "cfitsio: == Adding wrapper support for f2c""... $ac_c" 1>&6 - CFORTRANFLAGS="-Df2cFortran" - echo "$ac_t"" done" 1>&6 - fi - fi - fi -fi - -# ar & ranlib required -#--------------------- -# Extract the first word of "ar", so it can be a program name with args. -set dummy ar; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AR"; then - ac_cv_prog_AR="$AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AR="ar" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="noar" -fi -fi -AR=$ac_cv_prog_AR -if test -n "$AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -$as_echo "$AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -if test $AR = noar; then - as_fn_error $? "ar not found in your \$PATH. See your sysdamin." "$LINENO" 5 -fi -ARCHIVE="$AR rv" - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. -set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_RANLIB+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -RANLIB=$ac_cv_prog_RANLIB -if test -n "$RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 -$as_echo "$RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_RANLIB"; then - ac_ct_RANLIB=$RANLIB - # Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_RANLIB"; then - ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_RANLIB="ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB -if test -n "$ac_ct_RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 -$as_echo "$ac_ct_RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_RANLIB" = x; then - RANLIB=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - RANLIB=$ac_ct_RANLIB - fi -else - RANLIB="$ac_cv_prog_RANLIB" -fi - - -for ac_header in stdlib.h string.h math.h limits.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - ANSI_HEADER=yes -else - ANSI_HEADER=no -fi - -done - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -void d( int , double) - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - PROTO=yes -else - PROTO=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -if test $ANSI_HEADER = no -o $PROTO = no; then - echo " *********** WARNING: CFITSIO CONFIGURE FAILURE ************ " - echo "cfitsio: ANSI C environment NOT found. Aborting cfitsio configure." - if test $ANSI_HEADER = no; then - echo "cfitsio: You're missing a needed ANSI header file." - fi - if test $PROTO = no; then - echo "cfitsio: Your compiler can't do ANSI function prototypes." - fi - echo "cfitsio: You need an ANSI C compiler and all ANSI trappings" - echo "cfitsio: to build cfitsio. " - echo " ******************************************************* " - exit 0; -fi - -if test "x$SSE_FLAGS" != x; then - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $SSE_FLAGS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts $SSE_FLAGS" >&5 -$as_echo_n "checking whether $CC accepts $SSE_FLAGS... " >&6; } - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - c_has_option=yes -else - c_has_option=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_has_option" >&5 -$as_echo "$c_has_option" >&6; } - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - if test "$c_has_option" = no; then SSE_FLAGS=""; fi - CFLAGS="$SAVE_CFLAGS" -fi - - -CFLAGS="$CFLAGS" -LIBPRE="" - -case $host in - *cygwin*) - CFLAGS="$CFLAGS -DHAVE_POSIX_SIGNALS" - ;; - *apple-darwin*) - # Build for i386 & x86_64 architectures on Darwin 10.x or newer: - - case $host in - *darwin[56789]*) - ;; - *) - - echo "int main(){return(0);}" > /tmp/$$.c - $CC -v -o /tmp/$$.out /tmp/$$.c 2> /tmp/$$.log - if test `cat /tmp/$$.log | grep -ci 'LLVM'` -ne 0; then APPLEXCODE="yes"; fi - if test "x$APPLEXCODE" = xyes; then - # Apple XCode LLVM: - # Flags for building Universal binaries: - C_UNIV_SWITCH="-arch i386 -arch x86_64" - CFLAGS="$CFLAGS $C_UNIV_SWITCH" - # Set LDFLAGS used by utilities: - LDFLAGS_BIN="$LDFLAGS_BIN -rpath \${CFITSIO_LIB}" - else - # Non-Xcode GCC: - # Set LDFLAGS used by utilities: - LDFLAGS_BIN="$LDFLAGS_BIN -Wl,-rpath,\${CFITSIO_LIB}" - fi - ;; - esac - # For large file support (but may break Absoft compilers): - $as_echo "#define _LARGEFILE_SOURCE 1" >>confdefs.h - - $as_echo "#define _FILE_OFFSET_BITS 64" >>confdefs.h - - ;; - *hpux*) - if test "x$CFORTRANFLAGS" = x ; then - CFORTRANFLAGS="-Dappendus" - fi - CFLAGS="$CFLAGS -DPG_PPU" - LIBPRE="-Wl," - ;; - *irix*) - CFLAGS="$CFLAGS -DHAVE_POSIX_SIGNALS" - RANLIB="touch" - ;; - *linux*) - # For large file support: - $as_echo "#define _LARGEFILE_SOURCE 1" >>confdefs.h - - $as_echo "#define _FILE_OFFSET_BITS 64" >>confdefs.h - - ;; - *mingw32*) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for large file support" >&5 -$as_echo_n "checking for large file support... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -_FILE_OFFSET_BITS_SET_FSEEKO - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - - $as_echo "#define _LARGEFILE_SOURCE 1" >>confdefs.h - - $as_echo "#define _FILE_OFFSET_BITS 64" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ;; - *solaris*) - if test "x$CFORTRANFLAGS" = x ; then - CFORTRANFLAGS="-Dsolaris" - fi - # We need libm on Solaris: - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for frexp in -lm" >&5 -$as_echo_n "checking for frexp in -lm... " >&6; } -if ${ac_cv_lib_m_frexp+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lm $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char frexp (); -int -main () -{ -return frexp (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_m_frexp=yes -else - ac_cv_lib_m_frexp=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_frexp" >&5 -$as_echo "$ac_cv_lib_m_frexp" >&6; } -if test "x$ac_cv_lib_m_frexp" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBM 1 -_ACEOF - - LIBS="-lm $LIBS" - -fi - - # For large file support: - $as_echo "#define _LARGEFILE_SOURCE 1" >>confdefs.h - - $as_echo "#define _FILE_OFFSET_BITS 64" >>confdefs.h - - ;; - *) - echo "cfitsio: == Don't know what do do with $host" - ;; -esac - -CFLAGS="$CFLAGS $CFORTRANFLAGS" - -case $GCC in - yes) - GCCVERSION="`$CC -dumpversion 2>&1`" - echo "cfitsio: == Using gcc version $GCCVERSION" - - - gcc_test=`echo $GCCVERSION | grep -c '2\.[45678]'` - - if test $gcc_test -gt 0 - then - - CFLAGS=`echo $CFLAGS | sed 's:-O[^ ]* *::'` - - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: This gcc is pretty old. Disabling optimization to be safe." >&5 -$as_echo "$as_me: WARNING: This gcc is pretty old. Disabling optimization to be safe." >&2;} - fi - ;; - no) - echo "cfitsio: Old CFLAGS is $CFLAGS" - CFLAGS=`echo $CFLAGS | sed -e "s/-g/-O/"` - case $host in - *solaris*) - - if test `echo $CFLAGS | grep -c fast` -gt 0 - then - echo "cfitsio: Replacing -fast with -O3" - CFLAGS=`echo $CFLAGS | sed 's:-fast:-O3:'` - fi - - CFLAGS="$CFLAGS -DHAVE_ALLOCA_H -DHAVE_POSIX_SIGNALS" - ;; - *) - echo "== No special changes for $host" - ;; - esac - echo "New CFLAGS is $CFLAGS" - ;; - *) - # Don't do anything now - ;; -esac - -# GSIFTP flags: -if test "x$GSIFTP_PATH" != x -a "x$GSIFTP_FLAVOUR" != x; then - CFLAGS="$CFLAGS -I${GSIFTP_PATH}/include/${GSIFTP_FLAVOUR}" - LDFLAGS="$LDFLAGS -L${GSIFTP_PATH}/lib -lglobus_ftp_client_${GSIFTP_FLAVOUR}" -fi - -# BZIP2 flags: -if test "x$BZIP2_PATH" != x; then - CFLAGS="$CFLAGS -I${BZIP2_PATH}/include" - LDFLAGS="$LDFLAGS -L${BZIP2_PATH}/lib -lbz2" -fi - -# Shared library section -#------------------------------------------------------------------------------- -SHLIB_LD=: -SHLIB_SUFFIX=".so" -CFITSIO_SHLIB="" -CFITSIO_SHLIB_SONAME="" -lhea_shlib_cflags= -case $EXT in - cygwin|mingw32) - SHLIB_LD="$CC -shared" - SHLIB_SUFFIX=".dll" - ;; - darwin) - - SHLIB_SUFFIX=".dylib" - CFITSIO_SHLIB="lib\${PACKAGE}.\${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}\${SHLIB_SUFFIX}" - CFITSIO_SHLIB_SONAME="lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX}" - case $host in - *darwin[56789]*) - SHLIB_LD="$CC -dynamiclib -install_name lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX} -compatibility_version \${CFITSIO_SONAME} -current_version \${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}" - ;; - *) - # Build 'Universal' binaries (i386 & x86_64 architectures) and - # use rpath token on Darwin 10.x or newer: - SHLIB_LD="$CC -dynamiclib $C_UNIV_SWITCH -headerpad_max_install_names -install_name @rpath/lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX} -compatibility_version \${CFITSIO_SONAME} -current_version \${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}" - ;; - esac - - lhea_shlib_cflags="-fPIC -fno-common" - ;; - hpu) - SHLIB_LD="ld -b" - SHLIB_SUFFIX=".sl" - ;; - lnx) - SHLIB_LD=":" - CFITSIO_SHLIB="lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}" - CFITSIO_SHLIB_SONAME="lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}" - ;; - osf) - SHLIB_LD="ld -shared -expect_unresolved '*'" - LD_FLAGS="-taso" - ;; - sol) - SHLIB_LD="/usr/ccs/bin/ld -G" - lhea_shlib_cflags="-KPIC" - ;; - sgi) - SHLIB_LD="ld -shared -rdata_shared" - ;; - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to determine how to make a shared library" >&5 -$as_echo "$as_me: WARNING: Unable to determine how to make a shared library" >&2;} - ;; -esac -# Darwin uses gcc (=cc), but needs different flags (see above) -if test "x$EXT" != xdarwin && test "x$EXT" != xcygwin && test "x$EXT" != xmingw32; then - if test "x$GCC" = xyes; then - SHLIB_LD="$CC -shared -Wl,-soname,lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}" - lhea_shlib_cflags='-fPIC' - fi -fi -if test "x$lhea_shlib_cflags" != x; then - CFLAGS="$CFLAGS $lhea_shlib_cflags" -fi -# Set shared library name for cases in which we aren't setting a 'soname': -if test "x$CFITSIO_SHLIB" = x; then CFITSIO_SHLIB="lib\${PACKAGE}\${SHLIB_SUFFIX}"; fi - - - - -# ================= test for the unix ftruncate function ================ - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking \"whether ftruncate works\"" >&5 -$as_echo_n "checking \"whether ftruncate works\"... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -int -main () -{ - -ftruncate(0, 0); - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - -$as_echo "#define HAVE_FTRUNCATE 1" >>confdefs.h - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: \"yes\"" >&5 -$as_echo "\"yes\"" >&6; } - -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"no\"" >&5 -$as_echo "\"no\"" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - -# --------------------------------------------------------- -# some systems define long long for 64-bit ints -# --------------------------------------------------------- - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking \"whether long long is defined\"" >&5 -$as_echo_n "checking \"whether long long is defined\"... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -int -main () -{ - -long long filler; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -$as_echo "#define HAVE_LONGLONG 1" >>confdefs.h - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: \"yes\"" >&5 -$as_echo "\"yes\"" >&6; } - -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"no\"" >&5 -$as_echo "\"no\"" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -# ==================== SHARED MEMORY DRIVER SECTION ======================= -# -# 09-Mar-98 : modified by JB/ISDC -# 3 checks added to support autoconfiguration of shared memory -# driver. First generic check is made whether shared memory is supported -# at all, then 2 more specific checks are made (architecture dependent). -# Currently tested on : sparc-solaris, intel-linux, sgi-irix, dec-alpha-osf - -# ------------------------------------------------------------------------- -# check is System V IPC is supported on this machine -# ------------------------------------------------------------------------- - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking \"whether system V style IPC services are supported\"" >&5 -$as_echo_n "checking \"whether system V style IPC services are supported\"... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include - -int -main () -{ - -shmat(0, 0, 0); -shmdt(0); -shmget(0, 0, 0); -semget(0, 0, 0); - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - -$as_echo "#define HAVE_SHMEM_SERVICES 1" >>confdefs.h - -my_shmem=\${SOURCES_SHMEM} -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: \"yes\"" >&5 -$as_echo "\"yes\"" >&6; } - -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"no\"" >&5 -$as_echo "\"no\"" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - - - -# ------------------------------------------------------------------------- -# some systems define flock_t, for others we have to define it ourselves -# ------------------------------------------------------------------------- - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking \"do we have flock_t defined in sys/fcntl.h\"" >&5 -$as_echo_n "checking \"do we have flock_t defined in sys/fcntl.h\"... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -int -main () -{ - -flock_t filler; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -$as_echo "#define HAVE_FLOCK_T 1" >>confdefs.h - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: \"yes\"" >&5 -$as_echo "\"yes\"" >&6; } - -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"no\"" >&5 -$as_echo "\"no\"" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test "$HAVE_FLOCK_T" != 1; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking \"do we have flock_t defined in sys/flock.h\"" >&5 -$as_echo_n "checking \"do we have flock_t defined in sys/flock.h\"... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -int -main () -{ - - flock_t filler; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - - $as_echo "#define HAVE_FLOCK_T 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"yes\"" >&5 -$as_echo "\"yes\"" >&6; } - -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"no\"" >&5 -$as_echo "\"no\"" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -# ------------------------------------------------------------------------- -# there are some idiosyncrasies with semun defs (used in semxxx). Solaris -# does not define it at all -# ------------------------------------------------------------------------- - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking \"do we have union semun defined\"" >&5 -$as_echo_n "checking \"do we have union semun defined\"... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include - -int -main () -{ - -union semun filler; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -$as_echo "#define HAVE_UNION_SEMUN 1" >>confdefs.h - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: \"yes\"" >&5 -$as_echo "\"yes\"" >&6; } - -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"no\"" >&5 -$as_echo "\"no\"" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -# ==================== END OF SHARED MEMORY DRIVER SECTION ================ -# ================= test for the unix networking functions ================ - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 -$as_echo_n "checking for library containing gethostbyname... " >&6; } -if ${ac_cv_search_gethostbyname+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char gethostbyname (); -int -main () -{ -return gethostbyname (); - ; - return 0; -} -_ACEOF -for ac_lib in '' nsl; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_gethostbyname=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_gethostbyname+:} false; then : - break -fi -done -if ${ac_cv_search_gethostbyname+:} false; then : - -else - ac_cv_search_gethostbyname=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 -$as_echo "$ac_cv_search_gethostbyname" >&6; } -ac_res=$ac_cv_search_gethostbyname -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - cfitsio_have_nsl=1 -else - cfitsio_have_nsl=0 -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing connect" >&5 -$as_echo_n "checking for library containing connect... " >&6; } -if ${ac_cv_search_connect+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char connect (); -int -main () -{ -return connect (); - ; - return 0; -} -_ACEOF -for ac_lib in '' socket; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib -lnsl $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_connect=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_connect+:} false; then : - break -fi -done -if ${ac_cv_search_connect+:} false; then : - -else - ac_cv_search_connect=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_connect" >&5 -$as_echo "$ac_cv_search_connect" >&6; } -ac_res=$ac_cv_search_connect -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - cfitsio_have_socket=1 -else - cfitsio_have_socket=0 -fi - - -if test "$cfitsio_have_nsl" = 1 -a "$cfitsio_have_socket" = 1; then - $as_echo "#define HAVE_NET_SERVICES 1" >>confdefs.h - -fi - -# ==================== END OF unix networking SECTION ================ - -# ------------------------------------------------------------------------------ -# Define _REENTRANT & add -lpthread to LIBS if reentrant multithreading enabled: -# ------------------------------------------------------------------------------ -if test "x$BUILD_REENTRANT" = xyes; then - $as_echo "#define _REENTRANT 1" >>confdefs.h - - $as_echo "#define _XOPEN_SOURCE 700" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 -$as_echo_n "checking for main in -lpthread... " >&6; } -if ${ac_cv_lib_pthread_main+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpthread $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -int -main () -{ -return main (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_pthread_main=yes -else - ac_cv_lib_pthread_main=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5 -$as_echo "$ac_cv_lib_pthread_main" >&6; } -if test "x$ac_cv_lib_pthread_main" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBPTHREAD 1 -_ACEOF - - LIBS="-lpthread $LIBS" - -else - as_fn_error $? "Unable to locate pthread library needed when enabling reentrant multithreading" "$LINENO" 5 -fi - -fi -# ------------------------------------------------------------------------------ - -ac_config_files="$ac_config_files Makefile" - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes: double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \. - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - if test "x$cache_file" != "x/dev/null"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} - if test ! -f "$cache_file" || test -h "$cache_file"; then - cat confcache >"$cache_file" - else - case $cache_file in #( - */* | ?:*) - mv -f confcache "$cache_file"$$ && - mv -f "$cache_file"$$ "$cache_file" ;; #( - *) - mv -f confcache "$cache_file" ;; - esac - fi - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -:mline -/\\$/{ - N - s,\\\n,, - b mline -} -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\[/\\&/g -s/\]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - - -ac_libobjs= -ac_ltlibobjs= -U= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" - as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - - -: "${CONFIG_STATUS=./config.status}" -ac_write_fail=0 -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} -as_write_fail=0 -cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -_ASEOF -test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by $as_me, which was -generated by GNU Autoconf 2.69. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -case $ac_config_files in *" -"*) set x $ac_config_files; shift; ac_config_files=$*;; -esac - - - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# Files that config.status was made for. -config_files="$ac_config_files" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Report bugs to the package provider." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" -ac_cs_version="\\ -config.status -configured by $0, generated by GNU Autoconf 2.69, - with options \\"\$ac_cs_config\\" - -Copyright (C) 2012 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -test -n "\$AWK" || AWK=awk -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=?*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" - ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -if \$ac_cs_recheck; then - set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion - shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 - CONFIG_SHELL='$SHELL' - export CONFIG_SHELL - exec "\$@" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - $as_echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= ac_tmp= - trap 'exit_status=$? - : "${ac_tmp:=$tmp}" - { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status -' 0 - trap 'as_fn_exit 1' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 -ac_tmp=$tmp - -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. -if test -n "$CONFIG_FILES"; then - - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$ac_tmp/subs1.awk" && -_ACEOF - - -{ - echo "cat >conf$$subs.awk <<_ACEOF" && - echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && - echo "_ACEOF" -} >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - - ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` - if test $ac_delim_n = $ac_delim_num; then - break - elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done -rm -f conf$$subs.sh - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && -_ACEOF -sed -n ' -h -s/^/S["/; s/!.*/"]=/ -p -g -s/^[^!]*!// -:repl -t repl -s/'"$ac_delim"'$// -t delim -:nl -h -s/\(.\{148\}\)..*/\1/ -t more1 -s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ -p -n -b repl -:more1 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t nl -:delim -h -s/\(.\{148\}\)..*/\1/ -t more2 -s/["\\]/\\&/g; s/^/"/; s/$/"/ -p -b -:more2 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t delim -' >$CONFIG_STATUS || ac_write_fail=1 -rm -f conf$$subs.awk -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACAWK -cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" - -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 -_ACEOF - -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// -s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -fi # test -n "$CONFIG_FILES" - - -eval set X " :F $CONFIG_FILES " -shift -for ac_tag -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$ac_tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; - esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac - - case $ac_tag in - *:-:* | *:-) cat >"$ac_tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_sed_extra="$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -$ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ - >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ - "$ac_tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} - - rm -f "$ac_tmp/stdin" - case $ac_file in - -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; - *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; - esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - ;; - - - - esac - -done # for ac_tag - - -as_fn_exit 0 -_ACEOF -ac_clean_files=$ac_clean_files_save - -test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 -fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} -fi - -ac_config_files="$ac_config_files cfitsio.pc" - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes: double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \. - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - if test "x$cache_file" != "x/dev/null"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} - if test ! -f "$cache_file" || test -h "$cache_file"; then - cat confcache >"$cache_file" - else - case $cache_file in #( - */* | ?:*) - mv -f confcache "$cache_file"$$ && - mv -f "$cache_file"$$ "$cache_file" ;; #( - *) - mv -f confcache "$cache_file" ;; - esac - fi - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -:mline -/\\$/{ - N - s,\\\n,, - b mline -} -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\[/\\&/g -s/\]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - - -ac_libobjs= -ac_ltlibobjs= -U= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" - as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - - -: "${CONFIG_STATUS=./config.status}" -ac_write_fail=0 -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} -as_write_fail=0 -cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -_ASEOF -test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by $as_me, which was -generated by GNU Autoconf 2.69. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -case $ac_config_files in *" -"*) set x $ac_config_files; shift; ac_config_files=$*;; -esac - - - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# Files that config.status was made for. -config_files="$ac_config_files" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Report bugs to the package provider." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" -ac_cs_version="\\ -config.status -configured by $0, generated by GNU Autoconf 2.69, - with options \\"\$ac_cs_config\\" - -Copyright (C) 2012 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -test -n "\$AWK" || AWK=awk -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=?*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" - ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -if \$ac_cs_recheck; then - set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion - shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 - CONFIG_SHELL='$SHELL' - export CONFIG_SHELL - exec "\$@" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - $as_echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "cfitsio.pc") CONFIG_FILES="$CONFIG_FILES cfitsio.pc" ;; - - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= ac_tmp= - trap 'exit_status=$? - : "${ac_tmp:=$tmp}" - { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status -' 0 - trap 'as_fn_exit 1' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 -ac_tmp=$tmp - -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. -if test -n "$CONFIG_FILES"; then - - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$ac_tmp/subs1.awk" && -_ACEOF - - -{ - echo "cat >conf$$subs.awk <<_ACEOF" && - echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && - echo "_ACEOF" -} >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - - ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` - if test $ac_delim_n = $ac_delim_num; then - break - elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done -rm -f conf$$subs.sh - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && -_ACEOF -sed -n ' -h -s/^/S["/; s/!.*/"]=/ -p -g -s/^[^!]*!// -:repl -t repl -s/'"$ac_delim"'$// -t delim -:nl -h -s/\(.\{148\}\)..*/\1/ -t more1 -s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ -p -n -b repl -:more1 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t nl -:delim -h -s/\(.\{148\}\)..*/\1/ -t more2 -s/["\\]/\\&/g; s/^/"/; s/$/"/ -p -b -:more2 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t delim -' >$CONFIG_STATUS || ac_write_fail=1 -rm -f conf$$subs.awk -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACAWK -cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" - -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 -_ACEOF - -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// -s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -fi # test -n "$CONFIG_FILES" - - -eval set X " :F $CONFIG_FILES " -shift -for ac_tag -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$ac_tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; - esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac - - case $ac_tag in - *:-:* | *:-) cat >"$ac_tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_sed_extra="$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -$ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ - >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ - "$ac_tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} - - rm -f "$ac_tmp/stdin" - case $ac_file in - -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; - *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; - esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - ;; - - - - esac - -done # for ac_tag - - -as_fn_exit 0 -_ACEOF -ac_clean_files=$ac_clean_files_save - -test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 -fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} -fi - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 -$as_echo "" >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Congratulations, Makefile update was successful." >&5 -$as_echo " Congratulations, Makefile update was successful." >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: You may want to run \"make\" now." >&5 -$as_echo " You may want to run \"make\" now." >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 -$as_echo "" >&6; } - diff --git a/src/external/OpenGR/3rdparty/cfitsio/configure.in b/src/external/OpenGR/3rdparty/cfitsio/configure.in deleted file mode 100644 index 84ff5c778..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/configure.in +++ /dev/null @@ -1,590 +0,0 @@ -# -# configure.in for cfitsio -# -# /redshift/sgi6/lheavc/ftools/cfitsio/configure.in,v 3.4 1996/07/26 20:27:53 pence Exp -# -# copied from host and modified -# - -dnl Process this file with autoconf to produce a configure script. -AC_INIT -AC_CONFIG_SRCDIR([fitscore.c]) -AC_CANONICAL_TARGET([]) - -#-------------------------------------------------------------------- -# CFITSIO Version Numbers: -#-------------------------------------------------------------------- -AC_SUBST(CFITSIO_MAJOR,3) -AC_SUBST(CFITSIO_MINOR,41) -# Increment soname each time the interface changes: -AC_SUBST(CFITSIO_SONAME,5) - -#-------------------------------------------------------------------- -# Command options -#-------------------------------------------------------------------- - -AC_ARG_ENABLE( - reentrant, - [AS_HELP_STRING([--enable-reentrant],[Enable reentrant multithreading])], - [ if test $enableval = yes; then BUILD_REENTRANT=yes; fi ] -) - -SSE_FLAGS="" -AC_ARG_ENABLE( - sse2, - [AS_HELP_STRING([--enable-sse2],[Enable use of instructions in the SSE2 extended instruction set])], - [ if test $enableval = yes; then SSE_FLAGS="-msse2"; fi ] -) - -AC_ARG_ENABLE( - ssse3, - [AS_HELP_STRING([--enable-ssse3],[Enable use of instructions in the SSSE3 extended instruction set])], - [ if test $enableval = yes; then SSE_FLAGS="$SSE_FLAGS -mssse3"; fi ] -) - -# Define BUILD_HERA when building for HERA project to activate code in -# drvrfile.c (by way of fitsio2.h): -AC_ARG_ENABLE( - hera, - [AS_HELP_STRING([--enable-hera],[Build for HERA (ASD use only)])], - [ if test $enableval = yes; then BUILD_HERA=yes; fi ] -) -if test "x$BUILD_HERA" = xyes; then - AC_DEFINE(BUILD_HERA) -fi - -AC_ARG_WITH( - gsiftp-flavour, - [AS_HELP_STRING([--with-gsiftp-flavour[[=PATH]]],[Enable Globus Toolkit gsiftp protocol support])], - [ if test "x$withval" != "xno"; then - if test "x$withval" != "xyes" ; then - GSIFTP_FLAVOUR=${withval} - fi - AC_DEFINE(GSIFTP_FLAVOUR,1,[Define Globus Toolkit architecture]) - fi - ] -) - -AC_ARG_WITH( - gsiftp, - [AS_HELP_STRING([--with-gsiftp[[=PATH]]],[Enable Globus Toolkit gsiftp protocol support])], - [ if test "x$withval" != "xno"; then - if test "x$withval" != "xyes" ; then - GSIFTP_PATH=${withval} - HAVE_GSIFTP=yes - fi - AC_DEFINE(HAVE_GSIFTP,1,[Define if you want Globus Toolkit gsiftp protocol support]) - fi - ] -) - -# Enable support for bzip2 compression (disabled by default): -AC_ARG_WITH( - bzip2, - [AS_HELP_STRING([--with-bzip2[[=PATH]]],[Enable bzip2 support. Optional path to the location of include/bzlib.h and lib/libbz2])], - [ if test "x$withval" != "xno"; then - if test "x$withval" = "xyes" ; then - AC_CHECK_HEADERS(bzlib.h, - [AC_DEFINE(HAVE_BZIP2,1,[Define if you want bzip2 read support])] - ) - else - BZIP2_PATH=${withval} - fi - fi - ] -) - -#-------------------------------------------------------------------- -# Check for install location prefix -#-------------------------------------------------------------------- - -AC_PREFIX_DEFAULT(`pwd`) - -# make will complain about duplicate targets for the install directories -# if prefix == exec_prefix -AC_SUBST(INSTALL_ROOT,'${prefix}') -test "$exec_prefix" != NONE -a "$prefix" != "$exec_prefix" \ - && INSTALL_ROOT="$INSTALL_ROOT "'${exec_prefix}' - - -#-------------------------------------------------------------------- -# System type -#-------------------------------------------------------------------- - -case $host in - *cygwin*) - ARCH="cygwin" - EXT="cygwin" - ;; - *apple-darwin*) - # Darwin can be powerpc, i386, or x86_64 - ARCH=`uname -p` - EXT="darwin" - ;; - *freebsd*) - ARCH="linux" - EXT="lnx" - ;; - *hpux*) - ARCH="hp" - EXT="hpu" - ;; - *irix*) - ARCH="sgi" - EXT="sgi" - ;; - *linux*) - ARCH="linux" - EXT="lnx" - ;; - *mingw32*) - #ARCH="" - EXT="mingw32" - ;; - *osf1*) - ARCH="alpha" - EXT="osf" - ;; - *solaris*) - ARCH="solaris" - EXT="sol" - ;; - *ultrix*) - ARCH="dec" - EXT="dec" - ;; - *) - echo "cfitsio: == Don't know what do do with $host" - ;; -esac - - -dnl Checks for programs. - -# Try first to find a proprietary C compiler, then gcc -if test "x$EXT" != xcygwin && test "x$EXT" != xdarwin && test "x$EXT" != xlnx && test "x$EXT" != xmingw32; then - if test "x$CC" = x; then - AC_CHECK_PROGS(CC, cc) - fi -fi -AC_PROG_CC -LDFLAGS="$CFLAGS" -LDFLAGS_BIN="$LDFLAGS" - -if test "x$FC" = "xnone" ; then - AC_MSG_NOTICE(cfitsio: == Fortran compiler search has been overridden) - AC_MSG_NOTICE(cfitsio: == Cfitsio will be built without Fortran wrapper support) - FC= - F77_WRAPPERS= -else - AC_CHECK_PROGS(FC, gfortran g95 g77 f77 ifort f95 f90 xlf cf77 gf77 af77 ncf f2c, notfound) - if test $FC = 'notfound' ; then - AC_MSG_WARN(cfitsio: == No acceptable Fortran compiler found in \$PATH) - AC_MSG_NOTICE(cfitsio: == Adding wrapper support for GNU Fortran by default) - CFORTRANFLAGS="-Dg77Fortran" - F77_WRAPPERS="\${FITSIO_SRC}" - else - CFORTRANFLAGS= - F77_WRAPPERS="\${FITSIO_SRC}" - echo $ac_n "checking whether we are using GNU Fortran""... $ac_c" 1>&6 - if test `$FC --version -c < /dev/null 2> /dev/null | grep -c GNU` -gt 0 -o \ - `$FC --version -c < /dev/null 2> /dev/null | grep -ic egcs` -gt 0 - then - echo "$ac_t""yes" 1>&6 - echo $ac_n "cfitsio: == Adding wrapper support for GNU Fortran""... $ac_c" 1>&6 - CFORTRANFLAGS="-Dg77Fortran" - echo "$ac_t"" done" 1>&6 - else - echo "$ac_t""no" 1>&6 - if test $FC = 'f2c' ; then - echo $ac_n "cfitsio: == Adding wrapper support for f2c""... $ac_c" 1>&6 - CFORTRANFLAGS="-Df2cFortran" - echo "$ac_t"" done" 1>&6 - fi - fi - fi -fi - -# ar & ranlib required -#--------------------- -AC_CHECK_PROG(AR, ar, ar, noar) -if test $AR = noar; then - AC_MSG_ERROR(ar not found in your \$PATH. See your sysdamin.) -fi -ARCHIVE="$AR rv" -AC_SUBST(ARCHIVE) - -AC_PROG_RANLIB - -dnl Checks for ANSI stdlib.h. -AC_CHECK_HEADERS(stdlib.h string.h math.h limits.h ,ANSI_HEADER=yes,ANSI_HEADER=no)dnl - -dnl Check if prototyping is allowed. -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[void d( int , double) ]])],[PROTO=yes],[PROTO=no])dnl - -if test $ANSI_HEADER = no -o $PROTO = no; then - echo " *********** WARNING: CFITSIO CONFIGURE FAILURE ************ " - echo "cfitsio: ANSI C environment NOT found. Aborting cfitsio configure." - if test $ANSI_HEADER = no; then - echo "cfitsio: You're missing a needed ANSI header file." - fi - if test $PROTO = no; then - echo "cfitsio: Your compiler can't do ANSI function prototypes." - fi - echo "cfitsio: You need an ANSI C compiler and all ANSI trappings" - echo "cfitsio: to build cfitsio. " - echo " ******************************************************* " - exit 0; -fi - -dnl Check if C compiler supports sse extended instruction flags. -if test "x$SSE_FLAGS" != x; then - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $SSE_FLAGS" - AC_MSG_CHECKING([whether $CC accepts $SSE_FLAGS]) - AC_LANG_PUSH([C]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],[c_has_option=yes],[c_has_option=no]) - AC_MSG_RESULT($c_has_option) - AC_LANG_POP([]) - if test "$c_has_option" = no; then SSE_FLAGS=""; fi - CFLAGS="$SAVE_CFLAGS" -fi -AC_SUBST(SSE_FLAGS) - -CFLAGS="$CFLAGS" -LIBPRE="" - -case $host in - *cygwin*) - CFLAGS="$CFLAGS -DHAVE_POSIX_SIGNALS" - ;; - *apple-darwin*) - # Build for i386 & x86_64 architectures on Darwin 10.x or newer: - changequote(,) - case $host in - *darwin[56789]*) - ;; - *) - changequote([,]) - echo "int main(){return(0);}" > /tmp/$$.c - $CC -v -o /tmp/$$.out /tmp/$$.c 2> /tmp/$$.log - if test `cat /tmp/$$.log | grep -ci 'LLVM'` -ne 0; then APPLEXCODE="yes"; fi - if test "x$APPLEXCODE" = xyes; then - # Apple XCode LLVM: - # Flags for building Universal binaries: - C_UNIV_SWITCH="-arch i386 -arch x86_64" - CFLAGS="$CFLAGS $C_UNIV_SWITCH" - # Set LDFLAGS used by utilities: - LDFLAGS_BIN="$LDFLAGS_BIN -rpath \${CFITSIO_LIB}" - else - # Non-Xcode GCC: - # Set LDFLAGS used by utilities: - LDFLAGS_BIN="$LDFLAGS_BIN -Wl,-rpath,\${CFITSIO_LIB}" - fi - ;; - esac - # For large file support (but may break Absoft compilers): - AC_DEFINE(_LARGEFILE_SOURCE) - AC_DEFINE(_FILE_OFFSET_BITS,64) - ;; - *hpux*) - if test "x$CFORTRANFLAGS" = x ; then - CFORTRANFLAGS="-Dappendus" - fi - CFLAGS="$CFLAGS -DPG_PPU" - LIBPRE="-Wl," - ;; - *irix*) - CFLAGS="$CFLAGS -DHAVE_POSIX_SIGNALS" - RANLIB="touch" - ;; - *linux*) - # For large file support: - AC_DEFINE(_LARGEFILE_SOURCE) - AC_DEFINE(_FILE_OFFSET_BITS,64) - ;; - *mingw32*) - AC_MSG_CHECKING([for large file support]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], - [_FILE_OFFSET_BITS_SET_FSEEKO])],[ - AC_DEFINE(_LARGEFILE_SOURCE) - AC_DEFINE(_FILE_OFFSET_BITS,64) - AC_MSG_RESULT(yes) - ],[AC_MSG_RESULT(no)]) - ;; - *solaris*) - if test "x$CFORTRANFLAGS" = x ; then - CFORTRANFLAGS="-Dsolaris" - fi - # We need libm on Solaris: - AC_CHECK_LIB(m, frexp) - # For large file support: - AC_DEFINE(_LARGEFILE_SOURCE) - AC_DEFINE(_FILE_OFFSET_BITS,64) - ;; - *) - echo "cfitsio: == Don't know what do do with $host" - ;; -esac - -CFLAGS="$CFLAGS $CFORTRANFLAGS" - -case $GCC in - yes) - GCCVERSION="`$CC -dumpversion 2>&1`" - echo "cfitsio: == Using gcc version $GCCVERSION" - AC_SUBST(GCCVERSION) - changequote(,) - gcc_test=`echo $GCCVERSION | grep -c '2\.[45678]'` - changequote([,]) - if test $gcc_test -gt 0 - then - changequote(,) - CFLAGS=`echo $CFLAGS | sed 's:-O[^ ]* *::'` - changequote([,]) - AC_MSG_WARN(This gcc is pretty old. Disabling optimization to be safe.) - fi - ;; - no) - echo "cfitsio: Old CFLAGS is $CFLAGS" - CFLAGS=`echo $CFLAGS | sed -e "s/-g/-O/"` - case $host in - *solaris*) - changequote(,) - if test `echo $CFLAGS | grep -c fast` -gt 0 - then - echo "cfitsio: Replacing -fast with -O3" - CFLAGS=`echo $CFLAGS | sed 's:-fast:-O3:'` - fi - changequote([,]) - CFLAGS="$CFLAGS -DHAVE_ALLOCA_H -DHAVE_POSIX_SIGNALS" - ;; - *) - echo "== No special changes for $host" - ;; - esac - echo "New CFLAGS is $CFLAGS" - ;; - *) - # Don't do anything now - ;; -esac - -# GSIFTP flags: -if test "x$GSIFTP_PATH" != x -a "x$GSIFTP_FLAVOUR" != x; then - CFLAGS="$CFLAGS -I${GSIFTP_PATH}/include/${GSIFTP_FLAVOUR}" - LDFLAGS="$LDFLAGS -L${GSIFTP_PATH}/lib -lglobus_ftp_client_${GSIFTP_FLAVOUR}" -fi - -# BZIP2 flags: -if test "x$BZIP2_PATH" != x; then - CFLAGS="$CFLAGS -I${BZIP2_PATH}/include" - LDFLAGS="$LDFLAGS -L${BZIP2_PATH}/lib -lbz2" -fi - -# Shared library section -#------------------------------------------------------------------------------- -SHLIB_LD=: -SHLIB_SUFFIX=".so" -CFITSIO_SHLIB="" -CFITSIO_SHLIB_SONAME="" -lhea_shlib_cflags= -case $EXT in - cygwin|mingw32) - SHLIB_LD="$CC -shared" - SHLIB_SUFFIX=".dll" - ;; - darwin) - changequote(,) - SHLIB_SUFFIX=".dylib" - CFITSIO_SHLIB="lib\${PACKAGE}.\${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}\${SHLIB_SUFFIX}" - CFITSIO_SHLIB_SONAME="lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX}" - case $host in - *darwin[56789]*) - SHLIB_LD="$CC -dynamiclib -install_name lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX} -compatibility_version \${CFITSIO_SONAME} -current_version \${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}" - ;; - *) - # Build 'Universal' binaries (i386 & x86_64 architectures) and - # use rpath token on Darwin 10.x or newer: - SHLIB_LD="$CC -dynamiclib $C_UNIV_SWITCH -headerpad_max_install_names -install_name @rpath/lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX} -compatibility_version \${CFITSIO_SONAME} -current_version \${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}" - ;; - esac - changequote([,]) - lhea_shlib_cflags="-fPIC -fno-common" - ;; - hpu) - SHLIB_LD="ld -b" - SHLIB_SUFFIX=".sl" - ;; - lnx) - SHLIB_LD=":" - CFITSIO_SHLIB="lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}" - CFITSIO_SHLIB_SONAME="lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}" - ;; - osf) - SHLIB_LD="ld -shared -expect_unresolved '*'" - LD_FLAGS="-taso" - ;; - sol) - SHLIB_LD="/usr/ccs/bin/ld -G" - lhea_shlib_cflags="-KPIC" - ;; - sgi) - SHLIB_LD="ld -shared -rdata_shared" - ;; - *) - AC_MSG_WARN(Unable to determine how to make a shared library) - ;; -esac -# Darwin uses gcc (=cc), but needs different flags (see above) -if test "x$EXT" != xdarwin && test "x$EXT" != xcygwin && test "x$EXT" != xmingw32; then - if test "x$GCC" = xyes; then - SHLIB_LD="$CC -shared -Wl,-soname,lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}" - lhea_shlib_cflags='-fPIC' - fi -fi -if test "x$lhea_shlib_cflags" != x; then - CFLAGS="$CFLAGS $lhea_shlib_cflags" -fi -# Set shared library name for cases in which we aren't setting a 'soname': -if test "x$CFITSIO_SHLIB" = x; then CFITSIO_SHLIB="lib\${PACKAGE}\${SHLIB_SUFFIX}"; fi - -AC_SUBST(ARCH)dnl -AC_SUBST(CFLAGS)dnl -AC_SUBST(CC)dnl -AC_SUBST(FC)dnl -AC_SUBST(LIBPRE)dnl -AC_SUBST(SHLIB_LD)dnl -AC_SUBST(SHLIB_SUFFIX)dnl -AC_SUBST(CFITSIO_SHLIB)dnl -AC_SUBST(CFITSIO_SHLIB_SONAME)dnl -AC_SUBST(F77_WRAPPERS) -AC_SUBST(LDFLAGS_BIN) - -# ================= test for the unix ftruncate function ================ - -AC_MSG_CHECKING("whether ftruncate works") -AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include -]], [[ -ftruncate(0, 0); -]])],[ -AC_DEFINE(HAVE_FTRUNCATE) -AC_MSG_RESULT("yes") -],[AC_MSG_RESULT("no") ]) - -# --------------------------------------------------------- -# some systems define long long for 64-bit ints -# --------------------------------------------------------- - -AC_MSG_CHECKING("whether long long is defined") -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include -]], [[ -long long filler; -]])],[ -AC_DEFINE(HAVE_LONGLONG) -AC_MSG_RESULT("yes") -],[AC_MSG_RESULT("no") ]) - -# ==================== SHARED MEMORY DRIVER SECTION ======================= -# -# 09-Mar-98 : modified by JB/ISDC -# 3 checks added to support autoconfiguration of shared memory -# driver. First generic check is made whether shared memory is supported -# at all, then 2 more specific checks are made (architecture dependent). -# Currently tested on : sparc-solaris, intel-linux, sgi-irix, dec-alpha-osf - -# ------------------------------------------------------------------------- -# check is System V IPC is supported on this machine -# ------------------------------------------------------------------------- - -AC_MSG_CHECKING("whether system V style IPC services are supported") -AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include -#include -#include -]], [[ -shmat(0, 0, 0); -shmdt(0); -shmget(0, 0, 0); -semget(0, 0, 0); -]])],[ -AC_DEFINE(HAVE_SHMEM_SERVICES) -my_shmem=\${SOURCES_SHMEM} -AC_MSG_RESULT("yes") -],[AC_MSG_RESULT("no") ]) - -AC_SUBST(my_shmem) - -# ------------------------------------------------------------------------- -# some systems define flock_t, for others we have to define it ourselves -# ------------------------------------------------------------------------- - -AC_MSG_CHECKING("do we have flock_t defined in sys/fcntl.h") -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include -]], [[ -flock_t filler; -]])],[ -AC_DEFINE(HAVE_FLOCK_T) -AC_MSG_RESULT("yes") -],[AC_MSG_RESULT("no") ]) - -if test "$HAVE_FLOCK_T" != 1; then - AC_MSG_CHECKING("do we have flock_t defined in sys/flock.h") - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include - ]], [[ - flock_t filler; - ]])],[ - AC_DEFINE(HAVE_FLOCK_T) - AC_MSG_RESULT("yes") - ],[AC_MSG_RESULT("no") ]) -fi - -# ------------------------------------------------------------------------- -# there are some idiosyncrasies with semun defs (used in semxxx). Solaris -# does not define it at all -# ------------------------------------------------------------------------- - -AC_MSG_CHECKING("do we have union semun defined") -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include -#include -#include -]], [[ -union semun filler; -]])],[ -AC_DEFINE(HAVE_UNION_SEMUN) -AC_MSG_RESULT("yes") -],[AC_MSG_RESULT("no") ]) - -# ==================== END OF SHARED MEMORY DRIVER SECTION ================ -# ================= test for the unix networking functions ================ - -AC_SEARCH_LIBS([gethostbyname], [nsl], cfitsio_have_nsl=1, cfitsio_have_nsl=0) -AC_SEARCH_LIBS([connect], [socket], cfitsio_have_socket=1, - cfitsio_have_socket=0, [-lnsl]) - -if test "$cfitsio_have_nsl" = 1 -a "$cfitsio_have_socket" = 1; then - AC_DEFINE(HAVE_NET_SERVICES) -fi - -# ==================== END OF unix networking SECTION ================ - -# ------------------------------------------------------------------------------ -# Define _REENTRANT & add -lpthread to LIBS if reentrant multithreading enabled: -# ------------------------------------------------------------------------------ -if test "x$BUILD_REENTRANT" = xyes; then - AC_DEFINE(_REENTRANT) - AC_DEFINE([_XOPEN_SOURCE], [700]) - AC_CHECK_LIB([pthread],[main],[],[AC_MSG_ERROR(Unable to locate pthread library needed when enabling reentrant multithreading)]) -fi -# ------------------------------------------------------------------------------ - -AC_CONFIG_FILES([Makefile]) -AC_OUTPUT -AC_CONFIG_FILES([cfitsio.pc]) -AC_OUTPUT - - -AC_MSG_RESULT([]) -AC_MSG_RESULT([ Congratulations, Makefile update was successful.]) -AC_MSG_RESULT([ You may want to run \"make\" now.]) -AC_MSG_RESULT([]) - diff --git a/src/external/OpenGR/3rdparty/cfitsio/cookbook.c b/src/external/OpenGR/3rdparty/cfitsio/cookbook.c deleted file mode 100644 index 22cf546f4..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/cookbook.c +++ /dev/null @@ -1,571 +0,0 @@ -#include -#include -#include - -/* - Every program which uses the CFITSIO interface must include the - the fitsio.h header file. This contains the prototypes for all - the routines and defines the error status values and other symbolic - constants used in the interface. -*/ -#include "fitsio.h" - -int main( void ); -void writeimage( void ); -void writeascii( void ); -void writebintable( void ); -void copyhdu( void ); -void selectrows( void ); -void readheader( void ); -void readimage( void ); -void readtable( void ); -void printerror( int status); - -int main() -{ -/************************************************************************* - This is a simple main program that calls the following routines: - - writeimage - write a FITS primary array image - writeascii - write a FITS ASCII table extension - writebintable - write a FITS binary table extension - copyhdu - copy a header/data unit from one FITS file to another - selectrows - copy selected row from one HDU to another - readheader - read and print the header keywords in every extension - readimage - read a FITS image and compute the min and max value - readtable - read columns of data from ASCII and binary tables - -**************************************************************************/ - - writeimage(); - writeascii(); - writebintable(); - copyhdu(); - selectrows(); - readheader(); - readimage(); - readtable(); - - printf("\nAll the cfitsio cookbook routines ran successfully.\n"); - return(0); -} -/*--------------------------------------------------------------------------*/ -void writeimage( void ) - - /******************************************************/ - /* Create a FITS primary array containing a 2-D image */ - /******************************************************/ -{ - fitsfile *fptr; /* pointer to the FITS file, defined in fitsio.h */ - int status, ii, jj; - long fpixel, nelements, exposure; - unsigned short *array[200]; - - /* initialize FITS image parameters */ - char filename[] = "atestfil.fit"; /* name for new FITS file */ - int bitpix = USHORT_IMG; /* 16-bit unsigned short pixel values */ - long naxis = 2; /* 2-dimensional image */ - long naxes[2] = { 300, 200 }; /* image is 300 pixels wide by 200 rows */ - - /* allocate memory for the whole image */ - array[0] = (unsigned short *)malloc( naxes[0] * naxes[1] - * sizeof( unsigned short ) ); - - /* initialize pointers to the start of each row of the image */ - for( ii=1; ii 0) - { - nbuffer = npixels; - if (npixels > buffsize) - nbuffer = buffsize; /* read as many pixels as will fit in buffer */ - - /* Note that even though the FITS images contains unsigned integer */ - /* pixel values (or more accurately, signed integer pixels with */ - /* a bias of 32768), this routine is reading the values into a */ - /* float array. Cfitsio automatically performs the datatype */ - /* conversion in cases like this. */ - - if ( fits_read_img(fptr, TFLOAT, fpixel, nbuffer, &nullval, - buffer, &anynull, &status) ) - printerror( status ); - - for (ii = 0; ii < nbuffer; ii++) { - if ( buffer[ii] < datamin ) - datamin = buffer[ii]; - - if ( buffer[ii] > datamax ) - datamax = buffer[ii]; - } - npixels -= nbuffer; /* increment remaining number of pixels */ - fpixel += nbuffer; /* next pixel to be read in image */ - } - - printf("\nMin and max image pixels = %.0f, %.0f\n", datamin, datamax); - - if ( fits_close_file(fptr, &status) ) - printerror( status ); - - return; -} -/*--------------------------------------------------------------------------*/ -void readtable( void ) - - /************************************************************/ - /* read and print data values from an ASCII or binary table */ - /************************************************************/ -{ - fitsfile *fptr; /* pointer to the FITS file, defined in fitsio.h */ - int status, hdunum, hdutype, nfound, anynull, ii; - long frow, felem, nelem, longnull, dia[6]; - float floatnull, den[6]; - char strnull[10], *name[6], *ttype[3]; - - char filename[] = "atestfil.fit"; /* name of existing FITS file */ - - status = 0; - - if ( fits_open_file(&fptr, filename, READONLY, &status) ) - printerror( status ); - - for (ii = 0; ii < 3; ii++) /* allocate space for the column labels */ - ttype[ii] = (char *) malloc(FLEN_VALUE); /* max label length = 69 */ - - for (ii = 0; ii < 6; ii++) /* allocate space for string column value */ - name[ii] = (char *) malloc(10); - - for (hdunum = 2; hdunum <= 3; hdunum++) /*read ASCII, then binary table */ - { - /* move to the HDU */ - if ( fits_movabs_hdu(fptr, hdunum, &hdutype, &status) ) - printerror( status ); - - if (hdutype == ASCII_TBL) - printf("\nReading ASCII table in HDU %d:\n", hdunum); - else if (hdutype == BINARY_TBL) - printf("\nReading binary table in HDU %d:\n", hdunum); - else - { - printf("Error: this HDU is not an ASCII or binary table\n"); - printerror( status ); - } - - /* read the column names from the TTYPEn keywords */ - fits_read_keys_str(fptr, "TTYPE", 1, 3, ttype, &nfound, &status); - - printf(" Row %10s %10s %10s\n", ttype[0], ttype[1], ttype[2]); - - frow = 1; - felem = 1; - nelem = 6; - strcpy(strnull, " "); - longnull = 0; - floatnull = 0.; - - /* read the columns */ - fits_read_col(fptr, TSTRING, 1, frow, felem, nelem, strnull, name, - &anynull, &status); - fits_read_col(fptr, TLONG, 2, frow, felem, nelem, &longnull, dia, - &anynull, &status); - fits_read_col(fptr, TFLOAT, 3, frow, felem, nelem, &floatnull, den, - &anynull, &status); - - for (ii = 0; ii < 6; ii++) - printf("%5d %10s %10ld %10.2f\n", ii + 1, name[ii], dia[ii], den[ii]); - } - - for (ii = 0; ii < 3; ii++) /* free the memory for the column labels */ - free( ttype[ii] ); - - for (ii = 0; ii < 6; ii++) /* free the memory for the string column */ - free( name[ii] ); - - if ( fits_close_file(fptr, &status) ) - printerror( status ); - - return; -} -/*--------------------------------------------------------------------------*/ -void printerror( int status) -{ - /*****************************************************/ - /* Print out cfitsio error messages and exit program */ - /*****************************************************/ - - - if (status) - { - fits_report_error(stderr, status); /* print error report */ - - exit( status ); /* terminate the program, returning error status */ - } - return; -} diff --git a/src/external/OpenGR/3rdparty/cfitsio/cookbook.f b/src/external/OpenGR/3rdparty/cfitsio/cookbook.f deleted file mode 100644 index 8becfdd20..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/cookbook.f +++ /dev/null @@ -1,772 +0,0 @@ - program main - -C This is the FITSIO cookbook program that contains an annotated listing of -C various computer programs that read and write files in FITS format -C using the FITSIO subroutine interface. These examples are -C working programs which users may adapt and modify for their own -C purposes. This Cookbook serves as a companion to the FITSIO User's -C Guide that provides more complete documentation on all the -C available FITSIO subroutines. - -C Call each subroutine in turn: - - call writeimage - call writeascii - call writebintable - call copyhdu - call selectrows - call readheader - call readimage - call readtable - print * - print *,"All the fitsio cookbook routines ran successfully." - - end -C ************************************************************************* - subroutine writeimage - -C Create a FITS primary array containing a 2-D image - - integer status,unit,blocksize,bitpix,naxis,naxes(2) - integer i,j,group,fpixel,nelements,array(300,200) - character filename*80 - logical simple,extend - -C The STATUS parameter must be initialized before using FITSIO. A -C positive value of STATUS is returned whenever a serious error occurs. -C FITSIO uses an `inherited status' convention, which means that if a -C subroutine is called with a positive input value of STATUS, then the -C subroutine will exit immediately, preserving the status value. For -C simplicity, this program only checks the status value at the end of -C the program, but it is usually better practice to check the status -C value more frequently. - - status=0 - -C Name of the FITS file to be created: - filename='ATESTFILEZ.FITS' - -C Delete the file if it already exists, so we can then recreate it. -C The deletefile subroutine is listed at the end of this file. - call deletefile(filename,status) - -C Get an unused Logical Unit Number to use to open the FITS file. -C This routine is not required; programmers can choose any unused -C unit number to open the file. - call ftgiou(unit,status) - -C Create the new empty FITS file. The blocksize parameter is a -C historical artifact and the value is ignored by FITSIO. - blocksize=1 - call ftinit(unit,filename,blocksize,status) - -C Initialize parameters about the FITS image. -C BITPIX = 16 means that the image pixels will consist of 16-bit -C integers. The size of the image is given by the NAXES values. -C The EXTEND = TRUE parameter indicates that the FITS file -C may contain extensions following the primary array. - simple=.true. - bitpix=16 - naxis=2 - naxes(1)=300 - naxes(2)=200 - extend=.true. - -C Write the required header keywords to the file - call ftphpr(unit,simple,bitpix,naxis,naxes,0,1,extend,status) - -C Initialize the values in the image with a linear ramp function - do j=1,naxes(2) - do i=1,naxes(1) - array(i,j)=i - 1 +j - 1 - end do - end do - -C Write the array to the FITS file. -C The last letter of the subroutine name defines the datatype of the -C array argument; in this case the 'J' indicates that the array has an -C integer*4 datatype. ('I' = I*2, 'E' = Real*4, 'D' = Real*8). -C The 2D array is treated as a single 1-D array with NAXIS1 * NAXIS2 -C total number of pixels. GROUP is seldom used parameter that should -C almost always be set = 1. - group=1 - fpixel=1 - nelements=naxes(1)*naxes(2) - call ftpprj(unit,group,fpixel,nelements,array,status) - -C Write another optional keyword to the header -C The keyword record will look like this in the FITS file: -C -C EXPOSURE= 1500 / Total Exposure Time -C - call ftpkyj(unit,'EXPOSURE',1500,'Total Exposure Time',status) - -C The FITS file must always be closed before exiting the program. -C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. - call ftclos(unit, status) - call ftfiou(unit, status) - -C Check for any errors, and if so print out error messages. -C The PRINTERROR subroutine is listed near the end of this file. - if (status .gt. 0)call printerror(status) - end -C ************************************************************************* - subroutine writeascii - -C Create an ASCII table containing 3 columns and 6 rows. For convenience, -C the ASCII table extension is appended to the FITS image file created -C previously by the WRITEIMAGE subroutine. - - integer status,unit,readwrite,blocksize,tfields,nrows,rowlen - integer nspace,tbcol(3),diameter(6), colnum,frow,felem - real density(6) - character filename*40,extname*16 - character*16 ttype(3),tform(3),tunit(3),name(6) - data ttype/'Planet','Diameter','Density'/ - data tform/'A8','I6','F4.2'/ - data tunit/' ','km','g/cm'/ - data name/'Mercury','Venus','Earth','Mars','Jupiter','Saturn'/ - data diameter/4880,12112,12742,6800,143000,121000/ - data density/5.1,5.3,5.52,3.94,1.33,0.69/ - -C The STATUS parameter must always be initialized. - status=0 - -C Name of the FITS file to append the ASCII table to: - filename='ATESTFILEZ.FITS' - -C Get an unused Logical Unit Number to use to open the FITS file. - call ftgiou(unit,status) - -C Open the FITS file with write access. -C (readwrite = 0 would open the file with readonly access). - readwrite=1 - call ftopen(unit,filename,readwrite,blocksize,status) - -C FTCRHD creates a new empty FITS extension following the current -C extension and moves to it. In this case, FITSIO was initially -C positioned on the primary array when the FITS file was first opened, so -C FTCRHD appends an empty extension and moves to it. All future FITSIO -C calls then operate on the new extension (which will be an ASCII -C table). - call ftcrhd(unit,status) - -C define parameters for the ASCII table (see the above data statements) - tfields=3 - nrows=6 - extname='PLANETS_ASCII' - -C FTGABC is a convenient subroutine for calculating the total width of -C the table and the starting position of each column in an ASCII table. -C Any number of blank spaces (including zero) may be inserted between -C each column of the table, as specified by the NSPACE parameter. - nspace=1 - call ftgabc(tfields,tform,nspace,rowlen,tbcol,status) - -C FTPHTB writes all the required header keywords which define the -C structure of the ASCII table. NROWS and TFIELDS give the number of -C rows and columns in the table, and the TTYPE, TBCOL, TFORM, and TUNIT -C arrays give the column name, starting position, format, and units, -C respectively of each column. The values of the ROWLEN and TBCOL parameters -C were previously calculated by the FTGABC routine. - call ftphtb(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit, - & extname,status) - -C Write names to the first column, diameters to 2nd col., and density to 3rd -C FTPCLS writes the string values to the NAME column (column 1) of the -C table. The FTPCLJ and FTPCLE routines write the diameter (integer) and -C density (real) value to the 2nd and 3rd columns. The FITSIO routines -C are column oriented, so it is usually easier to read or write data in a -C table in a column by column order rather than row by row. - frow=1 - felem=1 - colnum=1 - call ftpcls(unit,colnum,frow,felem,nrows,name,status) - colnum=2 - call ftpclj(unit,colnum,frow,felem,nrows,diameter,status) - colnum=3 - call ftpcle(unit,colnum,frow,felem,nrows,density,status) - -C The FITS file must always be closed before exiting the program. -C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. - call ftclos(unit, status) - call ftfiou(unit, status) - -C Check for any error, and if so print out error messages. -C The PRINTERROR subroutine is listed near the end of this file. - if (status .gt. 0)call printerror(status) - end -C ************************************************************************* - subroutine writebintable - -C This routine creates a FITS binary table, or BINTABLE, containing -C 3 columns and 6 rows. This routine is nearly identical to the -C previous WRITEASCII routine, except that the call to FTGABC is not -C needed, and FTPHBN is called rather than FTPHTB to write the -C required header keywords. - - integer status,unit,readwrite,blocksize,hdutype,tfields,nrows - integer varidat,diameter(6), colnum,frow,felem - real density(6) - character filename*40,extname*16 - character*16 ttype(3),tform(3),tunit(3),name(6) - data ttype/'Planet','Diameter','Density'/ - data tform/'8A','1J','1E'/ - data tunit/' ','km','g/cm'/ - data name/'Mercury','Venus','Earth','Mars','Jupiter','Saturn'/ - data diameter/4880,12112,12742,6800,143000,121000/ - data density/5.1,5.3,5.52,3.94,1.33,0.69/ - -C The STATUS parameter must always be initialized. - status=0 - -C Name of the FITS file to append the ASCII table to: - filename='ATESTFILEZ.FITS' - -C Get an unused Logical Unit Number to use to open the FITS file. - call ftgiou(unit,status) - -C Open the FITS file, with write access. - readwrite=1 - call ftopen(unit,filename,readwrite,blocksize,status) - -C Move to the last (2nd) HDU in the file (the ASCII table). - call ftmahd(unit,2,hdutype,status) - -C Append/create a new empty HDU onto the end of the file and move to it. - call ftcrhd(unit,status) - -C Define parameters for the binary table (see the above data statements) - tfields=3 - nrows=6 - extname='PLANETS_BINARY' - varidat=0 - -C FTPHBN writes all the required header keywords which define the -C structure of the binary table. NROWS and TFIELDS gives the number of -C rows and columns in the table, and the TTYPE, TFORM, and TUNIT arrays -C give the column name, format, and units, respectively of each column. - call ftphbn(unit,nrows,tfields,ttype,tform,tunit, - & extname,varidat,status) - -C Write names to the first column, diameters to 2nd col., and density to 3rd -C FTPCLS writes the string values to the NAME column (column 1) of the -C table. The FTPCLJ and FTPCLE routines write the diameter (integer) and -C density (real) value to the 2nd and 3rd columns. The FITSIO routines -C are column oriented, so it is usually easier to read or write data in a -C table in a column by column order rather than row by row. Note that -C the identical subroutine calls are used to write to either ASCII or -C binary FITS tables. - frow=1 - felem=1 - colnum=1 - call ftpcls(unit,colnum,frow,felem,nrows,name,status) - colnum=2 - call ftpclj(unit,colnum,frow,felem,nrows,diameter,status) - colnum=3 - call ftpcle(unit,colnum,frow,felem,nrows,density,status) - -C The FITS file must always be closed before exiting the program. -C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. - call ftclos(unit, status) - call ftfiou(unit, status) - -C Check for any error, and if so print out error messages. -C The PRINTERROR subroutine is listed near the end of this file. - if (status .gt. 0)call printerror(status) - end -C ************************************************************************* - subroutine copyhdu - -C Copy the 1st and 3rd HDUs from the input file to a new FITS file - - integer status,inunit,outunit,readwrite,blocksize,morekeys,hdutype - character infilename*40,outfilename*40 - -C The STATUS parameter must always be initialized. - status=0 - -C Name of the FITS files: - infilename='ATESTFILEZ.FITS' - outfilename='BTESTFILEZ.FITS' - -C Delete the file if it already exists, so we can then recreate it -C The deletefile subroutine is listed at the end of this file. - call deletefile(outfilename,status) - -C Get unused Logical Unit Numbers to use to open the FITS files. - call ftgiou(inunit,status) - call ftgiou(outunit,status) - -C Open the input FITS file, with readonly access - readwrite=0 - call ftopen(inunit,infilename,readwrite,blocksize,status) - -C Create the new empty FITS file (value of blocksize is ignored) - blocksize=1 - call ftinit(outunit,outfilename,blocksize,status) - -C FTCOPY copies the current HDU from the input FITS file to the output -C file. The MOREKEY parameter allows one to reserve space for additional -C header keywords when the HDU is created. FITSIO will automatically -C insert more header space if required, so programmers do not have to -C reserve space ahead of time, although it is more efficient to do so if -C it is known that more keywords will be appended to the header. - morekeys=0 - call ftcopy(inunit,outunit,morekeys,status) - -C Append/create a new empty extension on the end of the output file - call ftcrhd(outunit,status) - -C Skip to the 3rd extension in the input file which in this case -C is the binary table created by the previous WRITEBINARY routine. - call ftmahd(inunit,3,hdutype,status) - -C FTCOPY now copies the binary table from the input FITS file -C to the output file. - call ftcopy(inunit,outunit,morekeys,status) - -C The FITS files must always be closed before exiting the program. -C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. -C Giving -1 for the value of the first argument causes all previously -C allocated unit numbers to be released. - - call ftclos(inunit, status) - call ftclos(outunit, status) - call ftfiou(-1, status) - -C Check for any error, and if so print out error messages. -C The PRINTERROR subroutine is listed near the end of this file. - if (status .gt. 0)call printerror(status) - end -C ************************************************************************* - subroutine selectrows - -C This routine copies selected rows from an input table into a new output -C FITS table. In this example all the rows in the input table that have -C a value of the DENSITY column less that 3.0 are copied to the output -C table. This program illustrates several generally useful techniques, -C including: -C how to locate the end of a FITS file -C how to create a table when the total number of rows in the table -C is not known until the table is completed -C how to efficiently copy entire rows from one table to another. - - integer status,inunit,outunit,readwrite,blocksize,hdutype - integer nkeys,nspace,naxes(2),nfound,colnum,frow,felem - integer noutrows,irow,temp(100),i - real nullval,density(6) - character infilename*40,outfilename*40,record*80 - logical exact,anynulls - -C The STATUS parameter must always be initialized. - status=0 - -C Names of the FITS files: - infilename='ATESTFILEZ.FITS' - outfilename='BTESTFILEZ.FITS' - -C Get unused Logical Unit Numbers to use to open the FITS files. - call ftgiou(inunit,status) - call ftgiou(outunit,status) - -C The input FITS file is opened with READONLY access, and the output -C FITS file is opened with WRITE access. - readwrite=0 - call ftopen(inunit,infilename,readwrite,blocksize,status) - readwrite=1 - call ftopen(outunit,outfilename,readwrite,blocksize,status) - -C move to the 3rd HDU in the input file (a binary table in this case) - call ftmahd(inunit,3,hdutype,status) - -C This do-loop illustrates how to move to the last extension in any FITS -C file. The call to FTMRHD moves one extension at a time through the -C FITS file until an `End-of-file' status value (= 107) is returned. - do while (status .eq. 0) - call ftmrhd(outunit,1,hdutype,status) - end do - -C After locating the end of the FITS file, it is necessary to reset the -C status value to zero and also clear the internal error message stack -C in FITSIO. The previous `End-of-file' error will have produced -C an unimportant message on the error stack which can be cleared with -C the call to the FTCMSG routine (which has no arguments). - - if (status .eq. 107)then - status=0 - call ftcmsg - end if - -C Create a new empty extension in the output file. - call ftcrhd(outunit,status) - -C Find the number of keywords in the input table header. - call ftghsp(inunit,nkeys,nspace,status) - -C This do-loop of calls to FTGREC and FTPREC copies all the keywords from -C the input to the output FITS file. Notice that the specified number -C of rows in the output table, as given by the NAXIS2 keyword, will be -C incorrect. This value will be modified later after it is known how many -C rows will be in the table, so it does not matter how many rows are specified -C initially. - do i=1,nkeys - call ftgrec(inunit,i,record,status) - call ftprec(outunit,record,status) - end do - -C FTGKNJ is used to get the value of the NAXIS1 and NAXIS2 keywords, -C which define the width of the table in bytes, and the number of -C rows in the table. - call ftgknj(inunit,'NAXIS',1,2,naxes,nfound,status) - -C FTGCNO gets the column number of the `DENSITY' column; the column -C number is needed when reading the data in the column. The EXACT -C parameter determines whether or not the match to the column names -C will be case sensitive. - exact=.false. - call ftgcno(inunit,exact,'DENSITY',colnum,status) - -C FTGCVE reads all 6 rows of data in the `DENSITY' column. The number -C of rows in the table is given by NAXES(2). Any null values in the -C table will be returned with the corresponding value set to -99 -C (= the value of NULLVAL). The ANYNULLS parameter will be set to TRUE -C if any null values were found while reading the data values in the table. - frow=1 - felem=1 - nullval=-99. - call ftgcve(inunit,colnum,frow,felem,naxes(2),nullval, - & density,anynulls,status) - -C If the density is less than 3.0, copy the row to the output table. -C FTGTBB and FTPTBB are low-level routines to read and write, respectively, -C a specified number of bytes in the table, starting at the specified -C row number and beginning byte within the row. These routines do -C not do any interpretation of the bytes, and simply pass them to or -C from the FITS file without any modification. This is a faster -C way of transferring large chunks of data from one FITS file to another, -C than reading and then writing each column of data individually. -C In this case an entire row of bytes (the row length is specified -C by the naxes(1) parameter) is transferred. The datatype of the -C buffer array (TEMP in this case) is immaterial so long as it is -C declared large enough to hold the required number of bytes. - noutrows=0 - do irow=1,naxes(2) - if (density(irow) .lt. 3.0)then - noutrows=noutrows+1 - call ftgtbb(inunit,irow,1,naxes(1),temp,status) - call ftptbb(outunit,noutrows,1,naxes(1),temp,status) - end if - end do - -C Update the NAXIS2 keyword with the correct no. of rows in the output file. -C After all the rows have been written to the output table, the -C FTMKYJ routine is used to overwrite the NAXIS2 keyword value with -C the correct number of rows. Specifying `\&' for the comment string -C tells FITSIO to keep the current comment string in the keyword and -C only modify the value. Because the total number of rows in the table -C was unknown when the table was first created, any value (including 0) -C could have been used for the initial NAXIS2 keyword value. - call ftmkyj(outunit,'NAXIS2',noutrows,'&',status) - -C The FITS files must always be closed before exiting the program. -C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. - call ftclos(inunit, status) - call ftclos(outunit, status) - call ftfiou(-1, status) - -C Check for any error, and if so print out error messages. -C The PRINTERROR subroutine is listed near the end of this file. - if (status .gt. 0)call printerror(status) - end -C ************************************************************************* - subroutine readheader - -C Print out all the header keywords in all extensions of a FITS file - - integer status,unit,readwrite,blocksize,nkeys,nspace,hdutype,i,j - character filename*80,record*80 - -C The STATUS parameter must always be initialized. - status=0 - -C Get an unused Logical Unit Number to use to open the FITS file. - call ftgiou(unit,status) - -C name of FITS file - filename='ATESTFILEZ.FITS' - -C open the FITS file, with read-only access. The returned BLOCKSIZE -C parameter is obsolete and should be ignored. - readwrite=0 - call ftopen(unit,filename,readwrite,blocksize,status) - - j = 0 -100 continue - j = j + 1 - - print *,'Header listing for HDU', j - -C The FTGHSP subroutine returns the number of existing keywords in the -C current header data unit (CHDU), not counting the required END keyword, - call ftghsp(unit,nkeys,nspace,status) - -C Read each 80-character keyword record, and print it out. - do i = 1, nkeys - call ftgrec(unit,i,record,status) - print *,record - end do - -C Print out an END record, and a blank line to mark the end of the header. - if (status .eq. 0)then - print *,'END' - print *,' ' - end if - -C Try moving to the next extension in the FITS file, if it exists. -C The FTMRHD subroutine attempts to move to the next HDU, as specified by -C the second parameter. This subroutine moves by a relative number of -C HDUs from the current HDU. The related FTMAHD routine may be used to -C move to an absolute HDU number in the FITS file. If the end-of-file is -C encountered when trying to move to the specified extension, then a -C status = 107 is returned. - call ftmrhd(unit,1,hdutype,status) - - if (status .eq. 0)then -C success, so jump back and print out keywords in this extension - go to 100 - - else if (status .eq. 107)then -C hit end of file, so quit - status=0 - end if - -C The FITS file must always be closed before exiting the program. -C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. - call ftclos(unit, status) - call ftfiou(unit, status) - -C Check for any error, and if so print out error messages. -C The PRINTERROR subroutine is listed near the end of this file. - if (status .gt. 0)call printerror(status) - end -C ************************************************************************* - subroutine readimage - -C Read a FITS image and determine the minimum and maximum pixel value. -C Rather than reading the entire image in -C at once (which could require a very large array), the image is read -C in pieces, 100 pixels at a time. - - integer status,unit,readwrite,blocksize,naxes(2),nfound - integer group,firstpix,nbuffer,npixels,i - real datamin,datamax,nullval,buffer(100) - logical anynull - character filename*80 - -C The STATUS parameter must always be initialized. - status=0 - -C Get an unused Logical Unit Number to use to open the FITS file. - call ftgiou(unit,status) - -C Open the FITS file previously created by WRITEIMAGE - filename='ATESTFILEZ.FITS' - readwrite=0 - call ftopen(unit,filename,readwrite,blocksize,status) - -C Determine the size of the image. - call ftgknj(unit,'NAXIS',1,2,naxes,nfound,status) - -C Check that it found both NAXIS1 and NAXIS2 keywords. - if (nfound .ne. 2)then - print *,'READIMAGE failed to read the NAXISn keywords.' - return - end if - -C Initialize variables - npixels=naxes(1)*naxes(2) - group=1 - firstpix=1 - nullval=-999 - datamin=1.0E30 - datamax=-1.0E30 - - do while (npixels .gt. 0) -C read up to 100 pixels at a time - nbuffer=min(100,npixels) - - call ftgpve(unit,group,firstpix,nbuffer,nullval, - & buffer,anynull,status) - -C find the min and max values - do i=1,nbuffer - datamin=min(datamin,buffer(i)) - datamax=max(datamax,buffer(i)) - end do - -C increment pointers and loop back to read the next group of pixels - npixels=npixels-nbuffer - firstpix=firstpix+nbuffer - end do - - print * - print *,'Min and max image pixels = ',datamin,datamax - -C The FITS file must always be closed before exiting the program. -C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. - call ftclos(unit, status) - call ftfiou(unit, status) - -C Check for any error, and if so print out error messages. -C The PRINTERROR subroutine is listed near the end of this file. - if (status .gt. 0)call printerror(status) - end -C ************************************************************************* - subroutine readtable - -C Read and print data values from an ASCII or binary table -C This example reads and prints out all the data in the ASCII and -C the binary tables that were previously created by WRITEASCII and -C WRITEBINTABLE. Note that the exact same FITSIO routines are -C used to read both types of tables. - - integer status,unit,readwrite,blocksize,hdutype,ntable - integer felem,nelems,nullj,diameter,nfound,irow,colnum - real nulle,density - character filename*40,nullstr*1,name*8,ttype(3)*10 - logical anynull - -C The STATUS parameter must always be initialized. - status=0 - -C Get an unused Logical Unit Number to use to open the FITS file. - call ftgiou(unit,status) - -C Open the FITS file previously created by WRITEIMAGE - filename='ATESTFILEZ.FITS' - readwrite=0 - call ftopen(unit,filename,readwrite,blocksize,status) - -C Loop twice, first reading the ASCII table, then the binary table - do ntable=2,3 - -C Move to the next extension - call ftmahd(unit,ntable,hdutype,status) - - print *,' ' - if (hdutype .eq. 1)then - print *,'Reading ASCII table in HDU ',ntable - else if (hdutype .eq. 2)then - print *,'Reading binary table in HDU ',ntable - end if - -C Read the TTYPEn keywords, which give the names of the columns - call ftgkns(unit,'TTYPE',1,3,ttype,nfound,status) - write(*,2000)ttype -2000 format(2x,"Row ",3a10) - -C Read the data, one row at a time, and print them out - felem=1 - nelems=1 - nullstr=' ' - nullj=0 - nulle=0. - do irow=1,6 -C FTGCVS reads the NAMES from the first column of the table. - colnum=1 - call ftgcvs(unit,colnum,irow,felem,nelems,nullstr,name, - & anynull,status) - -C FTGCVJ reads the DIAMETER values from the second column. - colnum=2 - call ftgcvj(unit,colnum,irow,felem,nelems,nullj,diameter, - & anynull,status) - -C FTGCVE reads the DENSITY values from the third column. - colnum=3 - call ftgcve(unit,colnum,irow,felem,nelems,nulle,density, - & anynull,status) - write(*,2001)irow,name,diameter,density -2001 format(i5,a10,i10,f10.2) - end do - end do - -C The FITS file must always be closed before exiting the program. -C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. - call ftclos(unit, status) - call ftfiou(unit, status) - -C Check for any error, and if so print out error messages. -C The PRINTERROR subroutine is listed near the end of this file. - if (status .gt. 0)call printerror(status) - end -C ************************************************************************* - subroutine printerror(status) - -C This subroutine prints out the descriptive text corresponding to the -C error status value and prints out the contents of the internal -C error message stack generated by FITSIO whenever an error occurs. - - integer status - character errtext*30,errmessage*80 - -C Check if status is OK (no error); if so, simply return - if (status .le. 0)return - -C The FTGERR subroutine returns a descriptive 30-character text string that -C corresponds to the integer error status number. A complete list of all -C the error numbers can be found in the back of the FITSIO User's Guide. - call ftgerr(status,errtext) - print *,'FITSIO Error Status =',status,': ',errtext - -C FITSIO usually generates an internal stack of error messages whenever -C an error occurs. These messages provide much more information on the -C cause of the problem than can be provided by the single integer error -C status value. The FTGMSG subroutine retrieves the oldest message from -C the stack and shifts any remaining messages on the stack down one -C position. FTGMSG is called repeatedly until a blank message is -C returned, which indicates that the stack is empty. Each error message -C may be up to 80 characters in length. Another subroutine, called -C FTCMSG, is available to simply clear the whole error message stack in -C cases where one is not interested in the contents. - call ftgmsg(errmessage) - do while (errmessage .ne. ' ') - print *,errmessage - call ftgmsg(errmessage) - end do - end -C ************************************************************************* - subroutine deletefile(filename,status) - -C A simple little routine to delete a FITS file - - integer status,unit,blocksize - character*(*) filename - -C Simply return if status is greater than zero - if (status .gt. 0)return - -C Get an unused Logical Unit Number to use to open the FITS file - call ftgiou(unit,status) - -C Try to open the file, to see if it exists - call ftopen(unit,filename,1,blocksize,status) - - if (status .eq. 0)then -C file was opened; so now delete it - call ftdelt(unit,status) - else if (status .eq. 103)then -C file doesn't exist, so just reset status to zero and clear errors - status=0 - call ftcmsg - else -C there was some other error opening the file; delete the file anyway - status=0 - call ftcmsg - call ftdelt(unit,status) - end if - -C Free the unit number for later reuse - call ftfiou(unit, status) - end diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.doc b/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.doc deleted file mode 100644 index fe9e644a2..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.doc +++ /dev/null @@ -1,9679 +0,0 @@ - CFITSIO - An Interface to FITS Format Files for C Programmers - - William D Pence, HEASARC, NASA/GSFC - Version 3.0 - - -[Note: This file contains various formatting command symbols ('*', '-') -in the first column which are used when generating the LATeX version of -this document.] - -*I. Introduction - -**A. A Brief Overview - -CFITSIO is a machine-independent library of routines for reading and -writing data files in the FITS (Flexible Image Transport System) data -format. It can also read IRAF format image files and raw binary data -arrays by converting them on the fly into a virtual FITS format file. -This library is written in ANSI C and provides a powerful yet simple -interface for accessing FITS files which will run on most commonly used -computers and workstations. CFITSIO supports all the features -described in the official definition of the FITS format and can -read and write all the currently defined types of extensions, including -ASCII tables (TABLE), Binary tables (BINTABLE) and IMAGE extensions. -The CFITSIO routines insulate the programmer from having to deal with -the complicated formatting details in the FITS file, however, it is -assumed that users have a general knowledge about the structure and -usage of FITS files. - -CFITSIO also contains a set of Fortran callable wrapper routines which -allow Fortran programs to call the CFITSIO routines. See the companion -``FITSIO User's Guide'' for the definition of the Fortran subroutine -calling sequences. These wrappers replace the older Fortran FITSIO -library which is no longer supported. - -The CFITSIO package was initially developed by the HEASARC (High Energy -Astrophysics Science Archive Research Center) at the NASA Goddard Space -Flight Center to convert various existing and newly acquired -astronomical data sets into FITS format and to further analyze data -already in FITS format. New features continue to be added to CFITSIO -in large part due to contributions of ideas or actual code from -users of the package. The Integral Science Data Center in Switzerland, -and the XMM/ESTEC project in The Netherlands made especially significant -contributions that resulted in many of the new features that appeared -in v2.0 of CFITSIO. - -**B. Sources of FITS Software and Information - -The latest version of the CFITSIO source code, -documentation, and example programs are available on the -Web or via anonymous ftp from: -- - http://heasarc.gsfc.nasa.gov/fitsio - ftp://legacy.gsfc.nasa.gov/software/fitsio/c -- - -Any questions, bug reports, or suggested enhancements related to the CFITSIO -package should be sent to the FTOOLS Help Desk at the HEASARC: -- - http://heasarc.gsfc.nasa.gov/cgi-bin/ftoolshelp -- - -This User's Guide assumes that readers already have a general -understanding of the definition and structure of FITS format files. -Further information about FITS formats is available from the FITS Support -Office at {\tt http://fits.gsfc.nasa.gov}. In particular, the -'FITS Standard' gives the authoritative definition of the FITS data -format. Other documents available at that Web site -provide additional historical background -and practical advice on using FITS files. - -The HEASARC also provides a very sophisticated FITS file analysis -program called `Fv' which can be used to display and edit the contents -of any FITS file as well as construct new FITS files from scratch. -Fv is freely available for -most Unix platforms, Mac PCs, and Windows PCs. -CFITSIO users may also be interested in the FTOOLS package of programs -that can be used to manipulate and analyze FITS format files. -Fv and FTOOLS are available from their respective Web sites at: -- - http://fv.gsfc.nasa.gov - http://heasarc.gsfc.nasa.gov/ftools -- - -**C. Acknowledgments - -The development of the many powerful features in CFITSIO was made -possible through collaborations with many people or organizations from -around the world. The following in particular have made especially -significant contributions: - -Programmers from the Integral Science Data Center, Switzerland (namely, -Jurek Borkowski, Bruce O'Neel, and Don Jennings), designed the concept -for the plug-in I/O drivers that was introduced with CFITSIO 2.0. The -use of `drivers' greatly simplified the low-level I/O, which in turn -made other new features in CFITSIO (e.g., support for compressed FITS -files and support for IRAF format image files) much easier to -implement. Jurek Borkowski wrote the Shared Memory driver, and Bruce -O'Neel wrote the drivers for accessing FITS files over the network -using the FTP, HTTP, and ROOT protocols. Also, in 2009, Bruce O'Neel -was the key developer of the thread-safe version of CFITSIO. - -The ISDC also provided the template parsing routines (written by Jurek -Borkowski) and the hierarchical grouping routines (written by Don -Jennings). The ISDC DAL (Data Access Layer) routines are layered on -top of CFITSIO and make extensive use of these features. - -Giuliano Taffoni and Andrea Barisani, at INAF, University of Trieste, -Italy, implemented the I/O driver routines for accessing FITS files -on the computational grids using the gridftp protocol. - -Uwe Lammers (XMM/ESA/ESTEC, The Netherlands) designed the -high-performance lexical parsing algorithm that is used to do -on-the-fly filtering of FITS tables. This algorithm essentially -pre-compiles the user-supplied selection expression into a form that -can be rapidly evaluated for each row. Peter Wilson (RSTX, NASA/GSFC) -then wrote the parsing routines used by CFITSIO based on Lammers' -design, combined with other techniques such as the CFITSIO iterator -routine to further enhance the data processing throughput. This effort -also benefited from a much earlier lexical parsing routine that was -developed by Kent Blackburn (NASA/GSFC). More recently, Craig Markwardt -(NASA/GSFC) implemented additional functions (median, average, stddev) -and other enhancements to the lexical parser. - -The CFITSIO iterator function is loosely based on similar ideas -developed for the XMM Data Access Layer. - -Peter Wilson (RSTX, NASA/GSFC) wrote the complete set of -Fortran-callable wrappers for all the CFITSIO routines, which in turn -rely on the CFORTRAN macro developed by Burkhard Burow. - -The syntax used by CFITSIO for filtering or binning input FITS files is -based on ideas developed for the AXAF Science Center Data Model by -Jonathan McDowell, Antonella Fruscione, Aneta Siemiginowska and Bill -Joye. See http://heasarc.gsfc.nasa.gov/docs/journal/axaf7.html for -further description of the AXAF Data Model. - -The file decompression code were taken directly from the gzip (GNU zip) -program developed by Jean-loup Gailly and others. - -The new compressed image data format (where the image is tiled and -the compressed byte stream from each tile is stored in a binary table) -was implemented in collaboration with Richard White (STScI), Perry -Greenfield (STScI) and Doug Tody (NOAO). - -Doug Mink (SAO) provided the routines for converting IRAF format -images into FITS format. - -Martin Reinecke (Max Planck Institute, Garching)) provided the modifications to -cfortran.h that are necessary to support 64-bit integer values when calling -C routines from fortran programs. The cfortran.h macros were originally developed -by Burkhard Burow (CERN). - -Julian Taylor (ESO, Garching) provided the fast byte-swapping algorithms -that use the SSE2 and SSSE3 machine instructions available on x86\_64 CPUs. - -In addition, many other people have made valuable contributions to the -development of CFITSIO. These include (with apologies to others that may -have inadvertently been omitted): - -Steve Allen, Carl Akerlof, Keith Arnaud, Morten Krabbe Barfoed, Kent -Blackburn, G Bodammer, Romke Bontekoe, Lucio Chiappetti, Keith Costorf, -Robin Corbet, John Davis, Richard Fink, Ning Gan, Emily Greene, Gretchen -Green, Joe Harrington, Cheng Ho, Phil Hodge, Jim Ingham, Yoshitaka -Ishisaki, Diab Jerius, Mark Levine, Todd Karakaskian, Edward King, -Scott Koch, Claire Larkin, Rob Managan, Eric Mandel, Richard Mathar, -John Mattox, Carsten Meyer, Emi Miyata, Stefan Mochnacki, Mike Noble, -Oliver Oberdorf, Clive Page, Arvind Parmar, Jeff Pedelty, Tim Pearson, -Philippe Prugniel, Maren Purves, Scott Randall, Chris Rogers, Arnold Rots, -Rob Seaman, Barry Schlesinger, Robin Stebbins, Andrew Szymkowiak, Allyn Tennant, -Peter Teuben, James Theiler, Doug Tody, Shiro Ueno, Steve Walton, Archie -Warnock, Alan Watson, Dan Whipple, Wim Wimmers, Peter Young, Jianjun Xu, -and Nelson Zarate. - -**D. Legal Stuff - -Copyright (Unpublished--all rights reserved under the copyright laws of -the United States), U.S. Government as represented by the Administrator -of the National Aeronautics and Space Administration. No copyright is -claimed in the United States under Title 17, U.S. Code. - -Permission to freely use, copy, modify, and distribute this software -and its documentation without fee is hereby granted, provided that this -copyright notice and disclaimer of warranty appears in all copies. - -DISCLAIMER: - -THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, -EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, -ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY -IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE -DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE -SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY -DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR -CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY -CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, -CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY -PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED -FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR -SERVICES PROVIDED HEREUNDER." - -*II. Creating the CFITSIO Library - -**A. Building the Library - -The CFITSIO code is contained in about 40 C source files (*.c) and header -files (*.h). On VAX/VMS systems 2 assembly-code files (vmsieeed.mar and -vmsieeer.mar) are also needed. - -CFITSIO is written in ANCI C and should be compatible with most existing C and C++ -compilers. Cray supercomputers are currently not supported. - -***1. Unix Systems - -The CFITSIO library is built on Unix systems by typing: -- - > ./configure [--prefix=/target/installation/path] [--enable-reentrant] - [--enable-sse2] [--enable-ssse3] - > make (or 'make shared') - > make install (this step is optional) -- -at the operating system prompt. The configure command customizes the -Makefile for the particular system, then the `make' command compiles the -source files and builds the library. Type `./configure' and not simply -`configure' to ensure that the configure script in the current directory -is run and not some other system-wide configure script. The optional -'prefix' argument to configure gives the path to the directory where -the CFITSIO library and include files should be installed via the later -'make install' command. For example, -- - > ./configure --prefix=/usr1/local -- -will cause the 'make install' command to copy the CFITSIO libcfitsio file -to /usr1/local/lib and the necessary include files to /usr1/local/include -(assuming of course that the process has permission to write to these -directories). - -All the available configure options can be seen by entering the command -- - > ./configure --help -- -Some of the more useful options are described below: - -The --enable-reentrant option will attempt to configure CFITSIO -so that it can be used in multi-threaded programs. See the -"Using CFITSIO in Multi-threaded Environments" section, below, for more details. - -The --enable-sse2 and --enable-ssse3 options will cause configure to -attempt to build CFITSIO using faster byte-swapping algorithms. -See the "Optimizing Programs" chapter of this manual for -more information about these options. - -The --with-gsiftp-flavour and --with-gsiftp options enable support for the Globus -Toolkit gsiftp protocal. See the "Extended File Name Syntax" chapter for more -information. - -The --with-bzip2 option enables support for reading FITS files that have been -externally compressed by the bzip2 algorithm. This requires that the CFITSIO -library, and all applications program that use CFITSIO, to be linked to include -the libbz2 library. - -The 'make shared' option builds a shared or dynamic version of the -CFITSIO library. When using the shared library the executable code is -not copied into your program at link time and instead the program -locates the necessary library code at run time, normally through -LD\_LIBRARY\_PATH or some other method. The advantages of using a shared -library are: -- - 1. Less disk space if you build more than 1 program - 2. Less memory if more than one copy of a program using the shared - library is running at the same time since the system is smart - enough to share copies of the shared library at run time. - 3. Possibly easier maintenance since a new version of the shared - library can be installed without relinking all the software - that uses it (as long as the subroutine names and calling - sequences remain unchanged). - 4. No run-time penalty. -- -The disadvantages are: -- - 1. More hassle at runtime. You have to either build the programs - specially or have LD_LIBRARY_PATH set right. - 2. There may be a slight start up penalty, depending on where you are - reading the shared library and the program from and if your CPU is - either really slow or really heavily loaded. -- - -On Mac OS X platforms the 'make shared' command works like on other -UNIX platforms, but a .dylib file will be created instead of .so. If -installed in a nonstandard location, add its location to the -DYLD\_LIBRARY\_PATH environment variable so that the library can be found -at run time. - -On HP/UX systems, the environment variable CFLAGS should be set -to -Ae before running configure to enable "extended ANSI" features. - -By default, a set of Fortran-callable wrapper routines are -also built and included in the CFITSIO library. If these wrapper -routines are not needed (i.e., the CFITSIO library will not -be linked to any Fortran applications which call FITSIO subroutines) -then they may be omitted from the build by typing 'make all-nofitsio' -instead of simply typing 'make'. This will reduce the size -of the CFITSIO library slightly. - -It may not be possible to statically link programs that use CFITSIO on -some platforms (namely, on Solaris 2.6) due to the network drivers -(which provide FTP and HTTP access to FITS files). It is possible to -make both a dynamic and a static version of the CFITSIO library, but -network file access will not be possible using the static version. - -***2. VMS - -On VAX/VMS and ALPHA/VMS systems the make\_gfloat.com command file may -be executed to build the cfitsio.olb object library using the default -G-floating point option for double variables. The make\_dfloat.com and -make\_ieee.com files may be used instead to build the library with the -other floating point options. Note that the getcwd function that is -used in the group.c module may require that programs using CFITSIO be -linked with the ALPHA\$LIBRARY:VAXCRTL.OLB library. See the example -link line in the next section of this document. - -***3. Windows PCs - -A precompiled DLL version of CFITSIO (not necessarily the latest version) -is available on the CFITSIO web site. -The CFITSIO library may also be built from the source code using the -CMake build system. See the "README.win" file in the CFITSIO source distribution -for more information. - -***4. Macintosh PCs - -When building on Mac OS-X, users should follow the Unix instructions, -above. See the README.MacOS file for instructions on building a Universal -Binary that supports both Intel and PowerPC CPUs. - -**B. Testing the Library - -The CFITSIO library should be tested by building and running -the testprog.c program that is included with the release. -On Unix systems, type: -- - % make testprog - % testprog > testprog.lis - % diff testprog.lis testprog.out - % cmp testprog.fit testprog.std -- - On VMS systems, -(assuming cc is the name of the C compiler command), type: -- - $ cc testprog.c - $ link testprog, cfitsio/lib, alpha$library:vaxcrtl/lib - $ run testprog -- -The test program should produce a FITS file called `testprog.fit' -that is identical to the `testprog.std' FITS file included with this -release. The diagnostic messages (which were piped to the file -testprog.lis in the Unix example) should be identical to the listing -contained in the file testprog.out. The 'diff' and 'cmp' commands -shown above should not report any differences in the files. (There -may be some minor format differences, such as the presence or -absence of leading zeros, or 3 digit exponents in numbers, -which can be ignored). - -The Fortran wrappers in CFITSIO may be tested with the testf77 -program on Unix systems with: -- - % f77 -o testf77 testf77.f -L. -lcfitsio -lnsl -lsocket - or - % f77 -f -o testf77 testf77.f -L. -lcfitsio (under SUN O/S) - or - % f77 -o testf77 testf77.f -Wl,-L. -lcfitsio -lm -lnsl -lsocket (HP/UX) - - % testf77 > testf77.lis - % diff testf77.lis testf77.out - % cmp testf77.fit testf77.std -- -On machines running SUN O/S, Fortran programs must be compiled with the -'-f' option to force double precision variables to be aligned on 8-byte -boundarys to make the fortran-declared variables compatible with C. A -similar compiler option may be required on other platforms. Failing to -use this option may cause the program to crash on FITSIO routines that -read or write double precision variables. - -Also note that on some systems, the output listing of the testf77 -program may differ slightly from the testf77.std template, if leading -zeros are not printed by default before the decimal point when using F -format. - -A few other utility programs are included with CFITSIO; the first four -of this programs can be compiled an linked by typing `make -program\_name' where `program\_name' is the actual name of the program: -- - speed - measures the maximum throughput (in MB per second) - for writing and reading FITS files with CFITSIO. - - listhead - lists all the header keywords in any FITS file - - fitscopy - copies any FITS file (especially useful in conjunction - with the CFITSIO's extended input filename syntax). - - cookbook - a sample program that performs common read and - write operations on a FITS file. - - iter_a, iter_b, iter_c - examples of the CFITSIO iterator routine -- - -**C. Linking Programs with CFITSIO - -When linking applications software with the CFITSIO library, several -system libraries usually need to be specified on the link command -line. On Unix systems, the most reliable way to determine what -libraries are required is to type 'make testprog' and see what -libraries the configure script has added. The typical libraries that -need to be added are -lm (the math library) and -lnsl and -lsocket -(needed only for FTP and HTTP file access). These latter 2 libraries -are not needed on VMS and Windows platforms, because FTP file access is -not currently supported on those platforms. - -Note that when upgrading to a newer version of CFITSIO it is usually -necessary to recompile, as well as relink, the programs that use CFITSIO, -because the definitions in fitsio.h often change. - -**D. Using CFITSIO in Multi-threaded Environments - -CFITSIO can be used either with the -POSIX pthreads interface or the OpenMP interface for multi-threaded -parallel programs. When used in a multi-threaded environment, -the CFITSIO library *must* be built using -the -D\_REENTRANT compiler directive. This can be done using the following -build commands: -- - >./configure --enable-reentrant - > make -- -A function called fits\_is\_reentrant is available to test -whether or not CFITSIO was compiled with the -D\_REENTRANT -directive. When this feature is enabled, multiple threads can -call any of the CFITSIO routines -to simultaneously read or write separate -FITS files. Multiple threads can also read data from -the same FITS file simultaneously, as long as the file -was opened independently by each thread. This relies on -the operating system to correctly deal with reading the -same file by multiple processes. Different threads should -not share the same 'fitsfile' pointer to read an opened -FITS file, unless locks are placed around the calls to -the CFITSIO reading routines. -Different threads should never try to write to the same -FITS file. - -**E. Getting Started with CFITSIO - -In order to effectively use the CFITSIO library it is recommended that -new users begin by reading the ``CFITSIO Quick Start Guide''. It -contains all the basic information needed to write programs that -perform most types of operations on FITS files. The set of example -FITS utility programs that are available from the CFITSIO web site are -also very useful for learning how to use CFITSIO. To learn even more -about the capabilities of the CFITSIO library the following steps are -recommended: - -1. Read the following short `FITS Primer' chapter for an overview of -the structure of FITS files. - -2. Review the Programming Guidelines in Chapter 4 to become familiar -with the conventions used by the CFITSIO interface. - -3. Refer to the cookbook.c, listhead.c, and fitscopy.c programs that -are included with this release for examples of routines that perform -various common FITS file operations. Type 'make program\_name' to -compile and link these programs on Unix systems. - -4. Write a simple program to read or write a FITS file using the Basic -Interface routines described in Chapter 5. - -5. Scan through the more specialized routines that are described in -the following chapters to become familiar with the functionality that -they provide. - -**F. Example Program - -The following listing shows an example of how to use the CFITSIO -routines in a C program. Refer to the cookbook.c program that is -included with the CFITSIO distribution for other example routines. - -This program creates a new FITS file, containing a FITS image. An -`EXPOSURE' keyword is written to the header, then the image data are -written to the FITS file before closing the FITS file. -- -#include "fitsio.h" /* required by every program that uses CFITSIO */ -main() -{ - fitsfile *fptr; /* pointer to the FITS file; defined in fitsio.h */ - int status, ii, jj; - long fpixel = 1, naxis = 2, nelements, exposure; - long naxes[2] = { 300, 200 }; /* image is 300 pixels wide by 200 rows */ - short array[200][300]; - - status = 0; /* initialize status before calling fitsio routines */ - fits_create_file(&fptr, "testfile.fits", &status); /* create new file */ - - /* Create the primary array image (16-bit short integer pixels */ - fits_create_img(fptr, SHORT_IMG, naxis, naxes, &status); - - /* Write a keyword; must pass the ADDRESS of the value */ - exposure = 1500.; - fits_update_key(fptr, TLONG, "EXPOSURE", &exposure, - "Total Exposure Time", &status); - - /* Initialize the values in the image with a linear ramp function */ - for (jj = 0; jj < naxes[1]; jj++) - for (ii = 0; ii < naxes[0]; ii++) - array[jj][ii] = ii + jj; - - nelements = naxes[0] * naxes[1]; /* number of pixels to write */ - - /* Write the array of integers to the image */ - fits_write_img(fptr, TSHORT, fpixel, nelements, array[0], &status); - - fits_close_file(fptr, &status); /* close the file */ - - fits_report_error(stderr, status); /* print out any error messages */ - return( status ); -} -- - -*III. A FITS Primer - -This section gives a brief overview of the structure of FITS files. -Users should refer to the documentation available from the FITS Support OFfice, -as described in the introduction, for more detailed information on FITS -formats. - -FITS was first developed in the late 1970's as a standard data -interchange format between various astronomical observatories. Since -then FITS has become the standard data format supported by most -astronomical data analysis software packages. - -A FITS file consists of one or more Header + Data Units (HDUs), where -the first HDU is called the `Primary HDU', or `Primary Array'. The -primary array contains an N-dimensional array of pixels, such as a 1-D -spectrum, a 2-D image, or a 3-D data cube. Six different primary -data types are supported: Unsigned 8-bit bytes, 16-bit, 32-bit, and 64-bit signed -integers, and 32 and 64-bit floating point reals. FITS also has a -convention for storing 16 and 32-bit unsigned integers (see the later -section entitled `Unsigned Integers' for more details). The primary HDU -may also consist of only a header with a null array containing no -data pixels. - -Any number of additional HDUs may follow the primary array; these -additional HDUs are called FITS `extensions'. There are currently 3 -types of extensions defined by the FITS standard: - -\begin{itemize} -\item - Image Extension - a N-dimensional array of pixels, like in a primary array -\item - ASCII Table Extension - rows and columns of data in ASCII character format -\item - Binary Table Extension - rows and columns of data in binary representation -\end{itemize} - -In each case the HDU consists of an ASCII Header Unit followed by an optional -Data Unit. For historical reasons, each Header or Data unit must be an -exact multiple of 2880 8-bit bytes long. Any unused space is padded -with fill characters (ASCII blanks or zeros). - -Each Header Unit consists of any number of 80-character keyword records -or `card images' which have the -general form: -- - KEYNAME = value / comment string - NULLKEY = / comment: This keyword has no value -- -The keyword names may be up to 8 characters long and can only contain -uppercase letters, the digits 0-9, the hyphen, and the underscore -character. The keyword name is (usually) followed by an equals sign and -a space character (= ) in columns 9 - 10 of the record, followed by the -value of the keyword which may be either an integer, a floating point -number, a character string (enclosed in single quotes), or a boolean -value (the letter T or F). A keyword may also have a null or undefined -value if there is no specified value string, as in the second example, above - -The last keyword in the header is always the `END' keyword which has no -value or comment fields. There are many rules governing the exact -format of a keyword record (see the FITS Standard) so it is better -to rely on standard interface software like CFITSIO to correctly -construct or to parse the keyword records rather than try to deal -directly with the raw FITS formats. - -Each Header Unit begins with a series of required keywords which depend -on the type of HDU. These required keywords specify the size and -format of the following Data Unit. The header may contain other -optional keywords to describe other aspects of the data, such as the -units or scaling values. Other COMMENT or HISTORY keywords are also -frequently added to further document the data file. - -The optional Data Unit immediately follows the last 2880-byte block in -the Header Unit. Some HDUs do not have a Data Unit and only consist of -the Header Unit. - -If there is more than one HDU in the FITS file, then the Header Unit of -the next HDU immediately follows the last 2880-byte block of the -previous Data Unit (or Header Unit if there is no Data Unit). - -The main required keywords in FITS primary arrays or image extensions are: -\begin{itemize} -\item -BITPIX -- defines the data type of the array: 8, 16, 32, 64, -32, -64 for -unsigned 8--bit byte, 16--bit signed integer, 32--bit signed integer, -32--bit IEEE floating point, and 64--bit IEEE double precision floating -point, respectively. -\item -NAXIS -- the number of dimensions in the array, usually 0, 1, 2, 3, or 4. -\item -NAXISn -- (n ranges from 1 to NAXIS) defines the size of each dimension. -\end{itemize} - -FITS tables start with the keyword XTENSION = `TABLE' (for ASCII -tables) or XTENSION = `BINTABLE' (for binary tables) and have the -following main keywords: -\begin{itemize} -\item -TFIELDS -- number of fields or columns in the table -\item -NAXIS2 -- number of rows in the table -\item -TTYPEn -- for each column (n ranges from 1 to TFIELDS) gives the -name of the column -\item -TFORMn -- the data type of the column -\item -TUNITn -- the physical units of the column (optional) -\end{itemize} - -Users should refer to the FITS Support Office at {\tt http://fits.gsfc.nasa.gov} -for further information about the FITS format and related software -packages. - - -*IV. Programming Guidelines - -**A. CFITSIO Definitions - -Any program that uses the CFITSIO interface must include the fitsio.h -header file with the statement -- - #include "fitsio.h" -- -This header file contains the prototypes for all the CFITSIO user -interface routines as well as the definitions of various constants used -in the interface. It also defines a C structure of type `fitsfile' -that is used by CFITSIO to store the relevant parameters that define -the format of a particular FITS file. Application programs must define -a pointer to this structure for each FITS file that is to be opened. -This structure is initialized (i.e., memory is allocated for the -structure) when the FITS file is first opened or created with the -fits\_open\_file or fits\_create\_file routines. This fitsfile pointer -is then passed as the first argument to every other CFITSIO routine -that operates on the FITS file. Application programs must not directly -read or write elements in this fitsfile structure because the -definition of the structure may change in future versions of CFITSIO. - -A number of symbolic constants are also defined in fitsio.h for the -convenience of application programmers. Use of these symbolic -constants rather than the actual numeric value will help to make the -source code more readable and easier for others to understand. -- -String Lengths, for use when allocating character arrays: - - #define FLEN_FILENAME 1025 /* max length of a filename */ - #define FLEN_KEYWORD 72 /* max length of a keyword */ - #define FLEN_CARD 81 /* max length of a FITS header card */ - #define FLEN_VALUE 71 /* max length of a keyword value string */ - #define FLEN_COMMENT 73 /* max length of a keyword comment string */ - #define FLEN_ERRMSG 81 /* max length of a CFITSIO error message */ - #define FLEN_STATUS 31 /* max length of a CFITSIO status text string */ - - Note that FLEN_KEYWORD is longer than the nominal 8-character keyword - name length because the HIERARCH convention supports longer keyword names. - -Access modes when opening a FITS file: - - #define READONLY 0 - #define READWRITE 1 - -BITPIX data type code values for FITS images: - - #define BYTE_IMG 8 /* 8-bit unsigned integers */ - #define SHORT_IMG 16 /* 16-bit signed integers */ - #define LONG_IMG 32 /* 32-bit signed integers */ - #define LONGLONG_IMG 64 /* 64-bit signed integers */ - #define FLOAT_IMG -32 /* 32-bit single precision floating point */ - #define DOUBLE_IMG -64 /* 64-bit double precision floating point */ - - The following 4 data type codes are also supported by CFITSIO: - #define SBYTE_IMG 10 /* 8-bit signed integers, equivalent to */ - /* BITPIX = 8, BSCALE = 1, BZERO = -128 */ - #define USHORT_IMG 20 /* 16-bit unsigned integers, equivalent to */ - /* BITPIX = 16, BSCALE = 1, BZERO = 32768 */ - #define ULONG_IMG 40 /* 32-bit unsigned integers, equivalent to */ - /* BITPIX = 32, BSCALE = 1, BZERO = 2147483648 */ - -Codes for the data type of binary table columns and/or for the -data type of variables when reading or writing keywords or data: - - DATATYPE TFORM CODE - #define TBIT 1 /* 'X' */ - #define TBYTE 11 /* 8-bit unsigned byte, 'B' */ - #define TLOGICAL 14 /* logicals (int for keywords */ - /* and char for table cols 'L' */ - #define TSTRING 16 /* ASCII string, 'A' */ - #define TSHORT 21 /* signed short, 'I' */ - #define TLONG 41 /* signed long, */ - #define TLONGLONG 81 /* 64-bit long signed integer 'K' */ - #define TFLOAT 42 /* single precision float, 'E' */ - #define TDOUBLE 82 /* double precision float, 'D' */ - #define TCOMPLEX 83 /* complex (pair of floats) 'C' */ - #define TDBLCOMPLEX 163 /* double complex (2 doubles) 'M' */ - - The following data type codes are also supported by CFITSIO: - #define TINT 31 /* int */ - #define TSBYTE 12 /* 8-bit signed byte, 'S' */ - #define TUINT 30 /* unsigned int 'V' */ - #define TUSHORT 20 /* unsigned short 'U' */ - #define TULONG 40 /* unsigned long */ - - The following data type code is only for use with fits\_get\_coltype - #define TINT32BIT 41 /* signed 32-bit int, 'J' */ - - -HDU type code values (value returned when moving to new HDU): - - #define IMAGE_HDU 0 /* Primary Array or IMAGE HDU */ - #define ASCII_TBL 1 /* ASCII table HDU */ - #define BINARY_TBL 2 /* Binary table HDU */ - #define ANY_HDU -1 /* matches any type of HDU */ - -Column name and string matching case-sensitivity: - - #define CASESEN 1 /* do case-sensitive string match */ - #define CASEINSEN 0 /* do case-insensitive string match */ - -Logical states (if TRUE and FALSE are not already defined): - - #define TRUE 1 - #define FALSE 0 - -Values to represent undefined floating point numbers: - - #define FLOATNULLVALUE -9.11912E-36F - #define DOUBLENULLVALUE -9.1191291391491E-36 - -Image compression algorithm definitions - - #define RICE_1 11 - #define GZIP_1 21 - #define GZIP_2 22 - #define PLIO_1 31 - #define HCOMPRESS_1 41 - #define NOCOMPRESS -1 - - #define NO_DITHER -1 - #define SUBTRACTIVE_DITHER_1 1 - #define SUBTRACTIVE_DITHER_2 2 -- - -**B. Current Header Data Unit (CHDU) - -The concept of the Current Header and Data Unit, or CHDU, is -fundamental to the use of the CFITSIO library. A simple FITS image may -only contain a single Header and Data unit (HDU), but in general FITS -files can contain multiple Header Data Units (also known as -`extensions'), concatenated one after the other in the file. The user -can specify which HDU should be initially opened at run time by giving -the HDU name or number after the root file name. For example, -'myfile.fits[4]' opens the 5th HDU in the file (note that the numbering -starts with 0), and 'myfile.fits[EVENTS] opens the HDU with the name -'EVENTS' (as defined by the EXTNAME or HDUNAME keywords). If no HDU is -specified then CFITSIO opens the first HDU (the primary array) by -default. The CFITSIO routines which read and write data only operate -within the opened HDU, Other CFITSIO routines are provided to move to -and open any other existing HDU within the FITS file or to append or -insert new HDUs in the FITS file. - -**C. Function Names and Variable Datatypes - -Most of the CFITSIO routines have both a short name as well as a -longer descriptive name. The short name is only 5 or 6 characters long -and is similar to the subroutine name in the Fortran-77 version of -FITSIO. The longer name is more descriptive and it is recommended that -it be used instead of the short name to more clearly document the -source code. - -Many of the CFITSIO routines come in families which differ only in the -data type of the associated parameter(s). The data type of these -routines is indicated by the suffix of the routine name. The short -routine names have a 1 or 2 character suffix (e.g., 'j' in 'ffpkyj') -while the long routine names have a 4 character or longer suffix -as shown in the following table: -- - Long Short Data - Names Names Type - ----- ----- ---- - _bit x bit - _byt b unsigned byte - _sbyt sb signed byte - _sht i short integer - _lng j long integer - _lnglng jj 8-byte LONGLONG integer (see note below) - _usht ui unsigned short integer - _ulng uj unsigned long integer - _uint uk unsigned int integer - _int k int integer - _flt e real exponential floating point (float) - _fixflt f real fixed-decimal format floating point (float) - _dbl d double precision real floating-point (double) - _fixdbl g double precision fixed-format floating point (double) - _cmp c complex reals (pairs of float values) - _fixcmp fc complex reals, fixed-format floating point - _dblcmp m double precision complex (pairs of double values) - _fixdblcmp fm double precision complex, fixed-format floating point - _log l logical (int) - _str s character string -- - -The logical data type corresponds to `int' for logical keyword values, -and `byte' for logical binary table columns. In other words, the value -when writing a logical keyword must be stored in an `int' variable, and -must be stored in a `char' array when reading or writing to `L' columns -in a binary table. Implicit data type conversion is not supported for -logical table columns, but is for keywords, so a logical keyword may be -read and cast to any numerical data type; a returned value = 0 -indicates false, and any other value = true. - -The `int' data type may be 2 bytes long on some old PC compilers, -but otherwise it is nearly always 4 bytes long. Some 64-bit -machines, like the Alpha/OSF, define the `short', `int', -and `long' integer data types to be 2, 4, and 8 bytes long, -respectively. - -Because there is no universal C compiler standard for the name of the -8-byte integer datatype, the fitsio.h include file typedef's -'LONGLONG' to be equivalent to an -appropriate 8-byte integer data type on each supported platform. -For maximum software portability it is recommended that -this LONGLONG datatype be used to define 8-byte integer variables -rather than using the native data type name on a particular -platform. On most -32-bit Unix and Mac OS-X operating systems LONGLONG is equivalent to the -intrinsic 'long long' 8-byte integer datatype. On 64-bit systems (which currently -includes Alpha OSF/1, 64-bit Sun Solaris, 64-bit SGI MIPS, and 64-bit -Itanium and Opteron PC systems), LONGLONG is simply typedef'ed to be -equivalent to 'long'. Microsoft Visual C++ Version 6.0 does not define -a 'long long' data type, so LONGLONG is typedef'ed to be equivalent to -the '\_\_int64' data type on 32-bit windows systems when using Visual C++. - -A related issue that affects the portability of software is how to print -out the value of a 'LONGLONG' variable with printf. Developers may -find it convenient to use the following preprocessing statements -in their C programs to handle this in a machine-portable manner: - -- -#if defined(_MSC_VER) /* Microsoft Visual C++ */ - printf("%I64d", longlongvalue); - -#elif (USE_LL_SUFFIX == 1) - printf("%lld", longlongvalue); - -#else - printf("%ld", longlongvalue); -#endif -- - -Similarly, the name of the C utility routine that converts a character -string of digits into a 8-byte integer value is platform dependent: - -- -#if defined(_MSC_VER) /* Microsoft Visual C++ */ - /* VC++ 6.0 does not seem to have an 8-byte conversion routine */ - -#elif (USE_LL_SUFFIX == 1) - longlongvalue = atoll(*string); - -#else - longlongvalue = atol(*string); -#endif -- - -When dealing with the FITS byte data type it is important to remember -that the raw values (before any scaling by the BSCALE and BZERO, or -TSCALn and TZEROn keyword values) in byte arrays (BITPIX = 8) or byte -columns (TFORMn = 'B') are interpreted as unsigned bytes with values -ranging from 0 to 255. Some C compilers define a 'char' variable as -signed, so it is important to explicitly declare a numeric char -variable as 'unsigned char' to avoid any ambiguity - -One feature of the CFITSIO routines is that they can operate on a `X' -(bit) column in a binary table as though it were a `B' (byte) column. -For example a `11X' data type column can be interpreted the same as a -`2B' column (i.e., 2 unsigned 8-bit bytes). In some instances, it can -be more efficient to read and write whole bytes at a time, rather than -reading or writing each individual bit. - -The complex and double precision complex data types are not directly -supported in ANSI C so these data types should be interpreted as pairs -of float or double values, respectively, where the first value in each -pair is the real part, and the second is the imaginary part. - -**D. Support for Unsigned Integers and Signed Bytes - -Although FITS does not directly support unsigned integers as one of its -fundamental data types, FITS can still be used to efficiently store -unsigned integer data values in images and binary tables. The -convention used in FITS files is to store the unsigned integers as -signed integers with an associated offset (specified by the BZERO or -TZEROn keyword). For example, to store unsigned 16-bit integer values -in a FITS image the image would be defined as a signed 16-bit integer -(with BITPIX keyword = SHORT\_IMG = 16) with the keywords BSCALE = 1.0 -and BZERO = 32768. Thus the unsigned values of 0, 32768, and 65535, -for example, are physically stored in the FITS image as -32768, 0, and -32767, respectively; CFITSIO automatically adds the BZERO offset to -these values when they are read. Similarly, in the case of unsigned -32-bit integers the BITPIX keyword would be equal to LONG\_IMG = 32 and -BZERO would be equal to 2147483648 (i.e. 2 raised to the 31st power). - -The CFITSIO interface routines will efficiently and transparently apply -the appropriate offset in these cases so in general application -programs do not need to be concerned with how the unsigned values are -actually stored in the FITS file. As a convenience for users, CFITSIO -has several predefined constants for the value of BITPIX (USHORT\_IMG, -ULONG\_IMG) and for the TFORMn value in the case of binary tables (`U' -and `V') which programmers can use when creating FITS files containing -unsigned integer values. The following code fragment illustrates how -to write a FITS 1-D primary array of unsigned 16-bit integers: -- - unsigned short uarray[100]; - int naxis, status; - long naxes[10], group, firstelem, nelements; - ... - status = 0; - naxis = 1; - naxes[0] = 100; - fits_create_img(fptr, USHORT_IMG, naxis, naxes, &status); - - firstelem = 1; - nelements = 100; - fits_write_img(fptr, TUSHORT, firstelem, nelements, - uarray, &status); - ... -- -In the above example, the 2nd parameter in fits\_create\_img tells -CFITSIO to write the header keywords appropriate for an array of 16-bit -unsigned integers (i.e., BITPIX = 16 and BZERO = 32768). Then the -fits\_write\_img routine writes the array of unsigned short integers -(uarray) into the primary array of the FITS file. Similarly, a 32-bit -unsigned integer image may be created by setting the second parameter -in fits\_create\_img equal to `ULONG\_IMG' and by calling the -fits\_write\_img routine with the second parameter = TULONG to write -the array of unsigned long image pixel values. - -An analogous set of routines are available for reading or writing unsigned -integer values and signed byte values in a FITS binary table extension. -When specifying the TFORMn keyword value which defines the format of a -column, CFITSIO recognized 3 additional data type codes besides those -already defined in the FITS standard: `U' meaning a 16-bit unsigned -integer column, `V' for a 32-bit unsigned integer column, and 'S' -for a signed byte column. These non-standard data type codes are not -actually written into the FITS file but instead are just used internally -within CFITSIO. The following code fragment illustrates how to use -these features: -- - unsigned short uarray[100]; - unsigned int varray[100]; - - int colnum, tfields, status; - long nrows, firstrow, firstelem, nelements, pcount; - - char extname[] = "Test_table"; /* extension name */ - - /* define the name, data type, and physical units for the 2 columns */ - char *ttype[] = { "Col_1", "Col_2", "Col_3" }; - char *tform[] = { "1U", "1V", "1S"}; /* special CFITSIO codes */ - char *tunit[] = { " ", " ", " " }; - ... - - /* write the header keywords */ - status = 0; - nrows = 1; - tfields = 3 - pcount = 0; - fits_create_tbl(fptr, BINARY_TBL, nrows, tfields, ttype, tform, - tunit, extname, &status); - - /* write the unsigned shorts to the 1st column */ - colnum = 1; - firstrow = 1; - firstelem = 1; - nelements = 100; - fits_write_col(fptr, TUSHORT, colnum, firstrow, firstelem, - nelements, uarray, &status); - - /* now write the unsigned longs to the 2nd column */ - colnum = 2; - fits_write_col(fptr, TUINT, colnum, firstrow, firstelem, - nelements, varray, &status); - ... -- -Note that the non-standard TFORM values for the 3 columns, `U' and `V', -tell CFITSIO to write the keywords appropriate for unsigned 16-bit and -unsigned 32-bit integers, respectively (i.e., TFORMn = '1I' and TZEROn -= 32768 for unsigned 16-bit integers, and TFORMn = '1J' and TZEROn = -2147483648 for unsigned 32-bit integers). The 'S' TFORMn value tells -CFITSIO to write the keywords appropriate for a signed 8-bit byte column -with TFORMn = '1B' and TZEROn = -128. The calls to fits\_write\_col -then write the arrays of unsigned integer values to the columns. - -**E. Dealing with Character Strings - -The character string values in a FITS header or in an ASCII column in a -FITS table extension are generally padded out with non-significant -space characters (ASCII 32) to fill up the header record or the column -width. When reading a FITS string value, the CFITSIO routines will -strip off these non-significant trailing spaces and will return a -null-terminated string value containing only the significant -characters. Leading spaces in a FITS string are considered -significant. If the string contains all blanks, then CFITSIO will -return a single blank character, i.e, the first blank is considered to -be significant, since it distinguishes the string from a null or -undefined string, but the remaining trailing spaces are not -significant. - -Similarly, when writing string values to a FITS file the -CFITSIO routines expect to get a null-terminated string as input; -CFITSIO will pad the string with blanks if necessary when writing it -to the FITS file. - -When calling CFITSIO routines that return a character string it is -vital that the size of the char array be large enough to hold the -entire string of characters, otherwise CFITSIO will overwrite whatever -memory locations follow the char array, possibly causing the program to -execute incorrectly. This type of error can be difficult to debug, so -programmers should always ensure that the char arrays are allocated -enough space to hold the longest possible string, {\bf including} the -terminating NULL character. The fitsio.h file contains the following -defined constants which programmers are strongly encouraged to use -whenever they are allocating space for char arrays: -- -#define FLEN_FILENAME 1025 /* max length of a filename */ -#define FLEN_KEYWORD 72 /* max length of a keyword */ -#define FLEN_CARD 81 /* length of a FITS header card */ -#define FLEN_VALUE 71 /* max length of a keyword value string */ -#define FLEN_COMMENT 73 /* max length of a keyword comment string */ -#define FLEN_ERRMSG 81 /* max length of a CFITSIO error message */ -#define FLEN_STATUS 31 /* max length of a CFITSIO status text string */ -- -For example, when declaring a char array to hold the value string -of FITS keyword, use the following statement: -- - char value[FLEN_VALUE]; -- -Note that FLEN\_KEYWORD is longer than needed for the nominal 8-character -keyword name because the HIERARCH convention supports longer keyword names. - -**F. Implicit Data Type Conversion - -The CFITSIO routines that read and write numerical data can perform -implicit data type conversion. This means that the data type of the -variable or array in the program does not need to be the same as the -data type of the value in the FITS file. Data type conversion is -supported for numerical and string data types (if the string contains a -valid number enclosed in quotes) when reading a FITS header keyword -value and for numeric values when reading or writing values in the -primary array or a table column. CFITSIO returns status = -NUM\_OVERFLOW if the converted data value exceeds the range of the -output data type. Implicit data type conversion is not supported -within binary tables for string, logical, complex, or double complex -data types. - -In addition, any table column may be read as if it contained string values. -In the case of numeric columns the returned string will be formatted -using the TDISPn display format if it exists. - -**G. Data Scaling - -When reading numerical data values in the primary array or a -table column, the values will be scaled automatically by the BSCALE and -BZERO (or TSCALn and TZEROn) header values if they are -present in the header. The scaled data that is returned to the reading -program will have -- - output value = (FITS value) * BSCALE + BZERO -- -(a corresponding formula using TSCALn and TZEROn is used when reading -from table columns). In the case of integer output values the floating -point scaled value is truncated to an integer (not rounded to the -nearest integer). The fits\_set\_bscale and fits\_set\_tscale routines -(described in the `Advanced' chapter) may be used to override the -scaling parameters defined in the header (e.g., to turn off the scaling -so that the program can read the raw unscaled values from the FITS -file). - -When writing numerical data to the primary array or to a table column -the data values will generally be automatically inversely scaled by the -value of the BSCALE and BZERO (or TSCALn and TZEROn) keyword values if -they they exist in the header. These keywords must have been written -to the header before any data is written for them to have any immediate -effect. One may also use the fits\_set\_bscale and fits\_set\_tscale -routines to define or override the scaling keywords in the header -(e.g., to turn off the scaling so that the program can write the raw -unscaled values into the FITS file). If scaling is performed, the -inverse scaled output value that is written into the FITS file will -have -- - FITS value = ((input value) - BZERO) / BSCALE -- -(a corresponding formula using TSCALn and TZEROn is used when -writing to table columns). Rounding to the nearest integer, rather -than truncation, is performed when writing integer data types to the -FITS file. - -**H. Support for IEEE Special Values - -The ANSI/IEEE-754 floating-point number standard defines certain -special values that are used to represent such quantities as -Not-a-Number (NaN), denormalized, underflow, overflow, and infinity. -(See the Appendix in the FITS standard or the FITS User's -Guide for a list of these values). The CFITSIO routines that read -floating point data in FITS files recognize these IEEE special values -and by default interpret the overflow and infinity values as being -equivalent to a NaN, and convert the underflow and denormalized values -into zeros. In some cases programmers may want access to the raw IEEE -values, without any modification by CFITSIO. This can be done by -calling the fits\_read\_img or fits\_read\_col routines while -specifying 0.0 as the value of the NULLVAL parameter. This will force -CFITSIO to simply pass the IEEE values through to the application -program without any modification. This is not fully supported on -VAX/VMS machines, however, where there is no easy way to bypass the -default interpretation of the IEEE special values. This is also not -supported when reading floating-point images that have been compressed -with the FITS tiled image compression convention that is discussed in -section 5.6; the pixels values in tile compressed images are -represented by scaled integers, and a reserved integer value -(not a NaN) is used to represent undefined pixels. - -**I. Error Status Values and the Error Message Stack - -Nearly all the CFITSIO routines return an error status value -in 2 ways: as the value of the last parameter in the function call, -and as the returned value of the function itself. This provides -some flexibility in the way programmers can test if an error -occurred, as illustrated in the following 2 code fragments: -- - if ( fits_write_record(fptr, card, &status) ) - printf(" Error occurred while writing keyword."); - -or, - - fits_write_record(fptr, card, &status); - if ( status ) - printf(" Error occurred while writing keyword."); -- -A listing of all the CFITSIO status code values is given at the end of -this document. Programmers are encouraged to use the symbolic -mnemonics (defined in fitsio.h) rather than the actual integer status -values to improve the readability of their code. - -The CFITSIO library uses an `inherited status' convention for the -status parameter which means that if a routine is called with a -positive input value of the status parameter as input, then the routine -will exit immediately without changing the value of the status -parameter. Thus, if one passes the status value returned from each -CFITSIO routine as input to the next CFITSIO routine, then whenever an -error is detected all further CFITSIO processing will cease. This -convention can simplify the error checking in application programs -because it is not necessary to check the value of the status parameter -after every single CFITSIO routine call. If a program contains a -sequence of several CFITSIO calls, one can just check the status value -after the last call. Since the returned status values are generally -distinctive, it should be possible to determine which routine -originally returned the error status. - -CFITSIO also maintains an internal stack of error messages -(80-character maximum length) which in many cases provide a more -detailed explanation of the cause of the error than is provided by the -error status number alone. It is recommended that the error message -stack be printed out whenever a program detects a CFITSIO error. The -function fits\_report\_error will print out the entire error message -stack, or alternatively one may call fits\_read\_errmsg to get the -error messages one at a time. - -**J. Variable-Length Arrays in Binary Tables - -CFITSIO provides easy-to-use support for reading and writing data in -variable length fields of a binary table. The variable length columns -have TFORMn keyword values of the form `1Pt(len)' or `1Qt(len)' where `t' -is the data type code (e.g., I, J, E, D, etc.) and `len' is an integer -specifying the maximum length of the vector in the table. The 'P' type -variable length columns use 32-bit array length and byte offset values, whereas -the 'Q' type columns use 64-bit values, which may be required when dealing -with large arrays. CFITSIO supports a local convention that interprets -the 'P' type descriptors as unsigned 32-bit integers, which provides -a factor of 2 greater range for the array length or heap address than -is possible with 32-bit 'signed' integers. Note, however, that other software -packages may not support this convention, and may be unable to read thees -extended range variable length records. - -If the value -of `len' is not specified when the table is created (e.g., if the TFORM -keyword value is simply specified as '1PE' instead of '1PE(400) ), then -CFITSIO will automatically scan the table when it is closed to -determine the maximum length of the vector and will append this value -to the TFORMn value. - -The same routines that read and write data in an ordinary fixed length -binary table extension are also used for variable length fields, -however, the routine parameters take on a slightly different -interpretation as described below. - -All the data in a variable length field is written into an area called -the `heap' which follows the main fixed-length FITS binary table. The -size of the heap, in bytes, is specified by the PCOUNT keyword in the -FITS header. When creating a new binary table, the initial value of -PCOUNT should usually be set to zero. CFITSIO will recompute the size -of the heap as the data is written and will automatically update the -PCOUNT keyword value when the table is closed. When writing variable -length data to a table, CFITSIO will automatically extend the size -of the heap area if necessary, so that any following HDUs do not -get overwritten. - -By default the heap data area starts immediately after the last row of -the fixed-length table. This default starting location may be -overridden by the THEAP keyword, but this is not recommended. -If additional rows of data are added to the table, CFITSIO will -automatically shift the the heap down to make room for the new -rows, but it is obviously be more efficient to initially -create the table with the necessary number of blank rows, so that -the heap does not needed to be constantly moved. - -When writing row of data to a variable length field the entire array of values for -a given row of the table must be written with a single call to -fits\_write\_col. -The total length of the array is given by nelements -+ firstelem - 1. Additional elements cannot be appended to an existing -vector at a later time since any attempt to do so will simply overwrite -all the previously written data and the new data will be -written to a new area of the heap. The fits\_compress\_heap routine -is provided to compress the heap and recover any unused space. -To avoid having to deal with this issue, it is recommended -that rows in a variable length field should only be written once. -An exception to -this general rule occurs when setting elements of an array as -undefined. It is allowed to first write a dummy value into the array with -fits\_write\_col, and then call fits\_write\_col\_nul to flag the -desired elements as undefined. Note that the rows of a table, -whether fixed or variable length, do not have to be written -consecutively and may be written in any order. - -When writing to a variable length ASCII character field (e.g., TFORM = -'1PA') only a single character string can be written. The `firstelem' -and `nelements' parameter values in the fits\_write\_col routine are -ignored and the number of characters to write is simply determined by -the length of the input null-terminated character string. - -The fits\_write\_descript routine is useful in situations where -multiple rows of a variable length column have the identical array of -values. One can simply write the array once for the first row, and -then use fits\_write\_descript to write the same descriptor values into -the other rows; all the rows will then point to the same storage -location thus saving disk space. - -When reading from a variable length array field one can only read as -many elements as actually exist in that row of the table; reading does -not automatically continue with the next row of the table as occurs -when reading an ordinary fixed length table field. Attempts to read -more than this will cause an error status to be returned. One can -determine the number of elements in each row of a variable column with -the fits\_read\_descript routine. - -**K. Multiple Access to the Same FITS File - -CFITSIO supports simultaneous read and write access to different -HDUs in the same FITS file in some circumstances, as described -below: - -\begin{itemize} - -\item -Multi-threaded programs - -When CFITSIO is compiled with the -D\_REENTRANT directive (as can be -tested with the fits\_is\_reentrant function) different threads can -call any of the CFITSIO routines to simultaneously read or write -separate FITS files. Multiple threads can also read data from the -same FITS file simultaneously, as long as the file was opened -independently by each thread. This relies on the operating system -to correctly deal with reading the same file by multiple processes. -Different threads should not share the same 'fitsfile' pointer to -read an opened FITS file, unless locks are placed around the calls -to the CFITSIO reading routines. Different threads should never -try to write to the same FITS file. - -\item -Multiple read access to the same FITS file within a single -program/thread - -A single process may open the same FITS file with READONLY access -multiple times, and thus create multiple 'fitsfile*' pointers to -that same file within CFITSIO. This relies on the operating system's -ability to open a single file multiple times and correctly manage -the subsequent read requests directed to the different C 'file*' -pointers, which actually all point to the same file. CFITSIO simply -executes the read requests to the differnet 'fitsfile*' pointers the -same as if they were physically different files. - -\item -Multiple write access to the same FITS file within a single -program/thread - -CFITSIO supports opening the same FITS file multiple times with -WRITE access, but it only physically opens the file (at the -operating system level) once, on the first call to fits\_open\_file. -If fits\_open\_file is subsequently called to open the same file -again, CFITSIO will recognize that the file is already open, and -will return a new 'fitsfile*' pointer that logically points to the -first 'fitsfile*' pointer, without actually opening the file a -second time. The application program can then treat the 2 -'fitsfile*' pointers as if they point to different files, and can -seemingly move to and write data to 2 different HDUs within the -same file. However, each time the application program switches -which 'fitsfile*' pointer it is writing to, CFITSIO will flush any -internal buffers that contain data written to the first 'fitsfile*' -pointer, then move to the HDU that the other 'fitsfile*' pointer -is writing to. Obviously, this may add a significant amount of -computational overhead if the application program uses this feature -to frequently switch back and forth between writing to 2 (or more) -HDUs in the same file, so this capability should be used -judiciously. - -Note that CFITSIO will not allow a FITS file to be opened a second -time with READWRITE access if it was opened previously with READONLY -access. - -\end{itemize} - -**L. When the Final Size of the FITS HDU is Unknown - -It is not required to know the total size of a FITS data array or table -before beginning to write the data to the FITS file. In the case of -the primary array or an image extension, one should initially create -the array with the size of the highest dimension (largest NAXISn -keyword) set to a dummy value, such as 1. Then after all the data have -been written and the true dimensions are known, then the NAXISn value -should be updated using the fits\_update\_key routine before moving to -another extension or closing the FITS file. - -When writing to FITS tables, CFITSIO automatically keeps track of the -highest row number that is written to, and will increase the size of -the table if necessary. CFITSIO will also automatically insert space -in the FITS file if necessary, to ensure that the data 'heap', if it -exists, and/or any additional HDUs that follow the table do not get -overwritten as new rows are written to the table. - -As a general rule it is best to specify the initial number of rows = 0 -when the table is created, then let CFITSIO keep track of the number of -rows that are actually written. The application program should not -manually update the number of rows in the table (as given by the NAXIS2 -keyword) since CFITSIO does this automatically. If a table is -initially created with more than zero rows, then this will usually be -considered as the minimum size of the table, even if fewer rows are -actually written to the table. Thus, if a table is initially created -with NAXIS2 = 20, and CFITSIO only writes 10 rows of data before -closing the table, then NAXIS2 will remain equal to 20. If however, 30 -rows of data are written to this table, then NAXIS2 will be increased -from 20 to 30. The one exception to this automatic updating of the -NAXIS2 keyword is if the application program directly modifies the -value of NAXIS2 (up or down) itself just before closing the table. In this -case, CFITSIO does not update NAXIS2 again, since it assumes that the -application program must have had a good reason for changing the value -directly. This is not recommended, however, and is only provided for -backward compatibility with software that initially creates a table -with a large number of rows, than decreases the NAXIS2 value to the -actual smaller value just before closing the table. - -**M. CFITSIO Size Limitations - -CFITSIO places very few restrictions on the size of FITS files that it -reads or writes. There are a few limits, however, that may affect -some extreme cases: - -1. The maximum number of FITS files that may be simultaneously opened by -CFITSIO is set by NMAXFILES, as defined in fitsio2.h. The current default -value is 1000, but this may be increased if necessary. Note that CFITSIO -allocates NIOBUF * 2880 bytes of I/O buffer space for each file that is -opened. The default value of NIOBUF is 40 (defined in fitsio.h), so this -amounts to more than 115K of memory for each opened file (or 115 MB for -1000 opened files). Note that the underlying operating system, may have a -lower limit on the number of files that can be opened simultaneously. - -2. It used to be common for computer systems to only support disk files up -to 2**31 bytes = 2.1 GB in size, but most systems now support larger files. -CFITSIO can optionally read and write these so-called 'large files' that -are greater than 2.1 GB on -platforms where they are supported, but this -usually requires that special compiler option flags be specified to turn -on this option. On linux and solaris systems the compiler flags are -'-D\_LARGEFILE\_SOURCE' and `-D\_FILE\_OFFSET\_BITS=64'. These flags -may also work on other platforms but this has not been tested. Starting -with version 3.0 of CFITSIO, the default Makefile that is distributed -with CFITSIO will include these 2 compiler flags when building on Solaris -and Linux PC systems. Users on other platforms will need to add these -compiler flags manually if they want to support large files. In most -cases it appears that it is not necessary to include these compiler -flags when compiling application code that call the CFITSIO library -routines. - -When CFITSIO is built with large file support (e.g., on Solaris and -Linux PC system by default) then it can read and write FITS data files -on disk that have any of these conditions: - -\begin{itemize} -\item -FITS files larger than 2.1 GB in size -\item -FITS images containing greater than 2.1 G pixels -\item -FITS images that have one dimension with more than 2.1 G pixels -(as given by one of the NAXISn keyword) -\item -FITS tables containing more than 2.1E09 rows (given by the NAXIS2 keyword), -or with rows that are more than 2.1 GB wide (given by the NAXIS1 keyword) -\item -FITS binary tables with a variable-length array heap that is larger -than 2.1 GB (given by the PCOUNT keyword) -\end{itemize} - -The current maximum FITS file size supported by CFITSIO -is about 6 terabytes (containing -2**31 FITS blocks, each 2880 bytes in size). Currently, support for large -files in CFITSIO has been tested on the Linux, Solaris, and IBM AIX -operating systems. - -Note that when writing application programs that are intended to support -large files it is important to use 64-bit integer variables -to store quantities such as the dimensions of images, or the number of -rows in a table. These programs must also call the special versions -of some of the CFITSIO routines that have been adapted to -support 64-bit integers. The names of these routines end in -'ll' ('el' 'el') to distinguish them from the 32-bit integer -version (e.g., fits\_get\_num\_rowsll). - - -*V. Basic CFITSIO Interface Routines - -This chapter describes the basic routines in the CFITSIO user interface -that provide all the functions normally needed to read and write most -FITS files. It is recommended that these routines be used for most -applications and that the more advanced routines described in the -next chapter only be used in special circumstances when necessary. - -The following conventions are used in this chapter in the description -of each function: - -1. Most functions have 2 names: a long descriptive name and a short -concise name. Both names are listed on the first line of the following -descriptions, separated by a slash (/) character. Programmers may use -either name in their programs but the long names are recommended to -help document the code and make it easier to read. - -2. A right arrow symbol ($>$) is used in the function descriptions to -separate the input parameters from the output parameters in the -definition of each routine. This symbol is not actually part of the C -calling sequence. - -3. The function parameters are defined in more detail in the -alphabetical listing in Appendix B. - -4. The first argument in almost all the functions is a pointer to a -structure of type `fitsfile'. Memory for this structure is allocated -by CFITSIO when the FITS file is first opened or created and is freed -when the FITS file is closed. - -5. The last argument in almost all the functions is the error status -parameter. It must be equal to 0 on input, otherwise the function will -immediately exit without doing anything. A non-zero output value -indicates that an error occurred in the function. In most cases the -status value is also returned as the value of the function itself. - -**A. CFITSIO Error Status Routines - ->1 Return a descriptive text string (30 char max.) corresponding to -> a CFITSIO error status code.\label{ffgerr} -- - void fits_get_errstatus / ffgerr (int status, > char *err_text) -- ->2 Return the top (oldest) 80-character error message from the - internal CFITSIO stack of error messages and shift any remaining - messages on the stack up one level. Call this routine - repeatedly to get each message in sequence. The function returns - a value = 0 and a null error message when the error stack is empty. ->\label{ffgmsg} -- - int fits_read_errmsg / ffgmsg (char *err_msg) -- ->3 Print out the error message corresponding to the input status - value and all the error messages on the CFITSIO stack to the specified - file stream (normally to stdout or stderr). If the input - status value = 0 then this routine does nothing. ->\label{ffrprt} -- - void fits_report_error / ffrprt (FILE *stream, status) -- ->4 The fits\_write\_errmark routine puts an invisible marker on the - CFITSIO error stack. The fits\_clear\_errmark routine can then be - used to delete any more recent error messages on the stack, back to - the position of the marker. This preserves any older error messages - on the stack. The fits\_clear\_errmsg routine simply clears all the - messages (and marks) from the stack. These routines are called - without any arguments. ->\label{ffpmrk} \label{ffcmsg} -- - void fits_write_errmark / ffpmrk (void) - void fits_clear_errmark / ffcmrk (void) - void fits_clear_errmsg / ffcmsg (void) -- - -**B. FITS File Access Routines - ->1 Open an existing data file. \label{ffopen} - -- -int fits_open_file / ffopen - (fitsfile **fptr, char *filename, int iomode, > int *status) - -int fits_open_diskfile / ffdkopen - (fitsfile **fptr, char *filename, int iomode, > int *status) - -int fits_open_data / ffdopn - (fitsfile **fptr, char *filename, int iomode, > int *status) - -int fits_open_table / fftopn - (fitsfile **fptr, char *filename, int iomode, > int *status) - -int fits_open_image / ffiopn - (fitsfile **fptr, char *filename, int iomode, > int *status) - -int fits_open_extlist / ffeopn - (fitsfile **fptr, char *filename, int iomode, char *extlist, - > int *hdutype, int *status) -- - -The iomode parameter determines the read/write access allowed in the -file and can have values of READONLY (0) or READWRITE (1). The filename -parameter gives the name of the file to be opened, followed by an -optional argument giving the name or index number of the extension -within the FITS file that should be moved to and opened (e.g., -\verb-myfile.fits+3- or \verb-myfile.fits[3]- moves to the 3rd extension within -the file, and \verb-myfile.fits[events]- moves to the extension with the -keyword EXTNAME = 'EVENTS'). - -The fits\_open\_diskfile routine is similar to the fits\_open\_file routine -except that it does not support the extended filename syntax in the input -file name. This routine simply tries to open the specified input file -on magnetic disk. This routine is mainly for use in cases where the -filename (or directory path) contains square or curly bracket characters -that would confuse the extended filename parser. - -The fits\_open\_data routine is similar to the fits\_open\_file routine -except that it will move to the first HDU containing significant data, -if a HDU name or number to open was not explicitly specified as -part of the filename. In this case, it will look for the first -IMAGE HDU with NAXIS greater than 0, or the first table that does not contain the -strings `GTI' (Good Time Interval extension) or `OBSTABLE' in the -EXTNAME keyword value. - -The fits\_open\_table and fits\_open\_image routines are similar to -fits\_open\_data except they will move to the first significant table -HDU or image HDU in the file, respectively, if a HDU name or -number is not specified as part of the filename. - -The fits\_open\_extname routine opens the file and attempts to move to a 'useful' -HDU. If after opening the file CFITSIO is pointing to null primary array, -then CFITSIO will attempt to move to the first extension that has an EXTNAME or -HDUNAME keyword value that matches one of the names in the input extlist -space-delimited list of names. If that fails, then CFITSIO simply moves to the -2nd HDU in the file. - -IRAF images (.imh format files) and raw binary data arrays may also be -opened with READONLY access. CFITSIO will automatically test if the -input file is an IRAF image, and if, so will convert it on the fly into -a virtual FITS image before it is opened by the application program. -If the input file is a raw binary data array of numbers, then the data type -and dimensions of the array must be specified in square brackets -following the name of the file (e.g. 'rawfile.dat[i512,512]' opens a -512 x 512 short integer image). See the `Extended File Name Syntax' -chapter for more details on how to specify the raw file name. The raw -file is converted on the fly into a virtual FITS image in memory that -is then opened by the application program with READONLY access. - -Programs can read the input file from the 'stdin' file stream if a dash -character ('-') is given as the filename. Files can also be opened over -the network using FTP or HTTP protocols by supplying the appropriate URL -as the filename. - -The input file can be modified in various ways to create a virtual file -(usually stored in memory) that is then opened by the application -program by supplying a filtering or binning specifier in square brackets -following the filename. Some of the more common filtering methods are -illustrated in the following paragraphs, but users should refer to the -'Extended File Name Syntax' chapter for a complete description of -the full file filtering syntax. - -When opening an image, a rectangular subset of the physical image may be -opened by listing the first and last pixel in each dimension (and -optional pixel skipping factor): -- -myimage.fits[101:200,301:400] -- -will create and open a 100x100 pixel virtual image of that section of -the physical image, and \verb+myimage.fits[*,-*]+ opens a virtual image -that is the same size as the physical image but has been flipped in -the vertical direction. - -When opening a table, the filtering syntax can be used to add or delete -columns or keywords in the virtual table: -\verb-myfile.fits[events][col !time; PI = PHA*1.2]- opens a virtual table in which the TIME column -has been deleted and a new PI column has been added with a value 1.2 -times that of the PHA column. Similarly, one can filter a table to keep -only those rows that satisfy a selection criterion: -\verb-myfile.fits[events][pha > 50]- creates and opens a virtual table -containing only those rows with a PHA value greater than 50. A large -number of boolean and mathematical operators can be used in the -selection expression. One can also filter table rows using 'Good Time -Interval' extensions, and spatial region filters as in -\verb-myfile.fits[events][gtifilter()]- and -\verb-myfile.fits[events][regfilter( "stars.rng")]-. - -Finally, table columns may be binned or histogrammed to generate a -virtual image. For example, \verb-myfile.fits[events][bin (X,Y)=4]- will -result in a 2-dimensional image calculated by binning the X and Y -columns in the event table with a bin size of 4 in each dimension. The -TLMINn and TLMAXn keywords will be used by default to determine the -range of the image. - -A single program can open the same FITS file more than once and then -treat the resulting fitsfile pointers as though they were completely -independent FITS files. Using this facility, a program can open a FITS -file twice, move to 2 different extensions within the file, and then -> read and write data in those extensions in any order. - ->2 Create and open a new empty output FITS file. \label{ffinit} - -- -int fits_create_file / ffinit - (fitsfile **fptr, char *filename, > int *status) - -int fits_create_diskfile / ffdkinit - (fitsfile **fptr, char *filename, > int *status) -- - -An error will be returned if the specified file already exists, unless -the filename is prefixed with an exclamation point (!). In that case -CFITSIO will overwrite (delete) any existing file with the same name. -Note that the exclamation point is a special UNIX character so if -it is used on the command line it must be preceded by a backslash to -force the UNIX shell to accept the character as part of the filename. - -The output file will be written to the 'stdout' file stream if a dash -character ('-') or the string 'stdout' is given as the filename. Similarly, -'-.gz' or 'stdout.gz' will cause the file to be gzip compressed before -it is written out to the stdout stream. - -Optionally, the name of a template file that is used to define the -structure of the new file may be specified in parentheses following the -output file name. The template file may be another FITS file, in which -case the new file, at the time it is opened, will be an exact copy of -the template file except that the data structures (images and tables) -will be filled with zeros. Alternatively, the template file may be an -ASCII format text file containing directives that define the keywords to be -created in each HDU of the file. See the 'Extended File Name Syntax' - section for a complete description of the template file syntax. - -The fits\_create\_diskfile routine is similar to the fits\_create\_file routine -except that it does not support the extended filename syntax in the input -file name. This routine simply tries to create the specified file -on magnetic disk. This routine is mainly for use in cases where the -filename (or directory path) contains square or curly bracket characters -> that would confuse the extended filename parser. - - ->3 Close a previously opened FITS file. The first routine simply -closes the file, whereas the second one also DELETES the file, which -can be useful in cases where a FITS file has been partially created, -but then an error occurs which prevents it from being completed. -Note that these routines behave differently than most other CFITSIO routines -if the input value of the `status' parameter is not zero: Instead of -simply returning to the calling program without doing anything, these -routines effectively ignore the input status value and still attempt -to close or delete the file. -> \label{ffclos} \label{ffdelt} -- - int fits_close_file / ffclos (fitsfile *fptr, > int *status) - - int fits_delete_file / ffdelt (fitsfile *fptr, > int *status) -- ->4 Return the name, I/O mode (READONLY or READWRITE), and/or the file -type (e.g. 'file://', 'ftp://') of the opened FITS file. \label{ffflnm} -> \label{ffflmd} \label{ffurlt} -- - int fits_file_name / ffflnm (fitsfile *fptr, > char *filename, int *status) - - int fits_file_mode / ffflmd (fitsfile *fptr, > int *iomode, int *status) - - int fits_url_type / ffurlt (fitsfile *fptr, > char *urltype, int *status) -- -**C. HDU Access Routines - -The following functions perform operations on Header-Data Units (HDUs) -as a whole. - ->1 Move to a different HDU in the file. The first routine moves to a - specified absolute HDU number (starting with 1 for the primary - array) in the FITS file, and the second routine moves a relative - number HDUs forward or backward from the current HDU. A null - pointer may be given for the hdutype parameter if it's value is not - needed. The third routine moves to the (first) HDU which has the - specified extension type and EXTNAME and EXTVER keyword values (or - HDUNAME and HDUVER keywords). The hdutype parameter may have a - value of IMAGE\_HDU, ASCII\_TBL, BINARY\_TBL, or ANY\_HDU where - ANY\_HDU means that only the extname and extver values will be used - to locate the correct extension. If the input value of extver is 0 - then the EXTVER keyword is ignored and the first HDU with a - matching EXTNAME (or HDUNAME) keyword will be found. If no - matching HDU is found in the file then the current HDU will remain - unchanged and a status = BAD\_HDU\_NUM will be returned. -> \label{ffmahd} \label{ffmrhd} \label{ffmnhd} -- - int fits_movabs_hdu / ffmahd - (fitsfile *fptr, int hdunum, > int *hdutype, int *status) - - int fits_movrel_hdu / ffmrhd - (fitsfile *fptr, int nmove, > int *hdutype, int *status) - - int fits_movnam_hdu / ffmnhd - (fitsfile *fptr, int hdutype, char *extname, int extver, > int *status) -- ->2 Return the total number of HDUs in the FITS file. This returns the -number of completely defined HDUs in the file. If a new HDU has just been added to -the FITS file, then that last HDU will only be counted if it has been closed, -or if data has been written to the HDU. -> The current HDU remains unchanged by this routine. \label{ffthdu} -- - int fits_get_num_hdus / ffthdu - (fitsfile *fptr, > int *hdunum, int *status) -- ->3 Return the number of the current HDU (CHDU) in the FITS file (where - the primary array = 1). This function returns the HDU number -> rather than a status value. \label{ffghdn} -- - int fits_get_hdu_num / ffghdn - (fitsfile *fptr, > int *hdunum) -- ->4 Return the type of the current HDU in the FITS file. The possible -> values for hdutype are: IMAGE\_HDU, ASCII\_TBL, or BINARY\_TBL. \label{ffghdt} -- - int fits_get_hdu_type / ffghdt - (fitsfile *fptr, > int *hdutype, int *status) -- ->5 Copy all or part of the HDUs in the FITS file associated with infptr - and append them to the end of the FITS file associated with - outfptr. If 'previous' is true (not 0), then any HDUs preceding - the current HDU in the input file will be copied to the output - file. Similarly, 'current' and 'following' determine whether the - current HDU, and/or any following HDUs in the input file will be - copied to the output file. Thus, if all 3 parameters are true, then the - entire input file will be copied. On exit, the current HDU in - the input file will be unchanged, and the last HDU in the output -> file will be the current HDU. \label{ffcpfl} -- - int fits_copy_file / ffcpfl - (fitsfile *infptr, fitsfile *outfptr, int previous, int current, - int following, > int *status) -- ->6 Copy the current HDU from the FITS file associated with infptr and append it - to the end of the FITS file associated with outfptr. Space may be -> reserved for MOREKEYS additional keywords in the output header. \label{ffcopy} -- - int fits_copy_hdu / ffcopy - (fitsfile *infptr, fitsfile *outfptr, int morekeys, > int *status) -- ->7 Write the current HDU in the input FITS file to the -> output FILE stream (e.g., to stdout). \label{ffwrhdu} -- - int fits_write_hdu / ffwrhdu - (fitsfile *infptr, FILE *stream, > int *status) -- ->8 Copy the header (and not the data) from the CHDU associated with infptr - to the CHDU associated with outfptr. If the current output HDU - is not completely empty, then the CHDU will be closed and a new - HDU will be appended to the output file. An empty output data unit -> will be created with all values initially = 0). \label{ffcphd} -- - int fits_copy_header / ffcphd - (fitsfile *infptr, fitsfile *outfptr, > int *status) -- ->9 Delete the CHDU in the FITS file. Any following HDUs will be shifted - forward in the file, to fill in the gap created by the deleted - HDU. In the case of deleting the primary array (the first HDU in - the file) then the current primary array will be replace by a null - primary array containing the minimum set of required keywords and - no data. If there are more extensions in the file following the - one that is deleted, then the the CHDU will be redefined to point - to the following extension. If there are no following extensions - then the CHDU will be redefined to point to the previous HDU. The - output hdutype parameter returns the type of the new CHDU. A null - pointer may be given for -> hdutype if the returned value is not needed. \label{ffdhdu} -- - int fits_delete_hdu / ffdhdu - (fitsfile *fptr, > int *hdutype, int *status) -- -**D. Header Keyword Read/Write Routines - -These routines read or write keywords in the Current Header Unit -(CHU). Wild card characters (*, ?, or \#) may be used when specifying -the name of the keyword to be read: a '?' will match any single -character at that position in the keyword name and a '*' will match any -length (including zero) string of characters. The '\#' character will -match any consecutive string of decimal digits (0 - 9). When a wild -card is used the routine will only search for a match from the current -header position to the end of the header and will not resume the search -from the top of the header back to the original header position as is -done when no wildcards are included in the keyword name. The -fits\_read\_record routine may be used to set the starting position -when doing wild card searches. A status value of KEY\_NO\_EXIST is -returned if the specified keyword to be read is not found in the -header. - -***1. Keyword Reading Routines - ->1 Return the number of existing keywords (not counting the - END keyword) and the amount of space currently available for more - keywords. It returns morekeys = -1 if the header has not yet been - closed. Note that CFITSIO will dynamically add space if required - when writing new keywords to a header so in practice there is no - limit to the number of keywords that can be added to a header. A - null pointer may be entered for the morekeys parameter if it's -> value is not needed. \label{ffghsp} -- - int fits_get_hdrspace / ffghsp - (fitsfile *fptr, > int *keysexist, int *morekeys, int *status) -- ->2 Return the specified keyword. In the first routine, - the datatype parameter specifies the desired returned data type of the - keyword value and can have one of the following symbolic constant - values: TSTRING, TLOGICAL (== int), TBYTE, TSHORT, TUSHORT, TINT, - TUINT, TLONG, TULONG, TLONGLONG, TFLOAT, TDOUBLE, TCOMPLEX, and TDBLCOMPLEX. - Within the context of this routine, TSTRING corresponds to a - 'char*' data type, i.e., a pointer to a character array. Data type - conversion will be performed for numeric values if the keyword - value does not have the same data type. If the value of the keyword - is undefined (i.e., the value field is blank) then an error status - = VALUE\_UNDEFINED will be returned. - - The second routine returns the keyword value as a character string - (a literal copy of what is in the value field) regardless of the - intrinsic data type of the keyword. The third routine returns - the entire 80-character header record of the keyword, with any - trailing blank characters stripped off. The fourth routine returns - the (next) header record that contains the literal string of characters - specified by the 'string' argument. - - If a NULL comment pointer is supplied then the comment string -> will not be returned. \label{ffgky} \label{ffgkey} \label{ffgcrd} -- - int fits_read_key / ffgky - (fitsfile *fptr, int datatype, char *keyname, > DTYPE *value, - char *comment, int *status) - - int fits_read_keyword / ffgkey - (fitsfile *fptr, char *keyname, > char *value, char *comment, - int *status) - - int fits_read_card / ffgcrd - (fitsfile *fptr, char *keyname, > char *card, int *status) - - int fits_read_str / ffgstr - (fitsfile *fptr, char *string, > char *card, int *status) -- ->3 Read a string-valued keyword and return the string length, the value string, - and/or the comment field. The first routine, ffgksl, simply - returns the length of the character string value of the specified keyword. - The second routine, ffgsky, also returns up to maxchar characters - of the keyword value string, starting with the firstchar character, - and the keyword comment string (unless the input value of comm = NULL). - The valuelen argument returns the total length of the keyword value string - regardless of how much of the string is actually returned (which - depends on the value of the firstchar and maxchar arguments). - Note that the value character string argument must be allocated large enough to - also hold the null terminator at the end of the returned string. These - routines support string keywords that use the CONTINUE convention to - continue long string values over multiple FITS header records. Normally, - string-valued keywords have a maximum length of 68 characters, however, -> CONTINUE'd string keywords may be arbitrarily long. \label{ffgksl} \label{ffgsky} -- - int fits_get_key_strlen / ffgksl - (fitsfile *fptr, const char *keyname, int *length, int *status); - - int fits_read_string_key / ffgsky - (fitsfile *fptr, const char *keyname, int firstchar, int maxchar, - char *value, int *valuelen, char *comm, int *status); -- ->4 Return the nth header record in the CHU. The first keyword - in the header is at keynum = 1; if keynum = 0 then these routines - simply reset the internal CFITSIO pointer to the beginning of the header - so that subsequent keyword operations will start at the top of the - header (e.g., prior to searching for keywords using wild cards in - the keyword name). The first routine returns the entire - 80-character header record (with trailing blanks truncated), - while the second routine parses the record and returns the name, - value, and comment fields as separate (blank truncated) - character strings. If a NULL comment pointer is given on input, - then the comment string will not be -> returned. \label{ffgrec} \label{ffgkyn} -- - int fits_read_record / ffgrec - (fitsfile *fptr, int keynum, > char *card, int *status) - - int fits_read_keyn / ffgkyn - (fitsfile *fptr, int keynum, > char *keyname, char *value, - char *comment, int *status) -- ->5 Return the next keyword whose name matches one of the strings in - 'inclist' but does not match any of the strings in 'exclist'. - The strings in inclist and exclist may contain wild card characters - (*, ?, and \#) as described at the beginning of this section. - This routine searches from the current header position to the - end of the header, only, and does not continue the search from - the top of the header back to the original position. The current - header position may be reset with the ffgrec routine. Note - that nexc may be set = 0 if there are no keywords to be excluded. - This routine returns status = KEY\_NO\_EXIST if a matching -> keyword is not found. \label{ffgnxk} -- - int fits_find_nextkey / ffgnxk - (fitsfile *fptr, char **inclist, int ninc, char **exclist, - int nexc, > char *card, int *status) -- ->6 Return the physical units string from an existing keyword. This - routine uses a local convention, shown in the following example, - in which the keyword units are enclosed in square brackets in the - beginning of the keyword comment field. A null string is returned -> if no units are defined for the keyword. \label{ffgunt} -- - VELOCITY= 12.3 / [km/s] orbital speed - - int fits_read_key_unit / ffgunt - (fitsfile *fptr, char *keyname, > char *unit, int *status) -- ->7 Concatenate the header keywords in the CHDU into a single long - string of characters. This provides a convenient way of passing - all or part of the header information in a FITS HDU to other subroutines. - Each 80-character fixed-length keyword record is appended to the - output character string, in order, with no intervening separator or - terminating characters. The last header record is terminated with - a NULL character. These routine allocates memory for the returned - character array, so the calling program must free the memory when - finished. The cleanest way to do this is to - call the fits\_free\_memory routine. - - There are 2 related routines: fits\_hdr2str simply concatenates all - the existing keywords in the header; fits\_convert\_hdr2str is similar, - except that if the CHDU is a tile compressed image (stored in a binary - table) then it will first convert that header back to that of the corresponding - normal FITS image before concatenating the keywords. - - Selected keywords may be excluded from the returned character string. - If the second parameter (nocomments) is TRUE (nonzero) then any - COMMENT, HISTORY, or blank keywords in the header will not be copied - to the output string. - - The 'exclist' parameter may be used to supply a list of keywords - that are to be excluded from the output character string. Wild card - characters (*, ?, and \#) may be used in the excluded keyword names. - If no additional keywords are to be excluded, then set nexc = 0 and -> specify NULL for the the **exclist parameter. \label{ffhdr2str} -- - int fits_hdr2str / ffhdr2str - (fitsfile *fptr, int nocomments, char **exclist, int nexc, - > char **header, int *nkeys, int *status) - - int fits_convert_hdr2str / ffcnvthdr2str - (fitsfile *fptr, int nocomments, char **exclist, int nexc, - > char **header, int *nkeys, int *status) - - int fits_free_memory / fffree - (char *header, > int *status); - -- - -***2. Keyword Writing Routines - ->1 Write a keyword of the appropriate data type into the - CHU. The first routine simply appends a new keyword whereas the - second routine will update the value and comment fields of the - keyword if it already exists, otherwise it appends a new - keyword. Note that the address to the value, and not the value - itself, must be entered. The datatype parameter specifies the - data type of the keyword value with one of the following values: - TSTRING, TLOGICAL (== int), TBYTE, TSHORT, TUSHORT, TINT, TUINT, - TLONG, TLONGLONG, TULONG, TFLOAT, TDOUBLE. Within the context of this - routine, TSTRING corresponds to a 'char*' data type, i.e., a pointer - to a character array. A null pointer may be entered for the - comment parameter in which case the keyword comment -> field will be unmodified or left blank. \label{ffpky} \label{ffuky} -- - int fits_write_key / ffpky - (fitsfile *fptr, int datatype, char *keyname, DTYPE *value, - char *comment, > int *status) - - int fits_update_key / ffuky - (fitsfile *fptr, int datatype, char *keyname, DTYPE *value, - char *comment, > int *status) -- ->2 Write a keyword with a null or undefined value (i.e., the - value field in the keyword is left blank). The first routine - simply appends a new keyword whereas the second routine will update - the value and comment fields of the keyword if it already exists, - otherwise it appends a new keyword. A null pointer may be - entered for the comment parameter in which case the keyword - comment -> field will be unmodified or left blank. \label{ffpkyu} \label{ffukyu} -- - int fits_write_key_null / ffpkyu - (fitsfile *fptr, char *keyname, char *comment, > int *status) - - int fits_update_key_null / ffukyu - (fitsfile *fptr, char *keyname, char *comment, > int *status) -- ->3 Write (append) a COMMENT or HISTORY keyword to the CHU. The comment or - history string will be continued over multiple keywords if it is longer -> than 70 characters. \label{ffpcom} \label{ffphis} -- - int fits_write_comment / ffpcom - (fitsfile *fptr, char *comment, > int *status) - - int fits_write_history / ffphis - (fitsfile *fptr, char *history, > int *status) -- ->4 Write the DATE keyword to the CHU. The keyword value will contain - the current system date as a character string in 'yyyy-mm-ddThh:mm:ss' - format. If a DATE keyword already exists in the header, then this - routine will simply update the keyword value with the current date. -> \label{ffpdat} -- - int fits_write_date / ffpdat - (fitsfile *fptr, > int *status) -- ->5 Write a user specified keyword record into the CHU. This is - a low--level routine which can be used to write any arbitrary - record into the header. The record must conform to the all -> the FITS format requirements. \label{ffprec} -- - int fits_write_record / ffprec - (fitsfile *fptr, char *card, > int *status) -- ->6 Update an 80-character record in the CHU. If a keyword with the input - name already exists, then it is overwritten by the value of card. This - could modify the keyword name as well as the value and comment fields. - If the keyword doesn't already exist then a new keyword card is appended -> to the header. \label{ffucrd} -- - int fits_update_card / ffucrd - (fitsfile *fptr, char *keyname, char *card, > int *status) -- - ->>7 Modify (overwrite) the comment field of an existing keyword. \label{ffmcom} -- - int fits_modify_comment / ffmcom - (fitsfile *fptr, char *keyname, char *comment, > int *status) -- - ->8 Write the physical units string into an existing keyword. This - routine uses a local convention, shown in the following example, - in which the keyword units are enclosed in square brackets in the -> beginning of the keyword comment field. \label{ffpunt} -- - VELOCITY= 12.3 / [km/s] orbital speed - - int fits_write_key_unit / ffpunt - (fitsfile *fptr, char *keyname, char *unit, > int *status) -- ->9 Rename an existing keyword, preserving the current value -> and comment fields. \label{ffmnam} -- - int fits_modify_name / ffmnam - (fitsfile *fptr, char *oldname, char *newname, > int *status) -- ->10 Delete a keyword record. The space occupied by - the keyword is reclaimed by moving all the following header records up - one row in the header. The first routine deletes a keyword at a - specified position in the header (the first keyword is at position 1), - whereas the second routine deletes a specifically named keyword. - Wild card characters may be used when specifying the name of the keyword - to be deleted. The third routine deletes the (next) keyword that contains - the literal character string specified by the 'string' -> argument.\label{ffdrec} \label{ffdkey} -- - int fits_delete_record / ffdrec - (fitsfile *fptr, int keynum, > int *status) - - int fits_delete_key / ffdkey - (fitsfile *fptr, char *keyname, > int *status) - - int fits_delete_str / ffdstr - (fitsfile *fptr, char *string, > int *status) -- -**E. Primary Array or IMAGE Extension I/O Routines - -These routines read or write data values in the primary data array (i.e., -the first HDU in a FITS file) or an IMAGE extension. There are also -routines to get information about the data type and size of the image. -Users should also read the following chapter on the CFITSIO iterator -function which provides a more `object oriented' method of reading and -writing images. The iterator function is a little more complicated to -use, but the advantages are that it usually takes less code to perform -the same operation, and the resulting program often runs faster because -the FITS files are read and written using the most efficient block size. - -C programmers should note that the ordering of arrays in FITS files, and -hence in all the CFITSIO calls, is more similar to the dimensionality -of arrays in Fortran rather than C. For instance if a FITS image has -NAXIS1 = 100 and NAXIS2 = 50, then a 2-D array just large enough to hold -the image should be declared as array[50][100] and not as array[100][50]. - -The `datatype' parameter specifies the data type of the `nulval' and -`array' pointers and can have one of the following values: TBYTE, -TSBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TLONGLONG, TULONG, TFLOAT, -TDOUBLE. Automatic data type conversion is performed if the data type -of the FITS array (as defined by the BITPIX keyword) differs from that -specified by 'datatype'. The data values are also automatically scaled -by the BSCALE and BZERO keyword values as they are being read or written -in the FITS array. - ->1 Get the data type or equivalent data type of the image. The - first routine returns the physical data type of the FITS image, as - given by the BITPIX keyword, with allowed values of BYTE\_IMG (8), - SHORT\_IMG (16), LONG\_IMG (32), LONGLONG\_IMG (64), - FLOAT\_IMG (-32), and DOUBLE\_IMG - (-64). - The second routine is similar, except that if the image pixel - values are scaled, with non-default values for the BZERO and BSCALE - keywords, then the routine will return the 'equivalent' data type - that is needed to store the scaled values. For example, if BITPIX - = 16 and BSCALE = 0.1 then the equivalent data type is FLOAT\_IMG. - Similarly if BITPIX = 16, BSCALE = 1, and BZERO = 32768, then the - the pixel values span the range of an unsigned short integer and -> the returned data type will be USHORT\_IMG. \label{ffgidt} -- - int fits_get_img_type / ffgidt - (fitsfile *fptr, > int *bitpix, int *status) - - int fits_get_img_equivtype / ffgiet - (fitsfile *fptr, > int *bitpix, int *status) -- ->2 Get the number of dimensions, and/or the size of - each dimension in the image . The number of axes in the image is - given by naxis, and the size of each dimension is given by the - naxes array (a maximum of maxdim dimensions will be returned). -> \label{ffgidm} \label{ffgisz} \label{ffgipr} -- - int fits_get_img_dim / ffgidm - (fitsfile *fptr, > int *naxis, int *status) - - int fits_get_img_size / ffgisz - (fitsfile *fptr, int maxdim, > long *naxes, int *status) - - int fits_get_img_sizell / ffgiszll - (fitsfile *fptr, int maxdim, > LONGLONG *naxes, int *status) - - int fits_get_img_param / ffgipr - (fitsfile *fptr, int maxdim, > int *bitpix, int *naxis, long *naxes, - int *status) - - int fits_get_img_paramll / ffgiprll - (fitsfile *fptr, int maxdim, > int *bitpix, int *naxis, LONGLONG *naxes, - int *status) -- ->3 Create a new primary array or IMAGE extension with a specified - data type and size. If the FITS file is currently empty then a - primary array is created, otherwise a new IMAGE extension is -> appended to the file. \label{ffcrim} -- - int fits_create_img / ffcrim - ( fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) - - int fits_create_imgll / ffcrimll - ( fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) -- ->4 Copy an n-dimensional image in a particular row and column of a - binary table (in a vector column) - to or from a primary array or image extension. - - The 'cell2image' routine - will append a new image extension (or primary array) to the output file. - Any WCS keywords associated with the input column image will be translated - into the appropriate form for an image extension. Any other keywords - in the table header that are not specifically related to defining the - binary table structure or to other columns in the table - will also be copied to the header of the output image. - - The 'image2cell' routine will copy the input image into the specified row - and column of the current binary table in the output file. The binary table - HDU must exist before calling this routine, but it - may be empty, with no rows or columns of data. The specified column - (and row) will be created if it does not already exist. The 'copykeyflag' - parameter controls which keywords are copied from the input - image to the header of the output table: 0 = no keywords will be copied, - 1 = all keywords will be copied (except those keywords that would be invalid in -> the table header), and 2 = copy only the WCS keywords. \label{copycell} -- - int fits_copy_cell2image - (fitsfile *infptr, fitsfile *outfptr, char *colname, long rownum, - > int *status) - - int fits_copy_image2cell - (fitsfile *infptr, fitsfile *outfptr, char *colname, long rownum, - int copykeyflag > int *status) -- - ->5 Write a rectangular subimage (or the whole image) to the FITS data - array. The fpixel and lpixel arrays give the coordinates of the - first (lower left corner) and last (upper right corner) pixels in -> FITS image to be written to. \label{ffpss} -- - int fits_write_subset / ffpss - (fitsfile *fptr, int datatype, long *fpixel, long *lpixel, - DTYPE *array, > int *status) -- ->6 Write pixels into the FITS data array. 'fpixel' is an array of - length NAXIS which gives the coordinate of the starting pixel to be - written to, such that fpixel[0] is in the range 1 to NAXIS1, - fpixel[1] is in the range 1 to NAXIS2, etc. The first pair of routines - simply writes the array of pixels to the FITS file (doing data type - conversion if necessary) whereas the second routines will substitute - the appropriate FITS null value for any elements which are equal to - the input value of nulval (note that this parameter gives the - address of the null value, not the null value itself). For integer - FITS arrays, the FITS null value is defined by the BLANK keyword (an - error is returned if the BLANK keyword doesn't exist). For floating - point FITS arrays the special IEEE NaN (Not-a-Number) value will be - written into the FITS file. If a null pointer is entered for - nulval, then the null value is ignored and this routine behaves -> the same as fits\_write\_pix. \label{ffppx} \label{ffppxn} -- - int fits_write_pix / ffppx - (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, - DTYPE *array, int *status); - - int fits_write_pixll / ffppxll - (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, - DTYPE *array, int *status); - - int fits_write_pixnull / ffppxn - (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, - DTYPE *array, DTYPE *nulval, > int *status); - - int fits_write_pixnullll / ffppxnll - (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, - DTYPE *array, DTYPE *nulval, > int *status); -- ->7 Set FITS data array elements equal to the appropriate null pixel - value. For integer FITS arrays, the FITS null value is defined by - the BLANK keyword (an error is returned if the BLANK keyword - doesn't exist). For floating point FITS arrays the special IEEE NaN - (Not-a-Number) value will be written into the FITS file. Note that - 'firstelem' is a scalar giving the offset to the first pixel to be -> written in the equivalent 1-dimensional array of image pixels. \label{ffpprn} -- - int fits_write_null_img / ffpprn - (fitsfile *fptr, LONGLONG firstelem, LONGLONG nelements, > int *status) -- ->8 Read a rectangular subimage (or the whole image) from the FITS - data array. The fpixel and lpixel arrays give the coordinates of - the first (lower left corner) and last (upper right corner) pixels - to be read from the FITS image. Undefined FITS array elements will - be returned with a value = *nullval, (note that this parameter - gives the address of the null value, not the null value itself) - unless nulval = 0 or *nulval = 0, in which case no checks for -> undefined pixels will be performed. \label{ffgsv} -- - int fits_read_subset / ffgsv - (fitsfile *fptr, int datatype, long *fpixel, long *lpixel, long *inc, - DTYPE *nulval, > DTYPE *array, int *anynul, int *status) -- ->9 Read pixels from the FITS data array. 'fpixel' is the starting - pixel location and is an array of length NAXIS such that fpixel[0] - is in the range 1 to NAXIS1, fpixel[1] is in the range 1 to NAXIS2, - etc. The nelements parameter specifies the number of pixels to - read. If fpixel is set to the first pixel, and nelements is set - equal to the NAXIS1 value, then this routine would read the first - row of the image. Alternatively, if nelements is set equal to - NAXIS1 * NAXIS2 then it would read an entire 2D image, or the first - plane of a 3-D datacube. - - The first 2 routines will return any undefined pixels in the FITS array - equal to the value of *nullval (note that this parameter gives the - address of the null value, not the null value itself) unless nulval - = 0 or *nulval = 0, in which case no checks for undefined pixels - will be performed. The second 2 routines are similar except that any - undefined pixels will have the corresponding nullarray element set -> equal to TRUE (= 1). \label{ffgpxv} \label{ffgpxf} -- - int fits_read_pix / ffgpxv - (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, - DTYPE *nulval, > DTYPE *array, int *anynul, int *status) - - int fits_read_pixll / ffgpxvll - (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, - DTYPE *nulval, > DTYPE *array, int *anynul, int *status) - - int fits_read_pixnull / ffgpxf - (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, - > DTYPE *array, char *nullarray, int *anynul, int *status) - - int fits_read_pixnullll / ffgpxfll - (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, - > DTYPE *array, char *nullarray, int *anynul, int *status) -- ->10 Copy a rectangular section of an image and write it to a new - FITS primary image or image extension. The new image HDU is appended - to the end of the output file; all the keywords in the input image - will be copied to the output image. The common WCS keywords will - be updated if necessary to correspond to the coordinates of the section. - The format of the section expression is - same as specifying an image section using the extended file name - syntax (see "Image Section" in Chapter 10). - (Examples: "1:100,1:200", "1:100:2, 1:*:2", "*, -*"). -> \label{ffcpimg} -- - int fits_copy_image_section / ffcpimg - (fitsfile *infptr, fitsfile *outfptr, char *section, int *status) -- - -**F. Image Compression - -CFITSIO transparently supports the 2 methods of image compression described -below. - -1) The entire FITS file may be externally compressed with the gzip or Unix -compress utility programs, producing a *.gz or *.Z file, respectively. When reading -compressed files of this type, CFITSIO first uncompresses the entire file -into memory before performing the requested read operations. Output files -can be directly written in the gzip compressed format if the user-specified -filename ends with `.gz'. In this case, CFITSIO initially writes the -uncompressed file in memory and then compresses it and writes it to disk -when the FITS file is closed, thus saving user disk space. Read and write -access to these compressed FITS files is generally quite fast since all the -I/O is performed in memory; the main limitation with this technique is that -there must be enough available memory (or swap space) to hold the entire -uncompressed FITS file. - -2) CFITSIO also supports the FITS tiled image compression convention in -which the image is subdivided into a grid of rectangular tiles, and each -tile of pixels is individually compressed. The details of this FITS -compression convention are described at the FITS Support Office web site at -http://fits.gsfc.nasa.gov/fits\_registry.html, and in the fpackguide pdf file -that is included with the CFITSIO source file distributions Basically, the compressed -image tiles are stored in rows of a variable length array column in a FITS -binary table, however CFITSIO recognizes that this binary table extension -contains an image and treats it as if it were an IMAGE extension. This -tile-compressed format is especially well suited for compressing very large -images because a) the FITS header keywords remain uncompressed for rapid -read access, and because b) it is possible to extract and uncompress -sections of the image without having to uncompress the entire image. This -format is also much more effective in compressing floating point images -than simply compressing the image using gzip or compress because it -approximates the floating point values with scaled integers which can then -be compressed more efficiently. - -Currently CFITSIO supports 3 general purpose compression algorithms plus -one other special-purpose compression technique that is designed for data -masks with positive integer pixel values. The 3 general purpose algorithms -are GZIP, Rice, and HCOMPRESS, and the special purpose algorithm is the -IRAF pixel list compression technique (PLIO). There are 2 variants of the GZIP -algorithm: GZIP\_1 compresses the array of image pixel value normally with the -GZIP algorithm, while GZIP\_2 first shuffles the bytes in all the pixel -values so that the most-significant byte of every pixel appears first, followed -by the less significant bytes in sequence. GZIP\_2 may be more effective -in cases where the most significant byte in most of the image pixel values -contains the same bit pattern. In principle, any number of -other compression algorithms could also be supported by the FITS tiled -image compression convention. - -The FITS image can be subdivided into any desired rectangular grid of -compression tiles. With the GZIP, Rice, and PLIO algorithms, the default -is to take each row of the image as a tile. The HCOMPRESS algorithm is -inherently 2-dimensional in nature, so the default in this case is to take -16 rows of the image per tile. In most cases it makes little difference what -tiling pattern is used, so the default tiles are usually adequate. In the -case of very small images, it could be more efficient to compress the whole -image as a single tile. Note that the image dimensions are not required to -be an integer multiple of the tile dimensions; if not, then the tiles at the -edges of the image will be smaller than the other tiles. - -The 4 supported image compression algorithms are all 'loss-less' when -applied to integer FITS images; the pixel values are preserved exactly with -no loss of information during the compression and uncompression process. In -addition, the HCOMPRESS algorithm supports a 'lossy' compression mode that -will produce -larger amount of image compression. This is achieved by specifying a non-zero -value for the HCOMPRESS ``scale'' -parameter. Since the amount of compression that is achieved depends directly -on the RMS noise in the image, it is usually more convention -to specify the HCOMPRESS scale factor relative to the RMS noise. -Setting s = 2.5 means use a scale factor that is 2.5 times the calculated RMS noise -in the image tile. In some cases -it may be desirable to specify the exact scaling to be used, -instead of specifying it relative to the calculated noise value. This may -be done by specifying the negative of desired scale value (typically -in the range -2 to -100). - -Very high compression factors (of 100 or more) can be -achieved by using large HCOMPRESS scale values, however, this can produce undesirable -``blocky'' artifacts in the compressed image. A variation of the HCOMPRESS -algorithm (called HSCOMPRESS) can be used in this case to apply a small -amount of smoothing of the image when it is uncompressed to help cover up -these artifacts. This smoothing is purely cosmetic and does not cause any -significant change to the image pixel values. - -Floating point FITS images (which have BITPIX = -32 or -64) usually contain -too much ``noise'' in the least significant bits of the mantissa of the -pixel values to be effectively compressed with any lossless algorithm. -Consequently, floating point images are first quantized into scaled integer -pixel values (and thus throwing away much of the noise) before being -compressed with the specified algorithm (either GZIP, Rice, or HCOMPRESS). -This technique produces much higher compression factors than -simply using the GZIP utility to externally compress the whole FITS file, but it also -means that the original floating value pixel values are not exactly -preserved. When done properly, this integer scaling technique will only -discard the insignificant noise while still preserving all the real -information in the image. The amount of precision that is retained in the -pixel values is controlled by the "quantization level" parameter, q. Larger -values of q will result in compressed images whose pixels more closely match -the floating point pixel values, but at the same time the amount of -compression that is achieved will be reduced. Users should experiment with -different values for this parameter to determine the optimal value that -preserves all the useful information in the image, without needlessly -preserving all the ``noise'' which will hurt the compression efficiency. - -The default value for the quantization scale factor is 4.0, which means that -scaled integer pixel values will be quantized such that the difference -between adjacent integer values will be 1/4th of the noise level in the -image background. CFITSIO uses an optimized algorithm to accurately estimate -the noise in the image. As an example, if the RMS noise in the background -pixels of an image = 32.0, then the spacing between adjacent scaled -integer pixel values will equal 8.0 by default. Note that the RMS noise is -independently calculated for each tile of the image, so the resulting -integer scaling factor may fluctuate slightly for each tile. In some cases -it may be desirable to specify the exact quantization level to be used, -instead of specifying it relative to the calculated noise value. This may -be done by specifying the negative of desired quantization level for the -value of q. In the previous example, one could specify q = -8.0 so that the -quantized integer levels differ by exactly 8.0. Larger negative values for q means -that the levels are more coarsely spaced, and will produce higher -compression factors. - -When floating point images are being quantized, one must also specify what -quantization method is to be used. The default algorithm is called -``SUBTRACTIVE\_DITHER\_1''. A second variation called ``SUBTRACTIVE\_DITHER\_2'' -is also available, which does the same thing except that any pixels with a -value of 0.0 are not dithered and instead the zero values are exactly -preserved in the compressed image. One may also turn off dithering -completely with the ``NO\_DITHER'' option, but this is not recommended -because it can cause larger systematic errors in measurements of the -position or brightness of objects in the compressed image. - -There are 3 methods for specifying all the parameters needed to write a FITS -image in the tile compressed format. The parameters may either be specified -at run time as part of the file name of the output compressed FITS file, or -the writing program may call a set of helper CFITSIO subroutines that are provided -for specifying the parameter values, or ``compression directive'' keywords -may be added to the header of each image HDU to specify the compression parameters. -These 3 methods are described below. - -1) At run time, when specifying the name of the output FITS file to be -created, the user can indicate that images should be -written in tile-compressed format by enclosing the compression -parameters in square brackets following the root disk file name -in the following format: -- - [compress NAME T1,T2; q[z] QLEVEL, s HSCALE] -- -where -- - NAME = algorithm name: GZIP, Rice, HCOMPRESS, HSCOMPRSS or PLIO - may be abbreviated to the first letter (or HS for HSCOMPRESS) - T1,T2 = tile dimension (e.g. 100,100 for square tiles 100 pixels wide) - QLEVEL = quantization level for floating point FITS images - HSCALE = HCOMPRESS scale factor; default = 0 which is lossless. -- - -Here are a few examples of this extended syntax: - -- - myfile.fit[compress] - use the default compression algorithm (Rice) - and the default tile size (row by row) - - myfile.fit[compress G] - use the specified compression algorithm; - myfile.fit[compress R] only the first letter of the algorithm - myfile.fit[compress P] should be given. - myfile.fit[compress H] - - myfile.fit[compress R 100,100] - use Rice and 100 x 100 pixel tiles - - myfile.fit[compress R; q 10.0] - quantization level = (RMS-noise) / 10. - myfile.fit[compress R; qz 10.0] - quantization level = (RMS-noise) / 10. - also use the SUBTRACTIVE_DITHER_2 quantization method - myfile.fit[compress HS; s 2.0] - HSCOMPRESS (with smoothing) - and scale = 2.0 * RMS-noise -- - -2) Before calling the CFITSIO routine to write the image header -keywords (e.g., fits\_create\_image) the programmer can call the -routines described below to specify the compression algorithm and the -tiling pattern that is to be used. There are routines for specifying -the various compression parameters and similar routines to -return the current values of the parameters: -\label{ffsetcomp} \label{ffgetcomp} -- - int fits_set_compression_type(fitsfile *fptr, int comptype, int *status) - int fits_set_tile_dim(fitsfile *fptr, int ndim, long *tilesize, int *status) - int fits_set_quantize_level(fitsfile *fptr, float qlevel, int *status) - int fits_set_quantize_method(fitsfile *fptr, int method, int *status) - int fits_set_quantize_dither(fitsfile *fptr, int dither, int *status) - int fits_set_dither_seed(fitsfile *fptr, int seed, int *status) - int fits_set_dither_offset(fitsfile *fptr, int offset, int *status) - int fits_set_lossy_int(fitsfile *fptr, int lossy_int, int *status) - this forces integer image to be converted to floats, then quantized - int fits_set_huge_hdu(fitsfile *fptr, int huge, int *status); - this should be called when the compressed image size is more than 4 GB. - int fits_set_hcomp_scale(fitsfile *fptr, float scale, int *status) - int fits_set_hcomp_smooth(fitsfile *fptr, int smooth, int *status) - Set smooth = 1 to apply smoothing when uncompressing the image - - int fits_get_compression_type(fitsfile *fptr, int *comptype, int *status) - int fits_get_tile_dim(fitsfile *fptr, int ndim, long *tilesize, int *status) - int fits_get_quantize_level(fitsfile *fptr, float *level, int *status) - int fits_get_hcomp_scale(fitsfile *fptr, float *scale, int *status) -- -Several symbolic constants are defined for use as the value of the -`comptype' parameter: GZIP\_1, GZIP\_2, RICE\_1, HCOMPRESS\_1 or PLIO\_1. -Entering NULL for comptype will turn off the tile-compression and cause normal FITS -images to be written. - -There are also defined symbolic constants for the quantization method: -``SUBTRACTIVE\_DITHER\_1'', ``SUBTRACTIVE\_DITHER\_2'', and ``NO\_DITHER''. - -3) CFITSIO will uses the values of the following keywords, if they are present -in the header of the image HDU, -to determine how to compress that HDU. These keywords override any compression parameters -that were specified with the previous 2 methods. -- - FZALGOR - 'RICE_1' , 'GZIP_1', 'GZIP_2', 'HCOMPRESS_1', 'PLIO_1', 'NONE' - FZTILE - 'ROW', 'WHOLE', or '(n,m)' - FZQVALUE - float value (default = 4.0) - FZQMETHD - 'SUBTRACTIVE_DITHER_1', 'SUBTRACTIVE_DITHER_2', 'NO_DITHER' - FZDTHRSD - 'CLOCK', 'CHECKSUM', 1 - 10000 - FZINT2F - T, or F: Convert integers to floats, then quantize? - FZHSCALE - float value (default = 0). Hcompress scale value. -- - -No special action is required by software when read tile-compressed images because -all the CFITSIO routines that read normal uncompressed FITS images also -transparently read images in the tile-compressed format; CFITSIO essentially -treats the binary table that contains the compressed tiles as if -it were an IMAGE extension. - - -The following 2 routines are available for compressing or -or decompressing an image: -- - int fits_img_compress(fitsfile *infptr, fitsfile *outfptr, int *status); - int fits_img_decompress (fitsfile *infptr, fitsfile *outfptr, int *status); -- -Before calling the compression routine, the compression parameters must -first be defined in one of the 3 way described in the previous paragraphs. -There is also a routine to determine if the current HDU contains -a tile compressed image (it returns 1 or 0): -- - int fits_is_compressed_image(fitsfile *fptr, int *status); -- -A small example program called 'imcopy' is included with CFITSIO that -can be used to compress (or uncompress) any FITS image. This -program can be used to experiment with the various compression options -on existing FITS images as shown in these examples: -- -1) imcopy infile.fit 'outfile.fit[compress]' - - This will use the default compression algorithm (Rice) and the - default tile size (row by row) - -2) imcopy infile.fit 'outfile.fit[compress GZIP]' - - This will use the GZIP compression algorithm and the default - tile size (row by row). The allowed compression algorithms are - Rice, GZIP, and PLIO. Only the first letter of the algorithm - name needs to be specified. - -3) imcopy infile.fit 'outfile.fit[compress G 100,100]' - - This will use the GZIP compression algorithm and 100 X 100 pixel - tiles. - -4) imcopy infile.fit 'outfile.fit[compress R 100,100; qz 10.0]' - - This will use the Rice compression algorithm, 100 X 100 pixel - tiles, and quantization level = RMSnoise / 10.0 (assuming the - input image has a floating point data type). By specifying - qz instead of q, this means use the subtractive dither2 - quantization method. - -5) imcopy infile.fit outfile.fit - - If the input file is in tile-compressed format, then it will be - uncompressed to the output file. Otherwise, it simply copies - the input image to the output image. - -6) imcopy 'infile.fit[1001:1500,2001:2500]' outfile.fit - - This extracts a 500 X 500 pixel section of the much larger - input image (which may be in tile-compressed format). The - output is a normal uncompressed FITS image. - -7) imcopy 'infile.fit[1001:1500,2001:2500]' outfile.fit.gz - - Same as above, except the output file is externally compressed - using the gzip algorithm. - -- -**G. ASCII and Binary Table Routines - -These routines perform read and write operations on columns of data in -FITS ASCII or Binary tables. Note that in the following discussions, -the first row and column in a table is at position 1 not 0. - -Users should also read the following chapter on the CFITSIO iterator -function which provides a more `object oriented' method of reading and -writing table columns. The iterator function is a little more -complicated to use, but the advantages are that it usually takes less -code to perform the same operation, and the resulting program often -runs faster because the FITS files are read and written using the most -efficient block size. - -***1. Create New Table - ->1 Create a new ASCII or bintable table extension. If - the FITS file is currently empty then a dummy primary array will be - created before appending the table extension to it. The tbltype - parameter defines the type of table and can have values of - ASCII\_TBL or BINARY\_TBL. The naxis2 parameter gives the initial - number of rows to be created in the table, and should normally be - set = 0. CFITSIO will automatically increase the size of the table - as additional rows are written. A non-zero number of rows may be - specified to reserve space for that many rows, even if a fewer - number of rows will be written. The tunit and extname parameters - are optional and a null pointer may be given if they are not - defined. The FITS Standard recommends that only letters, digits, - and the underscore character be used in column names (the ttype - parameter) with no embedded spaces. Trailing blank characters are -> not significant. \label{ffcrtb} -- - int fits_create_tbl / ffcrtb - (fitsfile *fptr, int tbltype, LONGLONG naxis2, int tfields, char *ttype[], - char *tform[], char *tunit[], char *extname, int *status) -- -***2. Column Information Routines - ->1 Get the number of rows or columns in the current FITS table. - The number of rows is given by the NAXIS2 keyword and the - number of columns is given by the TFIELDS keyword in the header -> of the table. \label{ffgnrw} -- - int fits_get_num_rows / ffgnrw - (fitsfile *fptr, > long *nrows, int *status); - - int fits_get_num_rowsll / ffgnrwll - (fitsfile *fptr, > LONGLONG *nrows, int *status); - - int fits_get_num_cols / ffgncl - (fitsfile *fptr, > int *ncols, int *status); -- - ->2 Get the table column number (and name) of the column whose name -matches an input template name. If casesen = CASESEN then the column -name match will be case-sensitive, whereas if casesen = CASEINSEN then -the case will be ignored. As a general rule, the column names should -be treated as case INsensitive. - -The input column name template may be either the exact name of the -column to be searched for, or it may contain wild card characters (*, -?, or \#), or it may contain the integer number of the desired column -(with the first column = 1). The `*' wild card character matches any -sequence of characters (including zero characters) and the `?' -character matches any single character. The \# wildcard will match any -consecutive string of decimal digits (0-9). If more than one column -name in the table matches the template string, then the first match is -returned and the status value will be set to COL\_NOT\_UNIQUE as a -warning that a unique match was not found. To find the other cases -that match the template, call the routine again leaving the input -status value equal to COL\_NOT\_UNIQUE and the next matching name will -then be returned. Repeat this process until a status = -COL\_NOT\_FOUND is returned. - -The FITS Standard recommends that only letters, digits, and the -underscore character be used in column names (with no embedded -spaces). Trailing blank characters are not significant. -> \label{ffgcno} \label{ffgcnn} -- - int fits_get_colnum / ffgcno - (fitsfile *fptr, int casesen, char *templt, > int *colnum, - int *status) - - int fits_get_colname / ffgcnn - (fitsfile *fptr, int casesen, char *templt, > char *colname, - int *colnum, int *status) -- ->3 Return the data type, vector repeat value, and the width in bytes - of a column in an ASCII or binary table. Allowed values for the - data type in ASCII tables are: TSTRING, TSHORT, TLONG, TFLOAT, and - TDOUBLE. Binary tables also support these types: TLOGICAL, TBIT, - TBYTE, TCOMPLEX and TDBLCOMPLEX. The negative of the data type code - value is returned if it is a variable length array column. Note - that in the case of a 'J' 32-bit integer binary table column, this - routine will return data type = TINT32BIT (which in fact is - equivalent to TLONG). With most current C compilers, a value in a - 'J' column has the same size as an 'int' variable, and may not be - equivalent to a 'long' variable, which is 64-bits long on an - increasing number of compilers. - - The 'repeat' parameter returns the vector repeat count on the binary - table TFORMn keyword value. (ASCII table columns always have repeat - = 1). The 'width' parameter returns the width in bytes of a single - column element (e.g., a '10D' binary table column will have width = - 8, an ASCII table 'F12.2' column will have width = 12, and a binary - table'60A' character string column will have width = 60); Note that - CFITSIO supports the local convention for specifying arrays of - fixed length strings within a binary table character column using - the syntax TFORM = 'rAw' where 'r' is the total number of characters - (= the width of the column) and 'w' is the width of a unit string - within the column. Thus if the column has TFORM = '60A12' then this - means that each row of the table contains 5 12-character substrings - within the 60-character field, and thus in this case this routine will - return typecode = TSTRING, repeat = 60, and width = 12. (The TDIMn - keyword may also be used to specify the unit string length; The pair - of keywords TFORMn = '60A' and TDIMn = '(12,5)' would have the - same effect as TFORMn = '60A12'). The number - of substrings in any binary table character string field can be - calculated by (repeat/width). A null pointer may be given for any of - the output parameters that are not needed. - - The second routine, fit\_get\_eqcoltype is similar except that in - the case of scaled integer columns it returns the 'equivalent' data - type that is needed to store the scaled values, and not necessarily - the physical data type of the unscaled values as stored in the FITS - table. For example if a '1I' column in a binary table has TSCALn = - 1 and TZEROn = 32768, then this column effectively contains unsigned - short integer values, and thus the returned value of typecode will - be TUSHORT, not TSHORT. Similarly, if a column has TTYPEn = '1I' - and TSCALn = 0.12, then the returned typecode -> will be TFLOAT. \label{ffgtcl} -- - int fits_get_coltype / ffgtcl - (fitsfile *fptr, int colnum, > int *typecode, long *repeat, - long *width, int *status) - - int fits_get_coltypell / ffgtclll - (fitsfile *fptr, int colnum, > int *typecode, LONGLONG *repeat, - LONGLONG *width, int *status) - - int fits_get_eqcoltype / ffeqty - (fitsfile *fptr, int colnum, > int *typecode, long *repeat, - long *width, int *status) - - int fits_get_eqcoltypell / ffeqtyll - (fitsfile *fptr, int colnum, > int *typecode, LONGLONG *repeat, - LONGLONG *width, int *status) -- ->4 Return the display width of a column. This is the length - of the string that will be returned by the fits\_read\_col routine - when reading the column as a formatted string. The display width is - determined by the TDISPn keyword, if present, otherwise by the data -> type of the column. \label{ffgcdw} -- - int fits_get_col_display_width / ffgcdw - (fitsfile *fptr, int colnum, > int *dispwidth, int *status) -- - ->5 Return the number of and size of the dimensions of a table column in - a binary table. Normally this information is given by the TDIMn keyword, - but if this keyword is not present then this routine returns naxis = 1 -> and naxes[0] equal to the repeat count in the TFORM keyword. \label{ffgtdm} -- - int fits_read_tdim / ffgtdm - (fitsfile *fptr, int colnum, int maxdim, > int *naxis, - long *naxes, int *status) - - int fits_read_tdimll / ffgtdmll - (fitsfile *fptr, int colnum, int maxdim, > int *naxis, - LONGLONG *naxes, int *status) -- ->6 Decode the input TDIMn keyword string (e.g. '(100,200)') and return the - number of and size of the dimensions of a binary table column. If the input - tdimstr character string is null, then this routine returns naxis = 1 - and naxes[0] equal to the repeat count in the TFORM keyword. This routine -> is called by fits\_read\_tdim. \label{ffdtdm} -- - int fits_decode_tdim / ffdtdm - (fitsfile *fptr, char *tdimstr, int colnum, int maxdim, > int *naxis, - long *naxes, int *status) - - int fits_decode_tdimll / ffdtdmll - (fitsfile *fptr, char *tdimstr, int colnum, int maxdim, > int *naxis, - LONGLONG *naxes, int *status) -- ->7 Write a TDIMn keyword whose value has the form '(l,m,n...)' - where l, m, n... are the dimensions of a multidimensional array -> column in a binary table. \label{ffptdm} -- - int fits_write_tdim / ffptdm - (fitsfile *fptr, int colnum, int naxis, long *naxes, > int *status) - - int fits_write_tdimll / ffptdmll - (fitsfile *fptr, int colnum, int naxis, LONGLONG *naxes, > int *status) -- - -***3. Routines to Edit Rows or Columns - ->1 Insert or delete rows in an ASCII or binary table. When inserting rows - all the rows following row FROW are shifted down by NROWS rows; if - FROW = 0 then the blank rows are inserted at the beginning of the - table. Note that it is *not* necessary to insert rows in a table before - writing data to those rows (indeed, it would be inefficient to do so). - Instead one may simply write data to any row of the table, whether that - row of data already exists or not. - - The first delete routine deletes NROWS consecutive rows - starting with row FIRSTROW. The second delete routine takes an - input string that lists the rows or row ranges (e.g., - '5-10,12,20-30'), whereas the third delete routine takes an input - integer array that specifies each individual row to be deleted. In - both latter cases, the input list of rows to delete must be sorted - in ascending order. These routines update the NAXIS2 keyword to - reflect the new number of rows in the -> table. \label{ffirow} \label{ffdrow} \label{ffdrws} \label{ffdrrg} -- - int fits_insert_rows / ffirow - (fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, > int *status) - - int fits_delete_rows / ffdrow - (fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, > int *status) - - int fits_delete_rowrange / ffdrrg - (fitsfile *fptr, char *rangelist, > int *status) - - int fits_delete_rowlist / ffdrws - (fitsfile *fptr, long *rowlist, long nrows, > int *status) - - int fits_delete_rowlistll / ffdrwsll - (fitsfile *fptr, LONGLONG *rowlist, LONGLONG nrows, > int *status) -- ->2 Insert or delete column(s) in an ASCII or binary - table. When inserting, COLNUM specifies the column number that the - (first) new column should occupy in the table. NCOLS specifies how - many columns are to be inserted. Any existing columns from this - position and higher are shifted over to allow room for the new - column(s). The index number on all the following keywords will be - incremented or decremented if necessary to reflect the new position - of the column(s) in the table: TBCOLn, TFORMn, TTYPEn, TUNITn, - TNULLn, TSCALn, TZEROn, TDISPn, TDIMn, TLMINn, TLMAXn, TDMINn, - TDMAXn, TCTYPn, TCRPXn, TCRVLn, TCDLTn, TCROTn, -> and TCUNIn. \label{fficol} \label{fficls} \label{ffdcol} -- - int fits_insert_col / fficol - (fitsfile *fptr, int colnum, char *ttype, char *tform, - > int *status) - - int fits_insert_cols / fficls - (fitsfile *fptr, int colnum, int ncols, char **ttype, - char **tform, > int *status) - - int fits_delete_col / ffdcol(fitsfile *fptr, int colnum, > int *status) -- ->3 Copy a column from one HDU to another (or to the same HDU). If - create\_col = TRUE, then a new column will be inserted in the output - table, at position `outcolumn', otherwise the existing output column will - be overwritten (in which case it must have a compatible data type). - If outcolnum is greater than the number of column in the table, then - the new column will be appended to the end of the table. - Note that the first column in a table is at colnum = 1. - The standard indexed keywords that related to the column (e.g., TDISPn, -> TUNITn, TCRPXn, TCDLTn, etc.) will also be copied. \label{ffcpcl} -- - int fits_copy_col / ffcpcl - (fitsfile *infptr, fitsfile *outfptr, int incolnum, int outcolnum, - int create_col, > int *status); -- ->4 Copy 'nrows' consecutive rows from one table to another, beginning - with row 'firstrow'. These rows will be appended to any existing - rows in the output table. -> Note that the first row in a table is at row = 1. \label{ffcprw} -- - int fits_copy_rows / ffcprw - (fitsfile *infptr, fitsfile *outfptr, LONGLONG firstrow, - LONGLONG nrows, > int *status); -- ->5 Modify the vector length of a binary table column (e.g., - change a column from TFORMn = '1E' to '20E'). The vector -> length may be increased or decreased from the current value. \label{ffmvec} -- - int fits_modify_vector_len / ffmvec - (fitsfile *fptr, int colnum, LONGLONG newveclen, > int *status) -- -***4. Read and Write Column Data Routines - -The following routines write or read data values in the current ASCII -or binary table extension. If a write operation extends beyond the -current size of the table, then the number of rows in the table will -automatically be increased and the NAXIS2 keyword value will be -updated. Attempts to read beyond the end of the table will result in -an error. - -Automatic data type conversion is performed for numerical data types -(only) if the data type of the column (defined by the TFORMn keyword) -differs from the data type of the array in the calling routine. ASCII and binary -tables support the following data type values: TSTRING, TBYTE, TSBYTE, TSHORT, -TUSHORT, TINT, TUINT, TLONG, TLONGLONG, TULONG, TFLOAT, or TDOUBLE. -Binary tables also support TLOGICAL (internally mapped to the `char' -data type), TCOMPLEX, and TDBLCOMPLEX. - -Note that it is *not* necessary to insert rows in a table before -writing data to those rows (indeed, it would be inefficient to do so). -Instead, one may simply write data to any row of the table, whether that -row of data already exists or not. - -Individual bits in a binary table 'X' or 'B' column may be read/written -to/from a *char array by specifying the TBIT datatype. The *char -array will be interpreted as an array of logical TRUE (1) or FALSE (0) -values that correspond to the value of each bit in the FITS 'X' or 'B' column. -Alternatively, the values in a binary table 'X' column may be read/written -8 bits at a time to/from an array of 8-bit integers by specifying the -TBYTE datatype. - -Note that within the context of these routines, the TSTRING data type -corresponds to a C 'char**' data type, i.e., a pointer to an array of -pointers to an array of characters. This is different from the keyword -reading and writing routines where TSTRING corresponds to a C 'char*' -data type, i.e., a single pointer to an array of characters. When -reading strings from a table, the char arrays obviously must have been -allocated long enough to hold the whole FITS table string. - -Numerical data values are automatically scaled by the TSCALn and TZEROn -keyword values (if they exist). - -In the case of binary tables with vector elements, the 'felem' -parameter defines the starting element (beginning with 1, not 0) within -the cell (a cell is defined as the intersection of a row and a column -and may contain a single value or a vector of values). The felem -parameter is ignored when dealing with ASCII tables. Similarly, in the -case of binary tables the 'nelements' parameter specifies the total -number of vector values to be read or written (continuing on subsequent -rows if required) and not the number of table cells. - ->>1 Write elements into an ASCII or binary table column. - The first routine simply writes the array of values to the FITS file - (doing data type conversion if necessary) whereas the second routine - will substitute the appropriate FITS null value for all elements - which are equal to the input value of nulval (note that this - parameter gives the address of nulval, not the null value - itself). For integer columns the FITS null value is defined by the - TNULLn keyword (an error is returned if the keyword doesn't exist). - For floating point columns the special IEEE NaN (Not-a-Number) - value will be written into the FITS file. If a null pointer is - entered for nulval, then the null value is ignored and this routine - behaves the same as the first routine. The third routine - simply writes undefined pixel values to the column. The fourth routine - fills every column in the table with null values, in the specified - rows (ignoring any columns that do not have a defined null value). - \label{ffpcl} \label{ffpcn} \label{ffpclu} -- - int fits_write_col / ffpcl - (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, - LONGLONG firstelem, LONGLONG nelements, DTYPE *array, > int *status) - - int fits_write_colnull / ffpcn - (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, - LONGLONG firstelem, LONGLONG nelements, DTYPE *array, DTYPE *nulval, - > int *status) - - int fits_write_col_null / ffpclu - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, > int *status) - - int fits_write_nullrows / ffprwu - (fitsfile *fptr, LONGLONG firstrow, LONGLONG nelements, > int *status) -- ->2 Read elements from an ASCII or binary table column. The data type - parameter specifies the data type of the `nulval' and `array' pointers; - Undefined array elements will be returned with a value = *nullval, - (note that this parameter gives the address of the null value, not the - null value itself) unless nulval = 0 or *nulval = 0, in which case - no checking for undefined pixels will be performed. The second - routine is similar except that any undefined pixels will have the - corresponding nullarray element set equal to TRUE (= 1). - - Any column, regardless of it's intrinsic data type, may be read as a - string. It should be noted however that reading a numeric column - as a string is 10 - 100 times slower than reading the same column - as a number due to the large overhead in constructing the formatted - strings. The display format of the returned strings will be - determined by the TDISPn keyword, if it exists, otherwise by the - data type of the column. The length of the returned strings (not - including the null terminating character) can be determined with - the fits\_get\_col\_display\_width routine. The following TDISPn - display formats are currently supported: -- - Iw.m Integer - Ow.m Octal integer - Zw.m Hexadecimal integer - Fw.d Fixed floating point - Ew.d Exponential floating point - Dw.d Exponential floating point - Gw.d General; uses Fw.d if significance not lost, else Ew.d -- - where w is the width in characters of the displayed values, m is the minimum - number of digits displayed, and d is the number of digits to the right of the - decimal. The .m field is optional. -> \label{ffgcv} \label{ffgcf} -- - int fits_read_col / ffgcv - (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, DTYPE *nulval, DTYPE *array, int *anynul, int *status) - - int fits_read_colnull / ffgcf - (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, DTYPE *array, char *nullarray, int *anynul, int *status) -- - -***5. Row Selection and Calculator Routines - -These routines all parse and evaluate an input string containing a user -defined arithmetic expression. The first 3 routines select rows in a -FITS table, based on whether the expression evaluates to true (not -equal to zero) or false (zero). The other routines evaluate the -expression and calculate a value for each row of the table. The -allowed expression syntax is described in the row filter section in the -`Extended File Name Syntax' chapter of this document. The expression -may also be written to a text file, and the name of the file, prepended -with a '@' character may be supplied for the 'expr' parameter (e.g. -'@filename.txt'). The expression in the file can be arbitrarily -complex and extend over multiple lines of the file. Lines that begin -with 2 slash characters ('//') will be ignored and may be used to add -comments to the file. - ->1 Evaluate a boolean expression over the indicated rows, returning an - array of flags indicating which rows evaluated to TRUE/FALSE. - Upon return, -> *n\_good\_rows contains the number of rows that evaluate to TRUE. \label{fffrow} -- - int fits_find_rows / fffrow - (fitsfile *fptr, char *expr, long firstrow, long nrows, - > long *n_good_rows, char *row_status, int *status) -- ->>2 Find the first row which satisfies the input boolean expression \label{ffffrw} -- - int fits_find_first_row / ffffrw - (fitsfile *fptr, char *expr, > long *rownum, int *status) -- ->3 Evaluate an expression on all rows of a table. If the input and output -files are not the same, copy the TRUE rows to the output file; if the output -table is not empty, then this routine will append the new -selected rows after the existing rows. If the ->files are the same, delete the FALSE rows (preserve the TRUE rows). \label{ffsrow} -- - int fits_select_rows / ffsrow - (fitsfile *infptr, fitsfile *outfptr, char *expr, > int *status ) -- ->4 Calculate an expression for the indicated rows of a table, returning -the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If -nulval==NULL, UNDEFs will be zeroed out. For vector results, the number -of elements returned may be less than nelements if nelements is not an -even multiple of the result dimension. Call fits\_test\_expr to obtain ->the dimensions of the results. \label{ffcrow} -- - int fits_calc_rows / ffcrow - (fitsfile *fptr, int datatype, char *expr, long firstrow, - long nelements, void *nulval, > void *array, int *anynul, int *status) -- ->5 Evaluate an expression and write the result either to a column (if -the expression is a function of other columns in the table) or to a -keyword (if the expression evaluates to a constant and is not a -function of other columns in the table). In the former case, the -parName parameter is the name of the column (which may or may not already -exist) into which to write the results, and parInfo contains an -optional TFORM keyword value if a new column is being created. If a -TFORM value is not specified then a default format will be used, -depending on the expression. If the expression evaluates to a constant, -then the result will be written to the keyword name given by the -parName parameter, and the parInfo parameter may be used to supply an -optional comment for the keyword. If the keyword does not already -exist, then the name of the keyword must be preceded with a '\#' character, -> otherwise the result will be written to a column with that name. \label{ffcalc} -- - int fits_calculator / ffcalc - (fitsfile *infptr, char *expr, fitsfile *outfptr, char *parName, - char *parInfo, > int *status) -- ->6 This calculator routine is similar to the previous routine, except -that the expression is only evaluated over the specified -row ranges. nranges specifies the number of row ranges, and firstrow ->and lastrow give the starting and ending row number of each range. \label{ffcalcrng} -- - int fits_calculator_rng / ffcalc_rng - (fitsfile *infptr, char *expr, fitsfile *outfptr, char *parName, - char *parInfo, int nranges, long *firstrow, long *lastrow - > int *status) -- ->7 Evaluate the given expression and return dimension and type information -on the result. The returned dimensions correspond to a single row entry -of the requested expression, and are equivalent to the result of fits\_read\_tdim(). -Note that strings are considered to be one element regardless of string length. ->If maxdim == 0, then naxes is optional. \label{fftexp} -- - int fits_test_expr / fftexp - (fitsfile *fptr, char *expr, int maxdim > int *datatype, long *nelem, int *naxis, - long *naxes, int *status) -- - -***6. Column Binning or Histogramming Routines - -The following routines may be useful when performing histogramming operations on -column(s) of a table to generate an image in a primary array or image extension. - ->1 Calculate the histogramming parameters (min, max, and bin size -for each axis of the histogram, based on a variety of possible input parameters. -If the input names of the columns to be binned are null, then the routine will first -look for the CPREF = "NAME1, NAME2, ..." keyword which lists the preferred -columns. If not present, then the routine will assume the column names X, Y, Z, and T -for up to 4 axes (as specified by the NAXIS parameter). - -MININ and MAXIN are input arrays that give the minimum and maximum value for -the histogram, along each axis. Alternatively, the name of keywords that give -the min, max, and binsize may be give with the MINNAME, MAXNAME, and BINNAME -array parameters. If the value = DOUBLENULLVALUE and no keyword names are -given, then the routine will use the TLMINn and TLMAXn keywords, if present, or the -actual min and/or max values in the column. - -BINSIZEIN is an array giving the binsize along each axis. -If the value = -DOUBLENULLVALUE, and a keyword name is not specified with BINNAME, -then this routine will first look for the TDBINn keyword, or else will -use a binsize = 1, or a binsize that produces 10 histogram bins, which ever -is smaller. -> \label{calcbinning} -- - int fits_calc_binning - Input parameters: - (fitsfile *fptr, /* IO - pointer to table to be binned */ - int naxis, /* I - number of axes/columns in the binned image */ - char colname[4][FLEN_VALUE], /* I - optional column names */ - double *minin, /* I - optional lower bound value for each axis */ - double *maxin, /* I - optional upper bound value, for each axis */ - double *binsizein, /* I - optional bin size along each axis */ - char minname[4][FLEN_VALUE], /* I - optional keywords for min */ - char maxname[4][FLEN_VALUE], /* I - optional keywords for max */ - char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */ - Output parameters: - int *colnum, /* O - column numbers, to be binned */ - long *naxes, /* O - number of bins in each histogram axis */ - float *amin, /* O - lower bound of the histogram axes */ - float *amax, /* O - upper bound of the histogram axes */ - float *binsize, /* O - width of histogram bins/pixels on each axis */ - int *status) -- - ->2 Copy the relevant keywords from the header of the table that is being -binned, to the the header of the output histogram image. This will not -copy the table structure keywords (e.g., NAXIS, TFORMn, TTYPEn, etc.) nor -will it copy the keywords that apply to other columns of the table that are -not used to create the histogram. This routine will translate the names of -the World Coordinate System (WCS) keywords for the binned columns into the -form that is need for a FITS image (e.g., the TCTYPn table keyword will -be translated to the CTYPEn image keyword). -> \label{copypixlist2image} -- - int fits_copy_pixlist2image - (fitsfile *infptr, /* I - pointer to input HDU */ - fitsfile *outfptr, /* I - pointer to output HDU */ - int firstkey, /* I - first HDU keyword to start with */ - int naxis, /* I - number of axes in the image */ - int *colnum, /* I - numbers of the columns to be binned */ - int *status) /* IO - error status */ -- - ->3 Write a set of default WCS keywords to the histogram header, IF the -WCS keywords do not already exist. This will create a linear WCS where -the coordinate types are equal to the original column names. -> \label{writekeyshisto} -- - int fits_write_keys_histo - (fitsfile *fptr, /* I - pointer to table to be binned */ - fitsfile *histptr, /* I - pointer to output histogram image HDU */ - int naxis, /* I - number of axes in the histogram image */ - int *colnum, /* I - column numbers of the binned columns */ - int *status) -- - ->4 Update the WCS keywords in a histogram image header that give the location -of the reference pixel (CRPIXn), and the pixel size (CDELTn), in the binned -image. -> \label{rebinwcs} -- - int fits_rebin_wcs - (fitsfile *fptr, /* I - pointer to table to be binned */ - int naxis, /* I - number of axes in the histogram image */ - float *amin, /* I - first pixel include in each axis */ - float *binsize, /* I - binning factor for each axis */ - int *status) -- - ->5 Bin the values in the input table columns, and write the histogram -array to the output FITS image (histptr). -> \label{makehist} -- - int fits_make_hist - (fitsfile *fptr, /* I - pointer to table with X and Y cols; */ - fitsfile *histptr, /* I - pointer to output FITS image */ - int bitpix, /* I - datatype for image: 16, 32, -32, etc */ - int naxis, /* I - number of axes in the histogram image */ - long *naxes, /* I - size of axes in the histogram image */ - int *colnum, /* I - column numbers (array length = naxis) */ - float *amin, /* I - minimum histogram value, for each axis */ - float *amax, /* I - maximum histogram value, for each axis */ - float *binsize, /* I - bin size along each axis */ - float weight, /* I - binning weighting factor (FLOATNULLVALUE */ - /* for no weighting) */ - int wtcolnum, /* I - keyword or col for weight (or NULL) */ - int recip, /* I - use reciprocal of the weight? 0 or 1 */ - char *selectrow, /* I - optional array (length = no. of */ - /* rows in the table). If the element is true */ - /* then the corresponding row of the table will */ - /* be included in the histogram, otherwise the */ - /* row will be skipped. Ingnored if *selectrow */ - /* is equal to NULL. */ - int *status) -- - - -**H. Utility Routines - -***1. File Checksum Routines - -The following routines either compute or validate the checksums for the -CHDU. The DATASUM keyword is used to store the numerical value of the -32-bit, 1's complement checksum for the data unit alone. If there is -no data unit then the value is set to zero. The numerical value is -stored as an ASCII string of digits, enclosed in quotes, because the -value may be too large to represent as a 32-bit signed integer. The -CHECKSUM keyword is used to store the ASCII encoded COMPLEMENT of the -checksum for the entire HDU. Storing the complement, rather than the -actual checksum, forces the checksum for the whole HDU to equal zero. -If the file has been modified since the checksums were computed, then -the HDU checksum will usually not equal zero. These checksum keyword -conventions are based on a paper by Rob Seaman published in the -proceedings of the ADASS IV conference in Baltimore in November 1994 -and a later revision in June 1995. See Appendix B for the definition -of the parameters used in these routines. - ->1 Compute and write the DATASUM and CHECKSUM keyword values for the CHDU - into the current header. If the keywords already exist, their values - will be updated only if necessary (i.e., if the file - has been modified since the original keyword -> values were computed). \label{ffpcks} -- - int fits_write_chksum / ffpcks - (fitsfile *fptr, > int *status) -- ->2 Update the CHECKSUM keyword value in the CHDU, assuming that the - DATASUM keyword exists and already has the correct value. This routine - calculates the new checksum for the current header unit, adds it to the - data unit checksum, encodes the value into an ASCII string, and writes -> the string to the CHECKSUM keyword. \label{ffupck} -- - int fits_update_chksum / ffupck - (fitsfile *fptr, > int *status) -- ->3 Verify the CHDU by computing the checksums and comparing - them with the keywords. The data unit is verified correctly - if the computed checksum equals the value of the DATASUM - keyword. The checksum for the entire HDU (header plus data unit) is - correct if it equals zero. The output DATAOK and HDUOK parameters - in this routine are integers which will have a value = 1 - if the data or HDU is verified correctly, a value = 0 - if the DATASUM or CHECKSUM keyword is not present, or value = -1 -> if the computed checksum is not correct. \label{ffvcks} -- - int fits_verify_chksum / ffvcks - (fitsfile *fptr, > int *dataok, int *hduok, int *status) -- ->4 Compute and return the checksum values for the CHDU - without creating or modifying the - CHECKSUM and DATASUM keywords. This routine is used internally by -> ffvcks, but may be useful in other situations as well. \label{ffgcks} -- - int fits_get_chksum/ /ffgcks - (fitsfile *fptr, > unsigned long *datasum, unsigned long *hdusum, - int *status) -- ->5 Encode a checksum value - into a 16-character string. If complm is non-zero (true) then the 32-bit -> sum value will be complemented before encoding. \label{ffesum} -- - int fits_encode_chksum / ffesum - (unsigned long sum, int complm, > char *ascii); -- ->6 Decode a 16-character checksum string into a unsigned long value. - If is non-zero (true). then the 32-bit sum value will be complemented - after decoding. The checksum value is also returned as the -> value of the function. \label{ffdsum} -- - unsigned long fits_decode_chksum / ffdsum - (char *ascii, int complm, > unsigned long *sum); -- - -***2. Date and Time Utility Routines - -The following routines help to construct or parse the FITS date/time -strings. Starting in the year 2000, the FITS DATE keyword values (and -the values of other `DATE-' keywords) must have the form 'YYYY-MM-DD' -(date only) or 'YYYY-MM-DDThh:mm:ss.ddd...' (date and time) where the -number of decimal places in the seconds value is optional. These times -are in UTC. The older 'dd/mm/yy' date format may not be used for dates -after 01 January 2000. See Appendix B for the definition of the -parameters used in these routines. - ->1 Get the current system date. C already provides standard - library routines for getting the current date and time, - but this routine is provided for compatibility with - the Fortran FITSIO library. The returned year has 4 digits -> (1999, 2000, etc.) \label{ffgsdt} -- - int fits_get_system_date/ffgsdt - ( > int *day, int *month, int *year, int *status ) -- - ->2 Get the current system date and time string ('YYYY-MM-DDThh:mm:ss'). -The time will be in UTC/GMT if available, as indicated by a returned timeref -value = 0. If the returned value of timeref = 1 then this indicates that -it was not possible to convert the local time to UTC, and thus the local ->time was returned. -- - int fits_get_system_time/ffgstm - (> char *datestr, int *timeref, int *status) -- - ->3 Construct a date string from the input date values. If the year -is between 1900 and 1998, inclusive, then the returned date string will -have the old FITS format ('dd/mm/yy'), otherwise the date string will -have the new FITS format ('YYYY-MM-DD'). Use fits\_time2str instead -> to always return a date string using the new FITS format. \label{ffdt2s} -- - int fits_date2str/ffdt2s - (int year, int month, int day, > char *datestr, int *status) -- - ->4 Construct a new-format date + time string ('YYYY-MM-DDThh:mm:ss.ddd...'). - If the year, month, and day values all = 0 then only the time is encoded - with format 'hh:mm:ss.ddd...'. The decimals parameter specifies how many - decimal places of fractional seconds to include in the string. If `decimals' -> is negative, then only the date will be return ('YYYY-MM-DD'). -- - int fits_time2str/fftm2s - (int year, int month, int day, int hour, int minute, double second, - int decimals, > char *datestr, int *status) -- - ->5 Return the date as read from the input string, where the string may be -in either the old ('dd/mm/yy') or new ('YYYY-MM-DDThh:mm:ss' or -'YYYY-MM-DD') FITS format. Null pointers may be supplied for any -> unwanted output date parameters. -- - int fits_str2date/ffs2dt - (char *datestr, > int *year, int *month, int *day, int *status) -- - ->6 Return the date and time as read from the input string, where the -string may be in either the old or new FITS format. The returned hours, -minutes, and seconds values will be set to zero if the input string -does not include the time ('dd/mm/yy' or 'YYYY-MM-DD') . Similarly, -the returned year, month, and date values will be set to zero if the -date is not included in the input string ('hh:mm:ss.ddd...'). Null -pointers may be supplied for any unwanted output date and time ->parameters. -- - int fits_str2time/ffs2tm - (char *datestr, > int *year, int *month, int *day, int *hour, - int *minute, double *second, int *status) -- - -***3. General Utility Routines - -The following utility routines may be useful for certain applications. - ->1 Return the revision number of the CFITSIO library. - The revision number will be incremented with each new -> release of CFITSIO. \label{ffvers} -- - float fits_get_version / ffvers ( > float *version) -- ->2 Write an 80-character message to the CFITSIO error stack. Application - programs should not normally write to the stack, but there may be -> some situations where this is desirable. \label{ffpmsg} -- - void fits_write_errmsg / ffpmsg (char *err_msg) -- ->>3 Convert a character string to uppercase (operates in place). \label{ffupch} -- - void fits_uppercase / ffupch (char *string) -- ->4 Compare the input template string against the reference string - to see if they match. The template string may contain wildcard - characters: '*' will match any sequence of characters (including - zero characters) and '?' will match any single character in the - reference string. The '\#' character will match any consecutive string - of decimal digits (0 - 9). If casesen = CASESEN = TRUE then the match will - be case sensitive, otherwise the case of the letters will be ignored - if casesen = CASEINSEN = FALSE. The returned MATCH parameter will be - TRUE if the 2 strings match, and EXACT will be TRUE if the match is - exact (i.e., if no wildcard characters were used in the match). -> Both strings must be 68 characters or less in length. \label{ffcmps} -- - void fits_compare_str / ffcmps - (char *templt, char *string, int casesen, > int *match, int *exact) -- ->5 Split a string containing a list of names (typically file names or column - names) into individual name tokens by a sequence of calls to - fits\_split\_names. The names in the list must be delimited by a comma - and/or spaces. This routine ignores spaces and commas that occur - within parentheses, brackets, or curly brackets. It also strips any - leading and trailing blanks from the returned name. - - This routine is similar to the ANSI C 'strtok' function: - - The first call to fits\_split\_names has a non-null input string. - It finds the first name in the string and terminates it by overwriting - the next character of the string with a null terminator and returns a - pointer to the name. Each subsequent call, indicated by a NULL value - of the input string, returns the next name, searching from just past - the end of the previous name. It returns NULL when no further names -> are found. \label{splitnames} -- - char *fits_split_names(char *namelist) -- - The following example shows how a string would be split into 3 names: -- - myfile[1][bin (x,y)=4], file2.fits file3.fits - ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ - 1st name 2nd name 3rd name -- ->6 Test that the keyword name contains only legal characters (A-Z,0-9, - hyphen, and underscore) or that the keyword record contains only legal -> printable ASCII characters \label{fftkey} \label{fftrec} -- - int fits_test_keyword / fftkey (char *keyname, > int *status) - - int fits_test_record / fftrec (char *card, > int *status) -- ->7 Test whether the current header contains any NULL (ASCII 0) characters. - These characters are illegal in the header, but they will go undetected - by most of the CFITSIO keyword header routines, because the null is - interpreted as the normal end-of-string terminator. This routine returns - the position of the first null character in the header, or zero if there - are no nulls. For example a returned value of 110 would indicate that - the first NULL is located in the 30th character of the second keyword - in the header (recall that each header record is 80 characters long). - Note that this is one of the few CFITSIO routines in which the returned -> value is not necessarily equal to the status value). \label{ffnchk} -- - int fits_null_check / ffnchk (char *card, > int *status) -- ->8 Parse a header keyword record and return the name of the keyword, - and the length of the name. - The keyword name normally occupies the first 8 characters of the - record, except under the HIERARCH convention where the name can -> be up to 70 characters in length. \label{ffgknm} -- - int fits_get_keyname / ffgknm - (char *card, > char *keyname, int *keylength, int *status) -- ->9 Parse a header keyword record, returning the value (as - a literal character string) and comment strings. If the keyword has no - value (columns 9-10 not equal to '= '), then a null value string is - returned and the comment string is set equal to column 9 - 80 of the -> input string. \label{ffpsvc} -- - int fits_parse_value / ffpsvc - (char *card, > char *value, char *comment, int *status) -- ->10 Construct a properly formated 80-character header keyword record from the - input keyword name, keyword value, and keyword comment strings. - Hierarchical keyword names (e.g., "ESO TELE CAM") are supported. - The value string may contain an integer, floating point, logical, or - quoted character string (e.g., "12", "15.7", "T", -> or "'NGC 1313'"). \label{ffmkky} -- - int fits_make_key / ffmkky - (const char *keyname, const char *value, const char *comment, - > char *card, int *status) -- ->11 Construct an array indexed keyword name (ROOT + nnn). - This routine appends the sequence number to the root string to create -> a keyword name (e.g., 'NAXIS' + 2 = 'NAXIS2') \label{ffkeyn} -- - int fits_make_keyn / ffkeyn - (char *keyroot, int value, > char *keyname, int *status) -- ->12 Construct a sequence keyword name (n + ROOT). - This routine concatenates the sequence number to the front of the -> root string to create a keyword name (e.g., 1 + 'CTYP' = '1CTYP') \label{ffnkey} -- - int fits_make_nkey / ffnkey - (int value, char *keyroot, > char *keyname, int *status) -- ->13 Determine the data type of a keyword value string. This routine - parses the keyword value string to determine its data type. - Returns 'C', 'L', 'I', 'F' or 'X', for character string, logical, -> integer, floating point, or complex, respectively. \label{ffdtyp} -- - int fits_get_keytype / ffdtyp - (char *value, > char *dtype, int *status) -- ->14 Determine the integer data type of an integer keyword value string. - The returned datatype value is the minimum integer datatype (starting - from top of the following list and working down) required -> to store the integer value: -- - Data Type Range - TSBYTE: -128 to 127 - TBYTE: 128 to 255 - TSHORT: -32768 to 32767 - TUSHORT: 32768 to 65535 - TINT -2147483648 to 2147483647 - TUINT 2147483648 to 4294967295 - TLONGLONG -9223372036854775808 to 9223372036854775807 -- -> The *neg parameter returns 1 if the input value is -> negative and returns 0 if it is non-negative.\label{ffinttyp} -- - int fits_get_inttype / ffinttyp - (char *value, > int *datatype, int *neg, int *status) -- ->15 Return the class of an input header record. The record is classified - into one of the following categories (the class values are - defined in fitsio.h). Note that this is one of the few CFITSIO -> routines that does not return a status value. \label{ffgkcl} -- - Class Value Keywords - TYP_STRUC_KEY 10 SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, - GROUPS, PCOUNT, GCOUNT, END - XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, - and the first 4 COMMENT keywords in the primary array - that define the FITS format. - TYP_CMPRS_KEY 20 The keywords used in the compressed image or table - format, including ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, - ZTILEn, ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK - TYP_SCAL_KEY 30 BSCALE, BZERO, TSCALn, TZEROn - TYP_NULL_KEY 40 BLANK, TNULLn - TYP_DIM_KEY 50 TDIMn - TYP_RANG_KEY 60 TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX - TYP_UNIT_KEY 70 BUNIT, TUNITn - TYP_DISP_KEY 80 TDISPn - TYP_HDUID_KEY 90 EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL - TYP_CKSUM_KEY 100 CHECKSUM, DATASUM - TYP_WCS_KEY 110 WCS keywords defined in the the WCS papers, including: - CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn - CDj_is, PVj_ms, LONPOLEs, LATPOLEs - TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, - TCRPks, TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn - jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, - iCRPns, jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn - (i,j,m,n are integers, s is any letter) - TYP_REFSYS_KEY 120 EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs, DATE-OBS - TYP_COMM_KEY 130 COMMENT, HISTORY, (blank keyword) - TYP_CONT_KEY 140 CONTINUE - TYP_USER_KEY 150 all other keywords - - int fits_get_keyclass / ffgkcl (char *card) -- ->16 Parse the 'TFORM' binary table column format string. - This routine parses the input TFORM character string and returns the - integer data type code, the repeat count of the field, and, in the case - of character string fields, the length of the unit string. See Appendix - B for the allowed values for the returned typecode parameter. A -> null pointer may be given for any output parameters that are not needed. \label{ffbnfm} -- - int fits_binary_tform / ffbnfm - (char *tform, > int *typecode, long *repeat, long *width, - int *status) - - int fits_binary_tformll / ffbnfmll - (char *tform, > int *typecode, LONGLONG *repeat, long *width, - int *status) -- ->17 Parse the 'TFORM' keyword value that defines the column format in - an ASCII table. This routine parses the input TFORM character - string and returns the data type code, the width of the column, - and (if it is a floating point column) the number of decimal places - to the right of the decimal point. The returned data type codes are - the same as for the binary table, with the following - additional rules: integer columns that are between 1 and 4 characters - wide are defined to be short integers (code = TSHORT). Wider integer - columns are defined to be regular integers (code = TLONG). Similarly, - Fixed decimal point columns (with TFORM = 'Fw.d') are defined to - be single precision reals (code = TFLOAT) if w is between 1 and 7 characters - wide, inclusive. Wider 'F' columns will return a double precision - data code (= TDOUBLE). 'Ew.d' format columns will have datacode = TFLOAT, - and 'Dw.d' format columns will have datacode = TDOUBLE. A null -> pointer may be given for any output parameters that are not needed. \label{ffasfm} -- - int fits_ascii_tform / ffasfm - (char *tform, > int *typecode, long *width, int *decimals, - int *status) -- ->18 Calculate the starting column positions and total ASCII table width - based on the input array of ASCII table TFORM values. The SPACE input - parameter defines how many blank spaces to leave between each column - (it is recommended to have one space between columns for better human -> readability). \label{ffgabc} -- - int fits_get_tbcol / ffgabc - (int tfields, char **tform, int space, > long *rowlen, - long *tbcol, int *status) -- ->19 Parse a template header record and return a formatted 80-character string - suitable for appending to (or deleting from) a FITS header file. - This routine is useful for parsing lines from an ASCII template file - and reformatting them into legal FITS header records. The formatted - string may then be passed to the fits\_write\_record, ffmcrd, or - fits\_delete\_key routines -> to append or modify a FITS header record. \label{ffgthd} -- - int fits_parse_template / ffgthd - (char *templt, > char *card, int *keytype, int *status) -- - The input templt character string generally should contain 3 tokens: - (1) the KEYNAME, (2) the VALUE, and (3) the COMMENT string. The - TEMPLATE string must adhere to the following format: - ->- The KEYNAME token must begin in columns 1-8 and be a maximum of 8 - characters long. A legal FITS keyword name may only - contain the characters A-Z, 0-9, and '-' (minus sign) and - underscore. This routine will automatically convert any lowercase - characters to uppercase in the output string. If the first 8 characters - of the template line are - blank then the remainder of the line is considered to be a FITS comment -> (with a blank keyword name). - ->- The VALUE token must be separated from the KEYNAME token by one or more - spaces and/or an '=' character. The data type of the VALUE token - (numeric, logical, or character string) is automatically determined - and the output CARD string is formatted accordingly. The value - token may be forced to be interpreted as a string (e.g. if it is a - string of numeric digits) by enclosing it in single quotes. - If the value token is a character string that contains 1 or more - embedded blank space characters or slash ('/') characters then the -> entire character string must be enclosed in single quotes. - ->- The COMMENT token is optional, but if present must be separated from -> the VALUE token by a blank space or a '/' character. - ->- One exception to the above rules is that if the first non-blank - character in the first 8 characters of the template string is a - minus sign ('-') followed - by a single token, or a single token followed by an equal sign, - then it is interpreted as the name of a keyword which is to be -> deleted from the FITS header. - ->- The second exception is that if the template string starts with - a minus sign and is followed by 2 tokens (without an equals sign between - them) then the second token - is interpreted as the new name for the keyword specified by - first token. In this case the old keyword name (first token) - is returned in characters 1-8 of the returned CARD string, and - the new keyword name (the second token) is returned in characters - 41-48 of the returned CARD string. These old and new names - may then be passed to the ffmnam routine which will change -> the keyword name. - - The keytype output parameter indicates how the returned CARD string - should be interpreted: -- - keytype interpretation - ------- ------------------------------------------------- - -2 Rename the keyword with name = the first 8 characters of CARD - to the new name given in characters 41 - 48 of CARD. - - -1 delete the keyword with this name from the FITS header. - - 0 append the CARD string to the FITS header if the - keyword does not already exist, otherwise update - the keyword value and/or comment field if is already exists. - - 1 This is a HISTORY or COMMENT keyword; append it to the header - - 2 END record; do not explicitly write it to the FITS file. -- - EXAMPLES: The following lines illustrate valid input template strings: -- - INTVAL 7 / This is an integer keyword - RVAL 34.6 / This is a floating point keyword - EVAL=-12.45E-03 / This is a floating point keyword in exponential notation - lval F / This is a boolean keyword - This is a comment keyword with a blank keyword name - SVAL1 = 'Hello world' / this is a string keyword - SVAL2 '123.5' this is also a string keyword - sval3 123+ / this is also a string keyword with the value '123+ ' - # the following template line deletes the DATE keyword - - DATE - # the following template line modifies the NAME keyword to OBJECT - - NAME OBJECT -- ->20 Translate a keyword name into a new name, based on a set of patterns. -This routine is useful for translating keywords in cases such as -adding or deleting columns in -a table, or copying a column from one table to another, or extracting -an array from a cell in a binary table column into an image extension. In -these cases, it is necessary to translate the names of the keywords associated -with the original table column(s) into the appropriate keyword name in the final -file. For example, if column 2 is deleted from a table, -then the value of 'n' in all the -TFORMn and TTYPEn keywords for columns 3 and higher must be decremented -by 1. Even more complex translations are sometimes needed to convert the -WCS keywords when extracting an image out of a table column cell into -a separate image extension. - -The user passes an array of patterns to be matched. Input pattern -number i is pattern[i][0], and output pattern number i is -pattern[i][1]. Keywords are matched against the input patterns. If a -match is found then the keyword is re-written according to the output -pattern. - -Order is important. The first match is accepted. The fastest match -will be made when templates with the same first character are grouped -together. - -Several characters have special meanings: -- - i,j - single digits, preserved in output template - n - column number of one or more digits, preserved in output template - m - generic number of one or more digits, preserved in output template - a - coordinate designator, preserved in output template - # - number of one or more digits - ? - any character - * - only allowed in first character position, to match all - keywords; only useful as last pattern in the list -- -i, j, n, and m are returned by the routine. - -For example, the input pattern "iCTYPn" will match "1CTYP5" (if n\_value -is 5); the output pattern "CTYPEi" will be re-written as "CTYPE1". -Notice that "i" is preserved. - -The following output patterns are special: - - "-" - do not copy a keyword that matches the corresponding input pattern - - "+" - copy the input unchanged - -The inrec string could be just the 8-char keyword name, or the entire -80-char header record. Characters 9 - 80 in the input string simply get -appended to the translated keyword name. - -If n\_range = 0, then only keywords with 'n' equal to n\_value will be -considered as a pattern match. If n\_range = +1, then all values of -'n' greater than or equal to n\_value will be a match, and if -1, ->then values of 'n' less than or equal to n\_value will match.\label{translatekey} -- -int fits_translate_keyword( - char *inrec, /* I - input string */ - char *outrec, /* O - output converted string, or */ - /* a null string if input does not */ - /* match any of the patterns */ - char *patterns[][2],/* I - pointer to input / output string */ - /* templates */ - int npat, /* I - number of templates passed */ - int n_value, /* I - base 'n' template value of interest */ - int n_offset, /* I - offset to be applied to the 'n' */ - /* value in the output string */ - int n_range, /* I - controls range of 'n' template */ - /* values of interest (-1,0, or +1) */ - int *pat_num, /* O - matched pattern number (0 based) or -1 */ - int *i, /* O - value of i, if any, else 0 */ - int *j, /* O - value of j, if any, else 0 */ - int *m, /* O - value of m, if any, else 0 */ - int *n, /* O - value of n, if any, else 0 */ - int *status) /* IO - error status */ -- -> Here is an example of some of the patterns used to convert the keywords associated -with an image in a cell of a table column into the keywords appropriate for ->an IMAGE extension: -- - char *patterns[][2] = {{"TSCALn", "BSCALE" }, /* Standard FITS keywords */ - {"TZEROn", "BZERO" }, - {"TUNITn", "BUNIT" }, - {"TNULLn", "BLANK" }, - {"TDMINn", "DATAMIN" }, - {"TDMAXn", "DATAMAX" }, - {"iCTYPn", "CTYPEi" }, /* Coordinate labels */ - {"iCTYna", "CTYPEia" }, - {"iCUNIn", "CUNITi" }, /* Coordinate units */ - {"iCUNna", "CUNITia" }, - {"iCRVLn", "CRVALi" }, /* WCS keywords */ - {"iCRVna", "CRVALia" }, - {"iCDLTn", "CDELTi" }, - {"iCDEna", "CDELTia" }, - {"iCRPXn", "CRPIXi" }, - {"iCRPna", "CRPIXia" }, - {"ijPCna", "PCi_ja" }, - {"ijCDna", "CDi_ja" }, - {"iVn_ma", "PVi_ma" }, - {"iSn_ma", "PSi_ma" }, - {"iCRDna", "CRDERia" }, - {"iCSYna", "CSYERia" }, - {"iCROTn", "CROTAi" }, - {"WCAXna", "WCSAXESa"}, - {"WCSNna", "WCSNAMEa"}}; -- ->21 Translate the keywords in the input HDU into the keywords that are -appropriate for the output HDU. This is a driver routine that calls ->the previously described routine. -- -int fits_translate_keywords( - fitsfile *infptr, /* I - pointer to input HDU */ - fitsfile *outfptr, /* I - pointer to output HDU */ - int firstkey, /* I - first HDU record number to start with */ - char *patterns[][2],/* I - pointer to input / output keyword templates */ - int npat, /* I - number of templates passed */ - int n_value, /* I - base 'n' template value of interest */ - int n_offset, /* I - offset to be applied to the 'n' */ - /* value in the output string */ - int n_range, /* I - controls range of 'n' template */ - /* values of interest (-1,0, or +1) */ - int *status) /* IO - error status */ -- - ->22 Parse the input string containing a list of rows or row ranges, and - return integer arrays containing the first and last row in each - range. For example, if rowlist = "3-5, 6, 8-9" then it will - return numranges = 3, rangemin = 3, 6, 8 and rangemax = 5, 6, 9. - At most, 'maxranges' number of ranges will be returned. 'maxrows' - is the maximum number of rows in the table; any rows or ranges - larger than this will be ignored. The rows must be specified in - increasing order, and the ranges must not overlap. A minus sign - may be use to specify all the rows to the upper or lower bound, so - "50-" means all the rows from 50 to the end of the table, and "-" - means all the rows in the table, from 1 - maxrows. -> \label{ffrwrg} -- - int fits_parse_range / ffrwrg(char *rowlist, LONGLONG maxrows, int maxranges, > - int *numranges, long *rangemin, long *rangemax, int *status) - - int fits_parse_rangell / ffrwrgll(char *rowlist, LONGLONG maxrows, int maxranges, > - int *numranges, LONGLONG *rangemin, LONGLONG *rangemax, int *status) -- ->23 Check that the Header fill bytes (if any) are all blank. These are the bytes - that may follow END keyword and before the beginning of data unit, - or the end of the HDU if there is no data unit. -> \label{ffchfl} -- - int ffchfl(fitsfile *fptr, > int *status) -- ->24 Check that the Data fill bytes (if any) are all zero (for IMAGE or - BINARY Table HDU) or all blanks (for ASCII table HDU). These file - bytes may be located after the last valid data byte in the HDU and - before the physical end of the HDU. -> \label{ffcdfl} -- - int ffcdfl(fitsfile *fptr, > int *status) -- ->25 Estimate the root-mean-squared (RMS) noise in an image. -These routines are mainly for use with the Hcompress image compression -algorithm. They return an estimate of the RMS noise in the background -pixels of the image. This robust algorithm (written by Richard -White, STScI) first attempts to estimate the RMS value -as 1.68 times the median of the absolute differences between successive -pixels in the image. If the median = 0, then the -algorithm falls back to computing the RMS of the difference between successive -pixels, after several N-sigma rejection cycles to remove -extreme values. The input parameters are: the array of image pixel values -(either float or short values), the number of values in the array, -the value that is used to represent null pixels (enter a very ->large number if there are no null pixels). \label{imageRMS} -- - int fits_rms_float (float fdata[], int npix, float in_null_value, - > double *rms, int *status) - int fits_rms_short (short fdata[], int npix, short in_null_value, - > double *rms, int *status) -- ->26 Was CFITSIO compiled with the -D\_REENTRANT directive -so that it may be safely used in multi-threaded environments? -The following function returns 1 if yes, 0 if no. Note, however, -that even if the -D\_REENTRANT directive was specified, this does -not guarantee that the CFITSIO routines are thread-safe, because ->some compilers may not support this feature.\label{reentrant} -- -int fits_is_reentrant(void) -- - -*VII. The CFITSIO Iterator Function - -The fits\_iterate\_data function in CFITSIO provides a unique method of -executing an arbitrary user-supplied `work' function that operates on -rows of data in FITS tables or on pixels in FITS images. Rather than -explicitly reading and writing the FITS images or columns of data, one -instead calls the CFITSIO iterator routine, passing to it the name of -the user's work function that is to be executed along with a list of -all the table columns or image arrays that are to be passed to the work -function. The CFITSIO iterator function then does all the work of -allocating memory for the arrays, reading the input data from the FITS -file, passing them to the work function, and then writing any output -data back to the FITS file after the work function exits. Because -it is often more efficient to process only a subset of the total table -rows at one time, the iterator function can determine the optimum -amount of data to pass in each iteration and repeatedly call the work -function until the entire table been processed. - -For many applications this single CFITSIO iterator function can -effectively replace all the other CFITSIO routines for reading or -writing data in FITS images or tables. Using the iterator has several -important advantages over the traditional method of reading and writing -FITS data files: - -\begin{itemize} -\item -It cleanly separates the data I/O from the routine that operates on -the data. This leads to a more modular and `object oriented' -programming style. - -\item -It simplifies the application program by eliminating the need to allocate -memory for the data arrays and eliminates most of the calls to the CFITSIO -routines that explicitly read and write the data. - -\item -It ensures that the data are processed as efficiently as possible. -This is especially important when processing tabular data since -the iterator function will calculate the most efficient number -of rows in the table to be passed at one time to the user's work -function on each iteration. - -\item -Makes it possible for larger projects to develop a library of work -functions that all have a uniform calling sequence and are all -independent of the details of the FITS file format. - -\end{itemize} - -There are basically 2 steps in using the CFITSIO iterator function. -The first step is to design the work function itself which must have a -prescribed set of input parameters. One of these parameters is a -structure containing pointers to the arrays of data; the work function -can perform any desired operations on these arrays and does not need to -worry about how the input data were read from the file or how the -output data get written back to the file. - -The second step is to design the driver routine that opens all the -necessary FITS files and initializes the input parameters to the -iterator function. The driver program calls the CFITSIO iterator -function which then reads the data and passes it to the user's work -function. - -The following 2 sections describe these steps in more detail. There -are also several example programs included with the CFITSIO -distribution which illustrate how to use the iterator function. - -**A The Iterator Work Function - -The user-supplied iterator work function must have the following set of -input parameters (the function can be given any desired name): - -- - int user_fn( long totaln, long offset, long firstn, long nvalues, - int narrays, iteratorCol *data, void *userPointer ) -- - -\begin{itemize} - -\item - totaln -- the total number of table rows or image pixels - that will be passed to the work function - during 1 or more iterations. - -\item - offset -- the offset applied to the first table row or image - pixel to be passed to the work function. In other - words, this is the number of rows or pixels that - are skipped over before starting the iterations. If - offset = 0, then all the table rows or image pixels - will be passed to the work function. - -\item - firstn -- the number of the first table row or image pixel - (starting with 1) that is being passed in this - particular call to the work function. - -\item - nvalues -- the number of table rows or image pixels that are - being passed in this particular call to the work - function. nvalues will always be less than or - equal to totaln and will have the same value on - each iteration, except possibly on the last - call which may have a smaller value. - -\item - narrays -- the number of arrays of data that are being passed - to the work function. There is one array for each - image or table column. - -\item - *data -- array of structures, one for each - column or image. Each structure contains a pointer - to the array of data as well as other descriptive - parameters about that array. - -\item - *userPointer -- a user supplied pointer that can be used - to pass ancillary information from the driver function - to the work function. - This pointer is passed to the CFITSIO iterator function - which then passes it on to the - work function without any modification. - It may point to a single number, to an array of values, - to a structure containing an arbitrary set of parameters - of different types, - or it may be a null pointer if it is not needed. - The work function must cast this pointer to the - appropriate data type before using it it. -\end{itemize} - -The totaln, offset, narrays, data, and userPointer parameters are -guaranteed to have the same value on each iteration. Only firstn, -nvalues, and the arrays of data pointed to by the data structures may -change on each iterative call to the work function. - -Note that the iterator treats an image as a long 1-D array of pixels -regardless of it's intrinsic dimensionality. The total number of -pixels is just the product of the size of each dimension, and the order -of the pixels is the same as the order that they are stored in the FITS -file. If the work function needs to know the number and size of the -image dimensions then these parameters can be passed via the -userPointer structure. - -The iteratorCol structure is currently defined as follows: -- -typedef struct /* structure for the iterator function column information */ -{ - /* structure elements required as input to fits_iterate_data: */ - - fitsfile *fptr; /* pointer to the HDU containing the column or image */ - int colnum; /* column number in the table; ignored for images */ - char colname[70]; /* name (TTYPEn) of the column; null for images */ - int datatype; /* output data type (converted if necessary) */ - int iotype; /* type: InputCol, InputOutputCol, or OutputCol */ - - /* output structure elements that may be useful for the work function: */ - - void *array; /* pointer to the array (and the null value) */ - long repeat; /* binary table vector repeat value; set */ - /* equal to 1 for images */ - long tlmin; /* legal minimum data value, if any */ - long tlmax; /* legal maximum data value, if any */ - char unit[70]; /* physical unit string (BUNIT or TUNITn) */ - char tdisp[70]; /* suggested display format; null if none */ - -} iteratorCol; -- - -Instead of directly reading or writing the elements in this structure, -it is recommended that programmers use the access functions that are -provided for this purpose. - -The first five elements in this structure must be initially defined by -the driver routine before calling the iterator routine. The CFITSIO -iterator routine uses this information to determine what column or -array to pass to the work function, and whether the array is to be -input to the work function, output from the work function, or both. -The CFITSIO iterator function fills in the values of the remaining -structure elements before passing it to the work function. - -The array structure element is a pointer to the actual data array and -it must be cast to the correct data type before it is used. The -`repeat' structure element give the number of data values in each row -of the table, so that the total number of data values in the array is -given by repeat * nvalues. In the case of image arrays and ASCII -tables, repeat will always be equal to 1. When the data type is a -character string, the array pointer is actually a pointer to an array -of string pointers (i.e., char **array). The other output structure -elements are provided for convenience in case that information is -needed within the work function. Any other information may be passed -from the driver routine to the work function via the userPointer -parameter. - -Upon completion, the work routine must return an integer status value, -with 0 indicating success and any other value indicating an error which -will cause the iterator function to immediately exit at that point. Return status -values in the range 1 -- 1000 should be avoided since these are -reserved for use by CFITSIO. A return status value of -1 may be used to -force the CFITSIO iterator function to stop at that point and return -control to the driver routine after writing any output arrays to the -FITS file. CFITSIO does not considered this to be an error condition, -so any further processing by the application program will continue normally. - -**B The Iterator Driver Function - -The iterator driver function must open the necessary FITS files and -position them to the correct HDU. It must also initialize the following -parameters in the iteratorCol structure (defined above) for each -column or image before calling the CFITSIO iterator function. -Several `constructor' routines are provided in CFITSIO for this -purpose. - -\begin{itemize} -\item - *fptr -- The fitsfile pointer to the table or image. -\item -colnum -- the number of the column in the table. This value is ignored - in the case of images. If colnum equals 0, then the column name - will be used to identify the column to be passed to the - work function. - -\item -colname -- the name (TTYPEn keyword) of the column. This is - only required if colnum = 0 and is ignored for images. -\item -datatype -- The desired data type of the array to be passed to the - work function. For numerical data the data type does - not need to be the same as the actual data type in the - FITS file, in which case CFITSIO will do the conversion. - Allowed values are: TSTRING, TLOGICAL, TBYTE, TSBYTE, TSHORT, TUSHORT, - TINT, TLONG, TULONG, TFLOAT, TDOUBLE. If the input - value of data type equals 0, then the existing - data type of the column or image will be used without - any conversion. - -\item -iotype -- defines whether the data array is to be input to the - work function (i.e, read from the FITS file), or output - from the work function (i.e., written to the FITS file) or - both. Allowed values are InputCol, OutputCol, or InputOutputCol. - Variable-length array columns are supported as InputCol or - InputOutputCol types, but may not be used for an OutputCol type. -\end{itemize} - -After the driver routine has initialized all these parameters, it -can then call the CFITSIO iterator function: - -- - int fits_iterate_data(int narrays, iteratorCol *data, long offset, - long nPerLoop, int (*workFn)( ), void *userPointer, int *status); -- - -\begin{itemize} -\item - - narrays -- the number of columns or images that are to be passed - to the work function. -\item - *data -- pointer to array of structures containing information - about each column or image. - -\item - offset -- if positive, this number of rows at the - beginning of the table (or pixels in the image) - will be skipped and will not be passed to the work - function. - -\item - nPerLoop - specifies the number of table rows (or number of - image pixels) that are to be passed to the work - function on each iteration. If nPerLoop = 0 - then CFITSIO will calculate the optimum number - for greatest efficiency. - If nPerLoop is negative, then all the rows - or pixels will be passed at one time, and the work - function will only be called once. If any variable - length arrays are being processed, then the nPerLoop - value is ignored, and the iterator will always process - one row of the table at a time. - -\item - *workFn - the name (actually the address) of the work function - that is to be called by fits\_iterate\_data. - -\item - *userPointer - this is a user supplied pointer that can be used - to pass ancillary information from the driver routine - to the work function. It may point to a single number, - an array, or to a structure containing an arbitrary set - of parameters. - -\item - *status - The CFITSIO error status. Should = 0 on input; - a non-zero output value indicates an error. -\end{itemize} - -When fits\_iterate\_data is called it first allocates memory to hold -all the requested columns of data or image pixel arrays. It then reads -the input data from the FITS tables or images into the arrays then -passes the structure with pointers to these data arrays to the work -function. After the work function returns, the iterator function -writes any output columns of data or images back to the FITS files. It -then repeats this process for any remaining sets of rows or image -pixels until it has processed the entire table or image or until the -work function returns a non-zero status value. The iterator then frees -the memory that it initially allocated and returns control to the -driver routine that called it. - -**C. Guidelines for Using the Iterator Function - -The totaln, offset, firstn, and nvalues parameters that are passed to -the work function are useful for determining how much of the data has -been processed and how much remains left to do. On the very first call -to the work function firstn will be equal to offset + 1; the work -function may need to perform various initialization tasks before -starting to process the data. Similarly, firstn + nvalues - 1 will be -equal to totaln on the last iteration, at which point the work function -may need to perform some clean up operations before exiting for the -last time. The work function can also force an early termination of -the iterations by returning a status value = -1. - -The narrays and iteratorCol.datatype arguments allow the work function -to double check that the number of input arrays and their data types -have the expected values. The iteratorCol.fptr and iteratorCol.colnum -structure elements can be used if the work function needs to read or -write the values of other keywords in the FITS file associated with -the array. This should generally only be done during the -initialization step or during the clean up step after the last set of -data has been processed. Extra FITS file I/O during the main -processing loop of the work function can seriously degrade the speed of -the program. - -If variable-length array columns are being processed, then the iterator -will operate on one row of the table at a time. In this case the -the repeat element in the interatorCol structure will be set equal to -the number of elements in the current row that is being processed. - -One important feature of the iterator is that the first element in each -array that is passed to the work function gives the value that is used -to represent null or undefined values in the array. The real data then -begins with the second element of the array (i.e., array[1], not -array[0]). If the first array element is equal to zero, then this -indicates that all the array elements have defined values and there are -no undefined values. If array[0] is not equal to zero, then this -indicates that some of the data values are undefined and this value -(array[0]) is used to represent them. In the case of output arrays -(i.e., those arrays that will be written back to the FITS file by the -iterator function after the work function exits) the work function must -set the first array element to the desired null value if necessary, -otherwise the first element should be set to zero to indicate that -there are no null values in the output array. CFITSIO defines 2 -values, FLOATNULLVALUE and DOUBLENULLVALUE, that can be used as default -null values for float and double data types, respectively. In the case -of character string data types, a null string is always used to -represent undefined strings. - -In some applications it may be necessary to recursively call the iterator -function. An example of this is given by one of the example programs -that is distributed with CFITSIO: it first calls a work function that -writes out a 2D histogram image. That work function in turn calls -another work function that reads the `X' and `Y' columns in a table to -calculate the value of each 2D histogram image pixel. Graphically, the -program structure can be described as: -- - driver --> iterator --> work1_fn --> iterator --> work2_fn -- - -Finally, it should be noted that the table columns or image arrays that -are passed to the work function do not all have to come from the same -FITS file and instead may come from any combination of sources as long -as they have the same length. The length of the first table column or -image array is used by the iterator if they do not all have the same -length. - -**D. Complete List of Iterator Routines - -All of the iterator routines are listed below. Most of these routines -do not have a corresponding short function name. - ->1 Iterator `constructor' functions that set - the value of elements in the iteratorCol structure - that define the columns or arrays. These set the fitsfile - pointer, column name, column number, datatype, and iotype, - respectively. The last 2 routines allow all the parameters - to be set with one function call (one supplies the column -> name, the other the column number). \label{ffiterset} - -- - int fits_iter_set_file(iteratorCol *col, fitsfile *fptr); - - int fits_iter_set_colname(iteratorCol *col, char *colname); - - int fits_iter_set_colnum(iteratorCol *col, int colnum); - - int fits_iter_set_datatype(iteratorCol *col, int datatype); - - int fits_iter_set_iotype(iteratorCol *col, int iotype); - - int fits_iter_set_by_name(iteratorCol *col, fitsfile *fptr, - char *colname, int datatype, int iotype); - - int fits_iter_set_by_num(iteratorCol *col, fitsfile *fptr, - int colnum, int datatype, int iotype); -- ->2 Iterator `accessor' functions that return the value of the - element in the iteratorCol structure -> that describes a particular data column or array \label{ffiterget} -- - fitsfile * fits_iter_get_file(iteratorCol *col); - - char * fits_iter_get_colname(iteratorCol *col); - - int fits_iter_get_colnum(iteratorCol *col); - - int fits_iter_get_datatype(iteratorCol *col); - - int fits_iter_get_iotype(iteratorCol *col); - - void * fits_iter_get_array(iteratorCol *col); - - long fits_iter_get_tlmin(iteratorCol *col); - - long fits_iter_get_tlmax(iteratorCol *col); - - long fits_iter_get_repeat(iteratorCol *col); - - char * fits_iter_get_tunit(iteratorCol *col); - - char * fits_iter_get_tdisp(iteratorCol *col); -- ->>3 The CFITSIO iterator function \label{ffiter} -- - int fits_iterate_data(int narrays, iteratorCol *data, long offset, - long nPerLoop, - int (*workFn)( long totaln, long offset, long firstn, - long nvalues, int narrays, iteratorCol *data, - void *userPointer), - void *userPointer, - int *status); -- - -*IX. World Coordinate System Routines - -The FITS community has adopted a set of keyword conventions that define -the transformations needed to convert between pixel locations in an -image and the corresponding celestial coordinates on the sky, or more -generally, that define world coordinates that are to be associated with -any pixel location in an n-dimensional FITS array. CFITSIO is distributed -with a a few self-contained World Coordinate System (WCS) routines, -however, these routines DO NOT support all the latest WCS conventions, -so it is STRONGLY RECOMMENDED that software developers use a more robust -external WCS library. Several recommended libraries are: - -- - WCSLIB - supported by Mark Calabretta - WCSTools - supported by Doug Mink - AST library - developed by the U.K. Starlink project -- - -More information about the WCS keyword conventions and links to all of -these WCS libraries can be found on the FITS Support Office web site at -http://fits.gsfc.nasa.gov under the WCS link. - -The functions provided in these external WCS libraries will need -access to the WCS keywords contained in the FITS file headers. -One convenient way to pass this information to the external library is -to use the fits\_hdr2str routine in CFITSIO (defined below) to copy the -header keywords into one long string, and then pass this string to an -interface routine in the external library that will extract -the necessary WCS information (e.g., the 'wcspih' routine in the WCSLIB -library and the 'astFitsChan' and 'astPutCards' functions in the AST -library). - ->1 Concatenate the header keywords in the CHDU into a single long - string of characters. Each 80-character fixed-length keyword - record is appended to the output character string, in order, with - no intervening separator or terminating characters. The last header - record is terminated with a NULL character. This routine allocates - memory for the returned character array, so the calling program must - free the memory when finished. - - There are 2 related routines: fits\_hdr2str simply concatenates all - the existing keywords in the header; fits\_convert\_hdr2str is similar, - except that if the CHDU is a tile compressed image (stored in a binary - table) then it will first convert that header back to that of a - normal FITS image before concatenating the keywords. - - Selected keywords may be excluded from the returned character string. - If the second parameter (nocomments) is TRUE (nonzero) then any - COMMENT, HISTORY, or blank keywords in the header will not be copied - to the output string. - - The 'exclist' parameter may be used to supply a list of keywords - that are to be excluded from the output character string. Wild card - characters (*, ?, and \#) may be used in the excluded keyword names. - If no additional keywords are to be excluded, then set nexc = 0 and -> specify NULL for the the **exclist parameter. \label{hdr2str} -- - int fits_hdr2str - (fitsfile *fptr, int nocomments, char **exclist, int nexc, - > char **header, int *nkeys, int *status) - - int fits_convert_hdr2str / ffcnvthdr2str - (fitsfile *fptr, int nocomments, char **exclist, int nexc, - > char **header, int *nkeys, int *status) -- - ->2 The following CFITSIO routine is specifically designed for use -in conjunction with the WCSLIB library. It is not expected that -applications programmers will call this routine directly, but it -is documented here for completeness. This routine extracts arrays -from a binary table that contain WCS information using the -TAB table -lookup convention. See the documentation provided with the WCSLIB -> library for more information. \label{wcstab} -- - int fits_read_wcstab - (fitsfile *fptr, int nwtb, wtbarr *wtb, int *status); -- -**A. Self-contained WCS Routines - -The following routines DO NOT support the more recent WCS conventions -that have been approved as part of the FITS standard. Consequently, -the following routines ARE NOW DEPRECATED. It is STRONGLY RECOMMENDED -that software developers not use these routines, and instead use an -external WCS library, as described in the previous section. - -These routines are included mainly for backward compatibility with -existing software. They support the following standard map -projections: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, and -AIT (these are the -legal values for the coordtype parameter). These routines are based -on similar functions in Classic AIPS. All the angular quantities are -given in units of degrees. - ->1 Get the values of the basic set of standard FITS celestial coordinate - system keywords from the header of a FITS image (i.e., the primary - array or an IMAGE extension). These values may then be passed to - the fits\_pix\_to\_world and fits\_world\_to\_pix routines that - perform the coordinate transformations. If any or all of the WCS - keywords are not present, then default values will be returned. If - the first coordinate axis is the declination-like coordinate, then - this routine will swap them so that the longitudinal-like coordinate - is returned as the first axis. - - The first routine (ffgics) returns - the primary WCS, whereas the second routine returns the particular - version of the WCS specified by the 'version' parameter, which much - be a character ranging from 'A' to 'Z' (or a blank character, which is - equivalent to calling ffgics). - - If the file uses the newer 'CDj\_i' WCS transformation matrix - keywords instead of old style 'CDELTn' and 'CROTA2' keywords, then - this routine will calculate and return the values of the equivalent - old-style keywords. Note that the conversion from the new-style - keywords to the old-style values is sometimes only an - approximation, so if the approximation is larger than an internally - defined threshold level, then CFITSIO will still return the - approximate WCS keyword values, but will also return with status = - APPROX\_WCS\_KEY, to warn the calling program that approximations - have been made. It is then up to the calling program to decide - whether the approximations are sufficiently accurate for the - particular application, or whether more precise WCS transformations -> must be performed using new-style WCS keywords directly. \label{ffgics} -- - int fits_read_img_coord / ffgics - (fitsfile *fptr, > double *xrefval, double *yrefval, - double *xrefpix, double *yrefpix, double *xinc, double *yinc, - double *rot, char *coordtype, int *status) - - int fits_read_img_coord_version / ffgicsa - (fitsfile *fptr, char version, > double *xrefval, double *yrefval, - double *xrefpix, double *yrefpix, double *xinc, double *yinc, - double *rot, char *coordtype, int *status) -- ->2 Get the values of the standard FITS celestial coordinate system - keywords from the header of a FITS table where the X and Y (or RA - and DEC) coordinates are stored in 2 separate columns of the table - (as in the Event List table format that is often used by high energy - astrophysics missions). These values may then be passed to the - fits\_pix\_to\_world and fits\_world\_to\_pix routines that perform -> the coordinate transformations. \label{ffgtcs} -- - int fits_read_tbl_coord / ffgtcs - (fitsfile *fptr, int xcol, int ycol, > double *xrefval, - double *yrefval, double *xrefpix, double *yrefpix, double *xinc, - double *yinc, double *rot, char *coordtype, int *status) -- ->3 Calculate the celestial coordinate corresponding to the input -> X and Y pixel location in the image. \label{ffwldp} -- - int fits_pix_to_world / ffwldp - (double xpix, double ypix, double xrefval, double yrefval, - double xrefpix, double yrefpix, double xinc, double yinc, - double rot, char *coordtype, > double *xpos, double *ypos, - int *status) -- ->4 Calculate the X and Y pixel location corresponding to the input -> celestial coordinate in the image. \label{ffxypx} -- - int fits_world_to_pix / ffxypx - (double xpos, double ypos, double xrefval, double yrefval, - double xrefpix, double yrefpix, double xinc, double yinc, - double rot, char *coordtype, > double *xpix, double *ypix, - int *status) -- - - -*VIII Hierarchical Grouping Routines - -These functions allow for the creation and manipulation of FITS HDU -Groups, as defined in "A Hierarchical Grouping Convention for FITS" by -Jennings, Pence, Folk and Schlesinger: - -http://fits.gsfc.nasa.gov/group.html - -A group is a -collection of HDUs whose association is defined by a {\it grouping -table}. HDUs which are part of a group are referred to as {\it member -HDUs} or simply as {\it members}. Grouping table member HDUs may -themselves be grouping tables, thus allowing for the construction of -open-ended hierarchies of HDUs. - -Grouping tables contain one row for each member HDU. The grouping table -columns provide identification information that allows applications to -reference or "point to" the member HDUs. Member HDUs are expected, but -not required, to contain a set of GRPIDn/GRPLCn keywords in their -headers for each grouping table that they are referenced by. In this -sense, the GRPIDn/GRPLCn keywords "link" the member HDU back to its -Grouping table. Note that a member HDU need not reside in the same FITS -file as its grouping table, and that a given HDU may be referenced by -up to 999 grouping tables simultaneously. - -Grouping tables are implemented as FITS binary tables with up to six -pre-defined column TTYPEn values: 'MEMBER\_XTENSION', 'MEMBER\_NAME', -'MEMBER\_VERSION', 'MEMBER\_POSITION', 'MEMBER\_URI\_TYPE' and 'MEMBER\_LOCATION'. -The first three columns allow member HDUs to be identified by reference to -their XTENSION, EXTNAME and EXTVER keyword values. The fourth column allows -member HDUs to be identified by HDU position within their FITS file. -The last two columns identify the FITS file in which the member HDU resides, -if different from the grouping table FITS file. - -Additional user defined "auxiliary" columns may also be included with any -grouping table. When a grouping table is copied or modified the presence of -auxiliary columns is always taken into account by the grouping support -functions; however, the grouping support functions cannot directly -make use of this data. - -If a grouping table column is defined but the corresponding member HDU -information is unavailable then a null value of the appropriate data type -is inserted in the column field. Integer columns (MEMBER\_POSITION, -MEMBER\_VERSION) are defined with a TNULLn value of zero (0). Character field -columns (MEMBER\_XTENSION, MEMBER\_NAME, MEMBER\_URI\_TYPE, MEMBER\_LOCATION) -utilize an ASCII null character to denote a null field value. - -The grouping support functions belong to two basic categories: those that -work with grouping table HDUs (ffgt**) and those that work with member HDUs -(ffgm**). Two functions, fits\_copy\_group() and fits\_remove\_group(), have the -option to recursively copy/delete entire groups. Care should be taken when -employing these functions in recursive mode as poorly defined groups could -cause unpredictable results. The problem of a grouping table directly or -indirectly referencing itself (thus creating an infinite loop) is protected -against; in fact, neither function will attempt to copy or delete an HDU -twice. - -**A. Grouping Table Routines - ->1 Create (append) a grouping table at the end of the current FITS file - pointed to by fptr. The grpname parameter provides the grouping table - name (GRPNAME keyword value) and may be set to NULL if no group name - is to be specified. The grouptype parameter specifies the desired - structure of the grouping table and may take on the values: - GT\_ID\_ALL\_URI (all columns created), GT\_ID\_REF (ID by reference columns), - GT\_ID\_POS (ID by position columns), GT\_ID\_ALL (ID by reference and - position columns), GT\_ID\_REF\_URI (ID by reference and FITS file URI -> columns), and GT\_ID\_POS\_URI (ID by position and FITS file URI columns). \label{ffgtcr} -- - int fits_create_group / ffgtcr - (fitsfile *fptr, char *grpname, int grouptype, > int *status) -- ->2 Create (insert) a grouping table just after the CHDU of the current FITS - file pointed to by fptr. All HDUs below the the insertion point will be - shifted downwards to make room for the new HDU. The grpname parameter - provides the grouping table name (GRPNAME keyword value) and may be set to - NULL if no group name is to be specified. The grouptype parameter specifies - the desired structure of the grouping table and may take on the values: - GT\_ID\_ALL\_URI (all columns created), GT\_ID\_REF (ID by reference columns), - GT\_ID\_POS (ID by position columns), GT\_ID\_ALL (ID by reference and - position columns), GT\_ID\_REF\_URI (ID by reference and FITS file URI -> columns), and GT\_ID\_POS\_URI (ID by position and FITS file URI columns) \label{ffgtis}. -- - int fits_insert_group / ffgtis - (fitsfile *fptr, char *grpname, int grouptype, > int *status) -- ->3 Change the structure of an existing grouping table pointed to by - gfptr. The grouptype parameter (see fits\_create\_group() for valid - parameter values) specifies the new structure of the grouping table. This - function only adds or removes grouping table columns, it does not add - or delete group members (i.e., table rows). If the grouping table already - has the desired structure then no operations are performed and function - simply returns with a (0) success status code. If the requested structure - change creates new grouping table columns, then the column values for all - existing members will be filled with the null values appropriate to the -> column type. \label{ffgtch} -- - int fits_change_group / ffgtch - (fitsfile *gfptr, int grouptype, > int *status) -- ->4 Remove the group defined by the grouping table pointed to by gfptr, and - optionally all the group member HDUs. The rmopt parameter specifies the - action to be taken for - all members of the group defined by the grouping table. Valid values are: - OPT\_RM\_GPT (delete only the grouping table) and OPT\_RM\_ALL (recursively - delete all HDUs that belong to the group). Any groups containing the - grouping table gfptr as a member are updated, and if rmopt == OPT\_RM\_GPT - all members have their GRPIDn and GRPLCn keywords updated accordingly. - If rmopt == OPT\_RM\_ALL, then other groups that contain the deleted members -> of gfptr are updated to reflect the deletion accordingly. \label{ffgtrm} -- - int fits_remove_group / ffgtrm - (fitsfile *gfptr, int rmopt, > int *status) -- ->5 Copy (append) the group defined by the grouping table pointed to by infptr, - and optionally all group member HDUs, to the FITS file pointed to by - outfptr. The cpopt parameter specifies the action to be taken for all - members of the group infptr. Valid values are: OPT\_GCP\_GPT (copy only - the grouping table) and OPT\_GCP\_ALL (recursively copy ALL the HDUs that - belong to the group defined by infptr). If the cpopt == OPT\_GCP\_GPT then - the members of infptr have their GRPIDn and GRPLCn keywords updated to - reflect the existence of the new grouping table outfptr, since they now - belong to the new group. If cpopt == OPT\_GCP\_ALL then the new - grouping table outfptr only contains pointers to the copied member HDUs - and not the original member HDUs of infptr. Note that, when - cpopt == OPT\_GCP\_ALL, all members of the group defined by infptr will be - copied to a single FITS file pointed to by outfptr regardless of their -> file distribution in the original group. \label{ffgtcp} -- - int fits_copy_group / ffgtcp - (fitsfile *infptr, fitsfile *outfptr, int cpopt, > int *status) -- ->6 Merge the two groups defined by the grouping table HDUs infptr and outfptr - by combining their members into a single grouping table. All member HDUs - (rows) are copied from infptr to outfptr. If mgopt == OPT\_MRG\_COPY then - infptr continues to exist unaltered after the merge. If the mgopt == - OPT\_MRG\_MOV then infptr is deleted after the merge. In both cases, -> the GRPIDn and GRPLCn keywords of the member HDUs are updated accordingly. \label{ffgtmg} -- - int fits_merge_groups / ffgtmg - (fitsfile *infptr, fitsfile *outfptr, int mgopt, > int *status) -- ->7 "Compact" the group defined by grouping table pointed to by gfptr. The - compaction is achieved by merging (via fits\_merge\_groups()) all direct - member HDUs of gfptr that are themselves grouping tables. The cmopt - parameter defines whether the merged grouping table HDUs remain after - merging (cmopt == OPT\_CMT\_MBR) or if they are deleted after merging - (cmopt == OPT\_CMT\_MBR\_DEL). If the grouping table contains no direct - member HDUs that are themselves grouping tables then this function - does nothing. Note that this function is not recursive, i.e., only the -> direct member HDUs of gfptr are considered for merging. \label{ffgtcm} -- - int fits_compact_group / ffgtcm - (fitsfile *gfptr, int cmopt, > int *status) -- ->8 Verify the integrity of the grouping table pointed to by gfptr to make - sure that all group members are accessible and that all links to other - grouping tables are valid. The firstfailed parameter returns the member - ID (row number) of the first member HDU to fail verification (if positive - value) or the first group link to fail (if negative value). If gfptr is -> successfully verified then firstfailed contains a return value of 0. \label{ffgtvf} -- - int fits_verify_group / ffgtvf - (fitsfile *gfptr, > long *firstfailed, int *status) -- ->9 Open a grouping table that contains the member HDU pointed to by mfptr. - The grouping table to open is defined by the grpid parameter, which - contains the keyword index value of the GRPIDn/GRPLCn keyword(s) that - link the member HDU mfptr to the grouping table. If the grouping table - resides in a file other than the member HDUs file then an attempt is - first made to open the file readwrite, and failing that readonly. A - pointer to the opened grouping table HDU is returned in gfptr. - - Note that it is possible, although unlikely and undesirable, for the - GRPIDn/GRPLCn keywords in a member HDU header to be non-continuous, e.g., - GRPID1, GRPID2, GRPID5, GRPID6. In such cases, the grpid index value - specified in the function call shall identify the (grpid)th GRPID value. - In the above example, if grpid == 3, then the group specified by GRPID5 -> would be opened. \label{ffgtop} -- - int fits_open_group / ffgtop - (fitsfile *mfptr, int group, > fitsfile **gfptr, int *status) -- ->10 Add a member HDU to an existing grouping table pointed to by gfptr. - The member HDU may either be pointed to mfptr (which must be positioned - to the member HDU) or, if mfptr == NULL, identified by the hdupos parameter - (the HDU position number, Primary array == 1) if both the grouping table - and the member HDU reside in the same FITS file. The new member HDU shall - have the appropriate GRPIDn and GRPLCn keywords created in its header. - Note that if the member HDU is already a member of the group then it will -> not be added a second time. \label{ffgtam} -- - int fits_add_group_member / ffgtam - (fitsfile *gfptr, fitsfile *mfptr, int hdupos, > int *status) -- - -**B. Group Member Routines - ->1 Return the number of member HDUs in a grouping table gfptr. The number - member HDUs is just the NAXIS2 value (number of rows) of the grouping -> table. \label{ffgtnm} -- - int fits_get_num_members / ffgtnm - (fitsfile *gfptr, > long *nmembers, int *status) -- ->2 Return the number of groups to which the HDU pointed to by mfptr is - linked, as defined by the number of GRPIDn/GRPLCn keyword records that - appear in its header. Note that each time this function is called, the - indices of the GRPIDn/GRPLCn keywords are checked to make sure they - are continuous (ie no gaps) and are re-enumerated to eliminate gaps if -> found. \label{ffgmng} -- - int fits_get_num_groups / ffgmng - (fitsfile *mfptr, > long *nmembers, int *status) -- ->3 Open a member of the grouping table pointed to by gfptr. The member to - open is identified by its row number within the grouping table as given - by the parameter 'member' (first member == 1) . A fitsfile pointer to - the opened member HDU is returned as mfptr. Note that if the member HDU - resides in a FITS file different from the grouping table HDU then the -> member file is first opened readwrite and, failing this, opened readonly. \label{ffgmop} -- - int fits_open_member / ffgmop - (fitsfile *gfptr, long member, > fitsfile **mfptr, int *status) -- ->4 Copy (append) a member HDU of the grouping table pointed to by gfptr. - The member HDU is identified by its row number within the grouping table - as given by the parameter 'member' (first member == 1). The copy of the - group member HDU will be appended to the FITS file pointed to by mfptr, - and upon return mfptr shall point to the copied member HDU. The cpopt - parameter may take on the following values: OPT\_MCP\_ADD which adds a new - entry in gfptr for the copied member HDU, OPT\_MCP\_NADD which does not add - an entry in gfptr for the copied member, and OPT\_MCP\_REPL which replaces -> the original member entry with the copied member entry. \label{ffgmcp} -- - int fits_copy_member / ffgmcp - (fitsfile *gfptr, fitsfile *mfptr, long member, int cpopt, > int *status) -- ->5 Transfer a group member HDU from the grouping table pointed to by - infptr to the grouping table pointed to by outfptr. The member HDU to - transfer is identified by its row number within infptr as specified by - the parameter 'member' (first member == 1). If tfopt == OPT\_MCP\_ADD then - the member HDU is made - a member of outfptr and remains a member of infptr. If tfopt == OPT\_MCP\_MOV -> then the member HDU is deleted from infptr after the transfer to outfptr. \label{ffgmtf} -- - int fits_transfer_member / ffgmtf - (fitsfile *infptr, fitsfile *outfptr, long member, int tfopt, - > int *status) -- ->6 Remove a member HDU from the grouping table pointed to by gfptr. The - member HDU to be deleted is identified by its row number in the grouping - table as specified by the parameter 'member' (first member == 1). The rmopt - parameter may take on the following values: OPT\_RM\_ENTRY which - removes the member HDU entry from the grouping table and updates the - member's GRPIDn/GRPLCn keywords, and OPT\_RM\_MBR which removes the member -> HDU entry from the grouping table and deletes the member HDU itself. \label{ffgmrm} -- - int fits_remove_member / ffgmrm - (fitsfile *fptr, long member, int rmopt, > int *status) -- - -*IX Specialized CFITSIO Interface Routines - -The basic interface routines described previously are recommended -for most uses, but the routines described in this chapter -are also available if necessary. Some of these routines perform more -specialized function that cannot easily be done with the basic -interface routines while others duplicate the functionality of the -basic routines but have a slightly different calling sequence. -See Appendix B for the definition of each function parameter. - -**A. FITS File Access Routines - ->1 Open an existing FITS file residing in core computer memory. This -routine is analogous to fits\_open\_file. The 'filename' is -currently ignored by this routine and may be any arbitrary string. In -general, the application must have preallocated an initial block of -memory to hold the FITS file prior to calling this routine: 'memptr' -points to the starting address and 'memsize' gives the initial size of -the block of memory. 'mem\_realloc' is a pointer to an optional -function that CFITSIO can call to allocate additional memory, if needed -(only if mode = READWRITE), and is modeled after the standard C -'realloc' function; a null pointer may be given if the initial -allocation of memory is all that will be required (e.g., if the file is -opened with mode = READONLY). The 'deltasize' parameter may be used to -suggest a minimum amount of additional memory that should be allocated -during each call to the memory reallocation function. By default, -CFITSIO will reallocate enough additional space to hold the entire -currently defined FITS file (as given by the NAXISn keywords) or 1 FITS -block (= 2880 bytes), which ever is larger. Values of deltasize less -than 2880 will be ignored. Since the memory reallocation operation can -be computationally expensive, allocating a larger initial block of -memory, and/or specifying a larger deltasize value may help to reduce -the number of reallocation calls and make the application program run -faster. Note that values of the memptr and memsize pointers will be updated -by CFITSIO if the location or size of the FITS file in memory ->should change as a result of allocating more memory. \label{ffomem} -- - int fits_open_memfile / ffomem - (fitsfile **fptr, const char *filename, int mode, void **memptr, - size_t *memsize, size_t deltasize, - void *(*mem_realloc)(void *p, size_t newsize), int *status) -- ->2 Create a new FITS file residing in core computer memory. This -routine is analogous to fits\_create\_file. In general, the -application must have preallocated an initial block of memory to hold -the FITS file prior to calling this routine: 'memptr' points to the -starting address and 'memsize' gives the initial size of the block of -memory. 'mem\_realloc' is a pointer to an optional function that -CFITSIO can call to allocate additional memory, if needed, and is -modeled after the standard C 'realloc' function; a null pointer may be -given if the initial allocation of memory is all that will be -required. The 'deltasize' parameter may be used to suggest a minimum -amount of additional memory that should be allocated during each call -to the memory reallocation function. By default, CFITSIO will -reallocate enough additional space to hold 1 FITS block (= 2880 bytes) -and values of deltasize less than 2880 will be ignored. Since the -memory reallocation operation can be computationally expensive, -allocating a larger initial block of memory, and/or specifying a larger -deltasize value may help to reduce the number of reallocation calls -and make the application program run -faster. Note that values of the memptr and memsize pointers will be updated -by CFITSIO if the location or size of the FITS file in memory ->should change as a result of allocating more memory. \label{ffimem} -- - int fits_create_memfile / ffimem - (fitsfile **fptr, void **memptr, - size_t *memsize, size_t deltasize, - void *(*mem_realloc)(void *p, size_t newsize), int *status) -- ->3 Reopen a FITS file that was previously opened with - fits\_open\_file or fits\_create\_file. The new fitsfile - pointer may then be treated as a separate file, and one may - simultaneously read or write to 2 (or more) different extensions in - the same file. The fits\_open\_file routine (above) automatically - detects cases where a previously opened file is being opened again, - and then internally call fits\_reopen\_file, so programs should rarely - need to explicitly call this routine. ->\label{ffreopen} -- - int fits_reopen_file / ffreopen - (fitsfile *openfptr, fitsfile **newfptr, > int *status) -- - ->4 Create a new FITS file, using a template file to define its - initial size and structure. The template may be another FITS HDU - or an ASCII template file. If the input template file name pointer - is null, then this routine behaves the same as fits\_create\_file. - The currently supported format of the ASCII template file is described - under the fits\_parse\_template routine (in the general Utilities - section) ->\label{fftplt} -- - int fits_create_template / fftplt - (fitsfile **fptr, char *filename, char *tpltfile > int *status) -- - ->5 Parse the input filename or URL into its component parts, namely: -\begin{itemize} -\item -the file type (file://, ftp://, http://, etc), -\item -the base input file name, -\item -the name of the output file that the input file is to be copied to prior -to opening, -\item -the HDU or extension specification, -\item -the filtering specifier, -\item -the binning specifier, -\item -the column specifier, -\item -and the -image pixel filtering specifier. -\end{itemize} -A null pointer (0) may be be specified for any of the output string arguments -that are not needed. Null strings will be returned for any components that are not -present in the input file name. The calling routine must allocate sufficient -memory to hold the returned character strings. Allocating the string lengths -equal to FLEN\_FILENAME is guaranteed to be safe. -These routines are mainly for internal use ->by other CFITSIO routines. \label{ffiurl} -- - int fits_parse_input_url / ffiurl - (char *filename, > char *filetype, char *infile, char *outfile, char - *extspec, char *filter, char *binspec, char *colspec, int *status) - - int fits_parse_input_filename / ffifile - (char *filename, > char *filetype, char *infile, char *outfile, char - *extspec, char *filter, char *binspec, char *colspec, char *pixspec, - int *status) -- ->6 Parse the input filename and return the HDU number that would be -moved to if the file were opened with fits\_open\_file. The returned -HDU number begins with 1 for the primary array, so for example, if the -input filename = `myfile.fits[2]' then hdunum = 3 will be returned. -CFITSIO does not open the file to check if the extension actually -exists if an extension number is specified. If an extension name is -included in the file name specification (e.g. `myfile.fits[EVENTS]' -then this routine will have to open the FITS file and look for the -position of the named extension, then close file again. This is not -possible if the file is being read from the stdin stream, and an error -will be returned in this case. If the filename does not specify an -explicit extension (e.g. 'myfile.fits') then hdunum = -99 will be -returned, which is functionally equivalent to hdunum = 1. This routine -is mainly used for backward compatibility in the ftools software -package and is not recommended for general use. It is generally better -and more efficient to first open the FITS file with fits\_open\_file, -then use fits\_get\_hdu\_num to determine which HDU in the file has -been opened, rather than calling fits\_parse\_input\_url followed by a -call to fits\_open\_file. -> \label{ffextn} -- - int fits_parse_extnum / ffextn - (char *filename, > int *hdunum, int *status) -- ->7 Parse the input file name and return the root file name. The root -name includes the file type if specified, (e.g. 'ftp://' or 'http://') -and the full path name, to the extent that it is specified in the input -filename. It does not include the HDU name or number, or any filtering -specifications. The calling routine must allocate sufficient -memory to hold the returned rootname character string. Allocating the length -equal to FLEN\_FILENAME is guaranteed to be safe. -> \label{ffrtnm} -- - int fits_parse_rootname / ffrtnm - (char *filename, > char *rootname, int *status); -- ->8 Test if the input file or a compressed version of the file (with -a .gz, .Z, .z, or .zip extension) exists on disk. The returned value of -the 'exists' parameter will have 1 of the 4 following values: -- - 2: the file does not exist, but a compressed version does exist - 1: the disk file does exist - 0: neither the file nor a compressed version of the file exist - -1: the input file name is not a disk file (could be a ftp, http, - smem, or mem file, or a file piped in on the STDIN stream) -- - -> \label{ffexist} -- - int fits_file_exists / ffexist - (char *filename, > int *exists, int *status); -- ->9 Flush any internal buffers of data to the output FITS file. These - routines rarely need to be called, but can be useful in cases where - other processes need to access the same FITS file in real time, - either on disk or in memory. These routines also help to ensure - that if the application program subsequently aborts then the FITS - file will have been closed properly. The first routine, - fits\_flush\_file is more rigorous and completely closes, then - reopens, the current HDU, before flushing the internal buffers, thus - ensuring that the output FITS file is identical to what would be - produced if the FITS was closed at that point (i.e., with a call to - fits\_close\_file). The second routine, fits\_flush\_buffer simply - flushes the internal CFITSIO buffers of data to the output FITS - file, without updating and closing the current HDU. This is much - faster, but there may be circumstances where the flushed file does - not completely reflect the final state of the file as it will exist - when the file is actually closed. - - A typical use of these routines would be to flush the state of a - FITS table to disk after each row of the table is written. It is - recommend that fits\_flush\_file be called after the first row is - written, then fits\_flush\_buffer may be called after each - subsequent row is written. Note that this latter routine will not - automatically update the NAXIS2 keyword which records the number of - rows of data in the table, so this keyword must be explicitly - updated by the application program after each row is written. -> \label{ffflus} -- - int fits_flush_file / ffflus - (fitsfile *fptr, > int *status) - - int fits_flush_buffer / ffflsh - (fitsfile *fptr, 0, > int *status) - - (Note: The second argument must be 0). -- - -**B. HDU Access Routines - ->1 Get the byte offsets in the FITS file to the start of the header - and the start and end of the data in the CHDU. The difference - between headstart and dataend equals the size of the CHDU. If the - CHDU is the last HDU in the file, then dataend is also equal to the - size of the entire FITS file. Null pointers may be input for any -> of the address parameters if their values are not needed. \label{ffghad} -- - int fits_get_hduaddr / ffghad (only supports files up to 2.1 GB in size) - (fitsfile *fptr, > long *headstart, long *datastart, long *dataend, - int *status) - - int fits_get_hduaddrll / ffghadll (supports large files) - (fitsfile *fptr, > LONGLONG *headstart, LONGLONG *datastart, - LONGLONG *dataend, int *status) -- ->2 Create (append) a new empty HDU at the end of the FITS file. - This is now the CHDU but it is completely empty and has - no header keywords. It is recommended that fits\_create\_img or -> fits\_create\_tbl be used instead of this routine. \label{ffcrhd} -- - int fits_create_hdu / ffcrhd - (fitsfile *fptr, > int *status) -- ->3 Insert a new IMAGE extension immediately following the CHDU, or - insert a new Primary Array at the beginning of the file. Any - following extensions in the file will be shifted down to make room - for the new extension. If the CHDU is the last HDU in the file - then the new image extension will simply be appended to the end of - the file. One can force a new primary array to be inserted at the - beginning of the FITS file by setting status = PREPEND\_PRIMARY prior - to calling the routine. In this case the old primary array will be - converted to an IMAGE extension. The new extension (or primary - array) will become the CHDU. Refer to Chapter 9 for a list of -> pre-defined bitpix values. \label{ffiimg} -- - int fits_insert_img / ffiimg - (fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) - - int fits_insert_imgll / ffiimgll - (fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) -- ->4 Insert a new ASCII or binary table extension immediately following the CHDU. - Any following extensions will be shifted down to make room for the - new extension. If there are no other following extensions then the - new table extension will simply be appended to the end of the - file. If the FITS file is currently empty then this routine will - create a dummy primary array before appending the table to it. The - new extension will become the CHDU. The tunit and extname - parameters are optional and a null pointer may be given if they are - not defined. When inserting an ASCII table with - fits\_insert\_atbl, a null pointer may given for the *tbcol - parameter in which case each column of the table will be separated - by a single space character. Similarly, if the input value of - rowlen is 0, then CFITSIO will calculate the default rowlength - based on the tbcol and ttype values. Under normal circumstances, - the nrows - paramenter should have a value of 0; CFITSIO will automatically update - the number of rows as data is written to the table. When inserting a binary table - with fits\_insert\_btbl, if there are following extensions in the - file and if the table contains variable length array columns then - pcount must specify the expected final size of the data heap, -> otherwise pcount must = 0. \label{ffitab} \label{ffibin} -- - int fits_insert_atbl / ffitab - (fitsfile *fptr, LONGLONG rowlen, LONGLONG nrows, int tfields, char *ttype[], - long *tbcol, char *tform[], char *tunit[], char *extname, > int *status) - - int fits_insert_btbl / ffibin - (fitsfile *fptr, LONGLONG nrows, int tfields, char **ttype, - char **tform, char **tunit, char *extname, long pcount, > int *status) -- ->5 Modify the size, dimensions, and/or data type of the current - primary array or image extension. If the new image, as specified - by the input arguments, is larger than the current existing image - in the FITS file then zero fill data will be inserted at the end - of the current image and any following extensions will be moved - further back in the file. Similarly, if the new image is - smaller than the current image then any following extensions - will be shifted up towards the beginning of the FITS file - and the image data will be truncated to the new size. - This routine rewrites the BITPIX, NAXIS, and NAXISn keywords -> with the appropriate values for the new image. \label{ffrsim} -- - int fits_resize_img / ffrsim - (fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) - - int fits_resize_imgll / ffrsimll - (fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) -- ->6 Copy the data (and not the header) from the CHDU associated with infptr - to the CHDU associated with outfptr. This will overwrite any data - previously in the output CHDU. This low level routine is used by - fits\_copy\_hdu, but it may also be useful in certain application programs - that want to copy the data from one FITS file to another but also - want to modify the header keywords. The required FITS header keywords - which define the structure of the HDU must be written to the -> output CHDU before calling this routine. \label{ffcpdt} -- - int fits_copy_data / ffcpdt - (fitsfile *infptr, fitsfile *outfptr, > int *status) -- ->7 Read or write a specified number of bytes starting at the specified byte - offset from the start of the extension data unit. These low - level routine are intended mainly for accessing the data in - non-standard, conforming extensions, and should not be used for standard -> IMAGE, TABLE, or BINTABLE extensions. \label{ffgextn} -- - int fits_read_ext / ffgextn - (fitsfile *fptr, LONGLONG offset, LONGLONG nbytes, void *buffer) - int fits_write_ext / ffpextn - (fitsfile *fptr, LONGLONG offset, LONGLONG nbytes, void *buffer) -- ->8 This routine forces CFITSIO to rescan the current header keywords that - define the structure of the HDU (such as the NAXIS and BITPIX - keywords) so that it reinitializes the internal buffers that - describe the HDU structure. This routine is useful for - reinitializing the structure of an HDU if any of the required - keywords (e.g., NAXISn) have been modified. In practice it should - rarely be necessary to call this routine because CFITSIO -> internally calls it in most situations. \label{ffrdef} -- - int fits_set_hdustruc / ffrdef - (fitsfile *fptr, > int *status) (DEPRECATED) -- -**C. Specialized Header Keyword Routines - -***1. Header Information Routines - ->1 Reserve space in the CHU for MOREKEYS more header keywords. - This routine may be called to allocate space for additional keywords - at the time the header is created (prior to writing any data). - CFITSIO can dynamically add more space to the header when needed, - however it is more efficient to preallocate the required space -> if the size is known in advance. \label{ffhdef} -- - int fits_set_hdrsize / ffhdef - (fitsfile *fptr, int morekeys, > int *status) -- ->2 Return the number of keywords in the header (not counting the END - keyword) and the current position - in the header. The position is the number of the keyword record that - will be read next (or one greater than the position of the last keyword - that was read). A value of 1 is returned if the pointer is -> positioned at the beginning of the header. \label{ffghps} -- - int fits_get_hdrpos / ffghps - (fitsfile *fptr, > int *keysexist, int *keynum, int *status) -- - -***2. Read and Write the Required Keywords - ->1 Write the required extension header keywords into the CHU. - These routines are not required, and instead the appropriate - header may be constructed by writing each individual keyword in the - proper sequence. - - The simpler fits\_write\_imghdr routine is equivalent to calling - fits\_write\_grphdr with the default values of simple = TRUE, pcount - = 0, gcount = 1, and extend = TRUE. The PCOUNT, GCOUNT and EXTEND - keywords are not required in the primary header and are only written - if pcount is not equal to zero, gcount is not equal to zero or one, - and if extend is TRUE, respectively. When writing to an IMAGE - extension, the SIMPLE and EXTEND parameters are ignored. It is - recommended that fits\_create\_image or fits\_create\_tbl be used - instead of these routines to write the - required header keywords. The general fits\_write\_exthdr routine - may be used to write the header of any conforming FITS -> extension. \label{ffphpr} \label{ffphps} -- - int fits_write_imghdr / ffphps - (fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) - - int fits_write_imghdrll / ffphpsll - (fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) - - int fits_write_grphdr / ffphpr - (fitsfile *fptr, int simple, int bitpix, int naxis, long *naxes, - LONGLONG pcount, LONGLONG gcount, int extend, > int *status) - - int fits_write_grphdrll / ffphprll - (fitsfile *fptr, int simple, int bitpix, int naxis, LONGLONG *naxes, - LONGLONG pcount, LONGLONG gcount, int extend, > int *status) - - int fits_write_exthdr /ffphext - (fitsfile *fptr, char *xtension, int bitpix, int naxis, long *naxes, - LONGLONG pcount, LONGLONG gcount, > int *status) - -- ->2 Write the ASCII table header keywords into the CHU. The optional - TUNITn and EXTNAME keywords are written only if the input pointers - are not null. A null pointer may given for the - *tbcol parameter in which case a single space will be inserted - between each column of the table. Similarly, if rowlen is - given = 0, then CFITSIO will calculate the default rowlength based on -> the tbcol and ttype values. \label{ffphtb} -- - int fits_write_atblhdr / ffphtb - (fitsfile *fptr, LONGLONG rowlen, LONGLONG nrows, int tfields, char **ttype, - long *tbcol, char **tform, char **tunit, char *extname, > int *status) -- ->3 Write the binary table header keywords into the CHU. The optional - TUNITn and EXTNAME keywords are written only if the input pointers - are not null. The pcount parameter, which specifies the - size of the variable length array heap, should initially = 0; - CFITSIO will automatically update the PCOUNT keyword value if any - variable length array data is written to the heap. The TFORM keyword - value for variable length vector columns should have the form 'Pt(len)' - or '1Pt(len)' where `t' is the data type code letter (A,I,J,E,D, etc.) - and `len' is an integer specifying the maximum length of the vectors - in that column (len must be greater than or equal to the longest - vector in the column). If `len' is not specified when the table is - created (e.g., the input TFORMn value is just '1Pt') then CFITSIO will - scan the column when the table is first closed and will append the - maximum length to the TFORM keyword value. Note that if the table - is subsequently modified to increase the maximum length of the vectors - then the modifying program is responsible for also updating the TFORM -> keyword value. \label{ffphbn} -- - int fits_write_btblhdr / ffphbn - (fitsfile *fptr, LONGLONG nrows, int tfields, char **ttype, - char **tform, char **tunit, char *extname, LONGLONG pcount, > int *status) -- ->4 Read the required keywords from the CHDU (image or table). When - reading from an IMAGE extension the SIMPLE and EXTEND parameters are - ignored. A null pointer may be supplied for any of the returned -> parameters that are not needed. \label{ffghpr} \label{ffghtb} \label{ffghbn} -- - int fits_read_imghdr / ffghpr - (fitsfile *fptr, int maxdim, > int *simple, int *bitpix, int *naxis, - long *naxes, long *pcount, long *gcount, int *extend, int *status) - - int fits_read_imghdrll / ffghprll - (fitsfile *fptr, int maxdim, > int *simple, int *bitpix, int *naxis, - LONGLONG *naxes, long *pcount, long *gcount, int *extend, int *status) - - int fits_read_atblhdr / ffghtb - (fitsfile *fptr,int maxdim, > long *rowlen, long *nrows, - int *tfields, char **ttype, LONGLONG *tbcol, char **tform, char **tunit, - char *extname, int *status) - - int fits_read_atblhdrll / ffghtbll - (fitsfile *fptr,int maxdim, > LONGLONG *rowlen, LONGLONG *nrows, - int *tfields, char **ttype, long *tbcol, char **tform, char **tunit, - char *extname, int *status) - - int fits_read_btblhdr / ffghbn - (fitsfile *fptr, int maxdim, > long *nrows, int *tfields, - char **ttype, char **tform, char **tunit, char *extname, - long *pcount, int *status) - - int fits_read_btblhdrll / ffghbnll - (fitsfile *fptr, int maxdim, > LONGLONG *nrows, int *tfields, - char **ttype, char **tform, char **tunit, char *extname, - long *pcount, int *status) -- -***3. Write Keyword Routines - -These routines simply append a new keyword to the header and do not -check to see if a keyword with the same name already exists. In -general it is preferable to use the fits\_update\_key routine to ensure -that the same keyword is not written more than once to the header. See -Appendix B for the definition of the parameters used in these -routines. - - ->1 Write (append) a new keyword of the appropriate data type into the CHU. - A null pointer may be entered for the comment parameter, which - will cause the comment field of the keyword to be left blank. The - flt, dbl, cmp, and dblcmp versions of this routine have the added - feature that if the 'decimals' parameter is negative, then the 'G' - display format rather then the 'E' format will be used when - constructing the keyword value, taking the absolute value of - 'decimals' for the precision. This will suppress trailing zeros, - and will use a fixed format rather than an exponential format, -> depending on the magnitude of the value. \label{ffpkyx} -- - int fits_write_key_str / ffpkys - (fitsfile *fptr, char *keyname, char *value, char *comment, - > int *status) - - int fits_write_key_[log, lng] / ffpky[lj] - (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, - > int *status) - - int fits_write_key_[flt, dbl, fixflg, fixdbl] / ffpky[edfg] - (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, - char *comment, > int *status) - - int fits_write_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffpk[yc,ym,fc,fm] - (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, - char *comment, > int *status) -- ->2 Write (append) a string valued keyword into the CHU which may be longer - than 68 characters in length. This uses the Long String Keyword - convention that is described in the`Local FITS Conventions' section - in Chapter 4. Since this uses a non-standard FITS convention to - encode the long keyword string, programs which use this routine - should also call the fits\_write\_key\_longwarn routine to add some - COMMENT keywords to warn users of the FITS file that this - convention is being used. The fits\_write\_key\_longwarn routine - also writes a keyword called LONGSTRN to record the version of the - longstring convention that has been used, in case a new convention - is adopted at some point in the future. If the LONGSTRN keyword - is already present in the header, then fits\_write\_key\_longwarn - will -> simply return without doing anything. \label{ffpkls} \label{ffplsw} -- - int fits_write_key_longstr / ffpkls - (fitsfile *fptr, char *keyname, char *longstr, char *comment, - > int *status) - - int fits_write_key_longwarn / ffplsw - (fitsfile *fptr, > int *status) -- ->3 Write (append) a numbered sequence of keywords into the CHU. The - starting index number (nstart) must be greater than 0. One may - append the same comment to every keyword (and eliminate the need - to have an array of identical comment strings, one for each keyword) by - including the ampersand character as the last non-blank character in the - (first) COMMENTS string parameter. This same string - will then be used for the comment field in all the keywords. - One may also enter a null pointer for the comment parameter to -> leave the comment field of the keyword blank. \label{ffpknx} -- - int fits_write_keys_str / ffpkns - (fitsfile *fptr, char *keyroot, int nstart, int nkeys, - char **value, char **comment, > int *status) - - int fits_write_keys_[log, lng] / ffpkn[lj] - (fitsfile *fptr, char *keyroot, int nstart, int nkeys, - DTYPE *numval, char **comment, int *status) - - int fits_write_keys_[flt, dbl, fixflg, fixdbl] / ffpkne[edfg] - (fitsfile *fptr, char *keyroot, int nstart, int nkey, - DTYPE *numval, int decimals, char **comment, > int *status) -- ->4 Copy an indexed keyword from one HDU to another, modifying - the index number of the keyword name in the process. For example, - this routine could read the TLMIN3 keyword from the input HDU - (by giving keyroot = `TLMIN' and innum = 3) and write it to the - output HDU with the keyword name TLMIN4 (by setting outnum = 4). - If the input keyword does not exist, then this routine simply -> returns without indicating an error. \label{ffcpky} -- - int fits_copy_key / ffcpky - (fitsfile *infptr, fitsfile *outfptr, int innum, int outnum, - char *keyroot, > int *status) -- ->5 Write (append) a `triple precision' keyword into the CHU in F28.16 format. - The floating point keyword value is constructed by concatenating the - input integer value with the input double precision fraction value - (which must have a value between 0.0 and 1.0). The ffgkyt routine should - be used to read this keyword value, because the other keyword reading -> routines will not preserve the full precision of the value. \label{ffpkyt} -- - int fits_write_key_triple / ffpkyt - (fitsfile *fptr, char *keyname, long intval, double frac, - char *comment, > int *status) -- ->6 Write keywords to the CHDU that are defined in an ASCII template file. - The format of the template file is described under the fits\_parse\_template -> routine. \label{ffpktp} -- - int fits_write_key_template / ffpktp - (fitsfile *fptr, const char *filename, > int *status) -- -***4. Insert Keyword Routines - -These insert routines are somewhat less efficient than the `update' or -`write' keyword routines because the following keywords in the header -must be shifted down to make room for the inserted keyword. See -Appendix B for the definition of the parameters used in these -routines. - ->1 Insert a new keyword record into the CHU at the specified position - (i.e., immediately preceding the (keynum)th keyword in the header.) -> \label{ffirec} -- - int fits_insert_record / ffirec - (fitsfile *fptr, int keynum, char *card, > int *status) -- ->2 Insert a new keyword into the CHU. The new keyword is inserted - immediately following the last keyword that has been read from the - header. The `longstr' version has the same functionality as the - `str' version except that it also supports the local long string - keyword convention for strings longer than 68 characters. A null - pointer may be entered for the comment parameter which will cause - the comment field to be left blank. The flt, dbl, cmp, and dblcmp - versions of this routine have the added - feature that if the 'decimals' parameter is negative, then the 'G' - display format rather then the 'E' format will be used when - constructing the keyword value, taking the absolute value of - 'decimals' for the precision. This will suppress trailing zeros, - and will use a fixed format rather than an exponential format, -> depending on the magnitude of the value. \label{ffikyx} -- - int fits_insert_card / ffikey - (fitsfile *fptr, char *card, > int *status) - - int fits_insert_key_[str, longstr] / ffi[kys, kls] - (fitsfile *fptr, char *keyname, char *value, char *comment, - > int *status) - - int fits_insert_key_[log, lng] / ffiky[lj] - (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, - > int *status) - - int fits_insert_key_[flt, fixflt, dbl, fixdbl] / ffiky[edfg] - (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, - char *comment, > int *status) - - int fits_insert_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffik[yc,ym,fc,fm] - (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, - char *comment, > int *status) -- ->3 Insert a new keyword with an undefined, or null, value into the CHU. -> The value string of the keyword is left blank in this case. \label{ffikyu} -- - int fits_insert_key_null / ffikyu - (fitsfile *fptr, char *keyname, char *comment, > int *status) -- - -***5. Read Keyword Routines - -Wild card characters may be used when specifying the name of the -keyword to be read. - ->1 Read a keyword value (with the appropriate data type) and comment from - the CHU. If a NULL comment pointer is given on input, then the comment - string will not be returned. If the value of the keyword is not defined - (i.e., the value field is blank) then an error status = VALUE\_UNDEFINED - will be returned and the input value will not be changed (except that - ffgkys will reset the value to a null string). -> \label{ffgkyx} \label{ffgkls} -- - int fits_read_key_str / ffgkys - (fitsfile *fptr, char *keyname, > char *value, char *comment, - int *status); - - NOTE: after calling the following routine, programs must explicitly free - the memory allocated for 'longstr' after it is no longer needed by - calling fits_free_memory. - - int fits_read_key_longstr / ffgkls - (fitsfile *fptr, char *keyname, > char **longstr, char *comment, - int *status) - - int fits_free_memory / fffree - (char *longstr, > int *status); - - int fits_read_key_[log, lng, flt, dbl, cmp, dblcmp] / ffgky[ljedcm] - (fitsfile *fptr, char *keyname, > DTYPE *numval, char *comment, - int *status) - - int fits_read_key_lnglng / ffgkyjj - (fitsfile *fptr, char *keyname, > LONGLONG *numval, char *comment, - int *status) -- ->2 Read a sequence of indexed keyword values (e.g., NAXIS1, NAXIS2, ...). - The input starting index number (nstart) must be greater than 0. - If the value of any of the keywords is not defined (i.e., the value - field is blank) then an error status = VALUE\_UNDEFINED will be - returned and the input value for the undefined keyword(s) will not - be changed. These routines do not support wild card characters in - the root name. If there are no indexed keywords in the header with - the input root name then these routines do not return a non-zero -> status value and instead simply return nfound = 0. \label{ffgknx} -- - int fits_read_keys_str / ffgkns - (fitsfile *fptr, char *keyname, int nstart, int nkeys, - > char **value, int *nfound, int *status) - - int fits_read_keys_[log, lng, flt, dbl] / ffgkn[ljed] - (fitsfile *fptr, char *keyname, int nstart, int nkeys, - > DTYPE *numval, int *nfound, int *status) -- ->3 Read the value of a floating point keyword, returning the integer and - fractional parts of the value in separate routine arguments. - This routine may be used to read any keyword but is especially - useful for reading the 'triple precision' keywords written by ffpkyt. -> \label{ffgkyt} -- - int fits_read_key_triple / ffgkyt - (fitsfile *fptr, char *keyname, > long *intval, double *frac, - char *comment, int *status) -- -***6. Modify Keyword Routines - -These routines modify the value of an existing keyword. An error is -returned if the keyword does not exist. Wild card characters may be -used when specifying the name of the keyword to be modified. See -Appendix B for the definition of the parameters used in these -routines. - ->>1 Modify (overwrite) the nth 80-character header record in the CHU. \label{ffmrec} -- - int fits_modify_record / ffmrec - (fitsfile *fptr, int keynum, char *card, > int *status) -- ->2 Modify (overwrite) the 80-character header record for the named keyword - in the CHU. This can be used to overwrite the name of the keyword as -> well as its value and comment fields. \label{ffmcrd} -- - int fits_modify_card / ffmcrd - (fitsfile *fptr, char *keyname, char *card, > int *status) -- ->5 Modify the value and comment fields of an existing keyword in the CHU. - The `longstr' version has the same functionality as the `str' - version except that it also supports the local long string keyword - convention for strings longer than 68 characters. Optionally, one - may modify only the value field and leave the comment field - unchanged by setting the input COMMENT parameter equal to the - ampersand character (\&) or by entering a null pointer for the - comment parameter. The flt, dbl, cmp, and dblcmp versions of this - routine have the added feature that if the 'decimals' parameter is - negative, then the 'G' display format rather then the 'E' format - will be used when constructing the keyword value, taking the - absolute value of 'decimals' for the precision. This will suppress - trailing zeros, and will use a fixed format rather than an - exponential format, -> depending on the magnitude of the value. \label{ffmkyx} -- - int fits_modify_key_[str, longstr] / ffm[kys, kls] - (fitsfile *fptr, char *keyname, char *value, char *comment, - > int *status); - - int fits_modify_key_[log, lng] / ffmky[lj] - (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, - > int *status) - - int fits_modify_key_[flt, dbl, fixflt, fixdbl] / ffmky[edfg] - (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, - char *comment, > int *status) - - int fits_modify_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffmk[yc,ym,fc,fm] - (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, - char *comment, > int *status) -- ->6 Modify the value of an existing keyword to be undefined, or null. - The value string of the keyword is set to blank. - Optionally, one may leave the comment field unchanged by setting the - input COMMENT parameter equal to -> the ampersand character (\&) or by entering a null pointer. \label{ffmkyu} -- - int fits_modify_key_null / ffmkyu - (fitsfile *fptr, char *keyname, char *comment, > int *status) -- -***7. Update Keyword Routines - ->1 These update routines modify the value, and optionally the comment field, - of the keyword if it already exists, otherwise the new keyword is - appended to the header. A separate routine is provided for each - keyword data type. The `longstr' version has the same functionality - as the `str' version except that it also supports the local long - string keyword convention for strings longer than 68 characters. A - null pointer may be entered for the comment parameter which will - leave the comment field unchanged or blank. The flt, dbl, cmp, and - dblcmp versions of this routine have the added feature that if the - 'decimals' parameter is negative, then the 'G' display format - rather then the 'E' format will be used when constructing the - keyword value, taking the absolute value of 'decimals' for the - precision. This will suppress trailing zeros, and will use a fixed - format rather than an exponential format, -> depending on the magnitude of the value. \label{ffukyx} -- - int fits_update_key_[str, longstr] / ffu[kys, kls] - (fitsfile *fptr, char *keyname, char *value, char *comment, - > int *status) - - int fits_update_key_[log, lng] / ffuky[lj] - (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, - > int *status) - - int fits_update_key_[flt, dbl, fixflt, fixdbl] / ffuky[edfg] - (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, - char *comment, > int *status) - - int fits_update_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffuk[yc,ym,fc,fm] - (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, - char *comment, > int *status) -- - -**D. Define Data Scaling and Undefined Pixel Parameters - -These routines set or modify the internal parameters used by CFITSIO -to either scale the data or to represent undefined pixels. Generally -CFITSIO will scale the data according to the values of the BSCALE and -BZERO (or TSCALn and TZEROn) keywords, however these routines may be -used to override the keyword values. This may be useful when one wants -to read or write the raw unscaled values in the FITS file. Similarly, -CFITSIO generally uses the value of the BLANK or TNULLn keyword to -signify an undefined pixel, but these routines may be used to override -this value. These routines do not create or modify the corresponding -header keyword values. See Appendix B for the definition of the -parameters used in these routines. - ->1 Reset the scaling factors in the primary array or image extension; does - not change the BSCALE and BZERO keyword values and only affects the - automatic scaling performed when the data elements are written/read - to/from the FITS file. When reading from a FITS file the returned - data value = (the value given in the FITS array) * BSCALE + BZERO. - The inverse formula is used when writing data values to the FITS -> file. \label{ffpscl} -- - int fits_set_bscale / ffpscl - (fitsfile *fptr, double scale, double zero, > int *status) -- ->2 Reset the scaling parameters for a table column; does not change - the TSCALn or TZEROn keyword values and only affects the automatic - scaling performed when the data elements are written/read to/from - the FITS file. When reading from a FITS file the returned data - value = (the value given in the FITS array) * TSCAL + TZERO. The - inverse formula is used when writing data values to the FITS file. -> \label{fftscl} -- - int fits_set_tscale / fftscl - (fitsfile *fptr, int colnum, double scale, double zero, - > int *status) -- ->3 Define the integer value to be used to signify undefined pixels in the - primary array or image extension. This is only used if BITPIX = 8, 16, - or 32. This does not create or change the value of the BLANK keyword in -> the header. \label{ffpnul} -- - int fits_set_imgnull / ffpnul - (fitsfile *fptr, LONGLONG nulval, > int *status) -- ->4 Define the string to be used to signify undefined pixels in - a column in an ASCII table. This does not create or change the value -> of the TNULLn keyword. \label{ffsnul} -- - int fits_set_atblnull / ffsnul - (fitsfile *fptr, int colnum, char *nulstr, > int *status) -- ->5 Define the value to be used to signify undefined pixels in - an integer column in a binary table (where TFORMn = 'B', 'I', or 'J'). - This does not create or change the value of the TNULLn keyword. -> \label{fftnul} -- - int fits_set_btblnull / fftnul - (fitsfile *fptr, int colnum, LONGLONG nulval, > int *status) -- - -**E. Specialized FITS Primary Array or IMAGE Extension I/O Routines - -These routines read or write data values in the primary data array -(i.e., the first HDU in the FITS file) or an IMAGE extension. -Automatic data type conversion is performed for if the data type of the -FITS array (as defined by the BITPIX keyword) differs from the data -type of the array in the calling routine. The data values are -automatically scaled by the BSCALE and BZERO header values as they are -being written or read from the FITS array. Unlike the basic routines -described in the previous chapter, most of these routines specifically -support the FITS random groups format. See Appendix B for the -definition of the parameters used in these routines. - -The more primitive reading and writing routines (i. e., ffppr\_, -ffppn\_, ffppn, ffgpv\_, or ffgpf\_) simply treat the primary array as -a long 1-dimensional array of pixels, ignoring the intrinsic -dimensionality of the array. When dealing with a 2D image, for -example, the application program must calculate the pixel offset in the -1-D array that corresponds to any particular X, Y coordinate in the -image. C programmers should note that the ordering of arrays in FITS -files, and hence in all the CFITSIO calls, is more similar to the -dimensionality of arrays in Fortran rather than C. For instance if a -FITS image has NAXIS1 = 100 and NAXIS2 = 50, then a 2-D array just -large enough to hold the image should be declared as array[50][100] and -not as array[100][50]. - -For convenience, higher-level routines are also provided to specifically -deal with 2D images (ffp2d\_ and ffg2d\_) and 3D data cubes (ffp3d\_ -and ffg3d\_). The dimensionality of the FITS image is passed by the -naxis1, naxis2, and naxis3 parameters and the declared dimensions of -the program array are passed in the dim1 and dim2 parameters. Note -that the dimensions of the program array may be larger than the -dimensions of the FITS array. For example if a FITS image with NAXIS1 -= NAXIS2 = 400 is read into a program array which is dimensioned as 512 -x 512 pixels, then the image will just fill the lower left corner of -the array with pixels in the range 1 - 400 in the X an Y directions. -This has the effect of taking a contiguous set of pixel value in the -FITS array and writing them to a non-contiguous array in program memory -(i.e., there are now some blank pixels around the edge of the image in -the program array). - -The most general set of routines (ffpss\_, ffgsv\_, and ffgsf\_) may be -used to transfer a rectangular subset of the pixels in a FITS -N-dimensional image to or from an array which has been declared in the -calling program. The fpixel and lpixel parameters are integer arrays -which specify the starting and ending pixel coordinate in each dimension -(starting with 1, not 0) of the FITS image that is to be read or -written. It is important to note that these are the starting and -ending pixels in the FITS image, not in the declared array in the -program. The array parameter in these routines is treated simply as a -large one-dimensional array of the appropriate data type containing the -pixel values; The pixel values in the FITS array are read/written -from/to this program array in strict sequence without any gaps; it is -up to the calling routine to correctly interpret the dimensionality of -this array. The two FITS reading routines (ffgsv\_ and ffgsf\_ ) also -have an `inc' parameter which defines the data sampling interval in -each dimension of the FITS array. For example, if inc[0]=2 and -inc[1]=3 when reading a 2-dimensional FITS image, then only every other -pixel in the first dimension and every 3rd pixel in the second -dimension will be returned to the 'array' parameter. - -Two types of routines are provided to read the data array which differ in -the way undefined pixels are handled. The first type of routines (e.g., -ffgpv\_) simply return an array of data elements in which undefined -pixels are set equal to a value specified by the user in the `nulval' -parameter. An additional feature of these routines is that if the user -sets nulval = 0, then no checks for undefined pixels will be performed, -thus reducing the amount of CPU processing. The second type of routines -(e.g., ffgpf\_) returns the data element array and, in addition, a char -array that indicates whether the value of the corresponding data pixel -is undefined (= 1) or defined (= 0). The latter type of routines may -be more convenient to use in some circumstances, however, it requires -an additional array of logical values which can be unwieldy when working -with large data arrays. - ->1 Write elements into the FITS data array. -> \label{ffppr} \label{ffpprx} \label{ffppn} \label{ffppnx} -- - int fits_write_img / ffppr - (fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelements, - DTYPE *array, int *status); - - int fits_write_img_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffppr[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelements, - DTYPE *array, > int *status); - - int fits_write_imgnull / ffppn - (fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelements, - DTYPE *array, DTYPE *nulval, > int *status); - - int fits_write_imgnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffppn[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelements, DTYPE *array, DTYPE nulval, > int *status); -- ->>2 Set data array elements as undefined. \label{ffppru} -- - int fits_write_img_null / ffppru - (fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelements, - > int *status) -- ->3 Write values into group parameters. This routine only applies - to the `Random Grouped' FITS format which has been used for - applications in radio interferometry, but is officially deprecated -> for future use. \label{ffpgpx} -- - int fits_write_grppar_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffpgp[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, long firstelem, long nelements, - > DTYPE *array, int *status) -- ->>4 Write a 2-D or 3-D image into the data array. \label{ffp2dx} \label{ffp3dx} -- - int fits_write_2d_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffp2d[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, LONGLONG dim1, LONGLONG naxis1, - LONGLONG naxis2, DTYPE *array, > int *status) - - int fits_write_3d_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffp3d[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, LONGLONG dim1, LONGLONG dim2, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, DTYPE *array, > int *status) -- ->>5 Write an arbitrary data subsection into the data array. \label{ffpssx} -- - int fits_write_subset_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffpss[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, DTYPE *array, > int *status) -- ->6 Read elements from the FITS data array. -> \label{ffgpv} \label{ffgpvx} \label{ffgpf} \label{ffgpfx} -- - int fits_read_img / ffgpv - (fitsfile *fptr, int datatype, long firstelem, long nelements, - DTYPE *nulval, > DTYPE *array, int *anynul, int *status) - - int fits_read_img_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffgpv[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, long firstelem, long nelements, - DTYPE nulval, > DTYPE *array, int *anynul, int *status) - - int fits_read_imgnull / ffgpf - (fitsfile *fptr, int datatype, long firstelem, long nelements, - > DTYPE *array, char *nullarray, int *anynul, int *status) - - int fits_read_imgnull_[byt, sht, usht, int, uint, lng, ulng, flt, dbl] / - ffgpf[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, long firstelem, long nelements, - > DTYPE *array, char *nullarray, int *anynul, int *status) -- ->7 Read values from group parameters. This routine only applies - to the `Random Grouped' FITS format which has been used for - applications in radio interferometry, but is officially deprecated -> for future use. \label{ffggpx} -- - int fits_read_grppar_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffggp[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, long firstelem, long nelements, - > DTYPE *array, int *status) -- ->8 Read 2-D or 3-D image from the data array. Undefined - pixels in the array will be set equal to the value of 'nulval', - unless nulval=0 in which case no testing for undefined pixels will -> be performed. \label{ffg2dx} \label{ffg3dx} -- - int fits_read_2d_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffg2d[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, DTYPE nulval, LONGLONG dim1, LONGLONG naxis1, - LONGLONG naxis2, > DTYPE *array, int *anynul, int *status) - - int fits_read_3d_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffg3d[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, DTYPE nulval, LONGLONG dim1, - LONGLONG dim2, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - > DTYPE *array, int *anynul, int *status) -- ->9 Read an arbitrary data subsection from the data array. -> \label{ffgsvx} \label{ffgsfx} -- - int fits_read_subset_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffgsv[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, int group, int naxis, long *naxes, - long *fpixel, long *lpixel, long *inc, DTYPE nulval, - > DTYPE *array, int *anynul, int *status) - - int fits_read_subsetnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffgsf[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, int group, int naxis, long *naxes, - long *fpixel, long *lpixel, long *inc, > DTYPE *array, - char *nullarray, int *anynul, int *status) -- - -**F. Specialized FITS ASCII and Binary Table Routines - -***1. General Column Routines - ->1 Get information about an existing ASCII or binary table column. A null - pointer may be given for any of the output parameters that are not - needed. DATATYPE is a character string which returns the data type - of the column as defined by the TFORMn keyword (e.g., 'I', 'J','E', - 'D', etc.). In the case of an ASCII character column, typecode - will have a value of the form 'An' where 'n' is an integer - expressing the width of the field in characters. For example, if - TFORM = '160A8' then ffgbcl will return typechar='A8' and - repeat=20. All the returned parameters are scalar quantities. -> \label{ffgacl} \label{ffgbcl} -- - int fits_get_acolparms / ffgacl - (fitsfile *fptr, int colnum, > char *ttype, long *tbcol, - char *tunit, char *tform, double *scale, double *zero, - char *nulstr, char *tdisp, int *status) - - int fits_get_bcolparms / ffgbcl - (fitsfile *fptr, int colnum, > char *ttype, char *tunit, - char *typechar, long *repeat, double *scale, double *zero, - long *nulval, char *tdisp, int *status) - - int fits_get_bcolparmsll / ffgbclll - (fitsfile *fptr, int colnum, > char *ttype, char *tunit, - char *typechar, LONGLONG *repeat, double *scale, double *zero, - LONGLONG *nulval, char *tdisp, int *status) -- ->2 Return optimal number of rows to read or write at one time for - maximum I/O efficiency. Refer to the - ``Optimizing Code'' section in Chapter 5 for more discussion on how -> to use this routine. \label{ffgrsz} -- - int fits_get_rowsize / ffgrsz - (fitsfile *fptr, long *nrows, *status) -- ->3 Define the zero indexed byte offset of the 'heap' measured from - the start of the binary table data. By default the heap is assumed - to start immediately following the regular table data, i.e., at - location NAXIS1 x NAXIS2. This routine is only relevant for - binary tables which contain variable length array columns (with - TFORMn = 'Pt'). This routine also automatically writes - the value of theap to a keyword in the extension header. This - routine must be called after the required keywords have been - written (with ffphbn) -> but before any data is written to the table. \label{ffpthp} -- - int fits_write_theap / ffpthp - (fitsfile *fptr, long theap, > int *status) -- ->4 Test the contents of the binary table variable array heap, returning - the size of the heap, the number of unused bytes that are not currently - pointed to by any of the descriptors, and the number of bytes which are - pointed to by multiple descriptors. It also returns valid = FALSE if - any of the descriptors point to invalid addresses out of range of the -> heap. \label{fftheap} -- - int fits_test_heap / fftheap - (fitsfile *fptr, > LONGLONG *heapsize, LONGLONG *unused, LONGLONG *overlap, - int *validheap, int *status) -- ->5 Re-pack the vectors in the binary table variable array heap to recover - any unused space. Normally, when a vector in a variable length - array column is rewritten the previously written array remains in - the heap as wasted unused space. This routine will repack the - arrays that are still in use, thus eliminating any bytes in the - heap that are no longer in use. Note that if several vectors point - to the same bytes in the heap, then this routine will make - duplicate copies of the bytes for each vector, which will actually -> expand the size of the heap. \label{ffcmph} -- - int fits_compress_heap / ffcmph - (fitsfile *fptr, > int *status) -- - -***2. Low-Level Table Access Routines - -The following 2 routines provide low-level access to the data in ASCII -or binary tables and are mainly useful as an efficient way to copy all -or part of a table from one location to another. These routines simply -read or write the specified number of consecutive bytes in an ASCII or -binary table, without regard for column boundaries or the row length in -the table. These routines do not perform any machine dependent data -conversion or byte swapping. See Appendix B for the definition of the -parameters used in these routines. - ->1 Read or write a consecutive array of bytes from an ASCII or binary -> table \label{ffgtbb} \label{ffptbb} -- - int fits_read_tblbytes / ffgtbb - (fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, - > unsigned char *values, int *status) - - int fits_write_tblbytes / ffptbb - (fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, - unsigned char *values, > int *status) -- - -***3. Write Column Data Routines - ->1 Write elements into an ASCII or binary table column (in the CDU). - The data type of the array is implied by the suffix of the -> routine name. \label{ffpcls} -- - int fits_write_col_str / ffpcls - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, char **array, > int *status) - - int fits_write_col_[log,byt,sht,usht,int,uint,lng,ulng,lnglng,flt,dbl,cmp,dblcmp] / - ffpcl[l,b,i,ui,k,uk,j,uj,jj,e,d,c,m] - (fitsfile *fptr, int colnum, LONGLONG firstrow, - LONGLONG firstelem, LONGLONG nelements, DTYPE *array, > int *status) -- ->2 Write elements into an ASCII or binary table column - substituting the appropriate FITS null value for any elements that -> are equal to the nulval parameter. \label{ffpcnx} -- - int fits_write_colnull_[log, byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffpcn[l,b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, DTYPE *array, DTYPE nulval, > int *status) -- ->3 Write string elements into a binary table column (in the CDU) - substituting the FITS null value for any elements that -> are equal to the nulstr string. \label{ffpcns} -- - int fits_write_colnull_str / ffpcns - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, char **array, char *nulstr, > int *status) -- ->4 Write bit values into a binary byte ('B') or bit ('X') table column (in - the CDU). Larray is an array of characters corresponding to the - sequence of bits to be written. If an element of larray is true - (not equal to zero) then the corresponding bit in the FITS table is - set to 1, otherwise the bit is set to 0. The 'X' column in a FITS - table is always padded out to a multiple of 8 bits where the bit - array starts with the most significant bit of the byte and works - down towards the 1's bit. For example, a '4X' array, with the - first bit = 1 and the remaining 3 bits = 0 is equivalent to the 8-bit - unsigned byte decimal value of 128 ('1000 0000B'). In the case of - 'X' columns, CFITSIO can write to all 8 bits of each byte whether - they are formally valid or not. Thus if the column is defined as - '4X', and one calls ffpclx with firstbit=1 and nbits=8, then all - 8 bits will be written into the first byte (as opposed to writing - the first 4 bits into the first row and then the next 4 bits into - the next row), even though the last 4 bits of each byte are formally - not defined and should all be set = 0. It should also be noted that - it is more efficient to write 'X' columns an entire byte at a time, - instead of bit by bit. Any of the CFITSIO routines that write to - columns (e.g. fits\_write\_col\_byt) may be used for this purpose. - These routines will interpret 'X' columns as though they were 'B' - columns (e.g., '1X' through '8X' is equivalent -> to '1B', and '9X' through '16X' is equivalent to '2B'). \label{ffpclx} -- - int fits_write_col_bit / ffpclx - (fitsfile *fptr, int colnum, LONGLONG firstrow, long firstbit, - long nbits, char *larray, > int *status) -- ->5 Write the descriptor for a variable length column in a binary table. - This routine can be used in conjunction with ffgdes to enable - 2 or more arrays to point to the same storage location to save -> storage space if the arrays are identical. \label{ffpdes} -- - int fits_write_descript / ffpdes - (fitsfile *fptr, int colnum, LONGLONG rownum, LONGLONG repeat, - LONGLONG offset, > int *status) -- -***4. Read Column Data Routines - -Two types of routines are provided to get the column data which differ -in the way undefined pixels are handled. The first set of routines -(ffgcv) simply return an array of data elements in which undefined -pixels are set equal to a value specified by the user in the 'nullval' -parameter. If nullval = 0, then no checks for undefined pixels will be -performed, thus increasing the speed of the program. The second set of -routines (ffgcf) returns the data element array and in addition a -logical array of flags which defines whether the corresponding data -pixel is undefined. See Appendix B for the definition of the -parameters used in these routines. - - Any column, regardless of it's intrinsic data type, may be read as a - string. It should be noted however that reading a numeric column as - a string is 10 - 100 times slower than reading the same column as a number - due to the large overhead in constructing the formatted strings. - The display format of the returned strings will be - determined by the TDISPn keyword, if it exists, otherwise by the - data type of the column. The length of the returned strings (not - including the null terminating character) can be determined with - the fits\_get\_col\_display\_width routine. The following TDISPn - display formats are currently supported: -- - Iw.m Integer - Ow.m Octal integer - Zw.m Hexadecimal integer - Fw.d Fixed floating point - Ew.d Exponential floating point - Dw.d Exponential floating point - Gw.d General; uses Fw.d if significance not lost, else Ew.d -- - where w is the width in characters of the displayed values, m is - the minimum number of digits displayed, and d is the number of - digits to the right of the decimal. The .m field is optional. - ->1 Read elements from an ASCII or binary table column (in the CDU). These - routines return the values of the table column array elements. Undefined - array elements will be returned with a value = nulval, unless nulval = 0 - (or = ' ' for ffgcvs) in which case no checking for undefined values will - be performed. The anynul parameter is set to true if any of the returned -> elements are undefined. \label{ffgcvx} -- - int fits_read_col_str / ffgcvs - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, char *nulstr, > char **array, int *anynul, - int *status) - - int fits_read_col_[log,byt,sht,usht,int,uint,lng,ulng, lnglng, flt, dbl, cmp, dblcmp] / - ffgcv[l,b,i,ui,k,uk,j,uj,jj,e,d,c,m] - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, DTYPE nulval, > DTYPE *array, int *anynul, - int *status) -- ->2 Read elements and null flags from an ASCII or binary table column (in the - CHDU). These routines return the values of the table column array elements. - Any undefined array elements will have the corresponding nullarray element - set equal to TRUE. The anynul parameter is set to true if any of the -> returned elements are undefined. \label{ffgcfx} -- - int fits_read_colnull_str / ffgcfs - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, > char **array, char *nullarray, int *anynul, - int *status) - - int fits_read_colnull_[log,byt,sht,usht,int,uint,lng,ulng,lnglng,flt,dbl,cmp,dblcmp] / - ffgcf[l,b,i,ui,k,uk,j,uj,jj,e,d,c,m] - (fitsfile *fptr, int colnum, LONGLONG firstrow, - LONGLONG firstelem, LONGLONG nelements, > DTYPE *array, - char *nullarray, int *anynul, int *status) -- ->3 Read an arbitrary data subsection from an N-dimensional array - in a binary table vector column. Undefined pixels - in the array will be set equal to the value of 'nulval', - unless nulval=0 in which case no testing for undefined pixels will - be performed. The first and last rows in the table to be read - are specified by fpixel(naxis+1) and lpixel(naxis+1), and hence - are treated as the next higher dimension of the FITS N-dimensional - array. The INC parameter specifies the sampling interval in -> each dimension between the data elements that will be returned. \label{ffgsvx2} -- - int fits_read_subset_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffgsv[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, int colnum, int naxis, long *naxes, long *fpixel, - long *lpixel, long *inc, DTYPE nulval, > DTYPE *array, int *anynul, - int *status) -- ->4 Read an arbitrary data subsection from an N-dimensional array - in a binary table vector column. Any Undefined - pixels in the array will have the corresponding 'nullarray' - element set equal to TRUE. The first and last rows in the table - to be read are specified by fpixel(naxis+1) and lpixel(naxis+1), - and hence are treated as the next higher dimension of the FITS - N-dimensional array. The INC parameter specifies the sampling - interval in each dimension between the data elements that will be -> returned. \label{ffgsfx2} -- - int fits_read_subsetnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffgsf[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, int colnum, int naxis, long *naxes, - long *fpixel, long *lpixel, long *inc, > DTYPE *array, - char *nullarray, int *anynul, int *status) -- ->5 Read bit values from a byte ('B') or bit (`X`) table column (in the - CDU). Larray is an array of logical values corresponding to the - sequence of bits to be read. If larray is true then the - corresponding bit was set to 1, otherwise the bit was set to 0. - The 'X' column in a FITS table is always padded out to a multiple - of 8 bits where the bit array starts with the most significant bit - of the byte and works down towards the 1's bit. For example, a - '4X' array, with the first bit = 1 and the remaining 3 bits = 0 is - equivalent to the 8-bit unsigned byte value of 128. - Note that in the case of 'X' columns, CFITSIO can read all 8 bits - of each byte whether they are formally valid or not. Thus if the - column is defined as '4X', and one calls ffgcx with firstbit=1 and - nbits=8, then all 8 bits will be read from the first byte (as - opposed to reading the first 4 bits from the first row and then the - first 4 bits from the next row), even though the last 4 bits of - each byte are formally not defined. It should also be noted that - it is more efficient to read 'X' columns an entire byte at a time, - instead of bit by bit. Any of the CFITSIO routines that read - columns (e.g. fits\_read\_col\_byt) may be used for this - purpose. These routines will interpret 'X' columns as though they - were 'B' columns (e.g., '8X' is equivalent to '1B', and '16X' is -> equivalent to '2B'). \label{ffgcx} -- - int fits_read_col_bit / ffgcx - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstbit, - LONGLONG nbits, > char *larray, int *status) -- ->6 Read any consecutive set of bits from an 'X' or 'B' column and - interpret them as an unsigned n-bit integer. nbits must be less - than 16 or 32 in ffgcxui and ffgcxuk, respectively. If nrows - is greater than 1, then the same set of bits will be read from - each row, starting with firstrow. The bits are numbered with - 1 = the most significant bit of the first element of the column. -> \label{ffgcxui} -- - int fits_read_col_bit_[usht, uint] / ffgcx[ui,uk] - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG, nrows, - long firstbit, long nbits, > DTYPE *array, int *status) -- ->7 Return the descriptor for a variable length column in a binary table. - The descriptor consists of 2 integer parameters: the number of elements - in the array and the starting offset relative to the start of the heap. - The first pair of routine returns a single descriptor whereas the second - pair of routine - returns the descriptors for a range of rows in the table. The only - difference between the 2 routines in each pair is that one returns - the parameters as 'long' integers, whereas the other returns the values - as 64-bit 'LONGLONG' integers. -> \label{ffgdes} -- - int fits_read_descript / ffgdes - (fitsfile *fptr, int colnum, LONGLONG rownum, > long *repeat, - long *offset, int *status) - - int fits_read_descriptll / ffgdesll - (fitsfile *fptr, int colnum, LONGLONG rownum, > LONGLONG *repeat, - LONGLONG *offset, int *status) - - int fits_read_descripts / ffgdess - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows - > long *repeat, long *offset, int *status) - - int fits_read_descriptsll / ffgdessll - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows - > LONGLONG *repeat, LONGLONG *offset, int *status) -- - -*X. Extended File Name Syntax - -**A. Overview - -CFITSIO supports an extended syntax when specifying the name of the -data file to be opened or created that includes the following -features: - -\begin{itemize} -\item -CFITSIO can read IRAF format images which have header file names that -end with the '.imh' extension, as well as reading and writing FITS -files, This feature is implemented in CFITSIO by first converting the -IRAF image into a temporary FITS format file in memory, then opening -the FITS file. Any of the usual CFITSIO routines then may be used to -read the image header or data. Similarly, raw binary data arrays can -be read by converting them on the fly into virtual FITS images. - -\item -FITS files on the Internet can be read (and sometimes written) using the FTP, -HTTP, or ROOT protocols. - -\item -FITS files can be piped between tasks on the stdin and stdout streams. - -\item -FITS files can be read and written in shared memory. This can -potentially achieve better data I/O performance compared to reading and -writing the same FITS files on magnetic disk. - -\item -Compressed FITS files in gzip or Unix COMPRESS format can be directly read. - -\item -Output FITS files can be written directly in compressed gzip format, -thus saving disk space. - -\item -FITS table columns can be created, modified, or deleted 'on-the-fly' as -the table is opened by CFITSIO. This creates a virtual FITS file containing -the modifications that is then opened by the application program. - -\item -Table rows may be selected, or filtered out, on the fly when the table -is opened by CFITSIO, based on an user-specified expression. -Only rows for which the expression evaluates to 'TRUE' are retained -in the copy of the table that is opened by the application program. - -\item -Histogram images may be created on the fly by binning the values in -table columns, resulting in a virtual N-dimensional FITS image. The -application program then only sees the FITS image (in the primary -array) instead of the original FITS table. -\end{itemize} - -The latter 3 table filtering features in particular add very powerful -data processing capabilities directly into CFITSIO, and hence into -every task that uses CFITSIO to read or write FITS files. For example, -these features transform a very simple program that just copies an -input FITS file to a new output file (like the `fitscopy' program that -is distributed with CFITSIO) into a multipurpose FITS file processing -tool. By appending fairly simple qualifiers onto the name of the input -FITS file, the user can perform quite complex table editing operations -(e.g., create new columns, or filter out rows in a table) or create -FITS images by binning or histogramming the values in table columns. -In addition, these functions have been coded using new state-of-the art -algorithms that are, in some cases, 10 - 100 times faster than previous -widely used implementations. - -Before describing the complete syntax for the extended FITS file names -in the next section, here are a few examples of FITS file names that -give a quick overview of the allowed syntax: - -\begin{itemize} -\item -{\tt myfile.fits}: the simplest case of a FITS file on disk in the current -directory. - -\item -{\tt myfile.imh}: opens an IRAF format image file and converts it on the -fly into a temporary FITS format image in memory which can then be read with -any other CFITSIO routine. - -\item -{\tt rawfile.dat[i512,512]}: opens a raw binary data array (a 512 x 512 -short integer array in this case) and converts it on the fly into a -temporary FITS format image in memory which can then be read with any -other CFITSIO routine. - -\item -{\tt myfile.fits.gz}: if this is the name of a new output file, the '.gz' -suffix will cause it to be compressed in gzip format when it is written to -disk. - -\item -{\tt myfile.fits.gz[events, 2]}: opens and uncompresses the gzipped file -myfile.fits then moves to the extension with the keywords EXTNAME -= 'EVENTS' and EXTVER = 2. - -\item -{\tt -}: a dash (minus sign) signifies that the input file is to be read -from the stdin file stream, or that the output file is to be written to -the stdout stream. See also the stream:// driver which provides a -more efficient, but more restricted method of reading or writing to -the stdin or stdout streams. - -\item -{\tt ftp://legacy.gsfc.nasa.gov/test/vela.fits}: FITS files in any ftp -archive site on the Internet may be directly opened with read-only -access. - -\item -{\tt http://legacy.gsfc.nasa.gov/software/test.fits}: any valid URL to a -FITS file on the Web may be opened with read-only access. - -\item -{\tt root://legacy.gsfc.nasa.gov/test/vela.fits}: similar to ftp access -except that it provides write as well as read access to the files -across the network. This uses the root protocol developed at CERN. - -\item -{\tt shmem://h2[events]}: opens the FITS file in a shared memory segment and -moves to the EVENTS extension. - -\item -{\tt mem://}: creates a scratch output file in core computer memory. The -resulting 'file' will disappear when the program exits, so this -is mainly useful for testing purposes when one does not want a -permanent copy of the output file. - -\item -{\tt myfile.fits[3; Images(10)]}: opens a copy of the image contained in the -10th row of the 'Images' column in the binary table in the 3th extension -of the FITS file. The virtual file that is opened by the application just -contains this single image in the primary array. - -\item -{\tt myfile.fits[1:512:2, 1:512:2]}: opens a section of the input image -ranging from the 1st to the 512th pixel in X and Y, and selects every -second pixel in both dimensions, resulting in a 256 x 256 pixel input image -in this case. - -\item -{\tt myfile.fits[EVENTS][col Rad = sqrt(X**2 + Y**2)]}: creates and opens -a virtual file on the fly that is identical to -myfile.fits except that it will contain a new column in the EVENTS -extension called 'Rad' whose value is computed using the indicated -expression which is a function of the values in the X and Y columns. - -\item -{\tt myfile.fits[EVENTS][PHA > 5]}: creates and opens a virtual FITS -files that is identical to 'myfile.fits' except that the EVENTS table -will only contain the rows that have values of the PHA column greater -than 5. In general, any arbitrary boolean expression using a C or -Fortran-like syntax, which may combine AND and OR operators, -may be used to select rows from a table. - -\item -{\tt myfile.fits[EVENTS][bin (X,Y)=1,2048,4]}: creates a temporary FITS -primary array image which is computed on the fly by binning (i.e, -computing the 2-dimensional histogram) of the values in the X and Y -columns of the EVENTS extension. In this case the X and Y coordinates -range from 1 to 2048 and the image pixel size is 4 units in both -dimensions, so the resulting image is 512 x 512 pixels in size. - -\item -The final example combines many of these feature into one complex -expression (it is broken into several lines for clarity): -- - ftp://legacy.gsfc.nasa.gov/data/sample.fits.gz[EVENTS] - [col phacorr = pha * 1.1 - 0.3][phacorr >= 5.0 && phacorr <= 14.0] - [bin (X,Y)=32] -- -In this case, CFITSIO (1) copies and uncompresses the FITS file from -the ftp site on the legacy machine, (2) moves to the 'EVENTS' -extension, (3) calculates a new column called 'phacorr', (4) selects -the rows in the table that have phacorr in the range 5 to 14, and -finally (5) bins the remaining rows on the X and Y column coordinates, -using a pixel size = 32 to create a 2D image. All this processing is -completely transparent to the application program, which simply sees -the final 2-D image in the primary array of the opened file. -\end{itemize} - -The full extended CFITSIO FITS file name can contain several different -components depending on the context. These components are described in -the following sections: -- -When creating a new file: - filetype://BaseFilename(templateName)[compress] - -When opening an existing primary array or image HDU: - filetype://BaseFilename(outName)[HDUlocation][ImageSection][pixFilter] - -When opening an existing table HDU: - filetype://BaseFilename(outName)[HDUlocation][colFilter][rowFilter][binSpec] -- -The filetype, BaseFilename, outName, HDUlocation, ImageSection, and pixFilter -components, if present, must be given in that order, but the colFilter, -rowFilter, and binSpec specifiers may follow in any order. Regardless -of the order, however, the colFilter specifier, if present, will be -processed first by CFITSIO, followed by the rowFilter specifier, and -finally by the binSpec specifier. - -**A. Filetype - -The type of file determines the medium on which the file is located -(e.g., disk or network) and, hence, which internal device driver is used by -CFITSIO to read and/or write the file. Currently supported types are -- - file:// - file on local magnetic disk (default) - ftp:// - a readonly file accessed with the anonymous FTP protocol. - It also supports ftp://username:password@hostname/... - for accessing password-protected ftp sites. - http:// - a readonly file accessed with the HTTP protocol. It - supports username:password just like the ftp driver. - Proxy HTTP servers are supported using the http_proxy - environment variable (see following note). - stream:// - special driver to read an input FITS file from the stdin - stream, and/or write an output FITS file to the stdout - stream. This driver is fragile and has limited - functionality (see the following note). - gsiftp:// - access files on a computational grid using the gridftp - protocol in the Globus toolkit (see following note). - root:// - uses the CERN root protocol for writing as well as - reading files over the network (see following note). - shmem:// - opens or creates a file which persists in the computer's - shared memory (see following note). - mem:// - opens a temporary file in core memory. The file - disappears when the program exits so this is mainly - useful for test purposes when a permanent output file - is not desired. -- -If the filetype is not specified, then type file:// is assumed. -The double slashes '//' are optional and may be omitted in most cases. - -***1. Notes about HTTP proxy servers - -A proxy HTTP server may be used by defining the address (URL) and port -number of the proxy server with the http\_proxy environment variable. -For example -- - setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 -- -will cause CFITSIO to use port 3128 on the heasarc proxy server whenever -reading a FITS file with HTTP. - -***2. Notes about the stream filetype driver - -The stream driver can be used to efficiently read a FITS file from the stdin -file stream or write a FITS to the stdout file stream. However, because these -input and output streams must be accessed sequentially, the FITS file reading or -writing application must also read and write the file sequentially, at least -within the tolerances described below. - -CFITSIO supports 2 different methods for accessing FITS files on the stdin and -stdout streams. The original method, which is invoked by specifying a dash -character, "-", as the name of the file when opening or creating it, works by -storing a complete copy of the entire FITS file in memory. In this case, when -reading from stdin, CFITSIO will copy the entire stream into memory before doing -any processing of the file. Similarly, when writing to stdout, CFITSIO will -create a copy of the entire FITS file in memory, before finally flushing it out -to the stdout stream when the FITS file is closed. Buffering the entire FITS -file in this way allows the application to randomly access any part of the FITS -file, in any order, but it also requires that the user have sufficient available -memory (or virtual memory) to store the entire file, which may not be possible -in the case of very large files. - -The newer stream filetype provides a more memory-efficient method of accessing -FITS files on the stdin or stdout streams. Instead of storing a copy of the -entire FITS file in memory, CFITSIO only uses a set of internal buffer which by -default can store 40 FITS blocks, or about 100K bytes of the FITS file. The -application program must process the FITS file sequentially from beginning to -end, within this 100K buffer. Generally speaking the application program must -conform to the following restrictions: - -\begin{itemize} -\item -The program must finish reading or writing the header keywords -before reading or writing any data in the HDU. -\item -The HDU can contain at most about 1400 header keywords. This is the -maximum that can fit in the nominal 40 FITS block buffer. In principle, -this limit could be increased by recompiling CFITSIO with a larger -buffer limit, which is set by the NIOBUF parameter in fitsio2.h. -\item -The program must read or write the data in a sequential manner from the -beginning to the end of the HDU. Note that CFITSIO's internal -100K buffer allows a little latitude in meeting this requirement. -\item -The program cannot move back to a previous HDU in the FITS file. -\item -Reading or writing of variable length array columns in binary tables is not -supported on streams, because this requires moving back and forth between the -fixed-length portion of the binary table and the following heap area where the -arrays are actually stored. -\item -Reading or writing of tile-compressed images is not supported on streams, -because the images are internally stored using variable length arrays. -\end{itemize} - -***3. Notes about the gsiftp filetype - -DEPENDENCIES: Globus toolkit (2.4.3 or higher) (GT) should be installed. -There are two different ways to install GT: - -1) goto the globus toolkit web page www.globus.org and follow the - download and compilation instructions; - -2) goto the Virtual Data Toolkit web page http://vdt.cs.wisc.edu/ - and follow the instructions (STRONGLY SUGGESTED); - -Once a globus client has been installed in your system with a specific flavour -it is possible to compile and install the CFITSIO libraries. -Specific configuration flags must be used: - -1) --with-gsiftp[[=PATH]] Enable Globus Toolkit gsiftp protocol support - PATH=GLOBUS\_LOCATION i.e. the location of your globus installation - -2) --with-gsiftp-flavour[[=PATH] defines the specific Globus flavour - ex. gcc32 - -Both the flags must be used and it is mandatory to set both the PATH and the -flavour. - -USAGE: To access files on a gridftp server it is necessary to use a gsiftp prefix: - -example: gsiftp://remote\_server\_fqhn/directory/filename - -The gridftp driver uses a local buffer on a temporary file the file is located -in the /tmp directory. If you have special permissions on /tmp or you do not have a /tmp -directory, it is possible to force another location setting the GSIFTP\_TMPFILE environment -variable (ex. export GSIFTP\_TMPFILE=/your/location/yourtmpfile). - -Grid FTP supports multi channel transfer. By default a single channel transmission is -available. However, it is possible to modify this behavior setting the GSIFTP\_STREAMS -environment variable (ex. export GSIFTP\_STREAMS=8). - - -***4. Notes about the root filetype - -The original rootd server can be obtained from: -\verb-ftp://root.cern.ch/root/rootd.tar.gz- -but, for it to work correctly with CFITSIO one has to use a modified -version which supports a command to return the length of the file. -This modified version is available in rootd subdirectory -in the CFITSIO ftp area at -- - ftp://legacy.gsfc.nasa.gov/software/fitsio/c/root/rootd.tar.gz. -- - -This small server is started either by inetd when a client requests a -connection to a rootd server or by hand (i.e. from the command line). -The rootd server works with the ROOT TNetFile class. It allows remote -access to ROOT database files in either read or write mode. By default -TNetFile assumes port 432 (which requires rootd to be started as root). -To run rootd via inetd add the following line to /etc/services: -- - rootd 432/tcp -- -and to /etc/inetd.conf, add the following line: -- - rootd stream tcp nowait root /user/rdm/root/bin/rootd rootd -i -- -Force inetd to reread its conf file with \verb+kill -HUP +. -You can also start rootd by hand running directly under your private -account (no root system privileges needed). For example to start -rootd listening on port 5151 just type: \verb+rootd -p 5151+ -Notice that no \& is needed. Rootd will go into background by itself. -- - Rootd arguments: - -i says we were started by inetd - -p port# specifies a different port to listen on - -d level level of debug info written to syslog - 0 = no debug (default) - 1 = minimum - 2 = medium - 3 = maximum -- -Rootd can also be configured for anonymous usage (like anonymous ftp). -To setup rootd to accept anonymous logins do the following (while being -logged in as root): -- - - Add the following line to /etc/passwd: - - rootd:*:71:72:Anonymous rootd:/var/spool/rootd:/bin/false - - where you may modify the uid, gid (71, 72) and the home directory - to suite your system. - - - Add the following line to /etc/group: - - rootd:*:72:rootd - - where the gid must match the gid in /etc/passwd. - - - Create the directories: - - mkdir /var/spool/rootd - mkdir /var/spool/rootd/tmp - chmod 777 /var/spool/rootd/tmp - - Where /var/spool/rootd must match the rootd home directory as - specified in the rootd /etc/passwd entry. - - - To make writeable directories for anonymous do, for example: - - mkdir /var/spool/rootd/pub - chown rootd:rootd /var/spool/rootd/pub -- -That's all. Several additional remarks: you can login to an anonymous -server either with the names "anonymous" or "rootd". The password should -be of type user@host.do.main. Only the @ is enforced for the time -being. In anonymous mode the top of the file tree is set to the rootd -home directory, therefore only files below the home directory can be -accessed. Anonymous mode only works when the server is started via -inetd. - -***5. Notes about the shmem filetype: - -Shared memory files are currently supported on most Unix platforms, -where the shared memory segments are managed by the operating system -kernel and `live' independently of processes. They are not deleted (by -default) when the process which created them terminates, although they -will disappear if the system is rebooted. Applications can create -shared memory files in CFITSIO by calling: -- - fit_create_file(&fitsfileptr, "shmem://h2", &status); -- -where the root `file' names are currently restricted to be 'h0', 'h1', -'h2', 'h3', etc., up to a maximum number defined by the the value of -SHARED\_MAXSEG (equal to 16 by default). This is a prototype -implementation of the shared memory interface and a more robust -interface, which will have fewer restrictions on the number of files -and on their names, may be developed in the future. - -When opening an already existing FITS file in shared memory one calls -the usual CFITSIO routine: -- - fits_open_file(&fitsfileptr, "shmem://h7", mode, &status) -- -The file mode can be READWRITE or READONLY just as with disk files. -More than one process can operate on READONLY mode files at the same -time. CFITSIO supports proper file locking (both in READONLY and -READWRITE modes), so calls to fits\_open\_file may be locked out until -another other process closes the file. - -When an application is finished accessing a FITS file in a shared -memory segment, it may close it (and the file will remain in the -system) with fits\_close\_file, or delete it with fits\_delete\_file. -Physical deletion is postponed until the last process calls -ffclos/ffdelt. fits\_delete\_file tries to obtain a READWRITE lock on -the file to be deleted, thus it can be blocked if the object was not -opened in READWRITE mode. - -A shared memory management utility program called `smem', is included -with the CFITSIO distribution. It can be built by typing `make smem'; -then type `smem -h' to get a list of valid options. Executing smem -without any options causes it to list all the shared memory segments -currently residing in the system and managed by the shared memory -driver. To get a list of all the shared memory objects, run the system -utility program `ipcs [-a]'. - -**B. Base Filename - -The base filename is the name of the file optionally including the -director/subdirectory path, and in the case of `ftp', `http', and `root' -filetypes, the machine identifier. Examples: -- - myfile.fits - !data.fits - /data/myfile.fits - fits.gsfc.nasa.gov/ftp/sampledata/myfile.fits.gz -- - -When creating a new output file on magnetic disk (of type file://) if -the base filename begins with an exclamation point (!) then any -existing file with that same basename will be deleted prior to creating -the new FITS file. Otherwise if the file to be created already exists, -then CFITSIO will return an error and will not overwrite the existing -file. Note that the exclamation point, '!', is a special UNIX -character, so if it is used on the command line rather than entered at -a task prompt, it must be preceded by a backslash to force the UNIX -shell to pass it verbatim to the application program. - -If the output disk file name ends with the suffix '.gz', then CFITSIO -will compress the file using the gzip compression algorithm before -writing it to disk. This can reduce the amount of disk space used by -the file. Note that this feature requires that the uncompressed file -be constructed in memory before it is compressed and written to disk, -so it can fail if there is insufficient available memory. - -An input FITS file may be compressed with the gzip or Unix compress -algorithms, in which case CFITSIO will uncompress the file on the fly -into a temporary file (in memory or on disk). Compressed files may -only be opened with read-only permission. When specifying the name of -a compressed FITS file it is not necessary to append the file suffix -(e.g., `.gz' or `.Z'). If CFITSIO cannot find the input file name -without the suffix, then it will automatically search for a compressed -file with the same root name. In the case of reading ftp and http type -files, CFITSIO generally looks for a compressed version of the file -first, before trying to open the uncompressed file. By default, -CFITSIO copies (and uncompressed if necessary) the ftp or http FITS -file into memory on the local machine before opening it. This will -fail if the local machine does not have enough memory to hold the whole -FITS file, so in this case, the output filename specifier (see the next -section) can be used to further control how CFITSIO reads ftp and http -files. - -If the input file is an IRAF image file (*.imh file) then CFITSIO will -automatically convert it on the fly into a virtual FITS image before it -is opened by the application program. IRAF images can only be opened -with READONLY file access. - -Similarly, if the input file is a raw binary data array, then CFITSIO -will convert it on the fly into a virtual FITS image with the basic set -of required header keywords before it is opened by the application -program (with READONLY access). In this case the data type and -dimensions of the image must be specified in square brackets following -the filename (e.g. rawfile.dat[ib512,512]). The first character (case -insensitive) defines the data type of the array: -- - b 8-bit unsigned byte - i 16-bit signed integer - u 16-bit unsigned integer - j 32-bit signed integer - r or f 32-bit floating point - d 64-bit floating point -- -An optional second character specifies the byte order of the array -values: b or B indicates big endian (as in FITS files and the native -format of SUN UNIX workstations and Mac PCs) and l or L indicates -little endian (native format of DEC OSF workstations and IBM PCs). If -this character is omitted then the array is assumed to have the native -byte order of the local machine. These data type characters are then -followed by a series of one or more integer values separated by commas -which define the size of each dimension of the raw array. Arrays with -up to 5 dimensions are currently supported. Finally, a byte offset to -the position of the first pixel in the data file may be specified by -separating it with a ':' from the last dimension value. If omitted, it -is assumed that the offset = 0. This parameter may be used to skip -over any header information in the file that precedes the binary data. -Further examples: -- - raw.dat[b10000] 1-dimensional 10000 pixel byte array - raw.dat[rb400,400,12] 3-dimensional floating point big-endian array - img.fits[ib512,512:2880] reads the 512 x 512 short integer array in - a FITS file, skipping over the 2880 byte header -- - -One special case of input file is where the filename = `-' (a dash or -minus sign) or 'stdin' or 'stdout', which signifies that the input file -is to be read from the stdin stream, or written to the stdout stream if -a new output file is being created. In the case of reading from stdin, -CFITSIO first copies the whole stream into a temporary FITS file (in -memory or on disk), and subsequent reading of the FITS file occurs in -this copy. When writing to stdout, CFITSIO first constructs the whole -file in memory (since random access is required), then flushes it out -to the stdout stream when the file is closed. In addition, if the -output filename = '-.gz' or 'stdout.gz' then it will be gzip compressed -before being written to stdout. - -This ability to read and write on the stdin and stdout steams allows -FITS files to be piped between tasks in memory rather than having to -create temporary intermediate FITS files on disk. For example if task1 -creates an output FITS file, and task2 reads an input FITS file, the -FITS file may be piped between the 2 tasks by specifying -- - task1 - | task2 - -- -where the vertical bar is the Unix piping symbol. This assumes that the 2 -tasks read the name of the FITS file off of the command line. - -**C. Output File Name when Opening an Existing File - -An optional output filename may be specified in parentheses immediately -following the base file name to be opened. This is mainly useful in -those cases where CFITSIO creates a temporary copy of the input FITS -file before it is opened and passed to the application program. This -happens by default when opening a network FTP or HTTP-type file, when -reading a compressed FITS file on a local disk, when reading from the -stdin stream, or when a column filter, row filter, or binning specifier -is included as part of the input file specification. By default this -temporary file is created in memory. If there is not enough memory to -create the file copy, then CFITSIO will exit with an error. In these -cases one can force a permanent file to be created on disk, instead of -a temporary file in memory, by supplying the name in parentheses -immediately following the base file name. The output filename can -include the '!' clobber flag. - -Thus, if the input filename to CFITSIO is: -\verb+file1.fits.gz(file2.fits)+ -then CFITSIO will uncompress `file1.fits.gz' into the local disk file -`file2.fits' before opening it. CFITSIO does not automatically delete -the output file, so it will still exist after the application program -exits. - -The output filename "mem://" is also allowed, which will write the -output file into memory, and also allow write access to the file. This -'file' will disappear when it is closed, but this may be useful for -some applications which only need to modify a temporary copy of the file. - -In some cases, several different temporary FITS files will be created -in sequence, for instance, if one opens a remote file using FTP, then -filters rows in a binary table extension, then create an image by -binning a pair of columns. In this case, the remote file will be -copied to a temporary local file, then a second temporary file will be -created containing the filtered rows of the table, and finally a third -temporary file containing the binned image will be created. In cases -like this where multiple files are created, the outfile specifier will -be interpreted the name of the final file as described below, in descending -priority: - -\begin{itemize} -\item -as the name of the final image file if an image within a single binary -table cell is opened or if an image is created by binning a table column. -\item -as the name of the file containing the filtered table if a column filter -and/or a row filter are specified. -\item -as the name of the local copy of the remote FTP or HTTP file. -\item -as the name of the uncompressed version of the FITS file, if a -compressed FITS file on local disk has been opened. -\item -otherwise, the output filename is ignored. -\end{itemize} - -The output file specifier is useful when reading FTP or HTTP-type -FITS files since it can be used to create a local disk copy of the file -that can be reused in the future. If the output file name = `*' then a -local file with the same name as the network file will be created. -Note that CFITSIO will behave differently depending on whether the -remote file is compressed or not as shown by the following examples: -\begin{itemize} -\item -\verb+ftp://remote.machine/tmp/myfile.fits.gz(*)+ - the remote compressed -file is copied to the local compressed file `myfile.fits.gz', which -is then uncompressed in local memory before being opened and passed -to the application program. - -\item -\verb+ftp://remote.machine/tmp/myfile.fits.gz(myfile.fits)+ - the -remote compressed file is copied and uncompressed into the local file -`myfile.fits'. This example requires less local memory than the -previous example since the file is uncompressed on disk instead of in -memory. - -\item -\verb+ftp://remote.machine/tmp/myfile.fits(myfile.fits.gz)+ - this will -usually produce an error since CFITSIO itself cannot compress files. -\end{itemize} - -The exact behavior of CFITSIO in the latter case depends on the type of -ftp server running on the remote machine and how it is configured. In -some cases, if the file `myfile.fits.gz' exists on the remote machine, -then the server will copy it to the local machine. In other cases the -ftp server will automatically create and transmit a compressed version -of the file if only the uncompressed version exists. This can get -rather confusing, so users should use a certain amount of caution when -using the output file specifier with FTP or HTTP file types, to make -sure they get the behavior that they expect. - -**D. Template File Name when Creating a New File - -When a new FITS file is created with a call to fits\_create\_file, the -name of a template file may be supplied in parentheses immediately -following the name of the new file to be created. This template is -used to define the structure of one or more HDUs in the new file. The -template file may be another FITS file, in which case the newly created -file will have exactly the same keywords in each HDU as in the template -FITS file, but all the data units will be filled with zeros. The -template file may also be an ASCII text file, where each line (in -general) describes one FITS keyword record. The format of the ASCII -template file is described in the following Template Files chapter. - -**E. Image Tile-Compression Specification - -When specifying the name of the output FITS file to be created, the -user can indicate that images should be written in tile-compressed -format (see section 5.5, ``Primary Array or IMAGE Extension I/O -Routines'') by enclosing the compression parameters in square brackets -following the root disk file name. Here are some examples of the -syntax for specifying tile-compressed output images: -- - myfile.fit[compress] - use Rice algorithm and default tile size - - myfile.fit[compress GZIP] - use the specified compression algorithm; - myfile.fit[compress Rice] only the first letter of the algorithm - myfile.fit[compress PLIO] name is required. - - myfile.fit[compress Rice 100,100] - use 100 x 100 pixel tile size - myfile.fit[compress Rice 100,100;2] - as above, and use noisebits = 2 -- - -**F. HDU Location Specification - -The optional HDU location specifier defines which HDU (Header-Data -Unit, also known as an `extension') within the FITS file to initially -open. It must immediately follow the base file name (or the output -file name if present). If it is not specified then the first HDU (the -primary array) is opened. The HDU location specifier is required if -the colFilter, rowFilter, or binSpec specifiers are present, because -the primary array is not a valid HDU for these operations. The HDU may -be specified either by absolute position number, starting with 0 for -the primary array, or by reference to the HDU name, and optionally, the -version number and the HDU type of the desired extension. The location -of an image within a single cell of a binary table may also be -specified, as described below. - -The absolute position of the extension is specified either by enclosed -the number in square brackets (e.g., `[1]' = the first extension -following the primary array) or by preceded the number with a plus sign -(`+1'). To specify the HDU by name, give the name of the desired HDU -(the value of the EXTNAME or HDUNAME keyword) and optionally the -extension version number (value of the EXTVER keyword) and the -extension type (value of the XTENSION keyword: IMAGE, ASCII or TABLE, -or BINTABLE), separated by commas and all enclosed in square brackets. -If the value of EXTVER and XTENSION are not specified, then the first -extension with the correct value of EXTNAME is opened. The extension -name and type are not case sensitive, and the extension type may be -abbreviated to a single letter (e.g., I = IMAGE extension or primary -array, A or T = ASCII table extension, and B = binary table BINTABLE -extension). If the HDU location specifier is equal to `[PRIMARY]' or -`[P]', then the primary array (the first HDU) will be opened. - -An optional pound sign character ("\#") may be appended to the extension -name or number to signify that any other extensions in the file should -be ignored during any subsequent file filtering operations. For example, -when doing row filtering operations on a table extension, CFITSIO normally -creates a copy of the filtered table in memory, along with a verbatim -copy of all the other extensions in the input FITS file. If the pound -sign is appended to the table extension name, then only that extension, -and none of the other extensions in the file, will by copied to memory, -as in the following example: -- - myfile.fit[events#][TIME > 10000] -- - -FITS images are most commonly stored in the primary array or an image -extension, but images can also be stored as a vector in a single cell -of a binary table (i.e. each row of the vector column contains a -different image). Such an image can be opened with CFITSIO by -specifying the desired column name and the row number after the binary -table HDU specifier as shown in the following examples. The column name -is separated from the HDU specifier by a semicolon and the row number -is enclosed in parentheses. In this case CFITSIO copies the image from -the table cell into a temporary primary array before it is opened. The -application program then just sees the image in the primary array, -without any extensions. The particular row to be opened may be -specified either by giving an absolute integer row number (starting -with 1 for the first row), or by specifying a boolean expression that -evaluates to TRUE for the desired row. The first row that satisfies -the expression will be used. The row selection expression has the same -syntax as described in the Row Filter Specifier section, below. - - Examples: -- - myfile.fits[3] - open the 3rd HDU following the primary array - myfile.fits+3 - same as above, but using the FTOOLS-style notation - myfile.fits[EVENTS] - open the extension that has EXTNAME = 'EVENTS' - myfile.fits[EVENTS, 2] - same as above, but also requires EXTVER = 2 - myfile.fits[events,2,b] - same, but also requires XTENSION = 'BINTABLE' - myfile.fits[3; images(17)] - opens the image in row 17 of the 'images' - column in the 3rd extension of the file. - myfile.fits[3; images(exposure > 100)] - as above, but opens the image - in the first row that has an 'exposure' column value - greater than 100. -- - -**G. Image Section - -A virtual file containing a rectangular subsection of an image can be -extracted and opened by specifying the range of pixels (start:end) -along each axis to be extracted from the original image. One can also -specify an optional pixel increment (start:end:step) for each axis of -the input image. A pixel step = 1 will be assumed if it is not -specified. If the start pixel is larger then the end pixel, then the -image will be flipped (producing a mirror image) along that dimension. -An asterisk, '*', may be used to specify the entire range of an axis, -and '-*' will flip the entire axis. The input image can be in the -primary array, in an image extension, or contained in a vector cell of -a binary table. In the later 2 cases the extension name or number must -be specified before the image section specifier. - - Examples: -- - myfile.fits[1:512:2, 2:512:2] - open a 256x256 pixel image - consisting of the odd numbered columns (1st axis) and - the even numbered rows (2nd axis) of the image in the - primary array of the file. - - myfile.fits[*, 512:256] - open an image consisting of all the columns - in the input image, but only rows 256 through 512. - The image will be flipped along the 2nd axis since - the starting pixel is greater than the ending pixel. - - myfile.fits[*:2, 512:256:2] - same as above but keeping only - every other row and column in the input image. - - myfile.fits[-*, *] - copy the entire image, flipping it along - the first axis. - - myfile.fits[3][1:256,1:256] - opens a subsection of the image that - is in the 3rd extension of the file. - - myfile.fits[4; images(12)][1:10,1:10] - open an image consisting - of the first 10 pixels in both dimensions. The original - image resides in the 12th row of the 'images' vector - column in the table in the 4th extension of the file. -- - -When CFITSIO opens an image section it first creates a temporary file -containing the image section plus a copy of any other HDUs in the -file. (If a `\#' character is appended to the name or number of the -image HDU, as in "myfile.fits[1\#][1:200,1:200]", then the other -HDUs in the input file will not be copied into memory). -This temporary file is then opened by the application program, -so it is not possible to write to or modify the input file when -specifying an image section. Note that CFITSIO automatically updates -the world coordinate system keywords in the header of the image -section, if they exist, so that the coordinate associated with each -pixel in the image section will be computed correctly. - -**H. Image Transform Filters - -CFITSIO can apply a user-specified mathematical function to the value -of every pixel in a FITS image, thus creating a new virtual image -in computer memory that is then opened and read by the application -program. The original FITS image is not modified by this process. - -The image transformation specifier is appended to the input -FITS file name and is enclosed in square brackets. It begins with the -letters 'PIX' to distinguish it from other types of FITS file filters -that are recognized by CFITSIO. The image transforming function may -use any of the mathematical operators listed in the following -'Row Filtering Specification' section of this document. -Some examples of image transform filters are: -- - [pix X * 2.0] - multiply each pixel by 2.0 - [pix sqrt(X)] - take the square root of each pixel - [pix X + #ZEROPT - add the value of the ZEROPT keyword - [pix X>0 ? log10(X) : -99.] - if the pixel value is greater - than 0, compute the base 10 log, - else set the pixel = -99. -- -Use the letter 'X' in the expression to represent the current pixel value -in the image. The expression is evaluated -independently for each pixel in the image and may be a function of 1) the -original pixel value, 2) the value of other pixels in the image at -a given relative offset from the position of the pixel that is being -evaluated, and 3) the value of -any header keywords. Header keyword values are represented -by the name of the keyword preceded by the '\#' sign. - - -To access the the value of adjacent pixels in the image, -specify the (1-D) offset from the current pixel in curly brackets. -For example -- - [pix (x{-1} + x + x{+1}) / 3] -- -will replace each pixel value with the running mean of the values of that -pixel and it's 2 neighboring pixels. Note that in this notation the image -is treated as a 1-D array, where each row of the image (or higher dimensional -cube) is appended one after another in one long array of pixels. -It is possible to refer to pixels -in the rows above or below the current pixel by using the value of the -NAXIS1 header keyword. For example -- - [pix (x{-#NAXIS1} + x + x{#NAXIS1}) / 3] -- -will compute the mean of each image pixel and the pixels immediately -above and below it in the adjacent rows of the image. -The following more complex example -creates a smoothed virtual image where each pixel -is a 3 x 3 boxcar average of the input image pixels: -- - [pix (X + X{-1} + X{+1} - + X{-#NAXIS1} + X{-#NAXIS1 - 1} + X{-#NAXIS1 + 1} - + X{#NAXIS1} + X{#NAXIS1 - 1} + X{#NAXIS1 + 1}) / 9.] -- -If the pixel offset -extends beyond the first or last pixel in the image, the function will -evaluate to undefined, or NULL. - -For complex or commonly used image filtering operations, -one can write the expression into an external text file and -then import it into the -filter using the syntax '[pix @filename.txt]'. The mathematical -expression can -extend over multiple lines of text in the file. -Any lines in the external text file -that begin with 2 slash characters ('//') will be ignored and may be -used to add comments into the file. - -By default, the datatype of the resulting image will be the same as -the original image, but one may force a different datatype by appended -a code letter to the 'pix' keyword: -- - pixb - 8-bit byte image with BITPIX = 8 - pixi - 16-bit integer image with BITPIX = 16 - pixj - 32-bit integer image with BITPIX = 32 - pixr - 32-bit float image with BITPIX = -32 - pixd - 64-bit float image with BITPIX = -64 -- -Also by default, any other HDUs in the input file will be copied without -change to the -output virtual FITS file, but one may discard the other HDUs by adding -the number '1' to the 'pix' keyword (and following any optional datatype code -letter). For example: -- - myfile.fits[3][pixr1 sqrt(X)] -- -will create a virtual FITS file containing only a primary array image -with 32-bit floating point pixels that have a value equal to the square -root of the pixels in the image that is in the 3rd extension -of the 'myfile.fits' file. - - -**I. Column and Keyword Filtering Specification - -The optional column/keyword filtering specifier is used to modify the -column structure and/or the header keywords in the HDU that was -selected with the previous HDU location specifier. This filtering -specifier must be enclosed in square brackets and can be distinguished -from a general row filter specifier (described below) by the fact that -it begins with the string 'col ' and is not immediately followed by an -equals sign. The original file is not changed by this filtering -operation, and instead the modifications are made on a copy of the -input FITS file (usually in memory), which also contains a copy of all -the other HDUs in the file. (If a `\#' character is appended to the name -or number of the -table HDU then only the primary array, and none of the other -HDUs in the input file will be copied into memory). -This temporary file is passed to the -application program and will persist only until the file is closed or -until the program exits, unless the outfile specifier (see above) is -also supplied. - -The column/keyword filter can be used to perform the following -operations. More than one operation may be specified by separating -them with commas or semi-colons. - -\begin{itemize} - -\item -Copy only a specified list of columns columns to the filtered input file. -The list of column name should be separated by commas or semi-colons. Wild card -characters may be used in the column names to match multiple columns. -If the expression contains both a list of columns to be included and -columns to be deleted, then all the columns in the original table -except the explicitly deleted columns will appear in the filtered -table (i.e., there is no need to explicitly list the columns to -be included if any columns are being deleted). - -\item -Delete a column or keyword by listing the name preceded by a minus sign -or an exclamation mark (!), e.g., '-TIME' will delete the TIME column -if it exists, otherwise the TIME keyword. An error is returned if -neither a column nor keyword with this name exists. Note that the -exclamation point, '!', is a special UNIX character, so if it is used -on the command line rather than entered at a task prompt, it must be -preceded by a backslash to force the UNIX shell to ignore it. - -\item -Rename an existing column or keyword with the syntax 'NewName == -OldName'. An error is returned if neither a column nor keyword with -this name exists. - -\item -Append a new column or keyword to the table. To create a column, -give the new name, optionally followed by the data type in parentheses, -followed by a single equals sign and an expression to be used to -compute the value (e.g., 'newcol(1J) = 0' will create a new 32-bit -integer column called 'newcol' filled with zeros). The data type is -specified using the same syntax that is allowed for the value of the -FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for binary tables, -and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If the data type is -not specified then an appropriate data type will be chosen depending on -the form of the expression (may be a character string, logical, bit, long -integer, or double column). An appropriate vector count (in the case -of binary tables) will also be added if not explicitly specified. - -When creating a new keyword, the keyword name must be preceded by a -pound sign '\#', and the expression must evaluate to a scalar -(i.e., cannot have a column name in the expression). The comment -string for the keyword may be specified in parentheses immediately -following the keyword name (instead of supplying a data type as in -the case of creating a new column). If the keyword name ends with a -pound sign '\#', then cfitsio will substitute the number of the -most recently referenced column for the \# character . -This is especially useful when writing -a column-related keyword like TUNITn for a newly created column, -as shown in the following examples. - -COMMENT and HISTORY keywords may also be created with the following syntax: -- - #COMMENT = 'This is a comment keyword' - #HISTORY = 'This is a history keyword' -- -Note that the equal sign and the quote characters will be removed, so -that the resulting header keywords in these cases will look like this: -- - COMMENT This is a comment keyword - HISTORY This is a history keyword -- -These two special keywords are always appended to the end of the header -and will not affect any previously existing COMMENT or HISTORY keywords. - -\item -Recompute (overwrite) the values in an existing column or keyword by -giving the name followed by an equals sign and an arithmetic -expression. -\end{itemize} - -The expression that is used when appending or recomputing columns or -keywords can be arbitrarily complex and may be a function of other -header keyword values and other columns (in the same row). The full -syntax and available functions for the expression are described below -in the row filter specification section. - -If the expression contains both a list of columns to be included and -columns to be deleted, then all the columns in the original table -except the explicitly deleted columns will appear in the filtered -table. If no columns to be deleted are specified, then only the -columns that are explicitly listed will be included in the filtered -output table. To include all the columns, add the '*' wildcard -specifier at the end of the list, as shown in the examples. - -For complex or commonly used operations, one can place the -operations into an external text file and import it into the column -filter using the syntax '[col @filename.txt]'. The operations can -extend over multiple lines of the file, but multiple operations must -still be separated by commas or semi-colons. Any lines in the external text file -that begin with 2 slash characters ('//') will be ignored and may be -used to add comments into the file. - -Examples: -- - [col Time, rate] - only the Time and rate columns will - appear in the filtered input file. - - [col Time, *raw] - include the Time column and any other - columns whose name ends with 'raw'. - - [col -TIME, Good == STATUS] - deletes the TIME column and - renames the status column to 'Good' - - [col PI=PHA * 1.1 + 0.2; #TUNIT#(column units) = 'counts';*] - - creates new PI column from PHA values - and also writes the TUNITn keyword - for the new column. The final '*' - expression means preserve all the - columns in the input table in the - virtual output table; without the '*' - the output table would only contain - the single 'PI' column. - - [col rate = rate/exposure; TUNIT#(&) = 'counts/s';*] - - recomputes the rate column by dividing - it by the EXPOSURE keyword value. This - also modifies the value of the TUNITn - keyword for this column. The use of the - '&' character for the keyword comment - string means preserve the existing - comment string for that keyword. The - final '*' preserves all the columns - in the input table in the virtual - output table. -- - -**J. Row Filtering Specification - - When entering the name of a FITS table that is to be opened by a - program, an optional row filter may be specified to select a subset - of the rows in the table. A temporary new FITS file is created on - the fly which contains only those rows for which the row filter - expression evaluates to true. The primary array and any other - extensions in the input file are also copied to the temporary - file. -(If a `\#' character is appended to the name or number of the -table HDU then only the primary array, and none of the other -HDUs in the input file will be copied into the temporary file). - The original FITS file is closed and the new virtual file - is opened by the application program. The row filter expression is - enclosed in square brackets following the file name and extension - name (e.g., 'file.fits[events][GRADE==50]' selects only those rows - where the GRADE column value equals 50). When dealing with tables - where each row has an associated time and/or 2D spatial position, - the row filter expression can also be used to select rows based on - the times in a Good Time Intervals (GTI) extension, or on spatial - position as given in a SAO-style region file. - -***1. General Syntax - - The row filtering expression can be an arbitrarily complex series - of operations performed on constants, keyword values, and column - data taken from the specified FITS TABLE extension. The expression - must evaluate to a boolean value for each row of the table, where - a value of FALSE means that the row will be excluded. - - For complex or commonly used filters, one can place the expression - into a text file and import it into the row filter using the syntax - '[@filename.txt]'. The expression can be arbitrarily complex and - extend over multiple lines of the file. Any lines in the external - text file that begin with 2 slash characters ('//') will be ignored - and may be used to add comments into the file. - - Keyword and column data are referenced by name. Any string of - characters not surrounded by quotes (ie, a constant string) or - followed by an open parentheses (ie, a function name) will be - initially interpreted as a column name and its contents for the - current row inserted into the expression. If no such column exists, - a keyword of that name will be searched for and its value used, if - found. To force the name to be interpreted as a keyword (in case - there is both a column and keyword with the same name), precede the - keyword name with a single pound sign, '\#', as in '\#NAXIS2'. Due to - the generalities of FITS column and keyword names, if the column or - keyword name contains a space or a character which might appear as - an arithmetic term then enclose the name in '\$' characters as in - \$MAX PHA\$ or \#\$MAX-PHA\$. Names are case insensitive. - - To access a table entry in a row other than the current one, follow - the column's name with a row offset within curly braces. For - example, 'PHA\{-3\}' will evaluate to the value of column PHA, 3 rows - above the row currently being processed. One cannot specify an - absolute row number, only a relative offset. Rows that fall outside - the table will be treated as undefined, or NULLs. - - Boolean operators can be used in the expression in either their - Fortran or C forms. The following boolean operators are available: -- - "equal" .eq. .EQ. == "not equal" .ne. .NE. != - "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< - "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => - "or" .or. .OR. || "and" .and. .AND. && - "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ -- - -Note that the exclamation -point, '!', is a special UNIX character, so if it is used on the -command line rather than entered at a task prompt, it must be preceded -by a backslash to force the UNIX shell to ignore it. - - The expression may also include arithmetic operators and functions. - Trigonometric functions use radians, not degrees. The following - arithmetic operators and functions can be used in the expression - (function names are case insensitive). A null value will be returned - in case of illegal operations such as divide by zero, sqrt(negative) - log(negative), log10(negative), arccos(.gt. 1), arcsin(.gt. 1). - -- - "addition" + "subtraction" - - "multiplication" * "division" / - "negation" - "exponentiation" ** ^ - "absolute value" abs(x) "cosine" cos(x) - "sine" sin(x) "tangent" tan(x) - "arc cosine" arccos(x) "arc sine" arcsin(x) - "arc tangent" arctan(x) "arc tangent" arctan2(y,x) - "hyperbolic cos" cosh(x) "hyperbolic sin" sinh(x) - "hyperbolic tan" tanh(x) "round to nearest int" round(x) - "round down to int" floor(x) "round up to int" ceil(x) - "exponential" exp(x) "square root" sqrt(x) - "natural log" log(x) "common log" log10(x) - "modulus" x % y "random # [0.0,1.0)" random() - "random Gaussian" randomn() "random Poisson" randomp(x) - "minimum" min(x,y) "maximum" max(x,y) - "cumulative sum" accum(x) "sequential difference" seqdiff(x) - "if-then-else" b?x:y - "angular separation" angsep(ra1,dec1,ra2,de2) (all in degrees) - "substring" strmid(s,p,n) "string search" strstr(s,r) -- -Three different random number functions are provided: random(), with -no arguments, produces a uniform random deviate between 0 and 1; -randomn(), also with no arguments, produces a normal (Gaussian) random -deviate with zero mean and unit standard deviation; randomp(x) -produces a Poisson random deviate whose expected number of counts is -X. X may be any positive real number of expected counts, including -fractional values, but the return value is an integer. - -When the random functions are used in a vector expression, by default -the same random value will be used when evaluating each element of the vector. -If different random numbers are desired, then the name of a vector -column should be supplied as the single argument to the random -function (e.g., "flux + 0.1 * random(flux)", where "flux' is the -name of a vector column). This will create a vector of -random numbers that will be used in sequence when evaluating each -element of the vector expression. - -An alternate syntax for the min and max functions has only a single -argument which should be a vector value (see below). The result -will be the minimum/maximum element contained within the vector. - -The accum(x) function forms the cumulative sum of x, element by element. -Vector columns are supported simply by performing the summation process -through all the values. Null values are treated as 0. The seqdiff(x) -function forms the sequential difference of x, element by element. -The first value of seqdiff is the first value of x. A single null -value in x causes a pair of nulls in the output. The seqdiff and -accum functions are functional inverses, i.e., seqdiff(accum(x)) == x -as long as no null values are present. - -In the if-then-else expression, "b?x:y", b is an explicit boolean -value or expression. There is no automatic type conversion from -numeric to boolean values, so one needs to use "iVal!=0" instead of -merely "iVal" as the boolean argument. x and y can be any scalar data -type (including string). - -The angsep function computes the angular separation in degrees -between 2 celestial positions, where the first 2 parameters -give the RA-like and Dec-like coordinates (in decimal degrees) -of the first position, and the 3rd and 4th parameters give the -coordinates of the second position. - -The substring function strmid(S,P,N) extracts a substring from S, -starting at string position P, with a substring length N. The first -character position in S is labeled as 1. If P is 0, or refers to a -position beyond the end of S, then the extracted substring will be -NULL. S, P, and N may be functions of other columns. - -The string search function strstr(S,R) searches for the first occurrence -of the substring R in S. The result is an integer, indicating the -character position of the first match (where 1 is the first character -position of S). If no match is found, then strstr() returns a NULL -value. - -The following type casting operators are available, where the -inclosing parentheses are required and taken from the C language -usage. Also, the integer to real casts values to double precision: -- - "real to integer" (int) x (INT) x - "integer to real" (float) i (FLOAT) i -- - - In addition, several constants are built in for use in numerical - expressions: - -- - #pi 3.1415... #e 2.7182... - #deg #pi/180 #row current row number - #null undefined value #snull undefined string -- - - A string constant must be enclosed in quotes as in 'Crab'. The - "null" constants are useful for conditionally setting table values - to a NULL, or undefined, value (eg., "col1==-99 ? \#NULL : col1"). - - There is also a function for testing if two values are close to - each other, i.e., if they are "near" each other to within a user - specified tolerance. The arguments, value\_1 and value\_2 can be - integer or real and represent the two values who's proximity is - being tested to be within the specified tolerance, also an integer - or real: -- - near(value_1, value_2, tolerance) -- - When a NULL, or undefined, value is encountered in the FITS table, - the expression will evaluate to NULL unless the undefined value is - not actually required for evaluation, e.g. "TRUE .or. NULL" - evaluates to TRUE. The following two functions allow some NULL - detection and handling: -- - "a null value?" ISNULL(x) - "define a value for null" DEFNULL(x,y) -- - The former - returns a boolean value of TRUE if the argument x is NULL. The - later "defines" a value to be substituted for NULL values; it - returns the value of x if x is not NULL, otherwise it returns the - value of y. - - - -***2. Bit Masks - - Bit masks can be used to select out rows from bit columns (TFORMn = - \#X) in FITS files. To represent the mask, binary, octal, and hex - formats are allowed: - -- - binary: b0110xx1010000101xxxx0001 - octal: o720x1 -> (b111010000xxx001) - hex: h0FxD -> (b00001111xxxx1101) -- - - In all the representations, an x or X is allowed in the mask as a - wild card. Note that the x represents a different number of wild - card bits in each representation. All representations are case - insensitive. - - To construct the boolean expression using the mask as the boolean - equal operator described above on a bit table column. For example, - if you had a 7 bit column named flags in a FITS table and wanted - all rows having the bit pattern 0010011, the selection expression - would be: - -- - flags == b0010011 - or - flags .eq. b10011 -- - - It is also possible to test if a range of bits is less than, less - than equal, greater than and greater than equal to a particular - boolean value: - -- - flags <= bxxx010xx - flags .gt. bxxx100xx - flags .le. b1xxxxxxx -- - - Notice the use of the x bit value to limit the range of bits being - compared. - - It is not necessary to specify the leading (most significant) zero - (0) bits in the mask, as shown in the second expression above. - - Bit wise AND, OR and NOT operations are also possible on two or - more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) - operators. All of these operators result in a bit field which can - then be used with the equal operator. For example: - -- - (!flags) == b1101100 - (flags & b1000001) == bx000001 -- - - Bit fields can be appended as well using the '+' operator. Strings - can be concatenated this way, too. - -***3. Vector Columns - - Vector columns can also be used in building the expression. No - special syntax is required if one wants to operate on all elements - of the vector. Simply use the column name as for a scalar column. - Vector columns can be freely intermixed with scalar columns or - constants in virtually all expressions. The result will be of the - same dimension as the vector. Two vectors in an expression, though, - need to have the same number of elements and have the same - dimensions. - - Arithmetic and logical operations are all performed on an element by - element basis. Comparing two vector columns, eg "COL1 == COL2", - thus results in another vector of boolean values indicating which - elements of the two vectors are equal. - - Eight functions are available that operate on a vector and return a - scalar result: -- - "minimum" MIN(V) "maximum" MAX(V) - "average" AVERAGE(V) "median" MEDIAN(V) - "summation" SUM(V) "standard deviation" STDDEV(V) - "# of values" NELEM(V) "# of non-null values" NVALID(V) -- - where V represents the name of a vector column or a manually - constructed vector using curly brackets as described below. The - first 6 of these functions ignore any null values in the vector when - computing the result. The STDDEV() function computes the sample - standard deviation, i.e. it is proportional to 1/SQRT(N-1) instead - of 1/SQRT(N), where N is NVALID(V). - - The SUM function literally sums all the elements in x, returning a - scalar value. If V is a boolean vector, SUM returns the number - of TRUE elements. The NELEM function returns the number of elements - in vector V whereas NVALID return the number of non-null elements in - the vector. (NELEM also operates on bit and string columns, - returning their column widths.) As an example, to test whether all - elements of two vectors satisfy a given logical comparison, one can - use the expression -- - SUM( COL1 > COL2 ) == NELEM( COL1 ) -- - - which will return TRUE if all elements of COL1 are greater than - their corresponding elements in COL2. - - To specify a single element of a vector, give the column name - followed by a comma-separated list of coordinates enclosed in - square brackets. For example, if a vector column named PHAS exists - in the table as a one dimensional, 256 component list of numbers - from which you wanted to select the 57th component for use in the - expression, then PHAS[57] would do the trick. Higher dimensional - arrays of data may appear in a column. But in order to interpret - them, the TDIMn keyword must appear in the header. Assuming that a - (4,4,4,4) array is packed into each row of a column named ARRAY4D, - the (1,2,3,4) component element of each row is accessed by - ARRAY4D[1,2,3,4]. Arrays up to dimension 5 are currently - supported. Each vector index can itself be an expression, although - it must evaluate to an integer value within the bounds of the - vector. Vector columns which contain spaces or arithmetic operators - must have their names enclosed in "\$" characters as with - \$ARRAY-4D\$[1,2,3,4]. - - A more C-like syntax for specifying vector indices is also - available. The element used in the preceding example alternatively - could be specified with the syntax ARRAY4D[4][3][2][1]. Note the - reverse order of indices (as in C), as well as the fact that the - values are still ones-based (as in Fortran -- adopted to avoid - ambiguity for 1D vectors). With this syntax, one does not need to - specify all of the indices. To extract a 3D slice of this 4D - array, use ARRAY4D[4]. - - Variable-length vector columns are not supported. - - Vectors can be manually constructed within the expression using a - comma-separated list of elements surrounded by curly braces ('\{\}'). - For example, '\{1,3,6,1\}' is a 4-element vector containing the values - 1, 3, 6, and 1. The vector can contain only boolean, integer, and - real values (or expressions). The elements will be promoted to the - highest data type present. Any elements which are themselves - vectors, will be expanded out with each of its elements becoming an - element in the constructed vector. - -***4. Good Time Interval Filtering - - A common filtering method involves selecting rows which have a time - value which lies within what is called a Good Time Interval or GTI. - The time intervals are defined in a separate FITS table extension - which contains 2 columns giving the start and stop time of each - good interval. The filtering operation accepts only those rows of - the input table which have an associated time which falls within - one of the time intervals defined in the GTI extension. A high - level function, gtifilter(a,b,c,d), is available which evaluates - each row of the input table and returns TRUE or FALSE depending - whether the row is inside or outside the good time interval. The - syntax is -- - gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) - or - gtifilter( [ 'gtifile' [, expr [, 'STARTCOL', 'STOPCOL' ] ] ] ) -- - where each "[]" demarks optional parameters. Note that the quotes - around the gtifile and START/STOP column are required. Either single - or double quotes may be used. In cases where this expression is - entered on the Unix command line, enclose the entire expression in - double quotes, and then use single quotes within the expression to - enclose the 'gtifile' and other terms. It is also usually possible - to do the reverse, and enclose the whole expression in single quotes - and then use double quotes within the expression. The gtifile, - if specified, can be blank ("") which will mean to use the first - extension with the name "*GTI*" in the current file, a plain - extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be - used to select an extension in the current file, or a regular - filename with or without an extension specifier which in the latter - case will mean to use the first extension with an extension name - "*GTI*". Expr can be any arithmetic expression, including simply - the time column name. A vector time expression will produce a - vector boolean result. STARTCOL and STOPCOL are the names of the - START/STOP columns in the GTI extension. If one of them is - specified, they both must be. - - In its simplest form, no parameters need to be provided -- default - values will be used. The expression "gtifilter()" is equivalent to -- - gtifilter( "", TIME, "*START*", "*STOP*" ) -- - This will search the current file for a GTI extension, filter the - TIME column in the current table, using START/STOP times taken from - columns in the GTI extension with names containing the strings - "START" and "STOP". The wildcards ('*') allow slight variations in - naming conventions such as "TSTART" or "STARTTIME". The same - default values apply for unspecified parameters when the first one - or two parameters are specified. The function automatically - searches for TIMEZERO/I/F keywords in the current and GTI - extensions, applying a relative time offset, if necessary. - -***5. Spatial Region Filtering - - Another common filtering method selects rows based on whether the - spatial position associated with each row is located within a given - 2-dimensional region. The syntax for this high-level filter is -- - regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) -- - where each "[]" demarks optional parameters. The region file name - is required and must be enclosed in quotes. The remaining - parameters are optional. There are 2 supported formats for the - region file: ASCII file or FITS binary table. The region file - contains a list of one or more geometric shapes (circle, - ellipse, box, etc.) which defines a region on the celestial sphere - or an area within a particular 2D image. The region file is - typically generated using an image display program such as fv/POW - (distribute by the HEASARC), or ds9 (distributed by the Smithsonian - Astrophysical Observatory). Users should refer to the documentation - provided with these programs for more details on the syntax used in - the region files. The FITS region file format is defined in a document - available from the FITS Support Office at - http://fits.gsfc.nasa.gov/ registry/ region.html - - In its simplest form, (e.g., regfilter("region.reg") ) the - coordinates in the default 'X' and 'Y' columns will be used to - determine if each row is inside or outside the area specified in - the region file. Alternate position column names, or expressions, - may be entered if needed, as in -- - regfilter("region.reg", XPOS, YPOS) -- - Region filtering can be applied most unambiguously if the positions - in the region file and in the table to be filtered are both give in - terms of absolute celestial coordinate units. In this case the - locations and sizes of the geometric shapes in the region file are - specified in angular units on the sky (e.g., positions given in - R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, - each row of the filtered table will have a celestial coordinate - associated with it. This association is usually implemented using - a set of so-called 'World Coordinate System' (or WCS) FITS keywords - that define the coordinate transformation that must be applied to - the values in the 'X' and 'Y' columns to calculate the coordinate. - - Alternatively, one can perform spatial filtering using unitless - 'pixel' coordinates for the regions and row positions. In this - case the user must be careful to ensure that the positions in the 2 - files are self-consistent. A typical problem is that the region - file may be generated using a binned image, but the unbinned - coordinates are given in the event table. The ROSAT events files, - for example, have X and Y pixel coordinates that range from 1 - - 15360. These coordinates are typically binned by a factor of 32 to - produce a 480x480 pixel image. If one then uses a region file - generated from this image (in image pixel units) to filter the - ROSAT events file, then the X and Y column values must be converted - to corresponding pixel units as in: -- - regfilter("rosat.reg", X/32.+.5, Y/32.+.5) -- - Note that this binning conversion is not necessary if the region - file is specified using celestial coordinate units instead of pixel - units because CFITSIO is then able to directly compare the - celestial coordinate of each row in the table with the celestial - coordinates in the region file without having to know anything - about how the image may have been binned. - - The last "wcs cols" parameter should rarely be needed. If supplied, - this string contains the names of the 2 columns (space or comma - separated) which have the associated WCS keywords. If not supplied, - the filter will scan the X and Y expressions for column names. - If only one is found in each expression, those columns will be - used, otherwise an error will be returned. - - These region shapes are supported (names are case insensitive): -- - Point ( X1, Y1 ) <- One pixel square region - Line ( X1, Y1, X2, Y2 ) <- One pixel wide region - Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with - Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered - Box ( Xc, Yc, Wdth, Hght, A ) V within the region - Diamond ( Xc, Yc, Wdth, Hght, A ) - Circle ( Xc, Yc, R ) - Annulus ( Xc, Yc, Rin, Rout ) - Ellipse ( Xc, Yc, Rx, Ry, A ) - Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) - Sector ( Xc, Yc, Amin, Amax ) -- - where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are - the coordinates of the shape's edges; Rxxx are the shapes' various - Radii or semimajor/minor axes; and Axxx are the angles of rotation - (or bounding angles for Sector) in degrees. For rotated shapes, the - rotation angle can be left off, indicating no rotation. Common - alternate names for the regions can also be used: rotbox = box; - rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie - = sector. When a shape's name is preceded by a minus sign, '-', - the defined region is instead the area *outside* its boundary (ie, - the region is inverted). All the shapes within a single region - file are OR'd together to create the region, and the order is - significant. The overall way of looking at region files is that if - the first region is an excluded region then a dummy included region - of the whole detector is inserted in the front. Then each region - specification as it is processed overrides any selections inside of - that region specified by previous regions. Another way of thinking - about this is that if a previous excluded region is completely - inside of a subsequent included region the excluded region is - ignored. - - The positional coordinates may be given either in pixel units, - decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes - may be given in pixels, degrees, arcminutes, or arcseconds. Look - at examples of region file produced by fv/POW or ds9 for further - details of the region file format. - - There are three low-level functions that are primarily for use with - regfilter function, but they can be called directly. They - return a boolean true or false depending on whether a two - dimensional point is in the region or not. The positional coordinates - must be given in pixel units: -- - "point in a circular region" - circle(xcntr,ycntr,radius,Xcolumn,Ycolumn) - - "point in an elliptical region" - ellipse(xcntr,ycntr,xhlf_wdth,yhlf_wdth,rotation,Xcolumn,Ycolumn) - - "point in a rectangular region" - box(xcntr,ycntr,xfll_wdth,yfll_wdth,rotation,Xcolumn,Ycolumn) - - where - (xcntr,ycntr) are the (x,y) position of the center of the region - (xhlf_wdth,yhlf_wdth) are the (x,y) half widths of the region - (xfll_wdth,yfll_wdth) are the (x,y) full widths of the region - (radius) is half the diameter of the circle - (rotation) is the angle(degrees) that the region is rotated with - respect to (xcntr,ycntr) - (Xcoord,Ycoord) are the (x,y) coordinates to test, usually column - names - NOTE: each parameter can itself be an expression, not merely a - column name or constant. -- - -***5. Example Row Filters -- - [ binary && mag <= 5.0] - Extract all binary stars brighter - than fifth magnitude (note that - the initial space is necessary to - prevent it from being treated as a - binning specification) - - [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 - - [IMAGE[4,5] .gt. 100] - Extract all rows that have the - (4,5) component of the IMAGE column - greater than 100 - - [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the - absolute value of the sine of theta - less than a half where the angles - are tabulated in degrees - - [SUM( SPEC > 3*BACKGRND )>=1] - Extract all rows containing a - spectrum, held in vector column - SPEC, with at least one value 3 - times greater than the background - level held in a keyword, BACKGRND - - [VCOL=={1,4,2}] - Extract all rows whose vector column - VCOL contains the 3-elements 1, 4, and - 2. - - [@rowFilter.txt] - Extract rows using the expression - contained within the text file - rowFilter.txt - - [gtifilter()] - Search the current file for a GTI - extension, filter the TIME - column in the current table, using - START/STOP times taken from - columns in the GTI extension - - [regfilter("pow.reg")] - Extract rows which have a coordinate - (as given in the X and Y columns) - within the spatial region specified - in the pow.reg region file. - - [regfilter("pow.reg", Xs, Ys)] - Same as above, except that the - Xs and Ys columns will be used to - determine the coordinate of each - row in the table. -- - -**J. Binning or Histogramming Specification - -The optional binning specifier is enclosed in square brackets and can -be distinguished from a general row filter specification by the fact -that it begins with the keyword 'bin' not immediately followed by an -equals sign. When binning is specified, a temporary N-dimensional FITS -primary array is created by computing the histogram of the values in -the specified columns of a FITS table extension. After the histogram -is computed the input FITS file containing the table is then closed and -the temporary FITS primary array is opened and passed to the -application program. Thus, the application program never sees the -original FITS table and only sees the image in the new temporary file -(which has no additional extensions). Obviously, the application -program must be expecting to open a FITS image and not a FITS table in -this case. - -The data type of the FITS histogram image may be specified by appending -'b' (for 8-bit byte), 'i' (for 16-bit integers), 'j' (for 32-bit -integer), 'r' (for 32-bit floating points), or 'd' (for 64-bit double -precision floating point) to the 'bin' keyword (e.g. '[binr X]' -creates a real floating point image). If the data type is not -explicitly specified then a 32-bit integer image will be created by -default, unless the weighting option is also specified in which case -the image will have a 32-bit floating point data type by default. - -The histogram image may have from 1 to 4 dimensions (axes), depending -on the number of columns that are specified. The general form of the -binning specification is: -- - [bin{bijrd} Xcol=min:max:binsize, Ycol= ..., Zcol=..., Tcol=...; weight] -- -in which up to 4 columns, each corresponding to an axis of the image, -are listed. The column names are case insensitive, and the column -number may be given instead of the name, preceded by a pound sign -(e.g., [bin \#4=1:512]). If the column name is not specified, then -CFITSIO will first try to use the 'preferred column' as specified by -the CPREF keyword if it exists (e.g., 'CPREF = 'DETX,DETY'), otherwise -column names 'X', 'Y', 'Z', and 'T' will be assumed for each of the 4 -axes, respectively. In cases where the column name could be confused -with an arithmetic expression, enclose the column name in parentheses to -force the name to be interpreted literally. - -Each column name may be followed by an equals sign and then the lower -and upper range of the histogram, and the size of the histogram bins, -separated by colons. Spaces are allowed before and after the equals -sign but not within the 'min:max:binsize' string. The min, max and -binsize values may be integer or floating point numbers, or they may be -the names of keywords in the header of the table. If the latter, then -the value of that keyword is substituted into the expression. - -Default values for the min, max and binsize quantities will be -used if not explicitly given in the binning expression as shown -in these examples: -- - [bin x = :512:2] - use default minimum value - [bin x = 1::2] - use default maximum value - [bin x = 1:512] - use default bin size - [bin x = 1:] - use default maximum value and bin size - [bin x = :512] - use default minimum value and bin size - [bin x = 2] - use default minimum and maximum values - [bin x] - use default minimum, maximum and bin size - [bin 4] - default 2-D image, bin size = 4 in both axes - [bin] - default 2-D image -- -CFITSIO will use the value of the TLMINn, TLMAXn, and TDBINn keywords, -if they exist, for the default min, max, and binsize, respectively. If -they do not exist then CFITSIO will use the actual minimum and maximum -values in the column for the histogram min and max values. The default -binsize will be set to 1, or (max - min) / 10., whichever is smaller, -so that the histogram will have at least 10 bins along each axis. - -A shortcut notation is allowed if all the columns/axes have the same -binning specification. In this case all the column names may be listed -within parentheses, followed by the (single) binning specification, as -in: -- - [bin (X,Y)=1:512:2] - [bin (X,Y) = 5] -- - -The optional weighting factor is the last item in the binning specifier -and, if present, is separated from the list of columns by a -semi-colon. As the histogram is accumulated, this weight is used to -incremented the value of the appropriated bin in the histogram. If the -weighting factor is not specified, then the default weight = 1 is -assumed. The weighting factor may be a constant integer or floating -point number, or the name of a keyword containing the weighting value. -Or the weighting factor may be the name of a table column in which case -the value in that column, on a row by row basis, will be used. - -In some cases, the column or keyword may give the reciprocal of the -actual weight value that is needed. In this case, precede the weight -keyword or column name by a slash '/' to tell CFITSIO to use the -reciprocal of the value when constructing the histogram. - -For complex or commonly used histograms, one can also place its -description into a text file and import it into the binning -specification using the syntax [bin @filename.txt]. The file's -contents can extend over multiple lines, although it must still -conform to the no-spaces rule for the min:max:binsize syntax and each -axis specification must still be comma-separated. Any lines in the -external text file that begin with 2 slash characters ('//') will be -ignored and may be used to add comments into the file. - - Examples: - -- - [bini detx, dety] - 2-D, 16-bit integer histogram - of DETX and DETY columns, using - default values for the histogram - range and binsize - - [bin (detx, dety)=16; /exposure] - 2-D, 32-bit real histogram of DETX - and DETY columns with a bin size = 16 - in both axes. The histogram values - are divided by the EXPOSURE keyword - value. - - [bin time=TSTART:TSTOP:0.1] - 1-D lightcurve, range determined by - the TSTART and TSTOP keywords, - with 0.1 unit size bins. - - [bin pha, time=8000.:8100.:0.1] - 2-D image using default binning - of the PHA column for the X axis, - and 1000 bins in the range - 8000. to 8100. for the Y axis. - - [bin @binFilter.txt] - Use the contents of the text file - binFilter.txt for the binning - specifications. - -- -*X. Template Files - -When a new FITS file is created with a call to fits\_create\_file, the -name of a template file may be supplied in parentheses immediately -following the name of the new file to be created. This template is -used to define the structure of one or more HDUs in the new file. The -template file may be another FITS file, in which case the newly created -file will have exactly the same keywords in each HDU as in the template -FITS file, but all the data units will be filled with zeros. The -template file may also be an ASCII text file, where each line (in -general) describes one FITS keyword record. The format of the ASCII -template file is described in the following sections. - -**A Detailed Template Line Format - -The format of each ASCII template line closely follows the format of a -FITS keyword record: -- - KEYWORD = KEYVALUE / COMMENT -- -except that free format may be used (e.g., the equals sign may appear -at any position in the line) and TAB characters are allowed and are -treated the same as space characters. The KEYVALUE and COMMENT fields -are optional. The equals sign character is also optional, but it is -recommended that it be included for clarity. Any template line that -begins with the pound '\#' character is ignored by the template parser -and may be use to insert comments into the template file itself. - -The KEYWORD name field is limited to 8 characters in length and only -the letters A-Z, digits 0-9, and the hyphen and underscore characters -may be used, without any embedded spaces. Lowercase letters in the -template keyword name will be converted to uppercase. Leading spaces -in the template line preceding the keyword name are generally ignored, -except if the first 8 characters of a template line are all blank, then -the entire line is treated as a FITS comment keyword (with a blank -keyword name) and is copied verbatim into the FITS header. - -The KEYVALUE field may have any allowed FITS data type: character -string, logical, integer, real, complex integer, or complex real. Integer -values must be within the allowed range of a 'signed long' variable; -some C compilers only suppport 4-byte long integers with a range -from -2147483648 to +2147483647, whereas other C compilers support 8-byte -integers with a range of plus or minus 2**63. - -The character string values need not be enclosed in single quote characters -unless they are necessary to distinguish the string from a different -data type (e.g. 2.0 is a real but '2.0' is a string). The keyword has -an undefined (null) value if the template record only contains blanks -following the "=" or between the "=" and the "/" comment field -delimiter. - -String keyword values longer than 68 characters (the maximum length -that will fit in a single FITS keyword record) are permitted using the -CFITSIO long string convention. They can either be specified as a -single long line in the template, or by using multiple lines where the -continuing lines contain the 'CONTINUE' keyword, as in this example: -- - LONGKEY = 'This is a long string value that is contin&' - CONTINUE 'ued over 2 records' / comment field goes here -- -The format of template lines with CONTINUE keyword is very strict: 3 -spaces must follow CONTINUE and the rest of the line is copied verbatim -to the FITS file. - -The start of the optional COMMENT field must be preceded by "/", which -is used to separate it from the keyword value field. Exceptions are if -the KEYWORD name field contains COMMENT, HISTORY, CONTINUE, or if the -first 8 characters of the template line are blanks. - -More than one Header-Data Unit (HDU) may be defined in the template -file. The start of an HDU definition is denoted with a SIMPLE or -XTENSION template line: - -1) SIMPLE begins a Primary HDU definition. SIMPLE may only appear as -the first keyword in the template file. If the template file begins -with XTENSION instead of SIMPLE, then a default empty Primary HDU is -created, and the template is then assumed to define the keywords -starting with the first extension following the Primary HDU. - -2) XTENSION marks the beginning of a new extension HDU definition. The -previous HDU will be closed at this point and processing of the next -extension begins. - -**B Auto-indexing of Keywords - -If a template keyword name ends with a "\#" character, it is said to be -'auto-indexed'. Each "\#" character will be replaced by the current -integer index value, which gets reset = 1 at the start of each new HDU -in the file (or 7 in the special case of a GROUP definition). The -FIRST indexed keyword in each template HDU definition is used as the -'incrementor'; each subsequent occurrence of this SAME keyword will -cause the index value to be incremented. This behavior can be rather -subtle, as illustrated in the following examples in which the TTYPE -keyword is the incrementor in both cases: -- - TTYPE# = TIME - TFORM# = 1D - TTYPE# = RATE - TFORM# = 1E -- -will create TTYPE1, TFORM1, TTYPE2, and TFORM2 keywords. But if the -template looks like, -- - TTYPE# = TIME - TTYPE# = RATE - TFORM# = 1D - TFORM# = 1E -- -this results in a FITS files with TTYPE1, TTYPE2, TFORM2, and TFORM2, -which is probably not what was intended! - -**C Template Parser Directives - -In addition to the template lines which define individual keywords, the -template parser recognizes 3 special directives which are each preceded -by the backslash character: \verb+ \include, \group+, and \verb+ \end+. - -The 'include' directive must be followed by a filename. It forces the -parser to temporarily stop reading the current template file and begin -reading the include file. Once the parser reaches the end of the -include file it continues parsing the current template file. Include -files can be nested, and HDU definitions can span multiple template -files. - -The start of a GROUP definition is denoted with the 'group' directive, -and the end of a GROUP definition is denoted with the 'end' directive. -Each GROUP contains 0 or more member blocks (HDUs or GROUPs). Member -blocks of type GROUP can contain their own member blocks. The GROUP -definition itself occupies one FITS file HDU of special type (GROUP -HDU), so if a template specifies 1 group with 1 member HDU like: -- -\group -grpdescr = 'demo' -xtension bintable -# this bintable has 0 cols, 0 rows -\end -- -then the parser creates a FITS file with 3 HDUs : -- -1) dummy PHDU -2) GROUP HDU (has 1 member, which is bintable in HDU number 3) -3) bintable (member of GROUP in HDU number 2) -- -Technically speaking, the GROUP HDU is a BINTABLE with 6 columns. Applications -can define additional columns in a GROUP HDU using TFORMn and TTYPEn -(where n is 7, 8, ....) keywords or their auto-indexing equivalents. - -For a more complicated example of a template file using the group directives, -look at the sample.tpl file that is included in the CFITSIO distribution. - -**D Formal Template Syntax - -The template syntax can formally be defined as follows: -- - TEMPLATE = BLOCK [ BLOCK ... ] - - BLOCK = { HDU | GROUP } - - GROUP = \GROUP [ BLOCK ... ] \END - - HDU = XTENSION [ LINE ... ] { XTENSION | \GROUP | \END | EOF } - - LINE = [ KEYWORD [ = ] ] [ VALUE ] [ / COMMENT ] - - X ... - X can be present 1 or more times - { X | Y } - X or Y - [ X ] - X is optional -- - -At the topmost level, the template defines 1 or more template blocks. Blocks -can be either HDU (Header Data Unit) or a GROUP. For each block the parser -creates 1 (or more for GROUPs) FITS file HDUs. - - -**E Errors - -In general the fits\_execute\_template() function tries to be as atomic -as possible, so either everything is done or nothing is done. If an -error occurs during parsing of the template, fits\_execute\_template() -will (try to) delete the top level BLOCK (with all its children if any) -in which the error occurred, then it will stop reading the template file -and it will return with an error. - -**F Examples - -1. This template file will create a 200 x 300 pixel image, with 4-byte -integer pixel values, in the primary HDU: -- - SIMPLE = T - BITPIX = 32 - NAXIS = 2 / number of dimensions - NAXIS1 = 100 / length of first axis - NAXIS2 = 200 / length of second axis - OBJECT = NGC 253 / name of observed object -- -The allowed values of BITPIX are 8, 16, 32, -32, or -64, -representing, respectively, 8-bit integer, 16-bit integer, 32-bit -integer, 32-bit floating point, or 64 bit floating point pixels. - -2. To create a FITS table, the template first needs to include -XTENSION = TABLE or BINTABLE to define whether it is an ASCII or binary -table, and NAXIS2 to define the number of rows in the table. Two -template lines are then needed to define the name (TTYPEn) and FITS data -format (TFORMn) of the columns, as in this example: -- - xtension = bintable - naxis2 = 40 - ttype# = Name - tform# = 10a - ttype# = Npoints - tform# = j - ttype# = Rate - tunit# = counts/s - tform# = e -- -The above example defines a null primary array followed by a 40-row -binary table extension with 3 columns called 'Name', 'Npoints', and -'Rate', with data formats of '10A' (ASCII character string), '1J' -(integer) and '1E' (floating point), respectively. Note that the other -required FITS keywords (BITPIX, NAXIS, NAXIS1, PCOUNT, GCOUNT, TFIELDS, -and END) do not need to be explicitly defined in the template because -their values can be inferred from the other keywords in the template. -This example also illustrates that the templates are generally -case-insensitive (the keyword names and TFORMn values are converted to -upper-case in the FITS file) and that string keyword values generally -do not need to be enclosed in quotes. - -*XI. Local FITS Conventions - -CFITSIO supports several local FITS conventions which are not -defined in the official FITS standard and which are not -necessarily recognized or supported by other FITS software packages. -Programmers should be cautious about using these features, especially -if the FITS files that are produced are expected to be processed by -other software systems which do not use the CFITSIO interface. - -**A. 64-Bit Long Integers - -CFITSIO supports reading and writing FITS images or table columns containing -64-bit integer data values. Support for 64-bit integers was added to the -official FITS Standard in December 2005. - FITS 64-bit images have BITPIX = -64, and the 64-bit binary table columns have TFORMn = 'K'. CFITSIO also -supports the 'Q' variable-length array table column format which is -analogous to the 'P' column format except that the array descriptor -is stored as a pair of 64-bit integers. - -For the convenience of C programmers, the fitsio.h include file -defines (with a typedef statement) the 'LONGLONG' datatype to be -equivalent to an appropriate 64-bit integer datatype on each platform. -Since there is currently no universal standard -for the name of the 64-bit integer datatype (it might be defined as -'long long', 'long', or '\_\_int64' depending on the platform) -C programmers may prefer to use the 'LONGLONG' datatype when -declaring or allocating 64-bit integer quantities when writing -code which needs to run on multiple platforms. -Note that CFITSIO will implicitly convert the datatype when reading -or writing FITS 64-bit integer images and columns with data arrays of -a different integer or floating point datatype, but there is an -increased risk of loss of numerical precision or -numerical overflow in this case. - -**B. Long String Keyword Values. - -The length of a standard FITS string keyword is limited to 68 -characters because it must fit entirely within a single FITS header -keyword record. In some instances it is necessary to encode strings -longer than this limit, so CFITSIO supports a local convention in which -the string value is continued over multiple keywords. This -continuation convention uses an ampersand character at the end of each -substring to indicate that it is continued on the next keyword, and the -continuation keywords all have the name CONTINUE without an equal sign -in column 9. The string value may be continued in this way over as many -additional CONTINUE keywords as is required. The following lines -illustrate this continuation convention which is used in the value of -the STRKEY keyword: -- -LONGSTRN= 'OGIP 1.0' / The OGIP Long String Convention may be used. -STRKEY = 'This is a very long string keyword&' / Optional Comment -CONTINUE ' value that is continued over 3 keywords in the & ' -CONTINUE 'FITS header.' / This is another optional comment. -- -It is recommended that the LONGSTRN keyword, as shown here, always be -included in any HDU that uses this longstring convention as a warning -to any software that must read the keywords. A routine called fits\_write\_key\_longwarn -has been provided in CFITSIO to write this keyword if it does not -already exist. - -This long string convention is supported by the following CFITSIO -routines: -- - fits_write_key_longstr - write a long string keyword value - fits_insert_key_longstr - insert a long string keyword value - fits_modify_key_longstr - modify a long string keyword value - fits_update_key_longstr - modify a long string keyword value - fits_read_key_longstr - read a long string keyword value - fits_delete_key - delete a keyword -- -The fits\_read\_key\_longstr routine is unique among all the CFITSIO -routines in that it internally allocates memory for the long string -value; all the other CFITSIO routines that deal with arrays require -that the calling program pre-allocate adequate space to hold the array -of data. Consequently, programs which use the fits\_read\_key\_longstr -routine must be careful to free the allocated memory for the string -when it is no longer needed. - -The following 2 routines also have limited support for this long string -convention, -- - fits_modify_key_str - modify an existing string keyword value - fits_update_key_str - update a string keyword value -- -in that they will correctly overwrite an existing long string value, -but the new string value is limited to a maximum of 68 characters in -length. - -The more commonly used CFITSIO routines to write string valued keywords -(fits\_update\_key and fits\_write\_key) do not support this long -string convention and only support strings up to 68 characters in -length. This has been done deliberately to prevent programs from -inadvertently writing keywords using this non-standard convention -without the explicit intent of the programmer or user. The -fits\_write\_key\_longstr routine must be called instead to write long -strings. This routine can also be used to write ordinary string values -less than 68 characters in length. - -**C. Arrays of Fixed-Length Strings in Binary Tables - -CFITSIO supports 2 ways to specify that a character column in a binary -table contains an array of fixed-length strings. The first way, which -is officially supported by the FITS Standard document, uses the TDIMn keyword. -For example, if TFORMn = '60A' and TDIMn = '(12,5)' then that -column will be interpreted as containing an array of 5 strings, each 12 -characters long. - -CFITSIO also supports a -local convention for the format of the TFORMn keyword value of the form -'rAw' where 'r' is an integer specifying the total width in characters -of the column, and 'w' is an integer specifying the (fixed) length of -an individual unit string within the vector. For example, TFORM1 = -'120A10' would indicate that the binary table column is 120 characters -wide and consists of 12 10-character length strings. This convention -is recognized by the CFITSIO routines that read or write strings in -binary tables. The Binary Table definition document specifies that -other optional characters may follow the data type code in the TFORM -keyword, so this local convention is in compliance with the -FITS standard although other FITS readers may not -recognize this convention. - - -**D. Keyword Units Strings - -One limitation of the current FITS Standard is that it does not define -a specific convention for recording the physical units of a keyword -value. The TUNITn keyword can be used to specify the physical units of -the values in a table column, but there is no analogous convention for -keyword values. The comment field of the keyword is often used for -this purpose, but the units are usually not specified in a well defined -format that FITS readers can easily recognize and extract. - -To solve this problem, CFITSIO uses a local convention in which the -keyword units are enclosed in square brackets as the first token in the -keyword comment field; more specifically, the opening square bracket -immediately follows the slash '/' comment field delimiter and a single -space character. The following examples illustrate keywords that use -this convention: - -- -EXPOSURE= 1800.0 / [s] elapsed exposure time -V_HELIO = 16.23 / [km s**(-1)] heliocentric velocity -LAMBDA = 5400. / [angstrom] central wavelength -FLUX = 4.9033487787637465E-30 / [J/cm**2/s] average flux -- - -In general, the units named in the IAU(1988) Style Guide are -recommended, with the main exception that the preferred unit for angle -is 'deg' for degrees. - -The fits\_read\_key\_unit and fits\_write\_key\_unit routines in -CFITSIO read and write, respectively, the keyword unit strings in an -existing keyword. - -**E. HIERARCH Convention for Extended Keyword Names - -CFITSIO supports the HIERARCH keyword convention which allows keyword -names that are longer then 8 characters and may contain the full range -of printable ASCII text characters. This convention -was developed at the European Southern Observatory (ESO) to support -hierarchical FITS keyword such as: -- -HIERARCH ESO INS FOCU POS = -0.00002500 / Focus position -- -Basically, this convention uses the FITS keyword 'HIERARCH' to indicate -that this convention is being used, then the actual keyword name -({\tt'ESO INS FOCU POS'} in this example) begins in column 10 and can -contain any printable ASCII text characters, including spaces. The -equals sign marks the end of the keyword name and is followed by the -usual value and comment fields just as in standard FITS keywords. -Further details of this convention are described at -http://fits.gsfc.nasa.gov/registry/hierarch\_keyword.html -and in Section 4.4 of the ESO Data Interface Control Document that -is linked to from -http://archive.eso.org/cms/tools-documentation/eso-data-interface-control.html. - -This convention allows a much broader range of keyword names -than is allowed by the FITS Standard. Here are more examples -of such keywords: -- -HIERARCH LongKeyword = 47.5 / Keyword has > 8 characters, and mixed case -HIERARCH XTE$TEMP = 98.6 / Keyword contains the '$' character -HIERARCH Earth is a star = F / Keyword contains embedded spaces -- -CFITSIO will transparently read and write these keywords, so application -programs do not in general need to know anything about the specific -implementation details of the HIERARCH convention. In particular, -application programs do not need to specify the `HIERARCH' part of the -keyword name when reading or writing keywords (although it -may be included if desired). When writing a keyword, CFITSIO first -checks to see if the keyword name is legal as a standard FITS keyword -(no more than 8 characters long and containing only letters, digits, or -a minus sign or underscore). If so it writes it as a standard FITS -keyword, otherwise it uses the hierarch convention to write the -keyword. The maximum keyword name length is 67 characters, which -leaves only 1 space for the value field. A more practical limit is -about 40 characters, which leaves enough room for most keyword values. -CFITSIO returns an error if there is not enough room for both the -keyword name and the keyword value on the 80-character card, except for -string-valued keywords which are simply truncated so that the closing -quote character falls in column 80. In the current implementation, -CFITSIO preserves the case of the letters when writing the keyword -name, but it is case-insensitive when reading or searching for a -keyword. The current implementation allows any ASCII text character -(ASCII 32 to ASCII 126) in the keyword name except for the '=' -character. A space is also required on either side of the equal sign. - -**F. Tile-Compressed Image Format - -CFITSIO supports a convention for compressing n-dimensional images and -storing the resulting byte stream in a variable-length column in a FITS -binary table. The general principle used in this convention is to -first divide the n-dimensional image into a rectangular grid of -subimages or `tiles'. Each tile is then compressed as a continuous -block of data, and the resulting compressed byte stream is stored in a -row of a variable length column in a FITS binary table. By dividing the -image into tiles it is generally possible to extract and uncompress -subsections of the image without having to uncompress the whole image. -The default tiling pattern treats each row of a 2-dimensional image (or -higher dimensional cube) as a tile, such that each tile contains NAXIS1 -pixels (except the default with the HCOMPRESS algorithm is to -compress the whole 2D image as a single tile). Any other rectangular -tiling pattern may also be defined. In -the case of relatively small images it may be sufficient to compress -the entire image as a single tile, resulting in an output binary table -with 1 row. In the case of 3-dimensional data cubes, it may be -advantageous to treat each plane of the cube as a separate tile if -application software typically needs to access the cube on a plane by -plane basis. - -See section 5.6 ``Image Compression'' -for more information on using this tile-compressed image format. - -*XII. Optimizing Programs - -CFITSIO has been carefully designed to obtain the highest possible -speed when reading and writing FITS files. In order to achieve the -best performance, however, application programmers must be careful to -call the CFITSIO routines appropriately and in an efficient sequence; -inappropriate usage of CFITSIO routines can greatly slow down the -execution speed of a program. - -The maximum possible I/O speed of CFITSIO depends of course on the type -of computer system that it is running on. To get a general idea of what -data I/O speeds are possible on a particular machine, build the speed.c -program that is distributed with CFITSIO (type 'make speed' in the CFITSIO -directory). This diagnostic program measures the speed of writing and reading -back a test FITS image, a binary table, and an ASCII table. - -The following 2 sections provide some background on how CFITSIO -internally manages the data I/O and describes some strategies that may -be used to optimize the processing speed of software that uses -CFITSIO. - -**A. How CFITSIO Manages Data I/O - -Many CFITSIO operations involve transferring only a small number of -bytes to or from the FITS file (e.g, reading a keyword, or writing a -row in a table); it would be very inefficient to physically read or -write such small blocks of data directly in the FITS file on disk, -therefore CFITSIO maintains a set of internal Input--Output (IO) -buffers in RAM memory that each contain one FITS block (2880 bytes) of -data. Whenever CFITSIO needs to access data in the FITS file, it first -transfers the FITS block containing those bytes into one of the IO -buffers in memory. The next time CFITSIO needs to access bytes in the -same block it can then go to the fast IO buffer rather than using a -much slower system disk access routine. The number of available IO -buffers is determined by the NIOBUF parameter (in fitsio2.h) and is -currently set to 40 by default. - -Whenever CFITSIO reads or writes data it first checks to see if that -block of the FITS file is already loaded into one of the IO buffers. -If not, and if there is an empty IO buffer available, then it will load -that block into the IO buffer (when reading a FITS file) or will -initialize a new block (when writing to a FITS file). If all the IO -buffers are already full, it must decide which one to reuse (generally -the one that has been accessed least recently), and flush the contents -back to disk if it has been modified before loading the new block. - -The one major exception to the above process occurs whenever a large -contiguous set of bytes are accessed, as might occur when reading or -writing a FITS image. In this case CFITSIO bypasses the internal IO -buffers and simply reads or writes the desired bytes directly in the -disk file with a single call to a low-level file read or write -routine. The minimum threshold for the number of bytes to read or -write this way is set by the MINDIRECT parameter and is currently set -to 3 FITS blocks = 8640 bytes. This is the most efficient way to read -or write large chunks of data. Note that this fast direct IO process is not -applicable when accessing columns of data in a FITS table because the -bytes are generally not contiguous since they are interleaved by the -other columns of data in the table. This explains why the speed for -accessing FITS tables is generally slower than accessing -FITS images. - -Given this background information, the general strategy for efficiently -accessing FITS files should be apparent: when dealing with FITS -images, read or write large chunks of data at a time so that the direct -IO mechanism will be invoked; when accessing FITS headers or FITS -tables, on the other hand, once a particular FITS block has been -loading into one of the IO buffers, try to access all the needed -information in that block before it gets flushed out of the IO buffer. -It is important to avoid the situation where the same FITS block is -being read then flushed from a IO buffer multiple times. - -The following section gives more specific suggestions for optimizing -the use of CFITSIO. - -**B. Optimization Strategies - -1. Because the data in FITS files is always stored in "big-endian" byte order, -where the first byte of numeric values contains the most significant bits and the -last byte contains the least significant bits, CFITSIO must swap the order of the bytes -when reading or writing FITS files when running on little-endian machines (e.g., -Linux and Microsoft Windows operating systems running on PCs with x86 CPUs). - -On relatively new CPUs that support "SSSE3" machine instructions -(e.g., starting with Intel Core 2 CPUs in 2007, and in AMD CPUs -beginning in 2011) significantly faster 4-byte and 8-byte swapping -algorithms are available. These faster byte swapping functions are -not used by default in CFITSIO (because of potential code -portablility issues), but users can enable them on supported -platforms by adding the appropriate compiler flags (-mssse3 with gcc -or icc on linux) when compiling the swapproc.c source file, which will -allow the compiler to generate code using the SSSE3 instruction set. -A convenient way to do this is to configure the CFITSIO library -with the following command: -- - > ./configure --enable-ssse3 -- -Note, however, that a binary executable file that is -created using these faster functions will only run on -machines that support the SSSE3 machine instructions. - -For faster 2-byte swaps on virtually all x86-64 CPUs (even those that -do not support SSSE3), a variant using only SSE2 instructions exists. -SSE2 is enabled by default on x86\_64 CPUs with 64-bit operating systems -(and is also automatically enabled by the --enable-ssse3 flag). -When running on x86\_64 CPUs with 32-bit operating systems, these faster -2-byte swapping algorithms are not used by default in CFITSIO, but can be -enabled explicitly with: -- -./configure --enable-sse2 -- -Preliminary testing indicates that these SSSE3 and SSE2 based -byte-swapping algorithms can boost the CFITSIO performance when -reading or writing FITS images by 20\% - 30\% or more. -It is important to note, however, that compiler optimization must be -turned on (e.g., by using the -O1 or -O2 flags in gcc) when building -programs that use these fast byte-swapping algorithms in order -to reap the full benefit of the SSSE3 and SSE2 instructions; without -optimization, the code may actually run slower than when using -more traditional byte-swapping techniques. - -2. When dealing with a FITS primary array or IMAGE extension, it is -more efficient to read or write large chunks of the image at a time -(at least 3 FITS blocks = 8640 bytes) so that the direct IO mechanism -will be used as described in the previous section. Smaller chunks of -data are read or written via the IO buffers, which is somewhat less -efficient because of the extra copy operation and additional -bookkeeping steps that are required. In principle it is more efficient -to read or write as big an array of image pixels at one time as -possible, however, if the array becomes so large that the operating -system cannot store it all in RAM, then the performance may be degraded -because of the increased swapping of virtual memory to disk. - -3. When dealing with FITS tables, the most important efficiency factor -in the software design is to read or write the data in the FITS file in -a single pass through the file. An example of poor program design -would be to read a large, 3-column table by sequentially reading the -entire first column, then going back to read the 2nd column, and -finally the 3rd column; this obviously requires 3 passes through the -file which could triple the execution time of an IO limited program. -For small tables this is not important, but when reading multi-megabyte -sized tables these inefficiencies can become significant. The more -efficient procedure in this case is to read or write only as many rows -of the table as will fit into the available internal IO buffers, then -access all the necessary columns of data within that range of rows. -Then after the program is completely finished with the data in those -rows it can move on to the next range of rows that will fit in the -buffers, continuing in this way until the entire file has been -processed. By using this procedure of accessing all the columns of a -table in parallel rather than sequentially, each block of the FITS file -will only be read or written once. - -The optimal number of rows to read or write at one time in a given -table depends on the width of the table row and on the number of IO -buffers that have been allocated in CFITSIO. The CFITSIO Iterator routine -will automatically use the optimal-sized buffer, but there is also a -CFITSIO routine that will return the optimal number of rows for a given -table: fits\_get\_rowsize. It is not critical to use exactly the -value of nrows returned by this routine, as long as one does not exceed -it. Using a very small value however can also lead to poor performance -because of the overhead from the larger number of subroutine calls. - -The optimal number of rows returned by fits\_get\_rowsize is valid only -as long as the application program is only reading or writing data in -the specified table. Any other calls to access data in the table -header would cause additional blocks of data -to be loaded into the IO buffers displacing data from the original -table, and should be avoided during the critical period while the table -is being read or written. - -4. Use the CFITSIO Iterator routine. This routine provides a -more `object oriented' way of reading and writing FITS files -which automatically uses the most appropriate data buffer size -to achieve the maximum I/O throughput. - -5. Use binary table extensions rather than ASCII table -extensions for better efficiency when dealing with tabular data. The -I/O to ASCII tables is slower because of the overhead in formatting or -parsing the ASCII data fields and because ASCII tables are about twice -as large as binary tables that have the same information content. - -6. Design software so that it reads the FITS header keywords in the -same order in which they occur in the file. When reading keywords, -CFITSIO searches forward starting from the position of the last keyword -that was read. If it reaches the end of the header without finding the -keyword, it then goes back to the start of the header and continues the -search down to the position where it started. In practice, as long as -the entire FITS header can fit at one time in the available internal IO -buffers, then the header keyword access will be relatively fast and it makes -little difference which order they are accessed. - -7. Avoid the use of scaling (by using the BSCALE and BZERO or TSCAL and -TZERO keywords) in FITS files since the scaling operations add to the -processing time needed to read or write the data. In some cases it may -be more efficient to temporarily turn off the scaling (using fits\_set\_bscale or -fits\_set\_tscale) and then read or write the raw unscaled values in the FITS -file. - -8. Avoid using the `implicit data type conversion' capability in -CFITSIO. For instance, when reading a FITS image with BITPIX = -32 -(32-bit floating point pixels), read the data into a single precision -floating point data array in the program. Forcing CFITSIO to convert -the data to a different data type can slow the program. - -9. Where feasible, design FITS binary tables using vector column -elements so that the data are written as a contiguous set of bytes, -rather than as single elements in multiple rows. For example, it is -faster to access the data in a table that contains a single row -and 2 columns with TFORM keywords equal to '10000E' and '10000J', than -it is to access the same amount of data in a table with 10000 rows -which has columns with the TFORM keywords equal to '1E' and '1J'. In -the former case the 10000 floating point values in the first column are -all written in a contiguous block of the file which can be read or -written quickly, whereas in the second case each floating point value -in the first column is interleaved with the integer value in the second -column of the same row so CFITSIO has to explicitly move to the -position of each element to be read or written. - -10. Avoid the use of variable length vector columns in binary tables, -since any reading or writing of these data requires that CFITSIO first -look up or compute the starting address of each row of data in the -heap. In practice, this is probably not a significant efficiency issue. - -11. When copying data from one FITS table to another, it is faster to -transfer the raw bytes instead of reading then writing each column of -the table. The CFITSIO routines fits\_read\_tblbytes and -fits\_write\_tblbytes will perform low-level reads or writes of any -contiguous range of bytes in a table extension. These routines can be -used to read or write a whole row (or multiple rows for even greater -efficiency) of a table with a single function call. These routines -are fast because they bypass all the usual data scaling, error checking -and machine dependent data conversion that is normally done by CFITSIO, -and they allow the program to write the data to the output file in -exactly the same byte order. For these same reasons, these routines -can corrupt the FITS data file if used incorrectly because no -validation or machine dependent conversion is performed by these -routines. These routines are only recommended for optimizing critical -pieces of code and should only be used by programmers who thoroughly -understand the internal format of the FITS tables they are reading or -writing. - -12. Another strategy for improving the speed of writing a FITS table, -similar to the previous one, is to directly construct the entire byte -stream for a whole table row (or multiple rows) within the application -program and then write it to the FITS file with -fits\_write\_tblbytes. This avoids all the overhead normally present -in the column-oriented CFITSIO write routines. This technique should -only be used for critical applications because it makes the code more -difficult to understand and maintain, and it makes the code more system -dependent (e.g., do the bytes need to be swapped before writing to the -FITS file?). - -13. Finally, external factors such as the speed of the data storage device, -the size of the data cache, the amount of disk fragmentation, and the amount of -RAM available on the system can all have a significant impact on -overall I/O efficiency. For critical applications, the entire hardware -and software system should be reviewed to identify any -potential I/O bottlenecks. - - -\appendix -*1 Index of Routines -\begin{tabular}{lr} -fits\_add\_group\_member & \pageref{ffgtam} \\ -fits\_ascii\_tform & \pageref{ffasfm} \\ -fits\_binary\_tform & \pageref{ffbnfm} \\ -fits\_calculator & \pageref{ffcalc} \\ -fits\_calculator\_rng & \pageref{ffcalcrng} \\ -fits\_calc\_binning & \pageref{calcbinning} \\ -fits\_calc\_rows & \pageref{ffcrow} \\ -fits\_change\_group & \pageref{ffgtch} \\ -fits\_clear\_errmark & \pageref{ffpmrk} \\ -fits\_clear\_errmsg & \pageref{ffcmsg} \\ -fits\_close\_file & \pageref{ffclos} \\ -fits\_compact\_group & \pageref{ffgtcm} \\ -fits\_compare\_str & \pageref{ffcmps} \\ -fits\_compress\_heap & \pageref{ffcmph} \\ -fits\_convert\_hdr2str & \pageref{ffhdr2str}, \pageref{hdr2str} \\ -fits\_copy\_cell2image & \pageref{copycell} \\ -fits\_copy\_col & \pageref{ffcpcl} \\ -fits\_copy\_data & \pageref{ffcpdt} \\ -fits\_copy\_file & \pageref{ffcpfl} \\ -fits\_copy\_group & \pageref{ffgtcp} \\ -fits\_copy\_hdu & \pageref{ffcopy} \\ -fits\_copy\_header & \pageref{ffcphd} \\ -fits\_copy\_image2cell & \pageref{copycell} \\ -fits\_copy\_image\_section & \pageref{ffcpimg} \\ -fits\_copy\_key & \pageref{ffcpky} \\ -fits\_copy\_member & \pageref{ffgmcp} \\ -fits\_copy\_pixlist2image & \pageref{copypixlist2image} \\ -fits\_copy\_rows & \pageref{ffcprw} \\ -fits\_create\_diskfile & \pageref{ffinit} \\ -fits\_create\_file & \pageref{ffinit} \\ -fits\_create\_group & \pageref{ffgtcr} \\ -fits\_create\_hdu & \pageref{ffcrhd} \\ - -\end{tabular} -\begin{tabular}{lr} -fits\_create\_img & \pageref{ffcrim} \\ -fits\_create\_memfile & \pageref{ffimem} \\ -fits\_create\_tbl & \pageref{ffcrtb} \\ -fits\_create\_template & \pageref{fftplt} \\ -fits\_date2str & \pageref{ffdt2s} \\ -fits\_decode\_chksum & \pageref{ffdsum} \\ -fits\_decode\_tdim & \pageref{ffdtdm} \\ -fits\_delete\_col & \pageref{ffdcol} \\ -fits\_delete\_file & \pageref{ffdelt} \\ -fits\_delete\_hdu & \pageref{ffdhdu} \\ -fits\_delete\_key & \pageref{ffdkey} \\ -fits\_delete\_record & \pageref{ffdrec} \\ -fits\_delete\_rowlist & \pageref{ffdrws} \\ -fits\_delete\_rowrange & \pageref{ffdrrg} \\ -fits\_delete\_rows & \pageref{ffdrow} \\ -fits\_delete\_str & \pageref{ffdkey} \\ -fits\_encode\_chksum & \pageref{ffesum} \\ -fits\_file\_exists & \pageref{ffexist} \\ -fits\_file\_mode & \pageref{ffflmd} \\ -fits\_file\_name & \pageref{ffflnm} \\ -fits\_find\_first\_row & \pageref{ffffrw} \\ -fits\_find\_nextkey & \pageref{ffgnxk} \\ -fits\_find\_rows & \pageref{fffrow} \\ -fits\_flush\_buffer & \pageref{ffflus} \\ -fits\_flush\_file & \pageref{ffflus} \\ -fits\_free\_memory & \pageref{ffgkls}, \pageref{ffhdr2str} \\ -fits\_get\_acolparms & \pageref{ffgacl} \\ -fits\_get\_bcolparms & \pageref{ffgbcl} \\ -fits\_get\_chksum & \pageref{ffgcks} \\ -fits\_get\_col\_display\_width & \pageref{ffgcdw} \\ -fits\_get\_colname & \pageref{ffgcnn} \\ -fits\_get\_colnum & \pageref{ffgcno} \\ -\end{tabular} -\begin{tabular}{lr} -fits\_get\_coltype & \pageref{ffgtcl} \\ -fits\_get\_compression\_type & \pageref{ffgetcomp} \\ -fits\_get\_eqcoltype & \pageref{ffgtcl} \\ -fits\_get\_errstatus & \pageref{ffgerr} \\ -fits\_get\_hdrpos & \pageref{ffghps} \\ -fits\_get\_hdrspace & \pageref{ffghsp} \\ -fits\_get\_hdu\_num & \pageref{ffghdn} \\ -fits\_get\_hdu\_type & \pageref{ffghdt} \\ -fits\_get\_hduaddr & \pageref{ffghad} \\ -fits\_get\_hduaddrll & \pageref{ffghad} \\ -fits\_get\_img\_dim & \pageref{ffgidm} \\ -fits\_get\_img\_equivtype & \pageref{ffgidt} \\ -fits\_get\_img\_param & \pageref{ffgipr} \\ -fits\_get\_img\_size & \pageref{ffgisz} \\ -fits\_get\_img\_type & \pageref{ffgidt} \\ -fits\_get\_inttype & \pageref{ffinttyp} \\ -fits\_get\_key\_strlen & \pageref{ffgksl} \\ -fits\_get\_keyclass & \pageref{ffgkcl} \\ -fits\_get\_keyname & \pageref{ffgknm} \\ -fits\_get\_keytype & \pageref{ffdtyp} \\ -fits\_get\_noise\_bits & \pageref{ffgetcomp} \\ -fits\_get\_num\_cols & \pageref{ffgnrw} \\ -fits\_get\_num\_groups & \pageref{ffgmng} \\ -fits\_get\_num\_hdus & \pageref{ffthdu} \\ -fits\_get\_num\_members & \pageref{ffgtnm} \\ -fits\_get\_num\_rows & \pageref{ffgnrw} \\ -fits\_get\_rowsize & \pageref{ffgrsz} \\ -fits\_get\_system\_time & \pageref{ffdt2s} \\ -fits\_get\_tile\_dim & \pageref{ffgetcomp} \\ -fits\_get\_tbcol & \pageref{ffgabc} \\ -fits\_get\_version & \pageref{ffvers} \\ -fits\_hdr2str & \pageref{ffhdr2str}, \pageref{hdr2str} \\ -\end{tabular} -\newpage -\begin{tabular}{lr} -fits\_insert\_atbl & \pageref{ffitab} \\ -fits\_insert\_btbl & \pageref{ffibin} \\ -fits\_insert\_col & \pageref{fficol} \\ -fits\_insert\_cols & \pageref{fficls} \\ -fits\_insert\_group & \pageref{ffgtis} \\ -fits\_insert\_img & \pageref{ffiimg} \\ -fits\_insert\_key\_null & \pageref{ffikyu} \\ -fits\_insert\_key\_TYP & \pageref{ffikyx} \\ -fits\_insert\_record & \pageref{ffirec} \\ -fits\_insert\_rows & \pageref{ffirow} \\ -fits\_is\_reentrant & \pageref{reentrant} \\ -fits\_iterate\_data & \pageref{ffiter} \\ -fits\_make\_hist & \pageref{makehist} \\ -fits\_make\_key & \pageref{ffmkky} \\ -fits\_make\_keyn & \pageref{ffkeyn} \\ -fits\_make\_nkey & \pageref{ffnkey} \\ -fits\_merge\_groups & \pageref{ffgtmg} \\ -fits\_modify\_card & \pageref{ffmcrd} \\ -fits\_modify\_comment & \pageref{ffmcom} \\ -fits\_modify\_key\_null & \pageref{ffmkyu} \\ -fits\_modify\_key\_TYP & \pageref{ffmkyx} \\ -fits\_modify\_name & \pageref{ffmnam} \\ -fits\_modify\_record & \pageref{ffmrec} \\ -fits\_modify\_vector\_len & \pageref{ffmvec} \\ -fits\_movabs\_hdu & \pageref{ffmahd} \\ -fits\_movnam\_hdu & \pageref{ffmnhd} \\ -fits\_movrel\_hdu & \pageref{ffmrhd} \\ -fits\_null\_check & \pageref{ffnchk} \\ -fits\_open\_data & \pageref{ffopen} \\ -fits\_open\_diskfile & \pageref{ffopen} \\ -fits\_open\_extlist & \pageref{ffopen} \\ -fits\_open\_file & \pageref{ffopen} \\ -fits\_open\_image & \pageref{ffopen} \\ -fits\_open\_table & \pageref{ffopen} \\ -fits\_open\_group & \pageref{ffgtop} \\ -fits\_open\_member & \pageref{ffgmop} \\ -fits\_open\_memfile & \pageref{ffomem} \\ -fits\_parse\_extnum & \pageref{ffextn} \\ -fits\_parse\_input\_filename & \pageref{ffiurl} \\ -fits\_parse\_input\_url & \pageref{ffiurl} \\ -fits\_parse\_range & \pageref{ffrwrg} \\ -fits\_parse\_rootname & \pageref{ffrtnm} \\ -fits\_parse\_template & \pageref{ffgthd} \\ -fits\_parse\_value & \pageref{ffpsvc} \\ -fits\_pix\_to\_world & \pageref{ffwldp} \\ -fits\_read\_2d\_TYP & \pageref{ffg2dx} \\ -fits\_read\_3d\_TYP & \pageref{ffg3dx} \\ -fits\_read\_atblhdr & \pageref{ffghtb} \\ -\end{tabular} -\begin{tabular}{lr} -fits\_read\_btblhdr & \pageref{ffghbn} \\ -fits\_read\_card & \pageref{ffgcrd} \\ -fits\_read\_col & \pageref{ffgcv} \\ -fits\_read\_col\_bit\_ & \pageref{ffgcx} \\ -fits\_read\_col\_TYP & \pageref{ffgcvx} \\ -fits\_read\_colnull & \pageref{ffgcf} \\ -fits\_read\_colnull\_TYP & \pageref{ffgcfx} \\ -fits\_read\_descript & \pageref{ffgdes} \\ -fits\_read\_descripts & \pageref{ffgdes} \\ -fits\_read\_errmsg & \pageref{ffgmsg} \\ -fits\_read\_ext & \pageref{ffgextn} \\ -fits\_read\_grppar\_TYP & \pageref{ffggpx} \\ -fits\_read\_img & \pageref{ffgpv} \\ -fits\_read\_img\_coord & \pageref{ffgics} \\ -fits\_read\_img\_TYP & \pageref{ffgpvx} \\ -fits\_read\_imghdr & \pageref{ffghpr} \\ -fits\_read\_imgnull & \pageref{ffgpf} \\ -fits\_read\_imgnull\_TYP & \pageref{ffgpfx} \\ -fits\_read\_key & \pageref{ffgky} \\ -fits\_read\_key\_longstr & \pageref{ffgkls} \\ -fits\_read\_key\_triple & \pageref{ffgkyt} \\ -fits\_read\_key\_unit & \pageref{ffgunt} \\ -fits\_read\_key\_TYP & \pageref{ffgkyx} \\ -fits\_read\_keyn & \pageref{ffgkyn} \\ -fits\_read\_keys\_TYP & \pageref{ffgknx} \\ -fits\_read\_keyword & \pageref{ffgkey} \\ -fits\_read\_pix & \pageref{ffgpxv} \\ -fits\_read\_pixnull & \pageref{ffgpxf} \\ -fits\_read\_record & \pageref{ffgrec} \\ -fits\_read\_str & \pageref{ffgcrd} \\ -fits\_read\_string\_key & \pageref{ffgsky} \\ -fits\_read\_subset & \pageref{ffgsv} \\ -fits\_read\_subset\_TYP & \pageref{ffgsvx} \pageref{ffgsvx2}\\ -fits\_read\_subsetnull\_TYP & \pageref{ffgsfx} \pageref{ffgsfx2} \\ -fits\_read\_tbl\_coord & \pageref{ffgtcs} \\ -fits\_read\_tblbytes & \pageref{ffgtbb} \\ -fits\_read\_tdim & \pageref{ffgtdm} \\ -fits\_read\_wcstab & \pageref{wcstab} \\ -fits\_rebin\_wcs & \pageref{rebinwcs} \\ -fits\_remove\_group & \pageref{ffgtrm} \\ -fits\_remove\_member & \pageref{ffgmrm} \\ -fits\_reopen\_file & \pageref{ffreopen} \\ -fits\_report\_error & \pageref{ffrprt} \\ -fits\_resize\_img & \pageref{ffrsim} \\ -fits\_rms\_float & \pageref{imageRMS} \\ -fits\_rms\_short & \pageref{imageRMS} \\ -fits\_select\_rows & \pageref{ffsrow} \\ -fits\_set\_atblnull & \pageref{ffsnul} \\ -\end{tabular} -\begin{tabular}{lr} -fits\_set\_bscale & \pageref{ffpscl} \\ -fits\_set\_btblnull & \pageref{fftnul} \\ -fits\_set\_compression\_type & \pageref{ffsetcomp} \\ -fits\_set\_hdrsize & \pageref{ffhdef} \\ -fits\_set\_hdustruc & \pageref{ffrdef} \\ -fits\_set\_imgnull & \pageref{ffpnul} \\ -fits\_set\_noise\_bits & \pageref{ffsetcomp} \\ -fits\_set\_tile\_dim & \pageref{ffsetcomp} \\ -fits\_set\_tscale & \pageref{fftscl} \\ -fits\_split\_names & \pageref{splitnames} \\ -fits\_str2date & \pageref{ffdt2s} \\ -fits\_str2time & \pageref{ffdt2s} \\ -fits\_test\_expr & \pageref{fftexp} \\ -fits\_test\_heap & \pageref{fftheap} \\ -fits\_test\_keyword & \pageref{fftkey} \\ -fits\_test\_record & \pageref{fftrec} \\ -fits\_time2str & \pageref{ffdt2s} \\ -fits\_transfer\_member & \pageref{ffgmtf} \\ -fits\_translate\_keyword & \pageref{translatekey} \\ -fits\_update\_card & \pageref{ffucrd} \\ -fits\_update\_chksum & \pageref{ffupck} \\ -fits\_update\_key & \pageref{ffuky} \\ -fits\_update\_key\_longstr & \pageref{ffukyx} \\ -fits\_update\_key\_null & \pageref{ffukyu} \\ -fits\_update\_key\_TYP & \pageref{ffukyx} \\ -fits\_uppercase & \pageref{ffupch} \\ -fits\_url\_type & \pageref{ffurlt} \\ -fits\_verify\_chksum & \pageref{ffvcks} \\ -fits\_verify\_group & \pageref{ffgtvf} \\ -fits\_world\_to\_pix & \pageref{ffxypx} \\ -fits\_write\_2d\_TYP & \pageref{ffp2dx} \\ -fits\_write\_3d\_TYP & \pageref{ffp3dx} \\ -fits\_write\_atblhdr & \pageref{ffphtb} \\ -fits\_write\_btblhdr & \pageref{ffphbn} \\ -fits\_write\_chksum & \pageref{ffpcks} \\ -fits\_write\_col & \pageref{ffpcl} \\ -fits\_write\_col\_bit & \pageref{ffpclx} \\ -fits\_write\_col\_TYP & \pageref{ffpcls} \\ -fits\_write\_col\_null & \pageref{ffpclu} \\ -fits\_write\_colnull & \pageref{ffpcn} \\ -fits\_write\_colnull\_TYP & \pageref{ffpcnx} \\ -fits\_write\_comment & \pageref{ffpcom} \\ -fits\_write\_date & \pageref{ffpdat} \\ -fits\_write\_descript & \pageref{ffpdes} \\ -fits\_write\_errmark & \pageref{ffpmrk} \\ -fits\_write\_errmsg & \pageref{ffpmsg} \\ -fits\_write\_ext & \pageref{ffgextn} \\ -fits\_write\_exthdr & \pageref{ffphps} \\ -\end{tabular} -\newpage -\begin{tabular}{lr} -fits\_write\_grphdr & \pageref{ffphpr} \\ -fits\_write\_grppar\_TYP & \pageref{ffpgpx} \\ -fits\_write\_hdu & \pageref{ffwrhdu} \\ -fits\_write\_history & \pageref{ffphis} \\ -fits\_write\_img & \pageref{ffppr} \\ -fits\_write\_img\_null & \pageref{ffppru} \\ -fits\_write\_img\_TYP & \pageref{ffpprx} \\ -fits\_write\_imghdr & \pageref{ffphps} \\ -fits\_write\_imgnull & \pageref{ffppn} \\ -fits\_write\_imgnull\_TYP & \pageref{ffppnx} \\ -fits\_write\_key & \pageref{ffpky} \\ -fits\_write\_key\_longstr & \pageref{ffpkls} \\ -fits\_write\_key\_longwarn & \pageref{ffplsw} \\ -fits\_write\_key\_null & \pageref{ffpkyu} \\ -fits\_write\_key\_template & \pageref{ffpktp} \\ -fits\_write\_key\_triple & \pageref{ffpkyt} \\ -fits\_write\_key\_unit & \pageref{ffpunt} \\ -fits\_write\_key\_TYP & \pageref{ffpkyx} \\ -fits\_write\_keys\_TYP & \pageref{ffpknx} \\ -fits\_write\_keys\_histo & \pageref{writekeyshisto} \\ -fits\_write\_null\_img & \pageref{ffpprn} \\ -fits\_write\_nullrows & \pageref{ffpclu} \\ -fits\_write\_pix & \pageref{ffppx} \\ -fits\_write\_pixnull & \pageref{ffppxn} \\ -fits\_write\_record & \pageref{ffprec} \\ -fits\_write\_subset & \pageref{ffpss} \\ -fits\_write\_subset\_TYP & \pageref{ffpssx} \\ -fits\_write\_tblbytes & \pageref{ffptbb} \\ -fits\_write\_tdim & \pageref{ffptdm} \\ -fits\_write\_theap & \pageref{ffpthp} \\ -\end{tabular} -\newpage -\begin{tabular}{lr} -ffasfm & \pageref{ffasfm} \\ -ffbnfm & \pageref{ffbnfm} \\ -ffcalc & \pageref{ffcalc} \\ -ffcalc\_rng & \pageref{ffcalcrng} \\ -ffclos & \pageref{ffclos} \\ -ffcmph & \pageref{ffcmph} \\ -ffcmps & \pageref{ffcmps} \\ -ffcmrk & \pageref{ffpmrk} \\ -ffcmsg & \pageref{ffcmsg} \\ -ffcopy & \pageref{ffcopy} \\ -ffcpcl & \pageref{ffcpcl} \\ -ffcpdt & \pageref{ffcpdt} \\ -ffcpfl & \pageref{ffcpfl} \\ -ffcphd & \pageref{ffcphd} \\ -ffcpimg & \pageref{ffcpimg} \\ -ffcpky & \pageref{ffcpky} \\ -ffcprw & \pageref{ffcprw} \\ -ffcrhd & \pageref{ffcrhd} \\ -ffcrim & \pageref{ffcrim} \\ -ffcrow & \pageref{ffcrow} \\ -ffcrtb & \pageref{ffcrtb} \\ -ffdcol & \pageref{ffdcol} \\ -ffdelt & \pageref{ffdelt} \\ -ffdhdu & \pageref{ffdhdu} \\ -ffdkey & \pageref{ffdkey} \\ -ffdkinit & \pageref{ffinit} \\ -ffdkopen & \pageref{ffopen} \\ -ffdopn & \pageref{ffopen} \\ -ffdrec & \pageref{ffdrec} \\ -ffdrow & \pageref{ffdrow} \\ -ffdrrg & \pageref{ffdrrg} \\ -ffdrws & \pageref{ffdrws} \\ -ffdstr & \pageref{ffdkey} \\ -ffdsum & \pageref{ffdsum} \\ -ffdt2s & \pageref{ffdt2s} \\ -ffdtdm & \pageref{ffdtdm} \\ -ffdtyp & \pageref{ffdtyp} \\ -ffeopn & \pageref{ffopen} \\ -ffeqty & \pageref{ffgtcl} \\ -ffesum & \pageref{ffesum} \\ -ffexest & \pageref{ffexist} \\ -ffextn & \pageref{ffextn} \\ -ffffrw & \pageref{ffffrw} \\ -ffflmd & \pageref{ffflmd} \\ -ffflnm & \pageref{ffflnm} \\ -ffflsh & \pageref{ffflus} \\ -ffflus & \pageref{ffflus} \\ -fffree & \pageref{ffgkls}, \pageref{ffhdr2str} \\ -\end{tabular} -\begin{tabular}{lr} -fffrow & \pageref{fffrow} \\ -ffg2d\_ & \pageref{ffg2dx} \\ -ffg3d\_ & \pageref{ffg3dx} \\ -ffgabc & \pageref{ffgabc} \\ -ffgacl & \pageref{ffgacl} \\ -ffgbcl & \pageref{ffgbcl} \\ -ffgcdw & \pageref{ffgcdw} \\ -ffgcf & \pageref{ffgcf} \\ -ffgcf\_ & \pageref{ffgcfx} \\ -ffgcks & \pageref{ffgcks} \\ -ffgcnn & \pageref{ffgcnn} \\ -ffgcno & \pageref{ffgcno} \\ -ffgcrd & \pageref{ffgcrd} \\ -ffgcv & \pageref{ffgcv} \\ -ffgcv\_ & \pageref{ffgcvx} \\ -ffgcx & \pageref{ffgcx} \\ -ffgdes & \pageref{ffgdes} \\ -ffgdess & \pageref{ffgdes} \\ -ffgerr & \pageref{ffgerr} \\ -ffgextn & \pageref{ffgextn} \\ -ffggp\_ & \pageref{ffggpx} \\ -ffghad & \pageref{ffghad} \\ -ffghbn & \pageref{ffghbn} \\ -ffghdn & \pageref{ffghdn} \\ -ffghdt & \pageref{ffghdt} \\ -ffghpr & \pageref{ffghpr} \\ -ffghps & \pageref{ffghps} \\ -ffghsp & \pageref{ffghsp} \\ -ffghtb & \pageref{ffghtb} \\ -ffgics & \pageref{ffgics} \\ -ffgidm & \pageref{ffgidm} \\ -ffgidt & \pageref{ffgidt} \\ -ffgiet & \pageref{ffgidt} \\ -ffgipr & \pageref{ffgipr} \\ -ffgisz & \pageref{ffgisz} \\ -ffgkcl & \pageref{ffgkcl} \\ -ffgkey & \pageref{ffgkey} \\ -ffgkls & \pageref{ffgkls} \\ -ffgksl & \pageref{ffgksl} \\ -ffgkn\_ & \pageref{ffgknx} \\ -ffgknm & \pageref{ffgknm} \\ -ffgky & \pageref{ffgky} \\ -ffgkyn & \pageref{ffgkyn} \\ -ffgkyt & \pageref{ffgkyt} \\ -ffgky\_ & \pageref{ffgkyx} \\ -ffgmcp & \pageref{ffgmcp} \\ -ffgmng & \pageref{ffgmng} \\ -ffgmop & \pageref{ffgmop} \\ - -\end{tabular} -\begin{tabular}{lr} -ffgmrm & \pageref{ffgmrm} \\ -ffgmsg & \pageref{ffgmsg} \\ -ffgmtf & \pageref{ffgmtf} \\ -ffgncl & \pageref{ffgnrw} \\ -ffgnrw & \pageref{ffgnrw} \\ -ffgnxk & \pageref{ffgnxk} \\ -ffgpf & \pageref{ffgpf} \\ -ffgpf\_ & \pageref{ffgpfx} \\ -ffgpv & \pageref{ffgpv} \\ -ffgpv\_ & \pageref{ffgpvx} \\ -ffgpxv & \pageref{ffgpxv} \\ -ffgpxf & \pageref{ffgpxf} \\ -ffgrec & \pageref{ffgrec} \\ -ffgrsz & \pageref{ffgrsz} \\ -ffgsdt & \pageref{ffdt2s} \\ -ffgsf\_ & \pageref{ffgsfx} \pageref{ffgsfx2} \\ -ffgsky & \pageref{ffgsky} \\ -ffgstm & \pageref{ffdt2s} \\ -ffgstr & \pageref{ffgcrd} \\ -ffgsv & \pageref{ffgsv} \\ -ffgsv\_ & \pageref{ffgsvx} \pageref{ffgsvx2}\\ -ffgtam & \pageref{ffgtam} \\ -ffgtbb & \pageref{ffgtbb} \\ -ffgtch & \pageref{ffgtch} \\ -ffgtcl & \pageref{ffgtcl} \\ -ffgtcm & \pageref{ffgtcm} \\ -ffgtcp & \pageref{ffgtcp} \\ -ffgtcr & \pageref{ffgtcr} \\ -ffgtcs & \pageref{ffgtcs} \\ -ffgtdm & \pageref{ffgtdm} \\ -ffgthd & \pageref{ffgthd} \\ -ffgtis & \pageref{ffgtis} \\ -ffgtmg & \pageref{ffgtmg} \\ -ffgtnm & \pageref{ffgtnm} \\ -ffgtop & \pageref{ffgtop} \\ -ffgtrm & \pageref{ffgtrm} \\ -ffgtvf & \pageref{ffgtvf} \\ -ffgunt & \pageref{ffgunt} \\ -ffhdef & \pageref{ffhdef} \\ -ffibin & \pageref{ffibin} \\ -fficls & \pageref{fficls} \\ -fficol & \pageref{fficol} \\ -ffifile & \pageref{ffiurl} \\ -ffiimg & \pageref{ffiimg} \\ -ffikls & \pageref{ffikyx} \\ -ffikyu & \pageref{ffikyu} \\ -ffiky\_ & \pageref{ffikyx} \\ -ffimem & \pageref{ffimem} \\ - -\end{tabular} -\begin{tabular}{lr} - -ffinit & \pageref{ffinit} \\ -ffinttyp & \pageref{ffinttyp} \\ -ffiopn & \pageref{ffopen} \\ -ffirec & \pageref{ffirec} \\ -ffirow & \pageref{ffirow} \\ -ffitab & \pageref{ffitab} \\ -ffiter & \pageref{ffiter} \\ -ffiurl & \pageref{ffiurl} \\ -ffkeyn & \pageref{ffkeyn} \\ -ffmahd & \pageref{ffmahd} \\ -ffmcom & \pageref{ffmcom} \\ -ffmcrd & \pageref{ffmcrd} \\ -ffmkky & \pageref{ffmkky} \\ -ffmkls & \pageref{ffmkyx} \\ -ffmkyu & \pageref{ffmkyu} \\ -ffmky\_ & \pageref{ffmkyx} \\ -ffmnam & \pageref{ffmnam} \\ -ffmnhd & \pageref{ffmnhd} \\ -ffmrec & \pageref{ffmrec} \\ -ffmrhd & \pageref{ffmrhd} \\ -ffmvec & \pageref{ffmvec} \\ -ffnchk & \pageref{ffnchk} \\ -ffnkey & \pageref{ffnkey} \\ -ffomem & \pageref{ffomem} \\ -ffopen & \pageref{ffopen} \\ -ffp2d\_ & \pageref{ffp2dx} \\ -ffp3d\_ & \pageref{ffp3dx} \\ -ffpcks & \pageref{ffpcks} \\ -ffpcl & \pageref{ffpcl} \\ -ffpcls & \pageref{ffpcls} \\ -ffpcl\_ & \pageref{ffpclx} \\ -ffpclu & \pageref{ffpclu} \\ -ffpcn & \pageref{ffpcn} \\ -ffpcn\_ & \pageref{ffpcnx} \\ -ffpcom & \pageref{ffpcom} \\ -ffpdat & \pageref{ffpdat} \\ -ffpdes & \pageref{ffpdes} \\ -ffpextn & \pageref{ffgextn} \\ -ffpgp\_ & \pageref{ffpgpx} \\ -ffphbn & \pageref{ffphbn} \\ -ffphext & \pageref{ffphpr} \\ -ffphis & \pageref{ffphis} \\ -ffphpr & \pageref{ffphpr} \\ -ffphps & \pageref{ffphps} \\ -ffphtb & \pageref{ffphtb} \\ -ffpkls & \pageref{ffpkls} \\ -ffpkn\_ & \pageref{ffpknx} \\ -ffpktp & \pageref{ffpktp} \\ - -\end{tabular} -\begin{tabular}{lr} - -ffpky & \pageref{ffpky} \\ -ffpkyt & \pageref{ffpkyt} \\ -ffpkyu & \pageref{ffpkyu} \\ -ffpky\_ & \pageref{ffpkyx} \\ -ffplsw & \pageref{ffplsw} \\ -ffpmrk & \pageref{ffpmrk} \\ -ffpmsg & \pageref{ffpmsg} \\ -ffpnul & \pageref{ffpnul} \\ -ffppn & \pageref{ffppn} \\ -ffppn\_ & \pageref{ffppnx} \\ -ffppr & \pageref{ffppr} \\ -ffpprn & \pageref{ffpprn} \\ -ffppru & \pageref{ffppru} \\ -ffppr\_ & \pageref{ffpprx} \\ -ffppx & \pageref{ffppx} \\ -ffppxn & \pageref{ffppxn} \\ -ffprec & \pageref{ffprec} \\ -ffprwu & \pageref{ffpclu} \\ -ffpscl & \pageref{ffpscl} \\ -ffpss & \pageref{ffpss} \\ -ffpss\_ & \pageref{ffpssx} \\ -ffpsvc & \pageref{ffpsvc} \\ -ffptbb & \pageref{ffptbb} \\ -ffptdm & \pageref{ffptdm} \\ -ffpthp & \pageref{ffpthp} \\ -ffpunt & \pageref{ffpunt} \\ -ffrdef & \pageref{ffrdef} \\ -ffreopen & \pageref{ffreopen} \\ -ffrprt & \pageref{ffrprt} \\ -ffrsim & \pageref{ffrsim} \\ -ffrtnm & \pageref{ffrtnm} \\ -ffrwrg & \pageref{ffrwrg} \\ -ffs2dt & \pageref{ffdt2s} \\ -ffs2tm & \pageref{ffdt2s} \\ -ffsnul & \pageref{ffsnul} \\ -ffsrow & \pageref{ffsrow} \\ -fftexp & \pageref{fftexp} \\ -ffthdu & \pageref{ffthdu} \\ -fftheap & \pageref{fftheap} \\ -fftkey & \pageref{fftkey} \\ -fftm2s & \pageref{ffdt2s} \\ -fftnul & \pageref{fftnul} \\ -fftopn & \pageref{ffopen} \\ -fftplt & \pageref{fftplt} \\ -fftrec & \pageref{fftrec} \\ -fftscl & \pageref{fftscl} \\ -ffucrd & \pageref{ffucrd} \\ -ffukls & \pageref{ffukyx} \\ - - -\end{tabular} -\newpage -\begin{tabular}{lr} - -ffuky & \pageref{ffuky} \\ -ffukyu & \pageref{ffukyu} \\ -ffuky\_ & \pageref{ffukyx} \\ -ffupch & \pageref{ffupch} \\ -ffupck & \pageref{ffupck} \\ -ffurlt & \pageref{ffurlt} \\ -ffvcks & \pageref{ffvcks} \\ -ffvers & \pageref{ffvers} \\ -ffwldp & \pageref{ffwldp} \\ -ffwrhdu & \pageref{ffwrhdu} \\ -ffxypx & \pageref{ffxypx} \\ - -\end{tabular} - - -*2 Parameter Definitions -- -anynul - set to TRUE (=1) if any returned values are undefined, else FALSE -array - array of numerical data values to read or write -ascii - encoded checksum string -binspec - the input table binning specifier -bitpix - bits per pixel. The following symbolic mnemonics are predefined: - BYTE_IMG = 8 (unsigned char) - SHORT_IMG = 16 (signed short integer) - LONG_IMG = 32 (signed long integer) - LONGLONG_IMG = 64 (signed long 64-bit integer) - FLOAT_IMG = -32 (float) - DOUBLE_IMG = -64 (double). - Two additional values, USHORT_IMG and ULONG_IMG are also available - for creating unsigned integer images. These are equivalent to - creating a signed integer image with BZERO offset keyword values - of 32768 or 2147483648, respectively, which is the convention that - FITS uses to store unsigned integers. -card - header record to be read or written (80 char max, null-terminated) -casesen - CASESEN (=1) for case-sensitive string matching, else CASEINSEN (=0) -cmopt - grouping table "compact" option parameter. Allowed values are: - OPT_CMT_MBR and OPT_CMT_MBR_DEL. -colname - name of the column (null-terminated) -colnum - column number (first column = 1) -colspec - the input file column specification; used to delete, create, or rename - table columns -comment - the keyword comment field (72 char max, null-terminated) -complm - should the checksum be complemented? -comptype - compression algorithm to use: GZIP_1, RICE_1, HCOMPRESS_1, or PLIO_1 -coordtype- type of coordinate projection (-SIN, -TAN, -ARC, -NCP, - -GLS, -MER, or -AIT) -cpopt - grouping table copy option parameter. Allowed values are: - OPT_GCP_GPT, OPT_GCP_MBR, OPT_GCP_ALL, OPT_MCP_ADD, OPT_MCP_NADD, - OPT_MCP_REPL, amd OPT_MCP_MOV. -create_col- If TRUE, then insert a new column in the table, otherwise - overwrite the existing column. -current - if TRUE, then the current HDU will be copied -dataok - was the data unit verification successful (=1) or - not (= -1). Equals zero if the DATASUM keyword is not present. -datasum - 32-bit 1's complement checksum for the data unit -dataend - address (in bytes) of the end of the HDU -datastart- address (in bytes) of the start of the data unit -datatype - specifies the data type of the value. Allowed value are: TSTRING, - TLOGICAL, TBYTE, TSBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, - TFLOAT, TDOUBLE, TCOMPLEX, and TDBLCOMPLEX -datestr - FITS date/time string: 'YYYY-MM-DDThh:mm:ss.ddd', 'YYYY-MM-dd', - or 'dd/mm/yy' -day - calendar day (UTC) (1-31) -decimals - number of decimal places to be displayed -deltasize - increment for allocating more memory -dim1 - declared size of the first dimension of the image or cube array -dim2 - declared size of the second dimension of the data cube array -dispwidth - display width of a column = length of string that will be read -dtype - data type of the keyword ('C', 'L', 'I', 'F' or 'X') - C = character string - L = logical - I = integer - F = floating point number - X = complex, e.g., "(1.23, -4.56)" -err_msg - error message on the internal stack (80 chars max) -err_text - error message string corresponding to error number (30 chars max) -exact - TRUE (=1) if the strings match exactly; - FALSE (=0) if wildcards are used -exclist - array of pointers to keyword names to be excluded from search -exists - flag indicating whether the file or compressed file exists on disk -expr - boolean or arithmetic expression -extend - TRUE (=1) if FITS file may have extensions, else FALSE (=0) -extname - value of the EXTNAME keyword (null-terminated) -extspec - the extension or HDU specifier; a number or name, version, and type -extver - value of the EXTVER keyword = integer version number -filename - full name of the FITS file, including optional HDU and filtering specs -filetype - type of file (file://, ftp://, http://, etc.) -filter - the input file filtering specifier -firstchar- starting byte in the row (first byte of row = 1) -firstfailed - member HDU ID (if positive) or grouping table GRPIDn index - value (if negative) that failed grouping table verification. -firstelem- first element in a vector (ignored for ASCII tables) -firstrow - starting row number (first row of table = 1) -following- if TRUE, any HDUs following the current HDU will be copied -fpixel - coordinate of the first pixel to be read or written in the - FITS array. The array must be of length NAXIS and have values such - that fpixel[0] is in the range 1 to NAXIS1, fpixel[1] is in the - range 1 to NAXIS2, etc. -fptr - pointer to a 'fitsfile' structure describing the FITS file. -frac - factional part of the keyword value -gcount - number of groups in the primary array (usually = 1) -gfptr - fitsfile* pointer to a grouping table HDU. -group - GRPIDn/GRPLCn index value identifying a grouping table HDU, or - data group number (=0 for non-grouped data) -grouptype - Grouping table parameter that specifies the columns to be - created in a grouping table HDU. Allowed values are: GT_ID_ALL_URI, - GT_ID_REF, GT_ID_POS, GT_ID_ALL, GT_ID_REF_URI, and GT_ID_POS_URI. -grpname - value to use for the GRPNAME keyword value. -hdunum - sequence number of the HDU (Primary array = 1) -hduok - was the HDU verification successful (=1) or - not (= -1). Equals zero if the CHECKSUM keyword is not present. -hdusum - 32 bit 1's complement checksum for the entire CHDU -hdutype - HDU type: IMAGE_HDU (0), ASCII_TBL (1), BINARY_TBL (2), ANY_HDU (-1) -header - returned character string containing all the keyword records -headstart- starting address (in bytes) of the CHDU -heapsize - size of the binary table heap, in bytes -history - the HISTORY keyword comment string (70 char max, null-terminated) -hour - hour within day (UTC) (0 - 23) -inc - sampling interval for pixels in each FITS dimension -inclist - array of pointers to matching keyword names -incolnum - input column number; range = 1 to TFIELDS -infile - the input filename, including path if specified -infptr - pointer to a 'fitsfile' structure describing the input FITS file. -intval - integer part of the keyword value -iomode - file access mode: either READONLY (=0) or READWRITE (=1) -keyname - name of a keyword (8 char max, null-terminated) -keynum - position of keyword in header (1st keyword = 1) -keyroot - root string for the keyword name (5 char max, null-terminated) -keysexist- number of existing keyword records in the CHU -keytype - header record type: -1=delete; 0=append or replace; - 1=append; 2=this is the END keyword -longstr - arbitrarily long string keyword value (null-terminated) -lpixel - coordinate of the last pixel to be read or written in the - FITS array. The array must be of length NAXIS and have values such - that lpixel[0] is in the range 1 to NAXIS1, lpixel[1] is in the - range 1 to NAXIS2, etc. -match - TRUE (=1) if the 2 strings match, else FALSE (=0) -maxdim - maximum number of values to return -member - row number of a grouping table member HDU. -memptr - pointer to the a FITS file in memory -mem_realloc - pointer to a function for reallocating more memory -memsize - size of the memory block allocated for the FITS file -mfptr - fitsfile* pointer to a grouping table member HDU. -mgopt - grouping table merge option parameter. Allowed values are: - OPT_MRG_COPY, and OPT_MRG_MOV. -minute - minute within hour (UTC) (0 - 59) -month - calendar month (UTC) (1 - 12) -morekeys - space in the header for this many more keywords -n_good_rows - number of rows evaluating to TRUE -namelist - string containing a comma or space delimited list of names -naxes - size of each dimension in the FITS array -naxis - number of dimensions in the FITS array -naxis1 - length of the X/first axis of the FITS array -naxis2 - length of the Y/second axis of the FITS array -naxis3 - length of the Z/third axis of the FITS array -nbytes - number of bytes or characters to read or write -nchars - number of characters to read or write -nelements- number of data elements to read or write -newfptr - returned pointer to the reopened file -newveclen- new value for the column vector repeat parameter -nexc - number of names in the exclusion list (may = 0) -nfound - number of keywords found (highest keyword number) -nkeys - number of keywords in the sequence -ninc - number of names in the inclusion list -nmembers - Number of grouping table members (NAXIS2 value). -nmove - number of HDUs to move (+ or -), relative to current position -nocomments - if equal to TRUE, then no commentary keywords will be copied -noisebits- number of bits to ignore when compressing floating point images -nrows - number of rows in the table -nstart - first integer value -nullarray- set to TRUE (=1) if corresponding data element is undefined -nulval - numerical value to represent undefined pixels -nulstr - character string used to represent undefined values in ASCII table -numval - numerical data value, of the appropriate data type -offset - byte offset in the heap or data unit to the first element of the vector -openfptr - pointer to a currently open FITS file -overlap - number of bytes in the binary table heap pointed to by more than 1 - descriptor -outcolnum- output column number; range = 1 to TFIELDS + 1 -outfile - and optional output filename; the input file will be copied to this prior - to opening the file -outfptr - pointer to a 'fitsfile' structure describing the output FITS file. -pcount - value of the PCOUNT keyword = size of binary table heap -previous - if TRUE, any previous HDUs in the input file will be copied. -repeat - length of column vector (e.g. 12J); == 1 for ASCII table -rmopt - grouping table remove option parameter. Allowed values are: - OPT_RM_GPT, OPT_RM_ENTRY, OPT_RM_MBR, and OPT_RM_ALL. -rootname - root filename, minus any extension or filtering specifications -rot - celestial coordinate rotation angle (degrees) -rowlen - length of a table row, in characters or bytes -rowlist - sorted list of row numbers to be deleted from the table -rownum - number of the row (first row = 1) -rowrange - list of rows or row ranges: '3,6-8,12,56-80' or '500-' -row_status - array of True/False results for each row that was evaluated -scale - linear scaling factor; true value = (FITS value) * scale + zero -second - second within minute (0 - 60.9999999999) (leap second!) -section - section of image to be copied (e.g. 21:80,101:200) -simple - TRUE (=1) if FITS file conforms to the Standard, else FALSE (=0) -space - number of blank spaces to leave between ASCII table columns -status - returned error status code (0 = OK) -sum - 32 bit unsigned checksum value -tbcol - byte position in row to start of column (1st col has tbcol = 1) -tdisp - Fortran style display format for the table column -tdimstr - the value of the TDIMn keyword -templt - template string used in comparison (null-terminated) -tfields - number of fields (columns) in the table -tfopt - grouping table member transfer option parameter. Allowed values are: - OPT_MCP_ADD, and OPT_MCP_MOV. -tform - format of the column (null-terminated); allowed values are: - ASCII tables: Iw, Aw, Fww.dd, Eww.dd, or Dww.dd - Binary tables: rL, rX, rB, rI, rJ, rA, rAw, rE, rD, rC, rM - where 'w'=width of the field, 'd'=no. of decimals, 'r'=repeat count. - Variable length array columns are denoted by a '1P' before the data type - character (e.g., '1PJ'). When creating a binary table, 2 addition tform - data type codes are recognized by CFITSIO: 'rU' and 'rV' for unsigned - 16-bit and unsigned 32-bit integer, respectively. - -theap - zero indexed byte offset of starting address of the heap - relative to the beginning of the binary table data -tilesize - array of length NAXIS that specifies the dimensions of - the image compression tiles -ttype - label or name for table column (null-terminated) -tunit - physical unit for table column (null-terminated) -typechar - symbolic code of the table column data type -typecode - data type code of the table column. The negative of - the value indicates a variable length array column. - Datatype typecode Mnemonic - bit, X 1 TBIT - byte, B 11 TBYTE - logical, L 14 TLOGICAL - ASCII character, A 16 TSTRING - short integer, I 21 TSHORT - integer, J 41 TINT32BIT (same as TLONG) - long long integer, K 81 TLONGLONG - real, E 42 TFLOAT - double precision, D 82 TDOUBLE - complex, C 83 TCOMPLEX - double complex, M 163 TDBLCOMPLEX -unit - the physical unit string (e.g., 'km/s') for a keyword -unused - number of unused bytes in the binary table heap -urltype - the file type of the FITS file (file://, ftp://, mem://, etc.) -validheap- returned value = FALSE if any of the variable length array - address are outside the valid range of addresses in the heap -value - the keyword value string (70 char max, null-terminated) -version - current version number of the CFITSIO library -width - width of the character string field -xcol - number of the column containing the X coordinate values -xinc - X axis coordinate increment at reference pixel (deg) -xpix - X axis pixel location -xpos - X axis celestial coordinate (usually RA) (deg) -xrefpix - X axis reference pixel array location -xrefval - X axis coordinate value at the reference pixel (deg) -ycol - number of the column containing the X coordinate values -year - calendar year (e.g. 1999, 2000, etc) -yinc - Y axis coordinate increment at reference pixel (deg) -ypix - y axis pixel location -ypos - y axis celestial coordinate (usually DEC) (deg) -yrefpix - Y axis reference pixel array location -yrefval - Y axis coordinate value at the reference pixel (deg) -zero - scaling offset; true value = (FITS value) * scale + zero -- - -*3 CFITSIO Error Status Codes - -The following table lists all the error status codes used by CFITSIO. -Programmers are encouraged to use the symbolic mnemonics (defined in -the file fitsio.h) rather than the actual integer status values to -improve the readability of their code. -- - Symbolic Const Value Meaning - -------------- ----- ----------------------------------------- - 0 OK, no error - SAME_FILE 101 input and output files are the same - TOO_MANY_FILES 103 tried to open too many FITS files at once - FILE_NOT_OPENED 104 could not open the named file - FILE_NOT_CREATED 105 could not create the named file - WRITE_ERROR 106 error writing to FITS file - END_OF_FILE 107 tried to move past end of file - READ_ERROR 108 error reading from FITS file - FILE_NOT_CLOSED 110 could not close the file - ARRAY_TOO_BIG 111 array dimensions exceed internal limit - READONLY_FILE 112 Cannot write to readonly file - MEMORY_ALLOCATION 113 Could not allocate memory - BAD_FILEPTR 114 invalid fitsfile pointer - NULL_INPUT_PTR 115 NULL input pointer to routine - SEEK_ERROR 116 error seeking position in file - - BAD_URL_PREFIX 121 invalid URL prefix on file name - TOO_MANY_DRIVERS 122 tried to register too many IO drivers - DRIVER_INIT_FAILED 123 driver initialization failed - NO_MATCHING_DRIVER 124 matching driver is not registered - URL_PARSE_ERROR 125 failed to parse input file URL - RANGE_PARSE_ERROR 126 parse error in range list - - SHARED_BADARG 151 bad argument in shared memory driver - SHARED_NULPTR 152 null pointer passed as an argument - SHARED_TABFULL 153 no more free shared memory handles - SHARED_NOTINIT 154 shared memory driver is not initialized - SHARED_IPCERR 155 IPC error returned by a system call - SHARED_NOMEM 156 no memory in shared memory driver - SHARED_AGAIN 157 resource deadlock would occur - SHARED_NOFILE 158 attempt to open/create lock file failed - SHARED_NORESIZE 159 shared memory block cannot be resized at the moment - - HEADER_NOT_EMPTY 201 header already contains keywords - KEY_NO_EXIST 202 keyword not found in header - KEY_OUT_BOUNDS 203 keyword record number is out of bounds - VALUE_UNDEFINED 204 keyword value field is blank - NO_QUOTE 205 string is missing the closing quote - BAD_INDEX_KEY 206 illegal indexed keyword name (e.g. 'TFORM1000') - BAD_KEYCHAR 207 illegal character in keyword name or card - BAD_ORDER 208 required keywords out of order - NOT_POS_INT 209 keyword value is not a positive integer - NO_END 210 couldn't find END keyword - BAD_BITPIX 211 illegal BITPIX keyword value - BAD_NAXIS 212 illegal NAXIS keyword value - BAD_NAXES 213 illegal NAXISn keyword value - BAD_PCOUNT 214 illegal PCOUNT keyword value - BAD_GCOUNT 215 illegal GCOUNT keyword value - BAD_TFIELDS 216 illegal TFIELDS keyword value - NEG_WIDTH 217 negative table row size - NEG_ROWS 218 negative number of rows in table - COL_NOT_FOUND 219 column with this name not found in table - BAD_SIMPLE 220 illegal value of SIMPLE keyword - NO_SIMPLE 221 Primary array doesn't start with SIMPLE - NO_BITPIX 222 Second keyword not BITPIX - NO_NAXIS 223 Third keyword not NAXIS - NO_NAXES 224 Couldn't find all the NAXISn keywords - NO_XTENSION 225 HDU doesn't start with XTENSION keyword - NOT_ATABLE 226 the CHDU is not an ASCII table extension - NOT_BTABLE 227 the CHDU is not a binary table extension - NO_PCOUNT 228 couldn't find PCOUNT keyword - NO_GCOUNT 229 couldn't find GCOUNT keyword - NO_TFIELDS 230 couldn't find TFIELDS keyword - NO_TBCOL 231 couldn't find TBCOLn keyword - NO_TFORM 232 couldn't find TFORMn keyword - NOT_IMAGE 233 the CHDU is not an IMAGE extension - BAD_TBCOL 234 TBCOLn keyword value < 0 or > rowlength - NOT_TABLE 235 the CHDU is not a table - COL_TOO_WIDE 236 column is too wide to fit in table - COL_NOT_UNIQUE 237 more than 1 column name matches template - BAD_ROW_WIDTH 241 sum of column widths not = NAXIS1 - UNKNOWN_EXT 251 unrecognizable FITS extension type - UNKNOWN_REC 252 unknown record; 1st keyword not SIMPLE or XTENSION - END_JUNK 253 END keyword is not blank - BAD_HEADER_FILL 254 Header fill area contains non-blank chars - BAD_DATA_FILL 255 Illegal data fill bytes (not zero or blank) - BAD_TFORM 261 illegal TFORM format code - BAD_TFORM_DTYPE 262 unrecognizable TFORM data type code - BAD_TDIM 263 illegal TDIMn keyword value - BAD_HEAP_PTR 264 invalid BINTABLE heap pointer is out of range - - BAD_HDU_NUM 301 HDU number < 1 - BAD_COL_NUM 302 column number < 1 or > tfields - NEG_FILE_POS 304 tried to move to negative byte location in file - NEG_BYTES 306 tried to read or write negative number of bytes - BAD_ROW_NUM 307 illegal starting row number in table - BAD_ELEM_NUM 308 illegal starting element number in vector - NOT_ASCII_COL 309 this is not an ASCII string column - NOT_LOGICAL_COL 310 this is not a logical data type column - BAD_ATABLE_FORMAT 311 ASCII table column has wrong format - BAD_BTABLE_FORMAT 312 Binary table column has wrong format - NO_NULL 314 null value has not been defined - NOT_VARI_LEN 317 this is not a variable length column - BAD_DIMEN 320 illegal number of dimensions in array - BAD_PIX_NUM 321 first pixel number greater than last pixel - ZERO_SCALE 322 illegal BSCALE or TSCALn keyword = 0 - NEG_AXIS 323 illegal axis length < 1 - - NOT_GROUP_TABLE 340 Grouping function error - HDU_ALREADY_MEMBER 341 - MEMBER_NOT_FOUND 342 - GROUP_NOT_FOUND 343 - BAD_GROUP_ID 344 - TOO_MANY_HDUS_TRACKED 345 - HDU_ALREADY_TRACKED 346 - BAD_OPTION 347 - IDENTICAL_POINTERS 348 - BAD_GROUP_ATTACH 349 - BAD_GROUP_DETACH 350 - - NGP_NO_MEMORY 360 malloc failed - NGP_READ_ERR 361 read error from file - NGP_NUL_PTR 362 null pointer passed as an argument. - Passing null pointer as a name of - template file raises this error - NGP_EMPTY_CURLINE 363 line read seems to be empty (used - internally) - NGP_UNREAD_QUEUE_FULL 364 cannot unread more then 1 line (or single - line twice) - NGP_INC_NESTING 365 too deep include file nesting (infinite - loop, template includes itself ?) - NGP_ERR_FOPEN 366 fopen() failed, cannot open template file - NGP_EOF 367 end of file encountered and not expected - NGP_BAD_ARG 368 bad arguments passed. Usually means - internal parser error. Should not happen - NGP_TOKEN_NOT_EXPECT 369 token not expected here - - BAD_I2C 401 bad int to formatted string conversion - BAD_F2C 402 bad float to formatted string conversion - BAD_INTKEY 403 can't interpret keyword value as integer - BAD_LOGICALKEY 404 can't interpret keyword value as logical - BAD_FLOATKEY 405 can't interpret keyword value as float - BAD_DOUBLEKEY 406 can't interpret keyword value as double - BAD_C2I 407 bad formatted string to int conversion - BAD_C2F 408 bad formatted string to float conversion - BAD_C2D 409 bad formatted string to double conversion - BAD_DATATYPE 410 illegal datatype code value - BAD_DECIM 411 bad number of decimal places specified - NUM_OVERFLOW 412 overflow during data type conversion - DATA_COMPRESSION_ERR 413 error compressing image - DATA_DECOMPRESSION_ERR 414 error uncompressing image - - BAD_DATE 420 error in date or time conversion - - PARSE_SYNTAX_ERR 431 syntax error in parser expression - PARSE_BAD_TYPE 432 expression did not evaluate to desired type - PARSE_LRG_VECTOR 433 vector result too large to return in array - PARSE_NO_OUTPUT 434 data parser failed not sent an out column - PARSE_BAD_COL 435 bad data encounter while parsing column - PARSE_BAD_OUTPUT 436 Output file not of proper type - - ANGLE_TOO_BIG 501 celestial angle too large for projection - BAD_WCS_VAL 502 bad celestial coordinate or pixel value - WCS_ERROR 503 error in celestial coordinate calculation - BAD_WCS_PROJ 504 unsupported type of celestial projection - NO_WCS_KEY 505 celestial coordinate keywords not found - APPROX_WCS_KEY 506 approximate wcs keyword values were returned -- -\end{document} - diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.pdf b/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.pdf deleted file mode 100644 index c022402c4..000000000 Binary files a/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.pdf and /dev/null differ diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.ps b/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.ps deleted file mode 100644 index aeb5f61d0..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.ps +++ /dev/null @@ -1,15458 +0,0 @@ -%!PS-Adobe-2.0 -%%Creator: dvips(k) 5.96.1 Copyright 2007 Radical Eye Software -%%Title: cfitsio.dvi -%%CreationDate: Mon Jun 13 15:50:57 2016 -%%Pages: 194 -%%PageOrder: Ascend -%%BoundingBox: 0 0 612 792 -%%DocumentFonts: CMBX12 CMR12 CMR10 CMBX10 CMSL10 CMTT10 CMSY10 CMMI10 -%%+ CMTI10 -%%DocumentPaperSizes: Letter -%%EndComments -%DVIPSWebPage: (www.radicaleye.com) -%DVIPSCommandLine: dvips -o cfitsio.ps cfitsio.dvi -%DVIPSParameters: dpi=600 -%DVIPSSource: TeX output 2016.06.13:1550 -%%BeginProcSet: tex.pro 0 0 -%! -/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S -N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 -mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 -0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ -landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize -mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ -matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round -exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ -statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] -N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin -/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array -/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 -array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N -df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A -definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get -}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} -B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr -1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S -/BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy -setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask -restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn -/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put -}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ -bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A -mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ -SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ -userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X -1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 -index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N -/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ -/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) -(LaserWriter 16/600)]{A length product length le{A length product exch 0 -exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse -end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask -grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} -imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round -exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto -fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p -delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} -B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ -p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S -rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end - -%%EndProcSet -%%BeginProcSet: texps.pro 0 0 -%! -TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 -index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll -exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 -ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ -pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get -div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type -/nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end -definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup -sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll -mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ -exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} -forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def -end - -%%EndProcSet -%%BeginFont: CMTI10 -%!PS-AdobeFont-1.1: CMTI10 1.00B -%%CreationDate: 1992 Feb 19 19:56:16 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.00B) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMTI10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle -14.04 def -/isFixedPitch false def -end readonly def -/FontName /CMTI10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 68 /D put -dup 72 /H put -dup 85 /U put -dup 97 /a put -dup 98 /b put -dup 101 /e put -dup 103 /g put -dup 105 /i put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -readonly def -/FontBBox{-163 -250 1146 969}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE -3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B -532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 -B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B -986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE -D919C2DDD26BDC0D99398B9F4D03D5993DFC0930297866E1CD0A319B6B1FD958 -9E3948FFB0B4E70F212EC976D65099D84E0D37A7A771C3101D6AD26A0513378F -21EC3643079EECE0C9AB54B4772E5DCA82D0D4ACC7F42FB493AA04A3BF4A1BD6 -06ECE186315DBE9CFDCB1A0303E8D3E83027CD3AFA8F0BD466A8E8CA0E7164CF -55B332FAD43482748DD4A1CB3F40CB1F5E67192B8216A0D8FE30F9F05BF016F5 -B5CC130A4B0796EE065495422FBA55BEE9BFD99D04464D987AC4D237C208FA86 -0B112E55CE7B3782A34BC22E3DE31755D9AFF19E490C8E43B85E17ECE87FA8B9 -1485831624D24F37C39BF9972D74E6EC4784727AC00B9C4A3AD3DA1C22BD6961 -7E0ADAF55422F22ACA5E4DCD4DF9FCD187A566B7FB661D0530454D0DD6C6C50A -7A3875C6CBF8EC7769F32A1F3F7FC1C072BADEC97794D4E90E0035282A170402 -356E5A9CD9ABD80AC4342A5283E458A7269252F4541CBB6452B39ED54D336D0B -19928E9CD1AB26AD83EB209E2EC75011A2643813053B5DBB0246097C4821B5F2 -C92554E9140BE35B2DBFCD98809A8EC9FC910FDE9E0D86457C70ACB056EBF90F -244DC0A5BBD455E15D6E3180311D52CF50B0BF7D0A7F64F3A1821E0AEDBC2E7B -AEB549FE1D51088C153799C6E089B5D5D65E1C4E2D2B430CDF1FFA23CCB25D95 -5C43C8942435D0AAA3D9055FF808F2C3C887A3C469BBD98F026D0A59E26BA9F9 -C2144CFE49A9AD892D4D31764F0AE3A10644AE3966B0A790684B14D11FA49785 -EC5565D2B2E584CBFD85125F3FAC133338DE35361943DCE9AF05FCF2840CE512 -998D42CBEC52B57B79DD63F00985881E8463396ADA47189A94DDF951A78866F0 -B8A3D9197E39335277EF2294308DA70065D910943A34F7D5F2090FB4AA42ED70 -CBA469A9F64B95A6FBA4BC89DBC93765E3AE4723162DF3F9D6BDE77DD5870ADE -C8900D6346957B84C3CE88A8F9A12D46B8FCA50DF4433B0B8AED6A63B3DA102B -6DF94E62408E24154BAAC66B2B249C695BC0FA37A28699D9C0F3EE94AA32E3C5 -8F8D7F803B5D25014D43A353D719B14B247A87898A960DF68C0C0BAF70C83917 -6E9F7B3ACC64DBAEF3FDCD3A80C0AB907EE342E543D607556CBE5A9089B86D1D -E768F27D74A613F3ABF883222A8596B542EBF54E9DCE327B5682AEE5F6BCC38A -2A052EC4018AE3189DC1963BA39ACDED8F0C60C83F8873FBBF0302010956C520 -A7F3F8ECD0F177EDF5F4D5522C5984A3678FF32EEEB570B69C142AB89467641F -917155D646DAF3352E27BF2AA0746E062E48532256AF364EFC0F0AAE3766F75C -5219ABA60BDFF177558536E000DE3263A4A6EAAA669F9F4E94BAB336391AF5FB -280A5B39995483E788CE4820EF77AECD73B1AE89DAC3F13E333F2628CDBA431D -2A5E547D4225E6BE13119660BEBC155823A51477647F7E07A23D7D24353F584B -2B311C4529E0E408B4E89A467BC03794CF4E7AA0A717A8247D5B60F438417D01 -8155F17E09D4C4FECED18CE574D6849640E5E0592D771F026BCB0CE66FD13BC9 -5A89D07EE26021FD5DF14B96AEDC02AEC3E099088C1DAE4FCA2AE841B17F5C4A -D251FB56462CF050AD3CA84DA12DC1D17F80301CCFDE6C35C81FA538A389E0B6 -8BFF0DDC4B97D49B485E8C6AF47F951C042D2C750748B4084B3F4AC18488EEC2 -900A9672A6CA2B06A0F091E8DD9DFE504A5C6DF1537AE7F54DCFD94EF5CC663A -A80E1C64CF1CD751D28858CDACA6F7CD0463A86619E87B9C03C9448B44537E78 -5E60A25045FBDBEE678737FA45F029D92908443C7BB9FC87B7B280C314F39A96 -B5287BA21CB3EBCF7816BC0900095F3F9F11D7774BC1D1D4A7F8098C610E3FB2 -C2E2E9D9DAAA6CD1EE4F35CE854B7C79DF8318CCC10C52DE36E4AC5D75ED7D8A -DD4E8A3B827DC8A7D437DD38B782929EA60CAC4930F9711087DDC18574B472FA -B40DEFFED99BE0C0CA85E9FA2028152C8B6423CB94E797E3651043BE9636109E -87B70592852FD5198A7D340C0E1C419D0EBAEAF483300E41A6F6B1DFEAB071CD -A4E0A596509369A4EDB66ABC883443FC615AFFA74C672922D263B5F64E861C6D -C44E9C0BBBBA305C9AB04FAEB77E0C25C0D67F77639F6022D028847E796879D2 -B6C4AB4313FF3568E407784F1E00503A5875DC68464A720C8E55BCD80269B4DE -B3C05D49DD15B581554B61E9D6313D47C39991582BECB1EF6E959CC64167DA7E -F98EB7F130EE821FF04BB4842D3B8F23E81C4DB8C4B340EC9807DA0CC2627ABE -9F1505EDA580A499BDC35E348CA6A15FB197597A5A3E519DF0B4749D5DC67B8E -2D93EA98498CA6129C0993C0A6945A5137CB4A1B4B38A008B1559D719681E6AC -09FAA1D2337E266FDC02D77AE822DC13724A0620C5ABFDA9402D3DD4DCB80CA5 -28F875133862164328A59F7E58E36CA06F23E651D8BBAA490D145F3788A30BA9 -C5389826A4B2F17E2B301BE89C464D9888C1E798744E815C44E68B94BABB8FC4 -2872E1AFBB63CA489FB1504926C84C5F8AC7E6A93942C3B0C3250EEFAFF70449 -3734AA4932BBF7B098C8287D8DD2F0E75F0F7B184BE5A24A6C9EF1C7CE86D58E -1018668396EF8842609FD4C207CF3D818DA21AB4FB96EDEDF11905E15153D319 -93EF1A3297FB71AC25E9FEE544D66A2E6D94D147408033B1784D060EA8BD6807 -1A2194884CBEFD552D52B7B8B63A2A9A1DE5C4B437262091089497D10E4C1678 -52664B16F1FA71371BDF96D038FF88F695A02B7057DB4D97CC9AF8534518BE9E -FCE87619AD6BDAFBE6EE8FDDE427D3CCD32E4143AB09B27F559E7727CEF7F39F -DFB7E07E86E3512757E64C82D0FA29EB1E00E4F213B12679E2307BA8A363BBF6 -B3411F4C50A8E51A11D6716CB5431B6B941B5548FCA3C85B3829F7EC05D881DE -4D2E994F6C815589CB4F5188A581FD9BE70E9D01E8F36BFBB5732F89DA7651FE -9F20A732F94035BDAB79728D559647EBC1A386F7BB3489D59BCB048910AB9D2F -38F9B3B9C0648A9AFA41B4089CE3EF93E7E8E5140532EFD745AE3F000502344B -5030FC71BAC616EF9349D5C8B336FA9A3624E1D2DDBE5C596702F778FD9FA98F -5899447510DDCDE2599939667F9831B6D06ED3CE3167D15F9C502EB035A05B86 -D4AA82D68A8511BFD3312250273545C5C4355629DFEE31B5A1B078BC2C805305 -22A3F4865F9C978C6E71A5F5C858E21CBA36053277190DB9D89A4B985FB916D8 -DEC338E997F3226EAFA917AA18C1C9B055BB82DDDD50FFE00B93DA5C9C662760 -7326F16E661443A6EDCCC04FF913605AD63E022EB96C7C9A7FA60E185073E163 -0A61ADC0E39B114BE69EAA874209C8713E765D017A8D727648B0340295D56C13 -34A95D3D2F40CF4CD2BBE527C433E09F00BC1BD5C7425E4DB2A17204F0B8DBA2 -82CA3F37C424FC07B69C89635DFB3971894E946D928802471C2B1C40F49701FB -485186D20A803C0BA76DFED4ECB2446FF25258118E593CD1EBC8ACA718B5C9D6 -C4F5AC941B28716B10B283FED21A16C94E92C431BFB9C8AC3D3F1EF7DC46ACCC -A82ACCE510A3F687AAEDC6839800F48AC96A5B81A97FE4F37CAA586969AB3D58 -001C8134BE160EEEDB79A780D2AA57BEEBD2FBCD9A453066B6642C459A679A84 -5E3FB8F50F7C00EFDE6049D2C01893750C5F60F2DC98FC36F2E656774123DFF3 -E4EEE44D085083365124889B3103DFA03F5A5648446BDDAC9FA40C69D83D2D4D -0D6017D7D840A4F7CD97EFF126F48B331CAF5DE0856F689FD0FC450005793C8A -74EC6BEF32FF405AA2F4F6ADF624E0C72CEF916ABD6BDB7C0AEECEA855F07AA7 -E5BE6F7DCCE459F4F390965C9350A3060825CE22CC25905FEEE40E4973C0189E -5021FF9FC2EAB4301790F255B617638A2C44F4D71A74EE96DA5178A9296D388C -0D43CD188C0F78D9A57D78EBE390A2BCCD0AC3087AF4A1273443795EF08D0F11 -ABEA3A173746C05E538D88FBC0A3A1DC82A762F951E63A135F63BC3B7E05B8E6 -B89DF17BD32E871FE1C967B5DA4FCB9187747B6A30B551B9C4FE920C34E40A8B -E268ED41382AD1DED7E79D18469F58305CE1275C4AFBE4770BCD87D06D7101F7 -5EBF74D9F3AFF9608BE5736BF1B2B33B4B3E3C8CFD3A91CECDFCD7E0A4A586FC -699EE79D7756E49DD686C65451A58BEDCF0FEED1B23EB408845391FEE74A3628 -11837485BDE72131D0EF7D0EDA3E23BCEFAFF9DC2616CBC8E52523EA157DF140 -9498280EB11F1C42B05BA5281F7ACE1BF40F74F3D5D61A6B852461013F773915 -0BA29094461022A1F1AD4B62CD619E6BDE7CA645914ABDFE87758C039B3C3848 -04BAF878C215BBC35A1D259B2CC21AA2B7C7B43165398CF37779B31190DC8526 -41E02F9361CA8E7750A39478DEAA823069009007B53FCBABBA40A98C90E603F0 -C76E3383938422548A9A49CD8D9CABEFEC5D9DB27F60303DE67AAC2E79EBE12E -48A2D6B687A720D73169236DFE597514C656AACF348201B76008714FEB551241 -5F2C86E06820109386E5588A7E67651C1EA9422DE9307BEEED35E87B6B61F0DE -3EE5C5B7FD94350FBB081378191539122C6A73939BA7D47AF08E54C5CC4553DA -420E9680BA4B954D9BBE82A8FC559C86861760F9B24103493A26FB55E2DC7880 -5ABD36590011431ED606491093B769CA74AA6F8B91076D6D8368BB39D4C7B435 -CC461A9E9FBDB28772E51AC2C563DD42C4A87F7A544C8B6D10D5D2504F9A4BBD -D4F1A5A6DF8278AB6F3B10214AD75FEB1B5E32801D2631983E2735BE149FAFA1 -560E57087EAEC3E45526DF9C748F42E6540CCB14DE6DD11509F3F1BD6D5B3BFD -3D59D2EDB6235DEEE1A893F522497EC38CEED07774E8B23AFC381D6432B87015 -A586224B9EC36C4498624E5CF2E9BE61FBFF52F479F4CD12A717C0FCC19182B5 -A5A9F8D415472F4C61E8965AE972EDAC4A17776B6EC1132CE29D6396D2B01B6D -BEBA1ABD3273C62B3475E2DB8B57E61208AC63BFF8CCE2BA085321FE0C9F874C -A645C234812D75E9C5C02D0B0E13D57725D105724BB2C5A916F6E82D57D005F3 -9F6B1F041A2B9675AF901B171E6E896F5B8FC545BC88E183AC5E5F1B2288CC5C -7351BAD140CBFA03F2FD18298551BDB15024BCBE844B418B067208EA0A13B731 -58747D1B90BB00E37FD7DF9FFAAC80DBDD92E1301DDF1ADE62ACBF169FBFD927 -AA84D56E00D02D5B8A34FE3D2B1AAC470336AA02062F42F2C958307142F7C6E7 -BD440AC8D8C6A46DFB2B42A32BFA4255A47F3CB3F0733F294EB47AA59DD26A03 -C81A4BD18162EFCB77F3BBEC3E8B225E76BA51DE178468B529D146A544180542 -6EAE3A451781F5E38DF15BB377C9FE92096E976AFC14DADD11581D29222948F9 -FE23D981CEE4E5013025FF3E69E479D32A7A8D25A842FB288A0EC63E23E297E0 -168D22FEC35E333A2D67A37A4EED7B59A06F21F44DC6831CAFA473E48A66EDB5 -00FEC1D5399A06F51A8A67A6803FE34C1B1F2E4CA8D7EA3CFA8BD046D477777A -D283296A8F181D671CBA5B9793DE178BFAF807A6F71E4FC6D69CE7CFEF11D0B6 -F8B23221E627475226706C19EF519D19B80633DDBF4A1AD9E271E547CCC846B3 -859CD96E495D12E3D5557A309F12949ACF5F373A29C0FD4A6456C737E6F08BDE -0A0C692D66BCE059ADB9B91F8F81975308ECB3313B34093E06462C9DA76A4BB2 -1D8DEB5E4526CF73DA4D9D5CC7148E5FBABDF1D45F024469B6D84BB607BA975F -1F6EE627044A93D108427B6C14528B5C6D1568E65F3450D7F4A37EE34D619138 -8B7914C63A362737025C0E57F928AB5741CB79D137249914A3CEEC0DECFF639C -0F6B8125C643EDA71F2945FC7DB555E4ED2896C49E83D4515B0DA9A72764C792 -9D6A72F18F15C71BB655DD64E421EFF712865D45D2642C7E63501F3289D589FB -B983626C60523142AFBEADD4019BB3C4D9C6ADD66012D0CA6AAB374FCB7FF77E -89BF30C153007F48E06EE2278BFF6F0C9AD9BCE6AF9A9171A58EA65CBA2A6A82 -E35D45980D84DE7D9199344686C8F08090DF43D0051C15C4E19A9D1C76E4686D -7412DAE7F6EF4E86230C43187D1997E98010F6C8E5E8941DC837C6E73E9C0947 -AD2B9E8333BE73BF30D56C31E2B76DE3F6C841F42B109270CBE04D10A9D64CE9 -0FB722EC4FCC3F1EB7CCAA2C6C6B3D285D786DAC189F440F32057CFC882A6257 -3068C55D4470801D8E2D6B5972D30B54C54E -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMMI10 -%!PS-AdobeFont-1.1: CMMI10 1.100 -%%CreationDate: 1996 Jul 23 07:53:57 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.100) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMMI10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle -14.04 def -/isFixedPitch false def -end readonly def -/FontName /CMMI10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 62 /greater put -readonly def -/FontBBox{-32 -250 1048 750}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE -3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B -532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 -B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B -986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE -D919C2DDD26BDC0D99398B9F4D03D5993DFC0930297866E1CD0A319B6B1FD958 -9E394A533A081C36D456A09920001A3D2199583EB9B84B4DEE08E3D12939E321 -990CD249827D9648574955F61BAAA11263A91B6C3D47A5190165B0C25ABF6D3E -6EC187E4B05182126BB0D0323D943170B795255260F9FD25F2248D04F45DFBFB -DEF7FF8B19BFEF637B210018AE02572B389B3F76282BEB29CC301905D388C721 -59616893E774413F48DE0B408BC66DCE3FE17CB9F84D205839D58014D6A88823 -D9320AE93AF96D97A02C4D5A2BB2B8C7925C4578003959C46E3CE1A2F0EAC4BF -8B9B325E46435BDE60BC54D72BC8ACB5C0A34413AC87045DC7B84646A324B808 -6FD8E34217213E131C3B1510415CE45420688ED9C1D27890EC68BD7C1235FAF9 -1DAB3A369DD2FC3BE5CF9655C7B7EDA7361D7E05E5831B6B8E2EEC542A7B38EE -03BE4BAC6079D038ACB3C7C916279764547C2D51976BABA94BA9866D79F13909 -95AA39B0F03103A07CBDF441B8C5669F729020AF284B7FF52A29C6255FCAACF1 -74109050FBA2602E72593FBCBFC26E726EE4AEF97B7632BC4F5F353B5C67FED2 -3EA752A4A57B8F7FEFF1D7341D895F0A3A0BE1D8E3391970457A967EFF84F6D8 -47750B1145B8CC5BD96EE7AA99DDC9E06939E383BDA41175233D58AD263EBF19 -AFC0E2F840512D321166547B306C592B8A01E1FA2564B9A26DAC14256414E4C8 -42616728D918C74D13C349F4186EC7B9708B86467425A6FDB3A396562F7EE4D8 -40B43621744CF8A23A6E532649B66C2A0002DD04F8F39618E4F572819DD34837 -B5A08E643FDCA1505AF6A1FA3DDFD1FA758013CAED8ACDDBBB334D664DFF5B53 -9560176676ABB71BBD0EE56B4CC492C0652750227CEC7B86E4740EB7B8775564 -332769DD30794E501BBB0E4E5CB665F3628E10B1137CC8BC5C0A64A310B5E27E -5FD6E3B04DA3914C15987E638A72790AF4073CE9CDBF6E3C749CB4DFF9C54951 -A58C386C54BC4E98B102B5E91E8567D2EEEF048F2CBD5D243701D20909290B4B -A3083F632D8552D42DEE0C69A4B14D8B15AA082DECC12B2ECAE6F663E6D09F81 -EE2979EF41FBF12C9D8BF23B77E0A20088EBD107C5BF9DD6F03FFC3AB65B69A7 -54953327E1D4AEF5A146273392BBDB321D4CC9A8FFFCFE5C515B466E21546CC7 -C6209E5A76F916B03DB98BC6CED334F33E7B373D42761696F5A876CA6F93F16E -15A07E2E102148CA4F62A99C -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMSY10 -%!PS-AdobeFont-1.1: CMSY10 1.0 -%%CreationDate: 1991 Aug 15 07:20:57 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMSY10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle -14.035 def -/isFixedPitch false def -end readonly def -/FontName /CMSY10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 15 /bullet put -dup 102 /braceleft put -dup 103 /braceright put -dup 106 /bar put -readonly def -/FontBBox{-29 -960 1116 775}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 -7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 -A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 -E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A -221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A -27D1663E0B62F461F6E40A5D6676D1D12B51E641C1D4E8E2771864FC104F8CBF -5B78EC1D88228725F1C453A678F58A7E1B7BD7CA700717D288EB8DA1F57C4F09 -0ABF1D42C5DDD0C384C7E22F8F8047BE1D4C1CC8E33368FB1AC82B4E96146730 -DE3302B2E6B819CB6AE455B1AF3187FFE8071AA57EF8A6616B9CB7941D44EC7A -71A7BB3DF755178D7D2E4BB69859EFA4BBC30BD6BB1531133FD4D9438FF99F09 -4ECC068A324D75B5F696B8688EEB2F17E5ED34CCD6D047A4E3806D000C199D7C -515DB70A8D4F6146FE068DC1E5DE8BC57030ACE57A0A31C99BEDB251A0ECAD78 -253AB321023D15FF7F55A3CE81514C1E7E76240C1FB36CD4874DDB761CC325F5 -D588700B294849D690F93526EF438A42B9B5B0508584EA3766D35F5B8D51C458 -ECB9FBD23A49576EAB06BACB7EA6D300985500835F4FE597D4A1110C8EABE6FC -CE3E1F95CFD3A42446F25355381D476B2FFB6EF247BF58A6FFC5EC0E4CC207BE -46485F8E07350B37DCA8C1864E62614332A1D3C9DEDDD6492181949A2C3498C9 -EC2A81C1F4FF989A4654E375F509D24D969B97D2A9940FAF43BBB286E08559C0 -F8D9674B0A294B36D3A050F7DED8C80E1D230812F6B8387B17948FD29FF050E2 -AAC5EBE5D96AFD0879534E2F4BB81613A1571750F9CF4215199F93813D815B5D -1C79E11A0FCBB627CDE569F88C741CD502627777BB058ECAC09B6ACCFACA69B9 -8F8168B0B5A1A6EB13E884B348FBB2ACF9EB180F6E27D57F8503710CE037A34A -F8B157201657C825E2A4B4A7696B58B7A988C05E43E66F0FF277A7694C555C54 -AFB1D32F6DE102136FC810E1F3B5CEA42476EAC7AAFB390E3252B2169DCDEE6E -328507BD0E24734A85AAA263E0D2F64BE1607455BC855785BC27F8B30FE917B4 -23AB3C812975355942E955501AF85A3C0CE836911AF679EA44AD6A7D042A6549 -0C471FE294E8490024D93ADCADED460FAB7FBCDC29EFEBD2A9A127E11869E659 -961B29206CE63944B6FA4B9315BCC528EB1E0223CE94C795A5D5231A7FC8545D -6B287B965F8EEDDB67A6774129DD01D5A21694ABE320BB2553043D4C42ACFF91 -1009372CB03381035BEEEEFD05631E026A0980A72A67B3703323A4E7C94FFCEE -8D0B7407F9CCC043D3D184BEA4728385D6AB2FB0641DD8F5BA7E04035D30D628 -7E97D31C1486DFD5B1D076B84B4ABA4829ED4310321F1F24B847C44E00185A69 -37711A -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMBX12 -%!PS-AdobeFont-1.1: CMBX12 1.0 -%%CreationDate: 1991 Aug 20 16:34:54 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMBX12) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Bold) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMBX12 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 11 /ff put -dup 12 /fi put -dup 39 /quoteright put -dup 40 /parenleft put -dup 41 /parenright put -dup 45 /hyphen put -dup 46 /period put -dup 47 /slash put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 56 /eight put -dup 57 /nine put -dup 58 /colon put -dup 65 /A put -dup 66 /B put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 72 /H put -dup 73 /I put -dup 75 /K put -dup 76 /L put -dup 77 /M put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 86 /V put -dup 87 /W put -dup 97 /a put -dup 98 /b put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 102 /f put -dup 103 /g put -dup 104 /h put -dup 105 /i put -dup 107 /k put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 113 /q put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -dup 118 /v put -dup 119 /w put -dup 120 /x put -dup 121 /y put -dup 122 /z put -readonly def -/FontBBox{-53 -251 1139 750}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5F0364CD5660F74BEE96790DE35AFA90CCF712 -B1805DA88AE375A04D99598EADFC625BDC1F9C315B6CF28C9BD427F32C745C99 -AEBE70DAAED49EA45AF94F081934AA47894A370D698ABABDA4215500B190AF26 -7FCFB7DDA2BC68605A4EF61ECCA3D61C684B47FFB5887A3BEDE0B4D30E8EBABF -20980C23312618EB0EAF289B2924FF4A334B85D98FD68545FDADB47F991E7390 -B10EE86A46A5AF8866C010225024D5E5862D49DEB5D8ECCB95D94283C50A363D -68A49071445610F03CE3600945118A6BC0B3AA4593104E727261C68C4A47F809 -D77E4CF27B3681F6B6F3AC498E45361BF9E01FAF5527F5E3CC790D3084674B3E -26296F3E03321B5C555D2458578A89E72D3166A3C5D740B3ABB127CF420C316D -F957873DA04CF0DB25A73574A4DE2E4F2D5D4E8E0B430654CF7F341A1BDB3E26 -77C194764EAD58C585F49EF10843FE020F9FDFD9008D660DE50B9BD7A2A87299 -BC319E66D781101BB956E30643A19B93C8967E1AE4719F300BFE5866F0D6DA5E -C55E171A24D3B707EFA325D47F473764E99BC8B1108D815CF2ACADFA6C4663E8 -30855D673CE98AB78F5F829F7FA226AB57F07B3E7D4E7CE30ED3B7EB0D3035C5 -148DA8D9FA34483414FDA8E3DC9E6C479E3EEE9A11A0547FC9085FA4631AD19C -E936E0598E3197207FA7BB6E55CFD5EF72AEC12D9A9675241C7A71316B2E148D -E2A1732B3627109EA446CB320EBBE2E78281CDF0890E2E72B6711335857F1E23 -337C75E729701E93D5BEC0630CDC7F4E957233EC09F917E5CA703C7E93841598 -0E73843FC6619DE017C8473A6D1B2BE5142DEBA285B98FA1CC5E64D2ADB981E6 -472971848451A245DDF6AA3B8225E9AC8E4630B0FF32D679EC27ACAD85C6394E -A6F71023B660EE883D8B676837E9EBA4E42BA8F365433A900F1DC3A9F0E88A26 -30F7B5CE2041568C18D8F66D36C31B003C916EC14620F67D695D846F2EF97CB8 -0D569CB47D8939FE3C0009749B48D0D9856FA050F2D1BEBE2DD68DDBFEAFC2ED -7A7BA881DF4859A0F43EF10EF5DC41B5E82C630F2E3E435E37DCD10B63D3C96A -38C0C5AAE886D864E24FDD862D6957C084CC4A39623629F00DA0F035DACFEF70 -4D8DF7C197095975D874B919691A7E03C56534645AB63E6B829038B435E1D2AC -2ACA8A5E4C2DBD300F7C786A9C196539C8BE8A6FFCC109193E97455DBB0B9E55 -941992A110EA4BC1B01B59EA538E6AE0749C24D452C351F13B1F64EF2D199563 -F88F92BB8C6C8EF4ADC5ECDA3C2BD22CCF84431E43BC5A630332184CE06454E5 -0F3A369D5B7B134E0CF54E4804F28162048BA9B8A03FD837E2C37D146EB0F14E -7DD93363EA5C819AC95F2C1501909E9F4B3A09CCF2C609F0A6EE86D340A19408 -6F985E999EAE40D936E3B0BF5D646941E5CE26E1AFAE1EF59329EA2E24EDBE17 -8B9F15CEC308AB6169A683CB3D56DE572DA21974D80181D7BCC09E8E08FFE441 -0F93897DC162D782209CC451E553232680F997451B1CB2D8AA0CBF5DBB7EF923 -1C7AA87DDE43C47B188B502C42FD3F47D73811469BC954267ADDAA9CD18D49D3 -2FB55FC5555338B4522F0A7309E487DBAE445E3FB3489EF7E396835B3FED2044 -5CCCAC17D69B0A1434958B658891E8AB16A992B77357BD4BD58A9251F50AB71C -B930D4652578C79C77D9083C420C895C83660D7FE13611BC7ABE5014C7CB5E37 -62E71B7D3E215A8A7E51F9E4F3AAAB983FF93E49CBC1EFBBB2FD7150FA3E4745 -5F8FC1DFD4A245586A56DE187584046746119E1F5770D83B0785427BDA36111A -881107BD4CDA253D2972687F010989B6FA7EED5836B377EA92906BFF453EA308 -B4BF3287D966E98262724C896177F042966FA9666CD0C628C648AD6D8CBD23B6 -6124005200490FB59E771E158055E93489A2D4D2447AF36988086AD21E8737E7 -37B21FF521B78B92B5DAB8685B1249B8E82915B06DE48E1979EAEB8E02952345 -53EA9181FD43C6F136FEE9286525F50ACC9236F602B542A36B51D511CE03EA9D -7F4E668FE9B7BB18A828DDD511C9AD2AF80B1D2F3D895D262C5FB883B36A4407 -671EDDD228337CCE4DEEB68FFF6D46D9C87F577F60445962A97BD61549A5F2B4 -F70E95DCCE8DA63DFB836F5A7901110B51B950872C8AFEC0495F51691B13DB31 -B84E89B8C7E6D0132A26A348C2804887685803DB72B8C3223AB655830BCBAC24 -2A3E989E13C38FD950B03977C2DE7BC27392A24DB30AD71D26E0969AE9D637C4 -4247FF262AA189818067A8D3FE7F042E4DC47CF6D21504A9F06E440F79851826 -ACDC43F89F482C220786BD85AF276D394B8D523C7675F57BE80E28F29A81EA0C -9875EE70C69D47EAF98963FC3DD370FC270A606BBD9FC16DC1B93B1179D810AC -F634883A2661B3B2DD26E0C24A6D8B3AD223FDC7251296A614D88F8860EE5031 -7E5CFCC7233D3397830A27DE6E5306EB074FA6698087E86A8E1F144F43FD3937 -0006B492CB5455EBEF58A9AA34FE66F5FF36B04A7CFAFE68F490854E2ED08EC3 -1E5DA648A76CF178AFC6C05813E88E1C84D9AF826DC9583A04EFEEBFCC351B65 -1C79FF12BD7D2879D8F4521E448757B3B2B9E7265FCD9D57D24A633E04676DAB -AC9B44A4406714856791692D23208139BC39147D57E4B1A9CC0CAFDBE4F2F6F8 -87315413CC58B8ADA31B15A17226AE0AC8F047F7C7D9550D820B23994438FACB -CC4C65A302F033D1ABF788848EE63E6DF1590B586DF40050A800AB7E535963A9 -18CD7F6DA52414A4EBBEBC24B83F824C0B85C3BD21401722E16307553617B597 -0DBDEFE85B9086F522FDA0C43FB27C14CB9621C75D8254B05E24C87D754B347C -C9BEA9F2BCA71B37E3F6A67B0879BD67E8509B5786DBB025AE6159A7CE5143C8 -0903EB0D6E6E40C36474093076EA17C554021D4C95A9B1AB6FDC30F5BAB2DC99 -CF5699757E036207867F75F7FF2266A806E6581724493EF360694831C58925BB -E271C8202068A9B9EECEFF854DB4D744102A902B913A1770A2A628B9B85048AF -697CB3CBEEF4F8064DC93E093A6D9637179265FD5ACDD5E3A9C406E8BE70F30D -EDAF394FCB91BDA810D1C5E4B472F60E900DFEB45AAF82983A714E860548B737 -BBE318EEBEE76B2063CEF47D7FA895A0237BA314DBF4E3A589B0DA21BD79F475 -52E5F674985E38B21D07175B9CADCD3B5FF64E5A4ABC1D21D9E50B6C33A1828A -05E23D11398E7B56C1F8C5636575AB08CAD336F2DC2F9418BB0FBCC0166C5D85 -FC062E82DC0E55C41C6C682ED75A78195C6FB552B19637B53467429726264132 -943CA57A8C30D1E31A67387B679827443A52C4557DB9DD719D9FEC539CA09D07 -47495060C8BFF195E7770D0B2F4DA353D7E755C853A7B9E9DDE5AED20A7DBECE -8569A8D9E5AF4D15388D65A10D055DE7EBC2E295073A86D082C2FFB2CCA7206A -7577BFD6E506D29F19452C3B2AF45D5531C0E1419B434F30ED32657A9DEE4C73 -604C3E5F239137F49958F5CA638964DB763BBDE618818BD4EB23E57F1B250D11 -B185093107056D2D4B6D53AD2BA245E121E3E206770CC01D0E07DDB5D00CF858 -48F23AD1CCC23C42DD9F25AEDF3029ECFD31821A734F83B7C9F94AF3E6EBDEB5 -686B484475F0AA7350856F9BFAFA0EEB9BFFA02E5CD0D8FDD562909539F89BA4 -505A45D79CD2E7587EFC5E579EDFAD3661ABA956C7AABC46DED840EE00370EEF -87C3C48F109BF3FE0CCDD17E2B9974F817A08A8BEC4CDDEBC43F32F685F33D20 -F3106584C83714D82D494C4721400FB88D7E5FACB331DFAA524553B401184571 -E7F2C4F954D586D03F4685CA6ADC774B8E24FFCEF33094842A5F226E7D681B27 -330F84BE13747EACEC6CA5D94F7A2C2E9C47EDD05B163A1A25FF78361F3FEB44 -20D6BD2DE10AD0F093365AF1C00CC88D15443A21EEAC4EAF1F50D5ACA6ADCD81 -D39D91A142999F33FCE4DC572BE9FBEA9F0BFA142976F2BCA7A6897135AC6E7E -D0435DABB724E2193489F87A87D54384B3CBA6395E7DE36AF07DB326C77AC61B -C9CD52C77A5A82A27C19D32D18B6FC17C1E6D38044A9DB4BCEFD8E05C1B5042B -4697173EA5ADCE6780871152B742AA7CEE0220663CC5C3AC3292C660FFF93286 -1E50DB297296156955D18DA85931CCC9AB9E0BE2157ADC1343066050C7B735FE -130364B736F6521BC4560D44437C0D45427C207AB54F70E2FB9A0C2EA2436191 -0F87B91BD3596F690335206069FA66A6BB08DE89C799966DA5C9857AC2F1339E -E6EFF63FCAF48D50CC130AA95B9B1EDE2DE8E19A98E9A8C93E2EBF60889081E2 -5C5D4C9AB8F800A784F1174595874A39239E74F3F5F8816E024F631CAF136E99 -39FF5D4F7FB5A4CDE1B57DA67AEABD4A41FFFA0AA4B210351EC5EEC22B857397 -9CC04CDAEA7D7FF4BB3C3D771AF80E630D7AB58097BDD1A037E40194452DDCD7 -376AE54B39206F76767460B9AD86530743BC63884C46F4577ADC62F19D38232F -1D80EC752DA6B4C8455A26574DF01D2D9686B7E75F19BE1A5A8758AB7B827ACF -0F8D395E6C18A6D591E01863DDB7BB7179FAB3F2C82D24F46151CFB8AE22F53F -4177189C80B26FA893E006321BBC6D9AC9817A1FBE4918F8A1B8658C35AC32D5 -335531F4F907143CF7F190991DB7E243F4CE9199E6E46F26F16E00325C395670 -330829D5AEDEA76337D4A9AD1C3A30AA28E56B40019C0836B4FC6BC22097FE3E -86175F36C3A5A879B9C700C50FFFFB6B7BE1361211E1D3F3BEB39A2267875463 -CDD79C44BEE54CC30F78BD48BC1D2B3C96C6D2D1D2A8484703C4727657E6C544 -C27C4ECFCB7090EC465D3E0C34BED015A0B017EA94FE7903C021580B83AA25A8 -307E13BE4FE137FD505749F447C2FF77F3039DDDFC476D9553BE3D3884E81C4C -03123E78FFAE5151D3CBB0473CDB4F083AA5FB0B1BA99A3AD5F49AA87B73282B -5084873CA47BAA9D1E0385C9D4EA3498AACECDF6A6A0EC09EE0520C9FDE792C3 -07FABCBCEC2B7474A6241099D6362C9436F32FBAF1D6CC11D933D4A64E0CB9E2 -0943E082F4335F23E7E2C719ABFB70D7C9F48C6B88E980CA8A980958A308E898 -BCC7C4E085167F33BC36349C0CC23B004C805DF196581DB0C551C2B53C82E948 -EFFC164541AD80E6014A723760ED548F3FB0C47F4459D855211824B04D28D3DC -18E204F3A43C5F8D489920CAEBE3FB9800061827656FEC3C43BAA4219978FBFF -85507FF60CD5020365D73914861254547B36171070053498052CA13E1CCE5C70 -B9ED44737D747DC28DA6FBB7791082C572BF8362C3D3E34FFB285AAFFBC1311B -ADF12AF9444E47D85B0169E851C2C35D8D089A5ACF6A2E9C94085ACDE361FAD2 -B54B901EF8ADD09B1835B37CC6A5509872AE193541685EEA1EEA3770A1FD6318 -DD7328E8CC51F099858659BFAA708541AB9E21CF1632458164B5E8659F6C23C6 -88C0FFE47B820388404D0E9FE6CB06195BF2B2444582D4B7B38F45E18B604639 -A0750219065C18492E2CDEF4BF96E2222A5D11DA68C6765565F9DBDED8F95F3E -7F2EB79DCE1C679D0743C5BDB832AD24C9B747AC4FA27D1279419E732DEEB543 -BEE45F538A500AE50151C16C81346B88AC63D707E50958536C3CAE834A27E77B -AD95CEBDCE16FAB65DF308A0D34EF798078BF8FB0D03DFC782449C0BEDBC4AD2 -5FDDF493FBDA5CA3641F4392487887D324A047904B1E033027143232A40D5014 -DE1EB3E58C535A317733EA1D93C33A252CF750A9EEAEDF6313B9CE44373A288C -EA8DF423F248E3DAE7DC96A211659305C9B97946AFDB3ACFA2B79F05CCD03E05 -2E372943C4F676BB72472D3EA1B0F566757FC5CFFF8F81F128995EEF12CBA8C3 -5C0450BFF4B9C68E93C1638A70509FB6BD34ABFD2C0B7C0A238E98FD8FBEACC1 -2539AA00D2B64D7C19AA45C3F1B17B9050546D751B2B346E19DE3359F02F5F1A -893148BA91ED8BD68A0BD5657F0001DB75E71F2A0160A7DDC39C773EBFB10458 -A1BA0DA0CF4976AA41063B2FBE875FF0DA96FBAFD6AF0DF9652AA0EEBC1AA768 -087B8CDD4883A044694186BBA78043EF79007FFCBCCA9606B0C132BBCF835ED5 -2A7F459264147B460E5C9A487911146939166679E6A193A4AC979653DD2B8522 -F6EB14CDED27F108C47D32E25D40FCCDA830D38B4AAEC9C6CDB212A1D8012AD8 -17BDFEEDEA83194DB3369B8E0FF2BC5BF2FB83EDD20248820FEFB41278A7DC96 -D47B40E6EE3F85FF38642B9C52CFA1F85FEF0DE3637BEBB66C1BDB2A8ACACB97 -9CDABA4F994E1656812B0321D999339A2384E07D19388ACB8FB4A86FC98A2E73 -3809461D8681C619766696A02A9099445CF756A6BD1ED778A4909D36839F7E91 -153C0BC25297495E3EC490B189AA7C7B64480362764F6B89753B0EFEF35C86F4 -65122B04CB43675EBE03A3026F4212D521AD81FC3E2D3575B1C6BBDF35E54199 -0FAA02480892DAE8DEB52A4E1C8E5995A67D2B3652CAFC5FB0BB108A40019896 -664ED1974AD21CABA4279BCC7D2E3DBFE7A70087CCBEA75FC65218C5ADF0D174 -436BB02AAD79BF172589C03D0C1D4DECCD14F98AE90A86B4A7BEEC0F1CDF724E -0912CCC14AEDB5EC8E297CE357ECFAA0CE69B16F93EF2B214AA9BE98DED441D8 -8DF022DD63C0AB8143A082073AE8FDD50DC7DD5BFF35F9BECE79C5188BF11056 -D8D61F9D5FB03CAEFB421682269D8F6DC6637F277E0C97D7639553644B59FA30 -DB3DF2B7B6633BA02AF683654FC048412F29BBA8872987BBF26FE15E4AAFD133 -E2A61425C364F7A22C201039D5D765C1B14A06C1FB3C2BDC517FD2D0CD1280DE -6973B6365CB32BA2D5B60E1CA37398A37B7951E74D201140CC5DAE4FC0D66418 -751EDA5A7D77D6CC9B4ED206B36A8CD4061E848500B284F1EFC5BC73CA717354 -5F1C96C3B176937070F8DEDAC70ACA1504A0557C7BCE23A8FCD4E179AE4C3375 -2A3099C9FAB588A0A47FA213030117F9455907169F00302E592A6B2D97CDF3F0 -E0441B0DB0FF1324F99FCF21119336CB7570B488B31A0F8FD3DB110733DDDAC0 -C9C994BD2AA5D5F4B3ED418205D8803C3EB6C591F7A5C34E00388A9E88DD8727 -C76F347D5B35F5D59EAAA48B62D575ED3CE9F3F61170A376AAEB825ECA1A20A7 -82C69F6BB354CA870717815F083067B7662A8950B85F64F693D58E17F1E35A39 -44E491D46C73775BA837DE6498334594C554C7FDFECC828E3728057E3AD3FFC0 -A1E63E94532B09CB28F5E50919A00A5AC50B0C6856A3697847314D8B9B8CCB52 -76E4A1FD2A075CB2E9B9929D1EC55F5EF9518437738BEC7B300C19038AD2DD8C -6AC399A0D71867B943B1B197E884B9DA58D5C175E1AE398EBC0B5AEBCF2AB1FD -A960D13F12E423B2DC17C8DA6DDD431219A0427EC28E1E4D708B4DB0C90B8A87 -738A2E4C6B8C49BE14091797A5CCE7A081485EBB8B2C629842DCBE25F5EAD1A0 -D546F57455B532A9DE145CDE4841B08B2DA52906FF16F53180FE42B2C53066DC -0926AE1BAEF441FEEFA91F722FE6CF5E0B2A0875F71DD42095DFEB5851C82792 -C5574EA07DDBD8D702B6AC0C82311A0490D5B57463389672933EC83FE646DAE6 -AE8BEBD6B5CBA53FA936F88A4E4F556CBC56B47B8393457C9D5E9FD8BBF800E9 -87CBC0C77CDDD9EE7768EA4A23E2B92ADB37BE882CD842D55EF629F6AB8E9C80 -13BB6E37014B2DA56FC65071B345789BA7D3C193D3579C6FD98DF997D8F1903E -D53670E6030D2ABA91DB82DA54B97D0D8D3C56E08A3C21DFC15FCC12DAF6CECF -6D085C337F6CDCD044EB3E7F1D4C29344DE105C7CBA03E211E3244C2365A4ABA -88D9E17389FE2161A6D9A2BFB14554B0071614A301741D6F604EC3788236D782 -152E3F41F8ACF4B04156EBA71CA125126C31FEDF066A474CCB8A76083B67EFA5 -9C34E8BC213AA01B1862D866CA2C7F9CA3444464EAF496186CBAF607A0E7A60E -4D8959DE9DD6B42E3995F0D92A7AEF7C6E5C3BD7DB1DBCB1E6EA19B10709F709 -40DC949106E454D9225606EEC9231D1694F71E350B8A8895016AAE4B44367EDA -F9E9FE18A201A08368AC00409F5FAFCE72DF38D27462875F0586E8631ECC090F -CE3DDB814193A5C154DDBCC1CCAAC3658BC4BE562DD1A5C3098BB32EA36D01E0 -345A00F76E722736BE3762177A1EBC5390457316FC105A26440011C3A3505DAD -DF4586C826B71A7E08291F1864BB50A422DCB42C15CC6EA2B93C5C8312EF4EAC -025AE0A87C6E8C824D6E0564037A3F2DF3507923D31501B9B8FDEE3A06761DA8 -25D1F3E7E4BFB11DC9C1981C0B1E878DEECDA57A367FCDE89B88707A07F1017C -CA88CB190F02CFD3541F27DE81A644E5B4318543740DF9D69CFA10EBAE0C487E -577ABD2155ADBAE841DA9C2FD0CB6D3FB4C8A109B7862A04B9976FE920B94318 -21B7D6DF66D1812E0D07257A5E354946D59E9F162FA611B1CDC737E2B60D52B3 -C82ADEAAC401B6C2D6DB473992B9E45B08A20744D53FC385E3F6D30C997F3FBB -7847C5B1ABB7AE53FD6616D7F23393E0AD34490AAFF9027168B5492145F5071F -DE0E6DD8E31277B3D3588B36372E4EA4F0107CC391DD3D0D5FE8970AD5FC5789 -17DCE9CA706164456BB7A18A68638403621251B60213B46971CE3434C70487E0 -6CA529999AEF89CCEA57A711290764C6E168E75EB756E0337081EDD6CC70FFB2 -9632D22FB3A400774642B85F576F1B73CA52E7F5A23591229C0B0AE6408059E1 -0427DA5122C7BAAFABE4ACAEDF7F5BDC3FE21909E7B474A52EEF3D98BF267FF2 -B3803AEE0D1392F5418E84759FCE4310048C9124824A5976B09B56F8BED6EC68 -D640A56126260FB5BD6D5AC13BFD5D0B0AEF252CD5FC1FA48A926F55885C6382 -99B48123231F416C19CC5FF196D13371DD5D33CDB23ECE5256EE5760471EDCE4 -26AF7FA95D468F2609FD64C6DE142E4961EC3156ACE3DC207C04CB4019CDB4AC -CE6013FD84D5B6887390A6C46F0F1A43FC0B1BA6AA6B5B44F23C9C360A20A1EF -E94366DA2A92098D60AEBDACB8D7B4736E4E17C4818DBD5398D8384CBE7CC1D4 -A28B28BA328202F087E841206B35D89E26C2FDEA77DA957A5759CDEA30AAEE94 -F6F5FFC1B3820C5E907CD6587295DDE110226E4DB1E46BA8DAA93EA2D135B635 -23F6B1A98F3F165C0EA13B809CCE4D64B942137BD1D3F98EC2AD678F26CAB779 -D9F8291DD64A677011B4B9604B8E4AC1F22B96A98760DB2FF1F47EEFB880814F -1200A077279EDF1BE39867C45DEC3596E4ACBDB1E200C27126AEC4366CB1A354 -F4660DF153B940679229990358B4942D6DFC7625273857445C967C24FC51C804 -3EDA0EDE8841235AF5F78B50368F80B3497E39F3EB0094F139D42BAA0831D6A4 -200538253A922BD5CD0FA548C2241F1442C1E35636014F7CE5C1D2294AEB4502 -F5248606EDEF0F33F998D05D95196AAF94039803898A673AFBB9873A1CC11045 -A01D174F8CCB0482F6EEF5D5879C16A4D7B573D84FD0CD5960672E6515CA1BC1 -BA40AF1D76501C06548399DA7D2662A61D03BC3BD75D012B30621D0C6A052213 -B3390976661462DA6E60DB0CEB9CA555AD3785E99AB8AEED42E70305BF90ABFC -C56C390EFA417FBE2FB82E9AEA03B36811B408CD5F90D706EF81DE9A75ED5B15 -6D726DCB2AFCE0E855DE25D23DF8E5D4EAA5364EBFF47C12481747F97B4826EA -2D639E00F037551E7A5EA6421BE789D54E1D5D30370196A35E65DF159E2C7FB3 -8057ACF28035C9EFFD9907D566937228062B07CAE8E2B199512529B71EA8AC90 -600AA84AEE684DD0EEB00CCE2355D089F6DFA6C0F18D138A7907615496D8A998 -5974A956A524FD8EE5E6A82798C7FA1B71FB68271A0C0FB71CA17036064CA597 -19F882FEE87C727ADF36872A0C05BA8D9FE0424CFFB637B1E85AA99B9572BEC8 -031F44D8E24FCAD7833E27372F06233E805B8FA976FF30CBE858F5FE88FC54EA -CD09B4F56E6A0A48049D84C1A124028072A0C6A1AD032F0D8194F5191F53DB6B -07B65F9EF3A59248C055EC60A2CF7CBEE5CFAD31E6C0B26937E7AD0991A1F0E1 -EAE9EF6F0D70E6C8649C460161EF09754C7246658454E44337119681342D7CCC -6438CBDA49130D072E2F49F1ED66B3A3BE6FDC93E573DF56748FD2F12E031DCF -2B0AD2F85D92AA9F31CA398D81572A05198E18DFDA86B817CB5F244AAB2A0039 -6FE7ABFD61675119D606D8432B84010B80ACFBD917782C45787C3F6E20616FA0 -301164B4386BC5A0D43732238A26553222C130A5981415B8DFF4467AF95C9605 -CF63D0DFAF6D7E2D05DB0FD260E5C28838B3D8AD910DFE029F3B1BF9D43C38F4 -5A6E3FE7DF3C1467C1D5C902EF9123C05F46EAAA8F17C380DF04B3F164C2180D -EA4EDE36FCF64AE318D8D13D0B307F668E3160A052639174F266116D4C6005C1 -4588F003B07A68BEEA3B5719F331A58BC4DFAF393B487599A0307A37235D83AE -DFC96552E2238FD4D4F1AC215A8ABD6F928C96EA7E1437230F12E7D6B0EC4B62 -40494113CFC38EF265418F4495020007B8F997875368D2F7EF8446CB30D370EE -DE8F36D195727C4A381F48F29B42AB70CC5211272822827868E958351B6E98F5 -26576770A833A726586A6FA59A42D2780FFE5AC3DE9358953261B31DE9FE468F -CC8DB501C0F41B8A218076D77579B4C437C564534EE5646151ECC37C58E1B32A -6BD702518C4A0BAD79B5CF825CAE60104D0838A4F15FB9E005507BAABABDDC2D -F0E67F620F9920A83890DDF699308ED3BE657C51214DBDA6412EAB1906DAD9AD -0422DC9DE4648D9E106990EC08FCB54A09A931A7A91121C7E5AC976D56907E84 -30B361DC13E62AA8CE37D255BA04EF9A2FC2D47484516B15C48BAF399DC489BA -68D0B7E973734FF9B17EF07AF4D5C93143EBE3E439717816F998A2AF4F7C684D -3CC1F9181C458A1D947F8A34C266882E62358F106EE81E02007C08C1A4F278A9 -8AD244A30F74B17408244FB69ECD2238705F5C2927C51C8698AC10B593C4A651 -04D5B601AB872D51288B5397165992E4CCB67B43F19E572472B6F804B309BA9A -1891C775EBC866CAE897FCBAA0DDB72469C51775E6C68EAEB4A0E0046F22013B -2E01213E604F9DE2DCE26273351A572C6408C264387CCEF8BE1CDE9DFA4E7F37 -55B7BD1ACAFE9422AFC886D6A27C8F9BECFDD6612C29DDD4F45DE8C9C0582C8A -0406CA4253ABFD29307E143CD843C666B567AEFFB5D9B0FAD58AC3F7D1545075 -8BFB2881035407A347E2CA572B4DF2266610A05B6FA34B59A54E0AD74A143F66 -64B35A58DFE2A5351683243FBEE5CC314995BCD1F918F581304CBD363EF21C91 -193428EB1CF98430D8BEB8D11E55E7A577B23BFA8609DA01593A6E53DB8756E6 -8C3645521BA08AF58442946E70A655DF2D7A9C1CC40060F7D413D73B751D48E0 -6D583969C3EA48526FC009311209D1600D9BEFCDC2F1A3F783D2A01B92F9F3DA -1BA6847BCE41847E6A991F54FEDE9D76DDF63E7D8312FDC6B308A6F5A1375EA2 -2280F3C1480E3CB9C38CFC536FFFA3A357AAE845B00EF45230EA00CEC2FF06B3 -670A87AC8CF3624898E4E240130AC15B8C573DCFB0B92E07D33B36CB5FFE70E1 -9E14DE5562F968CDEBEA75721B8B087C698F009454DFCA91DD29C261D60871DC -FF6142EB798849E9166F3D61E021CC30D4B5DF371400A697BDCB9A78ED973DB7 -8D8EB2DD13995F13C8653BC197F7D37F80F81C441DBF046E9CFA444CC1E189F5 -494BD128B24BFFC8F517A12CDC18846958B8C69D41FFCFBD2F5A09AD965EE8B1 -9E542E5AC2F5ADAB6A2C6EF31485D656CFD0B50720C5F3DFA642BCC1667BC298 -A76FAF7DB441D6877A8B53A450ABDD299B9315EBAD0DD48A933867DC86811DDE -0B5EED686655AB00EF4A6DF7B0EE644D578C6DEF011D47AFB8E8C9B8715BEA1A -20EFAC19F11808A6CF93074686496830676CDE3EF843A2D3EF68CB004C3CB472 -99E4DA5F2733B314FF90701AEA65130D1A18FADC67424526368158AE2D82079A -7E8078D9CE0C77AB16E582C16D0E5ACD1E12CF70A4A20689E33F9045781111AC -EDE1E3C25313D7DF52DBCC09303A0B2704C05CBB8F8C7226822F391C802BF293 -106D58D1C37D35CF48F3518B25EDD50CFF51055D22778A7FC5FD0C62E9EF6B4A -C43B814B5E0A12A49AAF20BE95F6FE037277FC4860A60714BC367D28C9B237FC -87E58A07AB03E869B9FA79989733DC3E929BF36ED0B71DD9A9D2614299426E5F -4EE3F63BF07C3186FE7FCF2E8041C0F685D01D7BC5CF84661899EA0AE20CB1A9 -3E37F28A6366D87B43FA2B9D256528A3E3442FC1F4AC3EDF8F074F8DDA4DA417 -4F7D9F14ECE3D16771406CBE27E7379B4DA0C2BEFB217BF112735F94E3A543FF -F21CF6BE56DA34313D637F19FFDE7E1C9E84A4F24541307575D6C1B13A9BA39A -619A67E81A1B09B02D1BEA936EA12FC8F11247235211060F9F076DD604D307AB -3DA4D7A02A2E8443EB55EE6205DA626E163C51945990C2CE68D8DB41F361A2A4 -1125C5C3CB75E039253C68EABD01F42012DEC2098B98EA479B510BE89967B61A -4AB9A5488A0FE103DA30872FF137B1D18DE85E083BF6D923D69A25FB315D432D -FA0F0A283231B5FD23FCF4EFE5EAF45EAEE63FD98132D68779943FA2D1A45576 -1118A3210CA455BE0CE81CD9BFF04B3D9B2DDFDC5A239757FBAB6A4FEE94ADEB -F0466FE94E22680A09CC0A81D4CFCD3B9BBC91E4ED0A4AB0BAE58EAB103A6074 -D0DA9D52DCE4931DDDD9451C1CB5B1669E518795C430C0AEFA33CB169692BBAA -4024E40CB5911215B4717530D9B2B937E8F86AB146A6C58B89F53403704ABA91 -C860CE9916AB4CD468D10EE5ACDCCC8E75C8AFF0AEEEFDCA43682480BAD0DD2D -B7D3DFAA55C59CDF224977840A8A7881FC89332DA667CA62C3804116E4E541C1 -1F7889D1CF79277EA29712531AB02D539B1FE27206F688765EB81716C41A3799 -FF72F5DAA298AB30152954822C77F3B66FC54A51D6BC7AB6AEFF7CD93FA94ED5 -66F0124F219ECEA72E6AEB15D5DD7EAA366128A54E43350B006CF47642900E0B -B4577DD12358BDF9C8E4C2C93444B9A29D442FEC36E40BF684D64594951EF807 -D587786C2E636CBCC165B63D8DDE01A0EEA0FBE2DCA45C4EAA1A1CB164B05A3D -4B594249D0A0BF0CB2AEA95A71A483A179E77A11A49B73CA88C81F763950C6CB -C4702FF7F4A58665C23D73F00F55C48527464B453150CA6E5B99D1BA08D3DDFB -B5B304DE4E6CABFF791CF2FB9912908029A383E8EE39F7EA2CCEFE949B536D90 -BC0D4D791582743075C21E37625DCD219364A71FB21476A2E559A9711F662F48 -AEEEE7E73B1DDF6BBA199A66C60CC2166FF9B4C4309D096C0B13C011D3ED30B9 -374210DC96CB26FB201EA9CDDF94DD9FAFF39732B4B6A71E86611FBDC8742D4A -C7E661E18DDE503C94DE0E6DADBB1AD6C7771D1AF783D504F2513FFB87C4B3B3 -90AFE5B8A8969CEDD65B59085A2C2D11E826D1AE484253E4B31EEE0C6583DFE4 -D482EAF253505DF691DE72EC54913AB5EAD1F051204DAFC9C6720157B67D883E -0D04B4D7412F0F854EC44CC4D83F8EA2A7DBE940F580DF77FC0B7F1687EA5FF6 -DC8AC26C07052E011A10738CC7FA1104FCC60AF85B66D2294484B391267CCACD -9F50661526250FAF134A8C487B1BE57F01D08E06AB5E1689CA9ECC8B6062B568 -0E43EDCB4C74EAADDFC3BB1D309C2BF166BA3E2E3F276E99A288D291630EA951 -E63D256587E54FC0E731E43AEEBF68ED71BD85D95C957FE1C2D78EB5CE3A2FC3 -B31F528FEE1B2B9EABF43AB591749CDEDDE9D83C2238E5541061E88C5B3E56D6 -3B5E1EDABC2C238682705B8BD673B383284AA5E8B4AFE1B05913D1BBE8ECE2AF -E5B96CB431D77065D35AF5EA0FF1B84B47655A45286E4D6EEA94D0C7C1BA6BD7 -9DD1943B5CA1D503CB10FC3F51FFC53E556893D280B1384F81599249F32BE524 -9439734EA7DAD4A6C7C0CE41FBA832EC6D4B3E54EDF0AF02AC694949F425BE49 -DAB43F2930D321A349023FBD4CFA05D9C8E1399E48F9EE7E3C61EF5833E89159 -423F3A8155FE9441C9172E51C9552ADEEF047312BADE124C8BD0A0FD2A2E0DD1 -A6F3D338598A3836AD46BEC0966499F558053D5DF15585DECA93339718037518 -DD8DB8E9D7303BFFDE3AE50902CD27A97388460424CB79BB1348D2C0E6DD71DC -0147D980E94B4DD28F3BFFBFC356EDE6220076D2E0F9286D7E6E0ADFB03FD673 -9095CB3696F5AB10F9CD2036CE9B88F51A3DE177DD9C6A82AD0D45DD6EA8B8AB -D8B7D1D5AB032EE378E5FB62E5C967F170590B0A9AD94E038C621902C674F43E -FC637BAD1B9EAC2206A29F6C7FD4448442BE438F688584192FDB60BB7524DEDF -0541CA37DC5E70A1776D62D5261425E17671E98C45070852192211D947627E8D -26195090547FAAC5D8763FA76353934B64DED4B01BB73A72131F60036CD7B86B -15B593959F997F7CB38189F00FD5BF1E90E7F419D163A57CEC5AF1ED84115741 -3C176C863F8D53C6AB667E141B13B4D07C822D461840C8F7F8D2C46EF4D10F12 -359C7C9EE4B4D7802C857544E4CCDEE30947593A474A87C81902983062345748 -370F307C3D91785239E17215291863C565D2F737E4B1C2E44E85E098EACEAB72 -0E31F40655E97175DF31035E66C73DD753561EB2F91FBAD13A4E1035775A4AA8 -6E2994505069A011CB338779D4C3859CCB24EB8F787435C959AB36D83F04EEA6 -50308A38CD3688C04A146DD15D2FE97716304CB6FECE9B748F9A5053DE280366 -A94C14C0D642D169AB4185673C97C2F1D864E72C18A44D8D7D5498D3BD1F17D9 -94A56AA314BB0BE57ACFEB16AE42FAA2DCD563CD67A9890B9AC072818838DB0A -F4A099C2DD -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMTT10 -%!PS-AdobeFont-1.1: CMTT10 1.00B -%%CreationDate: 1992 Apr 26 10:42:42 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.00B) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMTT10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle 0 def -/isFixedPitch true def -end readonly def -/FontName /CMTT10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 33 /exclam put -dup 34 /quotedbl put -dup 35 /numbersign put -dup 36 /dollar put -dup 37 /percent put -dup 38 /ampersand put -dup 39 /quoteright put -dup 40 /parenleft put -dup 41 /parenright put -dup 42 /asterisk put -dup 43 /plus put -dup 44 /comma put -dup 45 /hyphen put -dup 46 /period put -dup 47 /slash put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 56 /eight put -dup 57 /nine put -dup 58 /colon put -dup 59 /semicolon put -dup 60 /less put -dup 61 /equal put -dup 62 /greater put -dup 63 /question put -dup 64 /at put -dup 65 /A put -dup 66 /B put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 72 /H put -dup 73 /I put -dup 74 /J put -dup 75 /K put -dup 76 /L put -dup 77 /M put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 81 /Q put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 86 /V put -dup 87 /W put -dup 88 /X put -dup 89 /Y put -dup 90 /Z put -dup 91 /bracketleft put -dup 92 /backslash put -dup 93 /bracketright put -dup 94 /asciicircum put -dup 95 /underscore put -dup 97 /a put -dup 98 /b put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 102 /f put -dup 103 /g put -dup 104 /h put -dup 105 /i put -dup 106 /j put -dup 107 /k put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 113 /q put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -dup 118 /v put -dup 119 /w put -dup 120 /x put -dup 121 /y put -dup 122 /z put -dup 123 /braceleft put -dup 124 /bar put -dup 125 /braceright put -dup 126 /asciitilde put -readonly def -/FontBBox{-4 -235 731 800}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5F00F963068B8232429ED8B7CF6A3D879A2D19 -38DD5C4467F9DD8C5D1A2000B3A6BF2F25629BAEC199AE8BD4BA6ED9BBF7DABF -D0E153BAB1C17900D4FCE209622ACD19E7C74C2807D0397357ED07AB460D5204 -EB3A45B7AC4D106B7303AD8348853032A745F417943F9B4FED652B835AA49727 -A8B4117AFF1D4BCE831EB510B6851796D0BE6982B76620CB3CE0C22CACDD4593 -F244C14EEC0E5A7C4AC42392F81C01BC4257FE12AF33F4BFEA9108FF11CF9714 -4DD6EC70A2C4C1E4F328A1EB25E43525FB1E16C07E28CC359DF61F426B7D41EA -6A0C84DD63275395A503AAE908E1C82D389FD12A21E86999799E7F24A994472E -A10EAE77096709BE0D11AAD24A30D96E15A51D720AFB3B10D2E0AC8DC1A1204B -E8725E00D7E3A96F9978BC19377034D93D080C4391E579C34FF9FC2379CB119F -1E5BBEA91AE20F343C6420BE1E2BD0636B04FCCC0BEE0DC2D56D66F06DB22438 -452822CBEAF03EE9EAA8398F276EC0D92A7FB978C17805DB2F4A7DFBA56FD6AF -8670EB364F01DE8FCAFBAF657D68C3A03112915736CEABAA8BA5C0AC25288369 -5D49BD891FABEFE8699A0AE3ED85B48ACB22229E15623399C93DE7D935734ADA -DA7A1462C111D44AD53EA35B57E5D0B5FC0B481820E43222DB8EFCD5D30E15F9 -BA304FA879392EE0BCC0E1A61E74B3A1FC3A3D170218D7244580C7AA0DC65D19 -741FA5FE6F8CBF60250ACC27454BBF0897CA4B909C83A56672958752ED4B5E79 -E18660764F155E86F09EFA9F7685F2F5027EC85A775287B30E2069DE4E4D5712 -E7D033481A53A2702BA7542C71062173039030CF28D8B9C63B5596A9B42B33E7 -D922944A38713383D3648A4AF160A3B0C8F3379BA4372BE2E7EA49AABA75AEEE -C5DDE1D8BF68483C3D21271280ABB91D54CC819680322EAB72E1250A760BC8DA -726405EFE420635B5B7F0B48752C06083E92BDE06401C42A2C528C8A60381227 -CEBEF0C9440DC034DAD9C19FB27DB399BDAEE22053591D6538587C768C1B7B0B -7D1E222D2D8AF3A6473CC4C0D6C3E0DB49068CEB8C9BD1C5CD486A50DAA10BC7 -7D6286142355E3F21DD254E27C00C442728A0BAEC9D3F17AE9CE320D365152E9 -EB0D5E3874F2BCEDA98521D23FCFC30B4B69DAD2ADBE80E5964ED0ABEF6C73B6 -DAD30E2C5061E3747FE536E1A5D190D028F2130AF608F5DDF9DDDF1E77DC8437 -ECB3EC93B33505DF47884DDBD1DC6BBE4098DF04A29AF6FA3AE344600D0AAB53 -B3820DD7ECB600A3B8001C51AF2CA7A39AE1485A087FD1752DF68F55B52B4DA7 -48030F2AA7E570B3D56C4EAD367B9B73FBC0A7356253233006178B9A6BC19081 -B815B5988AE76FE6FAFD7AC239072B1106A3F509381AAEE79B2F2154CAC4727B -D199CDC8B4D05DF4BA006982512ABD7539E28D937B0F87FF79A3F84C29ECF943 -A8DCB8BDF8EA9E7A0E7CD60BC2308C96B3E889C797D0FF28FF4847016B3DA141 -E76FC6BE78A6EE9CE07E651FF86E720A1A1F075972D36E5C55162E3FE26BCE3A -814BFEB12D4C5FD24340CFFED499C7CA183E57EC4F12CFFBE3291D43F7270575 -C6C3306F832EF182ADD0AA14C4D8669A17C09F632406AFA195F90C4DDC39779E -EC0A77E590211592D6EE19563963225C06C2F13265EBB5A6CFB7C17D9E77650D -11958305727AF662AE73AD0E3ED5F7E7086C5A0C3548A8129575980B06C715AF -DD55C8DF869BED0A7883491030B1A7E82C5EB04E5A7D952E716DD8F2EF6275EE -087614CFAB55FCE2BBECD7E8D9C90FD8359E929D5E0A416A23BD58158318B4FF -87B095EB63F7F052B3A77F136FD66EB2C52BD46CD7DB3091A4B78A607112B12C -4D171B2A00B78B0E1C44B0D90C20D9244281F5123DC1F6063F91E9E3E48DE78B -C862D848BAD073A4FCB5EEC9FF54B5AB8E234CCC3C7439C62ABC4A13EF1B8897 -ABBF21F900C564C9A305FC36FC7224932F766E6E72C2EBB55953DFE2AFC2E3FD -33A0C6F0FDFF086E9FD796E7242596AE85B877223532667625E371D2156E4C04 -0D7FFCD3337B93DF066CB6FE1E13960719EB7CB409EE805C08ACD2C06303ED9C -E34C898787A43C1B428B896551C6FEB50A831C6F8CE2073EFC662EC286CB7555 -A3B42E58772E82FEE206948B8C439FEC5E4ECB9E11DC3A4CBC7611E30890E408 -637A01A2118441B4F9467A98BB2A1B03BB2F5D8E3DB7D1D15C188D9E856088EC -B762F07B1C06024F7EF53A2FBD60C0A1F4C0275D07164545250ECEEF8CB15B04 -A2D8AC44DDE818C4E3CBD2A5FA0FE49750886CD7CFAAF8B780255F89DF7F4F5C -BB594FE7C1597DA71813C2952AD3E811524459EB71D29696B450C924B6A5C843 -8F36A0F1D7DFE796FB9564333666D74AE614D0D698FAFF20F83C86524C894BB0 -272221C060544F3B653CB0E4E4F82B20D7530B3806E6A5830852C58070177815 -E287C847F19F64E854F1463C23DDD80093D6FEB8BAA22C5F05C21F99FBA7193A -EB7CD49CFDF4308C6C68CC955A45FCFB54FCADA9A3BFBDE086B057DE88BE335D -280F5338D7E66AD39FD08F9B55884F1F377FB6869FBABE3EAA4B7ACCD85BE672 -724B4B8F236B0889B6E7049CBA558A89F17863E82DF145DB8C7ED1F36332DE23 -3C0053B74E850FA14F9EC9EFC23AF18E153CC96FB0FFD910347370E57F0D81E9 -4A83E2D189EE5635E85A2BEAB5B1CB974546BFB2FC2ABA1E15DC0EC1BB3AF1DB -B2F93538B92F504CBD7AAFE36F5F3AD45EB16378F169B17869FE81464CB826CB -400D2F5441A496B6C60A4F15FD20ECCAC1F8F91015E7E1C1A10B7992A1554E52 -9FBEE905A3005336E49CB04BA7223F1674C0BBDFA06ACA34F7BFDA56906E04A7 -4DD79EC7E79B021A5008F3B1E04712D689366F520B0FA66A558F957011992728 -561BF4B75C2BE07C4024C172085E51CCC5CFA439F570297154CDDBB3AA25CD6A -3004B936488851BA1E814260C06CD5479DCAB1A6AE21A5F4563024F973D738B4 -0DDB6C6DD2E3AC21B4F6D95CF9AACA782919F5D3E613D61F3224A982AF485C8D -EA0037410EB70AB7D3EC174C6D5DE5C9C5A1220EF7C2B74499ADCEEFF077D1D3 -50C1124535F88C3C3F66477E42F1932665AD323E06B398D2805B9CEA632F5B1E -50FA587B102A35E2F15EC22DD66E4DF06A3F4BB717A3ED7FBBE2458EB4D896DD -AF00D1BC71FE1CCA27890ECBF9F0AF01D3E65CAA29427FAF06B3BE1E640522E0 -73B213D04491B93DB29113EF72211E31F4C5A7FD58451946CFC15FD805112FE2 -547D1131A46710DFB75659A33695FFAF3CDD40AE5260AD6766DA81DAB0A6E96B -E89D57AAEF32B5EDBBE9F7CC033BB2595CA3FEDA2ABAC8E5395EBC35BC112FE9 -67EAF1F123228538091483050847F8FB5194203609502D3A09CDE811EADC18B9 -F039593782C27EFA7697182D6367E88E326AD5622C5A457FE2644FEADA88615D -9DE3E483BFD9329667953CDB86F9D2F0D4F02DAB8A98FDEB1D17CAAED9B6E2E6 -0C55C1FEE25AB98FF59FC235876029CE03E4A713B75B3163BE3B2DC0D4472DBC -473E10400C0F57E627AE97FD0C1CB0F78FD8E2FA831A3D2B1C2BB3F2D4E812A4 -194C8732B0C525361DC8480CB27C30CD4DCFF01318D2EB4F5234B4A42EA8C23E -7B3EECA41B8E4F54D5458B37EF0FB2F49EB19F4EA8AD2B53820FA36E93DD309E -48847F5C01B1118ECE7D0186E6B8953344EB775D655AAAD7BCDA642EA2E39A15 -855C027CBC0E3FA752900EEB464E2D39404D1B85072B40834748C6F9C74C5B6C -3CEDE988343FD984CFE4B856A481E60E2E65D3BB41BAF2FA80AC0BFE381071C4 -573C6ED65C524FF777F34D82E9661E4A75E3878CC77BC59218244612219C5A92 -E95B90EC2C38614665550026F1730D11162F19D841681C04C401E102C047541B -97B9264D86F47E25A347696AE5EF0FF3ECD9BA32C92901DEDD816F7D73ED1216 -0A98771892472CD625A8F7F19DEFCF5CA2AE57F8AD3898F2C1005B187DEC6F2A -A31C32720EBC934178E0E9979013B3C9AEDA4051DF63D8C903A399DC88F83DCB -A73F1B2083819D1BBEA5235F8FE1D098F32A2BA6274424A99A4975FE4BFD59AD -79B40A8003CC0AA728EA79D6BDCBBD73DF45B7918BC099C5BE4A068BF64A30B1 -C39442CED98AAE1BD495F6CA32D564A72E3BF753B49E4178927E4BBC0F06048F -96DE7C30AF580B0BFFDB330B3B87D7F6532A24F403680BD9F15E758CDF04EB94 -E83C7E644FDE5BEE7CE73EFAC75669E41BDFB20A5B8ADE1137378DD8102A0DBE -19499A623770417CBF5211395A6BA9F4490F4707A46F1F9B3FBE642DEA0CA053 -9ABC307B1E71DC2B069DDDBB4EAE378BCC75AD61DA900AF8BA6DF0E27A8D2258 -DC80205305AB6ABFE3726703E60869BFAFF1874F3C0E05FAD9C05D7D89ECECA9 -DD2AF5F777D7514208697E712B52448B364D3ECEFD8127043DDC9D0757B7CC37 -5CDE8001D007A6E961EA24D7FFC92410F3B13A32946F12A50DFFA256249BC8D7 -C1842FB84AD51B41008EC4604F6B70990510EE13E6DA34F864A572D99A13FFC7 -3609EF2BB1FCDEDF37A6018248C545E086EAD1BA1143E74AC60B684E755E59E7 -36557B915F92EF78FC177621D49F777A2AF39F3C2AA6EC74750AAAE08BCC21CA -A71CCDC91DD45E6050D83ABA49ECE425B55EEE137C55619037F1C30530BD0A6E -CD2004B6A040405064D7E87C55536680364E09248BFAA3FDF95CDA0708E55F4C -F7D0A92A93DEE0C7B69638F171B28B7F854CCC6EBC6AEE14864BF5144EA36D46 -A9C297225AB0325E28EF6BD06D7E40E3A724EA1E50C4C6163B195CFFD5DD291D -D7BBE9AF4324A69394117EFD62F08D6BA6A8F0AC3E2353492999AF28FBA758C3 -A50B6840CC72054355E6CBDBD86F683537A4115049BC1616BA35C2B0B6F5CC32 -3F6831DE4E6029310738DE23D36D2C6E82F04EB675FB89789F74AFE3B8854250 -51812FBEFBCF162947554324FADAB765C74B6DA89F60A734076D44BBE45263B1 -3FEFEEA90EC7948F23F34D4049087AF6563692417DDBCDD5A9552A373C2528F8 -0318D3C0669279F292127CBA40B0ABE08A1476BC9EBFA8BD5D622BC5CE7DBA20 -C689BDAF50D5B1EAA89E296787CC53845DB2BA54FDE363DCC98A7BA256663869 -E9E02E09077884DF1A2A41AA698B7EDE8DAFA621B552DDA91AD1E671D636FB36 -91C62B4D2D4112F2C169E0023EB7521F570CECC54ECA5EBA462049AABBE2ADEF -E3234BFD71B26DFDD9D34DFA69E5E80FD90406E6505A6798F030A4B5172A7BC2 -C9B765A86ED55C0590E0432719BCD7BDE7CCC7F6B33BD467063D886276C8879D -E04897A4623111C14A1EDBBF69E2FEDDFEAEB2A785C6D2F0711DF4B93AAA291E -7F4E0CF9CC3FF0D31953C594DAD014097DA02CBD5AE8828C7E7B5BDA09188B05 -0D7263F164E1E78CC430ACAD1E8FA71001E9BCEFAE47C79846916A5F819CA366 -5734089BCDD458CA1A9E8E17BFF357A91F9A7A8A6E1DEFB121353AA80F1906A5 -AF7CD2E59EE6776FC0DA6574DA0DE522918CAC4E566F13FB9B64EFE79F3A3BC0 -689E3B0676741C90FF3BF85C7A0FA9716F4ED0E329512B66BFB8AEB56C3DD6B2 -24F8D6E23751A8485F7EB46719E9D22618FEE86D5E01ECCF4C6E74368A8E9B49 -245D80E7484DFBC916FB2447852B36EF3F99A82B6C106F786707D7689DCD7AEC -A0C51AC1A3F67034C16B74994403FAE7743BF02149BEBEF554814BEF31B79184 -3FAB4D2C887E1BEE81B465D12DCDDAD03DE5ABE9E763C440B2CFD42FD16D96EB -C21FE788C8C2688F79F148AA7090BE64B0EA710D376222FD1590301BA9A2E715 -D33B8C1D95F2589AB0EE476F7046537E27DBBCDADEA1E7357C9D7FA92C2F93A6 -7BDDF58A44966590821023380C97CDE37EF6D449E35EF32BCA6E69DC8458511E -8DC8AB63171A6018AC9A334829E5978484C4C6E917A5F1C254E6669F4037C691 -36980250A80673E0F18C9E0FBA1E5CCA3BE30B8E7B7188062B25F8E1E16528A2 -F217C18D6A1955482E5463FBF097ABAF7314E449C6FEE56E2695407A8AA9648C -61AC2BF3B2D9CB6317A9B16CE931D318C8BC9676CD908505568C197D90C2BB46 -06431C999EB68C8216409E4CABACB2BB34A05B697B9DD1E91471A404B4969519 -E25209EF4EDD420944BED17B18DB3566FCB8059699FE416789191EC2B35086AA -2E10C139E3C9FA0A535DEE9255A867A26656213E85851DE5F51F9780D3A6E572 -F1F5CE64DA176CA810799DC1C60A8FD2A5ED42E613021A19928EC4572059B2C1 -EE441E79CDF7DD4AF7B6E3D3230419ACAED329388044B107DCB4DE91B71EB838 -904B1F969738BBDA064FFE75C6623639BE9924602DDF0C166B433B9D54ACDA5E -018680477FB8F10621FF32319E58DB672D744959A33E7314A1B3CDE0C038F7D6 -0C8A195AF191E36B0325334A711CD8E25D9C1D257E46A734779E486567481108 -E0281DE96907D460546578DE83A0A01A9ABF64402B48DEF739F4308E14145753 -719CEF720FE5CF8DAD7845E74D502B69DC18D172C3A27411259B8042F3FF82C3 -B157BE242C351830255CF0EDA96577375A70657BD9A2E9FFC54AF0AE563D73F2 -E510279FEF48D79F5F7745DBB492F1D74DA738E6A4FE4364799B5BEC93B4CAF6 -B06B9B8C8D164F8FA1FBBA693204064F2C1806C39910910E02ECA8D092558CB8 -33338B359D56483B7B99A1D8137204EC1AE70ED3D75881FC3B00BB9349AD934C -81A9F285312FDDC77FA923B18B1873D288C2AAF2E6D0AF90BF25A982B843789D -5662D6A2DD58E065026885601ABED4B09CAAA3116DEE6B430B15BE0A121FC1BB -FDEA5A501F0798CFFFFEAB5101E707F1A00C8E014A3561FD39972EA9AB108EBB -960AEA7FF60C301AD6CBFCAA7D35CBF6F8462A4D76C4FBA6F3DF6BB762DF7900 -9F69529AB4EAF96C2866444B257160E8822533A7A1240C83EC18C364F577407B -4CB314678D2511735308A1660AD94B8B818CEA4A3DC00C5A1C978F8BB4E0491C -49328F6CDF95BF620AE53056364423841D84418B23C2A447B0CCF8D8633FE2E8 -4A4AC1C6C74627EECDC994059F1BAE9E6B10FA80D767B3FE97BFFAD413DCB0A8 -495039744B48266278194D60422D6E7C74D0DB45ACF217797D0C0678EEB60759 -6231438CFEFB346553A7A447B50807EBB6E885B5A49CA9A350EC4A8C76EDFBB3 -A4DA1C9E3EFA193CDF08553302998F20055C84420A4C5252F764CC4B7A4BEF6A -A09170EC417B296DD9E2301CD8EABE4A087E648E0525A9FFAF26374C47FDC123 -82F18C9884843864F418ACB08041E7896FDD395225532460A8194A8DB4DBD824 -1C68C6665F85059E365EC0972EC6465E2D8867449907DA6692A021F026F437BD -D02654BC11381BB6557663E0B0B8C4F2FF69E4776F4EABA69311BC1AF8155F7D -6D3A418BDC912CC7CF1A4BBC8A1376D8B4DEEB6585416959BCA4AA08D4520C33 -EB054DE53140992D0707210593BE62B3659E3E493C4562C2E99CECA143791DAC -679896BCDA0699E405957E17DDBD243E65CDD7C9C8629F29A2078658746A7779 -0F75BE24E2DDBB672B95F26366BAF036B3C23BE4132D7362E76D4183A469E0F7 -29174711ECAF4FD9A923E72FE58DF2854C5537E3626317D471D1E8A922C9BBA4 -CE9163A4086AC4A231C2BF35FBC39A5BBCFE41843CAC7D81A054509D31572BE1 -596E0B0B563DF2BF0E57DB4943DAEE35CA26C8433FEE4FC61145C77F65DADE75 -62DA18DFABC7F4194906F53884E62E77D8AB3E099776AB93B2B4D0C98FA44C71 -597202A2643942795EE8CE098FE26F1AF8134F1E75FAE18D563B1FF43A511C9E -EAFB9EFCF61490A1A4FD2CF354927B72C5EDD5D62B2F3F5006D6130562A13BCB -1B988A994A8D68B051A5A821CCD5D0F8D9D49FE7CD04EECCFD7A554CCDFFD77E -27AC4AB5BF9FE40F90EBD066C483796CE1A364E95C5E0CF2154834760522F128 -B2DBD1F4F73347D42635B2875A23597C35A0823CC6F71E49598125411BC9B2C2 -72470D36DD967C947AFB031BFCF770FE50551A134DF8C5D1AB1F09819569A57E -E23D4E87C0B52CD02B0A2E3FAA7D27A94359E82AF047756BB769BC5950A75207 -78ABD49D174F2F69810AFFA9336A52D6B93B004DCA5CDE58475C0210E0BA1D20 -FD4FFD6838EC56A0922472D4C4EE0CC481574BC30618179E733EA40A48847E14 -A75BE7717CC5DDCB5B0718074EAB6FF07CFFE794D335B3A13EB968EA8FC5B08A -13B38AD1C2C964E4B07E90B9732C458216B028E07DD593A5B767A2B415EFE7DA -951FC07800F11C7E2EF9BDD152BC6815B7F32117F49FE08BD79BEB949003512A -327F3F8FAE1767E7842348BA4373649F1A21DB2C56C081BCF9FA4EA86C8DFF00 -FF45C4F1386CF8C2C4120F3F6019CEBB639F2D272D08C1763A470D4BF6330DC8 -43C069A6333113C3A0C93471486EFE9BFC02B760C7CBB2E9156087D09EE8A178 -5EF50B34994094C3F0015EA2ADB6C920F4302FDEF128711994875551C4E883E2 -DDEFFAAE11F2234AFDD96400BB69C1B4E6EFD75734C586A10A54A98E7D790F28 -DEF7C7DF61FB23BF91AA700AE585EBDE74E215DA49F4ED466F46129022722086 -8884D8E026F35C4BEE7E866DF8E0846D5EC3534069B713FAB02D4B4EE3B44E1B -656F30D629D40AA1337786C1FDA08EA1217AFA4A6E2498B334DAB5461A70DFBB -5AA5686C89FFA4EE82D81CE2B28334DC5C032487CCE998616F48150BA1281911 -076E626E5BFCC56A0A4CDC559F878F14C2BD7A5148C1D8CC303FF9EC473354D2 -D4FB0F0F2AD0CF182A28074ED6552E179222570DE0E0D44E8FF4DB36C3AD6487 -C4BA53C8548714A69FCF8E3E5202F09469D7447C6519AE902C1D611A720BAFB5 -59E27A6DBA73624F44B4ABE0988BA3450F82E03521CCE8EDE8BE7EE1223B575A -DF9A52650E85545525E6F121FF2D1531F156EA9D5594239AEA2CD09EE28ACB15 -A445E11FD1C031188DB61881F474D49425C084489A88A47D681EA68E7FC4B1F9 -DBB552063A02A0EB51125E9B2CC646B940D46FF457415F9565892DEAC030F08B -E4C10DC38D825C7597394C844CB863CE6C843F67F2E1C42C4EF86AC7FB727BF0 -224B5E91BAD99CC6638AB2C64469A81D8B1789981872ED037B3A34BDF3130137 -80FE80FDA65EFBC11A08B98A1AE595F980B577E22D3CB7FED1D4016F5290ADF5 -47D7D9BAFE39F294582F2C084003E9C83FDB9EBC87C8B477CB8BB359EDD9BBC9 -9368D6605E1468A20909831BF602EFCEC0D5EBA99A2223E5A269275C8B221B3A -F9226654185929F794E1979ED18B4CD36152F973433AC67BE24B9D953254FBBD -B644CDF3BF0E29A2C72113DC486E46DED2CE8F8DFA8B0F8478D1F18C9AA8E054 -A31C3DBE84ECEDD85DF6AF9467AC2990ECAA3384FBCA1BBE598AA0D6813C859E -1520B88BF30ADA910A6AC3068A5B8CFD76B7F0F6F4AF4C32450D628B5320C384 -F23A2B5E8756895584155226A30F8B0437E028978491DCD00E79C0ED58DF261E -79B9DA17E57AEE03EE92102EAB2D63E69A88EE0B1E2087ED0C0CF6475EBDC3BE -0324D1FC8F7B90D8D807533E5436F2C2583B9629EC390403437FDAC908557894 -03054A6DD6A3586043A9C8BFD0C7EDE1229DBB9F69F7A5D20F55664D061F6517 -0051C6B3CD7338241FB403F2AF77DAB1A8EBE1650156D40863EC1957372BFDEA -BA8D0BB1193CC5BEB5A68C8274802E14FFA3ADCEBE19070325B1BDB960CF2988 -C0F5A9BFD843C515ADEC8B8AB02B2891EDD7502D9F28F4E58D8F67D1ACAFD0C3 -3531E0C7D1554344CCF90AC8696E83A3F968252981CAC09653956F4343B99D3D -4F17CB8BBE4506B354439B70F2024871D16668F9DECD8EDB872BE5E6ACC406F1 -1DF4E3ADF60EFED57D1C426292970199BB663405236C6A907B6891C6190E87F2 -78D9142220FF295C7BF44AF61470798FB8CFBEE6973C69DA1CC24ECB058AA753 -DDBFD92FBB15560EA19D5D92F0005B74F06F0EA5901D231996E0866389DCA433 -E62BE48479687084C1D67BC592E592939F806FA8BF5F0D3F644B1FA6F056DE0D -51D3F212C6818CB6166317058C2A0C07AE2E324CD90D4EC83CF4819B10CC348C -6DBABA024A5FCDAE6E288F82DA060BCD16437F07DCA43BF1E5A1B402F16C78FC -075BEE900B4021A1019C4A5ADC33230047FF11FDE8FB775DDA267040A22B4E5D -6012F7E72B8BC8DD3A81369A08FB81C6C4873C2147D03D4181D6D8032DD2B610 -9C44CAB50C5BD8F489EBF01C72D4198B66EEA4E976462F8874143640B82AE57C -A51EDEDE75A9A55D31587C14F8DEFFE69F75EA7B95BF725CE9991FB2F07AF568 -5AFEB39447B728B99BE0502BF28DE1D92B15926BE4E3DA2E7BB44A24836A97C6 -EE3A2080E01DC6514180DAF9C055F4C94929D34F193920020505E62804461630 -9F42C652F9D5681C91BE23DCB0C634247E739135F925EF3D5424767D5F5C5879 -C46F2E32C7B3BE9E90FD6ABE693A6016AB77670129B58B8FE719FA97FE320842 -6488CB85B6BCC0012975D22E75A2E086131DE676AB825A386C086FBE1B65DDDD -A19F06AA4C1D3EC84751C649F4A62CFDC48A7CF88CFEC68B959C211B60DCB045 -6BFF922FD7349B98E1769394E6CEA4F764AC4B6536AAE4E6BE69099A39A6A33C -97671C3AB4E7A94DCB829FBA97DFE5F71B1728FC81F826699DFDB0ACE9BC60E0 -6EC15D35EC479F3F53EE4D0398BAC138FED504A84A13B78568E3F9C86BAE8B88 -61830A80F8B994D0D66A8FA3FCD6C5099C29FC285ABF096EF9A3BFDBB522157C -DCE9F0D6AAFB1F8D7B0A3C573D0C170357175DD56EAF37BAAEF4C92FBE17E26C -7D2BDAACB9B8F33D09651FBE0D49A8BE66B78D075485BCD38DED5056FCE48A12 -D28E9670EC7CF4E9A277D6ABC2F7AB30BFF290B5452582F372FC9DE6CEA9EC0B -84328269F14FE7F47620B1042B283C54161AFCF84B46E6B1410587295E4F8958 -C1800F120B59639C85D46D46A4C64309931A8C91F138EB52F779189EF75B9157 -D624045F4B8846856ADF0AD735FC6FA41F7B6C002E9D1EBD92468E86C843AFB7 -4D78E3D54D866029DE5DF865EE3F7313AC358EDA70A792E22F2F806EF86A6B57 -64AAD565C57E64B1A6635B7394B4B5729189319FCAC8529ADE30633B9BDEE0D2 -AF1F8944EFDC7C408FD8FC270822CC01E7BA355C856219B3AC5D05CA37EB0EF1 -6766D62383AEDDA1F7CDAD1DF0172E766BB46C5FCCDDD61BB019D283EDEF312A -B2DBA38C9BB0928FB93F50E8516AB353BE04403D132805B5AAAA17163AB9C847 -F1B54946B0775FD21325C82E4EC7F2186C54B4396BC4B0B913A59E4444D11B39 -8AB56F2FD5788A9BA45DA5499A50BA74D28707F62086907BF8342E0C753A31A8 -DE293B592F51D74DECA52858CCF76C69BAF2224F640069BEF2604983FB478173 -792D68030D7A6E3FE083AFFE9488D872897ABFC88CA8BFE484A75201D73058D4 -72A8A26A50BA1F2B50CBF98D46DFED0BA057619BF370E435A0400147928D7C06 -28DF2A03527E3BE925D6A664E4640E63BD22D54A038D934B3DB5B500E075B8AB -06DB5279274E65FF870F1E5106E190AB0FD8849EEE2D605FD4F0DED2C3F86831 -4EECBFAAD8B2A895F08DBA692A8176F9080045519CC6C46B52F0F31DF112AD79 -8E46B9899C5527A011AB63FA443ACE90F09434C295A5D9E6753AF2645407488E -D29E7711546F87265C130B76B4632242E43962A5C886D4DB6316A2F3420FCAEA -3055AB5A9E1325EA870CE87F34BB2B3110E4919E1AFEE67606B00B03DD6824F0 -20BA42968B81DAE198C88057438E36056D46C550E3E5E03A99BD4B07E66A2179 -BBC5B3FB06D5D72022C53A3F3A1B759472D5A50D7F7A1F4E31D3F7A30EDC1D45 -4B00AEB5DF680145A123CCA3BBD801CA64B2CBEEA99842720F8DCE432909AE78 -5AD3F29AC69D302C62256CC4D47AC92EE11D2A3E1C666CEA24876491BB167548 -9E3A990252DF8254CB5E7141F57B78FD1FEB38BE135815C6FC86EF81B5994711 -E43083C3234C55DAD97CCCE4FF3F55C5A6C22ADD2C549513A465CFA3D8A9AEB6 -331374DC05A4F496BE33F9263172FB6FE1CCD19EE9515C5155ABECA9492DC743 -BE4142D63FB5E17D55C9FE642F07995502AECD9D555603D15B5BE420A65A6E98 -4F341BA13E44DBBC1DC8CF0D561198A2B40FAF35F7ED5FEB4429BF71F5C88637 -CB114F1377FD3227EDF592733EC68F4EFEAB14FE7C26DA7031075E04289FA6DC -8A79F81E4E18CAE8380CC585E7DA3DCDA3FCB53929AA8D772D53FC6D821EBB14 -EB472017FB56CE9410FEEFF14EA69C188993922DAFEC805F4C8028537A9D6365 -AE1A6BEF37CE8E02B995C41382984802AD3D12AA9FAA36837F9F9F8F60D16B81 -474238F136F442CA9B14620F83E4046E41EB0FD02BD04DA7863DF26624B5489A -B8BA35B0B3A8D128FA10E01DC9B622C26CC57CA79CCDEEB7E174698EFDCC0CBE -879AE1434B3EC5AF48E6C2EC5652DEFE0ECD7415FA46BC0C80FCC57CC808B3DE -CBE4CC7B62AD3B092487F7A23C38A2D9102DEBB1CF4C1EE7FEDE1E8BBCDF7F73 -54CAB1E591F9B3B3159D879A9492394B32F2CC43EE7EBA6E293AF12D7FC4ADF4 -DAF8F2F48A777E927A915DE1FD9125B52D406BACB0BEA149F6F6D79D92D06413 -5D68461A772D531F2E76D1947D2ED5BFFCD758E062B5435BFD180F7E3734D5DD -ABD86A1C2BA643955A36C482BEBAC608F588C43E6EA7EA2AE01D0346D28F50CD -BA8F9FD23674AB19A2B879E0DD19029EAC5D74D16B186CF4BE3382E74E361427 -536A00347E536701808C1D31A617D1F9269110B76A0D59C7B84D98C8FE308733 -C9497B807A77D244FEE03ED7FB5EB4D6ABB74A7129F23AF628BC01BEC6C43ED2 -D62F4E2133006FDB94D33CD31F9FFE57C8C9E31DC6D7A81A2C6ABF1D971EE222 -96A4D79F7232190EB796A43ECEB88F1C64A88A10C3AE8E98711EFDF984BF270B -55C5B9082D54DA7D32B168CE573597DC5A453D76953DBDDDBC1798F8A645AEB3 -78B6B5BAF60C9AFA9D5F818740EDAA977EBEA0F68E531550E607E6FCB04F3E22 -BC9D6440E1E153C8D780213DAB08CF8CFEB03018942AF980642745D711C7DB1D -BEFD825627798897ED8185D80234B6C087FBB602ADB1263C2A2A0F59AFCA7B09 -EA4ED3BCF936C2DAEA9C8DDAA90130C24AD1A1BA47711CC760FF72EB3F27C165 -CA1FDCF1250C6CA4A788AAEEE08902AB4EB03C6EDF281CA2F5B074C859DE3963 -27F7CFC53CC91C80F779ABB25F7A6601453DF5606B72EC562F615A92C1DCED58 -3911BE7784B6E8B17F8993E4D5693A327F9C289701F39ADCF583BB4EFDE1F835 -1A59BBC2E6B73CF422D877B0B423E4E8FD116F5C66A4BEB706A3D42E7EFBB5E5 -E73CD03D7A91719337CC8E13F9D8DA255185FBE3F4FB6DBE8EA90AF036A09BE3 -5047B59BC18C1C3658ACE003B6535E42043E4D7E6D79E0B48B3D0DCA36C046D1 -D5ACE0B6F91CB78BCBD144F3FAA3D9D711C9D11EC30B6CCDBF43CD490E9AC229 -9ED2CFAC4F53927040CC8FD26004450889A1167FA34247B7C283A46E4C0A8C20 -AB43314A34EF0BC02C5558746D35F2315624FB9D4A8ED13E3D1A8B80B872798E -CCB9775F985E31E8228B03949B4E35DCF7A41C834E53CE3C163EEECE81A8278C -FEA3A9E3264627D33738170C12F4EB23EF8F00811723FA4FE56A0EFE8ED5EBE4 -90455B690EAE1E8F1092C1AAC07FC418A6790C2DDA6DF739B9B586B68263EB63 -718EAD2B11037C5D26FF31FB2E56AB82773921B00EF07DECAEE2A8FD71AB232C -86865012F1FCC80CBDC4B0E881819601CE2FC5AC36875F2FB5C088436BB11159 -813020F0433EDF6D96FD162F5E3241F88BA7025F2B010208DD1DF737FFF1185B -812864C3049CE325E06610404C8DE9322187DAA7FD90FFDF2DF3C86D94E8E792 -377C1C1F10FDC78E1FDEAF718A2857C4922FA300C8D3FAC136BA2957C675FBDD -21E3A9E29C797142BA6D30FABB0D5E97AABB49D113A55C4838B253AB8D7443E7 -15596B3BDF01C88C17135A74AF78551CEB6B0041BD17ECAF89321E6948E1C531 -B227A1F071FC3558501BFFC842A4F8B80C14D9213E0633485A66F899BCB473D7 -3C72329610575B6279C781714761468C785E426DC9393564979B1D6A6D55AE9B -4954010208883EC964F35E8363129682AAFA2D40E1ED08A4A1DF27F3DB5474E2 -92B917B45D9473AC94EE40662DF06AC9D004541B6F88DF5AA4A36756620CBE83 -1254ED1C3C9CA39B09E0D4148DA552B00FC60FF68E7159F556998EB8A66C8EC3 -3B7842ACEE888BCBD1FA183BAB95B06B245ACEA49F8CC51A2EB01053E99E9A87 -A5198C2FC26E270961FFF61A093A084594E6C0298CF96B251C5F8395ACDA26FC -461E6DB774F6220F8FA04C68519E19CF69EFA73E9A1BDFFE833B228DC19571BA -34B7AC21EB2BF8B1876BD11E128F002AC9AD6A9785CBBFE2D5FBAC307BE7CE5B -DDA7C12820028FBDBEF1343638CE166E43B95E6518A83828AA3C3628779FB2E4 -CE32DED584715FD18C95D38FA85772DC8650EFC42F980A1ADC012ACD93B7E1E5 -FA6453179ADC6F17C94FEA1F4CC2EF6A2A975C687ED81DEB7111F0897742B373 -30720766409C534C5E0A42D7221337FF3C4C59BBD239518F3976DC55FDBB8C1C -8DB9CB4B05B1D9AFBAF0FA1D82B1564AD7FC92B6CB3582F7DA309403EB78916B -BFDC6F918E26A39755E5AD6394D985C92F7927FB1287FAFF2F60248236F918DC -2E8557C6805B01090A037E8D5C529E2D70976A9CBF3785F4BAFAF9923DB40756 -7B6CE8EE83559893E3930790E5917EC3421FEB042C0CBF6CE74F16C44FA08025 -82EDA0833C0486CDA66ACB450094BB65F54C83829B47DAAAC9E4CF115FC275C8 -6BE583008180F2E2C9B003712ECE32333199BBF9772A471EADE59355FF264DD7 -ADFD42FECCD00892FB545DFE555AAA4B273B82BD2740CB8C9ACD144DEEA94188 -D1AFEDFA1FC63557F9E527C00AE7D14762FEC2814487CB60E406F8D4A47365B1 -F7B0E0A56CEF011CC11345674611EBFB5A7C587C34F786498FEE4F0F999AF42F -D955CF2ECC5B64BB1C100310DE5B6C7D106A80FA4ACE0184A6E18FAC544EEDCF -307334E1C2A0CB6E488B21DA3BDDC5B593D5ABD6006D1E2BB56336EA88D56DAA -62DAFDDC379B06EF80E9F3661C6B7AA6787ADD06155F3DBCABAB6BA3A46C9047 -5D295774447BC007D5423B9840E2ABACB5B811B30ABFF547A8A6E2C18A92DEF5 -D30890D49388E80E6EC7626FE3236AABBF64B21E5525FFB7C802511129EBFAD3 -D1E19814500A465DA92054F93FF77864698288510AB599237D0DBE1EECF81C46 -F706515DF10A1D0FB06939473BC72429A42CE6E15BA2C97720756D80DDDC171E -7E8202D385C2E5B4A5A011933CE920E98A09527DDBF49FB4DAF2E736B1E42F57 -354C91CAACB68BEE8FDD10F4DECF25ABA4EFFC4588DFDB9E98640737C015EA04 -A33D5AAAF9AC4A7D288BC9D4A8AAB9B852516E215DF7614B10BEF003EE1D0572 -E4654DBA4D71959D403B936339D41C381FC1A206BFA6505DF3082D9FF767EF67 -437E8C2A14A8B6F0FB98C80DCC42A30C57C8AC3FE83570A1B4AB404374B85F45 -A1056E389A7148CAF714CF6DC26A04E3DE8E2E7FD26F6CDE3E836AE65E593A9D -3FA7A24A32E3E99A152009C8713FF8960FC93A2E49B8F442B81A90F98B99E140 -5F0E0253DE8ACE69F1248040510DEAEE069307FBD02B821D1DAEADE6C41111E8 -37A80AB702B8D79977DD73429695C13DF81ED3B562FF4C168AE03ECD24909A41 -22C579987CBB22700D1D34BB16E5D0B4BEDB4660D34EF5CF0A4FE507198EE14D -9FAF7C97CF769EA9159E1D8210B063141913DD402BAFD515CD746A7CBC061A74 -CD6D6DF78AA722FF543C5379A1AF5102B75C06F73E075BD8531353892E1733D5 -8143315C0C780BBB21D6954119C0AB1D4C89EA67C0AFDD4607AF07D509F481A9 -9045776F08003CB429316307E66E1F9490E8547FE0336BDD8B070290558E0DCE -DB08FCF371A8A9FE905E9C3BA4CBD4F12BB2F512838D395BBCAB1488C58122C0 -CD6D3634C0F6E193E2F2E8C632BB9185B20D94503E02244938D4400F0DD8FB81 -3AB0CBCF32E462A223F9680A14AC8876917ADEDCC9B181D584AA307CFF3B66B6 -F59FC840A9E8D1BE101AA1DE41934C22A1017A8AF69D257433C2D2C5A0474F9D -362A669B4044B3990BF83E8906C5B7E2B45D688CF12CC1FF38F2EA47743676CB -55FCD3C6261C6F5AF002869128882E39E089A6FA108195A8B86CB07913FFFA6F -6D8F8D5C9E897D63C174825286953B9DCB09B8475D0675E09C1D26286107E89C -C75F92D14002B1289A5E11F059F28FA27DF23FF395EEDFD5F22374FF67F0B60E -81D249898A228A6A89141B23918E977BA79C5F5E6CE84FD35F51B136D81428E4 -E4D205612F6DEEC1CE6AE571B30A33DE004A8F096656A3BFAF8BAE8A2C73AA53 -D7984D6777540082F3674304D2C3F17775BDF86A27563CC2BF95F190DB3E28E9 -FBD0716C0F1B0D56A96E2E870882F03A3E160621FB469355859954858C9CC2AB -06EA8F87EA163B9ABC176D704D3C17A37508864381659070B071B80C79D6D60C -7858A32F5DE87B1F818E78048CE81E229FD7BD91286ECD773147F94E7A184450 -D1060F0FBC5A8DB06BB4009B3F5F50EFEECEF8FE970E3FBFEB5ADEDE9EAC6A49 -AECCEB5378A9CE274BC7F25D03CF477C2054D313FD988A4D913D20ED3981CE47 -8674501E487FEFE5DD91CB0E5ED24BE1D2D45C88DBE1378B11F6B7076FE56BF4 -8E8925E65FBF23330B9C4A943CD96EEC06A6073AED304CDF520CD2AC1CFFAC7A -6B8D8FFB7327834C9DADF578F250A51BE64D27A2B65A16DD0204635560B47075 -3A054F7159EE483CA06345D3D55EFACD47AD32A9D7D7404ED0CB742A3AB8C47C -2C5CC71EA3E1405D6E114DD53D85C2350D46A8E4BDFD1667C65A8152D9F3331D -6235F40AE36EDB507325E21496725F3351C239207C0C4BBAEE2DC7D2797B8818 -BEBAFCA4FEDBBBBBF3FDB633A0C21A8BBA856D4A3119394FB00AD092E314558B -99CD5B138D4A42BB7B621DFCC2A2E2AD262479E878D8F26195A643BA0D13F9C9 -FCF3B6BE5774DE6F4564FB82BA3B2B9BA29A5F406F1A135D46DB10C80CA11E1C -39C9A74A18D8EEE86C85556F8B9203E00DE0B1A164134E48FCE7F37AAB98A79B -EAD809EA81192ADD3D3C6B35E521AC99E190262E5454C7170B081CB8AE338D09 -D489BB694D228CE9C05DA95297BF106A3B71A99A5F199F122971F5C4B0B9C53A -4344FD111B92AF456697E0B85142B71FA56802C392C886A408558A297EC3C717 -FB803CA1002361034D40420699FFE3C149800137EBA3AD99AAAD74B471038675 -8B073F692D278E0A088D3F51360C2C79A83FCDABE9963A4D636631310E7C6D35 -EF02828CD45CEBF9892C2761D934E07AF32BE74852C13FE63BD3DFF3619CEFA1 -25F5FAC01306FD99A573F0F5F29116967FFA22C9236EE8EB052488C4CC204855 -EEDB80B30838AEF66DD960389684231FAAB83750575E4C9BAE860D9B0F838927 -791AE22921BAF254FE561771B7A9164362D6BD462A82763F6D19737ADA1C2B92 -BD72443D7521795F9D3702F83B04BCF992667CA255A3AA539CB71F25F2D0ED57 -9E0B180D1C199211FBC17EE282E7CA9E078593E6340BA651AB949482A0760790 -E4C3F1446653CFF964B9A3142FF4FBE8C75CFBAEFFEEE1810D38033CBDA2FE9F -B42BBD97740EF0C118C7954FBE81FDDDC74608D036A3BBB75EEED4E1A4A56381 -0F57C993C4651E4753A27684D170EBC495D09202AC0CDC5F10267EF26EF4E7D0 -908F4524C91AD27F43737253BF0617559F2EB99EB26643D8C28B61F8968CEE7A -A79A818887ED9BC3AECE4A35AB15752A368D09594F93B7A741282DB5C6E42144 -EAD79AADE23733A43500563C3AD34E0421D1E3B4642EC1D70F0054E3DB6CC218 -FF930B11B1CCC3E4C90BC523D4635161C89CD9FF8F2C4F6E4127ABF479914610 -4D95589775902AE3993E1CE3D4868A1055BFF961CCB244AE25C76C4CE556B8AF -98129765EA10B35FFF3D24DE1CA68BA55E133084CD2562832630E302C3823EB2 -5D7293D0C760EC1788BA6BC9ADB7AF6DA83C951E0A23AD98EFAD64AD387F7764 -21320EAA8DD04EFC4C2BC011185DAC3DC1FEF1461F3F9ED515E2240433D855E2 -0229E1D5269092D0FF790539D2946A608E82E1FCA5E3A1254B27AA134C300FFE -C7C724824AE8B8436577129608078274BB69FB6A026D0CA48B97314F596EB375 -390574158057D3E1C3EA4AC61BEC73F81C706A6C7A9B42EEACD6A4B5C4E69FD2 -C68AB11CF02CE3D9B7148BAEC69F92FD7DAF6C9D772BE60AD4579BCE18396E4B -60EED65E6E2E62B283F135675C188F58C831B3A7ADCACACD39871EF8905B3264 -567AEEE25FB31D64C6596D60597315F1AD8F74E5577E6C966F8F65B001850D1F -39F0234F0478F6DB136F17F20262CC072B25202BCC8A67EECB03A2834136EE5E -8FDF55397F3572922DF82D25376DA73083419420003E99A020198ED0ECA44A72 -DCFF31392F59E14720BA027A5A5E81B3C32BE7DBEE039CEA50AFD5CF9CB9080B -3952949A3165C5AE1EF9D8C76E0C901DF5013469D55C8AFE1554A74D6C565533 -FD00D77FAA0311910C9C191ECBE1A0FE30A4FCDC3909D4F6322DE2DE90865099 -ABAA1A087DE9B4642DB649ECA28D40631EBA0B3902EA6D70F9260EA9DACBCE35 -8EFFA26B2E8BF4567406788443950D8A71339F595C83E28111FC90181AF60EC8 -9A7EDDE1989A2678B8C570F5D0BC178C4018626B9AC851604F03C98469EFDFCB -BC34589B59973E918756A2C1BB7D1811BEAA17D193DEA92EB273D50AE5C0FC30 -661B330B083311E5D971D70DE46E2239532FAC9A6D8FD913E6DD03F42ED6148C -4F04E6D136D41C24BD9B973109A9B63233E51176EE64D247DE1C5CBB43F568BC -DBD5A6AEDFB68E5A0C8DC465E9949A96665AB78F41132F96F3680B5A9A79DC44 -828FBDA04368F277C40F629961EAA9F3B253276EE252478A9F409C2FB6447C65 -37AB9FC9A216970D7BF6912FAFC92BA0C000A58950291FB3E47F0DFD493EC7CC -A99555CACEB7EC87F4250AB92E7136500138087A19053E9152B6F007B8D3DE8C -96224FF8D464BD3289C08AD1E05B9D063375F38FD42CE97ADAC4E5B83B8A88D2 -B2634B95A0DC0AE6A407E62D153BFC434B42680FD0F62F5FCF0818182F182D1D -6B9EBD47149F8506CF38BA61D8AE460A8B660F40DEFBC9243154E5683EA8D574 -8D48276FE5128F972D96E42D89E374F7D8C72E70F84F028263507BC96F6B2B92 -EF4B992CA46361BA3EDB888A6E5C57688198EF10A616F7DCCA55B4E1645FFBEA -C2201D5503101C400B147CA23A805AA95FF059120C677C32ADC486DCA6E775EC -23BB704624D3755E09505C395CC3AB83D68F10E2D6E1497BC179F3CA82A3DFC2 -38275D10D3253264BA9C32DA47C0088660037C7A789C1DAF75D0476BA9ED5B62 -CD30BA0E268DF3537F8298BDDCA16B1C970C2863B21CD839FF6B713438447A4C -C58C1F0ECE39E126AAC2353E31B6FB808253501CF26AA3AC48433D4CE5A946BF -10347C814A195929213655345791FAEB7986B1DD4F2B0C9E7116B11A4F1157CB -933B48B488B7DFE700423AD4FAA7E26F003B87B6255BB607A3A639830D68D663 -A3350CDD992B528E3D2176DAF79AC03F6455B1BD626ED15299042B46F03BB46B -992109329C6F67F1CD92A620FB4D806558D6CFDD75DE4F7D6C558CD5325302BF -ABBF40001F90CC940511F63F32F112EB958944E37A603642C0CDFC7941D9EC65 -F1F5B2805EC17A6662FABEAC3F1A7CE8A4958D64FCD57759F5CA294236B5834B -0071972DBCFAE0D89A1BA76FA1EEF2C8ACB12E45C8D8939B3EF1DA3970ECD2A3 -30AE415757A89E44CED997FFF9F6378FDB532ADAFB25872A690137609D91405F -4FDA7B432D432325F1467A7C85363A9E2825F86D5B9F9523E53FC5B58D82CB28 -90D43D172B2CBABDA71E5B83928A6271468C197108584BE45647AF5C9BD930E4 -18E321AE20B3D28980B1CA53F8B2696043BCC4C925F218B0AFF8E8C2BC1B85A9 -134BD28FC51E5F4E803761720601C5D9D87921116C342D832BB14EFA08032E5D -7C0C4F14F118883DBB1CA0313B6658E3BB5A7ABBA4970CAB64E66515031BEEA7 -F0311CD7DF8CCADCB38103DBB1D60CE59FEF567B2755D0A65100C8F8EA622025 -4AFEC5D179796C4F87808A76B3F420A228544CC12427AE7A5E2FB6CD76D4668D -BD5A22FF8161EF3FB20EE9FE64EFC4D1E466DEF81D20A395B020BDB7358E80D0 -6CCBBB8725B9AB973B060770E4CB902F429D75295D1E5ADA0BDC01D0DA7A4ED2 -A21346CC735F3E6662B87BCDED41C39EB2174C5ABD9C89A4A6554B3523E08BAD -F208FFE1095E6641C548DC0B7116851695AE8813E691347526DA61EC59DB43E1 -03BD503968825F7EA207E22EA04656780C15E1E9D0A00CF8CEEC4D3FD48A4E93 -7E82A2D0F952F5ED616618739ADDA48480DA4665526260E4269F135C89C2F28C -28B435A1A40C924B79934D6CC536A58D2F102CB46E4C3F6F5390008A7C7B5E28 -4044E385A5D6FBE641B6FB074C4E15DB9D25152E503EB7DB52F45913FBD962C4 -550310BC3592CF1C56A7E19A73261219812CA9A818856901E9F0FC46FA53FD67 -20A7AF35375DC845C8A9BC82F46C061F46233CE3F963C6AC49CCE0936A1813CC -F7904CBE756A07106AC3D9B58C28EB405FE50A12710C7FA7B4F6900E163125DC -43672E2C565C6959C412F7CC333F49E0FF5B1AE666E0770255C43E1779A67D7A -BD794057140D8D1478B7B3C43C84C2C2E56DCA12A1A536F80B16BF9C5244FFB6 -906F2729E0D6C3A6AE9A837CF39F81668CE7B299F4EC9825892A961935E4C81D -7A9FE5D9431283C53770E41DB77A70500A9B21D63B2F073D75D8E11579FF7C63 -3D1BD1D11EA3C49A594D1D83A733ADB8D887AABCB81C32E3913FC4B2DD1DFF11 -10C193CD5D5D5FDC8080F9B99C9B29A86ACFD94EAC9E052790D6A46E5A5E946F -6AB9541056CC23323C09CBA556F1B0F28BA2C30E039B3552DDBAC17B9311BF1F -648D3527E8650B3FC89CF81256E9A4A9054D9F1A9839BF7E0B875D25EAC8AFA8 -2B5663DAD7CC7DED3206BF5957291DF837535DB23BA63F9F7ACA7141E1490A68 -327E35FB7888C160C2D47BC4A7CD84194FF52646DF43AC83A51489481CBA4D20 -1E5094E7AC3EE66A5828BF1D87A530D7786577F164AC3D5C0D624FC6CF1DDFFF -C2 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMSL10 -%!PS-AdobeFont-1.1: CMSL10 1.0 -%%CreationDate: 1991 Aug 20 16:40:20 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMSL10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle -9.46 def -/isFixedPitch false def -end readonly def -/FontName /CMSL10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 40 /parenleft put -dup 41 /parenright put -dup 45 /hyphen put -dup 46 /period put -dup 47 /slash put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 56 /eight put -dup 57 /nine put -dup 65 /A put -dup 66 /B put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 72 /H put -dup 73 /I put -dup 75 /K put -dup 76 /L put -dup 77 /M put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 86 /V put -dup 87 /W put -dup 88 /X put -dup 89 /Y put -dup 90 /Z put -readonly def -/FontBBox{-62 -250 1123 750}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE -3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B -532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 -B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B -986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE -D919C2DDD26BDC0D99398B9F4D03D5993DFC0930297866E1CD0A319B6B1FD958 -9429B9D40924DC059325D9D4CC0344F3F997A99E6CC0676735EBCD685AAC9142 -08DAFEC78BB41AFC2F1C219910BDF41D6279284EF600B69776CA15BC8A34347C -30783C52AFA60FBE3E353E2AE354CF87B558776A22C776C7A0B5AB5CE1F941EF -C2D9CAC37294BF407A671F10E4743BF842143F4F7DFEE643BA3BBD8BB9E3F24A -BCCF7F0ADF8BA500620C81033EAE8C4EF2C1DEF13AC575F1B3BBB66F093D3B78 -5412B82B67FFA087AF57182B2230F9F2137180CA58A7D9B2C822FF04BE6CD01D -43B2CA7058C7B953F6D9B5D6E91ECBAA5CDE1159B0E59C83DBAD96D6C8C8BAB1 -374EF652D10C0F3EE7104472C98DD3572AAF2D45A70BF7061447E21EE3C3BF23 -DF39C2D1B35B42CD5297BEBE6BC94F7C9DC6E61EC67E4F677256FED9064BD3E4 -B51A71B1D27CA4E5AA9E1D8080E6DAB5310711EEF87C40859FA935B19524AE83 -63B163FA8397BDFF443227FEDF7DB27DC35D89FB1C5E435DA0619A5C88AFC73B -89A2DF5E767C5B536BC7167A840A0C32BD57A14DE69A7D0D819AC36FF32F908A -5070F32983BB007437E3500799DF5E0AD3710A4C0000F0098D5BE99F2EB9C1C2 -C444FD9552D0DCA098A94B3BF176F511CEE13DB7EFFAED7C47B5ADCF8D4700F5 -7A5FD1B49560969BF5C44F3749370663A04776F749DDD7B50674D93254426C4B -EFE264BEE7810EC93784B7C01A7F29EFD92547E13A2C7851A2E709FBD5B87850 -4A44F08F56A542DBE072D2FBC58D9E6468E1AB858DC35240E30D31C7AC13D6C5 -7D2BB634BEE96FA0E10F842B11A789F72A333DD6DDCB1BC23227EBC406E50B40 -30AF0C48E6359AB0C46898CDAF1118E46BFF8B00F54EACBC2AC262AB898C42B9 -2E080C10DE923C18AD2A2BE7ABFE6A00500618FACABBD844A515F5D7C7F7213D -7084E7361377127944EB80BD687ACC3F3400538570CFA3A299054F000E0390FF -5478FADAE4484DB8477D6E5E843DA9465F52C8CB88994A2DCD7BACB89D10EE84 -516D7ABC25A54AC996D6EBDCA47306CE267AF8AD5BB041EEB9F4B2CE4EAACFD1 -5D1DB53C1F07287450201D43E3AD980A644F39FB1FCDCE21711FD48169A9BA08 -EC2A65050703540945FEFDD28556DDA2FC55F7D7CAE89F4D176FBCB9A08A7BB0 -9F6F402A5087641EC7DB75D2CBCACADA9A373AC28AA030584C930A4F787C0D6A -2E1F7B837C949DDCF59E188349BEE6721335A3AA15FD72464171B978C66C24BA -5F94014AD374ACC4DB2D6C93D3C8FE5091397FBE134513AE4AC018EF044AD529 -02E2336906FE185C146C54EDCB967A7619E4403F9CE78491DE897A99715E0724 -028CB94B23C8141063150EE57F90A6BE0994D689C8545D763A8C60BF8A14AB1A -74FFD3FE096003CFD3A7C4BB8AF842BEBCF18CB9A22A575383956D85181EAB6E -C2D44AAB62708F00DEDF1488344F09D1D08B3EDB11D617A161A473A7570E15D5 -600868BFFFE8400320EF767806653ED6857CD72B6F038133C56AD7CD47A7B38C -9B2D909F4EAF9958CA3CDE2A6227254D968E72E24D3005E97C89927193F648D2 -D2FE80F2845860B7C3B3F23570A2C1C5BD6348B905969E3322E72510696FCFF2 -901F55946BB66CFD2472A24C3093964C546ECFDAD7FD28B24EFA1ACA58EC7BBF -470572D51E602B8AF8F42F8043D9A39D7598B61CFB7EC1E09E1FDE59A3AF2EE0 -6E402EC1335C147FC7050081CB486676A355508563FCF063646D7AE6224E0C0F -397CDB78934CA760E52E113AEB044F20AF17AC32AA85C319A58541BB43313032 -7374EFFD2DB344A77995A00ECB28192C3D65124F40A37E8CB3F6660204FBF2AB -CD193C8A1F199F1E92196742CA88926F6CEB7F72BEA0182365AAAE458A163A41 -3A9F6E8EC5AB9F8A73BBB46591F87371178741A97AE3B39EBD8280491FDF2584 -1F412CC3BCC22F2F7892A194E548D4B5712F7AC3CA4C5D43088FAFF53ECA3892 -65C6AD135E9D3B75B7606E259DEEA083CB2E9C3822B2B02C4A42A965DA50C3BD -7355FB5738E25881777111280AE04BC1273698F7BE40E33151055C8DB4E2F38D -F6A6BA5DF17D13494B2739328FE2544C893A43759C9D615C41E85B423DAA600B -4DEBFAF52824B3D296E1F47B666E2326FBE1CE1802252939F6EF819BE3A9338A -EF3DCC2B84E3DAF00E7C0D45E44840F8793BABB055C561E0928F7AA01B5955CE -E3D94A281F2D47B024D2DDFD1BE0D39263D097FF18662A63EEA49594BCB4F66E -0AD12249D6FBD2F0B4B51411884C235A64AE1E698CDFEED19765749F1FC5C9E7 -BFCDBCDD7F23D394EE73F2B73C65F0EE1C1FBB4000D63A2D1947CD869575A429 -65A8B30EB7019F74B2B2048898B27B0650E2D291C8D3337EE09BEE0A8421E2DF -0D986E66F97EFCCA660606F0B0A7B18339FC44C75134D8630C74FD296232B686 -47F3EFC94CBEE564EFA1CE4BD13947B32AE6C18C198FF5E3250F0BCE7A292004 -6DF7BD82592128AF3EB9DA27AFEF27878C75AAC551A9DD748DB7F58160C33C51 -3B28D39C1783DAB4696FD05D00D9A676083EA828D833649055CCBC47D14234AD -F2CE3C0A887655FC28EEACA2EA3258DD0237E1693F9E6B59815639757EF4D63E -837AD18BDD32B8E75D6AA862A057AEEB7201F5FED012C2C1FB3D9CEC057D3E23 -5723187BF8E37A6C8E7C0A4D19A78654D07C72725AABEB05958EC35617411FB0 -E66D2BBB10216B9AAAAC186CAD162E0F9D9953871816F1FD1A5423F43B2BFB5E -1AAE96834566EF0297E2D69CD19D6232CA6D5B6E9E9B7855796817F0DDCBA391 -B523F461C746120683CA7F7D123BC715A1D1C4567EBCB3B27CC2F66CC022555C -53AE7E06DE7B967D6F0708224EAF72EA3C4C349C6C1DBF4E3F9EEDD8D344FF26 -E0587F50407EF2F96B9FE5D4D1EED501BBABB525E43B9E34B1ABE4B4EE73C296 -CE2883BCDDADF33E48C8A879065E0079A820107AC5321F61F7A1BE6A9706EFB6 -598C0FA5F0C81C9E48CA22F86A9F437068711CB834D90CF79515BC7074C0E2BA -30E0486B9EA0B3DA075D6FA4BA44ACE3031E166F9BC8D293683C1D3B94A2653F -442958E6508B00EE81D879DD8EA003AA418A09893AD298C4708BC328A0A21A55 -62177339C36961B86AFC97EDB88206DA6712353887FC431D60344E483212AD4A -DF9EA4632745674A51067E5F308343E5D1B5845FA6A623BF4ECD000B368BA9B5 -9400034817AF11E3E4A5F8D00368A93E5D6F1FDBC3CC4B0065208B275B9858BB -40E57BF7C98A4E8158E84538E7541FD3FDFB11A015951187F875A0D8C9B7FDD1 -BB3FDB57F4C1D89B547369E1D52CF180C7C57F1F4ED0F93E98BDD54DE02B2064 -30D15CAC1DC1FB2ADA7D048AEFE4290B7F7E2AEBFB3C7D41EA1CFA52EA515C07 -520A359529A88CCBCA53FEB15FB263D01CF5DAC4096A00E5C6482841CC42AF26 -601A8101647FC35955587C768B7FBC7214098B01C53092C4869F65CD1E0E8616 -D6166662CCD0E2DBCED327A7C8A65F2BE7A6F2F5AF70C6722D3717C150F4BEA2 -C50CFD52C8473E80197084FD6220447C562981C6ACC17A833B6D88E3539D02EB -84AB15E42E4DDDC5A8F8EC091BA226888EBE1985A465DADE44B283B7EC620986 -1D6C8B22D7D7B5FFD77185643146D49B6A5EC171969360AD890CBDA38F7DA67A -AEB2ADDBA1EAACAF16A2C76080764DEC104C99359AC7B606197DEC3F91985097 -0B173D6DA02759B3406B1F05DB46A51DCA1B6A4D1BB709F5EE1C071553478ABF -AD71F1A99A6A8E488B32D0575ACA020AA97D9E107FCB5C7BA9428CCD04EDBB48 -A1346168107718F3C98978CEC898A3494D96C724C355F01C04FD608CF1B9206E -8507257264443BEECE2C8AD2986A5ED9CF5BC20F779856E29BC9D0E44CECAF16 -38483464B050DF21DB51C9AC852B60362F3FEE49F54152E794DA4BB628F1F1FC -0C7700599029ACDAC782DB220CFC678E82C09E51694EE72E821ED4CE5B524F38 -05ADFD38982E5B91313757B55FF58873F8FF594E177301904C33BD54DBD196EC -437060F04CEFD4648EC5D6CC04522885ED6F1887393B6E6836F3768C9207EA1D -9CCA8B396BBF77D4FBFBCD401206B629AB96091B729FF137A152BBC0485E49C9 -A0BA737BAFD17F53F319C202A90CC8153EDE244AB5EE452687C496C2E77FAD68 -21DDA15C279714E0F6864882FB357599424BC7BE8695089F89C76F12818825AA -8E1BCE2EEB1E038B02ACDDDE39C803DF4C8C0D38228F852A1DCDCA97912C59B6 -6C3CC7E533CCC630DA6920C04217E141E2F32AFEFC294A58AB3C95B326EF98EB -56E3F430BC78AF90D61BD5E810C9887877E93DC4D95DB2DC1D2C3C07D9BEF1CF -EE6FE5786CA88765C0899133AED7429395326A22D822027A4BC0475FE2F74EB8 -BDF61C69C950CB72F45A45F95920E2412B8D776C6E8BD6338D3AFBA07793F4D6 -7AD4CEDA52B8CA8BB8CB29DB49F8D5A920D1E167242F26C7D51FEE79677FC4E7 -0E711ED65A8FF70517BB5283E057D8C8B1175934F9567C4C7BF479839C2CFC76 -D990522E64E93579625F51A8D85B5CA4E3DC5ADBFE802F0B835F664572A2AA40 -2EBC631BF40F7F53C12E1156048ECAE68DEE3BFAAECB70013B7DC4C2ACD5DDE7 -D64C094E0FAACAC86246C5B9D522F483189D359DD65337DDCC6C4438615A99DC -1936E0C20D2109B3E7023F019BE2F006D12B5AA643C7B5443D73B7A3F28B5B7A -D8B8417E5B747A27FCF19B5263D542D6F2E02918E0B7A3574050641104FE2711 -33E011619A91AC3D293D98EE25C2549C895FA14F749E76BD4E81F4FB055B8FD3 -F2F65DA710EBEEA9AFFA46EBD7193F90D3112397A2AFAFE84CCF9DE1EA2147D1 -907C47480FBECB6A6EE3BDE00C63187143E74F35C2027714B30FD5F09D80C412 -BB820C5A8A30F3F11D395480FB43C20ABCCA913E6EDAACF7338A68EC3277A344 -D571E1D2CA0675C197BFDE9B37EA3AE6A43DF326E0AFD91D9514A962E44617C9 -AF848839DFEE22086E4EE1077403E9916D32348D4810FD973B7EBC4086700F29 -2F62B0D59571A52A88E6E8A64193228349E288173F794312189F2BD2E1FDCC97 -6881C1921FAB253BADE378D303BF2277DF8BE6D1C7A56C36C6CF3D74C6520AA2 -37333C8C0F4A8F1BBDA2FE5920997235C8C8651519DE875BBEA6BA56C065AE5C -6F8C1C6227971E3DA49BE96C70263FE2173A3363585096B304DA49E46BBF6E34 -715C7F41D56722C326CEA609CB72907D0732EBF080B538518CF0CB0635B0F97B -625F051EEDE437AD14A05A84DAD051E3425871065E4A2615874C30C0149837D6 -B5A2893A49D062658008FAB040D27101F1571AC352ECD9672E2A30027E204EE9 -433676723D012E8CC81569EC240B50C4902C5D4B30259BA95B69E82D1B81597F -CC48B22EC65F7237AF0B0A1595707489AC4452D40456E1247080B58A98419EE4 -4BC1937D64008ED2B1E7C13D7FD261BF3B63F65D7EBB05A00F057D78554AB6A0 -9AD437F65A25158A55155A9CBB0866DE98A2EDD5550590EEF0E1333DF5A974CF -39E4A61FF9F8802F030DEBF5039F962133D952073494FDBDB161DE14A84C6B62 -C54A5C749AE60EBD07A0C29842706B74B75BD54D5092694B1325A58D5CDED356 -CC6C8F81133915F05995EE1885991D3B14CE0794804F3BF58D5CE83BAFA05D5E -A005736C32E209E08555E88798A225113FAFB91F3946B290859B52D94C011F9A -295A554C3793C20ED3E3A6B5BE57B533E8FD92A5DB0F67A048743EF6C1BABD9B -FE787A1282E24B098F1276CDE25C6686E5455C8C84B19BEC816D58A5642E1660 -8DC4BF1D7EB903042F6B57687E6D9A25058DFFDD5A55D27B4E8E30ACA5C11A90 -CBE71DCD014E3ECBA954DE2EAE0E96BA275E6D5FBB2114BBA5D4AB02F9693545 -A2F3307783FC641D1767C8AC174B98876767E4ED9F6E22DEF90BF7BA35CE7173 -C7471745C7E3FFC15D15C135A87F38E96ADBDF35A36E86A8C30BA572A4A22FB0 -365A02B3EFFA2491C3A9CED6D76E9293AEC8724E46DA15312444FF8EEC21077A -26E54E8CD9B077C81EFD5745973DC67C072BE37D4B9B7C6C3E6DE4E74C035022 -52ADA17568968E18CE102CC748D679219D070864B2A465D6F4A2A0A4A08887D2 -BDF4865CEE5BBAE5C764373A5B44EC9B399387F79B84F5A85A5DAF403F64CD29 -6497560F918AB1D65397363498FDE113D1C43085B70F3761D6CFF81C64343B55 -113754EA46D2CC06ABA93EE3D388AD8514579CCE2CDE11E14C9C1FAD283F57AC -607BD42A8DBDFFBC679BC1B858A95F2A1F2BDF280E8A19C98EA5E5FFAD402AA3 -F03F1806AF305F072CE35F644BB0C095D38FECCAE226C00B63D26E367234E1C2 -12DD8D4D9CD3264A39749A76EAC7E03D389D6AE33B068B2D42A947C2CAA69295 -CFC49CF12D9898F5A54F12525B668555F97EDCFB8B0701A14DD5EADC49BB8531 -5D6D7A1A4C78C895154F4762BD3F34DA3A3836F1B52695A064530984FDBD32A1 -D064359695307BD42FF880489735008C405B63214F58EE970DA4F171BA941499 -EB22232F4EE7B4E3D6063CB4FD10DF9D6EABA14220B994E5BD8CF96E21F966B4 -9CD5A96EA1DF4430C46B043BDA6DB7A3C581A67AAA1773E8208E45F43DE3AE95 -8ECF8210DF6A0C3A69FDED35554CFAC2403BBF4BB808DE0DA9BC3EC57604F150 -17169E5A4BA101C020203EBC7CB27168348087687BA16096105BBCC82A0529EB -6E39BEC21BB348A074A0F2532307ABE656A0051F1B87C2B762074F7EA6A2611C -42244AC5AC971E43753FBCA6C025A5B9C03E573E0A9B42B43C2CD0E9FAE39E49 -62490710A8175427337E393F80DF3AC43BF179CB829DE6331AB86422FA498833 -D1C14F83E443DE738C7A9BAF36531D6FE7274FCF51A152B6447B15275AC70345 -A51815AEB0C014299B15E880D593BA8631D656F33A56B5FC851AFCE74EB8640C -0094ED50A6931FADB9C20C453690BA4D6EC88ED660AF05316DF2186757B7CDC6 -FF37755B746DC9FE45100117F1B8093F96254973D54B9DC21AC8B430DB9A6A5D -6CD60B3C822958C48EAD747F3C8AB10F47B29382BECC04D96B24B343CE86E7BB -C0926A6D6DED8F9F5E9B05F1CDFD07501315DBF2522EDB572B5724413A8051F5 -D84DE87C7D8C505256194D083FA9887166547D96576ADCB15D9A6A1A5886CBA0 -46372FCB670C6E95E2EA81DFB3511134C0CEC3C9280944958B7FA2B00D6A87C0 -D28A8C30A8F6D5FD6C61B152DA5D43F5525FAD3A004055212BBB225AB5601B65 -D684E9B4CB5DB6493BDF74B1F75B12F33ECDD0AD8103F865A36F2309ADDD8BE6 -229CDB25B3A922B591322257AB8A5BD62312758C5185D34B109317A6893CCC3F -BC668B9E0EDB1885D9EF6A6F1077CC9B025C66F4E20C0BD2326F82BC6097A63E -E332543684D7433A7FA613E82CFBE7D081B484E71B5A938FEE191AC8C9C79A2A -929E58EAA236E4FCAF87EF1A1DDE828A84D5D43C25F0CCCF3977C79DCDFEC056 -EFB75D03777F00F5AE7833F0EB91BBC1B6EE60B9CB8D6E774F72745D21FDC5D9 -472332B20CE5A9887550310CBA5DD35532E4E7A5C810041165CA595B2285572B -29AAAAF676D81B1A028B7D9503BD9EB46B4C2FDF24CE4FD5926E4FE2E53A0D75 -167FBF24100706E09CDA5B76C4650F9CF9A44E95560CFDF63672DEDCA589D737 -F4E48F28CB42582D4ADB35494B41A4D37CD59986AE9298E1B191538253677D54 -E0DE24266E195A6EDD88B9A5FF4C6A64B20194E86C551953458637878E41B944 -8299B195E848D4A51EF3AAB030AC0048C780A12440CBFAF8531859586C97E826 -9FFAF28E8BCF0AA7188CD31FA9F1A4C4D96B01C8F1E64895F16CA9EEDE3B1E05 -963CC6B45F0E5C5C5C62BFE4522E30CA010DD477C61FA989F6D0F1D3A17ACC9F -5A43F41A6015A9F942DBF8FDDDCD7C27B4FAC601C0415982E6FE6CEFA3F7C1E5 -9A182EB2235D4136F11D6F408BADA58654A928B58A24145E1F4B0B996D93635E -AFCDA40907CC13D1C1199ABB4F08E015C8B204A3A6EBCA8EA9A2A7D3ABFB00B9 -BBD42CCAB8753DB0CC5968081A27F638831E8A78EE7CD3FB1D74C9355517A1D9 -3AE0BD6ED674F581B398F1ADAF2AC848413BD4AB04B606C7D45C55B736E3F7F0 -17E77DE215FAD7AEFC628062E0E5513C9F7E629CFAB25E14B4E04C0E96689AA6 -8F6034FDE0E206CBAA6ED4D0799A99B41105A5C136CE05CBE2700B7B0283D376 -782D3518644FE0AAD2993CCA0CA08A70A6D42ABA5EEB4B0F8BC6F729608BAB40 -9D046BE1BDA44A9FAE8D534C365D0B8E6F39092461029CE88B843E33F93DC572 -B49C727AF0127907FCAA339808291BDD960A1D65F83A8AB8137D48BE5D0C7496 -439E9952B2667D999916C770FF0F8833FF9FEFFA76FDBD8DBFBD8673D95CA735 -28452636631B8717E5081A8B41A192836A9BE01B60D545EEAC2FFB961D0EB73E -7E0C5230E9AE38CF6754B6C6C9BCA4B819FA08CC989430B849FFA13260691523 -A03EB48C15A50A3A044C29BE621C4F8C124B53B09425AB326CFCB449759EA353 -B569DC0D6D1D7DC29C8B23A31F35A94CC47148033635C787E406037B1C618E31 -E3B43A9402E60720457F60BB4D5A31FFE1777644B053CD2BAF0D55DEA14434B2 -F230DD01934F90C7D3A20363058D96056ADE53FF93A84B6DCAD0CA78132BD6CB -8C3C2C02F569DE5FD19ECE80891582B445B9D2EBD93A8402948A2BCB5940C75A -9B7E35BA0A2F8D51F41D89D1D221887023521F707DBBFC51D3935137B07EBDB7 -FFFD435DA22425413DF92F516AFEB3F40BDE4BF90556AEAA944DBC5D8F17BAEA -67DD983C2ADD85D37289932A6462B632725EA66E3A335AEFDC40C5533EEA296F -CCA86531DB67AC517090633AB4DD8CBD7D8AA219FB1D58BE0B12E85D10E618CD -0FC6A362B042C6B9FCABAB9EFDCE81702A0F8AD3C64E4ADE4DF40E88197752C7 -C89B8481FA463C3845A4226DC7E7F613197D689A6956906D487195C167EEDDA1 -F4761DED3428B835AFC14E6683D7B4AB3CD54E3EF8D0CD312D29AABE4A31DA9A -1E488867F8B981E11207ECD854E55DB368A9A5BC9AB5FDCAAB67C9F0B5C27EC9 -EE29FBA4B8E195B8CD9D53D9B24E1830494B6085540F5467341D23C581FEB427 -52AF14F88D590F71F3A43407521FEB0F6F6D3885BDF79C8EE7414346853CECE8 -1AB8B35728A13632371CF9456A68C760155FFCD23D2029770AFE5DFECABE6571 -15FB24827CED98A2E39C9F3D3C6BC168191F0A32E1D4A3A6EFEFE5331555CE4B -AEF8502F2D20F1B561AEF8DDF61FE9A9C0DE17E1847B8C18342682BCEA1481B4 -2E03967B9393ED8F64262CE87F5732B2A8F5C8BBA53068CE14AC143A41AFE6FF -7D1BBD08CF1C89C3F9DA27436745AC6117B9C68A3410C1C0143A97F62FF7EE55 -4D23E7ED7EE9C31EC1913BC091E45E29E2EE681FDE83C55EBEA07BA7BE6A8883 -80E50B0820C2537995E2AFA62782DE1E30EA87A569AB931838BD7024D297A690 -106179136110A244859F1D5ABC6DBA94EC87C9DB9DE843AD2F05840D4F90E9F1 -91C41D5FD756E25FAD3492C463315A556A63D97F4CEE0971B8B9D1BB30A58665 -FD37B4D59A10F5365E3455A3DD3A732E5734279B6FDA63FE903CD70BC04D1358 -2AC8F9DBBAEEE92A8A933410493F9F186EC52F3304D50037C96A419A281541B2 -ACC0E5A9BAC9B7FAA8E0BD99B5251259A1A6EC8D3BA47974B9613948516857BD -A3B84DF70AFEB122B14982FB1C3E88F6EC2284DB4B4C943A2854FF29B4AF65E6 -974332441DD5C83163CCC2F174AC761B7C702AB6C9754836E8BC1EF7B6A5E7FF -9A86F51EA594E2C7CB13DABD156B477FFEE840EEA55129C3994A424F69AF08B3 -97D1663E33175B1159446831411E2F8C8CCD531FC46BDB0C1B590A396A3780F2 -FC055C5C752BC9DD17B1A4962727D4D255E5D6080661263244E38E1BE17043CF -4DB4CCA19DA7CDDD94988886604746B49BC36C73E168FE7CC628C9F6376D3DCB -B4DB779C0F29537FC2F22A5FF5DBDC8738D32973A64CDBDBD0FC8E956431E871 -8DD8E33DF06557E28B064CE7A7342FB658016BD92EE67A6E1F5389E977A95AC7 -29BA4581090B2E4D7D53B20F56FD9311D86A9CCD61D42CAAC4977674C8683193 -948DEB37FE15675B798F176632D7ECC56D9D48CFBD3EF0DCCB540BC072F887E1 -2BAF8767F80C248CA2843E9BD7D3ED9C693B6B2BF7769821A6E813518A810780 -EE9E13CC85358098797A1B19CE476831D3775D0DF7C7B90A8754E3D91FDA2873 -858030879318D96CBD2220402A008ED4040241138F4A7A0AB8E9356F6D53F819 -DDEF5FA13FB03DCC0C82CAE070E54A17C72B04A66EED7E6CF236C9CEA7E0BBC0 -29F6AC55678C3469F15189A585AE48156F620A2FA122B4F028E936CF5710591D -17C0BB7B6BC53208849952DC5184245FA6CDDB9AE599CA076F3AB8CE856E5B0E -9EEDE67AA13E8F5089C2130ED6A053979E0C62A104CACB2741089189F627099F -42C3B82D792D7ED93CD0D63C87F0FC5FBB74CE9AD5DE2D81CCBF067BBBD2C323 -411F1845C287B87BCFC5CCD50DDFC6B906E8D89D4994C8188D1DC5A40B0AF52E -5E8FF0F22280DDB503EEFED2236826F2EB9F5C3A23F343DD129A3D534D28548B -F2B08FCD34D33AA861266F62EBA0AA48C85A0D4869805F235278E49D9BCDDDB6 -7C293B8BE5EABB67E64247AD01451912A522BA99F82A1C50087474F2C2020CED -DED7584E3356566100B06A492BF76E6D0914D9A684ACF99AFDDF909DBCA11A87 -72FDDAB73425D666F55884D53D8E6DA6B8C1D6842B809A01BD806B648652949E -A7D352FCC8BCFEBCDD860DC736CFE87B09D47267912558F15560328573F1E163 - -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMBX10 -%!PS-AdobeFont-1.1: CMBX10 1.00B -%%CreationDate: 1992 Feb 19 19:54:06 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.00B) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMBX10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Bold) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMBX10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 12 /fi put -dup 45 /hyphen put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 56 /eight put -dup 57 /nine put -dup 65 /A put -dup 66 /B put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 72 /H put -dup 73 /I put -dup 76 /L put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 87 /W put -dup 97 /a put -dup 98 /b put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 102 /f put -dup 103 /g put -dup 104 /h put -dup 105 /i put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -dup 118 /v put -dup 120 /x put -dup 121 /y put -dup 122 /z put -readonly def -/FontBBox{-301 -250 1164 946}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5F00F963068B8B731A88D7740B0DDAED1B3F82 -7DB9DFB4372D3935C286E39EE7AC9FB6A9B5CE4D2FAE1BC0E55AE02BFC464378 -77B9F65C23E3BAB41EFAE344DDC9AB1B3CCBC0618290D83DC756F9D5BEFECB18 -2DB0E39997F264D408BD076F65A50E7E94C9C88D849AB2E92005CFA316ACCD91 -FF524AAD7262B10351C50EBAD08FB4CD55D2E369F6E836C82C591606E1E5C73F -DE3FA3CAD272C67C6CBF43B66FE4B8677DAFEEA19288428D07FEB1F4001BAA68 -7AAD6DDBE432714E799CFA49D8A1A128F32E8B280524BC8041F1E64ECE4053C4 -9F0AEC699A75B827002E9F95826DB3F643338F858011008E338A899020962176 -CF66A62E3AEF046D91C88C87DEB03CE6CCDF4FB651990F0E86D17409F121773D -6877DF0085DFB269A3C07AA6660419BD0F0EF3C53DA2318BA1860AB34E28BAC6 -E82DDB1C43E5203AC9DF9277098F2E42C0F7BD03C6D90B629DE97730245B8E8E -8903B9225098079C55A37E4E59AE2A9E36B6349FA2C09BB1F5F4433E4EEFC75E -3F9830EB085E7E6FBE2666AC5A398C2DF228062ACF9FCA5656390A15837C4A99 -EC3740D873CFEF2E248B44CA134693A782594DD0692B4DBF1F16C4CDECA692C4 -0E44FDBEF704101118BC53575BF22731E7F7717934AD715AC33B5D3679B784C9 -4046E6CD3C0AD80ED1F65626B14E33CFDA6EB2825DC444FA6209615BC08173FF -1805BDFCCA4B11F50D6BD483FD8639F9E8D0245B463D65A0F12C26C8A8EE2910 -757696C3F13144D8EA5649816AAD61A949C3A723ABB585990593F20A35CD6B7E -0FA0AD8551CEE41F61924DC36A464A10A1B14C33FAFB04862E30C66C1BC55665 -6D07D93B8C0D596E109EE2B1AAB479F7FAA35279ADB468A624BE26D527BFF5ED -E067598E1B8B78188FA4BCFB0B51692D07B0BEBB930C6F0997B437E2C51B876B -61A563A2673932C2045833FAA35DB22ADE12102335D5DC734AE3AC5EEE6658D7 -92EB62131E1DFBA441F53EFF9021D9D4C491F26BE8F54C61165CAD778CE8695C -EEAF70E3B20C64D4C2B34A084B5770BAB2A974E898F62BFE90F132A37E2DCA4F -43E13DB13C94DFA8ECE2B7374827AE168634FA007F8981ADA046CED3448BF453 -FCD9A4F194FA648F9FC0971734BB69CB73439CB0DD021D44A7C11BF295E81733 -4DFBA460FF3D654F9FB337E99E6D66FBA87A817EB9CA1536C84833870E3626DA -55D48DE850D3E6F6B29DA0E7C9D681283586F208DB8D58042E3A7CE55BE84822 -C98237911453E479EAB65AFEBA3F61A763B40E74535BE56C9D8D06DDF9441741 -5C9D9D917439368736619717FAB4F06E2C329AE0BA411F3FD522D9C33AD8369B -D7DCC9DF993778482F35F965973DE876FA19E109AA198A00658AB3F0D8E3DDD1 -08A573F2D525202AFC57E05D141E6C0BB811E1FE280EEA002B7A45BB363AD06C -318D320D2C81AA5DCC842CEF66E7DF7670588CB39C9F42EE7763A3A17372432A -173BDEF7ECCEA297CCDD76A835C36DCE9DB8F8CB66CC71B4920CF5BF055A5260 -5B41A5373BA6E4F63C85671D979EA5EC30D22163E6D206168A3827F465279870 -CA80E6632872F721BBCC622EE4214BF723551C846765495FA9921E11FE1A950A -53150C3F5D8595958A47E0B16064CC3AFD65DA294FFD111153F4F233BC5468AE -69585C16CFBFCA32C4B96C161F47B56661DF84FCD8ADD3EC086CFB6BB5179BC3 -A5469A1CFBC8620BC711F42D0D3139BCE4E38698D9C574450DB43B5A19FA6D54 -0368BA9F7A8DBF96DCD0B8968CD194264E6DD10A958846C278B8C2BAFE7AAF8B -44C84C955F1A89A13E62A054BC76CABBBF6296DE00A79CD7C8C61C70F127618E -9975B59A880685E126F57AD80F8F4D376E1B476BDFDAC868FB6AFAD9D694B561 -001623C4D9F55366D053B52F2B09EC08B81901AE0986C5350312E626006038AD -AC15FE313FCEE1A2E61F8992AC00CA7BB7F997707EA377D37EA6FF35BFBC2866 -A572B31491F9B80445685DBA5E62F166E80589F768FC95BBC79158C23B2F1BD1 -25816F1486A64F76D99A638AC0DC101FDF390811B3C118C2D972B2E7587F6F24 -7F1DB2DD922D237A7D18FF08FD665355CFBBEE799D3BFF11CD94CFFDBA3E725E -DCF4CDE4307E3B199D91893A365D04F43A5305BDD2538E28A0788E061F3A621A -B4A04E5063B47F0109C1693A284FA43E8F1EA9B68145FF51C005D3FA40713BA8 -1879BFC3CAA881B9D885A0C1AA8BB9A8C848963020A5B15F862E7DCC78F25D7C -56437215999EB78142C128C6CB1E6E75EBCBB1E4614E8516FEB1E68400C61326 -D9F9E8A41216901F77D9466455E2A0B45FF50B27B55A1E1DD4F243C92BA6B175 -8F7695CFA1E91CDD8651AEBA3D258FFABA6280BF2420A98FA7CECD552D152CFD -A8CCC94C032087A28D68332769DD2CB4ECECB15717C245BA305CB616CC72644D -C78326E77FA602364A7B1630CA0BD0282FA781E14282982C1AD13479B6178D28 -1CAA541FD3F4316F4FF81C53496DCDF5F86E0D7C870FFCD85B36C936B1E08D78 -CEF3823546BE4329B97EFA4E2880AF3361C0DD67F77C8BA6F1CE3822B7FBE567 -064ED0477949BDA06483F8DD04F891473C8FBF73A61F7C06B20FB8B5F0BF4B77 -1429190979A4BDB29D77E94D5FB486A93B8B61DBC84AE06B4E06CBDA3A942043 -9F9926F541DDE4E9B73606C3DE3E4E957C91D74BAA629641A6BA8E053FFA10E5 -581F14FAA575EEAFA39C6534A94D0B1BD7A8ADD7B219900B9F300BF1752C4236 -81CA46AEF5361701257648AB2ACC9825BD79FD6663507BED21CC7724BE327C32 -5223DCD4A92411BD7FEBC5C99BFD4C77DFE394FB6D190CBFF7C94837CF66EE0F -0D98EF9BF9CC9B14365F33C78320085E763FC27DA1E52B0006A0019F56E35236 -C5D3C182F26D23353CBAB3DF0625BA335B5B965A15119F1240E2D757837B195F -5B089B39BC8AE493CA98A6151FF1228EF46924021498A17AC49B68B8B555FAED -73449B45A818BB4BBD8A0D5910790C9824F13F5A0D0C07634CBF077840537E38 -E7B5D57B328D192C48DFDF345B485B9ABF6664FB147256268155E04BEB5E2D3C -B3635D6821066F8118281285E3DE0E31DCD1DD130171BDA0792ED9E4588D5A33 -E9703E3A82240D7CB225D971B91F4457AE9A119DCE5670CD46344C1E9367F1D1 -CF9FB36C5541128BEA31BD0E609170433D0092487F28845A5B234434B01BB2C0 -FA3F2E8562D927A5B25BE0DC8313029969C9AC313947C924800EC92FF63127F3 -0AC6801EC1B0FCB6C82CBF7370973B21C9C77CBDE9226278A4B5CC752FFECF16 -8CF30E7B81CE53C3933AC580D848F9CC7F3377E0BA5BD88905DAE82BFD42E1C1 -069C8AE5FEA017F4C8C9AED30585050FBDE9F530EFF051A780E5A7F7897B12BB -E968204D5654BF09156BAFB7DF7ADEB7AE2C0B05416D085ACAB40333D10926F3 -F5734F57F0ABAE2ACFFDD09DB497EFC9E66BEBBEF18ECCD13B09650857925716 -B4ACDABA324721422EEC2DF66005CA076F3657A12537DD5AA5E456FFFD52633F -12B352800E09339568D2F9BAC471B58E108C990AA8C481002C442932469EFA8D -67FD87C9F4DD28C62EDE5C0D58EA1E0911FDF9ED05E032E3D138D01B63F27988 -471935C56A7C7E77DB9E6A3044FE2EF9F721486F229836C139FD92D82057EFD7 -E7FBD5DCF2F9889F31ABF09F119DB6C0A9C2D56FAE51962FA345E78D873BA145 -A1CD40DF061187115093C6DADAD21C1925A83BEBE4279DEA1B78A0183E68DB58 -70409542168F86094825DE53480D281324FF58158658D21B48104B83D6347488 -819B637A785A8D353B506DFC8D58F57ADABD4B70BE468558A73CFC5D0FCBD1D7 -ECD18F93FB4B5125C5DA18FE220B12CBD50A1ADEA8158B4C48E2DB42DC80537E -4DA231CE0464C56CAB8F59FE60393C4C305F6E1724126F765B54652B93C96768 -15F572F786700305087B798177719B112B67BDF3EF0E708A48E8D6296BF3B937 -A9288AA57C8243C6D28DFA1B31C331FE72BECA3916FD0513E85709684D3C77C6 -4392980F0F2859D40903C3AB70270ACDCF7644032510BFDF0965B30E5FA47CA6 -61B6A7D3A467FFB5405A7FC00134B2D5570C74C1E27F5433FEDB15A29C7729C4 -AE8C7F7517718CD8BA705D76008CB471D250A77F7529AD67103FA172B2B482D6 -E6FBEB44DE62F956839E878A52588454DD72377A0CE7DF791C2EB04D559C0B4B -5BC9CD13D4B0082F29D8C2EBC6678050F0C6982DE10D3295086ECFE64255679F -EF0C90170EEE04D0DBC091DAD7472590E5D471239B1E9B8477B0EAF113B6DEE6 -54F55398F7DA7C64092F33FC1DBFADE12B23FE70BA4C9538DBF1C19F4B947603 -6D0B7049820B90804D19A22B8A9C3452CA601AE21204DB55787A53AAD6D42AD4 -9F2A2E849AB4B1F4FC726D0776520D3AF92AB14F3B76AD31E91D47E8FA5EF826 -642BB26EB6FE1BC93675AA40494148AD957B2077BBE240C1DC145C43F53C6DAA -4C5EAB2C91D2D3C63956160CB99ABF21C74C7930D7C9207E4B515293DC8B4BC1 -42DD53FB3DB8F793BC0298044BB2D9F7F8588F267646F0C72181B900B8840743 -A87717DE9694EABF10976EA2FC141DF70BBDAA4E1AED08ABA4E2C386ED629E24 -AB9157BBC4CA7AC1B4016F927473F787DDE44BEAB16319C8694BA592A1426213 -4DFE7039D154E7A5A969FCC2799A7ACA0174CADD74EE4B85AC4D62E1965FB298 -EACF6FCC737604E71381B924D00BF62CABE5421C98211C3C01CA517D4A3984D0 -0F5A24306C30224967BCFF64516137BE52BA47B283A62816C84205A296DD2CA0 -9F39B6FD01BD2AFBD06F66A45645662F5FFA5A3E0C35E6627211181152CCD857 -B2037555F204FA5B7E321873BCF4D84B1FC7C2942EA9F943D199AB7C7B12692F -77D30BF33B3F90905C1CF6AA6CF7FE2D7E7ACD6C296FF0AC39F9EC0335D1B1DF -B812CE8A9D64B833E0DD307DDAF65E9A2B4E7E03E79229F4E183540846A3C337 -B00DD353ABF3538EE6AE68D4DD7BDD3DA51B5097331BD48AE31EB303B66689B8 -2794A8D350F0B588B45632725BB6E7B14D89336E71D744C2E3E3453BA5407BB8 -8E9898D3D4D24A3DA0962FAA7BB24A66379FFB6F0AA077E3B01F2612BDC8DEA3 -CE1BCB25ACC872A6C0A98576F9EA016F723A0AE79BCC936BEDF4C091BA9F4764 -4C7D026ECEE22AC2FAA631FE4EA642570CD3AA905DD810F08F7FC8A9C26F17CF -95C05142A1ECE12979BBCD0F52C0E6CE766C904C0B0F37ADDD3D97154A2B3728 -F09C77809BF1CF46E09AFF024993E7C825A777815B420E3B8997B48E969DBDC7 -4127CF29407C0089ECB3D63F6FA89AAEB2E4AD2D8622A3E245C854AF13062EFA -C52C7929CC42FF622C13B8C13631D09E9BCA05B113896E559DE7CACDD2655C67 -BD760BF29FA4C51BF674A0D5DCA5DA2EC73E6C6101149DF9FFCDC152E7142CA8 -49F9A6277FAB6B35F42A35DB82A564EA0C5989282966A92EF9CD1A37264207BA -59EE7146905948A128002F70022748117950E2A706EA9851B337B3C54F6B948B -B4E92AC726D48C214924C86F27AA8D054FE6C9C471B0D7140CE08319EFA54510 -6DD42EA378FD0FFFCE2458630632AD8130DFD8701080D5F73A0CBE281EE5C3BD -81F49BCB11458164A061EFB788F7D2FBA00FC53E40A99CEBA0D4A6D1FA5D0FEE -07F08CF70575185902C77FF048E67B00440115054959D952CCD88580C590EA35 -6A0EDB91E90F8E0AEE102C2A4AB460257090496809AB12276D3A262608F356B0 -45D393DD4DF0031335BC278C2992866FFBF0CCCA02BC37C82680888C95E51917 -368167ACAC86ED36FD3FB26B2D17E375089C699AEEDA5B0F68D87C8EB6BE46FE -C4CB0F4FC636F6DFF435CFD510EAAFDD266D9BD57D33F71AE47584805E14979A -3A374DC19A43E1065D5E4ED4C2FBCCA6C3BCE0EE791BC30630E08AB40452DBF4 -9D2A21B4B01F5F210F3BB42FF8C9F869115E7A0D78F9D2AF68C91F9BEA8DC210 -03870231F666E31899B1A24A0757EFDCD4E16C2E383D690D04D3D57E1F2CC85F -D23AF5BE23B1D4AFFEE6F66C684B93916B91B64DD85D1231E3D60C8E2FBEEAE7 -81C58E0BE8A0016CE39EF705F76D628FB8C08013D25B925150B95F7D0B814D1A -A25C71C654D4F1B5213E05CABDCAC794BA0A1B9251A123ED53C36AF2177EFDFC -6AE748CFAA85A25946B2A72D599A076F5A515E3D741BD7119FC61C2C75C8589D -CCD57D7A9B15E7279ED49EE50A9B5AFA22B902074B5D471A8ED71187982AECA7 -EA542C62EC41C509D2B13609A07CFB15FB2520D04D6EBC1BCA3B0DD51C1EDEF8 -CCFE5B0B5123AE854AA7BE938A8F8D809047DF93499938EABC1614C7714600F8 -862C14E0A4C1767686DFC884E39A1C63B17870FBB98FD39041539E12338EC4FA -0BB682BFBFA5B748CDF535DEBA2828BA26BEC55B96868BC4FA6E288F3E1ED920 -EEFC42896CC017F618D19B63DF610CA08FF6721446B8AB73D536BD3F5BD1794E -F89F380D0E3EB181E0A675230FC8353B32A1DF6E7DE4EECD1EA87DF72F3033A3 -B48097F10AF413BB5BE98852AF7E62F088E885A86BB07C15B1A4497AB0C7E181 -7BAF23D1B31696AD74AF642F36ADB05A14F004EDB1CE6734E7FFC8CA049AB6C9 -5408F91DCDA00C4B5022C29DE7B6A2D1C41C244E771DA6D050B14C08A8E3C8B0 -D089BB4B68164EF281EEA9B6CF58A7B74B598A1E30DAD1F73D05D1E77647A6D5 -673C6B83A012B15F373079C30E72523B591D29CF5F7615DF4B5F6726915A5D03 -6D8233D313B1F8DCEE93FA749EEC483DDD9AF0FC7EB8C879930BE3BC58515B84 -BEFBD90CD57E8377E2EB2984DF2B1BDA6A6CB3926BA821F58F9BCBA8317C56D2 -6D37DF6AE562900695DC31004AF4506FEFDF6E8D5804A63A59D176517910C784 -BDD6B7729337C7668EC4E393FFE08A158F0592B746D6754F5A97E4312AA7D376 -A29C7D43BBBB8DB4CAE338FD76D8139D6D97F97F95905909490B48D37B7BBBA8 -D9A98555961E734822D846EBC665DE1792F0F0D942BD7DA2D8DD9AB29470AA75 -7D3078C021DF4BD24F5CC9B12F0C3D1DEF9CC10B47B7A12AD9558742B47484F2 -DEFA8B5077ED0191C15E89FE58490107733572AA95D643F4FBA761C5AF8E0D6C -3250D597317FE0BAAC5CE4072E688B388FFD7D7F6D1792985768AEDD8A20255B -44F26FB215A666FAE804204C23472876169608AFE831886F8EBBF3F84A9CB38C -D80226FBBB3C2B60EEF75F0E2C9A9A30F5618D13F0DD84B36F4F30A211896FA5 -858248862E9F422E9E31231DE72A628EA00EABA81C59567D86F0E66BBA8587D8 -A3A0133BDB30C74F2652CF75C7F247C7F5B01ACB9E8F892676A67CB7FA879D9C -6034BD216AA626EEF69C718CF5AE2B9215D949FB4566E39169C803A4122D7D8A -2F5D2A7B903E7A5013EEFE0558D472CCEAB9827620333E4B44BF44ACC1CC0E8D -689C9202A9E972D34ACBF7A1C7C97EF057D5575957272934E0E5800153C8DB88 -E771DC89C0407DD9C806EEBF6BAC5A15632C1A72EBB047F2C6C1583A2D4F8F08 -58D680B3F48738CBDC2E4E81B0BCE80470960073B5B0F69C62435F10FDD73C06 -80A0FCCD1B3BB0629A62F1EFC982C4328B6486FC222133091D4AC153D72C3A7F -C1ACF5B02AF85F63590D95DFA6B1F887B96505AB280053663AA8E9A0A8D446F2 -CEB9778334A1C8469F5DAA99734EA85DFF2929FC6C1CDA3D1984283D4F3C8E5A -D3DE3D61040654C0958F49FE50F737312B1B8B53FD77EA34B8CBE290BF448661 -F76CE5533613360094C37932A6A7AD06E63FD8D02B359688E345E548DF53DC86 -B16692D707E2901C0721DB5BADBFB271A7BF00F2F3F0EF70918E322E4F343CEA -D18FC6504C697E69EA7D6BEB73EA87AD51AB32BABF794F1B22A6955B6455C114 -9A438671F30970682719974FD0B71B2B4A699D0430027B3D3E6D8478CE522408 -BFC9FD0A559944D24955742BAFF646C98004AFBDD735D457CA34B400B5D5D14E -55466E7F6476C54F49D9C240917AC429E534C51C92A9B4E52F5CCA11E3E5D3EC -6A0A28B39C2C7AC684FA169914A7ADDA925851D8DE6C750222591B9D98E4A209 -0ECCF91AA890AAB75CF3D8F0651DD9440C5123C7F81446112B4B556CF001682C -C660950D870234A2E96B373C97AF166027AFEB6697748F952C87360540B26105 -E958B8A1C306BC1CEA926496C9ED819AF00EC1DD7AAA64E6EE21BE8A65A99CF7 -86746F3D155D79AC812E1F2A5CF3C6F5FB9716CA5C9A8AC7E580522C311B2990 -E289ADEE82099F2187F37CAEE490F807BAA4B520977A62DD017A7CF836CDE5A5 -6AA4A7862E11757B5D67A28BB35E3989BBDA1AE77AB80C7E33117D6A9A353593 -687B60BAE871DDC7B0E9A10758CFC7E3E972B51A8F1DD50546AF7C498EA487DD -FF5E9AC8D87F2485A4E680909C07CED7254B5FF9E5433C3CFC55286B1431E39D -D4912DC8BECBBDCE1B7FA21AEF907D5CFC56685FC47116F7F20629747F766974 -95D75B64D0A6657FD0CFE9B56B912E7FBA38AE10EDD1E8C427772EC42CC100BF -5ED34DFC3093EE90D7CFD9E2ACD55D1FF31118B86BFC8ADCB490499F71946C1F -57477E88574FAE17B4DAEBFC8E100BEECB1E473C5A2F882A63F61B7826C3CA7E -44363CB33E5D8BF5E88F27F626B3EBB0C313D34B0BC69CE395DF99983E35D77A -2193C441E0107DFCCF424F49E3C7995B8A2C6EED7ADA45A1A33895E07F9ECE8A -DD91AA4F5758CC030D3BB0D7C2E86A1531E9F1EDE5AE52F12AF9E91EDF021030 -6E69FFE765CE505C617E6ACAC1B3D2021F1DDF82B3CE0B7E9A68EECD246AA818 -2BBC9992E440BF3B96384125EF21BF56BF673D0256BF647CBA2A538438CA8292 -89464AA423C9438EE2235BFE98B57CF89B1B1CAAAC22343324A63F913D1432DD -44FDB2E1F60FB78653DAF52BA657E5A48DE5FA5B4A419B83D52EBDED19355B5C -FE6A57303C33413039B9C074187F2ED11E52074A6EDE22482DF46B624FA64A70 -B2FDCE4D657CD67EB327D5ACA3460815649AB144744DA5C51BC6EC5E94B3ED1E -4F88997E850E1ACC9544239CA85A7D5C28EE249B966081BCFDB0D51B81EE6D56 -DCB2FA5AB76D47BA98896B0D52934577760E231FE276629D9BEEF1179CDAE173 -BA3E480FD2E2D1AF8D73509D1AA108C56E668E8A7EBA8B6BD4FF4CA54FF2D202 -DE60493D82588C215EEFE423619700C3FD2BB73DFDC0CE2EB6EFE7C2184657D7 -33692854C0DB7DBC388D061CDC20060E4076889A01D0FC9D6368F0227FA1183C -3E68DD3AE54B28808C93FCEF4F7C0B3555234C1B700EF5F9906B871B2A33F656 -74FF5C9BA74ADE3B7DD08EACFD8252E5F7E00349EF090A0CB375E8E16C035BB7 -9C25D612AA75843EEC123998AD8AF43960D55DED6653D8E881C6D6B6DE9624C9 -6E9FF1D74AF8B3BB39CEA0F74E13B65A171F1816FC514A32D56A0F6D2947EB44 -FF916B467361A185C9D3337A26901BFB6137903D9A89359F3DFDCF4F74FE20ED -C37A1B1FA70E64B910E9E234F92CC6AFB9CD343E14C360C9A4D8349C125ED130 -EE506B5E53C74FD4DB539C4038A5E99CAA46429F02E3DD462F5D2A078E2E8880 -3AC7B4618454A08C8B3C994489449A5DA7ECA6B80FC084053C65B4574A75A1A7 -4A9E7F86FEBEAFAAE9EB8F10B6FD73DF6E6B1638CD6F73FA2B3AFA49EA56A2CE -751D167118B3073746FC301F5E5F97C0EAB8B7B5DF5BB27958312CE8792281B9 -D62301C147101F32634E7730E1697F6C76FF342770D635F417B26682E70FE88E -A5178BC9F1604681EF2E5BD37937B5EE0AFDAF9845F25A3454F30BE34BD516AC -7E104033A567B4445B5BD6ECB3D71EF454E349BAF12C059A90B9BED8A006CFC9 -A927BFFE206AD54351CB3772A33A83EEFEAC789492C95A15CF6ED00C9016E642 -3D474AAF77F5E968CED1637F7B96225C7D769FDDD18B385E78AA60089D2BE218 -14F2E47DCB504026811C1E1966754072525FC8554943EC9817AD0A7511F21CBC -49BA61D493584866C5FE4BCB22000E1F72D6320C7A6449559A9E085C10C3C1C1 -3C69C0C355385948C822CB4CE2726DB4A78BC3225FC1EDA373C64DFDD4F3A932 -C99C34F0048A3C8412B0660BC8E435D8AA311487E6766F203149941CE19B48E8 -724916A0250AEEB0EA527CB9D7DC48EC31BFD11190F329FD642D18A4BB0E01A2 -E6C59C2AD964A3EDDAC052FB2479401777E6A5AD02BF93FB0D3D4C02B8771CFE -95502A45F1E36516BE1715B4AF4B73021771E4808E5C95CF68E472DA9DD4C429 -936DE6A73825DBFB6CBFB3287A2922926B80CCB38D51612027440CC1CF53EAA5 -278D9AA61490D705A0F4F912C72EBC8E8FCF6A51AD580D483E3C5B830AB6A41E -4DF559E9E61B92D183B62B7EE4DDFB9AD14F244B19F6467B2BF210327845F1C3 -B77577E2E2A206913AA4FE0D5574230B54936A34ABDAF521F64DD42274A8DFC2 -46896952479D9498448B59DF3B31A4BF20AB11B425DF82F11024A09AA89D9BA9 -44E7E118D80E61DBB935B2EE788E0A79FC95BF18E264413186533EF5F24C4518 -BC7C75E83E12660CE2B2087851BB4DEF2263D647BCB2383429FA0239DD08CC2F -B60EBD65000D268A1EF12570FD0777405DB67FAB4529A3E4C4AF4093FD6A0A66 -5684568035B9B6B39C8B7263AAB848007FD44692A4D9C1DC972CA488D8979F78 -D984BBBBBA63594EAA2147190E82EBDE64C2B4116D43A9809A2133B6F79999B9 -22FC69623EC865A27A601351B1CD9F2534FB692DC570611FA8C87EAA4380637F -7939E2ECF4DE7E78E253AB42DA597D724ADACD23163F41DC48ADFCE89E241923 -4F45B563D56816079967D165BB8E6747CF9C2CAE63438D6EB7AFEFADA73C53A3 -524B8F33D53205E2C22C857836E2C71A87C3CE545814EDFB4007A69E5786B8DB -54B91E072C602898DF9CF4D93AB699101220A7B7A68192BFCDAB82947F7E1A77 -7B5D8B2CABE483B87D0DCE7C9AE04DBEB4EC3ED1C74BC5B4ACA1EE89E1F879F7 -89D81AC3BE8A1F61C0F0316DBD0363D193149EBA185CE7C561DE05C3E3FBBA9B -9BBE1C82E1D4BFA1F38F7CA850D101BF3C4B6D26D981CC71C7C9035809D17297 -3293D1C5030219DF943C42B8947D2D8DD8E1D63EA94F4E1429FA6AE178D317AF -242D813B967B677CBEA4197A3418D647A90BC15F13C5E448C74E6D3563D7399E -8EDA835684ED87775CD3955D69BA7E87A5DEDDEB53E898A30F9ACC5707067968 -90091B8862F83E3214191165AC4FE1F820A8DC9301A12E0C9B1706F0E655AD9D -3863E0D6B5700C23E47F17ED9F8D99296D4B84CF381C5BA776D5C210D193D22B -43ECC441368D803F4DF51BB88721F2765FA2DDFE5227846AF185745222E10BE0 -95C282B5BE11FD21DD470705221403C776CD2199AB378A1B808A8D8378B554C6 -41FD8C08EF663DC9B69BE65E4DA7E784D5C009E5F5E339DE43ACEAA8606ED98E -F88C13CF6B104463E048B405BC87A01C776CE1E6DD3BD14DCBF84C4F04F2DC70 -90B8D8FB1A7C23829AF0B4AEF88FBD330B5CA2C122FF88D5308C003ABAB85CE4 -283382B16DCBFAA56FC90BEC0390D4E9D159B27FC4359560F0B3F2D2A66E5957 -451D6A81889B299614E39F6F5DC8D2CDCD2AD0B2045804304FE4093DB8024F49 -095952867EE708A43684090C3C08325950E5B6E31614FCB9BE4530EA4F7C85AB -CEB8DCC3CA496E59DEF5F4D159B576C67D0F4E261D67F8D63446643C4AFDD11F -2D0B1A625F93E45A43A507D6137AE4D25A6AB887BDF403CFCAA4BE8B4F3433B5 -0492A4E82FCF71F0F81DF6CF1412420BF8B7B74C3510E4D057A6490BA235DBA7 -E2EAF838F9F6338EB93F5A5EBAABCCC73612D0EE7CAA32FBBC06F269D44429FB -9C9F270E8A461ED57EFE97D5620F357B37031C17DD01C129E42B7C09BEF447D6 -363162F1A326EF50C9339C532FCA859F155ADDA8A614EC8E083863D68084655B -B9D22E3198EF1476E7179201594ABF6AB55D9C58D3C27AD95A6ED28D89E30A0F -00896350907820CFD6E25B7B6A8D45614E3D92AA93D6795ABF514A58F1512D31 -C97E1588372BF8F0D3A25E86926EE1F546A1A9049F01186A2E057C26730B2DDE -EC28EB6A9F6A29EB6F6888C822AD5A1413FDA1990737E554056ACAA6358B8894 -26EE5AED75B3582E857A487A954390629DAFB8DDA976CA79970C1486F80C7C11 -F4FC26EE0B8B18BD9AC1ABC684E546D2FA829DA2BC619EA1BDFC27492CC0CC28 -C232399559A1D5706909228BF0CA06301B36B87C0B5C761B1AD05EBE4A7FC4DA -BE7C55BD3ABAC5095192FFD33D441120A6560F12D886AE15B0B1FDAC9730A7EB -E54A1FAD362ABFCF5B72EEB279A86A0495B78A8FE5338C3BCF5F0105C66C2674 -1DC8919CC9BF9F6BDDB04F42D18965C6D1C525E3E45ECE744F722BD6EA835732 -DD72EEC69CB42B634D5FAD83C295B184110CD718BE52B7BD4A170FCE27ABABA4 -74B32012F20F359D3F3D0C1818AE641D5DC4722221609DC3A78E826D68061EB8 -EC734E42B9469B715D78CB2BE74E1599A47ECAE1234F8D278633FB1EE2D83B52 -A7AA6B7E588819CEE90BEC43EBAE93E511E4BE18436657F174C2ED5957590800 -F35AD6671FC0A352B1562E042140D3668E1239C90FF717CFCA0EA4BBF2679B86 -B179F2717C27263E31DCF3788EE038D4C6FEFBC918C5313546C8AEFA73FCAB0D -FA055D120659BFD99937CCC34D533A10B67BF498E2A52E9DCCF38ED40F7FC380 -9F869127773514D198C61031EC04E916126227BC4611B8528362C78429C897E5 -8943F4B4DD8C590FC1AAABD603D9FF15133B1729FFBB1A2B0975BFDA92A30CDB -3C3A59B7A6B5255460A7AB1F01DB3C651DB95A3FA4D79E8EF704954A8F52343E -DDF4AD0DC6FF258118274C23A470844E58385F135D812D1EDB742CE6E33855EC -53EBEE6F4BFFD48A2230CBA4F30DCFC8F86037F942E6A253F03C2711002FF4F4 -7027D7D1C0475487527D316FA6AB9E1B1D04A56E818CCC1D106BD5D9D2858522 -92E832FD5718FBF7EC656CA84FE2B2794DBEE834BA2145EB1148FC5D57E818B9 -B7AFF6D2F2B0816C301175E6DAF7F276FF495C0D0E647F4028C94D9610EE2B7A -A81E66E07D2A9726CD469EDA81858F8C269797EA3A8CC018B7A6C2DBDD71E261 -90E903120EC01015CA59F444BA8D7137D57E68672C5CED88EAE80FCF9E67C3D7 -9B86FD5734278233C8E264C53C88CB7BEFE88BCC5384095154E3FC528520B6E8 -94BE6C714F9E8D97E2EE980FC6EC8AB86006D9F9D24F90D58BE98982ACB96F71 -C2D5B94CBB00AB07A1B132606A87B1BF710C9419EE196753E24E544DF7EE0766 -D2DCB7CF6A2934B96D66CDE5CDBDD23DD60F163217F3372138E7B8A7FD206843 -CA23986600CB3CB287BAFEA5D94479FA9ED24AFA727EB872CDF44C43E870E43E -0C9688D426F0C86794ECE9D133A7C32229ED93313AD008730C3000D053962330 -C8D100E7F5FE25E31D0C590010427CF42A6AA682AB43A082B52EA29C6C5BEE05 -2D69BD0400954CEF43016B51ED03B80A28A8A427A89F099EB2162E688373D231 -E7E9660ECAE039EF1F61CCE716589A9BC2DE32CDA7C2D72292608975DE5B5F5A -41F6169DC5A8097530BB4AB624ADCF9900247498756A91AF1257A7C980A5272A -3C6BD101D2706E53202682D16518C0B9B221A90EAA867ECA1FAEA87205AC8648 -413801CA4376CE0C7EB38A816C54402513E68A0CC783B352F0D5ACEB7E7F344D -557C8E732E089D7329DD8ED63F2A22AF3E66914F8907789972E8D5CF72865E68 -43783B11F75566F28081B5B74C56F44C05BE7DF015143E9F05ED154EB1CFDD7B -A99F2F535A258A9C6C0E6E0A2D4B91DF0CA6284C5EEA3263C3BFEE493E21F66F -A68B008DD39AEEB566C4F4FAB93E8172FD9EB0E00C93D057534C2FC2DFA4E92B -BEB8F33F1B685044467019470184DDDC1EA9A16F63DF5BF240EFC7B3DC53D8F0 -8C2C168C317757418EA33ECC81B136A3DAF4A7625DBB9DBA43D053364B910BAE -537FE379B65ABF70D6A5DE9613FAC4 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMR10 -%!PS-AdobeFont-1.1: CMR10 1.00B -%%CreationDate: 1992 Feb 19 19:54:52 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.00B) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMR10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMR10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 11 /ff put -dup 12 /fi put -dup 13 /fl put -dup 14 /ffi put -dup 15 /ffl put -dup 33 /exclam put -dup 34 /quotedblright put -dup 35 /numbersign put -dup 36 /dollar put -dup 37 /percent put -dup 38 /ampersand put -dup 39 /quoteright put -dup 40 /parenleft put -dup 41 /parenright put -dup 42 /asterisk put -dup 43 /plus put -dup 44 /comma put -dup 45 /hyphen put -dup 46 /period put -dup 47 /slash put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 56 /eight put -dup 57 /nine put -dup 58 /colon put -dup 59 /semicolon put -dup 61 /equal put -dup 63 /question put -dup 64 /at put -dup 65 /A put -dup 66 /B put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 72 /H put -dup 73 /I put -dup 74 /J put -dup 75 /K put -dup 76 /L put -dup 77 /M put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 81 /Q put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 86 /V put -dup 87 /W put -dup 88 /X put -dup 89 /Y put -dup 90 /Z put -dup 91 /bracketleft put -dup 92 /quotedblleft put -dup 93 /bracketright put -dup 96 /quoteleft put -dup 97 /a put -dup 98 /b put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 102 /f put -dup 103 /g put -dup 104 /h put -dup 105 /i put -dup 106 /j put -dup 107 /k put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 113 /q put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -dup 118 /v put -dup 119 /w put -dup 120 /x put -dup 121 /y put -dup 122 /z put -dup 123 /endash put -readonly def -/FontBBox{-251 -250 1009 969}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5CF7158F1163BC1F3352E22A1452E73FECA8A4 -87100FB1FFC4C8AF409B2067537220E605DA0852CA49839E1386AF9D7A1A455F -D1F017CE45884D76EF2CB9BC5821FD25365DDEA6E45F332B5F68A44AD8A530F0 -92A36FAC8D27F9087AFEEA2096F839A2BC4B937F24E080EF7C0F9374A18D565C -295A05210DB96A23175AC59A9BD0147A310EF49C551A417E0A22703F94FF7B75 -409A5D417DA6730A69E310FA6A4229FC7E4F620B0FC4C63C50E99E179EB51E4C -4BC45217722F1E8E40F1E1428E792EAFE05C5A50D38C52114DFCD24D54027CBF -2512DD116F0463DE4052A7AD53B641A27E81E481947884CE35661B49153FA19E -0A2A860C7B61558671303DE6AE06A80E4E450E17067676E6BBB42A9A24ACBC3E -B0CA7B7A3BFEA84FED39CCFB6D545BB2BCC49E5E16976407AB9D94556CD4F008 -24EF579B6800B6DC3AAF840B3FC6822872368E3B4274DD06CA36AF8F6346C11B -43C772CC242F3B212C4BD7018D71A1A74C9A94ED0093A5FB6557F4E0751047AF -D72098ECA301B8AE68110F983796E581F106144951DF5B750432A230FDA3B575 -5A38B5E7972AABC12306A01A99FCF8189D71B8DBF49550BAEA9CF1B97CBFC7CC -96498ECC938B1A1710B670657DE923A659DB8757147B140A48067328E7E3F9C3 -7D1888B284904301450CE0BC15EEEA00E48CCD6388F3FC3BEFD8D9C400015B65 -0F2F536D035626B1FF0A69D732C7A1836D635C30C06BED4327737029E5BA5830 -B9E88A4024C3326AD2F34F47B54739B48825AD6699F7D117EA4C4AEC4440BF6D -AA0099DEFD326235965C63647921828BF269ECC87A2B1C8CAD6C78B6E561B007 -97BE2BC7CA32B4534075F6491BE959D1F635463E71679E527F4F456F774B2AF8 -FEF3D8C63B2F8B99FE0F73BA44B3CF15A613471EA3C7A1CD783D3EB41F4ACEE5 -20759B6A4C4466E2D80EF7C7866BAD06E5DF0434D2C607FC82C9EBD4D8902EE4 -0A7617C3AEACCB7CCE00319D0677AA6DB7E0250B51908F966977BD8C8D07FDBD -F4D058444E7D7D91788DEA997CBE0545902E67194B7BA3CD0BF454FCA60B9A20 -3E6BB526D2D21FBD6D78E21A936F2E123C0F6EF41AA2266CF51B513EBF49D4D9 -2C0C93820A37010A4C8990B3D2551EEBA36E8B8DC122B1432A6BA9A8A674CA2D -5F3DE1AEC33589A13F6DBEAFAF69B753BC0DA94017AD3D1CE981FF38A306FE6B -A6A35630A7D636C1FCDB936F6BF93040C2E147714DEA74B7E32E97D4A9A10944 -1F389DAD067D206763C22156CACF1B820A6F71A5AEEB76D95A7BC008F0470EFF -D7D7BAE7545D44A16A51FBE1975162DB333B696716F8978E6E9589A86B824A07 -95F6BDDC7A0FB3D7EF795BFE39EA4885E6E3173C865CAAF8A0BCF4EC66FA0B06 -A3E04E071686DD0C578DEC9EDFD2ECF8457E0BBB5591AF24A8ED3316CF401C81 -EC70E8F0D3BF4A21529B5E42A049AF60AD5B7DCC6E9908902410779460D7BA86 -5C9C6AEED7A598A024222D4131D025ECA5B3321E2E99BB5B451D663E5E06000E -FF852435FA696BC421FB7B71F4AC3F060A4244F4405709FAE714D6AA3919B086 -308294FACD400EB49591DDADD04F5B5EA452CFA1356624091215D04D9D086929 -626217F6F167FD5FE4811A15068E576E95B795A7D58C9F45283714284A4F707D -03DB209B0E863AED1651B06C0C5C5724AE78785F5E53B44DB3512023D9C9F099 -4D01D2A9E965FEDD523240FF4F6ED5767302E55364365DC3211967EEE2D1AC50 -EAB6A0858F98FA558CD52801125FCE5AAEFF792DB7F0136E5933C9637A43446C -66440D8261366D37231AECCB3A698B06A710FB158506962A878E73666501B190 -2F56955D3BA06250B07649EA1DA47DC3FBCAA5A30C660591F221D0151ADB4DC2 -C46818A2303198B31801A280E4A11EED4850180894982876B3A8584593070EA5 -F961147137F29D045457258BF18BCC391A19576D3109BD0E196817A78D644AC9 -3C186C5D61871F9B990DEC2B37C42F545EA9394332C5E3D0703045A58A08618A -7F4F63575A2BFCBDC5A2EE53BFE40048BB6B9B5C4D965AD7A4AA724555AF912E -23831F300D9CECC1CEF0EA9555CA1499627A4ADCB469E474B04D7B31570E34EF -DE736A27654BC2ED0944D0ED61182FA54E38F264C3FB64A8DD7089A77D455F89 -E138660A52167BE25CBF95474A18AA51CBFDEA411CE8A715B0E10331BC9D294D -AB1EC8F0C2B4AA56382543DA98E3EFB9F8BD51C8A9DEE1596B6F059FF7CB4463 -440770329C5A76D56453CA3BAD039498DAD12005FA32C6E12D65C4367EC66D45 -28536DD4FA0479979A64A0421ED987382C0BA2941A66E22CE58FEB41FB82A57C -2B9E87B17D39B03D2D140996B03E144207DC3FB89B16DA8AA6BF0335B1459F87 -CBD5AFCCDF5778D1290B91DBF38FCE9009A72B6EC01E7B5A1BBC22C9A3DA10F0 -955B51AF2CF6CDCC737F7A6A9AC8F43C313C12DE02D6D281AD503BF9EA7273CE -E8B934C0238CD6D7CFBE61E649FC900D27981DF9FBD9FFCD66918147E883F119 -FA4813CA2426E774AFCBBD227CB14FC2D801CF69AF76207507E59ADE2D16189C -1AF84339766A71803F1BB1196EF5ABF883224F00F91157ED18164D367C06C4CD -C544C73C504AE636A10A25ACF8AB1444181F7EE62BB17F2AA1DE3757B5886094 -ABC25D7F142C2F08895A4B06ED0445D46726A6D4518E002BA8F3FF2646E920A8 -0B0274A17ACEAF889AC0F39A2FEDBB696783758D612268B74D8637CF00C7C14D -8D081011DAED60AABE95476AA9B0DCE3311955DFA2796DC14E2F310CB4AA4B85 -7448394B86C9BE2D4126610FBF1F1B2F3746FB90A75F647974535DB5B45CEBC0 -7576D5822804E254C7323CC6C277779781100F05835671D32EA6557C1CC603CC -552AF750697F26B3B746540BB6C5ADBB6A7F94560072FD8A1F0E8A352762F2D2 -32C5942DA29F3B61E534A9684078C428EA682C6E9CCAACE2ED894282BE43797A -A69BC6C5F064949128562CEC1E598673B0764CE69A26BF9941B78117A9A586D2 -9E21F93EFACAA034EB1A17D6ADEDD5B511B1E60363D295E7431C9494980BC599 -22E4BF0407E08A0D614C61743E667298A4F69D502859060637E4F59AD9688E3B -0EAB705CC3AE3A3B4DF0CCBB33A92D7235DFBC94DD373D1FF1D38C7F4A6F1669 -BB49E93F55C5B890D295A3CA22212F061C7764929046892A1DBB9EE17E6CE5FB -0229D451CEB774874B705ABD2F1191262932D5ABDBBCC616ADB2931496918BEA -7281D46DAA22477876A2512F3FCBFA48AB0CD8CB6E2E3956636FB6D4394A9F46 -A00398F18CAC9F515E18AB15D54CF94B26E0C292B747F825E49A3E8683F328DE -4B003D66FCC94F0369024127AFF4DFB89950EEB090DF2CCC172D9300E248755F -A92E5A9660ED4D8D0F1D66EB214BD9EADFBBDE38EDA3EDA801B4E034CB60671C -664786BFE090822216662279921128301988D14684C8C2FF71BD04D40F912A96 -AD2AC306FE3C4905C149A4090D146233579DAA74E462C695D674042DC6A72FA9 -6DE2FD30CAFB11C08D6DE6572D5F5228EFEE40BBD76985DAFDD5854926608B03 -01D505BCF417B30C8D2FB15A41D064B56082B2FC1AC51E13169F90DD6AF2F29A -F684C1B64E498194A80963D7F89BA113A6DCB49406BB15DAF6CB95FCAD5328B8 -D4A805FDA41E7FD6909E65BC96F4A2CE0051271880CD0D8EA0C689FC8BB39435 -FA03784AB431ACE16CE411F48A98E560D942EAE4382B360AE1CEA85D392D806D -C2CC7888FEA83D6F10DAF4866C57451E4399E6DC90307A2C2BBF452AD115FDC7 -D55FCACFE385B9A99F156D472751F8156EB65C036BC28F0218705639FFD2E454 -3751DD7E649982625D679900C8C36E76B9251447F31AF56901CD10076D565DCA -C2D8503E604D9C5AC382CAC1891C973302645D026F2DFA71ECE722A456DD269C -2FA07856BB1D393E14A96B5A30076C4A31CAD65BAE381D9D673A97A847AEB26C -EC7C12C64297F552051F3C8BCC430A9FF2DD7C91B9C903ACFF671C44D94B00F2 -CD253449A091CA3F7336DA8A6B11DF877BD07806CA5C38F8D123C2C2609452FC -7285FC5EE7A9A4A41399ED327EDC582607614E24A8ACF7A8129AFED960CC1CFB -1F58B8E02F49963103AE56181CF2E88E783F4C387C4F49676721470D8B9D41FA -9876A906429572169D99C54AE768658514BA2FAFA2D83E425F62440BA958388D -600BA268E30681984CA3EDA2B23852D2EBEF85DB0308894E9E572489ABB1262B -A847471BE73232FD38DD68DF2D2CA6D67EE09BA1F6B9C984E69CD00074D6B41F -401238F355B68FEE84B0C044B6692E24A6A3299F4928910E30E6B9B6962878AA -78C937243ED0E68E9995886B11BBBBF8F621080C0F7137735A22B88D25EF2AE6 -BE2B76D67E7BF5E04EFC382D7EC65AC13387A2EBB6E3D1248343E79403E909B2 -62D6FFE76181838C154E05133E92F8456943238C59B4802F094101D4BD5D30CC -A3B0B03731634D4B5DA478752E468021C38400B22DD8855108070CBC141E38B0 -216236362E0CF7C6C94F8E682BE7FE38E9496C718DA3B22C74F41A322A4CF1BD -D51FB1DC2EF8DBF800E63A8EBC4461E019591C2FE5B8FB89D843D19F76E82E2A -91566F034F5544E40E485FA63DFB4A83DB0C4AE10CB64798086CB356D3E3A329 -55C9B3DABCBBF25B603C48A50C7777F1A034B5864E9F23498963B5FC8ADB8CA2 -650AD80AE033B4EFCFF15625BBA7F70C10D589FD9F87BB6E174058319137B101 -F43DFD3385C77628FBFE8C0E13F17A3646AA6C0B02374C2AADC68F86327637CE -B2F2C445EE8B4011ABB8DCB31113F0814616D93A5F310F1919C819128983D7D5 -9DF0F434800761BC5F43C7B7E86A62A7BB4BB4C6657D653E5B3B46BFC073BF3E -A92392EE5949A7FF9F1A1FCEB51E5EAB4D59278B866E520BA571C5C1839D8FBB -80E4AA2E51F2B1A5347218EABACD0083F803459E5A6D583D740FA82C445594AA -CBA7D6576F39F040BE021734918E0AD2FC3C672DDEE53F5DA148C7A3B28A959D -7DF128379DD2C1C354DDFC00CD60AA72860DE96FB1ABC1CA06E6B6DA2FE8D343 -184C7A03C32AC66B6CF68EF8364CD00593B50B567C686122E702196D3A2C8647 -E2F02B2AE73371B062E15E565815C2CF90A1455CB2C322CCB91E7A13FFADE8EE -8F0EE48F2AA2791311A33C84E4266801361DAE9907A9B4C7A80549E59FEDBF93 -D1573B24E86E8A4581305AA11D9CA399BB34BBEFF7FF2740044B9B07963F5C71 -834B4A09BB5CCC60AD08AA084E97C1832A5AC2D850EF8F00349D7FF1882ACC9A -C4000307DC71B0AC37CDB5FBED339C6C21287F79CFA6B6A5E062C33456E56EE5 -D50677C739212A46718E2792AA09AC1344273F0F3A89A7D59131FEF172F59FCE -D48BB833711498F998AE7D0CB480DE994B76A4B605AE9CEAABFDB2716F0E6BB6 -EEC919349529943D629C243F8569DD70721E3445CCCF6DEE8070515FB32CB7A1 -944A3C6F242605630194824B1BBD05D053B5FA2AE49B1D3BCCBE39C1411D8864 -FF6FA8F82583CB0DF62303A438F15B98FEB403368EB37C34C5FE43FD1E829029 -511DE455DA5672F39B98A7BDB2ECF99F2E484FF5153281C8AF121DBECF25ECE4 -DD9E07C83D0E24C7F70FB41B6C1418B0472EBE2035B7B06516C4F51D635D1D2F -10AB3057A63EDC7C44E440C5DB32DD205693425F49AA1BDE0B737D6AF01F3918 -087C4CD6D4E826739E4DC746A6A58B6A45FF9C9F2845DE409C8CB17599396DC5 -BA8D641F9ACC7EAF3A82C1A39BB0B6C2B69BD2E09D034ACBA5E34C4751C1FAF5 -B7D00A584C7DBA6F50357CDC09FA1C66C21B7B585C8C0C04C5515DBFEB96FF6A -389FDB0DB0193951EF119A7B5DC3317957AB0B235273B02426F6AF53A0C7FB1A -4F547F0CC735156414EB33CBBDC6247232885F6AD906B1A814F134DC815017FE -EA6594BF84F14E5C507133722266882E1ACAC0B04E0B4447C49373D7F8D3823A -D2A511A18AED5E1D21A231F9EE5608C587E7DE3D1B6F2C0BED81FE4B40A7B04C -C0D964D9B421140EF9BFCE4100159B7A3766AE13A2D9B958DE1BF30D3C40DBF9 -ECAB6670A885B45677CEE294F1CC9F89CFC73DA5BA644D98B4F02D49FA77E755 -6E8740DCC22DCEC4DEFCBB895254F484DB325EF7AA7E7B4B5EA4538C201DC55D -60DB65291FA3C05D7985D3406CE451CAC888A6BE975C5C5730B064D732177ECC -731519E439D97D8E2893F040C8C5728A9E98C147B5C239C6A6394DECDCB46DBB -02C2A4D7C0AB670E65BECD8C420C5532FDD198EE4883E563E6D109917B56A028 -7F2660487F2DC49B4E294FF93FE1722EFD9CAE7EA41AD461E32D54A40E4BD564 -235D91A35B8CABE415F1332FE6FAAFA4844134E240E13017B36640DB65E09A84 -9B4F80107A147B66C4C7A650630DAC27BD97E859D861296290D36398B13659ED -30786EA54A5DFC5C38932F6774EBF6553FBBA7BE160EBDF71ACB83CED3DDD6E1 -69A9214B07838868D811B56D37602B97203E1F3BBFC892BE6412EC8A895195C7 -18DD3878C25875C1C963A4E8CC4D170F03C3F9A2B25AFAEBAAA977587E996DB9 -66B9F0B8101E72C9919BA0B8388B8A641E84D671C688772DB9EFCEC1A06D3B48 -FBD5E5E2780B3AE9137E35EE4C8BCD971CEED1CC3866DE186315C9D0369F0BE6 -FA27943AD63DFC9E37849FDA168E78815BE4A6030768BFC79B694BE50C9CE2B5 -D3F0468F99B4179ED7E1D228222321C0BC48C8BAEBF20FD6AC4E2C4DFB48316C -32697765E4DEC4E2AF1AB1BD0BF993AE888F901AFBEAF5C848A2D6A3AA203240 -AF089279CA0B323FC348EC8E04AD78F37DC30087E329544F47E37331CC328F9A -40C85BAA06CBD3758EF6D91B1D35FD7F49A7D046FC94988CEEA924A82BE61004 -7A5AA85D5BB9B3EF81593F82E8B0CC490DABE4EBD4DE5409DEF4691175040B07 -DEB329916F92FF6422442629F6BCBAE4D8A3F0AD2DA530CC67187A670116DEC2 -ADB194B18F851F74E50A1BFD4B1F4CA4D80867B759B245A9B48D1BB0B50805F2 -B04B079C214726BC5E00B603CD81C42583471CBE43265EBCC2E72B5616D0E367 -8682148C8BBD49D65F78F665769733FAC90810FC3D939C809ED41F8F1B49B7FC -FCC04063451F138B7178934E3B21443DE417F74180F426AEFA691136DF15EC5E -6C7156A505CCEFA3ECE87C9FA2DF0A9A08366867C114BDB0DC9AC620E07E2F7F -F08100CA47EDADFEF9837AB60B0F3BBFF5E4D963E89737B3E9F8C2399D62A821 -84D4294B78D690006DC5C4A235920524C22D4E2E75EF5510DF6B75279AF30956 -E016D8E4DA40BF0892B68E95243648B50C587DF69DA328D21EDC15B10FB9019F -1C21F02BD2B07B4BB3B1BBBE7CAF299C4F53A7AF8B62CF737D2DC15AA490DB01 -6A1A6E75EC9E1CF0458B63A0E0683FC4011903C08CB93D421DD51C423351748F -0E3E1E66BA6DB1B281BF1D83B87708D3C6342CE06BE403EF44E6BB7BAD058203 -4010C606724D0FE02964F1F448EDC02D55F4D6302C47C2B5B28FE771C11CAA0F -8D0204954C0B8C0C65C63545FC0165AD0D326B779B4F95334655E0F1288A37C9 -13EE3DF7E661457429ED6F40133601C4E69E8E7500E3661430F131D759C165FD -7570BD61795005AC92DAFA06318AC1509553AA05064CB4D5BC7CC0385C56D10B -AEBD2804F5F361F203236817602CE01E6DCF2E0DBD39492E3D65E5D7309EB885 -CF64095CA6906CCF815E3EAA30698A81228DF1DA07692D866DB201E00EAD4E48 -E2575BA6B695A8E41F2581AE76844EDDCFA86ED1546CEF56374DAE1BC91BC29D -10347574F3AC6709F66799D1D88699A6AB790CA7EB749BF3011FC9A5843AE231 -4AC4F5EA4E97901EE4270A5EB6C792F7A9B1923B48252F00F7E059FF12984C9A -E5662EDB2F2CD4D59B30E50A97E0802753BDCE107FEBC5A348B36E0D36B233AC -72D837CD3F69922114E300B954F09180AF58AECC9540C34D9F4634423CCACF11 -125E46D74B1676AE57939A83C77B1B46B90BA4CC1E75D0AAA4BE309C7D127E10 -0CFE31D1ACBD46E4CD838EEF41380ECBB96C91918451A04CF1880DF394693E8A -B2DA29B26797FF165570EF5B1700F42671A2553BBC97F765D3EC0B1B75F1BFFB -296677656105D98BFFAEEF5603F8C76E567F2F7681CAC59FE71D22B6EA92AA82 -94797EEB2913F49CE74EB6B495CA774CE170B2908EAC858CAE67933CB8506B21 -B3433DCD6ACE1CC826D48814BCD6BFF5C13E9F18FC2EF5907AA952B9B66C3459 -5DC23BF793C9A63680C3475D32D0AF6F712446CD44ABCC7DCA4B53D046D0C8CB -1915A9024D24D304FBE47B6B75CBD7023927CC60F136588634A482ABDAB8B560 -7BE700495E1BB55BC92109FBC90B9FB78A709F906AF69E084B8B76A3E900B241 -A0E833CF71616F8FACCDD482748BCC9EED2D4D72DB7D3C2DCB07C3A9A72A2CF1 -50E59E8B1679D6232D3DD0A5863D984AEA02DF2AEC816F4D1F31CDDD14C99E5C -39210C98A785289A7E9E23937A77AF4FDF1AE5AA02002FBA84FE94145AA40516 -752D7D5B8F189C5B70E09990AA850B10A86F1E01B577BCBB025C19B4A20CAF8E -A6D5C526DABC99ECF8F4A9C3AF463CCECAE7F6298300CD2A2186905AD0B90B0D -64465961B50B9E5B76C4D0C94BA3C2703436E39F0EA337A0DC33FC5207D764CF -9AFEF8CFCE78E25608F7BBCDF2DBCE86361805CD7534B1A793ABF37429CEEBE7 -5F9D6811C64DA3EC9A472DD608FECAD87F30A836BCBDBB346256B9DDC45F4649 -37F012265889CB110C5B89D1D1CB03D522E0241DAEEE4E7A0589940F7E292C05 -EB685A7D259D2261203BF92E14AE0A5C4B8EE345B0EFF2D5AB6E63201D9B5859 -22E64116D31D59AAF237D0FC26A3D77B2B38F605456AB970FB502C6DDE166B62 -3EE4E3F18C52C4812BE4EBBDD89CBFA077E42B2F426C4A18684474A6CA6A5407 -2535E1C1DB08E330C50080A1CD6BB6C6E4F7FBF442E3BCEB63FD3686F73DF2ED -DB8C4FE417AA5DE4BA6E33CA35C735E55D0C4693F42AEE73AB32FE00821518D8 -015CF13654D1C92241F47A58507AA5D072BC3E8245EFCC21D80EA2B36D6811AB -15F8151FA2F916BAEFF61EF58F8098897C91E2E1BB3738718B36D9AB951D72B7 -3A7E1B049DD946F2C53B5FE3B9A44004AC29B9807A89DFE954F9F75DB949F7C2 -E02A53C61A6C6304C18E327D8D17E502D7451440E02E17829C908B993893A8B5 -E8DA8A8203F615839BC2E5C42CBA42EE835A1D76518058349073870B4CF80D57 -7F0C6027CB34647A47A485B0626AEC308035CA5C6F41619122EF48B5D0CEAE1D -F08FE2ACB687D893885CA077C05D30F4FA5F2692443C65E1872708346B5C7EF7 -973EF391FDC9E176E88515B6F33A0FF5AA9B07E9030E362C7838A92A94A71A35 -58C836D8D8D5565814533D21635090DC7FEB59F822F3928DCDE293A11E8C5498 -876C93032117357B32ACAD3A71E184BCC86F0731F8DF6FFB4FF71CAC0585F10B -4264C52F74B1D7C9AB37C2CD8144CDB7479F2958FE214031D5E4658B35B0EC58 -18B8A9D2685524FBD152CA7D02A890FA7F295D11CBCB0E1662158B13D0E3C979 -FF1D130A96A1F1CAE3BB0427EFFCA53AD1730893A642D6C7913CC944E0AAE281 -5C1FB34D8FE5BD0B65914B6758F3623901A9ADA112BF5D1AFD0362DD9B21F8E1 -EAB590759CEEC9578B6B626B9BD221C89B48E9745A1E5DA37BF94EA1E81611AF -D2EEE138CA0D776E2A65BDD918E11C3CF5B6D71B0BC0E58FF41DFE0482D0CCDB -8C2F9AC7AA93B9482A13FD9BABF7BB0BE01F3E5B90707337D23F1984AAD9D2D5 -C883EE1A7DD2B0A84B02C73C86AF924263B78E38E6A5B98B433C406898CAB93A -0EA63BDCFAF4A368D136298012FC0B50253ADF38FA56780C68AFF5561D68ECE8 -FCA27DE51A4360098B65ACE4105F122BBBEE1AB11A110F9070B6A017039D59BC -F54F95FEBA8FA97179D619A76335E69F5BC41DD105FCF177567592561E51D3A5 -FB0F9DCAC0EA94865AA42E2A56EBC88D1F7F8DEAA2537B917D0DC554CFAC55FF -6633558B152C4DF2AA2D5D55CE401B0B56317675EBF15C2A7D8EFD28AEDB6EAE -0B9E42D8CC8A73CEF8D005AC7B9D104B02E9FC5FF89875E8825BE8B03C1C3048 -7B8579D3E4DC0883A28E0029909D5A5E70AB51E56382CD19796FAF5F5C2B7464 -8D3F85E09195A8A8BCA4757CD7F4CBA5E0F17510315B5A26582F5439841E212A -F62A5C34B0D85F37B3BA8DA132B6C468A7723C8E0BD02553D0D27759D0E2358C -22317EA7E8B7AD1000EE127F023A3683340492FE2523CA72114AF53DA436D2DF -D5F142C55B8BF2B23FE158CDCB24D50C3D4A0BE642702C560D627238833D1525 -E3E7FC448C1EC80F6A66A163AAC62CAFDD4D8B87E10940B3C75A14C64516F31C -43FD0F9879FB4491E2AD7D61D63BB643729CEF2A775FED235A8968A99D9720C6 -23D0EF639E26128F393F4877E4590AA209C067EE8D242F32DFCCB6EF87DC4DEA -84D7D73BCCCCA56355523602A02A60CE2BA40E6421F851CB4C42ECF0DF344FFA -1350552004587E95F0D181C883EE2908A0F48A86059ADB746A1BE7CF9412EC1B -2ACA7DEF2CBBD1ABA060182D7456313B2A2776E6C12ABA26A82FE8CBBFA5E43D -38F335F0E46B66C1F33F25FD4EC7AABF5466C5F34C00BA7FED5785DF024A614D -DB67101253EDEECBEC0BC7CC89B3309D27E0EDEE928FFBEC92EE835BD2A710AC -50E11EE5CFDB0805735476309209374D0DA0B3B8A8691EC1BA0B22DEE79B5874 -FFD1169DFAF3317371D760162D2E5E1E73EA7961C05F5DCD360E4443ABCA9B6F -F1C52B6F2170ECFAFC621B9B45E53F52B303869246487440F3D53F0D8237F0D3 -21F2C6A1CCB0E778835F6ECBAE779B02A4B430EE90FC9E639B4F21EB3B8EFC70 -1C3AC775BA52151982050E2D9078CABFB0E77BC1467D471D70BB4A81F2D8CE8F -110A35CD8F1B4E657CCE94A1FA11A68BE024EB644B132C316A09706B657102D3 -C609D216BA0FEEC8705A3EC5C2FB2C97D06E0119FAD3E0C488B3B5ADB720519E -8D779F642BD1C1C5FC160B0F75FD0EACAA229465DBE958DAFB1DAF86BE7E06F7 -CC8BD1D023696B692E9CD4A2C64364F598670F888A78C30712A68FFB2F50C08F -8CD4517F9ACC6E6274BF9527C25E59A1CC62510C3C159D8513707F1B5FACD0C9 -81895C54192752B04FE92BB6DE1022C44FA2C6216925986DAF611A1C530F9D3A -8730F45CA4EA6B21B6CF4D44F6E3A10B637B3410F4F5537AFC5EA54218E5379E -958FB904E65DD78DF1CB9758A1E675522D38016154FFB4CCF8DA7419616427D4 -D94A28F62C0F82704F4447A42E43E8BBC8AC451254EB898EB86135DF5DEFBC09 -94CCAEFD5C62DF5922A669E29A06E55ADAE0CFA13C441278BC9F300C60A0D140 -584AD7C102EA5BA4E140927DD70440CF0A04D4CEADE1F89935A05219D71B94D3 -4BACE59B6ABDCB6EAC73BE0E2E0E2B3DCEC436D37C2B31D93BAC0835F6C6AE36 -DA92DAA5DFEFF98AD88A3E39EA05C70517FD588FF595AC8ACEFD43DDA0EA0716 -AB97DF6A66B63AEFCCA311C1FD313DC6F1DF3A28CAEB6E1A878AE8D2204F13C4 -FF7F4BE6C7F6B1148D101EDA2E7EF5EF64358465A45FF5153097A0702C49FB5F -E772C974962A409AED231EED738A8441B4B74B18FC5C3E0D5658627880D15E24 -51C990612FC6EA4BCC7B19432120D109C7A0EFBCEE31CF2D0209EB582512B8DF -1EF478EE907A66ACFE0F0EB2367D30BEC512B3E13A77863F05DD3CEFD962EE21 -BE78478EAEC1CD6A1430753DC40E2F443F8811F4981FF7102D5C01EA61D68CE1 -70F92420E37FE3437858A9FF956DCCC9B991D9CDBAC0918FE8C8BFCB5EF28C3D -75BE99A302790CDB054BB82CD682D4A2F524371E3BDC71A910A873A7B5DA1748 -4BE4D3B0E1EB80CC24992A57F83BE21BDFD31D9EC9D0CCDB014451739397A1F5 -1F9C90F10457BE1731B9B53EE7F2CE5CABDC82B8B6077759101C5B04AC0F9FDA -DF4802620ECB8C7170BA39F7709F9AFAE6241C61AC8832688DAED86B85988790 -EC41B088CDA53DA646EC7D66ABBFD954E176F26E074A1EA2401A3EE979EEFCE7 -52F7A151B1786CC4159D94985D8D6083C23CDCA11C30E0D3A7B07CE8C005634A -8A737B518C8C436702EBE49D0709B59FD366603B062A10F82AF3D2EDE0374987 -4E14755E9BFBDB3D34A87F2C6659E7737B33A4368D556F1AE0FA06AAFD75BB54 -8E69DA1B393D7A068985A537EA9B3046AE397BBEA8006912097A0FF7A8588BFF -9D306370D71E9FE625F0746E526444AFDAF8F166A336EA2C0E28298ED7E06A80 -6F1785B62EC3DE9C104CCD52B318F2AE555A00719C43D68D70ED2451DF86AA08 -650D28ACCD67CBD33738E7757E8E2B0CB0093CD2F99FC78F082F294BB4F0B99C -F9231F11FBB3A1F2B5E12E7341CBBD518A1755F0BD5F99A1AB5558D08F531565 -D8FC143D9BD83DFBADEBD5E592869F85CCB38513AB28E8DB8BB3571CC6E3CEE2 -113B83F27568F2C06381E202A5DFD81182803EA2C9C5A42E025CCB47B9E28565 -1DE94328117528A57CFE7A2F947D137963798BFC38697078108C2DB9CD1172D4 -9C24A9E5CE4CC4C9588851EF85982ECC428B172FE186743B4EE44C89D2A8C5D4 -684D87E2D3E10E71887716F92D393E197D04D0530D7FD4D38344A8EDA3EB656D -43E2F0969B674A3E39EA722AA7E0F0FC15F7D815ECE3C0A014E08259EF587C6F -102F09659DCFD708E8460D6C139F906538DC8016DC25992B79DE18A8F05FD56E -BADFC6A1243D6F2B06B1A6714427A9D045DC87743ED9E41CE1ABA13060115199 -66601D96EBDBCCC874EDB0A29C1730789168BA13E312860F6F86465783C6A7D1 -603E86CAF75E0C43456D96124174117EC1007ECF9CC357F1315F74A733E787EF -9E3B8B0B75BE57C1CEFFD6B1B874D71EB8836894119991DCE9BEF9D8131CEBA6 -EDCAFAA65297048EB2C7DBD0B7504397BCC1F9814637EF5B32E1460EF2F95BA2 -27688CAAD92327EB9A0F938585F0C4E51A9A47983E8574836AA1D35FC57E139B -B2C82C969C76E3DC60201C072108277DD312DC4CF49CF87155CF50393705EFCB -2C14FF684DF7ED87626156DC32C14F705AD1D0D211F915CC725936768787EE0D -D642776251D24F43B3768D71DADC11E2AACB273F54C4F56099DF7F8A88B07516 -6575E551FAB8B2DBA3C0C1E04B8A06F4A8BB65814BDF54BD6E3BC7814B08FBB7 -456270E8C6AE4E821C7F2CFC2E5D63F5C1A11DD4C9E22DD675E80C52018F7499 -E826AA4B0847AAD1A6DE07CE420915D8D6818FB18F2A9ED99D88926E51C63059 -CB3953AE041479135B2E9B47BC35FDDC36FAA07882784CC78DA0D1A0C9A011CE -9FAF50F8F8ED0D2C9F7019A57B506845A95C8C5B84F758D82EAFD78EF15971FC -959C85DC40A32E9C92B313AE6C9B6A01363FC91D7820039F5C6F6C1F688198C5 -13E8D588B4A71EDBBFB9E6C75D7162DD1791E120BD3A7F227A8DDC3CEEFE0070 -8BA14D2D951331B13224D4CA86ECDC9F9A87B85B8B601B3C023490F8964B7340 -BE5DFEB44D8129E4DF880C7DF46B8AD43AB8258815A9FD0161B2C714B2F070D6 -A7C9C5DD73046F66812A64213663B22BCBE30E38EAE068CA839627F0FE89F632 -02FB4569D8E8A6E59914F1E260A60BFAE9FCE805B4AC2715F06CDAB981611B52 -32EF37F9856426422D99FD191A1EF1D7FC9ED28E0D6CC158B0B0A8F72B1E8883 -7143CACDC1F27EE7A0C5903718DC849403863F1534A7E23EBD7AB5AE29EBF935 -E959A974A941C1745C5770E6BBE7EC5FD30208774B8772016D316BD7690C6A39 -E8E20CFA76F939AE4B221A169A00A5039FA47A7B48986DF2CA1079FCEBAE747D -7513FB5EF38DC36342D70A9FB49A0614E2BAA890C8D785611AE96FA89A6435BE -44B1BAD77748A9B60AB93323E2A1D3CCA01ABC0D6D96CF72BE10B771A08A7129 -7FAB1C32C18830CDAB687B7D2052C021AD63857B72869941B712B26073AEA9D3 -C4549815A3CA2185086AE255D46057E9313C7DFA2AA8B5BF9D81397B3BF0E764 -6515C130474C7EEE18084EB0526182290F1DBEC691B8C91407C71F2A3E85D139 -B3F9D99F4DDE8DC25D5FE1920C0B143C205F743CDB43A3229A1300097ECC7E46 -036B57C6BF9E874A4F057629652A8120CCC58E9959E740D4DB634C6546DDDCF0 -2DA9C6338F2ACEBABDEF4500005A99B2994DA9A5E0A3C08F7A632456A6483D4D -9DEF610FAB840D0F62D874776B5C97AA423B447CE40314ACD46AAED6A25C5CD9 -8488212F7FB72A3955AAC14EB0C7615D40B8CA426A45777F9F93703C616D035F -A8893F61E04B7563E499191BDB49453FEA2D0879280FBAC652D9ECD62062E10B -2ACB96844957A3A5AD5A83791BCEFECCCBBC0B6BA1A117BE2CB9A71DDF073411 -AAB14A231355E9B0527A3C3EEC4D3DB9D735DAFCF970CB3F995DFC5875A489B9 -A4E96CECB90A2482626FF34C78B3CCFA0317DE630A588E279BC76A61B78FC928 -3D59E1D3D24211BB6EB15EFC7E8B9161510B5F0236B0AD1B67F3D088587FD0A2 -DEBACC3D547E0C12CE9FA3706DC50DCAF98065832E0A8A169190B86076EB2AF5 -25C8C3729E794BB0DCE5B4C9F11D740DCB0D0515ECDFDD48C47D3EA852DE75E7 -F3DD2718CA6B094A53260A57344AD125174EA3399A5F22C6B11DAB632D362C37 -EFB4A16A2B75AFE418BE039CDD72192BF9A58AD70FC104F589DC6023F37EABFF -EE3F006D95FDA92FAE72CF092A6709E39B7EBADC93261FBFFD1896A2F1E0256E -912046D78ABC3F29C67E6E5FE61A4BD9B5768AD9C04D391C982C34E1A64A7C4D -78D2E6F3158996F1BAA8E4016B8A28FADE2F30B99D56FC8DA18E1B26FB9B64BE -C64AC01227309C20FEC2826E4CA827DECDEC2DC1A3496813687176BA5A3D5A7F -932655878079E87BC60DE43BA4A5DDA07452BA34C90EB25ACBF6223117D2453E -469E1DD6A30013C02577C1988AE297C336BE4F1B2DAE1357DED4C281804A6428 -4A5DD81EC58E0AE4F3C4FBCC5871C3E5D608475F820178F239D20CFE4E231C43 -964D005E6C195073D311DC283EC992BBB401072FBCCC4DAB98176F964BD7BB62 -16A81626B2702B535AAB78180A766267F272BCADAA5FC72431B484A55A6E7F9C -5B088F33F101783661FDD5A09E032EDFFBC01C84B6610F4B91568706ED5A5170 -18A33B5477F84A6111FC62FBBEF6D5C81472649C512D4F2FFD5180F716AC3F4B -5614FA76EC6889E026DC2F3CCB57625A2640E9BDB0F65B0CBEEB39F0B52C0016 -825C2ECAB8D9032B8CEBB878B6FA092BE3DB7E31BD8682E70D248BADD12044AB -0224ABE40A44B8FDA4DC83A9F2D2D160EF0129C080784A4DE95117ED716DDD43 -12718062C87CC52DF973C4FA70F6AA8D618505C613321A4EA9FF19936D6D528B -4ED3A369F72E6286DACA19D79149584A0E801CF8D31F16452CFAD37F3021ADBC -CEE4E44E510E11683CCFBF492F94053AE23EFDFF2161808A8549B323FA990E0B -DB3943BFF22FC11B667A566E6AA953A16F5665C1801372F140867E4FB07E9669 -EFFDC88C3EE832487A4F1188C5CCE060AD8C19E1E147A6DF06D860EB7231EE5A -CE0E60D89DA003D46A4B0010514D8B80FBDA3B70E8DE17492CB746F9C082F69D -A4016DFE38C223D0D747F869FDCFD4FC890A4CA1ED03A6824E9BD3A3A425086E -7539FC47C845D4AB453DF6D0244CA6BD39582044E57A68A8A2438B4551341355 -630C439BE3347890E771980FC342679C4A0966EAC43627FFCC6DE49BE98A4CDC -0889B5005E7B092ECEF9089AA1BE5BDB65154D6A91CE4FF1DA94455DE9219C77 -80F67BE96BFC01BF65B5BFD30B6D8B2A362F19E3C822762EB978D0D240524934 -FF6674B1A8A82D4F91445F8A7C3E1EDF76C2E982473D8983E1A78DDFC92F2A44 -601C75FE11876E16B5CDF51F2C83CD6105AD789C510FF8788F65EB276649518A -C21E696A2230E409109227FBB7567875C1DA79283C403D427FB85E43DC1EFDAD -3C2431F18FFD7F0AF3CD7A374A90D822E290CDDDBB5375B2F8F572D8914F73A2 -54A28EAFBE8E14A890CAC1D169A8B63A34452524BD16EA3EF971293AA6B6C9C4 -183D333D4B5162B9072EDBC8059187FE1F442201A1EAEEE0ADAE144831093C93 -C429DB3FE6CE765B9BB1EA433E465420C5E14895A66A335DB242F65C7E59F2AE -7D9383C11D7071009F3A33819274FBC5940BD7810905B2E03E296CB0426076F4 -8D990685E417AA6F506F6F376B39BBCC77EF7C9E9BCA8FD86D1AD8C189ED73B4 -45F86749BDAB86E6ADC9F0BAD2A53345EC67C39740B2FC90007C07F3D7A73DA9 -002F0C14A1AD437ED53C620D2EF261EA7BB5CE7C8EDE7F3DA5098F95693275B9 -FB4BC5E77D169043AD6D1A513F94BB1DDFE211DF215E4E361F8E4B6335FE0417 -AA9424A8D18E814FC58DA5A396A84367751D40CBF433A2B2D199653076D96462 -69437612EE5467879FF9525B3A883F73A4E6764AE567A7FF370EEF9C212B4992 -B72168A66CAC4A3FD99CE692586F5B4B9D2B7D21B6554C0E465459DAF71A6790 -306811839A44C1AD488D12DBCB8C92D43B063ADE522B5F8A8E084BFBCC285144 -A046FBF740FF21BA2989FB62BA2963EB453D354C283AC28EF072D108421319C0 -19BCCA5379CCD8DDC7D5B125F319296A8C21DBFE593983B535CC755C875DA4AF -3019EBBEEF27471D150ABC30169BD4A812D17674F1213973460CB3DED092B767 -9E39F3ECC64AA8BBE99F8D1993AF8BBF23263869CEF635B1306583415B38C171 -FFEE3C2308C045A2420768F8DB732C0609FC8FA70C05ED8F3F99345236FAC181 -BC8999A8A905F7C36556FFE953C262375C74CA32F8DE7536951BADC2EE670CD1 -4728D3422535D68025B8780282F8FDCAC51C9BA5C12905E70812E6D1F6784A17 -811BFDBA1F876067DE0CE7D7828E57EA63FA1695DCB934870DFE60AA06873CCF -E7FDBAEB63524C98DE54C571AA8B601FEF90E8644358FB58F5230EC403B854D8 -C42A40CC1A10C4472579F3C3E021FA569FE7F95FBC924E5622994E56763B8323 -30F135AC7A00F4FCE208C0EE882213C393B7BDBB3FFDD71F697C78FA1A04BD8F -90920E21A78873EC55EF3452EEB8DA6284FA050B690C786B9A7922AB97BF6E8A -7E6261DE73497A0C517544A767918FEDAF76EFF5B3B4DA485AC3E430DC92D3FF -3D9EE4026880D9518E81B7BAF9C40536EA9B8FB04E92B6757D96206C4C73B5B2 -22E2A432BE7429E421FBEAE789154122B51033F44F79994E52010AE397C76BBE -1BE2CAB381B7D06E3E5B83B01636F1AADBCBCB635383759893DDE83EC09D2866 -0A9800E85432C0416178143D39B91027F7AAD2A5929D4CC2424921B2D3D734D4 -AFC2BCDCC61AE4D4BE4A371D158F1DEEDC8AAC215DB1F3FDDE37C7D591DA326F -AA5CF06CDDD1D11CD0C8150227B98850A6CFA4CC750F4429BAB0B465065ABF5F -F6D30344C9146538F55B5D04D25456FCF20F28543183547C9698DCFBA7CA76A4 -FA0E21538F3757D249154FCA75DD1A0F2FA7B54E185ADA55910EF3BA1311931E -51B3D2D5669970E685D63436B4111B1930F50ED4596983DC7F24B6C1CD274709 -3C5AD44D5F1F717F0827DDA6FC31779E03451CCE6581EA63906C5903ADB60FB5 -58CF0EDFCDC734868F0FF52F6D50A3D00852F3437414981A061DE1A2810F6CD7 -3FBB2992814DD9D07BBF47B6FF64D0CADEEC28809F0E14D26D11631B69E4E86F -F61D5C222ABFB3DCAE4D0EB67883F010ECF1FDBA7389843B4F095151ADD31A3B -0CD56AC195E0DBA0923032149E8EDA1C50B3E0A425EE077B8A2A29599E4E2FB5 -88AD74A4F775391403043020CF400E1DD5501E9997B53083A7E4CE64AC30108B -04D4BAAD9C844D73FE0CBDCF782941A00C97CA55238BE1B7058EFA8917743553 -D4956EBC4E7B27DA51CF9F2F10E257DAB7C9887BC0A8F14C57AC90CA41684588 -C09FA2470863F5D276D6C5ED760B77001CD09D838648FB5329E81AC30C12D170 -57CD73A1B56AA117DA3219B65C9DD97FE44F096FBB39FCBEF43FC119CD2CE3BA -6F3596F09526A3DE25B1FD0DB419B54AB405942CB45E8638E741438FF46DE505 -1B021D08D0BE0F1D8BBB382608F0315314311511D592C2E67CDB43F8F654F123 -047C880153BED6DDCF16FEBDA6AA567BC4DDFDC051DD41D840627A88272AFCFB -A3977038B42BB43F7AFF34F945ED97CD4CAA28400285E3C54E4B1032C4373F2D -6047C757C88E5666BA8D639B20959576CA6F2DE064C270EB5235B22F34F2B2E1 -8203AC15DEC0FD4DAF4C7F3BBF81DEF38569BD14B6D2A255DC599ACEB73199A4 -D7EC53B536510DCA20D410A662AFBC9D3AAB7A8E29D08EA1DEF9C0FFE4394532 -E58D5EBA9D542398E959DFC18E372A412BD39F066DC861F34C2AFBF09B49B5F5 -2A8EC0EEE77FDE43FCBB5A090D7A35A1B6A0A0817887D521EBBEC240369DA220 -002585EF3EDFF284E701D458DBB45B2EBD4396792A1D39A235D4D6D83B3C92D2 -D5A8F9F9E22FEE2E1F474B3AD49DB905F4BECA2FF798CAEDF46727E3D0694F8E -54A9B24BB9EDB35B7C98E9A5761F24448F61A4531499C23AE231C0ABD40CD036 -059E3AAEB136C9B025AA6E6AD9DFB5C17305526A2693DBD1C87D8AA06436283A -64B8B097B6CB0AC6B42D18149FE0B634C0DF78B15F636B0A362873A6AABE22AA -DE6EBD400396C61F7E0D84BF337098715A8405D42739C9A8DD911A638946F0B5 -5AE24D47E0420776F0A51A1A3260C324D5B955F837081BD40467B43FF49A0F53 -F658CD477E3D693822B73CDD1D652D62B229AB824BF7EF7859DE7B968BA04A61 -09721624BFD14914375E77C6B446425778AC25E6D3CED4AB1CE48960DB110BC2 -8533B3CF14AF449266F3EF4967FE45803C219D35945707AF991AB90DFA0555E2 -624F635CFF4078F17E26267807256DE04D347BF3C3EAC4C98071E382BA24834B -A854D5EBFD26AC126D7340535C4F4B5547E220779E3434C177D56ADE2F877D96 -3E0031162A79E93E1B32A5D4A9B1E1B084DD40C0528CF9AF65ACF6E834925E8F -E55F834BC5E66682D9A0D03B0FC3880AB92CE17A514A6C7EC7F2DBC7456BE9CA -EF4158ED3EA6782150B8652BB2CD96831F23D8307449F656C524E13D58ACE7FC -AE75E5E4BE00EA846D7FF44E459FE68A7668EC9BDF296BA04C9B66D9568CBAFA -8738509ECCFBF89027B516523B473D856FFF695566866A8C2913042097EEE2C1 -5A71C0637F87F2F38966B1B2C58FEF7BF8B1D6530224CBA844F17C7BB9F3DF6F -3B6EC807C829954ECC2154DCAFA8D4D7B8329A811C535E00AEB710E52321B987 -21AAC2B5539565BE2998C8E5BB6296C7E71B5D126A8D79CA73A7F62F43B30207 -97C94BFB00EEDFA89950F54DF238B96F769B6371DBB0734C98661E47C60D02CC -589CEEE0909C749F652CA0E9A2677D0C2EDB5B649536A779FE24B05E4215F205 -F530ED74402CFCBEBC403CC0193FDF5AC5CDE03D1066AE3429A4DE9C1C59A833 -60A28D4D79FCDD3DFCCD26A44D5B05155E7B5835C6A3A9CE6DBC1AA914EB4488 -69278FAB7C1BAE9CE7A5578CFE5D62E6F79B90D5D06BC7F8F774F8E2C656A588 -C0DEFD1DC89F3EF374BEA792F3DB1059BE3D0641DDBDE8D2106F5F4759AFF313 -04957B64AC47732ACD4A38FF44FE013E789C824ED88DED3677B04ABA725DE702 -4BACAB52388AED136B0857883FE9ABAB90892B53E1B7E4EFDEB6FC1BCE2F5EAC -400AF075D169C0E8908B0C6DBD1E20F6EF411F2CFA165AA7E322D759A48A23E1 -CCAC729AF13B5E0F1CCBD8F0F802AA29700D01B458DB10134F632C381FCA54DB -E4A2DCD5E8238F43FA5B4AED32D96617990B1190A694BA4278AFEEF4141DA69F -D5A608DE4CD199E707725DF2D3C2C73FC8371CE45D487DDBFF68E409408A1526 -0414D8EED328047DE4C0167AA43BB59648C3D508192162311911CB8967648A80 -FD49CDEE09F3BB1B2EC61EC04240A2A13C7C982D7BB3B0EC7A4293A1F59277E7 -A2E37BC6D60B7C3E54F1EAD546C00886BE531D342FD87514E96AF0BF2A234B72 -FC098986D17B15EE6E48473AC2C13809BC553F40CD996DA5097E51D0C672B9B9 -9715336EDBE4DBC6BC13262B40632EDEA4B7009A8CCDCFDC2940AAD46B4866D1 -F73A1BBE9924C27B26B47D099301831536E2F639BB5923B28F378FE54526C0E0 -FC4BB97B82A7D2FB8FC026B94FB59E0C380E822219665658EE5FFFFE35E1A60E -76A38763E408652622F59663C28C1C54B1682BD65C8B6D361EFBDE7A0E66FC6F -280FE47903BF24384A4F6A0EFE626622674B39E339956FAA2100C2B1DF034255 -EC78CA3AA823EC18F41F15F824FC4289E023C7F728E0BB9527DC9D7E0BC64054 -5258C4F6022865AA71F385BDD97FFF354454BED8A0C7B2FD2D4500CB71D8C0F6 -1C52D9BB9E3BF0E6C5AA89C8FE8E15D573868EC57A2EAE23B387EE619C3ECEA2 -FE453FAE298F27505B35203DCA7DE015A38F81459B79E117C5D96530D6DEEF87 -04A07821E02B8648EEEBAA121D5C70D85B870EBA691AAB08B5F8DDD1CB6EBF8B -8826EDB28C81ECDEE501651F4CF88C866F1650348263F427580D39E3CCA3A794 -74567A537BE66020F3C4FF8539F5E8AAA79F9D9E22613B7E52561D39038CBE68 -D9F848A182973C9FC2EE7E75EAEA13217CB7F607C41029E2B4B0DE86523222F7 -0CE81FC1DB45737814A119C76234549F23B6202E67B8014F11E5F3A01F35195C -2A19A13318FC85C8FF881E72A143CF17767A320872D06426319CA23F6DA6A7DF -EA5010078C939A8687F40BFD9510B69DF6F544CE8C2FA75D82F29A9AEF4AD59A -ABC1E1CA00F79A40C6C71729F58FF5DCEB26A4C088539C7DC625C961F794BCE8 -8431C1015078027BA87AAA95DA109CB9F467FFB69290FD7D36B055176A2561EC -B9CD09C9781152A0428F28CA06CB762C54A84FCC6FE132C9F85243749D1F505B -CFE451A2D1316A4D2A4F6E729D06E6AC1089344AB486BCDEE96A5BF3783380F5 -4471203EB837ABB300AC692F16E88E959EC7E8C8C1CD3AAE3901C29E27EB73D6 -84F066DA7BF5B3F02457F393AAAFA6BAEB747B9DA89577059EBB9216F9DCFEFD -796C7E3C10442EBF3353FA091AE5B3C46069851810B0681ADD3F7F4855381BD2 -F6AFA687A77C84CECEE21F9AA3782EB7D94E5E8C418B451150A7AA5E501F6554 -44FFFE8E759BD5D7407B7D99649CE27079960964C6EA21118C77149263BF0568 -527E6700BB2325812F89C929C7509A91F8D4B96B7D3FF64822B0ABE4D55F48AE -435C1E7663775975A9E16EA3CBDE7E04D143051505540ED08F7FFB6C431EF0F0 -1C37CE4452D4796F05C3F4BE838AAADB7EF6751EA917D14D9A7E58C9B526947E -00F69EA2B651F4A869E7B6F7AD075E3C1DDE7C256C4A38C25A0D2DAC8D72881D -766A39D877F0401F62B2A56DE81D6BAFDC95AE4B88126C184C3359172AADFD4F -A0C0B7655F33F372A022D54FBE3B6AB4226A4967F0C1CC1CFDC757D1B88F63C6 -337ACA3F14F6F45D395C1CA6B936A430502F991CA1941C0C63A85A4A2C48A209 -B3095B7141F8A8FA520E919AB1DBCDB6A6AD556580688FD24CDD2116466D434E -47444EDBDC6EE3AAB18D1E5FB9C64A5D9AA510F186D81CD1DE38B50AF76B403A -375EBF0DF5502BB55B16C89CCAD06C1447534501B8D344CB30B4C50E29DC7488 -1DBBB826274D1C8942D925B74BE59EEE00FF7D6D7B96CCF0EF6B5B277C38FA0E -D60D470C7ECF349DEF56E05BDFA18EECF5E2FB9A621AF1B88660FE31F08D8474 -7F618A7DDAA3C284BF789D65F5E6EBCE81C2CF36BF510F3230CD18921E14EF06 -1DF24F6E8FD4A2E01539C09A27BE95F97474B2636E1D60995EF9BC1FE37A2F11 -4F0500D496C347041B6DCC553DD6576A145C9ADDE6E7F9700D63AAA9B9AD4392 -11706CA76123C09F00DCB7F959EB346F8B0B354B56FEA4515A588E03720E9BBA -D8264BB8DBDF97F68A18B5C4F05490EB9D2EF35CE7814B8730BFE6E5A103F078 -F5620B47F434DD3F4FED2BC571FD975B70CBA36A1BA851E2DEE332BE98FB0BE1 -9A2E87AF124F21FF13F63D387F1497713BFA1719A76BB7AD34A0802525C2ADF4 -83B7B1B6D7EF72443ADE9E57A1B7333F5124206EBF16C1EF65493E4F4D817806 -BA91C0AC5FC6A398FC03EF4BC6EA0EE7E31D1A0274DD95EB9A0F44FBAA48A2DF -734320200436472EF4070CADCF16FE9355FF45EC9AB8825CB39192495785E774 -F411087FD7029082E3F9BC29A501E8687060F4475A09BAD31B5DE608159FDEAC -7674A6BADF286CA4DBA4F243124C7D2D294D165EED41F699B6050352E34756F5 -0796D45E4D60755D6E2187257E97A127713D5D5F433FE3F378E0635F5FAC70E5 -FE8A8F2632F613016D4D96D20B9D63D381DC300C8CAAB2593D568D5C12D27E73 -76B8B52FF36742CD36D176F396771902097606C99BADE74FFAA28D2A9643C4D1 -C8E162E95CCE4F0A88B7D178EB271E1DB5A98F0C3D10B46AA67466E53CD0282D -F799D0180755C1EA9E2946D515A35B4D138FEF636C1A4A1CF9E4B73AD4B5EBC1 -001BF56354979A9C6911C04CD16DB92F928D3B25B3B2B978FA9F2CD022F32127 -2C53468FF065ED789B8C05EC43BC579E3B839DB0DF526A38AC8D41F364D3DB51 -38D156013444A422EF8E5108423FEF5579FF88AD4004FAAD6EC0D9F2D9380A67 -9F3E4FC00987B4C679E1DEB71F8F0B32B7D572EC44DEF432EA9836FB28FFC7FE -5E6CACF5AC0EAE45D0E67B3FC8CD1DCEE671B6D45D988111E8076909842C3860 -718C95AE0660034B46A690ADB37143538D463B9561EF91ECAAFED08BF5307B52 -2B0A9F51B454ACF31A09FEA9CA44995857A50B3032CCEB393B8F15E0DF8816E4 -D60595608354EC44E4507C5E664ADD338750A4CB8278F6AA3AF6EBE22A991AF0 -E090D34BA8806915A8C68CD3B788DBD9387F0375B02073803E2D36604210BCF3 -E17629931EA004F10AA5EE60033404771623012F70F357A26934A3FF15C43F22 -431D98954F14AFCCF298AD43010C2B697C1A17A07A5E986DFD2A894573F8E337 -ED8FEDF80CB5D6E2E8D0AAD7D06F75A71164B3A4A22DB28BBEA08501FF460B91 -336CE3359D52C87C1340D6350F033BC838BF9BFE5782B53EDB3EB3535385FC5F -76B3CF48EFBEF9A7F498F02ADFABB7C14D067C9D2D1BF13190DE94E48FE09CC0 -E154D3E40FF0A5A9BA1EFB244A2E6E9AB60EDE02C555AE301E9D000E7C9E0323 -04925DD9B92820FC4282974DF466FCB385E9E304232D2A0868BBA516E88DAD68 -5691106CE164363D596F9B77997212D26D9F7AB2D5DA099546C7A4E186630A99 -F73A3D0FE1CEE30B5C1E00A38120343F9FBC50DFDB322CEB6E06385AE8AE7E99 -8A3D6FB0E91DF07D9BA89405E3FBFCF261D216F50354961BE1DD91E096AEBE1A -CAD955F991226AB4361D3034A3A38BC4F91C5D683204390D8AB0BBF0F1617BA4 -60300C04D3C15E603247A98A8921A1965452930A9AB691BC5B59564E0E5B1D86 -2280A11BCEA2AE406EBE3EE861178D863E2750C84E2C092E2F21D07D87CFC4F3 -63E6067DFF6C1D02E6CB05520747FCF4A17D9AE3A5C1B5ADB879B1E9A864BABC -B6248EF1C7EF10E58D9B04C3447F640B13D2D09BA4695DA2CB6B5894AF7F0883 -D53F2B6556B8ED90BECE732B8B5CE8C180DB102EFD164D88ECEAF0731DB83173 -1E02C85EE0291C791888C4C1C4EC556074D52518435B7E027D6438944B9CCE3F -CDF05366304992A0A47FEBDA62C60C2D7C11D62FBE1E19820940F91132CA4893 -0BA11E72291C4FFCEBF445BC14617D1FB6F7732D5EDD2A99D0A3B907DAAC260C -9CD53EBC5E56B2FA808FD204ED487F31BD7DBA40412EC3855B3C2B76F9316522 -5D231BBF01E8254A8E30430D7A1BFC0AD8F9B88B3F44EDCCCA536FC8E9AD2A9E -3B724D88D2738C820D7799A8EDBF1DC11CE59A4CEBF07E20E7FE9B188819AEB0 -1682C78A0A484DA5715C5556CC677D52C6F628D54985B5D8C886BCA2B6588115 -C26CCB972D3EC0E4DCB5832E26843D8C6EA0D920F65EE83A4D7BD416D43A0331 -B4698B5EDAB27B0DA06F813A5B48AA1F1AA3E2C5F1C70242062D29D19A864659 -41556894BF4A1A900B3F71E3EE80BF4B332B87F7789D864314ED0EF05D73515D -6054E270398F154E60203BC73CEB70A4A12C227C3DF935EDA545593DB7E7E5FC -0CE52EE88171E8DB8F3AEBAB3854B6CE1A3F21A2A59B22614716FA5C0CBDDF01 -2115F3326B2EAEBAE05B3BB8B56B082C9CAF7F948BFA435C99B45D6826F4F2E4 -5633AC12BE23EFE1F7CE878B1B10B5819D1D5067286FC1B8ECA00339936AAC46 -99D6DDBCAA2EADDB3151B0AF1B248BBBA1796E20EFF879FFD0FEA0A2E325EC6C -CE411337A54880A2F9F0313BC7861FBB07BBF098CA9B25107BCF4F471E6FD3D6 -18A80D73203C54B08541DD167B54B29E5E52CB811842259F32BC4BDD5399A9BF -CF095D573A3CCE0FECE49FE859A13616816BC26C0AD16157B877E057662AB696 -A5 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMR12 -%!PS-AdobeFont-1.1: CMR12 1.0 -%%CreationDate: 1991 Aug 20 16:38:05 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMR12) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMR12 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 46 /period put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 54 /six put -dup 65 /A put -dup 86 /V put -dup 101 /e put -dup 105 /i put -dup 108 /l put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 114 /r put -dup 115 /s put -readonly def -/FontBBox{-34 -251 988 750}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5CF4E9D2405B169CD5365D6ECED5D768D66D6C -68618B8C482B341F8CA38E9BB9BAFCFAAD9C2F3FD033B62690986ED43D9C9361 -3645B82392D5CAE11A7CB49D7E2E82DCD485CBA04C77322EB2E6A79D73DC194E -59C120A2DABB9BF72E2CF256DD6EB54EECBA588101ABD933B57CE8A3A0D16B28 -51D7494F73096DF53BDC66BBF896B587DF9643317D5F610CD9088F9849126F23 -DDE030F7B277DD99055C8B119CAE9C99158AC4E150CDFC2C66ED92EBB4CC092A -AA078CE16247A1335AD332DAA950D20395A7384C33FF72EAA31A5B89766E635F -45C4C068AD7EE867398F0381B07CB94D29FF097D59FF9961D195A948E3D87C31 -821E9295A56D21875B41988F7A16A1587050C3C71B4E4355BB37F255D6B237CE -96F25467F70FA19E0F85785FF49068949CCC79F2F8AE57D5F79BB9C5CF5EED5D -9857B9967D9B96CDCF73D5D65FF75AFABB66734018BAE264597220C89FD17379 -26764A9302D078B4EB0E29178C878FD61007EEA2DDB119AE88C57ECFEF4B71E4 -140A34951DDC3568A84CC92371A789021A103A1A347050FDA6ECF7903F67D213 -1D0C7C474A9053866E9C88E65E6932BA87A73686EAB0019389F84D159809C498 -1E7A30ED942EB211B00DBFF5BCC720F4E276C3339B31B6EABBB078430E6A09BB -377D3061A20B1EB98796B8607EECBC699445EAA866C38E02DF59F5EDD378303A -0733B90E7835C0AAF32BA04F1566D8161EA89CD4D14DDB953F8B910BFC8A7F03 -5020F55EF8FC2640ADADA156F6CF8F2EB6610F7EE8874A26CBE7CD154469B9F4 -ED76886B3FB679FFDEB59BB6C55AF7087BA48B75EE2FB374B19BCC421A963E15 -FE05ECAAF9EECDF4B2715010A320102E6F8CCAA342FA11532671CEBE01C1B982 -4B1CF704E817814FF9C921A7DF86627623F382208EB0CCEC832D35D9B936CFA7 -3946FA2494DBC51325D4330866D33DD3E546B774EB8ACC089E62AFEE8955A55F -F2B6F74FD94C06C5C71F87938D5295A2ACF34830CD5242B56841A2B4137544A1 -32D98E64AD37F790574845703C739F5BDFB05BFA53B0F4389B0FCCFF03D25AE7 -09DDC79EAB0178EF14D67282335F3AB8B2AFACE2E06433376B2007DEE8B60624 -AE40AA85E30531E640E128CD5F89EBA045D173D10E50C8C0522099DA01F1B00C -542D6FBFA1D372D43C55305F01D70BEC886B96806AC7BA30B76FA28E75717FC8 -AB91CB77949111B50B8566C1C0242A6F73E444877F0A39CC1EA349594E7540FF -AD34A14D43FC327A1517B6B034B322B09347BA663558256046DC0D66DE0099EA -1B33A960B7A3C37FEE174795CA3C975F9D16DD114308ADD38F203B7DE2E8A220 -885A7E036E768FBB3B599E5A76C8E7CE0B75820B269EEE63EEC8156098D183A8 -A6D20104A15BE6558EFD1C9C4F5D230827E102D33E5D96C9522AD0D46B430943 -3B64D20F701A7B064FEA4EA6E28DE141C2BEF2FC6C9F3237694002B9B18789C6 -D157AD81136E8E951CBD0366A5206F05F4A68C7C1017E49F254ED437707E87B6 -6AAD86C83DBC17FBC5FCF9E51DE92CEAE5C6818967AC83A26B3AE2E54AE34218 -0D5C577A0F56115705ADADCE83D89735A71D69E8CAF93A20A22616047C498A1A -0092BC92641DF088AC0C591572F8D719394C19585CD1F03DF4D35F627AFBC502 -A2C36CB17EB20E23835F6E0CB42B1C18532DFFBF0840666FED39C99BDE7DC317 -974DC1D34097CC7B71ACDBCDED56E7EB088B4E7D2AAF4F761745DEE6D371852D -4F51756C97363F7D9AE57D19341CF566C531110F8F04197B207A4BCADA5199D4 -CB86798A5059690E4F1C18A9ADBF9BD3E54AC6BC7B0908DBE211F4E7964CD594 -1C3AD1AA5536E4BF9A0586DDC944D99238E2A3ED0F178F49B1A45BCEB385BC68 -98AEE8041EDF3243ECE88920C04B609A7373E661B0E5ACDB0FD366CC417615B8 -6C35D5FEED5EB88FE43D4688A7ECAB9D1FF5A44DFB75FE133A5C243E2B9F7F77 -B33F05A19C616A5ED4634EEAC2B9E6F9A344ADF85759070E7083FA255EC10296 -E3DEBEC97364554F8CDF3BE4E5E2EEE9E4E45FB96E677F01FA938D0CDA3F5471 -AE69BCF62A767784279F56790C0789646DF52978F125488EDCD6B73EDBB489AF -F811E568EDD1F7CD8B5BF7EBC228245BF2C62A06EB195D8741C76F5DCFE74F80 -FED9A7B976104C0CA2536A4412B89AF59686278B858584AAF32B674E90412EE2 -1C8D0463194B58C61671161578E69FC7CC0FCC62B280055D4FC3043304E9E2CD -5F3318799C0EA5F28EED6D3504E96DFAFAFC4F543F230712C706DE7C45CC9787 -A069D4DF2A2C2FBD6EAA437DF7516A3E4FD3DA89419CC9BCCD2A73AD0FA50294 -CDE5E44A9165E301B5F704365678E92FBDC4510A5DB07FD9AE33D4C84C9FE155 -E37BD11BE772DC9251386845B7BEC43C24C189FFF8BDB7273F62220AE14B1A60 -0AFE4E34818E562F410E77821E76B484F1115BD553DCB16AA903852003EF08F2 -E0F957413F700296B101646D527B5B310F1B91D0BD9E89E6A775A580201E80B8 -7CF3C74957B2A3D1570A2A4916B8A0975F0A81716DBC3951ED697869EBC156E3 -F0A23EEBD4FC396012828EFF16B54612A009DD4995F130D37BE4807F8B245CE2 -BB5A38299450E19188E0C466A7797AB2C212116ACFAEAB012AB7107AA6A2FA37 -728C28CC379BFF030365AC36905415B2DBD212248390F79B7191F2F1DA344F0E -9619C0FA65A2F476272B03C5B796D926B1790F641EB6ADD5D4442C7CA34FD39F -0F07EF7837C5C9E4DBF477CED9AADBFDED496AFF3F1C45F23D7158A56CAF97EF -92C1C497C5A01F715F7E78E0254121B30DC4524D6D5F973A4B57FBF5DB7AEBE6 -9E8434BBFF5AF266ACD0AF8BBD187FCA81C2281F0C91A034F65F1D817C719C5B -0AE0A10EDB2710CC595B4573B65B1B8E98D763439902375896EE49506856F5E2 -51038BBE4FA692FE726887E9A5E065BCB4DA264DF7CD16D67B7ED0996CC4396C -B24053DCAD500585E333CA028CAE126BFB0377D0E8366EA01F735371E3EF5190 -50F0C3BDB1D32BE74968588ECE292B2F5012586265E55AAEBECD3951AE2C9C5F -3D64EAD776C7A4DEF14290037DF2ADE3A2810143A58AB50F5AB48232FF2B1A98 -982CFCFE7A9A52A774E0D9A624BAEEFEE43CF556BAB6ADFBCA7BCDD3F05778BD -F0FBD6EDB44CE80341CFE098F908A099EE3010C7BAF55C5582B053EB0CF5C34E -991FA08EBA1FC5D3B893F8545CC37AABC686FECA16646D81EA85D25F2AA8EA77 -5E8B2FBFF81D86B7C64925E42F9FF75655AA2DC7B5BEECF8BEC424A4C236A415 -6127438B84B02A8BF4D492512634F3AD4992201D7D6C6AE703A7809A77E7767A -3511588FB5B93013A1FCD2B0380C2321B19EE90EDA17B12A0D790E5DAE925B3A -4E026D2B52866C779C83EF5F31F4F54D7A289480C2FAE03138709E503ED81204 -D6287D1711497562A0E28416E75D65D3425560F1CB61104F2A733F15AA0BEF31 -D7308DD1846D6B9B5921D36F994344441189785075F9FF2EE79207AA0E82B5AD -609C387B86EB0ABACD9CEA427B981C30006ECE05BAADF7592F74DED5907FE422 -7D316876A7DEEA4B4053702EFDA2F861490C7034E7A929F0492535503C0837EE -BC80417EAC6704D64B693819FCC0BBBEC2B9BCBD2F5FD6B5FEC468E13BF720CE -EB0BA928A7A92CD4705CA1BF67B3B395148E434029714A75CAF4AED10E45D5DC -163EBCB40CF5C9066CC946B6310B505F8FE89D7F610C9EA4E542BDCC188353CE -90D7BB66398EB5B153AA09A62ECBAD0C8B40BCC4E30280E57B47418FA66A2347 -0CAACE2201AB788595D5B74EFE9BADF5679C6A97E7E714DA8D1E7C50271E072C -AE75962CA72981F6ED551C2C9D322C007234D5DBB570E3C1EBE06DDA2E011B20 -55DD67C1D3E9B3E7AC47C1D15DFE921E8F1FBB6843BBF37D669E637D201B84F0 -9D49E981C6F1A803C1B40FE4DB82C3A53D138795B3816D4B07DE20621D5A644A -57E86C30E7A8096880A02E4723AA31EDB8DB7E95E373F96CE6E41EEC9EF06020 -E11CB902AD80E02892F6733FC715C0957238158AAB70D6FAEF073D0259DC24FD -4B3DC7F0DE52D04B1F479806E7714B73EB1D225E1A83B9BC4177EB0C672BFBFA -CF4CD8EE1C5D8639434D7951537923AB79CB195181019DB1935B705EF6DD9A3D -3F15F7E634554208F4E8E7D775BB4A6E1E0EC05DF40B444B3B8D00A528E80B09 -ED50BCB1407B90D5CB7C3FE49C4420B51FA0DF45436FF5071FDE0E17F14C650A -0785E6CBFF8E6C6A79BB002AED449A16BE91458BF2DFAE96D887DBE264B45C86 -89DD114648E6626197C1D181F63141634346FBC14CF4BB310FBCED5657CDBD54 -D86C098E7A52D9D8A829BF4C700992862434F2FAEFBD7104CE221E8D985A2AA0 -B659BE12D8CFD0BFC998A2CF7409A90690A65D20E3C909B2073D336CAEAD -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -TeXDict begin 40258431 52099146 1000 600 600 (cfitsio.dvi) -@start /Fa 138[49 30 37 38 1[46 46 51 74 23 2[28 1[42 -1[42 2[42 46 11[68 12[68 3[69 68[{}17 90.9091 /CMTI10 -rf /Fb 193[71 62[{}1 90.9091 /CMMI10 rf /Fc 149[25 2[45 -45 86[45 15[{}4 90.9091 /CMSY10 rf /Fd 134[59 59 81 59 -62 44 44 46 59 62 56 62 93 31 59 1[31 62 56 34 51 62 -50 62 54 9[116 85 86 78 62 84 1[77 1[88 106 67 88 1[42 -88 88 70 74 86 81 80 85 6[31 56 56 56 56 56 56 56 56 -56 56 1[31 37 32[62 12[{}58 99.6264 /CMBX12 rf /Fe 129[48 -48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 48 1[48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 -48 48 48 33[{}93 90.9091 /CMTT10 rf /Ff 133[60 71 71 -97 71 75 52 53 55 1[75 67 75 112 37 71 1[37 75 67 41 -61 75 60 75 65 9[139 102 103 94 75 100 1[92 101 105 128 -81 105 1[50 105 106 85 88 103 97 96 102 7[67 67 67 67 -67 67 67 67 67 67 67 37 45 3[52 52 27[75 78 11[{}62 119.552 -/CMBX12 rf /Fg 135[102 3[75 1[79 1[108 1[108 4[54 108 -2[88 108 2[94 29[140 138 146 7[97 97 97 97 97 97 97 97 -97 97 48[{}23 172.188 /CMBX12 rf /Fh 165[56 68 68 93 -68 68 66 51 67 1[62 71 68 83 57 71 1[33 68 71 59 62 69 -66 64 68 7[45 45 45 45 45 45 45 45 45 45 45 25 30 3[35 -35 40[{}39 90.9091 /CMSL10 rf /Fi 133[46 55 55 1[55 58 -41 41 43 1[58 52 58 87 29 2[29 58 52 32 48 58 46 58 51 -9[108 2[73 58 78 1[71 79 82 1[63 2[40 82 82 66 69 80 -76 74 79 7[52 52 52 52 52 52 52 52 52 52 2[35 32[58 12[{}51 -90.9091 /CMBX10 rf /Fj 132[45 40 48 48 66 48 51 35 36 -36 48 51 45 51 76 25 48 28 25 51 45 28 40 51 40 51 45 -25 2[25 45 25 56 68 68 93 68 68 66 51 67 71 62 71 68 -83 57 71 47 33 68 71 59 62 69 66 64 68 71 43 1[71 1[25 -25 45 45 45 45 45 45 45 45 45 45 45 25 30 25 71 45 35 -35 25 71 76 45 76 45 25 17[76 76 51 51 53 11[{}92 90.9091 -/CMR10 rf /Fk 140[46 46 1[65 59 65 1[33 2[33 3[52 14[88 -20[88 10[59 2[59 59 59 59 1[33 46[{}16 119.552 /CMR12 -rf /Fl 139[63 64 66 2[81 90 134 45 2[45 1[81 49 74 1[72 -1[78 12[112 90 2[110 6[60 2[101 2[117 1[122 65[{}20 143.462 -/CMBX12 rf /Fm 133[103 123 123 1[123 129 90 92 95 1[129 -116 129 194 65 2[65 129 116 71 106 129 103 129 113 9[240 -1[179 162 129 173 1[159 175 182 1[140 2[87 182 183 146 -153 178 168 165 175 25[65 26[129 12[{}42 206.559 /CMBX12 -rf end -%%EndProlog -%%BeginSetup -%%Feature: *Resolution 600dpi -TeXDict begin -%%BeginPaperSize: Letter -letter -%%EndPaperSize - end -%%EndSetup -%%Page: 1 1 -TeXDict begin 1 0 bop 240 1799 a Fm(CFITSIO)76 b(User's)g(Reference)i -(Guide)727 2258 y Fl(An)53 b(In)l(terface)f(to)i(FITS)g(F)-13 -b(ormat)54 b(Files)1263 2518 y(for)g(C)f(Programmers)1667 -3013 y Fk(V)-10 b(ersion)38 b(3.3)1727 3916 y Fj(HEASAR)m(C)1764 -4029 y(Co)s(de)30 b(662)1363 4142 y(Go)s(ddard)f(Space)i(Fligh)m(t)h -(Cen)m(ter)1522 4255 y(Green)m(b)s(elt,)f(MD)h(20771)1857 -4367 y(USA)1682 5227 y Fk(April)37 b(2016)p eop end -%%Page: 2 2 -TeXDict begin 2 1 bop 0 299 a Fj(ii)p eop end -%%Page: 3 3 -TeXDict begin 3 2 bop 0 1267 a Fm(Con)-6 b(ten)g(ts)0 -1858 y Fi(1)84 b(In)m(tro)s(duction)3136 b(1)136 2020 -y Fj(1.1)125 b(A)30 b(Brief)h(Ov)m(erview)85 b(.)46 b(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 -b(1)136 2182 y(1.2)94 b(Sources)30 b(of)h(FITS)f(Soft)m(w)m(are)h(and)f -(Information)38 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(1)136 -2344 y(1.3)94 b(Ac)m(kno)m(wledgmen)m(ts)30 b(.)46 b(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 -b(2)136 2506 y(1.4)94 b(Legal)32 b(Stu\013)92 b(.)46 -b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)f(.)131 b(4)0 2766 y Fi(2)119 b(Creating)34 -b(the)h(CFITSIO)e(Library)2256 b(5)136 2928 y Fj(2.1)94 -b(Building)31 b(the)f(Library)58 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(5)345 3090 -y(2.1.1)106 b(Unix)31 b(Systems)44 b(.)h(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(5)345 3252 -y(2.1.2)106 b(VMS)33 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)345 -3413 y(2.1.3)106 b(Windo)m(ws)31 b(PCs)f(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)345 -3575 y(2.1.4)106 b(Macin)m(tosh)32 b(PCs)55 b(.)46 b(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)136 -3737 y(2.2)94 b(T)-8 b(esting)32 b(the)e(Library)j(.)46 -b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -f(.)131 b(7)136 3899 y(2.3)94 b(Linking)31 b(Programs)f(with)g(CFITSIO) -45 b(.)g(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(9)136 -4061 y(2.4)94 b(Using)31 b(CFITSIO)e(in)h(Multi-threaded)h(En)m -(vironmen)m(ts)62 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(9)136 4223 y(2.5)94 -b(Getting)32 b(Started)f(with)f(CFITSIO)60 b(.)46 b(.)f(.)h(.)g(.)f(.)h -(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)f(.)131 b(9)136 4385 y(2.6)94 b(Example)31 -b(Program)86 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)f(.)85 b(10)0 4645 y Fi(3)119 b(A)35 -b(FITS)f(Primer)2918 b(13)0 4904 y(4)119 b(Programming)37 -b(Guidelines)2482 b(15)136 5066 y Fj(4.1)94 b(CFITSIO)29 -b(De\014nitions)44 b(.)h(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)f(.)85 b(15)136 5228 y(4.2)94 b(Curren)m(t)30 -b(Header)h(Data)h(Unit)e(\(CHDU\))87 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)f(.)85 b(17)136 5390 y(4.3)94 b(F)-8 b(unction)32 -b(Names)e(and)g(V)-8 b(ariable)32 b(Datat)m(yp)s(es)41 -b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(18)136 5552 y(4.4)94 -b(Supp)s(ort)29 b(for)h(Unsigned)g(In)m(tegers)h(and)f(Signed)g(Bytes) -86 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)f(.)85 b(20)136 5714 y(4.5)94 b(Dealing)33 -b(with)d(Character)g(Strings)61 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)f(.)85 b(22)1912 5942 y(iii)p eop end -%%Page: 4 4 -TeXDict begin 4 3 bop 0 299 a Fj(iv)3311 b Fh(CONTENTS)136 -555 y Fj(4.6)94 b(Implicit)31 b(Data)h(T)m(yp)s(e)e(Con)m(v)m(ersion)65 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(23)136 716 y(4.7)94 b(Data)32 b(Scaling)89 b(.)46 b(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(23)136 876 y(4.8)94 b(Supp)s(ort)29 b(for)h(IEEE)g(Sp)s(ecial)g(V)-8 -b(alues)68 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(24)136 1037 y(4.9)94 b(Error)30 b(Status)g(V)-8 b(alues)32 -b(and)d(the)i(Error)e(Message)j(Stac)m(k)44 b(.)i(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(24)136 1197 y(4.10)49 b(V)-8 b(ariable-Length)33 b(Arra)m(ys)d(in)g -(Binary)h(T)-8 b(ables)31 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(25)136 1358 y(4.11)49 b(Multiple)32 b(Access)f(to)g(the)g(Same)f -(FITS)g(File)h(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(26)136 1518 y(4.12)49 b(When)31 b(the)f(Final)h(Size)g(of)g(the)f -(FITS)g(HDU)h(is)f(Unkno)m(wn)k(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(27)136 1678 -y(4.13)49 b(CFITSIO)29 b(Size)i(Limitations)42 b(.)k(.)f(.)h(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(28)0 1931 -y Fi(5)f(Basic)36 b(CFITSIO)d(In)m(terface)h(Routines)2074 -b(31)136 2092 y Fj(5.1)94 b(CFITSIO)29 b(Error)h(Status)g(Routines)89 -b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(31)136 -2252 y(5.2)94 b(FITS)30 b(File)i(Access)f(Routines)g(.)46 -b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(32)136 2412 y(5.3)94 b(HDU)32 b(Access)f(Routines)72 -b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f -(.)85 b(35)136 2573 y(5.4)94 b(Header)31 b(Keyw)m(ord)f(Read/W)-8 -b(rite)33 b(Routines)40 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(37)345 2733 y(5.4.1)106 b(Keyw)m(ord)30 b(Reading)h(Routines)65 -b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(38)345 -2894 y(5.4.2)106 b(Keyw)m(ord)30 b(W)-8 b(riting)32 b(Routines)86 -b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(40)136 -3054 y(5.5)94 b(Primary)30 b(Arra)m(y)h(or)f(IMA)m(GE)i(Extension)e -(I/O)g(Routines)54 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(43)136 3215 y(5.6)94 -b(Image)32 b(Compression)f(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(47)136 3375 -y(5.7)94 b(ASCI)s(I)29 b(and)h(Binary)h(T)-8 b(able)31 -b(Routines)85 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(52)345 3536 y(5.7.1)106 b(Create)32 b(New)e(T)-8 b(able)84 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(52)345 3696 y(5.7.2)106 b(Column)30 b(Information)g(Routines)h(.)46 -b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(53)345 3857 y(5.7.3)106 -b(Routines)31 b(to)g(Edit)f(Ro)m(ws)h(or)f(Columns)39 -b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(55)345 4017 y(5.7.4)106 -b(Read)31 b(and)f(W)-8 b(rite)31 b(Column)f(Data)i(Routines)66 -b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)f(.)85 b(57)345 4178 y(5.7.5)106 b(Ro)m(w)31 -b(Selection)h(and)e(Calculator)h(Routines)88 b(.)46 b(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(59)345 4338 y(5.7.6)106 b(Column)30 b(Binning)g(or)g(Histogramming)i -(Routines)74 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)f(.)85 b(61)136 4498 y(5.8)94 b(Utilit)m(y)33 -b(Routines)27 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(63)345 4659 y(5.8.1)106 -b(File)32 b(Chec)m(ksum)e(Routines)47 b(.)f(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)f(.)85 b(63)345 4819 y(5.8.2)106 b(Date)32 -b(and)e(Time)g(Utilit)m(y)j(Routines)90 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f -(.)85 b(65)345 4980 y(5.8.3)106 b(General)32 b(Utilit)m(y)g(Routines)h -(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(66)0 5232 y Fi(6)119 b(The)35 b(CFITSIO)e(Iterator)g(F)-9 -b(unction)2154 b(77)136 5393 y Fj(6.1)94 b(The)30 b(Iterator)i(W)-8 -b(ork)31 b(F)-8 b(unction)45 b(.)g(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)f(.)85 b(78)136 5553 y(6.2)94 b(The)30 b(Iterator)i(Driv)m -(er)f(F)-8 b(unction)78 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)f(.)85 b(80)136 5714 y(6.3)94 b(Guidelines)31 -b(for)f(Using)h(the)f(Iterator)i(F)-8 b(unction)45 b(.)h(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)85 b(81)p eop end -%%Page: 5 5 -TeXDict begin 5 4 bop 0 299 a Fh(CONTENTS)3334 b Fj(v)136 -555 y(6.4)94 b(Complete)32 b(List)e(of)h(Iterator)g(Routines)62 -b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(82)0 -823 y Fi(7)119 b(W)-9 b(orld)36 b(Co)s(ordinate)e(System)h(Routines) -1992 b(85)136 986 y Fj(7.1)125 b(Self-con)m(tained)32 -b(W)m(CS)e(Routines)f(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)85 b(86)0 1254 y Fi(8)119 b(Hierarc)m(hical)36 -b(Grouping)g(Routines)2163 b(89)136 1418 y Fj(8.1)94 -b(Grouping)30 b(T)-8 b(able)31 b(Routines)87 b(.)46 b(.)f(.)h(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(90)136 1581 -y(8.2)94 b(Group)30 b(Mem)m(b)s(er)g(Routines)h(.)46 -b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(92)0 1849 y Fi(9)119 b(Sp)s(ecialized)36 b(CFITSIO)d(In)m(terface)h -(Routines)1777 b(95)136 2013 y Fj(9.1)94 b(FITS)30 b(File)i(Access)f -(Routines)g(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -f(.)85 b(95)136 2176 y(9.2)94 b(HDU)32 b(Access)f(Routines)72 -b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f -(.)85 b(99)136 2340 y(9.3)94 b(Sp)s(ecialized)32 b(Header)e(Keyw)m(ord) -h(Routines)74 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(101)345 2503 y(9.3.1)106 b(Header)31 b(Information)f(Routines)64 -b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(101)345 -2667 y(9.3.2)106 b(Read)31 b(and)f(W)-8 b(rite)31 b(the)g(Required)f -(Keyw)m(ords)51 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(101)345 2830 y(9.3.3)106 -b(W)-8 b(rite)32 b(Keyw)m(ord)e(Routines)c(.)46 b(.)f(.)h(.)g(.)f(.)h -(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)f(.)40 b(103)345 2994 y(9.3.4)106 -b(Insert)30 b(Keyw)m(ord)g(Routines)89 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)f(.)40 b(105)345 3157 y(9.3.5)106 b(Read)31 -b(Keyw)m(ord)f(Routines)45 b(.)h(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)40 b(106)345 3321 y(9.3.6)106 b(Mo)s(dify)30 b(Keyw)m(ord)h -(Routines)36 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(108)345 3484 y(9.3.7)106 b(Up)s(date)31 b(Keyw)m(ord)f(Routines)c(.) -45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(109)136 -3648 y(9.4)94 b(De\014ne)31 b(Data)h(Scaling)f(and)f(Unde\014ned)f -(Pixel)i(P)m(arameters)43 b(.)j(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(110)136 3811 y(9.5)94 -b(Sp)s(ecialized)32 b(FITS)d(Primary)h(Arra)m(y)h(or)f(IMA)m(GE)h -(Extension)g(I/O)f(Routines)55 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) -40 b(111)136 3975 y(9.6)94 b(Sp)s(ecialized)32 b(FITS)d(ASCI)s(I)g(and) -h(Binary)g(T)-8 b(able)31 b(Routines)87 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(114)345 -4138 y(9.6.1)106 b(General)32 b(Column)d(Routines)51 -b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(114)345 -4302 y(9.6.2)106 b(Lo)m(w-Lev)m(el)33 b(T)-8 b(able)31 -b(Access)g(Routines)40 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(116)345 4465 y(9.6.3)106 b(W)-8 b(rite)32 b(Column)e(Data)i(Routines) -52 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(116)345 -4629 y(9.6.4)106 b(Read)31 b(Column)e(Data)j(Routines)72 -b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(117)0 4896 -y Fi(10)67 b(Extended)35 b(File)f(Name)h(Syn)m(tax)2278 -b(121)136 5060 y Fj(10.1)49 b(Ov)m(erview)84 b(.)46 b(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)40 b(121)136 5223 y(10.2)49 b(Filet)m(yp)s(e)62 -b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(124)345 5387 -y(10.2.1)61 b(Notes)32 b(ab)s(out)e(HTTP)g(pro)m(xy)g(serv)m(ers)k(.)46 -b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(124)345 5550 y(10.2.2)61 -b(Notes)32 b(ab)s(out)e(the)h(stream)f(\014let)m(yp)s(e)h(driv)m(er)54 -b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)f(.)40 b(125)345 5714 y(10.2.3)61 b(Notes)32 -b(ab)s(out)e(the)h(gsiftp)f(\014let)m(yp)s(e)83 b(.)45 -b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(126)p eop end -%%Page: 6 6 -TeXDict begin 6 5 bop 0 299 a Fj(vi)3311 b Fh(CONTENTS)345 -555 y Fj(10.2.4)61 b(Notes)32 b(ab)s(out)e(the)h(ro)s(ot)f(\014let)m -(yp)s(e)68 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(126)345 716 y(10.2.5)61 b(Notes)32 b(ab)s(out)e(the)h(shmem)e -(\014let)m(yp)s(e:)70 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(128)136 876 y(10.3)49 b(Base)32 b(Filename)90 b(.)45 -b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)f(.)40 b(128)136 1037 y(10.4)49 b(Output)30 b(File)h(Name)g -(when)f(Op)s(ening)f(an)h(Existing)h(File)81 b(.)45 b(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(130)136 1197 y(10.5)49 b(T)-8 b(emplate)32 b(File)g(Name)f(when)e -(Creating)i(a)g(New)f(File)57 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(132)136 -1358 y(10.6)49 b(Image)32 b(Tile-Compression)e(Sp)s(eci\014cation)91 -b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(132)136 1518 -y(10.7)49 b(HDU)32 b(Lo)s(cation)f(Sp)s(eci\014cation)47 -b(.)e(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(132)136 1678 y(10.8)49 b(Image)32 b(Section)39 b(.)46 -b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)f(.)40 b(134)136 1839 y(10.9)49 b(Image)32 -b(T)-8 b(ransform)29 b(Filters)54 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(135)136 1999 y(10.10)t(Column)30 -b(and)g(Keyw)m(ord)g(Filtering)h(Sp)s(eci\014cation)91 -b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)f(.)40 b(136)136 2160 y(10.11)t(Ro)m(w)31 -b(Filtering)h(Sp)s(eci\014cation)82 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(139)345 2320 y(10.11.1)16 -b(General)32 b(Syn)m(tax)44 b(.)i(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(139)345 2481 y(10.11.2)16 -b(Bit)32 b(Masks)43 b(.)j(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(142)345 2641 y(10.11.3)16 -b(V)-8 b(ector)32 b(Columns)92 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(143)345 2802 y(10.11.4)16 -b(Go)s(o)s(d)30 b(Time)h(In)m(terv)-5 b(al)31 b(Filtering)62 -b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(144)345 -2962 y(10.11.5)16 b(Spatial)31 b(Region)h(Filtering)59 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(145)345 3123 y(10.11.6)16 b(Example)31 b(Ro)m(w)g(Filters)h(.)45 -b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(147)136 3283 y(10.12)35 b(Binning)30 b(or)g(Histogramming)i(Sp)s -(eci\014cation)f(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(148)0 -3536 y Fi(11)32 b(T)-9 b(emplate)35 b(Files)2933 b(153)136 -3696 y Fj(11.1)49 b(Detailed)33 b(T)-8 b(emplate)31 b(Line)g(F)-8 -b(ormat)48 b(.)e(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(153)136 3857 y(11.2)49 b(Auto-indexing)31 b(of)g(Keyw)m(ords)73 -b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(154)136 4017 y(11.3)49 b(T)-8 b(emplate)32 b(P)m(arser)f(Directiv)m -(es)87 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(155)136 4178 y(11.4)49 b(F)-8 b(ormal)32 b(T)-8 b(emplate)32 -b(Syn)m(tax)i(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)f(.)40 b(156)136 4338 y(11.5)49 b(Errors)63 b(.)46 -b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(156)136 4498 y(11.6)49 -b(Examples)72 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(156)0 -4751 y Fi(12)67 b(Lo)s(cal)35 b(FITS)g(Con)m(v)m(en)m(tions)2462 -b(159)136 4912 y Fj(12.1)49 b(64-Bit)33 b(Long)e(In)m(tegers)61 -b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)40 b(159)136 5072 y(12.2)49 b(Long)31 b(String)f(Keyw)m(ord)g(V) --8 b(alues.)65 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) -40 b(159)136 5232 y(12.3)49 b(Arra)m(ys)31 b(of)f(Fixed-Length)i -(Strings)d(in)h(Binary)h(T)-8 b(ables)78 b(.)46 b(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(161)136 5393 y(12.4)49 b(Keyw)m(ord)31 b(Units)f(Strings)41 -b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f -(.)40 b(161)136 5553 y(12.5)49 b(HIERAR)m(CH)31 b(Con)m(v)m(en)m(tion)h -(for)e(Extended)g(Keyw)m(ord)g(Names)91 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.) -g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(161)136 5714 -y(12.6)49 b(Tile-Compressed)31 b(Image)g(F)-8 b(ormat)52 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(162)p eop end -%%Page: 7 7 -TeXDict begin 7 6 bop 0 299 a Fh(CONTENTS)3284 b Fj(vii)0 -555 y Fi(13)67 b(Optimizing)35 b(Programs)2589 b(165)136 -715 y Fj(13.1)49 b(Ho)m(w)32 b(CFITSIO)c(Manages)k(Data)g(I/O)78 -b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(165)136 -876 y(13.2)49 b(Optimization)32 b(Strategies)77 b(.)46 -b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(166)0 1127 y Fi(A)57 b(Index)35 b(of)g(Routines)2789 -b(171)0 1378 y(B)62 b(P)m(arameter)35 b(De\014nitions)2598 -b(177)0 1629 y(C)60 b(CFITSIO)33 b(Error)i(Status)f(Co)s(des)2255 -b(183)p eop end -%%Page: 8 8 -TeXDict begin 8 7 bop 0 299 a Fj(viii)3261 b Fh(CONTENTS)p -eop end -%%Page: 1 9 -TeXDict begin 1 8 bop 0 1225 a Fg(Chapter)65 b(1)0 1687 -y Fm(In)-6 b(tro)6 b(duction)0 2216 y Ff(1.1)180 b(A)45 -b(Brief)g(Ov)l(erview)0 2495 y Fj(CFITSIO)22 b(is)h(a)g(mac)m -(hine-indep)s(enden)m(t)g(library)g(of)g(routines)h(for)e(reading)i -(and)e(writing)h(data)h(\014les)f(in)g(the)h(FITS)0 2608 -y(\(Flexible)30 b(Image)e(T)-8 b(ransp)s(ort)27 b(System\))i(data)f -(format.)40 b(It)29 b(can)f(also)h(read)f(IRAF)g(format)g(image)h -(\014les)f(and)g(ra)m(w)0 2721 y(binary)39 b(data)i(arra)m(ys)g(b)m(y)f -(con)m(v)m(erting)i(them)e(on)g(the)g(\015y)g(in)m(to)h(a)f(virtual)h -(FITS)e(format)i(\014le.)70 b(This)39 b(library)0 2833 -y(is)c(written)g(in)g(ANSI)f(C)h(and)f(pro)m(vides)h(a)h(p)s(o)m(w)m -(erful)e(y)m(et)i(simple)f(in)m(terface)i(for)e(accessing)h(FITS)e -(\014les)h(whic)m(h)0 2946 y(will)c(run)f(on)h(most)g(commonly)h(used)e -(computers)h(and)f(w)m(orkstations.)44 b(CFITSIO)29 b(supp)s(orts)h -(all)h(the)h(features)0 3059 y(describ)s(ed)39 b(in)g(the)h(o\016cial)i -(de\014nition)d(of)h(the)g(FITS)f(format)i(and)e(can)h(read)g(and)f -(write)h(all)h(the)f(curren)m(tly)0 3172 y(de\014ned)g(t)m(yp)s(es)h -(of)g(extensions,)j(including)d(ASCI)s(I)e(tables)j(\(T)-8 -b(ABLE\),)42 b(Binary)f(tables)h(\(BINT)-8 b(ABLE\))43 -b(and)0 3285 y(IMA)m(GE)30 b(extensions.)41 b(The)28 -b(CFITSIO)f(routines)i(insulate)h(the)f(programmer)f(from)h(ha)m(ving)g -(to)h(deal)f(with)g(the)0 3398 y(complicated)36 b(formatting)g(details) -g(in)e(the)h(FITS)f(\014le,)i(ho)m(w)m(ev)m(er,)h(it)e(is)g(assumed)f -(that)h(users)f(ha)m(v)m(e)i(a)f(general)0 3511 y(kno)m(wledge)c(ab)s -(out)f(the)h(structure)f(and)g(usage)h(of)f(FITS)g(\014les.)0 -3671 y(CFITSIO)k(also)j(con)m(tains)h(a)e(set)h(of)f(F)-8 -b(ortran)36 b(callable)i(wrapp)s(er)d(routines)g(whic)m(h)h(allo)m(w)i -(F)-8 b(ortran)36 b(programs)0 3784 y(to)31 b(call)g(the)f(CFITSIO)e -(routines.)41 b(See)30 b(the)g(companion)g(\\FITSIO)f(User's)h(Guide")g -(for)g(the)g(de\014nition)g(of)g(the)0 3897 y(F)-8 b(ortran)39 -b(subroutine)d(calling)k(sequences.)63 b(These)38 b(wrapp)s(ers)e -(replace)j(the)f(older)g(F)-8 b(ortran)39 b(FITSIO)d(library)0 -4010 y(whic)m(h)30 b(is)h(no)f(longer)h(supp)s(orted.)0 -4170 y(The)20 b(CFITSIO)f(pac)m(k)-5 b(age)23 b(w)m(as)e(initially)i -(dev)m(elop)s(ed)e(b)m(y)f(the)h(HEASAR)m(C)g(\(High)h(Energy)e -(Astroph)m(ysics)h(Science)0 4283 y(Arc)m(hiv)m(e)35 -b(Researc)m(h)g(Cen)m(ter\))f(at)h(the)f(NASA)g(Go)s(ddard)e(Space)j -(Fligh)m(t)g(Cen)m(ter)f(to)h(con)m(v)m(ert)g(v)-5 b(arious)34 -b(existing)0 4396 y(and)25 b(newly)h(acquired)g(astronomical)i(data)e -(sets)h(in)m(to)g(FITS)e(format)h(and)f(to)i(further)e(analyze)i(data)g -(already)f(in)0 4509 y(FITS)h(format.)41 b(New)28 b(features)g(con)m -(tin)m(ue)h(to)g(b)s(e)e(added)h(to)g(CFITSIO)f(in)g(large)i(part)f -(due)g(to)g(con)m(tributions)h(of)0 4622 y(ideas)k(or)g(actual)h(co)s -(de)f(from)f(users)g(of)h(the)g(pac)m(k)-5 b(age.)49 -b(The)33 b(In)m(tegral)h(Science)f(Data)h(Cen)m(ter)f(in)g -(Switzerland,)0 4734 y(and)g(the)g(XMM/ESTEC)h(pro)5 -b(ject)34 b(in)f(The)g(Netherlands)g(made)g(esp)s(ecially)i -(signi\014can)m(t)f(con)m(tributions)g(that)0 4847 y(resulted)c(in)g -(man)m(y)h(of)f(the)h(new)f(features)g(that)h(app)s(eared)f(in)g(v2.0)i -(of)e(CFITSIO.)0 5322 y Ff(1.2)135 b(Sources)45 b(of)g(FITS)f(Soft)l(w) -l(are)i(and)f(Information)0 5601 y Fj(The)22 b(latest)i(v)m(ersion)f -(of)g(the)f(CFITSIO)f(source)i(co)s(de,)h(do)s(cumen)m(tation,)i(and)21 -b(example)j(programs)e(are)h(a)m(v)-5 b(ailable)0 5714 -y(on)30 b(the)h(W)-8 b(eb)31 b(or)f(via)h(anon)m(ymous)g(ftp)e(from:) -1927 5942 y(1)p eop end -%%Page: 2 10 -TeXDict begin 2 9 bop 0 299 a Fj(2)2452 b Fh(CHAPTER)30 -b(1.)71 b(INTR)m(ODUCTION)382 555 y Fe(http://heasarc.gsfc.nasa)o(.go)o -(v/fi)o(tsio)382 668 y(ftp://legacy.gsfc.nasa.g)o(ov/)o(soft)o(ware)o -(/fi)o(tsio)o(/c)0 933 y Fj(An)m(y)28 b(questions,)g(bug)f(rep)s(orts,) -h(or)f(suggested)i(enhancemen)m(ts)f(related)g(to)h(the)e(CFITSIO)f -(pac)m(k)-5 b(age)30 b(should)d(b)s(e)0 1045 y(sen)m(t)k(to)g(the)g -(FTOOLS)e(Help)h(Desk)h(at)g(the)g(HEASAR)m(C:)382 1310 -y Fe(http://heasarc.gsfc.nasa)o(.go)o(v/cg)o(i-bi)o(n/f)o(tool)o(shel)o -(p)0 1574 y Fj(This)40 b(User's)i(Guide)f(assumes)g(that)h(readers)f -(already)g(ha)m(v)m(e)i(a)f(general)g(understanding)d(of)j(the)f -(de\014nition)0 1687 y(and)31 b(structure)g(of)h(FITS)e(format)i -(\014les.)44 b(F)-8 b(urther)32 b(information)f(ab)s(out)h(FITS)f -(formats)g(is)h(a)m(v)-5 b(ailable)34 b(from)d(the)0 -1800 y(FITS)37 b(Supp)s(ort)f(O\016ce)i(at)h Fe -(http://fits.gsfc.nasa.g)o(ov)p Fj(.)57 b(In)37 b(particular,)j(the)e -('FITS)g(Standard')f(giv)m(es)0 1913 y(the)31 b(authoritativ)m(e)j -(de\014nition)d(of)g(the)h(FITS)e(data)i(format.)43 b(Other)31 -b(do)s(cumen)m(ts)g(a)m(v)-5 b(ailable)34 b(at)d(that)h(W)-8 -b(eb)32 b(site)0 2026 y(pro)m(vide)e(additional)i(historical)f(bac)m -(kground)g(and)e(practical)j(advice)g(on)e(using)g(FITS)f(\014les.)0 -2186 y(The)d(HEASAR)m(C)f(also)i(pro)m(vides)f(a)h(v)m(ery)f -(sophisticated)h(FITS)e(\014le)i(analysis)f(program)g(called)h(`Fv')g -(whic)m(h)f(can)0 2299 y(b)s(e)31 b(used)f(to)i(displa)m(y)f(and)g -(edit)g(the)h(con)m(ten)m(ts)g(of)g(an)m(y)f(FITS)g(\014le)g(as)g(w)m -(ell)h(as)g(construct)f(new)g(FITS)f(\014les)h(from)0 -2412 y(scratc)m(h.)56 b(Fv)36 b(is)f(freely)h(a)m(v)-5 -b(ailable)37 b(for)e(most)h(Unix)f(platforms,)i(Mac)f(PCs,)g(and)f -(Windo)m(ws)g(PCs.)54 b(CFITSIO)0 2525 y(users)29 b(ma)m(y)h(also)h(b)s -(e)f(in)m(terested)g(in)g(the)g(FTOOLS)f(pac)m(k)-5 b(age)31 -b(of)g(programs)e(that)h(can)h(b)s(e)e(used)g(to)i(manipulate)0 -2638 y(and)f(analyze)i(FITS)d(format)i(\014les.)41 b(Fv)30 -b(and)g(FTOOLS)f(are)i(a)m(v)-5 b(ailable)32 b(from)e(their)h(resp)s -(ectiv)m(e)g(W)-8 b(eb)31 b(sites)g(at:)382 2902 y Fe -(http://fv.gsfc.nasa.gov)382 3015 y(http://heasarc.gsfc.nasa)o(.go)o -(v/ft)o(ools)0 3354 y Ff(1.3)135 b(Ac)l(kno)l(wledgmen)l(ts)0 -3605 y Fj(The)27 b(dev)m(elopmen)m(t)h(of)g(the)f(man)m(y)g(p)s(o)m(w)m -(erful)g(features)h(in)f(CFITSIO)e(w)m(as)j(made)f(p)s(ossible)g -(through)f(collab)s(ora-)0 3718 y(tions)33 b(with)e(man)m(y)i(p)s -(eople)f(or)g(organizations)i(from)e(around)f(the)h(w)m(orld.)46 -b(The)32 b(follo)m(wing)h(in)f(particular)h(ha)m(v)m(e)0 -3831 y(made)d(esp)s(ecially)i(signi\014can)m(t)f(con)m(tributions:)0 -3991 y(Programmers)25 b(from)h(the)f(In)m(tegral)i(Science)g(Data)g -(Cen)m(ter,)g(Switzerland)f(\(namely)-8 b(,)28 b(Jurek)c(Bork)m(o)m -(wski,)29 b(Bruce)0 4104 y(O'Neel,)34 b(and)e(Don)h(Jennings\),)f -(designed)g(the)h(concept)g(for)f(the)h(plug-in)f(I/O)g(driv)m(ers)g -(that)h(w)m(as)g(in)m(tro)s(duced)0 4217 y(with)i(CFITSIO)e(2.0.)56 -b(The)34 b(use)h(of)g(`driv)m(ers')g(greatly)h(simpli\014ed)f(the)g(lo) -m(w-lev)m(el)j(I/O,)d(whic)m(h)f(in)h(turn)f(made)0 4330 -y(other)40 b(new)f(features)i(in)e(CFITSIO)f(\(e.g.,)45 -b(supp)s(ort)38 b(for)h(compressed)h(FITS)f(\014les)h(and)f(supp)s(ort) -f(for)i(IRAF)0 4443 y(format)32 b(image)g(\014les\))g(m)m(uc)m(h)f -(easier)i(to)f(implemen)m(t.)44 b(Jurek)31 b(Bork)m(o)m(wski)h(wrote)g -(the)g(Shared)e(Memory)i(driv)m(er,)0 4556 y(and)23 b(Bruce)i(O'Neel)g -(wrote)f(the)g(driv)m(ers)g(for)f(accessing)j(FITS)d(\014les)h(o)m(v)m -(er)h(the)f(net)m(w)m(ork)h(using)e(the)i(FTP)-8 b(,)24 -b(HTTP)-8 b(,)0 4669 y(and)26 b(R)m(OOT)g(proto)s(cols.)41 -b(Also,)28 b(in)e(2009,)k(Bruce)d(O'Neel)h(w)m(as)f(the)g(k)m(ey)g(dev) -m(elop)s(er)g(of)g(the)g(thread-safe)g(v)m(ersion)0 4782 -y(of)k(CFITSIO.)0 4942 y(The)45 b(ISDC)g(also)h(pro)m(vided)f(the)h -(template)h(parsing)e(routines)g(\(written)h(b)m(y)f(Jurek)g(Bork)m(o)m -(wski\))i(and)e(the)0 5055 y(hierarc)m(hical)39 b(grouping)d(routines)h -(\(written)h(b)m(y)f(Don)h(Jennings\).)60 b(The)37 b(ISDC)f(D)m(AL)i -(\(Data)h(Access)f(La)m(y)m(er\))0 5168 y(routines)30 -b(are)h(la)m(y)m(ered)h(on)e(top)h(of)f(CFITSIO)f(and)h(mak)m(e)h -(extensiv)m(e)h(use)e(of)h(these)g(features.)0 5328 y(Giuliano)g(T)-8 -b(a\013oni)31 b(and)f(Andrea)g(Barisani,)i(at)f(INAF,)g(Univ)m(ersit)m -(y)h(of)e(T)-8 b(rieste,)32 b(Italy)-8 b(,)32 b(implemen)m(ted)e(the)h -(I/O)0 5441 y(driv)m(er)f(routines)g(for)h(accessing)g(FITS)f(\014les)g -(on)h(the)f(computational)i(grids)e(using)g(the)h(gridftp)e(proto)s -(col.)0 5601 y(Uw)m(e)c(Lammers)e(\(XMM/ESA/ESTEC,)h(The)g -(Netherlands\))g(designed)g(the)g(high-p)s(erformance)f(lexical)j -(pars-)0 5714 y(ing)42 b(algorithm)h(that)f(is)g(used)f(to)i(do)e -(on-the-\015y)h(\014ltering)g(of)g(FITS)f(tables.)76 -b(This)41 b(algorithm)i(essen)m(tially)p eop end -%%Page: 3 11 -TeXDict begin 3 10 bop 0 299 a Fh(1.3.)72 b(A)m(CKNO)m(WLEDGMENTS)2623 -b Fj(3)0 555 y(pre-compiles)36 b(the)g(user-supplied)e(selection)k -(expression)d(in)m(to)i(a)f(form)g(that)g(can)g(b)s(e)f(rapidly)g(ev)-5 -b(aluated)37 b(for)0 668 y(eac)m(h)31 b(ro)m(w.)40 b(P)m(eter)31 -b(Wilson)f(\(RSTX,)f(NASA/GSF)m(C\))i(then)e(wrote)h(the)g(parsing)f -(routines)g(used)g(b)m(y)g(CFITSIO)0 781 y(based)i(on)f(Lammers')h -(design,)g(com)m(bined)g(with)g(other)g(tec)m(hniques)g(suc)m(h)g(as)g -(the)g(CFITSIO)f(iterator)i(routine)0 894 y(to)g(further)e(enhance)h -(the)h(data)g(pro)s(cessing)f(throughput.)42 b(This)31 -b(e\013ort)h(also)g(b)s(ene\014ted)e(from)h(a)h(m)m(uc)m(h)f(earlier)0 -1007 y(lexical)25 b(parsing)f(routine)f(that)h(w)m(as)g(dev)m(elop)s -(ed)g(b)m(y)g(Ken)m(t)g(Blac)m(kburn)f(\(NASA/GSF)m(C\).)i(More)g -(recen)m(tly)-8 b(,)27 b(Craig)0 1120 y(Markw)m(ardt)i(\(NASA/GSF)m -(C\))g(implemen)m(ted)g(additional)g(functions)f(\(median,)h(a)m(v)m -(erage,)j(stddev\))c(and)g(other)0 1233 y(enhancemen)m(ts)j(to)g(the)g -(lexical)h(parser.)0 1393 y(The)40 b(CFITSIO)g(iterator)i(function)e -(is)h(lo)s(osely)h(based)f(on)f(similar)i(ideas)f(dev)m(elop)s(ed)g -(for)g(the)g(XMM)g(Data)0 1506 y(Access)31 b(La)m(y)m(er.)0 -1666 y(P)m(eter)25 b(Wilson)g(\(RSTX,)f(NASA/GSF)m(C\))h(wrote)g(the)f -(complete)i(set)e(of)h(F)-8 b(ortran-callable)27 b(wrapp)s(ers)22 -b(for)i(all)h(the)0 1779 y(CFITSIO)k(routines,)h(whic)m(h)g(in)g(turn)g -(rely)g(on)h(the)f(CF)m(OR)-8 b(TRAN)31 b(macro)g(dev)m(elop)s(ed)g(b)m -(y)f(Burkhard)f(Buro)m(w.)0 1939 y(The)h(syn)m(tax)i(used)e(b)m(y)h -(CFITSIO)f(for)g(\014ltering)i(or)f(binning)e(input)h(FITS)h(\014les)g -(is)g(based)f(on)h(ideas)h(dev)m(elop)s(ed)0 2052 y(for)41 -b(the)g(AXAF)h(Science)g(Cen)m(ter)g(Data)h(Mo)s(del)e(b)m(y)g -(Jonathan)g(McDo)m(w)m(ell,)47 b(An)m(tonella)c(F)-8 -b(ruscione,)45 b(Aneta)0 2165 y(Siemigino)m(wsk)-5 b(a)27 -b(and)e(Bill)i(Jo)m(y)m(e.)41 b(See)26 b(h)m -(ttp://heasarc.gsfc.nasa.go)m(v/do)s(cs/journal/axa)q(f7.h)m(t)q(ml)32 -b(for)25 b(further)0 2278 y(description)30 b(of)h(the)g(AXAF)g(Data)h -(Mo)s(del.)0 2438 y(The)j(\014le)g(decompression)g(co)s(de)g(w)m(ere)h -(tak)m(en)g(directly)g(from)e(the)i(gzip)f(\(GNU)h(zip\))g(program)f -(dev)m(elop)s(ed)g(b)m(y)0 2551 y(Jean-loup)30 b(Gailly)i(and)e -(others.)0 2711 y(The)e(new)h(compressed)g(image)h(data)g(format)f -(\(where)g(the)g(image)h(is)f(tiled)h(and)e(the)h(compressed)g(b)m(yte) -h(stream)0 2824 y(from)k(eac)m(h)i(tile)h(is)d(stored)h(in)g(a)g -(binary)f(table\))j(w)m(as)e(implemen)m(ted)g(in)g(collab)s(oration)i -(with)d(Ric)m(hard)h(White)0 2937 y(\(STScI\),)30 b(P)m(erry)g -(Green\014eld)h(\(STScI\))f(and)f(Doug)i(T)-8 b(o)s(dy)30 -b(\(NO)m(A)m(O\).)0 3097 y(Doug)h(Mink)g(\(SA)m(O\))f(pro)m(vided)g -(the)h(routines)f(for)g(con)m(v)m(erting)j(IRAF)d(format)h(images)g(in) -m(to)h(FITS)d(format.)0 3257 y(Martin)k(Reinec)m(k)m(e)i(\(Max)f(Planc) -m(k)f(Institute,)h(Garc)m(hing\)\))g(pro)m(vided)f(the)g(mo)s -(di\014cations)f(to)i(cfortran.h)e(that)0 3370 y(are)d(necessary)h(to)f -(supp)s(ort)e(64-bit)k(in)m(teger)f(v)-5 b(alues)29 b(when)f(calling)i -(C)f(routines)g(from)f(fortran)h(programs.)39 b(The)0 -3483 y(cfortran.h)30 b(macros)h(w)m(ere)g(originally)h(dev)m(elop)s(ed) -e(b)m(y)h(Burkhard)e(Buro)m(w)h(\(CERN\).)0 3643 y(Julian)f(T)-8 -b(a)m(ylor)31 b(\(ESO,)e(Garc)m(hing\))i(pro)m(vided)e(the)g(fast)h(b)m -(yte-sw)m(apping)g(algorithms)h(that)f(use)f(the)h(SSE2)f(and)0 -3756 y(SSSE3)g(mac)m(hine)i(instructions)f(a)m(v)-5 b(ailable)33 -b(on)d(x86)p 1784 3756 28 4 v 34 w(64)h(CPUs.)0 3916 -y(In)c(addition,)i(man)m(y)f(other)g(p)s(eople)g(ha)m(v)m(e)h(made)f(v) --5 b(aluable)29 b(con)m(tributions)f(to)h(the)f(dev)m(elopmen)m(t)h(of) -f(CFITSIO.)0 4029 y(These)i(include)g(\(with)h(ap)s(ologies)h(to)f -(others)f(that)h(ma)m(y)g(ha)m(v)m(e)h(inadv)m(erten)m(tly)g(b)s(een)d -(omitted\):)0 4189 y(Stev)m(e)g(Allen,)g(Carl)f(Ak)m(erlof,)h(Keith)f -(Arnaud,)g(Morten)g(Krabb)s(e)e(Barfo)s(ed,)j(Ken)m(t)f(Blac)m(kburn,)h -(G)f(Bo)s(dammer,)0 4302 y(Romk)m(e)h(Bon)m(tek)m(o)s(e,)i(Lucio)d -(Chiapp)s(etti,)g(Keith)g(Costorf,)g(Robin)g(Corb)s(et,)g(John)e(Da)m -(vis,)k(Ric)m(hard)e(Fink,)h(Ning)0 4415 y(Gan,)i(Emily)f(Greene,)h -(Gretc)m(hen)g(Green,)f(Jo)s(e)g(Harrington,)h(Cheng)f(Ho,)h(Phil)f(Ho) -s(dge,)g(Jim)g(Ingham,)g(Y)-8 b(oshi-)0 4528 y(tak)j(a)44 -b(Ishisaki,)i(Diab)e(Jerius,)h(Mark)f(Levine,)i(T)-8 -b(o)s(dd)42 b(Karak)-5 b(askian,)47 b(Edw)m(ard)42 b(King,)k(Scott)e -(Ko)s(c)m(h,)i(Claire)0 4641 y(Larkin,)32 b(Rob)g(Managan,)i(Eric)e -(Mandel,)h(Ric)m(hard)f(Mathar,)h(John)e(Matto)m(x,)k(Carsten)d(Mey)m -(er,)i(Emi)d(Miy)m(ata,)0 4754 y(Stefan)39 b(Mo)s(c)m(hnac)m(ki,)k(Mik) -m(e)e(Noble,)h(Oliv)m(er)e(Ob)s(erdorf,)f(Cliv)m(e)i(P)m(age,)i(Arvind) -38 b(P)m(armar,)j(Je\013)f(P)m(edelt)m(y)-8 b(,)43 b(Tim)0 -4867 y(P)m(earson,)d(Philipp)s(e)c(Prugniel,)j(Maren)e(Purv)m(es,)i -(Scott)g(Randall,)g(Chris)d(Rogers,)k(Arnold)d(Rots,)i(Rob)e(Sea-)0 -4979 y(man,)23 b(Barry)e(Sc)m(hlesinger,)i(Robin)e(Stebbins,)h(Andrew)d -(Szymk)m(o)m(wiak,)25 b(Allyn)c(T)-8 b(ennan)m(t,)23 -b(P)m(eter)f(T)-8 b(eub)s(en,)22 b(James)0 5092 y(Theiler,)k(Doug)g(T) --8 b(o)s(dy)g(,)25 b(Shiro)f(Ueno,)j(Stev)m(e)f(W)-8 -b(alton,)28 b(Arc)m(hie)d(W)-8 b(arno)s(c)m(k,)27 b(Alan)e(W)-8 -b(atson,)28 b(Dan)d(Whipple,)h(Wim)0 5205 y(Wimmers,)31 -b(P)m(eter)g(Y)-8 b(oung,)31 b(Jianjun)e(Xu,)h(and)g(Nelson)h(Zarate.)p -eop end -%%Page: 4 12 -TeXDict begin 4 11 bop 0 299 a Fj(4)2452 b Fh(CHAPTER)30 -b(1.)71 b(INTR)m(ODUCTION)0 555 y Ff(1.4)135 b(Legal)46 -b(Stu\013)0 805 y Fj(Cop)m(yrigh)m(t)37 b(\(Unpublished{all)g(righ)m -(ts)g(reserv)m(ed)g(under)e(the)i(cop)m(yrigh)m(t)h(la)m(ws)f(of)g(the) -g(United)g(States\),)j(U.S.)0 918 y(Go)m(v)m(ernmen)m(t)30 -b(as)g(represen)m(ted)e(b)m(y)h(the)g(Administrator)g(of)g(the)g -(National)h(Aeronautics)g(and)e(Space)h(Adminis-)0 1031 -y(tration.)42 b(No)31 b(cop)m(yrigh)m(t)g(is)g(claimed)g(in)f(the)h -(United)f(States)h(under)e(Title)j(17,)f(U.S.)f(Co)s(de.)0 -1191 y(P)m(ermission)g(to)g(freely)f(use,)h(cop)m(y)-8 -b(,)31 b(mo)s(dify)-8 b(,)29 b(and)g(distribute)g(this)g(soft)m(w)m -(are)i(and)e(its)h(do)s(cumen)m(tation)g(without)0 1304 -y(fee)f(is)f(hereb)m(y)g(gran)m(ted,)i(pro)m(vided)e(that)h(this)f(cop) -m(yrigh)m(t)i(notice)f(and)f(disclaimer)h(of)f(w)m(arran)m(t)m(y)i(app) -s(ears)d(in)h(all)0 1417 y(copies.)0 1577 y(DISCLAIMER:)0 -1737 y(THE)33 b(SOFTW)-10 b(ARE)32 b(IS)g(PR)m(O)m(VIDED)i('AS)f(IS')g -(WITHOUT)f(ANY)i(W)-10 b(ARRANTY)33 b(OF)g(ANY)h(KIND,)f(EI-)0 -1850 y(THER)42 b(EXPRESSED,)f(IMPLIED,)i(OR)e(ST)-8 b(A)g(TUTOR)g(Y,)43 -b(INCLUDING,)f(BUT)h(NOT)e(LIMITED)h(TO,)0 1963 y(ANY)33 -b(W)-10 b(ARRANTY)33 b(THA)-8 b(T)32 b(THE)g(SOFTW)-10 -b(ARE)32 b(WILL)g(CONF)m(ORM)g(TO)g(SPECIFICA)-8 b(TIONS,)30 -b(ANY)0 2076 y(IMPLIED)38 b(W)-10 b(ARRANTIES)37 b(OF)h(MER)m(CHANT)-8 -b(ABILITY,)38 b(FITNESS)f(F)m(OR)h(A)g(P)-8 b(AR)g(TICULAR)38 -b(PUR-)0 2189 y(POSE,)24 b(AND)i(FREEDOM)f(FR)m(OM)h(INFRINGEMENT,)g -(AND)f(ANY)h(W)-10 b(ARRANTY)25 b(THA)-8 b(T)25 b(THE)g(DOC-)0 -2302 y(UMENT)-8 b(A)g(TION)31 b(WILL)f(CONF)m(ORM)h(TO)e(THE)h(SOFTW) --10 b(ARE,)30 b(OR)g(ANY)h(W)-10 b(ARRANTY)31 b(THA)-8 -b(T)30 b(THE)0 2415 y(SOFTW)-10 b(ARE)31 b(WILL)h(BE)g(ERR)m(OR)g -(FREE.)g(IN)g(NO)g(EVENT)f(SHALL)g(NASA)h(BE)g(LIABLE)g(F)m(OR)g(ANY)0 -2528 y(D)m(AMA)m(GES,)26 b(INCLUDING,)e(BUT)f(NOT)g(LIMITED)h(TO,)f -(DIRECT,)g(INDIRECT,)g(SPECIAL)f(OR)h(CON-)0 2641 y(SEQUENTIAL)28 -b(D)m(AMA)m(GES,)k(ARISING)d(OUT)g(OF,)h(RESUL)-8 b(TING)29 -b(FR)m(OM,)h(OR)f(IN)h(ANY)g(W)-10 b(A)i(Y)30 b(CON-)0 -2754 y(NECTED)25 b(WITH)g(THIS)f(SOFTW)-10 b(ARE,)25 -b(WHETHER)g(OR)g(NOT)g(BASED)g(UPON)g(W)-10 b(ARRANTY,)26 -b(CON-)0 2867 y(TRA)m(CT,)d(TOR)-8 b(T)23 b(,)g(OR)g(OTHER)-10 -b(WISE,)22 b(WHETHER)i(OR)f(NOT)f(INJUR)-8 b(Y)24 b(W)-10 -b(AS)23 b(SUST)-8 b(AINED)23 b(BY)h(PER-)0 2979 y(SONS)h(OR)i(PR)m -(OPER)-8 b(TY)26 b(OR)g(OTHER)-10 b(WISE,)26 b(AND)h(WHETHER)g(OR)f -(NOT)g(LOSS)f(W)-10 b(AS)26 b(SUST)-8 b(AINED)0 3092 -y(FR)m(OM,)37 b(OR)e(AR)m(OSE)h(OUT)f(OF)h(THE)g(RESUL)-8 -b(TS)35 b(OF,)h(OR)f(USE)h(OF,)g(THE)g(SOFTW)-10 b(ARE)35 -b(OR)g(SER-)0 3205 y(VICES)29 b(PR)m(O)m(VIDED)j(HEREUNDER.")p -eop end -%%Page: 5 13 -TeXDict begin 5 12 bop 0 1225 a Fg(Chapter)65 b(2)0 1687 -y Fm(Creating)77 b(the)h(CFITSIO)e(Library)0 2216 y Ff(2.1)135 -b(Building)45 b(the)h(Library)0 2467 y Fj(The)h(CFITSIO)f(co)s(de)h(is) -h(con)m(tained)g(in)f(ab)s(out)g(40)h(C)f(source)h(\014les)f(\(*.c\))i -(and)e(header)g(\014les)g(\(*.h\).)93 b(On)0 2580 y(V)-10 -b(AX/VMS)31 b(systems)g(2)f(assem)m(bly-co)s(de)i(\014les)e -(\(vmsieeed.mar)h(and)f(vmsieeer.mar\))i(are)e(also)i(needed.)0 -2740 y(CFITSIO)22 b(is)h(written)g(in)g(ANCI)g(C)g(and)g(should)f(b)s -(e)g(compatible)j(with)e(most)g(existing)i(C)d(and)h(C++)f(compilers.)0 -2853 y(Cra)m(y)30 b(sup)s(ercomputers)f(are)i(curren)m(tly)f(not)h -(supp)s(orted.)0 3149 y Fd(2.1.1)112 b(Unix)39 b(Systems)0 -3369 y Fj(The)30 b(CFITSIO)f(library)h(is)g(built)g(on)h(Unix)f -(systems)g(b)m(y)g(t)m(yping:)48 3633 y Fe(>)95 b(./configure)45 -b([--prefix=/target/insta)o(llat)o(ion)o(/pat)o(h])d -([--enable-reentrant])764 3746 y([--enable-sse2])h([--enable-ssse3])48 -3859 y(>)95 b(make)476 b(\(or)95 b('make)46 b(shared'\))48 -3971 y(>)95 b(make)47 b(install)93 b(\(this)46 b(step)h(is)g -(optional\))0 4235 y Fj(at)24 b(the)g(op)s(erating)g(system)g(prompt.) -38 b(The)23 b(con\014gure)g(command)g(customizes)i(the)f(Mak)m(e\014le) -h(for)f(the)g(particular)0 4348 y(system,)g(then)d(the)g(`mak)m(e')i -(command)e(compiles)h(the)f(source)h(\014les)f(and)g(builds)f(the)h -(library)-8 b(.)38 b(T)m(yp)s(e)21 b(`./con\014gure')0 -4461 y(and)34 b(not)h(simply)f(`con\014gure')h(to)h(ensure)e(that)h -(the)g(con\014gure)g(script)f(in)h(the)g(curren)m(t)f(directory)h(is)g -(run)f(and)0 4574 y(not)29 b(some)g(other)g(system-wide)g(con\014gure)f -(script.)40 b(The)29 b(optional)h('pre\014x')e(argumen)m(t)h(to)g -(con\014gure)g(giv)m(es)h(the)0 4687 y(path)e(to)i(the)f(directory)g -(where)f(the)h(CFITSIO)f(library)g(and)g(include)h(\014les)f(should)g -(b)s(e)g(installed)i(via)f(the)g(later)0 4800 y('mak)m(e)j(install')f -(command.)41 b(F)-8 b(or)31 b(example,)143 5064 y Fe(>)48 -b(./configure)c(--prefix=/usr1/local)0 5328 y Fj(will)25 -b(cause)h(the)f('mak)m(e)h(install')g(command)f(to)h(cop)m(y)g(the)f -(CFITSIO)e(lib)s(c\014tsio)i(\014le)h(to)f(/usr1/lo)s(cal/lib)i(and)e -(the)0 5441 y(necessary)33 b(include)e(\014les)i(to)f(/usr1/lo)s -(cal/include)j(\(assuming)d(of)g(course)g(that)h(the)f(pro)s(cess)g -(has)g(p)s(ermission)0 5554 y(to)f(write)g(to)g(these)g(directories\).) -0 5714 y(All)g(the)g(a)m(v)-5 b(ailable)32 b(con\014gure)e(options)h -(can)g(b)s(e)f(seen)g(b)m(y)g(en)m(tering)i(the)e(command)1927 -5942 y(5)p eop end -%%Page: 6 14 -TeXDict begin 6 13 bop 0 299 a Fj(6)1580 b Fh(CHAPTER)30 -b(2.)112 b(CREA)-8 b(TING)30 b(THE)g(CFITSIO)f(LIBRAR)-8 -b(Y)143 555 y Fe(>)48 b(./configure)c(--help)0 830 y -Fj(Some)30 b(of)h(the)g(more)f(useful)g(options)g(are)h(describ)s(ed)e -(b)s(elo)m(w:)0 990 y(The)j({enable-reen)m(tran)m(t)j(option)f(will)f -(attempt)h(to)f(con\014gure)g(CFITSIO)e(so)i(that)g(it)g(can)h(b)s(e)e -(used)g(in)g(m)m(ulti-)0 1103 y(threaded)c(programs.)39 -b(See)29 b(the)f("Using)h(CFITSIO)d(in)i(Multi-threaded)h(En)m -(vironmen)m(ts")f(section,)i(b)s(elo)m(w,)f(for)0 1216 -y(more)i(details.)0 1376 y(The)24 b({enable-sse2)j(and)d({enable-ssse3) -i(options)g(will)f(cause)g(con\014gure)g(to)g(attempt)h(to)f(build)f -(CFITSIO)f(using)0 1489 y(faster)31 b(b)m(yte-sw)m(apping)h -(algorithms.)42 b(See)31 b(the)g("Optimizing)h(Programs")f(c)m(hapter)h -(of)e(this)h(man)m(ual)g(for)g(more)0 1602 y(information)g(ab)s(out)f -(these)h(options.)0 1762 y(The)44 b({with-gsiftp-\015a)m(v)m(our)h(and) -f({with-gsiftp)g(options)h(enable)f(supp)s(ort)e(for)i(the)h(Globus)e -(T)-8 b(o)s(olkit)46 b(gsiftp)0 1875 y(proto)s(cal.)c(See)30 -b(the)h("Extended)f(File)i(Name)f(Syn)m(tax")g(c)m(hapter)g(for)f(more) -g(information.)0 2035 y(The)22 b({with-bzip2)h(option)h(enables)f(supp) -s(ort)d(for)j(reading)g(FITS)f(\014les)g(that)i(ha)m(v)m(e)f(b)s(een)f -(externally)i(compressed)0 2148 y(b)m(y)j(the)h(bzip2)f(algorithm.)41 -b(This)27 b(requires)g(that)h(the)f(CFITSIO)f(library)-8 -b(,)28 b(and)f(all)i(applications)f(program)f(that)0 -2261 y(use)j(CFITSIO,)f(to)i(b)s(e)f(link)m(ed)h(to)g(include)f(the)g -(libbz2)h(library)-8 b(.)0 2421 y(The)28 b('mak)m(e)h(shared')f(option) -h(builds)e(a)i(shared)e(or)i(dynamic)f(v)m(ersion)h(of)f(the)h(CFITSIO) -d(library)-8 b(.)40 b(When)28 b(using)0 2534 y(the)f(shared)f(library)h -(the)g(executable)h(co)s(de)f(is)g(not)g(copied)g(in)m(to)h(y)m(our)f -(program)g(at)g(link)g(time)g(and)g(instead)g(the)0 2647 -y(program)g(lo)s(cates)i(the)f(necessary)g(library)f(co)s(de)h(at)g -(run)e(time,)j(normally)f(through)e(LD)p 3065 2647 28 -4 v 33 w(LIBRAR)-8 b(Y)p 3514 2647 V 34 w(P)g(A)g(TH)28 -b(or)0 2760 y(some)j(other)f(metho)s(d.)41 b(The)29 b(adv)-5 -b(an)m(tages)33 b(of)d(using)g(a)h(shared)e(library)h(are:)143 -3035 y Fe(1.)95 b(Less)47 b(disk)f(space)h(if)g(you)g(build)f(more)h -(than)f(1)i(program)143 3148 y(2.)95 b(Less)47 b(memory)f(if)h(more)g -(than)f(one)h(copy)g(of)g(a)g(program)f(using)h(the)g(shared)334 -3261 y(library)f(is)h(running)f(at)h(the)g(same)g(time)f(since)h(the)g -(system)f(is)h(smart)334 3374 y(enough)f(to)h(share)g(copies)f(of)h -(the)g(shared)f(library)g(at)h(run)g(time.)143 3487 y(3.)95 -b(Possibly)46 b(easier)g(maintenance)e(since)j(a)g(new)g(version)f(of)h -(the)g(shared)334 3600 y(library)f(can)h(be)g(installed)e(without)h -(relinking)f(all)i(the)g(software)334 3713 y(that)g(uses)f(it)i(\(as)e -(long)h(as)g(the)g(subroutine)e(names)i(and)f(calling)334 -3825 y(sequences)f(remain)h(unchanged\).)143 3938 y(4.)95 -b(No)47 b(run-time)f(penalty.)0 4213 y Fj(The)30 b(disadv)-5 -b(an)m(tages)32 b(are:)143 4488 y Fe(1.)47 b(More)g(hassle)f(at)h -(runtime.)94 b(You)46 b(have)h(to)g(either)f(build)h(the)g(programs)286 -4601 y(specially)f(or)h(have)f(LD_LIBRARY_PATH)e(set)j(right.)143 -4714 y(2.)g(There)g(may)g(be)g(a)g(slight)f(start)h(up)g(penalty,)e -(depending)h(on)h(where)f(you)h(are)286 4827 y(reading)f(the)h(shared)f -(library)g(and)h(the)g(program)f(from)g(and)h(if)g(your)g(CPU)g(is)286 -4940 y(either)f(really)h(slow)f(or)h(really)f(heavily)g(loaded.)0 -5215 y Fj(On)32 b(Mac)i(OS)e(X)i(platforms)f(the)g('mak)m(e)h(shared')f -(command)f(w)m(orks)h(lik)m(e)i(on)e(other)g(UNIX)g(platforms,)h(but)f -(a)0 5328 y(.dylib)f(\014le)g(will)g(b)s(e)f(created)i(instead)g(of)f -(.so.)46 b(If)31 b(installed)i(in)f(a)g(nonstandard)f(lo)s(cation,)j -(add)d(its)i(lo)s(cation)g(to)0 5441 y(the)e(D)m(YLD)p -422 5441 V 34 w(LIBRAR)-8 b(Y)p 872 5441 V 33 w(P)g(A)g(TH)31 -b(en)m(vironmen)m(t)g(v)-5 b(ariable)31 b(so)g(that)g(the)f(library)g -(can)h(b)s(e)f(found)f(at)i(run)e(time.)0 5601 y(On)h(HP/UX)i(systems,) -g(the)f(en)m(vironmen)m(t)h(v)-5 b(ariable)32 b(CFLA)m(GS)f(should)f(b) -s(e)h(set)g(to)h(-Ae)g(b)s(efore)f(running)e(con-)0 5714 -y(\014gure)h(to)h(enable)g("extended)g(ANSI")f(features.)p -eop end -%%Page: 7 15 -TeXDict begin 7 14 bop 0 299 a Fh(2.2.)72 b(TESTING)29 -b(THE)h(LIBRAR)-8 b(Y)2555 b Fj(7)0 555 y(By)31 b(default,)h(a)f(set)h -(of)f(F)-8 b(ortran-callable)34 b(wrapp)s(er)29 b(routines)i(are)g -(also)h(built)f(and)f(included)h(in)f(the)h(CFITSIO)0 -668 y(library)-8 b(.)70 b(If)40 b(these)g(wrapp)s(er)f(routines)h(are)g -(not)h(needed)e(\(i.e.,)45 b(the)40 b(CFITSIO)f(library)g(will)i(not)f -(b)s(e)g(link)m(ed)0 781 y(to)d(an)m(y)f(F)-8 b(ortran)37 -b(applications)g(whic)m(h)f(call)h(FITSIO)e(subroutines\))g(then)h -(they)g(ma)m(y)h(b)s(e)e(omitted)i(from)f(the)0 894 y(build)28 -b(b)m(y)i(t)m(yping)g('mak)m(e)g(all-no\014tsio')i(instead)d(of)h -(simply)f(t)m(yping)h('mak)m(e'.)42 b(This)28 b(will)i(reduce)f(the)h -(size)g(of)g(the)0 1007 y(CFITSIO)f(library)h(sligh)m(tly)-8 -b(.)0 1167 y(It)33 b(ma)m(y)g(not)g(b)s(e)f(p)s(ossible)g(to)h -(statically)i(link)e(programs)f(that)h(use)g(CFITSIO)e(on)h(some)h -(platforms)g(\(namely)-8 b(,)0 1280 y(on)28 b(Solaris)h(2.6\))h(due)e -(to)h(the)g(net)m(w)m(ork)g(driv)m(ers)f(\(whic)m(h)h(pro)m(vide)g(FTP) -f(and)g(HTTP)g(access)h(to)h(FITS)d(\014les\).)41 b(It)0 -1393 y(is)33 b(p)s(ossible)f(to)i(mak)m(e)f(b)s(oth)g(a)g(dynamic)f -(and)g(a)i(static)g(v)m(ersion)f(of)g(the)g(CFITSIO)e(library)-8 -b(,)34 b(but)e(net)m(w)m(ork)i(\014le)0 1506 y(access)e(will)e(not)h(b) -s(e)f(p)s(ossible)g(using)g(the)g(static)i(v)m(ersion.)0 -1813 y Fd(2.1.2)112 b(VMS)0 2035 y Fj(On)28 b(V)-10 b(AX/VMS)31 -b(and)d(ALPHA/VMS)i(systems)f(the)h(mak)m(e)p 2100 2035 -28 4 v 34 w(g\015oat.com)h(command)e(\014le)g(ma)m(y)h(b)s(e)f -(executed)h(to)0 2148 y(build)35 b(the)i(c\014tsio.olb)g(ob)5 -b(ject)37 b(library)f(using)g(the)g(default)h(G-\015oating)g(p)s(oin)m -(t)g(option)f(for)g(double)g(v)-5 b(ariables.)0 2261 -y(The)37 b(mak)m(e)p 405 2261 V 33 w(d\015oat.com)i(and)d(mak)m(e)p -1279 2261 V 34 w(ieee.com)j(\014les)f(ma)m(y)f(b)s(e)g(used)f(instead)i -(to)g(build)e(the)h(library)g(with)g(the)0 2374 y(other)26 -b(\015oating)i(p)s(oin)m(t)e(options.)39 b(Note)28 b(that)f(the)f -(getcwd)h(function)f(that)h(is)f(used)f(in)h(the)h(group.c)f(mo)s(dule) -f(ma)m(y)0 2487 y(require)44 b(that)i(programs)e(using)g(CFITSIO)f(b)s -(e)h(link)m(ed)i(with)e(the)h(ALPHA$LIBRAR)-8 b(Y:V)e(AX)m(CR)i(TL.OLB) -0 2600 y(library)g(.)41 b(See)30 b(the)h(example)g(link)f(line)h(in)f -(the)h(next)f(section)i(of)e(this)h(do)s(cumen)m(t.)0 -2907 y Fd(2.1.3)112 b(Windo)m(ws)38 b(PCs)0 3129 y Fj(A)j(precompiled)f -(DLL)g(v)m(ersion)h(of)g(CFITSIO)e(\(not)i(necessarily)g(the)g(latest)h -(v)m(ersion\))f(is)g(a)m(v)-5 b(ailable)42 b(on)f(the)0 -3242 y(CFITSIO)26 b(w)m(eb)i(site.)41 b(The)27 b(CFITSIO)f(library)h -(ma)m(y)i(also)g(b)s(e)e(built)g(from)h(the)g(source)f(co)s(de)h(using) -g(the)g(CMak)m(e)0 3355 y(build)j(system.)44 b(See)32 -b(the)g("README.win")h(\014le)f(in)f(the)h(CFITSIO)e(source)i -(distribution)f(for)g(more)h(informa-)0 3468 y(tion.)0 -3775 y Fd(2.1.4)112 b(Macin)m(tosh)39 b(PCs)0 3998 y -Fj(When)20 b(building)f(on)i(Mac)g(OS-X,)f(users)g(should)f(follo)m(w)i -(the)g(Unix)f(instructions,)i(ab)s(o)m(v)m(e.)39 b(See)20 -b(the)h(README.MacOS)0 4111 y(\014le)30 b(for)h(instructions)f(on)g -(building)g(a)g(Univ)m(ersal)i(Binary)e(that)h(supp)s(orts)e(b)s(oth)g -(In)m(tel)i(and)f(P)m(o)m(w)m(erPC)h(CPUs.)0 4461 y Ff(2.2)135 -b(T)-11 b(esting)46 b(the)f(Library)0 4714 y Fj(The)40 -b(CFITSIO)e(library)i(should)f(b)s(e)g(tested)i(b)m(y)f(building)f(and) -g(running)g(the)h(testprog.c)h(program)f(that)h(is)0 -4827 y(included)30 b(with)g(the)g(release.)42 b(On)30 -b(Unix)g(systems,)h(t)m(yp)s(e:)191 5101 y Fe(\045)47 -b(make)g(testprog)191 5214 y(\045)g(testprog)f(>)h(testprog.lis)191 -5327 y(\045)g(diff)g(testprog.lis)d(testprog.out)191 -5440 y(\045)j(cmp)g(testprog.fit)e(testprog.std)0 5714 -y Fj(On)30 b(VMS)g(systems,)g(\(assuming)h(cc)g(is)f(the)h(name)f(of)h -(the)f(C)g(compiler)h(command\),)g(t)m(yp)s(e:)p eop -end -%%Page: 8 16 -TeXDict begin 8 15 bop 0 299 a Fj(8)1580 b Fh(CHAPTER)30 -b(2.)112 b(CREA)-8 b(TING)30 b(THE)g(CFITSIO)f(LIBRAR)-8 -b(Y)191 555 y Fe($)47 b(cc)h(testprog.c)191 668 y($)f(link)g(testprog,) -e(cfitsio/lib,)g(alpha$library:vaxcrtl/l)o(ib)191 781 -y($)i(run)g(testprog)0 1047 y Fj(The)42 b(test)h(program)f(should)f -(pro)s(duce)g(a)i(FITS)e(\014le)i(called)g(`testprog.\014t')h(that)f -(is)f(iden)m(tical)i(to)f(the)f(`test-)0 1160 y(prog.std')35 -b(FITS)e(\014le)i(included)e(with)h(this)g(release.)54 -b(The)34 b(diagnostic)i(messages)f(\(whic)m(h)g(w)m(ere)g(pip)s(ed)e -(to)i(the)0 1273 y(\014le)h(testprog.lis)i(in)e(the)h(Unix)f(example\)) -h(should)e(b)s(e)h(iden)m(tical)i(to)f(the)f(listing)h(con)m(tained)h -(in)e(the)g(\014le)h(test-)0 1386 y(prog.out.)63 b(The)37 -b('di\013)7 b(')38 b(and)f('cmp')h(commands)g(sho)m(wn)f(ab)s(o)m(v)m -(e)i(should)d(not)i(rep)s(ort)f(an)m(y)h(di\013erences)g(in)g(the)0 -1499 y(\014les.)65 b(\(There)38 b(ma)m(y)h(b)s(e)f(some)h(minor)f -(format)h(di\013erences,)i(suc)m(h)d(as)h(the)g(presence)f(or)h -(absence)g(of)f(leading)0 1612 y(zeros,)31 b(or)g(3)f(digit)i(exp)s -(onen)m(ts)e(in)g(n)m(um)m(b)s(ers,)f(whic)m(h)h(can)h(b)s(e)f -(ignored\).)0 1772 y(The)e(F)-8 b(ortran)30 b(wrapp)s(ers)d(in)h -(CFITSIO)f(ma)m(y)j(b)s(e)e(tested)h(with)g(the)g(testf77)h(program)f -(on)g(Unix)f(systems)h(with:)191 2038 y Fe(\045)47 b(f77)g(-o)g -(testf77)f(testf77.f)g(-L.)g(-lcfitsio)g(-lnsl)g(-lsocket)95 -2151 y(or)191 2264 y(\045)h(f77)g(-f)g(-o)h(testf77)d(testf77.f)h(-L.)h -(-lcfitsio)188 b(\(under)46 b(SUN)h(O/S\))95 2377 y(or)191 -2490 y(\045)g(f77)g(-o)g(testf77)f(testf77.f)g(-Wl,-L.)f(-lcfitsio)h -(-lm)h(-lnsl)f(-lsocket)f(\(HP/UX\))191 2716 y(\045)i(testf77)f(>)i -(testf77.lis)191 2829 y(\045)f(diff)g(testf77.lis)e(testf77.out)191 -2942 y(\045)i(cmp)g(testf77.fit)e(testf77.std)0 3208 -y Fj(On)31 b(mac)m(hines)h(running)f(SUN)g(O/S,)h(F)-8 -b(ortran)33 b(programs)e(m)m(ust)h(b)s(e)f(compiled)h(with)g(the)g('-f) -7 b(')32 b(option)h(to)f(force)0 3321 y(double)25 b(precision)h(v)-5 -b(ariables)26 b(to)g(b)s(e)f(aligned)h(on)g(8-b)m(yte)h(b)s(oundarys)c -(to)j(mak)m(e)h(the)e(fortran-declared)h(v)-5 b(ariables)0 -3434 y(compatible)34 b(with)e(C.)g(A)h(similar)g(compiler)g(option)g -(ma)m(y)g(b)s(e)f(required)g(on)g(other)h(platforms.)48 -b(F)-8 b(ailing)34 b(to)f(use)0 3547 y(this)26 b(option)g(ma)m(y)g -(cause)h(the)f(program)f(to)i(crash)e(on)h(FITSIO)f(routines)g(that)i -(read)f(or)f(write)h(double)g(precision)0 3659 y(v)-5 -b(ariables.)0 3820 y(Also)31 b(note)g(that)f(on)g(some)h(systems,)f -(the)h(output)e(listing)i(of)g(the)f(testf77)i(program)d(ma)m(y)i -(di\013er)f(sligh)m(tly)h(from)0 3933 y(the)g(testf77.std)h(template,)g -(if)f(leading)g(zeros)g(are)g(not)g(prin)m(ted)f(b)m(y)h(default)g(b)s -(efore)f(the)h(decimal)g(p)s(oin)m(t)g(when)0 4045 y(using)f(F)h -(format.)0 4206 y(A)37 b(few)f(other)g(utilit)m(y)i(programs)e(are)h -(included)f(with)g(CFITSIO;)f(the)i(\014rst)e(four)h(of)g(this)h -(programs)f(can)h(b)s(e)0 4319 y(compiled)e(an)g(link)m(ed)g(b)m(y)g(t) -m(yping)g(`mak)m(e)h(program)p 1815 4319 28 4 v 33 w(name')f(where)f -(`program)p 2746 4319 V 33 w(name')h(is)g(the)g(actual)h(name)f(of)0 -4431 y(the)c(program:)191 4698 y Fe(speed)46 b(-)i(measures)d(the)i -(maximum)f(throughput)f(\(in)i(MB)g(per)g(second\))668 -4811 y(for)g(writing)f(and)h(reading)f(FITS)g(files)h(with)f(CFITSIO.) -191 5036 y(listhead)f(-)j(lists)e(all)h(the)g(header)f(keywords)g(in)h -(any)g(FITS)f(file)191 5262 y(fitscopy)f(-)j(copies)e(any)h(FITS)g -(file)f(\(especially)f(useful)h(in)h(conjunction)811 -5375 y(with)g(the)g(CFITSIO's)e(extended)h(input)g(filename)g -(syntax\).)191 5601 y(cookbook)f(-)j(a)f(sample)f(program)g(that)h -(performs)e(common)i(read)f(and)811 5714 y(write)h(operations)e(on)i(a) -g(FITS)g(file.)p eop end -%%Page: 9 17 -TeXDict begin 9 16 bop 0 299 a Fh(2.3.)72 b(LINKING)30 -b(PR)m(OGRAMS)h(WITH)f(CFITSIO)1975 b Fj(9)191 668 y -Fe(iter_a,)46 b(iter_b,)g(iter_c)g(-)h(examples)f(of)h(the)g(CFITSIO)f -(iterator)f(routine)0 1017 y Ff(2.3)135 b(Linking)45 -b(Programs)h(with)f(CFITSIO)0 1271 y Fj(When)25 b(linking)h -(applications)h(soft)m(w)m(are)g(with)e(the)h(CFITSIO)e(library)-8 -b(,)27 b(sev)m(eral)g(system)f(libraries)g(usually)f(need)0 -1384 y(to)36 b(b)s(e)f(sp)s(eci\014ed)g(on)g(the)g(link)h(command)f -(line.)56 b(On)34 b(Unix)i(systems,)h(the)e(most)h(reliable)g(w)m(a)m -(y)h(to)f(determine)0 1497 y(what)26 b(libraries)h(are)f(required)g(is) -g(to)h(t)m(yp)s(e)f('mak)m(e)i(testprog')f(and)f(see)h(what)f -(libraries)h(the)f(con\014gure)g(script)g(has)0 1610 -y(added.)39 b(The)25 b(t)m(ypical)j(libraries)e(that)g(need)g(to)g(b)s -(e)g(added)f(are)h(-lm)h(\(the)f(math)g(library\))g(and)f(-lnsl)h(and)g -(-lso)s(c)m(k)m(et)0 1722 y(\(needed)k(only)g(for)g(FTP)g(and)f(HTTP)g -(\014le)h(access\).)43 b(These)30 b(latter)h(2)f(libraries)g(are)h(not) -f(needed)g(on)g(VMS)g(and)0 1835 y(Windo)m(ws)g(platforms,)h(b)s -(ecause)f(FTP)h(\014le)f(access)i(is)e(not)h(curren)m(tly)f(supp)s -(orted)f(on)h(those)h(platforms.)0 1996 y(Note)i(that)g(when)e -(upgrading)g(to)i(a)f(new)m(er)g(v)m(ersion)g(of)g(CFITSIO)f(it)h(is)g -(usually)g(necessary)g(to)h(recompile,)h(as)0 2108 y(w)m(ell)d(as)g -(relink,)g(the)f(programs)g(that)h(use)f(CFITSIO,)f(b)s(ecause)i(the)f -(de\014nitions)g(in)g(\014tsio.h)h(often)f(c)m(hange.)0 -2458 y Ff(2.4)135 b(Using)46 b(CFITSIO)e(in)h(Multi-threaded)g(En)l -(vironmen)l(ts)0 2711 y Fj(CFITSIO)d(can)h(b)s(e)g(used)f(either)i -(with)e(the)i(POSIX)e(pthreads)g(in)m(terface)j(or)e(the)h(Op)s(enMP)d -(in)m(terface)k(for)0 2824 y(m)m(ulti-threaded)g(parallel)g(programs.) -81 b(When)43 b(used)h(in)f(a)i(m)m(ulti-threaded)f(en)m(vironmen)m(t,)k -(the)c(CFITSIO)0 2937 y(library)26 b(*m)m(ust*)h(b)s(e)e(built)h(using) -g(the)g(-D)p 1426 2937 28 4 v 34 w(REENTRANT)f(compiler)i(directiv)m -(e.)41 b(This)25 b(can)i(b)s(e)e(done)h(using)g(the)0 -3050 y(follo)m(wing)32 b(build)d(commands:)95 3323 y -Fe(>./configure)45 b(--enable-reentrant)95 3436 y(>)j(make)0 -3709 y Fj(A)32 b(function)g(called)i(\014ts)p 845 3709 -V 32 w(is)p 938 3709 V 33 w(reen)m(tran)m(t)f(is)g(a)m(v)-5 -b(ailable)34 b(to)f(test)h(whether)d(or)i(not)f(CFITSIO)f(w)m(as)h -(compiled)h(with)0 3822 y(the)28 b(-D)p 258 3822 V 34 -w(REENTRANT)f(directiv)m(e.)42 b(When)28 b(this)g(feature)g(is)g -(enabled,)h(m)m(ultiple)g(threads)e(can)i(call)g(an)m(y)g(of)f(the)0 -3935 y(CFITSIO)k(routines)h(to)h(sim)m(ultaneously)g(read)f(or)h(write) -f(separate)h(FITS)f(\014les.)49 b(Multiple)34 b(threads)f(can)h(also)0 -4048 y(read)29 b(data)h(from)e(the)h(same)h(FITS)e(\014le)h(sim)m -(ultaneously)-8 b(,)31 b(as)e(long)h(as)f(the)g(\014le)g(w)m(as)h(op)s -(ened)e(indep)s(enden)m(tly)g(b)m(y)0 4161 y(eac)m(h)37 -b(thread.)58 b(This)35 b(relies)i(on)f(the)g(op)s(erating)h(system)f -(to)h(correctly)g(deal)g(with)f(reading)g(the)g(same)h(\014le)f(b)m(y)0 -4274 y(m)m(ultiple)30 b(pro)s(cesses.)41 b(Di\013eren)m(t)30 -b(threads)g(should)e(not)i(share)f(the)h(same)g('\014ts\014le')g(p)s -(oin)m(ter)f(to)i(read)e(an)h(op)s(ened)0 4386 y(FITS)40 -b(\014le,)j(unless)d(lo)s(c)m(ks)h(are)g(placed)f(around)g(the)g(calls) -i(to)f(the)g(CFITSIO)d(reading)j(routines.)71 b(Di\013eren)m(t)0 -4499 y(threads)30 b(should)f(nev)m(er)i(try)f(to)h(write)g(to)g(the)g -(same)f(FITS)g(\014le.)0 4849 y Ff(2.5)135 b(Getting)46 -b(Started)g(with)f(CFITSIO)0 5102 y Fj(In)27 b(order)h(to)g(e\013ectiv) -m(ely)j(use)d(the)g(CFITSIO)e(library)i(it)g(is)g(recommended)g(that)g -(new)f(users)h(b)s(egin)f(b)m(y)h(reading)0 5215 y(the)g(\\CFITSIO)g -(Quic)m(k)g(Start)g(Guide".)41 b(It)28 b(con)m(tains)h(all)h(the)e -(basic)h(information)f(needed)g(to)h(write)f(programs)0 -5328 y(that)c(p)s(erform)f(most)h(t)m(yp)s(es)g(of)g(op)s(erations)g -(on)g(FITS)f(\014les.)39 b(The)23 b(set)i(of)f(example)g(FITS)g(utilit) -m(y)h(programs)e(that)0 5441 y(are)29 b(a)m(v)-5 b(ailable)31 -b(from)d(the)g(CFITSIO)f(w)m(eb)i(site)g(are)g(also)g(v)m(ery)g(useful) -f(for)g(learning)h(ho)m(w)f(to)h(use)f(CFITSIO.)f(T)-8 -b(o)0 5554 y(learn)23 b(ev)m(en)g(more)g(ab)s(out)f(the)h(capabilities) -h(of)f(the)g(CFITSIO)e(library)h(the)h(follo)m(wing)h(steps)e(are)h -(recommended:)0 5714 y(1.)41 b(Read)31 b(the)f(follo)m(wing)i(short)e -(`FITS)g(Primer')g(c)m(hapter)h(for)f(an)h(o)m(v)m(erview)h(of)e(the)h -(structure)f(of)g(FITS)g(\014les.)p eop end -%%Page: 10 18 -TeXDict begin 10 17 bop 0 299 a Fj(10)1535 b Fh(CHAPTER)30 -b(2.)112 b(CREA)-8 b(TING)30 b(THE)g(CFITSIO)f(LIBRAR)-8 -b(Y)0 555 y Fj(2.)40 b(Review)28 b(the)f(Programming)g(Guidelines)h(in) -f(Chapter)f(4)i(to)g(b)s(ecome)f(familiar)h(with)f(the)h(con)m(v)m(en)m -(tions)h(used)0 668 y(b)m(y)h(the)h(CFITSIO)e(in)m(terface.)0 -828 y(3.)74 b(Refer)41 b(to)h(the)g(co)s(okb)s(o)s(ok.c,)j(listhead.c,) -h(and)40 b(\014tscop)m(y)-8 b(.c)43 b(programs)e(that)h(are)g(included) -e(with)h(this)h(re-)0 941 y(lease)g(for)e(examples)h(of)g(routines)f -(that)h(p)s(erform)e(v)-5 b(arious)41 b(common)g(FITS)f(\014le)g(op)s -(erations.)72 b(T)m(yp)s(e)40 b('mak)m(e)0 1054 y(program)p -339 1054 28 4 v 33 w(name')30 b(to)h(compile)h(and)d(link)i(these)g -(programs)f(on)g(Unix)g(systems.)0 1214 y(4.)40 b(W)-8 -b(rite)30 b(a)e(simple)g(program)g(to)g(read)g(or)g(write)g(a)h(FITS)e -(\014le)h(using)g(the)g(Basic)h(In)m(terface)g(routines)f(describ)s(ed) -0 1327 y(in)i(Chapter)g(5.)0 1487 y(5.)79 b(Scan)43 b(through)f(the)h -(more)g(sp)s(ecialized)i(routines)d(that)i(are)f(describ)s(ed)f(in)h -(the)g(follo)m(wing)i(c)m(hapters)e(to)0 1600 y(b)s(ecome)31 -b(familiar)g(with)f(the)h(functionalit)m(y)g(that)g(they)g(pro)m(vide.) -0 1964 y Ff(2.6)135 b(Example)46 b(Program)0 2220 y Fj(The)c(follo)m -(wing)j(listing)f(sho)m(ws)e(an)h(example)h(of)f(ho)m(w)g(to)g(use)g -(the)g(CFITSIO)f(routines)g(in)h(a)g(C)g(program.)0 2333 -y(Refer)26 b(to)g(the)g(co)s(okb)s(o)s(ok.c)g(program)f(that)i(is)e -(included)g(with)g(the)h(CFITSIO)e(distribution)h(for)g(other)h -(example)0 2446 y(routines.)0 2606 y(This)38 b(program)h(creates)h(a)f -(new)f(FITS)g(\014le,)k(con)m(taining)e(a)f(FITS)f(image.)68 -b(An)38 b(`EXPOSURE')h(k)m(eyw)m(ord)g(is)0 2719 y(written)27 -b(to)g(the)f(header,)i(then)e(the)h(image)g(data)h(are)f(written)f(to)h -(the)g(FITS)f(\014le)g(b)s(efore)h(closing)g(the)g(FITS)f(\014le.)0 -3004 y Fe(#include)46 b("fitsio.h")92 b(/*)47 b(required)f(by)h(every)g -(program)e(that)i(uses)g(CFITSIO)93 b(*/)0 3117 y(main\(\))0 -3230 y({)191 3343 y(fitsfile)45 b(*fptr;)333 b(/*)47 -b(pointer)f(to)h(the)g(FITS)g(file;)f(defined)g(in)h(fitsio.h)f(*/)191 -3456 y(int)h(status,)f(ii,)h(jj;)191 3569 y(long)94 b(fpixel)46 -b(=)i(1,)f(naxis)f(=)i(2,)f(nelements,)e(exposure;)191 -3681 y(long)i(naxes[2])e(=)j({)f(300,)g(200)g(};)142 -b(/*)47 b(image)g(is)g(300)g(pixels)f(wide)h(by)g(200)g(rows)f(*/)191 -3794 y(short)g(array[200][300];)191 4020 y(status)g(=)h(0;)429 -b(/*)48 b(initialize)d(status)h(before)g(calling)g(fitsio)g(routines)f -(*/)191 4133 y(fits_create_file\(&fptr,)c("testfile.fits",)j -(&status\);)140 b(/*)48 b(create)e(new)h(file)f(*/)191 -4359 y(/*)h(Create)f(the)h(primary)f(array)g(image)h(\(16-bit)e(short)i -(integer)f(pixels)g(*/)191 4472 y(fits_create_img\(fptr,)c(SHORT_IMG,)j -(naxis,)h(naxes,)g(&status\);)191 4698 y(/*)h(Write)f(a)i(keyword;)d -(must)i(pass)g(the)g(ADDRESS)e(of)j(the)f(value)f(*/)191 -4811 y(exposure)f(=)j(1500.;)191 4924 y(fits_update_key\(fptr,)42 -b(TLONG,)k("EXPOSURE",)f(&exposure,)430 5036 y("Total)h(Exposure)f -(Time",)h(&status\);)191 5262 y(/*)h(Initialize)e(the)i(values)f(in)h -(the)g(image)g(with)f(a)i(linear)e(ramp)g(function)g(*/)191 -5375 y(for)h(\(jj)g(=)g(0;)g(jj)h(<)f(naxes[1];)e(jj++\))382 -5488 y(for)i(\(ii)g(=)g(0;)g(ii)g(<)h(naxes[0];)d(ii++\))573 -5601 y(array[jj][ii])f(=)j(ii)h(+)f(jj;)p eop end -%%Page: 11 19 -TeXDict begin 11 18 bop 0 299 a Fh(2.6.)72 b(EXAMPLE)31 -b(PR)m(OGRAM)2618 b Fj(11)191 555 y Fe(nelements)45 b(=)j(naxes[0])d(*) -j(naxes[1];)474 b(/*)48 b(number)e(of)h(pixels)f(to)h(write)g(*/)191 -781 y(/*)g(Write)f(the)h(array)g(of)g(integers)e(to)j(the)f(image)f(*/) -191 894 y(fits_write_img\(fptr,)c(TSHORT,)k(fpixel,)g(nelements,)f -(array[0],)g(&status\);)191 1120 y(fits_close_file\(fptr,)d(&status\);) -570 b(/*)47 b(close)g(the)g(file)f(*/)191 1346 y -(fits_report_error\(stderr)o(,)c(status\);)93 b(/*)47 -b(print)g(out)g(any)f(error)h(messages)e(*/)191 1458 -y(return\()h(status)g(\);)0 1571 y(})p eop end -%%Page: 12 20 -TeXDict begin 12 19 bop 0 299 a Fj(12)1535 b Fh(CHAPTER)30 -b(2.)112 b(CREA)-8 b(TING)30 b(THE)g(CFITSIO)f(LIBRAR)-8 -b(Y)p eop end -%%Page: 13 21 -TeXDict begin 13 20 bop 0 1225 a Fg(Chapter)65 b(3)0 -1687 y Fm(A)78 b(FITS)f(Primer)0 2180 y Fj(This)36 b(section)h(giv)m -(es)h(a)f(brief)f(o)m(v)m(erview)i(of)e(the)h(structure)f(of)h(FITS)e -(\014les.)59 b(Users)36 b(should)g(refer)g(to)h(the)g(do)s(c-)0 -2293 y(umen)m(tation)i(a)m(v)-5 b(ailable)41 b(from)d(the)g(FITS)g -(Supp)s(ort)e(OF\014ce,)41 b(as)d(describ)s(ed)g(in)g(the)g(in)m(tro)s -(duction,)j(for)d(more)0 2406 y(detailed)31 b(information)g(on)f(FITS)g -(formats.)0 2566 y(FITS)e(w)m(as)h(\014rst)g(dev)m(elop)s(ed)g(in)f -(the)h(late)i(1970's)g(as)e(a)g(standard)f(data)i(in)m(terc)m(hange)g -(format)f(b)s(et)m(w)m(een)h(v)-5 b(arious)0 2679 y(astronomical)36 -b(observ)-5 b(atories.)52 b(Since)34 b(then)g(FITS)f(has)h(b)s(ecome)g -(the)h(standard)e(data)i(format)f(supp)s(orted)e(b)m(y)0 -2791 y(most)f(astronomical)h(data)f(analysis)g(soft)m(w)m(are)h(pac)m -(k)-5 b(ages.)0 2952 y(A)34 b(FITS)f(\014le)g(consists)h(of)g(one)g(or) -g(more)g(Header)g(+)f(Data)i(Units)f(\(HDUs\),)i(where)d(the)h(\014rst) -f(HDU)h(is)g(called)0 3065 y(the)j(`Primary)f(HDU',)i(or)f(`Primary)f -(Arra)m(y'.)60 b(The)36 b(primary)g(arra)m(y)h(con)m(tains)h(an)e -(N-dimensional)i(arra)m(y)f(of)0 3177 y(pixels,)30 b(suc)m(h)g(as)g(a)h -(1-D)g(sp)s(ectrum,)e(a)h(2-D)h(image,)h(or)e(a)g(3-D)i(data)e(cub)s -(e.)40 b(Six)30 b(di\013eren)m(t)g(primary)f(data)i(t)m(yp)s(es)0 -3290 y(are)j(supp)s(orted:)44 b(Unsigned)33 b(8-bit)h(b)m(ytes,)h -(16-bit,)g(32-bit,)h(and)c(64-bit)j(signed)e(in)m(tegers,)i(and)e(32)h -(and)f(64-bit)0 3403 y(\015oating)28 b(p)s(oin)m(t)e(reals.)40 -b(FITS)27 b(also)g(has)g(a)g(con)m(v)m(en)m(tion)i(for)d(storing)i(16)f -(and)f(32-bit)i(unsigned)e(in)m(tegers)i(\(see)g(the)0 -3516 y(later)k(section)h(en)m(titled)g(`Unsigned)e(In)m(tegers')h(for)f -(more)h(details\).)44 b(The)31 b(primary)g(HDU)h(ma)m(y)g(also)g -(consist)g(of)0 3629 y(only)e(a)h(header)f(with)h(a)f(n)m(ull)h(arra)m -(y)f(con)m(taining)i(no)f(data)g(pixels.)0 3789 y(An)m(y)i(n)m(um)m(b)s -(er)e(of)h(additional)i(HDUs)f(ma)m(y)g(follo)m(w)h(the)e(primary)g -(arra)m(y;)i(these)f(additional)h(HDUs)f(are)g(called)0 -3902 y(FITS)d(`extensions'.)41 b(There)30 b(are)h(curren)m(tly)f(3)h(t) -m(yp)s(es)g(of)f(extensions)h(de\014ned)e(b)m(y)h(the)h(FITS)f -(standard:)136 4171 y Fc(\017)46 b Fj(Image)31 b(Extension)g(-)g(a)f -(N-dimensional)h(arra)m(y)g(of)g(pixels,)g(lik)m(e)g(in)f(a)h(primary)e -(arra)m(y)136 4368 y Fc(\017)46 b Fj(ASCI)s(I)29 b(T)-8 -b(able)31 b(Extension)g(-)f(ro)m(ws)h(and)e(columns)h(of)h(data)g(in)f -(ASCI)s(I)f(c)m(haracter)j(format)136 4564 y Fc(\017)46 -b Fj(Binary)31 b(T)-8 b(able)31 b(Extension)f(-)h(ro)m(ws)f(and)g -(columns)g(of)h(data)g(in)f(binary)f(represen)m(tation)0 -4833 y(In)k(eac)m(h)i(case)g(the)f(HDU)h(consists)g(of)f(an)g(ASCI)s(I) -e(Header)i(Unit)h(follo)m(w)m(ed)g(b)m(y)f(an)g(optional)h(Data)g -(Unit.)52 b(F)-8 b(or)0 4946 y(historical)37 b(reasons,)g(eac)m(h)f -(Header)g(or)g(Data)h(unit)e(m)m(ust)g(b)s(e)g(an)g(exact)i(m)m -(ultiple)f(of)g(2880)h(8-bit)f(b)m(ytes)g(long.)0 5059 -y(An)m(y)30 b(un)m(used)g(space)g(is)h(padded)e(with)h(\014ll)g(c)m -(haracters)i(\(ASCI)s(I)d(blanks)h(or)h(zeros\).)0 5219 -y(Eac)m(h)i(Header)f(Unit)h(consists)g(of)f(an)m(y)g(n)m(um)m(b)s(er)f -(of)i(80-c)m(haracter)i(k)m(eyw)m(ord)d(records)g(or)g(`card)h(images') -g(whic)m(h)0 5332 y(ha)m(v)m(e)f(the)e(general)i(form:)95 -5601 y Fe(KEYNAME)46 b(=)i(value)e(/)i(comment)d(string)95 -5714 y(NULLKEY)h(=)334 b(/)48 b(comment:)d(This)i(keyword)f(has)g(no)i -(value)1905 5942 y Fj(13)p eop end -%%Page: 14 22 -TeXDict begin 14 21 bop 0 299 a Fj(14)2398 b Fh(CHAPTER)30 -b(3.)112 b(A)30 b(FITS)g(PRIMER)0 555 y Fj(The)35 b(k)m(eyw)m(ord)i -(names)f(ma)m(y)g(b)s(e)g(up)f(to)h(8)h(c)m(haracters)g(long)g(and)e -(can)h(only)h(con)m(tain)g(upp)s(ercase)e(letters,)k(the)0 -668 y(digits)25 b(0-9,)i(the)e(h)m(yphen,)g(and)f(the)h(underscore)e(c) -m(haracter.)41 b(The)24 b(k)m(eyw)m(ord)h(name)g(is)f(\(usually\))h -(follo)m(w)m(ed)i(b)m(y)d(an)0 781 y(equals)29 b(sign)g(and)f(a)g -(space)i(c)m(haracter)g(\(=)e(\))h(in)f(columns)h(9)g(-)f(10)i(of)f -(the)f(record,)h(follo)m(w)m(ed)i(b)m(y)d(the)h(v)-5 -b(alue)29 b(of)g(the)0 894 y(k)m(eyw)m(ord)34 b(whic)m(h)g(ma)m(y)g(b)s -(e)f(either)h(an)g(in)m(teger,)i(a)e(\015oating)g(p)s(oin)m(t)g(n)m(um) -m(b)s(er,)g(a)g(c)m(haracter)h(string)e(\(enclosed)i(in)0 -1007 y(single)28 b(quotes\),)i(or)e(a)g(b)s(o)s(olean)g(v)-5 -b(alue)28 b(\(the)g(letter)h(T)f(or)f(F\).)i(A)f(k)m(eyw)m(ord)g(ma)m -(y)h(also)f(ha)m(v)m(e)h(a)g(n)m(ull)e(or)h(unde\014ned)0 -1120 y(v)-5 b(alue)31 b(if)f(there)h(is)f(no)g(sp)s(eci\014ed)g(v)-5 -b(alue)31 b(string,)g(as)f(in)g(the)h(second)f(example,)i(ab)s(o)m(v)m -(e)0 1280 y(The)26 b(last)h(k)m(eyw)m(ord)g(in)g(the)f(header)h(is)f -(alw)m(a)m(ys)i(the)f(`END')g(k)m(eyw)m(ord)g(whic)m(h)g(has)f(no)g(v) --5 b(alue)27 b(or)g(commen)m(t)g(\014elds.)0 1393 y(There)k(are)g(man)m -(y)g(rules)g(go)m(v)m(erning)h(the)g(exact)g(format)g(of)f(a)g(k)m(eyw) -m(ord)h(record)f(\(see)h(the)f(FITS)f(Standard\))h(so)0 -1506 y(it)i(is)f(b)s(etter)h(to)g(rely)g(on)f(standard)f(in)m(terface)j -(soft)m(w)m(are)g(lik)m(e)g(CFITSIO)d(to)i(correctly)h(construct)f(or)f -(to)h(parse)0 1619 y(the)e(k)m(eyw)m(ord)f(records)h(rather)f(than)g -(try)g(to)h(deal)g(directly)g(with)f(the)h(ra)m(w)f(FITS)g(formats.)0 -1779 y(Eac)m(h)37 b(Header)g(Unit)f(b)s(egins)g(with)g(a)g(series)h(of) -f(required)g(k)m(eyw)m(ords)g(whic)m(h)g(dep)s(end)f(on)h(the)g(t)m(yp) -s(e)h(of)f(HDU.)0 1892 y(These)31 b(required)g(k)m(eyw)m(ords)h(sp)s -(ecify)g(the)f(size)i(and)e(format)h(of)g(the)g(follo)m(wing)h(Data)g -(Unit.)45 b(The)31 b(header)g(ma)m(y)0 2005 y(con)m(tain)h(other)f -(optional)g(k)m(eyw)m(ords)g(to)h(describ)s(e)e(other)g(asp)s(ects)h -(of)g(the)g(data,)g(suc)m(h)g(as)g(the)f(units)g(or)h(scaling)0 -2118 y(v)-5 b(alues.)44 b(Other)31 b(COMMENT)g(or)g(HISTOR)-8 -b(Y)30 b(k)m(eyw)m(ords)i(are)g(also)g(frequen)m(tly)g(added)e(to)i -(further)e(do)s(cumen)m(t)0 2230 y(the)h(data)g(\014le.)0 -2391 y(The)36 b(optional)h(Data)h(Unit)f(immediately)g(follo)m(ws)h -(the)e(last)h(2880-b)m(yte)i(blo)s(c)m(k)e(in)f(the)g(Header)h(Unit.)59 -b(Some)0 2503 y(HDUs)31 b(do)f(not)h(ha)m(v)m(e)g(a)g(Data)h(Unit)f -(and)f(only)g(consist)h(of)g(the)f(Header)h(Unit.)0 2664 -y(If)24 b(there)i(is)f(more)g(than)f(one)h(HDU)h(in)f(the)g(FITS)f -(\014le,)i(then)f(the)g(Header)h(Unit)f(of)g(the)g(next)g(HDU)h -(immediately)0 2777 y(follo)m(ws)g(the)e(last)i(2880-b)m(yte)h(blo)s(c) -m(k)e(of)g(the)f(previous)g(Data)j(Unit)d(\(or)h(Header)g(Unit)g(if)f -(there)h(is)g(no)f(Data)i(Unit\).)0 2937 y(The)k(main)g(required)g(k)m -(eyw)m(ords)g(in)g(FITS)g(primary)g(arra)m(ys)g(or)h(image)g -(extensions)g(are:)136 3172 y Fc(\017)46 b Fj(BITPIX)32 -b({)g(de\014nes)e(the)i(data)g(t)m(yp)s(e)g(of)g(the)g(arra)m(y:)43 -b(8,)33 b(16,)g(32,)g(64,)g(-32,)g(-64)g(for)e(unsigned)f(8{bit)j(b)m -(yte,)227 3284 y(16{bit)41 b(signed)f(in)m(teger,)j(32{bit)f(signed)d -(in)m(teger,)44 b(32{bit)d(IEEE)e(\015oating)h(p)s(oin)m(t,)i(and)e -(64{bit)h(IEEE)227 3397 y(double)30 b(precision)h(\015oating)g(p)s(oin) -m(t,)g(resp)s(ectiv)m(ely)-8 b(.)136 3585 y Fc(\017)46 -b Fj(NAXIS)30 b({)h(the)g(n)m(um)m(b)s(er)e(of)h(dimensions)g(in)g(the) -h(arra)m(y)-8 b(,)31 b(usually)f(0,)h(1,)g(2,)g(3,)g(or)g(4.)136 -3773 y Fc(\017)46 b Fj(NAXISn)30 b({)h(\(n)f(ranges)g(from)g(1)h(to)g -(NAXIS\))g(de\014nes)e(the)i(size)g(of)g(eac)m(h)g(dimension.)0 -4008 y(FITS)e(tables)i(start)g(with)f(the)g(k)m(eyw)m(ord)g(XTENSION)g -(=)f(`T)-8 b(ABLE')31 b(\(for)f(ASCI)s(I)f(tables\))i(or)f(XTENSION)f -(=)0 4120 y(`BINT)-8 b(ABLE')32 b(\(for)e(binary)g(tables\))h(and)f(ha) -m(v)m(e)i(the)e(follo)m(wing)i(main)e(k)m(eyw)m(ords:)136 -4355 y Fc(\017)46 b Fj(TFIELDS)30 b({)h(n)m(um)m(b)s(er)e(of)h -(\014elds)g(or)h(columns)f(in)g(the)g(table)136 4543 -y Fc(\017)46 b Fj(NAXIS2)31 b({)g(n)m(um)m(b)s(er)e(of)h(ro)m(ws)h(in)f -(the)g(table)136 4731 y Fc(\017)46 b Fj(TTYPEn)29 b({)i(for)f(eac)m(h)i -(column)e(\(n)g(ranges)h(from)f(1)g(to)h(TFIELDS\))g(giv)m(es)g(the)g -(name)f(of)h(the)f(column)136 4918 y Fc(\017)46 b Fj(TF)m(ORMn)31 -b({)f(the)h(data)g(t)m(yp)s(e)f(of)h(the)g(column)136 -5106 y Fc(\017)46 b Fj(TUNITn)30 b({)g(the)h(ph)m(ysical)g(units)f(of)g -(the)h(column)f(\(optional\))0 5341 y(Users)k(should)f(refer)h(to)h -(the)f(FITS)g(Supp)s(ort)e(O\016ce)i(at)h Fe(http://fits.gsfc.nasa.gov) -27 b Fj(for)34 b(further)f(infor-)0 5454 y(mation)e(ab)s(out)f(the)h -(FITS)e(format)i(and)f(related)h(soft)m(w)m(are)h(pac)m(k)-5 -b(ages.)p eop end -%%Page: 15 23 -TeXDict begin 15 22 bop 0 1225 a Fg(Chapter)65 b(4)0 -1687 y Fm(Programming)77 b(Guidelines)0 2216 y Ff(4.1)135 -b(CFITSIO)44 b(De\014nitions)0 2466 y Fj(An)m(y)30 b(program)g(that)h -(uses)f(the)h(CFITSIO)d(in)m(terface)k(m)m(ust)e(include)g(the)h -(\014tsio.h)f(header)g(\014le)h(with)f(the)g(state-)0 -2579 y(men)m(t)95 2818 y Fe(#include)46 b("fitsio.h")0 -3057 y Fj(This)30 b(header)h(\014le)h(con)m(tains)g(the)f(protot)m(yp)s -(es)h(for)f(all)h(the)f(CFITSIO)f(user)g(in)m(terface)j(routines)e(as)g -(w)m(ell)h(as)g(the)0 3170 y(de\014nitions)g(of)g(v)-5 -b(arious)32 b(constan)m(ts)h(used)e(in)h(the)h(in)m(terface.)47 -b(It)32 b(also)h(de\014nes)e(a)i(C)f(structure)f(of)h(t)m(yp)s(e)h -(`\014ts\014le')0 3283 y(that)j(is)g(used)f(b)m(y)g(CFITSIO)f(to)j -(store)f(the)g(relev)-5 b(an)m(t)37 b(parameters)f(that)g(de\014ne)f -(the)h(format)g(of)g(a)g(particular)0 3396 y(FITS)c(\014le.)48 -b(Application)34 b(programs)f(m)m(ust)g(de\014ne)f(a)h(p)s(oin)m(ter)g -(to)g(this)g(structure)g(for)f(eac)m(h)i(FITS)e(\014le)h(that)h(is)0 -3508 y(to)i(b)s(e)f(op)s(ened.)56 b(This)35 b(structure)g(is)h -(initialized)h(\(i.e.,)i(memory)c(is)h(allo)s(cated)h(for)f(the)g -(structure\))f(when)g(the)0 3621 y(FITS)h(\014le)g(is)h(\014rst)e(op)s -(ened)h(or)g(created)i(with)e(the)g(\014ts)p 1949 3621 -28 4 v 33 w(op)s(en)p 2172 3621 V 32 w(\014le)g(or)h(\014ts)p -2596 3621 V 32 w(create)p 2864 3621 V 34 w(\014le)g(routines.)59 -b(This)35 b(\014ts\014le)0 3734 y(p)s(oin)m(ter)c(is)h(then)f(passed)g -(as)g(the)h(\014rst)e(argumen)m(t)i(to)g(ev)m(ery)g(other)g(CFITSIO)d -(routine)j(that)g(op)s(erates)g(on)f(the)0 3847 y(FITS)h(\014le.)48 -b(Application)34 b(programs)f(m)m(ust)g(not)g(directly)g(read)g(or)g -(write)g(elemen)m(ts)h(in)f(this)g(\014ts\014le)f(structure)0 -3960 y(b)s(ecause)e(the)h(de\014nition)f(of)h(the)f(structure)g(ma)m(y) -h(c)m(hange)g(in)g(future)e(v)m(ersions)i(of)f(CFITSIO.)0 -4120 y(A)45 b(n)m(um)m(b)s(er)e(of)i(sym)m(b)s(olic)g(constan)m(ts)h -(are)f(also)g(de\014ned)f(in)g(\014tsio.h)h(for)f(the)h(con)m(v)m -(enience)i(of)e(application)0 4233 y(programmers.)55 -b(Use)35 b(of)h(these)f(sym)m(b)s(olic)h(constan)m(ts)g(rather)f(than)g -(the)h(actual)g(n)m(umeric)f(v)-5 b(alue)36 b(will)f(help)g(to)0 -4346 y(mak)m(e)c(the)g(source)f(co)s(de)h(more)g(readable)f(and)g -(easier)i(for)e(others)g(to)h(understand.)0 4585 y Fe(String)46 -b(Lengths,)g(for)h(use)f(when)h(allocating)e(character)g(arrays:)95 -4811 y(#define)h(FLEN_FILENAME)e(1025)j(/*)g(max)g(length)f(of)h(a)h -(filename)857 b(*/)95 4924 y(#define)46 b(FLEN_KEYWORD)140 -b(72)95 b(/*)47 b(max)g(length)f(of)h(a)h(keyword)905 -b(*/)95 5036 y(#define)46 b(FLEN_CARD)284 b(81)95 b(/*)47 -b(max)g(length)f(of)h(a)h(FITS)f(header)f(card)476 b(*/)95 -5149 y(#define)46 b(FLEN_VALUE)236 b(71)95 b(/*)47 b(max)g(length)f(of) -h(a)h(keyword)e(value)g(string)285 b(*/)95 5262 y(#define)46 -b(FLEN_COMMENT)140 b(73)95 b(/*)47 b(max)g(length)f(of)h(a)h(keyword)e -(comment)g(string)189 b(*/)95 5375 y(#define)46 b(FLEN_ERRMSG)188 -b(81)95 b(/*)47 b(max)g(length)f(of)h(a)h(CFITSIO)e(error)g(message)237 -b(*/)95 5488 y(#define)46 b(FLEN_STATUS)188 b(31)95 b(/*)47 -b(max)g(length)f(of)h(a)h(CFITSIO)e(status)g(text)g(string)h(*/)95 -5714 y(Note)g(that)g(FLEN_KEYWORD)d(is)j(longer)f(than)h(the)g(nominal) -f(8-character)f(keyword)1905 5942 y Fj(15)p eop end -%%Page: 16 24 -TeXDict begin 16 23 bop 0 299 a Fj(16)1763 b Fh(CHAPTER)29 -b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)95 555 y Fe(name)47 -b(length)f(because)g(the)h(HIERARCH)e(convention)g(supports)h(longer)g -(keyword)g(names.)0 781 y(Access)g(modes)g(when)h(opening)f(a)h(FITS)g -(file:)95 1007 y(#define)f(READONLY)94 b(0)95 1120 y(#define)46 -b(READWRITE)g(1)0 1346 y(BITPIX)g(data)h(type)f(code)h(values)f(for)h -(FITS)g(images:)95 1571 y(#define)f(BYTE_IMG)284 b(8)96 -b(/*)f(8-bit)46 b(unsigned)f(integers)h(*/)95 1684 y(#define)g -(SHORT_IMG)189 b(16)95 b(/*)47 b(16-bit)141 b(signed)46 -b(integers)g(*/)95 1797 y(#define)g(LONG_IMG)237 b(32)95 -b(/*)47 b(32-bit)141 b(signed)46 b(integers)g(*/)95 1910 -y(#define)g(LONGLONG_IMG)f(64)95 b(/*)47 b(64-bit)141 -b(signed)46 b(integers)g(*/)95 2023 y(#define)g(FLOAT_IMG)141 -b(-32)95 b(/*)47 b(32-bit)f(single)g(precision)f(floating)h(point)g(*/) -95 2136 y(#define)g(DOUBLE_IMG)93 b(-64)i(/*)47 b(64-bit)f(double)g -(precision)f(floating)h(point)g(*/)95 2362 y(The)h(following)f(4)h -(data)g(type)f(codes)h(are)g(also)f(supported)g(by)h(CFITSIO:)95 -2475 y(#define)f(SBYTE_IMG)93 b(10)143 b(/*)95 b(8-bit)46 -b(signed)g(integers,)g(equivalent)f(to)i(*/)1241 2588 -y(/*)95 b(BITPIX)46 b(=)h(8,)h(BSCALE)e(=)h(1,)g(BZERO)g(=)g(-128)g(*/) -95 2700 y(#define)f(USHORT_IMG)93 b(20)i(/*)47 b(16-bit)f(unsigned)g -(integers,)f(equivalent)g(to)i(*/)1241 2813 y(/*)95 b(BITPIX)46 -b(=)h(16,)g(BSCALE)f(=)i(1,)f(BZERO)f(=)i(32768)e(*/)95 -2926 y(#define)g(ULONG_IMG)141 b(40)95 b(/*)47 b(32-bit)f(unsigned)g -(integers,)f(equivalent)g(to)i(*/)1241 3039 y(/*)95 b(BITPIX)46 -b(=)h(32,)g(BSCALE)f(=)i(1,)f(BZERO)f(=)i(2147483648)d(*/)0 -3265 y(Codes)h(for)h(the)g(data)g(type)f(of)i(binary)e(table)g(columns) -g(and/or)g(for)h(the)0 3378 y(data)g(type)f(of)h(variables)f(when)g -(reading)g(or)h(writing)f(keywords)g(or)h(data:)1432 -3604 y(DATATYPE)714 b(TFORM)46 b(CODE)95 3717 y(#define)g(TBIT)476 -b(1)96 b(/*)1335 b('X')47 b(*/)95 3830 y(#define)f(TBYTE)381 -b(11)95 b(/*)47 b(8-bit)f(unsigned)g(byte,)332 b('B')47 -b(*/)95 3942 y(#define)f(TLOGICAL)237 b(14)95 b(/*)47 -b(logicals)e(\(int)i(for)g(keywords)236 b(*/)1289 4055 -y(/*)95 b(and)46 b(char)h(for)g(table)f(cols)142 b('L')47 -b(*/)95 4168 y(#define)f(TSTRING)285 b(16)95 b(/*)47 -b(ASCII)f(string,)666 b('A')47 b(*/)95 4281 y(#define)f(TSHORT)333 -b(21)95 b(/*)47 b(signed)f(short,)666 b('I')47 b(*/)95 -4394 y(#define)f(TLONG)381 b(41)95 b(/*)47 b(signed)f(long,)905 -b(*/)95 4507 y(#define)46 b(TLONGLONG)189 b(81)95 b(/*)47 -b(64-bit)f(long)h(signed)f(integer)f('K')i(*/)95 4620 -y(#define)f(TFLOAT)333 b(42)95 b(/*)47 b(single)f(precision)f(float,) -189 b('E')47 b(*/)95 4733 y(#define)f(TDOUBLE)285 b(82)95 -b(/*)47 b(double)f(precision)f(float,)189 b('D')47 b(*/)95 -4846 y(#define)f(TCOMPLEX)237 b(83)95 b(/*)47 b(complex)f(\(pair)g(of)h -(floats\))141 b('C')47 b(*/)95 4959 y(#define)f(TDBLCOMPLEX)f(163)95 -b(/*)47 b(double)f(complex)g(\(2)h(doubles\))e('M')i(*/)95 -5185 y(The)g(following)f(data)g(type)h(codes)f(are)h(also)g(supported)e -(by)i(CFITSIO:)95 5297 y(#define)f(TINT)429 b(31)95 b(/*)47 -b(int)1335 b(*/)95 5410 y(#define)46 b(TSBYTE)333 b(12)95 -b(/*)47 b(8-bit)f(signed)g(byte,)428 b('S')47 b(*/)95 -5523 y(#define)f(TUINT)381 b(30)95 b(/*)47 b(unsigned)e(int)715 -b('V')47 b(*/)95 5636 y(#define)f(TUSHORT)285 b(20)95 -b(/*)47 b(unsigned)e(short)619 b('U')95 b(*/)p eop end -%%Page: 17 25 -TeXDict begin 17 24 bop 0 299 a Fh(4.2.)72 b(CURRENT)30 -b(HEADER)h(D)m(A)-8 b(T)g(A)32 b(UNIT)e(\(CHDU\))1786 -b Fj(17)95 555 y Fe(#define)46 b(TULONG)333 b(40)95 b(/*)47 -b(unsigned)e(long)858 b(*/)95 781 y(The)47 b(following)f(data)g(type)h -(code)g(is)g(only)f(for)h(use)g(with)g(fits\\_get\\_coltype)95 -894 y(#define)f(TINT32BIT)189 b(41)95 b(/*)47 b(signed)f(32-bit)g(int,) -428 b('J')47 b(*/)0 1233 y(HDU)g(type)g(code)f(values)g(\(value)g -(returned)g(when)h(moving)f(to)h(new)g(HDU\):)95 1458 -y(#define)f(IMAGE_HDU)93 b(0)i(/*)48 b(Primary)d(Array)i(or)g(IMAGE)f -(HDU)h(*/)95 1571 y(#define)f(ASCII_TBL)93 b(1)i(/*)48 -b(ASCII)94 b(table)46 b(HDU)h(*/)95 1684 y(#define)f(BINARY_TBL)f(2)95 -b(/*)48 b(Binary)e(table)g(HDU)h(*/)95 1797 y(#define)f(ANY_HDU)142 -b(-1)94 b(/*)48 b(matches)d(any)i(type)g(of)g(HDU)g(*/)0 -2023 y(Column)f(name)h(and)g(string)f(matching)f(case-sensitivity:)95 -2249 y(#define)h(CASESEN)142 b(1)g(/*)48 b(do)f(case-sensitive)d -(string)i(match)g(*/)95 2362 y(#define)g(CASEINSEN)g(0)142 -b(/*)48 b(do)f(case-insensitive)c(string)j(match)h(*/)0 -2588 y(Logical)f(states)g(\(if)h(TRUE)f(and)h(FALSE)g(are)g(not)g -(already)e(defined\):)95 2813 y(#define)h(TRUE)h(1)95 -2926 y(#define)f(FALSE)h(0)0 3152 y(Values)f(to)h(represent)f -(undefined)f(floating)g(point)i(numbers:)95 3378 y(#define)f -(FLOATNULLVALUE)92 b(-9.11912E-36F)95 3491 y(#define)46 -b(DOUBLENULLVALUE)e(-9.1191291391491E-36)0 3717 y(Image)i(compression)f -(algorithm)g(definitions)95 3942 y(#define)h(RICE_1)333 -b(11)95 4055 y(#define)46 b(GZIP_1)333 b(21)95 4168 y(#define)46 -b(GZIP_2)333 b(22)95 4281 y(#define)46 b(PLIO_1)333 b(31)95 -4394 y(#define)46 b(HCOMPRESS_1)93 b(41)95 4507 y(#define)46 -b(NOCOMPRESS)93 b(-1)95 4733 y(#define)46 b(NO_DITHER)g(-1)95 -4846 y(#define)g(SUBTRACTIVE_DITHER_1)d(1)95 4959 y(#define)j -(SUBTRACTIVE_DITHER_2)d(2)0 5341 y Ff(4.2)135 b(Curren)l(t)46 -b(Header)f(Data)h(Unit)g(\(CHDU\))0 5601 y Fj(The)37 -b(concept)h(of)g(the)f(Curren)m(t)g(Header)g(and)g(Data)i(Unit,)h(or)d -(CHDU,)h(is)f(fundamen)m(tal)h(to)g(the)f(use)g(of)h(the)0 -5714 y(CFITSIO)31 b(library)-8 b(.)46 b(A)32 b(simple)h(FITS)e(image)j -(ma)m(y)f(only)f(con)m(tain)i(a)e(single)h(Header)g(and)f(Data)h(unit)f -(\(HDU\),)p eop end -%%Page: 18 26 -TeXDict begin 18 25 bop 0 299 a Fj(18)1763 b Fh(CHAPTER)29 -b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Fj(but)39 -b(in)g(general)i(FITS)e(\014les)h(can)g(con)m(tain)h(m)m(ultiple)g -(Header)f(Data)h(Units)f(\(also)h(kno)m(wn)e(as)h(`extensions'\),)0 -668 y(concatenated)c(one)f(after)f(the)h(other)f(in)g(the)g(\014le.)53 -b(The)33 b(user)h(can)g(sp)s(ecify)g(whic)m(h)g(HDU)h(should)e(b)s(e)g -(initially)0 781 y(op)s(ened)j(at)i(run)d(time)j(b)m(y)f(giving)h(the)f -(HDU)h(name)f(or)g(n)m(um)m(b)s(er)f(after)h(the)g(ro)s(ot)h(\014le)f -(name.)60 b(F)-8 b(or)38 b(example,)0 894 y('m)m(y\014le.\014ts[4]')i -(op)s(ens)d(the)h(5th)h(HDU)g(in)f(the)g(\014le)g(\(note)h(that)g(the)f -(n)m(um)m(b)s(ering)f(starts)i(with)f(0\),)j(and)c('m)m(y-)0 -1007 y(\014le.\014ts[EVENTS])k(op)s(ens)f(the)h(HDU)h(with)e(the)h -(name)g('EVENTS')g(\(as)g(de\014ned)f(b)m(y)h(the)g(EXTNAME)g(or)0 -1120 y(HDUNAME)35 b(k)m(eyw)m(ords\).)50 b(If)33 b(no)g(HDU)h(is)f(sp)s -(eci\014ed)g(then)g(CFITSIO)e(op)s(ens)i(the)g(\014rst)g(HDU)h(\(the)g -(primary)0 1233 y(arra)m(y\))24 b(b)m(y)e(default.)39 -b(The)22 b(CFITSIO)f(routines)i(whic)m(h)g(read)f(and)g(write)i(data)f -(only)g(op)s(erate)g(within)g(the)g(op)s(ened)0 1346 -y(HDU,)32 b(Other)e(CFITSIO)f(routines)i(are)g(pro)m(vided)f(to)i(mo)m -(v)m(e)g(to)f(and)f(op)s(en)g(an)m(y)h(other)g(existing)h(HDU)f(within) -0 1458 y(the)g(FITS)e(\014le)i(or)f(to)h(app)s(end)e(or)h(insert)g(new) -g(HDUs)h(in)f(the)h(FITS)f(\014le.)0 1836 y Ff(4.3)135 -b(F)-11 b(unction)44 b(Names)i(and)f(V)-11 b(ariable)46 -b(Datat)l(yp)t(es)0 2095 y Fj(Most)33 b(of)f(the)g(CFITSIO)f(routines)h -(ha)m(v)m(e)h(b)s(oth)e(a)i(short)e(name)h(as)h(w)m(ell)g(as)f(a)g -(longer)h(descriptiv)m(e)g(name.)45 b(The)0 2208 y(short)32 -b(name)g(is)g(only)g(5)h(or)f(6)g(c)m(haracters)h(long)g(and)f(is)g -(similar)g(to)h(the)f(subroutine)f(name)h(in)g(the)g(F)-8 -b(ortran-77)0 2321 y(v)m(ersion)38 b(of)g(FITSIO.)f(The)h(longer)g -(name)g(is)g(more)g(descriptiv)m(e)h(and)e(it)h(is)g(recommended)g -(that)g(it)h(b)s(e)e(used)0 2434 y(instead)31 b(of)f(the)h(short)f -(name)g(to)h(more)g(clearly)h(do)s(cumen)m(t)e(the)g(source)h(co)s(de.) -0 2594 y(Man)m(y)c(of)f(the)g(CFITSIO)f(routines)h(come)h(in)e -(families)i(whic)m(h)f(di\013er)g(only)g(in)g(the)g(data)h(t)m(yp)s(e)f -(of)g(the)g(asso)s(ciated)0 2707 y(parameter\(s\).)45 -b(The)31 b(data)h(t)m(yp)s(e)g(of)g(these)g(routines)f(is)h(indicated)g -(b)m(y)f(the)h(su\016x)e(of)i(the)g(routine)f(name.)44 -b(The)0 2820 y(short)27 b(routine)h(names)g(ha)m(v)m(e)h(a)f(1)g(or)f -(2)h(c)m(haracter)i(su\016x)c(\(e.g.,)31 b('j')c(in)h('\013pkyj'\))g -(while)f(the)h(long)g(routine)g(names)0 2933 y(ha)m(v)m(e)k(a)e(4)h(c)m -(haracter)h(or)e(longer)h(su\016x)f(as)g(sho)m(wn)g(in)g(the)h(follo)m -(wing)h(table:)191 3230 y Fe(Long)285 b(Short)94 b(Data)191 -3343 y(Names)237 b(Names)94 b(Type)191 3456 y(-----)237 -b(-----)94 b(----)191 3569 y(_bit)381 b(x)190 b(bit)191 -3681 y(_byt)381 b(b)190 b(unsigned)46 b(byte)191 3794 -y(_sbyt)333 b(sb)142 b(signed)46 b(byte)191 3907 y(_sht)381 -b(i)190 b(short)47 b(integer)191 4020 y(_lng)381 b(j)190 -b(long)47 b(integer)191 4133 y(_lnglng)237 b(jj)142 b(8-byte)46 -b(LONGLONG)g(integer)g(\(see)g(note)h(below\))191 4246 -y(_usht)333 b(ui)142 b(unsigned)46 b(short)g(integer)191 -4359 y(_ulng)333 b(uj)142 b(unsigned)46 b(long)g(integer)191 -4472 y(_uint)333 b(uk)142 b(unsigned)46 b(int)h(integer)191 -4585 y(_int)381 b(k)190 b(int)47 b(integer)191 4698 y(_flt)381 -b(e)190 b(real)47 b(exponential)e(floating)g(point)i(\(float\))191 -4811 y(_fixflt)237 b(f)190 b(real)47 b(fixed-decimal)d(format)i -(floating)g(point)g(\(float\))191 4924 y(_dbl)381 b(d)190 -b(double)46 b(precision)g(real)g(floating-point)e(\(double\))191 -5036 y(_fixdbl)237 b(g)190 b(double)46 b(precision)g(fixed-format)e -(floating)i(point)g(\(double\))191 5149 y(_cmp)381 b(c)190 -b(complex)46 b(reals)g(\(pairs)h(of)g(float)f(values\))191 -5262 y(_fixcmp)237 b(fc)142 b(complex)46 b(reals,)g(fixed-format)f -(floating)g(point)191 5375 y(_dblcmp)237 b(m)190 b(double)46 -b(precision)g(complex)f(\(pairs)i(of)g(double)f(values\))191 -5488 y(_fixdblcmp)93 b(fm)142 b(double)46 b(precision)g(complex,)f -(fixed-format)g(floating)g(point)191 5601 y(_log)381 -b(l)190 b(logical)46 b(\(int\))191 5714 y(_str)381 b(s)190 -b(character)46 b(string)p eop end -%%Page: 19 27 -TeXDict begin 19 26 bop 0 299 a Fh(4.3.)72 b(FUNCTION)30 -b(NAMES)h(AND)g(V)-10 b(ARIABLE)30 b(D)m(A)-8 b(T)g(A)g(TYPES)1409 -b Fj(19)0 555 y(The)32 b(logical)j(data)f(t)m(yp)s(e)f(corresp)s(onds)e -(to)j(`in)m(t')f(for)g(logical)i(k)m(eyw)m(ord)e(v)-5 -b(alues,)34 b(and)e(`b)m(yte')i(for)f(logical)i(binary)0 -668 y(table)40 b(columns.)67 b(In)39 b(other)g(w)m(ords,)i(the)f(v)-5 -b(alue)39 b(when)g(writing)g(a)h(logical)h(k)m(eyw)m(ord)f(m)m(ust)f(b) -s(e)g(stored)g(in)g(an)0 781 y(`in)m(t')g(v)-5 b(ariable,)40 -b(and)e(m)m(ust)f(b)s(e)g(stored)h(in)g(a)g(`c)m(har')h(arra)m(y)f -(when)f(reading)h(or)f(writing)h(to)h(`L')f(columns)f(in)h(a)0 -894 y(binary)c(table.)56 b(Implicit)35 b(data)h(t)m(yp)s(e)f(con)m(v)m -(ersion)i(is)e(not)g(supp)s(orted)e(for)i(logical)j(table)e(columns,)g -(but)e(is)h(for)0 1007 y(k)m(eyw)m(ords,)30 b(so)f(a)h(logical)h(k)m -(eyw)m(ord)f(ma)m(y)f(b)s(e)g(read)f(and)h(cast)h(to)g(an)m(y)f(n)m -(umerical)h(data)f(t)m(yp)s(e;)h(a)g(returned)d(v)-5 -b(alue)0 1120 y(=)30 b(0)h(indicates)g(false,)g(and)f(an)m(y)h(other)f -(v)-5 b(alue)31 b(=)f(true.)0 1280 y(The)24 b(`in)m(t')i(data)g(t)m(yp) -s(e)f(ma)m(y)h(b)s(e)e(2)h(b)m(ytes)h(long)f(on)g(some)g(old)g(PC)g -(compilers,)h(but)f(otherwise)g(it)g(is)g(nearly)g(alw)m(a)m(ys)0 -1393 y(4)i(b)m(ytes)g(long.)40 b(Some)27 b(64-bit)h(mac)m(hines,)g(lik) -m(e)g(the)f(Alpha/OSF,)g(de\014ne)f(the)h(`short',)h(`in)m(t',)h(and)d -(`long')i(in)m(teger)0 1506 y(data)j(t)m(yp)s(es)f(to)i(b)s(e)d(2,)i -(4,)g(and)f(8)h(b)m(ytes)g(long,)g(resp)s(ectiv)m(ely)-8 -b(.)0 1666 y(Because)40 b(there)e(is)h(no)f(univ)m(ersal)h(C)f -(compiler)g(standard)g(for)g(the)h(name)f(of)h(the)f(8-b)m(yte)i(in)m -(teger)g(datat)m(yp)s(e,)0 1779 y(the)33 b(\014tsio.h)h(include)f -(\014le)g(t)m(yp)s(edef)7 b('s)33 b('LONGLONG')h(to)g(b)s(e)e(equiv)-5 -b(alen)m(t)35 b(to)f(an)f(appropriate)g(8-b)m(yte)i(in)m(teger)0 -1892 y(data)c(t)m(yp)s(e)g(on)f(eac)m(h)i(supp)s(orted)d(platform.)41 -b(F)-8 b(or)31 b(maxim)m(um)f(soft)m(w)m(are)i(p)s(ortabilit)m(y)g(it)f -(is)f(recommended)g(that)0 2005 y(this)g(LONGLONG)g(datat)m(yp)s(e)h(b) -s(e)e(used)g(to)i(de\014ne)e(8-b)m(yte)i(in)m(teger)h(v)-5 -b(ariables)30 b(rather)g(than)g(using)f(the)i(nativ)m(e)0 -2118 y(data)h(t)m(yp)s(e)g(name)f(on)h(a)f(particular)h(platform.)44 -b(On)31 b(most)h(32-bit)g(Unix)g(and)e(Mac)j(OS-X)e(op)s(erating)h -(systems)0 2230 y(LONGLONG)h(is)f(equiv)-5 b(alen)m(t)34 -b(to)f(the)g(in)m(trinsic)g('long)g(long')h(8-b)m(yte)g(in)m(teger)f -(datat)m(yp)s(e.)49 b(On)31 b(64-bit)j(systems)0 2343 -y(\(whic)m(h)e(curren)m(tly)g(includes)f(Alpha)h(OSF/1,)g(64-bit)h(Sun) -e(Solaris,)h(64-bit)h(SGI)f(MIPS,)f(and)g(64-bit)i(Itanium)0 -2456 y(and)28 b(Opteron)g(PC)h(systems\),)g(LONGLONG)g(is)g(simply)f(t) -m(yp)s(edef)7 b('ed)29 b(to)g(b)s(e)g(equiv)-5 b(alen)m(t)30 -b(to)f('long'.)42 b(Microsoft)0 2569 y(Visual)33 b(C++)e(V)-8 -b(ersion)33 b(6.0)g(do)s(es)f(not)g(de\014ne)g(a)h('long)g(long')g -(data)g(t)m(yp)s(e,)g(so)f(LONGLONG)h(is)f(t)m(yp)s(edef)7 -b('ed)32 b(to)0 2682 y(b)s(e)e(equiv)-5 b(alen)m(t)32 -b(to)f(the)f(')p 853 2682 28 4 v 887 2682 V 66 w(in)m(t64')i(data)f(t)m -(yp)s(e)g(on)f(32-bit)h(windo)m(ws)f(systems)h(when)e(using)h(Visual)h -(C++.)0 2842 y(A)j(related)h(issue)e(that)i(a\013ects)g(the)f(p)s -(ortabilit)m(y)g(of)g(soft)m(w)m(are)i(is)d(ho)m(w)h(to)h(prin)m(t)e -(out)h(the)g(v)-5 b(alue)34 b(of)g(a)g('LONG-)0 2955 -y(LONG')e(v)-5 b(ariable)32 b(with)f(prin)m(tf.)44 b(Dev)m(elop)s(ers) -33 b(ma)m(y)f(\014nd)e(it)i(con)m(v)m(enien)m(t)h(to)g(use)e(the)h -(follo)m(wing)h(prepro)s(cessing)0 3068 y(statemen)m(ts)f(in)e(their)h -(C)f(programs)g(to)h(handle)f(this)g(in)g(a)h(mac)m(hine-p)s(ortable)g -(manner:)0 3310 y Fe(#if)47 b(defined\(_MSC_VER\))c(/*)k(Microsoft)e -(Visual)i(C++)f(*/)477 3423 y(printf\("\045I64d",)e(longlongvalue\);)0 -3649 y(#elif)i(\(USE_LL_SUFFIX)e(==)j(1\))477 3762 y -(printf\("\045lld",)d(longlongvalue\);)0 3988 y(#else)477 -4101 y(printf\("\045ld",)g(longlongvalue\);)0 4213 y(#endif)0 -4456 y Fj(Similarly)-8 b(,)32 b(the)f(name)g(of)g(the)h(C)e(utilit)m(y) -j(routine)e(that)g(con)m(v)m(erts)i(a)e(c)m(haracter)i(string)d(of)i -(digits)f(in)m(to)h(a)g(8-b)m(yte)0 4568 y(in)m(teger)g(v)-5 -b(alue)31 b(is)f(platform)g(dep)s(enden)m(t:)0 4811 y -Fe(#if)47 b(defined\(_MSC_VER\))c(/*)k(Microsoft)e(Visual)i(C++)f(*/) -286 4924 y(/*)i(VC++)e(6.0)h(does)g(not)g(seem)f(to)h(have)g(an)g -(8-byte)f(conversion)f(routine)h(*/)0 5149 y(#elif)g(\(USE_LL_SUFFIX)e -(==)j(1\))477 5262 y(longlongvalue)d(=)k(atoll\(*string\);)0 -5488 y(#else)477 5601 y(longlongvalue)c(=)k(atol\(*string\);)0 -5714 y(#endif)p eop end -%%Page: 20 28 -TeXDict begin 20 27 bop 0 299 a Fj(20)1763 b Fh(CHAPTER)29 -b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Fj(When)23 -b(dealing)h(with)f(the)h(FITS)f(b)m(yte)h(data)g(t)m(yp)s(e)f(it)h(is)g -(imp)s(ortan)m(t)f(to)h(remem)m(b)s(er)f(that)h(the)g(ra)m(w)f(v)-5 -b(alues)24 b(\(b)s(efore)0 668 y(an)m(y)h(scaling)g(b)m(y)f(the)h -(BSCALE)e(and)h(BZER)m(O,)g(or)h(TSCALn)d(and)i(TZER)m(On)f(k)m(eyw)m -(ord)i(v)-5 b(alues\))25 b(in)f(b)m(yte)h(arra)m(ys)0 -781 y(\(BITPIX)37 b(=)f(8\))h(or)f(b)m(yte)i(columns)e(\(TF)m(ORMn)h(=) -f('B'\))h(are)g(in)m(terpreted)g(as)g(unsigned)e(b)m(ytes)i(with)g(v)-5 -b(alues)0 894 y(ranging)34 b(from)g(0)g(to)h(255.)53 -b(Some)34 b(C)g(compilers)h(de\014ne)e(a)h('c)m(har')h(v)-5 -b(ariable)35 b(as)g(signed,)g(so)f(it)h(is)f(imp)s(ortan)m(t)g(to)0 -1007 y(explicitly)e(declare)f(a)g(n)m(umeric)f(c)m(har)h(v)-5 -b(ariable)31 b(as)g('unsigned)e(c)m(har')i(to)g(a)m(v)m(oid)h(an)m(y)f -(am)m(biguit)m(y)0 1167 y(One)22 b(feature)h(of)g(the)g(CFITSIO)e -(routines)i(is)f(that)i(they)f(can)g(op)s(erate)g(on)f(a)h(`X')h -(\(bit\))f(column)g(in)f(a)h(binary)f(table)0 1280 y(as)33 -b(though)f(it)h(w)m(ere)g(a)g(`B')g(\(b)m(yte\))h(column.)47 -b(F)-8 b(or)33 b(example)g(a)g(`11X')h(data)f(t)m(yp)s(e)g(column)f -(can)h(b)s(e)f(in)m(terpreted)0 1393 y(the)c(same)h(as)f(a)g(`2B')i -(column)e(\(i.e.,)i(2)e(unsigned)f(8-bit)i(b)m(ytes\).)41 -b(In)27 b(some)i(instances,)g(it)f(can)h(b)s(e)e(more)h(e\016cien)m(t)0 -1506 y(to)j(read)f(and)g(write)h(whole)f(b)m(ytes)h(at)g(a)g(time,)g -(rather)g(than)f(reading)g(or)h(writing)f(eac)m(h)i(individual)d(bit.)0 -1666 y(The)36 b(complex)i(and)e(double)h(precision)g(complex)h(data)g -(t)m(yp)s(es)f(are)g(not)g(directly)h(supp)s(orted)d(in)i(ANSI)f(C)h -(so)0 1779 y(these)g(data)g(t)m(yp)s(es)f(should)f(b)s(e)h(in)m -(terpreted)h(as)f(pairs)g(of)h(\015oat)g(or)f(double)g(v)-5 -b(alues,)38 b(resp)s(ectiv)m(ely)-8 b(,)40 b(where)c(the)0 -1892 y(\014rst)30 b(v)-5 b(alue)30 b(in)h(eac)m(h)g(pair)f(is)h(the)f -(real)h(part,)g(and)e(the)i(second)f(is)h(the)f(imaginary)h(part.)0 -2225 y Ff(4.4)135 b(Supp)t(ort)44 b(for)h(Unsigned)h(In)l(tegers)g(and) -f(Signed)g(Bytes)0 2475 y Fj(Although)33 b(FITS)f(do)s(es)g(not)h -(directly)h(supp)s(ort)d(unsigned)g(in)m(tegers)j(as)f(one)g(of)g(its)h -(fundamen)m(tal)e(data)i(t)m(yp)s(es,)0 2588 y(FITS)27 -b(can)h(still)h(b)s(e)e(used)g(to)i(e\016cien)m(tly)h(store)e(unsigned) -f(in)m(teger)i(data)g(v)-5 b(alues)28 b(in)g(images)h(and)e(binary)g -(tables.)0 2701 y(The)42 b(con)m(v)m(en)m(tion)j(used)d(in)g(FITS)g -(\014les)h(is)f(to)i(store)f(the)g(unsigned)e(in)m(tegers)j(as)f -(signed)g(in)m(tegers)h(with)e(an)0 2814 y(asso)s(ciated)34 -b(o\013set)f(\(sp)s(eci\014ed)f(b)m(y)g(the)g(BZER)m(O)g(or)g(TZER)m -(On)f(k)m(eyw)m(ord\).)47 b(F)-8 b(or)33 b(example,)g(to)g(store)g -(unsigned)0 2927 y(16-bit)g(in)m(teger)g(v)-5 b(alues)32 -b(in)f(a)h(FITS)f(image)i(the)e(image)i(w)m(ould)f(b)s(e)e(de\014ned)h -(as)h(a)g(signed)f(16-bit)i(in)m(teger)g(\(with)0 3040 -y(BITPIX)c(k)m(eyw)m(ord)g(=)g(SHOR)-8 b(T)p 1132 3040 -28 4 v 32 w(IMG)30 b(=)e(16\))j(with)d(the)i(k)m(eyw)m(ords)f(BSCALE)f -(=)h(1.0)h(and)f(BZER)m(O)g(=)f(32768.)0 3152 y(Th)m(us)34 -b(the)h(unsigned)f(v)-5 b(alues)35 b(of)g(0,)i(32768,)h(and)d(65535,)j -(for)d(example,)i(are)e(ph)m(ysically)h(stored)f(in)g(the)g(FITS)0 -3265 y(image)40 b(as)e(-32768,)43 b(0,)e(and)d(32767,)k(resp)s(ectiv)m -(ely;)i(CFITSIO)37 b(automatically)k(adds)c(the)i(BZER)m(O)f(o\013set)h -(to)0 3378 y(these)g(v)-5 b(alues)39 b(when)f(they)g(are)h(read.)65 -b(Similarly)-8 b(,)42 b(in)c(the)h(case)h(of)e(unsigned)g(32-bit)i(in)m -(tegers)f(the)g(BITPIX)0 3491 y(k)m(eyw)m(ord)c(w)m(ould)f(b)s(e)g -(equal)h(to)h(LONG)p 1392 3491 V 32 w(IMG)f(=)g(32)g(and)f(BZER)m(O)g -(w)m(ould)h(b)s(e)f(equal)h(to)g(2147483648)k(\(i.e.)55 -b(2)0 3604 y(raised)30 b(to)h(the)g(31st)g(p)s(o)m(w)m(er\).)0 -3764 y(The)j(CFITSIO)g(in)m(terface)i(routines)f(will)g(e\016cien)m -(tly)i(and)d(transparen)m(tly)i(apply)e(the)h(appropriate)g(o\013set)h -(in)0 3877 y(these)29 b(cases)h(so)f(in)g(general)h(application)g -(programs)f(do)g(not)g(need)f(to)i(b)s(e)e(concerned)h(with)g(ho)m(w)g -(the)g(unsigned)0 3990 y(v)-5 b(alues)44 b(are)h(actually)h(stored)e -(in)f(the)i(FITS)e(\014le.)82 b(As)44 b(a)g(con)m(v)m(enience)j(for)c -(users,)k(CFITSIO)c(has)h(sev)m(eral)0 4103 y(prede\014ned)19 -b(constan)m(ts)j(for)f(the)g(v)-5 b(alue)21 b(of)g(BITPIX)g(\(USHOR)-8 -b(T)p 2189 4103 V 33 w(IMG,)21 b(ULONG)p 2790 4103 V -33 w(IMG\))h(and)e(for)h(the)g(TF)m(ORMn)0 4216 y(v)-5 -b(alue)36 b(in)f(the)h(case)g(of)g(binary)f(tables)h(\(`U')h(and)e -(`V'\))h(whic)m(h)f(programmers)g(can)h(use)f(when)g(creating)i(FITS)0 -4329 y(\014les)i(con)m(taining)h(unsigned)e(in)m(teger)i(v)-5 -b(alues.)66 b(The)39 b(follo)m(wing)h(co)s(de)f(fragmen)m(t)g -(illustrates)h(ho)m(w)f(to)h(write)f(a)0 4442 y(FITS)30 -b(1-D)h(primary)f(arra)m(y)g(of)h(unsigned)e(16-bit)j(in)m(tegers:)286 -4698 y Fe(unsigned)46 b(short)g(uarray[100];)286 4811 -y(int)h(naxis,)f(status;)286 4924 y(long)h(naxes[10],)e(group,)h -(firstelem,)f(nelements;)334 5036 y(...)286 5149 y(status)h(=)i(0;)286 -5262 y(naxis)f(=)g(1;)286 5375 y(naxes[0])f(=)h(100;)286 -5488 y(fits_create_img\(fptr,)42 b(USHORT_IMG,)j(naxis,)h(naxes,)g -(&status\);)286 5714 y(firstelem)g(=)h(1;)p eop end -%%Page: 21 29 -TeXDict begin 21 28 bop 0 299 a Fh(4.4.)72 b(SUPPOR)-8 -b(T)30 b(F)m(OR)g(UNSIGNED)h(INTEGERS)f(AND)h(SIGNED)f(BYTES)942 -b Fj(21)286 555 y Fe(nelements)46 b(=)h(100;)286 668 -y(fits_write_img\(fptr,)c(TUSHORT,)i(firstelem,)g(nelements,)1241 -781 y(uarray,)h(&status\);)334 894 y(...)0 1135 y Fj(In)40 -b(the)h(ab)s(o)m(v)m(e)i(example,)h(the)e(2nd)e(parameter)h(in)g -(\014ts)p 1998 1135 28 4 v 33 w(create)p 2267 1135 V -34 w(img)g(tells)h(CFITSIO)e(to)i(write)f(the)g(header)0 -1248 y(k)m(eyw)m(ords)34 b(appropriate)g(for)f(an)g(arra)m(y)i(of)e -(16-bit)i(unsigned)e(in)m(tegers)i(\(i.e.,)h(BITPIX)d(=)g(16)i(and)e -(BZER)m(O)g(=)0 1361 y(32768\).)41 b(Then)23 b(the)h(\014ts)p -834 1361 V 32 w(write)p 1068 1361 V 33 w(img)h(routine)f(writes)f(the)i -(arra)m(y)f(of)g(unsigned)f(short)g(in)m(tegers)i(\(uarra)m(y\))g(in)m -(to)g(the)0 1474 y(primary)f(arra)m(y)h(of)g(the)g(FITS)f(\014le.)39 -b(Similarly)-8 b(,)27 b(a)e(32-bit)i(unsigned)c(in)m(teger)j(image)h -(ma)m(y)e(b)s(e)f(created)i(b)m(y)f(setting)0 1587 y(the)34 -b(second)f(parameter)h(in)f(\014ts)p 1130 1587 V 33 w(create)p -1399 1587 V 34 w(img)h(equal)g(to)g(`ULONG)p 2330 1587 -V 33 w(IMG')g(and)f(b)m(y)h(calling)g(the)g(\014ts)p -3491 1587 V 33 w(write)p 3726 1587 V 33 w(img)0 1700 -y(routine)j(with)f(the)h(second)f(parameter)h(=)f(TULONG)h(to)g(write)g -(the)f(arra)m(y)h(of)g(unsigned)f(long)h(image)h(pixel)0 -1812 y(v)-5 b(alues.)0 1973 y(An)27 b(analogous)h(set)f(of)g(routines)g -(are)g(a)m(v)-5 b(ailable)30 b(for)c(reading)h(or)g(writing)g(unsigned) -f(in)m(teger)i(v)-5 b(alues)28 b(and)e(signed)0 2086 -y(b)m(yte)i(v)-5 b(alues)28 b(in)g(a)g(FITS)f(binary)g(table)i -(extension.)40 b(When)28 b(sp)s(ecifying)f(the)h(TF)m(ORMn)g(k)m(eyw)m -(ord)g(v)-5 b(alue)28 b(whic)m(h)0 2198 y(de\014nes)36 -b(the)h(format)g(of)g(a)h(column,)g(CFITSIO)d(recognized)k(3)e -(additional)h(data)f(t)m(yp)s(e)g(co)s(des)g(b)s(esides)f(those)0 -2311 y(already)30 b(de\014ned)f(in)g(the)h(FITS)f(standard:)40 -b(`U')30 b(meaning)g(a)g(16-bit)h(unsigned)e(in)m(teger)i(column,)f -(`V')g(for)g(a)g(32-)0 2424 y(bit)c(unsigned)e(in)m(teger)j(column,)g -(and)e('S')g(for)g(a)h(signed)g(b)m(yte)g(column.)39 -b(These)25 b(non-standard)g(data)h(t)m(yp)s(e)g(co)s(des)0 -2537 y(are)36 b(not)g(actually)i(written)e(in)m(to)g(the)g(FITS)g -(\014le)f(but)h(instead)g(are)g(just)f(used)g(in)m(ternally)i(within)e -(CFITSIO.)0 2650 y(The)30 b(follo)m(wing)i(co)s(de)e(fragmen)m(t)h -(illustrates)h(ho)m(w)e(to)h(use)f(these)h(features:)286 -2891 y Fe(unsigned)46 b(short)g(uarray[100];)286 3004 -y(unsigned)g(int)95 b(varray[100];)286 3230 y(int)47 -b(colnum,)f(tfields,)g(status;)286 3343 y(long)h(nrows,)f(firstrow,)f -(firstelem,)g(nelements,)g(pcount;)286 3569 y(char)i(extname[])e(=)j -("Test_table";)521 b(/*)47 b(extension)f(name)g(*/)286 -3794 y(/*)i(define)e(the)h(name,)f(data)h(type,)f(and)h(physical)e -(units)i(for)g(the)g(2)g(columns)f(*/)286 3907 y(char)h(*ttype[])f(=)h -({)g("Col_1",)f("Col_2",)g("Col_3")f(};)286 4020 y(char)i(*tform[])f(=) -h({)g("1U",)285 b("1V",)190 b("1S"};)94 b(/*)47 b(special)f(CFITSIO)g -(codes)g(*/)286 4133 y(char)h(*tunit[])f(=)h({)g(")h(",)381 -b(")48 b(",)190 b(")47 b(")h(};)334 4246 y(...)525 4472 -y(/*)f(write)g(the)f(header)h(keywords)e(*/)286 4585 -y(status)94 b(=)48 b(0;)286 4698 y(nrows)142 b(=)48 b(1;)286 -4811 y(tfields)e(=)i(3)286 4924 y(pcount)94 b(=)48 b(0;)286 -5036 y(fits_create_tbl\(fptr,)42 b(BINARY_TBL,)j(nrows,)h(tfields,)g -(ttype,)g(tform,)764 5149 y(tunit,)g(extname,)f(&status\);)525 -5375 y(/*)i(write)g(the)f(unsigned)g(shorts)g(to)h(the)g(1st)g(column)f -(*/)286 5488 y(colnum)190 b(=)47 b(1;)286 5601 y(firstrow)94 -b(=)47 b(1;)286 5714 y(firstelem)f(=)h(1;)p eop end -%%Page: 22 30 -TeXDict begin 22 29 bop 0 299 a Fj(22)1763 b Fh(CHAPTER)29 -b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)286 555 y Fe(nelements)46 -b(=)h(100;)286 668 y(fits_write_col\(fptr,)c(TUSHORT,)i(colnum,)h -(firstrow,)f(firstelem,)668 781 y(nelements,)g(uarray,)h(&status\);)525 -1007 y(/*)h(now)g(write)f(the)h(unsigned)f(longs)g(to)h(the)g(2nd)g -(column)f(*/)286 1120 y(colnum)190 b(=)47 b(2;)286 1233 -y(fits_write_col\(fptr,)c(TUINT,)j(colnum,)g(firstrow,)f(firstelem,)668 -1346 y(nelements,)g(varray,)h(&status\);)334 1458 y(...)0 -1721 y Fj(Note)22 b(that)g(the)f(non-standard)f(TF)m(ORM)h(v)-5 -b(alues)21 b(for)g(the)g(3)g(columns,)i(`U')e(and)g(`V',)h(tell)g -(CFITSIO)d(to)j(write)f(the)0 1834 y(k)m(eyw)m(ords)27 -b(appropriate)f(for)g(unsigned)f(16-bit)j(and)d(unsigned)h(32-bit)h(in) -m(tegers,)i(resp)s(ectiv)m(ely)e(\(i.e.,)i(TF)m(ORMn)0 -1947 y(=)39 b('1I')i(and)e(TZER)m(On)f(=)h(32768)j(for)e(unsigned)e -(16-bit)j(in)m(tegers,)j(and)39 b(TF)m(ORMn)h(=)f('1J')h(and)f(TZER)m -(On)0 2060 y(=)c(2147483648)40 b(for)35 b(unsigned)f(32-bit)i(in)m -(tegers\).)57 b(The)35 b('S')g(TF)m(ORMn)g(v)-5 b(alue)36 -b(tells)h(CFITSIO)c(to)j(write)g(the)0 2173 y(k)m(eyw)m(ords)30 -b(appropriate)g(for)g(a)g(signed)g(8-bit)h(b)m(yte)f(column)g(with)f -(TF)m(ORMn)h(=)g('1B')h(and)e(TZER)m(On)g(=)g(-128.)0 -2285 y(The)h(calls)h(to)h(\014ts)p 628 2285 28 4 v 32 -w(write)p 862 2285 V 33 w(col)f(then)f(write)h(the)g(arra)m(ys)f(of)h -(unsigned)e(in)m(teger)j(v)-5 b(alues)31 b(to)g(the)f(columns.)0 -2622 y Ff(4.5)135 b(Dealing)47 b(with)e(Character)h(Strings)0 -2873 y Fj(The)36 b(c)m(haracter)j(string)d(v)-5 b(alues)38 -b(in)e(a)h(FITS)f(header)h(or)g(in)f(an)h(ASCI)s(I)e(column)i(in)f(a)i -(FITS)e(table)h(extension)0 2986 y(are)i(generally)i(padded)d(out)h -(with)g(non-signi\014can)m(t)h(space)f(c)m(haracters)i(\(ASCI)s(I)d -(32\))i(to)g(\014ll)f(up)f(the)h(header)0 3099 y(record)33 -b(or)h(the)f(column)h(width.)49 b(When)33 b(reading)h(a)g(FITS)e -(string)i(v)-5 b(alue,)35 b(the)e(CFITSIO)f(routines)i(will)f(strip)0 -3212 y(o\013)38 b(these)f(non-signi\014can)m(t)h(trailing)g(spaces)f -(and)g(will)g(return)f(a)i(n)m(ull-terminated)g(string)f(v)-5 -b(alue)37 b(con)m(taining)0 3325 y(only)d(the)g(signi\014can)m(t)g(c)m -(haracters.)52 b(Leading)34 b(spaces)g(in)g(a)g(FITS)f(string)g(are)h -(considered)g(signi\014can)m(t.)52 b(If)33 b(the)0 3438 -y(string)i(con)m(tains)h(all)g(blanks,)g(then)e(CFITSIO)g(will)h -(return)f(a)h(single)g(blank)g(c)m(haracter,)j(i.e,)f(the)e(\014rst)f -(blank)0 3550 y(is)c(considered)f(to)i(b)s(e)e(signi\014can)m(t,)i -(since)f(it)g(distinguishes)g(the)g(string)f(from)h(a)g(n)m(ull)f(or)h -(unde\014ned)e(string,)i(but)0 3663 y(the)h(remaining)f(trailing)h -(spaces)g(are)g(not)g(signi\014can)m(t.)0 3823 y(Similarly)-8 -b(,)41 b(when)c(writing)h(string)g(v)-5 b(alues)38 b(to)h(a)g(FITS)e -(\014le)h(the)g(CFITSIO)f(routines)h(exp)s(ect)g(to)h(get)g(a)g(n)m -(ull-)0 3936 y(terminated)33 b(string)g(as)g(input;)g(CFITSIO)e(will)i -(pad)f(the)h(string)g(with)f(blanks)g(if)h(necessary)g(when)f(writing)g -(it)0 4049 y(to)f(the)g(FITS)e(\014le.)0 4209 y(When)j(calling)i -(CFITSIO)d(routines)i(that)g(return)e(a)i(c)m(haracter)h(string)f(it)g -(is)f(vital)i(that)f(the)g(size)g(of)g(the)g(c)m(har)0 -4322 y(arra)m(y)38 b(b)s(e)g(large)h(enough)e(to)i(hold)e(the)h(en)m -(tire)h(string)f(of)g(c)m(haracters,)k(otherwise)c(CFITSIO)e(will)i(o)m -(v)m(erwrite)0 4435 y(whatev)m(er)d(memory)e(lo)s(cations)i(follo)m(w)g -(the)f(c)m(har)h(arra)m(y)-8 b(,)35 b(p)s(ossibly)e(causing)h(the)g -(program)g(to)g(execute)h(incor-)0 4548 y(rectly)-8 b(.)42 -b(This)30 b(t)m(yp)s(e)g(of)h(error)f(can)h(b)s(e)f(di\016cult)g(to)h -(debug,)f(so)h(programmers)f(should)f(alw)m(a)m(ys)j(ensure)e(that)h -(the)0 4661 y(c)m(har)c(arra)m(ys)g(are)g(allo)s(cated)i(enough)d -(space)i(to)f(hold)g(the)f(longest)i(p)s(ossible)f(string,)g -Fi(including)h Fj(the)f(terminat-)0 4774 y(ing)k(NULL)g(c)m(haracter.) -45 b(The)30 b(\014tsio.h)h(\014le)h(con)m(tains)g(the)f(follo)m(wing)i -(de\014ned)d(constan)m(ts)i(whic)m(h)f(programmers)0 -4887 y(are)g(strongly)g(encouraged)g(to)g(use)f(whenev)m(er)g(they)h -(are)f(allo)s(cating)j(space)e(for)f(c)m(har)h(arra)m(ys:)0 -5149 y Fe(#define)46 b(FLEN_FILENAME)e(1025)j(/*)g(max)g(length)f(of)h -(a)g(filename)f(*/)0 5262 y(#define)g(FLEN_KEYWORD)140 -b(72)95 b(/*)47 b(max)g(length)f(of)h(a)g(keyword)94 -b(*/)0 5375 y(#define)46 b(FLEN_CARD)284 b(81)95 b(/*)47 -b(length)f(of)h(a)h(FITS)e(header)g(card)h(*/)0 5488 -y(#define)f(FLEN_VALUE)236 b(71)95 b(/*)47 b(max)g(length)f(of)h(a)g -(keyword)f(value)h(string)f(*/)0 5601 y(#define)g(FLEN_COMMENT)140 -b(73)95 b(/*)47 b(max)g(length)f(of)h(a)g(keyword)f(comment)g(string)g -(*/)0 5714 y(#define)g(FLEN_ERRMSG)188 b(81)95 b(/*)47 -b(max)g(length)f(of)h(a)g(CFITSIO)f(error)h(message)e(*/)p -eop end -%%Page: 23 31 -TeXDict begin 23 30 bop 0 299 a Fh(4.6.)72 b(IMPLICIT)29 -b(D)m(A)-8 b(T)g(A)32 b(TYPE)e(CONVERSION)1938 b Fj(23)0 -555 y Fe(#define)46 b(FLEN_STATUS)188 b(31)95 b(/*)47 -b(max)g(length)f(of)h(a)g(CFITSIO)f(status)g(text)h(string)f(*/)0 -815 y Fj(F)-8 b(or)23 b(example,)h(when)d(declaring)i(a)f(c)m(har)g -(arra)m(y)h(to)f(hold)g(the)g(v)-5 b(alue)22 b(string)g(of)g(FITS)f(k)m -(eyw)m(ord,)k(use)c(the)h(follo)m(wing)0 928 y(statemen)m(t:)191 -1188 y Fe(char)47 b(value[FLEN_VALUE];)0 1448 y Fj(Note)41 -b(that)f(FLEN)p 686 1448 28 4 v 33 w(KEYW)m(ORD)g(is)f(longer)h(than)f -(needed)g(for)g(the)h(nominal)f(8-c)m(haracter)j(k)m(eyw)m(ord)e(name)0 -1561 y(b)s(ecause)30 b(the)h(HIERAR)m(CH)f(con)m(v)m(en)m(tion)j(supp)s -(orts)28 b(longer)j(k)m(eyw)m(ord)g(names.)0 1894 y Ff(4.6)135 -b(Implicit)46 b(Data)g(T)l(yp)t(e)f(Con)l(v)l(ersion)0 -2145 y Fj(The)29 b(CFITSIO)e(routines)i(that)h(read)f(and)f(write)i(n)m -(umerical)f(data)h(can)g(p)s(erform)d(implicit)j(data)g(t)m(yp)s(e)f -(con)m(v)m(er-)0 2257 y(sion.)39 b(This)25 b(means)h(that)g(the)g(data) -g(t)m(yp)s(e)g(of)g(the)g(v)-5 b(ariable)26 b(or)g(arra)m(y)g(in)f(the) -h(program)g(do)s(es)f(not)h(need)f(to)i(b)s(e)e(the)0 -2370 y(same)g(as)f(the)h(data)g(t)m(yp)s(e)g(of)f(the)h(v)-5 -b(alue)25 b(in)f(the)g(FITS)g(\014le.)39 b(Data)26 b(t)m(yp)s(e)f(con)m -(v)m(ersion)g(is)g(supp)s(orted)d(for)i(n)m(umerical)0 -2483 y(and)37 b(string)g(data)g(t)m(yp)s(es)h(\(if)f(the)g(string)g -(con)m(tains)i(a)e(v)-5 b(alid)38 b(n)m(um)m(b)s(er)e(enclosed)h(in)g -(quotes\))h(when)e(reading)i(a)0 2596 y(FITS)30 b(header)h(k)m(eyw)m -(ord)g(v)-5 b(alue)31 b(and)f(for)h(n)m(umeric)g(v)-5 -b(alues)31 b(when)f(reading)h(or)f(writing)h(v)-5 b(alues)31 -b(in)g(the)g(primary)0 2709 y(arra)m(y)24 b(or)g(a)h(table)f(column.)39 -b(CFITSIO)22 b(returns)h(status)h(=)f(NUM)p 2267 2709 -V 34 w(O)m(VERFLO)m(W)i(if)e(the)h(con)m(v)m(erted)i(data)e(v)-5 -b(alue)0 2822 y(exceeds)33 b(the)g(range)g(of)g(the)f(output)g(data)i -(t)m(yp)s(e.)47 b(Implicit)33 b(data)g(t)m(yp)s(e)g(con)m(v)m(ersion)h -(is)e(not)h(supp)s(orted)d(within)0 2935 y(binary)g(tables)h(for)f -(string,)g(logical,)k(complex,)d(or)f(double)g(complex)h(data)g(t)m(yp) -s(es.)0 3095 y(In)g(addition,)h(an)m(y)f(table)h(column)f(ma)m(y)h(b)s -(e)f(read)g(as)h(if)f(it)h(con)m(tained)g(string)f(v)-5 -b(alues.)44 b(In)31 b(the)g(case)i(of)e(n)m(umeric)0 -3208 y(columns)f(the)h(returned)e(string)h(will)h(b)s(e)f(formatted)h -(using)e(the)i(TDISPn)e(displa)m(y)i(format)f(if)h(it)g(exists.)0 -3542 y Ff(4.7)135 b(Data)46 b(Scaling)0 3792 y Fj(When)38 -b(reading)f(n)m(umerical)i(data)f(v)-5 b(alues)38 b(in)f(the)h(primary) -f(arra)m(y)h(or)g(a)g(table)h(column,)h(the)d(v)-5 b(alues)38 -b(will)h(b)s(e)0 3905 y(scaled)f(automatically)j(b)m(y)c(the)g(BSCALE)g -(and)g(BZER)m(O)g(\(or)h(TSCALn)e(and)h(TZER)m(On\))f(header)h(v)-5 -b(alues)38 b(if)0 4018 y(they)31 b(are)f(presen)m(t)h(in)f(the)g -(header.)41 b(The)30 b(scaled)h(data)g(that)g(is)f(returned)g(to)h(the) -f(reading)h(program)f(will)h(ha)m(v)m(e)382 4278 y Fe(output)46 -b(value)g(=)i(\(FITS)e(value\))g(*)i(BSCALE)e(+)h(BZERO)0 -4538 y Fj(\(a)30 b(corresp)s(onding)e(form)m(ula)h(using)g(TSCALn)e -(and)i(TZER)m(On)e(is)i(used)g(when)f(reading)h(from)g(table)h -(columns\).)0 4650 y(In)h(the)i(case)g(of)f(in)m(teger)h(output)f(v)-5 -b(alues)32 b(the)h(\015oating)g(p)s(oin)m(t)f(scaled)g(v)-5 -b(alue)33 b(is)f(truncated)g(to)h(an)f(in)m(teger)h(\(not)0 -4763 y(rounded)i(to)j(the)f(nearest)h(in)m(teger\).)62 -b(The)36 b(\014ts)p 1673 4763 V 32 w(set)p 1816 4763 -V 34 w(bscale)i(and)e(\014ts)p 2430 4763 V 32 w(set)p -2573 4763 V 34 w(tscale)i(routines)f(\(describ)s(ed)f(in)h(the)0 -4876 y(`Adv)-5 b(anced')29 b(c)m(hapter\))h(ma)m(y)g(b)s(e)e(used)h(to) -g(o)m(v)m(erride)i(the)e(scaling)h(parameters)f(de\014ned)f(in)h(the)g -(header)g(\(e.g.,)i(to)0 4989 y(turn)e(o\013)i(the)g(scaling)g(so)g -(that)g(the)f(program)g(can)h(read)f(the)h(ra)m(w)f(unscaled)h(v)-5 -b(alues)30 b(from)g(the)h(FITS)e(\014le\).)0 5149 y(When)44 -b(writing)h(n)m(umerical)g(data)g(to)g(the)g(primary)f(arra)m(y)h(or)f -(to)h(a)g(table)h(column)e(the)h(data)g(v)-5 b(alues)45 -b(will)0 5262 y(generally)29 b(b)s(e)f(automatically)j(in)m(v)m(ersely) -f(scaled)f(b)m(y)f(the)g(v)-5 b(alue)29 b(of)f(the)h(BSCALE)e(and)h -(BZER)m(O)g(\(or)h(TSCALn)0 5375 y(and)35 b(TZER)m(On\))f(k)m(eyw)m -(ord)i(v)-5 b(alues)35 b(if)h(they)f(they)g(exist)i(in)e(the)g(header.) -55 b(These)35 b(k)m(eyw)m(ords)h(m)m(ust)f(ha)m(v)m(e)i(b)s(een)0 -5488 y(written)31 b(to)h(the)g(header)f(b)s(efore)g(an)m(y)g(data)h(is) -g(written)f(for)g(them)g(to)h(ha)m(v)m(e)h(an)m(y)e(immediate)i -(e\013ect.)45 b(One)30 b(ma)m(y)0 5601 y(also)h(use)g(the)f(\014ts)p -623 5601 V 33 w(set)p 767 5601 V 33 w(bscale)i(and)d(\014ts)p -1367 5601 V 33 w(set)p 1511 5601 V 33 w(tscale)j(routines)f(to)g -(de\014ne)f(or)g(o)m(v)m(erride)i(the)f(scaling)g(k)m(eyw)m(ords)g(in)0 -5714 y(the)e(header)g(\(e.g.,)i(to)e(turn)f(o\013)h(the)g(scaling)h(so) -f(that)h(the)f(program)f(can)h(write)g(the)g(ra)m(w)g(unscaled)g(v)-5 -b(alues)29 b(in)m(to)p eop end -%%Page: 24 32 -TeXDict begin 24 31 bop 0 299 a Fj(24)1763 b Fh(CHAPTER)29 -b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Fj(the)26 -b(FITS)g(\014le\).)40 b(If)25 b(scaling)i(is)g(p)s(erformed,)e(the)i -(in)m(v)m(erse)g(scaled)g(output)e(v)-5 b(alue)27 b(that)g(is)f -(written)g(in)m(to)h(the)g(FITS)0 668 y(\014le)j(will)h(ha)m(v)m(e)430 -956 y Fe(FITS)46 b(value)h(=)g(\(\(input)f(value\))g(-)h(BZERO\))f(/)i -(BSCALE)0 1244 y Fj(\(a)39 b(corresp)s(onding)d(form)m(ula)i(using)g -(TSCALn)e(and)h(TZER)m(On)g(is)h(used)f(when)f(writing)i(to)h(table)g -(columns\).)0 1357 y(Rounding)34 b(to)i(the)g(nearest)g(in)m(teger,)i -(rather)d(than)g(truncation,)j(is)d(p)s(erformed)f(when)g(writing)h(in) -m(teger)i(data)0 1469 y(t)m(yp)s(es)30 b(to)i(the)e(FITS)g(\014le.)0 -1836 y Ff(4.8)135 b(Supp)t(ort)44 b(for)h(IEEE)h(Sp)t(ecial)f(V)-11 -b(alues)0 2093 y Fj(The)26 b(ANSI/IEEE-754)h(\015oating-p)s(oin)m(t)h -(n)m(um)m(b)s(er)d(standard)g(de\014nes)h(certain)h(sp)s(ecial)g(v)-5 -b(alues)26 b(that)h(are)g(used)e(to)0 2206 y(represen)m(t)j(suc)m(h)g -(quan)m(tities)h(as)f(Not-a-Num)m(b)s(er)h(\(NaN\),)h(denormalized,)f -(under\015o)m(w,)e(o)m(v)m(er\015o)m(w,)j(and)d(in\014nit)m(y)-8 -b(.)0 2319 y(\(See)31 b(the)g(App)s(endix)d(in)j(the)f(FITS)g(standard) -f(or)i(the)g(FITS)e(User's)i(Guide)f(for)g(a)h(list)g(of)g(these)g(v)-5 -b(alues\).)41 b(The)0 2432 y(CFITSIO)31 b(routines)i(that)g(read)f -(\015oating)i(p)s(oin)m(t)f(data)g(in)f(FITS)g(\014les)h(recognize)h -(these)f(IEEE)f(sp)s(ecial)i(v)-5 b(alues)0 2544 y(and)27 -b(b)m(y)h(default)h(in)m(terpret)f(the)h(o)m(v)m(er\015o)m(w)g(and)f -(in\014nit)m(y)f(v)-5 b(alues)29 b(as)f(b)s(eing)g(equiv)-5 -b(alen)m(t)29 b(to)g(a)g(NaN,)g(and)e(con)m(v)m(ert)0 -2657 y(the)37 b(under\015o)m(w)e(and)i(denormalized)g(v)-5 -b(alues)37 b(in)m(to)h(zeros.)60 b(In)36 b(some)i(cases)f(programmers)g -(ma)m(y)g(w)m(an)m(t)h(access)0 2770 y(to)d(the)g(ra)m(w)f(IEEE)g(v)-5 -b(alues,)36 b(without)e(an)m(y)h(mo)s(di\014cation)g(b)m(y)f(CFITSIO.)f -(This)h(can)h(b)s(e)e(done)i(b)m(y)f(calling)i(the)0 -2883 y(\014ts)p 127 2883 28 4 v 32 w(read)p 331 2883 -V 33 w(img)27 b(or)g(\014ts)p 767 2883 V 32 w(read)p -971 2883 V 33 w(col)g(routines)g(while)f(sp)s(ecifying)h(0.0)h(as)e -(the)h(v)-5 b(alue)27 b(of)g(the)g(NULL)-10 b(V)g(AL)26 -b(parameter.)0 2996 y(This)44 b(will)h(force)h(CFITSIO)d(to)i(simply)g -(pass)f(the)h(IEEE)f(v)-5 b(alues)45 b(through)f(to)i(the)f -(application)h(program)0 3109 y(without)38 b(an)m(y)h(mo)s -(di\014cation.)65 b(This)37 b(is)h(not)h(fully)f(supp)s(orted)e(on)i(V) --10 b(AX/VMS)40 b(mac)m(hines,)h(ho)m(w)m(ev)m(er,)g(where)0 -3222 y(there)34 b(is)f(no)g(easy)h(w)m(a)m(y)h(to)f(b)m(ypass)f(the)g -(default)h(in)m(terpretation)h(of)e(the)h(IEEE)f(sp)s(ecial)h(v)-5 -b(alues.)50 b(This)33 b(is)g(also)0 3335 y(not)e(supp)s(orted)e(when)h -(reading)g(\015oating-p)s(oin)m(t)i(images)g(that)g(ha)m(v)m(e)g(b)s -(een)e(compressed)g(with)g(the)h(FITS)f(tiled)0 3448 -y(image)i(compression)f(con)m(v)m(en)m(tion)j(that)d(is)g(discussed)g -(in)f(section)j(5.6;)f(the)g(pixels)f(v)-5 b(alues)31 -b(in)g(tile)h(compressed)0 3561 y(images)42 b(are)f(represen)m(ted)f(b) -m(y)h(scaled)h(in)m(tegers,)i(and)c(a)h(reserv)m(ed)g(in)m(teger)h(v)-5 -b(alue)41 b(\(not)h(a)f(NaN\))h(is)e(used)g(to)0 3674 -y(represen)m(t)30 b(unde\014ned)f(pixels.)0 4040 y Ff(4.9)135 -b(Error)46 b(Status)f(V)-11 b(alues)45 b(and)g(the)g(Error)g(Message)h -(Stac)l(k)0 4297 y Fj(Nearly)36 b(all)g(the)g(CFITSIO)e(routines)h -(return)f(an)h(error)g(status)h(v)-5 b(alue)35 b(in)g(2)h(w)m(a)m(ys:) -51 b(as)36 b(the)f(v)-5 b(alue)36 b(of)g(the)f(last)0 -4410 y(parameter)29 b(in)f(the)g(function)g(call,)j(and)d(as)g(the)h -(returned)e(v)-5 b(alue)29 b(of)f(the)h(function)f(itself.)41 -b(This)27 b(pro)m(vides)i(some)0 4523 y(\015exibilit)m(y)37 -b(in)e(the)h(w)m(a)m(y)h(programmers)e(can)h(test)h(if)f(an)f(error)h -(o)s(ccurred,)g(as)g(illustrated)h(in)e(the)h(follo)m(wing)i(2)0 -4636 y(co)s(de)31 b(fragmen)m(ts:)191 4924 y Fe(if)47 -b(\()h(fits_write_record\(fptr,)41 b(card,)46 b(&status\))g(\))430 -5036 y(printf\(")f(Error)h(occurred)g(while)g(writing)g(keyword."\);)0 -5262 y(or,)191 5488 y(fits_write_record\(fptr,)41 b(card,)47 -b(&status\);)191 5601 y(if)g(\()h(status)e(\))430 5714 -y(printf\(")f(Error)h(occurred)g(while)g(writing)g(keyword."\);)p -eop end -%%Page: 25 33 -TeXDict begin 25 32 bop 0 299 a Fh(4.10.)73 b(V)-10 b(ARIABLE-LENGTH)31 -b(ARRA)-8 b(YS)30 b(IN)g(BINAR)-8 b(Y)32 b(T)-8 b(ABLES)1327 -b Fj(25)0 555 y(A)27 b(listing)h(of)g(all)g(the)f(CFITSIO)f(status)i -(co)s(de)f(v)-5 b(alues)28 b(is)f(giv)m(en)h(at)g(the)g(end)e(of)i -(this)f(do)s(cumen)m(t.)39 b(Programmers)0 668 y(are)33 -b(encouraged)g(to)g(use)f(the)h(sym)m(b)s(olic)f(mnemonics)g -(\(de\014ned)g(in)g(\014tsio.h\))h(rather)f(than)g(the)h(actual)h(in)m -(teger)0 781 y(status)d(v)-5 b(alues)30 b(to)i(impro)m(v)m(e)f(the)f -(readabilit)m(y)i(of)f(their)f(co)s(de.)0 941 y(The)i(CFITSIO)f -(library)g(uses)h(an)g(`inherited)h(status')g(con)m(v)m(en)m(tion)h -(for)e(the)h(status)f(parameter)h(whic)m(h)f(means)0 -1054 y(that)37 b(if)f(a)h(routine)f(is)h(called)g(with)f(a)h(p)s -(ositiv)m(e)g(input)f(v)-5 b(alue)36 b(of)h(the)g(status)f(parameter)h -(as)g(input,)g(then)f(the)0 1167 y(routine)j(will)f(exit)i(immediately) -g(without)e(c)m(hanging)i(the)e(v)-5 b(alue)39 b(of)g(the)g(status)g -(parameter.)65 b(Th)m(us,)40 b(if)f(one)0 1280 y(passes)24 -b(the)h(status)g(v)-5 b(alue)25 b(returned)f(from)g(eac)m(h)i(CFITSIO)d -(routine)h(as)h(input)f(to)h(the)g(next)g(CFITSIO)e(routine,)0 -1393 y(then)28 b(whenev)m(er)g(an)g(error)g(is)h(detected)g(all)h -(further)d(CFITSIO)f(pro)s(cessing)i(will)h(cease.)42 -b(This)27 b(con)m(v)m(en)m(tion)k(can)0 1506 y(simplify)h(the)h(error)f -(c)m(hec)m(king)j(in)d(application)i(programs)e(b)s(ecause)h(it)g(is)g -(not)g(necessary)g(to)g(c)m(hec)m(k)i(the)d(v)-5 b(alue)0 -1619 y(of)30 b(the)g(status)h(parameter)f(after)h(ev)m(ery)g(single)f -(CFITSIO)f(routine)h(call.)42 b(If)30 b(a)g(program)g(con)m(tains)h(a)g -(sequence)0 1732 y(of)d(sev)m(eral)i(CFITSIO)d(calls,)j(one)e(can)h -(just)e(c)m(hec)m(k)j(the)f(status)f(v)-5 b(alue)29 b(after)g(the)f -(last)h(call.)41 b(Since)29 b(the)f(returned)0 1844 y(status)33 -b(v)-5 b(alues)33 b(are)g(generally)h(distinctiv)m(e,)h(it)f(should)d -(b)s(e)i(p)s(ossible)f(to)h(determine)g(whic)m(h)g(routine)g -(originally)0 1957 y(returned)c(the)i(error)f(status.)0 -2118 y(CFITSIO)c(also)i(main)m(tains)h(an)e(in)m(ternal)h(stac)m(k)h -(of)f(error)f(messages)h(\(80-c)m(haracter)j(maxim)m(um)c(length\))h -(whic)m(h)0 2230 y(in)36 b(man)m(y)g(cases)h(pro)m(vide)f(a)g(more)g -(detailed)i(explanation)f(of)f(the)g(cause)h(of)f(the)g(error)g(than)f -(is)h(pro)m(vided)g(b)m(y)0 2343 y(the)k(error)e(status)i(n)m(um)m(b)s -(er)e(alone.)69 b(It)39 b(is)h(recommended)f(that)g(the)h(error)f -(message)h(stac)m(k)h(b)s(e)e(prin)m(ted)g(out)0 2456 -y(whenev)m(er)g(a)g(program)g(detects)h(a)f(CFITSIO)e(error.)66 -b(The)38 b(function)h(\014ts)p 2653 2456 28 4 v 32 w(rep)s(ort)p -2931 2456 V 32 w(error)g(will)g(prin)m(t)g(out)g(the)0 -2569 y(en)m(tire)31 b(error)e(message)h(stac)m(k,)i(or)d(alternativ)m -(ely)k(one)d(ma)m(y)g(call)h(\014ts)p 2376 2569 V 32 -w(read)p 2580 2569 V 33 w(errmsg)e(to)h(get)h(the)f(error)f(messages)0 -2682 y(one)i(at)g(a)g(time.)0 3056 y Ff(4.10)136 b(V)-11 -b(ariable-Length)45 b(Arra)l(ys)g(in)g(Binary)g(T)-11 -b(ables)0 3314 y Fj(CFITSIO)33 b(pro)m(vides)i(easy-to-use)h(supp)s -(ort)d(for)i(reading)g(and)f(writing)h(data)g(in)g(v)-5 -b(ariable)35 b(length)g(\014elds)g(of)g(a)0 3427 y(binary)27 -b(table.)40 b(The)27 b(v)-5 b(ariable)29 b(length)f(columns)f(ha)m(v)m -(e)i(TF)m(ORMn)e(k)m(eyw)m(ord)h(v)-5 b(alues)28 b(of)g(the)f(form)g -(`1Pt\(len\)')j(or)0 3540 y(`1Qt\(len\)')36 b(where)d(`t')h(is)g(the)g -(data)g(t)m(yp)s(e)g(co)s(de)g(\(e.g.,)j(I,)c(J,)h(E,)g(D,)g(etc.\))52 -b(and)33 b(`len')i(is)e(an)h(in)m(teger)h(sp)s(ecifying)0 -3653 y(the)g(maxim)m(um)g(length)h(of)f(the)h(v)m(ector)h(in)d(the)i -(table.)56 b(The)35 b('P')g(t)m(yp)s(e)g(v)-5 b(ariable)36 -b(length)g(columns)f(use)g(32-bit)0 3766 y(arra)m(y)j(length)h(and)e(b) -m(yte)h(o\013set)h(v)-5 b(alues,)41 b(whereas)c(the)h('Q')g(t)m(yp)s(e) -g(columns)g(use)f(64-bit)i(v)-5 b(alues,)41 b(whic)m(h)c(ma)m(y)0 -3878 y(b)s(e)31 b(required)h(when)f(dealing)i(with)f(large)h(arra)m -(ys.)46 b(CFITSIO)31 b(supp)s(orts)f(a)i(lo)s(cal)i(con)m(v)m(en)m -(tion)g(that)f(in)m(terprets)0 3991 y(the)41 b('P')g(t)m(yp)s(e)g -(descriptors)g(as)g(unsigned)e(32-bit)j(in)m(tegers,)j(whic)m(h)c(pro)m -(vides)g(a)g(factor)g(of)g(2)h(greater)g(range)0 4104 -y(for)32 b(the)g(arra)m(y)h(length)g(or)f(heap)g(address)f(than)h(is)g -(p)s(ossible)g(with)g(32-bit)h('signed')g(in)m(tegers.)47 -b(Note,)34 b(ho)m(w)m(ev)m(er,)0 4217 y(that)i(other)g(soft)m(w)m(are)g -(pac)m(k)-5 b(ages)38 b(ma)m(y)d(not)h(supp)s(ort)e(this)h(con)m(v)m -(en)m(tion,)k(and)c(ma)m(y)h(b)s(e)e(unable)h(to)h(read)f(thees)0 -4330 y(extended)30 b(range)h(v)-5 b(ariable)31 b(length)g(records.)0 -4490 y(If)d(the)h(v)-5 b(alue)30 b(of)f(`len')g(is)g(not)g(sp)s -(eci\014ed)f(when)g(the)h(table)h(is)e(created)i(\(e.g.,)h(if)e(the)g -(TF)m(ORM)g(k)m(eyw)m(ord)h(v)-5 b(alue)29 b(is)0 4603 -y(simply)j(sp)s(eci\014ed)f(as)h('1PE')h(instead)g(of)f('1PE\(400\))i -(\),)g(then)d(CFITSIO)g(will)h(automatically)j(scan)e(the)f(table)0 -4716 y(when)27 b(it)j(is)e(closed)h(to)h(determine)e(the)h(maxim)m(um)f -(length)h(of)g(the)f(v)m(ector)j(and)c(will)i(app)s(end)e(this)i(v)-5 -b(alue)29 b(to)g(the)0 4829 y(TF)m(ORMn)h(v)-5 b(alue.)0 -4989 y(The)29 b(same)h(routines)g(that)g(read)f(and)g(write)h(data)g -(in)g(an)f(ordinary)g(\014xed)g(length)h(binary)f(table)h(extension)h -(are)0 5102 y(also)41 b(used)d(for)i(v)-5 b(ariable)40 -b(length)g(\014elds,)h(ho)m(w)m(ev)m(er,)j(the)c(routine)f(parameters)h -(tak)m(e)h(on)f(a)g(sligh)m(tly)g(di\013eren)m(t)0 5215 -y(in)m(terpretation)32 b(as)e(describ)s(ed)g(b)s(elo)m(w.)0 -5375 y(All)37 b(the)f(data)h(in)f(a)h(v)-5 b(ariable)37 -b(length)f(\014eld)g(is)g(written)h(in)m(to)g(an)f(area)h(called)h(the) -e(`heap')g(whic)m(h)g(follo)m(ws)i(the)0 5488 y(main)31 -b(\014xed-length)h(FITS)e(binary)h(table.)44 b(The)31 -b(size)h(of)f(the)h(heap,)f(in)g(b)m(ytes,)h(is)g(sp)s(eci\014ed)e(b)m -(y)h(the)h(PCOUNT)0 5601 y(k)m(eyw)m(ord)21 b(in)f(the)h(FITS)f -(header.)37 b(When)20 b(creating)i(a)f(new)f(binary)g(table,)j(the)e -(initial)h(v)-5 b(alue)21 b(of)f(PCOUNT)g(should)0 5714 -y(usually)27 b(b)s(e)h(set)g(to)g(zero.)41 b(CFITSIO)26 -b(will)i(recompute)g(the)g(size)g(of)g(the)g(heap)g(as)g(the)g(data)g -(is)g(written)f(and)h(will)p eop end -%%Page: 26 34 -TeXDict begin 26 33 bop 0 299 a Fj(26)1763 b Fh(CHAPTER)29 -b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Fj(automatically)c -(up)s(date)c(the)i(PCOUNT)e(k)m(eyw)m(ord)h(v)-5 b(alue)26 -b(when)e(the)h(table)h(is)f(closed.)40 b(When)25 b(writing)g(v)-5 -b(ariable)0 668 y(length)34 b(data)g(to)g(a)g(table,)i(CFITSIO)c(will)h -(automatically)k(extend)c(the)h(size)g(of)g(the)g(heap)f(area)h(if)g -(necessary)-8 b(,)0 781 y(so)31 b(that)g(an)m(y)f(follo)m(wing)i(HDUs)f -(do)f(not)h(get)h(o)m(v)m(erwritten.)0 941 y(By)e(default)f(the)h(heap) -f(data)i(area)f(starts)g(immediately)h(after)f(the)f(last)i(ro)m(w)e -(of)h(the)g(\014xed-length)f(table.)42 b(This)0 1054 -y(default)27 b(starting)g(lo)s(cation)i(ma)m(y)e(b)s(e)f(o)m(v)m -(erridden)h(b)m(y)g(the)g(THEAP)f(k)m(eyw)m(ord,)i(but)f(this)f(is)h -(not)g(recommended.)0 1167 y(If)34 b(additional)h(ro)m(ws)f(of)g(data)h -(are)g(added)e(to)i(the)f(table,)j(CFITSIO)32 b(will)j(automatically)i -(shift)c(the)i(the)f(heap)0 1280 y(do)m(wn)g(to)i(mak)m(e)f(ro)s(om)g -(for)f(the)h(new)f(ro)m(ws,)i(but)e(it)i(is)e(ob)m(viously)i(b)s(e)e -(more)h(e\016cien)m(t)h(to)f(initially)h(create)h(the)0 -1393 y(table)31 b(with)e(the)h(necessary)g(n)m(um)m(b)s(er)f(of)h -(blank)f(ro)m(ws,)h(so)g(that)g(the)g(heap)g(do)s(es)f(not)h(needed)g -(to)g(b)s(e)f(constan)m(tly)0 1506 y(mo)m(v)m(ed.)0 1666 -y(When)36 b(writing)g(ro)m(w)g(of)h(data)f(to)h(a)g(v)-5 -b(ariable)37 b(length)f(\014eld)g(the)g(en)m(tire)i(arra)m(y)e(of)g(v) --5 b(alues)37 b(for)f(a)g(giv)m(en)i(ro)m(w)e(of)0 1779 -y(the)30 b(table)h(m)m(ust)e(b)s(e)h(written)g(with)f(a)h(single)h -(call)g(to)f(\014ts)p 1986 1779 28 4 v 33 w(write)p 2221 -1779 V 33 w(col.)42 b(The)29 b(total)i(length)g(of)f(the)g(arra)m(y)g -(is)g(giv)m(en)0 1892 y(b)m(y)j(nelemen)m(ts)h(+)f(\014rstelem)g(-)g -(1.)49 b(Additional)34 b(elemen)m(ts)h(cannot)e(b)s(e)g(app)s(ended)e -(to)j(an)f(existing)h(v)m(ector)h(at)f(a)0 2005 y(later)c(time)g(since) -g(an)m(y)g(attempt)g(to)g(do)g(so)f(will)h(simply)f(o)m(v)m(erwrite)i -(all)f(the)f(previously)h(written)f(data)h(and)f(the)0 -2118 y(new)36 b(data)h(will)g(b)s(e)f(written)g(to)h(a)g(new)f(area)h -(of)g(the)g(heap.)58 b(The)36 b(\014ts)p 2496 2118 V -33 w(compress)p 2889 2118 V 32 w(heap)g(routine)h(is)f(pro)m(vided)0 -2230 y(to)h(compress)g(the)g(heap)g(and)f(reco)m(v)m(er)i(an)m(y)f(un)m -(used)f(space.)60 b(T)-8 b(o)37 b(a)m(v)m(oid)i(ha)m(ving)e(to)h(deal)f -(with)f(this)h(issue,)h(it)0 2343 y(is)31 b(recommended)h(that)g(ro)m -(ws)f(in)g(a)h(v)-5 b(ariable)32 b(length)g(\014eld)f(should)f(only)i -(b)s(e)f(written)g(once.)45 b(An)31 b(exception)h(to)0 -2456 y(this)e(general)h(rule)f(o)s(ccurs)g(when)f(setting)i(elemen)m -(ts)h(of)e(an)g(arra)m(y)g(as)h(unde\014ned.)38 b(It)30 -b(is)h(allo)m(w)m(ed)h(to)e(\014rst)g(write)0 2569 y(a)e(dumm)m(y)f(v) --5 b(alue)28 b(in)m(to)h(the)f(arra)m(y)h(with)e(\014ts)p -1534 2569 V 33 w(write)p 1769 2569 V 33 w(col,)j(and)d(then)g(call)j -(\014ts)p 2632 2569 V 32 w(write)p 2866 2569 V 33 w(col)p -3009 2569 V 34 w(n)m(ul)d(to)i(\015ag)f(the)g(desired)0 -2682 y(elemen)m(ts)h(as)f(unde\014ned.)38 b(Note)29 b(that)g(the)f(ro)m -(ws)g(of)g(a)g(table,)i(whether)d(\014xed)g(or)h(v)-5 -b(ariable)29 b(length,)g(do)f(not)g(ha)m(v)m(e)0 2795 -y(to)j(b)s(e)f(written)g(consecutiv)m(ely)j(and)d(ma)m(y)h(b)s(e)e -(written)i(in)f(an)m(y)h(order.)0 2955 y(When)40 b(writing)h(to)g(a)g -(v)-5 b(ariable)41 b(length)g(ASCI)s(I)e(c)m(haracter)j(\014eld)e -(\(e.g.,)45 b(TF)m(ORM)c(=)f('1P)-8 b(A'\))43 b(only)d(a)h(single)0 -3068 y(c)m(haracter)22 b(string)e(can)h(b)s(e)e(written.)38 -b(The)20 b(`\014rstelem')g(and)g(`nelemen)m(ts')i(parameter)e(v)-5 -b(alues)21 b(in)f(the)g(\014ts)p 3526 3068 V 33 w(write)p -3761 3068 V 33 w(col)0 3181 y(routine)35 b(are)h(ignored)f(and)f(the)i -(n)m(um)m(b)s(er)d(of)j(c)m(haracters)g(to)g(write)f(is)h(simply)e -(determined)h(b)m(y)g(the)g(length)h(of)0 3294 y(the)31 -b(input)e(n)m(ull-terminated)i(c)m(haracter)h(string.)0 -3454 y(The)21 b(\014ts)p 305 3454 V 33 w(write)p 540 -3454 V 33 w(descript)g(routine)h(is)f(useful)g(in)g(situations)i(where) -e(m)m(ultiple)h(ro)m(ws)g(of)g(a)g(v)-5 b(ariable)22 -b(length)g(column)0 3567 y(ha)m(v)m(e)32 b(the)e(iden)m(tical)i(arra)m -(y)f(of)g(v)-5 b(alues.)41 b(One)30 b(can)g(simply)g(write)h(the)f -(arra)m(y)h(once)g(for)g(the)f(\014rst)g(ro)m(w,)g(and)g(then)0 -3680 y(use)c(\014ts)p 280 3680 V 32 w(write)p 514 3680 -V 33 w(descript)g(to)g(write)g(the)g(same)h(descriptor)e(v)-5 -b(alues)27 b(in)m(to)g(the)f(other)g(ro)m(ws;)h(all)g(the)f(ro)m(ws)g -(will)g(then)0 3793 y(p)s(oin)m(t)k(to)h(the)g(same)g(storage)h(lo)s -(cation)g(th)m(us)e(sa)m(ving)h(disk)f(space.)0 3953 -y(When)35 b(reading)g(from)f(a)i(v)-5 b(ariable)35 b(length)h(arra)m(y) -f(\014eld)g(one)g(can)g(only)h(read)e(as)i(man)m(y)f(elemen)m(ts)h(as)f -(actually)0 4066 y(exist)i(in)e(that)i(ro)m(w)e(of)h(the)g(table;)k -(reading)c(do)s(es)g(not)g(automatically)i(con)m(tin)m(ue)f(with)f(the) -g(next)g(ro)m(w)g(of)g(the)0 4179 y(table)29 b(as)f(o)s(ccurs)g(when)f -(reading)h(an)g(ordinary)g(\014xed)f(length)h(table)h(\014eld.)40 -b(A)m(ttempts)29 b(to)g(read)f(more)g(than)g(this)0 4292 -y(will)k(cause)h(an)e(error)h(status)g(to)g(b)s(e)f(returned.)44 -b(One)32 b(can)g(determine)g(the)g(n)m(um)m(b)s(er)e(of)i(elemen)m(ts)h -(in)f(eac)m(h)h(ro)m(w)0 4405 y(of)e(a)f(v)-5 b(ariable)31 -b(column)g(with)f(the)g(\014ts)p 1329 4405 V 33 w(read)p -1534 4405 V 32 w(descript)h(routine.)0 4735 y Ff(4.11)136 -b(Multiple)45 b(Access)g(to)g(the)g(Same)h(FITS)d(File)0 -4986 y Fj(CFITSIO)29 b(supp)s(orts)g(sim)m(ultaneous)i(read)f(and)g -(write)h(access)h(to)f(di\013eren)m(t)g(HDUs)g(in)f(the)h(same)g(FITS)f -(\014le)g(in)0 5099 y(some)h(circumstances,)g(as)g(describ)s(ed)e(b)s -(elo)m(w:)136 5341 y Fc(\017)46 b Fj(Multi-threaded)31 -b(programs)227 5488 y(When)f(CFITSIO)f(is)h(compiled)h(with)e(the)i(-D) -p 1842 5488 V 33 w(REENTRANT)f(directiv)m(e)h(\(as)g(can)f(b)s(e)g -(tested)h(with)f(the)227 5601 y(\014ts)p 354 5601 V 33 -w(is)p 448 5601 V 33 w(reen)m(tran)m(t)38 b(function\))f(di\013eren)m -(t)h(threads)f(can)g(call)i(an)m(y)e(of)h(the)f(CFITSIO)f(routines)h -(to)h(sim)m(ul-)227 5714 y(taneously)g(read)g(or)f(write)h(separate)h -(FITS)d(\014les.)62 b(Multiple)39 b(threads)e(can)h(also)g(read)f(data) -i(from)e(the)p eop end -%%Page: 27 35 -TeXDict begin 27 34 bop 0 299 a Fh(4.12.)73 b(WHEN)31 -b(THE)f(FINAL)g(SIZE)f(OF)i(THE)f(FITS)f(HDU)i(IS)f(UNKNO)m(WN)978 -b Fj(27)227 555 y(same)32 b(FITS)f(\014le)g(sim)m(ultaneously)-8 -b(,)33 b(as)f(long)g(as)f(the)h(\014le)f(w)m(as)h(op)s(ened)f(indep)s -(enden)m(tly)f(b)m(y)h(eac)m(h)i(thread.)227 668 y(This)g(relies)h(on)g -(the)f(op)s(erating)h(system)g(to)g(correctly)h(deal)g(with)e(reading)g -(the)h(same)g(\014le)g(b)m(y)f(m)m(ultiple)227 781 y(pro)s(cesses.)64 -b(Di\013eren)m(t)40 b(threads)e(should)f(not)i(share)f(the)g(same)h -('\014ts\014le')f(p)s(oin)m(ter)g(to)h(read)g(an)f(op)s(ened)227 -894 y(FITS)25 b(\014le,)i(unless)e(lo)s(c)m(ks)h(are)g(placed)g(around) -e(the)i(calls)g(to)g(the)g(CFITSIO)e(reading)i(routines.)39 -b(Di\013eren)m(t)227 1007 y(threads)30 b(should)g(nev)m(er)g(try)h(to)g -(write)f(to)h(the)g(same)g(FITS)e(\014le.)136 1203 y -Fc(\017)46 b Fj(Multiple)31 b(read)g(access)g(to)h(the)e(same)h(FITS)e -(\014le)i(within)f(a)h(single)g(program/thread)227 1357 -y(A)46 b(single)g(pro)s(cess)f(ma)m(y)h(op)s(en)f(the)g(same)h(FITS)f -(\014le)g(with)g(READONL)-8 b(Y)46 b(access)h(m)m(ultiple)f(times,)227 -1470 y(and)32 b(th)m(us)f(create)j(m)m(ultiple)f('\014ts\014le*')g(p)s -(oin)m(ters)f(to)g(that)h(same)g(\014le)f(within)f(CFITSIO.)g(This)g -(relies)i(on)227 1583 y(the)h(op)s(erating)g(system's)g(abilit)m(y)h -(to)g(op)s(en)e(a)h(single)g(\014le)g(m)m(ultiple)g(times)g(and)f -(correctly)i(manage)g(the)227 1696 y(subsequen)m(t)24 -b(read)g(requests)g(directed)g(to)h(the)f(di\013eren)m(t)h(C)f -('\014le*')h(p)s(oin)m(ters,)g(whic)m(h)f(actually)i(all)f(p)s(oin)m(t) -f(to)227 1809 y(the)32 b(same)h(\014le.)45 b(CFITSIO)30 -b(simply)i(executes)h(the)f(read)g(requests)g(to)g(the)g(di\013ernet)g -('\014ts\014le*')h(p)s(oin)m(ters)227 1922 y(the)e(same)g(as)f(if)h -(they)f(w)m(ere)h(ph)m(ysically)g(di\013eren)m(t)g(\014les.)136 -2118 y Fc(\017)46 b Fj(Multiple)31 b(write)g(access)h(to)f(the)f(same)h -(FITS)f(\014le)g(within)g(a)h(single)g(program/thread)227 -2272 y(CFITSIO)22 b(supp)s(orts)g(op)s(ening)h(the)g(same)h(FITS)f -(\014le)g(m)m(ultiple)i(times)f(with)f(WRITE)g(access,)j(but)d(it)h -(only)227 2385 y(ph)m(ysically)j(op)s(ens)f(the)g(\014le)h(\(at)g(the)g -(op)s(erating)f(system)h(lev)m(el\))h(once,)g(on)e(the)h(\014rst)e -(call)j(to)f(\014ts)p 3509 2385 28 4 v 32 w(op)s(en)p -3731 2385 V 33 w(\014le.)227 2498 y(If)38 b(\014ts)p -453 2498 V 32 w(op)s(en)p 675 2498 V 32 w(\014le)g(is)g(subsequen)m -(tly)f(called)i(to)g(op)s(en)e(the)h(same)g(\014le)g(again,)j(CFITSIO) -36 b(will)i(recognize)227 2611 y(that)c(the)f(\014le)g(is)g(already)g -(op)s(en,)h(and)e(will)h(return)f(a)h(new)g('\014ts\014le*')g(p)s(oin)m -(ter)g(that)h(logically)h(p)s(oin)m(ts)e(to)227 2724 -y(the)i(\014rst)e('\014ts\014le*')i(p)s(oin)m(ter,)h(without)e -(actually)i(op)s(ening)e(the)g(\014le)h(a)f(second)h(time.)53 -b(The)34 b(application)227 2837 y(program)39 b(can)g(then)g(treat)h -(the)f(2)g('\014ts\014le*')h(p)s(oin)m(ters)f(as)g(if)g(they)g(p)s(oin) -m(t)g(to)h(di\013eren)m(t)f(\014les,)i(and)e(can)227 -2950 y(seemingly)c(mo)m(v)m(e)g(to)g(and)e(write)h(data)h(to)g(2)f -(di\013eren)m(t)g(HDUs)h(within)e(the)h(same)g(\014le.)52 -b(Ho)m(w)m(ev)m(er,)37 b(eac)m(h)227 3063 y(time)31 b(the)g -(application)g(program)g(switc)m(hes)g(whic)m(h)f('\014ts\014le*')h(p)s -(oin)m(ter)f(it)h(is)f(writing)h(to,)g(CFITSIO)e(will)227 -3176 y(\015ush)24 b(an)m(y)i(in)m(ternal)g(bu\013ers)e(that)i(con)m -(tain)h(data)f(written)g(to)g(the)g(\014rst)e('\014ts\014le*')i(p)s -(oin)m(ter,)h(then)e(mo)m(v)m(e)i(to)227 3288 y(the)j(HDU)g(that)g(the) -g(other)f('\014ts\014le*')h(p)s(oin)m(ter)g(is)f(writing)h(to.)41 -b(Ob)m(viously)-8 b(,)30 b(this)f(ma)m(y)h(add)f(a)h(signi\014can)m(t) -227 3401 y(amoun)m(t)h(of)f(computational)i(o)m(v)m(erhead)f(if)f(the)g -(application)h(program)f(uses)g(this)g(feature)g(to)h(frequen)m(tly)227 -3514 y(switc)m(h)25 b(bac)m(k)h(and)e(forth)g(b)s(et)m(w)m(een)i -(writing)f(to)g(2)g(\(or)g(more\))g(HDUs)h(in)e(the)h(same)g(\014le,)h -(so)f(this)g(capabilit)m(y)227 3627 y(should)30 b(b)s(e)f(used)h -(judiciously)-8 b(.)227 3782 y(Note)26 b(that)f(CFITSIO)e(will)i(not)g -(allo)m(w)h(a)e(FITS)g(\014le)h(to)g(b)s(e)f(op)s(ened)g(a)g(second)h -(time)g(with)f(READ)m(WRITE)227 3895 y(access)32 b(if)e(it)h(w)m(as)g -(op)s(ened)f(previously)g(with)g(READONL)-8 b(Y)31 b(access.)0 -4238 y Ff(4.12)136 b(When)44 b(the)h(Final)h(Size)f(of)g(the)g(FITS)f -(HDU)h(is)g(Unkno)l(wn)0 4490 y Fj(It)27 b(is)h(not)f(required)f(to)i -(kno)m(w)f(the)h(total)h(size)f(of)f(a)h(FITS)e(data)i(arra)m(y)g(or)f -(table)h(b)s(efore)f(b)s(eginning)f(to)i(write)g(the)0 -4603 y(data)k(to)f(the)g(FITS)f(\014le.)43 b(In)30 b(the)h(case)h(of)f -(the)g(primary)f(arra)m(y)h(or)g(an)f(image)j(extension,)e(one)h -(should)d(initially)0 4716 y(create)i(the)e(arra)m(y)h(with)e(the)i -(size)g(of)f(the)g(highest)g(dimension)g(\(largest)i(NAXISn)d(k)m(eyw)m -(ord\))i(set)g(to)g(a)f(dumm)m(y)0 4829 y(v)-5 b(alue,)26 -b(suc)m(h)e(as)g(1.)39 b(Then)23 b(after)i(all)g(the)g(data)f(ha)m(v)m -(e)i(b)s(een)d(written)h(and)g(the)g(true)g(dimensions)g(are)g(kno)m -(wn,)h(then)0 4942 y(the)33 b(NAXISn)f(v)-5 b(alue)33 -b(should)f(b)s(e)g(up)s(dated)g(using)g(the)h(\014ts)p -2069 4942 V 33 w(up)s(date)p 2378 4942 V 32 w(k)m(ey)g(routine)g(b)s -(efore)g(mo)m(ving)g(to)h(another)0 5055 y(extension)d(or)f(closing)i -(the)e(FITS)g(\014le.)0 5215 y(When)f(writing)g(to)g(FITS)g(tables,)h -(CFITSIO)d(automatically)32 b(k)m(eeps)e(trac)m(k)g(of)f(the)g(highest) -h(ro)m(w)f(n)m(um)m(b)s(er)e(that)0 5328 y(is)32 b(written)g(to,)h(and) -e(will)h(increase)h(the)f(size)h(of)f(the)g(table)g(if)g(necessary)-8 -b(.)46 b(CFITSIO)30 b(will)i(also)h(automatically)0 5441 -y(insert)j(space)h(in)f(the)g(FITS)f(\014le)i(if)f(necessary)-8 -b(,)39 b(to)e(ensure)e(that)i(the)f(data)h('heap',)h(if)e(it)h(exists,) -h(and/or)f(an)m(y)0 5554 y(additional)29 b(HDUs)g(that)g(follo)m(w)g -(the)g(table)g(do)f(not)h(get)g(o)m(v)m(erwritten)h(as)e(new)g(ro)m(ws) -g(are)h(written)f(to)h(the)g(table.)0 5714 y(As)37 b(a)h(general)g -(rule)f(it)h(is)f(b)s(est)g(to)h(sp)s(ecify)f(the)h(initial)g(n)m(um)m -(b)s(er)e(of)i(ro)m(ws)f(=)g(0)g(when)g(the)g(table)h(is)g(created,)p -eop end -%%Page: 28 36 -TeXDict begin 28 35 bop 0 299 a Fj(28)1763 b Fh(CHAPTER)29 -b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Fj(then)38 -b(let)h(CFITSIO)e(k)m(eep)i(trac)m(k)g(of)g(the)f(n)m(um)m(b)s(er)f(of) -i(ro)m(ws)f(that)h(are)f(actually)i(written.)65 b(The)38 -b(application)0 668 y(program)e(should)f(not)i(man)m(ually)g(up)s(date) -e(the)i(n)m(um)m(b)s(er)e(of)h(ro)m(ws)g(in)g(the)h(table)g(\(as)g(giv) -m(en)g(b)m(y)f(the)h(NAXIS2)0 781 y(k)m(eyw)m(ord\))j(since)f(CFITSIO)e -(do)s(es)i(this)g(automatically)-8 b(.)69 b(If)38 b(a)i(table)f(is)g -(initially)i(created)f(with)e(more)h(than)0 894 y(zero)i(ro)m(ws,)j -(then)c(this)h(will)f(usually)h(b)s(e)f(considered)g(as)h(the)g(minim)m -(um)f(size)h(of)g(the)g(table,)j(ev)m(en)d(if)g(few)m(er)0 -1007 y(ro)m(ws)30 b(are)g(actually)h(written)f(to)h(the)f(table.)41 -b(Th)m(us,)30 b(if)f(a)i(table)f(is)g(initially)h(created)g(with)f -(NAXIS2)g(=)g(20,)h(and)0 1120 y(CFITSIO)g(only)i(writes)f(10)i(ro)m -(ws)e(of)h(data)g(b)s(efore)f(closing)i(the)f(table,)h(then)e(NAXIS2)h -(will)g(remain)f(equal)h(to)0 1233 y(20.)50 b(If)33 b(ho)m(w)m(ev)m -(er,)i(30)g(ro)m(ws)e(of)g(data)h(are)g(written)f(to)h(this)f(table,)i -(then)e(NAXIS2)h(will)f(b)s(e)g(increased)g(from)g(20)0 -1346 y(to)f(30.)44 b(The)31 b(one)g(exception)i(to)f(this)f(automatic)i -(up)s(dating)d(of)h(the)h(NAXIS2)f(k)m(eyw)m(ord)h(is)f(if)g(the)h -(application)0 1458 y(program)c(directly)g(mo)s(di\014es)f(the)i(v)-5 -b(alue)28 b(of)g(NAXIS2)g(\(up)f(or)h(do)m(wn\))g(itself)h(just)e(b)s -(efore)h(closing)h(the)f(table.)41 b(In)0 1571 y(this)28 -b(case,)i(CFITSIO)d(do)s(es)h(not)h(up)s(date)e(NAXIS2)i(again,)h -(since)f(it)g(assumes)f(that)h(the)f(application)i(program)0 -1684 y(m)m(ust)i(ha)m(v)m(e)h(had)f(a)g(go)s(o)s(d)g(reason)h(for)f(c)m -(hanging)h(the)f(v)-5 b(alue)33 b(directly)-8 b(.)47 -b(This)31 b(is)h(not)h(recommended,)f(ho)m(w)m(ev)m(er,)0 -1797 y(and)j(is)h(only)g(pro)m(vided)g(for)f(bac)m(kw)m(ard)h -(compatibilit)m(y)i(with)e(soft)m(w)m(are)h(that)g(initially)g(creates) -g(a)f(table)h(with)0 1910 y(a)d(large)h(n)m(um)m(b)s(er)e(of)h(ro)m -(ws,)h(than)f(decreases)g(the)h(NAXIS2)f(v)-5 b(alue)34 -b(to)h(the)f(actual)h(smaller)g(v)-5 b(alue)34 b(just)f(b)s(efore)0 -2023 y(closing)e(the)g(table.)0 2407 y Ff(4.13)136 b(CFITSIO)44 -b(Size)h(Limitations)0 2668 y Fj(CFITSIO)29 b(places)j(v)m(ery)f(few)g -(restrictions)g(on)g(the)g(size)g(of)g(FITS)f(\014les)h(that)g(it)h -(reads)e(or)h(writes.)42 b(There)30 b(are)i(a)0 2781 -y(few)e(limits,)h(ho)m(w)m(ev)m(er,)h(that)f(ma)m(y)g(a\013ect)h(some)f -(extreme)g(cases:)0 2941 y(1.)43 b(The)31 b(maxim)m(um)g(n)m(um)m(b)s -(er)f(of)h(FITS)f(\014les)h(that)h(ma)m(y)g(b)s(e)e(sim)m(ultaneously)i -(op)s(ened)f(b)m(y)g(CFITSIO)e(is)i(set)h(b)m(y)0 3054 -y(NMAXFILES,)e(as)f(de\014ned)f(in)h(\014tsio2.h.)41 -b(The)29 b(curren)m(t)g(default)g(v)-5 b(alue)30 b(is)f(1000,)j(but)c -(this)h(ma)m(y)h(b)s(e)f(increased)0 3167 y(if)40 b(necessary)-8 -b(.)72 b(Note)42 b(that)f(CFITSIO)e(allo)s(cates)j(NIOBUF)f(*)g(2880)h -(b)m(ytes)f(of)g(I/O)f(bu\013er)g(space)h(for)f(eac)m(h)0 -3279 y(\014le)d(that)h(is)f(op)s(ened.)61 b(The)37 b(default)g(v)-5 -b(alue)38 b(of)f(NIOBUF)h(is)f(40)h(\(de\014ned)f(in)f(\014tsio.h\),)k -(so)e(this)f(amoun)m(ts)g(to)0 3392 y(more)31 b(than)g(115K)i(of)e -(memory)g(for)g(eac)m(h)i(op)s(ened)d(\014le)i(\(or)f(115)i(MB)f(for)f -(1000)i(op)s(ened)d(\014les\).)44 b(Note)33 b(that)f(the)0 -3505 y(underlying)k(op)s(erating)i(system,)h(ma)m(y)e(ha)m(v)m(e)i(a)e -(lo)m(w)m(er)i(limit)f(on)f(the)g(n)m(um)m(b)s(er)f(of)h(\014les)g -(that)h(can)f(b)s(e)g(op)s(ened)0 3618 y(sim)m(ultaneously)-8 -b(.)0 3778 y(2.)67 b(It)40 b(used)e(to)i(b)s(e)e(common)i(for)f -(computer)g(systems)g(to)h(only)f(supp)s(ort)f(disk)g(\014les)h(up)f -(to)i(2**31)i(b)m(ytes)d(=)0 3891 y(2.1)k(GB)g(in)f(size,)47 -b(but)41 b(most)i(systems)f(no)m(w)g(supp)s(ort)f(larger)i(\014les.)76 -b(CFITSIO)41 b(can)i(optionally)g(read)g(and)0 4004 y(write)37 -b(these)h(so-called)h('large)f(\014les')g(that)f(are)h(greater)g(than)f -(2.1)h(GB)g(on)f(platforms)g(where)g(they)g(are)h(sup-)0 -4117 y(p)s(orted,)43 b(but)d(this)g(usually)h(requires)f(that)i(sp)s -(ecial)f(compiler)g(option)g(\015ags)g(b)s(e)f(sp)s(eci\014ed)g(to)i -(turn)d(on)i(this)0 4230 y(option.)69 b(On)39 b(lin)m(ux)h(and)f -(solaris)i(systems)f(the)g(compiler)g(\015ags)g(are)g('-D)p -2617 4230 28 4 v 34 w(LAR)m(GEFILE)p 3184 4230 V 33 w(SOUR)m(CE')f(and) -g(`-)0 4343 y(D)p 74 4343 V 33 w(FILE)p 318 4343 V 33 -w(OFFSET)p 719 4343 V 32 w(BITS=64'.)i(These)29 b(\015ags)h(ma)m(y)g -(also)h(w)m(ork)f(on)g(other)g(platforms)f(but)g(this)h(has)g(not)g(b)s -(een)0 4456 y(tested.)43 b(Starting)31 b(with)f(v)m(ersion)h(3.0)h(of)f -(CFITSIO,)f(the)h(default)f(Mak)m(e\014le)j(that)e(is)g(distributed)f -(with)g(CFIT-)0 4569 y(SIO)h(will)h(include)g(these)g(2)g(compiler)h -(\015ags)f(when)e(building)h(on)h(Solaris)g(and)g(Lin)m(ux)f(PC)g -(systems.)45 b(Users)32 b(on)0 4682 y(other)g(platforms)g(will)g(need)f -(to)i(add)e(these)h(compiler)h(\015ags)f(man)m(ually)g(if)g(they)g(w)m -(an)m(t)g(to)h(supp)s(ort)d(large)j(\014les.)0 4795 y(In)j(most)i -(cases)g(it)g(app)s(ears)e(that)i(it)g(is)f(not)h(necessary)f(to)h -(include)f(these)h(compiler)g(\015ags)f(when)f(compiling)0 -4907 y(application)c(co)s(de)e(that)h(call)h(the)e(CFITSIO)f(library)h -(routines.)0 5068 y(When)i(CFITSIO)e(is)i(built)g(with)g(large)h -(\014le)f(supp)s(ort)e(\(e.g.,)35 b(on)d(Solaris)g(and)f(Lin)m(ux)h(PC) -f(system)h(b)m(y)g(default\))0 5181 y(then)e(it)h(can)g(read)f(and)g -(write)g(FITS)g(data)h(\014les)f(on)h(disk)e(that)i(ha)m(v)m(e)h(an)m -(y)f(of)f(these)h(conditions:)136 5483 y Fc(\017)46 b -Fj(FITS)30 b(\014les)g(larger)h(than)f(2.1)i(GB)f(in)f(size)136 -5714 y Fc(\017)46 b Fj(FITS)30 b(images)h(con)m(taining)h(greater)g -(than)e(2.1)h(G)g(pixels)p eop end -%%Page: 29 37 -TeXDict begin 29 36 bop 0 299 a Fh(4.13.)73 b(CFITSIO)28 -b(SIZE)h(LIMIT)-8 b(A)g(TIONS)2300 b Fj(29)136 555 y -Fc(\017)46 b Fj(FITS)34 b(images)i(that)g(ha)m(v)m(e)g(one)f(dimension) -f(with)g(more)h(than)g(2.1)h(G)f(pixels)g(\(as)g(giv)m(en)h(b)m(y)f -(one)g(of)g(the)227 668 y(NAXISn)30 b(k)m(eyw)m(ord\))136 -856 y Fc(\017)46 b Fj(FITS)26 b(tables)h(con)m(taining)g(more)g(than)f -(2.1E09)i(ro)m(ws)e(\(giv)m(en)i(b)m(y)e(the)g(NAXIS2)h(k)m(eyw)m -(ord\),)h(or)e(with)g(ro)m(ws)227 969 y(that)31 b(are)g(more)g(than)f -(2.1)h(GB)g(wide)f(\(giv)m(en)i(b)m(y)e(the)h(NAXIS1)f(k)m(eyw)m(ord\)) -136 1156 y Fc(\017)46 b Fj(FITS)36 b(binary)f(tables)i(with)f(a)h(v)-5 -b(ariable-length)38 b(arra)m(y)f(heap)f(that)h(is)f(larger)h(than)f -(2.1)h(GB)g(\(giv)m(en)h(b)m(y)227 1269 y(the)31 b(PCOUNT)e(k)m(eyw)m -(ord\))0 1529 y(The)c(curren)m(t)g(maxim)m(um)g(FITS)f(\014le)h(size)h -(supp)s(orted)e(b)m(y)h(CFITSIO)e(is)j(ab)s(out)f(6)g(terab)m(ytes)i -(\(con)m(taining)g(2**31)0 1642 y(FITS)d(blo)s(c)m(ks,)i(eac)m(h)g -(2880)h(b)m(ytes)e(in)f(size\).)40 b(Curren)m(tly)-8 -b(,)26 b(supp)s(ort)d(for)i(large)g(\014les)g(in)g(CFITSIO)e(has)h(b)s -(een)g(tested)0 1755 y(on)30 b(the)h(Lin)m(ux,)f(Solaris,)h(and)f(IBM)g -(AIX)h(op)s(erating)g(systems.)0 1915 y(Note)26 b(that)f(when)e -(writing)h(application)i(programs)e(that)h(are)f(in)m(tended)g(to)h -(supp)s(ort)e(large)i(\014les)g(it)f(is)h(imp)s(ortan)m(t)0 -2028 y(to)31 b(use)g(64-bit)g(in)m(teger)h(v)-5 b(ariables)31 -b(to)h(store)f(quan)m(tities)h(suc)m(h)e(as)h(the)f(dimensions)g(of)h -(images,)h(or)f(the)f(n)m(um)m(b)s(er)0 2141 y(of)38 -b(ro)m(ws)f(in)h(a)g(table.)63 b(These)38 b(programs)f(m)m(ust)g(also)i -(call)g(the)f(sp)s(ecial)g(v)m(ersions)g(of)g(some)g(of)g(the)f -(CFITSIO)0 2254 y(routines)28 b(that)h(ha)m(v)m(e)h(b)s(een)d(adapted)i -(to)g(supp)s(ort)e(64-bit)i(in)m(tegers.)42 b(The)27 -b(names)i(of)f(these)h(routines)f(end)g(in)g('ll')0 2367 -y(\('el')k('el'\))g(to)f(distinguish)e(them)i(from)f(the)g(32-bit)i(in) -m(teger)g(v)m(ersion)e(\(e.g.,)j(\014ts)p 2766 2367 28 -4 v 32 w(get)p 2918 2367 V 34 w(n)m(um)p 3127 2367 V -32 w(ro)m(wsll\).)p eop end -%%Page: 30 38 -TeXDict begin 30 37 bop 0 299 a Fj(30)1763 b Fh(CHAPTER)29 -b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)p eop end -%%Page: 31 39 -TeXDict begin 31 38 bop 0 1225 a Fg(Chapter)65 b(5)0 -1687 y Fm(Basic)77 b(CFITSIO)f(In)-6 b(terface)77 b(Routines)0 -2180 y Fj(This)30 b(c)m(hapter)i(describ)s(es)e(the)i(basic)f(routines) -g(in)g(the)g(CFITSIO)e(user)i(in)m(terface)h(that)g(pro)m(vide)f(all)h -(the)g(func-)0 2293 y(tions)j(normally)g(needed)g(to)g(read)g(and)f -(write)h(most)h(FITS)e(\014les.)54 b(It)35 b(is)g(recommended)f(that)i -(these)f(routines)0 2406 y(b)s(e)d(used)g(for)g(most)h(applications)h -(and)e(that)h(the)f(more)h(adv)-5 b(anced)33 b(routines)f(describ)s(ed) -g(in)g(the)h(next)f(c)m(hapter)0 2518 y(only)e(b)s(e)g(used)g(in)g(sp)s -(ecial)h(circumstances)g(when)e(necessary)-8 b(.)0 2679 -y(The)30 b(follo)m(wing)i(con)m(v)m(en)m(tions)g(are)f(used)e(in)i -(this)f(c)m(hapter)h(in)f(the)g(description)h(of)f(eac)m(h)i(function:) -0 2839 y(1.)39 b(Most)25 b(functions)e(ha)m(v)m(e)i(2)f(names:)37 -b(a)24 b(long)h(descriptiv)m(e)f(name)g(and)f(a)i(short)e(concise)i -(name.)38 b(Both)25 b(names)f(are)0 2952 y(listed)g(on)f(the)g(\014rst) -f(line)i(of)f(the)h(follo)m(wing)g(descriptions,)h(separated)e(b)m(y)h -(a)f(slash)g(\(/\))h(c)m(haracter.)40 b(Programmers)0 -3065 y(ma)m(y)27 b(use)g(either)g(name)g(in)f(their)h(programs)g(but)f -(the)h(long)g(names)g(are)g(recommended)f(to)i(help)e(do)s(cumen)m(t)h -(the)0 3177 y(co)s(de)k(and)e(mak)m(e)j(it)f(easier)g(to)g(read.)0 -3338 y(2.)42 b(A)30 b(righ)m(t)h(arro)m(w)g(sym)m(b)s(ol)f(\()p -Fb(>)p Fj(\))h(is)g(used)f(in)g(the)h(function)f(descriptions)g(to)i -(separate)f(the)g(input)f(parameters)0 3451 y(from)j(the)g(output)f -(parameters)i(in)f(the)g(de\014nition)g(of)g(eac)m(h)h(routine.)49 -b(This)32 b(sym)m(b)s(ol)h(is)g(not)g(actually)i(part)e(of)0 -3563 y(the)e(C)f(calling)h(sequence.)0 3724 y(3.)41 b(The)30 -b(function)g(parameters)h(are)g(de\014ned)e(in)h(more)g(detail)i(in)e -(the)g(alphab)s(etical)i(listing)f(in)f(App)s(endix)f(B.)0 -3884 y(4.)39 b(The)23 b(\014rst)g(argumen)m(t)g(in)h(almost)g(all)h -(the)e(functions)g(is)h(a)g(p)s(oin)m(ter)f(to)h(a)g(structure)f(of)h -(t)m(yp)s(e)g(`\014ts\014le'.)38 b(Memory)0 3997 y(for)26 -b(this)g(structure)f(is)h(allo)s(cated)i(b)m(y)e(CFITSIO)e(when)h(the)h -(FITS)g(\014le)g(is)g(\014rst)f(op)s(ened)g(or)h(created)h(and)e(is)h -(freed)0 4110 y(when)j(the)i(FITS)f(\014le)g(is)g(closed.)0 -4270 y(5.)53 b(The)34 b(last)h(argumen)m(t)f(in)g(almost)i(all)f(the)f -(functions)g(is)g(the)h(error)f(status)g(parameter.)53 -b(It)35 b(m)m(ust)f(b)s(e)f(equal)0 4383 y(to)k(0)g(on)f(input,)h -(otherwise)g(the)f(function)g(will)h(immediately)g(exit)g(without)g -(doing)f(an)m(ything.)59 b(A)36 b(non-zero)0 4496 y(output)27 -b(v)-5 b(alue)27 b(indicates)i(that)e(an)g(error)g(o)s(ccurred)g(in)g -(the)g(function.)39 b(In)27 b(most)g(cases)h(the)g(status)f(v)-5 -b(alue)28 b(is)f(also)0 4608 y(returned)i(as)i(the)f(v)-5 -b(alue)31 b(of)g(the)f(function)g(itself.)0 4935 y Ff(5.1)135 -b(CFITSIO)44 b(Error)h(Status)h(Routines)0 5168 y Fi(1)81 -b Fj(Return)27 b(a)j(descriptiv)m(e)f(text)h(string)e(\(30)i(c)m(har)f -(max.\))41 b(corresp)s(onding)28 b(to)h(a)g(CFITSIO)e(error)h(status)h -(co)s(de.)95 5385 y Fe(void)47 b(fits_get_errstatus)c(/)k(ffgerr)f -(\(int)h(status,)f(>)h(char)g(*err_text\))0 5601 y Fi(2)81 -b Fj(Return)35 b(the)h(top)g(\(oldest\))h(80-c)m(haracter)i(error)c -(message)i(from)e(the)h(in)m(ternal)h(CFITSIO)d(stac)m(k)j(of)f(error) -227 5714 y(messages)45 b(and)e(shift)h(an)m(y)g(remaining)g(messages)h -(on)f(the)g(stac)m(k)h(up)e(one)h(lev)m(el.)83 b(Call)44 -b(this)g(routine)1905 5942 y(31)p eop end -%%Page: 32 40 -TeXDict begin 32 39 bop 0 299 a Fj(32)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)227 555 y Fj(rep)s(eatedly)c(to)h(get)g(eac)m(h)g -(message)f(in)g(sequence.)39 b(The)26 b(function)f(returns)g(a)h(v)-5 -b(alue)26 b(=)f(0)h(and)g(a)g(n)m(ull)f(error)227 668 -y(message)32 b(when)d(the)i(error)f(stac)m(k)i(is)e(empt)m(y)-8 -b(.)95 940 y Fe(int)47 b(fits_read_errmsg)d(/)j(ffgmsg)f(\(char)h -(*err_msg\))0 1211 y Fi(3)81 b Fj(Prin)m(t)30 b(out)h(the)g(error)f -(message)i(corresp)s(onding)e(to)h(the)g(input)f(status)h(v)-5 -b(alue)31 b(and)f(all)i(the)f(error)f(messages)227 1324 -y(on)d(the)h(CFITSIO)e(stac)m(k)j(to)f(the)f(sp)s(eci\014ed)g(\014le)g -(stream)h(\(normally)g(to)g(stdout)f(or)g(stderr\).)40 -b(If)26 b(the)i(input)227 1437 y(status)j(v)-5 b(alue)31 -b(=)f(0)h(then)f(this)g(routine)g(do)s(es)g(nothing.)95 -1709 y Fe(void)47 b(fits_report_error)c(/)48 b(ffrprt)e(\(FILE)g -(*stream,)g(status\))0 1981 y Fi(4)81 b Fj(The)44 b(\014ts)p -461 1981 28 4 v 32 w(write)p 695 1981 V 33 w(errmark)g(routine)h(puts)f -(an)h(in)m(visible)g(mark)m(er)g(on)g(the)g(CFITSIO)e(error)h(stac)m -(k.)85 b(The)227 2094 y(\014ts)p 354 2094 V 33 w(clear)p -573 2094 V 34 w(errmark)31 b(routine)i(can)g(then)f(b)s(e)f(used)h(to)h -(delete)h(an)m(y)f(more)f(recen)m(t)i(error)e(messages)h(on)g(the)227 -2207 y(stac)m(k,)42 b(bac)m(k)c(to)g(the)g(p)s(osition)g(of)g(the)g -(mark)m(er.)63 b(This)37 b(preserv)m(es)g(an)m(y)h(older)g(error)f -(messages)i(on)f(the)227 2319 y(stac)m(k.)77 b(The)41 -b(\014ts)p 855 2319 V 32 w(clear)p 1073 2319 V 34 w(errmsg)g(routine)h -(simply)f(clears)i(all)g(the)f(messages)g(\(and)g(marks\))f(from)h(the) -227 2432 y(stac)m(k.)g(These)31 b(routines)f(are)h(called)g(without)g -(an)m(y)f(argumen)m(ts.)95 2704 y Fe(void)47 b(fits_write_errmark)c(/)k -(ffpmrk)f(\(void\))95 2817 y(void)h(fits_clear_errmark)c(/)k(ffcmrk)f -(\(void\))95 2930 y(void)h(fits_clear_errmsg)c(/)48 b(ffcmsg)e -(\(void\))0 3278 y Ff(5.2)135 b(FITS)44 b(File)i(Access)e(Routines)0 -3527 y Fi(1)81 b Fj(Op)s(en)29 b(an)h(existing)h(data)g(\014le.)227 -3794 y Fe(int)47 b(fits_open_file)d(/)k(ffopen)418 3907 -y(\(fitsfile)d(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h(int)g -(*status\))227 4133 y(int)g(fits_open_diskfile)c(/)k(ffdkopen)418 -4246 y(\(fitsfile)e(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h -(int)g(*status\))227 4472 y(int)g(fits_open_data)d(/)k(ffdopn)418 -4585 y(\(fitsfile)d(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h -(int)g(*status\))227 4811 y(int)g(fits_open_table)d(/)j(fftopn)418 -4924 y(\(fitsfile)e(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h -(int)g(*status\))227 5149 y(int)g(fits_open_image)d(/)j(ffiopn)418 -5262 y(\(fitsfile)e(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h -(int)g(*status\))227 5488 y(int)g(fits_open_extlist)c(/)48 -b(ffeopn)418 5601 y(\(fitsfile)d(**fptr,)h(char)h(*filename,)e(int)i -(iomode,)f(char)g(*extlist,)418 5714 y(>)95 b(int)47 -b(*hdutype,)f(int)g(*status\))p eop end -%%Page: 33 41 -TeXDict begin 33 40 bop 0 299 a Fh(5.2.)72 b(FITS)30 -b(FILE)g(A)m(CCESS)f(R)m(OUTINES)2244 b Fj(33)227 555 -y(The)41 b(iomo)s(de)h(parameter)g(determines)g(the)f(read/write)h -(access)h(allo)m(w)m(ed)h(in)d(the)g(\014le)h(and)f(can)h(ha)m(v)m(e) -227 668 y(v)-5 b(alues)32 b(of)g(READONL)-8 b(Y)32 b(\(0\))g(or)g(READ) -m(WRITE)g(\(1\).)44 b(The)31 b(\014lename)h(parameter)g(giv)m(es)h(the) -e(name)h(of)227 781 y(the)f(\014le)g(to)g(b)s(e)f(op)s(ened,)h(follo)m -(w)m(ed)h(b)m(y)f(an)f(optional)i(argumen)m(t)f(giving)h(the)f(name)f -(or)h(index)f(n)m(um)m(b)s(er)g(of)227 894 y(the)d(extension)g(within)g -(the)f(FITS)g(\014le)h(that)g(should)f(b)s(e)g(mo)m(v)m(ed)i(to)f(and)f -(op)s(ened)g(\(e.g.,)k Fe(myfile.fits+3)227 1007 y Fj(or)36 -b Fe(myfile.fits[3])d Fj(mo)m(v)m(es)k(to)g(the)g(3rd)f(extension)g -(within)g(the)h(\014le,)h(and)d Fe(myfile.fits[events])227 -1120 y Fj(mo)m(v)m(es)d(to)f(the)g(extension)g(with)f(the)g(k)m(eyw)m -(ord)h(EXTNAME)g(=)f('EVENTS'\).)227 1285 y(The)37 b(\014ts)p -548 1285 28 4 v 32 w(op)s(en)p 770 1285 V 32 w(disk\014le)g(routine)g -(is)g(similar)g(to)h(the)f(\014ts)p 2241 1285 V 33 w(op)s(en)p -2464 1285 V 32 w(\014le)g(routine)g(except)h(that)f(it)h(do)s(es)f(not) -227 1398 y(supp)s(ort)22 b(the)h(extended)h(\014lename)f(syn)m(tax)h -(in)f(the)h(input)e(\014le)i(name.)38 b(This)23 b(routine)g(simply)g -(tries)h(to)g(op)s(en)227 1511 y(the)36 b(sp)s(eci\014ed)e(input)h -(\014le)g(on)g(magnetic)i(disk.)55 b(This)34 b(routine)h(is)h(mainly)f -(for)g(use)g(in)g(cases)h(where)f(the)227 1623 y(\014lename)f(\(or)h -(directory)f(path\))g(con)m(tains)h(square)f(or)g(curly)f(brac)m(k)m -(et)j(c)m(haracters)f(that)f(w)m(ould)g(confuse)227 1736 -y(the)d(extended)f(\014lename)h(parser.)227 1901 y(The)i(\014ts)p -544 1901 V 32 w(op)s(en)p 766 1901 V 32 w(data)h(routine)e(is)h -(similar)g(to)h(the)f(\014ts)p 2113 1901 V 32 w(op)s(en)p -2335 1901 V 33 w(\014le)f(routine)h(except)h(that)f(it)h(will)f(mo)m(v) -m(e)h(to)227 2014 y(the)23 b(\014rst)f(HDU)h(con)m(taining)h -(signi\014can)m(t)f(data,)i(if)e(a)g(HDU)g(name)f(or)h(n)m(um)m(b)s(er) -e(to)i(op)s(en)f(w)m(as)h(not)f(explicitly)227 2127 y(sp)s(eci\014ed)37 -b(as)g(part)h(of)f(the)h(\014lename.)61 b(In)37 b(this)g(case,)j(it)e -(will)g(lo)s(ok)g(for)f(the)g(\014rst)g(IMA)m(GE)h(HDU)g(with)227 -2240 y(NAXIS)29 b(greater)h(than)e(0,)i(or)f(the)f(\014rst)g(table)i -(that)f(do)s(es)g(not)g(con)m(tain)h(the)f(strings)f(`GTI')h(\(Go)s(o)s -(d)g(Time)227 2353 y(In)m(terv)-5 b(al)31 b(extension\))h(or)e(`OBST)-8 -b(ABLE')31 b(in)f(the)h(EXTNAME)f(k)m(eyw)m(ord)h(v)-5 -b(alue.)227 2518 y(The)25 b(\014ts)p 536 2518 V 32 w(op)s(en)p -758 2518 V 32 w(table)h(and)e(\014ts)p 1305 2518 V 33 -w(op)s(en)p 1528 2518 V 32 w(image)i(routines)f(are)g(similar)h(to)f -(\014ts)p 2828 2518 V 33 w(op)s(en)p 3051 2518 V 32 w(data)h(except)f -(they)h(will)227 2631 y(mo)m(v)m(e)h(to)g(the)f(\014rst)f(signi\014can) -m(t)h(table)h(HDU)f(or)g(image)h(HDU)f(in)f(the)h(\014le,)h(resp)s -(ectiv)m(ely)-8 b(,)29 b(if)c(a)h(HDU)h(name)227 2744 -y(or)k(n)m(um)m(b)s(er)e(is)h(not)h(sp)s(eci\014ed)e(as)i(part)f(of)h -(the)f(\014lename.)227 2909 y(The)40 b(\014ts)p 551 2909 -V 33 w(op)s(en)p 774 2909 V 32 w(extname)h(routine)g(op)s(ens)f(the)h -(\014le)g(and)f(attempts)h(to)h(mo)m(v)m(e)g(to)f(a)g('useful')g(HDU.)g -(If)227 3022 y(after)28 b(op)s(ening)f(the)h(\014le)f(CFITSIO)f(is)h(p) -s(oin)m(ting)h(to)g(n)m(ull)f(primary)g(arra)m(y)-8 b(,)29 -b(then)e(CFITSIO)f(will)i(attempt)227 3135 y(to)38 b(mo)m(v)m(e)g(to)f -(the)g(\014rst)f(extension)h(that)g(has)f(an)h(EXTNAME)g(or)f(HDUNAME)i -(k)m(eyw)m(ord)f(v)-5 b(alue)37 b(that)227 3247 y(matc)m(hes)28 -b(one)f(of)g(the)g(names)f(in)h(the)g(input)f(extlist)i -(space-delimited)g(list)f(of)g(names.)39 b(If)27 b(that)g(fails,)h -(then)227 3360 y(CFITSIO)h(simply)h(mo)m(v)m(es)i(to)f(the)f(2nd)g(HDU) -h(in)f(the)h(\014le.)227 3525 y(IRAF)26 b(images)g(\(.imh)g(format)g -(\014les\))f(and)g(ra)m(w)h(binary)e(data)j(arra)m(ys)e(ma)m(y)h(also)h -(b)s(e)e(op)s(ened)f(with)h(READ-)227 3638 y(ONL)-8 b(Y)37 -b(access.)60 b(CFITSIO)35 b(will)i(automatically)i(test)f(if)e(the)h -(input)e(\014le)i(is)f(an)h(IRAF)f(image,)k(and)c(if,)227 -3751 y(so)c(will)g(con)m(v)m(ert)h(it)f(on)f(the)h(\015y)f(in)m(to)i(a) -f(virtual)f(FITS)g(image)i(b)s(efore)e(it)h(is)g(op)s(ened)e(b)m(y)i -(the)g(application)227 3864 y(program.)64 b(If)37 b(the)h(input)g -(\014le)g(is)g(a)g(ra)m(w)g(binary)g(data)g(arra)m(y)h(of)f(n)m(um)m(b) -s(ers,)h(then)e(the)i(data)f(t)m(yp)s(e)h(and)227 3977 -y(dimensions)d(of)g(the)g(arra)m(y)h(m)m(ust)f(b)s(e)f(sp)s(eci\014ed)g -(in)h(square)g(brac)m(k)m(ets)h(follo)m(wing)h(the)e(name)g(of)h(the)f -(\014le)227 4090 y(\(e.g.)56 b('ra)m(w\014le.dat[i512,512]')40 -b(op)s(ens)34 b(a)i(512)g(x)f(512)h(short)e(in)m(teger)j(image\).)56 -b(See)35 b(the)g(`Extended)g(File)227 4203 y(Name)k(Syn)m(tax')g(c)m -(hapter)g(for)e(more)i(details)g(on)f(ho)m(w)g(to)h(sp)s(ecify)f(the)g -(ra)m(w)h(\014le)f(name.)64 b(The)38 b(ra)m(w)g(\014le)227 -4316 y(is)k(con)m(v)m(erted)g(on)f(the)h(\015y)f(in)m(to)h(a)f(virtual) -h(FITS)e(image)j(in)e(memory)g(that)h(is)f(then)g(op)s(ened)g(b)m(y)g -(the)227 4429 y(application)32 b(program)e(with)g(READONL)-8 -b(Y)31 b(access.)227 4594 y(Programs)g(can)g(read)f(the)h(input)e -(\014le)i(from)f(the)h('stdin')f(\014le)h(stream)g(if)f(a)h(dash)f(c)m -(haracter)i(\('-'\))g(is)f(giv)m(en)227 4706 y(as)e(the)f(\014lename.) -40 b(Files)30 b(can)e(also)h(b)s(e)f(op)s(ened)f(o)m(v)m(er)j(the)e -(net)m(w)m(ork)h(using)f(FTP)g(or)g(HTTP)g(proto)s(cols)h(b)m(y)227 -4819 y(supplying)g(the)i(appropriate)f(URL)h(as)f(the)h(\014lename.)227 -4984 y(The)43 b(input)f(\014le)h(can)h(b)s(e)f(mo)s(di\014ed)f(in)g(v) --5 b(arious)44 b(w)m(a)m(ys)g(to)g(create)g(a)g(virtual)f(\014le)h -(\(usually)f(stored)g(in)227 5097 y(memory\))31 b(that)g(is)g(then)f -(op)s(ened)f(b)m(y)i(the)f(application)i(program)e(b)m(y)h(supplying)e -(a)i(\014ltering)g(or)f(binning)227 5210 y(sp)s(eci\014er)e(in)g -(square)g(brac)m(k)m(ets)h(follo)m(wing)h(the)e(\014lename.)40 -b(Some)29 b(of)f(the)g(more)h(common)f(\014ltering)h(meth-)227 -5323 y(o)s(ds)j(are)h(illustrated)h(in)e(the)h(follo)m(wing)i -(paragraphs,)e(but)f(users)g(should)f(refer)i(to)g(the)g('Extended)g -(File)227 5436 y(Name)e(Syn)m(tax')g(c)m(hapter)g(for)f(a)h(complete)h -(description)e(of)h(the)f(full)h(\014le)f(\014ltering)h(syn)m(tax.)227 -5601 y(When)c(op)s(ening)f(an)h(image,)h(a)g(rectangular)f(subset)f(of) -h(the)g(ph)m(ysical)g(image)h(ma)m(y)g(b)s(e)e(op)s(ened)f(b)m(y)i -(listing)227 5714 y(the)k(\014rst)e(and)h(last)h(pixel)g(in)f(eac)m(h)i -(dimension)e(\(and)g(optional)h(pixel)g(skipping)f(factor\):)p -eop end -%%Page: 34 42 -TeXDict begin 34 41 bop 0 299 a Fj(34)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)227 555 y Fe(myimage.fits[101:200,301:)o(400])227 -807 y Fj(will)g(create)h(and)e(op)s(en)f(a)i(100x100)i(pixel)e(virtual) -g(image)g(of)g(that)g(section)g(of)g(the)f(ph)m(ysical)h(image,)i(and) -227 920 y Fe(myimage.fits[*,-*])c Fj(op)s(ens)k(a)h(virtual)g(image)h -(that)f(is)g(the)g(same)g(size)h(as)e(the)h(ph)m(ysical)h(image)g(but) -227 1033 y(has)c(b)s(een)g(\015ipp)s(ed)f(in)h(the)g(v)m(ertical)j -(direction.)227 1184 y(When)28 b(op)s(ening)g(a)g(table,)i(the)e -(\014ltering)g(syn)m(tax)h(can)f(b)s(e)f(used)h(to)g(add)g(or)g(delete) -h(columns)f(or)g(k)m(eyw)m(ords)227 1297 y(in)g(the)g(virtual)h(table:) -40 b Fe(myfile.fits[events][col)i(!time;)k(PI)h(=)h(PHA*1.2])26 -b Fj(op)s(ens)h(a)h(virtual)h(ta-)227 1410 y(ble)j(in)f(whic)m(h)g(the) -h(TIME)f(column)g(has)g(b)s(een)g(deleted)h(and)f(a)g(new)g(PI)g -(column)h(has)f(b)s(een)g(added)f(with)227 1523 y(a)41 -b(v)-5 b(alue)40 b(1.2)i(times)e(that)h(of)f(the)h(PHA)f(column.)70 -b(Similarly)-8 b(,)43 b(one)e(can)f(\014lter)h(a)f(table)h(to)g(k)m -(eep)g(only)227 1635 y(those)35 b(ro)m(ws)e(that)i(satisfy)f(a)g -(selection)i(criterion:)48 b Fe(myfile.fits[events][pha)42 -b(>)47 b(50])33 b Fj(creates)j(and)227 1748 y(op)s(ens)31 -b(a)g(virtual)h(table)g(con)m(taining)h(only)e(those)h(ro)m(ws)f(with)g -(a)g(PHA)h(v)-5 b(alue)31 b(greater)i(than)e(50.)44 b(A)31 -b(large)227 1861 y(n)m(um)m(b)s(er)d(of)h(b)s(o)s(olean)h(and)e -(mathematical)k(op)s(erators)d(can)g(b)s(e)g(used)f(in)h(the)g -(selection)i(expression.)40 b(One)227 1974 y(can)25 b(also)g(\014lter)g -(table)g(ro)m(ws)f(using)g('Go)s(o)s(d)h(Time)f(In)m(terv)-5 -b(al')26 b(extensions,)g(and)e(spatial)h(region)g(\014lters)g(as)f(in) -227 2087 y Fe(myfile.fits[events][gtifi)o(lter)o(\(\)])14 -b Fj(and)19 b Fe(myfile.fits[events][regfil)o(ter)o(\()42 -b("stars.rng"\)])p Fj(.)227 2238 y(Finally)-8 b(,)34 -b(table)e(columns)f(ma)m(y)h(b)s(e)f(binned)f(or)h(histogrammed)h(to)g -(generate)h(a)e(virtual)h(image.)45 b(F)-8 b(or)32 b(ex-)227 -2351 y(ample,)d Fe(myfile.fits[events][bin)41 b(\(X,Y\)=4])26 -b Fj(will)h(result)h(in)f(a)h(2-dimensional)g(image)h(calculated)227 -2464 y(b)m(y)35 b(binning)e(the)i(X)f(and)g(Y)h(columns)f(in)g(the)h -(ev)m(en)m(t)h(table)f(with)f(a)h(bin)f(size)h(of)g(4)f(in)h(eac)m(h)g -(dimension.)227 2577 y(The)30 b(TLMINn)g(and)f(TLMAXn)h(k)m(eyw)m(ords) -h(will)g(b)s(e)e(used)h(b)m(y)g(default)h(to)g(determine)f(the)h(range) -f(of)h(the)227 2690 y(image.)227 2841 y(A)j(single)g(program)f(can)g -(op)s(en)g(the)h(same)f(FITS)g(\014le)g(more)h(than)f(once)h(and)f -(then)g(treat)h(the)g(resulting)227 2954 y(\014ts\014le)c(p)s(oin)m -(ters)g(as)g(though)g(they)g(w)m(ere)h(completely)h(indep)s(enden)m(t)d -(FITS)g(\014les.)40 b(Using)31 b(this)f(facilit)m(y)-8 -b(,)33 b(a)227 3066 y(program)f(can)f(op)s(en)g(a)h(FITS)f(\014le)g(t)m -(wice,)j(mo)m(v)m(e)f(to)f(2)g(di\013eren)m(t)g(extensions)g(within)f -(the)g(\014le,)h(and)f(then)227 3179 y(read)g(and)e(write)i(data)g(in)f -(those)h(extensions)g(in)f(an)m(y)h(order.)0 3440 y Fi(2)81 -b Fj(Create)31 b(and)f(op)s(en)f(a)i(new)f(empt)m(y)h(output)f(FITS)f -(\014le.)227 3692 y Fe(int)47 b(fits_create_file)d(/)j(ffinit)418 -3805 y(\(fitsfile)e(**fptr,)h(char)h(*filename,)e(>)i(int)g(*status\)) -227 4031 y(int)g(fits_create_diskfile)42 b(/)48 b(ffdkinit)418 -4144 y(\(fitsfile)d(**fptr,)h(char)h(*filename,)e(>)i(int)g(*status\)) -227 4396 y Fj(An)36 b(error)h(will)g(b)s(e)f(returned)f(if)h(the)h(sp)s -(eci\014ed)f(\014le)h(already)g(exists,)i(unless)d(the)h(\014lename)f -(is)h(pre\014xed)227 4509 y(with)30 b(an)g(exclamation)i(p)s(oin)m(t)e -(\(!\).)42 b(In)29 b(that)i(case)g(CFITSIO)d(will)j(o)m(v)m(erwrite)g -(\(delete\))h(an)m(y)f(existing)g(\014le)227 4622 y(with)36 -b(the)g(same)h(name.)57 b(Note)38 b(that)e(the)h(exclamation)h(p)s(oin) -m(t)e(is)g(a)h(sp)s(ecial)f(UNIX)g(c)m(haracter)i(so)e(if)g(it)227 -4735 y(is)d(used)e(on)h(the)h(command)f(line)h(it)g(m)m(ust)f(b)s(e)g -(preceded)g(b)m(y)g(a)g(bac)m(kslash)h(to)h(force)e(the)h(UNIX)g(shell) -f(to)227 4847 y(accept)g(the)f(c)m(haracter)h(as)e(part)g(of)h(the)g -(\014lename.)227 4998 y(The)26 b(output)h(\014le)g(will)g(b)s(e)f -(written)h(to)g(the)g('stdout')g(\014le)g(stream)g(if)g(a)g(dash)f(c)m -(haracter)i(\('-'\))g(or)f(the)g(string)227 5111 y('stdout')34 -b(is)f(giv)m(en)h(as)g(the)f(\014lename.)49 b(Similarly)-8 -b(,)35 b('-.gz')g(or)e('stdout.gz')i(will)f(cause)f(the)h(\014le)f(to)h -(b)s(e)e(gzip)227 5224 y(compressed)e(b)s(efore)g(it)h(is)g(written)f -(out)h(to)g(the)f(stdout)h(stream.)227 5375 y(Optionally)-8 -b(,)41 b(the)c(name)h(of)f(a)h(template)h(\014le)e(that)h(is)f(used)g -(to)h(de\014ne)f(the)g(structure)g(of)g(the)h(new)f(\014le)227 -5488 y(ma)m(y)i(b)s(e)f(sp)s(eci\014ed)f(in)h(paren)m(theses)h(follo)m -(wing)g(the)g(output)e(\014le)i(name.)64 b(The)38 b(template)h(\014le)g -(ma)m(y)g(b)s(e)227 5601 y(another)32 b(FITS)e(\014le,)i(in)f(whic)m(h) -g(case)i(the)e(new)g(\014le,)h(at)g(the)g(time)g(it)f(is)h(op)s(ened,)f -(will)g(b)s(e)g(an)g(exact)i(cop)m(y)227 5714 y(of)38 -b(the)g(template)i(\014le)e(except)g(that)h(the)f(data)g(structures)g -(\(images)h(and)e(tables\))i(will)f(b)s(e)g(\014lled)f(with)p -eop end -%%Page: 35 43 -TeXDict begin 35 42 bop 0 299 a Fh(5.3.)72 b(HDU)31 b(A)m(CCESS)e(R)m -(OUTINES)2488 b Fj(35)227 555 y(zeros.)41 b(Alternativ)m(ely)-8 -b(,)32 b(the)d(template)i(\014le)e(ma)m(y)g(b)s(e)f(an)h(ASCI)s(I)e -(format)i(text)h(\014le)f(con)m(taining)i(directiv)m(es)227 -668 y(that)e(de\014ne)e(the)h(k)m(eyw)m(ords)g(to)g(b)s(e)g(created)h -(in)e(eac)m(h)i(HDU)g(of)f(the)g(\014le.)40 b(See)28 -b(the)g('Extended)f(File)i(Name)227 781 y(Syn)m(tax')i(section)h(for)e -(a)h(complete)g(description)g(of)f(the)h(template)h(\014le)e(syn)m -(tax.)227 930 y(The)f(\014ts)p 540 930 28 4 v 33 w(create)p -809 930 V 34 w(disk\014le)g(routine)h(is)g(similar)g(to)g(the)g(\014ts) -p 2238 930 V 32 w(create)p 2506 930 V 34 w(\014le)g(routine)g(except)g -(that)g(it)g(do)s(es)g(not)227 1043 y(supp)s(ort)36 b(the)i(extended)g -(\014lename)g(syn)m(tax)g(in)g(the)g(input)f(\014le)h(name.)63 -b(This)37 b(routine)h(simply)f(tries)h(to)227 1156 y(create)e(the)e(sp) -s(eci\014ed)f(\014le)h(on)f(magnetic)j(disk.)50 b(This)33 -b(routine)h(is)g(mainly)g(for)g(use)f(in)h(cases)g(where)g(the)227 -1269 y(\014lename)g(\(or)h(directory)f(path\))g(con)m(tains)h(square)f -(or)g(curly)f(brac)m(k)m(et)j(c)m(haracters)f(that)f(w)m(ould)g -(confuse)227 1382 y(the)d(extended)f(\014lename)h(parser.)0 -1635 y Fi(3)81 b Fj(Close)28 b(a)f(previously)g(op)s(ened)g(FITS)g -(\014le.)40 b(The)27 b(\014rst)f(routine)i(simply)f(closes)h(the)g -(\014le,)g(whereas)f(the)h(second)227 1748 y(one)g(also)h(DELETES)e -(the)g(\014le,)i(whic)m(h)e(can)h(b)s(e)g(useful)e(in)i(cases)g(where)g -(a)g(FITS)f(\014le)g(has)h(b)s(een)f(partially)227 1861 -y(created,)37 b(but)c(then)h(an)h(error)e(o)s(ccurs)h(whic)m(h)g(prev)m -(en)m(ts)h(it)g(from)f(b)s(eing)g(completed.)53 b(Note)36 -b(that)e(these)227 1974 y(routines)23 b(b)s(eha)m(v)m(e)g(di\013eren)m -(tly)h(than)e(most)h(other)g(CFITSIO)e(routines)i(if)f(the)h(input)f(v) --5 b(alue)23 b(of)g(the)g(`status')227 2086 y(parameter)43 -b(is)f(not)h(zero:)65 b(Instead)42 b(of)h(simply)f(returning)f(to)i -(the)g(calling)g(program)g(without)f(doing)227 2199 y(an)m(ything,)30 -b(these)f(routines)f(e\013ectiv)m(ely)k(ignore)d(the)f(input)g(status)h -(v)-5 b(alue)29 b(and)f(still)h(attempt)h(to)f(close)h(or)227 -2312 y(delete)i(the)e(\014le.)95 2565 y Fe(int)47 b(fits_close_file)d -(/)j(ffclos)g(\(fitsfile)e(*fptr,)h(>)h(int)g(*status\))95 -2791 y(int)g(fits_delete_file)d(/)j(ffdelt)f(\(fitsfile)g(*fptr,)g(>)h -(int)g(*status\))0 3044 y Fi(4)81 b Fj(Return)21 b(the)i(name,)h(I/O)e -(mo)s(de)g(\(READONL)-8 b(Y)24 b(or)e(READ)m(WRITE\),)i(and/or)e(the)g -(\014le)h(t)m(yp)s(e)f(\(e.g.)40 b('\014le://',)227 3157 -y('ftp://'\))32 b(of)f(the)f(op)s(ened)g(FITS)g(\014le.)95 -3410 y Fe(int)47 b(fits_file_name)d(/)k(ffflnm)e(\(fitsfile)f(*fptr,)h -(>)i(char)e(*filename,)f(int)i(*status\))95 3636 y(int)g -(fits_file_mode)d(/)k(ffflmd)e(\(fitsfile)f(*fptr,)h(>)i(int)f -(*iomode,)e(int)i(*status\))95 3862 y(int)g(fits_url_type)e(/)i(ffurlt) -f(\(fitsfile)f(*fptr,)h(>)i(char)f(*urltype,)e(int)i(*status\))0 -4194 y Ff(5.3)135 b(HDU)46 b(Access)e(Routines)0 4445 -y Fj(The)30 b(follo)m(wing)i(functions)e(p)s(erform)f(op)s(erations)h -(on)h(Header-Data)h(Units)f(\(HDUs\))h(as)e(a)h(whole.)0 -4698 y Fi(1)81 b Fj(Mo)m(v)m(e)44 b(to)g(a)f(di\013eren)m(t)g(HDU)g(in) -g(the)g(\014le.)77 b(The)43 b(\014rst)f(routine)g(mo)m(v)m(es)i(to)g(a) -f(sp)s(eci\014ed)f(absolute)h(HDU)227 4811 y(n)m(um)m(b)s(er)f -(\(starting)h(with)g(1)f(for)h(the)g(primary)e(arra)m(y\))j(in)e(the)h -(FITS)f(\014le,)k(and)c(the)g(second)h(routine)227 4924 -y(mo)m(v)m(es)35 b(a)e(relativ)m(e)i(n)m(um)m(b)s(er)d(HDUs)i(forw)m -(ard)e(or)h(bac)m(kw)m(ard)h(from)f(the)g(curren)m(t)g(HDU.)h(A)f(n)m -(ull)g(p)s(oin)m(ter)227 5036 y(ma)m(y)e(b)s(e)f(giv)m(en)h(for)f(the)g -(hdut)m(yp)s(e)f(parameter)i(if)f(it's)h(v)-5 b(alue)31 -b(is)f(not)h(needed.)40 b(The)30 b(third)f(routine)i(mo)m(v)m(es)227 -5149 y(to)39 b(the)g(\(\014rst\))f(HDU)i(whic)m(h)e(has)g(the)h(sp)s -(eci\014ed)e(extension)i(t)m(yp)s(e)g(and)f(EXTNAME)g(and)g(EXTVER)227 -5262 y(k)m(eyw)m(ord)26 b(v)-5 b(alues)26 b(\(or)g(HDUNAME)h(and)e -(HDUVER)h(k)m(eyw)m(ords\).)40 b(The)24 b(hdut)m(yp)s(e)h(parameter)h -(ma)m(y)g(ha)m(v)m(e)227 5375 y(a)d(v)-5 b(alue)22 b(of)g(IMA)m(GE)p -935 5375 V 34 w(HDU,)h(ASCI)s(I)p 1476 5375 V 31 w(TBL,)f(BINAR)-8 -b(Y)p 2101 5375 V 34 w(TBL,)22 b(or)g(ANY)p 2676 5375 -V 34 w(HDU)g(where)g(ANY)p 3396 5375 V 33 w(HDU)h(means)227 -5488 y(that)33 b(only)g(the)f(extname)i(and)d(extv)m(er)j(v)-5 -b(alues)33 b(will)f(b)s(e)g(used)g(to)h(lo)s(cate)h(the)f(correct)g -(extension.)48 b(If)32 b(the)227 5601 y(input)i(v)-5 -b(alue)36 b(of)f(extv)m(er)h(is)f(0)h(then)e(the)i(EXTVER)e(k)m(eyw)m -(ord)i(is)f(ignored)g(and)g(the)g(\014rst)f(HDU)i(with)f(a)227 -5714 y(matc)m(hing)28 b(EXTNAME)g(\(or)f(HDUNAME\))i(k)m(eyw)m(ord)e -(will)g(b)s(e)g(found.)38 b(If)27 b(no)f(matc)m(hing)i(HDU)g(is)f -(found)p eop end -%%Page: 36 44 -TeXDict begin 36 43 bop 0 299 a Fj(36)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)227 555 y Fj(in)c(the)g(\014le)g(then)g(the)g(curren)m(t) -g(HDU)g(will)h(remain)f(unc)m(hanged)f(and)h(a)g(status)g(=)g(BAD)p -3246 555 28 4 v 33 w(HDU)p 3484 555 V 34 w(NUM)h(will)227 -668 y(b)s(e)j(returned.)95 938 y Fe(int)47 b(fits_movabs_hdu)d(/)j -(ffmahd)286 1051 y(\(fitsfile)f(*fptr,)g(int)h(hdunum,)e(>)j(int)f -(*hdutype,)e(int)i(*status\))95 1277 y(int)g(fits_movrel_hdu)d(/)j -(ffmrhd)286 1390 y(\(fitsfile)f(*fptr,)g(int)h(nmove,)f(>)h(int)g -(*hdutype,)e(int)i(*status\))95 1615 y(int)g(fits_movnam_hdu)d(/)j -(ffmnhd)286 1728 y(\(fitsfile)f(*fptr,)g(int)h(hdutype,)e(char)i -(*extname,)e(int)i(extver,)f(>)h(int)g(*status\))0 1998 -y Fi(2)81 b Fj(Return)38 b(the)i(total)h(n)m(um)m(b)s(er)d(of)i(HDUs)g -(in)f(the)h(FITS)f(\014le.)68 b(This)39 b(returns)f(the)h(n)m(um)m(b)s -(er)g(of)g(completely)227 2111 y(de\014ned)30 b(HDUs)h(in)f(the)h -(\014le.)42 b(If)30 b(a)h(new)f(HDU)h(has)g(just)f(b)s(een)g(added)f -(to)j(the)f(FITS)f(\014le,)h(then)f(that)h(last)227 2224 -y(HDU)f(will)f(only)g(b)s(e)g(coun)m(ted)g(if)g(it)h(has)e(b)s(een)h -(closed,)h(or)f(if)g(data)h(has)e(b)s(een)h(written)g(to)g(the)g(HDU.)h -(The)227 2337 y(curren)m(t)g(HDU)i(remains)e(unc)m(hanged)g(b)m(y)g -(this)g(routine.)95 2607 y Fe(int)47 b(fits_get_num_hdus)c(/)48 -b(ffthdu)286 2720 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*hdunum,)f(int)h -(*status\))0 2990 y Fi(3)81 b Fj(Return)31 b(the)h(n)m(um)m(b)s(er)f -(of)h(the)h(curren)m(t)e(HDU)i(\(CHDU\))h(in)d(the)i(FITS)e(\014le)h -(\(where)g(the)g(primary)g(arra)m(y)g(=)227 3102 y(1\).)42 -b(This)29 b(function)h(returns)g(the)g(HDU)h(n)m(um)m(b)s(er)e(rather)h -(than)h(a)f(status)h(v)-5 b(alue.)95 3372 y Fe(int)47 -b(fits_get_hdu_num)d(/)j(ffghdn)286 3485 y(\(fitsfile)f(*fptr,)g(>)h -(int)g(*hdunum\))0 3755 y Fi(4)81 b Fj(Return)38 b(the)h(t)m(yp)s(e)h -(of)f(the)h(curren)m(t)f(HDU)h(in)f(the)g(FITS)g(\014le.)67 -b(The)39 b(p)s(ossible)g(v)-5 b(alues)39 b(for)g(hdut)m(yp)s(e)f(are:) -227 3868 y(IMA)m(GE)p 546 3868 V 34 w(HDU,)31 b(ASCI)s(I)p -1095 3868 V 32 w(TBL,)f(or)g(BINAR)-8 b(Y)p 1840 3868 -V 34 w(TBL.)95 4138 y Fe(int)47 b(fits_get_hdu_type)c(/)48 -b(ffghdt)286 4251 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*hdutype,)e(int)i -(*status\))0 4521 y Fi(5)81 b Fj(Cop)m(y)24 b(all)h(or)f(part)g(of)g -(the)g(HDUs)h(in)f(the)g(FITS)g(\014le)g(asso)s(ciated)h(with)f(infptr) -f(and)h(app)s(end)e(them)i(to)h(the)g(end)227 4633 y(of)f(the)f(FITS)f -(\014le)i(asso)s(ciated)g(with)f(outfptr.)38 b(If)23 -b('previous')g(is)g(true)g(\(not)h(0\),)i(then)d(an)m(y)g(HDUs)h -(preceding)227 4746 y(the)35 b(curren)m(t)f(HDU)g(in)g(the)h(input)e -(\014le)h(will)h(b)s(e)e(copied)i(to)g(the)f(output)g(\014le.)52 -b(Similarly)-8 b(,)36 b('curren)m(t')f(and)227 4859 y('follo)m(wing')c -(determine)e(whether)f(the)h(curren)m(t)g(HDU,)g(and/or)g(an)m(y)g -(follo)m(wing)h(HDUs)g(in)e(the)h(input)f(\014le)227 -4972 y(will)i(b)s(e)f(copied)i(to)f(the)g(output)f(\014le.)41 -b(Th)m(us,)29 b(if)g(all)i(3)f(parameters)g(are)g(true,)g(then)g(the)f -(en)m(tire)i(input)e(\014le)227 5085 y(will)36 b(b)s(e)e(copied.)56 -b(On)35 b(exit,)i(the)f(curren)m(t)f(HDU)h(in)e(the)i(input)e(\014le)i -(will)f(b)s(e)g(unc)m(hanged,)h(and)f(the)g(last)227 -5198 y(HDU)c(in)f(the)h(output)f(\014le)g(will)h(b)s(e)f(the)g(curren)m -(t)h(HDU.)95 5468 y Fe(int)47 b(fits_copy_file)d(/)k(ffcpfl)286 -5581 y(\(fitsfile)e(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(previous,)e -(int)i(current,)477 5694 y(int)g(following,)e(>)j(int)f(*status\))p -eop end -%%Page: 37 45 -TeXDict begin 37 44 bop 0 299 a Fh(5.4.)72 b(HEADER)31 -b(KEYW)m(ORD)g(READ/WRITE)g(R)m(OUTINES)1495 b Fj(37)0 -555 y Fi(6)81 b Fj(Cop)m(y)34 b(the)h(curren)m(t)f(HDU)h(from)f(the)g -(FITS)g(\014le)h(asso)s(ciated)g(with)g(infptr)e(and)h(app)s(end)e(it)j -(to)g(the)g(end)f(of)227 668 y(the)39 b(FITS)e(\014le)h(asso)s(ciated)i -(with)e(outfptr.)64 b(Space)38 b(ma)m(y)h(b)s(e)e(reserv)m(ed)i(for)f -(MOREKEYS)f(additional)227 781 y(k)m(eyw)m(ords)31 b(in)f(the)h(output) -f(header.)95 1032 y Fe(int)47 b(fits_copy_hdu)e(/)i(ffcopy)286 -1144 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(morekeys,)e -(>)j(int)f(*status\))0 1395 y Fi(7)81 b Fj(W)-8 b(rite)31 -b(the)g(curren)m(t)f(HDU)h(in)f(the)h(input)e(FITS)h(\014le)g(to)h(the) -g(output)f(FILE)g(stream)h(\(e.g.,)h(to)f(stdout\).)95 -1645 y Fe(int)47 b(fits_write_hdu)d(/)k(ffwrhdu)286 1758 -y(\(fitsfile)e(*infptr,)f(FILE)i(*stream,)e(>)j(int)f(*status\))0 -2009 y Fi(8)81 b Fj(Cop)m(y)43 b(the)h(header)g(\(and)f(not)h(the)g -(data\))h(from)e(the)h(CHDU)g(asso)s(ciated)h(with)f(infptr)e(to)j(the) -f(CHDU)227 2122 y(asso)s(ciated)28 b(with)e(outfptr.)39 -b(If)26 b(the)h(curren)m(t)f(output)g(HDU)h(is)g(not)f(completely)i -(empt)m(y)-8 b(,)29 b(then)d(the)h(CHDU)227 2235 y(will)35 -b(b)s(e)f(closed)h(and)f(a)h(new)f(HDU)h(will)g(b)s(e)f(app)s(ended)e -(to)j(the)g(output)f(\014le.)53 b(An)34 b(empt)m(y)h(output)f(data)227 -2348 y(unit)c(will)h(b)s(e)f(created)h(with)f(all)h(v)-5 -b(alues)31 b(initially)h(=)e(0\).)95 2598 y Fe(int)47 -b(fits_copy_header)d(/)j(ffcphd)286 2711 y(\(fitsfile)f(*infptr,)f -(fitsfile)h(*outfptr,)f(>)i(int)g(*status\))0 2962 y -Fi(9)81 b Fj(Delete)35 b(the)e(CHDU)h(in)f(the)g(FITS)f(\014le.)50 -b(An)m(y)33 b(follo)m(wing)i(HDUs)e(will)h(b)s(e)e(shifted)h(forw)m -(ard)g(in)g(the)g(\014le,)h(to)227 3074 y(\014ll)k(in)f(the)g(gap)h -(created)g(b)m(y)g(the)f(deleted)h(HDU.)h(In)d(the)i(case)g(of)g -(deleting)g(the)g(primary)e(arra)m(y)i(\(the)227 3187 -y(\014rst)30 b(HDU)h(in)f(the)h(\014le\))g(then)f(the)h(curren)m(t)f -(primary)f(arra)m(y)i(will)g(b)s(e)f(replace)h(b)m(y)g(a)g(n)m(ull)f -(primary)f(arra)m(y)227 3300 y(con)m(taining)k(the)f(minim)m(um)e(set)i -(of)g(required)e(k)m(eyw)m(ords)i(and)e(no)i(data.)44 -b(If)31 b(there)g(are)h(more)f(extensions)227 3413 y(in)f(the)g(\014le) -g(follo)m(wing)i(the)e(one)g(that)h(is)f(deleted,)h(then)f(the)g(the)g -(CHDU)h(will)f(b)s(e)g(rede\014ned)e(to)j(p)s(oin)m(t)f(to)227 -3526 y(the)d(follo)m(wing)h(extension.)41 b(If)26 b(there)h(are)g(no)g -(follo)m(wing)h(extensions)f(then)g(the)g(CHDU)g(will)g(b)s(e)f -(rede\014ned)227 3639 y(to)36 b(p)s(oin)m(t)f(to)g(the)g(previous)f -(HDU.)i(The)e(output)h(hdut)m(yp)s(e)e(parameter)i(returns)f(the)h(t)m -(yp)s(e)g(of)f(the)h(new)227 3752 y(CHDU.)c(A)g(n)m(ull)f(p)s(oin)m -(ter)g(ma)m(y)h(b)s(e)f(giv)m(en)i(for)e(hdut)m(yp)s(e)f(if)h(the)h -(returned)e(v)-5 b(alue)31 b(is)f(not)h(needed.)95 4002 -y Fe(int)47 b(fits_delete_hdu)d(/)j(ffdhdu)286 4115 y(\(fitsfile)f -(*fptr,)g(>)h(int)g(*hdutype,)e(int)i(*status\))0 4448 -y Ff(5.4)135 b(Header)46 b(Keyw)l(ord)g(Read/W)-11 b(rite)46 -b(Routines)0 4698 y Fj(These)35 b(routines)g(read)f(or)h(write)h(k)m -(eyw)m(ords)f(in)g(the)g(Curren)m(t)f(Header)h(Unit)g(\(CHU\).)h(Wild)g -(card)e(c)m(haracters)0 4811 y(\(*,)28 b(?,)g(or)e(#\))h(ma)m(y)g(b)s -(e)f(used)g(when)f(sp)s(ecifying)i(the)g(name)f(of)h(the)g(k)m(eyw)m -(ord)g(to)g(b)s(e)f(read:)39 b(a)27 b(')10 b(?')39 b(will)27 -b(matc)m(h)h(an)m(y)0 4924 y(single)35 b(c)m(haracter)g(at)g(that)f(p)s -(osition)g(in)g(the)g(k)m(eyw)m(ord)h(name)f(and)f(a)h('*')h(will)g -(matc)m(h)f(an)m(y)h(length)f(\(including)0 5036 y(zero\))c(string)f -(of)g(c)m(haracters.)42 b(The)28 b('#')h(c)m(haracter)i(will)e(matc)m -(h)h(an)m(y)f(consecutiv)m(e)i(string)e(of)g(decimal)h(digits)f(\(0)0 -5149 y(-)35 b(9\).)55 b(When)35 b(a)g(wild)g(card)g(is)g(used)f(the)h -(routine)g(will)g(only)g(searc)m(h)h(for)f(a)g(matc)m(h)h(from)e(the)h -(curren)m(t)g(header)0 5262 y(p)s(osition)27 b(to)h(the)f(end)f(of)h -(the)g(header)g(and)f(will)h(not)g(resume)g(the)g(searc)m(h)g(from)g -(the)g(top)g(of)g(the)g(header)g(bac)m(k)g(to)0 5375 -y(the)k(original)i(header)e(p)s(osition)g(as)h(is)f(done)g(when)f(no)h -(wildcards)g(are)h(included)e(in)h(the)g(k)m(eyw)m(ord)h(name.)43 -b(The)0 5488 y(\014ts)p 127 5488 28 4 v 32 w(read)p 331 -5488 V 33 w(record)29 b(routine)h(ma)m(y)g(b)s(e)f(used)f(to)i(set)g -(the)g(starting)g(p)s(osition)f(when)g(doing)g(wild)g(card)h(searc)m -(hes.)41 b(A)0 5601 y(status)29 b(v)-5 b(alue)30 b(of)f(KEY)p -809 5601 V 32 w(NO)p 980 5601 V 33 w(EXIST)f(is)h(returned)e(if)i(the)g -(sp)s(eci\014ed)f(k)m(eyw)m(ord)i(to)f(b)s(e)g(read)f(is)h(not)h(found) -d(in)i(the)0 5714 y(header.)p eop end -%%Page: 38 46 -TeXDict begin 38 45 bop 0 299 a Fj(38)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Fd(5.4.1)112 b(Keyw)m(ord)38 b(Reading)g -(Routines)0 764 y Fi(1)81 b Fj(Return)33 b(the)h(n)m(um)m(b)s(er)e(of)i -(existing)h(k)m(eyw)m(ords)g(\(not)f(coun)m(ting)h(the)f(END)g(k)m(eyw) -m(ord\))h(and)e(the)h(amoun)m(t)h(of)227 877 y(space)e(curren)m(tly)f -(a)m(v)-5 b(ailable)34 b(for)e(more)g(k)m(eyw)m(ords.)46 -b(It)32 b(returns)e(morek)m(eys)j(=)f(-1)g(if)g(the)g(header)g(has)g -(not)227 990 y(y)m(et)27 b(b)s(een)d(closed.)40 b(Note)26 -b(that)g(CFITSIO)d(will)j(dynamically)g(add)e(space)i(if)f(required)f -(when)g(writing)h(new)227 1103 y(k)m(eyw)m(ords)32 b(to)g(a)f(header)g -(so)h(in)f(practice)h(there)g(is)f(no)g(limit)h(to)g(the)f(n)m(um)m(b)s -(er)f(of)i(k)m(eyw)m(ords)f(that)h(can)g(b)s(e)227 1216 -y(added)e(to)h(a)f(header.)41 b(A)30 b(n)m(ull)g(p)s(oin)m(ter)h(ma)m -(y)f(b)s(e)g(en)m(tered)h(for)f(the)g(morek)m(eys)h(parameter)g(if)f -(it's)h(v)-5 b(alue)31 b(is)227 1329 y(not)g(needed.)95 -1588 y Fe(int)47 b(fits_get_hdrspace)c(/)48 b(ffghsp)286 -1701 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*keysexist,)e(int)i(*morekeys,)e -(int)i(*status\))0 1960 y Fi(2)81 b Fj(Return)28 b(the)h(sp)s -(eci\014ed)f(k)m(eyw)m(ord.)41 b(In)29 b(the)g(\014rst)f(routine,)i -(the)f(datat)m(yp)s(e)h(parameter)g(sp)s(eci\014es)e(the)h(desired)227 -2073 y(returned)e(data)h(t)m(yp)s(e)g(of)g(the)g(k)m(eyw)m(ord)h(v)-5 -b(alue)28 b(and)f(can)h(ha)m(v)m(e)h(one)f(of)g(the)g(follo)m(wing)h -(sym)m(b)s(olic)g(constan)m(t)227 2186 y(v)-5 b(alues:)47 -b(TSTRING,)33 b(TLOGICAL)f(\(==)h(in)m(t\),)j(TBYTE,)d(TSHOR)-8 -b(T,)33 b(TUSHOR)-8 b(T,)32 b(TINT,)h(TUINT,)227 2298 -y(TLONG,)24 b(TULONG,)g(TLONGLONG,)g(TFLO)m(A)-8 b(T,)25 -b(TDOUBLE,)f(TCOMPLEX,)f(and)h(TDBLCOM-)227 2411 y(PLEX.)j(Within)f -(the)h(con)m(text)h(of)f(this)g(routine,)g(TSTRING)f(corresp)s(onds)f -(to)i(a)g('c)m(har*')h(data)f(t)m(yp)s(e,)h(i.e.,)227 -2524 y(a)k(p)s(oin)m(ter)g(to)g(a)g(c)m(haracter)i(arra)m(y)-8 -b(.)45 b(Data)33 b(t)m(yp)s(e)f(con)m(v)m(ersion)h(will)f(b)s(e)f(p)s -(erformed)f(for)i(n)m(umeric)f(v)-5 b(alues)32 b(if)227 -2637 y(the)27 b(k)m(eyw)m(ord)g(v)-5 b(alue)27 b(do)s(es)f(not)h(ha)m -(v)m(e)h(the)f(same)g(data)g(t)m(yp)s(e.)40 b(If)26 b(the)h(v)-5 -b(alue)27 b(of)g(the)f(k)m(eyw)m(ord)i(is)e(unde\014ned)227 -2750 y(\(i.e.,)31 b(the)e(v)-5 b(alue)30 b(\014eld)e(is)h(blank\))g -(then)f(an)h(error)g(status)g(=)f(V)-10 b(ALUE)p 2627 -2750 28 4 v 33 w(UNDEFINED)30 b(will)g(b)s(e)e(returned.)227 -2900 y(The)c(second)f(routine)h(returns)f(the)h(k)m(eyw)m(ord)g(v)-5 -b(alue)24 b(as)g(a)g(c)m(haracter)i(string)d(\(a)i(literal)g(cop)m(y)g -(of)f(what)f(is)h(in)227 3013 y(the)j(v)-5 b(alue)26 -b(\014eld\))g(regardless)h(of)f(the)g(in)m(trinsic)h(data)g(t)m(yp)s(e) -f(of)g(the)g(k)m(eyw)m(ord.)40 b(The)26 b(third)f(routine)h(returns)227 -3126 y(the)45 b(en)m(tire)h(80-c)m(haracter)i(header)c(record)h(of)g -(the)g(k)m(eyw)m(ord,)k(with)c(an)m(y)g(trailing)h(blank)e(c)m -(haracters)227 3239 y(stripp)s(ed)37 b(o\013.)64 b(The)38 -b(fourth)f(routine)h(returns)f(the)h(\(next\))h(header)f(record)g(that) -h(con)m(tains)g(the)f(literal)227 3352 y(string)31 b(of)f(c)m -(haracters)i(sp)s(eci\014ed)e(b)m(y)g(the)g('string')h(argumen)m(t.)227 -3502 y(If)f(a)h(NULL)f(commen)m(t)i(p)s(oin)m(ter)e(is)g(supplied)g -(then)g(the)g(commen)m(t)i(string)e(will)h(not)f(b)s(e)g(returned.)95 -3761 y Fe(int)47 b(fits_read_key)e(/)i(ffgky)286 3874 -y(\(fitsfile)f(*fptr,)g(int)h(datatype,)e(char)i(*keyname,)e(>)i(DTYPE) -g(*value,)334 3987 y(char)g(*comment,)e(int)i(*status\))95 -4213 y(int)g(fits_read_keyword)c(/)48 b(ffgkey)286 4326 -y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h(char)g(*value,)f(char)g -(*comment,)334 4439 y(int)h(*status\))95 4664 y(int)g(fits_read_card)d -(/)k(ffgcrd)286 4777 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h -(char)g(*card,)f(int)h(*status\))95 5003 y(int)g(fits_read_str)e(/)i -(ffgstr)286 5116 y(\(fitsfile)f(*fptr,)g(char)g(*string,)g(>)h(char)g -(*card,)f(int)h(*status\))0 5375 y Fi(3)81 b Fj(Read)22 -b(a)g(string-v)-5 b(alued)23 b(k)m(eyw)m(ord)f(and)g(return)e(the)j -(string)f(length,)i(the)e(v)-5 b(alue)23 b(string,)h(and/or)e(the)g -(commen)m(t)227 5488 y(\014eld.)48 b(The)33 b(\014rst)f(routine,)i -(\013gksl,)g(simply)e(returns)g(the)h(length)h(of)f(the)g(c)m(haracter) -h(string)f(v)-5 b(alue)34 b(of)f(the)227 5601 y(sp)s(eci\014ed)g(k)m -(eyw)m(ord.)50 b(The)32 b(second)i(routine,)g(\013gsky)-8 -b(,)35 b(also)f(returns)e(up)g(to)i(maxc)m(har)g(c)m(haracters)g(of)g -(the)227 5714 y(k)m(eyw)m(ord)d(v)-5 b(alue)31 b(string,)g(starting)g -(with)g(the)f(\014rstc)m(har)g(c)m(haracter,)j(and)d(the)g(k)m(eyw)m -(ord)h(commen)m(t)h(string)p eop end -%%Page: 39 47 -TeXDict begin 39 46 bop 0 299 a Fh(5.4.)72 b(HEADER)31 -b(KEYW)m(ORD)g(READ/WRITE)g(R)m(OUTINES)1495 b Fj(39)227 -555 y(\(unless)33 b(the)h(input)e(v)-5 b(alue)34 b(of)g(comm)f(=)g -(NULL\).)h(The)f(v)-5 b(aluelen)34 b(argumen)m(t)g(returns)e(the)h -(total)j(length)227 668 y(of)c(the)f(k)m(eyw)m(ord)h(v)-5 -b(alue)32 b(string)f(regardless)h(of)f(ho)m(w)h(m)m(uc)m(h)f(of)h(the)f -(string)g(is)h(actually)h(returned)d(\(whic)m(h)227 781 -y(dep)s(ends)25 b(on)i(the)g(v)-5 b(alue)27 b(of)g(the)g(\014rstc)m -(har)g(and)f(maxc)m(har)h(argumen)m(ts\).)40 b(Note)29 -b(that)e(the)g(v)-5 b(alue)27 b(c)m(haracter)227 894 -y(string)33 b(argumen)m(t)h(m)m(ust)f(b)s(e)f(allo)s(cated)j(large)g -(enough)e(to)g(also)i(hold)d(the)i(n)m(ull)f(terminator)g(at)h(the)g -(end)227 1007 y(of)41 b(the)f(returned)f(string.)69 b(These)40 -b(routines)g(supp)s(ort)f(string)h(k)m(eyw)m(ords)g(that)h(use)e(the)i -(CONTINUE)227 1120 y(con)m(v)m(en)m(tion)25 b(to)e(con)m(tin)m(ue)g -(long)g(string)f(v)-5 b(alues)23 b(o)m(v)m(er)h(m)m(ultiple)f(FITS)e -(header)h(records.)38 b(Normally)-8 b(,)26 b(string-)227 -1233 y(v)-5 b(alued)40 b(k)m(eyw)m(ords)h(ha)m(v)m(e)g(a)g(maxim)m(um)f -(length)h(of)f(68)h(c)m(haracters,)k(ho)m(w)m(ev)m(er,)f(CONTINUE'd)39 -b(string)227 1346 y(k)m(eyw)m(ords)31 b(ma)m(y)g(b)s(e)f(arbitrarily)g -(long.)95 1630 y Fe(int)47 b(fits_get_key_strlen)c(/)k(ffgksl)286 -1742 y(\(fitsfile)f(*fptr,)g(const)g(char)h(*keyname,)e(int)i(*length,) -e(int)i(*status\);)95 1968 y(int)g(fits_read_string_key)c(/)k(ffgsky) -334 2081 y(\(fitsfile)e(*fptr,)h(const)h(char)f(*keyname,)g(int)h -(firstchar,)e(int)i(maxchar,)334 2194 y(char)g(*value,)f(int)g -(*valuelen,)f(char)i(*comm,)f(int)h(*status\);)0 2478 -y Fi(4)81 b Fj(Return)38 b(the)h(n)m(th)f(header)h(record)g(in)f(the)i -(CHU.)f(The)f(\014rst)g(k)m(eyw)m(ord)i(in)e(the)h(header)g(is)g(at)g -(k)m(eyn)m(um)g(=)227 2591 y(1;)53 b(if)45 b(k)m(eyn)m(um)g(=)f(0)h -(then)g(these)g(routines)g(simply)f(reset)h(the)h(in)m(ternal)f -(CFITSIO)e(p)s(oin)m(ter)i(to)h(the)227 2704 y(b)s(eginning)35 -b(of)h(the)g(header)f(so)h(that)g(subsequen)m(t)f(k)m(eyw)m(ord)h(op)s -(erations)g(will)g(start)g(at)g(the)g(top)g(of)g(the)227 -2817 y(header)26 b(\(e.g.,)j(prior)c(to)h(searc)m(hing)h(for)f(k)m(eyw) -m(ords)g(using)f(wild)g(cards)h(in)f(the)h(k)m(eyw)m(ord)h(name\).)39 -b(The)26 b(\014rst)227 2930 y(routine)32 b(returns)e(the)i(en)m(tire)h -(80-c)m(haracter)h(header)e(record)g(\(with)f(trailing)i(blanks)e -(truncated\),)i(while)227 3043 y(the)41 b(second)f(routine)g(parses)g -(the)g(record)h(and)e(returns)g(the)i(name,)i(v)-5 b(alue,)43 -b(and)d(commen)m(t)h(\014elds)f(as)227 3156 y(separate)32 -b(\(blank)f(truncated\))g(c)m(haracter)i(strings.)42 -b(If)30 b(a)h(NULL)g(commen)m(t)h(p)s(oin)m(ter)f(is)g(giv)m(en)h(on)f -(input,)227 3268 y(then)f(the)h(commen)m(t)g(string)g(will)f(not)h(b)s -(e)f(returned.)95 3553 y Fe(int)47 b(fits_read_record)d(/)j(ffgrec)286 -3665 y(\(fitsfile)f(*fptr,)g(int)h(keynum,)e(>)j(char)f(*card,)f(int)h -(*status\))95 3891 y(int)g(fits_read_keyn)d(/)k(ffgkyn)286 -4004 y(\(fitsfile)e(*fptr,)g(int)h(keynum,)e(>)j(char)f(*keyname,)e -(char)h(*value,)334 4117 y(char)h(*comment,)e(int)i(*status\))0 -4401 y Fi(5)81 b Fj(Return)44 b(the)i(next)g(k)m(eyw)m(ord)g(whose)f -(name)h(matc)m(hes)g(one)g(of)g(the)f(strings)h(in)f('inclist')i(but)e -(do)s(es)g(not)227 4514 y(matc)m(h)31 b(an)m(y)g(of)g(the)f(strings)g -(in)g('exclist'.)43 b(The)30 b(strings)g(in)g(inclist)h(and)f(exclist)i -(ma)m(y)e(con)m(tain)i(wild)e(card)227 4627 y(c)m(haracters)k(\(*,)f -(?,)f(and)f(#\))h(as)g(describ)s(ed)f(at)i(the)f(b)s(eginning)f(of)h -(this)g(section.)46 b(This)31 b(routine)h(searc)m(hes)227 -4740 y(from)j(the)g(curren)m(t)g(header)g(p)s(osition)g(to)h(the)f(end) -f(of)h(the)h(header,)g(only)-8 b(,)37 b(and)d(do)s(es)h(not)g(con)m -(tin)m(ue)i(the)227 4853 y(searc)m(h)32 b(from)e(the)h(top)g(of)g(the)g -(header)g(bac)m(k)g(to)h(the)f(original)h(p)s(osition.)42 -b(The)31 b(curren)m(t)f(header)h(p)s(osition)227 4966 -y(ma)m(y)e(b)s(e)e(reset)h(with)g(the)g(\013grec)g(routine.)40 -b(Note)29 b(that)g(nexc)f(ma)m(y)g(b)s(e)f(set)h(=)g(0)g(if)g(there)g -(are)g(no)g(k)m(eyw)m(ords)227 5079 y(to)h(b)s(e)f(excluded.)39 -b(This)28 b(routine)g(returns)f(status)h(=)g(KEY)p 2268 -5079 28 4 v 32 w(NO)p 2439 5079 V 33 w(EXIST)f(if)h(a)h(matc)m(hing)g -(k)m(eyw)m(ord)g(is)f(not)227 5191 y(found.)95 5475 y -Fe(int)47 b(fits_find_nextkey)c(/)48 b(ffgnxk)286 5588 -y(\(fitsfile)e(*fptr,)g(char)g(**inclist,)f(int)i(ninc,)g(char)f -(**exclist,)334 5701 y(int)h(nexc,)f(>)i(char)e(*card,)h(int)94 -b(*status\))p eop end -%%Page: 40 48 -TeXDict begin 40 47 bop 0 299 a Fj(40)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Fi(6)81 b Fj(Return)25 b(the)h(ph)m(ysical)g -(units)g(string)g(from)f(an)h(existing)h(k)m(eyw)m(ord.)39 -b(This)26 b(routine)g(uses)f(a)h(lo)s(cal)i(con)m(v)m(en)m(tion,)227 -668 y(sho)m(wn)d(in)g(the)g(follo)m(wing)i(example,)g(in)e(whic)m(h)g -(the)h(k)m(eyw)m(ord)f(units)g(are)h(enclosed)g(in)f(square)g(brac)m(k) -m(ets)h(in)227 781 y(the)k(b)s(eginning)f(of)h(the)g(k)m(eyw)m(ord)g -(commen)m(t)g(\014eld.)40 b(A)30 b(n)m(ull)g(string)f(is)h(returned)e -(if)i(no)f(units)g(are)h(de\014ned)227 894 y(for)g(the)h(k)m(eyw)m -(ord.)239 1135 y Fe(VELOCITY=)809 b(12.3)46 b(/)i([km/s])e(orbital)g -(speed)95 1361 y(int)h(fits_read_key_unit)c(/)48 b(ffgunt)286 -1474 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h(char)g(*unit,)f -(int)h(*status\))0 1715 y Fi(7)81 b Fj(Concatenate)39 -b(the)f(header)f(k)m(eyw)m(ords)h(in)g(the)f(CHDU)h(in)m(to)h(a)f -(single)g(long)g(string)g(of)g(c)m(haracters.)64 b(This)227 -1828 y(pro)m(vides)28 b(a)h(con)m(v)m(enien)m(t)h(w)m(a)m(y)f(of)g -(passing)f(all)h(or)f(part)g(of)g(the)h(header)f(information)g(in)g(a)h -(FITS)e(HDU)i(to)227 1941 y(other)i(subroutines.)39 b(Eac)m(h)31 -b(80-c)m(haracter)h(\014xed-length)f(k)m(eyw)m(ord)f(record)g(is)g(app) -s(ended)e(to)j(the)f(output)227 2054 y(c)m(haracter)j(string,)f(in)f -(order,)g(with)g(no)g(in)m(terv)m(ening)i(separator)f(or)f(terminating) -h(c)m(haracters.)45 b(The)31 b(last)227 2167 y(header)e(record)g(is)g -(terminated)h(with)f(a)g(NULL)g(c)m(haracter.)42 b(These)29 -b(routine)g(allo)s(cates)j(memory)d(for)g(the)227 2279 -y(returned)k(c)m(haracter)j(arra)m(y)-8 b(,)37 b(so)d(the)h(calling)h -(program)e(m)m(ust)g(free)g(the)h(memory)f(when)f(\014nished.)51 -b(The)227 2392 y(cleanest)32 b(w)m(a)m(y)g(to)f(do)f(this)g(is)h(to)g -(call)g(the)g(\014ts)p 1823 2392 28 4 v 32 w(free)p 1999 -2392 V 33 w(memory)g(routine.)227 2540 y(There)38 b(are)h(2)g(related)g -(routines:)57 b(\014ts)p 1581 2540 V 32 w(hdr2str)37 -b(simply)h(concatenates)j(all)f(the)e(existing)i(k)m(eyw)m(ords)e(in) -227 2652 y(the)44 b(header;)51 b(\014ts)p 863 2652 V -33 w(con)m(v)m(ert)p 1185 2652 V 34 w(hdr2str)43 b(is)h(similar,)k -(except)d(that)f(if)g(the)g(CHDU)h(is)f(a)g(tile)h(compressed)227 -2765 y(image)c(\(stored)f(in)f(a)h(binary)e(table\))j(then)e(it)h(will) -f(\014rst)g(con)m(v)m(ert)i(that)f(header)f(bac)m(k)h(to)g(that)g(of)g -(the)227 2878 y(corresp)s(onding)30 b(normal)g(FITS)g(image)h(b)s -(efore)f(concatenating)j(the)e(k)m(eyw)m(ords.)227 3025 -y(Selected)f(k)m(eyw)m(ords)e(ma)m(y)h(b)s(e)e(excluded)h(from)g(the)g -(returned)f(c)m(haracter)j(string.)40 b(If)27 b(the)i(second)f(param-) -227 3138 y(eter)h(\(no)s(commen)m(ts\))g(is)f(TR)m(UE)g(\(nonzero\))h -(then)e(an)m(y)i(COMMENT,)f(HISTOR)-8 b(Y,)27 b(or)h(blank)g(k)m(eyw)m -(ords)227 3251 y(in)i(the)h(header)f(will)h(not)f(b)s(e)g(copied)h(to)g -(the)g(output)f(string.)227 3398 y(The)25 b('exclist')j(parameter)e(ma) -m(y)g(b)s(e)f(used)g(to)h(supply)e(a)i(list)h(of)e(k)m(eyw)m(ords)h -(that)h(are)f(to)g(b)s(e)f(excluded)g(from)227 3511 y(the)k(output)g(c) -m(haracter)h(string.)41 b(Wild)29 b(card)g(c)m(haracters)h(\(*,)g(?,)f -(and)g(#\))g(ma)m(y)g(b)s(e)f(used)g(in)h(the)g(excluded)227 -3624 y(k)m(eyw)m(ord)h(names.)41 b(If)29 b(no)g(additional)i(k)m(eyw)m -(ords)f(are)g(to)g(b)s(e)f(excluded,)h(then)f(set)h(nexc)g(=)f(0)h(and) -f(sp)s(ecify)227 3737 y(NULL)i(for)f(the)g(the)h(**exclist)i -(parameter.)95 3978 y Fe(int)47 b(fits_hdr2str)e(/)i(ffhdr2str)286 -4091 y(\(fitsfile)f(*fptr,)g(int)h(nocomments,)d(char)j(**exclist,)e -(int)i(nexc,)286 4204 y(>)h(char)e(**header,)g(int)h(*nkeys,)e(int)i -(*status\))95 4430 y(int)g(fits_convert_hdr2str)c(/)k(ffcnvthdr2str)286 -4543 y(\(fitsfile)f(*fptr,)g(int)h(nocomments,)d(char)j(**exclist,)e -(int)i(nexc,)286 4656 y(>)h(char)e(**header,)g(int)h(*nkeys,)e(int)i -(*status\))95 4882 y(int)g(fits_free_memory)d(/)j(fffree)286 -4994 y(\(char)g(*header,)e(>)j(int)f(*status\);)0 5395 -y Fd(5.4.2)112 b(Keyw)m(ord)38 b(W)-9 b(riting)37 b(Routines)0 -5601 y Fi(1)81 b Fj(W)-8 b(rite)32 b(a)g(k)m(eyw)m(ord)g(of)f(the)h -(appropriate)f(data)h(t)m(yp)s(e)g(in)m(to)g(the)g(CHU.)f(The)g -(\014rst)g(routine)g(simply)g(app)s(ends)227 5714 y(a)j(new)f(k)m(eyw)m -(ord)h(whereas)f(the)g(second)h(routine)f(will)h(up)s(date)e(the)i(v)-5 -b(alue)33 b(and)g(commen)m(t)h(\014elds)f(of)h(the)p -eop end -%%Page: 41 49 -TeXDict begin 41 48 bop 0 299 a Fh(5.4.)72 b(HEADER)31 -b(KEYW)m(ORD)g(READ/WRITE)g(R)m(OUTINES)1495 b Fj(41)227 -555 y(k)m(eyw)m(ord)34 b(if)g(it)g(already)g(exists,)h(otherwise)f(it)g -(app)s(ends)e(a)i(new)f(k)m(eyw)m(ord.)51 b(Note)35 b(that)f(the)g -(address)e(to)227 668 y(the)37 b(v)-5 b(alue,)38 b(and)d(not)i(the)f(v) --5 b(alue)36 b(itself,)j(m)m(ust)d(b)s(e)f(en)m(tered.)59 -b(The)35 b(datat)m(yp)s(e)i(parameter)g(sp)s(eci\014es)f(the)227 -781 y(data)25 b(t)m(yp)s(e)f(of)g(the)g(k)m(eyw)m(ord)g(v)-5 -b(alue)25 b(with)e(one)h(of)g(the)g(follo)m(wing)i(v)-5 -b(alues:)37 b(TSTRING,)23 b(TLOGICAL)g(\(==)227 894 y(in)m(t\),)38 -b(TBYTE,)d(TSHOR)-8 b(T,)34 b(TUSHOR)-8 b(T,)35 b(TINT,)f(TUINT,)h -(TLONG,)g(TLONGLONG,)g(TULONG,)227 1007 y(TFLO)m(A)-8 -b(T,)24 b(TDOUBLE.)f(Within)h(the)f(con)m(text)i(of)f(this)f(routine,)i -(TSTRING)d(corresp)s(onds)g(to)i(a)g('c)m(har*')227 1120 -y(data)j(t)m(yp)s(e,)h(i.e.,)g(a)f(p)s(oin)m(ter)f(to)i(a)e(c)m -(haracter)i(arra)m(y)-8 b(.)41 b(A)26 b(n)m(ull)g(p)s(oin)m(ter)h(ma)m -(y)g(b)s(e)e(en)m(tered)i(for)f(the)h(commen)m(t)227 -1233 y(parameter)k(in)f(whic)m(h)g(case)i(the)e(k)m(eyw)m(ord)h(commen) -m(t)h(\014eld)d(will)i(b)s(e)f(unmo)s(di\014ed)e(or)j(left)g(blank.)95 -1515 y Fe(int)47 b(fits_write_key)d(/)k(ffpky)286 1628 -y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(char)i(*keyname,)e(DTYPE)h -(*value,)477 1741 y(char)h(*comment,)e(>)j(int)f(*status\))95 -1967 y(int)g(fits_update_key)d(/)j(ffuky)286 2080 y(\(fitsfile)f -(*fptr,)g(int)h(datatype,)e(char)i(*keyname,)e(DTYPE)h(*value,)477 -2193 y(char)h(*comment,)e(>)j(int)f(*status\))0 2475 -y Fi(2)81 b Fj(W)-8 b(rite)44 b(a)g(k)m(eyw)m(ord)f(with)g(a)h(n)m(ull) -f(or)g(unde\014ned)e(v)-5 b(alue)43 b(\(i.e.,)48 b(the)c(v)-5 -b(alue)43 b(\014eld)g(in)g(the)g(k)m(eyw)m(ord)h(is)f(left)227 -2588 y(blank\).)70 b(The)40 b(\014rst)f(routine)h(simply)g(app)s(ends)e -(a)j(new)e(k)m(eyw)m(ord)i(whereas)f(the)g(second)g(routine)h(will)227 -2701 y(up)s(date)27 b(the)h(v)-5 b(alue)29 b(and)e(commen)m(t)i -(\014elds)e(of)h(the)g(k)m(eyw)m(ord)g(if)g(it)g(already)h(exists,)g -(otherwise)f(it)h(app)s(ends)227 2814 y(a)g(new)g(k)m(eyw)m(ord.)40 -b(A)29 b(n)m(ull)g(p)s(oin)m(ter)g(ma)m(y)g(b)s(e)g(en)m(tered)g(for)g -(the)g(commen)m(t)g(parameter)h(in)e(whic)m(h)h(case)h(the)227 -2927 y(k)m(eyw)m(ord)h(commen)m(t)h(\014eld)d(will)i(b)s(e)f(unmo)s -(di\014ed)e(or)j(left)g(blank.)95 3209 y Fe(int)47 b -(fits_write_key_null)c(/)k(ffpkyu)286 3322 y(\(fitsfile)f(*fptr,)g -(char)g(*keyname,)g(char)g(*comment,)g(>)h(int)g(*status\))95 -3548 y(int)g(fits_update_key_null)c(/)k(ffukyu)286 3661 -y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*comment,)g(>)h(int)g -(*status\))0 3943 y Fi(3)81 b Fj(W)-8 b(rite)40 b(\(app)s(end\))e(a)h -(COMMENT)g(or)g(HISTOR)-8 b(Y)38 b(k)m(eyw)m(ord)i(to)f(the)g(CHU.)h -(The)e(commen)m(t)i(or)f(history)227 4056 y(string)31 -b(will)f(b)s(e)g(con)m(tin)m(ued)h(o)m(v)m(er)h(m)m(ultiple)f(k)m(eyw)m -(ords)g(if)f(it)h(is)f(longer)h(than)f(70)i(c)m(haracters.)95 -4338 y Fe(int)47 b(fits_write_comment)c(/)48 b(ffpcom)286 -4451 y(\(fitsfile)e(*fptr,)g(char)g(*comment,)g(>)h(int)g(*status\))95 -4677 y(int)g(fits_write_history)c(/)48 b(ffphis)286 4790 -y(\(fitsfile)e(*fptr,)g(char)g(*history,)g(>)h(int)g(*status\))0 -5073 y Fi(4)81 b Fj(W)-8 b(rite)29 b(the)g(D)m(A)-8 b(TE)29 -b(k)m(eyw)m(ord)g(to)g(the)g(CHU.)f(The)g(k)m(eyw)m(ord)h(v)-5 -b(alue)29 b(will)f(con)m(tain)i(the)f(curren)m(t)f(system)g(date)227 -5185 y(as)k(a)g(c)m(haracter)h(string)e(in)g('yyyy-mm-ddThh:mm:ss')e -(format.)44 b(If)31 b(a)h(D)m(A)-8 b(TE)32 b(k)m(eyw)m(ord)g(already)g -(exists)227 5298 y(in)c(the)f(header,)i(then)e(this)g(routine)h(will)g -(simply)f(up)s(date)g(the)h(k)m(eyw)m(ord)g(v)-5 b(alue)28 -b(with)f(the)h(curren)m(t)g(date.)95 5581 y Fe(int)47 -b(fits_write_date)d(/)j(ffpdat)286 5694 y(\(fitsfile)f(*fptr,)g(>)h -(int)g(*status\))p eop end -%%Page: 42 50 -TeXDict begin 42 49 bop 0 299 a Fj(42)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Fi(5)81 b Fj(W)-8 b(rite)34 b(a)g(user)f(sp)s -(eci\014ed)g(k)m(eyw)m(ord)h(record)f(in)m(to)h(the)g(CHU.)g(This)e(is) -i(a)g(lo)m(w{lev)m(el)i(routine)e(whic)m(h)f(can)h(b)s(e)227 -668 y(used)f(to)h(write)f(an)m(y)h(arbitrary)f(record)g(in)m(to)i(the)e -(header.)50 b(The)32 b(record)i(m)m(ust)f(conform)g(to)h(the)g(all)g -(the)227 781 y(FITS)c(format)h(requiremen)m(ts.)95 1034 -y Fe(int)47 b(fits_write_record)c(/)48 b(ffprec)286 1147 -y(\(fitsfile)e(*fptr,)g(char)g(*card,)g(>)i(int)f(*status\))0 -1401 y Fi(6)81 b Fj(Up)s(date)34 b(an)g(80-c)m(haracter)j(record)e(in)f -(the)g(CHU.)h(If)f(a)h(k)m(eyw)m(ord)f(with)h(the)f(input)g(name)g -(already)h(exists,)227 1514 y(then)e(it)h(is)f(o)m(v)m(erwritten)h(b)m -(y)f(the)g(v)-5 b(alue)34 b(of)f(card.)49 b(This)32 b(could)h(mo)s -(dify)f(the)i(k)m(eyw)m(ord)f(name)g(as)h(w)m(ell)g(as)227 -1627 y(the)c(v)-5 b(alue)30 b(and)e(commen)m(t)j(\014elds.)40 -b(If)29 b(the)g(k)m(eyw)m(ord)h(do)s(esn't)f(already)h(exist)g(then)g -(a)f(new)g(k)m(eyw)m(ord)h(card)227 1739 y(is)h(app)s(ended)d(to)j(the) -g(header.)95 1993 y Fe(int)47 b(fits_update_card)d(/)j(ffucrd)286 -2106 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*card,)g(>)i -(int)f(*status\))0 2359 y Fi(7)81 b Fj(Mo)s(dify)30 b(\(o)m(v)m -(erwrite\))i(the)f(commen)m(t)g(\014eld)f(of)h(an)f(existing)h(k)m(eyw) -m(ord.)95 2613 y Fe(int)47 b(fits_modify_comment)c(/)k(ffmcom)286 -2726 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*comment,)g(>)h -(int)g(*status\))0 2979 y Fi(8)81 b Fj(W)-8 b(rite)33 -b(the)f(ph)m(ysical)h(units)f(string)g(in)m(to)h(an)f(existing)h(k)m -(eyw)m(ord.)46 b(This)32 b(routine)g(uses)g(a)g(lo)s(cal)i(con)m(v)m -(en)m(tion,)227 3092 y(sho)m(wn)e(in)g(the)h(follo)m(wing)h(example,)g -(in)e(whic)m(h)g(the)h(k)m(eyw)m(ord)g(units)f(are)h(enclosed)g(in)f -(square)g(brac)m(k)m(ets)227 3205 y(in)e(the)h(b)s(eginning)f(of)g(the) -h(k)m(eyw)m(ord)g(commen)m(t)g(\014eld.)239 3458 y Fe(VELOCITY=)809 -b(12.3)46 b(/)i([km/s])e(orbital)g(speed)95 3684 y(int)h -(fits_write_key_unit)c(/)k(ffpunt)286 3797 y(\(fitsfile)f(*fptr,)g -(char)g(*keyname,)g(char)g(*unit,)g(>)i(int)f(*status\))0 -4050 y Fi(9)81 b Fj(Rename)30 b(an)h(existing)g(k)m(eyw)m(ord,)g -(preserving)f(the)g(curren)m(t)h(v)-5 b(alue)30 b(and)g(commen)m(t)i -(\014elds.)95 4304 y Fe(int)47 b(fits_modify_name)d(/)j(ffmnam)286 -4417 y(\(fitsfile)f(*fptr,)g(char)g(*oldname,)g(char)g(*newname,)g(>)h -(int)g(*status\))0 4670 y Fi(10)f Fj(Delete)37 b(a)e(k)m(eyw)m(ord)g -(record.)54 b(The)34 b(space)i(o)s(ccupied)e(b)m(y)h(the)g(k)m(eyw)m -(ord)g(is)g(reclaimed)h(b)m(y)e(mo)m(ving)i(all)g(the)227 -4783 y(follo)m(wing)e(header)f(records)f(up)g(one)h(ro)m(w)f(in)h(the)f -(header.)48 b(The)32 b(\014rst)g(routine)g(deletes)i(a)f(k)m(eyw)m(ord) -g(at)h(a)227 4896 y(sp)s(eci\014ed)23 b(p)s(osition)h(in)g(the)g -(header)f(\(the)i(\014rst)e(k)m(eyw)m(ord)h(is)g(at)g(p)s(osition)g -(1\),)i(whereas)e(the)g(second)g(routine)227 5009 y(deletes)30 -b(a)f(sp)s(eci\014cally)g(named)f(k)m(eyw)m(ord.)41 b(Wild)29 -b(card)f(c)m(haracters)i(ma)m(y)f(b)s(e)f(used)g(when)f(sp)s(ecifying)i -(the)227 5122 y(name)23 b(of)g(the)f(k)m(eyw)m(ord)h(to)h(b)s(e)e -(deleted.)38 b(The)22 b(third)g(routine)h(deletes)g(the)g(\(next\))h(k) -m(eyw)m(ord)f(that)g(con)m(tains)227 5235 y(the)31 b(literal)h(c)m -(haracter)g(string)e(sp)s(eci\014ed)g(b)m(y)g(the)h('string')f(argumen) -m(t.)95 5488 y Fe(int)47 b(fits_delete_record)c(/)48 -b(ffdrec)286 5601 y(\(fitsfile)e(*fptr,)g(int)142 b(keynum,)94 -b(>)47 b(int)g(*status\))p eop end -%%Page: 43 51 -TeXDict begin 43 50 bop 0 299 a Fh(5.5.)72 b(PRIMAR)-8 -b(Y)31 b(ARRA)-8 b(Y)31 b(OR)f(IMA)m(GE)h(EXTENSION)f(I/O)g(R)m -(OUTINES)1011 b Fj(43)95 555 y Fe(int)47 b(fits_delete_key)d(/)j -(ffdkey)286 668 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(>)h(int)g -(*status\))95 894 y(int)g(fits_delete_str)d(/)j(ffdstr)286 -1007 y(\(fitsfile)f(*fptr,)g(char)g(*string,)g(>)h(int)g(*status\))0 -1334 y Ff(5.5)135 b(Primary)46 b(Arra)l(y)f(or)g(IMA)l(GE)f(Extension)i -(I/O)f(Routines)0 1584 y Fj(These)22 b(routines)g(read)h(or)f(write)h -(data)g(v)-5 b(alues)23 b(in)f(the)g(primary)g(data)h(arra)m(y)g -(\(i.e.,)j(the)c(\014rst)g(HDU)h(in)f(a)h(FITS)e(\014le\))0 -1697 y(or)32 b(an)g(IMA)m(GE)h(extension.)47 b(There)31 -b(are)i(also)g(routines)f(to)h(get)g(information)f(ab)s(out)g(the)g -(data)h(t)m(yp)s(e)g(and)e(size)0 1810 y(of)c(the)g(image.)41 -b(Users)27 b(should)f(also)i(read)f(the)g(follo)m(wing)h(c)m(hapter)g -(on)f(the)g(CFITSIO)e(iterator)k(function)d(whic)m(h)0 -1923 y(pro)m(vides)33 b(a)h(more)f(`ob)5 b(ject)35 b(orien)m(ted')f -(metho)s(d)f(of)g(reading)g(and)g(writing)g(images.)51 -b(The)32 b(iterator)j(function)e(is)0 2035 y(a)e(little)i(more)e -(complicated)h(to)g(use,)f(but)f(the)h(adv)-5 b(an)m(tages)32 -b(are)f(that)h(it)f(usually)g(tak)m(es)h(less)f(co)s(de)g(to)g(p)s -(erform)0 2148 y(the)37 b(same)f(op)s(eration,)j(and)c(the)i(resulting) -f(program)g(often)h(runs)e(faster)i(b)s(ecause)f(the)g(FITS)g(\014les)g -(are)h(read)0 2261 y(and)30 b(written)g(using)g(the)h(most)f(e\016cien) -m(t)i(blo)s(c)m(k)f(size.)0 2421 y(C)25 b(programmers)h(should)f(note)h -(that)g(the)h(ordering)e(of)h(arra)m(ys)g(in)g(FITS)f(\014les,)i(and)e -(hence)h(in)g(all)g(the)g(CFITSIO)0 2534 y(calls,)40 -b(is)d(more)g(similar)h(to)f(the)h(dimensionalit)m(y)g(of)f(arra)m(ys)g -(in)g(F)-8 b(ortran)38 b(rather)f(than)f(C.)h(F)-8 b(or)38 -b(instance)g(if)f(a)0 2647 y(FITS)28 b(image)i(has)e(NAXIS1)h(=)f(100)i -(and)e(NAXIS2)h(=)f(50,)i(then)e(a)h(2-D)h(arra)m(y)f(just)f(large)i -(enough)e(to)i(hold)e(the)0 2760 y(image)k(should)d(b)s(e)h(declared)h -(as)f(arra)m(y[50][100])k(and)c(not)h(as)f(arra)m(y[100][50].)0 -2920 y(The)h(`datat)m(yp)s(e')h(parameter)g(sp)s(eci\014es)e(the)i -(data)g(t)m(yp)s(e)f(of)g(the)g(`n)m(ulv)-5 b(al')32 -b(and)f(`arra)m(y')h(p)s(oin)m(ters)f(and)f(can)i(ha)m(v)m(e)0 -3033 y(one)h(of)g(the)g(follo)m(wing)h(v)-5 b(alues:)46 -b(TBYTE,)33 b(TSBYTE,)f(TSHOR)-8 b(T,)32 b(TUSHOR)-8 -b(T,)32 b(TINT,)h(TUINT,)f(TLONG,)0 3146 y(TLONGLONG,)26 -b(TULONG,)g(TFLO)m(A)-8 b(T,)27 b(TDOUBLE.)f(Automatic)i(data)f(t)m(yp) -s(e)g(con)m(v)m(ersion)g(is)f(p)s(erformed)f(if)0 3259 -y(the)j(data)h(t)m(yp)s(e)f(of)f(the)i(FITS)e(arra)m(y)h(\(as)g -(de\014ned)f(b)m(y)h(the)g(BITPIX)f(k)m(eyw)m(ord\))i(di\013ers)e(from) -h(that)g(sp)s(eci\014ed)f(b)m(y)0 3372 y('datat)m(yp)s(e'.)54 -b(The)34 b(data)h(v)-5 b(alues)35 b(are)f(also)i(automatically)h -(scaled)e(b)m(y)f(the)h(BSCALE)f(and)f(BZER)m(O)h(k)m(eyw)m(ord)0 -3485 y(v)-5 b(alues)31 b(as)f(they)h(are)g(b)s(eing)f(read)g(or)g -(written)h(in)f(the)g(FITS)g(arra)m(y)-8 b(.)0 3701 y -Fi(1)81 b Fj(Get)33 b(the)f(data)h(t)m(yp)s(e)f(or)g(equiv)-5 -b(alen)m(t)34 b(data)f(t)m(yp)s(e)f(of)g(the)h(image.)47 -b(The)32 b(\014rst)f(routine)h(returns)f(the)h(ph)m(ysical)227 -3814 y(data)46 b(t)m(yp)s(e)f(of)h(the)f(FITS)f(image,)51 -b(as)45 b(giv)m(en)h(b)m(y)f(the)g(BITPIX)g(k)m(eyw)m(ord,)50 -b(with)44 b(allo)m(w)m(ed)j(v)-5 b(alues)46 b(of)227 -3927 y(BYTE)p 492 3927 28 4 v 33 w(IMG)23 b(\(8\),)i(SHOR)-8 -b(T)p 1215 3927 V 32 w(IMG)23 b(\(16\),)i(LONG)p 1934 -3927 V 33 w(IMG)e(\(32\),)i(LONGLONG)p 2921 3927 V 33 -w(IMG)e(\(64\),)i(FLO)m(A)-8 b(T)p 3684 3927 V 33 w(IMG)227 -4040 y(\(-32\),)31 b(and)c(DOUBLE)p 1043 4040 V 33 w(IMG)h(\(-64\).)42 -b(The)27 b(second)h(routine)f(is)h(similar,)h(except)g(that)f(if)g(the) -g(image)h(pixel)227 4153 y(v)-5 b(alues)33 b(are)g(scaled,)g(with)f -(non-default)h(v)-5 b(alues)32 b(for)g(the)h(BZER)m(O)f(and)g(BSCALE)f -(k)m(eyw)m(ords,)j(then)e(the)227 4266 y(routine)j(will)g(return)e(the) -i('equiv)-5 b(alen)m(t')36 b(data)f(t)m(yp)s(e)g(that)g(is)f(needed)h -(to)g(store)g(the)g(scaled)g(v)-5 b(alues.)53 b(F)-8 -b(or)227 4378 y(example,)29 b(if)e(BITPIX)g(=)g(16)h(and)f(BSCALE)f(=)h -(0.1)h(then)f(the)h(equiv)-5 b(alen)m(t)28 b(data)g(t)m(yp)s(e)g(is)f -(FLO)m(A)-8 b(T)p 3659 4378 V 33 w(IMG.)227 4491 y(Similarly)25 -b(if)f(BITPIX)g(=)g(16,)i(BSCALE)e(=)g(1,)i(and)d(BZER)m(O)h(=)g -(32768,)k(then)c(the)g(the)h(pixel)f(v)-5 b(alues)25 -b(span)227 4604 y(the)31 b(range)g(of)f(an)g(unsigned)g(short)g(in)m -(teger)h(and)f(the)h(returned)e(data)i(t)m(yp)s(e)g(will)f(b)s(e)g -(USHOR)-8 b(T)p 3572 4604 V 32 w(IMG.)95 4820 y Fe(int)47 -b(fits_get_img_type)c(/)48 b(ffgidt)286 4933 y(\(fitsfile)e(*fptr,)g(>) -h(int)g(*bitpix,)f(int)h(*status\))95 5159 y(int)g -(fits_get_img_equivtype)42 b(/)48 b(ffgiet)286 5272 y(\(fitsfile)e -(*fptr,)g(>)h(int)g(*bitpix,)f(int)h(*status\))0 5488 -y Fi(2)81 b Fj(Get)34 b(the)g(n)m(um)m(b)s(er)e(of)i(dimensions,)g -(and/or)g(the)g(size)g(of)g(eac)m(h)h(dimension)e(in)g(the)h(image)h(.) -50 b(The)33 b(n)m(um)m(b)s(er)227 5601 y(of)h(axes)f(in)g(the)g(image)i -(is)e(giv)m(en)h(b)m(y)f(naxis,)h(and)f(the)g(size)h(of)f(eac)m(h)i -(dimension)d(is)h(giv)m(en)h(b)m(y)f(the)h(naxes)227 -5714 y(arra)m(y)d(\(a)g(maxim)m(um)g(of)f(maxdim)g(dimensions)g(will)g -(b)s(e)g(returned\).)p eop end -%%Page: 44 52 -TeXDict begin 44 51 bop 0 299 a Fj(44)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_get_img_dim)d(/)j(ffgidm)286 -668 y(\(fitsfile)f(*fptr,)g(>)h(int)g(*naxis,)f(int)h(*status\))95 -894 y(int)g(fits_get_img_size)c(/)48 b(ffgisz)286 1007 -y(\(fitsfile)e(*fptr,)g(int)h(maxdim,)e(>)j(long)f(*naxes,)e(int)i -(*status\))95 1233 y(int)g(fits_get_img_sizell)c(/)k(ffgiszll)286 -1346 y(\(fitsfile)f(*fptr,)g(int)h(maxdim,)e(>)j(LONGLONG)d(*naxes,)h -(int)h(*status\))95 1571 y(int)g(fits_get_img_param)c(/)48 -b(ffgipr)286 1684 y(\(fitsfile)e(*fptr,)g(int)h(maxdim,)e(>)j(int)f -(*bitpix,)e(int)i(*naxis,)f(long)h(*naxes,)334 1797 y(int)g(*status\)) -95 2023 y(int)g(fits_get_img_paramll)c(/)k(ffgiprll)286 -2136 y(\(fitsfile)f(*fptr,)g(int)h(maxdim,)e(>)j(int)f(*bitpix,)e(int)i -(*naxis,)f(LONGLONG)g(*naxes,)334 2249 y(int)h(*status\))0 -2504 y Fi(3)81 b Fj(Create)23 b(a)f(new)g(primary)f(arra)m(y)i(or)f -(IMA)m(GE)i(extension)e(with)g(a)h(sp)s(eci\014ed)f(data)h(t)m(yp)s(e)f -(and)g(size.)38 b(If)22 b(the)h(FITS)227 2617 y(\014le)30 -b(is)g(curren)m(tly)f(empt)m(y)h(then)g(a)g(primary)f(arra)m(y)h(is)g -(created,)h(otherwise)f(a)g(new)f(IMA)m(GE)i(extension)f(is)227 -2730 y(app)s(ended)f(to)i(the)g(\014le.)95 2985 y Fe(int)47 -b(fits_create_img)d(/)j(ffcrim)286 3098 y(\()h(fitsfile)d(*fptr,)h(int) -h(bitpix,)f(int)h(naxis,)f(long)h(*naxes,)f(>)h(int)g(*status\))95 -3324 y(int)g(fits_create_imgll)c(/)48 b(ffcrimll)286 -3437 y(\()g(fitsfile)d(*fptr,)h(int)h(bitpix,)f(int)h(naxis,)f -(LONGLONG)g(*naxes,)g(>)h(int)g(*status\))0 3692 y Fi(4)81 -b Fj(Cop)m(y)39 b(an)f(n-dimensional)h(image)h(in)f(a)g(particular)h -(ro)m(w)f(and)f(column)h(of)g(a)g(binary)f(table)i(\(in)f(a)g(v)m -(ector)227 3805 y(column\))31 b(to)g(or)f(from)g(a)h(primary)e(arra)m -(y)i(or)g(image)g(extension.)227 3954 y(The)c('cell2image')k(routine)d -(will)g(app)s(end)e(a)i(new)f(image)i(extension)f(\(or)g(primary)f -(arra)m(y\))h(to)h(the)e(output)227 4067 y(\014le.)43 -b(An)m(y)31 b(W)m(CS)g(k)m(eyw)m(ords)g(asso)s(ciated)h(with)f(the)g -(input)f(column)h(image)h(will)f(b)s(e)f(translated)i(in)m(to)g(the)227 -4180 y(appropriate)j(form)g(for)g(an)f(image)j(extension.)55 -b(An)m(y)35 b(other)g(k)m(eyw)m(ords)g(in)g(the)g(table)h(header)f -(that)h(are)227 4293 y(not)28 b(sp)s(eci\014cally)h(related)f(to)h -(de\014ning)e(the)g(binary)g(table)i(structure)e(or)h(to)g(other)g -(columns)g(in)f(the)h(table)227 4406 y(will)j(also)g(b)s(e)f(copied)h -(to)g(the)g(header)f(of)g(the)h(output)f(image.)227 4555 -y(The)i('image2cell')k(routine)c(will)h(cop)m(y)g(the)g(input)e(image)j -(in)m(to)f(the)g(sp)s(eci\014ed)f(ro)m(w)g(and)g(column)g(of)h(the)227 -4668 y(curren)m(t)e(binary)g(table)h(in)f(the)h(output)f(\014le.)44 -b(The)31 b(binary)f(table)j(HDU)f(m)m(ust)f(exist)h(b)s(efore)f -(calling)i(this)227 4781 y(routine,)h(but)f(it)h(ma)m(y)f(b)s(e)g(empt) -m(y)-8 b(,)35 b(with)e(no)g(ro)m(ws)g(or)g(columns)g(of)g(data.)50 -b(The)33 b(sp)s(eci\014ed)f(column)h(\(and)227 4894 y(ro)m(w\))e(will)h -(b)s(e)e(created)h(if)g(it)g(do)s(es)g(not)g(already)g(exist.)43 -b(The)30 b('cop)m(yk)m(ey\015ag')j(parameter)e(con)m(trols)h(whic)m(h) -227 5007 y(k)m(eyw)m(ords)26 b(are)g(copied)g(from)f(the)g(input)g -(image)h(to)g(the)g(header)f(of)h(the)f(output)g(table:)39 -b(0)26 b(=)f(no)h(k)m(eyw)m(ords)227 5120 y(will)k(b)s(e)g(copied,)g(1) -h(=)e(all)i(k)m(eyw)m(ords)f(will)g(b)s(e)f(copied)h(\(except)i(those)e -(k)m(eyw)m(ords)g(that)h(w)m(ould)e(b)s(e)g(in)m(v)-5 -b(alid)227 5233 y(in)30 b(the)h(table)g(header\),)g(and)f(2)g(=)g(cop)m -(y)i(only)e(the)h(W)m(CS)f(k)m(eyw)m(ords.)95 5488 y -Fe(int)47 b(fits_copy_cell2image)286 5601 y(\(fitsfile)f(*infptr,)f -(fitsfile)h(*outfptr,)f(char)i(*colname,)e(long)i(rownum,)334 -5714 y(>)h(int)e(*status\))p eop end -%%Page: 45 53 -TeXDict begin 45 52 bop 0 299 a Fh(5.5.)72 b(PRIMAR)-8 -b(Y)31 b(ARRA)-8 b(Y)31 b(OR)f(IMA)m(GE)h(EXTENSION)f(I/O)g(R)m -(OUTINES)1011 b Fj(45)95 668 y Fe(int)47 b(fits_copy_image2cell)286 -781 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(char)i(*colname,)e -(long)i(rownum,)334 894 y(int)g(copykeyflag)e(>)i(int)g(*status\))0 -1135 y Fi(5)81 b Fj(W)-8 b(rite)40 b(a)f(rectangular)g(subimage)g(\(or) -g(the)g(whole)g(image\))h(to)f(the)g(FITS)f(data)h(arra)m(y)-8 -b(.)67 b(The)38 b(fpixel)h(and)227 1248 y(lpixel)30 b(arra)m(ys)g(giv)m -(e)h(the)f(co)s(ordinates)g(of)f(the)h(\014rst)f(\(lo)m(w)m(er)i(left)f -(corner\))g(and)f(last)h(\(upp)s(er)e(righ)m(t)i(corner\))227 -1361 y(pixels)h(in)f(FITS)g(image)h(to)g(b)s(e)f(written)g(to.)95 -1602 y Fe(int)47 b(fits_write_subset)c(/)48 b(ffpss)286 -1715 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(long)i(*fpixel,)e(long)i -(*lpixel,)334 1828 y(DTYPE)f(*array,)g(>)i(int)f(*status\))0 -2070 y Fi(6)81 b Fj(W)-8 b(rite)39 b(pixels)g(in)m(to)g(the)g(FITS)f -(data)h(arra)m(y)-8 b(.)66 b('fpixel')39 b(is)f(an)g(arra)m(y)h(of)g -(length)g(NAXIS)f(whic)m(h)g(giv)m(es)i(the)227 2183 -y(co)s(ordinate)k(of)f(the)g(starting)g(pixel)g(to)h(b)s(e)e(written)h -(to,)j(suc)m(h)d(that)g(fpixel[0])h(is)f(in)f(the)h(range)g(1)g(to)227 -2295 y(NAXIS1,)34 b(fpixel[1])f(is)g(in)f(the)g(range)h(1)g(to)g -(NAXIS2,)g(etc.)48 b(The)32 b(\014rst)g(pair)g(of)h(routines)f(simply)g -(writes)227 2408 y(the)40 b(arra)m(y)g(of)g(pixels)f(to)i(the)e(FITS)g -(\014le)h(\(doing)g(data)g(t)m(yp)s(e)g(con)m(v)m(ersion)h(if)e -(necessary\))h(whereas)g(the)227 2521 y(second)c(routines)g(will)g -(substitute)f(the)h(appropriate)g(FITS)f(n)m(ull)g(v)-5 -b(alue)37 b(for)e(an)m(y)h(elemen)m(ts)h(whic)m(h)f(are)227 -2634 y(equal)41 b(to)g(the)f(input)g(v)-5 b(alue)40 b(of)h(n)m(ulv)-5 -b(al)40 b(\(note)h(that)g(this)f(parameter)h(giv)m(es)h(the)e(address)f -(of)i(the)f(n)m(ull)227 2747 y(v)-5 b(alue,)36 b(not)f(the)f(n)m(ull)g -(v)-5 b(alue)35 b(itself)7 b(\).)53 b(F)-8 b(or)35 b(in)m(teger)h(FITS) -d(arra)m(ys,)j(the)f(FITS)e(n)m(ull)h(v)-5 b(alue)35 -b(is)f(de\014ned)f(b)m(y)227 2860 y(the)26 b(BLANK)f(k)m(eyw)m(ord)h -(\(an)g(error)f(is)g(returned)f(if)i(the)f(BLANK)h(k)m(eyw)m(ord)g(do)s -(esn't)f(exist\).)40 b(F)-8 b(or)26 b(\015oating)227 -2973 y(p)s(oin)m(t)g(FITS)f(arra)m(ys)h(the)g(sp)s(ecial)g(IEEE)f(NaN)i -(\(Not-a-Num)m(b)s(er\))g(v)-5 b(alue)26 b(will)g(b)s(e)f(written)h(in) -m(to)h(the)f(FITS)227 3086 y(\014le.)66 b(If)38 b(a)h(n)m(ull)f(p)s -(oin)m(ter)h(is)f(en)m(tered)h(for)g(n)m(ulv)-5 b(al,)41 -b(then)d(the)h(n)m(ull)f(v)-5 b(alue)39 b(is)g(ignored)g(and)e(this)i -(routine)227 3199 y(b)s(eha)m(v)m(es)31 b(the)g(same)g(as)f(\014ts)p -1189 3199 28 4 v 33 w(write)p 1424 3199 V 33 w(pix.)95 -3440 y Fe(int)47 b(fits_write_pix)d(/)k(ffppx)286 3553 -y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(long)i(*fpixel,)e(LONGLONG)h -(nelements,)334 3666 y(DTYPE)g(*array,)g(int)h(*status\);)95 -3892 y(int)g(fits_write_pixll)d(/)j(ffppxll)286 4005 -y(\(fitsfile)f(*fptr,)g(int)h(datatype,)e(LONGLONG)g(*fpixel,)h -(LONGLONG)g(nelements,)334 4118 y(DTYPE)g(*array,)g(int)h(*status\);)95 -4343 y(int)g(fits_write_pixnull)c(/)48 b(ffppxn)286 4456 -y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(long)i(*fpixel,)e(LONGLONG)h -(nelements,)334 4569 y(DTYPE)g(*array,)g(DTYPE)h(*nulval,)e(>)j(int)f -(*status\);)95 4795 y(int)g(fits_write_pixnullll)c(/)k(ffppxnll)286 -4908 y(\(fitsfile)f(*fptr,)g(int)h(datatype,)e(LONGLONG)g(*fpixel,)h -(LONGLONG)g(nelements,)334 5021 y(DTYPE)g(*array,)g(DTYPE)h(*nulval,)e -(>)j(int)f(*status\);)0 5262 y Fi(7)81 b Fj(Set)24 b(FITS)g(data)i -(arra)m(y)f(elemen)m(ts)h(equal)f(to)g(the)g(appropriate)f(n)m(ull)h -(pixel)g(v)-5 b(alue.)39 b(F)-8 b(or)25 b(in)m(teger)h(FITS)e(arra)m -(ys,)227 5375 y(the)34 b(FITS)e(n)m(ull)h(v)-5 b(alue)34 -b(is)f(de\014ned)f(b)m(y)h(the)h(BLANK)f(k)m(eyw)m(ord)h(\(an)f(error)g -(is)g(returned)f(if)h(the)h(BLANK)227 5488 y(k)m(eyw)m(ord)23 -b(do)s(esn't)g(exist\).)39 b(F)-8 b(or)23 b(\015oating)g(p)s(oin)m(t)g -(FITS)f(arra)m(ys)g(the)h(sp)s(ecial)g(IEEE)f(NaN)h(\(Not-a-Num)m(b)s -(er\))227 5601 y(v)-5 b(alue)34 b(will)f(b)s(e)g(written)g(in)m(to)h -(the)g(FITS)e(\014le.)49 b(Note)34 b(that)g('\014rstelem')g(is)f(a)h -(scalar)g(giving)g(the)f(o\013set)h(to)227 5714 y(the)d(\014rst)e -(pixel)i(to)g(b)s(e)f(written)g(in)h(the)f(equiv)-5 b(alen)m(t)32 -b(1-dimensional)f(arra)m(y)g(of)g(image)g(pixels.)p eop -end -%%Page: 46 54 -TeXDict begin 46 53 bop 0 299 a Fj(46)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_write_null_img)c(/)k(ffpprn)286 -668 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(firstelem,)g(LONGLONG)h -(nelements,)f(>)i(int)g(*status\))0 925 y Fi(8)81 b Fj(Read)33 -b(a)h(rectangular)h(subimage)f(\(or)g(the)g(whole)g(image\))h(from)e -(the)h(FITS)f(data)h(arra)m(y)-8 b(.)52 b(The)33 b(fpixel)h(and)227 -1038 y(lpixel)c(arra)m(ys)g(giv)m(e)h(the)f(co)s(ordinates)g(of)f(the)h -(\014rst)f(\(lo)m(w)m(er)i(left)f(corner\))g(and)f(last)h(\(upp)s(er)e -(righ)m(t)i(corner\))227 1151 y(pixels)d(to)h(b)s(e)e(read)h(from)g -(the)g(FITS)f(image.)41 b(Unde\014ned)25 b(FITS)h(arra)m(y)i(elemen)m -(ts)g(will)f(b)s(e)f(returned)g(with)227 1263 y(a)k(v)-5 -b(alue)30 b(=)e(*n)m(ullv)-5 b(al,)31 b(\(note)f(that)g(this)f -(parameter)h(giv)m(es)g(the)g(address)e(of)h(the)h(n)m(ull)f(v)-5 -b(alue,)30 b(not)g(the)f(n)m(ull)227 1376 y(v)-5 b(alue)36 -b(itself)7 b(\))37 b(unless)e(n)m(ulv)-5 b(al)36 b(=)g(0)g(or)f(*n)m -(ulv)-5 b(al)37 b(=)e(0,)j(in)d(whic)m(h)g(case)i(no)f(c)m(hec)m(ks)h -(for)e(unde\014ned)f(pixels)227 1489 y(will)d(b)s(e)f(p)s(erformed.)95 -1746 y Fe(int)47 b(fits_read_subset)d(/)j(ffgsv)286 1859 -y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(long)g(*fpixel,)g(long) -g(*lpixel,)g(long)h(*inc,)334 1972 y(DTYPE)f(*nulval,)g(>)h(DTYPE)g -(*array,)f(int)h(*anynul,)e(int)i(*status\))0 2228 y -Fi(9)81 b Fj(Read)32 b(pixels)h(from)f(the)g(FITS)g(data)h(arra)m(y)-8 -b(.)48 b('fpixel')33 b(is)g(the)f(starting)h(pixel)g(lo)s(cation)h(and) -e(is)h(an)f(arra)m(y)h(of)227 2341 y(length)h(NAXIS)f(suc)m(h)g(that)h -(fpixel[0])g(is)f(in)g(the)h(range)f(1)h(to)g(NAXIS1,)g(fpixel[1])g(is) -g(in)f(the)g(range)h(1)f(to)227 2454 y(NAXIS2,)c(etc.)41 -b(The)28 b(nelemen)m(ts)h(parameter)f(sp)s(eci\014es)g(the)g(n)m(um)m -(b)s(er)f(of)h(pixels)h(to)g(read.)39 b(If)28 b(fpixel)g(is)g(set)227 -2567 y(to)36 b(the)f(\014rst)f(pixel,)j(and)e(nelemen)m(ts)g(is)g(set)h -(equal)g(to)f(the)g(NAXIS1)h(v)-5 b(alue,)37 b(then)d(this)h(routine)g -(w)m(ould)227 2680 y(read)28 b(the)g(\014rst)f(ro)m(w)h(of)g(the)h -(image.)41 b(Alternativ)m(ely)-8 b(,)31 b(if)d(nelemen)m(ts)h(is)f(set) -g(equal)h(to)f(NAXIS1)g(*)h(NAXIS2)227 2793 y(then)h(it)h(w)m(ould)f -(read)h(an)f(en)m(tire)h(2D)g(image,)h(or)f(the)f(\014rst)g(plane)g(of) -h(a)g(3-D)g(datacub)s(e.)227 2943 y(The)38 b(\014rst)g(2)h(routines)f -(will)h(return)f(an)m(y)h(unde\014ned)d(pixels)j(in)f(the)h(FITS)e -(arra)m(y)i(equal)g(to)h(the)e(v)-5 b(alue)227 3055 y(of)36 -b(*n)m(ullv)-5 b(al)36 b(\(note)g(that)g(this)f(parameter)h(giv)m(es)g -(the)g(address)e(of)i(the)f(n)m(ull)g(v)-5 b(alue,)37 -b(not)f(the)f(n)m(ull)g(v)-5 b(alue)227 3168 y(itself)7 -b(\))34 b(unless)d(n)m(ulv)-5 b(al)32 b(=)g(0)g(or)h(*n)m(ulv)-5 -b(al)32 b(=)g(0,)h(in)f(whic)m(h)g(case)h(no)f(c)m(hec)m(ks)h(for)f -(unde\014ned)e(pixels)i(will)h(b)s(e)227 3281 y(p)s(erformed.)42 -b(The)31 b(second)h(2)f(routines)h(are)f(similar)h(except)g(that)g(an)m -(y)g(unde\014ned)d(pixels)i(will)h(ha)m(v)m(e)h(the)227 -3394 y(corresp)s(onding)d(n)m(ullarra)m(y)g(elemen)m(t)i(set)f(equal)g -(to)g(TR)m(UE)g(\(=)f(1\).)95 3651 y Fe(int)47 b(fits_read_pix)e(/)i -(ffgpxv)286 3764 y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 -b(long)g(*fpixel,)g(LONGLONG)f(nelements,)334 3877 y(DTYPE)h(*nulval,)g -(>)h(DTYPE)g(*array,)f(int)h(*anynul,)e(int)i(*status\))95 -4102 y(int)g(fits_read_pixll)d(/)j(ffgpxvll)286 4215 -y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(LONGLONG)f(*fpixel,)h -(LONGLONG)f(nelements,)334 4328 y(DTYPE)h(*nulval,)g(>)h(DTYPE)g -(*array,)f(int)h(*anynul,)e(int)i(*status\))95 4554 y(int)g -(fits_read_pixnull)c(/)48 b(ffgpxf)286 4667 y(\(fitsfile)e(*fptr,)g -(int)94 b(datatype,)46 b(long)g(*fpixel,)g(LONGLONG)f(nelements,)334 -4780 y(>)j(DTYPE)e(*array,)g(char)g(*nullarray,)f(int)i(*anynul,)f(int) -g(*status\))95 5006 y(int)h(fits_read_pixnullll)c(/)k(ffgpxfll)286 -5119 y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(LONGLONG)f -(*fpixel,)h(LONGLONG)f(nelements,)334 5231 y(>)j(DTYPE)e(*array,)g -(char)g(*nullarray,)f(int)i(*anynul,)f(int)g(*status\))0 -5488 y Fi(10)g Fj(Cop)m(y)36 b(a)g(rectangular)h(section)g(of)g(an)e -(image)j(and)d(write)h(it)h(to)f(a)h(new)e(FITS)g(primary)g(image)j(or) -e(image)227 5601 y(extension.)49 b(The)32 b(new)g(image)i(HDU)g(is)e -(app)s(ended)f(to)j(the)f(end)f(of)h(the)g(output)f(\014le;)i(all)g -(the)f(k)m(eyw)m(ords)227 5714 y(in)39 b(the)f(input)g(image)i(will)f -(b)s(e)f(copied)h(to)g(the)g(output)f(image.)66 b(The)38 -b(common)h(W)m(CS)g(k)m(eyw)m(ords)g(will)p eop end -%%Page: 47 55 -TeXDict begin 47 54 bop 0 299 a Fh(5.6.)72 b(IMA)m(GE)31 -b(COMPRESSION)2567 b Fj(47)227 555 y(b)s(e)34 b(up)s(dated)f(if)i -(necessary)g(to)g(corresp)s(ond)e(to)j(the)e(co)s(ordinates)h(of)g(the) -g(section.)54 b(The)34 b(format)h(of)g(the)227 668 y(section)29 -b(expression)e(is)g(same)g(as)h(sp)s(ecifying)f(an)g(image)h(section)h -(using)d(the)i(extended)f(\014le)g(name)g(syn)m(tax)227 -781 y(\(see)32 b("Image)f(Section")h(in)e(Chapter)g(10\).)42 -b(\(Examples:)f("1:100,1:200",)36 b("1:100:2,)d(1:*:2",)g("*,)f(-*"\).) -95 996 y Fe(int)47 b(fits_copy_image_section)42 b(/)47 -b(ffcpimg)286 1109 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f -(char)i(*section,)e(int)i(*status\))0 1436 y Ff(5.6)135 -b(Image)46 b(Compression)0 1686 y Fj(CFITSIO)29 b(transparen)m(tly)h -(supp)s(orts)f(the)h(2)h(metho)s(ds)f(of)g(image)i(compression)e -(describ)s(ed)g(b)s(elo)m(w.)0 1846 y(1\))45 b(The)f(en)m(tire)i(FITS)e -(\014le)h(ma)m(y)g(b)s(e)f(externally)i(compressed)e(with)g(the)h(gzip) -g(or)g(Unix)f(compress)h(utilit)m(y)0 1959 y(programs,)37 -b(pro)s(ducing)d(a)j(*.gz)g(or)f(*.Z)g(\014le,)h(resp)s(ectiv)m(ely)-8 -b(.)59 b(When)36 b(reading)g(compressed)f(\014les)h(of)g(this)g(t)m(yp) -s(e,)0 2072 y(CFITSIO)43 b(\014rst)h(uncompresses)f(the)i(en)m(tire)g -(\014le)g(in)m(to)g(memory)g(b)s(efore)f(p)s(erforming)f(the)i -(requested)f(read)0 2185 y(op)s(erations.)c(Output)28 -b(\014les)g(can)h(b)s(e)f(directly)i(written)e(in)g(the)h(gzip)g -(compressed)g(format)g(if)f(the)h(user-sp)s(eci\014ed)0 -2298 y(\014lename)35 b(ends)e(with)i(`.gz'.)54 b(In)34 -b(this)g(case,)j(CFITSIO)c(initially)j(writes)e(the)h(uncompressed)e -(\014le)i(in)f(memory)0 2411 y(and)j(then)g(compresses)g(it)h(and)f -(writes)g(it)h(to)g(disk)f(when)f(the)i(FITS)f(\014le)g(is)g(closed,)k -(th)m(us)36 b(sa)m(ving)j(user)d(disk)0 2524 y(space.)59 -b(Read)36 b(and)g(write)h(access)g(to)g(these)g(compressed)f(FITS)g -(\014les)g(is)g(generally)i(quite)e(fast)h(since)g(all)g(the)0 -2636 y(I/O)28 b(is)g(p)s(erformed)e(in)i(memory;)h(the)f(main)g -(limitation)i(with)e(this)f(tec)m(hnique)i(is)f(that)h(there)f(m)m(ust) -g(b)s(e)f(enough)0 2749 y(a)m(v)-5 b(ailable)33 b(memory)d(\(or)h(sw)m -(ap)f(space\))h(to)g(hold)f(the)h(en)m(tire)g(uncompressed)e(FITS)h -(\014le.)0 2910 y(2\))42 b(CFITSIO)d(also)j(supp)s(orts)d(the)j(FITS)e -(tiled)h(image)i(compression)e(con)m(v)m(en)m(tion)i(in)e(whic)m(h)f -(the)i(image)g(is)0 3022 y(sub)s(divided)30 b(in)m(to)j(a)f(grid)g(of)g -(rectangular)i(tiles,)f(and)f(eac)m(h)h(tile)g(of)g(pixels)f(is)g -(individually)g(compressed.)45 b(The)0 3135 y(details)c(of)f(this)g -(FITS)g(compression)g(con)m(v)m(en)m(tion)i(are)e(describ)s(ed)f(at)i -(the)g(FITS)e(Supp)s(ort)f(O\016ce)i(w)m(eb)g(site)0 -3248 y(at)c(h)m(ttp://\014ts.gsfc.nasa.go)m(v/\014ts)p -1230 3248 28 4 v 37 w(registry)-8 b(.h)m(tml,)38 b(and)d(in)g(the)g -(fpac)m(kguide)h(p)s(df)e(\014le)h(that)h(is)g(included)e(with)0 -3361 y(the)h(CFITSIO)f(source)h(\014le)h(distributions)e(Basically)-8 -b(,)39 b(the)c(compressed)g(image)i(tiles)f(are)g(stored)f(in)g(ro)m -(ws)g(of)0 3474 y(a)42 b(v)-5 b(ariable)42 b(length)g(arra)m(y)h -(column)e(in)g(a)h(FITS)f(binary)g(table,)46 b(ho)m(w)m(ev)m(er)c -(CFITSIO)f(recognizes)i(that)f(this)0 3587 y(binary)37 -b(table)i(extension)f(con)m(tains)h(an)e(image)i(and)e(treats)i(it)f -(as)g(if)g(it)g(w)m(ere)g(an)g(IMA)m(GE)g(extension.)64 -b(This)0 3700 y(tile-compressed)37 b(format)f(is)f(esp)s(ecially)i(w)m -(ell)g(suited)e(for)h(compressing)f(v)m(ery)h(large)h(images)g(b)s -(ecause)e(a\))i(the)0 3813 y(FITS)28 b(header)h(k)m(eyw)m(ords)h -(remain)f(uncompressed)e(for)i(rapid)g(read)g(access,)h(and)f(b)s -(ecause)g(b\))g(it)g(is)h(p)s(ossible)e(to)0 3926 y(extract)f(and)e -(uncompress)g(sections)i(of)f(the)g(image)h(without)e(ha)m(ving)i(to)f -(uncompress)f(the)h(en)m(tire)g(image.)41 b(This)0 4039 -y(format)34 b(is)g(also)h(m)m(uc)m(h)e(more)h(e\013ectiv)m(e)j(in)c -(compressing)h(\015oating)h(p)s(oin)m(t)e(images)i(than)f(simply)f -(compressing)0 4152 y(the)39 b(image)i(using)d(gzip)i(or)f(compress)g -(b)s(ecause)g(it)h(appro)m(ximates)g(the)g(\015oating)g(p)s(oin)m(t)f -(v)-5 b(alues)39 b(with)g(scaled)0 4264 y(in)m(tegers)32 -b(whic)m(h)e(can)g(then)g(b)s(e)g(compressed)g(more)h(e\016cien)m(tly) --8 b(.)0 4425 y(Curren)m(tly)41 b(CFITSIO)e(supp)s(orts)h(3)h(general)i -(purp)s(ose)c(compression)i(algorithms)i(plus)d(one)i(other)f(sp)s -(ecial-)0 4538 y(purp)s(ose)31 b(compression)i(tec)m(hnique)h(that)f -(is)g(designed)g(for)g(data)g(masks)g(with)g(p)s(ositiv)m(e)h(in)m -(teger)g(pixel)f(v)-5 b(alues.)0 4650 y(The)40 b(3)g(general)h(purp)s -(ose)e(algorithms)i(are)f(GZIP)-8 b(,)41 b(Rice,)j(and)39 -b(HCOMPRESS,)g(and)h(the)g(sp)s(ecial)h(purp)s(ose)0 -4763 y(algorithm)33 b(is)f(the)g(IRAF)g(pixel)g(list)h(compression)f -(tec)m(hnique)g(\(PLIO\).)g(There)g(are)g(2)g(v)-5 b(arian)m(ts)33 -b(of)f(the)g(GZIP)0 4876 y(algorithm:)46 b(GZIP)p 681 -4876 V 33 w(1)33 b(compresses)f(the)h(arra)m(y)g(of)g(image)h(pixel)f -(v)-5 b(alue)33 b(normally)g(with)g(the)f(GZIP)h(algorithm,)0 -4989 y(while)26 b(GZIP)p 460 4989 V 32 w(2)g(\014rst)f(sh)m(u\017es)g -(the)g(b)m(ytes)i(in)e(all)h(the)g(pixel)g(v)-5 b(alues)26 -b(so)g(that)g(the)g(most-signi\014can)m(t)h(b)m(yte)f(of)g(ev)m(ery)0 -5102 y(pixel)h(app)s(ears)e(\014rst,)i(follo)m(w)m(ed)h(b)m(y)e(the)g -(less)h(signi\014can)m(t)g(b)m(ytes)g(in)f(sequence.)39 -b(GZIP)p 2944 5102 V 33 w(2)26 b(ma)m(y)h(b)s(e)f(more)g(e\013ectiv)m -(e)0 5215 y(in)36 b(cases)h(where)e(the)h(most)h(signi\014can)m(t)f(b)m -(yte)h(in)f(most)g(of)g(the)g(image)i(pixel)e(v)-5 b(alues)36 -b(con)m(tains)h(the)g(same)f(bit)0 5328 y(pattern.)41 -b(In)29 b(principle,)h(an)m(y)g(n)m(um)m(b)s(er)f(of)h(other)g -(compression)g(algorithms)h(could)f(also)h(b)s(e)e(supp)s(orted)f(b)m -(y)i(the)0 5441 y(FITS)g(tiled)h(image)g(compression)g(con)m(v)m(en)m -(tion.)0 5601 y(The)k(FITS)g(image)h(can)g(b)s(e)f(sub)s(divided)e(in)m -(to)k(an)m(y)f(desired)f(rectangular)h(grid)f(of)h(compression)f -(tiles.)57 b(With)0 5714 y(the)32 b(GZIP)-8 b(,)33 b(Rice,)h(and)e -(PLIO)f(algorithms,)j(the)e(default)h(is)f(to)h(tak)m(e)h(eac)m(h)g(ro) -m(w)e(of)h(the)f(image)i(as)e(a)h(tile.)47 b(The)p eop -end -%%Page: 48 56 -TeXDict begin 48 55 bop 0 299 a Fj(48)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Fj(HCOMPRESS)25 b(algorithm)i(is)g(inheren)m(tly) -f(2-dimensional)h(in)f(nature,)i(so)e(the)h(default)f(in)g(this)g(case) -i(is)e(to)h(tak)m(e)0 668 y(16)h(ro)m(ws)g(of)f(the)h(image)h(p)s(er)d -(tile.)41 b(In)27 b(most)h(cases)g(it)g(mak)m(es)h(little)g -(di\013erence)f(what)f(tiling)i(pattern)f(is)f(used,)h(so)0 -781 y(the)33 b(default)g(tiles)g(are)g(usually)g(adequate.)48 -b(In)32 b(the)h(case)g(of)g(v)m(ery)g(small)g(images,)i(it)e(could)g(b) -s(e)f(more)g(e\016cien)m(t)0 894 y(to)h(compress)f(the)h(whole)f(image) -i(as)e(a)h(single)g(tile.)48 b(Note)34 b(that)f(the)f(image)i -(dimensions)d(are)i(not)g(required)e(to)0 1007 y(b)s(e)d(an)g(in)m -(teger)i(m)m(ultiple)f(of)f(the)h(tile)g(dimensions;)g(if)f(not,)i -(then)e(the)g(tiles)i(at)f(the)f(edges)h(of)g(the)f(image)i(will)f(b)s -(e)0 1120 y(smaller)i(than)f(the)h(other)f(tiles.)0 1280 -y(The)41 b(4)g(supp)s(orted)f(image)i(compression)f(algorithms)h(are)g -(all)g('loss-less')h(when)d(applied)h(to)h(in)m(teger)h(FITS)0 -1393 y(images;)25 b(the)c(pixel)g(v)-5 b(alues)20 b(are)h(preserv)m(ed) -f(exactly)j(with)d(no)g(loss)h(of)f(information)h(during)e(the)i -(compression)g(and)0 1506 y(uncompression)34 b(pro)s(cess.)54 -b(In)34 b(addition,)j(the)e(HCOMPRESS)f(algorithm)i(supp)s(orts)d(a)i -('lossy')h(compression)0 1619 y(mo)s(de)41 b(that)h(will)g(pro)s(duce)f -(larger)h(amoun)m(t)g(of)g(image)h(compression.)74 b(This)41 -b(is)g(ac)m(hiev)m(ed)j(b)m(y)d(sp)s(ecifying)h(a)0 1732 -y(non-zero)32 b(v)-5 b(alue)32 b(for)f(the)g(HCOMPRESS)f(\\scale")k -(parameter.)44 b(Since)31 b(the)g(amoun)m(t)h(of)g(compression)f(that)h -(is)0 1844 y(ac)m(hiev)m(ed)g(dep)s(ends)d(directly)i(on)f(the)h(RMS)f -(noise)h(in)f(the)h(image,)h(it)f(is)g(usually)f(more)g(con)m(v)m(en)m -(tion)j(to)e(sp)s(ecify)0 1957 y(the)f(HCOMPRESS)e(scale)i(factor)h -(relativ)m(e)g(to)f(the)g(RMS)f(noise.)41 b(Setting)30 -b(s)f(=)g(2.5)i(means)e(use)g(a)h(scale)h(factor)0 2070 -y(that)h(is)f(2.5)i(times)e(the)h(calculated)h(RMS)e(noise)h(in)f(the)g -(image)i(tile.)44 b(In)31 b(some)g(cases)h(it)g(ma)m(y)g(b)s(e)f -(desirable)g(to)0 2183 y(sp)s(ecify)h(the)g(exact)i(scaling)f(to)g(b)s -(e)e(used,)h(instead)h(of)f(sp)s(ecifying)g(it)g(relativ)m(e)j(to)d -(the)h(calculated)h(noise)e(v)-5 b(alue.)0 2296 y(This)37 -b(ma)m(y)h(b)s(e)f(done)g(b)m(y)h(sp)s(ecifying)f(the)h(negativ)m(e)i -(of)d(desired)g(scale)i(v)-5 b(alue)38 b(\(t)m(ypically)i(in)d(the)h -(range)g(-2)g(to)0 2409 y(-100\).)0 2569 y(V)-8 b(ery)43 -b(high)g(compression)f(factors)i(\(of)f(100)h(or)f(more\))g(can)g(b)s -(e)f(ac)m(hiev)m(ed)j(b)m(y)d(using)h(large)g(HCOMPRESS)0 -2682 y(scale)31 b(v)-5 b(alues,)31 b(ho)m(w)m(ev)m(er,)h(this)e(can)g -(pro)s(duce)f(undesirable)g(\\blo)s(c)m(ky")j(artifacts)f(in)f(the)g -(compressed)g(image.)42 b(A)0 2795 y(v)-5 b(ariation)27 -b(of)g(the)f(HCOMPRESS)f(algorithm)i(\(called)h(HSCOMPRESS\))c(can)i(b) -s(e)g(used)f(in)h(this)g(case)h(to)g(apply)0 2908 y(a)f(small)h(amoun)m -(t)f(of)h(smo)s(othing)f(of)g(the)g(image)h(when)e(it)i(is)f -(uncompressed)f(to)h(help)g(co)m(v)m(er)i(up)d(these)h(artifacts.)0 -3021 y(This)36 b(smo)s(othing)h(is)g(purely)f(cosmetic)j(and)d(do)s(es) -h(not)g(cause)g(an)m(y)h(signi\014can)m(t)g(c)m(hange)g(to)f(the)g -(image)i(pixel)0 3134 y(v)-5 b(alues.)0 3294 y(Floating)34 -b(p)s(oin)m(t)f(FITS)e(images)j(\(whic)m(h)e(ha)m(v)m(e)i(BITPIX)e(=)g -(-32)h(or)g(-64\))g(usually)f(con)m(tain)i(to)s(o)f(m)m(uc)m(h)g -(\\noise")0 3407 y(in)k(the)g(least)i(signi\014can)m(t)f(bits)f(of)h -(the)f(man)m(tissa)h(of)g(the)f(pixel)h(v)-5 b(alues)37 -b(to)h(b)s(e)f(e\013ectiv)m(ely)j(compressed)d(with)0 -3520 y(an)m(y)d(lossless)g(algorithm.)52 b(Consequen)m(tly)-8 -b(,)35 b(\015oating)g(p)s(oin)m(t)e(images)i(are)f(\014rst)f(quan)m -(tized)h(in)m(to)h(scaled)g(in)m(teger)0 3633 y(pixel)26 -b(v)-5 b(alues)25 b(\(and)g(th)m(us)g(thro)m(wing)h(a)m(w)m(a)m(y)h(m)m -(uc)m(h)e(of)h(the)f(noise\))h(b)s(efore)f(b)s(eing)g(compressed)g -(with)g(the)h(sp)s(eci\014ed)0 3745 y(algorithm)d(\(either)g(GZIP)-8 -b(,)23 b(Rice,)i(or)d(HCOMPRESS\).)f(This)h(tec)m(hnique)h(pro)s(duces) -e(m)m(uc)m(h)h(higher)g(compression)0 3858 y(factors)33 -b(than)e(simply)g(using)g(the)h(GZIP)g(utilit)m(y)h(to)f(externally)h -(compress)f(the)f(whole)h(FITS)f(\014le,)i(but)e(it)h(also)0 -3971 y(means)d(that)h(the)g(original)g(\015oating)g(v)-5 -b(alue)30 b(pixel)f(v)-5 b(alues)30 b(are)g(not)f(exactly)i(preserv)m -(ed.)40 b(When)29 b(done)g(prop)s(erly)-8 b(,)0 4084 -y(this)33 b(in)m(teger)h(scaling)f(tec)m(hnique)h(will)f(only)f -(discard)h(the)f(insigni\014can)m(t)i(noise)f(while)g(still)g -(preserving)f(all)i(the)0 4197 y(real)43 b(information)f(in)g(the)h -(image.)77 b(The)42 b(amoun)m(t)g(of)h(precision)f(that)h(is)f -(retained)h(in)e(the)i(pixel)f(v)-5 b(alues)43 b(is)0 -4310 y(con)m(trolled)37 b(b)m(y)d(the)i("quan)m(tization)h(lev)m(el")g -(parameter,)g(q.)54 b(Larger)35 b(v)-5 b(alues)36 b(of)f(q)f(will)i -(result)f(in)f(compressed)0 4423 y(images)h(whose)e(pixels)h(more)f -(closely)i(matc)m(h)g(the)e(\015oating)i(p)s(oin)m(t)e(pixel)h(v)-5 -b(alues,)35 b(but)e(at)h(the)g(same)g(time)g(the)0 4536 -y(amoun)m(t)j(of)f(compression)g(that)h(is)f(ac)m(hiev)m(ed)i(will)f(b) -s(e)e(reduced.)58 b(Users)36 b(should)f(exp)s(erimen)m(t)i(with)e -(di\013eren)m(t)0 4649 y(v)-5 b(alues)25 b(for)g(this)g(parameter)g(to) -h(determine)f(the)g(optimal)h(v)-5 b(alue)25 b(that)h(preserv)m(es)f -(all)h(the)f(useful)f(information)h(in)0 4762 y(the)k(image,)h(without) -f(needlessly)g(preserving)f(all)h(the)g(\\noise")h(whic)m(h)e(will)h(h) -m(urt)f(the)h(compression)f(e\016ciency)-8 b(.)0 4922 -y(The)38 b(default)g(v)-5 b(alue)38 b(for)g(the)g(quan)m(tization)i -(scale)g(factor)f(is)f(4.0,)j(whic)m(h)d(means)g(that)g(scaled)h(in)m -(teger)h(pixel)0 5035 y(v)-5 b(alues)41 b(will)h(b)s(e)e(quan)m(tized)i -(suc)m(h)f(that)h(the)f(di\013erence)h(b)s(et)m(w)m(een)f(adjacen)m(t)i -(in)m(teger)f(v)-5 b(alues)42 b(will)f(b)s(e)g(1/4th)0 -5148 y(of)35 b(the)h(noise)f(lev)m(el)i(in)e(the)g(image)h(bac)m -(kground.)55 b(CFITSIO)34 b(uses)g(an)h(optimized)h(algorithm)g(to)g -(accurately)0 5261 y(estimate)41 b(the)e(noise)h(in)f(the)g(image.)68 -b(As)39 b(an)g(example,)k(if)c(the)g(RMS)g(noise)g(in)g(the)h(bac)m -(kground)e(pixels)i(of)0 5373 y(an)35 b(image)h(=)f(32.0,)j(then)d(the) -h(spacing)f(b)s(et)m(w)m(een)h(adjacen)m(t)g(scaled)g(in)m(teger)h -(pixel)e(v)-5 b(alues)36 b(will)f(equal)h(8.0)g(b)m(y)0 -5486 y(default.)63 b(Note)38 b(that)h(the)e(RMS)h(noise)g(is)f(indep)s -(enden)m(tly)g(calculated)j(for)d(eac)m(h)i(tile)f(of)g(the)g(image,)j -(so)d(the)0 5599 y(resulting)24 b(in)m(teger)i(scaling)f(factor)g(ma)m -(y)g(\015uctuate)g(sligh)m(tly)g(for)f(eac)m(h)i(tile.)40 -b(In)23 b(some)i(cases)g(it)f(ma)m(y)h(b)s(e)f(desirable)0 -5712 y(to)29 b(sp)s(ecify)f(the)h(exact)h(quan)m(tization)h(lev)m(el)f -(to)f(b)s(e)f(used,)g(instead)h(of)g(sp)s(ecifying)f(it)h(relativ)m(e)i -(to)e(the)g(calculated)p eop end -%%Page: 49 57 -TeXDict begin 49 56 bop 0 299 a Fh(5.6.)72 b(IMA)m(GE)31 -b(COMPRESSION)2567 b Fj(49)0 555 y(noise)27 b(v)-5 b(alue.)40 -b(This)27 b(ma)m(y)g(b)s(e)g(done)f(b)m(y)h(sp)s(ecifying)g(the)g -(negativ)m(e)i(of)f(desired)e(quan)m(tization)j(lev)m(el)g(for)d(the)h -(v)-5 b(alue)0 668 y(of)29 b(q.)40 b(In)28 b(the)i(previous)e(example,) -i(one)f(could)g(sp)s(ecify)g(q)g(=)f(-8.0)j(so)e(that)h(the)f(quan)m -(tized)g(in)m(teger)i(lev)m(els)f(di\013er)0 781 y(b)m(y)k(exactly)j -(8.0.)54 b(Larger)35 b(negativ)m(e)i(v)-5 b(alues)35 -b(for)f(q)h(means)f(that)h(the)g(lev)m(els)h(are)f(more)g(coarsely)h -(spaced,)g(and)0 894 y(will)31 b(pro)s(duce)e(higher)h(compression)g -(factors.)0 1054 y(When)h(\015oating)g(p)s(oin)m(t)g(images)h(are)f(b)s -(eing)g(quan)m(tized,)h(one)f(m)m(ust)g(also)h(sp)s(ecify)e(what)h -(quan)m(tization)h(metho)s(d)0 1167 y(is)g(to)h(b)s(e)e(used.)44 -b(The)32 b(default)g(algorithm)g(is)g(called)h(\\SUBTRA)m(CTIVE)p -2567 1167 28 4 v 33 w(DITHER)p 2965 1167 V 33 w(1".)46 -b(A)32 b(second)g(v)-5 b(ariation)0 1280 y(called)30 -b(\\SUBTRA)m(CTIVE)p 982 1280 V 33 w(DITHER)p 1380 1280 -V 33 w(2")g(is)f(also)h(a)m(v)-5 b(ailable,)32 b(whic)m(h)d(do)s(es)g -(the)h(same)f(thing)h(except)g(that)g(an)m(y)0 1393 y(pixels)g(with)g -(a)g(v)-5 b(alue)31 b(of)f(0.0)h(are)f(not)g(dithered)g(and)f(instead)h -(the)g(zero)h(v)-5 b(alues)30 b(are)h(exactly)g(preserv)m(ed)f(in)g -(the)0 1506 y(compressed)35 b(image.)58 b(One)35 b(ma)m(y)h(also)h -(turn)d(o\013)i(dithering)g(completely)h(with)e(the)h(\\NO)p -3148 1506 V 33 w(DITHER")g(option,)0 1619 y(but)30 b(this)g(is)g(not)h -(recommended)f(b)s(ecause)g(it)h(can)g(cause)g(larger)g(systematic)h -(errors)e(in)g(measuremen)m(ts)g(of)h(the)0 1732 y(p)s(osition)f(or)h -(brigh)m(tness)f(of)g(ob)5 b(jects)32 b(in)e(the)g(compressed)g(image.) -0 1892 y(There)37 b(are)g(3)h(metho)s(ds)e(for)h(sp)s(ecifying)g(all)h -(the)g(parameters)f(needed)g(to)h(write)f(a)h(FITS)e(image)j(in)d(the)i -(tile)0 2005 y(compressed)28 b(format.)41 b(The)28 b(parameters)g(ma)m -(y)h(either)g(b)s(e)f(sp)s(eci\014ed)g(at)h(run)e(time)i(as)g(part)f -(of)h(the)g(\014le)f(name)h(of)0 2118 y(the)e(output)f(compressed)h -(FITS)e(\014le,)j(or)f(the)g(writing)f(program)h(ma)m(y)g(call)h(a)f -(set)g(of)g(help)s(er)f(CFITSIO)f(subrou-)0 2230 y(tines)36 -b(that)g(are)g(pro)m(vided)f(for)h(sp)s(ecifying)f(the)h(parameter)g(v) --5 b(alues,)37 b(or)f(\\compression)g(directiv)m(e")i(k)m(eyw)m(ords)0 -2343 y(ma)m(y)c(b)s(e)e(added)h(to)g(the)h(header)f(of)g(eac)m(h)h -(image)h(HDU)e(to)h(sp)s(ecify)f(the)g(compression)g(parameters.)50 -b(These)33 b(3)0 2456 y(metho)s(ds)d(are)g(describ)s(ed)g(b)s(elo)m(w.) -0 2616 y(1\))23 b(A)m(t)g(run)e(time,)k(when)c(sp)s(ecifying)h(the)h -(name)f(of)g(the)h(output)f(FITS)f(\014le)i(to)g(b)s(e)e(created,)k -(the)e(user)e(can)i(indicate)0 2729 y(that)32 b(images)g(should)e(b)s -(e)h(written)g(in)g(tile-compressed)i(format)e(b)m(y)h(enclosing)g(the) -f(compression)h(parameters)0 2842 y(in)e(square)g(brac)m(k)m(ets)i -(follo)m(wing)g(the)e(ro)s(ot)h(disk)f(\014le)g(name)h(in)f(the)h -(follo)m(wing)g(format:)191 3100 y Fe([compress)45 b(NAME)i(T1,T2;)f -(q[z])h(QLEVEL,)e(s)j(HSCALE])0 3359 y Fj(where)191 3617 -y Fe(NAME)142 b(=)47 b(algorithm)f(name:)94 b(GZIP,)46 -b(Rice,)h(HCOMPRESS,)e(HSCOMPRSS)g(or)i(PLIO)620 3730 -y(may)g(be)h(abbreviated)c(to)j(the)g(first)g(letter)f(\(or)h(HS)g(for) -g(HSCOMPRESS\))191 3843 y(T1,T2)94 b(=)47 b(tile)g(dimension)e(\(e.g.)i -(100,100)f(for)g(square)h(tiles)f(100)h(pixels)f(wide\))191 -3955 y(QLEVEL)g(=)h(quantization)e(level)h(for)h(floating)f(point)g -(FITS)h(images)191 4068 y(HSCALE)f(=)h(HCOMPRESS)f(scale)g(factor;)g -(default)g(=)h(0)h(which)e(is)h(lossless.)0 4327 y Fj(Here)31 -b(are)g(a)f(few)h(examples)f(of)h(this)f(extended)h(syn)m(tax:)191 -4585 y Fe(myfile.fit[compress])185 b(-)48 b(use)f(the)g(default)e -(compression)g(algorithm)g(\(Rice\))1432 4698 y(and)i(the)g(default)e -(tile)i(size)g(\(row)f(by)i(row\))191 4924 y(myfile.fit[compress)42 -b(G])48 b(-)f(use)g(the)g(specified)e(compression)g(algorithm;)191 -5036 y(myfile.fit[compress)d(R])239 b(only)46 b(the)h(first)f(letter)h -(of)g(the)g(algorithm)191 5149 y(myfile.fit[compress)42 -b(P])239 b(should)46 b(be)h(given.)191 5262 y(myfile.fit[compress)42 -b(H])191 5488 y(myfile.fit[compress)g(R)48 b(100,100])141 -b(-)47 b(use)g(Rice)g(and)g(100)g(x)g(100)g(pixel)f(tiles)191 -5714 y(myfile.fit[compress)c(R;)48 b(q)f(10.0])f(-)i(quantization)c -(level)j(=)g(\(RMS-noise\))e(/)i(10.)p eop end -%%Page: 50 58 -TeXDict begin 50 57 bop 0 299 a Fj(50)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)191 555 y Fe(myfile.fit[compress)42 b(R;)48 -b(qz)f(10.0])f(-)i(quantization)c(level)i(=)i(\(RMS-noise\))d(/)i(10.) -1050 668 y(also)g(use)g(the)f(SUBTRACTIVE_DITHER_2)d(quantization)h -(method)191 781 y(myfile.fit[compress)e(HS;)47 b(s)h(2.0])94 -b(-)h(HSCOMPRESS)45 b(\(with)i(smoothing\))2005 894 y(and)f(scale)h(=)g -(2.0)g(*)h(RMS-noise)0 1116 y Fj(2\))29 b(Before)g(calling)g(the)f -(CFITSIO)e(routine)i(to)h(write)f(the)g(image)h(header)f(k)m(eyw)m -(ords)g(\(e.g.,)j(\014ts)p 3335 1116 28 4 v 32 w(create)p -3603 1116 V 34 w(image\))0 1228 y(the)37 b(programmer)g(can)g(call)i -(the)e(routines)g(describ)s(ed)f(b)s(elo)m(w)h(to)h(sp)s(ecify)f(the)g -(compression)g(algorithm)i(and)0 1341 y(the)g(tiling)h(pattern)f(that)g -(is)g(to)g(b)s(e)f(used.)65 b(There)38 b(are)i(routines)e(for)h(sp)s -(ecifying)f(the)h(v)-5 b(arious)39 b(compression)0 1454 -y(parameters)31 b(and)e(similar)i(routines)f(to)i(return)d(the)h -(curren)m(t)h(v)-5 b(alues)30 b(of)h(the)f(parameters:)95 -1676 y Fe(int)47 b(fits_set_compression_type\()o(fit)o(sfil)o(e)42 -b(*fptr,)k(int)h(comptype,)e(int)i(*status\))95 1789 -y(int)g(fits_set_tile_dim\(fitsfile)41 b(*fptr,)46 b(int)h(ndim,)f -(long)h(*tilesize,)e(int)i(*status\))95 1902 y(int)g -(fits_set_quantize_level\(fi)o(tsf)o(ile)41 b(*fptr,)46 -b(float)h(qlevel,)f(int)h(*status\))95 2015 y(int)g -(fits_set_quantize_method\(f)o(its)o(file)41 b(*fptr,)46 -b(int)h(method,)f(int)h(*status\))95 2128 y(int)g -(fits_set_quantize_dither\(f)o(its)o(file)41 b(*fptr,)46 -b(int)h(dither,)f(int)h(*status\))95 2240 y(int)g -(fits_set_dither_seed\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(seed,)g(int)f -(*status\))95 2353 y(int)h(fits_set_dither_offset\(fit)o(sfi)o(le)42 -b(*fptr,)k(int)h(offset,)e(int)i(*status\))95 2466 y(int)g -(fits_set_lossy_int\(fitsfil)o(e)42 b(*fptr,)k(int)h(lossy_int,)e(int)i -(*status\))286 2579 y(this)g(forces)f(integer)g(image)g(to)h(be)h -(converted)d(to)i(floats,)f(then)h(quantized)95 2692 -y(int)g(fits_set_huge_hdu\(fitsfile)41 b(*fptr,)46 b(int)h(huge,)f(int) -h(*status\);)286 2805 y(this)g(should)f(be)h(called)f(when)h(the)g -(compressed)e(image)h(size)h(is)g(more)g(than)f(4)i(GB.)95 -2918 y(int)f(fits_set_hcomp_scale\(fitsf)o(ile)41 b(*fptr,)46 -b(float)h(scale,)f(int)h(*status\))95 3031 y(int)g -(fits_set_hcomp_smooth\(fits)o(fil)o(e)42 b(*fptr,)k(int)h(smooth,)f -(int)h(*status\))668 3144 y(Set)g(smooth)f(=)i(1)f(to)g(apply)g -(smoothing)e(when)i(uncompressing)d(the)j(image)95 3370 -y(int)g(fits_get_compression_type\()o(fit)o(sfil)o(e)42 -b(*fptr,)k(int)h(*comptype,)e(int)i(*status\))95 3482 -y(int)g(fits_get_tile_dim\(fitsfile)41 b(*fptr,)46 b(int)h(ndim,)f -(long)h(*tilesize,)e(int)i(*status\))95 3595 y(int)g -(fits_get_quantize_level\(fi)o(tsf)o(ile)41 b(*fptr,)46 -b(float)h(*level,)f(int)h(*status\))95 3708 y(int)g -(fits_get_hcomp_scale\(fitsf)o(ile)41 b(*fptr,)46 b(float)h(*scale,)e -(int)i(*status\))0 3930 y Fj(Sev)m(eral)33 b(sym)m(b)s(olic)f(constan)m -(ts)h(are)f(de\014ned)e(for)i(use)f(as)h(the)g(v)-5 b(alue)33 -b(of)f(the)f(`compt)m(yp)s(e')i(parameter:)44 b(GZIP)p -3802 3930 V 32 w(1,)0 4043 y(GZIP)p 227 4043 V 32 w(2,)j(RICE)p -604 4043 V 32 w(1,)f(HCOMPRESS)p 1333 4043 V 32 w(1)d(or)g(PLIO)p -1800 4043 V 32 w(1.)78 b(En)m(tering)43 b(NULL)g(for)g(compt)m(yp)s(e)g -(will)g(turn)f(o\013)h(the)0 4156 y(tile-compression)32 -b(and)e(cause)h(normal)f(FITS)g(images)h(to)g(b)s(e)f(written.)0 -4316 y(There)20 b(are)g(also)i(de\014ned)d(sym)m(b)s(olic)h(constan)m -(ts)i(for)e(the)g(quan)m(tization)i(metho)s(d:)36 b(\\SUBTRA)m(CTIVE)p -3507 4316 V 32 w(DITHER)p 3904 4316 V 33 w(1",)0 4429 -y(\\SUBTRA)m(CTIVE)p 726 4429 V 33 w(DITHER)p 1124 4429 -V 32 w(2",)c(and)e(\\NO)p 1664 4429 V 33 w(DITHER".)0 -4589 y(3\))g(CFITSIO)e(will)i(uses)f(the)h(v)-5 b(alues)29 -b(of)h(the)g(follo)m(wing)g(k)m(eyw)m(ords,)h(if)e(they)h(are)g(presen) -m(t)f(in)g(the)h(header)f(of)h(the)0 4702 y(image)k(HDU,)g(to)g -(determine)f(ho)m(w)g(to)h(compress)f(that)g(HDU.)h(These)f(k)m(eyw)m -(ords)g(o)m(v)m(erride)i(an)m(y)e(compression)0 4815 -y(parameters)e(that)g(w)m(ere)g(sp)s(eci\014ed)e(with)h(the)h(previous) -f(2)g(metho)s(ds.)95 5036 y Fe(FZALGOR)94 b(-)47 b('RICE_1')f(,)h -('GZIP_1',)f('GZIP_2',)f('HCOMPRESS_1',)f('PLIO_1',)h('NONE')95 -5149 y(FZTILE)142 b(-)47 b('ROW',)g('WHOLE',)e(or)i('\(n,m\)')95 -5262 y(FZQVALUE)f(-)h(float)g(value)f(\(default)g(=)h(4.0\))95 -5375 y(FZQMETHD)f(-)h('SUBTRACTIVE_DITHER_1',)42 b -('SUBTRACTIVE_DITHER_2',)f('NO_DITHER')95 5488 y(FZDTHRSD)46 -b(-)h('CLOCK',)f('CHECKSUM',)f(1)i(-)h(10000)95 5601 -y(FZINT2F)94 b(-)h(T,)47 b(or)h(F:)94 b(Convert)46 b(integers)g(to)h -(floats,)f(then)g(quantize?)95 5714 y(FZHSCALE)g(-)h(float)g(value)f -(\(default)g(=)h(0\).)95 b(Hcompress)45 b(scale)h(value.)p -eop end -%%Page: 51 59 -TeXDict begin 51 58 bop 0 299 a Fh(5.6.)72 b(IMA)m(GE)31 -b(COMPRESSION)2567 b Fj(51)0 555 y(No)23 b(sp)s(ecial)f(action)i(is)e -(required)f(b)m(y)h(soft)m(w)m(are)i(when)d(read)h(tile-compressed)h -(images)g(b)s(ecause)f(all)h(the)f(CFITSIO)0 668 y(routines)35 -b(that)g(read)g(normal)g(uncompressed)f(FITS)g(images)i(also)g -(transparen)m(tly)g(read)e(images)j(in)d(the)h(tile-)0 -781 y(compressed)28 b(format;)h(CFITSIO)e(essen)m(tially)j(treats)f -(the)f(binary)g(table)h(that)f(con)m(tains)i(the)e(compressed)g(tiles)0 -894 y(as)j(if)f(it)h(w)m(ere)g(an)f(IMA)m(GE)h(extension.)0 -1054 y(The)f(follo)m(wing)i(2)e(routines)h(are)f(a)m(v)-5 -b(ailable)33 b(for)d(compressing)h(or)f(or)g(decompressing)h(an)f -(image:)95 1309 y Fe(int)47 b(fits_img_compress\(fitsfile)41 -b(*infptr,)46 b(fitsfile)f(*outfptr,)g(int)i(*status\);)95 -1421 y(int)g(fits_img_decompress)c(\(fitsfile)i(*infptr,)h(fitsfile)f -(*outfptr,)h(int)g(*status\);)0 1676 y Fj(Before)30 b(calling)h(the)f -(compression)f(routine,)h(the)g(compression)f(parameters)h(m)m(ust)f -(\014rst)g(b)s(e)g(de\014ned)f(in)h(one)h(of)0 1789 y(the)e(3)h(w)m(a)m -(y)g(describ)s(ed)e(in)h(the)g(previous)g(paragraphs.)39 -b(There)28 b(is)g(also)h(a)f(routine)h(to)f(determine)h(if)f(the)g -(curren)m(t)0 1902 y(HDU)j(con)m(tains)h(a)e(tile)i(compressed)e(image) -i(\(it)f(returns)e(1)i(or)f(0\):)95 2156 y Fe(int)47 -b(fits_is_compressed_image\(f)o(its)o(file)41 b(*fptr,)46 -b(int)h(*status\);)0 2411 y Fj(A)30 b(small)g(example)g(program)f -(called)i('imcop)m(y')f(is)g(included)f(with)g(CFITSIO)f(that)i(can)f -(b)s(e)g(used)g(to)h(compress)0 2524 y(\(or)44 b(uncompress\))g(an)m(y) -g(FITS)g(image.)83 b(This)43 b(program)h(can)h(b)s(e)e(used)h(to)g(exp) -s(erimen)m(t)h(with)f(the)g(v)-5 b(arious)0 2637 y(compression)30 -b(options)h(on)f(existing)i(FITS)d(images)j(as)e(sho)m(wn)g(in)g(these) -h(examples:)0 2891 y Fe(1\))95 b(imcopy)46 b(infile.fit)f -('outfile.fit[compress]')334 3117 y(This)i(will)f(use)h(the)g(default)f -(compression)f(algorithm)g(\(Rice\))h(and)h(the)334 3230 -y(default)f(tile)h(size)f(\(row)h(by)g(row\))0 3456 y(2\))95 -b(imcopy)46 b(infile.fit)f('outfile.fit[compress)d(GZIP]')334 -3681 y(This)47 b(will)f(use)h(the)g(GZIP)g(compression)e(algorithm)g -(and)i(the)g(default)334 3794 y(tile)g(size)f(\(row)h(by)g(row\).)94 -b(The)47 b(allowed)f(compression)f(algorithms)g(are)334 -3907 y(Rice,)h(GZIP,)h(and)g(PLIO.)94 b(Only)46 b(the)h(first)g(letter) -f(of)h(the)g(algorithm)334 4020 y(name)g(needs)f(to)h(be)g(specified.)0 -4246 y(3\))95 b(imcopy)46 b(infile.fit)f('outfile.fit[compress)d(G)47 -b(100,100]')334 4472 y(This)g(will)f(use)h(the)g(GZIP)g(compression)e -(algorithm)g(and)i(100)g(X)g(100)g(pixel)334 4585 y(tiles.)0 -4811 y(4\))95 b(imcopy)46 b(infile.fit)f('outfile.fit[compress)d(R)47 -b(100,100;)f(qz)h(10.0]')334 5036 y(This)g(will)f(use)h(the)g(Rice)g -(compression)e(algorithm,)g(100)h(X)i(100)f(pixel)334 -5149 y(tiles,)f(and)h(quantization)e(level)h(=)h(RMSnoise)f(/)h(10.0)g -(\(assuming)e(the)334 5262 y(input)h(image)h(has)g(a)g(floating)f -(point)g(data)h(type\).)f(By)h(specifying)334 5375 y(qz)g(instead)f(of) -h(q,)g(this)g(means)f(use)h(the)g(subtractive)e(dither2)334 -5488 y(quantization)g(method.)0 5714 y(5\))95 b(imcopy)46 -b(infile.fit)f(outfile.fit)p eop end -%%Page: 52 60 -TeXDict begin 52 59 bop 0 299 a Fj(52)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)334 668 y Fe(If)47 b(the)g(input)g(file)f(is)h(in)h -(tile-compressed)43 b(format,)j(then)h(it)g(will)f(be)334 -781 y(uncompressed)f(to)i(the)g(output)f(file.)94 b(Otherwise,)45 -b(it)i(simply)f(copies)334 894 y(the)h(input)f(image)h(to)g(the)g -(output)f(image.)0 1120 y(6\))95 b(imcopy)46 b -('infile.fit[1001:1500,20)o(01:2)o(500])o(')89 b(outfile.fit)334 -1346 y(This)47 b(extracts)e(a)j(500)f(X)g(500)g(pixel)f(section)g(of)h -(the)g(much)g(larger)334 1458 y(input)f(image)h(\(which)f(may)h(be)g -(in)g(tile-compressed)d(format\).)93 b(The)334 1571 y(output)46 -b(is)h(a)h(normal)e(uncompressed)e(FITS)j(image.)0 1797 -y(7\))95 b(imcopy)46 b('infile.fit[1001:1500,20)o(01:2)o(500])o(')89 -b(outfile.fit.gz)334 2023 y(Same)47 b(as)g(above,)f(except)g(the)h -(output)f(file)h(is)g(externally)e(compressed)334 2136 -y(using)h(the)h(gzip)g(algorithm.)0 2594 y Ff(5.7)135 -b(ASCI)t(I)45 b(and)f(Binary)h(T)-11 b(able)45 b(Routines)0 -2846 y Fj(These)36 b(routines)g(p)s(erform)f(read)i(and)e(write)i(op)s -(erations)g(on)f(columns)g(of)h(data)g(in)f(FITS)g(ASCI)s(I)e(or)j -(Binary)0 2959 y(tables.)47 b(Note)33 b(that)g(in)e(the)i(follo)m(wing) -g(discussions,)f(the)g(\014rst)g(ro)m(w)g(and)f(column)h(in)g(a)g -(table)h(is)g(at)f(p)s(osition)h(1)0 3072 y(not)e(0.)0 -3232 y(Users)k(should)g(also)i(read)e(the)h(follo)m(wing)h(c)m(hapter)g -(on)e(the)h(CFITSIO)e(iterator)j(function)f(whic)m(h)f(pro)m(vides)h(a) -0 3345 y(more)i(`ob)5 b(ject)39 b(orien)m(ted')g(metho)s(d)f(of)g -(reading)g(and)g(writing)g(table)h(columns.)63 b(The)37 -b(iterator)j(function)d(is)i(a)0 3458 y(little)e(more)f(complicated)h -(to)f(use,)h(but)e(the)g(adv)-5 b(an)m(tages)38 b(are)d(that)i(it)f -(usually)f(tak)m(es)i(less)e(co)s(de)h(to)g(p)s(erform)0 -3571 y(the)h(same)f(op)s(eration,)j(and)c(the)i(resulting)f(program)g -(often)h(runs)e(faster)i(b)s(ecause)f(the)g(FITS)g(\014les)g(are)h -(read)0 3684 y(and)30 b(written)g(using)g(the)h(most)f(e\016cien)m(t)i -(blo)s(c)m(k)f(size.)0 3986 y Fd(5.7.1)112 b(Create)38 -b(New)f(T)-9 b(able)0 4202 y Fi(1)81 b Fj(Create)40 b(a)f(new)g(ASCI)s -(I)e(or)i(bin)m(table)h(table)g(extension.)68 b(If)39 -b(the)g(FITS)g(\014le)g(is)g(curren)m(tly)g(empt)m(y)h(then)f(a)227 -4315 y(dumm)m(y)25 b(primary)f(arra)m(y)i(will)g(b)s(e)f(created)i(b)s -(efore)e(app)s(ending)f(the)i(table)g(extension)h(to)f(it.)40 -b(The)25 b(tblt)m(yp)s(e)227 4428 y(parameter)39 b(de\014nes)e(the)h(t) -m(yp)s(e)h(of)f(table)h(and)e(can)i(ha)m(v)m(e)g(v)-5 -b(alues)39 b(of)f(ASCI)s(I)p 2924 4428 28 4 v 31 w(TBL)g(or)g(BINAR)-8 -b(Y)p 3659 4428 V 34 w(TBL.)227 4541 y(The)29 b(naxis2)g(parameter)h -(giv)m(es)g(the)g(initial)g(n)m(um)m(b)s(er)e(of)h(ro)m(ws)g(to)h(b)s -(e)f(created)h(in)f(the)g(table,)h(and)f(should)227 4654 -y(normally)h(b)s(e)f(set)h(=)g(0.)40 b(CFITSIO)29 b(will)h -(automatically)i(increase)f(the)e(size)i(of)f(the)g(table)g(as)g -(additional)227 4767 y(ro)m(ws)d(are)g(written.)40 b(A)27 -b(non-zero)g(n)m(um)m(b)s(er)f(of)h(ro)m(ws)g(ma)m(y)g(b)s(e)f(sp)s -(eci\014ed)g(to)i(reserv)m(e)f(space)h(for)e(that)i(man)m(y)227 -4880 y(ro)m(ws,)41 b(ev)m(en)e(if)g(a)g(few)m(er)g(n)m(um)m(b)s(er)e -(of)i(ro)m(ws)f(will)h(b)s(e)f(written.)66 b(The)38 b(tunit)g(and)g -(extname)i(parameters)227 4993 y(are)e(optional)g(and)f(a)h(n)m(ull)f -(p)s(oin)m(ter)g(ma)m(y)h(b)s(e)f(giv)m(en)h(if)g(they)f(are)h(not)f -(de\014ned.)61 b(The)37 b(FITS)f(Standard)227 5106 y(recommends)29 -b(that)h(only)g(letters,)h(digits,)g(and)e(the)g(underscore)g(c)m -(haracter)i(b)s(e)e(used)g(in)g(column)g(names)227 5219 -y(\(the)c(tt)m(yp)s(e)g(parameter\))g(with)e(no)h(em)m(b)s(edded)f -(spaces.)40 b(T)-8 b(railing)24 b(blank)g(c)m(haracters)i(are)e(not)h -(signi\014can)m(t.)95 5601 y Fe(int)47 b(fits_create_tbl)d(/)j(ffcrtb) -286 5714 y(\(fitsfile)f(*fptr,)g(int)h(tbltype,)e(LONGLONG)h(naxis2,)g -(int)g(tfields,)g(char)h(*ttype[],)p eop end -%%Page: 53 61 -TeXDict begin 53 60 bop 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 -b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 -b Fj(53)334 555 y Fe(char)47 b(*tform[],)e(char)i(*tunit[],)e(char)i -(*extname,)e(int)i(*status\))0 844 y Fd(5.7.2)112 b(Column)39 -b(Information)f(Routines)0 1050 y Fi(1)81 b Fj(Get)30 -b(the)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(or)f(columns)g(in)h(the)g -(curren)m(t)f(FITS)g(table.)41 b(The)29 b(n)m(um)m(b)s(er)f(of)i(ro)m -(ws)g(is)f(giv)m(en)i(b)m(y)227 1163 y(the)j(NAXIS2)f(k)m(eyw)m(ord)h -(and)e(the)i(n)m(um)m(b)s(er)e(of)h(columns)g(is)g(giv)m(en)h(b)m(y)f -(the)h(TFIELDS)e(k)m(eyw)m(ord)i(in)f(the)227 1276 y(header)d(of)h(the) -g(table.)95 1521 y Fe(int)47 b(fits_get_num_rows)c(/)48 -b(ffgnrw)286 1634 y(\(fitsfile)e(*fptr,)g(>)h(long)g(*nrows,)f(int)h -(*status\);)95 1860 y(int)g(fits_get_num_rowsll)c(/)k(ffgnrwll)286 -1973 y(\(fitsfile)f(*fptr,)g(>)h(LONGLONG)f(*nrows,)g(int)g(*status\);) -95 2199 y(int)h(fits_get_num_cols)c(/)48 b(ffgncl)286 -2312 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*ncols,)f(int)h(*status\);)0 -2557 y Fi(2)81 b Fj(Get)25 b(the)f(table)i(column)e(n)m(um)m(b)s(er)f -(\(and)h(name\))h(of)f(the)h(column)f(whose)g(name)g(matc)m(hes)i(an)e -(input)g(template)227 2670 y(name.)48 b(If)32 b(casesen)i(=)e(CASESEN)g -(then)g(the)h(column)f(name)h(matc)m(h)h(will)f(b)s(e)f(case-sensitiv)m -(e,)k(whereas)227 2783 y(if)27 b(casesen)h(=)e(CASEINSEN)g(then)h(the)g -(case)h(will)f(b)s(e)f(ignored.)40 b(As)27 b(a)g(general)h(rule,)f(the) -g(column)g(names)227 2895 y(should)j(b)s(e)f(treated)j(as)e(case)i -(INsensitiv)m(e.)227 3043 y(The)26 b(input)g(column)g(name)g(template)i -(ma)m(y)f(b)s(e)f(either)h(the)g(exact)h(name)e(of)h(the)f(column)g(to) -i(b)s(e)d(searc)m(hed)227 3156 y(for,)k(or)f(it)h(ma)m(y)g(con)m(tain)h -(wild)e(card)g(c)m(haracters)i(\(*,)g(?,)f(or)f(#\),)h(or)f(it)h(ma)m -(y)g(con)m(tain)h(the)e(in)m(teger)i(n)m(um)m(b)s(er)227 -3269 y(of)j(the)f(desired)f(column)h(\(with)g(the)h(\014rst)e(column)h -(=)g(1\).)46 b(The)32 b(`*')h(wild)f(card)g(c)m(haracter)h(matc)m(hes)h -(an)m(y)227 3382 y(sequence)h(of)g(c)m(haracters)h(\(including)f(zero)g -(c)m(haracters\))i(and)d(the)h(`?')53 b(c)m(haracter)36 -b(matc)m(hes)g(an)m(y)f(single)227 3495 y(c)m(haracter.)42 -b(The)29 b(#)h(wildcard)f(will)h(matc)m(h)h(an)m(y)e(consecutiv)m(e)j -(string)e(of)f(decimal)i(digits)f(\(0-9\).)43 b(If)29 -b(more)227 3608 y(than)43 b(one)f(column)h(name)f(in)g(the)h(table)h -(matc)m(hes)f(the)g(template)h(string,)i(then)c(the)h(\014rst)e(matc)m -(h)j(is)227 3721 y(returned)28 b(and)h(the)g(status)h(v)-5 -b(alue)30 b(will)f(b)s(e)g(set)h(to)g(COL)p 2171 3721 -28 4 v 32 w(NOT)p 2408 3721 V 32 w(UNIQUE)f(as)h(a)f(w)m(arning)g(that) -h(a)g(unique)227 3834 y(matc)m(h)e(w)m(as)g(not)f(found.)39 -b(T)-8 b(o)27 b(\014nd)f(the)h(other)g(cases)h(that)g(matc)m(h)g(the)g -(template,)h(call)f(the)g(routine)f(again)227 3947 y(lea)m(ving)g(the)e -(input)f(status)h(v)-5 b(alue)26 b(equal)f(to)h(COL)p -1950 3947 V 32 w(NOT)p 2187 3947 V 32 w(UNIQUE)f(and)f(the)h(next)h -(matc)m(hing)g(name)f(will)227 4059 y(then)30 b(b)s(e)g(returned.)40 -b(Rep)s(eat)30 b(this)h(pro)s(cess)f(un)m(til)g(a)h(status)g(=)f(COL)p -2628 4059 V 32 w(NOT)p 2865 4059 V 32 w(F)m(OUND)i(is)e(returned.)227 -4207 y(The)36 b(FITS)g(Standard)g(recommends)g(that)i(only)e(letters,)k -(digits,)f(and)d(the)h(underscore)f(c)m(haracter)j(b)s(e)227 -4320 y(used)31 b(in)g(column)g(names)g(\(with)h(no)f(em)m(b)s(edded)f -(spaces\).)45 b(T)-8 b(railing)32 b(blank)f(c)m(haracters)i(are)e(not)h -(signi\014-)227 4433 y(can)m(t.)95 4678 y Fe(int)47 b(fits_get_colnum)d -(/)j(ffgcno)286 4791 y(\(fitsfile)f(*fptr,)g(int)h(casesen,)e(char)i -(*templt,)e(>)j(int)f(*colnum,)334 4904 y(int)g(*status\))95 -5130 y(int)g(fits_get_colname)d(/)j(ffgcnn)286 5243 y(\(fitsfile)f -(*fptr,)g(int)h(casesen,)e(char)i(*templt,)e(>)j(char)e(*colname,)334 -5356 y(int)h(*colnum,)f(int)g(*status\))0 5601 y Fi(3)81 -b Fj(Return)30 b(the)i(data)g(t)m(yp)s(e,)h(v)m(ector)g(rep)s(eat)f(v) --5 b(alue,)32 b(and)f(the)h(width)f(in)g(b)m(ytes)h(of)g(a)g(column)f -(in)g(an)h(ASCI)s(I)e(or)227 5714 y(binary)35 b(table.)56 -b(Allo)m(w)m(ed)37 b(v)-5 b(alues)36 b(for)f(the)h(data)g(t)m(yp)s(e)f -(in)g(ASCI)s(I)f(tables)i(are:)51 b(TSTRING,)35 b(TSHOR)-8 -b(T,)p eop end -%%Page: 54 62 -TeXDict begin 54 61 bop 0 299 a Fj(54)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)227 555 y Fj(TLONG,)36 b(TFLO)m(A)-8 b(T,)36 -b(and)f(TDOUBLE.)i(Binary)e(tables)i(also)g(supp)s(ort)d(these)i(t)m -(yp)s(es:)52 b(TLOGICAL,)227 668 y(TBIT,)38 b(TBYTE,)h(TCOMPLEX)e(and)h -(TDBLCOMPLEX.)h(The)f(negativ)m(e)i(of)f(the)g(data)g(t)m(yp)s(e)g(co)s -(de)227 781 y(v)-5 b(alue)32 b(is)f(returned)f(if)h(it)g(is)h(a)f(v)-5 -b(ariable)32 b(length)f(arra)m(y)h(column.)43 b(Note)32 -b(that)g(in)e(the)i(case)g(of)f(a)g('J')h(32-bit)227 -894 y(in)m(teger)g(binary)d(table)i(column,)f(this)g(routine)g(will)g -(return)f(data)i(t)m(yp)s(e)f(=)g(TINT32BIT)g(\(whic)m(h)g(in)g(fact) -227 1007 y(is)36 b(equiv)-5 b(alen)m(t)37 b(to)g(TLONG\).)f(With)g -(most)g(curren)m(t)g(C)f(compilers,)j(a)f(v)-5 b(alue)36 -b(in)f(a)i('J')f(column)f(has)h(the)227 1120 y(same)29 -b(size)g(as)g(an)f('in)m(t')i(v)-5 b(ariable,)30 b(and)d(ma)m(y)j(not)e -(b)s(e)g(equiv)-5 b(alen)m(t)30 b(to)f(a)g('long')g(v)-5 -b(ariable,)30 b(whic)m(h)e(is)h(64-bits)227 1233 y(long)i(on)g(an)f -(increasing)h(n)m(um)m(b)s(er)e(of)h(compilers.)227 1400 -y(The)22 b('rep)s(eat')h(parameter)g(returns)f(the)g(v)m(ector)i(rep)s -(eat)f(coun)m(t)g(on)f(the)h(binary)f(table)h(TF)m(ORMn)f(k)m(eyw)m -(ord)227 1513 y(v)-5 b(alue.)60 b(\(ASCI)s(I)35 b(table)j(columns)e -(alw)m(a)m(ys)i(ha)m(v)m(e)g(rep)s(eat)e(=)g(1\).)60 -b(The)36 b('width')g(parameter)h(returns)f(the)227 1626 -y(width)30 b(in)g(b)m(ytes)h(of)g(a)f(single)h(column)g(elemen)m(t)h -(\(e.g.,)g(a)f('10D')h(binary)e(table)h(column)f(will)h(ha)m(v)m(e)h -(width)227 1739 y(=)d(8,)i(an)e(ASCI)s(I)f(table)i('F12.2')i(column)e -(will)g(ha)m(v)m(e)g(width)f(=)g(12,)i(and)e(a)h(binary)e(table'60A')k -(c)m(haracter)227 1852 y(string)44 b(column)g(will)g(ha)m(v)m(e)h -(width)e(=)h(60\);)52 b(Note)45 b(that)f(CFITSIO)f(supp)s(orts)f(the)i -(lo)s(cal)h(con)m(v)m(en)m(tion)227 1965 y(for)d(sp)s(ecifying)f(arra)m -(ys)i(of)f(\014xed)f(length)h(strings)f(within)h(a)g(binary)f(table)h -(c)m(haracter)i(column)d(using)227 2078 y(the)g(syn)m(tax)g(TF)m(ORM)g -(=)g('rAw')f(where)g('r')h(is)g(the)g(total)h(n)m(um)m(b)s(er)d(of)i(c) -m(haracters)h(\(=)f(the)g(width)f(of)227 2191 y(the)f(column\))g(and)e -('w')i(is)f(the)h(width)f(of)g(a)h(unit)f(string)g(within)g(the)h -(column.)65 b(Th)m(us)37 b(if)h(the)h(column)227 2304 -y(has)34 b(TF)m(ORM)h(=)f('60A12')j(then)d(this)g(means)g(that)h(eac)m -(h)g(ro)m(w)g(of)f(the)h(table)g(con)m(tains)g(5)g(12-c)m(haracter)227 -2416 y(substrings)23 b(within)h(the)g(60-c)m(haracter)j(\014eld,)f(and) -d(th)m(us)h(in)g(this)g(case)h(this)g(routine)f(will)g(return)f(t)m(yp) -s(eco)s(de)227 2529 y(=)f(TSTRING,)g(rep)s(eat)g(=)g(60,)j(and)d(width) -f(=)h(12.)39 b(\(The)22 b(TDIMn)g(k)m(eyw)m(ord)h(ma)m(y)g(also)g(b)s -(e)f(used)f(to)i(sp)s(ecify)227 2642 y(the)29 b(unit)e(string)h -(length;)i(The)e(pair)g(of)g(k)m(eyw)m(ords)g(TF)m(ORMn)g(=)g('60A')i -(and)e(TDIMn)f(=)h('\(12,5\)')j(w)m(ould)227 2755 y(ha)m(v)m(e)g(the)f -(same)g(e\013ect)h(as)e(TF)m(ORMn)h(=)f('60A12'\).)43 -b(The)29 b(n)m(um)m(b)s(er)f(of)i(substrings)e(in)h(an)m(y)h(binary)f -(table)227 2868 y(c)m(haracter)36 b(string)e(\014eld)f(can)h(b)s(e)g -(calculated)i(b)m(y)d(\(rep)s(eat/width\).)53 b(A)34 -b(n)m(ull)f(p)s(oin)m(ter)h(ma)m(y)h(b)s(e)e(giv)m(en)i(for)227 -2981 y(an)m(y)c(of)g(the)f(output)g(parameters)h(that)g(are)g(not)f -(needed.)227 3149 y(The)46 b(second)g(routine,)k(\014t)p -1188 3149 28 4 v 33 w(get)p 1341 3149 V 34 w(eqcolt)m(yp)s(e)d(is)f -(similar)h(except)g(that)f(in)g(the)g(case)i(of)e(scaled)h(in)m(teger) -227 3262 y(columns)35 b(it)g(returns)f(the)h('equiv)-5 -b(alen)m(t')37 b(data)f(t)m(yp)s(e)f(that)h(is)f(needed)f(to)i(store)g -(the)f(scaled)h(v)-5 b(alues,)37 b(and)227 3374 y(not)28 -b(necessarily)h(the)f(ph)m(ysical)g(data)g(t)m(yp)s(e)g(of)g(the)g -(unscaled)f(v)-5 b(alues)29 b(as)e(stored)h(in)g(the)f(FITS)g(table.)41 -b(F)-8 b(or)227 3487 y(example)38 b(if)g(a)g('1I')g(column)f(in)g(a)h -(binary)f(table)h(has)g(TSCALn)d(=)j(1)f(and)g(TZER)m(On)f(=)i(32768,)j -(then)227 3600 y(this)29 b(column)f(e\013ectiv)m(ely)k(con)m(tains)d -(unsigned)f(short)g(in)m(teger)i(v)-5 b(alues,)29 b(and)f(th)m(us)h -(the)f(returned)g(v)-5 b(alue)29 b(of)227 3713 y(t)m(yp)s(eco)s(de)34 -b(will)f(b)s(e)g(TUSHOR)-8 b(T,)32 b(not)h(TSHOR)-8 b(T.)33 -b(Similarly)-8 b(,)34 b(if)f(a)h(column)f(has)f(TTYPEn)g(=)h('1I')h -(and)227 3826 y(TSCALn)29 b(=)h(0.12,)i(then)e(the)h(returned)e(t)m(yp) -s(eco)s(de)i(will)f(b)s(e)g(TFLO)m(A)-8 b(T.)95 4121 -y Fe(int)47 b(fits_get_coltype)d(/)j(ffgtcl)286 4233 -y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(>)j(int)f(*typecode,)e(long)h -(*repeat,)334 4346 y(long)h(*width,)f(int)g(*status\))95 -4572 y(int)h(fits_get_coltypell)c(/)48 b(ffgtclll)286 -4685 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(>)j(int)f(*typecode,)e -(LONGLONG)g(*repeat,)334 4798 y(LONGLONG)h(*width,)f(int)i(*status\))95 -5024 y(int)g(fits_get_eqcoltype)c(/)48 b(ffeqty)286 5137 -y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(>)j(int)f(*typecode,)e(long)h -(*repeat,)334 5250 y(long)h(*width,)f(int)g(*status\))95 -5475 y(int)h(fits_get_eqcoltypell)c(/)k(ffeqtyll)286 -5588 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(>)j(int)f(*typecode,)e -(LONGLONG)g(*repeat,)334 5701 y(LONGLONG)h(*width,)f(int)i(*status\))p -eop end -%%Page: 55 63 -TeXDict begin 55 62 bop 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 -b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 -b Fj(55)0 555 y Fi(4)81 b Fj(Return)29 b(the)h(displa)m(y)g(width)f(of) -h(a)h(column.)40 b(This)29 b(is)h(the)g(length)h(of)f(the)g(string)g -(that)h(will)f(b)s(e)f(returned)g(b)m(y)227 668 y(the)34 -b(\014ts)p 514 668 28 4 v 32 w(read)p 718 668 V 33 w(col)g(routine)f -(when)f(reading)h(the)h(column)e(as)i(a)f(formatted)h(string.)49 -b(The)32 b(displa)m(y)i(width)227 781 y(is)29 b(determined)g(b)m(y)g -(the)g(TDISPn)f(k)m(eyw)m(ord,)i(if)f(presen)m(t,)h(otherwise)f(b)m(y)g -(the)g(data)h(t)m(yp)s(e)f(of)h(the)f(column.)95 1125 -y Fe(int)47 b(fits_get_col_display_width)41 b(/)47 b(ffgcdw)286 -1238 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(>)j(int)f(*dispwidth,)e -(int)h(*status\))0 1470 y Fi(5)81 b Fj(Return)27 b(the)i(n)m(um)m(b)s -(er)e(of)i(and)e(size)j(of)e(the)h(dimensions)f(of)g(a)h(table)g -(column)g(in)f(a)g(binary)g(table.)41 b(Normally)227 -1583 y(this)28 b(information)h(is)f(giv)m(en)h(b)m(y)f(the)h(TDIMn)f(k) -m(eyw)m(ord,)h(but)e(if)i(this)f(k)m(eyw)m(ord)g(is)g(not)h(presen)m(t) -f(then)g(this)227 1695 y(routine)j(returns)e(naxis)h(=)g(1)h(and)f -(naxes[0])h(equal)g(to)g(the)g(rep)s(eat)f(coun)m(t)h(in)f(the)h(TF)m -(ORM)g(k)m(eyw)m(ord.)95 1927 y Fe(int)47 b(fits_read_tdim)d(/)k -(ffgtdm)286 2040 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(int)i(maxdim,) -f(>)i(int)f(*naxis,)334 2153 y(long)g(*naxes,)f(int)g(*status\))95 -2378 y(int)h(fits_read_tdimll)d(/)j(ffgtdmll)286 2491 -y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i(maxdim,)f(>)i(int)f -(*naxis,)334 2604 y(LONGLONG)f(*naxes,)f(int)i(*status\))0 -2836 y Fi(6)81 b Fj(Deco)s(de)33 b(the)g(input)f(TDIMn)h(k)m(eyw)m(ord) -g(string)f(\(e.g.)50 b('\(100,200\)'\))37 b(and)32 b(return)g(the)h(n)m -(um)m(b)s(er)e(of)i(and)f(size)227 2949 y(of)c(the)g(dimensions)f(of)h -(a)g(binary)f(table)h(column.)40 b(If)27 b(the)h(input)f(tdimstr)g(c)m -(haracter)i(string)f(is)g(n)m(ull,)g(then)227 3061 y(this)d(routine)f -(returns)f(naxis)h(=)h(1)f(and)g(naxes[0])i(equal)e(to)i(the)e(rep)s -(eat)h(coun)m(t)g(in)f(the)g(TF)m(ORM)h(k)m(eyw)m(ord.)227 -3174 y(This)30 b(routine)g(is)h(called)g(b)m(y)f(\014ts)p -1350 3174 V 33 w(read)p 1555 3174 V 33 w(tdim.)95 3406 -y Fe(int)47 b(fits_decode_tdim)d(/)j(ffdtdm)286 3519 -y(\(fitsfile)f(*fptr,)g(char)g(*tdimstr,)g(int)h(colnum,)e(int)i -(maxdim,)f(>)i(int)e(*naxis,)334 3632 y(long)h(*naxes,)f(int)g -(*status\))95 3857 y(int)h(fits_decode_tdimll)c(/)48 -b(ffdtdmll)286 3970 y(\(fitsfile)e(*fptr,)g(char)g(*tdimstr,)g(int)h -(colnum,)e(int)i(maxdim,)f(>)i(int)e(*naxis,)334 4083 -y(LONGLONG)g(*naxes,)f(int)i(*status\))0 4315 y Fi(7)81 -b Fj(W)-8 b(rite)23 b(a)g(TDIMn)f(k)m(eyw)m(ord)h(whose)f(v)-5 -b(alue)23 b(has)g(the)f(form)g('\(l,m,n...\)')40 b(where)22 -b(l,)i(m,)g(n...)38 b(are)23 b(the)g(dimensions)227 4427 -y(of)31 b(a)g(m)m(ultidimensional)g(arra)m(y)g(column)f(in)g(a)h -(binary)e(table.)95 4659 y Fe(int)47 b(fits_write_tdim)d(/)j(ffptdm)286 -4772 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i(naxis,)f(long)h -(*naxes,)f(>)h(int)g(*status\))95 4998 y(int)g(fits_write_tdimll)c(/)48 -b(ffptdmll)286 5110 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(int)i -(naxis,)f(LONGLONG)g(*naxes,)g(>)h(int)g(*status\))0 -5397 y Fd(5.7.3)112 b(Routines)38 b(to)f(Edit)g(Ro)m(ws)g(or)g(Columns) -0 5601 y Fi(1)81 b Fj(Insert)32 b(or)h(delete)i(ro)m(ws)e(in)g(an)g -(ASCI)s(I)f(or)h(binary)f(table.)50 b(When)33 b(inserting)h(ro)m(ws)f -(all)h(the)f(ro)m(ws)g(follo)m(wing)227 5714 y(ro)m(w)24 -b(FR)m(O)m(W)i(are)e(shifted)f(do)m(wn)h(b)m(y)g(NR)m(O)m(WS)g(ro)m -(ws;)j(if)c(FR)m(O)m(W)j(=)d(0)i(then)e(the)h(blank)g(ro)m(ws)g(are)g -(inserted)p eop end -%%Page: 56 64 -TeXDict begin 56 63 bop 0 299 a Fj(56)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)227 555 y Fj(at)h(the)e(b)s(eginning)g(of)h(the)f(table.) -42 b(Note)31 b(that)f(it)g(is)f(*not*)i(necessary)f(to)g(insert)f(ro)m -(ws)h(in)f(a)h(table)g(b)s(efore)227 668 y(writing)g(data)g(to)g(those) -h(ro)m(ws)e(\(indeed,)h(it)g(w)m(ould)f(b)s(e)g(ine\016cien)m(t)i(to)f -(do)g(so\).)41 b(Instead)29 b(one)h(ma)m(y)g(simply)227 -781 y(write)h(data)g(to)g(an)m(y)g(ro)m(w)f(of)h(the)f(table,)i -(whether)e(that)h(ro)m(w)f(of)h(data)g(already)g(exists)g(or)f(not.)227 -927 y(The)40 b(\014rst)g(delete)i(routine)e(deletes)i(NR)m(O)m(WS)f -(consecutiv)m(e)h(ro)m(ws)f(starting)g(with)f(ro)m(w)g(FIRSTR)m(O)m(W.) -227 1040 y(The)d(second)g(delete)h(routine)f(tak)m(es)h(an)f(input)f -(string)h(that)h(lists)f(the)g(ro)m(ws)g(or)g(ro)m(w)g(ranges)g -(\(e.g.,)k('5-)227 1153 y(10,12,20-30'\),)32 b(whereas)26 -b(the)g(third)g(delete)h(routine)f(tak)m(es)h(an)f(input)f(in)m(teger)j -(arra)m(y)e(that)h(sp)s(eci\014es)f(eac)m(h)227 1266 -y(individual)35 b(ro)m(w)h(to)g(b)s(e)f(deleted.)58 b(In)35 -b(b)s(oth)f(latter)j(cases,)i(the)c(input)g(list)h(of)g(ro)m(ws)g(to)g -(delete)h(m)m(ust)f(b)s(e)227 1379 y(sorted)i(in)g(ascending)g(order.) -62 b(These)38 b(routines)f(up)s(date)g(the)h(NAXIS2)g(k)m(eyw)m(ord)h -(to)f(re\015ect)g(the)g(new)227 1492 y(n)m(um)m(b)s(er)29 -b(of)i(ro)m(ws)f(in)g(the)h(table.)95 1729 y Fe(int)47 -b(fits_insert_rows)d(/)j(ffirow)286 1842 y(\(fitsfile)f(*fptr,)g -(LONGLONG)f(firstrow,)h(LONGLONG)f(nrows,)h(>)i(int)f(*status\))95 -2068 y(int)g(fits_delete_rows)d(/)j(ffdrow)286 2181 y(\(fitsfile)f -(*fptr,)g(LONGLONG)f(firstrow,)h(LONGLONG)f(nrows,)h(>)i(int)f -(*status\))95 2406 y(int)g(fits_delete_rowrange)c(/)k(ffdrrg)286 -2519 y(\(fitsfile)f(*fptr,)g(char)g(*rangelist,)f(>)j(int)e(*status\)) -95 2745 y(int)h(fits_delete_rowlist)c(/)k(ffdrws)286 -2858 y(\(fitsfile)f(*fptr,)g(long)g(*rowlist,)g(long)g(nrows,)g(>)i -(int)f(*status\))95 3084 y(int)g(fits_delete_rowlistll)42 -b(/)48 b(ffdrwsll)286 3197 y(\(fitsfile)e(*fptr,)g(LONGLONG)f -(*rowlist,)h(LONGLONG)f(nrows,)h(>)i(int)f(*status\))0 -3434 y Fi(2)81 b Fj(Insert)36 b(or)h(delete)i(column\(s\))e(in)g(an)g -(ASCI)s(I)f(or)h(binary)f(table.)62 b(When)37 b(inserting,)i(COLNUM)e -(sp)s(eci\014es)227 3546 y(the)28 b(column)g(n)m(um)m(b)s(er)f(that)h -(the)g(\(\014rst\))g(new)f(column)h(should)f(o)s(ccup)m(y)h(in)g(the)g -(table.)41 b(NCOLS)26 b(sp)s(eci\014es)227 3659 y(ho)m(w)35 -b(man)m(y)g(columns)f(are)h(to)g(b)s(e)f(inserted.)53 -b(An)m(y)35 b(existing)h(columns)e(from)g(this)h(p)s(osition)f(and)g -(higher)227 3772 y(are)c(shifted)f(o)m(v)m(er)h(to)g(allo)m(w)g(ro)s -(om)f(for)g(the)h(new)e(column\(s\).)41 b(The)29 b(index)f(n)m(um)m(b)s -(er)g(on)h(all)h(the)f(follo)m(wing)227 3885 y(k)m(eyw)m(ords)34 -b(will)f(b)s(e)g(incremen)m(ted)h(or)f(decremen)m(ted)h(if)f(necessary) -h(to)g(re\015ect)g(the)f(new)g(p)s(osition)g(of)h(the)227 -3998 y(column\(s\))26 b(in)f(the)h(table:)39 b(TBCOLn,)26 -b(TF)m(ORMn,)h(TTYPEn,)e(TUNITn,)h(TNULLn,)g(TSCALn,)f(TZE-)227 -4111 y(R)m(On,)43 b(TDISPn,)g(TDIMn,)g(TLMINn,)g(TLMAXn,)g(TDMINn,)g -(TDMAXn,)h(TCTYPn,)e(TCRPXn,)227 4224 y(TCR)-10 b(VLn,)29 -b(TCDL)-8 b(Tn,)30 b(TCR)m(OTn,)f(and)h(TCUNIn.)95 4461 -y Fe(int)47 b(fits_insert_col)d(/)j(fficol)286 4574 y(\(fitsfile)f -(*fptr,)g(int)h(colnum,)e(char)i(*ttype,)f(char)h(*tform,)334 -4687 y(>)h(int)e(*status\))95 4912 y(int)h(fits_insert_cols)d(/)j -(fficls)286 5025 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i(ncols,)f -(char)h(**ttype,)334 5138 y(char)g(**tform,)e(>)j(int)f(*status\))95 -5364 y(int)g(fits_delete_col)d(/)j(ffdcol\(fitsfile)d(*fptr,)i(int)h -(colnum,)f(>)h(int)g(*status\))0 5601 y Fi(3)81 b Fj(Cop)m(y)32 -b(a)h(column)g(from)f(one)h(HDU)g(to)h(another)e(\(or)h(to)h(the)f -(same)g(HDU\).)h(If)e(create)p 3129 5601 28 4 v 34 w(col)i(=)e(TR)m -(UE,)h(then)227 5714 y(a)40 b(new)e(column)h(will)g(b)s(e)g(inserted)g -(in)f(the)h(output)g(table,)j(at)e(p)s(osition)f(`outcolumn',)j -(otherwise)e(the)p eop end -%%Page: 57 65 -TeXDict begin 57 64 bop 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 -b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 -b Fj(57)227 555 y(existing)39 b(output)f(column)f(will)i(b)s(e)e(o)m(v) -m(erwritten)i(\(in)f(whic)m(h)g(case)h(it)f(m)m(ust)g(ha)m(v)m(e)h(a)f -(compatible)h(data)227 668 y(t)m(yp)s(e\).)i(If)29 b(outcoln)m(um)h(is) -f(greater)i(than)e(the)h(n)m(um)m(b)s(er)e(of)h(column)g(in)g(the)h -(table,)h(then)e(the)g(new)g(column)227 781 y(will)j(b)s(e)f(app)s -(ended)f(to)j(the)f(end)f(of)g(the)h(table.)46 b(Note)33 -b(that)f(the)g(\014rst)f(column)g(in)h(a)g(table)g(is)g(at)h(coln)m(um) -227 894 y(=)j(1.)58 b(The)36 b(standard)f(indexed)g(k)m(eyw)m(ords)i -(that)f(related)h(to)g(the)f(column)g(\(e.g.,)j(TDISPn,)e(TUNITn,)227 -1007 y(TCRPXn,)30 b(TCDL)-8 b(Tn,)29 b(etc.\))43 b(will)30 -b(also)i(b)s(e)d(copied.)95 1254 y Fe(int)47 b(fits_copy_col)e(/)i -(ffcpcl)286 1367 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(int)i -(incolnum,)e(int)i(outcolnum,)334 1480 y(int)g(create_col,)e(>)i(int)g -(*status\);)0 1727 y Fi(4)81 b Fj(Cop)m(y)30 b('nro)m(ws')g(consecutiv) -m(e)j(ro)m(ws)d(from)g(one)h(table)g(to)g(another,)g(b)s(eginning)f -(with)g(ro)m(w)g('\014rstro)m(w'.)41 b(These)227 1840 -y(ro)m(ws)31 b(will)h(b)s(e)e(app)s(ended)g(to)i(an)m(y)f(existing)h -(ro)m(ws)g(in)e(the)i(output)e(table.)44 b(Note)33 b(that)f(the)f -(\014rst)f(ro)m(w)i(in)f(a)227 1952 y(table)h(is)e(at)h(ro)m(w)g(=)f -(1.)95 2199 y Fe(int)47 b(fits_copy_rows)d(/)k(ffcprw)286 -2312 y(\(fitsfile)e(*infptr,)f(fitsfile)h(*outfptr,)f(LONGLONG)h -(firstrow,)334 2425 y(LONGLONG)g(nrows,)g(>)h(int)g(*status\);)0 -2672 y Fi(5)81 b Fj(Mo)s(dify)37 b(the)g(v)m(ector)i(length)f(of)f(a)h -(binary)e(table)i(column)f(\(e.g.,)k(c)m(hange)e(a)e(column)g(from)g -(TF)m(ORMn)g(=)227 2785 y('1E')31 b(to)h('20E'\).)g(The)e(v)m(ector)i -(length)e(ma)m(y)h(b)s(e)f(increased)h(or)f(decreased)h(from)f(the)g -(curren)m(t)h(v)-5 b(alue.)95 3032 y Fe(int)47 b -(fits_modify_vector_len)42 b(/)48 b(ffmvec)286 3145 y(\(fitsfile)e -(*fptr,)g(int)h(colnum,)e(LONGLONG)h(newveclen,)f(>)i(int)g(*status\))0 -3434 y Fd(5.7.4)112 b(Read)38 b(and)h(W)-9 b(rite)36 -b(Column)j(Data)e(Routines)0 3653 y Fj(The)e(follo)m(wing)h(routines)g -(write)f(or)g(read)g(data)h(v)-5 b(alues)36 b(in)f(the)g(curren)m(t)g -(ASCI)s(I)f(or)h(binary)g(table)h(extension.)0 3766 y(If)d(a)g(write)g -(op)s(eration)h(extends)f(b)s(ey)m(ond)f(the)h(curren)m(t)g(size)h(of)f -(the)g(table,)i(then)e(the)g(n)m(um)m(b)s(er)f(of)h(ro)m(ws)g(in)g(the) -0 3878 y(table)i(will)g(automatically)i(b)s(e)c(increased)i(and)e(the)i -(NAXIS2)f(k)m(eyw)m(ord)h(v)-5 b(alue)35 b(will)f(b)s(e)g(up)s(dated.) -51 b(A)m(ttempts)0 3991 y(to)31 b(read)f(b)s(ey)m(ond)g(the)h(end)e(of) -i(the)f(table)i(will)e(result)h(in)f(an)g(error.)0 4152 -y(Automatic)d(data)e(t)m(yp)s(e)g(con)m(v)m(ersion)h(is)f(p)s(erformed) -f(for)g(n)m(umerical)i(data)f(t)m(yp)s(es)g(\(only\))h(if)f(the)g(data) -h(t)m(yp)s(e)f(of)g(the)0 4264 y(column)34 b(\(de\014ned)f(b)m(y)h(the) -g(TF)m(ORMn)g(k)m(eyw)m(ord\))h(di\013ers)f(from)g(the)g(data)h(t)m(yp) -s(e)f(of)g(the)h(arra)m(y)f(in)g(the)g(calling)0 4377 -y(routine.)65 b(ASCI)s(I)37 b(and)h(binary)f(tables)i(supp)s(ort)e(the) -i(follo)m(wing)g(data)h(t)m(yp)s(e)e(v)-5 b(alues:)57 -b(TSTRING,)38 b(TBYTE,)0 4490 y(TSBYTE,)28 b(TSHOR)-8 -b(T,)27 b(TUSHOR)-8 b(T,)28 b(TINT,)g(TUINT,)g(TLONG,)g(TLONGLONG,)g -(TULONG,)g(TFLO)m(A)-8 b(T,)0 4603 y(or)25 b(TDOUBLE.)g(Binary)f -(tables)i(also)f(supp)s(ort)e(TLOGICAL)h(\(in)m(ternally)i(mapp)s(ed)d -(to)i(the)g(`c)m(har')h(data)f(t)m(yp)s(e\),)0 4716 y(TCOMPLEX,)30 -b(and)f(TDBLCOMPLEX.)0 4876 y(Note)d(that)g(it)g(is)f(*not*)h -(necessary)f(to)h(insert)f(ro)m(ws)g(in)g(a)g(table)h(b)s(efore)f -(writing)g(data)h(to)g(those)f(ro)m(ws)g(\(indeed,)h(it)0 -4989 y(w)m(ould)h(b)s(e)g(ine\016cien)m(t)i(to)f(do)f(so\).)41 -b(Instead,)28 b(one)g(ma)m(y)g(simply)f(write)g(data)h(to)h(an)m(y)e -(ro)m(w)h(of)g(the)f(table,)j(whether)0 5102 y(that)h(ro)m(w)f(of)h -(data)g(already)g(exists)g(or)f(not.)0 5262 y(Individual)g(bits)i(in)f -(a)h(binary)e(table)i('X')g(or)g('B')g(column)f(ma)m(y)h(b)s(e)f -(read/written)h(to/from)g(a)g(*c)m(har)g(arra)m(y)g(b)m(y)0 -5375 y(sp)s(ecifying)k(the)f(TBIT)h(datat)m(yp)s(e.)57 -b(The)35 b(*c)m(har)i(arra)m(y)f(will)g(b)s(e)f(in)m(terpreted)h(as)g -(an)g(arra)m(y)g(of)g(logical)i(TR)m(UE)0 5488 y(\(1\))d(or)g(F)-10 -b(ALSE)34 b(\(0\))h(v)-5 b(alues)35 b(that)g(corresp)s(ond)e(to)i(the)g -(v)-5 b(alue)35 b(of)f(eac)m(h)i(bit)e(in)g(the)h(FITS)e('X')i(or)g -('B')g(column.)0 5601 y(Alternativ)m(ely)-8 b(,)30 b(the)c(v)-5 -b(alues)27 b(in)e(a)i(binary)e(table)i('X')g(column)f(ma)m(y)h(b)s(e)e -(read/written)i(8)f(bits)g(at)h(a)f(time)h(to/from)0 -5714 y(an)j(arra)m(y)h(of)g(8-bit)g(in)m(tegers)g(b)m(y)g(sp)s -(ecifying)f(the)h(TBYTE)f(datat)m(yp)s(e.)p eop end -%%Page: 58 66 -TeXDict begin 58 65 bop 0 299 a Fj(58)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Fj(Note)25 b(that)g(within)e(the)h(con)m(text)i -(of)e(these)g(routines,)i(the)e(TSTRING)f(data)h(t)m(yp)s(e)g(corresp)s -(onds)f(to)h(a)h(C)e('c)m(har**')0 668 y(data)35 b(t)m(yp)s(e,)h(i.e.,) -h(a)e(p)s(oin)m(ter)f(to)i(an)e(arra)m(y)h(of)g(p)s(oin)m(ters)f(to)h -(an)g(arra)m(y)g(of)g(c)m(haracters.)54 b(This)34 b(is)g(di\013eren)m -(t)h(from)0 781 y(the)d(k)m(eyw)m(ord)h(reading)f(and)f(writing)h -(routines)g(where)g(TSTRING)f(corresp)s(onds)g(to)h(a)h(C)e('c)m(har*') -j(data)f(t)m(yp)s(e,)0 894 y(i.e.,)g(a)e(single)h(p)s(oin)m(ter)f(to)h -(an)f(arra)m(y)g(of)g(c)m(haracters.)45 b(When)30 b(reading)i(strings)e -(from)h(a)g(table,)i(the)e(c)m(har)h(arra)m(ys)0 1007 -y(ob)m(viously)f(m)m(ust)f(ha)m(v)m(e)i(b)s(een)e(allo)s(cated)i(long)f -(enough)f(to)h(hold)f(the)h(whole)f(FITS)g(table)h(string.)0 -1167 y(Numerical)i(data)g(v)-5 b(alues)33 b(are)g(automatically)j -(scaled)d(b)m(y)f(the)h(TSCALn)e(and)h(TZER)m(On)f(k)m(eyw)m(ord)i(v)-5 -b(alues)33 b(\(if)0 1280 y(they)e(exist\).)0 1440 y(In)25 -b(the)g(case)i(of)e(binary)g(tables)h(with)f(v)m(ector)i(elemen)m(ts,)h -(the)e('felem')g(parameter)g(de\014nes)f(the)g(starting)h(elemen)m(t)0 -1553 y(\(b)s(eginning)h(with)g(1,)h(not)g(0\))g(within)f(the)g(cell)i -(\(a)f(cell)g(is)f(de\014ned)f(as)i(the)f(in)m(tersection)i(of)f(a)f -(ro)m(w)h(and)e(a)i(column)0 1666 y(and)e(ma)m(y)h(con)m(tain)h(a)g -(single)f(v)-5 b(alue)27 b(or)g(a)g(v)m(ector)h(of)f(v)-5 -b(alues\).)40 b(The)26 b(felem)i(parameter)f(is)g(ignored)f(when)g -(dealing)0 1779 y(with)34 b(ASCI)s(I)e(tables.)52 b(Similarly)-8 -b(,)36 b(in)d(the)i(case)f(of)h(binary)e(tables)h(the)h('nelemen)m(ts') -g(parameter)f(sp)s(eci\014es)g(the)0 1892 y(total)28 -b(n)m(um)m(b)s(er)d(of)h(v)m(ector)i(v)-5 b(alues)27 -b(to)g(b)s(e)e(read)h(or)h(written)f(\(con)m(tin)m(uing)i(on)e -(subsequen)m(t)f(ro)m(ws)i(if)f(required\))g(and)0 2005 -y(not)31 b(the)f(n)m(um)m(b)s(er)f(of)i(table)g(cells.)0 -2254 y Fi(1)81 b Fj(W)-8 b(rite)31 b(elemen)m(ts)h(in)m(to)f(an)g(ASCI) -s(I)e(or)h(binary)f(table)j(column.)0 2504 y(The)38 b(\014rst)f -(routine)h(simply)g(writes)g(the)g(arra)m(y)h(of)f(v)-5 -b(alues)39 b(to)g(the)f(FITS)g(\014le)g(\(doing)g(data)h(t)m(yp)s(e)g -(con)m(v)m(ersion)0 2617 y(if)h(necessary\))h(whereas)f(the)h(second)f -(routine)h(will)f(substitute)h(the)f(appropriate)g(FITS)g(n)m(ull)g(v) --5 b(alue)41 b(for)f(all)0 2730 y(elemen)m(ts)34 b(whic)m(h)f(are)g -(equal)h(to)f(the)g(input)f(v)-5 b(alue)34 b(of)f(n)m(ulv)-5 -b(al)33 b(\(note)h(that)f(this)g(parameter)g(giv)m(es)i(the)e(address)0 -2843 y(of)40 b(n)m(ulv)-5 b(al,)44 b(not)c(the)g(n)m(ull)g(v)-5 -b(alue)41 b(itself)7 b(\).)72 b(F)-8 b(or)40 b(in)m(teger)i(columns)e -(the)g(FITS)g(n)m(ull)g(v)-5 b(alue)40 b(is)h(de\014ned)e(b)m(y)h(the)0 -2956 y(TNULLn)32 b(k)m(eyw)m(ord)i(\(an)g(error)e(is)i(returned)e(if)h -(the)h(k)m(eyw)m(ord)f(do)s(esn't)g(exist\).)51 b(F)-8 -b(or)34 b(\015oating)g(p)s(oin)m(t)f(columns)0 3069 y(the)h(sp)s(ecial) -h(IEEE)f(NaN)h(\(Not-a-Num)m(b)s(er\))h(v)-5 b(alue)35 -b(will)f(b)s(e)g(written)g(in)m(to)i(the)e(FITS)g(\014le.)52 -b(If)34 b(a)h(n)m(ull)f(p)s(oin)m(ter)0 3182 y(is)f(en)m(tered)g(for)g -(n)m(ulv)-5 b(al,)34 b(then)f(the)g(n)m(ull)g(v)-5 b(alue)33 -b(is)g(ignored)g(and)g(this)g(routine)f(b)s(eha)m(v)m(es)i(the)f(same)g -(as)h(the)f(\014rst)0 3295 y(routine.)41 b(The)29 b(third)g(routine)h -(simply)f(writes)h(unde\014ned)d(pixel)k(v)-5 b(alues)30 -b(to)g(the)g(column.)41 b(The)29 b(fourth)g(routine)0 -3408 y(\014lls)e(ev)m(ery)i(column)e(in)h(the)g(table)g(with)g(n)m(ull) -f(v)-5 b(alues,)29 b(in)e(the)h(sp)s(eci\014ed)f(ro)m(ws)h(\(ignoring)g -(an)m(y)g(columns)g(that)g(do)0 3521 y(not)j(ha)m(v)m(e)g(a)g -(de\014ned)e(n)m(ull)h(v)-5 b(alue\).)95 3770 y Fe(int)47 -b(fits_write_col)d(/)k(ffpcl)286 3883 y(\(fitsfile)e(*fptr,)g(int)h -(datatype,)e(int)i(colnum,)f(LONGLONG)f(firstrow,)334 -3996 y(LONGLONG)h(firstelem,)f(LONGLONG)g(nelements,)g(DTYPE)i(*array,) -e(>)j(int)f(*status\))95 4222 y(int)g(fits_write_colnull)c(/)48 -b(ffpcn)286 4335 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(int)i -(colnum,)f(LONGLONG)f(firstrow,)286 4448 y(LONGLONG)h(firstelem,)f -(LONGLONG)g(nelements,)g(DTYPE)i(*array,)f(DTYPE)g(*nulval,)286 -4561 y(>)i(int)f(*status\))143 4787 y(int)g(fits_write_col_null)c(/)k -(ffpclu)334 4899 y(\(fitsfile)e(*fptr,)h(int)h(colnum,)f(LONGLONG)g -(firstrow,)f(LONGLONG)h(firstelem,)382 5012 y(LONGLONG)f(nelements,)g -(>)j(int)f(*status\))143 5238 y(int)g(fits_write_nullrows)c(/)k(ffprwu) -334 5351 y(\(fitsfile)e(*fptr,)h(LONGLONG)g(firstrow,)f(LONGLONG)h -(nelements,)f(>)i(int)g(*status\))0 5601 y Fi(2)81 b -Fj(Read)33 b(elemen)m(ts)i(from)e(an)g(ASCI)s(I)f(or)i(binary)e(table)i -(column.)50 b(The)33 b(data)h(t)m(yp)s(e)g(parameter)g(sp)s(eci\014es)f -(the)227 5714 y(data)28 b(t)m(yp)s(e)g(of)g(the)f(`n)m(ulv)-5 -b(al')29 b(and)e(`arra)m(y')h(p)s(oin)m(ters;)h(Unde\014ned)c(arra)m(y) -j(elemen)m(ts)h(will)f(b)s(e)f(returned)f(with)p eop -end -%%Page: 59 67 -TeXDict begin 59 66 bop 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 -b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 -b Fj(59)227 555 y(a)30 b(v)-5 b(alue)30 b(=)e(*n)m(ullv)-5 -b(al,)31 b(\(note)f(that)g(this)f(parameter)h(giv)m(es)g(the)g(address) -e(of)h(the)h(n)m(ull)f(v)-5 b(alue,)30 b(not)g(the)f(n)m(ull)227 -668 y(v)-5 b(alue)31 b(itself)7 b(\))32 b(unless)e(n)m(ulv)-5 -b(al)32 b(=)e(0)h(or)g(*n)m(ulv)-5 b(al)31 b(=)g(0,)g(in)f(whic)m(h)h -(case)h(no)e(c)m(hec)m(king)j(for)d(unde\014ned)f(pixels)227 -781 y(will)34 b(b)s(e)f(p)s(erformed.)48 b(The)33 b(second)g(routine)h -(is)f(similar)h(except)g(that)g(an)m(y)g(unde\014ned)d(pixels)j(will)g -(ha)m(v)m(e)227 894 y(the)d(corresp)s(onding)e(n)m(ullarra)m(y)i -(elemen)m(t)h(set)f(equal)g(to)g(TR)m(UE)f(\(=)h(1\).)227 -1039 y(An)m(y)c(column,)g(regardless)f(of)g(it's)h(in)m(trinsic)g(data) -g(t)m(yp)s(e,)g(ma)m(y)g(b)s(e)e(read)i(as)f(a)g(string.)40 -b(It)26 b(should)f(b)s(e)h(noted)227 1152 y(ho)m(w)m(ev)m(er)32 -b(that)f(reading)f(a)h(n)m(umeric)f(column)g(as)h(a)g(string)f(is)g(10) -i(-)e(100)i(times)f(slo)m(w)m(er)g(than)f(reading)h(the)227 -1265 y(same)22 b(column)g(as)f(a)h(n)m(um)m(b)s(er)e(due)h(to)i(the)e -(large)i(o)m(v)m(erhead)g(in)e(constructing)h(the)g(formatted)g -(strings.)37 b(The)227 1378 y(displa)m(y)26 b(format)g(of)f(the)h -(returned)e(strings)h(will)h(b)s(e)f(determined)g(b)m(y)g(the)h(TDISPn) -e(k)m(eyw)m(ord,)j(if)e(it)h(exists,)227 1491 y(otherwise)32 -b(b)m(y)f(the)g(data)h(t)m(yp)s(e)f(of)g(the)g(column.)43 -b(The)30 b(length)i(of)f(the)g(returned)f(strings)h(\(not)g(including) -227 1604 y(the)26 b(n)m(ull)f(terminating)i(c)m(haracter\))g(can)f(b)s -(e)f(determined)g(with)g(the)h(\014ts)p 2703 1604 28 -4 v 32 w(get)p 2855 1604 V 34 w(col)p 2999 1604 V 34 -w(displa)m(y)p 3311 1604 V 33 w(width)f(routine.)227 -1717 y(The)30 b(follo)m(wing)i(TDISPn)d(displa)m(y)i(formats)f(are)h -(curren)m(tly)f(supp)s(orted:)418 1933 y Fe(Iw.m)142 -b(Integer)418 2046 y(Ow.m)g(Octal)47 b(integer)418 2159 -y(Zw.m)142 b(Hexadecimal)45 b(integer)418 2272 y(Fw.d)142 -b(Fixed)47 b(floating)e(point)418 2385 y(Ew.d)142 b(Exponential)45 -b(floating)h(point)418 2498 y(Dw.d)142 b(Exponential)45 -b(floating)h(point)418 2611 y(Gw.d)142 b(General;)46 -b(uses)g(Fw.d)h(if)g(significance)e(not)i(lost,)f(else)h(Ew.d)227 -2827 y Fj(where)24 b(w)h(is)f(the)h(width)f(in)g(c)m(haracters)i(of)f -(the)g(displa)m(y)m(ed)g(v)-5 b(alues,)27 b(m)d(is)h(the)f(minim)m(um)g -(n)m(um)m(b)s(er)g(of)g(digits)227 2940 y(displa)m(y)m(ed,)29 -b(and)e(d)g(is)h(the)f(n)m(um)m(b)s(er)g(of)g(digits)i(to)f(the)g(righ) -m(t)g(of)f(the)h(decimal.)41 b(The)27 b(.m)g(\014eld)g(is)h(optional.) -95 3171 y Fe(int)47 b(fits_read_col)e(/)i(ffgcv)286 3284 -y(\(fitsfile)f(*fptr,)g(int)h(datatype,)e(int)i(colnum,)f(LONGLONG)f -(firstrow,)g(LONGLONG)h(firstelem,)334 3397 y(LONGLONG)g(nelements,)f -(DTYPE)h(*nulval,)g(DTYPE)g(*array,)g(int)h(*anynul,)e(int)i(*status\)) -95 3623 y(int)g(fits_read_colnull)c(/)48 b(ffgcf)286 -3736 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(int)i(colnum,)f -(LONGLONG)f(firstrow,)g(LONGLONG)h(firstelem,)286 3849 -y(LONGLONG)g(nelements,)f(DTYPE)h(*array,)g(char)h(*nullarray,)d(int)j -(*anynul,)f(int)h(*status\))0 4135 y Fd(5.7.5)112 b(Ro)m(w)37 -b(Selection)h(and)h(Calculator)f(Routines)0 4354 y Fj(These)21 -b(routines)f(all)i(parse)f(and)f(ev)-5 b(aluate)23 b(an)d(input)g -(string)h(con)m(taining)i(a)e(user)f(de\014ned)g(arithmetic)i -(expression.)0 4467 y(The)29 b(\014rst)f(3)i(routines)f(select)i(ro)m -(ws)e(in)g(a)h(FITS)e(table,)j(based)e(on)g(whether)g(the)g(expression) -g(ev)-5 b(aluates)31 b(to)f(true)0 4580 y(\(not)e(equal)f(to)h(zero\))g -(or)f(false)h(\(zero\).)41 b(The)27 b(other)g(routines)g(ev)-5 -b(aluate)29 b(the)e(expression)g(and)f(calculate)k(a)d(v)-5 -b(alue)0 4692 y(for)26 b(eac)m(h)i(ro)m(w)f(of)g(the)g(table.)40 -b(The)26 b(allo)m(w)m(ed)j(expression)d(syn)m(tax)i(is)e(describ)s(ed)g -(in)g(the)h(ro)m(w)g(\014lter)g(section)g(in)g(the)0 -4805 y(`Extended)32 b(File)h(Name)g(Syn)m(tax')g(c)m(hapter)g(of)f -(this)g(do)s(cumen)m(t.)46 b(The)32 b(expression)g(ma)m(y)h(also)g(b)s -(e)e(written)i(to)g(a)0 4918 y(text)h(\014le,)h(and)e(the)h(name)f(of)h -(the)f(\014le,)i(prep)s(ended)c(with)i(a)h('@')g(c)m(haracter)h(ma)m(y) -f(b)s(e)f(supplied)f(for)h(the)h('expr')0 5031 y(parameter)d(\(e.g.)42 -b('@\014lename.txt'\).)g(The)30 b(expression)g(in)g(the)g(\014le)h(can) -f(b)s(e)g(arbitrarily)g(complex)h(and)f(extend)0 5144 -y(o)m(v)m(er)35 b(m)m(ultiple)g(lines)g(of)f(the)g(\014le.)53 -b(Lines)33 b(that)i(b)s(egin)f(with)g(2)g(slash)g(c)m(haracters)i -(\('//'\))g(will)f(b)s(e)e(ignored)i(and)0 5257 y(ma)m(y)c(b)s(e)f -(used)f(to)i(add)f(commen)m(ts)h(to)h(the)e(\014le.)0 -5488 y Fi(1)81 b Fj(Ev)-5 b(aluate)38 b(a)f(b)s(o)s(olean)g(expression) -g(o)m(v)m(er)h(the)g(indicated)f(ro)m(ws,)i(returning)d(an)h(arra)m(y)h -(of)f(\015ags)g(indicating)227 5601 y(whic)m(h)31 b(ro)m(ws)g(ev)-5 -b(aluated)32 b(to)f(TR)m(UE/F)-10 b(ALSE.)31 b(Up)s(on)f(return,)g(*n)p -2518 5601 V 33 w(go)s(o)s(d)p 2743 5601 V 33 w(ro)m(ws)g(con)m(tains)i -(the)f(n)m(um)m(b)s(er)f(of)227 5714 y(ro)m(ws)h(that)g(ev)-5 -b(aluate)32 b(to)f(TR)m(UE.)p eop end -%%Page: 60 68 -TeXDict begin 60 67 bop 0 299 a Fj(60)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_find_rows)d(/)k(fffrow)286 -668 y(\(fitsfile)e(*fptr,)93 b(char)47 b(*expr,)f(long)h(firstrow,)e -(long)i(nrows,)286 781 y(>)h(long)e(*n_good_rows,)f(char)h -(*row_status,)92 b(int)47 b(*status\))0 1015 y Fi(2)81 -b Fj(Find)29 b(the)i(\014rst)f(ro)m(w)g(whic)m(h)g(satis\014es)h(the)g -(input)e(b)s(o)s(olean)h(expression)95 1250 y Fe(int)47 -b(fits_find_first_row)c(/)k(ffffrw)286 1363 y(\(fitsfile)f(*fptr,)93 -b(char)47 b(*expr,)f(>)i(long)e(*rownum,)g(int)h(*status\))0 -1597 y Fi(3)81 b Fj(Ev)-5 b(aluate)35 b(an)f(expression)h(on)f(all)h -(ro)m(ws)g(of)f(a)h(table.)54 b(If)34 b(the)g(input)g(and)g(output)g -(\014les)g(are)h(not)g(the)f(same,)227 1710 y(cop)m(y)i(the)g(TR)m(UE)f -(ro)m(ws)g(to)h(the)f(output)g(\014le;)j(if)d(the)g(output)g(table)h -(is)f(not)h(empt)m(y)-8 b(,)37 b(then)e(this)g(routine)227 -1823 y(will)28 b(app)s(end)e(the)i(new)f(selected)i(ro)m(ws)e(after)h -(the)g(existing)h(ro)m(ws.)39 b(If)27 b(the)h(\014les)g(are)f(the)h -(same,)h(delete)g(the)227 1936 y(F)-10 b(ALSE)30 b(ro)m(ws)h(\(preserv) -m(e)f(the)h(TR)m(UE)f(ro)m(ws\).)95 2170 y Fe(int)47 -b(fits_select_rows)d(/)j(ffsrow)286 2283 y(\(fitsfile)f(*infptr,)f -(fitsfile)h(*outfptr,)93 b(char)46 b(*expr,)94 b(>)48 -b(int)f(*status)e(\))0 2518 y Fi(4)81 b Fj(Calculate)28 -b(an)f(expression)f(for)h(the)f(indicated)i(ro)m(ws)e(of)h(a)g(table,)i -(returning)d(the)h(results,)g(cast)h(as)f(datat)m(yp)s(e)227 -2631 y(\(TSHOR)-8 b(T,)32 b(TDOUBLE,)h(etc\),)h(in)e(arra)m(y)-8 -b(.)48 b(If)31 b(n)m(ulv)-5 b(al==NULL,)33 b(UNDEFs)g(will)f(b)s(e)g -(zero)s(ed)g(out.)47 b(F)-8 b(or)227 2744 y(v)m(ector)37 -b(results,)f(the)f(n)m(um)m(b)s(er)e(of)i(elemen)m(ts)i(returned)c(ma)m -(y)j(b)s(e)e(less)h(than)g(nelemen)m(ts)g(if)g(nelemen)m(ts)h(is)227 -2857 y(not)c(an)g(ev)m(en)h(m)m(ultiple)f(of)g(the)g(result)g -(dimension.)44 b(Call)33 b(\014ts)p 2392 2857 28 4 v -32 w(test)p 2570 2857 V 34 w(expr)e(to)h(obtain)h(the)f(dimensions)f -(of)227 2969 y(the)g(results.)95 3204 y Fe(int)47 b(fits_calc_rows)d(/) -k(ffcrow)286 3317 y(\(fitsfile)e(*fptr,)93 b(int)47 b(datatype,)f(char) -g(*expr,)g(long)h(firstrow,)334 3430 y(long)g(nelements,)e(void)h -(*nulval,)g(>)h(void)g(*array,)94 b(int)46 b(*anynul,)g(int)h -(*status\))0 3664 y Fi(5)81 b Fj(Ev)-5 b(aluate)33 b(an)g(expression)f -(and)h(write)f(the)h(result)g(either)g(to)h(a)f(column)f(\(if)h(the)g -(expression)f(is)h(a)g(function)227 3777 y(of)d(other)g(columns)g(in)f -(the)h(table\))h(or)f(to)g(a)h(k)m(eyw)m(ord)f(\(if)g(the)g(expression) -f(ev)-5 b(aluates)32 b(to)e(a)g(constan)m(t)i(and)227 -3890 y(is)f(not)f(a)h(function)f(of)h(other)f(columns)h(in)f(the)g -(table\).)42 b(In)30 b(the)h(former)e(case,)j(the)f(parName)f -(parameter)227 4003 y(is)40 b(the)g(name)f(of)h(the)g(column)f(\(whic)m -(h)h(ma)m(y)g(or)f(ma)m(y)h(not)g(already)g(exist\))h(in)m(to)f(whic)m -(h)g(to)g(write)g(the)227 4116 y(results,)e(and)f(parInfo)e(con)m -(tains)j(an)f(optional)g(TF)m(ORM)g(k)m(eyw)m(ord)g(v)-5 -b(alue)38 b(if)e(a)h(new)f(column)h(is)f(b)s(eing)227 -4229 y(created.)42 b(If)28 b(a)h(TF)m(ORM)h(v)-5 b(alue)29 -b(is)g(not)g(sp)s(eci\014ed)g(then)f(a)i(default)f(format)g(will)h(b)s -(e)e(used,)h(dep)s(ending)e(on)227 4342 y(the)35 b(expression.)54 -b(If)34 b(the)h(expression)f(ev)-5 b(aluates)37 b(to)e(a)g(constan)m -(t,)i(then)e(the)g(result)f(will)h(b)s(e)f(written)h(to)227 -4455 y(the)28 b(k)m(eyw)m(ord)g(name)f(giv)m(en)h(b)m(y)g(the)f -(parName)h(parameter,)h(and)d(the)i(parInfo)e(parameter)i(ma)m(y)g(b)s -(e)f(used)227 4568 y(to)k(supply)e(an)h(optional)i(commen)m(t)f(for)f -(the)g(k)m(eyw)m(ord.)42 b(If)29 b(the)i(k)m(eyw)m(ord)g(do)s(es)f(not) -g(already)h(exist,)g(then)227 4680 y(the)f(name)f(of)h(the)g(k)m(eyw)m -(ord)g(m)m(ust)f(b)s(e)g(preceded)g(with)g(a)h('#')f(c)m(haracter,)j -(otherwise)e(the)f(result)h(will)g(b)s(e)227 4793 y(written)h(to)g(a)g -(column)f(with)g(that)h(name.)95 5028 y Fe(int)47 b(fits_calculator)d -(/)j(ffcalc)286 5141 y(\(fitsfile)f(*infptr,)f(char)i(*expr,)f -(fitsfile)f(*outfptr,)h(char)g(*parName,)334 5254 y(char)h(*parInfo,)e -(>)95 b(int)47 b(*status\))0 5488 y Fi(6)81 b Fj(This)38 -b(calculator)k(routine)e(is)f(similar)h(to)g(the)g(previous)f(routine,) -j(except)f(that)f(the)g(expression)f(is)h(only)227 5601 -y(ev)-5 b(aluated)42 b(o)m(v)m(er)f(the)f(sp)s(eci\014ed)g(ro)m(w)g -(ranges.)70 b(nranges)39 b(sp)s(eci\014es)h(the)g(n)m(um)m(b)s(er)f(of) -h(ro)m(w)h(ranges,)i(and)227 5714 y(\014rstro)m(w)30 -b(and)g(lastro)m(w)h(giv)m(e)h(the)f(starting)g(and)f(ending)g(ro)m(w)g -(n)m(um)m(b)s(er)f(of)i(eac)m(h)g(range.)p eop end -%%Page: 61 69 -TeXDict begin 61 68 bop 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 -b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 -b Fj(61)95 555 y Fe(int)47 b(fits_calculator_rng)c(/)k(ffcalc_rng)286 -668 y(\(fitsfile)f(*infptr,)f(char)i(*expr,)f(fitsfile)f(*outfptr,)h -(char)g(*parName,)334 781 y(char)h(*parInfo,)e(int)i(nranges,)e(long)i -(*firstrow,)e(long)i(*lastrow)334 894 y(>)95 b(int)47 -b(*status\))0 1159 y Fi(7)81 b Fj(Ev)-5 b(aluate)36 b(the)f(giv)m(en)h -(expression)f(and)g(return)f(dimension)g(and)h(t)m(yp)s(e)g -(information)g(on)g(the)h(result.)54 b(The)227 1272 y(returned)37 -b(dimensions)f(corresp)s(ond)g(to)j(a)e(single)i(ro)m(w)e(en)m(try)h -(of)f(the)h(requested)f(expression,)j(and)d(are)227 1385 -y(equiv)-5 b(alen)m(t)26 b(to)f(the)g(result)f(of)g(\014ts)p -1380 1385 28 4 v 33 w(read)p 1585 1385 V 32 w(tdim\(\).)40 -b(Note)25 b(that)g(strings)f(are)h(considered)f(to)h(b)s(e)f(one)g -(elemen)m(t)227 1498 y(regardless)31 b(of)g(string)f(length.)41 -b(If)30 b(maxdim)g(==)g(0,)h(then)f(naxes)g(is)h(optional.)95 -1763 y Fe(int)47 b(fits_test_expr)d(/)k(fftexp)286 1876 -y(\(fitsfile)e(*fptr,)g(char)g(*expr,)g(int)h(maxdim)f(>)i(int)f -(*datatype,)e(long)h(*nelem,)g(int)h(*naxis,)334 1989 -y(long)g(*naxes,)f(int)g(*status\))0 2286 y Fd(5.7.6)112 -b(Column)39 b(Binning)f(or)f(Histogramming)i(Routines)0 -2506 y Fj(The)30 b(follo)m(wing)j(routines)e(ma)m(y)g(b)s(e)g(useful)f -(when)g(p)s(erforming)g(histogramming)h(op)s(erations)h(on)e -(column\(s\))i(of)0 2619 y(a)f(table)g(to)g(generate)h(an)e(image)i(in) -e(a)h(primary)e(arra)m(y)i(or)f(image)i(extension.)0 -2884 y Fi(1)81 b Fj(Calculate)27 b(the)e(histogramming)h(parameters)g -(\(min,)h(max,)f(and)f(bin)g(size)h(for)f(eac)m(h)i(axis)f(of)f(the)h -(histogram,)227 2997 y(based)38 b(on)g(a)g(v)-5 b(ariet)m(y)39 -b(of)f(p)s(ossible)g(input)f(parameters.)64 b(If)37 b(the)h(input)f -(names)h(of)g(the)g(columns)g(to)h(b)s(e)227 3110 y(binned)d(are)i(n)m -(ull,)h(then)e(the)h(routine)f(will)h(\014rst)f(lo)s(ok)h(for)f(the)h -(CPREF)f(=)g("NAME1,)j(NAME2,)h(...")227 3223 y(k)m(eyw)m(ord)34 -b(whic)m(h)f(lists)h(the)g(preferred)e(columns.)50 b(If)32 -b(not)i(presen)m(t,)h(then)e(the)g(routine)h(will)g(assume)f(the)227 -3336 y(column)d(names)h(X,)f(Y,)h(Z,)f(and)g(T)g(for)g(up)g(to)h(4)f -(axes)h(\(as)g(sp)s(eci\014ed)f(b)m(y)g(the)h(NAXIS)f(parameter\).)227 -3489 y(MININ)39 b(and)f(MAXIN)h(are)g(input)e(arra)m(ys)i(that)g(giv)m -(e)h(the)f(minim)m(um)e(and)h(maxim)m(um)h(v)-5 b(alue)39 -b(for)f(the)227 3602 y(histogram,)30 b(along)f(eac)m(h)g(axis.)40 -b(Alternativ)m(ely)-8 b(,)32 b(the)c(name)g(of)h(k)m(eyw)m(ords)f(that) -h(giv)m(e)g(the)f(min,)h(max,)g(and)227 3715 y(binsize)f(ma)m(y)g(b)s -(e)f(giv)m(e)h(with)f(the)h(MINNAME,)h(MAXNAME,)f(and)f(BINNAME)h(arra) -m(y)g(parameters.)40 b(If)227 3828 y(the)33 b(v)-5 b(alue)34 -b(=)e(DOUBLENULL)-10 b(V)g(ALUE)33 b(and)g(no)f(k)m(eyw)m(ord)i(names)e -(are)h(giv)m(en,)i(then)e(the)g(routine)g(will)227 3941 -y(use)i(the)f(TLMINn)g(and)g(TLMAXn)g(k)m(eyw)m(ords,)j(if)d(presen)m -(t,)i(or)f(the)f(actual)i(min)e(and/or)h(max)g(v)-5 b(alues)227 -4054 y(in)30 b(the)h(column.)227 4207 y(BINSIZEIN)j(is)h(an)g(arra)m(y) -g(giving)h(the)f(binsize)g(along)h(eac)m(h)g(axis.)55 -b(If)34 b(the)h(v)-5 b(alue)36 b(=)e(DOUBLENULL-)227 -4320 y(V)-10 b(ALUE,)38 b(and)e(a)i(k)m(eyw)m(ord)f(name)g(is)h(not)f -(sp)s(eci\014ed)f(with)h(BINNAME,)h(then)f(this)g(routine)g(will)h -(\014rst)227 4432 y(lo)s(ok)d(for)f(the)g(TDBINn)g(k)m(eyw)m(ord,)i(or) -f(else)g(will)f(use)g(a)h(binsize)f(=)g(1,)h(or)g(a)f(binsize)g(that)h -(pro)s(duces)e(10)227 4545 y(histogram)e(bins,)f(whic)m(h)g(ev)m(er)h -(is)g(smaller.)95 4811 y Fe(int)47 b(fits_calc_binning)143 -4924 y(Input)g(parameters:)239 5036 y(\(fitsfile)e(*fptr,)94 -b(/*)47 b(IO)g(-)h(pointer)d(to)j(table)e(to)h(be)g(binned)667 -b(*/)286 5149 y(int)47 b(naxis,)333 b(/*)47 b(I)g(-)h(number)e(of)h -(axes/columns)e(in)i(the)g(binned)f(image)94 b(*/)286 -5262 y(char)47 b(colname[4][FLEN_VALUE],)137 b(/*)47 -b(I)h(-)f(optional)f(column)g(names)428 b(*/)286 5375 -y(double)46 b(*minin,)237 b(/*)47 b(I)h(-)f(optional)f(lower)g(bound)h -(value)f(for)h(each)f(axis)95 b(*/)286 5488 y(double)46 -b(*maxin,)237 b(/*)47 b(I)h(-)f(optional)f(upper)g(bound)h(value,)f -(for)h(each)f(axis)h(*/)286 5601 y(double)f(*binsizein,)f(/*)i(I)h(-)f -(optional)f(bin)h(size)f(along)h(each)f(axis)429 b(*/)286 -5714 y(char)47 b(minname[4][FLEN_VALUE],)41 b(/*)48 b(I)f(-)h(optional) -d(keywords)h(for)h(min)333 b(*/)p eop end -%%Page: 62 70 -TeXDict begin 62 69 bop 0 299 a Fj(62)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)286 555 y Fe(char)47 b(maxname[4][FLEN_VALUE],)41 -b(/*)48 b(I)f(-)h(optional)d(keywords)h(for)h(max)333 -b(*/)286 668 y(char)47 b(binname[4][FLEN_VALUE],)41 b(/*)48 -b(I)f(-)h(optional)d(keywords)h(for)h(binsize)141 b(*/)143 -781 y(Output)46 b(parameters:)286 894 y(int)h(*colnum,)237 -b(/*)47 b(O)g(-)h(column)e(numbers,)f(to)j(be)f(binned)f(*/)286 -1007 y(long)h(*naxes,)237 b(/*)47 b(O)g(-)h(number)e(of)h(bins)g(in)g -(each)g(histogram)e(axis)h(*/)286 1120 y(float)h(*amin,)237 -b(/*)47 b(O)g(-)h(lower)e(bound)h(of)g(the)g(histogram)e(axes)i(*/)286 -1233 y(float)g(*amax,)237 b(/*)47 b(O)g(-)h(upper)e(bound)h(of)g(the)g -(histogram)e(axes)i(*/)286 1346 y(float)g(*binsize,)93 -b(/*)47 b(O)g(-)h(width)e(of)h(histogram)f(bins/pixels)e(on)k(each)e -(axis)h(*/)286 1458 y(int)g(*status\))0 1697 y Fi(2)81 -b Fj(Cop)m(y)26 b(the)h(relev)-5 b(an)m(t)28 b(k)m(eyw)m(ords)f(from)g -(the)g(header)f(of)h(the)g(table)h(that)f(is)g(b)s(eing)f(binned,)h(to) -g(the)g(the)g(header)227 1810 y(of)e(the)h(output)e(histogram)i(image.) -40 b(This)24 b(will)i(not)f(cop)m(y)h(the)f(table)h(structure)f(k)m -(eyw)m(ords)g(\(e.g.,)j(NAXIS,)227 1923 y(TF)m(ORMn,)j(TTYPEn,)f -(etc.\))44 b(nor)31 b(will)g(it)g(cop)m(y)h(the)f(k)m(eyw)m(ords)g -(that)h(apply)e(to)i(other)f(columns)g(of)g(the)227 2036 -y(table)g(that)g(are)f(not)h(used)e(to)i(create)g(the)f(histogram.)42 -b(This)29 b(routine)h(will)g(translate)h(the)g(names)f(of)g(the)227 -2149 y(W)-8 b(orld)27 b(Co)s(ordinate)e(System)h(\(W)m(CS\))g(k)m(eyw)m -(ords)g(for)g(the)g(binned)e(columns)h(in)m(to)i(the)f(form)f(that)h -(is)g(need)227 2262 y(for)h(a)g(FITS)g(image)h(\(e.g.,)h(the)e(TCTYPn)f -(table)i(k)m(eyw)m(ord)f(will)g(b)s(e)g(translated)g(to)h(the)f(CTYPEn) -f(image)227 2375 y(k)m(eyw)m(ord\).)95 2613 y Fe(int)47 -b(fits_copy_pixlist2image)286 2726 y(\(fitsfile)f(*infptr,)141 -b(/*)47 b(I)g(-)h(pointer)e(to)h(input)f(HDU)h(*/)334 -2839 y(fitsfile)f(*outfptr,)93 b(/*)47 b(I)g(-)h(pointer)e(to)h(output) -f(HDU)h(*/)334 2952 y(int)g(firstkey,)332 b(/*)47 b(I)g(-)h(first)e -(HDU)h(keyword)f(to)h(start)f(with)h(*/)334 3065 y(int)g(naxis,)476 -b(/*)47 b(I)g(-)h(number)e(of)h(axes)g(in)g(the)g(image)f(*/)334 -3178 y(int)h(*colnum,)380 b(/*)47 b(I)g(-)h(numbers)e(of)h(the)g -(columns)e(to)j(be)f(binned)94 b(*/)334 3291 y(int)47 -b(*status\))380 b(/*)47 b(IO)g(-)g(error)g(status)f(*/)0 -3530 y Fi(3)81 b Fj(W)-8 b(rite)36 b(a)f(set)h(of)f(default)h(W)m(CS)f -(k)m(eyw)m(ords)g(to)h(the)f(histogram)h(header,)g(IF)f(the)g(W)m(CS)g -(k)m(eyw)m(ords)h(do)f(not)227 3643 y(already)40 b(exist.)69 -b(This)38 b(will)i(create)h(a)e(linear)h(W)m(CS)f(where)g(the)h(co)s -(ordinate)g(t)m(yp)s(es)f(are)h(equal)g(to)g(the)227 -3756 y(original)32 b(column)e(names.)95 3994 y Fe(int)47 -b(fits_write_keys_histo)239 4107 y(\(fitsfile)e(*fptr,)237 -b(/*)47 b(I)h(-)f(pointer)f(to)h(table)f(to)i(be)f(binned)666 -b(*/)286 4220 y(fitsfile)46 b(*histptr,)93 b(/*)47 b(I)h(-)f(pointer)f -(to)h(output)f(histogram)f(image)i(HDU)285 b(*/)286 4333 -y(int)47 b(naxis,)476 b(/*)47 b(I)h(-)f(number)f(of)h(axes)g(in)g(the)g -(histogram)e(image)285 b(*/)286 4446 y(int)47 b(*colnum,)380 -b(/*)47 b(I)h(-)f(column)f(numbers)g(of)h(the)g(binned)f(columns)332 -b(*/)286 4559 y(int)47 b(*status\))0 4798 y Fi(4)81 b -Fj(Up)s(date)29 b(the)i(W)m(CS)f(k)m(eyw)m(ords)g(in)g(a)g(histogram)h -(image)g(header)f(that)h(giv)m(e)g(the)f(lo)s(cation)i(of)e(the)g -(reference)227 4911 y(pixel)h(\(CRPIXn\),)f(and)g(the)h(pixel)f(size)h -(\(CDEL)-8 b(Tn\),)31 b(in)f(the)h(binned)e(image.)95 -5149 y Fe(int)47 b(fits_rebin_wcs)239 5262 y(\(fitsfile)e(*fptr,)237 -b(/*)47 b(I)h(-)f(pointer)f(to)h(table)f(to)i(be)f(binned)523 -b(*/)286 5375 y(int)47 b(naxis,)476 b(/*)47 b(I)h(-)f(number)f(of)h -(axes)g(in)g(the)g(histogram)e(image)142 b(*/)286 5488 -y(float)47 b(*amin,)380 b(/*)47 b(I)h(-)f(first)f(pixel)h(include)f(in) -h(each)f(axis)381 b(*/)286 5601 y(float)47 b(*binsize,)236 -b(/*)47 b(I)h(-)f(binning)f(factor)g(for)h(each)f(axis)572 -b(*/)286 5714 y(int)47 b(*status\))p eop end -%%Page: 63 71 -TeXDict begin 63 70 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 -b(R)m(OUTINES)2693 b Fj(63)0 555 y Fi(5)81 b Fj(Bin)33 -b(the)h(v)-5 b(alues)35 b(in)e(the)h(input)f(table)h(columns,)h(and)e -(write)h(the)g(histogram)h(arra)m(y)f(to)g(the)g(output)g(FITS)227 -668 y(image)e(\(histptr\).)95 951 y Fe(int)47 b(fits_make_hist)143 -1064 y(\(fitsfile)e(*fptr,)190 b(/*)47 b(I)g(-)h(pointer)e(to)h(table)f -(with)h(X)g(and)g(Y)h(cols;)285 b(*/)191 1177 y(fitsfile)45 -b(*histptr,)h(/*)h(I)g(-)h(pointer)e(to)h(output)f(FITS)h(image)619 -b(*/)191 1290 y(int)47 b(bitpix,)380 b(/*)47 b(I)g(-)h(datatype)d(for)i -(image:)f(16,)h(32,)g(-32,)g(etc)238 b(*/)191 1403 y(int)47 -b(naxis,)428 b(/*)47 b(I)g(-)h(number)e(of)h(axes)g(in)g(the)g -(histogram)e(image)190 b(*/)191 1516 y(long)47 b(*naxes,)332 -b(/*)47 b(I)g(-)h(size)e(of)i(axes)e(in)h(the)g(histogram)f(image)285 -b(*/)191 1628 y(int)47 b(*colnum,)332 b(/*)47 b(I)g(-)h(column)e -(numbers)g(\(array)g(length)g(=)h(naxis\))190 b(*/)191 -1741 y(float)46 b(*amin,)333 b(/*)47 b(I)g(-)h(minimum)e(histogram)f -(value,)h(for)h(each)g(axis)142 b(*/)191 1854 y(float)46 -b(*amax,)333 b(/*)47 b(I)g(-)h(maximum)e(histogram)f(value,)h(for)h -(each)g(axis)142 b(*/)191 1967 y(float)46 b(*binsize,)189 -b(/*)47 b(I)g(-)h(bin)f(size)f(along)h(each)f(axis)811 -b(*/)191 2080 y(float)46 b(weight,)285 b(/*)47 b(I)g(-)h(binning)e -(weighting)f(factor)h(\(FLOATNULLVALUE)e(*/)1098 2193 -y(/*)238 b(for)47 b(no)g(weighting\))1143 b(*/)191 2306 -y(int)47 b(wtcolnum,)284 b(/*)47 b(I)g(-)h(keyword)e(or)h(col)g(for)g -(weight)284 b(\(or)47 b(NULL\))g(*/)191 2419 y(int)g(recip,)428 -b(/*)47 b(I)g(-)h(use)f(reciprocal)e(of)i(the)g(weight?)f(0)h(or)g(1) -239 b(*/)191 2532 y(char)47 b(*selectrow,)140 b(/*)47 -b(I)g(-)h(optional)d(array)i(\(length)f(=)h(no.)g(of)477 -b(*/)1098 2645 y(/*)47 b(rows)g(in)g(the)g(table\).)93 -b(If)47 b(the)g(element)f(is)h(true)95 b(*/)1098 2758 -y(/*)47 b(then)g(the)f(corresponding)f(row)i(of)g(the)g(table)f(will)h -(*/)1098 2870 y(/*)g(be)g(included)f(in)h(the)g(histogram,)e(otherwise) -g(the)95 b(*/)1098 2983 y(/*)47 b(row)g(will)f(be)i(skipped.)93 -b(Ingnored)45 b(if)j(*selectrow)d(*/)1098 3096 y(/*)i(is)g(equal)f(to)i -(NULL.)1335 b(*/)191 3209 y(int)47 b(*status\))0 3570 -y Ff(5.8)135 b(Utilit)l(y)47 b(Routines)0 3829 y Fd(5.8.1)112 -b(File)39 b(Chec)m(ksum)f(Routines)0 4053 y Fj(The)33 -b(follo)m(wing)h(routines)f(either)h(compute)f(or)h(v)-5 -b(alidate)34 b(the)g(c)m(hec)m(ksums)f(for)g(the)h(CHDU.)g(The)e(D)m(A) --8 b(T)g(ASUM)0 4166 y(k)m(eyw)m(ord)33 b(is)f(used)f(to)i(store)f(the) -h(n)m(umerical)f(v)-5 b(alue)33 b(of)f(the)g(32-bit,)i(1's)f(complemen) -m(t)g(c)m(hec)m(ksum)g(for)f(the)g(data)0 4279 y(unit)26 -b(alone.)40 b(If)25 b(there)h(is)h(no)e(data)i(unit)f(then)f(the)h(v)-5 -b(alue)27 b(is)f(set)g(to)h(zero.)40 b(The)26 b(n)m(umerical)g(v)-5 -b(alue)27 b(is)f(stored)g(as)g(an)0 4392 y(ASCI)s(I)20 -b(string)i(of)h(digits,)h(enclosed)f(in)e(quotes,)k(b)s(ecause)d(the)g -(v)-5 b(alue)23 b(ma)m(y)f(b)s(e)f(to)s(o)i(large)g(to)g(represen)m(t)f -(as)g(a)h(32-bit)0 4505 y(signed)28 b(in)m(teger.)41 -b(The)27 b(CHECKSUM)g(k)m(eyw)m(ord)i(is)f(used)f(to)h(store)h(the)f -(ASCI)s(I)e(enco)s(ded)i(COMPLEMENT)f(of)0 4618 y(the)f(c)m(hec)m(ksum) -h(for)f(the)h(en)m(tire)g(HDU.)g(Storing)f(the)h(complemen)m(t,)h -(rather)e(than)g(the)h(actual)g(c)m(hec)m(ksum,)h(forces)0 -4731 y(the)k(c)m(hec)m(ksum)h(for)f(the)h(whole)f(HDU)h(to)g(equal)g -(zero.)47 b(If)31 b(the)i(\014le)f(has)g(b)s(een)f(mo)s(di\014ed)g -(since)i(the)f(c)m(hec)m(ksums)0 4844 y(w)m(ere)39 b(computed,)i(then)e -(the)g(HDU)g(c)m(hec)m(ksum)h(will)f(usually)f(not)h(equal)h(zero.)66 -b(These)39 b(c)m(hec)m(ksum)g(k)m(eyw)m(ord)0 4957 y(con)m(v)m(en)m -(tions)34 b(are)f(based)f(on)g(a)g(pap)s(er)f(b)m(y)h(Rob)g(Seaman)g -(published)f(in)h(the)g(pro)s(ceedings)g(of)g(the)h(AD)m(ASS)f(IV)0 -5070 y(conference)h(in)e(Baltimore)j(in)d(No)m(v)m(em)m(b)s(er)i(1994)h -(and)d(a)h(later)h(revision)f(in)f(June)g(1995.)47 b(See)32 -b(App)s(endix)e(B)i(for)0 5182 y(the)f(de\014nition)f(of)g(the)h -(parameters)f(used)g(in)g(these)h(routines.)0 5465 y -Fi(1)81 b Fj(Compute)33 b(and)g(write)h(the)g(D)m(A)-8 -b(T)g(ASUM)35 b(and)e(CHECKSUM)g(k)m(eyw)m(ord)h(v)-5 -b(alues)34 b(for)f(the)h(CHDU)g(in)m(to)h(the)227 5578 -y(curren)m(t)d(header.)46 b(If)32 b(the)g(k)m(eyw)m(ords)h(already)g -(exist,)g(their)g(v)-5 b(alues)32 b(will)h(b)s(e)e(up)s(dated)g(only)h -(if)h(necessary)227 5691 y(\(i.e.,)f(if)f(the)f(\014le)h(has)f(b)s(een) -f(mo)s(di\014ed)h(since)g(the)h(original)h(k)m(eyw)m(ord)e(v)-5 -b(alues)31 b(w)m(ere)g(computed\).)p eop end -%%Page: 64 72 -TeXDict begin 64 71 bop 0 299 a Fj(64)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_write_chksum)c(/)48 -b(ffpcks)286 668 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*status\))0 -945 y Fi(2)81 b Fj(Up)s(date)28 b(the)h(CHECKSUM)e(k)m(eyw)m(ord)i(v)-5 -b(alue)29 b(in)f(the)h(CHDU,)g(assuming)f(that)h(the)f(D)m(A)-8 -b(T)g(ASUM)30 b(k)m(eyw)m(ord)227 1058 y(exists)36 b(and)f(already)h -(has)f(the)h(correct)g(v)-5 b(alue.)56 b(This)35 b(routine)g -(calculates)j(the)e(new)f(c)m(hec)m(ksum)h(for)f(the)227 -1171 y(curren)m(t)40 b(header)g(unit,)j(adds)c(it)i(to)g(the)f(data)h -(unit)f(c)m(hec)m(ksum,)k(enco)s(des)c(the)g(v)-5 b(alue)41 -b(in)m(to)g(an)f(ASCI)s(I)227 1284 y(string,)31 b(and)f(writes)g(the)h -(string)f(to)h(the)g(CHECKSUM)e(k)m(eyw)m(ord.)95 1560 -y Fe(int)47 b(fits_update_chksum)c(/)48 b(ffupck)286 -1673 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*status\))0 1950 -y Fi(3)81 b Fj(V)-8 b(erify)35 b(the)f(CHDU)h(b)m(y)g(computing)f(the)h -(c)m(hec)m(ksums)g(and)f(comparing)h(them)f(with)g(the)h(k)m(eyw)m -(ords.)53 b(The)227 2063 y(data)34 b(unit)f(is)g(v)m(eri\014ed)g -(correctly)h(if)f(the)h(computed)f(c)m(hec)m(ksum)g(equals)h(the)f(v)-5 -b(alue)34 b(of)f(the)g(D)m(A)-8 b(T)g(ASUM)227 2176 y(k)m(eyw)m(ord.)64 -b(The)37 b(c)m(hec)m(ksum)i(for)f(the)g(en)m(tire)g(HDU)h(\(header)f -(plus)f(data)i(unit\))e(is)h(correct)h(if)f(it)h(equals)227 -2289 y(zero.)47 b(The)32 b(output)f(D)m(A)-8 b(T)g(A)m(OK)34 -b(and)d(HDUOK)i(parameters)f(in)g(this)g(routine)g(are)g(in)m(tegers)i -(whic)m(h)e(will)227 2402 y(ha)m(v)m(e)k(a)f(v)-5 b(alue)35 -b(=)f(1)h(if)f(the)h(data)g(or)f(HDU)h(is)g(v)m(eri\014ed)f(correctly) --8 b(,)38 b(a)d(v)-5 b(alue)35 b(=)f(0)h(if)f(the)h(D)m(A)-8 -b(T)g(ASUM)36 b(or)227 2515 y(CHECKSUM)29 b(k)m(eyw)m(ord)g(is)h(not)f -(presen)m(t,)h(or)f(v)-5 b(alue)30 b(=)f(-1)h(if)f(the)h(computed)f(c)m -(hec)m(ksum)h(is)f(not)h(correct.)95 2904 y Fe(int)47 -b(fits_verify_chksum)c(/)48 b(ffvcks)286 3017 y(\(fitsfile)e(*fptr,)g -(>)h(int)g(*dataok,)f(int)h(*hduok,)e(int)i(*status\))0 -3294 y Fi(4)81 b Fj(Compute)40 b(and)g(return)g(the)h(c)m(hec)m(ksum)g -(v)-5 b(alues)41 b(for)g(the)g(CHDU)g(without)g(creating)h(or)f(mo)s -(difying)f(the)227 3407 y(CHECKSUM)33 b(and)h(D)m(A)-8 -b(T)g(ASUM)35 b(k)m(eyw)m(ords.)52 b(This)33 b(routine)h(is)g(used)f -(in)m(ternally)i(b)m(y)f(\013v)m(c)m(ks,)i(but)d(ma)m(y)227 -3520 y(b)s(e)d(useful)g(in)g(other)g(situations)h(as)g(w)m(ell.)95 -3796 y Fe(int)47 b(fits_get_chksum/)d(/ffgcks)286 3909 -y(\(fitsfile)i(*fptr,)g(>)h(unsigned)f(long)g(*datasum,)g(unsigned)f -(long)i(*hdusum,)334 4022 y(int)g(*status\))0 4299 y -Fi(5)81 b Fj(Enco)s(de)23 b(a)h(c)m(hec)m(ksum)g(v)-5 -b(alue)24 b(in)m(to)g(a)g(16-c)m(haracter)j(string.)38 -b(If)23 b(complm)h(is)f(non-zero)i(\(true\))f(then)f(the)h(32-bit)227 -4412 y(sum)30 b(v)-5 b(alue)31 b(will)f(b)s(e)g(complemen)m(ted)h(b)s -(efore)f(enco)s(ding.)95 4689 y Fe(int)47 b(fits_encode_chksum)c(/)48 -b(ffesum)286 4801 y(\(unsigned)e(long)g(sum,)h(int)g(complm,)f(>)h -(char)g(*ascii\);)0 5078 y Fi(6)81 b Fj(Deco)s(de)24 -b(a)f(16-c)m(haracter)j(c)m(hec)m(ksum)e(string)f(in)m(to)g(a)h -(unsigned)e(long)h(v)-5 b(alue.)39 b(If)23 b(is)g(non-zero)g(\(true\).) -39 b(then)23 b(the)227 5191 y(32-bit)33 b(sum)d(v)-5 -b(alue)32 b(will)g(b)s(e)f(complemen)m(ted)h(after)g(deco)s(ding.)44 -b(The)31 b(c)m(hec)m(ksum)h(v)-5 b(alue)32 b(is)g(also)g(returned)227 -5304 y(as)f(the)f(v)-5 b(alue)31 b(of)g(the)f(function.)95 -5581 y Fe(unsigned)46 b(long)h(fits_decode_chksum)42 -b(/)48 b(ffdsum)525 5694 y(\(char)e(*ascii,)g(int)h(complm,)f(>)h -(unsigned)f(long)h(*sum\);)p eop end -%%Page: 65 73 -TeXDict begin 65 72 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 -b(R)m(OUTINES)2693 b Fj(65)0 555 y Fd(5.8.2)112 b(Date)38 -b(and)g(Time)g(Utilit)m(y)f(Routines)0 774 y Fj(The)29 -b(follo)m(wing)i(routines)f(help)f(to)i(construct)f(or)f(parse)h(the)g -(FITS)f(date/time)i(strings.)41 b(Starting)30 b(in)f(the)h(y)m(ear)0 -887 y(2000,)k(the)d(FITS)g(D)m(A)-8 b(TE)32 b(k)m(eyw)m(ord)g(v)-5 -b(alues)31 b(\(and)h(the)f(v)-5 b(alues)32 b(of)f(other)h(`D)m(A)-8 -b(TE-')33 b(k)m(eyw)m(ords\))f(m)m(ust)f(ha)m(v)m(e)i(the)0 -1000 y(form)j('YYYY-MM-DD')k(\(date)e(only\))f(or)g -('YYYY-MM-DDThh:mm:ss.ddd...')61 b(\(date)38 b(and)e(time\))h(where)0 -1113 y(the)30 b(n)m(um)m(b)s(er)f(of)i(decimal)g(places)g(in)f(the)g -(seconds)g(v)-5 b(alue)31 b(is)f(optional.)42 b(These)30 -b(times)h(are)f(in)g(UTC.)g(The)g(older)0 1226 y('dd/mm/yy')d(date)g -(format)g(ma)m(y)h(not)f(b)s(e)f(used)g(for)h(dates)h(after)f(01)h(Jan) -m(uary)e(2000.)42 b(See)27 b(App)s(endix)e(B)i(for)g(the)0 -1339 y(de\014nition)j(of)h(the)f(parameters)h(used)e(in)h(these)h -(routines.)0 1597 y Fi(1)81 b Fj(Get)23 b(the)f(curren)m(t)f(system)i -(date.)38 b(C)22 b(already)g(pro)m(vides)g(standard)f(library)h -(routines)g(for)f(getting)j(the)e(curren)m(t)227 1710 -y(date)k(and)e(time,)j(but)d(this)h(routine)g(is)g(pro)m(vided)g(for)f -(compatibilit)m(y)k(with)c(the)h(F)-8 b(ortran)26 b(FITSIO)e(library)-8 -b(.)227 1823 y(The)30 b(returned)f(y)m(ear)j(has)e(4)g(digits)h -(\(1999,)i(2000,)g(etc.\))95 2081 y Fe(int)47 b -(fits_get_system_date/ffgsd)o(t)286 2194 y(\()h(>)f(int)g(*day,)g(int)f -(*month,)g(int)h(*year,)f(int)h(*status)f(\))0 2452 y -Fi(2)81 b Fj(Get)34 b(the)g(curren)m(t)g(system)f(date)i(and)e(time)h -(string)g(\('YYYY-MM-DDThh:mm:ss'\).)53 b(The)33 b(time)i(will)f(b)s(e) -227 2565 y(in)26 b(UTC/GMT)g(if)g(a)m(v)-5 b(ailable,)29 -b(as)e(indicated)f(b)m(y)g(a)g(returned)f(timeref)h(v)-5 -b(alue)27 b(=)e(0.)40 b(If)26 b(the)g(returned)e(v)-5 -b(alue)227 2678 y(of)31 b(timeref)g(=)g(1)g(then)f(this)h(indicates)g -(that)h(it)f(w)m(as)g(not)g(p)s(ossible)f(to)h(con)m(v)m(ert)i(the)d -(lo)s(cal)i(time)g(to)f(UTC,)227 2791 y(and)f(th)m(us)g(the)h(lo)s(cal) -g(time)g(w)m(as)g(returned.)95 3049 y Fe(int)47 b -(fits_get_system_time/ffgst)o(m)286 3162 y(\(>)h(char)e(*datestr,)f -(int)95 b(*timeref,)45 b(int)i(*status\))0 3421 y Fi(3)81 -b Fj(Construct)26 b(a)i(date)g(string)f(from)g(the)g(input)f(date)i(v) --5 b(alues.)40 b(If)27 b(the)g(y)m(ear)h(is)g(b)s(et)m(w)m(een)f(1900)i -(and)e(1998,)j(inclu-)227 3534 y(siv)m(e,)38 b(then)c(the)i(returned)d -(date)j(string)f(will)g(ha)m(v)m(e)i(the)e(old)g(FITS)f(format)i -(\('dd/mm/yy'\),)h(otherwise)227 3647 y(the)32 b(date)f(string)g(will)h -(ha)m(v)m(e)g(the)g(new)e(FITS)h(format)g(\('YYYY-MM-DD'\).)36 -b(Use)31 b(\014ts)p 3229 3647 28 4 v 33 w(time2str)h(instead)227 -3759 y(to)f(alw)m(a)m(ys)h(return)e(a)g(date)h(string)g(using)f(the)g -(new)g(FITS)g(format.)95 4018 y Fe(int)47 b(fits_date2str/ffdt2s)286 -4131 y(\(int)g(year,)f(int)h(month,)f(int)h(day,)g(>)g(char)g -(*datestr,)e(int)i(*status\))0 4389 y Fi(4)81 b Fj(Construct)34 -b(a)i(new-format)f(date)h(+)f(time)h(string)f -(\('YYYY-MM-DDThh:mm:ss.ddd...'\).)57 b(If)34 b(the)i(y)m(ear,)227 -4502 y(mon)m(th,)d(and)e(da)m(y)h(v)-5 b(alues)32 b(all)h(=)e(0)h(then) -g(only)g(the)g(time)g(is)g(enco)s(ded)f(with)h(format)g -('hh:mm:ss.ddd...'.)227 4615 y(The)j(decimals)h(parameter)g(sp)s -(eci\014es)e(ho)m(w)i(man)m(y)f(decimal)h(places)g(of)f(fractional)i -(seconds)e(to)h(include)227 4728 y(in)30 b(the)h(string.)41 -b(If)29 b(`decimals')j(is)f(negativ)m(e,)h(then)f(only)f(the)h(date)g -(will)f(b)s(e)g(return)f(\('YYYY-MM-DD'\).)95 4986 y -Fe(int)47 b(fits_time2str/fftm2s)286 5099 y(\(int)g(year,)f(int)h -(month,)f(int)h(day,)g(int)g(hour,)f(int)h(minute,)f(double)g(second,) -286 5212 y(int)h(decimals,)f(>)h(char)g(*datestr,)e(int)i(*status\))0 -5470 y Fi(5)81 b Fj(Return)44 b(the)g(date)i(as)f(read)f(from)h(the)g -(input)e(string,)49 b(where)44 b(the)h(string)g(ma)m(y)g(b)s(e)f(in)h -(either)g(the)g(old)227 5583 y(\('dd/mm/yy'\))29 b(or)f(new)f -(\('YYYY-MM-DDThh:mm:ss')k(or)d('YYYY-MM-DD'\))j(FITS)d(format.)40 -b(Null)227 5696 y(p)s(oin)m(ters)31 b(ma)m(y)f(b)s(e)g(supplied)f(for)h -(an)m(y)h(un)m(w)m(an)m(ted)g(output)f(date)h(parameters.)p -eop end -%%Page: 66 74 -TeXDict begin 66 73 bop 0 299 a Fj(66)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_str2date/ffs2dt)286 -668 y(\(char)g(*datestr,)e(>)i(int)g(*year,)f(int)h(*month,)f(int)h -(*day,)f(int)h(*status\))0 917 y Fi(6)81 b Fj(Return)30 -b(the)h(date)h(and)f(time)h(as)f(read)g(from)g(the)h(input)e(string,)h -(where)g(the)h(string)f(ma)m(y)h(b)s(e)e(in)h(either)h(the)227 -1030 y(old)d(or)f(new)g(FITS)g(format.)40 b(The)28 b(returned)f(hours,) -h(min)m(utes,)h(and)f(seconds)g(v)-5 b(alues)29 b(will)f(b)s(e)g(set)h -(to)g(zero)227 1142 y(if)k(the)h(input)e(string)h(do)s(es)g(not)h -(include)f(the)g(time)h(\('dd/mm/yy')f(or)h('YYYY-MM-DD'\))j(.)c -(Similarly)-8 b(,)227 1255 y(the)36 b(returned)e(y)m(ear,)j(mon)m(th,)g -(and)d(date)i(v)-5 b(alues)36 b(will)f(b)s(e)g(set)h(to)g(zero)g(if)f -(the)g(date)h(is)f(not)h(included)e(in)227 1368 y(the)29 -b(input)f(string)h(\('hh:mm:ss.ddd...'\).)40 b(Null)29 -b(p)s(oin)m(ters)f(ma)m(y)i(b)s(e)e(supplied)f(for)i(an)m(y)g(un)m(w)m -(an)m(ted)g(output)227 1481 y(date)i(and)f(time)h(parameters.)95 -1730 y Fe(int)47 b(fits_str2time/ffs2tm)286 1843 y(\(char)g(*datestr,)e -(>)i(int)g(*year,)f(int)h(*month,)f(int)h(*day,)f(int)h(*hour,)286 -1956 y(int)g(*minute,)f(double)g(*second,)f(int)i(*status\))0 -2244 y Fd(5.8.3)112 b(General)39 b(Utilit)m(y)e(Routines)0 -2463 y Fj(The)30 b(follo)m(wing)i(utilit)m(y)f(routines)g(ma)m(y)g(b)s -(e)e(useful)h(for)g(certain)h(applications.)0 2712 y -Fi(1)81 b Fj(Return)30 b(the)h(revision)g(n)m(um)m(b)s(er)f(of)h(the)g -(CFITSIO)f(library)-8 b(.)42 b(The)31 b(revision)g(n)m(um)m(b)s(er)f -(will)h(b)s(e)f(incremen)m(ted)227 2825 y(with)g(eac)m(h)i(new)e -(release)h(of)g(CFITSIO.)95 3073 y Fe(float)47 b(fits_get_version)c(/) -48 b(ffvers)e(\()h(>)h(float)e(*version\))0 3322 y Fi(2)81 -b Fj(W)-8 b(rite)34 b(an)g(80-c)m(haracter)i(message)e(to)g(the)g -(CFITSIO)e(error)h(stac)m(k.)51 b(Application)34 b(programs)f(should)g -(not)227 3435 y(normally)e(write)f(to)i(the)e(stac)m(k,)i(but)e(there)g -(ma)m(y)h(b)s(e)f(some)h(situations)g(where)f(this)g(is)h(desirable.)95 -3683 y Fe(void)47 b(fits_write_errmsg)c(/)48 b(ffpmsg)e(\(char)g -(*err_msg\))0 3932 y Fi(3)81 b Fj(Con)m(v)m(ert)31 b(a)g(c)m(haracter)h -(string)e(to)h(upp)s(ercase)e(\(op)s(erates)j(in)e(place\).)95 -4180 y Fe(void)47 b(fits_uppercase)d(/)j(ffupch)g(\(char)f(*string\))0 -4429 y Fi(4)81 b Fj(Compare)43 b(the)i(input)e(template)i(string)f -(against)h(the)g(reference)f(string)g(to)h(see)g(if)f(they)g(matc)m(h.) -82 b(The)227 4542 y(template)36 b(string)f(ma)m(y)g(con)m(tain)g -(wildcard)f(c)m(haracters:)51 b('*')35 b(will)g(matc)m(h)g(an)m(y)g -(sequence)g(of)f(c)m(haracters)227 4655 y(\(including)j(zero)h(c)m -(haracters\))g(and)e(')10 b(?')60 b(will)38 b(matc)m(h)f(an)m(y)g -(single)h(c)m(haracter)g(in)f(the)g(reference)g(string.)227 -4768 y(The)e('#')h(c)m(haracter)h(will)f(matc)m(h)g(an)m(y)g -(consecutiv)m(e)h(string)f(of)f(decimal)i(digits)f(\(0)g(-)f(9\).)57 -b(If)35 b(casesen)h(=)227 4881 y(CASESEN)c(=)h(TR)m(UE)h(then)f(the)g -(matc)m(h)i(will)e(b)s(e)g(case)h(sensitiv)m(e,)i(otherwise)e(the)f -(case)i(of)e(the)h(letters)227 4993 y(will)g(b)s(e)f(ignored)h(if)g -(casesen)g(=)g(CASEINSEN)e(=)h(F)-10 b(ALSE.)34 b(The)f(returned)f(MA) --8 b(TCH)34 b(parameter)h(will)227 5106 y(b)s(e)30 b(TR)m(UE)g(if)g -(the)g(2)h(strings)f(matc)m(h,)h(and)f(EXA)m(CT)g(will)g(b)s(e)g(TR)m -(UE)g(if)g(the)g(matc)m(h)h(is)f(exact)i(\(i.e.,)g(if)e(no)227 -5219 y(wildcard)k(c)m(haracters)i(w)m(ere)f(used)e(in)h(the)h(matc)m -(h\).)53 b(Both)35 b(strings)g(m)m(ust)f(b)s(e)f(68)j(c)m(haracters)f -(or)g(less)f(in)227 5332 y(length.)95 5581 y Fe(void)47 -b(fits_compare_str)c(/)48 b(ffcmps)334 5694 y(\(char)e(*templt,)g(char) -h(*string,)e(int)i(casesen,)f(>)h(int)g(*match,)f(int)h(*exact\))p -eop end -%%Page: 67 75 -TeXDict begin 67 74 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 -b(R)m(OUTINES)2693 b Fj(67)0 555 y Fi(5)81 b Fj(Split)30 -b(a)i(string)f(con)m(taining)h(a)g(list)f(of)g(names)g(\(t)m(ypically)j -(\014le)d(names)g(or)g(column)f(names\))i(in)m(to)g(individual)227 -668 y(name)23 b(tok)m(ens)g(b)m(y)g(a)g(sequence)g(of)g(calls)g(to)h -(\014ts)p 1814 668 28 4 v 32 w(split)p 2018 668 V 33 -w(names.)38 b(The)22 b(names)h(in)f(the)h(list)g(m)m(ust)f(b)s(e)g -(delimited)227 781 y(b)m(y)45 b(a)f(comma)i(and/or)e(spaces.)83 -b(This)44 b(routine)g(ignores)h(spaces)g(and)f(commas)h(that)g(o)s -(ccur)f(within)227 894 y(paren)m(theses,)36 b(brac)m(k)m(ets,)h(or)e -(curly)f(brac)m(k)m(ets.)54 b(It)35 b(also)g(strips)f(an)m(y)h(leading) -g(and)f(trailing)h(blanks)f(from)227 1007 y(the)d(returned)e(name.)227 -1156 y(This)h(routine)g(is)h(similar)f(to)h(the)g(ANSI)f(C)g('strtok')h -(function:)227 1305 y(The)37 b(\014rst)f(call)i(to)g(\014ts)p -1033 1305 V 32 w(split)p 1237 1305 V 33 w(names)f(has)g(a)g(non-n)m -(ull)f(input)g(string.)61 b(It)37 b(\014nds)e(the)i(\014rst)f(name)h -(in)g(the)227 1418 y(string)26 b(and)f(terminates)h(it)h(b)m(y)e(o)m(v) -m(erwriting)i(the)f(next)g(c)m(haracter)h(of)f(the)g(string)f(with)h(a) -g(n)m(ull)f(terminator)227 1530 y(and)31 b(returns)g(a)h(p)s(oin)m(ter) -f(to)i(the)e(name.)45 b(Eac)m(h)32 b(subsequen)m(t)f(call,)j(indicated) -e(b)m(y)f(a)h(NULL)g(v)-5 b(alue)32 b(of)g(the)227 1643 -y(input)f(string,)i(returns)e(the)h(next)h(name,)f(searc)m(hing)h(from) -f(just)g(past)g(the)g(end)f(of)i(the)f(previous)g(name.)227 -1756 y(It)f(returns)e(NULL)h(when)g(no)g(further)f(names)h(are)h -(found.)143 2008 y Fe(char)47 b(*fits_split_names\(char)42 -b(*namelist\))0 2259 y Fj(The)30 b(follo)m(wing)i(example)f(sho)m(ws)f -(ho)m(w)g(a)h(string)f(w)m(ould)h(b)s(e)e(split)i(in)m(to)g(3)g(names:) -191 2511 y Fe(myfile[1][bin)44 b(\(x,y\)=4],)h(file2.fits)93 -b(file3.fits)191 2624 y(^^^^^^^^^^^^^^^^^^^^^^)c(^^^^^^^^^^)k -(^^^^^^^^^^)382 2737 y(1st)47 b(name)619 b(2nd)47 b(name)190 -b(3rd)47 b(name)0 2988 y Fi(6)81 b Fj(T)-8 b(est)34 b(that)g(the)g(k)m -(eyw)m(ord)g(name)f(con)m(tains)i(only)e(legal)j(c)m(haracters)f -(\(A-Z,0-9,)h(h)m(yphen,)d(and)g(underscore\))227 3101 -y(or)e(that)g(the)f(k)m(eyw)m(ord)h(record)f(con)m(tains)i(only)e -(legal)i(prin)m(table)f(ASCI)s(I)e(c)m(haracters)95 3353 -y Fe(int)47 b(fits_test_keyword)c(/)48 b(fftkey)e(\(char)g(*keyname,)g -(>)h(int)g(*status\))95 3579 y(int)g(fits_test_record)d(/)j(fftrec)f -(\(char)h(*card,)f(>)h(int)g(*status\))0 3830 y Fi(7)81 -b Fj(T)-8 b(est)25 b(whether)f(the)h(curren)m(t)f(header)h(con)m(tains) -g(an)m(y)g(NULL)g(\(ASCI)s(I)e(0\))j(c)m(haracters.)40 -b(These)24 b(c)m(haracters)j(are)227 3943 y(illegal)37 -b(in)d(the)h(header,)g(but)f(they)g(will)h(go)g(undetected)g(b)m(y)f -(most)h(of)g(the)f(CFITSIO)f(k)m(eyw)m(ord)i(header)227 -4056 y(routines,)29 b(b)s(ecause)f(the)h(n)m(ull)f(is)g(in)m(terpreted) -g(as)h(the)f(normal)g(end-of-string)h(terminator.)41 -b(This)27 b(routine)227 4169 y(returns)h(the)g(p)s(osition)h(of)g(the)g -(\014rst)f(n)m(ull)g(c)m(haracter)i(in)f(the)f(header,)h(or)g(zero)g -(if)g(there)g(are)g(no)f(n)m(ulls.)40 b(F)-8 b(or)227 -4282 y(example)37 b(a)f(returned)f(v)-5 b(alue)37 b(of)f(110)h(w)m -(ould)f(indicate)h(that)g(the)f(\014rst)f(NULL)h(is)g(lo)s(cated)h(in)f -(the)g(30th)227 4395 y(c)m(haracter)28 b(of)f(the)g(second)f(k)m(eyw)m -(ord)h(in)f(the)h(header)f(\(recall)i(that)f(eac)m(h)h(header)e(record) -h(is)f(80)h(c)m(haracters)227 4508 y(long\).)45 b(Note)33 -b(that)f(this)g(is)f(one)h(of)g(the)g(few)f(CFITSIO)f(routines)h(in)h -(whic)m(h)f(the)h(returned)e(v)-5 b(alue)32 b(is)g(not)227 -4620 y(necessarily)g(equal)e(to)i(the)e(status)h(v)-5 -b(alue\).)95 4872 y Fe(int)47 b(fits_null_check)d(/)j(ffnchk)g(\(char)f -(*card,)g(>)h(int)g(*status\))0 5124 y Fi(8)81 b Fj(P)m(arse)25 -b(a)g(header)g(k)m(eyw)m(ord)g(record)g(and)f(return)g(the)h(name)g(of) -g(the)g(k)m(eyw)m(ord,)i(and)d(the)h(length)h(of)f(the)g(name.)227 -5237 y(The)34 b(k)m(eyw)m(ord)h(name)f(normally)h(o)s(ccupies)f(the)h -(\014rst)e(8)i(c)m(haracters)g(of)g(the)f(record,)i(except)f(under)e -(the)227 5349 y(HIERAR)m(CH)e(con)m(v)m(en)m(tion)h(where)e(the)h(name) -f(can)h(b)s(e)f(up)f(to)i(70)g(c)m(haracters)h(in)e(length.)95 -5601 y Fe(int)47 b(fits_get_keyname)d(/)j(ffgknm)286 -5714 y(\(char)g(*card,)f(>)h(char)g(*keyname,)e(int)i(*keylength,)e -(int)i(*status\))p eop end -%%Page: 68 76 -TeXDict begin 68 75 bop 0 299 a Fj(68)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Fi(9)81 b Fj(P)m(arse)29 b(a)h(header)f(k)m(eyw)m -(ord)h(record,)f(returning)g(the)g(v)-5 b(alue)30 b(\(as)g(a)f(literal) -i(c)m(haracter)g(string\))e(and)g(commen)m(t)227 668 -y(strings.)40 b(If)27 b(the)g(k)m(eyw)m(ord)h(has)f(no)g(v)-5 -b(alue)28 b(\(columns)f(9-10)i(not)f(equal)f(to)h('=)g('\),)g(then)f(a) -h(n)m(ull)f(v)-5 b(alue)28 b(string)227 781 y(is)j(returned)e(and)h -(the)g(commen)m(t)i(string)e(is)g(set)h(equal)g(to)g(column)f(9)h(-)g -(80)g(of)g(the)f(input)g(string.)95 1034 y Fe(int)47 -b(fits_parse_value)d(/)j(ffpsvc)286 1147 y(\(char)g(*card,)f(>)h(char)g -(*value,)f(char)g(*comment,)g(int)h(*status\))0 1401 -y Fi(10)f Fj(Construct)40 b(a)g(prop)s(erly)f(formated)i(80-c)m -(haracter)i(header)d(k)m(eyw)m(ord)g(record)g(from)g(the)g(input)f(k)m -(eyw)m(ord)227 1514 y(name,)25 b(k)m(eyw)m(ord)f(v)-5 -b(alue,)25 b(and)e(k)m(eyw)m(ord)h(commen)m(t)g(strings.)38 -b(Hierarc)m(hical)26 b(k)m(eyw)m(ord)e(names)f(\(e.g.,)j("ESO)227 -1627 y(TELE)e(CAM"\))i(are)f(supp)s(orted.)37 b(The)25 -b(v)-5 b(alue)25 b(string)g(ma)m(y)h(con)m(tain)g(an)f(in)m(teger,)i -(\015oating)f(p)s(oin)m(t,)g(logical,)227 1739 y(or)31 -b(quoted)f(c)m(haracter)i(string)e(\(e.g.,)j("12",)f("15.7",)h("T",)e -(or)g("'NGC)g(1313'"\).)143 1993 y Fe(int)47 b(fits_make_key)d(/)k -(ffmkky)334 2106 y(\(const)e(char)h(*keyname,)e(const)h(char)h(*value,) -f(const)g(char)h(*comment,)430 2219 y(>)g(char)g(*card,)f(int)h -(*status\))0 2472 y Fi(11)f Fj(Construct)26 b(an)h(arra)m(y)g(indexed)f -(k)m(eyw)m(ord)h(name)f(\(R)m(OOT)g(+)h(nnn\).)38 b(This)26 -b(routine)g(app)s(ends)f(the)i(sequence)227 2585 y(n)m(um)m(b)s(er)i -(to)i(the)g(ro)s(ot)g(string)f(to)h(create)h(a)f(k)m(eyw)m(ord)g(name)f -(\(e.g.,)i('NAXIS')f(+)f(2)h(=)f('NAXIS2'\))95 2838 y -Fe(int)47 b(fits_make_keyn)d(/)k(ffkeyn)286 2951 y(\(char)f(*keyroot,)e -(int)i(value,)f(>)h(char)g(*keyname,)e(int)i(*status\))0 -3205 y Fi(12)f Fj(Construct)41 b(a)h(sequence)f(k)m(eyw)m(ord)h(name)g -(\(n)f(+)g(R)m(OOT\).)g(This)g(routine)g(concatenates)j(the)e(sequence) -227 3318 y(n)m(um)m(b)s(er)20 b(to)j(the)e(fron)m(t)h(of)g(the)f(ro)s -(ot)h(string)g(to)g(create)h(a)f(k)m(eyw)m(ord)g(name)g(\(e.g.,)j(1)d -(+)f('CTYP')g(=)g('1CTYP'\))95 3684 y Fe(int)47 b(fits_make_nkey)d(/)k -(ffnkey)286 3797 y(\(int)f(value,)f(char)h(*keyroot,)e(>)i(char)g -(*keyname,)e(int)i(*status\))0 4050 y Fi(13)f Fj(Determine)41 -b(the)g(data)f(t)m(yp)s(e)h(of)f(a)h(k)m(eyw)m(ord)f(v)-5 -b(alue)41 b(string.)70 b(This)39 b(routine)i(parses)e(the)i(k)m(eyw)m -(ord)f(v)-5 b(alue)227 4163 y(string)28 b(to)h(determine)f(its)g(data)h -(t)m(yp)s(e.)40 b(Returns)27 b('C',)h('L',)h('I',)f('F')h(or)f('X',)g -(for)g(c)m(haracter)i(string,)e(logical,)227 4276 y(in)m(teger,)k -(\015oating)g(p)s(oin)m(t,)e(or)h(complex,)g(resp)s(ectiv)m(ely)-8 -b(.)95 4530 y Fe(int)47 b(fits_get_keytype)d(/)j(ffdtyp)286 -4642 y(\(char)g(*value,)f(>)h(char)g(*dtype,)e(int)i(*status\))0 -4896 y Fi(14)f Fj(Determine)39 b(the)f(in)m(teger)h(data)g(t)m(yp)s(e)f -(of)g(an)g(in)m(teger)h(k)m(eyw)m(ord)f(v)-5 b(alue)39 -b(string.)63 b(The)37 b(returned)g(datat)m(yp)s(e)227 -5009 y(v)-5 b(alue)36 b(is)f(the)g(minim)m(um)f(in)m(teger)i(datat)m -(yp)s(e)g(\(starting)g(from)f(top)g(of)g(the)g(follo)m(wing)i(list)e -(and)g(w)m(orking)227 5122 y(do)m(wn\))c(required)e(to)i(store)g(the)g -(in)m(teger)h(v)-5 b(alue:)191 5375 y Fe(Data)47 b(Type)285 -b(Range)239 5488 y(TSBYTE:)236 b(-128)47 b(to)g(127)239 -5601 y(TBYTE:)332 b(128)47 b(to)g(255)239 5714 y(TSHORT:)236 -b(-32768)46 b(to)i(32767)p eop end -%%Page: 69 77 -TeXDict begin 69 76 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 -b(R)m(OUTINES)2693 b Fj(69)239 555 y Fe(TUSHORT:)236 -b(32768)46 b(to)i(65535)239 668 y(TINT)380 b(-2147483648)45 -b(to)i(2147483647)239 781 y(TUINT)380 b(2147483648)45 -b(to)i(4294967295)239 894 y(TLONGLONG)140 b(-9223372036854775808)43 -b(to)k(9223372036854775807)80 1162 y Fj(The)30 b(*neg)h(parameter)g -(returns)e(1)i(if)f(the)h(input)e(v)-5 b(alue)31 b(is)g(negativ)m(e)h -(and)e(returns)f(0)i(if)f(it)h(is)g(non-negativ)m(e.)95 -1431 y Fe(int)47 b(fits_get_inttype)d(/)j(ffinttyp)286 -1544 y(\(char)g(*value,)f(>)h(int)g(*datatype,)e(int)i(*neg,)f(int)h -(*status\))0 1812 y Fi(15)f Fj(Return)35 b(the)g(class)h(of)g(an)f -(input)g(header)g(record.)56 b(The)35 b(record)g(is)g(classi\014ed)h -(in)m(to)h(one)e(of)h(the)f(follo)m(wing)227 1925 y(categories)d(\(the) -e(class)g(v)-5 b(alues)30 b(are)f(de\014ned)f(in)h(\014tsio.h\).)41 -b(Note)31 b(that)e(this)h(is)f(one)h(of)f(the)g(few)g(CFITSIO)227 -2038 y(routines)i(that)f(do)s(es)h(not)f(return)f(a)i(status)g(v)-5 -b(alue.)334 2306 y Fe(Class)94 b(Value)619 b(Keywords)95 -2419 y(TYP_STRUC_KEY)92 b(10)j(SIMPLE,)46 b(BITPIX,)g(NAXIS,)g(NAXISn,) -g(EXTEND,)g(BLOCKED,)1002 2532 y(GROUPS,)g(PCOUNT,)g(GCOUNT,)g(END)1002 -2645 y(XTENSION,)g(TFIELDS,)f(TTYPEn,)h(TBCOLn,)g(TFORMn,)g(THEAP,)1002 -2758 y(and)h(the)g(first)f(4)i(COMMENT)e(keywords)f(in)i(the)g(primary) -f(array)1002 2871 y(that)h(define)f(the)h(FITS)g(format.)95 -2984 y(TYP_CMPRS_KEY)92 b(20)j(The)47 b(keywords)f(used)g(in)i(the)e -(compressed)f(image)i(or)g(table)1002 3097 y(format,)f(including)f -(ZIMAGE,)h(ZCMPTYPE,)f(ZNAMEn,)h(ZVALn,)1002 3210 y(ZTILEn,)g(ZBITPIX,) -g(ZNAXISn,)f(ZSCALE,)h(ZZERO,)g(ZBLANK)95 3323 y(TYP_SCAL_KEY)140 -b(30)95 b(BSCALE,)46 b(BZERO,)g(TSCALn,)g(TZEROn)95 3435 -y(TYP_NULL_KEY)140 b(40)95 b(BLANK,)46 b(TNULLn)95 3548 -y(TYP_DIM_KEY)188 b(50)95 b(TDIMn)95 3661 y(TYP_RANG_KEY)140 -b(60)95 b(TLMINn,)46 b(TLMAXn,)g(TDMINn,)g(TDMAXn,)g(DATAMIN,)f -(DATAMAX)95 3774 y(TYP_UNIT_KEY)140 b(70)95 b(BUNIT,)46 -b(TUNITn)95 3887 y(TYP_DISP_KEY)140 b(80)95 b(TDISPn)95 -4000 y(TYP_HDUID_KEY)d(90)j(EXTNAME,)46 b(EXTVER,)g(EXTLEVEL,)f -(HDUNAME,)g(HDUVER,)h(HDULEVEL)95 4113 y(TYP_CKSUM_KEY)f(100)94 -b(CHECKSUM,)46 b(DATASUM)95 4226 y(TYP_WCS_KEY)141 b(110)94 -b(WCS)47 b(keywords)f(defined)g(in)h(the)g(the)g(WCS)f(papers,)g -(including:)1002 4339 y(CTYPEn,)g(CUNITn,)g(CRVALn,)g(CRPIXn,)g -(CROTAn,)f(CDELTn)1002 4452 y(CDj_is,)h(PVj_ms,)g(LONPOLEs,)f(LATPOLEs) -1002 4565 y(TCTYPn,)h(TCTYns,)g(TCUNIn,)g(TCUNns,)g(TCRVLn,)f(TCRVns,)h -(TCRPXn,)1002 4677 y(TCRPks,)g(TCDn_k,)g(TCn_ks,)g(TPVn_m,)g(TPn_ms,)f -(TCDLTn,)h(TCROTn)1002 4790 y(jCTYPn,)g(jCTYns,)g(jCUNIn,)g(jCUNns,)g -(jCRVLn,)f(jCRVns,)h(iCRPXn,)1002 4903 y(iCRPns,)g(jiCDn,)94 -b(jiCDns,)46 b(jPVn_m,)g(jPn_ms,)f(jCDLTn,)h(jCROTn)1002 -5016 y(\(i,j,m,n)g(are)h(integers,)e(s)i(is)h(any)f(letter\))95 -5129 y(TYP_REFSYS_KEY)d(120)j(EQUINOXs,)f(EPOCH,)g(MJD-OBSs,)f -(RADECSYS,)g(RADESYSs,)g(DATE-OBS)95 5242 y(TYP_COMM_KEY)140 -b(130)47 b(COMMENT,)f(HISTORY,)f(\(blank)h(keyword\))95 -5355 y(TYP_CONT_KEY)140 b(140)47 b(CONTINUE)95 5468 y(TYP_USER_KEY)140 -b(150)47 b(all)g(other)g(keywords)95 5694 y(int)g(fits_get_keyclass)c -(/)48 b(ffgkcl)e(\(char)g(*card\))p eop end -%%Page: 70 78 -TeXDict begin 70 77 bop 0 299 a Fj(70)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Fi(16)46 b Fj(P)m(arse)28 b(the)g('TF)m(ORM')g -(binary)f(table)h(column)g(format)f(string.)40 b(This)27 -b(routine)g(parses)g(the)h(input)f(TF)m(ORM)227 668 y(c)m(haracter)38 -b(string)d(and)g(returns)g(the)g(in)m(teger)i(data)g(t)m(yp)s(e)f(co)s -(de,)h(the)f(rep)s(eat)g(coun)m(t)g(of)g(the)f(\014eld,)i(and,)227 -781 y(in)e(the)f(case)i(of)f(c)m(haracter)h(string)f(\014elds,)g(the)g -(length)g(of)g(the)g(unit)f(string.)54 b(See)34 b(App)s(endix)f(B)i -(for)g(the)227 894 y(allo)m(w)m(ed)41 b(v)-5 b(alues)38 -b(for)h(the)f(returned)g(t)m(yp)s(eco)s(de)h(parameter.)65 -b(A)39 b(n)m(ull)f(p)s(oin)m(ter)h(ma)m(y)g(b)s(e)f(giv)m(en)h(for)g -(an)m(y)227 1007 y(output)30 b(parameters)h(that)g(are)g(not)f(needed.) -143 1261 y Fe(int)47 b(fits_binary_tform)c(/)48 b(ffbnfm)334 -1374 y(\(char)e(*tform,)g(>)i(int)f(*typecode,)e(long)h(*repeat,)g -(long)g(*width,)382 1487 y(int)h(*status\))143 1713 y(int)g -(fits_binary_tformll)c(/)k(ffbnfmll)334 1826 y(\(char)f(*tform,)g(>)i -(int)f(*typecode,)e(LONGLONG)g(*repeat,)h(long)g(*width,)382 -1939 y(int)h(*status\))0 2194 y Fi(17)f Fj(P)m(arse)38 -b(the)f('TF)m(ORM')h(k)m(eyw)m(ord)g(v)-5 b(alue)37 b(that)h(de\014nes) -e(the)h(column)g(format)h(in)e(an)h(ASCI)s(I)f(table.)62 -b(This)227 2307 y(routine)29 b(parses)g(the)g(input)f(TF)m(ORM)h(c)m -(haracter)h(string)f(and)g(returns)e(the)i(data)h(t)m(yp)s(e)f(co)s -(de,)h(the)f(width)227 2419 y(of)f(the)f(column,)h(and)f(\(if)h(it)g -(is)f(a)h(\015oating)g(p)s(oin)m(t)g(column\))f(the)h(n)m(um)m(b)s(er)e -(of)h(decimal)i(places)f(to)g(the)f(righ)m(t)227 2532 -y(of)39 b(the)f(decimal)h(p)s(oin)m(t.)65 b(The)38 b(returned)f(data)i -(t)m(yp)s(e)f(co)s(des)g(are)h(the)g(same)f(as)h(for)f(the)g(binary)g -(table,)227 2645 y(with)26 b(the)h(follo)m(wing)h(additional)f(rules:) -38 b(in)m(teger)28 b(columns)e(that)h(are)f(b)s(et)m(w)m(een)h(1)g(and) -f(4)g(c)m(haracters)i(wide)227 2758 y(are)i(de\014ned)e(to)j(b)s(e)d -(short)i(in)m(tegers)g(\(co)s(de)g(=)g(TSHOR)-8 b(T\).)29 -b(Wider)g(in)m(teger)i(columns)e(are)h(de\014ned)e(to)j(b)s(e)227 -2871 y(regular)39 b(in)m(tegers)g(\(co)s(de)g(=)f(TLONG\).)h(Similarly) --8 b(,)41 b(Fixed)e(decimal)g(p)s(oin)m(t)f(columns)g(\(with)h(TF)m -(ORM)227 2984 y(=)c('Fw.d'\))g(are)h(de\014ned)d(to)j(b)s(e)e(single)i -(precision)f(reals)h(\(co)s(de)f(=)g(TFLO)m(A)-8 b(T\))35 -b(if)g(w)g(is)g(b)s(et)m(w)m(een)g(1)h(and)227 3097 y(7)42 -b(c)m(haracters)h(wide,)h(inclusiv)m(e.)75 b(Wider)41 -b('F')h(columns)f(will)h(return)e(a)i(double)f(precision)h(data)g(co)s -(de)227 3210 y(\(=)32 b(TDOUBLE\).)h('Ew.d')f(format)g(columns)g(will)g -(ha)m(v)m(e)i(dataco)s(de)f(=)e(TFLO)m(A)-8 b(T,)33 b(and)e('Dw.d')i -(format)227 3323 y(columns)45 b(will)h(ha)m(v)m(e)h(dataco)s(de)f(=)f -(TDOUBLE.)g(A)h(n)m(ull)f(p)s(oin)m(ter)h(ma)m(y)f(b)s(e)g(giv)m(en)i -(for)e(an)m(y)g(output)227 3436 y(parameters)31 b(that)g(are)g(not)f -(needed.)95 3690 y Fe(int)47 b(fits_ascii_tform)d(/)j(ffasfm)286 -3803 y(\(char)g(*tform,)f(>)h(int)g(*typecode,)e(long)i(*width,)e(int)i -(*decimals,)334 3916 y(int)g(*status\))0 4171 y Fi(18)f -Fj(Calculate)32 b(the)f(starting)g(column)g(p)s(ositions)f(and)g(total) -i(ASCI)s(I)d(table)j(width)d(based)i(on)f(the)h(input)e(arra)m(y)227 -4284 y(of)e(ASCI)s(I)e(table)i(TF)m(ORM)g(v)-5 b(alues.)40 -b(The)26 b(SP)-8 b(A)m(CE)27 b(input)e(parameter)i(de\014nes)f(ho)m(w)h -(man)m(y)f(blank)h(spaces)227 4397 y(to)40 b(lea)m(v)m(e)i(b)s(et)m(w)m -(een)e(eac)m(h)g(column)g(\(it)g(is)f(recommended)g(to)h(ha)m(v)m(e)h -(one)e(space)h(b)s(et)m(w)m(een)g(columns)f(for)227 4509 -y(b)s(etter)31 b(h)m(uman)e(readabilit)m(y\).)95 4764 -y Fe(int)47 b(fits_get_tbcol)d(/)k(ffgabc)286 4877 y(\(int)f(tfields,)f -(char)g(**tform,)g(int)h(space,)f(>)h(long)g(*rowlen,)334 -4990 y(long)g(*tbcol,)f(int)g(*status\))0 5245 y Fi(19)g -Fj(P)m(arse)27 b(a)g(template)h(header)e(record)g(and)g(return)g(a)g -(formatted)h(80-c)m(haracter)j(string)c(suitable)h(for)f(app)s(end-)227 -5357 y(ing)40 b(to)f(\(or)h(deleting)g(from\))f(a)g(FITS)g(header)g -(\014le.)67 b(This)38 b(routine)h(is)g(useful)g(for)f(parsing)h(lines)g -(from)227 5470 y(an)33 b(ASCI)s(I)f(template)i(\014le)f(and)g -(reformatting)h(them)f(in)m(to)h(legal)h(FITS)d(header)h(records.)49 -b(The)32 b(format-)227 5583 y(ted)i(string)g(ma)m(y)g(then)f(b)s(e)g -(passed)h(to)g(the)g(\014ts)p 1880 5583 28 4 v 32 w(write)p -2114 5583 V 33 w(record,)h(\013mcrd,)f(or)g(\014ts)p -3007 5583 V 32 w(delete)p 3270 5583 V 34 w(k)m(ey)h(routines)e(to)227 -5696 y(app)s(end)c(or)h(mo)s(dify)g(a)h(FITS)e(header)h(record.)p -eop end -%%Page: 71 79 -TeXDict begin 71 78 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 -b(R)m(OUTINES)2693 b Fj(71)95 555 y Fe(int)47 b(fits_parse_template)c -(/)k(ffgthd)286 668 y(\(char)g(*templt,)e(>)j(char)e(*card,)g(int)h -(*keytype,)f(int)h(*status\))0 932 y Fj(The)31 b(input)g(templt)h(c)m -(haracter)h(string)f(generally)h(should)d(con)m(tain)j(3)f(tok)m(ens:) -44 b(\(1\))33 b(the)f(KEYNAME,)g(\(2\))h(the)0 1045 y(V)-10 -b(ALUE,)37 b(and)f(\(3\))i(the)f(COMMENT)g(string.)59 -b(The)37 b(TEMPLA)-8 b(TE)36 b(string)h(m)m(ust)f(adhere)h(to)h(the)e -(follo)m(wing)0 1158 y(format:)0 1421 y Fi(-)80 b Fj(The)32 -b(KEYNAME)h(tok)m(en)h(m)m(ust)f(b)s(egin)f(in)h(columns)f(1-8)i(and)e -(b)s(e)g(a)h(maxim)m(um)g(of)g(8)g(c)m(haracters)h(long.)49 -b(A)227 1534 y(legal)30 b(FITS)e(k)m(eyw)m(ord)h(name)f(ma)m(y)h(only)f -(con)m(tain)i(the)f(c)m(haracters)g(A-Z,)g(0-9,)h(and)e('-')h(\(min)m -(us)f(sign\))h(and)227 1647 y(underscore.)40 b(This)27 -b(routine)i(will)g(automatically)i(con)m(v)m(ert)f(an)m(y)f(lo)m(w)m -(ercase)i(c)m(haracters)f(to)g(upp)s(ercase)d(in)227 -1760 y(the)k(output)f(string.)42 b(If)30 b(the)h(\014rst)f(8)h(c)m -(haracters)h(of)f(the)g(template)h(line)f(are)g(blank)f(then)h(the)g -(remainder)227 1873 y(of)g(the)f(line)h(is)g(considered)f(to)h(b)s(e)f -(a)g(FITS)g(commen)m(t)h(\(with)g(a)g(blank)f(k)m(eyw)m(ord)g(name\).)0 -2137 y Fi(-)80 b Fj(The)26 b(V)-10 b(ALUE)26 b(tok)m(en)h(m)m(ust)e(b)s -(e)h(separated)g(from)f(the)i(KEYNAME)f(tok)m(en)h(b)m(y)f(one)g(or)g -(more)g(spaces)g(and/or)227 2250 y(an)g('=')g(c)m(haracter.)41 -b(The)25 b(data)h(t)m(yp)s(e)g(of)g(the)g(V)-10 b(ALUE)26 -b(tok)m(en)g(\(n)m(umeric,)h(logical,)j(or)c(c)m(haracter)h(string\))f -(is)227 2363 y(automatically)35 b(determined)c(and)h(the)g(output)f -(CARD)h(string)g(is)g(formatted)g(accordingly)-8 b(.)47 -b(The)31 b(v)-5 b(alue)227 2476 y(tok)m(en)34 b(ma)m(y)f(b)s(e)f -(forced)g(to)i(b)s(e)e(in)m(terpreted)g(as)h(a)g(string)g(\(e.g.)48 -b(if)33 b(it)g(is)f(a)h(string)g(of)f(n)m(umeric)h(digits\))g(b)m(y)227 -2588 y(enclosing)g(it)f(in)f(single)h(quotes.)45 b(If)31 -b(the)h(v)-5 b(alue)32 b(tok)m(en)g(is)g(a)g(c)m(haracter)h(string)e -(that)i(con)m(tains)f(1)g(or)g(more)227 2701 y(em)m(b)s(edded)39 -b(blank)g(space)h(c)m(haracters)h(or)e(slash)h(\('/'\))h(c)m(haracters) -g(then)e(the)g(en)m(tire)i(c)m(haracter)g(string)227 -2814 y(m)m(ust)31 b(b)s(e)e(enclosed)i(in)f(single)h(quotes.)0 -3078 y Fi(-)80 b Fj(The)28 b(COMMENT)g(tok)m(en)h(is)f(optional,)i(but) -e(if)g(presen)m(t)g(m)m(ust)g(b)s(e)g(separated)g(from)g(the)h(V)-10 -b(ALUE)28 b(tok)m(en)h(b)m(y)227 3191 y(a)i(blank)f(space)h(or)f(a)h -('/')g(c)m(haracter.)0 3455 y Fi(-)80 b Fj(One)29 b(exception)h(to)f -(the)g(ab)s(o)m(v)m(e)i(rules)d(is)h(that)g(if)g(the)g(\014rst)g -(non-blank)f(c)m(haracter)i(in)f(the)g(\014rst)f(8)h(c)m(haracters)227 -3568 y(of)24 b(the)h(template)g(string)f(is)g(a)g(min)m(us)g(sign)g -(\('-'\))h(follo)m(w)m(ed)h(b)m(y)e(a)g(single)h(tok)m(en,)h(or)e(a)h -(single)f(tok)m(en)h(follo)m(w)m(ed)227 3681 y(b)m(y)k(an)g(equal)h -(sign,)g(then)f(it)g(is)h(in)m(terpreted)f(as)h(the)f(name)g(of)h(a)f -(k)m(eyw)m(ord)h(whic)m(h)f(is)g(to)h(b)s(e)e(deleted)i(from)227 -3793 y(the)h(FITS)e(header.)0 4057 y Fi(-)80 b Fj(The)32 -b(second)g(exception)h(is)f(that)h(if)f(the)g(template)h(string)f -(starts)h(with)e(a)i(min)m(us)e(sign)h(and)f(is)h(follo)m(w)m(ed)i(b)m -(y)227 4170 y(2)f(tok)m(ens)g(\(without)g(an)f(equals)h(sign)g(b)s(et)m -(w)m(een)g(them\))f(then)g(the)h(second)f(tok)m(en)i(is)e(in)m -(terpreted)h(as)g(the)227 4283 y(new)f(name)h(for)f(the)h(k)m(eyw)m -(ord)g(sp)s(eci\014ed)f(b)m(y)h(\014rst)f(tok)m(en.)48 -b(In)32 b(this)g(case)i(the)f(old)g(k)m(eyw)m(ord)g(name)f(\(\014rst) -227 4396 y(tok)m(en\))c(is)e(returned)e(in)i(c)m(haracters)h(1-8)g(of)g -(the)f(returned)e(CARD)j(string,)g(and)e(the)h(new)f(k)m(eyw)m(ord)i -(name)227 4509 y(\(the)35 b(second)e(tok)m(en\))j(is)e(returned)e(in)i -(c)m(haracters)h(41-48)h(of)e(the)g(returned)e(CARD)i(string.)51 -b(These)34 b(old)227 4622 y(and)i(new)f(names)h(ma)m(y)h(then)f(b)s(e)f -(passed)g(to)i(the)f(\013mnam)g(routine)g(whic)m(h)g(will)g(c)m(hange)h -(the)f(k)m(eyw)m(ord)227 4735 y(name.)0 4998 y(The)30 -b(k)m(eyt)m(yp)s(e)h(output)f(parameter)h(indicates)g(ho)m(w)g(the)f -(returned)g(CARD)g(string)g(should)g(b)s(e)f(in)m(terpreted:)382 -5262 y Fe(keytype)857 b(interpretation)382 5375 y(-------)475 -b(-------------------------)o(----)o(---)o(----)o(----)o(---)o(----)o -(--)525 5488 y(-2)572 b(Rename)46 b(the)h(keyword)f(with)h(name)f(=)i -(the)f(first)f(8)h(characters)e(of)j(CARD)1193 5601 y(to)f(the)g(new)g -(name)g(given)f(in)h(characters)e(41)j(-)f(48)g(of)g(CARD.)p -eop end -%%Page: 72 80 -TeXDict begin 72 79 bop 0 299 a Fj(72)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)525 555 y Fe(-1)572 b(delete)46 b(the)h(keyword)f(with)h -(this)f(name)h(from)g(the)f(FITS)h(header.)573 781 y(0)572 -b(append)46 b(the)h(CARD)g(string)f(to)h(the)g(FITS)g(header)f(if)h -(the)1193 894 y(keyword)f(does)h(not)g(already)e(exist,)h(otherwise)g -(update)1193 1007 y(the)h(keyword)f(value)g(and/or)g(comment)g(field)h -(if)g(is)g(already)f(exists.)573 1233 y(1)572 b(This)47 -b(is)g(a)g(HISTORY)f(or)h(COMMENT)f(keyword;)g(append)g(it)h(to)g(the)g -(header)573 1458 y(2)572 b(END)47 b(record;)f(do)h(not)g(explicitly)e -(write)h(it)i(to)f(the)g(FITS)f(file.)0 1708 y Fj(EXAMPLES:)30 -b(The)g(follo)m(wing)i(lines)e(illustrate)i(v)-5 b(alid)31 -b(input)e(template)j(strings:)286 1958 y Fe(INTVAL)46 -b(7)i(/)f(This)g(is)g(an)g(integer)f(keyword)286 2071 -y(RVAL)524 b(34.6)142 b(/)239 b(This)46 b(is)i(a)f(floating)f(point)g -(keyword)286 2184 y(EVAL=-12.45E-03)92 b(/)47 b(This)g(is)g(a)g -(floating)f(point)g(keyword)g(in)h(exponential)e(notation)286 -2296 y(lval)i(F)g(/)h(This)f(is)g(a)g(boolean)f(keyword)859 -2409 y(This)h(is)g(a)g(comment)f(keyword)g(with)h(a)g(blank)f(keyword)g -(name)286 2522 y(SVAL1)h(=)g('Hello)f(world')142 b(/)95 -b(this)47 b(is)g(a)g(string)f(keyword)286 2635 y(SVAL2)94 -b('123.5')g(this)47 b(is)g(also)f(a)i(string)e(keyword)286 -2748 y(sval3)94 b(123+)h(/)g(this)47 b(is)g(also)f(a)i(string)e -(keyword)g(with)g(the)h(value)g('123+)189 b(')286 2861 -y(#)48 b(the)f(following)e(template)h(line)g(deletes)g(the)h(DATE)g -(keyword)286 2974 y(-)h(DATE)286 3087 y(#)g(the)f(following)e(template) -h(line)g(modifies)g(the)h(NAME)f(keyword)g(to)h(OBJECT)286 -3200 y(-)h(NAME)e(OBJECT)0 3449 y Fi(20)g Fj(T)-8 b(ranslate)32 -b(a)g(k)m(eyw)m(ord)g(name)f(in)m(to)h(a)g(new)f(name,)h(based)f(on)g -(a)h(set)f(of)h(patterns.)43 b(This)31 b(routine)g(is)h(useful)227 -3562 y(for)j(translating)h(k)m(eyw)m(ords)g(in)e(cases)i(suc)m(h)f(as)h -(adding)e(or)h(deleting)h(columns)f(in)g(a)g(table,)j(or)d(cop)m(ying) -227 3675 y(a)41 b(column)g(from)f(one)h(table)g(to)g(another,)j(or)c -(extracting)j(an)d(arra)m(y)h(from)f(a)h(cell)h(in)e(a)h(binary)f -(table)227 3788 y(column)31 b(in)m(to)g(an)g(image)g(extension.)42 -b(In)30 b(these)h(cases,)h(it)f(is)g(necessary)g(to)g(translate)h(the)f -(names)f(of)h(the)227 3901 y(k)m(eyw)m(ords)f(asso)s(ciated)i(with)d -(the)h(original)h(table)g(column\(s\))f(in)m(to)g(the)g(appropriate)g -(k)m(eyw)m(ord)g(name)g(in)227 4014 y(the)37 b(\014nal)f(\014le.)58 -b(F)-8 b(or)37 b(example,)i(if)d(column)h(2)f(is)h(deleted)g(from)e(a)i -(table,)i(then)d(the)h(v)-5 b(alue)36 b(of)h('n')f(in)g(all)227 -4127 y(the)c(TF)m(ORMn)g(and)f(TTYPEn)f(k)m(eyw)m(ords)i(for)g(columns) -f(3)h(and)f(higher)h(m)m(ust)f(b)s(e)g(decremen)m(ted)i(b)m(y)e(1.)227 -4240 y(Ev)m(en)j(more)g(complex)h(translations)f(are)h(sometimes)f -(needed)g(to)h(con)m(v)m(ert)g(the)f(W)m(CS)g(k)m(eyw)m(ords)g(when)227 -4353 y(extracting)e(an)f(image)g(out)g(of)f(a)h(table)g(column)g(cell)g -(in)m(to)h(a)e(separate)i(image)f(extension.)227 4501 -y(The)g(user)f(passes)i(an)f(arra)m(y)g(of)h(patterns)f(to)h(b)s(e)e -(matc)m(hed.)44 b(Input)30 b(pattern)h(n)m(um)m(b)s(er)f(i)i(is)f -(pattern[i][0],)227 4614 y(and)j(output)f(pattern)h(n)m(um)m(b)s(er)f -(i)h(is)g(pattern[i][1].)53 b(Keyw)m(ords)34 b(are)g(matc)m(hed)h -(against)g(the)f(input)f(pat-)227 4727 y(terns.)41 b(If)30 -b(a)g(matc)m(h)i(is)e(found)f(then)h(the)h(k)m(eyw)m(ord)g(is)f -(re-written)h(according)g(to)g(the)g(output)f(pattern.)227 -4876 y(Order)41 b(is)h(imp)s(ortan)m(t.)76 b(The)41 b(\014rst)h(matc)m -(h)h(is)f(accepted.)77 b(The)41 b(fastest)i(matc)m(h)g(will)f(b)s(e)g -(made)g(when)227 4989 y(templates)32 b(with)e(the)h(same)f(\014rst)g(c) -m(haracter)i(are)f(group)s(ed)e(together.)227 5137 y(Sev)m(eral)j(c)m -(haracters)f(ha)m(v)m(e)h(sp)s(ecial)f(meanings:)466 -5375 y Fe(i,j)47 b(-)g(single)f(digits,)g(preserved)f(in)j(output)e -(template)466 5488 y(n)h(-)h(column)e(number)g(of)h(one)g(or)g(more)g -(digits,)f(preserved)f(in)i(output)f(template)466 5601 -y(m)h(-)h(generic)e(number)g(of)h(one)g(or)g(more)g(digits,)e -(preserved)h(in)h(output)f(template)466 5714 y(a)h(-)h(coordinate)d -(designator,)g(preserved)g(in)i(output)f(template)p eop -end -%%Page: 73 81 -TeXDict begin 73 80 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 -b(R)m(OUTINES)2693 b Fj(73)466 555 y Fe(#)47 b(-)h(number)e(of)h(one)g -(or)g(more)g(digits)466 668 y(?)g(-)h(any)f(character)466 -781 y(*)g(-)h(only)e(allowed)g(in)h(first)g(character)e(position,)g(to) -j(match)e(all)657 894 y(keywords;)f(only)i(useful)f(as)h(last)g -(pattern)e(in)j(the)f(list)227 1133 y Fj(i,)31 b(j,)f(n,)g(and)g(m)g -(are)h(returned)e(b)m(y)i(the)f(routine.)227 1282 y(F)-8 -b(or)27 b(example,)g(the)f(input)f(pattern)h("iCTYPn")g(will)g(matc)m -(h)h("1CTYP5")g(\(if)f(n)p 3003 1282 28 4 v 32 w(v)-5 -b(alue)26 b(is)g(5\);)i(the)e(output)227 1395 y(pattern)31 -b("CTYPEi")f(will)h(b)s(e)f(re-written)h(as)f("CTYPE1".)42 -b(Notice)32 b(that)f("i")g(is)g(preserv)m(ed.)227 1544 -y(The)f(follo)m(wing)i(output)e(patterns)g(are)h(sp)s(ecial:)227 -1693 y("-")h(-)e(do)h(not)f(cop)m(y)h(a)g(k)m(eyw)m(ord)g(that)g(matc)m -(hes)g(the)g(corresp)s(onding)e(input)h(pattern)227 1841 -y("+")h(-)g(cop)m(y)g(the)f(input)g(unc)m(hanged)227 -1990 y(The)f(inrec)h(string)g(could)g(b)s(e)f(just)g(the)h(8-c)m(har)h -(k)m(eyw)m(ord)f(name,)g(or)f(the)h(en)m(tire)h(80-c)m(har)g(header)f -(record.)227 2103 y(Characters)h(9)g(-)f(80)h(in)g(the)f(input)g -(string)g(simply)g(get)h(app)s(ended)e(to)i(the)g(translated)g(k)m(eyw) -m(ord)f(name.)227 2252 y(If)h(n)p 375 2252 V 33 w(range)g(=)g(0,)i -(then)e(only)h(k)m(eyw)m(ords)f(with)h('n')f(equal)h(to)g(n)p -2410 2252 V 32 w(v)-5 b(alue)32 b(will)g(b)s(e)f(considered)g(as)h(a)g -(pattern)227 2365 y(matc)m(h.)70 b(If)39 b(n)p 722 2365 -V 32 w(range)h(=)f(+1,)j(then)e(all)g(v)-5 b(alues)40 -b(of)g('n')f(greater)i(than)e(or)h(equal)g(to)g(n)p 3269 -2365 V 33 w(v)-5 b(alue)40 b(will)g(b)s(e)f(a)227 2478 -y(matc)m(h,)32 b(and)e(if)g(-1,)h(then)f(v)-5 b(alues)31 -b(of)g('n')f(less)g(than)h(or)f(equal)h(to)g(n)p 2530 -2478 V 32 w(v)-5 b(alue)31 b(will)g(matc)m(h.)0 2728 -y Fe(int)47 b(fits_translate_keyword\()286 2841 y(char)g(*inrec,)380 -b(/*)47 b(I)h(-)f(input)f(string)g(*/)286 2954 y(char)h(*outrec,)332 -b(/*)47 b(O)h(-)f(output)f(converted)f(string,)h(or)h(*/)1241 -3067 y(/*)238 b(a)47 b(null)g(string)f(if)h(input)g(does)f(not)95 -b(*/)1241 3180 y(/*)238 b(match)46 b(any)h(of)g(the)g(patterns)f(*/)286 -3293 y(char)h(*patterns[][2],/*)c(I)48 b(-)f(pointer)f(to)h(input)f(/)i -(output)e(string)g(*/)1241 3406 y(/*)238 b(templates)45 -b(*/)286 3519 y(int)i(npat,)524 b(/*)47 b(I)h(-)f(number)f(of)h -(templates)f(passed)g(*/)286 3632 y(int)h(n_value,)380 -b(/*)47 b(I)h(-)f(base)g('n')g(template)e(value)h(of)i(interest)d(*/) -286 3745 y(int)i(n_offset,)332 b(/*)47 b(I)h(-)f(offset)f(to)h(be)g -(applied)f(to)h(the)g('n')g(*/)1241 3857 y(/*)238 b(value)46 -b(in)i(the)e(output)h(string)f(*/)286 3970 y(int)h(n_range,)380 -b(/*)47 b(I)h(-)f(controls)f(range)g(of)h('n')g(template)f(*/)1241 -4083 y(/*)238 b(values)46 b(of)h(interest)f(\(-1,0,)g(or)h(+1\))g(*/) -286 4196 y(int)g(*pat_num,)332 b(/*)47 b(O)h(-)f(matched)f(pattern)g -(number)g(\(0)h(based\))f(or)h(-1)g(*/)286 4309 y(int)g(*i,)620 -b(/*)47 b(O)h(-)f(value)f(of)i(i,)f(if)g(any,)g(else)f(0)i(*/)286 -4422 y(int)f(*j,)620 b(/*)47 b(O)h(-)f(value)f(of)i(j,)f(if)g(any,)g -(else)f(0)i(*/)286 4535 y(int)f(*m,)620 b(/*)47 b(O)h(-)f(value)f(of)i -(m,)f(if)g(any,)g(else)f(0)i(*/)286 4648 y(int)f(*n,)620 -b(/*)47 b(O)h(-)f(value)f(of)i(n,)f(if)g(any,)g(else)f(0)i(*/)286 -4761 y(int)f(*status\))380 b(/*)47 b(IO)g(-)h(error)e(status)g(*/)80 -5011 y Fj(Here)25 b(is)f(an)g(example)g(of)g(some)h(of)f(the)g -(patterns)g(used)f(to)i(con)m(v)m(ert)g(the)f(k)m(eyw)m(ords)h(asso)s -(ciated)g(with)f(an)g(image)227 5124 y(in)30 b(a)h(cell)h(of)e(a)h -(table)g(column)f(in)m(to)i(the)e(k)m(eyw)m(ords)h(appropriate)f(for)h -(an)f(IMA)m(GE)h(extension:)191 5375 y Fe(char)47 b(*patterns[][2])c(=) -48 b({{"TSCALn",)92 b("BSCALE")i(},)h(/*)47 b(Standard)e(FITS)i -(keywords)e(*/)143 5488 y({"TZEROn",)93 b("BZERO")141 -b(},)143 5601 y({"TUNITn",)93 b("BUNIT")141 b(},)143 -5714 y({"TNULLn",)93 b("BLANK")141 b(},)p eop end -%%Page: 74 82 -TeXDict begin 74 81 bop 0 299 a Fj(74)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)143 555 y Fe({"TDMINn",)93 b("DATAMIN")45 -b(},)143 668 y({"TDMAXn",)93 b("DATAMAX")45 b(},)143 -781 y({"iCTYPn",)93 b("CTYPEi")g(},)i(/*)47 b(Coordinate)e(labels)h(*/) -143 894 y({"iCTYna",)93 b("CTYPEia")45 b(},)143 1007 -y({"iCUNIn",)93 b("CUNITi")g(},)i(/*)47 b(Coordinate)e(units)i(*/)143 -1120 y({"iCUNna",)93 b("CUNITia")45 b(},)143 1233 y({"iCRVLn",)93 -b("CRVALi")g(},)i(/*)47 b(WCS)g(keywords)f(*/)143 1346 -y({"iCRVna",)93 b("CRVALia")45 b(},)143 1458 y({"iCDLTn",)93 -b("CDELTi")g(},)143 1571 y({"iCDEna",)g("CDELTia")45 -b(},)143 1684 y({"iCRPXn",)93 b("CRPIXi")g(},)143 1797 -y({"iCRPna",)g("CRPIXia")45 b(},)143 1910 y({"ijPCna",)93 -b("PCi_ja")g(},)143 2023 y({"ijCDna",)g("CDi_ja")g(},)143 -2136 y({"iVn_ma",)g("PVi_ma")g(},)143 2249 y({"iSn_ma",)g("PSi_ma")g -(},)143 2362 y({"iCRDna",)g("CRDERia")45 b(},)143 2475 -y({"iCSYna",)93 b("CSYERia")45 b(},)143 2588 y({"iCROTn",)93 -b("CROTAi")g(},)143 2700 y({"WCAXna",)g("WCSAXESa"},)143 -2813 y({"WCSNna",)g("WCSNAMEa"}};)0 3065 y Fi(21)46 b -Fj(T)-8 b(ranslate)26 b(the)f(k)m(eyw)m(ords)g(in)g(the)g(input)e(HDU)j -(in)m(to)g(the)f(k)m(eyw)m(ords)g(that)h(are)f(appropriate)g(for)f(the) -h(output)227 3178 y(HDU.)32 b(This)d(is)i(a)f(driv)m(er)h(routine)f -(that)h(calls)g(the)g(previously)f(describ)s(ed)f(routine.)0 -3430 y Fe(int)47 b(fits_translate_keywords\()143 3543 -y(fitsfile)f(*infptr,)141 b(/*)47 b(I)g(-)h(pointer)e(to)h(input)f(HDU) -h(*/)143 3656 y(fitsfile)f(*outfptr,)93 b(/*)47 b(I)g(-)h(pointer)e(to) -h(output)f(HDU)h(*/)143 3768 y(int)g(firstkey,)332 b(/*)47 -b(I)g(-)h(first)e(HDU)h(record)f(number)g(to)h(start)g(with)f(*/)143 -3881 y(char)h(*patterns[][2],/*)c(I)k(-)h(pointer)e(to)h(input)f(/)i -(output)e(keyword)g(templates)f(*/)143 3994 y(int)i(npat,)524 -b(/*)47 b(I)g(-)h(number)e(of)h(templates)e(passed)h(*/)143 -4107 y(int)h(n_value,)380 b(/*)47 b(I)g(-)h(base)e('n')h(template)f -(value)g(of)h(interest)f(*/)143 4220 y(int)h(n_offset,)332 -b(/*)47 b(I)g(-)h(offset)e(to)h(be)g(applied)f(to)h(the)g('n')g(*/)1193 -4333 y(/*)238 b(value)47 b(in)g(the)g(output)f(string)g(*/)143 -4446 y(int)h(n_range,)380 b(/*)47 b(I)g(-)h(controls)d(range)i(of)g -('n')g(template)e(*/)1098 4559 y(/*)238 b(values)46 b(of)h(interest)f -(\(-1,0,)g(or)h(+1\))g(*/)143 4672 y(int)g(*status\))380 -b(/*)47 b(IO)g(-)h(error)e(status)g(*/)0 4924 y Fi(22)g -Fj(P)m(arse)35 b(the)g(input)f(string)h(con)m(taining)h(a)f(list)h(of)f -(ro)m(ws)f(or)h(ro)m(w)g(ranges,)h(and)e(return)g(in)m(teger)i(arra)m -(ys)f(con-)227 5036 y(taining)27 b(the)f(\014rst)f(and)g(last)i(ro)m(w) -f(in)f(eac)m(h)i(range.)40 b(F)-8 b(or)26 b(example,)i(if)d(ro)m(wlist) -i(=)e("3-5,)k(6,)e(8-9")h(then)d(it)i(will)227 5149 y(return)34 -b(n)m(umranges)h(=)g(3,)h(rangemin)f(=)g(3,)i(6,)g(8)e(and)g(rangemax)g -(=)g(5,)i(6,)g(9.)55 b(A)m(t)36 b(most,)h('maxranges')227 -5262 y(n)m(um)m(b)s(er)31 b(of)h(ranges)f(will)h(b)s(e)g(returned.)43 -b('maxro)m(ws')32 b(is)g(the)g(maxim)m(um)g(n)m(um)m(b)s(er)e(of)i(ro)m -(ws)g(in)f(the)h(table;)227 5375 y(an)m(y)e(ro)m(ws)f(or)g(ranges)g -(larger)h(than)f(this)g(will)g(b)s(e)g(ignored.)40 b(The)29 -b(ro)m(ws)g(m)m(ust)g(b)s(e)f(sp)s(eci\014ed)h(in)f(increasing)227 -5488 y(order,)33 b(and)f(the)g(ranges)h(m)m(ust)f(not)g(o)m(v)m(erlap.) -48 b(A)33 b(min)m(us)e(sign)i(ma)m(y)g(b)s(e)e(use)h(to)h(sp)s(ecify)f -(all)h(the)g(ro)m(ws)f(to)227 5601 y(the)h(upp)s(er)d(or)j(lo)m(w)m(er) -h(b)s(ound,)d(so)i("50-")h(means)e(all)i(the)f(ro)m(ws)f(from)g(50)h -(to)h(the)e(end)g(of)h(the)f(table,)j(and)227 5714 y("-")d(means)e(all) -h(the)g(ro)m(ws)f(in)g(the)h(table,)g(from)f(1)h(-)g(maxro)m(ws.)p -eop end -%%Page: 75 83 -TeXDict begin 75 82 bop 0 299 a Fh(5.8.)72 b(UTILITY)30 -b(R)m(OUTINES)2693 b Fj(75)191 555 y Fe(int)47 b(fits_parse_range)c(/) -48 b(ffrwrg\(char)c(*rowlist,)i(LONGLONG)f(maxrows,)h(int)h(maxranges,) -e(>)334 668 y(int)i(*numranges,)e(long)h(*rangemin,)f(long)i -(*rangemax,)e(int)i(*status\))191 894 y(int)g(fits_parse_rangell)c(/)k -(ffrwrgll\(char)d(*rowlist,)i(LONGLONG)f(maxrows,)h(int)h(maxranges,)e -(>)334 1007 y(int)i(*numranges,)e(LONGLONG)g(*rangemin,)g(LONGLONG)h -(*rangemax,)f(int)i(*status\))0 1267 y Fi(23)f Fj(Chec)m(k)37 -b(that)g(the)g(Header)g(\014ll)g(b)m(ytes)g(\(if)g(an)m(y\))g(are)g -(all)h(blank.)59 b(These)36 b(are)h(the)g(b)m(ytes)g(that)g(ma)m(y)h -(follo)m(w)227 1380 y(END)e(k)m(eyw)m(ord)g(and)f(b)s(efore)g(the)h(b)s -(eginning)f(of)h(data)g(unit,)g(or)g(the)g(end)f(of)g(the)h(HDU)g(if)g -(there)f(is)h(no)227 1492 y(data)31 b(unit.)191 1752 -y Fe(int)47 b(ffchfl\(fitsfile)c(*fptr,)k(>)g(int)g(*status\))0 -2012 y Fi(24)f Fj(Chec)m(k)30 b(that)g(the)f(Data)i(\014ll)e(b)m(ytes)h -(\(if)g(an)m(y\))g(are)g(all)g(zero)g(\(for)f(IMA)m(GE)i(or)e(BINAR)-8 -b(Y)30 b(T)-8 b(able)30 b(HDU\))h(or)e(all)227 2125 y(blanks)g(\(for)g -(ASCI)s(I)f(table)i(HDU\).)g(These)f(\014le)g(b)m(ytes)h(ma)m(y)f(b)s -(e)g(lo)s(cated)h(after)g(the)f(last)h(v)-5 b(alid)29 -b(data)h(b)m(yte)227 2238 y(in)g(the)h(HDU)g(and)f(b)s(efore)g(the)g -(ph)m(ysical)h(end)f(of)h(the)f(HDU.)191 2498 y Fe(int)47 -b(ffcdfl\(fitsfile)c(*fptr,)k(>)g(int)g(*status\))0 2757 -y Fi(25)f Fj(Estimate)35 b(the)e(ro)s(ot-mean-squared)h(\(RMS\))f -(noise)h(in)f(an)g(image.)51 b(These)33 b(routines)g(are)h(mainly)f -(for)g(use)227 2870 y(with)25 b(the)g(Hcompress)g(image)i(compression)e -(algorithm.)40 b(They)24 b(return)g(an)h(estimate)i(of)e(the)h(RMS)f -(noise)227 2983 y(in)38 b(the)f(bac)m(kground)h(pixels)f(of)h(the)g -(image.)64 b(This)36 b(robust)h(algorithm)i(\(written)f(b)m(y)f(Ric)m -(hard)h(White,)227 3096 y(STScI\))e(\014rst)f(attempts)i(to)g(estimate) -h(the)f(RMS)e(v)-5 b(alue)37 b(as)g(1.68)g(times)g(the)f(median)g(of)h -(the)f(absolute)227 3209 y(di\013erences)26 b(b)s(et)m(w)m(een)h -(successiv)m(e)g(pixels)f(in)g(the)g(image.)41 b(If)25 -b(the)h(median)g(=)f(0,)j(then)d(the)h(algorithm)h(falls)227 -3322 y(bac)m(k)h(to)f(computing)g(the)g(RMS)f(of)h(the)g(di\013erence)g -(b)s(et)m(w)m(een)h(successiv)m(e)g(pixels,)f(after)h(sev)m(eral)g -(N-sigma)227 3435 y(rejection)e(cycles)g(to)g(remo)m(v)m(e)g(extreme)g -(v)-5 b(alues.)39 b(The)25 b(input)e(parameters)j(are:)38 -b(the)25 b(arra)m(y)g(of)g(image)i(pixel)227 3548 y(v)-5 -b(alues)30 b(\(either)h(\015oat)f(or)g(short)f(v)-5 b(alues\),)31 -b(the)f(n)m(um)m(b)s(er)e(of)i(v)-5 b(alues)30 b(in)g(the)g(arra)m(y)-8 -b(,)31 b(the)f(v)-5 b(alue)30 b(that)g(is)g(used)227 -3661 y(to)h(represen)m(t)g(n)m(ull)f(pixels)h(\(en)m(ter)g(a)g(v)m(ery) -g(large)g(n)m(um)m(b)s(er)e(if)h(there)h(are)g(no)f(n)m(ull)g -(pixels\).)191 3920 y Fe(int)47 b(fits_rms_float)d(\(float)i(fdata[],)f -(int)i(npix,)g(float)f(in_null_value,)907 4033 y(>)h(double)f(*rms,)h -(int)g(*status\))191 4146 y(int)g(fits_rms_short)d(\(short)i(fdata[],)f -(int)i(npix,)g(short)f(in_null_value,)907 4259 y(>)h(double)f(*rms,)h -(int)g(*status\))0 4519 y Fi(26)f Fj(W)-8 b(as)33 b(CFITSIO)d(compiled) -h(with)h(the)f(-D)p 1612 4519 28 4 v 34 w(REENTRANT)g(directiv)m(e)i -(so)e(that)h(it)g(ma)m(y)h(b)s(e)d(safely)j(used)d(in)227 -4632 y(m)m(ulti-threaded)d(en)m(vironmen)m(ts?)40 b(The)26 -b(follo)m(wing)i(function)e(returns)f(1)i(if)f(y)m(es,)i(0)f(if)f(no.) -40 b(Note,)28 b(ho)m(w)m(ev)m(er,)227 4745 y(that)35 -b(ev)m(en)g(if)g(the)f(-D)p 991 4745 V 34 w(REENTRANT)f(directiv)m(e)j -(w)m(as)f(sp)s(eci\014ed,)g(this)f(do)s(es)g(not)h(guaran)m(tee)h(that) -f(the)227 4858 y(CFITSIO)29 b(routines)h(are)h(thread-safe,)g(b)s -(ecause)g(some)f(compilers)h(ma)m(y)g(not)g(supp)s(ort)d(this)j -(feature.)0 5117 y Fe(int)47 b(fits_is_reentrant\(void\))p -eop end -%%Page: 76 84 -TeXDict begin 76 83 bop 0 299 a Fj(76)1379 b Fh(CHAPTER)30 -b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)p eop end -%%Page: 77 85 -TeXDict begin 77 84 bop 0 1225 a Fg(Chapter)65 b(6)0 -1687 y Fm(The)77 b(CFITSIO)f(Iterator)i(F)-19 b(unction)0 -2180 y Fj(The)41 b(\014ts)p 325 2180 28 4 v 33 w(iterate)p -614 2180 V 34 w(data)i(function)e(in)h(CFITSIO)e(pro)m(vides)i(a)g -(unique)e(metho)s(d)i(of)g(executing)h(an)e(arbitrary)0 -2293 y(user-supplied)35 b(`w)m(ork')i(function)f(that)h(op)s(erates)g -(on)g(ro)m(ws)f(of)h(data)g(in)f(FITS)g(tables)h(or)f(on)h(pixels)f(in) -h(FITS)0 2406 y(images.)i(Rather)24 b(than)e(explicitly)j(reading)e -(and)g(writing)g(the)g(FITS)g(images)h(or)f(columns)g(of)g(data,)i(one) -f(instead)0 2518 y(calls)36 b(the)g(CFITSIO)d(iterator)k(routine,)g -(passing)e(to)h(it)g(the)f(name)g(of)h(the)f(user's)g(w)m(ork)g -(function)g(that)h(is)f(to)0 2631 y(b)s(e)30 b(executed)h(along)g(with) -f(a)h(list)g(of)f(all)h(the)f(table)i(columns)e(or)g(image)h(arra)m(ys) -g(that)g(are)f(to)h(b)s(e)f(passed)g(to)h(the)0 2744 -y(w)m(ork)37 b(function.)61 b(The)37 b(CFITSIO)e(iterator)k(function)e -(then)g(do)s(es)g(all)h(the)f(w)m(ork)g(of)h(allo)s(cating)h(memory)e -(for)0 2857 y(the)28 b(arra)m(ys,)h(reading)f(the)g(input)e(data)j -(from)e(the)h(FITS)f(\014le,)h(passing)g(them)g(to)g(the)g(w)m(ork)g -(function,)g(and)f(then)0 2970 y(writing)36 b(an)m(y)h(output)f(data)h -(bac)m(k)h(to)f(the)f(FITS)g(\014le)g(after)h(the)g(w)m(ork)g(function) -f(exits.)59 b(Because)38 b(it)f(is)g(often)0 3083 y(more)g(e\016cien)m -(t)i(to)f(pro)s(cess)f(only)g(a)h(subset)f(of)g(the)g(total)i(table)g -(ro)m(ws)e(at)h(one)f(time,)j(the)e(iterator)g(function)0 -3196 y(can)31 b(determine)f(the)h(optim)m(um)f(amoun)m(t)h(of)f(data)h -(to)g(pass)f(in)g(eac)m(h)i(iteration)f(and)f(rep)s(eatedly)h(call)g -(the)g(w)m(ork)0 3309 y(function)f(un)m(til)h(the)f(en)m(tire)i(table)f -(b)s(een)e(pro)s(cessed.)0 3469 y(F)-8 b(or)37 b(man)m(y)f -(applications)h(this)e(single)i(CFITSIO)d(iterator)k(function)d(can)h -(e\013ectiv)m(ely)j(replace)e(all)g(the)f(other)0 3582 -y(CFITSIO)g(routines)i(for)f(reading)h(or)f(writing)h(data)g(in)f(FITS) -g(images)i(or)e(tables.)64 b(Using)37 b(the)h(iterator)h(has)0 -3695 y(sev)m(eral)32 b(imp)s(ortan)m(t)e(adv)-5 b(an)m(tages)32 -b(o)m(v)m(er)g(the)f(traditional)g(metho)s(d)f(of)h(reading)f(and)g -(writing)g(FITS)g(data)h(\014les:)136 3961 y Fc(\017)46 -b Fj(It)33 b(cleanly)h(separates)g(the)f(data)h(I/O)f(from)f(the)h -(routine)g(that)h(op)s(erates)f(on)g(the)g(data.)49 b(This)32 -b(leads)h(to)227 4074 y(a)e(more)g(mo)s(dular)e(and)h(`ob)5 -b(ject)31 b(orien)m(ted')h(programming)e(st)m(yle.)136 -4268 y Fc(\017)46 b Fj(It)27 b(simpli\014es)f(the)h(application)h -(program)f(b)m(y)f(eliminating)i(the)f(need)g(to)g(allo)s(cate)i -(memory)e(for)f(the)h(data)227 4381 y(arra)m(ys)e(and)f(eliminates)i -(most)e(of)h(the)f(calls)i(to)f(the)g(CFITSIO)d(routines)j(that)g -(explicitly)h(read)e(and)g(write)227 4494 y(the)31 b(data.)136 -4689 y Fc(\017)46 b Fj(It)32 b(ensures)e(that)i(the)g(data)g(are)g(pro) -s(cessed)f(as)h(e\016cien)m(tly)h(as)e(p)s(ossible.)44 -b(This)31 b(is)g(esp)s(ecially)i(imp)s(ortan)m(t)227 -4801 y(when)44 b(pro)s(cessing)g(tabular)h(data)h(since)f(the)g -(iterator)h(function)e(will)h(calculate)i(the)e(most)g(e\016cien)m(t) -227 4914 y(n)m(um)m(b)s(er)36 b(of)i(ro)m(ws)g(in)f(the)h(table)g(to)g -(b)s(e)f(passed)g(at)i(one)e(time)i(to)f(the)g(user's)e(w)m(ork)i -(function)f(on)h(eac)m(h)227 5027 y(iteration.)136 5222 -y Fc(\017)46 b Fj(Mak)m(es)39 b(it)e(p)s(ossible)g(for)g(larger)h(pro)5 -b(jects)37 b(to)h(dev)m(elop)g(a)g(library)e(of)i(w)m(ork)f(functions)f -(that)i(all)g(ha)m(v)m(e)h(a)227 5335 y(uniform)29 b(calling)j -(sequence)f(and)f(are)h(all)g(indep)s(enden)m(t)e(of)i(the)f(details)i -(of)e(the)h(FITS)e(\014le)i(format.)0 5601 y(There)f(are)h(basically)h -(2)g(steps)e(in)h(using)f(the)h(CFITSIO)e(iterator)j(function.)42 -b(The)30 b(\014rst)g(step)h(is)g(to)g(design)g(the)0 -5714 y(w)m(ork)26 b(function)f(itself)h(whic)m(h)f(m)m(ust)h(ha)m(v)m -(e)g(a)g(prescrib)s(ed)e(set)i(of)g(input)f(parameters.)39 -b(One)25 b(of)h(these)g(parameters)1905 5942 y(77)p eop -end -%%Page: 78 86 -TeXDict begin 78 85 bop 0 299 a Fj(78)1455 b Fh(CHAPTER)30 -b(6.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)0 -555 y Fj(is)f(a)g(structure)g(con)m(taining)i(p)s(oin)m(ters)d(to)i -(the)f(arra)m(ys)h(of)f(data;)h(the)f(w)m(ork)h(function)e(can)i(p)s -(erform)d(an)m(y)i(desired)0 668 y(op)s(erations)k(on)h(these)f(arra)m -(ys)h(and)e(do)s(es)h(not)g(need)g(to)h(w)m(orry)f(ab)s(out)g(ho)m(w)g -(the)h(input)e(data)i(w)m(ere)f(read)g(from)0 781 y(the)e(\014le)f(or)g -(ho)m(w)h(the)f(output)g(data)h(get)h(written)e(bac)m(k)h(to)h(the)e -(\014le.)0 941 y(The)24 b(second)h(step)g(is)f(to)i(design)e(the)h -(driv)m(er)g(routine)f(that)i(op)s(ens)e(all)h(the)g(necessary)g(FITS)f -(\014les)h(and)f(initializes)0 1054 y(the)41 b(input)g(parameters)g(to) -h(the)g(iterator)g(function.)73 b(The)41 b(driv)m(er)g(program)g(calls) -h(the)g(CFITSIO)e(iterator)0 1167 y(function)30 b(whic)m(h)g(then)g -(reads)g(the)h(data)g(and)f(passes)g(it)h(to)g(the)g(user's)e(w)m(ork)i -(function.)0 1327 y(The)20 b(follo)m(wing)i(2)f(sections)g(describ)s(e) -f(these)h(steps)g(in)f(more)g(detail.)39 b(There)20 b(are)h(also)g(sev) -m(eral)h(example)f(programs)0 1440 y(included)30 b(with)g(the)g -(CFITSIO)f(distribution)h(whic)m(h)g(illustrate)i(ho)m(w)e(to)h(use)f -(the)h(iterator)g(function.)0 1789 y Ff(6.1)135 b(The)45 -b(Iterator)h(W)-11 b(ork)45 b(F)-11 b(unction)0 2043 -y Fj(The)42 b(user-supplied)f(iterator)j(w)m(ork)f(function)f(m)m(ust)g -(ha)m(v)m(e)i(the)f(follo)m(wing)h(set)f(of)g(input)e(parameters)i -(\(the)0 2156 y(function)30 b(can)h(b)s(e)e(giv)m(en)j(an)m(y)f -(desired)e(name\):)95 2429 y Fe(int)47 b(user_fn\()f(long)h(totaln,)e -(long)i(offset,)f(long)g(firstn,)g(long)h(nvalues,)716 -2542 y(int)g(narrays,)e(iteratorCol)g(*data,)94 b(void)47 -b(*userPointer)d(\))136 2815 y Fc(\017)i Fj(totaln)24 -b({)f(the)f(total)j(n)m(um)m(b)s(er)c(of)h(table)i(ro)m(ws)e(or)g -(image)i(pixels)f(that)g(will)f(b)s(e)g(passed)g(to)h(the)g(w)m(ork)f -(function)227 2928 y(during)29 b(1)i(or)g(more)f(iterations.)136 -3129 y Fc(\017)46 b Fj(o\013set)d({)f(the)h(o\013set)f(applied)g(to)h -(the)f(\014rst)f(table)i(ro)m(w)f(or)g(image)h(pixel)f(to)h(b)s(e)e -(passed)g(to)i(the)f(w)m(ork)227 3241 y(function.)55 -b(In)34 b(other)i(w)m(ords,)g(this)f(is)g(the)g(n)m(um)m(b)s(er)f(of)h -(ro)m(ws)h(or)f(pixels)g(that)h(are)f(skipp)s(ed)f(o)m(v)m(er)i(b)s -(efore)227 3354 y(starting)30 b(the)g(iterations.)42 -b(If)28 b(o\013set)j(=)e(0,)h(then)f(all)h(the)f(table)i(ro)m(ws)e(or)g -(image)i(pixels)e(will)h(b)s(e)e(passed)h(to)227 3467 -y(the)i(w)m(ork)f(function.)136 3668 y Fc(\017)46 b Fj(\014rstn)26 -b({)i(the)f(n)m(um)m(b)s(er)f(of)i(the)f(\014rst)g(table)h(ro)m(w)f(or) -g(image)i(pixel)e(\(starting)i(with)e(1\))h(that)f(is)h(b)s(eing)e -(passed)227 3781 y(in)k(this)h(particular)f(call)i(to)f(the)g(w)m(ork)f -(function.)136 3982 y Fc(\017)46 b Fj(n)m(v)-5 b(alues)35 -b({)g(the)f(n)m(um)m(b)s(er)g(of)g(table)h(ro)m(ws)g(or)f(image)i -(pixels)e(that)h(are)g(b)s(eing)f(passed)g(in)g(this)h(particular)227 -4095 y(call)h(to)g(the)f(w)m(ork)f(function.)54 b(n)m(v)-5 -b(alues)35 b(will)g(alw)m(a)m(ys)h(b)s(e)e(less)h(than)f(or)h(equal)g -(to)h(totaln)g(and)e(will)h(ha)m(v)m(e)227 4208 y(the)f(same)f(v)-5 -b(alue)34 b(on)f(eac)m(h)h(iteration,)i(except)e(p)s(ossibly)f(on)g -(the)g(last)h(call)h(whic)m(h)e(ma)m(y)g(ha)m(v)m(e)i(a)e(smaller)227 -4321 y(v)-5 b(alue.)136 4522 y Fc(\017)46 b Fj(narra)m(ys)31 -b({)g(the)g(n)m(um)m(b)s(er)f(of)h(arra)m(ys)g(of)g(data)h(that)f(are)g -(b)s(eing)g(passed)f(to)i(the)f(w)m(ork)g(function.)42 -b(There)30 b(is)227 4635 y(one)h(arra)m(y)g(for)f(eac)m(h)i(image)f(or) -f(table)i(column.)136 4835 y Fc(\017)46 b Fj(*data)31 -b({)e(arra)m(y)h(of)f(structures,)g(one)h(for)f(eac)m(h)h(column)f(or)g -(image.)42 b(Eac)m(h)29 b(structure)g(con)m(tains)h(a)g(p)s(oin)m(ter) -227 4948 y(to)h(the)g(arra)m(y)g(of)f(data)h(as)g(w)m(ell)g(as)g(other) -g(descriptiv)m(e)g(parameters)g(ab)s(out)f(that)h(arra)m(y)-8 -b(.)136 5149 y Fc(\017)46 b Fj(*userP)m(oin)m(ter)26 -b({)g(a)f(user)f(supplied)g(p)s(oin)m(ter)h(that)h(can)f(b)s(e)f(used)h -(to)g(pass)g(ancillary)h(information)f(from)g(the)227 -5262 y(driv)m(er)h(function)g(to)g(the)g(w)m(ork)g(function.)39 -b(This)25 b(p)s(oin)m(ter)h(is)g(passed)g(to)g(the)h(CFITSIO)d -(iterator)j(function)227 5375 y(whic)m(h)37 b(then)f(passes)g(it)h(on)g -(to)g(the)f(w)m(ork)h(function)f(without)h(an)m(y)g(mo)s(di\014cation.) -59 b(It)37 b(ma)m(y)g(p)s(oin)m(t)f(to)i(a)227 5488 y(single)29 -b(n)m(um)m(b)s(er,)f(to)h(an)f(arra)m(y)h(of)g(v)-5 b(alues,)29 -b(to)g(a)g(structure)f(con)m(taining)i(an)e(arbitrary)g(set)h(of)g -(parameters)227 5601 y(of)e(di\013eren)m(t)h(t)m(yp)s(es,)g(or)f(it)h -(ma)m(y)f(b)s(e)g(a)g(n)m(ull)g(p)s(oin)m(ter)g(if)g(it)h(is)f(not)g -(needed.)40 b(The)26 b(w)m(ork)h(function)g(m)m(ust)g(cast)227 -5714 y(this)k(p)s(oin)m(ter)f(to)h(the)g(appropriate)f(data)h(t)m(yp)s -(e)g(b)s(efore)f(using)f(it)i(it.)p eop end -%%Page: 79 87 -TeXDict begin 79 86 bop 0 299 a Fh(6.1.)72 b(THE)30 b(ITERA)-8 -b(TOR)30 b(W)m(ORK)g(FUNCTION)2021 b Fj(79)0 555 y(The)23 -b(totaln,)k(o\013set,)g(narra)m(ys,)e(data,)h(and)d(userP)m(oin)m(ter)i -(parameters)f(are)g(guaran)m(teed)h(to)g(ha)m(v)m(e)g(the)f(same)g(v)-5 -b(alue)0 668 y(on)35 b(eac)m(h)i(iteration.)57 b(Only)34 -b(\014rstn,)i(n)m(v)-5 b(alues,)37 b(and)d(the)i(arra)m(ys)f(of)h(data) -g(p)s(oin)m(ted)f(to)h(b)m(y)f(the)h(data)g(structures)0 -781 y(ma)m(y)31 b(c)m(hange)g(on)g(eac)m(h)g(iterativ)m(e)i(call)f(to)f -(the)f(w)m(ork)h(function.)0 941 y(Note)43 b(that)g(the)f(iterator)h -(treats)g(an)f(image)h(as)f(a)g(long)h(1-D)g(arra)m(y)f(of)h(pixels)f -(regardless)g(of)g(it's)h(in)m(trinsic)0 1054 y(dimensionalit)m(y)-8 -b(.)52 b(The)33 b(total)j(n)m(um)m(b)s(er)c(of)i(pixels)g(is)g(just)f -(the)h(pro)s(duct)e(of)i(the)g(size)h(of)e(eac)m(h)i(dimension,)g(and)0 -1167 y(the)e(order)g(of)g(the)g(pixels)g(is)g(the)g(same)g(as)g(the)h -(order)e(that)h(they)h(are)f(stored)g(in)g(the)g(FITS)f(\014le.)48 -b(If)33 b(the)g(w)m(ork)0 1280 y(function)27 b(needs)g(to)h(kno)m(w)f -(the)h(n)m(um)m(b)s(er)e(and)h(size)h(of)g(the)f(image)i(dimensions)d -(then)h(these)h(parameters)g(can)g(b)s(e)0 1393 y(passed)i(via)h(the)f -(userP)m(oin)m(ter)i(structure.)0 1553 y(The)e(iteratorCol)i(structure) -e(is)g(curren)m(tly)h(de\014ned)e(as)h(follo)m(ws:)0 -1780 y Fe(typedef)46 b(struct)94 b(/*)47 b(structure)e(for)i(the)g -(iterator)e(function)h(column)g(information)f(*/)0 1893 -y({)143 2005 y(/*)i(structure)f(elements)f(required)h(as)h(input)f(to)h -(fits_iterate_data:)c(*/)95 2231 y(fitsfile)j(*fptr;)332 -b(/*)48 b(pointer)d(to)j(the)f(HDU)f(containing)f(the)i(column)f(or)i -(image)e(*/)95 2344 y(int)286 b(colnum;)e(/*)48 b(column)e(number)g(in) -h(the)g(table;)f(ignored)g(for)h(images)189 b(*/)95 2457 -y(char)238 b(colname[70];)44 b(/*)k(name)e(\(TTYPEn\))g(of)h(the)g -(column;)f(null)g(for)h(images)285 b(*/)95 2570 y(int)h(datatype;)188 -b(/*)48 b(output)e(data)g(type)h(\(converted)e(if)i(necessary\))e(*/)95 -2683 y(int)286 b(iotype;)e(/*)48 b(type:)e(InputCol,)f(InputOutputCol,) -f(or)j(OutputCol)e(*/)95 2909 y(/*)j(output)e(structure)f(elements)h -(that)g(may)h(be)g(useful)f(for)h(the)g(work)g(function:)e(*/)95 -3135 y(void)238 b(*array;)189 b(/*)47 b(pointer)f(to)h(the)g(array)f -(\(and)h(the)g(null)g(value\))f(*/)95 3247 y(long)238 -b(repeat;)189 b(/*)47 b(binary)f(table)h(vector)f(repeat)g(value;)g -(set)238 b(*/)1050 3360 y(/*)g(equal)46 b(to)i(1)f(for)g(images)810 -b(*/)95 3473 y(long)238 b(tlmin;)f(/*)47 b(legal)g(minimum)e(data)i -(value,)f(if)h(any)477 b(*/)95 3586 y(long)238 b(tlmax;)f(/*)47 -b(legal)g(maximum)e(data)i(value,)f(if)h(any)477 b(*/)95 -3699 y(char)238 b(unit[70];)93 b(/*)47 b(physical)f(unit)g(string)g -(\(BUNIT)h(or)g(TUNITn\))189 b(*/)95 3812 y(char)238 -b(tdisp[70];)45 b(/*)i(suggested)e(display)h(format;)g(null)h(if)g -(none)190 b(*/)0 4038 y(})47 b(iteratorCol;)0 4264 y -Fj(Instead)34 b(of)g(directly)g(reading)g(or)g(writing)g(the)f(elemen)m -(ts)j(in)d(this)h(structure,)g(it)h(is)e(recommended)h(that)g(pro-)0 -4377 y(grammers)c(use)g(the)h(access)h(functions)d(that)i(are)g(pro)m -(vided)f(for)g(this)h(purp)s(ose.)0 4538 y(The)25 b(\014rst)g(\014v)m -(e)h(elemen)m(ts)h(in)f(this)f(structure)h(m)m(ust)f(b)s(e)g(initially) -j(de\014ned)c(b)m(y)i(the)g(driv)m(er)f(routine)h(b)s(efore)f(calling)0 -4650 y(the)f(iterator)h(routine.)38 b(The)23 b(CFITSIO)f(iterator)j -(routine)f(uses)f(this)g(information)h(to)g(determine)g(what)f(column)0 -4763 y(or)32 b(arra)m(y)h(to)h(pass)e(to)h(the)g(w)m(ork)f(function,)h -(and)f(whether)g(the)g(arra)m(y)h(is)g(to)g(b)s(e)f(input)g(to)h(the)f -(w)m(ork)h(function,)0 4876 y(output)g(from)g(the)h(w)m(ork)f -(function,)h(or)g(b)s(oth.)49 b(The)33 b(CFITSIO)f(iterator)i(function) -f(\014lls)h(in)f(the)g(v)-5 b(alues)34 b(of)g(the)0 4989 -y(remaining)c(structure)g(elemen)m(ts)i(b)s(efore)e(passing)g(it)h(to)g -(the)g(w)m(ork)f(function.)0 5149 y(The)d(arra)m(y)g(structure)g -(elemen)m(t)i(is)e(a)g(p)s(oin)m(ter)g(to)h(the)g(actual)g(data)g(arra) -m(y)g(and)e(it)i(m)m(ust)f(b)s(e)f(cast)j(to)e(the)h(correct)0 -5262 y(data)k(t)m(yp)s(e)f(b)s(efore)f(it)i(is)f(used.)41 -b(The)31 b(`rep)s(eat')g(structure)g(elemen)m(t)h(giv)m(e)g(the)g(n)m -(um)m(b)s(er)d(of)i(data)h(v)-5 b(alues)31 b(in)g(eac)m(h)0 -5375 y(ro)m(w)f(of)g(the)g(table,)i(so)e(that)h(the)f(total)i(n)m(um)m -(b)s(er)c(of)i(data)h(v)-5 b(alues)30 b(in)g(the)g(arra)m(y)h(is)f(giv) -m(en)h(b)m(y)f(rep)s(eat)g(*)g(n)m(v)-5 b(alues.)0 5488 -y(In)36 b(the)g(case)i(of)e(image)i(arra)m(ys)f(and)e(ASCI)s(I)g -(tables,)k(rep)s(eat)e(will)g(alw)m(a)m(ys)g(b)s(e)f(equal)h(to)g(1.)59 -b(When)37 b(the)f(data)0 5601 y(t)m(yp)s(e)k(is)f(a)h(c)m(haracter)h -(string,)h(the)e(arra)m(y)g(p)s(oin)m(ter)f(is)h(actually)h(a)f(p)s -(oin)m(ter)f(to)i(an)e(arra)m(y)h(of)g(string)f(p)s(oin)m(ters)0 -5714 y(\(i.e.,)31 b(c)m(har)e(**arra)m(y\).)42 b(The)29 -b(other)g(output)g(structure)f(elemen)m(ts)j(are)e(pro)m(vided)g(for)f -(con)m(v)m(enience)k(in)c(case)i(that)p eop end -%%Page: 80 88 -TeXDict begin 80 87 bop 0 299 a Fj(80)1455 b Fh(CHAPTER)30 -b(6.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)0 -555 y Fj(information)36 b(is)g(needed)f(within)g(the)h(w)m(ork)g -(function.)56 b(An)m(y)35 b(other)h(information)g(ma)m(y)g(b)s(e)f -(passed)h(from)f(the)0 668 y(driv)m(er)30 b(routine)h(to)g(the)f(w)m -(ork)h(function)f(via)h(the)f(userP)m(oin)m(ter)h(parameter.)0 -828 y(Up)s(on)g(completion,)j(the)e(w)m(ork)h(routine)f(m)m(ust)g -(return)f(an)h(in)m(teger)h(status)f(v)-5 b(alue,)34 -b(with)d(0)i(indicating)g(success)0 941 y(and)e(an)m(y)g(other)g(v)-5 -b(alue)32 b(indicating)g(an)f(error)g(whic)m(h)g(will)g(cause)h(the)f -(iterator)i(function)e(to)h(immediately)g(exit)0 1054 -y(at)27 b(that)f(p)s(oin)m(t.)39 b(Return)25 b(status)i(v)-5 -b(alues)26 b(in)f(the)h(range)h(1)f({)g(1000)i(should)c(b)s(e)i(a)m(v)m -(oided)h(since)f(these)h(are)f(reserv)m(ed)0 1167 y(for)d(use)g(b)m(y)h -(CFITSIO.)e(A)i(return)e(status)i(v)-5 b(alue)24 b(of)g(-1)g(ma)m(y)g -(b)s(e)f(used)f(to)j(force)f(the)f(CFITSIO)f(iterator)j(function)0 -1280 y(to)i(stop)g(at)g(that)h(p)s(oin)m(t)e(and)g(return)g(con)m(trol) -i(to)f(the)g(driv)m(er)f(routine)h(after)g(writing)f(an)m(y)h(output)f -(arra)m(ys)h(to)h(the)0 1393 y(FITS)e(\014le.)40 b(CFITSIO)26 -b(do)s(es)g(not)i(considered)f(this)g(to)h(b)s(e)e(an)h(error)g -(condition,)i(so)e(an)m(y)g(further)f(pro)s(cessing)h(b)m(y)0 -1506 y(the)k(application)g(program)f(will)h(con)m(tin)m(ue)h(normally) --8 b(.)0 1837 y Ff(6.2)135 b(The)45 b(Iterator)h(Driv)l(er)g(F)-11 -b(unction)0 2087 y Fj(The)33 b(iterator)h(driv)m(er)f(function)g(m)m -(ust)h(op)s(en)e(the)i(necessary)f(FITS)g(\014les)g(and)g(p)s(osition)g -(them)g(to)h(the)g(correct)0 2200 y(HDU.)23 b(It)f(m)m(ust)g(also)i -(initialize)g(the)e(follo)m(wing)i(parameters)e(in)g(the)h(iteratorCol) -h(structure)d(\(de\014ned)g(ab)s(o)m(v)m(e\))j(for)0 -2313 y(eac)m(h)31 b(column)f(or)g(image)h(b)s(efore)e(calling)j(the)e -(CFITSIO)e(iterator)j(function.)40 b(Sev)m(eral)31 b(`constructor')g -(routines)0 2426 y(are)g(pro)m(vided)f(in)g(CFITSIO)f(for)h(this)g -(purp)s(ose.)136 2670 y Fc(\017)46 b Fj(*fptr)30 b({)h(The)f -(\014ts\014le)g(p)s(oin)m(ter)g(to)i(the)e(table)h(or)g(image.)136 -2853 y Fc(\017)46 b Fj(coln)m(um)30 b({)f(the)h(n)m(um)m(b)s(er)e(of)h -(the)h(column)f(in)g(the)g(table.)42 b(This)28 b(v)-5 -b(alue)30 b(is)f(ignored)g(in)g(the)h(case)g(of)g(images.)227 -2966 y(If)j(coln)m(um)h(equals)g(0,)g(then)g(the)f(column)g(name)h -(will)f(b)s(e)g(used)g(to)h(iden)m(tify)g(the)f(column)h(to)g(b)s(e)e -(passed)227 3079 y(to)f(the)g(w)m(ork)f(function.)136 -3261 y Fc(\017)46 b Fj(colname)32 b({)e(the)g(name)h(\(TTYPEn)e(k)m -(eyw)m(ord\))i(of)f(the)h(column.)40 b(This)29 b(is)i(only)f(required)f -(if)h(coln)m(um)h(=)f(0)227 3374 y(and)g(is)g(ignored)h(for)f(images.) -136 3556 y Fc(\017)46 b Fj(datat)m(yp)s(e)29 b({)g(The)e(desired)h -(data)g(t)m(yp)s(e)g(of)h(the)f(arra)m(y)g(to)h(b)s(e)e(passed)h(to)h -(the)f(w)m(ork)g(function.)40 b(F)-8 b(or)28 b(n)m(umer-)227 -3669 y(ical)h(data)f(the)f(data)h(t)m(yp)s(e)g(do)s(es)f(not)g(need)g -(to)h(b)s(e)f(the)g(same)h(as)f(the)h(actual)g(data)g(t)m(yp)s(e)g(in)f -(the)g(FITS)g(\014le,)227 3782 y(in)h(whic)m(h)h(case)g(CFITSIO)e(will) -i(do)g(the)f(con)m(v)m(ersion.)42 b(Allo)m(w)m(ed)30 -b(v)-5 b(alues)29 b(are:)40 b(TSTRING,)28 b(TLOGICAL,)227 -3895 y(TBYTE,)37 b(TSBYTE,)f(TSHOR)-8 b(T,)36 b(TUSHOR)-8 -b(T,)37 b(TINT,)f(TLONG,)h(TULONG,)f(TFLO)m(A)-8 b(T,)38 -b(TDOU-)227 4008 y(BLE.)33 b(If)g(the)g(input)f(v)-5 -b(alue)33 b(of)g(data)h(t)m(yp)s(e)f(equals)g(0,)i(then)d(the)h -(existing)h(data)g(t)m(yp)s(e)f(of)g(the)g(column)g(or)227 -4121 y(image)f(will)f(b)s(e)e(used)h(without)g(an)m(y)h(con)m(v)m -(ersion.)136 4303 y Fc(\017)46 b Fj(iot)m(yp)s(e)37 b({)f(de\014nes)e -(whether)h(the)h(data)g(arra)m(y)g(is)g(to)g(b)s(e)f(input)g(to)h(the)g -(w)m(ork)f(function)h(\(i.e,)i(read)d(from)227 4416 y(the)42 -b(FITS)e(\014le\),)k(or)d(output)g(from)g(the)g(w)m(ork)g(function)g -(\(i.e.,)k(written)c(to)h(the)f(FITS)g(\014le\))g(or)g(b)s(oth.)227 -4529 y(Allo)m(w)m(ed)30 b(v)-5 b(alues)29 b(are)f(InputCol,)g -(OutputCol,)h(or)f(InputOutputCol.)38 b(V)-8 b(ariable-length)30 -b(arra)m(y)f(columns)227 4642 y(are)h(supp)s(orted)e(as)i(InputCol)e -(or)i(InputOutputCol)d(t)m(yp)s(es,)j(but)f(ma)m(y)h(not)g(b)s(e)e -(used)h(for)g(an)h(OutputCol)227 4755 y(t)m(yp)s(e.)0 -4999 y(After)h(the)f(driv)m(er)g(routine)g(has)g(initialized)j(all)e -(these)f(parameters,)h(it)g(can)g(then)f(call)h(the)g(CFITSIO)e -(iterator)0 5112 y(function:)95 5357 y Fe(int)47 b -(fits_iterate_data\(int)42 b(narrays,)k(iteratorCol)f(*data,)h(long)g -(offset,)286 5470 y(long)h(nPerLoop,)e(int)i(\(*workFn\)\()e(\),)i -(void)g(*userPointer,)d(int)j(*status\);)136 5714 y Fc(\017)f -Fj(narra)m(ys)31 b({)f(the)h(n)m(um)m(b)s(er)e(of)h(columns)g(or)h -(images)g(that)g(are)g(to)g(b)s(e)f(passed)g(to)h(the)f(w)m(ork)h -(function.)p eop end -%%Page: 81 89 -TeXDict begin 81 88 bop 0 299 a Fh(6.3.)72 b(GUIDELINES)30 -b(F)m(OR)h(USING)f(THE)g(ITERA)-8 b(TOR)30 b(FUNCTION)1200 -b Fj(81)136 555 y Fc(\017)46 b Fj(*data)32 b({)f(p)s(oin)m(ter)f(to)h -(arra)m(y)g(of)f(structures)g(con)m(taining)i(information)f(ab)s(out)f -(eac)m(h)h(column)g(or)f(image.)136 736 y Fc(\017)46 -b Fj(o\013set)31 b({)f(if)f(p)s(ositiv)m(e,)i(this)f(n)m(um)m(b)s(er)e -(of)i(ro)m(ws)f(at)h(the)g(b)s(eginning)f(of)h(the)f(table)i(\(or)f -(pixels)f(in)h(the)f(image\))227 849 y(will)i(b)s(e)f(skipp)s(ed)f(and) -g(will)i(not)g(b)s(e)e(passed)h(to)h(the)g(w)m(ork)f(function.)136 -1030 y Fc(\017)46 b Fj(nP)m(erLo)s(op)38 b(-)h(sp)s(eci\014es)e(the)i -(n)m(um)m(b)s(er)e(of)h(table)h(ro)m(ws)g(\(or)f(n)m(um)m(b)s(er)f(of)i -(image)g(pixels\))g(that)g(are)g(to)g(b)s(e)227 1143 -y(passed)29 b(to)h(the)f(w)m(ork)h(function)e(on)h(eac)m(h)i -(iteration.)42 b(If)28 b(nP)m(erLo)s(op)h(=)g(0)g(then)g(CFITSIO)f -(will)i(calculate)227 1256 y(the)22 b(optim)m(um)g(n)m(um)m(b)s(er)e -(for)h(greatest)j(e\016ciency)-8 b(.)39 b(If)21 b(nP)m(erLo)s(op)g(is)h -(negativ)m(e,)k(then)21 b(all)i(the)f(ro)m(ws)f(or)h(pixels)227 -1368 y(will)36 b(b)s(e)f(passed)g(at)h(one)g(time,)i(and)c(the)i(w)m -(ork)g(function)f(will)h(only)f(b)s(e)g(called)i(once.)56 -b(If)35 b(an)m(y)h(v)-5 b(ariable)227 1481 y(length)33 -b(arra)m(ys)g(are)g(b)s(eing)f(pro)s(cessed,)h(then)g(the)f(nP)m(erLo)s -(op)h(v)-5 b(alue)33 b(is)f(ignored,)i(and)e(the)h(iterator)h(will)227 -1594 y(alw)m(a)m(ys)e(pro)s(cess)e(one)h(ro)m(w)f(of)h(the)f(table)i -(at)f(a)g(time.)136 1775 y Fc(\017)46 b Fj(*w)m(orkFn)f(-)f(the)h(name) -f(\(actually)i(the)f(address\))f(of)g(the)g(w)m(ork)h(function)f(that)h -(is)f(to)h(b)s(e)f(called)h(b)m(y)227 1888 y(\014ts)p -354 1888 28 4 v 33 w(iterate)p 643 1888 V 34 w(data.)136 -2069 y Fc(\017)h Fj(*userP)m(oin)m(ter)34 b(-)f(this)g(is)g(a)g(user)f -(supplied)g(p)s(oin)m(ter)h(that)g(can)g(b)s(e)g(used)f(to)h(pass)g -(ancillary)h(information)227 2182 y(from)f(the)g(driv)m(er)g(routine)g -(to)h(the)f(w)m(ork)g(function.)48 b(It)33 b(ma)m(y)h(p)s(oin)m(t)f(to) -h(a)f(single)h(n)m(um)m(b)s(er,)e(an)h(arra)m(y)-8 b(,)35 -b(or)227 2295 y(to)c(a)g(structure)f(con)m(taining)i(an)e(arbitrary)g -(set)h(of)g(parameters.)136 2476 y Fc(\017)46 b Fj(*status)30 -b(-)f(The)f(CFITSIO)f(error)h(status.)41 b(Should)27 -b(=)h(0)h(on)g(input;)f(a)h(non-zero)h(output)e(v)-5 -b(alue)29 b(indicates)227 2588 y(an)i(error.)0 2828 y(When)f(\014ts)p -392 2828 V 32 w(iterate)p 680 2828 V 35 w(data)h(is)f(called)h(it)f -(\014rst)g(allo)s(cates)i(memory)e(to)h(hold)e(all)i(the)f(requested)g -(columns)g(of)g(data)0 2941 y(or)f(image)i(pixel)e(arra)m(ys.)41 -b(It)29 b(then)g(reads)g(the)h(input)e(data)i(from)f(the)g(FITS)f -(tables)i(or)g(images)g(in)m(to)g(the)g(arra)m(ys)0 3054 -y(then)h(passes)h(the)g(structure)f(with)g(p)s(oin)m(ters)h(to)g(these) -g(data)h(arra)m(ys)f(to)g(the)g(w)m(ork)g(function.)44 -b(After)32 b(the)g(w)m(ork)0 3167 y(function)37 b(returns,)g(the)h -(iterator)g(function)f(writes)g(an)m(y)g(output)g(columns)f(of)h(data)h -(or)f(images)h(bac)m(k)g(to)g(the)0 3279 y(FITS)31 b(\014les.)46 -b(It)32 b(then)g(rep)s(eats)g(this)g(pro)s(cess)g(for)f(an)m(y)i -(remaining)f(sets)g(of)h(ro)m(ws)f(or)g(image)h(pixels)f(un)m(til)h(it) -f(has)0 3392 y(pro)s(cessed)27 b(the)i(en)m(tire)g(table)f(or)g(image)i -(or)e(un)m(til)g(the)g(w)m(ork)g(function)g(returns)f(a)h(non-zero)h -(status)f(v)-5 b(alue.)40 b(The)0 3505 y(iterator)33 -b(then)f(frees)g(the)h(memory)e(that)i(it)g(initially)g(allo)s(cated)h -(and)e(returns)f(con)m(trol)i(to)g(the)f(driv)m(er)g(routine)0 -3618 y(that)f(called)h(it.)0 3949 y Ff(6.3)135 b(Guidelines)46 -b(for)f(Using)h(the)f(Iterator)h(F)-11 b(unction)0 4199 -y Fj(The)34 b(totaln,)i(o\013set,)h(\014rstn,)d(and)f(n)m(v)-5 -b(alues)35 b(parameters)f(that)h(are)f(passed)g(to)h(the)f(w)m(ork)g -(function)g(are)h(useful)0 4312 y(for)f(determining)g(ho)m(w)g(m)m(uc)m -(h)g(of)h(the)f(data)h(has)f(b)s(een)f(pro)s(cessed)h(and)f(ho)m(w)h(m) -m(uc)m(h)g(remains)g(left)h(to)g(do.)52 b(On)0 4425 y(the)36 -b(v)m(ery)h(\014rst)f(call)h(to)g(the)f(w)m(ork)h(function)f(\014rstn)f -(will)h(b)s(e)g(equal)h(to)g(o\013set)g(+)f(1;)k(the)c(w)m(ork)g -(function)g(ma)m(y)0 4538 y(need)31 b(to)g(p)s(erform)f(v)-5 -b(arious)31 b(initialization)i(tasks)f(b)s(efore)e(starting)i(to)f(pro) -s(cess)g(the)g(data.)43 b(Similarly)-8 b(,)32 b(\014rstn)d(+)0 -4650 y(n)m(v)-5 b(alues)29 b(-)f(1)h(will)f(b)s(e)g(equal)g(to)h -(totaln)h(on)e(the)g(last)h(iteration,)i(at)e(whic)m(h)f(p)s(oin)m(t)g -(the)g(w)m(ork)h(function)e(ma)m(y)i(need)0 4763 y(to)k(p)s(erform)f -(some)h(clean)h(up)d(op)s(erations)i(b)s(efore)g(exiting)h(for)e(the)h -(last)h(time.)48 b(The)33 b(w)m(ork)f(function)h(can)g(also)0 -4876 y(force)e(an)f(early)h(termination)g(of)g(the)g(iterations)g(b)m -(y)g(returning)e(a)i(status)g(v)-5 b(alue)30 b(=)g(-1.)0 -5036 y(The)f(narra)m(ys)g(and)g(iteratorCol.datat)m(yp)s(e)j(argumen)m -(ts)e(allo)m(w)g(the)g(w)m(ork)f(function)g(to)h(double)f(c)m(hec)m(k)i -(that)f(the)0 5149 y(n)m(um)m(b)s(er)k(of)i(input)f(arra)m(ys)h(and)f -(their)g(data)i(t)m(yp)s(es)e(ha)m(v)m(e)i(the)f(exp)s(ected)g(v)-5 -b(alues.)57 b(The)35 b(iteratorCol.fptr)i(and)0 5262 -y(iteratorCol.coln)m(um)d(structure)d(elemen)m(ts)h(can)g(b)s(e)f(used) -f(if)i(the)f(w)m(ork)h(function)f(needs)g(to)h(read)f(or)g(write)h(the) -0 5375 y(v)-5 b(alues)31 b(of)g(other)g(k)m(eyw)m(ords)g(in)g(the)g -(FITS)f(\014le)h(asso)s(ciated)h(with)f(the)g(arra)m(y)-8 -b(.)43 b(This)30 b(should)g(generally)i(only)f(b)s(e)0 -5488 y(done)j(during)e(the)i(initialization)j(step)c(or)h(during)f(the) -h(clean)g(up)f(step)h(after)g(the)g(last)h(set)f(of)g(data)g(has)g(b)s -(een)0 5601 y(pro)s(cessed.)40 b(Extra)29 b(FITS)f(\014le)h(I/O)g -(during)e(the)i(main)g(pro)s(cessing)g(lo)s(op)g(of)g(the)g(w)m(ork)g -(function)g(can)g(seriously)0 5714 y(degrade)i(the)f(sp)s(eed)g(of)g -(the)h(program.)p eop end -%%Page: 82 90 -TeXDict begin 82 89 bop 0 299 a Fj(82)1455 b Fh(CHAPTER)30 -b(6.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)0 -555 y Fj(If)i(v)-5 b(ariable-length)35 b(arra)m(y)e(columns)g(are)g(b)s -(eing)f(pro)s(cessed,)h(then)g(the)g(iterator)h(will)f(op)s(erate)h(on) -f(one)g(ro)m(w)g(of)0 668 y(the)j(table)g(at)g(a)g(time.)57 -b(In)34 b(this)i(case)g(the)g(the)f(rep)s(eat)h(elemen)m(t)h(in)e(the)h -(in)m(teratorCol)h(structure)e(will)h(b)s(e)e(set)0 781 -y(equal)d(to)g(the)g(n)m(um)m(b)s(er)e(of)h(elemen)m(ts)i(in)e(the)h -(curren)m(t)f(ro)m(w)g(that)h(is)g(b)s(eing)f(pro)s(cessed.)0 -941 y(One)j(imp)s(ortan)m(t)g(feature)h(of)f(the)h(iterator)h(is)e -(that)h(the)f(\014rst)g(elemen)m(t)i(in)e(eac)m(h)h(arra)m(y)g(that)g -(is)f(passed)g(to)h(the)0 1054 y(w)m(ork)f(function)g(giv)m(es)h(the)f -(v)-5 b(alue)33 b(that)h(is)f(used)f(to)h(represen)m(t)g(n)m(ull)g(or)g -(unde\014ned)d(v)-5 b(alues)34 b(in)e(the)h(arra)m(y)-8 -b(.)49 b(The)0 1167 y(real)41 b(data)g(then)g(b)s(egins)f(with)g(the)g -(second)h(elemen)m(t)h(of)f(the)f(arra)m(y)h(\(i.e.,)k(arra)m(y[1],)g -(not)c(arra)m(y[0]\).)73 b(If)40 b(the)0 1280 y(\014rst)e(arra)m(y)h -(elemen)m(t)h(is)f(equal)g(to)g(zero,)j(then)c(this)g(indicates)i(that) -f(all)h(the)e(arra)m(y)h(elemen)m(ts)h(ha)m(v)m(e)g(de\014ned)0 -1393 y(v)-5 b(alues)33 b(and)f(there)h(are)g(no)g(unde\014ned)d(v)-5 -b(alues.)48 b(If)33 b(arra)m(y[0])h(is)f(not)g(equal)g(to)g(zero,)i -(then)d(this)h(indicates)g(that)0 1506 y(some)h(of)g(the)g(data)h(v)-5 -b(alues)34 b(are)g(unde\014ned)d(and)j(this)f(v)-5 b(alue)35 -b(\(arra)m(y[0]\))h(is)d(used)g(to)i(represen)m(t)f(them.)51 -b(In)33 b(the)0 1619 y(case)i(of)e(output)g(arra)m(ys)h(\(i.e.,)i -(those)e(arra)m(ys)g(that)g(will)g(b)s(e)f(written)g(bac)m(k)h(to)h -(the)e(FITS)g(\014le)g(b)m(y)h(the)g(iterator)0 1732 -y(function)h(after)i(the)f(w)m(ork)f(function)h(exits\))h(the)f(w)m -(ork)g(function)f(m)m(ust)h(set)g(the)g(\014rst)f(arra)m(y)h(elemen)m -(t)h(to)g(the)0 1844 y(desired)g(n)m(ull)g(v)-5 b(alue)37 -b(if)g(necessary)-8 b(,)40 b(otherwise)e(the)f(\014rst)g(elemen)m(t)h -(should)e(b)s(e)h(set)g(to)h(zero)g(to)g(indicate)g(that)0 -1957 y(there)30 b(are)h(no)e(n)m(ull)h(v)-5 b(alues)31 -b(in)e(the)h(output)g(arra)m(y)-8 b(.)42 b(CFITSIO)28 -b(de\014nes)h(2)h(v)-5 b(alues,)31 b(FLO)m(A)-8 b(TNULL)e(V)g(ALUE)31 -b(and)0 2070 y(DOUBLENULL)-10 b(V)g(ALUE,)37 b(that)f(can)h(b)s(e)e -(used)g(as)i(default)f(n)m(ull)g(v)-5 b(alues)36 b(for)g(\015oat)h(and) -e(double)h(data)h(t)m(yp)s(es,)0 2183 y(resp)s(ectiv)m(ely)-8 -b(.)60 b(In)35 b(the)i(case)g(of)f(c)m(haracter)i(string)e(data)h(t)m -(yp)s(es,)h(a)e(n)m(ull)h(string)f(is)g(alw)m(a)m(ys)i(used)d(to)i -(represen)m(t)0 2296 y(unde\014ned)28 b(strings.)0 2456 -y(In)33 b(some)h(applications)g(it)g(ma)m(y)g(b)s(e)f(necessary)h(to)g -(recursiv)m(ely)g(call)h(the)f(iterator)h(function.)50 -b(An)33 b(example)h(of)0 2569 y(this)27 b(is)g(giv)m(en)h(b)m(y)f(one)h -(of)f(the)h(example)f(programs)g(that)h(is)f(distributed)f(with)h -(CFITSIO:)f(it)i(\014rst)e(calls)i(a)g(w)m(ork)0 2682 -y(function)38 b(that)g(writes)h(out)f(a)g(2D)h(histogram)g(image.)65 -b(That)38 b(w)m(ork)g(function)g(in)f(turn)g(calls)j(another)e(w)m(ork) -0 2795 y(function)29 b(that)h(reads)g(the)f(`X')i(and)e(`Y')h(columns)f -(in)g(a)h(table)h(to)f(calculate)i(the)d(v)-5 b(alue)31 -b(of)e(eac)m(h)i(2D)f(histogram)0 2908 y(image)i(pixel.)41 -b(Graphically)-8 b(,)32 b(the)e(program)g(structure)g(can)h(b)s(e)f -(describ)s(ed)f(as:)48 3153 y Fe(driver)46 b(-->)h(iterator)e(-->)i -(work1_fn)f(-->)h(iterator)e(-->)i(work2_fn)0 3399 y -Fj(Finally)-8 b(,)42 b(it)d(should)e(b)s(e)h(noted)g(that)h(the)g -(table)g(columns)f(or)g(image)i(arra)m(ys)f(that)g(are)f(passed)g(to)h -(the)g(w)m(ork)0 3512 y(function)c(do)h(not)g(all)g(ha)m(v)m(e)h(to)f -(come)h(from)e(the)h(same)g(FITS)f(\014le)g(and)g(instead)h(ma)m(y)g -(come)h(from)e(an)m(y)h(com-)0 3625 y(bination)d(of)g(sources)g(as)h -(long)f(as)h(they)f(ha)m(v)m(e)h(the)f(same)h(length.)49 -b(The)32 b(length)i(of)f(the)g(\014rst)f(table)i(column)f(or)0 -3738 y(image)f(arra)m(y)f(is)f(used)f(b)m(y)i(the)f(iterator)i(if)e -(they)h(do)f(not)h(all)g(ha)m(v)m(e)h(the)e(same)h(length.)0 -4069 y Ff(6.4)135 b(Complete)47 b(List)e(of)g(Iterator)i(Routines)0 -4319 y Fj(All)36 b(of)f(the)g(iterator)h(routines)f(are)g(listed)h(b)s -(elo)m(w.)54 b(Most)36 b(of)f(these)h(routines)e(do)h(not)g(ha)m(v)m(e) -i(a)e(corresp)s(onding)0 4432 y(short)30 b(function)g(name.)0 -4678 y Fi(1)81 b Fj(Iterator)32 b(`constructor')h(functions)e(that)i -(set)f(the)g(v)-5 b(alue)32 b(of)g(elemen)m(ts)h(in)f(the)g -(iteratorCol)h(structure)e(that)227 4791 y(de\014ne)k(the)h(columns)f -(or)h(arra)m(ys.)56 b(These)36 b(set)g(the)g(\014ts\014le)f(p)s(oin)m -(ter,)i(column)e(name,)j(column)d(n)m(um)m(b)s(er,)227 -4904 y(datat)m(yp)s(e,)28 b(and)e(iot)m(yp)s(e,)i(resp)s(ectiv)m(ely)-8 -b(.)41 b(The)25 b(last)i(2)g(routines)f(allo)m(w)h(all)g(the)f -(parameters)h(to)f(b)s(e)g(set)g(with)227 5017 y(one)31 -b(function)f(call)i(\(one)f(supplies)e(the)i(column)f(name,)h(the)f -(other)h(the)f(column)g(n)m(um)m(b)s(er\).)95 5262 y -Fe(int)47 b(fits_iter_set_file\(iterato)o(rCo)o(l)42 -b(*col,)k(fitsfile)g(*fptr\);)95 5488 y(int)h -(fits_iter_set_colname\(iter)o(ato)o(rCol)41 b(*col,)46 -b(char)h(*colname\);)95 5714 y(int)g(fits_iter_set_colnum\(itera)o(tor) -o(Col)41 b(*col,)47 b(int)g(colnum\);)p eop end -%%Page: 83 91 -TeXDict begin 83 90 bop 0 299 a Fh(6.4.)72 b(COMPLETE)29 -b(LIST)g(OF)i(ITERA)-8 b(TOR)29 b(R)m(OUTINES)1638 b -Fj(83)95 668 y Fe(int)47 b(fits_iter_set_datatype\(ite)o(rat)o(orCo)o -(l)42 b(*col,)k(int)h(datatype\);)95 894 y(int)g -(fits_iter_set_iotype\(itera)o(tor)o(Col)41 b(*col,)47 -b(int)g(iotype\);)95 1120 y(int)g(fits_iter_set_by_name\(iter)o(ato)o -(rCol)41 b(*col,)46 b(fitsfile)g(*fptr,)477 1233 y(char)h(*colname,)e -(int)i(datatype,)93 b(int)47 b(iotype\);)95 1458 y(int)g -(fits_iter_set_by_num\(itera)o(tor)o(Col)41 b(*col,)47 -b(fitsfile)e(*fptr,)477 1571 y(int)i(colnum,)f(int)h(datatype,)93 -b(int)47 b(iotype\);)0 1820 y Fi(2)81 b Fj(Iterator)38 -b(`accessor')h(functions)e(that)g(return)g(the)g(v)-5 -b(alue)38 b(of)f(the)g(elemen)m(t)i(in)e(the)g(iteratorCol)i(structure) -227 1933 y(that)31 b(describ)s(es)f(a)h(particular)f(data)h(column)g -(or)f(arra)m(y)95 2181 y Fe(fitsfile)46 b(*)h -(fits_iter_get_file\(iterato)o(rCol)41 b(*col\);)95 2407 -y(char)47 b(*)h(fits_iter_get_colname\(i)o(ter)o(ator)o(Col)41 -b(*col\);)95 2633 y(int)47 b(fits_iter_get_colnum\(itera)o(tor)o(Col)41 -b(*col\);)95 2858 y(int)47 b(fits_iter_get_datatype\(ite)o(rat)o(orCo)o -(l)42 b(*col\);)95 3084 y(int)47 b(fits_iter_get_iotype\(itera)o(tor)o -(Col)41 b(*col\);)95 3310 y(void)47 b(*)h(fits_iter_get_array\(ite)o -(rat)o(orCo)o(l)42 b(*col\);)95 3536 y(long)47 b -(fits_iter_get_tlmin\(itera)o(tor)o(Col)41 b(*col\);)95 -3762 y(long)47 b(fits_iter_get_tlmax\(itera)o(tor)o(Col)41 -b(*col\);)95 3987 y(long)47 b(fits_iter_get_repeat\(iter)o(ato)o(rCol) -41 b(*col\);)95 4213 y(char)47 b(*)h(fits_iter_get_tunit\(ite)o(rat)o -(orCo)o(l)42 b(*col\);)95 4439 y(char)47 b(*)h -(fits_iter_get_tdisp\(ite)o(rat)o(orCo)o(l)42 b(*col\);)0 -4687 y Fi(3)81 b Fj(The)29 b(CFITSIO)g(iterator)j(function)95 -4936 y Fe(int)47 b(fits_iterate_data\(int)42 b(narrays,)94 -b(iteratorCol)44 b(*data,)i(long)h(offset,)573 5049 y(long)f(nPerLoop,) -573 5161 y(int)h(\(*workFn\)\()e(long)h(totaln,)g(long)h(offset,)f -(long)g(firstn,)1289 5274 y(long)g(nvalues,)g(int)h(narrays,)e -(iteratorCol)g(*data,)1289 5387 y(void)h(*userPointer\),)573 -5500 y(void)g(*userPointer,)573 5613 y(int)h(*status\);)p -eop end -%%Page: 84 92 -TeXDict begin 84 91 bop 0 299 a Fj(84)1455 b Fh(CHAPTER)30 -b(6.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)p -eop end -%%Page: 85 93 -TeXDict begin 85 92 bop 0 1225 a Fg(Chapter)65 b(7)0 -1687 y Fm(W)-19 b(orld)77 b(Co)6 b(ordinate)78 b(System)f(Routines)0 -2180 y Fj(The)36 b(FITS)g(comm)m(unit)m(y)h(has)f(adopted)h(a)g(set)g -(of)g(k)m(eyw)m(ord)g(con)m(v)m(en)m(tions)h(that)f(de\014ne)f(the)h -(transformations)0 2293 y(needed)30 b(to)i(con)m(v)m(ert)g(b)s(et)m(w)m -(een)f(pixel)g(lo)s(cations)h(in)e(an)h(image)h(and)e(the)g(corresp)s -(onding)g(celestial)j(co)s(ordinates)0 2406 y(on)25 b(the)h(sky)-8 -b(,)27 b(or)e(more)g(generally)-8 b(,)29 b(that)d(de\014ne)e(w)m(orld)h -(co)s(ordinates)i(that)e(are)h(to)g(b)s(e)f(asso)s(ciated)i(with)e(an)m -(y)h(pixel)0 2518 y(lo)s(cation)h(in)e(an)h(n-dimensional)f(FITS)g -(arra)m(y)-8 b(.)40 b(CFITSIO)24 b(is)h(distributed)g(with)g(a)h(a)g -(few)f(self-con)m(tained)i(W)-8 b(orld)0 2631 y(Co)s(ordinate)30 -b(System)g(\(W)m(CS\))g(routines,)g(ho)m(w)m(ev)m(er,)i(these)e -(routines)g(DO)f(NOT)h(supp)s(ort)e(all)j(the)f(latest)h(W)m(CS)0 -2744 y(con)m(v)m(en)m(tions,)38 b(so)c(it)h(is)g(STR)m(ONGL)-8 -b(Y)34 b(RECOMMENDED)h(that)g(soft)m(w)m(are)h(dev)m(elop)s(ers)e(use)g -(a)h(more)g(robust)0 2857 y(external)c(W)m(CS)g(library)-8 -b(.)40 b(Sev)m(eral)32 b(recommended)e(libraries)g(are:)95 -3138 y Fe(WCSLIB)47 b(-)95 b(supported)45 b(by)i(Mark)g(Calabretta)95 -3251 y(WCSTools)f(-)h(supported)f(by)h(Doug)g(Mink)95 -3364 y(AST)g(library)f(-)i(developed)d(by)i(the)g(U.K.)g(Starlink)e -(project)0 3644 y Fj(More)30 b(information)f(ab)s(out)g(the)g(W)m(CS)g -(k)m(eyw)m(ord)h(con)m(v)m(en)m(tions)h(and)d(links)h(to)h(all)g(of)f -(these)g(W)m(CS)g(libraries)h(can)0 3757 y(b)s(e)g(found)f(on)h(the)h -(FITS)e(Supp)s(ort)g(O\016ce)h(w)m(eb)g(site)i(at)f(h)m -(ttp://\014ts.gsfc.nasa.go)m(v)j(under)29 b(the)h(W)m(CS)h(link.)0 -3917 y(The)40 b(functions)h(pro)m(vided)g(in)f(these)i(external)f(W)m -(CS)g(libraries)h(will)f(need)g(access)h(to)f(the)h(W)m(CS)f(k)m(eyw)m -(ords)0 4030 y(con)m(tained)36 b(in)f(the)h(FITS)e(\014le)i(headers.)55 -b(One)35 b(con)m(v)m(enien)m(t)i(w)m(a)m(y)f(to)g(pass)f(this)g -(information)h(to)g(the)f(external)0 4143 y(library)c(is)f(to)i(use)f -(the)g(\014ts)p 942 4143 28 4 v 32 w(hdr2str)f(routine)h(in)g(CFITSIO)e -(\(de\014ned)h(b)s(elo)m(w\))h(to)h(cop)m(y)g(the)f(header)g(k)m(eyw)m -(ords)0 4256 y(in)m(to)k(one)e(long)i(string,)f(and)f(then)g(pass)g -(this)h(string)f(to)i(an)e(in)m(terface)i(routine)f(in)f(the)h -(external)g(library)f(that)0 4369 y(will)d(extract)h(the)f(necessary)f -(W)m(CS)h(information)g(\(e.g.,)h(the)f('w)m(cspih')g(routine)f(in)g -(the)h(W)m(CSLIB)f(library)h(and)0 4482 y(the)h('astFitsChan')g(and)f -('astPutCards')g(functions)g(in)g(the)h(AST)e(library\).)0 -4763 y Fi(1)81 b Fj(Concatenate)38 b(the)f(header)f(k)m(eyw)m(ords)h -(in)f(the)g(CHDU)h(in)m(to)h(a)f(single)g(long)g(string)f(of)h(c)m -(haracters.)60 b(Eac)m(h)227 4876 y(80-c)m(haracter)28 -b(\014xed-length)c(k)m(eyw)m(ord)h(record)g(is)g(app)s(ended)d(to)k -(the)f(output)f(c)m(haracter)i(string,)g(in)e(order,)227 -4989 y(with)h(no)f(in)m(terv)m(ening)i(separator)f(or)g(terminating)h -(c)m(haracters.)40 b(The)24 b(last)i(header)e(record)h(is)f(terminated) -227 5101 y(with)33 b(a)g(NULL)f(c)m(haracter.)49 b(This)32 -b(routine)h(allo)s(cates)i(memory)d(for)h(the)g(returned)e(c)m -(haracter)j(arra)m(y)-8 b(,)35 b(so)227 5214 y(the)c(calling)h(program) -e(m)m(ust)g(free)h(the)f(memory)g(when)g(\014nished.)227 -5375 y(There)c(are)h(2)f(related)h(routines:)39 b(\014ts)p -1514 5375 V 32 w(hdr2str)25 b(simply)h(concatenates)j(all)e(the)f -(existing)h(k)m(eyw)m(ords)g(in)f(the)227 5488 y(header;)40 -b(\014ts)p 682 5488 V 32 w(con)m(v)m(ert)p 1003 5488 -V 34 w(hdr2str)35 b(is)i(similar,)h(except)f(that)g(if)f(the)h(CHDU)f -(is)h(a)f(tile)i(compressed)e(image)227 5601 y(\(stored)28 -b(in)g(a)f(binary)g(table\))i(then)e(it)h(will)g(\014rst)f(con)m(v)m -(ert)i(that)f(header)g(bac)m(k)g(to)g(that)g(of)g(a)g(normal)g(FITS)227 -5714 y(image)k(b)s(efore)e(concatenating)j(the)d(k)m(eyw)m(ords.)1905 -5942 y(85)p eop end -%%Page: 86 94 -TeXDict begin 86 93 bop 0 299 a Fj(86)1169 b Fh(CHAPTER)29 -b(7.)112 b(W)m(ORLD)31 b(COORDINA)-8 b(TE)30 b(SYSTEM)f(R)m(OUTINES)227 -555 y Fj(Selected)h(k)m(eyw)m(ords)e(ma)m(y)h(b)s(e)e(excluded)h(from)g -(the)g(returned)f(c)m(haracter)j(string.)40 b(If)27 b(the)i(second)f -(param-)227 668 y(eter)h(\(no)s(commen)m(ts\))g(is)f(TR)m(UE)g -(\(nonzero\))h(then)e(an)m(y)i(COMMENT,)f(HISTOR)-8 b(Y,)27 -b(or)h(blank)g(k)m(eyw)m(ords)227 781 y(in)i(the)h(header)f(will)h(not) -f(b)s(e)g(copied)h(to)g(the)g(output)f(string.)227 924 -y(The)25 b('exclist')j(parameter)e(ma)m(y)g(b)s(e)f(used)g(to)h(supply) -e(a)i(list)h(of)e(k)m(eyw)m(ords)h(that)h(are)f(to)g(b)s(e)f(excluded)g -(from)227 1037 y(the)k(output)g(c)m(haracter)h(string.)41 -b(Wild)29 b(card)g(c)m(haracters)h(\(*,)g(?,)f(and)g(#\))g(ma)m(y)g(b)s -(e)f(used)g(in)h(the)g(excluded)227 1150 y(k)m(eyw)m(ord)h(names.)41 -b(If)29 b(no)g(additional)i(k)m(eyw)m(ords)f(are)g(to)g(b)s(e)f -(excluded,)h(then)f(set)h(nexc)g(=)f(0)h(and)f(sp)s(ecify)227 -1263 y(NULL)i(for)f(the)g(the)h(**exclist)i(parameter.)95 -1478 y Fe(int)47 b(fits_hdr2str)286 1591 y(\(fitsfile)f(*fptr,)g(int)h -(nocomments,)d(char)j(**exclist,)e(int)i(nexc,)286 1704 -y(>)h(char)e(**header,)g(int)h(*nkeys,)e(int)i(*status\))95 -1930 y(int)g(fits_convert_hdr2str)c(/)k(ffcnvthdr2str)286 -2043 y(\(fitsfile)f(*fptr,)g(int)h(nocomments,)d(char)j(**exclist,)e -(int)i(nexc,)286 2155 y(>)h(char)e(**header,)g(int)h(*nkeys,)e(int)i -(*status\))0 2371 y Fi(2)81 b Fj(The)24 b(follo)m(wing)j(CFITSIO)d -(routine)i(is)f(sp)s(eci\014cally)h(designed)f(for)h(use)f(in)g -(conjunction)g(with)g(the)h(W)m(CSLIB)227 2484 y(library)-8 -b(.)40 b(It)27 b(is)h(not)f(exp)s(ected)h(that)g(applications)g -(programmers)f(will)h(call)g(this)f(routine)h(directly)-8 -b(,)29 b(but)d(it)227 2597 y(is)33 b(do)s(cumen)m(ted)g(here)g(for)g -(completeness.)50 b(This)33 b(routine)g(extracts)h(arra)m(ys)g(from)e -(a)i(binary)e(table)i(that)227 2710 y(con)m(tain)i(W)m(CS)e -(information)h(using)f(the)g(-T)-8 b(AB)36 b(table)f(lo)s(okup)f(con)m -(v)m(en)m(tion.)55 b(See)35 b(the)f(do)s(cumen)m(tation)227 -2822 y(pro)m(vided)c(with)g(the)h(W)m(CSLIB)f(library)g(for)g(more)h -(information.)95 3038 y Fe(int)47 b(fits_read_wcstab)334 -3151 y(\(fitsfile)e(*fptr,)h(int)h(nwtb,)g(wtbarr)f(*wtb,)g(int)h -(*status\);)0 3477 y Ff(7.1)180 b(Self-con)l(tained)46 -b(W)l(CS)f(Routines)0 3728 y Fj(The)21 b(follo)m(wing)i(routines)e(DO)g -(NOT)g(supp)s(ort)f(the)h(more)h(recen)m(t)g(W)m(CS)f(con)m(v)m(en)m -(tions)j(that)d(ha)m(v)m(e)i(b)s(een)e(appro)m(v)m(ed)0 -3841 y(as)34 b(part)g(of)g(the)g(FITS)f(standard.)50 -b(Consequen)m(tly)-8 b(,)35 b(the)f(follo)m(wing)i(routines)d(ARE)h(NO) -m(W)h(DEPRECA)-8 b(TED.)0 3953 y(It)30 b(is)g(STR)m(ONGL)-8 -b(Y)30 b(RECOMMENDED)h(that)g(soft)m(w)m(are)g(dev)m(elop)s(ers)f(not)h -(use)f(these)g(routines,)g(and)g(instead)0 4066 y(use)g(an)g(external)i -(W)m(CS)e(library)-8 b(,)31 b(as)f(describ)s(ed)f(in)i(the)f(previous)g -(section.)0 4227 y(These)21 b(routines)g(are)g(included)f(mainly)h(for) -g(bac)m(kw)m(ard)g(compatibilit)m(y)j(with)c(existing)i(soft)m(w)m -(are.)39 b(They)21 b(supp)s(ort)0 4339 y(the)30 b(follo)m(wing)i -(standard)d(map)g(pro)5 b(jections:)41 b(-SIN,)30 b(-T)-8 -b(AN,)31 b(-AR)m(C,)g(-NCP)-8 b(,)30 b(-GLS,)g(-MER,)h(and)e(-AIT)h -(\(these)0 4452 y(are)f(the)g(legal)h(v)-5 b(alues)29 -b(for)f(the)h(co)s(ordt)m(yp)s(e)f(parameter\).)41 b(These)28 -b(routines)h(are)g(based)f(on)g(similar)h(functions)f(in)0 -4565 y(Classic)j(AIPS.)f(All)h(the)g(angular)f(quan)m(tities)i(are)f -(giv)m(en)g(in)f(units)g(of)g(degrees.)0 4781 y Fi(1)81 -b Fj(Get)41 b(the)f(v)-5 b(alues)41 b(of)g(the)f(basic)h(set)g(of)f -(standard)g(FITS)f(celestial)k(co)s(ordinate)e(system)g(k)m(eyw)m(ords) -f(from)227 4894 y(the)33 b(header)f(of)h(a)f(FITS)g(image)i(\(i.e.,)g -(the)f(primary)f(arra)m(y)g(or)h(an)f(IMA)m(GE)i(extension\).)47 -b(These)33 b(v)-5 b(alues)227 5006 y(ma)m(y)35 b(then)f(b)s(e)g(passed) -f(to)i(the)g(\014ts)p 1462 5006 28 4 v 32 w(pix)p 1618 -5006 V 32 w(to)p 1730 5006 V 34 w(w)m(orld)f(and)g(\014ts)p -2321 5006 V 32 w(w)m(orld)p 2573 5006 V 33 w(to)p 2686 -5006 V 33 w(pix)g(routines)g(that)h(p)s(erform)e(the)227 -5119 y(co)s(ordinate)f(transformations.)42 b(If)30 b(an)m(y)h(or)f(all) -i(of)f(the)g(W)m(CS)f(k)m(eyw)m(ords)h(are)g(not)g(presen)m(t,)g(then)g -(default)227 5232 y(v)-5 b(alues)26 b(will)f(b)s(e)f(returned.)38 -b(If)24 b(the)i(\014rst)e(co)s(ordinate)i(axis)f(is)g(the)g -(declination-lik)m(e)j(co)s(ordinate,)f(then)e(this)227 -5345 y(routine)31 b(will)f(sw)m(ap)h(them)f(so)h(that)g(the)f -(longitudinal-lik)m(e)j(co)s(ordinate)e(is)f(returned)g(as)g(the)h -(\014rst)e(axis.)227 5488 y(The)34 b(\014rst)g(routine)h(\(\013gics\))h -(returns)e(the)h(primary)f(W)m(CS,)g(whereas)h(the)g(second)g(routine)f -(returns)g(the)227 5601 y(particular)24 b(v)m(ersion)h(of)f(the)g(W)m -(CS)f(sp)s(eci\014ed)g(b)m(y)h(the)g('v)m(ersion')h(parameter,)h(whic)m -(h)d(m)m(uc)m(h)h(b)s(e)f(a)h(c)m(haracter)227 5714 y(ranging)31 -b(from)f('A')h(to)g('Z')f(\(or)h(a)g(blank)f(c)m(haracter,)i(whic)m(h)e -(is)g(equiv)-5 b(alen)m(t)32 b(to)f(calling)h(\013gics\).)p -eop end -%%Page: 87 95 -TeXDict begin 87 94 bop 0 299 a Fh(7.1.)113 b(SELF-CONT)-8 -b(AINED)30 b(W)m(CS)g(R)m(OUTINES)1984 b Fj(87)227 555 -y(If)35 b(the)h(\014le)f(uses)g(the)g(new)m(er)h('CDj)p -1454 555 28 4 v 32 w(i')g(W)m(CS)f(transformation)h(matrix)g(k)m(eyw)m -(ords)f(instead)h(of)f(old)h(st)m(yle)227 668 y('CDEL)-8 -b(Tn')37 b(and)f('CR)m(OT)-8 b(A2')38 b(k)m(eyw)m(ords,)h(then)e(this)f -(routine)h(will)g(calculate)j(and)c(return)g(the)h(v)-5 -b(alues)227 781 y(of)33 b(the)g(equiv)-5 b(alen)m(t)35 -b(old-st)m(yle)f(k)m(eyw)m(ords.)49 b(Note)34 b(that)g(the)f(con)m(v)m -(ersion)h(from)e(the)i(new-st)m(yle)g(k)m(eyw)m(ords)227 -894 y(to)e(the)f(old-st)m(yle)h(v)-5 b(alues)31 b(is)g(sometimes)g -(only)g(an)g(appro)m(ximation,)h(so)e(if)h(the)g(appro)m(ximation)h(is) -e(larger)227 1007 y(than)37 b(an)h(in)m(ternally)g(de\014ned)e -(threshold)h(lev)m(el,)k(then)c(CFITSIO)f(will)i(still)g(return)e(the)i -(appro)m(ximate)227 1120 y(W)m(CS)32 b(k)m(eyw)m(ord)h(v)-5 -b(alues,)33 b(but)e(will)h(also)h(return)e(with)h(status)g(=)f(APPR)m -(O)m(X)p 2908 1120 V 34 w(W)m(CS)p 3149 1120 V 33 w(KEY,)g(to)i(w)m -(arn)f(the)227 1233 y(calling)k(program)e(that)h(appro)m(ximations)g -(ha)m(v)m(e)g(b)s(een)f(made.)52 b(It)35 b(is)f(then)g(up)f(to)i(the)f -(calling)i(program)227 1346 y(to)30 b(decide)g(whether)e(the)h(appro)m -(ximations)h(are)g(su\016cien)m(tly)f(accurate)i(for)e(the)g -(particular)g(application,)227 1458 y(or)46 b(whether)e(more)i(precise) -g(W)m(CS)f(transformations)h(m)m(ust)f(b)s(e)g(p)s(erformed)f(using)g -(new-st)m(yle)j(W)m(CS)227 1571 y(k)m(eyw)m(ords)31 b(directly)-8 -b(.)95 1824 y Fe(int)47 b(fits_read_img_coord)c(/)k(ffgics)286 -1937 y(\(fitsfile)f(*fptr,)g(>)h(double)f(*xrefval,)g(double)g -(*yrefval,)334 2050 y(double)g(*xrefpix,)f(double)i(*yrefpix,)e(double) -h(*xinc,)g(double)g(*yinc,)334 2163 y(double)g(*rot,)h(char)f -(*coordtype,)f(int)i(*status\))95 2389 y(int)g -(fits_read_img_coord_versio)o(n)42 b(/)47 b(ffgicsa)286 -2502 y(\(fitsfile)f(*fptr,)g(char)g(version,)g(>)h(double)f(*xrefval,)g -(double)g(*yrefval,)334 2615 y(double)g(*xrefpix,)f(double)i(*yrefpix,) -e(double)h(*xinc,)g(double)g(*yinc,)334 2728 y(double)g(*rot,)h(char)f -(*coordtype,)f(int)i(*status\))0 2981 y Fi(2)81 b Fj(Get)30 -b(the)f(v)-5 b(alues)30 b(of)f(the)h(standard)e(FITS)h(celestial)j(co)s -(ordinate)e(system)f(k)m(eyw)m(ords)h(from)f(the)g(header)g(of)h(a)227 -3094 y(FITS)23 b(table)i(where)e(the)h(X)g(and)g(Y)g(\(or)g(RA)g(and)f -(DEC\))h(co)s(ordinates)h(are)f(stored)g(in)f(2)h(separate)h(columns) -227 3207 y(of)30 b(the)f(table)h(\(as)g(in)f(the)h(Ev)m(en)m(t)g(List)g -(table)g(format)f(that)h(is)g(often)f(used)g(b)m(y)g(high)g(energy)g -(astroph)m(ysics)227 3320 y(missions\).)71 b(These)40 -b(v)-5 b(alues)40 b(ma)m(y)h(then)f(b)s(e)f(passed)h(to)h(the)f(\014ts) -p 2511 3320 V 33 w(pix)p 2668 3320 V 32 w(to)p 2780 3320 -V 34 w(w)m(orld)g(and)g(\014ts)p 3383 3320 V 32 w(w)m(orld)p -3635 3320 V 33 w(to)p 3748 3320 V 33 w(pix)227 3432 y(routines)31 -b(that)f(p)s(erform)f(the)i(co)s(ordinate)g(transformations.)95 -3685 y Fe(int)47 b(fits_read_tbl_coord)c(/)k(ffgtcs)286 -3798 y(\(fitsfile)f(*fptr,)g(int)h(xcol,)f(int)h(ycol,)f(>)i(double)e -(*xrefval,)334 3911 y(double)g(*yrefval,)f(double)i(*xrefpix,)e(double) -h(*yrefpix,)f(double)h(*xinc,)334 4024 y(double)g(*yinc,)g(double)g -(*rot,)h(char)f(*coordtype,)f(int)i(*status\))0 4277 -y Fi(3)81 b Fj(Calculate)42 b(the)g(celestial)h(co)s(ordinate)f -(corresp)s(onding)e(to)i(the)f(input)f(X)h(and)g(Y)g(pixel)g(lo)s -(cation)i(in)e(the)227 4390 y(image.)95 4643 y Fe(int)47 -b(fits_pix_to_world)c(/)48 b(ffwldp)286 4756 y(\(double)e(xpix,)h -(double)f(ypix,)g(double)g(xrefval,)g(double)g(yrefval,)334 -4869 y(double)g(xrefpix,)g(double)g(yrefpix,)f(double)h(xinc,)h(double) -f(yinc,)334 4982 y(double)g(rot,)h(char)f(*coordtype,)f(>)j(double)e -(*xpos,)g(double)g(*ypos,)334 5095 y(int)h(*status\))0 -5348 y Fi(4)81 b Fj(Calculate)42 b(the)g(X)f(and)f(Y)h(pixel)h(lo)s -(cation)g(corresp)s(onding)e(to)i(the)f(input)f(celestial)k(co)s -(ordinate)e(in)f(the)227 5461 y(image.)95 5714 y Fe(int)47 -b(fits_world_to_pix)c(/)48 b(ffxypx)p eop end -%%Page: 88 96 -TeXDict begin 88 95 bop 0 299 a Fj(88)1169 b Fh(CHAPTER)29 -b(7.)112 b(W)m(ORLD)31 b(COORDINA)-8 b(TE)30 b(SYSTEM)f(R)m(OUTINES)286 -555 y Fe(\(double)46 b(xpos,)h(double)f(ypos,)g(double)g(xrefval,)g -(double)g(yrefval,)334 668 y(double)g(xrefpix,)g(double)g(yrefpix,)f -(double)h(xinc,)h(double)f(yinc,)334 781 y(double)g(rot,)h(char)f -(*coordtype,)f(>)j(double)e(*xpix,)g(double)g(*ypix,)334 -894 y(int)h(*status\))p eop end -%%Page: 89 97 -TeXDict begin 89 96 bop 0 1225 a Fg(Chapter)65 b(8)0 -1687 y Fm(Hierarc)-6 b(hical)76 b(Grouping)h(Routines)0 -2180 y Fj(These)34 b(functions)h(allo)m(w)h(for)e(the)h(creation)h(and) -e(manipulation)h(of)g(FITS)f(HDU)h(Groups,)h(as)f(de\014ned)e(in)h("A)0 -2293 y(Hierarc)m(hical)f(Grouping)c(Con)m(v)m(en)m(tion)j(for)e(FITS")h -(b)m(y)f(Jennings,)g(P)m(ence,)h(F)-8 b(olk)32 b(and)e(Sc)m(hlesinger:) -0 2453 y(h)m(ttp://\014ts.gsfc.nasa.go)m(v/group.h)m(tml)0 -2613 y(A)38 b(group)g(is)g(a)g(collection)j(of)d(HDUs)h(whose)f(asso)s -(ciation)h(is)g(de\014ned)d(b)m(y)i(a)h Fa(gr)-5 b(ouping)40 -b(table)p Fj(.)65 b(HDUs)38 b(whic)m(h)0 2726 y(are)46 -b(part)f(of)g(a)g(group)g(are)h(referred)e(to)i(as)f -Fa(memb)-5 b(er)47 b(HDUs)d Fj(or)h(simply)g(as)g Fa(memb)-5 -b(ers)p Fj(.)86 b(Grouping)45 b(table)0 2839 y(mem)m(b)s(er)40 -b(HDUs)i(ma)m(y)f(themselv)m(es)h(b)s(e)f(grouping)f(tables,)45 -b(th)m(us)40 b(allo)m(wing)j(for)e(the)g(construction)g(of)g(op)s(en-)0 -2952 y(ended)30 b(hierarc)m(hies)h(of)f(HDUs.)0 3112 -y(Grouping)c(tables)i(con)m(tain)g(one)f(ro)m(w)g(for)f(eac)m(h)i(mem)m -(b)s(er)e(HDU.)i(The)e(grouping)g(table)i(columns)e(pro)m(vide)h(iden-) -0 3225 y(ti\014cation)i(information)f(that)g(allo)m(ws)h(applications)f -(to)g(reference)g(or)g("p)s(oin)m(t)g(to")g(the)g(mem)m(b)s(er)f(HDUs.) -40 b(Mem-)0 3338 y(b)s(er)27 b(HDUs)h(are)g(exp)s(ected,)h(but)e(not)h -(required,)f(to)i(con)m(tain)g(a)f(set)g(of)g(GRPIDn/GRPLCn)f(k)m(eyw)m -(ords)h(in)f(their)0 3451 y(headers)j(for)h(eac)m(h)g(grouping)g(table) -g(that)g(they)g(are)g(referenced)g(b)m(y)-8 b(.)41 b(In)30 -b(this)h(sense,)g(the)g(GRPIDn/GRPLCn)0 3563 y(k)m(eyw)m(ords)d("link") -g(the)g(mem)m(b)s(er)f(HDU)h(bac)m(k)g(to)g(its)g(Grouping)f(table.)41 -b(Note)29 b(that)f(a)f(mem)m(b)s(er)g(HDU)h(need)g(not)0 -3676 y(reside)i(in)g(the)g(same)g(FITS)f(\014le)i(as)f(its)g(grouping)g -(table,)h(and)e(that)i(a)f(giv)m(en)h(HDU)g(ma)m(y)g(b)s(e)e -(referenced)h(b)m(y)g(up)0 3789 y(to)h(999)h(grouping)e(tables)h(sim)m -(ultaneously)-8 b(.)0 3949 y(Grouping)22 b(tables)i(are)f(implemen)m -(ted)g(as)g(FITS)f(binary)g(tables)h(with)g(up)e(to)j(six)e -(pre-de\014ned)g(column)g(TTYPEn)0 4062 y(v)-5 b(alues:)36 -b('MEMBER)p 752 4062 28 4 v 34 w(XTENSION',)20 b('MEMBER)p -1789 4062 V 33 w(NAME',)h('MEMBER)p 2620 4062 V 34 w(VERSION',)f -('MEMBER)p 3590 4062 V 34 w(POSITION',)0 4175 y('MEMBER)p -451 4175 V 34 w(URI)p 653 4175 V 32 w(TYPE')g(and)g('MEMBER)p -1601 4175 V 34 w(LOCA)-8 b(TION'.)20 b(The)f(\014rst)h(three)g(columns) -g(allo)m(w)i(mem)m(b)s(er)e(HDUs)0 4288 y(to)28 b(b)s(e)f(iden)m -(ti\014ed)g(b)m(y)g(reference)h(to)g(their)f(XTENSION,)g(EXTNAME)g(and) -g(EXTVER)g(k)m(eyw)m(ord)g(v)-5 b(alues.)40 b(The)0 4401 -y(fourth)29 b(column)h(allo)m(ws)i(mem)m(b)s(er)d(HDUs)i(to)g(b)s(e)f -(iden)m(ti\014ed)g(b)m(y)g(HDU)h(p)s(osition)f(within)g(their)g(FITS)g -(\014le.)40 b(The)0 4514 y(last)f(t)m(w)m(o)g(columns)e(iden)m(tify)h -(the)g(FITS)f(\014le)h(in)f(whic)m(h)h(the)g(mem)m(b)s(er)f(HDU)h -(resides,)i(if)d(di\013eren)m(t)i(from)e(the)0 4627 y(grouping)30 -b(table)h(FITS)f(\014le.)0 4787 y(Additional)25 b(user)f(de\014ned)f -("auxiliary")j(columns)e(ma)m(y)h(also)g(b)s(e)f(included)g(with)g(an)m -(y)h(grouping)f(table.)39 b(When)25 b(a)0 4900 y(grouping)i(table)i(is) -f(copied)g(or)f(mo)s(di\014ed)g(the)h(presence)g(of)f(auxiliary)i -(columns)e(is)h(alw)m(a)m(ys)h(tak)m(en)g(in)m(to)f(accoun)m(t)0 -5013 y(b)m(y)j(the)g(grouping)g(supp)s(ort)f(functions;)h(ho)m(w)m(ev)m -(er,)i(the)e(grouping)g(supp)s(ort)f(functions)g(cannot)i(directly)g -(mak)m(e)0 5126 y(use)e(of)h(this)f(data.)0 5286 y(If)44 -b(a)h(grouping)f(table)h(column)f(is)h(de\014ned)e(but)h(the)g(corresp) -s(onding)g(mem)m(b)s(er)f(HDU)j(information)e(is)h(un-)0 -5399 y(a)m(v)-5 b(ailable)41 b(then)c(a)i(n)m(ull)f(v)-5 -b(alue)39 b(of)f(the)g(appropriate)h(data)f(t)m(yp)s(e)h(is)f(inserted) -g(in)g(the)g(column)g(\014eld.)64 b(In)m(teger)0 5512 -y(columns)26 b(\(MEMBER)p 811 5512 V 34 w(POSITION,)f(MEMBER)p -1771 5512 V 34 w(VERSION\))h(are)h(de\014ned)f(with)g(a)h(TNULLn)f(v)-5 -b(alue)27 b(of)g(zero)0 5625 y(\(0\).)41 b(Character)27 -b(\014eld)f(columns)h(\(MEMBER)p 1607 5625 V 34 w(XTENSION,)f(MEMBER)p -2600 5625 V 33 w(NAME,)i(MEMBER)p 3388 5625 V 34 w(URI)p -3590 5625 V 32 w(TYPE,)1905 5942 y(89)p eop end -%%Page: 90 98 -TeXDict begin 90 97 bop 0 299 a Fj(90)1338 b Fh(CHAPTER)29 -b(8.)112 b(HIERAR)m(CHICAL)30 b(GR)m(OUPING)h(R)m(OUTINES)0 -555 y Fj(MEMBER)p 426 555 28 4 v 33 w(LOCA)-8 b(TION\))30 -b(utilize)i(an)e(ASCI)s(I)f(n)m(ull)h(c)m(haracter)i(to)f(denote)g(a)g -(n)m(ull)f(\014eld)g(v)-5 b(alue.)0 715 y(The)23 b(grouping)g(supp)s -(ort)f(functions)h(b)s(elong)h(to)g(t)m(w)m(o)h(basic)f(categories:)40 -b(those)24 b(that)h(w)m(ork)e(with)h(grouping)f(table)0 -828 y(HDUs)j(\(\013gt**\))j(and)c(those)h(that)h(w)m(ork)f(with)f(mem)m -(b)s(er)h(HDUs)g(\(\013gm**\).)41 b(Tw)m(o)26 b(functions,)h(\014ts)p -3360 828 V 32 w(cop)m(y)p 3573 828 V 34 w(group\(\))0 -941 y(and)40 b(\014ts)p 314 941 V 33 w(remo)m(v)m(e)p -626 941 V 34 w(group\(\),)k(ha)m(v)m(e)e(the)f(option)g(to)h(recursiv)m -(ely)f(cop)m(y/delete)j(en)m(tire)e(groups.)71 b(Care)41 -b(should)0 1054 y(b)s(e)33 b(tak)m(en)h(when)f(emplo)m(ying)h(these)g -(functions)f(in)g(recursiv)m(e)h(mo)s(de)f(as)g(p)s(o)s(orly)g -(de\014ned)f(groups)h(could)g(cause)0 1167 y(unpredictable)25 -b(results.)39 b(The)25 b(problem)g(of)h(a)g(grouping)f(table)i -(directly)f(or)g(indirectly)g(referencing)g(itself)g(\(th)m(us)0 -1280 y(creating)41 b(an)f(in\014nite)f(lo)s(op\))i(is)e(protected)i -(against;)46 b(in)39 b(fact,)44 b(neither)39 b(function)h(will)g -(attempt)h(to)f(cop)m(y)h(or)0 1393 y(delete)32 b(an)e(HDU)h(t)m(wice.) -0 1745 y Ff(8.1)135 b(Grouping)45 b(T)-11 b(able)45 b(Routines)0 -1997 y Fi(1)81 b Fj(Create)34 b(\(app)s(end\))f(a)h(grouping)f(table)i -(at)f(the)g(end)f(of)h(the)g(curren)m(t)f(FITS)g(\014le)h(p)s(oin)m -(ted)g(to)g(b)m(y)g(fptr.)49 b(The)227 2110 y(grpname)28 -b(parameter)h(pro)m(vides)g(the)g(grouping)f(table)h(name)g(\(GRPNAME)g -(k)m(eyw)m(ord)g(v)-5 b(alue\))29 b(and)f(ma)m(y)227 -2223 y(b)s(e)42 b(set)h(to)g(NULL)f(if)g(no)g(group)g(name)g(is)h(to)g -(b)s(e)e(sp)s(eci\014ed.)76 b(The)42 b(groupt)m(yp)s(e)g(parameter)g -(sp)s(eci\014es)227 2336 y(the)c(desired)g(structure)f(of)h(the)g -(grouping)f(table)i(and)e(ma)m(y)i(tak)m(e)g(on)f(the)g(v)-5 -b(alues:)56 b(GT)p 3355 2336 V 33 w(ID)p 3490 2336 V -33 w(ALL)p 3705 2336 V 32 w(URI)227 2449 y(\(all)35 b(columns)e -(created\),)j(GT)p 1274 2449 V 33 w(ID)p 1409 2449 V -33 w(REF)d(\(ID)h(b)m(y)g(reference)g(columns\),)g(GT)p -2904 2449 V 33 w(ID)p 3039 2449 V 33 w(POS)e(\(ID)i(b)m(y)g(p)s -(osition)227 2562 y(columns\),)48 b(GT)p 801 2562 V 32 -w(ID)p 935 2562 V 33 w(ALL)c(\(ID)g(b)m(y)f(reference)i(and)e(p)s -(osition)g(columns\),)48 b(GT)p 3028 2562 V 32 w(ID)p -3162 2562 V 33 w(REF)p 3383 2562 V 33 w(URI)c(\(ID)g(b)m(y)227 -2674 y(reference)35 b(and)e(FITS)g(\014le)i(URI)e(columns\),)j(and)d -(GT)p 2129 2674 V 33 w(ID)p 2264 2674 V 33 w(POS)p 2481 -2674 V 32 w(URI)h(\(ID)g(b)m(y)g(p)s(osition)g(and)g(FITS)f(\014le)227 -2787 y(URI)e(columns\).)95 3063 y Fe(int)47 b(fits_create_group)c(/)48 -b(ffgtcr)286 3176 y(\(fitsfile)e(*fptr,)g(char)g(*grpname,)g(int)h -(grouptype,)e(>)i(int)g(*status\))0 3451 y Fi(2)81 b -Fj(Create)26 b(\(insert\))g(a)f(grouping)g(table)h(just)f(after)h(the)f -(CHDU)h(of)g(the)f(curren)m(t)g(FITS)g(\014le)g(p)s(oin)m(ted)g(to)h(b) -m(y)g(fptr.)227 3564 y(All)k(HDUs)f(b)s(elo)m(w)g(the)g(the)g -(insertion)g(p)s(oin)m(t)f(will)i(b)s(e)e(shifted)g(do)m(wn)m(w)m(ards) -g(to)i(mak)m(e)g(ro)s(om)e(for)g(the)h(new)227 3677 y(HDU.)23 -b(The)e(grpname)h(parameter)g(pro)m(vides)f(the)h(grouping)g(table)g -(name)g(\(GRPNAME)h(k)m(eyw)m(ord)f(v)-5 b(alue\))227 -3790 y(and)25 b(ma)m(y)i(b)s(e)e(set)h(to)h(NULL)e(if)h(no)g(group)f -(name)h(is)g(to)g(b)s(e)f(sp)s(eci\014ed.)39 b(The)25 -b(groupt)m(yp)s(e)h(parameter)g(sp)s(eci-)227 3903 y(\014es)g(the)h -(desired)f(structure)g(of)h(the)f(grouping)g(table)i(and)e(ma)m(y)h -(tak)m(e)h(on)e(the)h(v)-5 b(alues:)39 b(GT)p 3355 3903 -V 33 w(ID)p 3490 3903 V 33 w(ALL)p 3705 3903 V 32 w(URI)227 -4016 y(\(all)c(columns)e(created\),)j(GT)p 1274 4016 -V 33 w(ID)p 1409 4016 V 33 w(REF)d(\(ID)h(b)m(y)g(reference)g -(columns\),)g(GT)p 2904 4016 V 33 w(ID)p 3039 4016 V -33 w(POS)e(\(ID)i(b)m(y)g(p)s(osition)227 4129 y(columns\),)29 -b(GT)p 782 4129 V 33 w(ID)p 917 4129 V 33 w(ALL)f(\(ID)g(b)m(y)g -(reference)h(and)e(p)s(osition)h(columns\),)h(GT)p 2897 -4129 V 33 w(ID)p 3032 4129 V 33 w(REF)p 3253 4129 V 32 -w(URI)f(\(ID)h(b)m(y)f(ref-)227 4242 y(erence)g(and)e(FITS)h(\014le)g -(URI)g(columns\),)h(and)e(GT)p 1976 4242 V 33 w(ID)p -2111 4242 V 33 w(POS)p 2328 4242 V 32 w(URI)h(\(ID)g(b)m(y)g(p)s -(osition)g(and)g(FITS)f(\014le)h(URI)227 4355 y(columns\))k(.)95 -4630 y Fe(int)47 b(fits_insert_group)c(/)48 b(ffgtis)286 -4743 y(\(fitsfile)e(*fptr,)g(char)g(*grpname,)g(int)h(grouptype,)e(>)i -(int)g(*status\))0 5019 y Fi(3)81 b Fj(Change)20 b(the)h(structure)f -(of)h(an)g(existing)g(grouping)g(table)g(p)s(oin)m(ted)g(to)g(b)m(y)g -(gfptr.)37 b(The)20 b(groupt)m(yp)s(e)g(parameter)227 -5132 y(\(see)27 b(\014ts)p 532 5132 V 32 w(create)p 800 -5132 V 35 w(group\(\))e(for)h(v)-5 b(alid)26 b(parameter)g(v)-5 -b(alues\))26 b(sp)s(eci\014es)g(the)f(new)g(structure)h(of)f(the)h -(grouping)227 5245 y(table.)44 b(This)30 b(function)h(only)g(adds)g(or) -g(remo)m(v)m(es)h(grouping)f(table)h(columns,)f(it)h(do)s(es)f(not)g -(add)g(or)g(delete)227 5357 y(group)26 b(mem)m(b)s(ers)f(\(i.e.,)k -(table)e(ro)m(ws\).)40 b(If)26 b(the)g(grouping)g(table)h(already)g -(has)f(the)h(desired)e(structure)h(then)227 5470 y(no)35 -b(op)s(erations)f(are)h(p)s(erformed)e(and)h(function)g(simply)h -(returns)e(with)h(a)h(\(0\))g(success)g(status)g(co)s(de.)53 -b(If)227 5583 y(the)32 b(requested)g(structure)g(c)m(hange)h(creates)g -(new)f(grouping)g(table)h(columns,)f(then)g(the)g(column)g(v)-5 -b(alues)227 5696 y(for)30 b(all)i(existing)f(mem)m(b)s(ers)f(will)g(b)s -(e)g(\014lled)g(with)g(the)h(n)m(ull)f(v)-5 b(alues)31 -b(appropriate)f(to)h(the)g(column)f(t)m(yp)s(e.)p eop -end -%%Page: 91 99 -TeXDict begin 91 98 bop 0 299 a Fh(8.1.)72 b(GR)m(OUPING)31 -b(T)-8 b(ABLE)31 b(R)m(OUTINES)2235 b Fj(91)95 555 y -Fe(int)47 b(fits_change_group)c(/)48 b(ffgtch)286 668 -y(\(fitsfile)e(*gfptr,)f(int)i(grouptype,)e(>)j(int)f(*status\))0 -905 y Fi(4)81 b Fj(Remo)m(v)m(e)41 b(the)e(group)g(de\014ned)f(b)m(y)h -(the)h(grouping)f(table)h(p)s(oin)m(ted)f(to)h(b)m(y)g(gfptr,)h(and)e -(optionally)i(all)f(the)227 1018 y(group)29 b(mem)m(b)s(er)f(HDUs.)41 -b(The)28 b(rmopt)h(parameter)g(sp)s(eci\014es)g(the)g(action)h(to)g(b)s -(e)e(tak)m(en)i(for)f(all)h(mem)m(b)s(ers)227 1131 y(of)d(the)g(group)g -(de\014ned)e(b)m(y)i(the)g(grouping)g(table.)40 b(V)-8 -b(alid)28 b(v)-5 b(alues)27 b(are:)40 b(OPT)p 2848 1131 -28 4 v 32 w(RM)p 3030 1131 V 33 w(GPT)26 b(\(delete)j(only)e(the)227 -1244 y(grouping)33 b(table\))i(and)e(OPT)p 1259 1244 -V 32 w(RM)p 1441 1244 V 33 w(ALL)g(\(recursiv)m(ely)h(delete)h(all)f -(HDUs)g(that)g(b)s(elong)f(to)h(the)g(group\).)227 1357 -y(An)m(y)d(groups)g(con)m(taining)i(the)e(grouping)g(table)h(gfptr)e -(as)i(a)f(mem)m(b)s(er)g(are)g(up)s(dated,)f(and)h(if)g(rmopt)g(==)227 -1470 y(OPT)p 431 1470 V 32 w(RM)p 613 1470 V 33 w(GPT)21 -b(all)h(mem)m(b)s(ers)f(ha)m(v)m(e)h(their)f(GRPIDn)g(and)g(GRPLCn)f(k) -m(eyw)m(ords)h(up)s(dated)f(accordingly)-8 b(.)227 1582 -y(If)36 b(rmopt)g(==)g(OPT)p 985 1582 V 32 w(RM)p 1167 -1582 V 33 w(ALL,)g(then)g(other)h(groups)e(that)i(con)m(tain)h(the)e -(deleted)h(mem)m(b)s(ers)f(of)g(gfptr)227 1695 y(are)31 -b(up)s(dated)e(to)i(re\015ect)g(the)g(deletion)g(accordingly)-8 -b(.)95 1932 y Fe(int)47 b(fits_remove_group)c(/)48 b(ffgtrm)286 -2045 y(\(fitsfile)e(*gfptr,)f(int)i(rmopt,)f(>)i(int)f(*status\))0 -2282 y Fi(5)81 b Fj(Cop)m(y)28 b(\(app)s(end\))g(the)h(group)f -(de\014ned)g(b)m(y)h(the)f(grouping)h(table)h(p)s(oin)m(ted)e(to)i(b)m -(y)e(infptr,)h(and)f(optionally)i(all)227 2395 y(group)g(mem)m(b)s(er)h -(HDUs,)g(to)h(the)f(FITS)f(\014le)g(p)s(oin)m(ted)h(to)h(b)m(y)e -(outfptr.)41 b(The)31 b(cp)s(opt)f(parameter)h(sp)s(eci\014es)227 -2508 y(the)c(action)h(to)f(b)s(e)f(tak)m(en)h(for)g(all)g(mem)m(b)s -(ers)f(of)g(the)h(group)f(infptr.)38 b(V)-8 b(alid)28 -b(v)-5 b(alues)26 b(are:)40 b(OPT)p 3443 2508 V 32 w(GCP)p -3674 2508 V 32 w(GPT)227 2621 y(\(cop)m(y)d(only)g(the)f(grouping)g -(table\))h(and)e(OPT)p 1887 2621 V 32 w(GCP)p 2118 2621 -V 33 w(ALL)h(\(recursiv)m(ely)h(cop)m(y)g(ALL)e(the)i(HDUs)f(that)227 -2734 y(b)s(elong)24 b(to)g(the)g(group)f(de\014ned)g(b)m(y)g(infptr\).) -38 b(If)23 b(the)h(cp)s(opt)g(==)f(OPT)p 2618 2734 V -32 w(GCP)p 2849 2734 V 32 w(GPT)h(then)f(the)h(mem)m(b)s(ers)f(of)227 -2847 y(infptr)i(ha)m(v)m(e)h(their)g(GRPIDn)f(and)g(GRPLCn)g(k)m(eyw)m -(ords)h(up)s(dated)e(to)i(re\015ect)g(the)g(existence)h(of)f(the)f(new) -227 2960 y(grouping)f(table)g(outfptr,)h(since)f(they)g(no)m(w)g(b)s -(elong)g(to)g(the)g(new)g(group.)38 b(If)23 b(cp)s(opt)h(==)f(OPT)p -3460 2960 V 32 w(GCP)p 3691 2960 V 32 w(ALL)227 3073 -y(then)29 b(the)g(new)g(grouping)g(table)h(outfptr)e(only)h(con)m -(tains)i(p)s(oin)m(ters)e(to)h(the)f(copied)g(mem)m(b)s(er)g(HDUs)h -(and)227 3185 y(not)38 b(the)g(original)g(mem)m(b)s(er)f(HDUs)h(of)g -(infptr.)61 b(Note)39 b(that,)h(when)d(cp)s(opt)g(==)g(OPT)p -3301 3185 V 32 w(GCP)p 3532 3185 V 33 w(ALL,)g(all)227 -3298 y(mem)m(b)s(ers)h(of)h(the)f(group)g(de\014ned)f(b)m(y)i(infptr)e -(will)i(b)s(e)e(copied)i(to)g(a)g(single)g(FITS)f(\014le)h(p)s(oin)m -(ted)f(to)h(b)m(y)227 3411 y(outfptr)30 b(regardless)h(of)f(their)h -(\014le)f(distribution)g(in)g(the)h(original)g(group.)95 -3648 y Fe(int)47 b(fits_copy_group)d(/)j(ffgtcp)286 3761 -y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(cpopt,)f(>)h -(int)g(*status\))0 3998 y Fi(6)81 b Fj(Merge)40 b(the)f(t)m(w)m(o)h -(groups)e(de\014ned)g(b)m(y)h(the)g(grouping)g(table)g(HDUs)h(infptr)e -(and)g(outfptr)h(b)m(y)f(com)m(bining)227 4111 y(their)30 -b(mem)m(b)s(ers)f(in)m(to)i(a)f(single)g(grouping)f(table.)42 -b(All)30 b(mem)m(b)s(er)f(HDUs)h(\(ro)m(ws\))h(are)f(copied)g(from)f -(infptr)227 4224 y(to)f(outfptr.)39 b(If)26 b(mgopt)i(==)e(OPT)p -1419 4224 V 32 w(MR)m(G)p 1669 4224 V 34 w(COPY)g(then)g(infptr)g(con)m -(tin)m(ues)i(to)g(exist)g(unaltered)e(after)i(the)227 -4337 y(merge.)57 b(If)36 b(the)f(mgopt)i(==)e(OPT)p 1474 -4337 V 31 w(MR)m(G)p 1723 4337 V 34 w(MO)m(V)i(then)e(infptr)f(is)i -(deleted)h(after)f(the)g(merge.)57 b(In)35 b(b)s(oth)227 -4450 y(cases,)d(the)e(GRPIDn)h(and)e(GRPLCn)h(k)m(eyw)m(ords)g(of)h -(the)g(mem)m(b)s(er)e(HDUs)i(are)g(up)s(dated)e(accordingly)-8 -b(.)95 4687 y Fe(int)47 b(fits_merge_groups)c(/)48 b(ffgtmg)286 -4799 y(\(fitsfile)e(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(mgopt,)f(>) -h(int)g(*status\))0 5036 y Fi(7)81 b Fj("Compact")24 -b(the)f(group)g(de\014ned)f(b)m(y)h(grouping)f(table)i(p)s(oin)m(ted)f -(to)h(b)m(y)f(gfptr.)38 b(The)22 b(compaction)j(is)e(ac)m(hiev)m(ed)227 -5149 y(b)m(y)37 b(merging)h(\(via)g(\014ts)p 1034 5149 -V 32 w(merge)p 1303 5149 V 34 w(groups\(\)\))f(all)h(direct)g(mem)m(b)s -(er)f(HDUs)g(of)h(gfptr)e(that)i(are)g(themselv)m(es)227 -5262 y(grouping)i(tables.)70 b(The)40 b(cmopt)g(parameter)h(de\014nes)e -(whether)g(the)i(merged)f(grouping)f(table)i(HDUs)227 -5375 y(remain)j(after)h(merging)f(\(cmopt)h(==)f(OPT)p -1852 5375 V 32 w(CMT)p 2099 5375 V 32 w(MBR\))h(or)f(if)g(they)h(are)f -(deleted)h(after)g(merging)227 5488 y(\(cmopt)31 b(==)f(OPT)p -916 5488 V 32 w(CMT)p 1163 5488 V 32 w(MBR)p 1409 5488 -V 34 w(DEL\).)g(If)g(the)h(grouping)e(table)j(con)m(tains)f(no)f -(direct)h(mem)m(b)s(er)e(HDUs)227 5601 y(that)i(are)f(themselv)m(es)h -(grouping)e(tables)i(then)e(this)h(function)f(do)s(es)h(nothing.)40 -b(Note)31 b(that)g(this)e(function)227 5714 y(is)i(not)f(recursiv)m(e,) -h(i.e.,)h(only)f(the)f(direct)h(mem)m(b)s(er)f(HDUs)h(of)f(gfptr)g(are) -h(considered)f(for)g(merging.)p eop end -%%Page: 92 100 -TeXDict begin 92 99 bop 0 299 a Fj(92)1338 b Fh(CHAPTER)29 -b(8.)112 b(HIERAR)m(CHICAL)30 b(GR)m(OUPING)h(R)m(OUTINES)95 -555 y Fe(int)47 b(fits_compact_group)c(/)48 b(ffgtcm)286 -668 y(\(fitsfile)e(*gfptr,)f(int)i(cmopt,)f(>)i(int)f(*status\))0 -945 y Fi(8)81 b Fj(V)-8 b(erify)21 b(the)h(in)m(tegrit)m(y)h(of)e(the)g -(grouping)g(table)h(p)s(oin)m(ted)f(to)h(b)m(y)f(gfptr)g(to)h(mak)m(e)g -(sure)e(that)i(all)g(group)f(mem)m(b)s(ers)227 1058 y(are)31 -b(accessible)i(and)d(that)h(all)g(links)g(to)g(other)g(grouping)f -(tables)i(are)f(v)-5 b(alid.)42 b(The)30 b(\014rstfailed)g(parameter) -227 1171 y(returns)c(the)i(mem)m(b)s(er)e(ID)h(\(ro)m(w)h(n)m(um)m(b)s -(er\))e(of)i(the)f(\014rst)f(mem)m(b)s(er)h(HDU)h(to)g(fail)g(v)m -(eri\014cation)g(\(if)g(p)s(ositiv)m(e)227 1284 y(v)-5 -b(alue\))36 b(or)e(the)h(\014rst)e(group)h(link)g(to)i(fail)f(\(if)f -(negativ)m(e)j(v)-5 b(alue\).)54 b(If)34 b(gfptr)g(is)g(successfully)h -(v)m(eri\014ed)f(then)227 1397 y(\014rstfailed)d(con)m(tains)g(a)g -(return)e(v)-5 b(alue)31 b(of)g(0.)95 1673 y Fe(int)47 -b(fits_verify_group)c(/)48 b(ffgtvf)286 1786 y(\(fitsfile)e(*gfptr,)f -(>)j(long)f(*firstfailed,)d(int)j(*status\))0 2063 y -Fi(9)81 b Fj(Op)s(en)23 b(a)j(grouping)f(table)h(that)g(con)m(tains)g -(the)g(mem)m(b)s(er)e(HDU)i(p)s(oin)m(ted)f(to)h(b)m(y)f(mfptr.)38 -b(The)25 b(grouping)g(table)227 2176 y(to)39 b(op)s(en)e(is)h -(de\014ned)f(b)m(y)h(the)g(grpid)f(parameter,)j(whic)m(h)e(con)m(tains) -h(the)f(k)m(eyw)m(ord)h(index)e(v)-5 b(alue)39 b(of)f(the)227 -2289 y(GRPIDn/GRPLCn)d(k)m(eyw)m(ord\(s\))g(that)h(link)f(the)g(mem)m -(b)s(er)f(HDU)h(mfptr)f(to)i(the)f(grouping)f(table.)55 -b(If)227 2402 y(the)30 b(grouping)f(table)h(resides)f(in)h(a)f(\014le)h -(other)f(than)h(the)f(mem)m(b)s(er)g(HDUs)h(\014le)f(then)g(an)h -(attempt)g(is)g(\014rst)227 2515 y(made)f(to)h(op)s(en)e(the)h(\014le)g -(readwrite,)h(and)e(failing)i(that)g(readonly)-8 b(.)40 -b(A)29 b(p)s(oin)m(ter)g(to)h(the)f(op)s(ened)f(grouping)227 -2628 y(table)k(HDU)f(is)f(returned)f(in)h(gfptr.)227 -2786 y(Note)35 b(that)g(it)f(is)g(p)s(ossible,)g(although)h(unlik)m -(ely)f(and)f(undesirable,)h(for)g(the)g(GRPIDn/GRPLCn)f(k)m(ey-)227 -2899 y(w)m(ords)k(in)g(a)g(mem)m(b)s(er)g(HDU)h(header)f(to)h(b)s(e)e -(non-con)m(tin)m(uous,)k(e.g.,)g(GRPID1,)g(GRPID2,)g(GRPID5,)227 -3012 y(GRPID6.)i(In)29 b(suc)m(h)g(cases,)i(the)f(grpid)f(index)g(v)-5 -b(alue)31 b(sp)s(eci\014ed)e(in)g(the)h(function)f(call)j(shall)e(iden) -m(tify)g(the)227 3125 y(\(grpid\)th)36 b(GRPID)f(v)-5 -b(alue.)57 b(In)34 b(the)i(ab)s(o)m(v)m(e)h(example,)g(if)f(grpid)e(==) -h(3,)j(then)d(the)g(group)g(sp)s(eci\014ed)g(b)m(y)227 -3238 y(GRPID5)c(w)m(ould)g(b)s(e)e(op)s(ened.)95 3515 -y Fe(int)47 b(fits_open_group)d(/)j(ffgtop)286 3628 y(\(fitsfile)f -(*mfptr,)f(int)i(group,)f(>)i(fitsfile)d(**gfptr,)h(int)h(*status\))0 -3905 y Fi(10)f Fj(Add)38 b(a)h(mem)m(b)s(er)f(HDU)i(to)f(an)g(existing) -g(grouping)g(table)h(p)s(oin)m(ted)e(to)i(b)m(y)e(gfptr.)66 -b(The)38 b(mem)m(b)s(er)g(HDU)227 4017 y(ma)m(y)30 b(either)g(b)s(e)f -(p)s(oin)m(ted)g(to)h(mfptr)f(\(whic)m(h)g(m)m(ust)h(b)s(e)e(p)s -(ositioned)i(to)g(the)f(mem)m(b)s(er)g(HDU\))i(or,)f(if)f(mfptr)227 -4130 y(==)36 b(NULL,)g(iden)m(ti\014ed)g(b)m(y)g(the)g(hdup)s(os)e -(parameter)i(\(the)h(HDU)g(p)s(osition)f(n)m(um)m(b)s(er,)g(Primary)f -(arra)m(y)227 4243 y(==)f(1\))i(if)f(b)s(oth)f(the)h(grouping)g(table)g -(and)g(the)g(mem)m(b)s(er)f(HDU)h(reside)g(in)g(the)g(same)g(FITS)f -(\014le.)54 b(The)227 4356 y(new)27 b(mem)m(b)s(er)f(HDU)h(shall)g(ha)m -(v)m(e)h(the)f(appropriate)g(GRPIDn)f(and)g(GRPLCn)g(k)m(eyw)m(ords)h -(created)h(in)f(its)227 4469 y(header.)44 b(Note)33 b(that)f(if)g(the)g -(mem)m(b)s(er)e(HDU)j(is)e(already)h(a)g(mem)m(b)s(er)f(of)h(the)g -(group)f(then)g(it)h(will)g(not)g(b)s(e)227 4582 y(added)e(a)h(second)f -(time.)95 4859 y Fe(int)47 b(fits_add_group_member)42 -b(/)48 b(ffgtam)286 4972 y(\(fitsfile)e(*gfptr,)f(fitsfile)h(*mfptr,)g -(int)h(hdupos,)f(>)h(int)g(*status\))0 5325 y Ff(8.2)135 -b(Group)45 b(Mem)l(b)t(er)f(Routines)0 5578 y Fi(1)81 -b Fj(Return)29 b(the)h(n)m(um)m(b)s(er)f(of)i(mem)m(b)s(er)e(HDUs)i(in) -f(a)h(grouping)e(table)j(gfptr.)40 b(The)30 b(n)m(um)m(b)s(er)e(mem)m -(b)s(er)i(HDUs)h(is)227 5691 y(just)f(the)h(NAXIS2)f(v)-5 -b(alue)31 b(\(n)m(um)m(b)s(er)f(of)g(ro)m(ws\))h(of)f(the)h(grouping)f -(table.)p eop end -%%Page: 93 101 -TeXDict begin 93 100 bop 0 299 a Fh(8.2.)72 b(GR)m(OUP)31 -b(MEMBER)g(R)m(OUTINES)2295 b Fj(93)95 555 y Fe(int)47 -b(fits_get_num_members)c(/)k(ffgtnm)286 668 y(\(fitsfile)f(*gfptr,)f(>) -j(long)f(*nmembers,)e(int)h(*status\))0 945 y Fi(2)81 -b Fj(Return)34 b(the)h(n)m(um)m(b)s(er)f(of)i(groups)e(to)i(whic)m(h)f -(the)g(HDU)h(p)s(oin)m(ted)f(to)h(b)m(y)f(mfptr)f(is)i(link)m(ed,)h(as) -e(de\014ned)f(b)m(y)227 1058 y(the)27 b(n)m(um)m(b)s(er)f(of)h -(GRPIDn/GRPLCn)f(k)m(eyw)m(ord)i(records)e(that)i(app)s(ear)e(in)g(its) -i(header.)39 b(Note)28 b(that)g(eac)m(h)227 1171 y(time)37 -b(this)g(function)f(is)g(called,)k(the)c(indices)h(of)g(the)f -(GRPIDn/GRPLCn)g(k)m(eyw)m(ords)h(are)g(c)m(hec)m(k)m(ed)h(to)227 -1284 y(mak)m(e)29 b(sure)e(they)g(are)h(con)m(tin)m(uous)g(\(ie)h(no)e -(gaps\))h(and)f(are)h(re-en)m(umerated)g(to)h(eliminate)g(gaps)f(if)f -(found.)95 1674 y Fe(int)47 b(fits_get_num_groups)c(/)k(ffgmng)286 -1787 y(\(fitsfile)f(*mfptr,)f(>)j(long)f(*nmembers,)e(int)h(*status\))0 -2063 y Fi(3)81 b Fj(Op)s(en)26 b(a)i(mem)m(b)s(er)f(of)h(the)f -(grouping)h(table)g(p)s(oin)m(ted)g(to)g(b)m(y)g(gfptr.)39 -b(The)27 b(mem)m(b)s(er)g(to)i(op)s(en)e(is)g(iden)m(ti\014ed)h(b)m(y) -227 2176 y(its)i(ro)m(w)g(n)m(um)m(b)s(er)e(within)h(the)g(grouping)h -(table)g(as)g(giv)m(en)g(b)m(y)g(the)f(parameter)h('mem)m(b)s(er')f -(\(\014rst)h(mem)m(b)s(er)227 2289 y(==)g(1\))g(.)41 -b(A)30 b(\014ts\014le)f(p)s(oin)m(ter)h(to)h(the)f(op)s(ened)f(mem)m(b) -s(er)g(HDU)i(is)f(returned)f(as)h(mfptr.)39 b(Note)31 -b(that)g(if)f(the)227 2402 y(mem)m(b)s(er)e(HDU)h(resides)g(in)f(a)h -(FITS)f(\014le)g(di\013eren)m(t)h(from)f(the)h(grouping)f(table)h(HDU)h -(then)e(the)h(mem)m(b)s(er)227 2515 y(\014le)i(is)f(\014rst)g(op)s -(ened)f(readwrite)i(and,)f(failing)h(this,)g(op)s(ened)e(readonly)-8 -b(.)95 2792 y Fe(int)47 b(fits_open_member)d(/)j(ffgmop)286 -2905 y(\(fitsfile)f(*gfptr,)f(long)i(member,)f(>)h(fitsfile)f(**mfptr,) -f(int)i(*status\))0 3182 y Fi(4)81 b Fj(Cop)m(y)27 b(\(app)s(end\))f(a) -i(mem)m(b)s(er)f(HDU)h(of)f(the)h(grouping)e(table)j(p)s(oin)m(ted)e -(to)h(b)m(y)f(gfptr.)39 b(The)27 b(mem)m(b)s(er)g(HDU)h(is)227 -3295 y(iden)m(ti\014ed)33 b(b)m(y)g(its)h(ro)m(w)f(n)m(um)m(b)s(er)e -(within)i(the)g(grouping)g(table)g(as)h(giv)m(en)g(b)m(y)e(the)i -(parameter)f('mem)m(b)s(er')227 3408 y(\(\014rst)j(mem)m(b)s(er)f(==)g -(1\).)58 b(The)35 b(cop)m(y)i(of)f(the)g(group)f(mem)m(b)s(er)g(HDU)i -(will)f(b)s(e)f(app)s(ended)f(to)j(the)f(FITS)227 3521 -y(\014le)29 b(p)s(oin)m(ted)g(to)g(b)m(y)f(mfptr,)h(and)f(up)s(on)f -(return)g(mfptr)h(shall)h(p)s(oin)m(t)f(to)i(the)f(copied)g(mem)m(b)s -(er)f(HDU.)h(The)227 3633 y(cp)s(opt)e(parameter)h(ma)m(y)g(tak)m(e)h -(on)e(the)g(follo)m(wing)i(v)-5 b(alues:)40 b(OPT)p 2465 -3633 28 4 v 32 w(MCP)p 2708 3633 V 32 w(ADD)29 b(whic)m(h)e(adds)f(a)i -(new)f(en)m(try)227 3746 y(in)d(gfptr)g(for)f(the)i(copied)f(mem)m(b)s -(er)g(HDU,)h(OPT)p 1907 3746 V 31 w(MCP)p 2149 3746 V -33 w(NADD)g(whic)m(h)f(do)s(es)g(not)g(add)f(an)h(en)m(try)h(in)e -(gfptr)227 3859 y(for)i(the)h(copied)f(mem)m(b)s(er,)h(and)f(OPT)p -1536 3859 V 32 w(MCP)p 1779 3859 V 32 w(REPL)g(whic)m(h)g(replaces)h -(the)f(original)h(mem)m(b)s(er)f(en)m(try)g(with)227 -3972 y(the)31 b(copied)g(mem)m(b)s(er)e(en)m(try)-8 b(.)95 -4249 y Fe(int)47 b(fits_copy_member)d(/)j(ffgmcp)286 -4362 y(\(fitsfile)f(*gfptr,)f(fitsfile)h(*mfptr,)g(long)g(member,)g -(int)h(cpopt,)f(>)i(int)f(*status\))0 4639 y Fi(5)81 -b Fj(T)-8 b(ransfer)34 b(a)i(group)f(mem)m(b)s(er)f(HDU)i(from)f(the)h -(grouping)f(table)h(p)s(oin)m(ted)f(to)h(b)m(y)f(infptr)g(to)h(the)f -(grouping)227 4752 y(table)i(p)s(oin)m(ted)f(to)h(b)m(y)f(outfptr.)58 -b(The)35 b(mem)m(b)s(er)h(HDU)h(to)f(transfer)g(is)g(iden)m(ti\014ed)g -(b)m(y)g(its)h(ro)m(w)f(n)m(um)m(b)s(er)227 4865 y(within)42 -b(infptr)f(as)i(sp)s(eci\014ed)f(b)m(y)g(the)h(parameter)g('mem)m(b)s -(er')f(\(\014rst)g(mem)m(b)s(er)g(==)f(1\).)78 b(If)42 -b(tfopt)h(==)227 4978 y(OPT)p 431 4978 V 32 w(MCP)p 674 -4978 V 33 w(ADD)26 b(then)f(the)h(mem)m(b)s(er)e(HDU)i(is)g(made)f(a)h -(mem)m(b)s(er)f(of)g(outfptr)g(and)g(remains)g(a)h(mem)m(b)s(er)227 -5091 y(of)34 b(infptr.)51 b(If)34 b(tfopt)g(==)g(OPT)p -1339 5091 V 32 w(MCP)p 1582 5091 V 32 w(MO)m(V)h(then)f(the)g(mem)m(b)s -(er)f(HDU)i(is)f(deleted)h(from)e(infptr)g(after)227 -5204 y(the)e(transfer)f(to)h(outfptr.)95 5480 y Fe(int)47 -b(fits_transfer_member)c(/)k(ffgmtf)286 5593 y(\(fitsfile)f(*infptr,)f -(fitsfile)h(*outfptr,)f(long)i(member,)e(int)i(tfopt,)334 -5706 y(>)h(int)e(*status\))p eop end -%%Page: 94 102 -TeXDict begin 94 101 bop 0 299 a Fj(94)1338 b Fh(CHAPTER)29 -b(8.)112 b(HIERAR)m(CHICAL)30 b(GR)m(OUPING)h(R)m(OUTINES)0 -555 y Fi(6)81 b Fj(Remo)m(v)m(e)31 b(a)e(mem)m(b)s(er)g(HDU)h(from)f -(the)h(grouping)f(table)h(p)s(oin)m(ted)f(to)h(b)m(y)g(gfptr.)40 -b(The)29 b(mem)m(b)s(er)f(HDU)i(to)h(b)s(e)227 668 y(deleted)37 -b(is)e(iden)m(ti\014ed)h(b)m(y)f(its)h(ro)m(w)g(n)m(um)m(b)s(er)f(in)g -(the)h(grouping)f(table)h(as)g(sp)s(eci\014ed)f(b)m(y)h(the)f -(parameter)227 781 y('mem)m(b)s(er')41 b(\(\014rst)g(mem)m(b)s(er)g(==) -f(1\).)74 b(The)41 b(rmopt)g(parameter)h(ma)m(y)f(tak)m(e)i(on)e(the)h -(follo)m(wing)g(v)-5 b(alues:)227 894 y(OPT)p 431 894 -28 4 v 32 w(RM)p 613 894 V 33 w(ENTR)d(Y)34 b(whic)m(h)e(remo)m(v)m(es) -j(the)e(mem)m(b)s(er)g(HDU)h(en)m(try)f(from)g(the)g(grouping)g(table)h -(and)f(up-)227 1007 y(dates)40 b(the)f(mem)m(b)s(er's)f(GRPIDn/GRPLCn)g -(k)m(eyw)m(ords,)k(and)c(OPT)p 2687 1007 V 32 w(RM)p -2869 1007 V 33 w(MBR)h(whic)m(h)g(remo)m(v)m(es)h(the)227 -1120 y(mem)m(b)s(er)30 b(HDU)h(en)m(try)g(from)f(the)g(grouping)g -(table)i(and)d(deletes)j(the)e(mem)m(b)s(er)g(HDU)h(itself.)95 -1380 y Fe(int)47 b(fits_remove_member)c(/)48 b(ffgmrm)286 -1492 y(\(fitsfile)e(*fptr,)g(long)g(member,)g(int)h(rmopt,)f(>)i(int)f -(*status\))p eop end -%%Page: 95 103 -TeXDict begin 95 102 bop 0 1225 a Fg(Chapter)65 b(9)0 -1687 y Fm(Sp)6 b(ecialized)77 b(CFITSIO)f(In)-6 b(terface)0 -1937 y(Routines)0 2429 y Fj(The)28 b(basic)h(in)m(terface)i(routines)e -(describ)s(ed)e(previously)i(are)g(recommended)f(for)h(most)g(uses,)g -(but)f(the)h(routines)0 2542 y(describ)s(ed)h(in)g(this)h(c)m(hapter)g -(are)h(also)f(a)m(v)-5 b(ailable)34 b(if)c(necessary)-8 -b(.)43 b(Some)31 b(of)g(these)g(routines)g(p)s(erform)e(more)i(sp)s(e-) -0 2655 y(cialized)e(function)d(that)i(cannot)f(easily)h(b)s(e)e(done)h -(with)f(the)h(basic)h(in)m(terface)g(routines)f(while)f(others)h -(duplicate)0 2767 y(the)j(functionalit)m(y)i(of)e(the)g(basic)h -(routines)f(but)f(ha)m(v)m(e)i(a)g(sligh)m(tly)g(di\013eren)m(t)g -(calling)g(sequence.)41 b(See)31 b(App)s(endix)0 2880 -y(B)g(for)f(the)g(de\014nition)g(of)h(eac)m(h)h(function)e(parameter.)0 -3210 y Ff(9.1)135 b(FITS)44 b(File)i(Access)e(Routines)0 -3446 y Fi(1)81 b Fj(Op)s(en)37 b(an)i(existing)i(FITS)d(\014le)h -(residing)g(in)g(core)h(computer)f(memory)-8 b(.)68 b(This)38 -b(routine)h(is)h(analogous)g(to)227 3559 y(\014ts)p 354 -3559 28 4 v 33 w(op)s(en)p 577 3559 V 32 w(\014le.)55 -b(The)35 b('\014lename')g(is)g(curren)m(tly)h(ignored)f(b)m(y)g(this)g -(routine)g(and)g(ma)m(y)g(b)s(e)g(an)m(y)g(arbitrary)227 -3672 y(string.)78 b(In)42 b(general,)47 b(the)c(application)h(m)m(ust)f -(ha)m(v)m(e)h(preallo)s(cated)g(an)e(initial)i(blo)s(c)m(k)g(of)f -(memory)f(to)227 3785 y(hold)i(the)h(FITS)f(\014le)h(prior)f(to)h -(calling)h(this)e(routine:)70 b('memptr')44 b(p)s(oin)m(ts)g(to)i(the)e -(starting)i(address)227 3898 y(and)39 b('memsize')i(giv)m(es)g(the)f -(initial)h(size)f(of)g(the)g(blo)s(c)m(k)g(of)g(memory)-8 -b(.)69 b('mem)p 2958 3898 V 33 w(reallo)s(c')41 b(is)f(a)g(p)s(oin)m -(ter)f(to)227 4011 y(an)c(optional)i(function)d(that)i(CFITSIO)e(can)h -(call)h(to)g(allo)s(cate)i(additional)e(memory)-8 b(,)37 -b(if)e(needed)f(\(only)227 4124 y(if)41 b(mo)s(de)e(=)h(READ)m -(WRITE\),)i(and)e(is)g(mo)s(deled)g(after)h(the)f(standard)g(C)g -('reallo)s(c')i(function;)j(a)c(n)m(ull)227 4237 y(p)s(oin)m(ter)g(ma)m -(y)g(b)s(e)f(giv)m(en)i(if)e(the)h(initial)h(allo)s(cation)h(of)e -(memory)f(is)h(all)g(that)g(will)g(b)s(e)f(required)g(\(e.g.,)227 -4350 y(if)35 b(the)g(\014le)g(is)g(op)s(ened)f(with)h(mo)s(de)f(=)h -(READONL)-8 b(Y\).)36 b(The)e('deltasize')j(parameter)e(ma)m(y)h(b)s(e) -e(used)g(to)227 4463 y(suggest)g(a)f(minim)m(um)f(amoun)m(t)h(of)g -(additional)h(memory)f(that)g(should)f(b)s(e)g(allo)s(cated)j(during)d -(eac)m(h)i(call)227 4575 y(to)d(the)f(memory)f(reallo)s(cation)j -(function.)40 b(By)30 b(default,)g(CFITSIO)e(will)i(reallo)s(cate)j -(enough)c(additional)227 4688 y(space)44 b(to)g(hold)f(the)h(en)m(tire) -g(curren)m(tly)f(de\014ned)g(FITS)f(\014le)i(\(as)f(giv)m(en)i(b)m(y)e -(the)h(NAXISn)e(k)m(eyw)m(ords\))227 4801 y(or)g(1)f(FITS)g(blo)s(c)m -(k)h(\(=)f(2880)i(b)m(ytes\),)i(whic)m(h)d(ev)m(er)g(is)f(larger.)74 -b(V)-8 b(alues)43 b(of)e(deltasize)i(less)f(than)f(2880)227 -4914 y(will)31 b(b)s(e)f(ignored.)42 b(Since)31 b(the)g(memory)g -(reallo)s(cation)i(op)s(eration)e(can)g(b)s(e)f(computationally)i(exp)s -(ensiv)m(e,)227 5027 y(allo)s(cating)27 b(a)e(larger)g(initial)h(blo)s -(c)m(k)f(of)g(memory)-8 b(,)26 b(and/or)f(sp)s(ecifying)f(a)h(larger)h -(deltasize)g(v)-5 b(alue)25 b(ma)m(y)g(help)227 5140 -y(to)i(reduce)f(the)g(n)m(um)m(b)s(er)e(of)i(reallo)s(cation)i(calls)f -(and)f(mak)m(e)h(the)f(application)h(program)f(run)e(faster.)40 -b(Note)227 5253 y(that)29 b(v)-5 b(alues)29 b(of)f(the)h(memptr)f(and)f -(memsize)j(p)s(oin)m(ters)e(will)h(b)s(e)e(up)s(dated)g(b)m(y)i -(CFITSIO)d(if)j(the)f(lo)s(cation)227 5366 y(or)j(size)g(of)f(the)h -(FITS)f(\014le)g(in)g(memory)g(should)g(c)m(hange)h(as)g(a)g(result)f -(of)g(allo)s(cating)j(more)e(memory)-8 b(.)95 5601 y -Fe(int)47 b(fits_open_memfile)c(/)48 b(ffomem)286 5714 -y(\(fitsfile)e(**fptr,)f(const)i(char)f(*filename,)f(int)i(mode,)g -(void)f(**memptr,)1905 5942 y Fj(95)p eop end -%%Page: 96 104 -TeXDict begin 96 103 bop 0 299 a Fj(96)1003 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)334 555 y Fe(size_t)46 b(*memsize,)f(size_t)i(deltasize,) -334 668 y(void)g(*\(*mem_realloc\)\(void)42 b(*p,)47 -b(size_t)f(newsize\),)f(int)i(*status\))0 927 y Fi(2)81 -b Fj(Create)49 b(a)g(new)f(FITS)g(\014le)h(residing)f(in)h(core)g -(computer)g(memory)-8 b(.)96 b(This)48 b(routine)g(is)h(analogous)h(to) -227 1040 y(\014ts)p 354 1040 28 4 v 33 w(create)p 623 -1040 V 34 w(\014le.)40 b(In)29 b(general,)i(the)e(application)h(m)m -(ust)f(ha)m(v)m(e)i(preallo)s(cated)g(an)e(initial)h(blo)s(c)m(k)g(of)f -(memory)227 1152 y(to)38 b(hold)e(the)h(FITS)f(\014le)h(prior)f(to)h -(calling)i(this)d(routine:)54 b('memptr')36 b(p)s(oin)m(ts)h(to)g(the)g -(starting)h(address)227 1265 y(and)h('memsize')i(giv)m(es)g(the)f -(initial)h(size)f(of)g(the)g(blo)s(c)m(k)g(of)g(memory)-8 -b(.)69 b('mem)p 2958 1265 V 33 w(reallo)s(c')41 b(is)f(a)g(p)s(oin)m -(ter)f(to)227 1378 y(an)f(optional)g(function)f(that)h(CFITSIO)e(can)i -(call)h(to)f(allo)s(cate)i(additional)e(memory)-8 b(,)40 -b(if)d(needed,)j(and)227 1491 y(is)34 b(mo)s(deled)f(after)h(the)g -(standard)f(C)g('reallo)s(c')i(function;)g(a)f(n)m(ull)f(p)s(oin)m(ter) -h(ma)m(y)g(b)s(e)f(giv)m(en)h(if)g(the)g(initial)227 -1604 y(allo)s(cation)i(of)d(memory)g(is)h(all)g(that)g(will)f(b)s(e)g -(required.)48 b(The)33 b('deltasize')j(parameter)d(ma)m(y)h(b)s(e)f -(used)f(to)227 1717 y(suggest)i(a)f(minim)m(um)f(amoun)m(t)h(of)g -(additional)h(memory)f(that)g(should)f(b)s(e)g(allo)s(cated)j(during)d -(eac)m(h)i(call)227 1830 y(to)d(the)f(memory)f(reallo)s(cation)j -(function.)40 b(By)30 b(default,)g(CFITSIO)e(will)i(reallo)s(cate)j -(enough)c(additional)227 1943 y(space)41 b(to)g(hold)e(1)i(FITS)e(blo)s -(c)m(k)h(\(=)g(2880)i(b)m(ytes\))f(and)e(v)-5 b(alues)41 -b(of)f(deltasize)h(less)g(than)f(2880)h(will)g(b)s(e)227 -2056 y(ignored.)f(Since)28 b(the)f(memory)h(reallo)s(cation)i(op)s -(eration)e(can)g(b)s(e)f(computationally)i(exp)s(ensiv)m(e,)g(allo)s -(cat-)227 2169 y(ing)36 b(a)f(larger)h(initial)h(blo)s(c)m(k)e(of)h -(memory)-8 b(,)37 b(and/or)e(sp)s(ecifying)g(a)h(larger)g(deltasize)h -(v)-5 b(alue)36 b(ma)m(y)f(help)g(to)227 2282 y(reduce)f(the)g(n)m(um)m -(b)s(er)e(of)i(reallo)s(cation)i(calls)f(and)e(mak)m(e)i(the)f -(application)h(program)f(run)e(faster.)52 b(Note)227 -2395 y(that)29 b(v)-5 b(alues)29 b(of)f(the)h(memptr)f(and)f(memsize)j -(p)s(oin)m(ters)e(will)h(b)s(e)e(up)s(dated)g(b)m(y)i(CFITSIO)d(if)j -(the)f(lo)s(cation)227 2507 y(or)j(size)g(of)f(the)h(FITS)f(\014le)g -(in)g(memory)g(should)g(c)m(hange)h(as)g(a)g(result)f(of)g(allo)s -(cating)j(more)e(memory)-8 b(.)95 2766 y Fe(int)47 b -(fits_create_memfile)c(/)k(ffimem)286 2879 y(\(fitsfile)f(**fptr,)f -(void)i(**memptr,)334 2992 y(size_t)f(*memsize,)f(size_t)i(deltasize,) -334 3105 y(void)g(*\(*mem_realloc\)\(void)42 b(*p,)47 -b(size_t)f(newsize\),)f(int)i(*status\))0 3363 y Fi(3)81 -b Fj(Reop)s(en)34 b(a)i(FITS)e(\014le)h(that)h(w)m(as)f(previously)g -(op)s(ened)g(with)f(\014ts)p 2414 3363 V 33 w(op)s(en)p -2637 3363 V 32 w(\014le)h(or)g(\014ts)p 3058 3363 V 33 -w(create)p 3327 3363 V 34 w(\014le.)55 b(The)34 b(new)227 -3476 y(\014ts\014le)i(p)s(oin)m(ter)h(ma)m(y)g(then)f(b)s(e)f(treated)j -(as)e(a)h(separate)g(\014le,)h(and)e(one)h(ma)m(y)g(sim)m(ultaneously)g -(read)f(or)227 3589 y(write)e(to)h(2)f(\(or)g(more\))g(di\013eren)m(t)g -(extensions)g(in)g(the)g(same)g(\014le.)51 b(The)33 b(\014ts)p -2886 3589 V 32 w(op)s(en)p 3108 3589 V 32 w(\014le)h(routine)g(\(ab)s -(o)m(v)m(e\))227 3702 y(automatically)k(detects)f(cases)f(where)e(a)i -(previously)f(op)s(ened)f(\014le)i(is)f(b)s(eing)g(op)s(ened)f(again,)k -(and)c(then)227 3815 y(in)m(ternally)e(call)f(\014ts)p -930 3815 V 33 w(reop)s(en)p 1229 3815 V 32 w(\014le,)g(so)f(programs)g -(should)g(rarely)g(need)g(to)h(explicitly)h(call)g(this)e(routine.)95 -4073 y Fe(int)47 b(fits_reopen_file)d(/)j(ffreopen)286 -4186 y(\(fitsfile)f(*openfptr,)f(fitsfile)g(**newfptr,)g(>)j(int)f -(*status\))0 4445 y Fi(4)81 b Fj(Create)24 b(a)g(new)f(FITS)g(\014le,)i -(using)e(a)h(template)h(\014le)e(to)i(de\014ne)d(its)i(initial)h(size)g -(and)e(structure.)37 b(The)24 b(template)227 4558 y(ma)m(y)i(b)s(e)f -(another)g(FITS)g(HDU)h(or)f(an)g(ASCI)s(I)f(template)j(\014le.)39 -b(If)25 b(the)g(input)g(template)h(\014le)g(name)f(p)s(oin)m(ter)227 -4671 y(is)j(n)m(ull,)h(then)e(this)h(routine)f(b)s(eha)m(v)m(es)i(the)f -(same)g(as)g(\014ts)p 2160 4671 V 32 w(create)p 2428 -4671 V 35 w(\014le.)40 b(The)27 b(curren)m(tly)h(supp)s(orted)e(format) -227 4784 y(of)33 b(the)g(ASCI)s(I)e(template)j(\014le)e(is)h(describ)s -(ed)e(under)g(the)i(\014ts)p 2350 4784 V 33 w(parse)p -2591 4784 V 32 w(template)h(routine)f(\(in)f(the)h(general)227 -4897 y(Utilities)g(section\))95 5155 y Fe(int)47 b -(fits_create_template)c(/)k(fftplt)286 5268 y(\(fitsfile)f(**fptr,)f -(char)i(*filename,)e(char)i(*tpltfile)e(>)i(int)g(*status\))0 -5527 y Fi(5)81 b Fj(P)m(arse)31 b(the)f(input)g(\014lename)g(or)g(URL)h -(in)m(to)g(its)g(comp)s(onen)m(t)f(parts,)h(namely:)336 -5714 y Fc(\017)46 b Fj(the)31 b(\014le)f(t)m(yp)s(e)h(\(\014le://,)h -(ftp://,)f(h)m(ttp://,)h(etc\),)p eop end -%%Page: 97 105 -TeXDict begin 97 104 bop 0 299 a Fh(9.1.)72 b(FITS)30 -b(FILE)g(A)m(CCESS)f(R)m(OUTINES)2244 b Fj(97)336 555 -y Fc(\017)46 b Fj(the)31 b(base)f(input)g(\014le)g(name,)336 -702 y Fc(\017)46 b Fj(the)31 b(name)f(of)h(the)f(output)g(\014le)h -(that)g(the)f(input)g(\014le)g(is)h(to)g(b)s(e)e(copied)i(to)g(prior)f -(to)h(op)s(ening,)336 848 y Fc(\017)46 b Fj(the)31 b(HDU)g(or)f -(extension)h(sp)s(eci\014cation,)336 995 y Fc(\017)46 -b Fj(the)31 b(\014ltering)f(sp)s(eci\014er,)336 1141 -y Fc(\017)46 b Fj(the)31 b(binning)e(sp)s(eci\014er,)336 -1288 y Fc(\017)46 b Fj(the)31 b(column)f(sp)s(eci\014er,)336 -1434 y Fc(\017)46 b Fj(and)30 b(the)h(image)g(pixel)g(\014ltering)g(sp) -s(eci\014er.)227 1623 y(A)k(n)m(ull)g(p)s(oin)m(ter)f(\(0\))i(ma)m(y)g -(b)s(e)e(b)s(e)g(sp)s(eci\014ed)g(for)g(an)m(y)h(of)g(the)g(output)g -(string)f(argumen)m(ts)h(that)h(are)f(not)227 1736 y(needed.)52 -b(Null)34 b(strings)g(will)g(b)s(e)g(returned)f(for)h(an)m(y)g(comp)s -(onen)m(ts)g(that)h(are)f(not)h(presen)m(t)f(in)g(the)g(input)227 -1849 y(\014le)28 b(name.)39 b(The)27 b(calling)i(routine)e(m)m(ust)g -(allo)s(cate)j(su\016cien)m(t)d(memory)g(to)h(hold)f(the)g(returned)f -(c)m(haracter)227 1962 y(strings.)52 b(Allo)s(cating)37 -b(the)d(string)g(lengths)h(equal)g(to)g(FLEN)p 2362 1962 -28 4 v 33 w(FILENAME)f(is)g(guaran)m(teed)i(to)f(b)s(e)e(safe.)227 -2075 y(These)d(routines)h(are)f(mainly)h(for)f(in)m(ternal)h(use)f(b)m -(y)h(other)f(CFITSIO)f(routines.)95 2335 y Fe(int)47 -b(fits_parse_input_url)c(/)k(ffiurl)286 2448 y(\(char)g(*filename,)e(>) -i(char)g(*filetype,)e(char)h(*infile,)g(char)h(*outfile,)e(char)334 -2561 y(*extspec,)g(char)i(*filter,)f(char)g(*binspec,)f(char)i -(*colspec,)e(int)i(*status\))95 2787 y(int)g(fits_parse_input_filename) -41 b(/)48 b(ffifile)286 2900 y(\(char)f(*filename,)e(>)i(char)g -(*filetype,)e(char)h(*infile,)g(char)h(*outfile,)e(char)334 -3013 y(*extspec,)g(char)i(*filter,)f(char)g(*binspec,)f(char)i -(*colspec,)e(char)i(*pixspec,)334 3125 y(int)g(*status\))0 -3386 y Fi(6)81 b Fj(P)m(arse)33 b(the)f(input)g(\014lename)h(and)e -(return)h(the)h(HDU)g(n)m(um)m(b)s(er)e(that)i(w)m(ould)f(b)s(e)g(mo)m -(v)m(ed)i(to)f(if)f(the)h(\014le)f(w)m(ere)227 3499 y(op)s(ened)h(with) -g(\014ts)p 878 3499 V 32 w(op)s(en)p 1100 3499 V 32 w(\014le.)49 -b(The)33 b(returned)f(HDU)i(n)m(um)m(b)s(er)e(b)s(egins)h(with)g(1)g -(for)g(the)g(primary)g(arra)m(y)-8 b(,)227 3612 y(so)40 -b(for)f(example,)k(if)c(the)h(input)e(\014lename)i(=)f(`m)m -(y\014le.\014ts[2]')i(then)e(hdun)m(um)e(=)i(3)h(will)g(b)s(e)f -(returned.)227 3725 y(CFITSIO)j(do)s(es)i(not)g(op)s(en)f(the)g(\014le) -h(to)h(c)m(hec)m(k)g(if)e(the)h(extension)h(actually)g(exists)f(if)g -(an)f(extension)227 3838 y(n)m(um)m(b)s(er)e(is)i(sp)s(eci\014ed.)75 -b(If)42 b(an)g(extension)h(name)f(is)h(included)e(in)h(the)h(\014le)f -(name)g(sp)s(eci\014cation)h(\(e.g.)227 3951 y(`m)m -(y\014le.\014ts[EVENTS]')i(then)e(this)h(routine)g(will)h(ha)m(v)m(e)g -(to)f(op)s(en)g(the)g(FITS)f(\014le)h(and)f(lo)s(ok)i(for)f(the)227 -4064 y(p)s(osition)31 b(of)f(the)h(named)f(extension,)i(then)e(close)i -(\014le)e(again.)42 b(This)30 b(is)g(not)h(p)s(ossible)f(if)h(the)f -(\014le)h(is)f(b)s(eing)227 4176 y(read)k(from)f(the)h(stdin)f(stream,) -i(and)f(an)f(error)g(will)i(b)s(e)e(returned)f(in)i(this)f(case.)52 -b(If)33 b(the)h(\014lename)g(do)s(es)227 4289 y(not)42 -b(sp)s(ecify)g(an)g(explicit)h(extension)g(\(e.g.)76 -b('m)m(y\014le.\014ts'\))43 b(then)f(hdun)m(um)e(=)h(-99)i(will)g(b)s -(e)e(returned,)227 4402 y(whic)m(h)35 b(is)g(functionally)h(equiv)-5 -b(alen)m(t)36 b(to)g(hdun)m(um)d(=)h(1.)55 b(This)34 -b(routine)h(is)g(mainly)h(used)e(for)g(bac)m(kw)m(ard)227 -4515 y(compatibilit)m(y)39 b(in)e(the)f(fto)s(ols)i(soft)m(w)m(are)g -(pac)m(k)-5 b(age)39 b(and)d(is)g(not)h(recommended)g(for)f(general)i -(use.)59 b(It)37 b(is)227 4628 y(generally)k(b)s(etter)e(and)g(more)g -(e\016cien)m(t)i(to)f(\014rst)e(op)s(en)h(the)g(FITS)g(\014le)g(with)g -(\014ts)p 3125 4628 V 32 w(op)s(en)p 3347 4628 V 33 w(\014le,)i(then)e -(use)227 4741 y(\014ts)p 354 4741 V 33 w(get)p 507 4741 -V 34 w(hdu)p 694 4741 V 31 w(n)m(um)c(to)i(determine)g(whic)m(h)f(HDU)h -(in)f(the)h(\014le)f(has)g(b)s(een)g(op)s(ened,)h(rather)f(than)g -(calling)227 4854 y(\014ts)p 354 4854 V 33 w(parse)p -595 4854 V 32 w(input)p 840 4854 V 32 w(url)30 b(follo)m(w)m(ed)i(b)m -(y)e(a)h(call)g(to)h(\014ts)p 1967 4854 V 32 w(op)s(en)p -2189 4854 V 32 w(\014le.)143 5115 y Fe(int)47 b(fits_parse_extnum)c(/) -48 b(ffextn)334 5227 y(\(char)e(*filename,)f(>)j(int)f(*hdunum,)e(int)i -(*status\))0 5488 y Fi(7)81 b Fj(P)m(arse)45 b(the)g(input)e(\014le)i -(name)g(and)f(return)f(the)i(ro)s(ot)g(\014le)g(name.)83 -b(The)44 b(ro)s(ot)h(name)g(includes)f(the)h(\014le)227 -5601 y(t)m(yp)s(e)35 b(if)g(sp)s(eci\014ed,)h(\(e.g.)56 -b('ftp://')37 b(or)e('h)m(ttp://'\))i(and)d(the)h(full)g(path)g(name,)h -(to)g(the)f(exten)m(t)i(that)e(it)h(is)227 5714 y(sp)s(eci\014ed)26 -b(in)f(the)i(input)e(\014lename.)39 b(It)26 b(do)s(es)g(not)g(include)g -(the)g(HDU)h(name)f(or)g(n)m(um)m(b)s(er,)g(or)g(an)m(y)h(\014ltering)p -eop end -%%Page: 98 106 -TeXDict begin 98 105 bop 0 299 a Fj(98)1003 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)227 555 y Fj(sp)s(eci\014cations.)86 b(The)45 -b(calling)h(routine)g(m)m(ust)f(allo)s(cate)i(su\016cien)m(t)f(memory)f -(to)h(hold)f(the)g(returned)227 668 y(ro)s(otname)33 -b(c)m(haracter)g(string.)46 b(Allo)s(cating)34 b(the)f(length)f(equal)h -(to)f(FLEN)p 2817 668 28 4 v 33 w(FILENAME)h(is)f(guaran)m(teed)227 -781 y(to)f(b)s(e)f(safe.)143 1019 y Fe(int)47 b(fits_parse_rootname)c -(/)k(ffrtnm)334 1132 y(\(char)f(*filename,)f(>)j(char)f(*rootname,)e -(int)h(*status\);)0 1370 y Fi(8)81 b Fj(T)-8 b(est)37 -b(if)f(the)h(input)f(\014le)h(or)f(a)h(compressed)g(v)m(ersion)g(of)g -(the)g(\014le)f(\(with)h(a)g(.gz,)j(.Z,)c(.z,)j(or)e(.zip)g -(extension\))227 1483 y(exists)i(on)f(disk.)63 b(The)37 -b(returned)g(v)-5 b(alue)38 b(of)g(the)h('exists')g(parameter)f(will)g -(ha)m(v)m(e)i(1)e(of)g(the)g(4)g(follo)m(wing)227 1596 -y(v)-5 b(alues:)370 1820 y Fe(2:)95 b(the)47 b(file)g(does)g(not)f -(exist,)h(but)f(a)i(compressed)d(version)h(does)g(exist)370 -1933 y(1:)95 b(the)47 b(disk)g(file)g(does)f(exist)370 -2046 y(0:)95 b(neither)46 b(the)h(file)g(nor)g(a)g(compressed)e -(version)h(of)h(the)g(file)g(exist)323 2159 y(-1:)94 -b(the)47 b(input)g(file)f(name)h(is)g(not)g(a)g(disk)g(file)g(\(could)f -(be)h(a)g(ftp,)g(http,)561 2272 y(smem,)g(or)g(mem)g(file,)f(or)h(a)h -(file)e(piped)h(in)g(on)g(the)g(STDIN)f(stream\))143 -2587 y(int)h(fits_file_exists)c(/)48 b(ffexist)334 2700 -y(\(char)e(*filename,)f(>)j(int)f(*exists,)e(int)i(*status\);)0 -2938 y Fi(9)81 b Fj(Flush)36 b(an)m(y)i(in)m(ternal)g(bu\013ers)e(of)i -(data)g(to)g(the)f(output)g(FITS)g(\014le.)62 b(These)37 -b(routines)g(rarely)g(need)g(to)i(b)s(e)227 3051 y(called,)i(but)36 -b(can)i(b)s(e)f(useful)f(in)h(cases)i(where)d(other)i(pro)s(cesses)f -(need)g(to)h(access)h(the)f(same)f(FITS)g(\014le)227 -3164 y(in)j(real)i(time,)h(either)e(on)g(disk)f(or)g(in)g(memory)-8 -b(.)71 b(These)41 b(routines)f(also)h(help)f(to)i(ensure)d(that)i(if)g -(the)227 3277 y(application)c(program)d(subsequen)m(tly)h(ab)s(orts)f -(then)h(the)g(FITS)f(\014le)h(will)g(ha)m(v)m(e)i(b)s(een)d(closed)h -(prop)s(erly)-8 b(.)227 3390 y(The)43 b(\014rst)g(routine,)k(\014ts)p -1110 3390 V 33 w(\015ush)p 1332 3390 V 31 w(\014le)c(is)h(more)f -(rigorous)h(and)f(completely)i(closes,)j(then)c(reop)s(ens,)i(the)227 -3503 y(curren)m(t)31 b(HDU,)h(b)s(efore)e(\015ushing)g(the)h(in)m -(ternal)g(bu\013ers,)f(th)m(us)h(ensuring)f(that)h(the)g(output)g(FITS) -f(\014le)h(is)227 3615 y(iden)m(tical)38 b(to)e(what)f(w)m(ould)h(b)s -(e)f(pro)s(duced)f(if)h(the)h(FITS)f(w)m(as)h(closed)g(at)g(that)g(p)s -(oin)m(t)g(\(i.e.,)i(with)e(a)g(call)227 3728 y(to)g(\014ts)p -470 3728 V 33 w(close)p 689 3728 V 34 w(\014le\).)56 -b(The)35 b(second)g(routine,)i(\014ts)p 1912 3728 V 33 -w(\015ush)p 2134 3728 V 31 w(bu\013er)d(simply)h(\015ushes)f(the)h(in)m -(ternal)h(CFITSIO)227 3841 y(bu\013ers)28 b(of)h(data)h(to)f(the)h -(output)e(FITS)g(\014le,)i(without)f(up)s(dating)f(and)g(closing)i(the) -f(curren)m(t)g(HDU.)h(This)227 3954 y(is)37 b(m)m(uc)m(h)g(faster,)i -(but)e(there)g(ma)m(y)g(b)s(e)f(circumstances)i(where)e(the)h -(\015ushed)f(\014le)h(do)s(es)f(not)h(completely)227 -4067 y(re\015ect)31 b(the)g(\014nal)f(state)i(of)e(the)h(\014le)f(as)h -(it)g(will)f(exist)i(when)d(the)h(\014le)h(is)f(actually)i(closed.)227 -4214 y(A)f(t)m(ypical)h(use)e(of)h(these)g(routines)f(w)m(ould)g(b)s(e) -g(to)h(\015ush)e(the)h(state)i(of)f(a)g(FITS)e(table)j(to)f(disk)f -(after)h(eac)m(h)227 4327 y(ro)m(w)36 b(of)f(the)h(table)g(is)f -(written.)55 b(It)36 b(is)f(recommend)g(that)h(\014ts)p -2392 4327 V 32 w(\015ush)p 2613 4327 V 32 w(\014le)f(b)s(e)g(called)h -(after)g(the)f(\014rst)g(ro)m(w)227 4440 y(is)k(written,)i(then)d -(\014ts)p 1023 4440 V 32 w(\015ush)p 1244 4440 V 31 w(bu\013er)g(ma)m -(y)h(b)s(e)f(called)h(after)g(eac)m(h)h(subsequen)m(t)e(ro)m(w)g(is)h -(written.)65 b(Note)227 4552 y(that)40 b(this)f(latter)h(routine)f -(will)g(not)g(automatically)j(up)s(date)c(the)h(NAXIS2)g(k)m(eyw)m(ord) -h(whic)m(h)e(records)227 4665 y(the)c(n)m(um)m(b)s(er)d(of)i(ro)m(ws)h -(of)f(data)g(in)g(the)g(table,)i(so)f(this)f(k)m(eyw)m(ord)g(m)m(ust)g -(b)s(e)f(explicitly)j(up)s(dated)d(b)m(y)h(the)227 4778 -y(application)f(program)e(after)h(eac)m(h)h(ro)m(w)e(is)g(written.)95 -5016 y Fe(int)47 b(fits_flush_file)d(/)j(ffflus)286 5129 -y(\(fitsfile)f(*fptr,)g(>)h(int)g(*status\))95 5355 y(int)g -(fits_flush_buffer)c(/)48 b(ffflsh)286 5468 y(\(fitsfile)e(*fptr,)g(0,) -h(>)g(int)g(*status\))286 5694 y(\(Note:)94 b(The)47 -b(second)f(argument)g(must)g(be)i(0\).)p eop end -%%Page: 99 107 -TeXDict begin 99 106 bop 0 299 a Fh(9.2.)72 b(HDU)31 -b(A)m(CCESS)e(R)m(OUTINES)2488 b Fj(99)0 555 y Ff(9.2)135 -b(HDU)46 b(Access)e(Routines)0 795 y Fi(1)81 b Fj(Get)28 -b(the)f(b)m(yte)h(o\013sets)g(in)f(the)g(FITS)f(\014le)i(to)f(the)h -(start)g(of)f(the)g(header)g(and)g(the)g(start)h(and)e(end)h(of)g(the)g -(data)227 908 y(in)34 b(the)g(CHDU.)g(The)f(di\013erence)h(b)s(et)m(w)m -(een)h(headstart)f(and)f(dataend)h(equals)g(the)g(size)g(of)g(the)g -(CHDU.)227 1021 y(If)e(the)h(CHDU)f(is)h(the)f(last)h(HDU)g(in)f(the)h -(\014le,)g(then)f(dataend)g(is)g(also)i(equal)e(to)h(the)g(size)g(of)g -(the)f(en)m(tire)227 1133 y(FITS)i(\014le.)55 b(Null)35 -b(p)s(oin)m(ters)g(ma)m(y)g(b)s(e)f(input)g(for)h(an)m(y)g(of)g(the)g -(address)f(parameters)i(if)e(their)h(v)-5 b(alues)36 -b(are)227 1246 y(not)31 b(needed.)95 1502 y Fe(int)47 -b(fits_get_hduaddr)d(/)j(ffghad)94 b(\(only)46 b(supports)g(files)g(up) -h(to)h(2.1)f(GB)g(in)g(size\))334 1615 y(\(fitsfile)e(*fptr,)h(>)i -(long)f(*headstart,)d(long)j(*datastart,)e(long)h(*dataend,)382 -1728 y(int)h(*status\))95 1953 y(int)g(fits_get_hduaddrll)c(/)48 -b(ffghadll)93 b(\(supports)45 b(large)i(files\))334 2066 -y(\(fitsfile)e(*fptr,)h(>)i(LONGLONG)d(*headstart,)g(LONGLONG)h -(*datastart,)382 2179 y(LONGLONG)f(*dataend,)h(int)h(*status\))0 -2434 y Fi(2)81 b Fj(Create)31 b(\(app)s(end\))f(a)i(new)e(empt)m(y)i -(HDU)f(at)h(the)f(end)f(of)i(the)f(FITS)f(\014le.)42 -b(This)31 b(is)g(no)m(w)g(the)g(CHDU)g(but)f(it)227 2547 -y(is)i(completely)g(empt)m(y)g(and)f(has)g(no)g(header)g(k)m(eyw)m -(ords.)43 b(It)32 b(is)f(recommended)g(that)h(\014ts)p -3344 2547 28 4 v 32 w(create)p 3612 2547 V 34 w(img)g(or)227 -2660 y(\014ts)p 354 2660 V 33 w(create)p 623 2660 V 34 -w(tbl)e(b)s(e)g(used)g(instead)g(of)h(this)f(routine.)95 -2916 y Fe(int)47 b(fits_create_hdu)d(/)j(ffcrhd)286 3028 -y(\(fitsfile)f(*fptr,)g(>)h(int)g(*status\))0 3284 y -Fi(3)81 b Fj(Insert)22 b(a)h(new)g(IMA)m(GE)h(extension)f(immediately)i -(follo)m(wing)f(the)f(CHDU,)h(or)f(insert)g(a)g(new)f(Primary)h(Arra)m -(y)227 3397 y(at)30 b(the)e(b)s(eginning)g(of)h(the)g(\014le.)40 -b(An)m(y)29 b(follo)m(wing)h(extensions)f(in)g(the)f(\014le)h(will)g(b) -s(e)f(shifted)g(do)m(wn)h(to)g(mak)m(e)227 3510 y(ro)s(om)36 -b(for)h(the)f(new)g(extension.)59 b(If)36 b(the)h(CHDU)g(is)f(the)h -(last)g(HDU)g(in)f(the)h(\014le)f(then)g(the)h(new)f(image)227 -3623 y(extension)31 b(will)g(simply)e(b)s(e)h(app)s(ended)e(to)j(the)f -(end)g(of)g(the)g(\014le.)41 b(One)30 b(can)g(force)h(a)g(new)e -(primary)g(arra)m(y)227 3735 y(to)35 b(b)s(e)d(inserted)i(at)g(the)g(b) -s(eginning)f(of)g(the)h(FITS)f(\014le)g(b)m(y)h(setting)h(status)e(=)h -(PREPEND)p 3432 3735 V 32 w(PRIMAR)-8 b(Y)227 3848 y(prior)25 -b(to)g(calling)i(the)e(routine.)38 b(In)25 b(this)f(case)i(the)f(old)g -(primary)f(arra)m(y)i(will)f(b)s(e)f(con)m(v)m(erted)j(to)e(an)g(IMA)m -(GE)227 3961 y(extension.)49 b(The)32 b(new)g(extension)i(\(or)f -(primary)f(arra)m(y\))h(will)h(b)s(ecome)f(the)g(CHDU.)g(Refer)g(to)h -(Chapter)227 4074 y(9)d(for)f(a)h(list)g(of)f(pre-de\014ned)f(bitpix)i -(v)-5 b(alues.)95 4329 y Fe(int)47 b(fits_insert_img)d(/)j(ffiimg)286 -4442 y(\(fitsfile)f(*fptr,)g(int)h(bitpix,)e(int)i(naxis,)f(long)h -(*naxes,)f(>)h(int)g(*status\))95 4668 y(int)g(fits_insert_imgll)c(/)48 -b(ffiimgll)286 4781 y(\(fitsfile)e(*fptr,)g(int)h(bitpix,)e(int)i -(naxis,)f(LONGLONG)g(*naxes,)g(>)h(int)g(*status\))0 -5036 y Fi(4)81 b Fj(Insert)30 b(a)g(new)g(ASCI)s(I)f(or)i(binary)f -(table)h(extension)g(immediately)h(follo)m(wing)g(the)f(CHDU.)g(An)m(y) -f(follo)m(wing)227 5149 y(extensions)36 b(will)g(b)s(e)f(shifted)g(do)m -(wn)g(to)h(mak)m(e)g(ro)s(om)g(for)f(the)g(new)g(extension.)57 -b(If)35 b(there)h(are)f(no)h(other)227 5262 y(follo)m(wing)c -(extensions)g(then)e(the)h(new)f(table)h(extension)h(will)f(simply)f(b) -s(e)g(app)s(ended)f(to)i(the)g(end)f(of)h(the)227 5375 -y(\014le.)42 b(If)30 b(the)h(FITS)f(\014le)g(is)h(curren)m(tly)g(empt)m -(y)g(then)f(this)g(routine)h(will)g(create)h(a)f(dumm)m(y)f(primary)f -(arra)m(y)227 5488 y(b)s(efore)i(app)s(ending)f(the)i(table)h(to)f(it.) -44 b(The)31 b(new)g(extension)i(will)e(b)s(ecome)h(the)g(CHDU.)g(The)f -(tunit)h(and)227 5601 y(extname)39 b(parameters)g(are)f(optional)i(and) -e(a)g(n)m(ull)g(p)s(oin)m(ter)h(ma)m(y)f(b)s(e)g(giv)m(en)h(if)f(they)h -(are)f(not)h(de\014ned.)227 5714 y(When)32 b(inserting)g(an)g(ASCI)s(I) -f(table)i(with)e(\014ts)p 1847 5714 V 33 w(insert)p 2103 -5714 V 33 w(atbl,)i(a)f(n)m(ull)g(p)s(oin)m(ter)g(ma)m(y)h(giv)m(en)g -(for)f(the)g(*tb)s(col)p eop end -%%Page: 100 108 -TeXDict begin 100 107 bop 0 299 a Fj(100)958 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)227 555 y Fj(parameter)23 b(in)f(whic)m(h)h(case)g(eac)m -(h)h(column)e(of)h(the)g(table)g(will)g(b)s(e)f(separated)h(b)m(y)f(a)h -(single)g(space)g(c)m(haracter.)227 668 y(Similarly)-8 -b(,)29 b(if)d(the)h(input)f(v)-5 b(alue)27 b(of)g(ro)m(wlen)g(is)f(0,)i -(then)f(CFITSIO)e(will)i(calculate)i(the)e(default)f(ro)m(wlength)227 -781 y(based)39 b(on)g(the)g(tb)s(col)h(and)e(tt)m(yp)s(e)h(v)-5 -b(alues.)67 b(Under)39 b(normal)g(circumstances,)j(the)d(nro)m(ws)f -(paramen)m(ter)227 894 y(should)31 b(ha)m(v)m(e)i(a)f(v)-5 -b(alue)32 b(of)f(0;)i(CFITSIO)d(will)i(automatically)j(up)s(date)30 -b(the)i(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(as)g(data)g(is)227 -1007 y(written)26 b(to)h(the)f(table.)40 b(When)25 b(inserting)h(a)h -(binary)e(table)h(with)g(\014ts)p 2596 1007 28 4 v 32 -w(insert)p 2851 1007 V 33 w(btbl,)g(if)g(there)g(are)g(follo)m(wing)227 -1120 y(extensions)f(in)f(the)h(\014le)f(and)g(if)g(the)h(table)g(con)m -(tains)g(v)-5 b(ariable)25 b(length)g(arra)m(y)g(columns)f(then)g(p)s -(coun)m(t)g(m)m(ust)227 1233 y(sp)s(ecify)30 b(the)h(exp)s(ected)g -(\014nal)f(size)h(of)f(the)h(data)g(heap,)f(otherwise)h(p)s(coun)m(t)f -(m)m(ust)h(=)f(0.)95 1490 y Fe(int)47 b(fits_insert_atbl)d(/)j(ffitab) -286 1603 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(rowlen,)h(LONGLONG)g -(nrows,)g(int)h(tfields,)e(char)i(*ttype[],)334 1716 -y(long)g(*tbcol,)f(char)g(*tform[],)f(char)i(*tunit[],)e(char)i -(*extname,)e(>)j(int)f(*status\))95 1942 y(int)g(fits_insert_btbl)d(/)j -(ffibin)286 2055 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(nrows,)h(int)h -(tfields,)f(char)g(**ttype,)286 2168 y(char)h(**tform,)f(char)g -(**tunit,)g(char)g(*extname,)g(long)g(pcount,)g(>)i(int)e(*status\))0 -2425 y Fi(5)81 b Fj(Mo)s(dify)27 b(the)h(size,)h(dimensions,)f(and/or)f -(data)i(t)m(yp)s(e)f(of)f(the)h(curren)m(t)g(primary)e(arra)m(y)i(or)g -(image)h(extension.)227 2538 y(If)39 b(the)h(new)e(image,)44 -b(as)39 b(sp)s(eci\014ed)g(b)m(y)g(the)g(input)g(argumen)m(ts,)j(is)d -(larger)h(than)f(the)h(curren)m(t)f(existing)227 2651 -y(image)30 b(in)e(the)g(FITS)g(\014le)g(then)g(zero)h(\014ll)f(data)h -(will)g(b)s(e)f(inserted)g(at)h(the)f(end)g(of)g(the)h(curren)m(t)f -(image)i(and)227 2764 y(an)m(y)35 b(follo)m(wing)h(extensions)f(will)g -(b)s(e)f(mo)m(v)m(ed)i(further)d(bac)m(k)i(in)g(the)f(\014le.)54 -b(Similarly)-8 b(,)36 b(if)f(the)g(new)f(image)227 2877 -y(is)j(smaller)g(than)g(the)f(curren)m(t)h(image)h(then)e(an)m(y)h -(follo)m(wing)h(extensions)f(will)g(b)s(e)f(shifted)h(up)e(to)m(w)m -(ards)227 2990 y(the)h(b)s(eginning)f(of)h(the)g(FITS)f(\014le)h(and)f -(the)h(image)h(data)f(will)h(b)s(e)e(truncated)g(to)i(the)f(new)f -(size.)58 b(This)227 3103 y(routine)27 b(rewrites)g(the)h(BITPIX,)f -(NAXIS,)g(and)f(NAXISn)g(k)m(eyw)m(ords)i(with)f(the)g(appropriate)g(v) --5 b(alues)27 b(for)227 3216 y(the)k(new)f(image.)95 -3473 y Fe(int)47 b(fits_resize_img)d(/)j(ffrsim)286 3586 -y(\(fitsfile)f(*fptr,)g(int)h(bitpix,)e(int)i(naxis,)f(long)h(*naxes,)f -(>)h(int)g(*status\))95 3812 y(int)g(fits_resize_imgll)c(/)48 -b(ffrsimll)286 3925 y(\(fitsfile)e(*fptr,)g(int)h(bitpix,)e(int)i -(naxis,)f(LONGLONG)g(*naxes,)g(>)h(int)g(*status\))0 -4183 y Fi(6)81 b Fj(Cop)m(y)43 b(the)h(data)h(\(and)e(not)h(the)g -(header\))g(from)f(the)h(CHDU)g(asso)s(ciated)h(with)f(infptr)e(to)j -(the)f(CHDU)227 4295 y(asso)s(ciated)34 b(with)e(outfptr.)47 -b(This)32 b(will)g(o)m(v)m(erwrite)i(an)m(y)f(data)g(previously)g(in)f -(the)h(output)f(CHDU.)h(This)227 4408 y(lo)m(w)39 b(lev)m(el)h(routine) -e(is)g(used)f(b)m(y)h(\014ts)p 1510 4408 V 33 w(cop)m(y)p -1724 4408 V 33 w(hdu,)h(but)e(it)i(ma)m(y)f(also)h(b)s(e)f(useful)f(in) -h(certain)h(application)227 4521 y(programs)30 b(that)h(w)m(an)m(t)g -(to)g(cop)m(y)g(the)f(data)h(from)f(one)h(FITS)e(\014le)i(to)g(another) -f(but)f(also)j(w)m(an)m(t)f(to)g(mo)s(dify)227 4634 y(the)h(header)g(k) -m(eyw)m(ords.)46 b(The)32 b(required)f(FITS)g(header)h(k)m(eyw)m(ords)g -(whic)m(h)g(de\014ne)f(the)h(structure)g(of)g(the)227 -4747 y(HDU)f(m)m(ust)g(b)s(e)e(written)i(to)g(the)f(output)g(CHDU)h(b)s -(efore)f(calling)i(this)e(routine.)95 5005 y Fe(int)47 -b(fits_copy_data)d(/)k(ffcpdt)286 5118 y(\(fitsfile)e(*infptr,)f -(fitsfile)h(*outfptr,)f(>)i(int)g(*status\))0 5375 y -Fi(7)81 b Fj(Read)30 b(or)g(write)g(a)h(sp)s(eci\014ed)e(n)m(um)m(b)s -(er)g(of)i(b)m(ytes)f(starting)h(at)g(the)g(sp)s(eci\014ed)e(b)m(yte)i -(o\013set)g(from)f(the)g(start)h(of)227 5488 y(the)c(extension)g(data)f -(unit.)39 b(These)26 b(lo)m(w)h(lev)m(el)h(routine)e(are)h(in)m(tended) -f(mainly)g(for)g(accessing)i(the)e(data)h(in)227 5601 -y(non-standard,)h(conforming)g(extensions,)h(and)e(should)g(not)h(b)s -(e)g(used)f(for)g(standard)g(IMA)m(GE,)i(T)-8 b(ABLE,)227 -5714 y(or)31 b(BINT)-8 b(ABLE)31 b(extensions.)p eop -end -%%Page: 101 109 -TeXDict begin 101 108 bop 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 -b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(101)95 -555 y Fe(int)47 b(fits_read_ext)e(/)i(ffgextn)286 668 -y(\(fitsfile)f(*fptr,)g(LONGLONG)f(offset,)h(LONGLONG)g(nbytes,)f(void) -i(*buffer\))95 781 y(int)g(fits_write_ext)d(/)k(ffpextn)286 -894 y(\(fitsfile)e(*fptr,)g(LONGLONG)f(offset,)h(LONGLONG)g(nbytes,)f -(void)i(*buffer\))0 1158 y Fi(8)81 b Fj(This)34 b(routine)g(forces)h -(CFITSIO)f(to)h(rescan)g(the)g(curren)m(t)g(header)f(k)m(eyw)m(ords)h -(that)g(de\014ne)f(the)h(structure)227 1271 y(of)f(the)f(HDU)h(\(suc)m -(h)g(as)f(the)h(NAXIS)f(and)g(BITPIX)g(k)m(eyw)m(ords\))h(so)f(that)h -(it)g(reinitializes)i(the)d(in)m(ternal)227 1384 y(bu\013ers)26 -b(that)h(describ)s(e)g(the)g(HDU)g(structure.)39 b(This)26 -b(routine)h(is)g(useful)f(for)g(reinitializing)j(the)e(structure)227 -1497 y(of)34 b(an)f(HDU)h(if)f(an)m(y)h(of)g(the)f(required)g(k)m(eyw)m -(ords)g(\(e.g.,)j(NAXISn\))d(ha)m(v)m(e)i(b)s(een)e(mo)s(di\014ed.)48 -b(In)33 b(practice)227 1610 y(it)e(should)e(rarely)h(b)s(e)f(necessary) -h(to)h(call)g(this)f(routine)g(b)s(ecause)f(CFITSIO)g(in)m(ternally)i -(calls)g(it)f(in)g(most)227 1723 y(situations.)95 1987 -y Fe(int)47 b(fits_set_hdustruc)c(/)48 b(ffrdef)286 2100 -y(\(fitsfile)e(*fptr,)g(>)h(int)g(*status\))141 b(\(DEPRECATED\))0 -2439 y Ff(9.3)135 b(Sp)t(ecialized)46 b(Header)g(Keyw)l(ord)f(Routines) -0 2693 y Fd(9.3.1)112 b(Header)38 b(Information)h(Routines)0 -2906 y Fi(1)81 b Fj(Reserv)m(e)29 b(space)g(in)e(the)i(CHU)f(for)g -(MOREKEYS)f(more)h(header)g(k)m(eyw)m(ords.)41 b(This)27 -b(routine)h(ma)m(y)h(b)s(e)f(called)227 3018 y(to)34 -b(allo)s(cate)h(space)e(for)f(additional)i(k)m(eyw)m(ords)f(at)g(the)g -(time)g(the)g(header)f(is)h(created)g(\(prior)g(to)g(writing)227 -3131 y(an)m(y)h(data\).)51 b(CFITSIO)32 b(can)i(dynamically)g(add)f -(more)g(space)h(to)g(the)g(header)f(when)f(needed,)j(ho)m(w)m(ev)m(er) -227 3244 y(it)c(is)g(more)f(e\016cien)m(t)i(to)f(preallo)s(cate)h(the)f -(required)f(space)h(if)f(the)g(size)i(is)e(kno)m(wn)g(in)g(adv)-5 -b(ance.)95 3509 y Fe(int)47 b(fits_set_hdrsize)d(/)j(ffhdef)286 -3621 y(\(fitsfile)f(*fptr,)g(int)h(morekeys,)e(>)i(int)g(*status\))0 -3886 y Fi(2)81 b Fj(Return)26 b(the)h(n)m(um)m(b)s(er)e(of)j(k)m(eyw)m -(ords)f(in)f(the)h(header)g(\(not)h(coun)m(ting)g(the)f(END)g(k)m(eyw)m -(ord\))h(and)e(the)h(curren)m(t)227 3999 y(p)s(osition)34 -b(in)g(the)g(header.)50 b(The)34 b(p)s(osition)f(is)h(the)g(n)m(um)m(b) -s(er)f(of)h(the)g(k)m(eyw)m(ord)g(record)f(that)i(will)f(b)s(e)f(read) -227 4112 y(next)k(\(or)g(one)f(greater)i(than)e(the)h(p)s(osition)f(of) -h(the)g(last)g(k)m(eyw)m(ord)g(that)g(w)m(as)g(read\).)59 -b(A)37 b(v)-5 b(alue)36 b(of)h(1)g(is)227 4224 y(returned)29 -b(if)i(the)f(p)s(oin)m(ter)h(is)f(p)s(ositioned)h(at)g(the)f(b)s -(eginning)g(of)g(the)h(header.)95 4489 y Fe(int)47 b(fits_get_hdrpos)d -(/)j(ffghps)286 4602 y(\(fitsfile)f(*fptr,)g(>)h(int)g(*keysexist,)e -(int)i(*keynum,)e(int)i(*status\))0 4897 y Fd(9.3.2)112 -b(Read)38 b(and)h(W)-9 b(rite)36 b(the)h(Required)h(Keyw)m(ords)0 -5110 y Fi(1)81 b Fj(W)-8 b(rite)34 b(the)f(required)g(extension)h -(header)e(k)m(eyw)m(ords)i(in)m(to)g(the)f(CHU.)h(These)f(routines)g -(are)g(not)g(required,)227 5223 y(and)g(instead)g(the)g(appropriate)g -(header)g(ma)m(y)g(b)s(e)g(constructed)g(b)m(y)g(writing)g(eac)m(h)h -(individual)e(k)m(eyw)m(ord)227 5336 y(in)e(the)h(prop)s(er)e -(sequence.)227 5488 y(The)21 b(simpler)g(\014ts)p 842 -5488 28 4 v 33 w(write)p 1077 5488 V 33 w(imghdr)f(routine)i(is)f -(equiv)-5 b(alen)m(t)23 b(to)f(calling)h(\014ts)p 2727 -5488 V 32 w(write)p 2961 5488 V 33 w(grphdr)d(with)h(the)h(default)227 -5601 y(v)-5 b(alues)37 b(of)f(simple)g(=)g(TR)m(UE,)g(p)s(coun)m(t)g(=) -g(0,)i(gcoun)m(t)f(=)f(1,)i(and)e(extend)g(=)f(TR)m(UE.)i(The)e -(PCOUNT,)227 5714 y(GCOUNT)43 b(and)g(EXTEND)g(k)m(eyw)m(ords)g(are)h -(not)f(required)f(in)h(the)h(primary)e(header)h(and)f(are)i(only)p -eop end -%%Page: 102 110 -TeXDict begin 102 109 bop 0 299 a Fj(102)958 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)227 555 y Fj(written)38 b(if)f(p)s(coun)m(t)g(is)g(not)h -(equal)f(to)i(zero,)h(gcoun)m(t)e(is)f(not)h(equal)g(to)g(zero)g(or)f -(one,)j(and)c(if)i(extend)f(is)227 668 y(TR)m(UE,)k(resp)s(ectiv)m(ely) --8 b(.)74 b(When)41 b(writing)g(to)h(an)e(IMA)m(GE)i(extension,)i(the)e -(SIMPLE)e(and)g(EXTEND)227 781 y(parameters)c(are)f(ignored.)56 -b(It)35 b(is)g(recommended)g(that)h(\014ts)p 2342 781 -28 4 v 32 w(create)p 2610 781 V 35 w(image)g(or)f(\014ts)p -3150 781 V 33 w(create)p 3419 781 V 34 w(tbl)g(b)s(e)g(used)227 -894 y(instead)26 b(of)f(these)h(routines)g(to)g(write)f(the)h(required) -e(header)i(k)m(eyw)m(ords.)39 b(The)25 b(general)h(\014ts)p -3377 894 V 33 w(write)p 3612 894 V 33 w(exthdr)227 1007 -y(routine)31 b(ma)m(y)g(b)s(e)e(used)h(to)h(write)g(the)f(header)g(of)h -(an)m(y)g(conforming)f(FITS)g(extension.)95 1252 y Fe(int)47 -b(fits_write_imghdr)c(/)48 b(ffphps)286 1365 y(\(fitsfile)e(*fptr,)g -(int)h(bitpix,)e(int)i(naxis,)f(long)h(*naxes,)f(>)h(int)g(*status\))95 -1591 y(int)g(fits_write_imghdrll)c(/)k(ffphpsll)286 1704 -y(\(fitsfile)f(*fptr,)g(int)h(bitpix,)e(int)i(naxis,)f(LONGLONG)g -(*naxes,)g(>)h(int)g(*status\))95 1930 y(int)g(fits_write_grphdr)c(/)48 -b(ffphpr)286 2042 y(\(fitsfile)e(*fptr,)g(int)h(simple,)e(int)i -(bitpix,)f(int)h(naxis,)f(long)h(*naxes,)334 2155 y(LONGLONG)f(pcount,) -f(LONGLONG)h(gcount,)g(int)h(extend,)f(>)h(int)g(*status\))95 -2381 y(int)g(fits_write_grphdrll)c(/)k(ffphprll)286 2494 -y(\(fitsfile)f(*fptr,)g(int)h(simple,)e(int)i(bitpix,)f(int)h(naxis,)f -(LONGLONG)g(*naxes,)334 2607 y(LONGLONG)g(pcount,)f(LONGLONG)h(gcount,) -g(int)h(extend,)f(>)h(int)g(*status\))95 2833 y(int)g -(fits_write_exthdr)c(/ffphext)286 2946 y(\(fitsfile)j(*fptr,)g(char)g -(*xtension,)f(int)i(bitpix,)f(int)h(naxis,)f(long)h(*naxes,)334 -3059 y(LONGLONG)f(pcount,)f(LONGLONG)h(gcount,)g(>)h(int)g(*status\))0 -3417 y Fi(2)81 b Fj(W)-8 b(rite)30 b(the)g(ASCI)s(I)d(table)k(header)e -(k)m(eyw)m(ords)g(in)m(to)i(the)e(CHU.)h(The)e(optional)j(TUNITn)d(and) -h(EXTNAME)227 3530 y(k)m(eyw)m(ords)f(are)h(written)e(only)h(if)g(the)g -(input)f(p)s(oin)m(ters)h(are)g(not)g(n)m(ull.)40 b(A)27 -b(n)m(ull)h(p)s(oin)m(ter)g(ma)m(y)g(giv)m(en)h(for)f(the)227 -3643 y(*tb)s(col)37 b(parameter)g(in)f(whic)m(h)g(case)i(a)e(single)h -(space)g(will)g(b)s(e)f(inserted)g(b)s(et)m(w)m(een)h(eac)m(h)g(column) -f(of)h(the)227 3756 y(table.)57 b(Similarly)-8 b(,)37 -b(if)f(ro)m(wlen)f(is)h(giv)m(en)g(=)f(0,)i(then)e(CFITSIO)f(will)i -(calculate)h(the)f(default)f(ro)m(wlength)227 3868 y(based)30 -b(on)h(the)f(tb)s(col)h(and)f(tt)m(yp)s(e)h(v)-5 b(alues.)95 -4114 y Fe(int)47 b(fits_write_atblhdr)c(/)48 b(ffphtb)286 -4227 y(\(fitsfile)e(*fptr,)g(LONGLONG)f(rowlen,)h(LONGLONG)g(nrows,)g -(int)h(tfields,)e(char)i(**ttype,)334 4340 y(long)g(*tbcol,)f(char)g -(**tform,)g(char)g(**tunit,)g(char)h(*extname,)e(>)i(int)g(*status\))0 -4585 y Fi(3)81 b Fj(W)-8 b(rite)30 b(the)f(binary)g(table)h(header)e(k) -m(eyw)m(ords)i(in)m(to)g(the)f(CHU.)g(The)g(optional)h(TUNITn)e(and)h -(EXTNAME)227 4698 y(k)m(eyw)m(ords)35 b(are)g(written)g(only)g(if)f -(the)h(input)f(p)s(oin)m(ters)g(are)h(not)g(n)m(ull.)53 -b(The)35 b(p)s(coun)m(t)f(parameter,)i(whic)m(h)227 4811 -y(sp)s(eci\014es)h(the)g(size)g(of)g(the)g(v)-5 b(ariable)38 -b(length)f(arra)m(y)g(heap,)h(should)e(initially)i(=)f(0;)j(CFITSIO)c -(will)h(au-)227 4924 y(tomatically)d(up)s(date)d(the)g(PCOUNT)f(k)m -(eyw)m(ord)i(v)-5 b(alue)32 b(if)f(an)m(y)g(v)-5 b(ariable)32 -b(length)g(arra)m(y)g(data)g(is)f(written)227 5036 y(to)g(the)e(heap.) -41 b(The)29 b(TF)m(ORM)g(k)m(eyw)m(ord)h(v)-5 b(alue)30 -b(for)g(v)-5 b(ariable)30 b(length)g(v)m(ector)h(columns)e(should)g(ha) -m(v)m(e)i(the)227 5149 y(form)c('Pt\(len\)')j(or)d('1Pt\(len\)')j -(where)d(`t')h(is)g(the)g(data)g(t)m(yp)s(e)g(co)s(de)f(letter)i -(\(A,I,J,E,D,)g(etc.\))42 b(and)27 b(`len')h(is)227 5262 -y(an)g(in)m(teger)i(sp)s(ecifying)e(the)g(maxim)m(um)g(length)g(of)h -(the)f(v)m(ectors)h(in)f(that)h(column)f(\(len)g(m)m(ust)g(b)s(e)g -(greater)227 5375 y(than)36 b(or)g(equal)h(to)g(the)f(longest)i(v)m -(ector)f(in)f(the)h(column\).)58 b(If)36 b(`len')g(is)h(not)f(sp)s -(eci\014ed)g(when)f(the)h(table)227 5488 y(is)c(created)g(\(e.g.,)h -(the)f(input)e(TF)m(ORMn)h(v)-5 b(alue)32 b(is)f(just)g('1Pt'\))i(then) -e(CFITSIO)f(will)h(scan)h(the)f(column)227 5601 y(when)f(the)h(table)h -(is)f(\014rst)f(closed)h(and)g(will)g(app)s(end)e(the)i(maxim)m(um)g -(length)g(to)g(the)g(TF)m(ORM)g(k)m(eyw)m(ord)227 5714 -y(v)-5 b(alue.)41 b(Note)30 b(that)f(if)f(the)h(table)g(is)g(subsequen) -m(tly)f(mo)s(di\014ed)f(to)j(increase)f(the)g(maxim)m(um)f(length)h(of) -g(the)p eop end -%%Page: 103 111 -TeXDict begin 103 110 bop 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 -b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(103)227 -555 y(v)m(ectors)39 b(then)e(the)g(mo)s(difying)g(program)g(is)g(resp)s -(onsible)g(for)g(also)h(up)s(dating)e(the)i(TF)m(ORM)f(k)m(eyw)m(ord) -227 668 y(v)-5 b(alue.)95 935 y Fe(int)47 b(fits_write_btblhdr)c(/)48 -b(ffphbn)286 1048 y(\(fitsfile)e(*fptr,)g(LONGLONG)f(nrows,)h(int)h -(tfields,)f(char)g(**ttype,)334 1161 y(char)h(**tform,)e(char)i -(**tunit,)e(char)i(*extname,)e(LONGLONG)h(pcount,)g(>)h(int)g -(*status\))0 1427 y Fi(4)81 b Fj(Read)30 b(the)h(required)e(k)m(eyw)m -(ords)i(from)f(the)h(CHDU)f(\(image)j(or)d(table\).)42 -b(When)30 b(reading)h(from)f(an)g(IMA)m(GE)227 1540 y(extension)24 -b(the)g(SIMPLE)e(and)h(EXTEND)g(parameters)h(are)f(ignored.)39 -b(A)23 b(n)m(ull)g(p)s(oin)m(ter)h(ma)m(y)g(b)s(e)e(supplied)227 -1653 y(for)30 b(an)m(y)h(of)g(the)f(returned)f(parameters)i(that)g(are) -g(not)f(needed.)95 1920 y Fe(int)47 b(fits_read_imghdr)d(/)j(ffghpr)286 -2033 y(\(fitsfile)f(*fptr,)g(int)h(maxdim,)e(>)j(int)f(*simple,)e(int)i -(*bitpix,)f(int)h(*naxis,)334 2146 y(long)g(*naxes,)f(long)g(*pcount,)g -(long)g(*gcount,)g(int)h(*extend,)e(int)i(*status\))95 -2372 y(int)g(fits_read_imghdrll)c(/)48 b(ffghprll)286 -2485 y(\(fitsfile)e(*fptr,)g(int)h(maxdim,)e(>)j(int)f(*simple,)e(int)i -(*bitpix,)f(int)h(*naxis,)334 2598 y(LONGLONG)f(*naxes,)f(long)i -(*pcount,)f(long)g(*gcount,)g(int)h(*extend,)e(int)i(*status\))95 -2823 y(int)g(fits_read_atblhdr)c(/)48 b(ffghtb)286 2936 -y(\(fitsfile)e(*fptr,int)f(maxdim,)h(>)h(long)g(*rowlen,)e(long)i -(*nrows,)334 3049 y(int)g(*tfields,)e(char)i(**ttype,)e(LONGLONG)h -(*tbcol,)g(char)g(**tform,)g(char)h(**tunit,)334 3162 -y(char)g(*extname,)93 b(int)47 b(*status\))95 3388 y(int)g -(fits_read_atblhdrll)c(/)k(ffghtbll)286 3501 y(\(fitsfile)f(*fptr,int)f -(maxdim,)h(>)h(LONGLONG)f(*rowlen,)f(LONGLONG)h(*nrows,)334 -3614 y(int)h(*tfields,)e(char)i(**ttype,)e(long)i(*tbcol,)f(char)h -(**tform,)e(char)i(**tunit,)334 3727 y(char)g(*extname,)93 -b(int)47 b(*status\))95 3952 y(int)g(fits_read_btblhdr)c(/)48 -b(ffghbn)286 4065 y(\(fitsfile)e(*fptr,)g(int)h(maxdim,)e(>)j(long)f -(*nrows,)e(int)i(*tfields,)334 4178 y(char)g(**ttype,)e(char)i -(**tform,)e(char)i(**tunit,)f(char)g(*extname,)334 4291 -y(long)h(*pcount,)e(int)i(*status\))95 4517 y(int)g -(fits_read_btblhdrll)c(/)k(ffghbnll)286 4630 y(\(fitsfile)f(*fptr,)g -(int)h(maxdim,)e(>)j(LONGLONG)d(*nrows,)h(int)h(*tfields,)334 -4743 y(char)g(**ttype,)e(char)i(**tform,)e(char)i(**tunit,)f(char)g -(*extname,)334 4856 y(long)h(*pcount,)e(int)i(*status\))0 -5155 y Fd(9.3.3)112 b(W)-9 b(rite)37 b(Keyw)m(ord)g(Routines)0 -5375 y Fj(These)32 b(routines)h(simply)f(app)s(end)f(a)h(new)g(k)m(eyw) -m(ord)h(to)h(the)e(header)h(and)f(do)g(not)h(c)m(hec)m(k)h(to)f(see)g -(if)g(a)f(k)m(eyw)m(ord)0 5488 y(with)d(the)g(same)h(name)f(already)h -(exists.)41 b(In)28 b(general)i(it)g(is)f(preferable)g(to)h(use)f(the)h -(\014ts)p 3009 5488 28 4 v 32 w(up)s(date)p 3317 5488 -V 32 w(k)m(ey)g(routine)f(to)0 5601 y(ensure)34 b(that)h(the)g(same)g -(k)m(eyw)m(ord)g(is)f(not)h(written)g(more)g(than)f(once)h(to)h(the)e -(header.)54 b(See)34 b(App)s(endix)f(B)i(for)0 5714 y(the)c -(de\014nition)f(of)g(the)h(parameters)f(used)g(in)g(these)h(routines.)p -eop end -%%Page: 104 112 -TeXDict begin 104 111 bop 0 299 a Fj(104)958 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Fi(1)81 b Fj(W)-8 b(rite)30 b(\(app)s(end\))f(a)g -(new)g(k)m(eyw)m(ord)h(of)g(the)f(appropriate)g(data)h(t)m(yp)s(e)g(in) -m(to)g(the)g(CHU.)f(A)h(n)m(ull)f(p)s(oin)m(ter)g(ma)m(y)227 -668 y(b)s(e)35 b(en)m(tered)h(for)f(the)h(commen)m(t)h(parameter,)g -(whic)m(h)e(will)h(cause)g(the)g(commen)m(t)g(\014eld)f(of)h(the)f(k)m -(eyw)m(ord)227 781 y(to)43 b(b)s(e)e(left)i(blank.)76 -b(The)41 b(\015t,)k(dbl,)f(cmp,)h(and)d(dblcmp)f(v)m(ersions)h(of)g -(this)g(routine)g(ha)m(v)m(e)h(the)g(added)227 894 y(feature)33 -b(that)g(if)g(the)f('decimals')i(parameter)f(is)g(negativ)m(e,)i(then)d -(the)h('G')g(displa)m(y)g(format)g(rather)f(then)227 -1007 y(the)i('E')f(format)h(will)f(b)s(e)g(used)f(when)g(constructing)i -(the)g(k)m(eyw)m(ord)f(v)-5 b(alue,)35 b(taking)f(the)g(absolute)f(v)-5 -b(alue)227 1120 y(of)34 b('decimals')h(for)e(the)h(precision.)51 -b(This)33 b(will)h(suppress)d(trailing)k(zeros,)g(and)e(will)h(use)g(a) -g(\014xed)f(format)227 1233 y(rather)e(than)f(an)g(exp)s(onen)m(tial)h -(format,)g(dep)s(ending)e(on)h(the)h(magnitude)f(of)h(the)g(v)-5 -b(alue.)95 1478 y Fe(int)47 b(fits_write_key_str)c(/)48 -b(ffpkys)286 1591 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(char)g -(*value,)g(char)h(*comment,)334 1704 y(>)h(int)e(*status\))95 -1930 y(int)h(fits_write_key_[log,)c(lng])j(/)95 b(ffpky[lj])286 -2042 y(\(fitsfile)46 b(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g -(char)g(*comment,)334 2155 y(>)i(int)e(*status\))95 2381 -y(int)h(fits_write_key_[flt,)c(dbl,)j(fixflg,)g(fixdbl])g(/)h -(ffpky[edfg])286 2494 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE) -g(numval,)g(int)h(decimals,)286 2607 y(char)g(*comment,)e(>)j(int)f -(*status\))95 2833 y(int)g(fits_write_key_[cmp,)c(dblcmp,)i(fixcmp,)h -(fixdblcmp])f(/)j(ffpk[yc,ym,fc,fm])286 2946 y(\(fitsfile)e(*fptr,)g -(char)g(*keyname,)g(DTYPE)g(*numval,)g(int)g(decimals,)286 -3059 y(char)h(*comment,)e(>)j(int)f(*status\))0 3304 -y Fi(2)81 b Fj(W)-8 b(rite)30 b(\(app)s(end\))e(a)i(string)f(v)-5 -b(alued)29 b(k)m(eyw)m(ord)h(in)m(to)g(the)f(CHU)h(whic)m(h)e(ma)m(y)i -(b)s(e)f(longer)h(than)e(68)i(c)m(haracters)227 3417 -y(in)43 b(length.)80 b(This)42 b(uses)h(the)g(Long)h(String)e(Keyw)m -(ord)h(con)m(v)m(en)m(tion)j(that)d(is)h(describ)s(ed)e(in)h(the`Lo)s -(cal)227 3530 y(FITS)38 b(Con)m(v)m(en)m(tions')i(section)g(in)f -(Chapter)f(4.)66 b(Since)38 b(this)h(uses)f(a)h(non-standard)f(FITS)g -(con)m(v)m(en)m(tion)227 3643 y(to)45 b(enco)s(de)f(the)g(long)h(k)m -(eyw)m(ord)f(string,)k(programs)43 b(whic)m(h)h(use)g(this)g(routine)g -(should)f(also)h(call)i(the)227 3756 y(\014ts)p 354 3756 -28 4 v 33 w(write)p 589 3756 V 33 w(k)m(ey)p 755 3756 -V 33 w(longw)m(arn)26 b(routine)f(to)h(add)f(some)h(COMMENT)f(k)m(eyw)m -(ords)g(to)h(w)m(arn)f(users)g(of)g(the)h(FITS)227 3868 -y(\014le)43 b(that)h(this)e(con)m(v)m(en)m(tion)j(is)e(b)s(eing)f -(used.)78 b(The)42 b(\014ts)p 2220 3868 V 32 w(write)p -2454 3868 V 33 w(k)m(ey)p 2620 3868 V 34 w(longw)m(arn)h(routine)g -(also)h(writes)f(a)227 3981 y(k)m(eyw)m(ord)29 b(called)g(LONGSTRN)e -(to)i(record)f(the)g(v)m(ersion)h(of)f(the)g(longstring)h(con)m(v)m(en) -m(tion)h(that)f(has)f(b)s(een)227 4094 y(used,)35 b(in)f(case)i(a)f -(new)e(con)m(v)m(en)m(tion)k(is)e(adopted)f(at)h(some)g(p)s(oin)m(t)f -(in)h(the)f(future.)52 b(If)34 b(the)h(LONGSTRN)227 4207 -y(k)m(eyw)m(ord)43 b(is)g(already)g(presen)m(t)g(in)g(the)f(header,)k -(then)d(\014ts)p 2332 4207 V 32 w(write)p 2566 4207 V -33 w(k)m(ey)p 2732 4207 V 34 w(longw)m(arn)g(will)g(simply)f(return)227 -4320 y(without)31 b(doing)f(an)m(ything.)95 4565 y Fe(int)47 -b(fits_write_key_longstr)42 b(/)48 b(ffpkls)286 4678 -y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(char)g(*longstr,)g(char)g -(*comment,)334 4791 y(>)i(int)e(*status\))95 5017 y(int)h -(fits_write_key_longwarn)42 b(/)47 b(ffplsw)286 5130 -y(\(fitsfile)f(*fptr,)g(>)h(int)g(*status\))0 5375 y -Fi(3)81 b Fj(W)-8 b(rite)38 b(\(app)s(end\))d(a)i(n)m(um)m(b)s(ered)e -(sequence)i(of)g(k)m(eyw)m(ords)g(in)m(to)g(the)g(CHU.)g(The)f -(starting)h(index)f(n)m(um)m(b)s(er)227 5488 y(\(nstart\))30 -b(m)m(ust)e(b)s(e)g(greater)i(than)f(0.)40 b(One)28 b(ma)m(y)i(app)s -(end)d(the)h(same)i(commen)m(t)f(to)h(ev)m(ery)f(k)m(eyw)m(ord)g(\(and) -227 5601 y(eliminate)35 b(the)f(need)f(to)h(ha)m(v)m(e)g(an)f(arra)m(y) -h(of)f(iden)m(tical)j(commen)m(t)e(strings,)g(one)f(for)h(eac)m(h)g(k)m -(eyw)m(ord\))g(b)m(y)227 5714 y(including)24 b(the)h(amp)s(ersand)e(c)m -(haracter)j(as)e(the)h(last)g(non-blank)f(c)m(haracter)i(in)e(the)g -(\(\014rst\))h(COMMENTS)p eop end -%%Page: 105 113 -TeXDict begin 105 112 bop 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 -b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(105)227 -555 y(string)23 b(parameter.)38 b(This)22 b(same)h(string)f(will)h -(then)f(b)s(e)g(used)f(for)h(the)h(commen)m(t)g(\014eld)f(in)g(all)i -(the)e(k)m(eyw)m(ords.)227 668 y(One)32 b(ma)m(y)h(also)g(en)m(ter)f(a) -h(n)m(ull)f(p)s(oin)m(ter)g(for)g(the)g(commen)m(t)h(parameter)g(to)f -(lea)m(v)m(e)j(the)d(commen)m(t)h(\014eld)f(of)227 781 -y(the)f(k)m(eyw)m(ord)g(blank.)95 995 y Fe(int)47 b -(fits_write_keys_str)c(/)k(ffpkns)286 1107 y(\(fitsfile)f(*fptr,)g -(char)g(*keyroot,)g(int)h(nstart,)e(int)i(nkeys,)334 -1220 y(char)g(**value,)e(char)i(**comment,)e(>)i(int)g(*status\))95 -1446 y(int)g(fits_write_keys_[log,)42 b(lng])47 b(/)g(ffpkn[lj])286 -1559 y(\(fitsfile)f(*fptr,)g(char)g(*keyroot,)g(int)h(nstart,)e(int)i -(nkeys,)334 1672 y(DTYPE)f(*numval,)g(char)h(**comment,)e(int)i -(*status\))95 1898 y(int)g(fits_write_keys_[flt,)42 b(dbl,)47 -b(fixflg,)f(fixdbl])g(/)h(ffpkne[edfg])286 2011 y(\(fitsfile)f(*fptr,)g -(char)g(*keyroot,)g(int)h(nstart,)e(int)i(nkey,)334 2124 -y(DTYPE)f(*numval,)g(int)h(decimals,)e(char)i(**comment,)e(>)i(int)g -(*status\))0 2337 y Fi(4)81 b Fj(Cop)m(y)21 b(an)h(indexed)f(k)m(eyw)m -(ord)i(from)e(one)h(HDU)h(to)f(another,)i(mo)s(difying)e(the)g(index)f -(n)m(um)m(b)s(er)f(of)i(the)g(k)m(eyw)m(ord)227 2450 -y(name)37 b(in)f(the)g(pro)s(cess.)58 b(F)-8 b(or)37 -b(example,)i(this)d(routine)h(could)f(read)g(the)h(TLMIN3)f(k)m(eyw)m -(ord)h(from)f(the)227 2563 y(input)30 b(HDU)h(\(b)m(y)g(giving)h(k)m -(eyro)s(ot)f(=)g(`TLMIN')g(and)f(inn)m(um)f(=)h(3\))i(and)e(write)h(it) -g(to)g(the)g(output)f(HDU)227 2676 y(with)36 b(the)g(k)m(eyw)m(ord)h -(name)f(TLMIN4)g(\(b)m(y)g(setting)i(outn)m(um)d(=)h(4\).)58 -b(If)36 b(the)g(input)f(k)m(eyw)m(ord)i(do)s(es)f(not)227 -2789 y(exist,)c(then)e(this)g(routine)g(simply)g(returns)f(without)i -(indicating)g(an)f(error.)95 3002 y Fe(int)47 b(fits_copy_key)e(/)i -(ffcpky)286 3115 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(int)i -(innum,)f(int)h(outnum,)334 3228 y(char)g(*keyroot,)e(>)i(int)g -(*status\))0 3442 y Fi(5)81 b Fj(W)-8 b(rite)30 b(\(app)s(end\))f(a)h -(`triple)f(precision')h(k)m(eyw)m(ord)g(in)m(to)g(the)g(CHU)f(in)g -(F28.16)j(format.)41 b(The)29 b(\015oating)h(p)s(oin)m(t)227 -3555 y(k)m(eyw)m(ord)g(v)-5 b(alue)30 b(is)f(constructed)h(b)m(y)f -(concatenating)j(the)d(input)g(in)m(teger)i(v)-5 b(alue)29 -b(with)g(the)h(input)e(double)227 3668 y(precision)35 -b(fraction)f(v)-5 b(alue)35 b(\(whic)m(h)f(m)m(ust)g(ha)m(v)m(e)i(a)e -(v)-5 b(alue)35 b(b)s(et)m(w)m(een)f(0.0)i(and)d(1.0\).)53 -b(The)34 b(\013gkyt)h(routine)227 3781 y(should)d(b)s(e)h(used)f(to)i -(read)f(this)g(k)m(eyw)m(ord)h(v)-5 b(alue,)35 b(b)s(ecause)e(the)g -(other)h(k)m(eyw)m(ord)f(reading)h(routines)f(will)227 -3893 y(not)e(preserv)m(e)f(the)h(full)f(precision)h(of)f(the)h(v)-5 -b(alue.)95 4107 y Fe(int)47 b(fits_write_key_triple)42 -b(/)48 b(ffpkyt)286 4220 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g -(long)g(intval,)g(double)g(frac,)334 4333 y(char)h(*comment,)e(>)i(int) -g(*status\))0 4546 y Fi(6)81 b Fj(W)-8 b(rite)37 b(k)m(eyw)m(ords)f(to) -h(the)f(CHDU)g(that)h(are)f(de\014ned)f(in)h(an)g(ASCI)s(I)e(template)j -(\014le.)58 b(The)35 b(format)i(of)f(the)227 4659 y(template)c(\014le)f -(is)f(describ)s(ed)f(under)g(the)i(\014ts)p 1788 4659 -28 4 v 32 w(parse)p 2028 4659 V 33 w(template)g(routine.)95 -4873 y Fe(int)47 b(fits_write_key_template)42 b(/)47 -b(ffpktp)286 4986 y(\(fitsfile)f(*fptr,)g(const)g(char)h(*filename,)e -(>)i(int)g(*status\))0 5269 y Fd(9.3.4)112 b(Insert)38 -b(Keyw)m(ord)f(Routines)0 5488 y Fj(These)42 b(insert)h(routines)f(are) -h(somewhat)g(less)f(e\016cien)m(t)i(than)f(the)f(`up)s(date')g(or)h -(`write')g(k)m(eyw)m(ord)g(routines)0 5601 y(b)s(ecause)30 -b(the)g(follo)m(wing)i(k)m(eyw)m(ords)e(in)g(the)g(header)g(m)m(ust)g -(b)s(e)f(shifted)h(do)m(wn)f(to)i(mak)m(e)g(ro)s(om)f(for)g(the)g -(inserted)0 5714 y(k)m(eyw)m(ord.)41 b(See)31 b(App)s(endix)d(B)j(for)f -(the)h(de\014nition)f(of)g(the)h(parameters)g(used)e(in)h(these)h -(routines.)p eop end -%%Page: 106 114 -TeXDict begin 106 113 bop 0 299 a Fj(106)958 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Fi(1)81 b Fj(Insert)26 b(a)h(new)f(k)m(eyw)m(ord) -h(record)g(in)m(to)g(the)g(CHU)g(at)g(the)g(sp)s(eci\014ed)f(p)s -(osition)h(\(i.e.,)i(immediately)f(preceding)227 668 -y(the)j(\(k)m(eyn)m(um\)th)g(k)m(eyw)m(ord)g(in)f(the)g(header.\))95 -921 y Fe(int)47 b(fits_insert_record)c(/)48 b(ffirec)286 -1034 y(\(fitsfile)e(*fptr,)g(int)h(keynum,)e(char)i(*card,)f(>)i(int)f -(*status\))0 1286 y Fi(2)81 b Fj(Insert)24 b(a)h(new)g(k)m(eyw)m(ord)g -(in)m(to)h(the)f(CHU.)g(The)g(new)f(k)m(eyw)m(ord)i(is)f(inserted)f -(immediately)j(follo)m(wing)f(the)f(last)227 1399 y(k)m(eyw)m(ord)i -(that)f(has)f(b)s(een)h(read)f(from)h(the)g(header.)39 -b(The)25 b(`longstr')i(v)m(ersion)f(has)f(the)h(same)g(functionalit)m -(y)227 1512 y(as)33 b(the)g(`str')f(v)m(ersion)h(except)h(that)f(it)g -(also)g(supp)s(orts)e(the)h(lo)s(cal)i(long)f(string)g(k)m(eyw)m(ord)g -(con)m(v)m(en)m(tion)h(for)227 1625 y(strings)29 b(longer)g(than)g(68)h -(c)m(haracters.)41 b(A)29 b(n)m(ull)g(p)s(oin)m(ter)g(ma)m(y)g(b)s(e)g -(en)m(tered)g(for)g(the)g(commen)m(t)g(parameter)227 -1738 y(whic)m(h)d(will)f(cause)h(the)g(commen)m(t)h(\014eld)e(to)h(b)s -(e)f(left)h(blank.)39 b(The)25 b(\015t,)h(dbl,)g(cmp,)h(and)e(dblcmp)f -(v)m(ersions)i(of)227 1851 y(this)k(routine)g(ha)m(v)m(e)h(the)e(added) -g(feature)i(that)f(if)g(the)g('decimals')h(parameter)f(is)g(negativ)m -(e,)i(then)d(the)h('G')227 1964 y(displa)m(y)g(format)g(rather)f(then)g -(the)h('E')f(format)h(will)g(b)s(e)f(used)f(when)h(constructing)h(the)f -(k)m(eyw)m(ord)h(v)-5 b(alue,)227 2077 y(taking)27 b(the)g(absolute)g -(v)-5 b(alue)26 b(of)h('decimals')g(for)f(the)h(precision.)39 -b(This)26 b(will)g(suppress)e(trailing)k(zeros,)g(and)227 -2189 y(will)37 b(use)g(a)g(\014xed)f(format)h(rather)g(than)f(an)h(exp) -s(onen)m(tial)g(format,)i(dep)s(ending)c(on)i(the)g(magnitude)g(of)227 -2302 y(the)31 b(v)-5 b(alue.)95 2555 y Fe(int)47 b(fits_insert_card)d -(/)j(ffikey)286 2668 y(\(fitsfile)f(*fptr,)g(char)g(*card,)g(>)i(int)f -(*status\))95 2894 y(int)g(fits_insert_key_[str,)42 b(longstr])k(/)h -(ffi[kys,)f(kls])286 3007 y(\(fitsfile)g(*fptr,)g(char)g(*keyname,)g -(char)g(*value,)g(char)h(*comment,)334 3120 y(>)h(int)e(*status\))95 -3345 y(int)h(fits_insert_key_[log,)42 b(lng])47 b(/)g(ffiky[lj])286 -3458 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g(char) -g(*comment,)334 3571 y(>)i(int)e(*status\))95 3797 y(int)h -(fits_insert_key_[flt,)42 b(fixflt,)k(dbl,)h(fixdbl])f(/)h(ffiky[edfg]) -286 3910 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g -(int)h(decimals,)334 4023 y(char)g(*comment,)e(>)i(int)g(*status\))95 -4249 y(int)g(fits_insert_key_[cmp,)42 b(dblcmp,)k(fixcmp,)g(fixdblcmp]) -f(/)i(ffik[yc,ym,fc,fm])286 4362 y(\(fitsfile)f(*fptr,)g(char)g -(*keyname,)g(DTYPE)g(*numval,)g(int)g(decimals,)334 4474 -y(char)h(*comment,)e(>)i(int)g(*status\))0 4727 y Fi(3)81 -b Fj(Insert)32 b(a)i(new)f(k)m(eyw)m(ord)h(with)f(an)h(unde\014ned,)e -(or)h(n)m(ull,)h(v)-5 b(alue)34 b(in)m(to)h(the)e(CHU.)h(The)f(v)-5 -b(alue)34 b(string)f(of)h(the)227 4840 y(k)m(eyw)m(ord)d(is)g(left)g -(blank)f(in)g(this)g(case.)95 5093 y Fe(int)47 b(fits_insert_key_null)c -(/)k(ffikyu)286 5205 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g -(*comment,)g(>)h(int)g(*status\))0 5495 y Fd(9.3.5)112 -b(Read)38 b(Keyw)m(ord)g(Routines)0 5714 y Fj(Wild)31 -b(card)f(c)m(haracters)i(ma)m(y)f(b)s(e)f(used)f(when)h(sp)s(ecifying)g -(the)g(name)h(of)f(the)h(k)m(eyw)m(ord)g(to)g(b)s(e)f(read.)p -eop end -%%Page: 107 115 -TeXDict begin 107 114 bop 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 -b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(107)0 555 -y Fi(1)81 b Fj(Read)43 b(a)h(k)m(eyw)m(ord)g(v)-5 b(alue)43 -b(\(with)h(the)f(appropriate)h(data)g(t)m(yp)s(e\))g(and)e(commen)m(t)j -(from)e(the)g(CHU.)h(If)f(a)227 668 y(NULL)32 b(commen)m(t)h(p)s(oin)m -(ter)f(is)h(giv)m(en)g(on)f(input,)f(then)h(the)g(commen)m(t)i(string)e -(will)g(not)g(b)s(e)g(returned.)44 b(If)227 781 y(the)32 -b(v)-5 b(alue)33 b(of)f(the)g(k)m(eyw)m(ord)g(is)g(not)h(de\014ned)d -(\(i.e.,)k(the)e(v)-5 b(alue)33 b(\014eld)e(is)h(blank\))g(then)g(an)g -(error)f(status)h(=)227 894 y(V)-10 b(ALUE)p 545 894 -28 4 v 33 w(UNDEFINED)29 b(will)f(b)s(e)g(returned)e(and)h(the)h(input) -f(v)-5 b(alue)28 b(will)h(not)f(b)s(e)f(c)m(hanged)h(\(except)h(that) -227 1007 y(\013gkys)i(will)g(reset)g(the)f(v)-5 b(alue)31 -b(to)g(a)g(n)m(ull)f(string\).)95 1252 y Fe(int)47 b(fits_read_key_str) -c(/)48 b(ffgkys)286 1365 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h -(char)g(*value,)f(char)g(*comment,)334 1478 y(int)h(*status\);)95 -1704 y(NOTE:)g(after)f(calling)g(the)h(following)e(routine,)h(programs) -f(must)i(explicitly)e(free)382 1817 y(the)i(memory)f(allocated)f(for)i -('longstr')e(after)i(it)g(is)g(no)g(longer)f(needed)g(by)382 -1930 y(calling)g(fits_free_memory.)95 2155 y(int)h -(fits_read_key_longstr)42 b(/)48 b(ffgkls)286 2268 y(\(fitsfile)e -(*fptr,)g(char)g(*keyname,)g(>)h(char)g(**longstr,)e(char)h(*comment,) -620 2381 y(int)h(*status\))95 2607 y(int)g(fits_free_memory)d(/)j -(fffree)286 2720 y(\(char)g(*longstr,)e(>)i(int)g(*status\);)95 -2946 y(int)g(fits_read_key_[log,)c(lng,)k(flt,)f(dbl,)h(cmp,)f(dblcmp]) -g(/)i(ffgky[ljedcm])286 3059 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g -(>)h(DTYPE)f(*numval,)g(char)h(*comment,)334 3172 y(int)g(*status\))95 -3397 y(int)g(fits_read_key_lnglng)c(/)k(ffgkyjj)286 3510 -y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(>)h(LONGLONG)f(*numval,)f -(char)i(*comment,)334 3623 y(int)g(*status\))0 3868 y -Fi(2)81 b Fj(Read)36 b(a)h(sequence)f(of)h(indexed)e(k)m(eyw)m(ord)i(v) --5 b(alues)37 b(\(e.g.,)i(NAXIS1,)g(NAXIS2,)f(...\).)59 -b(The)36 b(input)f(starting)227 3981 y(index)j(n)m(um)m(b)s(er)e -(\(nstart\))j(m)m(ust)f(b)s(e)f(greater)i(than)e(0.)64 -b(If)37 b(the)h(v)-5 b(alue)38 b(of)g(an)m(y)h(of)f(the)g(k)m(eyw)m -(ords)g(is)g(not)227 4094 y(de\014ned)c(\(i.e.,)j(the)e(v)-5 -b(alue)35 b(\014eld)f(is)h(blank\))g(then)f(an)g(error)h(status)g(=)f -(V)-10 b(ALUE)p 3009 4094 V 33 w(UNDEFINED)36 b(will)f(b)s(e)227 -4207 y(returned)21 b(and)h(the)h(input)e(v)-5 b(alue)23 -b(for)f(the)g(unde\014ned)e(k)m(eyw)m(ord\(s\))k(will)e(not)h(b)s(e)e -(c)m(hanged.)39 b(These)22 b(routines)227 4320 y(do)j(not)h(supp)s(ort) -d(wild)i(card)h(c)m(haracters)g(in)f(the)h(ro)s(ot)f(name.)39 -b(If)25 b(there)h(are)f(no)g(indexed)g(k)m(eyw)m(ords)h(in)f(the)227 -4433 y(header)35 b(with)f(the)h(input)e(ro)s(ot)i(name)g(then)f(these)h -(routines)g(do)f(not)h(return)e(a)i(non-zero)h(status)e(v)-5 -b(alue)227 4546 y(and)30 b(instead)h(simply)f(return)f(nfound)f(=)i(0.) -95 4791 y Fe(int)47 b(fits_read_keys_str)c(/)48 b(ffgkns)286 -4904 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(int)h(nstart,)e(int)i -(nkeys,)334 5017 y(>)h(char)e(**value,)g(int)h(*nfound,)93 -b(int)47 b(*status\))95 5243 y(int)g(fits_read_keys_[log,)c(lng,)j -(flt,)h(dbl])g(/)g(ffgkn[ljed])286 5356 y(\(fitsfile)f(*fptr,)g(char)g -(*keyname,)g(int)h(nstart,)e(int)i(nkeys,)334 5469 y(>)h(DTYPE)e -(*numval,)f(int)i(*nfound,)f(int)h(*status\))0 5714 y -Fi(3)81 b Fj(Read)37 b(the)h(v)-5 b(alue)38 b(of)g(a)g(\015oating)g(p)s -(oin)m(t)g(k)m(eyw)m(ord,)i(returning)d(the)h(in)m(teger)h(and)e -(fractional)i(parts)e(of)h(the)p eop end -%%Page: 108 116 -TeXDict begin 108 115 bop 0 299 a Fj(108)958 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)227 555 y Fj(v)-5 b(alue)35 b(in)e(separate)i(routine)f -(argumen)m(ts.)52 b(This)33 b(routine)h(ma)m(y)g(b)s(e)f(used)h(to)g -(read)g(an)m(y)g(k)m(eyw)m(ord)h(but)e(is)227 668 y(esp)s(ecially)f -(useful)d(for)i(reading)f(the)h('triple)g(precision')f(k)m(eyw)m(ords)h -(written)g(b)m(y)f(\013pkyt.)95 929 y Fe(int)47 b(fits_read_key_triple) -c(/)k(ffgkyt)286 1042 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(>)h -(long)g(*intval,)e(double)h(*frac,)334 1155 y(char)h(*comment,)e(int)i -(*status\))0 1446 y Fd(9.3.6)112 b(Mo)s(dify)39 b(Keyw)m(ord)e -(Routines)0 1666 y Fj(These)31 b(routines)h(mo)s(dify)f(the)h(v)-5 -b(alue)32 b(of)g(an)g(existing)g(k)m(eyw)m(ord.)46 b(An)31 -b(error)g(is)h(returned)e(if)i(the)g(k)m(eyw)m(ord)g(do)s(es)0 -1778 y(not)43 b(exist.)77 b(Wild)43 b(card)g(c)m(haracters)h(ma)m(y)f -(b)s(e)f(used)f(when)h(sp)s(ecifying)g(the)h(name)f(of)h(the)f(k)m(eyw) -m(ord)h(to)h(b)s(e)0 1891 y(mo)s(di\014ed.)c(See)30 b(App)s(endix)f(B)i -(for)f(the)g(de\014nition)g(of)h(the)f(parameters)h(used)f(in)g(these)h -(routines.)0 2152 y Fi(1)81 b Fj(Mo)s(dify)30 b(\(o)m(v)m(erwrite\))i -(the)f(n)m(th)f(80-c)m(haracter)j(header)d(record)h(in)f(the)g(CHU.)95 -2413 y Fe(int)47 b(fits_modify_record)c(/)48 b(ffmrec)286 -2526 y(\(fitsfile)e(*fptr,)g(int)h(keynum,)e(char)i(*card,)f(>)i(int)f -(*status\))0 2786 y Fi(2)81 b Fj(Mo)s(dify)37 b(\(o)m(v)m(erwrite\))j -(the)e(80-c)m(haracter)j(header)c(record)h(for)f(the)h(named)f(k)m(eyw) -m(ord)h(in)g(the)g(CHU.)g(This)227 2899 y(can)31 b(b)s(e)f(used)f(to)i -(o)m(v)m(erwrite)h(the)f(name)f(of)h(the)f(k)m(eyw)m(ord)h(as)g(w)m -(ell)g(as)g(its)g(v)-5 b(alue)30 b(and)g(commen)m(t)i(\014elds.)95 -3160 y Fe(int)47 b(fits_modify_card)d(/)j(ffmcrd)286 -3273 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*card,)g(>)i -(int)f(*status\))0 3534 y Fi(5)81 b Fj(Mo)s(dify)30 b(the)g(v)-5 -b(alue)31 b(and)e(commen)m(t)i(\014elds)f(of)g(an)g(existing)h(k)m(eyw) -m(ord)g(in)f(the)g(CHU.)h(The)e(`longstr')i(v)m(ersion)227 -3647 y(has)41 b(the)h(same)f(functionalit)m(y)i(as)e(the)h(`str')f(v)m -(ersion)h(except)g(that)g(it)g(also)g(supp)s(orts)d(the)j(lo)s(cal)g -(long)227 3760 y(string)29 b(k)m(eyw)m(ord)h(con)m(v)m(en)m(tion)h(for) -e(strings)f(longer)i(than)f(68)h(c)m(haracters.)41 b(Optionally)-8 -b(,)31 b(one)e(ma)m(y)h(mo)s(dify)227 3872 y(only)e(the)g(v)-5 -b(alue)28 b(\014eld)g(and)f(lea)m(v)m(e)j(the)e(commen)m(t)h(\014eld)e -(unc)m(hanged)h(b)m(y)g(setting)g(the)g(input)f(COMMENT)227 -3985 y(parameter)c(equal)h(to)f(the)g(amp)s(ersand)e(c)m(haracter)j -(\(&\))f(or)g(b)m(y)g(en)m(tering)g(a)g(n)m(ull)g(p)s(oin)m(ter)g(for)f -(the)h(commen)m(t)227 4098 y(parameter.)40 b(The)24 b(\015t,)i(dbl,)g -(cmp,)f(and)g(dblcmp)e(v)m(ersions)j(of)f(this)g(routine)g(ha)m(v)m(e)h -(the)f(added)f(feature)h(that)227 4211 y(if)h(the)h('decimals')g -(parameter)g(is)f(negativ)m(e,)k(then)c(the)g('G')h(displa)m(y)f -(format)h(rather)f(then)g(the)g('E')h(format)227 4324 -y(will)i(b)s(e)f(used)f(when)h(constructing)h(the)f(k)m(eyw)m(ord)h(v) --5 b(alue,)30 b(taking)f(the)g(absolute)g(v)-5 b(alue)29 -b(of)f('decimals')i(for)227 4437 y(the)37 b(precision.)60 -b(This)35 b(will)i(suppress)e(trailing)i(zeros,)i(and)d(will)h(use)g(a) -g(\014xed)e(format)i(rather)g(than)f(an)227 4550 y(exp)s(onen)m(tial)c -(format,)f(dep)s(ending)d(on)j(the)f(magnitude)h(of)f(the)h(v)-5 -b(alue.)95 4811 y Fe(int)47 b(fits_modify_key_[str,)42 -b(longstr])k(/)h(ffm[kys,)f(kls])286 4924 y(\(fitsfile)g(*fptr,)g(char) -g(*keyname,)g(char)g(*value,)g(char)h(*comment,)334 5036 -y(>)h(int)e(*status\);)95 5262 y(int)h(fits_modify_key_[log,)42 -b(lng])47 b(/)g(ffmky[lj])286 5375 y(\(fitsfile)f(*fptr,)g(char)g -(*keyname,)g(DTYPE)g(numval,)g(char)g(*comment,)334 5488 -y(>)i(int)e(*status\))95 5714 y(int)h(fits_modify_key_[flt,)42 -b(dbl,)47 b(fixflt,)f(fixdbl])g(/)h(ffmky[edfg])p eop -end -%%Page: 109 117 -TeXDict begin 109 116 bop 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 -b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(109)286 -555 y Fe(\(fitsfile)46 b(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g -(int)h(decimals,)334 668 y(char)g(*comment,)e(>)i(int)g(*status\))95 -894 y(int)g(fits_modify_key_[cmp,)42 b(dblcmp,)k(fixcmp,)g(fixdblcmp])f -(/)i(ffmk[yc,ym,fc,fm])286 1007 y(\(fitsfile)f(*fptr,)g(char)g -(*keyname,)g(DTYPE)g(*numval,)g(int)g(decimals,)334 1120 -y(char)h(*comment,)e(>)i(int)g(*status\))0 1431 y Fi(6)81 -b Fj(Mo)s(dify)22 b(the)g(v)-5 b(alue)23 b(of)f(an)g(existing)i(k)m -(eyw)m(ord)e(to)h(b)s(e)f(unde\014ned,)g(or)g(n)m(ull.)38 -b(The)22 b(v)-5 b(alue)22 b(string)h(of)f(the)g(k)m(eyw)m(ord)227 -1544 y(is)30 b(set)h(to)g(blank.)40 b(Optionally)-8 b(,)31 -b(one)f(ma)m(y)h(lea)m(v)m(e)h(the)f(commen)m(t)g(\014eld)e(unc)m -(hanged)h(b)m(y)g(setting)h(the)f(input)227 1657 y(COMMENT)f(parameter) -g(equal)g(to)g(the)g(amp)s(ersand)e(c)m(haracter)k(\(&\))e(or)f(b)m(y)h -(en)m(tering)g(a)g(n)m(ull)g(p)s(oin)m(ter.)95 1968 y -Fe(int)47 b(fits_modify_key_null)c(/)k(ffmkyu)286 2081 -y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*comment,)g(>)h(int)g -(*status\))0 2433 y Fd(9.3.7)112 b(Up)s(date)39 b(Keyw)m(ord)e -(Routines)0 2680 y Fi(1)81 b Fj(These)29 b(up)s(date)g(routines)h(mo)s -(dify)f(the)g(v)-5 b(alue,)31 b(and)e(optionally)i(the)f(commen)m(t)h -(\014eld,)f(of)g(the)g(k)m(eyw)m(ord)g(if)f(it)227 2793 -y(already)34 b(exists,)g(otherwise)f(the)g(new)f(k)m(eyw)m(ord)h(is)f -(app)s(ended)f(to)j(the)f(header.)47 b(A)33 b(separate)g(routine)g(is) -227 2906 y(pro)m(vided)c(for)g(eac)m(h)h(k)m(eyw)m(ord)f(data)h(t)m(yp) -s(e.)41 b(The)28 b(`longstr')i(v)m(ersion)g(has)e(the)i(same)f -(functionalit)m(y)h(as)g(the)227 3019 y(`str')h(v)m(ersion)g(except)h -(that)g(it)f(also)h(supp)s(orts)c(the)j(lo)s(cal)h(long)g(string)e(k)m -(eyw)m(ord)i(con)m(v)m(en)m(tion)h(for)d(strings)227 -3132 y(longer)i(than)f(68)h(c)m(haracters.)45 b(A)31 -b(n)m(ull)g(p)s(oin)m(ter)h(ma)m(y)f(b)s(e)g(en)m(tered)h(for)f(the)g -(commen)m(t)i(parameter)e(whic)m(h)227 3245 y(will)i(lea)m(v)m(e)h(the) -f(commen)m(t)g(\014eld)f(unc)m(hanged)g(or)g(blank.)46 -b(The)31 b(\015t,)i(dbl,)f(cmp,)h(and)e(dblcmp)g(v)m(ersions)i(of)227 -3357 y(this)d(routine)g(ha)m(v)m(e)h(the)e(added)g(feature)i(that)f(if) -g(the)g('decimals')h(parameter)f(is)g(negativ)m(e,)i(then)d(the)h('G') -227 3470 y(displa)m(y)g(format)g(rather)f(then)g(the)h('E')f(format)h -(will)g(b)s(e)f(used)f(when)h(constructing)h(the)f(k)m(eyw)m(ord)h(v)-5 -b(alue,)227 3583 y(taking)27 b(the)g(absolute)g(v)-5 -b(alue)26 b(of)h('decimals')g(for)f(the)h(precision.)39 -b(This)26 b(will)g(suppress)e(trailing)k(zeros,)g(and)227 -3696 y(will)37 b(use)g(a)g(\014xed)f(format)h(rather)g(than)f(an)h(exp) -s(onen)m(tial)g(format,)i(dep)s(ending)c(on)i(the)g(magnitude)g(of)227 -3809 y(the)31 b(v)-5 b(alue.)95 4121 y Fe(int)47 b -(fits_update_key_[str,)42 b(longstr])k(/)h(ffu[kys,)f(kls])286 -4233 y(\(fitsfile)g(*fptr,)g(char)g(*keyname,)g(char)g(*value,)g(char)h -(*comment,)334 4346 y(>)h(int)e(*status\))95 4572 y(int)h -(fits_update_key_[log,)42 b(lng])47 b(/)g(ffuky[lj])286 -4685 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g(char) -g(*comment,)334 4798 y(>)i(int)e(*status\))95 5024 y(int)h -(fits_update_key_[flt,)42 b(dbl,)47 b(fixflt,)f(fixdbl])g(/)h -(ffuky[edfg])286 5137 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE) -g(numval,)g(int)h(decimals,)334 5250 y(char)g(*comment,)e(>)i(int)g -(*status\))95 5475 y(int)g(fits_update_key_[cmp,)42 b(dblcmp,)k -(fixcmp,)g(fixdblcmp])f(/)i(ffuk[yc,ym,fc,fm])286 5588 -y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(*numval,)g(int)g -(decimals,)334 5701 y(char)h(*comment,)e(>)i(int)g(*status\))p -eop end -%%Page: 110 118 -TeXDict begin 110 117 bop 0 299 a Fj(110)958 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Ff(9.4)135 b(De\014ne)45 b(Data)h(Scaling)g(and)e -(Unde\014ned)h(Pixel)h(P)l(arameters)0 805 y Fj(These)37 -b(routines)g(set)h(or)f(mo)s(dify)g(the)g(in)m(ternal)h(parameters)g -(used)e(b)m(y)i(CFITSIO)d(to)j(either)g(scale)h(the)e(data)0 -918 y(or)f(to)h(represen)m(t)f(unde\014ned)d(pixels.)58 -b(Generally)37 b(CFITSIO)d(will)j(scale)g(the)f(data)h(according)g(to)f -(the)h(v)-5 b(alues)0 1031 y(of)35 b(the)f(BSCALE)g(and)g(BZER)m(O)h -(\(or)g(TSCALn)d(and)i(TZER)m(On\))g(k)m(eyw)m(ords,)i(ho)m(w)m(ev)m -(er)g(these)f(routines)f(ma)m(y)0 1144 y(b)s(e)e(used)h(to)h(o)m(v)m -(erride)g(the)f(k)m(eyw)m(ord)h(v)-5 b(alues.)49 b(This)32 -b(ma)m(y)i(b)s(e)f(useful)f(when)g(one)i(w)m(an)m(ts)f(to)h(read)f(or)g -(write)h(the)0 1257 y(ra)m(w)e(unscaled)g(v)-5 b(alues)33 -b(in)f(the)g(FITS)f(\014le.)47 b(Similarly)-8 b(,)33 -b(CFITSIO)e(generally)i(uses)f(the)g(v)-5 b(alue)33 b(of)f(the)h(BLANK) -0 1370 y(or)40 b(TNULLn)f(k)m(eyw)m(ord)h(to)h(signify)e(an)h -(unde\014ned)e(pixel,)43 b(but)c(these)h(routines)g(ma)m(y)g(b)s(e)f -(used)g(to)i(o)m(v)m(erride)0 1483 y(this)32 b(v)-5 b(alue.)48 -b(These)32 b(routines)g(do)h(not)f(create)i(or)f(mo)s(dify)e(the)i -(corresp)s(onding)e(header)i(k)m(eyw)m(ord)f(v)-5 b(alues.)48 -b(See)0 1596 y(App)s(endix)29 b(B)h(for)h(the)f(de\014nition)g(of)h -(the)f(parameters)h(used)e(in)i(these)f(routines.)0 1827 -y Fi(1)81 b Fj(Reset)26 b(the)g(scaling)g(factors)g(in)f(the)h(primary) -f(arra)m(y)h(or)f(image)i(extension;)h(do)s(es)d(not)g(c)m(hange)i(the) -f(BSCALE)227 1940 y(and)i(BZER)m(O)g(k)m(eyw)m(ord)h(v)-5 -b(alues)28 b(and)g(only)g(a\013ects)i(the)e(automatic)j(scaling)e(p)s -(erformed)e(when)g(the)h(data)227 2053 y(elemen)m(ts)f(are)f -(written/read)g(to/from)g(the)g(FITS)f(\014le.)39 b(When)25 -b(reading)h(from)f(a)h(FITS)f(\014le)g(the)h(returned)227 -2166 y(data)i(v)-5 b(alue)28 b(=)f(\(the)h(v)-5 b(alue)28 -b(giv)m(en)h(in)e(the)g(FITS)g(arra)m(y\))h(*)g(BSCALE)f(+)g(BZER)m(O.) -g(The)g(in)m(v)m(erse)i(form)m(ula)227 2279 y(is)i(used)e(when)h -(writing)g(data)h(v)-5 b(alues)31 b(to)g(the)f(FITS)g(\014le.)95 -2511 y Fe(int)47 b(fits_set_bscale)d(/)j(ffpscl)286 2624 -y(\(fitsfile)f(*fptr,)g(double)g(scale,)g(double)g(zero,)g(>)i(int)f -(*status\))0 2856 y Fi(2)81 b Fj(Reset)39 b(the)f(scaling)i(parameters) -e(for)h(a)f(table)h(column;)k(do)s(es)38 b(not)g(c)m(hange)i(the)e -(TSCALn)f(or)h(TZER)m(On)227 2968 y(k)m(eyw)m(ord)29 -b(v)-5 b(alues)29 b(and)e(only)i(a\013ects)g(the)g(automatic)h(scaling) -f(p)s(erformed)e(when)g(the)i(data)g(elemen)m(ts)h(are)227 -3081 y(written/read)i(to/from)g(the)g(FITS)f(\014le.)44 -b(When)31 b(reading)g(from)g(a)h(FITS)f(\014le)g(the)h(returned)e(data) -i(v)-5 b(alue)227 3194 y(=)25 b(\(the)i(v)-5 b(alue)26 -b(giv)m(en)g(in)f(the)h(FITS)f(arra)m(y\))h(*)g(TSCAL)e(+)i(TZER)m(O.)e -(The)h(in)m(v)m(erse)i(form)m(ula)f(is)f(used)g(when)227 -3307 y(writing)31 b(data)g(v)-5 b(alues)30 b(to)i(the)e(FITS)g(\014le.) -95 3539 y Fe(int)47 b(fits_set_tscale)d(/)j(fftscl)286 -3652 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(double)i(scale,)f(double)g -(zero,)334 3765 y(>)i(int)e(*status\))0 3997 y Fi(3)81 -b Fj(De\014ne)36 b(the)g(in)m(teger)i(v)-5 b(alue)36 -b(to)h(b)s(e)e(used)h(to)h(signify)f(unde\014ned)e(pixels)i(in)g(the)g -(primary)f(arra)m(y)i(or)f(image)227 4109 y(extension.)54 -b(This)34 b(is)g(only)h(used)f(if)g(BITPIX)g(=)h(8,)h(16,)g(or)f(32.)54 -b(This)34 b(do)s(es)g(not)h(create)h(or)e(c)m(hange)i(the)227 -4222 y(v)-5 b(alue)31 b(of)g(the)f(BLANK)h(k)m(eyw)m(ord)g(in)f(the)g -(header.)95 4454 y Fe(int)47 b(fits_set_imgnull)d(/)j(ffpnul)286 -4567 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(nulval,)h(>)i(int)e(*status\))0 -4799 y Fi(4)81 b Fj(De\014ne)36 b(the)g(string)g(to)g(b)s(e)f(used)g -(to)i(signify)f(unde\014ned)e(pixels)i(in)f(a)h(column)g(in)g(an)f -(ASCI)s(I)g(table.)58 b(This)227 4912 y(do)s(es)30 b(not)h(create)h(or) -e(c)m(hange)i(the)e(v)-5 b(alue)31 b(of)g(the)f(TNULLn)g(k)m(eyw)m -(ord.)95 5143 y Fe(int)47 b(fits_set_atblnull)c(/)48 -b(ffsnul)286 5256 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(char)i -(*nulstr,)f(>)h(int)g(*status\))0 5488 y Fi(5)81 b Fj(De\014ne)34 -b(the)h(v)-5 b(alue)34 b(to)h(b)s(e)f(used)g(to)h(signify)f -(unde\014ned)e(pixels)j(in)f(an)g(in)m(teger)i(column)e(in)g(a)g -(binary)g(table)227 5601 y(\(where)29 b(TF)m(ORMn)f(=)g('B',)i('I',)f -(or)f('J'\).)i(This)d(do)s(es)i(not)f(create)j(or)d(c)m(hange)i(the)e -(v)-5 b(alue)29 b(of)g(the)g(TNULLn)227 5714 y(k)m(eyw)m(ord.)p -eop end -%%Page: 111 119 -TeXDict begin 111 118 bop 0 299 a Fh(9.5.)72 b(SPECIALIZED)29 -b(FITS)g(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)32 b(OR)d(IMA)m(GE)j(EXTENSION) -d(I/O)h(R)m(OUTINES)80 b Fj(111)95 555 y Fe(int)47 b(fits_set_btblnull) -c(/)48 b(fftnul)286 668 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e -(LONGLONG)h(nulval,)g(>)h(int)g(*status\))0 995 y Ff(9.5)135 -b(Sp)t(ecialized)61 b(FITS)e(Primary)i(Arra)l(y)f(or)h(IMA)l(GE)e -(Extension)j(I/O)306 1144 y(Routines)0 1394 y Fj(These)27 -b(routines)h(read)f(or)h(write)g(data)g(v)-5 b(alues)28 -b(in)g(the)f(primary)g(data)h(arra)m(y)h(\(i.e.,)g(the)f(\014rst)f(HDU) -i(in)e(the)h(FITS)0 1507 y(\014le\))37 b(or)g(an)f(IMA)m(GE)h -(extension.)60 b(Automatic)39 b(data)e(t)m(yp)s(e)g(con)m(v)m(ersion)g -(is)g(p)s(erformed)e(for)h(if)h(the)g(data)g(t)m(yp)s(e)0 -1620 y(of)c(the)g(FITS)f(arra)m(y)h(\(as)g(de\014ned)f(b)m(y)g(the)h -(BITPIX)g(k)m(eyw)m(ord\))g(di\013ers)g(from)f(the)h(data)g(t)m(yp)s(e) -g(of)g(the)g(arra)m(y)g(in)0 1733 y(the)c(calling)i(routine.)40 -b(The)28 b(data)i(v)-5 b(alues)29 b(are)h(automatically)i(scaled)d(b)m -(y)g(the)h(BSCALE)e(and)g(BZER)m(O)h(header)0 1846 y(v)-5 -b(alues)25 b(as)h(they)f(are)g(b)s(eing)g(written)g(or)g(read)f(from)h -(the)g(FITS)f(arra)m(y)-8 b(.)40 b(Unlik)m(e)26 b(the)f(basic)h -(routines)e(describ)s(ed)g(in)0 1959 y(the)31 b(previous)g(c)m(hapter,) -i(most)e(of)h(these)g(routines)f(sp)s(eci\014cally)h(supp)s(ort)d(the)j -(FITS)e(random)h(groups)f(format.)0 2072 y(See)h(App)s(endix)d(B)j(for) -f(the)h(de\014nition)f(of)g(the)h(parameters)g(used)e(in)h(these)h -(routines.)0 2232 y(The)24 b(more)h(primitiv)m(e)h(reading)f(and)f -(writing)h(routines)f(\(i.)40 b(e.,)26 b(\013ppr)p 2364 -2232 28 4 v 32 w(,)g(\013ppn)p 2653 2232 V 31 w(,)g(\013ppn,)f(\013gp)m -(v)p 3185 2232 V 33 w(,)h(or)f(\013gpf)p 3552 2232 V -32 w(\))g(simply)0 2345 y(treat)g(the)g(primary)e(arra)m(y)i(as)f(a)h -(long)g(1-dimensional)g(arra)m(y)g(of)f(pixels,)i(ignoring)f(the)f(in)m -(trinsic)h(dimensionalit)m(y)0 2458 y(of)30 b(the)g(arra)m(y)-8 -b(.)42 b(When)30 b(dealing)h(with)e(a)i(2D)g(image,)g(for)f(example,)h -(the)f(application)i(program)e(m)m(ust)g(calculate)0 -2571 y(the)i(pixel)g(o\013set)g(in)f(the)h(1-D)h(arra)m(y)f(that)g -(corresp)s(onds)e(to)i(an)m(y)g(particular)g(X,)g(Y)f(co)s(ordinate)i -(in)e(the)g(image.)0 2684 y(C)25 b(programmers)h(should)f(note)h(that)g -(the)h(ordering)e(of)h(arra)m(ys)g(in)g(FITS)f(\014les,)i(and)e(hence)h -(in)g(all)g(the)g(CFITSIO)0 2797 y(calls,)40 b(is)d(more)g(similar)h -(to)f(the)h(dimensionalit)m(y)g(of)f(arra)m(ys)g(in)g(F)-8 -b(ortran)38 b(rather)f(than)f(C.)h(F)-8 b(or)38 b(instance)g(if)f(a)0 -2910 y(FITS)28 b(image)i(has)e(NAXIS1)h(=)f(100)i(and)e(NAXIS2)h(=)f -(50,)i(then)e(a)h(2-D)h(arra)m(y)f(just)f(large)i(enough)e(to)i(hold)e -(the)0 3022 y(image)k(should)d(b)s(e)h(declared)h(as)f(arra)m -(y[50][100])k(and)c(not)h(as)f(arra)m(y[100][50].)0 3183 -y(F)-8 b(or)30 b(con)m(v)m(enience,)i(higher-lev)m(el)g(routines)d(are) -h(also)h(pro)m(vided)e(to)h(sp)s(eci\014cally)h(deal)f(with)f(2D)i -(images)f(\(\013p2d)p 3872 3183 V 0 3296 a(and)c(\013g2d)p -372 3296 V 33 w(\))h(and)f(3D)i(data)f(cub)s(es)f(\(\013p3d)p -1467 3296 V 59 w(and)g(\013g3d)p 1893 3296 V 33 w(\).)40 -b(The)26 b(dimensionalit)m(y)i(of)f(the)g(FITS)f(image)i(is)e(passed)0 -3408 y(b)m(y)36 b(the)h(naxis1,)h(naxis2,)h(and)d(naxis3)h(parameters)f -(and)g(the)h(declared)f(dimensions)g(of)h(the)f(program)g(arra)m(y)0 -3521 y(are)30 b(passed)g(in)f(the)h(dim1)g(and)f(dim2)h(parameters.)41 -b(Note)31 b(that)f(the)g(dimensions)f(of)h(the)g(program)g(arra)m(y)g -(ma)m(y)0 3634 y(b)s(e)35 b(larger)h(than)f(the)h(dimensions)f(of)h -(the)g(FITS)e(arra)m(y)-8 b(.)58 b(F)-8 b(or)36 b(example)g(if)g(a)g -(FITS)e(image)j(with)e(NAXIS1)h(=)0 3747 y(NAXIS2)g(=)g(400)h(is)f -(read)g(in)m(to)h(a)g(program)f(arra)m(y)g(whic)m(h)g(is)g(dimensioned) -f(as)i(512)g(x)f(512)h(pixels,)h(then)e(the)0 3860 y(image)g(will)f -(just)f(\014ll)g(the)h(lo)m(w)m(er)h(left)f(corner)f(of)h(the)g(arra)m -(y)g(with)f(pixels)h(in)f(the)h(range)g(1)g(-)g(400)g(in)g(the)f(X)h -(an)0 3973 y(Y)g(directions.)54 b(This)34 b(has)h(the)g(e\013ect)h(of)f -(taking)g(a)h(con)m(tiguous)f(set)h(of)f(pixel)g(v)-5 -b(alue)35 b(in)f(the)h(FITS)f(arra)m(y)i(and)0 4086 y(writing)30 -b(them)g(to)h(a)f(non-con)m(tiguous)h(arra)m(y)g(in)e(program)h(memory) -g(\(i.e.,)i(there)e(are)h(no)m(w)f(some)g(blank)g(pixels)0 -4199 y(around)f(the)i(edge)g(of)g(the)f(image)i(in)e(the)g(program)g -(arra)m(y\).)0 4359 y(The)k(most)i(general)f(set)h(of)f(routines)f -(\(\013pss)p 1560 4359 V 33 w(,)i(\013gsv)p 1836 4359 -V 33 w(,)g(and)e(\013gsf)p 2273 4359 V 33 w(\))h(ma)m(y)h(b)s(e)e(used) -g(to)h(transfer)g(a)g(rectangular)0 4472 y(subset)27 -b(of)h(the)g(pixels)f(in)h(a)g(FITS)f(N-dimensional)h(image)h(to)f(or)g -(from)f(an)g(arra)m(y)i(whic)m(h)e(has)g(b)s(een)g(declared)h(in)0 -4585 y(the)h(calling)h(program.)40 b(The)28 b(fpixel)h(and)f(lpixel)h -(parameters)g(are)g(in)m(teger)h(arra)m(ys)f(whic)m(h)f(sp)s(ecify)g -(the)h(starting)0 4698 y(and)k(ending)f(pixel)i(co)s(ordinate)g(in)f -(eac)m(h)h(dimension)f(\(starting)h(with)f(1,)h(not)g(0\))g(of)f(the)g -(FITS)g(image)h(that)g(is)0 4811 y(to)f(b)s(e)e(read)g(or)h(written.)45 -b(It)32 b(is)g(imp)s(ortan)m(t)g(to)h(note)f(that)h(these)f(are)g(the)g -(starting)h(and)e(ending)g(pixels)h(in)g(the)0 4924 y(FITS)i(image,)k -(not)d(in)f(the)h(declared)h(arra)m(y)f(in)f(the)h(program.)54 -b(The)35 b(arra)m(y)g(parameter)g(in)g(these)g(routines)g(is)0 -5036 y(treated)f(simply)e(as)h(a)f(large)i(one-dimensional)g(arra)m(y)f -(of)f(the)h(appropriate)g(data)g(t)m(yp)s(e)g(con)m(taining)h(the)f -(pixel)0 5149 y(v)-5 b(alues;)37 b(The)d(pixel)h(v)-5 -b(alues)35 b(in)g(the)f(FITS)g(arra)m(y)h(are)g(read/written)g(from/to) -h(this)e(program)h(arra)m(y)g(in)f(strict)0 5262 y(sequence)d(without)f -(an)m(y)h(gaps;)g(it)g(is)f(up)f(to)j(the)e(calling)i(routine)e(to)i -(correctly)f(in)m(terpret)g(the)g(dimensionalit)m(y)0 -5375 y(of)d(this)f(arra)m(y)-8 b(.)41 b(The)27 b(t)m(w)m(o)i(FITS)e -(reading)h(routines)f(\(\013gsv)p 2018 5375 V 61 w(and)g(\013gsf)p -2415 5375 V 61 w(\))h(also)g(ha)m(v)m(e)h(an)f(`inc')g(parameter)g -(whic)m(h)0 5488 y(de\014nes)33 b(the)h(data)h(sampling)f(in)m(terv)-5 -b(al)36 b(in)d(eac)m(h)j(dimension)d(of)h(the)h(FITS)e(arra)m(y)-8 -b(.)53 b(F)-8 b(or)35 b(example,)h(if)e(inc[0]=2)0 5601 -y(and)i(inc[1]=3)j(when)d(reading)h(a)g(2-dimensional)h(FITS)e(image,) -41 b(then)36 b(only)h(ev)m(ery)h(other)f(pixel)h(in)e(the)i(\014rst)0 -5714 y(dimension)30 b(and)g(ev)m(ery)h(3rd)f(pixel)g(in)g(the)h(second) -f(dimension)g(will)h(b)s(e)f(returned)f(to)i(the)f('arra)m(y')i -(parameter.)p eop end -%%Page: 112 120 -TeXDict begin 112 119 bop 0 299 a Fj(112)958 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Fj(Tw)m(o)f(t)m(yp)s(es)h(of)f(routines)g(are)h -(pro)m(vided)e(to)i(read)f(the)h(data)g(arra)m(y)f(whic)m(h)g(di\013er) -g(in)g(the)h(w)m(a)m(y)g(unde\014ned)d(pixels)0 668 y(are)38 -b(handled.)60 b(The)37 b(\014rst)g(t)m(yp)s(e)g(of)g(routines)h -(\(e.g.,)i(\013gp)m(v)p 2059 668 28 4 v 34 w(\))d(simply)g(return)f(an) -h(arra)m(y)h(of)g(data)g(elemen)m(ts)g(in)0 781 y(whic)m(h)30 -b(unde\014ned)f(pixels)h(are)h(set)g(equal)g(to)h(a)f(v)-5 -b(alue)31 b(sp)s(eci\014ed)e(b)m(y)i(the)g(user)e(in)i(the)f(`n)m(ulv) --5 b(al')32 b(parameter.)41 b(An)0 894 y(additional)30 -b(feature)f(of)g(these)h(routines)e(is)h(that)h(if)f(the)g(user)f(sets) -h(n)m(ulv)-5 b(al)29 b(=)g(0,)h(then)e(no)h(c)m(hec)m(ks)h(for)f -(unde\014ned)0 1007 y(pixels)c(will)g(b)s(e)g(p)s(erformed,)f(th)m(us)h -(reducing)f(the)h(amoun)m(t)h(of)f(CPU)f(pro)s(cessing.)39 -b(The)24 b(second)h(t)m(yp)s(e)g(of)g(routines)0 1120 -y(\(e.g.,)36 b(\013gpf)p 413 1120 V 32 w(\))e(returns)e(the)i(data)g -(elemen)m(t)g(arra)m(y)g(and,)g(in)f(addition,)h(a)g(c)m(har)g(arra)m -(y)f(that)h(indicates)h(whether)0 1233 y(the)f(v)-5 b(alue)34 -b(of)g(the)f(corresp)s(onding)g(data)h(pixel)g(is)g(unde\014ned)d(\(=)j -(1\))g(or)g(de\014ned)e(\(=)i(0\).)51 b(The)33 b(latter)i(t)m(yp)s(e)f -(of)0 1346 y(routines)d(ma)m(y)h(b)s(e)e(more)i(con)m(v)m(enien)m(t)h -(to)f(use)f(in)g(some)g(circumstances,)i(ho)m(w)m(ev)m(er,)g(it)e -(requires)g(an)g(additional)0 1458 y(arra)m(y)g(of)f(logical)j(v)-5 -b(alues)31 b(whic)m(h)f(can)h(b)s(e)e(un)m(wieldy)h(when)g(w)m(orking)g -(with)g(large)i(data)f(arra)m(ys.)0 1732 y Fi(1)81 b -Fj(W)-8 b(rite)31 b(elemen)m(ts)h(in)m(to)f(the)g(FITS)f(data)h(arra)m -(y)-8 b(.)95 2005 y Fe(int)47 b(fits_write_img)d(/)k(ffppr)286 -2117 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(LONGLONG)g(firstelem,)g -(LONGLONG)h(nelements,)334 2230 y(DTYPE)g(*array,)g(int)h(*status\);)95 -2456 y(int)g(fits_write_img_[byt,)c(sht,)j(usht,)h(int,)f(uint,)h(lng,) -f(ulng,)h(lnglng,)e(flt,)i(dbl])g(/)286 2569 y -(ffppr[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 2682 y(\(fitsfile)f(*fptr,)g -(long)g(group,)g(LONGLONG)g(firstelem,)f(LONGLONG)h(nelements,)334 -2795 y(DTYPE)g(*array,)g(>)i(int)f(*status\);)95 3021 -y(int)g(fits_write_imgnull)c(/)48 b(ffppn)286 3134 y(\(fitsfile)e -(*fptr,)g(int)h(datatype,)e(LONGLONG)g(firstelem,)g(LONGLONG)h -(nelements,)334 3247 y(DTYPE)g(*array,)g(DTYPE)h(*nulval,)e(>)j(int)f -(*status\);)95 3472 y(int)g(fits_write_imgnull_[byt,)42 -b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f(ulng,)h(lnglng,)e(flt,)i(dbl])g -(/)286 3585 y(ffppn[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 -3698 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(LONGLONG)g(firstelem,)525 -3811 y(LONGLONG)g(nelements,)f(DTYPE)h(*array,)g(DTYPE)g(nulval,)g(>)h -(int)g(*status\);)0 4084 y Fi(2)81 b Fj(Set)30 b(data)h(arra)m(y)g -(elemen)m(ts)h(as)e(unde\014ned.)95 4357 y Fe(int)47 -b(fits_write_img_null)c(/)k(ffppru)286 4470 y(\(fitsfile)f(*fptr,)g -(long)g(group,)g(LONGLONG)g(firstelem,)f(LONGLONG)h(nelements,)334 -4583 y(>)i(int)e(*status\))0 4856 y Fi(3)81 b Fj(W)-8 -b(rite)32 b(v)-5 b(alues)30 b(in)m(to)i(group)e(parameters.)42 -b(This)30 b(routine)g(only)h(applies)g(to)g(the)g(`Random)f(Group)s -(ed')g(FITS)227 4969 y(format)22 b(whic)m(h)f(has)g(b)s(een)f(used)h -(for)g(applications)h(in)f(radio)h(in)m(terferometry)-8 -b(,)25 b(but)20 b(is)h(o\016cially)i(deprecated)227 5082 -y(for)30 b(future)g(use.)95 5355 y Fe(int)47 b(fits_write_grppar_[byt,) -42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f(ulng,)h(lnglng,)f(flt,)g -(dbl])h(/)286 5468 y(ffpgp[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 -5581 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(long)h(firstelem,)e(long)i -(nelements,)334 5694 y(>)h(DTYPE)e(*array,)g(int)h(*status\))p -eop end -%%Page: 113 121 -TeXDict begin 113 120 bop 0 299 a Fh(9.5.)72 b(SPECIALIZED)29 -b(FITS)g(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)32 b(OR)d(IMA)m(GE)j(EXTENSION) -d(I/O)h(R)m(OUTINES)80 b Fj(113)0 555 y Fi(4)h Fj(W)-8 -b(rite)31 b(a)g(2-D)h(or)e(3-D)h(image)h(in)m(to)f(the)g(data)g(arra)m -(y)-8 b(.)95 776 y Fe(int)47 b(fits_write_2d_[byt,)c(sht,)k(usht,)f -(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(flt,)g(dbl])h(/)286 -889 y(ffp2d[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 1002 y(\(fitsfile)f -(*fptr,)g(long)g(group,)g(LONGLONG)g(dim1,)g(LONGLONG)g(naxis1,)334 -1115 y(LONGLONG)g(naxis2,)f(DTYPE)i(*array,)f(>)h(int)g(*status\))95 -1341 y(int)g(fits_write_3d_[byt,)c(sht,)k(usht,)f(int,)h(uint,)f(lng,)h -(ulng,)f(lnglng,)g(flt,)g(dbl])h(/)286 1453 y -(ffp3d[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 1566 y(\(fitsfile)f(*fptr,)g -(long)g(group,)g(LONGLONG)g(dim1,)g(LONGLONG)g(dim2,)g(LONGLONG)g -(naxis1,)334 1679 y(LONGLONG)g(naxis2,)f(LONGLONG)h(naxis3,)g(DTYPE)g -(*array,)g(>)h(int)g(*status\))0 1900 y Fi(5)81 b Fj(W)-8 -b(rite)31 b(an)g(arbitrary)f(data)h(subsection)f(in)m(to)i(the)e(data)h -(arra)m(y)-8 b(.)95 2121 y Fe(int)47 b(fits_write_subset_[byt,)42 -b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f(ulng,)h(lnglng,)f(flt,)g(dbl])h -(/)286 2234 y(ffpss[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 -2347 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(long)h(naxis,)f(long)h -(*naxes,)334 2460 y(long)g(*fpixel,)e(long)i(*lpixel,)e(DTYPE)i -(*array,)f(>)h(int)g(*status\))0 2680 y Fi(6)81 b Fj(Read)30 -b(elemen)m(ts)i(from)e(the)g(FITS)g(data)h(arra)m(y)-8 -b(.)95 2901 y Fe(int)47 b(fits_read_img)e(/)i(ffgpv)286 -3014 y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(long)g(firstelem,) -f(long)i(nelements,)334 3127 y(DTYPE)f(*nulval,)g(>)h(DTYPE)g(*array,)f -(int)h(*anynul,)e(int)i(*status\))95 3353 y(int)g(fits_read_img_[byt,)c -(sht,)k(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(flt,)g(dbl])h -(/)286 3466 y(ffgpv[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 -3579 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(long)h(firstelem,)e(long)i -(nelements,)334 3692 y(DTYPE)f(nulval,)g(>)i(DTYPE)e(*array,)g(int)h -(*anynul,)e(int)i(*status\))95 3917 y(int)g(fits_read_imgnull)c(/)48 -b(ffgpf)286 4030 y(\(fitsfile)e(*fptr,)g(int)94 b(datatype,)46 -b(long)g(firstelem,)f(long)i(nelements,)334 4143 y(>)h(DTYPE)e(*array,) -g(char)g(*nullarray,)f(int)i(*anynul,)f(int)g(*status\))95 -4369 y(int)95 b(fits_read_imgnull_[byt,)42 b(sht,)k(usht,)h(int,)f -(uint,)h(lng,)f(ulng,)h(flt,)f(dbl])h(/)334 4482 y -(ffgpf[b,i,ui,k,uk,j,uj,jj)o(,e,)o(d])334 4595 y(\(fitsfile)e(*fptr,)h -(long)h(group,)f(long)h(firstelem,)e(long)h(nelements,)334 -4708 y(>)i(DTYPE)e(*array,)g(char)g(*nullarray,)f(int)i(*anynul,)f(int) -g(*status\))0 4929 y Fi(7)81 b Fj(Read)29 b(v)-5 b(alues)31 -b(from)e(group)g(parameters.)41 b(This)29 b(routine)g(only)h(applies)g -(to)h(the)e(`Random)h(Group)s(ed')f(FITS)227 5041 y(format)22 -b(whic)m(h)f(has)g(b)s(een)f(used)h(for)g(applications)h(in)f(radio)h -(in)m(terferometry)-8 b(,)25 b(but)20 b(is)h(o\016cially)i(deprecated) -227 5154 y(for)30 b(future)g(use.)95 5375 y Fe(int)95 -b(fits_read_grppar_[byt,)42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f -(ulng,)h(lnglng,)f(flt,)g(dbl])h(/)334 5488 y -(ffggp[b,i,ui,k,uk,j,uj,jj)o(,e,)o(d])334 5601 y(\(fitsfile)e(*fptr,)h -(long)h(group,)f(long)h(firstelem,)e(long)h(nelements,)334 -5714 y(>)i(DTYPE)e(*array,)g(int)h(*status\))p eop end -%%Page: 114 122 -TeXDict begin 114 121 bop 0 299 a Fj(114)958 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Fi(8)81 b Fj(Read)37 b(2-D)h(or)g(3-D)g(image)g -(from)f(the)g(data)h(arra)m(y)-8 b(.)62 b(Unde\014ned)36 -b(pixels)i(in)e(the)i(arra)m(y)g(will)f(b)s(e)g(set)g(equal)227 -668 y(to)32 b(the)g(v)-5 b(alue)31 b(of)h('n)m(ulv)-5 -b(al',)32 b(unless)f(n)m(ulv)-5 b(al=0)31 b(in)g(whic)m(h)g(case)h(no)f -(testing)i(for)e(unde\014ned)e(pixels)i(will)h(b)s(e)227 -781 y(p)s(erformed.)95 1049 y Fe(int)95 b(fits_read_2d_[byt,)43 -b(sht,)k(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(flt,)g(dbl])h -(/)334 1162 y(ffg2d[b,i,ui,k,uk,j,uj,jj)o(,e,)o(d])334 -1275 y(\(fitsfile)e(*fptr,)h(long)h(group,)f(DTYPE)h(nulval,)e -(LONGLONG)h(dim1,)g(LONGLONG)g(naxis1,)334 1387 y(LONGLONG)g(naxis2,)f -(>)j(DTYPE)e(*array,)g(int)h(*anynul,)f(int)g(*status\))95 -1613 y(int)95 b(fits_read_3d_[byt,)43 b(sht,)k(usht,)f(int,)h(uint,)f -(lng,)h(ulng,)f(lnglng,)g(flt,)g(dbl])h(/)334 1726 y -(ffg3d[b,i,ui,k,uk,j,uj,jj)o(,e,)o(d])334 1839 y(\(fitsfile)e(*fptr,)h -(long)h(group,)f(DTYPE)h(nulval,)e(LONGLONG)h(dim1,)334 -1952 y(LONGLONG)g(dim2,)g(LONGLONG)g(naxis1,)f(LONGLONG)h(naxis2,)g -(LONGLONG)f(naxis3,)334 2065 y(>)j(DTYPE)e(*array,)g(int)h(*anynul,)e -(int)i(*status\))0 2333 y Fi(9)81 b Fj(Read)30 b(an)g(arbitrary)h(data) -g(subsection)f(from)g(the)g(data)i(arra)m(y)-8 b(.)95 -2600 y Fe(int)95 b(fits_read_subset_[byt,)42 b(sht,)k(usht,)h(int,)f -(uint,)h(lng,)f(ulng,)h(lnglng,)f(flt,)g(dbl])h(/)334 -2713 y(ffgsv[b,i,ui,k,uk,j,uj,jj)o(,e,)o(d])334 2826 -y(\(fitsfile)e(*fptr,)h(int)h(group,)f(int)h(naxis,)f(long)h(*naxes,) -334 2939 y(long)g(*fpixel,)e(long)i(*lpixel,)e(long)i(*inc,)f(DTYPE)h -(nulval,)334 3052 y(>)h(DTYPE)e(*array,)g(int)h(*anynul,)e(int)i -(*status\))95 3278 y(int)95 b(fits_read_subsetnull_[byt)o(,)42 -b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f(ulng,)h(lnglng,)f(flt,)g(dbl])h -(/)334 3391 y(ffgsf[b,i,ui,k,uk,j,uj,jj)o(,e,)o(d])334 -3504 y(\(fitsfile)e(*fptr,)h(int)h(group,)f(int)h(naxis,)f(long)h -(*naxes,)334 3617 y(long)g(*fpixel,)e(long)i(*lpixel,)e(long)i(*inc,)f -(>)i(DTYPE)e(*array,)334 3730 y(char)h(*nullarray,)d(int)j(*anynul,)f -(int)h(*status\))0 4073 y Ff(9.6)135 b(Sp)t(ecialized)46 -b(FITS)e(ASCI)t(I)g(and)g(Binary)h(T)-11 b(able)45 b(Routines)0 -4328 y Fd(9.6.1)112 b(General)39 b(Column)f(Routines)0 -4543 y Fi(1)81 b Fj(Get)31 b(information)f(ab)s(out)g(an)g(existing)h -(ASCI)s(I)d(or)i(binary)f(table)i(column.)41 b(A)30 b(n)m(ull)g(p)s -(oin)m(ter)g(ma)m(y)h(b)s(e)e(giv)m(en)227 4656 y(for)40 -b(an)m(y)h(of)f(the)h(output)f(parameters)g(that)h(are)g(not)f(needed.) -70 b(D)m(A)-8 b(T)g(A)g(TYPE)42 b(is)e(a)h(c)m(haracter)h(string)227 -4769 y(whic)m(h)d(returns)e(the)i(data)g(t)m(yp)s(e)g(of)g(the)f -(column)h(as)g(de\014ned)e(b)m(y)i(the)f(TF)m(ORMn)h(k)m(eyw)m(ord)g -(\(e.g.,)j('I',)227 4882 y('J','E',)28 b('D',)g(etc.\).)41 -b(In)27 b(the)g(case)g(of)g(an)g(ASCI)s(I)f(c)m(haracter)i(column,)g(t) -m(yp)s(eco)s(de)f(will)g(ha)m(v)m(e)h(a)f(v)-5 b(alue)28 -b(of)f(the)227 4994 y(form)g('An')g(where)f('n')h(is)g(an)g(in)m(teger) -i(expressing)d(the)h(width)g(of)g(the)g(\014eld)g(in)f(c)m(haracters.) -41 b(F)-8 b(or)28 b(example,)227 5107 y(if)g(TF)m(ORM)h(=)e('160A8')k -(then)d(\013gb)s(cl)g(will)g(return)f(t)m(yp)s(ec)m(har='A8')j(and)d -(rep)s(eat=20.)41 b(All)29 b(the)f(returned)227 5220 -y(parameters)j(are)g(scalar)g(quan)m(tities.)95 5488 -y Fe(int)47 b(fits_get_acolparms)c(/)48 b(ffgacl)191 -5601 y(\(fitsfile)d(*fptr,)h(int)h(colnum,)f(>)h(char)g(*ttype,)f(long) -h(*tbcol,)239 5714 y(char)f(*tunit,)g(char)h(*tform,)f(double)g -(*scale,)f(double)i(*zero,)p eop end -%%Page: 115 123 -TeXDict begin 115 122 bop 0 299 a Fh(9.6.)72 b(SPECIALIZED)29 -b(FITS)g(ASCI)s(I)g(AND)i(BINAR)-8 b(Y)32 b(T)-8 b(ABLE)30 -b(R)m(OUTINES)933 b Fj(115)239 555 y Fe(char)46 b(*nulstr,)g(char)g -(*tdisp,)g(int)h(*status\))95 781 y(int)g(fits_get_bcolparms)c(/)48 -b(ffgbcl)286 894 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(>)j(char)f -(*ttype,)e(char)i(*tunit,)334 1007 y(char)g(*typechar,)e(long)h -(*repeat,)g(double)g(*scale,)g(double)g(*zero,)334 1120 -y(long)h(*nulval,)e(char)i(*tdisp,)f(int)94 b(*status\))95 -1346 y(int)47 b(fits_get_bcolparmsll)c(/)k(ffgbclll)286 -1458 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(>)j(char)f(*ttype,)e(char) -i(*tunit,)334 1571 y(char)g(*typechar,)e(LONGLONG)g(*repeat,)h(double)g -(*scale,)g(double)g(*zero,)334 1684 y(LONGLONG)g(*nulval,)f(char)i -(*tdisp,)f(int)94 b(*status\))0 1937 y Fi(2)81 b Fj(Return)27 -b(optimal)i(n)m(um)m(b)s(er)e(of)h(ro)m(ws)g(to)h(read)f(or)g(write)g -(at)h(one)f(time)h(for)f(maxim)m(um)g(I/O)f(e\016ciency)-8 -b(.)42 b(Refer)227 2050 y(to)25 b(the)g(\\Optimizing)g(Co)s(de")f -(section)i(in)e(Chapter)g(5)g(for)g(more)h(discussion)f(on)g(ho)m(w)g -(to)h(use)f(this)h(routine.)95 2416 y Fe(int)47 b(fits_get_rowsize)d(/) -j(ffgrsz)286 2529 y(\(fitsfile)f(*fptr,)g(long)g(*nrows,)g(*status\))0 -2782 y Fi(3)81 b Fj(De\014ne)22 b(the)g(zero)i(indexed)d(b)m(yte)i -(o\013set)g(of)g(the)f('heap')h(measured)e(from)h(the)h(start)g(of)f -(the)g(binary)g(table)h(data.)227 2895 y(By)30 b(default)g(the)f(heap)h -(is)f(assumed)g(to)h(start)g(immediately)h(follo)m(wing)g(the)f -(regular)f(table)i(data,)f(i.e.,)h(at)227 3008 y(lo)s(cation)38 -b(NAXIS1)f(x)g(NAXIS2.)59 b(This)36 b(routine)g(is)h(only)f(relev)-5 -b(an)m(t)38 b(for)e(binary)g(tables)h(whic)m(h)g(con)m(tain)227 -3121 y(v)-5 b(ariable)25 b(length)g(arra)m(y)g(columns)f(\(with)g(TF)m -(ORMn)g(=)g('Pt'\).)40 b(This)23 b(routine)i(also)g(automatically)i -(writes)227 3234 y(the)35 b(v)-5 b(alue)35 b(of)g(theap)f(to)h(a)g(k)m -(eyw)m(ord)g(in)g(the)f(extension)h(header.)53 b(This)34 -b(routine)g(m)m(ust)h(b)s(e)f(called)h(after)227 3347 -y(the)c(required)e(k)m(eyw)m(ords)h(ha)m(v)m(e)i(b)s(een)d(written)h -(\(with)g(\013ph)m(bn\))f(but)h(b)s(efore)f(an)m(y)i(data)g(is)f -(written)g(to)h(the)227 3460 y(table.)95 3713 y Fe(int)47 -b(fits_write_theap)d(/)j(ffpthp)286 3826 y(\(fitsfile)f(*fptr,)g(long)g -(theap,)g(>)i(int)f(*status\))0 4079 y Fi(4)81 b Fj(T)-8 -b(est)37 b(the)f(con)m(ten)m(ts)i(of)f(the)g(binary)e(table)j(v)-5 -b(ariable)37 b(arra)m(y)g(heap,)h(returning)e(the)g(size)h(of)g(the)g -(heap,)h(the)227 4192 y(n)m(um)m(b)s(er)30 b(of)h(un)m(used)e(b)m(ytes) -j(that)f(are)g(not)g(curren)m(tly)g(p)s(oin)m(ted)g(to)h(b)m(y)e(an)m -(y)i(of)f(the)g(descriptors,)g(and)f(the)227 4304 y(n)m(um)m(b)s(er)d -(of)h(b)m(ytes)h(whic)m(h)f(are)g(p)s(oin)m(ted)g(to)h(b)m(y)f(m)m -(ultiple)h(descriptors.)40 b(It)28 b(also)h(returns)e(v)-5 -b(alid)29 b(=)e(F)-10 b(ALSE)227 4417 y(if)31 b(an)m(y)f(of)h(the)f -(descriptors)h(p)s(oin)m(t)f(to)h(in)m(v)-5 b(alid)31 -b(addresses)f(out)g(of)h(range)g(of)f(the)h(heap.)95 -4670 y Fe(int)47 b(fits_test_heap)d(/)k(fftheap)286 4783 -y(\(fitsfile)e(*fptr,)g(>)h(LONGLONG)f(*heapsize,)f(LONGLONG)g -(*unused,)h(LONGLONG)f(*overlap,)334 4896 y(int)i(*validheap,)e(int)i -(*status\))0 5149 y Fi(5)81 b Fj(Re-pac)m(k)33 b(the)f(v)m(ectors)h(in) -e(the)h(binary)f(table)i(v)-5 b(ariable)32 b(arra)m(y)g(heap)g(to)g -(reco)m(v)m(er)i(an)m(y)e(un)m(used)e(space.)45 b(Nor-)227 -5262 y(mally)-8 b(,)40 b(when)d(a)g(v)m(ector)i(in)e(a)g(v)-5 -b(ariable)38 b(length)g(arra)m(y)f(column)g(is)g(rewritten)h(the)f -(previously)g(written)227 5375 y(arra)m(y)d(remains)e(in)h(the)g(heap)f -(as)h(w)m(asted)h(un)m(used)d(space.)49 b(This)32 b(routine)g(will)i -(repac)m(k)f(the)g(arra)m(ys)g(that)227 5488 y(are)h(still)g(in)f(use,) -h(th)m(us)f(eliminating)h(an)m(y)g(b)m(ytes)g(in)f(the)g(heap)g(that)h -(are)g(no)f(longer)h(in)f(use.)49 b(Note)34 b(that)227 -5601 y(if)f(sev)m(eral)h(v)m(ectors)g(p)s(oin)m(t)e(to)i(the)e(same)h -(b)m(ytes)g(in)g(the)f(heap,)i(then)e(this)g(routine)h(will)g(mak)m(e)g -(duplicate)227 5714 y(copies)e(of)g(the)g(b)m(ytes)f(for)h(eac)m(h)g(v) -m(ector,)h(whic)m(h)e(will)h(actually)h(expand)e(the)g(size)i(of)e(the) -h(heap.)p eop end -%%Page: 116 124 -TeXDict begin 116 123 bop 0 299 a Fj(116)958 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_compress_heap)c(/)48 -b(ffcmph)286 668 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*status\))0 -976 y Fd(9.6.2)112 b(Lo)m(w-Lev)m(el)39 b(T)-9 b(able)38 -b(Access)f(Routines)0 1198 y Fj(The)g(follo)m(wing)j(2)e(routines)f -(pro)m(vide)h(lo)m(w-lev)m(el)j(access)e(to)g(the)f(data)g(in)g(ASCI)s -(I)e(or)i(binary)f(tables)h(and)g(are)0 1311 y(mainly)29 -b(useful)f(as)i(an)f(e\016cien)m(t)h(w)m(a)m(y)g(to)g(cop)m(y)g(all)g -(or)f(part)g(of)g(a)g(table)h(from)f(one)g(lo)s(cation)i(to)f(another.) -40 b(These)0 1424 y(routines)24 b(simply)g(read)g(or)h(write)f(the)h -(sp)s(eci\014ed)e(n)m(um)m(b)s(er)g(of)i(consecutiv)m(e)h(b)m(ytes)f -(in)f(an)g(ASCI)s(I)f(or)h(binary)g(table,)0 1537 y(without)g(regard)g -(for)f(column)h(b)s(oundaries)e(or)i(the)g(ro)m(w)g(length)g(in)f(the)h -(table.)40 b(These)23 b(routines)h(do)f(not)h(p)s(erform)0 -1650 y(an)m(y)36 b(mac)m(hine)h(dep)s(enden)m(t)e(data)i(con)m(v)m -(ersion)g(or)g(b)m(yte)f(sw)m(apping.)58 b(See)36 b(App)s(endix)e(B)j -(for)f(the)g(de\014nition)g(of)0 1763 y(the)31 b(parameters)f(used)g -(in)g(these)h(routines.)0 2037 y Fi(1)81 b Fj(Read)30 -b(or)h(write)f(a)h(consecutiv)m(e)h(arra)m(y)f(of)g(b)m(ytes)f(from)g -(an)h(ASCI)s(I)d(or)j(binary)e(table)95 2311 y Fe(int)47 -b(fits_read_tblbytes)c(/)48 b(ffgtbb)286 2424 y(\(fitsfile)e(*fptr,)g -(LONGLONG)f(firstrow,)h(LONGLONG)f(firstchar,)g(LONGLONG)h(nchars,)334 -2537 y(>)i(unsigned)d(char)i(*values,)e(int)i(*status\))95 -2763 y(int)g(fits_write_tblbytes)c(/)k(ffptbb)286 2876 -y(\(fitsfile)f(*fptr,)g(LONGLONG)f(firstrow,)h(LONGLONG)f(firstchar,)g -(LONGLONG)h(nchars,)334 2989 y(unsigned)g(char)g(*values,)g(>)h(int)g -(*status\))0 3296 y Fd(9.6.3)112 b(W)-9 b(rite)37 b(Column)h(Data)g -(Routines)0 3516 y Fi(1)81 b Fj(W)-8 b(rite)28 b(elemen)m(ts)h(in)m(to) -f(an)g(ASCI)s(I)d(or)j(binary)e(table)j(column)e(\(in)g(the)h(CDU\).)g -(The)f(data)h(t)m(yp)s(e)f(of)h(the)f(arra)m(y)227 3629 -y(is)k(implied)f(b)m(y)g(the)h(su\016x)e(of)i(the)f(routine)h(name.)95 -3903 y Fe(int)47 b(fits_write_col_str)c(/)48 b(ffpcls)286 -4016 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f -(LONGLONG)h(firstelem,)334 4129 y(LONGLONG)g(nelements,)f(char)h -(**array,)g(>)h(int)g(*status\))95 4355 y(int)g -(fits_write_col_[log,byt,sh)o(t,u)o(sht,)o(int,)o(uin)o(t,ln)o(g,ul)o -(ng,)o(lngl)o(ng,f)o(lt,)o(dbl,)o(cmp,)o(dbl)o(cmp])41 -b(/)286 4468 y(ffpcl[l,b,i,ui,k,uk,j,uj,j)o(j,e)o(,d,c)o(,m])286 -4581 y(\(fitsfile)46 b(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,) -525 4694 y(LONGLONG)g(firstelem,)f(LONGLONG)g(nelements,)g(DTYPE)h -(*array,)g(>)i(int)f(*status\))0 4968 y Fi(2)81 b Fj(W)-8 -b(rite)36 b(elemen)m(ts)h(in)m(to)g(an)e(ASCI)s(I)f(or)i(binary)e -(table)j(column)e(substituting)g(the)h(appropriate)f(FITS)g(n)m(ull)227 -5081 y(v)-5 b(alue)31 b(for)f(an)m(y)h(elemen)m(ts)h(that)f(are)f -(equal)h(to)g(the)g(n)m(ulv)-5 b(al)31 b(parameter.)95 -5355 y Fe(int)47 b(fits_write_colnull_[log,)42 b(byt,)k(sht,)h(usht,)f -(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(flt,)h(dbl])f(/)286 -5468 y(ffpcn[l,b,i,ui,k,uk,j,uj,j)o(j,e)o(,d])286 5581 -y(\(fitsfile)g(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f -(LONGLONG)h(firstelem,)334 5694 y(LONGLONG)g(nelements,)f(DTYPE)h -(*array,)g(DTYPE)g(nulval,)g(>)h(int)g(*status\))p eop -end -%%Page: 117 125 -TeXDict begin 117 124 bop 0 299 a Fh(9.6.)72 b(SPECIALIZED)29 -b(FITS)g(ASCI)s(I)g(AND)i(BINAR)-8 b(Y)32 b(T)-8 b(ABLE)30 -b(R)m(OUTINES)933 b Fj(117)0 555 y Fi(3)81 b Fj(W)-8 -b(rite)27 b(string)g(elemen)m(ts)h(in)m(to)f(a)g(binary)f(table)h -(column)f(\(in)h(the)f(CDU\))i(substituting)e(the)g(FITS)g(n)m(ull)g(v) --5 b(alue)227 668 y(for)30 b(an)m(y)h(elemen)m(ts)h(that)f(are)g(equal) -f(to)i(the)e(n)m(ulstr)g(string.)95 921 y Fe(int)47 b -(fits_write_colnull_str)42 b(/)48 b(ffpcns)286 1034 y(\(fitsfile)e -(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f(LONGLONG)h(firstelem,) -334 1147 y(LONGLONG)g(nelements,)f(char)h(**array,)g(char)g(*nulstr,)g -(>)h(int)g(*status\))0 1399 y Fi(4)81 b Fj(W)-8 b(rite)34 -b(bit)f(v)-5 b(alues)33 b(in)m(to)h(a)g(binary)e(b)m(yte)h(\('B'\))i -(or)e(bit)g(\('X'\))h(table)g(column)f(\(in)g(the)g(CDU\).)h(Larra)m(y) -f(is)g(an)227 1512 y(arra)m(y)25 b(of)g(c)m(haracters)h(corresp)s -(onding)e(to)h(the)g(sequence)g(of)f(bits)h(to)g(b)s(e)f(written.)39 -b(If)24 b(an)g(elemen)m(t)i(of)f(larra)m(y)227 1625 y(is)k(true)g -(\(not)h(equal)f(to)h(zero\))g(then)f(the)g(corresp)s(onding)f(bit)h -(in)g(the)g(FITS)f(table)i(is)f(set)h(to)g(1,)g(otherwise)227 -1738 y(the)37 b(bit)g(is)g(set)g(to)g(0.)60 b(The)37 -b('X')g(column)f(in)h(a)g(FITS)f(table)h(is)g(alw)m(a)m(ys)h(padded)e -(out)h(to)g(a)g(m)m(ultiple)h(of)227 1851 y(8)f(bits)f(where)g(the)g -(bit)h(arra)m(y)f(starts)h(with)f(the)h(most)f(signi\014can)m(t)h(bit)g -(of)f(the)h(b)m(yte)g(and)e(w)m(orks)h(do)m(wn)227 1964 -y(to)m(w)m(ards)h(the)g(1's)f(bit.)59 b(F)-8 b(or)37 -b(example,)i(a)d('4X')h(arra)m(y)-8 b(,)39 b(with)d(the)h(\014rst)e -(bit)i(=)e(1)i(and)f(the)g(remaining)h(3)227 2077 y(bits)31 -b(=)g(0)h(is)f(equiv)-5 b(alen)m(t)33 b(to)f(the)g(8-bit)g(unsigned)e -(b)m(yte)i(decimal)g(v)-5 b(alue)32 b(of)g(128)g(\('1000)i(0000B'\).)g -(In)d(the)227 2189 y(case)h(of)f('X')g(columns,)g(CFITSIO)f(can)h -(write)g(to)g(all)h(8)f(bits)g(of)g(eac)m(h)h(b)m(yte)f(whether)f(they) -h(are)g(formally)227 2302 y(v)-5 b(alid)34 b(or)f(not.)50 -b(Th)m(us)32 b(if)i(the)f(column)g(is)h(de\014ned)e(as)h('4X',)i(and)e -(one)g(calls)i(\013p)s(clx)e(with)g(\014rstbit=1)g(and)227 -2415 y(n)m(bits=8,)i(then)f(all)g(8)h(bits)e(will)h(b)s(e)g(written)g -(in)m(to)g(the)g(\014rst)f(b)m(yte)i(\(as)f(opp)s(osed)f(to)i(writing)e -(the)h(\014rst)g(4)227 2528 y(bits)28 b(in)m(to)h(the)e(\014rst)g(ro)m -(w)h(and)f(then)h(the)g(next)g(4)g(bits)f(in)m(to)i(the)f(next)g(ro)m -(w\),)h(ev)m(en)f(though)f(the)h(last)h(4)f(bits)227 -2641 y(of)j(eac)m(h)g(b)m(yte)g(are)f(formally)h(not)f(de\014ned)f(and) -h(should)f(all)i(b)s(e)e(set)i(=)f(0.)41 b(It)30 b(should)f(also)j(b)s -(e)d(noted)h(that)227 2754 y(it)k(is)e(more)h(e\016cien)m(t)i(to)e -(write)g('X')h(columns)e(an)h(en)m(tire)h(b)m(yte)f(at)h(a)f(time,)h -(instead)f(of)g(bit)g(b)m(y)g(bit.)48 b(An)m(y)227 2867 -y(of)31 b(the)g(CFITSIO)e(routines)h(that)i(write)f(to)g(columns)f -(\(e.g.)43 b(\014ts)p 2481 2867 28 4 v 33 w(write)p 2716 -2867 V 33 w(col)p 2859 2867 V 33 w(b)m(yt\))32 b(ma)m(y)f(b)s(e)f(used) -g(for)g(this)227 2980 y(purp)s(ose.)60 b(These)36 b(routines)i(will)f -(in)m(terpret)h('X')f(columns)g(as)g(though)g(they)h(w)m(ere)f('B')h -(columns)f(\(e.g.,)227 3093 y('1X')32 b(through)d('8X')j(is)e(equiv)-5 -b(alen)m(t)32 b(to)f('1B',)h(and)e('9X')h(through)f('16X')i(is)e(equiv) --5 b(alen)m(t)32 b(to)f('2B'\).)95 3345 y Fe(int)47 b -(fits_write_col_bit)c(/)48 b(ffpclx)286 3458 y(\(fitsfile)e(*fptr,)g -(int)h(colnum,)e(LONGLONG)h(firstrow,)f(long)i(firstbit,)334 -3571 y(long)g(nbits,)f(char)g(*larray,)g(>)h(int)g(*status\))0 -3824 y Fi(5)81 b Fj(W)-8 b(rite)35 b(the)f(descriptor)g(for)f(a)h(v)-5 -b(ariable)35 b(length)f(column)g(in)f(a)i(binary)e(table.)52 -b(This)33 b(routine)g(can)i(b)s(e)e(used)227 3937 y(in)h(conjunction)g -(with)f(\013gdes)h(to)h(enable)f(2)g(or)g(more)g(arra)m(ys)h(to)f(p)s -(oin)m(t)g(to)h(the)f(same)g(storage)h(lo)s(cation)227 -4050 y(to)c(sa)m(v)m(e)h(storage)g(space)f(if)f(the)h(arra)m(ys)g(are)g -(iden)m(tical.)191 4302 y Fe(int)47 b(fits_write_descript)42 -b(/)48 b(ffpdes)382 4415 y(\(fitsfile)d(*fptr,)h(int)h(colnum,)f -(LONGLONG)f(rownum,)h(LONGLONG)g(repeat,)430 4528 y(LONGLONG)f(offset,) -h(>)h(int)g(*status\))0 4818 y Fd(9.6.4)112 b(Read)38 -b(Column)h(Data)f(Routines)0 5036 y Fj(Tw)m(o)28 b(t)m(yp)s(es)f(of)h -(routines)f(are)h(pro)m(vided)f(to)h(get)h(the)e(column)h(data)g(whic)m -(h)f(di\013er)g(in)g(the)h(w)m(a)m(y)h(unde\014ned)c(pixels)0 -5149 y(are)40 b(handled.)66 b(The)39 b(\014rst)g(set)h(of)f(routines)g -(\(\013gcv\))i(simply)e(return)f(an)h(arra)m(y)h(of)g(data)g(elemen)m -(ts)g(in)f(whic)m(h)0 5262 y(unde\014ned)28 b(pixels)j(are)g(set)g -(equal)g(to)g(a)g(v)-5 b(alue)31 b(sp)s(eci\014ed)f(b)m(y)h(the)f(user) -g(in)g(the)h('n)m(ullv)-5 b(al')32 b(parameter.)41 b(If)30 -b(n)m(ullv)-5 b(al)0 5375 y(=)22 b(0,)j(then)d(no)g(c)m(hec)m(ks)i(for) -e(unde\014ned)e(pixels)j(will)g(b)s(e)f(p)s(erformed,)g(th)m(us)g -(increasing)i(the)e(sp)s(eed)g(of)g(the)h(program.)0 -5488 y(The)36 b(second)g(set)g(of)h(routines)e(\(\013gcf)7 -b(\))38 b(returns)d(the)h(data)h(elemen)m(t)g(arra)m(y)g(and)e(in)h -(addition)g(a)h(logical)h(arra)m(y)0 5601 y(of)33 b(\015ags)f(whic)m(h) -g(de\014nes)g(whether)g(the)g(corresp)s(onding)g(data)h(pixel)f(is)h -(unde\014ned.)44 b(See)33 b(App)s(endix)e(B)i(for)f(the)0 -5714 y(de\014nition)e(of)h(the)f(parameters)h(used)e(in)h(these)h -(routines.)p eop end -%%Page: 118 126 -TeXDict begin 118 125 bop 0 299 a Fj(118)958 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)0 555 y Fj(An)m(y)39 b(column,)h(regardless)f(of)g(it's)g -(in)m(trinsic)g(data)h(t)m(yp)s(e,)h(ma)m(y)e(b)s(e)f(read)g(as)h(a)g -(string.)66 b(It)38 b(should)g(b)s(e)g(noted)0 668 y(ho)m(w)m(ev)m(er) -32 b(that)f(reading)f(a)h(n)m(umeric)f(column)g(as)h(a)f(string)h(is)f -(10)h(-)g(100)g(times)g(slo)m(w)m(er)h(than)e(reading)g(the)h(same)0 -781 y(column)g(as)h(a)g(n)m(um)m(b)s(er)e(due)h(to)h(the)g(large)h(o)m -(v)m(erhead)f(in)g(constructing)g(the)g(formatted)g(strings.)44 -b(The)31 b(displa)m(y)0 894 y(format)26 b(of)g(the)h(returned)d -(strings)i(will)g(b)s(e)g(determined)f(b)m(y)h(the)g(TDISPn)f(k)m(eyw)m -(ord,)j(if)d(it)i(exists,)h(otherwise)e(b)m(y)0 1007 -y(the)h(data)g(t)m(yp)s(e)f(of)h(the)f(column.)39 b(The)26 -b(length)h(of)g(the)f(returned)f(strings)h(\(not)h(including)f(the)h(n) -m(ull)f(terminating)0 1120 y(c)m(haracter\))38 b(can)e(b)s(e)g -(determined)f(with)h(the)g(\014ts)p 1722 1120 28 4 v -33 w(get)p 1875 1120 V 34 w(col)p 2019 1120 V 33 w(displa)m(y)p -2330 1120 V 33 w(width)g(routine.)57 b(The)36 b(follo)m(wing)h(TDISPn)0 -1233 y(displa)m(y)31 b(formats)f(are)h(curren)m(tly)f(supp)s(orted:)191 -1490 y Fe(Iw.m)142 b(Integer)191 1603 y(Ow.m)g(Octal)46 -b(integer)191 1716 y(Zw.m)142 b(Hexadecimal)45 b(integer)191 -1829 y(Fw.d)142 b(Fixed)46 b(floating)g(point)191 1942 -y(Ew.d)142 b(Exponential)45 b(floating)g(point)191 2055 -y(Dw.d)142 b(Exponential)45 b(floating)g(point)191 2168 -y(Gw.d)142 b(General;)46 b(uses)g(Fw.d)h(if)g(significance)d(not)j -(lost,)g(else)f(Ew.d)0 2425 y Fj(where)37 b(w)h(is)g(the)g(width)f(in)h -(c)m(haracters)h(of)f(the)h(displa)m(y)m(ed)f(v)-5 b(alues,)41 -b(m)c(is)h(the)g(minim)m(um)g(n)m(um)m(b)s(er)e(of)i(digits)0 -2538 y(displa)m(y)m(ed,)31 b(and)f(d)g(is)g(the)h(n)m(um)m(b)s(er)e(of) -h(digits)h(to)g(the)g(righ)m(t)g(of)g(the)f(decimal.)42 -b(The)30 b(.m)g(\014eld)g(is)g(optional.)0 2796 y Fi(1)81 -b Fj(Read)29 b(elemen)m(ts)i(from)e(an)g(ASCI)s(I)f(or)i(binary)f -(table)h(column)f(\(in)h(the)f(CDU\).)i(These)e(routines)g(return)g -(the)227 2909 y(v)-5 b(alues)30 b(of)g(the)g(table)h(column)f(arra)m(y) -g(elemen)m(ts.)42 b(Unde\014ned)28 b(arra)m(y)j(elemen)m(ts)g(will)f(b) -s(e)f(returned)g(with)h(a)227 3022 y(v)-5 b(alue)30 b(=)e(n)m(ulv)-5 -b(al,)30 b(unless)e(n)m(ulv)-5 b(al)29 b(=)f(0)i(\(or)f(=)f(')h(')g -(for)g(\013gcvs\))g(in)g(whic)m(h)f(case)i(no)f(c)m(hec)m(king)i(for)d -(unde\014ned)227 3135 y(v)-5 b(alues)28 b(will)g(b)s(e)f(p)s(erformed.) -38 b(The)27 b(an)m(yn)m(ul)h(parameter)g(is)g(set)g(to)g(true)f(if)h -(an)m(y)g(of)f(the)h(returned)f(elemen)m(ts)227 3247 -y(are)k(unde\014ned.)95 3505 y Fe(int)47 b(fits_read_col_str)c(/)48 -b(ffgcvs)286 3618 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h -(firstrow,)f(LONGLONG)h(firstelem,)334 3731 y(LONGLONG)g(nelements,)f -(char)h(*nulstr,)g(>)h(char)g(**array,)e(int)i(*anynul,)334 -3844 y(int)g(*status\))95 4070 y(int)g(fits_read_col_[log,byt,sht)o -(,us)o(ht,i)o(nt,u)o(int)o(,lng)o(,uln)o(g,)41 b(lnglng,)46 -b(flt,)h(dbl,)g(cmp,)f(dblcmp])g(/)286 4183 y -(ffgcv[l,b,i,ui,k,uk,j,uj,j)o(j,e)o(,d,c)o(,m])286 4295 -y(\(fitsfile)g(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f -(LONGLONG)h(firstelem,)334 4408 y(LONGLONG)g(nelements,)f(DTYPE)h -(nulval,)g(>)h(DTYPE)g(*array,)e(int)i(*anynul,)334 4521 -y(int)g(*status\))0 4779 y Fi(2)81 b Fj(Read)39 b(elemen)m(ts)i(and)e -(n)m(ull)h(\015ags)g(from)f(an)g(ASCI)s(I)g(or)g(binary)g(table)i -(column)e(\(in)h(the)g(CHDU\).)g(These)227 4892 y(routines)29 -b(return)e(the)i(v)-5 b(alues)29 b(of)g(the)g(table)h(column)e(arra)m -(y)i(elemen)m(ts.)41 b(An)m(y)29 b(unde\014ned)d(arra)m(y)k(elemen)m -(ts)227 5005 y(will)k(ha)m(v)m(e)h(the)f(corresp)s(onding)e(n)m -(ullarra)m(y)i(elemen)m(t)h(set)f(equal)g(to)g(TR)m(UE.)g(The)f(an)m -(yn)m(ul)h(parameter)g(is)227 5118 y(set)d(to)g(true)f(if)h(an)m(y)g -(of)f(the)h(returned)e(elemen)m(ts)j(are)e(unde\014ned.)95 -5375 y Fe(int)47 b(fits_read_colnull_str)42 b(/)48 b(ffgcfs)286 -5488 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f -(LONGLONG)h(firstelem,)334 5601 y(LONGLONG)g(nelements,)f(>)i(char)g -(**array,)e(char)i(*nullarray,)e(int)i(*anynul,)334 5714 -y(int)g(*status\))p eop end -%%Page: 119 127 -TeXDict begin 119 126 bop 0 299 a Fh(9.6.)72 b(SPECIALIZED)29 -b(FITS)g(ASCI)s(I)g(AND)i(BINAR)-8 b(Y)32 b(T)-8 b(ABLE)30 -b(R)m(OUTINES)933 b Fj(119)95 668 y Fe(int)47 b -(fits_read_colnull_[log,byt)o(,sh)o(t,us)o(ht,i)o(nt,)o(uint)o(,lng)o -(,ul)o(ng,l)o(ngln)o(g,f)o(lt,d)o(bl,c)o(mp,)o(dblc)o(mp])41 -b(/)286 781 y(ffgcf[l,b,i,ui,k,uk,j,uj,j)o(j,e)o(,d,c)o(,m])286 -894 y(\(fitsfile)46 b(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)334 -1007 y(LONGLONG)g(firstelem,)f(LONGLONG)g(nelements,)g(>)j(DTYPE)e -(*array,)334 1120 y(char)h(*nullarray,)d(int)j(*anynul,)f(int)h -(*status\))0 1384 y Fi(3)81 b Fj(Read)24 b(an)g(arbitrary)g(data)h -(subsection)f(from)g(an)g(N-dimensional)h(arra)m(y)g(in)f(a)g(binary)g -(table)h(v)m(ector)h(column.)227 1497 y(Unde\014ned)21 -b(pixels)i(in)f(the)h(arra)m(y)g(will)g(b)s(e)f(set)h(equal)h(to)f(the) -g(v)-5 b(alue)23 b(of)g('n)m(ulv)-5 b(al',)25 b(unless)d(n)m(ulv)-5 -b(al=0)23 b(in)f(whic)m(h)227 1610 y(case)37 b(no)e(testing)h(for)f -(unde\014ned)e(pixels)i(will)h(b)s(e)f(p)s(erformed.)53 -b(The)35 b(\014rst)g(and)f(last)i(ro)m(ws)g(in)f(the)g(table)227 -1722 y(to)30 b(b)s(e)e(read)h(are)g(sp)s(eci\014ed)g(b)m(y)g -(fpixel\(naxis+1\))g(and)g(lpixel\(naxis+1\),)i(and)d(hence)h(are)h -(treated)g(as)f(the)227 1835 y(next)38 b(higher)f(dimension)g(of)h(the) -f(FITS)g(N-dimensional)h(arra)m(y)-8 b(.)63 b(The)37 -b(INC)h(parameter)g(sp)s(eci\014es)f(the)227 1948 y(sampling)31 -b(in)m(terv)-5 b(al)31 b(in)f(eac)m(h)i(dimension)e(b)s(et)m(w)m(een)h -(the)f(data)h(elemen)m(ts)h(that)f(will)g(b)s(e)e(returned.)95 -2212 y Fe(int)47 b(fits_read_subset_[byt,)42 b(sht,)47 -b(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(flt,)h(dbl])f(/)286 -2325 y(ffgsv[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 2438 -y(\(fitsfile)g(*fptr,)g(int)h(colnum,)e(int)i(naxis,)f(long)h(*naxes,)f -(long)h(*fpixel,)334 2551 y(long)g(*lpixel,)e(long)i(*inc,)f(DTYPE)h -(nulval,)e(>)j(DTYPE)e(*array,)g(int)h(*anynul,)334 2664 -y(int)g(*status\))0 2928 y Fi(4)81 b Fj(Read)24 b(an)g(arbitrary)g -(data)h(subsection)f(from)g(an)g(N-dimensional)h(arra)m(y)g(in)f(a)g -(binary)g(table)h(v)m(ector)h(column.)227 3041 y(An)m(y)34 -b(Unde\014ned)e(pixels)i(in)g(the)f(arra)m(y)i(will)f(ha)m(v)m(e)h(the) -f(corresp)s(onding)e('n)m(ullarra)m(y')j(elemen)m(t)g(set)f(equal)227 -3154 y(to)40 b(TR)m(UE.)e(The)h(\014rst)e(and)h(last)i(ro)m(ws)e(in)h -(the)f(table)i(to)f(b)s(e)f(read)h(are)g(sp)s(eci\014ed)e(b)m(y)i -(fpixel\(naxis+1\))227 3267 y(and)i(lpixel\(naxis+1\),)47 -b(and)41 b(hence)h(are)g(treated)g(as)g(the)g(next)g(higher)g -(dimension)f(of)h(the)g(FITS)f(N-)227 3379 y(dimensional)i(arra)m(y)-8 -b(.)78 b(The)41 b(INC)h(parameter)h(sp)s(eci\014es)f(the)h(sampling)f -(in)m(terv)-5 b(al)44 b(in)e(eac)m(h)i(dimension)227 -3492 y(b)s(et)m(w)m(een)31 b(the)g(data)g(elemen)m(ts)h(that)f(will)f -(b)s(e)g(returned.)95 3756 y Fe(int)47 b(fits_read_subsetnull_[byt,)41 -b(sht,)47 b(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(flt,)g -(dbl])h(/)286 3869 y(ffgsf[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 -3982 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i(naxis,)f(long)h -(*naxes,)334 4095 y(long)g(*fpixel,)e(long)i(*lpixel,)e(long)i(*inc,)f -(>)i(DTYPE)e(*array,)334 4208 y(char)h(*nullarray,)d(int)j(*anynul,)f -(int)h(*status\))0 4472 y Fi(5)81 b Fj(Read)35 b(bit)g(v)-5 -b(alues)35 b(from)g(a)g(b)m(yte)h(\('B'\))g(or)f(bit)g(\(`X`\))h(table) -g(column)f(\(in)g(the)g(CDU\).)h(Larra)m(y)g(is)f(an)f(arra)m(y)227 -4585 y(of)g(logical)i(v)-5 b(alues)34 b(corresp)s(onding)f(to)h(the)g -(sequence)g(of)g(bits)g(to)g(b)s(e)f(read.)51 b(If)33 -b(larra)m(y)h(is)g(true)f(then)h(the)227 4698 y(corresp)s(onding)i(bit) -h(w)m(as)g(set)h(to)f(1,)j(otherwise)d(the)g(bit)g(w)m(as)g(set)h(to)f -(0.)61 b(The)37 b('X')g(column)g(in)f(a)i(FITS)227 4811 -y(table)e(is)e(alw)m(a)m(ys)i(padded)e(out)h(to)g(a)g(m)m(ultiple)g(of) -g(8)g(bits)f(where)g(the)h(bit)g(arra)m(y)g(starts)g(with)f(the)h(most) -227 4924 y(signi\014can)m(t)j(bit)e(of)h(the)g(b)m(yte)g(and)f(w)m -(orks)g(do)m(wn)h(to)m(w)m(ards)g(the)g(1's)g(bit.)59 -b(F)-8 b(or)37 b(example,)i(a)e('4X')h(arra)m(y)-8 b(,)227 -5036 y(with)33 b(the)h(\014rst)e(bit)i(=)f(1)h(and)e(the)i(remaining)f -(3)h(bits)f(=)g(0)h(is)f(equiv)-5 b(alen)m(t)35 b(to)f(the)g(8-bit)g -(unsigned)e(b)m(yte)227 5149 y(v)-5 b(alue)31 b(of)f(128.)42 -b(Note)31 b(that)g(in)e(the)i(case)g(of)f('X')g(columns,)g(CFITSIO)f -(can)h(read)g(all)h(8)f(bits)g(of)g(eac)m(h)h(b)m(yte)227 -5262 y(whether)h(they)h(are)g(formally)g(v)-5 b(alid)33 -b(or)f(not.)48 b(Th)m(us)31 b(if)i(the)f(column)h(is)f(de\014ned)f(as)i -('4X',)h(and)e(one)h(calls)227 5375 y(\013gcx)d(with)f(\014rstbit=1)f -(and)h(n)m(bits=8,)g(then)g(all)h(8)f(bits)g(will)g(b)s(e)g(read)g -(from)f(the)h(\014rst)g(b)m(yte)g(\(as)h(opp)s(osed)227 -5488 y(to)39 b(reading)f(the)g(\014rst)g(4)g(bits)g(from)g(the)g -(\014rst)f(ro)m(w)h(and)g(then)f(the)i(\014rst)e(4)h(bits)g(from)g(the) -g(next)g(ro)m(w\),)227 5601 y(ev)m(en)g(though)f(the)g(last)i(4)e(bits) -g(of)h(eac)m(h)g(b)m(yte)g(are)f(formally)h(not)g(de\014ned.)60 -b(It)37 b(should)f(also)i(b)s(e)f(noted)227 5714 y(that)f(it)f(is)h -(more)f(e\016cien)m(t)h(to)g(read)f('X')h(columns)e(an)h(en)m(tire)h(b) -m(yte)g(at)g(a)f(time,)i(instead)e(of)h(bit)f(b)m(y)g(bit.)p -eop end -%%Page: 120 128 -TeXDict begin 120 127 bop 0 299 a Fj(120)958 b Fh(CHAPTER)30 -b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 -b(R)m(OUTINES)227 555 y Fj(An)m(y)f(of)g(the)h(CFITSIO)d(routines)i -(that)g(read)g(columns)g(\(e.g.)42 b(\014ts)p 2520 555 -28 4 v 32 w(read)p 2724 555 V 33 w(col)p 2867 555 V 34 -w(b)m(yt\))29 b(ma)m(y)h(b)s(e)e(used)g(for)h(this)227 -668 y(purp)s(ose.)60 b(These)36 b(routines)i(will)f(in)m(terpret)h('X') -f(columns)g(as)g(though)g(they)h(w)m(ere)f('B')h(columns)f(\(e.g.,)227 -781 y('8X')32 b(is)e(equiv)-5 b(alen)m(t)32 b(to)f('1B',)h(and)e('16X') -i(is)e(equiv)-5 b(alen)m(t)32 b(to)f('2B'\).)95 1041 -y Fe(int)47 b(fits_read_col_bit)c(/)48 b(ffgcx)286 1154 -y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f -(LONGLONG)h(firstbit,)334 1267 y(LONGLONG)g(nbits,)g(>)h(char)g -(*larray,)e(int)i(*status\))0 1526 y Fi(6)81 b Fj(Read)31 -b(an)m(y)h(consecutiv)m(e)i(set)e(of)g(bits)f(from)h(an)f('X')h(or)g -('B')h(column)e(and)g(in)m(terpret)h(them)g(as)f(an)h(unsigned)227 -1639 y(n-bit)h(in)m(teger.)48 b(n)m(bits)33 b(m)m(ust)f(b)s(e)g(less)h -(than)g(16)g(or)g(32)g(in)f(\013gcxui)i(and)d(\013gcxuk,)j(resp)s -(ectiv)m(ely)-8 b(.)49 b(If)32 b(nro)m(ws)227 1752 y(is)c(greater)h -(than)f(1,)h(then)e(the)h(same)h(set)f(of)g(bits)g(will)g(b)s(e)f(read) -h(from)f(eac)m(h)i(ro)m(w,)g(starting)g(with)e(\014rstro)m(w.)227 -1865 y(The)j(bits)g(are)h(n)m(um)m(b)s(ered)e(with)h(1)h(=)f(the)h -(most)f(signi\014can)m(t)i(bit)e(of)h(the)f(\014rst)g(elemen)m(t)i(of)e -(the)h(column.)95 2125 y Fe(int)47 b(fits_read_col_bit_[usht,)42 -b(uint])k(/)h(ffgcx[ui,uk])286 2238 y(\(fitsfile)f(*fptr,)g(int)h -(colnum,)e(LONGLONG)h(firstrow,)f(LONGLONG,)h(nrows,)334 -2351 y(long)h(firstbit,)e(long)i(nbits,)f(>)h(DTYPE)g(*array,)e(int)i -(*status\))0 2611 y Fi(7)81 b Fj(Return)27 b(the)i(descriptor)f(for)h -(a)g(v)-5 b(ariable)29 b(length)g(column)f(in)h(a)g(binary)e(table.)41 -b(The)28 b(descriptor)h(consists)g(of)227 2723 y(2)j(in)m(teger)g -(parameters:)42 b(the)31 b(n)m(um)m(b)s(er)f(of)h(elemen)m(ts)i(in)d -(the)h(arra)m(y)h(and)e(the)h(starting)h(o\013set)g(relativ)m(e)h(to) -227 2836 y(the)c(start)h(of)e(the)h(heap.)40 b(The)29 -b(\014rst)f(pair)g(of)h(routine)g(returns)e(a)i(single)h(descriptor)e -(whereas)h(the)g(second)227 2949 y(pair)34 b(of)h(routine)f(returns)g -(the)g(descriptors)g(for)g(a)h(range)g(of)f(ro)m(ws)h(in)f(the)g -(table.)54 b(The)34 b(only)g(di\013erence)227 3062 y(b)s(et)m(w)m(een) -42 b(the)f(2)g(routines)f(in)h(eac)m(h)h(pair)e(is)h(that)g(one)g -(returns)f(the)h(parameters)g(as)g('long')g(in)m(tegers,)227 -3175 y(whereas)30 b(the)h(other)g(returns)e(the)h(v)-5 -b(alues)31 b(as)g(64-bit)g('LONGLONG')g(in)m(tegers.)95 -3435 y Fe(int)47 b(fits_read_descript)c(/)48 b(ffgdes)286 -3548 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(rownum,)g(>)h -(long)g(*repeat,)525 3661 y(long)g(*offset,)e(int)i(*status\))95 -3886 y(int)g(fits_read_descriptll)c(/)k(ffgdesll)286 -3999 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(LONGLONG)h(rownum,)g(>)h -(LONGLONG)f(*repeat,)525 4112 y(LONGLONG)g(*offset,)f(int)i(*status\)) -95 4338 y(int)g(fits_read_descripts)c(/)k(ffgdess)286 -4451 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f -(LONGLONG)h(nrows)334 4564 y(>)i(long)e(*repeat,)g(long)g(*offset,)g -(int)h(*status\))95 4790 y(int)g(fits_read_descriptsll)42 -b(/)48 b(ffgdessll)286 4903 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e -(LONGLONG)h(firstrow,)f(LONGLONG)h(nrows)334 5016 y(>)i(LONGLONG)d -(*repeat,)h(LONGLONG)f(*offset,)h(int)h(*status\))p eop -end -%%Page: 121 129 -TeXDict begin 121 128 bop 0 1225 a Fg(Chapter)65 b(10)0 -1687 y Fm(Extended)77 b(File)g(Name)g(Syn)-6 b(tax)0 -2216 y Ff(10.1)136 b(Ov)l(erview)0 2466 y Fj(CFITSIO)30 -b(supp)s(orts)f(an)j(extended)f(syn)m(tax)h(when)f(sp)s(ecifying)g(the) -h(name)f(of)h(the)g(data)g(\014le)f(to)h(b)s(e)f(op)s(ened)g(or)0 -2579 y(created)g(that)g(includes)f(the)h(follo)m(wing)h(features:)136 -2813 y Fc(\017)46 b Fj(CFITSIO)40 b(can)i(read)f(IRAF)h(format)g -(images)g(whic)m(h)f(ha)m(v)m(e)i(header)e(\014le)h(names)f(that)h(end) -f(with)g(the)227 2926 y('.imh')d(extension,)i(as)e(w)m(ell)g(as)g -(reading)f(and)g(writing)g(FITS)g(\014les,)i(This)e(feature)h(is)f -(implemen)m(ted)h(in)227 3039 y(CFITSIO)29 b(b)m(y)i(\014rst)e(con)m(v) -m(erting)k(the)d(IRAF)h(image)h(in)m(to)f(a)g(temp)s(orary)f(FITS)g -(format)h(\014le)f(in)g(memory)-8 b(,)227 3152 y(then)35 -b(op)s(ening)f(the)h(FITS)f(\014le.)54 b(An)m(y)35 b(of)g(the)g(usual)f -(CFITSIO)g(routines)g(then)h(ma)m(y)g(b)s(e)f(used)g(to)i(read)227 -3265 y(the)31 b(image)g(header)f(or)h(data.)41 b(Similarly)-8 -b(,)31 b(ra)m(w)f(binary)g(data)h(arra)m(ys)f(can)h(b)s(e)f(read)g(b)m -(y)g(con)m(v)m(erting)i(them)227 3378 y(on)f(the)f(\015y)g(in)m(to)h -(virtual)g(FITS)f(images.)136 3557 y Fc(\017)46 b Fj(FITS)37 -b(\014les)g(on)g(the)g(In)m(ternet)h(can)f(b)s(e)g(read)g(\(and)g -(sometimes)h(written\))f(using)g(the)g(FTP)-8 b(,)38 -b(HTTP)-8 b(,)37 b(or)227 3670 y(R)m(OOT)30 b(proto)s(cols.)136 -3849 y Fc(\017)46 b Fj(FITS)30 b(\014les)g(can)h(b)s(e)f(pip)s(ed)f(b)s -(et)m(w)m(een)i(tasks)f(on)h(the)f(stdin)g(and)g(stdout)g(streams.)136 -4028 y Fc(\017)46 b Fj(FITS)36 b(\014les)h(can)g(b)s(e)f(read)h(and)f -(written)h(in)g(shared)f(memory)-8 b(.)60 b(This)36 b(can)h(p)s(oten)m -(tially)i(ac)m(hiev)m(e)g(b)s(etter)227 4141 y(data)26 -b(I/O)e(p)s(erformance)g(compared)h(to)h(reading)f(and)f(writing)g(the) -h(same)h(FITS)e(\014les)g(on)h(magnetic)h(disk.)136 4320 -y Fc(\017)46 b Fj(Compressed)30 b(FITS)f(\014les)i(in)f(gzip)h(or)f -(Unix)g(COMPRESS)f(format)h(can)h(b)s(e)f(directly)h(read.)136 -4499 y Fc(\017)46 b Fj(Output)28 b(FITS)h(\014les)g(can)g(b)s(e)g -(written)g(directly)h(in)e(compressed)h(gzip)h(format,)g(th)m(us)e(sa)m -(ving)i(disk)f(space.)136 4678 y Fc(\017)46 b Fj(FITS)26 -b(table)h(columns)f(can)h(b)s(e)f(created,)i(mo)s(di\014ed,)f(or)f -(deleted)h('on-the-\015y')g(as)g(the)g(table)g(is)f(op)s(ened)g(b)m(y) -227 4791 y(CFITSIO.)32 b(This)h(creates)i(a)e(virtual)h(FITS)f(\014le)g -(con)m(taining)i(the)f(mo)s(di\014cations)f(that)h(is)g(then)f(op)s -(ened)227 4904 y(b)m(y)e(the)f(application)i(program.)136 -5083 y Fc(\017)46 b Fj(T)-8 b(able)29 b(ro)m(ws)e(ma)m(y)i(b)s(e)e -(selected,)j(or)e(\014ltered)g(out,)g(on)g(the)g(\015y)f(when)g(the)h -(table)h(is)f(op)s(ened)f(b)m(y)g(CFITSIO,)227 5196 y(based)22 -b(on)f(an)g(user-sp)s(eci\014ed)g(expression.)38 b(Only)21 -b(ro)m(ws)g(for)g(whic)m(h)h(the)g(expression)f(ev)-5 -b(aluates)23 b(to)f('TR)m(UE')227 5309 y(are)31 b(retained)g(in)f(the)g -(cop)m(y)i(of)e(the)h(table)g(that)g(is)f(op)s(ened)g(b)m(y)g(the)h -(application)g(program.)136 5488 y Fc(\017)46 b Fj(Histogram)28 -b(images)g(ma)m(y)f(b)s(e)f(created)h(on)f(the)h(\015y)f(b)m(y)g -(binning)g(the)g(v)-5 b(alues)27 b(in)f(table)i(columns,)f(resulting) -227 5601 y(in)36 b(a)g(virtual)h(N-dimensional)f(FITS)g(image.)59 -b(The)35 b(application)i(program)f(then)g(only)g(sees)g(the)h(FITS)227 -5714 y(image)32 b(\(in)e(the)h(primary)e(arra)m(y\))j(instead)e(of)h -(the)f(original)i(FITS)d(table.)1882 5942 y(121)p eop -end -%%Page: 122 130 -TeXDict begin 122 129 bop 0 299 a Fj(122)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fj(The)39 b(latter)i(3)f(table)h(\014ltering)f(features)g(in)f -(particular)h(add)f(v)m(ery)h(p)s(o)m(w)m(erful)f(data)i(pro)s(cessing) -e(capabilities)0 668 y(directly)33 b(in)m(to)g(CFITSIO,)e(and)h(hence)h -(in)m(to)g(ev)m(ery)g(task)g(that)g(uses)f(CFITSIO)f(to)i(read)f(or)h -(write)f(FITS)g(\014les.)0 781 y(F)-8 b(or)29 b(example,)g(these)f -(features)h(transform)e(a)h(v)m(ery)g(simple)g(program)g(that)g(just)g -(copies)g(an)g(input)f(FITS)g(\014le)h(to)0 894 y(a)c(new)f(output)h -(\014le)g(\(lik)m(e)h(the)f(`\014tscop)m(y')h(program)e(that)i(is)e -(distributed)g(with)h(CFITSIO\))e(in)m(to)j(a)f(m)m(ultipurp)s(ose)0 -1007 y(FITS)33 b(\014le)g(pro)s(cessing)g(to)s(ol.)51 -b(By)33 b(app)s(ending)f(fairly)i(simple)f(quali\014ers)g(on)m(to)h -(the)g(name)f(of)h(the)f(input)g(FITS)0 1120 y(\014le,)45 -b(the)d(user)f(can)h(p)s(erform)e(quite)i(complex)h(table)f(editing)h -(op)s(erations)f(\(e.g.,)k(create)d(new)e(columns,)k(or)0 -1233 y(\014lter)32 b(out)h(ro)m(ws)f(in)g(a)g(table\))i(or)e(create)i -(FITS)d(images)j(b)m(y)e(binning)f(or)h(histogramming)h(the)g(v)-5 -b(alues)32 b(in)g(table)0 1346 y(columns.)47 b(In)32 -b(addition,)h(these)g(functions)f(ha)m(v)m(e)i(b)s(een)e(co)s(ded)g -(using)g(new)g(state-of-the)j(art)e(algorithms)g(that)0 -1458 y(are,)e(in)f(some)h(cases,)g(10)h(-)e(100)i(times)f(faster)g -(than)f(previous)g(widely)g(used)f(implemen)m(tations.)0 -1619 y(Before)34 b(describing)f(the)h(complete)h(syn)m(tax)f(for)f(the) -h(extended)f(FITS)g(\014le)g(names)g(in)g(the)h(next)g(section,)h(here) -0 1732 y(are)c(a)g(few)f(examples)h(of)f(FITS)g(\014le)g(names)h(that)f -(giv)m(e)i(a)f(quic)m(k)g(o)m(v)m(erview)h(of)f(the)f(allo)m(w)m(ed)i -(syn)m(tax:)136 2005 y Fc(\017)46 b Fe(myfile.fits)p -Fj(:)38 b(the)30 b(simplest)h(case)g(of)g(a)g(FITS)e(\014le)i(on)f -(disk)g(in)g(the)h(curren)m(t)f(directory)-8 b(.)136 -2207 y Fc(\017)46 b Fe(myfile.imh)p Fj(:)i(op)s(ens)34 -b(an)h(IRAF)g(format)g(image)i(\014le)e(and)f(con)m(v)m(erts)j(it)e(on) -g(the)g(\015y)g(in)m(to)h(a)f(temp)s(orary)227 2320 y(FITS)30 -b(format)h(image)g(in)f(memory)h(whic)m(h)f(can)g(then)g(b)s(e)g(read)g -(with)g(an)m(y)h(other)g(CFITSIO)e(routine.)136 2521 -y Fc(\017)46 b Fe(rawfile.dat[i512,512])p Fj(:)35 b(op)s(ens)30 -b(a)g(ra)m(w)h(binary)e(data)i(arra)m(y)g(\(a)g(512)g(x)f(512)i(short)e -(in)m(teger)h(arra)m(y)g(in)227 2634 y(this)i(case\))i(and)d(con)m(v)m -(erts)j(it)e(on)g(the)g(\015y)g(in)m(to)h(a)f(temp)s(orary)g(FITS)f -(format)h(image)i(in)d(memory)h(whic)m(h)227 2747 y(can)e(then)f(b)s(e) -g(read)g(with)g(an)m(y)h(other)f(CFITSIO)f(routine.)136 -2948 y Fc(\017)46 b Fe(myfile.fits.gz)p Fj(:)d(if)33 -b(this)g(is)g(the)g(name)g(of)h(a)f(new)g(output)g(\014le,)h(the)f -('.gz')i(su\016x)d(will)h(cause)h(it)g(to)g(b)s(e)227 -3061 y(compressed)c(in)g(gzip)h(format)g(when)e(it)i(is)g(written)f(to) -h(disk.)136 3263 y Fc(\017)46 b Fe(myfile.fits.gz[events,)c(2])p -Fj(:)35 b(op)s(ens)20 b(and)f(uncompresses)g(the)i(gzipp)s(ed)f(\014le) -g(m)m(y\014le.\014ts)h(then)f(mo)m(v)m(es)227 3376 y(to)31 -b(the)g(extension)g(with)f(the)h(k)m(eyw)m(ords)f(EXTNAME)h(=)f -('EVENTS')g(and)g(EXTVER)g(=)g(2.)136 3577 y Fc(\017)46 -b Fe(-)p Fj(:)40 b(a)30 b(dash)f(\(min)m(us)g(sign\))h(signi\014es)g -(that)g(the)g(input)f(\014le)g(is)h(to)g(b)s(e)f(read)h(from)f(the)h -(stdin)f(\014le)h(stream,)g(or)227 3690 y(that)d(the)g(output)f(\014le) -h(is)f(to)h(b)s(e)f(written)h(to)g(the)g(stdout)f(stream.)40 -b(See)27 b(also)g(the)g(stream://)h(driv)m(er)e(whic)m(h)227 -3803 y(pro)m(vides)37 b(a)f(more)h(e\016cien)m(t,)i(but)d(more)g -(restricted)h(metho)s(d)f(of)h(reading)f(or)g(writing)h(to)g(the)f -(stdin)g(or)227 3916 y(stdout)31 b(streams.)136 4117 -y Fc(\017)46 b Fe(ftp://legacy.gsfc.nasa.go)o(v/te)o(st/v)o(ela)o(.fit) -o(s)p Fj(:)k(FITS)37 b(\014les)h(in)g(an)m(y)h(ftp)e(arc)m(hiv)m(e)j -(site)f(on)f(the)227 4230 y(In)m(ternet)31 b(ma)m(y)g(b)s(e)f(directly) -h(op)s(ened)e(with)h(read-only)h(access.)136 4432 y Fc(\017)46 -b Fe(http://legacy.gsfc.nasa.g)o(ov/s)o(oftw)o(are)o(/tes)o(t.fi)o(ts)p -Fj(:)33 b(an)m(y)27 b(v)-5 b(alid)28 b(URL)f(to)h(a)g(FITS)e(\014le)i -(on)f(the)227 4545 y(W)-8 b(eb)31 b(ma)m(y)g(b)s(e)f(op)s(ened)g(with)g -(read-only)g(access.)136 4746 y Fc(\017)46 b Fe -(root://legacy.gsfc.nasa.g)o(ov/t)o(est/)o(vel)o(a.fi)o(ts)p -Fj(:)e(similar)36 b(to)g(ftp)f(access)i(except)f(that)g(it)g(pro-)227 -4859 y(vides)30 b(write)h(as)f(w)m(ell)h(as)g(read)f(access)h(to)g(the) -f(\014les)h(across)f(the)h(net)m(w)m(ork.)41 b(This)29 -b(uses)h(the)h(ro)s(ot)f(proto)s(col)227 4972 y(dev)m(elop)s(ed)h(at)g -(CERN.)136 5174 y Fc(\017)46 b Fe(shmem://h2[events])p -Fj(:)j(op)s(ens)36 b(the)i(FITS)e(\014le)h(in)g(a)g(shared)f(memory)h -(segmen)m(t)h(and)f(mo)m(v)m(es)h(to)g(the)227 5287 y(EVENTS)30 -b(extension.)136 5488 y Fc(\017)46 b Fe(mem://)p Fj(:)65 -b(creates)44 b(a)g(scratc)m(h)g(output)f(\014le)g(in)g(core)h(computer) -f(memory)-8 b(.)79 b(The)43 b(resulting)g('\014le')h(will)227 -5601 y(disapp)s(ear)25 b(when)f(the)i(program)f(exits,)i(so)f(this)f -(is)h(mainly)f(useful)g(for)g(testing)i(purp)s(oses)c(when)i(one)g(do)s -(es)227 5714 y(not)31 b(w)m(an)m(t)g(a)g(p)s(ermanen)m(t)f(cop)m(y)h -(of)f(the)h(output)f(\014le.)p eop end -%%Page: 123 131 -TeXDict begin 123 130 bop 0 299 a Fh(10.1.)73 b(O)m(VER)-10 -b(VIEW)2995 b Fj(123)136 555 y Fc(\017)46 b Fe(myfile.fits[3;)e -(Images\(10\)])p Fj(:)c(op)s(ens)30 b(a)i(cop)m(y)g(of)g(the)g(image)g -(con)m(tained)h(in)e(the)h(10th)g(ro)m(w)f(of)h(the)227 -668 y('Images')38 b(column)f(in)g(the)g(binary)f(table)i(in)e(the)h -(3th)g(extension)h(of)f(the)g(FITS)f(\014le.)60 b(The)37 -b(virtual)g(\014le)227 781 y(that)31 b(is)g(op)s(ened)e(b)m(y)i(the)f -(application)i(just)e(con)m(tains)h(this)f(single)h(image)h(in)e(the)h -(primary)e(arra)m(y)-8 b(.)136 973 y Fc(\017)46 b Fe -(myfile.fits[1:512:2,)d(1:512:2])p Fj(:)c(op)s(ens)30 -b(a)h(section)h(of)g(the)f(input)f(image)i(ranging)f(from)f(the)h(1st) -227 1086 y(to)k(the)f(512th)h(pixel)f(in)g(X)g(and)g(Y,)g(and)f -(selects)j(ev)m(ery)e(second)g(pixel)h(in)e(b)s(oth)g(dimensions,)i -(resulting)227 1198 y(in)30 b(a)h(256)h(x)e(256)i(pixel)e(input)g -(image)h(in)g(this)f(case.)136 1390 y Fc(\017)46 b Fe -(myfile.fits[EVENTS][col)c(Rad)47 b(=)g(sqrt\(X**2)e(+)j(Y**2\)])p -Fj(:)36 b(creates)27 b(and)d(op)s(ens)h(a)g(virtual)h(\014le)f(on)227 -1503 y(the)h(\015y)f(that)i(is)f(iden)m(tical)h(to)g(m)m -(y\014le.\014ts)f(except)g(that)h(it)f(will)g(con)m(tain)h(a)f(new)g -(column)f(in)h(the)g(EVENTS)227 1616 y(extension)41 b(called)h('Rad')f -(whose)f(v)-5 b(alue)41 b(is)g(computed)f(using)h(the)f(indicated)h -(expression)g(whic)m(h)f(is)h(a)227 1729 y(function)30 -b(of)h(the)f(v)-5 b(alues)31 b(in)f(the)h(X)f(and)g(Y)h(columns.)136 -1920 y Fc(\017)46 b Fe(myfile.fits[EVENTS][PHA)c(>)47 -b(5])p Fj(:)41 b(creates)33 b(and)d(op)s(ens)g(a)i(virtual)f(FITS)f -(\014les)h(that)g(is)g(iden)m(tical)i(to)227 2033 y('m)m -(y\014le.\014ts')40 b(except)h(that)f(the)f(EVENTS)g(table)h(will)g -(only)f(con)m(tain)i(the)e(ro)m(ws)h(that)g(ha)m(v)m(e)g(v)-5 -b(alues)40 b(of)227 2146 y(the)34 b(PHA)g(column)g(greater)h(than)e(5.) -52 b(In)33 b(general,)j(an)m(y)e(arbitrary)g(b)s(o)s(olean)f -(expression)h(using)f(a)i(C)e(or)227 2259 y(F)-8 b(ortran-lik)m(e)31 -b(syn)m(tax,)e(whic)m(h)f(ma)m(y)h(com)m(bine)g(AND)g(and)f(OR)f(op)s -(erators,)i(ma)m(y)g(b)s(e)f(used)f(to)i(select)h(ro)m(ws)227 -2372 y(from)g(a)h(table.)136 2564 y Fc(\017)46 b Fe -(myfile.fits[EVENTS][bin)c(\(X,Y\)=1,2048,4])p Fj(:)34 -b(creates)26 b(a)g(temp)s(orary)f(FITS)g(primary)f(arra)m(y)i(im-)227 -2677 y(age)38 b(whic)m(h)e(is)h(computed)f(on)g(the)h(\015y)f(b)m(y)g -(binning)f(\(i.e,)40 b(computing)c(the)h(2-dimensional)g(histogram\)) -227 2789 y(of)d(the)f(v)-5 b(alues)34 b(in)f(the)h(X)g(and)e(Y)i -(columns)f(of)h(the)f(EVENTS)g(extension.)50 b(In)33 -b(this)g(case)i(the)e(X)h(and)f(Y)227 2902 y(co)s(ordinates)h(range)g -(from)f(1)h(to)g(2048)h(and)e(the)h(image)g(pixel)g(size)g(is)g(4)f -(units)g(in)g(b)s(oth)g(dimensions,)h(so)227 3015 y(the)d(resulting)f -(image)i(is)e(512)i(x)e(512)i(pixels)f(in)f(size.)136 -3207 y Fc(\017)46 b Fj(The)31 b(\014nal)g(example)i(com)m(bines)f(man)m -(y)f(of)h(these)g(feature)g(in)m(to)g(one)g(complex)g(expression)f -(\(it)i(is)e(brok)m(en)227 3320 y(in)m(to)h(sev)m(eral)f(lines)g(for)f -(clarit)m(y\):)370 3576 y Fe(ftp://legacy.gsfc.nasa.gov)o(/dat)o(a/s)o -(ampl)o(e.fi)o(ts.)o(gz[E)o(VENT)o(S])370 3689 y([col)47 -b(phacorr)f(=)h(pha)g(*)h(1.1)f(-)g(0.3][phacorr)e(>=)i(5.0)g(&&)g -(phacorr)f(<=)h(14.0])370 3801 y([bin)g(\(X,Y\)=32])227 -4057 y Fj(In)37 b(this)h(case,)j(CFITSIO)36 b(\(1\))j(copies)g(and)e -(uncompresses)g(the)h(FITS)f(\014le)h(from)f(the)h(ftp)f(site)i(on)f -(the)227 4170 y(legacy)g(mac)m(hine,)h(\(2\))e(mo)m(v)m(es)g(to)g(the)g -('EVENTS')f(extension,)i(\(3\))f(calculates)i(a)d(new)g(column)g -(called)227 4283 y('phacorr',)30 b(\(4\))f(selects)h(the)f(ro)m(ws)g -(in)f(the)h(table)h(that)f(ha)m(v)m(e)h(phacorr)e(in)g(the)h(range)g(5) -g(to)h(14,)g(and)e(\014nally)227 4396 y(\(5\))35 b(bins)d(the)h -(remaining)g(ro)m(ws)g(on)h(the)f(X)g(and)g(Y)g(column)g(co)s -(ordinates,)i(using)d(a)i(pixel)f(size)h(=)f(32)h(to)227 -4509 y(create)d(a)f(2D)g(image.)42 b(All)30 b(this)f(pro)s(cessing)g -(is)h(completely)h(transparen)m(t)e(to)i(the)e(application)i(program,) -227 4622 y(whic)m(h)f(simply)g(sees)h(the)g(\014nal)f(2-D)h(image)h(in) -e(the)g(primary)g(arra)m(y)h(of)f(the)h(op)s(ened)f(\014le.)0 -4886 y(The)c(full)h(extended)g(CFITSIO)e(FITS)h(\014le)h(name)g(can)g -(con)m(tain)h(sev)m(eral)g(di\013eren)m(t)g(comp)s(onen)m(ts)f(dep)s -(ending)e(on)0 4998 y(the)31 b(con)m(text.)42 b(These)30 -b(comp)s(onen)m(ts)h(are)g(describ)s(ed)e(in)h(the)g(follo)m(wing)i -(sections:)0 5262 y Fe(When)47 b(creating)e(a)j(new)f(file:)143 -5375 y(filetype://BaseFilename\(t)o(empl)o(ate)o(Name)o(\)[co)o(mpr)o -(ess])0 5601 y(When)g(opening)e(an)j(existing)d(primary)h(array)g(or)i -(image)e(HDU:)143 5714 y(filetype://BaseFilename\(o)o(utNa)o(me\))o -([HDU)o(loca)o(tio)o(n][I)o(mage)o(Sec)o(tion)o(][pi)o(xFi)o(lter)o(])p -eop end -%%Page: 124 132 -TeXDict begin 124 131 bop 0 299 a Fj(124)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -668 y Fe(When)47 b(opening)e(an)j(existing)d(table)i(HDU:)143 -781 y(filetype://BaseFilename\(o)o(utNa)o(me\))o([HDU)o(loca)o(tio)o -(n][c)o(olFi)o(lte)o(r][r)o(owFi)o(lte)o(r][b)o(inSp)o(ec])0 -1010 y Fj(The)35 b(\014let)m(yp)s(e,)j(BaseFilename,)h(outName,)g -(HDUlo)s(cation,)g(ImageSection,)g(and)c(pixFilter)i(comp)s(onen)m(ts,) -g(if)0 1123 y(presen)m(t,)27 b(m)m(ust)f(b)s(e)g(giv)m(en)h(in)f(that)g -(order,)h(but)e(the)i(colFilter,)i(ro)m(wFilter,)g(and)c(binSp)s(ec)g -(sp)s(eci\014ers)g(ma)m(y)i(follo)m(w)0 1236 y(in)j(an)m(y)h(order.)42 -b(Regardless)31 b(of)g(the)g(order,)f(ho)m(w)m(ev)m(er,)i(the)f -(colFilter)i(sp)s(eci\014er,)e(if)f(presen)m(t,)h(will)g(b)s(e)f(pro)s -(cessed)0 1349 y(\014rst)g(b)m(y)g(CFITSIO,)f(follo)m(w)m(ed)j(b)m(y)e -(the)h(ro)m(wFilter)h(sp)s(eci\014er,)e(and)f(\014nally)i(b)m(y)f(the)g -(binSp)s(ec)f(sp)s(eci\014er.)0 1678 y Ff(10.2)136 b(Filet)l(yp)t(e)0 -1928 y Fj(The)37 b(t)m(yp)s(e)g(of)g(\014le)g(determines)g(the)g -(medium)f(on)h(whic)m(h)g(the)g(\014le)g(is)h(lo)s(cated)g(\(e.g.,)i -(disk)d(or)g(net)m(w)m(ork\))h(and,)0 2041 y(hence,)f(whic)m(h)e(in)m -(ternal)h(device)g(driv)m(er)f(is)g(used)f(b)m(y)h(CFITSIO)f(to)i(read) -f(and/or)g(write)g(the)g(\014le.)56 b(Curren)m(tly)0 -2154 y(supp)s(orted)29 b(t)m(yp)s(es)h(are)382 2383 y -Fe(file://)93 b(-)48 b(file)e(on)i(local)e(magnetic)g(disk)g -(\(default\))430 2496 y(ftp://)93 b(-)48 b(a)f(readonly)f(file)g -(accessed)g(with)h(the)g(anonymous)e(FTP)i(protocol.)907 -2609 y(It)g(also)g(supports)93 b(ftp://username:password@)o(host)o(nam) -o(e/..)o(.)907 2722 y(for)47 b(accessing)e(password-protected)e(ftp)k -(sites.)382 2835 y(http://)93 b(-)48 b(a)f(readonly)f(file)g(accessed)g -(with)h(the)g(HTTP)f(protocol.)93 b(It)907 2948 y(supports)45 -b(username:password)e(just)k(like)g(the)g(ftp)g(driver.)907 -3060 y(Proxy)f(HTTP)h(servers)f(are)h(supported)e(using)h(the)h -(http_proxy)907 3173 y(environment)e(variable)g(\(see)i(following)e -(note\).)286 3286 y(stream://)93 b(-)48 b(special)e(driver)g(to)h(read) -g(an)g(input)f(FITS)h(file)f(from)h(the)g(stdin)907 3399 -y(stream,)f(and/or)g(write)g(an)h(output)f(FITS)h(file)g(to)g(the)g -(stdout)143 3512 y(stream.)94 b(This)46 b(driver)g(is)i(fragile)d(and)i -(has)g(limited)143 3625 y(functionality)d(\(see)j(the)g(following)e -(note\).)286 3738 y(gsiftp://)93 b(-)48 b(access)e(files)g(on)h(a)h -(computational)c(grid)j(using)f(the)h(gridftp)907 3851 -y(protocol)e(in)j(the)e(Globus)h(toolkit)e(\(see)i(following)e(note\).) -382 3964 y(root://)93 b(-)48 b(uses)e(the)h(CERN)g(root)g(protocol)e -(for)i(writing)f(as)h(well)g(as)907 4077 y(reading)f(files)g(over)h -(the)g(network)e(\(see)i(following)e(note\).)334 4190 -y(shmem://)93 b(-)48 b(opens)e(or)h(creates)f(a)i(file)e(which)h -(persists)e(in)i(the)g(computer's)907 4302 y(shared)f(memory)g(\(see)h -(following)e(note\).)430 4415 y(mem://)93 b(-)48 b(opens)e(a)i -(temporary)d(file)i(in)g(core)f(memory.)94 b(The)47 b(file)907 -4528 y(disappears)e(when)h(the)h(program)f(exits)h(so)g(this)f(is)i -(mainly)907 4641 y(useful)e(for)h(test)f(purposes)g(when)h(a)g -(permanent)e(output)h(file)907 4754 y(is)h(not)g(desired.)0 -4983 y Fj(If)35 b(the)h(\014let)m(yp)s(e)g(is)f(not)h(sp)s(eci\014ed,)h -(then)e(t)m(yp)s(e)h(\014le://)h(is)e(assumed.)56 b(The)35 -b(double)g(slashes)h('//')h(are)f(optional)0 5096 y(and)30 -b(ma)m(y)h(b)s(e)e(omitted)j(in)e(most)h(cases.)0 5382 -y Fd(10.2.1)113 b(Notes)36 b(ab)s(out)j(HTTP)d(pro)m(xy)i(serv)m(ers)0 -5601 y Fj(A)32 b(pro)m(xy)g(HTTP)f(serv)m(er)h(ma)m(y)h(b)s(e)e(used)g -(b)m(y)h(de\014ning)f(the)h(address)f(\(URL\))i(and)e(p)s(ort)g(n)m(um) -m(b)s(er)g(of)h(the)g(pro)m(xy)0 5714 y(serv)m(er)f(with)f(the)g(h)m -(ttp)p 801 5714 28 4 v 33 w(pro)m(xy)g(en)m(vironmen)m(t)h(v)-5 -b(ariable.)42 b(F)-8 b(or)31 b(example)p eop end -%%Page: 125 133 -TeXDict begin 125 132 bop 0 299 a Fh(10.2.)73 b(FILETYPE)3037 -b Fj(125)191 555 y Fe(setenv)46 b(http_proxy)f -(http://heasarc.gsfc.nasa)o(.gov)o(:312)o(8)0 793 y Fj(will)38 -b(cause)g(CFITSIO)f(to)h(use)g(p)s(ort)f(3128)i(on)f(the)g(heasarc)g -(pro)m(xy)g(serv)m(er)g(whenev)m(er)g(reading)g(a)g(FITS)f(\014le)0 -906 y(with)30 b(HTTP)-8 b(.)0 1194 y Fd(10.2.2)113 b(Notes)36 -b(ab)s(out)j(the)e(stream)h(\014let)m(yp)s(e)g(driv)m(er)0 -1413 y Fj(The)e(stream)h(driv)m(er)f(can)h(b)s(e)f(used)g(to)h -(e\016cien)m(tly)i(read)d(a)h(FITS)f(\014le)h(from)f(the)h(stdin)f -(\014le)g(stream)h(or)g(write)0 1525 y(a)44 b(FITS)e(to)i(the)g(stdout) -f(\014le)g(stream.)80 b(Ho)m(w)m(ev)m(er,)49 b(b)s(ecause)43 -b(these)h(input)e(and)h(output)g(streams)g(m)m(ust)h(b)s(e)0 -1638 y(accessed)30 b(sequen)m(tially)-8 b(,)31 b(the)e(FITS)f(\014le)g -(reading)h(or)f(writing)h(application)h(m)m(ust)e(also)i(read)e(and)g -(write)h(the)g(\014le)0 1751 y(sequen)m(tially)-8 b(,)33 -b(at)e(least)g(within)f(the)h(tolerances)h(describ)s(ed)d(b)s(elo)m(w.) -0 1911 y(CFITSIO)34 b(supp)s(orts)f(2)j(di\013eren)m(t)f(metho)s(ds)g -(for)g(accessing)i(FITS)d(\014les)h(on)h(the)f(stdin)g(and)f(stdout)h -(streams.)0 2024 y(The)c(original)i(metho)s(d,)f(whic)m(h)f(is)h(in)m -(v)m(ok)m(ed)h(b)m(y)f(sp)s(ecifying)f(a)h(dash)f(c)m(haracter,)j("-",) -g(as)d(the)h(name)g(of)g(the)g(\014le)0 2137 y(when)g(op)s(ening)g(or)h -(creating)h(it,)g(w)m(orks)e(b)m(y)h(storing)g(a)g(complete)h(cop)m(y)g -(of)f(the)g(en)m(tire)g(FITS)f(\014le)h(in)f(memory)-8 -b(.)0 2250 y(In)35 b(this)g(case,)k(when)34 b(reading)i(from)f(stdin,)i -(CFITSIO)d(will)i(cop)m(y)h(the)e(en)m(tire)i(stream)f(in)m(to)h -(memory)e(b)s(efore)0 2363 y(doing)c(an)m(y)h(pro)s(cessing)f(of)h(the) -f(\014le.)44 b(Similarly)-8 b(,)32 b(when)f(writing)g(to)h(stdout,)g -(CFITSIO)d(will)j(create)h(a)f(cop)m(y)g(of)0 2476 y(the)h(en)m(tire)g -(FITS)f(\014le)g(in)h(memory)-8 b(,)33 b(b)s(efore)f(\014nally)h -(\015ushing)e(it)i(out)f(to)i(the)e(stdout)h(stream)g(when)e(the)i -(FITS)0 2589 y(\014le)g(is)g(closed.)49 b(Bu\013ering)33 -b(the)g(en)m(tire)h(FITS)e(\014le)h(in)g(this)f(w)m(a)m(y)i(allo)m(ws)g -(the)f(application)i(to)e(randomly)g(access)0 2702 y(an)m(y)h(part)f -(of)h(the)f(FITS)g(\014le,)i(in)e(an)m(y)h(order,)f(but)g(it)h(also)h -(requires)e(that)h(the)f(user)g(ha)m(v)m(e)i(su\016cien)m(t)f(a)m(v)-5 -b(ailable)0 2815 y(memory)30 b(\(or)g(virtual)g(memory\))g(to)h(store)f -(the)g(en)m(tire)h(\014le,)f(whic)m(h)f(ma)m(y)i(not)f(b)s(e)f(p)s -(ossible)g(in)h(the)g(case)h(of)f(v)m(ery)0 2928 y(large)h(\014les.)0 -3088 y(The)e(new)m(er)g(stream)h(\014let)m(yp)s(e)g(pro)m(vides)f(a)h -(more)f(memory-e\016cien)m(t)i(metho)s(d)e(of)h(accessing)h(FITS)d -(\014les)h(on)h(the)0 3201 y(stdin)37 b(or)h(stdout)g(streams.)64 -b(Instead)38 b(of)g(storing)g(a)g(cop)m(y)h(of)f(the)g(en)m(tire)h -(FITS)e(\014le)h(in)g(memory)-8 b(,)40 b(CFITSIO)0 3314 -y(only)32 b(uses)g(a)g(set)h(of)f(in)m(ternal)h(bu\013er)e(whic)m(h)h -(b)m(y)g(default)g(can)g(store)h(40)g(FITS)e(blo)s(c)m(ks,)i(or)g(ab)s -(out)e(100K)i(b)m(ytes)0 3427 y(of)f(the)f(FITS)g(\014le.)43 -b(The)31 b(application)i(program)e(m)m(ust)g(pro)s(cess)g(the)h(FITS)e -(\014le)i(sequen)m(tially)h(from)e(b)s(eginning)0 3539 -y(to)h(end,)e(within)g(this)h(100K)h(bu\013er.)41 b(Generally)32 -b(sp)s(eaking)f(the)g(application)h(program)f(m)m(ust)f(conform)h(to)h -(the)0 3652 y(follo)m(wing)g(restrictions:)136 3891 y -Fc(\017)46 b Fj(The)36 b(program)f(m)m(ust)h(\014nish)e(reading)i(or)g -(writing)f(the)h(header)g(k)m(eyw)m(ords)g(b)s(efore)f(reading)h(or)g -(writing)227 4004 y(an)m(y)31 b(data)g(in)f(the)h(HDU.)136 -4184 y Fc(\017)46 b Fj(The)24 b(HDU)h(can)f(con)m(tain)i(at)e(most)h -(ab)s(out)f(1400)h(header)f(k)m(eyw)m(ords.)39 b(This)24 -b(is)g(the)g(maxim)m(um)g(that)h(can)f(\014t)227 4297 -y(in)g(the)g(nominal)h(40)g(FITS)e(blo)s(c)m(k)i(bu\013er.)37 -b(In)24 b(principle,)h(this)f(limit)h(could)f(b)s(e)g(increased)g(b)m -(y)g(recompiling)227 4410 y(CFITSIO)29 b(with)h(a)h(larger)g(bu\013er)e -(limit,)j(whic)m(h)e(is)g(set)h(b)m(y)f(the)h(NIOBUF)g(parameter)g(in)f -(\014tsio2.h.)136 4590 y Fc(\017)46 b Fj(The)32 b(program)g(m)m(ust)f -(read)h(or)g(write)h(the)f(data)g(in)g(a)g(sequen)m(tial)i(manner)d -(from)h(the)g(b)s(eginning)f(to)i(the)227 4703 y(end)26 -b(of)g(the)h(HDU.)g(Note)h(that)f(CFITSIO's)e(in)m(ternal)i(100K)g -(bu\013er)e(allo)m(ws)j(a)e(little)j(latitude)e(in)f(meeting)227 -4816 y(this)31 b(requiremen)m(t.)136 4997 y Fc(\017)46 -b Fj(The)30 b(program)g(cannot)h(mo)m(v)m(e)h(bac)m(k)f(to)g(a)g -(previous)f(HDU)h(in)f(the)h(FITS)e(\014le.)136 5177 -y Fc(\017)46 b Fj(Reading)c(or)f(writing)f(of)h(v)-5 -b(ariable)42 b(length)f(arra)m(y)h(columns)e(in)h(binary)f(tables)i(is) -f(not)g(supp)s(orted)e(on)227 5290 y(streams,)29 b(b)s(ecause)f(this)g -(requires)g(mo)m(ving)g(bac)m(k)h(and)f(forth)f(b)s(et)m(w)m(een)i(the) -f(\014xed-length)g(p)s(ortion)g(of)g(the)227 5403 y(binary)i(table)h -(and)f(the)g(follo)m(wing)i(heap)e(area)i(where)e(the)g(arra)m(ys)h -(are)g(actually)h(stored.)136 5583 y Fc(\017)46 b Fj(Reading)25 -b(or)g(writing)f(of)h(tile-compressed)h(images)g(is)e(not)h(supp)s -(orted)e(on)h(streams,)i(b)s(ecause)f(the)g(images)227 -5696 y(are)31 b(in)m(ternally)g(stored)g(using)f(v)-5 -b(ariable)31 b(length)g(arra)m(ys.)p eop end -%%Page: 126 134 -TeXDict begin 126 133 bop 0 299 a Fj(126)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fd(10.2.3)113 b(Notes)36 b(ab)s(out)j(the)e(gsiftp)h(\014let)m -(yp)s(e)0 774 y Fj(DEPENDENCIES:)c(Globus)h(to)s(olkit)h(\(2.4.3)g(or)f -(higher\))f(\(GT\))h(should)f(b)s(e)g(installed.)53 b(There)34 -b(are)h(t)m(w)m(o)h(dif-)0 887 y(feren)m(t)31 b(w)m(a)m(ys)g(to)g -(install)g(GT:)0 1047 y(1\))43 b(goto)h(the)f(globus)f(to)s(olkit)i(w)m -(eb)e(page)i(www.globus.org)e(and)g(follo)m(w)h(the)g(do)m(wnload)g -(and)e(compilation)0 1160 y(instructions;)0 1320 y(2\))j(goto)i(the)d -(Virtual)i(Data)g(T)-8 b(o)s(olkit)45 b(w)m(eb)e(page)i(h)m -(ttp://vdt.cs.wisc.edu/)g(and)e(follo)m(w)i(the)f(instructions)0 -1433 y(\(STR)m(ONGL)-8 b(Y)31 b(SUGGESTED\);)0 1593 y(Once)23 -b(a)h(globus)f(clien)m(t)h(has)f(b)s(een)g(installed)h(in)e(y)m(our)i -(system)f(with)g(a)g(sp)s(eci\014c)g(\015a)m(v)m(our)h(it)f(is)g(p)s -(ossible)g(to)h(compile)0 1706 y(and)30 b(install)h(the)g(CFITSIO)d -(libraries.)41 b(Sp)s(eci\014c)30 b(con\014guration)h(\015ags)f(m)m -(ust)h(b)s(e)e(used:)0 1866 y(1\))21 b({with-gsiftp[[=P)-8 -b(A)g(TH]])22 b(Enable)f(Globus)f(T)-8 b(o)s(olkit)21 -b(gsiftp)g(proto)s(col)g(supp)s(ort)d(P)-8 b(A)g(TH=GLOBUS)p -3532 1866 28 4 v 33 w(LOCA)g(TION)0 1979 y(i.e.)42 b(the)30 -b(lo)s(cation)i(of)f(y)m(our)f(globus)g(installation)0 -2139 y(2\))h({with-gsiftp-\015a)m(v)m(our[[=P)-8 b(A)g(TH])33 -b(de\014nes)d(the)g(sp)s(eci\014c)g(Globus)h(\015a)m(v)m(our)f(ex.)41 -b(gcc32)0 2300 y(Both)31 b(the)g(\015ags)f(m)m(ust)g(b)s(e)g(used)g -(and)f(it)i(is)g(mandatory)f(to)h(set)g(b)s(oth)f(the)g(P)-8 -b(A)g(TH)31 b(and)f(the)h(\015a)m(v)m(our.)0 2460 y(USA)m(GE:)g(T)-8 -b(o)31 b(access)h(\014les)e(on)g(a)h(gridftp)f(serv)m(er)g(it)h(is)g -(necessary)f(to)i(use)e(a)g(gsiftp)h(pre\014x:)0 2620 -y(example:)41 b(gsiftp://remote)p 1003 2620 V 35 w(serv)m(er)p -1271 2620 V 34 w(fqhn/directory/\014lename)0 2780 y(The)f(gridftp)g -(driv)m(er)g(uses)g(a)g(lo)s(cal)i(bu\013er)d(on)i(a)f(temp)s(orary)g -(\014le)h(the)f(\014le)h(is)f(lo)s(cated)i(in)e(the)g(/tmp)h(direc-)0 -2893 y(tory)-8 b(.)73 b(If)40 b(y)m(ou)h(ha)m(v)m(e)h(sp)s(ecial)g(p)s -(ermissions)d(on)i(/tmp)g(or)g(y)m(ou)g(do)f(not)i(ha)m(v)m(e)g(a)f -(/tmp)g(directory)-8 b(,)44 b(it)e(is)e(p)s(os-)0 3006 -y(sible)d(to)h(force)g(another)g(lo)s(cation)g(setting)h(the)e(GSIFTP)p -2068 3006 V 32 w(TMPFILE)g(en)m(vironmen)m(t)h(v)-5 b(ariable)38 -b(\(ex.)62 b(exp)s(ort)0 3119 y(GSIFTP)p 347 3119 V 32 -w(TMPFILE=/y)m(our/lo)s(cation/y)m(ourtmp\014le\).)0 -3279 y(Grid)34 b(FTP)g(supp)s(orts)f(m)m(ulti)h(c)m(hannel)h(transfer.) -52 b(By)35 b(default)f(a)h(single)g(c)m(hannel)g(transmission)f(is)g(a) -m(v)-5 b(ailable.)0 3392 y(Ho)m(w)m(ev)m(er,)34 b(it)d(is)h(p)s -(ossible)e(to)i(mo)s(dify)e(this)i(b)s(eha)m(vior)f(setting)h(the)f -(GSIFTP)p 2691 3392 V 33 w(STREAMS)f(en)m(vironmen)m(t)h(v)-5 -b(ari-)0 3505 y(able)31 b(\(ex.)41 b(exp)s(ort)30 b(GSIFTP)p -1016 3505 V 33 w(STREAMS=8\).)0 3790 y Fd(10.2.4)113 -b(Notes)36 b(ab)s(out)j(the)e(ro)s(ot)g(\014let)m(yp)s(e)0 -4009 y Fj(The)20 b(original)j(ro)s(otd)d(serv)m(er)h(can)h(b)s(e)e -(obtained)h(from:)36 b Fe(ftp://root.cern.ch/root)o(/roo)o(td.t)o(ar.)o -(gz)15 b Fj(but,)22 b(for)0 4122 y(it)33 b(to)h(w)m(ork)f(correctly)h -(with)e(CFITSIO)g(one)h(has)f(to)i(use)e(a)i(mo)s(di\014ed)d(v)m -(ersion)j(whic)m(h)e(supp)s(orts)f(a)i(command)0 4235 -y(to)41 b(return)d(the)j(length)f(of)g(the)g(\014le.)70 -b(This)39 b(mo)s(di\014ed)f(v)m(ersion)j(is)f(a)m(v)-5 -b(ailable)42 b(in)e(ro)s(otd)f(sub)s(directory)g(in)h(the)0 -4348 y(CFITSIO)29 b(ftp)h(area)h(at)286 4577 y Fe -(ftp://legacy.gsfc.nasa.gov)o(/so)o(ftwa)o(re/f)o(its)o(io/c)o(/roo)o -(t/r)o(ootd)o(.tar)o(.gz)o(.)0 4805 y Fj(This)j(small)g(serv)m(er)h(is) -g(started)f(either)h(b)m(y)g(inetd)f(when)f(a)i(clien)m(t)h(requests)e -(a)h(connection)h(to)f(a)f(ro)s(otd)h(serv)m(er)0 4918 -y(or)30 b(b)m(y)g(hand)f(\(i.e.)42 b(from)30 b(the)g(command)g(line\).) -42 b(The)29 b(ro)s(otd)h(serv)m(er)h(w)m(orks)f(with)g(the)g(R)m(OOT)g -(TNetFile)i(class.)0 5031 y(It)e(allo)m(ws)g(remote)h(access)f(to)h(R)m -(OOT)e(database)h(\014les)f(in)g(either)h(read)g(or)f(write)h(mo)s(de.) -40 b(By)30 b(default)f(TNetFile)0 5144 y(assumes)38 b(p)s(ort)g(432)h -(\(whic)m(h)f(requires)g(ro)s(otd)g(to)h(b)s(e)f(started)h(as)f(ro)s -(ot\).)65 b(T)-8 b(o)39 b(run)e(ro)s(otd)h(via)h(inetd)f(add)g(the)0 -5257 y(follo)m(wing)32 b(line)f(to)g(/etc/services:)95 -5485 y Fe(rootd)238 b(432/tcp)0 5714 y Fj(and)30 b(to)h -(/etc/inetd.conf,)i(add)d(the)g(follo)m(wing)i(line:)p -eop end -%%Page: 127 135 -TeXDict begin 127 134 bop 0 299 a Fh(10.2.)73 b(FILETYPE)3037 -b Fj(127)95 555 y Fe(rootd)47 b(stream)f(tcp)h(nowait)f(root)h -(/user/rdm/root/bin/root)o(d)42 b(rootd)k(-i)0 829 y -Fj(F)-8 b(orce)30 b(inetd)e(to)h(reread)f(its)h(conf)f(\014le)g(with)g -Fe(kill)47 b(-HUP)g()p Fj(.)39 b(Y)-8 b(ou)28 -b(can)h(also)g(start)g(ro)s(otd)f(b)m(y)g(hand)0 942 -y(running)35 b(directly)i(under)d(y)m(our)j(priv)-5 b(ate)37 -b(accoun)m(t)g(\(no)g(ro)s(ot)g(system)f(privileges)h(needed\).)59 -b(F)-8 b(or)37 b(example)g(to)0 1054 y(start)e(ro)s(otd)g(listening)g -(on)g(p)s(ort)f(5151)j(just)d(t)m(yp)s(e:)49 b Fe(rootd)e(-p)g(5151)33 -b Fj(Notice)k(that)f(no)e(&)h(is)f(needed.)54 b(Ro)s(otd)0 -1167 y(will)31 b(go)g(in)m(to)g(bac)m(kground)f(b)m(y)h(itself.)95 -1441 y Fe(Rootd)47 b(arguments:)191 1554 y(-i)763 b(says)47 -b(we)g(were)f(started)g(by)h(inetd)191 1667 y(-p)g(port#)476 -b(specifies)45 b(a)j(different)d(port)i(to)g(listen)f(on)191 -1780 y(-d)h(level)476 b(level)46 b(of)i(debug)e(info)h(written)e(to)j -(syslog)1050 1893 y(0)f(=)h(no)f(debug)f(\(default\))1050 -2005 y(1)h(=)h(minimum)1050 2118 y(2)f(=)h(medium)1050 -2231 y(3)f(=)h(maximum)0 2505 y Fj(Ro)s(otd)29 b(can)f(also)h(b)s(e)f -(con\014gured)g(for)g(anon)m(ymous)g(usage)h(\(lik)m(e)h(anon)m(ymous)e -(ftp\).)40 b(T)-8 b(o)29 b(setup)f(ro)s(otd)g(to)h(accept)0 -2618 y(anon)m(ymous)h(logins)h(do)g(the)f(follo)m(wing)i(\(while)f(b)s -(eing)f(logged)i(in)e(as)g(ro)s(ot\):)143 2891 y Fe(-)48 -b(Add)f(the)f(following)g(line)g(to)i(/etc/passwd:)239 -3117 y(rootd:*:71:72:Anonymous)41 b(rootd:/var/spool/rootd:/b)o(in/)o -(fals)o(e)239 3343 y(where)46 b(you)h(may)g(modify)f(the)h(uid,)f(gid)h -(\(71,)g(72\))g(and)g(the)g(home)f(directory)239 3456 -y(to)h(suite)f(your)h(system.)143 3681 y(-)h(Add)f(the)f(following)g -(line)g(to)i(/etc/group:)239 3907 y(rootd:*:72:rootd)239 -4133 y(where)e(the)h(gid)g(must)f(match)h(the)g(gid)g(in)g -(/etc/passwd.)143 4359 y(-)h(Create)e(the)h(directories:)239 -4585 y(mkdir)f(/var/spool/rootd)239 4698 y(mkdir)g -(/var/spool/rootd/tmp)239 4811 y(chmod)g(777)h(/var/spool/rootd/tmp)239 -5036 y(Where)f(/var/spool/rootd)d(must)k(match)f(the)h(rootd)g(home)f -(directory)g(as)239 5149 y(specified)f(in)i(the)g(rootd)f(/etc/passwd)f -(entry.)143 5375 y(-)j(To)f(make)f(writeable)g(directories)e(for)j -(anonymous)f(do,)h(for)f(example:)239 5601 y(mkdir)g -(/var/spool/rootd/pub)239 5714 y(chown)g(rootd:rootd)f -(/var/spool/rootd/pub)p eop end -%%Page: 128 136 -TeXDict begin 128 135 bop 0 299 a Fj(128)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fj(That's)42 b(all.)76 b(Sev)m(eral)43 b(additional)g(remarks:)64 -b(y)m(ou)42 b(can)g(login)h(to)g(an)f(anon)m(ymous)f(serv)m(er)i -(either)f(with)g(the)0 668 y(names)31 b("anon)m(ymous")h(or)f("ro)s -(otd".)43 b(The)31 b(passw)m(ord)f(should)g(b)s(e)h(of)g(t)m(yp)s(e)g -(user@host.do.main.)43 b(Only)30 b(the)h(@)0 781 y(is)e(enforced)f(for) -h(the)f(time)i(b)s(eing.)39 b(In)28 b(anon)m(ymous)h(mo)s(de)f(the)g -(top)h(of)g(the)g(\014le)f(tree)i(is)e(set)h(to)h(the)e(ro)s(otd)h -(home)0 894 y(directory)-8 b(,)39 b(therefore)e(only)f(\014les)h(b)s -(elo)m(w)f(the)h(home)f(directory)h(can)f(b)s(e)g(accessed.)60 -b(Anon)m(ymous)36 b(mo)s(de)g(only)0 1007 y(w)m(orks)30 -b(when)g(the)g(serv)m(er)h(is)f(started)h(via)g(inetd.)0 -1296 y Fd(10.2.5)113 b(Notes)36 b(ab)s(out)j(the)e(shmem)i(\014let)m -(yp)s(e:)0 1515 y Fj(Shared)34 b(memory)h(\014les)g(are)g(curren)m(tly) -g(supp)s(orted)e(on)i(most)h(Unix)f(platforms,)h(where)f(the)g(shared)f -(memory)0 1627 y(segmen)m(ts)d(are)g(managed)g(b)m(y)f(the)g(op)s -(erating)h(system)g(k)m(ernel)f(and)g(`liv)m(e')i(indep)s(enden)m(tly)d -(of)i(pro)s(cesses.)40 b(They)0 1740 y(are)34 b(not)g(deleted)h(\(b)m -(y)f(default\))g(when)f(the)h(pro)s(cess)f(whic)m(h)h(created)h(them)f -(terminates,)h(although)g(they)f(will)0 1853 y(disapp)s(ear)e(if)h(the) -h(system)f(is)g(reb)s(o)s(oted.)49 b(Applications)34 -b(can)g(create)h(shared)d(memory)h(\014les)g(in)g(CFITSIO)f(b)m(y)0 -1966 y(calling:)143 2214 y Fe(fit_create_file\(&fitsfile)o(ptr,)41 -b("shmem://h2",)j(&status\);)0 2462 y Fj(where)25 b(the)g(ro)s(ot)h -(`\014le')f(names)h(are)f(curren)m(tly)g(restricted)h(to)g(b)s(e)f -('h0',)i('h1',)g('h2',)g('h3',)f(etc.,)i(up)d(to)g(a)h(maxim)m(um)0 -2575 y(n)m(um)m(b)s(er)20 b(de\014ned)f(b)m(y)i(the)g(the)g(v)-5 -b(alue)22 b(of)f(SHARED)p 1746 2575 28 4 v 33 w(MAXSEG)g(\(equal)h(to)f -(16)h(b)m(y)f(default\).)38 b(This)20 b(is)h(a)g(protot)m(yp)s(e)0 -2688 y(implemen)m(tation)30 b(of)f(the)g(shared)f(memory)g(in)m -(terface)i(and)e(a)h(more)g(robust)f(in)m(terface,)j(whic)m(h)d(will)h -(ha)m(v)m(e)h(few)m(er)0 2801 y(restrictions)h(on)f(the)h(n)m(um)m(b)s -(er)e(of)i(\014les)f(and)g(on)g(their)g(names,)h(ma)m(y)g(b)s(e)f(dev)m -(elop)s(ed)g(in)g(the)h(future.)0 2961 y(When)23 b(op)s(ening)h(an)f -(already)h(existing)h(FITS)e(\014le)h(in)f(shared)g(memory)h(one)g -(calls)g(the)g(usual)g(CFITSIO)e(routine:)143 3209 y -Fe(fits_open_file\(&fitsfilep)o(tr,)41 b("shmem://h7",)j(mode,)j -(&status\))0 3457 y Fj(The)26 b(\014le)h(mo)s(de)g(can)g(b)s(e)f(READ)m -(WRITE)h(or)g(READONL)-8 b(Y)28 b(just)e(as)h(with)f(disk)h(\014les.)39 -b(More)28 b(than)e(one)h(pro)s(cess)0 3570 y(can)35 b(op)s(erate)g(on)f -(READONL)-8 b(Y)35 b(mo)s(de)f(\014les)h(at)g(the)f(same)h(time.)54 -b(CFITSIO)33 b(supp)s(orts)f(prop)s(er)h(\014le)i(lo)s(c)m(king)0 -3682 y(\(b)s(oth)27 b(in)h(READONL)-8 b(Y)29 b(and)e(READ)m(WRITE)h(mo) -s(des\),)h(so)f(calls)h(to)f(\014ts)p 2572 3682 V 33 -w(op)s(en)p 2795 3682 V 32 w(\014le)g(ma)m(y)g(b)s(e)f(lo)s(c)m(k)m(ed) -j(out)e(un)m(til)0 3795 y(another)j(other)f(pro)s(cess)g(closes)i(the)e -(\014le.)0 3956 y(When)g(an)g(application)i(is)e(\014nished)f -(accessing)j(a)e(FITS)g(\014le)g(in)g(a)h(shared)e(memory)h(segmen)m -(t,)i(it)f(ma)m(y)g(close)g(it)0 4068 y(\(and)j(the)g(\014le)g(will)g -(remain)f(in)h(the)g(system\))g(with)g(\014ts)p 1955 -4068 V 32 w(close)p 2173 4068 V 34 w(\014le,)h(or)f(delete)h(it)g(with) -e(\014ts)p 3191 4068 V 33 w(delete)p 3455 4068 V 34 w(\014le.)51 -b(Ph)m(ys-)0 4181 y(ical)36 b(deletion)g(is)f(p)s(ostp)s(oned)e(un)m -(til)j(the)f(last)g(pro)s(cess)g(calls)h(\013clos/\013delt.)56 -b(\014ts)p 2801 4181 V 32 w(delete)p 3064 4181 V 34 w(\014le)35 -b(tries)h(to)f(obtain)h(a)0 4294 y(READ)m(WRITE)e(lo)s(c)m(k)g(on)f -(the)g(\014le)h(to)g(b)s(e)e(deleted,)j(th)m(us)e(it)h(can)f(b)s(e)g -(blo)s(c)m(k)m(ed)h(if)f(the)h(ob)5 b(ject)34 b(w)m(as)f(not)h(op)s -(ened)0 4407 y(in)c(READ)m(WRITE)h(mo)s(de.)0 4567 y(A)i(shared)f -(memory)h(managemen)m(t)h(utilit)m(y)g(program)f(called)h(`smem',)f(is) -g(included)f(with)h(the)g(CFITSIO)e(dis-)0 4680 y(tribution.)39 -b(It)27 b(can)g(b)s(e)f(built)h(b)m(y)g(t)m(yping)g(`mak)m(e)h(smem';)g -(then)f(t)m(yp)s(e)g(`smem)f(-h')h(to)h(get)g(a)f(list)g(of)g(v)-5 -b(alid)27 b(options.)0 4793 y(Executing)37 b(smem)f(without)g(an)m(y)h -(options)g(causes)f(it)h(to)g(list)g(all)g(the)g(shared)e(memory)i -(segmen)m(ts)g(curren)m(tly)0 4906 y(residing)c(in)g(the)g(system)h -(and)e(managed)i(b)m(y)f(the)h(shared)e(memory)h(driv)m(er.)49 -b(T)-8 b(o)34 b(get)g(a)g(list)g(of)f(all)h(the)g(shared)0 -5019 y(memory)c(ob)5 b(jects,)32 b(run)d(the)h(system)h(utilit)m(y)g -(program)f(`ip)s(cs)h([-a]'.)0 5351 y Ff(10.3)136 b(Base)45 -b(Filename)0 5601 y Fj(The)31 b(base)g(\014lename)h(is)f(the)h(name)f -(of)h(the)f(\014le)h(optionally)g(including)f(the)h(director/sub)s -(directory)f(path,)h(and)0 5714 y(in)e(the)h(case)g(of)g(`ftp',)f(`h)m -(ttp',)i(and)d(`ro)s(ot')j(\014let)m(yp)s(es,)e(the)h(mac)m(hine)g -(iden)m(ti\014er.)41 b(Examples:)p eop end -%%Page: 129 137 -TeXDict begin 129 136 bop 0 299 a Fh(10.3.)73 b(BASE)30 -b(FILENAME)2739 b Fj(129)191 555 y Fe(myfile.fits)191 -668 y(!data.fits)191 781 y(/data/myfile.fits)191 894 -y(fits.gsfc.nasa.gov/ftp/s)o(ampl)o(eda)o(ta/m)o(yfil)o(e.f)o(its.)o -(gz)0 1120 y Fj(When)29 b(creating)h(a)f(new)f(output)h(\014le)g(on)g -(magnetic)h(disk)e(\(of)i(t)m(yp)s(e)f(\014le://\))h(if)f(the)g(base)g -(\014lename)g(b)s(egins)f(with)0 1233 y(an)34 b(exclamation)j(p)s(oin)m -(t)d(\(!\))54 b(then)34 b(an)m(y)g(existing)i(\014le)e(with)g(that)h -(same)g(basename)g(will)g(b)s(e)e(deleted)i(prior)f(to)0 -1346 y(creating)h(the)f(new)g(FITS)f(\014le.)51 b(Otherwise)34 -b(if)g(the)g(\014le)g(to)g(b)s(e)g(created)h(already)f(exists,)i(then)d -(CFITSIO)g(will)0 1459 y(return)g(an)h(error)f(and)g(will)i(not)f(o)m -(v)m(erwrite)h(the)f(existing)h(\014le.)52 b(Note)35 -b(that)g(the)f(exclamation)i(p)s(oin)m(t,)f(')10 b(!',)36 -b(is)e(a)0 1572 y(sp)s(ecial)28 b(UNIX)g(c)m(haracter,)j(so)d(if)f(it)i -(is)f(used)f(on)g(the)h(command)g(line)g(rather)g(than)f(en)m(tered)h -(at)h(a)f(task)h(prompt,)0 1685 y(it)j(m)m(ust)f(b)s(e)g(preceded)g(b)m -(y)h(a)g(bac)m(kslash)g(to)g(force)g(the)g(UNIX)g(shell)f(to)h(pass)f -(it)i(v)m(erbatim)f(to)g(the)g(application)0 1798 y(program.)0 -1958 y(If)24 b(the)i(output)e(disk)h(\014le)g(name)g(ends)f(with)g(the) -h(su\016x)f('.gz',)k(then)d(CFITSIO)e(will)i(compress)g(the)g(\014le)g -(using)g(the)0 2071 y(gzip)g(compression)f(algorithm)h(b)s(efore)f -(writing)g(it)h(to)g(disk.)38 b(This)23 b(can)i(reduce)f(the)g(amoun)m -(t)h(of)f(disk)g(space)h(used)0 2184 y(b)m(y)34 b(the)h(\014le.)53 -b(Note)36 b(that)f(this)g(feature)g(requires)f(that)h(the)f -(uncompressed)g(\014le)g(b)s(e)g(constructed)h(in)f(memory)0 -2297 y(b)s(efore)c(it)h(is)f(compressed)g(and)g(written)h(to)g(disk,)f -(so)g(it)h(can)g(fail)g(if)f(there)h(is)f(insu\016cien)m(t)h(a)m(v)-5 -b(ailable)33 b(memory)-8 b(.)0 2457 y(An)45 b(input)g(FITS)f(\014le)i -(ma)m(y)g(b)s(e)f(compressed)g(with)h(the)f(gzip)h(or)g(Unix)f -(compress)h(algorithms,)k(in)45 b(whic)m(h)0 2570 y(case)38 -b(CFITSIO)e(will)i(uncompress)e(the)i(\014le)g(on)f(the)h(\015y)e(in)m -(to)j(a)f(temp)s(orary)f(\014le)g(\(in)h(memory)f(or)g(on)h(disk\).)0 -2683 y(Compressed)32 b(\014les)i(ma)m(y)g(only)f(b)s(e)g(op)s(ened)f -(with)h(read-only)h(p)s(ermission.)49 b(When)33 b(sp)s(ecifying)g(the)h -(name)f(of)h(a)0 2796 y(compressed)h(FITS)g(\014le)h(it)g(is)g(not)g -(necessary)g(to)g(app)s(end)e(the)i(\014le)g(su\016x)e(\(e.g.,)39 -b(`.gz')e(or)f(`.Z'\).)g(If)f(CFITSIO)0 2908 y(cannot)24 -b(\014nd)e(the)h(input)f(\014le)i(name)f(without)g(the)g(su\016x,)h -(then)f(it)h(will)g(automatically)i(searc)m(h)e(for)f(a)g(compressed)0 -3021 y(\014le)36 b(with)f(the)h(same)g(ro)s(ot)g(name.)57 -b(In)35 b(the)h(case)h(of)f(reading)g(ftp)f(and)g(h)m(ttp)h(t)m(yp)s(e) -g(\014les,)h(CFITSIO)e(generally)0 3134 y(lo)s(oks)j(for)g(a)g -(compressed)g(v)m(ersion)g(of)g(the)g(\014le)g(\014rst,)h(b)s(efore)e -(trying)h(to)h(op)s(en)e(the)h(uncompressed)e(\014le.)64 -b(By)0 3247 y(default,)37 b(CFITSIO)e(copies)h(\(and)g(uncompressed)e -(if)i(necessary\))g(the)g(ftp)f(or)h(h)m(ttp)g(FITS)f(\014le)g(in)m(to) -i(memory)0 3360 y(on)f(the)g(lo)s(cal)h(mac)m(hine)f(b)s(efore)g(op)s -(ening)f(it.)58 b(This)35 b(will)h(fail)g(if)g(the)g(lo)s(cal)h(mac)m -(hine)g(do)s(es)e(not)h(ha)m(v)m(e)h(enough)0 3473 y(memory)g(to)h -(hold)f(the)g(whole)h(FITS)e(\014le,)k(so)d(in)g(this)g(case,)k(the)c -(output)g(\014lename)g(sp)s(eci\014er)g(\(see)h(the)g(next)0 -3586 y(section\))32 b(can)f(b)s(e)e(used)h(to)h(further)e(con)m(trol)j -(ho)m(w)e(CFITSIO)f(reads)h(ftp)g(and)g(h)m(ttp)g(\014les.)0 -3746 y(If)i(the)h(input)f(\014le)h(is)g(an)g(IRAF)g(image)h(\014le)f -(\(*.imh)g(\014le\))h(then)e(CFITSIO)f(will)j(automatically)h(con)m(v)m -(ert)g(it)e(on)0 3859 y(the)27 b(\015y)g(in)m(to)h(a)g(virtual)f(FITS)f -(image)j(b)s(efore)e(it)g(is)g(op)s(ened)g(b)m(y)g(the)g(application)i -(program.)39 b(IRAF)27 b(images)i(can)0 3972 y(only)h(b)s(e)g(op)s -(ened)g(with)g(READONL)-8 b(Y)31 b(\014le)f(access.)0 -4132 y(Similarly)-8 b(,)32 b(if)f(the)g(input)f(\014le)i(is)f(a)g(ra)m -(w)g(binary)f(data)i(arra)m(y)-8 b(,)33 b(then)d(CFITSIO)g(will)h(con)m -(v)m(ert)i(it)e(on)g(the)h(\015y)e(in)m(to)0 4245 y(a)38 -b(virtual)g(FITS)g(image)h(with)e(the)h(basic)h(set)f(of)g(required)f -(header)h(k)m(eyw)m(ords)g(b)s(efore)g(it)g(is)g(op)s(ened)f(b)m(y)h -(the)0 4358 y(application)32 b(program)f(\(with)g(READONL)-8 -b(Y)31 b(access\).)44 b(In)30 b(this)h(case)h(the)f(data)g(t)m(yp)s(e)g -(and)g(dimensions)f(of)h(the)0 4471 y(image)d(m)m(ust)f(b)s(e)f(sp)s -(eci\014ed)g(in)h(square)g(brac)m(k)m(ets)h(follo)m(wing)g(the)f -(\014lename)g(\(e.g.)41 b(ra)m(w\014le.dat[ib512,512]\).)j(The)0 -4584 y(\014rst)30 b(c)m(haracter)i(\(case)f(insensitiv)m(e\))h -(de\014nes)e(the)g(data)h(t)m(yp)s(e)g(of)f(the)h(arra)m(y:)239 -4810 y Fe(b)429 b(8-bit)46 b(unsigned)g(byte)239 4923 -y(i)381 b(16-bit)46 b(signed)g(integer)239 5036 y(u)381 -b(16-bit)46 b(unsigned)g(integer)239 5149 y(j)381 b(32-bit)46 -b(signed)g(integer)239 5262 y(r)h(or)g(f)143 b(32-bit)46 -b(floating)g(point)239 5375 y(d)381 b(64-bit)46 b(floating)g(point)0 -5601 y Fj(An)40 b(optional)h(second)f(c)m(haracter)i(sp)s(eci\014es)e -(the)h(b)m(yte)f(order)g(of)g(the)h(arra)m(y)g(v)-5 b(alues:)60 -b(b)40 b(or)g(B)h(indicates)g(big)0 5714 y(endian)30 -b(\(as)g(in)g(FITS)f(\014les)h(and)f(the)h(nativ)m(e)i(format)e(of)g -(SUN)g(UNIX)g(w)m(orkstations)h(and)f(Mac)h(PCs\))e(and)h(l)g(or)p -eop end -%%Page: 130 138 -TeXDict begin 130 137 bop 0 299 a Fj(130)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fj(L)27 b(indicates)i(little)g(endian)e(\(nativ)m(e)j(format)d -(of)h(DEC)g(OSF)f(w)m(orkstations)h(and)f(IBM)h(PCs\).)40 -b(If)27 b(this)g(c)m(haracter)0 668 y(is)f(omitted)g(then)f(the)h(arra) -m(y)g(is)g(assumed)f(to)h(ha)m(v)m(e)h(the)f(nativ)m(e)g(b)m(yte)h -(order)e(of)h(the)f(lo)s(cal)i(mac)m(hine.)40 b(These)25 -b(data)0 781 y(t)m(yp)s(e)35 b(c)m(haracters)h(are)g(then)e(follo)m(w)m -(ed)j(b)m(y)d(a)i(series)f(of)g(one)g(or)g(more)g(in)m(teger)h(v)-5 -b(alues)35 b(separated)h(b)m(y)e(commas)0 894 y(whic)m(h)41 -b(de\014ne)f(the)h(size)h(of)f(eac)m(h)h(dimension)f(of)g(the)g(ra)m(w) -g(arra)m(y)-8 b(.)74 b(Arra)m(ys)41 b(with)f(up)g(to)i(5)f(dimensions)g -(are)0 1007 y(curren)m(tly)31 b(supp)s(orted.)41 b(Finally)-8 -b(,)33 b(a)e(b)m(yte)h(o\013set)g(to)g(the)f(p)s(osition)h(of)f(the)g -(\014rst)f(pixel)i(in)f(the)g(data)h(\014le)f(ma)m(y)h(b)s(e)0 -1120 y(sp)s(eci\014ed)h(b)m(y)g(separating)i(it)f(with)f(a)h(':')48 -b(from)33 b(the)h(last)g(dimension)f(v)-5 b(alue.)51 -b(If)33 b(omitted,)j(it)e(is)f(assumed)g(that)0 1233 -y(the)i(o\013set)h(=)f(0.)54 b(This)35 b(parameter)g(ma)m(y)h(b)s(e)e -(used)g(to)i(skip)e(o)m(v)m(er)i(an)m(y)g(header)e(information)i(in)e -(the)h(\014le)g(that)0 1346 y(precedes)30 b(the)h(binary)f(data.)41 -b(F)-8 b(urther)30 b(examples:)95 1603 y Fe(raw.dat[b10000])521 -b(1-dimensional)45 b(10000)h(pixel)g(byte)h(array)95 -1715 y(raw.dat[rb400,400,12])233 b(3-dimensional)45 b(floating)g(point) -h(big-endian)f(array)95 1828 y(img.fits[ib512,512:2880])89 -b(reads)47 b(the)g(512)g(x)g(512)g(short)f(integer)g(array)g(in)1336 -1941 y(a)i(FITS)e(file,)h(skipping)e(over)i(the)g(2880)g(byte)f(header) -0 2198 y Fj(One)25 b(sp)s(ecial)g(case)h(of)f(input)f(\014le)h(is)g -(where)g(the)g(\014lename)g(=)g(`-')h(\(a)f(dash)g(or)g(min)m(us)f -(sign\))h(or)g('stdin')g(or)g('stdout',)0 2311 y(whic)m(h)d -(signi\014es)h(that)h(the)f(input)e(\014le)i(is)g(to)h(b)s(e)e(read)g -(from)h(the)g(stdin)f(stream,)j(or)e(written)f(to)i(the)f(stdout)g -(stream)0 2424 y(if)34 b(a)g(new)g(output)f(\014le)h(is)g(b)s(eing)g -(created.)52 b(In)33 b(the)h(case)h(of)f(reading)h(from)e(stdin,)h -(CFITSIO)f(\014rst)g(copies)i(the)0 2537 y(whole)g(stream)h(in)m(to)g -(a)f(temp)s(orary)g(FITS)f(\014le)i(\(in)f(memory)g(or)g(on)g(disk\),)h -(and)f(subsequen)m(t)f(reading)h(of)h(the)0 2650 y(FITS)c(\014le)h(o)s -(ccurs)g(in)f(this)h(cop)m(y)-8 b(.)49 b(When)33 b(writing)g(to)g -(stdout,)h(CFITSIO)d(\014rst)h(constructs)h(the)g(whole)g(\014le)g(in)0 -2763 y(memory)h(\(since)i(random)d(access)j(is)e(required\),)i(then)e -(\015ushes)f(it)i(out)g(to)g(the)f(stdout)h(stream)g(when)e(the)i -(\014le)0 2876 y(is)30 b(closed.)42 b(In)29 b(addition,)i(if)f(the)g -(output)g(\014lename)g(=)g('-.gz')i(or)e('stdout.gz')h(then)f(it)h -(will)f(b)s(e)g(gzip)g(compressed)0 2989 y(b)s(efore)g(b)s(eing)g -(written)g(to)h(stdout.)0 3149 y(This)25 b(abilit)m(y)j(to)e(read)g -(and)f(write)h(on)g(the)g(stdin)g(and)f(stdout)h(steams)g(allo)m(ws)i -(FITS)d(\014les)h(to)g(b)s(e)g(pip)s(ed)e(b)s(et)m(w)m(een)0 -3262 y(tasks)42 b(in)f(memory)g(rather)g(than)h(ha)m(ving)g(to)g -(create)h(temp)s(orary)e(in)m(termediate)i(FITS)d(\014les)i(on)f(disk.) -73 b(F)-8 b(or)0 3375 y(example)28 b(if)e(task1)i(creates)h(an)e -(output)f(FITS)g(\014le,)i(and)f(task2)g(reads)g(an)g(input)f(FITS)g -(\014le,)i(the)f(FITS)f(\014le)h(ma)m(y)0 3487 y(b)s(e)j(pip)s(ed)f(b)s -(et)m(w)m(een)i(the)f(2)h(tasks)g(b)m(y)f(sp)s(ecifying)143 -3744 y Fe(task1)47 b(-)g(|)g(task2)g(-)0 4001 y Fj(where)30 -b(the)h(v)m(ertical)i(bar)e(is)f(the)h(Unix)g(piping)f(sym)m(b)s(ol.)42 -b(This)30 b(assumes)g(that)i(the)f(2)g(tasks)g(read)g(the)g(name)g(of)0 -4114 y(the)g(FITS)e(\014le)i(o\013)f(of)h(the)g(command)f(line.)0 -4448 y Ff(10.4)136 b(Output)44 b(File)i(Name)f(when)g(Op)t(ening)g(an)g -(Existing)h(File)0 4698 y Fj(An)36 b(optional)i(output)e(\014lename)h -(ma)m(y)h(b)s(e)e(sp)s(eci\014ed)g(in)g(paren)m(theses)h(immediately)h -(follo)m(wing)g(the)f(base)g(\014le)0 4811 y(name)28 -b(to)h(b)s(e)f(op)s(ened.)39 b(This)28 b(is)g(mainly)g(useful)g(in)g -(those)g(cases)i(where)d(CFITSIO)g(creates)j(a)e(temp)s(orary)g(cop)m -(y)0 4924 y(of)i(the)f(input)g(FITS)f(\014le)i(b)s(efore)f(it)h(is)f -(op)s(ened)g(and)f(passed)h(to)h(the)g(application)h(program.)40 -b(This)28 b(happ)s(ens)g(b)m(y)0 5036 y(default)i(when)g(op)s(ening)g -(a)g(net)m(w)m(ork)h(FTP)g(or)f(HTTP-t)m(yp)s(e)g(\014le,)h(when)e -(reading)h(a)h(compressed)f(FITS)g(\014le)g(on)0 5149 -y(a)36 b(lo)s(cal)h(disk,)g(when)e(reading)h(from)g(the)g(stdin)f -(stream,)j(or)d(when)g(a)i(column)e(\014lter,)j(ro)m(w)e(\014lter,)h -(or)f(binning)0 5262 y(sp)s(eci\014er)29 b(is)g(included)g(as)h(part)f -(of)g(the)h(input)f(\014le)g(sp)s(eci\014cation.)41 b(By)30 -b(default)g(this)f(temp)s(orary)g(\014le)g(is)h(created)0 -5375 y(in)g(memory)-8 b(.)41 b(If)29 b(there)h(is)g(not)g(enough)g -(memory)g(to)h(create)g(the)g(\014le)f(cop)m(y)-8 b(,)31 -b(then)f(CFITSIO)e(will)i(exit)h(with)f(an)0 5488 y(error.)45 -b(In)32 b(these)g(cases)h(one)g(can)f(force)h(a)f(p)s(ermanen)m(t)g -(\014le)g(to)h(b)s(e)e(created)i(on)f(disk,)g(instead)h(of)f(a)g(temp)s -(orary)0 5601 y(\014le)38 b(in)f(memory)-8 b(,)40 b(b)m(y)d(supplying)f -(the)i(name)g(in)f(paren)m(theses)h(immediately)h(follo)m(wing)g(the)e -(base)h(\014le)g(name.)0 5714 y(The)30 b(output)g(\014lename)g(can)h -(include)f(the)h(')10 b(!')41 b(clobb)s(er)30 b(\015ag.)p -eop end -%%Page: 131 139 -TeXDict begin 131 138 bop 0 299 a Fh(10.4.)73 b(OUTPUT)29 -b(FILE)h(NAME)h(WHEN)g(OPENING)f(AN)h(EXISTING)f(FILE)876 -b Fj(131)0 555 y(Th)m(us,)48 b(if)d(the)g(input)f(\014lename)h(to)g -(CFITSIO)f(is:)70 b Fe(file1.fits.gz\(file2.fit)o(s\))39 -b Fj(then)44 b(CFITSIO)g(will)0 668 y(uncompress)39 b -(`\014le1.\014ts.gz')j(in)m(to)f(the)f(lo)s(cal)h(disk)e(\014le)h -(`\014le2.\014ts')h(b)s(efore)f(op)s(ening)f(it.)70 b(CFITSIO)38 -b(do)s(es)i(not)0 781 y(automatically)33 b(delete)f(the)e(output)g -(\014le,)h(so)g(it)g(will)f(still)i(exist)f(after)g(the)f(application)i -(program)e(exits.)0 941 y(The)i(output)h(\014lename)g("mem://")i(is)e -(also)h(allo)m(w)m(ed,)i(whic)m(h)c(will)i(write)f(the)g(output)f -(\014le)h(in)m(to)h(memory)-8 b(,)35 b(and)0 1054 y(also)28 -b(allo)m(w)g(write)f(access)h(to)g(the)f(\014le.)39 b(This)26 -b('\014le')i(will)f(disapp)s(ear)f(when)g(it)h(is)g(closed,)h(but)e -(this)h(ma)m(y)h(b)s(e)e(useful)0 1167 y(for)k(some)h(applications)g -(whic)m(h)g(only)f(need)g(to)h(mo)s(dify)f(a)h(temp)s(orary)f(cop)m(y)h -(of)f(the)h(\014le.)0 1327 y(In)k(some)i(cases,)h(sev)m(eral)f -(di\013eren)m(t)g(temp)s(orary)e(FITS)h(\014les)g(will)g(b)s(e)f -(created)i(in)f(sequence,)i(for)e(instance,)i(if)0 1440 -y(one)f(op)s(ens)g(a)g(remote)h(\014le)f(using)g(FTP)-8 -b(,)37 b(then)g(\014lters)g(ro)m(ws)g(in)g(a)h(binary)e(table)i -(extension,)i(then)c(create)j(an)0 1553 y(image)f(b)m(y)f(binning)f(a)h -(pair)g(of)g(columns.)60 b(In)36 b(this)h(case,)j(the)d(remote)h -(\014le)f(will)g(b)s(e)f(copied)h(to)h(a)f(temp)s(orary)0 -1666 y(lo)s(cal)j(\014le,)h(then)d(a)h(second)f(temp)s(orary)h(\014le)f -(will)h(b)s(e)f(created)i(con)m(taining)g(the)e(\014ltered)h(ro)m(ws)f -(of)h(the)g(table,)0 1779 y(and)c(\014nally)g(a)h(third)e(temp)s(orary) -h(\014le)h(con)m(taining)g(the)g(binned)e(image)i(will)g(b)s(e)f -(created.)57 b(In)34 b(cases)i(lik)m(e)h(this)0 1892 -y(where)28 b(m)m(ultiple)h(\014les)f(are)h(created,)h(the)e(out\014le)h -(sp)s(eci\014er)f(will)g(b)s(e)g(in)m(terpreted)h(the)f(name)g(of)h -(the)f(\014nal)g(\014le)h(as)0 2005 y(describ)s(ed)g(b)s(elo)m(w,)i(in) -f(descending)g(priorit)m(y:)136 2266 y Fc(\017)46 b Fj(as)29 -b(the)g(name)g(of)g(the)g(\014nal)f(image)i(\014le)f(if)f(an)h(image)h -(within)e(a)h(single)g(binary)f(table)i(cell)g(is)e(op)s(ened)g(or)h -(if)227 2379 y(an)i(image)g(is)g(created)g(b)m(y)f(binning)g(a)g(table) -i(column.)136 2568 y Fc(\017)46 b Fj(as)33 b(the)f(name)h(of)f(the)h -(\014le)f(con)m(taining)i(the)e(\014ltered)g(table)i(if)e(a)h(column)f -(\014lter)g(and/or)g(a)h(ro)m(w)f(\014lter)h(are)227 -2681 y(sp)s(eci\014ed.)136 2870 y Fc(\017)46 b Fj(as)31 -b(the)f(name)h(of)f(the)h(lo)s(cal)h(cop)m(y)f(of)f(the)h(remote)g(FTP) -f(or)h(HTTP)e(\014le.)136 3059 y Fc(\017)46 b Fj(as)31 -b(the)g(name)g(of)g(the)f(uncompressed)g(v)m(ersion)h(of)g(the)f(FITS)g -(\014le,)h(if)g(a)g(compressed)f(FITS)g(\014le)h(on)g(lo)s(cal)227 -3172 y(disk)f(has)g(b)s(een)g(op)s(ened.)136 3361 y Fc(\017)46 -b Fj(otherwise,)31 b(the)g(output)f(\014lename)g(is)h(ignored.)0 -3622 y(The)e(output)f(\014le)h(sp)s(eci\014er)g(is)g(useful)f(when)g -(reading)h(FTP)g(or)g(HTTP-t)m(yp)s(e)g(FITS)f(\014les)h(since)g(it)h -(can)f(b)s(e)g(used)0 3735 y(to)34 b(create)i(a)e(lo)s(cal)h(disk)e -(cop)m(y)i(of)f(the)g(\014le)f(that)i(can)f(b)s(e)f(reused)g(in)g(the)h -(future.)50 b(If)33 b(the)h(output)g(\014le)f(name)h(=)0 -3848 y(`*')i(then)e(a)i(lo)s(cal)g(\014le)f(with)g(the)g(same)g(name)g -(as)g(the)h(net)m(w)m(ork)f(\014le)g(will)h(b)s(e)e(created.)56 -b(Note)36 b(that)f(CFITSIO)0 3961 y(will)30 b(b)s(eha)m(v)m(e)g -(di\013eren)m(tly)h(dep)s(ending)d(on)i(whether)f(the)h(remote)g -(\014le)g(is)g(compressed)f(or)h(not)g(as)g(sho)m(wn)f(b)m(y)h(the)0 -4074 y(follo)m(wing)i(examples:)136 4309 y Fc(\017)46 -b Fe(ftp://remote.machine/tmp/)o(myfi)o(le.f)o(its)o(.gz\()o(*\))28 -b Fj(-)35 b(the)g(remote)h(compressed)e(\014le)h(is)g(copied)g(to)227 -4422 y(the)d(lo)s(cal)h(compressed)f(\014le)g(`m)m(y\014le.\014ts.gz',) -i(whic)m(h)d(is)h(then)g(uncompressed)e(in)i(lo)s(cal)h(memory)e(b)s -(efore)227 4535 y(b)s(eing)f(op)s(ened)g(and)g(passed)f(to)j(the)e -(application)i(program.)136 4724 y Fc(\017)46 b Fe -(ftp://remote.machine/tmp/)o(myfi)o(le.f)o(its)o(.gz\()o(myfi)o(le.)o -(fits)o(\))33 b Fj(-)39 b(the)g(remote)h(compressed)f(\014le)227 -4837 y(is)d(copied)g(and)f(uncompressed)g(in)m(to)h(the)g(lo)s(cal)h -(\014le)f(`m)m(y\014le.\014ts'.)57 b(This)35 b(example)h(requires)g -(less)g(lo)s(cal)227 4950 y(memory)21 b(than)g(the)g(previous)f -(example)i(since)f(the)g(\014le)g(is)g(uncompressed)e(on)i(disk)g -(instead)g(of)g(in)f(memory)-8 b(.)136 5139 y Fc(\017)46 -b Fe(ftp://remote.machine/tmp/)o(myfi)o(le.f)o(its)o(\(myf)o(ile.)o -(fit)o(s.gz)o(\))24 b Fj(-)30 b(this)g(will)g(usually)g(pro)s(duce)f -(an)227 5252 y(error)h(since)h(CFITSIO)e(itself)i(cannot)g(compress)f -(\014les.)0 5488 y(The)36 b(exact)i(b)s(eha)m(vior)e(of)h(CFITSIO)e(in) -h(the)h(latter)g(case)h(dep)s(ends)c(on)j(the)f(t)m(yp)s(e)h(of)g(ftp)f -(serv)m(er)g(running)f(on)0 5601 y(the)c(remote)g(mac)m(hine)g(and)f -(ho)m(w)g(it)h(is)f(con\014gured.)40 b(In)30 b(some)h(cases,)g(if)f -(the)h(\014le)f(`m)m(y\014le.\014ts.gz')j(exists)e(on)f(the)0 -5714 y(remote)38 b(mac)m(hine,)h(then)e(the)g(serv)m(er)g(will)h(cop)m -(y)f(it)h(to)f(the)h(lo)s(cal)g(mac)m(hine.)61 b(In)36 -b(other)h(cases)h(the)f(ftp)g(serv)m(er)p eop end -%%Page: 132 140 -TeXDict begin 132 139 bop 0 299 a Fj(132)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fj(will)36 b(automatically)j(create)e(and)f(transmit)g(a)g -(compressed)g(v)m(ersion)g(of)g(the)g(\014le)g(if)g(only)g(the)g -(uncompressed)0 668 y(v)m(ersion)27 b(exists.)41 b(This)26 -b(can)h(get)h(rather)f(confusing,)h(so)f(users)f(should)g(use)h(a)g -(certain)h(amoun)m(t)g(of)f(caution)h(when)0 781 y(using)34 -b(the)h(output)f(\014le)h(sp)s(eci\014er)f(with)h(FTP)f(or)h(HTTP)f -(\014le)h(t)m(yp)s(es,)h(to)f(mak)m(e)h(sure)e(they)h(get)h(the)f(b)s -(eha)m(vior)0 894 y(that)c(they)g(exp)s(ect.)0 1250 y -Ff(10.5)136 b(T)-11 b(emplate)45 b(File)h(Name)g(when)e(Creating)j(a)e -(New)g(File)0 1504 y Fj(When)38 b(a)h(new)f(FITS)g(\014le)h(is)g -(created)g(with)g(a)f(call)i(to)g(\014ts)p 2101 1504 -28 4 v 32 w(create)p 2369 1504 V 35 w(\014le,)g(the)f(name)g(of)g(a)g -(template)h(\014le)e(ma)m(y)0 1617 y(b)s(e)h(supplied)g(in)h(paren)m -(theses)g(immediately)h(follo)m(wing)g(the)g(name)f(of)g(the)g(new)f -(\014le)h(to)h(b)s(e)e(created.)71 b(This)0 1730 y(template)27 -b(is)e(used)g(to)h(de\014ne)f(the)h(structure)f(of)h(one)f(or)h(more)g -(HDUs)g(in)f(the)h(new)f(\014le.)39 b(The)25 b(template)i(\014le)e(ma)m -(y)0 1843 y(b)s(e)32 b(another)h(FITS)f(\014le,)i(in)f(whic)m(h)f(case) -i(the)f(newly)g(created)h(\014le)f(will)g(ha)m(v)m(e)h(exactly)h(the)e -(same)g(k)m(eyw)m(ords)g(in)0 1956 y(eac)m(h)25 b(HDU)g(as)g(in)f(the)g -(template)i(FITS)d(\014le,)j(but)d(all)j(the)e(data)h(units)e(will)i(b) -s(e)f(\014lled)g(with)f(zeros.)40 b(The)24 b(template)0 -2069 y(\014le)i(ma)m(y)h(also)g(b)s(e)e(an)h(ASCI)s(I)e(text)j(\014le,) -g(where)f(eac)m(h)h(line)f(\(in)g(general\))i(describ)s(es)d(one)h -(FITS)f(k)m(eyw)m(ord)i(record.)0 2182 y(The)j(format)h(of)f(the)h -(ASCI)s(I)e(template)i(\014le)g(is)f(describ)s(ed)f(in)i(the)f(follo)m -(wing)i(T)-8 b(emplate)31 b(Files)h(c)m(hapter.)0 2538 -y Ff(10.6)136 b(Image)46 b(Tile-Compression)g(Sp)t(eci\014cation)0 -2792 y Fj(When)28 b(sp)s(ecifying)g(the)h(name)g(of)f(the)h(output)f -(FITS)g(\014le)g(to)h(b)s(e)f(created,)i(the)f(user)f(can)g(indicate)i -(that)f(images)0 2905 y(should)d(b)s(e)h(written)g(in)g -(tile-compressed)h(format)g(\(see)g(section)g(5.5,)h(\\Primary)e(Arra)m -(y)h(or)f(IMA)m(GE)h(Extension)0 3018 y(I/O)f(Routines"\))i(b)m(y)e -(enclosing)h(the)g(compression)f(parameters)h(in)f(square)g(brac)m(k)m -(ets)i(follo)m(wing)g(the)f(ro)s(ot)f(disk)0 3131 y(\014le)j(name.)41 -b(Here)31 b(are)g(some)g(examples)g(of)f(the)h(syn)m(tax)g(for)f(sp)s -(ecifying)g(tile-compressed)i(output)e(images:)191 3410 -y Fe(myfile.fit[compress])185 b(-)48 b(use)f(Rice)f(algorithm)g(and)h -(default)e(tile)i(size)191 3636 y(myfile.fit[compress)42 -b(GZIP])47 b(-)g(use)g(the)g(specified)e(compression)g(algorithm;)191 -3748 y(myfile.fit[compress)d(Rice])238 b(only)46 b(the)h(first)g -(letter)f(of)h(the)g(algorithm)191 3861 y(myfile.fit[compress)42 -b(PLIO])238 b(name)46 b(is)i(required.)191 4087 y(myfile.fit[compress) -42 b(Rice)47 b(100,100])141 b(-)48 b(use)e(100)h(x)h(100)f(pixel)f -(tile)h(size)191 4200 y(myfile.fit[compress)42 b(Rice)47 -b(100,100;2])e(-)j(as)f(above,)f(and)h(use)g(noisebits)e(=)i(2)0 -4556 y Ff(10.7)136 b(HDU)45 b(Lo)t(cation)g(Sp)t(eci\014cation)0 -4811 y Fj(The)c(optional)h(HDU)h(lo)s(cation)g(sp)s(eci\014er)d -(de\014nes)h(whic)m(h)g(HDU)h(\(Header-Data)i(Unit,)h(also)d(kno)m(wn)f -(as)h(an)0 4924 y(`extension'\))36 b(within)d(the)i(FITS)e(\014le)h(to) -h(initially)h(op)s(en.)51 b(It)34 b(m)m(ust)g(immediately)i(follo)m(w)f -(the)f(base)h(\014le)f(name)0 5036 y(\(or)g(the)g(output)g(\014le)g -(name)f(if)h(presen)m(t\).)52 b(If)33 b(it)h(is)g(not)g(sp)s(eci\014ed) -g(then)f(the)h(\014rst)f(HDU)i(\(the)f(primary)f(arra)m(y\))0 -5149 y(is)g(op)s(ened.)46 b(The)32 b(HDU)h(lo)s(cation)h(sp)s -(eci\014er)e(is)h(required)f(if)g(the)h(colFilter,)i(ro)m(wFilter,)g -(or)e(binSp)s(ec)e(sp)s(eci\014ers)0 5262 y(are)f(presen)m(t,)f(b)s -(ecause)h(the)f(primary)f(arra)m(y)i(is)f(not)h(a)f(v)-5 -b(alid)30 b(HDU)g(for)f(these)g(op)s(erations.)41 b(The)29 -b(HDU)h(ma)m(y)g(b)s(e)0 5375 y(sp)s(eci\014ed)e(either)i(b)m(y)e -(absolute)i(p)s(osition)f(n)m(um)m(b)s(er,)f(starting)i(with)e(0)i(for) -e(the)h(primary)f(arra)m(y)-8 b(,)31 b(or)e(b)m(y)f(reference)0 -5488 y(to)h(the)g(HDU)g(name,)g(and)f(optionally)-8 b(,)31 -b(the)e(v)m(ersion)g(n)m(um)m(b)s(er)e(and)h(the)h(HDU)g(t)m(yp)s(e)g -(of)f(the)h(desired)f(extension.)0 5601 y(The)k(lo)s(cation)h(of)f(an)g -(image)i(within)d(a)i(single)f(cell)i(of)e(a)g(binary)g(table)h(ma)m(y) -f(also)h(b)s(e)f(sp)s(eci\014ed,)g(as)g(describ)s(ed)0 -5714 y(b)s(elo)m(w.)p eop end -%%Page: 133 141 -TeXDict begin 133 140 bop 0 299 a Fh(10.7.)73 b(HDU)31 -b(LOCA)-8 b(TION)29 b(SPECIFICA)-8 b(TION)2019 b Fj(133)0 -555 y(The)26 b(absolute)h(p)s(osition)f(of)g(the)h(extension)g(is)f(sp) -s(eci\014ed)f(either)i(b)m(y)f(enclosed)h(the)g(n)m(um)m(b)s(er)e(in)h -(square)f(brac)m(k)m(ets)0 668 y(\(e.g.,)k(`[1]')g(=)d(the)h(\014rst)f -(extension)h(follo)m(wing)i(the)e(primary)e(arra)m(y\))j(or)f(b)m(y)f -(preceded)h(the)g(n)m(um)m(b)s(er)e(with)i(a)g(plus)0 -781 y(sign)37 b(\(`+1'\).)63 b(T)-8 b(o)38 b(sp)s(ecify)f(the)g(HDU)h -(b)m(y)g(name,)h(giv)m(e)g(the)e(name)h(of)f(the)h(desired)f(HDU)h -(\(the)f(v)-5 b(alue)38 b(of)g(the)0 894 y(EXTNAME)e(or)g(HDUNAME)h(k)m -(eyw)m(ord\))g(and)f(optionally)h(the)f(extension)h(v)m(ersion)f(n)m -(um)m(b)s(er)f(\(v)-5 b(alue)37 b(of)f(the)0 1007 y(EXTVER)27 -b(k)m(eyw)m(ord\))i(and)e(the)h(extension)h(t)m(yp)s(e)e(\(v)-5 -b(alue)29 b(of)f(the)g(XTENSION)f(k)m(eyw)m(ord:)40 b(IMA)m(GE,)29 -b(ASCI)s(I)d(or)0 1120 y(T)-8 b(ABLE,)36 b(or)f(BINT)-8 -b(ABLE\),)36 b(separated)f(b)m(y)g(commas)h(and)e(all)i(enclosed)g(in)f -(square)g(brac)m(k)m(ets.)56 b(If)34 b(the)h(v)-5 b(alue)0 -1233 y(of)34 b(EXTVER)f(and)f(XTENSION)h(are)h(not)f(sp)s(eci\014ed,)h -(then)f(the)h(\014rst)e(extension)j(with)e(the)g(correct)i(v)-5 -b(alue)34 b(of)0 1346 y(EXTNAME)39 b(is)g(op)s(ened.)67 -b(The)38 b(extension)i(name)f(and)f(t)m(yp)s(e)i(are)f(not)h(case)g -(sensitiv)m(e,)j(and)38 b(the)h(extension)0 1458 y(t)m(yp)s(e)29 -b(ma)m(y)g(b)s(e)f(abbreviated)h(to)g(a)g(single)g(letter)h(\(e.g.,)h -(I)d(=)g(IMA)m(GE)i(extension)f(or)f(primary)g(arra)m(y)-8 -b(,)30 b(A)f(or)f(T)g(=)0 1571 y(ASCI)s(I)d(table)i(extension,)h(and)e -(B)h(=)f(binary)g(table)h(BINT)-8 b(ABLE)27 b(extension\).)41 -b(If)26 b(the)g(HDU)h(lo)s(cation)i(sp)s(eci\014er)0 -1684 y(is)h(equal)h(to)g(`[PRIMAR)-8 b(Y]')32 b(or)f(`[P]',)g(then)f -(the)h(primary)e(arra)m(y)i(\(the)g(\014rst)f(HDU\))h(will)g(b)s(e)f -(op)s(ened.)0 1844 y(An)36 b(optional)j(p)s(ound)34 b(sign)j(c)m -(haracter)i(\("#"\))f(ma)m(y)f(b)s(e)g(app)s(ended)e(to)i(the)g -(extension)h(name)f(or)g(n)m(um)m(b)s(er)e(to)0 1957 -y(signify)e(that)h(an)m(y)g(other)f(extensions)h(in)f(the)g(\014le)g -(should)g(b)s(e)f(ignored)h(during)f(an)m(y)i(subsequen)m(t)e(\014le)i -(\014ltering)0 2070 y(op)s(erations.)83 b(F)-8 b(or)45 -b(example,)k(when)43 b(doing)i(ro)m(w)f(\014ltering)h(op)s(erations)f -(on)h(a)f(table)i(extension,)i(CFITSIO)0 2183 y(normally)27 -b(creates)i(a)e(cop)m(y)h(of)f(the)g(\014ltered)g(table)h(in)f(memory) --8 b(,)28 b(along)h(with)d(a)i(v)m(erbatim)f(cop)m(y)h(of)f(all)h(the)g -(other)0 2296 y(extensions)h(in)g(the)g(input)f(FITS)g(\014le.)41 -b(If)28 b(the)h(p)s(ound)e(sign)i(is)g(app)s(ended)e(to)j(the)f(table)h -(extension)g(name,)f(then)0 2409 y(only)34 b(that)g(extension,)i(and)d -(none)h(of)g(the)g(other)g(extensions)g(in)f(the)h(\014le,)h(will)g(b)m -(y)e(copied)h(to)h(memory)-8 b(,)35 b(as)f(in)0 2522 -y(the)d(follo)m(wing)g(example:)143 2773 y Fe(myfile.fit[events#][TIME) -41 b(>)48 b(10000])0 3024 y Fj(FITS)34 b(images)i(are)f(most)h -(commonly)f(stored)g(in)g(the)g(primary)f(arra)m(y)h(or)g(an)g(image)h -(extension,)h(but)d(images)0 3137 y(can)d(also)h(b)s(e)e(stored)h(as)h -(a)f(v)m(ector)h(in)f(a)g(single)h(cell)g(of)f(a)h(binary)e(table)i -(\(i.e.)43 b(eac)m(h)32 b(ro)m(w)f(of)g(the)h(v)m(ector)g(column)0 -3250 y(con)m(tains)d(a)g(di\013eren)m(t)f(image\).)42 -b(Suc)m(h)27 b(an)h(image)i(can)e(b)s(e)g(op)s(ened)f(with)h(CFITSIO)e -(b)m(y)i(sp)s(ecifying)g(the)g(desired)0 3363 y(column)k(name)g(and)f -(the)h(ro)m(w)g(n)m(um)m(b)s(er)f(after)h(the)g(binary)f(table)i(HDU)g -(sp)s(eci\014er)e(as)h(sho)m(wn)g(in)f(the)h(follo)m(wing)0 -3476 y(examples.)71 b(The)40 b(column)g(name)h(is)f(separated)h(from)f -(the)h(HDU)g(sp)s(eci\014er)f(b)m(y)g(a)h(semicolon)g(and)f(the)h(ro)m -(w)0 3589 y(n)m(um)m(b)s(er)29 b(is)h(enclosed)h(in)e(paren)m(theses.) -41 b(In)30 b(this)g(case)h(CFITSIO)d(copies)j(the)f(image)i(from)d(the) -i(table)g(cell)g(in)m(to)0 3702 y(a)h(temp)s(orary)e(primary)h(arra)m -(y)g(b)s(efore)g(it)h(is)f(op)s(ened.)43 b(The)30 b(application)j -(program)e(then)g(just)g(sees)g(the)h(image)0 3815 y(in)i(the)h -(primary)e(arra)m(y)-8 b(,)37 b(without)d(an)m(y)h(extensions.)53 -b(The)34 b(particular)g(ro)m(w)h(to)g(b)s(e)e(op)s(ened)h(ma)m(y)h(b)s -(e)f(sp)s(eci\014ed)0 3927 y(either)28 b(b)m(y)f(giving)h(an)f -(absolute)h(in)m(teger)h(ro)m(w)f(n)m(um)m(b)s(er)e(\(starting)i(with)f -(1)h(for)f(the)g(\014rst)g(ro)m(w\),)i(or)e(b)m(y)g(sp)s(ecifying)0 -4040 y(a)33 b(b)s(o)s(olean)f(expression)g(that)h(ev)-5 -b(aluates)34 b(to)f(TR)m(UE)g(for)f(the)g(desired)g(ro)m(w.)47 -b(The)32 b(\014rst)f(ro)m(w)i(that)g(satis\014es)g(the)0 -4153 y(expression)28 b(will)g(b)s(e)g(used.)39 b(The)28 -b(ro)m(w)g(selection)i(expression)e(has)g(the)g(same)g(syn)m(tax)h(as)f -(describ)s(ed)f(in)h(the)g(Ro)m(w)0 4266 y(Filter)k(Sp)s(eci\014er)d -(section,)j(b)s(elo)m(w.)0 4426 y(Examples:)143 4677 -y Fe(myfile.fits[3])44 b(-)k(open)e(the)h(3rd)g(HDU)g(following)e(the)i -(primary)f(array)143 4790 y(myfile.fits+3)92 b(-)48 b(same)e(as)h -(above,)f(but)h(using)g(the)g(FTOOLS-style)d(notation)143 -4903 y(myfile.fits[EVENTS])f(-)k(open)g(the)g(extension)e(that)i(has)g -(EXTNAME)e(=)j('EVENTS')143 5016 y(myfile.fits[EVENTS,)43 -b(2])95 b(-)47 b(same)g(as)g(above,)f(but)h(also)g(requires)e(EXTVER)h -(=)i(2)143 5129 y(myfile.fits[events,2,b])42 b(-)47 b(same,)f(but)h -(also)g(requires)f(XTENSION)f(=)j('BINTABLE')143 5242 -y(myfile.fits[3;)c(images\(17\)])h(-)i(opens)g(the)g(image)f(in)h(row)g -(17)g(of)g(the)g('images')1527 5355 y(column)f(in)i(the)e(3rd)h -(extension)f(of)h(the)g(file.)143 5468 y(myfile.fits[3;)d -(images\(exposure)g(>)j(100\)])g(-)g(as)g(above,)f(but)h(opens)g(the)f -(image)907 5581 y(in)h(the)g(first)f(row)h(that)g(has)g(an)g -('exposure')e(column)h(value)907 5694 y(greater)g(than)g(100.)p -eop end -%%Page: 134 142 -TeXDict begin 134 141 bop 0 299 a Fj(134)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Ff(10.8)136 b(Image)46 b(Section)0 811 y Fj(A)41 -b(virtual)g(\014le)f(con)m(taining)i(a)f(rectangular)h(subsection)e(of) -h(an)g(image)g(can)g(b)s(e)f(extracted)i(and)e(op)s(ened)g(b)m(y)0 -924 y(sp)s(ecifying)32 b(the)h(range)g(of)g(pixels)g(\(start:end\))g -(along)h(eac)m(h)g(axis)f(to)g(b)s(e)f(extracted)i(from)e(the)h -(original)g(image.)0 1037 y(One)d(can)h(also)h(sp)s(ecify)e(an)h -(optional)h(pixel)f(incremen)m(t)g(\(start:end:step\))h(for)f(eac)m(h)h -(axis)f(of)g(the)g(input)e(image.)0 1149 y(A)f(pixel)f(step)h(=)f(1)h -(will)g(b)s(e)f(assumed)f(if)i(it)g(is)f(not)h(sp)s(eci\014ed.)39 -b(If)27 b(the)h(start)g(pixel)g(is)f(larger)i(then)e(the)h(end)e -(pixel,)0 1262 y(then)32 b(the)g(image)h(will)f(b)s(e)f(\015ipp)s(ed)f -(\(pro)s(ducing)h(a)h(mirror)g(image\))h(along)g(that)f(dimension.)45 -b(An)32 b(asterisk,)h('*',)0 1375 y(ma)m(y)39 b(b)s(e)e(used)h(to)h(sp) -s(ecify)f(the)g(en)m(tire)h(range)g(of)f(an)h(axis,)i(and)c('-*')j -(will)e(\015ip)g(the)g(en)m(tire)h(axis.)65 b(The)38 -b(input)0 1488 y(image)31 b(can)f(b)s(e)f(in)g(the)h(primary)f(arra)m -(y)-8 b(,)31 b(in)e(an)g(image)i(extension,)g(or)f(con)m(tained)g(in)g -(a)g(v)m(ector)h(cell)g(of)f(a)g(binary)0 1601 y(table.)40 -b(In)25 b(the)h(later)h(2)f(cases)h(the)f(extension)h(name)f(or)f(n)m -(um)m(b)s(er)g(m)m(ust)h(b)s(e)f(sp)s(eci\014ed)g(b)s(efore)h(the)g -(image)h(section)0 1714 y(sp)s(eci\014er.)0 1874 y(Examples:)95 -2157 y Fe(myfile.fits[1:512:2,)43 b(2:512:2])i(-)95 b(open)47 -b(a)h(256x256)d(pixel)i(image)668 2270 y(consisting)e(of)i(the)g(odd)g -(numbered)f(columns)g(\(1st)g(axis\))h(and)668 2383 y(the)g(even)g -(numbered)e(rows)i(\(2nd)g(axis\))f(of)h(the)g(image)f(in)i(the)668 -2496 y(primary)e(array)g(of)i(the)e(file.)95 2721 y(myfile.fits[*,)e -(512:256])i(-)h(open)g(an)g(image)g(consisting)e(of)i(all)g(the)g -(columns)668 2834 y(in)g(the)g(input)g(image,)f(but)h(only)f(rows)h -(256)g(through)f(512.)668 2947 y(The)h(image)f(will)h(be)g(flipped)f -(along)g(the)h(2nd)g(axis)g(since)668 3060 y(the)g(starting)f(pixel)g -(is)h(greater)f(than)h(the)g(ending)f(pixel.)95 3286 -y(myfile.fits[*:2,)e(512:256:2])h(-)i(same)g(as)g(above)f(but)h -(keeping)f(only)668 3399 y(every)h(other)f(row)h(and)g(column)f(in)h -(the)g(input)f(image.)95 3625 y(myfile.fits[-*,)e(*])j(-)h(copy)e(the)h -(entire)f(image,)g(flipping)g(it)h(along)668 3738 y(the)g(first)f -(axis.)95 3963 y(myfile.fits[3][1:256,1:256)o(])c(-)47 -b(opens)g(a)g(subsection)e(of)i(the)g(image)g(that)668 -4076 y(is)g(in)h(the)e(3rd)h(extension)f(of)h(the)g(file.)95 -4302 y(myfile.fits[4;)d(images\(12\)][1:10,1:10])e(-)48 -b(open)e(an)h(image)g(consisting)286 4415 y(of)h(the)e(first)h(10)g -(pixels)f(in)h(both)g(dimensions.)e(The)i(original)286 -4528 y(image)g(resides)f(in)h(the)g(12th)f(row)h(of)g(the)g('images')f -(vector)286 4641 y(column)g(in)i(the)f(table)f(in)h(the)g(4th)g -(extension)e(of)i(the)g(file.)0 4924 y Fj(When)23 b(CFITSIO)f(op)s(ens) -h(an)g(image)h(section)h(it)f(\014rst)f(creates)h(a)g(temp)s(orary)f -(\014le)h(con)m(taining)h(the)e(image)i(section)0 5036 -y(plus)30 b(a)h(cop)m(y)h(of)f(an)m(y)g(other)g(HDUs)g(in)g(the)g -(\014le.)42 b(\(If)31 b(a)g(`#')g(c)m(haracter)h(is)f(app)s(ended)e(to) -j(the)f(name)f(or)h(n)m(um)m(b)s(er)0 5149 y(of)i(the)g(image)i(HDU,)e -(as)h(in)e("m)m(y\014le.\014ts[1#][1:200,1:200)q(]",)40 -b(then)33 b(the)g(other)g(HDUs)h(in)e(the)h(input)g(\014le)g(will)0 -5262 y(not)j(b)s(e)f(copied)i(in)m(to)f(memory\).)58 -b(This)35 b(temp)s(orary)g(\014le)h(is)g(then)f(op)s(ened)h(b)m(y)f -(the)h(application)h(program,)h(so)0 5375 y(it)32 b(is)g(not)f(p)s -(ossible)h(to)g(write)g(to)g(or)f(mo)s(dify)g(the)h(input)e(\014le)i -(when)f(sp)s(ecifying)g(an)g(image)i(section.)45 b(Note)33 -b(that)0 5488 y(CFITSIO)27 b(automatically)32 b(up)s(dates)c(the)h(w)m -(orld)f(co)s(ordinate)i(system)f(k)m(eyw)m(ords)g(in)f(the)h(header)g -(of)g(the)g(image)0 5601 y(section,)h(if)f(they)g(exist,)h(so)f(that)g -(the)g(co)s(ordinate)h(asso)s(ciated)g(with)e(eac)m(h)i(pixel)f(in)g -(the)g(image)h(section)g(will)f(b)s(e)0 5714 y(computed)h(correctly)-8 -b(.)p eop end -%%Page: 135 143 -TeXDict begin 135 142 bop 0 299 a Fh(10.9.)73 b(IMA)m(GE)31 -b(TRANSF)m(ORM)f(FIL)-8 b(TERS)2147 b Fj(135)0 555 y -Ff(10.9)136 b(Image)46 b(T)-11 b(ransform)44 b(Filters)0 -807 y Fj(CFITSIO)33 b(can)h(apply)g(a)h(user-sp)s(eci\014ed)e -(mathematical)j(function)e(to)h(the)g(v)-5 b(alue)34 -b(of)h(ev)m(ery)g(pixel)f(in)g(a)h(FITS)0 920 y(image,)29 -b(th)m(us)e(creating)h(a)g(new)e(virtual)h(image)i(in)d(computer)h -(memory)g(that)h(is)f(then)f(op)s(ened)h(and)f(read)h(b)m(y)g(the)0 -1033 y(application)32 b(program.)40 b(The)30 b(original)i(FITS)d(image) -j(is)e(not)h(mo)s(di\014ed)e(b)m(y)h(this)h(pro)s(cess.)0 -1193 y(The)20 b(image)j(transformation)e(sp)s(eci\014er)f(is)h(app)s -(ended)e(to)j(the)f(input)f(FITS)h(\014le)g(name)g(and)f(is)h(enclosed) -h(in)e(square)0 1306 y(brac)m(k)m(ets.)42 b(It)29 b(b)s(egins)f(with)h -(the)g(letters)i('PIX')e(to)h(distinguish)e(it)i(from)e(other)i(t)m(yp) -s(es)f(of)g(FITS)f(\014le)h(\014lters)g(that)0 1419 y(are)36 -b(recognized)i(b)m(y)e(CFITSIO.)e(The)i(image)h(transforming)f -(function)f(ma)m(y)i(use)f(an)m(y)g(of)g(the)h(mathematical)0 -1532 y(op)s(erators)44 b(listed)h(in)f(the)h(follo)m(wing)h('Ro)m(w)f -(Filtering)g(Sp)s(eci\014cation')g(section)h(of)e(this)h(do)s(cumen)m -(t.)82 b(Some)0 1645 y(examples)31 b(of)f(image)i(transform)e -(\014lters)g(are:)48 1913 y Fe([pix)46 b(X)i(*)f(2.0])715 -b(-)48 b(multiply)d(each)i(pixel)f(by)h(2.0)48 2026 y([pix)f -(sqrt\(X\)])714 b(-)48 b(take)e(the)h(square)f(root)h(of)g(each)g -(pixel)48 2139 y([pix)f(X)i(+)f(#ZEROPT)571 b(-)48 b(add)e(the)h(value) -g(of)g(the)g(ZEROPT)f(keyword)48 2252 y([pix)g(X>0)h(?)h(log10\(X\))d -(:)j(-99.])e(-)i(if)f(the)g(pixel)f(value)g(is)i(greater)1480 -2365 y(than)e(0,)h(compute)f(the)h(base)g(10)g(log,)1480 -2478 y(else)f(set)h(the)g(pixel)f(=)i(-99.)0 2746 y Fj(Use)24 -b(the)g(letter)h('X')f(in)f(the)h(expression)g(to)g(represen)m(t)g(the) -g(curren)m(t)f(pixel)h(v)-5 b(alue)24 b(in)f(the)h(image.)40 -b(The)23 b(expression)0 2859 y(is)38 b(ev)-5 b(aluated)39 -b(indep)s(enden)m(tly)e(for)g(eac)m(h)i(pixel)f(in)g(the)g(image)h(and) -e(ma)m(y)h(b)s(e)g(a)g(function)f(of)h(1\))h(the)f(original)0 -2971 y(pixel)32 b(v)-5 b(alue,)32 b(2\))g(the)f(v)-5 -b(alue)32 b(of)f(other)h(pixels)f(in)g(the)g(image)i(at)f(a)f(giv)m(en) -i(relativ)m(e)g(o\013set)f(from)f(the)g(p)s(osition)h(of)0 -3084 y(the)d(pixel)f(that)h(is)g(b)s(eing)f(ev)-5 b(aluated,)30 -b(and)e(3\))h(the)g(v)-5 b(alue)29 b(of)f(an)m(y)h(header)f(k)m(eyw)m -(ords.)41 b(Header)29 b(k)m(eyw)m(ord)g(v)-5 b(alues)0 -3197 y(are)31 b(represen)m(ted)f(b)m(y)g(the)h(name)f(of)h(the)f(k)m -(eyw)m(ord)h(preceded)f(b)m(y)h(the)f('#')h(sign.)0 3357 -y(T)-8 b(o)35 b(access)h(the)f(the)g(v)-5 b(alue)35 b(of)g(adjacen)m(t) -h(pixels)f(in)f(the)h(image,)i(sp)s(ecify)e(the)g(\(1-D\))h(o\013set)g -(from)e(the)h(curren)m(t)0 3470 y(pixel)c(in)f(curly)g(brac)m(k)m(ets.) -42 b(F)-8 b(or)31 b(example)48 3738 y Fe([pix)94 b(\(x{-1})46 -b(+)i(x)f(+)h(x{+1}\))e(/)h(3])0 4006 y Fj(will)25 b(replace)g(eac)m(h) -h(pixel)f(v)-5 b(alue)25 b(with)f(the)h(running)e(mean)i(of)f(the)h(v) --5 b(alues)25 b(of)g(that)g(pixel)g(and)f(it's)h(2)g(neigh)m(b)s(oring) -0 4119 y(pixels.)40 b(Note)30 b(that)g(in)e(this)g(notation)i(the)f -(image)h(is)f(treated)g(as)g(a)g(1-D)h(arra)m(y)-8 b(,)30 -b(where)e(eac)m(h)i(ro)m(w)f(of)g(the)g(image)0 4232 -y(\(or)c(higher)f(dimensional)g(cub)s(e\))h(is)f(app)s(ended)f(one)h -(after)h(another)g(in)f(one)h(long)g(arra)m(y)g(of)f(pixels.)39 -b(It)25 b(is)f(p)s(ossible)0 4345 y(to)35 b(refer)f(to)h(pixels)f(in)g -(the)g(ro)m(ws)g(ab)s(o)m(v)m(e)h(or)g(b)s(elo)m(w)f(the)g(curren)m(t)g -(pixel)h(b)m(y)f(using)f(the)h(v)-5 b(alue)35 b(of)f(the)h(NAXIS1)0 -4458 y(header)30 b(k)m(eyw)m(ord.)41 b(F)-8 b(or)32 b(example)48 -4726 y Fe([pix)46 b(\(x{-#NAXIS1})f(+)i(x)h(+)f(x{#NAXIS1}\))e(/)i(3])0 -4994 y Fj(will)34 b(compute)f(the)h(mean)f(of)g(eac)m(h)i(image)f -(pixel)g(and)e(the)i(pixels)f(immediately)i(ab)s(o)m(v)m(e)f(and)f(b)s -(elo)m(w)g(it)h(in)f(the)0 5107 y(adjacen)m(t)27 b(ro)m(ws)f(of)g(the)f -(image.)41 b(The)25 b(follo)m(wing)i(more)f(complex)h(example)f -(creates)h(a)f(smo)s(othed)g(virtual)g(image)0 5220 y(where)k(eac)m(h)h -(pixel)g(is)g(a)f(3)h(x)f(3)h(b)s(o)m(xcar)g(a)m(v)m(erage)i(of)d(the)h -(input)e(image)j(pixels:)95 5488 y Fe([pix)47 b(\(X)g(+)h(X{-1})e(+)i -(X{+1})286 5601 y(+)g(X{-#NAXIS1})d(+)i(X{-#NAXIS1)e(-)i(1})h(+)f -(X{-#NAXIS1)e(+)j(1})286 5714 y(+)g(X{#NAXIS1})d(+)i(X{#NAXIS1)f(-)h -(1})g(+)h(X{#NAXIS1)d(+)i(1}\))g(/)h(9.])p eop end -%%Page: 136 144 -TeXDict begin 136 143 bop 0 299 a Fj(136)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fj(If)31 b(the)h(pixel)g(o\013set)h(extends)f(b)s(ey)m(ond)f(the) -h(\014rst)f(or)h(last)h(pixel)f(in)f(the)h(image,)i(the)e(function)g -(will)g(ev)-5 b(aluate)33 b(to)0 668 y(unde\014ned,)28 -b(or)j(NULL.)0 828 y(F)-8 b(or)39 b(complex)g(or)g(commonly)g(used)e -(image)j(\014ltering)f(op)s(erations,)i(one)d(can)h(write)g(the)f -(expression)h(in)m(to)g(an)0 941 y(external)i(text)h(\014le)f(and)f -(then)g(imp)s(ort)g(it)h(in)m(to)h(the)e(\014lter)h(using)f(the)h(syn)m -(tax)g('[pix)g(@\014lename.txt]'.)72 b(The)0 1054 y(mathematical)29 -b(expression)e(can)g(extend)g(o)m(v)m(er)i(m)m(ultiple)e(lines)g(of)h -(text)g(in)e(the)h(\014le.)40 b(An)m(y)27 b(lines)g(in)g(the)g -(external)0 1167 y(text)h(\014le)e(that)i(b)s(egin)e(with)g(2)h(slash)f -(c)m(haracters)i(\('//'\))h(will)e(b)s(e)f(ignored)h(and)f(ma)m(y)h(b)s -(e)f(used)g(to)h(add)f(commen)m(ts)0 1280 y(in)m(to)31 -b(the)g(\014le.)0 1440 y(By)c(default,)g(the)f(datat)m(yp)s(e)i(of)e -(the)g(resulting)h(image)g(will)g(b)s(e)e(the)i(same)f(as)h(the)f -(original)i(image,)g(but)e(one)g(ma)m(y)0 1553 y(force)31 -b(a)g(di\013eren)m(t)g(datat)m(yp)s(e)g(b)m(y)f(app)s(ended)f(a)h(co)s -(de)h(letter)h(to)f(the)f('pix')h(k)m(eyw)m(ord:)286 -1786 y Fe(pixb)95 b(-)g(8-bit)46 b(byte)190 b(image)46 -b(with)h(BITPIX)f(=)143 b(8)286 1898 y(pixi)95 b(-)47 -b(16-bit)f(integer)g(image)g(with)h(BITPIX)f(=)95 b(16)286 -2011 y(pixj)g(-)47 b(32-bit)f(integer)g(image)g(with)h(BITPIX)f(=)95 -b(32)286 2124 y(pixr)g(-)47 b(32-bit)f(float)142 b(image)46 -b(with)h(BITPIX)f(=)i(-32)286 2237 y(pixd)95 b(-)47 b(64-bit)f(float) -142 b(image)46 b(with)h(BITPIX)f(=)i(-64)0 2470 y Fj(Also)23 -b(b)m(y)f(default,)j(an)m(y)d(other)h(HDUs)g(in)f(the)g(input)g(\014le) -g(will)h(b)s(e)e(copied)i(without)g(c)m(hange)g(to)g(the)g(output)f -(virtual)0 2583 y(FITS)k(\014le,)h(but)f(one)g(ma)m(y)h(discard)f(the)h -(other)f(HDUs)h(b)m(y)f(adding)g(the)h(n)m(um)m(b)s(er)e('1')i(to)g -(the)g('pix')f(k)m(eyw)m(ord)h(\(and)0 2696 y(follo)m(wing)32 -b(an)m(y)f(optional)g(datat)m(yp)s(e)g(co)s(de)g(letter\).)42 -b(F)-8 b(or)32 b(example:)239 2928 y Fe(myfile.fits[3][pixr1)90 -b(sqrt\(X\)])0 3161 y Fj(will)23 b(create)i(a)e(virtual)g(FITS)f -(\014le)h(con)m(taining)h(only)f(a)g(primary)f(arra)m(y)i(image)g(with) -e(32-bit)i(\015oating)g(p)s(oin)m(t)f(pixels)0 3274 y(that)29 -b(ha)m(v)m(e)h(a)f(v)-5 b(alue)30 b(equal)f(to)g(the)g(square)g(ro)s -(ot)g(of)g(the)g(pixels)f(in)h(the)g(image)h(that)f(is)g(in)f(the)h -(3rd)f(extension)i(of)0 3387 y(the)h('m)m(y\014le.\014ts')g(\014le.)0 -3716 y Ff(10.10)136 b(Column)45 b(and)g(Keyw)l(ord)g(Filtering)h(Sp)t -(eci\014cation)0 3966 y Fj(The)27 b(optional)i(column/k)m(eyw)m(ord)g -(\014ltering)f(sp)s(eci\014er)f(is)h(used)f(to)i(mo)s(dify)e(the)h -(column)g(structure)f(and/or)h(the)0 4079 y(header)38 -b(k)m(eyw)m(ords)h(in)f(the)h(HDU)g(that)h(w)m(as)f(selected)h(with)e -(the)h(previous)f(HDU)h(lo)s(cation)h(sp)s(eci\014er.)65 -b(This)0 4192 y(\014ltering)42 b(sp)s(eci\014er)f(m)m(ust)h(b)s(e)f -(enclosed)i(in)e(square)h(brac)m(k)m(ets)h(and)e(can)h(b)s(e)f -(distinguished)g(from)h(a)g(general)0 4305 y(ro)m(w)d(\014lter)g(sp)s -(eci\014er)f(\(describ)s(ed)g(b)s(elo)m(w\))h(b)m(y)g(the)g(fact)h -(that)f(it)g(b)s(egins)f(with)h(the)g(string)g('col)h(')f(and)f(is)h -(not)0 4418 y(immediately)30 b(follo)m(w)m(ed)g(b)m(y)e(an)g(equals)h -(sign.)40 b(The)28 b(original)h(\014le)f(is)h(not)f(c)m(hanged)h(b)m(y) -f(this)h(\014ltering)f(op)s(eration,)0 4531 y(and)c(instead)h(the)g(mo) -s(di\014cations)g(are)g(made)g(on)f(a)h(cop)m(y)h(of)e(the)h(input)f -(FITS)g(\014le)h(\(usually)g(in)f(memory\),)i(whic)m(h)0 -4644 y(also)31 b(con)m(tains)g(a)g(cop)m(y)g(of)f(all)h(the)f(other)g -(HDUs)h(in)f(the)g(\014le.)41 b(\(If)30 b(a)g(`#')h(c)m(haracter)g(is)f -(app)s(ended)f(to)i(the)f(name)0 4757 y(or)d(n)m(um)m(b)s(er)e(of)i -(the)g(table)g(HDU)h(then)e(only)h(the)g(primary)f(arra)m(y)-8 -b(,)28 b(and)e(none)h(of)g(the)f(other)h(HDUs)h(in)e(the)h(input)0 -4869 y(\014le)i(will)f(b)s(e)g(copied)h(in)m(to)g(memory\).)41 -b(This)27 b(temp)s(orary)h(\014le)h(is)f(passed)g(to)h(the)g -(application)h(program)e(and)g(will)0 4982 y(p)s(ersist)e(only)i(un)m -(til)f(the)g(\014le)g(is)h(closed)f(or)g(un)m(til)h(the)f(program)g -(exits,)i(unless)d(the)h(out\014le)h(sp)s(eci\014er)e(\(see)i(ab)s(o)m -(v)m(e\))0 5095 y(is)i(also)i(supplied.)0 5255 y(The)f(column/k)m(eyw)m -(ord)h(\014lter)f(can)g(b)s(e)g(used)f(to)i(p)s(erform)e(the)i(follo)m -(wing)g(op)s(erations.)44 b(More)32 b(than)f(one)g(op)s(er-)0 -5368 y(ation)g(ma)m(y)g(b)s(e)f(sp)s(eci\014ed)g(b)m(y)g(separating)h -(them)f(with)h(commas)f(or)h(semi-colons.)136 5601 y -Fc(\017)46 b Fj(Cop)m(y)36 b(only)g(a)g(sp)s(eci\014ed)g(list)g(of)g -(columns)g(columns)f(to)i(the)f(\014ltered)g(input)f(\014le.)57 -b(The)36 b(list)g(of)g(column)227 5714 y(name)41 b(should)e(b)s(e)g -(separated)i(b)m(y)f(commas)h(or)f(semi-colons.)72 b(Wild)41 -b(card)f(c)m(haracters)h(ma)m(y)g(b)s(e)f(used)p eop -end -%%Page: 137 145 -TeXDict begin 137 144 bop 0 299 a Fh(10.10.)73 b(COLUMN)30 -b(AND)h(KEYW)m(ORD)g(FIL)-8 b(TERING)31 b(SPECIFICA)-8 -b(TION)984 b Fj(137)227 555 y(in)38 b(the)f(column)h(names)g(to)g(matc) -m(h)g(m)m(ultiple)h(columns.)62 b(If)37 b(the)h(expression)g(con)m -(tains)g(b)s(oth)f(a)h(list)h(of)227 668 y(columns)29 -b(to)h(b)s(e)f(included)g(and)g(columns)g(to)h(b)s(e)e(deleted,)j(then) -e(all)h(the)g(columns)f(in)g(the)h(original)g(table)227 -781 y(except)36 b(the)e(explicitly)i(deleted)f(columns)f(will)h(app)s -(ear)e(in)h(the)h(\014ltered)f(table)h(\(i.e.,)i(there)e(is)f(no)g -(need)227 894 y(to)d(explicitly)h(list)f(the)g(columns)f(to)h(b)s(e)f -(included)f(if)i(an)m(y)f(columns)h(are)f(b)s(eing)g(deleted\).)136 -1084 y Fc(\017)46 b Fj(Delete)32 b(a)d(column)g(or)g(k)m(eyw)m(ord)h(b) -m(y)f(listing)h(the)f(name)g(preceded)g(b)m(y)g(a)g(min)m(us)g(sign)g -(or)g(an)g(exclamation)227 1197 y(mark)c(\(!\),)h(e.g.,)i('-TIME')d -(will)g(delete)h(the)e(TIME)h(column)f(if)g(it)i(exists,)g(otherwise)f -(the)g(TIME)f(k)m(eyw)m(ord.)227 1310 y(An)35 b(error)f(is)h(returned)e -(if)i(neither)f(a)i(column)e(nor)g(k)m(eyw)m(ord)h(with)g(this)f(name)h -(exists.)54 b(Note)36 b(that)g(the)227 1422 y(exclamation)27 -b(p)s(oin)m(t,)g(')10 b(!',)27 b(is)e(a)g(sp)s(ecial)h(UNIX)f(c)m -(haracter,)j(so)d(if)g(it)h(is)f(used)f(on)h(the)g(command)g(line)g -(rather)227 1535 y(than)33 b(en)m(tered)h(at)g(a)g(task)g(prompt,)f(it) -h(m)m(ust)f(b)s(e)g(preceded)g(b)m(y)g(a)h(bac)m(kslash)g(to)g(force)g -(the)f(UNIX)h(shell)227 1648 y(to)d(ignore)g(it.)136 -1838 y Fc(\017)46 b Fj(Rename)29 b(an)g(existing)g(column)f(or)h(k)m -(eyw)m(ord)g(with)f(the)h(syn)m(tax)g('NewName)h(==)e(OldName'.)40 -b(An)28 b(error)227 1951 y(is)j(returned)e(if)h(neither)h(a)f(column)g -(nor)g(k)m(eyw)m(ord)h(with)f(this)h(name)f(exists.)136 -2141 y Fc(\017)46 b Fj(App)s(end)37 b(a)j(new)f(column)f(or)i(k)m(eyw)m -(ord)f(to)h(the)f(table.)68 b(T)-8 b(o)40 b(create)g(a)g(column,)h(giv) -m(e)g(the)e(new)g(name,)227 2254 y(optionally)c(follo)m(w)m(ed)f(b)m(y) -f(the)g(data)h(t)m(yp)s(e)f(in)f(paren)m(theses,)i(follo)m(w)m(ed)h(b)m -(y)e(a)g(single)h(equals)f(sign)g(and)f(an)227 2366 y(expression)j(to)h -(b)s(e)e(used)g(to)i(compute)f(the)g(v)-5 b(alue)35 b(\(e.g.,)j('new)m -(col\(1J\))f(=)e(0')g(will)h(create)g(a)f(new)g(32-bit)227 -2479 y(in)m(teger)i(column)d(called)j('new)m(col')f(\014lled)f(with)g -(zeros\).)55 b(The)35 b(data)g(t)m(yp)s(e)h(is)f(sp)s(eci\014ed)f -(using)g(the)i(same)227 2592 y(syn)m(tax)j(that)g(is)f(allo)m(w)m(ed)i -(for)e(the)g(v)-5 b(alue)39 b(of)f(the)g(FITS)f(TF)m(ORMn)h(k)m(eyw)m -(ord)h(\(e.g.,)j('I',)d('J',)f('E',)h('D',)227 2705 y(etc.)66 -b(for)38 b(binary)f(tables,)42 b(and)37 b('I8',)k(F12.3',)i('E20.12',)g -(etc.)65 b(for)38 b(ASCI)s(I)f(tables\).)66 b(If)37 b(the)i(data)g(t)m -(yp)s(e)227 2818 y(is)c(not)g(sp)s(eci\014ed)f(then)g(an)g(appropriate) -h(data)g(t)m(yp)s(e)g(will)g(b)s(e)f(c)m(hosen)h(dep)s(ending)e(on)h -(the)h(form)f(of)h(the)227 2931 y(expression)44 b(\(ma)m(y)g(b)s(e)f(a) -h(c)m(haracter)i(string,)h(logical,)j(bit,)d(long)d(in)m(teger,)49 -b(or)43 b(double)h(column\).)80 b(An)227 3044 y(appropriate)39 -b(v)m(ector)i(coun)m(t)e(\(in)g(the)g(case)h(of)f(binary)f(tables\))i -(will)f(also)h(b)s(e)e(added)g(if)h(not)g(explicitly)227 -3157 y(sp)s(eci\014ed.)227 3308 y(When)26 b(creating)h(a)f(new)f(k)m -(eyw)m(ord,)j(the)e(k)m(eyw)m(ord)g(name)g(m)m(ust)g(b)s(e)f(preceded)g -(b)m(y)h(a)g(p)s(ound)e(sign)h('#',)j(and)227 3421 y(the)h(expression)f -(m)m(ust)g(ev)-5 b(aluate)30 b(to)f(a)g(scalar)g(\(i.e.,)h(cannot)f(ha) -m(v)m(e)h(a)f(column)f(name)g(in)g(the)h(expression\).)227 -3534 y(The)j(commen)m(t)i(string)f(for)f(the)h(k)m(eyw)m(ord)h(ma)m(y)f -(b)s(e)f(sp)s(eci\014ed)g(in)g(paren)m(theses)h(immediately)h(follo)m -(wing)227 3647 y(the)27 b(k)m(eyw)m(ord)g(name)f(\(instead)h(of)g -(supplying)e(a)i(data)g(t)m(yp)s(e)g(as)f(in)g(the)h(case)g(of)g -(creating)h(a)f(new)f(column\).)227 3760 y(If)e(the)h(k)m(eyw)m(ord)g -(name)f(ends)g(with)g(a)h(p)s(ound)d(sign)i('#',)i(then)e(c\014tsio)i -(will)e(substitute)h(the)f(n)m(um)m(b)s(er)f(of)i(the)227 -3873 y(most)31 b(recen)m(tly)h(referenced)e(column)h(for)f(the)h(#)f(c) -m(haracter)i(.)41 b(This)29 b(is)i(esp)s(ecially)h(useful)d(when)h -(writing)227 3986 y(a)c(column-related)g(k)m(eyw)m(ord)g(lik)m(e)g -(TUNITn)e(for)h(a)h(newly)f(created)h(column,)g(as)g(sho)m(wn)e(in)h -(the)g(follo)m(wing)227 4099 y(examples.)227 4250 y(COMMENT)30 -b(and)g(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords)g(ma)m(y)h(also)h(b)s(e)e -(created)h(with)f(the)h(follo)m(wing)g(syn)m(tax:)370 -4503 y Fe(#COMMENT)46 b(=)h('This)g(is)g(a)g(comment)f(keyword')370 -4616 y(#HISTORY)g(=)h('This)g(is)g(a)g(history)f(keyword')227 -4869 y Fj(Note)d(that)f(the)f(equal)h(sign)f(and)f(the)i(quote)f(c)m -(haracters)i(will)f(b)s(e)e(remo)m(v)m(ed,)45 b(so)d(that)f(the)h -(resulting)227 4982 y(header)30 b(k)m(eyw)m(ords)h(in)f(these)h(cases)g -(will)g(lo)s(ok)g(lik)m(e)h(this:)370 5235 y Fe(COMMENT)46 -b(This)h(is)g(a)h(comment)d(keyword)370 5348 y(HISTORY)h(This)h(is)g(a) -h(history)d(keyword)227 5601 y Fj(These)29 b(t)m(w)m(o)h(sp)s(ecial)f -(k)m(eyw)m(ords)h(are)f(alw)m(a)m(ys)h(app)s(ended)d(to)j(the)f(end)f -(of)h(the)g(header)g(and)f(will)h(not)g(a\013ect)227 -5714 y(an)m(y)i(previously)f(existing)h(COMMENT)f(or)h(HISTOR)-8 -b(Y)30 b(k)m(eyw)m(ords.)p eop end -%%Page: 138 146 -TeXDict begin 138 145 bop 0 299 a Fj(138)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)136 -555 y Fc(\017)46 b Fj(Recompute)f(\(o)m(v)m(erwrite\))i(the)d(v)-5 -b(alues)44 b(in)g(an)g(existing)i(column)e(or)g(k)m(eyw)m(ord)g(b)m(y)g -(giving)i(the)e(name)227 668 y(follo)m(w)m(ed)32 b(b)m(y)f(an)f(equals) -h(sign)f(and)g(an)g(arithmetic)i(expression.)0 918 y(The)23 -b(expression)g(that)i(is)e(used)g(when)g(app)s(ending)f(or)h -(recomputing)h(columns)f(or)h(k)m(eyw)m(ords)g(can)g(b)s(e)f -(arbitrarily)0 1031 y(complex)36 b(and)g(ma)m(y)g(b)s(e)f(a)h(function) -g(of)g(other)g(header)g(k)m(eyw)m(ord)g(v)-5 b(alues)36 -b(and)f(other)h(columns)g(\(in)g(the)g(same)0 1144 y(ro)m(w\).)63 -b(The)37 b(full)g(syn)m(tax)i(and)e(a)m(v)-5 b(ailable)40 -b(functions)d(for)g(the)h(expression)f(are)h(describ)s(ed)f(b)s(elo)m -(w)h(in)f(the)h(ro)m(w)0 1257 y(\014lter)30 b(sp)s(eci\014cation)i -(section.)0 1417 y(If)27 b(the)h(expression)g(con)m(tains)g(b)s(oth)f -(a)h(list)h(of)f(columns)f(to)h(b)s(e)g(included)e(and)i(columns)f(to)h -(b)s(e)f(deleted,)j(then)d(all)0 1530 y(the)34 b(columns)g(in)g(the)g -(original)h(table)g(except)g(the)f(explicitly)i(deleted)f(columns)e -(will)i(app)s(ear)e(in)h(the)g(\014ltered)0 1643 y(table.)40 -b(If)26 b(no)g(columns)f(to)i(b)s(e)f(deleted)g(are)h(sp)s(eci\014ed,)f -(then)g(only)g(the)h(columns)e(that)i(are)f(explicitly)i(listed)f(will) -0 1756 y(b)s(e)k(included)g(in)g(the)h(\014ltered)f(output)h(table.)45 -b(T)-8 b(o)32 b(include)f(all)i(the)e(columns,)h(add)f(the)h('*')g -(wildcard)g(sp)s(eci\014er)0 1869 y(at)f(the)g(end)e(of)i(the)f(list,)i -(as)e(sho)m(wn)g(in)g(the)h(examples.)0 2029 y(F)-8 b(or)33 -b(complex)f(or)g(commonly)h(used)e(op)s(erations,)i(one)f(can)h(place)g -(the)f(op)s(erations)g(in)m(to)h(an)f(external)h(text)g(\014le)0 -2142 y(and)39 b(imp)s(ort)h(it)g(in)m(to)h(the)f(column)g(\014lter)g -(using)f(the)h(syn)m(tax)h('[col)g(@\014lename.txt]'.)71 -b(The)39 b(op)s(erations)i(can)0 2255 y(extend)35 b(o)m(v)m(er)h(m)m -(ultiple)g(lines)f(of)g(the)g(\014le,)h(but)e(m)m(ultiple)i(op)s -(erations)f(m)m(ust)f(still)i(b)s(e)e(separated)i(b)m(y)e(commas)0 -2368 y(or)e(semi-colons.)47 b(An)m(y)32 b(lines)h(in)f(the)g(external)h -(text)g(\014le)f(that)h(b)s(egin)e(with)h(2)h(slash)e(c)m(haracters)j -(\('//'\))g(will)f(b)s(e)0 2481 y(ignored)d(and)g(ma)m(y)h(b)s(e)f -(used)g(to)h(add)e(commen)m(ts)j(in)m(to)f(the)g(\014le.)0 -2641 y(Examples:)143 2891 y Fe([col)47 b(Time,)f(rate])667 -b(-)47 b(only)g(the)g(Time)g(and)g(rate)f(columns)g(will)1670 -3004 y(appear)h(in)g(the)g(filtered)e(input)i(file.)143 -3230 y([col)g(Time,)f(*raw])667 b(-)47 b(include)f(the)h(Time)g(column) -f(and)h(any)g(other)1670 3343 y(columns)f(whose)h(name)f(ends)h(with)g -('raw'.)143 3569 y([col)g(-TIME,)f(Good)h(==)g(STATUS])141 -b(-)47 b(deletes)f(the)h(TIME)g(column)f(and)1670 3681 -y(renames)g(the)h(status)f(column)g(to)i('Good')143 3907 -y([col)f(PI=PHA)f(*)h(1.1)g(+)h(0.2;)e(#TUNIT#\(column)e(units\))i(=)i -('counts';*])1575 4020 y(-)f(creates)f(new)h(PI)g(column)f(from)h(PHA)g -(values)1670 4133 y(and)g(also)g(writes)f(the)h(TUNITn)f(keyword)1670 -4246 y(for)h(the)g(new)g(column.)94 b(The)47 b(final)f('*')1670 -4359 y(expression)f(means)i(preserve)e(all)i(the)1670 -4472 y(columns)f(in)h(the)g(input)g(table)f(in)h(the)1670 -4585 y(virtual)f(output)g(table;)94 b(without)46 b(the)h('*')1670 -4698 y(the)g(output)f(table)h(would)f(only)h(contain)1670 -4811 y(the)g(single)f('PI')h(column.)143 5036 y([col)g(rate)f(=)i -(rate/exposure;)c(TUNIT#\(&\))h(=)j('counts/s';*])1575 -5149 y(-)f(recomputes)e(the)i(rate)g(column)f(by)h(dividing)1670 -5262 y(it)h(by)f(the)g(EXPOSURE)e(keyword)h(value.)g(This)1670 -5375 y(also)h(modifies)f(the)h(value)f(of)h(the)g(TUNITn)1670 -5488 y(keyword)f(for)h(this)g(column.)f(The)h(use)f(of)i(the)1670 -5601 y('&')f(character)f(for)h(the)f(keyword)g(comment)1670 -5714 y(string)h(means)f(preserve)f(the)i(existing)p eop -end -%%Page: 139 147 -TeXDict begin 139 146 bop 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 -b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(139)1670 -555 y Fe(comment)46 b(string)g(for)h(that)g(keyword.)e(The)1670 -668 y(final)i('*')g(preserves)e(all)i(the)g(columns)1670 -781 y(in)h(the)f(input)f(table)g(in)h(the)g(virtual)1670 -894 y(output)g(table.)0 1263 y Ff(10.11)136 b(Ro)l(w)46 -b(Filtering)g(Sp)t(eci\014cation)0 1520 y Fj(When)29 -b(en)m(tering)h(the)f(name)g(of)g(a)g(FITS)f(table)i(that)g(is)e(to)i -(b)s(e)e(op)s(ened)h(b)m(y)f(a)i(program,)f(an)g(optional)h(ro)m(w)f -(\014lter)0 1633 y(ma)m(y)i(b)s(e)g(sp)s(eci\014ed)f(to)h(select)h(a)g -(subset)e(of)h(the)g(ro)m(ws)f(in)h(the)g(table.)43 b(A)31 -b(temp)s(orary)f(new)g(FITS)g(\014le)h(is)g(created)0 -1746 y(on)40 b(the)f(\015y)g(whic)m(h)h(con)m(tains)h(only)e(those)h -(ro)m(ws)g(for)f(whic)m(h)h(the)g(ro)m(w)f(\014lter)h(expression)f(ev) --5 b(aluates)42 b(to)e(true.)0 1859 y(The)29 b(primary)f(arra)m(y)i -(and)f(an)m(y)g(other)h(extensions)g(in)f(the)g(input)g(\014le)g(are)h -(also)g(copied)g(to)g(the)g(temp)s(orary)f(\014le.)0 -1972 y(\(If)35 b(a)h(`#')f(c)m(haracter)i(is)e(app)s(ended)e(to)j(the)g -(name)f(or)g(n)m(um)m(b)s(er)f(of)h(the)g(table)h(HDU)g(then)f(only)g -(the)h(primary)0 2085 y(arra)m(y)-8 b(,)37 b(and)d(none)h(of)g(the)g -(other)g(HDUs)h(in)e(the)i(input)e(\014le)g(will)i(b)s(e)e(copied)h(in) -m(to)h(the)f(temp)s(orary)g(\014le\).)54 b(The)0 2198 -y(original)30 b(FITS)f(\014le)g(is)g(closed)h(and)e(the)i(new)e -(virtual)i(\014le)f(is)g(op)s(ened)f(b)m(y)h(the)h(application)g -(program.)40 b(The)29 b(ro)m(w)0 2310 y(\014lter)37 b(expression)g(is)h -(enclosed)g(in)f(square)g(brac)m(k)m(ets)i(follo)m(wing)g(the)e(\014le) -h(name)f(and)g(extension)h(name)f(\(e.g.,)0 2423 y('\014le.\014ts[ev)m -(en)m(ts][GRADE==50]')29 b(selects)d(only)f(those)h(ro)m(ws)f(where)f -(the)h(GRADE)h(column)f(v)-5 b(alue)25 b(equals)g(50\).)0 -2536 y(When)33 b(dealing)h(with)f(tables)g(where)g(eac)m(h)h(ro)m(w)f -(has)g(an)g(asso)s(ciated)i(time)f(and/or)f(2D)g(spatial)i(p)s -(osition,)f(the)0 2649 y(ro)m(w)e(\014lter)h(expression)e(can)i(also)g -(b)s(e)f(used)f(to)i(select)h(ro)m(ws)e(based)g(on)g(the)g(times)h(in)f -(a)g(Go)s(o)s(d)g(Time)g(In)m(terv)-5 b(als)0 2762 y(\(GTI\))31 -b(extension,)g(or)f(on)h(spatial)g(p)s(osition)g(as)f(giv)m(en)i(in)e -(a)g(SA)m(O-st)m(yle)i(region)f(\014le.)0 3088 y Fd(10.11.1)113 -b(General)38 b(Syn)m(tax)0 3314 y Fj(The)32 b(ro)m(w)h(\014ltering)g -(expression)g(can)g(b)s(e)f(an)h(arbitrarily)g(complex)g(series)g(of)g -(op)s(erations)g(p)s(erformed)f(on)g(con-)0 3427 y(stan)m(ts,)39 -b(k)m(eyw)m(ord)e(v)-5 b(alues,)38 b(and)e(column)g(data)i(tak)m(en)f -(from)f(the)h(sp)s(eci\014ed)e(FITS)h(T)-8 b(ABLE)37 -b(extension.)59 b(The)0 3540 y(expression)37 b(m)m(ust)h(ev)-5 -b(aluate)39 b(to)g(a)f(b)s(o)s(olean)g(v)-5 b(alue)38 -b(for)f(eac)m(h)i(ro)m(w)f(of)g(the)f(table,)k(where)c(a)h(v)-5 -b(alue)39 b(of)e(F)-10 b(ALSE)0 3653 y(means)30 b(that)h(the)g(ro)m(w)f -(will)h(b)s(e)f(excluded.)0 3813 y(F)-8 b(or)34 b(complex)g(or)g -(commonly)f(used)g(\014lters,)h(one)g(can)g(place)g(the)g(expression)f -(in)m(to)h(a)g(text)g(\014le)g(and)f(imp)s(ort)f(it)0 -3926 y(in)m(to)38 b(the)e(ro)m(w)h(\014lter)g(using)f(the)h(syn)m(tax)g -('[@\014lename.txt]'.)61 b(The)36 b(expression)h(can)f(b)s(e)g -(arbitrarily)h(complex)0 4039 y(and)27 b(extend)i(o)m(v)m(er)g(m)m -(ultiple)g(lines)f(of)g(the)h(\014le.)40 b(An)m(y)28 -b(lines)g(in)g(the)g(external)h(text)g(\014le)f(that)h(b)s(egin)f(with) -g(2)g(slash)0 4152 y(c)m(haracters)k(\('//'\))g(will)f(b)s(e)f(ignored) -g(and)g(ma)m(y)h(b)s(e)f(used)f(to)i(add)f(commen)m(ts)h(in)m(to)h(the) -e(\014le.)0 4312 y(Keyw)m(ord)37 b(and)f(column)g(data)i(are)f -(referenced)g(b)m(y)g(name.)60 b(An)m(y)37 b(string)f(of)h(c)m -(haracters)i(not)e(surrounded)d(b)m(y)0 4425 y(quotes)41 -b(\(ie,)j(a)d(constan)m(t)h(string\))f(or)f(follo)m(w)m(ed)i(b)m(y)f -(an)f(op)s(en)g(paren)m(theses)h(\(ie,)j(a)d(function)f(name\))h(will)g -(b)s(e)0 4538 y(initially)d(in)m(terpreted)e(as)h(a)g(column)f(name)g -(and)g(its)h(con)m(ten)m(ts)h(for)e(the)h(curren)m(t)f(ro)m(w)g -(inserted)g(in)m(to)i(the)e(ex-)0 4650 y(pression.)k(If)28 -b(no)h(suc)m(h)g(column)g(exists,)h(a)g(k)m(eyw)m(ord)f(of)h(that)f -(name)g(will)h(b)s(e)e(searc)m(hed)i(for)f(and)f(its)i(v)-5 -b(alue)29 b(used,)0 4763 y(if)36 b(found.)55 b(T)-8 b(o)36 -b(force)g(the)g(name)g(to)h(b)s(e)e(in)m(terpreted)h(as)g(a)g(k)m(eyw)m -(ord)g(\(in)g(case)g(there)g(is)g(b)s(oth)f(a)h(column)g(and)0 -4876 y(k)m(eyw)m(ord)41 b(with)e(the)i(same)f(name\),)j(precede)d(the)h -(k)m(eyw)m(ord)f(name)g(with)g(a)h(single)f(p)s(ound)e(sign,)43 -b('#',)g(as)d(in)0 4989 y('#NAXIS2'.)g(Due)27 b(to)g(the)f -(generalities)j(of)d(FITS)g(column)g(and)g(k)m(eyw)m(ord)h(names,)g(if) -f(the)h(column)f(or)g(k)m(eyw)m(ord)0 5102 y(name)33 -b(con)m(tains)h(a)f(space)h(or)f(a)g(c)m(haracter)h(whic)m(h)f(migh)m -(t)h(app)s(ear)e(as)h(an)g(arithmetic)h(term)f(then)g(enclose)h(the)0 -5215 y(name)c(in)g('$')i(c)m(haracters)g(as)e(in)g($MAX)i(PHA$)f(or)f -(#$MAX-PHA$.)43 b(Names)31 b(are)f(case)i(insensitiv)m(e.)0 -5375 y(T)-8 b(o)32 b(access)g(a)g(table)g(en)m(try)g(in)f(a)h(ro)m(w)f -(other)h(than)f(the)g(curren)m(t)g(one,)h(follo)m(w)h(the)e(column's)h -(name)f(with)g(a)h(ro)m(w)0 5488 y(o\013set)37 b(within)e(curly)g -(braces.)57 b(F)-8 b(or)36 b(example,)i('PHA)p Fc(f)p -Fj(-3)p Fc(g)p Fj(')g(will)e(ev)-5 b(aluate)38 b(to)e(the)g(v)-5 -b(alue)36 b(of)g(column)f(PHA,)i(3)0 5601 y(ro)m(ws)28 -b(ab)s(o)m(v)m(e)i(the)e(ro)m(w)h(curren)m(tly)f(b)s(eing)g(pro)s -(cessed.)40 b(One)28 b(cannot)h(sp)s(ecify)f(an)g(absolute)h(ro)m(w)f -(n)m(um)m(b)s(er,)g(only)h(a)0 5714 y(relativ)m(e)j(o\013set.)42 -b(Ro)m(ws)31 b(that)g(fall)g(outside)g(the)f(table)h(will)g(b)s(e)f -(treated)h(as)g(unde\014ned,)d(or)j(NULLs.)p eop end -%%Page: 140 148 -TeXDict begin 140 147 bop 0 299 a Fj(140)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fj(Bo)s(olean)32 b(op)s(erators)f(can)g(b)s(e)f(used)f(in)i(the)f -(expression)h(in)f(either)h(their)g(F)-8 b(ortran)31 -b(or)f(C)h(forms.)40 b(The)30 b(follo)m(wing)0 668 y(b)s(o)s(olean)g -(op)s(erators)h(are)g(a)m(v)-5 b(ailable:)191 918 y Fe("equal")428 -b(.eq.)46 b(.EQ.)h(==)95 b("not)46 b(equal")476 b(.ne.)94 -b(.NE.)h(!=)191 1031 y("less)46 b(than")238 b(.lt.)46 -b(.LT.)h(<)143 b("less)46 b(than/equal")188 b(.le.)94 -b(.LE.)h(<=)47 b(=<)191 1144 y("greater)e(than")95 b(.gt.)46 -b(.GT.)h(>)143 b("greater)45 b(than/equal")g(.ge.)94 -b(.GE.)h(>=)47 b(=>)191 1257 y("or")572 b(.or.)46 b(.OR.)h(||)95 -b("and")762 b(.and.)46 b(.AND.)h(&&)191 1370 y("negation")236 -b(.not.)46 b(.NOT.)h(!)95 b("approx.)45 b(equal\(1e-7\)")92 -b(~)0 1619 y Fj(Note)32 b(that)g(the)f(exclamation)i(p)s(oin)m(t,)e(') -10 b(!',)33 b(is)e(a)g(sp)s(ecial)g(UNIX)h(c)m(haracter,)h(so)e(if)g -(it)g(is)g(used)f(on)h(the)g(command)0 1732 y(line)i(rather)f(than)h -(en)m(tered)g(at)g(a)g(task)g(prompt,)g(it)g(m)m(ust)f(b)s(e)g -(preceded)h(b)m(y)f(a)h(bac)m(kslash)g(to)h(force)f(the)g(UNIX)0 -1845 y(shell)e(to)g(ignore)g(it.)0 2005 y(The)h(expression)g(ma)m(y)i -(also)f(include)f(arithmetic)i(op)s(erators)f(and)f(functions.)47 -b(T)-8 b(rigonometric)34 b(functions)e(use)0 2118 y(radians,)23 -b(not)g(degrees.)38 b(The)22 b(follo)m(wing)h(arithmetic)g(op)s -(erators)g(and)e(functions)g(can)i(b)s(e)e(used)g(in)h(the)g -(expression)0 2231 y(\(function)38 b(names)f(are)h(case)g(insensitiv)m -(e\).)64 b(A)37 b(n)m(ull)h(v)-5 b(alue)38 b(will)f(b)s(e)g(returned)g -(in)g(case)h(of)g(illegal)i(op)s(erations)0 2344 y(suc)m(h)30 -b(as)h(divide)f(b)m(y)g(zero,)i(sqrt\(negativ)m(e\))h(log\(negativ)m -(e\),)h(log10\(negativ)m(e\),)i(arccos\(.gt.)43 b(1\),)32 -b(arcsin\(.gt.)42 b(1\).)191 2594 y Fe("addition")474 -b(+)j("subtraction")d(-)191 2707 y("multiplication")186 -b(*)477 b("division")618 b(/)191 2820 y("negation")474 -b(-)j("exponentiation")330 b(**)143 b(^)191 2933 y("absolute)45 -b(value")189 b(abs\(x\))237 b("cosine")762 b(cos\(x\))191 -3046 y("sine")666 b(sin\(x\))237 b("tangent")714 b(tan\(x\))191 -3159 y("arc)47 b(cosine")379 b(arccos\(x\))93 b("arc)47 -b(sine")667 b(arcsin\(x\))191 3271 y("arc)47 b(tangent")331 -b(arctan\(x\))93 b("arc)47 b(tangent")523 b(arctan2\(y,x\))191 -3384 y("hyperbolic)45 b(cos")189 b(cosh\(x\))g("hyperbolic)45 -b(sin")381 b(sinh\(x\))191 3497 y("hyperbolic)45 b(tan")189 -b(tanh\(x\))g("round)47 b(to)g(nearest)f(int")94 b(round\(x\))191 -3610 y("round)46 b(down)h(to)g(int")f(floor\(x\))141 -b("round)47 b(up)g(to)g(int")333 b(ceil\(x\))191 3723 -y("exponential")d(exp\(x\))237 b("square)46 b(root")524 -b(sqrt\(x\))191 3836 y("natural)45 b(log")333 b(log\(x\))237 -b("common)46 b(log")572 b(log10\(x\))191 3949 y("modulus")522 -b(x)48 b(\045)f(y)286 b("random)46 b(#)i([0.0,1.0\)")188 -b(random\(\))191 4062 y("random)46 b(Gaussian")140 b(randomn\(\))93 -b("random)46 b(Poisson")380 b(randomp\(x\))191 4175 y("minimum")522 -b(min\(x,y\))141 b("maximum")714 b(max\(x,y\))191 4288 -y("cumulative)45 b(sum")189 b(accum\(x\))141 b("sequential)45 -b(difference")g(seqdiff\(x\))191 4401 y("if-then-else")282 -b(b?x:y)191 4513 y("angular)45 b(separation")93 b -(angsep\(ra1,dec1,ra2,de2\))41 b(\(all)47 b(in)g(degrees\))191 -4626 y("substring")283 b(strmid\(s,p,n\))44 b("string)i(search")428 -b(strstr\(s,r\))0 4876 y Fj(Three)30 b(di\013eren)m(t)h(random)f(n)m -(um)m(b)s(er)f(functions)h(are)h(pro)m(vided:)41 b(random\(\),)30 -b(with)h(no)f(argumen)m(ts,)h(pro)s(duces)f(a)0 4989 -y(uniform)g(random)f(deviate)k(b)s(et)m(w)m(een)e(0)g(and)f(1;)i -(randomn\(\),)e(also)i(with)e(no)h(argumen)m(ts,)g(pro)s(duces)f(a)h -(normal)0 5102 y(\(Gaussian\))k(random)e(deviate)j(with)e(zero)h(mean)f -(and)g(unit)f(standard)h(deviation;)j(randomp\(x\))d(pro)s(duces)f(a)0 -5215 y(P)m(oisson)27 b(random)f(deviate)h(whose)f(exp)s(ected)h(n)m(um) -m(b)s(er)e(of)h(coun)m(ts)h(is)g(X.)f(X)h(ma)m(y)g(b)s(e)e(an)m(y)i(p)s -(ositiv)m(e)g(real)g(n)m(um)m(b)s(er)0 5328 y(of)k(exp)s(ected)f(coun)m -(ts,)h(including)f(fractional)i(v)-5 b(alues,)31 b(but)f(the)g(return)g -(v)-5 b(alue)31 b(is)f(an)g(in)m(teger.)0 5488 y(When)d(the)g(random)g -(functions)f(are)i(used)e(in)h(a)h(v)m(ector)g(expression,)g(b)m(y)f -(default)h(the)f(same)h(random)e(v)-5 b(alue)28 b(will)0 -5601 y(b)s(e)g(used)f(when)h(ev)-5 b(aluating)30 b(eac)m(h)f(elemen)m -(t)h(of)f(the)g(v)m(ector.)41 b(If)28 b(di\013eren)m(t)h(random)f(n)m -(um)m(b)s(ers)f(are)i(desired,)f(then)0 5714 y(the)37 -b(name)g(of)g(a)g(v)m(ector)i(column)e(should)e(b)s(e)i(supplied)e(as)i -(the)h(single)f(argumen)m(t)g(to)h(the)f(random)f(function)p -eop end -%%Page: 141 149 -TeXDict begin 141 148 bop 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 -b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(141)0 -555 y(\(e.g.,)31 b("\015ux)c(+)h(0.1)h(*)g(random\(\015ux\)",)f(where)g -("\015ux')g(is)g(the)g(name)h(of)f(a)h(v)m(ector)h(column\).)40 -b(This)27 b(will)i(create)h(a)0 668 y(v)m(ector)d(of)f(random)f(n)m(um) -m(b)s(ers)f(that)i(will)g(b)s(e)f(used)f(in)i(sequence)g(when)e(ev)-5 -b(aluating)27 b(eac)m(h)g(elemen)m(t)g(of)f(the)f(v)m(ector)0 -781 y(expression.)0 941 y(An)31 b(alternate)i(syn)m(tax)f(for)f(the)g -(min)g(and)g(max)g(functions)g(has)g(only)g(a)h(single)g(argumen)m(t)g -(whic)m(h)f(should)f(b)s(e)h(a)0 1054 y(v)m(ector)g(v)-5 -b(alue)30 b(\(see)g(b)s(elo)m(w\).)41 b(The)29 b(result)g(will)h(b)s(e) -e(the)i(minim)m(um/maxim)m(um)f(elemen)m(t)h(con)m(tained)h(within)e -(the)0 1167 y(v)m(ector.)0 1327 y(The)35 b(accum\(x\))i(function)f -(forms)f(the)h(cum)m(ulativ)m(e)i(sum)d(of)h(x,)h(elemen)m(t)h(b)m(y)e -(elemen)m(t.)58 b(V)-8 b(ector)38 b(columns)e(are)0 1440 -y(supp)s(orted)h(simply)h(b)m(y)g(p)s(erforming)f(the)i(summation)g -(pro)s(cess)f(through)f(all)j(the)f(v)-5 b(alues.)65 -b(Null)39 b(v)-5 b(alues)39 b(are)0 1553 y(treated)30 -b(as)f(0.)41 b(The)29 b(seqdi\013\(x\))h(function)e(forms)h(the)g -(sequen)m(tial)i(di\013erence)e(of)h(x,)f(elemen)m(t)i(b)m(y)e(elemen)m -(t.)41 b(The)0 1666 y(\014rst)36 b(v)-5 b(alue)38 b(of)f(seqdi\013)g -(is)g(the)g(\014rst)g(v)-5 b(alue)37 b(of)g(x.)61 b(A)37 -b(single)h(n)m(ull)f(v)-5 b(alue)38 b(in)e(x)h(causes)h(a)f(pair)g(of)g -(n)m(ulls)g(in)g(the)0 1779 y(output.)55 b(The)35 b(seqdi\013)g(and)g -(accum)g(functions)g(are)h(functional)f(in)m(v)m(erses,)j(i.e.,)g -(seqdi\013\(accum\(x\)\))f(==)e(x)g(as)0 1892 y(long)c(as)g(no)f(n)m -(ull)g(v)-5 b(alues)31 b(are)g(presen)m(t.)0 2052 y(In)36 -b(the)h(if-then-else)i(expression,)f("b?x:y",)i(b)c(is)h(an)g(explicit) -h(b)s(o)s(olean)f(v)-5 b(alue)37 b(or)g(expression.)61 -b(There)36 b(is)h(no)0 2165 y(automatic)d(t)m(yp)s(e)e(con)m(v)m -(ersion)h(from)e(n)m(umeric)h(to)g(b)s(o)s(olean)g(v)-5 -b(alues,)33 b(so)f(one)g(needs)f(to)i(use)e("iV)-8 b(al!=0")35 -b(instead)0 2278 y(of)30 b(merely)g("iV)-8 b(al")32 b(as)e(the)g(b)s(o) -s(olean)g(argumen)m(t.)41 b(x)30 b(and)f(y)h(can)g(b)s(e)f(an)m(y)h -(scalar)h(data)g(t)m(yp)s(e)f(\(including)f(string\).)0 -2438 y(The)22 b(angsep)g(function)f(computes)i(the)f(angular)g -(separation)h(in)e(degrees)i(b)s(et)m(w)m(een)g(2)f(celestial)j(p)s -(ositions,)e(where)0 2551 y(the)36 b(\014rst)f(2)h(parameters)g(giv)m -(e)h(the)f(RA-lik)m(e)i(and)d(Dec-lik)m(e)j(co)s(ordinates)f(\(in)f -(decimal)g(degrees\))h(of)f(the)g(\014rst)0 2664 y(p)s(osition,)31 -b(and)e(the)i(3rd)f(and)g(4th)g(parameters)h(giv)m(e)h(the)e(co)s -(ordinates)i(of)e(the)h(second)f(p)s(osition.)0 2824 -y(The)38 b(substring)f(function)i(strmid\(S,P)-8 b(,N\))39 -b(extracts)g(a)g(substring)f(from)g(S,)g(starting)h(at)g(string)g(p)s -(osition)f(P)-8 b(,)0 2937 y(with)33 b(a)h(substring)f(length)h(N.)g -(The)f(\014rst)g(c)m(haracter)j(p)s(osition)d(in)h(S)f(is)h(lab)s(eled) -g(as)g(1.)51 b(If)33 b(P)g(is)h(0,)h(or)f(refers)f(to)0 -3050 y(a)i(p)s(osition)g(b)s(ey)m(ond)f(the)h(end)e(of)i(S,)g(then)f -(the)h(extracted)h(substring)d(will)i(b)s(e)f(NULL.)h(S,)f(P)-8 -b(,)36 b(and)e(N)g(ma)m(y)i(b)s(e)0 3163 y(functions)30 -b(of)g(other)h(columns.)0 3323 y(The)39 b(string)h(searc)m(h)h -(function)e(strstr\(S,R\))h(searc)m(hes)h(for)f(the)g(\014rst)f(o)s -(ccurrence)h(of)g(the)g(substring)f(R)h(in)f(S.)0 3436 -y(The)c(result)h(is)f(an)h(in)m(teger,)i(indicating)f(the)e(c)m -(haracter)i(p)s(osition)f(of)g(the)g(\014rst)e(matc)m(h)j(\(where)e(1)h -(is)g(the)g(\014rst)0 3548 y(c)m(haracter)c(p)s(osition)e(of)h(S\).)f -(If)g(no)h(matc)m(h)g(is)f(found,)g(then)g(strstr\(\))g(returns)f(a)i -(NULL)f(v)-5 b(alue.)0 3709 y(The)38 b(follo)m(wing)i(t)m(yp)s(e)f -(casting)h(op)s(erators)f(are)g(a)m(v)-5 b(ailable,)44 -b(where)38 b(the)h(inclosing)h(paren)m(theses)f(are)g(required)0 -3822 y(and)30 b(tak)m(en)h(from)f(the)h(C)f(language)h(usage.)42 -b(Also,)31 b(the)g(in)m(teger)g(to)h(real)f(casts)g(v)-5 -b(alues)30 b(to)i(double)e(precision:)764 4085 y Fe("real)46 -b(to)h(integer")189 b(\(int\))46 b(x)239 b(\(INT\))46 -b(x)764 4198 y("integer)f(to)i(real")190 b(\(float\))46 -b(i)143 b(\(FLOAT\))45 b(i)0 4462 y Fj(In)30 b(addition,)g(sev)m(eral)i -(constan)m(ts)g(are)f(built)f(in)g(for)g(use)g(in)g(n)m(umerical)h -(expressions:)382 4725 y Fe(#pi)667 b(3.1415...)284 b(#e)620 -b(2.7182...)382 4838 y(#deg)f(#pi/180)380 b(#row)524 -b(current)46 b(row)h(number)382 4951 y(#null)428 b(undefined)45 -b(value)142 b(#snull)428 b(undefined)45 b(string)0 5215 -y Fj(A)40 b(string)f(constan)m(t)i(m)m(ust)e(b)s(e)g(enclosed)h(in)g -(quotes)g(as)f(in)h('Crab'.)67 b(The)39 b("n)m(ull")i(constan)m(ts)f -(are)g(useful)f(for)0 5328 y(conditionally)g(setting)g(table)g(v)-5 -b(alues)38 b(to)g(a)g(NULL,)g(or)g(unde\014ned,)f(v)-5 -b(alue)39 b(\(eg.,)i("col1==-99)f(?)62 b(#NULL)38 b(:)0 -5441 y(col1"\).)0 5601 y(There)27 b(is)g(also)i(a)e(function)g(for)h -(testing)g(if)f(t)m(w)m(o)i(v)-5 b(alues)28 b(are)g(close)g(to)h(eac)m -(h)f(other,)h(i.e.,)g(if)e(they)h(are)g("near")g(eac)m(h)0 -5714 y(other)c(to)h(within)e(a)h(user)g(sp)s(eci\014ed)f(tolerance.)40 -b(The)24 b(argumen)m(ts,)h(v)-5 b(alue)p 2502 5714 28 -4 v 34 w(1)24 b(and)f(v)-5 b(alue)p 2979 5714 V 33 w(2)25 -b(can)f(b)s(e)f(in)m(teger)i(or)f(real)p eop end -%%Page: 142 150 -TeXDict begin 142 149 bop 0 299 a Fj(142)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fj(and)32 b(represen)m(t)h(the)g(t)m(w)m(o)h(v)-5 -b(alues)33 b(who's)f(pro)m(ximit)m(y)i(is)f(b)s(eing)f(tested)h(to)h(b) -s(e)e(within)g(the)h(sp)s(eci\014ed)f(tolerance,)0 668 -y(also)f(an)g(in)m(teger)g(or)g(real:)955 950 y Fe(near\(value_1,)44 -b(value_2,)h(tolerance\))0 1232 y Fj(When)24 b(a)i(NULL,)e(or)h -(unde\014ned,)f(v)-5 b(alue)25 b(is)g(encoun)m(tered)g(in)g(the)f(FITS) -g(table,)j(the)e(expression)g(will)g(ev)-5 b(aluate)26 -b(to)0 1345 y(NULL)31 b(unless)f(the)h(unde\014ned)e(v)-5 -b(alue)31 b(is)g(not)g(actually)h(required)e(for)h(ev)-5 -b(aluation,)33 b(e.g.)43 b("TR)m(UE)31 b(.or.)43 b(NULL")0 -1458 y(ev)-5 b(aluates)32 b(to)f(TR)m(UE.)g(The)f(follo)m(wing)h(t)m(w) -m(o)h(functions)e(allo)m(w)i(some)f(NULL)f(detection)i(and)e(handling:) -430 1740 y Fe("a)47 b(null)f(value?")667 b(ISNULL\(x\))430 -1853 y("define)45 b(a)j(value)e(for)h(null")190 b(DEFNULL\(x,y\))0 -2135 y Fj(The)36 b(former)h(returns)e(a)i(b)s(o)s(olean)g(v)-5 -b(alue)37 b(of)g(TR)m(UE)g(if)g(the)g(argumen)m(t)g(x)g(is)g(NULL.)g -(The)f(later)i("de\014nes")f(a)0 2248 y(v)-5 b(alue)35 -b(to)g(b)s(e)e(substituted)h(for)g(NULL)g(v)-5 b(alues;)37 -b(it)e(returns)e(the)h(v)-5 b(alue)35 b(of)f(x)g(if)g(x)h(is)f(not)g -(NULL,)h(otherwise)f(it)0 2361 y(returns)29 b(the)i(v)-5 -b(alue)31 b(of)f(y)-8 b(.)0 2678 y Fd(10.11.2)113 b(Bit)36 -b(Masks)0 2902 y Fj(Bit)g(masks)f(can)h(b)s(e)f(used)f(to)i(select)h -(out)e(ro)m(ws)h(from)e(bit)i(columns)f(\(TF)m(ORMn)g(=)g(#X\))h(in)f -(FITS)f(\014les.)55 b(T)-8 b(o)0 3015 y(represen)m(t)30 -b(the)h(mask,)g(binary)-8 b(,)30 b(o)s(ctal,)i(and)e(hex)g(formats)g -(are)h(allo)m(w)m(ed:)811 3297 y Fe(binary:)142 b -(b0110xx1010000101xxxx00)o(01)811 3410 y(octal:)190 b(o720x1)46 -b(->)h(\(b111010000xxx001\))811 3522 y(hex:)286 b(h0FxD)94 -b(->)47 b(\(b00001111xxxx1101\))0 3804 y Fj(In)22 b(all)i(the)f -(represen)m(tations,)j(an)c(x)h(or)g(X)g(is)g(allo)m(w)m(ed)i(in)d(the) -h(mask)g(as)g(a)h(wild)e(card.)38 b(Note)25 b(that)e(the)g(x)g -(represen)m(ts)0 3917 y(a)k(di\013eren)m(t)h(n)m(um)m(b)s(er)e(of)h -(wild)f(card)h(bits)g(in)g(eac)m(h)h(represen)m(tation.)41 -b(All)27 b(represen)m(tations)h(are)g(case)g(insensitiv)m(e.)0 -4077 y(T)-8 b(o)28 b(construct)g(the)g(b)s(o)s(olean)f(expression)h -(using)f(the)h(mask)f(as)h(the)g(b)s(o)s(olean)f(equal)h(op)s(erator)g -(describ)s(ed)f(ab)s(o)m(v)m(e)0 4190 y(on)34 b(a)h(bit)g(table)h -(column.)53 b(F)-8 b(or)35 b(example,)i(if)d(y)m(ou)h(had)f(a)h(7)g -(bit)g(column)f(named)g(\015ags)h(in)f(a)h(FITS)f(table)i(and)0 -4303 y(w)m(an)m(ted)31 b(all)g(ro)m(ws)g(ha)m(ving)g(the)f(bit)h -(pattern)f(0010011,)k(the)c(selection)j(expression)d(w)m(ould)g(b)s(e:) -1336 4585 y Fe(flags)47 b(==)g(b0010011)191 4698 y(or)1336 -4811 y(flags)g(.eq.)f(b10011)0 5093 y Fj(It)35 b(is)g(also)h(p)s -(ossible)e(to)i(test)g(if)f(a)g(range)g(of)g(bits)g(is)g(less)g(than,)h -(less)f(than)g(equal,)i(greater)f(than)e(and)h(greater)0 -5206 y(than)30 b(equal)h(to)g(a)g(particular)g(b)s(o)s(olean)f(v)-5 -b(alue:)1336 5488 y Fe(flags)47 b(<=)g(bxxx010xx)1336 -5601 y(flags)g(.gt.)f(bxxx100xx)1336 5714 y(flags)h(.le.)f(b1xxxxxxx)p -eop end -%%Page: 143 151 -TeXDict begin 143 150 bop 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 -b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(143)0 -555 y(Notice)32 b(the)f(use)f(of)h(the)f(x)g(bit)h(v)-5 -b(alue)31 b(to)g(limit)g(the)f(range)h(of)g(bits)f(b)s(eing)g -(compared.)0 715 y(It)i(is)h(not)f(necessary)h(to)g(sp)s(ecify)f(the)h -(leading)g(\(most)g(signi\014can)m(t\))h(zero)f(\(0\))g(bits)f(in)g -(the)h(mask,)g(as)g(sho)m(wn)e(in)0 828 y(the)g(second)f(expression)g -(ab)s(o)m(v)m(e.)0 988 y(Bit)44 b(wise)f(AND,)h(OR)e(and)g(NOT)h(op)s -(erations)g(are)g(also)h(p)s(ossible)e(on)h(t)m(w)m(o)h(or)f(more)g -(bit)g(\014elds)f(using)h(the)0 1101 y('&'\(AND\),)35 -b(')p Fc(j)p Fj('\(OR\),)g(and)e(the)h(')10 b(!'\(NOT\))34 -b(op)s(erators.)51 b(All)34 b(of)f(these)h(op)s(erators)g(result)f(in)h -(a)g(bit)f(\014eld)g(whic)m(h)0 1214 y(can)e(then)f(b)s(e)f(used)h -(with)g(the)h(equal)g(op)s(erator.)41 b(F)-8 b(or)31 -b(example:)1241 1484 y Fe(\(!flags\))45 b(==)j(b1101100)1241 -1597 y(\(flags)e(&)h(b1000001\))f(==)h(bx000001)0 1867 -y Fj(Bit)35 b(\014elds)f(can)g(b)s(e)f(app)s(ended)g(as)h(w)m(ell)h -(using)f(the)g('+')g(op)s(erator.)53 b(Strings)33 b(can)i(b)s(e)e -(concatenated)j(this)e(w)m(a)m(y)-8 b(,)0 1980 y(to)s(o.)0 -2283 y Fd(10.11.3)113 b(V)-9 b(ector)36 b(Columns)0 2504 -y Fj(V)-8 b(ector)37 b(columns)e(can)h(also)g(b)s(e)f(used)f(in)h -(building)g(the)g(expression.)56 b(No)36 b(sp)s(ecial)g(syn)m(tax)f(is) -h(required)e(if)i(one)0 2617 y(w)m(an)m(ts)46 b(to)f(op)s(erate)h(on)f -(all)h(elemen)m(ts)g(of)f(the)h(v)m(ector.)86 b(Simply)44 -b(use)h(the)g(column)g(name)g(as)g(for)g(a)g(scalar)0 -2730 y(column.)d(V)-8 b(ector)32 b(columns)f(can)g(b)s(e)f(freely)h(in) -m(termixed)h(with)e(scalar)i(columns)e(or)h(constan)m(ts)h(in)f -(virtually)g(all)0 2843 y(expressions.)40 b(The)29 b(result)g(will)g(b) -s(e)g(of)g(the)g(same)h(dimension)e(as)i(the)f(v)m(ector.)42 -b(Tw)m(o)29 b(v)m(ectors)i(in)e(an)g(expression,)0 2956 -y(though,)h(need)g(to)i(ha)m(v)m(e)f(the)g(same)g(n)m(um)m(b)s(er)e(of) -h(elemen)m(ts)i(and)e(ha)m(v)m(e)h(the)g(same)g(dimensions.)0 -3116 y(Arithmetic)24 b(and)e(logical)k(op)s(erations)d(are)h(all)g(p)s -(erformed)d(on)i(an)g(elemen)m(t)h(b)m(y)f(elemen)m(t)i(basis.)38 -b(Comparing)23 b(t)m(w)m(o)0 3229 y(v)m(ector)32 b(columns,)e(eg)h -("COL1)f(==)g(COL2",)g(th)m(us)g(results)g(in)g(another)g(v)m(ector)i -(of)e(b)s(o)s(olean)h(v)-5 b(alues)30 b(indicating)0 -3342 y(whic)m(h)g(elemen)m(ts)i(of)e(the)h(t)m(w)m(o)h(v)m(ectors)f -(are)g(equal.)0 3502 y(Eigh)m(t)g(functions)f(are)h(a)m(v)-5 -b(ailable)33 b(that)e(op)s(erate)g(on)f(a)h(v)m(ector)h(and)d(return)h -(a)g(scalar)i(result:)191 3772 y Fe("minimum")284 b(MIN\(V\))475 -b("maximum")714 b(MAX\(V\))191 3885 y("average")284 b(AVERAGE\(V\))f -("median")762 b(MEDIAN\(V\))191 3998 y("summation")188 -b(SUM\(V\))475 b("standard)46 b(deviation")188 b(STDDEV\(V\))191 -4110 y("#)47 b(of)g(values")94 b(NELEM\(V\))379 b("#)48 -b(of)f(non-null)e(values")94 b(NVALID\(V\))0 4380 y Fj(where)40 -b(V)h(represen)m(ts)g(the)g(name)g(of)h(a)f(v)m(ector)h(column)f(or)g -(a)h(man)m(ually)f(constructed)g(v)m(ector)i(using)d(curly)0 -4493 y(brac)m(k)m(ets)27 b(as)f(describ)s(ed)e(b)s(elo)m(w.)39 -b(The)25 b(\014rst)g(6)h(of)g(these)g(functions)f(ignore)h(an)m(y)g(n)m -(ull)f(v)-5 b(alues)26 b(in)f(the)h(v)m(ector)h(when)0 -4606 y(computing)k(the)f(result.)41 b(The)30 b(STDDEV\(\))h(function)g -(computes)f(the)h(sample)g(standard)e(deviation,)j(i.e.)42 -b(it)31 b(is)0 4719 y(prop)s(ortional)f(to)h(1/SQR)-8 -b(T\(N-1\))32 b(instead)f(of)g(1/SQR)-8 b(T\(N\),)31 -b(where)f(N)h(is)f(NV)-10 b(ALID\(V\).)0 4879 y(The)31 -b(SUM)h(function)f(literally)j(sums)d(all)h(the)g(elemen)m(ts)h(in)f -(x,)g(returning)f(a)h(scalar)h(v)-5 b(alue.)45 b(If)31 -b(V)h(is)g(a)g(b)s(o)s(olean)0 4992 y(v)m(ector,)40 b(SUM)c(returns)f -(the)h(n)m(um)m(b)s(er)f(of)i(TR)m(UE)f(elemen)m(ts.)60 -b(The)36 b(NELEM)g(function)g(returns)f(the)h(n)m(um)m(b)s(er)0 -5105 y(of)h(elemen)m(ts)g(in)g(v)m(ector)h(V)e(whereas)h(NV)-10 -b(ALID)36 b(return)g(the)h(n)m(um)m(b)s(er)e(of)h(non-n)m(ull)g(elemen) -m(ts)i(in)e(the)h(v)m(ector.)0 5218 y(\(NELEM)28 b(also)h(op)s(erates)f -(on)g(bit)f(and)g(string)h(columns,)g(returning)f(their)h(column)f -(widths.\))40 b(As)27 b(an)h(example,)0 5331 y(to)42 -b(test)g(whether)f(all)h(elemen)m(ts)h(of)f(t)m(w)m(o)g(v)m(ectors)h -(satisfy)f(a)g(giv)m(en)g(logical)i(comparison,)g(one)e(can)g(use)f -(the)0 5444 y(expression)668 5714 y Fe(SUM\()47 b(COL1)f(>)i(COL2)f(\)) -g(==)g(NELEM\()f(COL1)h(\))p eop end -%%Page: 144 152 -TeXDict begin 144 151 bop 0 299 a Fj(144)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fj(whic)m(h)32 b(will)g(return)f(TR)m(UE)h(if)g(all)h(elemen)m -(ts)g(of)f(COL1)g(are)g(greater)h(than)f(their)g(corresp)s(onding)f -(elemen)m(ts)i(in)0 668 y(COL2.)0 828 y(T)-8 b(o)32 b(sp)s(ecify)f(a)i -(single)f(elemen)m(t)h(of)f(a)g(v)m(ector,)i(giv)m(e)f(the)f(column)f -(name)h(follo)m(w)m(ed)h(b)m(y)f(a)g(comma-separated)h(list)0 -941 y(of)c(co)s(ordinates)g(enclosed)h(in)e(square)h(brac)m(k)m(ets.)41 -b(F)-8 b(or)30 b(example,)g(if)e(a)h(v)m(ector)i(column)d(named)h(PHAS) -f(exists)h(in)0 1054 y(the)e(table)g(as)g(a)g(one)g(dimensional,)h(256) -g(comp)s(onen)m(t)f(list)g(of)g(n)m(um)m(b)s(ers)e(from)h(whic)m(h)h(y) -m(ou)g(w)m(an)m(ted)g(to)g(select)i(the)0 1167 y(57th)j(comp)s(onen)m -(t)g(for)f(use)g(in)g(the)h(expression,)f(then)h(PHAS[57])g(w)m(ould)f -(do)h(the)f(tric)m(k.)45 b(Higher)32 b(dimensional)0 -1280 y(arra)m(ys)41 b(of)h(data)f(ma)m(y)h(app)s(ear)f(in)f(a)i -(column.)73 b(But)41 b(in)g(order)f(to)i(in)m(terpret)f(them,)j(the)e -(TDIMn)e(k)m(eyw)m(ord)0 1393 y(m)m(ust)34 b(app)s(ear)g(in)g(the)g -(header.)52 b(Assuming)34 b(that)h(a)f(\(4,4,4,4\))k(arra)m(y)c(is)h -(pac)m(k)m(ed)g(in)m(to)g(eac)m(h)h(ro)m(w)e(of)g(a)h(column)0 -1506 y(named)26 b(ARRA)-8 b(Y4D,)28 b(the)f(\(1,2,3,4\))i(comp)s(onen)m -(t)e(elemen)m(t)g(of)g(eac)m(h)g(ro)m(w)g(is)f(accessed)i(b)m(y)e(ARRA) --8 b(Y4D[1,2,3,4].)0 1619 y(Arra)m(ys)33 b(up)e(to)j(dimension)e(5)h -(are)f(curren)m(tly)h(supp)s(orted.)46 b(Eac)m(h)33 b(v)m(ector)h -(index)e(can)h(itself)g(b)s(e)f(an)h(expression,)0 1732 -y(although)39 b(it)g(m)m(ust)g(ev)-5 b(aluate)40 b(to)f(an)g(in)m -(teger)h(v)-5 b(alue)39 b(within)f(the)h(b)s(ounds)d(of)j(the)g(v)m -(ector.)67 b(V)-8 b(ector)40 b(columns)0 1844 y(whic)m(h)31 -b(con)m(tain)h(spaces)g(or)f(arithmetic)h(op)s(erators)g(m)m(ust)f(ha)m -(v)m(e)h(their)f(names)g(enclosed)h(in)f("$")h(c)m(haracters)h(as)0 -1957 y(with)d($ARRA)-8 b(Y-4D$[1,2,3,4].)0 2118 y(A)45 -b(more)f(C-lik)m(e)i(syn)m(tax)g(for)e(sp)s(ecifying)g(v)m(ector)j -(indices)d(is)h(also)h(a)m(v)-5 b(ailable.)85 b(The)45 -b(elemen)m(t)h(used)d(in)i(the)0 2230 y(preceding)28 -b(example)h(alternativ)m(ely)i(could)d(b)s(e)g(sp)s(eci\014ed)g(with)f -(the)i(syn)m(tax)g(ARRA)-8 b(Y4D[4][3][2][1].)45 b(Note)30 -b(the)0 2343 y(rev)m(erse)40 b(order)f(of)h(indices)f(\(as)h(in)f(C\),) -h(as)f(w)m(ell)i(as)e(the)h(fact)g(that)g(the)g(v)-5 -b(alues)40 b(are)f(still)i(ones-based)e(\(as)h(in)0 2456 -y(F)-8 b(ortran)39 b({)g(adopted)g(to)g(a)m(v)m(oid)h(am)m(biguit)m(y)g -(for)f(1D)g(v)m(ectors\).)67 b(With)39 b(this)g(syn)m(tax,)i(one)e(do)s -(es)f(not)h(need)f(to)0 2569 y(sp)s(ecify)30 b(all)h(of)g(the)f -(indices.)41 b(T)-8 b(o)31 b(extract)h(a)f(3D)g(slice)g(of)g(this)f(4D) -h(arra)m(y)-8 b(,)32 b(use)e(ARRA)-8 b(Y4D[4].)0 2729 -y(V)g(ariable-length)33 b(v)m(ector)f(columns)e(are)g(not)h(supp)s -(orted.)0 2889 y(V)-8 b(ectors)24 b(can)e(b)s(e)f(man)m(ually)h -(constructed)h(within)e(the)h(expression)g(using)f(a)h(comma-separated) -i(list)f(of)f(elemen)m(ts)0 3002 y(surrounded)35 b(b)m(y)j(curly)g -(braces)h(\(')p Fc(fg)p Fj('\).)66 b(F)-8 b(or)38 b(example,)j(')p -Fc(f)p Fj(1,3,6,1)p Fc(g)p Fj(')h(is)d(a)f(4-elemen)m(t)i(v)m(ector)g -(con)m(taining)g(the)0 3115 y(v)-5 b(alues)26 b(1,)h(3,)g(6,)g(and)e -(1.)40 b(The)25 b(v)m(ector)i(can)f(con)m(tain)h(only)f(b)s(o)s(olean,) -g(in)m(teger,)j(and)c(real)h(v)-5 b(alues)26 b(\(or)g(expressions\).)0 -3228 y(The)c(elemen)m(ts)i(will)f(b)s(e)f(promoted)h(to)g(the)g -(highest)g(data)g(t)m(yp)s(e)g(presen)m(t.)38 b(An)m(y)22 -b(elemen)m(ts)i(whic)m(h)f(are)g(themselv)m(es)0 3341 -y(v)m(ectors,)40 b(will)d(b)s(e)f(expanded)g(out)h(with)g(eac)m(h)g(of) -g(its)g(elemen)m(ts)i(b)s(ecoming)d(an)h(elemen)m(t)h(in)f(the)g -(constructed)0 3454 y(v)m(ector.)0 3744 y Fd(10.11.4)113 -b(Go)s(o)s(d)38 b(Time)g(In)m(terv)-6 b(al)37 b(Filtering)0 -3963 y Fj(A)44 b(common)g(\014ltering)h(metho)s(d)e(in)m(v)m(olv)m(es)j -(selecting)g(ro)m(ws)e(whic)m(h)f(ha)m(v)m(e)j(a)e(time)h(v)-5 -b(alue)44 b(whic)m(h)g(lies)g(within)0 4076 y(what)37 -b(is)g(called)i(a)f(Go)s(o)s(d)f(Time)g(In)m(terv)-5 -b(al)38 b(or)f(GTI.)g(The)g(time)h(in)m(terv)-5 b(als)38 -b(are)g(de\014ned)e(in)h(a)g(separate)i(FITS)0 4189 y(table)i -(extension)g(whic)m(h)e(con)m(tains)i(2)g(columns)f(giving)g(the)h -(start)f(and)g(stop)g(time)g(of)g(eac)m(h)i(go)s(o)s(d)e(in)m(terv)-5 -b(al.)0 4301 y(The)34 b(\014ltering)h(op)s(eration)h(accepts)g(only)e -(those)i(ro)m(ws)e(of)h(the)g(input)f(table)i(whic)m(h)e(ha)m(v)m(e)i -(an)f(asso)s(ciated)h(time)0 4414 y(whic)m(h)f(falls)i(within)e(one)h -(of)g(the)g(time)g(in)m(terv)-5 b(als)37 b(de\014ned)e(in)g(the)h(GTI)g -(extension.)57 b(A)36 b(high)g(lev)m(el)h(function,)0 -4527 y(gti\014lter\(a,b,c,d\),)44 b(is)c(a)m(v)-5 b(ailable)42 -b(whic)m(h)d(ev)-5 b(aluates)41 b(eac)m(h)g(ro)m(w)e(of)h(the)f(input)g -(table)h(and)f(returns)f(TR)m(UE)i(or)0 4640 y(F)-10 -b(ALSE)30 b(dep)s(ending)f(whether)h(the)g(ro)m(w)h(is)f(inside)g(or)g -(outside)h(the)g(go)s(o)s(d)f(time)h(in)m(terv)-5 b(al.)42 -b(The)30 b(syn)m(tax)h(is)286 4895 y Fe(gtifilter\()45 -b([)j("gtifile")d([,)i(expr)g([,)g("STARTCOL",)e("STOPCOL")g(])j(])f(]) -g(\))191 5008 y(or)286 5121 y(gtifilter\()e([)j('gtifile')d([,)i(expr)g -([,)g('STARTCOL',)e('STOPCOL')g(])j(])f(])g(\))0 5375 -y Fj(where)20 b(eac)m(h)h("[]")h(demarks)e(optional)h(parameters.)38 -b(Note)21 b(that)g(the)g(quotes)f(around)g(the)g(gti\014le)i(and)d(ST) --8 b(AR)g(T/STOP)0 5488 y(column)33 b(are)h(required.)50 -b(Either)34 b(single)g(or)g(double)f(quotes)h(ma)m(y)g(b)s(e)f(used.)50 -b(In)33 b(cases)h(where)g(this)f(expression)0 5601 y(is)d(en)m(tered)g -(on)g(the)g(Unix)g(command)g(line,)g(enclose)h(the)f(en)m(tire)h -(expression)f(in)f(double)h(quotes,)g(and)g(then)f(use)0 -5714 y(single)c(quotes)g(within)e(the)i(expression)f(to)h(enclose)g -(the)g('gti\014le')h(and)d(other)i(terms.)38 b(It)25 -b(is)f(also)h(usually)f(p)s(ossible)p eop end -%%Page: 145 153 -TeXDict begin 145 152 bop 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 -b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(145)0 -555 y(to)38 b(do)e(the)h(rev)m(erse,)j(and)c(enclose)i(the)f(whole)g -(expression)g(in)f(single)i(quotes)f(and)f(then)h(use)f(double)g -(quotes)0 668 y(within)d(the)g(expression.)50 b(The)33 -b(gti\014le,)i(if)f(sp)s(eci\014ed,)f(can)h(b)s(e)f(blank)g(\(""\))i -(whic)m(h)e(will)g(mean)h(to)g(use)f(the)h(\014rst)0 -781 y(extension)g(with)g(the)f(name)h("*GTI*")h(in)f(the)f(curren)m(t)h -(\014le,)h(a)f(plain)f(extension)h(sp)s(eci\014er)f(\(eg,)j("+2",)g -("[2]",)0 894 y(or)30 b("[STDGTI]"\))i(whic)m(h)e(will)h(b)s(e)f(used)f -(to)j(select)g(an)e(extension)h(in)f(the)h(curren)m(t)f(\014le,)h(or)f -(a)h(regular)g(\014lename)0 1007 y(with)f(or)h(without)f(an)h -(extension)g(sp)s(eci\014er)f(whic)m(h)g(in)g(the)h(latter)h(case)f -(will)g(mean)f(to)i(use)e(the)h(\014rst)e(extension)0 -1120 y(with)37 b(an)g(extension)g(name)h("*GTI*".)62 -b(Expr)36 b(can)h(b)s(e)g(an)m(y)g(arithmetic)i(expression,)f -(including)f(simply)g(the)0 1233 y(time)f(column)g(name.)57 -b(A)36 b(v)m(ector)h(time)g(expression)e(will)h(pro)s(duce)f(a)h(v)m -(ector)h(b)s(o)s(olean)f(result.)57 b(ST)-8 b(AR)g(TCOL)0 -1346 y(and)27 b(STOPCOL)f(are)i(the)g(names)g(of)g(the)g(ST)-8 -b(AR)g(T/STOP)26 b(columns)i(in)f(the)h(GTI)g(extension.)41 -b(If)27 b(one)h(of)g(them)0 1458 y(is)i(sp)s(eci\014ed,)g(they)h(b)s -(oth)f(m)m(ust)g(b)s(e.)0 1619 y(In)21 b(its)h(simplest)g(form,)i(no)d -(parameters)h(need)g(to)h(b)s(e)e(pro)m(vided)g({)h(default)g(v)-5 -b(alues)22 b(will)h(b)s(e)e(used.)37 b(The)21 b(expression)0 -1732 y("gti\014lter\(\)")33 b(is)e(equiv)-5 b(alen)m(t)31 -b(to)334 1988 y Fe(gtifilter\()45 b("",)i(TIME,)f("*START*",)f -("*STOP*")h(\))0 2244 y Fj(This)31 b(will)g(searc)m(h)h(the)g(curren)m -(t)f(\014le)g(for)g(a)h(GTI)f(extension,)h(\014lter)g(the)f(TIME)g -(column)g(in)g(the)h(curren)m(t)f(table,)0 2357 y(using)j(ST)-8 -b(AR)g(T/STOP)34 b(times)i(tak)m(en)f(from)g(columns)f(in)h(the)g(GTI)g -(extension)g(with)g(names)f(con)m(taining)j(the)0 2470 -y(strings)32 b("ST)-8 b(AR)g(T")33 b(and)e("STOP".)46 -b(The)32 b(wildcards)f(\('*'\))j(allo)m(w)g(sligh)m(t)f(v)-5 -b(ariations)33 b(in)f(naming)g(con)m(v)m(en)m(tions)0 -2583 y(suc)m(h)38 b(as)g("TST)-8 b(AR)g(T")39 b(or)f("ST)-8 -b(AR)g(TTIME".)65 b(The)37 b(same)i(default)g(v)-5 b(alues)38 -b(apply)g(for)g(unsp)s(eci\014ed)f(parame-)0 2696 y(ters)f(when)f(the)h -(\014rst)f(one)i(or)f(t)m(w)m(o)h(parameters)f(are)h(sp)s(eci\014ed.)56 -b(The)36 b(function)f(automatically)k(searc)m(hes)e(for)0 -2808 y(TIMEZER)m(O/I/F)g(k)m(eyw)m(ords)f(in)g(the)h(curren)m(t)f(and)g -(GTI)g(extensions,)i(applying)f(a)f(relativ)m(e)j(time)e(o\013set,)i -(if)0 2921 y(necessary)-8 b(.)0 3211 y Fd(10.11.5)113 -b(Spatial)38 b(Region)g(Filtering)0 3430 y Fj(Another)g(common)g -(\014ltering)g(metho)s(d)f(selects)i(ro)m(ws)f(based)g(on)f(whether)h -(the)g(spatial)h(p)s(osition)e(asso)s(ciated)0 3543 y(with)32 -b(eac)m(h)i(ro)m(w)e(is)h(lo)s(cated)h(within)e(a)h(giv)m(en)g -(2-dimensional)g(region.)48 b(The)32 b(syn)m(tax)h(for)f(this)h -(high-lev)m(el)h(\014lter)0 3656 y(is)334 3912 y Fe(regfilter\()45 -b("regfilename")f([)k(,)f(Xexpr,)f(Yexpr)h([)g(,)h("wcs)e(cols")h(])g -(])g(\))0 4168 y Fj(where)22 b(eac)m(h)i("[]")g(demarks)e(optional)i -(parameters.)38 b(The)22 b(region)h(\014le)g(name)f(is)h(required)f -(and)g(m)m(ust)g(b)s(e)g(enclosed)0 4281 y(in)34 b(quotes.)51 -b(The)33 b(remaining)h(parameters)h(are)f(optional.)52 -b(There)33 b(are)i(2)f(supp)s(orted)e(formats)i(for)f(the)h(region)0 -4394 y(\014le:)62 b(ASCI)s(I)39 b(\014le)h(or)h(FITS)f(binary)g(table.) -73 b(The)40 b(region)h(\014le)g(con)m(tains)h(a)f(list)g(of)g(one)g(or) -g(more)g(geometric)0 4507 y(shap)s(es)30 b(\(circle,)j(ellipse,)g(b)s -(o)m(x,)e(etc.\))44 b(whic)m(h)31 b(de\014nes)f(a)i(region)g(on)f(the)g -(celestial)j(sphere)c(or)h(an)g(area)h(within)f(a)0 4620 -y(particular)36 b(2D)g(image.)57 b(The)35 b(region)h(\014le)f(is)g(t)m -(ypically)j(generated)e(using)f(an)g(image)i(displa)m(y)e(program)g -(suc)m(h)0 4733 y(as)e(fv/PO)m(W)g(\(distribute)f(b)m(y)h(the)f(HEASAR) -m(C\),)h(or)g(ds9)f(\(distributed)g(b)m(y)g(the)h(Smithsonian)f -(Astroph)m(ysical)0 4846 y(Observ)-5 b(atory\).)69 b(Users)39 -b(should)g(refer)g(to)h(the)g(do)s(cumen)m(tation)h(pro)m(vided)e(with) -g(these)h(programs)f(for)h(more)0 4959 y(details)29 b(on)f(the)g(syn)m -(tax)h(used)e(in)h(the)h(region)f(\014les.)40 b(The)28 -b(FITS)f(region)i(\014le)f(format)h(is)f(de\014ned)f(in)h(a)g(do)s -(cumen)m(t)0 5072 y(a)m(v)-5 b(ailable)33 b(from)d(the)g(FITS)g(Supp)s -(ort)e(O\016ce)j(at)g(h)m(ttp://\014ts.gsfc.nasa.go)m(v/)k(registry/)c -(region.h)m(tml)0 5232 y(In)21 b(its)h(simplest)g(form,)i(\(e.g.,)h -(reg\014lter\("region.reg"\))h(\))c(the)g(co)s(ordinates)g(in)g(the)g -(default)g('X')h(and)e('Y')h(columns)0 5345 y(will)43 -b(b)s(e)g(used)f(to)i(determine)f(if)g(eac)m(h)h(ro)m(w)f(is)g(inside)g -(or)g(outside)g(the)g(area)h(sp)s(eci\014ed)e(in)h(the)g(region)h -(\014le.)0 5458 y(Alternate)32 b(p)s(osition)e(column)g(names,)h(or)f -(expressions,)h(ma)m(y)g(b)s(e)e(en)m(tered)i(if)g(needed,)f(as)h(in) -382 5714 y Fe(regfilter\("region.reg",)41 b(XPOS,)47 -b(YPOS\))p eop end -%%Page: 146 154 -TeXDict begin 146 153 bop 0 299 a Fj(146)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fj(Region)37 b(\014ltering)f(can)g(b)s(e)f(applied)g(most)h(unam) -m(biguously)f(if)h(the)g(p)s(ositions)g(in)f(the)h(region)g(\014le)g -(and)f(in)h(the)0 668 y(table)g(to)g(b)s(e)e(\014ltered)h(are)h(b)s -(oth)e(giv)m(e)j(in)e(terms)g(of)g(absolute)h(celestial)i(co)s -(ordinate)e(units.)54 b(In)35 b(this)g(case)h(the)0 781 -y(lo)s(cations)26 b(and)d(sizes)i(of)g(the)f(geometric)i(shap)s(es)e -(in)g(the)g(region)h(\014le)f(are)h(sp)s(eci\014ed)f(in)g(angular)g -(units)g(on)g(the)g(sky)0 894 y(\(e.g.,)32 b(p)s(ositions)e(giv)m(en)i -(in)e(R.A.)g(and)g(Dec.)42 b(and)30 b(sizes)h(in)f(arcseconds)g(or)h -(arcmin)m(utes\).)41 b(Similarly)-8 b(,)31 b(eac)m(h)h(ro)m(w)0 -1007 y(of)h(the)h(\014ltered)f(table)h(will)f(ha)m(v)m(e)i(a)e -(celestial)j(co)s(ordinate)e(asso)s(ciated)g(with)f(it.)50 -b(This)32 b(asso)s(ciation)j(is)e(usually)0 1120 y(implemen)m(ted)39 -b(using)e(a)i(set)g(of)f(so-called)i('W)-8 b(orld)39 -b(Co)s(ordinate)g(System')f(\(or)h(W)m(CS\))f(FITS)g(k)m(eyw)m(ords)g -(that)0 1233 y(de\014ne)27 b(the)g(co)s(ordinate)h(transformation)g -(that)g(m)m(ust)f(b)s(e)f(applied)h(to)h(the)g(v)-5 b(alues)27 -b(in)g(the)h('X')g(and)e('Y')i(columns)0 1346 y(to)j(calculate)i(the)d -(co)s(ordinate.)0 1506 y(Alternativ)m(ely)-8 b(,)30 b(one)d(can)g(p)s -(erform)e(spatial)j(\014ltering)e(using)g(unitless)h('pixel')g(co)s -(ordinates)h(for)e(the)h(regions)g(and)0 1619 y(ro)m(w)33 -b(p)s(ositions.)49 b(In)33 b(this)g(case)h(the)f(user)g(m)m(ust)g(b)s -(e)f(careful)h(to)h(ensure)f(that)g(the)h(p)s(ositions)f(in)g(the)g(2)g -(\014les)h(are)0 1732 y(self-consisten)m(t.)54 b(A)34 -b(t)m(ypical)i(problem)d(is)h(that)h(the)f(region)h(\014le)f(ma)m(y)h -(b)s(e)e(generated)j(using)d(a)i(binned)d(image,)0 1844 -y(but)g(the)h(un)m(binned)e(co)s(ordinates)i(are)g(giv)m(en)h(in)e(the) -h(ev)m(en)m(t)i(table.)48 b(The)32 b(R)m(OSA)-8 b(T)33 -b(ev)m(en)m(ts)h(\014les,)g(for)e(example,)0 1957 y(ha)m(v)m(e)f(X)f -(and)f(Y)g(pixel)h(co)s(ordinates)g(that)h(range)f(from)f(1)h(-)g -(15360.)42 b(These)30 b(co)s(ordinates)g(are)g(t)m(ypically)h(binned)0 -2070 y(b)m(y)i(a)h(factor)g(of)f(32)h(to)g(pro)s(duce)e(a)i(480x480)i -(pixel)d(image.)51 b(If)32 b(one)i(then)f(uses)g(a)g(region)h(\014le)f -(generated)h(from)0 2183 y(this)c(image)i(\(in)f(image)g(pixel)g -(units\))g(to)g(\014lter)f(the)h(R)m(OSA)-8 b(T)30 b(ev)m(en)m(ts)i -(\014le,)f(then)f(the)h(X)g(and)f(Y)g(column)h(v)-5 b(alues)0 -2296 y(m)m(ust)30 b(b)s(e)g(con)m(v)m(erted)i(to)f(corresp)s(onding)e -(pixel)i(units)f(as)g(in:)382 2562 y Fe(regfilter\("rosat.reg",)42 -b(X/32.+.5,)j(Y/32.+.5\))0 2829 y Fj(Note)h(that)f(this)f(binning)f -(con)m(v)m(ersion)j(is)e(not)h(necessary)g(if)f(the)h(region)g(\014le)f -(is)h(sp)s(eci\014ed)e(using)h(celestial)0 2942 y(co)s(ordinate)h -(units)f(instead)g(of)g(pixel)h(units)f(b)s(ecause)g(CFITSIO)e(is)j -(then)e(able)i(to)g(directly)g(compare)g(the)0 3054 y(celestial)30 -b(co)s(ordinate)f(of)e(eac)m(h)i(ro)m(w)f(in)f(the)h(table)g(with)g -(the)f(celestial)k(co)s(ordinates)d(in)f(the)h(region)g(\014le)g -(without)0 3167 y(ha)m(ving)j(to)g(kno)m(w)f(an)m(ything)h(ab)s(out)f -(ho)m(w)h(the)f(image)i(ma)m(y)f(ha)m(v)m(e)g(b)s(een)f(binned.)0 -3328 y(The)f(last)h("w)m(cs)g(cols")h(parameter)f(should)e(rarely)h(b)s -(e)g(needed.)40 b(If)29 b(supplied,)f(this)i(string)f(con)m(tains)i -(the)e(names)0 3440 y(of)37 b(the)g(2)h(columns)f(\(space)h(or)f(comma) -g(separated\))h(whic)m(h)f(ha)m(v)m(e)h(the)g(asso)s(ciated)g(W)m(CS)f -(k)m(eyw)m(ords.)61 b(If)37 b(not)0 3553 y(supplied,)f(the)g(\014lter)g -(will)h(scan)f(the)g(X)g(and)f(Y)h(expressions)g(for)g(column)f(names.) -58 b(If)35 b(only)h(one)h(is)f(found)e(in)0 3666 y(eac)m(h)e -(expression,)e(those)h(columns)f(will)h(b)s(e)e(used,)h(otherwise)h(an) -f(error)g(will)h(b)s(e)f(returned.)0 3826 y(These)g(region)h(shap)s(es) -f(are)g(supp)s(orted)f(\(names)h(are)h(case)h(insensitiv)m(e\):)334 -4093 y Fe(Point)428 b(\()48 b(X1,)f(Y1)g(\))715 b(<-)48 -b(One)f(pixel)f(square)g(region)334 4206 y(Line)476 b(\()48 -b(X1,)f(Y1,)g(X2,)f(Y2)i(\))333 b(<-)48 b(One)f(pixel)f(wide)h(region) -334 4319 y(Polygon)332 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(...)g(\))95 -b(<-)48 b(Rest)e(are)h(interiors)e(with)334 4431 y(Rectangle)236 -b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(A)h(\))334 b(|)47 b(boundaries)e -(considered)334 4544 y(Box)524 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A) -i(\))143 b(V)47 b(within)f(the)h(region)334 4657 y(Diamond)332 -b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A)i(\))334 4770 -y(Circle)380 b(\()48 b(Xc,)f(Yc,)g(R)g(\))334 4883 y(Annulus)332 -b(\()48 b(Xc,)f(Yc,)g(Rin,)f(Rout)h(\))334 4996 y(Ellipse)332 -b(\()48 b(Xc,)f(Yc,)g(Rx,)f(Ry,)h(A)h(\))334 5109 y(Elliptannulus)c(\() -k(Xc,)f(Yc,)g(Rinx,)f(Riny,)g(Routx,)g(Routy,)g(Ain,)h(Aout)g(\))334 -5222 y(Sector)380 b(\()48 b(Xc,)f(Yc,)g(Amin,)f(Amax)h(\))0 -5488 y Fj(where)28 b(\(Xc,Yc\))j(is)d(the)h(co)s(ordinate)h(of)e(the)h -(shap)s(e's)f(cen)m(ter;)j(\(X#,Y#\))e(are)g(the)g(co)s(ordinates)g(of) -g(the)g(shap)s(e's)0 5601 y(edges;)39 b(Rxxx)c(are)g(the)h(shap)s(es')f -(v)-5 b(arious)35 b(Radii)h(or)f(semima)5 b(jor/minor)36 -b(axes;)i(and)d(Axxx)g(are)h(the)g(angles)g(of)0 5714 -y(rotation)d(\(or)e(b)s(ounding)f(angles)i(for)f(Sector\))h(in)f -(degrees.)44 b(F)-8 b(or)32 b(rotated)h(shap)s(es,)e(the)g(rotation)i -(angle)f(can)g(b)s(e)p eop end -%%Page: 147 155 -TeXDict begin 147 154 bop 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 -b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(147)0 -555 y(left)32 b(o\013,)h(indicating)f(no)f(rotation.)46 -b(Common)31 b(alternate)i(names)e(for)h(the)f(regions)h(can)g(also)h(b) -s(e)d(used:)43 b(rotb)s(o)m(x)0 668 y(=)29 b(b)s(o)m(x;)g(rotrectangle) -i(=)e(rectangle;)i(\(rot\)rhom)m(bus)e(=)f(\(rot\)diamond;)j(and)d(pie) -h(=)f(sector.)42 b(When)28 b(a)i(shap)s(e's)0 781 y(name)e(is)g -(preceded)f(b)m(y)h(a)g(min)m(us)g(sign,)g('-',)i(the)e(de\014ned)e -(region)j(is)f(instead)g(the)g(area)h(*outside*)g(its)f(b)s(oundary)0 -894 y(\(ie,)36 b(the)e(region)h(is)f(in)m(v)m(erted\).)53 -b(All)34 b(the)g(shap)s(es)f(within)h(a)g(single)h(region)f(\014le)h -(are)f(OR'd)f(together)j(to)e(create)0 1007 y(the)29 -b(region,)i(and)d(the)i(order)f(is)g(signi\014can)m(t.)41 -b(The)29 b(o)m(v)m(erall)i(w)m(a)m(y)g(of)e(lo)s(oking)h(at)g(region)g -(\014les)f(is)g(that)h(if)f(the)h(\014rst)0 1120 y(region)f(is)g(an)g -(excluded)g(region)g(then)f(a)i(dumm)m(y)d(included)h(region)i(of)f -(the)g(whole)g(detector)h(is)f(inserted)f(in)h(the)0 -1233 y(fron)m(t.)40 b(Then)25 b(eac)m(h)j(region)f(sp)s(eci\014cation)h -(as)f(it)g(is)g(pro)s(cessed)f(o)m(v)m(errides)h(an)m(y)g(selections)i -(inside)d(of)h(that)g(region)0 1346 y(sp)s(eci\014ed)36 -b(b)m(y)g(previous)g(regions.)59 b(Another)37 b(w)m(a)m(y)g(of)g -(thinking)f(ab)s(out)g(this)g(is)h(that)g(if)f(a)h(previous)f(excluded) -0 1458 y(region)31 b(is)f(completely)i(inside)f(of)f(a)h(subsequen)m(t) -e(included)h(region)h(the)g(excluded)f(region)h(is)f(ignored.)0 -1619 y(The)44 b(p)s(ositional)i(co)s(ordinates)g(ma)m(y)f(b)s(e)g(giv)m -(en)h(either)f(in)g(pixel)g(units,)j(decimal)e(degrees)g(or)f -(hh:mm:ss.s,)0 1732 y(dd:mm:ss.s)25 b(units.)38 b(The)26 -b(shap)s(e)f(sizes)i(ma)m(y)f(b)s(e)g(giv)m(en)h(in)e(pixels,)j -(degrees,)f(arcmin)m(utes,)h(or)e(arcseconds.)40 b(Lo)s(ok)0 -1844 y(at)31 b(examples)g(of)f(region)h(\014le)g(pro)s(duced)d(b)m(y)i -(fv/PO)m(W)h(or)g(ds9)f(for)g(further)f(details)i(of)g(the)f(region)h -(\014le)f(format.)0 2005 y(There)h(are)g(three)h(lo)m(w-lev)m(el)i -(functions)d(that)g(are)h(primarily)f(for)g(use)g(with)g(reg\014lter)g -(function,)h(but)e(they)i(can)0 2118 y(b)s(e)j(called)i(directly)-8 -b(.)59 b(They)35 b(return)g(a)h(b)s(o)s(olean)g(true)g(or)g(false)h -(dep)s(ending)d(on)i(whether)f(a)i(t)m(w)m(o)g(dimensional)0 -2230 y(p)s(oin)m(t)30 b(is)h(in)f(the)g(region)h(or)g(not.)41 -b(The)30 b(p)s(ositional)h(co)s(ordinates)g(m)m(ust)f(b)s(e)g(giv)m(en) -h(in)f(pixel)h(units:)191 2492 y Fe("point)46 b(in)h(a)h(circular)d -(region")477 2605 y(circle\(xcntr,ycntr,radius)o(,Xco)o(lumn)o(,Yc)o -(olum)o(n\))191 2831 y("point)h(in)h(an)g(elliptical)e(region")430 -2944 y(ellipse\(xcntr,ycntr,xhl)o(f_w)o(dth,)o(yhlf)o(_wd)o(th,r)o -(otat)o(ion)o(,Xco)o(lumn)o(,Yc)o(olum)o(n\))191 3169 -y("point)h(in)h(a)h(rectangular)c(region")620 3282 y -(box\(xcntr,ycntr,xfll_wdth,)o(yfll)o(_wd)o(th,r)o(otat)o(ion)o(,Xco)o -(lumn)o(,Yc)o(olum)o(n\))191 3508 y(where)334 3621 y(\(xcntr,ycntr\))g -(are)j(the)g(\(x,y\))f(position)g(of)h(the)g(center)f(of)h(the)g -(region)334 3734 y(\(xhlf_wdth,yhlf_wdth\))42 b(are)47 -b(the)g(\(x,y\))f(half)h(widths)f(of)h(the)g(region)334 -3847 y(\(xfll_wdth,yfll_wdth\))42 b(are)47 b(the)g(\(x,y\))f(full)h -(widths)f(of)h(the)g(region)334 3960 y(\(radius\))f(is)h(half)f(the)h -(diameter)f(of)h(the)g(circle)334 4073 y(\(rotation\))e(is)i(the)g -(angle\(degrees\))d(that)j(the)g(region)f(is)h(rotated)f(with)620 -4186 y(respect)g(to)h(\(xcntr,ycntr\))334 4299 y(\(Xcoord,Ycoord\))d -(are)j(the)g(\(x,y\))f(coordinates)f(to)i(test,)f(usually)g(column)620 -4411 y(names)334 4524 y(NOTE:)g(each)h(parameter)e(can)i(itself)f(be)i -(an)f(expression,)d(not)j(merely)f(a)620 4637 y(column)h(name)f(or)h -(constant.)0 4930 y Fd(10.11.6)113 b(Example)38 b(Ro)m(w)f(Filters)191 -5149 y Fe([)47 b(binary)f(&&)i(mag)f(<=)g(5.0])380 b(-)48 -b(Extract)e(all)h(binary)f(stars)g(brighter)1766 5262 -y(than)94 b(fifth)47 b(magnitude)e(\(note)h(that)1766 -5375 y(the)h(initial)f(space)g(is)h(necessary)e(to)1766 -5488 y(prevent)h(it)h(from)g(being)f(treated)g(as)h(a)1766 -5601 y(binning)f(specification\))p eop end -%%Page: 148 156 -TeXDict begin 148 155 bop 0 299 a Fj(148)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)191 -555 y Fe([#row)46 b(>=)h(125)g(&&)h(#row)e(<=)h(175])142 -b(-)48 b(Extract)e(row)h(numbers)e(125)i(through)f(175)191 -781 y([IMAGE[4,5])f(.gt.)h(100])476 b(-)48 b(Extract)e(all)h(rows)f -(that)h(have)g(the)1766 894 y(\(4,5\))f(component)g(of)h(the)g(IMAGE)f -(column)1766 1007 y(greater)g(than)g(100)191 1233 y([abs\(sin\(theta)e -(*)j(#deg\)\))f(<)i(0.5])e(-)i(Extract)e(all)h(rows)f(having)g(the)1766 -1346 y(absolute)f(value)i(of)g(the)g(sine)g(of)g(theta)1766 -1458 y(less)94 b(than)47 b(a)g(half)g(where)f(the)h(angles)1766 -1571 y(are)g(tabulated)e(in)i(degrees)191 1797 y([SUM\()f(SPEC)h(>)g -(3*BACKGRND)e(\)>=1])94 b(-)48 b(Extract)e(all)h(rows)f(containing)f(a) -1766 1910 y(spectrum,)g(held)i(in)g(vector)f(column)1766 -2023 y(SPEC,)g(with)h(at)g(least)f(one)h(value)g(3)1766 -2136 y(times)f(greater)g(than)h(the)g(background)1766 -2249 y(level)f(held)h(in)g(a)h(keyword,)d(BACKGRND)191 -2475 y([VCOL=={1,4,2}])759 b(-)48 b(Extract)e(all)h(rows)f(whose)h -(vector)f(column)1766 2588 y(VCOL)h(contains)e(the)i(3-elements)e(1,)i -(4,)g(and)1766 2700 y(2.)191 2926 y([@rowFilter.txt])711 -b(-)48 b(Extract)e(rows)g(using)h(the)g(expression)1766 -3039 y(contained)e(within)h(the)h(text)g(file)1766 3152 -y(rowFilter.txt)191 3378 y([gtifilter\(\)])855 b(-)48 -b(Search)e(the)h(current)f(file)g(for)h(a)h(GTI)239 3491 -y(extension,)92 b(filter)i(the)47 b(TIME)239 3604 y(column)f(in)h(the)g -(current)f(table,)g(using)239 3717 y(START/STOP)f(times)h(taken)g(from) -239 3830 y(columns)f(in)j(the)f(GTI)94 b(extension)191 -4055 y([regfilter\("pow.reg"\)])423 b(-)48 b(Extract)e(rows)g(which)h -(have)f(a)i(coordinate)1766 4168 y(\(as)f(given)f(in)h(the)g(X)h(and)f -(Y)g(columns\))1766 4281 y(within)f(the)h(spatial)f(region)g(specified) -1766 4394 y(in)h(the)g(pow.reg)f(region)g(file.)191 4620 -y([regfilter\("pow.reg",)c(Xs,)47 b(Ys\)])f(-)i(Same)f(as)g(above,)f -(except)g(that)h(the)1766 4733 y(Xs)g(and)g(Ys)g(columns)f(will)h(be)g -(used)f(to)1766 4846 y(determine)f(the)i(coordinate)e(of)i(each)1766 -4959 y(row)g(in)g(the)g(table.)0 5341 y Ff(10.12)181 -b(Binning)44 b(or)h(Histogramming)i(Sp)t(eci\014cation)0 -5601 y Fj(The)22 b(optional)i(binning)e(sp)s(eci\014er)g(is)h(enclosed) -h(in)f(square)f(brac)m(k)m(ets)j(and)d(can)h(b)s(e)f(distinguished)g -(from)h(a)g(general)0 5714 y(ro)m(w)32 b(\014lter)h(sp)s(eci\014cation) -g(b)m(y)f(the)h(fact)g(that)g(it)g(b)s(egins)f(with)g(the)g(k)m(eyw)m -(ord)h('bin')f(not)h(immediately)g(follo)m(w)m(ed)p eop -end -%%Page: 149 157 -TeXDict begin 149 156 bop 0 299 a Fh(10.12.)113 b(BINNING)32 -b(OR)e(HISTOGRAMMING)g(SPECIFICA)-8 b(TION)1223 b Fj(149)0 -555 y(b)m(y)41 b(an)f(equals)i(sign.)72 b(When)41 b(binning)e(is)i(sp)s -(eci\014ed,)i(a)e(temp)s(orary)g(N-dimensional)g(FITS)f(primary)g(arra) -m(y)0 668 y(is)j(created)h(b)m(y)f(computing)h(the)f(histogram)h(of)f -(the)g(v)-5 b(alues)44 b(in)e(the)i(sp)s(eci\014ed)e(columns)h(of)g(a)h -(FITS)e(table)0 781 y(extension.)f(After)30 b(the)f(histogram)h(is)g -(computed)f(the)h(input)e(FITS)h(\014le)h(con)m(taining)h(the)e(table)i -(is)e(then)g(closed)0 894 y(and)34 b(the)h(temp)s(orary)f(FITS)g -(primary)g(arra)m(y)h(is)g(op)s(ened)f(and)g(passed)g(to)h(the)g -(application)h(program.)54 b(Th)m(us,)0 1007 y(the)39 -b(application)h(program)f(nev)m(er)g(sees)g(the)g(original)h(FITS)e -(table)i(and)e(only)h(sees)h(the)f(image)h(in)e(the)h(new)0 -1120 y(temp)s(orary)32 b(\014le)h(\(whic)m(h)g(has)f(no)h(additional)g -(extensions\).)49 b(Ob)m(viously)-8 b(,)34 b(the)f(application)h -(program)e(m)m(ust)h(b)s(e)0 1233 y(exp)s(ecting)e(to)g(op)s(en)f(a)h -(FITS)e(image)j(and)e(not)g(a)h(FITS)f(table)h(in)f(this)g(case.)0 -1393 y(The)g(data)h(t)m(yp)s(e)f(of)h(the)f(FITS)g(histogram)g(image)i -(ma)m(y)f(b)s(e)f(sp)s(eci\014ed)f(b)m(y)h(app)s(ending)f('b')h(\(for)h -(8-bit)g(b)m(yte\),)g('i')0 1506 y(\(for)g(16-bit)g(in)m(tegers\),)h -('j')f(\(for)g(32-bit)g(in)m(teger\),)i('r')d(\(for)h(32-bit)g -(\015oating)h(p)s(oin)m(ts\),)e(or)h('d')f(\(for)h(64-bit)g(double)0 -1619 y(precision)j(\015oating)i(p)s(oin)m(t\))e(to)h(the)g('bin')f(k)m -(eyw)m(ord)h(\(e.g.)54 b('[binr)33 b(X]')i(creates)h(a)f(real)g -(\015oating)g(p)s(oin)m(t)f(image\).)0 1732 y(If)g(the)i(data)f(t)m(yp) -s(e)g(is)g(not)h(explicitly)g(sp)s(eci\014ed)e(then)h(a)g(32-bit)i(in)m -(teger)f(image)g(will)f(b)s(e)g(created)h(b)m(y)e(default,)0 -1844 y(unless)24 b(the)i(w)m(eigh)m(ting)g(option)g(is)f(also)h(sp)s -(eci\014ed)e(in)h(whic)m(h)g(case)h(the)f(image)i(will)e(ha)m(v)m(e)h -(a)g(32-bit)g(\015oating)g(p)s(oin)m(t)0 1957 y(data)31 -b(t)m(yp)s(e)g(b)m(y)f(default.)0 2118 y(The)24 b(histogram)g(image)i -(ma)m(y)f(ha)m(v)m(e)g(from)f(1)g(to)h(4)g(dimensions)e(\(axes\),)k -(dep)s(ending)c(on)h(the)g(n)m(um)m(b)s(er)f(of)h(columns)0 -2230 y(that)31 b(are)g(sp)s(eci\014ed.)40 b(The)30 b(general)h(form)f -(of)g(the)h(binning)e(sp)s(eci\014cation)i(is:)48 2457 -y Fe([bin{bijrd})92 b(Xcol=min:max:binsize,)42 b(Ycol=)47 -b(...,)f(Zcol=...,)f(Tcol=...;)h(weight])0 2683 y Fj(in)39 -b(whic)m(h)g(up)f(to)i(4)g(columns,)h(eac)m(h)f(corresp)s(onding)e(to)i -(an)g(axis)f(of)h(the)f(image,)k(are)d(listed.)67 b(The)39 -b(column)0 2796 y(names)27 b(are)h(case)h(insensitiv)m(e,)g(and)e(the)h -(column)f(n)m(um)m(b)s(er)f(ma)m(y)i(b)s(e)f(giv)m(en)h(instead)g(of)g -(the)g(name,)g(preceded)f(b)m(y)0 2909 y(a)32 b(p)s(ound)e(sign)i -(\(e.g.,)i([bin)d(#4=1:512]\).)47 b(If)31 b(the)h(column)g(name)g(is)f -(not)h(sp)s(eci\014ed,)g(then)f(CFITSIO)g(will)h(\014rst)0 -3022 y(try)37 b(to)h(use)f(the)g('preferred)f(column')i(as)f(sp)s -(eci\014ed)g(b)m(y)g(the)g(CPREF)g(k)m(eyw)m(ord)h(if)f(it)g(exists)h -(\(e.g.,)j('CPREF)0 3135 y(=)i('DETX,DETY'\),)h(otherwise)g(column)f -(names)g('X',)h('Y',)g('Z',)f(and)f('T')i(will)f(b)s(e)f(assumed)h(for) -g(eac)m(h)h(of)0 3247 y(the)37 b(4)h(axes,)i(resp)s(ectiv)m(ely)-8 -b(.)62 b(In)37 b(cases)h(where)e(the)i(column)f(name)g(could)g(b)s(e)f -(confused)h(with)g(an)g(arithmetic)0 3360 y(expression,)30 -b(enclose)i(the)f(column)f(name)g(in)g(paren)m(theses)h(to)g(force)g -(the)f(name)h(to)g(b)s(e)f(in)m(terpreted)g(literally)-8 -b(.)0 3521 y(Eac)m(h)33 b(column)f(name)g(ma)m(y)h(b)s(e)f(follo)m(w)m -(ed)h(b)m(y)g(an)f(equals)g(sign)h(and)e(then)h(the)g(lo)m(w)m(er)i -(and)e(upp)s(er)e(range)i(of)h(the)0 3633 y(histogram,)f(and)e(the)h -(size)h(of)f(the)g(histogram)h(bins,)e(separated)h(b)m(y)g(colons.)43 -b(Spaces)31 b(are)g(allo)m(w)m(ed)i(b)s(efore)e(and)0 -3746 y(after)e(the)g(equals)g(sign)f(but)g(not)h(within)f(the)h -('min:max:binsize')g(string.)40 b(The)29 b(min,)f(max)h(and)f(binsize)h -(v)-5 b(alues)0 3859 y(ma)m(y)32 b(b)s(e)e(in)m(teger)i(or)f -(\015oating)h(p)s(oin)m(t)f(n)m(um)m(b)s(ers,)f(or)h(they)g(ma)m(y)g(b) -s(e)g(the)g(names)g(of)g(k)m(eyw)m(ords)g(in)g(the)g(header)g(of)0 -3972 y(the)g(table.)41 b(If)30 b(the)h(latter,)h(then)e(the)g(v)-5 -b(alue)31 b(of)g(that)g(k)m(eyw)m(ord)f(is)h(substituted)f(in)m(to)h -(the)g(expression.)0 4132 y(Default)37 b(v)-5 b(alues)36 -b(for)g(the)g(min,)h(max)f(and)g(binsize)g(quan)m(tities)h(will)f(b)s -(e)f(used)h(if)f(not)i(explicitly)g(giv)m(en)g(in)f(the)0 -4245 y(binning)29 b(expression)h(as)h(sho)m(wn)f(in)g(these)h -(examples:)191 4471 y Fe([bin)47 b(x)g(=)g(:512:2])94 -b(-)47 b(use)g(default)f(minimum)g(value)191 4584 y([bin)h(x)g(=)g -(1::2])190 b(-)47 b(use)g(default)f(maximum)g(value)191 -4697 y([bin)h(x)g(=)g(1:512])142 b(-)47 b(use)g(default)f(bin)h(size) -191 4810 y([bin)g(x)g(=)g(1:])286 b(-)47 b(use)g(default)f(maximum)g -(value)g(and)h(bin)g(size)191 4923 y([bin)g(x)g(=)g(:512])190 -b(-)47 b(use)g(default)f(minimum)g(value)g(and)h(bin)g(size)191 -5036 y([bin)g(x)g(=)g(2])334 b(-)47 b(use)g(default)f(minimum)g(and)h -(maximum)f(values)191 5149 y([bin)h(x])524 b(-)47 b(use)g(default)f -(minimum,)g(maximum)g(and)g(bin)h(size)191 5262 y([bin)g(4])524 -b(-)47 b(default)f(2-D)h(image,)f(bin)h(size)g(=)g(4)h(in)f(both)g -(axes)191 5375 y([bin])619 b(-)47 b(default)f(2-D)h(image)0 -5601 y Fj(CFITSIO)31 b(will)i(use)f(the)h(v)-5 b(alue)33 -b(of)g(the)g(TLMINn,)f(TLMAXn,)h(and)f(TDBINn)h(k)m(eyw)m(ords,)h(if)e -(they)h(exist,)h(for)0 5714 y(the)j(default)f(min,)i(max,)g(and)e -(binsize,)i(resp)s(ectiv)m(ely)-8 b(.)61 b(If)36 b(they)h(do)f(not)h -(exist)g(then)f(CFITSIO)f(will)i(use)f(the)p eop end -%%Page: 150 158 -TeXDict begin 150 157 bop 0 299 a Fj(150)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fj(actual)33 b(minim)m(um)e(and)h(maxim)m(um)g(v)-5 -b(alues)32 b(in)g(the)g(column)f(for)h(the)g(histogram)h(min)e(and)h -(max)g(v)-5 b(alues.)45 b(The)0 668 y(default)34 b(binsize)f(will)h(b)s -(e)f(set)h(to)h(1,)g(or)e(\(max)h(-)g(min\))f(/)h(10.,)i(whic)m(hev)m -(er)e(is)g(smaller,)h(so)e(that)i(the)e(histogram)0 781 -y(will)e(ha)m(v)m(e)g(at)g(least)h(10)f(bins)f(along)h(eac)m(h)h(axis.) -0 941 y(A)41 b(shortcut)g(notation)h(is)f(allo)m(w)m(ed)i(if)e(all)h -(the)f(columns/axes)h(ha)m(v)m(e)g(the)f(same)g(binning)f(sp)s -(eci\014cation.)74 b(In)0 1054 y(this)33 b(case)g(all)h(the)f(column)f -(names)h(ma)m(y)g(b)s(e)f(listed)h(within)f(paren)m(theses,)i(follo)m -(w)m(ed)h(b)m(y)d(the)h(\(single\))h(binning)0 1167 y(sp)s -(eci\014cation,)d(as)g(in:)191 1431 y Fe([bin)47 b(\(X,Y\)=1:512:2])191 -1544 y([bin)g(\(X,Y\))f(=)h(5])0 1808 y Fj(The)31 b(optional)i(w)m -(eigh)m(ting)h(factor)e(is)g(the)g(last)g(item)h(in)e(the)h(binning)f -(sp)s(eci\014er)g(and,)h(if)f(presen)m(t,)i(is)e(separated)0 -1921 y(from)38 b(the)g(list)h(of)f(columns)g(b)m(y)g(a)h(semi-colon.)65 -b(As)39 b(the)f(histogram)h(is)f(accum)m(ulated,)k(this)c(w)m(eigh)m(t) -i(is)e(used)0 2034 y(to)d(incremen)m(ted)f(the)g(v)-5 -b(alue)35 b(of)f(the)g(appropriated)f(bin)h(in)f(the)h(histogram.)52 -b(If)34 b(the)g(w)m(eigh)m(ting)i(factor)f(is)f(not)0 -2147 y(sp)s(eci\014ed,)24 b(then)f(the)g(default)g(w)m(eigh)m(t)i(=)d -(1)i(is)f(assumed.)37 b(The)23 b(w)m(eigh)m(ting)i(factor)f(ma)m(y)f(b) -s(e)g(a)g(constan)m(t)i(in)m(teger)f(or)0 2260 y(\015oating)30 -b(p)s(oin)m(t)f(n)m(um)m(b)s(er,)f(or)h(the)g(name)g(of)g(a)g(k)m(eyw)m -(ord)h(con)m(taining)g(the)g(w)m(eigh)m(ting)g(v)-5 b(alue.)41 -b(Or)28 b(the)h(w)m(eigh)m(ting)0 2372 y(factor)g(ma)m(y)g(b)s(e)e(the) -h(name)g(of)h(a)f(table)h(column)f(in)g(whic)m(h)f(case)j(the)e(v)-5 -b(alue)28 b(in)g(that)h(column,)f(on)g(a)h(ro)m(w)f(b)m(y)g(ro)m(w)0 -2485 y(basis,)i(will)h(b)s(e)f(used.)0 2646 y(In)35 b(some)h(cases,)i -(the)d(column)h(or)f(k)m(eyw)m(ord)h(ma)m(y)g(giv)m(e)h(the)f(recipro)s -(cal)g(of)g(the)g(actual)h(w)m(eigh)m(t)g(v)-5 b(alue)36 -b(that)g(is)0 2758 y(needed.)49 b(In)32 b(this)h(case,)i(precede)e(the) -h(w)m(eigh)m(t)g(k)m(eyw)m(ord)g(or)f(column)g(name)g(b)m(y)g(a)g -(slash)g('/')h(to)g(tell)g(CFITSIO)0 2871 y(to)d(use)f(the)h(recipro)s -(cal)g(of)f(the)h(v)-5 b(alue)31 b(when)e(constructing)i(the)g -(histogram.)0 3032 y(F)-8 b(or)25 b(complex)g(or)f(commonly)g(used)g -(histograms,)i(one)e(can)h(also)g(place)g(its)f(description)g(in)m(to)h -(a)g(text)g(\014le)f(and)g(im-)0 3144 y(p)s(ort)e(it)g(in)m(to)h(the)g -(binning)e(sp)s(eci\014cation)i(using)e(the)i(syn)m(tax)f([bin)g -(@\014lename.txt].)39 b(The)22 b(\014le's)g(con)m(ten)m(ts)i(can)e(ex-) -0 3257 y(tend)h(o)m(v)m(er)i(m)m(ultiple)f(lines,)h(although)f(it)g(m)m -(ust)f(still)h(conform)f(to)h(the)g(no-spaces)g(rule)f(for)g(the)h -(min:max:binsize)0 3370 y(syn)m(tax)35 b(and)f(eac)m(h)h(axis)g(sp)s -(eci\014cation)h(m)m(ust)e(still)h(b)s(e)f(comma-separated.)55 -b(An)m(y)34 b(lines)h(in)f(the)h(external)g(text)0 3483 -y(\014le)27 b(that)g(b)s(egin)g(with)f(2)i(slash)e(c)m(haracters)j -(\('//'\))g(will)e(b)s(e)f(ignored)h(and)f(ma)m(y)i(b)s(e)e(used)g(to)i -(add)e(commen)m(ts)i(in)m(to)0 3596 y(the)j(\014le.)0 -3756 y(Examples:)191 4020 y Fe([bini)46 b(detx,)h(dety])762 -b(-)47 b(2-D,)g(16-bit)f(integer)g(histogram)1861 4133 -y(of)i(DETX)e(and)h(DETY)g(columns,)e(using)1861 4246 -y(default)h(values)g(for)h(the)g(histogram)1861 4359 -y(range)g(and)g(binsize)191 4585 y([bin)g(\(detx,)f(dety\)=16;)f -(/exposure])g(-)i(2-D,)g(32-bit)f(real)h(histogram)e(of)i(DETX)1861 -4698 y(and)g(DETY)g(columns)f(with)g(a)i(bin)f(size)f(=)i(16)1861 -4811 y(in)g(both)e(axes.)h(The)f(histogram)g(values)1861 -4924 y(are)h(divided)f(by)h(the)g(EXPOSURE)f(keyword)1861 -5036 y(value.)191 5262 y([bin)h(time=TSTART:TSTOP:0.1])280 -b(-)47 b(1-D)g(lightcurve,)e(range)h(determined)f(by)1861 -5375 y(the)i(TSTART)f(and)h(TSTOP)g(keywords,)1861 5488 -y(with)g(0.1)g(unit)g(size)f(bins.)191 5714 y([bin)h(pha,)f -(time=8000.:8100.:0.1])90 b(-)47 b(2-D)g(image)g(using)f(default)g -(binning)p eop end -%%Page: 151 159 -TeXDict begin 151 158 bop 0 299 a Fh(10.12.)113 b(BINNING)32 -b(OR)e(HISTOGRAMMING)g(SPECIFICA)-8 b(TION)1223 b Fj(151)1861 -555 y Fe(of)48 b(the)e(PHA)h(column)f(for)h(the)g(X)h(axis,)1861 -668 y(and)f(1000)g(bins)g(in)g(the)g(range)1861 781 y(8000.)g(to)g -(8100.)f(for)h(the)g(Y)h(axis.)191 1007 y([bin)f(@binFilter.txt])616 -b(-)47 b(Use)g(the)g(contents)f(of)h(the)g(text)f(file)1861 -1120 y(binFilter.txt)f(for)h(the)h(binning)1861 1233 -y(specifications.)p eop end -%%Page: 152 160 -TeXDict begin 152 159 bop 0 299 a Fj(152)1528 b Fh(CHAPTER)29 -b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)p -eop end -%%Page: 153 161 -TeXDict begin 153 160 bop 0 1225 a Fg(Chapter)65 b(11)0 -1687 y Fm(T)-19 b(emplate)76 b(Files)0 2180 y Fj(When)38 -b(a)h(new)f(FITS)g(\014le)h(is)g(created)g(with)g(a)f(call)i(to)g -(\014ts)p 2101 2180 28 4 v 32 w(create)p 2369 2180 V -35 w(\014le,)g(the)f(name)g(of)g(a)g(template)h(\014le)e(ma)m(y)0 -2293 y(b)s(e)h(supplied)g(in)h(paren)m(theses)g(immediately)h(follo)m -(wing)g(the)g(name)f(of)g(the)g(new)f(\014le)h(to)h(b)s(e)e(created.)71 -b(This)0 2406 y(template)27 b(is)e(used)g(to)h(de\014ne)f(the)h -(structure)f(of)h(one)f(or)h(more)g(HDUs)g(in)f(the)h(new)f(\014le.)39 -b(The)25 b(template)i(\014le)e(ma)m(y)0 2518 y(b)s(e)32 -b(another)h(FITS)f(\014le,)i(in)f(whic)m(h)f(case)i(the)f(newly)g -(created)h(\014le)f(will)g(ha)m(v)m(e)h(exactly)h(the)e(same)g(k)m(eyw) -m(ords)g(in)0 2631 y(eac)m(h)25 b(HDU)g(as)g(in)f(the)g(template)i -(FITS)d(\014le,)j(but)d(all)j(the)e(data)h(units)e(will)i(b)s(e)f -(\014lled)g(with)f(zeros.)40 b(The)24 b(template)0 2744 -y(\014le)i(ma)m(y)h(also)g(b)s(e)e(an)h(ASCI)s(I)e(text)j(\014le,)g -(where)f(eac)m(h)h(line)f(\(in)g(general\))i(describ)s(es)d(one)h(FITS) -f(k)m(eyw)m(ord)i(record.)0 2857 y(The)j(format)h(of)f(the)h(ASCI)s(I)e -(template)i(\014le)g(is)f(describ)s(ed)f(in)i(the)f(follo)m(wing)i -(sections.)0 3188 y Ff(11.1)136 b(Detailed)46 b(T)-11 -b(emplate)46 b(Line)f(F)-11 b(ormat)0 3438 y Fj(The)30 -b(format)h(of)f(eac)m(h)i(ASCI)s(I)c(template)k(line)f(closely)h(follo) -m(ws)f(the)g(format)g(of)f(a)h(FITS)f(k)m(eyw)m(ord)g(record:)95 -3682 y Fe(KEYWORD)46 b(=)i(KEYVALUE)d(/)j(COMMENT)0 3926 -y Fj(except)22 b(that)g(free)g(format)f(ma)m(y)h(b)s(e)f(used)f -(\(e.g.,)25 b(the)d(equals)f(sign)h(ma)m(y)f(app)s(ear)g(at)h(an)m(y)g -(p)s(osition)f(in)g(the)h(line\))g(and)0 4039 y(T)-8 -b(AB)34 b(c)m(haracters)g(are)g(allo)m(w)m(ed)h(and)e(are)g(treated)h -(the)g(same)f(as)h(space)f(c)m(haracters.)51 b(The)33 -b(KEYV)-10 b(ALUE)33 b(and)0 4152 y(COMMENT)d(\014elds)g(are)h -(optional.)43 b(The)30 b(equals)h(sign)f(c)m(haracter)j(is)d(also)i -(optional,)g(but)e(it)h(is)f(recommended)0 4264 y(that)42 -b(it)f(b)s(e)g(included)f(for)h(clarit)m(y)-8 b(.)75 -b(An)m(y)41 b(template)i(line)e(that)h(b)s(egins)f(with)f(the)i(p)s -(ound)d('#')i(c)m(haracter)i(is)0 4377 y(ignored)30 b(b)m(y)h(the)f -(template)i(parser)e(and)g(ma)m(y)h(b)s(e)e(use)h(to)h(insert)g(commen) -m(ts)g(in)m(to)g(the)g(template)h(\014le)e(itself.)0 -4538 y(The)c(KEYW)m(ORD)g(name)g(\014eld)g(is)g(limited)h(to)g(8)f(c)m -(haracters)h(in)f(length)h(and)e(only)h(the)g(letters)i(A-Z,)e(digits)h -(0-9,)0 4650 y(and)h(the)g(h)m(yphen)f(and)h(underscore)g(c)m -(haracters)h(ma)m(y)g(b)s(e)f(used,)g(without)h(an)m(y)f(em)m(b)s -(edded)g(spaces.)40 b(Lo)m(w)m(ercase)0 4763 y(letters)22 -b(in)f(the)h(template)g(k)m(eyw)m(ord)g(name)f(will)g(b)s(e)g(con)m(v)m -(erted)i(to)f(upp)s(ercase.)36 b(Leading)22 b(spaces)f(in)g(the)h -(template)0 4876 y(line)k(preceding)g(the)f(k)m(eyw)m(ord)h(name)g(are) -g(generally)h(ignored,)g(except)f(if)g(the)g(\014rst)f(8)h(c)m -(haracters)h(of)f(a)g(template)0 4989 y(line)f(are)h(all)g(blank,)g -(then)f(the)g(en)m(tire)h(line)g(is)f(treated)h(as)f(a)h(FITS)e(commen) -m(t)i(k)m(eyw)m(ord)g(\(with)f(a)h(blank)e(k)m(eyw)m(ord)0 -5102 y(name\))31 b(and)f(is)g(copied)h(v)m(erbatim)g(in)m(to)g(the)g -(FITS)e(header.)0 5262 y(The)37 b(KEYV)-10 b(ALUE)37 -b(\014eld)g(ma)m(y)h(ha)m(v)m(e)g(an)m(y)g(allo)m(w)m(ed)h(FITS)e(data) -h(t)m(yp)s(e:)54 b(c)m(haracter)39 b(string,)h(logical,)h(in)m(teger,)0 -5375 y(real,)28 b(complex)g(in)m(teger,)h(or)d(complex)i(real.)40 -b(In)m(teger)28 b(v)-5 b(alues)27 b(m)m(ust)f(b)s(e)g(within)g(the)h -(allo)m(w)m(ed)i(range)e(of)g(a)g('signed)0 5488 y(long')h(v)-5 -b(ariable;)29 b(some)f(C)e(compilers)i(only)f(suppp)s(ort)e(4-b)m(yte)j -(long)g(in)m(tegers)g(with)f(a)g(range)h(from)e(-2147483648)0 -5601 y(to)31 b(+2147483647,)k(whereas)30 b(other)h(C)f(compilers)h -(supp)s(ort)e(8-b)m(yte)j(in)m(tegers)f(with)f(a)h(range)g(of)g(plus)e -(or)i(min)m(us)0 5714 y(2**63.)1882 5942 y(153)p eop -end -%%Page: 154 162 -TeXDict begin 154 161 bop 0 299 a Fj(154)2250 b Fh(CHAPTER)29 -b(11.)72 b(TEMPLA)-8 b(TE)30 b(FILES)0 555 y Fj(The)23 -b(c)m(haracter)h(string)f(v)-5 b(alues)24 b(need)f(not)g(b)s(e)g -(enclosed)g(in)g(single)h(quote)g(c)m(haracters)g(unless)f(they)g(are)h -(necessary)0 668 y(to)37 b(distinguish)e(the)i(string)f(from)f(a)i -(di\013eren)m(t)g(data)f(t)m(yp)s(e)h(\(e.g.)59 b(2.0)38 -b(is)e(a)g(real)h(but)f('2.0')h(is)f(a)h(string\).)58 -b(The)0 781 y(k)m(eyw)m(ord)38 b(has)g(an)g(unde\014ned)d(\(n)m(ull\))k -(v)-5 b(alue)38 b(if)g(the)g(template)h(record)f(only)g(con)m(tains)h -(blanks)e(follo)m(wing)j(the)0 894 y("=")31 b(or)f(b)s(et)m(w)m(een)h -(the)g("=")g(and)f(the)g("/")i(commen)m(t)f(\014eld)f(delimiter.)0 -1054 y(String)c(k)m(eyw)m(ord)h(v)-5 b(alues)27 b(longer)g(than)f(68)h -(c)m(haracters)h(\(the)f(maxim)m(um)f(length)h(that)g(will)g(\014t)f -(in)g(a)h(single)g(FITS)0 1167 y(k)m(eyw)m(ord)41 b(record\))g(are)g(p) -s(ermitted)f(using)g(the)h(CFITSIO)e(long)i(string)g(con)m(v)m(en)m -(tion.)74 b(They)40 b(can)h(either)g(b)s(e)0 1280 y(sp)s(eci\014ed)28 -b(as)i(a)f(single)h(long)f(line)h(in)e(the)i(template,)h(or)e(b)m(y)f -(using)h(m)m(ultiple)h(lines)f(where)f(the)i(con)m(tin)m(uing)g(lines)0 -1393 y(con)m(tain)i(the)e('CONTINUE')g(k)m(eyw)m(ord,)h(as)g(in)f(this) -g(example:)95 1657 y Fe(LONGKEY)46 b(=)i('This)e(is)h(a)h(long)e -(string)g(value)h(that)f(is)i(contin&')95 1770 y(CONTINUE)94 -b('ued)46 b(over)h(2)g(records')f(/)h(comment)f(field)h(goes)f(here)0 -2035 y Fj(The)29 b(format)h(of)g(template)h(lines)e(with)h(CONTINUE)e -(k)m(eyw)m(ord)i(is)g(v)m(ery)g(strict:)41 b(3)30 b(spaces)g(m)m(ust)f -(follo)m(w)i(CON-)0 2147 y(TINUE)f(and)g(the)g(rest)h(of)f(the)h(line)g -(is)f(copied)h(v)m(erbatim)g(to)g(the)g(FITS)e(\014le.)0 -2308 y(The)i(start)h(of)g(the)f(optional)i(COMMENT)e(\014eld)g(m)m(ust) -h(b)s(e)e(preceded)i(b)m(y)f("/",)i(whic)m(h)e(is)h(used)f(to)h -(separate)g(it)0 2421 y(from)e(the)g(k)m(eyw)m(ord)h(v)-5 -b(alue)30 b(\014eld.)41 b(Exceptions)30 b(are)h(if)f(the)h(KEYW)m(ORD)g -(name)f(\014eld)g(con)m(tains)h(COMMENT,)0 2533 y(HISTOR)-8 -b(Y,)30 b(CONTINUE,)g(or)g(if)g(the)h(\014rst)f(8)g(c)m(haracters)i(of) -f(the)f(template)i(line)f(are)g(blanks.)0 2694 y(More)c(than)f(one)h -(Header-Data)i(Unit)e(\(HDU\))g(ma)m(y)g(b)s(e)f(de\014ned)f(in)h(the)h -(template)h(\014le.)39 b(The)26 b(start)h(of)g(an)f(HDU)0 -2806 y(de\014nition)k(is)g(denoted)h(with)f(a)h(SIMPLE)e(or)i(XTENSION) -e(template)j(line:)0 2967 y(1\))i(SIMPLE)f(b)s(egins)g(a)h(Primary)g -(HDU)g(de\014nition.)50 b(SIMPLE)33 b(ma)m(y)h(only)g(app)s(ear)f(as)h -(the)g(\014rst)f(k)m(eyw)m(ord)h(in)0 3080 y(the)e(template)i(\014le.) -45 b(If)32 b(the)g(template)i(\014le)e(b)s(egins)f(with)h(XTENSION)f -(instead)h(of)g(SIMPLE,)g(then)f(a)i(default)0 3192 y(empt)m(y)d -(Primary)e(HDU)i(is)g(created,)h(and)d(the)i(template)h(is)e(then)g -(assumed)f(to)i(de\014ne)f(the)h(k)m(eyw)m(ords)f(starting)0 -3305 y(with)h(the)h(\014rst)e(extension)i(follo)m(wing)h(the)f(Primary) -f(HDU.)0 3466 y(2\))35 b(XTENSION)e(marks)g(the)i(b)s(eginning)e(of)h -(a)h(new)e(extension)i(HDU)f(de\014nition.)52 b(The)33 -b(previous)h(HDU)h(will)0 3578 y(b)s(e)30 b(closed)h(at)g(this)f(p)s -(oin)m(t)h(and)e(pro)s(cessing)i(of)f(the)h(next)f(extension)h(b)s -(egins.)0 3918 y Ff(11.2)136 b(Auto-indexing)45 b(of)g(Keyw)l(ords)0 -4169 y Fj(If)31 b(a)h(template)g(k)m(eyw)m(ord)g(name)f(ends)g(with)g -(a)g("#")h(c)m(haracter,)i(it)e(is)f(said)g(to)h(b)s(e)f -('auto-indexed'.)44 b(Eac)m(h)32 b("#")0 4282 y(c)m(haracter)i(will)f -(b)s(e)f(replaced)i(b)m(y)e(the)h(curren)m(t)g(in)m(teger)h(index)e(v) --5 b(alue,)34 b(whic)m(h)f(gets)g(reset)h(=)e(1)h(at)h(the)e(start)i -(of)0 4395 y(eac)m(h)h(new)f(HDU)g(in)g(the)g(\014le)g(\(or)g(7)h(in)e -(the)h(sp)s(ecial)h(case)g(of)f(a)g(GR)m(OUP)h(de\014nition\).)51 -b(The)33 b(FIRST)g(indexed)0 4508 y(k)m(eyw)m(ord)c(in)f(eac)m(h)h -(template)h(HDU)f(de\014nition)f(is)g(used)f(as)i(the)f('incremen)m -(tor';)j(eac)m(h)e(subsequen)m(t)f(o)s(ccurrence)0 4620 -y(of)k(this)f(SAME)g(k)m(eyw)m(ord)h(will)g(cause)g(the)g(index)f(v)-5 -b(alue)32 b(to)g(b)s(e)f(incremen)m(ted.)44 b(This)31 -b(b)s(eha)m(vior)g(can)h(b)s(e)f(rather)0 4733 y(subtle,)d(as)g -(illustrated)h(in)e(the)h(follo)m(wing)h(examples)f(in)f(whic)m(h)h -(the)g(TTYPE)e(k)m(eyw)m(ord)i(is)g(the)g(incremen)m(tor)g(in)0 -4846 y(b)s(oth)i(cases:)95 5111 y Fe(TTYPE#)47 b(=)g(TIME)95 -5224 y(TFORM#)g(=)g(1D)95 5337 y(TTYPE#)g(=)g(RATE)95 -5449 y(TFORM#)g(=)g(1E)0 5714 y Fj(will)26 b(create)i(TTYPE1,)e(TF)m -(ORM1,)i(TTYPE2,)f(and)e(TF)m(ORM2)i(k)m(eyw)m(ords.)40 -b(But)26 b(if)g(the)g(template)h(lo)s(oks)f(lik)m(e,)p -eop end -%%Page: 155 163 -TeXDict begin 155 162 bop 0 299 a Fh(11.3.)73 b(TEMPLA)-8 -b(TE)30 b(P)-8 b(ARSER)30 b(DIRECTIVES)1982 b Fj(155)95 -555 y Fe(TTYPE#)47 b(=)g(TIME)95 668 y(TTYPE#)g(=)g(RATE)95 -781 y(TFORM#)g(=)g(1D)95 894 y(TFORM#)g(=)g(1E)0 1202 -y Fj(this)31 b(results)f(in)h(a)g(FITS)f(\014les)h(with)f(TTYPE1,)h -(TTYPE2,)g(TF)m(ORM2,)h(and)e(TF)m(ORM2,)i(whic)m(h)f(is)g(probably)0 -1315 y(not)g(what)f(w)m(as)h(in)m(tended!)0 1706 y Ff(11.3)136 -b(T)-11 b(emplate)45 b(P)l(arser)h(Directiv)l(es)0 1968 -y Fj(In)29 b(addition)i(to)f(the)g(template)i(lines)e(whic)m(h)g -(de\014ne)f(individual)h(k)m(eyw)m(ords,)g(the)g(template)i(parser)d -(recognizes)0 2081 y(3)h(sp)s(ecial)h(directiv)m(es)g(whic)m(h)f(are)g -(eac)m(h)h(preceded)f(b)m(y)f(the)h(bac)m(kslash)h(c)m(haracter:)90 -b Fe(\\include,)45 b(\\group)p Fj(,)29 b(and)48 2194 -y Fe(\\end)p Fj(.)0 2354 y(The)37 b('include')h(directiv)m(e)i(m)m(ust) -d(b)s(e)h(follo)m(w)m(ed)h(b)m(y)f(a)g(\014lename.)63 -b(It)38 b(forces)g(the)g(parser)f(to)i(temp)s(orarily)f(stop)0 -2467 y(reading)d(the)g(curren)m(t)g(template)h(\014le)f(and)f(b)s(egin) -h(reading)g(the)g(include)f(\014le.)55 b(Once)35 b(the)g(parser)f(reac) -m(hes)i(the)0 2579 y(end)f(of)h(the)g(include)f(\014le)h(it)g(con)m -(tin)m(ues)g(parsing)g(the)f(curren)m(t)h(template)h(\014le.)56 -b(Include)35 b(\014les)h(can)g(b)s(e)f(nested,)0 2692 -y(and)30 b(HDU)h(de\014nitions)f(can)g(span)g(m)m(ultiple)h(template)h -(\014les.)0 2853 y(The)f(start)h(of)g(a)g(GR)m(OUP)h(de\014nition)e(is) -h(denoted)g(with)f(the)h('group')g(directiv)m(e,)h(and)f(the)f(end)h -(of)f(a)i(GR)m(OUP)0 2965 y(de\014nition)k(is)h(denoted)f(with)g(the)h -('end')f(directiv)m(e.)63 b(Eac)m(h)39 b(GR)m(OUP)e(con)m(tains)i(0)f -(or)f(more)h(mem)m(b)s(er)f(blo)s(c)m(ks)0 3078 y(\(HDUs)44 -b(or)f(GR)m(OUPs\).)79 b(Mem)m(b)s(er)42 b(blo)s(c)m(ks)i(of)f(t)m(yp)s -(e)g(GR)m(OUP)g(can)g(con)m(tain)h(their)f(o)m(wn)g(mem)m(b)s(er)f(blo) -s(c)m(ks.)0 3191 y(The)32 b(GR)m(OUP)g(de\014nition)g(itself)h(o)s -(ccupies)g(one)f(FITS)g(\014le)g(HDU)h(of)f(sp)s(ecial)h(t)m(yp)s(e)f -(\(GR)m(OUP)h(HDU\),)h(so)e(if)h(a)0 3304 y(template)f(sp)s(eci\014es)e -(1)h(group)e(with)h(1)h(mem)m(b)s(er)f(HDU)h(lik)m(e:)0 -3613 y Fe(\\group)0 3725 y(grpdescr)46 b(=)h('demo')0 -3838 y(xtension)f(bintable)0 3951 y(#)h(this)g(bintable)f(has)h(0)g -(cols,)f(0)i(rows)0 4064 y(\\end)0 4373 y Fj(then)30 -b(the)h(parser)e(creates)j(a)f(FITS)f(\014le)g(with)g(3)h(HDUs)g(:)0 -4681 y Fe(1\))47 b(dummy)g(PHDU)0 4794 y(2\))g(GROUP)g(HDU)f(\(has)h(1) -h(member,)d(which)i(is)g(bintable)e(in)j(HDU)f(number)f(3\))0 -4907 y(3\))h(bintable)f(\(member)g(of)h(GROUP)f(in)h(HDU)g(number)f -(2\))0 5215 y Fj(T)-8 b(ec)m(hnically)32 b(sp)s(eaking,)e(the)f(GR)m -(OUP)i(HDU)f(is)g(a)g(BINT)-8 b(ABLE)30 b(with)g(6)g(columns.)40 -b(Applications)31 b(can)f(de\014ne)0 5328 y(additional)23 -b(columns)f(in)f(a)i(GR)m(OUP)f(HDU)h(using)f(TF)m(ORMn)f(and)h(TTYPEn) -f(\(where)g(n)h(is)g(7,)i(8,)h(....\))39 b(k)m(eyw)m(ords)0 -5441 y(or)30 b(their)h(auto-indexing)g(equiv)-5 b(alen)m(ts.)0 -5601 y(F)d(or)26 b(a)f(more)g(complicated)h(example)f(of)g(a)h -(template)g(\014le)f(using)f(the)h(group)f(directiv)m(es,)k(lo)s(ok)d -(at)g(the)g(sample.tpl)0 5714 y(\014le)30 b(that)h(is)g(included)e(in)i -(the)f(CFITSIO)f(distribution.)p eop end -%%Page: 156 164 -TeXDict begin 156 163 bop 0 299 a Fj(156)2250 b Fh(CHAPTER)29 -b(11.)72 b(TEMPLA)-8 b(TE)30 b(FILES)0 555 y Ff(11.4)136 -b(F)-11 b(ormal)45 b(T)-11 b(emplate)46 b(Syn)l(tax)0 -805 y Fj(The)30 b(template)i(syn)m(tax)f(can)f(formally)h(b)s(e)f -(de\014ned)f(as)i(follo)m(ws:)191 1063 y Fe(TEMPLATE)45 -b(=)j(BLOCK)e([)i(BLOCK)e(...)h(])334 1289 y(BLOCK)f(=)i({)f(HDU)g(|)h -(GROUP)e(})334 1515 y(GROUP)g(=)i(\\GROUP)e([)h(BLOCK)g(...)g(])g -(\\END)430 1741 y(HDU)f(=)i(XTENSION)d([)j(LINE)f(...)f(])i({)f -(XTENSION)f(|)h(\\GROUP)f(|)i(\\END)f(|)g(EOF)g(})382 -1967 y(LINE)f(=)i([)f(KEYWORD)f([)i(=)f(])h(])f([)g(VALUE)g(])g([)h(/)f -(COMMENT)f(])191 2192 y(X)h(...)238 b(-)48 b(X)f(can)g(be)g(present)f -(1)h(or)h(more)e(times)191 2305 y({)h(X)h(|)f(Y)h(})f(-)h(X)f(or)g(Y) -191 2418 y([)g(X)h(])238 b(-)48 b(X)f(is)g(optional)0 -2676 y Fj(A)m(t)34 b(the)f(topmost)g(lev)m(el,)i(the)e(template)i -(de\014nes)c(1)j(or)e(more)h(template)h(blo)s(c)m(ks.)49 -b(Blo)s(c)m(ks)34 b(can)f(b)s(e)f(either)h(HDU)0 2789 -y(\(Header)27 b(Data)h(Unit\))g(or)e(a)h(GR)m(OUP)-8 -b(.)28 b(F)-8 b(or)27 b(eac)m(h)g(blo)s(c)m(k)g(the)g(parser)f(creates) -i(1)f(\(or)g(more)f(for)h(GR)m(OUPs\))g(FITS)0 2902 y(\014le)j(HDUs.)0 -3235 y Ff(11.5)136 b(Errors)0 3485 y Fj(In)24 b(general)h(the)f(\014ts) -p 692 3485 28 4 v 33 w(execute)p 1019 3485 V 34 w(template\(\))i -(function)e(tries)h(to)g(b)s(e)f(as)g(atomic)i(as)f(p)s(ossible,)g(so)f -(either)h(ev)m(erything)0 3598 y(is)f(done)g(or)g(nothing)f(is)h(done.) -39 b(If)23 b(an)h(error)f(o)s(ccurs)h(during)f(parsing)g(of)h(the)g -(template,)j(\014ts)p 3125 3598 V 33 w(execute)p 3452 -3598 V 34 w(template\(\))0 3711 y(will)k(\(try)g(to\))h(delete)g(the)f -(top)g(lev)m(el)h(BLOCK)e(\(with)h(all)g(its)h(c)m(hildren)e(if)h(an)m -(y\))g(in)g(whic)m(h)f(the)h(error)f(o)s(ccurred,)0 3824 -y(then)g(it)h(will)g(stop)f(reading)h(the)f(template)i(\014le)e(and)g -(it)h(will)g(return)e(with)h(an)g(error.)0 4158 y Ff(11.6)136 -b(Examples)0 4408 y Fj(1.)54 b(This)34 b(template)i(\014le)f(will)g -(create)h(a)f(200)h(x)e(300)i(pixel)f(image,)j(with)c(4-b)m(yte)i(in)m -(teger)g(pixel)f(v)-5 b(alues,)36 b(in)f(the)0 4521 y(primary)29 -b(HDU:)95 4779 y Fe(SIMPLE)47 b(=)g(T)95 4891 y(BITPIX)g(=)g(32)95 -5004 y(NAXIS)g(=)g(2)239 b(/)47 b(number)f(of)h(dimensions)95 -5117 y(NAXIS1)g(=)g(100)95 b(/)47 b(length)f(of)h(first)g(axis)95 -5230 y(NAXIS2)g(=)g(200)95 b(/)47 b(length)f(of)h(second)f(axis)95 -5343 y(OBJECT)h(=)g(NGC)g(253)g(/)g(name)g(of)g(observed)f(object)0 -5601 y Fj(The)35 b(allo)m(w)m(ed)i(v)-5 b(alues)36 b(of)f(BITPIX)g(are) -h(8,)h(16,)h(32,)g(-32,)g(or)d(-64,)j(represen)m(ting,)f(resp)s(ectiv)m -(ely)-8 b(,)39 b(8-bit)d(in)m(teger,)0 5714 y(16-bit)c(in)m(teger,)g -(32-bit)f(in)m(teger,)h(32-bit)g(\015oating)f(p)s(oin)m(t,)g(or)f(64)h -(bit)g(\015oating)g(p)s(oin)m(t)f(pixels.)p eop end -%%Page: 157 165 -TeXDict begin 157 164 bop 0 299 a Fh(11.6.)73 b(EXAMPLES)2993 -b Fj(157)0 555 y(2.)39 b(T)-8 b(o)23 b(create)h(a)f(FITS)e(table,)26 -b(the)c(template)i(\014rst)e(needs)g(to)i(include)e(XTENSION)g(=)g(T)-8 -b(ABLE)23 b(or)f(BINT)-8 b(ABLE)0 668 y(to)31 b(de\014ne)e(whether)g -(it)h(is)g(an)f(ASCI)s(I)g(or)g(binary)g(table,)i(and)f(NAXIS2)g(to)g -(de\014ne)f(the)h(n)m(um)m(b)s(er)f(of)h(ro)m(ws)f(in)h(the)0 -781 y(table.)50 b(Tw)m(o)34 b(template)g(lines)g(are)g(then)f(needed)f -(to)i(de\014ne)f(the)g(name)h(\(TTYPEn\))e(and)h(FITS)g(data)h(format)0 -894 y(\(TF)m(ORMn\))d(of)f(the)h(columns,)f(as)h(in)f(this)g(example:) -95 1154 y Fe(xtension)46 b(=)h(bintable)95 1267 y(naxis2)g(=)g(40)95 -1380 y(ttype#)g(=)g(Name)95 1492 y(tform#)g(=)g(10a)95 -1605 y(ttype#)g(=)g(Npoints)95 1718 y(tform#)g(=)g(j)95 -1831 y(ttype#)g(=)g(Rate)95 1944 y(tunit#)g(=)g(counts/s)95 -2057 y(tform#)g(=)g(e)0 2317 y Fj(The)26 b(ab)s(o)m(v)m(e)j(example)e -(de\014nes)f(a)i(n)m(ull)f(primary)f(arra)m(y)h(follo)m(w)m(ed)i(b)m(y) -e(a)g(40-ro)m(w)h(binary)e(table)i(extension)g(with)f(3)0 -2430 y(columns)h(called)h('Name',)h('Np)s(oin)m(ts',)f(and)f('Rate',)i -(with)e(data)h(formats)f(of)g('10A')i(\(ASCI)s(I)d(c)m(haracter)i -(string\),)0 2543 y('1J')k(\(in)m(teger\))i(and)d('1E')i(\(\015oating)f -(p)s(oin)m(t\),)h(resp)s(ectiv)m(ely)-8 b(.)50 b(Note)34 -b(that)f(the)g(other)g(required)f(FITS)g(k)m(eyw)m(ords)0 -2655 y(\(BITPIX,)37 b(NAXIS,)g(NAXIS1,)h(PCOUNT,)e(GCOUNT,)h(TFIELDS,)f -(and)g(END\))h(do)g(not)g(need)f(to)h(b)s(e)f(ex-)0 2768 -y(plicitly)j(de\014ned)d(in)i(the)f(template)i(b)s(ecause)f(their)g(v) --5 b(alues)38 b(can)g(b)s(e)f(inferred)f(from)i(the)f(other)h(k)m(eyw)m -(ords)g(in)0 2881 y(the)d(template.)55 b(This)34 b(example)i(also)g -(illustrates)f(that)h(the)f(templates)h(are)f(generally)h -(case-insensitiv)m(e)h(\(the)0 2994 y(k)m(eyw)m(ord)29 -b(names)g(and)g(TF)m(ORMn)f(v)-5 b(alues)30 b(are)f(con)m(v)m(erted)i -(to)e(upp)s(er-case)g(in)f(the)h(FITS)g(\014le\))g(and)f(that)i(string) -0 3107 y(k)m(eyw)m(ord)h(v)-5 b(alues)31 b(generally)g(do)f(not)h(need) -f(to)h(b)s(e)f(enclosed)h(in)f(quotes.)p eop end -%%Page: 158 166 -TeXDict begin 158 165 bop 0 299 a Fj(158)2250 b Fh(CHAPTER)29 -b(11.)72 b(TEMPLA)-8 b(TE)30 b(FILES)p eop end -%%Page: 159 167 -TeXDict begin 159 166 bop 0 1225 a Fg(Chapter)65 b(12)0 -1687 y Fm(Lo)6 b(cal)78 b(FITS)e(Con)-6 b(v)g(en)g(tions)0 -2180 y Fj(CFITSIO)29 b(supp)s(orts)g(sev)m(eral)j(lo)s(cal)g(FITS)e -(con)m(v)m(en)m(tions)i(whic)m(h)f(are)g(not)g(de\014ned)e(in)i(the)f -(o\016cial)j(FITS)d(stan-)0 2293 y(dard)43 b(and)g(whic)m(h)g(are)h -(not)g(necessarily)g(recognized)h(or)f(supp)s(orted)e(b)m(y)h(other)h -(FITS)f(soft)m(w)m(are)i(pac)m(k)-5 b(ages.)0 2406 y(Programmers)36 -b(should)f(b)s(e)g(cautious)i(ab)s(out)e(using)h(these)g(features,)i -(esp)s(ecially)f(if)f(the)g(FITS)f(\014les)h(that)h(are)0 -2518 y(pro)s(duced)31 b(are)i(exp)s(ected)g(to)g(b)s(e)f(pro)s(cessed)g -(b)m(y)h(other)f(soft)m(w)m(are)i(systems)f(whic)m(h)f(do)h(not)f(use)h -(the)f(CFITSIO)0 2631 y(in)m(terface.)0 2990 y Ff(12.1)136 -b(64-Bit)45 b(Long)g(In)l(tegers)0 3246 y Fj(CFITSIO)37 -b(supp)s(orts)g(reading)i(and)f(writing)h(FITS)f(images)i(or)f(table)h -(columns)e(con)m(taining)i(64-bit)h(in)m(teger)0 3359 -y(data)26 b(v)-5 b(alues.)40 b(Supp)s(ort)23 b(for)i(64-bit)i(in)m -(tegers)g(w)m(as)f(added)e(to)j(the)e(o\016cial)i(FITS)e(Standard)f(in) -i(Decem)m(b)s(er)g(2005.)0 3472 y(FITS)g(64-bit)i(images)g(ha)m(v)m(e)g -(BITPIX)e(=)h(64,)h(and)e(the)h(64-bit)h(binary)e(table)i(columns)f(ha) -m(v)m(e)h(TF)m(ORMn)e(=)h('K'.)0 3584 y(CFITSIO)35 b(also)i(supp)s -(orts)e(the)i('Q')f(v)-5 b(ariable-length)38 b(arra)m(y)f(table)h -(column)e(format)h(whic)m(h)f(is)g(analogous)i(to)0 3697 -y(the)31 b('P')f(column)g(format)h(except)g(that)g(the)g(arra)m(y)g -(descriptor)f(is)h(stored)f(as)h(a)f(pair)h(of)f(64-bit)i(in)m(tegers.) -0 3858 y(F)-8 b(or)33 b(the)f(con)m(v)m(enience)i(of)f(C)e -(programmers,)h(the)h(\014tsio.h)f(include)g(\014le)g(de\014nes)f -(\(with)h(a)h(t)m(yp)s(edef)f(statemen)m(t\))0 3970 y(the)39 -b('LONGLONG')g(datat)m(yp)s(e)h(to)f(b)s(e)f(equiv)-5 -b(alen)m(t)40 b(to)f(an)g(appropriate)g(64-bit)h(in)m(teger)g(datat)m -(yp)s(e)f(on)g(eac)m(h)0 4083 y(platform.)g(Since)27 -b(there)f(is)g(curren)m(tly)g(no)g(univ)m(ersal)h(standard)e(for)h(the) -g(name)g(of)h(the)f(64-bit)h(in)m(teger)h(datat)m(yp)s(e)0 -4196 y(\(it)33 b(migh)m(t)f(b)s(e)f(de\014ned)g(as)h('long)g(long',)i -('long',)f(or)f(')p 1832 4196 28 4 v 1865 4196 V 66 w(in)m(t64')h(dep)s -(ending)d(on)i(the)g(platform\))g(C)g(programmers)0 4309 -y(ma)m(y)24 b(prefer)f(to)i(use)e(the)h('LONGLONG')h(datat)m(yp)s(e)f -(when)f(declaring)i(or)e(allo)s(cating)j(64-bit)f(in)m(teger)h(quan)m -(tities)0 4422 y(when)33 b(writing)h(co)s(de)g(whic)m(h)f(needs)h(to)h -(run)d(on)i(m)m(ultiple)g(platforms.)52 b(Note)35 b(that)f(CFITSIO)f -(will)h(implicitly)0 4535 y(con)m(v)m(ert)h(the)e(datat)m(yp)s(e)h -(when)f(reading)g(or)g(writing)h(FITS)e(64-bit)j(in)m(teger)f(images)h -(and)d(columns)h(with)g(data)0 4648 y(arra)m(ys)40 b(of)h(a)f -(di\013eren)m(t)h(in)m(teger)g(or)f(\015oating)h(p)s(oin)m(t)f(datat)m -(yp)s(e,)k(but)c(there)g(is)g(an)g(increased)g(risk)g(of)g(loss)h(of)0 -4761 y(n)m(umerical)31 b(precision)f(or)h(n)m(umerical)g(o)m(v)m -(er\015o)m(w)h(in)e(this)g(case.)0 5120 y Ff(12.2)136 -b(Long)44 b(String)i(Keyw)l(ord)f(V)-11 b(alues.)0 5375 -y Fj(The)43 b(length)i(of)f(a)g(standard)g(FITS)f(string)h(k)m(eyw)m -(ord)g(is)g(limited)h(to)g(68)f(c)m(haracters)i(b)s(ecause)e(it)g(m)m -(ust)g(\014t)0 5488 y(en)m(tirely)35 b(within)e(a)h(single)h(FITS)e -(header)g(k)m(eyw)m(ord)i(record.)50 b(In)33 b(some)i(instances)f(it)g -(is)g(necessary)g(to)h(enco)s(de)0 5601 y(strings)29 -b(longer)i(than)e(this)g(limit,)i(so)f(CFITSIO)e(supp)s(orts)g(a)h(lo)s -(cal)i(con)m(v)m(en)m(tion)h(in)d(whic)m(h)h(the)f(string)h(v)-5 -b(alue)30 b(is)0 5714 y(con)m(tin)m(ued)36 b(o)m(v)m(er)g(m)m(ultiple)f -(k)m(eyw)m(ords.)55 b(This)34 b(con)m(tin)m(uation)i(con)m(v)m(en)m -(tion)h(uses)e(an)f(amp)s(ersand)g(c)m(haracter)i(at)1882 -5942 y(159)p eop end -%%Page: 160 168 -TeXDict begin 160 167 bop 0 299 a Fj(160)1741 b Fh(CHAPTER)30 -b(12.)112 b(LOCAL)29 b(FITS)h(CONVENTIONS)0 555 y Fj(the)c(end)f(of)h -(eac)m(h)g(substring)f(to)h(indicate)h(that)f(it)h(is)e(con)m(tin)m -(ued)i(on)e(the)h(next)g(k)m(eyw)m(ord,)h(and)e(the)h(con)m(tin)m -(uation)0 668 y(k)m(eyw)m(ords)40 b(all)h(ha)m(v)m(e)g(the)f(name)g -(CONTINUE)f(without)h(an)g(equal)g(sign)g(in)g(column)g(9.)69 -b(The)40 b(string)f(v)-5 b(alue)0 781 y(ma)m(y)33 b(b)s(e)f(con)m(tin)m -(ued)h(in)g(this)f(w)m(a)m(y)h(o)m(v)m(er)h(as)f(man)m(y)g(additional)g -(CONTINUE)f(k)m(eyw)m(ords)h(as)f(is)h(required.)46 b(The)0 -894 y(follo)m(wing)37 b(lines)e(illustrate)h(this)f(con)m(tin)m(uation) -i(con)m(v)m(en)m(tion)h(whic)m(h)c(is)i(used)e(in)h(the)g(v)-5 -b(alue)36 b(of)f(the)g(STRKEY)0 1007 y(k)m(eyw)m(ord:)0 -1297 y Fe(LONGSTRN=)45 b('OGIP)i(1.0')189 b(/)48 b(The)f(OGIP)f(Long)h -(String)f(Convention)f(may)i(be)g(used.)0 1410 y(STRKEY)94 -b(=)47 b('This)g(is)g(a)g(very)g(long)g(string)f(keyword&')93 -b(/)47 b(Optional)f(Comment)0 1523 y(CONTINUE)93 b(')48 -b(value)e(that)h(is)g(continued)e(over)i(3)g(keywords)f(in)h(the)g(&)95 -b(')0 1636 y(CONTINUE)e('FITS)47 b(header.')e(/)j(This)e(is)h(another)f -(optional)g(comment.)0 1926 y Fj(It)29 b(is)g(recommended)f(that)h(the) -g(LONGSTRN)f(k)m(eyw)m(ord,)i(as)f(sho)m(wn)f(here,)h(alw)m(a)m(ys)i(b) -s(e)d(included)g(in)g(an)m(y)h(HDU)0 2039 y(that)i(uses)f(this)g -(longstring)h(con)m(v)m(en)m(tion)i(as)e(a)f(w)m(arning)h(to)g(an)m(y)g -(soft)m(w)m(are)g(that)g(m)m(ust)g(read)f(the)h(k)m(eyw)m(ords.)41 -b(A)0 2152 y(routine)d(called)g(\014ts)p 712 2152 28 -4 v 33 w(write)p 947 2152 V 33 w(k)m(ey)p 1113 2152 V -33 w(longw)m(arn)g(has)f(b)s(een)g(pro)m(vided)g(in)h(CFITSIO)d(to)k -(write)e(this)h(k)m(eyw)m(ord)g(if)f(it)0 2265 y(do)s(es)30 -b(not)h(already)g(exist.)0 2425 y(This)f(long)h(string)f(con)m(v)m(en)m -(tion)i(is)f(supp)s(orted)d(b)m(y)j(the)f(follo)m(wing)i(CFITSIO)d -(routines:)191 2716 y Fe(fits_write_key_longstr)89 b(-)48 -b(write)e(a)i(long)e(string)g(keyword)g(value)191 2829 -y(fits_insert_key_longstr)41 b(-)48 b(insert)e(a)h(long)g(string)f -(keyword)g(value)191 2942 y(fits_modify_key_longstr)41 -b(-)48 b(modify)e(a)h(long)g(string)f(keyword)g(value)191 -3054 y(fits_update_key_longstr)41 b(-)48 b(modify)e(a)h(long)g(string)f -(keyword)g(value)191 3167 y(fits_read_key_longstr)137 -b(-)48 b(read)94 b(a)48 b(long)e(string)g(keyword)g(value)191 -3280 y(fits_delete_key)425 b(-)48 b(delete)e(a)h(keyword)0 -3571 y Fj(The)36 b(\014ts)p 320 3571 V 32 w(read)p 524 -3571 V 33 w(k)m(ey)p 690 3571 V 34 w(longstr)g(routine)h(is)f(unique)f -(among)i(all)h(the)e(CFITSIO)f(routines)h(in)g(that)h(it)g(in)m -(ternally)0 3684 y(allo)s(cates)f(memory)d(for)h(the)f(long)h(string)g -(v)-5 b(alue;)36 b(all)e(the)g(other)g(CFITSIO)e(routines)h(that)h -(deal)g(with)g(arra)m(ys)0 3797 y(require)39 b(that)h(the)g(calling)h -(program)e(pre-allo)s(cate)j(adequate)e(space)g(to)g(hold)f(the)h(arra) -m(y)g(of)f(data.)69 b(Conse-)0 3909 y(quen)m(tly)-8 b(,)31 -b(programs)f(whic)m(h)g(use)g(the)g(\014ts)p 1443 3909 -V 32 w(read)p 1647 3909 V 33 w(k)m(ey)p 1813 3909 V 34 -w(longstr)g(routine)g(m)m(ust)g(b)s(e)g(careful)g(to)h(free)g(the)f -(allo)s(cated)0 4022 y(memory)g(for)g(the)h(string)f(when)g(it)h(is)f -(no)g(longer)h(needed.)0 4183 y(The)f(follo)m(wing)i(2)e(routines)h -(also)g(ha)m(v)m(e)h(limited)f(supp)s(ort)d(for)i(this)h(long)g(string) -f(con)m(v)m(en)m(tion,)286 4473 y Fe(fits_modify_key_str)43 -b(-)k(modify)f(an)i(existing)d(string)h(keyword)g(value)286 -4586 y(fits_update_key_str)d(-)k(update)f(a)i(string)e(keyword)g(value) -0 4876 y Fj(in)24 b(that)h(they)f(will)h(correctly)g(o)m(v)m(erwrite)h -(an)e(existing)h(long)g(string)f(v)-5 b(alue,)27 b(but)c(the)h(new)g -(string)g(v)-5 b(alue)25 b(is)f(limited)0 4989 y(to)31 -b(a)g(maxim)m(um)f(of)h(68)g(c)m(haracters)h(in)e(length.)0 -5149 y(The)f(more)h(commonly)h(used)e(CFITSIO)f(routines)i(to)g(write)g -(string)g(v)-5 b(alued)30 b(k)m(eyw)m(ords)g(\(\014ts)p -3254 5149 V 33 w(up)s(date)p 3563 5149 V 32 w(k)m(ey)h(and)0 -5262 y(\014ts)p 127 5262 V 32 w(write)p 361 5262 V 33 -w(k)m(ey\))j(do)e(not)h(supp)s(ort)d(this)i(long)h(string)g(con)m(v)m -(en)m(tion)h(and)e(only)g(supp)s(ort)f(strings)h(up)f(to)i(68)g(c)m -(har-)0 5375 y(acters)g(in)f(length.)48 b(This)31 b(has)h(b)s(een)g -(done)g(delib)s(erately)h(to)g(prev)m(en)m(t)g(programs)f(from)g(inadv) -m(erten)m(tly)i(writing)0 5488 y(k)m(eyw)m(ords)25 b(using)f(this)h -(non-standard)e(con)m(v)m(en)m(tion)k(without)e(the)g(explicit)h(in)m -(ten)m(t)g(of)f(the)f(programmer)h(or)f(user.)0 5601 -y(The)36 b(\014ts)p 320 5601 V 32 w(write)p 554 5601 -V 33 w(k)m(ey)p 720 5601 V 34 w(longstr)h(routine)f(m)m(ust)h(b)s(e)f -(called)i(instead)e(to)i(write)e(long)h(strings.)59 b(This)36 -b(routine)h(can)0 5714 y(also)31 b(b)s(e)f(used)g(to)h(write)f -(ordinary)g(string)g(v)-5 b(alues)31 b(less)g(than)f(68)h(c)m -(haracters)h(in)e(length.)p eop end -%%Page: 161 169 -TeXDict begin 161 168 bop 0 299 a Fh(12.3.)73 b(ARRA)-8 -b(YS)30 b(OF)h(FIXED-LENGTH)g(STRINGS)e(IN)h(BINAR)-8 -b(Y)32 b(T)-8 b(ABLES)871 b Fj(161)0 555 y Ff(12.3)136 -b(Arra)l(ys)45 b(of)g(Fixed-Length)g(Strings)g(in)g(Binary)f(T)-11 -b(ables)0 807 y Fj(CFITSIO)25 b(supp)s(orts)g(2)i(w)m(a)m(ys)g(to)g(sp) -s(ecify)f(that)i(a)f(c)m(haracter)h(column)e(in)g(a)h(binary)f(table)i -(con)m(tains)f(an)g(arra)m(y)g(of)0 920 y(\014xed-length)32 -b(strings.)46 b(The)32 b(\014rst)f(w)m(a)m(y)-8 b(,)34 -b(whic)m(h)e(is)g(o\016cially)i(supp)s(orted)c(b)m(y)i(the)h(FITS)e -(Standard)g(do)s(cumen)m(t,)0 1033 y(uses)38 b(the)g(TDIMn)g(k)m(eyw)m -(ord.)65 b(F)-8 b(or)39 b(example,)i(if)d(TF)m(ORMn)g(=)g('60A')h(and)f -(TDIMn)g(=)g('\(12,5\)')i(then)e(that)0 1146 y(column)30 -b(will)h(b)s(e)f(in)m(terpreted)g(as)h(con)m(taining)h(an)e(arra)m(y)h -(of)g(5)f(strings,)h(eac)m(h)g(12)g(c)m(haracters)h(long.)0 -1306 y(CFITSIO)j(also)j(supp)s(orts)c(a)j(lo)s(cal)h(con)m(v)m(en)m -(tion)h(for)d(the)h(format)g(of)g(the)f(TF)m(ORMn)h(k)m(eyw)m(ord)g(v) --5 b(alue)37 b(of)g(the)0 1419 y(form)42 b('rAw')g(where)g('r')g(is)h -(an)f(in)m(teger)i(sp)s(ecifying)e(the)g(total)j(width)c(in)h(c)m -(haracters)i(of)f(the)f(column,)k(and)0 1532 y('w')36 -b(is)g(an)g(in)m(teger)h(sp)s(ecifying)f(the)g(\(\014xed\))g(length)h -(of)f(an)g(individual)f(unit)h(string)f(within)h(the)g(v)m(ector.)59 -b(F)-8 b(or)0 1644 y(example,)29 b(TF)m(ORM1)f(=)f('120A10')j(w)m(ould) -d(indicate)h(that)g(the)f(binary)g(table)h(column)f(is)g(120)i(c)m -(haracters)f(wide)0 1757 y(and)42 b(consists)h(of)f(12)h(10-c)m -(haracter)i(length)e(strings.)77 b(This)41 b(con)m(v)m(en)m(tion)k(is)d -(recognized)i(b)m(y)e(the)g(CFITSIO)0 1870 y(routines)26 -b(that)h(read)e(or)h(write)h(strings)e(in)h(binary)f(tables.)40 -b(The)26 b(Binary)g(T)-8 b(able)27 b(de\014nition)e(do)s(cumen)m(t)h -(sp)s(eci\014es)0 1983 y(that)i(other)f(optional)h(c)m(haracters)h(ma)m -(y)e(follo)m(w)i(the)e(data)h(t)m(yp)s(e)f(co)s(de)g(in)g(the)g(TF)m -(ORM)h(k)m(eyw)m(ord,)g(so)g(this)f(lo)s(cal)0 2096 y(con)m(v)m(en)m -(tion)f(is)d(in)h(compliance)h(with)e(the)h(FITS)e(standard)h(although) -h(other)g(FITS)f(readers)g(ma)m(y)h(not)g(recognize)0 -2209 y(this)30 b(con)m(v)m(en)m(tion.)0 2550 y Ff(12.4)136 -b(Keyw)l(ord)45 b(Units)h(Strings)0 2801 y Fj(One)37 -b(limitation)j(of)d(the)h(curren)m(t)g(FITS)e(Standard)h(is)h(that)g -(it)g(do)s(es)f(not)h(de\014ne)f(a)h(sp)s(eci\014c)f(con)m(v)m(en)m -(tion)j(for)0 2914 y(recording)30 b(the)g(ph)m(ysical)h(units)f(of)g(a) -g(k)m(eyw)m(ord)h(v)-5 b(alue.)41 b(The)30 b(TUNITn)f(k)m(eyw)m(ord)h -(can)g(b)s(e)g(used)f(to)i(sp)s(ecify)f(the)0 3027 y(ph)m(ysical)36 -b(units)f(of)g(the)h(v)-5 b(alues)36 b(in)f(a)g(table)i(column,)f(but)f -(there)g(is)h(no)f(analogous)i(con)m(v)m(en)m(tion)g(for)e(k)m(eyw)m -(ord)0 3140 y(v)-5 b(alues.)42 b(The)30 b(commen)m(t)h(\014eld)g(of)f -(the)h(k)m(eyw)m(ord)g(is)g(often)g(used)f(for)g(this)g(purp)s(ose,)g -(but)f(the)i(units)f(are)h(usually)0 3253 y(not)g(sp)s(eci\014ed)e(in)h -(a)h(w)m(ell)g(de\014ned)f(format)g(that)h(FITS)f(readers)g(can)h -(easily)g(recognize)h(and)e(extract.)0 3413 y(T)-8 b(o)27 -b(solv)m(e)i(this)d(problem,)i(CFITSIO)d(uses)i(a)g(lo)s(cal)h(con)m(v) -m(en)m(tion)h(in)e(whic)m(h)f(the)i(k)m(eyw)m(ord)f(units)f(are)i -(enclosed)f(in)0 3526 y(square)20 b(brac)m(k)m(ets)j(as)e(the)f -(\014rst)g(tok)m(en)i(in)f(the)f(k)m(eyw)m(ord)i(commen)m(t)f(\014eld;) -j(more)d(sp)s(eci\014cally)-8 b(,)24 b(the)d(op)s(ening)f(square)0 -3639 y(brac)m(k)m(et)28 b(immediately)g(follo)m(ws)f(the)g(slash)f('/') -h(commen)m(t)h(\014eld)e(delimiter)h(and)f(a)g(single)h(space)g(c)m -(haracter.)41 b(The)0 3752 y(follo)m(wing)32 b(examples)f(illustrate)g -(k)m(eyw)m(ords)g(that)g(use)f(this)g(con)m(v)m(en)m(tion:)0 -4018 y Fe(EXPOSURE=)713 b(1800.0)47 b(/)g([s])g(elapsed)f(exposure)f -(time)0 4131 y(V_HELIO)h(=)763 b(16.23)47 b(/)g([km)g(s**\(-1\)])e -(heliocentric)g(velocity)0 4244 y(LAMBDA)94 b(=)763 b(5400.)47 -b(/)g([angstrom])e(central)h(wavelength)0 4357 y(FLUX)190 -b(=)47 b(4.9033487787637465E-30)42 b(/)47 b([J/cm**2/s])e(average)h -(flux)0 4622 y Fj(In)28 b(general,)h(the)g(units)e(named)h(in)g(the)h -(IA)m(U\(1988\))i(St)m(yle)e(Guide)f(are)h(recommended,)f(with)g(the)h -(main)f(excep-)0 4735 y(tion)j(that)g(the)f(preferred)g(unit)f(for)i -(angle)g(is)f('deg')i(for)e(degrees.)0 4896 y(The)38 -b(\014ts)p 322 4896 28 4 v 33 w(read)p 527 4896 V 33 -w(k)m(ey)p 693 4896 V 33 w(unit)h(and)f(\014ts)p 1234 -4896 V 32 w(write)p 1468 4896 V 33 w(k)m(ey)p 1634 4896 -V 34 w(unit)g(routines)h(in)g(CFITSIO)e(read)i(and)f(write,)k(resp)s -(ectiv)m(ely)-8 b(,)0 5008 y(the)31 b(k)m(eyw)m(ord)f(unit)g(strings)h -(in)f(an)g(existing)h(k)m(eyw)m(ord.)0 5349 y Ff(12.5)136 -b(HIERAR)l(CH)46 b(Con)l(v)l(en)l(tion)g(for)f(Extended)h(Keyw)l(ord)f -(Names)0 5601 y Fj(CFITSIO)c(supp)s(orts)g(the)i(HIERAR)m(CH)g(k)m(eyw) -m(ord)g(con)m(v)m(en)m(tion)i(whic)m(h)e(allo)m(ws)h(k)m(eyw)m(ord)f -(names)g(that)h(are)0 5714 y(longer)34 b(then)e(8)i(c)m(haracters)g -(and)f(ma)m(y)h(con)m(tain)g(the)f(full)g(range)g(of)h(prin)m(table)f -(ASCI)s(I)e(text)j(c)m(haracters.)51 b(This)p eop end -%%Page: 162 170 -TeXDict begin 162 169 bop 0 299 a Fj(162)1741 b Fh(CHAPTER)30 -b(12.)112 b(LOCAL)29 b(FITS)h(CONVENTIONS)0 555 y Fj(con)m(v)m(en)m -(tion)39 b(w)m(as)f(dev)m(elop)s(ed)f(at)h(the)f(Europ)s(ean)f -(Southern)g(Observ)-5 b(atory)37 b(\(ESO\))f(to)i(supp)s(ort)d(hierarc) -m(hical)0 668 y(FITS)30 b(k)m(eyw)m(ord)g(suc)m(h)h(as:)0 -925 y Fe(HIERARCH)46 b(ESO)g(INS)h(FOCU)g(POS)g(=)g(-0.00002500)e(/)j -(Focus)e(position)0 1182 y Fj(Basically)-8 b(,)55 b(this)47 -b(con)m(v)m(en)m(tion)j(uses)d(the)h(FITS)f(k)m(eyw)m(ord)h('HIERAR)m -(CH')h(to)f(indicate)h(that)f(this)f(con)m(v)m(en-)0 -1295 y(tion)e(is)f(b)s(eing)g(used,)j(then)d(the)g(actual)i(k)m(eyw)m -(ord)e(name)h(\()p Fe('ESO)i(INS)f(FOCU)h(POS')c Fj(in)h(this)g -(example\))h(b)s(e-)0 1408 y(gins)40 b(in)f(column)g(10)i(and)e(can)h -(con)m(tain)g(an)m(y)g(prin)m(table)g(ASCI)s(I)e(text)j(c)m(haracters,) -i(including)d(spaces.)68 b(The)0 1521 y(equals)44 b(sign)h(marks)e(the) -h(end)g(of)g(the)g(k)m(eyw)m(ord)h(name)f(and)f(is)i(follo)m(w)m(ed)g -(b)m(y)f(the)g(usual)g(v)-5 b(alue)45 b(and)e(com-)0 -1634 y(men)m(t)31 b(\014elds)f(just)g(as)h(in)f(standard)g(FITS)g(k)m -(eyw)m(ords.)41 b(F)-8 b(urther)30 b(details)i(of)f(this)f(con)m(v)m -(en)m(tion)j(are)e(describ)s(ed)e(at)0 1747 y(h)m -(ttp://\014ts.gsfc.nasa.go)m(v/registry/hierarc)m(h)p -1659 1747 28 4 v 38 w(k)m(eyw)m(ord.h)m(tml)f(and)f(in)g(Section)g(4.4) -h(of)g(the)f(ESO)f(Data)j(In)m(ter-)0 1859 y(face)c(Con)m(trol)f(Do)s -(cumen)m(t)h(that)g(is)f(link)m(ed)g(to)g(from)g(h)m(ttp://arc)m(hiv)m -(e.eso.org/cms/to)s(ols-)q(do)s(cumen)m(tati)q(on/eso)q(-)0 -1972 y(data-in)m(terface-con)m(trol.h)m(tml.)0 2133 y(This)43 -b(con)m(v)m(en)m(tion)k(allo)m(ws)f(a)e(m)m(uc)m(h)h(broader)e(range)i -(of)f(k)m(eyw)m(ord)h(names)f(than)h(is)f(allo)m(w)m(ed)i(b)m(y)e(the)h -(FITS)0 2245 y(Standard.)40 b(Here)30 b(are)h(more)g(examples)g(of)f -(suc)m(h)g(k)m(eyw)m(ords:)0 2502 y Fe(HIERARCH)46 b(LongKeyword)e(=)k -(47.5)e(/)i(Keyword)e(has)h(>)g(8)g(characters,)e(and)i(mixed)f(case)0 -2615 y(HIERARCH)g(XTE$TEMP)f(=)j(98.6)e(/)i(Keyword)d(contains)h(the)h -('$')g(character)0 2728 y(HIERARCH)f(Earth)g(is)h(a)h(star)e(=)i(F)f(/) -h(Keyword)d(contains)h(embedded)f(spaces)0 2985 y Fj(CFITSIO)40 -b(will)i(transparen)m(tly)g(read)g(and)f(write)g(these)i(k)m(eyw)m -(ords,)i(so)d(application)h(programs)e(do)g(not)h(in)0 -3098 y(general)33 b(need)f(to)h(kno)m(w)f(an)m(ything)h(ab)s(out)f(the) -g(sp)s(eci\014c)g(implemen)m(tation)i(details)f(of)g(the)f(HIERAR)m(CH) -g(con-)0 3211 y(v)m(en)m(tion.)50 b(In)32 b(particular,)j(application)f -(programs)e(do)h(not)h(need)e(to)i(sp)s(ecify)f(the)g(`HIERAR)m(CH')h -(part)f(of)g(the)0 3324 y(k)m(eyw)m(ord)g(name)f(when)g(reading)g(or)g -(writing)h(k)m(eyw)m(ords)f(\(although)h(it)g(ma)m(y)g(b)s(e)f -(included)f(if)i(desired\).)46 b(When)0 3437 y(writing)35 -b(a)g(k)m(eyw)m(ord,)h(CFITSIO)d(\014rst)h(c)m(hec)m(ks)i(to)f(see)g -(if)g(the)g(k)m(eyw)m(ord)g(name)f(is)h(legal)h(as)f(a)g(standard)f -(FITS)0 3550 y(k)m(eyw)m(ord)k(\(no)g(more)f(than)h(8)g(c)m(haracters)h -(long)f(and)f(con)m(taining)i(only)e(letters,)k(digits,)f(or)e(a)g(min) -m(us)e(sign)i(or)0 3663 y(underscore\).)68 b(If)39 b(so)h(it)g(writes)g -(it)g(as)f(a)h(standard)f(FITS)g(k)m(eyw)m(ord,)k(otherwise)d(it)g -(uses)f(the)h(hierarc)m(h)f(con-)0 3776 y(v)m(en)m(tion)34 -b(to)f(write)g(the)f(k)m(eyw)m(ord.)48 b(The)32 b(maxim)m(um)g(k)m(eyw) -m(ord)h(name)f(length)h(is)g(67)g(c)m(haracters,)i(whic)m(h)d(lea)m(v)m -(es)0 3888 y(only)c(1)h(space)g(for)f(the)h(v)-5 b(alue)29 -b(\014eld.)39 b(A)29 b(more)f(practical)i(limit)f(is)g(ab)s(out)f(40)h -(c)m(haracters,)i(whic)m(h)d(lea)m(v)m(es)i(enough)0 -4001 y(ro)s(om)e(for)h(most)f(k)m(eyw)m(ord)h(v)-5 b(alues.)41 -b(CFITSIO)27 b(returns)g(an)h(error)h(if)f(there)h(is)f(not)h(enough)f -(ro)s(om)h(for)f(b)s(oth)g(the)0 4114 y(k)m(eyw)m(ord)k(name)f(and)f -(the)i(k)m(eyw)m(ord)f(v)-5 b(alue)32 b(on)f(the)h(80-c)m(haracter)h -(card,)f(except)g(for)f(string-v)-5 b(alued)32 b(k)m(eyw)m(ords)0 -4227 y(whic)m(h)h(are)g(simply)f(truncated)h(so)g(that)h(the)f(closing) -h(quote)g(c)m(haracter)g(falls)f(in)g(column)g(80.)49 -b(In)32 b(the)h(curren)m(t)0 4340 y(implemen)m(tation,)e(CFITSIO)c -(preserv)m(es)i(the)g(case)h(of)f(the)g(letters)h(when)e(writing)h(the) -g(k)m(eyw)m(ord)g(name,)g(but)f(it)0 4453 y(is)d(case-insensitiv)m(e)i -(when)d(reading)h(or)g(searc)m(hing)h(for)f(a)g(k)m(eyw)m(ord.)40 -b(The)24 b(curren)m(t)h(implemen)m(tation)h(allo)m(ws)h(an)m(y)0 -4566 y(ASCI)s(I)i(text)j(c)m(haracter)h(\(ASCI)s(I)c(32)j(to)f(ASCI)s -(I)f(126\))i(in)f(the)g(k)m(eyw)m(ord)g(name)g(except)h(for)e(the)h -('=')g(c)m(haracter.)0 4679 y(A)f(space)h(is)g(also)g(required)f(on)g -(either)h(side)f(of)h(the)f(equal)h(sign.)0 5012 y Ff(12.6)136 -b(Tile-Compressed)46 b(Image)g(F)-11 b(ormat)0 5262 y -Fj(CFITSIO)36 b(supp)s(orts)f(a)j(con)m(v)m(en)m(tion)i(for)d -(compressing)h(n-dimensional)f(images)h(and)f(storing)h(the)g -(resulting)0 5375 y(b)m(yte)i(stream)g(in)f(a)h(v)-5 -b(ariable-length)41 b(column)e(in)g(a)h(FITS)f(binary)f(table.)69 -b(The)39 b(general)i(principle)e(used)f(in)0 5488 y(this)c(con)m(v)m -(en)m(tion)j(is)d(to)h(\014rst)f(divide)g(the)h(n-dimensional)f(image)i -(in)m(to)f(a)g(rectangular)g(grid)f(of)h(subimages)f(or)0 -5601 y(`tiles'.)57 b(Eac)m(h)35 b(tile)i(is)e(then)g(compressed)g(as)g -(a)h(con)m(tin)m(uous)g(blo)s(c)m(k)f(of)h(data,)h(and)e(the)g -(resulting)g(compressed)0 5714 y(b)m(yte)i(stream)h(is)f(stored)g(in)f -(a)h(ro)m(w)g(of)g(a)h(v)-5 b(ariable)37 b(length)g(column)g(in)g(a)g -(FITS)f(binary)g(table.)61 b(By)37 b(dividing)p eop end -%%Page: 163 171 -TeXDict begin 163 170 bop 0 299 a Fh(12.6.)73 b(TILE-COMPRESSED)28 -b(IMA)m(GE)j(F)m(ORMA)-8 b(T)1838 b Fj(163)0 555 y(the)40 -b(image)g(in)m(to)g(tiles)h(it)f(is)f(generally)i(p)s(ossible)e(to)h -(extract)h(and)d(uncompress)g(subsections)i(of)f(the)h(image)0 -668 y(without)d(ha)m(ving)h(to)g(uncompress)e(the)h(whole)g(image.)62 -b(The)37 b(default)g(tiling)h(pattern)g(treats)g(eac)m(h)g(ro)m(w)f(of) -h(a)0 781 y(2-dimensional)e(image)g(\(or)f(higher)f(dimensional)h(cub)s -(e\))g(as)g(a)g(tile,)j(suc)m(h)c(that)i(eac)m(h)g(tile)g(con)m(tains)g -(NAXIS1)0 894 y(pixels)29 b(\(except)h(the)f(default)g(with)g(the)g -(HCOMPRESS)e(algorithm)j(is)f(to)h(compress)f(the)g(whole)g(2D)h(image) -g(as)0 1007 y(a)35 b(single)g(tile\).)56 b(An)m(y)34 -b(other)h(rectangular)h(tiling)g(pattern)f(ma)m(y)g(also)h(b)s(e)e -(de\014ned.)52 b(In)34 b(the)h(case)h(of)f(relativ)m(ely)0 -1120 y(small)25 b(images)h(it)f(ma)m(y)g(b)s(e)f(su\016cien)m(t)h(to)h -(compress)e(the)h(en)m(tire)g(image)h(as)f(a)g(single)h(tile,)h -(resulting)d(in)h(an)f(output)0 1233 y(binary)29 b(table)i(with)f(1)g -(ro)m(w.)41 b(In)29 b(the)h(case)h(of)f(3-dimensional)h(data)g(cub)s -(es,)e(it)i(ma)m(y)f(b)s(e)f(adv)-5 b(an)m(tageous)32 -b(to)f(treat)0 1346 y(eac)m(h)i(plane)f(of)g(the)g(cub)s(e)f(as)h(a)g -(separate)h(tile)g(if)f(application)h(soft)m(w)m(are)h(t)m(ypically)f -(needs)f(to)g(access)i(the)e(cub)s(e)0 1458 y(on)e(a)h(plane)f(b)m(y)h -(plane)f(basis.)0 1619 y(See)41 b(section)g(5.6)h(\\Image)f -(Compression")f(for)g(more)h(information)g(on)f(using)g(this)g -(tile-compressed)i(image)0 1732 y(format.)p eop end -%%Page: 164 172 -TeXDict begin 164 171 bop 0 299 a Fj(164)1741 b Fh(CHAPTER)30 -b(12.)112 b(LOCAL)29 b(FITS)h(CONVENTIONS)p eop end -%%Page: 165 173 -TeXDict begin 165 172 bop 0 1225 a Fg(Chapter)65 b(13)0 -1687 y Fm(Optimizing)76 b(Programs)0 2180 y Fj(CFITSIO)22 -b(has)h(b)s(een)f(carefully)i(designed)f(to)h(obtain)g(the)f(highest)h -(p)s(ossible)e(sp)s(eed)h(when)f(reading)h(and)g(writing)0 -2293 y(FITS)33 b(\014les.)51 b(In)33 b(order)h(to)g(ac)m(hiev)m(e)i -(the)e(b)s(est)g(p)s(erformance,)g(ho)m(w)m(ev)m(er,)i(application)g -(programmers)d(m)m(ust)h(b)s(e)0 2406 y(careful)24 b(to)h(call)g(the)f -(CFITSIO)f(routines)g(appropriately)i(and)e(in)h(an)f(e\016cien)m(t)j -(sequence;)h(inappropriate)c(usage)0 2518 y(of)31 b(CFITSIO)d(routines) -j(can)f(greatly)i(slo)m(w)f(do)m(wn)f(the)h(execution)g(sp)s(eed)f(of)g -(a)h(program.)0 2679 y(The)f(maxim)m(um)h(p)s(ossible)f(I/O)h(sp)s(eed) -f(of)h(CFITSIO)e(dep)s(ends)g(of)i(course)g(on)f(the)h(t)m(yp)s(e)g(of) -g(computer)g(system)0 2791 y(that)j(it)g(is)g(running)d(on.)50 -b(T)-8 b(o)34 b(get)h(a)f(general)g(idea)g(of)g(what)f(data)i(I/O)e(sp) -s(eeds)f(are)i(p)s(ossible)f(on)h(a)g(particular)0 2904 -y(mac)m(hine,)j(build)e(the)g(sp)s(eed.c)g(program)g(that)h(is)g -(distributed)e(with)h(CFITSIO)f(\(t)m(yp)s(e)i('mak)m(e)g(sp)s(eed')f -(in)g(the)0 3017 y(CFITSIO)e(directory\).)54 b(This)33 -b(diagnostic)j(program)e(measures)h(the)f(sp)s(eed)g(of)g(writing)h -(and)f(reading)g(bac)m(k)i(a)0 3130 y(test)31 b(FITS)f(image,)i(a)f -(binary)e(table,)j(and)d(an)i(ASCI)s(I)e(table.)0 3290 -y(The)k(follo)m(wing)h(2)g(sections)g(pro)m(vide)g(some)f(bac)m -(kground)g(on)h(ho)m(w)f(CFITSIO)f(in)m(ternally)i(manages)g(the)f -(data)0 3403 y(I/O)g(and)g(describ)s(es)f(some)i(strategies)h(that)f -(ma)m(y)g(b)s(e)e(used)h(to)h(optimize)g(the)g(pro)s(cessing)f(sp)s -(eed)f(of)h(soft)m(w)m(are)0 3516 y(that)e(uses)f(CFITSIO.)0 -3932 y Ff(13.1)136 b(Ho)l(w)45 b(CFITSIO)f(Manages)i(Data)g(I/O)0 -4199 y Fj(Man)m(y)22 b(CFITSIO)e(op)s(erations)i(in)m(v)m(olv)m(e)i -(transferring)d(only)h(a)g(small)g(n)m(um)m(b)s(er)f(of)h(b)m(ytes)g -(to)g(or)g(from)f(the)h(FITS)f(\014le)0 4312 y(\(e.g,)31 -b(reading)e(a)g(k)m(eyw)m(ord,)h(or)f(writing)g(a)g(ro)m(w)g(in)f(a)h -(table\);)i(it)f(w)m(ould)e(b)s(e)g(v)m(ery)i(ine\016cien)m(t)g(to)f -(ph)m(ysically)h(read)0 4425 y(or)i(write)h(suc)m(h)f(small)g(blo)s(c)m -(ks)h(of)f(data)h(directly)g(in)f(the)g(FITS)g(\014le)g(on)g(disk,)h -(therefore)f(CFITSIO)f(main)m(tains)0 4538 y(a)38 b(set)g(of)g(in)m -(ternal)h(Input{Output)c(\(IO\))j(bu\013ers)f(in)g(RAM)h(memory)g(that) -g(eac)m(h)h(con)m(tain)g(one)f(FITS)f(blo)s(c)m(k)0 4650 -y(\(2880)27 b(b)m(ytes\))f(of)f(data.)40 b(Whenev)m(er)25 -b(CFITSIO)f(needs)g(to)i(access)g(data)g(in)f(the)g(FITS)f(\014le,)j -(it)e(\014rst)f(transfers)h(the)0 4763 y(FITS)30 b(blo)s(c)m(k)h(con)m -(taining)h(those)f(b)m(ytes)g(in)m(to)g(one)g(of)f(the)h(IO)f -(bu\013ers)f(in)h(memory)-8 b(.)42 b(The)30 b(next)g(time)h(CFITSIO)0 -4876 y(needs)36 b(to)g(access)i(b)m(ytes)e(in)g(the)g(same)h(blo)s(c)m -(k)f(it)h(can)f(then)g(go)h(to)f(the)h(fast)f(IO)f(bu\013er)g(rather)h -(than)g(using)g(a)0 4989 y(m)m(uc)m(h)c(slo)m(w)m(er)i(system)e(disk)g -(access)h(routine.)46 b(The)32 b(n)m(um)m(b)s(er)f(of)h(a)m(v)-5 -b(ailable)35 b(IO)d(bu\013ers)f(is)h(determined)g(b)m(y)g(the)0 -5102 y(NIOBUF)f(parameter)g(\(in)f(\014tsio2.h\))h(and)f(is)h(curren)m -(tly)f(set)h(to)g(40)g(b)m(y)g(default.)0 5262 y(Whenev)m(er)24 -b(CFITSIO)f(reads)g(or)h(writes)g(data)g(it)h(\014rst)e(c)m(hec)m(ks)i -(to)g(see)f(if)g(that)g(blo)s(c)m(k)h(of)f(the)g(FITS)f(\014le)g(is)h -(already)0 5375 y(loaded)33 b(in)m(to)g(one)f(of)g(the)g(IO)g -(bu\013ers.)44 b(If)32 b(not,)h(and)e(if)h(there)g(is)g(an)g(empt)m(y)h -(IO)e(bu\013er)g(a)m(v)-5 b(ailable,)35 b(then)d(it)h(will)0 -5488 y(load)g(that)h(blo)s(c)m(k)f(in)m(to)g(the)g(IO)g(bu\013er)e -(\(when)h(reading)h(a)g(FITS)f(\014le\))h(or)g(will)g(initialize)i(a)e -(new)f(blo)s(c)m(k)i(\(when)0 5601 y(writing)j(to)h(a)g(FITS)f -(\014le\).)62 b(If)37 b(all)h(the)g(IO)e(bu\013ers)h(are)g(already)h -(full,)h(it)f(m)m(ust)g(decide)f(whic)m(h)g(one)h(to)g(reuse)0 -5714 y(\(generally)c(the)f(one)g(that)g(has)f(b)s(een)g(accessed)i -(least)f(recen)m(tly\),)i(and)d(\015ush)f(the)i(con)m(ten)m(ts)h(bac)m -(k)g(to)f(disk)f(if)g(it)1882 5942 y(165)p eop end -%%Page: 166 174 -TeXDict begin 166 173 bop 0 299 a Fj(166)1876 b Fh(CHAPTER)30 -b(13.)112 b(OPTIMIZING)29 b(PR)m(OGRAMS)0 555 y Fj(has)h(b)s(een)g(mo)s -(di\014ed)f(b)s(efore)h(loading)h(the)g(new)f(blo)s(c)m(k.)0 -715 y(The)g(one)g(ma)5 b(jor)30 b(exception)i(to)f(the)f(ab)s(o)m(v)m -(e)h(pro)s(cess)f(o)s(ccurs)g(whenev)m(er)g(a)g(large)i(con)m(tiguous)f -(set)g(of)f(b)m(ytes)h(are)0 828 y(accessed,)37 b(as)d(migh)m(t)i(o)s -(ccur)e(when)f(reading)i(or)f(writing)g(a)h(FITS)f(image.)54 -b(In)34 b(this)g(case)h(CFITSIO)e(b)m(ypasses)0 941 y(the)i(in)m -(ternal)h(IO)f(bu\013ers)f(and)g(simply)h(reads)g(or)g(writes)h(the)f -(desired)g(b)m(ytes)g(directly)h(in)f(the)g(disk)g(\014le)g(with)0 -1054 y(a)i(single)g(call)g(to)g(a)g(lo)m(w-lev)m(el)i(\014le)d(read)g -(or)h(write)f(routine.)58 b(The)36 b(minim)m(um)g(threshold)f(for)h -(the)h(n)m(um)m(b)s(er)e(of)0 1167 y(b)m(ytes)27 b(to)g(read)f(or)g -(write)g(this)g(w)m(a)m(y)i(is)e(set)g(b)m(y)h(the)f(MINDIRECT)g -(parameter)g(and)g(is)g(curren)m(tly)g(set)h(to)g(3)g(FITS)0 -1280 y(blo)s(c)m(ks)36 b(=)g(8640)i(b)m(ytes.)58 b(This)35 -b(is)h(the)g(most)g(e\016cien)m(t)i(w)m(a)m(y)f(to)g(read)e(or)h(write) -h(large)g(c)m(h)m(unks)e(of)h(data.)59 b(Note)0 1393 -y(that)34 b(this)f(fast)h(direct)g(IO)f(pro)s(cess)f(is)i(not)f -(applicable)i(when)d(accessing)j(columns)e(of)h(data)g(in)f(a)g(FITS)g -(table)0 1506 y(b)s(ecause)f(the)h(b)m(ytes)g(are)g(generally)g(not)g -(con)m(tiguous)g(since)g(they)g(are)f(in)m(terlea)m(v)m(ed)j(b)m(y)e -(the)f(other)h(columns)f(of)0 1619 y(data)i(in)e(the)h(table.)49 -b(This)33 b(explains)g(wh)m(y)f(the)h(sp)s(eed)f(for)h(accessing)h -(FITS)e(tables)i(is)f(generally)h(slo)m(w)m(er)g(than)0 -1732 y(accessing)e(FITS)e(images.)0 1892 y(Giv)m(en)i(this)g(bac)m -(kground)f(information,)h(the)g(general)g(strategy)h(for)e(e\016cien)m -(tly)i(accessing)g(FITS)e(\014les)g(should)0 2005 y(b)s(e)e(apparen)m -(t:)41 b(when)28 b(dealing)j(with)e(FITS)g(images,)i(read)e(or)h(write) -g(large)g(c)m(h)m(unks)g(of)g(data)g(at)g(a)g(time)g(so)g(that)0 -2118 y(the)25 b(direct)g(IO)f(mec)m(hanism)g(will)h(b)s(e)f(in)m(v)m -(ok)m(ed;)k(when)c(accessing)i(FITS)e(headers)g(or)g(FITS)g(tables,)j -(on)d(the)h(other)0 2230 y(hand,)35 b(once)g(a)g(particular)g(FITS)f -(blo)s(c)m(k)i(has)e(b)s(een)g(loading)i(in)m(to)f(one)g(of)g(the)g(IO) -f(bu\013ers,)h(try)g(to)g(access)h(all)0 2343 y(the)30 -b(needed)g(information)g(in)g(that)g(blo)s(c)m(k)h(b)s(efore)f(it)g -(gets)h(\015ushed)d(out)j(of)f(the)g(IO)f(bu\013er.)40 -b(It)30 b(is)g(imp)s(ortan)m(t)g(to)0 2456 y(a)m(v)m(oid)e(the)f -(situation)g(where)f(the)h(same)g(FITS)e(blo)s(c)m(k)i(is)g(b)s(eing)f -(read)g(then)g(\015ushed)f(from)h(a)h(IO)f(bu\013er)f(m)m(ultiple)0 -2569 y(times.)0 2729 y(The)30 b(follo)m(wing)i(section)f(giv)m(es)h -(more)e(sp)s(eci\014c)h(suggestions)g(for)f(optimizing)i(the)e(use)g -(of)h(CFITSIO.)0 3095 y Ff(13.2)136 b(Optimization)46 -b(Strategies)0 3352 y Fj(1.)d(Because)32 b(the)f(data)g(in)g(FITS)f -(\014les)h(is)g(alw)m(a)m(ys)h(stored)f(in)g("big-endian")h(b)m(yte)f -(order,)g(where)f(the)h(\014rst)f(b)m(yte)0 3465 y(of)g(n)m(umeric)h(v) --5 b(alues)30 b(con)m(tains)i(the)e(most)h(signi\014can)m(t)g(bits)f -(and)g(the)g(last)i(b)m(yte)e(con)m(tains)i(the)e(least)i(signi\014can) -m(t)0 3578 y(bits,)e(CFITSIO)f(m)m(ust)h(sw)m(ap)g(the)g(order)f(of)h -(the)h(b)m(ytes)f(when)f(reading)h(or)g(writing)g(FITS)g(\014les)g -(when)f(running)0 3690 y(on)k(little-endian)i(mac)m(hines)f(\(e.g.,)i -(Lin)m(ux)d(and)g(Microsoft)i(Windo)m(ws)e(op)s(erating)h(systems)g -(running)d(on)j(PCs)0 3803 y(with)c(x86)h(CPUs\).)0 3963 -y(On)21 b(relativ)m(ely)k(new)d(CPUs)g(that)h(supp)s(ort)d("SSSE3")i -(mac)m(hine)h(instructions)f(\(e.g.,)k(starting)d(with)f(In)m(tel)h -(Core)g(2)0 4076 y(CPUs)e(in)h(2007,)j(and)d(in)f(AMD)i(CPUs)e(b)s -(eginning)g(in)h(2011\))i(signi\014can)m(tly)f(faster)f(4-b)m(yte)h -(and)e(8-b)m(yte)i(sw)m(apping)0 4189 y(algorithms)k(are)g(a)m(v)-5 -b(ailable.)42 b(These)26 b(faster)h(b)m(yte)g(sw)m(apping)f(functions)g -(are)h(not)g(used)e(b)m(y)i(default)f(in)g(CFITSIO)0 -4302 y(\(b)s(ecause)33 b(of)g(p)s(oten)m(tial)h(co)s(de)f(p)s -(ortablilit)m(y)h(issues\),)g(but)e(users)g(can)h(enable)g(them)f(on)h -(supp)s(orted)e(platforms)0 4415 y(b)m(y)38 b(adding)f(the)h -(appropriate)f(compiler)i(\015ags)e(\(-mssse3)i(with)e(gcc)i(or)f(icc)g -(on)g(lin)m(ux\))g(when)e(compiling)j(the)0 4528 y(sw)m(appro)s(c.c)30 -b(source)g(\014le,)g(whic)m(h)g(will)g(allo)m(w)i(the)e(compiler)g(to)h -(generate)h(co)s(de)e(using)f(the)h(SSSE3)f(instruction)0 -4641 y(set.)41 b(A)28 b(con)m(v)m(enien)m(t)i(w)m(a)m(y)f(to)g(do)g -(this)f(is)g(to)h(con\014gure)f(the)g(CFITSIO)f(library)h(with)g(the)g -(follo)m(wing)i(command:)95 4928 y Fe(>)96 b(./configure)44 -b(--enable-ssse3)0 5215 y Fj(Note,)37 b(ho)m(w)m(ev)m(er,)h(that)d(a)g -(binary)f(executable)j(\014le)e(that)g(is)g(created)h(using)e(these)h -(faster)g(functions)g(will)g(only)0 5328 y(run)29 b(on)h(mac)m(hines)h -(that)g(supp)s(ort)e(the)h(SSSE3)f(mac)m(hine)i(instructions.)0 -5488 y(F)-8 b(or)36 b(faster)f(2-b)m(yte)i(sw)m(aps)e(on)g(virtually)g -(all)h(x86-64)h(CPUs)e(\(ev)m(en)h(those)g(that)f(do)g(not)h(supp)s -(ort)d(SSSE3\),)j(a)0 5601 y(v)-5 b(arian)m(t)26 b(using)e(only)g(SSE2) -g(instructions)h(exists.)39 b(SSE2)24 b(is)h(enabled)f(b)m(y)h(default) -g(on)f(x86)p 3066 5601 28 4 v 34 w(64)h(CPUs)f(with)h(64-bit)0 -5714 y(op)s(erating)30 b(systems)f(\(and)g(is)g(also)i(automatically)h -(enabled)d(b)m(y)g(the)g({enable-ssse3)i(\015ag\).)41 -b(When)30 b(running)d(on)p eop end -%%Page: 167 175 -TeXDict begin 167 174 bop 0 299 a Fh(13.2.)73 b(OPTIMIZA)-8 -b(TION)29 b(STRA)-8 b(TEGIES)2186 b Fj(167)0 555 y(x86)p -143 555 28 4 v 34 w(64)31 b(CPUs)g(with)f(32-bit)i(op)s(erating)g -(systems,)f(these)g(faster)h(2-b)m(yte)g(sw)m(apping)f(algorithms)g -(are)h(not)f(used)0 668 y(b)m(y)f(default)h(in)f(CFITSIO,)f(but)h(can)g -(b)s(e)g(enabled)g(explicitly)i(with:)0 951 y Fe(./configure)45 -b(--enable-sse2)0 1234 y Fj(Preliminary)f(testing)h(indicates)g(that)g -(these)f(SSSE3)f(and)g(SSE2)g(based)h(b)m(yte-sw)m(apping)h(algorithms) -g(can)0 1347 y(b)s(o)s(ost)31 b(the)h(CFITSIO)e(p)s(erformance)h(when)f -(reading)i(or)f(writing)h(FITS)f(images)h(b)m(y)g(20\045)g(-)g(30\045)g -(or)f(more.)45 b(It)0 1460 y(is)36 b(imp)s(ortan)m(t)g(to)g(note,)i(ho) -m(w)m(ev)m(er,)h(that)d(compiler)g(optimization)i(m)m(ust)e(b)s(e)f -(turned)f(on)i(\(e.g.,)j(b)m(y)d(using)f(the)0 1573 y(-O1)f(or)g(-O2)g -(\015ags)g(in)g(gcc\))h(when)e(building)g(programs)h(that)g(use)g -(these)g(fast)g(b)m(yte-sw)m(apping)h(algorithms)f(in)0 -1686 y(order)d(to)h(reap)f(the)h(full)f(b)s(ene\014t)g(of)g(the)h -(SSSE3)e(and)h(SSE2)g(instructions;)h(without)f(optimization,)j(the)e -(co)s(de)0 1799 y(ma)m(y)f(actually)h(run)d(slo)m(w)m(er)i(than)f(when) -g(using)g(more)g(traditional)i(b)m(yte-sw)m(apping)f(tec)m(hniques.)0 -1959 y(2.)54 b(When)34 b(dealing)h(with)g(a)g(FITS)e(primary)h(arra)m -(y)h(or)g(IMA)m(GE)g(extension,)i(it)e(is)f(more)h(e\016cien)m(t)h(to)f -(read)g(or)0 2072 y(write)c(large)g(c)m(h)m(unks)f(of)g(the)h(image)g -(at)h(a)e(time)h(\(at)h(least)f(3)g(FITS)f(blo)s(c)m(ks)g(=)g(8640)i(b) -m(ytes\))f(so)g(that)g(the)f(direct)0 2185 y(IO)j(mec)m(hanism)h(will)f -(b)s(e)g(used)g(as)g(describ)s(ed)g(in)g(the)g(previous)g(section.)51 -b(Smaller)34 b(c)m(h)m(unks)f(of)g(data)h(are)g(read)0 -2298 y(or)d(written)g(via)h(the)f(IO)f(bu\013ers,)g(whic)m(h)h(is)g -(somewhat)g(less)g(e\016cien)m(t)i(b)s(ecause)e(of)g(the)g(extra)h(cop) -m(y)f(op)s(eration)0 2411 y(and)26 b(additional)h(b)s(o)s(okk)m(eeping) -g(steps)g(that)g(are)g(required.)39 b(In)26 b(principle)g(it)h(is)g -(more)f(e\016cien)m(t)i(to)g(read)e(or)h(write)0 2524 -y(as)i(big)g(an)g(arra)m(y)h(of)f(image)h(pixels)f(at)h(one)f(time)g -(as)h(p)s(ossible,)f(ho)m(w)m(ev)m(er,)h(if)f(the)h(arra)m(y)f(b)s -(ecomes)g(so)g(large)h(that)0 2636 y(the)i(op)s(erating)g(system)f -(cannot)h(store)g(it)g(all)h(in)e(RAM,)h(then)f(the)h(p)s(erformance)f -(ma)m(y)h(b)s(e)f(degraded)g(b)s(ecause)0 2749 y(of)g(the)f(increased)h -(sw)m(apping)f(of)g(virtual)h(memory)f(to)h(disk.)0 2910 -y(3.)51 b(When)33 b(dealing)i(with)e(FITS)g(tables,)j(the)e(most)g(imp) -s(ortan)m(t)g(e\016ciency)g(factor)h(in)e(the)h(soft)m(w)m(are)h -(design)f(is)0 3022 y(to)j(read)f(or)g(write)g(the)g(data)h(in)f(the)g -(FITS)g(\014le)g(in)g(a)g(single)h(pass)f(through)f(the)h(\014le.)58 -b(An)36 b(example)h(of)f(p)s(o)s(or)0 3135 y(program)g(design)h(w)m -(ould)f(b)s(e)g(to)h(read)g(a)f(large,)k(3-column)d(table)g(b)m(y)g -(sequen)m(tially)h(reading)f(the)f(en)m(tire)i(\014rst)0 -3248 y(column,)25 b(then)f(going)h(bac)m(k)f(to)h(read)e(the)h(2nd)g -(column,)h(and)e(\014nally)h(the)g(3rd)f(column;)j(this)e(ob)m(viously) -g(requires)0 3361 y(3)j(passes)g(through)g(the)g(\014le)g(whic)m(h)g -(could)g(triple)g(the)h(execution)g(time)g(of)f(an)g(IO)f(limited)i -(program.)40 b(F)-8 b(or)27 b(small)0 3474 y(tables)k(this)f(is)h(not)f -(imp)s(ortan)m(t,)h(but)f(when)f(reading)h(m)m(ulti-megab)m(yte)j -(sized)e(tables)g(these)g(ine\016ciencies)h(can)0 3587 -y(b)s(ecome)d(signi\014can)m(t.)41 b(The)28 b(more)h(e\016cien)m(t)h -(pro)s(cedure)d(in)i(this)f(case)i(is)e(to)i(read)e(or)h(write)g(only)f -(as)h(man)m(y)g(ro)m(ws)0 3700 y(of)j(the)g(table)g(as)g(will)g(\014t)g -(in)m(to)g(the)g(a)m(v)-5 b(ailable)34 b(in)m(ternal)e(IO)f(bu\013ers,) -h(then)f(access)i(all)f(the)g(necessary)g(columns)0 3813 -y(of)f(data)h(within)e(that)i(range)f(of)g(ro)m(ws.)43 -b(Then)29 b(after)j(the)f(program)g(is)g(completely)h(\014nished)e -(with)g(the)i(data)f(in)0 3926 y(those)i(ro)m(ws)e(it)i(can)f(mo)m(v)m -(e)i(on)e(to)g(the)h(next)f(range)g(of)g(ro)m(ws)g(that)h(will)f(\014t) -g(in)g(the)g(bu\013ers,)f(con)m(tin)m(uing)i(in)f(this)0 -4039 y(w)m(a)m(y)c(un)m(til)f(the)f(en)m(tire)i(\014le)f(has)f(b)s(een) -g(pro)s(cessed.)39 b(By)27 b(using)f(this)h(pro)s(cedure)e(of)i -(accessing)h(all)g(the)e(columns)h(of)0 4152 y(a)j(table)g(in)f -(parallel)h(rather)f(than)g(sequen)m(tially)-8 b(,)32 -b(eac)m(h)e(blo)s(c)m(k)g(of)g(the)f(FITS)g(\014le)g(will)g(only)h(b)s -(e)e(read)i(or)f(written)0 4264 y(once.)0 4425 y(The)g(optimal)h(n)m -(um)m(b)s(er)e(of)i(ro)m(ws)f(to)i(read)e(or)g(write)h(at)g(one)g(time) -g(in)f(a)h(giv)m(en)g(table)h(dep)s(ends)c(on)j(the)f(width)g(of)0 -4538 y(the)c(table)h(ro)m(w)f(and)f(on)h(the)g(n)m(um)m(b)s(er)e(of)i -(IO)g(bu\013ers)e(that)j(ha)m(v)m(e)g(b)s(een)e(allo)s(cated)j(in)e -(CFITSIO.)e(The)h(CFITSIO)0 4650 y(Iterator)h(routine)f(will)g -(automatically)j(use)c(the)h(optimal-sized)i(bu\013er,)e(but)g(there)g -(is)g(also)g(a)h(CFITSIO)d(routine)0 4763 y(that)31 b(will)g(return)f -(the)h(optimal)h(n)m(um)m(b)s(er)d(of)i(ro)m(ws)g(for)f(a)h(giv)m(en)h -(table:)43 b(\014ts)p 2629 4763 V 32 w(get)p 2781 4763 -V 34 w(ro)m(wsize.)g(It)31 b(is)g(not)g(critical)h(to)0 -4876 y(use)h(exactly)j(the)e(v)-5 b(alue)34 b(of)g(nro)m(ws)f(returned) -f(b)m(y)i(this)g(routine,)g(as)g(long)h(as)f(one)g(do)s(es)f(not)h -(exceed)h(it.)51 b(Using)0 4989 y(a)37 b(v)m(ery)g(small)g(v)-5 -b(alue)37 b(ho)m(w)m(ev)m(er)h(can)f(also)g(lead)g(to)h(p)s(o)s(or)d(p) -s(erformance)h(b)s(ecause)g(of)h(the)g(o)m(v)m(erhead)h(from)e(the)0 -5102 y(larger)31 b(n)m(um)m(b)s(er)e(of)i(subroutine)e(calls.)0 -5262 y(The)36 b(optimal)h(n)m(um)m(b)s(er)e(of)h(ro)m(ws)g(returned)f -(b)m(y)i(\014ts)p 1829 5262 V 32 w(get)p 1981 5262 V -34 w(ro)m(wsize)g(is)g(v)-5 b(alid)36 b(only)g(as)h(long)g(as)f(the)h -(application)0 5375 y(program)27 b(is)g(only)g(reading)h(or)f(writing)g -(data)h(in)f(the)g(sp)s(eci\014ed)f(table.)41 b(An)m(y)27 -b(other)g(calls)i(to)f(access)g(data)g(in)f(the)0 5488 -y(table)i(header)f(w)m(ould)f(cause)i(additional)g(blo)s(c)m(ks)f(of)g -(data)g(to)h(b)s(e)e(loaded)i(in)m(to)g(the)f(IO)f(bu\013ers)g -(displacing)h(data)0 5601 y(from)34 b(the)h(original)h(table,)h(and)d -(should)f(b)s(e)h(a)m(v)m(oided)i(during)e(the)h(critical)h(p)s(erio)s -(d)e(while)g(the)h(table)h(is)e(b)s(eing)0 5714 y(read)c(or)h(written.) -p eop end -%%Page: 168 176 -TeXDict begin 168 175 bop 0 299 a Fj(168)1876 b Fh(CHAPTER)30 -b(13.)112 b(OPTIMIZING)29 b(PR)m(OGRAMS)0 555 y Fj(4.)39 -b(Use)25 b(the)g(CFITSIO)e(Iterator)j(routine.)39 b(This)24 -b(routine)h(pro)m(vides)f(a)i(more)e(`ob)5 b(ject)26 -b(orien)m(ted')g(w)m(a)m(y)g(of)f(reading)0 668 y(and)34 -b(writing)g(FITS)g(\014les)g(whic)m(h)h(automatically)i(uses)d(the)g -(most)h(appropriate)g(data)g(bu\013er)e(size)i(to)h(ac)m(hiev)m(e)0 -781 y(the)31 b(maxim)m(um)f(I/O)g(throughput.)0 941 y(5.)39 -b(Use)24 b(binary)f(table)h(extensions)g(rather)f(than)h(ASCI)s(I)e -(table)i(extensions)g(for)f(b)s(etter)h(e\016ciency)h(when)d(dealing)0 -1054 y(with)37 b(tabular)h(data.)62 b(The)37 b(I/O)g(to)h(ASCI)s(I)e -(tables)i(is)g(slo)m(w)m(er)g(b)s(ecause)g(of)f(the)h(o)m(v)m(erhead)h -(in)e(formatting)h(or)0 1167 y(parsing)32 b(the)g(ASCI)s(I)f(data)i -(\014elds)f(and)g(b)s(ecause)g(ASCI)s(I)f(tables)i(are)g(ab)s(out)f(t)m -(wice)i(as)f(large)g(as)g(binary)e(tables)0 1280 y(that)g(ha)m(v)m(e)h -(the)e(same)h(information)g(con)m(ten)m(t.)0 1440 y(6.)64 -b(Design)39 b(soft)m(w)m(are)g(so)g(that)f(it)h(reads)f(the)g(FITS)f -(header)h(k)m(eyw)m(ords)g(in)g(the)g(same)h(order)e(in)h(whic)m(h)g -(they)0 1553 y(o)s(ccur)28 b(in)h(the)g(\014le.)40 b(When)28 -b(reading)h(k)m(eyw)m(ords,)h(CFITSIO)d(searc)m(hes)i(forw)m(ard)g -(starting)g(from)f(the)h(p)s(osition)g(of)0 1666 y(the)g(last)i(k)m -(eyw)m(ord)e(that)h(w)m(as)g(read.)40 b(If)29 b(it)g(reac)m(hes)i(the)e -(end)g(of)g(the)h(header)f(without)g(\014nding)f(the)h(k)m(eyw)m(ord,)h -(it)0 1779 y(then)j(go)s(es)h(bac)m(k)g(to)h(the)e(start)h(of)g(the)g -(header)f(and)g(con)m(tin)m(ues)h(the)g(searc)m(h)g(do)m(wn)f(to)h(the) -g(p)s(osition)f(where)g(it)0 1892 y(started.)41 b(In)30 -b(practice,)i(as)e(long)h(as)g(the)f(en)m(tire)i(FITS)d(header)h(can)h -(\014t)f(at)h(one)g(time)g(in)f(the)g(a)m(v)-5 b(ailable)33 -b(in)m(ternal)0 2005 y(IO)23 b(bu\013ers,)i(then)e(the)i(header)e(k)m -(eyw)m(ord)i(access)g(will)f(b)s(e)g(relativ)m(ely)i(fast)e(and)g(it)g -(mak)m(es)h(little)h(di\013erence)e(whic)m(h)0 2118 y(order)30 -b(they)g(are)h(accessed.)0 2278 y(7.)40 b(Av)m(oid)29 -b(the)e(use)h(of)f(scaling)i(\(b)m(y)f(using)f(the)h(BSCALE)e(and)h -(BZER)m(O)h(or)f(TSCAL)g(and)g(TZER)m(O)f(k)m(eyw)m(ords\))0 -2391 y(in)35 b(FITS)f(\014les)g(since)i(the)f(scaling)h(op)s(erations)f -(add)f(to)i(the)f(pro)s(cessing)f(time)i(needed)e(to)i(read)f(or)g -(write)g(the)0 2503 y(data.)k(In)24 b(some)h(cases)h(it)f(ma)m(y)g(b)s -(e)f(more)g(e\016cien)m(t)i(to)g(temp)s(orarily)e(turn)g(o\013)h(the)f -(scaling)i(\(using)e(\014ts)p 3490 2503 28 4 v 33 w(set)p -3634 2503 V 33 w(bscale)0 2616 y(or)30 b(\014ts)p 238 -2616 V 33 w(set)p 382 2616 V 33 w(tscale\))j(and)c(then)h(read)h(or)f -(write)h(the)f(ra)m(w)h(unscaled)f(v)-5 b(alues)31 b(in)f(the)g(FITS)g -(\014le.)0 2777 y(8.)77 b(Av)m(oid)43 b(using)f(the)h(`implicit)g(data) -h(t)m(yp)s(e)e(con)m(v)m(ersion')i(capabilit)m(y)g(in)e(CFITSIO.)f(F)-8 -b(or)44 b(instance,)i(when)0 2889 y(reading)28 b(a)g(FITS)f(image)i -(with)e(BITPIX)h(=)f(-32)i(\(32-bit)g(\015oating)g(p)s(oin)m(t)f -(pixels\),)h(read)e(the)h(data)g(in)m(to)h(a)f(single)0 -3002 y(precision)40 b(\015oating)h(p)s(oin)m(t)f(data)h(arra)m(y)f(in)g -(the)g(program.)69 b(F)-8 b(orcing)41 b(CFITSIO)e(to)i(con)m(v)m(ert)g -(the)f(data)h(to)g(a)0 3115 y(di\013eren)m(t)31 b(data)g(t)m(yp)s(e)f -(can)h(slo)m(w)g(the)g(program.)0 3275 y(9.)57 b(Where)36 -b(feasible,)i(design)e(FITS)f(binary)g(tables)h(using)f(v)m(ector)j -(column)d(elemen)m(ts)i(so)f(that)g(the)g(data)h(are)0 -3388 y(written)30 b(as)g(a)g(con)m(tiguous)h(set)f(of)g(b)m(ytes,)g -(rather)g(than)f(as)h(single)g(elemen)m(ts)h(in)f(m)m(ultiple)g(ro)m -(ws.)41 b(F)-8 b(or)30 b(example,)0 3501 y(it)36 b(is)g(faster)g(to)g -(access)h(the)f(data)h(in)e(a)h(table)h(that)f(con)m(tains)h(a)f -(single)g(ro)m(w)g(and)f(2)h(columns)f(with)h(TF)m(ORM)0 -3614 y(k)m(eyw)m(ords)d(equal)h(to)g('10000E')h(and)e('10000J',)j(than) -d(it)g(is)g(to)h(access)g(the)g(same)f(amoun)m(t)h(of)f(data)h(in)f(a)g -(table)0 3727 y(with)40 b(10000)j(ro)m(ws)d(whic)m(h)h(has)f(columns)g -(with)g(the)h(TF)m(ORM)g(k)m(eyw)m(ords)g(equal)g(to)g('1E')h(and)e -('1J'.)h(In)f(the)0 3840 y(former)27 b(case)i(the)f(10000)i(\015oating) -f(p)s(oin)m(t)f(v)-5 b(alues)28 b(in)g(the)g(\014rst)f(column)h(are)g -(all)h(written)f(in)f(a)h(con)m(tiguous)h(blo)s(c)m(k)0 -3953 y(of)d(the)f(\014le)h(whic)m(h)f(can)h(b)s(e)f(read)g(or)g -(written)h(quic)m(kly)-8 b(,)28 b(whereas)d(in)g(the)h(second)f(case)i -(eac)m(h)g(\015oating)f(p)s(oin)m(t)f(v)-5 b(alue)0 4066 -y(in)34 b(the)g(\014rst)f(column)g(is)h(in)m(terlea)m(v)m(ed)j(with)c -(the)h(in)m(teger)i(v)-5 b(alue)34 b(in)g(the)g(second)g(column)f(of)h -(the)g(same)h(ro)m(w)f(so)0 4179 y(CFITSIO)29 b(has)h(to)h(explicitly)h -(mo)m(v)m(e)g(to)f(the)g(p)s(osition)f(of)h(eac)m(h)g(elemen)m(t)h(to)f -(b)s(e)f(read)g(or)g(written.)0 4339 y(10.)45 b(Av)m(oid)33 -b(the)f(use)f(of)h(v)-5 b(ariable)32 b(length)g(v)m(ector)h(columns)f -(in)f(binary)g(tables,)i(since)f(an)m(y)g(reading)f(or)h(writing)0 -4452 y(of)h(these)g(data)g(requires)f(that)h(CFITSIO)f(\014rst)f(lo)s -(ok)j(up)d(or)i(compute)g(the)f(starting)i(address)e(of)g(eac)m(h)i(ro) -m(w)f(of)0 4565 y(data)e(in)f(the)h(heap.)40 b(In)30 -b(practice,)i(this)e(is)g(probably)g(not)h(a)f(signi\014can)m(t)i -(e\016ciency)f(issue.)0 4725 y(11.)73 b(When)40 b(cop)m(ying)i(data)g -(from)e(one)h(FITS)f(table)i(to)f(another,)j(it)e(is)e(faster)i(to)f -(transfer)g(the)f(ra)m(w)h(b)m(ytes)0 4838 y(instead)28 -b(of)h(reading)f(then)g(writing)g(eac)m(h)h(column)f(of)g(the)g(table.) -41 b(The)28 b(CFITSIO)e(routines)i(\014ts)p 3349 4838 -V 33 w(read)p 3554 4838 V 32 w(tblb)m(ytes)0 4951 y(and)36 -b(\014ts)p 310 4951 V 32 w(write)p 544 4951 V 33 w(tblb)m(ytes)i(will)f -(p)s(erform)e(lo)m(w-lev)m(el)k(reads)e(or)f(writes)h(of)g(an)m(y)g -(con)m(tiguous)g(range)g(of)g(b)m(ytes)g(in)0 5064 y(a)d(table)g -(extension.)51 b(These)33 b(routines)h(can)f(b)s(e)g(used)g(to)h(read)f -(or)h(write)g(a)f(whole)h(ro)m(w)g(\(or)g(m)m(ultiple)g(ro)m(ws)f(for)0 -5176 y(ev)m(en)e(greater)h(e\016ciency\))h(of)e(a)g(table)h(with)e(a)h -(single)h(function)e(call.)43 b(These)31 b(routines)g(are)g(fast)g(b)s -(ecause)g(they)0 5289 y(b)m(ypass)36 b(all)h(the)g(usual)f(data)h -(scaling,)i(error)d(c)m(hec)m(king)i(and)e(mac)m(hine)h(dep)s(enden)m -(t)e(data)i(con)m(v)m(ersion)h(that)f(is)0 5402 y(normally)g(done)g(b)m -(y)f(CFITSIO,)g(and)g(they)h(allo)m(w)h(the)g(program)e(to)i(write)f -(the)g(data)g(to)h(the)f(output)f(\014le)h(in)0 5515 -y(exactly)30 b(the)e(same)h(b)m(yte)g(order.)40 b(F)-8 -b(or)29 b(these)f(same)h(reasons,)g(these)g(routines)f(can)g(corrupt)g -(the)g(FITS)g(data)h(\014le)0 5628 y(if)36 b(used)e(incorrectly)j(b)s -(ecause)f(no)f(v)-5 b(alidation)37 b(or)f(mac)m(hine)g(dep)s(enden)m(t) -e(con)m(v)m(ersion)j(is)f(p)s(erformed)e(b)m(y)h(these)p -eop end -%%Page: 169 177 -TeXDict begin 169 176 bop 0 299 a Fh(13.2.)73 b(OPTIMIZA)-8 -b(TION)29 b(STRA)-8 b(TEGIES)2186 b Fj(169)0 555 y(routines.)55 -b(These)35 b(routines)g(are)h(only)f(recommended)g(for)g(optimizing)h -(critical)h(pieces)f(of)g(co)s(de)f(and)g(should)0 668 -y(only)e(b)s(e)g(used)g(b)m(y)g(programmers)g(who)g(thoroughly)g -(understand)e(the)j(in)m(ternal)g(format)g(of)f(the)h(FITS)e(tables)0 -781 y(they)f(are)f(reading)h(or)f(writing.)0 941 y(12.)41 -b(Another)30 b(strategy)g(for)g(impro)m(ving)f(the)h(sp)s(eed)e(of)i -(writing)g(a)f(FITS)g(table,)i(similar)f(to)g(the)f(previous)g(one,)0 -1054 y(is)j(to)g(directly)h(construct)f(the)f(en)m(tire)i(b)m(yte)f -(stream)g(for)g(a)g(whole)g(table)g(ro)m(w)g(\(or)g(m)m(ultiple)h(ro)m -(ws\))f(within)f(the)0 1167 y(application)g(program)e(and)g(then)h -(write)g(it)g(to)g(the)g(FITS)f(\014le)h(with)f(\014ts)p -2520 1167 28 4 v 32 w(write)p 2754 1167 V 33 w(tblb)m(ytes.)41 -b(This)29 b(a)m(v)m(oids)i(all)g(the)0 1280 y(o)m(v)m(erhead)f -(normally)g(presen)m(t)f(in)g(the)h(column-orien)m(ted)g(CFITSIO)e -(write)h(routines.)40 b(This)29 b(tec)m(hnique)h(should)0 -1393 y(only)35 b(b)s(e)e(used)h(for)g(critical)i(applications)g(b)s -(ecause)e(it)h(mak)m(es)h(the)e(co)s(de)h(more)f(di\016cult)h(to)g -(understand)e(and)0 1506 y(main)m(tain,)38 b(and)d(it)h(mak)m(es)g(the) -g(co)s(de)f(more)h(system)g(dep)s(enden)m(t)e(\(e.g.,)39 -b(do)c(the)h(b)m(ytes)g(need)f(to)h(b)s(e)f(sw)m(app)s(ed)0 -1619 y(b)s(efore)30 b(writing)g(to)h(the)g(FITS)f(\014le?\).)0 -1779 y(13.)40 b(Finally)-8 b(,)29 b(external)e(factors)g(suc)m(h)e(as)i -(the)f(sp)s(eed)f(of)i(the)f(data)h(storage)g(device,)h(the)f(size)g -(of)f(the)g(data)h(cac)m(he,)0 1892 y(the)34 b(amoun)m(t)h(of)f(disk)g -(fragmen)m(tation,)j(and)c(the)i(amoun)m(t)f(of)h(RAM)f(a)m(v)-5 -b(ailable)37 b(on)d(the)g(system)g(can)h(all)g(ha)m(v)m(e)0 -2005 y(a)k(signi\014can)m(t)g(impact)g(on)f(o)m(v)m(erall)j(I/O)d -(e\016ciency)-8 b(.)66 b(F)-8 b(or)39 b(critical)h(applications,)i(the) -c(en)m(tire)i(hardw)m(are)e(and)0 2118 y(soft)m(w)m(are)32 -b(system)e(should)g(b)s(e)f(review)m(ed)i(to)h(iden)m(tify)e(an)m(y)h -(p)s(oten)m(tial)h(I/O)e(b)s(ottlenec)m(ks.)p eop end -%%Page: 170 178 -TeXDict begin 170 177 bop 0 299 a Fj(170)1876 b Fh(CHAPTER)30 -b(13.)112 b(OPTIMIZING)29 b(PR)m(OGRAMS)p eop end -%%Page: 171 179 -TeXDict begin 171 178 bop 0 1225 a Fg(App)5 b(endix)64 -b(A)0 1687 y Fm(Index)77 b(of)h(Routines)50 2154 y Fj(\014ts)p -177 2154 28 4 v 32 w(add)p 356 2154 V 32 w(group)p 616 -2154 V 33 w(mem)m(b)s(er)245 b(92)50 2267 y(\014ts)p -177 2267 V 32 w(ascii)p 380 2267 V 34 w(tform)579 b(70)50 -2380 y(\014ts)p 177 2380 V 32 w(binary)p 465 2380 V 32 -w(tform)496 b(70)50 2493 y(\014ts)p 177 2493 V 32 w(calculator)617 -b(60)50 2606 y(\014ts)p 177 2606 V 32 w(calculator)p -596 2606 V 35 w(rng)450 b(60)50 2719 y(\014ts)p 177 2719 -V 32 w(calc)p 359 2719 V 35 w(binning)520 b(61)50 2832 -y(\014ts)p 177 2832 V 32 w(calc)p 359 2832 V 35 w(ro)m(ws)639 -b(60)50 2945 y(\014ts)p 177 2945 V 32 w(c)m(hange)p 478 -2945 V 34 w(group)473 b(90)50 3057 y(\014ts)p 177 3057 -V 32 w(clear)p 395 3057 V 34 w(errmark)467 b(32)50 3170 -y(\014ts)p 177 3170 V 32 w(clear)p 395 3170 V 34 w(errmsg)515 -b(32)50 3283 y(\014ts)p 177 3283 V 32 w(close)p 395 3283 -V 34 w(\014le)668 b(35)50 3396 y(\014ts)p 177 3396 V -32 w(compact)p 541 3396 V 34 w(group)410 b(91)50 3509 -y(\014ts)p 177 3509 V 32 w(compare)p 542 3509 V 34 w(str)530 -b(66)50 3622 y(\014ts)p 177 3622 V 32 w(compress)p 569 -3622 V 33 w(heap)379 b(115)50 3735 y(\014ts)p 177 3735 -V 32 w(con)m(v)m(ert)p 498 3735 V 35 w(hdr2str)244 b(40,)31 -b(86)50 3848 y(\014ts)p 177 3848 V 32 w(cop)m(y)p 390 -3848 V 34 w(cell2image)383 b(44)50 3961 y(\014ts)p 177 -3961 V 32 w(cop)m(y)p 390 3961 V 34 w(col)679 b(57)50 -4074 y(\014ts)p 177 4074 V 32 w(cop)m(y)p 390 4074 V -34 w(data)568 b(100)50 4187 y(\014ts)p 177 4187 V 32 -w(cop)m(y)p 390 4187 V 34 w(\014le)673 b(36)50 4299 y(\014ts)p -177 4299 V 32 w(cop)m(y)p 390 4299 V 34 w(group)561 b(91)50 -4412 y(\014ts)p 177 4412 V 32 w(cop)m(y)p 390 4412 V -34 w(hdu)636 b(37)50 4525 y(\014ts)p 177 4525 V 32 w(cop)m(y)p -390 4525 V 34 w(header)526 b(37)50 4638 y(\014ts)p 177 -4638 V 32 w(cop)m(y)p 390 4638 V 34 w(image2cell)383 -b(44)50 4751 y(\014ts)p 177 4751 V 32 w(cop)m(y)p 390 -4751 V 34 w(image)p 655 4751 V 34 w(section)252 b(47)50 -4864 y(\014ts)p 177 4864 V 32 w(cop)m(y)p 390 4864 V -34 w(k)m(ey)611 b(105)50 4977 y(\014ts)p 177 4977 V 32 -w(cop)m(y)p 390 4977 V 34 w(mem)m(b)s(er)470 b(93)50 -5090 y(\014ts)p 177 5090 V 32 w(cop)m(y)p 390 5090 V -34 w(pixlist2image)268 b(62)50 5203 y(\014ts)p 177 5203 -V 32 w(cop)m(y)p 390 5203 V 34 w(ro)m(ws)609 b(57)50 -5316 y(\014ts)p 177 5316 V 32 w(create)p 445 5316 V 35 -w(disk\014le)457 b(34)50 5429 y(\014ts)p 177 5429 V 32 -w(create)p 445 5429 V 35 w(\014le)617 b(34)50 5541 y(\014ts)p -177 5541 V 32 w(create)p 445 5541 V 35 w(group)505 b(90)50 -5654 y(\014ts)p 177 5654 V 32 w(create)p 445 5654 V 35 -w(hdu)580 b(99)1419 2154 y(\014ts)p 1546 2154 V 32 w(create)p -1814 2154 V 35 w(img)711 b(44)1419 2267 y(\014ts)p 1546 -2267 V 32 w(create)p 1814 2267 V 35 w(mem\014le)549 b(96)1419 -2380 y(\014ts)p 1546 2380 V 32 w(create)p 1814 2380 V -35 w(tbl)746 b(52)1419 2493 y(\014ts)p 1546 2493 V 32 -w(create)p 1814 2493 V 35 w(template)510 b(96)1419 2606 -y(\014ts)p 1546 2606 V 32 w(date2str)805 b(65)1419 2719 -y(\014ts)p 1546 2719 V 32 w(deco)s(de)p 1848 2719 V 33 -w(c)m(hksum)526 b(64)1419 2832 y(\014ts)p 1546 2832 V -32 w(deco)s(de)p 1848 2832 V 33 w(tdim)638 b(55)1419 -2945 y(\014ts)p 1546 2945 V 32 w(delete)p 1809 2945 V -34 w(col)753 b(56)1419 3057 y(\014ts)p 1546 3057 V 32 -w(delete)p 1809 3057 V 34 w(\014le)747 b(35)1419 3170 -y(\014ts)p 1546 3170 V 32 w(delete)p 1809 3170 V 34 w(hdu)710 -b(37)1419 3283 y(\014ts)p 1546 3283 V 32 w(delete)p 1809 -3283 V 34 w(k)m(ey)730 b(42)1419 3396 y(\014ts)p 1546 -3396 V 32 w(delete)p 1809 3396 V 34 w(record)615 b(42)1419 -3509 y(\014ts)p 1546 3509 V 32 w(delete)p 1809 3509 V -34 w(ro)m(wlist)598 b(56)1419 3622 y(\014ts)p 1546 3622 -V 32 w(delete)p 1809 3622 V 34 w(ro)m(wrange)502 b(56)1419 -3735 y(\014ts)p 1546 3735 V 32 w(delete)p 1809 3735 V -34 w(ro)m(ws)683 b(56)1419 3848 y(\014ts)p 1546 3848 -V 32 w(delete)p 1809 3848 V 34 w(str)756 b(42)1419 3961 -y(\014ts)p 1546 3961 V 32 w(enco)s(de)p 1848 3961 V 33 -w(c)m(hksum)526 b(64)1419 4074 y(\014ts)p 1546 4074 V -32 w(\014le)p 1694 4074 V 33 w(exists)759 b(98)1419 4187 -y(\014ts)p 1546 4187 V 32 w(\014le)p 1694 4187 V 33 w(mo)s(de)764 -b(35)1419 4299 y(\014ts)p 1546 4299 V 32 w(\014le)p 1694 -4299 V 33 w(name)j(35)1419 4412 y(\014ts)p 1546 4412 -V 32 w(\014nd)p 1731 4412 V 32 w(\014rst)p 1921 4412 -V 32 w(ro)m(w)609 b(60)1419 4525 y(\014ts)p 1546 4525 -V 32 w(\014nd)p 1731 4525 V 32 w(nextk)m(ey)636 b(39)1419 -4638 y(\014ts)p 1546 4638 V 32 w(\014nd)p 1731 4638 V -32 w(ro)m(ws)763 b(59)1419 4751 y(\014ts)p 1546 4751 -V 32 w(\015ush)p 1767 4751 V 32 w(bu\013er)676 b(98)1419 -4864 y(\014ts)p 1546 4864 V 32 w(\015ush)p 1767 4864 -V 32 w(\014le)791 b(98)1419 4977 y(\014ts)p 1546 4977 -V 32 w(free)p 1722 4977 V 33 w(memory)438 b(107,)32 b(40)1419 -5090 y(\014ts)p 1546 5090 V 32 w(get)p 1698 5090 V 34 -w(acolparms)530 b(114)1419 5203 y(\014ts)p 1546 5203 -V 32 w(get)p 1698 5203 V 34 w(b)s(colparms)521 b(114)1419 -5316 y(\014ts)p 1546 5316 V 32 w(get)p 1698 5316 V 34 -w(c)m(hksum)675 b(64)1419 5429 y(\014ts)p 1546 5429 V -32 w(get)p 1698 5429 V 34 w(col)p 1842 5429 V 34 w(displa)m(y)p -2154 5429 V 33 w(width)291 b(55)1419 5541 y(\014ts)p -1546 5541 V 32 w(get)p 1698 5541 V 34 w(colname)652 b(53)1419 -5654 y(\014ts)p 1546 5654 V 32 w(get)p 1698 5654 V 34 -w(coln)m(um)689 b(53)2912 2154 y(\014ts)p 3039 2154 V -32 w(get)p 3191 2154 V 34 w(colt)m(yp)s(e)650 b(54)2912 -2267 y(\014ts)p 3039 2267 V 32 w(get)p 3191 2267 V 34 -w(compression)p 3706 2267 V 33 w(t)m(yp)s(e)246 b(50)2912 -2380 y(\014ts)p 3039 2380 V 32 w(get)p 3191 2380 V 34 -w(eqcolt)m(yp)s(e)562 b(54)2912 2493 y(\014ts)p 3039 -2493 V 32 w(get)p 3191 2493 V 34 w(errstatus)584 b(31)2912 -2606 y(\014ts)p 3039 2606 V 32 w(get)p 3191 2606 V 34 -w(hdrp)s(os)616 b(101)2912 2719 y(\014ts)p 3039 2719 -V 32 w(get)p 3191 2719 V 34 w(hdrspace)584 b(38)2912 -2832 y(\014ts)p 3039 2832 V 32 w(get)p 3191 2832 V 34 -w(hdu)p 3378 2832 V 31 w(n)m(um)575 b(36)2912 2945 y(\014ts)p -3039 2945 V 32 w(get)p 3191 2945 V 34 w(hdu)p 3378 2945 -V 31 w(t)m(yp)s(e)h(36)2912 3057 y(\014ts)p 3039 3057 -V 32 w(get)p 3191 3057 V 34 w(hduaddr)598 b(99)2912 3170 -y(\014ts)p 3039 3170 V 32 w(get)p 3191 3170 V 34 w(hduaddrll)548 -b(99)2912 3283 y(\014ts)p 3039 3283 V 32 w(get)p 3191 -3283 V 34 w(img)p 3371 3283 V 33 w(dim)603 b(43)2912 -3396 y(\014ts)p 3039 3396 V 32 w(get)p 3191 3396 V 34 -w(img)p 3371 3396 V 33 w(equivt)m(yp)s(e)369 b(43)2912 -3509 y(\014ts)p 3039 3509 V 32 w(get)p 3191 3509 V 34 -w(img)p 3371 3509 V 33 w(param)502 b(43)2912 3622 y(\014ts)p -3039 3622 V 32 w(get)p 3191 3622 V 34 w(img)p 3371 3622 -V 33 w(size)614 b(43)2912 3735 y(\014ts)p 3039 3735 V -32 w(get)p 3191 3735 V 34 w(img)p 3371 3735 V 33 w(t)m(yp)s(e)581 -b(43)2912 3848 y(\014ts)p 3039 3848 V 32 w(get)p 3191 -3848 V 34 w(in)m(tt)m(yp)s(e)652 b(69)2912 3961 y(\014ts)p -3039 3961 V 32 w(get)p 3191 3961 V 34 w(k)m(ey)p 3358 -3961 V 34 w(strlen)544 b(39)2912 4074 y(\014ts)p 3039 -4074 V 32 w(get)p 3191 4074 V 34 w(k)m(eyclass)619 b(69)2912 -4187 y(\014ts)p 3039 4187 V 32 w(get)p 3191 4187 V 34 -w(k)m(eyname)589 b(67)2912 4299 y(\014ts)p 3039 4299 -V 32 w(get)p 3191 4299 V 34 w(k)m(eyt)m(yp)s(e)627 b(68)2912 -4412 y(\014ts)p 3039 4412 V 32 w(get)p 3191 4412 V 34 -w(noise)p 3422 4412 V 33 w(bits)557 b(50)2912 4525 y(\014ts)p -3039 4525 V 32 w(get)p 3191 4525 V 34 w(n)m(um)p 3400 -4525 V 32 w(cols)581 b(53)2912 4638 y(\014ts)p 3039 4638 -V 32 w(get)p 3191 4638 V 34 w(n)m(um)p 3400 4638 V 32 -w(groups)463 b(93)2912 4751 y(\014ts)p 3039 4751 V 32 -w(get)p 3191 4751 V 34 w(n)m(um)p 3400 4751 V 32 w(hdus)538 -b(36)2912 4864 y(\014ts)p 3039 4864 V 32 w(get)p 3191 -4864 V 34 w(n)m(um)p 3400 4864 V 32 w(mem)m(b)s(ers)372 -b(92)2912 4977 y(\014ts)p 3039 4977 V 32 w(get)p 3191 -4977 V 34 w(n)m(um)p 3400 4977 V 32 w(ro)m(ws)547 b(53)2912 -5090 y(\014ts)p 3039 5090 V 32 w(get)p 3191 5090 V 34 -w(ro)m(wsize)604 b(115)2912 5203 y(\014ts)p 3039 5203 -V 32 w(get)p 3191 5203 V 34 w(system)p 3496 5203 V 33 -w(time)454 b(65)2912 5316 y(\014ts)p 3039 5316 V 32 w(get)p -3191 5316 V 34 w(tile)p 3350 5316 V 34 w(dim)623 b(50)2912 -5429 y(\014ts)p 3039 5429 V 32 w(get)p 3191 5429 V 34 -w(tb)s(col)735 b(70)2912 5541 y(\014ts)p 3039 5541 V -32 w(get)p 3191 5541 V 34 w(v)m(ersion)656 b(66)2912 -5654 y(\014ts)p 3039 5654 V 32 w(hdr2str)c(40,)31 b(86)1882 -5942 y(171)p eop end -%%Page: 172 180 -TeXDict begin 172 179 bop 0 299 a Fj(172)2084 b Fh(APPENDIX)31 -b(A.)61 b(INDEX)31 b(OF)f(R)m(OUTINES)50 543 y Fj(\014ts)p -177 543 28 4 v 32 w(insert)p 432 543 V 33 w(atbl)502 -b(100)50 656 y(\014ts)p 177 656 V 32 w(insert)p 432 656 -V 33 w(btbl)496 b(100)50 769 y(\014ts)p 177 769 V 32 -w(insert)p 432 769 V 33 w(col)593 b(56)50 882 y(\014ts)p -177 882 V 32 w(insert)p 432 882 V 33 w(cols)557 b(56)50 -995 y(\014ts)p 177 995 V 32 w(insert)p 432 995 V 33 w(group)475 -b(90)50 1107 y(\014ts)p 177 1107 V 32 w(insert)p 432 -1107 V 33 w(img)557 b(99)50 1220 y(\014ts)p 177 1220 -V 32 w(insert)p 432 1220 V 33 w(k)m(ey)p 598 1220 V 34 -w(n)m(ull)342 b(106)50 1333 y(\014ts)p 177 1333 V 32 -w(insert)p 432 1333 V 33 w(k)m(ey)p 598 1333 V 34 w(TYP)295 -b(106)50 1446 y(\014ts)p 177 1446 V 32 w(insert)p 432 -1446 V 33 w(record)410 b(106)50 1559 y(\014ts)p 177 1559 -V 32 w(insert)p 432 1559 V 33 w(ro)m(ws)523 b(56)50 1672 -y(\014ts)p 177 1672 V 32 w(is)p 270 1672 V 33 w(reen)m(tran)m(t)502 -b(75)50 1785 y(\014ts)p 177 1785 V 32 w(iterate)p 465 -1785 V 35 w(data)492 b(83)50 1898 y(\014ts)p 177 1898 -V 32 w(mak)m(e)p 415 1898 V 34 w(hist)572 b(63)50 2011 -y(\014ts)p 177 2011 V 32 w(mak)m(e)p 415 2011 V 34 w(k)m(ey)586 -b(68)50 2124 y(\014ts)p 177 2124 V 32 w(mak)m(e)p 415 -2124 V 34 w(k)m(eyn)535 b(68)50 2237 y(\014ts)p 177 2237 -V 32 w(mak)m(e)p 415 2237 V 34 w(nk)m(ey)g(68)50 2349 -y(\014ts)p 177 2349 V 32 w(merge)p 446 2349 V 34 w(groups)424 -b(91)50 2462 y(\014ts)p 177 2462 V 32 w(mo)s(dify)p 485 -2462 V 32 w(card)434 b(108)50 2575 y(\014ts)p 177 2575 -V 32 w(mo)s(dify)p 485 2575 V 32 w(commen)m(t)291 b(42)50 -2688 y(\014ts)p 177 2688 V 32 w(mo)s(dify)p 485 2688 -V 32 w(k)m(ey)p 650 2688 V 34 w(n)m(ull)f(109)50 2801 -y(\014ts)p 177 2801 V 32 w(mo)s(dify)p 485 2801 V 32 -w(k)m(ey)p 650 2801 V 34 w(TYP)243 b(108)50 2914 y(\014ts)p -177 2914 V 32 w(mo)s(dify)p 485 2914 V 32 w(name)439 -b(42)50 3027 y(\014ts)p 177 3027 V 32 w(mo)s(dify)p 485 -3027 V 32 w(record)358 b(108)50 3140 y(\014ts)p 177 3140 -V 32 w(mo)s(dify)p 485 3140 V 32 w(v)m(ector)p 758 3140 -V 35 w(len)259 b(57)50 3253 y(\014ts)p 177 3253 V 32 -w(mo)m(v)-5 b(abs)p 502 3253 V 33 w(hdu)480 b(36)50 3366 -y(\014ts)p 177 3366 V 32 w(mo)m(vnam)p 547 3366 V 33 -w(hdu)435 b(36)50 3479 y(\014ts)p 177 3479 V 32 w(mo)m(vrel)p -476 3479 V 34 w(hdu)505 b(36)50 3591 y(\014ts)p 177 3591 -V 32 w(n)m(ull)p 358 3591 V 33 w(c)m(hec)m(k)564 b(67)50 -3704 y(\014ts)p 177 3704 V 32 w(op)s(en)p 399 3704 V -32 w(data)d(32)50 3817 y(\014ts)p 177 3817 V 32 w(op)s(en)p -399 3817 V 32 w(disk\014le)461 b(32)50 3930 y(\014ts)p -177 3930 V 32 w(op)s(en)p 399 3930 V 32 w(extlist)493 -b(32)50 4043 y(\014ts)p 177 4043 V 32 w(op)s(en)p 399 -4043 V 32 w(\014le)621 b(32)50 4156 y(\014ts)p 177 4156 -V 32 w(op)s(en)p 399 4156 V 32 w(image)506 b(32)50 4269 -y(\014ts)p 177 4269 V 32 w(op)s(en)p 399 4269 V 32 w(table)541 -b(32)50 4382 y(\014ts)p 177 4382 V 32 w(op)s(en)p 399 -4382 V 32 w(group)509 b(92)50 4495 y(\014ts)p 177 4495 -V 32 w(op)s(en)p 399 4495 V 32 w(mem)m(b)s(er)418 b(93)50 -4608 y(\014ts)p 177 4608 V 32 w(op)s(en)p 399 4608 V -32 w(mem\014le)429 b(95)50 4721 y(\014ts)p 177 4721 V -32 w(parse)p 417 4721 V 33 w(extn)m(um)420 b(97)50 4833 -y(\014ts)p 177 4833 V 32 w(parse)p 417 4833 V 33 w(input)p -663 4833 V 32 w(\014lename)145 b(97)50 4946 y(\014ts)p -177 4946 V 32 w(parse)p 417 4946 V 33 w(input)p 663 4946 -V 32 w(url)361 b(97)50 5059 y(\014ts)p 177 5059 V 32 -w(parse)p 417 5059 V 33 w(range)501 b(74)50 5172 y(\014ts)p -177 5172 V 32 w(parse)p 417 5172 V 33 w(ro)s(otname)342 -b(98)50 5285 y(\014ts)p 177 5285 V 32 w(parse)p 417 5285 -V 33 w(template)371 b(70)50 5398 y(\014ts)p 177 5398 -V 32 w(parse)p 417 5398 V 33 w(v)-5 b(alue)514 b(68)50 -5511 y(\014ts)p 177 5511 V 32 w(pix)p 333 5511 V 33 w(to)p -446 5511 V 33 w(w)m(orld)469 b(87)50 5624 y(\014ts)p -177 5624 V 32 w(read)p 381 5624 V 33 w(2d)p 510 5624 -V 33 w(TYP)384 b(114)50 5737 y(\014ts)p 177 5737 V 32 -w(read)p 381 5737 V 33 w(3d)p 510 5737 V 33 w(TYP)g(114)50 -5850 y(\014ts)p 177 5850 V 32 w(read)p 381 5850 V 33 -w(atblhdr)415 b(103)1374 543 y(\014ts)p 1501 543 V 32 -w(read)p 1705 543 V 33 w(btblhdr)592 b(103)1374 656 y(\014ts)p -1501 656 V 32 w(read)p 1705 656 V 33 w(card)766 b(38)1374 -769 y(\014ts)p 1501 769 V 32 w(read)p 1705 769 V 33 w(col)828 -b(59)1374 882 y(\014ts)p 1501 882 V 32 w(read)p 1705 -882 V 33 w(col)p 1848 882 V 34 w(bit)p 1993 882 V 637 -w(120)1374 995 y(\014ts)p 1501 995 V 32 w(read)p 1705 -995 V 33 w(col)p 1848 995 V 34 w(TYP)552 b(118)1374 1107 -y(\014ts)p 1501 1107 V 32 w(read)p 1705 1107 V 33 w(coln)m(ull)679 -b(59)1374 1220 y(\014ts)p 1501 1220 V 32 w(read)p 1705 -1220 V 33 w(coln)m(ull)p 1997 1220 V 34 w(TYP)403 b(118)1374 -1333 y(\014ts)p 1501 1333 V 32 w(read)p 1705 1333 V 33 -w(descript)578 b(120)1374 1446 y(\014ts)p 1501 1446 V -32 w(read)p 1705 1446 V 33 w(descripts)542 b(120)1374 -1559 y(\014ts)p 1501 1559 V 32 w(read)p 1705 1559 V 33 -w(errmsg)669 b(32)1374 1672 y(\014ts)p 1501 1672 V 32 -w(read)p 1705 1672 V 33 w(ext)769 b(100)1374 1785 y(\014ts)p -1501 1785 V 32 w(read)p 1705 1785 V 33 w(grppar)p 2002 -1785 V 32 w(TYP)400 b(113)1374 1898 y(\014ts)p 1501 1898 -V 32 w(read)p 1705 1898 V 33 w(img)746 b(113)1374 2011 -y(\014ts)p 1501 2011 V 32 w(read)p 1705 2011 V 33 w(img)p -1884 2011 V 33 w(co)s(ord)539 b(87)1374 2124 y(\014ts)p -1501 2124 V 32 w(read)p 1705 2124 V 33 w(img)p 1884 2124 -V 33 w(TYP)517 b(113)1374 2237 y(\014ts)p 1501 2237 V -32 w(read)p 1705 2237 V 33 w(imghdr)608 b(103)1374 2349 -y(\014ts)p 1501 2349 V 32 w(read)p 1705 2349 V 33 w(imgn)m(ull)597 -b(113)1374 2462 y(\014ts)p 1501 2462 V 32 w(read)p 1705 -2462 V 33 w(imgn)m(ull)p 2033 2462 V 33 w(TYP)368 b(113)1374 -2575 y(\014ts)p 1501 2575 V 32 w(read)p 1705 2575 V 33 -w(k)m(ey)805 b(38)1374 2688 y(\014ts)p 1501 2688 V 32 -w(read)p 1705 2688 V 33 w(k)m(ey)p 1871 2688 V 33 w(longstr)453 -b(107)1374 2801 y(\014ts)p 1501 2801 V 32 w(read)p 1705 -2801 V 33 w(k)m(ey)p 1871 2801 V 33 w(triple)514 b(108)1374 -2914 y(\014ts)p 1501 2914 V 32 w(read)p 1705 2914 V 33 -w(k)m(ey)p 1871 2914 V 33 w(unit)610 b(40)1374 3027 y(\014ts)p -1501 3027 V 32 w(read)p 1705 3027 V 33 w(k)m(ey)p 1871 -3027 V 33 w(TYP)530 b(107)1374 3140 y(\014ts)p 1501 3140 -V 32 w(read)p 1705 3140 V 33 w(k)m(eyn)754 b(39)1374 -3253 y(\014ts)p 1501 3253 V 32 w(read)p 1705 3253 V 33 -w(k)m(eys)p 1907 3253 V 33 w(TYP)494 b(107)1374 3366 -y(\014ts)p 1501 3366 V 32 w(read)p 1705 3366 V 33 w(k)m(eyw)m(ord)610 -b(38)1374 3479 y(\014ts)p 1501 3479 V 32 w(read)p 1705 -3479 V 33 w(pix)814 b(46)1374 3591 y(\014ts)p 1501 3591 -V 32 w(read)p 1705 3591 V 33 w(pixn)m(ull)665 b(46)1374 -3704 y(\014ts)p 1501 3704 V 32 w(read)p 1705 3704 V 33 -w(record)690 b(39)1374 3817 y(\014ts)p 1501 3817 V 32 -w(read)p 1705 3817 V 33 w(str)831 b(38)1374 3930 y(\014ts)p -1501 3930 V 32 w(read)p 1705 3930 V 33 w(string)p 1966 -3930 V 33 w(k)m(ey)544 b(39)1374 4043 y(\014ts)p 1501 -4043 V 32 w(read)p 1705 4043 V 33 w(subset)689 b(46)1374 -4156 y(\014ts)p 1501 4156 V 32 w(read)p 1705 4156 V 33 -w(subset)p 1987 4156 V 32 w(TYP)248 b(114)32 b(119)1374 -4269 y(\014ts)p 1501 4269 V 32 w(read)p 1705 4269 V 33 -w(subsetn)m(ull)p 2136 4269 V 32 w(TYP)99 b(114)32 b(119)1374 -4382 y(\014ts)p 1501 4382 V 32 w(read)p 1705 4382 V 33 -w(tbl)p 1849 4382 V 33 w(co)s(ord)574 b(87)1374 4495 -y(\014ts)p 1501 4495 V 32 w(read)p 1705 4495 V 33 w(tblb)m(ytes)g(116) -1374 4608 y(\014ts)p 1501 4608 V 32 w(read)p 1705 4608 -V 33 w(tdim)751 b(55)1374 4721 y(\014ts)p 1501 4721 V -32 w(read)p 1705 4721 V 33 w(w)m(cstab)668 b(86)1374 -4833 y(\014ts)p 1501 4833 V 32 w(rebin)p 1736 4833 V -32 w(w)m(cs)769 b(62)1374 4946 y(\014ts)p 1501 4946 V -32 w(remo)m(v)m(e)p 1812 4946 V 34 w(group)602 b(91)1374 -5059 y(\014ts)p 1501 5059 V 32 w(remo)m(v)m(e)p 1812 -5059 V 34 w(mem)m(b)s(er)511 b(94)1374 5172 y(\014ts)p -1501 5172 V 32 w(reop)s(en)p 1799 5172 V 32 w(\014le)729 -b(96)1374 5285 y(\014ts)p 1501 5285 V 32 w(rep)s(ort)p -1779 5285 V 32 w(error)672 b(32)1374 5398 y(\014ts)p -1501 5398 V 32 w(resize)p 1750 5398 V 34 w(img)700 b(100)1374 -5511 y(\014ts)p 1501 5511 V 32 w(rms)p 1681 5511 V 32 -w(\015oat)787 b(75)1374 5624 y(\014ts)p 1501 5624 V 32 -w(rms)p 1681 5624 V 32 w(short)760 b(75)1374 5737 y(\014ts)p -1501 5737 V 32 w(select)p 1749 5737 V 35 w(ro)m(ws)712 -b(60)1374 5850 y(\014ts)p 1501 5850 V 32 w(set)p 1644 -5850 V 34 w(atbln)m(ull)647 b(110)2881 543 y(\014ts)p -3008 543 V 33 w(set)p 3152 543 V 33 w(bscale)551 b(110)2881 -656 y(\014ts)p 3008 656 V 33 w(set)p 3152 656 V 33 w(btbln)m(ull)477 -b(110)2881 769 y(\014ts)p 3008 769 V 33 w(set)p 3152 -769 V 33 w(compression)p 3666 769 V 33 w(t)m(yp)s(e)145 -b(50)2881 882 y(\014ts)p 3008 882 V 33 w(set)p 3152 882 -V 33 w(hdrsize)509 b(101)2881 995 y(\014ts)p 3008 995 -V 33 w(set)p 3152 995 V 33 w(hdustruc)437 b(101)2881 -1107 y(\014ts)p 3008 1107 V 33 w(set)p 3152 1107 V 33 -w(imgn)m(ull)493 b(110)2881 1220 y(\014ts)p 3008 1220 -V 33 w(set)p 3152 1220 V 33 w(noise)p 3382 1220 V 33 -w(bits)456 b(50)2881 1333 y(\014ts)p 3008 1333 V 33 w(set)p -3152 1333 V 33 w(tile)p 3310 1333 V 34 w(dim)522 b(50)2881 -1446 y(\014ts)p 3008 1446 V 33 w(set)p 3152 1446 V 33 -w(tscale)567 b(110)2881 1559 y(\014ts)p 3008 1559 V 33 -w(split)p 3213 1559 V 33 w(names)524 b(67)2881 1672 y(\014ts)p -3008 1672 V 33 w(str2date)654 b(65)2881 1785 y(\014ts)p -3008 1785 V 33 w(str2time)649 b(65)2881 1898 y(\014ts)p -3008 1898 V 33 w(test)p 3187 1898 V 33 w(expr)623 b(61)2881 -2011 y(\014ts)p 3008 2011 V 33 w(test)p 3187 2011 V 33 -w(heap)566 b(115)2881 2124 y(\014ts)p 3008 2124 V 33 -w(test)p 3187 2124 V 33 w(k)m(eyw)m(ord)470 b(67)2881 -2237 y(\014ts)p 3008 2237 V 33 w(test)p 3187 2237 V 33 -w(record)550 b(67)2881 2349 y(\014ts)p 3008 2349 V 33 -w(time2str)649 b(65)2881 2462 y(\014ts)p 3008 2462 V -33 w(transfer)p 3348 2462 V 32 w(mem)m(b)s(er)319 b(93)2881 -2575 y(\014ts)p 3008 2575 V 33 w(translate)p 3389 2575 -V 34 w(k)m(eyw)m(ord)267 b(73)2881 2688 y(\014ts)p 3008 -2688 V 33 w(up)s(date)p 3317 2688 V 32 w(card)497 b(42)2881 -2801 y(\014ts)p 3008 2801 V 33 w(up)s(date)p 3317 2801 -V 32 w(c)m(hksum)370 b(64)2881 2914 y(\014ts)p 3008 2914 -V 33 w(up)s(date)p 3317 2914 V 32 w(k)m(ey)536 b(41)2881 -3027 y(\014ts)p 3008 3027 V 33 w(up)s(date)p 3317 3027 -V 32 w(k)m(ey)p 3482 3027 V 33 w(longstr)185 b(109)2881 -3140 y(\014ts)p 3008 3140 V 33 w(up)s(date)p 3317 3140 -V 32 w(k)m(ey)p 3482 3140 V 33 w(n)m(ull)354 b(41)2881 -3253 y(\014ts)p 3008 3253 V 33 w(up)s(date)p 3317 3253 -V 32 w(k)m(ey)p 3482 3253 V 33 w(TYP)262 b(109)2881 3366 -y(\014ts)p 3008 3366 V 33 w(upp)s(ercase)584 b(66)2881 -3479 y(\014ts)p 3008 3479 V 33 w(url)p 3153 3479 V 32 -w(t)m(yp)s(e)659 b(35)2881 3591 y(\014ts)p 3008 3591 -V 33 w(v)m(erify)p 3263 3591 V 33 w(c)m(hksum)423 b(64)2881 -3704 y(\014ts)p 3008 3704 V 33 w(v)m(erify)p 3263 3704 -V 33 w(group)494 b(92)2881 3817 y(\014ts)p 3008 3817 -V 33 w(w)m(orld)p 3261 3817 V 32 w(to)p 3373 3817 V 34 -w(pix)487 b(87)2881 3930 y(\014ts)p 3008 3930 V 33 w(write)p -3243 3930 V 33 w(2d)p 3372 3930 V 32 w(TYP)373 b(113)2881 -4043 y(\014ts)p 3008 4043 V 33 w(write)p 3243 4043 V -33 w(3d)p 3372 4043 V 32 w(TYP)g(113)2881 4156 y(\014ts)p -3008 4156 V 33 w(write)p 3243 4156 V 33 w(atblhdr)403 -b(102)2881 4269 y(\014ts)p 3008 4269 V 33 w(write)p 3243 -4269 V 33 w(btblhdr)397 b(103)2881 4382 y(\014ts)p 3008 -4382 V 33 w(write)p 3243 4382 V 33 w(c)m(hksum)443 b(63)2881 -4495 y(\014ts)p 3008 4495 V 33 w(write)p 3243 4495 V -33 w(col)632 b(58)2881 4608 y(\014ts)p 3008 4608 V 33 -w(write)p 3243 4608 V 33 w(col)p 3386 4608 V 34 w(bit)442 -b(117)2881 4721 y(\014ts)p 3008 4721 V 33 w(write)p 3243 -4721 V 33 w(col)p 3386 4721 V 34 w(TYP)357 b(116)2881 -4833 y(\014ts)p 3008 4833 V 33 w(write)p 3243 4833 V -33 w(col)p 3386 4833 V 34 w(n)m(ull)449 b(58)2881 4946 -y(\014ts)p 3008 4946 V 33 w(write)p 3243 4946 V 33 w(coln)m(ull)483 -b(58)2881 5059 y(\014ts)p 3008 5059 V 33 w(write)p 3243 -5059 V 33 w(coln)m(ull)p 3535 5059 V 34 w(TYP)208 b(116)2881 -5172 y(\014ts)p 3008 5172 V 33 w(write)p 3243 5172 V -33 w(commen)m(t)382 b(41)2881 5285 y(\014ts)p 3008 5285 -V 33 w(write)p 3243 5285 V 33 w(date)571 b(41)2881 5398 -y(\014ts)p 3008 5398 V 33 w(write)p 3243 5398 V 33 w(descript)383 -b(117)2881 5511 y(\014ts)p 3008 5511 V 33 w(write)p 3243 -5511 V 33 w(errmark)425 b(32)2881 5624 y(\014ts)p 3008 -5624 V 33 w(write)p 3243 5624 V 33 w(errmsg)473 b(66)2881 -5737 y(\014ts)p 3008 5737 V 33 w(write)p 3243 5737 V -33 w(ext)574 b(100)2881 5850 y(\014ts)p 3008 5850 V 33 -w(write)p 3243 5850 V 33 w(exthdr)436 b(102)p eop end -%%Page: 173 181 -TeXDict begin 173 180 bop 3764 299 a Fj(173)50 543 y(\014ts)p -177 543 28 4 v 32 w(write)p 411 543 V 33 w(grphdr)358 -b(102)50 656 y(\014ts)p 177 656 V 32 w(write)p 411 656 -V 33 w(grppar)p 708 656 V 32 w(TYP)136 b(112)50 769 y(\014ts)p -177 769 V 32 w(write)p 411 769 V 33 w(hdu)520 b(37)50 -882 y(\014ts)p 177 882 V 32 w(write)p 411 882 V 33 w(history)397 -b(41)50 995 y(\014ts)p 177 995 V 32 w(write)p 411 995 -V 33 w(img)482 b(112)50 1107 y(\014ts)p 177 1107 V 32 -w(write)p 411 1107 V 33 w(img)p 590 1107 V 33 w(n)m(ull)300 -b(112)50 1220 y(\014ts)p 177 1220 V 32 w(write)p 411 -1220 V 33 w(img)p 590 1220 V 33 w(TYP)253 b(112)50 1333 -y(\014ts)p 177 1333 V 32 w(write)p 411 1333 V 33 w(imghdr)344 -b(102)50 1446 y(\014ts)p 177 1446 V 32 w(write)p 411 -1446 V 33 w(imgn)m(ull)333 b(112)50 1559 y(\014ts)p 177 -1559 V 32 w(write)p 411 1559 V 33 w(imgn)m(ull)p 739 -1559 V 33 w(TYP)104 b(112)50 1672 y(\014ts)p 177 1672 -V 32 w(write)p 411 1672 V 33 w(k)m(ey)540 b(41)50 1785 -y(\014ts)p 177 1785 V 32 w(write)p 411 1785 V 33 w(k)m(ey)p -577 1785 V 34 w(longstr)188 b(104)50 1898 y(\014ts)p -177 1898 V 32 w(write)p 411 1898 V 33 w(k)m(ey)p 577 -1898 V 34 w(longw)m(arn)100 b(104)50 2011 y(\014ts)p -177 2011 V 32 w(write)p 411 2011 V 33 w(k)m(ey)p 577 -2011 V 34 w(n)m(ull)357 b(41)50 2124 y(\014ts)p 177 2124 -V 32 w(write)p 411 2124 V 33 w(k)m(ey)p 577 2124 V 34 -w(template)114 b(105)50 2237 y(\014ts)p 177 2237 V 32 -w(write)p 411 2237 V 33 w(k)m(ey)p 577 2237 V 34 w(triple)249 -b(105)50 2349 y(\014ts)p 177 2349 V 32 w(write)p 411 -2349 V 33 w(k)m(ey)p 577 2349 V 34 w(unit)344 b(42)50 -2462 y(\014ts)p 177 2462 V 32 w(write)p 411 2462 V 33 -w(k)m(ey)p 577 2462 V 34 w(TYP)265 b(104)50 2575 y(\014ts)p -177 2575 V 32 w(write)p 411 2575 V 33 w(k)m(eys)p 613 -2575 V 34 w(TYP)229 b(105)50 2688 y(\014ts)p 177 2688 -V 32 w(write)p 411 2688 V 33 w(k)m(eys)p 613 2688 V 34 -w(histo)278 b(62)50 2801 y(\014ts)p 177 2801 V 32 w(write)p -411 2801 V 33 w(n)m(ull)p 593 2801 V 33 w(img)345 b(45)50 -2914 y(\014ts)p 177 2914 V 32 w(write)p 411 2914 V 33 -w(n)m(ullro)m(ws)f(58)50 3027 y(\014ts)p 177 3027 V 32 -w(write)p 411 3027 V 33 w(pix)549 b(45)50 3140 y(\014ts)p -177 3140 V 32 w(write)p 411 3140 V 33 w(pixn)m(ull)400 -b(45)50 3253 y(\014ts)p 177 3253 V 32 w(write)p 411 3253 -V 33 w(record)425 b(42)50 3366 y(\014ts)p 177 3366 V -32 w(write)p 411 3366 V 33 w(subset)f(45)50 3479 y(\014ts)p -177 3479 V 32 w(write)p 411 3479 V 33 w(subset)p 693 -3479 V 32 w(TYP)151 b(113)50 3591 y(\014ts)p 177 3591 -V 32 w(write)p 411 3591 V 33 w(tblb)m(ytes)310 b(116)50 -3704 y(\014ts)p 177 3704 V 32 w(write)p 411 3704 V 33 -w(tdim)486 b(55)50 3817 y(\014ts)p 177 3817 V 32 w(write)p -411 3817 V 33 w(theap)406 b(115)p eop end -%%Page: 174 182 -TeXDict begin 174 181 bop 0 299 a Fj(174)2084 b Fh(APPENDIX)31 -b(A.)61 b(INDEX)31 b(OF)f(R)m(OUTINES)50 543 y Fj(\013asfm)422 -b(70)50 656 y(\013bnfm)401 b(70)50 769 y(\013calc)457 -b(60)50 882 y(\013calc)p 258 882 28 4 v 34 w(rng)291 -b(60)50 995 y(\013clos)461 b(35)50 1107 y(\013cmph)344 -b(115)50 1220 y(\013cmps)404 b(66)50 1333 y(\013cmrk)j(32)50 -1446 y(\013cmsg)j(32)50 1559 y(\013cop)m(y)426 b(37)50 -1672 y(\013cp)s(cl)448 b(57)50 1785 y(\013cp)s(dt)382 -b(100)50 1898 y(\013cp\015)465 b(36)50 2011 y(\013cphd)414 -b(37)50 2124 y(\013cpimg)370 b(47)50 2237 y(\013cpky)375 -b(105)50 2349 y(\013cprw)414 b(57)50 2462 y(\013crhd)429 -b(99)50 2575 y(\013crim)h(44)50 2688 y(\013cro)m(w)423 -b(60)50 2801 y(\013crtb)445 b(52)50 2914 y(\013dcol)h(56)50 -3027 y(\013delt)456 b(35)50 3140 y(\013dhdu)403 b(37)50 -3253 y(\013dk)m(ey)423 b(42)50 3366 y(\013dkinit)372 -b(34)50 3479 y(\013dk)m(op)s(en)321 b(32)50 3591 y(\013dopn)409 -b(32)50 3704 y(\013drec)440 b(42)50 3817 y(\013dro)m(w)412 -b(56)50 3930 y(\013drrg)439 b(56)50 4043 y(\013drws)418 -b(56)50 4156 y(\013dstr)449 b(42)50 4269 y(\013dsum)393 -b(64)50 4382 y(\013dt2s)440 b(65)50 4495 y(\013dtdm)394 -b(55)50 4608 y(\013dt)m(yp)425 b(68)50 4721 y(\013eopn)420 -b(32)50 4833 y(\013eqt)m(y)439 b(54)50 4946 y(\013esum)404 -b(64)50 5059 y(\013exest)k(98)50 5172 y(\013extn)433 -b(97)50 5285 y(\013\013rw)452 b(60)50 5398 y(\013\015md)429 -b(35)50 5511 y(\013\015nm)g(35)50 5624 y(\013\015sh)469 -b(98)50 5737 y(\013\015us)g(98)50 5850 y(\013free)271 -b(107,)32 b(40)931 543 y(\013fro)m(w)193 b(59)931 656 -y(\013g2d)p 1130 656 V 178 w(114)931 769 y(\013g3d)p -1130 769 V 178 w(114)931 882 y(\013gab)s(c)181 b(70)931 -995 y(\013gacl)164 b(114)931 1107 y(\013gb)s(cl)155 b(114)931 -1220 y(\013gcdw)163 b(55)931 1333 y(\013gcf)252 b(59)931 -1446 y(\013gcf)p 1102 1446 V 206 w(118)931 1559 y(\013gc)m(ks)199 -b(64)931 1672 y(\013gcnn)178 b(53)931 1785 y(\013gcno)184 -b(53)931 1898 y(\013gcrd)193 b(38)931 2011 y(\013gcv)232 -b(59)931 2124 y(\013gcv)p 1122 2124 V 186 w(118)931 2237 -y(\013gcx)186 b(120)931 2349 y(\013gdes)147 b(120)931 -2462 y(\013gdess)111 b(120)931 2575 y(\013gerr)208 b(31)931 -2688 y(\013gextn)100 b(100)931 2801 y(\013ggp)p 1130 -2801 V 178 w(113)931 2914 y(\013ghad)173 b(99)931 3027 -y(\013gh)m(bn)124 b(103)931 3140 y(\013ghdn)167 b(36)931 -3253 y(\013ghdt)183 b(36)931 3366 y(\013ghpr)136 b(103)931 -3479 y(\013ghps)g(101)931 3591 y(\013ghsp)182 b(38)931 -3704 y(\013gh)m(tb)140 b(103)931 3817 y(\013gics)219 -b(87)931 3930 y(\013gidm)168 b(43)931 4043 y(\013gidt)209 -b(43)931 4156 y(\013giet)220 b(43)931 4269 y(\013gipr)208 -b(43)931 4382 y(\013gisz)219 b(43)931 4495 y(\013gk)m(cl)210 -b(69)931 4608 y(\013gk)m(ey)187 b(38)931 4721 y(\013gkls)165 -b(107)931 4833 y(\013gksl)211 b(39)931 4946 y(\013gkn)p -1133 4946 V 175 w(107)931 5059 y(\013gknm)145 b(67)931 -5172 y(\013gky)224 b(38)931 5285 y(\013gkyn)173 b(39)931 -5398 y(\013gkyt)143 b(108)931 5511 y(\013gky)p 1130 5511 -V 178 w(107)931 5624 y(\013gmcp)153 b(93)931 5737 y(\013gmng)148 -b(93)931 5850 y(\013gmop)g(93)1570 543 y(\013gmrm)311 -b(94)1570 656 y(\013gmsg)342 b(32)1570 769 y(\013gm)m(tf)363 -b(93)1570 882 y(\013gncl)383 b(53)1570 995 y(\013gnrw)346 -b(53)1570 1107 y(\013gnxk)352 b(39)1570 1220 y(\013gpf)375 -b(113)1570 1333 y(\013gpf)p 1752 1333 V 375 w(113)1570 -1446 y(\013gp)m(v)358 b(113)1570 1559 y(\013gp)m(v)p -1769 1559 V 358 w(113)1570 1672 y(\013gp)m(xv)d(46)1570 -1785 y(\013gp)m(xf)375 b(46)1570 1898 y(\013grec)383 -b(39)1570 2011 y(\013grsz)342 b(115)1570 2124 y(\013gsdt)377 -b(65)1570 2237 y(\013gsf)p 1737 2237 V 223 w(114)32 b(119)1570 -2349 y(\013gsky)367 b(39)1570 2462 y(\013gstm)352 b(65)1570 -2575 y(\013gstr)392 b(38)1570 2688 y(\013gsv)415 b(46)1570 -2801 y(\013gsv)p 1757 2801 V 203 w(114)32 b(119)1570 -2914 y(\013gtam)343 b(92)1570 3027 y(\013gtbb)317 b(116)1570 -3140 y(\013gtc)m(h)376 b(90)1570 3253 y(\013gtcl)399 -b(54)1570 3366 y(\013gtcm)348 b(91)1570 3479 y(\013gtcp)373 -b(91)1570 3591 y(\013gtcr)388 b(90)1570 3704 y(\013gtcs)g(87)1570 -3817 y(\013gtdm)337 b(55)1570 3930 y(\013gthd)362 b(70)1570 -4043 y(\013gtis)403 b(90)1570 4156 y(\013gtmg)343 b(91)1570 -4269 y(\013gtnm)337 b(92)1570 4382 y(\013gtop)368 b(92)1570 -4495 y(\013gtrm)352 b(91)1570 4608 y(\013gtvf)388 b(92)1570 -4721 y(\013gun)m(t)365 b(40)1570 4833 y(\013hdef)329 -b(101)1570 4946 y(\016bin)349 b(100)1570 5059 y(\016cls)420 -b(56)1570 5172 y(\016col)411 b(56)1570 5285 y(\016\014le)405 -b(97)1570 5398 y(\016img)375 b(99)1570 5511 y(\016kls)367 -b(106)1570 5624 y(\016kyu)329 b(106)1570 5737 y(\016ky)p -1747 5737 V 380 w(106)1570 5850 y(\016mem)g(96)2388 543 -y(\016nit)258 b(34)2388 656 y(\016n)m(tt)m(yp)155 b(69)2388 -769 y(\016opn)222 b(32)2388 882 y(\016rec)208 b(106)2388 -995 y(\016ro)m(w)225 b(56)2388 1107 y(\016tab)193 b(100)2388 -1220 y(\016ter)258 b(83)2388 1333 y(\016url)f(97)2388 -1446 y(\013k)m(eyn)208 b(68)2388 1559 y(\013mahd)169 -b(36)2388 1672 y(\013mcom)155 b(42)2388 1785 y(\013mcrd)144 -b(108)2388 1898 y(\013mkky)172 b(68)2388 2011 y(\013mkls)162 -b(108)2388 2124 y(\013mkyu)124 b(109)2388 2237 y(\013mky)p -2618 2237 V 175 w(108)2388 2349 y(\013mnam)144 b(42)2388 -2462 y(\013mnhd)163 b(36)2388 2575 y(\013mrec)155 b(108)2388 -2688 y(\013mrhd)178 b(36)2388 2801 y(\013m)m(v)m(ec)194 -b(57)2388 2914 y(\013nc)m(hk)205 b(67)2388 3027 y(\013nk)m(ey)j(68)2388 -3140 y(\013omem)155 b(95)2388 3253 y(\013op)s(en)202 -b(32)2388 3366 y(\013p2d)p 2593 3366 V 200 w(113)2388 -3479 y(\013p3d)p 2593 3479 V 200 w(113)2388 3591 y(\013p)s(c)m(ks)217 -b(63)2388 3704 y(\013p)s(cl)273 b(58)2388 3817 y(\013p)s(cls)192 -b(116)2388 3930 y(\013p)s(cl)p 2565 3930 V 228 w(117)2388 -4043 y(\013p)s(clu)222 b(58)2388 4156 y(\013p)s(cn)247 -b(58)2388 4269 y(\013p)s(cn)p 2591 4269 V 202 w(116)2388 -4382 y(\013p)s(com)177 b(41)2388 4495 y(\013p)s(dat)207 -b(41)2388 4608 y(\013p)s(des)166 b(117)2388 4721 y(\013p)s(extn)119 -b(100)2388 4833 y(\013pgp)p 2593 4833 V 200 w(112)2388 -4946 y(\013ph)m(bn)146 b(103)2388 5059 y(\013phext)122 -b(102)2388 5172 y(\013phis)229 b(41)2388 5285 y(\013phpr)158 -b(102)2388 5398 y(\013phps)g(102)2388 5511 y(\013ph)m(tb)k(102)2388 -5624 y(\013pkls)187 b(104)2388 5737 y(\013pkn)p 2596 -5737 V 197 w(105)2388 5850 y(\013pktp)162 b(105)3054 -543 y(\013pky)264 b(41)3054 656 y(\013pkyt)183 b(105)3054 -769 y(\013pkyu)213 b(41)3054 882 y(\013pky)p 3259 882 -V 218 w(104)3054 995 y(\013plsw)187 b(104)3054 1107 y(\013pmrk)200 -b(32)3054 1220 y(\013pmsg)j(66)3054 1333 y(\013pn)m(ul)190 -b(110)3054 1446 y(\013ppn)212 b(112)3054 1559 y(\013ppn)p -3265 1559 V 212 w(112)3054 1672 y(\013ppr)227 b(112)3054 -1785 y(\013pprn)222 b(45)3054 1898 y(\013ppru)176 b(112)3054 -2011 y(\013ppr)p 3250 2011 V 227 w(112)3054 2124 y(\013pp)m(x)264 -b(45)3054 2237 y(\013pp)m(xn)213 b(45)3054 2349 y(\013prec)244 -b(42)3054 2462 y(\013prwu)207 b(58)3054 2575 y(\013pscl)213 -b(110)3054 2688 y(\013pss)288 b(45)3054 2801 y(\013pss)p -3235 2801 V 242 w(113)3054 2914 y(\013psv)m(c)239 b(68)3054 -3027 y(\013ptbb)177 b(116)3054 3140 y(\013ptdm)198 b(55)3054 -3253 y(\013pthp)177 b(115)3054 3366 y(\013pun)m(t)226 -b(42)3054 3479 y(\013rdef)210 b(101)3054 3591 y(\013reop)s(en)145 -b(96)3054 3704 y(\013rprt)253 b(32)3054 3817 y(\013rsim)192 -b(100)3054 3930 y(\013rtnm)213 b(98)3054 4043 y(\013rwrg)228 -b(74)3054 4156 y(\013s2dt)244 b(65)3054 4269 y(\013s2tm)219 -b(65)3054 4382 y(\013sn)m(ul)205 b(110)3054 4495 y(\013sro)m(w)231 -b(60)3054 4608 y(\013texp)237 b(61)3054 4721 y(\013thdu)223 -b(36)3054 4833 y(\013theap)143 b(115)3054 4946 y(\013tk)m(ey)243 -b(67)3054 5059 y(\013tm2s)219 b(65)3054 5172 y(\013tn)m(ul)206 -b(110)3054 5285 y(\013topn)229 b(32)3054 5398 y(\013tplt)265 -b(96)3054 5511 y(\013trec)260 b(67)3054 5624 y(\013tscl)229 -b(110)3054 5737 y(\013ucrd)k(42)3054 5850 y(\013ukls)205 -b(109)p eop end -%%Page: 175 183 -TeXDict begin 175 182 bop 3764 299 a Fj(175)50 543 y(\013uky)251 -b(41)50 656 y(\013ukyu)200 b(41)50 769 y(\013uky)p 255 -769 28 4 v 205 w(109)50 882 y(\013up)s(c)m(h)205 b(66)50 -995 y(\013up)s(c)m(k)j(64)50 1107 y(\013urlt)251 b(35)50 -1220 y(\013v)m(c)m(ks)232 b(64)50 1333 y(\013v)m(ers)241 -b(66)50 1446 y(\013wldp)205 b(87)50 1559 y(\013wrhdu)143 -b(37)50 1672 y(\013xyp)m(x)206 b(87)p eop end -%%Page: 176 184 -TeXDict begin 176 183 bop 0 299 a Fj(176)2084 b Fh(APPENDIX)31 -b(A.)61 b(INDEX)31 b(OF)f(R)m(OUTINES)p eop end -%%Page: 177 185 -TeXDict begin 177 184 bop 0 1225 a Fg(App)5 b(endix)64 -b(B)0 1687 y Fm(P)-6 b(arameter)77 b(De\014nitions)0 -2180 y Fe(anynul)142 b(-)47 b(set)g(to)g(TRUE)g(\(=1\))f(if)i(any)e -(returned)g(values)g(are)h(undefined,)e(else)i(FALSE)0 -2293 y(array)190 b(-)47 b(array)f(of)i(numerical)d(data)h(values)h(to)g -(read)f(or)i(write)0 2406 y(ascii)190 b(-)47 b(encoded)f(checksum)f -(string)0 2518 y(binspec)94 b(-)47 b(the)g(input)f(table)h(binning)e -(specifier)0 2631 y(bitpix)142 b(-)47 b(bits)g(per)g(pixel.)f(The)h -(following)e(symbolic)g(mnemonics)h(are)h(predefined:)716 -2744 y(BYTE_IMG)141 b(=)i(8)47 b(\(unsigned)f(char\))716 -2857 y(SHORT_IMG)93 b(=)i(16)47 b(\(signed)f(short)g(integer\))716 -2970 y(LONG_IMG)141 b(=)95 b(32)47 b(\(signed)f(long)h(integer\))716 -3083 y(LONGLONG_IMG)d(=)96 b(64)47 b(\(signed)f(long)g(64-bit)g -(integer\))716 3196 y(FLOAT_IMG)93 b(=)47 b(-32)g(\(float\))716 -3309 y(DOUBLE_IMG)e(=)i(-64)g(\(double\).)525 3422 y(Two)g(additional)e -(values,)h(USHORT_IMG)f(and)i(ULONG_IMG)e(are)i(also)f(available)525 -3535 y(for)h(creating)e(unsigned)h(integer)g(images.)93 -b(These)47 b(are)g(equivalent)e(to)525 3648 y(creating)h(a)h(signed)f -(integer)g(image)g(with)h(BZERO)f(offset)g(keyword)g(values)525 -3760 y(of)h(32768)g(or)g(2147483648,)d(respectively,)h(which)h(is)h -(the)g(convention)e(that)525 3873 y(FITS)i(uses)f(to)h(store)g -(unsigned)e(integers.)0 3986 y(card)238 b(-)47 b(header)f(record)g(to)h -(be)h(read)e(or)h(written)f(\(80)h(char)g(max,)f(null-terminated\))0 -4099 y(casesen)94 b(-)47 b(CASESEN)f(\(=1\))g(for)h(case-sensitive)d -(string)i(matching,)g(else)g(CASEINSEN)g(\(=0\))0 4212 -y(cmopt)190 b(-)47 b(grouping)f(table)g("compact")f(option)h -(parameter.)f(Allowed)h(values)g(are:)525 4325 y(OPT_CMT_MBR)f(and)i -(OPT_CMT_MBR_DEL.)0 4438 y(colname)94 b(-)47 b(name)g(of)g(the)g -(column)f(\(null-terminated\))0 4551 y(colnum)142 b(-)47 -b(column)f(number)g(\(first)g(column)g(=)i(1\))0 4664 -y(colspec)94 b(-)47 b(the)g(input)f(file)h(column)f(specification;)e -(used)j(to)g(delete,)f(create,)f(or)j(rename)525 4777 -y(table)e(columns)0 4890 y(comment)94 b(-)47 b(the)g(keyword)f(comment) -g(field)g(\(72)h(char)f(max,)h(null-terminated\))0 5002 -y(complm)142 b(-)47 b(should)f(the)h(checksum)f(be)h(complemented?)0 -5115 y(comptype)f(-)h(compression)e(algorithm)g(to)i(use:)g(GZIP_1,)f -(RICE_1,)f(HCOMPRESS_1,)g(or)i(PLIO_1)0 5228 y(coordtype-)e(type)i(of)g -(coordinate)e(projection)g(\(-SIN,)h(-TAN,)g(-ARC,)h(-NCP,)525 -5341 y(-GLS,)f(-MER,)h(or)g(-AIT\))0 5454 y(cpopt)190 -b(-)47 b(grouping)f(table)g(copy)h(option)f(parameter.)f(Allowed)g -(values)i(are:)525 5567 y(OPT_GCP_GPT,)d(OPT_GCP_MBR,)h(OPT_GCP_ALL,)f -(OPT_MCP_ADD,)h(OPT_MCP_NADD,)525 5680 y(OPT_MCP_REPL,)f(amd)j -(OPT_MCP_MOV.)1882 5942 y Fj(177)p eop end -%%Page: 178 186 -TeXDict begin 178 185 bop 0 299 a Fj(178)1822 b Fh(APPENDIX)31 -b(B.)61 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)0 555 y Fe(create_col-)45 -b(If)i(TRUE,)f(then)h(insert)f(a)h(new)g(column)f(in)i(the)f(table,)f -(otherwise)525 668 y(overwrite)f(the)i(existing)f(column.)0 -781 y(current)94 b(-)47 b(if)g(TRUE,)g(then)f(the)h(current)f(HDU)h -(will)f(be)i(copied)0 894 y(dataok)142 b(-)47 b(was)g(the)g(data)f -(unit)h(verification)e(successful)g(\(=1\))h(or)525 1007 -y(not)h(\(=)g(-1\).)94 b(Equals)47 b(zero)f(if)h(the)g(DATASUM)f -(keyword)g(is)h(not)g(present.)0 1120 y(datasum)94 b(-)47 -b(32-bit)f(1's)h(complement)e(checksum)h(for)g(the)h(data)g(unit)0 -1233 y(dataend)94 b(-)47 b(address)f(\(in)h(bytes\))f(of)h(the)g(end)g -(of)g(the)g(HDU)0 1346 y(datastart-)e(address)h(\(in)h(bytes\))f(of)h -(the)g(start)f(of)h(the)g(data)g(unit)0 1458 y(datatype)f(-)h -(specifies)e(the)i(data)g(type)f(of)i(the)f(value.)93 -b(Allowed)46 b(value)h(are:)94 b(TSTRING,)525 1571 y(TLOGICAL,)45 -b(TBYTE,)h(TSBYTE,)g(TSHORT,)g(TUSHORT,)g(TINT,)g(TUINT,)g(TLONG,)g -(TULONG,)525 1684 y(TFLOAT,)g(TDOUBLE,)f(TCOMPLEX,)h(and)h(TDBLCOMPLEX) -0 1797 y(datestr)94 b(-)47 b(FITS)g(date/time)e(string:)h -('YYYY-MM-DDThh:mm:ss.dd)o(d',)41 b('YYYY-MM-dd',)525 -1910 y(or)47 b('dd/mm/yy')0 2023 y(day)286 b(-)47 b(calendar)f(day)g -(\(UTC\))h(\(1-31\))0 2136 y(decimals)f(-)h(number)f(of)h(decimal)f -(places)g(to)h(be)h(displayed)0 2249 y(deltasize)d(-)j(increment)d(for) -i(allocating)e(more)i(memory)0 2362 y(dim1)238 b(-)47 -b(declared)f(size)g(of)h(the)g(first)g(dimension)e(of)i(the)g(image)f -(or)i(cube)e(array)0 2475 y(dim2)238 b(-)47 b(declared)f(size)g(of)h -(the)g(second)f(dimension)g(of)h(the)g(data)f(cube)h(array)0 -2588 y(dispwidth)e(-)j(display)e(width)g(of)h(a)h(column)e(=)h(length)f -(of)h(string)f(that)h(will)g(be)g(read)0 2700 y(dtype)190 -b(-)47 b(data)g(type)f(of)h(the)g(keyword)f(\('C',)h('L',)f('I',)h('F') -g(or)g('X'\))764 2813 y(C)g(=)h(character)d(string)764 -2926 y(L)i(=)h(logical)764 3039 y(I)f(=)h(integer)764 -3152 y(F)f(=)h(floating)d(point)h(number)764 3265 y(X)h(=)h(complex,)d -(e.g.,)h("\(1.23,)g(-4.56\)")0 3378 y(err_msg)94 b(-)47 -b(error)f(message)g(on)h(the)g(internal)f(stack)g(\(80)h(chars)f(max\)) -0 3491 y(err_text)g(-)h(error)f(message)g(string)g(corresponding)e(to)k -(error)e(number)g(\(30)h(chars)f(max\))0 3604 y(exact)190 -b(-)47 b(TRUE)g(\(=1\))f(if)h(the)g(strings)f(match)h(exactly;)525 -3717 y(FALSE)f(\(=0\))h(if)g(wildcards)e(are)i(used)0 -3830 y(exclist)94 b(-)47 b(array)f(of)i(pointers)d(to)i(keyword)f -(names)g(to)i(be)f(excluded)e(from)i(search)0 3942 y(exists)142 -b(-)47 b(flag)g(indicating)e(whether)g(the)i(file)g(or)g(compressed)e -(file)i(exists)f(on)h(disk)0 4055 y(expr)238 b(-)47 b(boolean)f(or)h -(arithmetic)e(expression)0 4168 y(extend)142 b(-)47 b(TRUE)g(\(=1\))f -(if)h(FITS)g(file)g(may)g(have)f(extensions,)f(else)i(FALSE)f(\(=0\))0 -4281 y(extname)94 b(-)47 b(value)f(of)i(the)e(EXTNAME)g(keyword)g -(\(null-terminated\))0 4394 y(extspec)94 b(-)47 b(the)g(extension)e(or) -i(HDU)g(specifier;)e(a)j(number)e(or)h(name,)f(version,)g(and)h(type)0 -4507 y(extver)142 b(-)47 b(value)f(of)i(the)e(EXTVER)h(keyword)e(=)j -(integer)e(version)f(number)0 4620 y(filename)h(-)h(full)g(name)f(of)h -(the)g(FITS)g(file,)f(including)g(optional)f(HDU)i(and)g(filtering)e -(specs)0 4733 y(filetype)h(-)h(type)g(of)g(file)f(\(file://,)g(ftp://,) -g(http://,)f(etc.\))0 4846 y(filter)142 b(-)47 b(the)g(input)f(file)h -(filtering)e(specifier)0 4959 y(firstchar-)g(starting)h(byte)g(in)h -(the)g(row)g(\(first)f(byte)h(of)g(row)g(=)g(1\))0 5072 -y(firstfailed)e(-)i(member)f(HDU)h(ID)g(\(if)g(positive\))f(or)h -(grouping)e(table)i(GRPIDn)f(index)525 5185 y(value)g(\(if)h -(negative\))f(that)g(failed)g(grouping)g(table)g(verification.)0 -5297 y(firstelem-)f(first)h(element)g(in)h(a)h(vector)e(\(ignored)f -(for)i(ASCII)g(tables\))0 5410 y(firstrow)f(-)h(starting)f(row)g -(number)h(\(first)f(row)h(of)g(table)f(=)i(1\))0 5523 -y(following-)d(if)i(TRUE,)g(any)f(HDUs)h(following)e(the)i(current)f -(HDU)h(will)g(be)g(copied)0 5636 y(fpixel)142 b(-)47 -b(coordinate)e(of)i(the)g(first)f(pixel)h(to)g(be)g(read)g(or)g -(written)f(in)h(the)p eop end -%%Page: 179 187 -TeXDict begin 179 186 bop 3764 299 a Fj(179)525 555 y -Fe(FITS)47 b(array.)93 b(The)47 b(array)g(must)f(be)i(of)f(length)f -(NAXIS)g(and)h(have)g(values)f(such)525 668 y(that)h(fpixel[0])e(is)i -(in)g(the)g(range)g(1)g(to)g(NAXIS1,)f(fpixel[1])f(is)i(in)h(the)525 -781 y(range)e(1)i(to)f(NAXIS2,)f(etc.)0 894 y(fptr)238 -b(-)47 b(pointer)f(to)h(a)g('fitsfile')e(structure)h(describing)f(the)i -(FITS)f(file.)0 1007 y(frac)238 b(-)47 b(factional)e(part)i(of)g(the)g -(keyword)f(value)0 1120 y(gcount)142 b(-)47 b(number)f(of)h(groups)f -(in)i(the)e(primary)g(array)h(\(usually)e(=)j(1\))0 1233 -y(gfptr)190 b(-)47 b(fitsfile*)e(pointer)h(to)h(a)h(grouping)d(table)i -(HDU.)0 1346 y(group)190 b(-)47 b(GRPIDn/GRPLCn)d(index)j(value)f -(identifying)f(a)i(grouping)f(table)g(HDU,)h(or)525 1458 -y(data)g(group)f(number)g(\(=0)h(for)g(non-grouped)e(data\))0 -1571 y(grouptype)g(-)j(Grouping)d(table)i(parameter)e(that)i(specifies) -e(the)i(columns)f(to)h(be)525 1684 y(created)f(in)h(a)g(grouping)f -(table)g(HDU.)h(Allowed)f(values)g(are:)h(GT_ID_ALL_URI,)525 -1797 y(GT_ID_REF,)e(GT_ID_POS,)g(GT_ID_ALL,)g(GT_ID_REF_URI,)f(and)j -(GT_ID_POS_URI.)0 1910 y(grpname)94 b(-)47 b(value)f(to)i(use)e(for)h -(the)g(GRPNAME)f(keyword)g(value.)0 2023 y(hdunum)142 -b(-)47 b(sequence)f(number)g(of)h(the)g(HDU)g(\(Primary)e(array)i(=)g -(1\))0 2136 y(hduok)190 b(-)47 b(was)g(the)g(HDU)g(verification)d -(successful)h(\(=1\))i(or)525 2249 y(not)g(\(=)g(-1\).)94 -b(Equals)47 b(zero)f(if)h(the)g(CHECKSUM)f(keyword)g(is)h(not)g -(present.)0 2362 y(hdusum)142 b(-)47 b(32)g(bit)g(1's)g(complement)e -(checksum)h(for)g(the)h(entire)f(CHDU)0 2475 y(hdutype)94 -b(-)47 b(HDU)g(type:)f(IMAGE_HDU)g(\(0\),)g(ASCII_TBL)f(\(1\),)i -(BINARY_TBL)e(\(2\),)i(ANY_HDU)f(\(-1\))0 2588 y(header)142 -b(-)47 b(returned)f(character)f(string)h(containing)f(all)i(the)g -(keyword)f(records)0 2700 y(headstart-)f(starting)h(address)f(\(in)i -(bytes\))f(of)i(the)e(CHDU)0 2813 y(heapsize)g(-)h(size)g(of)g(the)g -(binary)f(table)g(heap,)h(in)g(bytes)0 2926 y(history)94 -b(-)47 b(the)g(HISTORY)f(keyword)g(comment)f(string)h(\(70)h(char)g -(max,)g(null-terminated\))0 3039 y(hour)238 b(-)47 b(hour)g(within)f -(day)h(\(UTC\))f(\(0)h(-)h(23\))0 3152 y(inc)286 b(-)47 -b(sampling)f(interval)f(for)i(pixels)f(in)h(each)g(FITS)g(dimension)0 -3265 y(inclist)94 b(-)47 b(array)f(of)i(pointers)d(to)i(matching)f -(keyword)g(names)0 3378 y(incolnum)g(-)h(input)f(column)g(number;)g -(range)h(=)g(1)h(to)f(TFIELDS)0 3491 y(infile)142 b(-)47 -b(the)g(input)f(filename,)g(including)f(path)h(if)i(specified)0 -3604 y(infptr)142 b(-)47 b(pointer)f(to)h(a)g('fitsfile')e(structure)h -(describing)f(the)i(input)f(FITS)h(file.)0 3717 y(intval)142 -b(-)47 b(integer)f(part)g(of)i(the)f(keyword)e(value)0 -3830 y(iomode)142 b(-)47 b(file)g(access)f(mode:)g(either)g(READONLY)g -(\(=0\))g(or)i(READWRITE)d(\(=1\))0 3942 y(keyname)94 -b(-)47 b(name)g(of)g(a)g(keyword)f(\(8)h(char)g(max,)g -(null-terminated\))0 4055 y(keynum)142 b(-)47 b(position)f(of)h -(keyword)f(in)h(header)f(\(1st)g(keyword)g(=)i(1\))0 -4168 y(keyroot)94 b(-)47 b(root)g(string)f(for)h(the)g(keyword)e(name)i -(\(5)g(char)g(max,)f(null-terminated\))0 4281 y(keysexist-)f(number)h -(of)h(existing)f(keyword)g(records)f(in)j(the)f(CHU)0 -4394 y(keytype)94 b(-)47 b(header)f(record)g(type:)h(-1=delete;)92 -b(0=append)46 b(or)h(replace;)907 4507 y(1=append;)e(2=this)h(is)h(the) -g(END)g(keyword)0 4620 y(longstr)94 b(-)47 b(arbitrarily)e(long)h -(string)g(keyword)g(value)h(\(null-terminated\))0 4733 -y(lpixel)142 b(-)47 b(coordinate)e(of)i(the)g(last)g(pixel)f(to)h(be)g -(read)g(or)g(written)f(in)h(the)525 4846 y(FITS)g(array.)93 -b(The)47 b(array)g(must)f(be)i(of)f(length)f(NAXIS)g(and)h(have)g -(values)f(such)525 4959 y(that)h(lpixel[0])e(is)i(in)g(the)g(range)g(1) -g(to)g(NAXIS1,)f(lpixel[1])f(is)i(in)h(the)525 5072 y(range)e(1)i(to)f -(NAXIS2,)f(etc.)0 5185 y(match)190 b(-)47 b(TRUE)g(\(=1\))f(if)h(the)g -(2)h(strings)e(match,)g(else)g(FALSE)h(\(=0\))0 5297 -y(maxdim)142 b(-)47 b(maximum)f(number)g(of)h(values)f(to)h(return)0 -5410 y(member)142 b(-)47 b(row)g(number)f(of)h(a)h(grouping)d(table)i -(member)f(HDU.)0 5523 y(memptr)142 b(-)47 b(pointer)f(to)h(the)g(a)g -(FITS)g(file)g(in)g(memory)0 5636 y(mem_realloc)e(-)i(pointer)f(to)h(a) -h(function)d(for)i(reallocating)e(more)h(memory)p eop -end -%%Page: 180 188 -TeXDict begin 180 187 bop 0 299 a Fj(180)1822 b Fh(APPENDIX)31 -b(B.)61 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)0 555 y Fe(memsize)94 -b(-)47 b(size)g(of)g(the)g(memory)f(block)g(allocated)f(for)i(the)g -(FITS)g(file)0 668 y(mfptr)190 b(-)47 b(fitsfile*)e(pointer)h(to)h(a)h -(grouping)d(table)i(member)f(HDU.)0 781 y(mgopt)190 b(-)47 -b(grouping)f(table)g(merge)g(option)g(parameter.)f(Allowed)h(values)g -(are:)525 894 y(OPT_MRG_COPY,)e(and)j(OPT_MRG_MOV.)0 -1007 y(minute)142 b(-)47 b(minute)f(within)g(hour)h(\(UTC\))f(\(0)h(-)h -(59\))0 1120 y(month)190 b(-)47 b(calendar)f(month)g(\(UTC\))g(\(1)h(-) -h(12\))0 1233 y(morekeys)e(-)h(space)f(in)i(the)e(header)h(for)f(this)h -(many)g(more)f(keywords)0 1346 y(n_good_rows)f(-)i(number)f(of)h(rows)g -(evaluating)e(to)i(TRUE)0 1458 y(namelist)f(-)h(string)f(containing)f -(a)j(comma)e(or)h(space)f(delimited)g(list)g(of)i(names)0 -1571 y(naxes)190 b(-)47 b(size)g(of)g(each)f(dimension)g(in)h(the)g -(FITS)f(array)0 1684 y(naxis)190 b(-)47 b(number)f(of)h(dimensions)e -(in)i(the)g(FITS)g(array)0 1797 y(naxis1)142 b(-)47 b(length)f(of)h -(the)g(X/first)f(axis)h(of)g(the)g(FITS)f(array)0 1910 -y(naxis2)142 b(-)47 b(length)f(of)h(the)g(Y/second)f(axis)g(of)i(the)e -(FITS)h(array)0 2023 y(naxis3)142 b(-)47 b(length)f(of)h(the)g(Z/third) -f(axis)h(of)g(the)g(FITS)f(array)0 2136 y(nbytes)142 -b(-)47 b(number)f(of)h(bytes)g(or)g(characters)e(to)i(read)g(or)g -(write)0 2249 y(nchars)142 b(-)47 b(number)f(of)h(characters)e(to)i -(read)g(or)g(write)0 2362 y(nelements-)e(number)h(of)h(data)g(elements) -e(to)j(read)e(or)h(write)0 2475 y(newfptr)94 b(-)47 b(returned)f -(pointer)f(to)j(the)e(reopened)g(file)0 2588 y(newveclen-)f(new)i -(value)f(for)h(the)g(column)f(vector)g(repeat)g(parameter)0 -2700 y(nexc)238 b(-)47 b(number)f(of)h(names)g(in)g(the)g(exclusion)e -(list)i(\(may)f(=)i(0\))0 2813 y(nfound)142 b(-)47 b(number)f(of)h -(keywords)f(found)g(\(highest)g(keyword)g(number\))0 -2926 y(nkeys)190 b(-)47 b(number)f(of)h(keywords)f(in)h(the)g(sequence) -0 3039 y(ninc)238 b(-)47 b(number)f(of)h(names)g(in)g(the)g(inclusion)e -(list)0 3152 y(nmembers)h(-)h(Number)f(of)h(grouping)f(table)g(members) -g(\(NAXIS2)g(value\).)0 3265 y(nmove)190 b(-)47 b(number)f(of)h(HDUs)g -(to)g(move)g(\(+)g(or)g(-\),)g(relative)f(to)h(current)f(position)0 -3378 y(nocomments)f(-)i(if)h(equal)e(to)h(TRUE,)g(then)f(no)h -(commentary)e(keywords)h(will)h(be)g(copied)0 3491 y(noisebits-)e -(number)h(of)h(bits)g(to)g(ignore)f(when)h(compressing)e(floating)g -(point)h(images)0 3604 y(nrows)190 b(-)47 b(number)f(of)h(rows)g(in)g -(the)g(table)0 3717 y(nstart)142 b(-)47 b(first)f(integer)g(value)0 -3830 y(nullarray-)f(set)i(to)g(TRUE)g(\(=1\))f(if)i(corresponding)c -(data)i(element)g(is)h(undefined)0 3942 y(nulval)142 -b(-)47 b(numerical)e(value)i(to)g(represent)e(undefined)g(pixels)0 -4055 y(nulstr)142 b(-)47 b(character)e(string)h(used)h(to)g(represent)e -(undefined)h(values)g(in)h(ASCII)f(table)0 4168 y(numval)142 -b(-)47 b(numerical)e(data)i(value,)f(of)h(the)g(appropriate)e(data)h -(type)0 4281 y(offset)142 b(-)47 b(byte)g(offset)f(in)h(the)g(heap)f -(or)i(data)e(unit)h(to)g(the)g(first)f(element)g(of)h(the)g(vector)0 -4394 y(openfptr)f(-)h(pointer)f(to)h(a)g(currently)f(open)g(FITS)h -(file)0 4507 y(overlap)94 b(-)47 b(number)f(of)h(bytes)g(in)g(the)g -(binary)f(table)g(heap)h(pointed)f(to)h(by)g(more)g(than)f(1)525 -4620 y(descriptor)0 4733 y(outcolnum-)f(output)h(column)g(number;)g -(range)g(=)i(1)f(to)g(TFIELDS)f(+)i(1)0 4846 y(outfile)94 -b(-)47 b(and)g(optional)e(output)i(filename;)e(the)i(input)f(file)h -(will)f(be)i(copied)e(to)h(this)f(prior)525 4959 y(to)h(opening)f(the)h -(file)0 5072 y(outfptr)94 b(-)47 b(pointer)f(to)h(a)g('fitsfile')e -(structure)h(describing)f(the)i(output)f(FITS)g(file.)0 -5185 y(pcount)142 b(-)47 b(value)f(of)i(the)e(PCOUNT)h(keyword)e(=)j -(size)e(of)i(binary)e(table)g(heap)0 5297 y(previous)g(-)h(if)g(TRUE,)g -(any)f(previous)g(HDUs)h(in)g(the)g(input)f(file)h(will)f(be)i(copied.) -0 5410 y(repeat)142 b(-)47 b(length)f(of)h(column)f(vector)g(\(e.g.)h -(12J\);)f(==)h(1)h(for)f(ASCII)f(table)0 5523 y(rmopt)190 -b(-)47 b(grouping)f(table)g(remove)g(option)g(parameter.)f(Allowed)h -(values)g(are:)525 5636 y(OPT_RM_GPT,)f(OPT_RM_ENTRY,)f(OPT_RM_MBR,)h -(and)i(OPT_RM_ALL.)p eop end -%%Page: 181 189 -TeXDict begin 181 188 bop 3764 299 a Fj(181)0 555 y Fe(rootname)46 -b(-)h(root)g(filename,)e(minus)h(any)h(extension)e(or)j(filtering)d -(specifications)0 668 y(rot)286 b(-)47 b(celestial)e(coordinate)g -(rotation)h(angle)g(\(degrees\))0 781 y(rowlen)142 b(-)47 -b(length)f(of)h(a)h(table)e(row,)h(in)g(characters)e(or)i(bytes)0 -894 y(rowlist)94 b(-)47 b(sorted)f(list)h(of)g(row)g(numbers)f(to)h(be) -g(deleted)f(from)g(the)h(table)0 1007 y(rownum)142 b(-)47 -b(number)f(of)h(the)g(row)g(\(first)f(row)h(=)h(1\))0 -1120 y(rowrange)e(-)h(list)g(of)g(rows)f(or)i(row)f(ranges:)e -('3,6-8,12,56-80')f(or)j('500-')0 1233 y(row_status)e(-)i(array)g(of)g -(True/False)e(results)h(for)h(each)f(row)h(that)g(was)g(evaluated)0 -1346 y(scale)190 b(-)47 b(linear)f(scaling)g(factor;)g(true)g(value)h -(=)g(\(FITS)g(value\))f(*)h(scale)f(+)i(zero)0 1458 y(second)142 -b(-)47 b(second)f(within)g(minute)g(\(0)h(-)h(60.9999999999\))c(\(leap) -i(second!\))0 1571 y(section)94 b(-)47 b(section)f(of)h(image)f(to)i -(be)f(copied)f(\(e.g.)g(21:80,101:200\))0 1684 y(simple)142 -b(-)47 b(TRUE)g(\(=1\))f(if)h(FITS)g(file)g(conforms)e(to)i(the)g -(Standard,)f(else)g(FALSE)h(\(=0\))0 1797 y(space)190 -b(-)47 b(number)f(of)h(blank)g(spaces)f(to)h(leave)f(between)g(ASCII)g -(table)h(columns)0 1910 y(status)142 b(-)47 b(returned)f(error)g -(status)g(code)h(\(0)g(=)g(OK\))0 2023 y(sum)286 b(-)47 -b(32)g(bit)g(unsigned)f(checksum)f(value)0 2136 y(tbcol)190 -b(-)47 b(byte)g(position)e(in)i(row)g(to)g(start)g(of)g(column)f(\(1st) -h(col)g(has)g(tbcol)f(=)h(1\))0 2249 y(tdisp)190 b(-)47 -b(Fortran)f(style)g(display)g(format)g(for)h(the)g(table)f(column)0 -2362 y(tdimstr)94 b(-)47 b(the)g(value)f(of)h(the)g(TDIMn)g(keyword)0 -2475 y(templt)142 b(-)47 b(template)f(string)g(used)g(in)h(comparison)e -(\(null-terminated\))0 2588 y(tfields)94 b(-)47 b(number)f(of)h(fields) -f(\(columns\))g(in)h(the)g(table)0 2700 y(tfopt)190 b(-)47 -b(grouping)f(table)g(member)g(transfer)g(option)g(parameter.)f(Allowed) -g(values)i(are:)525 2813 y(OPT_MCP_ADD,)d(and)j(OPT_MCP_MOV.)0 -2926 y(tform)190 b(-)47 b(format)f(of)h(the)g(column)f -(\(null-terminated\);)d(allowed)j(values)g(are:)525 3039 -y(ASCII)g(tables:)94 b(Iw,)47 b(Aw,)g(Fww.dd,)f(Eww.dd,)f(or)j(Dww.dd) -525 3152 y(Binary)e(tables:)g(rL,)h(rX,)g(rB,)g(rI,)g(rJ,)f(rA,)h(rAw,) -g(rE,)g(rD,)g(rC,)g(rM)525 3265 y(where)f('w'=width)g(of)h(the)g -(field,)f('d'=no.)g(of)h(decimals,)e('r'=repeat)g(count.)525 -3378 y(Variable)h(length)g(array)g(columns)g(are)h(denoted)f(by)h(a)g -('1P')g(before)f(the)h(data)f(type)525 3491 y(character)f(\(e.g.,)h -('1PJ'\).)94 b(When)47 b(creating)e(a)j(binary)e(table,)g(2)h(addition) -f(tform)525 3604 y(data)h(type)f(codes)h(are)g(recognized)e(by)i -(CFITSIO:)e('rU')i(and)g('rV')f(for)h(unsigned)525 3717 -y(16-bit)f(and)h(unsigned)f(32-bit)g(integer,)f(respectively.)0 -3942 y(theap)190 b(-)47 b(zero)g(indexed)e(byte)i(offset)f(of)h -(starting)f(address)g(of)h(the)g(heap)525 4055 y(relative)f(to)h(the)g -(beginning)e(of)i(the)g(binary)f(table)g(data)0 4168 -y(tilesize)g(-)h(array)f(of)i(length)e(NAXIS)g(that)h(specifies)e(the)i -(dimensions)e(of)525 4281 y(the)i(image)f(compression)f(tiles)0 -4394 y(ttype)190 b(-)47 b(label)f(or)i(name)e(for)h(table)f(column)h -(\(null-terminated\))0 4507 y(tunit)190 b(-)47 b(physical)f(unit)g(for) -h(table)f(column)h(\(null-terminated\))0 4620 y(typechar)f(-)h -(symbolic)f(code)g(of)h(the)g(table)g(column)f(data)g(type)0 -4733 y(typecode)g(-)h(data)g(type)f(code)h(of)g(the)g(table)f(column.) -94 b(The)47 b(negative)e(of)525 4846 y(the)i(value)f(indicates)g(a)h -(variable)f(length)g(array)g(column.)764 4959 y(Datatype)618 -b(typecode)189 b(Mnemonic)764 5072 y(bit,)46 b(X)907 -b(1)381 b(TBIT)764 5185 y(byte,)46 b(B)811 b(11)381 b(TBYTE)764 -5297 y(logical,)45 b(L)668 b(14)381 b(TLOGICAL)764 5410 -y(ASCII)46 b(character,)f(A)286 b(16)381 b(TSTRING)764 -5523 y(short)46 b(integer,)g(I)381 b(21)g(TSHORT)764 -5636 y(integer,)45 b(J)668 b(41)381 b(TINT32BIT)46 b(\(same)g(as)h -(TLONG\))p eop end -%%Page: 182 190 -TeXDict begin 182 189 bop 0 299 a Fj(182)1822 b Fh(APPENDIX)31 -b(B.)61 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)764 555 y -Fe(long)46 b(long)h(integer,)e(K)191 b(81)381 b(TLONGLONG)764 -668 y(real,)46 b(E)811 b(42)381 b(TFLOAT)764 781 y(double)46 -b(precision,)f(D)238 b(82)381 b(TDOUBLE)764 894 y(complex,)45 -b(C)668 b(83)381 b(TCOMPLEX)764 1007 y(double)46 b(complex,)f(M)286 -b(163)381 b(TDBLCOMPLEX)0 1120 y(unit)238 b(-)47 b(the)g(physical)e -(unit)i(string)f(\(e.g.,)g('km/s'\))g(for)h(a)g(keyword)0 -1233 y(unused)142 b(-)47 b(number)f(of)h(unused)f(bytes)h(in)g(the)g -(binary)f(table)g(heap)0 1346 y(urltype)94 b(-)47 b(the)g(file)g(type)f -(of)h(the)g(FITS)g(file)g(\(file://,)e(ftp://,)h(mem://,)f(etc.\))0 -1458 y(validheap-)g(returned)h(value)g(=)h(FALSE)g(if)g(any)g(of)g(the) -g(variable)e(length)i(array)525 1571 y(address)f(are)h(outside)f(the)g -(valid)h(range)f(of)h(addresses)f(in)h(the)g(heap)0 1684 -y(value)190 b(-)47 b(the)g(keyword)f(value)g(string)g(\(70)h(char)g -(max,)f(null-terminated\))0 1797 y(version)94 b(-)47 -b(current)f(version)g(number)g(of)h(the)g(CFITSIO)f(library)0 -1910 y(width)190 b(-)47 b(width)f(of)i(the)e(character)g(string)g -(field)0 2023 y(xcol)238 b(-)47 b(number)f(of)h(the)g(column)f -(containing)f(the)i(X)h(coordinate)d(values)0 2136 y(xinc)238 -b(-)47 b(X)g(axis)g(coordinate)e(increment)g(at)j(reference)d(pixel)h -(\(deg\))0 2249 y(xpix)238 b(-)47 b(X)g(axis)g(pixel)f(location)0 -2362 y(xpos)238 b(-)47 b(X)g(axis)g(celestial)e(coordinate)g(\(usually) -h(RA\))h(\(deg\))0 2475 y(xrefpix)94 b(-)47 b(X)g(axis)g(reference)e -(pixel)i(array)f(location)0 2588 y(xrefval)94 b(-)47 -b(X)g(axis)g(coordinate)e(value)h(at)i(the)f(reference)e(pixel)h -(\(deg\))0 2700 y(ycol)238 b(-)47 b(number)f(of)h(the)g(column)f -(containing)f(the)i(X)h(coordinate)d(values)0 2813 y(year)238 -b(-)47 b(calendar)f(year)g(\(e.g.)h(1999,)f(2000,)g(etc\))0 -2926 y(yinc)238 b(-)47 b(Y)g(axis)g(coordinate)e(increment)g(at)j -(reference)d(pixel)h(\(deg\))0 3039 y(ypix)238 b(-)47 -b(y)g(axis)g(pixel)f(location)0 3152 y(ypos)238 b(-)47 -b(y)g(axis)g(celestial)e(coordinate)g(\(usually)h(DEC\))h(\(deg\))0 -3265 y(yrefpix)94 b(-)47 b(Y)g(axis)g(reference)e(pixel)i(array)f -(location)0 3378 y(yrefval)94 b(-)47 b(Y)g(axis)g(coordinate)e(value)h -(at)i(the)f(reference)e(pixel)h(\(deg\))0 3491 y(zero)238 -b(-)47 b(scaling)f(offset;)g(true)g(value)h(=)g(\(FITS)f(value\))h(*)g -(scale)f(+)i(zero)p eop end -%%Page: 183 191 -TeXDict begin 183 190 bop 0 1225 a Fg(App)5 b(endix)64 -b(C)0 1687 y Fm(CFITSIO)76 b(Error)h(Status)h(Co)6 b(des)0 -2180 y Fj(The)28 b(follo)m(wing)h(table)g(lists)g(all)g(the)f(error)g -(status)g(co)s(des)g(used)f(b)m(y)h(CFITSIO.)f(Programmers)h(are)g -(encouraged)0 2293 y(to)37 b(use)e(the)h(sym)m(b)s(olic)h(mnemonics)e -(\(de\014ned)g(in)h(the)g(\014le)g(\014tsio.h\))h(rather)e(than)h(the)g -(actual)h(in)m(teger)h(status)0 2406 y(v)-5 b(alues)31 -b(to)g(impro)m(v)m(e)g(the)g(readabilit)m(y)g(of)g(their)f(co)s(de.)48 -2665 y Fe(Symbolic)45 b(Const)190 b(Value)237 b(Meaning)48 -2778 y(--------------)187 b(-----)94 b(------------------------)o(----) -o(---)o(----)o(----)o(--)1002 2891 y(0)191 b(OK,)47 b(no)g(error)48 -3004 y(SAME_FILE)427 b(101)190 b(input)46 b(and)h(output)f(files)h(are) -g(the)f(same)48 3117 y(TOO_MANY_FILES)187 b(103)j(tried)46 -b(to)h(open)g(too)g(many)g(FITS)f(files)h(at)g(once)48 -3230 y(FILE_NOT_OPENED)139 b(104)190 b(could)46 b(not)h(open)g(the)g -(named)f(file)48 3343 y(FILE_NOT_CREATED)91 b(105)190 -b(could)46 b(not)h(create)f(the)h(named)g(file)48 3456 -y(WRITE_ERROR)331 b(106)190 b(error)46 b(writing)g(to)h(FITS)g(file)48 -3569 y(END_OF_FILE)331 b(107)190 b(tried)46 b(to)h(move)g(past)g(end)g -(of)g(file)48 3681 y(READ_ERROR)379 b(108)190 b(error)46 -b(reading)g(from)h(FITS)f(file)48 3794 y(FILE_NOT_CLOSED)139 -b(110)190 b(could)46 b(not)h(close)g(the)f(file)48 3907 -y(ARRAY_TOO_BIG)235 b(111)190 b(array)46 b(dimensions)f(exceed)h -(internal)g(limit)48 4020 y(READONLY_FILE)235 b(112)190 -b(Cannot)46 b(write)g(to)i(readonly)d(file)48 4133 y(MEMORY_ALLOCATION) -e(113)190 b(Could)46 b(not)h(allocate)f(memory)48 4246 -y(BAD_FILEPTR)331 b(114)190 b(invalid)46 b(fitsfile)f(pointer)48 -4359 y(NULL_INPUT_PTR)187 b(115)j(NULL)47 b(input)f(pointer)g(to)h -(routine)48 4472 y(SEEK_ERROR)379 b(116)190 b(error)46 -b(seeking)g(position)g(in)h(file)48 4698 y(BAD_URL_PREFIX)235 -b(121)142 b(invalid)46 b(URL)h(prefix)f(on)h(file)g(name)48 -4811 y(TOO_MANY_DRIVERS)139 b(122)j(tried)46 b(to)h(register)f(too)h -(many)g(IO)g(drivers)48 4924 y(DRIVER_INIT_FAILED)c(123)142 -b(driver)46 b(initialization)e(failed)48 5036 y(NO_MATCHING_DRIVER)f -(124)142 b(matching)45 b(driver)i(is)g(not)g(registered)48 -5149 y(URL_PARSE_ERROR)187 b(125)142 b(failed)46 b(to)h(parse)g(input)f -(file)h(URL)48 5262 y(RANGE_PARSE_ERROR)91 b(126)142 -b(parse)46 b(error)h(in)g(range)f(list)48 5488 y(SHARED_BADARG)235 -b(151)190 b(bad)47 b(argument)e(in)j(shared)e(memory)g(driver)48 -5601 y(SHARED_NULPTR)235 b(152)190 b(null)47 b(pointer)e(passed)h(as)i -(an)f(argument)48 5714 y(SHARED_TABFULL)187 b(153)j(no)47 -b(more)g(free)f(shared)g(memory)h(handles)1882 5942 y -Fj(183)p eop end -%%Page: 184 192 -TeXDict begin 184 191 bop 0 299 a Fj(184)1589 b Fh(APPENDIX)31 -b(C.)61 b(CFITSIO)29 b(ERR)m(OR)h(ST)-8 b(A)g(TUS)30 -b(CODES)48 555 y Fe(SHARED_NOTINIT)187 b(154)j(shared)46 -b(memory)g(driver)g(is)h(not)g(initialized)48 668 y(SHARED_IPCERR)235 -b(155)190 b(IPC)47 b(error)f(returned)g(by)h(a)g(system)f(call)48 -781 y(SHARED_NOMEM)283 b(156)190 b(no)47 b(memory)f(in)h(shared)f -(memory)h(driver)48 894 y(SHARED_AGAIN)283 b(157)190 -b(resource)45 b(deadlock)h(would)g(occur)48 1007 y(SHARED_NOFILE)235 -b(158)190 b(attempt)46 b(to)h(open/create)e(lock)h(file)h(failed)48 -1120 y(SHARED_NORESIZE)139 b(159)190 b(shared)46 b(memory)g(block)g -(cannot)h(be)g(resized)f(at)h(the)g(moment)48 1346 y(HEADER_NOT_EMPTY) -91 b(201)190 b(header)46 b(already)g(contains)f(keywords)48 -1458 y(KEY_NO_EXIST)283 b(202)190 b(keyword)46 b(not)h(found)f(in)h -(header)48 1571 y(KEY_OUT_BOUNDS)187 b(203)j(keyword)46 -b(record)g(number)g(is)h(out)g(of)g(bounds)48 1684 y(VALUE_UNDEFINED) -139 b(204)190 b(keyword)46 b(value)g(field)g(is)i(blank)48 -1797 y(NO_QUOTE)475 b(205)190 b(string)46 b(is)h(missing)f(the)h -(closing)f(quote)48 1910 y(BAD_INDEX_KEY)235 b(206)190 -b(illegal)46 b(indexed)g(keyword)f(name)i(\(e.g.)f('TFORM1000'\))48 -2023 y(BAD_KEYCHAR)331 b(207)190 b(illegal)46 b(character)f(in)i -(keyword)f(name)h(or)g(card)48 2136 y(BAD_ORDER)427 b(208)190 -b(required)45 b(keywords)h(out)h(of)g(order)48 2249 y(NOT_POS_INT)331 -b(209)190 b(keyword)46 b(value)g(is)h(not)g(a)h(positive)d(integer)48 -2362 y(NO_END)571 b(210)190 b(couldn't)45 b(find)i(END)g(keyword)48 -2475 y(BAD_BITPIX)379 b(211)190 b(illegal)46 b(BITPIX)g(keyword)g -(value)48 2588 y(BAD_NAXIS)427 b(212)190 b(illegal)46 -b(NAXIS)g(keyword)g(value)48 2700 y(BAD_NAXES)427 b(213)190 -b(illegal)46 b(NAXISn)g(keyword)g(value)48 2813 y(BAD_PCOUNT)379 -b(214)190 b(illegal)46 b(PCOUNT)g(keyword)g(value)48 -2926 y(BAD_GCOUNT)379 b(215)190 b(illegal)46 b(GCOUNT)g(keyword)g -(value)48 3039 y(BAD_TFIELDS)331 b(216)190 b(illegal)46 -b(TFIELDS)g(keyword)f(value)48 3152 y(NEG_WIDTH)427 b(217)190 -b(negative)45 b(table)i(row)g(size)48 3265 y(NEG_ROWS)475 -b(218)190 b(negative)45 b(number)i(of)g(rows)f(in)i(table)48 -3378 y(COL_NOT_FOUND)235 b(219)190 b(column)46 b(with)h(this)f(name)h -(not)g(found)f(in)h(table)48 3491 y(BAD_SIMPLE)379 b(220)190 -b(illegal)46 b(value)g(of)h(SIMPLE)f(keyword)48 3604 -y(NO_SIMPLE)427 b(221)190 b(Primary)46 b(array)g(doesn't)g(start)g -(with)h(SIMPLE)48 3717 y(NO_BITPIX)427 b(222)190 b(Second)46 -b(keyword)g(not)h(BITPIX)48 3830 y(NO_NAXIS)475 b(223)190 -b(Third)46 b(keyword)g(not)h(NAXIS)48 3942 y(NO_NAXES)475 -b(224)190 b(Couldn't)45 b(find)i(all)g(the)g(NAXISn)f(keywords)48 -4055 y(NO_XTENSION)331 b(225)190 b(HDU)47 b(doesn't)f(start)g(with)h -(XTENSION)e(keyword)48 4168 y(NOT_ATABLE)379 b(226)190 -b(the)47 b(CHDU)f(is)i(not)f(an)g(ASCII)f(table)g(extension)48 -4281 y(NOT_BTABLE)379 b(227)190 b(the)47 b(CHDU)f(is)i(not)f(a)g -(binary)f(table)g(extension)48 4394 y(NO_PCOUNT)427 b(228)190 -b(couldn't)45 b(find)i(PCOUNT)f(keyword)48 4507 y(NO_GCOUNT)427 -b(229)190 b(couldn't)45 b(find)i(GCOUNT)f(keyword)48 -4620 y(NO_TFIELDS)379 b(230)190 b(couldn't)45 b(find)i(TFIELDS)f -(keyword)48 4733 y(NO_TBCOL)475 b(231)190 b(couldn't)45 -b(find)i(TBCOLn)f(keyword)48 4846 y(NO_TFORM)475 b(232)190 -b(couldn't)45 b(find)i(TFORMn)f(keyword)48 4959 y(NOT_IMAGE)427 -b(233)190 b(the)47 b(CHDU)f(is)i(not)f(an)g(IMAGE)f(extension)48 -5072 y(BAD_TBCOL)427 b(234)190 b(TBCOLn)46 b(keyword)g(value)g(<)i(0)f -(or)g(>)h(rowlength)48 5185 y(NOT_TABLE)427 b(235)190 -b(the)47 b(CHDU)f(is)i(not)f(a)g(table)48 5297 y(COL_TOO_WIDE)283 -b(236)190 b(column)46 b(is)h(too)g(wide)g(to)g(fit)g(in)g(table)48 -5410 y(COL_NOT_UNIQUE)187 b(237)j(more)47 b(than)f(1)i(column)e(name)g -(matches)g(template)48 5523 y(BAD_ROW_WIDTH)235 b(241)190 -b(sum)47 b(of)g(column)f(widths)g(not)h(=)h(NAXIS1)48 -5636 y(UNKNOWN_EXT)331 b(251)190 b(unrecognizable)44 -b(FITS)i(extension)g(type)p eop end -%%Page: 185 193 -TeXDict begin 185 192 bop 3764 299 a Fj(185)48 555 y -Fe(UNKNOWN_REC)331 b(252)190 b(unknown)46 b(record;)g(1st)g(keyword)g -(not)h(SIMPLE)f(or)h(XTENSION)48 668 y(END_JUNK)475 b(253)190 -b(END)47 b(keyword)f(is)h(not)g(blank)48 781 y(BAD_HEADER_FILL)139 -b(254)190 b(Header)46 b(fill)h(area)f(contains)g(non-blank)f(chars)48 -894 y(BAD_DATA_FILL)235 b(255)190 b(Illegal)46 b(data)g(fill)h(bytes)f -(\(not)h(zero)g(or)g(blank\))48 1007 y(BAD_TFORM)427 -b(261)190 b(illegal)46 b(TFORM)g(format)g(code)48 1120 -y(BAD_TFORM_DTYPE)139 b(262)190 b(unrecognizable)44 b(TFORM)i(data)h -(type)f(code)48 1233 y(BAD_TDIM)475 b(263)190 b(illegal)46 -b(TDIMn)g(keyword)g(value)48 1346 y(BAD_HEAP_PTR)283 -b(264)190 b(invalid)46 b(BINTABLE)f(heap)i(pointer)f(is)h(out)g(of)g -(range)48 1571 y(BAD_HDU_NUM)331 b(301)190 b(HDU)47 b(number)f(<)h(1)48 -1684 y(BAD_COL_NUM)331 b(302)190 b(column)46 b(number)g(<)i(1)f(or)g(>) -h(tfields)48 1797 y(NEG_FILE_POS)283 b(304)190 b(tried)46 -b(to)h(move)g(to)g(negative)f(byte)g(location)g(in)h(file)48 -1910 y(NEG_BYTES)427 b(306)190 b(tried)46 b(to)h(read)g(or)g(write)g -(negative)e(number)h(of)h(bytes)48 2023 y(BAD_ROW_NUM)331 -b(307)190 b(illegal)46 b(starting)f(row)i(number)f(in)h(table)48 -2136 y(BAD_ELEM_NUM)283 b(308)190 b(illegal)46 b(starting)f(element)h -(number)g(in)h(vector)48 2249 y(NOT_ASCII_COL)235 b(309)190 -b(this)47 b(is)g(not)g(an)g(ASCII)f(string)g(column)48 -2362 y(NOT_LOGICAL_COL)139 b(310)190 b(this)47 b(is)g(not)g(a)g -(logical)f(data)h(type)f(column)48 2475 y(BAD_ATABLE_FORMAT)d(311)190 -b(ASCII)46 b(table)h(column)f(has)h(wrong)f(format)48 -2588 y(BAD_BTABLE_FORMAT)d(312)190 b(Binary)46 b(table)g(column)g(has)h -(wrong)g(format)48 2700 y(NO_NULL)523 b(314)190 b(null)47 -b(value)f(has)h(not)g(been)f(defined)48 2813 y(NOT_VARI_LEN)283 -b(317)190 b(this)47 b(is)g(not)g(a)g(variable)f(length)g(column)48 -2926 y(BAD_DIMEN)427 b(320)190 b(illegal)46 b(number)g(of)h(dimensions) -e(in)i(array)48 3039 y(BAD_PIX_NUM)331 b(321)190 b(first)46 -b(pixel)h(number)f(greater)g(than)g(last)h(pixel)48 3152 -y(ZERO_SCALE)379 b(322)190 b(illegal)46 b(BSCALE)g(or)h(TSCALn)f -(keyword)g(=)h(0)48 3265 y(NEG_AXIS)475 b(323)190 b(illegal)46 -b(axis)g(length)g(<)i(1)48 3491 y(NOT_GROUP_TABLE)330 -b(340)142 b(Grouping)46 b(function)f(error)48 3604 y -(HDU_ALREADY_MEMBER)186 b(341)48 3717 y(MEMBER_NOT_FOUND)282 -b(342)48 3830 y(GROUP_NOT_FOUND)330 b(343)48 3942 y(BAD_GROUP_ID)474 -b(344)48 4055 y(TOO_MANY_HDUS_TRACKED)42 b(345)48 4168 -y(HDU_ALREADY_TRACKED)138 b(346)48 4281 y(BAD_OPTION)570 -b(347)48 4394 y(IDENTICAL_POINTERS)186 b(348)48 4507 -y(BAD_GROUP_ATTACH)282 b(349)48 4620 y(BAD_GROUP_DETACH)g(350)48 -4846 y(NGP_NO_MEMORY)426 b(360)238 b(malloc)46 b(failed)48 -4959 y(NGP_READ_ERR)474 b(361)238 b(read)46 b(error)h(from)f(file)48 -5072 y(NGP_NUL_PTR)522 b(362)238 b(null)46 b(pointer)g(passed)g(as)h -(an)g(argument.)1575 5185 y(Passing)f(null)g(pointer)g(as)h(a)h(name)f -(of)1575 5297 y(template)f(file)g(raises)g(this)h(error)48 -5410 y(NGP_EMPTY_CURLINE)234 b(363)k(line)46 b(read)h(seems)f(to)h(be)h -(empty)e(\(used)1575 5523 y(internally\))48 5636 y -(NGP_UNREAD_QUEUE_FULL)c(364)238 b(cannot)46 b(unread)g(more)g(then)h -(1)g(line)g(\(or)g(single)p eop end -%%Page: 186 194 -TeXDict begin 186 193 bop 0 299 a Fj(186)1589 b Fh(APPENDIX)31 -b(C.)61 b(CFITSIO)29 b(ERR)m(OR)h(ST)-8 b(A)g(TUS)30 -b(CODES)1575 555 y Fe(line)47 b(twice\))48 668 y(NGP_INC_NESTING)330 -b(365)238 b(too)46 b(deep)h(include)f(file)h(nesting)e(\(infinite)1575 -781 y(loop,)h(template)g(includes)f(itself)i(?\))48 894 -y(NGP_ERR_FOPEN)426 b(366)238 b(fopen\(\))45 b(failed,)h(cannot)g(open) -h(template)e(file)48 1007 y(NGP_EOF)714 b(367)238 b(end)46 -b(of)i(file)e(encountered)f(and)i(not)g(expected)48 1120 -y(NGP_BAD_ARG)522 b(368)238 b(bad)46 b(arguments)g(passed.)g(Usually)f -(means)1575 1233 y(internal)h(parser)g(error.)g(Should)g(not)h(happen) -48 1346 y(NGP_TOKEN_NOT_EXPECT)90 b(369)238 b(token)46 -b(not)h(expected)e(here)48 1571 y(BAD_I2C)523 b(401)190 -b(bad)47 b(int)g(to)g(formatted)e(string)h(conversion)48 -1684 y(BAD_F2C)523 b(402)190 b(bad)47 b(float)f(to)h(formatted)f -(string)g(conversion)48 1797 y(BAD_INTKEY)379 b(403)190 -b(can't)46 b(interpret)g(keyword)f(value)i(as)g(integer)48 -1910 y(BAD_LOGICALKEY)187 b(404)j(can't)46 b(interpret)g(keyword)f -(value)i(as)g(logical)48 2023 y(BAD_FLOATKEY)283 b(405)190 -b(can't)46 b(interpret)g(keyword)f(value)i(as)g(float)48 -2136 y(BAD_DOUBLEKEY)235 b(406)190 b(can't)46 b(interpret)g(keyword)f -(value)i(as)g(double)48 2249 y(BAD_C2I)523 b(407)190 -b(bad)47 b(formatted)e(string)h(to)h(int)g(conversion)48 -2362 y(BAD_C2F)523 b(408)190 b(bad)47 b(formatted)e(string)h(to)h -(float)g(conversion)48 2475 y(BAD_C2D)523 b(409)190 b(bad)47 -b(formatted)e(string)h(to)h(double)f(conversion)48 2588 -y(BAD_DATATYPE)283 b(410)190 b(illegal)46 b(datatype)f(code)i(value)48 -2700 y(BAD_DECIM)427 b(411)190 b(bad)47 b(number)f(of)h(decimal)f -(places)g(specified)48 2813 y(NUM_OVERFLOW)283 b(412)190 -b(overflow)45 b(during)i(data)f(type)h(conversion)48 -2926 y(DATA_COMPRESSION_ERR)137 b(413)95 b(error)46 b(compressing)f -(image)48 3039 y(DATA_DECOMPRESSION_ERR)c(414)95 b(error)46 -b(uncompressing)f(image)48 3265 y(BAD_DATE)475 b(420)190 -b(error)46 b(in)h(date)g(or)g(time)g(conversion)48 3491 -y(PARSE_SYNTAX_ERR)91 b(431)190 b(syntax)46 b(error)g(in)i(parser)e -(expression)48 3604 y(PARSE_BAD_TYPE)187 b(432)j(expression)45 -b(did)i(not)g(evaluate)e(to)i(desired)f(type)48 3717 -y(PARSE_LRG_VECTOR)91 b(433)190 b(vector)46 b(result)g(too)h(large)f -(to)i(return)e(in)h(array)48 3830 y(PARSE_NO_OUTPUT)139 -b(434)190 b(data)47 b(parser)f(failed)g(not)h(sent)f(an)h(out)g(column) -48 3942 y(PARSE_BAD_COL)235 b(435)190 b(bad)47 b(data)f(encounter)g -(while)g(parsing)g(column)48 4055 y(PARSE_BAD_OUTPUT)91 -b(436)190 b(Output)46 b(file)h(not)g(of)g(proper)f(type)48 -4281 y(ANGLE_TOO_BIG)235 b(501)190 b(celestial)45 b(angle)i(too)f -(large)h(for)g(projection)48 4394 y(BAD_WCS_VAL)331 b(502)190 -b(bad)47 b(celestial)e(coordinate)g(or)i(pixel)g(value)48 -4507 y(WCS_ERROR)427 b(503)190 b(error)46 b(in)h(celestial)f -(coordinate)f(calculation)48 4620 y(BAD_WCS_PROJ)283 -b(504)190 b(unsupported)45 b(type)h(of)h(celestial)f(projection)48 -4733 y(NO_WCS_KEY)379 b(505)190 b(celestial)45 b(coordinate)g(keywords) -h(not)h(found)48 4846 y(APPROX_WCS_KEY)187 b(506)j(approximate)45 -b(wcs)i(keyword)e(values)h(were)h(returned)p eop end -%%Trailer - -userdict /end-hook known{end-hook}if -%%EOF diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.tex b/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.tex deleted file mode 100644 index 3fc5d1bb0..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.tex +++ /dev/null @@ -1,10799 +0,0 @@ -\documentclass[11pt]{book} -\input{html.sty} -\htmladdtonavigation - {\begin{rawhtml} - FITSIO Home - \end{rawhtml}} -\oddsidemargin=0.00in -\evensidemargin=0.00in -\textwidth=6.5in -%\topmargin=0.0in -\textheight=8.75in -\parindent=0cm -\parskip=0.2cm -\begin{document} -\pagenumbering{roman} - -\begin{titlepage} -\normalsize -\vspace*{4.0cm} -\begin{center} -{\Huge \bf CFITSIO User's Reference Guide}\\ -\end{center} -\medskip -\medskip -\begin{center} -{\LARGE \bf An Interface to FITS Format Files}\\ -\end{center} -\begin{center} -{\LARGE \bf for C Programmers}\\ -\end{center} -\medskip -\medskip -\begin{center} -{\Large Version 3.3 \\} -\end{center} -\bigskip -\vskip 2.5cm -\begin{center} -{HEASARC\\ -Code 662\\ -Goddard Space Flight Center\\ -Greenbelt, MD 20771\\ -USA} -\end{center} - -\vfill -\bigskip -\begin{center} -{\Large April 2016\\} -\end{center} -\vfill -\end{titlepage} - -\clearpage - -\tableofcontents -\chapter{Introduction } -\pagenumbering{arabic} - - -\section{ A Brief Overview} - -CFITSIO is a machine-independent library of routines for reading and -writing data files in the FITS (Flexible Image Transport System) data -format. It can also read IRAF format image files and raw binary data -arrays by converting them on the fly into a virtual FITS format file. -This library is written in ANSI C and provides a powerful yet simple -interface for accessing FITS files which will run on most commonly used -computers and workstations. CFITSIO supports all the features -described in the official definition of the FITS format and can -read and write all the currently defined types of extensions, including -ASCII tables (TABLE), Binary tables (BINTABLE) and IMAGE extensions. -The CFITSIO routines insulate the programmer from having to deal with -the complicated formatting details in the FITS file, however, it is -assumed that users have a general knowledge about the structure and -usage of FITS files. - -CFITSIO also contains a set of Fortran callable wrapper routines which -allow Fortran programs to call the CFITSIO routines. See the companion -``FITSIO User's Guide'' for the definition of the Fortran subroutine -calling sequences. These wrappers replace the older Fortran FITSIO -library which is no longer supported. - -The CFITSIO package was initially developed by the HEASARC (High Energy -Astrophysics Science Archive Research Center) at the NASA Goddard Space -Flight Center to convert various existing and newly acquired -astronomical data sets into FITS format and to further analyze data -already in FITS format. New features continue to be added to CFITSIO -in large part due to contributions of ideas or actual code from -users of the package. The Integral Science Data Center in Switzerland, -and the XMM/ESTEC project in The Netherlands made especially significant -contributions that resulted in many of the new features that appeared -in v2.0 of CFITSIO. - - -\section{Sources of FITS Software and Information} - -The latest version of the CFITSIO source code, -documentation, and example programs are available on the -Web or via anonymous ftp from: - -\begin{verbatim} - http://heasarc.gsfc.nasa.gov/fitsio - ftp://legacy.gsfc.nasa.gov/software/fitsio/c -\end{verbatim} - -Any questions, bug reports, or suggested enhancements related to the CFITSIO -package should be sent to the FTOOLS Help Desk at the HEASARC: - -\begin{verbatim} - http://heasarc.gsfc.nasa.gov/cgi-bin/ftoolshelp -\end{verbatim} - -This User's Guide assumes that readers already have a general -understanding of the definition and structure of FITS format files. -Further information about FITS formats is available from the FITS Support -Office at {\tt http://fits.gsfc.nasa.gov}. In particular, the -'FITS Standard' gives the authoritative definition of the FITS data -format. Other documents available at that Web site -provide additional historical background -and practical advice on using FITS files. - -The HEASARC also provides a very sophisticated FITS file analysis -program called `Fv' which can be used to display and edit the contents -of any FITS file as well as construct new FITS files from scratch. -Fv is freely available for -most Unix platforms, Mac PCs, and Windows PCs. -CFITSIO users may also be interested in the FTOOLS package of programs -that can be used to manipulate and analyze FITS format files. -Fv and FTOOLS are available from their respective Web sites at: - -\begin{verbatim} - http://fv.gsfc.nasa.gov - http://heasarc.gsfc.nasa.gov/ftools -\end{verbatim} - - -\section{Acknowledgments} - -The development of the many powerful features in CFITSIO was made -possible through collaborations with many people or organizations from -around the world. The following in particular have made especially -significant contributions: - -Programmers from the Integral Science Data Center, Switzerland (namely, -Jurek Borkowski, Bruce O'Neel, and Don Jennings), designed the concept -for the plug-in I/O drivers that was introduced with CFITSIO 2.0. The -use of `drivers' greatly simplified the low-level I/O, which in turn -made other new features in CFITSIO (e.g., support for compressed FITS -files and support for IRAF format image files) much easier to -implement. Jurek Borkowski wrote the Shared Memory driver, and Bruce -O'Neel wrote the drivers for accessing FITS files over the network -using the FTP, HTTP, and ROOT protocols. Also, in 2009, Bruce O'Neel -was the key developer of the thread-safe version of CFITSIO. - -The ISDC also provided the template parsing routines (written by Jurek -Borkowski) and the hierarchical grouping routines (written by Don -Jennings). The ISDC DAL (Data Access Layer) routines are layered on -top of CFITSIO and make extensive use of these features. - -Giuliano Taffoni and Andrea Barisani, at INAF, University of Trieste, -Italy, implemented the I/O driver routines for accessing FITS files -on the computational grids using the gridftp protocol. - -Uwe Lammers (XMM/ESA/ESTEC, The Netherlands) designed the -high-performance lexical parsing algorithm that is used to do -on-the-fly filtering of FITS tables. This algorithm essentially -pre-compiles the user-supplied selection expression into a form that -can be rapidly evaluated for each row. Peter Wilson (RSTX, NASA/GSFC) -then wrote the parsing routines used by CFITSIO based on Lammers' -design, combined with other techniques such as the CFITSIO iterator -routine to further enhance the data processing throughput. This effort -also benefited from a much earlier lexical parsing routine that was -developed by Kent Blackburn (NASA/GSFC). More recently, Craig Markwardt -(NASA/GSFC) implemented additional functions (median, average, stddev) -and other enhancements to the lexical parser. - -The CFITSIO iterator function is loosely based on similar ideas -developed for the XMM Data Access Layer. - -Peter Wilson (RSTX, NASA/GSFC) wrote the complete set of -Fortran-callable wrappers for all the CFITSIO routines, which in turn -rely on the CFORTRAN macro developed by Burkhard Burow. - -The syntax used by CFITSIO for filtering or binning input FITS files is -based on ideas developed for the AXAF Science Center Data Model by -Jonathan McDowell, Antonella Fruscione, Aneta Siemiginowska and Bill -Joye. See http://heasarc.gsfc.nasa.gov/docs/journal/axaf7.html for -further description of the AXAF Data Model. - -The file decompression code were taken directly from the gzip (GNU zip) -program developed by Jean-loup Gailly and others. - -The new compressed image data format (where the image is tiled and -the compressed byte stream from each tile is stored in a binary table) -was implemented in collaboration with Richard White (STScI), Perry -Greenfield (STScI) and Doug Tody (NOAO). - -Doug Mink (SAO) provided the routines for converting IRAF format -images into FITS format. - -Martin Reinecke (Max Planck Institute, Garching)) provided the modifications to -cfortran.h that are necessary to support 64-bit integer values when calling -C routines from fortran programs. The cfortran.h macros were originally developed -by Burkhard Burow (CERN). - -Julian Taylor (ESO, Garching) provided the fast byte-swapping algorithms -that use the SSE2 and SSSE3 machine instructions available on x86\_64 CPUs. - -In addition, many other people have made valuable contributions to the -development of CFITSIO. These include (with apologies to others that may -have inadvertently been omitted): - -Steve Allen, Carl Akerlof, Keith Arnaud, Morten Krabbe Barfoed, Kent -Blackburn, G Bodammer, Romke Bontekoe, Lucio Chiappetti, Keith Costorf, -Robin Corbet, John Davis, Richard Fink, Ning Gan, Emily Greene, Gretchen -Green, Joe Harrington, Cheng Ho, Phil Hodge, Jim Ingham, Yoshitaka -Ishisaki, Diab Jerius, Mark Levine, Todd Karakaskian, Edward King, -Scott Koch, Claire Larkin, Rob Managan, Eric Mandel, Richard Mathar, -John Mattox, Carsten Meyer, Emi Miyata, Stefan Mochnacki, Mike Noble, -Oliver Oberdorf, Clive Page, Arvind Parmar, Jeff Pedelty, Tim Pearson, -Philippe Prugniel, Maren Purves, Scott Randall, Chris Rogers, Arnold Rots, -Rob Seaman, Barry Schlesinger, Robin Stebbins, Andrew Szymkowiak, Allyn Tennant, -Peter Teuben, James Theiler, Doug Tody, Shiro Ueno, Steve Walton, Archie -Warnock, Alan Watson, Dan Whipple, Wim Wimmers, Peter Young, Jianjun Xu, -and Nelson Zarate. - - -\section{Legal Stuff} - -Copyright (Unpublished--all rights reserved under the copyright laws of -the United States), U.S. Government as represented by the Administrator -of the National Aeronautics and Space Administration. No copyright is -claimed in the United States under Title 17, U.S. Code. - -Permission to freely use, copy, modify, and distribute this software -and its documentation without fee is hereby granted, provided that this -copyright notice and disclaimer of warranty appears in all copies. - -DISCLAIMER: - -THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, -EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, -ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY -IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE -DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE -SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY -DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR -CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY -CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, -CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY -PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED -FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR -SERVICES PROVIDED HEREUNDER." - -\chapter{ Creating the CFITSIO Library } - - -\section{Building the Library} - -The CFITSIO code is contained in about 40 C source files (*.c) and header -files (*.h). On VAX/VMS systems 2 assembly-code files (vmsieeed.mar and -vmsieeer.mar) are also needed. - -CFITSIO is written in ANCI C and should be compatible with most existing C and C++ -compilers. Cray supercomputers are currently not supported. - - -\subsection{Unix Systems} - -The CFITSIO library is built on Unix systems by typing: - -\begin{verbatim} - > ./configure [--prefix=/target/installation/path] [--enable-reentrant] - [--enable-sse2] [--enable-ssse3] - > make (or 'make shared') - > make install (this step is optional) -\end{verbatim} -at the operating system prompt. The configure command customizes the -Makefile for the particular system, then the `make' command compiles the -source files and builds the library. Type `./configure' and not simply -`configure' to ensure that the configure script in the current directory -is run and not some other system-wide configure script. The optional -'prefix' argument to configure gives the path to the directory where -the CFITSIO library and include files should be installed via the later -'make install' command. For example, - -\begin{verbatim} - > ./configure --prefix=/usr1/local -\end{verbatim} -will cause the 'make install' command to copy the CFITSIO libcfitsio file -to /usr1/local/lib and the necessary include files to /usr1/local/include -(assuming of course that the process has permission to write to these -directories). - -All the available configure options can be seen by entering the command - -\begin{verbatim} - > ./configure --help -\end{verbatim} -Some of the more useful options are described below: - -The --enable-reentrant option will attempt to configure CFITSIO -so that it can be used in multi-threaded programs. See the -"Using CFITSIO in Multi-threaded Environments" section, below, for more details. - -The --enable-sse2 and --enable-ssse3 options will cause configure to -attempt to build CFITSIO using faster byte-swapping algorithms. -See the "Optimizing Programs" chapter of this manual for -more information about these options. - -The --with-gsiftp-flavour and --with-gsiftp options enable support for the Globus -Toolkit gsiftp protocal. See the "Extended File Name Syntax" chapter for more -information. - -The --with-bzip2 option enables support for reading FITS files that have been -externally compressed by the bzip2 algorithm. This requires that the CFITSIO -library, and all applications program that use CFITSIO, to be linked to include -the libbz2 library. - -The 'make shared' option builds a shared or dynamic version of the -CFITSIO library. When using the shared library the executable code is -not copied into your program at link time and instead the program -locates the necessary library code at run time, normally through -LD\_LIBRARY\_PATH or some other method. The advantages of using a shared -library are: - -\begin{verbatim} - 1. Less disk space if you build more than 1 program - 2. Less memory if more than one copy of a program using the shared - library is running at the same time since the system is smart - enough to share copies of the shared library at run time. - 3. Possibly easier maintenance since a new version of the shared - library can be installed without relinking all the software - that uses it (as long as the subroutine names and calling - sequences remain unchanged). - 4. No run-time penalty. -\end{verbatim} -The disadvantages are: - -\begin{verbatim} - 1. More hassle at runtime. You have to either build the programs - specially or have LD_LIBRARY_PATH set right. - 2. There may be a slight start up penalty, depending on where you are - reading the shared library and the program from and if your CPU is - either really slow or really heavily loaded. -\end{verbatim} - -On Mac OS X platforms the 'make shared' command works like on other -UNIX platforms, but a .dylib file will be created instead of .so. If -installed in a nonstandard location, add its location to the -DYLD\_LIBRARY\_PATH environment variable so that the library can be found -at run time. - -On HP/UX systems, the environment variable CFLAGS should be set -to -Ae before running configure to enable "extended ANSI" features. - -By default, a set of Fortran-callable wrapper routines are -also built and included in the CFITSIO library. If these wrapper -routines are not needed (i.e., the CFITSIO library will not -be linked to any Fortran applications which call FITSIO subroutines) -then they may be omitted from the build by typing 'make all-nofitsio' -instead of simply typing 'make'. This will reduce the size -of the CFITSIO library slightly. - -It may not be possible to statically link programs that use CFITSIO on -some platforms (namely, on Solaris 2.6) due to the network drivers -(which provide FTP and HTTP access to FITS files). It is possible to -make both a dynamic and a static version of the CFITSIO library, but -network file access will not be possible using the static version. - - -\subsection{VMS} - -On VAX/VMS and ALPHA/VMS systems the make\_gfloat.com command file may -be executed to build the cfitsio.olb object library using the default -G-floating point option for double variables. The make\_dfloat.com and -make\_ieee.com files may be used instead to build the library with the -other floating point options. Note that the getcwd function that is -used in the group.c module may require that programs using CFITSIO be -linked with the ALPHA\$LIBRARY:VAXCRTL.OLB library. See the example -link line in the next section of this document. - - -\subsection{Windows PCs} - -A precompiled DLL version of CFITSIO (not necessarily the latest version) -is available on the CFITSIO web site. -The CFITSIO library may also be built from the source code using the -CMake build system. See the "README.win" file in the CFITSIO source distribution -for more information. - - -\subsection{Macintosh PCs} - -When building on Mac OS-X, users should follow the Unix instructions, -above. See the README.MacOS file for instructions on building a Universal -Binary that supports both Intel and PowerPC CPUs. - - -\section{Testing the Library} - -The CFITSIO library should be tested by building and running -the testprog.c program that is included with the release. -On Unix systems, type: - -\begin{verbatim} - % make testprog - % testprog > testprog.lis - % diff testprog.lis testprog.out - % cmp testprog.fit testprog.std -\end{verbatim} - On VMS systems, -(assuming cc is the name of the C compiler command), type: - -\begin{verbatim} - $ cc testprog.c - $ link testprog, cfitsio/lib, alpha$library:vaxcrtl/lib - $ run testprog -\end{verbatim} -The test program should produce a FITS file called `testprog.fit' -that is identical to the `testprog.std' FITS file included with this -release. The diagnostic messages (which were piped to the file -testprog.lis in the Unix example) should be identical to the listing -contained in the file testprog.out. The 'diff' and 'cmp' commands -shown above should not report any differences in the files. (There -may be some minor format differences, such as the presence or -absence of leading zeros, or 3 digit exponents in numbers, -which can be ignored). - -The Fortran wrappers in CFITSIO may be tested with the testf77 -program on Unix systems with: - -\begin{verbatim} - % f77 -o testf77 testf77.f -L. -lcfitsio -lnsl -lsocket - or - % f77 -f -o testf77 testf77.f -L. -lcfitsio (under SUN O/S) - or - % f77 -o testf77 testf77.f -Wl,-L. -lcfitsio -lm -lnsl -lsocket (HP/UX) - - % testf77 > testf77.lis - % diff testf77.lis testf77.out - % cmp testf77.fit testf77.std -\end{verbatim} -On machines running SUN O/S, Fortran programs must be compiled with the -'-f' option to force double precision variables to be aligned on 8-byte -boundarys to make the fortran-declared variables compatible with C. A -similar compiler option may be required on other platforms. Failing to -use this option may cause the program to crash on FITSIO routines that -read or write double precision variables. - -Also note that on some systems, the output listing of the testf77 -program may differ slightly from the testf77.std template, if leading -zeros are not printed by default before the decimal point when using F -format. - -A few other utility programs are included with CFITSIO; the first four -of this programs can be compiled an linked by typing `make -program\_name' where `program\_name' is the actual name of the program: - -\begin{verbatim} - speed - measures the maximum throughput (in MB per second) - for writing and reading FITS files with CFITSIO. - - listhead - lists all the header keywords in any FITS file - - fitscopy - copies any FITS file (especially useful in conjunction - with the CFITSIO's extended input filename syntax). - - cookbook - a sample program that performs common read and - write operations on a FITS file. - - iter_a, iter_b, iter_c - examples of the CFITSIO iterator routine -\end{verbatim} - - -\section{Linking Programs with CFITSIO} - -When linking applications software with the CFITSIO library, several -system libraries usually need to be specified on the link command -line. On Unix systems, the most reliable way to determine what -libraries are required is to type 'make testprog' and see what -libraries the configure script has added. The typical libraries that -need to be added are -lm (the math library) and -lnsl and -lsocket -(needed only for FTP and HTTP file access). These latter 2 libraries -are not needed on VMS and Windows platforms, because FTP file access is -not currently supported on those platforms. - -Note that when upgrading to a newer version of CFITSIO it is usually -necessary to recompile, as well as relink, the programs that use CFITSIO, -because the definitions in fitsio.h often change. - - -\section{Using CFITSIO in Multi-threaded Environments} - -CFITSIO can be used either with the -POSIX pthreads interface or the OpenMP interface for multi-threaded -parallel programs. When used in a multi-threaded environment, -the CFITSIO library *must* be built using -the -D\_REENTRANT compiler directive. This can be done using the following -build commands: - -\begin{verbatim} - >./configure --enable-reentrant - > make -\end{verbatim} -A function called fits\_is\_reentrant is available to test -whether or not CFITSIO was compiled with the -D\_REENTRANT -directive. When this feature is enabled, multiple threads can -call any of the CFITSIO routines -to simultaneously read or write separate -FITS files. Multiple threads can also read data from -the same FITS file simultaneously, as long as the file -was opened independently by each thread. This relies on -the operating system to correctly deal with reading the -same file by multiple processes. Different threads should -not share the same 'fitsfile' pointer to read an opened -FITS file, unless locks are placed around the calls to -the CFITSIO reading routines. -Different threads should never try to write to the same -FITS file. - - -\section{Getting Started with CFITSIO} - -In order to effectively use the CFITSIO library it is recommended that -new users begin by reading the ``CFITSIO Quick Start Guide''. It -contains all the basic information needed to write programs that -perform most types of operations on FITS files. The set of example -FITS utility programs that are available from the CFITSIO web site are -also very useful for learning how to use CFITSIO. To learn even more -about the capabilities of the CFITSIO library the following steps are -recommended: - -1. Read the following short `FITS Primer' chapter for an overview of -the structure of FITS files. - -2. Review the Programming Guidelines in Chapter 4 to become familiar -with the conventions used by the CFITSIO interface. - -3. Refer to the cookbook.c, listhead.c, and fitscopy.c programs that -are included with this release for examples of routines that perform -various common FITS file operations. Type 'make program\_name' to -compile and link these programs on Unix systems. - -4. Write a simple program to read or write a FITS file using the Basic -Interface routines described in Chapter 5. - -5. Scan through the more specialized routines that are described in -the following chapters to become familiar with the functionality that -they provide. - - -\section{Example Program} - -The following listing shows an example of how to use the CFITSIO -routines in a C program. Refer to the cookbook.c program that is -included with the CFITSIO distribution for other example routines. - -This program creates a new FITS file, containing a FITS image. An -`EXPOSURE' keyword is written to the header, then the image data are -written to the FITS file before closing the FITS file. - -\begin{verbatim} -#include "fitsio.h" /* required by every program that uses CFITSIO */ -main() -{ - fitsfile *fptr; /* pointer to the FITS file; defined in fitsio.h */ - int status, ii, jj; - long fpixel = 1, naxis = 2, nelements, exposure; - long naxes[2] = { 300, 200 }; /* image is 300 pixels wide by 200 rows */ - short array[200][300]; - - status = 0; /* initialize status before calling fitsio routines */ - fits_create_file(&fptr, "testfile.fits", &status); /* create new file */ - - /* Create the primary array image (16-bit short integer pixels */ - fits_create_img(fptr, SHORT_IMG, naxis, naxes, &status); - - /* Write a keyword; must pass the ADDRESS of the value */ - exposure = 1500.; - fits_update_key(fptr, TLONG, "EXPOSURE", &exposure, - "Total Exposure Time", &status); - - /* Initialize the values in the image with a linear ramp function */ - for (jj = 0; jj < naxes[1]; jj++) - for (ii = 0; ii < naxes[0]; ii++) - array[jj][ii] = ii + jj; - - nelements = naxes[0] * naxes[1]; /* number of pixels to write */ - - /* Write the array of integers to the image */ - fits_write_img(fptr, TSHORT, fpixel, nelements, array[0], &status); - - fits_close_file(fptr, &status); /* close the file */ - - fits_report_error(stderr, status); /* print out any error messages */ - return( status ); -} -\end{verbatim} - -\chapter{ A FITS Primer } - -This section gives a brief overview of the structure of FITS files. -Users should refer to the documentation available from the FITS Support OFfice, -as described in the introduction, for more detailed information on FITS -formats. - -FITS was first developed in the late 1970's as a standard data -interchange format between various astronomical observatories. Since -then FITS has become the standard data format supported by most -astronomical data analysis software packages. - -A FITS file consists of one or more Header + Data Units (HDUs), where -the first HDU is called the `Primary HDU', or `Primary Array'. The -primary array contains an N-dimensional array of pixels, such as a 1-D -spectrum, a 2-D image, or a 3-D data cube. Six different primary -data types are supported: Unsigned 8-bit bytes, 16-bit, 32-bit, and 64-bit signed -integers, and 32 and 64-bit floating point reals. FITS also has a -convention for storing 16 and 32-bit unsigned integers (see the later -section entitled `Unsigned Integers' for more details). The primary HDU -may also consist of only a header with a null array containing no -data pixels. - -Any number of additional HDUs may follow the primary array; these -additional HDUs are called FITS `extensions'. There are currently 3 -types of extensions defined by the FITS standard: - -\begin{itemize} -\item - Image Extension - a N-dimensional array of pixels, like in a primary array -\item - ASCII Table Extension - rows and columns of data in ASCII character format -\item - Binary Table Extension - rows and columns of data in binary representation -\end{itemize} - -In each case the HDU consists of an ASCII Header Unit followed by an optional -Data Unit. For historical reasons, each Header or Data unit must be an -exact multiple of 2880 8-bit bytes long. Any unused space is padded -with fill characters (ASCII blanks or zeros). - -Each Header Unit consists of any number of 80-character keyword records -or `card images' which have the -general form: - -\begin{verbatim} - KEYNAME = value / comment string - NULLKEY = / comment: This keyword has no value -\end{verbatim} -The keyword names may be up to 8 characters long and can only contain -uppercase letters, the digits 0-9, the hyphen, and the underscore -character. The keyword name is (usually) followed by an equals sign and -a space character (= ) in columns 9 - 10 of the record, followed by the -value of the keyword which may be either an integer, a floating point -number, a character string (enclosed in single quotes), or a boolean -value (the letter T or F). A keyword may also have a null or undefined -value if there is no specified value string, as in the second example, above - -The last keyword in the header is always the `END' keyword which has no -value or comment fields. There are many rules governing the exact -format of a keyword record (see the FITS Standard) so it is better -to rely on standard interface software like CFITSIO to correctly -construct or to parse the keyword records rather than try to deal -directly with the raw FITS formats. - -Each Header Unit begins with a series of required keywords which depend -on the type of HDU. These required keywords specify the size and -format of the following Data Unit. The header may contain other -optional keywords to describe other aspects of the data, such as the -units or scaling values. Other COMMENT or HISTORY keywords are also -frequently added to further document the data file. - -The optional Data Unit immediately follows the last 2880-byte block in -the Header Unit. Some HDUs do not have a Data Unit and only consist of -the Header Unit. - -If there is more than one HDU in the FITS file, then the Header Unit of -the next HDU immediately follows the last 2880-byte block of the -previous Data Unit (or Header Unit if there is no Data Unit). - -The main required keywords in FITS primary arrays or image extensions are: -\begin{itemize} -\item -BITPIX -- defines the data type of the array: 8, 16, 32, 64, -32, -64 for -unsigned 8--bit byte, 16--bit signed integer, 32--bit signed integer, -32--bit IEEE floating point, and 64--bit IEEE double precision floating -point, respectively. -\item -NAXIS -- the number of dimensions in the array, usually 0, 1, 2, 3, or 4. -\item -NAXISn -- (n ranges from 1 to NAXIS) defines the size of each dimension. -\end{itemize} - -FITS tables start with the keyword XTENSION = `TABLE' (for ASCII -tables) or XTENSION = `BINTABLE' (for binary tables) and have the -following main keywords: -\begin{itemize} -\item -TFIELDS -- number of fields or columns in the table -\item -NAXIS2 -- number of rows in the table -\item -TTYPEn -- for each column (n ranges from 1 to TFIELDS) gives the -name of the column -\item -TFORMn -- the data type of the column -\item -TUNITn -- the physical units of the column (optional) -\end{itemize} - -Users should refer to the FITS Support Office at {\tt http://fits.gsfc.nasa.gov} -for further information about the FITS format and related software -packages. - - -\chapter{ Programming Guidelines } - - -\section{CFITSIO Definitions} - -Any program that uses the CFITSIO interface must include the fitsio.h -header file with the statement - -\begin{verbatim} - #include "fitsio.h" -\end{verbatim} -This header file contains the prototypes for all the CFITSIO user -interface routines as well as the definitions of various constants used -in the interface. It also defines a C structure of type `fitsfile' -that is used by CFITSIO to store the relevant parameters that define -the format of a particular FITS file. Application programs must define -a pointer to this structure for each FITS file that is to be opened. -This structure is initialized (i.e., memory is allocated for the -structure) when the FITS file is first opened or created with the -fits\_open\_file or fits\_create\_file routines. This fitsfile pointer -is then passed as the first argument to every other CFITSIO routine -that operates on the FITS file. Application programs must not directly -read or write elements in this fitsfile structure because the -definition of the structure may change in future versions of CFITSIO. - -A number of symbolic constants are also defined in fitsio.h for the -convenience of application programmers. Use of these symbolic -constants rather than the actual numeric value will help to make the -source code more readable and easier for others to understand. - -\begin{verbatim} -String Lengths, for use when allocating character arrays: - - #define FLEN_FILENAME 1025 /* max length of a filename */ - #define FLEN_KEYWORD 72 /* max length of a keyword */ - #define FLEN_CARD 81 /* max length of a FITS header card */ - #define FLEN_VALUE 71 /* max length of a keyword value string */ - #define FLEN_COMMENT 73 /* max length of a keyword comment string */ - #define FLEN_ERRMSG 81 /* max length of a CFITSIO error message */ - #define FLEN_STATUS 31 /* max length of a CFITSIO status text string */ - - Note that FLEN_KEYWORD is longer than the nominal 8-character keyword - name length because the HIERARCH convention supports longer keyword names. - -Access modes when opening a FITS file: - - #define READONLY 0 - #define READWRITE 1 - -BITPIX data type code values for FITS images: - - #define BYTE_IMG 8 /* 8-bit unsigned integers */ - #define SHORT_IMG 16 /* 16-bit signed integers */ - #define LONG_IMG 32 /* 32-bit signed integers */ - #define LONGLONG_IMG 64 /* 64-bit signed integers */ - #define FLOAT_IMG -32 /* 32-bit single precision floating point */ - #define DOUBLE_IMG -64 /* 64-bit double precision floating point */ - - The following 4 data type codes are also supported by CFITSIO: - #define SBYTE_IMG 10 /* 8-bit signed integers, equivalent to */ - /* BITPIX = 8, BSCALE = 1, BZERO = -128 */ - #define USHORT_IMG 20 /* 16-bit unsigned integers, equivalent to */ - /* BITPIX = 16, BSCALE = 1, BZERO = 32768 */ - #define ULONG_IMG 40 /* 32-bit unsigned integers, equivalent to */ - /* BITPIX = 32, BSCALE = 1, BZERO = 2147483648 */ - -Codes for the data type of binary table columns and/or for the -data type of variables when reading or writing keywords or data: - - DATATYPE TFORM CODE - #define TBIT 1 /* 'X' */ - #define TBYTE 11 /* 8-bit unsigned byte, 'B' */ - #define TLOGICAL 14 /* logicals (int for keywords */ - /* and char for table cols 'L' */ - #define TSTRING 16 /* ASCII string, 'A' */ - #define TSHORT 21 /* signed short, 'I' */ - #define TLONG 41 /* signed long, */ - #define TLONGLONG 81 /* 64-bit long signed integer 'K' */ - #define TFLOAT 42 /* single precision float, 'E' */ - #define TDOUBLE 82 /* double precision float, 'D' */ - #define TCOMPLEX 83 /* complex (pair of floats) 'C' */ - #define TDBLCOMPLEX 163 /* double complex (2 doubles) 'M' */ - - The following data type codes are also supported by CFITSIO: - #define TINT 31 /* int */ - #define TSBYTE 12 /* 8-bit signed byte, 'S' */ - #define TUINT 30 /* unsigned int 'V' */ - #define TUSHORT 20 /* unsigned short 'U' */ - #define TULONG 40 /* unsigned long */ - - The following data type code is only for use with fits\_get\_coltype - #define TINT32BIT 41 /* signed 32-bit int, 'J' */ - - -HDU type code values (value returned when moving to new HDU): - - #define IMAGE_HDU 0 /* Primary Array or IMAGE HDU */ - #define ASCII_TBL 1 /* ASCII table HDU */ - #define BINARY_TBL 2 /* Binary table HDU */ - #define ANY_HDU -1 /* matches any type of HDU */ - -Column name and string matching case-sensitivity: - - #define CASESEN 1 /* do case-sensitive string match */ - #define CASEINSEN 0 /* do case-insensitive string match */ - -Logical states (if TRUE and FALSE are not already defined): - - #define TRUE 1 - #define FALSE 0 - -Values to represent undefined floating point numbers: - - #define FLOATNULLVALUE -9.11912E-36F - #define DOUBLENULLVALUE -9.1191291391491E-36 - -Image compression algorithm definitions - - #define RICE_1 11 - #define GZIP_1 21 - #define GZIP_2 22 - #define PLIO_1 31 - #define HCOMPRESS_1 41 - #define NOCOMPRESS -1 - - #define NO_DITHER -1 - #define SUBTRACTIVE_DITHER_1 1 - #define SUBTRACTIVE_DITHER_2 2 -\end{verbatim} - - -\section{Current Header Data Unit (CHDU)} - -The concept of the Current Header and Data Unit, or CHDU, is -fundamental to the use of the CFITSIO library. A simple FITS image may -only contain a single Header and Data unit (HDU), but in general FITS -files can contain multiple Header Data Units (also known as -`extensions'), concatenated one after the other in the file. The user -can specify which HDU should be initially opened at run time by giving -the HDU name or number after the root file name. For example, -'myfile.fits[4]' opens the 5th HDU in the file (note that the numbering -starts with 0), and 'myfile.fits[EVENTS] opens the HDU with the name -'EVENTS' (as defined by the EXTNAME or HDUNAME keywords). If no HDU is -specified then CFITSIO opens the first HDU (the primary array) by -default. The CFITSIO routines which read and write data only operate -within the opened HDU, Other CFITSIO routines are provided to move to -and open any other existing HDU within the FITS file or to append or -insert new HDUs in the FITS file. - - -\section{Function Names and Variable Datatypes} - -Most of the CFITSIO routines have both a short name as well as a -longer descriptive name. The short name is only 5 or 6 characters long -and is similar to the subroutine name in the Fortran-77 version of -FITSIO. The longer name is more descriptive and it is recommended that -it be used instead of the short name to more clearly document the -source code. - -Many of the CFITSIO routines come in families which differ only in the -data type of the associated parameter(s). The data type of these -routines is indicated by the suffix of the routine name. The short -routine names have a 1 or 2 character suffix (e.g., 'j' in 'ffpkyj') -while the long routine names have a 4 character or longer suffix -as shown in the following table: - -\begin{verbatim} - Long Short Data - Names Names Type - ----- ----- ---- - _bit x bit - _byt b unsigned byte - _sbyt sb signed byte - _sht i short integer - _lng j long integer - _lnglng jj 8-byte LONGLONG integer (see note below) - _usht ui unsigned short integer - _ulng uj unsigned long integer - _uint uk unsigned int integer - _int k int integer - _flt e real exponential floating point (float) - _fixflt f real fixed-decimal format floating point (float) - _dbl d double precision real floating-point (double) - _fixdbl g double precision fixed-format floating point (double) - _cmp c complex reals (pairs of float values) - _fixcmp fc complex reals, fixed-format floating point - _dblcmp m double precision complex (pairs of double values) - _fixdblcmp fm double precision complex, fixed-format floating point - _log l logical (int) - _str s character string -\end{verbatim} - -The logical data type corresponds to `int' for logical keyword values, -and `byte' for logical binary table columns. In other words, the value -when writing a logical keyword must be stored in an `int' variable, and -must be stored in a `char' array when reading or writing to `L' columns -in a binary table. Implicit data type conversion is not supported for -logical table columns, but is for keywords, so a logical keyword may be -read and cast to any numerical data type; a returned value = 0 -indicates false, and any other value = true. - -The `int' data type may be 2 bytes long on some old PC compilers, -but otherwise it is nearly always 4 bytes long. Some 64-bit -machines, like the Alpha/OSF, define the `short', `int', -and `long' integer data types to be 2, 4, and 8 bytes long, -respectively. - -Because there is no universal C compiler standard for the name of the -8-byte integer datatype, the fitsio.h include file typedef's -'LONGLONG' to be equivalent to an -appropriate 8-byte integer data type on each supported platform. -For maximum software portability it is recommended that -this LONGLONG datatype be used to define 8-byte integer variables -rather than using the native data type name on a particular -platform. On most -32-bit Unix and Mac OS-X operating systems LONGLONG is equivalent to the -intrinsic 'long long' 8-byte integer datatype. On 64-bit systems (which currently -includes Alpha OSF/1, 64-bit Sun Solaris, 64-bit SGI MIPS, and 64-bit -Itanium and Opteron PC systems), LONGLONG is simply typedef'ed to be -equivalent to 'long'. Microsoft Visual C++ Version 6.0 does not define -a 'long long' data type, so LONGLONG is typedef'ed to be equivalent to -the '\_\_int64' data type on 32-bit windows systems when using Visual C++. - -A related issue that affects the portability of software is how to print -out the value of a 'LONGLONG' variable with printf. Developers may -find it convenient to use the following preprocessing statements -in their C programs to handle this in a machine-portable manner: - - -\begin{verbatim} -#if defined(_MSC_VER) /* Microsoft Visual C++ */ - printf("%I64d", longlongvalue); - -#elif (USE_LL_SUFFIX == 1) - printf("%lld", longlongvalue); - -#else - printf("%ld", longlongvalue); -#endif -\end{verbatim} - -Similarly, the name of the C utility routine that converts a character -string of digits into a 8-byte integer value is platform dependent: - - -\begin{verbatim} -#if defined(_MSC_VER) /* Microsoft Visual C++ */ - /* VC++ 6.0 does not seem to have an 8-byte conversion routine */ - -#elif (USE_LL_SUFFIX == 1) - longlongvalue = atoll(*string); - -#else - longlongvalue = atol(*string); -#endif -\end{verbatim} - -When dealing with the FITS byte data type it is important to remember -that the raw values (before any scaling by the BSCALE and BZERO, or -TSCALn and TZEROn keyword values) in byte arrays (BITPIX = 8) or byte -columns (TFORMn = 'B') are interpreted as unsigned bytes with values -ranging from 0 to 255. Some C compilers define a 'char' variable as -signed, so it is important to explicitly declare a numeric char -variable as 'unsigned char' to avoid any ambiguity - -One feature of the CFITSIO routines is that they can operate on a `X' -(bit) column in a binary table as though it were a `B' (byte) column. -For example a `11X' data type column can be interpreted the same as a -`2B' column (i.e., 2 unsigned 8-bit bytes). In some instances, it can -be more efficient to read and write whole bytes at a time, rather than -reading or writing each individual bit. - -The complex and double precision complex data types are not directly -supported in ANSI C so these data types should be interpreted as pairs -of float or double values, respectively, where the first value in each -pair is the real part, and the second is the imaginary part. - - -\section{Support for Unsigned Integers and Signed Bytes} - -Although FITS does not directly support unsigned integers as one of its -fundamental data types, FITS can still be used to efficiently store -unsigned integer data values in images and binary tables. The -convention used in FITS files is to store the unsigned integers as -signed integers with an associated offset (specified by the BZERO or -TZEROn keyword). For example, to store unsigned 16-bit integer values -in a FITS image the image would be defined as a signed 16-bit integer -(with BITPIX keyword = SHORT\_IMG = 16) with the keywords BSCALE = 1.0 -and BZERO = 32768. Thus the unsigned values of 0, 32768, and 65535, -for example, are physically stored in the FITS image as -32768, 0, and -32767, respectively; CFITSIO automatically adds the BZERO offset to -these values when they are read. Similarly, in the case of unsigned -32-bit integers the BITPIX keyword would be equal to LONG\_IMG = 32 and -BZERO would be equal to 2147483648 (i.e. 2 raised to the 31st power). - -The CFITSIO interface routines will efficiently and transparently apply -the appropriate offset in these cases so in general application -programs do not need to be concerned with how the unsigned values are -actually stored in the FITS file. As a convenience for users, CFITSIO -has several predefined constants for the value of BITPIX (USHORT\_IMG, -ULONG\_IMG) and for the TFORMn value in the case of binary tables (`U' -and `V') which programmers can use when creating FITS files containing -unsigned integer values. The following code fragment illustrates how -to write a FITS 1-D primary array of unsigned 16-bit integers: - -\begin{verbatim} - unsigned short uarray[100]; - int naxis, status; - long naxes[10], group, firstelem, nelements; - ... - status = 0; - naxis = 1; - naxes[0] = 100; - fits_create_img(fptr, USHORT_IMG, naxis, naxes, &status); - - firstelem = 1; - nelements = 100; - fits_write_img(fptr, TUSHORT, firstelem, nelements, - uarray, &status); - ... -\end{verbatim} -In the above example, the 2nd parameter in fits\_create\_img tells -CFITSIO to write the header keywords appropriate for an array of 16-bit -unsigned integers (i.e., BITPIX = 16 and BZERO = 32768). Then the -fits\_write\_img routine writes the array of unsigned short integers -(uarray) into the primary array of the FITS file. Similarly, a 32-bit -unsigned integer image may be created by setting the second parameter -in fits\_create\_img equal to `ULONG\_IMG' and by calling the -fits\_write\_img routine with the second parameter = TULONG to write -the array of unsigned long image pixel values. - -An analogous set of routines are available for reading or writing unsigned -integer values and signed byte values in a FITS binary table extension. -When specifying the TFORMn keyword value which defines the format of a -column, CFITSIO recognized 3 additional data type codes besides those -already defined in the FITS standard: `U' meaning a 16-bit unsigned -integer column, `V' for a 32-bit unsigned integer column, and 'S' -for a signed byte column. These non-standard data type codes are not -actually written into the FITS file but instead are just used internally -within CFITSIO. The following code fragment illustrates how to use -these features: - -\begin{verbatim} - unsigned short uarray[100]; - unsigned int varray[100]; - - int colnum, tfields, status; - long nrows, firstrow, firstelem, nelements, pcount; - - char extname[] = "Test_table"; /* extension name */ - - /* define the name, data type, and physical units for the 2 columns */ - char *ttype[] = { "Col_1", "Col_2", "Col_3" }; - char *tform[] = { "1U", "1V", "1S"}; /* special CFITSIO codes */ - char *tunit[] = { " ", " ", " " }; - ... - - /* write the header keywords */ - status = 0; - nrows = 1; - tfields = 3 - pcount = 0; - fits_create_tbl(fptr, BINARY_TBL, nrows, tfields, ttype, tform, - tunit, extname, &status); - - /* write the unsigned shorts to the 1st column */ - colnum = 1; - firstrow = 1; - firstelem = 1; - nelements = 100; - fits_write_col(fptr, TUSHORT, colnum, firstrow, firstelem, - nelements, uarray, &status); - - /* now write the unsigned longs to the 2nd column */ - colnum = 2; - fits_write_col(fptr, TUINT, colnum, firstrow, firstelem, - nelements, varray, &status); - ... -\end{verbatim} -Note that the non-standard TFORM values for the 3 columns, `U' and `V', -tell CFITSIO to write the keywords appropriate for unsigned 16-bit and -unsigned 32-bit integers, respectively (i.e., TFORMn = '1I' and TZEROn -= 32768 for unsigned 16-bit integers, and TFORMn = '1J' and TZEROn = -2147483648 for unsigned 32-bit integers). The 'S' TFORMn value tells -CFITSIO to write the keywords appropriate for a signed 8-bit byte column -with TFORMn = '1B' and TZEROn = -128. The calls to fits\_write\_col -then write the arrays of unsigned integer values to the columns. - - -\section{Dealing with Character Strings} - -The character string values in a FITS header or in an ASCII column in a -FITS table extension are generally padded out with non-significant -space characters (ASCII 32) to fill up the header record or the column -width. When reading a FITS string value, the CFITSIO routines will -strip off these non-significant trailing spaces and will return a -null-terminated string value containing only the significant -characters. Leading spaces in a FITS string are considered -significant. If the string contains all blanks, then CFITSIO will -return a single blank character, i.e, the first blank is considered to -be significant, since it distinguishes the string from a null or -undefined string, but the remaining trailing spaces are not -significant. - -Similarly, when writing string values to a FITS file the -CFITSIO routines expect to get a null-terminated string as input; -CFITSIO will pad the string with blanks if necessary when writing it -to the FITS file. - -When calling CFITSIO routines that return a character string it is -vital that the size of the char array be large enough to hold the -entire string of characters, otherwise CFITSIO will overwrite whatever -memory locations follow the char array, possibly causing the program to -execute incorrectly. This type of error can be difficult to debug, so -programmers should always ensure that the char arrays are allocated -enough space to hold the longest possible string, {\bf including} the -terminating NULL character. The fitsio.h file contains the following -defined constants which programmers are strongly encouraged to use -whenever they are allocating space for char arrays: - -\begin{verbatim} -#define FLEN_FILENAME 1025 /* max length of a filename */ -#define FLEN_KEYWORD 72 /* max length of a keyword */ -#define FLEN_CARD 81 /* length of a FITS header card */ -#define FLEN_VALUE 71 /* max length of a keyword value string */ -#define FLEN_COMMENT 73 /* max length of a keyword comment string */ -#define FLEN_ERRMSG 81 /* max length of a CFITSIO error message */ -#define FLEN_STATUS 31 /* max length of a CFITSIO status text string */ -\end{verbatim} -For example, when declaring a char array to hold the value string -of FITS keyword, use the following statement: - -\begin{verbatim} - char value[FLEN_VALUE]; -\end{verbatim} -Note that FLEN\_KEYWORD is longer than needed for the nominal 8-character -keyword name because the HIERARCH convention supports longer keyword names. - - -\section{Implicit Data Type Conversion} - -The CFITSIO routines that read and write numerical data can perform -implicit data type conversion. This means that the data type of the -variable or array in the program does not need to be the same as the -data type of the value in the FITS file. Data type conversion is -supported for numerical and string data types (if the string contains a -valid number enclosed in quotes) when reading a FITS header keyword -value and for numeric values when reading or writing values in the -primary array or a table column. CFITSIO returns status = -NUM\_OVERFLOW if the converted data value exceeds the range of the -output data type. Implicit data type conversion is not supported -within binary tables for string, logical, complex, or double complex -data types. - -In addition, any table column may be read as if it contained string values. -In the case of numeric columns the returned string will be formatted -using the TDISPn display format if it exists. - - -\section{Data Scaling} - -When reading numerical data values in the primary array or a -table column, the values will be scaled automatically by the BSCALE and -BZERO (or TSCALn and TZEROn) header values if they are -present in the header. The scaled data that is returned to the reading -program will have - -\begin{verbatim} - output value = (FITS value) * BSCALE + BZERO -\end{verbatim} -(a corresponding formula using TSCALn and TZEROn is used when reading -from table columns). In the case of integer output values the floating -point scaled value is truncated to an integer (not rounded to the -nearest integer). The fits\_set\_bscale and fits\_set\_tscale routines -(described in the `Advanced' chapter) may be used to override the -scaling parameters defined in the header (e.g., to turn off the scaling -so that the program can read the raw unscaled values from the FITS -file). - -When writing numerical data to the primary array or to a table column -the data values will generally be automatically inversely scaled by the -value of the BSCALE and BZERO (or TSCALn and TZEROn) keyword values if -they they exist in the header. These keywords must have been written -to the header before any data is written for them to have any immediate -effect. One may also use the fits\_set\_bscale and fits\_set\_tscale -routines to define or override the scaling keywords in the header -(e.g., to turn off the scaling so that the program can write the raw -unscaled values into the FITS file). If scaling is performed, the -inverse scaled output value that is written into the FITS file will -have - -\begin{verbatim} - FITS value = ((input value) - BZERO) / BSCALE -\end{verbatim} -(a corresponding formula using TSCALn and TZEROn is used when -writing to table columns). Rounding to the nearest integer, rather -than truncation, is performed when writing integer data types to the -FITS file. - - -\section{Support for IEEE Special Values} - -The ANSI/IEEE-754 floating-point number standard defines certain -special values that are used to represent such quantities as -Not-a-Number (NaN), denormalized, underflow, overflow, and infinity. -(See the Appendix in the FITS standard or the FITS User's -Guide for a list of these values). The CFITSIO routines that read -floating point data in FITS files recognize these IEEE special values -and by default interpret the overflow and infinity values as being -equivalent to a NaN, and convert the underflow and denormalized values -into zeros. In some cases programmers may want access to the raw IEEE -values, without any modification by CFITSIO. This can be done by -calling the fits\_read\_img or fits\_read\_col routines while -specifying 0.0 as the value of the NULLVAL parameter. This will force -CFITSIO to simply pass the IEEE values through to the application -program without any modification. This is not fully supported on -VAX/VMS machines, however, where there is no easy way to bypass the -default interpretation of the IEEE special values. This is also not -supported when reading floating-point images that have been compressed -with the FITS tiled image compression convention that is discussed in -section 5.6; the pixels values in tile compressed images are -represented by scaled integers, and a reserved integer value -(not a NaN) is used to represent undefined pixels. - - -\section{Error Status Values and the Error Message Stack} - -Nearly all the CFITSIO routines return an error status value -in 2 ways: as the value of the last parameter in the function call, -and as the returned value of the function itself. This provides -some flexibility in the way programmers can test if an error -occurred, as illustrated in the following 2 code fragments: - -\begin{verbatim} - if ( fits_write_record(fptr, card, &status) ) - printf(" Error occurred while writing keyword."); - -or, - - fits_write_record(fptr, card, &status); - if ( status ) - printf(" Error occurred while writing keyword."); -\end{verbatim} -A listing of all the CFITSIO status code values is given at the end of -this document. Programmers are encouraged to use the symbolic -mnemonics (defined in fitsio.h) rather than the actual integer status -values to improve the readability of their code. - -The CFITSIO library uses an `inherited status' convention for the -status parameter which means that if a routine is called with a -positive input value of the status parameter as input, then the routine -will exit immediately without changing the value of the status -parameter. Thus, if one passes the status value returned from each -CFITSIO routine as input to the next CFITSIO routine, then whenever an -error is detected all further CFITSIO processing will cease. This -convention can simplify the error checking in application programs -because it is not necessary to check the value of the status parameter -after every single CFITSIO routine call. If a program contains a -sequence of several CFITSIO calls, one can just check the status value -after the last call. Since the returned status values are generally -distinctive, it should be possible to determine which routine -originally returned the error status. - -CFITSIO also maintains an internal stack of error messages -(80-character maximum length) which in many cases provide a more -detailed explanation of the cause of the error than is provided by the -error status number alone. It is recommended that the error message -stack be printed out whenever a program detects a CFITSIO error. The -function fits\_report\_error will print out the entire error message -stack, or alternatively one may call fits\_read\_errmsg to get the -error messages one at a time. - - -\section{Variable-Length Arrays in Binary Tables} - -CFITSIO provides easy-to-use support for reading and writing data in -variable length fields of a binary table. The variable length columns -have TFORMn keyword values of the form `1Pt(len)' or `1Qt(len)' where `t' -is the data type code (e.g., I, J, E, D, etc.) and `len' is an integer -specifying the maximum length of the vector in the table. The 'P' type -variable length columns use 32-bit array length and byte offset values, whereas -the 'Q' type columns use 64-bit values, which may be required when dealing -with large arrays. CFITSIO supports a local convention that interprets -the 'P' type descriptors as unsigned 32-bit integers, which provides -a factor of 2 greater range for the array length or heap address than -is possible with 32-bit 'signed' integers. Note, however, that other software -packages may not support this convention, and may be unable to read thees -extended range variable length records. - -If the value -of `len' is not specified when the table is created (e.g., if the TFORM -keyword value is simply specified as '1PE' instead of '1PE(400) ), then -CFITSIO will automatically scan the table when it is closed to -determine the maximum length of the vector and will append this value -to the TFORMn value. - -The same routines that read and write data in an ordinary fixed length -binary table extension are also used for variable length fields, -however, the routine parameters take on a slightly different -interpretation as described below. - -All the data in a variable length field is written into an area called -the `heap' which follows the main fixed-length FITS binary table. The -size of the heap, in bytes, is specified by the PCOUNT keyword in the -FITS header. When creating a new binary table, the initial value of -PCOUNT should usually be set to zero. CFITSIO will recompute the size -of the heap as the data is written and will automatically update the -PCOUNT keyword value when the table is closed. When writing variable -length data to a table, CFITSIO will automatically extend the size -of the heap area if necessary, so that any following HDUs do not -get overwritten. - -By default the heap data area starts immediately after the last row of -the fixed-length table. This default starting location may be -overridden by the THEAP keyword, but this is not recommended. -If additional rows of data are added to the table, CFITSIO will -automatically shift the the heap down to make room for the new -rows, but it is obviously be more efficient to initially -create the table with the necessary number of blank rows, so that -the heap does not needed to be constantly moved. - -When writing row of data to a variable length field the entire array of values for -a given row of the table must be written with a single call to -fits\_write\_col. -The total length of the array is given by nelements -+ firstelem - 1. Additional elements cannot be appended to an existing -vector at a later time since any attempt to do so will simply overwrite -all the previously written data and the new data will be -written to a new area of the heap. The fits\_compress\_heap routine -is provided to compress the heap and recover any unused space. -To avoid having to deal with this issue, it is recommended -that rows in a variable length field should only be written once. -An exception to -this general rule occurs when setting elements of an array as -undefined. It is allowed to first write a dummy value into the array with -fits\_write\_col, and then call fits\_write\_col\_nul to flag the -desired elements as undefined. Note that the rows of a table, -whether fixed or variable length, do not have to be written -consecutively and may be written in any order. - -When writing to a variable length ASCII character field (e.g., TFORM = -'1PA') only a single character string can be written. The `firstelem' -and `nelements' parameter values in the fits\_write\_col routine are -ignored and the number of characters to write is simply determined by -the length of the input null-terminated character string. - -The fits\_write\_descript routine is useful in situations where -multiple rows of a variable length column have the identical array of -values. One can simply write the array once for the first row, and -then use fits\_write\_descript to write the same descriptor values into -the other rows; all the rows will then point to the same storage -location thus saving disk space. - -When reading from a variable length array field one can only read as -many elements as actually exist in that row of the table; reading does -not automatically continue with the next row of the table as occurs -when reading an ordinary fixed length table field. Attempts to read -more than this will cause an error status to be returned. One can -determine the number of elements in each row of a variable column with -the fits\_read\_descript routine. - - -\section{Multiple Access to the Same FITS File} - -CFITSIO supports simultaneous read and write access to different -HDUs in the same FITS file in some circumstances, as described -below: - -\begin{itemize} - -\item -Multi-threaded programs - -When CFITSIO is compiled with the -D\_REENTRANT directive (as can be -tested with the fits\_is\_reentrant function) different threads can -call any of the CFITSIO routines to simultaneously read or write -separate FITS files. Multiple threads can also read data from the -same FITS file simultaneously, as long as the file was opened -independently by each thread. This relies on the operating system -to correctly deal with reading the same file by multiple processes. -Different threads should not share the same 'fitsfile' pointer to -read an opened FITS file, unless locks are placed around the calls -to the CFITSIO reading routines. Different threads should never -try to write to the same FITS file. - -\item -Multiple read access to the same FITS file within a single -program/thread - -A single process may open the same FITS file with READONLY access -multiple times, and thus create multiple 'fitsfile*' pointers to -that same file within CFITSIO. This relies on the operating system's -ability to open a single file multiple times and correctly manage -the subsequent read requests directed to the different C 'file*' -pointers, which actually all point to the same file. CFITSIO simply -executes the read requests to the differnet 'fitsfile*' pointers the -same as if they were physically different files. - -\item -Multiple write access to the same FITS file within a single -program/thread - -CFITSIO supports opening the same FITS file multiple times with -WRITE access, but it only physically opens the file (at the -operating system level) once, on the first call to fits\_open\_file. -If fits\_open\_file is subsequently called to open the same file -again, CFITSIO will recognize that the file is already open, and -will return a new 'fitsfile*' pointer that logically points to the -first 'fitsfile*' pointer, without actually opening the file a -second time. The application program can then treat the 2 -'fitsfile*' pointers as if they point to different files, and can -seemingly move to and write data to 2 different HDUs within the -same file. However, each time the application program switches -which 'fitsfile*' pointer it is writing to, CFITSIO will flush any -internal buffers that contain data written to the first 'fitsfile*' -pointer, then move to the HDU that the other 'fitsfile*' pointer -is writing to. Obviously, this may add a significant amount of -computational overhead if the application program uses this feature -to frequently switch back and forth between writing to 2 (or more) -HDUs in the same file, so this capability should be used -judiciously. - -Note that CFITSIO will not allow a FITS file to be opened a second -time with READWRITE access if it was opened previously with READONLY -access. - -\end{itemize} - - -\section{When the Final Size of the FITS HDU is Unknown} - -It is not required to know the total size of a FITS data array or table -before beginning to write the data to the FITS file. In the case of -the primary array or an image extension, one should initially create -the array with the size of the highest dimension (largest NAXISn -keyword) set to a dummy value, such as 1. Then after all the data have -been written and the true dimensions are known, then the NAXISn value -should be updated using the fits\_update\_key routine before moving to -another extension or closing the FITS file. - -When writing to FITS tables, CFITSIO automatically keeps track of the -highest row number that is written to, and will increase the size of -the table if necessary. CFITSIO will also automatically insert space -in the FITS file if necessary, to ensure that the data 'heap', if it -exists, and/or any additional HDUs that follow the table do not get -overwritten as new rows are written to the table. - -As a general rule it is best to specify the initial number of rows = 0 -when the table is created, then let CFITSIO keep track of the number of -rows that are actually written. The application program should not -manually update the number of rows in the table (as given by the NAXIS2 -keyword) since CFITSIO does this automatically. If a table is -initially created with more than zero rows, then this will usually be -considered as the minimum size of the table, even if fewer rows are -actually written to the table. Thus, if a table is initially created -with NAXIS2 = 20, and CFITSIO only writes 10 rows of data before -closing the table, then NAXIS2 will remain equal to 20. If however, 30 -rows of data are written to this table, then NAXIS2 will be increased -from 20 to 30. The one exception to this automatic updating of the -NAXIS2 keyword is if the application program directly modifies the -value of NAXIS2 (up or down) itself just before closing the table. In this -case, CFITSIO does not update NAXIS2 again, since it assumes that the -application program must have had a good reason for changing the value -directly. This is not recommended, however, and is only provided for -backward compatibility with software that initially creates a table -with a large number of rows, than decreases the NAXIS2 value to the -actual smaller value just before closing the table. - - -\section{CFITSIO Size Limitations} - -CFITSIO places very few restrictions on the size of FITS files that it -reads or writes. There are a few limits, however, that may affect -some extreme cases: - -1. The maximum number of FITS files that may be simultaneously opened by -CFITSIO is set by NMAXFILES, as defined in fitsio2.h. The current default -value is 1000, but this may be increased if necessary. Note that CFITSIO -allocates NIOBUF * 2880 bytes of I/O buffer space for each file that is -opened. The default value of NIOBUF is 40 (defined in fitsio.h), so this -amounts to more than 115K of memory for each opened file (or 115 MB for -1000 opened files). Note that the underlying operating system, may have a -lower limit on the number of files that can be opened simultaneously. - -2. It used to be common for computer systems to only support disk files up -to 2**31 bytes = 2.1 GB in size, but most systems now support larger files. -CFITSIO can optionally read and write these so-called 'large files' that -are greater than 2.1 GB on -platforms where they are supported, but this -usually requires that special compiler option flags be specified to turn -on this option. On linux and solaris systems the compiler flags are -'-D\_LARGEFILE\_SOURCE' and `-D\_FILE\_OFFSET\_BITS=64'. These flags -may also work on other platforms but this has not been tested. Starting -with version 3.0 of CFITSIO, the default Makefile that is distributed -with CFITSIO will include these 2 compiler flags when building on Solaris -and Linux PC systems. Users on other platforms will need to add these -compiler flags manually if they want to support large files. In most -cases it appears that it is not necessary to include these compiler -flags when compiling application code that call the CFITSIO library -routines. - -When CFITSIO is built with large file support (e.g., on Solaris and -Linux PC system by default) then it can read and write FITS data files -on disk that have any of these conditions: - -\begin{itemize} -\item -FITS files larger than 2.1 GB in size -\item -FITS images containing greater than 2.1 G pixels -\item -FITS images that have one dimension with more than 2.1 G pixels -(as given by one of the NAXISn keyword) -\item -FITS tables containing more than 2.1E09 rows (given by the NAXIS2 keyword), -or with rows that are more than 2.1 GB wide (given by the NAXIS1 keyword) -\item -FITS binary tables with a variable-length array heap that is larger -than 2.1 GB (given by the PCOUNT keyword) -\end{itemize} - -The current maximum FITS file size supported by CFITSIO -is about 6 terabytes (containing -2**31 FITS blocks, each 2880 bytes in size). Currently, support for large -files in CFITSIO has been tested on the Linux, Solaris, and IBM AIX -operating systems. - -Note that when writing application programs that are intended to support -large files it is important to use 64-bit integer variables -to store quantities such as the dimensions of images, or the number of -rows in a table. These programs must also call the special versions -of some of the CFITSIO routines that have been adapted to -support 64-bit integers. The names of these routines end in -'ll' ('el' 'el') to distinguish them from the 32-bit integer -version (e.g., fits\_get\_num\_rowsll). - - -\chapter{Basic CFITSIO Interface Routines } - -This chapter describes the basic routines in the CFITSIO user interface -that provide all the functions normally needed to read and write most -FITS files. It is recommended that these routines be used for most -applications and that the more advanced routines described in the -next chapter only be used in special circumstances when necessary. - -The following conventions are used in this chapter in the description -of each function: - -1. Most functions have 2 names: a long descriptive name and a short -concise name. Both names are listed on the first line of the following -descriptions, separated by a slash (/) character. Programmers may use -either name in their programs but the long names are recommended to -help document the code and make it easier to read. - -2. A right arrow symbol ($>$) is used in the function descriptions to -separate the input parameters from the output parameters in the -definition of each routine. This symbol is not actually part of the C -calling sequence. - -3. The function parameters are defined in more detail in the -alphabetical listing in Appendix B. - -4. The first argument in almost all the functions is a pointer to a -structure of type `fitsfile'. Memory for this structure is allocated -by CFITSIO when the FITS file is first opened or created and is freed -when the FITS file is closed. - -5. The last argument in almost all the functions is the error status -parameter. It must be equal to 0 on input, otherwise the function will -immediately exit without doing anything. A non-zero output value -indicates that an error occurred in the function. In most cases the -status value is also returned as the value of the function itself. - - -\section{CFITSIO Error Status Routines} - - -\begin{description} -\item[1 ] Return a descriptive text string (30 char max.) corresponding to - a CFITSIO error status code.\label{ffgerr} -\end{description} - -\begin{verbatim} - void fits_get_errstatus / ffgerr (int status, > char *err_text) -\end{verbatim} - -\begin{description} -\item[2 ] Return the top (oldest) 80-character error message from the - internal CFITSIO stack of error messages and shift any remaining - messages on the stack up one level. Call this routine - repeatedly to get each message in sequence. The function returns - a value = 0 and a null error message when the error stack is empty. -\label{ffgmsg} -\end{description} - -\begin{verbatim} - int fits_read_errmsg / ffgmsg (char *err_msg) -\end{verbatim} - -\begin{description} -\item[3 ] Print out the error message corresponding to the input status - value and all the error messages on the CFITSIO stack to the specified - file stream (normally to stdout or stderr). If the input - status value = 0 then this routine does nothing. -\label{ffrprt} -\end{description} - -\begin{verbatim} - void fits_report_error / ffrprt (FILE *stream, status) -\end{verbatim} - -\begin{description} -\item[4 ]The fits\_write\_errmark routine puts an invisible marker on the - CFITSIO error stack. The fits\_clear\_errmark routine can then be - used to delete any more recent error messages on the stack, back to - the position of the marker. This preserves any older error messages - on the stack. The fits\_clear\_errmsg routine simply clears all the - messages (and marks) from the stack. These routines are called - without any arguments. -\label{ffpmrk} \label{ffcmsg} -\end{description} - -\begin{verbatim} - void fits_write_errmark / ffpmrk (void) - void fits_clear_errmark / ffcmrk (void) - void fits_clear_errmsg / ffcmsg (void) -\end{verbatim} - - -\section{FITS File Access Routines} - - -\begin{description} -\item[1 ] Open an existing data file. \label{ffopen} - - -\begin{verbatim} -int fits_open_file / ffopen - (fitsfile **fptr, char *filename, int iomode, > int *status) - -int fits_open_diskfile / ffdkopen - (fitsfile **fptr, char *filename, int iomode, > int *status) - -int fits_open_data / ffdopn - (fitsfile **fptr, char *filename, int iomode, > int *status) - -int fits_open_table / fftopn - (fitsfile **fptr, char *filename, int iomode, > int *status) - -int fits_open_image / ffiopn - (fitsfile **fptr, char *filename, int iomode, > int *status) - -int fits_open_extlist / ffeopn - (fitsfile **fptr, char *filename, int iomode, char *extlist, - > int *hdutype, int *status) -\end{verbatim} - -The iomode parameter determines the read/write access allowed in the -file and can have values of READONLY (0) or READWRITE (1). The filename -parameter gives the name of the file to be opened, followed by an -optional argument giving the name or index number of the extension -within the FITS file that should be moved to and opened (e.g., -\verb-myfile.fits+3- or \verb-myfile.fits[3]- moves to the 3rd extension within -the file, and \verb-myfile.fits[events]- moves to the extension with the -keyword EXTNAME = 'EVENTS'). - -The fits\_open\_diskfile routine is similar to the fits\_open\_file routine -except that it does not support the extended filename syntax in the input -file name. This routine simply tries to open the specified input file -on magnetic disk. This routine is mainly for use in cases where the -filename (or directory path) contains square or curly bracket characters -that would confuse the extended filename parser. - -The fits\_open\_data routine is similar to the fits\_open\_file routine -except that it will move to the first HDU containing significant data, -if a HDU name or number to open was not explicitly specified as -part of the filename. In this case, it will look for the first -IMAGE HDU with NAXIS greater than 0, or the first table that does not contain the -strings `GTI' (Good Time Interval extension) or `OBSTABLE' in the -EXTNAME keyword value. - -The fits\_open\_table and fits\_open\_image routines are similar to -fits\_open\_data except they will move to the first significant table -HDU or image HDU in the file, respectively, if a HDU name or -number is not specified as part of the filename. - -The fits\_open\_extname routine opens the file and attempts to move to a 'useful' -HDU. If after opening the file CFITSIO is pointing to null primary array, -then CFITSIO will attempt to move to the first extension that has an EXTNAME or -HDUNAME keyword value that matches one of the names in the input extlist -space-delimited list of names. If that fails, then CFITSIO simply moves to the -2nd HDU in the file. - -IRAF images (.imh format files) and raw binary data arrays may also be -opened with READONLY access. CFITSIO will automatically test if the -input file is an IRAF image, and if, so will convert it on the fly into -a virtual FITS image before it is opened by the application program. -If the input file is a raw binary data array of numbers, then the data type -and dimensions of the array must be specified in square brackets -following the name of the file (e.g. 'rawfile.dat[i512,512]' opens a -512 x 512 short integer image). See the `Extended File Name Syntax' -chapter for more details on how to specify the raw file name. The raw -file is converted on the fly into a virtual FITS image in memory that -is then opened by the application program with READONLY access. - -Programs can read the input file from the 'stdin' file stream if a dash -character ('-') is given as the filename. Files can also be opened over -the network using FTP or HTTP protocols by supplying the appropriate URL -as the filename. - -The input file can be modified in various ways to create a virtual file -(usually stored in memory) that is then opened by the application -program by supplying a filtering or binning specifier in square brackets -following the filename. Some of the more common filtering methods are -illustrated in the following paragraphs, but users should refer to the -'Extended File Name Syntax' chapter for a complete description of -the full file filtering syntax. - -When opening an image, a rectangular subset of the physical image may be -opened by listing the first and last pixel in each dimension (and -optional pixel skipping factor): - -\begin{verbatim} -myimage.fits[101:200,301:400] -\end{verbatim} -will create and open a 100x100 pixel virtual image of that section of -the physical image, and \verb+myimage.fits[*,-*]+ opens a virtual image -that is the same size as the physical image but has been flipped in -the vertical direction. - -When opening a table, the filtering syntax can be used to add or delete -columns or keywords in the virtual table: -\verb-myfile.fits[events][col !time; PI = PHA*1.2]- opens a virtual table in which the TIME column -has been deleted and a new PI column has been added with a value 1.2 -times that of the PHA column. Similarly, one can filter a table to keep -only those rows that satisfy a selection criterion: -\verb-myfile.fits[events][pha > 50]- creates and opens a virtual table -containing only those rows with a PHA value greater than 50. A large -number of boolean and mathematical operators can be used in the -selection expression. One can also filter table rows using 'Good Time -Interval' extensions, and spatial region filters as in -\verb-myfile.fits[events][gtifilter()]- and -\verb-myfile.fits[events][regfilter( "stars.rng")]-. - -Finally, table columns may be binned or histogrammed to generate a -virtual image. For example, \verb-myfile.fits[events][bin (X,Y)=4]- will -result in a 2-dimensional image calculated by binning the X and Y -columns in the event table with a bin size of 4 in each dimension. The -TLMINn and TLMAXn keywords will be used by default to determine the -range of the image. - -A single program can open the same FITS file more than once and then -treat the resulting fitsfile pointers as though they were completely -independent FITS files. Using this facility, a program can open a FITS -file twice, move to 2 different extensions within the file, and then - read and write data in those extensions in any order. -\end{description} - - -\begin{description} -\item[2 ] Create and open a new empty output FITS file. \label{ffinit} - - -\begin{verbatim} -int fits_create_file / ffinit - (fitsfile **fptr, char *filename, > int *status) - -int fits_create_diskfile / ffdkinit - (fitsfile **fptr, char *filename, > int *status) -\end{verbatim} - -An error will be returned if the specified file already exists, unless -the filename is prefixed with an exclamation point (!). In that case -CFITSIO will overwrite (delete) any existing file with the same name. -Note that the exclamation point is a special UNIX character so if -it is used on the command line it must be preceded by a backslash to -force the UNIX shell to accept the character as part of the filename. - -The output file will be written to the 'stdout' file stream if a dash -character ('-') or the string 'stdout' is given as the filename. Similarly, -'-.gz' or 'stdout.gz' will cause the file to be gzip compressed before -it is written out to the stdout stream. - -Optionally, the name of a template file that is used to define the -structure of the new file may be specified in parentheses following the -output file name. The template file may be another FITS file, in which -case the new file, at the time it is opened, will be an exact copy of -the template file except that the data structures (images and tables) -will be filled with zeros. Alternatively, the template file may be an -ASCII format text file containing directives that define the keywords to be -created in each HDU of the file. See the 'Extended File Name Syntax' - section for a complete description of the template file syntax. - -The fits\_create\_diskfile routine is similar to the fits\_create\_file routine -except that it does not support the extended filename syntax in the input -file name. This routine simply tries to create the specified file -on magnetic disk. This routine is mainly for use in cases where the -filename (or directory path) contains square or curly bracket characters - that would confuse the extended filename parser. -\end{description} - - - -\begin{description} -\item[3 ] Close a previously opened FITS file. The first routine simply -closes the file, whereas the second one also DELETES the file, which -can be useful in cases where a FITS file has been partially created, -but then an error occurs which prevents it from being completed. -Note that these routines behave differently than most other CFITSIO routines -if the input value of the `status' parameter is not zero: Instead of -simply returning to the calling program without doing anything, these -routines effectively ignore the input status value and still attempt -to close or delete the file. - \label{ffclos} \label{ffdelt} -\end{description} - -\begin{verbatim} - int fits_close_file / ffclos (fitsfile *fptr, > int *status) - - int fits_delete_file / ffdelt (fitsfile *fptr, > int *status) -\end{verbatim} - -\begin{description} -\item[4 ]Return the name, I/O mode (READONLY or READWRITE), and/or the file -type (e.g. 'file://', 'ftp://') of the opened FITS file. \label{ffflnm} - \label{ffflmd} \label{ffurlt} -\end{description} - -\begin{verbatim} - int fits_file_name / ffflnm (fitsfile *fptr, > char *filename, int *status) - - int fits_file_mode / ffflmd (fitsfile *fptr, > int *iomode, int *status) - - int fits_url_type / ffurlt (fitsfile *fptr, > char *urltype, int *status) -\end{verbatim} - -\section{HDU Access Routines} - -The following functions perform operations on Header-Data Units (HDUs) -as a whole. - - -\begin{description} -\item[1 ] Move to a different HDU in the file. The first routine moves to a - specified absolute HDU number (starting with 1 for the primary - array) in the FITS file, and the second routine moves a relative - number HDUs forward or backward from the current HDU. A null - pointer may be given for the hdutype parameter if it's value is not - needed. The third routine moves to the (first) HDU which has the - specified extension type and EXTNAME and EXTVER keyword values (or - HDUNAME and HDUVER keywords). The hdutype parameter may have a - value of IMAGE\_HDU, ASCII\_TBL, BINARY\_TBL, or ANY\_HDU where - ANY\_HDU means that only the extname and extver values will be used - to locate the correct extension. If the input value of extver is 0 - then the EXTVER keyword is ignored and the first HDU with a - matching EXTNAME (or HDUNAME) keyword will be found. If no - matching HDU is found in the file then the current HDU will remain - unchanged and a status = BAD\_HDU\_NUM will be returned. - \label{ffmahd} \label{ffmrhd} \label{ffmnhd} -\end{description} - -\begin{verbatim} - int fits_movabs_hdu / ffmahd - (fitsfile *fptr, int hdunum, > int *hdutype, int *status) - - int fits_movrel_hdu / ffmrhd - (fitsfile *fptr, int nmove, > int *hdutype, int *status) - - int fits_movnam_hdu / ffmnhd - (fitsfile *fptr, int hdutype, char *extname, int extver, > int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Return the total number of HDUs in the FITS file. This returns the -number of completely defined HDUs in the file. If a new HDU has just been added to -the FITS file, then that last HDU will only be counted if it has been closed, -or if data has been written to the HDU. - The current HDU remains unchanged by this routine. \label{ffthdu} -\end{description} - -\begin{verbatim} - int fits_get_num_hdus / ffthdu - (fitsfile *fptr, > int *hdunum, int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Return the number of the current HDU (CHDU) in the FITS file (where - the primary array = 1). This function returns the HDU number - rather than a status value. \label{ffghdn} -\end{description} - -\begin{verbatim} - int fits_get_hdu_num / ffghdn - (fitsfile *fptr, > int *hdunum) -\end{verbatim} - -\begin{description} -\item[4 ] Return the type of the current HDU in the FITS file. The possible - values for hdutype are: IMAGE\_HDU, ASCII\_TBL, or BINARY\_TBL. \label{ffghdt} -\end{description} - -\begin{verbatim} - int fits_get_hdu_type / ffghdt - (fitsfile *fptr, > int *hdutype, int *status) -\end{verbatim} - -\begin{description} -\item[5 ] Copy all or part of the HDUs in the FITS file associated with infptr - and append them to the end of the FITS file associated with - outfptr. If 'previous' is true (not 0), then any HDUs preceding - the current HDU in the input file will be copied to the output - file. Similarly, 'current' and 'following' determine whether the - current HDU, and/or any following HDUs in the input file will be - copied to the output file. Thus, if all 3 parameters are true, then the - entire input file will be copied. On exit, the current HDU in - the input file will be unchanged, and the last HDU in the output - file will be the current HDU. \label{ffcpfl} -\end{description} - -\begin{verbatim} - int fits_copy_file / ffcpfl - (fitsfile *infptr, fitsfile *outfptr, int previous, int current, - int following, > int *status) -\end{verbatim} - -\begin{description} -\item[6 ] Copy the current HDU from the FITS file associated with infptr and append it - to the end of the FITS file associated with outfptr. Space may be - reserved for MOREKEYS additional keywords in the output header. \label{ffcopy} -\end{description} - -\begin{verbatim} - int fits_copy_hdu / ffcopy - (fitsfile *infptr, fitsfile *outfptr, int morekeys, > int *status) -\end{verbatim} - -\begin{description} -\item[7 ] Write the current HDU in the input FITS file to the - output FILE stream (e.g., to stdout). \label{ffwrhdu} -\end{description} - -\begin{verbatim} - int fits_write_hdu / ffwrhdu - (fitsfile *infptr, FILE *stream, > int *status) -\end{verbatim} - -\begin{description} -\item[8 ] Copy the header (and not the data) from the CHDU associated with infptr - to the CHDU associated with outfptr. If the current output HDU - is not completely empty, then the CHDU will be closed and a new - HDU will be appended to the output file. An empty output data unit - will be created with all values initially = 0). \label{ffcphd} -\end{description} - -\begin{verbatim} - int fits_copy_header / ffcphd - (fitsfile *infptr, fitsfile *outfptr, > int *status) -\end{verbatim} - -\begin{description} -\item[9 ] Delete the CHDU in the FITS file. Any following HDUs will be shifted - forward in the file, to fill in the gap created by the deleted - HDU. In the case of deleting the primary array (the first HDU in - the file) then the current primary array will be replace by a null - primary array containing the minimum set of required keywords and - no data. If there are more extensions in the file following the - one that is deleted, then the the CHDU will be redefined to point - to the following extension. If there are no following extensions - then the CHDU will be redefined to point to the previous HDU. The - output hdutype parameter returns the type of the new CHDU. A null - pointer may be given for - hdutype if the returned value is not needed. \label{ffdhdu} -\end{description} - -\begin{verbatim} - int fits_delete_hdu / ffdhdu - (fitsfile *fptr, > int *hdutype, int *status) -\end{verbatim} - -\section{Header Keyword Read/Write Routines} - -These routines read or write keywords in the Current Header Unit -(CHU). Wild card characters (*, ?, or \#) may be used when specifying -the name of the keyword to be read: a '?' will match any single -character at that position in the keyword name and a '*' will match any -length (including zero) string of characters. The '\#' character will -match any consecutive string of decimal digits (0 - 9). When a wild -card is used the routine will only search for a match from the current -header position to the end of the header and will not resume the search -from the top of the header back to the original header position as is -done when no wildcards are included in the keyword name. The -fits\_read\_record routine may be used to set the starting position -when doing wild card searches. A status value of KEY\_NO\_EXIST is -returned if the specified keyword to be read is not found in the -header. - - -\subsection{Keyword Reading Routines} - - -\begin{description} -\item[1 ] Return the number of existing keywords (not counting the - END keyword) and the amount of space currently available for more - keywords. It returns morekeys = -1 if the header has not yet been - closed. Note that CFITSIO will dynamically add space if required - when writing new keywords to a header so in practice there is no - limit to the number of keywords that can be added to a header. A - null pointer may be entered for the morekeys parameter if it's - value is not needed. \label{ffghsp} -\end{description} - -\begin{verbatim} - int fits_get_hdrspace / ffghsp - (fitsfile *fptr, > int *keysexist, int *morekeys, int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Return the specified keyword. In the first routine, - the datatype parameter specifies the desired returned data type of the - keyword value and can have one of the following symbolic constant - values: TSTRING, TLOGICAL (== int), TBYTE, TSHORT, TUSHORT, TINT, - TUINT, TLONG, TULONG, TLONGLONG, TFLOAT, TDOUBLE, TCOMPLEX, and TDBLCOMPLEX. - Within the context of this routine, TSTRING corresponds to a - 'char*' data type, i.e., a pointer to a character array. Data type - conversion will be performed for numeric values if the keyword - value does not have the same data type. If the value of the keyword - is undefined (i.e., the value field is blank) then an error status - = VALUE\_UNDEFINED will be returned. - - The second routine returns the keyword value as a character string - (a literal copy of what is in the value field) regardless of the - intrinsic data type of the keyword. The third routine returns - the entire 80-character header record of the keyword, with any - trailing blank characters stripped off. The fourth routine returns - the (next) header record that contains the literal string of characters - specified by the 'string' argument. - - If a NULL comment pointer is supplied then the comment string - will not be returned. \label{ffgky} \label{ffgkey} \label{ffgcrd} -\end{description} - -\begin{verbatim} - int fits_read_key / ffgky - (fitsfile *fptr, int datatype, char *keyname, > DTYPE *value, - char *comment, int *status) - - int fits_read_keyword / ffgkey - (fitsfile *fptr, char *keyname, > char *value, char *comment, - int *status) - - int fits_read_card / ffgcrd - (fitsfile *fptr, char *keyname, > char *card, int *status) - - int fits_read_str / ffgstr - (fitsfile *fptr, char *string, > char *card, int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Read a string-valued keyword and return the string length, the value string, - and/or the comment field. The first routine, ffgksl, simply - returns the length of the character string value of the specified keyword. - The second routine, ffgsky, also returns up to maxchar characters - of the keyword value string, starting with the firstchar character, - and the keyword comment string (unless the input value of comm = NULL). - The valuelen argument returns the total length of the keyword value string - regardless of how much of the string is actually returned (which - depends on the value of the firstchar and maxchar arguments). - Note that the value character string argument must be allocated large enough to - also hold the null terminator at the end of the returned string. These - routines support string keywords that use the CONTINUE convention to - continue long string values over multiple FITS header records. Normally, - string-valued keywords have a maximum length of 68 characters, however, - CONTINUE'd string keywords may be arbitrarily long. \label{ffgksl} \label{ffgsky} -\end{description} - -\begin{verbatim} - int fits_get_key_strlen / ffgksl - (fitsfile *fptr, const char *keyname, int *length, int *status); - - int fits_read_string_key / ffgsky - (fitsfile *fptr, const char *keyname, int firstchar, int maxchar, - char *value, int *valuelen, char *comm, int *status); -\end{verbatim} - -\begin{description} -\item[4 ] Return the nth header record in the CHU. The first keyword - in the header is at keynum = 1; if keynum = 0 then these routines - simply reset the internal CFITSIO pointer to the beginning of the header - so that subsequent keyword operations will start at the top of the - header (e.g., prior to searching for keywords using wild cards in - the keyword name). The first routine returns the entire - 80-character header record (with trailing blanks truncated), - while the second routine parses the record and returns the name, - value, and comment fields as separate (blank truncated) - character strings. If a NULL comment pointer is given on input, - then the comment string will not be - returned. \label{ffgrec} \label{ffgkyn} -\end{description} - -\begin{verbatim} - int fits_read_record / ffgrec - (fitsfile *fptr, int keynum, > char *card, int *status) - - int fits_read_keyn / ffgkyn - (fitsfile *fptr, int keynum, > char *keyname, char *value, - char *comment, int *status) -\end{verbatim} - -\begin{description} -\item[5 ] Return the next keyword whose name matches one of the strings in - 'inclist' but does not match any of the strings in 'exclist'. - The strings in inclist and exclist may contain wild card characters - (*, ?, and \#) as described at the beginning of this section. - This routine searches from the current header position to the - end of the header, only, and does not continue the search from - the top of the header back to the original position. The current - header position may be reset with the ffgrec routine. Note - that nexc may be set = 0 if there are no keywords to be excluded. - This routine returns status = KEY\_NO\_EXIST if a matching - keyword is not found. \label{ffgnxk} -\end{description} - -\begin{verbatim} - int fits_find_nextkey / ffgnxk - (fitsfile *fptr, char **inclist, int ninc, char **exclist, - int nexc, > char *card, int *status) -\end{verbatim} - -\begin{description} -\item[6 ] Return the physical units string from an existing keyword. This - routine uses a local convention, shown in the following example, - in which the keyword units are enclosed in square brackets in the - beginning of the keyword comment field. A null string is returned - if no units are defined for the keyword. \label{ffgunt} -\end{description} - -\begin{verbatim} - VELOCITY= 12.3 / [km/s] orbital speed - - int fits_read_key_unit / ffgunt - (fitsfile *fptr, char *keyname, > char *unit, int *status) -\end{verbatim} - -\begin{description} -\item[7 ] Concatenate the header keywords in the CHDU into a single long - string of characters. This provides a convenient way of passing - all or part of the header information in a FITS HDU to other subroutines. - Each 80-character fixed-length keyword record is appended to the - output character string, in order, with no intervening separator or - terminating characters. The last header record is terminated with - a NULL character. These routine allocates memory for the returned - character array, so the calling program must free the memory when - finished. The cleanest way to do this is to - call the fits\_free\_memory routine. - - There are 2 related routines: fits\_hdr2str simply concatenates all - the existing keywords in the header; fits\_convert\_hdr2str is similar, - except that if the CHDU is a tile compressed image (stored in a binary - table) then it will first convert that header back to that of the corresponding - normal FITS image before concatenating the keywords. - - Selected keywords may be excluded from the returned character string. - If the second parameter (nocomments) is TRUE (nonzero) then any - COMMENT, HISTORY, or blank keywords in the header will not be copied - to the output string. - - The 'exclist' parameter may be used to supply a list of keywords - that are to be excluded from the output character string. Wild card - characters (*, ?, and \#) may be used in the excluded keyword names. - If no additional keywords are to be excluded, then set nexc = 0 and - specify NULL for the the **exclist parameter. \label{ffhdr2str} -\end{description} - -\begin{verbatim} - int fits_hdr2str / ffhdr2str - (fitsfile *fptr, int nocomments, char **exclist, int nexc, - > char **header, int *nkeys, int *status) - - int fits_convert_hdr2str / ffcnvthdr2str - (fitsfile *fptr, int nocomments, char **exclist, int nexc, - > char **header, int *nkeys, int *status) - - int fits_free_memory / fffree - (char *header, > int *status); - -\end{verbatim} - - -\subsection{Keyword Writing Routines} - - -\begin{description} -\item[1 ] Write a keyword of the appropriate data type into the - CHU. The first routine simply appends a new keyword whereas the - second routine will update the value and comment fields of the - keyword if it already exists, otherwise it appends a new - keyword. Note that the address to the value, and not the value - itself, must be entered. The datatype parameter specifies the - data type of the keyword value with one of the following values: - TSTRING, TLOGICAL (== int), TBYTE, TSHORT, TUSHORT, TINT, TUINT, - TLONG, TLONGLONG, TULONG, TFLOAT, TDOUBLE. Within the context of this - routine, TSTRING corresponds to a 'char*' data type, i.e., a pointer - to a character array. A null pointer may be entered for the - comment parameter in which case the keyword comment - field will be unmodified or left blank. \label{ffpky} \label{ffuky} -\end{description} - -\begin{verbatim} - int fits_write_key / ffpky - (fitsfile *fptr, int datatype, char *keyname, DTYPE *value, - char *comment, > int *status) - - int fits_update_key / ffuky - (fitsfile *fptr, int datatype, char *keyname, DTYPE *value, - char *comment, > int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Write a keyword with a null or undefined value (i.e., the - value field in the keyword is left blank). The first routine - simply appends a new keyword whereas the second routine will update - the value and comment fields of the keyword if it already exists, - otherwise it appends a new keyword. A null pointer may be - entered for the comment parameter in which case the keyword - comment - field will be unmodified or left blank. \label{ffpkyu} \label{ffukyu} -\end{description} - -\begin{verbatim} - int fits_write_key_null / ffpkyu - (fitsfile *fptr, char *keyname, char *comment, > int *status) - - int fits_update_key_null / ffukyu - (fitsfile *fptr, char *keyname, char *comment, > int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Write (append) a COMMENT or HISTORY keyword to the CHU. The comment or - history string will be continued over multiple keywords if it is longer - than 70 characters. \label{ffpcom} \label{ffphis} -\end{description} - -\begin{verbatim} - int fits_write_comment / ffpcom - (fitsfile *fptr, char *comment, > int *status) - - int fits_write_history / ffphis - (fitsfile *fptr, char *history, > int *status) -\end{verbatim} - -\begin{description} -\item[4 ] Write the DATE keyword to the CHU. The keyword value will contain - the current system date as a character string in 'yyyy-mm-ddThh:mm:ss' - format. If a DATE keyword already exists in the header, then this - routine will simply update the keyword value with the current date. - \label{ffpdat} -\end{description} - -\begin{verbatim} - int fits_write_date / ffpdat - (fitsfile *fptr, > int *status) -\end{verbatim} - -\begin{description} -\item[5 ]Write a user specified keyword record into the CHU. This is - a low--level routine which can be used to write any arbitrary - record into the header. The record must conform to the all - the FITS format requirements. \label{ffprec} -\end{description} - -\begin{verbatim} - int fits_write_record / ffprec - (fitsfile *fptr, char *card, > int *status) -\end{verbatim} - -\begin{description} -\item[6 ]Update an 80-character record in the CHU. If a keyword with the input - name already exists, then it is overwritten by the value of card. This - could modify the keyword name as well as the value and comment fields. - If the keyword doesn't already exist then a new keyword card is appended - to the header. \label{ffucrd} -\end{description} - -\begin{verbatim} - int fits_update_card / ffucrd - (fitsfile *fptr, char *keyname, char *card, > int *status) -\end{verbatim} - - -\begin{description} -\item[7 ] Modify (overwrite) the comment field of an existing keyword. \label{ffmcom} -\end{description} - -\begin{verbatim} - int fits_modify_comment / ffmcom - (fitsfile *fptr, char *keyname, char *comment, > int *status) -\end{verbatim} - - -\begin{description} -\item[8 ] Write the physical units string into an existing keyword. This - routine uses a local convention, shown in the following example, - in which the keyword units are enclosed in square brackets in the - beginning of the keyword comment field. \label{ffpunt} -\end{description} - -\begin{verbatim} - VELOCITY= 12.3 / [km/s] orbital speed - - int fits_write_key_unit / ffpunt - (fitsfile *fptr, char *keyname, char *unit, > int *status) -\end{verbatim} - -\begin{description} -\item[9 ] Rename an existing keyword, preserving the current value - and comment fields. \label{ffmnam} -\end{description} - -\begin{verbatim} - int fits_modify_name / ffmnam - (fitsfile *fptr, char *oldname, char *newname, > int *status) -\end{verbatim} - -\begin{description} -\item[10] Delete a keyword record. The space occupied by - the keyword is reclaimed by moving all the following header records up - one row in the header. The first routine deletes a keyword at a - specified position in the header (the first keyword is at position 1), - whereas the second routine deletes a specifically named keyword. - Wild card characters may be used when specifying the name of the keyword - to be deleted. The third routine deletes the (next) keyword that contains - the literal character string specified by the 'string' - argument.\label{ffdrec} \label{ffdkey} -\end{description} - -\begin{verbatim} - int fits_delete_record / ffdrec - (fitsfile *fptr, int keynum, > int *status) - - int fits_delete_key / ffdkey - (fitsfile *fptr, char *keyname, > int *status) - - int fits_delete_str / ffdstr - (fitsfile *fptr, char *string, > int *status) -\end{verbatim} - -\section{Primary Array or IMAGE Extension I/O Routines} - -These routines read or write data values in the primary data array (i.e., -the first HDU in a FITS file) or an IMAGE extension. There are also -routines to get information about the data type and size of the image. -Users should also read the following chapter on the CFITSIO iterator -function which provides a more `object oriented' method of reading and -writing images. The iterator function is a little more complicated to -use, but the advantages are that it usually takes less code to perform -the same operation, and the resulting program often runs faster because -the FITS files are read and written using the most efficient block size. - -C programmers should note that the ordering of arrays in FITS files, and -hence in all the CFITSIO calls, is more similar to the dimensionality -of arrays in Fortran rather than C. For instance if a FITS image has -NAXIS1 = 100 and NAXIS2 = 50, then a 2-D array just large enough to hold -the image should be declared as array[50][100] and not as array[100][50]. - -The `datatype' parameter specifies the data type of the `nulval' and -`array' pointers and can have one of the following values: TBYTE, -TSBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TLONGLONG, TULONG, TFLOAT, -TDOUBLE. Automatic data type conversion is performed if the data type -of the FITS array (as defined by the BITPIX keyword) differs from that -specified by 'datatype'. The data values are also automatically scaled -by the BSCALE and BZERO keyword values as they are being read or written -in the FITS array. - - -\begin{description} -\item[1 ] Get the data type or equivalent data type of the image. The - first routine returns the physical data type of the FITS image, as - given by the BITPIX keyword, with allowed values of BYTE\_IMG (8), - SHORT\_IMG (16), LONG\_IMG (32), LONGLONG\_IMG (64), - FLOAT\_IMG (-32), and DOUBLE\_IMG - (-64). - The second routine is similar, except that if the image pixel - values are scaled, with non-default values for the BZERO and BSCALE - keywords, then the routine will return the 'equivalent' data type - that is needed to store the scaled values. For example, if BITPIX - = 16 and BSCALE = 0.1 then the equivalent data type is FLOAT\_IMG. - Similarly if BITPIX = 16, BSCALE = 1, and BZERO = 32768, then the - the pixel values span the range of an unsigned short integer and - the returned data type will be USHORT\_IMG. \label{ffgidt} -\end{description} - -\begin{verbatim} - int fits_get_img_type / ffgidt - (fitsfile *fptr, > int *bitpix, int *status) - - int fits_get_img_equivtype / ffgiet - (fitsfile *fptr, > int *bitpix, int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Get the number of dimensions, and/or the size of - each dimension in the image . The number of axes in the image is - given by naxis, and the size of each dimension is given by the - naxes array (a maximum of maxdim dimensions will be returned). - \label{ffgidm} \label{ffgisz} \label{ffgipr} -\end{description} - -\begin{verbatim} - int fits_get_img_dim / ffgidm - (fitsfile *fptr, > int *naxis, int *status) - - int fits_get_img_size / ffgisz - (fitsfile *fptr, int maxdim, > long *naxes, int *status) - - int fits_get_img_sizell / ffgiszll - (fitsfile *fptr, int maxdim, > LONGLONG *naxes, int *status) - - int fits_get_img_param / ffgipr - (fitsfile *fptr, int maxdim, > int *bitpix, int *naxis, long *naxes, - int *status) - - int fits_get_img_paramll / ffgiprll - (fitsfile *fptr, int maxdim, > int *bitpix, int *naxis, LONGLONG *naxes, - int *status) -\end{verbatim} - -\begin{description} -\item[3 ]Create a new primary array or IMAGE extension with a specified - data type and size. If the FITS file is currently empty then a - primary array is created, otherwise a new IMAGE extension is - appended to the file. \label{ffcrim} -\end{description} - -\begin{verbatim} - int fits_create_img / ffcrim - ( fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) - - int fits_create_imgll / ffcrimll - ( fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) -\end{verbatim} - -\begin{description} -\item[4 ] Copy an n-dimensional image in a particular row and column of a - binary table (in a vector column) - to or from a primary array or image extension. - - The 'cell2image' routine - will append a new image extension (or primary array) to the output file. - Any WCS keywords associated with the input column image will be translated - into the appropriate form for an image extension. Any other keywords - in the table header that are not specifically related to defining the - binary table structure or to other columns in the table - will also be copied to the header of the output image. - - The 'image2cell' routine will copy the input image into the specified row - and column of the current binary table in the output file. The binary table - HDU must exist before calling this routine, but it - may be empty, with no rows or columns of data. The specified column - (and row) will be created if it does not already exist. The 'copykeyflag' - parameter controls which keywords are copied from the input - image to the header of the output table: 0 = no keywords will be copied, - 1 = all keywords will be copied (except those keywords that would be invalid in - the table header), and 2 = copy only the WCS keywords. \label{copycell} -\end{description} - -\begin{verbatim} - int fits_copy_cell2image - (fitsfile *infptr, fitsfile *outfptr, char *colname, long rownum, - > int *status) - - int fits_copy_image2cell - (fitsfile *infptr, fitsfile *outfptr, char *colname, long rownum, - int copykeyflag > int *status) -\end{verbatim} - - -\begin{description} -\item[5 ] Write a rectangular subimage (or the whole image) to the FITS data - array. The fpixel and lpixel arrays give the coordinates of the - first (lower left corner) and last (upper right corner) pixels in - FITS image to be written to. \label{ffpss} -\end{description} - -\begin{verbatim} - int fits_write_subset / ffpss - (fitsfile *fptr, int datatype, long *fpixel, long *lpixel, - DTYPE *array, > int *status) -\end{verbatim} - -\begin{description} -\item[6 ] Write pixels into the FITS data array. 'fpixel' is an array of - length NAXIS which gives the coordinate of the starting pixel to be - written to, such that fpixel[0] is in the range 1 to NAXIS1, - fpixel[1] is in the range 1 to NAXIS2, etc. The first pair of routines - simply writes the array of pixels to the FITS file (doing data type - conversion if necessary) whereas the second routines will substitute - the appropriate FITS null value for any elements which are equal to - the input value of nulval (note that this parameter gives the - address of the null value, not the null value itself). For integer - FITS arrays, the FITS null value is defined by the BLANK keyword (an - error is returned if the BLANK keyword doesn't exist). For floating - point FITS arrays the special IEEE NaN (Not-a-Number) value will be - written into the FITS file. If a null pointer is entered for - nulval, then the null value is ignored and this routine behaves - the same as fits\_write\_pix. \label{ffppx} \label{ffppxn} -\end{description} - -\begin{verbatim} - int fits_write_pix / ffppx - (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, - DTYPE *array, int *status); - - int fits_write_pixll / ffppxll - (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, - DTYPE *array, int *status); - - int fits_write_pixnull / ffppxn - (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, - DTYPE *array, DTYPE *nulval, > int *status); - - int fits_write_pixnullll / ffppxnll - (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, - DTYPE *array, DTYPE *nulval, > int *status); -\end{verbatim} - -\begin{description} -\item[7 ] Set FITS data array elements equal to the appropriate null pixel - value. For integer FITS arrays, the FITS null value is defined by - the BLANK keyword (an error is returned if the BLANK keyword - doesn't exist). For floating point FITS arrays the special IEEE NaN - (Not-a-Number) value will be written into the FITS file. Note that - 'firstelem' is a scalar giving the offset to the first pixel to be - written in the equivalent 1-dimensional array of image pixels. \label{ffpprn} -\end{description} - -\begin{verbatim} - int fits_write_null_img / ffpprn - (fitsfile *fptr, LONGLONG firstelem, LONGLONG nelements, > int *status) -\end{verbatim} - -\begin{description} -\item[8 ] Read a rectangular subimage (or the whole image) from the FITS - data array. The fpixel and lpixel arrays give the coordinates of - the first (lower left corner) and last (upper right corner) pixels - to be read from the FITS image. Undefined FITS array elements will - be returned with a value = *nullval, (note that this parameter - gives the address of the null value, not the null value itself) - unless nulval = 0 or *nulval = 0, in which case no checks for - undefined pixels will be performed. \label{ffgsv} -\end{description} - -\begin{verbatim} - int fits_read_subset / ffgsv - (fitsfile *fptr, int datatype, long *fpixel, long *lpixel, long *inc, - DTYPE *nulval, > DTYPE *array, int *anynul, int *status) -\end{verbatim} - -\begin{description} -\item[9 ] Read pixels from the FITS data array. 'fpixel' is the starting - pixel location and is an array of length NAXIS such that fpixel[0] - is in the range 1 to NAXIS1, fpixel[1] is in the range 1 to NAXIS2, - etc. The nelements parameter specifies the number of pixels to - read. If fpixel is set to the first pixel, and nelements is set - equal to the NAXIS1 value, then this routine would read the first - row of the image. Alternatively, if nelements is set equal to - NAXIS1 * NAXIS2 then it would read an entire 2D image, or the first - plane of a 3-D datacube. - - The first 2 routines will return any undefined pixels in the FITS array - equal to the value of *nullval (note that this parameter gives the - address of the null value, not the null value itself) unless nulval - = 0 or *nulval = 0, in which case no checks for undefined pixels - will be performed. The second 2 routines are similar except that any - undefined pixels will have the corresponding nullarray element set - equal to TRUE (= 1). \label{ffgpxv} \label{ffgpxf} -\end{description} - -\begin{verbatim} - int fits_read_pix / ffgpxv - (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, - DTYPE *nulval, > DTYPE *array, int *anynul, int *status) - - int fits_read_pixll / ffgpxvll - (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, - DTYPE *nulval, > DTYPE *array, int *anynul, int *status) - - int fits_read_pixnull / ffgpxf - (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, - > DTYPE *array, char *nullarray, int *anynul, int *status) - - int fits_read_pixnullll / ffgpxfll - (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, - > DTYPE *array, char *nullarray, int *anynul, int *status) -\end{verbatim} - -\begin{description} -\item[10] Copy a rectangular section of an image and write it to a new - FITS primary image or image extension. The new image HDU is appended - to the end of the output file; all the keywords in the input image - will be copied to the output image. The common WCS keywords will - be updated if necessary to correspond to the coordinates of the section. - The format of the section expression is - same as specifying an image section using the extended file name - syntax (see "Image Section" in Chapter 10). - (Examples: "1:100,1:200", "1:100:2, 1:*:2", "*, -*"). - \label{ffcpimg} -\end{description} - -\begin{verbatim} - int fits_copy_image_section / ffcpimg - (fitsfile *infptr, fitsfile *outfptr, char *section, int *status) -\end{verbatim} - - -\section{Image Compression} - -CFITSIO transparently supports the 2 methods of image compression described -below. - -1) The entire FITS file may be externally compressed with the gzip or Unix -compress utility programs, producing a *.gz or *.Z file, respectively. When reading -compressed files of this type, CFITSIO first uncompresses the entire file -into memory before performing the requested read operations. Output files -can be directly written in the gzip compressed format if the user-specified -filename ends with `.gz'. In this case, CFITSIO initially writes the -uncompressed file in memory and then compresses it and writes it to disk -when the FITS file is closed, thus saving user disk space. Read and write -access to these compressed FITS files is generally quite fast since all the -I/O is performed in memory; the main limitation with this technique is that -there must be enough available memory (or swap space) to hold the entire -uncompressed FITS file. - -2) CFITSIO also supports the FITS tiled image compression convention in -which the image is subdivided into a grid of rectangular tiles, and each -tile of pixels is individually compressed. The details of this FITS -compression convention are described at the FITS Support Office web site at -http://fits.gsfc.nasa.gov/fits\_registry.html, and in the fpackguide pdf file -that is included with the CFITSIO source file distributions Basically, the compressed -image tiles are stored in rows of a variable length array column in a FITS -binary table, however CFITSIO recognizes that this binary table extension -contains an image and treats it as if it were an IMAGE extension. This -tile-compressed format is especially well suited for compressing very large -images because a) the FITS header keywords remain uncompressed for rapid -read access, and because b) it is possible to extract and uncompress -sections of the image without having to uncompress the entire image. This -format is also much more effective in compressing floating point images -than simply compressing the image using gzip or compress because it -approximates the floating point values with scaled integers which can then -be compressed more efficiently. - -Currently CFITSIO supports 3 general purpose compression algorithms plus -one other special-purpose compression technique that is designed for data -masks with positive integer pixel values. The 3 general purpose algorithms -are GZIP, Rice, and HCOMPRESS, and the special purpose algorithm is the -IRAF pixel list compression technique (PLIO). There are 2 variants of the GZIP -algorithm: GZIP\_1 compresses the array of image pixel value normally with the -GZIP algorithm, while GZIP\_2 first shuffles the bytes in all the pixel -values so that the most-significant byte of every pixel appears first, followed -by the less significant bytes in sequence. GZIP\_2 may be more effective -in cases where the most significant byte in most of the image pixel values -contains the same bit pattern. In principle, any number of -other compression algorithms could also be supported by the FITS tiled -image compression convention. - -The FITS image can be subdivided into any desired rectangular grid of -compression tiles. With the GZIP, Rice, and PLIO algorithms, the default -is to take each row of the image as a tile. The HCOMPRESS algorithm is -inherently 2-dimensional in nature, so the default in this case is to take -16 rows of the image per tile. In most cases it makes little difference what -tiling pattern is used, so the default tiles are usually adequate. In the -case of very small images, it could be more efficient to compress the whole -image as a single tile. Note that the image dimensions are not required to -be an integer multiple of the tile dimensions; if not, then the tiles at the -edges of the image will be smaller than the other tiles. - -The 4 supported image compression algorithms are all 'loss-less' when -applied to integer FITS images; the pixel values are preserved exactly with -no loss of information during the compression and uncompression process. In -addition, the HCOMPRESS algorithm supports a 'lossy' compression mode that -will produce -larger amount of image compression. This is achieved by specifying a non-zero -value for the HCOMPRESS ``scale'' -parameter. Since the amount of compression that is achieved depends directly -on the RMS noise in the image, it is usually more convention -to specify the HCOMPRESS scale factor relative to the RMS noise. -Setting s = 2.5 means use a scale factor that is 2.5 times the calculated RMS noise -in the image tile. In some cases -it may be desirable to specify the exact scaling to be used, -instead of specifying it relative to the calculated noise value. This may -be done by specifying the negative of desired scale value (typically -in the range -2 to -100). - -Very high compression factors (of 100 or more) can be -achieved by using large HCOMPRESS scale values, however, this can produce undesirable -``blocky'' artifacts in the compressed image. A variation of the HCOMPRESS -algorithm (called HSCOMPRESS) can be used in this case to apply a small -amount of smoothing of the image when it is uncompressed to help cover up -these artifacts. This smoothing is purely cosmetic and does not cause any -significant change to the image pixel values. - -Floating point FITS images (which have BITPIX = -32 or -64) usually contain -too much ``noise'' in the least significant bits of the mantissa of the -pixel values to be effectively compressed with any lossless algorithm. -Consequently, floating point images are first quantized into scaled integer -pixel values (and thus throwing away much of the noise) before being -compressed with the specified algorithm (either GZIP, Rice, or HCOMPRESS). -This technique produces much higher compression factors than -simply using the GZIP utility to externally compress the whole FITS file, but it also -means that the original floating value pixel values are not exactly -preserved. When done properly, this integer scaling technique will only -discard the insignificant noise while still preserving all the real -information in the image. The amount of precision that is retained in the -pixel values is controlled by the "quantization level" parameter, q. Larger -values of q will result in compressed images whose pixels more closely match -the floating point pixel values, but at the same time the amount of -compression that is achieved will be reduced. Users should experiment with -different values for this parameter to determine the optimal value that -preserves all the useful information in the image, without needlessly -preserving all the ``noise'' which will hurt the compression efficiency. - -The default value for the quantization scale factor is 4.0, which means that -scaled integer pixel values will be quantized such that the difference -between adjacent integer values will be 1/4th of the noise level in the -image background. CFITSIO uses an optimized algorithm to accurately estimate -the noise in the image. As an example, if the RMS noise in the background -pixels of an image = 32.0, then the spacing between adjacent scaled -integer pixel values will equal 8.0 by default. Note that the RMS noise is -independently calculated for each tile of the image, so the resulting -integer scaling factor may fluctuate slightly for each tile. In some cases -it may be desirable to specify the exact quantization level to be used, -instead of specifying it relative to the calculated noise value. This may -be done by specifying the negative of desired quantization level for the -value of q. In the previous example, one could specify q = -8.0 so that the -quantized integer levels differ by exactly 8.0. Larger negative values for q means -that the levels are more coarsely spaced, and will produce higher -compression factors. - -When floating point images are being quantized, one must also specify what -quantization method is to be used. The default algorithm is called -``SUBTRACTIVE\_DITHER\_1''. A second variation called ``SUBTRACTIVE\_DITHER\_2'' -is also available, which does the same thing except that any pixels with a -value of 0.0 are not dithered and instead the zero values are exactly -preserved in the compressed image. One may also turn off dithering -completely with the ``NO\_DITHER'' option, but this is not recommended -because it can cause larger systematic errors in measurements of the -position or brightness of objects in the compressed image. - -There are 3 methods for specifying all the parameters needed to write a FITS -image in the tile compressed format. The parameters may either be specified -at run time as part of the file name of the output compressed FITS file, or -the writing program may call a set of helper CFITSIO subroutines that are provided -for specifying the parameter values, or ``compression directive'' keywords -may be added to the header of each image HDU to specify the compression parameters. -These 3 methods are described below. - -1) At run time, when specifying the name of the output FITS file to be -created, the user can indicate that images should be -written in tile-compressed format by enclosing the compression -parameters in square brackets following the root disk file name -in the following format: - -\begin{verbatim} - [compress NAME T1,T2; q[z] QLEVEL, s HSCALE] -\end{verbatim} -where - -\begin{verbatim} - NAME = algorithm name: GZIP, Rice, HCOMPRESS, HSCOMPRSS or PLIO - may be abbreviated to the first letter (or HS for HSCOMPRESS) - T1,T2 = tile dimension (e.g. 100,100 for square tiles 100 pixels wide) - QLEVEL = quantization level for floating point FITS images - HSCALE = HCOMPRESS scale factor; default = 0 which is lossless. -\end{verbatim} - -Here are a few examples of this extended syntax: - - -\begin{verbatim} - myfile.fit[compress] - use the default compression algorithm (Rice) - and the default tile size (row by row) - - myfile.fit[compress G] - use the specified compression algorithm; - myfile.fit[compress R] only the first letter of the algorithm - myfile.fit[compress P] should be given. - myfile.fit[compress H] - - myfile.fit[compress R 100,100] - use Rice and 100 x 100 pixel tiles - - myfile.fit[compress R; q 10.0] - quantization level = (RMS-noise) / 10. - myfile.fit[compress R; qz 10.0] - quantization level = (RMS-noise) / 10. - also use the SUBTRACTIVE_DITHER_2 quantization method - myfile.fit[compress HS; s 2.0] - HSCOMPRESS (with smoothing) - and scale = 2.0 * RMS-noise -\end{verbatim} - -2) Before calling the CFITSIO routine to write the image header -keywords (e.g., fits\_create\_image) the programmer can call the -routines described below to specify the compression algorithm and the -tiling pattern that is to be used. There are routines for specifying -the various compression parameters and similar routines to -return the current values of the parameters: -\label{ffsetcomp} \label{ffgetcomp} - -\begin{verbatim} - int fits_set_compression_type(fitsfile *fptr, int comptype, int *status) - int fits_set_tile_dim(fitsfile *fptr, int ndim, long *tilesize, int *status) - int fits_set_quantize_level(fitsfile *fptr, float qlevel, int *status) - int fits_set_quantize_method(fitsfile *fptr, int method, int *status) - int fits_set_quantize_dither(fitsfile *fptr, int dither, int *status) - int fits_set_dither_seed(fitsfile *fptr, int seed, int *status) - int fits_set_dither_offset(fitsfile *fptr, int offset, int *status) - int fits_set_lossy_int(fitsfile *fptr, int lossy_int, int *status) - this forces integer image to be converted to floats, then quantized - int fits_set_huge_hdu(fitsfile *fptr, int huge, int *status); - this should be called when the compressed image size is more than 4 GB. - int fits_set_hcomp_scale(fitsfile *fptr, float scale, int *status) - int fits_set_hcomp_smooth(fitsfile *fptr, int smooth, int *status) - Set smooth = 1 to apply smoothing when uncompressing the image - - int fits_get_compression_type(fitsfile *fptr, int *comptype, int *status) - int fits_get_tile_dim(fitsfile *fptr, int ndim, long *tilesize, int *status) - int fits_get_quantize_level(fitsfile *fptr, float *level, int *status) - int fits_get_hcomp_scale(fitsfile *fptr, float *scale, int *status) -\end{verbatim} -Several symbolic constants are defined for use as the value of the -`comptype' parameter: GZIP\_1, GZIP\_2, RICE\_1, HCOMPRESS\_1 or PLIO\_1. -Entering NULL for comptype will turn off the tile-compression and cause normal FITS -images to be written. - -There are also defined symbolic constants for the quantization method: -``SUBTRACTIVE\_DITHER\_1'', ``SUBTRACTIVE\_DITHER\_2'', and ``NO\_DITHER''. - -3) CFITSIO will uses the values of the following keywords, if they are present -in the header of the image HDU, -to determine how to compress that HDU. These keywords override any compression parameters -that were specified with the previous 2 methods. - -\begin{verbatim} - FZALGOR - 'RICE_1' , 'GZIP_1', 'GZIP_2', 'HCOMPRESS_1', 'PLIO_1', 'NONE' - FZTILE - 'ROW', 'WHOLE', or '(n,m)' - FZQVALUE - float value (default = 4.0) - FZQMETHD - 'SUBTRACTIVE_DITHER_1', 'SUBTRACTIVE_DITHER_2', 'NO_DITHER' - FZDTHRSD - 'CLOCK', 'CHECKSUM', 1 - 10000 - FZINT2F - T, or F: Convert integers to floats, then quantize? - FZHSCALE - float value (default = 0). Hcompress scale value. -\end{verbatim} - -No special action is required by software when read tile-compressed images because -all the CFITSIO routines that read normal uncompressed FITS images also -transparently read images in the tile-compressed format; CFITSIO essentially -treats the binary table that contains the compressed tiles as if -it were an IMAGE extension. - - -The following 2 routines are available for compressing or -or decompressing an image: - -\begin{verbatim} - int fits_img_compress(fitsfile *infptr, fitsfile *outfptr, int *status); - int fits_img_decompress (fitsfile *infptr, fitsfile *outfptr, int *status); -\end{verbatim} -Before calling the compression routine, the compression parameters must -first be defined in one of the 3 way described in the previous paragraphs. -There is also a routine to determine if the current HDU contains -a tile compressed image (it returns 1 or 0): - -\begin{verbatim} - int fits_is_compressed_image(fitsfile *fptr, int *status); -\end{verbatim} -A small example program called 'imcopy' is included with CFITSIO that -can be used to compress (or uncompress) any FITS image. This -program can be used to experiment with the various compression options -on existing FITS images as shown in these examples: - -\begin{verbatim} -1) imcopy infile.fit 'outfile.fit[compress]' - - This will use the default compression algorithm (Rice) and the - default tile size (row by row) - -2) imcopy infile.fit 'outfile.fit[compress GZIP]' - - This will use the GZIP compression algorithm and the default - tile size (row by row). The allowed compression algorithms are - Rice, GZIP, and PLIO. Only the first letter of the algorithm - name needs to be specified. - -3) imcopy infile.fit 'outfile.fit[compress G 100,100]' - - This will use the GZIP compression algorithm and 100 X 100 pixel - tiles. - -4) imcopy infile.fit 'outfile.fit[compress R 100,100; qz 10.0]' - - This will use the Rice compression algorithm, 100 X 100 pixel - tiles, and quantization level = RMSnoise / 10.0 (assuming the - input image has a floating point data type). By specifying - qz instead of q, this means use the subtractive dither2 - quantization method. - -5) imcopy infile.fit outfile.fit - - If the input file is in tile-compressed format, then it will be - uncompressed to the output file. Otherwise, it simply copies - the input image to the output image. - -6) imcopy 'infile.fit[1001:1500,2001:2500]' outfile.fit - - This extracts a 500 X 500 pixel section of the much larger - input image (which may be in tile-compressed format). The - output is a normal uncompressed FITS image. - -7) imcopy 'infile.fit[1001:1500,2001:2500]' outfile.fit.gz - - Same as above, except the output file is externally compressed - using the gzip algorithm. - -\end{verbatim} - -\section{ASCII and Binary Table Routines} - -These routines perform read and write operations on columns of data in -FITS ASCII or Binary tables. Note that in the following discussions, -the first row and column in a table is at position 1 not 0. - -Users should also read the following chapter on the CFITSIO iterator -function which provides a more `object oriented' method of reading and -writing table columns. The iterator function is a little more -complicated to use, but the advantages are that it usually takes less -code to perform the same operation, and the resulting program often -runs faster because the FITS files are read and written using the most -efficient block size. - - -\subsection{Create New Table} - - -\begin{description} -\item[1 ]Create a new ASCII or bintable table extension. If - the FITS file is currently empty then a dummy primary array will be - created before appending the table extension to it. The tbltype - parameter defines the type of table and can have values of - ASCII\_TBL or BINARY\_TBL. The naxis2 parameter gives the initial - number of rows to be created in the table, and should normally be - set = 0. CFITSIO will automatically increase the size of the table - as additional rows are written. A non-zero number of rows may be - specified to reserve space for that many rows, even if a fewer - number of rows will be written. The tunit and extname parameters - are optional and a null pointer may be given if they are not - defined. The FITS Standard recommends that only letters, digits, - and the underscore character be used in column names (the ttype - parameter) with no embedded spaces. Trailing blank characters are - not significant. \label{ffcrtb} -\end{description} - -\begin{verbatim} - int fits_create_tbl / ffcrtb - (fitsfile *fptr, int tbltype, LONGLONG naxis2, int tfields, char *ttype[], - char *tform[], char *tunit[], char *extname, int *status) -\end{verbatim} - -\subsection{Column Information Routines} - - -\begin{description} -\item[1 ] Get the number of rows or columns in the current FITS table. - The number of rows is given by the NAXIS2 keyword and the - number of columns is given by the TFIELDS keyword in the header - of the table. \label{ffgnrw} -\end{description} - -\begin{verbatim} - int fits_get_num_rows / ffgnrw - (fitsfile *fptr, > long *nrows, int *status); - - int fits_get_num_rowsll / ffgnrwll - (fitsfile *fptr, > LONGLONG *nrows, int *status); - - int fits_get_num_cols / ffgncl - (fitsfile *fptr, > int *ncols, int *status); -\end{verbatim} - - -\begin{description} -\item[2 ] Get the table column number (and name) of the column whose name -matches an input template name. If casesen = CASESEN then the column -name match will be case-sensitive, whereas if casesen = CASEINSEN then -the case will be ignored. As a general rule, the column names should -be treated as case INsensitive. - -The input column name template may be either the exact name of the -column to be searched for, or it may contain wild card characters (*, -?, or \#), or it may contain the integer number of the desired column -(with the first column = 1). The `*' wild card character matches any -sequence of characters (including zero characters) and the `?' -character matches any single character. The \# wildcard will match any -consecutive string of decimal digits (0-9). If more than one column -name in the table matches the template string, then the first match is -returned and the status value will be set to COL\_NOT\_UNIQUE as a -warning that a unique match was not found. To find the other cases -that match the template, call the routine again leaving the input -status value equal to COL\_NOT\_UNIQUE and the next matching name will -then be returned. Repeat this process until a status = -COL\_NOT\_FOUND is returned. - -The FITS Standard recommends that only letters, digits, and the -underscore character be used in column names (with no embedded -spaces). Trailing blank characters are not significant. - \label{ffgcno} \label{ffgcnn} -\end{description} - -\begin{verbatim} - int fits_get_colnum / ffgcno - (fitsfile *fptr, int casesen, char *templt, > int *colnum, - int *status) - - int fits_get_colname / ffgcnn - (fitsfile *fptr, int casesen, char *templt, > char *colname, - int *colnum, int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Return the data type, vector repeat value, and the width in bytes - of a column in an ASCII or binary table. Allowed values for the - data type in ASCII tables are: TSTRING, TSHORT, TLONG, TFLOAT, and - TDOUBLE. Binary tables also support these types: TLOGICAL, TBIT, - TBYTE, TCOMPLEX and TDBLCOMPLEX. The negative of the data type code - value is returned if it is a variable length array column. Note - that in the case of a 'J' 32-bit integer binary table column, this - routine will return data type = TINT32BIT (which in fact is - equivalent to TLONG). With most current C compilers, a value in a - 'J' column has the same size as an 'int' variable, and may not be - equivalent to a 'long' variable, which is 64-bits long on an - increasing number of compilers. - - The 'repeat' parameter returns the vector repeat count on the binary - table TFORMn keyword value. (ASCII table columns always have repeat - = 1). The 'width' parameter returns the width in bytes of a single - column element (e.g., a '10D' binary table column will have width = - 8, an ASCII table 'F12.2' column will have width = 12, and a binary - table'60A' character string column will have width = 60); Note that - CFITSIO supports the local convention for specifying arrays of - fixed length strings within a binary table character column using - the syntax TFORM = 'rAw' where 'r' is the total number of characters - (= the width of the column) and 'w' is the width of a unit string - within the column. Thus if the column has TFORM = '60A12' then this - means that each row of the table contains 5 12-character substrings - within the 60-character field, and thus in this case this routine will - return typecode = TSTRING, repeat = 60, and width = 12. (The TDIMn - keyword may also be used to specify the unit string length; The pair - of keywords TFORMn = '60A' and TDIMn = '(12,5)' would have the - same effect as TFORMn = '60A12'). The number - of substrings in any binary table character string field can be - calculated by (repeat/width). A null pointer may be given for any of - the output parameters that are not needed. - - The second routine, fit\_get\_eqcoltype is similar except that in - the case of scaled integer columns it returns the 'equivalent' data - type that is needed to store the scaled values, and not necessarily - the physical data type of the unscaled values as stored in the FITS - table. For example if a '1I' column in a binary table has TSCALn = - 1 and TZEROn = 32768, then this column effectively contains unsigned - short integer values, and thus the returned value of typecode will - be TUSHORT, not TSHORT. Similarly, if a column has TTYPEn = '1I' - and TSCALn = 0.12, then the returned typecode - will be TFLOAT. \label{ffgtcl} -\end{description} - -\begin{verbatim} - int fits_get_coltype / ffgtcl - (fitsfile *fptr, int colnum, > int *typecode, long *repeat, - long *width, int *status) - - int fits_get_coltypell / ffgtclll - (fitsfile *fptr, int colnum, > int *typecode, LONGLONG *repeat, - LONGLONG *width, int *status) - - int fits_get_eqcoltype / ffeqty - (fitsfile *fptr, int colnum, > int *typecode, long *repeat, - long *width, int *status) - - int fits_get_eqcoltypell / ffeqtyll - (fitsfile *fptr, int colnum, > int *typecode, LONGLONG *repeat, - LONGLONG *width, int *status) -\end{verbatim} - -\begin{description} -\item[4 ] Return the display width of a column. This is the length - of the string that will be returned by the fits\_read\_col routine - when reading the column as a formatted string. The display width is - determined by the TDISPn keyword, if present, otherwise by the data - type of the column. \label{ffgcdw} -\end{description} - -\begin{verbatim} - int fits_get_col_display_width / ffgcdw - (fitsfile *fptr, int colnum, > int *dispwidth, int *status) -\end{verbatim} - - -\begin{description} -\item[5 ] Return the number of and size of the dimensions of a table column in - a binary table. Normally this information is given by the TDIMn keyword, - but if this keyword is not present then this routine returns naxis = 1 - and naxes[0] equal to the repeat count in the TFORM keyword. \label{ffgtdm} -\end{description} - -\begin{verbatim} - int fits_read_tdim / ffgtdm - (fitsfile *fptr, int colnum, int maxdim, > int *naxis, - long *naxes, int *status) - - int fits_read_tdimll / ffgtdmll - (fitsfile *fptr, int colnum, int maxdim, > int *naxis, - LONGLONG *naxes, int *status) -\end{verbatim} - -\begin{description} -\item[6 ] Decode the input TDIMn keyword string (e.g. '(100,200)') and return the - number of and size of the dimensions of a binary table column. If the input - tdimstr character string is null, then this routine returns naxis = 1 - and naxes[0] equal to the repeat count in the TFORM keyword. This routine - is called by fits\_read\_tdim. \label{ffdtdm} -\end{description} - -\begin{verbatim} - int fits_decode_tdim / ffdtdm - (fitsfile *fptr, char *tdimstr, int colnum, int maxdim, > int *naxis, - long *naxes, int *status) - - int fits_decode_tdimll / ffdtdmll - (fitsfile *fptr, char *tdimstr, int colnum, int maxdim, > int *naxis, - LONGLONG *naxes, int *status) -\end{verbatim} - -\begin{description} -\item[7 ] Write a TDIMn keyword whose value has the form '(l,m,n...)' - where l, m, n... are the dimensions of a multidimensional array - column in a binary table. \label{ffptdm} -\end{description} - -\begin{verbatim} - int fits_write_tdim / ffptdm - (fitsfile *fptr, int colnum, int naxis, long *naxes, > int *status) - - int fits_write_tdimll / ffptdmll - (fitsfile *fptr, int colnum, int naxis, LONGLONG *naxes, > int *status) -\end{verbatim} - - -\subsection{Routines to Edit Rows or Columns} - - -\begin{description} -\item[1 ] Insert or delete rows in an ASCII or binary table. When inserting rows - all the rows following row FROW are shifted down by NROWS rows; if - FROW = 0 then the blank rows are inserted at the beginning of the - table. Note that it is *not* necessary to insert rows in a table before - writing data to those rows (indeed, it would be inefficient to do so). - Instead one may simply write data to any row of the table, whether that - row of data already exists or not. - - The first delete routine deletes NROWS consecutive rows - starting with row FIRSTROW. The second delete routine takes an - input string that lists the rows or row ranges (e.g., - '5-10,12,20-30'), whereas the third delete routine takes an input - integer array that specifies each individual row to be deleted. In - both latter cases, the input list of rows to delete must be sorted - in ascending order. These routines update the NAXIS2 keyword to - reflect the new number of rows in the - table. \label{ffirow} \label{ffdrow} \label{ffdrws} \label{ffdrrg} -\end{description} - -\begin{verbatim} - int fits_insert_rows / ffirow - (fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, > int *status) - - int fits_delete_rows / ffdrow - (fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, > int *status) - - int fits_delete_rowrange / ffdrrg - (fitsfile *fptr, char *rangelist, > int *status) - - int fits_delete_rowlist / ffdrws - (fitsfile *fptr, long *rowlist, long nrows, > int *status) - - int fits_delete_rowlistll / ffdrwsll - (fitsfile *fptr, LONGLONG *rowlist, LONGLONG nrows, > int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Insert or delete column(s) in an ASCII or binary - table. When inserting, COLNUM specifies the column number that the - (first) new column should occupy in the table. NCOLS specifies how - many columns are to be inserted. Any existing columns from this - position and higher are shifted over to allow room for the new - column(s). The index number on all the following keywords will be - incremented or decremented if necessary to reflect the new position - of the column(s) in the table: TBCOLn, TFORMn, TTYPEn, TUNITn, - TNULLn, TSCALn, TZEROn, TDISPn, TDIMn, TLMINn, TLMAXn, TDMINn, - TDMAXn, TCTYPn, TCRPXn, TCRVLn, TCDLTn, TCROTn, - and TCUNIn. \label{fficol} \label{fficls} \label{ffdcol} -\end{description} - -\begin{verbatim} - int fits_insert_col / fficol - (fitsfile *fptr, int colnum, char *ttype, char *tform, - > int *status) - - int fits_insert_cols / fficls - (fitsfile *fptr, int colnum, int ncols, char **ttype, - char **tform, > int *status) - - int fits_delete_col / ffdcol(fitsfile *fptr, int colnum, > int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Copy a column from one HDU to another (or to the same HDU). If - create\_col = TRUE, then a new column will be inserted in the output - table, at position `outcolumn', otherwise the existing output column will - be overwritten (in which case it must have a compatible data type). - If outcolnum is greater than the number of column in the table, then - the new column will be appended to the end of the table. - Note that the first column in a table is at colnum = 1. - The standard indexed keywords that related to the column (e.g., TDISPn, - TUNITn, TCRPXn, TCDLTn, etc.) will also be copied. \label{ffcpcl} -\end{description} - -\begin{verbatim} - int fits_copy_col / ffcpcl - (fitsfile *infptr, fitsfile *outfptr, int incolnum, int outcolnum, - int create_col, > int *status); -\end{verbatim} - -\begin{description} -\item[4 ] Copy 'nrows' consecutive rows from one table to another, beginning - with row 'firstrow'. These rows will be appended to any existing - rows in the output table. - Note that the first row in a table is at row = 1. \label{ffcprw} -\end{description} - -\begin{verbatim} - int fits_copy_rows / ffcprw - (fitsfile *infptr, fitsfile *outfptr, LONGLONG firstrow, - LONGLONG nrows, > int *status); -\end{verbatim} - -\begin{description} -\item[5 ] Modify the vector length of a binary table column (e.g., - change a column from TFORMn = '1E' to '20E'). The vector - length may be increased or decreased from the current value. \label{ffmvec} -\end{description} - -\begin{verbatim} - int fits_modify_vector_len / ffmvec - (fitsfile *fptr, int colnum, LONGLONG newveclen, > int *status) -\end{verbatim} - -\subsection{Read and Write Column Data Routines} - -The following routines write or read data values in the current ASCII -or binary table extension. If a write operation extends beyond the -current size of the table, then the number of rows in the table will -automatically be increased and the NAXIS2 keyword value will be -updated. Attempts to read beyond the end of the table will result in -an error. - -Automatic data type conversion is performed for numerical data types -(only) if the data type of the column (defined by the TFORMn keyword) -differs from the data type of the array in the calling routine. ASCII and binary -tables support the following data type values: TSTRING, TBYTE, TSBYTE, TSHORT, -TUSHORT, TINT, TUINT, TLONG, TLONGLONG, TULONG, TFLOAT, or TDOUBLE. -Binary tables also support TLOGICAL (internally mapped to the `char' -data type), TCOMPLEX, and TDBLCOMPLEX. - -Note that it is *not* necessary to insert rows in a table before -writing data to those rows (indeed, it would be inefficient to do so). -Instead, one may simply write data to any row of the table, whether that -row of data already exists or not. - -Individual bits in a binary table 'X' or 'B' column may be read/written -to/from a *char array by specifying the TBIT datatype. The *char -array will be interpreted as an array of logical TRUE (1) or FALSE (0) -values that correspond to the value of each bit in the FITS 'X' or 'B' column. -Alternatively, the values in a binary table 'X' column may be read/written -8 bits at a time to/from an array of 8-bit integers by specifying the -TBYTE datatype. - -Note that within the context of these routines, the TSTRING data type -corresponds to a C 'char**' data type, i.e., a pointer to an array of -pointers to an array of characters. This is different from the keyword -reading and writing routines where TSTRING corresponds to a C 'char*' -data type, i.e., a single pointer to an array of characters. When -reading strings from a table, the char arrays obviously must have been -allocated long enough to hold the whole FITS table string. - -Numerical data values are automatically scaled by the TSCALn and TZEROn -keyword values (if they exist). - -In the case of binary tables with vector elements, the 'felem' -parameter defines the starting element (beginning with 1, not 0) within -the cell (a cell is defined as the intersection of a row and a column -and may contain a single value or a vector of values). The felem -parameter is ignored when dealing with ASCII tables. Similarly, in the -case of binary tables the 'nelements' parameter specifies the total -number of vector values to be read or written (continuing on subsequent -rows if required) and not the number of table cells. - - -\begin{description} -\item[1 ] Write elements into an ASCII or binary table column. -\end{description} - The first routine simply writes the array of values to the FITS file - (doing data type conversion if necessary) whereas the second routine - will substitute the appropriate FITS null value for all elements - which are equal to the input value of nulval (note that this - parameter gives the address of nulval, not the null value - itself). For integer columns the FITS null value is defined by the - TNULLn keyword (an error is returned if the keyword doesn't exist). - For floating point columns the special IEEE NaN (Not-a-Number) - value will be written into the FITS file. If a null pointer is - entered for nulval, then the null value is ignored and this routine - behaves the same as the first routine. The third routine - simply writes undefined pixel values to the column. The fourth routine - fills every column in the table with null values, in the specified - rows (ignoring any columns that do not have a defined null value). - \label{ffpcl} \label{ffpcn} \label{ffpclu} - -\begin{verbatim} - int fits_write_col / ffpcl - (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, - LONGLONG firstelem, LONGLONG nelements, DTYPE *array, > int *status) - - int fits_write_colnull / ffpcn - (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, - LONGLONG firstelem, LONGLONG nelements, DTYPE *array, DTYPE *nulval, - > int *status) - - int fits_write_col_null / ffpclu - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, > int *status) - - int fits_write_nullrows / ffprwu - (fitsfile *fptr, LONGLONG firstrow, LONGLONG nelements, > int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Read elements from an ASCII or binary table column. The data type - parameter specifies the data type of the `nulval' and `array' pointers; - Undefined array elements will be returned with a value = *nullval, - (note that this parameter gives the address of the null value, not the - null value itself) unless nulval = 0 or *nulval = 0, in which case - no checking for undefined pixels will be performed. The second - routine is similar except that any undefined pixels will have the - corresponding nullarray element set equal to TRUE (= 1). - - Any column, regardless of it's intrinsic data type, may be read as a - string. It should be noted however that reading a numeric column - as a string is 10 - 100 times slower than reading the same column - as a number due to the large overhead in constructing the formatted - strings. The display format of the returned strings will be - determined by the TDISPn keyword, if it exists, otherwise by the - data type of the column. The length of the returned strings (not - including the null terminating character) can be determined with - the fits\_get\_col\_display\_width routine. The following TDISPn - display formats are currently supported: - -\begin{verbatim} - Iw.m Integer - Ow.m Octal integer - Zw.m Hexadecimal integer - Fw.d Fixed floating point - Ew.d Exponential floating point - Dw.d Exponential floating point - Gw.d General; uses Fw.d if significance not lost, else Ew.d -\end{verbatim} - where w is the width in characters of the displayed values, m is the minimum - number of digits displayed, and d is the number of digits to the right of the - decimal. The .m field is optional. - \label{ffgcv} \label{ffgcf} -\end{description} - -\begin{verbatim} - int fits_read_col / ffgcv - (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, DTYPE *nulval, DTYPE *array, int *anynul, int *status) - - int fits_read_colnull / ffgcf - (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, DTYPE *array, char *nullarray, int *anynul, int *status) -\end{verbatim} - - -\subsection{Row Selection and Calculator Routines} - -These routines all parse and evaluate an input string containing a user -defined arithmetic expression. The first 3 routines select rows in a -FITS table, based on whether the expression evaluates to true (not -equal to zero) or false (zero). The other routines evaluate the -expression and calculate a value for each row of the table. The -allowed expression syntax is described in the row filter section in the -`Extended File Name Syntax' chapter of this document. The expression -may also be written to a text file, and the name of the file, prepended -with a '@' character may be supplied for the 'expr' parameter (e.g. -'@filename.txt'). The expression in the file can be arbitrarily -complex and extend over multiple lines of the file. Lines that begin -with 2 slash characters ('//') will be ignored and may be used to add -comments to the file. - - -\begin{description} -\item[1 ] Evaluate a boolean expression over the indicated rows, returning an - array of flags indicating which rows evaluated to TRUE/FALSE. - Upon return, - *n\_good\_rows contains the number of rows that evaluate to TRUE. \label{fffrow} -\end{description} - -\begin{verbatim} - int fits_find_rows / fffrow - (fitsfile *fptr, char *expr, long firstrow, long nrows, - > long *n_good_rows, char *row_status, int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Find the first row which satisfies the input boolean expression \label{ffffrw} -\end{description} - -\begin{verbatim} - int fits_find_first_row / ffffrw - (fitsfile *fptr, char *expr, > long *rownum, int *status) -\end{verbatim} - -\begin{description} -\item[3 ]Evaluate an expression on all rows of a table. If the input and output -files are not the same, copy the TRUE rows to the output file; if the output -table is not empty, then this routine will append the new -selected rows after the existing rows. If the -files are the same, delete the FALSE rows (preserve the TRUE rows). \label{ffsrow} -\end{description} - -\begin{verbatim} - int fits_select_rows / ffsrow - (fitsfile *infptr, fitsfile *outfptr, char *expr, > int *status ) -\end{verbatim} - -\begin{description} -\item[4 ] Calculate an expression for the indicated rows of a table, returning -the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If -nulval==NULL, UNDEFs will be zeroed out. For vector results, the number -of elements returned may be less than nelements if nelements is not an -even multiple of the result dimension. Call fits\_test\_expr to obtain -the dimensions of the results. \label{ffcrow} -\end{description} - -\begin{verbatim} - int fits_calc_rows / ffcrow - (fitsfile *fptr, int datatype, char *expr, long firstrow, - long nelements, void *nulval, > void *array, int *anynul, int *status) -\end{verbatim} - -\begin{description} -\item[5 ]Evaluate an expression and write the result either to a column (if -the expression is a function of other columns in the table) or to a -keyword (if the expression evaluates to a constant and is not a -function of other columns in the table). In the former case, the -parName parameter is the name of the column (which may or may not already -exist) into which to write the results, and parInfo contains an -optional TFORM keyword value if a new column is being created. If a -TFORM value is not specified then a default format will be used, -depending on the expression. If the expression evaluates to a constant, -then the result will be written to the keyword name given by the -parName parameter, and the parInfo parameter may be used to supply an -optional comment for the keyword. If the keyword does not already -exist, then the name of the keyword must be preceded with a '\#' character, - otherwise the result will be written to a column with that name. \label{ffcalc} -\end{description} - -\begin{verbatim} - int fits_calculator / ffcalc - (fitsfile *infptr, char *expr, fitsfile *outfptr, char *parName, - char *parInfo, > int *status) -\end{verbatim} - -\begin{description} -\item[6 ] This calculator routine is similar to the previous routine, except -that the expression is only evaluated over the specified -row ranges. nranges specifies the number of row ranges, and firstrow -and lastrow give the starting and ending row number of each range. \label{ffcalcrng} -\end{description} - -\begin{verbatim} - int fits_calculator_rng / ffcalc_rng - (fitsfile *infptr, char *expr, fitsfile *outfptr, char *parName, - char *parInfo, int nranges, long *firstrow, long *lastrow - > int *status) -\end{verbatim} - -\begin{description} -\item[7 ]Evaluate the given expression and return dimension and type information -on the result. The returned dimensions correspond to a single row entry -of the requested expression, and are equivalent to the result of fits\_read\_tdim(). -Note that strings are considered to be one element regardless of string length. -If maxdim == 0, then naxes is optional. \label{fftexp} -\end{description} - -\begin{verbatim} - int fits_test_expr / fftexp - (fitsfile *fptr, char *expr, int maxdim > int *datatype, long *nelem, int *naxis, - long *naxes, int *status) -\end{verbatim} - - -\subsection{Column Binning or Histogramming Routines} - -The following routines may be useful when performing histogramming operations on -column(s) of a table to generate an image in a primary array or image extension. - - -\begin{description} -\item[1 ] Calculate the histogramming parameters (min, max, and bin size -for each axis of the histogram, based on a variety of possible input parameters. -If the input names of the columns to be binned are null, then the routine will first -look for the CPREF = "NAME1, NAME2, ..." keyword which lists the preferred -columns. If not present, then the routine will assume the column names X, Y, Z, and T -for up to 4 axes (as specified by the NAXIS parameter). - -MININ and MAXIN are input arrays that give the minimum and maximum value for -the histogram, along each axis. Alternatively, the name of keywords that give -the min, max, and binsize may be give with the MINNAME, MAXNAME, and BINNAME -array parameters. If the value = DOUBLENULLVALUE and no keyword names are -given, then the routine will use the TLMINn and TLMAXn keywords, if present, or the -actual min and/or max values in the column. - -BINSIZEIN is an array giving the binsize along each axis. -If the value = -DOUBLENULLVALUE, and a keyword name is not specified with BINNAME, -then this routine will first look for the TDBINn keyword, or else will -use a binsize = 1, or a binsize that produces 10 histogram bins, which ever -is smaller. - \label{calcbinning} -\end{description} - -\begin{verbatim} - int fits_calc_binning - Input parameters: - (fitsfile *fptr, /* IO - pointer to table to be binned */ - int naxis, /* I - number of axes/columns in the binned image */ - char colname[4][FLEN_VALUE], /* I - optional column names */ - double *minin, /* I - optional lower bound value for each axis */ - double *maxin, /* I - optional upper bound value, for each axis */ - double *binsizein, /* I - optional bin size along each axis */ - char minname[4][FLEN_VALUE], /* I - optional keywords for min */ - char maxname[4][FLEN_VALUE], /* I - optional keywords for max */ - char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */ - Output parameters: - int *colnum, /* O - column numbers, to be binned */ - long *naxes, /* O - number of bins in each histogram axis */ - float *amin, /* O - lower bound of the histogram axes */ - float *amax, /* O - upper bound of the histogram axes */ - float *binsize, /* O - width of histogram bins/pixels on each axis */ - int *status) -\end{verbatim} - - -\begin{description} -\item[2 ] Copy the relevant keywords from the header of the table that is being -binned, to the the header of the output histogram image. This will not -copy the table structure keywords (e.g., NAXIS, TFORMn, TTYPEn, etc.) nor -will it copy the keywords that apply to other columns of the table that are -not used to create the histogram. This routine will translate the names of -the World Coordinate System (WCS) keywords for the binned columns into the -form that is need for a FITS image (e.g., the TCTYPn table keyword will -be translated to the CTYPEn image keyword). - \label{copypixlist2image} -\end{description} - -\begin{verbatim} - int fits_copy_pixlist2image - (fitsfile *infptr, /* I - pointer to input HDU */ - fitsfile *outfptr, /* I - pointer to output HDU */ - int firstkey, /* I - first HDU keyword to start with */ - int naxis, /* I - number of axes in the image */ - int *colnum, /* I - numbers of the columns to be binned */ - int *status) /* IO - error status */ -\end{verbatim} - - -\begin{description} -\item[3 ] Write a set of default WCS keywords to the histogram header, IF the -WCS keywords do not already exist. This will create a linear WCS where -the coordinate types are equal to the original column names. - \label{writekeyshisto} -\end{description} - -\begin{verbatim} - int fits_write_keys_histo - (fitsfile *fptr, /* I - pointer to table to be binned */ - fitsfile *histptr, /* I - pointer to output histogram image HDU */ - int naxis, /* I - number of axes in the histogram image */ - int *colnum, /* I - column numbers of the binned columns */ - int *status) -\end{verbatim} - - -\begin{description} -\item[4 ] Update the WCS keywords in a histogram image header that give the location -of the reference pixel (CRPIXn), and the pixel size (CDELTn), in the binned -image. - \label{rebinwcs} -\end{description} - -\begin{verbatim} - int fits_rebin_wcs - (fitsfile *fptr, /* I - pointer to table to be binned */ - int naxis, /* I - number of axes in the histogram image */ - float *amin, /* I - first pixel include in each axis */ - float *binsize, /* I - binning factor for each axis */ - int *status) -\end{verbatim} - - -\begin{description} -\item[5 ] Bin the values in the input table columns, and write the histogram -array to the output FITS image (histptr). - \label{makehist} -\end{description} - -\begin{verbatim} - int fits_make_hist - (fitsfile *fptr, /* I - pointer to table with X and Y cols; */ - fitsfile *histptr, /* I - pointer to output FITS image */ - int bitpix, /* I - datatype for image: 16, 32, -32, etc */ - int naxis, /* I - number of axes in the histogram image */ - long *naxes, /* I - size of axes in the histogram image */ - int *colnum, /* I - column numbers (array length = naxis) */ - float *amin, /* I - minimum histogram value, for each axis */ - float *amax, /* I - maximum histogram value, for each axis */ - float *binsize, /* I - bin size along each axis */ - float weight, /* I - binning weighting factor (FLOATNULLVALUE */ - /* for no weighting) */ - int wtcolnum, /* I - keyword or col for weight (or NULL) */ - int recip, /* I - use reciprocal of the weight? 0 or 1 */ - char *selectrow, /* I - optional array (length = no. of */ - /* rows in the table). If the element is true */ - /* then the corresponding row of the table will */ - /* be included in the histogram, otherwise the */ - /* row will be skipped. Ingnored if *selectrow */ - /* is equal to NULL. */ - int *status) -\end{verbatim} - - - -\section{Utility Routines} - - -\subsection{File Checksum Routines} - -The following routines either compute or validate the checksums for the -CHDU. The DATASUM keyword is used to store the numerical value of the -32-bit, 1's complement checksum for the data unit alone. If there is -no data unit then the value is set to zero. The numerical value is -stored as an ASCII string of digits, enclosed in quotes, because the -value may be too large to represent as a 32-bit signed integer. The -CHECKSUM keyword is used to store the ASCII encoded COMPLEMENT of the -checksum for the entire HDU. Storing the complement, rather than the -actual checksum, forces the checksum for the whole HDU to equal zero. -If the file has been modified since the checksums were computed, then -the HDU checksum will usually not equal zero. These checksum keyword -conventions are based on a paper by Rob Seaman published in the -proceedings of the ADASS IV conference in Baltimore in November 1994 -and a later revision in June 1995. See Appendix B for the definition -of the parameters used in these routines. - - -\begin{description} -\item[1 ] Compute and write the DATASUM and CHECKSUM keyword values for the CHDU - into the current header. If the keywords already exist, their values - will be updated only if necessary (i.e., if the file - has been modified since the original keyword - values were computed). \label{ffpcks} -\end{description} - -\begin{verbatim} - int fits_write_chksum / ffpcks - (fitsfile *fptr, > int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Update the CHECKSUM keyword value in the CHDU, assuming that the - DATASUM keyword exists and already has the correct value. This routine - calculates the new checksum for the current header unit, adds it to the - data unit checksum, encodes the value into an ASCII string, and writes - the string to the CHECKSUM keyword. \label{ffupck} -\end{description} - -\begin{verbatim} - int fits_update_chksum / ffupck - (fitsfile *fptr, > int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Verify the CHDU by computing the checksums and comparing - them with the keywords. The data unit is verified correctly - if the computed checksum equals the value of the DATASUM - keyword. The checksum for the entire HDU (header plus data unit) is - correct if it equals zero. The output DATAOK and HDUOK parameters - in this routine are integers which will have a value = 1 - if the data or HDU is verified correctly, a value = 0 - if the DATASUM or CHECKSUM keyword is not present, or value = -1 - if the computed checksum is not correct. \label{ffvcks} -\end{description} - -\begin{verbatim} - int fits_verify_chksum / ffvcks - (fitsfile *fptr, > int *dataok, int *hduok, int *status) -\end{verbatim} - -\begin{description} -\item[4 ] Compute and return the checksum values for the CHDU - without creating or modifying the - CHECKSUM and DATASUM keywords. This routine is used internally by - ffvcks, but may be useful in other situations as well. \label{ffgcks} -\end{description} - -\begin{verbatim} - int fits_get_chksum/ /ffgcks - (fitsfile *fptr, > unsigned long *datasum, unsigned long *hdusum, - int *status) -\end{verbatim} - -\begin{description} -\item[5 ] Encode a checksum value - into a 16-character string. If complm is non-zero (true) then the 32-bit - sum value will be complemented before encoding. \label{ffesum} -\end{description} - -\begin{verbatim} - int fits_encode_chksum / ffesum - (unsigned long sum, int complm, > char *ascii); -\end{verbatim} - -\begin{description} -\item[6 ] Decode a 16-character checksum string into a unsigned long value. - If is non-zero (true). then the 32-bit sum value will be complemented - after decoding. The checksum value is also returned as the - value of the function. \label{ffdsum} -\end{description} - -\begin{verbatim} - unsigned long fits_decode_chksum / ffdsum - (char *ascii, int complm, > unsigned long *sum); -\end{verbatim} - - -\subsection{Date and Time Utility Routines} - -The following routines help to construct or parse the FITS date/time -strings. Starting in the year 2000, the FITS DATE keyword values (and -the values of other `DATE-' keywords) must have the form 'YYYY-MM-DD' -(date only) or 'YYYY-MM-DDThh:mm:ss.ddd...' (date and time) where the -number of decimal places in the seconds value is optional. These times -are in UTC. The older 'dd/mm/yy' date format may not be used for dates -after 01 January 2000. See Appendix B for the definition of the -parameters used in these routines. - - -\begin{description} -\item[1 ] Get the current system date. C already provides standard - library routines for getting the current date and time, - but this routine is provided for compatibility with - the Fortran FITSIO library. The returned year has 4 digits - (1999, 2000, etc.) \label{ffgsdt} -\end{description} - -\begin{verbatim} - int fits_get_system_date/ffgsdt - ( > int *day, int *month, int *year, int *status ) -\end{verbatim} - - -\begin{description} -\item[2 ] Get the current system date and time string ('YYYY-MM-DDThh:mm:ss'). -The time will be in UTC/GMT if available, as indicated by a returned timeref -value = 0. If the returned value of timeref = 1 then this indicates that -it was not possible to convert the local time to UTC, and thus the local -time was returned. -\end{description} - -\begin{verbatim} - int fits_get_system_time/ffgstm - (> char *datestr, int *timeref, int *status) -\end{verbatim} - - -\begin{description} -\item[3 ] Construct a date string from the input date values. If the year -is between 1900 and 1998, inclusive, then the returned date string will -have the old FITS format ('dd/mm/yy'), otherwise the date string will -have the new FITS format ('YYYY-MM-DD'). Use fits\_time2str instead - to always return a date string using the new FITS format. \label{ffdt2s} -\end{description} - -\begin{verbatim} - int fits_date2str/ffdt2s - (int year, int month, int day, > char *datestr, int *status) -\end{verbatim} - - -\begin{description} -\item[4 ] Construct a new-format date + time string ('YYYY-MM-DDThh:mm:ss.ddd...'). - If the year, month, and day values all = 0 then only the time is encoded - with format 'hh:mm:ss.ddd...'. The decimals parameter specifies how many - decimal places of fractional seconds to include in the string. If `decimals' - is negative, then only the date will be return ('YYYY-MM-DD'). -\end{description} - -\begin{verbatim} - int fits_time2str/fftm2s - (int year, int month, int day, int hour, int minute, double second, - int decimals, > char *datestr, int *status) -\end{verbatim} - - -\begin{description} -\item[5 ] Return the date as read from the input string, where the string may be -in either the old ('dd/mm/yy') or new ('YYYY-MM-DDThh:mm:ss' or -'YYYY-MM-DD') FITS format. Null pointers may be supplied for any - unwanted output date parameters. -\end{description} - -\begin{verbatim} - int fits_str2date/ffs2dt - (char *datestr, > int *year, int *month, int *day, int *status) -\end{verbatim} - - -\begin{description} -\item[6 ] Return the date and time as read from the input string, where the -string may be in either the old or new FITS format. The returned hours, -minutes, and seconds values will be set to zero if the input string -does not include the time ('dd/mm/yy' or 'YYYY-MM-DD') . Similarly, -the returned year, month, and date values will be set to zero if the -date is not included in the input string ('hh:mm:ss.ddd...'). Null -pointers may be supplied for any unwanted output date and time -parameters. -\end{description} - -\begin{verbatim} - int fits_str2time/ffs2tm - (char *datestr, > int *year, int *month, int *day, int *hour, - int *minute, double *second, int *status) -\end{verbatim} - - -\subsection{General Utility Routines} - -The following utility routines may be useful for certain applications. - - -\begin{description} -\item[1 ] Return the revision number of the CFITSIO library. - The revision number will be incremented with each new - release of CFITSIO. \label{ffvers} -\end{description} - -\begin{verbatim} - float fits_get_version / ffvers ( > float *version) -\end{verbatim} - -\begin{description} -\item[2 ] Write an 80-character message to the CFITSIO error stack. Application - programs should not normally write to the stack, but there may be - some situations where this is desirable. \label{ffpmsg} -\end{description} - -\begin{verbatim} - void fits_write_errmsg / ffpmsg (char *err_msg) -\end{verbatim} - -\begin{description} -\item[3 ] Convert a character string to uppercase (operates in place). \label{ffupch} -\end{description} - -\begin{verbatim} - void fits_uppercase / ffupch (char *string) -\end{verbatim} - -\begin{description} -\item[4 ] Compare the input template string against the reference string - to see if they match. The template string may contain wildcard - characters: '*' will match any sequence of characters (including - zero characters) and '?' will match any single character in the - reference string. The '\#' character will match any consecutive string - of decimal digits (0 - 9). If casesen = CASESEN = TRUE then the match will - be case sensitive, otherwise the case of the letters will be ignored - if casesen = CASEINSEN = FALSE. The returned MATCH parameter will be - TRUE if the 2 strings match, and EXACT will be TRUE if the match is - exact (i.e., if no wildcard characters were used in the match). - Both strings must be 68 characters or less in length. \label{ffcmps} -\end{description} - -\begin{verbatim} - void fits_compare_str / ffcmps - (char *templt, char *string, int casesen, > int *match, int *exact) -\end{verbatim} - -\begin{description} -\item[5 ]Split a string containing a list of names (typically file names or column - names) into individual name tokens by a sequence of calls to - fits\_split\_names. The names in the list must be delimited by a comma - and/or spaces. This routine ignores spaces and commas that occur - within parentheses, brackets, or curly brackets. It also strips any - leading and trailing blanks from the returned name. - - This routine is similar to the ANSI C 'strtok' function: - - The first call to fits\_split\_names has a non-null input string. - It finds the first name in the string and terminates it by overwriting - the next character of the string with a null terminator and returns a - pointer to the name. Each subsequent call, indicated by a NULL value - of the input string, returns the next name, searching from just past - the end of the previous name. It returns NULL when no further names - are found. \label{splitnames} -\end{description} - -\begin{verbatim} - char *fits_split_names(char *namelist) -\end{verbatim} - The following example shows how a string would be split into 3 names: - -\begin{verbatim} - myfile[1][bin (x,y)=4], file2.fits file3.fits - ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ - 1st name 2nd name 3rd name -\end{verbatim} - -\begin{description} -\item[6 ] Test that the keyword name contains only legal characters (A-Z,0-9, - hyphen, and underscore) or that the keyword record contains only legal - printable ASCII characters \label{fftkey} \label{fftrec} -\end{description} - -\begin{verbatim} - int fits_test_keyword / fftkey (char *keyname, > int *status) - - int fits_test_record / fftrec (char *card, > int *status) -\end{verbatim} - -\begin{description} -\item[7 ] Test whether the current header contains any NULL (ASCII 0) characters. - These characters are illegal in the header, but they will go undetected - by most of the CFITSIO keyword header routines, because the null is - interpreted as the normal end-of-string terminator. This routine returns - the position of the first null character in the header, or zero if there - are no nulls. For example a returned value of 110 would indicate that - the first NULL is located in the 30th character of the second keyword - in the header (recall that each header record is 80 characters long). - Note that this is one of the few CFITSIO routines in which the returned - value is not necessarily equal to the status value). \label{ffnchk} -\end{description} - -\begin{verbatim} - int fits_null_check / ffnchk (char *card, > int *status) -\end{verbatim} - -\begin{description} -\item[8 ] Parse a header keyword record and return the name of the keyword, - and the length of the name. - The keyword name normally occupies the first 8 characters of the - record, except under the HIERARCH convention where the name can - be up to 70 characters in length. \label{ffgknm} -\end{description} - -\begin{verbatim} - int fits_get_keyname / ffgknm - (char *card, > char *keyname, int *keylength, int *status) -\end{verbatim} - -\begin{description} -\item[9 ] Parse a header keyword record, returning the value (as - a literal character string) and comment strings. If the keyword has no - value (columns 9-10 not equal to '= '), then a null value string is - returned and the comment string is set equal to column 9 - 80 of the - input string. \label{ffpsvc} -\end{description} - -\begin{verbatim} - int fits_parse_value / ffpsvc - (char *card, > char *value, char *comment, int *status) -\end{verbatim} - -\begin{description} -\item[10] Construct a properly formated 80-character header keyword record from the - input keyword name, keyword value, and keyword comment strings. - Hierarchical keyword names (e.g., "ESO TELE CAM") are supported. - The value string may contain an integer, floating point, logical, or - quoted character string (e.g., "12", "15.7", "T", - or "'NGC 1313'"). \label{ffmkky} -\end{description} - -\begin{verbatim} - int fits_make_key / ffmkky - (const char *keyname, const char *value, const char *comment, - > char *card, int *status) -\end{verbatim} - -\begin{description} -\item[11] Construct an array indexed keyword name (ROOT + nnn). - This routine appends the sequence number to the root string to create - a keyword name (e.g., 'NAXIS' + 2 = 'NAXIS2') \label{ffkeyn} -\end{description} - -\begin{verbatim} - int fits_make_keyn / ffkeyn - (char *keyroot, int value, > char *keyname, int *status) -\end{verbatim} - -\begin{description} -\item[12] Construct a sequence keyword name (n + ROOT). - This routine concatenates the sequence number to the front of the - root string to create a keyword name (e.g., 1 + 'CTYP' = '1CTYP') \label{ffnkey} -\end{description} - -\begin{verbatim} - int fits_make_nkey / ffnkey - (int value, char *keyroot, > char *keyname, int *status) -\end{verbatim} - -\begin{description} -\item[13] Determine the data type of a keyword value string. This routine - parses the keyword value string to determine its data type. - Returns 'C', 'L', 'I', 'F' or 'X', for character string, logical, - integer, floating point, or complex, respectively. \label{ffdtyp} -\end{description} - -\begin{verbatim} - int fits_get_keytype / ffdtyp - (char *value, > char *dtype, int *status) -\end{verbatim} - -\begin{description} -\item[14] Determine the integer data type of an integer keyword value string. - The returned datatype value is the minimum integer datatype (starting - from top of the following list and working down) required - to store the integer value: -\end{description} - -\begin{verbatim} - Data Type Range - TSBYTE: -128 to 127 - TBYTE: 128 to 255 - TSHORT: -32768 to 32767 - TUSHORT: 32768 to 65535 - TINT -2147483648 to 2147483647 - TUINT 2147483648 to 4294967295 - TLONGLONG -9223372036854775808 to 9223372036854775807 -\end{verbatim} - -\begin{description} -\item[ ] The *neg parameter returns 1 if the input value is - negative and returns 0 if it is non-negative.\label{ffinttyp} -\end{description} - -\begin{verbatim} - int fits_get_inttype / ffinttyp - (char *value, > int *datatype, int *neg, int *status) -\end{verbatim} - -\begin{description} -\item[15] Return the class of an input header record. The record is classified - into one of the following categories (the class values are - defined in fitsio.h). Note that this is one of the few CFITSIO - routines that does not return a status value. \label{ffgkcl} -\end{description} - -\begin{verbatim} - Class Value Keywords - TYP_STRUC_KEY 10 SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, - GROUPS, PCOUNT, GCOUNT, END - XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, - and the first 4 COMMENT keywords in the primary array - that define the FITS format. - TYP_CMPRS_KEY 20 The keywords used in the compressed image or table - format, including ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, - ZTILEn, ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK - TYP_SCAL_KEY 30 BSCALE, BZERO, TSCALn, TZEROn - TYP_NULL_KEY 40 BLANK, TNULLn - TYP_DIM_KEY 50 TDIMn - TYP_RANG_KEY 60 TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX - TYP_UNIT_KEY 70 BUNIT, TUNITn - TYP_DISP_KEY 80 TDISPn - TYP_HDUID_KEY 90 EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL - TYP_CKSUM_KEY 100 CHECKSUM, DATASUM - TYP_WCS_KEY 110 WCS keywords defined in the the WCS papers, including: - CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn - CDj_is, PVj_ms, LONPOLEs, LATPOLEs - TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, - TCRPks, TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn - jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, - iCRPns, jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn - (i,j,m,n are integers, s is any letter) - TYP_REFSYS_KEY 120 EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs, DATE-OBS - TYP_COMM_KEY 130 COMMENT, HISTORY, (blank keyword) - TYP_CONT_KEY 140 CONTINUE - TYP_USER_KEY 150 all other keywords - - int fits_get_keyclass / ffgkcl (char *card) -\end{verbatim} - -\begin{description} -\item[16] Parse the 'TFORM' binary table column format string. - This routine parses the input TFORM character string and returns the - integer data type code, the repeat count of the field, and, in the case - of character string fields, the length of the unit string. See Appendix - B for the allowed values for the returned typecode parameter. A - null pointer may be given for any output parameters that are not needed. \label{ffbnfm} -\end{description} - -\begin{verbatim} - int fits_binary_tform / ffbnfm - (char *tform, > int *typecode, long *repeat, long *width, - int *status) - - int fits_binary_tformll / ffbnfmll - (char *tform, > int *typecode, LONGLONG *repeat, long *width, - int *status) -\end{verbatim} - -\begin{description} -\item[17] Parse the 'TFORM' keyword value that defines the column format in - an ASCII table. This routine parses the input TFORM character - string and returns the data type code, the width of the column, - and (if it is a floating point column) the number of decimal places - to the right of the decimal point. The returned data type codes are - the same as for the binary table, with the following - additional rules: integer columns that are between 1 and 4 characters - wide are defined to be short integers (code = TSHORT). Wider integer - columns are defined to be regular integers (code = TLONG). Similarly, - Fixed decimal point columns (with TFORM = 'Fw.d') are defined to - be single precision reals (code = TFLOAT) if w is between 1 and 7 characters - wide, inclusive. Wider 'F' columns will return a double precision - data code (= TDOUBLE). 'Ew.d' format columns will have datacode = TFLOAT, - and 'Dw.d' format columns will have datacode = TDOUBLE. A null - pointer may be given for any output parameters that are not needed. \label{ffasfm} -\end{description} - -\begin{verbatim} - int fits_ascii_tform / ffasfm - (char *tform, > int *typecode, long *width, int *decimals, - int *status) -\end{verbatim} - -\begin{description} -\item[18] Calculate the starting column positions and total ASCII table width - based on the input array of ASCII table TFORM values. The SPACE input - parameter defines how many blank spaces to leave between each column - (it is recommended to have one space between columns for better human - readability). \label{ffgabc} -\end{description} - -\begin{verbatim} - int fits_get_tbcol / ffgabc - (int tfields, char **tform, int space, > long *rowlen, - long *tbcol, int *status) -\end{verbatim} - -\begin{description} -\item[19] Parse a template header record and return a formatted 80-character string - suitable for appending to (or deleting from) a FITS header file. - This routine is useful for parsing lines from an ASCII template file - and reformatting them into legal FITS header records. The formatted - string may then be passed to the fits\_write\_record, ffmcrd, or - fits\_delete\_key routines - to append or modify a FITS header record. \label{ffgthd} -\end{description} - -\begin{verbatim} - int fits_parse_template / ffgthd - (char *templt, > char *card, int *keytype, int *status) -\end{verbatim} - The input templt character string generally should contain 3 tokens: - (1) the KEYNAME, (2) the VALUE, and (3) the COMMENT string. The - TEMPLATE string must adhere to the following format: - - -\begin{description} -\item[- ] The KEYNAME token must begin in columns 1-8 and be a maximum of 8 - characters long. A legal FITS keyword name may only - contain the characters A-Z, 0-9, and '-' (minus sign) and - underscore. This routine will automatically convert any lowercase - characters to uppercase in the output string. If the first 8 characters - of the template line are - blank then the remainder of the line is considered to be a FITS comment - (with a blank keyword name). -\end{description} - - -\begin{description} -\item[- ] The VALUE token must be separated from the KEYNAME token by one or more - spaces and/or an '=' character. The data type of the VALUE token - (numeric, logical, or character string) is automatically determined - and the output CARD string is formatted accordingly. The value - token may be forced to be interpreted as a string (e.g. if it is a - string of numeric digits) by enclosing it in single quotes. - If the value token is a character string that contains 1 or more - embedded blank space characters or slash ('/') characters then the - entire character string must be enclosed in single quotes. -\end{description} - - -\begin{description} -\item[- ] The COMMENT token is optional, but if present must be separated from - the VALUE token by a blank space or a '/' character. -\end{description} - - -\begin{description} -\item[- ] One exception to the above rules is that if the first non-blank - character in the first 8 characters of the template string is a - minus sign ('-') followed - by a single token, or a single token followed by an equal sign, - then it is interpreted as the name of a keyword which is to be - deleted from the FITS header. -\end{description} - - -\begin{description} -\item[- ] The second exception is that if the template string starts with - a minus sign and is followed by 2 tokens (without an equals sign between - them) then the second token - is interpreted as the new name for the keyword specified by - first token. In this case the old keyword name (first token) - is returned in characters 1-8 of the returned CARD string, and - the new keyword name (the second token) is returned in characters - 41-48 of the returned CARD string. These old and new names - may then be passed to the ffmnam routine which will change - the keyword name. -\end{description} - - The keytype output parameter indicates how the returned CARD string - should be interpreted: - -\begin{verbatim} - keytype interpretation - ------- ------------------------------------------------- - -2 Rename the keyword with name = the first 8 characters of CARD - to the new name given in characters 41 - 48 of CARD. - - -1 delete the keyword with this name from the FITS header. - - 0 append the CARD string to the FITS header if the - keyword does not already exist, otherwise update - the keyword value and/or comment field if is already exists. - - 1 This is a HISTORY or COMMENT keyword; append it to the header - - 2 END record; do not explicitly write it to the FITS file. -\end{verbatim} - EXAMPLES: The following lines illustrate valid input template strings: - -\begin{verbatim} - INTVAL 7 / This is an integer keyword - RVAL 34.6 / This is a floating point keyword - EVAL=-12.45E-03 / This is a floating point keyword in exponential notation - lval F / This is a boolean keyword - This is a comment keyword with a blank keyword name - SVAL1 = 'Hello world' / this is a string keyword - SVAL2 '123.5' this is also a string keyword - sval3 123+ / this is also a string keyword with the value '123+ ' - # the following template line deletes the DATE keyword - - DATE - # the following template line modifies the NAME keyword to OBJECT - - NAME OBJECT -\end{verbatim} - -\begin{description} -\item[20] Translate a keyword name into a new name, based on a set of patterns. -This routine is useful for translating keywords in cases such as -adding or deleting columns in -a table, or copying a column from one table to another, or extracting -an array from a cell in a binary table column into an image extension. In -these cases, it is necessary to translate the names of the keywords associated -with the original table column(s) into the appropriate keyword name in the final -file. For example, if column 2 is deleted from a table, -then the value of 'n' in all the -TFORMn and TTYPEn keywords for columns 3 and higher must be decremented -by 1. Even more complex translations are sometimes needed to convert the -WCS keywords when extracting an image out of a table column cell into -a separate image extension. - -The user passes an array of patterns to be matched. Input pattern -number i is pattern[i][0], and output pattern number i is -pattern[i][1]. Keywords are matched against the input patterns. If a -match is found then the keyword is re-written according to the output -pattern. - -Order is important. The first match is accepted. The fastest match -will be made when templates with the same first character are grouped -together. - -Several characters have special meanings: - -\begin{verbatim} - i,j - single digits, preserved in output template - n - column number of one or more digits, preserved in output template - m - generic number of one or more digits, preserved in output template - a - coordinate designator, preserved in output template - # - number of one or more digits - ? - any character - * - only allowed in first character position, to match all - keywords; only useful as last pattern in the list -\end{verbatim} -i, j, n, and m are returned by the routine. - -For example, the input pattern "iCTYPn" will match "1CTYP5" (if n\_value -is 5); the output pattern "CTYPEi" will be re-written as "CTYPE1". -Notice that "i" is preserved. - -The following output patterns are special: - - "-" - do not copy a keyword that matches the corresponding input pattern - - "+" - copy the input unchanged - -The inrec string could be just the 8-char keyword name, or the entire -80-char header record. Characters 9 - 80 in the input string simply get -appended to the translated keyword name. - -If n\_range = 0, then only keywords with 'n' equal to n\_value will be -considered as a pattern match. If n\_range = +1, then all values of -'n' greater than or equal to n\_value will be a match, and if -1, -then values of 'n' less than or equal to n\_value will match.\label{translatekey} -\end{description} - -\begin{verbatim} -int fits_translate_keyword( - char *inrec, /* I - input string */ - char *outrec, /* O - output converted string, or */ - /* a null string if input does not */ - /* match any of the patterns */ - char *patterns[][2],/* I - pointer to input / output string */ - /* templates */ - int npat, /* I - number of templates passed */ - int n_value, /* I - base 'n' template value of interest */ - int n_offset, /* I - offset to be applied to the 'n' */ - /* value in the output string */ - int n_range, /* I - controls range of 'n' template */ - /* values of interest (-1,0, or +1) */ - int *pat_num, /* O - matched pattern number (0 based) or -1 */ - int *i, /* O - value of i, if any, else 0 */ - int *j, /* O - value of j, if any, else 0 */ - int *m, /* O - value of m, if any, else 0 */ - int *n, /* O - value of n, if any, else 0 */ - int *status) /* IO - error status */ -\end{verbatim} - -\begin{description} -\item[ ] Here is an example of some of the patterns used to convert the keywords associated -with an image in a cell of a table column into the keywords appropriate for -an IMAGE extension: -\end{description} - -\begin{verbatim} - char *patterns[][2] = {{"TSCALn", "BSCALE" }, /* Standard FITS keywords */ - {"TZEROn", "BZERO" }, - {"TUNITn", "BUNIT" }, - {"TNULLn", "BLANK" }, - {"TDMINn", "DATAMIN" }, - {"TDMAXn", "DATAMAX" }, - {"iCTYPn", "CTYPEi" }, /* Coordinate labels */ - {"iCTYna", "CTYPEia" }, - {"iCUNIn", "CUNITi" }, /* Coordinate units */ - {"iCUNna", "CUNITia" }, - {"iCRVLn", "CRVALi" }, /* WCS keywords */ - {"iCRVna", "CRVALia" }, - {"iCDLTn", "CDELTi" }, - {"iCDEna", "CDELTia" }, - {"iCRPXn", "CRPIXi" }, - {"iCRPna", "CRPIXia" }, - {"ijPCna", "PCi_ja" }, - {"ijCDna", "CDi_ja" }, - {"iVn_ma", "PVi_ma" }, - {"iSn_ma", "PSi_ma" }, - {"iCRDna", "CRDERia" }, - {"iCSYna", "CSYERia" }, - {"iCROTn", "CROTAi" }, - {"WCAXna", "WCSAXESa"}, - {"WCSNna", "WCSNAMEa"}}; -\end{verbatim} - -\begin{description} -\item[21] Translate the keywords in the input HDU into the keywords that are -appropriate for the output HDU. This is a driver routine that calls -the previously described routine. -\end{description} - -\begin{verbatim} -int fits_translate_keywords( - fitsfile *infptr, /* I - pointer to input HDU */ - fitsfile *outfptr, /* I - pointer to output HDU */ - int firstkey, /* I - first HDU record number to start with */ - char *patterns[][2],/* I - pointer to input / output keyword templates */ - int npat, /* I - number of templates passed */ - int n_value, /* I - base 'n' template value of interest */ - int n_offset, /* I - offset to be applied to the 'n' */ - /* value in the output string */ - int n_range, /* I - controls range of 'n' template */ - /* values of interest (-1,0, or +1) */ - int *status) /* IO - error status */ -\end{verbatim} - - -\begin{description} -\item[22] Parse the input string containing a list of rows or row ranges, and - return integer arrays containing the first and last row in each - range. For example, if rowlist = "3-5, 6, 8-9" then it will - return numranges = 3, rangemin = 3, 6, 8 and rangemax = 5, 6, 9. - At most, 'maxranges' number of ranges will be returned. 'maxrows' - is the maximum number of rows in the table; any rows or ranges - larger than this will be ignored. The rows must be specified in - increasing order, and the ranges must not overlap. A minus sign - may be use to specify all the rows to the upper or lower bound, so - "50-" means all the rows from 50 to the end of the table, and "-" - means all the rows in the table, from 1 - maxrows. - \label{ffrwrg} -\end{description} - -\begin{verbatim} - int fits_parse_range / ffrwrg(char *rowlist, LONGLONG maxrows, int maxranges, > - int *numranges, long *rangemin, long *rangemax, int *status) - - int fits_parse_rangell / ffrwrgll(char *rowlist, LONGLONG maxrows, int maxranges, > - int *numranges, LONGLONG *rangemin, LONGLONG *rangemax, int *status) -\end{verbatim} - -\begin{description} -\item[23] Check that the Header fill bytes (if any) are all blank. These are the bytes - that may follow END keyword and before the beginning of data unit, - or the end of the HDU if there is no data unit. - \label{ffchfl} -\end{description} - -\begin{verbatim} - int ffchfl(fitsfile *fptr, > int *status) -\end{verbatim} - -\begin{description} -\item[24] Check that the Data fill bytes (if any) are all zero (for IMAGE or - BINARY Table HDU) or all blanks (for ASCII table HDU). These file - bytes may be located after the last valid data byte in the HDU and - before the physical end of the HDU. - \label{ffcdfl} -\end{description} - -\begin{verbatim} - int ffcdfl(fitsfile *fptr, > int *status) -\end{verbatim} - -\begin{description} -\item[25] Estimate the root-mean-squared (RMS) noise in an image. -These routines are mainly for use with the Hcompress image compression -algorithm. They return an estimate of the RMS noise in the background -pixels of the image. This robust algorithm (written by Richard -White, STScI) first attempts to estimate the RMS value -as 1.68 times the median of the absolute differences between successive -pixels in the image. If the median = 0, then the -algorithm falls back to computing the RMS of the difference between successive -pixels, after several N-sigma rejection cycles to remove -extreme values. The input parameters are: the array of image pixel values -(either float or short values), the number of values in the array, -the value that is used to represent null pixels (enter a very -large number if there are no null pixels). \label{imageRMS} -\end{description} - -\begin{verbatim} - int fits_rms_float (float fdata[], int npix, float in_null_value, - > double *rms, int *status) - int fits_rms_short (short fdata[], int npix, short in_null_value, - > double *rms, int *status) -\end{verbatim} - -\begin{description} -\item[26] Was CFITSIO compiled with the -D\_REENTRANT directive -so that it may be safely used in multi-threaded environments? -The following function returns 1 if yes, 0 if no. Note, however, -that even if the -D\_REENTRANT directive was specified, this does -not guarantee that the CFITSIO routines are thread-safe, because -some compilers may not support this feature.\label{reentrant} -\end{description} - -\begin{verbatim} -int fits_is_reentrant(void) -\end{verbatim} - -\chapter{ The CFITSIO Iterator Function } - -The fits\_iterate\_data function in CFITSIO provides a unique method of -executing an arbitrary user-supplied `work' function that operates on -rows of data in FITS tables or on pixels in FITS images. Rather than -explicitly reading and writing the FITS images or columns of data, one -instead calls the CFITSIO iterator routine, passing to it the name of -the user's work function that is to be executed along with a list of -all the table columns or image arrays that are to be passed to the work -function. The CFITSIO iterator function then does all the work of -allocating memory for the arrays, reading the input data from the FITS -file, passing them to the work function, and then writing any output -data back to the FITS file after the work function exits. Because -it is often more efficient to process only a subset of the total table -rows at one time, the iterator function can determine the optimum -amount of data to pass in each iteration and repeatedly call the work -function until the entire table been processed. - -For many applications this single CFITSIO iterator function can -effectively replace all the other CFITSIO routines for reading or -writing data in FITS images or tables. Using the iterator has several -important advantages over the traditional method of reading and writing -FITS data files: - -\begin{itemize} -\item -It cleanly separates the data I/O from the routine that operates on -the data. This leads to a more modular and `object oriented' -programming style. - -\item -It simplifies the application program by eliminating the need to allocate -memory for the data arrays and eliminates most of the calls to the CFITSIO -routines that explicitly read and write the data. - -\item -It ensures that the data are processed as efficiently as possible. -This is especially important when processing tabular data since -the iterator function will calculate the most efficient number -of rows in the table to be passed at one time to the user's work -function on each iteration. - -\item -Makes it possible for larger projects to develop a library of work -functions that all have a uniform calling sequence and are all -independent of the details of the FITS file format. - -\end{itemize} - -There are basically 2 steps in using the CFITSIO iterator function. -The first step is to design the work function itself which must have a -prescribed set of input parameters. One of these parameters is a -structure containing pointers to the arrays of data; the work function -can perform any desired operations on these arrays and does not need to -worry about how the input data were read from the file or how the -output data get written back to the file. - -The second step is to design the driver routine that opens all the -necessary FITS files and initializes the input parameters to the -iterator function. The driver program calls the CFITSIO iterator -function which then reads the data and passes it to the user's work -function. - -The following 2 sections describe these steps in more detail. There -are also several example programs included with the CFITSIO -distribution which illustrate how to use the iterator function. - - -\section{The Iterator Work Function} - -The user-supplied iterator work function must have the following set of -input parameters (the function can be given any desired name): - - -\begin{verbatim} - int user_fn( long totaln, long offset, long firstn, long nvalues, - int narrays, iteratorCol *data, void *userPointer ) -\end{verbatim} - -\begin{itemize} - -\item - totaln -- the total number of table rows or image pixels - that will be passed to the work function - during 1 or more iterations. - -\item - offset -- the offset applied to the first table row or image - pixel to be passed to the work function. In other - words, this is the number of rows or pixels that - are skipped over before starting the iterations. If - offset = 0, then all the table rows or image pixels - will be passed to the work function. - -\item - firstn -- the number of the first table row or image pixel - (starting with 1) that is being passed in this - particular call to the work function. - -\item - nvalues -- the number of table rows or image pixels that are - being passed in this particular call to the work - function. nvalues will always be less than or - equal to totaln and will have the same value on - each iteration, except possibly on the last - call which may have a smaller value. - -\item - narrays -- the number of arrays of data that are being passed - to the work function. There is one array for each - image or table column. - -\item - *data -- array of structures, one for each - column or image. Each structure contains a pointer - to the array of data as well as other descriptive - parameters about that array. - -\item - *userPointer -- a user supplied pointer that can be used - to pass ancillary information from the driver function - to the work function. - This pointer is passed to the CFITSIO iterator function - which then passes it on to the - work function without any modification. - It may point to a single number, to an array of values, - to a structure containing an arbitrary set of parameters - of different types, - or it may be a null pointer if it is not needed. - The work function must cast this pointer to the - appropriate data type before using it it. -\end{itemize} - -The totaln, offset, narrays, data, and userPointer parameters are -guaranteed to have the same value on each iteration. Only firstn, -nvalues, and the arrays of data pointed to by the data structures may -change on each iterative call to the work function. - -Note that the iterator treats an image as a long 1-D array of pixels -regardless of it's intrinsic dimensionality. The total number of -pixels is just the product of the size of each dimension, and the order -of the pixels is the same as the order that they are stored in the FITS -file. If the work function needs to know the number and size of the -image dimensions then these parameters can be passed via the -userPointer structure. - -The iteratorCol structure is currently defined as follows: - -\begin{verbatim} -typedef struct /* structure for the iterator function column information */ -{ - /* structure elements required as input to fits_iterate_data: */ - - fitsfile *fptr; /* pointer to the HDU containing the column or image */ - int colnum; /* column number in the table; ignored for images */ - char colname[70]; /* name (TTYPEn) of the column; null for images */ - int datatype; /* output data type (converted if necessary) */ - int iotype; /* type: InputCol, InputOutputCol, or OutputCol */ - - /* output structure elements that may be useful for the work function: */ - - void *array; /* pointer to the array (and the null value) */ - long repeat; /* binary table vector repeat value; set */ - /* equal to 1 for images */ - long tlmin; /* legal minimum data value, if any */ - long tlmax; /* legal maximum data value, if any */ - char unit[70]; /* physical unit string (BUNIT or TUNITn) */ - char tdisp[70]; /* suggested display format; null if none */ - -} iteratorCol; -\end{verbatim} - -Instead of directly reading or writing the elements in this structure, -it is recommended that programmers use the access functions that are -provided for this purpose. - -The first five elements in this structure must be initially defined by -the driver routine before calling the iterator routine. The CFITSIO -iterator routine uses this information to determine what column or -array to pass to the work function, and whether the array is to be -input to the work function, output from the work function, or both. -The CFITSIO iterator function fills in the values of the remaining -structure elements before passing it to the work function. - -The array structure element is a pointer to the actual data array and -it must be cast to the correct data type before it is used. The -`repeat' structure element give the number of data values in each row -of the table, so that the total number of data values in the array is -given by repeat * nvalues. In the case of image arrays and ASCII -tables, repeat will always be equal to 1. When the data type is a -character string, the array pointer is actually a pointer to an array -of string pointers (i.e., char **array). The other output structure -elements are provided for convenience in case that information is -needed within the work function. Any other information may be passed -from the driver routine to the work function via the userPointer -parameter. - -Upon completion, the work routine must return an integer status value, -with 0 indicating success and any other value indicating an error which -will cause the iterator function to immediately exit at that point. Return status -values in the range 1 -- 1000 should be avoided since these are -reserved for use by CFITSIO. A return status value of -1 may be used to -force the CFITSIO iterator function to stop at that point and return -control to the driver routine after writing any output arrays to the -FITS file. CFITSIO does not considered this to be an error condition, -so any further processing by the application program will continue normally. - - -\section{The Iterator Driver Function} - -The iterator driver function must open the necessary FITS files and -position them to the correct HDU. It must also initialize the following -parameters in the iteratorCol structure (defined above) for each -column or image before calling the CFITSIO iterator function. -Several `constructor' routines are provided in CFITSIO for this -purpose. - -\begin{itemize} -\item - *fptr -- The fitsfile pointer to the table or image. -\item -colnum -- the number of the column in the table. This value is ignored - in the case of images. If colnum equals 0, then the column name - will be used to identify the column to be passed to the - work function. - -\item -colname -- the name (TTYPEn keyword) of the column. This is - only required if colnum = 0 and is ignored for images. -\item -datatype -- The desired data type of the array to be passed to the - work function. For numerical data the data type does - not need to be the same as the actual data type in the - FITS file, in which case CFITSIO will do the conversion. - Allowed values are: TSTRING, TLOGICAL, TBYTE, TSBYTE, TSHORT, TUSHORT, - TINT, TLONG, TULONG, TFLOAT, TDOUBLE. If the input - value of data type equals 0, then the existing - data type of the column or image will be used without - any conversion. - -\item -iotype -- defines whether the data array is to be input to the - work function (i.e, read from the FITS file), or output - from the work function (i.e., written to the FITS file) or - both. Allowed values are InputCol, OutputCol, or InputOutputCol. - Variable-length array columns are supported as InputCol or - InputOutputCol types, but may not be used for an OutputCol type. -\end{itemize} - -After the driver routine has initialized all these parameters, it -can then call the CFITSIO iterator function: - - -\begin{verbatim} - int fits_iterate_data(int narrays, iteratorCol *data, long offset, - long nPerLoop, int (*workFn)( ), void *userPointer, int *status); -\end{verbatim} - -\begin{itemize} -\item - - narrays -- the number of columns or images that are to be passed - to the work function. -\item - *data -- pointer to array of structures containing information - about each column or image. - -\item - offset -- if positive, this number of rows at the - beginning of the table (or pixels in the image) - will be skipped and will not be passed to the work - function. - -\item - nPerLoop - specifies the number of table rows (or number of - image pixels) that are to be passed to the work - function on each iteration. If nPerLoop = 0 - then CFITSIO will calculate the optimum number - for greatest efficiency. - If nPerLoop is negative, then all the rows - or pixels will be passed at one time, and the work - function will only be called once. If any variable - length arrays are being processed, then the nPerLoop - value is ignored, and the iterator will always process - one row of the table at a time. - -\item - *workFn - the name (actually the address) of the work function - that is to be called by fits\_iterate\_data. - -\item - *userPointer - this is a user supplied pointer that can be used - to pass ancillary information from the driver routine - to the work function. It may point to a single number, - an array, or to a structure containing an arbitrary set - of parameters. - -\item - *status - The CFITSIO error status. Should = 0 on input; - a non-zero output value indicates an error. -\end{itemize} - -When fits\_iterate\_data is called it first allocates memory to hold -all the requested columns of data or image pixel arrays. It then reads -the input data from the FITS tables or images into the arrays then -passes the structure with pointers to these data arrays to the work -function. After the work function returns, the iterator function -writes any output columns of data or images back to the FITS files. It -then repeats this process for any remaining sets of rows or image -pixels until it has processed the entire table or image or until the -work function returns a non-zero status value. The iterator then frees -the memory that it initially allocated and returns control to the -driver routine that called it. - - -\section{Guidelines for Using the Iterator Function} - -The totaln, offset, firstn, and nvalues parameters that are passed to -the work function are useful for determining how much of the data has -been processed and how much remains left to do. On the very first call -to the work function firstn will be equal to offset + 1; the work -function may need to perform various initialization tasks before -starting to process the data. Similarly, firstn + nvalues - 1 will be -equal to totaln on the last iteration, at which point the work function -may need to perform some clean up operations before exiting for the -last time. The work function can also force an early termination of -the iterations by returning a status value = -1. - -The narrays and iteratorCol.datatype arguments allow the work function -to double check that the number of input arrays and their data types -have the expected values. The iteratorCol.fptr and iteratorCol.colnum -structure elements can be used if the work function needs to read or -write the values of other keywords in the FITS file associated with -the array. This should generally only be done during the -initialization step or during the clean up step after the last set of -data has been processed. Extra FITS file I/O during the main -processing loop of the work function can seriously degrade the speed of -the program. - -If variable-length array columns are being processed, then the iterator -will operate on one row of the table at a time. In this case the -the repeat element in the interatorCol structure will be set equal to -the number of elements in the current row that is being processed. - -One important feature of the iterator is that the first element in each -array that is passed to the work function gives the value that is used -to represent null or undefined values in the array. The real data then -begins with the second element of the array (i.e., array[1], not -array[0]). If the first array element is equal to zero, then this -indicates that all the array elements have defined values and there are -no undefined values. If array[0] is not equal to zero, then this -indicates that some of the data values are undefined and this value -(array[0]) is used to represent them. In the case of output arrays -(i.e., those arrays that will be written back to the FITS file by the -iterator function after the work function exits) the work function must -set the first array element to the desired null value if necessary, -otherwise the first element should be set to zero to indicate that -there are no null values in the output array. CFITSIO defines 2 -values, FLOATNULLVALUE and DOUBLENULLVALUE, that can be used as default -null values for float and double data types, respectively. In the case -of character string data types, a null string is always used to -represent undefined strings. - -In some applications it may be necessary to recursively call the iterator -function. An example of this is given by one of the example programs -that is distributed with CFITSIO: it first calls a work function that -writes out a 2D histogram image. That work function in turn calls -another work function that reads the `X' and `Y' columns in a table to -calculate the value of each 2D histogram image pixel. Graphically, the -program structure can be described as: - -\begin{verbatim} - driver --> iterator --> work1_fn --> iterator --> work2_fn -\end{verbatim} - -Finally, it should be noted that the table columns or image arrays that -are passed to the work function do not all have to come from the same -FITS file and instead may come from any combination of sources as long -as they have the same length. The length of the first table column or -image array is used by the iterator if they do not all have the same -length. - - -\section{Complete List of Iterator Routines} - -All of the iterator routines are listed below. Most of these routines -do not have a corresponding short function name. - - -\begin{description} -\item[1 ] Iterator `constructor' functions that set - the value of elements in the iteratorCol structure - that define the columns or arrays. These set the fitsfile - pointer, column name, column number, datatype, and iotype, - respectively. The last 2 routines allow all the parameters - to be set with one function call (one supplies the column - name, the other the column number). \label{ffiterset} -\end{description} - - -\begin{verbatim} - int fits_iter_set_file(iteratorCol *col, fitsfile *fptr); - - int fits_iter_set_colname(iteratorCol *col, char *colname); - - int fits_iter_set_colnum(iteratorCol *col, int colnum); - - int fits_iter_set_datatype(iteratorCol *col, int datatype); - - int fits_iter_set_iotype(iteratorCol *col, int iotype); - - int fits_iter_set_by_name(iteratorCol *col, fitsfile *fptr, - char *colname, int datatype, int iotype); - - int fits_iter_set_by_num(iteratorCol *col, fitsfile *fptr, - int colnum, int datatype, int iotype); -\end{verbatim} - -\begin{description} -\item[2 ] Iterator `accessor' functions that return the value of the - element in the iteratorCol structure - that describes a particular data column or array \label{ffiterget} -\end{description} - -\begin{verbatim} - fitsfile * fits_iter_get_file(iteratorCol *col); - - char * fits_iter_get_colname(iteratorCol *col); - - int fits_iter_get_colnum(iteratorCol *col); - - int fits_iter_get_datatype(iteratorCol *col); - - int fits_iter_get_iotype(iteratorCol *col); - - void * fits_iter_get_array(iteratorCol *col); - - long fits_iter_get_tlmin(iteratorCol *col); - - long fits_iter_get_tlmax(iteratorCol *col); - - long fits_iter_get_repeat(iteratorCol *col); - - char * fits_iter_get_tunit(iteratorCol *col); - - char * fits_iter_get_tdisp(iteratorCol *col); -\end{verbatim} - -\begin{description} -\item[3 ] The CFITSIO iterator function \label{ffiter} -\end{description} - -\begin{verbatim} - int fits_iterate_data(int narrays, iteratorCol *data, long offset, - long nPerLoop, - int (*workFn)( long totaln, long offset, long firstn, - long nvalues, int narrays, iteratorCol *data, - void *userPointer), - void *userPointer, - int *status); -\end{verbatim} - -\chapter{ World Coordinate System Routines } - -The FITS community has adopted a set of keyword conventions that define -the transformations needed to convert between pixel locations in an -image and the corresponding celestial coordinates on the sky, or more -generally, that define world coordinates that are to be associated with -any pixel location in an n-dimensional FITS array. CFITSIO is distributed -with a a few self-contained World Coordinate System (WCS) routines, -however, these routines DO NOT support all the latest WCS conventions, -so it is STRONGLY RECOMMENDED that software developers use a more robust -external WCS library. Several recommended libraries are: - - -\begin{verbatim} - WCSLIB - supported by Mark Calabretta - WCSTools - supported by Doug Mink - AST library - developed by the U.K. Starlink project -\end{verbatim} - -More information about the WCS keyword conventions and links to all of -these WCS libraries can be found on the FITS Support Office web site at -http://fits.gsfc.nasa.gov under the WCS link. - -The functions provided in these external WCS libraries will need -access to the WCS keywords contained in the FITS file headers. -One convenient way to pass this information to the external library is -to use the fits\_hdr2str routine in CFITSIO (defined below) to copy the -header keywords into one long string, and then pass this string to an -interface routine in the external library that will extract -the necessary WCS information (e.g., the 'wcspih' routine in the WCSLIB -library and the 'astFitsChan' and 'astPutCards' functions in the AST -library). - - -\begin{description} -\item[1 ] Concatenate the header keywords in the CHDU into a single long - string of characters. Each 80-character fixed-length keyword - record is appended to the output character string, in order, with - no intervening separator or terminating characters. The last header - record is terminated with a NULL character. This routine allocates - memory for the returned character array, so the calling program must - free the memory when finished. - - There are 2 related routines: fits\_hdr2str simply concatenates all - the existing keywords in the header; fits\_convert\_hdr2str is similar, - except that if the CHDU is a tile compressed image (stored in a binary - table) then it will first convert that header back to that of a - normal FITS image before concatenating the keywords. - - Selected keywords may be excluded from the returned character string. - If the second parameter (nocomments) is TRUE (nonzero) then any - COMMENT, HISTORY, or blank keywords in the header will not be copied - to the output string. - - The 'exclist' parameter may be used to supply a list of keywords - that are to be excluded from the output character string. Wild card - characters (*, ?, and \#) may be used in the excluded keyword names. - If no additional keywords are to be excluded, then set nexc = 0 and - specify NULL for the the **exclist parameter. \label{hdr2str} -\end{description} - -\begin{verbatim} - int fits_hdr2str - (fitsfile *fptr, int nocomments, char **exclist, int nexc, - > char **header, int *nkeys, int *status) - - int fits_convert_hdr2str / ffcnvthdr2str - (fitsfile *fptr, int nocomments, char **exclist, int nexc, - > char **header, int *nkeys, int *status) -\end{verbatim} - - -\begin{description} -\item[2 ] The following CFITSIO routine is specifically designed for use -in conjunction with the WCSLIB library. It is not expected that -applications programmers will call this routine directly, but it -is documented here for completeness. This routine extracts arrays -from a binary table that contain WCS information using the -TAB table -lookup convention. See the documentation provided with the WCSLIB - library for more information. \label{wcstab} -\end{description} - -\begin{verbatim} - int fits_read_wcstab - (fitsfile *fptr, int nwtb, wtbarr *wtb, int *status); -\end{verbatim} - -\section{ Self-contained WCS Routines} - -The following routines DO NOT support the more recent WCS conventions -that have been approved as part of the FITS standard. Consequently, -the following routines ARE NOW DEPRECATED. It is STRONGLY RECOMMENDED -that software developers not use these routines, and instead use an -external WCS library, as described in the previous section. - -These routines are included mainly for backward compatibility with -existing software. They support the following standard map -projections: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, and -AIT (these are the -legal values for the coordtype parameter). These routines are based -on similar functions in Classic AIPS. All the angular quantities are -given in units of degrees. - - -\begin{description} -\item[1 ] Get the values of the basic set of standard FITS celestial coordinate - system keywords from the header of a FITS image (i.e., the primary - array or an IMAGE extension). These values may then be passed to - the fits\_pix\_to\_world and fits\_world\_to\_pix routines that - perform the coordinate transformations. If any or all of the WCS - keywords are not present, then default values will be returned. If - the first coordinate axis is the declination-like coordinate, then - this routine will swap them so that the longitudinal-like coordinate - is returned as the first axis. - - The first routine (ffgics) returns - the primary WCS, whereas the second routine returns the particular - version of the WCS specified by the 'version' parameter, which much - be a character ranging from 'A' to 'Z' (or a blank character, which is - equivalent to calling ffgics). - - If the file uses the newer 'CDj\_i' WCS transformation matrix - keywords instead of old style 'CDELTn' and 'CROTA2' keywords, then - this routine will calculate and return the values of the equivalent - old-style keywords. Note that the conversion from the new-style - keywords to the old-style values is sometimes only an - approximation, so if the approximation is larger than an internally - defined threshold level, then CFITSIO will still return the - approximate WCS keyword values, but will also return with status = - APPROX\_WCS\_KEY, to warn the calling program that approximations - have been made. It is then up to the calling program to decide - whether the approximations are sufficiently accurate for the - particular application, or whether more precise WCS transformations - must be performed using new-style WCS keywords directly. \label{ffgics} -\end{description} - -\begin{verbatim} - int fits_read_img_coord / ffgics - (fitsfile *fptr, > double *xrefval, double *yrefval, - double *xrefpix, double *yrefpix, double *xinc, double *yinc, - double *rot, char *coordtype, int *status) - - int fits_read_img_coord_version / ffgicsa - (fitsfile *fptr, char version, > double *xrefval, double *yrefval, - double *xrefpix, double *yrefpix, double *xinc, double *yinc, - double *rot, char *coordtype, int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Get the values of the standard FITS celestial coordinate system - keywords from the header of a FITS table where the X and Y (or RA - and DEC) coordinates are stored in 2 separate columns of the table - (as in the Event List table format that is often used by high energy - astrophysics missions). These values may then be passed to the - fits\_pix\_to\_world and fits\_world\_to\_pix routines that perform - the coordinate transformations. \label{ffgtcs} -\end{description} - -\begin{verbatim} - int fits_read_tbl_coord / ffgtcs - (fitsfile *fptr, int xcol, int ycol, > double *xrefval, - double *yrefval, double *xrefpix, double *yrefpix, double *xinc, - double *yinc, double *rot, char *coordtype, int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Calculate the celestial coordinate corresponding to the input - X and Y pixel location in the image. \label{ffwldp} -\end{description} - -\begin{verbatim} - int fits_pix_to_world / ffwldp - (double xpix, double ypix, double xrefval, double yrefval, - double xrefpix, double yrefpix, double xinc, double yinc, - double rot, char *coordtype, > double *xpos, double *ypos, - int *status) -\end{verbatim} - -\begin{description} -\item[4 ] Calculate the X and Y pixel location corresponding to the input - celestial coordinate in the image. \label{ffxypx} -\end{description} - -\begin{verbatim} - int fits_world_to_pix / ffxypx - (double xpos, double ypos, double xrefval, double yrefval, - double xrefpix, double yrefpix, double xinc, double yinc, - double rot, char *coordtype, > double *xpix, double *ypix, - int *status) -\end{verbatim} - - -\chapter{ Hierarchical Grouping Routines } - -These functions allow for the creation and manipulation of FITS HDU -Groups, as defined in "A Hierarchical Grouping Convention for FITS" by -Jennings, Pence, Folk and Schlesinger: - -http://fits.gsfc.nasa.gov/group.html - -A group is a -collection of HDUs whose association is defined by a {\it grouping -table}. HDUs which are part of a group are referred to as {\it member -HDUs} or simply as {\it members}. Grouping table member HDUs may -themselves be grouping tables, thus allowing for the construction of -open-ended hierarchies of HDUs. - -Grouping tables contain one row for each member HDU. The grouping table -columns provide identification information that allows applications to -reference or "point to" the member HDUs. Member HDUs are expected, but -not required, to contain a set of GRPIDn/GRPLCn keywords in their -headers for each grouping table that they are referenced by. In this -sense, the GRPIDn/GRPLCn keywords "link" the member HDU back to its -Grouping table. Note that a member HDU need not reside in the same FITS -file as its grouping table, and that a given HDU may be referenced by -up to 999 grouping tables simultaneously. - -Grouping tables are implemented as FITS binary tables with up to six -pre-defined column TTYPEn values: 'MEMBER\_XTENSION', 'MEMBER\_NAME', -'MEMBER\_VERSION', 'MEMBER\_POSITION', 'MEMBER\_URI\_TYPE' and 'MEMBER\_LOCATION'. -The first three columns allow member HDUs to be identified by reference to -their XTENSION, EXTNAME and EXTVER keyword values. The fourth column allows -member HDUs to be identified by HDU position within their FITS file. -The last two columns identify the FITS file in which the member HDU resides, -if different from the grouping table FITS file. - -Additional user defined "auxiliary" columns may also be included with any -grouping table. When a grouping table is copied or modified the presence of -auxiliary columns is always taken into account by the grouping support -functions; however, the grouping support functions cannot directly -make use of this data. - -If a grouping table column is defined but the corresponding member HDU -information is unavailable then a null value of the appropriate data type -is inserted in the column field. Integer columns (MEMBER\_POSITION, -MEMBER\_VERSION) are defined with a TNULLn value of zero (0). Character field -columns (MEMBER\_XTENSION, MEMBER\_NAME, MEMBER\_URI\_TYPE, MEMBER\_LOCATION) -utilize an ASCII null character to denote a null field value. - -The grouping support functions belong to two basic categories: those that -work with grouping table HDUs (ffgt**) and those that work with member HDUs -(ffgm**). Two functions, fits\_copy\_group() and fits\_remove\_group(), have the -option to recursively copy/delete entire groups. Care should be taken when -employing these functions in recursive mode as poorly defined groups could -cause unpredictable results. The problem of a grouping table directly or -indirectly referencing itself (thus creating an infinite loop) is protected -against; in fact, neither function will attempt to copy or delete an HDU -twice. - - -\section{Grouping Table Routines} - - -\begin{description} -\item[1 ]Create (append) a grouping table at the end of the current FITS file - pointed to by fptr. The grpname parameter provides the grouping table - name (GRPNAME keyword value) and may be set to NULL if no group name - is to be specified. The grouptype parameter specifies the desired - structure of the grouping table and may take on the values: - GT\_ID\_ALL\_URI (all columns created), GT\_ID\_REF (ID by reference columns), - GT\_ID\_POS (ID by position columns), GT\_ID\_ALL (ID by reference and - position columns), GT\_ID\_REF\_URI (ID by reference and FITS file URI - columns), and GT\_ID\_POS\_URI (ID by position and FITS file URI columns). \label{ffgtcr} -\end{description} - -\begin{verbatim} - int fits_create_group / ffgtcr - (fitsfile *fptr, char *grpname, int grouptype, > int *status) -\end{verbatim} - -\begin{description} -\item[2 ]Create (insert) a grouping table just after the CHDU of the current FITS - file pointed to by fptr. All HDUs below the the insertion point will be - shifted downwards to make room for the new HDU. The grpname parameter - provides the grouping table name (GRPNAME keyword value) and may be set to - NULL if no group name is to be specified. The grouptype parameter specifies - the desired structure of the grouping table and may take on the values: - GT\_ID\_ALL\_URI (all columns created), GT\_ID\_REF (ID by reference columns), - GT\_ID\_POS (ID by position columns), GT\_ID\_ALL (ID by reference and - position columns), GT\_ID\_REF\_URI (ID by reference and FITS file URI - columns), and GT\_ID\_POS\_URI (ID by position and FITS file URI columns) \label{ffgtis}. -\end{description} - -\begin{verbatim} - int fits_insert_group / ffgtis - (fitsfile *fptr, char *grpname, int grouptype, > int *status) -\end{verbatim} - -\begin{description} -\item[3 ]Change the structure of an existing grouping table pointed to by - gfptr. The grouptype parameter (see fits\_create\_group() for valid - parameter values) specifies the new structure of the grouping table. This - function only adds or removes grouping table columns, it does not add - or delete group members (i.e., table rows). If the grouping table already - has the desired structure then no operations are performed and function - simply returns with a (0) success status code. If the requested structure - change creates new grouping table columns, then the column values for all - existing members will be filled with the null values appropriate to the - column type. \label{ffgtch} -\end{description} - -\begin{verbatim} - int fits_change_group / ffgtch - (fitsfile *gfptr, int grouptype, > int *status) -\end{verbatim} - -\begin{description} -\item[4 ]Remove the group defined by the grouping table pointed to by gfptr, and - optionally all the group member HDUs. The rmopt parameter specifies the - action to be taken for - all members of the group defined by the grouping table. Valid values are: - OPT\_RM\_GPT (delete only the grouping table) and OPT\_RM\_ALL (recursively - delete all HDUs that belong to the group). Any groups containing the - grouping table gfptr as a member are updated, and if rmopt == OPT\_RM\_GPT - all members have their GRPIDn and GRPLCn keywords updated accordingly. - If rmopt == OPT\_RM\_ALL, then other groups that contain the deleted members - of gfptr are updated to reflect the deletion accordingly. \label{ffgtrm} -\end{description} - -\begin{verbatim} - int fits_remove_group / ffgtrm - (fitsfile *gfptr, int rmopt, > int *status) -\end{verbatim} - -\begin{description} -\item[5 ]Copy (append) the group defined by the grouping table pointed to by infptr, - and optionally all group member HDUs, to the FITS file pointed to by - outfptr. The cpopt parameter specifies the action to be taken for all - members of the group infptr. Valid values are: OPT\_GCP\_GPT (copy only - the grouping table) and OPT\_GCP\_ALL (recursively copy ALL the HDUs that - belong to the group defined by infptr). If the cpopt == OPT\_GCP\_GPT then - the members of infptr have their GRPIDn and GRPLCn keywords updated to - reflect the existence of the new grouping table outfptr, since they now - belong to the new group. If cpopt == OPT\_GCP\_ALL then the new - grouping table outfptr only contains pointers to the copied member HDUs - and not the original member HDUs of infptr. Note that, when - cpopt == OPT\_GCP\_ALL, all members of the group defined by infptr will be - copied to a single FITS file pointed to by outfptr regardless of their - file distribution in the original group. \label{ffgtcp} -\end{description} - -\begin{verbatim} - int fits_copy_group / ffgtcp - (fitsfile *infptr, fitsfile *outfptr, int cpopt, > int *status) -\end{verbatim} - -\begin{description} -\item[6 ] Merge the two groups defined by the grouping table HDUs infptr and outfptr - by combining their members into a single grouping table. All member HDUs - (rows) are copied from infptr to outfptr. If mgopt == OPT\_MRG\_COPY then - infptr continues to exist unaltered after the merge. If the mgopt == - OPT\_MRG\_MOV then infptr is deleted after the merge. In both cases, - the GRPIDn and GRPLCn keywords of the member HDUs are updated accordingly. \label{ffgtmg} -\end{description} - -\begin{verbatim} - int fits_merge_groups / ffgtmg - (fitsfile *infptr, fitsfile *outfptr, int mgopt, > int *status) -\end{verbatim} - -\begin{description} -\item[7 ]"Compact" the group defined by grouping table pointed to by gfptr. The - compaction is achieved by merging (via fits\_merge\_groups()) all direct - member HDUs of gfptr that are themselves grouping tables. The cmopt - parameter defines whether the merged grouping table HDUs remain after - merging (cmopt == OPT\_CMT\_MBR) or if they are deleted after merging - (cmopt == OPT\_CMT\_MBR\_DEL). If the grouping table contains no direct - member HDUs that are themselves grouping tables then this function - does nothing. Note that this function is not recursive, i.e., only the - direct member HDUs of gfptr are considered for merging. \label{ffgtcm} -\end{description} - -\begin{verbatim} - int fits_compact_group / ffgtcm - (fitsfile *gfptr, int cmopt, > int *status) -\end{verbatim} - -\begin{description} -\item[8 ]Verify the integrity of the grouping table pointed to by gfptr to make - sure that all group members are accessible and that all links to other - grouping tables are valid. The firstfailed parameter returns the member - ID (row number) of the first member HDU to fail verification (if positive - value) or the first group link to fail (if negative value). If gfptr is - successfully verified then firstfailed contains a return value of 0. \label{ffgtvf} -\end{description} - -\begin{verbatim} - int fits_verify_group / ffgtvf - (fitsfile *gfptr, > long *firstfailed, int *status) -\end{verbatim} - -\begin{description} -\item[9 ] Open a grouping table that contains the member HDU pointed to by mfptr. - The grouping table to open is defined by the grpid parameter, which - contains the keyword index value of the GRPIDn/GRPLCn keyword(s) that - link the member HDU mfptr to the grouping table. If the grouping table - resides in a file other than the member HDUs file then an attempt is - first made to open the file readwrite, and failing that readonly. A - pointer to the opened grouping table HDU is returned in gfptr. - - Note that it is possible, although unlikely and undesirable, for the - GRPIDn/GRPLCn keywords in a member HDU header to be non-continuous, e.g., - GRPID1, GRPID2, GRPID5, GRPID6. In such cases, the grpid index value - specified in the function call shall identify the (grpid)th GRPID value. - In the above example, if grpid == 3, then the group specified by GRPID5 - would be opened. \label{ffgtop} -\end{description} - -\begin{verbatim} - int fits_open_group / ffgtop - (fitsfile *mfptr, int group, > fitsfile **gfptr, int *status) -\end{verbatim} - -\begin{description} -\item[10] Add a member HDU to an existing grouping table pointed to by gfptr. - The member HDU may either be pointed to mfptr (which must be positioned - to the member HDU) or, if mfptr == NULL, identified by the hdupos parameter - (the HDU position number, Primary array == 1) if both the grouping table - and the member HDU reside in the same FITS file. The new member HDU shall - have the appropriate GRPIDn and GRPLCn keywords created in its header. - Note that if the member HDU is already a member of the group then it will - not be added a second time. \label{ffgtam} -\end{description} - -\begin{verbatim} - int fits_add_group_member / ffgtam - (fitsfile *gfptr, fitsfile *mfptr, int hdupos, > int *status) -\end{verbatim} - - -\section{Group Member Routines} - - -\begin{description} -\item[1 ] Return the number of member HDUs in a grouping table gfptr. The number - member HDUs is just the NAXIS2 value (number of rows) of the grouping - table. \label{ffgtnm} -\end{description} - -\begin{verbatim} - int fits_get_num_members / ffgtnm - (fitsfile *gfptr, > long *nmembers, int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Return the number of groups to which the HDU pointed to by mfptr is - linked, as defined by the number of GRPIDn/GRPLCn keyword records that - appear in its header. Note that each time this function is called, the - indices of the GRPIDn/GRPLCn keywords are checked to make sure they - are continuous (ie no gaps) and are re-enumerated to eliminate gaps if - found. \label{ffgmng} -\end{description} - -\begin{verbatim} - int fits_get_num_groups / ffgmng - (fitsfile *mfptr, > long *nmembers, int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Open a member of the grouping table pointed to by gfptr. The member to - open is identified by its row number within the grouping table as given - by the parameter 'member' (first member == 1) . A fitsfile pointer to - the opened member HDU is returned as mfptr. Note that if the member HDU - resides in a FITS file different from the grouping table HDU then the - member file is first opened readwrite and, failing this, opened readonly. \label{ffgmop} -\end{description} - -\begin{verbatim} - int fits_open_member / ffgmop - (fitsfile *gfptr, long member, > fitsfile **mfptr, int *status) -\end{verbatim} - -\begin{description} -\item[4 ]Copy (append) a member HDU of the grouping table pointed to by gfptr. - The member HDU is identified by its row number within the grouping table - as given by the parameter 'member' (first member == 1). The copy of the - group member HDU will be appended to the FITS file pointed to by mfptr, - and upon return mfptr shall point to the copied member HDU. The cpopt - parameter may take on the following values: OPT\_MCP\_ADD which adds a new - entry in gfptr for the copied member HDU, OPT\_MCP\_NADD which does not add - an entry in gfptr for the copied member, and OPT\_MCP\_REPL which replaces - the original member entry with the copied member entry. \label{ffgmcp} -\end{description} - -\begin{verbatim} - int fits_copy_member / ffgmcp - (fitsfile *gfptr, fitsfile *mfptr, long member, int cpopt, > int *status) -\end{verbatim} - -\begin{description} -\item[5 ]Transfer a group member HDU from the grouping table pointed to by - infptr to the grouping table pointed to by outfptr. The member HDU to - transfer is identified by its row number within infptr as specified by - the parameter 'member' (first member == 1). If tfopt == OPT\_MCP\_ADD then - the member HDU is made - a member of outfptr and remains a member of infptr. If tfopt == OPT\_MCP\_MOV - then the member HDU is deleted from infptr after the transfer to outfptr. \label{ffgmtf} -\end{description} - -\begin{verbatim} - int fits_transfer_member / ffgmtf - (fitsfile *infptr, fitsfile *outfptr, long member, int tfopt, - > int *status) -\end{verbatim} - -\begin{description} -\item[6 ]Remove a member HDU from the grouping table pointed to by gfptr. The - member HDU to be deleted is identified by its row number in the grouping - table as specified by the parameter 'member' (first member == 1). The rmopt - parameter may take on the following values: OPT\_RM\_ENTRY which - removes the member HDU entry from the grouping table and updates the - member's GRPIDn/GRPLCn keywords, and OPT\_RM\_MBR which removes the member - HDU entry from the grouping table and deletes the member HDU itself. \label{ffgmrm} -\end{description} - -\begin{verbatim} - int fits_remove_member / ffgmrm - (fitsfile *fptr, long member, int rmopt, > int *status) -\end{verbatim} - -\chapter{ Specialized CFITSIO Interface Routines } - -The basic interface routines described previously are recommended -for most uses, but the routines described in this chapter -are also available if necessary. Some of these routines perform more -specialized function that cannot easily be done with the basic -interface routines while others duplicate the functionality of the -basic routines but have a slightly different calling sequence. -See Appendix B for the definition of each function parameter. - - -\section{FITS File Access Routines} - - -\begin{description} -\item[1 ] Open an existing FITS file residing in core computer memory. This -routine is analogous to fits\_open\_file. The 'filename' is -currently ignored by this routine and may be any arbitrary string. In -general, the application must have preallocated an initial block of -memory to hold the FITS file prior to calling this routine: 'memptr' -points to the starting address and 'memsize' gives the initial size of -the block of memory. 'mem\_realloc' is a pointer to an optional -function that CFITSIO can call to allocate additional memory, if needed -(only if mode = READWRITE), and is modeled after the standard C -'realloc' function; a null pointer may be given if the initial -allocation of memory is all that will be required (e.g., if the file is -opened with mode = READONLY). The 'deltasize' parameter may be used to -suggest a minimum amount of additional memory that should be allocated -during each call to the memory reallocation function. By default, -CFITSIO will reallocate enough additional space to hold the entire -currently defined FITS file (as given by the NAXISn keywords) or 1 FITS -block (= 2880 bytes), which ever is larger. Values of deltasize less -than 2880 will be ignored. Since the memory reallocation operation can -be computationally expensive, allocating a larger initial block of -memory, and/or specifying a larger deltasize value may help to reduce -the number of reallocation calls and make the application program run -faster. Note that values of the memptr and memsize pointers will be updated -by CFITSIO if the location or size of the FITS file in memory -should change as a result of allocating more memory. \label{ffomem} -\end{description} - -\begin{verbatim} - int fits_open_memfile / ffomem - (fitsfile **fptr, const char *filename, int mode, void **memptr, - size_t *memsize, size_t deltasize, - void *(*mem_realloc)(void *p, size_t newsize), int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Create a new FITS file residing in core computer memory. This -routine is analogous to fits\_create\_file. In general, the -application must have preallocated an initial block of memory to hold -the FITS file prior to calling this routine: 'memptr' points to the -starting address and 'memsize' gives the initial size of the block of -memory. 'mem\_realloc' is a pointer to an optional function that -CFITSIO can call to allocate additional memory, if needed, and is -modeled after the standard C 'realloc' function; a null pointer may be -given if the initial allocation of memory is all that will be -required. The 'deltasize' parameter may be used to suggest a minimum -amount of additional memory that should be allocated during each call -to the memory reallocation function. By default, CFITSIO will -reallocate enough additional space to hold 1 FITS block (= 2880 bytes) -and values of deltasize less than 2880 will be ignored. Since the -memory reallocation operation can be computationally expensive, -allocating a larger initial block of memory, and/or specifying a larger -deltasize value may help to reduce the number of reallocation calls -and make the application program run -faster. Note that values of the memptr and memsize pointers will be updated -by CFITSIO if the location or size of the FITS file in memory -should change as a result of allocating more memory. \label{ffimem} -\end{description} - -\begin{verbatim} - int fits_create_memfile / ffimem - (fitsfile **fptr, void **memptr, - size_t *memsize, size_t deltasize, - void *(*mem_realloc)(void *p, size_t newsize), int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Reopen a FITS file that was previously opened with - fits\_open\_file or fits\_create\_file. The new fitsfile - pointer may then be treated as a separate file, and one may - simultaneously read or write to 2 (or more) different extensions in - the same file. The fits\_open\_file routine (above) automatically - detects cases where a previously opened file is being opened again, - and then internally call fits\_reopen\_file, so programs should rarely - need to explicitly call this routine. -\label{ffreopen} -\end{description} - -\begin{verbatim} - int fits_reopen_file / ffreopen - (fitsfile *openfptr, fitsfile **newfptr, > int *status) -\end{verbatim} - - -\begin{description} -\item[4 ] Create a new FITS file, using a template file to define its - initial size and structure. The template may be another FITS HDU - or an ASCII template file. If the input template file name pointer - is null, then this routine behaves the same as fits\_create\_file. - The currently supported format of the ASCII template file is described - under the fits\_parse\_template routine (in the general Utilities - section) -\label{fftplt} -\end{description} - -\begin{verbatim} - int fits_create_template / fftplt - (fitsfile **fptr, char *filename, char *tpltfile > int *status) -\end{verbatim} - - -\begin{description} -\item[5 ] Parse the input filename or URL into its component parts, namely: -\begin{itemize} -\item -the file type (file://, ftp://, http://, etc), -\item -the base input file name, -\item -the name of the output file that the input file is to be copied to prior -to opening, -\item -the HDU or extension specification, -\item -the filtering specifier, -\item -the binning specifier, -\item -the column specifier, -\item -and the -image pixel filtering specifier. -\end{itemize} -A null pointer (0) may be be specified for any of the output string arguments -that are not needed. Null strings will be returned for any components that are not -present in the input file name. The calling routine must allocate sufficient -memory to hold the returned character strings. Allocating the string lengths -equal to FLEN\_FILENAME is guaranteed to be safe. -These routines are mainly for internal use -by other CFITSIO routines. \label{ffiurl} -\end{description} - -\begin{verbatim} - int fits_parse_input_url / ffiurl - (char *filename, > char *filetype, char *infile, char *outfile, char - *extspec, char *filter, char *binspec, char *colspec, int *status) - - int fits_parse_input_filename / ffifile - (char *filename, > char *filetype, char *infile, char *outfile, char - *extspec, char *filter, char *binspec, char *colspec, char *pixspec, - int *status) -\end{verbatim} - -\begin{description} -\item[6 ] Parse the input filename and return the HDU number that would be -moved to if the file were opened with fits\_open\_file. The returned -HDU number begins with 1 for the primary array, so for example, if the -input filename = `myfile.fits[2]' then hdunum = 3 will be returned. -CFITSIO does not open the file to check if the extension actually -exists if an extension number is specified. If an extension name is -included in the file name specification (e.g. `myfile.fits[EVENTS]' -then this routine will have to open the FITS file and look for the -position of the named extension, then close file again. This is not -possible if the file is being read from the stdin stream, and an error -will be returned in this case. If the filename does not specify an -explicit extension (e.g. 'myfile.fits') then hdunum = -99 will be -returned, which is functionally equivalent to hdunum = 1. This routine -is mainly used for backward compatibility in the ftools software -package and is not recommended for general use. It is generally better -and more efficient to first open the FITS file with fits\_open\_file, -then use fits\_get\_hdu\_num to determine which HDU in the file has -been opened, rather than calling fits\_parse\_input\_url followed by a -call to fits\_open\_file. - \label{ffextn} -\end{description} - -\begin{verbatim} - int fits_parse_extnum / ffextn - (char *filename, > int *hdunum, int *status) -\end{verbatim} - -\begin{description} -\item[7 ]Parse the input file name and return the root file name. The root -name includes the file type if specified, (e.g. 'ftp://' or 'http://') -and the full path name, to the extent that it is specified in the input -filename. It does not include the HDU name or number, or any filtering -specifications. The calling routine must allocate sufficient -memory to hold the returned rootname character string. Allocating the length -equal to FLEN\_FILENAME is guaranteed to be safe. - \label{ffrtnm} -\end{description} - -\begin{verbatim} - int fits_parse_rootname / ffrtnm - (char *filename, > char *rootname, int *status); -\end{verbatim} - -\begin{description} -\item[8 ]Test if the input file or a compressed version of the file (with -a .gz, .Z, .z, or .zip extension) exists on disk. The returned value of -the 'exists' parameter will have 1 of the 4 following values: - -\begin{verbatim} - 2: the file does not exist, but a compressed version does exist - 1: the disk file does exist - 0: neither the file nor a compressed version of the file exist - -1: the input file name is not a disk file (could be a ftp, http, - smem, or mem file, or a file piped in on the STDIN stream) -\end{verbatim} - - \label{ffexist} -\end{description} - -\begin{verbatim} - int fits_file_exists / ffexist - (char *filename, > int *exists, int *status); -\end{verbatim} - -\begin{description} -\item[9 ]Flush any internal buffers of data to the output FITS file. These - routines rarely need to be called, but can be useful in cases where - other processes need to access the same FITS file in real time, - either on disk or in memory. These routines also help to ensure - that if the application program subsequently aborts then the FITS - file will have been closed properly. The first routine, - fits\_flush\_file is more rigorous and completely closes, then - reopens, the current HDU, before flushing the internal buffers, thus - ensuring that the output FITS file is identical to what would be - produced if the FITS was closed at that point (i.e., with a call to - fits\_close\_file). The second routine, fits\_flush\_buffer simply - flushes the internal CFITSIO buffers of data to the output FITS - file, without updating and closing the current HDU. This is much - faster, but there may be circumstances where the flushed file does - not completely reflect the final state of the file as it will exist - when the file is actually closed. - - A typical use of these routines would be to flush the state of a - FITS table to disk after each row of the table is written. It is - recommend that fits\_flush\_file be called after the first row is - written, then fits\_flush\_buffer may be called after each - subsequent row is written. Note that this latter routine will not - automatically update the NAXIS2 keyword which records the number of - rows of data in the table, so this keyword must be explicitly - updated by the application program after each row is written. - \label{ffflus} -\end{description} - -\begin{verbatim} - int fits_flush_file / ffflus - (fitsfile *fptr, > int *status) - - int fits_flush_buffer / ffflsh - (fitsfile *fptr, 0, > int *status) - - (Note: The second argument must be 0). -\end{verbatim} - - -\section{HDU Access Routines} - - -\begin{description} -\item[1 ] Get the byte offsets in the FITS file to the start of the header - and the start and end of the data in the CHDU. The difference - between headstart and dataend equals the size of the CHDU. If the - CHDU is the last HDU in the file, then dataend is also equal to the - size of the entire FITS file. Null pointers may be input for any - of the address parameters if their values are not needed. \label{ffghad} -\end{description} - -\begin{verbatim} - int fits_get_hduaddr / ffghad (only supports files up to 2.1 GB in size) - (fitsfile *fptr, > long *headstart, long *datastart, long *dataend, - int *status) - - int fits_get_hduaddrll / ffghadll (supports large files) - (fitsfile *fptr, > LONGLONG *headstart, LONGLONG *datastart, - LONGLONG *dataend, int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Create (append) a new empty HDU at the end of the FITS file. - This is now the CHDU but it is completely empty and has - no header keywords. It is recommended that fits\_create\_img or - fits\_create\_tbl be used instead of this routine. \label{ffcrhd} -\end{description} - -\begin{verbatim} - int fits_create_hdu / ffcrhd - (fitsfile *fptr, > int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Insert a new IMAGE extension immediately following the CHDU, or - insert a new Primary Array at the beginning of the file. Any - following extensions in the file will be shifted down to make room - for the new extension. If the CHDU is the last HDU in the file - then the new image extension will simply be appended to the end of - the file. One can force a new primary array to be inserted at the - beginning of the FITS file by setting status = PREPEND\_PRIMARY prior - to calling the routine. In this case the old primary array will be - converted to an IMAGE extension. The new extension (or primary - array) will become the CHDU. Refer to Chapter 9 for a list of - pre-defined bitpix values. \label{ffiimg} -\end{description} - -\begin{verbatim} - int fits_insert_img / ffiimg - (fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) - - int fits_insert_imgll / ffiimgll - (fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) -\end{verbatim} - -\begin{description} -\item[4 ] Insert a new ASCII or binary table extension immediately following the CHDU. - Any following extensions will be shifted down to make room for the - new extension. If there are no other following extensions then the - new table extension will simply be appended to the end of the - file. If the FITS file is currently empty then this routine will - create a dummy primary array before appending the table to it. The - new extension will become the CHDU. The tunit and extname - parameters are optional and a null pointer may be given if they are - not defined. When inserting an ASCII table with - fits\_insert\_atbl, a null pointer may given for the *tbcol - parameter in which case each column of the table will be separated - by a single space character. Similarly, if the input value of - rowlen is 0, then CFITSIO will calculate the default rowlength - based on the tbcol and ttype values. Under normal circumstances, - the nrows - paramenter should have a value of 0; CFITSIO will automatically update - the number of rows as data is written to the table. When inserting a binary table - with fits\_insert\_btbl, if there are following extensions in the - file and if the table contains variable length array columns then - pcount must specify the expected final size of the data heap, - otherwise pcount must = 0. \label{ffitab} \label{ffibin} -\end{description} - -\begin{verbatim} - int fits_insert_atbl / ffitab - (fitsfile *fptr, LONGLONG rowlen, LONGLONG nrows, int tfields, char *ttype[], - long *tbcol, char *tform[], char *tunit[], char *extname, > int *status) - - int fits_insert_btbl / ffibin - (fitsfile *fptr, LONGLONG nrows, int tfields, char **ttype, - char **tform, char **tunit, char *extname, long pcount, > int *status) -\end{verbatim} - -\begin{description} -\item[5 ] Modify the size, dimensions, and/or data type of the current - primary array or image extension. If the new image, as specified - by the input arguments, is larger than the current existing image - in the FITS file then zero fill data will be inserted at the end - of the current image and any following extensions will be moved - further back in the file. Similarly, if the new image is - smaller than the current image then any following extensions - will be shifted up towards the beginning of the FITS file - and the image data will be truncated to the new size. - This routine rewrites the BITPIX, NAXIS, and NAXISn keywords - with the appropriate values for the new image. \label{ffrsim} -\end{description} - -\begin{verbatim} - int fits_resize_img / ffrsim - (fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) - - int fits_resize_imgll / ffrsimll - (fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) -\end{verbatim} - -\begin{description} -\item[6 ] Copy the data (and not the header) from the CHDU associated with infptr - to the CHDU associated with outfptr. This will overwrite any data - previously in the output CHDU. This low level routine is used by - fits\_copy\_hdu, but it may also be useful in certain application programs - that want to copy the data from one FITS file to another but also - want to modify the header keywords. The required FITS header keywords - which define the structure of the HDU must be written to the - output CHDU before calling this routine. \label{ffcpdt} -\end{description} - -\begin{verbatim} - int fits_copy_data / ffcpdt - (fitsfile *infptr, fitsfile *outfptr, > int *status) -\end{verbatim} - -\begin{description} -\item[7 ] Read or write a specified number of bytes starting at the specified byte - offset from the start of the extension data unit. These low - level routine are intended mainly for accessing the data in - non-standard, conforming extensions, and should not be used for standard - IMAGE, TABLE, or BINTABLE extensions. \label{ffgextn} -\end{description} - -\begin{verbatim} - int fits_read_ext / ffgextn - (fitsfile *fptr, LONGLONG offset, LONGLONG nbytes, void *buffer) - int fits_write_ext / ffpextn - (fitsfile *fptr, LONGLONG offset, LONGLONG nbytes, void *buffer) -\end{verbatim} - -\begin{description} -\item[8 ] This routine forces CFITSIO to rescan the current header keywords that - define the structure of the HDU (such as the NAXIS and BITPIX - keywords) so that it reinitializes the internal buffers that - describe the HDU structure. This routine is useful for - reinitializing the structure of an HDU if any of the required - keywords (e.g., NAXISn) have been modified. In practice it should - rarely be necessary to call this routine because CFITSIO - internally calls it in most situations. \label{ffrdef} -\end{description} - -\begin{verbatim} - int fits_set_hdustruc / ffrdef - (fitsfile *fptr, > int *status) (DEPRECATED) -\end{verbatim} - -\section{Specialized Header Keyword Routines} - - -\subsection{Header Information Routines} - - -\begin{description} -\item[1 ] Reserve space in the CHU for MOREKEYS more header keywords. - This routine may be called to allocate space for additional keywords - at the time the header is created (prior to writing any data). - CFITSIO can dynamically add more space to the header when needed, - however it is more efficient to preallocate the required space - if the size is known in advance. \label{ffhdef} -\end{description} - -\begin{verbatim} - int fits_set_hdrsize / ffhdef - (fitsfile *fptr, int morekeys, > int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Return the number of keywords in the header (not counting the END - keyword) and the current position - in the header. The position is the number of the keyword record that - will be read next (or one greater than the position of the last keyword - that was read). A value of 1 is returned if the pointer is - positioned at the beginning of the header. \label{ffghps} -\end{description} - -\begin{verbatim} - int fits_get_hdrpos / ffghps - (fitsfile *fptr, > int *keysexist, int *keynum, int *status) -\end{verbatim} - - -\subsection{Read and Write the Required Keywords} - - -\begin{description} -\item[1 ] Write the required extension header keywords into the CHU. - These routines are not required, and instead the appropriate - header may be constructed by writing each individual keyword in the - proper sequence. - - The simpler fits\_write\_imghdr routine is equivalent to calling - fits\_write\_grphdr with the default values of simple = TRUE, pcount - = 0, gcount = 1, and extend = TRUE. The PCOUNT, GCOUNT and EXTEND - keywords are not required in the primary header and are only written - if pcount is not equal to zero, gcount is not equal to zero or one, - and if extend is TRUE, respectively. When writing to an IMAGE - extension, the SIMPLE and EXTEND parameters are ignored. It is - recommended that fits\_create\_image or fits\_create\_tbl be used - instead of these routines to write the - required header keywords. The general fits\_write\_exthdr routine - may be used to write the header of any conforming FITS - extension. \label{ffphpr} \label{ffphps} -\end{description} - -\begin{verbatim} - int fits_write_imghdr / ffphps - (fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) - - int fits_write_imghdrll / ffphpsll - (fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) - - int fits_write_grphdr / ffphpr - (fitsfile *fptr, int simple, int bitpix, int naxis, long *naxes, - LONGLONG pcount, LONGLONG gcount, int extend, > int *status) - - int fits_write_grphdrll / ffphprll - (fitsfile *fptr, int simple, int bitpix, int naxis, LONGLONG *naxes, - LONGLONG pcount, LONGLONG gcount, int extend, > int *status) - - int fits_write_exthdr /ffphext - (fitsfile *fptr, char *xtension, int bitpix, int naxis, long *naxes, - LONGLONG pcount, LONGLONG gcount, > int *status) - -\end{verbatim} - -\begin{description} -\item[2 ] Write the ASCII table header keywords into the CHU. The optional - TUNITn and EXTNAME keywords are written only if the input pointers - are not null. A null pointer may given for the - *tbcol parameter in which case a single space will be inserted - between each column of the table. Similarly, if rowlen is - given = 0, then CFITSIO will calculate the default rowlength based on - the tbcol and ttype values. \label{ffphtb} -\end{description} - -\begin{verbatim} - int fits_write_atblhdr / ffphtb - (fitsfile *fptr, LONGLONG rowlen, LONGLONG nrows, int tfields, char **ttype, - long *tbcol, char **tform, char **tunit, char *extname, > int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Write the binary table header keywords into the CHU. The optional - TUNITn and EXTNAME keywords are written only if the input pointers - are not null. The pcount parameter, which specifies the - size of the variable length array heap, should initially = 0; - CFITSIO will automatically update the PCOUNT keyword value if any - variable length array data is written to the heap. The TFORM keyword - value for variable length vector columns should have the form 'Pt(len)' - or '1Pt(len)' where `t' is the data type code letter (A,I,J,E,D, etc.) - and `len' is an integer specifying the maximum length of the vectors - in that column (len must be greater than or equal to the longest - vector in the column). If `len' is not specified when the table is - created (e.g., the input TFORMn value is just '1Pt') then CFITSIO will - scan the column when the table is first closed and will append the - maximum length to the TFORM keyword value. Note that if the table - is subsequently modified to increase the maximum length of the vectors - then the modifying program is responsible for also updating the TFORM - keyword value. \label{ffphbn} -\end{description} - -\begin{verbatim} - int fits_write_btblhdr / ffphbn - (fitsfile *fptr, LONGLONG nrows, int tfields, char **ttype, - char **tform, char **tunit, char *extname, LONGLONG pcount, > int *status) -\end{verbatim} - -\begin{description} -\item[4 ] Read the required keywords from the CHDU (image or table). When - reading from an IMAGE extension the SIMPLE and EXTEND parameters are - ignored. A null pointer may be supplied for any of the returned - parameters that are not needed. \label{ffghpr} \label{ffghtb} \label{ffghbn} -\end{description} - -\begin{verbatim} - int fits_read_imghdr / ffghpr - (fitsfile *fptr, int maxdim, > int *simple, int *bitpix, int *naxis, - long *naxes, long *pcount, long *gcount, int *extend, int *status) - - int fits_read_imghdrll / ffghprll - (fitsfile *fptr, int maxdim, > int *simple, int *bitpix, int *naxis, - LONGLONG *naxes, long *pcount, long *gcount, int *extend, int *status) - - int fits_read_atblhdr / ffghtb - (fitsfile *fptr,int maxdim, > long *rowlen, long *nrows, - int *tfields, char **ttype, LONGLONG *tbcol, char **tform, char **tunit, - char *extname, int *status) - - int fits_read_atblhdrll / ffghtbll - (fitsfile *fptr,int maxdim, > LONGLONG *rowlen, LONGLONG *nrows, - int *tfields, char **ttype, long *tbcol, char **tform, char **tunit, - char *extname, int *status) - - int fits_read_btblhdr / ffghbn - (fitsfile *fptr, int maxdim, > long *nrows, int *tfields, - char **ttype, char **tform, char **tunit, char *extname, - long *pcount, int *status) - - int fits_read_btblhdrll / ffghbnll - (fitsfile *fptr, int maxdim, > LONGLONG *nrows, int *tfields, - char **ttype, char **tform, char **tunit, char *extname, - long *pcount, int *status) -\end{verbatim} - -\subsection{Write Keyword Routines} - -These routines simply append a new keyword to the header and do not -check to see if a keyword with the same name already exists. In -general it is preferable to use the fits\_update\_key routine to ensure -that the same keyword is not written more than once to the header. See -Appendix B for the definition of the parameters used in these -routines. - - - -\begin{description} -\item[1 ] Write (append) a new keyword of the appropriate data type into the CHU. - A null pointer may be entered for the comment parameter, which - will cause the comment field of the keyword to be left blank. The - flt, dbl, cmp, and dblcmp versions of this routine have the added - feature that if the 'decimals' parameter is negative, then the 'G' - display format rather then the 'E' format will be used when - constructing the keyword value, taking the absolute value of - 'decimals' for the precision. This will suppress trailing zeros, - and will use a fixed format rather than an exponential format, - depending on the magnitude of the value. \label{ffpkyx} -\end{description} - -\begin{verbatim} - int fits_write_key_str / ffpkys - (fitsfile *fptr, char *keyname, char *value, char *comment, - > int *status) - - int fits_write_key_[log, lng] / ffpky[lj] - (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, - > int *status) - - int fits_write_key_[flt, dbl, fixflg, fixdbl] / ffpky[edfg] - (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, - char *comment, > int *status) - - int fits_write_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffpk[yc,ym,fc,fm] - (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, - char *comment, > int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Write (append) a string valued keyword into the CHU which may be longer - than 68 characters in length. This uses the Long String Keyword - convention that is described in the`Local FITS Conventions' section - in Chapter 4. Since this uses a non-standard FITS convention to - encode the long keyword string, programs which use this routine - should also call the fits\_write\_key\_longwarn routine to add some - COMMENT keywords to warn users of the FITS file that this - convention is being used. The fits\_write\_key\_longwarn routine - also writes a keyword called LONGSTRN to record the version of the - longstring convention that has been used, in case a new convention - is adopted at some point in the future. If the LONGSTRN keyword - is already present in the header, then fits\_write\_key\_longwarn - will - simply return without doing anything. \label{ffpkls} \label{ffplsw} -\end{description} - -\begin{verbatim} - int fits_write_key_longstr / ffpkls - (fitsfile *fptr, char *keyname, char *longstr, char *comment, - > int *status) - - int fits_write_key_longwarn / ffplsw - (fitsfile *fptr, > int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Write (append) a numbered sequence of keywords into the CHU. The - starting index number (nstart) must be greater than 0. One may - append the same comment to every keyword (and eliminate the need - to have an array of identical comment strings, one for each keyword) by - including the ampersand character as the last non-blank character in the - (first) COMMENTS string parameter. This same string - will then be used for the comment field in all the keywords. - One may also enter a null pointer for the comment parameter to - leave the comment field of the keyword blank. \label{ffpknx} -\end{description} - -\begin{verbatim} - int fits_write_keys_str / ffpkns - (fitsfile *fptr, char *keyroot, int nstart, int nkeys, - char **value, char **comment, > int *status) - - int fits_write_keys_[log, lng] / ffpkn[lj] - (fitsfile *fptr, char *keyroot, int nstart, int nkeys, - DTYPE *numval, char **comment, int *status) - - int fits_write_keys_[flt, dbl, fixflg, fixdbl] / ffpkne[edfg] - (fitsfile *fptr, char *keyroot, int nstart, int nkey, - DTYPE *numval, int decimals, char **comment, > int *status) -\end{verbatim} - -\begin{description} -\item[4 ]Copy an indexed keyword from one HDU to another, modifying - the index number of the keyword name in the process. For example, - this routine could read the TLMIN3 keyword from the input HDU - (by giving keyroot = `TLMIN' and innum = 3) and write it to the - output HDU with the keyword name TLMIN4 (by setting outnum = 4). - If the input keyword does not exist, then this routine simply - returns without indicating an error. \label{ffcpky} -\end{description} - -\begin{verbatim} - int fits_copy_key / ffcpky - (fitsfile *infptr, fitsfile *outfptr, int innum, int outnum, - char *keyroot, > int *status) -\end{verbatim} - -\begin{description} -\item[5 ]Write (append) a `triple precision' keyword into the CHU in F28.16 format. - The floating point keyword value is constructed by concatenating the - input integer value with the input double precision fraction value - (which must have a value between 0.0 and 1.0). The ffgkyt routine should - be used to read this keyword value, because the other keyword reading - routines will not preserve the full precision of the value. \label{ffpkyt} -\end{description} - -\begin{verbatim} - int fits_write_key_triple / ffpkyt - (fitsfile *fptr, char *keyname, long intval, double frac, - char *comment, > int *status) -\end{verbatim} - -\begin{description} -\item[6 ]Write keywords to the CHDU that are defined in an ASCII template file. - The format of the template file is described under the fits\_parse\_template - routine. \label{ffpktp} -\end{description} - -\begin{verbatim} - int fits_write_key_template / ffpktp - (fitsfile *fptr, const char *filename, > int *status) -\end{verbatim} - -\subsection{Insert Keyword Routines} - -These insert routines are somewhat less efficient than the `update' or -`write' keyword routines because the following keywords in the header -must be shifted down to make room for the inserted keyword. See -Appendix B for the definition of the parameters used in these -routines. - - -\begin{description} -\item[1 ] Insert a new keyword record into the CHU at the specified position - (i.e., immediately preceding the (keynum)th keyword in the header.) - \label{ffirec} -\end{description} - -\begin{verbatim} - int fits_insert_record / ffirec - (fitsfile *fptr, int keynum, char *card, > int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Insert a new keyword into the CHU. The new keyword is inserted - immediately following the last keyword that has been read from the - header. The `longstr' version has the same functionality as the - `str' version except that it also supports the local long string - keyword convention for strings longer than 68 characters. A null - pointer may be entered for the comment parameter which will cause - the comment field to be left blank. The flt, dbl, cmp, and dblcmp - versions of this routine have the added - feature that if the 'decimals' parameter is negative, then the 'G' - display format rather then the 'E' format will be used when - constructing the keyword value, taking the absolute value of - 'decimals' for the precision. This will suppress trailing zeros, - and will use a fixed format rather than an exponential format, - depending on the magnitude of the value. \label{ffikyx} -\end{description} - -\begin{verbatim} - int fits_insert_card / ffikey - (fitsfile *fptr, char *card, > int *status) - - int fits_insert_key_[str, longstr] / ffi[kys, kls] - (fitsfile *fptr, char *keyname, char *value, char *comment, - > int *status) - - int fits_insert_key_[log, lng] / ffiky[lj] - (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, - > int *status) - - int fits_insert_key_[flt, fixflt, dbl, fixdbl] / ffiky[edfg] - (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, - char *comment, > int *status) - - int fits_insert_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffik[yc,ym,fc,fm] - (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, - char *comment, > int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Insert a new keyword with an undefined, or null, value into the CHU. - The value string of the keyword is left blank in this case. \label{ffikyu} -\end{description} - -\begin{verbatim} - int fits_insert_key_null / ffikyu - (fitsfile *fptr, char *keyname, char *comment, > int *status) -\end{verbatim} - - -\subsection{Read Keyword Routines} - -Wild card characters may be used when specifying the name of the -keyword to be read. - - -\begin{description} -\item[1 ] Read a keyword value (with the appropriate data type) and comment from - the CHU. If a NULL comment pointer is given on input, then the comment - string will not be returned. If the value of the keyword is not defined - (i.e., the value field is blank) then an error status = VALUE\_UNDEFINED - will be returned and the input value will not be changed (except that - ffgkys will reset the value to a null string). - \label{ffgkyx} \label{ffgkls} -\end{description} - -\begin{verbatim} - int fits_read_key_str / ffgkys - (fitsfile *fptr, char *keyname, > char *value, char *comment, - int *status); - - NOTE: after calling the following routine, programs must explicitly free - the memory allocated for 'longstr' after it is no longer needed by - calling fits_free_memory. - - int fits_read_key_longstr / ffgkls - (fitsfile *fptr, char *keyname, > char **longstr, char *comment, - int *status) - - int fits_free_memory / fffree - (char *longstr, > int *status); - - int fits_read_key_[log, lng, flt, dbl, cmp, dblcmp] / ffgky[ljedcm] - (fitsfile *fptr, char *keyname, > DTYPE *numval, char *comment, - int *status) - - int fits_read_key_lnglng / ffgkyjj - (fitsfile *fptr, char *keyname, > LONGLONG *numval, char *comment, - int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Read a sequence of indexed keyword values (e.g., NAXIS1, NAXIS2, ...). - The input starting index number (nstart) must be greater than 0. - If the value of any of the keywords is not defined (i.e., the value - field is blank) then an error status = VALUE\_UNDEFINED will be - returned and the input value for the undefined keyword(s) will not - be changed. These routines do not support wild card characters in - the root name. If there are no indexed keywords in the header with - the input root name then these routines do not return a non-zero - status value and instead simply return nfound = 0. \label{ffgknx} -\end{description} - -\begin{verbatim} - int fits_read_keys_str / ffgkns - (fitsfile *fptr, char *keyname, int nstart, int nkeys, - > char **value, int *nfound, int *status) - - int fits_read_keys_[log, lng, flt, dbl] / ffgkn[ljed] - (fitsfile *fptr, char *keyname, int nstart, int nkeys, - > DTYPE *numval, int *nfound, int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Read the value of a floating point keyword, returning the integer and - fractional parts of the value in separate routine arguments. - This routine may be used to read any keyword but is especially - useful for reading the 'triple precision' keywords written by ffpkyt. - \label{ffgkyt} -\end{description} - -\begin{verbatim} - int fits_read_key_triple / ffgkyt - (fitsfile *fptr, char *keyname, > long *intval, double *frac, - char *comment, int *status) -\end{verbatim} - -\subsection{Modify Keyword Routines} - -These routines modify the value of an existing keyword. An error is -returned if the keyword does not exist. Wild card characters may be -used when specifying the name of the keyword to be modified. See -Appendix B for the definition of the parameters used in these -routines. - - -\begin{description} -\item[1 ] Modify (overwrite) the nth 80-character header record in the CHU. \label{ffmrec} -\end{description} - -\begin{verbatim} - int fits_modify_record / ffmrec - (fitsfile *fptr, int keynum, char *card, > int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Modify (overwrite) the 80-character header record for the named keyword - in the CHU. This can be used to overwrite the name of the keyword as - well as its value and comment fields. \label{ffmcrd} -\end{description} - -\begin{verbatim} - int fits_modify_card / ffmcrd - (fitsfile *fptr, char *keyname, char *card, > int *status) -\end{verbatim} - -\begin{description} -\item[5 ] Modify the value and comment fields of an existing keyword in the CHU. - The `longstr' version has the same functionality as the `str' - version except that it also supports the local long string keyword - convention for strings longer than 68 characters. Optionally, one - may modify only the value field and leave the comment field - unchanged by setting the input COMMENT parameter equal to the - ampersand character (\&) or by entering a null pointer for the - comment parameter. The flt, dbl, cmp, and dblcmp versions of this - routine have the added feature that if the 'decimals' parameter is - negative, then the 'G' display format rather then the 'E' format - will be used when constructing the keyword value, taking the - absolute value of 'decimals' for the precision. This will suppress - trailing zeros, and will use a fixed format rather than an - exponential format, - depending on the magnitude of the value. \label{ffmkyx} -\end{description} - -\begin{verbatim} - int fits_modify_key_[str, longstr] / ffm[kys, kls] - (fitsfile *fptr, char *keyname, char *value, char *comment, - > int *status); - - int fits_modify_key_[log, lng] / ffmky[lj] - (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, - > int *status) - - int fits_modify_key_[flt, dbl, fixflt, fixdbl] / ffmky[edfg] - (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, - char *comment, > int *status) - - int fits_modify_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffmk[yc,ym,fc,fm] - (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, - char *comment, > int *status) -\end{verbatim} - -\begin{description} -\item[6 ] Modify the value of an existing keyword to be undefined, or null. - The value string of the keyword is set to blank. - Optionally, one may leave the comment field unchanged by setting the - input COMMENT parameter equal to - the ampersand character (\&) or by entering a null pointer. \label{ffmkyu} -\end{description} - -\begin{verbatim} - int fits_modify_key_null / ffmkyu - (fitsfile *fptr, char *keyname, char *comment, > int *status) -\end{verbatim} - -\subsection{Update Keyword Routines} - - -\begin{description} -\item[1 ] These update routines modify the value, and optionally the comment field, - of the keyword if it already exists, otherwise the new keyword is - appended to the header. A separate routine is provided for each - keyword data type. The `longstr' version has the same functionality - as the `str' version except that it also supports the local long - string keyword convention for strings longer than 68 characters. A - null pointer may be entered for the comment parameter which will - leave the comment field unchanged or blank. The flt, dbl, cmp, and - dblcmp versions of this routine have the added feature that if the - 'decimals' parameter is negative, then the 'G' display format - rather then the 'E' format will be used when constructing the - keyword value, taking the absolute value of 'decimals' for the - precision. This will suppress trailing zeros, and will use a fixed - format rather than an exponential format, - depending on the magnitude of the value. \label{ffukyx} -\end{description} - -\begin{verbatim} - int fits_update_key_[str, longstr] / ffu[kys, kls] - (fitsfile *fptr, char *keyname, char *value, char *comment, - > int *status) - - int fits_update_key_[log, lng] / ffuky[lj] - (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, - > int *status) - - int fits_update_key_[flt, dbl, fixflt, fixdbl] / ffuky[edfg] - (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, - char *comment, > int *status) - - int fits_update_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffuk[yc,ym,fc,fm] - (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, - char *comment, > int *status) -\end{verbatim} - - -\section{Define Data Scaling and Undefined Pixel Parameters} - -These routines set or modify the internal parameters used by CFITSIO -to either scale the data or to represent undefined pixels. Generally -CFITSIO will scale the data according to the values of the BSCALE and -BZERO (or TSCALn and TZEROn) keywords, however these routines may be -used to override the keyword values. This may be useful when one wants -to read or write the raw unscaled values in the FITS file. Similarly, -CFITSIO generally uses the value of the BLANK or TNULLn keyword to -signify an undefined pixel, but these routines may be used to override -this value. These routines do not create or modify the corresponding -header keyword values. See Appendix B for the definition of the -parameters used in these routines. - - -\begin{description} -\item[1 ] Reset the scaling factors in the primary array or image extension; does - not change the BSCALE and BZERO keyword values and only affects the - automatic scaling performed when the data elements are written/read - to/from the FITS file. When reading from a FITS file the returned - data value = (the value given in the FITS array) * BSCALE + BZERO. - The inverse formula is used when writing data values to the FITS - file. \label{ffpscl} -\end{description} - -\begin{verbatim} - int fits_set_bscale / ffpscl - (fitsfile *fptr, double scale, double zero, > int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Reset the scaling parameters for a table column; does not change - the TSCALn or TZEROn keyword values and only affects the automatic - scaling performed when the data elements are written/read to/from - the FITS file. When reading from a FITS file the returned data - value = (the value given in the FITS array) * TSCAL + TZERO. The - inverse formula is used when writing data values to the FITS file. - \label{fftscl} -\end{description} - -\begin{verbatim} - int fits_set_tscale / fftscl - (fitsfile *fptr, int colnum, double scale, double zero, - > int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Define the integer value to be used to signify undefined pixels in the - primary array or image extension. This is only used if BITPIX = 8, 16, - or 32. This does not create or change the value of the BLANK keyword in - the header. \label{ffpnul} -\end{description} - -\begin{verbatim} - int fits_set_imgnull / ffpnul - (fitsfile *fptr, LONGLONG nulval, > int *status) -\end{verbatim} - -\begin{description} -\item[4 ] Define the string to be used to signify undefined pixels in - a column in an ASCII table. This does not create or change the value - of the TNULLn keyword. \label{ffsnul} -\end{description} - -\begin{verbatim} - int fits_set_atblnull / ffsnul - (fitsfile *fptr, int colnum, char *nulstr, > int *status) -\end{verbatim} - -\begin{description} -\item[5 ] Define the value to be used to signify undefined pixels in - an integer column in a binary table (where TFORMn = 'B', 'I', or 'J'). - This does not create or change the value of the TNULLn keyword. - \label{fftnul} -\end{description} - -\begin{verbatim} - int fits_set_btblnull / fftnul - (fitsfile *fptr, int colnum, LONGLONG nulval, > int *status) -\end{verbatim} - - -\section{Specialized FITS Primary Array or IMAGE Extension I/O Routines} - -These routines read or write data values in the primary data array -(i.e., the first HDU in the FITS file) or an IMAGE extension. -Automatic data type conversion is performed for if the data type of the -FITS array (as defined by the BITPIX keyword) differs from the data -type of the array in the calling routine. The data values are -automatically scaled by the BSCALE and BZERO header values as they are -being written or read from the FITS array. Unlike the basic routines -described in the previous chapter, most of these routines specifically -support the FITS random groups format. See Appendix B for the -definition of the parameters used in these routines. - -The more primitive reading and writing routines (i. e., ffppr\_, -ffppn\_, ffppn, ffgpv\_, or ffgpf\_) simply treat the primary array as -a long 1-dimensional array of pixels, ignoring the intrinsic -dimensionality of the array. When dealing with a 2D image, for -example, the application program must calculate the pixel offset in the -1-D array that corresponds to any particular X, Y coordinate in the -image. C programmers should note that the ordering of arrays in FITS -files, and hence in all the CFITSIO calls, is more similar to the -dimensionality of arrays in Fortran rather than C. For instance if a -FITS image has NAXIS1 = 100 and NAXIS2 = 50, then a 2-D array just -large enough to hold the image should be declared as array[50][100] and -not as array[100][50]. - -For convenience, higher-level routines are also provided to specifically -deal with 2D images (ffp2d\_ and ffg2d\_) and 3D data cubes (ffp3d\_ -and ffg3d\_). The dimensionality of the FITS image is passed by the -naxis1, naxis2, and naxis3 parameters and the declared dimensions of -the program array are passed in the dim1 and dim2 parameters. Note -that the dimensions of the program array may be larger than the -dimensions of the FITS array. For example if a FITS image with NAXIS1 -= NAXIS2 = 400 is read into a program array which is dimensioned as 512 -x 512 pixels, then the image will just fill the lower left corner of -the array with pixels in the range 1 - 400 in the X an Y directions. -This has the effect of taking a contiguous set of pixel value in the -FITS array and writing them to a non-contiguous array in program memory -(i.e., there are now some blank pixels around the edge of the image in -the program array). - -The most general set of routines (ffpss\_, ffgsv\_, and ffgsf\_) may be -used to transfer a rectangular subset of the pixels in a FITS -N-dimensional image to or from an array which has been declared in the -calling program. The fpixel and lpixel parameters are integer arrays -which specify the starting and ending pixel coordinate in each dimension -(starting with 1, not 0) of the FITS image that is to be read or -written. It is important to note that these are the starting and -ending pixels in the FITS image, not in the declared array in the -program. The array parameter in these routines is treated simply as a -large one-dimensional array of the appropriate data type containing the -pixel values; The pixel values in the FITS array are read/written -from/to this program array in strict sequence without any gaps; it is -up to the calling routine to correctly interpret the dimensionality of -this array. The two FITS reading routines (ffgsv\_ and ffgsf\_ ) also -have an `inc' parameter which defines the data sampling interval in -each dimension of the FITS array. For example, if inc[0]=2 and -inc[1]=3 when reading a 2-dimensional FITS image, then only every other -pixel in the first dimension and every 3rd pixel in the second -dimension will be returned to the 'array' parameter. - -Two types of routines are provided to read the data array which differ in -the way undefined pixels are handled. The first type of routines (e.g., -ffgpv\_) simply return an array of data elements in which undefined -pixels are set equal to a value specified by the user in the `nulval' -parameter. An additional feature of these routines is that if the user -sets nulval = 0, then no checks for undefined pixels will be performed, -thus reducing the amount of CPU processing. The second type of routines -(e.g., ffgpf\_) returns the data element array and, in addition, a char -array that indicates whether the value of the corresponding data pixel -is undefined (= 1) or defined (= 0). The latter type of routines may -be more convenient to use in some circumstances, however, it requires -an additional array of logical values which can be unwieldy when working -with large data arrays. - - -\begin{description} -\item[1 ] Write elements into the FITS data array. - \label{ffppr} \label{ffpprx} \label{ffppn} \label{ffppnx} -\end{description} - -\begin{verbatim} - int fits_write_img / ffppr - (fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelements, - DTYPE *array, int *status); - - int fits_write_img_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffppr[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelements, - DTYPE *array, > int *status); - - int fits_write_imgnull / ffppn - (fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelements, - DTYPE *array, DTYPE *nulval, > int *status); - - int fits_write_imgnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffppn[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelements, DTYPE *array, DTYPE nulval, > int *status); -\end{verbatim} - -\begin{description} -\item[2 ]Set data array elements as undefined. \label{ffppru} -\end{description} - -\begin{verbatim} - int fits_write_img_null / ffppru - (fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelements, - > int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Write values into group parameters. This routine only applies - to the `Random Grouped' FITS format which has been used for - applications in radio interferometry, but is officially deprecated - for future use. \label{ffpgpx} -\end{description} - -\begin{verbatim} - int fits_write_grppar_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffpgp[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, long firstelem, long nelements, - > DTYPE *array, int *status) -\end{verbatim} - -\begin{description} -\item[4 ] Write a 2-D or 3-D image into the data array. \label{ffp2dx} \label{ffp3dx} -\end{description} - -\begin{verbatim} - int fits_write_2d_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffp2d[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, LONGLONG dim1, LONGLONG naxis1, - LONGLONG naxis2, DTYPE *array, > int *status) - - int fits_write_3d_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffp3d[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, LONGLONG dim1, LONGLONG dim2, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, DTYPE *array, > int *status) -\end{verbatim} - -\begin{description} -\item[5 ] Write an arbitrary data subsection into the data array. \label{ffpssx} -\end{description} - -\begin{verbatim} - int fits_write_subset_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffpss[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, DTYPE *array, > int *status) -\end{verbatim} - -\begin{description} -\item[6 ] Read elements from the FITS data array. - \label{ffgpv} \label{ffgpvx} \label{ffgpf} \label{ffgpfx} -\end{description} - -\begin{verbatim} - int fits_read_img / ffgpv - (fitsfile *fptr, int datatype, long firstelem, long nelements, - DTYPE *nulval, > DTYPE *array, int *anynul, int *status) - - int fits_read_img_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffgpv[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, long firstelem, long nelements, - DTYPE nulval, > DTYPE *array, int *anynul, int *status) - - int fits_read_imgnull / ffgpf - (fitsfile *fptr, int datatype, long firstelem, long nelements, - > DTYPE *array, char *nullarray, int *anynul, int *status) - - int fits_read_imgnull_[byt, sht, usht, int, uint, lng, ulng, flt, dbl] / - ffgpf[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, long firstelem, long nelements, - > DTYPE *array, char *nullarray, int *anynul, int *status) -\end{verbatim} - -\begin{description} -\item[7 ] Read values from group parameters. This routine only applies - to the `Random Grouped' FITS format which has been used for - applications in radio interferometry, but is officially deprecated - for future use. \label{ffggpx} -\end{description} - -\begin{verbatim} - int fits_read_grppar_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffggp[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, long firstelem, long nelements, - > DTYPE *array, int *status) -\end{verbatim} - -\begin{description} -\item[8 ] Read 2-D or 3-D image from the data array. Undefined - pixels in the array will be set equal to the value of 'nulval', - unless nulval=0 in which case no testing for undefined pixels will - be performed. \label{ffg2dx} \label{ffg3dx} -\end{description} - -\begin{verbatim} - int fits_read_2d_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffg2d[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, DTYPE nulval, LONGLONG dim1, LONGLONG naxis1, - LONGLONG naxis2, > DTYPE *array, int *anynul, int *status) - - int fits_read_3d_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffg3d[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, long group, DTYPE nulval, LONGLONG dim1, - LONGLONG dim2, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - > DTYPE *array, int *anynul, int *status) -\end{verbatim} - -\begin{description} -\item[9 ] Read an arbitrary data subsection from the data array. - \label{ffgsvx} \label{ffgsfx} -\end{description} - -\begin{verbatim} - int fits_read_subset_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffgsv[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, int group, int naxis, long *naxes, - long *fpixel, long *lpixel, long *inc, DTYPE nulval, - > DTYPE *array, int *anynul, int *status) - - int fits_read_subsetnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffgsf[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, int group, int naxis, long *naxes, - long *fpixel, long *lpixel, long *inc, > DTYPE *array, - char *nullarray, int *anynul, int *status) -\end{verbatim} - - -\section{Specialized FITS ASCII and Binary Table Routines} - - -\subsection{General Column Routines} - - -\begin{description} -\item[1 ] Get information about an existing ASCII or binary table column. A null - pointer may be given for any of the output parameters that are not - needed. DATATYPE is a character string which returns the data type - of the column as defined by the TFORMn keyword (e.g., 'I', 'J','E', - 'D', etc.). In the case of an ASCII character column, typecode - will have a value of the form 'An' where 'n' is an integer - expressing the width of the field in characters. For example, if - TFORM = '160A8' then ffgbcl will return typechar='A8' and - repeat=20. All the returned parameters are scalar quantities. - \label{ffgacl} \label{ffgbcl} -\end{description} - -\begin{verbatim} - int fits_get_acolparms / ffgacl - (fitsfile *fptr, int colnum, > char *ttype, long *tbcol, - char *tunit, char *tform, double *scale, double *zero, - char *nulstr, char *tdisp, int *status) - - int fits_get_bcolparms / ffgbcl - (fitsfile *fptr, int colnum, > char *ttype, char *tunit, - char *typechar, long *repeat, double *scale, double *zero, - long *nulval, char *tdisp, int *status) - - int fits_get_bcolparmsll / ffgbclll - (fitsfile *fptr, int colnum, > char *ttype, char *tunit, - char *typechar, LONGLONG *repeat, double *scale, double *zero, - LONGLONG *nulval, char *tdisp, int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Return optimal number of rows to read or write at one time for - maximum I/O efficiency. Refer to the - ``Optimizing Code'' section in Chapter 5 for more discussion on how - to use this routine. \label{ffgrsz} -\end{description} - -\begin{verbatim} - int fits_get_rowsize / ffgrsz - (fitsfile *fptr, long *nrows, *status) -\end{verbatim} - -\begin{description} -\item[3 ] Define the zero indexed byte offset of the 'heap' measured from - the start of the binary table data. By default the heap is assumed - to start immediately following the regular table data, i.e., at - location NAXIS1 x NAXIS2. This routine is only relevant for - binary tables which contain variable length array columns (with - TFORMn = 'Pt'). This routine also automatically writes - the value of theap to a keyword in the extension header. This - routine must be called after the required keywords have been - written (with ffphbn) - but before any data is written to the table. \label{ffpthp} -\end{description} - -\begin{verbatim} - int fits_write_theap / ffpthp - (fitsfile *fptr, long theap, > int *status) -\end{verbatim} - -\begin{description} -\item[4 ] Test the contents of the binary table variable array heap, returning - the size of the heap, the number of unused bytes that are not currently - pointed to by any of the descriptors, and the number of bytes which are - pointed to by multiple descriptors. It also returns valid = FALSE if - any of the descriptors point to invalid addresses out of range of the - heap. \label{fftheap} -\end{description} - -\begin{verbatim} - int fits_test_heap / fftheap - (fitsfile *fptr, > LONGLONG *heapsize, LONGLONG *unused, LONGLONG *overlap, - int *validheap, int *status) -\end{verbatim} - -\begin{description} -\item[5 ] Re-pack the vectors in the binary table variable array heap to recover - any unused space. Normally, when a vector in a variable length - array column is rewritten the previously written array remains in - the heap as wasted unused space. This routine will repack the - arrays that are still in use, thus eliminating any bytes in the - heap that are no longer in use. Note that if several vectors point - to the same bytes in the heap, then this routine will make - duplicate copies of the bytes for each vector, which will actually - expand the size of the heap. \label{ffcmph} -\end{description} - -\begin{verbatim} - int fits_compress_heap / ffcmph - (fitsfile *fptr, > int *status) -\end{verbatim} - - -\subsection{Low-Level Table Access Routines} - -The following 2 routines provide low-level access to the data in ASCII -or binary tables and are mainly useful as an efficient way to copy all -or part of a table from one location to another. These routines simply -read or write the specified number of consecutive bytes in an ASCII or -binary table, without regard for column boundaries or the row length in -the table. These routines do not perform any machine dependent data -conversion or byte swapping. See Appendix B for the definition of the -parameters used in these routines. - - -\begin{description} -\item[1 ] Read or write a consecutive array of bytes from an ASCII or binary - table \label{ffgtbb} \label{ffptbb} -\end{description} - -\begin{verbatim} - int fits_read_tblbytes / ffgtbb - (fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, - > unsigned char *values, int *status) - - int fits_write_tblbytes / ffptbb - (fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, - unsigned char *values, > int *status) -\end{verbatim} - - -\subsection{Write Column Data Routines} - - -\begin{description} -\item[1 ] Write elements into an ASCII or binary table column (in the CDU). - The data type of the array is implied by the suffix of the - routine name. \label{ffpcls} -\end{description} - -\begin{verbatim} - int fits_write_col_str / ffpcls - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, char **array, > int *status) - - int fits_write_col_[log,byt,sht,usht,int,uint,lng,ulng,lnglng,flt,dbl,cmp,dblcmp] / - ffpcl[l,b,i,ui,k,uk,j,uj,jj,e,d,c,m] - (fitsfile *fptr, int colnum, LONGLONG firstrow, - LONGLONG firstelem, LONGLONG nelements, DTYPE *array, > int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Write elements into an ASCII or binary table column - substituting the appropriate FITS null value for any elements that - are equal to the nulval parameter. \label{ffpcnx} -\end{description} - -\begin{verbatim} - int fits_write_colnull_[log, byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffpcn[l,b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, DTYPE *array, DTYPE nulval, > int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Write string elements into a binary table column (in the CDU) - substituting the FITS null value for any elements that - are equal to the nulstr string. \label{ffpcns} -\end{description} - -\begin{verbatim} - int fits_write_colnull_str / ffpcns - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, char **array, char *nulstr, > int *status) -\end{verbatim} - -\begin{description} -\item[4 ] Write bit values into a binary byte ('B') or bit ('X') table column (in - the CDU). Larray is an array of characters corresponding to the - sequence of bits to be written. If an element of larray is true - (not equal to zero) then the corresponding bit in the FITS table is - set to 1, otherwise the bit is set to 0. The 'X' column in a FITS - table is always padded out to a multiple of 8 bits where the bit - array starts with the most significant bit of the byte and works - down towards the 1's bit. For example, a '4X' array, with the - first bit = 1 and the remaining 3 bits = 0 is equivalent to the 8-bit - unsigned byte decimal value of 128 ('1000 0000B'). In the case of - 'X' columns, CFITSIO can write to all 8 bits of each byte whether - they are formally valid or not. Thus if the column is defined as - '4X', and one calls ffpclx with firstbit=1 and nbits=8, then all - 8 bits will be written into the first byte (as opposed to writing - the first 4 bits into the first row and then the next 4 bits into - the next row), even though the last 4 bits of each byte are formally - not defined and should all be set = 0. It should also be noted that - it is more efficient to write 'X' columns an entire byte at a time, - instead of bit by bit. Any of the CFITSIO routines that write to - columns (e.g. fits\_write\_col\_byt) may be used for this purpose. - These routines will interpret 'X' columns as though they were 'B' - columns (e.g., '1X' through '8X' is equivalent - to '1B', and '9X' through '16X' is equivalent to '2B'). \label{ffpclx} -\end{description} - -\begin{verbatim} - int fits_write_col_bit / ffpclx - (fitsfile *fptr, int colnum, LONGLONG firstrow, long firstbit, - long nbits, char *larray, > int *status) -\end{verbatim} - -\begin{description} -\item[5 ] Write the descriptor for a variable length column in a binary table. - This routine can be used in conjunction with ffgdes to enable - 2 or more arrays to point to the same storage location to save - storage space if the arrays are identical. \label{ffpdes} -\end{description} - -\begin{verbatim} - int fits_write_descript / ffpdes - (fitsfile *fptr, int colnum, LONGLONG rownum, LONGLONG repeat, - LONGLONG offset, > int *status) -\end{verbatim} - -\subsection{Read Column Data Routines} - -Two types of routines are provided to get the column data which differ -in the way undefined pixels are handled. The first set of routines -(ffgcv) simply return an array of data elements in which undefined -pixels are set equal to a value specified by the user in the 'nullval' -parameter. If nullval = 0, then no checks for undefined pixels will be -performed, thus increasing the speed of the program. The second set of -routines (ffgcf) returns the data element array and in addition a -logical array of flags which defines whether the corresponding data -pixel is undefined. See Appendix B for the definition of the -parameters used in these routines. - - Any column, regardless of it's intrinsic data type, may be read as a - string. It should be noted however that reading a numeric column as - a string is 10 - 100 times slower than reading the same column as a number - due to the large overhead in constructing the formatted strings. - The display format of the returned strings will be - determined by the TDISPn keyword, if it exists, otherwise by the - data type of the column. The length of the returned strings (not - including the null terminating character) can be determined with - the fits\_get\_col\_display\_width routine. The following TDISPn - display formats are currently supported: - -\begin{verbatim} - Iw.m Integer - Ow.m Octal integer - Zw.m Hexadecimal integer - Fw.d Fixed floating point - Ew.d Exponential floating point - Dw.d Exponential floating point - Gw.d General; uses Fw.d if significance not lost, else Ew.d -\end{verbatim} - where w is the width in characters of the displayed values, m is - the minimum number of digits displayed, and d is the number of - digits to the right of the decimal. The .m field is optional. - - -\begin{description} -\item[1 ] Read elements from an ASCII or binary table column (in the CDU). These - routines return the values of the table column array elements. Undefined - array elements will be returned with a value = nulval, unless nulval = 0 - (or = ' ' for ffgcvs) in which case no checking for undefined values will - be performed. The anynul parameter is set to true if any of the returned - elements are undefined. \label{ffgcvx} -\end{description} - -\begin{verbatim} - int fits_read_col_str / ffgcvs - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, char *nulstr, > char **array, int *anynul, - int *status) - - int fits_read_col_[log,byt,sht,usht,int,uint,lng,ulng, lnglng, flt, dbl, cmp, dblcmp] / - ffgcv[l,b,i,ui,k,uk,j,uj,jj,e,d,c,m] - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, DTYPE nulval, > DTYPE *array, int *anynul, - int *status) -\end{verbatim} - -\begin{description} -\item[2 ] Read elements and null flags from an ASCII or binary table column (in the - CHDU). These routines return the values of the table column array elements. - Any undefined array elements will have the corresponding nullarray element - set equal to TRUE. The anynul parameter is set to true if any of the - returned elements are undefined. \label{ffgcfx} -\end{description} - -\begin{verbatim} - int fits_read_colnull_str / ffgcfs - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelements, > char **array, char *nullarray, int *anynul, - int *status) - - int fits_read_colnull_[log,byt,sht,usht,int,uint,lng,ulng,lnglng,flt,dbl,cmp,dblcmp] / - ffgcf[l,b,i,ui,k,uk,j,uj,jj,e,d,c,m] - (fitsfile *fptr, int colnum, LONGLONG firstrow, - LONGLONG firstelem, LONGLONG nelements, > DTYPE *array, - char *nullarray, int *anynul, int *status) -\end{verbatim} - -\begin{description} -\item[3 ] Read an arbitrary data subsection from an N-dimensional array - in a binary table vector column. Undefined pixels - in the array will be set equal to the value of 'nulval', - unless nulval=0 in which case no testing for undefined pixels will - be performed. The first and last rows in the table to be read - are specified by fpixel(naxis+1) and lpixel(naxis+1), and hence - are treated as the next higher dimension of the FITS N-dimensional - array. The INC parameter specifies the sampling interval in - each dimension between the data elements that will be returned. \label{ffgsvx2} -\end{description} - -\begin{verbatim} - int fits_read_subset_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffgsv[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, int colnum, int naxis, long *naxes, long *fpixel, - long *lpixel, long *inc, DTYPE nulval, > DTYPE *array, int *anynul, - int *status) -\end{verbatim} - -\begin{description} -\item[4 ] Read an arbitrary data subsection from an N-dimensional array - in a binary table vector column. Any Undefined - pixels in the array will have the corresponding 'nullarray' - element set equal to TRUE. The first and last rows in the table - to be read are specified by fpixel(naxis+1) and lpixel(naxis+1), - and hence are treated as the next higher dimension of the FITS - N-dimensional array. The INC parameter specifies the sampling - interval in each dimension between the data elements that will be - returned. \label{ffgsfx2} -\end{description} - -\begin{verbatim} - int fits_read_subsetnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / - ffgsf[b,i,ui,k,uk,j,uj,jj,e,d] - (fitsfile *fptr, int colnum, int naxis, long *naxes, - long *fpixel, long *lpixel, long *inc, > DTYPE *array, - char *nullarray, int *anynul, int *status) -\end{verbatim} - -\begin{description} -\item[5 ] Read bit values from a byte ('B') or bit (`X`) table column (in the - CDU). Larray is an array of logical values corresponding to the - sequence of bits to be read. If larray is true then the - corresponding bit was set to 1, otherwise the bit was set to 0. - The 'X' column in a FITS table is always padded out to a multiple - of 8 bits where the bit array starts with the most significant bit - of the byte and works down towards the 1's bit. For example, a - '4X' array, with the first bit = 1 and the remaining 3 bits = 0 is - equivalent to the 8-bit unsigned byte value of 128. - Note that in the case of 'X' columns, CFITSIO can read all 8 bits - of each byte whether they are formally valid or not. Thus if the - column is defined as '4X', and one calls ffgcx with firstbit=1 and - nbits=8, then all 8 bits will be read from the first byte (as - opposed to reading the first 4 bits from the first row and then the - first 4 bits from the next row), even though the last 4 bits of - each byte are formally not defined. It should also be noted that - it is more efficient to read 'X' columns an entire byte at a time, - instead of bit by bit. Any of the CFITSIO routines that read - columns (e.g. fits\_read\_col\_byt) may be used for this - purpose. These routines will interpret 'X' columns as though they - were 'B' columns (e.g., '8X' is equivalent to '1B', and '16X' is - equivalent to '2B'). \label{ffgcx} -\end{description} - -\begin{verbatim} - int fits_read_col_bit / ffgcx - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstbit, - LONGLONG nbits, > char *larray, int *status) -\end{verbatim} - -\begin{description} -\item[6 ] Read any consecutive set of bits from an 'X' or 'B' column and - interpret them as an unsigned n-bit integer. nbits must be less - than 16 or 32 in ffgcxui and ffgcxuk, respectively. If nrows - is greater than 1, then the same set of bits will be read from - each row, starting with firstrow. The bits are numbered with - 1 = the most significant bit of the first element of the column. - \label{ffgcxui} -\end{description} - -\begin{verbatim} - int fits_read_col_bit_[usht, uint] / ffgcx[ui,uk] - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG, nrows, - long firstbit, long nbits, > DTYPE *array, int *status) -\end{verbatim} - -\begin{description} -\item[7 ] Return the descriptor for a variable length column in a binary table. - The descriptor consists of 2 integer parameters: the number of elements - in the array and the starting offset relative to the start of the heap. - The first pair of routine returns a single descriptor whereas the second - pair of routine - returns the descriptors for a range of rows in the table. The only - difference between the 2 routines in each pair is that one returns - the parameters as 'long' integers, whereas the other returns the values - as 64-bit 'LONGLONG' integers. - \label{ffgdes} -\end{description} - -\begin{verbatim} - int fits_read_descript / ffgdes - (fitsfile *fptr, int colnum, LONGLONG rownum, > long *repeat, - long *offset, int *status) - - int fits_read_descriptll / ffgdesll - (fitsfile *fptr, int colnum, LONGLONG rownum, > LONGLONG *repeat, - LONGLONG *offset, int *status) - - int fits_read_descripts / ffgdess - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows - > long *repeat, long *offset, int *status) - - int fits_read_descriptsll / ffgdessll - (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows - > LONGLONG *repeat, LONGLONG *offset, int *status) -\end{verbatim} - -\chapter{ Extended File Name Syntax } - - -\section{Overview} - -CFITSIO supports an extended syntax when specifying the name of the -data file to be opened or created that includes the following -features: - -\begin{itemize} -\item -CFITSIO can read IRAF format images which have header file names that -end with the '.imh' extension, as well as reading and writing FITS -files, This feature is implemented in CFITSIO by first converting the -IRAF image into a temporary FITS format file in memory, then opening -the FITS file. Any of the usual CFITSIO routines then may be used to -read the image header or data. Similarly, raw binary data arrays can -be read by converting them on the fly into virtual FITS images. - -\item -FITS files on the Internet can be read (and sometimes written) using the FTP, -HTTP, or ROOT protocols. - -\item -FITS files can be piped between tasks on the stdin and stdout streams. - -\item -FITS files can be read and written in shared memory. This can -potentially achieve better data I/O performance compared to reading and -writing the same FITS files on magnetic disk. - -\item -Compressed FITS files in gzip or Unix COMPRESS format can be directly read. - -\item -Output FITS files can be written directly in compressed gzip format, -thus saving disk space. - -\item -FITS table columns can be created, modified, or deleted 'on-the-fly' as -the table is opened by CFITSIO. This creates a virtual FITS file containing -the modifications that is then opened by the application program. - -\item -Table rows may be selected, or filtered out, on the fly when the table -is opened by CFITSIO, based on an user-specified expression. -Only rows for which the expression evaluates to 'TRUE' are retained -in the copy of the table that is opened by the application program. - -\item -Histogram images may be created on the fly by binning the values in -table columns, resulting in a virtual N-dimensional FITS image. The -application program then only sees the FITS image (in the primary -array) instead of the original FITS table. -\end{itemize} - -The latter 3 table filtering features in particular add very powerful -data processing capabilities directly into CFITSIO, and hence into -every task that uses CFITSIO to read or write FITS files. For example, -these features transform a very simple program that just copies an -input FITS file to a new output file (like the `fitscopy' program that -is distributed with CFITSIO) into a multipurpose FITS file processing -tool. By appending fairly simple qualifiers onto the name of the input -FITS file, the user can perform quite complex table editing operations -(e.g., create new columns, or filter out rows in a table) or create -FITS images by binning or histogramming the values in table columns. -In addition, these functions have been coded using new state-of-the art -algorithms that are, in some cases, 10 - 100 times faster than previous -widely used implementations. - -Before describing the complete syntax for the extended FITS file names -in the next section, here are a few examples of FITS file names that -give a quick overview of the allowed syntax: - -\begin{itemize} -\item -{\tt myfile.fits}: the simplest case of a FITS file on disk in the current -directory. - -\item -{\tt myfile.imh}: opens an IRAF format image file and converts it on the -fly into a temporary FITS format image in memory which can then be read with -any other CFITSIO routine. - -\item -{\tt rawfile.dat[i512,512]}: opens a raw binary data array (a 512 x 512 -short integer array in this case) and converts it on the fly into a -temporary FITS format image in memory which can then be read with any -other CFITSIO routine. - -\item -{\tt myfile.fits.gz}: if this is the name of a new output file, the '.gz' -suffix will cause it to be compressed in gzip format when it is written to -disk. - -\item -{\tt myfile.fits.gz[events, 2]}: opens and uncompresses the gzipped file -myfile.fits then moves to the extension with the keywords EXTNAME -= 'EVENTS' and EXTVER = 2. - -\item -{\tt -}: a dash (minus sign) signifies that the input file is to be read -from the stdin file stream, or that the output file is to be written to -the stdout stream. See also the stream:// driver which provides a -more efficient, but more restricted method of reading or writing to -the stdin or stdout streams. - -\item -{\tt ftp://legacy.gsfc.nasa.gov/test/vela.fits}: FITS files in any ftp -archive site on the Internet may be directly opened with read-only -access. - -\item -{\tt http://legacy.gsfc.nasa.gov/software/test.fits}: any valid URL to a -FITS file on the Web may be opened with read-only access. - -\item -{\tt root://legacy.gsfc.nasa.gov/test/vela.fits}: similar to ftp access -except that it provides write as well as read access to the files -across the network. This uses the root protocol developed at CERN. - -\item -{\tt shmem://h2[events]}: opens the FITS file in a shared memory segment and -moves to the EVENTS extension. - -\item -{\tt mem://}: creates a scratch output file in core computer memory. The -resulting 'file' will disappear when the program exits, so this -is mainly useful for testing purposes when one does not want a -permanent copy of the output file. - -\item -{\tt myfile.fits[3; Images(10)]}: opens a copy of the image contained in the -10th row of the 'Images' column in the binary table in the 3th extension -of the FITS file. The virtual file that is opened by the application just -contains this single image in the primary array. - -\item -{\tt myfile.fits[1:512:2, 1:512:2]}: opens a section of the input image -ranging from the 1st to the 512th pixel in X and Y, and selects every -second pixel in both dimensions, resulting in a 256 x 256 pixel input image -in this case. - -\item -{\tt myfile.fits[EVENTS][col Rad = sqrt(X**2 + Y**2)]}: creates and opens -a virtual file on the fly that is identical to -myfile.fits except that it will contain a new column in the EVENTS -extension called 'Rad' whose value is computed using the indicated -expression which is a function of the values in the X and Y columns. - -\item -{\tt myfile.fits[EVENTS][PHA > 5]}: creates and opens a virtual FITS -files that is identical to 'myfile.fits' except that the EVENTS table -will only contain the rows that have values of the PHA column greater -than 5. In general, any arbitrary boolean expression using a C or -Fortran-like syntax, which may combine AND and OR operators, -may be used to select rows from a table. - -\item -{\tt myfile.fits[EVENTS][bin (X,Y)=1,2048,4]}: creates a temporary FITS -primary array image which is computed on the fly by binning (i.e, -computing the 2-dimensional histogram) of the values in the X and Y -columns of the EVENTS extension. In this case the X and Y coordinates -range from 1 to 2048 and the image pixel size is 4 units in both -dimensions, so the resulting image is 512 x 512 pixels in size. - -\item -The final example combines many of these feature into one complex -expression (it is broken into several lines for clarity): - -\begin{verbatim} - ftp://legacy.gsfc.nasa.gov/data/sample.fits.gz[EVENTS] - [col phacorr = pha * 1.1 - 0.3][phacorr >= 5.0 && phacorr <= 14.0] - [bin (X,Y)=32] -\end{verbatim} -In this case, CFITSIO (1) copies and uncompresses the FITS file from -the ftp site on the legacy machine, (2) moves to the 'EVENTS' -extension, (3) calculates a new column called 'phacorr', (4) selects -the rows in the table that have phacorr in the range 5 to 14, and -finally (5) bins the remaining rows on the X and Y column coordinates, -using a pixel size = 32 to create a 2D image. All this processing is -completely transparent to the application program, which simply sees -the final 2-D image in the primary array of the opened file. -\end{itemize} - -The full extended CFITSIO FITS file name can contain several different -components depending on the context. These components are described in -the following sections: - -\begin{verbatim} -When creating a new file: - filetype://BaseFilename(templateName)[compress] - -When opening an existing primary array or image HDU: - filetype://BaseFilename(outName)[HDUlocation][ImageSection][pixFilter] - -When opening an existing table HDU: - filetype://BaseFilename(outName)[HDUlocation][colFilter][rowFilter][binSpec] -\end{verbatim} -The filetype, BaseFilename, outName, HDUlocation, ImageSection, and pixFilter -components, if present, must be given in that order, but the colFilter, -rowFilter, and binSpec specifiers may follow in any order. Regardless -of the order, however, the colFilter specifier, if present, will be -processed first by CFITSIO, followed by the rowFilter specifier, and -finally by the binSpec specifier. - - -\section{Filetype} - -The type of file determines the medium on which the file is located -(e.g., disk or network) and, hence, which internal device driver is used by -CFITSIO to read and/or write the file. Currently supported types are - -\begin{verbatim} - file:// - file on local magnetic disk (default) - ftp:// - a readonly file accessed with the anonymous FTP protocol. - It also supports ftp://username:password@hostname/... - for accessing password-protected ftp sites. - http:// - a readonly file accessed with the HTTP protocol. It - supports username:password just like the ftp driver. - Proxy HTTP servers are supported using the http_proxy - environment variable (see following note). - stream:// - special driver to read an input FITS file from the stdin - stream, and/or write an output FITS file to the stdout - stream. This driver is fragile and has limited - functionality (see the following note). - gsiftp:// - access files on a computational grid using the gridftp - protocol in the Globus toolkit (see following note). - root:// - uses the CERN root protocol for writing as well as - reading files over the network (see following note). - shmem:// - opens or creates a file which persists in the computer's - shared memory (see following note). - mem:// - opens a temporary file in core memory. The file - disappears when the program exits so this is mainly - useful for test purposes when a permanent output file - is not desired. -\end{verbatim} -If the filetype is not specified, then type file:// is assumed. -The double slashes '//' are optional and may be omitted in most cases. - - -\subsection{Notes about HTTP proxy servers} - -A proxy HTTP server may be used by defining the address (URL) and port -number of the proxy server with the http\_proxy environment variable. -For example - -\begin{verbatim} - setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 -\end{verbatim} -will cause CFITSIO to use port 3128 on the heasarc proxy server whenever -reading a FITS file with HTTP. - - -\subsection{Notes about the stream filetype driver} - -The stream driver can be used to efficiently read a FITS file from the stdin -file stream or write a FITS to the stdout file stream. However, because these -input and output streams must be accessed sequentially, the FITS file reading or -writing application must also read and write the file sequentially, at least -within the tolerances described below. - -CFITSIO supports 2 different methods for accessing FITS files on the stdin and -stdout streams. The original method, which is invoked by specifying a dash -character, "-", as the name of the file when opening or creating it, works by -storing a complete copy of the entire FITS file in memory. In this case, when -reading from stdin, CFITSIO will copy the entire stream into memory before doing -any processing of the file. Similarly, when writing to stdout, CFITSIO will -create a copy of the entire FITS file in memory, before finally flushing it out -to the stdout stream when the FITS file is closed. Buffering the entire FITS -file in this way allows the application to randomly access any part of the FITS -file, in any order, but it also requires that the user have sufficient available -memory (or virtual memory) to store the entire file, which may not be possible -in the case of very large files. - -The newer stream filetype provides a more memory-efficient method of accessing -FITS files on the stdin or stdout streams. Instead of storing a copy of the -entire FITS file in memory, CFITSIO only uses a set of internal buffer which by -default can store 40 FITS blocks, or about 100K bytes of the FITS file. The -application program must process the FITS file sequentially from beginning to -end, within this 100K buffer. Generally speaking the application program must -conform to the following restrictions: - -\begin{itemize} -\item -The program must finish reading or writing the header keywords -before reading or writing any data in the HDU. -\item -The HDU can contain at most about 1400 header keywords. This is the -maximum that can fit in the nominal 40 FITS block buffer. In principle, -this limit could be increased by recompiling CFITSIO with a larger -buffer limit, which is set by the NIOBUF parameter in fitsio2.h. -\item -The program must read or write the data in a sequential manner from the -beginning to the end of the HDU. Note that CFITSIO's internal -100K buffer allows a little latitude in meeting this requirement. -\item -The program cannot move back to a previous HDU in the FITS file. -\item -Reading or writing of variable length array columns in binary tables is not -supported on streams, because this requires moving back and forth between the -fixed-length portion of the binary table and the following heap area where the -arrays are actually stored. -\item -Reading or writing of tile-compressed images is not supported on streams, -because the images are internally stored using variable length arrays. -\end{itemize} - - -\subsection{Notes about the gsiftp filetype} - -DEPENDENCIES: Globus toolkit (2.4.3 or higher) (GT) should be installed. -There are two different ways to install GT: - -1) goto the globus toolkit web page www.globus.org and follow the - download and compilation instructions; - -2) goto the Virtual Data Toolkit web page http://vdt.cs.wisc.edu/ - and follow the instructions (STRONGLY SUGGESTED); - -Once a globus client has been installed in your system with a specific flavour -it is possible to compile and install the CFITSIO libraries. -Specific configuration flags must be used: - -1) --with-gsiftp[[=PATH]] Enable Globus Toolkit gsiftp protocol support - PATH=GLOBUS\_LOCATION i.e. the location of your globus installation - -2) --with-gsiftp-flavour[[=PATH] defines the specific Globus flavour - ex. gcc32 - -Both the flags must be used and it is mandatory to set both the PATH and the -flavour. - -USAGE: To access files on a gridftp server it is necessary to use a gsiftp prefix: - -example: gsiftp://remote\_server\_fqhn/directory/filename - -The gridftp driver uses a local buffer on a temporary file the file is located -in the /tmp directory. If you have special permissions on /tmp or you do not have a /tmp -directory, it is possible to force another location setting the GSIFTP\_TMPFILE environment -variable (ex. export GSIFTP\_TMPFILE=/your/location/yourtmpfile). - -Grid FTP supports multi channel transfer. By default a single channel transmission is -available. However, it is possible to modify this behavior setting the GSIFTP\_STREAMS -environment variable (ex. export GSIFTP\_STREAMS=8). - - - -\subsection{Notes about the root filetype} - -The original rootd server can be obtained from: -\verb-ftp://root.cern.ch/root/rootd.tar.gz- -but, for it to work correctly with CFITSIO one has to use a modified -version which supports a command to return the length of the file. -This modified version is available in rootd subdirectory -in the CFITSIO ftp area at - -\begin{verbatim} - ftp://legacy.gsfc.nasa.gov/software/fitsio/c/root/rootd.tar.gz. -\end{verbatim} - -This small server is started either by inetd when a client requests a -connection to a rootd server or by hand (i.e. from the command line). -The rootd server works with the ROOT TNetFile class. It allows remote -access to ROOT database files in either read or write mode. By default -TNetFile assumes port 432 (which requires rootd to be started as root). -To run rootd via inetd add the following line to /etc/services: - -\begin{verbatim} - rootd 432/tcp -\end{verbatim} -and to /etc/inetd.conf, add the following line: - -\begin{verbatim} - rootd stream tcp nowait root /user/rdm/root/bin/rootd rootd -i -\end{verbatim} -Force inetd to reread its conf file with \verb+kill -HUP +. -You can also start rootd by hand running directly under your private -account (no root system privileges needed). For example to start -rootd listening on port 5151 just type: \verb+rootd -p 5151+ -Notice that no \& is needed. Rootd will go into background by itself. - -\begin{verbatim} - Rootd arguments: - -i says we were started by inetd - -p port# specifies a different port to listen on - -d level level of debug info written to syslog - 0 = no debug (default) - 1 = minimum - 2 = medium - 3 = maximum -\end{verbatim} -Rootd can also be configured for anonymous usage (like anonymous ftp). -To setup rootd to accept anonymous logins do the following (while being -logged in as root): - -\begin{verbatim} - - Add the following line to /etc/passwd: - - rootd:*:71:72:Anonymous rootd:/var/spool/rootd:/bin/false - - where you may modify the uid, gid (71, 72) and the home directory - to suite your system. - - - Add the following line to /etc/group: - - rootd:*:72:rootd - - where the gid must match the gid in /etc/passwd. - - - Create the directories: - - mkdir /var/spool/rootd - mkdir /var/spool/rootd/tmp - chmod 777 /var/spool/rootd/tmp - - Where /var/spool/rootd must match the rootd home directory as - specified in the rootd /etc/passwd entry. - - - To make writeable directories for anonymous do, for example: - - mkdir /var/spool/rootd/pub - chown rootd:rootd /var/spool/rootd/pub -\end{verbatim} -That's all. Several additional remarks: you can login to an anonymous -server either with the names "anonymous" or "rootd". The password should -be of type user@host.do.main. Only the @ is enforced for the time -being. In anonymous mode the top of the file tree is set to the rootd -home directory, therefore only files below the home directory can be -accessed. Anonymous mode only works when the server is started via -inetd. - - -\subsection{Notes about the shmem filetype:} - -Shared memory files are currently supported on most Unix platforms, -where the shared memory segments are managed by the operating system -kernel and `live' independently of processes. They are not deleted (by -default) when the process which created them terminates, although they -will disappear if the system is rebooted. Applications can create -shared memory files in CFITSIO by calling: - -\begin{verbatim} - fit_create_file(&fitsfileptr, "shmem://h2", &status); -\end{verbatim} -where the root `file' names are currently restricted to be 'h0', 'h1', -'h2', 'h3', etc., up to a maximum number defined by the the value of -SHARED\_MAXSEG (equal to 16 by default). This is a prototype -implementation of the shared memory interface and a more robust -interface, which will have fewer restrictions on the number of files -and on their names, may be developed in the future. - -When opening an already existing FITS file in shared memory one calls -the usual CFITSIO routine: - -\begin{verbatim} - fits_open_file(&fitsfileptr, "shmem://h7", mode, &status) -\end{verbatim} -The file mode can be READWRITE or READONLY just as with disk files. -More than one process can operate on READONLY mode files at the same -time. CFITSIO supports proper file locking (both in READONLY and -READWRITE modes), so calls to fits\_open\_file may be locked out until -another other process closes the file. - -When an application is finished accessing a FITS file in a shared -memory segment, it may close it (and the file will remain in the -system) with fits\_close\_file, or delete it with fits\_delete\_file. -Physical deletion is postponed until the last process calls -ffclos/ffdelt. fits\_delete\_file tries to obtain a READWRITE lock on -the file to be deleted, thus it can be blocked if the object was not -opened in READWRITE mode. - -A shared memory management utility program called `smem', is included -with the CFITSIO distribution. It can be built by typing `make smem'; -then type `smem -h' to get a list of valid options. Executing smem -without any options causes it to list all the shared memory segments -currently residing in the system and managed by the shared memory -driver. To get a list of all the shared memory objects, run the system -utility program `ipcs [-a]'. - - -\section{Base Filename} - -The base filename is the name of the file optionally including the -director/subdirectory path, and in the case of `ftp', `http', and `root' -filetypes, the machine identifier. Examples: - -\begin{verbatim} - myfile.fits - !data.fits - /data/myfile.fits - fits.gsfc.nasa.gov/ftp/sampledata/myfile.fits.gz -\end{verbatim} - -When creating a new output file on magnetic disk (of type file://) if -the base filename begins with an exclamation point (!) then any -existing file with that same basename will be deleted prior to creating -the new FITS file. Otherwise if the file to be created already exists, -then CFITSIO will return an error and will not overwrite the existing -file. Note that the exclamation point, '!', is a special UNIX -character, so if it is used on the command line rather than entered at -a task prompt, it must be preceded by a backslash to force the UNIX -shell to pass it verbatim to the application program. - -If the output disk file name ends with the suffix '.gz', then CFITSIO -will compress the file using the gzip compression algorithm before -writing it to disk. This can reduce the amount of disk space used by -the file. Note that this feature requires that the uncompressed file -be constructed in memory before it is compressed and written to disk, -so it can fail if there is insufficient available memory. - -An input FITS file may be compressed with the gzip or Unix compress -algorithms, in which case CFITSIO will uncompress the file on the fly -into a temporary file (in memory or on disk). Compressed files may -only be opened with read-only permission. When specifying the name of -a compressed FITS file it is not necessary to append the file suffix -(e.g., `.gz' or `.Z'). If CFITSIO cannot find the input file name -without the suffix, then it will automatically search for a compressed -file with the same root name. In the case of reading ftp and http type -files, CFITSIO generally looks for a compressed version of the file -first, before trying to open the uncompressed file. By default, -CFITSIO copies (and uncompressed if necessary) the ftp or http FITS -file into memory on the local machine before opening it. This will -fail if the local machine does not have enough memory to hold the whole -FITS file, so in this case, the output filename specifier (see the next -section) can be used to further control how CFITSIO reads ftp and http -files. - -If the input file is an IRAF image file (*.imh file) then CFITSIO will -automatically convert it on the fly into a virtual FITS image before it -is opened by the application program. IRAF images can only be opened -with READONLY file access. - -Similarly, if the input file is a raw binary data array, then CFITSIO -will convert it on the fly into a virtual FITS image with the basic set -of required header keywords before it is opened by the application -program (with READONLY access). In this case the data type and -dimensions of the image must be specified in square brackets following -the filename (e.g. rawfile.dat[ib512,512]). The first character (case -insensitive) defines the data type of the array: - -\begin{verbatim} - b 8-bit unsigned byte - i 16-bit signed integer - u 16-bit unsigned integer - j 32-bit signed integer - r or f 32-bit floating point - d 64-bit floating point -\end{verbatim} -An optional second character specifies the byte order of the array -values: b or B indicates big endian (as in FITS files and the native -format of SUN UNIX workstations and Mac PCs) and l or L indicates -little endian (native format of DEC OSF workstations and IBM PCs). If -this character is omitted then the array is assumed to have the native -byte order of the local machine. These data type characters are then -followed by a series of one or more integer values separated by commas -which define the size of each dimension of the raw array. Arrays with -up to 5 dimensions are currently supported. Finally, a byte offset to -the position of the first pixel in the data file may be specified by -separating it with a ':' from the last dimension value. If omitted, it -is assumed that the offset = 0. This parameter may be used to skip -over any header information in the file that precedes the binary data. -Further examples: - -\begin{verbatim} - raw.dat[b10000] 1-dimensional 10000 pixel byte array - raw.dat[rb400,400,12] 3-dimensional floating point big-endian array - img.fits[ib512,512:2880] reads the 512 x 512 short integer array in - a FITS file, skipping over the 2880 byte header -\end{verbatim} - -One special case of input file is where the filename = `-' (a dash or -minus sign) or 'stdin' or 'stdout', which signifies that the input file -is to be read from the stdin stream, or written to the stdout stream if -a new output file is being created. In the case of reading from stdin, -CFITSIO first copies the whole stream into a temporary FITS file (in -memory or on disk), and subsequent reading of the FITS file occurs in -this copy. When writing to stdout, CFITSIO first constructs the whole -file in memory (since random access is required), then flushes it out -to the stdout stream when the file is closed. In addition, if the -output filename = '-.gz' or 'stdout.gz' then it will be gzip compressed -before being written to stdout. - -This ability to read and write on the stdin and stdout steams allows -FITS files to be piped between tasks in memory rather than having to -create temporary intermediate FITS files on disk. For example if task1 -creates an output FITS file, and task2 reads an input FITS file, the -FITS file may be piped between the 2 tasks by specifying - -\begin{verbatim} - task1 - | task2 - -\end{verbatim} -where the vertical bar is the Unix piping symbol. This assumes that the 2 -tasks read the name of the FITS file off of the command line. - - -\section{Output File Name when Opening an Existing File} - -An optional output filename may be specified in parentheses immediately -following the base file name to be opened. This is mainly useful in -those cases where CFITSIO creates a temporary copy of the input FITS -file before it is opened and passed to the application program. This -happens by default when opening a network FTP or HTTP-type file, when -reading a compressed FITS file on a local disk, when reading from the -stdin stream, or when a column filter, row filter, or binning specifier -is included as part of the input file specification. By default this -temporary file is created in memory. If there is not enough memory to -create the file copy, then CFITSIO will exit with an error. In these -cases one can force a permanent file to be created on disk, instead of -a temporary file in memory, by supplying the name in parentheses -immediately following the base file name. The output filename can -include the '!' clobber flag. - -Thus, if the input filename to CFITSIO is: -\verb+file1.fits.gz(file2.fits)+ -then CFITSIO will uncompress `file1.fits.gz' into the local disk file -`file2.fits' before opening it. CFITSIO does not automatically delete -the output file, so it will still exist after the application program -exits. - -The output filename "mem://" is also allowed, which will write the -output file into memory, and also allow write access to the file. This -'file' will disappear when it is closed, but this may be useful for -some applications which only need to modify a temporary copy of the file. - -In some cases, several different temporary FITS files will be created -in sequence, for instance, if one opens a remote file using FTP, then -filters rows in a binary table extension, then create an image by -binning a pair of columns. In this case, the remote file will be -copied to a temporary local file, then a second temporary file will be -created containing the filtered rows of the table, and finally a third -temporary file containing the binned image will be created. In cases -like this where multiple files are created, the outfile specifier will -be interpreted the name of the final file as described below, in descending -priority: - -\begin{itemize} -\item -as the name of the final image file if an image within a single binary -table cell is opened or if an image is created by binning a table column. -\item -as the name of the file containing the filtered table if a column filter -and/or a row filter are specified. -\item -as the name of the local copy of the remote FTP or HTTP file. -\item -as the name of the uncompressed version of the FITS file, if a -compressed FITS file on local disk has been opened. -\item -otherwise, the output filename is ignored. -\end{itemize} - -The output file specifier is useful when reading FTP or HTTP-type -FITS files since it can be used to create a local disk copy of the file -that can be reused in the future. If the output file name = `*' then a -local file with the same name as the network file will be created. -Note that CFITSIO will behave differently depending on whether the -remote file is compressed or not as shown by the following examples: -\begin{itemize} -\item -\verb+ftp://remote.machine/tmp/myfile.fits.gz(*)+ - the remote compressed -file is copied to the local compressed file `myfile.fits.gz', which -is then uncompressed in local memory before being opened and passed -to the application program. - -\item -\verb+ftp://remote.machine/tmp/myfile.fits.gz(myfile.fits)+ - the -remote compressed file is copied and uncompressed into the local file -`myfile.fits'. This example requires less local memory than the -previous example since the file is uncompressed on disk instead of in -memory. - -\item -\verb+ftp://remote.machine/tmp/myfile.fits(myfile.fits.gz)+ - this will -usually produce an error since CFITSIO itself cannot compress files. -\end{itemize} - -The exact behavior of CFITSIO in the latter case depends on the type of -ftp server running on the remote machine and how it is configured. In -some cases, if the file `myfile.fits.gz' exists on the remote machine, -then the server will copy it to the local machine. In other cases the -ftp server will automatically create and transmit a compressed version -of the file if only the uncompressed version exists. This can get -rather confusing, so users should use a certain amount of caution when -using the output file specifier with FTP or HTTP file types, to make -sure they get the behavior that they expect. - - -\section{Template File Name when Creating a New File} - -When a new FITS file is created with a call to fits\_create\_file, the -name of a template file may be supplied in parentheses immediately -following the name of the new file to be created. This template is -used to define the structure of one or more HDUs in the new file. The -template file may be another FITS file, in which case the newly created -file will have exactly the same keywords in each HDU as in the template -FITS file, but all the data units will be filled with zeros. The -template file may also be an ASCII text file, where each line (in -general) describes one FITS keyword record. The format of the ASCII -template file is described in the following Template Files chapter. - - -\section{Image Tile-Compression Specification} - -When specifying the name of the output FITS file to be created, the -user can indicate that images should be written in tile-compressed -format (see section 5.5, ``Primary Array or IMAGE Extension I/O -Routines'') by enclosing the compression parameters in square brackets -following the root disk file name. Here are some examples of the -syntax for specifying tile-compressed output images: - -\begin{verbatim} - myfile.fit[compress] - use Rice algorithm and default tile size - - myfile.fit[compress GZIP] - use the specified compression algorithm; - myfile.fit[compress Rice] only the first letter of the algorithm - myfile.fit[compress PLIO] name is required. - - myfile.fit[compress Rice 100,100] - use 100 x 100 pixel tile size - myfile.fit[compress Rice 100,100;2] - as above, and use noisebits = 2 -\end{verbatim} - - -\section{HDU Location Specification} - -The optional HDU location specifier defines which HDU (Header-Data -Unit, also known as an `extension') within the FITS file to initially -open. It must immediately follow the base file name (or the output -file name if present). If it is not specified then the first HDU (the -primary array) is opened. The HDU location specifier is required if -the colFilter, rowFilter, or binSpec specifiers are present, because -the primary array is not a valid HDU for these operations. The HDU may -be specified either by absolute position number, starting with 0 for -the primary array, or by reference to the HDU name, and optionally, the -version number and the HDU type of the desired extension. The location -of an image within a single cell of a binary table may also be -specified, as described below. - -The absolute position of the extension is specified either by enclosed -the number in square brackets (e.g., `[1]' = the first extension -following the primary array) or by preceded the number with a plus sign -(`+1'). To specify the HDU by name, give the name of the desired HDU -(the value of the EXTNAME or HDUNAME keyword) and optionally the -extension version number (value of the EXTVER keyword) and the -extension type (value of the XTENSION keyword: IMAGE, ASCII or TABLE, -or BINTABLE), separated by commas and all enclosed in square brackets. -If the value of EXTVER and XTENSION are not specified, then the first -extension with the correct value of EXTNAME is opened. The extension -name and type are not case sensitive, and the extension type may be -abbreviated to a single letter (e.g., I = IMAGE extension or primary -array, A or T = ASCII table extension, and B = binary table BINTABLE -extension). If the HDU location specifier is equal to `[PRIMARY]' or -`[P]', then the primary array (the first HDU) will be opened. - -An optional pound sign character ("\#") may be appended to the extension -name or number to signify that any other extensions in the file should -be ignored during any subsequent file filtering operations. For example, -when doing row filtering operations on a table extension, CFITSIO normally -creates a copy of the filtered table in memory, along with a verbatim -copy of all the other extensions in the input FITS file. If the pound -sign is appended to the table extension name, then only that extension, -and none of the other extensions in the file, will by copied to memory, -as in the following example: - -\begin{verbatim} - myfile.fit[events#][TIME > 10000] -\end{verbatim} - -FITS images are most commonly stored in the primary array or an image -extension, but images can also be stored as a vector in a single cell -of a binary table (i.e. each row of the vector column contains a -different image). Such an image can be opened with CFITSIO by -specifying the desired column name and the row number after the binary -table HDU specifier as shown in the following examples. The column name -is separated from the HDU specifier by a semicolon and the row number -is enclosed in parentheses. In this case CFITSIO copies the image from -the table cell into a temporary primary array before it is opened. The -application program then just sees the image in the primary array, -without any extensions. The particular row to be opened may be -specified either by giving an absolute integer row number (starting -with 1 for the first row), or by specifying a boolean expression that -evaluates to TRUE for the desired row. The first row that satisfies -the expression will be used. The row selection expression has the same -syntax as described in the Row Filter Specifier section, below. - - Examples: - -\begin{verbatim} - myfile.fits[3] - open the 3rd HDU following the primary array - myfile.fits+3 - same as above, but using the FTOOLS-style notation - myfile.fits[EVENTS] - open the extension that has EXTNAME = 'EVENTS' - myfile.fits[EVENTS, 2] - same as above, but also requires EXTVER = 2 - myfile.fits[events,2,b] - same, but also requires XTENSION = 'BINTABLE' - myfile.fits[3; images(17)] - opens the image in row 17 of the 'images' - column in the 3rd extension of the file. - myfile.fits[3; images(exposure > 100)] - as above, but opens the image - in the first row that has an 'exposure' column value - greater than 100. -\end{verbatim} - - -\section{Image Section} - -A virtual file containing a rectangular subsection of an image can be -extracted and opened by specifying the range of pixels (start:end) -along each axis to be extracted from the original image. One can also -specify an optional pixel increment (start:end:step) for each axis of -the input image. A pixel step = 1 will be assumed if it is not -specified. If the start pixel is larger then the end pixel, then the -image will be flipped (producing a mirror image) along that dimension. -An asterisk, '*', may be used to specify the entire range of an axis, -and '-*' will flip the entire axis. The input image can be in the -primary array, in an image extension, or contained in a vector cell of -a binary table. In the later 2 cases the extension name or number must -be specified before the image section specifier. - - Examples: - -\begin{verbatim} - myfile.fits[1:512:2, 2:512:2] - open a 256x256 pixel image - consisting of the odd numbered columns (1st axis) and - the even numbered rows (2nd axis) of the image in the - primary array of the file. - - myfile.fits[*, 512:256] - open an image consisting of all the columns - in the input image, but only rows 256 through 512. - The image will be flipped along the 2nd axis since - the starting pixel is greater than the ending pixel. - - myfile.fits[*:2, 512:256:2] - same as above but keeping only - every other row and column in the input image. - - myfile.fits[-*, *] - copy the entire image, flipping it along - the first axis. - - myfile.fits[3][1:256,1:256] - opens a subsection of the image that - is in the 3rd extension of the file. - - myfile.fits[4; images(12)][1:10,1:10] - open an image consisting - of the first 10 pixels in both dimensions. The original - image resides in the 12th row of the 'images' vector - column in the table in the 4th extension of the file. -\end{verbatim} - -When CFITSIO opens an image section it first creates a temporary file -containing the image section plus a copy of any other HDUs in the -file. (If a `\#' character is appended to the name or number of the -image HDU, as in "myfile.fits[1\#][1:200,1:200]", then the other -HDUs in the input file will not be copied into memory). -This temporary file is then opened by the application program, -so it is not possible to write to or modify the input file when -specifying an image section. Note that CFITSIO automatically updates -the world coordinate system keywords in the header of the image -section, if they exist, so that the coordinate associated with each -pixel in the image section will be computed correctly. - - -\section{Image Transform Filters} - -CFITSIO can apply a user-specified mathematical function to the value -of every pixel in a FITS image, thus creating a new virtual image -in computer memory that is then opened and read by the application -program. The original FITS image is not modified by this process. - -The image transformation specifier is appended to the input -FITS file name and is enclosed in square brackets. It begins with the -letters 'PIX' to distinguish it from other types of FITS file filters -that are recognized by CFITSIO. The image transforming function may -use any of the mathematical operators listed in the following -'Row Filtering Specification' section of this document. -Some examples of image transform filters are: - -\begin{verbatim} - [pix X * 2.0] - multiply each pixel by 2.0 - [pix sqrt(X)] - take the square root of each pixel - [pix X + #ZEROPT - add the value of the ZEROPT keyword - [pix X>0 ? log10(X) : -99.] - if the pixel value is greater - than 0, compute the base 10 log, - else set the pixel = -99. -\end{verbatim} -Use the letter 'X' in the expression to represent the current pixel value -in the image. The expression is evaluated -independently for each pixel in the image and may be a function of 1) the -original pixel value, 2) the value of other pixels in the image at -a given relative offset from the position of the pixel that is being -evaluated, and 3) the value of -any header keywords. Header keyword values are represented -by the name of the keyword preceded by the '\#' sign. - - -To access the the value of adjacent pixels in the image, -specify the (1-D) offset from the current pixel in curly brackets. -For example - -\begin{verbatim} - [pix (x{-1} + x + x{+1}) / 3] -\end{verbatim} -will replace each pixel value with the running mean of the values of that -pixel and it's 2 neighboring pixels. Note that in this notation the image -is treated as a 1-D array, where each row of the image (or higher dimensional -cube) is appended one after another in one long array of pixels. -It is possible to refer to pixels -in the rows above or below the current pixel by using the value of the -NAXIS1 header keyword. For example - -\begin{verbatim} - [pix (x{-#NAXIS1} + x + x{#NAXIS1}) / 3] -\end{verbatim} -will compute the mean of each image pixel and the pixels immediately -above and below it in the adjacent rows of the image. -The following more complex example -creates a smoothed virtual image where each pixel -is a 3 x 3 boxcar average of the input image pixels: - -\begin{verbatim} - [pix (X + X{-1} + X{+1} - + X{-#NAXIS1} + X{-#NAXIS1 - 1} + X{-#NAXIS1 + 1} - + X{#NAXIS1} + X{#NAXIS1 - 1} + X{#NAXIS1 + 1}) / 9.] -\end{verbatim} -If the pixel offset -extends beyond the first or last pixel in the image, the function will -evaluate to undefined, or NULL. - -For complex or commonly used image filtering operations, -one can write the expression into an external text file and -then import it into the -filter using the syntax '[pix @filename.txt]'. The mathematical -expression can -extend over multiple lines of text in the file. -Any lines in the external text file -that begin with 2 slash characters ('//') will be ignored and may be -used to add comments into the file. - -By default, the datatype of the resulting image will be the same as -the original image, but one may force a different datatype by appended -a code letter to the 'pix' keyword: - -\begin{verbatim} - pixb - 8-bit byte image with BITPIX = 8 - pixi - 16-bit integer image with BITPIX = 16 - pixj - 32-bit integer image with BITPIX = 32 - pixr - 32-bit float image with BITPIX = -32 - pixd - 64-bit float image with BITPIX = -64 -\end{verbatim} -Also by default, any other HDUs in the input file will be copied without -change to the -output virtual FITS file, but one may discard the other HDUs by adding -the number '1' to the 'pix' keyword (and following any optional datatype code -letter). For example: - -\begin{verbatim} - myfile.fits[3][pixr1 sqrt(X)] -\end{verbatim} -will create a virtual FITS file containing only a primary array image -with 32-bit floating point pixels that have a value equal to the square -root of the pixels in the image that is in the 3rd extension -of the 'myfile.fits' file. - - - -\section{Column and Keyword Filtering Specification} - -The optional column/keyword filtering specifier is used to modify the -column structure and/or the header keywords in the HDU that was -selected with the previous HDU location specifier. This filtering -specifier must be enclosed in square brackets and can be distinguished -from a general row filter specifier (described below) by the fact that -it begins with the string 'col ' and is not immediately followed by an -equals sign. The original file is not changed by this filtering -operation, and instead the modifications are made on a copy of the -input FITS file (usually in memory), which also contains a copy of all -the other HDUs in the file. (If a `\#' character is appended to the name -or number of the -table HDU then only the primary array, and none of the other -HDUs in the input file will be copied into memory). -This temporary file is passed to the -application program and will persist only until the file is closed or -until the program exits, unless the outfile specifier (see above) is -also supplied. - -The column/keyword filter can be used to perform the following -operations. More than one operation may be specified by separating -them with commas or semi-colons. - -\begin{itemize} - -\item -Copy only a specified list of columns columns to the filtered input file. -The list of column name should be separated by commas or semi-colons. Wild card -characters may be used in the column names to match multiple columns. -If the expression contains both a list of columns to be included and -columns to be deleted, then all the columns in the original table -except the explicitly deleted columns will appear in the filtered -table (i.e., there is no need to explicitly list the columns to -be included if any columns are being deleted). - -\item -Delete a column or keyword by listing the name preceded by a minus sign -or an exclamation mark (!), e.g., '-TIME' will delete the TIME column -if it exists, otherwise the TIME keyword. An error is returned if -neither a column nor keyword with this name exists. Note that the -exclamation point, '!', is a special UNIX character, so if it is used -on the command line rather than entered at a task prompt, it must be -preceded by a backslash to force the UNIX shell to ignore it. - -\item -Rename an existing column or keyword with the syntax 'NewName == -OldName'. An error is returned if neither a column nor keyword with -this name exists. - -\item -Append a new column or keyword to the table. To create a column, -give the new name, optionally followed by the data type in parentheses, -followed by a single equals sign and an expression to be used to -compute the value (e.g., 'newcol(1J) = 0' will create a new 32-bit -integer column called 'newcol' filled with zeros). The data type is -specified using the same syntax that is allowed for the value of the -FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for binary tables, -and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If the data type is -not specified then an appropriate data type will be chosen depending on -the form of the expression (may be a character string, logical, bit, long -integer, or double column). An appropriate vector count (in the case -of binary tables) will also be added if not explicitly specified. - -When creating a new keyword, the keyword name must be preceded by a -pound sign '\#', and the expression must evaluate to a scalar -(i.e., cannot have a column name in the expression). The comment -string for the keyword may be specified in parentheses immediately -following the keyword name (instead of supplying a data type as in -the case of creating a new column). If the keyword name ends with a -pound sign '\#', then cfitsio will substitute the number of the -most recently referenced column for the \# character . -This is especially useful when writing -a column-related keyword like TUNITn for a newly created column, -as shown in the following examples. - -COMMENT and HISTORY keywords may also be created with the following syntax: - -\begin{verbatim} - #COMMENT = 'This is a comment keyword' - #HISTORY = 'This is a history keyword' -\end{verbatim} -Note that the equal sign and the quote characters will be removed, so -that the resulting header keywords in these cases will look like this: - -\begin{verbatim} - COMMENT This is a comment keyword - HISTORY This is a history keyword -\end{verbatim} -These two special keywords are always appended to the end of the header -and will not affect any previously existing COMMENT or HISTORY keywords. - -\item -Recompute (overwrite) the values in an existing column or keyword by -giving the name followed by an equals sign and an arithmetic -expression. -\end{itemize} - -The expression that is used when appending or recomputing columns or -keywords can be arbitrarily complex and may be a function of other -header keyword values and other columns (in the same row). The full -syntax and available functions for the expression are described below -in the row filter specification section. - -If the expression contains both a list of columns to be included and -columns to be deleted, then all the columns in the original table -except the explicitly deleted columns will appear in the filtered -table. If no columns to be deleted are specified, then only the -columns that are explicitly listed will be included in the filtered -output table. To include all the columns, add the '*' wildcard -specifier at the end of the list, as shown in the examples. - -For complex or commonly used operations, one can place the -operations into an external text file and import it into the column -filter using the syntax '[col @filename.txt]'. The operations can -extend over multiple lines of the file, but multiple operations must -still be separated by commas or semi-colons. Any lines in the external text file -that begin with 2 slash characters ('//') will be ignored and may be -used to add comments into the file. - -Examples: - -\begin{verbatim} - [col Time, rate] - only the Time and rate columns will - appear in the filtered input file. - - [col Time, *raw] - include the Time column and any other - columns whose name ends with 'raw'. - - [col -TIME, Good == STATUS] - deletes the TIME column and - renames the status column to 'Good' - - [col PI=PHA * 1.1 + 0.2; #TUNIT#(column units) = 'counts';*] - - creates new PI column from PHA values - and also writes the TUNITn keyword - for the new column. The final '*' - expression means preserve all the - columns in the input table in the - virtual output table; without the '*' - the output table would only contain - the single 'PI' column. - - [col rate = rate/exposure; TUNIT#(&) = 'counts/s';*] - - recomputes the rate column by dividing - it by the EXPOSURE keyword value. This - also modifies the value of the TUNITn - keyword for this column. The use of the - '&' character for the keyword comment - string means preserve the existing - comment string for that keyword. The - final '*' preserves all the columns - in the input table in the virtual - output table. -\end{verbatim} - - -\section{Row Filtering Specification} - - When entering the name of a FITS table that is to be opened by a - program, an optional row filter may be specified to select a subset - of the rows in the table. A temporary new FITS file is created on - the fly which contains only those rows for which the row filter - expression evaluates to true. The primary array and any other - extensions in the input file are also copied to the temporary - file. -(If a `\#' character is appended to the name or number of the -table HDU then only the primary array, and none of the other -HDUs in the input file will be copied into the temporary file). - The original FITS file is closed and the new virtual file - is opened by the application program. The row filter expression is - enclosed in square brackets following the file name and extension - name (e.g., 'file.fits[events][GRADE==50]' selects only those rows - where the GRADE column value equals 50). When dealing with tables - where each row has an associated time and/or 2D spatial position, - the row filter expression can also be used to select rows based on - the times in a Good Time Intervals (GTI) extension, or on spatial - position as given in a SAO-style region file. - - -\subsection{General Syntax} - - The row filtering expression can be an arbitrarily complex series - of operations performed on constants, keyword values, and column - data taken from the specified FITS TABLE extension. The expression - must evaluate to a boolean value for each row of the table, where - a value of FALSE means that the row will be excluded. - - For complex or commonly used filters, one can place the expression - into a text file and import it into the row filter using the syntax - '[@filename.txt]'. The expression can be arbitrarily complex and - extend over multiple lines of the file. Any lines in the external - text file that begin with 2 slash characters ('//') will be ignored - and may be used to add comments into the file. - - Keyword and column data are referenced by name. Any string of - characters not surrounded by quotes (ie, a constant string) or - followed by an open parentheses (ie, a function name) will be - initially interpreted as a column name and its contents for the - current row inserted into the expression. If no such column exists, - a keyword of that name will be searched for and its value used, if - found. To force the name to be interpreted as a keyword (in case - there is both a column and keyword with the same name), precede the - keyword name with a single pound sign, '\#', as in '\#NAXIS2'. Due to - the generalities of FITS column and keyword names, if the column or - keyword name contains a space or a character which might appear as - an arithmetic term then enclose the name in '\$' characters as in - \$MAX PHA\$ or \#\$MAX-PHA\$. Names are case insensitive. - - To access a table entry in a row other than the current one, follow - the column's name with a row offset within curly braces. For - example, 'PHA\{-3\}' will evaluate to the value of column PHA, 3 rows - above the row currently being processed. One cannot specify an - absolute row number, only a relative offset. Rows that fall outside - the table will be treated as undefined, or NULLs. - - Boolean operators can be used in the expression in either their - Fortran or C forms. The following boolean operators are available: - -\begin{verbatim} - "equal" .eq. .EQ. == "not equal" .ne. .NE. != - "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< - "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => - "or" .or. .OR. || "and" .and. .AND. && - "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ -\end{verbatim} - -Note that the exclamation -point, '!', is a special UNIX character, so if it is used on the -command line rather than entered at a task prompt, it must be preceded -by a backslash to force the UNIX shell to ignore it. - - The expression may also include arithmetic operators and functions. - Trigonometric functions use radians, not degrees. The following - arithmetic operators and functions can be used in the expression - (function names are case insensitive). A null value will be returned - in case of illegal operations such as divide by zero, sqrt(negative) - log(negative), log10(negative), arccos(.gt. 1), arcsin(.gt. 1). - - -\begin{verbatim} - "addition" + "subtraction" - - "multiplication" * "division" / - "negation" - "exponentiation" ** ^ - "absolute value" abs(x) "cosine" cos(x) - "sine" sin(x) "tangent" tan(x) - "arc cosine" arccos(x) "arc sine" arcsin(x) - "arc tangent" arctan(x) "arc tangent" arctan2(y,x) - "hyperbolic cos" cosh(x) "hyperbolic sin" sinh(x) - "hyperbolic tan" tanh(x) "round to nearest int" round(x) - "round down to int" floor(x) "round up to int" ceil(x) - "exponential" exp(x) "square root" sqrt(x) - "natural log" log(x) "common log" log10(x) - "modulus" x % y "random # [0.0,1.0)" random() - "random Gaussian" randomn() "random Poisson" randomp(x) - "minimum" min(x,y) "maximum" max(x,y) - "cumulative sum" accum(x) "sequential difference" seqdiff(x) - "if-then-else" b?x:y - "angular separation" angsep(ra1,dec1,ra2,de2) (all in degrees) - "substring" strmid(s,p,n) "string search" strstr(s,r) -\end{verbatim} -Three different random number functions are provided: random(), with -no arguments, produces a uniform random deviate between 0 and 1; -randomn(), also with no arguments, produces a normal (Gaussian) random -deviate with zero mean and unit standard deviation; randomp(x) -produces a Poisson random deviate whose expected number of counts is -X. X may be any positive real number of expected counts, including -fractional values, but the return value is an integer. - -When the random functions are used in a vector expression, by default -the same random value will be used when evaluating each element of the vector. -If different random numbers are desired, then the name of a vector -column should be supplied as the single argument to the random -function (e.g., "flux + 0.1 * random(flux)", where "flux' is the -name of a vector column). This will create a vector of -random numbers that will be used in sequence when evaluating each -element of the vector expression. - -An alternate syntax for the min and max functions has only a single -argument which should be a vector value (see below). The result -will be the minimum/maximum element contained within the vector. - -The accum(x) function forms the cumulative sum of x, element by element. -Vector columns are supported simply by performing the summation process -through all the values. Null values are treated as 0. The seqdiff(x) -function forms the sequential difference of x, element by element. -The first value of seqdiff is the first value of x. A single null -value in x causes a pair of nulls in the output. The seqdiff and -accum functions are functional inverses, i.e., seqdiff(accum(x)) == x -as long as no null values are present. - -In the if-then-else expression, "b?x:y", b is an explicit boolean -value or expression. There is no automatic type conversion from -numeric to boolean values, so one needs to use "iVal!=0" instead of -merely "iVal" as the boolean argument. x and y can be any scalar data -type (including string). - -The angsep function computes the angular separation in degrees -between 2 celestial positions, where the first 2 parameters -give the RA-like and Dec-like coordinates (in decimal degrees) -of the first position, and the 3rd and 4th parameters give the -coordinates of the second position. - -The substring function strmid(S,P,N) extracts a substring from S, -starting at string position P, with a substring length N. The first -character position in S is labeled as 1. If P is 0, or refers to a -position beyond the end of S, then the extracted substring will be -NULL. S, P, and N may be functions of other columns. - -The string search function strstr(S,R) searches for the first occurrence -of the substring R in S. The result is an integer, indicating the -character position of the first match (where 1 is the first character -position of S). If no match is found, then strstr() returns a NULL -value. - -The following type casting operators are available, where the -inclosing parentheses are required and taken from the C language -usage. Also, the integer to real casts values to double precision: - -\begin{verbatim} - "real to integer" (int) x (INT) x - "integer to real" (float) i (FLOAT) i -\end{verbatim} - - In addition, several constants are built in for use in numerical - expressions: - - -\begin{verbatim} - #pi 3.1415... #e 2.7182... - #deg #pi/180 #row current row number - #null undefined value #snull undefined string -\end{verbatim} - - A string constant must be enclosed in quotes as in 'Crab'. The - "null" constants are useful for conditionally setting table values - to a NULL, or undefined, value (eg., "col1==-99 ? \#NULL : col1"). - - There is also a function for testing if two values are close to - each other, i.e., if they are "near" each other to within a user - specified tolerance. The arguments, value\_1 and value\_2 can be - integer or real and represent the two values who's proximity is - being tested to be within the specified tolerance, also an integer - or real: - -\begin{verbatim} - near(value_1, value_2, tolerance) -\end{verbatim} - When a NULL, or undefined, value is encountered in the FITS table, - the expression will evaluate to NULL unless the undefined value is - not actually required for evaluation, e.g. "TRUE .or. NULL" - evaluates to TRUE. The following two functions allow some NULL - detection and handling: - -\begin{verbatim} - "a null value?" ISNULL(x) - "define a value for null" DEFNULL(x,y) -\end{verbatim} - The former - returns a boolean value of TRUE if the argument x is NULL. The - later "defines" a value to be substituted for NULL values; it - returns the value of x if x is not NULL, otherwise it returns the - value of y. - - - - -\subsection{Bit Masks} - - Bit masks can be used to select out rows from bit columns (TFORMn = - \#X) in FITS files. To represent the mask, binary, octal, and hex - formats are allowed: - - -\begin{verbatim} - binary: b0110xx1010000101xxxx0001 - octal: o720x1 -> (b111010000xxx001) - hex: h0FxD -> (b00001111xxxx1101) -\end{verbatim} - - In all the representations, an x or X is allowed in the mask as a - wild card. Note that the x represents a different number of wild - card bits in each representation. All representations are case - insensitive. - - To construct the boolean expression using the mask as the boolean - equal operator described above on a bit table column. For example, - if you had a 7 bit column named flags in a FITS table and wanted - all rows having the bit pattern 0010011, the selection expression - would be: - - -\begin{verbatim} - flags == b0010011 - or - flags .eq. b10011 -\end{verbatim} - - It is also possible to test if a range of bits is less than, less - than equal, greater than and greater than equal to a particular - boolean value: - - -\begin{verbatim} - flags <= bxxx010xx - flags .gt. bxxx100xx - flags .le. b1xxxxxxx -\end{verbatim} - - Notice the use of the x bit value to limit the range of bits being - compared. - - It is not necessary to specify the leading (most significant) zero - (0) bits in the mask, as shown in the second expression above. - - Bit wise AND, OR and NOT operations are also possible on two or - more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) - operators. All of these operators result in a bit field which can - then be used with the equal operator. For example: - - -\begin{verbatim} - (!flags) == b1101100 - (flags & b1000001) == bx000001 -\end{verbatim} - - Bit fields can be appended as well using the '+' operator. Strings - can be concatenated this way, too. - - -\subsection{Vector Columns} - - Vector columns can also be used in building the expression. No - special syntax is required if one wants to operate on all elements - of the vector. Simply use the column name as for a scalar column. - Vector columns can be freely intermixed with scalar columns or - constants in virtually all expressions. The result will be of the - same dimension as the vector. Two vectors in an expression, though, - need to have the same number of elements and have the same - dimensions. - - Arithmetic and logical operations are all performed on an element by - element basis. Comparing two vector columns, eg "COL1 == COL2", - thus results in another vector of boolean values indicating which - elements of the two vectors are equal. - - Eight functions are available that operate on a vector and return a - scalar result: - -\begin{verbatim} - "minimum" MIN(V) "maximum" MAX(V) - "average" AVERAGE(V) "median" MEDIAN(V) - "summation" SUM(V) "standard deviation" STDDEV(V) - "# of values" NELEM(V) "# of non-null values" NVALID(V) -\end{verbatim} - where V represents the name of a vector column or a manually - constructed vector using curly brackets as described below. The - first 6 of these functions ignore any null values in the vector when - computing the result. The STDDEV() function computes the sample - standard deviation, i.e. it is proportional to 1/SQRT(N-1) instead - of 1/SQRT(N), where N is NVALID(V). - - The SUM function literally sums all the elements in x, returning a - scalar value. If V is a boolean vector, SUM returns the number - of TRUE elements. The NELEM function returns the number of elements - in vector V whereas NVALID return the number of non-null elements in - the vector. (NELEM also operates on bit and string columns, - returning their column widths.) As an example, to test whether all - elements of two vectors satisfy a given logical comparison, one can - use the expression - -\begin{verbatim} - SUM( COL1 > COL2 ) == NELEM( COL1 ) -\end{verbatim} - - which will return TRUE if all elements of COL1 are greater than - their corresponding elements in COL2. - - To specify a single element of a vector, give the column name - followed by a comma-separated list of coordinates enclosed in - square brackets. For example, if a vector column named PHAS exists - in the table as a one dimensional, 256 component list of numbers - from which you wanted to select the 57th component for use in the - expression, then PHAS[57] would do the trick. Higher dimensional - arrays of data may appear in a column. But in order to interpret - them, the TDIMn keyword must appear in the header. Assuming that a - (4,4,4,4) array is packed into each row of a column named ARRAY4D, - the (1,2,3,4) component element of each row is accessed by - ARRAY4D[1,2,3,4]. Arrays up to dimension 5 are currently - supported. Each vector index can itself be an expression, although - it must evaluate to an integer value within the bounds of the - vector. Vector columns which contain spaces or arithmetic operators - must have their names enclosed in "\$" characters as with - \$ARRAY-4D\$[1,2,3,4]. - - A more C-like syntax for specifying vector indices is also - available. The element used in the preceding example alternatively - could be specified with the syntax ARRAY4D[4][3][2][1]. Note the - reverse order of indices (as in C), as well as the fact that the - values are still ones-based (as in Fortran -- adopted to avoid - ambiguity for 1D vectors). With this syntax, one does not need to - specify all of the indices. To extract a 3D slice of this 4D - array, use ARRAY4D[4]. - - Variable-length vector columns are not supported. - - Vectors can be manually constructed within the expression using a - comma-separated list of elements surrounded by curly braces ('\{\}'). - For example, '\{1,3,6,1\}' is a 4-element vector containing the values - 1, 3, 6, and 1. The vector can contain only boolean, integer, and - real values (or expressions). The elements will be promoted to the - highest data type present. Any elements which are themselves - vectors, will be expanded out with each of its elements becoming an - element in the constructed vector. - - -\subsection{Good Time Interval Filtering} - - A common filtering method involves selecting rows which have a time - value which lies within what is called a Good Time Interval or GTI. - The time intervals are defined in a separate FITS table extension - which contains 2 columns giving the start and stop time of each - good interval. The filtering operation accepts only those rows of - the input table which have an associated time which falls within - one of the time intervals defined in the GTI extension. A high - level function, gtifilter(a,b,c,d), is available which evaluates - each row of the input table and returns TRUE or FALSE depending - whether the row is inside or outside the good time interval. The - syntax is - -\begin{verbatim} - gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) - or - gtifilter( [ 'gtifile' [, expr [, 'STARTCOL', 'STOPCOL' ] ] ] ) -\end{verbatim} - where each "[]" demarks optional parameters. Note that the quotes - around the gtifile and START/STOP column are required. Either single - or double quotes may be used. In cases where this expression is - entered on the Unix command line, enclose the entire expression in - double quotes, and then use single quotes within the expression to - enclose the 'gtifile' and other terms. It is also usually possible - to do the reverse, and enclose the whole expression in single quotes - and then use double quotes within the expression. The gtifile, - if specified, can be blank ("") which will mean to use the first - extension with the name "*GTI*" in the current file, a plain - extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be - used to select an extension in the current file, or a regular - filename with or without an extension specifier which in the latter - case will mean to use the first extension with an extension name - "*GTI*". Expr can be any arithmetic expression, including simply - the time column name. A vector time expression will produce a - vector boolean result. STARTCOL and STOPCOL are the names of the - START/STOP columns in the GTI extension. If one of them is - specified, they both must be. - - In its simplest form, no parameters need to be provided -- default - values will be used. The expression "gtifilter()" is equivalent to - -\begin{verbatim} - gtifilter( "", TIME, "*START*", "*STOP*" ) -\end{verbatim} - This will search the current file for a GTI extension, filter the - TIME column in the current table, using START/STOP times taken from - columns in the GTI extension with names containing the strings - "START" and "STOP". The wildcards ('*') allow slight variations in - naming conventions such as "TSTART" or "STARTTIME". The same - default values apply for unspecified parameters when the first one - or two parameters are specified. The function automatically - searches for TIMEZERO/I/F keywords in the current and GTI - extensions, applying a relative time offset, if necessary. - - -\subsection{Spatial Region Filtering} - - Another common filtering method selects rows based on whether the - spatial position associated with each row is located within a given - 2-dimensional region. The syntax for this high-level filter is - -\begin{verbatim} - regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) -\end{verbatim} - where each "[]" demarks optional parameters. The region file name - is required and must be enclosed in quotes. The remaining - parameters are optional. There are 2 supported formats for the - region file: ASCII file or FITS binary table. The region file - contains a list of one or more geometric shapes (circle, - ellipse, box, etc.) which defines a region on the celestial sphere - or an area within a particular 2D image. The region file is - typically generated using an image display program such as fv/POW - (distribute by the HEASARC), or ds9 (distributed by the Smithsonian - Astrophysical Observatory). Users should refer to the documentation - provided with these programs for more details on the syntax used in - the region files. The FITS region file format is defined in a document - available from the FITS Support Office at - http://fits.gsfc.nasa.gov/ registry/ region.html - - In its simplest form, (e.g., regfilter("region.reg") ) the - coordinates in the default 'X' and 'Y' columns will be used to - determine if each row is inside or outside the area specified in - the region file. Alternate position column names, or expressions, - may be entered if needed, as in - -\begin{verbatim} - regfilter("region.reg", XPOS, YPOS) -\end{verbatim} - Region filtering can be applied most unambiguously if the positions - in the region file and in the table to be filtered are both give in - terms of absolute celestial coordinate units. In this case the - locations and sizes of the geometric shapes in the region file are - specified in angular units on the sky (e.g., positions given in - R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, - each row of the filtered table will have a celestial coordinate - associated with it. This association is usually implemented using - a set of so-called 'World Coordinate System' (or WCS) FITS keywords - that define the coordinate transformation that must be applied to - the values in the 'X' and 'Y' columns to calculate the coordinate. - - Alternatively, one can perform spatial filtering using unitless - 'pixel' coordinates for the regions and row positions. In this - case the user must be careful to ensure that the positions in the 2 - files are self-consistent. A typical problem is that the region - file may be generated using a binned image, but the unbinned - coordinates are given in the event table. The ROSAT events files, - for example, have X and Y pixel coordinates that range from 1 - - 15360. These coordinates are typically binned by a factor of 32 to - produce a 480x480 pixel image. If one then uses a region file - generated from this image (in image pixel units) to filter the - ROSAT events file, then the X and Y column values must be converted - to corresponding pixel units as in: - -\begin{verbatim} - regfilter("rosat.reg", X/32.+.5, Y/32.+.5) -\end{verbatim} - Note that this binning conversion is not necessary if the region - file is specified using celestial coordinate units instead of pixel - units because CFITSIO is then able to directly compare the - celestial coordinate of each row in the table with the celestial - coordinates in the region file without having to know anything - about how the image may have been binned. - - The last "wcs cols" parameter should rarely be needed. If supplied, - this string contains the names of the 2 columns (space or comma - separated) which have the associated WCS keywords. If not supplied, - the filter will scan the X and Y expressions for column names. - If only one is found in each expression, those columns will be - used, otherwise an error will be returned. - - These region shapes are supported (names are case insensitive): - -\begin{verbatim} - Point ( X1, Y1 ) <- One pixel square region - Line ( X1, Y1, X2, Y2 ) <- One pixel wide region - Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with - Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered - Box ( Xc, Yc, Wdth, Hght, A ) V within the region - Diamond ( Xc, Yc, Wdth, Hght, A ) - Circle ( Xc, Yc, R ) - Annulus ( Xc, Yc, Rin, Rout ) - Ellipse ( Xc, Yc, Rx, Ry, A ) - Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) - Sector ( Xc, Yc, Amin, Amax ) -\end{verbatim} - where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are - the coordinates of the shape's edges; Rxxx are the shapes' various - Radii or semimajor/minor axes; and Axxx are the angles of rotation - (or bounding angles for Sector) in degrees. For rotated shapes, the - rotation angle can be left off, indicating no rotation. Common - alternate names for the regions can also be used: rotbox = box; - rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie - = sector. When a shape's name is preceded by a minus sign, '-', - the defined region is instead the area *outside* its boundary (ie, - the region is inverted). All the shapes within a single region - file are OR'd together to create the region, and the order is - significant. The overall way of looking at region files is that if - the first region is an excluded region then a dummy included region - of the whole detector is inserted in the front. Then each region - specification as it is processed overrides any selections inside of - that region specified by previous regions. Another way of thinking - about this is that if a previous excluded region is completely - inside of a subsequent included region the excluded region is - ignored. - - The positional coordinates may be given either in pixel units, - decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes - may be given in pixels, degrees, arcminutes, or arcseconds. Look - at examples of region file produced by fv/POW or ds9 for further - details of the region file format. - - There are three low-level functions that are primarily for use with - regfilter function, but they can be called directly. They - return a boolean true or false depending on whether a two - dimensional point is in the region or not. The positional coordinates - must be given in pixel units: - -\begin{verbatim} - "point in a circular region" - circle(xcntr,ycntr,radius,Xcolumn,Ycolumn) - - "point in an elliptical region" - ellipse(xcntr,ycntr,xhlf_wdth,yhlf_wdth,rotation,Xcolumn,Ycolumn) - - "point in a rectangular region" - box(xcntr,ycntr,xfll_wdth,yfll_wdth,rotation,Xcolumn,Ycolumn) - - where - (xcntr,ycntr) are the (x,y) position of the center of the region - (xhlf_wdth,yhlf_wdth) are the (x,y) half widths of the region - (xfll_wdth,yfll_wdth) are the (x,y) full widths of the region - (radius) is half the diameter of the circle - (rotation) is the angle(degrees) that the region is rotated with - respect to (xcntr,ycntr) - (Xcoord,Ycoord) are the (x,y) coordinates to test, usually column - names - NOTE: each parameter can itself be an expression, not merely a - column name or constant. -\end{verbatim} - - -\subsection{Example Row Filters} - -\begin{verbatim} - [ binary && mag <= 5.0] - Extract all binary stars brighter - than fifth magnitude (note that - the initial space is necessary to - prevent it from being treated as a - binning specification) - - [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 - - [IMAGE[4,5] .gt. 100] - Extract all rows that have the - (4,5) component of the IMAGE column - greater than 100 - - [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the - absolute value of the sine of theta - less than a half where the angles - are tabulated in degrees - - [SUM( SPEC > 3*BACKGRND )>=1] - Extract all rows containing a - spectrum, held in vector column - SPEC, with at least one value 3 - times greater than the background - level held in a keyword, BACKGRND - - [VCOL=={1,4,2}] - Extract all rows whose vector column - VCOL contains the 3-elements 1, 4, and - 2. - - [@rowFilter.txt] - Extract rows using the expression - contained within the text file - rowFilter.txt - - [gtifilter()] - Search the current file for a GTI - extension, filter the TIME - column in the current table, using - START/STOP times taken from - columns in the GTI extension - - [regfilter("pow.reg")] - Extract rows which have a coordinate - (as given in the X and Y columns) - within the spatial region specified - in the pow.reg region file. - - [regfilter("pow.reg", Xs, Ys)] - Same as above, except that the - Xs and Ys columns will be used to - determine the coordinate of each - row in the table. -\end{verbatim} - - -\section{ Binning or Histogramming Specification} - -The optional binning specifier is enclosed in square brackets and can -be distinguished from a general row filter specification by the fact -that it begins with the keyword 'bin' not immediately followed by an -equals sign. When binning is specified, a temporary N-dimensional FITS -primary array is created by computing the histogram of the values in -the specified columns of a FITS table extension. After the histogram -is computed the input FITS file containing the table is then closed and -the temporary FITS primary array is opened and passed to the -application program. Thus, the application program never sees the -original FITS table and only sees the image in the new temporary file -(which has no additional extensions). Obviously, the application -program must be expecting to open a FITS image and not a FITS table in -this case. - -The data type of the FITS histogram image may be specified by appending -'b' (for 8-bit byte), 'i' (for 16-bit integers), 'j' (for 32-bit -integer), 'r' (for 32-bit floating points), or 'd' (for 64-bit double -precision floating point) to the 'bin' keyword (e.g. '[binr X]' -creates a real floating point image). If the data type is not -explicitly specified then a 32-bit integer image will be created by -default, unless the weighting option is also specified in which case -the image will have a 32-bit floating point data type by default. - -The histogram image may have from 1 to 4 dimensions (axes), depending -on the number of columns that are specified. The general form of the -binning specification is: - -\begin{verbatim} - [bin{bijrd} Xcol=min:max:binsize, Ycol= ..., Zcol=..., Tcol=...; weight] -\end{verbatim} -in which up to 4 columns, each corresponding to an axis of the image, -are listed. The column names are case insensitive, and the column -number may be given instead of the name, preceded by a pound sign -(e.g., [bin \#4=1:512]). If the column name is not specified, then -CFITSIO will first try to use the 'preferred column' as specified by -the CPREF keyword if it exists (e.g., 'CPREF = 'DETX,DETY'), otherwise -column names 'X', 'Y', 'Z', and 'T' will be assumed for each of the 4 -axes, respectively. In cases where the column name could be confused -with an arithmetic expression, enclose the column name in parentheses to -force the name to be interpreted literally. - -Each column name may be followed by an equals sign and then the lower -and upper range of the histogram, and the size of the histogram bins, -separated by colons. Spaces are allowed before and after the equals -sign but not within the 'min:max:binsize' string. The min, max and -binsize values may be integer or floating point numbers, or they may be -the names of keywords in the header of the table. If the latter, then -the value of that keyword is substituted into the expression. - -Default values for the min, max and binsize quantities will be -used if not explicitly given in the binning expression as shown -in these examples: - -\begin{verbatim} - [bin x = :512:2] - use default minimum value - [bin x = 1::2] - use default maximum value - [bin x = 1:512] - use default bin size - [bin x = 1:] - use default maximum value and bin size - [bin x = :512] - use default minimum value and bin size - [bin x = 2] - use default minimum and maximum values - [bin x] - use default minimum, maximum and bin size - [bin 4] - default 2-D image, bin size = 4 in both axes - [bin] - default 2-D image -\end{verbatim} -CFITSIO will use the value of the TLMINn, TLMAXn, and TDBINn keywords, -if they exist, for the default min, max, and binsize, respectively. If -they do not exist then CFITSIO will use the actual minimum and maximum -values in the column for the histogram min and max values. The default -binsize will be set to 1, or (max - min) / 10., whichever is smaller, -so that the histogram will have at least 10 bins along each axis. - -A shortcut notation is allowed if all the columns/axes have the same -binning specification. In this case all the column names may be listed -within parentheses, followed by the (single) binning specification, as -in: - -\begin{verbatim} - [bin (X,Y)=1:512:2] - [bin (X,Y) = 5] -\end{verbatim} - -The optional weighting factor is the last item in the binning specifier -and, if present, is separated from the list of columns by a -semi-colon. As the histogram is accumulated, this weight is used to -incremented the value of the appropriated bin in the histogram. If the -weighting factor is not specified, then the default weight = 1 is -assumed. The weighting factor may be a constant integer or floating -point number, or the name of a keyword containing the weighting value. -Or the weighting factor may be the name of a table column in which case -the value in that column, on a row by row basis, will be used. - -In some cases, the column or keyword may give the reciprocal of the -actual weight value that is needed. In this case, precede the weight -keyword or column name by a slash '/' to tell CFITSIO to use the -reciprocal of the value when constructing the histogram. - -For complex or commonly used histograms, one can also place its -description into a text file and import it into the binning -specification using the syntax [bin @filename.txt]. The file's -contents can extend over multiple lines, although it must still -conform to the no-spaces rule for the min:max:binsize syntax and each -axis specification must still be comma-separated. Any lines in the -external text file that begin with 2 slash characters ('//') will be -ignored and may be used to add comments into the file. - - Examples: - - -\begin{verbatim} - [bini detx, dety] - 2-D, 16-bit integer histogram - of DETX and DETY columns, using - default values for the histogram - range and binsize - - [bin (detx, dety)=16; /exposure] - 2-D, 32-bit real histogram of DETX - and DETY columns with a bin size = 16 - in both axes. The histogram values - are divided by the EXPOSURE keyword - value. - - [bin time=TSTART:TSTOP:0.1] - 1-D lightcurve, range determined by - the TSTART and TSTOP keywords, - with 0.1 unit size bins. - - [bin pha, time=8000.:8100.:0.1] - 2-D image using default binning - of the PHA column for the X axis, - and 1000 bins in the range - 8000. to 8100. for the Y axis. - - [bin @binFilter.txt] - Use the contents of the text file - binFilter.txt for the binning - specifications. - -\end{verbatim} -\chapter{Template Files } - -When a new FITS file is created with a call to fits\_create\_file, the -name of a template file may be supplied in parentheses immediately -following the name of the new file to be created. This template is -used to define the structure of one or more HDUs in the new file. The -template file may be another FITS file, in which case the newly created -file will have exactly the same keywords in each HDU as in the template -FITS file, but all the data units will be filled with zeros. The -template file may also be an ASCII text file, where each line (in -general) describes one FITS keyword record. The format of the ASCII -template file is described in the following sections. - - -\section{Detailed Template Line Format} - -The format of each ASCII template line closely follows the format of a -FITS keyword record: - -\begin{verbatim} - KEYWORD = KEYVALUE / COMMENT -\end{verbatim} -except that free format may be used (e.g., the equals sign may appear -at any position in the line) and TAB characters are allowed and are -treated the same as space characters. The KEYVALUE and COMMENT fields -are optional. The equals sign character is also optional, but it is -recommended that it be included for clarity. Any template line that -begins with the pound '\#' character is ignored by the template parser -and may be use to insert comments into the template file itself. - -The KEYWORD name field is limited to 8 characters in length and only -the letters A-Z, digits 0-9, and the hyphen and underscore characters -may be used, without any embedded spaces. Lowercase letters in the -template keyword name will be converted to uppercase. Leading spaces -in the template line preceding the keyword name are generally ignored, -except if the first 8 characters of a template line are all blank, then -the entire line is treated as a FITS comment keyword (with a blank -keyword name) and is copied verbatim into the FITS header. - -The KEYVALUE field may have any allowed FITS data type: character -string, logical, integer, real, complex integer, or complex real. Integer -values must be within the allowed range of a 'signed long' variable; -some C compilers only suppport 4-byte long integers with a range -from -2147483648 to +2147483647, whereas other C compilers support 8-byte -integers with a range of plus or minus 2**63. - -The character string values need not be enclosed in single quote characters -unless they are necessary to distinguish the string from a different -data type (e.g. 2.0 is a real but '2.0' is a string). The keyword has -an undefined (null) value if the template record only contains blanks -following the "=" or between the "=" and the "/" comment field -delimiter. - -String keyword values longer than 68 characters (the maximum length -that will fit in a single FITS keyword record) are permitted using the -CFITSIO long string convention. They can either be specified as a -single long line in the template, or by using multiple lines where the -continuing lines contain the 'CONTINUE' keyword, as in this example: - -\begin{verbatim} - LONGKEY = 'This is a long string value that is contin&' - CONTINUE 'ued over 2 records' / comment field goes here -\end{verbatim} -The format of template lines with CONTINUE keyword is very strict: 3 -spaces must follow CONTINUE and the rest of the line is copied verbatim -to the FITS file. - -The start of the optional COMMENT field must be preceded by "/", which -is used to separate it from the keyword value field. Exceptions are if -the KEYWORD name field contains COMMENT, HISTORY, CONTINUE, or if the -first 8 characters of the template line are blanks. - -More than one Header-Data Unit (HDU) may be defined in the template -file. The start of an HDU definition is denoted with a SIMPLE or -XTENSION template line: - -1) SIMPLE begins a Primary HDU definition. SIMPLE may only appear as -the first keyword in the template file. If the template file begins -with XTENSION instead of SIMPLE, then a default empty Primary HDU is -created, and the template is then assumed to define the keywords -starting with the first extension following the Primary HDU. - -2) XTENSION marks the beginning of a new extension HDU definition. The -previous HDU will be closed at this point and processing of the next -extension begins. - - -\section{Auto-indexing of Keywords} - -If a template keyword name ends with a "\#" character, it is said to be -'auto-indexed'. Each "\#" character will be replaced by the current -integer index value, which gets reset = 1 at the start of each new HDU -in the file (or 7 in the special case of a GROUP definition). The -FIRST indexed keyword in each template HDU definition is used as the -'incrementor'; each subsequent occurrence of this SAME keyword will -cause the index value to be incremented. This behavior can be rather -subtle, as illustrated in the following examples in which the TTYPE -keyword is the incrementor in both cases: - -\begin{verbatim} - TTYPE# = TIME - TFORM# = 1D - TTYPE# = RATE - TFORM# = 1E -\end{verbatim} -will create TTYPE1, TFORM1, TTYPE2, and TFORM2 keywords. But if the -template looks like, - -\begin{verbatim} - TTYPE# = TIME - TTYPE# = RATE - TFORM# = 1D - TFORM# = 1E -\end{verbatim} -this results in a FITS files with TTYPE1, TTYPE2, TFORM2, and TFORM2, -which is probably not what was intended! - - -\section{Template Parser Directives} - -In addition to the template lines which define individual keywords, the -template parser recognizes 3 special directives which are each preceded -by the backslash character: \verb+ \include, \group+, and \verb+ \end+. - -The 'include' directive must be followed by a filename. It forces the -parser to temporarily stop reading the current template file and begin -reading the include file. Once the parser reaches the end of the -include file it continues parsing the current template file. Include -files can be nested, and HDU definitions can span multiple template -files. - -The start of a GROUP definition is denoted with the 'group' directive, -and the end of a GROUP definition is denoted with the 'end' directive. -Each GROUP contains 0 or more member blocks (HDUs or GROUPs). Member -blocks of type GROUP can contain their own member blocks. The GROUP -definition itself occupies one FITS file HDU of special type (GROUP -HDU), so if a template specifies 1 group with 1 member HDU like: - -\begin{verbatim} -\group -grpdescr = 'demo' -xtension bintable -# this bintable has 0 cols, 0 rows -\end -\end{verbatim} -then the parser creates a FITS file with 3 HDUs : - -\begin{verbatim} -1) dummy PHDU -2) GROUP HDU (has 1 member, which is bintable in HDU number 3) -3) bintable (member of GROUP in HDU number 2) -\end{verbatim} -Technically speaking, the GROUP HDU is a BINTABLE with 6 columns. Applications -can define additional columns in a GROUP HDU using TFORMn and TTYPEn -(where n is 7, 8, ....) keywords or their auto-indexing equivalents. - -For a more complicated example of a template file using the group directives, -look at the sample.tpl file that is included in the CFITSIO distribution. - - -\section{Formal Template Syntax} - -The template syntax can formally be defined as follows: - -\begin{verbatim} - TEMPLATE = BLOCK [ BLOCK ... ] - - BLOCK = { HDU | GROUP } - - GROUP = \GROUP [ BLOCK ... ] \END - - HDU = XTENSION [ LINE ... ] { XTENSION | \GROUP | \END | EOF } - - LINE = [ KEYWORD [ = ] ] [ VALUE ] [ / COMMENT ] - - X ... - X can be present 1 or more times - { X | Y } - X or Y - [ X ] - X is optional -\end{verbatim} - -At the topmost level, the template defines 1 or more template blocks. Blocks -can be either HDU (Header Data Unit) or a GROUP. For each block the parser -creates 1 (or more for GROUPs) FITS file HDUs. - - - -\section{Errors} - -In general the fits\_execute\_template() function tries to be as atomic -as possible, so either everything is done or nothing is done. If an -error occurs during parsing of the template, fits\_execute\_template() -will (try to) delete the top level BLOCK (with all its children if any) -in which the error occurred, then it will stop reading the template file -and it will return with an error. - - -\section{Examples} - -1. This template file will create a 200 x 300 pixel image, with 4-byte -integer pixel values, in the primary HDU: - -\begin{verbatim} - SIMPLE = T - BITPIX = 32 - NAXIS = 2 / number of dimensions - NAXIS1 = 100 / length of first axis - NAXIS2 = 200 / length of second axis - OBJECT = NGC 253 / name of observed object -\end{verbatim} -The allowed values of BITPIX are 8, 16, 32, -32, or -64, -representing, respectively, 8-bit integer, 16-bit integer, 32-bit -integer, 32-bit floating point, or 64 bit floating point pixels. - -2. To create a FITS table, the template first needs to include -XTENSION = TABLE or BINTABLE to define whether it is an ASCII or binary -table, and NAXIS2 to define the number of rows in the table. Two -template lines are then needed to define the name (TTYPEn) and FITS data -format (TFORMn) of the columns, as in this example: - -\begin{verbatim} - xtension = bintable - naxis2 = 40 - ttype# = Name - tform# = 10a - ttype# = Npoints - tform# = j - ttype# = Rate - tunit# = counts/s - tform# = e -\end{verbatim} -The above example defines a null primary array followed by a 40-row -binary table extension with 3 columns called 'Name', 'Npoints', and -'Rate', with data formats of '10A' (ASCII character string), '1J' -(integer) and '1E' (floating point), respectively. Note that the other -required FITS keywords (BITPIX, NAXIS, NAXIS1, PCOUNT, GCOUNT, TFIELDS, -and END) do not need to be explicitly defined in the template because -their values can be inferred from the other keywords in the template. -This example also illustrates that the templates are generally -case-insensitive (the keyword names and TFORMn values are converted to -upper-case in the FITS file) and that string keyword values generally -do not need to be enclosed in quotes. - -\chapter{ Local FITS Conventions } - -CFITSIO supports several local FITS conventions which are not -defined in the official FITS standard and which are not -necessarily recognized or supported by other FITS software packages. -Programmers should be cautious about using these features, especially -if the FITS files that are produced are expected to be processed by -other software systems which do not use the CFITSIO interface. - - -\section{64-Bit Long Integers} - -CFITSIO supports reading and writing FITS images or table columns containing -64-bit integer data values. Support for 64-bit integers was added to the -official FITS Standard in December 2005. - FITS 64-bit images have BITPIX = -64, and the 64-bit binary table columns have TFORMn = 'K'. CFITSIO also -supports the 'Q' variable-length array table column format which is -analogous to the 'P' column format except that the array descriptor -is stored as a pair of 64-bit integers. - -For the convenience of C programmers, the fitsio.h include file -defines (with a typedef statement) the 'LONGLONG' datatype to be -equivalent to an appropriate 64-bit integer datatype on each platform. -Since there is currently no universal standard -for the name of the 64-bit integer datatype (it might be defined as -'long long', 'long', or '\_\_int64' depending on the platform) -C programmers may prefer to use the 'LONGLONG' datatype when -declaring or allocating 64-bit integer quantities when writing -code which needs to run on multiple platforms. -Note that CFITSIO will implicitly convert the datatype when reading -or writing FITS 64-bit integer images and columns with data arrays of -a different integer or floating point datatype, but there is an -increased risk of loss of numerical precision or -numerical overflow in this case. - - -\section{Long String Keyword Values.} - -The length of a standard FITS string keyword is limited to 68 -characters because it must fit entirely within a single FITS header -keyword record. In some instances it is necessary to encode strings -longer than this limit, so CFITSIO supports a local convention in which -the string value is continued over multiple keywords. This -continuation convention uses an ampersand character at the end of each -substring to indicate that it is continued on the next keyword, and the -continuation keywords all have the name CONTINUE without an equal sign -in column 9. The string value may be continued in this way over as many -additional CONTINUE keywords as is required. The following lines -illustrate this continuation convention which is used in the value of -the STRKEY keyword: - -\begin{verbatim} -LONGSTRN= 'OGIP 1.0' / The OGIP Long String Convention may be used. -STRKEY = 'This is a very long string keyword&' / Optional Comment -CONTINUE ' value that is continued over 3 keywords in the & ' -CONTINUE 'FITS header.' / This is another optional comment. -\end{verbatim} -It is recommended that the LONGSTRN keyword, as shown here, always be -included in any HDU that uses this longstring convention as a warning -to any software that must read the keywords. A routine called fits\_write\_key\_longwarn -has been provided in CFITSIO to write this keyword if it does not -already exist. - -This long string convention is supported by the following CFITSIO -routines: - -\begin{verbatim} - fits_write_key_longstr - write a long string keyword value - fits_insert_key_longstr - insert a long string keyword value - fits_modify_key_longstr - modify a long string keyword value - fits_update_key_longstr - modify a long string keyword value - fits_read_key_longstr - read a long string keyword value - fits_delete_key - delete a keyword -\end{verbatim} -The fits\_read\_key\_longstr routine is unique among all the CFITSIO -routines in that it internally allocates memory for the long string -value; all the other CFITSIO routines that deal with arrays require -that the calling program pre-allocate adequate space to hold the array -of data. Consequently, programs which use the fits\_read\_key\_longstr -routine must be careful to free the allocated memory for the string -when it is no longer needed. - -The following 2 routines also have limited support for this long string -convention, - -\begin{verbatim} - fits_modify_key_str - modify an existing string keyword value - fits_update_key_str - update a string keyword value -\end{verbatim} -in that they will correctly overwrite an existing long string value, -but the new string value is limited to a maximum of 68 characters in -length. - -The more commonly used CFITSIO routines to write string valued keywords -(fits\_update\_key and fits\_write\_key) do not support this long -string convention and only support strings up to 68 characters in -length. This has been done deliberately to prevent programs from -inadvertently writing keywords using this non-standard convention -without the explicit intent of the programmer or user. The -fits\_write\_key\_longstr routine must be called instead to write long -strings. This routine can also be used to write ordinary string values -less than 68 characters in length. - - -\section{Arrays of Fixed-Length Strings in Binary Tables} - -CFITSIO supports 2 ways to specify that a character column in a binary -table contains an array of fixed-length strings. The first way, which -is officially supported by the FITS Standard document, uses the TDIMn keyword. -For example, if TFORMn = '60A' and TDIMn = '(12,5)' then that -column will be interpreted as containing an array of 5 strings, each 12 -characters long. - -CFITSIO also supports a -local convention for the format of the TFORMn keyword value of the form -'rAw' where 'r' is an integer specifying the total width in characters -of the column, and 'w' is an integer specifying the (fixed) length of -an individual unit string within the vector. For example, TFORM1 = -'120A10' would indicate that the binary table column is 120 characters -wide and consists of 12 10-character length strings. This convention -is recognized by the CFITSIO routines that read or write strings in -binary tables. The Binary Table definition document specifies that -other optional characters may follow the data type code in the TFORM -keyword, so this local convention is in compliance with the -FITS standard although other FITS readers may not -recognize this convention. - - - -\section{Keyword Units Strings} - -One limitation of the current FITS Standard is that it does not define -a specific convention for recording the physical units of a keyword -value. The TUNITn keyword can be used to specify the physical units of -the values in a table column, but there is no analogous convention for -keyword values. The comment field of the keyword is often used for -this purpose, but the units are usually not specified in a well defined -format that FITS readers can easily recognize and extract. - -To solve this problem, CFITSIO uses a local convention in which the -keyword units are enclosed in square brackets as the first token in the -keyword comment field; more specifically, the opening square bracket -immediately follows the slash '/' comment field delimiter and a single -space character. The following examples illustrate keywords that use -this convention: - - -\begin{verbatim} -EXPOSURE= 1800.0 / [s] elapsed exposure time -V_HELIO = 16.23 / [km s**(-1)] heliocentric velocity -LAMBDA = 5400. / [angstrom] central wavelength -FLUX = 4.9033487787637465E-30 / [J/cm**2/s] average flux -\end{verbatim} - -In general, the units named in the IAU(1988) Style Guide are -recommended, with the main exception that the preferred unit for angle -is 'deg' for degrees. - -The fits\_read\_key\_unit and fits\_write\_key\_unit routines in -CFITSIO read and write, respectively, the keyword unit strings in an -existing keyword. - - -\section{HIERARCH Convention for Extended Keyword Names} - -CFITSIO supports the HIERARCH keyword convention which allows keyword -names that are longer then 8 characters and may contain the full range -of printable ASCII text characters. This convention -was developed at the European Southern Observatory (ESO) to support -hierarchical FITS keyword such as: - -\begin{verbatim} -HIERARCH ESO INS FOCU POS = -0.00002500 / Focus position -\end{verbatim} -Basically, this convention uses the FITS keyword 'HIERARCH' to indicate -that this convention is being used, then the actual keyword name -({\tt'ESO INS FOCU POS'} in this example) begins in column 10 and can -contain any printable ASCII text characters, including spaces. The -equals sign marks the end of the keyword name and is followed by the -usual value and comment fields just as in standard FITS keywords. -Further details of this convention are described at -http://fits.gsfc.nasa.gov/registry/hierarch\_keyword.html -and in Section 4.4 of the ESO Data Interface Control Document that -is linked to from -http://archive.eso.org/cms/tools-documentation/eso-data-interface-control.html. - -This convention allows a much broader range of keyword names -than is allowed by the FITS Standard. Here are more examples -of such keywords: - -\begin{verbatim} -HIERARCH LongKeyword = 47.5 / Keyword has > 8 characters, and mixed case -HIERARCH XTE$TEMP = 98.6 / Keyword contains the '$' character -HIERARCH Earth is a star = F / Keyword contains embedded spaces -\end{verbatim} -CFITSIO will transparently read and write these keywords, so application -programs do not in general need to know anything about the specific -implementation details of the HIERARCH convention. In particular, -application programs do not need to specify the `HIERARCH' part of the -keyword name when reading or writing keywords (although it -may be included if desired). When writing a keyword, CFITSIO first -checks to see if the keyword name is legal as a standard FITS keyword -(no more than 8 characters long and containing only letters, digits, or -a minus sign or underscore). If so it writes it as a standard FITS -keyword, otherwise it uses the hierarch convention to write the -keyword. The maximum keyword name length is 67 characters, which -leaves only 1 space for the value field. A more practical limit is -about 40 characters, which leaves enough room for most keyword values. -CFITSIO returns an error if there is not enough room for both the -keyword name and the keyword value on the 80-character card, except for -string-valued keywords which are simply truncated so that the closing -quote character falls in column 80. In the current implementation, -CFITSIO preserves the case of the letters when writing the keyword -name, but it is case-insensitive when reading or searching for a -keyword. The current implementation allows any ASCII text character -(ASCII 32 to ASCII 126) in the keyword name except for the '=' -character. A space is also required on either side of the equal sign. - - -\section{Tile-Compressed Image Format} - -CFITSIO supports a convention for compressing n-dimensional images and -storing the resulting byte stream in a variable-length column in a FITS -binary table. The general principle used in this convention is to -first divide the n-dimensional image into a rectangular grid of -subimages or `tiles'. Each tile is then compressed as a continuous -block of data, and the resulting compressed byte stream is stored in a -row of a variable length column in a FITS binary table. By dividing the -image into tiles it is generally possible to extract and uncompress -subsections of the image without having to uncompress the whole image. -The default tiling pattern treats each row of a 2-dimensional image (or -higher dimensional cube) as a tile, such that each tile contains NAXIS1 -pixels (except the default with the HCOMPRESS algorithm is to -compress the whole 2D image as a single tile). Any other rectangular -tiling pattern may also be defined. In -the case of relatively small images it may be sufficient to compress -the entire image as a single tile, resulting in an output binary table -with 1 row. In the case of 3-dimensional data cubes, it may be -advantageous to treat each plane of the cube as a separate tile if -application software typically needs to access the cube on a plane by -plane basis. - -See section 5.6 ``Image Compression'' -for more information on using this tile-compressed image format. - -\chapter{ Optimizing Programs } - -CFITSIO has been carefully designed to obtain the highest possible -speed when reading and writing FITS files. In order to achieve the -best performance, however, application programmers must be careful to -call the CFITSIO routines appropriately and in an efficient sequence; -inappropriate usage of CFITSIO routines can greatly slow down the -execution speed of a program. - -The maximum possible I/O speed of CFITSIO depends of course on the type -of computer system that it is running on. To get a general idea of what -data I/O speeds are possible on a particular machine, build the speed.c -program that is distributed with CFITSIO (type 'make speed' in the CFITSIO -directory). This diagnostic program measures the speed of writing and reading -back a test FITS image, a binary table, and an ASCII table. - -The following 2 sections provide some background on how CFITSIO -internally manages the data I/O and describes some strategies that may -be used to optimize the processing speed of software that uses -CFITSIO. - - -\section{How CFITSIO Manages Data I/O} - -Many CFITSIO operations involve transferring only a small number of -bytes to or from the FITS file (e.g, reading a keyword, or writing a -row in a table); it would be very inefficient to physically read or -write such small blocks of data directly in the FITS file on disk, -therefore CFITSIO maintains a set of internal Input--Output (IO) -buffers in RAM memory that each contain one FITS block (2880 bytes) of -data. Whenever CFITSIO needs to access data in the FITS file, it first -transfers the FITS block containing those bytes into one of the IO -buffers in memory. The next time CFITSIO needs to access bytes in the -same block it can then go to the fast IO buffer rather than using a -much slower system disk access routine. The number of available IO -buffers is determined by the NIOBUF parameter (in fitsio2.h) and is -currently set to 40 by default. - -Whenever CFITSIO reads or writes data it first checks to see if that -block of the FITS file is already loaded into one of the IO buffers. -If not, and if there is an empty IO buffer available, then it will load -that block into the IO buffer (when reading a FITS file) or will -initialize a new block (when writing to a FITS file). If all the IO -buffers are already full, it must decide which one to reuse (generally -the one that has been accessed least recently), and flush the contents -back to disk if it has been modified before loading the new block. - -The one major exception to the above process occurs whenever a large -contiguous set of bytes are accessed, as might occur when reading or -writing a FITS image. In this case CFITSIO bypasses the internal IO -buffers and simply reads or writes the desired bytes directly in the -disk file with a single call to a low-level file read or write -routine. The minimum threshold for the number of bytes to read or -write this way is set by the MINDIRECT parameter and is currently set -to 3 FITS blocks = 8640 bytes. This is the most efficient way to read -or write large chunks of data. Note that this fast direct IO process is not -applicable when accessing columns of data in a FITS table because the -bytes are generally not contiguous since they are interleaved by the -other columns of data in the table. This explains why the speed for -accessing FITS tables is generally slower than accessing -FITS images. - -Given this background information, the general strategy for efficiently -accessing FITS files should be apparent: when dealing with FITS -images, read or write large chunks of data at a time so that the direct -IO mechanism will be invoked; when accessing FITS headers or FITS -tables, on the other hand, once a particular FITS block has been -loading into one of the IO buffers, try to access all the needed -information in that block before it gets flushed out of the IO buffer. -It is important to avoid the situation where the same FITS block is -being read then flushed from a IO buffer multiple times. - -The following section gives more specific suggestions for optimizing -the use of CFITSIO. - - -\section{Optimization Strategies} - -1. Because the data in FITS files is always stored in "big-endian" byte order, -where the first byte of numeric values contains the most significant bits and the -last byte contains the least significant bits, CFITSIO must swap the order of the bytes -when reading or writing FITS files when running on little-endian machines (e.g., -Linux and Microsoft Windows operating systems running on PCs with x86 CPUs). - -On relatively new CPUs that support "SSSE3" machine instructions -(e.g., starting with Intel Core 2 CPUs in 2007, and in AMD CPUs -beginning in 2011) significantly faster 4-byte and 8-byte swapping -algorithms are available. These faster byte swapping functions are -not used by default in CFITSIO (because of potential code -portablility issues), but users can enable them on supported -platforms by adding the appropriate compiler flags (-mssse3 with gcc -or icc on linux) when compiling the swapproc.c source file, which will -allow the compiler to generate code using the SSSE3 instruction set. -A convenient way to do this is to configure the CFITSIO library -with the following command: - -\begin{verbatim} - > ./configure --enable-ssse3 -\end{verbatim} -Note, however, that a binary executable file that is -created using these faster functions will only run on -machines that support the SSSE3 machine instructions. - -For faster 2-byte swaps on virtually all x86-64 CPUs (even those that -do not support SSSE3), a variant using only SSE2 instructions exists. -SSE2 is enabled by default on x86\_64 CPUs with 64-bit operating systems -(and is also automatically enabled by the --enable-ssse3 flag). -When running on x86\_64 CPUs with 32-bit operating systems, these faster -2-byte swapping algorithms are not used by default in CFITSIO, but can be -enabled explicitly with: - -\begin{verbatim} -./configure --enable-sse2 -\end{verbatim} -Preliminary testing indicates that these SSSE3 and SSE2 based -byte-swapping algorithms can boost the CFITSIO performance when -reading or writing FITS images by 20\% - 30\% or more. -It is important to note, however, that compiler optimization must be -turned on (e.g., by using the -O1 or -O2 flags in gcc) when building -programs that use these fast byte-swapping algorithms in order -to reap the full benefit of the SSSE3 and SSE2 instructions; without -optimization, the code may actually run slower than when using -more traditional byte-swapping techniques. - -2. When dealing with a FITS primary array or IMAGE extension, it is -more efficient to read or write large chunks of the image at a time -(at least 3 FITS blocks = 8640 bytes) so that the direct IO mechanism -will be used as described in the previous section. Smaller chunks of -data are read or written via the IO buffers, which is somewhat less -efficient because of the extra copy operation and additional -bookkeeping steps that are required. In principle it is more efficient -to read or write as big an array of image pixels at one time as -possible, however, if the array becomes so large that the operating -system cannot store it all in RAM, then the performance may be degraded -because of the increased swapping of virtual memory to disk. - -3. When dealing with FITS tables, the most important efficiency factor -in the software design is to read or write the data in the FITS file in -a single pass through the file. An example of poor program design -would be to read a large, 3-column table by sequentially reading the -entire first column, then going back to read the 2nd column, and -finally the 3rd column; this obviously requires 3 passes through the -file which could triple the execution time of an IO limited program. -For small tables this is not important, but when reading multi-megabyte -sized tables these inefficiencies can become significant. The more -efficient procedure in this case is to read or write only as many rows -of the table as will fit into the available internal IO buffers, then -access all the necessary columns of data within that range of rows. -Then after the program is completely finished with the data in those -rows it can move on to the next range of rows that will fit in the -buffers, continuing in this way until the entire file has been -processed. By using this procedure of accessing all the columns of a -table in parallel rather than sequentially, each block of the FITS file -will only be read or written once. - -The optimal number of rows to read or write at one time in a given -table depends on the width of the table row and on the number of IO -buffers that have been allocated in CFITSIO. The CFITSIO Iterator routine -will automatically use the optimal-sized buffer, but there is also a -CFITSIO routine that will return the optimal number of rows for a given -table: fits\_get\_rowsize. It is not critical to use exactly the -value of nrows returned by this routine, as long as one does not exceed -it. Using a very small value however can also lead to poor performance -because of the overhead from the larger number of subroutine calls. - -The optimal number of rows returned by fits\_get\_rowsize is valid only -as long as the application program is only reading or writing data in -the specified table. Any other calls to access data in the table -header would cause additional blocks of data -to be loaded into the IO buffers displacing data from the original -table, and should be avoided during the critical period while the table -is being read or written. - -4. Use the CFITSIO Iterator routine. This routine provides a -more `object oriented' way of reading and writing FITS files -which automatically uses the most appropriate data buffer size -to achieve the maximum I/O throughput. - -5. Use binary table extensions rather than ASCII table -extensions for better efficiency when dealing with tabular data. The -I/O to ASCII tables is slower because of the overhead in formatting or -parsing the ASCII data fields and because ASCII tables are about twice -as large as binary tables that have the same information content. - -6. Design software so that it reads the FITS header keywords in the -same order in which they occur in the file. When reading keywords, -CFITSIO searches forward starting from the position of the last keyword -that was read. If it reaches the end of the header without finding the -keyword, it then goes back to the start of the header and continues the -search down to the position where it started. In practice, as long as -the entire FITS header can fit at one time in the available internal IO -buffers, then the header keyword access will be relatively fast and it makes -little difference which order they are accessed. - -7. Avoid the use of scaling (by using the BSCALE and BZERO or TSCAL and -TZERO keywords) in FITS files since the scaling operations add to the -processing time needed to read or write the data. In some cases it may -be more efficient to temporarily turn off the scaling (using fits\_set\_bscale or -fits\_set\_tscale) and then read or write the raw unscaled values in the FITS -file. - -8. Avoid using the `implicit data type conversion' capability in -CFITSIO. For instance, when reading a FITS image with BITPIX = -32 -(32-bit floating point pixels), read the data into a single precision -floating point data array in the program. Forcing CFITSIO to convert -the data to a different data type can slow the program. - -9. Where feasible, design FITS binary tables using vector column -elements so that the data are written as a contiguous set of bytes, -rather than as single elements in multiple rows. For example, it is -faster to access the data in a table that contains a single row -and 2 columns with TFORM keywords equal to '10000E' and '10000J', than -it is to access the same amount of data in a table with 10000 rows -which has columns with the TFORM keywords equal to '1E' and '1J'. In -the former case the 10000 floating point values in the first column are -all written in a contiguous block of the file which can be read or -written quickly, whereas in the second case each floating point value -in the first column is interleaved with the integer value in the second -column of the same row so CFITSIO has to explicitly move to the -position of each element to be read or written. - -10. Avoid the use of variable length vector columns in binary tables, -since any reading or writing of these data requires that CFITSIO first -look up or compute the starting address of each row of data in the -heap. In practice, this is probably not a significant efficiency issue. - -11. When copying data from one FITS table to another, it is faster to -transfer the raw bytes instead of reading then writing each column of -the table. The CFITSIO routines fits\_read\_tblbytes and -fits\_write\_tblbytes will perform low-level reads or writes of any -contiguous range of bytes in a table extension. These routines can be -used to read or write a whole row (or multiple rows for even greater -efficiency) of a table with a single function call. These routines -are fast because they bypass all the usual data scaling, error checking -and machine dependent data conversion that is normally done by CFITSIO, -and they allow the program to write the data to the output file in -exactly the same byte order. For these same reasons, these routines -can corrupt the FITS data file if used incorrectly because no -validation or machine dependent conversion is performed by these -routines. These routines are only recommended for optimizing critical -pieces of code and should only be used by programmers who thoroughly -understand the internal format of the FITS tables they are reading or -writing. - -12. Another strategy for improving the speed of writing a FITS table, -similar to the previous one, is to directly construct the entire byte -stream for a whole table row (or multiple rows) within the application -program and then write it to the FITS file with -fits\_write\_tblbytes. This avoids all the overhead normally present -in the column-oriented CFITSIO write routines. This technique should -only be used for critical applications because it makes the code more -difficult to understand and maintain, and it makes the code more system -dependent (e.g., do the bytes need to be swapped before writing to the -FITS file?). - -13. Finally, external factors such as the speed of the data storage device, -the size of the data cache, the amount of disk fragmentation, and the amount of -RAM available on the system can all have a significant impact on -overall I/O efficiency. For critical applications, the entire hardware -and software system should be reviewed to identify any -potential I/O bottlenecks. - - -\appendix -\chapter{Index of Routines } -\begin{tabular}{lr} -fits\_add\_group\_member & \pageref{ffgtam} \\ -fits\_ascii\_tform & \pageref{ffasfm} \\ -fits\_binary\_tform & \pageref{ffbnfm} \\ -fits\_calculator & \pageref{ffcalc} \\ -fits\_calculator\_rng & \pageref{ffcalcrng} \\ -fits\_calc\_binning & \pageref{calcbinning} \\ -fits\_calc\_rows & \pageref{ffcrow} \\ -fits\_change\_group & \pageref{ffgtch} \\ -fits\_clear\_errmark & \pageref{ffpmrk} \\ -fits\_clear\_errmsg & \pageref{ffcmsg} \\ -fits\_close\_file & \pageref{ffclos} \\ -fits\_compact\_group & \pageref{ffgtcm} \\ -fits\_compare\_str & \pageref{ffcmps} \\ -fits\_compress\_heap & \pageref{ffcmph} \\ -fits\_convert\_hdr2str & \pageref{ffhdr2str}, \pageref{hdr2str} \\ -fits\_copy\_cell2image & \pageref{copycell} \\ -fits\_copy\_col & \pageref{ffcpcl} \\ -fits\_copy\_data & \pageref{ffcpdt} \\ -fits\_copy\_file & \pageref{ffcpfl} \\ -fits\_copy\_group & \pageref{ffgtcp} \\ -fits\_copy\_hdu & \pageref{ffcopy} \\ -fits\_copy\_header & \pageref{ffcphd} \\ -fits\_copy\_image2cell & \pageref{copycell} \\ -fits\_copy\_image\_section & \pageref{ffcpimg} \\ -fits\_copy\_key & \pageref{ffcpky} \\ -fits\_copy\_member & \pageref{ffgmcp} \\ -fits\_copy\_pixlist2image & \pageref{copypixlist2image} \\ -fits\_copy\_rows & \pageref{ffcprw} \\ -fits\_create\_diskfile & \pageref{ffinit} \\ -fits\_create\_file & \pageref{ffinit} \\ -fits\_create\_group & \pageref{ffgtcr} \\ -fits\_create\_hdu & \pageref{ffcrhd} \\ - -\end{tabular} -\begin{tabular}{lr} -fits\_create\_img & \pageref{ffcrim} \\ -fits\_create\_memfile & \pageref{ffimem} \\ -fits\_create\_tbl & \pageref{ffcrtb} \\ -fits\_create\_template & \pageref{fftplt} \\ -fits\_date2str & \pageref{ffdt2s} \\ -fits\_decode\_chksum & \pageref{ffdsum} \\ -fits\_decode\_tdim & \pageref{ffdtdm} \\ -fits\_delete\_col & \pageref{ffdcol} \\ -fits\_delete\_file & \pageref{ffdelt} \\ -fits\_delete\_hdu & \pageref{ffdhdu} \\ -fits\_delete\_key & \pageref{ffdkey} \\ -fits\_delete\_record & \pageref{ffdrec} \\ -fits\_delete\_rowlist & \pageref{ffdrws} \\ -fits\_delete\_rowrange & \pageref{ffdrrg} \\ -fits\_delete\_rows & \pageref{ffdrow} \\ -fits\_delete\_str & \pageref{ffdkey} \\ -fits\_encode\_chksum & \pageref{ffesum} \\ -fits\_file\_exists & \pageref{ffexist} \\ -fits\_file\_mode & \pageref{ffflmd} \\ -fits\_file\_name & \pageref{ffflnm} \\ -fits\_find\_first\_row & \pageref{ffffrw} \\ -fits\_find\_nextkey & \pageref{ffgnxk} \\ -fits\_find\_rows & \pageref{fffrow} \\ -fits\_flush\_buffer & \pageref{ffflus} \\ -fits\_flush\_file & \pageref{ffflus} \\ -fits\_free\_memory & \pageref{ffgkls}, \pageref{ffhdr2str} \\ -fits\_get\_acolparms & \pageref{ffgacl} \\ -fits\_get\_bcolparms & \pageref{ffgbcl} \\ -fits\_get\_chksum & \pageref{ffgcks} \\ -fits\_get\_col\_display\_width & \pageref{ffgcdw} \\ -fits\_get\_colname & \pageref{ffgcnn} \\ -fits\_get\_colnum & \pageref{ffgcno} \\ -\end{tabular} -\begin{tabular}{lr} -fits\_get\_coltype & \pageref{ffgtcl} \\ -fits\_get\_compression\_type & \pageref{ffgetcomp} \\ -fits\_get\_eqcoltype & \pageref{ffgtcl} \\ -fits\_get\_errstatus & \pageref{ffgerr} \\ -fits\_get\_hdrpos & \pageref{ffghps} \\ -fits\_get\_hdrspace & \pageref{ffghsp} \\ -fits\_get\_hdu\_num & \pageref{ffghdn} \\ -fits\_get\_hdu\_type & \pageref{ffghdt} \\ -fits\_get\_hduaddr & \pageref{ffghad} \\ -fits\_get\_hduaddrll & \pageref{ffghad} \\ -fits\_get\_img\_dim & \pageref{ffgidm} \\ -fits\_get\_img\_equivtype & \pageref{ffgidt} \\ -fits\_get\_img\_param & \pageref{ffgipr} \\ -fits\_get\_img\_size & \pageref{ffgisz} \\ -fits\_get\_img\_type & \pageref{ffgidt} \\ -fits\_get\_inttype & \pageref{ffinttyp} \\ -fits\_get\_key\_strlen & \pageref{ffgksl} \\ -fits\_get\_keyclass & \pageref{ffgkcl} \\ -fits\_get\_keyname & \pageref{ffgknm} \\ -fits\_get\_keytype & \pageref{ffdtyp} \\ -fits\_get\_noise\_bits & \pageref{ffgetcomp} \\ -fits\_get\_num\_cols & \pageref{ffgnrw} \\ -fits\_get\_num\_groups & \pageref{ffgmng} \\ -fits\_get\_num\_hdus & \pageref{ffthdu} \\ -fits\_get\_num\_members & \pageref{ffgtnm} \\ -fits\_get\_num\_rows & \pageref{ffgnrw} \\ -fits\_get\_rowsize & \pageref{ffgrsz} \\ -fits\_get\_system\_time & \pageref{ffdt2s} \\ -fits\_get\_tile\_dim & \pageref{ffgetcomp} \\ -fits\_get\_tbcol & \pageref{ffgabc} \\ -fits\_get\_version & \pageref{ffvers} \\ -fits\_hdr2str & \pageref{ffhdr2str}, \pageref{hdr2str} \\ -\end{tabular} -\newpage -\begin{tabular}{lr} -fits\_insert\_atbl & \pageref{ffitab} \\ -fits\_insert\_btbl & \pageref{ffibin} \\ -fits\_insert\_col & \pageref{fficol} \\ -fits\_insert\_cols & \pageref{fficls} \\ -fits\_insert\_group & \pageref{ffgtis} \\ -fits\_insert\_img & \pageref{ffiimg} \\ -fits\_insert\_key\_null & \pageref{ffikyu} \\ -fits\_insert\_key\_TYP & \pageref{ffikyx} \\ -fits\_insert\_record & \pageref{ffirec} \\ -fits\_insert\_rows & \pageref{ffirow} \\ -fits\_is\_reentrant & \pageref{reentrant} \\ -fits\_iterate\_data & \pageref{ffiter} \\ -fits\_make\_hist & \pageref{makehist} \\ -fits\_make\_key & \pageref{ffmkky} \\ -fits\_make\_keyn & \pageref{ffkeyn} \\ -fits\_make\_nkey & \pageref{ffnkey} \\ -fits\_merge\_groups & \pageref{ffgtmg} \\ -fits\_modify\_card & \pageref{ffmcrd} \\ -fits\_modify\_comment & \pageref{ffmcom} \\ -fits\_modify\_key\_null & \pageref{ffmkyu} \\ -fits\_modify\_key\_TYP & \pageref{ffmkyx} \\ -fits\_modify\_name & \pageref{ffmnam} \\ -fits\_modify\_record & \pageref{ffmrec} \\ -fits\_modify\_vector\_len & \pageref{ffmvec} \\ -fits\_movabs\_hdu & \pageref{ffmahd} \\ -fits\_movnam\_hdu & \pageref{ffmnhd} \\ -fits\_movrel\_hdu & \pageref{ffmrhd} \\ -fits\_null\_check & \pageref{ffnchk} \\ -fits\_open\_data & \pageref{ffopen} \\ -fits\_open\_diskfile & \pageref{ffopen} \\ -fits\_open\_extlist & \pageref{ffopen} \\ -fits\_open\_file & \pageref{ffopen} \\ -fits\_open\_image & \pageref{ffopen} \\ -fits\_open\_table & \pageref{ffopen} \\ -fits\_open\_group & \pageref{ffgtop} \\ -fits\_open\_member & \pageref{ffgmop} \\ -fits\_open\_memfile & \pageref{ffomem} \\ -fits\_parse\_extnum & \pageref{ffextn} \\ -fits\_parse\_input\_filename & \pageref{ffiurl} \\ -fits\_parse\_input\_url & \pageref{ffiurl} \\ -fits\_parse\_range & \pageref{ffrwrg} \\ -fits\_parse\_rootname & \pageref{ffrtnm} \\ -fits\_parse\_template & \pageref{ffgthd} \\ -fits\_parse\_value & \pageref{ffpsvc} \\ -fits\_pix\_to\_world & \pageref{ffwldp} \\ -fits\_read\_2d\_TYP & \pageref{ffg2dx} \\ -fits\_read\_3d\_TYP & \pageref{ffg3dx} \\ -fits\_read\_atblhdr & \pageref{ffghtb} \\ -\end{tabular} -\begin{tabular}{lr} -fits\_read\_btblhdr & \pageref{ffghbn} \\ -fits\_read\_card & \pageref{ffgcrd} \\ -fits\_read\_col & \pageref{ffgcv} \\ -fits\_read\_col\_bit\_ & \pageref{ffgcx} \\ -fits\_read\_col\_TYP & \pageref{ffgcvx} \\ -fits\_read\_colnull & \pageref{ffgcf} \\ -fits\_read\_colnull\_TYP & \pageref{ffgcfx} \\ -fits\_read\_descript & \pageref{ffgdes} \\ -fits\_read\_descripts & \pageref{ffgdes} \\ -fits\_read\_errmsg & \pageref{ffgmsg} \\ -fits\_read\_ext & \pageref{ffgextn} \\ -fits\_read\_grppar\_TYP & \pageref{ffggpx} \\ -fits\_read\_img & \pageref{ffgpv} \\ -fits\_read\_img\_coord & \pageref{ffgics} \\ -fits\_read\_img\_TYP & \pageref{ffgpvx} \\ -fits\_read\_imghdr & \pageref{ffghpr} \\ -fits\_read\_imgnull & \pageref{ffgpf} \\ -fits\_read\_imgnull\_TYP & \pageref{ffgpfx} \\ -fits\_read\_key & \pageref{ffgky} \\ -fits\_read\_key\_longstr & \pageref{ffgkls} \\ -fits\_read\_key\_triple & \pageref{ffgkyt} \\ -fits\_read\_key\_unit & \pageref{ffgunt} \\ -fits\_read\_key\_TYP & \pageref{ffgkyx} \\ -fits\_read\_keyn & \pageref{ffgkyn} \\ -fits\_read\_keys\_TYP & \pageref{ffgknx} \\ -fits\_read\_keyword & \pageref{ffgkey} \\ -fits\_read\_pix & \pageref{ffgpxv} \\ -fits\_read\_pixnull & \pageref{ffgpxf} \\ -fits\_read\_record & \pageref{ffgrec} \\ -fits\_read\_str & \pageref{ffgcrd} \\ -fits\_read\_string\_key & \pageref{ffgsky} \\ -fits\_read\_subset & \pageref{ffgsv} \\ -fits\_read\_subset\_TYP & \pageref{ffgsvx} \pageref{ffgsvx2}\\ -fits\_read\_subsetnull\_TYP & \pageref{ffgsfx} \pageref{ffgsfx2} \\ -fits\_read\_tbl\_coord & \pageref{ffgtcs} \\ -fits\_read\_tblbytes & \pageref{ffgtbb} \\ -fits\_read\_tdim & \pageref{ffgtdm} \\ -fits\_read\_wcstab & \pageref{wcstab} \\ -fits\_rebin\_wcs & \pageref{rebinwcs} \\ -fits\_remove\_group & \pageref{ffgtrm} \\ -fits\_remove\_member & \pageref{ffgmrm} \\ -fits\_reopen\_file & \pageref{ffreopen} \\ -fits\_report\_error & \pageref{ffrprt} \\ -fits\_resize\_img & \pageref{ffrsim} \\ -fits\_rms\_float & \pageref{imageRMS} \\ -fits\_rms\_short & \pageref{imageRMS} \\ -fits\_select\_rows & \pageref{ffsrow} \\ -fits\_set\_atblnull & \pageref{ffsnul} \\ -\end{tabular} -\begin{tabular}{lr} -fits\_set\_bscale & \pageref{ffpscl} \\ -fits\_set\_btblnull & \pageref{fftnul} \\ -fits\_set\_compression\_type & \pageref{ffsetcomp} \\ -fits\_set\_hdrsize & \pageref{ffhdef} \\ -fits\_set\_hdustruc & \pageref{ffrdef} \\ -fits\_set\_imgnull & \pageref{ffpnul} \\ -fits\_set\_noise\_bits & \pageref{ffsetcomp} \\ -fits\_set\_tile\_dim & \pageref{ffsetcomp} \\ -fits\_set\_tscale & \pageref{fftscl} \\ -fits\_split\_names & \pageref{splitnames} \\ -fits\_str2date & \pageref{ffdt2s} \\ -fits\_str2time & \pageref{ffdt2s} \\ -fits\_test\_expr & \pageref{fftexp} \\ -fits\_test\_heap & \pageref{fftheap} \\ -fits\_test\_keyword & \pageref{fftkey} \\ -fits\_test\_record & \pageref{fftrec} \\ -fits\_time2str & \pageref{ffdt2s} \\ -fits\_transfer\_member & \pageref{ffgmtf} \\ -fits\_translate\_keyword & \pageref{translatekey} \\ -fits\_update\_card & \pageref{ffucrd} \\ -fits\_update\_chksum & \pageref{ffupck} \\ -fits\_update\_key & \pageref{ffuky} \\ -fits\_update\_key\_longstr & \pageref{ffukyx} \\ -fits\_update\_key\_null & \pageref{ffukyu} \\ -fits\_update\_key\_TYP & \pageref{ffukyx} \\ -fits\_uppercase & \pageref{ffupch} \\ -fits\_url\_type & \pageref{ffurlt} \\ -fits\_verify\_chksum & \pageref{ffvcks} \\ -fits\_verify\_group & \pageref{ffgtvf} \\ -fits\_world\_to\_pix & \pageref{ffxypx} \\ -fits\_write\_2d\_TYP & \pageref{ffp2dx} \\ -fits\_write\_3d\_TYP & \pageref{ffp3dx} \\ -fits\_write\_atblhdr & \pageref{ffphtb} \\ -fits\_write\_btblhdr & \pageref{ffphbn} \\ -fits\_write\_chksum & \pageref{ffpcks} \\ -fits\_write\_col & \pageref{ffpcl} \\ -fits\_write\_col\_bit & \pageref{ffpclx} \\ -fits\_write\_col\_TYP & \pageref{ffpcls} \\ -fits\_write\_col\_null & \pageref{ffpclu} \\ -fits\_write\_colnull & \pageref{ffpcn} \\ -fits\_write\_colnull\_TYP & \pageref{ffpcnx} \\ -fits\_write\_comment & \pageref{ffpcom} \\ -fits\_write\_date & \pageref{ffpdat} \\ -fits\_write\_descript & \pageref{ffpdes} \\ -fits\_write\_errmark & \pageref{ffpmrk} \\ -fits\_write\_errmsg & \pageref{ffpmsg} \\ -fits\_write\_ext & \pageref{ffgextn} \\ -fits\_write\_exthdr & \pageref{ffphps} \\ -\end{tabular} -\newpage -\begin{tabular}{lr} -fits\_write\_grphdr & \pageref{ffphpr} \\ -fits\_write\_grppar\_TYP & \pageref{ffpgpx} \\ -fits\_write\_hdu & \pageref{ffwrhdu} \\ -fits\_write\_history & \pageref{ffphis} \\ -fits\_write\_img & \pageref{ffppr} \\ -fits\_write\_img\_null & \pageref{ffppru} \\ -fits\_write\_img\_TYP & \pageref{ffpprx} \\ -fits\_write\_imghdr & \pageref{ffphps} \\ -fits\_write\_imgnull & \pageref{ffppn} \\ -fits\_write\_imgnull\_TYP & \pageref{ffppnx} \\ -fits\_write\_key & \pageref{ffpky} \\ -fits\_write\_key\_longstr & \pageref{ffpkls} \\ -fits\_write\_key\_longwarn & \pageref{ffplsw} \\ -fits\_write\_key\_null & \pageref{ffpkyu} \\ -fits\_write\_key\_template & \pageref{ffpktp} \\ -fits\_write\_key\_triple & \pageref{ffpkyt} \\ -fits\_write\_key\_unit & \pageref{ffpunt} \\ -fits\_write\_key\_TYP & \pageref{ffpkyx} \\ -fits\_write\_keys\_TYP & \pageref{ffpknx} \\ -fits\_write\_keys\_histo & \pageref{writekeyshisto} \\ -fits\_write\_null\_img & \pageref{ffpprn} \\ -fits\_write\_nullrows & \pageref{ffpclu} \\ -fits\_write\_pix & \pageref{ffppx} \\ -fits\_write\_pixnull & \pageref{ffppxn} \\ -fits\_write\_record & \pageref{ffprec} \\ -fits\_write\_subset & \pageref{ffpss} \\ -fits\_write\_subset\_TYP & \pageref{ffpssx} \\ -fits\_write\_tblbytes & \pageref{ffptbb} \\ -fits\_write\_tdim & \pageref{ffptdm} \\ -fits\_write\_theap & \pageref{ffpthp} \\ -\end{tabular} -\newpage -\begin{tabular}{lr} -ffasfm & \pageref{ffasfm} \\ -ffbnfm & \pageref{ffbnfm} \\ -ffcalc & \pageref{ffcalc} \\ -ffcalc\_rng & \pageref{ffcalcrng} \\ -ffclos & \pageref{ffclos} \\ -ffcmph & \pageref{ffcmph} \\ -ffcmps & \pageref{ffcmps} \\ -ffcmrk & \pageref{ffpmrk} \\ -ffcmsg & \pageref{ffcmsg} \\ -ffcopy & \pageref{ffcopy} \\ -ffcpcl & \pageref{ffcpcl} \\ -ffcpdt & \pageref{ffcpdt} \\ -ffcpfl & \pageref{ffcpfl} \\ -ffcphd & \pageref{ffcphd} \\ -ffcpimg & \pageref{ffcpimg} \\ -ffcpky & \pageref{ffcpky} \\ -ffcprw & \pageref{ffcprw} \\ -ffcrhd & \pageref{ffcrhd} \\ -ffcrim & \pageref{ffcrim} \\ -ffcrow & \pageref{ffcrow} \\ -ffcrtb & \pageref{ffcrtb} \\ -ffdcol & \pageref{ffdcol} \\ -ffdelt & \pageref{ffdelt} \\ -ffdhdu & \pageref{ffdhdu} \\ -ffdkey & \pageref{ffdkey} \\ -ffdkinit & \pageref{ffinit} \\ -ffdkopen & \pageref{ffopen} \\ -ffdopn & \pageref{ffopen} \\ -ffdrec & \pageref{ffdrec} \\ -ffdrow & \pageref{ffdrow} \\ -ffdrrg & \pageref{ffdrrg} \\ -ffdrws & \pageref{ffdrws} \\ -ffdstr & \pageref{ffdkey} \\ -ffdsum & \pageref{ffdsum} \\ -ffdt2s & \pageref{ffdt2s} \\ -ffdtdm & \pageref{ffdtdm} \\ -ffdtyp & \pageref{ffdtyp} \\ -ffeopn & \pageref{ffopen} \\ -ffeqty & \pageref{ffgtcl} \\ -ffesum & \pageref{ffesum} \\ -ffexest & \pageref{ffexist} \\ -ffextn & \pageref{ffextn} \\ -ffffrw & \pageref{ffffrw} \\ -ffflmd & \pageref{ffflmd} \\ -ffflnm & \pageref{ffflnm} \\ -ffflsh & \pageref{ffflus} \\ -ffflus & \pageref{ffflus} \\ -fffree & \pageref{ffgkls}, \pageref{ffhdr2str} \\ -\end{tabular} -\begin{tabular}{lr} -fffrow & \pageref{fffrow} \\ -ffg2d\_ & \pageref{ffg2dx} \\ -ffg3d\_ & \pageref{ffg3dx} \\ -ffgabc & \pageref{ffgabc} \\ -ffgacl & \pageref{ffgacl} \\ -ffgbcl & \pageref{ffgbcl} \\ -ffgcdw & \pageref{ffgcdw} \\ -ffgcf & \pageref{ffgcf} \\ -ffgcf\_ & \pageref{ffgcfx} \\ -ffgcks & \pageref{ffgcks} \\ -ffgcnn & \pageref{ffgcnn} \\ -ffgcno & \pageref{ffgcno} \\ -ffgcrd & \pageref{ffgcrd} \\ -ffgcv & \pageref{ffgcv} \\ -ffgcv\_ & \pageref{ffgcvx} \\ -ffgcx & \pageref{ffgcx} \\ -ffgdes & \pageref{ffgdes} \\ -ffgdess & \pageref{ffgdes} \\ -ffgerr & \pageref{ffgerr} \\ -ffgextn & \pageref{ffgextn} \\ -ffggp\_ & \pageref{ffggpx} \\ -ffghad & \pageref{ffghad} \\ -ffghbn & \pageref{ffghbn} \\ -ffghdn & \pageref{ffghdn} \\ -ffghdt & \pageref{ffghdt} \\ -ffghpr & \pageref{ffghpr} \\ -ffghps & \pageref{ffghps} \\ -ffghsp & \pageref{ffghsp} \\ -ffghtb & \pageref{ffghtb} \\ -ffgics & \pageref{ffgics} \\ -ffgidm & \pageref{ffgidm} \\ -ffgidt & \pageref{ffgidt} \\ -ffgiet & \pageref{ffgidt} \\ -ffgipr & \pageref{ffgipr} \\ -ffgisz & \pageref{ffgisz} \\ -ffgkcl & \pageref{ffgkcl} \\ -ffgkey & \pageref{ffgkey} \\ -ffgkls & \pageref{ffgkls} \\ -ffgksl & \pageref{ffgksl} \\ -ffgkn\_ & \pageref{ffgknx} \\ -ffgknm & \pageref{ffgknm} \\ -ffgky & \pageref{ffgky} \\ -ffgkyn & \pageref{ffgkyn} \\ -ffgkyt & \pageref{ffgkyt} \\ -ffgky\_ & \pageref{ffgkyx} \\ -ffgmcp & \pageref{ffgmcp} \\ -ffgmng & \pageref{ffgmng} \\ -ffgmop & \pageref{ffgmop} \\ - -\end{tabular} -\begin{tabular}{lr} -ffgmrm & \pageref{ffgmrm} \\ -ffgmsg & \pageref{ffgmsg} \\ -ffgmtf & \pageref{ffgmtf} \\ -ffgncl & \pageref{ffgnrw} \\ -ffgnrw & \pageref{ffgnrw} \\ -ffgnxk & \pageref{ffgnxk} \\ -ffgpf & \pageref{ffgpf} \\ -ffgpf\_ & \pageref{ffgpfx} \\ -ffgpv & \pageref{ffgpv} \\ -ffgpv\_ & \pageref{ffgpvx} \\ -ffgpxv & \pageref{ffgpxv} \\ -ffgpxf & \pageref{ffgpxf} \\ -ffgrec & \pageref{ffgrec} \\ -ffgrsz & \pageref{ffgrsz} \\ -ffgsdt & \pageref{ffdt2s} \\ -ffgsf\_ & \pageref{ffgsfx} \pageref{ffgsfx2} \\ -ffgsky & \pageref{ffgsky} \\ -ffgstm & \pageref{ffdt2s} \\ -ffgstr & \pageref{ffgcrd} \\ -ffgsv & \pageref{ffgsv} \\ -ffgsv\_ & \pageref{ffgsvx} \pageref{ffgsvx2}\\ -ffgtam & \pageref{ffgtam} \\ -ffgtbb & \pageref{ffgtbb} \\ -ffgtch & \pageref{ffgtch} \\ -ffgtcl & \pageref{ffgtcl} \\ -ffgtcm & \pageref{ffgtcm} \\ -ffgtcp & \pageref{ffgtcp} \\ -ffgtcr & \pageref{ffgtcr} \\ -ffgtcs & \pageref{ffgtcs} \\ -ffgtdm & \pageref{ffgtdm} \\ -ffgthd & \pageref{ffgthd} \\ -ffgtis & \pageref{ffgtis} \\ -ffgtmg & \pageref{ffgtmg} \\ -ffgtnm & \pageref{ffgtnm} \\ -ffgtop & \pageref{ffgtop} \\ -ffgtrm & \pageref{ffgtrm} \\ -ffgtvf & \pageref{ffgtvf} \\ -ffgunt & \pageref{ffgunt} \\ -ffhdef & \pageref{ffhdef} \\ -ffibin & \pageref{ffibin} \\ -fficls & \pageref{fficls} \\ -fficol & \pageref{fficol} \\ -ffifile & \pageref{ffiurl} \\ -ffiimg & \pageref{ffiimg} \\ -ffikls & \pageref{ffikyx} \\ -ffikyu & \pageref{ffikyu} \\ -ffiky\_ & \pageref{ffikyx} \\ -ffimem & \pageref{ffimem} \\ - -\end{tabular} -\begin{tabular}{lr} - -ffinit & \pageref{ffinit} \\ -ffinttyp & \pageref{ffinttyp} \\ -ffiopn & \pageref{ffopen} \\ -ffirec & \pageref{ffirec} \\ -ffirow & \pageref{ffirow} \\ -ffitab & \pageref{ffitab} \\ -ffiter & \pageref{ffiter} \\ -ffiurl & \pageref{ffiurl} \\ -ffkeyn & \pageref{ffkeyn} \\ -ffmahd & \pageref{ffmahd} \\ -ffmcom & \pageref{ffmcom} \\ -ffmcrd & \pageref{ffmcrd} \\ -ffmkky & \pageref{ffmkky} \\ -ffmkls & \pageref{ffmkyx} \\ -ffmkyu & \pageref{ffmkyu} \\ -ffmky\_ & \pageref{ffmkyx} \\ -ffmnam & \pageref{ffmnam} \\ -ffmnhd & \pageref{ffmnhd} \\ -ffmrec & \pageref{ffmrec} \\ -ffmrhd & \pageref{ffmrhd} \\ -ffmvec & \pageref{ffmvec} \\ -ffnchk & \pageref{ffnchk} \\ -ffnkey & \pageref{ffnkey} \\ -ffomem & \pageref{ffomem} \\ -ffopen & \pageref{ffopen} \\ -ffp2d\_ & \pageref{ffp2dx} \\ -ffp3d\_ & \pageref{ffp3dx} \\ -ffpcks & \pageref{ffpcks} \\ -ffpcl & \pageref{ffpcl} \\ -ffpcls & \pageref{ffpcls} \\ -ffpcl\_ & \pageref{ffpclx} \\ -ffpclu & \pageref{ffpclu} \\ -ffpcn & \pageref{ffpcn} \\ -ffpcn\_ & \pageref{ffpcnx} \\ -ffpcom & \pageref{ffpcom} \\ -ffpdat & \pageref{ffpdat} \\ -ffpdes & \pageref{ffpdes} \\ -ffpextn & \pageref{ffgextn} \\ -ffpgp\_ & \pageref{ffpgpx} \\ -ffphbn & \pageref{ffphbn} \\ -ffphext & \pageref{ffphpr} \\ -ffphis & \pageref{ffphis} \\ -ffphpr & \pageref{ffphpr} \\ -ffphps & \pageref{ffphps} \\ -ffphtb & \pageref{ffphtb} \\ -ffpkls & \pageref{ffpkls} \\ -ffpkn\_ & \pageref{ffpknx} \\ -ffpktp & \pageref{ffpktp} \\ - -\end{tabular} -\begin{tabular}{lr} - -ffpky & \pageref{ffpky} \\ -ffpkyt & \pageref{ffpkyt} \\ -ffpkyu & \pageref{ffpkyu} \\ -ffpky\_ & \pageref{ffpkyx} \\ -ffplsw & \pageref{ffplsw} \\ -ffpmrk & \pageref{ffpmrk} \\ -ffpmsg & \pageref{ffpmsg} \\ -ffpnul & \pageref{ffpnul} \\ -ffppn & \pageref{ffppn} \\ -ffppn\_ & \pageref{ffppnx} \\ -ffppr & \pageref{ffppr} \\ -ffpprn & \pageref{ffpprn} \\ -ffppru & \pageref{ffppru} \\ -ffppr\_ & \pageref{ffpprx} \\ -ffppx & \pageref{ffppx} \\ -ffppxn & \pageref{ffppxn} \\ -ffprec & \pageref{ffprec} \\ -ffprwu & \pageref{ffpclu} \\ -ffpscl & \pageref{ffpscl} \\ -ffpss & \pageref{ffpss} \\ -ffpss\_ & \pageref{ffpssx} \\ -ffpsvc & \pageref{ffpsvc} \\ -ffptbb & \pageref{ffptbb} \\ -ffptdm & \pageref{ffptdm} \\ -ffpthp & \pageref{ffpthp} \\ -ffpunt & \pageref{ffpunt} \\ -ffrdef & \pageref{ffrdef} \\ -ffreopen & \pageref{ffreopen} \\ -ffrprt & \pageref{ffrprt} \\ -ffrsim & \pageref{ffrsim} \\ -ffrtnm & \pageref{ffrtnm} \\ -ffrwrg & \pageref{ffrwrg} \\ -ffs2dt & \pageref{ffdt2s} \\ -ffs2tm & \pageref{ffdt2s} \\ -ffsnul & \pageref{ffsnul} \\ -ffsrow & \pageref{ffsrow} \\ -fftexp & \pageref{fftexp} \\ -ffthdu & \pageref{ffthdu} \\ -fftheap & \pageref{fftheap} \\ -fftkey & \pageref{fftkey} \\ -fftm2s & \pageref{ffdt2s} \\ -fftnul & \pageref{fftnul} \\ -fftopn & \pageref{ffopen} \\ -fftplt & \pageref{fftplt} \\ -fftrec & \pageref{fftrec} \\ -fftscl & \pageref{fftscl} \\ -ffucrd & \pageref{ffucrd} \\ -ffukls & \pageref{ffukyx} \\ - - -\end{tabular} -\newpage -\begin{tabular}{lr} - -ffuky & \pageref{ffuky} \\ -ffukyu & \pageref{ffukyu} \\ -ffuky\_ & \pageref{ffukyx} \\ -ffupch & \pageref{ffupch} \\ -ffupck & \pageref{ffupck} \\ -ffurlt & \pageref{ffurlt} \\ -ffvcks & \pageref{ffvcks} \\ -ffvers & \pageref{ffvers} \\ -ffwldp & \pageref{ffwldp} \\ -ffwrhdu & \pageref{ffwrhdu} \\ -ffxypx & \pageref{ffxypx} \\ - -\end{tabular} - - -\chapter{Parameter Definitions } - -\begin{verbatim} -anynul - set to TRUE (=1) if any returned values are undefined, else FALSE -array - array of numerical data values to read or write -ascii - encoded checksum string -binspec - the input table binning specifier -bitpix - bits per pixel. The following symbolic mnemonics are predefined: - BYTE_IMG = 8 (unsigned char) - SHORT_IMG = 16 (signed short integer) - LONG_IMG = 32 (signed long integer) - LONGLONG_IMG = 64 (signed long 64-bit integer) - FLOAT_IMG = -32 (float) - DOUBLE_IMG = -64 (double). - Two additional values, USHORT_IMG and ULONG_IMG are also available - for creating unsigned integer images. These are equivalent to - creating a signed integer image with BZERO offset keyword values - of 32768 or 2147483648, respectively, which is the convention that - FITS uses to store unsigned integers. -card - header record to be read or written (80 char max, null-terminated) -casesen - CASESEN (=1) for case-sensitive string matching, else CASEINSEN (=0) -cmopt - grouping table "compact" option parameter. Allowed values are: - OPT_CMT_MBR and OPT_CMT_MBR_DEL. -colname - name of the column (null-terminated) -colnum - column number (first column = 1) -colspec - the input file column specification; used to delete, create, or rename - table columns -comment - the keyword comment field (72 char max, null-terminated) -complm - should the checksum be complemented? -comptype - compression algorithm to use: GZIP_1, RICE_1, HCOMPRESS_1, or PLIO_1 -coordtype- type of coordinate projection (-SIN, -TAN, -ARC, -NCP, - -GLS, -MER, or -AIT) -cpopt - grouping table copy option parameter. Allowed values are: - OPT_GCP_GPT, OPT_GCP_MBR, OPT_GCP_ALL, OPT_MCP_ADD, OPT_MCP_NADD, - OPT_MCP_REPL, amd OPT_MCP_MOV. -create_col- If TRUE, then insert a new column in the table, otherwise - overwrite the existing column. -current - if TRUE, then the current HDU will be copied -dataok - was the data unit verification successful (=1) or - not (= -1). Equals zero if the DATASUM keyword is not present. -datasum - 32-bit 1's complement checksum for the data unit -dataend - address (in bytes) of the end of the HDU -datastart- address (in bytes) of the start of the data unit -datatype - specifies the data type of the value. Allowed value are: TSTRING, - TLOGICAL, TBYTE, TSBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, - TFLOAT, TDOUBLE, TCOMPLEX, and TDBLCOMPLEX -datestr - FITS date/time string: 'YYYY-MM-DDThh:mm:ss.ddd', 'YYYY-MM-dd', - or 'dd/mm/yy' -day - calendar day (UTC) (1-31) -decimals - number of decimal places to be displayed -deltasize - increment for allocating more memory -dim1 - declared size of the first dimension of the image or cube array -dim2 - declared size of the second dimension of the data cube array -dispwidth - display width of a column = length of string that will be read -dtype - data type of the keyword ('C', 'L', 'I', 'F' or 'X') - C = character string - L = logical - I = integer - F = floating point number - X = complex, e.g., "(1.23, -4.56)" -err_msg - error message on the internal stack (80 chars max) -err_text - error message string corresponding to error number (30 chars max) -exact - TRUE (=1) if the strings match exactly; - FALSE (=0) if wildcards are used -exclist - array of pointers to keyword names to be excluded from search -exists - flag indicating whether the file or compressed file exists on disk -expr - boolean or arithmetic expression -extend - TRUE (=1) if FITS file may have extensions, else FALSE (=0) -extname - value of the EXTNAME keyword (null-terminated) -extspec - the extension or HDU specifier; a number or name, version, and type -extver - value of the EXTVER keyword = integer version number -filename - full name of the FITS file, including optional HDU and filtering specs -filetype - type of file (file://, ftp://, http://, etc.) -filter - the input file filtering specifier -firstchar- starting byte in the row (first byte of row = 1) -firstfailed - member HDU ID (if positive) or grouping table GRPIDn index - value (if negative) that failed grouping table verification. -firstelem- first element in a vector (ignored for ASCII tables) -firstrow - starting row number (first row of table = 1) -following- if TRUE, any HDUs following the current HDU will be copied -fpixel - coordinate of the first pixel to be read or written in the - FITS array. The array must be of length NAXIS and have values such - that fpixel[0] is in the range 1 to NAXIS1, fpixel[1] is in the - range 1 to NAXIS2, etc. -fptr - pointer to a 'fitsfile' structure describing the FITS file. -frac - factional part of the keyword value -gcount - number of groups in the primary array (usually = 1) -gfptr - fitsfile* pointer to a grouping table HDU. -group - GRPIDn/GRPLCn index value identifying a grouping table HDU, or - data group number (=0 for non-grouped data) -grouptype - Grouping table parameter that specifies the columns to be - created in a grouping table HDU. Allowed values are: GT_ID_ALL_URI, - GT_ID_REF, GT_ID_POS, GT_ID_ALL, GT_ID_REF_URI, and GT_ID_POS_URI. -grpname - value to use for the GRPNAME keyword value. -hdunum - sequence number of the HDU (Primary array = 1) -hduok - was the HDU verification successful (=1) or - not (= -1). Equals zero if the CHECKSUM keyword is not present. -hdusum - 32 bit 1's complement checksum for the entire CHDU -hdutype - HDU type: IMAGE_HDU (0), ASCII_TBL (1), BINARY_TBL (2), ANY_HDU (-1) -header - returned character string containing all the keyword records -headstart- starting address (in bytes) of the CHDU -heapsize - size of the binary table heap, in bytes -history - the HISTORY keyword comment string (70 char max, null-terminated) -hour - hour within day (UTC) (0 - 23) -inc - sampling interval for pixels in each FITS dimension -inclist - array of pointers to matching keyword names -incolnum - input column number; range = 1 to TFIELDS -infile - the input filename, including path if specified -infptr - pointer to a 'fitsfile' structure describing the input FITS file. -intval - integer part of the keyword value -iomode - file access mode: either READONLY (=0) or READWRITE (=1) -keyname - name of a keyword (8 char max, null-terminated) -keynum - position of keyword in header (1st keyword = 1) -keyroot - root string for the keyword name (5 char max, null-terminated) -keysexist- number of existing keyword records in the CHU -keytype - header record type: -1=delete; 0=append or replace; - 1=append; 2=this is the END keyword -longstr - arbitrarily long string keyword value (null-terminated) -lpixel - coordinate of the last pixel to be read or written in the - FITS array. The array must be of length NAXIS and have values such - that lpixel[0] is in the range 1 to NAXIS1, lpixel[1] is in the - range 1 to NAXIS2, etc. -match - TRUE (=1) if the 2 strings match, else FALSE (=0) -maxdim - maximum number of values to return -member - row number of a grouping table member HDU. -memptr - pointer to the a FITS file in memory -mem_realloc - pointer to a function for reallocating more memory -memsize - size of the memory block allocated for the FITS file -mfptr - fitsfile* pointer to a grouping table member HDU. -mgopt - grouping table merge option parameter. Allowed values are: - OPT_MRG_COPY, and OPT_MRG_MOV. -minute - minute within hour (UTC) (0 - 59) -month - calendar month (UTC) (1 - 12) -morekeys - space in the header for this many more keywords -n_good_rows - number of rows evaluating to TRUE -namelist - string containing a comma or space delimited list of names -naxes - size of each dimension in the FITS array -naxis - number of dimensions in the FITS array -naxis1 - length of the X/first axis of the FITS array -naxis2 - length of the Y/second axis of the FITS array -naxis3 - length of the Z/third axis of the FITS array -nbytes - number of bytes or characters to read or write -nchars - number of characters to read or write -nelements- number of data elements to read or write -newfptr - returned pointer to the reopened file -newveclen- new value for the column vector repeat parameter -nexc - number of names in the exclusion list (may = 0) -nfound - number of keywords found (highest keyword number) -nkeys - number of keywords in the sequence -ninc - number of names in the inclusion list -nmembers - Number of grouping table members (NAXIS2 value). -nmove - number of HDUs to move (+ or -), relative to current position -nocomments - if equal to TRUE, then no commentary keywords will be copied -noisebits- number of bits to ignore when compressing floating point images -nrows - number of rows in the table -nstart - first integer value -nullarray- set to TRUE (=1) if corresponding data element is undefined -nulval - numerical value to represent undefined pixels -nulstr - character string used to represent undefined values in ASCII table -numval - numerical data value, of the appropriate data type -offset - byte offset in the heap or data unit to the first element of the vector -openfptr - pointer to a currently open FITS file -overlap - number of bytes in the binary table heap pointed to by more than 1 - descriptor -outcolnum- output column number; range = 1 to TFIELDS + 1 -outfile - and optional output filename; the input file will be copied to this prior - to opening the file -outfptr - pointer to a 'fitsfile' structure describing the output FITS file. -pcount - value of the PCOUNT keyword = size of binary table heap -previous - if TRUE, any previous HDUs in the input file will be copied. -repeat - length of column vector (e.g. 12J); == 1 for ASCII table -rmopt - grouping table remove option parameter. Allowed values are: - OPT_RM_GPT, OPT_RM_ENTRY, OPT_RM_MBR, and OPT_RM_ALL. -rootname - root filename, minus any extension or filtering specifications -rot - celestial coordinate rotation angle (degrees) -rowlen - length of a table row, in characters or bytes -rowlist - sorted list of row numbers to be deleted from the table -rownum - number of the row (first row = 1) -rowrange - list of rows or row ranges: '3,6-8,12,56-80' or '500-' -row_status - array of True/False results for each row that was evaluated -scale - linear scaling factor; true value = (FITS value) * scale + zero -second - second within minute (0 - 60.9999999999) (leap second!) -section - section of image to be copied (e.g. 21:80,101:200) -simple - TRUE (=1) if FITS file conforms to the Standard, else FALSE (=0) -space - number of blank spaces to leave between ASCII table columns -status - returned error status code (0 = OK) -sum - 32 bit unsigned checksum value -tbcol - byte position in row to start of column (1st col has tbcol = 1) -tdisp - Fortran style display format for the table column -tdimstr - the value of the TDIMn keyword -templt - template string used in comparison (null-terminated) -tfields - number of fields (columns) in the table -tfopt - grouping table member transfer option parameter. Allowed values are: - OPT_MCP_ADD, and OPT_MCP_MOV. -tform - format of the column (null-terminated); allowed values are: - ASCII tables: Iw, Aw, Fww.dd, Eww.dd, or Dww.dd - Binary tables: rL, rX, rB, rI, rJ, rA, rAw, rE, rD, rC, rM - where 'w'=width of the field, 'd'=no. of decimals, 'r'=repeat count. - Variable length array columns are denoted by a '1P' before the data type - character (e.g., '1PJ'). When creating a binary table, 2 addition tform - data type codes are recognized by CFITSIO: 'rU' and 'rV' for unsigned - 16-bit and unsigned 32-bit integer, respectively. - -theap - zero indexed byte offset of starting address of the heap - relative to the beginning of the binary table data -tilesize - array of length NAXIS that specifies the dimensions of - the image compression tiles -ttype - label or name for table column (null-terminated) -tunit - physical unit for table column (null-terminated) -typechar - symbolic code of the table column data type -typecode - data type code of the table column. The negative of - the value indicates a variable length array column. - Datatype typecode Mnemonic - bit, X 1 TBIT - byte, B 11 TBYTE - logical, L 14 TLOGICAL - ASCII character, A 16 TSTRING - short integer, I 21 TSHORT - integer, J 41 TINT32BIT (same as TLONG) - long long integer, K 81 TLONGLONG - real, E 42 TFLOAT - double precision, D 82 TDOUBLE - complex, C 83 TCOMPLEX - double complex, M 163 TDBLCOMPLEX -unit - the physical unit string (e.g., 'km/s') for a keyword -unused - number of unused bytes in the binary table heap -urltype - the file type of the FITS file (file://, ftp://, mem://, etc.) -validheap- returned value = FALSE if any of the variable length array - address are outside the valid range of addresses in the heap -value - the keyword value string (70 char max, null-terminated) -version - current version number of the CFITSIO library -width - width of the character string field -xcol - number of the column containing the X coordinate values -xinc - X axis coordinate increment at reference pixel (deg) -xpix - X axis pixel location -xpos - X axis celestial coordinate (usually RA) (deg) -xrefpix - X axis reference pixel array location -xrefval - X axis coordinate value at the reference pixel (deg) -ycol - number of the column containing the X coordinate values -year - calendar year (e.g. 1999, 2000, etc) -yinc - Y axis coordinate increment at reference pixel (deg) -ypix - y axis pixel location -ypos - y axis celestial coordinate (usually DEC) (deg) -yrefpix - Y axis reference pixel array location -yrefval - Y axis coordinate value at the reference pixel (deg) -zero - scaling offset; true value = (FITS value) * scale + zero -\end{verbatim} - -\chapter{CFITSIO Error Status Codes } - -The following table lists all the error status codes used by CFITSIO. -Programmers are encouraged to use the symbolic mnemonics (defined in -the file fitsio.h) rather than the actual integer status values to -improve the readability of their code. - -\begin{verbatim} - Symbolic Const Value Meaning - -------------- ----- ----------------------------------------- - 0 OK, no error - SAME_FILE 101 input and output files are the same - TOO_MANY_FILES 103 tried to open too many FITS files at once - FILE_NOT_OPENED 104 could not open the named file - FILE_NOT_CREATED 105 could not create the named file - WRITE_ERROR 106 error writing to FITS file - END_OF_FILE 107 tried to move past end of file - READ_ERROR 108 error reading from FITS file - FILE_NOT_CLOSED 110 could not close the file - ARRAY_TOO_BIG 111 array dimensions exceed internal limit - READONLY_FILE 112 Cannot write to readonly file - MEMORY_ALLOCATION 113 Could not allocate memory - BAD_FILEPTR 114 invalid fitsfile pointer - NULL_INPUT_PTR 115 NULL input pointer to routine - SEEK_ERROR 116 error seeking position in file - - BAD_URL_PREFIX 121 invalid URL prefix on file name - TOO_MANY_DRIVERS 122 tried to register too many IO drivers - DRIVER_INIT_FAILED 123 driver initialization failed - NO_MATCHING_DRIVER 124 matching driver is not registered - URL_PARSE_ERROR 125 failed to parse input file URL - RANGE_PARSE_ERROR 126 parse error in range list - - SHARED_BADARG 151 bad argument in shared memory driver - SHARED_NULPTR 152 null pointer passed as an argument - SHARED_TABFULL 153 no more free shared memory handles - SHARED_NOTINIT 154 shared memory driver is not initialized - SHARED_IPCERR 155 IPC error returned by a system call - SHARED_NOMEM 156 no memory in shared memory driver - SHARED_AGAIN 157 resource deadlock would occur - SHARED_NOFILE 158 attempt to open/create lock file failed - SHARED_NORESIZE 159 shared memory block cannot be resized at the moment - - HEADER_NOT_EMPTY 201 header already contains keywords - KEY_NO_EXIST 202 keyword not found in header - KEY_OUT_BOUNDS 203 keyword record number is out of bounds - VALUE_UNDEFINED 204 keyword value field is blank - NO_QUOTE 205 string is missing the closing quote - BAD_INDEX_KEY 206 illegal indexed keyword name (e.g. 'TFORM1000') - BAD_KEYCHAR 207 illegal character in keyword name or card - BAD_ORDER 208 required keywords out of order - NOT_POS_INT 209 keyword value is not a positive integer - NO_END 210 couldn't find END keyword - BAD_BITPIX 211 illegal BITPIX keyword value - BAD_NAXIS 212 illegal NAXIS keyword value - BAD_NAXES 213 illegal NAXISn keyword value - BAD_PCOUNT 214 illegal PCOUNT keyword value - BAD_GCOUNT 215 illegal GCOUNT keyword value - BAD_TFIELDS 216 illegal TFIELDS keyword value - NEG_WIDTH 217 negative table row size - NEG_ROWS 218 negative number of rows in table - COL_NOT_FOUND 219 column with this name not found in table - BAD_SIMPLE 220 illegal value of SIMPLE keyword - NO_SIMPLE 221 Primary array doesn't start with SIMPLE - NO_BITPIX 222 Second keyword not BITPIX - NO_NAXIS 223 Third keyword not NAXIS - NO_NAXES 224 Couldn't find all the NAXISn keywords - NO_XTENSION 225 HDU doesn't start with XTENSION keyword - NOT_ATABLE 226 the CHDU is not an ASCII table extension - NOT_BTABLE 227 the CHDU is not a binary table extension - NO_PCOUNT 228 couldn't find PCOUNT keyword - NO_GCOUNT 229 couldn't find GCOUNT keyword - NO_TFIELDS 230 couldn't find TFIELDS keyword - NO_TBCOL 231 couldn't find TBCOLn keyword - NO_TFORM 232 couldn't find TFORMn keyword - NOT_IMAGE 233 the CHDU is not an IMAGE extension - BAD_TBCOL 234 TBCOLn keyword value < 0 or > rowlength - NOT_TABLE 235 the CHDU is not a table - COL_TOO_WIDE 236 column is too wide to fit in table - COL_NOT_UNIQUE 237 more than 1 column name matches template - BAD_ROW_WIDTH 241 sum of column widths not = NAXIS1 - UNKNOWN_EXT 251 unrecognizable FITS extension type - UNKNOWN_REC 252 unknown record; 1st keyword not SIMPLE or XTENSION - END_JUNK 253 END keyword is not blank - BAD_HEADER_FILL 254 Header fill area contains non-blank chars - BAD_DATA_FILL 255 Illegal data fill bytes (not zero or blank) - BAD_TFORM 261 illegal TFORM format code - BAD_TFORM_DTYPE 262 unrecognizable TFORM data type code - BAD_TDIM 263 illegal TDIMn keyword value - BAD_HEAP_PTR 264 invalid BINTABLE heap pointer is out of range - - BAD_HDU_NUM 301 HDU number < 1 - BAD_COL_NUM 302 column number < 1 or > tfields - NEG_FILE_POS 304 tried to move to negative byte location in file - NEG_BYTES 306 tried to read or write negative number of bytes - BAD_ROW_NUM 307 illegal starting row number in table - BAD_ELEM_NUM 308 illegal starting element number in vector - NOT_ASCII_COL 309 this is not an ASCII string column - NOT_LOGICAL_COL 310 this is not a logical data type column - BAD_ATABLE_FORMAT 311 ASCII table column has wrong format - BAD_BTABLE_FORMAT 312 Binary table column has wrong format - NO_NULL 314 null value has not been defined - NOT_VARI_LEN 317 this is not a variable length column - BAD_DIMEN 320 illegal number of dimensions in array - BAD_PIX_NUM 321 first pixel number greater than last pixel - ZERO_SCALE 322 illegal BSCALE or TSCALn keyword = 0 - NEG_AXIS 323 illegal axis length < 1 - - NOT_GROUP_TABLE 340 Grouping function error - HDU_ALREADY_MEMBER 341 - MEMBER_NOT_FOUND 342 - GROUP_NOT_FOUND 343 - BAD_GROUP_ID 344 - TOO_MANY_HDUS_TRACKED 345 - HDU_ALREADY_TRACKED 346 - BAD_OPTION 347 - IDENTICAL_POINTERS 348 - BAD_GROUP_ATTACH 349 - BAD_GROUP_DETACH 350 - - NGP_NO_MEMORY 360 malloc failed - NGP_READ_ERR 361 read error from file - NGP_NUL_PTR 362 null pointer passed as an argument. - Passing null pointer as a name of - template file raises this error - NGP_EMPTY_CURLINE 363 line read seems to be empty (used - internally) - NGP_UNREAD_QUEUE_FULL 364 cannot unread more then 1 line (or single - line twice) - NGP_INC_NESTING 365 too deep include file nesting (infinite - loop, template includes itself ?) - NGP_ERR_FOPEN 366 fopen() failed, cannot open template file - NGP_EOF 367 end of file encountered and not expected - NGP_BAD_ARG 368 bad arguments passed. Usually means - internal parser error. Should not happen - NGP_TOKEN_NOT_EXPECT 369 token not expected here - - BAD_I2C 401 bad int to formatted string conversion - BAD_F2C 402 bad float to formatted string conversion - BAD_INTKEY 403 can't interpret keyword value as integer - BAD_LOGICALKEY 404 can't interpret keyword value as logical - BAD_FLOATKEY 405 can't interpret keyword value as float - BAD_DOUBLEKEY 406 can't interpret keyword value as double - BAD_C2I 407 bad formatted string to int conversion - BAD_C2F 408 bad formatted string to float conversion - BAD_C2D 409 bad formatted string to double conversion - BAD_DATATYPE 410 illegal datatype code value - BAD_DECIM 411 bad number of decimal places specified - NUM_OVERFLOW 412 overflow during data type conversion - DATA_COMPRESSION_ERR 413 error compressing image - DATA_DECOMPRESSION_ERR 414 error uncompressing image - - BAD_DATE 420 error in date or time conversion - - PARSE_SYNTAX_ERR 431 syntax error in parser expression - PARSE_BAD_TYPE 432 expression did not evaluate to desired type - PARSE_LRG_VECTOR 433 vector result too large to return in array - PARSE_NO_OUTPUT 434 data parser failed not sent an out column - PARSE_BAD_COL 435 bad data encounter while parsing column - PARSE_BAD_OUTPUT 436 Output file not of proper type - - ANGLE_TOO_BIG 501 celestial angle too large for projection - BAD_WCS_VAL 502 bad celestial coordinate or pixel value - WCS_ERROR 503 error in celestial coordinate calculation - BAD_WCS_PROJ 504 unsupported type of celestial projection - NO_WCS_KEY 505 celestial coordinate keywords not found - APPROX_WCS_KEY 506 approximate wcs keyword values were returned -\end{verbatim} -\end{document} - diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.toc b/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.toc deleted file mode 100644 index 0dc5ce777..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/cfitsio.toc +++ /dev/null @@ -1,123 +0,0 @@ -\contentsline {chapter}{\numberline {1}Introduction }{1} -\contentsline {section}{\numberline {1.1} A Brief Overview}{1} -\contentsline {section}{\numberline {1.2}Sources of FITS Software and Information}{1} -\contentsline {section}{\numberline {1.3}Acknowledgments}{2} -\contentsline {section}{\numberline {1.4}Legal Stuff}{4} -\contentsline {chapter}{\numberline {2} Creating the CFITSIO Library }{5} -\contentsline {section}{\numberline {2.1}Building the Library}{5} -\contentsline {subsection}{\numberline {2.1.1}Unix Systems}{5} -\contentsline {subsection}{\numberline {2.1.2}VMS}{7} -\contentsline {subsection}{\numberline {2.1.3}Windows PCs}{7} -\contentsline {subsection}{\numberline {2.1.4}Macintosh PCs}{7} -\contentsline {section}{\numberline {2.2}Testing the Library}{7} -\contentsline {section}{\numberline {2.3}Linking Programs with CFITSIO}{9} -\contentsline {section}{\numberline {2.4}Using CFITSIO in Multi-threaded Environments}{9} -\contentsline {section}{\numberline {2.5}Getting Started with CFITSIO}{9} -\contentsline {section}{\numberline {2.6}Example Program}{10} -\contentsline {chapter}{\numberline {3} A FITS Primer }{13} -\contentsline {chapter}{\numberline {4} Programming Guidelines }{15} -\contentsline {section}{\numberline {4.1}CFITSIO Definitions}{15} -\contentsline {section}{\numberline {4.2}Current Header Data Unit (CHDU)}{17} -\contentsline {section}{\numberline {4.3}Function Names and Variable Datatypes}{18} -\contentsline {section}{\numberline {4.4}Support for Unsigned Integers and Signed Bytes}{20} -\contentsline {section}{\numberline {4.5}Dealing with Character Strings}{22} -\contentsline {section}{\numberline {4.6}Implicit Data Type Conversion}{23} -\contentsline {section}{\numberline {4.7}Data Scaling}{23} -\contentsline {section}{\numberline {4.8}Support for IEEE Special Values}{24} -\contentsline {section}{\numberline {4.9}Error Status Values and the Error Message Stack}{24} -\contentsline {section}{\numberline {4.10}Variable-Length Arrays in Binary Tables}{25} -\contentsline {section}{\numberline {4.11}Multiple Access to the Same FITS File}{26} -\contentsline {section}{\numberline {4.12}When the Final Size of the FITS HDU is Unknown}{27} -\contentsline {section}{\numberline {4.13}CFITSIO Size Limitations}{28} -\contentsline {chapter}{\numberline {5}Basic CFITSIO Interface Routines }{31} -\contentsline {section}{\numberline {5.1}CFITSIO Error Status Routines}{31} -\contentsline {section}{\numberline {5.2}FITS File Access Routines}{32} -\contentsline {section}{\numberline {5.3}HDU Access Routines}{35} -\contentsline {section}{\numberline {5.4}Header Keyword Read/Write Routines}{37} -\contentsline {subsection}{\numberline {5.4.1}Keyword Reading Routines}{38} -\contentsline {subsection}{\numberline {5.4.2}Keyword Writing Routines}{40} -\contentsline {section}{\numberline {5.5}Primary Array or IMAGE Extension I/O Routines}{43} -\contentsline {section}{\numberline {5.6}Image Compression}{47} -\contentsline {section}{\numberline {5.7}ASCII and Binary Table Routines}{52} -\contentsline {subsection}{\numberline {5.7.1}Create New Table}{52} -\contentsline {subsection}{\numberline {5.7.2}Column Information Routines}{53} -\contentsline {subsection}{\numberline {5.7.3}Routines to Edit Rows or Columns}{55} -\contentsline {subsection}{\numberline {5.7.4}Read and Write Column Data Routines}{57} -\contentsline {subsection}{\numberline {5.7.5}Row Selection and Calculator Routines}{59} -\contentsline {subsection}{\numberline {5.7.6}Column Binning or Histogramming Routines}{61} -\contentsline {section}{\numberline {5.8}Utility Routines}{63} -\contentsline {subsection}{\numberline {5.8.1}File Checksum Routines}{63} -\contentsline {subsection}{\numberline {5.8.2}Date and Time Utility Routines}{65} -\contentsline {subsection}{\numberline {5.8.3}General Utility Routines}{66} -\contentsline {chapter}{\numberline {6} The CFITSIO Iterator Function }{77} -\contentsline {section}{\numberline {6.1}The Iterator Work Function}{78} -\contentsline {section}{\numberline {6.2}The Iterator Driver Function}{80} -\contentsline {section}{\numberline {6.3}Guidelines for Using the Iterator Function}{81} -\contentsline {section}{\numberline {6.4}Complete List of Iterator Routines}{82} -\contentsline {chapter}{\numberline {7} World Coordinate System Routines }{85} -\contentsline {section}{\numberline {7.1} Self-contained WCS Routines}{86} -\contentsline {chapter}{\numberline {8} Hierarchical Grouping Routines }{89} -\contentsline {section}{\numberline {8.1}Grouping Table Routines}{90} -\contentsline {section}{\numberline {8.2}Group Member Routines}{92} -\contentsline {chapter}{\numberline {9} Specialized CFITSIO Interface Routines }{95} -\contentsline {section}{\numberline {9.1}FITS File Access Routines}{95} -\contentsline {section}{\numberline {9.2}HDU Access Routines}{99} -\contentsline {section}{\numberline {9.3}Specialized Header Keyword Routines}{101} -\contentsline {subsection}{\numberline {9.3.1}Header Information Routines}{101} -\contentsline {subsection}{\numberline {9.3.2}Read and Write the Required Keywords}{101} -\contentsline {subsection}{\numberline {9.3.3}Write Keyword Routines}{103} -\contentsline {subsection}{\numberline {9.3.4}Insert Keyword Routines}{105} -\contentsline {subsection}{\numberline {9.3.5}Read Keyword Routines}{106} -\contentsline {subsection}{\numberline {9.3.6}Modify Keyword Routines}{108} -\contentsline {subsection}{\numberline {9.3.7}Update Keyword Routines}{109} -\contentsline {section}{\numberline {9.4}Define Data Scaling and Undefined Pixel Parameters}{110} -\contentsline {section}{\numberline {9.5}Specialized FITS Primary Array or IMAGE Extension I/O Routines}{111} -\contentsline {section}{\numberline {9.6}Specialized FITS ASCII and Binary Table Routines}{114} -\contentsline {subsection}{\numberline {9.6.1}General Column Routines}{114} -\contentsline {subsection}{\numberline {9.6.2}Low-Level Table Access Routines}{116} -\contentsline {subsection}{\numberline {9.6.3}Write Column Data Routines}{116} -\contentsline {subsection}{\numberline {9.6.4}Read Column Data Routines}{117} -\contentsline {chapter}{\numberline {10} Extended File Name Syntax }{121} -\contentsline {section}{\numberline {10.1}Overview}{121} -\contentsline {section}{\numberline {10.2}Filetype}{124} -\contentsline {subsection}{\numberline {10.2.1}Notes about HTTP proxy servers}{124} -\contentsline {subsection}{\numberline {10.2.2}Notes about the stream filetype driver}{125} -\contentsline {subsection}{\numberline {10.2.3}Notes about the gsiftp filetype}{126} -\contentsline {subsection}{\numberline {10.2.4}Notes about the root filetype}{126} -\contentsline {subsection}{\numberline {10.2.5}Notes about the shmem filetype:}{128} -\contentsline {section}{\numberline {10.3}Base Filename}{128} -\contentsline {section}{\numberline {10.4}Output File Name when Opening an Existing File}{130} -\contentsline {section}{\numberline {10.5}Template File Name when Creating a New File}{132} -\contentsline {section}{\numberline {10.6}Image Tile-Compression Specification}{132} -\contentsline {section}{\numberline {10.7}HDU Location Specification}{132} -\contentsline {section}{\numberline {10.8}Image Section}{134} -\contentsline {section}{\numberline {10.9}Image Transform Filters}{135} -\contentsline {section}{\numberline {10.10}Column and Keyword Filtering Specification}{136} -\contentsline {section}{\numberline {10.11}Row Filtering Specification}{139} -\contentsline {subsection}{\numberline {10.11.1}General Syntax}{139} -\contentsline {subsection}{\numberline {10.11.2}Bit Masks}{142} -\contentsline {subsection}{\numberline {10.11.3}Vector Columns}{143} -\contentsline {subsection}{\numberline {10.11.4}Good Time Interval Filtering}{144} -\contentsline {subsection}{\numberline {10.11.5}Spatial Region Filtering}{145} -\contentsline {subsection}{\numberline {10.11.6}Example Row Filters}{147} -\contentsline {section}{\numberline {10.12} Binning or Histogramming Specification}{148} -\contentsline {chapter}{\numberline {11}Template Files }{153} -\contentsline {section}{\numberline {11.1}Detailed Template Line Format}{153} -\contentsline {section}{\numberline {11.2}Auto-indexing of Keywords}{154} -\contentsline {section}{\numberline {11.3}Template Parser Directives}{155} -\contentsline {section}{\numberline {11.4}Formal Template Syntax}{156} -\contentsline {section}{\numberline {11.5}Errors}{156} -\contentsline {section}{\numberline {11.6}Examples}{156} -\contentsline {chapter}{\numberline {12} Local FITS Conventions }{159} -\contentsline {section}{\numberline {12.1}64-Bit Long Integers}{159} -\contentsline {section}{\numberline {12.2}Long String Keyword Values.}{159} -\contentsline {section}{\numberline {12.3}Arrays of Fixed-Length Strings in Binary Tables}{161} -\contentsline {section}{\numberline {12.4}Keyword Units Strings}{161} -\contentsline {section}{\numberline {12.5}HIERARCH Convention for Extended Keyword Names}{161} -\contentsline {section}{\numberline {12.6}Tile-Compressed Image Format}{162} -\contentsline {chapter}{\numberline {13} Optimizing Programs }{165} -\contentsline {section}{\numberline {13.1}How CFITSIO Manages Data I/O}{165} -\contentsline {section}{\numberline {13.2}Optimization Strategies}{166} -\contentsline {chapter}{\numberline {A}Index of Routines }{171} -\contentsline {chapter}{\numberline {B}Parameter Definitions }{177} -\contentsline {chapter}{\numberline {C}CFITSIO Error Status Codes }{183} diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/cfortran.doc b/src/external/OpenGR/3rdparty/cfitsio/docs/cfortran.doc deleted file mode 100644 index f2230b011..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/cfortran.doc +++ /dev/null @@ -1,2088 +0,0 @@ -/* cfortran.doc 4.3 */ -/* www-zeus.desy.de/~burow OR anonymous ftp@zebra.desy.de */ -/* Burkhard Burow burow@desy.de 1990 - 1998. */ - -See Licensing information at the end of this file. - - - cfortran.h : Interfacing C or C++ and FORTRAN - -Supports: Alpha and VAX VMS, Alpha OSF, DECstation and VAX Ultrix, IBM RS/6000, - Silicon Graphics, Sun, CRAY, Apollo, HP9000, LynxOS, Convex, Absoft, - f2c, g77, NAG f90, PowerStation Fortran with Visual C++, NEC SX-4, - Portland Group. - -C and C++ are generally equivalent as far as cfortran.h is concerned. -Unless explicitly noted otherwise, mention of C implicitly includes C++. -C++ compilers tested include: - SunOS> CC +p +w # Clean compiles. - IRIX> CC # Clean compiles. - IRIX> CC -fullwarn # Still some warnings to be overcome. - GNU> g++ -Wall # Compiles are clean, other than warnings for unused - # cfortran.h static routines. - -N.B.: The best documentation on interfacing C or C++ and Fortran is in - the chapter named something like 'Interfacing C and Fortran' - to be found in the user's guide of almost every Fortran compiler. - Understanding this information for one or more Fortran compilers - greatly clarifies the aims and actions of cfortran.h. - Such a chapter generally also addresses issues orthogonal to cfortran.h, - for example the order of array indices, the index of the first element, - as well as compiling and linking issues. - - -0 Short Summary of the Syntax Required to Create the Interface --------------------------------------------------------------- - -e.g. Prototyping a FORTRAN subroutine for C: - -/* PROTOCCALLSFSUBn is optional for C, but mandatory for C++. */ - - PROTOCCALLSFSUB2(SUB_NAME,sub_name,STRING,PINT) -#define SUB_NAME(A,B) CCALLSFSUB2(SUB_NAME,sub_name,STRING,PINT, A,B) - - ^ - - - number of arguments _____| | STRING BYTE PBYTE BYTEV(..)| - / | STRINGV DOUBLE PDOUBLE DOUBLEV(..)| - / | PSTRING FLOAT PFLOAT FLOATV(..)| - types of arguments ____ / | PNSTRING INT PINT INTV(..)| - \ | PPSTRING LOGICAL PLOGICAL LOGICALV(..)| - \ | PSTRINGV LONG PLONG LONGV(..)| - \ | ZTRINGV SHORT PSHORT SHORTV(..)| - | PZTRINGV ROUTINE PVOID SIMPLE | - - - - - -e.g. Prototyping a FORTRAN function for C: -/* PROTOCCALLSFFUNn is mandatory for both C and C++. */ -PROTOCCALLSFFUN1(INT,FUN_NAME,fun_name,STRING) -#define FUN_NAME(A) CCALLSFFUN1(FUN_NAME,fun_name,STRING, A) - -e.g. calling FUN_NAME from C: {int a; a = FUN_NAME("hello");} - - -e.g. Creating a FORTRAN-callable wrapper for - a C function returning void, with a 7 dimensional integer array argument: - [Not supported from C++.] -FCALLSCSUB1(csub_name,CSUB_NAME,csub_name,INTVVVVVVV) - - -e.g. Creating a FORTRAN-callable wrapper for other C functions: -FCALLSCFUN1(STRING,cfun_name,CFUN_NAME,cfun_name,INT) - [ ^-- BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, VOID - are other types returned by functions. ] - - -e.g. COMMON BLOCKs: -FORTRAN: common /fcb/ v,w,x - character *(13) v, w(4), x(3,2) -C: -typedef struct { char v[13],w[4][13],x[2][3][13]; } FCB_DEF; -#define FCB COMMON_BLOCK(FCB,fcb) -COMMON_BLOCK_DEF(FCB_DEF,FCB); -FCB_DEF FCB; /* Define, i.e. allocate memory, in exactly one *.c file. */ - -e.g. accessing FCB in C: printf("%.13s",FCB.v); - - - -I Introduction --------------- - -cfortran.h is an easy-to-use powerful bridge between C and FORTRAN. -It provides a completely transparent, machine independent interface between -C and FORTRAN routines (= subroutines and/or functions) and global data, -i.e. structures and COMMON blocks. - -The complete cfortran.h package consists of 4 files: the documentation in -cfortran.doc, the engine cfortran.h, examples in cfortest.c and -cfortex.f/or. [cfortex.for under VMS, cfortex.f on other machines.] - -The cfortran.h package continues to be developed. The most recent version is -available via www at http://www-zeus.desy.de/~burow -or via anonymous ftp at zebra.desy.de (131.169.2.244). - -The examples may be run using one of the following sets of instructions: - -N.B. Unlike earlier versions, cfortran.h 3.0 and later versions - automatically uses the correct ANSI ## or pre-ANSI /**/ - preprocessor operator as required by the C compiler. - -N.B. As a general rule when trying to determine how to link C and Fortran, - link a trivial Fortran program using the Fortran compilers verbose option, - in order to see how the Fortran compiler drives the linker. e.g. - unix> cat f.f - END - unix> f77 -v f.f - .. lots of info. follows ... - -N.B. If using a C main(), i.e. Fortran PROGRAM is not entry of the executable, - and if the link bombs with a complaint about - a missing "MAIN" (e.g. MAIN__, MAIN_, f90_main or similar), - then Fortran has hijacked the entry point to the executable - and wishes to call the rest of the executable via "MAIN". - This can usually be satisfied by doing e.g. 'cc -Dmain=MAIN__ ...' - but often kills the command line arguments in argv and argc. - The f77 verbose option, usually -v, may point to a solution. - - -RS/6000> # Users are strongly urged to use f77 -qextname and cc -Dextname -RS/6000> # Use -Dextname=extname if extname is a symbol used in the C code. -RS/6000> xlf -c -qextname cfortex.f -RS/6000> cc -c -Dextname cfortest.c -RS/6000> xlf -o cfortest cfortest.o cfortex.o && cfortest - -DECFortran> #Only DECstations with DECFortran for Ultrix RISC Systems. -DECFortran> cc -c -DDECFortran cfortest.c -DECFortran> f77 -o cfortest cfortest.o cfortex.f && cfortest - -IRIX xxxxxx 5.2 02282015 IP20 mips -MIPS> # DECstations and Silicon Graphics using the MIPS compilers. -MIPS> cc -o cfortest cfortest.c cfortex.f -lI77 -lU77 -lF77 && cfortest -MIPS> # Can also let f77 drive linking, e.g. -MIPS> cc -c cfortest.c -MIPS> f77 -o cfortest cfortest.o cfortex.f && cfortest - -Apollo> # Some 'C compiler 68K Rev6.8' break. [See Section II o) Notes: Apollo] -Apollo> f77 -c cfortex.f && cc -o cfortest cfortest.c cfortex.o && cfortest - -VMS> define lnk$library sys$library:vaxcrtl -VMS> cc cfortest.c -VMS> fortran cfortex.for -VMS> link/exec=cfortest cfortest,cfortex -VMS> run cfortest - -OSF1 xxxxxx V3.0 347 alpha -Alpha/OSF> # Probably better to let cc drive linking, e.g. -Alpha/OSF> f77 -c cfortex.f -Alpha/OSF> cc -o cfortest cfortest.c cfortex.o -lUfor -lfor -lFutil -lots -lm -Alpha/OSF> cfortest -Alpha/OSF> # Else may need 'cc -Dmain=MAIN__' to let f77 drive linking. - -Sun> # Some old cc(1) need a little help. [See Section II o) Notes: Sun] -Sun> f77 -o cfortest cfortest.c cfortex.f -lc -lm && cfortest -Sun> # Some older f77 may require 'cc -Dmain=MAIN_'. - -CRAY> cft77 cfortex.f -CRAY> cc -c cfortest.c -CRAY> segldr -o cfortest.e cfortest.o cfortex.o -CRAY> ./cfortest.e - -NEC> cc -c -Xa cfortest.c -NEC> f77 -o cfortest cfortest.o cfortex.f && cfortest - -VAX/Ultrix/cc> # For cc on VAX Ultrix only, do the following once to cfortran.h. -VAX/Ultrix/cc> mv cfortran.h cftmp.h && grep -v "^#pragma" cfortran.h - -VAX/Ultrix/f77> # In the following, 'CC' is either 'cc' or 'gcc -ansi'. NOT'vcc' -VAX/Ultrix/f77> CC -c -Dmain=MAIN_ cfortest.c -VAX/Ultrix/f77> f77 -o cfortest cfortex.f cfortest.o && cfortest - -LynxOS> # In the following, 'CC' is either 'cc' or 'gcc -ansi'. -LynxOS> # Unfortunately cc is easily overwhelmed by cfortran.h, -LynxOS> # and won't compile some of the cfortest.c demos. -LynxOS> f2c -R cfortex.f -LynxOS> CC -Dlynx -o cfortest cfortest.c cfortex.c -lf2c && cfortest - -HP9000> # Tested with HP-UX 7.05 B 9000/380 and with A.08.07 A 9000/730 -HP9000> # CC may be either 'c89 -Aa' or 'cc -Aa' -HP9000> # Depending on the compiler version, you may need to include the -HP9000> # option '-tp,/lib/cpp' or worse, you'll have to stick to the K&R C. -HP9000> # [See Section II o) Notes: HP9000] -HP9000> # Users are strongly urged to use f77 +ppu and cc -Dextname -HP9000> # Use -Dextname=extname if extname is a symbol used in the C code. -HP9000> CC -Dextname -c cfortest.c -HP9000> f77 +ppu cfortex.f -o cfortest cfortest.o && cfortest -HP9000> # Older f77 may need -HP9000> f77 -c cfortex.f -HP9000> CC -o cfortest cfortest.c cfortex.o -lI77 -lF77 && cfortest - -HP0000> # If old-style f77 +800 compiled objects are required: -HP9000> # #define hpuxFortran800 -HP9000> cc -c -Aa -DhpuxFortran800 cfortest.c -HP9000> f77 +800 -o cfortest cfortest.o cfortex.f - -f2c> # In the following, 'CC' is any C compiler. -f2c> f2c -R cfortex.f -f2c> CC -o cfortest -Df2cFortran cfortest.c cfortex.c -lf2c && cfortest - -Portland Group $ # Presumably other C compilers also work. -Portland Group $ pgcc -DpgiFortran -c cfortest.c -Portland Group $ pgf77 -o cfortest cfortex.f cfortest.o && cfortest - -NAGf90> # cfortex.f is distributed with Fortran 77 style comments. -NAGf90> # To convert to f90 style comments do the following once to cfortex.f: -NAGf90> mv cfortex.f cf_temp.f && sed 's/^C/\!/g' cf_temp.f > cfortex.f -NAGf90> # In the following, 'CC' is any C compiler. -NAGf90> CC -c -DNAGf90Fortran cfortest.c -NAGf90> f90 -o cfortest cfortest.o cfortex.f && cfortest - -PC> # On a PC with PowerStation Fortran and Visual_C++ -PC> cl /c cftest.c -PC> fl32 cftest.obj cftex.for - -GNU> # GNU Fortran -GNU> # See Section VI caveat on using 'gcc -traditional'. -GNU> gcc -ansi -Wall -O -c -Df2cFortran cfortest.c -GNU> g77 -ff2c -o cfortest cfortest.o cfortex.f && cfortest - -AbsoftUNIX> # Absoft Fortran for all UNIX based operating systems. -AbsoftUNIX> # e.g. Linux or Next on Intel or Motorola68000. -AbsoftUNIX> # Absoft f77 -k allows Fortran routines to be safely called from C. -AbsoftUNIX> gcc -ansi -Wall -O -c -DAbsoftUNIXFortran cfortest.c -AbsoftUNIX> f77 -k -o cfortest cfortest.o cfortex.f && cfortest - -AbsoftPro> # Absoft Pro Fortran for MacOS -AbsoftPro> # Use #define AbsoftProFortran - -CLIPPER> # INTERGRAPH CLIX using CLIPPER C and Fortran compilers. -CLIPPER> # N.B. - User, not cfortran.h, is responsible for -CLIPPER> # f77initio() and f77uninitio() if required. -CLIPPER> # - LOGICAL values are not mentioned in CLIPPER doc.s, -CLIPPER> # so they may not yet be correct in cfortran.h. -CLIPPER> # - K&R mode (-knr or Ac=knr) breaks FLOAT functions -CLIPPER> # (see CLIPPER doc.s) and cfortran.h does not fix it up. -CLIPPER> # [cfortran.h ok for old sun C which made the same mistake.] -CLIPPER> acc cfortest.c -c -DCLIPPERFortran -CLIPPER> af77 cfortex.f cfortest.o -o cfortest - - -By changing the SELECTion ifdef of cfortest.c and recompiling one can try out -a few dozen different few-line examples. - - - -The benefits of using cfortran.h include: -1. Machine/OS/compiler independent mixing of C and FORTRAN. - -2. Identical (within syntax) calls across languages, e.g. -C FORTRAN - CALL HBOOK1(1,'pT spectrum of pi+',100,0.,5.,0.) -/* C*/ - HBOOK1(1,"pT spectrum of pi+",100,0.,5.,0.); - -3. Each routine need only be set up once in its lifetime. e.g. -/* Setting up a FORTRAN routine to be called by C. - ID,...,VMX are merely the names of arguments. - These tags must be unique w.r.t. each other but are otherwise arbitrary. */ -PROTOCCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT) -#define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \ - CCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \ - ID,CHTITLE,NX,XMI,XMA,VMX) - -4. Source code is NOT required for the C routines exported to FORTRAN, nor for - the FORTRAN routines imported to C. In fact, routines are most easily - prototyped using the information in the routines' documentation. - -5. Routines, and the code calling them, can be coded naturally in the language - of choice. C routines may be coded with the natural assumption of being - called only by C code. cfortran.h does all the required work for FORTRAN - code to call C routines. Similarly it also does all the work required for C - to call FORTRAN routines. Therefore: - - C programmers need not embed FORTRAN argument passing mechanisms into - their code. - - FORTRAN code need not be converted into C code. i.e. The honed and - time-honored FORTRAN routines are called by C. - -6. cfortran.h is a single ~1700 line C include file; portable to most - remaining, if not all, platforms. - -7. STRINGS and VECTORS of STRINGS along with the usual simple arguments to - routines are supported as are functions returning STRINGS or numbers. Arrays - of pointers to strings and values of structures as C arguments, will soon be - implemented. After learning the machinery of cfortran.h, users can expand - it to create custom types of arguments. [This requires no modification to - cfortran.h, all the preprocessor directives required to implement the - custom types can be defined outside cfortran.h] - -8. cfortran.h requires each routine to be exported to be explicitly set up. - While is usually only be done once in a header file it would be best if - applications were required to do no work at all in order to cross languages. - cfortran.h's simple syntax could be a convenient back-end for a program - which would export FORTRAN or C routines directly from the source code. - - - ----- - -Example 1 - cfortran.h has been used to make the C header file hbook.h, - which then gives any C programmer, e.g. example.c, full and - completely transparent access to CERN's HBOOK library of routines. - Each HBOOK routine required about 3 lines of simple code in - hbook.h. The example also demonstrates how FORTRAN common blocks - are defined and used. - -/* hbook.h */ -#include "cfortran.h" - : -PROTOCCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT) -#define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \ - CCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \ - ID,CHTITLE,NX,XMI,XMA,VMX) - : -/* end hbook.h */ - -/* example.c */ -#include "hbook.h" - : -typedef struct { - int lines; - int status[SIZE]; - float p[SIZE]; /* momentum */ -} FAKE_DEF; -#define FAKE COMMON_BLOCK(FAKE,fake) -COMMON_BLOCK_DEF(FAKE_DEF,FAKE); - : -main () -{ - : - HBOOK1(1,"pT spectrum of pi+",100,0.,5.,0.); -/* c.f. the call in FORTRAN: - CALL HBOOK1(1,'pT spectrum of pi+',100,0.,5.,0.) -*/ - : - FAKE.p[7]=1.0; - : -} - -N.B. i) The routine is language independent. - ii) hbook.h is machine independent. - iii) Applications using routines via cfortran.h are machine independent. - - ----- - -Example 2 - Many VMS System calls are most easily called from FORTRAN, but - cfortran.h now gives that ease in C. - -#include "cfortran.h" - -PROTOCCALLSFSUB3(LIB$SPAWN,lib$spawn,STRING,STRING,STRING) -#define LIB$SPAWN(command,input_file,output_file) \ - CCALLSFSUB3(LIB$SPAWN,lib$spawn,STRING,STRING,STRING, \ - command,input_file,output_file) - -main () -{ -LIB$SPAWN("set term/width=132","",""); -} - -Obviously the cfortran.h command above could be put into a header file along -with the description of the other system calls, but as this example shows, it's -not much hassle to set up cfortran.h for even a single call. - - ----- - -Example 3 - cfortran.h and the source cstring.c create the cstring.obj library - which gives FORTRAN access to all the functions in C's system - library described by the system's C header file string.h. - -C EXAMPLE.FOR - PROGRAM EXAMPLE - DIMENSION I(20), J(30) - : - CALL MEMCPY(I,J,7) - : - END - -/* cstring.c */ -#include /* string.h prototypes memcpy() */ -#include "cfortran.h" - - : -FCALLSCSUB3(memcpy,MEMCPY,memcpy,PVOID,PVOID,INT) - : - - -The simplicity exhibited in the above example exists for many but not all -machines. Note 4. of Section II ii) details the limitations and describes tools -which try to maintain the best possible interface when FORTRAN calls C -routines. - - ----- - - -II Using cfortran.h -------------------- - -The user is asked to look at the source files cfortest.c and cfortex.f -for clarification by example. - -o) Notes: - -o Specifying the Fortran compiler - cfortran.h generates interfaces for the default Fortran compiler. The default -can be overridden by defining, - . in the code, e.g.: #define NAGf90Fortran - OR . in the compile directive, e.g.: unix> cc -DNAGf90Fortran -one of the following before including cfortran.h: - NAGf90Fortran f2cFortran hpuxFortran apolloFortran sunFortran - IBMR2Fortran CRAYFortran mipsFortran DECFortran vmsFortran - CONVEXFortran PowerStationFortran AbsoftUNIXFortran - SXFortran pgiFortran AbsoftProFortran -This also allows crosscompilation. -If wanted, NAGf90Fortran, f2cFortran, DECFortran, AbsoftUNIXFortran, -AbsoftProFortran and pgiFortran must be requested by the user. - -o /**/ - cfortran.h (ab)uses the comment kludge /**/ when the ANSI C preprocessor -catenation operator ## doesn't exist. In at least MIPS C, this kludge is -sensitive to blanks surrounding arguments to macros. - Therefore, for applications using non-ANSI C compilers, the argtype_i, -routine_name, routine_type and common_block_name arguments to the -PROTOCCALLSFFUNn, CCALLSFSUB/FUNn, FCALLSCSUB/FUNn and COMMON_BLOCK macros ---- MUST NOT --- be followed by any white space characters such as -blanks, tabs or newlines. - -o LOGICAL - FORTRAN LOGICAL values of .TRUE. and .FALSE. do not agree with the C -representation of TRUE and FALSE on all machines. cfortran.h does the -conversion for LOGICAL and PLOGICAL arguments and for functions returning -LOGICAL. Users must convert arrays of LOGICALs from C to FORTRAN with the -C2FLOGICALV(array_name, elements_in_array); macro. Similarly, arrays of LOGICAL -values may be converted from the FORTRAN into C representation by using -F2CLOGICALV(array_name, elements_in_array); - - When C passes or returns LOGICAL values to FORTRAN, by default cfortran.h -only makes the minimal changes required to the value. [e.g. Set/Unset the -single relevant bit or do nothing for FORTRAN compilers which use 0 as FALSE -and treat all other values as TRUE.] Therefore cfortran.h will pass LOGICALs -to FORTRAN which do not have an identical representation to .TRUE. or .FALSE. -This is fine except for abuses of FORTRAN/77 in the style of: - logical l - if (l .eq. .TRUE.) ! (1) -instead of the correct: - if (l .eqv. .TRUE.) ! (2) -or: - if (l) ! (3) -For FORTRAN code which treats LOGICALs from C in the method of (1), -LOGICAL_STRICT must be defined before including cfortran.h, either in the -code, "#define LOGICAL_STRICT", or compile with "cc -DLOGICAL_STRICT". -There is no reason to use LOGICAL_STRICT for FORTRAN code which does not do (1). -At least the IBM's xlf and the Apollo's f77 do not even allow code along the -lines of (1). - - DECstations' DECFortran and MIPS FORTRAN compilers use different internal -representations for LOGICAL values. [Both compilers are usually called f77, -although when both are installed on a single machine the MIPS' one is usually -renamed. (e.g. f772.1 for version 2.10.)] cc doesn't know which FORTRAN -compiler is present, so cfortran.h assumes MIPS f77. To use cc with DECFortran -define the preprocessor constant 'DECFortran'. -e.g. i) cc -DDECFortran -c the_code.c - or ii) #define DECFortran /* in the C code or add to cfortran.h. */ - - MIPS f77 [SGI and DECstations], f2c, and f77 on VAX Ultrix treat -.eqv./.neqv. as .eq./.ne.. Therefore, for these compilers, LOGICAL_STRICT is -defined by default in cfortran.h. [The Sun and HP compilers have not been -tested, so they may also require LOGICAL_STRICT as the default.] - -o SHORT and BYTE - They are irrelevant for the CRAY where FORTRAN has no equivalent to C's short. -Similarly BYTE is irrelevant for f2c and for VAX Ultrix f77 and fort. The -author has tested SHORT and BYTE with a modified cfortest.c/cfortex.f on all -machines supported except for the HP9000 and the Sun. - - BYTE is a signed 8-bit quantity, i.e. values are -128 to 127, on all machines -except for the SGI [at least for MIPS Computer Systems 2.0.] On the SGI it is -an unsigned 8-bit quantity, i.e. values are 0 to 255, although the SGI 'FORTRAN -77 Programmers Guide' claims BYTE is signed. Perhaps MIPS 2.0 is dated, since -the DECstations using MIPS 2.10 f77 have a signed BYTE. - - To minimize the difficulties of signed and unsigned BYTE, cfortran.h creates -the type 'INTEGER_BYTE' to agree with FORTRAN's BYTE. Users may define -SIGNED_BYTE or UNSIGNED_BYTE, before including cfortran.h, to specify FORTRAN's -BYTE. If neither is defined, cfortran.h assumes SIGNED_BYTE. - -o CRAY - The type DOUBLE in cfortran.h corresponds to FORTRAN's DOUBLE PRECISION. - The type FLOAT in cfortran.h corresponds to FORTRAN's REAL. - -On a classic CRAY [i.e. all models except for the t3e]: -( 64 bit) C float == C double == Fortran REAL -(128 bit) C long double == Fortran DOUBLE PRECISION -Therefore when moving a mixed C and FORTRAN app. to/from a classic CRAY, -either the C code will have to change, -or the FORTRAN code and cfortran.h declarations will have to change. -DOUBLE_PRECISION is a cfortran.h macro which provides the former option, -i.e. the C code is automatically changed. -DOUBLE_PRECISION is 'long double' on classic CRAY and 'double' elsewhere. -DOUBLE_PRECISION thus corresponds to FORTRAN's DOUBLE PRECISION -on all machines, including classic CRAY. - -On a classic CRAY with the fortran compiler flag '-dp': -Fortran DOUBLE PRECISION thus is also the faster 64bit type. -(This switch is often used since the application is usually satisfied by - 64 bit precision and the application needs the speed.) -DOUBLE_PRECISION is thus not required in this case, -since the classic CRAY behaves like all other machines. -If DOUBLE_PRECISION is used nonetheless, then on the classic CRAY -the default cfortran.h behavior must be overridden, -for example by the C compiler option '-DDOUBLE_PRECISION=double'. - -On a CRAY t3e: -(32 bit) C float == Fortran Unavailable -(64 bit) C double == C long double == Fortran REAL == Fortran DOUBLE PRECISION -Notes: -- (32 bit) is available as Fortran REAL*4 and - (64 bit) is available as Fortran REAL*8. - Since cfortran.h is all about more portability, not about less portability, - the use of the nonstandard REAL*4 and REAL*8 is strongly discouraged. -- Fortran DOUBLE PRECISION is folded to REAL with the following warning: - 'DOUBLE PRECISION is not supported on this platform. REAL will be used.' - Similarly, Fortran REAL*16 is mapped to REAL*8 with a warning. -This behavior differs from that of other machines, including the classic CRAY. -FORTRAN_REAL is thus introduced for the t3e, -just as DOUBLE_PRECISION is introduced for the classic CRAY. -FORTRAN_REAL is 'double' on t3e and 'float' elsewhere. -FORTRAN_REAL thus corresponds to FORTRAN's REAL on all machines, including t3e. - - -o f2c - f2c, by default promotes REAL functions to double. cfortran.h does not (yet) -support this, so the f2c -R option must be used to turn this promotion off. - -o f2c -[Thanks to Dario Autiero for pointing out the following.] -f2c has a strange feature in that either one or two underscores are appended -to a Fortran name of a routine or common block, -depending on whether or not the original name contains an underscore. - - S.I. Feldman et al., "A fortran to C converter", - Computing Science Technical Report No. 149. - - page 2, chapter 2: INTERLANGUAGE conventions - ........... - To avoid conflict with the names of library routines and with names that - f2c generates, - Fortran names may have one or two underscores appended. Fortran names are - forced to lower case (unless the -U option described in Appendix B is in - effect); external names, i.e. the names of fortran procedures and common - blocks, have a single underscore appended if they do not contain any - underscore and have a pair of underscores appended if they do contain - underscores. Thus fortran subroutines names ABC, A_B_C and A_B_C_ result - in C functions named abc_, a_b_c__ and a_b_c___. - ........... - -cfortran.h is unable to change the naming convention on a name by name basis. -Fortran routine and common block names which do not contain an underscore -are unaffected by this feature. -Names which do contain an underscore may use the following work-around: - -/* First 2 lines are a completely standard cfortran.h interface - to the Fortran routine E_ASY . */ - PROTOCCALLSFSUB2(E_ASY,e_asy, PINT, INT) -#define E_ASY(A,B) CCALLSFSUB2(E_ASY,e_asy, PINT, INT, A, B) -#ifdef f2cFortran -#define e_asy_ e_asy__ -#endif -/* Last three lines are a work-around for the strange f2c naming feature. */ - -o NAG f90 - The Fortran 77 subset of Fortran 90 is supported. Extending cfortran.h to -interface C with all of Fortran 90 has not yet been examined. - The NAG f90 library hijacks the main() of any program and starts the user's -program with a call to: void f90_main(void); -While this in itself is only a minor hassle, a major problem arises because -NAG f90 provides no mechanism to access command line arguments. - At least version 'NAGWare f90 compiler Version 1.1(334)' appended _CB to -common block names instead of the usual _. To fix, add this to cfortran.h: -#ifdef old_NAG_f90_CB_COMMON -#define COMMON_BLOCK CFC_ /* for all other Fortran compilers */ -#else -#define COMMON_BLOCK(UN,LN) _(LN,_CB) -#endif - -o RS/6000 - Using "xlf -qextname ...", which appends an underscore, '_', to all FORTRAN -external references, requires "cc -Dextname ..." so that cfortran.h also -generates these underscores. -Use -Dextname=extname if extname is a symbol used in the C code. -The use of "xlf -qextname" is STRONGLY ENCOURAGED, since it allows for -transparent naming schemes when mixing C and Fortran. - -o HP9000 - Using "f77 +ppu ...", which appends an underscore, '_', to all FORTRAN -external references, requires "cc -Dextname ..." so that cfortran.h also -generates these underscores. -Use -Dextname=extname if extname is a symbol used in the C code. -The use of "f77 +ppu" is STRONGLY ENCOURAGED, since it allows for -transparent naming schemes when mixing C and Fortran. - - At least one release of the HP /lib/cpp.ansi preprocessor is broken and will -go into an infinite loop when trying to process cfortran.h with the -## catenation operator. The K&R version of cfortran.h must then be used and the -K&R preprocessor must be specified. e.g. - HP9000> cc -Aa -tp,/lib/cpp -c source.c -The same problem with a similar solution exists on the Apollo. -An irrelevant error message '0: extraneous name /usr/include' will appear for -each source file due to another HP bug, and can be safely ignored. -e.g. 'cc -v -c -Aa -tp,/lib/cpp cfortest.c' will show that the driver passes -'-I /usr/include' instead of '-I/usr/include' to /lib/cpp - -On some machines the above error causes compilation to stop; one must then use -K&R C, as with old HP compilers which don't support function prototyping. -cfortran.h has to be informed that K&R C is to being used, e.g. -HP9000> cc -D__CF__KnR -c source.c - -o AbsoftUNIXFortran -By default, cfortran.h follows the default AbsoftUNIX/ProFortran and prepends _C -to each COMMON BLOCK name. To override the cfortran.h behavior -#define COMMON_BLOCK(UN,LN) before #including cfortran.h. -[Search for COMMON_BLOCK in cfortran.h for examples.] - -o Apollo -On at least one release, 'C compiler 68K Rev6.8(168)', the default C -preprocessor, from cc -A xansi or cc -A ansi, enters an infinite loop when -using cfortran.h. This Apollo bug can be circumvented by using: - . cc -DANSI_C_preprocessor=0 to force use of /**/, instead of '##'. - AND . The pre-ANSI preprocessor, i.e. use cc -Yp,/usr/lib -The same problem with a similar solution exists on the HP. - -o Sun -Old versions of cc(1), say <~1986, may require help for cfortran.h applications: - . #pragma may not be understood, hence cfortran.h and cfortest.c may require - sun> mv cfortran.h cftmp.h && grep -v "^#pragma" cfortran.h - sun> mv cfortest.c cftmp.c && grep -v "^#pragma" cfortest.c - . Old copies of math.h may not include the following from a newer math.h. - [For an ancient math.h on a 386 or sparc, get similar from a new math.h.] - #ifdef mc68000 /* 5 lines Copyright (c) 1988 by Sun Microsystems, Inc. */ - #define FLOATFUNCTIONTYPE int - #define RETURNFLOAT(x) return (*(int *)(&(x))) - #define ASSIGNFLOAT(x,y) *(int *)(&x) = y - #endif - -o CRAY, Sun, Apollo [pre 6.8 cc], VAX Ultrix and HP9000 - Only FORTRAN routines with less than 15 arguments can be prototyped for C, -since these compilers don't allow more than 31 arguments to a C macro. This can -be overcome, [see Section IV], with access to any C compiler without this -limitation, e.g. gcc, on ANY machine. - -o VAX Ultrix - vcc (1) with f77 is not supported. Although: -VAXUltrix> f77 -c cfortex.f -VAXUltrix> vcc -o cfortest cfortest.c cfortex.o -lI77 -lU77 -lF77 && cfortest -will link and run. However, the FORTRAN standard I/O is NOT merged with the -stdin and stdout of C, and instead uses the files fort.6 and fort.5. For vcc, -f77 can't drive the linking, as for gcc and cc, since vcc objects must be -linked using lk (1). f77 -v doesn't tell much, and without VAX Ultrix manuals, -the author can only wait for the info. required. - - fort (1) is not supported. Without VAX Ultrix manuals the author cannot -convince vcc/gcc/cc and fort to generate names of routines and COMMON blocks -that match at the linker, lk (1). i.e. vcc/gcc/cc prepend a single underscore -to external references, e.g. NAME becomes _NAME, while fort does not modify the -references. So ... either fort has prepend an underscore to external -references, or vcc/gcc/cc have to generate unmodified names. man 1 fort -mentions JBL, is JBL the only way? - -o VAX VMS C - The compiler 'easily' exhausts its table space and generates: -%CC-F-BUGCHECK, Compiler bug check during parser phase . - Submit an SPR with a problem description. - At line number 777 in DISK:[DIR]FILE.C;1. -where the line given, '777', includes a call across C and FORTRAN via -cfortran.h, usually with >7 arguments and/or very long argument expressions. -This SPR can be staved off, with the simple modification to cfortran.h, such -that the relevant CCALLSFSUBn (or CCALLSFFUNn or FCALLSCFUNn) is not -cascaded up to CCALLSFSUB14, and instead has its own copy of the contents of -CCALLSFSUB14. [If these instructions are not obvious after examining cfortran.h -please contact the author.] -[Thanks go to Mark Kyprianou (kyp@stsci.edu) for this solution.] - -o Mips compilers - e.g. DECstations and SGI, require applications with a C main() and calls to -GETARG(3F), i.e. FORTRAN routines returning the command line arguments, to use -two macros as shown: - : -CF_DECLARE_GETARG; /* This must be external to all routines. */ - : -main(int argc, char *argv[]) -{ - : -CF_SET_GETARG(argc,argv); /* This must precede any calls to GETARG(3F). */ - : -} -The macros are null and benign on all other systems. Sun's GETARG(3F) also -doesn't work with a generic C main() and perhaps a workaround similar to the -Mips' one exists. - -o Alpha/OSF -Using the DEC Fortran and the DEC C compilers of DEC OSF/1 [RT] V1.2 (Rev. 10), -Fortran, when called from C, has occasional trouble using a routine received as -a dummy argument. - -e.g. In the following the Fortran routine 'e' will crash when it tries to use - the C routine 'c' or the Fortran routine 'f'. - The example works on other systems. - -C FORTRAN /* C */ - integer function f() #include - f = 2 int f_(); - return int e_(int (*u)()); - end - int c(){ return 1;} - integer function e(u) int d (int (*u)()) { return u();} - integer u - external u main() - e=u() { /* Calls to d work. */ - return printf("d (c ) returns %d.\n",d (c )); - end printf("d (f_) returns %d.\n",d (f_)); - /* Calls to e_ crash. */ - printf("e_(c ) returns %d.\n",e_(c )); - printf("e_(f_) returns %d.\n",e_(f_)); - } - -Solutions to the problem are welcomed! -A kludge which allows the above example to work correctly, requires an extra -argument to be given when calling the dummy argument function. -i.e. Replacing 'e=u()' by 'e=u(1)' allows the above example to work. - - -o The FORTRAN routines are called using macro expansions, therefore the usual -caveats for expressions in arguments apply. The expressions to the routines may -be evaluated more than once, leading to lower performance and in the worst case -bizarre bugs. - -o For those who wish to use cfortran.h in large applications. [See Section IV.] -This release is intended to make it easy to get applications up and running. -This implies that applications are not as efficient as they could be: -- The current mechanism is inefficient if a single header file is used to - describe a large library of FORTRAN functions. Code for a static wrapper fn. - is generated in each piece of C source code for each FORTRAN function - specified with the CCALLSFFUNn statement, irrespective of whether or not the - function is ever called. -- Code for several static utility routines internal to cfortran.h is placed - into any source code which #includes cfortran.h. These routines should - probably be in a library. - - -i) Calling FORTRAN routines from C: - -------------------------------- - -The FORTRAN routines are defined by one of the following two instructions: - -for a SUBROUTINE: -/* PROTOCCALLSFSUBn is optional for C, but mandatory for C++. */ -PROTOCCALLSFSUBn(ROUTINE_NAME,routine_name,argtype_1,...,argtype_n) -#define Routine_name(argname_1,..,argname_n) \ -CCALLSFSUBn(ROUTINE_NAME,routine_name,argtype_1,...,argtype_n, \ - argname_1,..,argname_n) - -for a FUNCTION: -PROTOCCALLSFFUNn(routine_type,ROUTINE_NAME,routine_name,argtype_1,...,argtype_n) -#define Routine_name(argname_1,..,argname_n) \ -CCALLSFFUNn(ROUTINE_NAME,routine_name,argtype_1,...,argtype_n, \ - argname_1,..,argname_n) - -Where: -'n' = 0->14 [SUBROUTINE's ->27] (easily expanded in cfortran.h to > 14 [27]) is - the number of arguments to the routine. -Routine_name = C name of the routine (IN UPPER CASE LETTERS).[see 2.below] -ROUTINE_NAME = FORTRAN name of the routine (IN UPPER CASE LETTERS). -routine_name = FORTRAN name of the routine (IN lower case LETTERS). -routine_type = the type of argument returned by FORTRAN functions. - = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING, VOID. - [Instead of VOID one would usually use CCALLSFSUBn. - VOID forces a wrapper function to be used.] -argtype_i = the type of argument passed to the FORTRAN routine and must be - consistent in the definition and prototyping of the routine s.a. - = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING. - For vectors, i.e. 1 dim. arrays use - = BYTEV, DOUBLEV, FLOATV, INTV, LOGICALV, LONGV, SHORTV, - STRINGV, ZTRINGV. - For vectors of vectors, i.e. 2 dim. arrays use - = BYTEVV, DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, SHORTVV. - For n-dim. arrays, 1<=n<=7 [7 is the maximum in Fortran 77], - = BYTEV..nV's..V, DOUBLEV..V, FLOATV..V, INTV..V, LOGICALV..V, - LONGV..V, SHORTV..V. - N.B. Array dimensions and types are checked by the C compiler. - For routines changing the values of an argument, the keyword is - prepended by a 'P'. - = PBYTE, PDOUBLE, PFLOAT, PINT, PLOGICAL, PLONG, PSHORT, - PSTRING, PSTRINGV, PZTRINGV. - For EXTERNAL procedures passed as arguments use - = ROUTINE. - For exceptional arguments which require no massaging to fit the - argument passing mechanisms use - = PVOID. - The argument is cast and passed as (void *). - Although PVOID could be used to describe all array arguments on - most (all?) machines , it shouldn't be because the C compiler - can no longer check the type and dimension of the array. -argname_i = any valid unique C tag, but must be consistent in the definition - as shown. - -Notes: - -1. cfortran.h may be expanded to handle a more argument type. To suppport new -arguments requiring complicated massaging when passed between Fortran and C, -the user will have to understand cfortran.h and follow its code and mechanisms. - -To define types requiring little or no massaging when passed between Fortran -and C, the pseudo argument type SIMPLE may be used. -For a user defined type called 'newtype', the definitions required are: - -/* The following 7 lines are required verbatim. - 'newtype' is the name of the new user defined argument type. -*/ -#define newtype_cfV( T,A,B,F) SIMPLE_cfV(T,A,B,F) -#define newtype_cfSEP(T, B) SIMPLE_cfSEP(T,B) -#define newtype_cfINT(N,A,B,X,Y,Z) SIMPLE_cfINT(N,A,B,X,Y,Z) -#define newtype_cfSTR(N,T,A,B,C,D,E) SIMPLE_cfSTR(N,T,A,B,C,D,E) -#define newtype_cfCC( T,A,B) SIMPLE_cfCC(T,A,B) -#define newtype_cfAA( T,A,B) newtype_cfB(T,A) /* Argument B not used. */ -#define newtype_cfU( T,A) newtype_cfN(T,A) - -/* 'parameter_type(A)' is a declaration for 'A' and describes the type of the -parameter expected by the Fortran function. This type will be used in the -prototype for the function, if using ANSI C, and to declare the argument used -by the intermediate function if calling a Fortran FUNCTION. -Valid 'parameter_type(A)' include: int A - void (*A)() - double A[17] -*/ -#define newtype_cfN( T,A) parameter_type(A) /* Argument T not used. */ - -/* Before any argument of the new type is passed to the Fortran routine, it may -be massaged as given by 'massage(A)'. -*/ -#define newtype_cfB( T,A) massage(A) /* Argument T not used. */ - -An example of a simple user defined type is given cfortex.f and cfortest.c. -Two uses of SIMPLE user defined types are [don't show the 7 verbatim #defines]: - -/* Pass the address of a structure, using a type called PSTRUCT */ -#define PSTRUCT_cfN( T,A) void *A -#define PSTRUCT_cfB( T,A) (void *) &(A) - -/* Pass an integer by value, (not standard F77 ), using a type called INTVAL */ -#define INTVAL_cfN( T,A) int A -#define INTVAL_cfB( T,A) (A) - -[If using VAX VMS, surrounding the #defines with "#pragma (no)standard" allows - the %CC-I-PARAMNOTUSED messages to be avoided.] - -Upgrades to cfortran.h try to be, and have been, backwards compatible. This -compatibility cannot be offered to user defined types. SIMPLE user defined -types are less of a risk since they require so little effort in their creation. -If a user defined type is required in more than one C header file of interfaces -to libraries of Fortran routines, good programming practice, and ease of code -maintenance, suggests keeping any user defined type within a single file which -is #included as required. To date, changes to the SIMPLE macros were introduced -in versions 2.6, 3.0 and 3.2 of cfortran.h. - - -2. Routine_name is the name of the macro which the C programmer will use in -order to call a FORTRAN routine. In theory Routine_name could be any valid and -unique name, but in practice, the name of the FORTRAN routine in UPPER CASE -works everywhere and would seem to be an obvious choice. - - -3. - -cfortran.h encourages the exact specification of the type and dimension of -array parameters because it allows the C compiler to detect errors in the -arguments when calling the routine. - -cfortran.h does not strictly require the exact specification since the argument -is merely the address of the array and is passed on to the calling routine. -Any array parameter could be declared as PVOID, but this circumvents -C's compiletime ability to check the correctness of arguments and is therefore -discouraged. - -Passing the address of these arguments implies that PBYTEV, PFLOATV, ... , -PDOUBLEVV, ... don't exist in cfortran.h, since by default the routine and the -calling code share the same array, i.e. the same values at the same memory -location. - -These comments do NOT apply to arrays of (P)S/ZTRINGV. For these parameters, -cfortran.h passes a massaged copy of the array to the routine. When the routine -returns, S/ZTRINGV ignores the copy, while PS/ZTRINGV replaces the calling -code's original array with copy, which may have been modified by the called -routine. - - -4. (P)STRING(V): -- STRING - If the argument is a fixed length character array, e.g. char ar[8];, -the string is blank, ' ', padded on the right to fill out the array before -being passed to the FORTRAN routine. The useful size of the string is the same -in both languages, e.g. ar[8] is passed as character*7. If the argument is a -pointer, the string cannot be blank padded, so the length is passed as -strlen(argument). On return from the FORTRAN routine, pointer arguments are not -disturbed, but arrays have the terminating '\0' replaced to its original -position. i.e. The padding blanks are never visible to the C code. - -- PSTRING - The argument is massaged as with STRING before being passed to the -FORTRAN routine. On return, the argument has all trailing blanks removed, -regardless of whether the argument was a pointer or an array. - -- (P)STRINGV - Passes a 1- or 2-dimensional char array. e.g. char a[7],b[6][8]; -STRINGV may thus also pass a string constant, e.g. "hiho". -(P)STRINGV does NOT pass a pointer, e.g. char *, to either a 1- or a -2-dimensional array, since it cannot determine the array dimensions. -A pointer can only be passed using (P)ZTRINGV. -N.B. If a C routine receives a character array argument, e.g. char a[2][3], - such an argument is actually a pointer and my thus not be passed by - (P)STRINGV. Instead (P)ZTRINGV must be used. - -- STRINGV - The elements of the argument are copied into space malloc'd, and -each element is padded with blanks. The useful size of each element is the same -in both languages. Therefore char bb[6][8]; is equivalent to character*7 bb(6). -On return from the routine the malloc'd space is simply released. - -- PSTRINGV - Since FORTRAN has no trailing '\0', elements in an array of -strings are contiguous. Therefore each element of the C array is padded with -blanks and strip out C's trailing '\0'. After returning from the routine, the -trailing '\0' is reinserted and kill the trailing blanks in each element. - -- SUMMARY: STRING(V) arguments are blank padded during the call to the FORTRAN -routine, but remain original in the C code. (P)STRINGV arguments are blank -padded for the FORTRAN call, and after returning from FORTRAN trailing blanks -are stripped off. - - -5. (P)ZTRINGV: -- (P)ZTRINGV - is identical to (P)STRINGV, -except that the dimensions of the array of strings is explicitly specified, -which thus also allows a pointer to be passed. -(P)ZTRINGV can thus pass a 1- or 2-dimensional char array, e.g. char b[6][8], -or it can pass a pointer to such an array, e.g. char *p;. -ZTRINGV may thus also pass a string constant, e.g. "hiho". -If passing a 1-dimensional array, routine_name_ELEMS_j (see below) must be 1. -[Users of (P)ZTRINGV should examine cfortest.c for examples.]: - -- (P)ZTRINGV must thus be used instead of (P)STRINGV whenever sizeof() -can't be used to determine the dimensions of the array of string or strings. -e.g. when calling FORTRAN from C with a char * received by C as an argument. - -- There is no (P)ZTRING type, since (P)ZTRINGV can pass a 1-dimensional -array or a pointer to such an array, e.g. char a[7], *b; -If passing a 1-dimensional array, routine_name_ELEMS_j (see below) must be 1. - -- To specify the numbers of elements, -routine_name_ELEMS_j and routine_name_ELEMLEN_j must be defined as shown below -before interfacing the routine with CCALLSFSUBn, PROTOCCALLSFFUNn, etc. - -#define routine_name_ELEMS_j ZTRINGV_ARGS(k) - [..ARGS for subroutines, ..ARGF for functions.] -or -#define routine_name_ELEMS_j ZTRINGV_NUM(l) -Where: routine_name is as above. - j [1-n], is the argument being specifying. - k [1-n], the value of the k'th argument is the dynamic number - of elements for argument j. The k'th argument must be - of type BYTE, DOUBLE, FLOAT, INT, LONG or SHORT. - l the number of elements for argument j. This must be an - integer constant available at compile time. - i.e. it is static. - -- Similarly to specify the useful length, [i.e. don't count C's trailing '\0',] -of each element: -#define routine_name_ELEMLEN_j ZTRINGV_ARGS(m) - [..ARGS for subroutines, ..ARGF for functions.] -or -#define routine_name_ELEMLEN_j ZTRINGV_NUM(q) -Where: m [1-n], as for k but this is the length of each element. - q as for l but this is the length of each element. - - -6. ROUTINE -The argument is an EXTERNAL procedure. - -When C passes a routine to Fortran, the language of the function must be -specified as follows: [The case of some_*_function must be given as shown.] - -When C passes a C routine to a Fortran: - FORTRAN_ROUTINE(arg1, .... , - C_FUNCTION(SOME_C_FUNCTION,some_c_function), - ...., argn); - -and similarly when C passes a Fortran routine to Fortran: - FORTRAN_ROUTINE(arg1, .... , - FORTRAN_FUNCTION(SOME_FORT_FUNCTION,some_fort_function), - ...., argn); - -If fcallsc has been redefined; the same definition of fcallsc used when creating -the wrapper for 'some_c_function' must also be defined when C_FUNCTION is used. -See ii) 4. of this section for when and how to redefine fcallsc. - -ROUTINE was introduced with cfortran.h version 2.6. Earlier versions of -cfortran.h used PVOID to pass external procedures as arguments. Using PVOID for -this purpose is no longer recommended since it won't work 'as is' for -apolloFortran, hpuxFortran800, AbsoftUNIXFortran, AbsoftProFortran. - -7. CRAY only: -In a given piece of source code, where FFUNC is any FORTRAN routine, -FORTRAN_FUNCTION(FFUNC,ffunc) -disallows a previous -#define FFUNC(..) CCALLSFSUBn(FFUNC,ffunc,...) [ or CCALLSFFUNn] -in order to make the UPPER CASE FFUNC callable from C. -#define Ffunc(..) ... is OK though, as are obviously any other names. - - -ii) Calling C routines from FORTRAN: - -------------------------------- - -Each of the following two statements to export a C routine to FORTRAN create -FORTRAN 'wrappers', written in C, which must be compiled and linked along with -the original C routines and with the FORTRAN calling code. - -FORTRAN callable 'wrappers' may also be created for C macros. i.e. in this -section, the term 'C function' may be replaced by 'C macro'. - -for C functions returning void: -FCALLSCSUBn( Routine_name,ROUTINE_NAME,routine_name,argtype_1,...,argtype_n) - -for all other C functions: -FCALLSCFUNn(routine_type,Routine_name,ROUTINE_NAME,routine_name,argtype_1,...,argtype_n) - -Where: -'n' = 0->27 (easily expanded to > 27) stands for the number of arguments to the - routine. -Routine_name = the C name of the routine. [see 9. below] -ROUTINE_NAME = the FORTRAN name of the routine (IN UPPER CASE LETTERS). -routine_name = the FORTRAN name of the routine (IN lower case LETTERS). -routine_type = the type of argument returned by C functions. - = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING, VOID. - [Instead of VOID, FCALLSCSUBn is recommended.] -argtype_i = the type of argument passed to the FORTRAN routine and must be - consistent in the definition and prototyping of the routine - = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING. - For vectors, i.e. 1 dim. arrays use - = BYTEV, DOUBLEV, FLOATV, INTV, LOGICALV, LONGV, SHORTV, STRINGV. - For vectors of vectors, 2 dim. arrays use - = BYTEVV, DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, SHORTVV. - For n-dim. arrays use - = BYTEV..nV's..V, DOUBLEV..V, FLOATV..V, INTV..V, LOGICALV..V, - LONGV..V, SHORTV..V. - For routines changing the values of an argument, the keyword is - prepended by a 'P'. - = PBYTE, PDOUBLE, PFLOAT, PINT, PLOGICAL, PLONG, PSHORT, - PSTRING, PNSTRING, PPSTRING, PSTRINGV. - For EXTERNAL procedures passed as arguments use - = ROUTINE. - For exceptional arguments which require no massaging to fit the - argument passing mechanisms use - = PVOID. - The argument is cast and passed as (void *). - - -Notes: - -0. For Fortran calling C++ routines, C++ does NOT easily allow support for: - STRINGV. - BYTEVV, DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, SHORTVV. - BYTEV..V, DOUBLEV..V, FLOATV..V, INTV..V, LOGICALV..V, LONGV..V, SHORTV..V. -Though there are ways to get around this restriction, -the restriction is not serious since these types are unlikely to be used as -arguments for a C++ routine. - -1. FCALLSCSUB/FUNn expect that the routine to be 'wrapped' has been properly -prototyped, or at least declared. - - -2. cfortran.h may be expanded to handle a new argument type not already among -the above. - - -3. - -cfortran.h encourages the exact specification of the type and dimension of -array parameters because it allows the C compiler to detect errors in the -arguments when declaring the routine using FCALLSCSUB/FUNn, assuming the -routine to be 'wrapped' has been properly prototyped. - -cfortran.h does not strictly require the exact specification since the argument -is merely the address of the array and is passed on to the calling routine. -Any array parameter could be declared as PVOID, but this circumvents -C's compiletime ability to check the correctness of arguments and is therefore -discouraged. - -Passing the address of these arguments implies that PBYTEV, PFLOATV, ... , -PDOUBLEVV, ... don't exist in cfortran.h, since by default the routine and the -calling code share the same array, i.e. the same values at the same memory -location. - -These comments do NOT apply to arrays of (P)STRINGV. For these parameters, -cfortran.h passes a massaged copy of the array to the routine. When the routine -returns, STRINGV ignores the copy, while PSTRINGV replaces the calling -code's original array with copy, which may have been modified by the called -routine. - - -4. (P(N))STRING arguments have any trailing blanks removed before being passed -to C, the same holds true for each element in (P)STRINGV. Space is malloc'd in -all cases big enough to hold the original string (elements) as well as C's -terminating '\0'. i.e. The useful size of the string (elements) is the same in -both languages. P(N)STRING(V) => the string (elements) will be copied from the -malloc'd space back into the FORTRAN bytes. If one of the two escape mechanisms -mentioned below for PNSTRING has been used, the copying back to FORTRAN is -obviously not relevant. - - -5. (PN)STRING's, [NOT PSTRING's nor (P)STRINGV's,] behavior may be overridden -in two cases. In both cases PNSTRING and STRING behave identically. - -a) If a (PN)STRING argument's first 4 bytes are all the NUL character, -i.e. '\0\0\0\0' the NULL pointer is passed to the C routine. - -b) If the characters of a (PN)STRING argument contain at least one HEX-00, i.e. -the NUL character, i.e. C strings' terminating '\0', the address of the string -is simply passed to the C routine. i.e. The argument is treated in this case as -it would be with PPSTRING, to which we refer the reader for more detail. - -Mechanism a) overrides b). Therefore, to use this mechanism to pass the NULL -string, "", to C, the first character of the string must obviously be the NUL -character, but of the first 4 characters in the string, at least one must not -be HEX-00. - -Example: -C FORTRAN /* C */ - character*40 str #include "cfortran.h" -C Set up a NULL as : void cs(char *s) {if (s) printf("%s.\n",s);} -C i) 4 NUL characters. FCALLSCSUB1(cs,CS,cs,STRING) -C ii) NULL pointer. - character*4 NULL - NULL = CHAR(0)//CHAR(0)//CHAR(0)//CHAR(0) - - data str/'just some string'/ - -C Passing the NULL pointer to cs. - call cs(NULL) -C Passing a copy of 'str' to cs. - call cs(str) -C Passing address of 'str' to cs. Trailing blanks NOT killed. - str(40:) = NULL - call cs(str) - end - -Strings passed from Fortran to C via (PN)STRING must not have undefined -contents, otherwise undefined behavior will result, since one of the above two -escape mechanisms may occur depending on the contents of the string. - -This is not be a problem for STRING arguments, which are read-only in the C -routine and hence must have a well defined value when being passed in. - -PNSTRING arguments require special care. Even if they are write-only in the C -routine, PNSTRING's above two escape mechanisms require that the value of the -argument be well defined when being passed in from Fortran to C. Therefore, -unless one or both of PNSTRING's escape mechanisms are required, PSTRING should -be used instead of PNSTRING. -Prior to version 2.8, PSTRING did have the above two escape mechanisms, -but they were removed from PSTRING to allow strings with undefined contents to -be passed in. PNSTRING behaves like the old PSTRING. -[Thanks go to Paul Dubois (dubios@icf.llnl.gov) for pointing out that PSTRING - must allow for strings with undefined contents to be passed in.] - -Example: -C FORTRAN /* C */ - character*10 s,sn #include "cfortran.h" - void ps(char *s) {strcpy(s,"hello");} -C Can call ps with undef. s. FCALLSCSUB1(ps,PS,ps,PSTRING) - call ps(s) FCALLSCSUB1(ps,PNS,pns,PNSTRING) - print *,s,'=s' - -C Can't call pns with undef. s. -C e.g. If first 4 bytes of s were -C "\0\0\0\0", ps would try -C to copy to NULL because -C of PNSTRING mechanism. - sn = "" - call pns(sn) - print *,sn,'=sn' - - end - - -6. PPSTRING -The address of the string argument is simply passed to the C routine. Therefore -the C routine and the FORTRAN calling code share the same string at the same -memory location. If the C routine modifies the string, the string will also be -modified for the FORTRAN calling code. -The user is responsible for negociating the differences in representation of a -string in Fortran and in C, i.e. the differences are not automatically resolved -as they are for (P(N)STRING(V). -This mechanism is provided for two reasons: - - Some C routines require the string to exist at the given memory location, - after the C routine has exited. Recall that for the usual (P(N)STRING(V) - mechanism, a copy of the FORTRAN string is given to the C routine, and this - copy ceases to exist after returning to the FORTRAN calling code. - - This mechanism can save runtime CPU cycles over (P(N)STRING(V), since it - does not perform their malloc, copy and kill trailing blanks of the string - to be passed. - Only in a small minority of cases does the potential benefit of the saved - CPU cycles outweigh the programming effort required to manually resolve - the differences in representation of a string in Fortran and in C. - -For arguments passed via PPSTRING, the argument passed may also be an array of -strings. - - -7. ROUTINE -ANSI C requires that the type of the value returned by the routine be known, -For all ROUTINE arguments passed from Fortran to C, the type of ROUTINE is -specified by defining a cast as follows: - -#undef ROUTINE_j -#define ROUTINE_j (cast) -where: - j [1-n], is the argument being specifying. - (cast) is a cast matching that of the argument expected by the C - function protoytpe for which a wrapper is being defined. - -e.g. To create a Fortran wrapper for qsort(3C): -#undef ROUTINE_4 -#define ROUTINE_4 (int (*)(void *,void *)) -FCALLSCSUB4(qsort,FQSORT,fqsort,PVOID,INT,INT,ROUTINE) - -In order to maintain backward compatibility, cfortran.h defines a generic cast -for ROUTINE_1, ROUTINE_2, ..., ROUTINE_27. The user's definition is therefore -strictly required only for DEC C, which at the moment is the only compiler -which insists on the correct cast for pointers to functions. - -When using the ROUTINE argument inside some Fortran code: -- it is difficult to pass a C routine as the parameter, - since in many Fortran implementations, - Fortran has no access to the normal C namespace. - e.g. For most UNIX, - Fortran implicitly only has access to C routines ending in _. - If the calling Fortran code receives the routine as a parameter - it can of course easily pass it along. -- if a Fortran routine is passed directly as the parameter, - the called C routine must call the parameter routine - using the Fortran argument passing conventions. -- if a Fortran routine is to be passed as the parameter, - but if Fortran can be made to pass a C routine as the parameter, - then it may be best to pass a C-callable wrapper for the Fortran routine. - The called C routine is thus spared all Fortran argument passing conventions. - cfortran.h can be used to create such a C-callable wrapper - to the parameter Fortran routine. - -ONLY PowerStationFortran: -This Fortran provides no easy way to pass a Fortran routine as an argument to a -C routine. The problem arises because in Fortran the stack is cleared by the -called routine, while in C/C++ it is cleared by the caller. -The C/C++ stack clearing behavior can be changed to that of Fortran by using -stdcall__ in the function prototype. The stdcall__ cannot be applied in this -case since the called C routine expects the ROUTINE parameter to be a C routine -and does not know that it should apply stdcall__. -In principle the cfortran.h generated Fortran callable wrapper for the called C -routine should be able to massage the ROUTINE argument such that stdcall__ is -performed, but it is not yet known how this could be easily done. - - -8. THE FOLLOWING INSTRUCTIONS ARE NOT REQUIRED FOR VAX VMS - ------------ -(P)STRINGV information [NOT required for VAX VMS]: cfortran.h cannot convert -the FORTRAN vector of STRINGS to the required C vector of STRINGS without -explicitly knowing the number of elements in the vector. The application must -do one of the following for each (P)STRINGV argument in a routine before that -routine's FCALLSCFUNn/SUBn is called: - -#define routine_name_STRV_Ai NUM_ELEMS(j) - or -#define routine_name_STRV_Ai NUM_ELEM_ARG(k) - or -#define routine_name_STRV_Ai TERM_CHARS(l,m) - -where: routine_name is as above. - i [i=1->n.] specifies the argument number of a STRING VECTOR. - j would specify a fixed number of elements. - k [k=1->n. k!=i] would specify an integer argument which specifies the - number of elements. - l [char] the terminating character at the beginning of an - element, indicating to cfortran.h that the preceding - elements in the vector are the valid ones. - m [m=1-...] the number of terminating characters required to appear - at the beginning of the terminating string element. - The terminating element is NOT passed on to - the C routine. - -e.g. #define ce_STRV_A1 TERM_CHARS(' ',2) - FCALLSCSUB1(ce,CE,ce,STRINGV) - -cfortran.h will pass on all elements, in the 1st and only argument to the C -routine ce, of the STRING VECTOR until, but not including, the first string -element beginning with 2 blank, ' ', characters. - - -9. INSTRUCTIONS REQUIRED ONLY FOR FORTRAN COMPILERS WHICH GENERATE - ------------- - ROUTINE NAMES WHICH ARE UNDISTINGUISHABLE FROM C ROUTINE NAMES - i.e. VAX VMS - AbsoftUNIXFortran (AbsoftProFortran ok, since it uses Uppercase names.) - HP9000 if not using the +ppu option of f77 - IBM RS/6000 if not using the -qextname option of xlf - Call them the same_namespace compilers. - -FCALLSCSUBn(...) and FCALLSCFUNn(...), when compiled, are expanded into -'wrapper' functions, so called because they wrap around the original C -functions and interface the format of the original C functions' arguments and -return values with the format of the FORTRAN call. - -Ideally one wants to be able to call the C routine from FORTRAN using the same -name as the original C name. This is not a problem for FORTRAN compilers which -append an underscore, '_', to the names of routines, since the original C -routine has the name 'name', and the FORTRAN wrapper is called 'name_'. -Similarly, if the FORTRAN compiler generates upper case names for routines, the -original C routine 'name' can have a wrapper called 'NAME', [Assuming the C -routine name is not in upper case.] For these compilers, e.g. Mips, CRAY, IBM -RS/6000 'xlf -qextname', HP-UX 'f77 +ppu', the naming of the wrappers is done -automatically. - -For same_namespace compilers things are not as simple, but cfortran.h tries to -provide tools and guidelines to minimize the costs involved in meeting their -constraints. The following two options can provide same_namespace compilers -with distinct names for the wrapper and the original C function. - -These compilers are flagged by cfortran.h with the CF_SAME_NAMESPACE constant, -so that the change in the C name occurs only when required. - -For the remainder of the discussion, routine names generated by FORTRAN -compilers are referred to in lower case, these names should be read as upper -case for the appropriate compilers. - - -HP9000: (When f77 +ppu is not used.) -f77 has a -U option which forces uppercase external names to be generated. -Unfortunately, cc does not handle recursive macros. Hence, if one wished to use --U for separate C and FORTRAN namespaces, one would have to adopt a different -convention of naming the macros which allow C to call FORTRAN subroutines. -(Functions are not a problem.) The macros are currently the uppercase of the -original FORTRAN name, and would have to be changed to lower case or mixed -case, or to a different name. (Lower case would of course cause conflicts on -many other machines.) Therefore, it is suggested that f77 -U not be used, and -instead that Option a) or Option b) outlined below be used. - - -VAX/VMS: -For the name used by FORTRAN in calling a C routine to be the same as that of -the C routine, the source code of the C routine is required. A preprocessor -directive can then force the C compiler to generate a different name for the C -routine. -e.g. #if defined(vms) - #define name name_ - #endif - void name() {printf("name: was called.\n");} - FCALLSCSUB0(name,NAME,name) - -In the above, the C compiler generates the original routine with the name -'name_' and a wrapper called 'NAME'. This assumes that the name of the routine, -as seen by the C programmer, is not in upper case. The VAX VMS linker is not -case sensitive, allowing cfortran.h to export the upper case name as the -wrapper, which then doesn't conflict with the routine name in C. Since the IBM, -HP and AbsoftUNIXFortran platforms have case sensitive linkers -this technique is not available to them. - -The above technique is required even if the C name is in mixed case, see -Option a) for the other compilers, but is obviously not required when -Option b) is used. - - -Option a) Mixed Case names for the C routines to be called by FORTRAN. - -If the original C routines have mixed case names, there are no name space -conflicts. - -Nevertheless for VAX/VMS, the technique outlined above must also used. - - -Option b) Modifying the names of C routines when used by FORTRAN: - -The more robust naming mechanism, which guarantees portability to all machines, -'renames' C routines when called by FORTRAN. Indeed, one must change the names -on same_namespace compilers when FORTRAN calls C routines for which the source -is unavailable. [Even when the source is available, renaming may be preferable -to Option a) for large libraries of C routines.] - -Obviously, if done for a single type of machine, it must be done for all -machines since the names of routines used in FORTRAN code cannot be easily -redefined for different machines. - -The simplest way to achieve this end is to do explicitly give the modified -FORTRAN name in the FCALLSCSUBn(...) and FCALLSCFUNn(...) declarations. e.g. - -FCALLSCSUB0(name,CFNAME,cfname) - -This allows FORTRAN to call the C routine 'name' as 'cfname'. Any name can of -course be used for a given routine when it is called from FORTRAN, although -this is discouraged due to the confusion it is sure to cause. e.g. Bizarre, -but valid and allowing C's 'call_back' routine to be called from FORTRAN as -'abcd': - -FCALLSCSUB0(call_back,ABCD,abcd) - - -cfortran.h also provides preprocessor directives for a systematic 'renaming' of -the C routines when they are called from FORTRAN. This is done by redefining -the fcallsc macro before the FCALLSCSUB/FUN/n declarations as follows: - -#undef fcallsc -#define fcallsc(UN,LN) preface_fcallsc(CF,cf,UN,LN) - -FCALLSCSUB0(hello,HELLO,hello) - -Will cause C's routine 'hello' to be known in FORTRAN as 'cfhello'. Similarly -all subsequent FCALLSCSUB/FUN/n declarations will generate wrappers to allow -FORTRAN to call C with the C routine's name prefaced by 'cf'. The following has -the same effect, with subsequent FCALLSCSUB/FUN/n's appending the modifier to -the original C routines name. - -#undef fcallsc -#define fcallsc(UN,LN) append_fcallsc(Y,y,UN,LN) - -FCALLSCSUB0(Xroutine,ROUTINE,routine) - -Hence, C's Xroutine is called from FORTRAN as: - CALL XROUTINEY() - -The original behavior of FCALLSCSUB/FUN/n, where FORTRAN routine names are left -identical to those of C, is returned using: - -#undef fcallsc -#define fcallsc(UN,LN) orig_fcallsc(UN,LN) - - -In C, when passing a C routine, i.e. its wrapper, as an argument to a FORTRAN -routine, the FORTRAN name declared is used and the correct fcallsc must be in -effect. E.g. Passing 'name' and 'routine' of the above examples to the FORTRAN -routines, FT1 and FT2, respectively: - -/* This might not be needed if fcallsc is already orig_fcallsc. */ -#undef fcallsc -#define fcallsc(UN,LN) orig_fcallsc(UN,LN) -FT1(C_FUNCTION(CFNAME,cfname)); - -#undef fcallsc -#define fcallsc(UN,LN) append_fcallsc(Y,y,UN,LN) -FT1(C_FUNCTION(XROUTINE,xroutine)); - -If the names of C routines are modified when used by FORTRAN, fcallsc would -usually be defined once in a header_file.h for the application. This definition -would then be used and be valid for the entire application and fcallsc would at -no point need to be redefined. - - -ONCE AGAIN: THE DEFINITIONS, INSTRUCTIONS, DECLARATIONS AND DIFFICULTIES -DESCRIBED HERE, NOTE 9. of II ii), -APPLY ONLY FOR VAX VMS, - IBM RS/6000 WITHOUT THE -qextname OPTION FOR xlf, OR - HP-UX WITHOUT THE +ppu OPTION FOR f77 - AbsoftUNIXFortran -AND APPLY ONLY WHEN CREATING WRAPPERS WHICH ENABLE FORTRAN TO CALL C ROUTINES. - - - -iii) Using C to manipulate FORTRAN COMMON BLOCKS: - ------------------------------------------------------- - -FORTRAN common blocks are set up with the following three constructs: - -1. -#define Common_block_name COMMON_BLOCK(COMMON_BLOCK_NAME,common_block_name) - -Common_block_name is in UPPER CASE. -COMMON_BLOCK_NAME is in UPPER CASE. -common_block_name is in lower case. -[Common_block_name actually follows the same 'rules' as Routine_name in Note 2. - of II i).] This construct exists to ensure that C code accessing the common -block is machine independent. - -2. -COMMON_BLOCK_DEF(TYPEDEF_OF_STRUCT, Common_block_name); - -where -typedef { ... } TYPEDEF_OF_STRUCT; -declares the structure which maps on to the common block. The #define of -Common_block_name must come before the use of COMMON_BLOCK_DEF. - -3. -In exactly one of the C source files, storage should be set aside for the -common block with the definition: - -TYPEDEF_OF_STRUCT Common_block_name; - -The above definition may have to be omitted on some machines for a common block -which is initialized by Fortran BLOCK DATA or is declared with a smaller size -in the C routines than in the Fortran routines. - -The rules for common blocks are not well defined when linking/loading a mixture -of C and Fortran, but the following information may help resolve problems. - -From the 2nd or ANSI ed. of K&R C, p.31, last paragraph: -i) - An external variable must be defined, exactly once, outside of any function; - this sets aside storage for it. -ii) - The variable must also be declared in each function that wants to access it; - ... - The declaration ... may be implicit from context. - -In Fortran, every routine says 'common /bar/ foo', -i.e. part ii) of the above, but there's no part i) requirement. -cc/ld on some machines don't require i) either. -Therefore, when handling Fortran, and sometimes C, -the loader/linker must automagically set aside storage for common blocks. - -Some loaders, including at least one for the CRAY, turn off the -'automagically set aside storage' capability for Fortran common blocks, -if any C object declares that common block. -Therefore, C code should define, i.e. set aside storage, -for the the common block as shown above. - -e.g. -C Fortran - common /fcb/ v,w,x - character *(13) v, w(4), x(3,2) - -/* C */ -typedef struct { char v[13],w[4][13],x[2][3][13]; } FCB_DEF; -#define Fcb COMMON_BLOCK(FCB,fcb) -COMMON_BLOCK_DEF(FCB_DEF,Fcb); -FCB_DEF Fcb; /* Definition, which sets aside storage for Fcb, */ - /* may appear in at most one C source file. */ - - -C programs can place a string (or a multidimensional array of strings) into a -FORTRAN common block using the following call: - -C2FCBSTR( CSTR, FSTR,DIMENSIONS); - -where: - -CSTR is a pointer to the first element of C's copy of the string (array). - The C code must use a duplicate of, not the original, common block string, - because the FORTRAN common block does not allocate space for C strings' - terminating '\0'. - -FSTR is a pointer to the first element of the string (array) in the common - block. - -DIMENSIONS is the number of dimensions of string array. - e.g. char a[10] has DIMENSIONS=0. - char aa[10][17] has DIMENSIONS=1. - etc... - -C2FCBSTR will copy the string (array) from CSTR to FSTR, padding with blanks, -' ', the trailing characters as required. C2FCBSTR uses DIMENSIONS and FSTR to -determine the lengths of the individual string elements and the total number of -elements in the string array. - -Note that: -- the number of string elements in CSTR and FSTR are identical. -- for arrays of strings, the useful lengths of strings in CSTR and FSTR must be - the same. i.e. CSTR elements each have 1 extra character to accommodate the - terminating '\0'. -- On most non-ANSI compilers, the DIMENSION argument cannot be prepended by any - blanks. - - -FCB2CSTR( FSTR, CSTR,DIMENSIONS) - -is the inverse of C2FCBSTR, and shares the same arguments and caveats. -FCB2CSTR copies each string element of FSTR to CSTR, minus FORTRAN strings' -trailing blanks. - - -cfortran.h USERS ARE STRONGLY URGED TO EXAMINE THE COMMON BLOCK EXAMPLES IN -cfortest.c AND cfortex.f. The use of strings in common blocks is -demonstrated, along with a suggested way for C to imitate FORTRAN EQUIVALENCE'd -variables. - - - ===> USERS OF CFORTRAN.H NEED READ NO FURTHER <=== - - -III Some Musings ----------------- - -cfortran.h is simple enough to be used by the most basic of applications, i.e. -making a single C/FORTRAN routine available to the FORTRAN/C programmers. Yet -cfortran.h is powerful enough to easily make entire C/FORTRAN libraries -available to FORTRAN/C programmers. - - -cfortran.h is the ideal tool for FORTRAN libraries which are being (re)written -in C, but are to (continue to) support FORTRAN users. It allows the routines to -be written in 'natural C', without having to consider the FORTRAN argument -passing mechanisms of any machine. It also allows C code accessing these -rewritten routines, to use the C entry point. Without cfortran.h, one risks the -perverse practice of C code calling a C function using FORTRAN argument passing -mechanisms! - - -Perhaps the philosophy and mechanisms of cfortran.h could be used and extended -to create other language bridges such as ADAFORTRAN, CPASCAL, COCCAM, etc. - - -The code generation machinery inside cfortran.h, i.e. the global structure is -quite good, being clean and workable as seen by its ability to meet the needs -and constraints of many different compilers. Though the individual instructions -of the A..., C..., T..., R... and K... tables deserve to be cleaned up. - - - -IV Getting Serious with cfortran.h ------------------------------------ - -cfortran.h is set up to be as simple as possible for the casual user. While -this ease of use will always be present, 'hooks', i.e. preprocessor directives, -are required in cfortran.h so that some of the following 'inefficiencies' can -be eliminated if they cause difficulties: - -o cfortran.h contains a few small routines for string manipulation. These -routines are declared static and are included and compiled in all source code -which uses cfortran.h. Hooks should be provided in cfortran.h to create an -object file of these routines, allowing cfortran.h to merely prototypes -these routines in the application source code. This is the only 'problem' which -afflicts both halves of cfortran.h. The remaining discussion refers to the C -calls FORTRAN half only. - -o Similar to the above routines, cfortran.h generates code for a 'wrapper' -routine for each FUNCTION exported from FORTRAN. Again cfortran.h needs -preprocessor directives to create a single object file of these routines, -and to merely prototype them in the applications. - -o Libraries often contain hundreds of routines. While the preprocessor makes -quick work of generating the required interface code from cfortran.h and the -application.h's, it may be convenient for very large stable libraries to have -final_application.h's which already contain the interface code, i.e. these -final_application.h's would not require cfortran.h. [The convenience can be -imagined for the VAX VMS CC compiler which has a fixed amount of memory for -preprocessor directives. Not requiring cfortran.h, with its hundreds of -directives, could help prevent this compiler from choking on its internal -limits quite so often.] - -With a similar goal in mind, cfortran.h defines 100's of preprocessor -directives. There is always the potential that these will clash with other tags -in the users code, so final_applications.h, which don't require cfortran.h, -also provide the solution. - -In the same vein, routines with more than 14 arguments can not be interfaced by -cfortran.h with compilers which limit C macros to 31 arguments. To resolve this -difficulty, final_application.h's can be created on a compiler without this -limitation. - -Therefore, new machinery is required to do: - -application.h + cfortran.h => final_application.h - -The following example may help clarify the means and ends: - -If the following definition of the HBOOK1 routine, the /*commented_out_part*/, -is passed through the preprocessor [perhaps #undefing and #defining preprocessor -constants if creating an application.h for compiler other than that of the -preprocessor being used, e.g. cpp -Umips -DCRAY ... ] : - -#include "cfortran.h" -PROTOCCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT) -/*#define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \*/ - CCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \ - ID,CHTITLE,NX,XMI,XMA,VMX) - -A function prototype is produced by the PROTOCCALLSFSUB6(...). -Interface code is produced, based on the 'variables', -ID,CHTITLE,NX,XMI,XMA,VMX, which will correctly massage a HBOOK1 call. -Therefore, adding the #define line: - -'prototype code' -#define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \ - 'interface code'(ID,CHTITLE,NX,XMI,XMA,VMX) - -which is placed into final_application.h. - -The only known limitation of the above method does not allow the 'variable' -names to include B1,B2,...,B9,BA,BB,... - -Obviously the machinery to automatically generate final_applications.h from -cfortran.h and applications.h needs more than just some preprocessor -directives, but a fairly simple unix shell script should be sufficient. Any -takers? - - - -V Machine Dependencies of cfortran.h ------------------------------------- - -Porting cfortran.h applications, e.g. the hbook.h and cstring.c mentioned -above, to other machines is trivial since they are machine independent. Porting -cfortran.h requires a solid knowledge of the new machines C preprocessor, and -its FORTRAN argument passing mechanisms. Logically cfortran.h exists as two -halves, a "C CALLS FORTRAN" and a "FORTRAN CALLS C" utility. In some cases it -may be perfectly reasonable to port only 'one half' of cfortran.h onto a new -system. - - -The lucky programmer porting cfortran.h to a new machine, must discover the -FORTRAN argument passing mechanisms. A safe starting point is to assume that -variables and arrays are simply passed by reference, but nothing is guaranteed. -Strings, and n-dimensional arrays of strings are a different story. It is -doubtful that any systems do it quite like VAX VMS does it, so that a UNIX or -f2c versions may provide an easier starting point. - - -cfortran.h uses and abuses the preprocessor's ## operator. Although the ## -operator does not exist in many compilers, many kludges do. cfortran.h uses -/**/ with no space allowed between the slashes, '/', and the macros or tags -to be concatenated. e.g. -#define concat(a,b) a/**/b /* works*/ -main() -{ - concat(pri,ntf)("hello"); /* e.g. */ -} -N.B. On some compilers without ##, /**/ may also not work. The author may be -able to offer alternate kludges. - - - -VI Bugs in vendors C compilers and other curiosities ----------------------------------------------------- - -1. ULTRIX xxxxxx 4.3 1 RISC - -Condolences to long suffering ultrix users! -DEC supplies a working C front end for alpha/OSF, but not for ultrix. - -From K&R ANSI C p. 231: - ultrix> cat cat.c - #define cat(x, y) x ## y - #define xcat(x,y) cat(x,y) - cat(cat(1,2),3) - xcat(xcat(1,2),3) - ultrix> cc -E cat.c - 123 <---- Should be: cat(1,2)3 - 123 <---- Correct. - ultrix> - -The problem for cfortran.h, preventing use of -std and -std1: - ultrix> cat c.c - #define cat(x, y) x ## y - #define xcat(x,y) cat(x,y) - #define AB(X) X+X - #define C(E,F,G) cat(E,F)(G) - #define X(E,F,G) xcat(E,F)(G) - C(A,B,2) - X(A,B,2) - ultrix> cc -std1 -E c.c - 2+2 - AB (2) <---- ????????????? - ultrix> - ultrix> cc -std0 -E c.c - 2+2 - AB(2) <---- ????????????? - ultrix> - -Due to further ultrix preprocessor problems, -for all definitions of definitions with arguments, -cfortran.h >= 3.0 includes the arguments and recommends the same, -even though it is not required by ANSI C. -e.g. Users are advised to do - #define fcallsc(UN,LN) orig_fcallsc(UN,LN) -instead of - #define fcallsc orig_fcallsc -since ultrix fails to properly preprocess the latter example. -CRAY used to (still does?) occasionally trip up on this problem. - - -2. ConvexOS convex C210 11.0 convex - -In a program with a C main, output to LUN=6=* from Fortran goes into -$pwd/fort.6 instead of stdout. Presumably, a magic incantation can be called -from the C main in order to properly initialize the Fortran I/O. - - -3. SunOS 5.3 Generic_101318-69 sun4m sparc - -The default data and code alignments produced by cc, gcc and f77 are compatible. -If deviating from the defaults, consistent alignment options must be used -across all objects compiled by cc and f77. [Does gcc provide such options?] - - -4. SunOS 5.3 Generic_101318-69 sun4m sparc with cc: SC3.0.1 13 Jul 1994 - or equivalently - ULTRIX 4.4 0 RISC using cc -oldc - are K&R C preprocessors that suffer from infinite loop macros, e.g. - - zedy03> cat src.c - #include "cfortran.h" - PROTOCCALLSFFUN1(INT,FREV,frev, INTV) - #define FREV(A1) CCALLSFFUN1( FREV,frev, INTV, A1) - /* To avoid the problem, deletete these ---^^^^--- spaces. */ - main() { static int a[] = {1,2}; FREV(a); return EXIT_SUCCESS; } - - zedy03> cc -c -Xs -v -DMAX_PREPRO_ARGS=31 -D__CF__KnR src.c - "src.c", line 4: FREV: actuals too long - "src.c", line 4: FREV: actuals too long - .... 3427 more lines of the same message - "src.c", line 4: FREV: actuals too long - cc : Fatal error in /usr/ccs/lib/cpp - Segmentation fault (core dumped) - - -5. Older sun C compilers - -To link to f77 objects, older sun C compilers require the math.h macros: - -#define RETURNFLOAT(x) { union {double _d; float _f; } _kluge; \ - _kluge._f = (x); return _kluge._d; } -#define ASSIGNFLOAT(x,y) { union {double _d; float _f; } _kluge; \ - _kluge._d = (y); x = _kluge._f; } - -Unfortunately, in at least some copies of the sun math.h, the semi-colon -for 'float _f;' is left out, leading to compiler warnings. - -The solution is to correct math.h, or to change cfortran.h to #define -RETURNFLOAT(x) and ASSIGNFLOAT(x,y) instead of including math.h. - - -6. gcc version 2.6.3 and probably all other versions as well - -Unlike all other C compilers supported by cfortran.h, -'gcc -traditional' promotes to double all functions returning float -as demonstrated bu the following example. - -/* m.c */ -#include -int main() { FLOAT_FUNCTION d(); float f; f = d(); printf("%f\n",f); return 0; } - -/* d.c */ -float d() { return -123.124; } - -burow[29] gcc -c -traditional d.c -burow[30] gcc -DFLOAT_FUNCTION=float m.c d.o && a.out -0.000000 -burow[31] gcc -DFLOAT_FUNCTION=double m.c d.o && a.out --123.124001 -burow[32] - -Thus, 'gcc -traditional' is not supported by cfortran.h. -Support would require the same RETURNFLOAT, etc. macro machinery -present in old sun math.h, before sun gave up the same promotion. - - -7. CRAY - -At least some versions of the t3e and t3d C preprocessor are broken -in the fashion described below. -At least some versions of the t90 C preprocessor do not have this problem. - -On the CRAY, all Fortran names are converted to uppercase. -Generally the uppercase name is also used for the macro interface -created by cfortran.h. - -For example, in the following interface, -EASY is both the name of the macro in the original C code -and EASY is the name of the resulting function to be called. - -#define EASY(A,B) CCALLSFSUB2(EASY,easy, PINT, INTV, A, B) - -The fact that a macro called EASY() expands to a function called EASY() -is not a problem for a working C preprocessor. -From Kernighan and Ritchie, 2nd edition, p.230: - - In both kinds of macro, the replacement token sequence is repeatedly - rescanned for more identifiers. However, once a given identifier has been - replaced in a given expansion, it is not replaced if it turns up again during - rescanning; instead it is left unchanged. - -Unfortunately, some CRAY preprocessors are broken and don't obey the above rule. -A work-around is for the user to NOT use the uppercase name -of the name of the macro interface provided by cfortran.h. For example: - -#define Easy(A,B) CCALLSFSUB2(EASY,easy, PINT, INTV, A, B) - -Luckily, the above work-around is not required since the following -work-around within cfortran.h also circumvents the bug: - - /* (UN), not UN, is required in order to get around CRAY preprocessor bug.*/ - #define CFC_(UN,LN) (UN) /* Uppercase FORTRAN symbols. */ - -Aside: The Visual C++ compiler is happy with UN, but barfs on (UN), - so either (UN) causes nonstandard C/C++ or Visual C++ is broken. - - -VII History and Acknowledgements --------------------------------- - -1.0 - Supports VAX VMS using C 3.1 and FORTRAN 5.4. Oct. '90. -1.0 - Supports Silicon Graphics w. Mips Computer 2.0 f77 and cc. Feb. '91. - [Port of C calls FORTRAN half only.] -1.1 - Supports Mips Computer System 2.0 f77 and cc. Mar. '91. - [Runs on at least: Silicon Graphics IRIX 3.3.1 - DECstations with Ultrix V4.1] -1.2 - Internals made simpler, smaller, faster, stronger. May '91. - - Mips version works on IBM RS/6000, this is now called the unix version. -1.3 - UNIX and VAX VMS versions are merged into a single cfortran.h. July '91. - - C can help manipulate (arrays of) strings in FORTRAN common blocks. - - Dimensions of string arrays arguments can be explicit. - - Supports Apollo DomainOS 10.2 (sys5.3) with f77 10.7 and cc 6.7. - -2.0 - Improved code generation machinery creates K&R or ANSI C. Aug. '91. - - Supports Sun, CRAY. f2c with vcc on VAX Ultrix. - - cfortran.h macros now require routine and COMMON block names in both - upper and lower case. No changes required to applications though. - - PROTOCCALLSFSUBn is eliminated, with no loss to cfortran.h performance. - - Improved tools and guidelines for naming C routines called by FORTRAN. -2.1 - LOGICAL correctly supported across all machines. Oct. '91. - - Improved support for DOUBLE PRECISION on the CRAY. - - HP9000 fully supported. - - VAX Ultrix cc or gcc with f77 now supported. -2.2 - SHORT, i.e. INTEGER*2, and BYTE now supported. Dec. '91. - - LOGICAL_STRICT introduced. More compact and robust internal tables. - - typeV and typeVV for type = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG,SHORT. - - FORTRAN passing strings and NULL pointer to C routines improved. -2.3 - Extraneous arguments removed from many internal tables. May '92. - - Introduce pseudo argument type SIMPLE for user defined types. - - LynxOS using f2c supported. (Tested with LynxOS 2.0 386/AT.) -2.4 - Separation of internal C and Fortran compilation directives. Oct. '92. - - f2c and NAG f90 supported on all machines. -2.5 - Minor mod.s to source and/or doc for HP9000, f2c, and NAG f90. Nov. '92. -2.6 - Support external procedures as arguments with type ROUTINE. Dec. '92. -2.7 - Support Alpha VMS. Support HP9000 f77 +ppu Jan. '93. - - Support arrays with up to 7 dimensions. - - Minor mod. of Fortran NULL to C via (P)STRING. - - Specify the type of ROUTINE passed from Fortran to C [ANSI C requirement.] - - Macros never receive a null parameter [RS/6000 requirement.] -2.8 - PSTRING for Fortran calls C no longer provides escape to pass April'93. - NULL pointer nor to pass address of original string. - PNSTRING introduced with old PSTRING's behavior. - PPSTRING introduced to always pass original address of string. - - Support Alpha/OSF. - - Document that common blocks used in C should be declared AND defined. - -3.0 - Automagic handling of ANSI ## versus K&R /**/ preprocessor op. March'95. - - Less chance of name space collisions between cfortran.h and other codes. - - SIMPLE macros, supporting user defined types, have changed names. -3.1 - Internal macro name _INT not used. Conflicted with IRIX 5.3. May '95. - - SunOS, all versions, should work out of the box. - - ZTRINGV_ARGS|F(k) may no longer point to a PDOUBLE or PFLOAT argument. - - ConvexOS 11.0 supported. -3.2 - __hpux no longer needs to be restricted to MAX_PREPRO_ARGS=31. Oct. '95. - - PSTRING bug fixed. - - ZTRINGV_ARGS|F(k) may not point to a PBYTE,PINT,PLONG or PSHORT argument. - - (P)ZTRINGV machinery improved. Should lead to fewer compiler warnings. - (P)ZTRINGV no longer limits recursion or the nesting of routines. - - SIMPLE macros, supporting user defined types, have changed slightly. -3.3 - Supports PowerStation Fortran with Visual C++. Nov. '95. - - g77 should work using f2cFortran, though no changes made for it. - - (PROTO)CCALLSFFUN10 extended to (PROTO)CCALLSFFUN14. - - FCALLSCFUN10 and SUB10 extended to FCALLSCFUN14 and SUB14. -3.4 - C++ supported, Dec. '95. - but it required the reintroduction of PROTOCCALLSFSUBn for users. - - HP-UX f77 +800 supported. -3.5 - Absoft UNIX Fortran supported. Sept.'96. -3.6 - Minor corrections to cfortran.doc. Oct. '96. - - Fixed bug for 15th argument. [Thanks to Tom Epperly at Aspen Tech.] - - For AbsoftUNIXFortran, obey default of prepending _C to COMMON BLOCK name. - - Fortran calling C with ROUTINE argument fixed and cleaned up. -3.7 - Circumvent IBM and HP "null argument" preprocessor warning. Oct. '96 -3.8 - (P)STRINGV and (P)ZTRINGV can pass a 1- or 2-dim. char array. Feb. '97 - (P)ZTRINGV thus effectively also provides (P)ZTRING. - - (P)ZTRINGV accepts a (char *) pointer. -3.9 - Bug fixed for *VVVVV. May '97 - - f2c: Work-around for strange underscore-dependent naming feature. - - NEC SX-4 supported. - - CRAY: LOGICAL conversion uses _btol and _ltob from CRAY's fortran.h. - - CRAY: Avoid bug of some versions of the C preprocessor. - - CRAY T3E: FORTRAN_REAL introduced. - -4.0 - new/delete now used for C++. malloc/free still used for C. Jan. '98 - - FALSE no longer is defined by cfortran.h . - - Absoft Pro Fortran for MacOS supported. -4.1 - COMMA and COLON no longer are defined by cfortran.h . April'98 - - Bug fixed when 10th arg. or beyond is a string. - [Rob Lucchesi of NASA-Goddard pointed out this bug.] - - CCALLSFSUB/FUN extended from 14 to 27 arguments. - - Workaround SunOS CC 4.2 cast bug. [Thanks to Savrak SAR of CERN.] -4.2 - Portland Group needs -DpgiFortran . [Thank George Lai of NASA.] June '98 -4.3 - (PROTO)CCALLSFSUB extended from 20 to 27 arguments. July '98 - - -['Support' implies these and more recent releases of the respective - OS/compilers/linkers can be used with cfortran.h. - Earlier releases may also work.] - - -Acknowledgements: -- CERN very generously sponsored a week in 1994 for me to work on cfortran.h. -- M.L.Luvisetto (Istituto Nazionale Fisica Nucleare - Centro Nazionale - Analisi Fotogrammi, Bologna, Italy) provided all the support for the port to - the CRAY. Marisa's encouragement and enthusiasm was also much appreciated. -- J.Bunn (CERN) supported the port to PowerStation Fortran with Visual C++. -- Paul Schenk (UC Riverside, CERN PPE/OPAL) in June 1993 extended cfortran.h 2.7 - to have C++ call Fortran. This was the starting point for full C++ in 3.4. -- Glenn P.Davis of University Corp. for Atmospheric Research (UCAR) / Unidata - supported the NEC SX-4 port and helped understand the CRAY. -- Tony Goelz of Absoft Corporation ported cfortran.h to Absoft. -- Though cfortran.h has been created in my 'copious' free time, I thank - NSERC for their generous support of my grad. student and postdoc years. -- Univ.Toronto, DESY, CERN and others have provided time on their computers. - - -THIS PACKAGE, I.E. CFORTRAN.H, THIS DOCUMENT, AND THE CFORTRAN.H EXAMPLE -PROGRAMS ARE PROPERTY OF THE AUTHOR WHO RESERVES ALL RIGHTS. THIS PACKAGE AND -THE CODE IT PRODUCES MAY BE FREELY DISTRIBUTED WITHOUT FEES, SUBJECT TO THE -FOLLOWING RESTRICTIONS: -- YOU MUST ACCOMPANY ANY COPIES OR DISTRIBUTION WITH THIS (UNALTERED) NOTICE. -- YOU MAY NOT RECEIVE MONEY FOR THE DISTRIBUTION OR FOR ITS MEDIA - (E.G. TAPE, DISK, COMPUTER, PAPER.) -- YOU MAY NOT PREVENT OTHERS FROM COPYING IT FREELY. -- YOU MAY NOT DISTRIBUTE MODIFIED VERSIONS WITHOUT CLEARLY DOCUMENTING YOUR - CHANGES AND NOTIFYING THE AUTHOR. -- YOU MAY NOT MISREPRESENTED THE ORIGIN OF THIS SOFTWARE, EITHER BY EXPLICIT - CLAIM OR BY OMISSION. - -THE INTENT OF THE ABOVE TERMS IS TO ENSURE THAT THE CFORTRAN.H PACKAGE NOT BE -USED FOR PROFIT MAKING ACTIVITIES UNLESS SOME ROYALTY ARRANGEMENT IS ENTERED -INTO WITH ITS AUTHOR. - -THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESSED OR IMPLIED. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST -OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. THE AUTHOR IS NOT RESPONSIBLE -FOR ANY SUPPORT OR SERVICE OF THE CFORTRAN.H PACKAGE. - - Burkhard Burow - burow@desy.de - -P.S. Your comments and questions are welcomed and usually promptly answered. - -VAX VMS and Ultrix, Alpha, OSF, Silicon Graphics (SGI), DECstation, Mips RISC, -Sun, CRAY, Convex, IBM RS/6000, Apollo DomainOS, HP, LynxOS, f2c, NAG, Absoft, -NEC SX-4, PowerStation and Visual C++ are registered trademarks of their -respective owners. - -============================================================================ - -ADDITIONAL LICENSING INFORMATION (added by W D Pence on 4 October 2007) - -The author of cfortran has subsequently stated that cfortran.h may optionally -be used and distributed under the GNU Library General Public License (LGPL). -This statement was made in an email to Kevin McCarty, which is reproduced below: - ----------------------------------------- -Date: Tue, 22 Oct 2002 12:48:00 -0400 -From: Burkhard D Steinmacher-burow -To: Kevin B. McCarty -Subject: Re: CFortran licensing question - -Kevin, - -[Just noticed that I didn't send this yesterady.] - -I have no time right now to read through licenses. -IIRC, library GPL is fairly unrestrictive, so I'll choose that. So..... - -You may consider this e-mail as a notice that as an alternative to any -other cfortran licenses, -I hereby relase all versions and all parts of cfortran under the -the Library GPL license. -From among these licenses, the user is free to choose -the license or licenses under which cfortran is used. - -Contact me if you'd like to be able to choose another license. - -Burkhard - -steinmac@us.ibm.com, (914)945-3756, Fax 3684, Tieline 862 ------------------------------------------- - -/* end: cfortran.doc */ diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/changes.txt b/src/external/OpenGR/3rdparty/cfitsio/docs/changes.txt deleted file mode 100644 index 6f62e6d8b..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/changes.txt +++ /dev/null @@ -1,4418 +0,0 @@ - Log of Changes Made to CFITSIO - -Version 3.41 - November 2016 - - - The change made in version 3.40 to include strings.h caused problems on - Windows (and other) platforms, so this change was backed out. The reason - for including it was to define the strcasecmp and strcasencmp functions, so - as an alternative, new equivalent functions called fits_strcasecmp and - fits_strncasecmp have been added to CFITSIO.as a substitute. All the - previous calls to the str[n]casecmp functions have been changed to - now call fits_str[n]casecmp. In addition, the previously defined - ngp_strcasecmp function (in grparser.c) has been removed and the calls to - it have been changed to fits_strcasecmp. - - - The speed.c utility program was changed to correctly call - the gettimeofday function with a NULL second arguement. - -Version 3.40 - October 2016 - - - fixed a bug when writing long string keywords with the CONTINUE convention - which caused the CONTINUE'd strings to only be 16 characters long, instead - of using up all the available space in the 80-character header record. - - - fixed a missing 'defined' keyword in fitsio.h. - - - replaced all calls to strtok (which is not threadsafe) with a new ffstrtok - function which internally calls the threadsafe strtok_r function. One - byproduct of this change is that must also be included - in several of the C source code files. - - - modified the ffphbn function in putkey.c to support TFORM specifiers that - use lowercase 'p' (instead of uppercase) when referring to a variable-length - array column. - - - modified the lexical parser in eval.y and eval_y.c to support bit array - columns (with TFORMn = 'X') with greater than 256 elements. Fix to bitcmp - function: The internal 'stream' array is now - allocated dynamically rather than statically fixed at size 256. - This was failing when users attempted a row filtering of a bitcol - that was wider than 256X. In bitlgte, bitand, and bitor functions, replaced - static stream[256] array allocation with dynamic allocation. - - - modified the ffiter function in putcol.c to fix a problem which could - cause the iterator function to incorrectly deal with null values. This - only affected TLONG type columns in cases where sizeof(long) = 8, as well - as for TLONGLONG type columns. - - - Fix made to uncompress2mem function in zcomprss.c for case where output - uncompressed file expands to over the 2^32 (4Gb) limit. It now - checks for this case at the start, and implements a 4Gb paging - system through the output buffer. The problem was specifically - caused by the d_stream.avail_out member being of 4-byte type uInt, - and thus unable to handle any memory position values above 4Gb. - - - fixed a bug in fpackutil.c when using the -i2f (integer to float) option - in fpack to compress an integer image that is scaled with non-default values - for BSCALE and BZERO. This required an additional call to ffrhdu to reset - the internal structures that describe the input FITS file. - - - modified fits_uncompress_table in imcompress.c to silently ignore the - ZTILELEN keyword value if it larger than the number of rows in the table - - - Tweak strcasecmp/strncasecmp ifdefs to exclude 64-bit MINGW - environment, as it does not lack those functions. (eval_l.c, - fitsio2.h) - - - CMakeLists.txt: Set M_LIB to "" for MINGW build environment (in - addition to MSVC). - - - Makefile.in: Add *.dSYM (non-XCode gcc leftovers on Macs) to - clean list. Install libs by name rather than using a wildcard. - - - configure: Fix rpath token usage for XCode vs. non-XCode gcc on Macs. - - -Version 3.39 - April 2016 - - - added 2 new routines suggested by Eric Mandel: - ffhisto3 is similar to ffhisto2, except that it does not close the - original file. - fits_open_extlist is similar to fits_open_data except that it opens - the FITS file and then moves to the first extension in the user-input - list of 'interesting' extensions. - - - in ffpsvc and ffprec, it is necessary to treat CONTINUE, COMMENT, HISTORY, - and blank name keywords as a special case which must be treated differently - from other keywords because they have no value field and, by definition, - have keyword names that are strictly limited in length. - - - added the Fortran wrapper routines for the 2 new string keyword reading - routines (FTGSKY and FTGKSL), and documented all the routines in the - FITSIO and CFITSIO users guides. - - - in ffinttyp, added explicit initialization of the input 'negative' - argument to 0. - - - added new routine to return the length of the keyword value string: - fits_get_key_strlen / ffgksl. - This is primarily intended for use with string keywords - that use the CONTINUE convention to continue the - value over multiple header records, but this routine can be used - to get the length of the value string for any type keyword. - - - added new routine to read string-valued keywords: - fits_read_string_key / ffgsky - This routine supports normal string keywords as well as long string - keywords that use the CONTINUE convention. In many cases this routine - may be more convenient to use then the older fits_read_key_longstr - routine. - - - changed the prototype of fits_register_driver in fitsio2.h so that the - pointer definition argument does not have the same name as the pointer - itself (to work around a bug in the pgcc compiler). - - - added the missing FTDTDM fortran wrapper definition to f77_wrap3.c. - - - modified Makefile.in and configure.in to add LDFLAGS_BIN for task linker - flages, which will be the same as LDFLAGS except on newer Mac OS X where - an rpath flag is added. - - - modified Makefile.in to add a new "make utils" command which will build - fpack, funpack, cookbook, fitscopy, imcopy, smem, speed, and testprog. - These programs will be installed into $prfix/bin. - - - fixed a bug when attempting to modify the values in a variable-length - bit ("X") column in a binary table. - - - reinstated the ability to write HIERARCH keywords that contain characters - that would not be allowed in a normal 8-character keyword name, which had - been disabled in the previous release. - -Version 3.38 - February 2016 - - - CRITICAL BUG FIX: - The Intel 15 and 16 compilers (and potentially other compilers) may silently - produce incorrect assembly code when compiling CFITSIO with the -O2 (or - higher) optimization flag. In particular, this problem could cause CFITSIO - to incorrectly read the values of arrays of 32-bit integers in a FITS file - (i.e., images with BITPIX = 32 or table columns with TFORM = 'J') when the - array is being read into a 'long' integer array in cases where the long - array elements are 8 bytes long. - - One way to test if a particular system is affected by this problem is to - compile CFITSIO V3.37 (or earlier) with optimization enabled, and then - compare the output of the testprog.c program with the testprog.out file - that is distributed with CFITSIO. If there are any differences in the - files, then this system might be affected by this bug. Further tests - should be performed to determine the exact cause. - - The root cause of this problem was traced to the fact that CFITSIO was - aliasing an array of 32-bit integers and an array of 64-bit integers to the - same memory location in order to obtain better data I/O efficiency when - reading FITS files. When CFITSIO modified the values in these arrays, it - was essential that the processing be done in strict sequential order from - one end of the array to the other end, as was implicit in the C code - algorithm. In this case, however, the compiler adopted certain loop - optimization techniques that produced assembly code that violated this - assumption. Technically, the CFITSIO code violates the "strict aliasing" - assumption in ANSI C99, therefore the affected CFITSIO routines have been - modified so that the aliasing of different data types to the same memory - location no longer occurs. - - - fixed problem in configure and configure.in which caused the programs that - are distributed with CFITSIO (most notably, fack and funpack) to be build - without using any compiler optimization options, which could make them - run more slowly than expected. - - - in imcompress.c, fixed bug where the rowspertile variable (declared as 'long') - was mistakenly declared as a TLONGLONG variable in a call to fits_write_key. - This could have caused the ZTILELEN keyword to be written incorrectly in - the header of tile-compressed FITS tables on systems where sizeof(long) = 4. - - - in imcompress.c, implemented a new set of routines that safely convert - shorter integer arrays into a longer integer arrays (e.g. short to int) - where both arrays are aliased to the same memory location. These - special routines were needed to guard against certain compiler optimization - techniques that could produce incorrect code. - - - modified the 4 FnNoise5_(type) routines in quantize.c to correctly - count the number of non-null pixels in the input array. Previously the - count could be inaccurate if the image mainly consisted of null pixels. - This could have caused certain floating point image tiles to be - quantized during the image compression process, when in fact the tile - did not satisfy all the criteria to be safely quantized. - - - in imcomp_copy_comp2img, added THEAP to the list of binary table - keywords that may be present in the header of a compressed image - and should not be copied to the uncompressed image header. - - - modified fits_copy_col to check that when copying a vector column, the - vector length in the output column is the same as in the input column. - Also modified the code to support the case where a column is being copied - to an earlier position in the same table (which shifts the input column - over 1 space). - - - added configure option (--with-bzip2) to support reading bzip2 compressed - FITS files. This also required modifications to drvrmem.c and drvrfile.c - This depends on having the bzlib library installed on the - local machine. This patch was submitted by Dustin Lang. - - - replaced calls to 'memcpy' by 'memmove' in getcolb.c, getcold.c, - getcole.c, and getcoli.c to support cases where the 2 memory areas - overlap. (submitted by Aurelien Jarno) - - - modified the FITS keyword reading and writing routines to potentially - support keywords with names longer than 8-characters. This was implemented - in anticipation of a new experimental FITS convention which allows longer - keyword names. - - - in fits_quantize_double in quantize.c, test if iseed == N_RANDOM, - to avoid the (unlikely) possibility of overflowing the random number - array bounds. (The corresponding fits_quantize_float routine already - performed this test). - - - in the FnNoise5_short routine in quantize.c, change the first 'if' - statement from "if (nx < 5)" to "if )nx < 9)", in order to support the - (very rare) case where the tile is from 5 to 8 pixels wide. Also make - the same change in the 3 other similar FnNoise5_* routines. - - - in the qtree_bitins64 routine in fits_hdecompress.c, must declare the - plane_val variable as 'LONGLONG' instead of int. This bug could have - caused integer overflow errors when uncompressing integer*4 images that - had been compressed with the Hcompress algorithm, but only in cases - where the image contains large regions of pixels whose values are close - to the maximum integer*4 value of 2**31. - - - in fits_hcompress.c, call the calloc function instead of malloc when - allocating the signbits array, to eliminate the need to individually - set each byte to zero. - - - in the ffinit routine, and in a couple other routines that call ffinit, - initialize the *fptr input parameter to NULL, even if the input - status parameter value is greater than zero. This helps prevent - errors later on if that fptr value is passed to ffclos. - - - modified ftcopy, in edithdu.c, to only abort if status > 0 rather - than if status != 0. This had caused a problem in funpack in rare - circumstances. - - - in imcompress.c changed all the calls to ffgdes to ffgdesll, to support - compressed files greater than 2.1 GB in size. - - - fixed bug in ffeqtyll when it is called with 4th and 5th arguments - set to NULL. - - - in fitsio.h, added the standard C++ guard around the declaration of the - function fits_read_wcstab. (reported by Tammo Jan Dijkema, Astron.) - - - in fitsio.h, changed the prototype variable name "zero" to "zeroval" to - avoid conflict in code that uses a literal definition of 'zero' to mean 0. - - - tweaked Makefile.in and configure.in to use LDFLAGS instead of CFLAGS - for linking, use Macros for library name, and let fpack and funpack - link with shared library. - - - modified an 'ifdef' statement in cfileio.c to test for '__GLIBC__' - instead of 'linux' when initializing support for multi-threading. - - - modified ffeqtyll to return an effective column data type of TDOUBLE - in the case of a 'K' (64-bit integer) column that has non-integer - TSCALn or TZEROn keywords. - - - modified ffgcls (which returns the value in a column as a formatted string) - so that when reading a 'K' (TLONGLONG) column it returns a long long integer - value if the column is not scaled, but returns a double floating point - value if the column has non-integer TSCALn or TZEROn values. - - - modified fitsio.h to correctly define "OFF_T long long" when using - the Borland compiler - - - converted the 'end of line' characters in simplerng.c file to the unix - style, instead of PC DOS. - - - updated CMakeLists.txt CMake build file which is primarily used to - build CFITSIO on Windows machines. - - - modified fits_get_keyclass to recognize ZQUANTIZ and ZDITHER0 as - TYP_CMPRS_KEY type keywords, i.e., keywords used in tile compressed - image files. - - - added test to see if HAVE_UNISTD_H is defined, as a condition for - including unistd.h in drvrfile.c drvrnet.c, drvrsmem.c, and group.c. - - - modified the CMakelist.txt file to fix several issues (primarily for - building CFITSIO on Windows machines).. - - - fixed bug when reading tile-compressed images that were compressed with - the IRAF PLIO algorithm. This bug did not affect fpack or funpack, but - other software that reads the compressed image could be affected. The - bug would cause the data values to be offset by 32768 from the actual - pixel values. - -Version 3.37 - 3 June 2014 - - - replaced the random Gaussian and Poissonian distribution functions with - new code written by Craig Markwardt derived from public domain C++ functions - written by John D Cook. - - - patched fitsio2.h to support CFITSIO on AArch64 (64-bit ARM) - architecture (both big and little endian). Supplied by - Marcin Juszkiewicz and Sergio Pascual Ramirez, with further update - by Michel Normand. - - - fixed bug in fpackutil.c that caused fpack to exit prematurely if - the FZALGOR directive keyword was present in the HDU header. - -Version 3.36 - 6 December 2013 - - - added 9 Dec: small change to the fileseek function in drvrfile.c to - support large files > 2 GB when building CFITSIO with MinGW on Windows - - - reorganized the CFITSIO code directory structure; added a 'docs' - subdirectory for all the documentation, and a 'zlib' directory - for the zlib/gzip file compression code. - - - made major changes to the compression code for FITS binary table - to support all types of columns, including variable-length arrays. - This code is mainly used via the fpack and funpack programs. - - - increased the number of FITS files that can be opened as one - time to 1000, as defined by NMAXFILES in fitsio2.h. - - - made small configuration changes to configure.in, configure, - fitsio.h, and drvrfile.c to support large files (64-bit file - offsets} when using the mingw-w64 compiler (provided by - Benjamin Gilbert). - - - made small change to fits_delete_file to more completely ignore - any non-zero input status value. - - - fixed a logic error in a 'if' test when parsing a keyword name - in the ngp_keyword_is_write function in grparser.c (provided - by David Binderman). - - - when specifying the image compression parameters as part of the - compressed image file name (using the "[compress]" qualifier - after the name of the file), the quantization level value, if - specified, was not being recognized by the CFITSIO compression - routines. The image would always be compressed with the default - quantization level of 4.0, regardless of what was specified. This - affected the imcopy program, and potentially other user-generated - application programs that used this method to specify the - compression parameters. This bug did not affect fpack or - funpack. This was fixed in the imcomp_get_compressed_image_par - routine in the imcompress.c file. (reported by Sean Peters) - - - defined a new CFITS_API macro in fitsio.h which is used to export the - public symbols when building CFITSIO on Windows systems with CMake. This - works in conjunction with the new Windows CMake build procedure that - is described in the README.win32 file. This complete revamping of the - way CFITSIO is built under Windows now supports building 64-bit - versions of the library. Thanks to Daniel Kaneider (Luminance HDR - Team) for providing these new CMake build procedures. - - - modified the way that the low-level file_create routine works when - running in the Hera environment to ensure that the FITS file that is - created is within the allow user data disk area. - - - modified fits_get_compression_type so that it does not return an error - if the HDU is a normal FITS IMAGE extension, and is not a tile-compressed - image. - - - modified the low-level ffgcl* and ffpcl* routines to ensure that they - never try ro read or write more than 2**31 bytes from disk at one time, - as might happen with very large images, to avoid integer overflow errors. - Fix kindly provided by Fred Gutsche at NanoFocus AG (www.nanofocus.de). - - - modified Makefile.in so that doing 'make distclean' does not delete - new config.sub and config.guess files that were recently added. - - - adopted a patch from Debian in zcompress.c to "define" the values of - GZBUFSIZE and BUFFINCR, instead of exporting the symbols as 'int's. - -Version 3.35 - 26 June 2013 (1st beta release was on 24 May) - - - fixed problem with the default tile size when compressing images with - fpack using the Hcompress algorithm. - - - fixed returned value ("status" instead of "*status") - - - in imcompress.c, declared some arrays that are used to store the dimensions - of the image from 'int' to 'long', to support very large images (at least - on systems where sizeof(long) = 8), - - - modified the routines that convert a string value to a float or double - to prevent them from returning a NaN or Inf value if the - string is "NaN" or "Inf" (as can happen with gcc implementation of the - strtod function). - - - removed/replaced the use of the assert() functions when locking or - unlocking threads because they did not work correctly if NDEBUG is - defined. - - - made modifications to the way the command-line file filters are parsed to - 1) remove the 1024-character limit when specifying a column filter, - 2) fixed a potential character buffer-overflow risk in fits_get_token, and - 3) improved the parsing logic to remove any possible of confusing - 2 slash characters ("//") in the string as the beginning of a - comment string. - - - modified configure and Makefile.in so that when building CFITSIO - as a shared library on linux or Mac platforms, it will use the SONAME - convention to indicate whether each new release of the CFITSIO - library is binary-compatible with the previous version. Application - programs that link with the shared library will not need to be - recompiled as long as the versions are compatible. In practice, - this means that the shared library binary file that is created (on - Linux systems) will have a name like 'libcfitsio.so.I.J.K', where I is the - SONAME version number, J is the major CFITSIO version number (e.g. 3), - and K is the minor CFITSIO version number (e.g., 34). Two link - files will also be created such that - libcfitsio.so -> libcfitsio.so.I, and - libcfitsio.so.I -> libcfitsio.I.J.K - Application programs will still run correctly with the new version of - CFITSIO as long as the 'I' version number remains the same, but the - applications will fail to run if the 'I' number changes, thus alerting - the user that the application must be rebuilt. - - - fixed bug in fits_insert_col when computing the new table row width - when inserting a '1Q' variable length array column. - - - modified the image compression routines so that the output compressed - image (stored in a FITS binary table) uses the '1Q' variable length - array format (instead of '1P') when the input file is larger than 4 GB. - - - added support for "compression directive" keywords which indicate how - that HDU should be compressed (e.g., which compression algorithm to use, - what tiling pattern to use, etc.). The values of these keywords will - override the compression parameters that were specified on the command - line when running the fpack FITS file compression program. - - - globally changed the variable and/or subroutine name "dither_offset" - to "dither_seed" and "quantize_dither" to "quantize_method" so - that the names more accurately reflects their purpose. - - - added support for a new SUBTRACTIVE_DITHER_2 method when compressing - floating point images. The only difference with the previous method - is that pixels with a value exactly equal to 0.0 will not be dithered, - and instead will be exactly preserved when the image is compressed. - - - added support for an alias of "RICE_ONE" for "RICE_1" as the value - of the ZCMPTYPE keyword, which gives the name of the image compression - algorithm. This alias is used if the new SUBTRACTIVE_DITHER_2 option - is used, to prevent old versions of funpack from creating a corrupted - uncompressed image file. Only newer versions of funpack will recognize - this alias and be able to uncompress the image. - - - made performance improvement to fits_read_compressed_img so that - when reading a section of an compressed image that includes only - every nth pixel in some dimension, it will only uncompressed a tile - if there are actually any pixels of interest in that tile. - - - fixed several issues with the beta FITS binary table compression code - that is used by fpack: added support for zero-length vector columns, - made improvements to the output report when using the -T option in fpack, - changed the default table compression method to 'Rice' instead of - 'Best', and now writes the 'ZTILELEN' keyword to document the number - of table rows in each tile. - - - fixed error in ffbinit in calculating the total length of the binary - table extension if the THEAP keyword was used to override the - default starting location of the heap. - -Version 3.34 - 20 March 2013 - - - modified configure and configure.in to support cross-compiled cfitsio - as a static library for Windows on a Linux platform using MXE - (http://mxe.cc) - a build environment for mingw32. (contributed by - Niels Kristian Bech Jensen) - - - added conditional compilation statementsfor the mingw32 environment in - drvrfile.c because mingw32 does not include the ftello and fseeko functions. - (contributed by Niels Kristian Bech Jensen) - - - fixed a potential bug in ffcpcl (routine to copy a column from one table - to another table) when dealing with the rare case of a '0X' column (zero - length bit column). - - - fixed an issue in the routines that update or modify string-valued - keyword values, as a result of the change to ffc2s in the previous - release. These routines would exit with a 204 error status if the - current value of the keyword to be updated or modified is null. - - - fixed typo in the previous modification that was intended to ignore - numerical overflows in Hcompress when decompressing an image. - - - moved the 'startcol' static variable out of the ffgcnn routine and - instead added it as a member of the 'FITSfile' structure that is defined - in fitsio.h. This removes a possible race condition in ffgcnn in - multi-threaded environments. - -Version 3.33 - 14 Feb 2013 - - - modified the imcomp_decompress_tile routine to ignore any numerical - overflows that might occur when using Hcompress to decompress the - image. If Hcompress is used in its 'lossy' mode, the uncompressed - image pixel values may slightly exceed the range of an integer*2 - variable. This is generally of no consequence, so we can safely ignore - any overflows in this case and just clip the values to the legal range. - - - the default tiling pattern when writing a tile-compressed image - has been changed. The old behavior was to compress the whole image - as one single large tile. This is often not optimal when dealing - with large images, so the new default behavior is to treat each - row of the image as one tile. This is the same default behavior - as in the standalone fpack program. The default tile size can - be overridden by calling fits_set_tile_dim. - - - fixed bug that resulted in a corrupted output FITS image when - attempting to write a float or double array of values to a - tile-compressed integer data type image. CFITSIO does not support - implicit data type conversion in this case and now correctly - returns an appropriate error status. - - - modified ricecomp.c to define the nonzero_count lookup table as an - external variable, rather then dynamically allocating it within the - 3 routines that use it. This simplifies the code and eliminates the - need for special thread locking and unlocking statements. (Thanks to - Lars Kr. Lundin for this suggestion). - - - modified how the uncompressed size of a gzipped file is computed in the - mem_compress_open routine in drvrmem.c. Since gzip only uses 4 bytes - in the compressed file header to store the original file size, one may - need to apply a modulo 2^32 byte correction in some cases. The logic - here was modified to allow for corner cases (e.g., very small files, and - when running on 32-bit platforms that do not support files larger than - 2^31 bytes in size). - - - added new public routine to construct a 80 keyword record from the 3 input - component strings, i.e, the keyword name string, the value string, and - the comment string: fits_make_key/ffmkky. (This was already an undocumented - internal routine in previous versions of CFITSIO). - - - modified ffc2s so that if the input keyword value string is a null string, - then it will return a VALUE_UNDEFINED (204) status value. This makes it - consistent with the behavior when attempting to read a null keyword - (which has no value) as a logical or as a number (which also returns - the 204 error). This should only affect cases where the header keyword - does not have an equal sign followed by a space character in columns 9 - and 10 of the header record. - - - Changed the "char *" parameter declarations to "const char *" in many - of the routines (mainly the routines that modify or update keywords) to - avoid compiler warnings or errors from C++ programs that tend to be more - rigorous about using "const char *" when appropriate. - - - added support for caching uncompressed image tiles, so that the tile does - not need to be uncompressed again if the application program wants - to read more data from the same tile. This required changes to the - main FITS file structure that is defined in fitsio.h, as well as - changes to imcompress.c. - - - enhanced the previous modification to drvrfile.c to handle additional user - cases when running in the HEASARC's Hera environment. - -Version 3.32 - Oct 2012 - - - fixed flaw in the way logical columns (TFORM = 'L') in binary tables - were read which caused an illegal value of 1 in the column to be interpreted - as a 'T' (TRUE) value. - - - extended the column filtering syntax in the CFITSIO file name parser to - enable users and scripts to append new COMMENT or HISTORY keyword into the - header of the filtered file (provided by Craig Markwardt). For example, - fcopy "infile.fits[col #HISTORY='Processed on 2012-10-05']" outfile.fits - will append this header keyword: "HISTORY Processed on 2012-10-05" - - - small change to the code that opens and reads an ASCII region file to - return an error if the file is empty. - - - fixed obscure sign propagation error when attempting to read the - uncompressed size of a gzipped FITS file. This resulted in a memory - allocation error if the gzipped file had an uncompressed file - size between 2^31 and 2^32 bytes. Fix supplied by Gudlaugur Johannesson - (Stanford). - -Version 3.31 - 18 July 2012 - - - enhanced the CFITSIO column filtering syntax to allow the comma, in addition - to the semi-colon, to be used to separate clauses, for example: - [col X,Y;Z = max(X,Y)]. This was done because users are not allowed to - enter the semi-colon character in the on-line Hera data processing - system due to computer security concerns. - - - enhanced the CFITSIO extended filename syntax to allow specifying image - compression parameters (e.g. '[compress Rice]') when opening an existing - FITS file with write access. The specified compression parameters will - be used by default if more images are appended to the existing file. - - - modified drvrfile.c to do additional file security checks when CFITSIO - is running within the HEASARC's Hera software system. In this case - CFITSIO will not allow FITS files to be created outside of the user's - individual Hera data directory area. - - - fixed an issue in fpack and funpack on Windows machines, caused by - the fact that the 'rename' function behaves differently on Windows - in that it does not clobber an existing file, as it does on Unix - platforms. - - - fixed bug in the way byte-swapping was being performed when writing - integer*8 null values to an image or binary table column. - - - added the missing macro definition for fffree to fitsio.h. - - - modified the low level table read and write functions in getcol*.c and - putcol*.c to remove the 32-bit limitation on the number of elements. - These routines now support reading and writing more than 2**31 elements - at one time. Thanks to Keh-Cheng Chu (Stanford U.) for the patch. - - - modified Makefile.in so that the shared libcfitsio.so is linked against - pthreads and libm. - -Version 3.30 - 11 April 2012 - - Enhancements - - - Added new routine called fits_is_reentrant which returns 1 or 0 depending on - whether or not CFITSIO was compiled with the -D_REENTRANT directive. This can - be used to determine if it is safe to use CFITSIO in multi-threaded programs. - - - Implemented much faster byte-swapping algorithms in swapproc.c based on code - provided by Julian Taylor at ESO, Garching. These routines significantly - improve the FITS image read and write speed (by more than a factor of 2 in - some cases) on little-endian machines (e.g., Linux and Microsoft Windows and - Macs running on x86 CPUs) where byte-swapping is required when reading and - writing data in FITS files. This has no effect on big-endian machines - (e.g. Motorola CPUs and some IBM systems). Even faster byte-swapping - performance can be achieved in some cases by invoking the new "--enable-sse2" - or "--enable-ssse3" configure options when building CFITSIO on machines that - have CPUs and compilers that support the SSE2 and SSSE3 machine instructions. - - - added additional support for implicit data type conversion in cases where - the floating point image has been losslessly compressed with gzip. The - pixels in these compressed images can now be read back as arrays of short, - int, and long integers as well as single and double precision floating-point. - - - modified fitsio2.h and f77_wrap.h to recognize IBM System z mainframes by - testing if __s390x__ or __s390__ is defined. - - - small change to ffgcrd in getkey.c so that it supports reading a blank - keyword (e.g., a keyword whose name simply contains 8 space characters). - - Bug Fixes - - - fixed a bug in imcomp_decompress_tile that caused the tile-compressed image - to be uncompressed incorrectly (even though the tile-compressed image itself - was written correctly) under the following specific conditions: - - the original FITS image has a "float" datatype (R*4) - - one or more of the image tiles cannot be compressed using the standard - quantization method and instead are losslessly compressed with gzip - - the pixels in these tiles are not all equal to zero (this bug does - affect tiles where all the pixels are equal to zero) - - the program that is reading the compressed image uses CFITSIO's - "implicit datatype conversion" feature to read the "float" image - back into an array of "double" pixel values. - If all these conditions are met, then the returned pixel values in the - affected image tiles will be garbage, with values often ranging - up to 10**34. Note that this bug does not affect the fpack/funpack - programs, because funpack does not use CFITSIO's implicit datatype - conversion feature when uncompressing the image. - -Version 3.29 - 2 December 2011 - - Enhancements - - - modified Makefile.in to allow configure to override the lib and include - destination directories. - - - added (or restored actually) support for tile compression of 1-byte integer - images in imcomp_compress_tile. Support for that data type was overlooked - during recent updates to this routine. - - - modified the fits_get_token command-line parsing routine to perform more - rigorous checks to determine if the token can be interpreted as a number - or not. - - - made small modification to fpack.c to not allow the -i2f option (convert - image from integer to floating point) with the "-g -q 0" option (do lossless - gzip compression). It is more efficient to simply use the -g option alone. - - - made modifications to fitsio.h and drvrfile.c to support reading and - writing large FITS files (> 2.1 GB) when building CFITSIO using - Microsoft Visual C++ on Windows platforms. - - - added new WCS routine (ffgicsa) which returns the WCS keyword values - for a particular WCS version ('A' - 'Z'). - - Bug Fixes - - - fixed a problem with multi-threaded apps that open/close FITS files - simultaneously by putting mutex locks around the call to - fits_already_open and in fits_clear_Fptr. - - - fixed a bug when using the 'regfilter' function to select a subset of the - rows in a FITS table that have coordinates that lie within a specified - spatial region on the sky. This bug only affects the rarely used panda - (and epanda and bpanda) region shapes in which the region is defined by - the intersection of an annulus and a pie-shaped wedge. The previous code - (starting with version 3.181 of CFITSIO where support for the panda region - was first introduced) only worked correctly if the 2 angles that define - the wedge have values between -180 and +180. If not, then fewer rows than - expected may have been selected from the table. - - - fixed the extended filename parser so that when creating a histogram by - binning 2 table columns, if a keyword or column name is given as the - weighting factor, then the output histogram image will have a floating - point datatype, not the default integer datatype as is the case when no - weight is specified (e.g. with a filename like - "myfile.fits[bin x,y; weight_column]" - - - added fix to the code in imcompress.c to work around a problem with - dereferencing the value of a pointer, in cases where the address of - that pointer has not been defined (e.g., the nulval variable). - - - modified the byte shuffling algorithm in fits_shuffle_8bytes to work - around a strange bug in the proprietary SunStudioExpress C compiler - under OpenSolaris. - - - removed spurious messages on the CFITSIO error stack when opening a - FITS file with FTP (in drvrnet.c); - -Version 3.28 - 12 May 2011 - - - added an enhancement to the tiled-image compression method when compressing - floating-point image using the standard (lossy) quantization method. In - cases where an image tile cannot be quantized, The floating-point pixel values - will be losslessly compressed with gzip before writing them to the tile- - compressed file. Previously, the uncompressed pixel values would have - been written to the file, which obviously requires more disk space. - - - made significant internal changes to the structure of the tile compression - and uncompression routines in imcompress.c to make them more modular and - easier to maintain. - - - modified configure.in and configure to force it to build a Universal - binary on Mac OS X. - - - modified the ffiter function in putcol.c to properly clean up allocated - memory if an error occurs. - - - in quantize.c, when searching for the min and max values in a float array, - initialize the max value to -FLT_MAX instead of FLT_MIN (and similarly - for double array). - -Version 3.27 - 3 March 2011 - - Enhancements - - - added new routines fits_read_str and fits_delete_str which read or - delete, respectively, a header keyword record that contains a specified - character string. - - - added a new routine called fits_free_memory which frees the memory - that fits_read_key_longstr allocated for the long string keyword value. - - - enhanced the ffmkky routine in fitscore.c to not put a space before the - equals sign when writing long string-valued keywords using the ESO - HIERARCH keyword convention, if that extra character is needed to - fit the length of the keyword name + value string within the 80-character - FITS keyword record. - - - made small change to fits_translate_keyword to support translation of - blank keywords (where the name = 8 blank characters) - - - modified fpack so that it uses the minimum of the 2nd, 3rd, and 5th order - MAD noise values when quantizing and compressing a floating point image. - This is more conservative than just using the 3rd order MAD value alone. - - - added new routine imcomp_copy_prime2img to imcompress.c that is used by - funpack to copy any keywords that may have been added to the primary - array of the compressed image file (a null image) back into the header of - the uncompressed image. - - - enhanced the fits_quantize_float and fits_quantize_double routines in - quantize.c to also compress the tile if it is completely filled with - null values. Previously, this type of tile would have been written - to the output compressed image without any compression. - - - enhanced imcomp_decompress_tile to support implicit datatype conversion - when reading a losslessly compressed (with gzip) real*4 image into an - array of real*8 values. - - - in imcompress.c, removed possible attempt to free memory that had not - been allocated. - - -Version 3.26 - 30 December 2010 - - Enhancements - - - defined 2 new macros in fitsio.h: - #define CFITSIO_MAJOR 3 - #define CFITSIO_MINOR 26 - These may be used within other macros to detect the CFITSIO - version number at compile time. - - - modified group.c to initialize the output URL to a null string in - fits_url2relurl. Also added more robust tests to see if 2 file - pointers point to the same file. - - - enhanced the template keyword parsing code in grparser.c to support - the 'D' exponent character in the ASCII representation of floating - point keyword values (as in TVAL = 1.23D03). Previously, the parser - would have written this keyword with a string value (TVAL = '1.23D03'). - - - modified the low-level routines that write a keyword record to a FITS - header so that they silently replace any illegal characters (ASCII - values less than 32 or greater than 126) with an ASCII space character. - Previously, these routines would have returned with an error when - encountering these illegal characters in the keyword record (most commonly - tab, carriage return, and line feed characters). - - - made substantial internal changes to imcompress.c in preparation for - possible future support for compression methods for FITS tables analogous - to the tiled image compression method. - - - replaced all the source code in CFITSIO that was distributed under the - GNU General Public License with freely available code. In particular, - the gzip file compression and uncompression code was replaced by the - zlib compression library. Thus, beginning with this version 3.26 of CFITSIO, - other software applications may freely use CFITSIO without necessarily - incurring any GNU licensing requirement. See the License.txt file for - the CFITSIO licensing requirements. - - - added support for using cfitsio in different 'locales' which use a - comma, not a period, as the decimal point character in ASCII - representation of a floating point number (e.g., France). This - affects how floating point keyword values and floating point numbers - in ASCII tables are read and written with the 'printf' and 'strtod' - functions. - - - added a new utility routine called fits_copy_rows/ffcprw that copies - a specified range of rows from one table to another. - - - enhanced the test for illegal ASCII characters in a header (fftrec) to - print out the name of the offending character (e.g TAB or Line Feed) as - well as the Hex value of the character. - - - modified ffgtbc (in fitscore.c) to support nonstandard vector variable - length array columns in binary tables (e.g. with TFORMn = 2000PE(500)'). - - - modified the configure file to add "-lm" when linking CFITSIO on - Solaris machines. - - - added new routine, fits_get_inttype, to parse an integer keyword value - string and return the minimum integer datatype (TBYTE, TSHORT, TLONG, - TLONGLONG) required to store the integer value. - - - added new routine, fits_convert_hdr2str, which is similar to fits_hdr2str - except that if the input HDU is a tile compressed image (stored - in a binary table) then it will first convert that header back to - that of a normal uncompressed FITS image before concatenating the header - keyword records. - - - modified the file template reading routine (ngp_line_from_file in - grparser.c) so that it ignores any carriage return characters (\r) - in the line, that might be present, e.g. if the file was created on a - Windows machine that uses \r\n as end of line characters. - - - modified the ffoptplt routine in cfileio.c to check if the PCOUNT - keyword in the template file has a non-zero value, and if so, resets - it to zero in the newly created file. - - Bug Fixes - - - fixed a bug when uncompressing floating-point images that contain Nan - values on some 64-bit platforms. - - - fixed a bug when updating the value of the CRPIXn world coordinate - system keywords when extracting a subimage from larger FITS image, using the - extended CFITSIO syntax (e.g. myimage[1:500:2, 1:500:2]). This bug only - affects cases where the pixel increment value is not equal to 1, and caused - the coordinate grid to be shifted by between 0.25 pixels (in the case of - a pixel increment of 2) and 0.5 pixels (for large pixel increment values). - - - fixed a potential string buffer overflow error in the ffmkls routine - that modifies the value and comment strings in a keyword that uses - the HEASARC long string keyword convention. - - - fixed a bug in imcompress.c that could cause programs to abort on 64-bit - machines when using gzip to tile-compress images. Changed the declaration - of clen in imcomp_compress_tile from int to size_t. - -Version 3.25 - 9 June 2010 - - - fixed bug that was introduced in version 3.13 that broke the ability - to reverse an image section along the y-axis with an image section - specifier like this: myimage.fits[*,-*]. This bug caused the output - image to be filled with zeros. - - - fixed typo in the definition of the ftgprh Fortran wrapper routine - in f77_wrap3.c. - - - modified the cfitsio.pc.in configuration file to make the lib path - a variable instead of hard coding the path. The provides more - flexibility for projects such as suse and fedora when building CFITSIO. - - - fixed bug in imcomp_compress_tile in imcompress.c which caused - null pixel values to be written incorrectly in the rare case where - the floating-point tile of pixels could not be quantized into integers. - - - modified imcompress.c to add a new specialized routine to uncompress - an input image and then write it to a output image on a tile by tile basis. - This appears to be faster than the old method of uncompressing the - whole image into memory before writing it out. It also supports - large images with more than 2**31 pixels. - - - made trivial changes to 2 statements in drvrfile.c to suppress - nuisance compiler warnings. - - - some compilers define CLOCKS_PER_SEC as a double instead of an integer, - so added an explicit integer type conversion to 2 statements in - imcompress.c that used this macro. - - - removed debugging printf statements in drvrnet.c (15 July) - -Version 3.24 - 26 January 2010 - - - modified fits_translate_keywords so that it silently ignores any - illegal ASCII characters in the value or comment fields of the input - FITS file. Otherwise, fpack would abort without compressing input - files that contained this minor violation of the FITS rules. - - - added support for Super H cpu in fitsio2.h - - - updated funpack to correctly handle the -S option, and to use a - more robust algorithm for creating temporary output files. - - - modified the imcomp_compress_tile routine to support the NOCOMPRESS - debugging option for real*4 images. - -Version 3.23 - 7 January 2010 - - - reduced the default value for the floating point image quantization - parameter (q) from 16 to 4. This parameter is used when tile compressing - floating point images. This change will increase the average compression - ratio for floating point images from about 4.6 to about 6.5 without losing - any significant information in the image. - - - enhanced the template keyword parsing routine to reject a header - template string that only contains a sequence of dashes. - - - enhanced the ASCII region file reading routine to allow tabs as well - as spaces between fields in the file. - - - got rid of bogus error message when calling fits_update_key_longstr - - - Made the error message more explicit when CFITSIO tries to write - to a GZIP compressed file. Instead of just stating "cannot write - to a READONLY file", it will say "cannot write to a GZIP compressed - file". - -Version 3.22 - 28 October 2009 - - - added an option (in imcompress.c) to losslessly compress floating - point images, rather than using the default integer scaling method. - This option is almost never useful in practice for astronomical - images (because the amount of compression is so poor), but it has - been added for test comparison purposes. - - - enhanced the dithering option when quantizing and compressing - floating point images so that a random dithering starting point - is used, so that the same dithering pattern does not get used for - every image. - - - modified the architecture setup section of fitsio2.h to support the - 64-core 8x8-architecture Tile64 platform (thanks to Ken Mighell, NOAO) - - Fixes - - - fixed a problem that was introduced in version 3.13 of CFITSIO - in cases where a program writes it own END keyword to the header - instead of letting CFITSIO do it, as is strongly recommended. In - one case this caused CFITSIO to rewrite the END keyword and any - blank fill keywords in the header many times, causing a - noticeable slow-down in the FITS file writing speed. - -Version 3.21 - 24 September 2009 - - - fixed bug in cfileio.c that caused CFITSIO to crash with a bus error - on Mac OS X if CFITSIO was compiled with multi-threaded support (with - the --enable-reentrant configure option). The Mac requires an - additional thread initialization step that is not required on Linux - machines. Even with this fix, occasional bus errors have been seen on - some Mac platforms, The bus errors are seen when running the - thread_test.c program. The bus errors are very intermittent, and occur - less than about 1% of the time, on the affected platforms. - These bus errors have not been seen on Linux platforms. - - - fixed invalid C comment delimiter ("//*" should have been "/*") - in imcompress.c. - - - Increased the CFITSIO version number string length - in fpackutil.c, to fix problem on some platforms when running - fpack -V or funpack -V. Also modified the output format of the - fpack -L command. - -Version 3.20 - 31 August 2009 - - - modified configure.in and configure so that it will build the Fortran - interface routines by default, even if no Fortran compiler is found - in the user's path. Building the interface routines may be disabled - by specifying FC="none". This was done at the request of users who - obtained CFITSIO from some other standard linux distributions, where - CFITSIO was apparently built in an environment that had no Fortran - compiler and hence did not build the Fortran wrappers. - - - modified ffchdu (close HDU) so that it calls the routine to update - the maximum length of variable length table columns in the TFORM - values in all cases where the values may have changed. Previously - it would not update the values if a value was already specified in - the TFORM value. - - - added 2 new string manipulation functions to the CFITSIO parser - (contributed by Craig Markwardt): strmid extracts a substring - from a string, and strstr searches for a substring within a string. - - - removed the code in quantize.c that treated "floating-point integer" - images as a special case (it would just do a datatype conversion from - float to int, and not otherwise quantize the pixel values). This - caused complications with the new subtractive dithering feature. - - - enhanced the code for converting floating point images to quantized - scaled integer prior to tile-compressing them, to apply a random - subtractive dithering, which improves the photometric accuracy - of the compressed images. - - - added new internal routine, iraf_delete_file, for use by fpack to - delete a pair of IRAF format header and pixel files. - - - small change in cfileio.c in the way it recognizes an IRAF format - .imh file. Instead of just requiring that the filename contain the - ".imh" string, that string must occur at the end of the file name. - - - fixed bug in the code that is used when tile-compressing real*4 FITS - images, which quantizes the floating point pixel values into - integer levels. The bug would only appear in the fairly rare - circumstance of tile compressing a floating point image that contains - null pixels (NaNs) and only when using the lossy Hcompress algorithm - (with the s parameter not equal to 1). This could cause underflow of - low valued pixels, causing them to appear as very large pixel values - (e.g., > 10**30) in the compressed image - - - changed the "if defined" blocks in fitsio.h, fitsio2.h and f77_wrap.h - to correctly set the length of long variables on sparc64 machines. - Patch contributed by Matthew Truch (U. Penn). - - - modified the HTTP file access code in drvrnet.c to support basic - HTTP authentication, where the user supplies a user name and - password. The CFITSIO filename format in this case is: - "http://username:password@hostname/..." - Thanks to Jochen Liske (ESO) for the suggestion and the code. - -Version 3.181 (BETA) - 12 May 2009 - - - modified region.c and region.h to add support for additional - types of region shapes that are supported by ds9: panda, epanda, - and bpanda. - - - fixed compiler error when using the new _REENTRANT flag, having to - do with the an attempted static definition of Fitsio_Lock in - several source files, after declaring it to be non-static in fitsio2.h. - -Version 3.18 (BETA) - 10 April 2009 - - - Made extensive changes to make CFITSIO thread safe. Previously, - all opened FITS files shared a common pool of memory to store - the most recently read or written FITS records in the files. - In a multi-threaded environment different threads could - simultaneously read or write to this common area causing - unpredictable results. This was changed so that every opened - FITS file has its own private memory area for buffering the - file. Most of the changes were in buffers.c, fitsio.h, and - fitsio2.h. Additional changes were made to cfileio.c, mainly - to put locks around small sections of code when setting up the - low-level drivers to read or write the FITS file. Also, locks - were needed around the GZIP compression and uncompression code - in compress.c., the error message stack access routine in - fitscore.c, the encode and decode routines in fits_hcompress.c - and fits_hdecompress.c, in ricecomp.c, and the table row - selection and table calculator functions. Also, removed the - 'static' declaration of the local variables in pliocomp.c - which did not appeared to be required and prevented the - routines from being thread safe. - - As a consequence of having a separate memory buffer for every - FITS file (by default, about 115 kB per file), CFITSIO may now - allocate more memory than previously when an application - program opens multiple FITS files at once. The read and write - speed may also be slightly faster, since the buffers are not - shared between files. - - - Added new families of Fortran wrapper routines to read and - write values to large tables that have more than 2**31 rows. - The arguments that define the first row and first element to - read or write must be I*8 integers, not ordinary I*4 - integers. The names of these new routines have 'LL' appended - to them, so for example, ftgcvb becomes ftgcvbll. - - Fixes - - - Corrected an obscure bug in imcompress.c that would have incorrectly - written the null values only in the rare case of writing a signed - byte array that is then tile compressed using the Hcompress or PLIO - algorithm. - -Version 3.14 - 18 March 2009 - - Enhancements - - - modified the tiled-image compression and uncompression code to - support compressing unsigned 16-bit integer images with PLIO. - FITS unsigned integer arrays are offset by -32768, but the PLIO - algorithm does not work with negative integer values. In this - case, an offset of 32768 is added to the array before compression, - and then subtracted again when reading the compressed array. - IMPORTANT NOTE: This change is not backward compatible, so - these PLIO compressed unsigned 16-bit integer images will not be - read correctly by previous versions of CFITSIO; the pixel values - will have an offset of +32768. - - - minor changes to the fpack utility to print out more complete - version information with the -V option, and format the report - produced by the -T option more compactly. - - Fixes - - - Modified imcomp_compress_image (which is called by fpack) so that - it will preserve any null values (NaNs) if the input image has - a floating point datatype (BITPIX = -32 or -64). Null values in - integer datatype images are handled correctly. - - - Modified imcomp_copy_comp2img so that it does not copy the - ZBLANK keyword, if present, from the compressed image header - when uncompressing the image. - - - Fixed typo in the Fortran wrapper macro for the ftexist function. - -Version 3.13 - 5 January 2009 - - Enhancements - - - updated the typedef of LONGLONG in fitsio.h and cfortran.h to - support the Borland compiler which uses the __int64 data type. - - - added new feature to the extended filename syntax so that when - performing a filtering operation on specified HDU, if you add - a '#' character after the name or number of the HDU, then ONLY - that HDU (and the primary array if the HDU is a table) will be - copied into the filtered version of the file in memory. Otherwise, - by default CFITSIO copies all the HDUs from the input file into - memory. - - - when specifying a section, if the specified number of dimensions - is less than the number of dimensions in the image, then CFITSIO - will use the entire dimension, as if a '*' had been specified. - Thus [1:100] is equivalent to [1:100,*] when specifying a section - of 2 dimensional image. - - - modified fits_copy_image_section to read/write the section 1 row - at a time, instead of the whole section, to reduce memory usage. - - - added new stream:// drivers for reading/writing to stdin/stdout. - This driver is somewhat fragile, but for simple FITS read and - write operations this driver streams the FITS file on stdin - or stdout without first copying the entire file in memory, as is - done when specifying the file name as "-". - - - slight modification to ffcopy to make sure that the END keyword - is correctly written before copying the data. This is required - by the new stream driver. - - - modified ffgcprll, so that when writing data to an HDU, it first - checks that the END keyword has been written to the correct place. - This is required by the new stream driver. - - Fixes - - - fixed bug in ffgcls2 when reading an ASCII string column in binary - tables in cases where the width of the column is greater than 2880 - characters and when reading more than 1 row at a time. Similar - change was made to ffpcls to fix same problem with writing to - columns wider than 2880 characters. - - - updated the source files listed in makepc.bat so that it can be - used to build CFITSIO with the Borland C++ compiler. - - - fixed overflow error in ffiblk that could cause writing to Large Files - (> 2.1 GB) to fail with an error status. - - - fixed a bug in the spatial region code (region.c) with the annulus - region. This bug only affected specialized applications which - directly use the internal region structure; it does not affect - any CFITSIO functions directly. - - - fixed memory corruption bug in region.c that was triggered if the - region file contained a large number of excluded regions. - - - got rid of a harmless error message that would appear if filtering - a FITS table with a GTI file that has zero rows. (eval_f.c) - - - modified fits_read_rgnfile so that it removes the error messages - from the error stack if it is unable to open the region file as - a FITS file. (region.c) - -Version 3.12 - 8 October 2008 - - - modified the histogramming code so that the first pixel in the binned - array is chosen as the reference pixel by default, if no other - value is previously defined. - - - modified ffitab and ffibin to allow a null pointer to the - EXTNAME string, when inserting a table with no name. - -Version 3.11 - 19 September 2008 - - - optimized the code when tile compressing real*4 images (which get - scaled to integers). This produced a modest speed increase. For - best performance, one must specify the absolute q quantization - parameter, rather than relative to the noise in the tile (which - is expensive to compute). - - - modified the FITS region file reading code to check for NaN values, - which signify the end of the array of points in a polygon region. - - - removed the test for LONGSIZE == 64 from fitsio.h, since it may - not be defined. - - - modified imcompress.c to support unconventional floating point FITS - images that also have BSCALE and BZERO keywords. The compressed - floating point images are linearly scaled twice in this case. - -Version 3.10 - 20 August 2008 - - - fixed a number of cases, mainly dealing with long input file names - (> 1024 char), where unsafe usage of strcat and strcpy could have caused - buffer overflows. These buffer overflows could cause the application - to crash, and at least theoretically, could be exploited by a - malicious user to execute arbitrary code. There are no known instances - of this type of malicious attack on CFITSIO applications, and the - likelihood of such an attack seems remote. None the less, it would - be prudent for CFITSIO users to upgrade to this new version to guard - against this possibility. - - - modified some of the routines to define input character string - parameters as "const char *" rather than just "char *" to eliminate - some compiler warnings when the calling routine passes a constant - string to the CFITSIO routine. Most of the changes were to the - keyword name argument in the many routines that read or write keywords. - - - fixed bug when tile-compressing a FITS image which caused all the - completely blank keywords in the input header to be deleted from - the output compressed image. Also added a feature to preserve any - empty FITS blocks in the header (reserved space for future keywords) - when compressing or uncompressing an image. - - - fixed small bug in the way the default tile size is set in imcompress.c. - (Fix sent in by Paul Price). - - - added support for reading FITS format region files (in addition - to the ASCII format that was previously supported). Thanks to - Keith Arnaud for modifying region.c to do this. - -Version 3.09 - 12 June 2008 - - - fixed bug in the calculator function, parse_data, that evaluates - expressions then selecting rows or modifying values in table columns. - This bug only appeared in unusual circumstances - where the calculated value has a null value (= TNULLn). The bug - could cause elements to not be flagged as having a null value, or - in rare cases could cause valid elements to be flagged as null. This - only appears to have affected 64-bit platforms (where size(long) = 8). - - - fixed typo in imcomp_decompress_tile: call to fffi2r8 should have - been to fffi4r8. - - - in the imcopy_copy_comp2img routine, moved the call to - fits_translate_keywords outside of the 'if' statement. This could - affect reading compressed images that did not have a EXTNAME keyword - in the header. - - - fixed imcomp_compress_tile in imcompress.c to properly support - writing unsigned integers, in place, to tile compressed images. - - - modified fits_read_compressed_img so that if the calling routine - specifies nullval = 0, then it will not check for null-valued - pixels in the compressed FITS image. This mimics the same - behavior when reading normal uncompressed FITS images. - -Version 3.08 - 15 April 2008 - - - fixed backwards compatibility issue when uncompressing a Rice - compressed image that was created with previous versions of - CFITSIO (this late fix was added on May 18). - - - small change to cfortran.h to add "extern" to the common block - definition. This was done for compatibility with the version - of cfortran.h that is distributed by the Debian project. - - - relaxed the requirement that a string valued keyword must have a - closing quote character. If the quote is missing, CFITSIO will silently - append a quote at the end of the keyword record. This change was made - because otherwise it is very difficult to correct the keyword - because CFITSIO would exit with an error before making the fix. - - - added a new BYTEPIX compression parameter when tile-compressing - images with the Rice algorithm. - - - cached the NAXIS and NAXISn keyword values in the fitsio structure - for efficiency, to eliminate duplicates reads of these keywords. - - - added variants of the Rice compression and uncompression routines to - support short int images (in addition to the routines that support int). - - - moved the definition of LONGLONG_MIN and LONGLONG_MAX from fitsio2.h - to fitsio.h, to make it accessible to application programs. - - - make efficiency improvements to fitscore.c, to avoid needless searches - through the entire header when reading the required keywords that must - be near the beginning of the header. - - - made several improvements to getcol.c to optimize reading of compressed - and uncompressed images. - - - changed the compression level in the gzip code from 6 to 1. In most - cases this will provide nearly the same amount of compression, but is - significantly faster in some cases. - - - added new "helper routines' to imcompress.c to allow applications to - specified the "quantize level" and Hcompress scaling and smoothing - parameters - - - modified the extended filename syntax to support the "quantize level" - and Hcompress scaling and smoothing parameters. The parser in - cfileio.c was extensively modified. - - - extensive changes to quantize.c: - - replace the "nbits" parameter with "quantize level" - - the quantize level is now relative to the RMS noise in the image - - the HCOMPRESS scale factor is now relative to the RMS noise - - added routines to calculate RMS noise in image - (these changes require a change to the main file structure in fitsio.h) - - - initialize errno = 0 before the call to strtol in ffext, in case errno - has previously been set by an unrelated error condition. - - - added the corresponding long name for the ffgkyjj routine to longnam.h. - - - changed imcomp_copy_comp2img (in imcompress.c) to not require the - presence of the EXTNAME keyword in the input compressed image header. - - - modified imcompress.c to only write the UNCOMPRESSED_DATA column - in tile-compressed images if it is actually needed. This eliminates - the need to subsequently delete the column if it is not used - (which is almost always the case). - - - found that it is necessary to seek to the EOF of a file after - truncating the size of the file, to reestablish a definite - current location in the file. The required small changes to 3 - routines: file_truncate (to seek to EOF) and fftrun (to set io_pos) - and the truncation routine in drvrmem.c. - - - improved the efficiency when compressing integer images with - gzip. Previously, the image was always represented using integer*4 - pixels, which were then compressed. Now, if the range of pixel - values can be represented with integer*2 pixels or integer*1 pixels, - then that is used. This change is backward compatible with any - compressed images that used the previous method. - - - changed the default tiling pattern when using Hcompress from - large squares (200 to 600 pixels wide) to 16 rows of the image. - This generally requires less memory, compresses faster, and is more - consistent with the default row by row tiling when using the other - compression methods. - - - modified imcomp_init_table in imcompress.c to enforce a restriction - when using the Hcompress algorithm that the 1st 2 dimensions of sll - image tiles must be at least 4 pixels long. Hcompress becomes very - inefficient for smaller dimensions, and does not work at all with - 1D images. - - - fixed bug in the Hcompress compression algorithm that could affect - compression of I*4 images, using non-square compression tiles - (in the encode64 routine). - -Version 3.07 - 6 December 2007 (internal release) - - - fixed bug with the PLIO image compression routine which silently - produced a corrupted compressed image if the uncompressed image pixels - were not all in the range 0 to 2**24. (fixed in November) - - - fixed several 'for' loops in imcompress.c which were exceeding the - bounds of an array by 1. (fixed in November) - - - fixed a possible, but unlikely, memory overflow issue in iraffits.c. - - - added a clarification to the cfortran.doc file that cfortran.h - may be used and distributed under the terms of the GNU Library - General Public License. - - - fixed bug in the fits_modify_vector_len routine when modifying - the vector length of a 'X' bit column. - -Version 3.06 - 27 August 2007 - - - modified the imcopy.c utility program (to tile-compress images) - so that it writes the default EXTNAME = 'COMPRESSED_IMAGE' - keyword in the compressed images, to preserve the behavior of - earlier versions of imcopy. - - - modified the angsep function in the FITS calculator (in eval.y) - to use haversines, instead of the 'law of cosines', to provide - more precision at small angles (< 0.1 arcsec). - -Version 3.05 - July 2007 (internal release only) - - - extensive changes to imcompress.c to fully support implicit data - type conversion when reading and writing arrays of data to FITS - images, where the data type of the array is not the same as the - data type of the FITS image. This includes support for null pixels, - and data scaling via the BSCALE and BZERO keywords. - - - rewrote the fits_read_tbl_coord routine in wcssub.c, that gets the - standard set of WCS keywords appropriate to a pair of columns in a - table, to better support the full set of officially approved WCS keywords. - - - made significant changes to histo.c, which creates an image by binning - columns of a table, to better translate the WCS keywords in the table - header into the WCS keywords that are appropriate for an image HDU. - - - modified imcompress.c so that when pixels are written to a - tile-compressed image, the appropriate BSCALE and BZERO values of - that image are applied. This fixes a bug in which writing to - an unsigned integer datatype image (with BZERO = 32768) was not - done correctly. - -Version 3.04 - 3 April 2007 - - - The various table calculator routines (fits_select_rows, etc.) implicitly - assumed that the input table has not been modified immediately prior to - the call. To cover cases where the table has been modified a call to - ffrdef has been added to ffprs. IN UNUSUAL CASES THIS CHANGE COULD - CAUSE CFITSIO TO BEHAVE DIFFERENTLY THAN IN PREVIOUS VERSIONS. For - example, opening a FITS table with this column-editing virtual file - expression: - myfile.fits[3][col A==X; B = sqrt(X)] - no longer works, because the X column does not exist when the - sqrt expression is evaluated. The correct expression in this case is - myfile.fits[3][col A==X; B = sqrt(A)] - - - modified putkey.c to support USHORT_IMG when calling fits_create_img - to create a signed byte datatype image. - - - enhanced the column histogramming function to propagate any TCn_k and - TPn_k keywords in the table header to the corresponding CDi_j and PCi_j - keywords in the image header. - - - enhanced the random, randomn, and randomp functions in the lexical - parser to take a vector column name argument to specify the length - of the vector of random numbers that should be generated (provided by - Craig Markwardt, GSFC) - - - enhanced the ffmcrd routine (to modify an existing header card) to - support long string keywords so that any CONTINUE keywords associated - with the previous keyword will be deleted. - - - modified the ffgtbp routine to recognize the TDIMn keyword for - ASCII string columns in a binary table. The first dimension is - taken to be the size of a unit string. (The TFORMn = 'rAw' - syntax may also be used to specify the unit string size). - - - in fits_img_decompress, the fits_get_img_param function was called - with an invalid dimension size, which caused a fatal error on at - least 1 platform. - - - in ffopentest, set the status value before returning in case of error. - - - in the drvrnet.c file, the string terminators needed to be changed - from "\n" to "\r\n" to support the strict interpretation of the - http and ftp standard that is enforced by some newer web servers. - -Version 3.03 - 11 December 2006 - - New Routine - - - fits_write_hdu writes the current HDU to a FILE stream (e.g. stdout). - - Changes - - - modified the region parsing code to support region files where the - keyword "physical" is on a separate line preceding the region shape - token. (However, "physical" coordinates are not fully supported, and - are treated identically to "image" coordinates). - - - enhanced the iterator routines to support calculations on 64-bit - integer columns and images. Currently, the values are cast to - double precision when doing the calculations, which can cause a - loss of precision for integer values greater than about 2**52. - - - added support for accessing FITS files on the computational grid. - Giuliano Taffoni and Andrea Barisani, at INAF, University of Trieste, - Italy, implemented the necessary I/O driver routines in drvrgsiftp.c. - - - modified the tiled image compression/uncompression routines to - preserve/restore the original CHECKSUM and DATASUM keywords if they - exist. (saved as ZHECKSUM and ZDATASUM in the compressed image) - - - split fits_select_image_section into 2 routines: a higher level routine - that creates the output file and copies other HDUs from the input file - to the output file, and a lower level routine that extracts the image - section from the input image into an output image HDU. - - - Improved the error messages that get generated if one tries to - use the lexical parser to perform calculations on variable-length - array columns. - - - added "#define MACHINE NATIVE" in fitsio2.h for all machines where - BYTESWAPPED == FALSE. This may improve the file writing performance - by eliminating the need to allocate a temporary buffer in some cases. - - - modified the configure.in and configure script to fix problems with - testing if network services are available, which affects the definition - of the HAVE_NET_SERVICES flag. - - - added explicit type casting to all malloc statements, and deleted - declarations of unreferenced variables in the image compression code - to suppress compiler warnings. - - - fixed incorrect logic in fitsio2.h in the way it determined if numerical - values are byteswapped or not on MIPS and ARM architectures. - - - added __BORLANDC__ to the list of environments in fitsio.h that don't - use %lld in printf for longlong integers - - - added "#if defined(unix)" around "#include " statements in - several C source files, to make them compatible with Windows. - - -Version 3.02 - 18 Sept 2006 - - - applied the security patch to the gzip code, available at - http://security.FreeBSD.org/patches/SA-06:21/gzip.patch - The insufficient bounds checks in buffer use can cause gzip to crash, - and may permit the execution of arbitrary code. The NULL pointer - deference can cause gzip to crash. The infinite loop can cause a - Denial-of-Service situation where gzip uses all available CPU time. - - - added HCOMPRESS as one of the compression algorithm options in the - tiled image compression code. (code provided by Richard White (STScI)) - Made other improvements to preserve the exact header structure in the - compressed image file so that the compressed-and-then-uncompressed FITS - image will be as identical as possible to the original FITS image file. - - New Routines - - - the following new routines were added to support reading and writing - non-standard extension types: - fits_write_exthdr - write required keywords for a conforming extension - fits_write_ext - write data to the extension - fits_read_ext - read data from the extension - - - added new routines to compute the RMS noise in the background pixels - of an image: fits_rms_float and fits_rms_short (take an input - array of floats or shorts, respectively). - - Fixes - - - added the missing 64-bit integer case to set of "if (datatype)" - statements in the routine that returns information about a - particular column (ffgbclll). - - - fixed a parsing error in ffexts in cases where an extension number - is followed by a semi-colon and then the column and row number of an - array in a binary table. Also removed an extraneous HISTORY keyword - that was being written when specifying an input image in a table cel. - - - modified the routine that reads a table column returning a string - value (ffgcls) so that if the displayed numerical value is too - wide to fit in the specified length string, then it will return - a string of "*" characters instead of the number string. - - - small change to fitsio.h to support a particular Fortran and C - compiler combination on a SGI Altix system - - - added a test in the gunzip code to prevent seg. fault when trying - to uncompress a corrupted file (at least in some cases). - - - fixed a rarely-occurring bug in the routine that copies a table - cell into an image; had to call the ffflsh call a few lines earlier. - -Version 3.01 - (in FTOOLS 6.1 release) - - - modified fits_copy_image2cell to correctly copy all the appropriate - header keywords when copying an image into a table cell - - - in eval.y, explicitly included the code for the lgamma function - instead of assuming it is available in a system library (e.g., the - lgamma function is currently not included in MS Visual++ libraries) - - - modified the logic in fits_pixel_filter so that the default data - type of the output image will be promoted to at least BITPIX = -32 - (a single precision floating point) if the expression that is being - evaluated resolves to a floating point result. If the expression - resolves to an integer result, the output image will have the same - BITPIX as the input image. - - - in fits_copy_cell2image, added 5 more WCS keywords to the list of - keywords related to other columns that should be deleted in the - output image header. - - - disabled code in cfileio.c that would write HISTORY keywords to the - output file in fits_copy_image2cell and cell2image, because some tasks - would not want these extraneous HISTORY keywords. - - - added 2 new random number functions to the CFITSIO parser - RANDOMN() - produces a normal deviate (mean=0, stddev=1) - RANDOMP(X) - produces a Poisson deviate for an expected # of counts X - - - in f77_wrap.h, removed the restriction that "g77Fortran" must be - defined on 64-bit Itanium machines before assuming that - sizeof(long) = 8. It appears that "long"s are always - 8 bytes long on this machine, regardless of what compilers are used. - - - added test in fitsio.h so that LONGLONG cannot be multiply defined - - - modified longnam.h so that both "fits_write_nulrows" and - "fits_write_nullrows" get replace by the string "ffprwu". This - fixes a documentation error regarding the long name of this - routine. - - Bug fixes - - - fixed a potential null character string dereferencing error in the - the ffphtb and ffphbn routines that write the FITS table keywords. - This concerned the optional TUNITn keywords. - - - fixed a few issues in fits_copy_cell2image and fits_copy_image2cell - related to converting some WCS keyword between the image extension - form and the table cell form of the keyword. (cfileio.c) - - - fixed bug in fits_translate_keyword (fitscore.c) that, e.g., caused - 'EQUINOX' to be translated to EQUINOXA' if the pattern is 'EQUINOXa' - - - fixed 2 bugs that could affect 'tile compressed' floating point - images that contain NaN pixels (null pixels). First, the - ZBLANK keyword was not being written, and second, an integer - overflow could occur when computing the BZERO offset in the - compressed array. (quantize.c and imcompress.c) - -Version 3.006 - 20 February 2006 -(first full release of v3) - - - enhanced the 'col' extended filename syntax to support keyword name - expressions like - [col error=sqrt(rate); #TUNIT# = 'counts/s'], - in which the trailing '#' will be replaced by the column number - of the most recently referenced column. - - - fixed bug in the parse_data iterator work function that caused it - to fail to return a value of -1 in cases where only a selected - set of rows were to be processed. (affected Fv) - - - added code to fitsio.h and cfortran.h to typedef LONGLONG to - the appropriate 8-byte integer data type. Most compilers now - support the 'long long' data type, but older MS Visual C++ - compilers used '__int64' instead. - - - made several small changes based on testing by Martin Reinecke: - o in eval.y, change 'int undef' to 'long undef' - o in getcold.c and getcole.c, fixed a couple format conversion - specifiers when displaying the value of long long variables. - o in fitsio.h, modified the definition of USE_LL_SUFFIX in the - case of Athon64 machines. - o in fitsio2.h, defined BYTESWAPPED in the case of SGI machines. - o in group.c, added 'include unistd.h' to get rid of compiler warning. - -Version 3.005 - 20 December 2005 (beta) - - - cfortran.h has been enhanced to support 64-bit integer parameters - when calling C routines from Fortran. This modification was kindly - provided by Martin Reinecke (MPE, Garching). - - - Many new Fortran wrapper routines have been added to support reading - and writing 64-bit integer values in FITS files. These new routines - are documented in the updated version of the 'FITSIO User's Guide' - for Fortran programmers. - - - fixed a problem in the fits_get_keyclass routine that caused it - to not recognize the special COMMENT keywords at the beginning - of most FITS files that defines the FITS format. - - - added a new check to the ffifile routine that parses the - input extended file name, to distinguish between a FITS extension - name that begins with 'pix', and a pixel filtering operator that - begins with the 'pix' keyword. - - - small change to the WCSLIB interface routine, fits_read_wcstab, to - be more permissive in allowing the TDIMn keyword to be omitted for - degenerate coordinate array. - -Version 3.004 - 16 September 2005 (3rd public beta release) - - - a major enhancement to the CFITSIO virtual file parser was provided - by Robert Wiegand (GSFC). One can now specify filtering operations - that will be applied on the fly to the pixel values in a FITS image. - For example [pix sqrt(X)] will create a virtual FITS image where the - pixel values are the square root of the input image pixels. - - - modified region.c so that it interprets the position angles of regions - in a SAO style region file in the same way as DS9. In particular, if - the region parameters are given in WCS units, then the position angle - should be relative to the WCS coordinates of the image (increasing CCW - from West) instead of relative to the X/Y pixel coordinate system. - This only affects rotated images (e.g. with non-zero CROTA2 keyword) - with elliptical or rectangular regions. - - - cleaned up fitsio.h and fitsio2.h to make the definition of LONGLONG - and BYTESWAPPED and MACHINE more logical. - - - removed HAVE_LONGLONG everywhere since it is no longer needed (the - compiler now must have an 8-byte integer datatype to build CFITSIO). - - - added support for the 64-bit IBM AIX platform - - - modified eval.y so that the circle, ellipse, box, and near functions - can operate on vectors as well as scalars. This allows region filtering - on images that are stored in a vector cell in a binary table. - (provided by Craig Markwardt, GSFC) - - New Routines - - - added new fits_read_wcstab routine that serves as an interface to - Mark Calabretta's wcslib library for reading WCS information when - the -TAB table lookup convention is used in the FITS file. - - - added new fits_write_nullrows routine, which writes null values into - every column of a specified range of rows in a FITS table. - - - added the fits_translate_keyword and fits_translate_keywords utility - routines for converting the names of keywords when moving columns and - images around. - - - added fits_copy_cell2image and fits_copy_image2cell routines for - copying an image extension (or primary array) to or from a cell - in a binary table vector column. - - Bug fixes - - - fixed a memory leak in eval.y; was fixed by changing a call to malloc - to cmalloc instead. - - - changed the definition of several global variables at the beginning - of buffers.c to make them 'static' and thus invisible to applications - programs. - - - in fits_copy_image_cell, added a call to flush the internal buffers - before reading from the file, in case any records had been modified. - -Version 3.003 - 28 July 2005 - 2nd public beta release (used in HEASOFT) - - Enhancements - - - enhanced the string column reading routing fits_get_col_str to - support cases where the user enters a null pointer (rather than - a null string) as the nulval parameter. - - - modified the low level ffread and ffwrite routines that physically - read and write data from the FITS file so that they write the name - of the file to the CFITSIO error stack if an error occurs. - - - changed the definition of fits_open_file into a macro that will test - that the version of the fitsio.h include file that was used to - build the CFITSIO library is the same version as included when - compiling the application program. - - - made a simple modification to region.c to support regions files - of type "linear", for compatibility with ds9 and fv. - - - modified the internal ffgpr routine (and renamed it ffgprll) so - that it returns the TNULL value as a LONGLONG parameter instead - of 'long'. - - - in fits_get_col_display_width, added support for TFORM = 'k' - - - modified fitsio.h, fitsio2.h, and f77_wrap.h to add test for (_SX) - to identify NEC SX supercomputers. - - - modified eval_f.c to treat table columns of TULONG (unsigned long) - as a double. Also added support for TLONGLONG (8-byte integers) as - a double, which is only a temporary fix, since doubles only have about - 52 bits of precision. - - - changed the 'blank' parameter in the internal ffgphd function to - to type LONGLONG to support integer*8 FITS images. - - - when reading the TNULL keyword value, now use ffc2jj instead of - ffc2ii, to support integer*8 values. - - Bug fixes - - - fixed a significant bug when writing character strings to a variable - length array column of a binary table. This bug would result in some - unused space in the variable length heap, making the heap somewhat - larger than necessary. This in itself is usually a minor issue, since - the FITS files are perfectly valid, and other software should have - no problems reading back the characters strings. In some cases, however, - this problem could cause the program that is writing the table - to exit with a status = 108 disk read error. - - - modified the standalone imcopy.c utility program to fix a memory allocation - bug when running on 64-bit platforms where sizeof(long) = 8 bytes. - - - added an immediate 'return' statement to ffgtcl if the input status >0, - to prevent a segfault on some platforms. - -Version 3.002 - 15 April 2005 - first public beta release - - - in drvrfile.c, if it fails to open the file for some reason, then - it should reset file_outfile to a null string, to avoid errors on - a subsequent call to open a file. - - - updated fits_get_keyclass to recognize most of the WCS keywords - defined in the WCS Papers I and II. - -Version 3.001 - 15 March 2005 - released with HEASOFT 6.0 - - - numerous minor changes to the code to get rid of compiler warning - messages, mainly dealing with numerical data type casting and the - subsequent possible loss of precision in the result. - -Version 3.000 - 1 March 2005 (internal beta release) - - Enhancements: - - - Made major changes to many of the CFITSIO routines to more generally - support Large Files (> 2.1 GB). These changes are intended to - be 100% backward compatible with software that used the previous - versions of CFITSIO. The datatype of many of the integer parameters - in the CFITSIO functions has been changed from 'long' to 'LONGLONG', - which is typedef'ed to be equivalent to an 8-byte integer datatype on - each platform. With these changes, CFITSIO supports the following: - - integer FITS keywords with absolute values > 2**31 - - FITS files with total sizes > 2**31 bytes - - FITS tables in which the number of rows, the row width, or - the size of the heap is > 2**31 bytes - - FITS images with dimensions > 2**31 bytes (support is still - somewhat limited, with full support to be added later). - - - added another lexical parser function (thanks to Craig Markwardt, - GSFC): angsep computes the angular separation between 2 positions - on the celestial sphere. - - - modified the image subset extraction code (e.g., when specifying - an image subregion when opening the file, such as - 'myimage.fits[21:40, 81:90]') so that in addition to - updating the values of the primary WCS keywords CRPIXk, CDELTi, and - CDj_i in the extracted/binned image, it also looks for and updates - any secondary WCS keywords (e.g., 'CRPIX1P'). - - - made cosmetic change to group.c, so that when a group table is - copied, any extra columns will be appended after the last existing - column, instead of being inserted before the last column. - - - modified the routines that read tile compressed images to support - NULL as the input value for the 'anynul' parameter (meaning the - calling program does not want the value of 'anynul' returned to it). - - - when constructing or parsing a year/month/day character string, - (e.g, when writing the DATE keyword) the routines now rigorously - verify that the input day value is valid for the given month - (including leap years). - - - added some checks in cfileio.c to detect if some vital parameters - that are stored in memory have been corrupted. This can occur if - a user's program writes to areas of memory that it did not allocate. - - - added the wcsutil_alternate.c source code file which contains - non-working stubs for the 2 Classic AIPS world coordinate - conversion routines that are distributed under the GNU General - Public License. Users who are unwilling or unable to distribute - their software under the General Public License may use this - alternate source file which has no GPL restrictions, instead - of wcsutil.c. This will have no effect on programs that use - CFITSIO as long as they do not call the fits_pix_to_world/ffwldp - or fits_world_to_pix/ffxypx routines. - - Bug Fixes - - - in ffdtdm (which parses the TDIMn keyword value), the check for - consistency between the length of the array defined by TDIMn and - the size of the TFORMn repeat value, is now not performed for variable - length array columns (which always have repeat = 1). - - - fixed byteswapping problem when writing null values to non-standard - long integer FITS images with BITPIX = 64 and FITS table columns with - TFORMn = 'K'. - - - fixed buffer overflow problem in fits_parse_template/ffgthd that - occurred only if the input template keyword value string was much - longer than can fit in an 80-char header record. - -Version 2.510 - 2 December 2004 - - New Routines: - - - added fits_open_diskfile and fits_create_diskfile routines that simply - open or create a FITS file with a specified name. CFITSIO does not - try to parse the name using the extended filename syntax. - - - 2 new C functions, CFITS2Unit and CUnit2FITS, were added to convert - between the C fitsfile pointer value and the Fortran unit number. - These functions may be useful in mixed language C and Fortran programs. - - Enhancements: - - - added the ability to recognize and open a compressed FITS file - (compressed with gzip or unix compress) on the stdin standard input - stream. - - - Craig Markwardt (GSFC) provided 2 more lexical parser functions: - accum(x) and seqdiff(x) that compute the cumulative sum and the - sequential difference of the values of x. - - - modified putcole.c and putcold.c so that when writing arrays of - pixels to the FITS image or column that contain null values, and - there are also numerical overflows when converting some of the - non-null values to the FITS values, CFITSIO will now ignore the - overflow error until after all the data have been written. Previously, - in some circumstances CFITSIO would have simply stopped writing any - data after the first overflow error. - - - modified fitsio2.h to try to eliminate compiler warning messages - on some platforms about the use of 'long long' constants when - defining the value of LONGLONG_MAX (whether to use L or LL - suffix). - - - modified region.c to support 'physical' regions in addition to - 'image', 'fk4', etc. - - - modified ffiurl (input filename parsing routine) to increase the - maximum allowed extension number that can be specified from 9999 - to 99999 (e.g. 'myfile.fits+99999') - - Bug Fixes: - - - added check to fits_create_template to force it to start with - the primary array in the template file, in case an extension - number was specified as part of the template FITS file name. - -Version 2.500 - 28 & 30 July 2004 - - New Routine: - - - fits_file_exists tests whether the specified input file, or a - compressed version of the file, exists on disk. - - Enhancements: - - - modified the way CFITSIO reads and writes data in COMPLEX ('C') and - DBLCOMPLEX 'M' columns. Now, in all cases, when referring to the - number of elements in the vector, or the value of the offset to a - particular element within the vector, CFITSIO considers each pair of - numbers (the imaginary and real parts) as a single element instead of - treating each single number as an element. In particular, this changes - the behavior of fits_write_col_null when writing to complex columns. - It also changes the length of the 'nullarray' vector in the - fits_read_colnull routine; it is now only 1/2 as long as before. - Each element of the nullarray is set = 1 if either the real or - imaginary parts of the corresponding complex value have a null - value.(this change was added to version 2.500 on 30 July). - - - Craig Markwardt, at GSFC, provided a number of significant enhancements - to the CFITSIO lexical parser that is used to evaluate expressions: - - - the parser now can operate on bit columns ('X') in a similar - way as for other numeric columns (e.g., 'B' or 'I' columns) - - - range checking has been implemented, so that the following - conditions return a Null value, rather than returning an error: - divide by zero, sqrt(negative), arccos(>1), arcsin(>1), - log(negative), log10(negative) - - - new vector functions: MEDIAN, AVERAGE, STDDEV, and - NVALID (returns the number of non-null values in the vector) - - - all the new functions (and SUM, MIN and MAX) ignore null values - - - modified the iterator to support variable-length array columns - - - modified configure to support AIX systems that have flock in a non- - standard location. - - - modified configure to remove the -D_FILE_OFFSET_BITS flag when running - on Mac Darwin systems. This caused conflicts with the Fortran - wrappers, and should only be needed in any case when using CFITSIO - to read/write FITS files greater than 2.1 GB in size. - - - modified fitsio2.h to support compilers that define LONG_LONG_MAX. - - - modified ffrsim (resize an existing image) so that it supports changing - the datatype to an unsigned integer image using the USHORT_IMG and - ULONG_IMG definitions. - - - modified the disk file driver (drvrfile.c) so that if an output - file is specified when opening an ordinary file (e.g. with the syntax - 'myfile.fits(outputfile.fits)' then it will make a copy of the file, - close the original file and open the copy. Previously, the - specified output file would be ignored unless the file was compressed. - - - modified f77_wrap.h and f77_wrap3.c to support the Fortran wrappers - on 64-bit AMD Opteron machines - - Bug fixes: - - - made small change to ffsrow in eval_f.c to avoid potential array - bounds overflow. - - - made small change to group.c to fix problem where an 'int' was - incorrectly being cast to a 'long'. - - - corrected a memory allocation error in the new fits_hdr2str routine - that was added in version 2.48 - - - The on-the-fly row-selection filtering would fail with a segfault - if the length of a table row (NAXIS1 value) was greater than - 500000 bytes. A small change to eval_f.c was required to fix this. - -Version 2.490 - 11 February 2004 - - Bug fixes: - - - fixed a bug that was introduced in the previous release, which caused - the CFITSIO parser to no longer move to a named extension when opening - a FITS file, e.g., when opening myfile.fit[events] CFITSIO would just - open the primary array instead of moving to the EVENTS extension. - - - new group.c file from the INTEGRAL Science Data Center. It fixes - a problem when you attach a child to a parent and they are both - is the same file, but, that parent contains groups in other files. - In certain cases the attach would not happen because it seemed that - the new child was already in the parent group. - - - fixed bug in fits_calculator_rng when performing a calculation - on a range of rows in a table, so that it does not reset the - value in all the other rows that are not in the range = 0. - - - modified fits_write_chksum so that it updates the TFORMn - keywords for any variable length vector table columns BEFORE - calculating the CHECKSUM values. Otherwise the CHECKSUM - value is invalidated when the HDU is subsequently closed. - -Version 2.480 - 28 January 2004 - - New Routines: - - - fits_get_img_equivtype - just like fits_get_img_type, except in - the case of scaled integer images, it returns the 'equivalent' - data type that is necessary to store the scaled data values. - - - fits_hdr2str copies all the header keywords in the current HDU - into a single long character string. This is a convenient method - of passing the header information to other subroutines. - The user may exclude any specified keywords from the list. - - Enhancements: - - - modified the filename parser so that it accepts extension - names that begin with digits, as in 'myfile.fits[123TEST]'. - In this case CFITSIO will try to open the extension with - EXTNAME = '123TEST' instead of trying to move to the 123rd - extension in the file. - - - the template keyword parser now preserves the comments on the - the mandatory FITS keywords if present, otherwise a standard - default comment is provided. - - - modified the ftp driver file (drvrnet.c) to overcome a timeout - or hangup problem caused by some firewall software at the user's - end (Thanks to Bruce O'Neel for this fix). - - - modified iraffits.c to incorporate Doug Mink's latest changes to - his wcstools library routines. The biggest change is that now - the actual image dimensions, rather than the physically stored - dimensions, are used when converting an IRAF file to FITS. - - Bug fixes: - - - when writing to ASCII FITS tables, the 'elemnum' parameter was - supposed to be ignored if it did not have the default value of 1. - In some cases however setting elemnum to a value other than 1 - could cause the wrong number of rows to be produced in the output - table. - - - If a cfitsio calculator expression was imported from a text file - (e.g. using the extended filename syntax 'file.fits[col @file.calc]') - and if any individual lines in that text file were greater than - 255 characters long, then a space character would be inserted - after the 255th character. This could corrupt the line if the space - was inserted within a column name or keyword name token. - -Version 2.480beta (used in the FTOOLS 5.3 release, 1 Nov 2003) - - New Routines: - - - fits_get_eqcoltype - just like fits_get_coltype, except in the - case of scaled integer columns, it returns the 'equivalent' - data type that is necessary to store the scaled data values. - - - fits_split_names - splits an input string containing a comma or - space delimited list of names (typically file names or column - names) into individual name tokens. - - Enhancements: - - - changed fhist in histo.c so that it can make histograms of ASCII - table columns as well as binary table columns (as long as they - contain numeric data). - - Bug fixes: - - - removed an erroneous reference to listhead.c in makefile.vcc, that is - used to build the cfitsio dll under Windows. This caused a 'main' - routine to be added to the library, which causes problems when linking - fortran programs to cfitsio under windows. - - - if an error occurs when opening for a 2nd time (with ffopen) a file that - is already open (e.g., the specified extension doesn't exist), and - if the file had been modified before attempting to reopen it, then - the modified buffers may not get written to disk and the internal - state of the file may become corrupted. ffclos was modified to - always set status=0 before calling ffflsh if the file has been - concurrently opened more than once. - -Version 2.470 - 18 August 2003 - - Enhancements: - - - defined 'TSBYTE' to represent the 'signed char' datatype (similar to - 'TBYTE' that represents the 'unsigned char' datatype) and added - support for this datatype to all the routines that read or write - data to a FITS image or table. This was implemented by adding 2 - new C source code files to the package: getcolsb.c and putcolsb.c. - - - Defined a new '1S' shorthand data code for a signed byte column in - a binary table. CFITSIO will write TFORMn = '1B' and - TZEROn = -128 in this case, which is the convention used to - store signed byte values in a 'B' type column. - - - in fitsio2.h, added test of whether `__x86_64__` is defined, to - support the new AMD Opteron 64-bit processor - - - modified configure to not use the -fast compiler flag on Solaris - platforms when using the proprietary Solaris cc compiler. This - flag causes compilation problems in eval_y.c (compiler just - hangs forever). - - Bug fixes: - - - In the special case of writing 0 elements to a vector table column - that contains 0 rows, ffgcpr no longer adds a blank row to the table. - - - added error checking code for cases where a ASCII string column - in a binary table is greater than 28800 characters wide, to avoid - going into an infinite loop. - - - the fits_get_col_display_width routine was incorrectly returning - width = 0 for a 'A' binary table column that did not have an - explicit vector length character. - -Version 2.460 - 20 May 2003 - - Enhancements: - - - modified the HTTP driver in drvrnet.c so that CFITSIO can read - FITS files via a proxy HTTP server. (This code was contributed by - Philippe Prugniel, Obs. de Lyon). To use this feature, the - 'http_proxy' environment variable must be defined with the - address (URL) and port number of the proxy server, i.e., - > setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 - will use port 3128 on heasarc.gsfc.nasa.gov - - - suppressed some compiler warnings by casting a variable of - type 'size_t' to type 'int' in fftkey (in fitscore.c) and - iraftofits and irafrdimge (in iraffits.c). - -Version 2.450 - 30 April 2003 - - Enhancements: - - - modified the WCS keyword reading routine (ffgics) to support cases - where some of the CDi_j keywords are omitted (with an assumed - value = 0). - - - Made a change to http_open_network in drvrnet.c to add a 'Host: ' - string to the open request. This is required by newer HTTP 1.1 - servers (so-called virtual servers). - - - modified ffgcll (read logical table column) to return the illegal - character value itself if the FITS file contains a logical value that is - not equal to T, F or zero. Previously it treated this case the - same as if the FITS file value was = 0. - - - modified fits_movnam_hdu (ffmnhd) so that it will move to a tile- - compressed image (that is stored in a binary table) if the input - desired HDU type is BINARY_TBL as well as if the HDU type = IMAGE_HDU. - - Bug fixes: - - - in the routine that checks the data fill bytes (ffcdfl), the call - to ffmbyt should not ignore an EOF error when trying to read the bytes. - This is a little-used routine that is not called by any other CFITSIO - routine. - - - fits_copy_file was not reporting an error if it hit the End Of File - while copying the last extension in the input file to the output file. - - - fixed inconsistencies in the virtual file column filter parser - (ffedit_columns) to properly support expressions which create or - modify a keyword, instead of a column. Previously it was only possible - to modify keywords in a table extension (not an image), and the - keyword filtering could cause some of the table columns to not - get propagated into the virtual file. Also, spaces are now - allowed within the specified keyword comment field. - - - ffdtyp was incorrectly returning the data type of FITS keyword - values of the form '1E-09' (i.e., an exponential value without - a decimal point) as integer rather than floating point. - - - The enhancement in the previous 2.440 release to allow more files to be - opened at one time introduced a bug: if ffclos is called with - a non-zero status value, then any subsequent call to ffopen will likely - cause a segmentation fault. The fits_clear_Fptr routine was modified - to fix this. - - - rearranged the order of some computations in fits_resize_img so as - to not exceed the range of a 32-bit integer when dealing with - large images. - - - the template parser routine, ngp_read_xtension, was testing for - "ASCIITABLE" instead of "TABLE" as the XTENSION value of an ASCII - table, and it did not allow for optional trailing spaces in the IMAGE" - or "TABLE" string value. - -Version 2.440 - 8 January 2003 - - Enhancements: - - - modified the iterator function, ffiter, to operate on random - groups files. - - - decoupled the NIOBUF (= 40) parameter from the limit on the number - FITS files that can be opened, so that more files may be opened - without the overhead of having to increase the number of NIOBUF - buffers. A new NMAXFILES parameter is defined in fitsio2.h which sets - the maximum number of opened FITS files. It is set = 300 by default. - Note however, that the underlying compiler or operating system may - not allow this many files to be opened at one time. - - - updated the version of cfortran.h that is distributed with CFITSIO from - version 3.9 to version 4.4. This required changes to f77_wrap.h - and f77_wrap3.c. The original cfortran.h v4.4 file was modified - slightly to support CFITSIO and ftools (see comments in the header - of cfortran.h). - - - modified ffhist so that it copies all the non-structural keywords from - the original binary table header to the binned image header. - - - modified fits_get_keyclass so that it recognizes EXTNAME = - COMPRESSED_IMAGE as a special tile compression keyword. - - - modified Makefile.in to support the standard --prefix convention - for specifying the install target directory. - - Bug fixes: - - - in fits_decompress_img, needed to add a call to ffpscl to turn - off the BZERO and BSCALE scaling when reading the compressed image. - -Version 2.430 - 4 November 2002 - - Enhancements: - - - modified fits_create_hdu/ffcrhd so that it returns without doing - anything and does not generate an error if the current HDU is - already an empty HDU. There is no need in this case to append - a new empty HDU to the file. - - - new version of group.c (supplied by B. O'Neel at the ISDC) fixes 2 - limitations: 1 - Groups now have 256 characters rather than 160 - for the path lengths in the group tables. - ISDC SPR 1720. 2 - - Groups now can have backpointers longer than 68 chars using the long - string convention. - ISDC SPR 1738. - - - small change to f77_wrap.h and f77_wrap3.c to support the fortran - wrappers on SUN solaris 64-bit sparc systems (see also change to v2.033) - - - small change to find_column in eval_f.c to support unsigned long - columns in binary tables (with TZEROn = 2147483648.0) - - - small modification to cfortran.h to support Mac OS-X, (Darwin) - - Bug fixes: - - - When reading tile-compress images, the BSCALE and BZERO scaling - keywords were not being applied, if present. - - - Previous changes to the error message stack code caused the - tile compressed image routines to not clean up spurious error - messages properly. - - - fits_open_image was not skipping over null primary arrays. - -Version 2.420 - 19 July 2002 - - Enhancements: - - - modified the virtual filename parser to support exponential notation - when specifying the min, max or binsize in a binning specifier, as in: - myfile.fits[binr X=1:10:1.0E-01, Y=1:10:1.0E-01] - - - removed the limitation on the maximum number of HDUs in a FITS file - (limit used to be 1000 HDUs per file). Now any number of HDUs - can be written/read in a FITS file. (BUT files that have huge numbers - of HDUs can be difficult to manage and are not recommended); - - - modified grparser.c to support HIERARCH keywords, based on - code supplied by Richard Mathar (Max-Planck) - - - moved the ffflsh (fits_flush_buffer) from the private to the - public interface, since this routine may be useful for some - applications. It is much faster than ffflus. - - - small change to the definition of OFF_T in fitsio.h to support - large files on IBM AIX operating systems. - - Bug fixes: - - - fixed potential problem reading beyond array bounds in ffpkls. This - would not have affected the content of any previously generated FITS - files. - - - in the net driver code in drvrnet.c, the requested protocol string - was changed from "http/1.0" to "HTTP/1.0" to support apache 1.3.26. - - - When using the virtual file syntax to open a vector cell in a binary - table as if it were a primary array image, there was a bug - in fits_copy_image_cell which garbled the data if the vector - was more than 30000 bytes long. - - - fixed problem that caused fits_report_error to crash under Visual - C++ on Windows systems. The fix is to use the '/MD' switch - on the cl command line, or, in Visual Studio, under project - settings / C++ select use runtime library multithreaded DLL - - - modified ffpscl so it does not attempt to reset the scaling values - in the internal structure if the image is tile-compressed. - - - fixed multiple bugs in mem_rawfile_open which affected the case - where a raw binary file is read and converted on the fly into - a FITS file. - - - several small changes to group.c to suppress compiler warnings. - -Version 2.410 - 22 April 2002 (used in the FTOOLS 5.2 release) - - New Routines: - - - fits_open_data behaves similarly to fits_open_file except that it - also will move to the first HDU containing significant data if - and an explicit HDU name or number to open was not specified. - This is useful for automatically skipping over a null primary - array when opening the file. - - - fits_open_table and fits_open_image behaves similarly to - fits_open_data, except they move to the first table or image - HDU in the file, respectively. - - - fits_write_errmark and fits_clear_errmark routines can be use - to write an invisible marker to the CFITSIO error stack, and - then clear any more recent messages on the stack, back to - that mark. This preserves any older messages on the stack. - - - fits_parse_range utility routine parses a row list string - and returns integer arrays giving the min and max row in each - range. - - - fits_delete_rowrange deletes a specified list of rows or row - ranges. - - - fits_copy_file copies all or part of the HDUs in the input file - to the output file. - - - added fits_insert_card/ffikey to the publicly defined set - of routines (previously, it was a private routine). - - Enhancements: - - - changed the default numeric display format in ffgkys from 'E' format - to 'G' format, and changed the format for 'X' columns to a - string of 8 1s or 0s representing each bit value. - - - modified ffflsh so the system 'fflush' call is not made in cases - where the file was opened with 'READONLY' access. - - - modified the output filename parser so the "-.gz", and "stdout.gz" - now cause the output file to be initially created in memory, - and then compressed and written out to the stdout stream when - the file is closed. - - - modified the routines that delete rows from a table to also - update the variable length array heap, to remove any orphaned - data from the heap. - - - modified ffedit_columns so that wild card characters may be - used when specifying column names in the 'col' file filter - specifier (e.g., file.fits[col TIME; *RAW] will create a - virtual table contain only the TIME column and any other columns - whose name ends with 'RAW'). - - - modified the keyword classifier utility, fits_get_keyclass, to - support cases where the input string is just the keyword name, - not the entire 80-character card. - - - modified configure.in and configure to see if a proprietary - C compiler is available (e.g. 'cc'), and only use 'gcc' if not. - - - modified ffcpcl (copy columns from one table to another) so that - it also copies any WCS keywords related to that column. - - - included an alternate source file that can be used to replace - compress.c, which is distributed under the GNU General Public - License. The alternate file contains non-functional stubs for - the compression routines, which can be used to make a version of - CFITSIO that does not have the GPL restrictions (and is also less - functional since it cannot read or write compressed FITS files). - - - modifications to the iterator routine (ffiter) to support writing - tile compressed output images. - - - modified ffourl to support the [compress] qualifier when specifying - the optional output file name. E.g., file.fit(out.file[compress])[3] - - - modified imcomp_compress_tile to fully support implicit data type - conversion when writing to tile-compressed images. Previously, - one could not write a floating point array to an integer compressed - image. - - - increased the number of internal 2880-byte I/O buffers allocated - by CFITSIO from 25 to 40, in recognition of the larger amount - of memory available on typical machines today compared with - a few years ago. The number of buffers can be set by the user - with the NIOBUF parameter in fitsio2.h. (Setting this too large - can actually hurt performance). - - - modified the #if statements in fitsio2.h, f77_wrap.h and f77_wrap1.c - to support the new Itanium 64-bit Intel PC. - - - a couple minor modifications to fitsio.h needed to support the off_t - datatype on Debian linux systems. - - - increased internal buffer sizes in ffshft and ffsrow to improve - the I/O performance. - - Bug fixes: - - - fits_get_keyclass could sometimes try to append to an unterminated - string, causing an overflow of a string array. - - - fits_create_template no longer worked because of improvements made - to other routines. Had to modify ffghdt to not try to rescan - the header keywords if the file is still empty and contains no - keywords yet. - - - ffrtnm, which returns the root filename, sometimes did not work - properly when testing if the 'filename+n' convention was used for - specifying an extension number. - - - fixed minor problem in the keyword template parsing routine, ffgthd - which in rare cases could cause an improperly terminated string to - be returned. - - - the routine to compare 2 strings, ffcmps, failed to find a match - in comparing strings like "*R" and "ERROR" where the match occurs - on the last character, but where the same matching character occurs - previously in the 2nd string. - - - the region file reading routine (ffrrgn) did not work correctly if - the region file (created by POW and perhaps other programs) had an - 'exclude' region (beginning with a '-' sign) as the first region - in the file. In this case all points outside the excluded region - should be accepted, but in fact no points were being accepted - in this case. - -Version 2.401 - 28 Jan 2002 - - - added the imcopy example program to the release (and Makefile) - - Bug fixes: - - - fixed typo in the imcompress code which affected compression - of 3D datacubes. - - - made small change to fficls (insert column) to allow colums with - TFORMn = '1PU' and '1PV' to be inserted in a binary table. The - 'U' and 'V' are codes only used within CFITSIO to represent unsigned - 16-bit and 32-bit integers; They get replaced by '1PI' and '1PJ' - respectively in the FITS table header, along with the appropriate - TZEROn keyword. - -Version 2.400 - 18 Jan 2002 - - (N.B.: Application programs must be recompiled, not just relinked - with the new CFITSIO library because of changes made to fitsio.h) - - New Routines: - - - fits_write_subset/ffpss writes a rectangular subset (or the whole - image) to a FITS image. - - - added a whole new family of routines to read and write arrays of - 'long long' integers (64-bit) to FITS images or table columns. The - new routine names all end in 'jj': ffpprjj, ffppnjj, ffp2djj, - ffp3djj, ffppssjj, ffpgpjj, ffpcljj, ffpcnjj. ffgpvjj, ffgpfjj, - ffg2djj, ffg3djj, ffgsvjj, ffgsfjj, ffggpjj, ffgcvjj, and ffgcfjj. - - - added a set of helper routines that are used in conjunction with - the new support for tiled image compression. 3 routines set the - parameters that should be used when CFITSIO compresses an image: - fits_set_compression_type - fits_set_tile_dim - fits_set_noise_bits - - 3 corresponding routines report back the current settings: - fits_get_compression_type - fits_get_tile_dim - fits_get_noise_bits - - Enhancements: - - - major enhancement was made to support writing to tile-compressed - images. In this format, the image is divided up into a rectangular - grid of tiles, and each tile of pixels is compressed individually - and stored in a row of a variable-length array column in a binary - table. CFITSIO has been able to transparently read this compressed - image format ever since version 2.1. Now all the CFITSIO image - writing routines also transparently support this format. There are - 2 ways to force CFITSIO to write compressed images: 1) call the - fits_set_compression_type routine before writing the image header - keywords, or 2), specify that the image should be compressed when - entering the name of the output FITS file, using a new extended - filename syntax. (examples: "myfile.fits[compress]" will use the - default compression parameters, and "myfile.fits[compress GZIP - 100,100] will use the GZIP compression algorithm with 100 x 100 - pixel tiles. - - - added new driver to support creating output .gz compressed fits - files. If the name of the output FITS file to be created ends with - '.gz' then CFITSIO will initially write the FITS file in memory and - then, when the FITS file is closed, CFITSIO will gzip the entire - file before writing it out to disk. - - - when over-writing vectors in a variable length array in a binary - table, if the new vector to be written is less than or equal to - the length of the previously written vector, then CFITSIO will now - reuse the existing space in the heap, rather than always appending - the new array to the end of the heap. - - - modified configure.in to support building cfitsio as a dynamic - library on Mac OS X. Use 'make shared' like on other UNIX platforms, - but a .dylib file will be created instead of .so. If installed in a - nonstandard location, add its location to the DYLD_LIBRARY_PATH - environment variable so that the library can be found at run time. - - - made various modifications to better support the 8-byte long integer - datatype on more platforms. The 'LONGLONG' datatype is typedef'ed - to equal 'long long' on most Unix platforms and MacOS, and equal - to '__int64' on Windows machines. - - - modified configure.in and makefile.in to better support cases - where the system has no Fortran compiler and thus the f77 wrapper - routines should not be compiled. - - - made small modification to eval.y and eval_y.f to get rid of warning - on some platforms about redefinition of the 'alloca'. - - Bug fixes: - - - other recent bug fixes in ffdblk (delete blocks) caused ffdhdu (delete - HDU) to fail when trying to replace the primary array with a null - primary array. - - - fixed bug that prevented inserting a new variable length column - into a table that already contained variable length data. - - - modified fits_delete_file so that it will delete the file even if - the input status value is not equal to zero. - - - in fits_resize_image, it was sometimes necessary to call ffrdef to - force the image structure to be defined. - - - modified the filename parser to support input files with names like: - "myfile.fits.gz(mem://tmp)" in which the url type is specified for - the output file but not for the input file itself. This required - modifications to ffiurl and ffrtnm. - -Version 2.301 - 7 Dec 2001 - - Enhancements: - - - modified the http file driver so that if the filename to be opened - contains a '?' character (most likely a cgi related string) then it - will not attempt to append a .gz or .Z as it would normally do. - - - added support for the '!' clobber character when specifying - the output disk file name in CFITSIO's extended filename syntax, e.g., - 'http://a.b.c.d/myfile.fits.gz(!outfile.fits)' - - - added new device driver which is used when opening a compressed FITS - file on disk by uncompressing it into memory with READWRITE - access. This happens when specifying an output filename - 'mem://'. - - - added 2 other device drivers to open http and ftp files in memory - with write access. - - - improved the error trapping and reporting in cases where program - attempts to write to a READONLY file (especially in cases where the - 'file' resides in memory, as is the case when opening an ftp or http - file. - - - modified the extended filename parser so that it is does not confuse - the bracket character '[' which is sometimes used in the root name - of files of type 'http://', as the start of an extname or row filter - expression. If the file is of type 'http://', the parser now - checks to see if the last character in the extended file name is - a ')' or ']'. If not, it does not try to parse the file name - any further. - - - improved the efficiency when writing FITS files in memory, by - initially allocating enough memory for the entire HDU when it is - created, rather than incrementally reallocing memory 2880 bytes - at a time (modified ffrhdu and mem_truncate). This change also - means that the program will fail much sooner if it cannot allocate - enough memory to hold the entire FITS HDU. - - Bug fixes: - - - There was an error in the definition of the Fortran ftphtb wrapper - routine (writes required ASCII table header keywords) that caused - it to fail on DEC OSF and other platforms where sizeof(long) = 8. - -Version 2.300 - 23 Oct 2001 - - New Routines: - - - fits_comp_img and fits_decomp_img are now fully supported and - documented. These routine compress and decompress, respective, - a FITS image using a new algorithm in which the image is first - divided into a grid of rectangular tiles, then the compressed byte - stream from each tile is stored in a row of a binary table. - CFITSIO can transparently read FITS images stored in this - compressed format. Compression ratios of 3 - 6 are typically - achieved. Large compression ratios are achieved for floating - point images by throwing away non-significant noise bits in the - pixel values. - - - fits_test_heap tests the integrity of the binary table heap and - returns statistics on the amount of unused space in the heap and - the amount of space that is pointed to by more than 1 descriptor. - - - fits_compress_heap which will reorder the arrays in the binary - table heap, recovering any unused space. - - Enhancements: - - - made substantial internal changes to the code to support FITS - files containing 64-bit integer data values. These files have - BITPIX = 64 or TFORMn = 'K'. This new feature in CFITSIO is - currently only enabled if SUPPORT_64BIT_INTEGERS is defined = 1 in - the beginning of the fitsio2.h file. By default support for - 64-bit integers is not enabled. - - - improved the ability to read and return a table column value as a - formatted string by supporting quasi-legal TDISPn values which - have a lowercase format code letter, and by completely ignoring - other unrecognizable TDISPn values. Previously, unrecognized - TDISPn values could cause zero length strings to be returned. - - - made fits_write_key_longstr more efficient when writing keywords - using the long string CONTINUE convention. It previously did not - use all the available space on each card when the string to be - written contained many single quote characters. - - - added a new "CFITSIO Quick Start Guide" which provides all the - basic information needed to write C programs using CFITSIO. - - - updated the standard COMMENT keywords that are written at the - beginning of every primary array to refer to the newly published - FITS Standard document in Astronomy and Astrophysics. - Note: because of this change, any FITS file created with this - version of CFITSIO will not be identical to the same file written - with a previous version of CFITSIO. - - - replaced the 2 routines in pliocomp.c with new versions provided by - D Tody and N Zarate. These routines compress/uncompress image pixels - using the IRAF pixel list compression algorithm. - - - modified fits_copy_hdu so that when copying a Primary Array - to an Image extension, the COMMENT cards which give the reference - to the A&A journal article about FITS are not copied. In the - inverse case the COMMENT keywords are inserted in the header. - - - modified configure and Makefile.in to add capability to build a - shared version of the CFITSIO library. Type 'make shared' or - 'make libcfitsio.so' to invoke this option. - - - disabled some uninformative error messages on the error stack: - 1) when calling ffclos (and then ffchdu) with input status > 0 - 2) when ffmahd tries to move beyond the end of file. - The returned status value remains the same as before, but the - annoying error messages no longer get written to the error stack. - - - The syntax for column filtering has been modified so that - if one only specifies a list of column names, then only those - columns will be copied into the output file. This provides a simple - way to make a copy of a table containing only a specified list of - columns. If the column specifier explicitly deletes a column, however, - than all the other columns will be copied to the filtered input - file, regardless of whether the columns were listed or not. - Similarly, if the expression specifies only a column to be modified - or created, then all the other columns in the table will be - copied. - - mytable.fit[1][col Time;Rate] - only the Time and Rate - columns will be copied to the filtered input file. - - mytable.fit[1][col -Time ] - all but the Time column are copied - to the filtered input file. - - mytable.fit[1][col Rate;-Time] - same as above. - - - changed a '#if defined' statement in f77_wrap.h and f77_wrap1.c - to support the fortran wrappers on 64-bit IBM/RS6000 systems - - - modified group.c so that when attaching one group (the child) to - another (the parent), check in each file for the existence of a - pointer to the other before adding the link. This is to prevent - multiple links from forming under all circumstances. - - - modified the filename parser to accept 'STDIN', 'stdin', - 'STDOUT' and 'stdout' in addition to '-' to mean read the - file from standard input or write to standard output. - - - Added support for reversing an axis when reading a subsection - of a compressed image using the extended filename syntax, as in - myfile.fits+1[-*, *] or myfile.fits+1[600:501,501:600] - - - When copying a compressed image to a uncompressed image, the - EXTNAME keyword is no longer copied if the value is equal to - 'COMPRESSED_IMAGE'. - - - slight change to the comment field of the DATE keyword to reflect - the fact that the Unix system date and time is not true UTC time. - - Bug fixes: - - - fits_write_key_longstr was not writing the keyword if a null - input string value was given. - - - writing data to a variable length column, if that binary table is not - the last HDU in the FITS file, might overwrite the following HDU. - Fixed this by changing the order of a couple operations in ffgcpr. - - - deleting a column from a table containing variable length columns - could cause the last few FITS blocks of the file to be reset = 0. - This bug occurred as a result of modifications to ffdblk in v2.202. - This mainly affects users of the 'compress_fits' utility - program. - - - fixed obscure problem when writing bits to a variable length 'B' - column. - - - when reading a subsection of an image, the BSCALE and BZERO pixel - scaling may not have been applied when reading image pixel values - (even though the scaling keywords were properly written in the - header). - - - fits_get_keyclass was not returning 'TYP_STRUCT_KEY' for the - END keyword. - -Version 2.204 - 26 July 2001 - - Bug fixes: - - - Re-write of fits_clean_url in group.c to solve various problems - with invalid bounds checking. - -Version 2.203 - 19 July 2001 (version in FTOOLS v5.1) - - Enhancements: - - - When a row selection or calculator expression is written in - an external file (and read by CFITSIO with the '@filename' syntax) - the file can now contain comment lines. The comment line must - begin with 2 slash characters as the first 2 characters on the - line. CFITSIO will ignore the entire line when reading the - expression. - - Bug fixes: - - - With previous versions of CFITSIO, the pixel values in a FITS - image could be read incorrectly in the following case: when - opening a subset of a FITS image (using the - 'filename.fits[Xmin:Xmax,Ymin:Ymax]' notation) on a PC linux, PC - Windows, or DEC OSF machine (but not on a SUN or Mac). This - problem only occurs when reading more than 8640 bytes of data - (2160 4-byte integers) at a time, and usually only occurs if the - reading program reads the pixel data immediately after opening the - file, without first reading any header keywords. This error would - cause strips of zero valued pixels to appear at semi-random - positions in the image, where each strip usually would be 2880 - bytes long. This problem does not affect cases where the input - subsetted image is simply copied to a new output FITS file. - - -Version 2.202 - 22 May 2001 - - Enhancements: - - - revised the logic in the routine that tests if a point is - within a region: if the first region is an excluded region, - then it implicitly assumes a prior include region covering - the entire detector. It also now supports cases where a - smaller include region is within a prior exclude region. - - - made enhancement to ffgclb (read bytes) so that it can - also read values from a logical column, returning an array - of 1s and 0s. - - - defined 2 new grouping error status values (349, 350) in - cfitsio.h and made minor changes to group.c to use these new - status values. - - - modified fits_open_file so that if it encounters an error while - trying to move to a user-specified extension (or select a subset - of the rows in an input table, or make a histogram of the - column values) it will close the input file instead of leaving - it open. - - - when using the extended filename syntax to filter the rows in - an input table, or create a histogram image from the values in - a table column, CFITSIO now writes HISTORY keywords in the - output file to document the filtering expression that was used. - - Bug fixes: - - - ffdblk (called by ffdrow) could overwrite the last FITS block(s) in - the file in some cases where one writes data to a variable length - column and then calls ffdrow to delete rows in the table. This - bug was similar to the ffiblk bug that was fixed in v2.033. - - - modified fits_write_col_null to fix a problem which under unusual - circumstances would cause a End-of-File error when trying to - read back the value in an ASCII string column, after initializing - if by writing a null value to it. - - - fixed obscure bug in the calculator function that caused an - error when trying to modify the value of a keyword in a HDU - that does not have a NAXIS2 keyword (e.g., a null primary array). - - - the iterator function (in putcol.c) had a bug when calculating - the optimum number rows to process in the case where the table - has very wide rows (>33120 bytes) and the calculator expression - involves columns from more than one FITS table. This could - cause an infinite loop in calls to the ffcalc calculator function. - - - fixed bug in ffmvec, which modifies the length of an - existing vector column in a binary table. If the vector - was reduced in length, the FITS file could sometimes be left - in a corrupted state, and in all cases the values in the remaining - vector elements of that column would be altered. - - - in drvrfile.c, replaced calls to fsetpos and fgetpos with - fseek and ftell (or fseeko and ftello) because the fpos_t - filetype used in fsetpos is incompatible with the off_t - filetype used in fseek, at least on some platforms (Linux 7.0). - (This fix was inserted into the V2.201 release on April 4). - - - added "#define fits_write_pixnull ffppxn" to longnam.h - -Version 2.201 - 15 March 2001 - - Enhancements - - - enhanced the keyword reading routines so that they will do - implicit datatype conversion from a string keyword value - to a numeric keyword value, if the string consist of a - valid number enclosed in quotes. For example, the keyword - mykey = '37.5' can be read by ffgkye. - - - modified ffiimg so that it is possible to insert a new - primary array at the beginning of the file. The original - primary array is then converted into an IMAGE extension. - - - modified ffcpdt (copy data unit) to support the case where - the data unit is being copied between 2 HDUs in the same file. - - - enhanced the fits_read_pix and fits_read_pixnull routines so - that they support the tiled image compression format that the - other image reading routines also support. - - - modified the Extended File Name syntax to also accept a - minus sign (-) as well as an exclamation point (!) as - the leading character when specifying a column or or keyword - to be deleted, as in [col -time] will delete the TIME column. - - - now completely support reading subimages, including pixel - increments in each dimension, for tile-compressed images - (where the compressed image tiles are stored in a binary - table). - - Bug fixes: - - - fixed confusion in the use of the fpos_t and off_t datatypes - in the fgetpos and fsetpos routines in drvrfile.c which caused - problems with the Windows VC++ compiler. (fpos_t is not - necessarily identical to off_t) - - - fixed a typo in the fits_get_url function in group.c which - caused problems when determining the relative URL to a compressed - FITS file. - - - included fitsio.h in the shared memory utility program, - smem.c, in order to define OFF_T. - - - fixed typo in the datatype of 'nullvalue' in ffgsvi, which caused - attempts to read subsections of a short integer tiled compressed - image to fail with a bus error. - - - fixed bug in ffdkey which sometimes worked incorrectly if one - tried to delete a nonexistent keyword beyond the end of the header. - - - fixed problem in fits_select_image_section when it writes a dummy - value to the last pixel of the section. If the image contains - scaled integer pixels, then in some cases the pixel value could end - up out of range. - - - fixed obscure bug in the ffpcn_ family of routines which gave - a floating exception when trying to write zero number of pixels to - a zero length array (why would anyone do this?) - -Version 2.200 - 26 Jan 2001 - - Enhancements - - - updated the region filtering code to support the latest region - file formats that are generated by the POW, SAOtng and ds9 - programs. Region positions may now be given in HH:MM:SS.s, - DD:MM:SS.s format, and region sizes may be given arcsec or arcmin - instead of only in pixel units. Also changed the logic so that if - multiple 'include' regions are specified in the region file, they - are ORed together, instead of ANDed, so that the filtering keeps - points that are located within any of the 'include' regions, not - just the intersection of the regions. - - - added support for reading raw binary data arrays by converting - them on the fly into virtual FITS files. - - - modified ffpmsg, which writes error messages to CFITSIO's internal - error stack, so that messages > 80 characters long will be wrapped - around into multiple 80 character messages, instead of just - being truncated at 80 characters. - - - modified the CFITSIO parser so that expression which involve - scaled integer columns get cast to double rather than int. - - - Modified the keyword template parsing routine, ffgthd, to - support the HIERARCH keyword. - - - modified ffainit and ffbinit so that they don't unnecessarily - allocate 0 bytes of memory if there are no columns (TFIELDS = 0) - in the table that is being opened. - - - modified fitsio2.h to support NetBSD on Alpha OSF platforms - (NetBSD does not define the '__unix__' symbol). - - - changed the way OFF_T is defined in fitsio.h for greater - portability. - - - changed drvrsmem.c so it is compiled only when HAVE_SHMEM_SERVICES - is defined in order to removed the conditional logic from the Makefile - - - reorganized the CFITSIO User's guide to make it - clearer and easier for new users to learn the basic routines. - - - fixed ffhdef (which reserves space for more header keywords) so - that is also updates the start position of the next HDU. This - affected the offset values returned by ffghof. - -Version 2.100 - 18 Oct 2000 - - Enhancements - - - made substantial modification to the code to support Large files, - i.e., files larger than 2**31 bytes = 2.1GB. FITS files up to - 6 terabytes in size may now be read and written on platforms - that support Large files (currently only Solaris). - - - modified ffpcom and ffphis, which write COMMENT and HISTORY - keywords, respectively, so that they now use columns 9 - 80, - instead of only columns 11 - 80. Previously, these routines - avoided using columns 9 and 10, but this is was unnecessarily - restrictive. - - - modified ffdhdu so that instead of refusing to delete the - primary array, it will replace the current primary array - with a null primary array containing the bare minimum of - required keywords and no data. - - New Routines - - - fits_read_pix, fits_read_pixnull, fits_read_subset, and fits_write_pix - routines were added to enable reading and writing of Large images, - with more than 2.1e9 pixels. These new routines are now recommended - as the basic routines for reading and writing all images. - - - fits_get_hduoff returns the byte offset in the file to - the start and end of the current HDU. This routine replaces the - now obsolete fits_get_hduaddr routine; it uses 'off_t' instead of - 'long' as the datatype of the arguments and can support offsets - in files greater than 2.1GB in size. - - Bug fixes: - - - fixed bug in fits_select_image_section that caused an integer - overflow when reading very large image sections (bigger than - 8192 x 8192 4-byte pixels). - - - improved ffptbb, the low-level table writing routine, so that - it will insert additional rows in the table if the table is - not already big enough. Previously it would have just over- - written any HDUs following the table in the FITS file. - - - fixed a bug in the fits_write_col_bit/ffpclx routine which - could not write to a bit 'X' column if that was the first column - in the table to be written to. This bug would not appear if - any other datatype column was written to first. - - - non-sensible (but still formally legal) binary table TFORM values - such as '8A15', or '1A8' or 'A8' would confuse CFITSIO and cause it - to return a 308 error. When parsing the TFORMn = 'rAw' value, - the ffbnfm routine has been modified to ignore the 'w' value in cases - where w > r. - - - fixed bug in the blsearch routine in iraffits.c which sometimes - caused an out-of-bounds string pointer to be returned when searching - for blank space in the header just before the 'END' keyword. - - - fixed minor problem in ffgtcr in group.c, which sometimes failed - while trying to move to the end of file before appending a - grouping table. - - - on Solaris, with Sun CC 5.0, one must check for '__unix' rather - than '__unix__' or 'unix' as it's symbol. Needed to modify this - in drvrfile.c in 3 places. - - - in ffextn, the FITS file would be left open if the named - extension doesn't exist, thus preventing the file from being - opened again later with write access. - - - fixed bug in ffiimg that would cause attempts to insert a new - image extension following a table extension, and in front of any - other type of extension, to fail. - -Version 2.037 - 6 July 2000 - - Enhancements - - - added support in the extended filename syntax for flipping - an image along any axis either by specifying a starting - section pixel number greater than the ending pixel number, - or by using '-*' to flip the whole axis. Examples: - "myfile.fits[1:100, 50:10]" or "myfile.fits[-*,*]". - - - when reading a section of an image with the extended filename - syntax (e.g. image.fits[1:100:2, 1:100:2), any CDi_j WCS keywords - will be updated if necessary to transfer the world coordinate - system from the input image to the output image section. - - - on UNIX platforms, added support for filenames that begin - with "~/" or "~user/". The "~" symbol will get expanded - into a string that gives the user's home directory. - - - changed the filename parser to support disk file names that - begin with a minus sign. Previously, the leading minus sign would - cause CFITSIO to try to read/write the file from/to stdin/stdout. - - - modified the general fits_update_key routine, which writes - or updates a keyword value, to use the 'G' display format - instead of the 'E' format for floating point keyword values. - This will eliminate trailing zeros from appearing in the value. - - - added support for the "-CAR" celestial coordinate projection - in the ffwldp and ffxypx routines. The "-CAR" projection is - the default simplest possible linear projection. - - - added new fits_create_memfile/ffimem routine to create a new - fits file at a designated memory location. - - - ported f77_wrap.h and f77_wrap1.c so that the Fortran interface - wrappers work correctly on 64-bit SGI operating systems. In this - environment, C 'long's are 8-bytes long, but Fortran 'integers' - are still only 4-bytes long, so the words have to be converted - by the wrappers. - - - minor modification to cfortran.h to automatically detect when it - is running on a linux platform, and then define f2cFortran in that - case. This eliminates the need to define -Df2cFortran on the - command line. - - - modified group.c to support multiple "/" characters in - the path name of the file to be opened/created. - - - minor modifications to the parser (eval.y, eval_f.c, eval_y.c) - to a) add the unary '+' operator, and b) support copying the - TDIMn keyword from the input to the output image under certain - circumstances. - - - modified the lexical parser in eval_l.y and eval_l.c to - support #NULL and #SNULL constants which act to set the - value to Null. Support was also added for the C-conditional - expression: 'Boolean ? trueVal : falseVal'. - - - small modification to eval_f.c to write an error message to - the error stack if numerical overflow occurs when evaluating - an expression. - - - configure and configure.in now support the egcs g77 compiler - on Linux platforms. - - Bug fixes: - - - fixed a significant bug when using the extended filename binning - syntax to generate a 2-dimensional image from a histogram of the - values in 2 table columns. This bug would cause table events that - should have been located in the row just below the bottom row of - the image (and thus should have been excluded from the histogram) - to be instead added into the first row of the image. Similarly, - the first plane of a 3-D or 4-D data cube would include the events - that should have been excluded as falling in the previous plane of - the cube. - - - fixed minor bug when parsing an extended filename that contains - nested pairs of square brackets (e.g., '[col newcol=oldcol[9]]'). - - - fixed bug when reading unsigned integer values from a table or - image with fits_read_col_uint/ffgcvuk. This bug only occurred on - systems like Digital Unix (now Tru64 Unix) in which 'long' - integers are 8 bytes long, and only when reading more than 7200 - elements at a time. This bug would generally cause the program to - crash with a segmentation fault. - - - modified ffgcpr to update 'heapstart' as well as 'numrows' when - writing more rows beyond the end of the table. heapstart - is needed to calculate if more space needs to be inserted in the - table when inserting columns into the table. - - - modified fficls (insert column), ffmvec, ffdrow and ffdcol to - not use the value of the NAXIS2 keyword as the number of rows - in the table, and instead use the value that is stored in - an internal structure, because the keyword value may not - be up to date. - - - Fixed bug in the iterator function that affected the handling - of null values in string columns in ASCII and binary tables. - - - Reading a subsample of pixels in very large images, (e.g., - file = myfile.fits[1:10000:10,1:10000:10], could cause a - long integer overflow (value > 2**31) in the computation of the - starting byte offset in the file, and cause a return error status - = 304 (negative byte address). This was fixed by changing the - order of the arithmetic operations in calculating the value of - 'readptr' in the ffgcli, ffgclj, ffgcle, ffgcld, etc. routines. - - - In version 2.031, a fix to prevent compressed files from being - opened with write privilege was implemented incorrectly. The fix - was intended to not allow a compressed FITS file to be opened - except when a local uncompressed copy of the file is being - produced (then the copy is opened with write access), but in fact - the opposite behavior occurred: Compressed files could be opened - with write access, EXCEPT when a local copy is produced. This - has been fixed in the mem_compress_open and file_compress_open - routines. - - - in iraffits.c, a global variable called 'val' caused multiply - defined symbols warning when linking cfitsio and IRAF libraries. - This was fixed by making 'val' a local variable within the - routine. - -Version 2.036 - 1 Feb 2000 - - - added 2 new generic routines, ffgpf and ffgcf which are analogous - to ffgpv and ffgcv but return an array of null flag values instead - of setting null pixels to a reserved value. - - - minor change to eval_y.c and eval.y to "define alloca malloc" - on all platforms, not just VMS. - - - added support for the unsigned int datatype (TUINT) in the - generic ffuky routine and changed ffpky so that unsigned ints - are cast to double instead of long before being written to - the header. - - - modified ffs2c so that if a null string is given as input then - a null FITS string (2 successive single quotes) will be returned. - Previously this routine would just return a string with a single - quote, which could cause an illegal keyword record to be written. - - - The file flush operation on Windows platforms apparently - changes the internal file position pointer (!) in violation of the - C standard. Put a patch into the file_flush routine to explicitly - seek back to the original file position. - - - changed the name of imcomp_get_compressed_image_parms to - imcomp_get_compressed_image_par to not exceed the 31 character - limit on some compilers. - - - modified the filename parser (which is used when moving to a - named HDU) to support EXTNAME values which contain embedded blanks. - - - modified drvrnet.c to deal with ftp compressed files better so - that even fits files returned from cgi queries which have the wrong - mime types and/or wrong types of file names should still decompress. - - - modified ffgics to reduce the tolerance for acceptable skewness - between the axes, and added a new warning return status = - APPROX_WCS_KEY in cases where there is significant skewness - between the axes. - - - fixed bug in ffgics that affected cases where the first coordinate - axis was DEC, not RA, and the image was a mirror image of the sky. - - - fixed bug in ffhist when trying to read the default binning - factor keyword, TDBIN. - - - modified ffhist so that is correctly computes the rotation angle - in a 2-D image if the first histogram column has a CROTA type - keyword but the 2nd column does not. - - - modified ffcpcl so that it preserves the comment fields on the - TTYPE and TFORM keywords when the column is copied to a new file. - - - make small change to configure.in to support FreeBSD Linux - by setting CFLAGS = -Df2cFortran instead of -Dg77Fortran. Then - regenerated configure with autoconf 2.13 instead of 2.12. - -Version 2.035 - 7 Dec 1999 (internal release only, FTOOLS 5.0.2) - - - added new routine called fits_get_keyclass/ffgkcl that returns - the general class of the keyword, e.g., required structural - keyword, WCS keyword, Comment keyword, etc. 15 classes of - keywords have been defined in fitsio.h - - - added new routine called fits_get_img_parm/ffgipr that is similar - to ffgphd but it only return the bitpix, naxis, and naxisn values. - - - added 3 new routines that support the long string keyword - convention: fits_insert_key_longstr, fits_modify_key_longstr - fits_update_key_longstr. - - - modified ffgphd which reads image header keywords to support - the new experimental compressed image format. - - - when opening a .Z compressed file, CFITSIO tries to allocate - memory equal to 3 times the file size, which may be excessive - in some cases. This was changed so that if the allocation fails, - then CFITSIO will try again to allocate only enough memory - equal to 1 times the file size. More memory will be allocated - later if this turns out to be too small. - - - improved the error checking in the fits_insert_key routine - to check for illegal characters in the keyword. - -Version 2.034 - 23 Nov 1999 - - - enhanced support for the new 'CD' matrix world coordinate system - keywords in the ffigics routine. This routine has been enhanced - to look for the new 'CD' keywords, if present, and convert them - back to the old CDELTn and CROTAn values, which are then returned. - The routine will also swap the WCS parameters for the 2 axes if - the declination-like axis is the first WCS axis. - - - modified ffphbn in putkey.c to support the 'U' and 'V" TFORM characters - (which represent unsigned short and unsigned int columns) in variable - length array columns. (previously only supported these types in - fixed length columns). - - - added checks when reading gzipped files to detect unexpected EOF. - Previously, the 'inflate_codes' routine would just sit in an infinite - loop if the file ended unexpectedly. - - - modified fits_verify_chksum/ffvcks so that checksum keywords with - a blank value string are treated as undefined, the same as - if the keyword did not exist at all. - - - fixed ffghtb and ffghbn so that they return the extname value - in cases where there are no columns in the table. - - - fixed bug in the ffgtwcs routine (this is a little utility - routine to aid in interfacing to Doug Mink's WCS routines); - it was not correctly padding the length of string-valued keywords - in the returned string. - - - fixed bug in 'iraffits.c' that prevented Type-2 IRAF images from - being correctly byte-swapped on PCs and DEC-OSF machines. - - - fixed tiny memory leak in irafncmp in iraffits.c. Only relevant when - reading IRAF .imh files. - - - fixed a bug (introduced in version 2.027) that caused the keyword - reading routines to sometimes not find a matching keyword if the - input name template used the '*' wildcard as the last character. - (e.g., if input name = 'COMMENT*' then it would not find the - 'COMMENT' keywords. (It would have found longer keywords like - 'COMMENTX' correctly). The fix required a minor change to ffgcrd - in getkey.c - - - modified the routine (ffswap8) that does byteswapping of - double precision numbers. Some linux systems have reported floating - point exceptions because they were trying to interpret the bytes - as a double before the bytes had been swapped. - - - fixed bug in the calculation of the position of the last byte - in the string of bits to be read in ffgcxuk and ffgcxui. This - bug generally caused no harm, but could cause the routine to - exit with an invalid error message about trying to read - beyond the size of the field. - - - If a unix machine did not have '__unix__', 'unix', or '__unix' - C preprocessor symbols defined, then CFITSIO would correctly open - one FITS file, but would not correctly open subsequent files. Instead - it would think that the same file was being opened multiple times. - This problem has only been seen on an IBM/AIX machine. The fits_path2url - and fits_url2path routines in group.c were modified to fix the problem. - - - fixed bug in group.c, which affected WINDOWS platforms only, that - caused programs to go into infinite loop when trying to open - certain files. - - - the ftrsim Fortran wrapper routine to ffrsim was not defined - correctly, which caused the naxis(2) value to be passed incorrectly - on Dec OSF machines, where sizeof(long) != sizeof(int). - -Version 2.033 - 17 Sept 1999 - - - New Feature: enhanced the row selection parser so that comparisons - between values in different rows of the table are allowed, and the - string comparisons with <, >, <=, and >= are supported. - - - added new routine the returns the name of the keyword in the - input keyword record string. The name is usually the first - 8 characters of the record, except if the HIERARCH convention - is being used in which case the name may be up to 67 characters - long. - - - added new routine called fits_null_check/ffnchk that checks to - see if the current header contains any null (ASCII 0) characters. - These characters are illegal in FITS headers, but they go undetected - by the other CFITSIO routines that read the header keywords. - - - the group.c file has been replaced with a new version as supplied - by the ISDC. The changes are mainly to support partial URLs and - absolute URLs more robustly. Host dependent directory paths are - now converted to true URLs before being read from/written to - grouping tables. - - - modified ffnmhd slightly so that it will move to the first extension - in which either the EXTNAME or the HDUNAME keyword is equal to the - user-specified name. Previously, it only checked for HDUNAME if - the EXTNAME keyword did not exist. - - - made small change to drvrnet.c so that it uncompress files - which end in .Z and .gz just as for ftp files. - - - rewrote ffcphd (copy header) to handle the case where the - input and output HDU are in the same physical FITS file. - - - fixed bug in how long string keyword values (using the CONTINUE - convention) were read. If the string keyword value ended in an - '&' character, then fits_read_key_longstr, fits_modify_key_str, - and fits_delete_key would interpret the following keyword as - a continuation, regardless of whether that keyword name was - 'CONTINUE' as required by this convention. There was also a bug - in that if the string keyword value was all blanks, then - fits_modify_key_str could in certain unusual cases think - that the keyword ended in an '&' and go into an infinite loop. - - - modified ffgpv so that it calls the higher level ffgpv_ routine - rather than directly calling the lower level ffgcl_ routine. This - change is needed to eventually support reading compressed images. - - - added 3 new routines to get the image datatype, image dimensions, - and image axes length. These support the case where the image is - compressed and stored in a binary table. - - - fixed bug in ffiblk that could sometimes cause it to insert a - new block in a file somewhere in the middle of the data, instead - of at the end of the HDU. This fortunately is a rare problem, - mainly only occurring in certain cases when inserting rows in a binary - table that contains variable length array data (i.e., has a heap). - - - modified fits_write_tdim so that it double checks the TFORMn - value directly if the column repeat count stored in the internal - structure is not equal to the product of all the dimensions. - - - fixed bug that prevented ffitab or ffibin from inserting a new - table after a null primary array (can't read NAXIS2 keyword). - Required a small change to ffrdef. - - - modified testprog.c so that it will continue to run even if - it cannot open or process the template file testprog.tpt. - - - modified the logic in lines 1182-1185 of grparser.c so that - it returns the correct status value in case of an error. - - - added test in fitsio2.h to see if __sparcv9 is defined; this - identifies a machine running Solaris 7 in 64-bit mode where - long integers are 64 bits long. - -Version 2.032 - 25 May 1999 - - - the distribution .tar file was changed so that all the files - will be untarred into a subdirectory by default instead of - into the current directory. - - - modified ffclos so that it always frees the space allocated by - the fptr pointer, even when another fptr points to the same file. - - - plugged a potential (but rare in practice) memory leak in ffpinit - - - fixed bug in all the ffp3d_ and ffg3d_ routines in cases where - the data cube that has been allocated in memory has more planes - than the data cube in the FITS file. - - - modified drvrsmem.c so that it allocates a small shared - memory segment only if CFITSIO tries to read or write a - FITS file in shared memory. Previously it always allocated - the segment whether it was needed or not. Also, this small - segment is removed if 0 shared memory segments remain in - the system. - - - put "static" in front of 7 DECLARE macros in compress.c - because these global variables were causing conflicts with other - applications programs that had variables with the same names. - - - modified ffasfm to return datatype = TDOUBLE instead of TFLOAT - if the ASCII table column has TFORMn = 'Ew.d' with d > 6. - - - modified the column reading routines to a) print out the offending - entry if an error occurs when trying to read a numeric ASCII table - column, and b) print out the column number that had the error - (the messages are written to CFITSIOs error stack) - - - major updates to the Fortran FITSIO User's Guide to include many - new functions that have been added to CFITSIO in the past year. - - - modified fitsio2.h so that the test for __D_FLOAT etc. is only - made on Alpha VMS machines, to avoid syntax errors on some other - platforms. - - - modified ffgthd so that it recognizes a floating point value - that uses the 'd' or 'D' exponent character. - - - removed the range check in fftm2s that returned an error if - 'decimals' was less than zero. A negative value is OK and is - used to return only the date and not the time in the string. - -Version 2.031 - 31 Mar 1999 - - - moved the code that updates the NAXIS2 and PCOUNT keywords from - ffchdu into the lower lever ffrdef routine. This ensures that - other routines which call ffrdef will correctly update these 2 - keywords if required. Otherwise, for instance, calling - fits_write_checksum before closing the HDU could cause the NAXIS2 - keyword (number of rows in the table) to not be updated. - - - fixed bug (introduced in version 2.030) when writing null values - to a primary array or image extension. If trying to set more - than 1 pixel to null at a time, then typically only 1 null would - be written. Also fixed related bug when writing null values to - rows in a table that are beyond the currently defined size of the - table (the size of the table was not being expanded properly). - - - enhanced the extended filename parser to support '*' in image - section specifiers, to mean use the whole range of the axis. - myfile.fits[*,1:100] means use the whole range of the first - axis and pixels 1 to 100 in the second axis. Also supports - an increment, as in myfile.fits[*:2, *:2] to use just the - odd numbered rows and columns. - - - modified fitscore.c to set the initial max size of the header, when - first reading it, to the current size of the file, rather than to - 2 x 10**9 to avoid rare cases where CFITSIO ends up writing a huge - file to disk. - - - modified file_compress_open so that it will not allow a compressed - FITS file to be opened with write access. Otherwise, a program - could write to the temporary copy of the uncompressed file, but - the modification would be lost when the program exits. - -Version 2.030 - 24 Feb 1999 - - - fixed bug in ffpclu when trying to write a null value to a row - beyond the current size of the table (wouldn't append new rows - like it should). - - - major new feature: enhanced the routines that read ASCII string - columns in tables so that they can read any table column, including - logical and numeric valued columns. The column values are returned - as a formatted string. The format is determined by the TDISPn - keyword if present, otherwise a default format based on the - datatype of the column is used. - - - new routine: fits_get_col_display_width/ffgcdw returns the length - of the formatted strings that will be returned by the routines that - read table columns as strings. - - - major new feature: added support for specifying an 'image section' - when opening an image: e.g, myfile.fits[1:512:2,2:512:2] to - open a 256x256 pixel image consisting of the odd columns and the - even numbered rows of the input image. - - - added supporting project files and instructions for building - CFITSIO under Windows NT with the Microsoft Visual C++ compiler. - - - changed the variable 'template' to 'templt' in testprog.c since - it conflicted with a reserved word on some compilers. - - - modified group.c to conditionally include sys/stat.h only on - unix platforms - - - fixed bug in the ffiter iterator function that caused it to always - pass 'firstn' = 1 to the work function when reading from the - primary array or IMAGE extension. It worked correctly for tables. - - - fixed bug in the template header keyword parser (ffgthd) in cases - where the input template line contains a logical valued keyword - (T or F) without any following comment string. It was previously - interpreting this as a string-valued keyword. - - - modified ffrhdu that reads and opens a new HDU, so that it - ignores any leading blank characters in the XTENSION name, e.g., - XTENSION= ' BINTABLE' will not cause any errors, even though - this technically violates the FITS Standard. - - - modified ffgtbp that reads the required table keywords to make - it more lenient and not exit with an error if the THEAP keyword - in binary tables cannot be read as an integer. Now it will - simply ignore this keyword if it cannot be read. - - - added test for 'WIN32' as well as '__WIN32__' in fitsio2.h, - eval.l and eval_l.c in a preprocessor statement. - - - changed definition of strcasecmp and strncasecmp in fitsio2.h, - eval.l and eval_l.c to conform to the function prototypes under - the Alpha VMS v7.1 compiler. - - - corrected the long function names in longnam.h for the new WCS - utility functions in wcssubs.c - -Version 2.029 - 11 Feb 1999 - - - fixed bug in the way NANs and underflows were being detected on - VAX and Alpha VMS machines. - - - enhanced the filename parser to distinguish between a VMS-style - directory name (e.g. disk:[directory]myfile.fits) and a CFITSIO - filter specifier at the end of the name. - - - modified ffgthd to support the HIERARCH convention for keyword - names that are longer than 8 characters or contain characters - that would be illegal in standard FITS keyword names. - - - modified the include statements in grparser.c so that malloc.h - and memory.h are only included on the few platforms that really - need them. - - - modified the file_read routine in drvrfile.c to ignore the last - record in the FITS file it it only contains a single character that - is equal to 0, 10 or 32. Text editors sometimes append a character - like this to the end of the file, so CFITSIO will ignore it and - treat it as if it had reached the end of file. - - - minor modifications to fitsio.h to help support the ROOT environment. - - - installed new version of group.c and group.h; the main change - is to support relative paths (e.g. "../filename") in the URLs - - - modified the histogramming routines so that it looks for the - default preferred column axes in a keyword of the form - CPREF = 'Xcol, Ycol' - instead of separate keywords of the form - CPREF1 = 'Xcol' - CPREF2 = 'Ycol' - - - fixed bug so that if the binning spec is just a single integer, - as in [bin 4] then this will be interpreted as meaning to make - a 2D histogram using the preferred or default axes, with the - integer taken as the binning factor in both axes. - -Version 2.028 - 27 Jan 1999 - - - if the TNULLn keyword value was outside the range of a 'I' or 'B' - column, an overflow would occur when setting the short or char - to the TNULLn value, leading to incorrect values being flagged as - being undefined. This has been fixed so that CFITSIO will ignore - TNULLn values that are beyond the range of the column data type. - - - changed a few instances of the string {"\0"} to {'\0'} in the - file groups.c - - - installed new version of the grparser.c file from the ISDC - - - added new WCS support routines (in wcssub.c) which make it easier - to call Doug Mink's WCSlib routines for converting between plate - and sky coordinates. The CFITSIO routines themselves never - call a WCSlib routine, so CFITSIO is not dependent on WCSlib. - - - modified ffopen so that if you use the extended filename - syntax to both select rows in a table and then bin columns into - a histogram, then CFITSIO will simply construct an array listing - the good row numbers to be used when making the histogram, - instead of making a whole new temporary FITS file containing - the selected rows. - - - modified ffgphd which parses the primary array header keywords - when opening a file, to not choke on minor format errors in - optional keywords. Otherwise, this prevents CFITSIO from - even opening the file. - - - changed a few more variable declarations in compress.c from global - to static. - -Version 2.027 - 12 Jan 1999 - - - modified the usage of the output filename specifier so that it, - a) gives the name of the binned image, if specified, else, - b) gives the name of column filtered and/or row filtered table, if - specified, else - c) is the name for a local copy of the ftp or http file, else, - d) is the name for the local uncompressed version of the compressed - FITS file, else, - e) the output filename is ignored. - - - fixed minor bug in ffcmps, when comparing 2 strings while using - a '*' wild card character. - - - fixed bug in ftgthd that affected cases where the template string - started with a minus sign and contained 2 tokens (to rename a - keyword). - - - added support for the HIERARCH keyword convention for reading - and writing keywords longer than 8 characters or that contain - ASCII characters not allowed in normal FITS keywords. - - - modified the extended filename syntax to support opening images - that are contained in a single cell of a binary table with syntax: - filename.fits[extname; col_name(row_expression)] - -Version 2.026 - 23 Dec 1998 - - - modified the group parser to: - a) support CFITSIO_INCLUDE_FILES environment variable, which can - point to the location of template files, and, - b) the FITS file parameter passed to the parser no longer has to point - to an empty file. If there are already HDUs in the file, then the - parser appends new HDUs to the end of the file. - - - make a small change to the drvrnet.c file to accommodate creating - a static version of the CFITSIO library. - - - added 2 new routines to read consecutive bits as an unsigned integer - from a Bit 'X' or Byte 'B' column (ffgcxui and ffgcxuk). - - - modified the logic for determining histogram boundaries in ffhisto - to add one more bin by default, to catch values that are right on - the upper boundary of the histogram, or are in the last partial bin. - - - modified cfitsio2.h to support the new Solaris 7 64-bit mode operating - system. - - - Add utility routine, CFits2Unit, to the Fortran wrappers which searches - the gFitsFiles array for a fptr, returning its element (Fortran unit - number), or allocating a new element if one doesn't already - exists... for C calling Fortran calling CFITSIO. - - - modified configure so that it does not use the compiler optimizer - when using gcc 2.8.x on Linux - - - (re)added the fitsio.* documentation files that describe the - Fortran-callable FITSIO interface to the C routines. - - - modified the lexical parser in eval_f.c to fix bug in null detections - and bug in ffsrow when nrows = 0. - - - modified ffcalc so that it creates a TNULLn keyword if appropriate - when a new column is created. Also fixed detection of OVERFLOWs - so that it ignores null values. - - - added hyperbolic trig and rounding functions to - the lexical parser in the eval* files. - - - improved error message that gets written when the group number is - out of range when reading a 'random groups' array. - - - added description of shared memory, grouping, and template parsing - error messages to ffgerr and to the User's Guide. Moved the error - code definitions from drvsmem.h to fitsio.h. - - - modified grparser.c to compile correctly on Alpha/OSF machines - - - modified drvrnet.c to eliminate compiler warnings - - - Modified Makefile.in to include targets for building all the sample - programs that are included with CFITSIO. - -Version 2.025 - 1 Dec 1998 - - - modified ffgphd and ffgtbp so that they ignores BLANK and TNULLn keywords - that do not have a valid integer value. Also, any error while reading - the BSCALE, BZERO, TSCALn, or TZEROn keywords will be ignored. - Previously, CFITSIO would have simply refused to read an HDU that had - such an invalid keyword. - - - modified the parser in eval_f.c to accept out of order times in GTIs - - - updated cfitsio_mac.sit.hqx to fix bad target parameters for Mac's - speed test program - - - modified template parser in grparser.c to: 1) not write GRPNAME keyword - twice, and 2) assign correct value for EXTVERS keyword. - - - fixed minor bugs in group.c; mainly would only affect users of the - INTEGRAL Data Access Layer. - - - temporarily removed the prototype for ffiwcs from fitsio.h until - full WCS support is added to CFITSIO in the near future. - - - modified the HTTP driver to send a User-Agent string: - HEASARC/CFITSIO/ - - - declared local variables in compress.c as 'static' to avoid - conflicts with other libraries. - -Version 2.024 - 9 Nov 1998 - - - added new function fits_url_type which returns the driver prefix string - associated with a particular FITS file pointer. - -Version 2.023 - 1 Nov 1998 - first full release of CFITSIO 2.0 - - - slightly modified the way real keyword values are formatted, to ensure - that it includes a decimal point. E.g., '1.0E-09' instead of '1E-09' - - - added new function to support template files when creating new FITS files. - - - support the TCROTn WCS keyword in tables, when reading the WCS keywords. - - - modified the iterator to support null values in logical columns in - binary tables. - - - fixed bug in iterator to support null values in integer columns in - ASCII tables. - - - changed the values for FLOATNULLVALUE and DOUBLENULLVALUE to make them - less likely to duplicate actual values in the data. - - - fixed major bug when freeing memory in the iterator function. It caused - mysterious crashes on a few platforms, but had no effect on most others. - - - added support for reading IRAF format image (.imh files) - - - added more error checking to return an error if the size of the FITS - file exceeds the largest value of a long integer (2.1 GB on 32-bit - platforms). - - - CFITSIO now will automatically insert space for additional table rows - or add space to the data heap, if one writes beyond the current end - of the table or heap. This prevents any HDUs which might follow - the current HDU from being overwritten. It is thus no longer necessary - to explicitly call fits_insert_rows before writing new rows of data - to the FITS file. - - - CFITSIO now automatically keeps track of the number of rows that have - been written to a FITS table, and updates the NAXIS2 keyword accordingly - when the table is closed. It is no longer necessary for the application - program to updated NAXIS2. - - - When reading from a FITS table, CFITSIO will now return an error if the - application tries to read beyond the end of the table. - - - added 2 routines to get the number of rows or columns in a table. - - - improved the undocumented feature that allows a '20A' column to be - read as though it were a '20B' column by fits_read_col_byt. - - - added overflow error checking when reading keywords. Previously, the - returned value could be silently truncated to the maximum allowed value - for that data type. Now an error status is returned whenever an - overflow occurs. - - - added new set of routines dealing with hierarchical groups of files. - These were provided by Don Jennings of the INTEGRAL Science Data Center. - - - added new URL parsing routines. - - - changed the calling sequence to ffghad (get HDU address) from - ffghad(fitsfile *fptr, > long *headstart, long *dataend) to - ffghad(fitsfile *fptr, > long *headstart, long datastart, - long *dataend, int *status) - - - major modification to support opening the same FITS file more - than once. Now one can open the same file multiple times and - read and write simultaneously to different HDUs within the file. - fits_open_file automatically detects if the file is already opened. - - - added the ability to clobber/overwrite an existing file - with the same name when creating a new output file. Just - precede the output file name with '!' (an exclamation mark) - - - changed the ffpdat routine which writes the DATE keyword - to use the new 'YYYY-MM-DDThh:mm:ss' format. - - - added several new routines to create or parse the new date/time - format string. - - - changed ifdef for DECFortran in f77_wrap.h and f77_wrap1.c: - expanded to recognize Linux/Alpha - - - added new lexical parsing routines (from Peter Wilson): - eval_l.c, eval_y.c, eval_f.c, eval_defs.h, and eval_tab.h. - These are used when doing on-the-fly table row selections. - - - added new family of routines to support reading and writing - 'unsigned int' data type values in keywords, images or tables. - - - restructured all the putcol and getcol routines to provide - simpler and more robust support for machines which have - sizeof(long) = 8. Defined a new datatype INT32BIT which is - always 32 bits long (platform independent) and is used internally - in CFITSIO when reading or writing BITPIX = 32 images or 'J' - columns. This eliminated the need for specialize routines like - ffswaplong, ffunswaplong, and ffpacklong. - - - overhauled cfileio.c (and other files) to use loadable drivers for - doing data I/O to different devices. Now CFITSIO support network - access to ftp:// and http:// files, and to shared memory files. - - - removed the ffsmem routine and replaced it with ffomem. This will - only affect software that reads an existing file in core memory. - (written there by some other process). - - - modified all the ffgkn[] routines (get an array of keywords) so - that the 'nfound' parameter is = the number of keywords returned, - not the highest index value on the returned keywords. This makes - no difference if the starting index value to look for = 1. - This change is not backward compatible with previous versions - of CFITSIO, but is the way that FITSIO behaved. - - - added new error code = 1 for any application error external - to CFITSIO. Also reports "unknown error status" if the - value doesn't match a known CFITSIO error. - -Version 1.42 - 30 April 1998 (included in FTOOLS 4.1 release) - - - modified the routines which read a FITS float values into - a float array, or read FITS double values into a double array, - so that the array value is also explicitly set in addition - to setting the array of flag values, if the FITS value is a NaN. - This ensures that no NaN values get passed back to the calling - program, which can cause serious problems on some platforms (OSF). - - - added calls to ffrdef at the beginning of the insert - or delete rows or columns routines in editcol.c to make sure - that CFITSIO has correctly initialized the HDU information. - - - added new routine ffdrws to delete a list of rows in a table - - - added ffcphd to copy the header keywords from one hdu to another - - - made the anynul parameter in the ffgcl* routines optional - by first checking to see if the pointer is not null before - initializing it. - - - modified ffbinit and ffainit to ignore minor format - errors in header keywords so that cfitsio can at least - move to an extension that contains illegal keywords. - - - modified all the ffgcl* routines to simply return without - error if nelem = 0. - - - added check to ffclose to check the validity of the fitsfile - pointer before closing it. This should prevent program crashes - when someone tries to close the same file more than once. - - - replaced calls to strcmp and strncmp with macros FSTRCMP and - FSTRNCMP in a few places to improve performance when reading - header keywords (suggested by Mike Noble) - - Bug Fixes: - - - fixed typo in macro definition of error 504 in the file fitsio.h. - - - in ffopen, reserved space for 4 more characters in the input - file name in case a '.zip' suffix needs to be added. - - - small changes to ffpclx to fix problems when writing bit (X) data - columns beyond the current end of file. - - - fixed small bug in ffcrhd where a dummy pointer was not initialized - - - initialized the dummy variable in ffgcfe and ffgcfd which - was causing crashes under OSF in some cases. - - - increased the length of the allocated string ffgkls by 2 - to support the case of reading a numeric keyword as a string - which doesn't have the enclosing quote characters. - -Version 1.4 - 6 Feb 1998 - - - major restructuring of the CFITSIO User's Guide - - - added the new 'iterator' function. The fortran wrapper is - in f77_iter.c for now. - - - enhanced ffcrtb so that it writes a dummy primary array - if none currently exists before appending the table. - - - removed the ffgcl routine and replaced it with ffgcvl - - - modified ffpcnl to just take a single input null value instead - of an entire array of null value flags. - - - modified ffcmps and ffgnxk so that, for example, the string 'rate' - is not considered a match to the string 'rate2', and 'rate*' - is a match to the string 'rate'. - - - modified ffgrsz to also work with images, in which case - it returns the optimum number of pixels to process at - one time. - - - modified ffgthd to support null valued keywords - - - added a new source file 'f77_wrap.c' that includes all the - Fortran77 wrapper routines for calling CFITSIO. This will - eventually replace the Fortran FITSIO library. - - - added new routines: - ffppn - generic write primary array with null values - ffpprn - write null values to primary array - - ffuky - 'update' a keyword value, with any specified datatype. - - ffrprt - write out report of error status and error messages - ffiter - apply a user function iteratively to all the rows of a table - ffpkyc - write complex-valued keyword - ffpkym - write double complex-valued keyword - ffpkfc - write complex-valued keyword in fixed format - ffpkfm - write double complex-valued keyword in fixed format - - ffgkyc - read complex-valued keyword - ffgkym - read double complex-valued keyword - - ffmkyc - modify complex-valued keyword - ffmkym - modify double complex-valued keyword - ffmkfc - modify complex-valued keyword in fixed format - ffmkfm - modify double complex-valued keyword in fixed format - - ffukyc - update complex-valued keyword - ffukym - update double complex-valued keyword - ffukfc - update complex-valued keyword in fixed format - ffukfm - update double complex-valued keyword in fixed format - - ffikyc - insert complex-valued keyword - ffikym - insert double complex-valued keyword - ffikfc - insert complex-valued keyword in fixed format - ffikfm - insert double complex-valued keyword in fixed format - - ffpktp - write or modify keywords using ASCII template file - ffcpcl - copy a column from one table to another - ffcpky - copy an indexed keyword from one HDU to another - ffpcnl - write logical values, including nulls, to binary table - ffpcns - write string values, including nulls, to table - ffmnhd - move to HDU with given exttype, EXTNAME and EXTVERS values - ffthdu - return the total number of HDUs in the file - ffghdt - return the type of the CHDU - ffflnm - return the name of the open FITS file - ffflmd - return the mode of the file (READONLY or READWRITE) - - - modified ffmahd and ffmrhd (to move to a new extension) so that - a null pointer may be given for the returned HDUTYPE argument. - - - worked around a bug in the Mac CWpro2 compiler by changing all - the statements like "#if BYTESWAPPED == TRUE" to "if BYTESWAPPED". - - - modified ffitab (insert new ASCII table) to allow tables with - zero number of columns - - - modified Makefile.in and configure to define the -Dg77Fortran - CFLAGS variable on Linux platforms. This is needed to - compile the new f77_wrap.c file (which includes cfortran.h) - - Bug Fixes: - - - fixed small bug in ffgrz (get optimum row size) which sometimes - caused it to return slightly less than the maximum optimum size. - This bug would have done no harm to application programs. - - - fixed bug in ffpclk and ffgclk to add an 'else' case - if size of int is not equal to size of short or size of long. - - - added test to ffgkls to check if the input string is not null before - allocating memory for it. - -Version 1.32 - 21 November 1997 (internal release only) - - - fixed bug in the memory deallocation (free) statements - in the ffopen routine in the cfileio.c file. - - - modified ffgphd to tolerate minor violations of the FITS - standard in the format of the XTENSION = 'IMAGE ' - keyword when reading FITS files. Extra trailing spaces - are now allowed in the keyword value. (FITS standard - will be changed so that this is not a violation). - -Version 1.31 - 4 November 1997 (internal release only) - - Enhancements: - - - added support for directly reading compressed FITS files - by copying the algorithms from the gzip program. This - supports the Unix compress, gzip and pkzip algorithms. - - - modified ffiimg, ffitab, and ffibin (insert HDUs into - a FITS file) so that if the inserted HDU is at the end of - the FITS file, then it simply appends a new empty HDU - and writes the required keywords. This allows space - to be reserved for additional keywords in the header - if desired. - - - added the ffchfl and ffcdfl routines to check the header and - data fill values, for compatibility with the Fortran FITSIO - library. - - - added the ffgsdt routine to return the system date - for compatibility with the Fortran FITSIO library. - - - added a diagnostic error message (written to the error stack) - if the routines that read data from image or column fail. - - - modified ffgclb so that it simply copies the bytes from - an ASCII 'nA' or 'An' format column into the user's byte - array. Previously, CFITSIO would return an error when - trying to read an 'A' column with ffgclb. - - - modified ffpclb so that it simply copies the input array - of bytes to an ASCII 'nA' or 'An' format column. - Previously, CFITSIO would return an error when - trying to write to an 'A' column with ffpclb. - - Bug Fixes: - - - ffgkls was allocating one too few bytes when reading continued - string keyword values. - - - in testprog.c added code to properly free the memory that - had been allocated for string arrays. - - - corrected typographical errors in the User's Guide. - -Version 1.30 - 11 September 1997 - - - major overhaul to support reading and writing FITS files - in memory. The new routines fits_set_mem_buff and - fits_write_mem_buff have been added to initialize and - copy out the memory buffer, respectively. - - - added support for reading FITS files piped in on 'stdin' - and piped out on 'stdout'. Just specify the file name as '-' - when opening or creating the FITS file. - - - added support for 64-bit SGI IRIX machines. This required - adding routines to pack and unpack 32-bit integers into - 64-bit integers. - - - cleaned up the code that supports G_FLOAT and IEEE_FLOAT - on Alpha VMS systems. Now, the type of float is determined - at compile time, not run time. - - Bug Fixes: - - - replaced the malloc calls in the error message stack routines - with a static fixed size array. The malloc's cause more - problems than they solved, and were prone to cause memory - leaks if users don't clear the error message stack when - closing the FITS file. - - - when writing float or double keywords, test that the value - is not a special IEEE value such as a NaN. Some - compilers would write the string 'NaN' in this case into - the output value string. - - - fixed bug in ffiblk, to ignore EOF status return if it is - inserting blocks at the end of the file. - - - removed the 'l' from printf format string that is constructed - in the ffcfmt routine. This 'l' is non-standard and causes problems - with the Metrowerks compiler on a Mac. - - - the default null value in images was mistakenly being set - equal to NO_NULL = 314, rather than NULL_UNDEFINED = 1234554321 - in the ffgphd routine. - - - check status value in ffgkls to make sure the keyword exists - before allocating memory for the value string. - - - fixed the support for writing and reading unsigned long integer - keyword values in ffpky and ffgky by internally treating - the values as doubles. This required changes to ffc2r and - ffc2d as well. - - - added explicit cast to 'double' in one place in putcolb.c and - 6 places in pubcolui.c, to get rid of warning messages issued - by one compiler. - - - in ffbinit and ffainit, it is necessary to test that tfield > 0 - before trying to allocate memory with calloc. Otherwise, some - compilers return a null pointer which CFITSIO interprets to - mean the memory allocation failed. - - - had to explicitly cast the null buffer pointer to a char - pointer (cptr = (char *)buffer;) in 4 places in the buffers.c - file to satisfy a picky C++ compiler. - - - changed the test for an ALPHA VMS system to see if - '__VMS' is defined, rather than 'VMS'. The latter - is not defined by at least one C++ compiler. - - - modified ffpcls so that it can write a null string to - a variable length string column, without going into - an infinite loop. - - - fixed bug in ffgcfl that caused the 'next' variable to be - incremented twice. - - - fixed bug in ffgcpr that caused it write 2x the number of - complex elements into the descriptor when writing to - a complex or double complex variable length array column. - - - added call to ffrdef at the end of ffrsim to ensure that - the internal structures are updated to correspond to the - modified header keywords - -Version 1.25 - 7 July 1997 - - - improved the efficiency of the ffiblk routine, when inserting - more than one block into the file. - - - fixed bug in ffwend that in rare instances caused the beginning - of the following extension to be overwritten by blank fill. - - - added new routine to modify the size of an existing primary - array or image extension: fits_resize_img/ffrsim. - - - added support for null-valued keywords, e.g., keywords that - have no defined value. These keywords have an equal sign and - space in columns 9-10, but have not value string. Example: - KEYNAME = / null-valued keyword - Support for this feature required the following changes: - - modified ffpsvc to return a null value string without error - - modified ffc2[ilrd] to return error VALUE_UNDEFINED in this case - - modified ffgkn[sljed] to continue reading additional keywords - even if one or more keywords have undefined values. - - added 4 new routines: ffpkyu, ffikyu, ffmkyu, ffukyu to - write, insert, modify, or update an undefined keyword - - - a new makefile.os2 file was added, for building CFITSIO - on OS/2 systems. - - - modified ffgtkn so that if it finds an unexpected keyword - name, the returned error status = BAD_ORDER instead of - NOT_POS_INT. - - - added 2 new routines, fits_write_key_unit/ffpunt and - fits_read_key_unit/ffgunt to write/read the physical - units of a keyword value. These routines use a local - FITS convention for storing the units in square brackets - following the '/' comment field separator, as in: - VELOCITY= 12 / [km/s] orbit speed - The testprog.c program was modified to test these - new routines. - - - in the test of Alpha OSF/1 machines in fitsio2.h, - change 'defined(unix)' to 'defined(__unix__)' which - appears to be a more robust test. - - - remove test for linux environment variable from fitsio2.h - -Version 1.24 - 2 May 1997 - - - fixed bug in ffpbyt that incorrectly computed the current - location in the FITS file when writing > 10000 bytes. - - - changed the datatype of the 'nbytes' parameter in ffpbyt - from 'int' to 'long'. Made corresponding datatype change - to some internal variables in ffshft. - - - changed '(unsigned short *)' to '(short *)' in getcolui.c, and - changed '(unsigned long *)' to '(long *)' in getcoluj.c, to - work around problem with the VAX/VMS cc compiler. - -Version 1.23 - 24 April 1997 - - - modified ffcins and ffdins (in editcol.c) to simply return - without error if there are no (zero) rows in the table. - -Version 1.22 - 18 April 1997 - - - fixed bug in ffgcpr that caused it to think that all values were - undefined in ASCII tables columns that have TNULLn = ' ' - (i.e., the TNULLn keyword value is a string of blanks. - - - fixed bug in the ffgcl[bdeijk,ui,uj] family of routines - when parsing a numeric value in an ASCII table. The - returned values would have the decimal place shifted to - the left if the table field contained an explicit decimal - point followed by blanks. Example: in an F5.2 column, - the value '16. ' would be returned as 0.16. If the - trailing zeros were present, then cfitsio returned the - correct value (e.g., '16.00' returns 16.). - - - fixed another bug in the ffgcl[bdeijk,ui,uj] family of routines - that caused them to misread values in an ASCII table in rows - following an undefined value when all the values were read - at once in a single call to the routine. - -Version 1.21 - 26 March 1997 - - - added general support for reading and writing unsigned integer - keywords, images, and binary table column values. - - - fixed bug in the way the column number was used in ffgsve and - similar routines. This bug caused cfitsio to read (colnum - 1) - rather than the desired column. - - - fixed a bug in ftgkls that prevented it from reading more than one - continuation line of a long string keyword value. - - - fixed the definition of fits_write_longwarn in longnam.h - -Version 1.20 - 29 Jan 1997 - - - when creating a binary table with variable length vector columns, if the - calling routine does not specify a value for the maximum length of - the vector (e.g., TFORMn = '1PE(400)') then cfitsio will automatically - calculate the maximum value and append it to the TFORM value - when the binary table is first closed. - - - added the set of routines to do coordinate system transformations - - - added support for wildcards ('*', '?', and '#') in the input - keyword name when reading, modifying, or deleting keywords. - - - added new general keyword reading routine, ffgnxk, to return - the next keyword whose name matches a list of template names, - but does not match any names on a second template list. - - - modified ftgrec so that it simply moves to the beginning - of the header if the input keyword number = 0 - - - added check in ffdelt to make sure the input fits file pointer is - not already null - - - added check in ffcopy to make sure the output HDU does not - already contain any keywords (it must be empty). - - - modified ffgcls so that it does not test if each string column - value equals the null string value if the null string value - is longer than the width of the column. - - - fixed bug in ftgtdm that caused it to fail if the TDIMn - keyword did not exist in the FITS file - - - modified testprog.c to include tests of keyword wildcards - and the WCS coordinate transformation routines. - - - added a test for 'EMX' in fitsio2.h so that cfitsio builds - correctly on a PC running OS/2. - -Version 1.11 - 04 Dec 1996 - - - modified the testprog.c program that is included with the - distribution, so that the output FITS file is identical to - that produced by the Fortran FITSIO test program. - - - changed all instances of the 'extname' variable to 'extnm' - to avoid a conflict with the -Dextname switch in cfortran.h - on HP machines. - - - in all the routines like ffi4fi1, which convert an array - of values to integers just prior to writing them to the FITS - file, the integer value is now rounded to the nearest integer - rather than truncated. (ffi4fi1, ffi4fi2, ffi4fi4, etc) - - - changed ffgcfl (and hence ffgcl) so that the input value - of the logical array element is not changed if the corresponding - FITS value is undefined. - - - in ffgacl, the returned value of TBCOL was off by 1 (too small) - - - fixed the comment of EXTNAME keyword to read 'binary table' - instead of 'ASCII table' in the header of binary tables. - -Version 1.101 - 17 Nov 1996 - - - Made major I/O efficiency improvements by adding internal buffers - rather than directly reading or writing to disk. Access to - columns in binary tables is now 50 - 150 times faster. Access to - FITS image is also slightly faster. - - - made significant speed improvements when reading numerical data - in FITS ASCII tables by writing my own number parsing routines - rather than using the sscanf C library routine. This change - requires that the -lm argument now be included when linking - a program that calls cfitsio (under UNIX). - - - regrouped the source files into logically related sets of routines. - The Makefile now runs much faster since every single routine is - not split into a separate file. - - - now use the memcpy function, rather than a 'for' loop in several - places for added efficiency - - - redesigned the low-level binary table read and write routines - (ffpbytoff and ffgbytoff) for greater efficiency. - - - added a new error status: 103 = too many open FITS files. - - - added a 'extern "C"' statement around the function prototypes - in fitsio.h, to support use of cfitsio by C++ compilers. - - - fixed routines for writing or reading fixed-length substrings - within a binary table ASCII column, with TFORM values of - of the form 'rAw' where 'r' is the total width of the ASCII - column and 'w' is the width of a substring within the column. - - - no longer automatically rewrite the END card and following fill - values if they are already correct. - - - all the 'get keyword value and comment' routines have been changed - so that the comment is not returned if the input pointer is NULL. - - - added new routine to return the optimum number of tables rows - that should be read or written at one time for optimum efficiency. - - - modified the way numerical values in ASCII tables are parsed so - that embedded spaces in the value are ignored, and implicit - decimal points are now supported. (e.g, the string '123E 12' - in a 'E10.2' format column will be interpreted as 1.23 * 10**12). - - - modified ffpcl and ffgcl to support binary table columns of - all datatype (added logical, bit, complex, and double complex) - - - when writing numerical data to ASCII table columns, the ffpcl_ - routines now return an overflow error if a value is too large - to be expressed in the column format. - - - closed small memory leak in ffpcls. - - - initialized the 'incre' variable in ffgcpr to eliminate compiler warning. - -Version 1.04 - 17 Sept 1996 - - - added README.MacOS and cfitsio_mac.sit.hqx to the distribution - to support the Mac platforms. - - - fixed bug in ffpdfl that caused an EOF error (107) when a program - creates a new extension that is an exact multiple of 2880 bytes long, - AND the program does not write a value to the last element - in the table or image. - - - fixed bug in all the ffgsf* and ffgcv* routines which caused - core dumps when reading null values in a table. - -Version 1.03 - 20 August 1996 - - - added full support for reading and writing the C 'int' - data type. This was a problem on Alpha/OSF where short, - int, and long datatypes are 2, 4, and 8 bytes long, respectively. - - - cleaned up the code in the byte-swapping routines. - - - renamed the file 'longname.h' to 'longnam.h' to avoid conflict - with a file with the same name in another unrelated package. - -Version 1.02 - 15 August 1996 - - - ffgtbp was not correctly reading the THEAP keyword, hence would - not correctly read variable length data in binary tables if - the heap was not at the default starting location (i.e., - starting immediately after the fixed length table). - - - now force the cbuff variable in ffpcl_ and ffgcl_ to be - aligned on a double word boundary. Non-alignment can - cause program to crash on some systems. - -Version 1.01 - 12 August 1996 - - - initial public release diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.doc b/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.doc deleted file mode 100644 index 72f2124f2..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.doc +++ /dev/null @@ -1,6615 +0,0 @@ - FITSIO - An Interface to FITS Format Files for Fortran Programmers - - William D Pence, HEASARC, NASA/GSFC - Version 3.0 - - -[Note: This file contains various formatting command symbols in the first -column which are used when generating the LATeX version of this document.] - -*I. Introduction - -This document describes the Fortran-callable subroutine interface that -is provided as part of the CFITSIO library (which is written in ANSI -C). This is a companion document to the CFITSIO User's Guide which -should be consulted for further information about the underlying -CFITSIO library. In the remainder of this document, the terms FITSIO -and CFITSIO are interchangeable and refer to the same library. - -FITSIO/CFITSIO is a machine-independent library of routines for reading -and writing data files in the FITS (Flexible Image Transport System) -data format. It can also read IRAF format image files and raw binary -data arrays by converting them on the fly into a virtual FITS format -file. This library was written to provide a powerful yet simple -interface for accessing FITS files which will run on most commonly used -computers and workstations. FITSIO supports all the features described -in the official definition of the FITS format and can read and -write all the currently defined types of extensions, including ASCII -tables (TABLE), Binary tables (BINTABLE) and IMAGE extensions. The -FITSIO subroutines insulate the programmer from having to deal with the -complicated formatting details in the FITS file, however, it is assumed -that users have a general knowledge about the structure and usage of -FITS files. - -The CFITSIO package was initially developed by the HEASARC (High Energy -Astrophysics Science Archive Research Center) at the NASA Goddard Space -Flight Center to convert various existing and newly acquired -astronomical data sets into FITS format and to further analyze data -already in FITS format. New features continue to be added to CFITSIO -in large part due to contributions of ideas or actual code from users -of the package. The Integral Science Data Center in Switzerland, and -the XMM/ESTEC project in The Netherlands made especially significant -contributions that resulted in many of the new features that appeared -in v2.0 of CFITSIO. - -The latest version of the CFITSIO source code, documentation, and -example programs are available on the World-Wide Web or via anonymous -ftp from: -- - http://heasarc.gsfc.nasa.gov/fitsio - ftp://legacy.gsfc.nasa.gov/software/fitsio/c -- -\newpage -Any questions, bug reports, or suggested enhancements related to the CFITSIO -package should be sent to the FTOOLS Help Desk at the HEASARC: -- - http://heasarc.gsfc.nasa.gov/cgi-bin/ftoolshelp -- - -This User's Guide assumes that readers already have a general -understanding of the definition and structure of FITS format files. -Further information about FITS formats is available from the FITS Support -Office at {\tt http://fits.gsfc.nasa.gov}. In particular, the -'FITS Standard' gives the authoritative definition of the FITS data -format. Other documents available at that Web site -provide additional historical background -and practical advice on using FITS files. - -The HEASARC also provides a very sophisticated FITS file analysis -program called `Fv' which can be used to display and edit the contents -of any FITS file as well as construct new FITS files from scratch. -Fv is freely available for -most Unix platforms, Mac PCs, and Windows PCs. -CFITSIO users may also be interested in the FTOOLS package of programs -that can be used to manipulate and analyze FITS format files. -Fv and FTOOLS are available from their respective Web sites at: -- - http://fv.gsfc.nasa.gov - http://heasarc.gsfc.nasa.gov/ftools -- - - -*II. Creating FITSIO/CFITSIO - -**A. Building the Library - -To use the FITSIO subroutines one must first build the CFITSIO library, -which requires a C compiler. gcc is ideal, or most other ANSI-C -compilers will also work. The CFITSIO code is contained in about 40 C -source files (*.c) and header files (*.h). On VAX/VMS systems 2 -assembly-code files (vmsieeed.mar and vmsieeer.mar) are also needed. - -The Fortran interface subroutines to the C CFITSIO routines are located -in the f77\_wrap1.c, through f77\_wrap4.c files. These are relatively simple -'wrappers' that translate the arguments in the Fortran subroutine into -the appropriate format for the corresponding C routine. This -translation is performed transparently to the user by a set of C macros -located in the cfortran.h file. Unfortunately cfortran.h does not -support every combination of C and Fortran compilers so the Fortran -interface is not supported on all platforms. (see further notes below). - -A standard combination of C and Fortran compilers will be assumed by -default, but one may also specify a particular Fortran compiler by -doing: -- - > setenv CFLAGS -DcompilerName=1 -- -(where 'compilerName' is the name of the compiler) before running -the configure command. The currently recognized compiler -names are: -- - g77Fortran - IBMR2Fortran - CLIPPERFortran - pgiFortran - NAGf90Fortran - f2cFortran - hpuxFortran - apolloFortran - sunFortran - CRAYFortran - mipsFortran - DECFortran - vmsFortran - CONVEXFortran - PowerStationFortran - AbsoftUNIXFortran - AbsoftProFortran - SXFortran -- -Alternatively, one may edit the CFLAGS line in the Makefile to add the -'-DcompilerName' flag after running the './configure' command. - -The CFITSIO library is built on Unix systems by typing: -- - > ./configure [--prefix=/target/installation/path] - [--enable-sse2] [--enable-ssse3] - > make (or 'make shared') - > make install (this step is optional) -- -at the operating system prompt. The configure command customizes the -Makefile for the particular system, then the `make' command compiles the -source files and builds the library. Type `./configure' and not simply -`configure' to ensure that the configure script in the current directory -is run and not some other system-wide configure script. The optional -'prefix' argument to configure gives the path to the directory where -the CFITSIO library and include files should be installed via the later -'make install' command. For example, -- - > ./configure --prefix=/usr1/local -- -will cause the 'make install' command to copy the CFITSIO libcfitsio file -to /usr1/local/lib and the necessary include files to /usr1/local/include -(assuming of course that the process has permission to write to these -directories). - -The optional --enable-sse2 and --enable-ssse3 flags will cause configure to -attempt to build CFITSIO using faster byte-swapping algorithms. -See the "Optimizing Programs" section of this manual for -more information about these options. - -By default, the Makefile will be configured to build the set of Fortran-callable -wrapper routines whose calling sequences are described later in this -document. - -The 'make shared' option builds a shared or dynamic version of the -CFITSIO library. When using the shared library the executable code is -not copied into your program at link time and instead the program -locates the necessary library code at run time, normally through -LD\_LIBRARY\_PATH or some other method. The advantages of using a shared -library are: -- - 1. Less disk space if you build more than 1 program - 2. Less memory if more than one copy of a program using the shared - library is running at the same time since the system is smart - enough to share copies of the shared library at run time. - 3. Possibly easier maintenance since a new version of the shared - library can be installed without relinking all the software - that uses it (as long as the subroutine names and calling - sequences remain unchanged). - 4. No run-time penalty. -- -The disadvantages are: -- - 1. More hassle at runtime. You have to either build the programs - specially or have LD_LIBRARY_PATH set right. - 2. There may be a slight start up penalty, depending on where you are - reading the shared library and the program from and if your CPU is - either really slow or really heavily loaded. -- - -On HP/UX systems, the environment variable CFLAGS should be set -to -Ae before running configure to enable "extended ANSI" features. - -It may not be possible to statically link programs that use CFITSIO on -some platforms (namely, on Solaris 2.6) due to the network drivers -(which provide FTP and HTTP access to FITS files). It is possible to -make both a dynamic and a static version of the CFITSIO library, but -network file access will not be possible using the static version. - -On VAX/VMS and ALPHA/VMS systems the make\_gfloat.com command file may -be executed to build the cfitsio.olb object library using the default -G-floating point option for double variables. The make\_dfloat.com and -make\_ieee.com files may be used instead to build the library with the -other floating point options. Note that the getcwd function that is -used in the group.c module may require that programs using CFITSIO be -linked with the ALPHA\$LIBRARY:VAXCRTL.OLB library. See the example -link line in the next section of this document. - -On Windows IBM-PC type platforms the situation is more complicated -because of the wide variety of Fortran compilers that are available and -because of the inherent complexities of calling the CFITSIO C routines -from Fortran. Two different versions of the CFITSIO dll library are -available, compiled with the Borland C++ compiler and the Microsoft -Visual C++ compiler, respectively, in the files -cfitsiodll\_2xxx\_borland.zip and cfitsiodll\_3xxx\_vcc.zip, where -'3xxx' represents the current release number. Both these dll libraries -contain a set of Fortran wrapper routines which may be compatible with -some, but probably not all, available Fortran compilers. To test if -they are compatible, compile the program testf77.f and try linking to -these dll libraries. If these libraries do not work with a particular -Fortran compiler, then it may be necessary to modify the file -"cfortran.h" to support that particular -combination of C and Fortran compilers, and then rebuild the CFITSIO -dll library. This will require, however, some expertise in -mixed language programming. - -CFITSIO should be compatible with most current ANCI C and C++ compilers: -Cray supercomputers are currently not supported. - -**B. Testing the Library - -The CFITSIO library should be tested by building and running -the testprog.c program that is included with the release. -On Unix systems type: -- - % make testprog - % testprog > testprog.lis - % diff testprog.lis testprog.out - % cmp testprog.fit testprog.std -- - On VMS systems, -(assuming cc is the name of the C compiler command), type: -- - $ cc testprog.c - $ link testprog, cfitsio/lib, alpha$library:vaxcrtl/lib - $ run testprog -- -The testprog program should produce a FITS file called `testprog.fit' -that is identical to the `testprog.std' FITS file included with this -release. The diagnostic messages (which were piped to the file -testprog.lis in the Unix example) should be identical to the listing -contained in the file testprog.out. The 'diff' and 'cmp' commands -shown above should not report any differences in the files. (There -may be some minor formatting differences, such as the presence or -absence of leading zeros, or 3 digit exponents in numbers, -which can be ignored). - -The Fortran wrappers in CFITSIO may be tested with the testf77 -program. On Unix systems the fortran compilation and link command -may be called 'f77' or 'g77', depending on the system. -- - % f77 -o testf77 testf77.f -L. -lcfitsio -lnsl -lsocket - or - % f77 -f -o testf77 testf77.f -L. -lcfitsio (under SUN O/S) - or - % f77 -o testf77 testf77.f -Wl,-L. -lcfitsio -lm -lnsl -lsocket (HP/UX) - or - % g77 -o testf77 -s testf77.f -lcfitsio -lcc_dynamic -lncurses (Mac OS-X) - - % testf77 > testf77.lis - % diff testf77.lis testf77.out - % cmp testf77.fit testf77.std -- -On machines running SUN O/S, Fortran programs must be compiled with the -'-f' option to force double precision variables to be aligned on 8-byte -boundaries to make the fortran-declared variables compatible with C. A -similar compiler option may be required on other platforms. Failing to -use this option may cause the program to crash on FITSIO routines that -read or write double precision variables. - -On Windows platforms, linking Fortran programs with a C library -often depends on the particular compilers involved. Some users have -found the following commands work when using the Intel Fortran compiler: -- -ifort /libs.dll cfitsio.lib /MD testf77.f /Gm - -or possibly, - -ifort /libs:dll cfitsio.lib /MD /fpp /extfpp:cfortran.h,fitsio.h - /iface:cvf testf77.f -- -Also note that on some systems the output listing of the testf77 -program may differ slightly from the testf77.std template if leading -zeros are not printed by default before the decimal point when using F -format. - -A few other utility programs are included with CFITSIO: -- - speed - measures the maximum throughput (in MB per second) - for writing and reading FITS files with CFITSIO - - listhead - lists all the header keywords in any FITS file - - fitscopy - copies any FITS file (especially useful in conjunction - with the CFITSIO's extended input filename syntax) - - cookbook - a sample program that performs common read and - write operations on a FITS file. - - iter_a, iter_b, iter_c - examples of the CFITSIO iterator routine -- - -The first 4 of these utility programs can be compiled and linked by typing -- - % make program_name -- - -**C. Linking Programs with FITSIO - -When linking applications software with the FITSIO library, several system libraries usually need to be specified on the link command line. On -Unix systems, the most reliable way to determine what libraries are required -is to type 'make testprog' and see what libraries the configure script has -added. The typical libraries that may need to be added are -lm (the math -library) and -lnsl and -lsocket (needed only for FTP and HTTP file access). -These latter 2 libraries are not needed on VMS and Windows platforms, -because FTP file access is not currently supported on those platforms. - -Note that when upgrading to a newer version of CFITSIO it is usually -necessary to recompile, as well as relink, the programs that use CFITSIO, -because the definitions in fitsio.h often change. - -**D. Getting Started with FITSIO - -In order to effectively use the FITSIO library as quickly as possible, -it is recommended that new users follow these steps: - -1. Read the following `FITS Primer' chapter for a brief -overview of the structure of FITS files. This is especially important -for users who have not previously dealt with the FITS table and image -extensions. - -2. Write a simple program to read or write a FITS file using the Basic -Interface routines. - -3. Refer to the cookbook.f program that is included with this release -for examples of routines that perform various common FITS file -operations. - -4. Read Chapters 4 and 5 to become familiar with the conventions and -advanced features of the FITSIO interface. - -5. Scan through the more extensive set of routines that are provided -in the `Advanced Interface'. These routines perform more specialized -functions than are provided by the Basic Interface routines. - -**E. Example Program - -The following listing shows an example of how to use the FITSIO -routines in a Fortran program. Refer to the cookbook.f program that -is included with the FITSIO distribution for examples of other -FITS programs. -- - program writeimage - -C Create a FITS primary array containing a 2-D image - - integer status,unit,blocksize,bitpix,naxis,naxes(2) - integer i,j,group,fpixel,nelements,array(300,200) - character filename*80 - logical simple,extend - - status=0 -C Name of the FITS file to be created: - filename='ATESTFILE.FITS' - -C Get an unused Logical Unit Number to use to create the FITS file - call ftgiou(unit,status) - -C create the new empty FITS file - blocksize=1 - call ftinit(unit,filename,blocksize,status) - -C initialize parameters about the FITS image (300 x 200 16-bit integers) - simple=.true. - bitpix=16 - naxis=2 - naxes(1)=300 - naxes(2)=200 - extend=.true. - -C write the required header keywords - call ftphpr(unit,simple,bitpix,naxis,naxes,0,1,extend,status) - -C initialize the values in the image with a linear ramp function - do j=1,naxes(2) - do i=1,naxes(1) - array(i,j)=i+j - end do - end do - -C write the array to the FITS file - group=1 - fpixel=1 - nelements=naxes(1)*naxes(2) - call ftpprj(unit,group,fpixel,nelements,array,status) - -C write another optional keyword to the header - call ftpkyj(unit,'EXPOSURE',1500,'Total Exposure Time',status) - -C close the file and free the unit number - call ftclos(unit, status) - call ftfiou(unit, status) - end -- - -**F. Legal Stuff - -Copyright (Unpublished--all rights reserved under the copyright laws of -the United States), U.S. Government as represented by the Administrator -of the National Aeronautics and Space Administration. No copyright is -claimed in the United States under Title 17, U.S. Code. - -Permission to freely use, copy, modify, and distribute this software -and its documentation without fee is hereby granted, provided that this -copyright notice and disclaimer of warranty appears in all copies. - -DISCLAIMER: - -THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, -EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, -ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY -IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE -DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE -SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY -DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR -CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY -CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, -CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY -PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED -FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR -SERVICES PROVIDED HEREUNDER." - -**G. Acknowledgments - -The development of many of the powerful features in CFITSIO was made -possible through collaborations with many people or organizations from -around the world. The following, in particular, have made especially -significant contributions: - -Programmers from the Integral Science Data Center, Switzerland (namely, -Jurek Borkowski, Bruce O'Neel, and Don Jennings), designed the concept -for the plug-in I/O drivers that was introduced with CFITSIO 2.0. The -use of `drivers' greatly simplified the low-level I/O, which in turn -made other new features in CFITSIO (e.g., support for compressed FITS -files and support for IRAF format image files) much easier to -implement. Jurek Borkowski wrote the Shared Memory driver, and Bruce -O'Neel wrote the drivers for accessing FITS files over the network -using the FTP, HTTP, and ROOT protocols. - -The ISDC also provided the template parsing routines (written by Jurek -Borkowski) and the hierarchical grouping routines (written by Don -Jennings). The ISDC DAL (Data Access Layer) routines are layered on -top of CFITSIO and make extensive use of these features. - -Uwe Lammers (XMM/ESA/ESTEC, The Netherlands) designed the -high-performance lexical parsing algorithm that is used to do -on-the-fly filtering of FITS tables. This algorithm essentially -pre-compiles the user-supplied selection expression into a form that -can be rapidly evaluated for each row. Peter Wilson (RSTX, NASA/GSFC) -then wrote the parsing routines used by CFITSIO based on Lammers' -design, combined with other techniques such as the CFITSIO iterator -routine to further enhance the data processing throughput. This effort -also benefited from a much earlier lexical parsing routine that was -developed by Kent Blackburn (NASA/GSFC). More recently, Craig Markwardt -(NASA/GSFC) implemented additional functions (median, average, stddev) -and other enhancements to the lexical parser. - -The CFITSIO iterator function is loosely based on similar ideas -developed for the XMM Data Access Layer. - -Peter Wilson (RSTX, NASA/GSFC) wrote the complete set of -Fortran-callable wrappers for all the CFITSIO routines, which in turn -rely on the CFORTRAN macro developed by Burkhard Burow. - -The syntax used by CFITSIO for filtering or binning input FITS files is -based on ideas developed for the AXAF Science Center Data Model by -Jonathan McDowell, Antonella Fruscione, Aneta Siemiginowska and Bill -Joye. See http://heasarc.gsfc.nasa.gov/docs/journal/axaf7.html for -further description of the AXAF Data Model. - -The file decompression code were taken directly from the gzip (GNU zip) -program developed by Jean-loup Gailly and others. - -Doug Mink, SAO, provided the routines for converting IRAF format -images into FITS format. - -Martin Reinecke (Max Planck Institute, Garching)) provided the modifications to -cfortran.h that are necessary to support 64-bit integer values when calling -C routines from fortran programs. The cfortran.h macros were originally developed -by Burkhard Burow (CERN). - -Julian Taylor (ESO, Garching) provided the fast byte-swapping algorithms -that use the SSE2 and SSSE3 machine instructions available on x86\_64 CPUs. - -In addition, many other people have made valuable contributions to the -development of CFITSIO. These include (with apologies to others that may -have inadvertently been omitted): - -Steve Allen, Carl Akerlof, Keith Arnaud, Morten Krabbe Barfoed, Kent -Blackburn, G Bodammer, Romke Bontekoe, Lucio Chiappetti, Keith Costorf, -Robin Corbet, John Davis, Richard Fink, Ning Gan, Emily Greene, Joe -Harrington, Cheng Ho, Phil Hodge, Jim Ingham, Yoshitaka Ishisaki, Diab -Jerius, Mark Levine, Todd Karakaskian, Edward King, Scott Koch, Claire -Larkin, Rob Managan, Eric Mandel, John Mattox, Carsten Meyer, Emi -Miyata, Stefan Mochnacki, Mike Noble, Oliver Oberdorf, Clive Page, -Arvind Parmar, Jeff Pedelty, Tim Pearson, Maren Purves, Scott Randall, -Chris Rogers, Arnold Rots, Barry Schlesinger, Robin Stebbins, Andrew -Szymkowiak, Allyn Tennant, Peter Teuben, James Theiler, Doug Tody, -Shiro Ueno, Steve Walton, Archie Warnock, Alan Watson, Dan Whipple, Wim -Wimmers, Peter Young, Jianjun Xu, and Nelson Zarate. - - -*III. A FITS Primer - -This section gives a brief overview of the structure of FITS files. -Users should refer to the documentation available from the FITS Support Office, as -described in the introduction, for more detailed information on FITS -formats. - -FITS was first developed in the late 1970's as a standard data -interchange format between various astronomical observatories. Since -then FITS has become the defacto standard data format supported by most -astronomical data analysis software packages. - -A FITS file consists of one or more Header + Data Units (HDUs), where -the first HDU is called the `Primary HDU', or `Primary Array'. The -primary array contains an N-dimensional array of pixels, such as a 1-D -spectrum, a 2-D image, or a 3-D data cube. Six different primary -datatypes are supported: Unsigned 8-bit bytes, 16, 32, and 64-bit signed -integers, and 32 and 64-bit floating point reals. FITS also has a -convention for storing unsigned integers (see the later -section entitled `Unsigned Integers' for more details). The primary HDU -may also consist of only a header with a null array containing no -data pixels. - -Any number of additional HDUs may follow the primary array; these -additional HDUs are called FITS `extensions'. There are currently 3 -types of extensions defined by the FITS standard: - -\begin{itemize} -\item - Image Extension - a N-dimensional array of pixels, like in a primary array -\item - ASCII Table Extension - rows and columns of data in ASCII character format -\item - Binary Table Extension - rows and columns of data in binary representation -\end{itemize} - -In each case the HDU consists of an ASCII Header Unit followed by an optional -Data Unit. For historical reasons, each Header or Data unit must be an -exact multiple of 2880 8-bit bytes long. Any unused space is padded -with fill characters (ASCII blanks or zeros). - -Each Header Unit consists of any number of 80-character keyword records -or `card images' which have the general form: -- - KEYNAME = value / comment string - NULLKEY = / comment: This keyword has no value -- -The keyword names may be up to 8 characters long and can only contain -uppercase letters, the digits 0-9, the hyphen, and the underscore -character. The keyword name is (usually) followed by an equals sign and -a space character (= ) in columns 9 - 10 of the record, followed by the -value of the keyword which may be either an integer, a floating point -number, a character string (enclosed in single quotes), or a boolean -value (the letter T or F). A keyword may also have a null or undefined -value if there is no specified value string, as in the second example. - -The last keyword in the header is always the `END' keyword which has no -value or comment fields. There are many rules governing the exact -format of a keyword record (see the FITS Standard) so it is better -to rely on standard interface software like FITSIO to correctly -construct or to parse the keyword records rather than try to deal -directly with the raw FITS formats. - -Each Header Unit begins with a series of required keywords which depend -on the type of HDU. These required keywords specify the size and -format of the following Data Unit. The header may contain other -optional keywords to describe other aspects of the data, such as the -units or scaling values. Other COMMENT or HISTORY keywords are also -frequently added to further document the data file. - -The optional Data Unit immediately follows the last 2880-byte block in -the Header Unit. Some HDUs do not have a Data Unit and only consist of -the Header Unit. - -If there is more than one HDU in the FITS file, then the Header Unit of -the next HDU immediately follows the last 2880-byte block of the -previous Data Unit (or Header Unit if there is no Data Unit). - -The main required keywords in FITS primary arrays or image extensions are: -\begin{itemize} -\item -BITPIX -- defines the datatype of the array: 8, 16, 32, 64, -32, -64 for -unsigned 8--bit byte, 16--bit signed integer, 32--bit signed integer, -64--bit signed integer, -32--bit IEEE floating point, and 64--bit IEEE double precision floating -point, respectively. -\item -NAXIS -- the number of dimensions in the array, usually 0, 1, 2, 3, or 4. -\item -NAXISn -- (n ranges from 1 to NAXIS) defines the size of each dimension. -\end{itemize} - -FITS tables start with the keyword XTENSION = `TABLE' (for ASCII -tables) or XTENSION = `BINTABLE' (for binary tables) and have the -following main keywords: -\begin{itemize} -\item -TFIELDS -- number of fields or columns in the table -\item -NAXIS2 -- number of rows in the table -\item -TTYPEn -- for each column (n ranges from 1 to TFIELDS) gives the -name of the column -\item -TFORMn -- the datatype of the column -\item -TUNITn -- the physical units of the column (optional) -\end{itemize} - -Users should refer to the FITS Support Office at {\tt http://fits.gsfc.nasa.gov} -for further information about the FITS format and related software -packages. - - - -*V. FITSIO Conventions and Guidelines - -**A. CFITSIO Size Limitations - -CFITSIO places few restrictions on the size of FITS files that it -reads or writes. There are a few limits, however, which may affect -some extreme cases: - -1. The maximum number of FITS files that may be simultaneously opened by -CFITSIO is set by NMAXFILES, as defined in fitsio2.h. The current default -value is 1000, but this may be increased if necessary. Note that CFITSIO -allocates NIOBUF * 2880 bytes of I/O buffer space for each file that is -opened. The default value of NIOBUF is 40 (defined in fitsio.h), so this -amounts to more than 115K of memory for each opened file (or 115 MB for -1000 opened files). Note that the underlying operating system, may have a -lower limit on the number of files that can be opened simultaneously. - -2. By default, CFITSIO can handle FITS files up to 2.1 GB in size (2**31 -bytes). This file size limit is often imposed by 32-bit operating -systems. More recently, as 64-bit operating systems become more common, an -industry-wide standard (at least on Unix systems) has been developed to -support larger sized files (see http://ftp.sas.com/standards/large.file/). -Starting with version 2.1 of CFITSIO, larger FITS files up to 6 terabytes -in size may be read and written on supported platforms. In order -to support these larger files, CFITSIO must be compiled with the -'-D\_LARGEFILE\_SOURCE' and `-D\_FILE\_OFFSET\_BITS=64' compiler flags. -Some platforms may also require the `-D\_LARGE\_FILES' compiler flag. - This causes the compiler to allocate 8-bytes instead of -4-bytes for the `off\_t' datatype which is used to store file offset -positions. It appears that in most cases it is not necessary to -also include these compiler flags when compiling programs that link to -the CFITSIO library. - -If CFITSIO is compiled with the -D\_LARGEFILE\_SOURCE -and -D\_FILE\_OFFSET\_BITS=64 flags on a -platform that supports large files, then it can read and write FITS -files that contain up to 2**31 2880-byte FITS records, or approximately -6 terabytes in size. It is still required that the value of the NAXISn -and PCOUNT keywords in each extension be within the range of a signed -4-byte integer (max value = 2,147,483,648). Thus, each dimension of an -image (given by the NAXISn keywords), the total width of a table -(NAXIS1 keyword), the number of rows in a table (NAXIS2 keyword), and -the total size of the variable-length array heap in binary tables -(PCOUNT keyword) must be less than this limit. - -Currently, support for large files within CFITSIO has been tested -on the Linux, Solaris, and IBM AIX operating systems. - -**B. Multiple Access to the Same FITS File - -CFITSIO supports simultaneous read and write access to multiple HDUs in -the same FITS file. Thus, one can open the same FITS file twice within -a single program and move to 2 different HDUs in the file, and then -read and write data or keywords to the 2 extensions just as if one were -accessing 2 completely separate FITS files. Since in general it is -not possible to physically open the same file twice and then expect to -be able to simultaneously (or in alternating succession) write to 2 -different locations in the file, CFITSIO recognizes when the file to be -opened (in the call to fits\_open\_file) has already been opened and -instead of actually opening the file again, just logically links the -new file to the old file. (This only applies if the file is opened -more than once within the same program, and does not prevent the same -file from being simultaneously opened by more than one program). Then -before CFITSIO reads or writes to either (logical) file, it makes sure -that any modifications made to the other file have been completely -flushed from the internal buffers to the file. Thus, in principle, one -could open a file twice, in one case pointing to the first extension -and in the other pointing to the 2nd extension and then write data to -both extensions, in any order, without danger of corrupting the file, -There may be some efficiency penalties in doing this however, since -CFITSIO has to flush all the internal buffers related to one file -before switching to the other, so it would still be prudent to -minimize the number of times one switches back and forth between doing -I/O to different HDUs in the same file. - -**C. Current Header Data Unit (CHDU) - -In general, a FITS file can contain multiple Header Data Units, also -called extensions. CFITSIO only operates within one HDU at any given -time, and the currently selected HDU is called the Current Header Data -Unit (CHDU). When a FITS file is first created or opened the CHDU is -automatically defined to be the first HDU (i.e., the primary array). -CFITSIO routines are provided to move to and open any other existing -HDU within the FITS file or to append or insert a new HDU in the FITS -file which then becomes the CHDU. - -**D. Subroutine Names - -All FITSIO subroutine names begin with the letters 'ft' to distinguish -them from other subroutines and are 5 or 6 characters long. Users should -not name their own subroutines beginning with 'ft' to avoid conflicts. -(The SPP interface routines all begin with 'fs'). Subroutines which read -or get information from the FITS file have names beginning with -'ftg...'. Subroutines which write or put information into the FITS file -have names beginning with 'ftp...'. - -**E. Subroutine Families and Datatypes - -Many of the subroutines come in families which differ only in the -datatype of the associated parameter(s) . The datatype of these -subroutines is indicated by the last letter of the subroutine name -(e.g., 'j' in 'ftpkyj') as follows: -- - x - bit - b - character*1 (unsigned byte) - i - short integer (I*2) - j - integer (I*4, 32-bit integer) - k - long long integer (I*8, 64-bit integer) - e - real exponential floating point (R*4) - f - real fixed-format floating point (R*4) - d - double precision real floating-point (R*8) - g - double precision fixed-format floating point (R*8) - c - complex reals (pairs of R*4 values) - m - double precision complex (pairs of R*8 values) - l - logical (L*4) - s - character string -- - -When dealing with the FITS byte datatype, it is important to remember -that the raw values (before any scaling by the BSCALE and BZERO, or -TSCALn and TZEROn keyword values) in byte arrays (BITPIX = 8) or byte -columns (TFORMn = 'B') are interpreted as unsigned bytes with values -ranging from 0 to 255. Some Fortran compilers support a non-standard -byte datatype such as INTEGER*1, LOGICAL*1, or BYTE, which can sometimes -be used instead of CHARACTER*1 variables. Many machines permit passing a -numeric datatype (such as INTEGER*1) to the FITSIO subroutines which are -expecting a CHARACTER*1 datatype, but this technically violates the -Fortran-77 standard and is not supported on all machines (e.g., on a VAX/VMS -machine one must use the VAX-specific \%DESCR function). - -One feature of the CFITSIO routines is that they can operate on a `X' -(bit) column in a binary table as though it were a `B' (byte) column. -For example a `11X' datatype column can be interpreted the same as a -`2B' column (i.e., 2 unsigned 8-bit bytes). In some instances, it can -be more efficient to read and write whole bytes at a time, rather than -reading or writing each individual bit. - -The double precision complex datatype is not a standard Fortran-77 -datatype. If a particular Fortran compiler does not directly support -this datatype, then one may instead pass an array of pairs of double -precision values to these subroutines. The first value in each pair -is the real part, and the second is the imaginary part. - -**F. Implicit Data Type Conversion - -The FITSIO routines that read and write numerical data can perform -implicit data type conversion. This means that the data type of the -variable or array in the program does not need to be the same as the -data type of the value in the FITS file. Data type conversion is -supported for numerical and string data types (if the string contains a -valid number enclosed in quotes) when reading a FITS header keyword -value and for numeric values when reading or writing values in the -primary array or a table column. CFITSIO returns status = -NUM\_OVERFLOW if the converted data value exceeds the range of the -output data type. Implicit data type conversion is not supported -within binary tables for string, logical, complex, or double complex -data types. - -In addition, any table column may be read as if it contained string values. -In the case of numeric columns the returned string will be formatted -using the TDISPn display format if it exists. - -**G. Data Scaling - -When reading numerical data values in the primary array or a -table column, the values will be scaled automatically by the BSCALE and -BZERO (or TSCALn and TZEROn) header keyword values if they are -present in the header. The scaled data that is returned to the reading -program will have -- - output value = (FITS value) * BSCALE + BZERO -- -(a corresponding formula using TSCALn and TZEROn is used when reading -from table columns). In the case of integer output values the floating -point scaled value is truncated to an integer (not rounded to the -nearest integer). The ftpscl and fttscl subroutines may be used to -override the scaling parameters defined in the header (e.g., to turn -off the scaling so that the program can read the raw unscaled values -from the FITS file). - -When writing numerical data to the primary array or to a table -column the data values will generally be automatically inversely scaled -by the value of the BSCALE and BZERO (or TSCALn and TZEROn) header -keyword values if they they exist in the header. These keywords must -have been written to the header before any data is written for them to -have any effect. Otherwise, one may use the ftpscl and fttscl -subroutines to define or override the scaling keywords in the header -(e.g., to turn off the scaling so that the program can write the raw -unscaled values into the FITS file). If scaling is performed, the -inverse scaled output value that is written into the FITS file will -have -- - FITS value = ((input value) - BZERO) / BSCALE -- -(a corresponding formula using TSCALn and TZEROn is used when -writing to table columns). Rounding to the nearest integer, rather -than truncation, is performed when writing integer datatypes to the -FITS file. - -**H. Error Status Values and the Error Message Stack - -The last parameter in nearly every FITSIO subroutine is the error -status value which is both an input and an output parameter. A -returned positive value for this parameter indicates an error was -detected. A listing of all the FITSIO status code values is given at -the end of this document. - -The FITSIO library uses an `inherited status' convention for the status -parameter which means that if a subroutine is called with a positive -input value of the status parameter, then the subroutine will exit -immediately without changing the value of the status parameter. Thus, -if one passes the status value returned from each FITSIO routine as -input to the next FITSIO subroutine, then whenever an error is detected -all further FITSIO processing will cease. This convention can simplify -the error checking in application programs because it is not necessary -to check the value of the status parameter after every single FITSIO -subroutine call. If a program contains a sequence of several FITSIO -calls, one can just check the status value after the last call. Since -the returned status values are generally distinctive, it should be -possible to determine which subroutine originally returned the error -status. - -FITSIO also maintains an internal stack of error messages (80-character -maximum length) which in many cases provide a more detailed explanation -of the cause of the error than is provided by the error status number -alone. It is recommended that the error message stack be printed out -whenever a program detects a FITSIO error. To do this, call the FTGMSG -routine repeatedly to get the successive messages on the stack. When the -stack is empty FTGMSG will return a blank string. Note that this is a -`First In -- First Out' stack, so the oldest error message is returned -first by ftgmsg. - -**I. Variable-Length Array Facility in Binary Tables - -FITSIO provides easy-to-use support for reading and writing data in -variable length fields of a binary table. The variable length columns -have TFORMn keyword values of the form `1Pt(len)' or `1Qt(len)' where `t' is the -datatype code (e.g., I, J, E, D, etc.) and `len' is an integer -specifying the maximum length of the vector in the table. If the value -of `len' is not specified when the table is created (e.g., if the TFORM -keyword value is simply specified as '1PE' instead of '1PE(400) ), then -FITSIO will automatically scan the table when it is closed to -determine the maximum length of the vector and will append this value -to the TFORMn value. - -The same routines which read and write data in an ordinary fixed length -binary table extension are also used for variable length fields, -however, the subroutine parameters take on a slightly different -interpretation as described below. - -All the data in a variable length field is written into an area called -the `heap' which follows the main fixed-length FITS binary table. The -size of the heap, in bytes, is specified with the PCOUNT keyword in the -FITS header. When creating a new binary table, the initial value of -PCOUNT should usually be set to zero. FITSIO will recompute the size -of the heap as the data is written and will automatically update the -PCOUNT keyword value when the table is closed. When writing variable -length data to a table, CFITSIO will automatically extend the size -of the heap area if necessary, so that any following HDUs do not -get overwritten. - -By default the heap data area starts immediately after the last row of -the fixed-length table. This default starting location may be -overridden by the THEAP keyword, but this is not recommended. -If additional rows of data are added to the table, CFITSIO will -automatically shift the the heap down to make room for the new -rows, but it is obviously be more efficient to initially -create the table with the necessary number of blank rows, so that -the heap does not needed to be constantly moved. - -When writing to a variable length field, the entire array of values for -a given row of the table must be written with a single call to FTPCLx. -The total length of the array is calculated from (NELEM+FELEM-1). One -cannot append more elements to an existing field at a later time; any -attempt to do so will simply overwrite all the data which was previously -written. Note also that the new data will be written to a new area of -the heap and the heap space used by the previous write cannot be -reclaimed. For this reason it is advised that each row of a variable -length field only be written once. An exception to this general rule -occurs when setting elements of an array as undefined. One must first -write a dummy value into the array with FTPCLx, and then call FTPCLU to -flag the desired elements as undefined. (Do not use the FTPCNx family -of routines with variable length fields). Note that the rows of a table, -whether fixed or variable length, do not have to be written -consecutively and may be written in any order. - -When writing to a variable length ASCII character field (e.g., TFORM = -'1PA') only a single character string written. FTPCLS writes the whole -length of the input string (minus any trailing blank characters), thus -the NELEM and FELEM parameters are ignored. If the input string is -completely blank then FITSIO will write one blank character to the FITS -file. Similarly, FTGCVS and FTGCFS read the entire string (truncated -to the width of the character string argument in the subroutine call) -and also ignore the NELEM and FELEM parameters. - -The FTPDES subroutine is useful in situations where multiple rows of a -variable length column have the identical array of values. One can -simply write the array once for the first row, and then use FTPDES to -write the same descriptor values into the other rows (use the FTGDES -routine to read the first descriptor value); all the rows will then -point to the same storage location thus saving disk space. - -When reading from a variable length array field one can only read as -many elements as actually exist in that row of the table; reading does -not automatically continue with the next row of the table as occurs -when reading an ordinary fixed length table field. Attempts to read -more than this will cause an error status to be returned. One can -determine the number of elements in each row of a variable column with -the FTGDES subroutine. - -**I. Support for IEEE Special Values - -The ANSI/IEEE-754 floating-point number standard defines certain -special values that are used to represent such quantities as -Not-a-Number (NaN), denormalized, underflow, overflow, and infinity. -(See the Appendix in the FITS standard or the FITS User's -Guide for a list of these values). The FITSIO subroutines that read -floating point data in FITS files recognize these IEEE special values -and by default interpret the overflow and infinity values as being -equivalent to a NaN, and convert the underflow and denormalized values -into zeros. In some cases programmers may want access to the raw IEEE -values, without any modification by FITSIO. This can be done by -calling the FTGPVx or FTGCVx routines while specifying 0.0 as the value -of the NULLVAL parameter. This will force FITSIO to simply pass the -IEEE values through to the application program, without any -modification. This does not work for double precision values on -VAX/VMS machines, however, where there is no easy way to bypass the -default interpretation of the IEEE special values. This is also not -supported when reading floating-point images that have been compressed -with the FITS tiled image compression convention that is discussed in -section 5.6; the pixels values in tile compressed images are -represented by scaled integers, and a reserved integer value -(not a NaN) is used to represent undefined pixels. - - -**J. When the Final Size of the FITS HDU is Unknown - -It is not required to know the total size of a FITS data array or table -before beginning to write the data to the FITS file. In the case of -the primary array or an image extension, one should initially create -the array with the size of the highest dimension (largest NAXISn -keyword) set to a dummy value, such as 1. Then after all the data have -been written and the true dimensions are known, then the NAXISn value -should be updated using the fits\_ update\_key routine before moving to -another extension or closing the FITS file. - -When writing to FITS tables, CFITSIO automatically keeps track of the -highest row number that is written to, and will increase the size of -the table if necessary. CFITSIO will also automatically insert space -in the FITS file if necessary, to ensure that the data 'heap', if it -exists, and/or any additional HDUs that follow the table do not get -overwritten as new rows are written to the table. - -As a general rule it is best to specify the initial number of rows = 0 -when the table is created, then let CFITSIO keep track of the number of -rows that are actually written. The application program should not -manually update the number of rows in the table (as given by the NAXIS2 -keyword) since CFITSIO does this automatically. If a table is -initially created with more than zero rows, then this will usually be -considered as the minimum size of the table, even if fewer rows are -actually written to the table. Thus, if a table is initially created -with NAXIS2 = 20, and CFITSIO only writes 10 rows of data before -closing the table, then NAXIS2 will remain equal to 20. If however, 30 -rows of data are written to this table, then NAXIS2 will be increased -from 20 to 30. The one exception to this automatic updating of the -NAXIS2 keyword is if the application program directly modifies the -value of NAXIS2 (up or down) itself just before closing the table. In this -case, CFITSIO does not update NAXIS2 again, since it assumes that the -application program must have had a good reason for changing the value -directly. This is not recommended, however, and is only provided for -backward compatibility with software that initially creates a table -with a large number of rows, than decreases the NAXIS2 value to the -actual smaller value just before closing the table. - -**K. Local FITS Conventions supported by FITSIO - -CFITSIO supports several local FITS conventions which are not -defined in the official FITS standard and which are not -necessarily recognized or supported by other FITS software packages. -Programmers should be cautious about using these features, especially -if the FITS files that are produced are expected to be processed by -other software systems which do not use the CFITSIO interface. - -***1. Support for Long String Keyword Values. - -The length of a standard FITS string keyword is limited to 68 -characters because it must fit entirely within a single FITS header -keyword record. In some instances it is necessary to encode strings -longer than this limit, so FITSIO supports a local convention in which -the string value is continued over multiple keywords. This -continuation convention uses an ampersand character at the end of each -substring to indicate that it is continued on the next keyword, and the -continuation keywords all have the name CONTINUE without an equal sign -in column 9. The string value may be continued in this way over as many -additional CONTINUE keywords as is required. The following lines -illustrate this continuation convention which is used in the value of -the STRKEY keyword: -- -LONGSTRN= 'OGIP 1.0' / The OGIP Long String Convention may be used. -STRKEY = 'This is a very long string keyword&' / Optional Comment -CONTINUE ' value that is continued over 3 keywords in the & ' -CONTINUE 'FITS header.' / This is another optional comment. -- -It is recommended that the LONGSTRN keyword, as shown -here, always be included in any HDU that uses this longstring -convention. A subroutine called FTPLSW -has been provided in CFITSIO to write this keyword if it does not -already exist. - -This long string convention is supported by the following FITSIO -subroutines that deal with string-valued keywords: -- - ftgkys - read a string keyword - ftpkls - write (append) a string keyword - ftikls - insert a string keyword - ftmkls - modify the value of an existing string keyword - ftukls - update an existing keyword, or write a new keyword - ftdkey - delete a keyword -- -These routines will transparently read, write, or delete a long string -value in the FITS file, so programmers in general do not have to be -concerned about the details of the convention that is used to encode -the long string in the FITS header. When reading a long string, one -must ensure that the character string parameter used in these -subroutine calls has been declared long enough to hold the entire -string, otherwise the returned string value will be truncated. - -Note that the more commonly used FITSIO subroutine to write string -valued keywords (FTPKYS) does NOT support this long string convention -and only supports strings up to 68 characters in length. This has been -done deliberately to prevent programs from inadvertently writing -keywords using this non-standard convention without the explicit intent -of the programmer or user. The FTPKLS subroutine must be called -instead to write long strings. This routine can also be used to write -ordinary string values less than 68 characters in length. - -***2. Arrays of Fixed-Length Strings in Binary Tables - -CFITSIO supports 2 ways to specify that a character column in a binary -table contains an array of fixed-length strings. The first way, which -is officially supported by the FITS Standard document, uses the TDIMn keyword. -For example, if TFORMn = '60A' and TDIMn = '(12,5)' then that -column will be interpreted as containing an array of 5 strings, each 12 -characters long. - -FITSIO also supports a -local convention for the format of the TFORMn keyword value of the form -'rAw' where 'r' is an integer specifying the total width in characters -of the column, and 'w' is an integer specifying the (fixed) length of -an individual unit string within the vector. For example, TFORM1 = -'120A10' would indicate that the binary table column is 120 characters -wide and consists of 12 10-character length strings. This convention -is recognized by the FITSIO subroutines that read or write strings in -binary tables. The Binary Table definition document specifies that -other optional characters may follow the datatype code in the TFORM -keyword, so this local convention is in compliance with the -FITS standard, although other FITS readers are not required to -recognize this convention. - -***3. Keyword Units Strings - -One deficiency of the current FITS Standard is that it does not define -a specific convention for recording the physical units of a keyword -value. The TUNITn keyword can be used to specify the physical units of -the values in a table column, but there is no analogous convention for -keyword values. The comment field of the keyword is often used for -this purpose, but the units are usually not specified in a well defined -format that FITS readers can easily recognize and extract. - -To solve this deficiency, FITSIO uses a local convention in which the -keyword units are enclosed in square brackets as the first token in the -keyword comment field; more specifically, the opening square bracket -immediately follows the slash '/' comment field delimiter and a single -space character. The following examples illustrate keywords that use -this convention: - -- -EXPOSURE= 1800.0 / [s] elapsed exposure time -V_HELIO = 16.23 / [km s**(-1)] heliocentric velocity -LAMBDA = 5400. / [angstrom] central wavelength -FLUX = 4.9033487787637465E-30 / [J/cm**2/s] average flux -- - -In general, the units named in the IAU(1988) Style Guide are -recommended, with the main exception that the preferred unit for angle -is 'deg' for degrees. - -The FTPUNT and FTGUNT subroutines in FITSIO write and read, -respectively, the keyword unit strings in an existing keyword. - -***4. HIERARCH Convention for Extended Keyword Names - -CFITSIO supports the HIERARCH keyword convention which allows keyword -names that are longer then 8 characters and may contain the full range -of printable ASCII text characters. This convention -was developed at the European Southern Observatory (ESO) to support -hierarchical FITS keyword such as: -- -HIERARCH ESO INS FOCU POS = -0.00002500 / Focus position -- -Basically, this convention uses the FITS keyword 'HIERARCH' to indicate -that this convention is being used, then the actual keyword name -({\tt'ESO INS FOCU POS'} in this example) begins in column 10 and can -contain any printable ASCII text characters, including spaces. The -equals sign marks the end of the keyword name and is followed by the -usual value and comment fields just as in standard FITS keywords. -Further details of this convention are described at -http://fits.gsfc.nasa.gov/registry/hierarch\_keyword.html -and in Section 4.4 of the ESO Data Interface Control Document that -is linked to from -http://archive.eso.org/cms/tools-documentation/eso-data-interface-control.html. - -This convention allows a much broader range of keyword names -than is allowed by the FITS Standard. Here are more examples -of such keywords: -- -HIERARCH LongKeyword = 47.5 / Keyword has > 8 characters, and mixed case -HIERARCH XTE$TEMP = 98.6 / Keyword contains the '$' character -HIERARCH Earth is a star = F / Keyword contains embedded spaces -- -CFITSIO will transparently read and write these keywords, so application -programs do not in general need to know anything about the specific -implementation details of the HIERARCH convention. In particular, -application programs do not need to specify the `HIERARCH' part of the -keyword name when reading or writing keywords (although it -may be included if desired). When writing a keyword, CFITSIO first -checks to see if the keyword name is legal as a standard FITS keyword -(no more than 8 characters long and containing only letters, digits, or -a minus sign or underscore). If so it writes it as a standard FITS -keyword, otherwise it uses the hierarch convention to write the -keyword. The maximum keyword name length is 67 characters, which -leaves only 1 space for the value field. A more practical limit is -about 40 characters, which leaves enough room for most keyword values. -CFITSIO returns an error if there is not enough room for both the -keyword name and the keyword value on the 80-character card, except for -string-valued keywords which are simply truncated so that the closing -quote character falls in column 80. In the current implementation, -CFITSIO preserves the case of the letters when writing the keyword -name, but it is case-insensitive when reading or searching for a -keyword. The current implementation allows any ASCII text character -(ASCII 32 to ASCII 126) in the keyword name except for the '=' -character. A space is also required on either side of the equal sign. - -**L. Optimizing Code for Maximum Processing Speed - -CFITSIO has been carefully designed to obtain the highest possible -speed when reading and writing FITS files. In order to achieve the -best performance, however, application programmers must be careful to -call the CFITSIO routines appropriately and in an efficient sequence; -inappropriate usage of CFITSIO routines can greatly slow down the -execution speed of a program. - -The maximum possible I/O speed of CFITSIO depends of course on the type -of computer system that it is running on. To get a general idea of what -data I/O speeds are possible on a particular machine, build the speed.c -program that is distributed with CFITSIO (type 'make speed' in the CFITSIO -directory). This diagnostic program measures the speed of writing and reading -back a test FITS image, a binary table, and an ASCII table. - -The following 2 sections provide some background on how CFITSIO -internally manages the data I/O and describes some strategies that may -be used to optimize the processing speed of software that uses -CFITSIO. - -***1. Background Information: How CFITSIO Manages Data I/O - -Many CFITSIO operations involve transferring only a small number of -bytes to or from the FITS file (e.g, reading a keyword, or writing a -row in a table); it would be very inefficient to physically read or -write such small blocks of data directly in the FITS file on disk, -therefore CFITSIO maintains a set of internal Input--Output (IO) -buffers in RAM memory that each contain one FITS block (2880 bytes) of -data. Whenever CFITSIO needs to access data in the FITS file, it first -transfers the FITS block containing those bytes into one of the IO -buffers in memory. The next time CFITSIO needs to access bytes in the -same block it can then go to the fast IO buffer rather than using a -much slower system disk access routine. The number of available IO -buffers is determined by the NIOBUF parameter (in fitsio2.h) and is -currently set to 40. - -Whenever CFITSIO reads or writes data it first checks to see if that -block of the FITS file is already loaded into one of the IO buffers. -If not, and if there is an empty IO buffer available, then it will load -that block into the IO buffer (when reading a FITS file) or will -initialize a new block (when writing to a FITS file). If all the IO -buffers are already full, it must decide which one to reuse (generally -the one that has been accessed least recently), and flush the contents -back to disk if it has been modified before loading the new block. - -The one major exception to the above process occurs whenever a large -contiguous set of bytes are accessed, as might occur when reading or -writing a FITS image. In this case CFITSIO bypasses the internal IO -buffers and simply reads or writes the desired bytes directly in the -disk file with a single call to a low-level file read or write -routine. The minimum threshold for the number of bytes to read or -write this way is set by the MINDIRECT parameter and is currently set -to 3 FITS blocks = 8640 bytes. This is the most efficient way to read -or write large chunks of data. Note that this fast direct IO process is not -applicable when accessing columns of data in a FITS table because the -bytes are generally not contiguous since they are interleaved by the -other columns of data in the table. This explains why the speed for -accessing FITS tables is generally slower than accessing -FITS images. - -Given this background information, the general strategy for efficiently -accessing FITS files should now be apparent: when dealing with FITS -images, read or write large chunks of data at a time so that the direct -IO mechanism will be invoked; when accessing FITS headers or FITS -tables, on the other hand, once a particular FITS block has been -loading into one of the IO buffers, try to access all the needed -information in that block before it gets flushed out of the IO buffer. -It is important to avoid the situation where the same FITS block is -being read then flushed from a IO buffer multiple times. - -The following section gives more specific suggestions for optimizing -the use of CFITSIO. - -***2. Optimization Strategies - -1. Because the data in FITS files is always stored in "big-endian" byte order, -where the first byte of numeric values contains the most significant bits and the -last byte contains the least significant bits, CFITSIO must swap the order of the bytes -when reading or writing FITS files when running on little-endian machines (e.g., -Linux and Microsoft Windows operating systems running on PCs with x86 CPUs). - -On fairly new CPUs that support "SSSE3" machine instructions -(e.g., starting with Intel Core 2 CPUs in 2007, and in AMD CPUs -beginning in 2011) significantly faster 4-byte and 8-byte swapping -algorithms are available. These faster byte swapping functions are -not used by default in CFITSIO (because of the potential code -portablility issues), but users can enable them on supported -platforms by adding the appropriate compiler flags (-mssse3 with gcc -or icc on linux) when compiling the swapproc.c source file, which will -allow the compiler to generate code using the SSSE3 instruction set. -A convenient way to do this is to configure the CFITSIO library -with the following command: -- - > ./configure --enable-ssse3 -- -Note, however, that a binary executable file that is -created using these faster functions will only run on -machines that support the SSSE3 machine instructions. It will -crash on machines that do not support them. - -For faster 2-byte swaps on virtually all x86-64 CPUs (even those that -do not support SSSE3), a variant using only SSE2 instructions exists. -SSE2 is enabled by default on x86\_64 CPUs with 64-bit operating systems -(and is also automatically enabled by the --enable-ssse3 flag). -When running on x86\_64 CPUs with 32-bit operating systems, these faster -2-byte swapping algorithms are not used by default in CFITSIO, but can be -enabled explicitly with: -- -./configure --enable-sse2 -- -Preliminary testing indicates that these SSSE3 and SSE2 based -byte-swapping algorithms can boost the CFITSIO performance when -reading or writing FITS images by 20\% - 30\% or more. -It is important to note, however, that compiler optimization must be -turned on (e.g., by using the -O1 or -O2 flags in gcc) when building -programs that use these fast byte-swapping algorithms in order -to reap the full benefit of the SSSE3 and SSE2 instructions; without -optimization, the code may actually run slower than when using -more traditional byte-swapping techniques. - -2. When dealing with a FITS primary array or IMAGE extension, it is -more efficient to read or write large chunks of the image at a time -(at least 3 FITS blocks = 8640 bytes) so that the direct IO mechanism -will be used as described in the previous section. Smaller chunks of -data are read or written via the IO buffers, which is somewhat less -efficient because of the extra copy operation and additional -bookkeeping steps that are required. In principle it is more efficient -to read or write as big an array of image pixels at one time as -possible, however, if the array becomes so large that the operating -system cannot store it all in RAM, then the performance may be degraded -because of the increased swapping of virtual memory to disk. - -3. When dealing with FITS tables, the most important efficiency factor -in the software design is to read or write the data in the FITS file in -a single pass through the file. An example of poor program design -would be to read a large, 3-column table by sequentially reading the -entire first column, then going back to read the 2nd column, and -finally the 3rd column; this obviously requires 3 passes through the -file which could triple the execution time of an I/O limited program. -For small tables this is not important, but when reading multi-megabyte -sized tables these inefficiencies can become significant. The more -efficient procedure in this case is to read or write only as many rows -of the table as will fit into the available internal I/O buffers, then -access all the necessary columns of data within that range of rows. -Then after the program is completely finished with the data in those -rows it can move on to the next range of rows that will fit in the -buffers, continuing in this way until the entire file has been -processed. By using this procedure of accessing all the columns of a -table in parallel rather than sequentially, each block of the FITS file -will only be read or written once. - -The optimal number of rows to read or write at one time in a given -table depends on the width of the table row, on the number of I/O -buffers that have been allocated in FITSIO, and also on the number of -other FITS files that are open at the same time (since one I/O buffer -is always reserved for each open FITS file). Fortunately, a FITSIO -routine is available that will return the optimal number of rows for a -given table: call ftgrsz(unit, nrows, status). It is not critical to -use exactly the value of nrows returned by this routine, as long as one -does not exceed it. Using a very small value however can also lead to -poor performance because of the overhead from the larger number of -subroutine calls. - -The optimal number of rows returned by ftgrsz is valid only as long as -the application program is only reading or writing data in the -specified table. Any other calls to access data in the table header -would cause additional blocks of data to be -loaded into the I/O buffers displacing data from the original table, -and should be avoided during the critical period while the table is -being read or written. - -4. Use binary table extensions rather than ASCII table -extensions for better efficiency when dealing with tabular data. The -I/O to ASCII tables is slower because of the overhead in formatting or -parsing the ASCII data fields, and because ASCII tables are about twice -as large as binary tables with the same information content. - -5. Design software so that it reads the FITS header keywords in the -same order in which they occur in the file. When reading keywords, -FITSIO searches forward starting from the position of the last keyword -that was read. If it reaches the end of the header without finding the -keyword, it then goes back to the start of the header and continues the -search down to the position where it started. In practice, as long as -the entire FITS header can fit at one time in the available internal I/O -buffers, then the header keyword access will be very fast and it makes -little difference which order they are accessed. - -6. Avoid the use of scaling (by using the BSCALE and BZERO or TSCAL and -TZERO keywords) in FITS files since the scaling operations add to the -processing time needed to read or write the data. In some cases it may -be more efficient to temporarily turn off the scaling (using ftpscl or -fttscl) and then read or write the raw unscaled values in the FITS -file. - -7. Avoid using the 'implicit datatype conversion' capability in -FITSIO. For instance, when reading a FITS image with BITPIX = -32 -(32-bit floating point pixels), read the data into a single precision -floating point data array in the program. Forcing FITSIO to convert -the data to a different datatype can significantly slow the program. - -8. Where feasible, design FITS binary tables using vector column -elements so that the data are written as a contiguous set of bytes, -rather than as single elements in multiple rows. For example, it is -faster to access the data in a table that contains a single row -and 2 columns with TFORM keywords equal to '10000E' and '10000J', than -it is to access the same amount of data in a table with 10000 rows -which has columns with the TFORM keywords equal to '1E' and '1J'. In -the former case the 10000 floating point values in the first column are -all written in a contiguous block of the file which can be read or -written quickly, whereas in the second case each floating point value -in the first column is interleaved with the integer value in the second -column of the same row so CFITSIO has to explicitly move to the -position of each element to be read or written. - -9. Avoid the use of variable length vector columns in binary tables, -since any reading or writing of these data requires that CFITSIO first -look up or compute the starting address of each row of data in the -heap. In practice, this is probably not a significant efficiency issue. - -10. When copying data from one FITS table to another, it is faster to -transfer the raw bytes instead of reading then writing each column of -the table. The FITSIO subroutines FTGTBS and FTPTBS (for ASCII -tables), and FTGTBB and FTPTBB (for binary tables) will perform -low-level reads or writes of any contiguous range of bytes in a table -extension. These routines can be used to read or write a whole row (or -multiple rows) of a table with a single subroutine call. These -routines are fast because they bypass all the usual data scaling, error -checking and machine dependent data conversion that is normally done by -FITSIO, and they allow the program to write the data to the output file -in exactly the same byte order. For these same reasons, use of these -routines can be somewhat risky because no validation or machine -dependent conversion is performed by these routines. In general these -routines are only recommended for optimizing critical pieces of code -and should only be used by programmers who thoroughly understand the -internal byte structure of the FITS tables they are reading or -writing. - -11. Another strategy for improving the speed of writing a FITS table, -similar to the previous one, is to directly construct the entire byte -stream for a whole table row (or multiple rows) within the application -program and then write it to the FITS file with -ftptbb. This avoids all the overhead normally present -in the column-oriented CFITSIO write routines. This technique should -only be used for critical applications, because it makes the code more -difficult to understand and maintain, and it makes the code more system -dependent (e.g., do the bytes need to be swapped before writing to the -FITS file?). - -12. Finally, external factors such as the type of magnetic disk -controller (SCSI or IDE), the size of the disk cache, the average seek -speed of the disk, the amount of disk fragmentation, and the amount of -RAM available on the system can all have a significant impact on -overall I/O efficiency. For critical applications, a system -administrator should review the proposed system hardware to identify any -potential I/O bottlenecks. - - - -*VII. Basic Interface Routines - -This section defines a basic set of subroutines that can be -used to perform the most common types of read and write operations -on FITS files. New users should start with these subroutines and -then, as needed, explore the more advance routines described in -the following chapter to perform more complex or specialized operations. - -A right arrow symbol ($>$) is used to separate the input parameters from -the output parameters in the definition of each routine. This symbol -is not actually part of the calling sequence. Note that -the status parameter is both an input and an output parameter -and must be initialized = 0 prior to calling the FITSIO subroutines. - -Refer to Chapter 9 for the definition of all the parameters -used by these interface routines. - -**A. FITSIO Error Status Routines \label{FTVERS} - ->1 Return the current version number of the fitsio library. - The version number will be incremented with each new -> release of CFITSIO. -- - FTVERS( > version) -- ->2 Return the descriptive text string corresponding to a FITSIO error - status code. The 30-character length string contains a brief -> description of the cause of the error. -- - FTGERR(status, > errtext) -- ->3 Return the top (oldest) 80-character error message from the - internal FITSIO stack of error messages and shift any remaining - messages on the stack up one level. Any FITSIO error will - generate one or more messages on the stack. Call this routine - repeatedly to get each message in sequence. The error stack is empty -> when a blank string is returned. -- - FTGMSG( > errmsg) -- ->4 The FTPMRK routine puts an invisible marker on the - CFITSIO error stack. The FTCMRK routine can then be - used to delete any more recent error messages on the stack, back to - the position of the marker. This preserves any older error messages - on the stack. FTCMSG simply clears the entire error message stack. -> These routines are called without any arguments. -- - FTPMRK - FTCMRK - FTCMSG -- - ->5 Print out the error message corresponding to the input status - value and all the error messages on the FITSIO stack to the specified - file stream (stream can be either the string 'STDOUT' or 'STDERR'). -> If the input status value = 0 then this routine does nothing. -- - FTRPRT (stream, > status) -- ->6 Write an 80-character message to the FITSIO error stack. Application - programs should not normally write to the stack, but there may be -> some situations where this is desirable. -- - FTPMSG(errmsg) -- - -**B. File I/O Routines - ->1 Open an existing FITS file with readonly or readwrite access. - This routine always opens the primary array (the first HDU) of - the file, and does not move to a following extension, if one was - specified as part of the filename. Use the FTNOPN routine to - automatically move to the extension. This routine will also - open IRAF images (.imh format files) and raw binary data arrays - with READONLY access by first converting them on the fly into - virtual FITS images. See the `Extended File Name Syntax' chapter - for more details. The FTDKOPN routine simply opens the specified - file without trying to interpret the filename using the extended -> filename syntax. -- - FTOPEN(unit,filename,rwmode, > blocksize,status) - FTDKOPN(unit,filename,rwmode, > blocksize,status) -- ->2 Open an existing FITS file with readonly or readwrite access - and move to a following extension, if one was specified as - part of the filename. (e.g., 'filename.fits+2' or - 'filename.fits[2]' will move to the 3rd HDU in the file). - Note that this routine differs from FTOPEN in that it does not -> have the redundant blocksize argument. -- - FTNOPN(unit,filename,rwmode, > status) -- ->3 Open an existing FITS file with readonly or readwrite access - and then move to the first HDU containing significant data, if a) an HDU - name or number to open was not explicitly specified as part of the - filename, and b) if the FITS file contains a null primary array (i.e., - NAXIS = 0). In this case, it will look for the first IMAGE HDU with - NAXIS > 0, or the first table that does not contain the strings `GTI' - (Good Time Interval) or `OBSTABLE' in the EXTNAME keyword value. FTTOPN - is similar, except it will move to the first significant table HDU - (skipping over any image HDUs) in the file if a specific HDU name - or number is not specified. FTIOPN will move to the first non-null -> image HDU, skipping over any tables. -- - FTDOPN(unit,filename,rwmode, > status) - FTTOPN(unit,filename,rwmode, > status) - FTIOPN(unit,filename,rwmode, > status) -- ->4 Open and initialize a new empty FITS file. A template file may also be - specified to define the structure of the new file (see section 4.2.4). - The FTDKINIT routine simply creates the specified - file without trying to interpret the filename using the extended -> filename syntax. -- - FTINIT(unit,filename,blocksize, > status) - FTDKINIT(unit,filename,blocksize, > status) -- ->>5 Close a FITS file previously opened with ftopen or ftinit -- - FTCLOS(unit, > status) -- ->6 Move to a specified (absolute) HDU in the FITS file (nhdu = 1 for the -> FITS primary array) -- - FTMAHD(unit,nhdu, > hdutype,status) -- ->7 Create a primary array (if none already exists), or insert a - new IMAGE extension immediately following the CHDU, or - insert a new Primary Array at the beginning of the file. Any - following extensions in the file will be shifted down to make room - for the new extension. If the CHDU is the last HDU in the file - then the new image extension will simply be appended to the end of - the file. One can force a new primary array to be inserted at the - beginning of the FITS file by setting status = -9 prior - to calling the routine. In this case the existing primary array will be - converted to an IMAGE extension. The new extension (or primary - array) will become the CHDU. The FTIIMGLL routine is identical - to the FTIIMG routine except that the 4th parameter (the length - of each axis) is an array of 64-bit integers rather than an array -> of 32-bit integers. -- - FTIIMG(unit,bitpix,naxis,naxes, > status) - FTIIMGLL(unit,bitpix,naxis,naxesll, > status) -- ->8 Insert a new ASCII TABLE extension immediately following the CHDU. - Any following extensions will be shifted down to make room for - the new extension. If there are no other following extensions - then the new table extension will simply be appended to the - end of the file. The new extension will become the CHDU. The FTITABLL - routine is identical - to the FTITAB routine except that the 2nd and 3rd parameters (that give - the size of the table) are 64-bit integers rather than - 32-bit integers. Under normal circumstances, the nrows and nrowsll - paramenters should have a value of 0; CFITSIO will automatically update -> the number of rows as data is written to the table. -- - FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > - status) - FTITABLL(unit,rowlenll,nrowsll,tfields,ttype,tbcol,tform,tunit,extname, > - status) -- ->9 Insert a new binary table extension immediately following the CHDU. - Any following extensions will be shifted down to make room for - the new extension. If there are no other following extensions - then the new bintable extension will simply be appended to the - end of the file. The new extension will become the CHDU. The FTIBINLL - routine is identical - to the FTIBIN routine except that the 2nd parameter (that gives - the length of the table) is a 64-bit integer rather than - a 32-bit integer. Under normal circumstances, the nrows and nrowsll - paramenters should have a value of 0; CFITSIO will automatically update -> the number of rows as data is written to the table. -- - FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) - FTIBINLL(unit,nrowsll,tfields,ttype,tform,tunit,extname,varidat > status) - -- -**C. Keyword I/O Routines - ->>1 Put (append) an 80-character record into the CHU. -- - FTPREC(unit,card, > status) -- ->2 Put (append) a new keyword of the appropriate datatype into the CHU. - The E and D versions of this routine have the added feature that - if the 'decimals' parameter is negative, then the 'G' display - format rather then the 'E' format will be used when constructing - the keyword value, taking the absolute value of 'decimals' for the - precision. This will suppress trailing zeros, and will use a - fixed format rather than an exponential format, -> depending on the magnitude of the value. -- - FTPKY[JKLS](unit,keyword,keyval,comment, > status) - FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) -- ->3 Get the nth 80-character header record from the CHU. The first keyword - in the header is at key\_no = 1; if key\_no = 0 then this subroutine - simple moves the internal pointer to the beginning of the header - so that subsequent keyword operations will start at the top of -> the header; it also returns a blank card value in this case. -- - FTGREC(unit,key_no, > card,status) -- ->4 Get a keyword value (with the appropriate datatype) and comment from -> the CHU -- - FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) -- ->>5 Delete an existing keyword record. -- - FTDKEY(unit,keyword, > status) -- - -**D. Data I/O Routines - -The following routines read or write data values in the current HDU of -the FITS file. Automatic datatype conversion -will be attempted for numerical datatypes if the specified datatype is -different from the actual datatype of the FITS array or table column. - ->>1 Write elements into the primary data array or image extension. -- - FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) -- ->2 Read elements from the primary data array or image extension. - Undefined array elements will be - returned with a value = nullval, unless nullval = 0 in which case no - checks for undefined pixels will be performed. The anyf parameter is - set to true (= .true.) if any of the returned -> elements were undefined. -- - FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) -- ->3 Write elements into an ASCII or binary table column. The `felem' - parameter applies only to vector columns in binary tables and is -> ignored when writing to ASCII tables. -- - FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) -- ->4 Read elements from an ASCII or binary table column. Undefined - array elements will be returned with a value = nullval, unless nullval = 0 - (or = ' ' for ftgcvs) in which case no checking for undefined values will - be performed. The ANYF parameter is set to true if any of the returned - elements are undefined. - - Any column, regardless of it's intrinsic datatype, may be read as a - string. It should be noted however that reading a numeric column - as a string is 10 - 100 times slower than reading the same column - as a number due to the large overhead in constructing the formatted - strings. The display format of the returned strings will be - determined by the TDISPn keyword, if it exists, otherwise by the - datatype of the column. The length of the returned strings can be - determined with the ftgcdw routine. The following TDISPn display - formats are currently supported: -- - Iw.m Integer - Ow.m Octal integer - Zw.m Hexadecimal integer - Fw.d Fixed floating point - Ew.d Exponential floating point - Dw.d Exponential floating point - Gw.d General; uses Fw.d if significance not lost, else Ew.d -- - where w is the width in characters of the displayed values, m is the minimum - number of digits displayed, and d is the number of digits to the right of the -> decimal. The .m field is optional. - -- - FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > - values,anyf,status) -- ->5 Get the table column number and full name of the column whose name - matches the input template string. See the `Advanced Interface Routines' -> chapter for a full description of this routine. -- - FTGCNN(unit,casesen,coltemplate, > colname,colnum,status) -- - - -*VIII Advanced Interface Subroutines - -This chapter defines all the available subroutines in the FITSIO user -interface. For completeness, the basic subroutines described in the -previous chapter are also repeated here. A right arrow symbol is used -here to separate the input parameters from the output parameters in the -definition of each subroutine. This symbol is not actually part of the -calling sequence. An alphabetical list and definition of all the -parameters is given at the end of this section. - -**A. FITS File Open and Close Subroutines: \label{FTOPEN} - ->1 Open an existing FITS file with readonly or readwrite access. The -FTDKOPN routine simply opens the specified file without trying to -interpret the filename using the extended filename syntax. FTDOPN opens -the file and -also moves to the first HDU containing significant data, if no specific -HDU is specified as part of the filename. FTTOPN and FTIOPN are similar -except that they will move to the first table HDU or image HDU, respectively, ->if a HDU name or number is not specified as part of the filename. -- - FTOPEN(unit,filename,rwmode, > blocksize,status) - FTDKOPN(unit,filename,rwmode, > blocksize,status) - - FTDOPN(unit,filename,rwmode, > status) - FTTOPN(unit,filename,rwmode, > status) - FTIOPN(unit,filename,rwmode, > status) -- - ->2 Open an existing FITS file with readonly or readwrite access - and move to a following extension, if one was specified as - part of the filename. (e.g., 'filename.fits+2' or - 'filename.fits[2]' will move to the 3rd HDU in the file). - Note that this routine differs from FTOPEN in that it does not -> have the redundant blocksize argument. -- - FTNOPN(unit,filename,rwmode, > status) -- ->3 Reopen a FITS file that was previously opened with - FTOPEN, FTNOPN, or FTINIT. The newunit number - may then be treated as a separate file, and one may - simultaneously read or write to 2 (or more) different extensions in - the same file. The FTOPEN and FTNOPN routines (above) automatically - detects cases where a previously opened file is being opened again, - and then internally call FTREOPEN, so programs should rarely -> need to explicitly call this routine. -- - FTREOPEN(unit, > newunit, status) -- ->4 Open and initialize a new empty FITS file. - The FTDKINIT routine simply creates the specified - file without trying to interpret the filename using the extended -> filename syntax. -- - FTINIT(unit,filename,blocksize, > status) - FTDKINIT(unit,filename,blocksize, > status) -- - ->5 Create a new FITS file, using a template file to define its - initial size and structure. The template may be another FITS HDU - or an ASCII template file. If the input template file name - is blank, then this routine behaves the same as FTINIT. - The currently supported format of the ASCII template file is described - under the fits\_parse\_template routine (in the general Utilities - section), but this may change slightly later releases of -> CFITSIO. -- - FTTPLT(unit, filename, tplfilename, > status) -- ->6 Flush internal buffers of data to the output FITS file - previously opened with ftopen or ftinit. The routine usually - never needs to be called, but doing so will ensure that - if the program subsequently aborts, then the FITS file will -> have at least been closed properly. -- - FTFLUS(unit, > status) -- ->>7 Close a FITS file previously opened with ftopen or ftinit -- - FTCLOS(unit, > status) -- ->8 Close and DELETE a FITS file previously opened with ftopen or ftinit. - This routine may be useful in cases where a FITS file is created, but -> an error occurs which prevents the complete file from being written. -- - FTDELT(unit, > status) -- ->9 Get the value of an unused I/O unit number which may then be used - as input to FTOPEN or FTINIT. This routine searches for the first - unused unit number in the range from with 99 down to 50. This - routine just keeps an internal list of the allocated unit numbers - and does not physically check that the Fortran unit is available (to be - compatible with the SPP version of FITSIO). Thus users must not - independently allocate any unit numbers in the range 50 - 99 - if this routine is also to be used in the same program. This - routine is provided for convenience only, and it is not required -> that the unit numbers used by FITSIO be allocated by this routine. -- - FTGIOU( > iounit, status) -- ->10 Free (deallocate) an I/O unit number which was previously allocated - with FTGIOU. All previously allocated unit numbers may be -> deallocated at once by calling FTFIOU with iounit = -1. -- - FTFIOU(iounit, > status) -- ->11 Return the Fortran unit number that corresponds to the C fitsfile -pointer value, or vice versa. These 2 C routines may be useful in -mixed language programs where both C and Fortran subroutines need -to access the same file. For example, if a FITS file is opened -with unit 12 by a Fortran subroutine, then a C routine within the -same program could get the fitfile pointer value to access the same file -by calling 'fptr = CUnit2FITS(12)'. These routines return a value ->of zero if an error occurs. -- - int CFITS2Unit(fitsfile *ptr); - fitsfile* CUnit2FITS(int unit); -- - ->11 Parse the input filename and return the HDU number that would be -moved to if the file were opened with FTNOPN. The returned HDU -number begins with 1 for the primary array, so for example, if the -input filename = `myfile.fits[2]' then hdunum = 3 will be returned. -FITSIO does not open the file to check if the extension actually exists -if an extension number is specified. If an extension *name* is included -in the file name specification (e.g. `myfile.fits[EVENTS]' then this -routine will have to open the FITS file and look for the position of -the named extension, then close file again. This is not possible if -the file is being read from the stdin stream, and an error will be -returned in this case. If the filename does not specify an explicit -extension (e.g. 'myfile.fits') then hdunum = -99 will be returned, -which is functionally equivalent to hdunum = 1. This routine is mainly -used for backward compatibility in the ftools software package and is -not recommended for general use. It is generally better and more -efficient to first open the FITS file with FTNOPN, then use FTGHDN to -determine which HDU in the file has been opened, rather than calling -> FTEXTN followed by a call to FTNOPN. -- - FTEXTN(filename, > nhdu, status) -- ->>12 Return the name of the opened FITS file. -- - FTFLNM(unit, > filename, status) -- ->>13 Return the I/O mode of the open FITS file (READONLY = 0, READWRITE = 1). -- - FTFLMD(unit, > iomode, status) -- ->14 Return the file type of the opened FITS file (e.g. 'file://', 'ftp://', -> etc.). -- - FTURLT(unit, > urltype, status) -- ->15 Parse the input filename or URL into its component parts: the file -type (file://, ftp://, http://, etc), the base input file name, the -name of the output file that the input file is to be copied to prior -to opening, the HDU or extension specification, the filtering -specifier, the binning specifier, and the column specifier. Blank -strings will be returned for any components that are not present ->in the input file name. -- - FTIURL(filename, > filetype, infile, outfile, extspec, filter, - binspec, colspec, status) -- ->16 Parse the input file name and return the root file name. The root -name includes the file type if specified, (e.g. 'ftp://' or 'http://') -and the full path name, to the extent that it is specified in the input -filename. It does not include the HDU name or number, or any filtering ->specifications. -- - FTRTNM(filename, > rootname, status) -- - ->16 Test if the input file or a compressed version of the file (with -a .gz, .Z, .z, or .zip extension) exists on disk. The returned value of -the 'exists' parameter will have 1 of the 4 following values: -- - 2: the file does not exist, but a compressed version does exist - 1: the disk file does exist - 0: neither the file nor a compressed version of the file exist - -1: the input file name is not a disk file (could be a ftp, http, - smem, or mem file, or a file piped in on the STDIN stream) -- -> -- - FTEXIST(filename, > exists, status); -- -**B. HDU-Level Operations \label{FTMAHD} - -When a FITS file is first opened or created, the internal buffers in -FITSIO automatically point to the first HDU in the file. The following -routines may be used to move to another HDU in the file. Note that -the HDU numbering convention used in FITSIO denotes the primary array -as the first HDU, the first extension in a FITS file is the second HDU, -and so on. - ->1 Move to a specified (absolute) HDU in the FITS file (nhdu = 1 for the -> FITS primary array) -- - FTMAHD(unit,nhdu, > hdutype,status) -- ->>2 Move to a new (existing) HDU forward or backwards relative to the CHDU -- - FTMRHD(unit,nmove, > hdutype,status) -- ->3 Move to the (first) HDU which has the specified extension type and - EXTNAME (or HDUNAME) and EXTVER keyword values. The hdutype parameter - may have - a value of IMAGE\_HDU (0), ASCII\_TBL (1), BINARY\_TBL (2), or ANY\_HDU (-1) - where ANY\_HDU means that only the extname and extver values will be - used to locate the correct extension. If the input value of - extver is 0 then the EXTVER keyword is ignored and the first HDU - with a matching EXTNAME (or HDUNAME) keyword will be found. If no - matching HDU is found in the file then the current HDU will remain - unchanged -> and a status = BAD\_HDU\_NUM (301) will be returned. -- - FTMNHD(unit, hdutype, extname, extver, > status) -- ->>4 Get the number of the current HDU in the FITS file (primary array = 1) -- - FTGHDN(unit, > nhdu) -- ->5 Return the type of the current HDU in the FITS file. The possible -> values for hdutype are IMAGE\_HDU (0), ASCII\_TBL (1), or BINARY\_TBL (2). -- - FTGHDT(unit, > hdutype, status) -- ->6 Return the total number of HDUs in the FITS file. -> The CHDU remains unchanged. -- - FTTHDU(unit, > hdunum, status) -- ->7 Create (append) a new empty HDU at the end of the FITS file. This - new HDU becomes the Current HDU, but it is completely empty and contains - no header keywords or data. It is recommended that FTIIMG, FTITAB or -> FTIBIN be used instead of this routine. -- - FTCRHD(unit, > status) -- - ->8 Create a primary array (if none already exists), or insert a - new IMAGE extension immediately following the CHDU, or - insert a new Primary Array at the beginning of the file. Any - following extensions in the file will be shifted down to make room - for the new extension. If the CHDU is the last HDU in the file - then the new image extension will simply be appended to the end of - the file. One can force a new primary array to be inserted at the - beginning of the FITS file by setting status = -9 prior - to calling the routine. In this case the existing primary array will be - converted to an IMAGE extension. The new extension (or primary - array) will become the CHDU. The FTIIMGLL routine is identical - to the FTIIMG routine except that the 4th parameter (the length - of each axis) is an array of 64-bit integers rather than an array -> of 32-bit integers. -- - FTIIMG(unit,bitpix,naxis,naxes, > status) - FTIIMGLL(unit,bitpix,naxis,naxesll, > status) -- ->9 Insert a new ASCII TABLE extension immediately following the CHDU. - Any following extensions will be shifted down to make room for - the new extension. If there are no other following extensions - then the new table extension will simply be appended to the - end of the file. The new extension will become the CHDU. The FTITABLL - routine is identical - to the FTITAB routine except that the 2nd and 3rd parameters (that give - the size of the table) are 64-bit integers rather than -> 32-bit integers. -- - FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > - status) - FTITABLL(unit,rowlenll,nrowsll,tfields,ttype,tbcol,tform,tunit,extname, > - status) -- - ->10 Insert a new binary table extension immediately following the CHDU. - Any following extensions will be shifted down to make room for - the new extension. If there are no other following extensions - then the new bintable extension will simply be appended to the - end of the file. The new extension will become the CHDU. The FTIBINLL - routine is identical - to the FTIBIN routine except that the 2nd parameter (that gives - the length of the table) is a 64-bit integer rather than -> a 32-bit integer. -- - FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) - FTIBINLL(unit,nrowsll,tfields,ttype,tform,tunit,extname,varidat > status) - -- - ->11 Resize an image by modifing the size, dimensions, and/or datatype of the - current primary array or image extension. If the new image, as specified - by the input arguments, is larger than the current existing image - in the FITS file then zero fill data will be inserted at the end - of the current image and any following extensions will be moved - further back in the file. Similarly, if the new image is - smaller than the current image then any following extensions - will be shifted up towards the beginning of the FITS file - and the image data will be truncated to the new size. - This routine rewrites the BITPIX, NAXIS, and NAXISn keywords - with the appropriate values for new image. The FTRSIMLL routine is identical - to the FTRSIM routine except that the 4th parameter (the length - of each axis) is an array of 64-bit integers rather than an array -> of 32-bit integers. -- - FTRSIM(unit,bitpix,naxis,naxes,status) - FTRSIMLL(unit,bitpix,naxis,naxesll,status) -- ->12 Delete the CHDU in the FITS file. Any following HDUs will be shifted - forward in the file, to fill in the gap created by the deleted - HDU. In the case of deleting the primary array (the first HDU in - the file) then the current primary array will be replace by a null - primary array containing the minimum set of required keywords and - no data. If there are more extensions in the file following the - one that is deleted, then the the CHDU will be redefined to point - to the following extension. If there are no following extensions - then the CHDU will be redefined to point to the previous HDU. The - output HDUTYPE parameter indicates the type of the new CHDU after -> the previous CHDU has been deleted. -- - FTDHDU(unit, > hdutype,status) -- ->13 Copy all or part of the input FITS file and append it - to the end of the output FITS file. If 'previous' (an integer parameter) is - not equal to 0, then any HDUs preceding the current HDU in the input file - will be copied to the output file. Similarly, 'current' and 'following' - determine whether the current HDU, and/or any following HDUs in the input - file will be copied to the output file. If all 3 parameters are not equal - to zero, then the entire input file will be copied. On return, the current - HDU in the input file will be unchanged, and the last copied HDU will be the -> current HDU in the output file. -- - FTCPFL(iunit, ounit, previous, current, following, > status) -- ->14 Copy the entire CHDU from the FITS file associated with IUNIT to the CHDU - of the FITS file associated with OUNIT. The output HDU must be empty and - not already contain any keywords. Space will be reserved for MOREKEYS - additional keywords in the output header if there is not already enough -> space. -- - FTCOPY(iunit,ounit,morekeys, > status) -- ->15 Copy the header (and not the data) from the CHDU associated with inunit - to the CHDU associated with outunit. If the current output HDU - is not completely empty, then the CHDU will be closed and a new - HDU will be appended to the output file. This routine will automatically - transform the necessary keywords when copying a primary array to - and image extension, or an image extension to a primary array. -> An empty output data unit will be created (all values = 0). -- - FTCPHD(inunit, outunit, > status) -- ->16 Copy just the data from the CHDU associated with IUNIT - to the CHDU associated with OUNIT. This will overwrite - any data previously in the OUNIT CHDU. This low level routine is used - by FTCOPY, but it may also be useful in certain application programs - which want to copy the data from one FITS file to another but also - want to modify the header keywords in the process. all the required - header keywords must be written to the OUNIT CHDU before calling -> this routine -- - FTCPDT(iunit,ounit, > status) -- - -**C. Define or Redefine the structure of the CHDU \label{FTRDEF} - -It should rarely be necessary to call the subroutines in this section. -FITSIO internally calls these routines whenever necessary, so any calls -to these routines by application programs will likely be redundant. - ->1 This routine forces FITSIO to scan the current header keywords that - define the structure of the HDU (such as the NAXISn, PCOUNT and GCOUNT - keywords) so that it can initialize the internal buffers that describe - the HDU structure. This routine may be used instead of the more - complicated calls to ftpdef, ftadef or ftbdef. This routine is - also very useful for reinitializing the structure of an HDU, - if the number of rows in a table, as specified by the NAXIS2 keyword, -> has been modified from its initial value. -- - FTRDEF(unit, > status) (DEPRECATED) -- ->2 Define the structure of the primary array or IMAGE extension. When - writing GROUPed FITS files that by convention set the NAXIS1 keyword - equal to 0, ftpdef must be called with naxes(1) = 1, NOT 0, otherwise - FITSIO will report an error status=308 when trying to write data - to a group. Note: it is usually simpler to call FTRDEF rather -> than this routine. -- - FTPDEF(unit,bitpix,naxis,naxes,pcount,gcount, > status) (DEPRECATED) -- ->3 Define the structure of an ASCII table (TABLE) extension. Note: it -> is usually simpler to call FTRDEF rather than this routine. -- - FTADEF(unit,rowlen,tfields,tbcol,tform,nrows > status) (DEPRECATED) -- ->4 Define the structure of a binary table (BINTABLE) extension. Note: it -> is usually simpler to call FTRDEF rather than this routine. -- - FTBDEF(unit,tfields,tform,varidat,nrows > status) (DEPRECATED) -- ->5 Define the size of the Current Data Unit, overriding the length - of the data unit as previously defined by ftpdef, ftadef, or ftbdef. - This is useful if one does not know the total size of the data unit until - after the data have been written. The size (in bytes) of an ASCII or - Binary table is given by NAXIS1 * NAXIS2. (Note that to determine the - value of NAXIS1 it is often more convenient to read the value of the - NAXIS1 keyword from the output file, rather than computing the row - length directly from all the TFORM keyword values). Note: it -> is usually simpler to call FTRDEF rather than this routine. -- - FTDDEF(unit,bytlen, > status) (DEPRECATED) -- ->6 Define the zero indexed byte offset of the 'heap' measured from - the start of the binary table data. By default the heap is assumed - to start immediately following the regular table data, i.e., at - location NAXIS1 x NAXIS2. This routine is only relevant for - binary tables which contain variable length array columns (with - TFORMn = 'Pt'). This subroutine also automatically writes - the value of theap to a keyword in the extension header. This - subroutine must be called after the required keywords have been - written (with ftphbn) and after the table structure has been defined -> (with ftbdef) but before any data is written to the table. -- - FTPTHP(unit,theap, > status) -- - -**D. FITS Header I/O Subroutines - -***1. Header Space and Position Routines \label{FTHDEF} - ->1 Reserve space in the CHU for MOREKEYS more header keywords. - This subroutine may be called to reserve space for keywords which are - to be written at a later time, after the data unit or subsequent - extensions have been written to the FITS file. If this subroutine is - not explicitly called, then the initial size of the FITS header will be - limited to the space available at the time that the first data is written - to the associated data unit. FITSIO has the ability to dynamically - add more space to the header if needed, however it is more efficient -> to preallocate the required space if the size is known in advance. -- - FTHDEF(unit,morekeys, > status) -- ->2 Return the number of existing keywords in the CHU (NOT including the - END keyword which is not considered a real keyword) and the remaining - space available to write additional keywords in the CHU. (returns - KEYSADD = -1 if the header has not yet been closed). - Note that FITSIO will attempt to dynamically add space for more -> keywords if required when appending new keywords to a header. -- - FTGHSP(iunit, > keysexist,keysadd,status) -- ->3 Return the number of keywords in the header and the current position - in the header. This returns the number of the keyword record that - will be read next (or one greater than the position of the last keyword - that was read or written). A value of 1 is returned if the pointer is -> positioned at the beginning of the header. -- - FTGHPS(iunit, > keysexist,key_no,status) -- -***2. Read or Write Standard Header Routines \label{FTPHPR} - -These subroutines provide a simple method of reading or writing most of -the keyword values that are normally required in a FITS files. These -subroutines are provided for convenience only and are not required to -be used. If preferred, users may call the lower-level subroutines -described in the previous section to individually read or write the -required keywords. Note that in most cases, the required keywords such -as NAXIS, TFIELD, TTYPEn, etc, which define the structure of the HDU -must be written to the header before any data can be written to the -image or table. - ->1 Put the primary header or IMAGE extension keywords into the CHU. -There are 2 available routines: The simpler FTPHPS routine is -equivalent to calling ftphpr with the default values of SIMPLE = true, -pcount = 0, gcount = 1, and EXTEND = true. PCOUNT, GCOUNT and EXTEND -keywords are not required in the primary header and are only written if -pcount is not equal to zero, gcount is not equal to zero or one, and if -extend is TRUE, respectively. When writing to an IMAGE extension, the ->SIMPLE and EXTEND parameters are ignored. -- - FTPHPS(unit,bitpix,naxis,naxes, > status) - - FTPHPR(unit,simple,bitpix,naxis,naxes,pcount,gcount,extend, > status) -- ->2 Get primary header or IMAGE extension keywords from the CHU. When - reading from an IMAGE extension the SIMPLE and EXTEND parameters are -> ignored. -- - FTGHPR(unit,maxdim, > simple,bitpix,naxis,naxes,pcount,gcount,extend, - status) -- ->3 Put the ASCII table header keywords into the CHU. The optional -TUNITn and EXTNAME keywords are written only if the input string ->values are not blank. -- - FTPHTB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > - status) -- ->>4 Get the ASCII table header keywords from the CHU -- - FTGHTB(unit,maxdim, > rowlen,nrows,tfields,ttype,tbcol,tform,tunit, - extname,status) -- ->5 Put the binary table header keywords into the CHU. The optional - TUNITn and EXTNAME keywords are written only if the input string - values are not blank. The pcount parameter, which specifies the - size of the variable length array heap, should initially = 0; - FITSIO will automatically update the PCOUNT keyword value if any - variable length array data is written to the heap. The TFORM keyword - value for variable length vector columns should have the form 'Pt(len)' - or '1Pt(len)' where `t' is the data type code letter (A,I,J,E,D, etc.) - and `len' is an integer specifying the maximum length of the vectors - in that column (len must be greater than or equal to the longest - vector in the column). If `len' is not specified when the table is - created (e.g., the input TFORMn value is just '1Pt') then FITSIO will - scan the column when the table is first closed and will append the - maximum length to the TFORM keyword value. Note that if the table - is subsequently modified to increase the maximum length of the vectors - then the modifying program is responsible for also updating the TFORM -> keyword value. - -- - FTPHBN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat, > status) -- ->>6 Get the binary table header keywords from the CHU -- - FTGHBN(unit,maxdim, > nrows,tfields,ttype,tform,tunit,extname,varidat, - status) -- -***3. Write Keyword Subroutines \label{FTPREC} - ->>1 Put (append) an 80-character record into the CHU. -- - FTPREC(unit,card, > status) -- ->2 Put (append) a COMMENT keyword into the CHU. Multiple COMMENT keywords -> will be written if the input comment string is longer than 72 characters. -- - FTPCOM(unit,comment, > status) -- ->3 Put (append) a HISTORY keyword into the CHU. Multiple HISTORY keywords -> will be written if the input history string is longer than 72 characters. -- - FTPHIS(unit,history, > status) -- ->4 Put (append) the DATE keyword into the CHU. The keyword value will contain - the current system date as a character string in 'dd/mm/yy' format. If - a DATE keyword already exists in the header, then this subroutine will -> simply update the keyword value in-place with the current date. -- - FTPDAT(unit, > status) -- ->5 Put (append) a new keyword of the appropriate datatype into the CHU. - Note that FTPKYS will only write string values up to 68 characters in - length; longer strings will be truncated. The FTPKLS routine can be - used to write longer strings, using a non-standard FITS convention. - The E and D versions of this routine have the added feature that - if the 'decimals' parameter is negative, then the 'G' display - format rather then the 'E' format will be used when constructing - the keyword value, taking the absolute value of 'decimals' for the - precision. This will suppress trailing zeros, and will use a - fixed format rather than an exponential format, -> depending on the magnitude of the value. -- - FTPKY[JKLS](unit,keyword,keyval,comment, > status) - FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) -- ->6 Put (append) a string valued keyword into the CHU which may be longer - than 68 characters in length. This uses the Long String Keyword - convention that is described in the "Usage Guidelines and Suggestions" - section of this document. Since this uses a non-standard FITS - convention to encode the long keyword string, programs which use - this routine should also call the FTPLSW routine to add some COMMENT - keywords to warn users of the FITS file that this convention is - being used. FTPLSW also writes a keyword called LONGSTRN to record - the version of the longstring convention that has been used, in case - a new convention is adopted at some point in the future. If the - LONGSTRN keyword is already present in the header, then FTPLSW will -> simply return and will not write duplicate keywords. -- - FTPKLS(unit,keyword,keyval,comment, > status) - FTPLSW(unit, > status) -- ->7 Put (append) a new keyword with an undefined, or null, value into the CHU. -> The value string of the keyword is left blank in this case. -- - FTPKYU(unit,keyword,comment, > status) -- ->8 Put (append) a numbered sequence of keywords into the CHU. One may - append the same comment to every keyword (and eliminate the need - to have an array of identical comment strings, one for each keyword) by - including the ampersand character as the last non-blank character in the - (first) COMMENTS string parameter. This same string - will then be used for the comment field in all the keywords. (Note - that the SPP version of these routines only supports a single comment -> string). -- - FTPKN[JKLS](unit,keyroot,startno,no_keys,keyvals,comments, > status) - FTPKN[EDFG](unit,keyroot,startno,no_keys,keyvals,decimals,comments, > - status) -- ->9 Copy an indexed keyword from one HDU to another, modifying - the index number of the keyword name in the process. For example, - this routine could read the TLMIN3 keyword from the input HDU - (by giving keyroot = "TLMIN" and innum = 3) and write it to the - output HDU with the keyword name TLMIN4 (by setting outnum = 4). - If the input keyword does not exist, then this routine simply -> returns without indicating an error. -- - FTCPKY(inunit, outunit, innum, outnum, keyroot, > status) -- ->10 Put (append) a 'triple precision' keyword into the CHU in F28.16 format. - The floating point keyword value is constructed by concatenating the - input integer value with the input double precision fraction value - (which must have a value between 0.0 and 1.0). The FTGKYT routine should - be used to read this keyword value, because the other keyword reading -> subroutines will not preserve the full precision of the value. -- - FTPKYT(unit,keyword,intval,dblval,comment, > status) -- ->11 Write keywords to the CHDU that are defined in an ASCII template file. - The format of the template file is described under the ftgthd -> routine below. -- - FTPKTP(unit, filename, > status) -- ->12 Append the physical units string to an existing keyword. This - routine uses a local convention, shown in the following example, - in which the keyword units are enclosed in square brackets in the -> beginning of the keyword comment field. - -- - VELOCITY= 12.3 / [km/s] orbital speed - - FTPUNT(unit,keyword,units, > status) -- -***4. Insert Keyword Subroutines \label{FTIREC} - ->1 Insert a new keyword record into the CHU at the specified position - (i.e., immediately preceding the (keyno)th keyword in the header.) - This 'insert record' subroutine is somewhat less efficient - then the 'append record' subroutine (FTPREC) described above because -> the remaining keywords in the header have to be shifted down one slot. -- - FTIREC(unit,key_no,card, > status) -- ->2 Insert a new keyword into the CHU. The new keyword is inserted - immediately following the last keyword that has been read from the header. - The FTIKLS subroutine works the same as the FTIKYS subroutine, except - it also supports long string values greater than 68 characters in length. - These 'insert keyword' subroutines are somewhat less efficient then - the 'append keyword' subroutines described above because the remaining -> keywords in the header have to be shifted down one slot. -- - FTIKEY(unit, card, > status) - FTIKY[JKLS](unit,keyword,keyval,comment, > status) - FTIKLS(unit,keyword,keyval,comment, > status) - FTIKY[EDFG](unit,keyword,keyval,decimals,comment, > status) -- ->3 Insert a new keyword with an undefined, or null, value into the CHU. -> The value string of the keyword is left blank in this case. -- - FTIKYU(unit,keyword,comment, > status) -- -***5. Read Keyword Subroutines \label{FTGREC} - -These routines return the value of the specified keyword(s). Wild card -characters (*, ?, or \#) may be used when specifying the name of the keyword -to be read: a '?' will match any single character at that position in the -keyword name and a '*' will match any length (including zero) string of -characters. The '\#' character will match any consecutive string of -decimal digits (0 - 9). Note that when a wild card is used in the input -keyword name, the routine will only search for a match from the current -header position to the end of the header. It will not resume the search -from the top of the header back to the original header position as is done -when no wildcards are included in the keyword name. If the desired -keyword string is 8-characters long (the maximum length of a keyword -name) then a '*' may be appended as the ninth character of the input -name to force the keyword search to stop at the end of the header -(e.g., 'COMMENT *' will search for the next COMMENT keyword). The -ffgrec routine may be used to set the starting position when doing -wild card searches. - ->1 Get the nth 80-character header record from the CHU. The first keyword - in the header is at key\_no = 1; if key\_no = 0 then this subroutine - simple moves the internal pointer to the beginning of the header - so that subsequent keyword operations will start at the top of -> the header; it also returns a blank card value in this case. -- - FTGREC(unit,key_no, > card,status) -- ->2 Get the name, value (as a string), and comment of the nth keyword in CHU. - This routine also checks that the returned keyword name (KEYWORD) contains - only legal ASCII characters. Call FTGREC and FTPSVC to bypass this error -> check. -- - FTGKYN(unit,key_no, > keyword,value,comment,status) -- ->>3 Get the 80-character header record for the named keyword -- - FTGCRD(unit,keyword, > card,status) -- ->4 Get the next keyword whose name matches one of the strings in - 'inclist' but does not match any of the strings in 'exclist'. - The strings in inclist and exclist may contain wild card characters - (*, ?, and \#) as described at the beginning of this section. - This routine searches from the current header position to the - end of the header, only, and does not continue the search from - the top of the header back to the original position. The current - header position may be reset with the ftgrec routine. Note - that nexc may be set = 0 if there are no keywords to be excluded. - This routine returns status = 202 if a matching -> keyword is not found. -- - FTGNXK(unit,inclist,ninc,exclist,nexc, > card,status) -- ->5 Get the literal keyword value as a character string. Regardless - of the datatype of the keyword, this routine simply returns the - string of characters in the value field of the keyword along with -> the comment field. -- - FTGKEY(unit,keyword, > value,comment,status) -- ->6 Get a keyword value (with the appropriate datatype) and comment from -> the CHU -- - FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) -- ->7 Read a string-valued keyword and return the string length, the value string, - and/or the comment field. The first routine, FTGKSL, simply - returns the length of the character string value of the specified keyword. - The second routine, FTGSKY, also returns up to maxchar characters - of the keyword value string, starting with the firstchar character, - and the keyword comment string. - The length argument returns the total length of the keyword value string - regardless of how much of the string is actually returned (which - depends on the value of the firstchar and maxchar arguments). These - routines support string keywords that use the CONTINUE convention to - continue long string values over multiple FITS header records. Normally, - string-valued keywords have a maximum length of 68 characters, however, -> CONTINUE'd string keywords may be arbitrarily long. -- - FTGKSL(unit,keyword, > length,status) - FTGSKY(unit,keyword,firstchar,maxchar,> keyval,length,comment,status) -- ->8 Get a sequence of numbered keyword values. These -> routines do not support wild card characters in the root name. -- - FTGKN[EDJKLS](unit,keyroot,startno,max_keys, > keyvals,nfound,status) -- ->9 Get the value of a floating point keyword, returning the integer and - fractional parts of the value in separate subroutine arguments. - This subroutine may be used to read any keyword but is especially -> useful for reading the 'triple precision' keywords written by FTPKYT. -- - FTGKYT(unit,keyword, > intval,dblval,comment,status) -- ->10 Get the physical units string in an existing keyword. This - routine uses a local convention, shown in the following example, - in which the keyword units are - enclosed in square brackets in the beginning of the keyword comment - field. A blank string is returned if no units are defined -> for the keyword. -- - VELOCITY= 12.3 / [km/s] orbital speed - - FTGUNT(unit,keyword, > units,status) -- -***6. Modify Keyword Subroutines \label{FTMREC} - -Wild card characters, as described in the Read Keyword section, above, -may be used when specifying the name of the keyword to be modified. - ->>1 Modify (overwrite) the nth 80-character header record in the CHU -- - FTMREC(unit,key_no,card, > status) -- ->2 Modify (overwrite) the 80-character header record for the named keyword - in the CHU. This can be used to overwrite the name of the keyword as -> well as its value and comment fields. -- - FTMCRD(unit,keyword,card, > status) -- ->3 Modify (overwrite) the name of an existing keyword in the CHU -> preserving the current value and comment fields. -- - FTMNAM(unit,oldkey,keyword, > status) -- ->>4 Modify (overwrite) the comment field of an existing keyword in the CHU -- - FTMCOM(unit,keyword,comment, > status) -- ->5 Modify the value and comment fields of an existing keyword in the CHU. - The FTMKLS subroutine works the same as the FTMKYS subroutine, except - it also supports long string values greater than 68 characters in length. - Optionally, one may modify only the value field and leave the comment - field unchanged by setting the input COMMENT parameter equal to - the ampersand character (\&). - The E and D versions of this routine have the added feature that - if the 'decimals' parameter is negative, then the 'G' display - format rather then the 'E' format will be used when constructing - the keyword value, taking the absolute value of 'decimals' for the - precision. This will suppress trailing zeros, and will use a - fixed format rather than an exponential format, -> depending on the magnitude of the value. -- - FTMKY[JKLS](unit,keyword,keyval,comment, > status) - FTMKLS(unit,keyword,keyval,comment, > status) - FTMKY[EDFG](unit,keyword,keyval,decimals,comment, > status) -- ->6 Modify the value of an existing keyword to be undefined, or null. - The value string of the keyword is set to blank. - Optionally, one may leave the comment field unchanged by setting the -> input COMMENT parameter equal to the ampersand character (\&). -- - FTMKYU(unit,keyword,comment, > status) -- -***7. Update Keyword Subroutines \label{FTUCRD} - ->1 Update an 80-character record in the CHU. If the specified keyword - already exists then that header record will be replaced with - the input CARD string. If it does not exist then the new record will - be added to the header. - The FTUKLS subroutine works the same as the FTUKYS subroutine, except -> it also supports long string values greater than 68 characters in length. -- - FTUCRD(unit,keyword,card, > status) -- ->2 Update the value and comment fields of a keyword in the CHU. - The specified keyword is modified if it already exists (by calling - FTMKYx) otherwise a new keyword is created by calling FTPKYx. - The E and D versions of this routine have the added feature that - if the 'decimals' parameter is negative, then the 'G' display - format rather then the 'E' format will be used when constructing - the keyword value, taking the absolute value of 'decimals' for the - precision. This will suppress trailing zeros, and will use a - fixed format rather than an exponential format, -> depending on the magnitude of the value. -- - FTUKY[JKLS](unit,keyword,keyval,comment, > status) - FTUKLS(unit,keyword,keyval,comment, > status) - FTUKY[EDFG](unit,keyword,keyval,decimals,comment, > status) -- ->3 Update the value of an existing keyword to be undefined, or null, - or insert a new undefined-value keyword if it doesn't already exist. -> The value string of the keyword is left blank in this case. -- - FTUKYU(unit,keyword,comment, > status) -- -***8. Delete Keyword Subroutines \label{FTDREC} - ->1 Delete an existing keyword record. The space previously occupied by - the keyword is reclaimed by moving all the following header records up - one row in the header. The first routine deletes a keyword at a - specified position in the header (the first keyword is at position 1), - whereas the second routine deletes a specifically named keyword. - Wild card characters, as described in the Read Keyword section, above, - may be used when specifying the name of the keyword to be deleted -> (be careful!). -- - FTDREC(unit,key_no, > status) - FTDKEY(unit,keyword, > status) -- - -**F. Data Scaling and Undefined Pixel Parameters \label{FTPSCL} - -These subroutines define or modify the internal parameters used by -FITSIO to either scale the data or to represent undefined pixels. -Generally FITSIO will scale the data according to the values of the BSCALE -and BZERO (or TSCALn and TZEROn) keywords, however these subroutines -may be used to override the keyword values. This may be useful when -one wants to read or write the raw unscaled values in the FITS file. -Similarly, FITSIO generally uses the value of the BLANK or TNULLn -keyword to signify an undefined pixel, but these routines may be used -to override this value. These subroutines do not create or modify the -corresponding header keyword values. - ->1 Reset the scaling factors in the primary array or image extension; does - not change the BSCALE and BZERO keyword values and only affects the - automatic scaling performed when the data elements are written/read - to/from the FITS file. When reading from a FITS file the returned - data value = (the value given in the FITS array) * BSCALE + BZERO. - The inverse formula is used when writing data values to the FITS - file. (NOTE: BSCALE and BZERO must be declared as Double Precision -> variables). -- - FTPSCL(unit,bscale,bzero, > status) -- ->2 Reset the scaling parameters for a table column; does not change - the TSCALn or TZEROn keyword values and only affects the automatic - scaling performed when the data elements are written/read to/from - the FITS file. When reading from a FITS file the returned data - value = (the value given in the FITS array) * TSCAL + TZERO. The - inverse formula is used when writing data values to the FITS file. - (NOTE: TSCAL and TZERO must be declared as Double Precision -> variables). -- - FTTSCL(unit,colnum,tscal,tzero, > status) -- ->3 Define the integer value to be used to signify undefined pixels in the - primary array or image extension. This is only used if BITPIX = 8, 16, - 32. or 64 This does not create or change the value of the BLANK keyword in - the header. FTPNULLL is identical to FTPNUL except that the blank -> value is a 64-bit integer instead of a 32-bit integer. -- - FTPNUL(unit,blank, > status) - FTPNULLL(unit,blankll, > status) -- ->4 Define the string to be used to signify undefined pixels in - a column in an ASCII table. This does not create or change the value -> of the TNULLn keyword. -- - FTSNUL(unit,colnum,snull > status) -- ->5 Define the value to be used to signify undefined pixels in - an integer column in a binary table (where TFORMn = 'B', 'I', 'J', or 'K'). - This does not create or change the value of the TNULLn keyword. - FTTNULLL is identical to FTTNUL except that the tnull -> value is a 64-bit integer instead of a 32-bit integer. -- - FTTNUL(unit,colnum,tnull > status) - FTTNULLL(unit,colnum,tnullll > status) -- - -**G. FITS Primary Array or IMAGE Extension I/O Subroutines \label{FTPPR} - - These subroutines put or get data values in the primary data array -(i.e., the first HDU in the FITS file) or an IMAGE extension. The -data array is represented as a single one-dimensional array of -pixels regardless of the actual dimensionality of the array, and the -FPIXEL parameter gives the position within this 1-D array of the first -pixel to read or write. Automatic data type conversion is performed -for numeric data (except for complex data types) if the data type of -the primary array (defined by the BITPIX keyword) differs from the data -type of the array in the calling subroutine. The data values are also -scaled by the BSCALE and BZERO header values as they are being written -or read from the FITS array. The ftpscl subroutine MUST be -called to define the scaling parameters when writing data to the FITS -array or to override the default scaling value given in the header when -reading the FITS array. - - Two sets of subroutines are provided to read the data array which -differ in the way undefined pixels are handled. The first set of -routines (FTGPVx) simply return an array of data elements in which -undefined pixels are set equal to a value specified by the user in the -'nullval' parameter. An additional feature of these subroutines is -that if the user sets nullval = 0, then no checks for undefined pixels -will be performed, thus increasing the speed of the program. The -second set of routines (FTGPFx) returns the data element array and, in -addition, a logical array which defines whether the corresponding data -pixel is undefined. The latter set of subroutines may be more -convenient to use in some circumstances, however, it requires an -additional array of logical values which can be unwieldy when working -with large data arrays. Also for programmer convenience, sets of -subroutines to directly read or write 2 and 3 dimensional arrays have -been provided, as well as a set of subroutines to read or write any -contiguous rectangular subset of pixels within the n-dimensional array. - ->1 Get the data type of the image (= BITPIX value). Possible returned - values are: 8, 16, 32, 64, -32, or -64 corresponding to unsigned byte, - signed 2-byte integer, signed 4-byte integer, signed 8-byte integer, - real, and double. - - The second subroutine is similar to FTGIDT, except that if the image - pixel values are scaled, with non-default values for the BZERO and - BSCALE keywords, then this routine will return the 'equivalent' - data type that is needed to store the scaled values. For example, - if BITPIX = 16 and BSCALE = 0.1 then the equivalent data type is - floating point, and -32 will be returned. There are 2 special cases: - if the image contains unsigned 2-byte integer values, with BITPIX = - 16, BSCALE = 1, and BZERO = 32768, then this routine will return - a non-standard value of 20 for the bitpix value. Similarly if the - image contains unsigned 4-byte integers, then bitpix will -> be returned with a value of 40. - -- - FTGIDT(unit, > bitpix,status) - FTGIET(unit, > bitpix,status) -- ->>2 Get the dimension (number of axes = NAXIS) of the image -- - FTGIDM(unit, > naxis,status) -- ->3 Get the size of all the dimensions of the image. The FTGISZLL -> routine returns an array of 64-bit integers instead of 32-bit integers. -- - FTGISZ(unit, maxdim, > naxes,status) - FTGISZLL(unit, maxdim, > naxesll,status) -- ->4 Get the parameters that define the type and size of the image. This - routine simply combines calls to the above 3 routines. The FTGIPRLL -> routine returns an array of 64-bit integers instead of 32-bit integers. - -- - FTGIPR(unit, maxdim, > bitpix, naxis, naxes, int *status) - FTGIPRLL(unit, maxdim, > bitpix, naxis, naxesll, int *status) -- ->>5 Put elements into the data array -- - FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) -- ->6 Put elements into the data array, substituting the appropriate FITS null - value for all elements which are equal to the value of NULLVAL. For - integer FITS arrays, the null value defined by the previous call to FTPNUL - will be substituted; for floating point FITS arrays (BITPIX = -32 - or -64) then the special IEEE NaN (Not-a-Number) value will be -> substituted. -- - FTPPN[BIJKED](unit,group,fpixel,nelements,values,nullval > status) -- ->>7 Set data array elements as undefined -- - FTPPRU(unit,group,fpixel,nelements, > status) -- ->8 Get elements from the data array. Undefined array elements will be - returned with a value = nullval, unless nullval = 0 in which case no -> checks for undefined pixels will be performed. -- - FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) -- ->9 Get elements and nullflags from data array. - Any undefined array elements will have the corresponding flagvals element -> set equal to .TRUE. -- - FTGPF[BIJKED](unit,group,fpixel,nelements, > values,flagvals,anyf,status) -- ->>10 Put values into group parameters -- - FTPGP[BIJKED](unit,group,fparm,nparm,values, > status) -- ->>11 Get values from group parameters -- - FTGGP[BIJKED](unit,group,fparm,nparm, > values,status) -- -The following 4 subroutines transfer FITS images with 2 or 3 dimensions -to or from a data array which has been declared in the calling program. -The dimensionality of the FITS image is passed by the naxis1, naxis2, -and naxis3 parameters and the declared dimensions of the program array -are passed in the dim1 and dim2 parameters. Note that the program array -does not have to have the same dimensions as the FITS array, but must -be at least as big. For example if a FITS image with NAXIS1 = NAXIS2 = 400 -is read into a program array which is dimensioned as 512 x 512 pixels, -then the image will just fill the lower left corner of the array -with pixels in the range 1 - 400 in the X an Y directions. This has -the effect of taking a contiguous set of pixel value in the FITS array -and writing them to a non-contiguous array in program memory -(i.e., there are now some blank pixels around the edge of the image -in the program array). - ->>11 Put 2-D image into the data array -- - FTP2D[BIJKED](unit,group,dim1,naxis1,naxis2,image, > status) -- ->>12 Put 3-D cube into the data array -- - FTP3D[BIJKED](unit,group,dim1,dim2,naxis1,naxis2,naxis3,cube, > status) -- ->13 Get 2-D image from the data array. Undefined - pixels in the array will be set equal to the value of 'nullval', - unless nullval=0 in which case no testing for undefined pixels will -> be performed. -- - FTG2D[BIJKED](unit,group,nullval,dim1,naxis1,naxis2, > image,anyf,status) -- ->14 Get 3-D cube from the data array. Undefined - pixels in the array will be set equal to the value of 'nullval', - unless nullval=0 in which case no testing for undefined pixels will -> be performed. -- - FTG3D[BIJKED](unit,group,nullval,dim1,dim2,naxis1,naxis2,naxis3, > - cube,anyf,status) -- - -The following subroutines transfer a rectangular subset of the pixels -in a FITS N-dimensional image to or from an array which has been -declared in the calling program. The fpixels and lpixels parameters -are integer arrays which specify the starting and ending pixels in each -dimension of the FITS image that are to be read or written. (Note that -these are the starting and ending pixels in the FITS image, not in the -declared array). The array parameter is treated simply as a large -one-dimensional array of the appropriate datatype containing the pixel -values; The pixel values in the FITS array are read/written from/to -this program array in strict sequence without any gaps; it is up to -the calling routine to correctly interpret the dimensionality of this -array. The two families of FITS reading routines (FTGSVx and FTGSFx -subroutines) also have an 'incs' parameter which defines the -data sampling interval in each dimension of the FITS array. For -example, if incs(1)=2 and incs(2)=3 when reading a 2-dimensional -FITS image, then only every other pixel in the first dimension -and every 3rd pixel in the second dimension will be returned in -the 'array' parameter. [Note: the FTGSSx family of routines which -were present in previous versions of FITSIO have been superseded -by the more general FTGSVx family of routines.] - ->>15 Put an arbitrary data subsection into the data array. -- - FTPSS[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,array, > status) -- ->16 Get an arbitrary data subsection from the data array. Undefined - pixels in the array will be set equal to the value of 'nullval', - unless nullval=0 in which case no testing for undefined pixels will -> be performed. -- - FTGSV[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs,nullval, > - array,anyf,status) -- ->17 Get an arbitrary data subsection from the data array. Any Undefined - pixels in the array will have the corresponding 'flagvals' -> element set equal to .TRUE. -- - FTGSF[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs, > - array,flagvals,anyf,status) -- - -**H. FITS ASCII and Binary Table Data I/O Subroutines - -***1. Column Information Subroutines \label{FTGCNO} - ->1 Get the number of rows or columns in the current FITS table. - The number of rows is given by the NAXIS2 keyword and the - number of columns is given by the TFIELDS keyword in the header - of the table. The FTGNRWLL routine is identical to FTGNRW except - that the number of rows is returned as a 64-bit integer rather -> than a 32-bit integer. -- - FTGNRW(unit, > nrows, status) - FTGNRWLL(unit, > nrowsll, status) - FTGNCL(unit, > ncols, status) -- ->2 Get the table column number (and name) of the column whose name -matches an input template name. The table column names are defined by -the TTYPEn keywords in the FITS header. If a column does not have a -TTYPEn keyword, then these routines assume that the name consists of -all blank characters. These 2 subroutines perform the same function -except that FTGCNO only returns the number of the matching column whereas -FTGCNN also returns the name of the column. If CASESEN = .true. then -the column name match will be case-sensitive. - -The input column name template (COLTEMPLATE) is (1) either the exact -name of the column to be searched for, or (2) it may contain wild cards -characters (*, ?, or \#), or (3) it may contain the number of the desired -column (where the number is expressed as ASCII digits). The first 2 wild -cards behave similarly to UNIX filename matching: the '*' character matches -any sequence of characters (including zero characters) and the '?' -character matches any single character. The \# wildcard will match -any consecutive string of decimal digits (0-9). As an example, the template -strings 'AB?DE', 'AB*E', and 'AB*CDE' will all match the string -'ABCDE'. If more than one column name in the table matches the -template string, then the first match is returned and the status value -will be set to 237 as a warning that a unique match was not found. To -find the other cases that match the template, simply call the -subroutine again leaving the input status value equal to 237 and the -next matching name will then be returned. Repeat this process until a -status = 219 (column name not found) is returned. If these subroutines -fail to match the template to any of the columns in the table, they -lastly check if the template can be interpreted as a simple positive -integer (e.g., '7', or '512') and if so, they return that column -number. If no matches are found then a status = 219 error is -returned. - -Note that the FITS Standard recommends that only letters, digits, and -the underscore character be used in column names (with no embedded ->spaces in the name). Trailing blank characters are not significant. -- - FTGCNO(unit,casesen,coltemplate, > colnum,status) - FTGCNN(unit,casesen,coltemplate, > colname,colnum,status) -- ->3 Get the datatype of a column in an ASCII or binary table. This - routine returns an integer code value corresponding to the datatype - of the column. (See the FTBNFM and FTASFM subroutines in the Utilities - section of this document for a list of the code values). The vector - repeat count (which is alway 1 for ASCII table columns) is also returned. - If the specified column has an ASCII character datatype (code = 16) then - the width of a unit string in the column is also returned. Note that - this routine supports the local convention for specifying arrays of - strings within a binary table character column, using the syntax - TFORM = 'rAw' where 'r' is the total number of characters (= the width - of the column) and 'w' is the width of a unit string within the column. - Thus if the column has TFORM = '60A12' then this routine will return - datacode = 16, repeat = 60, and width = 12. (The TDIMn - keyword may also be used to specify the unit string length; The pair - of keywords TFORMn = '60A' and TDIMn = '(12,5)' would have the - same effect as TFORMn = '60A12'). - - The second routine, FTEQTY is similar except that in - the case of scaled integer columns it returns the 'equivalent' data - type that is needed to store the scaled values, and not necessarily - the physical data type of the unscaled values as stored in the FITS - table. For example if a '1I' column in a binary table has TSCALn = - 1 and TZEROn = 32768, then this column effectively contains unsigned - short integer values, and thus the returned value of typecode will - be the code for an unsigned short integer, not a signed short integer. - Similarly, if a column has TTYPEn = '1I' - and TSCALn = 0.12, then the returned typecode -> will be the code for a 'real' column. -- - FTGTCL(unit,colnum, > datacode,repeat,width,status) - FTEQTY(unit,colnum, > datacode,repeat,width,status) -- ->4 Return the display width of a column. This is the length - of the string that will be returned - when reading the column as a formatted string. The display width is - determined by the TDISPn keyword, if present, otherwise by the data -> type of the column. -- - FTGCDW(unit, colnum, > dispwidth, status) -- ->5 Get information about an existing ASCII table column. (NOTE: TSCAL and - TZERO must be declared as Double Precision variables). All the -> returned parameters are scalar quantities. -- - FTGACL(unit,colnum, > - ttype,tbcol,tunit,tform,tscal,tzero,snull,tdisp,status) -- ->6 Get information about an existing binary table column. (NOTE: TSCAL and - TZERO must be declared as Double Precision variables). DATATYPE is a - character string which returns the datatype of the column as defined - by the TFORMn keyword (e.g., 'I', 'J','E', 'D', etc.). In the case - of an ASCII character column, DATATYPE will have a value of the - form 'An' where 'n' is an integer expressing the width of the field - in characters. For example, if TFORM = '160A8' then FTGBCL will return - DATATYPE='A8' and REPEAT=20. All the returned parameters are scalar -> quantities. -- - FTGBCL(unit,colnum, > - ttype,tunit,datatype,repeat,tscal,tzero,tnull,tdisp,status) -- ->7 Put (append) a TDIMn keyword whose value has the form '(l,m,n...)' - where l, m, n... are the dimensions of a multidimensional array -> column in a binary table. -- - FTPTDM(unit,colnum,naxis,naxes, > status) -- ->8 Return the number of and size of the dimensions of a table column. - Normally this information is given by the TDIMn keyword, but if - this keyword is not present then this routine returns NAXIS = 1 -> and NAXES(1) equal to the repeat count in the TFORM keyword. -- - FTGTDM(unit,colnum,maxdim, > naxis,naxes,status) -- ->9 Decode the input TDIMn keyword string (e.g. '(100,200)') and return the - number of and size of the dimensions of a binary table column. If the input - tdimstr character string is null, then this routine returns naxis = 1 - and naxes[0] equal to the repeat count in the TFORM keyword. This routine -> is called by FTGTDM. -- - FTDTDM(unit,tdimstr,colnum,maxdim, > naxis,naxes, status) -- ->10 Return the optimal number of rows to read or write at one time for - maximum I/O efficiency. Refer to the ``Optimizing Code'' section -> in Chapter 5 for more discussion on how to use this routine. - -- - FTGRSZ(unit, > nrows,status) -- - -***2. Low-Level Table Access Subroutines \label{FTGTBS} - -The following subroutines provide low-level access to the data in ASCII -or binary tables and are mainly useful as an efficient way to copy all -or part of a table from one location to another. These routines simply -read or write the specified number of consecutive bytes in an ASCII or -binary table, without regard for column boundaries or the row length in -the table. The first two subroutines read or write consecutive bytes -in a table to or from a character string variable, while the last two -subroutines read or write consecutive bytes to or from a variable -declared as a numeric data type (e.g., INTEGER, INTEGER*2, REAL, DOUBLE -PRECISION). These routines do not perform any machine dependent data -conversion or byte swapping, except that conversion to/from ASCII -format is performed by the FTGTBS and FTPTBS routines on machines which -do not use ASCII character codes in the internal data representations -(e.g., on IBM mainframe computers). - ->1 Read a consecutive string of characters from an ASCII table - into a character variable (spanning columns and multiple rows if necessary) - This routine should not be used with binary tables because of -> complications related to passing string variables between C and Fortran. -- - FTGTBS(unit,frow,startchar,nchars, > string,status) -- ->2 Write a consecutive string of characters to an ASCII table - from a character variable (spanning columns and multiple rows if necessary) - This routine should not be used with binary tables because of -> complications related to passing string variables between C and Fortran. -- - FTPTBS(unit,frow,startchar,nchars,string, > status) -- ->3 Read a consecutive array of bytes from an ASCII or binary table - into a numeric variable (spanning columns and multiple rows if necessary). - The array parameter may be declared as any numerical datatype as long - as the array is at least 'nchars' bytes long, e.g., if nchars = 17, -> then declare the array as INTEGER*4 ARRAY(5). -- - FTGTBB(unit,frow,startchar,nchars, > array,status) -- ->4 Write a consecutive array of bytes to an ASCII or binary table - from a numeric variable (spanning columns and multiple rows if necessary) - The array parameter may be declared as any numerical datatype as long - as the array is at least 'nchars' bytes long, e.g., if nchars = 17, -> then declare the array as INTEGER*4 ARRAY(5). -- - FTPTBB(unit,frow,startchar,nchars,array, > status) -- - -***3. Edit Rows or Columns \label{FTIROW} - ->1 Insert blank rows into an existing ASCII or binary table (in the CDU). - All the rows FOLLOWING row FROW are shifted down by NROWS rows. If - FROW or FROWLL equals 0 then the blank rows are inserted at the beginning of the - table. These routines modify the NAXIS2 keyword to reflect the new - number of rows in the table. Note that it is *not* necessary to insert rows in a table before - writing data to those rows (indeed, it would be inefficient to do so). - Instead, one may simply write data to any row of the table, whether that -> row of data already exists or not. -- - FTIROW(unit,frow,nrows, > status) - FTIROWLL(unit,frowll,nrowsll, > status) -- ->2 Delete rows from an existing ASCII or binary table (in the CDU). - The NROWS (or NROWSLL) is the number of rows are deleted, starting - with row FROW (or FROWLL), and - any remaining rows in the table are shifted up to fill in the space. - These routines modify the NAXIS2 keyword to reflect the new number -> of rows in the table. -- - FTDROW(unit,frow,nrows, > status) - FTDROWLL(unit,frowll,nrowsll, > status) -- ->3 Delete a list of rows from an ASCII or binary table (in the CDU). - In the first routine, 'rowrange' is a character string listing the - rows or row ranges to delete (e.g., '2-4, 5, 8-9'). In the second - routine, 'rowlist' is an integer array of row numbers to be deleted - from the table. nrows is the number of row numbers in the list. - The first row in the table is 1 not 0. The list of row numbers -> must be sorted in ascending order. -- - FTDRRG(unit,rowrange, > status) - FTDRWS(unit,rowlist,nrows, > status) -- ->4 Insert a blank column (or columns) into an existing ASCII or binary - table (in the CDU). COLNUM specifies the column number that the (first) - new column should occupy in the table. NCOLS specifies how many - columns are to be inserted. Any existing columns from this position and - higher are moved over to allow room for the new column(s). - The index number on all the following keywords will be incremented - if necessary to reflect the new position of the column(s) in the table: - TBCOLn, TFORMn, TTYPEn, TUNITn, TNULLn, TSCALn, TZEROn, TDISPn, TDIMn, - TLMINn, TLMAXn, TDMINn, TDMAXn, TCTYPn, TCRPXn, TCRVLn, TCDLTn, TCROTn, -> and TCUNIn. -- - FTICOL(unit,colnum,ttype,tform, > status) - FTICLS(unit,colnum,ncols,ttype,tform, > status) -- ->5 Modify the vector length of a binary table column (e.g., - change a column from TFORMn = '1E' to '20E'). The vector -> length may be increased or decreased from the current value. -- - FTMVEC(unit,colnum,newveclen, > status) -- ->6 Delete a column from an existing ASCII or binary table (in the CDU). - The index number of all the keywords listed above (for FTICOL) will be - decremented if necessary to reflect the new position of the column(s) in - the table. Those index keywords that refer to the deleted column will - also be deleted. Note that the physical size of the FITS file will - not be reduced by this operation, and the empty FITS blocks if any -> at the end of the file will be padded with zeros. -- - FTDCOL(unit,colnum, > status) -- ->7 Copy a column from one HDU to another (or to the same HDU). If - createcol = TRUE, then a new column will be inserted in the output - table, at position `outcolumn', otherwise the existing output column will - be overwritten (in which case it must have a compatible datatype). -> Note that the first column in a table is at colnum = 1. -- - FTCPCL(inunit,outunit,incolnum,outcolnum,createcol, > status); -- -***4. Read and Write Column Data Routines \label{FTPCLS} - -These subroutines put or get data values in the current ASCII or Binary table -extension. Automatic data type conversion is performed for numerical data -types (B,I,J,E,D) if the data type of the column (defined by the TFORM keyword) -differs from the data type of the calling subroutine. The data values are also -scaled by the TSCALn and TZEROn header values as they are being written to -or read from the FITS array. The fttscl subroutine MUST be used to define the -scaling parameters when writing data to the table or to override the default -scaling values given in the header when reading from the table. -Note that it is *not* necessary to insert rows in a table before -writing data to those rows (indeed, it would be inefficient to do so). -Instead, one may simply write data to any row of the table, whether that -row of data already exists or not. - - In the case of binary tables with vector elements, the 'felem' -parameter defines the starting pixel within the element vector. This -parameter is ignored with ASCII tables. Similarly, in the case of -binary tables the 'nelements' parameter specifies the total number of -vector values read or written (continuing on subsequent rows if -required) and not the number of table elements. Two sets of -subroutines are provided to get the column data which differ in the way -undefined pixels are handled. The first set of routines (FTGCV) -simply return an array of data elements in which undefined pixels are -set equal to a value specified by the user in the 'nullval' parameter. -An additional feature of these subroutines is that if the user sets -nullval = 0, then no checks for undefined pixels will be performed, -thus increasing the speed of the program. The second set of routines -(FTGCF) returns the data element array and in addition a logical array -of flags which defines whether the corresponding data pixel is undefined. - - Any column, regardless of it's intrinsic datatype, may be read as a - string. It should be noted however that reading a numeric column - as a string is 10 - 100 times slower than reading the same column as - a number due to the large overhead in constructing the formatted - strings. The display format of the returned strings will be - determined by the TDISPn keyword, if it exists, otherwise by the - datatype of the column. The length of the returned strings can be - determined with the ftgcdw routine. The following TDISPn display - formats are currently supported: -- - Iw.m Integer - Ow.m Octal integer - Zw.m Hexadecimal integer - Fw.d Fixed floating point - Ew.d Exponential floating point - Dw.d Exponential floating point - Gw.d General; uses Fw.d if significance not lost, else Ew.d -- - where w is the width in characters of the displayed values, m is the minimum - number of digits displayed, and d is the number of digits to the right of the - decimal. The .m field is optional. - ->1 Put elements into an ASCII or binary table column (in the CDU). - (The SPP FSPCLS routine has an additional integer argument after - the VALUES character string which specifies the size of the 1st - dimension of this 2-D CHAR array). - - The alternate version of these routines, whose names end in 'LL' - after the datatype character, support large tables with more then - 2*31 rows. When calling these routines, the frow and felem parameters -> *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. -- - FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) - FTPCL[LBIJKEDCM]LL(unit,colnum,frow,felem,nelements,values, > status) -- ->2 Put elements into an ASCII or binary table column (in the CDU) - substituting the appropriate FITS null value for any elements that - are equal to NULLVAL. For ASCII TABLE extensions, the - null value defined by the previous call to FTSNUL will be substituted; - For integer FITS columns, in a binary table the null value - defined by the previous call to FTTNUL will be substituted; - For floating point FITS columns a special IEEE NaN (Not-a-Number) - value will be substituted. - - The alternate version of these routines, whose names end in 'LL' - after the datatype character, support large tables with more then - 2*31 rows. When calling these routines, the frow and felem parameters -> *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. -- - FTPCN[SBIJKED](unit,colnum,frow,felem,nelements,values,nullval > status) - FTPCN[SBIJKED]LL(unit,colnum,(I*8) frow,(I*8) felem,nelements,values, - nullval > status) -- ->3 Put bit values into a binary byte ('B') or bit ('X') table column (in the - CDU). LRAY is an array of logical values corresponding to the sequence of - bits to be written. If LRAY is true then the corresponding bit is - set to 1, otherwise the bit is set to 0. Note that in the case of - 'X' columns, FITSIO will write to all 8 bits of each byte whether - they are formally valid or not. Thus if the column is defined as - '4X', and one calls FTPCLX with fbit=1 and nbit=8, then all 8 bits - will be written into the first byte (as opposed to writing the - first 4 bits into the first row and then the next 4 bits into the - next row), even though the last 4 bits of each byte are formally -> not defined. -- - FTPCLX(unit,colnum,frow,fbit,nbit,lray, > status) -- ->>4 Set table elements in a column as undefined -- - FTPCLU(unit,colnum,frow,felem,nelements, > status) -- ->5 Get elements from an ASCII or binary table column (in the CDU). These - routines return the values of the table column array elements. Undefined - array elements will be returned with a value = nullval, unless nullval = 0 - (or = ' ' for ftgcvs) in which case no checking for undefined values will - be performed. The ANYF parameter is set to true if any of the returned - elements are undefined. (Note: the ftgcl routine simple gets an array - of logical data values without any checks for undefined values; use - the ftgcfl routine to check for undefined logical elements). - (The SPP FSGCVS routine has an additional integer argument after - the VALUES character string which specifies the size of the 1st - dimension of this 2-D CHAR array). - - The alternate version of these routines, whose names end in 'LL' - after the datatype character, support large tables with more then - 2*31 rows. When calling these routines, the frow and felem parameters -> *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. -- - FTGCL(unit,colnum,frow,felem,nelements, > values,status) - FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > - values,anyf,status) - FTGCV[BIJKEDCM]LL(unit,colnum,(I*8) frow, (I*8) felem, nelements, - nullval, > values,anyf,status) -- ->6 Get elements and null flags from an ASCII or binary table column (in the - CHDU). These routines return the values of the table column array elements. - Any undefined array elements will have the corresponding flagvals element - set equal to .TRUE. The ANYF parameter is set to true if any of the - returned elements are undefined. - (The SPP FSGCFS routine has an additional integer argument after - the VALUES character string which specifies the size of the 1st - dimension of this 2-D CHAR array). - - The alternate version of these routines, whose names end in 'LL' - after the datatype character, support large tables with more then - 2*31 rows. When calling these routines, the frow and felem parameters -> *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. -- - FTGCF[SLBIJKEDCM](unit,colnum,frow,felem,nelements, > - values,flagvals,anyf,status) - FTGCF[BIJKED]LL(unit,colnum, (I*8) frow, (I*8) felem,nelements, > - values,flagvals,anyf,status) -- ->7 Get an arbitrary data subsection from an N-dimensional array - in a binary table vector column. Undefined pixels - in the array will be set equal to the value of 'nullval', - unless nullval=0 in which case no testing for undefined pixels will - be performed. The first and last rows in the table to be read - are specified by fpixels(naxis+1) and lpixels(naxis+1), and hence - are treated as the next higher dimension of the FITS N-dimensional - array. The INCS parameter specifies the sampling interval in -> each dimension between the data elements that will be returned. -- - FTGSV[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs,nullval, > - array,anyf,status) -- ->8 Get an arbitrary data subsection from an N-dimensional array - in a binary table vector column. Any Undefined - pixels in the array will have the corresponding 'flagvals' - element set equal to .TRUE. The first and last rows in the table - to be read are specified by fpixels(naxis+1) and lpixels(naxis+1), - and hence are treated as the next higher dimension of the FITS - N-dimensional array. The INCS parameter specifies the sampling - interval in each dimension between the data elements that will be -> returned. -- - FTGSF[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs, > - array,flagvals,anyf,status) -- ->9 Get bit values from a byte ('B') or bit (`X`) table column (in the - CDU). LRAY is an array of logical values corresponding to the - sequence of bits to be read. If LRAY is true then the - corresponding bit was set to 1, otherwise the bit was set to 0. - Note that in the case of 'X' columns, FITSIO will read all 8 bits - of each byte whether they are formally valid or not. Thus if the - column is defined as '4X', and one calls FTGCX with fbit=1 and - nbit=8, then all 8 bits will be read from the first byte (as - opposed to reading the first 4 bits from the first row and then the - first 4 bits from the next row), even though the last 4 bits of -> each byte are formally not defined. -- - FTGCX(unit,colnum,frow,fbit,nbit, > lray,status) -- ->10 Read any consecutive set of bits from an 'X' or 'B' column and - interpret them as an unsigned n-bit integer. NBIT must be less than - or equal to 16 when calling FTGCXI, and less than or equal to 32 when - calling FTGCXJ; there is no limit on the value of NBIT for FTGCXD, but - the returned double precision value only has 48 bits of precision on - most 32-bit word machines. The NBITS bits are interpreted as an - unsigned integer unless NBITS = 16 (in FTGCXI) or 32 (in FTGCXJ) in which - case the string of bits are interpreted as 16-bit or 32-bit 2's - complement signed integers. If NROWS is greater than 1 then the - same set of bits will be read from sequential rows in the table - starting with row FROW. Note that the numbering convention - used here for the FBIT parameter adopts 1 for the first element of the -> vector of bits; this is the Most Significant Bit of the integer value. -- - FTGCX[IJD](unit,colnum,frow,nrows,fbit,nbit, > array,status) -- ->11 Get the descriptor for a variable length column in a binary table. - The descriptor consists of 2 integer parameters: the number of elements - in the array and the starting offset relative to the start of the heap. - The first routine returns a single descriptor whereas the second routine -> returns the descriptors for a range of rows in the table. -- - FTGDES(unit,colnum,rownum, > nelements,offset,status) - FTGDESLL(unit,colnum,rownum, > nelementsll,offsetll,status) - - FTGDESS(unit,colnum,firstrow,nrows > nelements,offset, status) - FTGDESSLL(unit,colnum,firstrow,nrows > nelementsll,offsetll, status) -- ->12 Write the descriptor for a variable length column in a binary table. - These subroutines can be used in conjunction with FTGDES to enable - 2 or more arrays to point to the same storage location to save -> storage space if the arrays are identical. -- - FTPDES(unit,colnum,rownum,nelements,offset, > status) - FTPDESLL(unit,colnum,rownum,nelementsll,offsetll, > status) -- - -**I. Row Selection and Calculator Routines \label{FTFROW} - -These routines all parse and evaluate an input string containing a user -defined arithmetic expression. The first 3 routines select rows in a -FITS table, based on whether the expression evaluates to true (not -equal to zero) or false (zero). The other routines evaluate the -expression and calculate a value for each row of the table. The -allowed expression syntax is described in the row filter section in the -earlier `Extended File Name Syntax' chapter of this document. The -expression may also be written to a text file, and the name of the -file, prepended with a '@' character may be supplied for the 'expr' -parameter (e.g. '@filename.txt'). The expression in the file can -be arbitrarily complex and extend over multiple lines of the file. -Lines that begin with 2 slash characters ('//') will be ignored and -may be used to add comments to the file. - ->1 Evaluate a boolean expression over the indicated rows, returning an -> array of flags indicating which rows evaluated to TRUE/FALSE -- - FTFROW(unit,expr,firstrow, nrows, > n_good_rows, row_status, status) -- ->>2 Find the first row which satisfies the input boolean expression -- - FTFFRW(unit, expr, > rownum, status) -- ->3 Evaluate an expression on all rows of a table. If the input and output -files are not the same, copy the TRUE rows to the output file; if the output -table is not empty, then this routine will append the new -selected rows after the existing rows. If the ->files are the same, delete the FALSE rows (preserve the TRUE rows). -- - FTSROW(inunit, outunit, expr, > status) -- ->4 Calculate an expression for the indicated rows of a table, returning -the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If -nulval==NULL, UNDEFs will be zeroed out. For vector results, the number -of elements returned may be less than nelements if nelements is not an -even multiple of the result dimension. Call FTTEXP to obtain ->the dimensions of the results. -- - FTCROW(unit,datatype,expr,firstrow,nelements,nulval, > - array,anynul,status) -- ->5 Evaluate an expression and write the result either to a column (if -the expression is a function of other columns in the table) or to a -keyword (if the expression evaluates to a constant and is not a -function of other columns in the table). In the former case, the -parName parameter is the name of the column (which may or may not already -exist) into which to write the results, and parInfo contains an -optional TFORM keyword value if a new column is being created. If a -TFORM value is not specified then a default format will be used, -depending on the expression. If the expression evaluates to a constant, -then the result will be written to the keyword name given by the -parName parameter, and the parInfo parameter may be used to supply an -optional comment for the keyword. If the keyword does not already -exist, then the name of the keyword must be preceded with a '\#' character, ->otherwise the result will be written to a column with that name. - -- - FTCALC(inunit, expr, outunit, parName, parInfo, > status) -- ->6 This calculator routine is similar to the previous routine, except -that the expression is only evaluated over the specified -row ranges. nranges specifies the number of row ranges, and firstrow ->and lastrow give the starting and ending row number of each range. -- - FTCALC_RNG(inunit, expr, outunit, parName, parInfo, - nranges, firstrow, lastrow, > status) -- ->7 Evaluate the given expression and return dimension and type information -on the result. The returned dimensions correspond to a single row entry -of the requested expression, and are equivalent to the result of fits\_read\_tdim(). -Note that strings are considered to be one element regardless of string length. ->If maxdim == 0, then naxes is optional. -- - FTTEXP(unit, expr, maxdim > datatype, nelem, naxis, naxes, status) -- - - -**J. Celestial Coordinate System Subroutines \label{FTGICS} - -The FITS community has adopted a set of keyword conventions that define -the transformations needed to convert between pixel locations in an -image and the corresponding celestial coordinates on the sky, or more -generally, that define world coordinates that are to be associated with -any pixel location in an n-dimensional FITS array. CFITSIO is distributed -with a couple of self-contained World Coordinate System (WCS) routines, -however, these routines DO NOT support all the latest WCS conventions, -so it is STRONGLY RECOMMENDED that software developers use a more robust -external WCS library. Several recommended libraries are: -- - WCSLIB - supported by Mark Calabretta - WCSTools - supported by Doug Mink - AST library - developed by the U.K. Starlink project -- - -More information about the WCS keyword conventions and links to all of -these WCS libraries can be found on the FITS Support Office web site at -http://fits.gsfc.nasa.gov under the WCS link. - -The functions provided in these external WCS libraries will need access to -the WCS information contained in the FITS file headers. One convenient -way to pass this information to the external library is to use FITSIO -to copy the header keywords into one long character string, and then -pass this string to an interface routine in the external library that -will extract the necessary WCS information (e.g., see the astFitsChan -and astPutCards routines in the Starlink AST library). - -The following FITSIO routines DO NOT support the more recent WCS conventions -that have been approved as part of the FITS standard. Consequently, -the following routines ARE NOW DEPRECATED. It is STRONGLY RECOMMENDED -that software developers not use these routines, and instead use an -external WCS library, as described above. - -These routines are included mainly for backward compatibility with -existing software. They support the following standard map -projections: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, and -AIT (these are the -legal values for the coordtype parameter). These routines are based -on similar functions in Classic AIPS. All the angular quantities are -given in units of degrees. - ->1 Get the values of all the standard FITS celestial coordinate system - keywords from the header of a FITS image (i.e., the primary array or - an image extension). These values may then be passed to the subroutines - that perform the coordinate transformations. If any or all of the WCS - keywords are not present, then default values will be returned. If - the first coordinate axis is the declination-like coordinate, then - this routine will swap them so that the longitudinal-like coordinate - is returned as the first axis. - - If the file uses the newer 'CDj\_i' WCS transformation matrix - keywords instead of old style 'CDELTn' and 'CROTA2' keywords, then - this routine will calculate and return the values of the equivalent - old-style keywords. Note that the conversion from the new-style - keywords to the old-style values is sometimes only an - approximation, so if the approximation is larger than an internally - defined threshold level, then CFITSIO will still return the - approximate WCS keyword values, but will also return with status = - 506, to warn the calling program that approximations have been - made. It is then up to the calling program to decide whether the - approximations are sufficiently accurate for the particular - application, or whether more precise WCS transformations must be -> performed using new-style WCS keywords directly. -- - FTGICS(unit, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) -- ->2 Get the values of all the standard FITS celestial coordinate system - keywords from the header of a FITS table where the X and Y (or RA and - DEC coordinates are stored in 2 separate columns of the table. - These values may then be passed to the subroutines that perform the -> coordinate transformations. -- - FTGTCS(unit,xcol,ycol, > - xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) -- ->3 Calculate the celestial coordinate corresponding to the input -> X and Y pixel location in the image. -- - FTWLDP(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, - coordtype, > xpos,ypos,status) -- ->4 Calculate the X and Y pixel location corresponding to the input -> celestial coordinate in the image. -- - FTXYPX(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, - coordtype, > xpix,ypix,status) -- - -**K. File Checksum Subroutines \label{FTPCKS} - -The following routines either compute or validate the checksums for the -CHDU. The DATASUM keyword is used to store the numerical value of the -32-bit, 1's complement checksum for the data unit alone. If there is -no data unit then the value is set to zero. The numerical value is -stored as an ASCII string of digits, enclosed in quotes, because the -value may be too large to represent as a 32-bit signed integer. The -CHECKSUM keyword is used to store the ASCII encoded COMPLEMENT of the -checksum for the entire HDU. Storing the complement, rather than the -actual checksum, forces the checksum for the whole HDU to equal zero. -If the file has been modified since the checksums were computed, then -the HDU checksum will usually not equal zero. These checksum keyword -conventions are based on a paper by Rob Seaman published in the -proceedings of the ADASS IV conference in Baltimore in November 1994 -and a later revision in June 1995. - ->1 Compute and write the DATASUM and CHECKSUM keyword values for the CHDU - into the current header. The DATASUM value is the 32-bit checksum - for the data unit, expressed as a decimal integer enclosed in single - quotes. The CHECKSUM keyword value is a 16-character string which - is the ASCII-encoded value for the complement of the checksum for - the whole HDU. If these keywords already exist, their values - will be updated only if necessary (i.e., if the file has been modified -> since the original keyword values were computed). -- - FTPCKS(unit, > status) -- ->2 Update the CHECKSUM keyword value in the CHDU, assuming that the - DATASUM keyword exists and already has the correct value. This routine - calculates the new checksum for the current header unit, adds it to the - data unit checksum, encodes the value into an ASCII string, and writes -> the string to the CHECKSUM keyword. -- - FTUCKS(unit, > status) -- ->3 Verify the CHDU by computing the checksums and comparing - them with the keywords. The data unit is verified correctly - if the computed checksum equals the value of the DATASUM - keyword. The checksum for the entire HDU (header plus data unit) is - correct if it equals zero. The output DATAOK and HDUOK parameters - in this subroutine are integers which will have a value = 1 - if the data or HDU is verified correctly, a value = 0 - if the DATASUM or CHECKSUM keyword is not present, or value = -1 -> if the computed checksum is not correct. -- - FTVCKS(unit, > dataok,hduok,status) -- ->4 Compute and return the checksum values for the CHDU (as - double precision variables) without creating or modifying the - CHECKSUM and DATASUM keywords. This routine is used internally by -> FTVCKS, but may be useful in other situations as well. -- - FTGCKS(unit, > datasum,hdusum,status) -- ->5 Encode a checksum value (stored in a double precision variable) - into a 16-character string. If COMPLEMENT = .true. then the 32-bit -> sum value will be complemented before encoding. -- - FTESUM(sum,complement, > checksum) -- ->6 Decode a 16 character checksum string into a double precision value. - If COMPLEMENT = .true. then the 32-bit sum value will be complemented -> after decoding. -- - FTDSUM(checksum,complement, > sum) -- - -**L. Date and Time Utility Routines \label{FTGSDT} - -The following routines help to construct or parse the FITS date/time -strings. Starting in the year 2000, the FITS DATE keyword values (and -the values of other `DATE-' keywords) must have the form 'YYYY-MM-DD' -(date only) or 'YYYY-MM-DDThh:mm:ss.ddd...' (date and time) where the -number of decimal places in the seconds value is optional. These times -are in UTC. The older 'dd/mm/yy' date format may not be used for dates -after 01 January 2000. - ->1 Get the current system date. The returned year has 4 digits -> (1999, 2000, etc.) -- - FTGSDT( > day, month, year, status ) -- - ->2 Get the current system date and time string ('YYYY-MM-DDThh:mm:ss'). -The time will be in UTC/GMT if available, as indicated by a returned timeref -value = 0. If the returned value of timeref = 1 then this indicates that -it was not possible to convert the local time to UTC, and thus the local ->time was returned. -- - FTGSTM(> datestr, timeref, status) -- - ->3 Construct a date string from the input date values. If the year -is between 1900 and 1998, inclusive, then the returned date string will -have the old FITS format ('dd/mm/yy'), otherwise the date string will -have the new FITS format ('YYYY-MM-DD'). Use FTTM2S instead -> to always return a date string using the new FITS format. -- - FTDT2S( year, month, day, > datestr, status) -- - ->4 Construct a new-format date + time string ('YYYY-MM-DDThh:mm:ss.ddd...'). - If the year, month, and day values all = 0 then only the time is encoded - with format 'hh:mm:ss.ddd...'. The decimals parameter specifies how many - decimal places of fractional seconds to include in the string. If `decimals' -> is negative, then only the date will be return ('YYYY-MM-DD'). -- - FTTM2S( year, month, day, hour, minute, second, decimals, - > datestr, status) -- - ->5 Return the date as read from the input string, where the string may be -in either the old ('dd/mm/yy') or new ('YYYY-MM-DDThh:mm:ss' or ->'YYYY-MM-DD') FITS format. -- - FTS2DT(datestr, > year, month, day, status) -- - ->6 Return the date and time as read from the input string, where the -string may be in either the old or new FITS format. The returned hours, -minutes, and seconds values will be set to zero if the input string -does not include the time ('dd/mm/yy' or 'YYYY-MM-DD') . Similarly, -the returned year, month, and date values will be set to zero if the ->date is not included in the input string ('hh:mm:ss.ddd...'). -- - FTS2TM(datestr, > year, month, day, hour, minute, second, status) -- - -**M. General Utility Subroutines \label{FTGHAD} - -The following utility subroutines may be useful for certain applications: - ->>1 Return the starting byte address of the CHDU and the next HDU. -- - FTGHAD(iunit, > curaddr, nextaddr) -- ->>2 Convert a character string to uppercase (operates in place). -- - FTUPCH(string) -- ->3 Compare the input template string against the reference string - to see if they match. The template string may contain wildcard - characters: '*' will match any sequence of characters (including - zero characters) and '?' will match any single character in the - reference string. The '\#' character will match any consecutive string - of decimal digits (0 - 9). If CASESN = .true. then the match will be - case sensitive. The returned MATCH parameter will be .true. if - the 2 strings match, and EXACT will be .true. if the match is - exact (i.e., if no wildcard characters were used in the match). -> Both strings must be 68 characters or less in length. -- - FTCMPS(str_template, string, casesen, > match, exact) -- - ->4 Test that the keyword name contains only legal characters: A-Z,0-9, -> hyphen, and underscore. -- - FTTKEY(keyword, > status) -- ->5 Test that the keyword record contains only legal printable ASCII -> characters -- - FTTREC(card, > status) -- ->6 Test whether the current header contains any NULL (ASCII 0) characters. - These characters are illegal in the header, but they will go undetected - by most of the CFITSIO keyword header routines, because the null is - interpreted as the normal end-of-string terminator. This routine returns - the position of the first null character in the header, or zero if there - are no nulls. For example a returned value of 110 would indicate that - the first NULL is located in the 30th character of the second keyword - in the header (recall that each header record is 80 characters long). - Note that this is one of the few FITSIO routines in which the returned -> value is not necessarily equal to the status value). -- - FTNCHK(unit, > status) -- ->7 Parse a header keyword record and return the name of the keyword - and the length of the name. - The keyword name normally occupies the first 8 characters of the - record, except under the HIERARCH convention where the name can -> be up to 70 characters in length. -- - FTGKNM(card, > keyname, keylength, staThe '\#' character will match any consecutive string - of decimal digits (0 - 9). tus) -- ->8 Parse a header keyword record. - This subroutine parses the input header record to return the value (as - a character string) and comment strings. If the keyword has no - value (columns 9-10 not equal to '= '), then the value string is returned - blank and the comment string is set equal to column 9 - 80 of the -> input string. -- - FTPSVC(card, > value,comment,status) -- ->9 Construct a properly formated 80-character header keyword record from the - input keyword name, keyword value, and keyword comment strings. - Hierarchical keyword names (e.g., "ESO TELE CAM") are supported. - The value string may contain an integer, floating point, logical, or - quoted character string (e.g., "12", "15.7", "T", -> or "'NGC 1313'"). -- - FTMKKY(keyname, value, comment, > card, status) -- ->10 Construct a sequence keyword name (ROOT + nnn). - This subroutine appends the sequence number to the root string to create -> a keyword name (e.g., 'NAXIS' + 2 = 'NAXIS2') -- - FTKEYN(keyroot,seq_no, > keyword,status) -- ->11 Construct a sequence keyword name (n + ROOT). - This subroutine concatenates the sequence number to the front of the -> root string to create a keyword name (e.g., 1 + 'CTYP' = '1CTYP') -- - FTNKEY(seq_no,keyroot, > keyword,status) -- ->12 Determine the datatype of a keyword value string. - This subroutine parses the keyword value string (usually columns 11-30 -> of the header record) to determine its datatype. -- - FTDTYP(value, > dtype,status) -- ->13 Return the class of input header record. The record is classified - into one of the following categories (the class values are - defined in fitsio.h). Note that this is one of the few FITSIO -> routines that does not return a status value. -- - Class Value Keywords - TYP_STRUC_KEY 10 SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, - GROUPS, PCOUNT, GCOUNT, END - XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, - and the first 4 COMMENT keywords in the primary array - that define the FITS format. - TYP_CMPRS_KEY 20 The keywords used in the compressed image or table - format, including ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, - ZTILEn, ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK - TYP_SCAL_KEY 30 BSCALE, BZERO, TSCALn, TZEROn - TYP_NULL_KEY 40 BLANK, TNULLn - TYP_DIM_KEY 50 TDIMn - TYP_RANG_KEY 60 TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX - TYP_UNIT_KEY 70 BUNIT, TUNITn - TYP_DISP_KEY 80 TDISPn - TYP_HDUID_KEY 90 EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL - TYP_CKSUM_KEY 100 CHECKSUM, DATASUM - TYP_WCS_KEY 110 CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn - CDj_is, PVj_ms, LONPOLEs, LATPOLEs - TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, - TCRPks, TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn - jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, - iCRPns, jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn - (i,j,m,n are integers, s is any letter) - TYP_REFSYS_KEY 120 EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs - TYP_COMM_KEY 130 COMMENT, HISTORY, (blank keyword) - TYP_CONT_KEY 140 CONTINUE - TYP_USER_KEY 150 all other keywords - - class = FTGKCL (char *card) -- ->14 Parse the 'TFORM' binary table column format string. - This subroutine parses the input TFORM character string and returns the - integer datatype code, the repeat count of the field, and, in the case - of character string fields, the length of the unit string. The following - datatype codes are returned (the negative of the value is returned -> if the column contains variable-length arrays): -- - Datatype DATACODE value - bit, X 1 - byte, B 11 - logical, L 14 - ASCII character, A 16 - short integer, I 21 - integer, J 41 - real, E 42 - double precision, D 82 - complex 83 - double complex 163 - - FTBNFM(tform, > datacode,repeat,width,status) -- ->15 Parse the 'TFORM' keyword value that defines the column format in - an ASCII table. This routine parses the input TFORM character - string and returns the datatype code, the width of the column, - and (if it is a floating point column) the number of decimal places - to the right of the decimal point. The returned datatype codes are - the same as for the binary table, listed above, with the following - additional rules: integer columns that are between 1 and 4 characters - wide are defined to be short integers (code = 21). Wider integer - columns are defined to be regular integers (code = 41). Similarly, - Fixed decimal point columns (with TFORM = 'Fw.d') are defined to - be single precision reals (code = 42) if w is between 1 and 7 characters - wide, inclusive. Wider 'F' columns will return a double precision - data code (= 82). 'Ew.d' format columns will have datacode = 42, -> and 'Dw.d' format columns will have datacode = 82. -- - FTASFM(tform, > datacode,width,decimals,status) -- ->16 Calculate the starting column positions and total ASCII table width - based on the input array of ASCII table TFORM values. The SPACE input - parameter defines how many blank spaces to leave between each column - (it is recommended to have one space between columns for better human -> readability). -- - FTGABC(tfields,tform,space, > rowlen,tbcol,status) -- ->17 Parse a template string and return a formatted 80-character string - suitable for appending to (or deleting from) a FITS header file. - This subroutine is useful for parsing lines from an ASCII template file - and reformatting them into legal FITS header records. The formatted - string may then be passed to the FTPREC, FTMCRD, or FTDKEY subroutines -> to append or modify a FITS header record. -- - FTGTHD(template, > card,hdtype,status) -- - The input TEMPLATE character string generally should contain 3 tokens: - (1) the KEYNAME, (2) the VALUE, and (3) the COMMENT string. The - TEMPLATE string must adhere to the following format: - ->- The KEYNAME token must begin in columns 1-8 and be a maximum of 8 - characters long. If the first 8 characters of the template line are - blank then the remainder of the line is considered to be a FITS comment - (with a blank keyword name). A legal FITS keyword name may only - contain the characters A-Z, 0-9, and '-' (minus sign) and - underscore. This subroutine will automatically convert any lowercase - characters to uppercase in the output string. If KEYNAME = 'COMMENT' - or 'HISTORY' then the remainder of the line is considered to be a FITS -> COMMENT or HISTORY record, respectively. - ->- The VALUE token must be separated from the KEYNAME token by one or more - spaces and/or an '=' character. The datatype of the VALUE token - (numeric, logical, or character string) is automatically determined - and the output CARD string is formatted accordingly. The value - token may be forced to be interpreted as a string (e.g. if it is a - string of numeric digits) by enclosing it in single quotes. - If the value token is a character string that contains 1 or more - embedded blank space characters or slash ('/') characters then the -> entire character string must be enclosed in single quotes. - ->- The COMMENT token is optional, but if present must be separated from -> the VALUE token by a blank space or a '/' character. - ->- One exception to the above rules is that if the first non-blank - character in the template string is a minus sign ('-') followed - by a single token, or a single token followed by an equal sign, - then it is interpreted as the name of a keyword which is to be -> deleted from the FITS header. - ->- The second exception is that if the template string starts with - a minus sign and is followed by 2 tokens then the second token - is interpreted as the new name for the keyword specified by - first token. In this case the old keyword name (first token) - is returned in characters 1-8 of the returned CARD string, and - the new keyword name (the second token) is returned in characters - 41-48 of the returned CARD string. These old and new names - may then be passed to the FTMNAM subroutine which will change -> the keyword name. - - The HDTYPE output parameter indicates how the returned CARD string - should be interpreted: -- - hdtype interpretation - ------ ------------------------------------------------- - -2 Modify the name of the keyword given in CARD(1:8) - to the new name given in CARD(41:48) - - -1 CARD(1:8) contains the name of a keyword to be deleted - from the FITS header. - - 0 append the CARD string to the FITS header if the - keyword does not already exist, otherwise update - the value/comment if the keyword is already present - in the header. - - 1 simply append this keyword to the FITS header (CARD - is either a HISTORY or COMMENT keyword). - - 2 This is a FITS END record; it should not be written - to the FITS header because FITSIO automatically - appends the END record when the header is closed. -- - EXAMPLES: The following lines illustrate valid input template strings: -- - INTVAL 7 This is an integer keyword - RVAL 34.6 / This is a floating point keyword - EVAL=-12.45E-03 This is a floating point keyword in exponential notation - lval F This is a boolean keyword - This is a comment keyword with a blank keyword name - SVAL1 = 'Hello world' / this is a string keyword - SVAL2 '123.5' this is also a string keyword - sval3 123+ / this is also a string keyword with the value '123+ ' - # the following template line deletes the DATE keyword - - DATE - # the following template line modifies the NAME keyword to OBJECT - - NAME OBJECT -- ->18 Parse the input string containing a list of rows or row ranges, and - return integer arrays containing the first and last row in each - range. For example, if rowlist = "3-5, 6, 8-9" then it will - return numranges = 3, rangemin = 3, 6, 8 and rangemax = 5, 6, 9. - At most, 'maxranges' number of ranges will be returned. 'maxrows' - is the maximum number of rows in the table; any rows or ranges - larger than this will be ignored. The rows must be specified in - increasing order, and the ranges must not overlap. A minus sign - may be use to specify all the rows to the upper or lower bound, so - "50-" means all the rows from 50 to the end of the table, and "-" -> means all the rows in the table, from 1 - maxrows. -- - FTRWRG(rowlist, maxrows, maxranges, > - numranges, rangemin, rangemax, status) -- - - - -*VI. The CFITSIO Iterator Function - -The fits\_iterate\_data function in CFITSIO provides a unique method of -executing an arbitrary user-supplied `work' function that operates on -rows of data in FITS tables or on pixels in FITS images. Rather than -explicitly reading and writing the FITS images or columns of data, one -instead calls the CFITSIO iterator routine, passing to it the name of -the user's work function that is to be executed along with a list of -all the table columns or image arrays that are to be passed to the work -function. The CFITSIO iterator function then does all the work of -allocating memory for the arrays, reading the input data from the FITS -file, passing them to the work function, and then writing any output -data back to the FITS file after the work function exits. Because -it is often more efficient to process only a subset of the total table -rows at one time, the iterator function can determine the optimum -amount of data to pass in each iteration and repeatedly call the work -function until the entire table been processed. - -For many applications this single CFITSIO iterator function can -effectively replace all the other CFITSIO routines for reading or -writing data in FITS images or tables. Using the iterator has several -important advantages over the traditional method of reading and writing -FITS data files: - -\begin{itemize} -\item -It cleanly separates the data I/O from the routine that operates on -the data. This leads to a more modular and `object oriented' -programming style. - -\item -It simplifies the application program by eliminating the need to allocate -memory for the data arrays and eliminates most of the calls to the CFITSIO -routines that explicitly read and write the data. - -\item -It ensures that the data are processed as efficiently as possible. -This is especially important when processing tabular data since -the iterator function will calculate the most efficient number -of rows in the table to be passed at one time to the user's work -function on each iteration. - -\item -Makes it possible for larger projects to develop a library of work -functions that all have a uniform calling sequence and are all -independent of the details of the FITS file format. - -\end{itemize} - -There are basically 2 steps in using the CFITSIO iterator function. -The first step is to design the work function itself which must have a -prescribed set of input parameters. One of these parameters is a -structure containing pointers to the arrays of data; the work function -can perform any desired operations on these arrays and does not need to -worry about how the input data were read from the file or how the -output data get written back to the file. - -The second step is to design the driver routine that opens all the -necessary FITS files and initializes the input parameters to the -iterator function. The driver program calls the CFITSIO iterator -function which then reads the data and passes it to the user's work -function. - -Further details on using the iterator function can be found in the -companion CFITSIO User's Guide, and in the iter\_a.f, iter\_b.f and -iter\_c.f example programs. - - - -*IV. Extended File Name Syntax - -**A. Overview - -CFITSIO supports an extended syntax when specifying the name of the -data file to be opened or created that includes the following -features: - -\begin{itemize} -\item -CFITSIO can read IRAF format images which have header file names that -end with the '.imh' extension, as well as reading and writing FITS -files, This feature is implemented in CFITSIO by first converting the -IRAF image into a temporary FITS format file in memory, then opening -the FITS file. Any of the usual CFITSIO routines then may be used to -read the image header or data. Similarly, raw binary data arrays can -be read by converting them on the fly into virtual FITS images. - -\item -FITS files on the Internet can be read (and sometimes written) using the FTP, -HTTP, or ROOT protocols. - -\item -FITS files can be piped between tasks on the stdin and stdout streams. - -\item -FITS files can be read and written in shared memory. This can potentially -achieve much better data I/O performance compared to reading and -writing the same FITS files on magnetic disk. - -\item -Compressed FITS files in gzip or Unix COMPRESS format can be directly read. - -\item -Output FITS files can be written directly in compressed gzip format, -thus saving disk space. - -\item -FITS table columns can be created, modified, or deleted 'on-the-fly' as -the table is opened by CFITSIO. This creates a virtual FITS file containing -the modifications that is then opened by the application program. - -\item -Table rows may be selected, or filtered out, on the fly when the table -is opened by CFITSIO, based on an arbitrary user-specified expression. -Only rows for which the expression evaluates to 'TRUE' are retained -in the copy of the table that is opened by the application program. - -\item -Histogram images may be created on the fly by binning the values in -table columns, resulting in a virtual N-dimensional FITS image. The -application program then only sees the FITS image (in the primary -array) instead of the original FITS table. -\end{itemize} - -The latter 3 features in particular add very powerful data processing -capabilities directly into CFITSIO, and hence into every task that uses -CFITSIO to read or write FITS files. For example, these features -transform a very simple program that just copies an input FITS file to -a new output file (like the `fitscopy' program that is distributed with -CFITSIO) into a multipurpose FITS file processing tool. By appending -fairly simple qualifiers onto the name of the input FITS file, the user -can perform quite complex table editing operations (e.g., create new -columns, or filter out rows in a table) or create FITS images by -binning or histogramming the values in table columns. In addition, -these functions have been coded using new state-of-the art algorithms -that are, in some cases, 10 - 100 times faster than previous widely -used implementations. - -Before describing the complete syntax for the extended FITS file names -in the next section, here are a few examples of FITS file names that -give a quick overview of the allowed syntax: - -\begin{itemize} -\item -{\tt 'myfile.fits'}: the simplest case of a FITS file on disk in the current -directory. - -\item -{\tt 'myfile.imh'}: opens an IRAF format image file and converts it on the -fly into a temporary FITS format image in memory which can then be read with -any other CFITSIO routine. - -\item -{\tt rawfile.dat[i512,512]}: opens a raw binary data array (a 512 x 512 -short integer array in this case) and converts it on the fly into a -temporary FITS format image in memory which can then be read with any -other CFITSIO routine. - -\item -{\tt myfile.fits.gz}: if this is the name of a new output file, the '.gz' -suffix will cause it to be compressed in gzip format when it is written to -disk. - -\item -{\tt 'myfile.fits.gz[events, 2]'}: opens and uncompresses the gzipped file -myfile.fits then moves to the extension which has the keywords EXTNAME -= 'EVENTS' and EXTVER = 2. - -\item -{\tt '-'}: a dash (minus sign) signifies that the input file is to be read -from the stdin file stream, or that the output file is to be written to -the stdout stream. - -\item -{\tt 'ftp://legacy.gsfc.nasa.gov/test/vela.fits'}: FITS files in any ftp -archive site on the Internet may be directly opened with read-only -access. - -\item -{\tt 'http://legacy.gsfc.nasa.gov/software/test.fits'}: any valid URL to a -FITS file on the Web may be opened with read-only access. - -\item -{\tt 'root://legacy.gsfc.nasa.gov/test/vela.fits'}: similar to ftp access -except that it provides write as well as read access to the files -across the network. This uses the root protocol developed at CERN. - -\item -{\tt 'shmem://h2[events]'}: opens the FITS file in a shared memory segment and -moves to the EVENTS extension. - -\item -{\tt 'mem://'}: creates a scratch output file in core computer memory. The -resulting 'file' will disappear when the program exits, so this -is mainly useful for testing purposes when one does not want a -permanent copy of the output file. - -\item -{\tt 'myfile.fits[3; Images(10)]'}: opens a copy of the image contained in the -10th row of the 'Images' column in the binary table in the 3th extension -of the FITS file. The application just sees this single image as the -primary array. - -\item -{\tt 'myfile.fits[1:512:2, 1:512:2]'}: opens a section of the input image -ranging from the 1st to the 512th pixel in X and Y, and selects every -second pixel in both dimensions, resulting in a 256 x 256 pixel image -in this case. - -\item -{\tt 'myfile.fits[EVENTS][col Rad = sqrt(X**2 + Y**2)]'}: creates and opens -a temporary file on the fly (in memory or on disk) that is identical to -myfile.fits except that it will contain a new column in the EVENTS -extension called 'Rad' whose value is computed using the indicated -expression which is a function of the values in the X and Y columns. - -\item -{\tt 'myfile.fits[EVENTS][PHA > 5]'}: creates and opens a temporary FITS -files that is identical to 'myfile.fits' except that the EVENTS table -will only contain the rows that have values of the PHA column greater -than 5. In general, any arbitrary boolean expression using a C or -Fortran-like syntax, which may combine AND and OR operators, -may be used to select rows from a table. - -\item -{\tt 'myfile.fits[EVENTS][bin (X,Y)=1,2048,4]'}: creates a temporary FITS -primary array image which is computed on the fly by binning (i.e, -computing the 2-dimensional histogram) of the values in the X and Y -columns of the EVENTS extension. In this case the X and Y coordinates -range from 1 to 2048 and the image pixel size is 4 units in both -dimensions, so the resulting image is 512 x 512 pixels in size. - -\item -The final example combines many of these feature into one complex -expression (it is broken into several lines for clarity): -- - 'ftp://legacy.gsfc.nasa.gov/data/sample.fits.gz[EVENTS] - [col phacorr = pha * 1.1 - 0.3][phacorr >= 5.0 && phacorr <= 14.0] - [bin (X,Y)=32]' -- -In this case, CFITSIO (1) copies and uncompresses the FITS file from -the ftp site on the legacy machine, (2) moves to the 'EVENTS' -extension, (3) calculates a new column called 'phacorr', (4) selects -the rows in the table that have phacorr in the range 5 to 14, and -finally (5) bins the remaining rows on the X and Y column coordinates, -using a pixel size = 32 to create a 2D image. All this processing is -completely transparent to the application program, which simply sees -the final 2-D image in the primary array of the opened file. -\end{itemize} - -The full extended CFITSIO FITS file name can contain several different -components depending on the context. These components are described in -the following sections: -- -When creating a new file: - filetype://BaseFilename(templateName) - -When opening an existing primary array or image HDU: - filetype://BaseFilename(outName)[HDUlocation][ImageSection] - -When opening an existing table HDU: - filetype://BaseFilename(outName)[HDUlocation][colFilter][rowFilter][binSpec] -- -The filetype, BaseFilename, outName, HDUlocation, and ImageSection -components, if present, must be given in that order, but the colFilter, -rowFilter, and binSpec specifiers may follow in any order. Regardless -of the order, however, the colFilter specifier, if present, will be -processed first by CFITSIO, followed by the rowFilter specifier, and -finally by the binSpec specifier. - -**A. Filetype - -The type of file determines the medium on which the file is located -(e.g., disk or network) and, hence, which internal device driver is used by -CFITSIO to read and/or write the file. Currently supported types are -- - file:// - file on local magnetic disk (default) - ftp:// - a readonly file accessed with the anonymous FTP protocol. - It also supports ftp://username:password@hostname/... - for accessing password-protected ftp sites. - http:// - a readonly file accessed with the HTTP protocol. It - supports username:password just like the ftp driver. - Proxy HTTP servers are supported using the http_proxy - environment variable (see following note). - stream:// - special driver to read an input FITS file from the stdin - stream, and/or write an output FITS file to the stdout - stream. This driver is fragile and has limited - functionality (see the following note). - gsiftp:// - access files on a computational grid using the gridftp - protocol in the Globus toolkit (see following note). - root:// - uses the CERN root protocol for writing as well as - reading files over the network. - shmem:// - opens or creates a file which persists in the computer's - shared memory. - mem:// - opens a temporary file in core memory. The file - disappears when the program exits so this is mainly - useful for test purposes when a permanent output file - is not desired. -- -If the filetype is not specified, then type file:// is assumed. -The double slashes '//' are optional and may be omitted in most cases. - -***1. Notes about HTTP proxy servers - -A proxy HTTP server may be used by defining the address (URL) and port -number of the proxy server with the http\_proxy environment variable. -For example -- - setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 -- -will cause CFITSIO to use port 3128 on the heasarc proxy server whenever -reading a FITS file with HTTP. - -***2. Notes about the stream filetype driver - -The stream driver can be used to efficiently read a FITS file from the stdin -file stream or write a FITS to the stdout file stream. However, because these -input and output streams must be accessed sequentially, the FITS file reading or -writing application must also read and write the file sequentially, at least -within the tolerances described below. - -CFITSIO supports 2 different methods for accessing FITS files on the stdin and -stdout streams. The original method, which is invoked by specifying a dash -character, "-", as the name of the file when opening or creating it, works by -storing a complete copy of the entire FITS file in memory. In this case, when -reading from stdin, CFITSIO will copy the entire stream into memory before doing -any processing of the file. Similarly, when writing to stdout, CFITSIO will -create a copy of the entire FITS file in memory, before finally flushing it out -to the stdout stream when the FITS file is closed. Buffering the entire FITS -file in this way allows the application to randomly access any part of the FITS -file, in any order, but it also requires that the user have sufficient available -memory (or virtual memory) to store the entire file, which may not be possible -in the case of very large files. - -The newer stream filetype provides a more memory-efficient method of accessing -FITS files on the stdin or stdout streams. Instead of storing a copy of the -entire FITS file in memory, CFITSIO only uses a set of internal buffer which by -default can store 40 FITS blocks, or about 100K bytes of the FITS file. The -application program must process the FITS file sequentially from beginning to -end, within this 100K buffer. Generally speaking the application program must -conform to the following restrictions: - -\begin{itemize} -\item -The program must finish reading or writing the header keywords -before reading or writing any data in the HDU. -\item -The HDU can contain at most about 1400 header keywords. This is the -maximum that can fit in the nominal 40 FITS block buffer. In principle, -this limit could be increased by recompiling CFITSIO with a larger -buffer limit, which is set by the NIOBUF parameter in fitsio2.h. -\item -The program must read or write the data in a sequential manner from the -beginning to the end of the HDU. Note that CFITSIO's internal -100K buffer allows a little latitude in meeting this requirement. -\item -The program cannot move back to a previous HDU in the FITS file. -\item -Reading or writing of variable length array columns in binary tables is not -supported on streams, because this requires moving back and forth between the -fixed-length portion of the binary table and the following heap area where the -arrays are actually stored. -\item -Reading or writing of tile-compressed images is not supported on streams, -because the images are internally stored using variable length arrays. -\end{itemize} - -***3. Notes about the gsiftp filetype - -DEPENDENCIES: Globus toolkit (2.4.3 or higher) (GT) should be installed. -There are two different ways to install GT: - -1) goto the globus toolkit web page www.globus.org and follow the - download and compilation instructions; - -2) goto the Virtual Data Toolkit web page http://vdt.cs.wisc.edu/ - and follow the instructions (STRONGLY SUGGESTED); - -Once a globus client has been installed in your system with a specific flavour -it is possible to compile and install the CFITSIO libraries. -Specific configuration flags must be used: - -1) --with-gsiftp[[=PATH]] Enable Globus Toolkit gsiftp protocol support - PATH=GLOBUS\_LOCATION i.e. the location of your globus installation - -2) --with-gsiftp-flavour[[=PATH] defines the specific Globus flavour - ex. gcc32 - -Both the flags must be used and it is mandatory to set both the PATH and the -flavour. - -USAGE: To access files on a gridftp server it is necessary to use a gsiftp prefix: - -example: gsiftp://remote\_server\_fqhn/directory/filename - -The gridftp driver uses a local buffer on a temporary file the file is located -in the /tmp directory. If you have special permissions on /tmp or you do not have a /tmp -directory, it is possible to force another location setting the GSIFTP\_TMPFILE environment -variable (ex. export GSIFTP\_TMPFILE=/your/location/yourtmpfile). - -Grid FTP supports multi channel transfer. By default a single channel transmission is -available. However, it is possible to modify this behavior setting the GSIFTP\_STREAMS -environment variable (ex. export GSIFTP\_STREAMS=8). - -***4. Notes about the root filetype - -The original rootd server can be obtained from: -\verb-ftp://root.cern.ch/root/rootd.tar.gz- -but, for it to work correctly with CFITSIO one has to use a modified -version which supports a command to return the length of the file. -This modified version is available in rootd subdirectory -in the CFITSIO ftp area at -- - ftp://legacy.gsfc.nasa.gov/software/fitsio/c/root/rootd.tar.gz. -- - -This small server is started either by inetd when a client requests a -connection to a rootd server or by hand (i.e. from the command line). -The rootd server works with the ROOT TNetFile class. It allows remote -access to ROOT database files in either read or write mode. By default -TNetFile assumes port 432 (which requires rootd to be started as root). -To run rootd via inetd add the following line to /etc/services: -- - rootd 432/tcp -- -and to /etc/inetd.conf, add the following line: -- - rootd stream tcp nowait root /user/rdm/root/bin/rootd rootd -i -- -Force inetd to reread its conf file with "kill -HUP ". -You can also start rootd by hand running directly under your private -account (no root system privileges needed). For example to start -rootd listening on port 5151 just type: \verb+rootd -p 5151+ -Notice: no \& is needed. Rootd will go into background by itself. -- - Rootd arguments: - -i says we were started by inetd - -p port# specifies a different port to listen on - -d level level of debug info written to syslog - 0 = no debug (default) - 1 = minimum - 2 = medium - 3 = maximum -- -Rootd can also be configured for anonymous usage (like anonymous ftp). -To setup rootd to accept anonymous logins do the following (while being -logged in as root): -- - - Add the following line to /etc/passwd: - - rootd:*:71:72:Anonymous rootd:/var/spool/rootd:/bin/false - - where you may modify the uid, gid (71, 72) and the home directory - to suite your system. - - - Add the following line to /etc/group: - - rootd:*:72:rootd - - where the gid must match the gid in /etc/passwd. - - - Create the directories: - - mkdir /var/spool/rootd - mkdir /var/spool/rootd/tmp - chmod 777 /var/spool/rootd/tmp - - Where /var/spool/rootd must match the rootd home directory as - specified in the rootd /etc/passwd entry. - - - To make writeable directories for anonymous do, for example: - - mkdir /var/spool/rootd/pub - chown rootd:rootd /var/spool/rootd/pub -- -That's all. Several additional remarks: you can login to an anonymous -server either with the names "anonymous" or "rootd". The password should -be of type user@host.do.main. Only the @ is enforced for the time -being. In anonymous mode the top of the file tree is set to the rootd -home directory, therefore only files below the home directory can be -accessed. Anonymous mode only works when the server is started via -inetd. - -***5. Notes about the shmem filetype: - -Shared memory files are currently supported on most Unix platforms, -where the shared memory segments are managed by the operating system -kernel and `live' independently of processes. They are not deleted (by -default) when the process which created them terminates, although they -will disappear if the system is rebooted. Applications can create -shared memory files in CFITSIO by calling: -- - fit_create_file(&fitsfileptr, "shmem://h2", &status); -- -where the root `file' names are currently restricted to be 'h0', 'h1', -'h2', 'h3', etc., up to a maximum number defined by the the value of -SHARED\_MAXSEG (equal to 16 by default). This is a prototype -implementation of the shared memory interface and a more robust -interface, which will have fewer restrictions on the number of files -and on their names, may be developed in the future. - -When opening an already existing FITS file in shared memory one calls -the usual CFITSIO routine: -- - fits_open_file(&fitsfileptr, "shmem://h7", mode, &status) -- -The file mode can be READWRITE or READONLY just as with disk files. -More than one process can operate on READONLY mode files at the same -time. CFITSIO supports proper file locking (both in READONLY and -READWRITE modes), so calls to fits\_open\_file may be locked out until -another other process closes the file. - -When an application is finished accessing a FITS file in a shared -memory segment, it may close it (and the file will remain in the -system) with fits\_close\_file, or delete it with fits\_delete\_file. -Physical deletion is postponed until the last process calls -ffclos/ffdelt. fits\_delete\_file tries to obtain a READWRITE lock on -the file to be deleted, thus it can be blocked if the object was not -opened in READWRITE mode. - -A shared memory management utility program called `smem', is included -with the CFITSIO distribution. It can be built by typing `make smem'; -then type `smem -h' to get a list of valid options. Executing smem -without any options causes it to list all the shared memory segments -currently residing in the system and managed by the shared memory -driver. To get a list of all the shared memory objects, run the system -utility program `ipcs [-a]'. - -**B. Base Filename - -The base filename is the name of the file optionally including the -director/subdirectory path, and in the case of `ftp', `http', and `root' -filetypes, the machine identifier. Examples: -- - myfile.fits - !data.fits - /data/myfile.fits - fits.gsfc.nasa.gov/ftp/sampledata/myfile.fits.gz -- - -When creating a new output file on magnetic disk (of type file://) if -the base filename begins with an exclamation point (!) then any -existing file with that same basename will be deleted prior to creating -the new FITS file. Otherwise if the file to be created already exists, -then CFITSIO will return an error and will not overwrite the existing -file. Note that the exclamation point, '!', is a special UNIX character, -so if it is used on the command line rather than entered at a task -prompt, it must be preceded by a backslash to force the UNIX -shell to pass it verbatim to the application program. - -If the output disk file name ends with the suffix '.gz', then CFITSIO -will compress the file using the gzip compression algorithm before -writing it to disk. This can reduce the amount of disk space used by -the file. Note that this feature requires that the uncompressed file -be constructed in memory before it is compressed and written to disk, -so it can fail if there is insufficient available memory. - -An input FITS file may be compressed with the gzip or Unix compress -algorithms, in which case CFITSIO will uncompress the file on the fly -into a temporary file (in memory or on disk). Compressed files may -only be opened with read-only permission. When specifying the name of -a compressed FITS file it is not necessary to append the file suffix -(e.g., `.gz' or `.Z'). If CFITSIO cannot find the input file name -without the suffix, then it will automatically search for a compressed -file with the same root name. In the case of reading ftp and http type -files, CFITSIO generally looks for a compressed version of the file -first, before trying to open the uncompressed file. By default, -CFITSIO copies (and uncompressed if necessary) the ftp or http FITS -file into memory on the local machine before opening it. This will -fail if the local machine does not have enough memory to hold the whole -FITS file, so in this case, the output filename specifier (see the next -section) can be used to further control how CFITSIO reads ftp and http -files. - -If the input file is an IRAF image file (*.imh file) then CFITSIO will -automatically convert it on the fly into a virtual FITS image before it -is opened by the application program. IRAF images can only be opened -with READONLY file access. - -Similarly, if the input file is a raw binary data array, then CFITSIO -will convert it on the fly into a virtual FITS image with the basic set -of required header keywords before it is opened by the application -program (with READONLY access). In this case the data type and -dimensions of the image must be specified in square brackets following -the filename (e.g. rawfile.dat[ib512,512]). The first character (case -insensitive) defines the datatype of the array: -- - b 8-bit unsigned byte - i 16-bit signed integer - u 16-bit unsigned integer - j 32-bit signed integer - r or f 32-bit floating point - d 64-bit floating point -- -An optional second character specifies the byte order of the array -values: b or B indicates big endian (as in FITS files and the native -format of SUN UNIX workstations and Mac PCs) and l or L indicates -little endian (native format of DEC OSF workstations and IBM PCs). If -this character is omitted then the array is assumed to have the native -byte order of the local machine. These datatype characters are then -followed by a series of one or more integer values separated by commas -which define the size of each dimension of the raw array. Arrays with -up to 5 dimensions are currently supported. Finally, a byte offset to -the position of the first pixel in the data file may be specified by -separating it with a ':' from the last dimension value. If omitted, it -is assumed that the offset = 0. This parameter may be used to skip -over any header information in the file that precedes the binary data. -Further examples: -- - raw.dat[b10000] 1-dimensional 10000 pixel byte array - raw.dat[rb400,400,12] 3-dimensional floating point big-endian array - img.fits[ib512,512:2880] reads the 512 x 512 short integer array in - a FITS file, skipping over the 2880 byte header -- - -One special case of input file is where the filename = `-' (a dash or -minus sign) or 'stdin' or 'stdout', which signifies that the input file -is to be read from the stdin stream, or written to the stdout stream if -a new output file is being created. In the case of reading from stdin, -CFITSIO first copies the whole stream into a temporary FITS file (in -memory or on disk), and subsequent reading of the FITS file occurs in -this copy. When writing to stdout, CFITSIO first constructs the whole -file in memory (since random access is required), then flushes it out -to the stdout stream when the file is closed. In addition, if the -output filename = '-.gz' or 'stdout.gz' then it will be gzip compressed -before being written to stdout. - -This ability to read and write on the stdin and stdout steams allows -FITS files to be piped between tasks in memory rather than having to -create temporary intermediate FITS files on disk. For example if task1 -creates an output FITS file, and task2 reads an input FITS file, the -FITS file may be piped between the 2 tasks by specifying -- - task1 - | task2 - -- -where the vertical bar is the Unix piping symbol. This assumes that the 2 -tasks read the name of the FITS file off of the command line. - -**C. Output File Name when Opening an Existing File - -An optional output filename may be specified in parentheses immediately -following the base file name to be opened. This is mainly useful in -those cases where CFITSIO creates a temporary copy of the input FITS -file before it is opened and passed to the application program. This -happens by default when opening a network FTP or HTTP-type file, when -reading a compressed FITS file on a local disk, when reading from the -stdin stream, or when a column filter, row filter, or binning specifier -is included as part of the input file specification. By default this -temporary file is created in memory. If there is not enough memory to -create the file copy, then CFITSIO will exit with an error. In these -cases one can force a permanent file to be created on disk, instead of -a temporary file in memory, by supplying the name in parentheses -immediately following the base file name. The output filename can -include the '!' clobber flag. - -Thus, if the input filename to CFITSIO is: -\verb+file1.fits.gz(file2.fits)+ -then CFITSIO will uncompress `file1.fits.gz' into the local disk file -`file2.fits' before opening it. CFITSIO does not automatically delete -the output file, so it will still exist after the application program -exits. - -In some cases, several different temporary FITS files will be created -in sequence, for instance, if one opens a remote file using FTP, then -filters rows in a binary table extension, then create an image by -binning a pair of columns. In this case, the remote file will be -copied to a temporary local file, then a second temporary file will be -created containing the filtered rows of the table, and finally a third -temporary file containing the binned image will be created. In cases -like this where multiple files are created, the outfile specifier will -be interpreted the name of the final file as described below, in descending -priority: - -\begin{itemize} -\item -as the name of the final image file if an image within a single binary -table cell is opened or if an image is created by binning a table column. -\item -as the name of the file containing the filtered table if a column filter -and/or a row filter are specified. -\item -as the name of the local copy of the remote FTP or HTTP file. -\item -as the name of the uncompressed version of the FITS file, if a -compressed FITS file on local disk has been opened. -\item -otherwise, the output filename is ignored. -\end{itemize} - - -The output file specifier is useful when reading FTP or HTTP-type -FITS files since it can be used to create a local disk copy of the file -that can be reused in the future. If the output file name = `*' then a -local file with the same name as the network file will be created. -Note that CFITSIO will behave differently depending on whether the -remote file is compressed or not as shown by the following examples: -\begin{itemize} -\item -`ftp://remote.machine/tmp/myfile.fits.gz(*)' - the remote compressed -file is copied to the local compressed file `myfile.fits.gz', which -is then uncompressed in local memory before being opened and passed -to the application program. - -\item -`ftp://remote.machine/tmp/myfile.fits.gz(myfile.fits)' - the remote -compressed file is copied and uncompressed into the local file -`myfile.fits'. This example requires less local memory than the -previous example since the file is uncompressed on disk instead of -in memory. - -\item -`ftp://remote.machine/tmp/myfile.fits(myfile.fits.gz)' - this will -usually produce an error since CFITSIO itself cannot compress files. -\end{itemize} - -The exact behavior of CFITSIO in the latter case depends on the type of -ftp server running on the remote machine and how it is configured. In -some cases, if the file `myfile.fits.gz' exists on the remote machine, -then the server will copy it to the local machine. In other cases the -ftp server will automatically create and transmit a compressed version -of the file if only the uncompressed version exists. This can get -rather confusing, so users should use a certain amount of caution when -using the output file specifier with FTP or HTTP file types, to make -sure they get the behavior that they expect. - -**D. Template File Name when Creating a New File - -When a new FITS file is created with a call to fits\_create\_file, the -name of a template file may be supplied in parentheses immediately -following the name of the new file to be created. This template is -used to define the structure of one or more HDUs in the new file. The -template file may be another FITS file, in which case the newly created -file will have exactly the same keywords in each HDU as in the template -FITS file, but all the data units will be filled with zeros. The -template file may also be an ASCII text file, where each line (in -general) describes one FITS keyword record. The format of the ASCII -template file is described below. - -**E. Image Tile-Compression Specification - -When specifying the name of the output FITS file to be created, the -user can indicate that images should be written in tile-compressed -format (see section 5.5, ``Primary Array or IMAGE Extension I/O -Routines'') by enclosing the compression parameters in square brackets -following the root disk file name. Here are some examples of the -syntax for specifying tile-compressed output images: -- - myfile.fit[compress] - use Rice algorithm and default tile size - - myfile.fit[compress GZIP] - use the specified compression algorithm; - myfile.fit[compress Rice] only the first letter of the algorithm - myfile.fit[compress PLIO] name is required. - - myfile.fit[compress Rice 100,100] - use 100 x 100 pixel tile size - myfile.fit[compress Rice 100,100;2] - as above, and use noisebits = 2 -- - -**F. HDU Location Specification - -The optional HDU location specifier defines which HDU (Header-Data -Unit, also known as an `extension') within the FITS file to initially -open. It must immediately follow the base file name (or the output -file name if present). If it is not specified then the first HDU (the -primary array) is opened. The HDU location specifier is required if -the colFilter, rowFilter, or binSpec specifiers are present, because -the primary array is not a valid HDU for these operations. The HDU may -be specified either by absolute position number, starting with 0 for -the primary array, or by reference to the HDU name, and optionally, the -version number and the HDU type of the desired extension. The location -of an image within a single cell of a binary table may also be -specified, as described below. - -The absolute position of the extension is specified either by enclosed -the number in square brackets (e.g., `[1]' = the first extension -following the primary array) or by preceded the number with a plus sign -(`+1'). To specify the HDU by name, give the name of the desired HDU -(the value of the EXTNAME or HDUNAME keyword) and optionally the -extension version number (value of the EXTVER keyword) and the -extension type (value of the XTENSION keyword: IMAGE, ASCII or TABLE, -or BINTABLE), separated by commas and all enclosed in square brackets. -If the value of EXTVER and XTENSION are not specified, then the first -extension with the correct value of EXTNAME is opened. The extension -name and type are not case sensitive, and the extension type may be -abbreviated to a single letter (e.g., I = IMAGE extension or primary -array, A or T = ASCII table extension, and B = binary table BINTABLE -extension). If the HDU location specifier is equal to `[PRIMARY]' or -`[P]', then the primary array (the first HDU) will be opened. - -FITS images are most commonly stored in the primary array or an image -extension, but images can also be stored as a vector in a single cell -of a binary table (i.e. each row of the vector column contains a -different image). Such an image can be opened with CFITSIO by -specifying the desired column name and the row number after the binary -table HDU specifier as shown in the following examples. The column name -is separated from the HDU specifier by a semicolon and the row number -is enclosed in parentheses. In this case CFITSIO copies the image from -the table cell into a temporary primary array before it is opened. The -application program then just sees the image in the primary array, -without any extensions. The particular row to be opened may be -specified either by giving an absolute integer row number (starting -with 1 for the first row), or by specifying a boolean expression that -evaluates to TRUE for the desired row. The first row that satisfies -the expression will be used. The row selection expression has the same -syntax as described in the Row Filter Specifier section, below. - - Examples: -- - myfile.fits[3] - open the 3rd HDU following the primary array - myfile.fits+3 - same as above, but using the FTOOLS-style notation - myfile.fits[EVENTS] - open the extension that has EXTNAME = 'EVENTS' - myfile.fits[EVENTS, 2] - same as above, but also requires EXTVER = 2 - myfile.fits[events,2,b] - same, but also requires XTENSION = 'BINTABLE' - myfile.fits[3; images(17)] - opens the image in row 17 of the 'images' - column in the 3rd extension of the file. - myfile.fits[3; images(exposure > 100)] - as above, but opens the image - in the first row that has an 'exposure' column value - greater than 100. -- - -**G. Image Section - -A virtual file containing a rectangular subsection of an image can be -extracted and opened by specifying the range of pixels (start:end) -along each axis to be extracted from the original image. One can also -specify an optional pixel increment (start:end:step) for each axis of -the input image. A pixel step = 1 will be assumed if it is not -specified. If the start pixel is larger then the end pixel, then the -image will be flipped (producing a mirror image) along that dimension. -An asterisk, '*', may be used to specify the entire range of an axis, -and '-*' will flip the entire axis. The input image can be in the -primary array, in an image extension, or contained in a vector cell of -a binary table. In the later 2 cases the extension name or number must -be specified before the image section specifier. - - Examples: -- - myfile.fits[1:512:2, 2:512:2] - open a 256x256 pixel image - consisting of the odd numbered columns (1st axis) and - the even numbered rows (2nd axis) of the image in the - primary array of the file. - - myfile.fits[*, 512:256] - open an image consisting of all the columns - in the input image, but only rows 256 through 512. - The image will be flipped along the 2nd axis since - the starting pixel is greater than the ending pixel. - - myfile.fits[*:2, 512:256:2] - same as above but keeping only - every other row and column in the input image. - - myfile.fits[-*, *] - copy the entire image, flipping it along - the first axis. - - myfile.fits[3][1:256,1:256] - opens a subsection of the image that - is in the 3rd extension of the file. - - myfile.fits[4; images(12)][1:10,1:10] - open an image consisting - of the first 10 pixels in both dimensions. The original - image resides in the 12th row of the 'images' vector - column in the table in the 4th extension of the file. -- - -When CFITSIO opens an image section it first creates a temporary file -containing the image section plus a copy of any other HDUs in the -file. This temporary file is then opened by the application program, -so it is not possible to write to or modify the input file when -specifying an image section. Note that CFITSIO automatically updates -the world coordinate system keywords in the header of the image -section, if they exist, so that the coordinate associated with each -pixel in the image section will be computed correctly. - -**H. Image Transform Filters - -CFITSIO can apply a user-specified mathematical function to the value -of every pixel in a FITS image, thus creating a new virtual image -in computer memory that is then opened and read by the application -program. The original FITS image is not modified by this process. - -The image transformation specifier is appended to the input -FITS file name and is enclosed in square brackets. It begins with the -letters 'PIX' to distinguish it from other types of FITS file filters -that are recognized by CFITSIO. The image transforming function may -use any of the mathematical operators listed in the following -'Row Filtering Specification' section of this document. -Some examples of image transform filters are: -- - [pix X * 2.0] - multiply each pixel by 2.0 - [pix sqrt(X)] - take the square root of each pixel - [pix X + #ZEROPT - add the value of the ZEROPT keyword - [pix X>0 ? log10(X) : -99.] - if the pixel value is greater - than 0, compute the base 10 log, - else set the pixel = -99. -- -Use the letter 'X' in the expression to represent the current pixel value -in the image. The expression is evaluated -independently for each pixel in the image and may be a function of 1) the -original pixel value, 2) the value of other pixels in the image at -a given relative offset from the position of the pixel that is being -evaluated, and 3) the value of -any header keywords. Header keyword values are represented -by the name of the keyword preceded by the '\#' sign. - - -To access the the value of adjacent pixels in the image, -specify the (1-D) offset from the current pixel in curly brackets. -For example -- - [pix (x{-1} + x + x{+1}) / 3] -- -will replace each pixel value with the running mean of the values of that -pixel and it's 2 neighboring pixels. Note that in this notation the image -is treated as a 1-D array, where each row of the image (or higher dimensional -cube) is appended one after another in one long array of pixels. -It is possible to refer to pixels -in the rows above or below the current pixel by using the value of the -NAXIS1 header keyword. For example -- - [pix (x{-#NAXIS1} + x + x{#NAXIS1}) / 3] -- -will compute the mean of each image pixel and the pixels immediately -above and below it in the adjacent rows of the image. -The following more complex example -creates a smoothed virtual image where each pixel -is a 3 x 3 boxcar average of the input image pixels: -- - [pix (X + X{-1} + X{+1} - + X{-#NAXIS1} + X{-#NAXIS1 - 1} + X{-#NAXIS1 + 1} - + X{#NAXIS1} + X{#NAXIS1 - 1} + X{#NAXIS1 + 1}) / 9.] -- -If the pixel offset -extends beyond the first or last pixel in the image, the function will -evaluate to undefined, or NULL. - -For complex or commonly used image filtering operations, -one can write the expression into an external text file and -then import it into the -filter using the syntax '[pix @filename.txt]'. The mathematical -expression can -extend over multiple lines of text in the file. -Any lines in the external text file -that begin with 2 slash characters ('//') will be ignored and may be -used to add comments into the file. - -By default, the datatype of the resulting image will be the same as -the original image, but one may force a different datatype by appended -a code letter to the 'pix' keyword: -- - pixb - 8-bit byte image with BITPIX = 8 - pixi - 16-bit integer image with BITPIX = 16 - pixj - 32-bit integer image with BITPIX = 32 - pixr - 32-bit float image with BITPIX = -32 - pixd - 64-bit float image with BITPIX = -64 -- -Also by default, any other HDUs in the input file will be copied without -change to the -output virtual FITS file, but one may discard the other HDUs by adding -the number '1' to the 'pix' keyword (and following any optional datatype code -letter). For example: -- - myfile.fits[3][pixr1 sqrt(X)] -- -will create a virtual FITS file containing only a primary array image -with 32-bit floating point pixels that have a value equal to the square -root of the pixels in the image that is in the 3rd extension -of the 'myfile.fits' file. - - - -**I. Column and Keyword Filtering Specification - -The optional column/keyword filtering specifier is used to modify the -column structure and/or the header keywords in the HDU that was -selected with the previous HDU location specifier. This filtering -specifier must be enclosed in square brackets and can be distinguished -from a general row filter specifier (described below) by the fact that -it begins with the string 'col ' and is not immediately followed by an -equals sign. The original file is not changed by this filtering -operation, and instead the modifications are made on a copy of the -input FITS file (usually in memory), which also contains a copy of all -the other HDUs in the file. This temporary file is passed to the -application program and will persist only until the file is closed or -until the program exits, unless the outfile specifier (see above) is -also supplied. - -The column/keyword filter can be used to perform the following -operations. More than one operation may be specified by separating -them with commas or semi-colons. - -\begin{itemize} - -\item -Copy only a specified list of columns columns to the filtered input file. -The list of column name should be separated by commas or semi-colons. Wild card -characters may be used in the column names to match multiple columns. -If the expression contains both a list of columns to be included and -columns to be deleted, then all the columns in the original table -except the explicitly deleted columns will appear in the filtered -table (i.e., there is no need to explicitly list the columns to -be included if any columns are being deleted). - -\item -Delete a column or keyword by listing the name preceded by a minus -sign or an exclamation mark (!), e.g., '-TIME' will delete the TIME -column if it exists, otherwise the TIME keyword. An error is returned -if neither a column nor keyword with this name exists. Note that the -exclamation point, '!', is a special UNIX character, so if it is used -on the command line rather than entered at a task prompt, it must be -preceded by a backslash to force the UNIX shell to ignore it. - -\item -Rename an existing column or keyword with the syntax 'NewName == -OldName'. An error is returned if neither a column nor keyword with -this name exists. - -\item -Append a new column or keyword to the table. To create a column, -give the new name, optionally followed by the datatype in parentheses, -followed by a single equals sign and an expression to be used to -compute the value (e.g., 'newcol(1J) = 0' will create a new 32-bit -integer column called 'newcol' filled with zeros). The datatype is -specified using the same syntax that is allowed for the value of the -FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for binary tables, -and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If the datatype is -not specified then an appropriate datatype will be chosen depending on -the form of the expression (may be a character string, logical, bit, long -integer, or double column). An appropriate vector count (in the case -of binary tables) will also be added if not explicitly specified. - -When creating a new keyword, the keyword name must be preceded by a -pound sign '\#', and the expression must evaluate to a scalar -(i.e., cannot have a column name in the expression). The comment -string for the keyword may be specified in parentheses immediately -following the keyword name (instead of supplying a datatype as in -the case of creating a new column). If the keyword name ends with a -pound sign '\#', then cfitsio will substitute the number of the -most recently referenced column for the \# character . -This is especially useful when writing -a column-related keyword like TUNITn for a newly created column, -as shown in the following examples. - -COMMENT and HISTORY keywords may also be created with the following syntax: -- - #COMMENT = 'This is a comment keyword' - #HISTORY = 'This is a history keyword' -- -Note that the equal sign and the quote characters will be removed, so -that the resulting header keywords in these cases will look like this: -- - COMMENT This is a comment keyword - HISTORY This is a history keyword -- -These two special keywords are always appended to the end of the header -and will not affect any previously existing COMMENT or HISTORY keywords. - -\item -Recompute (overwrite) the values in an existing column or keyword by -giving the name followed by an equals sign and an arithmetic -expression. -\end{itemize} - -The expression that is used when appending or recomputing columns or -keywords can be arbitrarily complex and may be a function of other -header keyword values and other columns (in the same row). The full -syntax and available functions for the expression are described below -in the row filter specification section. - -If the expression contains both a list of columns to be included and -columns to be deleted, then all the columns in the original table -except the explicitly deleted columns will appear in the filtered -table. If no columns to be deleted are specified, then only the -columns that are explicitly listed will be included in the filtered -output table. To include all the columns, add the '*' wildcard -specifier at the end of the list, as shown in the examples. - -For complex or commonly used operations, one can also place the -operations into an external text file and import it into the column -filter using the syntax '[col @filename.txt]'. The operations can -extend over multiple lines of the file, but multiple operations must -still be separated by commas or semi-colons. Any lines in the external text file -that begin with 2 slash characters ('//') will be ignored and may be -used to add comments into the file. - -Examples: -- - [col Time, rate] - only the Time and rate columns will - appear in the filtered input file. - - [col Time, *raw] - include the Time column and any other - columns whose name ends with 'raw'. - - [col -TIME; Good == STATUS] - deletes the TIME column and - renames the status column to 'Good' - - [col PI=PHA * 1.1 + 0.2; #TUNIT#(column units) = 'counts';*] - - creates new PI column from PHA values - and also writes the TUNITn keyword - for the new column. The final '*' - expression means preserve all the - columns in the input table in the - virtual output table; without the '*' - the output table would only contain - the single 'PI' column. - - [col rate = rate/exposure, TUNIT#(&) = 'counts/s';*] - - recomputes the rate column by dividing - it by the EXPOSURE keyword value. This - also modifies the value of the TUNITn - keyword for this column. The use of the - '&' character for the keyword comment - string means preserve the existing - comment string for that keyword. The - final '*' preserves all the columns - in the input table in the virtual - output table. -- - -**J. Row Filtering Specification - - When entering the name of a FITS table that is to be opened by a - program, an optional row filter may be specified to select a subset - of the rows in the table. A temporary new FITS file is created on - the fly which contains only those rows for which the row filter - expression evaluates to true. (The primary array and any other - extensions in the input file are also copied to the temporary - file). The original FITS file is closed and the new virtual file - is opened by the application program. The row filter expression is - enclosed in square brackets following the file name and extension - name (e.g., 'file.fits[events][GRADE==50]' selects only those rows - where the GRADE column value equals 50). When dealing with tables - where each row has an associated time and/or 2D spatial position, - the row filter expression can also be used to select rows based on - the times in a Good Time Intervals (GTI) extension, or on spatial - position as given in a SAO-style region file. - -***1. General Syntax - - The row filtering expression can be an arbitrarily complex series - of operations performed on constants, keyword values, and column - data taken from the specified FITS TABLE extension. The expression - must evaluate to a boolean value for each row of the table, where - a value of FALSE means that the row will be excluded. - - For complex or commonly used filters, one can place the expression - into a text file and import it into the row filter using the syntax - '[@filename.txt]'. The expression can be arbitrarily complex and - extend over multiple lines of the file. Any lines in the external - text file that begin with 2 slash characters ('//') will be ignored - and may be used to add comments into the file. - - Keyword and column data are referenced by name. Any string of - characters not surrounded by quotes (ie, a constant string) or - followed by an open parentheses (ie, a function name) will be - initially interpreted as a column name and its contents for the - current row inserted into the expression. If no such column exists, - a keyword of that name will be searched for and its value used, if - found. To force the name to be interpreted as a keyword (in case - there is both a column and keyword with the same name), precede the - keyword name with a single pound sign, '\#', as in '\#NAXIS2'. Due to - the generalities of FITS column and keyword names, if the column or - keyword name contains a space or a character which might appear as - an arithmetic term then enclose the name in '\$' characters as in - \$MAX PHA\$ or \#\$MAX-PHA\$. Names are case insensitive. - - To access a table entry in a row other than the current one, follow - the column's name with a row offset within curly braces. For - example, 'PHA\{-3\}' will evaluate to the value of column PHA, 3 rows - above the row currently being processed. One cannot specify an - absolute row number, only a relative offset. Rows that fall outside - the table will be treated as undefined, or NULLs. - - Boolean operators can be used in the expression in either their - Fortran or C forms. The following boolean operators are available: -- - "equal" .eq. .EQ. == "not equal" .ne. .NE. != - "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< - "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => - "or" .or. .OR. || "and" .and. .AND. && - "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ -- - -Note that the exclamation -point, '!', is a special UNIX character, so if it is used on the -command line rather than entered at a task prompt, it must be preceded -by a backslash to force the UNIX shell to ignore it. - - The expression may also include arithmetic operators and functions. - Trigonometric functions use radians, not degrees. The following - arithmetic operators and functions can be used in the expression - (function names are case insensitive). A null value will be returned - in case of illegal operations such as divide by zero, sqrt(negative) - log(negative), log10(negative), arccos(.gt. 1), arcsin(.gt. 1). - -- - "addition" + "subtraction" - - "multiplication" * "division" / - "negation" - "exponentiation" ** ^ - "absolute value" abs(x) "cosine" cos(x) - "sine" sin(x) "tangent" tan(x) - "arc cosine" arccos(x) "arc sine" arcsin(x) - "arc tangent" arctan(x) "arc tangent" arctan2(y,x) - "hyperbolic cos" cosh(x) "hyperbolic sin" sinh(x) - "hyperbolic tan" tanh(x) "round to nearest int" round(x) - "round down to int" floor(x) "round up to int" ceil(x) - "exponential" exp(x) "square root" sqrt(x) - "natural log" log(x) "common log" log10(x) - "modulus" x % y "random # [0.0,1.0)" random() - "random Gaussian" randomn() "random Poisson" randomp(x) - "minimum" min(x,y) "maximum" max(x,y) - "cumulative sum" accum(x) "sequential difference" seqdiff(x) - "if-then-else" b?x:y - "angular separation" angsep(ra1,dec1,ra2,de2) (all in degrees) - "substring" strmid(s,p,n) "string search" strstr(s,r) -- -Three different random number functions are provided: random(), with no -arguments, produces a uniform random deviate between 0 and 1; randomn(), -also with no arguments, produces a normal (Gaussian) random deviate with -zero mean and unit standard deviation; randomp(x) produces a Poisson random -deviate whose expected number of counts is X. X may be any positive real -number of expected counts, including fractional values, but the return value -is an integer. - -When the random functions are used in a vector expression, by default -the same random value will be used when evaluating each element of the vector. -If different random numbers are desired, then the name of a vector -column should be supplied as the single argument to the random -function (e.g., "flux + 0.1 * random(flux)", where "flux' is the -name of a vector column). This will create a vector of -random numbers that will be used in sequence when evaluating each -element of the vector expression. - - An alternate syntax for the min and max functions has only a single - argument which should be a vector value (see below). The result - will be the minimum/maximum element contained within the vector. - - The accum(x) function forms the cumulative sum of x, element by element. - Vector columns are supported simply by performing the summation process - through all the values. Null values are treated as 0. The seqdiff(x) - function forms the sequential difference of x, element by element. - The first value of seqdiff is the first value of x. A single null - value in x causes a pair of nulls in the output. The seqdiff and - accum functions are functional inverses, i.e., seqdiff(accum(x)) == x - as long as no null values are present. - -In the if-then-else expression, "b?x:y", b is an explicit boolean -value or expression. There is no automatic type conversion from -numeric to boolean values, so one needs to use "iVal!=0" instead of -merely "iVal" as the boolean argument. x and y can be any scalar data -type (including string). - - The angsep function computes the angular separation in degrees - between 2 celestial positions, where the first 2 parameters - give the RA-like and Dec-like coordinates (in decimal degrees) - of the first position, and the 3rd and 4th parameters give the - coordinates of the second position. - -The substring function strmid(S,P,N) extracts a substring from S, -starting at string position P, with a substring length N. The first -character position in S is labeled as 1. If P is 0, or refers to a -position beyond the end of S, then the extracted substring will be -NULL. S, P, and N may be functions of other columns. - -The string search function strstr(S,R) searches for the first occurrence -of the substring R in S. The result is an integer, indicating the -character position of the first match (where 1 is the first character -position of S). If no match is found, then strstr() returns a NULL -value. - - The following type casting operators are available, where the - enclosing parentheses are required and taken from the C language - usage. Also, the integer to real casts values to double precision: -- - "real to integer" (int) x (INT) x - "integer to real" (float) i (FLOAT) i -- - - In addition, several constants are built in for use in numerical - expressions: - -- - #pi 3.1415... #e 2.7182... - #deg #pi/180 #row current row number - #null undefined value #snull undefined string -- - - A string constant must be enclosed in quotes as in 'Crab'. The - "null" constants are useful for conditionally setting table values - to a NULL, or undefined, value (eg., "col1==-99 ? \#NULL : col1"). - - There is also a function for testing if two values are close to - each other, i.e., if they are "near" each other to within a user - specified tolerance. The arguments, value\_1 and value\_2 can be - integer or real and represent the two values who's proximity is - being tested to be within the specified tolerance, also an integer - or real: -- - near(value_1, value_2, tolerance) -- - When a NULL, or undefined, value is encountered in the FITS table, - the expression will evaluate to NULL unless the undefined value is - not actually required for evaluation, e.g. "TRUE .or. NULL" - evaluates to TRUE. The following two functions allow some NULL - detection and handling: -- - "a null value?" ISNULL(x) - "define a value for null" DEFNULL(x,y) -- - The former - returns a boolean value of TRUE if the argument x is NULL. The - later "defines" a value to be substituted for NULL values; it - returns the value of x if x is not NULL, otherwise it returns the - value of y. - -***2. Bit Masks - - Bit masks can be used to select out rows from bit columns (TFORMn = - \#X) in FITS files. To represent the mask, binary, octal, and hex - formats are allowed: - -- - binary: b0110xx1010000101xxxx0001 - octal: o720x1 -> (b111010000xxx001) - hex: h0FxD -> (b00001111xxxx1101) -- - - In all the representations, an x or X is allowed in the mask as a - wild card. Note that the x represents a different number of wild - card bits in each representation. All representations are case - insensitive. - - To construct the boolean expression using the mask as the boolean - equal operator described above on a bit table column. For example, - if you had a 7 bit column named flags in a FITS table and wanted - all rows having the bit pattern 0010011, the selection expression - would be: - -- - flags == b0010011 - or - flags .eq. b10011 -- - - It is also possible to test if a range of bits is less than, less - than equal, greater than and greater than equal to a particular - boolean value: - -- - flags <= bxxx010xx - flags .gt. bxxx100xx - flags .le. b1xxxxxxx -- - - Notice the use of the x bit value to limit the range of bits being - compared. - - It is not necessary to specify the leading (most significant) zero - (0) bits in the mask, as shown in the second expression above. - - Bit wise AND, OR and NOT operations are also possible on two or - more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) - operators. All of these operators result in a bit field which can - then be used with the equal operator. For example: - -- - (!flags) == b1101100 - (flags & b1000001) == bx000001 -- - - Bit fields can be appended as well using the '+' operator. Strings - can be concatenated this way, too. - -***3. Vector Columns - - Vector columns can also be used in building the expression. No - special syntax is required if one wants to operate on all elements - of the vector. Simply use the column name as for a scalar column. - Vector columns can be freely intermixed with scalar columns or - constants in virtually all expressions. The result will be of the - same dimension as the vector. Two vectors in an expression, though, - need to have the same number of elements and have the same - dimensions. The only places a vector column cannot be used (for - now, anyway) are the SAO region functions and the NEAR boolean - function. - - Arithmetic and logical operations are all performed on an element by - element basis. Comparing two vector columns, eg "COL1 == COL2", - thus results in another vector of boolean values indicating which - elements of the two vectors are equal. - - Eight functions are available that operate on a vector and return a - scalar result: -- - "minimum" MIN(V) "maximum" MAX(V) - "average" AVERAGE(V) "median" MEDIAN(V) - "summation" SUM(V) "standard deviation" STDDEV(V) - "# of values" NELEM(V) "# of non-null values" NVALID(V) -- - where V represents the name of a vector column or a manually - constructed vector using curly brackets as described below. The - first 6 of these functions ignore any null values in the vector when - computing the result. The STDDEV() function computes the sample - standard deviation, i.e. it is proportional to 1/SQRT(N-1) instead - of 1/SQRT(N), where N is NVALID(V). - - The SUM function literally sums all the elements in x, returning a - scalar value. If x is a boolean vector, SUM returns the number - of TRUE elements. The NELEM function returns the number of elements - in vector x whereas NVALID return the number of non-null elements in - the vector. (NELEM also operates on bit and string columns, - returning their column widths.) As an example, to test whether all - elements of two vectors satisfy a given logical comparison, one can - use the expression -- - SUM( COL1 > COL2 ) == NELEM( COL1 ) -- - - which will return TRUE if all elements of COL1 are greater than - their corresponding elements in COL2. - - To specify a single element of a vector, give the column name - followed by a comma-separated list of coordinates enclosed in - square brackets. For example, if a vector column named PHAS exists - in the table as a one dimensional, 256 component list of numbers - from which you wanted to select the 57th component for use in the - expression, then PHAS[57] would do the trick. Higher dimensional - arrays of data may appear in a column. But in order to interpret - them, the TDIMn keyword must appear in the header. Assuming that a - (4,4,4,4) array is packed into each row of a column named ARRAY4D, - the (1,2,3,4) component element of each row is accessed by - ARRAY4D[1,2,3,4]. Arrays up to dimension 5 are currently - supported. Each vector index can itself be an expression, although - it must evaluate to an integer value within the bounds of the - vector. Vector columns which contain spaces or arithmetic operators - must have their names enclosed in "\$" characters as with - \$ARRAY-4D\$[1,2,3,4]. - - A more C-like syntax for specifying vector indices is also - available. The element used in the preceding example alternatively - could be specified with the syntax ARRAY4D[4][3][2][1]. Note the - reverse order of indices (as in C), as well as the fact that the - values are still ones-based (as in Fortran -- adopted to avoid - ambiguity for 1D vectors). With this syntax, one does not need to - specify all of the indices. To extract a 3D slice of this 4D - array, use ARRAY4D[4]. - - Variable-length vector columns are not supported. - - Vectors can be manually constructed within the expression using a - comma-separated list of elements surrounded by curly braces ('\{\}'). - For example, '\{1,3,6,1\}' is a 4-element vector containing the values - 1, 3, 6, and 1. The vector can contain only boolean, integer, and - real values (or expressions). The elements will be promoted to the - highest datatype present. Any elements which are themselves - vectors, will be expanded out with each of its elements becoming an - element in the constructed vector. - -***4. Good Time Interval Filtering - - A common filtering method involves selecting rows which have a time - value which lies within what is called a Good Time Interval or GTI. - The time intervals are defined in a separate FITS table extension - which contains 2 columns giving the start and stop time of each - good interval. The filtering operation accepts only those rows of - the input table which have an associated time which falls within - one of the time intervals defined in the GTI extension. A high - level function, gtifilter(a,b,c,d), is available which evaluates - each row of the input table and returns TRUE or FALSE depending - whether the row is inside or outside the good time interval. The - syntax is -- - gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) -- - where each "[]" demarks optional parameters. Note that the quotes - around the gtifile and START/STOP column are required. Either single - or double quotes may be used. In cases where this expression is - entered on the Unix command line, enclose the entire expression in - double quotes, and then use single quotes within the expression to - enclose the 'gtifile' and other terms. It is also usually possible - to do the reverse, and enclose the whole expression in single quotes - and then use double quotes within the expression. The gtifile, - if specified, can be blank ("") which will mean to use the first - extension with the name "*GTI*" in the current file, a plain - extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be - used to select an extension in the current file, or a regular - filename with or without an extension specifier which in the latter - case will mean to use the first extension with an extension name - "*GTI*". Expr can be any arithmetic expression, including simply - the time column name. A vector time expression will produce a - vector boolean result. STARTCOL and STOPCOL are the names of the - START/STOP columns in the GTI extension. If one of them is - specified, they both must be. - - In its simplest form, no parameters need to be provided -- default - values will be used. The expression "gtifilter()" is equivalent to -- - gtifilter( "", TIME, "*START*", "*STOP*" ) -- - This will search the current file for a GTI extension, filter the - TIME column in the current table, using START/STOP times taken from - columns in the GTI extension with names containing the strings - "START" and "STOP". The wildcards ('*') allow slight variations in - naming conventions such as "TSTART" or "STARTTIME". The same - default values apply for unspecified parameters when the first one - or two parameters are specified. The function automatically - searches for TIMEZERO/I/F keywords in the current and GTI - extensions, applying a relative time offset, if necessary. - -***5. Spatial Region Filtering - - Another common filtering method selects rows based on whether the - spatial position associated with each row is located within a given - 2-dimensional region. The syntax for this high-level filter is -- - regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) -- - where each "[]" demarks optional parameters. The region file name - is required and must be enclosed in quotes. The remaining - parameters are optional. There are 2 supported formats for the - region file: ASCII file or FITS binary table. The region file - contains a list of one or more geometric shapes (circle, - ellipse, box, etc.) which defines a region on the celestial sphere - or an area within a particular 2D image. The region file is - typically generated using an image display program such as fv/POW - (distribute by the HEASARC), or ds9 (distributed by the Smithsonian - Astrophysical Observatory). Users should refer to the documentation - provided with these programs for more details on the syntax used in - the region files. The FITS region file format is defined in a document - available from the FITS Support Office at - http://fits.gsfc.nasa.gov/ registry/ region.html - - In its simplest form, (e.g., regfilter("region.reg") ) the - coordinates in the default 'X' and 'Y' columns will be used to - determine if each row is inside or outside the area specified in - the region file. Alternate position column names, or expressions, - may be entered if needed, as in -- - regfilter("region.reg", XPOS, YPOS) -- - Region filtering can be applied most unambiguously if the positions - in the region file and in the table to be filtered are both give in - terms of absolute celestial coordinate units. In this case the - locations and sizes of the geometric shapes in the region file are - specified in angular units on the sky (e.g., positions given in - R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, - each row of the filtered table will have a celestial coordinate - associated with it. This association is usually implemented using - a set of so-called 'World Coordinate System' (or WCS) FITS keywords - that define the coordinate transformation that must be applied to - the values in the 'X' and 'Y' columns to calculate the coordinate. - - Alternatively, one can perform spatial filtering using unitless - 'pixel' coordinates for the regions and row positions. In this - case the user must be careful to ensure that the positions in the 2 - files are self-consistent. A typical problem is that the region - file may be generated using a binned image, but the unbinned - coordinates are given in the event table. The ROSAT events files, - for example, have X and Y pixel coordinates that range from 1 - - 15360. These coordinates are typically binned by a factor of 32 to - produce a 480x480 pixel image. If one then uses a region file - generated from this image (in image pixel units) to filter the - ROSAT events file, then the X and Y column values must be converted - to corresponding pixel units as in: -- - regfilter("rosat.reg", X/32.+.5, Y/32.+.5) -- - Note that this binning conversion is not necessary if the region - file is specified using celestial coordinate units instead of pixel - units because CFITSIO is then able to directly compare the - celestial coordinate of each row in the table with the celestial - coordinates in the region file without having to know anything - about how the image may have been binned. - - The last "wcs cols" parameter should rarely be needed. If supplied, - this string contains the names of the 2 columns (space or comma - separated) which have the associated WCS keywords. If not supplied, - the filter will scan the X and Y expressions for column names. - If only one is found in each expression, those columns will be - used, otherwise an error will be returned. - - These region shapes are supported (names are case insensitive): -- - Point ( X1, Y1 ) <- One pixel square region - Line ( X1, Y1, X2, Y2 ) <- One pixel wide region - Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with - Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered - Box ( Xc, Yc, Wdth, Hght, A ) V within the region - Diamond ( Xc, Yc, Wdth, Hght, A ) - Circle ( Xc, Yc, R ) - Annulus ( Xc, Yc, Rin, Rout ) - Ellipse ( Xc, Yc, Rx, Ry, A ) - Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) - Sector ( Xc, Yc, Amin, Amax ) -- - where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are - the coordinates of the shape's edges; Rxxx are the shapes' various - Radii or semi-major/minor axes; and Axxx are the angles of rotation - (or bounding angles for Sector) in degrees. For rotated shapes, the - rotation angle can be left off, indicating no rotation. Common - alternate names for the regions can also be used: rotbox = box; - rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie - = sector. When a shape's name is preceded by a minus sign, '-', - the defined region is instead the area *outside* its boundary (ie, - the region is inverted). All the shapes within a single region - file are OR'd together to create the region, and the order is - significant. The overall way of looking at region files is that if - the first region is an excluded region then a dummy included region - of the whole detector is inserted in the front. Then each region - specification as it is processed overrides any selections inside of - that region specified by previous regions. Another way of thinking - about this is that if a previous excluded region is completely - inside of a subsequent included region the excluded region is - ignored. - - The positional coordinates may be given either in pixel units, - decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes - may be given in pixels, degrees, arcminutes, or arcseconds. Look - at examples of region file produced by fv/POW or ds9 for further - details of the region file format. - - There are three functions that are primarily for use with SAO region - files and the FSAOI task, but they can be used directly. They - return a boolean true or false depending on whether a two - dimensional point is in the region or not: -- - "point in a circular region" - circle(xcntr,ycntr,radius,Xcolumn,Ycolumn) - - "point in an elliptical region" - ellipse(xcntr,ycntr,xhlf_wdth,yhlf_wdth,rotation,Xcolumn,Ycolumn) - - "point in a rectangular region" - box(xcntr,ycntr,xfll_wdth,yfll_wdth,rotation,Xcolumn,Ycolumn) - - where - (xcntr,ycntr) are the (x,y) position of the center of the region - (xhlf_wdth,yhlf_wdth) are the (x,y) half widths of the region - (xfll_wdth,yfll_wdth) are the (x,y) full widths of the region - (radius) is half the diameter of the circle - (rotation) is the angle(degrees) that the region is rotated with - respect to (xcntr,ycntr) - (Xcoord,Ycoord) are the (x,y) coordinates to test, usually column - names - NOTE: each parameter can itself be an expression, not merely a - column name or constant. -- - -***5. Example Row Filters -- - [ binary && mag <= 5.0] - Extract all binary stars brighter - than fifth magnitude (note that - the initial space is necessary to - prevent it from being treated as a - binning specification) - - [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 - - [IMAGE[4,5] .gt. 100] - Extract all rows that have the - (4,5) component of the IMAGE column - greater than 100 - - [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the - absolute value of the sine of theta - less than a half where the angles - are tabulated in degrees - - [SUM( SPEC > 3*BACKGRND )>=1] - Extract all rows containing a - spectrum, held in vector column - SPEC, with at least one value 3 - times greater than the background - level held in a keyword, BACKGRND - - [VCOL=={1,4,2}] - Extract all rows whose vector column - VCOL contains the 3-elements 1, 4, and - 2. - - [@rowFilter.txt] - Extract rows using the expression - contained within the text file - rowFilter.txt - - [gtifilter()] - Search the current file for a GTI - extension, filter the TIME - column in the current table, using - START/STOP times taken from - columns in the GTI extension - - [regfilter("pow.reg")] - Extract rows which have a coordinate - (as given in the X and Y columns) - within the spatial region specified - in the pow.reg region file. - - [regfilter("pow.reg", Xs, Ys)] - Same as above, except that the - Xs and Ys columns will be used to - determine the coordinate of each - row in the table. -- - -**K. Binning or Histogramming Specification - -The optional binning specifier is enclosed in square brackets and can -be distinguished from a general row filter specification by the fact -that it begins with the keyword 'bin' not immediately followed by an -equals sign. When binning is specified, a temporary N-dimensional FITS -primary array is created by computing the histogram of the values in -the specified columns of a FITS table extension. After the histogram -is computed the input FITS file containing the table is then closed and -the temporary FITS primary array is opened and passed to the -application program. Thus, the application program never sees the -original FITS table and only sees the image in the new temporary file -(which has no additional extensions). Obviously, the application -program must be expecting to open a FITS image and not a FITS table in -this case. - -The data type of the FITS histogram image may be specified by appending -'b' (for 8-bit byte), 'i' (for 16-bit integers), 'j' (for 32-bit -integer), 'r' (for 32-bit floating points), or 'd' (for 64-bit double -precision floating point) to the 'bin' keyword (e.g. '[binr X]' -creates a real floating point image). If the datatype is not -explicitly specified then a 32-bit integer image will be created by -default, unless the weighting option is also specified in which case -the image will have a 32-bit floating point data type by default. - -The histogram image may have from 1 to 4 dimensions (axes), depending -on the number of columns that are specified. The general form of the -binning specification is: -- - [bin{bijrd} Xcol=min:max:binsize, Ycol= ..., Zcol=..., Tcol=...; weight] -- -in which up to 4 columns, each corresponding to an axis of the image, -are listed. The column names are case insensitive, and the column -number may be given instead of the name, preceded by a pound sign -(e.g., [bin \#4=1:512]). If the column name is not specified, then -CFITSIO will first try to use the 'preferred column' as specified by -the CPREF keyword if it exists (e.g., 'CPREF = 'DETX,DETY'), otherwise -column names 'X', 'Y', 'Z', and 'T' will be assumed for each of the 4 -axes, respectively. In cases where the column name could be confused -with an arithmetic expression, enclose the column name in parentheses to -force the name to be interpreted literally. - -Each column name may be followed by an equals sign and then the lower -and upper range of the histogram, and the size of the histogram bins, -separated by colons. Spaces are allowed before and after the equals -sign but not within the 'min:max:binsize' string. The min, max and -binsize values may be integer or floating point numbers, or they may be -the names of keywords in the header of the table. If the latter, then -the value of that keyword is substituted into the expression. - -Default values for the min, max and binsize quantities will be -used if not explicitly given in the binning expression as shown -in these examples: -- - [bin x = :512:2] - use default minimum value - [bin x = 1::2] - use default maximum value - [bin x = 1:512] - use default bin size - [bin x = 1:] - use default maximum value and bin size - [bin x = :512] - use default minimum value and bin size - [bin x = 2] - use default minimum and maximum values - [bin x] - use default minimum, maximum and bin size - [bin 4] - default 2-D image, bin size = 4 in both axes - [bin] - default 2-D image -- -CFITSIO will use the value of the TLMINn, TLMAXn, and TDBINn keywords, -if they exist, for the default min, max, and binsize, respectively. If -they do not exist then CFITSIO will use the actual minimum and maximum -values in the column for the histogram min and max values. The default -binsize will be set to 1, or (max - min) / 10., whichever is smaller, -so that the histogram will have at least 10 bins along each axis. - -A shortcut notation is allowed if all the columns/axes have the same -binning specification. In this case all the column names may be listed -within parentheses, followed by the (single) binning specification, as -in: -- - [bin (X,Y)=1:512:2] - [bin (X,Y) = 5] -- - -The optional weighting factor is the last item in the binning specifier -and, if present, is separated from the list of columns by a -semi-colon. As the histogram is accumulated, this weight is used to -incremented the value of the appropriated bin in the histogram. If the -weighting factor is not specified, then the default weight = 1 is -assumed. The weighting factor may be a constant integer or floating -point number, or the name of a keyword containing the weighting value. -Or the weighting factor may be the name of a table column in which case -the value in that column, on a row by row basis, will be used. - -In some cases, the column or keyword may give the reciprocal of the -actual weight value that is needed. In this case, precede the weight -keyword or column name by a slash '/' to tell CFITSIO to use the -reciprocal of the value when constructing the histogram. - -For complex or commonly used histograms, one can also place its -description into a text file and import it into the binning -specification using the syntax '[bin @filename.txt]'. The file's -contents can extend over multiple lines, although it must still -conform to the no-spaces rule for the min:max:binsize syntax and each -axis specification must still be comma-separated. Any lines in the -external text file that begin with 2 slash characters ('//') will be -ignored and may be used to add comments into the file. - - Examples: - -- - [bini detx, dety] - 2-D, 16-bit integer histogram - of DETX and DETY columns, using - default values for the histogram - range and binsize - - [bin (detx, dety)=16; /exposure] - 2-D, 32-bit real histogram of DETX - and DETY columns with a bin size = 16 - in both axes. The histogram values - are divided by the EXPOSURE keyword - value. - - [bin time=TSTART:TSTOP:0.1] - 1-D lightcurve, range determined by - the TSTART and TSTOP keywords, - with 0.1 unit size bins. - - [bin pha, time=8000.:8100.:0.1] - 2-D image using default binning - of the PHA column for the X axis, - and 1000 bins in the range - 8000. to 8100. for the Y axis. - - [bin @binFilter.txt] - Use the contents of the text file - binFilter.txt for the binning - specifications. - -- - - -*V. Template Files - -When a new FITS file is created with a call to fits\_create\_file, the -name of a template file may be supplied in parentheses immediately -following the name of the new file to be created. This template is -used to define the structure of one or more HDUs in the new file. The -template file may be another FITS file, in which case the newly created -file will have exactly the same keywords in each HDU as in the template -FITS file, but all the data units will be filled with zeros. The -template file may also be an ASCII text file, where each line (in -general) describes one FITS keyword record. The format of the ASCII -template file is described in the following sections. - -**A Detailed Template Line Format - -The format of each ASCII template line closely follows the format of a -FITS keyword record: -- - KEYWORD = KEYVALUE / COMMENT -- -except that free format may be used (e.g., the equals sign may appear -at any position in the line) and TAB characters are allowed and are -treated the same as space characters. The KEYVALUE and COMMENT fields -are optional. The equals sign character is also optional, but it is -recommended that it be included for clarity. Any template line that -begins with the pound '\#' character is ignored by the template parser -and may be use to insert comments into the template file itself. - -The KEYWORD name field is limited to 8 characters in length and only -the letters A-Z, digits 0-9, and the hyphen and underscore characters -may be used, without any embedded spaces. Lowercase letters in the -template keyword name will be converted to uppercase. Leading spaces -in the template line preceding the keyword name are generally ignored, -except if the first 8 characters of a template line are all blank, then -the entire line is treated as a FITS comment keyword (with a blank -keyword name) and is copied verbatim into the FITS header. - -The KEYVALUE field may have any allowed FITS data type: character -string, logical, integer, real, complex integer, or complex real. Integer -values must be within the allowed range of a 'signed long' variable; -some C compilers only suppport 4-byte long integers with a range -from -2147483648 to +2147483647, whereas other C compilers support 8-byte -integers with a range of plus or minus 2**63. - -The character string values need not be enclosed in single quote characters -unless they are necessary to distinguish the string from a different -data type (e.g. 2.0 is a real but '2.0' is a string). The keyword has -an undefined (null) value if the template record only contains blanks -following the "=" or between the "=" and the "/" comment field -delimiter. - -String keyword values longer than 68 characters (the maximum length -that will fit in a single FITS keyword record) are permitted using the -CFITSIO long string convention. They can either be specified as a -single long line in the template, or by using multiple lines where the -continuing lines contain the 'CONTINUE' keyword, as in this example: -- - LONGKEY = 'This is a long string value that is contin&' - CONTINUE 'ued over 2 records' / comment field goes here -- -The format of template lines with CONTINUE keyword is very strict: 3 -spaces must follow CONTINUE and the rest of the line is copied verbatim -to the FITS file. - -The start of the optional COMMENT field must be preceded by "/", which -is used to separate it from the keyword value field. Exceptions are if -the KEYWORD name field contains COMMENT, HISTORY, CONTINUE, or if the -first 8 characters of the template line are blanks. - -More than one Header-Data Unit (HDU) may be defined in the template -file. The start of an HDU definition is denoted with a SIMPLE or -XTENSION template line: - -1) SIMPLE begins a Primary HDU definition. SIMPLE may only appear as -the first keyword in the template file. If the template file begins -with XTENSION instead of SIMPLE, then a default empty Primary HDU is -created, and the template is then assumed to define the keywords -starting with the first extension following the Primary HDU. - -2) XTENSION marks the beginning of a new extension HDU definition. The -previous HDU will be closed at this point and processing of the next -extension begins. - -**B Auto-indexing of Keywords - -If a template keyword name ends with a "\#" character, it is said to be -'auto-indexed'. Each "\#" character will be replaced by the current -integer index value, which gets reset = 1 at the start of each new HDU -in the file (or 7 in the special case of a GROUP definition). The -FIRST indexed keyword in each template HDU definition is used as the -'incrementor'; each subsequent occurrence of this SAME keyword will -cause the index value to be incremented. This behavior can be rather -subtle, as illustrated in the following examples in which the TTYPE -keyword is the incrementor in both cases: -- - TTYPE# = TIME - TFORM# = 1D - TTYPE# = RATE - TFORM# = 1E -- -will create TTYPE1, TFORM1, TTYPE2, and TFORM2 keywords. But if the -template looks like, -- - TTYPE# = TIME - TTYPE# = RATE - TFORM# = 1D - TFORM# = 1E -- -this results in a FITS files with TTYPE1, TTYPE2, TFORM2, and TFORM2, -which is probably not what was intended! - -**C Template Parser Directives - -In addition to the template lines which define individual keywords, the -template parser recognizes 3 special directives which are each preceded -by the backslash character: \verb+ \include, \group+, and \verb+ \end+. - -The 'include' directive must be followed by a filename. It forces the -parser to temporarily stop reading the current template file and begin -reading the include file. Once the parser reaches the end of the -include file it continues parsing the current template file. Include -files can be nested, and HDU definitions can span multiple template -files. - -The start of a GROUP definition is denoted with the 'group' directive, -and the end of a GROUP definition is denoted with the 'end' directive. -Each GROUP contains 0 or more member blocks (HDUs or GROUPs). Member -blocks of type GROUP can contain their own member blocks. The GROUP -definition itself occupies one FITS file HDU of special type (GROUP -HDU), so if a template specifies 1 group with 1 member HDU like: -- -\group -grpdescr = 'demo' -xtension bintable -# this bintable has 0 cols, 0 rows -\end -- -then the parser creates a FITS file with 3 HDUs : -- -1) dummy PHDU -2) GROUP HDU (has 1 member, which is bintable in HDU number 3) -3) bintable (member of GROUP in HDU number 2) -- -Technically speaking, the GROUP HDU is a BINTABLE with 6 columns. Applications -can define additional columns in a GROUP HDU using TFORMn and TTYPEn -(where n is 7, 8, ....) keywords or their auto-indexing equivalents. - -For a more complicated example of a template file using the group directives, -look at the sample.tpl file that is included in the CFITSIO distribution. - -**D Formal Template Syntax - -The template syntax can formally be defined as follows: -- - TEMPLATE = BLOCK [ BLOCK ... ] - - BLOCK = { HDU | GROUP } - - GROUP = \GROUP [ BLOCK ... ] \END - - HDU = XTENSION [ LINE ... ] { XTENSION | \GROUP | \END | EOF } - - LINE = [ KEYWORD [ = ] ] [ VALUE ] [ / COMMENT ] - - X ... - X can be present 1 or more times - { X | Y } - X or Y - [ X ] - X is optional -- - -At the topmost level, the template defines 1 or more template blocks. Blocks -can be either HDU (Header Data Unit) or a GROUP. For each block the parser -creates 1 (or more for GROUPs) FITS file HDUs. - - -**E Errors - -In general the fits\_execute\_template() function tries to be as atomic -as possible, so either everything is done or nothing is done. If an -error occurs during parsing of the template, fits\_execute\_template() -will (try to) delete the top level BLOCK (with all its children if any) -in which the error occurred, then it will stop reading the template file -and it will return with an error. - -**F Examples - -1. This template file will create a 200 x 300 pixel image, with 4-byte -integer pixel values, in the primary HDU: -- - SIMPLE = T - BITPIX = 32 - NAXIS = 2 / number of dimensions - NAXIS1 = 100 / length of first axis - NAXIS2 = 200 / length of second axis - OBJECT = NGC 253 / name of observed object -- -The allowed values of BITPIX are 8, 16, 32, -32, or -64, -representing, respectively, 8-bit integer, 16-bit integer, 32-bit -integer, 32-bit floating point, or 64 bit floating point pixels. - -2. To create a FITS table, the template first needs to include -XTENSION = TABLE or BINTABLE to define whether it is an ASCII or binary -table, and NAXIS2 to define the number of rows in the table. Two -template lines are then needed to define the name (TTYPEn) and FITS data -format (TFORMn) of the columns, as in this example: -- - xtension = bintable - naxis2 = 40 - ttype# = Name - tform# = 10a - ttype# = Npoints - tform# = j - ttype# = Rate - tunit# = counts/s - tform# = e -- -The above example defines a null primary array followed by a 40-row -binary table extension with 3 columns called 'Name', 'Npoints', and -'Rate', with data formats of '10A' (ASCII character string), '1J' -(integer) and '1E' (floating point), respectively. Note that the other -required FITS keywords (BITPIX, NAXIS, NAXIS1, PCOUNT, GCOUNT, TFIELDS, -and END) do not need to be explicitly defined in the template because -their values can be inferred from the other keywords in the template. -This example also illustrates that the templates are generally -case-insensitive (the keyword names and TFORMn values are converted to -upper-case in the FITS file) and that string keyword values generally -do not need to be enclosed in quotes. - - -*IX Summary of all FITSIO User-Interface Subroutines - - Error Status Routines page~\pageref{FTVERS} -- - FTVERS( > version) - FTGERR(status, > errtext) - FTGMSG( > errmsg) - FTRPRT (stream, > status) - FTPMSG(errmsg) - FTPMRK - FTCMSG - FTCMRK -- - FITS File Open and Close Subroutines: page~\pageref{FTOPEN} -- - FTOPEN(unit,filename,rwmode, > blocksize,status) - FTDKOPN(unit,filename,rwmode, > blocksize,status) - FTNOPN(unit,filename,rwmode, > status) - FTDOPN(unit,filename,rwmode, > status) - FTTOPN(unit,filename,rwmode, > status) - FTIOPN(unit,filename,rwmode, > status) - FTREOPEN(unit, > newunit, status) - FTINIT(unit,filename,blocksize, > status) - FTDKINIT(unit,filename,blocksize, > status) - FTTPLT(unit, filename, tplfilename, > status) - FTFLUS(unit, > status) - FTCLOS(unit, > status) - FTDELT(unit, > status) - FTGIOU( > iounit, status) - FTFIOU(iounit, > status) - CFITS2Unit(fitsfile *ptr) (C routine) - CUnit2FITS(int unit) (C routine) - FTEXTN(filename, > nhdu, status) - FTFLNM(unit, > filename, status) - FTFLMD(unit, > iomode, status) - FTURLT(unit, > urltype, status) - FTIURL(filename, > filetype, infile, outfile, extspec, filter, - binspec, colspec, status) - FTRTNM(filename, > rootname, status) - FTEXIST(filename, > exist, status) -- - HDU-Level Operations: page~\pageref{FTMAHD} -- - FTMAHD(unit,nhdu, > hdutype,status) - FTMRHD(unit,nmove, > hdutype,status) - FTGHDN(unit, > nhdu) - FTMNHD(unit, hdutype, extname, extver, > status) - FTGHDT(unit, > hdutype, status) - FTTHDU(unit, > hdunum, status) - FTCRHD(unit, > status) - FTIIMG(unit,bitpix,naxis,naxes, > status) - FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > - status) - FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) - FTRSIM(unit,bitpix,naxis,naxes,status) - FTDHDU(unit, > hdutype,status) - FTCPFL(iunit,ounit,previous, current, following, > status) - FTCOPY(iunit,ounit,morekeys, > status) - FTCPHD(inunit, outunit, > status) - FTCPDT(iunit,ounit, > status) -- - Subroutines to specify or modify the structure of the CHDU: page~\pageref{FTRDEF} -- - FTRDEF(unit, > status) (DEPRECATED) - FTPDEF(unit,bitpix,naxis,naxes,pcount,gcount, > status) (DEPRECATED) - FTADEF(unit,rowlen,tfields,tbcol,tform,nrows > status) (DEPRECATED) - FTBDEF(unit,tfields,tform,varidat,nrows > status) (DEPRECATED) - FTDDEF(unit,bytlen, > status) (DEPRECATED) - FTPTHP(unit,theap, > status) -- - Header Space and Position Subroutines: page~\pageref{FTHDEF} -- - FTHDEF(unit,morekeys, > status) - FTGHSP(iunit, > keysexist,keysadd,status) - FTGHPS(iunit, > keysexist,key_no,status) -- - Read or Write Standard Header Subroutines: page~\pageref{FTPHPR} -- - FTPHPS(unit,bitpix,naxis,naxes, > status) - FTPHPR(unit,simple,bitpix,naxis,naxes,pcount,gcount,extend, > status) - FTGHPR(unit,maxdim, > simple,bitpix,naxis,naxes,pcount,gcount,extend, - status) - FTPHTB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > - status) - FTGHTB(unit,maxdim, > rowlen,nrows,tfields,ttype,tbcol,tform,tunit, - extname,status) - FTPHBN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) - FTGHBN(unit,maxdim, > nrows,tfields,ttype,tform,tunit,extname,varidat, - status) -- - Write Keyword Subroutines: page~\pageref{FTPREC} -- - FTPREC(unit,card, > status) - FTPCOM(unit,comment, > status) - FTPHIS(unit,history, > status) - FTPDAT(unit, > status) - FTPKY[JKLS](unit,keyword,keyval,comment, > status) - FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - FTPKLS(unit,keyword,keyval,comment, > status) - FTPLSW(unit, > status) - FTPKYU(unit,keyword,comment, > status) - FTPKN[JKLS](unit,keyroot,startno,no_keys,keyvals,comments, > status) - FTPKN[EDFG](unit,keyroot,startno,no_keys,keyvals,decimals,comments, > - status) - FTCPKYinunit, outunit, innum, outnum, keyroot, > status) - FTPKYT(unit,keyword,intval,dblval,comment, > status) - FTPKTP(unit, filename, > status) - FTPUNT(unit,keyword,units, > status) -- - Insert Keyword Subroutines: page~\pageref{FTIREC} -- - FTIREC(unit,key_no,card, > status) - FTIKY[JKLS](unit,keyword,keyval,comment, > status) - FTIKLS(unit,keyword,keyval,comment, > status) - FTIKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - FTIKYU(unit,keyword,comment, > status) -- - Read Keyword Subroutines: page~\pageref{FTGREC} -- - FTGREC(unit,key_no, > card,status) - FTGKYN(unit,key_no, > keyword,value,comment,status) - FTGCRD(unit,keyword, > card,status) - FTGNXK(unit,inclist,ninc,exclist,nexc, > card,status) - FTGKEY(unit,keyword, > value,comment,status) - FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) - FTGKSL(unit,keyword, > length,status) - FTGSKY(unit,keyword,firstchar,maxchar,> keyval,length,comment,status) - FTGKN[EDJKLS](unit,keyroot,startno,max_keys, > keyvals,nfound,status) - FTGKYT(unit,keyword, > intval,dblval,comment,status) - FTGUNT(unit,keyword, > units,status) -- - Modify Keyword Subroutines: page~\pageref{FTMREC} -- - FTMREC(unit,key_no,card, > status) - FTMCRD(unit,keyword,card, > status) - FTMNAM(unit,oldkey,keyword, > status) - FTMCOM(unit,keyword,comment, > status) - FTMKY[JKLS](unit,keyword,keyval,comment, > status) - FTMKLS(unit,keyword,keyval,comment, > status) - FTMKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - FTMKYU(unit,keyword,comment, > status) -- - Update Keyword Subroutines: page~\pageref{FTUCRD} -- - FTUCRD(unit,keyword,card, > status) - FTUKY[JKLS](unit,keyword,keyval,comment, > status) - FTUKLS(unit,keyword,keyval,comment, > status) - FTUKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - FTUKYU(unit,keyword,comment, > status) -- - Delete Keyword Subroutines: page~\pageref{FTDREC} -- - FTDREC(unit,key_no, > status) - FTDKEY(unit,keyword, > status) -- - Define Data Scaling Parameters and Undefined Pixel Flags: page~\pageref{FTPSCL} -- - FTPSCL(unit,bscale,bzero, > status) - FTTSCL(unit,colnum,tscal,tzero, > status) - FTPNUL(unit,blank, > status) - FTSNUL(unit,colnum,snull > status) - FTTNUL(unit,colnum,tnull > status) -- - FITS Primary Array or IMAGE Extension I/O Subroutines: page~\pageref{FTPPR} -- - FTGIDT(unit, > bitpix,status) - FTGIET(unit, > bitpix,status) - FTGIDM(unit, > naxis,status) - FTGISZ(unit, maxdim, > naxes,status) - FTGIPR(unit, maxdim, > bitpix,naxis,naxes,status) - FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) - FTPPN[BIJKED](unit,group,fpixel,nelements,values,nullval > status) - FTPPRU(unit,group,fpixel,nelements, > status) - FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) - FTGPF[BIJKED](unit,group,fpixel,nelements, > values,flagvals,anyf,status) - FTPGP[BIJKED](unit,group,fparm,nparm,values, > status) - FTGGP[BIJKED](unit,group,fparm,nparm, > values,status) - FTP2D[BIJKED](unit,group,dim1,naxis1,naxis2,image, > status) - FTP3D[BIJKED](unit,group,dim1,dim2,naxis1,naxis2,naxis3,cube, > status) - FTG2D[BIJKED](unit,group,nullval,dim1,naxis1,naxis2, > image,anyf,status) - FTG3D[BIJKED](unit,group,nullval,dim1,dim2,naxis1,naxis2,naxis3, > - cube,anyf,status) - FTPSS[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,array, > status) - FTGSV[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs,nullval, > - array,anyf,status) - FTGSF[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs, > - array,flagvals,anyf,status) -- - Table Column Information Subroutines: page~\pageref{FTGCNO} -- - FTGNRW(unit, > nrows, status) - FTGNCL(unit, > ncols, status) - FTGCNO(unit,casesen,coltemplate, > colnum,status) - FTGCNN(unit,casesen,coltemplate, > colnam,colnum,status) - FTGTCL(unit,colnum, > datacode,repeat,width,status) - FTEQTY(unit,colnum, > datacode,repeat,width,status) - FTGCDW(unit,colnum, > dispwidth,status) - FTGACL(unit,colnum, > - ttype,tbcol,tunit,tform,tscal,tzero,snull,tdisp,status) - FTGBCL(unit,colnum, > - ttype,tunit,datatype,repeat,tscal,tzero,tnull,tdisp,status) - FTPTDM(unit,colnum,naxis,naxes, > status) - FTGTDM(unit,colnum,maxdim, > naxis,naxes,status) - FTDTDM(unit,tdimstr,colnum,maxdim, > naxis,naxes, status) - FTGRSZ(unit, > nrows,status) -- - Low-Level Table Access Subroutines: page~\pageref{FTGTBS} -- - FTGTBS(unit,frow,startchar,nchars, > string,status) - FTPTBS(unit,frow,startchar,nchars,string, > status) - FTGTBB(unit,frow,startchar,nchars, > array,status) - FTPTBB(unit,frow,startchar,nchars,array, > status) -- - Edit Rows or Columns page~\pageref{FTIROW} -- - FTIROW(unit,frow,nrows, > status) - FTDROW(unit,frow,nrows, > status) - FTDRRG(unit,rowrange, > status) - FTDRWS(unit,rowlist,nrows, > status) - FTICOL(unit,colnum,ttype,tform, > status) - FTICLS(unit,colnum,ncols,ttype,tform, > status) - FTMVEC(unit,colnum,newveclen, > status) - FTDCOL(unit,colnum, > status) - FTCPCL(inunit,outunit,incolnum,outcolnum,createcol, > status); -- - Read and Write Column Data Routines page~\pageref{FTPCLS} -- - FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) - FTPCN[BIJKED](unit,colnum,frow,felem,nelements,values,nullval > status) - FTPCLX(unit,colnum,frow,fbit,nbit,lray, > status) - FTPCLU(unit,colnum,frow,felem,nelements, > status) - FTGCL(unit,colnum,frow,felem,nelements, > values,status) - FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > - values,anyf,status) - FTGCF[SLBIJKEDCM](unit,colnum,frow,felem,nelements, > - values,flagvals,anyf,status) - FTGSV[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs,nullval, > - array,anyf,status) - FTGSF[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs, > - array,flagvals,anyf,status) - FTGCX(unit,colnum,frow,fbit,nbit, > lray,status) - FTGCX[IJD](unit,colnum,frow,nrows,fbit,nbit, > array,status) - FTGDES(unit,colnum,rownum, > nelements,offset,status) - FTPDES(unit,colnum,rownum,nelements,offset, > status) -- - Row Selection and Calculator Routines: page~\pageref{FTFROW} -- - FTFROW(unit,expr,firstrow, nrows, > n_good_rows, row_status, status) - FTFFRW(unit, expr, > rownum, status) - FTSROW(inunit, outunit, expr, > status ) - FTCROW(unit,datatype,expr,firstrow,nelements,nulval, > - array,anynul,status) - FTCALC(inunit, expr, outunit, parName, parInfo, > status) - FTCALC_RNG(inunit, expr, outunit, parName, parInfo, - nranges, firstrow, lastrow, > status) - FTTEXP(unit, expr, > datatype, nelem, naxis, naxes, status) -- - Celestial Coordinate System Subroutines: page~\pageref{FTGICS} -- - FTGICS(unit, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) - FTGTCS(unit,xcol,ycol, > - xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) - FTWLDP(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, - coordtype, > xpos,ypos,status) - FTXYPX(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, - coordtype, > xpix,ypix,status) -- - File Checksum Subroutines: page~\pageref{FTPCKS} -- - FTPCKS(unit, > status) - FTUCKS(unit, > status) - FTVCKS(unit, > dataok,hduok,status) - FTGCKS(unit, > datasum,hdusum,status) - FTESUM(sum,complement, > checksum) - FTDSUM(checksum,complement, > sum) - -- - Time and Date Utility Subroutines: page~\pageref{FTGSDT} -- - FTGSDT( > day, month, year, status ) - FTGSTM(> datestr, timeref, status) - FTDT2S( year, month, day, > datestr, status) - FTTM2S( year, month, day, hour, minute, second, decimals, - > datestr, status) - FTS2DT(datestr, > year, month, day, status) - FTS2TM(datestr, > year, month, day, hour, minute, second, status) -- - General Utility Subroutines: page~\pageref{FTGHAD} -- - FTGHAD(unit, > curaddr,nextaddr) - FTUPCH(string) - FTCMPS(str_template,string,casesen, > match,exact) - FTTKEY(keyword, > status) - FTTREC(card, > status) - FTNCHK(unit, > status) - FTGKNM(unit, > keyword, keylength, status) - FTMKKY(keyword, value,comment, > card, status) - FTPSVC(card, > value,comment,status) - FTKEYN(keyroot,seq_no, > keyword,status) - FTNKEY(seq_no,keyroot, > keyword,status) - FTDTYP(value, > dtype,status) - class = FTGKCL(card) - FTASFM(tform, > datacode,width,decimals,status) - FTBNFM(tform, > datacode,repeat,width,status) - FTGABC(tfields,tform,space, > rowlen,tbcol,status) - FTGTHD(template, > card,hdtype,status) - FTRWRG(rowlist, maxrows, maxranges, > numranges, rangemin, - rangemax, status) -- - -*X. Parameter Definitions -- -anyf - (logical) set to TRUE if any of the returned data values are undefined -array - (any datatype except character) array of bytes to be read or written. -bitpix - (integer) bits per pixel: 8, 16, 32, -32, or -64 -blank - (integer) value used for undefined pixels in integer primary array -blank - (integer*8) value used for undefined pixels in integer primary array -blocksize - (integer) 2880-byte logical record blocking factor - (if 0 < blocksize < 11) or the actual block size in bytes - (if 10 < blocksize < 28800). As of version 3.3 of FITSIO, - blocksizes greater than 2880 are no longer supported. -bscale - (double precision) scaling factor for the primary array -bytlen - (integer) length of the data unit, in bytes -bzero - (double precision) zero point for primary array scaling -card - (character*80) header record to be read or written -casesen - (logical) will string matching be case sensitive? -checksum - (character*16) encoded checksum string -colname - (character) ASCII name of the column -colnum - (integer) number of the column (first column = 1) -coltemplate - (character) template string to be matched to column names -comment - (character) the keyword comment field -comments - (character array) keyword comment fields -compid - (integer) the type of computer that the program is running on -complement - (logical) should the checksum be complemented? -coordtype - (character) type of coordinate projection (-SIN, -TAN, -ARC, - -NCP, -GLS, -MER, or -AIT) -cube - 3D data cube of the appropriate datatype -curaddr - (integer) starting address (in bytes) of the CHDU -current - (integer) if not equal to 0, copy the current HDU -datacode - (integer) symbolic code of the binary table column datatype -dataok - (integer) was the data unit verification successful (=1) or - not (= -1). Equals zero if the DATASUM keyword is not present. -datasum - (double precision) 32-bit 1's complement checksum for the data unit -datatype - (character) datatype (format) of the binary table column -datestr - (string) FITS date/time string: 'YYYY-MM-DDThh:mm:ss.ddd', - 'YYYY-MM-dd', or 'dd/mm/yy' -day - (integer) current day of the month -dblval - (double precision) fractional part of the keyword value -decimals - (integer) number of decimal places to be displayed -dim1 - (integer) actual size of the first dimension of the image or cube array -dim2 - (integer) actual size of the second dimension of the cube array -dispwidth - (integer) - the display width (length of string) for a column -dtype - (character) datatype of the keyword ('C', 'L', 'I', or 'F') - C = character string - L = logical - I = integer - F = floating point number -errmsg - (character*80) oldest error message on the internal stack -errtext - (character*30) descriptive error message corresponding to error number -casesen - (logical) true if column name matching is case sensitive -exact - (logical) do the strings match exactly, or were wildcards used? -exclist (character array) list of names to be excluded from search -exists - flag indicating whether the file or compressed file exists on disk -extend - (logical) true if there may be extensions following the primary data -extname - (character) value of the EXTNAME keyword (if not blank) -fbit - (integer) first bit in the field to be read or written -felem - (integer) first pixel of the element vector (ignored for ASCII tables) -filename - (character) name of the FITS file -flagvals - (logical array) True if corresponding data element is undefined -following - (integer) if not equal to 0, copy all following HDUs in the input file -fparm - (integer) sequence number of the first group parameter to read or write -fpixel - (integer) the first pixel position -fpixels - (integer array) the first included pixel in each dimension -frow - (integer) beginning row number (first row of table = 1) -frowll - (integer*8) beginning row number (first row of table = 1) -gcount - (integer) value of the GCOUNT keyword (usually = 1) -group - (integer) sequence number of the data group (=0 for non-grouped data) -hdtype - (integer) header record type: -1=delete; 0=append or replace; - 1=append; 2=this is the END keyword -hduok - (integer) was the HDU verification successful (=1) or - not (= -1). Equals zero if the CHECKSUM keyword is not present. -hdusum - (double precision) 32 bit 1's complement checksum for the entire CHDU -hdutype - (integer) type of HDU: 0 = primary array or IMAGE, 1 = ASCII table, - 2 = binary table, -1 = any HDU type or unknown type -history - (character) the HISTORY keyword comment string -hour - (integer) hour from 0 - 23 -image - 2D image of the appropriate datatype -inclist (character array) list of names to be included in search -incs - (integer array) sampling interval for pixels in each FITS dimension -intval - (integer) integer part of the keyword value -iounit - (integer) value of an unused I/O unit number -iunit - (integer) logical unit number associated with the input FITS file, 1-300 -key_no - (integer) sequence number (starting with 1) of the keyword record -keylength - (integer) length of the keyword name -keyroot - (character) root string for the keyword name -keysadd -(integer) number of new keyword records which can fit in the CHU -keysexist - (integer) number of existing keyword records in the CHU -keyval - value of the keyword in the appropriate datatype -keyvals - (array) value of the keywords in the appropriate datatype -keyword - (character*8) name of a keyword -lray - (logical array) array of logical values corresponding to the bit array -lpixels - (integer array) the last included pixel in each dimension -match - (logical) do the 2 strings match? -maxdim - (integer) dimensioned size of the NAXES, TTYPE, TFORM or TUNIT arrays -max_keys - (integer) maximum number of keywords to search for -minute - (integer) minute of an hour (0 - 59) -month - (integer) current month of the year (1 - 12) -morekeys - (integer) will leave space in the header for this many more keywords -naxes - (integer array) size of each dimension in the FITS array -naxesll - (integer*8 array) size of each dimension in the FITS array -naxis - (integer) number of dimensions in the FITS array -naxis1 - (integer) length of the X/first axis of the FITS array -naxis2 - (integer) length of the Y/second axis of the FITS array -naxis3 - (integer) length of the Z/third axis of the FITS array -nbit - (integer) number of bits in the field to read or write -nchars - (integer) number of characters to read and return -ncols - (integer) number of columns -nelements - (integer) number of data elements to read or write -nelementsll - (integer*8) number of data elements to read or write -nexc (integer) number of names in the exclusion list (may = 0) -nhdu - (integer) absolute number of the HDU (1st HDU = 1) -ninc (integer) number of names in the inclusion list -nmove - (integer) number of HDUs to move (+ or -), relative to current position -nfound - (integer) number of keywords found (highest keyword number) -no_keys - (integer) number of keywords to write in the sequence -nparm - (integer) number of group parameters to read or write -nrows - (integer) number of rows in the table -nrowsll - (integer*8) number of rows in the table -nullval - value to represent undefined pixels, of the appropriate datatype -nextaddr - (integer) starting address (in bytes) of the HDU following the CHDU -offset - (integer) byte offset in the heap to the first element of the array -offsetll - (integer*8) byte offset in the heap to the first element of the array -oldkey - (character) old name of keyword to be modified -ounit - (integer) logical unit number associated with the output FITS file 1-300 -pcount - (integer) value of the PCOUNT keyword (usually = 0) -previous - (integer) if not equal to 0, copy all previous HDUs in the input file -repeat - (integer) length of element vector (e.g. 12J); ignored for ASCII table -rot - (double precision) celestial coordinate rotation angle (degrees) -rowlen - (integer) length of a table row, in characters or bytes -rowlenll - (integer*8) length of a table row, in characters or bytes -rowlist - (integer array) list of row numbers to be deleted in increasing order -rownum - (integer) number of the row (first row = 1) -rowrange- (string) list of rows or row ranges to be deleted -rwmode - (integer) file access mode: 0 = readonly, 1 = readwrite -second (double)- second within minute (0 - 60.9999999999) (leap second!) -seq_no - (integer) the sequence number to append to the keyword root name -simple - (logical) does the FITS file conform to all the FITS standards -snull - (character) value used to represent undefined values in ASCII table -space - (integer) number of blank spaces to leave between ASCII table columns -startchar - (integer) first character in the row to be read -startno - (integer) value of the first keyword sequence number (usually 1) -status - (integer) returned error status code (0 = OK) -str_template (character) template string to be matched to reference string -stream - (character) output stream for the report: either 'STDOUT' or 'STDERR' -string - (character) character string -sum - (double precision) 32 bit unsigned checksum value -tbcol - (integer array) column number of the first character in the field(s) -tdisp - (character) Fortran type display format for the table column -template-(character) template string for a FITS header record -tfields - (integer) number of fields (columns) in the table -tform - (character array) format of the column(s); allowed values are: - For ASCII tables: Iw, Aw, Fww.dd, Eww.dd, or Dww.dd - For binary tables: rL, rX, rB, rI, rJ, rA, rAw, rE, rD, rC, rM - where 'w'=width of the field, 'd'=no. of decimals, 'r'=repeat count - Note that the 'rAw' form is non-standard extension to the - TFORM keyword syntax that is not specifically defined in the - Binary Tables definition document. -theap - (integer) zero indexed byte offset of starting address of the heap - relative to the beginning of the binary table data -tnull - (integer) value used to represent undefined values in binary table -tnullll - (integer*8) value used to represent undefined values in binary table -ttype - (character array) label for table column(s) -tscal - (double precision) scaling factor for table column -tunit - (character array) physical unit for table column(s) -tzero - (double precision) scaling zero point for table column -unit - (integer) logical unit number associated with the FITS file (1-300) -units - (character) the keyword units string (e.g., 'km/s') -value - (character) the keyword value string -values - array of data values of the appropriate datatype -varidat - (integer) size in bytes of the 'variable length data area' - following the binary table data (usually = 0) -version - (real) current revision number of the library -width - (integer) width of the character string field -xcol - (integer) number of the column containing the X coordinate values -xinc - (double precision) X axis coordinate increment at reference pixel (deg) -xpix - (double precision) X axis pixel location -xpos - (double precision) X axis celestial coordinate (usually RA) (deg) -xrpix - (double precision) X axis reference pixel array location -xrval - (double precision) X axis coordinate value at the reference pixel (deg) -ycol - (integer) number of the column containing the X coordinate values -year - (integer) last 2 digits of the year (00 - 99) -yinc - (double precision) Y axis coordinate increment at reference pixel (deg) -ypix - (double precision) y axis pixel location -ypos - (double precision) y axis celestial coordinate (usually DEC) (deg) -yrpix - (double precision) Y axis reference pixel array location -yrval - (double precision) Y axis coordinate value at the reference pixel (deg) -- - -*XI. FITSIO Error Status Codes -- -Status codes in the range -99 to -999 and 1 to 999 are reserved for future -FITSIO use. - - 0 OK, no error -101 input and output files are the same -103 too many FITS files open at once; all internal buffers full -104 error opening existing file -105 error creating new FITS file; (does a file with this name already exist?) -106 error writing record to FITS file -107 end-of-file encountered while reading record from FITS file -108 error reading record from file -110 error closing FITS file -111 internal array dimensions exceeded -112 Cannot modify file with readonly access -113 Could not allocate memory -114 illegal logical unit number; must be between 1 - 300, inclusive -115 NULL input pointer to routine -116 error seeking position in file - -121 invalid URL prefix on file name -122 tried to register too many IO drivers -123 driver initialization failed -124 matching driver is not registered -125 failed to parse input file URL -126 parse error in range list - -151 bad argument in shared memory driver -152 null pointer passed as an argument -153 no more free shared memory handles -154 shared memory driver is not initialized -155 IPC error returned by a system call -156 no memory in shared memory driver -157 resource deadlock would occur -158 attempt to open/create lock file failed -159 shared memory block cannot be resized at the moment - - -201 header not empty; can't write required keywords -202 specified keyword name was not found in the header -203 specified header record number is out of bounds -204 keyword value field is blank -205 keyword value string is missing the closing quote character -206 illegal indexed keyword name (e.g. 'TFORM1000') -207 illegal character in keyword name or header record -208 keyword does not have expected name. Keyword out of sequence? -209 keyword does not have expected integer value -210 could not find the required END header keyword -211 illegal BITPIX keyword value -212 illegal NAXIS keyword value -213 illegal NAXISn keyword value: must be 0 or positive integer -214 illegal PCOUNT keyword value -215 illegal GCOUNT keyword value -216 illegal TFIELDS keyword value -217 negative ASCII or binary table width value (NAXIS1) -218 negative number of rows in ASCII or binary table (NAXIS2) -219 column name (TTYPE keyword) not found -220 illegal SIMPLE keyword value -221 could not find the required SIMPLE header keyword -222 could not find the required BITPIX header keyword -223 could not find the required NAXIS header keyword -224 could not find all the required NAXISn keywords in the header -225 could not find the required XTENSION header keyword -226 the CHDU is not an ASCII table extension -227 the CHDU is not a binary table extension -228 could not find the required PCOUNT header keyword -229 could not find the required GCOUNT header keyword -230 could not find the required TFIELDS header keyword -231 could not find all the required TBCOLn keywords in the header -232 could not find all the required TFORMn keywords in the header -233 the CHDU is not an IMAGE extension -234 illegal TBCOL keyword value; out of range -235 this operation only allowed for ASCII or BINARY table extension -236 column is too wide to fit within the specified width of the ASCII table -237 the specified column name template matched more than one column name -241 binary table row width is not equal to the sum of the field widths -251 unrecognizable type of FITS extension -252 unrecognizable FITS record -253 END keyword contains non-blank characters in columns 9-80 -254 Header fill area contains non-blank characters -255 Data fill area contains non-blank on non-zero values -261 unable to parse the TFORM keyword value string -262 unrecognizable TFORM datatype code -263 illegal TDIMn keyword value - -301 illegal HDU number; less than 1 or greater than internal buffer size -302 column number out of range (1 - 999) -304 attempt to move to negative file record number -306 attempted to read or write a negative number of bytes in the FITS file -307 illegal starting row number for table read or write operation -308 illegal starting element number for table read or write operation -309 attempted to read or write character string in non-character table column -310 attempted to read or write logical value in non-logical table column -311 illegal ASCII table TFORM format code for attempted operation -312 illegal binary table TFORM format code for attempted operation -314 value for undefined pixels has not been defined -317 attempted to read or write descriptor in a non-descriptor field -320 number of array dimensions out of range -321 first pixel number is greater than the last pixel number -322 attempt to set BSCALE or TSCALn scaling parameter = 0 -323 illegal axis length less than 1 - -340 NOT_GROUP_TABLE 340 Grouping function error -341 HDU_ALREADY_MEMBER -342 MEMBER_NOT_FOUND -343 GROUP_NOT_FOUND -344 BAD_GROUP_ID -345 TOO_MANY_HDUS_TRACKED -346 HDU_ALREADY_TRACKED -347 BAD_OPTION -348 IDENTICAL_POINTERS -349 BAD_GROUP_ATTACH -350 BAD_GROUP_DETACH - -360 NGP_NO_MEMORY malloc failed -361 NGP_READ_ERR read error from file -362 NGP_NUL_PTR null pointer passed as an argument. - Passing null pointer as a name of - template file raises this error -363 NGP_EMPTY_CURLINE line read seems to be empty (used - internally) -364 NGP_UNREAD_QUEUE_FULL cannot unread more then 1 line (or single - line twice) -365 NGP_INC_NESTING too deep include file nesting (infinite - loop, template includes itself ?) -366 NGP_ERR_FOPEN fopen() failed, cannot open template file -367 NGP_EOF end of file encountered and not expected -368 NGP_BAD_ARG bad arguments passed. Usually means - internal parser error. Should not happen -369 NGP_TOKEN_NOT_EXPECT token not expected here - -401 error attempting to convert an integer to a formatted character string -402 error attempting to convert a real value to a formatted character string -403 cannot convert a quoted string keyword to an integer -404 attempted to read a non-logical keyword value as a logical value -405 cannot convert a quoted string keyword to a real value -406 cannot convert a quoted string keyword to a double precision value -407 error attempting to read character string as an integer -408 error attempting to read character string as a real value -409 error attempting to read character string as a double precision value -410 bad keyword datatype code -411 illegal number of decimal places while formatting floating point value -412 numerical overflow during implicit datatype conversion -413 error compressing image -414 error uncompressing image -420 error in date or time conversion - -431 syntax error in parser expression -432 expression did not evaluate to desired type -433 vector result too large to return in array -434 data parser failed not sent an out column -435 bad data encounter while parsing column -436 parse error: output file not of proper type - -501 celestial angle too large for projection -502 bad celestial coordinate or pixel value -503 error in celestial coordinate calculation -504 unsupported type of celestial projection -505 required celestial coordinate keywords not found -506 approximate wcs keyword values were returned -- -\end{document} diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.pdf b/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.pdf deleted file mode 100644 index 1ca96a41c..000000000 Binary files a/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.pdf and /dev/null differ diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.ps b/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.ps deleted file mode 100644 index 9eea16699..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.ps +++ /dev/null @@ -1,11377 +0,0 @@ -%!PS-Adobe-2.0 -%%Creator: dvips(k) 5.96.1 Copyright 2007 Radical Eye Software -%%Title: fitsio.dvi -%%CreationDate: Mon Jun 13 15:51:07 2016 -%%Pages: 138 -%%PageOrder: Ascend -%%BoundingBox: 0 0 612 792 -%%DocumentFonts: CMBX12 CMR12 CMR10 CMBX10 CMSL10 CMTT10 CMSY10 CMMI10 -%%DocumentPaperSizes: Letter -%%EndComments -%DVIPSWebPage: (www.radicaleye.com) -%DVIPSCommandLine: dvips -o fitsio.ps fitsio.dvi -%DVIPSParameters: dpi=600 -%DVIPSSource: TeX output 2016.06.13:1550 -%%BeginProcSet: tex.pro 0 0 -%! -/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S -N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 -mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 -0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ -landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize -mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ -matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round -exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ -statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] -N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin -/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array -/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 -array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N -df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A -definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get -}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} -B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr -1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S -/BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy -setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask -restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn -/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put -}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ -bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A -mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ -SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ -userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X -1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 -index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N -/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ -/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) -(LaserWriter 16/600)]{A length product length le{A length product exch 0 -exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse -end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask -grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} -imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round -exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto -fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p -delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} -B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ -p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S -rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end - -%%EndProcSet -%%BeginProcSet: texps.pro 0 0 -%! -TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 -index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll -exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 -ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ -pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get -div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type -/nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end -definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup -sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll -mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ -exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} -forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def -end - -%%EndProcSet -%%BeginFont: CMMI10 -%!PS-AdobeFont-1.1: CMMI10 1.100 -%%CreationDate: 1996 Jul 23 07:53:57 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.100) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMMI10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle -14.04 def -/isFixedPitch false def -end readonly def -/FontName /CMMI10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 62 /greater put -readonly def -/FontBBox{-32 -250 1048 750}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE -3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B -532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 -B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B -986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE -D919C2DDD26BDC0D99398B9F4D03D5993DFC0930297866E1CD0A319B6B1FD958 -9E394A533A081C36D456A09920001A3D2199583EB9B84B4DEE08E3D12939E321 -990CD249827D9648574955F61BAAA11263A91B6C3D47A5190165B0C25ABF6D3E -6EC187E4B05182126BB0D0323D943170B795255260F9FD25F2248D04F45DFBFB -DEF7FF8B19BFEF637B210018AE02572B389B3F76282BEB29CC301905D388C721 -59616893E774413F48DE0B408BC66DCE3FE17CB9F84D205839D58014D6A88823 -D9320AE93AF96D97A02C4D5A2BB2B8C7925C4578003959C46E3CE1A2F0EAC4BF -8B9B325E46435BDE60BC54D72BC8ACB5C0A34413AC87045DC7B84646A324B808 -6FD8E34217213E131C3B1510415CE45420688ED9C1D27890EC68BD7C1235FAF9 -1DAB3A369DD2FC3BE5CF9655C7B7EDA7361D7E05E5831B6B8E2EEC542A7B38EE -03BE4BAC6079D038ACB3C7C916279764547C2D51976BABA94BA9866D79F13909 -95AA39B0F03103A07CBDF441B8C5669F729020AF284B7FF52A29C6255FCAACF1 -74109050FBA2602E72593FBCBFC26E726EE4AEF97B7632BC4F5F353B5C67FED2 -3EA752A4A57B8F7FEFF1D7341D895F0A3A0BE1D8E3391970457A967EFF84F6D8 -47750B1145B8CC5BD96EE7AA99DDC9E06939E383BDA41175233D58AD263EBF19 -AFC0E2F840512D321166547B306C592B8A01E1FA2564B9A26DAC14256414E4C8 -42616728D918C74D13C349F4186EC7B9708B86467425A6FDB3A396562F7EE4D8 -40B43621744CF8A23A6E532649B66C2A0002DD04F8F39618E4F572819DD34837 -B5A08E643FDCA1505AF6A1FA3DDFD1FA758013CAED8ACDDBBB334D664DFF5B53 -9560176676ABB71BBD0EE56B4CC492C0652750227CEC7B86E4740EB7B8775564 -332769DD30794E501BBB0E4E5CB665F3628E10B1137CC8BC5C0A64A310B5E27E -5FD6E3B04DA3914C15987E638A72790AF4073CE9CDBF6E3C749CB4DFF9C54951 -A58C386C54BC4E98B102B5E91E8567D2EEEF048F2CBD5D243701D20909290B4B -A3083F632D8552D42DEE0C69A4B14D8B15AA082DECC12B2ECAE6F663E6D09F81 -EE2979EF41FBF12C9D8BF23B77E0A20088EBD107C5BF9DD6F03FFC3AB65B69A7 -54953327E1D4AEF5A146273392BBDB321D4CC9A8FFFCFE5C515B466E21546CC7 -C6209E5A76F916B03DB98BC6CED334F33E7B373D42761696F5A876CA6F93F16E -15A07E2E102148CA4F62A99C -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMBX12 -%!PS-AdobeFont-1.1: CMBX12 1.0 -%%CreationDate: 1991 Aug 20 16:34:54 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMBX12) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Bold) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMBX12 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 11 /ff put -dup 12 /fi put -dup 39 /quoteright put -dup 40 /parenleft put -dup 41 /parenright put -dup 45 /hyphen put -dup 46 /period put -dup 47 /slash put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 56 /eight put -dup 57 /nine put -dup 58 /colon put -dup 65 /A put -dup 66 /B put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 72 /H put -dup 73 /I put -dup 75 /K put -dup 76 /L put -dup 77 /M put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 86 /V put -dup 87 /W put -dup 97 /a put -dup 98 /b put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 102 /f put -dup 103 /g put -dup 104 /h put -dup 105 /i put -dup 107 /k put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -dup 118 /v put -dup 119 /w put -dup 120 /x put -dup 121 /y put -dup 122 /z put -readonly def -/FontBBox{-53 -251 1139 750}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5F0364CD5660F74BEE96790DE35AFA90CCF712 -B1805DA88AE375A04D99598EADFC625BDC1F9C315B6CF28C9BD427F32C745C99 -AEBE70DAAED49EA45AF94F081934AA47894A370D698ABABDA4215500B190AF26 -7FCFB7DDA2BC68605A4EF61ECCA3D61C684B47FFB5887A3BEDE0B4D30E8EBABF -20980C23312618EB0EAF289B2924FF4A334B85D98FD68545FDADB47F991E7390 -B10EE86A46A5AF8866C010225024D5E5862D49DEB5D8ECCB95D94283C50A363D -68A49071445610F03CE3600945118A6BC0B3AA4593104E727261C68C4A47F809 -D77E4CF27B3681F6B6F3AC498E45361BF9E01FAF5527F5E3CC790D3084674B3E -26296F3E03321B5C555D2458578A89E72D3166A3C5D740B3ABB127CF420C316D -F957873DA04CF0DB25A73574A4DE2E4F2D5D4E8E0B430654CF7F341A1BDB3E26 -77C194764EAD58C585F49EF10843FE020F9FDFD9008D660DE50B9BD7A2A87299 -BC319E66D781101BB956E30643A19B93C8967E1AE4719F300BFE5866F0D6DA5E -C55E171A24D3B707EFA325D47F473764E99BC8B1108D815CF2ACADFA6C4663E8 -30855D673CE98AB78F5F829F7FA226AB57F07B3E7D4E7CE30ED3B7EB0D3035C5 -148DA8D9FA34483414FDA8E3DC9E6C479E3EEE9A11A0547FC9085FA4631AD19C -E936E0598E3197207FA7BB6E55CFD5EF72AEC12D9A9675241C7A71316B2E148D -E2A1732B3627109EA446CB320EBBE2E78281CDF0890E2E72B6711335857F1E23 -337C75E729701E93D5BEC0630CDC7F4E957233EC09F917E5CA703C7E93841598 -0E73843FC6619DE017C8473A6D1B2BE5142DEBA285B98FA1CC5E64D2ADB981E6 -472971848451A245DDF6AA3B8225E9AC8E4630B0FF32D679EC27ACAD85C6394E -A6F71023B660EE883D8B676837E9EBA4E42BA8F365433A900F1DC3A9F0E88A26 -30F40A9C74C8E7773BE601C0E245E7FC10C02939848C3D28D823057B3EA23EC9 -E2BFF7851FB65FB12A4318A21D2C88EF9245D4C7BF21C81C4FC4CE0149E96278 -48F7BF97A5C3691E6CE038033AF54DE91D320EABF2B2E98617FD4145BFE5EBBF -1A5634DA07B00257A51966FFC009CA416D37AD30F4BEE6D72AB64CB2D62466F0 -42D66D6D33EF9107272835EA9C1C8FA04562864BE684FD5F8E6DF19916FF8346 -F39F3E1FA2975B5CED24EB160FEF6149954F76C359E9D15A209EDD7445BB6303 -6AFF9E1373CDD50B93DB137F3896D282F5C04AF0AC84AA02D5421A73E3AFB735 -80EBE676C2870822BA89F4BA85034D6431BC4A44CC264DDD10EA146913E9063B -038BD787A659C6A88C42FD5FBC51234664A8A1621A38C73ACB7199592AA5EA84 -B78BB5DBA7CA43E30CA8D3957CFF478712556EEAB1990C97B9BAB47ADB75E327 -B361D3039A3629B09EB84CF814773858F1D354AD8D526E85EAFD50944CBCE042 -367D1153D7B4EC4DD597DB0F57379DD63304869DEA4FA008D411E30ECFD62E41 -29F51841A9E07E066F06BB4829F87B7722562686FB801D6690F73233053B2EEC -473B9899F284296BB634358A22DBF361C2A57C59438C429EFB04B80BE083E238 -A6749D6AAD1F17F318B880D26D230B86F80A99C27B87F7605DE40A0848543DE2 -4AF7D5BF61CA6B00FA156DBB9ABE7BB0EC79CE8FD5A2FC5BE17050F2A74E8905 -75A9982E12698B289E2213DAFAAE40DD22B424562D7417E8B82A5E3DDA814669 -D4CC949397B0DD2B0787016CB8FDFD09318719D7C47DB72E094C12C6DF3EDE88 -663D6357CE7BFE51FD4A93887F022E3A22DCBE39CA86E104CE54C05AA0B5E469 -0AB9DA29D19ED5E783225ECD1122BFFF5E4E63488FF215A9F555C190ECDAF130 -B34E6BFC66AB1F7D000CC09CA9872299E23EC9B0A8ED04135C982978B9D7C4E5 -F9C7968B540837CC667196C7B40F579E8258C8C7AC569AB787BB112C046D0068 -86AEC034183A3DE02FB82C2CD3E252746C012F2385493F59DDEFD5AA95A26C61 -BA64D85CE90339A0C19F538C6E0516513B9E7661505AB81F45AEA04618CEB379 -12F6BB94E2812F2B3C69BAFC9135B439D74C6A94C0317E1B2A2EA514536AA990 -7B94105AF7DA13148A807CB2F679DBDEE10B09BDCC8BDC7365166C910AA450C7 -4FD88CA8BB639F1BA53A4B108D2E1633C5DB38E64DF4881E0FC1118559A078E8 -52A0E2A87F98461EE7B0B56DFB6C3F340430E3D5C41C12141E4332951B4DF03A -6824E8CEEA4AE8AC9F51981184287EC2710E4A51DB5E09DCFF4DFCE6B82A0B5C -D2E658D38FA7B2854778650A78AF230E97A4C195865C404EC18A5FA99EA30FE8 -755EE5B11397D3CCAECD81EE3F3D1EE1A1B1FD6B669270912948134ECBA3D5B3 -011CD3286DD6729DBCFC9A8FC93356BC70A876AB636E5C8EFA89881D3A6E0592 -D4CDDBBD21A67033AB3354BA1333206874D2F7D0E571AAD845A96057F005F730 -C98EBDFB006EF8874CC386A0B611389F9CF5204C65AD951306B0E090BB287EF9 -CB7DB38F2A58E2ED6813F2138922E28FA44792E5C57A70C6152B4A6E73462F8C -869886D1E5718C85F1CD5E7EC4BD73C6A4E3218A7118D42CFE42BB83A6B72729 -0E096EA902F81330771203309DEA91A560B56DE63911EBB6147600BB9B6A5166 -A818B7B8CE58279E22D776B2CF423897110CFF24807319C84A2063CA464C7616 -8260B36124AFE08188795E334864712574CC3DE12C3F0962D51734A44289BFE2 -2525F5D641EF82F25C1EAEA56C621525EC86FB6D09D99941D18094B7D77719E0 -3957294DBF2D221A49807B44323098D816A21C8F1BB888BC1075E2D6FD770014 -829050B6F8E297853701C467BFE76C1E52E8AFD5AF67B3FAD5A608C23E925F0A -87E7F56B0D05F4D4276CE619190A983BB19417E280B53060AF777BCEA0D1F4D1 -B803687D9C2050D0B2EBF3EFCB9FE42E02AFFA5233A49D27550BF8B32B1A3A3D -A8F58FC0FEC58439D12CC87CEEBED10BB6D9BE84DDDA7FE7A7283D2639212CEE -2DA539DE06298BF452F896FE103A4BF864E5399C3F220FFFD82AF1975FCFA69B -8C9782842F016682EFAE7269A34FDC5ED188E3E6E24FAA0345D9558B19521D16 -9FB47306CD1D15F36C9386347FCC9906A5420F4F6E030B007DF4D311B8E102DA -A653AB0BA300D9467B092165B016C6F28E8D417E1B93A6A176329A67C5E0FF79 -167F9CD8E2EDD33D5B11348EC7BF4C88C3226377DBA6C4723CBE67A7118F3CBA -34EF78E08A4211C39205325D138840E3F3FAA9CCEE74569B8F59CCE7E7D35D3A -0999DB04EC83483BA245883D764A3CF556949BE4B121C6483ED26D192405EBFF -089A97C4BA9649916F1A922F48CD04B7338EABDAEADAC52F42CF48272EAB9192 -C17906F59CD98D5A54443BD474385AF6B51B9C14EA8AEA27AE3473DC12DE901B -42DC378872B001B2C929C54117E6EDAC6202BF1028AD2793FEA3620935539071 -9BA89FBFB98229EF30B0382D9D603BB451634BFD08901432F16B31C9245D3645 -28456E44DC8B6C9C052B9446107116AFCC2EC0F39F0CC7B5E146FD9E995594A2 -DDDE2BD3DDAE13B9659969623BDE57219731BD3893B63B77D5218B94FF535FAF -2595C30EB0A003B144461C8115C5EC93595B4FAC2BC0D084E326E1F2CD14AC0D -D9B4C1467961E2FFC04BD2DCDC1A16E9582653B1CECD98AEB6ABF1E88086FD2F -347774D628A4E70B6803EA481996C07D6D84661D003CF3C92D32791A06405C2D -BDDED14EA55744AA956D04CADD4B2F5A0FBA5D29CFC84CC54CBCA53B19FBB69B -6199174100938FC1E16E7EC73BF85B058E235E282B17116250CC9965706D80F4 -EAE76E2F7E96E901CE29AFBDE9CF9E19CC2432DE75B4E67DBB7BF62C6A3A0C4A -1800F457B745F18AAAACAB8DEA973869EFED9464631EA2CBE95F78133B4DA06D -394AB1CB50B6EED8E868AEA0EABDB783EFB7F0431A450D9C48492A04BFE3A0A7 -9BFDE3B9DB2235EE46EF0D3E754F95819B6FD407E974856C83228A3C2A076966 -02E3F0F2F27CAE5C820FCF3AC5FF38C715B3DC3CE9AC77FB13382D2B606F469F -768D1B82CE3D66F1AB552902B3BFC8E1B3A5A45D3C3D914D304070AAB6C49393 -028CD984C44C2D8DEDEB61AB45A4B2237A236C0D3088AAC5A7F89EDFF9A09639 -8B1887E2CB29D9E9B5630A45879069E58DA52E5603D026339E637D7B83E6550E -CBD4349FB018A01749E171C987C30F8C36651501653A4421869F04A9B8BF792F -41B8D1E9F9101B658EF726DE26BA616A20A667FE7B571F68FF3BC77B127EF315 -64D1D39C07799B45A40CA2D4FD81633368EC9654282A91B8F38066B3D781E8EF -3DCF9CB050096E84E8DE000568251ADFB56AB4AECF2D29BB47110D277E5A1634 -D2813F9239951645D505C53CA91481C2B0F9DB72CC4C3EBB12D2BEB7B4201C23 -BE8EFE99CCC6A0D520F6282F0876E6A69CF5ED38AAA9066196A9456C5DEC58F3 -341797EFFF3040BB65E2479165581DD67AD36EDF24DA29DE341106F258C5FEA2 -D538201FBB6C0C3A132487E01488FAF2EE5A61E7079547278DFA812C5D822454 -F5B0E67620BEBAED135E63C8A55B29F685CA3CCCCBA06E2AEEECBD92E29B985A -23B93078BF8A6F41125529C1C171D7A8C1AFD9017CC089570E45E873E74D7FEA -7193C263492D4A6E73C65531C324FEA1CF9C4EBB6E501562EAA0EC4DA6C5FF7C -49DAFA4DA93D9F35F06616002A66468D7ABF3B3CAFE293A7CE0D1034B971B063 -EF162C62E480D259E5AD6383DDCCB0F2CE0059E7E04681106CA6378D59F3EEE7 -0AF84F11FCB538E4155CEB05D48678FBADF22F99B9D6589629FAAA181F78BD79 -9D97F53E9FC10919970EF6CECCC6464540FB4A8EAD144B5662A4B0BAD31DEFA4 -9C1F280C18BBB0FB005896075E3F4C52C9F11A2C0DD60CFE581C771A72273053 -796AB48AD2500600E3355CE0C91E26DBF8C135C6B12FB3B2E89B9011CCAA3D2C -AF8E2F38BE8D2BD82966B0037DA0B64A955AFC5181D3F2DA0F4FAE47875B5D3B -ABCF48A2C3D1ADF69F5A3BB51D456B19085363318C3D371221A7319EDA644EA0 -C30EB56AF819CAE5DEA47A7495B463E388562FB76C94621CA7F0DF9FA6C080EC -9F8AFC21AAAEAE2359869EFEFC8BCC433B683EE1DBE927463CEB19CCBE08ACA5 -B925E88AB69BF8EB7A0781F57FADC2111659F9A480B8B4158806CDBFD950C4A7 -0D792235486658CF8A96B0FDA2EE36468788225B794AE541683D2F5568B1239B -2956E585AE96E5C0FEF1D632895B3A0E0FCC57EEDBAF40F395547F77D7F4F6D5 -23066F8B08FD44B1F26E89083C70FF24CE2AA2168AA8B09BDFD763286A243BC3 -0431A22C8CC88A524E2C3DB01F1B65A1540A8C2EF5CEA9303DFC3F3CDB20EA23 -600F870EC83EF9992A976ABA1D086EE4018DD3F7004301A7A431694DAAB46B29 -538000BA28F999C70C3F72C1DB5CD7B1A4FDE6A0A87BA98332EDD260D30CE677 -7176F2FE3D12C3434985AB6CC12AB6BD4872F5376AE6E6CA9C4871007D6DEF15 -6D15C96C0433ACFD3AD8DB22100ED3D696FFA7DEDDA0449A14F435E9868DC2CB -8C1306330A68C38FCC010442A51DDC47BBFC474BCBA5A404A5705A0812B1DDB6 -CDE7EFD4D833C7DB0D4C91561C7369AEF96E849D23FBC55429427FDAF7E2DEFD -18E2BA193293C0BF21F7241626E30573F2BB36C0BDF9A1065B2AE02DCE822156 -0AD58921ED46E65C40FE54C0F9C58AD8531536208F5A6F538836B74090AD8191 -486F29CED44DF9C4A547FDE7C40F833887845BDDCC68D84F2F445CD4D871FE87 -52681595A6D0DC3FE1E2B00C53AD686E866FEFC39F6C7FFCAFF8191C13F7598D -3EBDCD33CA548FE31C67AA26568BE071A4D5750F9246695A4184042DB2FB0680 -C0E1FF57CF2E9E360828CCE1C7F22D5CC921A995DBAE0D2469D4C5147D607923 -455D9390580E120416B814A310E5588A0D54160728CCE53712D266C090F7175D -96725CE1CF85B0E3772347D9DB0CB282F04A2CE1A1358675ADAB4F5504554189 -B141B5FA5BE5D2DD4FD88C91AE99E6504365853F95620C378657DBC98D06A4F0 -38DAC9CB25A11D8A9D224C9CAD1369245B4A8E19AA55523BA8402CF056FA7818 -DA762A53F9A2F02F17E23C97A38C14ECC34B985B1EABF9900698E122F11EB4AA -E5524C3DA713271DAB8969B693A7CBD313F28120C7A68F4B3037AC043C992D7E -F5829F11930CA70B580A161635228ECF20C5BA4D3B1587FD7A1D52C2530FAF7D -C2C9431C7B4521296D391A3436642230E0E5D74E6D5E94277373513DC443B09C -0BC80C1EA1F22A7F2F4CE3627E852B5A636DEC22ECE7FE76F53FFC41AAF1B490 -15E8060C6448F07997AE8D012B640630D72B11D77FBFF41F65B6EE2D70345A6D -E6137355349A55DEA19D1DF5551B54F1E2F57E85568954AF23B2CA6D60859F11 -2BCF6FB935BC106B9BBCD8E8DD551D82C7D348E03B71BD4E052686F1A0D59091 -EE647EC64FBF77F558358129B938993D0F75673B45F41D2EDE54FACD6DDEF68A -A8D55C257CEFC0E0D382C60A73C49DEC67AC68E5066749A1C00AE616A2C71A4E -14A95123F58FB1D940E2A0E51EFA67C2F2BDEFF85376D211DD8F15D43F2CCE7B -47B0CE25CEF1D450EFE17476BC3CFF661C1EFFC82E80E0A69FCCB25F39E51454 -E53912FF49EBFB3CD9593F6FAE81F1F0A9E167282286F8407F9F0023538D75E5 -76171E5A7005F053ECA82809C7073A1A480198BAE0085BA9BD1EF107D4324B24 -F96E24BB4FDD80B195546854618282F770631B5F3FEFDC035E6954AE76304038 -9ED525495644EA353E32F65140DEDEF41CD343B5333954D3A4C413BC3365B0B7 -3ED0DB1A27C60237A0E82407753C1F9817C4A0D7F07D328FE2216B34CB8A233D -FC5A420704C8F1D42B57E69424267E5BFA8C2AE65BA324262DDA2812D893050F -7D50D4487A5BBE53D7CF041DA6EF76A659DE8EE07DE413E940AC2160C994648A -6D0D0A59860B4080977C18CF6540B5F5B3B4DB52EE9CDE105D965E9FE5999208 -02CFC8639767B033A3EBC2C42066F6E7CE3B8D6E2F25030D14957F7FA8E59A7A -5685A8A8479545C373DE7778A5A65D7ED6139A2C8FADBE8AACD08D56C42D11E2 -CF01E2D78D4301556A8D7AFFF7642B10A36E93546EC8B2059870C472F5CD463C -DE1DBB211CFF689095891B9980D9C9438FF7EC687DA72C548502B5EA0FFDFEE8 -D982B934E7A9F4D62428FC6719894C0ED4B0040BBA5D0FCBD0E3D80F2E245513 -4C78489DB71F2EDF17CEF7784370D080B75122290F59D4B4CAA0484A809CAD27 -94FE9EDD79994079695C3DC4440C6B2FE4AB0129F2514EFFD8615425F7E74567 -D93EADD0FB68FD8C6B9E3C1275F4FD32B8CFF3D8D04B185E2D702E46289456E7 -F6A2A0D83DCF29862BD08AD7AF05E3380AEE207F44E5B8C11A89E954AE0BAB81 -C5A8D1449693A0E5AE02D0AC8D1BF1CD96DBA29A747CF41292027ED8C05DD325 -8B92300CFA2FD33F14CEE073F8CA93E33BB952B2E58E666B1E12CB5634136777 -6D155B1855064842120EF87ED8B1CB6C95D74EF97C0B85DE90E266DD14793F70 -27038C774A64E5757DE6FFFDE5CCB2BFA4B771BD7D02FCF0530E0768DB74FA39 -2BE1C80A37A77AAC1B4972AA0335A6E51787781D482D01CCE8CD8FC732BFB1CD -69E5BF80E44F7F484277E5D8B9611B8614ABB9C8865F26DA08108D355EA7B451 -2364F41F4EA9BA074CFD14377B092F4274F18F42B30C83ACFAF87513E8CC9716 -7ADFE45917E3B9D034F4ECE1455318BA74C68CD534B7DA3E3C1C94A10E7F5738 -46EF5ABAA7F58C0CB25A1F78F8FCF83DC2FA4F74B7F01E3141E1886C457FD285 -A44A1A57E968358BC29CAC2BC79CD14FEF92F522C9873ECFE82A01BC4191BAA4 -5D5212A7AFACEF600F738F4E6C691BD5D8D6F494187F43D42B1E876E6B12A02E -8357B376CA901EF9945D7703E28549C291731B78BC185AB2D3EA810CAB3A500E -2D2DF7934A616B3B0705F0928D97A742DB11392C51901CAB772C44113F1A5873 -54C74B49EA48DE55089AFFB75B288185955DFEF25610BEFF0789A40381A1ADFB -95628B44B810062EF1AE97D6101B13B020276040FD886422F69A92254B222986 -500384843D82F4A706D5160CE4E35556253C2B73B539D101F166873974CB1819 -26D751F2E4DDA3D93FC7128C2515A75C676ACCAF8C07E2863951ACED319EB268 -87C5802B7C54317A414BF9DA26EA1B53C5A8A9536F54FBA1699E1FEC82403359 -66741ED2B98756BD5DE594C8CB2E0C24BB372EB2EE6F7910940CE6EE8D2770DE -6343C52B4065B6AC1B3DE9C4575B8061DE6F05961E68FE6527BA66EC51AF4948 -8CEEC967F6E376BAA1DCCC8D50DC72C76DEE3644F890D4DFAD6E4B9115F43F9F -25CB66AE9E46331F5233609A390523BFD6D642F6BEA65B7500C3F7C28D03C2D8 -A3B5C7ACCEB8147C62865F8DD2F844F294E8AA932F5D9482FE0A1461EF74BA57 -BF1848B7CE0CD572A583A6837F9D27B6844E62DB08DF1AC678861485877454E2 -FADCD5C87B57340824621B978982092C1334625551D36494A1E0246336B4104C -B823C8ECEB49EAC4F8360867BA86FA2929918ABFEBC195C559BAF28B2396DE2C -5A550C3A17CDB40C4E2A4683590B0BBE2031F525216083CA6D9DE3247D0B77A7 -7348225427CBD78F4C8DD795D010D66B5D16F513066C021F54DB36BC6902190E -53470B96270C8DCE6AA8F836F926EC56E5A4C69BA37EEAAF22AB1D09860279BF -97935068A4D11319146344CA8CA2B87E81D08345C699A81F0F4BAF56E39969AF -A8094449E595CFFAF5CEC0540940DBBF79273B13D1A884BB2C354509CA95E582 -34284D9EE6992D5F3D2FCC09F99D1B8B31B59E651C17A174D98E2AE214332D44 -9F3769402AE4D2E6707450545C6A5322637648488BDE496DFA32BEBA617BDE88 -D07982B6948B94C91247FAAE6AC69A8727FD4AF3154C5F6B435379119898DC8C -3110AC36907AA6653E28D292D7AFE2C3E54B6D29800BC7176B4F0D00E09904D2 -F5DF5805E4C8E4348F017ACB5C62DD8EE155F56AB87315F95BF1A7AF147B71B6 -AE4952942EE6676E491E9CA622504DCE2ADC678AABB16886ED89B6309EEEEE6E -08D8133000ECFE0BE713E5D144DF17E98DDFC61C688E9A89302773835DDF9254 -A4985D6567AF8DFEB4335E1CD6B9D7DE23B009A7BEEED3BE0D7F77BEFB5BF2A1 -07A44B1F9CEF1EEB6D3F49804D6BC47AE26DF2F878E8ED4861FA691AF085A254 -688418486DAF652BE04054A8A8CE7EB42C5B30146C3ACC47502AD1BFB1A92DEE -B3D317D4D2FB276BF7C4F11678AC10CBB01C3DA178A5C101BA5B995D18136261 -EE1EDCBF883B6BA4335CC33BCBB116EE70B1372E01E64DCFD534672D9C84FBDD -79C8D2BDDE8D5C55F852E41FB5C1076D91B0D5C0E13F70B66904E08243EB3287 -C6257181962EF755E7A603AA23D63BCABF36F18684582182CC20CEA4F1DA0665 -1A8F1A4AF7C09F0351460919B10537E19A0ECA06DD9C00368137115979D3058F -635AEB09C1C561D020B5E19358F216B8D17582A518FDEB4AD7735FFA2C746D5F -163CA092531649865A1DA92CC8FDA32490826FAF4A9BA50653C2C3667F61D880 -D6523745251E5BADE8DB233EF3A62E7C92F21AA31618EB0A08D47F406FC07C54 -FC04404F5BF9DF6D2D53334DC93138323AE39E95F9CB2260995970E173C997B3 -414701687EFD2B2088E50ECBDF14FBCC612AEF323683D2800DC9B9EB054B8CF9 -3295728A29DFA6E22A98540806D6C89C34B188C29723DF52C50BBD4EF02C887B -335A72FCC0F7C358AE98D26FF44F1632CAA1774AE6F8852EE8BC262FF77A2E24 -8B8833B7C9F9C65F94C889A06095776BC75361EA184FB5C5C8BA401A8D2D9771 -D0D71BEADEDFD70EF617B92FE12FEAEAFA5F6013A28DA3C666BEE78D103C8947 -3901E3B368BEE322935020EEE395B9701F65615D510809D8AF431537805E0B5A -908D1B2C659582D0E54294B5BAFDF5FF482712179CE8F6820C3E72A73EE0A4C2 -43F792139AE3F8AB7A8D22A6D4C222B2B63CE37F0431157AD317A63E05067704 -85F00AD9B822B1506DA0551ED23099D53CF6E5127B5AB291B33EFBD26C21E9AA -4096BA233B76B87EEFBBF8721EA8C37B933C5D901C4E451C1B05A5920CDAC618 -F9431CEED497EA77D36CDF497354E158B9016CC888DDE52EF00302C140B29C1E -392F5974EF8EB272C054F3906F5D0B493C2478AEB0A83E469850BF76AE766B4C -884B10B49EDB704B33AA96020522C5218D7258210572E8B274FBB05B51380F5F -DD14C84263128C4D037314263E8B1ED48C816F06B39E32D5A894E114F9B1A2EA -F255A824E41E768E70ABBB14964CA00C9C3EC281D14BCFB681BDC943BCF320C3 -0DB0B18DB7FDE42A3A2DEBF1746BE74E18BC0A8081DFAFDBCD64050ABBBF3A66 -72D0D7CA15E88ADD7F0A1E1F70D397D838AFECE3352FAF0B149D5DA940B518FA -9594FF7171A2A6B77CD9CF96143DF0B708EF569CC135A2240343B3B50633437B -BFCB0416AE4AADA1A480CFC134C1DBB9472279C4966B99B473272AF27150B683 -09C57E73A83E7339B022F0388640EF9561C518AF312EBF0EF120CDFFF9F193AC -FD6FCCCC337922405224C8015431BA7610EDE19CE9176A6C1F552AC7413ABFCF -EAE1FC65D1F56917B125E498E37D2E7AD170F0DB13DFD8D430523B774DF5B2B9 -971F0F78F0931E81A848B1E2D901BA1A011957B56831AA755DE617F8A40B843B -470D96140340CA72B45C2BF0C0CB635A6D7B25A084AAD2830288ACFA119C3AF9 -5ACBEE18F38B244B7FD29210A7BF1D3A5EBD17E2B268C36CF439120B1947EBC2 -CF769AD003B5C178F5FBC3AB5D901682CAF6AEC1D66B3F3DF730C27F09430EF3 -81F32BE8B781338BCA00F8BB26B89804E750BEB587E558F48AE34A0516B1B4F8 -342A97EEE51D352EB39C2819A200790E5BEBBC50EF4FC2DB326FB61F969EC2C0 -98CD4F78F741C11D2744F26B443302392316A5C80A9ED122C7D27C1C89D098E3 -ED365F63F5F2DB3889A4EF86587722E0059123D95D3C471751D8D8E84941BB5A -D14766DF319F648FB6FC6B39E94450BBAD6F83E43B92B72B5D4F6804031782D9 -9E40AAF10A291F048E4A0B6E726B1E81942615DD0A862087048BD3B261E8F8A4 -25D82D60D90E58A9F3C03CCF9593F0A8738F397E058AC523438F58B2AD206B85 -98B61EB8536BDEE0219867CD40F10F622EABC2D52297B257EA0DD929B0BB7938 -158C6A6BA70514C27CAD1F310C493FEFC4EBCA10CE4F77686C374E1125F69855 -9869DB3887046E82DA5EDDBDECABBEF1E050B26A91A6CF23D3F06B4206D5573F -EDC6CB4DA302A355CD3CF80B54B270FA1844FB5DA988D08A754D30CC5F8DB71A -5AFF8F08A67CF1DF916E3370D961EBC802E2AE36B25F0B2BD2F01DDC9D52E45E -18D579D5C4A750F27262D2364A1CB2BB36B116626A9C1B6E35E22E81FF695E1F -713B9461726F5427EBABD116AF543A84981796A6FB49F72BB7AEAB3ED5E771EC -D1823DCED5EE170126069B5369BFBE2C1225EF0E5757B2ECC2360F8EB34EE3F2 -5F39660B7F714A82EFF3A61B7C9D26A32FD4C6EEEFABDB9914BF7DD6FB240198 -81F121394D0C2386738E343645A9CE8585145ED6957EB06466D5037B1FB3210D -CF0E79E0920167C5DBD605FDF8A66F96CE741DA7DD85D629280681BFFCEF027D -C9390E2EE59F24B714AE30A802F112BCA54AB3FCF419F65B4B27CB7A543B55ED -350D9BE596B15AD6F79730DC86D82DD075390869201CD6FA2D22F77FEF7619AE -6FB42C939079757BDD06BE3B8A7CE60AEA6D1B753658F858AA2584D4A4CBAF7F -0D701BBC0379973E5753B848BCB7CF56FF30E5AC9D2E83F33B4D87DA222F1306 -1877A2D810123D951F5CE12B17862EFDD5A86DA3A3987D973F70541D70B0CB3D -0F214AD4B1FFFA21A29E5C7856CE49FA93528E6D53570E3D8D6B17FA27B28AB3 -FD2BBCC63139FD7F86DE6A84A2204CB30FD14080D45EA14EA784A5471ADE8A70 -2864A204F10AA5B2A2C870521B97AD75CE3F6C078F1BACC99BBFC0E2F2387022 -6F72BF44DDB62051E1B81A1419CF2F033B77FE46C2208E7DA22F83392EC97328 -9A5E3DEF8BD6323E16D1D14FCFC890BEFAAC9F879198703CC9FD0FEEAA639EC1 -B787D77B325A213B71ED56F1ED09DAB41AD4F8E314FA8154BAACF480F110B939 -86477401D4ADE8FB386CE8959027A8B91C56C53028C7AD7EEB61DD986D303572 -86324689E1AFF282E10F789421EC2BBFC5637C18936B1F2B4D02C8C8D5039503 -D425992185042BA95E50C1ADD6563F3C661AAAF32E29F9A4BD3ADBA7A55962F9 -ADD1CA560CDF1D0BEF0C57E4EA11587CD17CAB65D9DD830CB738549C6F614612 -FACA8E3031BBF29682324D9E12BD792F9F3A24D7250D2AB55FC984C6CDBE070F -5F6282F51C4DEAD075EFA1820E044174FDBFE9AABB68E6254F4B59E8F442DBCF -D2AE8ED7ACAFDD486DD36530A71F9A0D9FF91B19FAF723B4909C9F99D5CB29F6 -2CB6384D6A3544359AE23E09770F82FF7C9327BD392BD0F6B607897B6D826C50 -B84B2E0722B0E27ADD479E5607B4500B8ED238B99C40B2BB47F02352BDACAD22 -262DBFBD38A9D4D1BAB79053F4F172397F8F7C00CBD37164A0C89B7E31EDB3C2 -25D32798F7F83582CCA56EC0F419316EDB2F3299E40BFFFE63C5C2A0ACDE3C9A -414C2BF9F341F40FD4C8A5B1950EA05A26DD6CE187E181E6AA167F26AF6A4E5D -6E4AE9430E0069749299D2B9D8ED6A3E647BF2707948B8F6D16D4DFBBC71BF61 -5EBDC349EAA9EC847880990795B75B118423D9153B05D5D6BF0D20E909F8B22D -0DC9A8CD8CA5B43D92F4CB54344B375926EEFA5BF058B7BAB54B5C97BD5653FC -F05BB1A5991B068C26B0420DECA3F1943D093997A3A8BB061BB25CFFC0CA1DCD -D85CB203491D176C4C183BB124F22D57678841F08419028F250C30D1237A0213 -E5A392E60B27D2BE5240346B99EAFF9B57F108DA66B6AB826546C6411864F7CD -FE404BEE7D58F28580C448AAB599D12B00A3FDB2BB93737971A5E13FD7CFA970 -656D45145A54DB1BDD0701097445ACF73861FEEB01835F35790E98EF162D5F37 -E1A5617CB2BC22074305FBDC8024E741C7BB0FA0E17F123AF953742E01AF56A0 -AFF35515ED55F9621AAA309D36964B0187F56FE1F02662B7DFD745F2F3BCCC43 -23C8FFD86F382E99DFF681A7D22CD133153C40C3FCBDF86DBED11FD36F9B6B3F -C5FDBEFB72496F3C209BD61EB9558CB2BB1672CAD20F8086DF3492147770C0F5 -95444F8731D0A1F6036C3099DAC1993B2C838794554E8A3B96614090077BAB84 -A5954FF123B90550E1D1A4AB2CA6E8214C473B3CF56746959C062AB6C28EC09B -F22096BF7FB6321338085C726C42745088742C6C55D4EA9854CAA71E7BAFEC70 -A29302F3C909A6E193ACDC6496F7929713DDD1F4B813D73E794377CC0B956B9C -2D07F5AF8C01D7D9F932F114547E4EBB953ADCED8B20E83FF41B1F4FA5A02915 -0C63DC0619BD7E3B5E6FA60157A21794D7299C5774C0FF7D929FE9BC1EABB7F3 -193E83584567271D2123E6B069DC23889B93CBF2ECE77CD8CCD649AE853784CE -A79337DC93FB835373CAB6E183F5CFEDCE41C418E8C0C48D02BDDDC0CD3D3B4B -285195948E36529F28A6F925FDF16248F9331CBF5A08DC0ECDE2C36FB0A0AB89 -2DC0EA84D93C834DDC1BF962D89153901ED7784D9E68BD06357F279CCB7C602B -CCF4F389CD7CB4197D2A9271D65097AC31DC2FFEF76884D0910639237DD0C020 -F0DDBBAD4C2883ED7313DFA0539D989C1FABB6A5ED54FC791B196AFE787363DE -6688123AAD777F27E4DD19C32B7FAFB9E8E0552DE8DA00570B1AC3E8CA4C7866 -6CDE42B4CB89FA30F0AC964EC7F2F77D3F1980313330F26E545BC7A8F5072AA3 -2FB0329361BC8BE2C2B48FD060C89CAED6DD9BF6462BEE5FBA59C569D8EEEEFD -8C1BBEA3B73A537D1256C7D6CC73A9CFA3DDB34252A3A4509536D62802A615DA -4AC07C441743B45A15D85181482717316C5B12F6E52BF9A1C287801F3677CFEA -6B60F505F9234792D6E82DCE04C72C308C0D17B80B14B291AA4B437DB7CE5E35 -436CC41F868ED6162F25BE5C9FE406FE656FAAA39A72CD5DE07569F21C55198E -54678E869AB6959798013ED6CB2D9CAF568F43D2624ED5F602B7F16F9D27C12D -48EE40743E1DA97E6702FC3634CEE0AF9E6FB3C4587346219C4CDC0B6CCF7F99 -E40B48B6C7F5BB21DA0656B683E71A4CC310B001A180D9E00BE05215B170D2B5 -C93C2636B61BA3A840076A5F41B8DB3E0B2A38C3848DB0CCD419E5E14DCD1397 -AD9811172CE82D7CC7D825B6722205E0072FC807FB647E0442333D42CF799579 -C7B7406D147A69C59E03536C8D2EF372AD9C374B977CE1A0784C83073742008E -480EC148196F146C5278FF1EC8252E708B9042389C11547351F093CA8488DC3E -1D5126DF92EB568240BBBDD84B2129B6E8FD6999651566BFB632984240E14F4A -E8F5BC9C04ACFB19B327E5246E5BA5B73A0A308D930A588E57174574ED2FE506 -9512E3CD02D75AFDC1A36BFB585493E4164F3894679FA602BEDD8CE9E821D187 -47CD38794364E336B65126F61CD3CA861F9919F24CDD410E5F03AAFC4E45E30A -486F6CB28CE7A6A2125C55CCCC11BA659E72234CE9D5F6 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMSY10 -%!PS-AdobeFont-1.1: CMSY10 1.0 -%%CreationDate: 1991 Aug 15 07:20:57 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMSY10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle -14.035 def -/isFixedPitch false def -end readonly def -/FontName /CMSY10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 15 /bullet put -dup 102 /braceleft put -dup 103 /braceright put -dup 106 /bar put -readonly def -/FontBBox{-29 -960 1116 775}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 -7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 -A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 -E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A -221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A -27D1663E0B62F461F6E40A5D6676D1D12B51E641C1D4E8E2771864FC104F8CBF -5B78EC1D88228725F1C453A678F58A7E1B7BD7CA700717D288EB8DA1F57C4F09 -0ABF1D42C5DDD0C384C7E22F8F8047BE1D4C1CC8E33368FB1AC82B4E96146730 -DE3302B2E6B819CB6AE455B1AF3187FFE8071AA57EF8A6616B9CB7941D44EC7A -71A7BB3DF755178D7D2E4BB69859EFA4BBC30BD6BB1531133FD4D9438FF99F09 -4ECC068A324D75B5F696B8688EEB2F17E5ED34CCD6D047A4E3806D000C199D7C -515DB70A8D4F6146FE068DC1E5DE8BC57030ACE57A0A31C99BEDB251A0ECAD78 -253AB321023D15FF7F55A3CE81514C1E7E76240C1FB36CD4874DDB761CC325F5 -D588700B294849D690F93526EF438A42B9B5B0508584EA3766D35F5B8D51C458 -ECB9FBD23A49576EAB06BACB7EA6D300985500835F4FE597D4A1110C8EABE6FC -CE3E1F95CFD3A42446F25355381D476B2FFB6EF247BF58A6FFC5EC0E4CC207BE -46485F8E07350B37DCA8C1864E62614332A1D3C9DEDDD6492181949A2C3498C9 -EC2A81C1F4FF989A4654E375F509D24D969B97D2A9940FAF43BBB286E08559C0 -F8D9674B0A294B36D3A050F7DED8C80E1D230812F6B8387B17948FD29FF050E2 -AAC5EBE5D96AFD0879534E2F4BB81613A1571750F9CF4215199F93813D815B5D -1C79E11A0FCBB627CDE569F88C741CD502627777BB058ECAC09B6ACCFACA69B9 -8F8168B0B5A1A6EB13E884B348FBB2ACF9EB180F6E27D57F8503710CE037A34A -F8B157201657C825E2A4B4A7696B58B7A988C05E43E66F0FF277A7694C555C54 -AFB1D32F6DE102136FC810E1F3B5CEA42476EAC7AAFB390E3252B2169DCDEE6E -328507BD0E24734A85AAA263E0D2F64BE1607455BC855785BC27F8B30FE917B4 -23AB3C812975355942E955501AF85A3C0CE836911AF679EA44AD6A7D042A6549 -0C471FE294E8490024D93ADCADED460FAB7FBCDC29EFEBD2A9A127E11869E659 -961B29206CE63944B6FA4B9315BCC528EB1E0223CE94C795A5D5231A7FC8545D -6B287B965F8EEDDB67A6774129DD01D5A21694ABE320BB2553043D4C42ACFF91 -1009372CB03381035BEEEEFD05631E026A0980A72A67B3703323A4E7C94FFCEE -8D0B7407F9CCC043D3D184BEA4728385D6AB2FB0641DD8F5BA7E04035D30D628 -7E97D31C1486DFD5B1D076B84B4ABA4829ED4310321F1F24B847C44E00185A69 -37711A -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMTT10 -%!PS-AdobeFont-1.1: CMTT10 1.00B -%%CreationDate: 1992 Apr 26 10:42:42 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.00B) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMTT10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle 0 def -/isFixedPitch true def -end readonly def -/FontName /CMTT10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 33 /exclam put -dup 34 /quotedbl put -dup 35 /numbersign put -dup 36 /dollar put -dup 37 /percent put -dup 38 /ampersand put -dup 39 /quoteright put -dup 40 /parenleft put -dup 41 /parenright put -dup 42 /asterisk put -dup 43 /plus put -dup 44 /comma put -dup 45 /hyphen put -dup 46 /period put -dup 47 /slash put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 56 /eight put -dup 57 /nine put -dup 58 /colon put -dup 59 /semicolon put -dup 60 /less put -dup 61 /equal put -dup 62 /greater put -dup 63 /question put -dup 64 /at put -dup 65 /A put -dup 66 /B put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 72 /H put -dup 73 /I put -dup 74 /J put -dup 75 /K put -dup 76 /L put -dup 77 /M put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 81 /Q put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 86 /V put -dup 87 /W put -dup 88 /X put -dup 89 /Y put -dup 90 /Z put -dup 91 /bracketleft put -dup 92 /backslash put -dup 93 /bracketright put -dup 94 /asciicircum put -dup 95 /underscore put -dup 97 /a put -dup 98 /b put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 102 /f put -dup 103 /g put -dup 104 /h put -dup 105 /i put -dup 106 /j put -dup 107 /k put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 113 /q put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -dup 118 /v put -dup 119 /w put -dup 120 /x put -dup 121 /y put -dup 122 /z put -dup 123 /braceleft put -dup 124 /bar put -dup 125 /braceright put -dup 126 /asciitilde put -readonly def -/FontBBox{-4 -235 731 800}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5F00F963068B8232429ED8B7CF6A3D879A2D19 -38DD5C4467F9DD8C5D1A2000B3A6BF2F25629BAEC199AE8BD4BA6ED9BBF7DABF -D0E153BAB1C17900D4FCE209622ACD19E7C74C2807D0397357ED07AB460D5204 -EB3A45B7AC4D106B7303AD8348853032A745F417943F9B4FED652B835AA49727 -A8B4117AFF1D4BCE831EB510B6851796D0BE6982B76620CB3CE0C22CACDD4593 -F244C14EEC0E5A7C4AC42392F81C01BC4257FE12AF33F4BFEA9108FF11CF9714 -4DD6EC70A2C4C1E4F328A1EB25E43525FB1E16C07E28CC359DF61F426B7D41EA -6A0C84DD63275395A503AAE908E1C82D389FD12A21E86999799E7F24A994472E -A10EAE77096709BE0D11AAD24A30D96E15A51D720AFB3B10D2E0AC8DC1A1204B -E8725E00D7E3A96F9978BC19377034D93D080C4391E579C34FF9FC2379CB119F -1E5BBEA91AE20F343C6420BE1E2BD0636B04FCCC0BEE0DC2D56D66F06DB22438 -452822CBEAF03EE9EAA8398F276EC0D92A7FB978C17805DB2F4A7DFBA56FD6AF -8670EB364F01DE8FCAFBAF657D68C3A03112915736CEABAA8BA5C0AC25288369 -5D49BD891FABEFE8699A0AE3ED85B48ACB22229E15623399C93DE7D935734ADA -DA7A1462C111D44AD53EA35B57E5D0B5FC0B481820E43222DB8EFCD5D30E15F9 -BA304FA879392EE0BCC0E1A61E74B3A1FC3A3D170218D7244580C7AA0DC65D19 -741FA5FE6F8CBF60250ACC27454BBF0897CA4B909C83A56672958752ED4B5E79 -E18660764F155E86F09EFA9F7685F2F5027EC85A775287B30E2069DE4E4D5712 -E7D033481A53A2702BA7542C71062173039030CF28D8B9C63B5596A9B42B33E7 -D922944A38713383D3648A4AF160A3B0C8F3379BA4372BE2E7EA49AABA75AEEE -C5DDE1D8BF68483C3D21271280ABB91D54CC819680322EAB72E1250A760BC8DA -726405EFE420635B5B7F0B48752C06083E92BDE06401C42A2C528C8A60381227 -CEBEF0C9440DC034DAD9C19FB27DB399BDAEE22053591D6538587C768C1B7B0B -7D1E222D2D8AF3A6473CC4C0D6C3E0DB49068CEB8C9BD1C5CD486A50DAA10BC7 -7D6286142355E3F21DD254E27C00C442728A0BAEC9D3F17AE9CE320D365152E9 -EB0D5E3874F2BCEDA98521D23FCFC30B4B69DAD2ADBE80E5964ED0ABEF6C73B6 -DAD30E2C5061E3747FE536E1A5D190D028F2130AF608F5DDF9DDDF1E77DC8437 -ECB3EC93B33505DF47884DDBD1DC6BBE4098DF04A29AF6FA3AE344600D0AAB53 -B3820DD7ECB600A3B8001C51AF2CA7A39AE1485A087FD1752DF68F55B52B4DA7 -48030F2AA7E570B3D56C4EAD367B9B73FBC0A7356253233006178B9A6BC19081 -B815B5988AE76FE6FAFD7AC239072B1106A3F509381AAEE79B2F2154CAC4727B -D199CDC8B4D05DF4BA006982512ABD7539E28D937B0F87FF79A3F84C29ECF943 -A8DCB8BDF8EA9E7A0E7CD60BC2308C96B3E889C797D0FF28FF4847016B3DA141 -E76FC6BE78A6EE9CE07E651FF86E720A1A1F075972D36E5C55162E3FE26BCE3A -814BFEB12D4C5FD24340CFFED499C7CA183E57EC4F12CFFBE3291D43F7270575 -C6C3306F832EF182ADD0AA14C4D8669A17C09F632406AFA195F90C4DDC39779E -EC0A77E590211592D6EE19563963225C06C2F13265EBB5A6CFB7C17D9E77650D -11958305727AF662AE73AD0E3ED5F7E7086C5A0C3548A8129575980B06C715AF -DD55C8DF869BED0A7883491030B1A7E82C5EB04E5A7D952E716DD8F2EF6275EE -087614CFAB55FCE2BBECD7E8D9C90FD8359E929D5E0A416A23BD58158318B4FF -87B095EB63F7F052B3A77F136FD66EB2C52BD46CD7DB3091A4B78A607112B12C -4D171B2A00B78B0E1C44B0D90C20D9244281F5123DC1F6063F91E9E3E48DE78B -C862D848BAD073A4FCB5EEC9FF54B5AB8E234CCC3C7439C62ABC4A13EF1B8897 -ABBF21F900C564C9A305FC36FC7224932F766E6E72C2EBB55953DFE2AFC2E3FD -33A0C6F0FDFF086E9FD796E7242596AE85B877223532667625E371D2156E4C04 -0D7FFCD3337B93DF066CB6FE1E13960719EB7CB409EE805C08ACD2C06303ED9C -E34C898787A43C1B428B896551C6FEB50A831C6F8CE2073EFC662EC286CB7555 -A3B42E58772E82FEE206948B8C439FEC5E4ECB9E11DC3A4CBC7611E30890E408 -637A01A2118441B4F9467A98BB2A1B03BB2F5D8E3DB7D1D15C188D9E856088EC -B762F07B1C06024F7EF53A2FBD60C0A1F4C0275D07164545250ECEEF8CB15B04 -A2D8AC44DDE818C4E3CBD2A5FA0FE49750886CD7CFAAF8B780255F89DF7F4F5C -BB594FE7C1597DA71813C2952AD3E811524459EB71D29696B450C924B6A5C843 -8F36A0F1D7DFE796FB9564333666D74AE614D0D698FAFF20F83C86524C894BB0 -272221C060544F3B653CB0E4E4F82B20D7530B3806E6A5830852C58070177815 -E287C847F19F64E854F1463C23DDD80093D6FEB8BAA22C5F05C21F99FBA7193A -EB7CD49CFDF4308C6C68CC955A45FCFB54FCADA9A3BFBDE086B057DE88BE335D -280F5338D7E66AD39FD08F9B55884F1F377FB6869FBABE3EAA4B7ACCD85BE672 -724B4B8F236B0889B6E7049CBA558A89F17863E82DF145DB8C7ED1F36332DE23 -3C0053B74E850FA14F9EC9EFC23AF18E153CC96FB0FFD910347370E57F0D81E9 -4A83E2D189EE5635E85A2BEAB5B1CB974546BFB2FC2ABA1E15DC0EC1BB3AF1DB -B2F93538B92F504CBD7AAFE36F5F3AD45EB16378F169B17869FE81464CB826CB -400D2F5441A496B6C60A4F15FD20ECCAC1F8F91015E7E1C1A10B7992A1554E52 -9FBEE905A3005336E49CB04BA7223F1674C0BBDFA06ACA34F7BFDA56906E04A7 -4DD79EC7E79B021A5008F3B1E04712D689366F520B0FA66A558F957011992728 -561BF4B75C2BE07C4024C172085E51CCC5CFA439F570297154CDDBB3AA25CD6A -3004B936488851BA1E814260C06CD5479DCAB1A6AE21A5F4563024F973D738B4 -0DDB6C6DD2E3AC21B4F6D95CF9AACA782919F5D3E613D61F3224A982AF485C8D -EA0037410EB70AB7D3EC174C6D5DE5C9C5A1220EF7C2B74499ADCEEFF077D1D3 -50C1124535F88C3C3F66477E42F1932665AD323E06B398D2805B9CEA632F5B1E -50FA587B102A35E2F15EC22DD66E4DF06A3F4BB717A3ED7FBBE2458EB4D896DD -AF00D1BC71FE1CCA27890ECBF9F0AF01D3E65CAA29427FAF06B3BE1E640522E0 -73B213D04491B93DB29113EF72211E31F4C5A7FD58451946CFC15FD805112FE2 -547D1131A46710DFB75659A33695FFAF3CDD40AE5260AD6766DA81DAB0A6E96B -E89D57AAEF32B5EDBBE9F7CC033BB2595CA3FEDA2ABAC8E5395EBC35BC112FE9 -67EAF1F123228538091483050847F8FB5194203609502D3A09CDE811EADC18B9 -F039593782C27EFA7697182D6367E88E326AD5622C5A457FE2644FEADA88615D -9DE3E483BFD9329667953CDB86F9D2F0D4F02DAB8A98FDEB1D17CAAED9B6E2E6 -0C55C1FEE25AB98FF59FC235876029CE03E4A713B75B3163BE3B2DC0D4472DBC -473E10400C0F57E627AE97FD0C1CB0F78FD8E2FA831A3D2B1C2BB3F2D4E812A4 -194C8732B0C525361DC8480CB27C30CD4DCFF01318D2EB4F5234B4A42EA8C23E -7B3EECA41B8E4F54D5458B37EF0FB2F49EB19F4EA8AD2B53820FA36E93DD309E -48847F5C01B1118ECE7D0186E6B8953344EB775D655AAAD7BCDA642EA2E39A15 -855C027CBC0E3FA752900EEB464E2D39404D1B85072B40834748C6F9C74C5B6C -3CEDE988343FD984CFE4B856A481E60E2E65D3BB41BAF2FA80AC0BFE381071C4 -573C6ED65C524FF777F34D82E9661E4A75E3878CC77BC59218244612219C5A92 -E95B90EC2C38614665550026F1730D11162F19D841681C04C401E102C047541B -97B9264D86F47E25A347696AE5EF0FF3ECD9BA32C92901DEDD816F7D73ED1216 -0A98771892472CD625A8F7F19DEFCF5CA2AE57F8AD3898F2C1005B187DEC6F2A -A31C32720EBC934178E0E9979013B3C9AEDA4051DF63D8C903A399DC88F83DCB -A73F1B2083819D1BBEA5235F8FE1D098F32A2BA6274424A99A4975FE4BFD59AD -79B40A8003CC0AA728EA79D6BDCBBD73DF45B7918BC099C5BE4A068BF64A30B1 -C39442CED98AAE1BD495F6CA32D564A72E3BF753B49E4178927E4BBC0F06048F -96DE7C30AF580B0BFFDB330B3B87D7F6532A24F403680BD9F15E758CDF04EB94 -E83C7E644FDE5BEE7CE73EFAC75669E41BDFB20A5B8ADE1137378DD8102A0DBE -19499A623770417CBF5211395A6BA9F4490F4707A46F1F9B3FBE642DEA0CA053 -9ABC307B1E71DC2B069DDDBB4EAE378BCC75AD61DA900AF8BA6DF0E27A8D2258 -DC80205305AB6ABFE3726703E60869BFAFF1874F3C0E05FAD9C05D7D89ECECA9 -DD2AF5F777D7514208697E712B52448B364D3ECEFD8127043DDC9D0757B7CC37 -5CDE8001D007A6E961EA24D7FFC92410F3B13A32946F12A50DFFA256249BC8D7 -C1842FB84AD51B41008EC4604F6B70990510EE13E6DA34F864A572D99A13FFC7 -3609EF2BB1FCDEDF37A6018248C545E086EAD1BA1143E74AC60B684E755E59E7 -36557B915F92EF78FC177621D49F777A2AF39F3C2AA6EC74750AAAE08BCC21CA -A71CCDC91DD45E6050D83ABA49ECE425B55EEE137C55619037F1C30530BD0A6E -CD2004B6A040405064D7E87C55536680364E09248BFAA3FDF95CDA0708E55F4C -F7D0A92A93DEE0C7B69638F171B28B7F854CCC6EBC6AEE14864BF5144EA36D46 -A9C297225AB0325E28EF6BD06D7E40E3A724EA1E50C4C6163B195CFFD5DD291D -D7BBE9AF4324A69394117EFD62F08D6BA6A8F0AC3E2353492999AF28FBA758C3 -A50B6840CC72054355E6CBDBD86F683537A4115049BC1616BA35C2B0B6F5CC32 -3F6831DE4E6029310738DE23D36D2C6E82F04EB675FB89789F74AFE3B8854250 -51812FBEFBCF162947554324FADAB765C74B6DA89F60A734076D44BBE45263B1 -3FEFEEA90EC7948F23F34D4049087AF6563692417DDBCDD5A9552A373C2528F8 -0318D3C0669279F292127CBA40B0ABE08A1476BC9EBFA8BD5D622BC5CE7DBA20 -C689BDAF50D5B1EAA89E296787CC53845DB2BA54FDE363DCC98A7BA256663869 -E9E02E09077884DF1A2A41AA698B7EDE8DAFA621B552DDA91AD1E671D636FB36 -91C62B4D2D4112F2C169E0023EB7521F570CECC54ECA5EBA462049AABBE2ADEF -E3234BFD71B26DFDD9D34DFA69E5E80FD90406E6505A6798F030A4B5172A7BC2 -C9B765A86ED55C0590E0432719BCD7BDE7CCC7F6B33BD467063D886276C8879D -E04897A4623111C14A1EDBBF69E2FEDDFEAEB2A785C6D2F0711DF4B93AAA291E -7F4E0CF9CC3FF0D31953C594DAD014097DA02CBD5AE8828C7E7B5BDA09188B05 -0D7263F164E1E78CC430ACAD1E8FA71001E9BCEFAE47C79846916A5F819CA366 -5734089BCDD458CA1A9E8E17BFF357A91F9A7A8A6E1DEFB121353AA80F1906A5 -AF7CD2E59EE6776FC0DA6574DA0DE522918CAC4E566F13FB9B64EFE79F3A3BC0 -689E3B0676741C90FF3BF85C7A0FA9716F4ED0E329512B66BFB8AEB56C3DD6B2 -24F8D6E23751A8485F7EB46719E9D22618FEE86D5E01ECCF4C6E74368A8E9B49 -245D80E7484DFBC916FB2447852B36EF3F99A82B6C106F786707D7689DCD7AEC -A0C51AC1A3F67034C16B74994403FAE7743BF02149BEBEF554814BEF31B79184 -3FAB4D2C887E1BEE81B465D12DCDDAD03DE5ABE9E763C440B2CFD42FD16D96EB -C21FE788C8C2688F79F148AA7090BE64B0EA710D376222FD1590301BA9A2E715 -D33B8C1D95F2589AB0EE476F7046537E27DBBCDADEA1E7357C9D7FA92C2F93A6 -7BDDF58A44966590821023380C97CDE37EF6D449E35EF32BCA6E69DC8458511E -8DC8AB63171A6018AC9A334829E5978484C4C6E917A5F1C254E6669F4037C691 -36980250A80673E0F18C9E0FBA1E5CCA3BE30B8E7B7188062B25F8E1E16528A2 -F217C18D6A1955482E5463FBF097ABAF7314E449C6FEE56E2695407A8AA9648C -61AC2BF3B2D9CB6317A9B16CE931D318C8BC9676CD908505568C197D90C2BB46 -06431C999EB68C8216409E4CABACB2BB34A05B697B9DD1E91471A404B4969519 -E25209EF4EDD420944BED17B18DB3566FCB8059699FE416789191EC2B35086AA -2E10C139E3C9FA0A535DEE9255A867A26656213E85851DE5F51F9780D3A6E572 -F1F5CE64DA176CA810799DC1C60A8FD2A5ED42E613021A19928EC4572059B2C1 -EE441E79CDF7DD4AF7B6E3D3230419ACAED329388044B107DCB4DE91B71EB838 -904B1F969738BBDA064FFE75C6623639BE9924602DDF0C166B433B9D54ACDA5E -018680477FB8F10621FF32319E58DB672D744959A33E7314A1B3CDE0C038F7D6 -0C8A195AF191E36B0325334A711CD8E25D9C1D257E46A734779E486567481108 -E0281DE96907D460546578DE83A0A01A9ABF64402B48DEF739F4308E14145753 -719CEF720FE5CF8DAD7845E74D502B69DC18D172C3A27411259B8042F3FF82C3 -B157BE242C351830255CF0EDA96577375A70657BD9A2E9FFC54AF0AE563D73F2 -E510279FEF48D79F5F7745DBB492F1D74DA738E6A4FE4364799B5BEC93B4CAF6 -B06B9B8C8D164F8FA1FBBA693204064F2C1806C39910910E02ECA8D092558CB8 -33338B359D56483B7B99A1D8137204EC1AE70ED3D75881FC3B00BB9349AD934C -81A9F285312FDDC77FA923B18B1873D288C2AAF2E6D0AF90BF25A982B843789D -5662D6A2DD58E065026885601ABED4B09CAAA3116DEE6B430B15BE0A121FC1BB -FDEA5A501F0798CFFFFEAB5101E707F1A00C8E014A3561FD39972EA9AB108EBB -960AEA7FF60C301AD6CBFCAA7D35CBF6F8462A4D76C4FBA6F3DF6BB762DF7900 -9F69529AB4EAF96C2866444B257160E8822533A7A1240C83EC18C364F577407B -4CB314678D2511735308A1660AD94B8B818CEA4A3DC00C5A1C978F8BB4E0491C -49328F6CDF95BF620AE53056364423841D84418B23C2A447B0CCF8D8633FE2E8 -4A4AC1C6C74627EECDC994059F1BAE9E6B10FA80D767B3FE97BFFAD413DCB0A8 -495039744B48266278194D60422D6E7C74D0DB45ACF217797D0C0678EEB60759 -6231438CFEFB346553A7A447B50807EBB6E885B5A49CA9A350EC4A8C76EDFBB3 -A4DA1C9E3EFA193CDF08553302998F20055C84420A4C5252F764CC4B7A4BEF6A -A09170EC417B296DD9E2301CD8EABE4A087E648E0525A9FFAF26374C47FDC123 -82F18C9884843864F418ACB08041E7896FDD395225532460A8194A8DB4DBD824 -1C68C6665F85059E365EC0972EC6465E2D8867449907DA6692A021F026F437BD -D02654BC11381BB6557663E0B0B8C4F2FF69E4776F4EABA69311BC1AF8155F7D -6D3A418BDC912CC7CF1A4BBC8A1376D8B4DEEB6585416959BCA4AA08D4520C33 -EB054DE53140992D0707210593BE62B3659E3E493C4562C2E99CECA143791DAC -679896BCDA0699E405957E17DDBD243E65CDD7C9C8629F29A2078658746A7779 -0F75BE24E2DDBB672B95F26366BAF036B3C23BE4132D7362E76D4183A469E0F7 -29174711ECAF4FD9A923E72FE58DF2854C5537E3626317D471D1E8A922C9BBA4 -CE9163A4086AC4A231C2BF35FBC39A5BBCFE41843CAC7D81A054509D31572BE1 -596E0B0B563DF2BF0E57DB4943DAEE35CA26C8433FEE4FC61145C77F65DADE75 -62DA18DFABC7F4194906F53884E62E77D8AB3E099776AB93B2B4D0C98FA44C71 -597202A2643942795EE8CE098FE26F1AF8134F1E75FAE18D563B1FF43A511C9E -EAFB9EFCF61490A1A4FD2CF354927B72C5EDD5D62B2F3F5006D6130562A13BCB -1B988A994A8D68B051A5A821CCD5D0F8D9D49FE7CD04EECCFD7A554CCDFFD77E -27AC4AB5BF9FE40F90EBD066C483796CE1A364E95C5E0CF2154834760522F128 -B2DBD1F4F73347D42635B2875A23597C35A0823CC6F71E49598125411BC9B2C2 -72470D36DD967C947AFB031BFCF770FE50551A134DF8C5D1AB1F09819569A57E -E23D4E87C0B52CD02B0A2E3FAA7D27A94359E82AF047756BB769BC5950A75207 -78ABD49D174F2F69810AFFA9336A52D6B93B004DCA5CDE58475C0210E0BA1D20 -FD4FFD6838EC56A0922472D4C4EE0CC481574BC30618179E733EA40A48847E14 -A75BE7717CC5DDCB5B0718074EAB6FF07CFFE794D335B3A13EB968EA8FC5B08A -13B38AD1C2C964E4B07E90B9732C458216B028E07DD593A5B767A2B415EFE7DA -951FC07800F11C7E2EF9BDD152BC6815B7F32117F49FE08BD79BEB949003512A -327F3F8FAE1767E7842348BA4373649F1A21DB2C56C081BCF9FA4EA86C8DFF00 -FF45C4F1386CF8C2C4120F3F6019CEBB639F2D272D08C1763A470D4BF6330DC8 -43C069A6333113C3A0C93471486EFE9BFC02B760C7CBB2E9156087D09EE8A178 -5EF50B34994094C3F0015EA2ADB6C920F4302FDEF128711994875551C4E883E2 -DDEFFAAE11F2234AFDD96400BB69C1B4E6EFD75734C586A10A54A98E7D790F28 -DEF7C7DF61FB23BF91AA700AE585EBDE74E215DA49F4ED466F46129022722086 -8884D8E026F35C4BEE7E866DF8E0846D5EC3534069B713FAB02D4B4EE3B44E1B -656F30D629D40AA1337786C1FDA08EA1217AFA4A6E2498B334DAB5461A70DFBB -5AA5686C89FFA4EE82D81CE2B28334DC5C032487CCE998616F48150BA1281911 -076E626E5BFCC56A0A4CDC559F878F14C2BD7A5148C1D8CC303FF9EC473354D2 -D4FB0F0F2AD0CF182A28074ED6552E179222570DE0E0D44E8FF4DB36C3AD6487 -C4BA53C8548714A69FCF8E3E5202F09469D7447C6519AE902C1D611A720BAFB5 -59E27A6DBA73624F44B4ABE0988BA3450F82E03521CCE8EDE8BE7EE1223B575A -DF9A52650E85545525E6F121FF2D1531F156EA9D5594239AEA2CD09EE28ACB15 -A445E11FD1C031188DB61881F474D49425C084489A88A47D681EA68E7FC4B1F9 -DBB552063A02A0EB51125E9B2CC646B940D46FF457415F9565892DEAC030F08B -E4C10DC38D825C7597394C844CB863CE6C843F67F2E1C42C4EF86AC7FB727BF0 -224B5E91BAD99CC6638AB2C64469A81D8B1789981872ED037B3A34BDF3130137 -80FE80FDA65EFBC11A08B98A1AE595F980B577E22D3CB7FED1D4016F5290ADF5 -47D7D9BAFE39F294582F2C084003E9C83FDB9EBC87C8B477CB8BB359EDD9BBC9 -9368D6605E1468A20909831BF602EFCEC0D5EBA99A2223E5A269275C8B221B3A -F9226654185929F794E1979ED18B4CD36152F973433AC67BE24B9D953254FBBD -B644CDF3BF0E29A2C72113DC486E46DED2CE8F8DFA8B0F8478D1F18C9AA8E054 -A31C3DBE84ECEDD85DF6AF9467AC2990ECAA3384FBCA1BBE598AA0D6813C859E -1520B88BF30ADA910A6AC3068A5B8CFD76B7F0F6F4AF4C32450D628B5320C384 -F23A2B5E8756895584155226A30F8B0437E028978491DCD00E79C0ED58DF261E -79B9DA17E57AEE03EE92102EAB2D63E69A88EE0B1E2087ED0C0CF6475EBDC3BE -0324D1FC8F7B90D8D807533E5436F2C2583B9629EC390403437FDAC908557894 -03054A6DD6A3586043A9C8BFD0C7EDE1229DBB9F69F7A5D20F55664D061F6517 -0051C6B3CD7338241FB403F2AF77DAB1A8EBE1650156D40863EC1957372BFDEA -BA8D0BB1193CC5BEB5A68C8274802E14FFA3ADCEBE19070325B1BDB960CF2988 -C0F5A9BFD843C515ADEC8B8AB02B2891EDD7502D9F28F4E58D8F67D1ACAFD0C3 -3531E0C7D1554344CCF90AC8696E83A3F968252981CAC09653956F4343B99D3D -4F17CB8BBE4506B354439B70F2024871D16668F9DECD8EDB872BE5E6ACC406F1 -1DF4E3ADF60EFED57D1C426292970199BB663405236C6A907B6891C6190E87F2 -78D9142220FF295C7BF44AF61470798FB8CFBEE6973C69DA1CC24ECB058AA753 -DDBFD92FBB15560EA19D5D92F0005B74F06F0EA5901D231996E0866389DCA433 -E62BE48479687084C1D67BC592E592939F806FA8BF5F0D3F644B1FA6F056DE0D -51D3F212C6818CB6166317058C2A0C07AE2E324CD90D4EC83CF4819B10CC348C -6DBABA024A5FCDAE6E288F82DA060BCD16437F07DCA43BF1E5A1B402F16C78FC -075BEE900B4021A1019C4A5ADC33230047FF11FDE8FB775DDA267040A22B4E5D -6012F7E72B8BC8DD3A81369A08FB81C6C4873C2147D03D4181D6D8032DD2B610 -9C44CAB50C5BD8F489EBF01C72D4198B66EEA4E976462F8874143640B82AE57C -A51EDEDE75A9A55D31587C14F8DEFFE69F75EA7B95BF725CE9991FB2F07AF568 -5AFEB39447B728B99BE0502BF28DE1D92B15926BE4E3DA2E7BB44A24836A97C6 -EE3A2080E01DC6514180DAF9C055F4C94929D34F193920020505E62804461630 -9F42C652F9D5681C91BE23DCB0C634247E739135F925EF3D5424767D5F5C5879 -C46F2E32C7B3BE9E90FD6ABE693A6016AB77670129B58B8FE719FA97FE320842 -6488CB85B6BCC0012975D22E75A2E086131DE676AB825A386C086FBE1B65DDDD -A19F06AA4C1D3EC84751C649F4A62CFDC48A7CF88CFEC68B959C211B60DCB045 -6BFF922FD7349B98E1769394E6CEA4F764AC4B6536AAE4E6BE69099A39A6A33C -97671C3AB4E7A94DCB829FBA97DFE5F71B1728FC81F826699DFDB0ACE9BC60E0 -6EC15D35EC479F3F53EE4D0398BAC138FED504A84A13B78568E3F9C86BAE8B88 -61830A80F8B994D0D66A8FA3FCD6C5099C29FC285ABF096EF9A3BFDBB522157C -DCE9F0D6AAFB1F8D7B0A3C573D0C170357175DD56EAF37BAAEF4C92FBE17E26C -7D2BDAACB9B8F33D09651FBE0D49A8BE66B78D075485BCD38DED5056FCE48A12 -D28E9670EC7CF4E9A277D6ABC2F7AB30BFF290B5452582F372FC9DE6CEA9EC0B -84328269F14FE7F47620B1042B283C54161AFCF84B46E6B1410587295E4F8958 -C1800F120B59639C85D46D46A4C64309931A8C91F138EB52F779189EF75B9157 -D624045F4B8846856ADF0AD735FC6FA41F7B6C002E9D1EBD92468E86C843AFB7 -4D78E3D54D866029DE5DF865EE3F7313AC358EDA70A792E22F2F806EF86A6B57 -64AAD565C57E64B1A6635B7394B4B5729189319FCAC8529ADE30633B9BDEE0D2 -AF1F8944EFDC7C408FD8FC270822CC01E7BA355C856219B3AC5D05CA37EB0EF1 -6766D62383AEDDA1F7CDAD1DF0172E766BB46C5FCCDDD61BB019D283EDEF312A -B2DBA38C9BB0928FB93F50E8516AB353BE04403D132805B5AAAA17163AB9C847 -F1B54946B0775FD21325C82E4EC7F2186C54B4396BC4B0B913A59E4444D11B39 -8AB56F2FD5788A9BA45DA5499A50BA74D28707F62086907BF8342E0C753A31A8 -DE293B592F51D74DECA52858CCF76C69BAF2224F640069BEF2604983FB478173 -792D68030D7A6E3FE083AFFE9488D872897ABFC88CA8BFE484A75201D73058D4 -72A8A26A50BA1F2B50CBF98D46DFED0BA057619BF370E435A0400147928D7C06 -28DF2A03527E3BE925D6A664E4640E63BD22D54A038D934B3DB5B500E075B8AB -06DB5279274E65FF870F1E5106E190AB0FD8849EEE2D605FD4F0DED2C3F86831 -4EECBFAAD8B2A895F08DBA692A8176F9080045519CC6C46B52F0F31DF112AD79 -8E46B9899C5527A011AB63FA443ACE90F09434C295A5D9E6753AF2645407488E -D29E7711546F87265C130B76B4632242E43962A5C886D4DB6316A2F3420FCAEA -3055AB5A9E1325EA870CE87F34BB2B3110E4919E1AFEE67606B00B03DD6824F0 -20BA42968B81DAE198C88057438E36056D46C550E3E5E03A99BD4B07E66A2179 -BBC5B3FB06D5D72022C53A3F3A1B759472D5A50D7F7A1F4E31D3F7A30EDC1D45 -4B00AEB5DF680145A123CCA3BBD801CA64B2CBEEA99842720F8DCE432909AE78 -5AD3F29AC69D302C62256CC4D47AC92EE11D2A3E1C666CEA24876491BB167548 -9E3A990252DF8254CB5E7141F57B78FD1FEB38BE135815C6FC86EF81B5994711 -E43083C3234C55DAD97CCCE4FF3F55C5A6C22ADD2C549513A465CFA3D8A9AEB6 -331374DC05A4F496BE33F9263172FB6FE1CCD19EE9515C5155ABECA9492DC743 -BE4142D63FB5E17D55C9FE642F07995502AECD9D555603D15B5BE420A65A6E98 -4F341BA13E44DBBC1DC8CF0D561198A2B40FAF35F7ED5FEB4429BF71F5C88637 -CB114F1377FD3227EDF592733EC68F4EFEAB14FE7C26DA7031075E04289FA6DC -8A79F81E4E18CAE8380CC585E7DA3DCDA3FCB53929AA8D772D53FC6D821EBB14 -EB472017FB56CE9410FEEFF14EA69C188993922DAFEC805F4C8028537A9D6365 -AE1A6BEF37CE8E02B995C41382984802AD3D12AA9FAA36837F9F9F8F60D16B81 -474238F136F442CA9B14620F83E4046E41EB0FD02BD04DA7863DF26624B5489A -B8BA35B0B3A8D128FA10E01DC9B622C26CC57CA79CCDEEB7E174698EFDCC0CBE -879AE1434B3EC5AF48E6C2EC5652DEFE0ECD7415FA46BC0C80FCC57CC808B3DE -CBE4CC7B62AD3B092487F7A23C38A2D9102DEBB1CF4C1EE7FEDE1E8BBCDF7F73 -54CAB1E591F9B3B3159D879A9492394B32F2CC43EE7EBA6E293AF12D7FC4ADF4 -DAF8F2F48A777E927A915DE1FD9125B52D406BACB0BEA149F6F6D79D92D06413 -5D68461A772D531F2E76D1947D2ED5BFFCD758E062B5435BFD180F7E3734D5DD -ABD86A1C2BA643955A36C482BEBAC608F588C43E6EA7EA2AE01D0346D28F50CD -BA8F9FD23674AB19A2B879E0DD19029EAC5D74D16B186CF4BE3382E74E361427 -536A00347E536701808C1D31A617D1F9269110B76A0D59C7B84D98C8FE308733 -C9497B807A77D244FEE03ED7FB5EB4D6ABB74A7129F23AF628BC01BEC6C43ED2 -D62F4E2133006FDB94D33CD31F9FFE57C8C9E31DC6D7A81A2C6ABF1D971EE222 -96A4D79F7232190EB796A43ECEB88F1C64A88A10C3AE8E98711EFDF984BF270B -55C5B9082D54DA7D32B168CE573597DC5A453D76953DBDDDBC1798F8A645AEB3 -78B6B5BAF60C9AFA9D5F818740EDAA977EBEA0F68E531550E607E6FCB04F3E22 -BC9D6440E1E153C8D780213DAB08CF8CFEB03018942AF980642745D711C7DB1D -BEFD825627798897ED8185D80234B6C087FBB602ADB1263C2A2A0F59AFCA7B09 -EA4ED3BCF936C2DAEA9C8DDAA90130C24AD1A1BA47711CC760FF72EB3F27C165 -CA1FDCF1250C6CA4A788AAEEE08902AB4EB03C6EDF281CA2F5B074C859DE3963 -27F7CFC53CC91C80F779ABB25F7A6601453DF5606B72EC562F615A92C1DCED58 -3911BE7784B6E8B17F8993E4D5693A327F9C289701F39ADCF583BB4EFDE1F835 -1A59BBC2E6B73CF422D877B0B423E4E8FD116F5C66A4BEB706A3D42E7EFBB5E5 -E73CD03D7A91719337CC8E13F9D8DA255185FBE3F4FB6DBE8EA90AF036A09BE3 -5047B59BC18C1C3658ACE003B6535E42043E4D7E6D79E0B48B3D0DCA36C046D1 -D5ACE0B6F91CB78BCBD144F3FAA3D9D711C9D11EC30B6CCDBF43CD490E9AC229 -9ED2CFAC4F53927040CC8FD26004450889A1167FA34247B7C283A46E4C0A8C20 -AB43314A34EF0BC02C5558746D35F2315624FB9D4A8ED13E3D1A8B80B872798E -CCB9775F985E31E8228B03949B4E35DCF7A41C834E53CE3C163EEECE81A8278C -FEA3A9E3264627D33738170C12F4EB23EF8F00811723FA4FE56A0EFE8ED5EBE4 -90455B690EAE1E8F1092C1AAC07FC418A6790C2DDA6DF739B9B586B68263EB63 -718EAD2B11037C5D26FF31FB2E56AB82773921B00EF07DECAEE2A8FD71AB232C -86865012F1FCC80CBDC4B0E881819601CE2FC5AC36875F2FB5C088436BB11159 -813020F0433EDF6D96FD162F5E3241F88BA7025F2B010208DD1DF737FFF1185B -812864C3049CE325E06610404C8DE9322187DAA7FD90FFDF2DF3C86D94E8E792 -377C1C1F10FDC78E1FDEAF718A2857C4922FA300C8D3FAC136BA2957C675FBDD -21E3A9E29C797142BA6D30FABB0D5E97AABB49D113A55C4838B253AB8D7443E7 -15596B3BDF01C88C17135A74AF78551CEB6B0041BD17ECAF89321E6948E1C531 -B227A1F071FC3558501BFFC842A4F8B80C14D9213E0633485A66F899BCB473D7 -3C72329610575B6279C781714761468C785E426DC9393564979B1D6A6D55AE9B -4954010208883EC964F35E8363129682AAFA2D40E1ED08A4A1DF27F3DB5474E2 -92B917B45D9473AC94EE40662DF06AC9D004541B6F88DF5AA4A36756620CBE83 -1254ED1C3C9CA39B09E0D4148DA552B00FC60FF68E7159F556998EB8A66C8EC3 -3B7842ACEE888BCBD1FA183BAB95B06B245ACEA49F8CC51A2EB01053E99E9A87 -A5198C2FC26E270961FFF61A093A084594E6C0298CF96B251C5F8395ACDA26FC -461E6DB774F6220F8FA04C68519E19CF69EFA73E9A1BDFFE833B228DC19571BA -34B7AC21EB2BF8B1876BD11E128F002AC9AD6A9785CBBFE2D5FBAC307BE7CE5B -DDA7C12820028FBDBEF1343638CE166E43B95E6518A83828AA3C3628779FB2E4 -CE32DED584715FD18C95D38FA85772DC8650EFC42F980A1ADC012ACD93B7E1E5 -FA6453179ADC6F17C94FEA1F4CC2EF6A2A975C687ED81DEB7111F0897742B373 -30720766409C534C5E0A42D7221337FF3C4C59BBD239518F3976DC55FDBB8C1C -8DB9CB4B05B1D9AFBAF0FA1D82B1564AD7FC92B6CB3582F7DA309403EB78916B -BFDC6F918E26A39755E5AD6394D985C92F7927FB1287FAFF2F60248236F918DC -2E8557C6805B01090A037E8D5C529E2D70976A9CBF3785F4BAFAF9923DB40756 -7B6CE8EE83559893E3930790E5917EC3421FEB042C0CBF6CE74F16C44FA08025 -82EDA0833C0486CDA66ACB450094BB65F54C83829B47DAAAC9E4CF115FC275C8 -6BE583008180F2E2C9B003712ECE32333199BBF9772A471EADE59355FF264DD7 -ADFD42FECCD00892FB545DFE555AAA4B273B82BD2740CB8C9ACD144DEEA94188 -D1AFEDFA1FC63557F9E527C00AE7D14762FEC2814487CB60E406F8D4A47365B1 -F7B0E0A56CEF011CC11345674611EBFB5A7C587C34F786498FEE4F0F999AF42F -D955CF2ECC5B64BB1C100310DE5B6C7D106A80FA4ACE0184A6E18FAC544EEDCF -307334E1C2A0CB6E488B21DA3BDDC5B593D5ABD6006D1E2BB56336EA88D56DAA -62DAFDDC379B06EF80E9F3661C6B7AA6787ADD06155F3DBCABAB6BA3A46C9047 -5D295774447BC007D5423B9840E2ABACB5B811B30ABFF547A8A6E2C18A92DEF5 -D30890D49388E80E6EC7626FE3236AABBF64B21E5525FFB7C802511129EBFAD3 -D1E19814500A465DA92054F93FF77864698288510AB599237D0DBE1EECF81C46 -F706515DF10A1D0FB06939473BC72429A42CE6E15BA2C97720756D80DDDC171E -7E8202D385C2E5B4A5A011933CE920E98A09527DDBF49FB4DAF2E736B1E42F57 -354C91CAACB68BEE8FDD10F4DECF25ABA4EFFC4588DFDB9E98640737C015EA04 -A33D5AAAF9AC4A7D288BC9D4A8AAB9B852516E215DF7614B10BEF003EE1D0572 -E4654DBA4D71959D403B936339D41C381FC1A206BFA6505DF3082D9FF767EF67 -437E8C2A14A8B6F0FB98C80DCC42A30C57C8AC3FE83570A1B4AB404374B85F45 -A1056E389A7148CAF714CF6DC26A04E3DE8E2E7FD26F6CDE3E836AE65E593A9D -3FA7A24A32E3E99A152009C8713FF8960FC93A2E49B8F442B81A90F98B99E140 -5F0E0253DE8ACE69F1248040510DEAEE069307FBD02B821D1DAEADE6C41111E8 -37A80AB702B8D79977DD73429695C13DF81ED3B562FF4C168AE03ECD24909A41 -22C579987CBB22700D1D34BB16E5D0B4BEDB4660D34EF5CF0A4FE507198EE14D -9FAF7C97CF769EA9159E1D8210B063141913DD402BAFD515CD746A7CBC061A74 -CD6D6DF78AA722FF543C5379A1AF5102B75C06F73E075BD8531353892E1733D5 -8143315C0C780BBB21D6954119C0AB1D4C89EA67C0AFDD4607AF07D509F481A9 -9045776F08003CB429316307E66E1F9490E8547FE0336BDD8B070290558E0DCE -DB08FCF371A8A9FE905E9C3BA4CBD4F12BB2F512838D395BBCAB1488C58122C0 -CD6D3634C0F6E193E2F2E8C632BB9185B20D94503E02244938D4400F0DD8FB81 -3AB0CBCF32E462A223F9680A14AC8876917ADEDCC9B181D584AA307CFF3B66B6 -F59FC840A9E8D1BE101AA1DE41934C22A1017A8AF69D257433C2D2C5A0474F9D -362A669B4044B3990BF83E8906C5B7E2B45D688CF12CC1FF38F2EA47743676CB -55FCD3C6261C6F5AF002869128882E39E089A6FA108195A8B86CB07913FFFA6F -6D8F8D5C9E897D63C174825286953B9DCB09B8475D0675E09C1D26286107E89C -C75F92D14002B1289A5E11F059F28FA27DF23FF395EEDFD5F22374FF67F0B60E -81D249898A228A6A89141B23918E977BA79C5F5E6CE84FD35F51B136D81428E4 -E4D205612F6DEEC1CE6AE571B30A33DE004A8F096656A3BFAF8BAE8A2C73AA53 -D7984D6777540082F3674304D2C3F17775BDF86A27563CC2BF95F190DB3E28E9 -FBD0716C0F1B0D56A96E2E870882F03A3E160621FB469355859954858C9CC2AB -06EA8F87EA163B9ABC176D704D3C17A37508864381659070B071B80C79D6D60C -7858A32F5DE87B1F818E78048CE81E229FD7BD91286ECD773147F94E7A184450 -D1060F0FBC5A8DB06BB4009B3F5F50EFEECEF8FE970E3FBFEB5ADEDE9EAC6A49 -AECCEB5378A9CE274BC7F25D03CF477C2054D313FD988A4D913D20ED3981CE47 -8674501E487FEFE5DD91CB0E5ED24BE1D2D45C88DBE1378B11F6B7076FE56BF4 -8E8925E65FBF23330B9C4A943CD96EEC06A6073AED304CDF520CD2AC1CFFAC7A -6B8D8FFB7327834C9DADF578F250A51BE64D27A2B65A16DD0204635560B47075 -3A054F7159EE483CA06345D3D55EFACD47AD32A9D7D7404ED0CB742A3AB8C47C -2C5CC71EA3E1405D6E114DD53D85C2350D46A8E4BDFD1667C65A8152D9F3331D -6235F40AE36EDB507325E21496725F3351C239207C0C4BBAEE2DC7D2797B8818 -BEBAFCA4FEDBBBBBF3FDB633A0C21A8BBA856D4A3119394FB00AD092E314558B -99CD5B138D4A42BB7B621DFCC2A2E2AD262479E878D8F26195A643BA0D13F9C9 -FCF3B6BE5774DE6F4564FB82BA3B2B9BA29A5F406F1A135D46DB10C80CA11E1C -39C9A74A18D8EEE86C85556F8B9203E00DE0B1A164134E48FCE7F37AAB98A79B -EAD809EA81192ADD3D3C6B35E521AC99E190262E5454C7170B081CB8AE338D09 -D489BB694D228CE9C05DA95297BF106A3B71A99A5F199F122971F5C4B0B9C53A -4344FD111B92AF456697E0B85142B71FA56802C392C886A408558A297EC3C717 -FB803CA1002361034D40420699FFE3C149800137EBA3AD99AAAD74B471038675 -8B073F692D278E0A088D3F51360C2C79A83FCDABE9963A4D636631310E7C6D35 -EF02828CD45CEBF9892C2761D934E07AF32BE74852C13FE63BD3DFF3619CEFA1 -25F5FAC01306FD99A573F0F5F29116967FFA22C9236EE8EB052488C4CC204855 -EEDB80B30838AEF66DD960389684231FAAB83750575E4C9BAE860D9B0F838927 -791AE22921BAF254FE561771B7A9164362D6BD462A82763F6D19737ADA1C2B92 -BD72443D7521795F9D3702F83B04BCF992667CA255A3AA539CB71F25F2D0ED57 -9E0B180D1C199211FBC17EE282E7CA9E078593E6340BA651AB949482A0760790 -E4C3F1446653CFF964B9A3142FF4FBE8C75CFBAEFFEEE1810D38033CBDA2FE9F -B42BBD97740EF0C118C7954FBE81FDDDC74608D036A3BBB75EEED4E1A4A56381 -0F57C993C4651E4753A27684D170EBC495D09202AC0CDC5F10267EF26EF4E7D0 -908F4524C91AD27F43737253BF0617559F2EB99EB26643D8C28B61F8968CEE7A -A79A818887ED9BC3AECE4A35AB15752A368D09594F93B7A741282DB5C6E42144 -EAD79AADE23733A43500563C3AD34E0421D1E3B4642EC1D70F0054E3DB6CC218 -FF930B11B1CCC3E4C90BC523D4635161C89CD9FF8F2C4F6E4127ABF479914610 -4D95589775902AE3993E1CE3D4868A1055BFF961CCB244AE25C76C4CE556B8AF -98129765EA10B35FFF3D24DE1CA68BA55E133084CD2562832630E302C3823EB2 -5D7293D0C760EC1788BA6BC9ADB7AF6DA83C951E0A23AD98EFAD64AD387F7764 -21320EAA8DD04EFC4C2BC011185DAC3DC1FEF1461F3F9ED515E2240433D855E2 -0229E1D5269092D0FF790539D2946A608E82E1FCA5E3A1254B27AA134C300FFE -C7C724824AE8B8436577129608078274BB69FB6A026D0CA48B97314F596EB375 -390574158057D3E1C3EA4AC61BEC73F81C706A6C7A9B42EEACD6A4B5C4E69FD2 -C68AB11CF02CE3D9B7148BAEC69F92FD7DAF6C9D772BE60AD4579BCE18396E4B -60EED65E6E2E62B283F135675C188F58C831B3A7ADCACACD39871EF8905B3264 -567AEEE25FB31D64C6596D60597315F1AD8F74E5577E6C966F8F65B001850D1F -39F0234F0478F6DB136F17F20262CC072B25202BCC8A67EECB03A2834136EE5E -8FDF55397F3572922DF82D25376DA73083419420003E99A020198ED0ECA44A72 -DCFF31392F59E14720BA027A5A5E81B3C32BE7DBEE039CEA50AFD5CF9CB9080B -3952949A3165C5AE1EF9D8C76E0C901DF5013469D55C8AFE1554A74D6C565533 -FD00D77FAA0311910C9C191ECBE1A0FE30A4FCDC3909D4F6322DE2DE90865099 -ABAA1A087DE9B4642DB649ECA28D40631EBA0B3902EA6D70F9260EA9DACBCE35 -8EFFA26B2E8BF4567406788443950D8A71339F595C83E28111FC90181AF60EC8 -9A7EDDE1989A2678B8C570F5D0BC178C4018626B9AC851604F03C98469EFDFCB -BC34589B59973E918756A2C1BB7D1811BEAA17D193DEA92EB273D50AE5C0FC30 -661B330B083311E5D971D70DE46E2239532FAC9A6D8FD913E6DD03F42ED6148C -4F04E6D136D41C24BD9B973109A9B63233E51176EE64D247DE1C5CBB43F568BC -DBD5A6AEDFB68E5A0C8DC465E9949A96665AB78F41132F96F3680B5A9A79DC44 -828FBDA04368F277C40F629961EAA9F3B253276EE252478A9F409C2FB6447C65 -37AB9FC9A216970D7BF6912FAFC92BA0C000A58950291FB3E47F0DFD493EC7CC -A99555CACEB7EC87F4250AB92E7136500138087A19053E9152B6F007B8D3DE8C -96224FF8D464BD3289C08AD1E05B9D063375F38FD42CE97ADAC4E5B83B8A88D2 -B2634B95A0DC0AE6A407E62D153BFC434B42680FD0F62F5FCF0818182F182D1D -6B9EBD47149F8506CF38BA61D8AE460A8B660F40DEFBC9243154E5683EA8D574 -8D48276FE5128F972D96E42D89E374F7D8C72E70F84F028263507BC96F6B2B92 -EF4B992CA46361BA3EDB888A6E5C57688198EF10A616F7DCCA55B4E1645FFBEA -C2201D5503101C400B147CA23A805AA95FF059120C677C32ADC486DCA6E775EC -23BB704624D3755E09505C395CC3AB83D68F10E2D6E1497BC179F3CA82A3DFC2 -38275D10D3253264BA9C32DA47C0088660037C7A789C1DAF75D0476BA9ED5B62 -CD30BA0E268DF3537F8298BDDCA16B1C970C2863B21CD839FF6B713438447A4C -C58C1F0ECE39E126AAC2353E31B6FB808253501CF26AA3AC48433D4CE5A946BF -10347C814A195929213655345791FAEB7986B1DD4F2B0C9E7116B11A4F1157CB -933B48B488B7DFE700423AD4FAA7E26F003B87B6255BB607A3A639830D68D663 -A3350CDD992B528E3D2176DAF79AC03F6455B1BD626ED15299042B46F03BB46B -992109329C6F67F1CD92A620FB4D806558D6CFDD75DE4F7D6C558CD5325302BF -ABBF40001F90CC940511F63F32F112EB958944E37A603642C0CDFC7941D9EC65 -F1F5B2805EC17A6662FABEAC3F1A7CE8A4958D64FCD57759F5CA294236B5834B -0071972DBCFAE0D89A1BA76FA1EEF2C8ACB12E45C8D8939B3EF1DA3970ECD2A3 -30AE415757A89E44CED997FFF9F6378FDB532ADAFB25872A690137609D91405F -4FDA7B432D432325F1467A7C85363A9E2825F86D5B9F9523E53FC5B58D82CB28 -90D43D172B2CBABDA71E5B83928A6271468C197108584BE45647AF5C9BD930E4 -18E321AE20B3D28980B1CA53F8B2696043BCC4C925F218B0AFF8E8C2BC1B85A9 -134BD28FC51E5F4E803761720601C5D9D87921116C342D832BB14EFA08032E5D -7C0C4F14F118883DBB1CA0313B6658E3BB5A7ABBA4970CAB64E66515031BEEA7 -F0311CD7DF8CCADCB38103DBB1D60CE59FEF567B2755D0A65100C8F8EA622025 -4AFEC5D179796C4F87808A76B3F420A228544CC12427AE7A5E2FB6CD76D4668D -BD5A22FF8161EF3FB20EE9FE64EFC4D1E466DEF81D20A395B020BDB7358E80D0 -6CCBBB8725B9AB973B060770E4CB902F429D75295D1E5ADA0BDC01D0DA7A4ED2 -A21346CC735F3E6662B87BCDED41C39EB2174C5ABD9C89A4A6554B3523E08BAD -F208FFE1095E6641C548DC0B7116851695AE8813E691347526DA61EC59DB43E1 -03BD503968825F7EA207E22EA04656780C15E1E9D0A00CF8CEEC4D3FD48A4E93 -7E82A2D0F952F5ED616618739ADDA48480DA4665526260E4269F135C89C2F28C -28B435A1A40C924B79934D6CC536A58D2F102CB46E4C3F6F5390008A7C7B5E28 -4044E385A5D6FBE641B6FB074C4E15DB9D25152E503EB7DB52F45913FBD962C4 -550310BC3592CF1C56A7E19A73261219812CA9A818856901E9F0FC46FA53FD67 -20A7AF35375DC845C8A9BC82F46C061F46233CE3F963C6AC49CCE0936A1813CC -F7904CBE756A07106AC3D9B58C28EB405FE50A12710C7FA7B4F6900E163125DC -43672E2C565C6959C412F7CC333F49E0FF5B1AE666E0770255C43E1779A67D7A -BD794057140D8D1478B7B3C43C84C2C2E56DCA12A1A536F80B16BF9C5244FFB6 -906F2729E0D6C3A6AE9A837CF39F81668CE7B299F4EC9825892A961935E4C81D -7A9FE5D9431283C53770E41DB77A70500A9B21D63B2F073D75D8E11579FF7C63 -3D1BD1D11EA3C49A594D1D83A733ADB8D887AABCB81C32E3913FC4B2DD1DFF11 -10C193CD5D5D5FDC8080F9B99C9B29A86ACFD94EAC9E052790D6A46E5A5E946F -6AB9541056CC23323C09CBA556F1B0F28BA2C30E039B3552DDBAC17B9311BF1F -648D3527E8650B3FC89CF81256E9A4A9054D9F1A9839BF7E0B875D25EAC8AFA8 -2B5663DAD7CC7DED3206BF5957291DF837535DB23BA63F9F7ACA7141E1490A68 -327E35FB7888C160C2D47BC4A7CD84194FF52646DF43AC83A51489481CBA4D20 -1E5094E7AC3EE66A5828BF1D87A530D7786577F164AC3D5C0D624FC6CF1DDFFF -C2 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMSL10 -%!PS-AdobeFont-1.1: CMSL10 1.0 -%%CreationDate: 1991 Aug 20 16:40:20 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMSL10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle -9.46 def -/isFixedPitch false def -end readonly def -/FontName /CMSL10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 45 /hyphen put -dup 46 /period put -dup 47 /slash put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 56 /eight put -dup 57 /nine put -dup 58 /colon put -dup 65 /A put -dup 66 /B put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 72 /H put -dup 73 /I put -dup 75 /K put -dup 76 /L put -dup 77 /M put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 86 /V put -dup 87 /W put -dup 88 /X put -dup 89 /Y put -dup 90 /Z put -readonly def -/FontBBox{-62 -250 1123 750}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE -3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B -532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 -B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B -986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE -D919C2DDD26BDC0D99398B9F4D03D5993DFC0930297866E1CD0A319B6B1FD958 -9429B9D40924DC059325D9D4CC0344F3F997A99E6CC0676735EBCD685AAC9142 -08DAFEC78BB41AFC2F1C219910BDF41D6279284EF600B69776CA15BC8A34347C -30783C52AFA60FBE3E353E2AE354CF87B558776A22C776C7A0B5AB5CE1F941EF -C2D9CAC37294BF407A671F10E4743BF842143F4F7DFEE643BA3BBD8BB9E3F24A -BCCF7F0ADF8BA500620C81033EAE8C4EF2C1DEF13AC575F1B3BBB66F093D3B78 -5412B82B67FFA087AF57182B2230F9F2137180CA58A7D9B2C822FF04BE6CD01D -43B2CA7058C7B953F6D9B5D6E91ECBAA5CDE1159B0E59C83DBAD96D6C8C8BAB1 -374EF652D10C0F3EE7104472C98DD3572AAF2D45A70BF7061447E21EE3C3BF23 -DF39C2D1B35B42CD5297BEBE6BC94F7C9DC6E61EC67E4F677256FED9064BD3E4 -B51A71B1D27CA4E5AA9E1D8080E6DAB5310711EEF87C40859FA935B19524AE83 -63B163FA8397BDFF443227FEDF7DB27DC35D89FB1C5E435DA0619A5C88AFC73B -89A2DF5E767C5B536BC7167A840A0C32BD57A14DE69A7D0D819AC36FF32F908A -5070F32983BB007437E3500799DF5E0AD3710A4C0000F0098D5BE99F2EB9C1C2 -C444FD9552D0DCA098A94B3BF176F511CEE13DB7EFFAED7C47B5ADCF8D4700F5 -7A5FD1B49560969BF5C44F3749370663A04776F749DDD7B50674D93254426C4B -EFE264BEE7810EC93784B7C01A7F29EFD92547E13A2C7851A2E709FBD5B87850 -4A44F08F56A542DBE072D2FBC58D9E6468E1AB858DC35240E30D31C7AC13D6C5 -7D2BB634BEE96FA0E10F842B11A789F72A333DD6DDCB1BC23227EBC406E50B40 -30AF0C48E6359AB0C46898CDAF1118E46BFF8B00F54EACBC2AC262AB898C42B9 -2E080C10DE923C1F7BD11CA700DA95F7E94C4C77EB24EFB7D5DD39CF43896343 -AD32237117AD4B4C24EF2B9AAB4228720C9F9EDA61ECC327D71641E9657DB045 -3E35C6ED9AFD4B88FBBC287F2B08E20CD064866D01062364E81E3594D85A3216 -396597A1DFC0BE35873C5BF3B12F115AE64354DE66EACD29A904A98FB23A530A -64D6DBD4198DF302D6EC7460A65E40609374E2031E0A3E8A3CB33C9823F1CEDA -6857069DCB4384BD963FE143AB8C46C2A6953B5EE8CA955E084517BDEB8A6EAE -7004A47347A65802F42FB1C3E2BCDFEED75859F600C521207B1F12360D8B5B5E -BCDDD9A8B43BE2886777EAB5A7006AB74FE08677A20579E5E0B6B949759F8346 -347F3AF2C105AF9A10341270B338AB4FDC2288B79D98A54F8457205DF24ED632 -B28F3773A7D9B85113CB50A9C472C537EC2F2AEC0243B6211664D78DE60EB3C9 -717285D76DD931E6BFC44864BFC7F99BFDB8A2954BF0C5712F21B490CD7E416F -12EBFE13341161A9053FF78435759B60B0F54888463C4B456CBAC7490988317F -17CCF703B1298BFF7B8F1002A86171BD2B7E9D8C4E20D426C132E7A9A1020653 -B82A9B932ADB1C912AB90997600AF5D56DBCE887D79EB994466A78D9040C2034 -1E537DA15822B32E17DA808628519B5D964B961125D6CE8158FD72D84EC1021C -68FB5F28CCC9FC14CA321D290B9A2F8A9196B06F787DC618E6C1957AE2DD8C3F -C2D2BE2A46B8A2CB9BA13255AA74ECFAAB942328B176D6E13C3810CF28B976BA -58E89F16B00B2BE618A07955CC9C46A95F5A07FB240D95452CE799C8709D45A1 -85994D7BAB6792B58694594B881C240F3C36129EFBFA4AC5B5074E390AB2E39F -CE9E366EA4E95A5DFF8CA2E144E2F0050F512414FBDA7A7EA24D2804D22FAA04 -C2261EE07DD605953453B94243250098753EC7FAF186A2BB5FD481DE92D3A6B1 -E03DCF5C2E2EB80A30D0569ED52550B5ACB2BBF67A86D4F4E65D868B2178AC94 -14C344582F4ADB60E79ED161C0B7DB7CC6FF8C391FC1B2A290B33DEAB127C200 -C309335A5601E10DA4BE03730AF8297EF872B08C54110804CE0FAD959F416B9D -5E13E390C820F540C109F6D0F71AF41B0587CA7450810019F8CAEC40CFC3C617 -5D0163AAAF368C1DDC966CAE0BC65A31083D01CA513CAA2A5D3FDD301A557CAD -148344C2463CD950F033DF4686BC452D6206760EDB2EB00026F5318440AC8795 -D1F9C0595F392BC030B70806C8FEE3DE6C140547CA3CAE9B4B3F1663CFDB5519 -6F2790055E57B004E48FDCEC080F8C8417FCB849E34D5C85CDE82D435089956A -C0F3E924EB2C4328CBFDA7D115BDBC58716D98B4F49A6F2E841AD8B31F2148D1 -34A68D8E23ED7AF5D891A520ADE49714ACD727EE708BCB6668939DCE322AF08E -53F071980E0077FC9BA5A10B3BF911664F61327233022B59E72F38B2A64E90AA -C858FEFC4476C42C6398128D10F889CB7E0B96E4D13EFE60CD99998388CCB554 -C7561FCCE0BC98152D9E4FB1D7AB69A5BBB87CE684CB2795F90A682210E75F9A -539CADFF715672E0122236E42A8F54DD833D4F99E672B390CB63849D911943E4 -CB0C6C9693751380E7ED446DADB9C7CD98E042FEA6E76E473AB981D8A5CED403 -9A06577BF4960204938151DACE2CB21BA653A580DC8E57500B172839CBDE3751 -8A48345DD78508B4D5B35083973E026272994D3D58C6BC0F505BFCF708388ECA -514F0DB510FF93CF4673EF0A19A89B0E08F3235BABE22638A843CD1B92DC72F6 -7EF613DCA9053AE8177BF3650C44CCCE8F1B7CCE6EE269F54F8857B5576BA1D7 -8403538A00B1675276C38CD38CBC7B73906FAA9A34DE35A9F03CE84A0E60B499 -CFBA23F6C2EB6580B07EF12D68446359FF50E039E0AC2186499E9B589B6DD483 -0D432890F26241863A182314369ABE41338B2883A7CCA07439FE96465A5DE153 -490D3DDFEC94DFE203CA50520AB3553F6FF5630404C2A2BCA0E65935210CFDDD -433842A96E7646942824D43D0F9F5DDA9195850737EDE2D65B769292D5427023 -AEB225160606F8D821F08AB9B33E8C30D492E1C57A3259B1CFC1C56C5747EFE4 -792D365BD95A08758383C496F6D2729EDD5297E8C1571C2711F65FD6D6BA0126 -BCC6FCADF50C3075B9339D9194E79A4377D728EFD1E597635425407FD3BF22E1 -062866AC4580ED0DCE3329BD884F5E022385FB0D020CAD3ACBB9B0F696C4C911 -8C26C714194A606A95441101F427247208E296212B4FDF1E68CD054122C64CD6 -C0CD1EE077F2630FC30DA75EA8C3DEB388418C004557EBE97A136308B2E8F079 -2A225D5684449EC17A1A288265CDC0A0FAE05DF0F03AC4C61B13C2AF9C5AEB97 -4E63BB904FC564A28601A9F79E43155F3560A67B2B49EBDB1399962A2C0F55ED -73FC547D024FE86F65FE2AB8EE5B65377F9458077B0C6D31BE033B258B87E1DE -2C9646601F49B17A69341E8064F6DF881046488C2FA69AA0F9BD635057256127 -C4DC77D9D71C895D3040F9E6EF7653BE1F904978749D5F98F531C5564FE02F4D -000DB6DF12C17EB6B9C13726B0DD1D8A23F5CA8B984A350DE453F808963140E4 -3248089231E94E9B298DC62B46610176ECF3B8A1C77064CA3E90480C27FB8B01 -5E06A2CC70485242DE5CAD12DBE8037433E39E978DCA6D59923C557FDEBCBAFA -48B435C528845F0B7BEED2323CB3622C19816F2AAD6BC7027E36BE571A1C8FF9 -F2090A806CCA9B4A869E5E15EB363C608EDFD82C88A11E6644978790A0AD0647 -A786BDC3B6F0531B1D5F01AD551C3C759EFAF72E146CC7BB125ACD1DD6197DC5 -2B3AAA053519F55E433569CEECBA8009C20B4AAFDE97B8EA362C8639ADB0F771 -0D7AFD709E4E16C1CCAC746A2307505A462F77B1B977F4EF3BC32CD87968D463 -C7B02975D3269F1E3AB3CB1565CBE061F928AB2943B43408891B9D3C6FF864B8 -FD69D33E79951101FACE7C635F8B2BD3F45C27F4E2F119C969F552EC2C5D047D -EC3D0C212AA56F51240DB8861DF7398C3897B8DD8F1B2400FB49197AED7803AA -FC07426EF806A7CB2DD05B8978996754E72BD2A3078E578191221EC40C71F050 -79257CA1E7B0EAACB2C0DEEF23C4B2BCA93AF1BB58D94BCA90BC12A50FF9FC32 -253C51DC821ED1FA42318788342A8C1812EB45E1A1AA66D9CCFE0D7A107638CD -EFB007C6A6BE3D58B81AA688D787F7D0553677EFE62A3E59C2874A88D5719E8F -9F1E12B507D39FF42589C1475DC5F0974B423DB8DBCBA2C04075518EF5CD747D -C582F0DEFE4F674617DE189EF2030FB38194C08D3FF6D0CC1969494D86A74342 -337F5A3EAB685175FCF927B27E00F69A3F0B5B65E6FCB9C310ABBD731CA8D647 -F87D8B2BAC0D46E4CB24290D064B536CC0FEE46BE2E0982DC832F17A8668A78D -313F9943C5CE466123BC3B80122B69278A3B61FD4C5ACEFFA8B62EB6A1DA2AEC -7A7FB0D4B1A5D3B59235430FA156F45CA682AD86F3FF33D94C0867AD1E1D7AD8 -7439A4E3ABE919C6E3DE041175E0E3A1F2A878CF7144ADD7091DC52E5BE98830 -0AB8869740D57C6013C92CF23FE175EBD5C26330CA8B83F1B3EA50228085651E -64F36D1E8B1FEC84FE96CD2BC8AF45198C9CD8388301B1BAE9926BD8A014CEAC -3F8D5AA5C6DD2232A3F2FEB58E86F2835FB055ABA8567A3E53D0D7DD404E0D99 -7F2D19678CF28BBC35AFDD80DA0F1F47060CBCEA4EC5358FA8B000C570169AA7 -6718FF6DD3EA7622AB8725FD764C2EC14E2DCDA0548EB94981931C0A2FBFE083 -37D342A73ADF7BD3282E25390EA45D5AE7052C058AD6780ED90AA5007669AD9D -839B78DBC708D312C5E109E7756AE6D7D6BB2191FE1B6EC56B0721E6A53C8CB1 -6519FB1F37A8F38EC33E4A5766672E4785475A0F8431CEE6D66FDFA4680BCB28 -4EFAAC29A37BC21D9B884F508738D5F0225ABCDF34CEBD4D173321E328F877E8 -590DA7057B8EC485BC92A14DFAA31A63A6244D1AF09F29F0E36C6F9CFF260EED -10CC0D2730237B4C7D32BFDD509B6E3502A463284271A3991982887CF56DD662 -0654E725CE1642E0816092D6EA59CB60244DE99E733C2C8E990EF76B70B20B00 -734092F47103AE3ADD001D19F588546D8F9E8405290CA23BB3D3FA81F034EE89 -EEC731F922E6F28BBF12798A0A4D6856DC7D1987829310C32CB81B5F85B92FA4 -3DBA34BD1950E4E4ADD08B54F12F923A36195790A7D91447E91C75DB1D17F351 -D2FE11A9158534ADF9D06E2CA4BC2F11E9914AE70550D52C5667DE9DCDDEEF24 -E57C9F372DE435F3FFBB3BD498BD0B56B1B53534CE9F74BDF113E06268AA1050 -CC6D925F17CE2F7AF499C5DA843EFE205E640079F47F5B5BA0F8FA27FB30DBBC -3D3F95DE3D72DA6E726F7D599AB903EA90506732D051B5541C5952D522F354EB -F8B4E8C34660F9A53F9299DABF9C0CB5EE6F0685E522042814F58A0C5B54E0CE -58BB142FF89520E7DCD0321598AEEBB393008EFC4774E2B3BAA16C714BA68DE0 -C8814BDE1B37E87B1F7D4E8177A23C793F8D3F6CBC6833848CCC0885D01F20C2 -479E8F80CD07715EDB2BA7139837DB3E090F2FF71A66016E6805C6CACB18BA97 -035C6F33D8CB3CEB57D55B07AB10FBD469B14933299737F2535C97643662868E -41B46920C640A039A4DCE141371BCA56E66A2A6C0FF74A4CF52A851291B7B674 -8B7B676307320B1DE482A28741FE51E8FCCCB79DF636DDD2CCD73F2B46C29C2B -6B32C6C58AD847A41486323E5B75AB58BCF81FAB2E7D794191D6C66F1DD1F742 -6B0D0356D9460AE3287B98D3613E576238C10B6D18D4FC4FF25ED3A7A85EEDD7 -5FACEAB91FB2F0E6ABB6499AE02C3B1E6D2032BDF5E1ACC575620FD8199058DD -499B758C1B5C0B69F930F3A4C73E2E363168FD7E03352DBAA3FAEB32B29C34EB -7DB8B049FE0C20AE7B36DA2F783F8AF72CFBDFC698CEC9362FB188DE13CF08B4 -830993A117A1F06996B000787DDFBEDA484266BF6956FB0B27CF5613CF11DF1C -2BB3677E8CD75742BE2DF91F646817E1EC1F60EE24AC8B116CA297F57CF6317D -0F098301800B7664C0C19D12BC6C85688F105D3C91F18C6166EB9E586980FD40 -1928B4190E3DFCFB858DCFB0B8A536D14B9AF13BA62BD71969E9141ADEEDAB35 -1DA0931BF97D7749C4F93577D4DFFE52B373D4E88D85BE4F9E87B858AB32C26F -D4417FCA56EA2EBD9C96D3596D09781E09AFFFB1B4441293EA965FE8F78487A0 -5B327A789E1104D30C62248A62660C3F5710E0DE61F6F5DF848507F1CB7DCCDA -5F4D645939ABBAE1472F2704FEBF7AE27D7075946A02E322D43DB7A48F75A467 -5E081127E8CC6C1F4E674A6A8883E67BF4CD67DC016F0734DB7D2D1CA01FCEE6 -DD0B05A18A0FE8D678524A936B4AC20E512606DC99F412B589DE60841A0B67D0 -82F5F8202C1C561A60CD6779FB9DB36D5C210973BC6460EF7A01271CDB1F1D63 -FADD31E847C3B1EB0B9D4803A59CF6101D2178B0C68660E5078DCE5079FCCEEE -1DBE1E9FB0ACC7C973CD013E06A8D0D99B73E863987676E852F08756EE0DC548 -D2ACE7C12532CF8A53253722C0AC57FAA8E9B95916E30B46A8481C6607CC8979 -012E32098D7BF25586677CF9349456D708D37D676AB9E72877A4AA616389EACC -D4568F515BFDA5F56938455FD44F42AED19E9933930F0BE06B999D82C9A1A37E -BBB23B6F155C8DF5CD9374D76DE34F099B42DD6DE794BF68684DB697EA5ACDED -49880D90DBEC3E5E2F5EC08F1EA04B29174D918F6DA252FDF531D7873BF74871 -224BCB8A5AD6D87583AEEB673FB02EADFE76CFB7D08ADD021FC30DDE27E77D7F -50F3B5D09196AB64CE919D4E991D84D1D583763D5ED14EF6B106399908DBAED0 -D3900D1E15205C0F4B5AFF9104926FEAF219FEB0690552827DC496C10556441F -60FB15A6D64B52B2F84C6E49DFDF59816D67553AD81ED5573B000FDD6519864D -C384B3D60EEF2B1BB5C1141764AD6807DBF37BE031D670AF8632BE22A7076AA9 -99555DE31320B458C792EBD69279F58EC7317B1A52D0E51E950D76FB2C254C11 -CF91B8EB98EA650ACCE188585E642D17A211DA2574E509EB4E87EBFE313CBFDE -51F501C45B182D75EBFEA3EC9B95691E097E46D792BC095C6B0BD266B097BAB7 -9B8ED5797C17FDDB538AA00DB25482823B875CCD6E5EE55A76FCECAFFE8631B5 -3E4C3E9EC1E5408A2A2010FF96502D1CB940350524C797A89A5FF8E6AB47E4D2 -80BBE24B89EC689BFB00B9C5B469620DBB2F0281B757FF3AD2E84EFD0CA3D456 -A481978D788B40C8EF363A41B2C85E0AE198216E29A17D67D0FB19919879EA31 -57B62FA6123AC99A36840C6432895DC4528BE0D2FB5FE4F24F5DE3DFC5CE5E57 -CA4BE5EC998712BE30C680B8DD1F730CED756221598A0A8E5C448800491D8907 -A80C58E0D78D4A53C7B651177453802785A39C887AD73E87908D1E6AF244C67A -9A5029E17CA9F1BAFCC5802E842C33B39275F046C809F2AC427279361B3FCA39 -154E1175EFDB43DCD748DC7ABC240C8AED3F4FD78FF4C7AA684AADCEDC564AED -B35CF787921E74B51F4BAF2A8EC4BB2C3A78D2CD697BBAF16A14236BF7607F81 -6093A211924ECEBC1AA68511F7D9963DEC9689E801CA25DB41B89782A6471A62 -92965E950E21D5E41CE5496D95553FE6B9BDD94424914A3DA9F878A28BCF77B3 -BDA77E647D03250DFF74A2D17CD59BCC2763171F0EFA759C453A435F0AFC814E -D64E3EDD354A334150402AC48A6F84693B2C10E91C67537B45A5308502E96460 -871481EB917739EB412DC4262012D9ADED07CA03BABCACDD04A6C3A87F4938CD -6EE57009BB556DBCAA1E208D1B2C03F01E47EC0826C99C8A8DFB89212193E8A0 -2B2865539F8B7888664DE8CD3E5A193E6320EE7E111EF5A3EB73DF7ED921E4E7 -A26B1B1D18D92D78858086F7133DF3ECC8A80E499C576DAFFA25DA530769829D -FC01632F7E18C5F481DB0006621F7DD4320ACEF939AEF57A41A11E6BF8A183DC -6B2380A390E5F3568AAA53ED30292C6B28EC7EC45C17F471229E37FB8C1E5582 -B480FA1B647B69280035A0823C512F4AA0286201B2C9B7CA85D5FA65648F1479 -C86882D06BAFC16E0BE7EF0F4E16FBC4ADED7F49A2DCC9E151E26F1502748B2C -0BC4FECC8B11398034491060133041AF08BF8EF5B1103852F3834F6DD659494D -4AFD896D3E85560664B0F1F031ADACC315BC6140CF38668BBDEC82C202890144 -64BB345B4866F14CABC63D744F3E158AEEB004AC1A550502C2AD5F9595170EC0 -BE4A0A8D1232E0DEDA7F829B0D1A599BAD2007F9111EC24F1E08022168C2C34A -B1DBC6A844531D7A8D21731C042A7B380A1FB1D6B82E6EA341B123F8CC078324 -95A5049CC0C46392EB9116A03FE0F1B6168D272D96D8281A1527CA80A16A7449 -F31C1948E9D6A0E6550B686D985786CB6AC7B58DB428755875CFAE0572D2FD6F -7AA794CEC2AF0B7099AFC1DA5B3ABB479A7530B8EB9BCE9688BCE0276BA736BA -E88737ACD9E781828D687114ED67DCAFD4E7404C7C0E924A9141CC27692BEBE9 -5E8660B935A6F18F321E0AFA5B606F67A4D8CDDE5B424E504D52B2CB8E831A5D -F77DCCA96FC7D75E24F2D44D897FBBC3E35C98EFC52875E149E2C583AF6C10CA -BEDDD89A099F97D70AD5CA26C0CCF9E65352819C2FA1174C157E69D48AB817FC -007ED04651DDEB2FF2D8D7D405B401DAEBCE6151353441860A41731CE520F75F -6FA578EAFE5631925738B325F8AF2B0E15A5B84E9E1E203119ADF574989F3B33 -84404AF0FF3EF287A226E8C9877DAAFB358E5F1A5F5420767C0B6836FFE901F7 -CD1DF68CA5778B4649759E1F3F9FB5C5748E295ACD163EBF1EFB64785625ECB7 -A5060407B009B0CBEF3FF5935CB10233BD332B73F9C69AF4ADF799CFA08EF25C -A6CCCA840FAEBBC99C8639A75667BF652CF3FC25542FA6D873AEDC7AE369BB1E -C15BEB51ACB928C61F97E45559FDC572003885B999B4B91F66459BA96082C763 -A9F7A5C7C7F27B9CFAE1E80ADA4570300158A71016DA3600579434AF7F35AE65 -8B267F947E13216E437A98485CCBC940389CFDB05BA3E663DACF32F21978FDB5 -18528E1CB7AE189E007FA0778D62B9D05592E25559747E578C17156BB507D6DF -4B4198BED9F33ABD6E93F7D084DB0824F0C351F8D820BD9530CBC821CBDB276A -8C58D133DB076D9BB5689DCA2257FBC741C5F59AECB0BAFF81E0B899291B6F72 -5CAF3CE6A729BABE19AD5E6C31A790ACE92E952E82638B6AE9C0F61FF3A30003 -22F75DD843E2317CBA51FEC548525A4C8EDE18D2FEA0F6D8FC00B33E44938D2E -88663593AC4D1652680D51F1DACC46413C43902F77790B1C2E266293EBFB9C78 -833A274EDBF9BC80D19212D2635532B935766D0006697A7EC775AA3657152D72 -53540266F89330E3E19671E73E4BBB5F9A716EB13CD23FEC5B5358C7E004F101 -6100FEBFBE124B765BE98D24BF2E89AAD4A27C75A3549CD3907BD582E577B1C9 -1543C1AA7625E5AC9AFFCA8BEB637E5EA8C2BEAA30C8A7741D954422171D5086 -07E87A41204D0CCBD3A22E2D5184764921F19ED5981C52B539B06EDFF7A3EC02 -DF85F0132F038BE6CA49DB6A4F5A17CD5FA0AEC05478BE9605A3F7BA1159A76F -03A38668E6F2C72AA7E4DDE730641216CF7B9A61BFEA6EF937A54F2A2962A320 -9498FD339342ECD80A0FB71DE820AE65B80A5B7A8E9196D2530B8DEB0A1FB8C7 -15EAAD601F6836A6C8C0605BBB6A336A523A6CAF13B064D04F48F002B579266A -A46A47426ADB627668386804EB7AA726E1D65249F6440447BEC02306368C6B9B -0C736C4E5BD2362B7C9F0F7540B5DEBF391141BAE24EE7995303C1967B3DA371 -E0E052DB1D5259725163265BDFEAD1798D71912B4C7AE63BA1CEF08FB8A15E3A -25D67D9E3A70A040AFC254086D02FCDA5BCC1EF37450BA967EA9AA5C952AB4F2 -64F3D7487617B261CB8DDA5AD34429E3474A5C12D7DABD9F7053B22935909AE7 -D1D554D0C24436476ED68B1D209DD7AA80A6A547E045178D1763D596A5CA7AC6 -4E38DFD247A13D54EE7F2FF5A3442EDDF7F4894CA301A05ADD6E9C5020076497 -F2BF7F15BC210DFCE1A8DB7DB5ECA33EC5A7D635C089620177BD3E1F981D9CBA -B1299C0CFB41F53253A367F7B05C110C3702C570EE29503EFCAB28EAE54FC81C -922A0A80EC12E1A5D7C191603CCEB1FC7F41B06F2D91DADB13716D2D1F6BBB2F -927AB0F59DEA31F198D5422989AF7AE03D5F4AEF146323F8977F79540DC4200A -89615E702B72127B7FAFEA8152B53EA8ED9BE3BE7EE935B61ABD0B9C3DFE96E5 -B1A47626E4B62D96A9AEA785524FE73F68FA218DD58918D55E8338000DF0F5AC -6ECC8E6ED15AF45B45E74AED4F06C132E8076E21C79F6D313494BA23EAC84742 -2F778B9948CAD5BA1D589A3EA21516EC56A5E40D4CC0A5919180C2736D6570CC -FC03087BB9333C11310C8E5D814CB9AE8EC2D2973437F8B80C8CF48930E228B1 -4B35BFF4A7423DFD51D881829038D15AA5E3AC6AB976D3549CCBBD59034F1E7B -A539B629EB8C2FD450677510A7056C1D6184C20AE04B8BE7525526C9B19BC64B -1B3F6BFFB675B7D218D58C8D87F4EB1A28082A923D404CC58859AE55F0F8F433 -3063E52630170B2CB806BC95469581FB149AC66F00C26466ED3E1BA6459309DF -AE6050F36FEF2453D0CDB3DDAED0FD1E5C7B21A9469E62E9CC09 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMBX10 -%!PS-AdobeFont-1.1: CMBX10 1.00B -%%CreationDate: 1992 Feb 19 19:54:06 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.00B) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMBX10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Bold) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMBX10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 12 /fi put -dup 45 /hyphen put -dup 47 /slash put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 56 /eight put -dup 57 /nine put -dup 65 /A put -dup 66 /B put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 73 /I put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 97 /a put -dup 98 /b put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 102 /f put -dup 103 /g put -dup 104 /h put -dup 105 /i put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -dup 118 /v put -dup 120 /x put -dup 121 /y put -readonly def -/FontBBox{-301 -250 1164 946}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5F00F963068B8B731A88D7740B0DDAED1B3F82 -7DB9DFB4372D3935C286E39EE7AC9FB6A9B5CE4D2FAE1BC0E55AE02BFC464378 -77B9F65C23E3BAB41EFAE344DDC9AB1B3CCBC0618290D83DC756F9D5BEFECB18 -2DB0E39997F264D408BD076F65A50E7E94C9C88D849AB2E92005CFA316ACCD91 -FF524AAD7262B10351C50EBAD08FB4CD55D2E369F6E836C82C591606E1E5C73F -DE3FA3CAD272C67C6CBF43B66FE4B8677DAFEEA19288428D07FEB1F4001BAA68 -7AAD6DDBE432714E799CFA49D8A1A128F32E8B280524BC8041F1E64ECE4053C4 -9F0AEC699A75B827002E9F95826DB3F643338F858011008E338A899020962176 -CF66A62E3AEF046D91C88C87DEB03CE6CCDF4FB651990F0E86D17409F121773D -6877DF0085DFB269A3C07AA6660419BD0F0EF3C53DA2318BA1860AB34E28BAC6 -E82DDB1C43E5203AC9DF9277098F2E42C0F7BD03C6D90B629DE97730245B8E8E -8903B9225098079C55A37E4E59AE2A9E36B6349FA2C09BB1F5F4433E4EEFC75E -3F9830EB085E7E6FBE2666AC5A398C2DF228062ACF9FCA5656390A15837C4A99 -EC3740D873CFEF2E248B44CA134693A782594DD0692B4DBF1F16C4CDECA692C4 -0E44FDBEF704101118BC53575BF22731E7F7717934AD715AC33B5D3679B784C9 -4046E6CD3C0AD80ED1F65626B14E33CFDA6EB2825DC444FA6209615BC08173FF -1805BDFCCA4B11F50D6BD483FD8639F9E8D0245B463D65A0F12C26C8A8EE2910 -757696C3F13144D8EA5649816AAD61A949C3A723ABB585990593F20A35CD6B7E -0FA0AD8551CEE41F61924DC36A464A10A1B14C33FAFB04862E30C66C1BC55665 -6D07D93B8C0D596E109EE2B1AAB479F7FAA35279ADB468A624BE26D527BFF5ED -E067598E1B8B78188FA4BCFB0B51692D07B0BEBB930C6F0997B437E2C51B876B -61A563A2673932C2045833FAA35DB22ADE12102335D5DC734AE3AC5EEE6658D7 -92EB62131E1DFBA441F53EFF9021D9D4C491F26BE8F54C61165CAD778CE8695C -EEAF70E3B20C64D4C2B34A084B5770BAB2A974E898F62BFE90F132A37E2DCA4F -43E13DB13C94DFA8ECE2B7374827AE168634FA007F8981ADA046CED3448BF453 -FCD9A4F194FA648F9FC0971734BB69CB73439CB0DD021D44A7C11BF295E81733 -4DFBA460FF3D654F9FB337E99E6D66FBA87A817EB9CA1536C84833870E3626DA -55D48DE850D3E6F6B29DA0E7C9D681283586F208DB8D58042E3A7CE55BE84822 -C98237911453E479EAB65AFEBA3F61A763B40E74535BE56C9D8D06DDF9441741 -5C9D9D917439368736619717FAB4F06E2C329AE0BA411F3FD522D9C33AD8369B -D7DCC9DF993778482F35F965973DE876FA19E109AA198A00658AB3F0D8E3DDD1 -08A573F2D525202AFC57E05D141E6C0BB811E1FE280EEA002B7A45BB363AD06C -318D320D2C81AA5DCC842CEF66E7DF7670588CB39C9F42EE7763A3A17372432A -173BDEF7ECCEA297CCDD76A835C36DCE9DB8F8CB66CC71B4920CF5BF055A5260 -5B41A5373BA6E4F63C85671D979EA5EC30D22163E6D206168A3827F465279870 -CA80E6632872F721BBCC622EE4214BF723551C846765495FA9921E11FE1A950A -53150C3F5D8595958A47E0B16064CC3AFD65DA294FFD111153F4F233BC5468AE -69585C16CFBFCA32C4B96C161F47B56661DF84FCD8ADD3EC086CFB6BB5179BC3 -A5469A1CFBC8620BC711F42D0D3139BCE4E38698D9C574450DB43B5A19FA6D54 -0368BA9F7A8DBF96DCD0B8968CD194264E6DD10A958846C278B8C2BAFE7AAF8B -44C84C955F1A89A13E62A054BC76CABBBF6296DE00A79CD7C8C61C70F127618E -9975B59A880685E126F57AD80F8F4D376E1B476BDFDAC868FB6AFAD9D694B561 -001623C4D9F55366D053B52F2B09EC08B81901AE0986C5350312E626006038AD -AC15FE313FCEE1A2E61F8992AC00CA7BB7F997707EA377D37EA6FF35BFBC2866 -A572B31491F9B80445685DBA5E62F166E80589F768FC95BBC79158C23B2F1BD1 -25816F1486A64F76D99A638AC0DC101FDF390811B3C118C2D972B2E7587F6F24 -7F1DB2DD922D237A7D18FF08FD665355CFBBEE799D3BFF11CD94CFFDBA3E725E -DCF4CDE4307E3B199D91893A365D04F43A5305BDD2538E28A0788E061F3A621A -B4A04E5063B47F0109C1693A284FA43E8F1EA9B68145FF51C005D3FA40713BA8 -1879BFC3CAA881B9D885A0C1AA8BB9A8C848963020A5B15F862E7DCC78F25D7C -56437215999EB78142C128C6CB1E6E75EBCBB1E4614E8516FEB1E68400C61326 -D9F9E8A41216901F77D9466455E2A0B45FF50B27B55A1E1DD4F243C92BA6B175 -8F7695CFA1E91CDD8651AEBA3D258FFABA6280BF2420A98FA7CECD552D152CFD -A8CCC94C032087A28D68332769DD2CB4ECECB15717C245BA305CB616CC72644D -C78326E77FA602364A7B1630CA0BD0282FA781E14282982C1AD13479B6178D28 -1CAA541FD3F4316F4FF81C53496DCDF5F86E0D7C870FFCD85B36C936B1E08D78 -CEF3823546BE4329B97EFA4E2880AF3361C0DD67F77C8BA6F1CE3822B7FBE567 -064ED0477949BDA06483F8DD04F891473C8FBF73A61F7C06B20FB8B5F0BF4B77 -1429190979A4BDB29D77E94D5FB486A93B8B61DBC84AE06B4E06CBDA3A942043 -9F9926F541DDE4E9B734A985F9054493508C5F7EF9ADE372C520840F15F705D2 -51826A537FD158C4105443E38116307A1D4608E9C6FEC3353F57E65E150EAC0D -B923BA82331D83E41C97ECAD6F8F32242DFB52EAFE2209B9F41DE483C8549B97 -407186E3A04011C8301B6C9A6D36D8170F40523FEBA5E498B8E5B7BB28581B5A -08892C2894316068537336338E46F5113462AEA9DA7102ADD13EFD2EBFBC27EF -00B38C25E4E23843C50C888B22BE1C76AC3F85CE148B7EA0F47D72E56726D13C -ADE5A5D539A8379887352298B7ED202D909C8BBFAA0BBE7CD378B80488333B88 -E38B1C3C8DD17F32583A642A1D0A4408B0C244185C1376364E723D83803813BF -106524811B9116A47F0A3205513EB80A4F798B330C9C4560F98FC3A2FA181680 -C83D6BA02AEB9E57310A60C39D31D5BC8AE28BB3171F90B69C11688521BA0845 -3F7D6E4CDB496E3F8B46D080156669BE81DE017A70B3B7D5EFD202F26514335E -E06DF49F24576733B1BC191480D8C4E613537A80FBB7C408E7562D31833E3405 -2C16297EFEA28E55E929640DDC8D9C12D15A89A03C8637336BDD0D712AD5A2EE -34012D38FD1AC70D13C3833B0A055B545F9EE98A463A2B3B424CC138AF6CA929 -A7BD80C3A804D5F80153DCA086B862A7D621B47F109EB93D67A73934B066B546 -BF15F27517D10CB8C83F7B319F423C16B42AA435231B9C4A05053D7109715804 -660B7052FAC3EF49E66AA763DCF07FD1AEFB5ADBC9913D3329AF36A7C5359038 -963383D68357C48B254DC2508706B1D5B71B66E2589214A336ACB11EA0E4070E -3F993DACD86186718E488D4734F024DB314643A9488841654924DF275A1A2221 -2FCDFDB677FC3FB49409A644CEB01B260A4210613C0AB3FA3BBA7CFD4CF2867B -B261875B9C592124D8A5609FCE7B376A39F6AC86E94F40587F69BE0E8B4C2E64 -DDBFADD699BCAA66A856556CDE4620A3C104EE29F9523D0ECBE6552A1B8211CF -66D12AFAA3E9611858D51B46039B5EF0F3E9A020A6370B34E80F83195A643F15 -86934B5BA8B60ECCD0D3C9496F8D32E70ABE513FCBB85A77D992E73AF8B955DD -5AE1FDC1CD972E81DF6816DBBDB583FC1410D2486F7479F1A466182482EFFE44 -DAC31E1F059370329DE19FE4629F33433576C1E3E6B49F122F2F7333C36AC744 -BA663E209AB384C9AC13B5AF8E9D0D7182D5F4D1EA874AE24DBA41DDB6586535 -8CA487EE4084602F3F2A7A46A1DEF17DE9B98728FB8113FD1BC2A62D3EAF7F83 -EEB13A260689B6BC369064D027601C48AF68CF0B507BD5AA8426833B11D5F086 -E0759BF00A3044F0719679D27D8D8AFA8FC303917255FBE6C1317702DAAB2C88 -4669AE63FDC111F7FDF28CDBADD14E9D82CB39340F567FFDFA4716CB99CED1C5 -871E005ED9EF2A8C3BD948CAD403F180EC8649FA7C4258DB0E1CA5F1ACA24DBD -B59A2D1D7D920103457822D0F03F7D4CA5FA2D944B13FAFE51C031FC9416E5E3 -4987815ABCD52F279B7E1A86F659576B57860004E6E22A6FF097760138E683C0 -638CA1E808E4B88CE859772171D8F864F99FA82FBB5909E75603C5010D49C62F -256EF48E28DB392A15716DCDEE0993D3C8B9D7A8DEE99AF3401FA9A39521767B -F04344EBC10A08F880FE13DB7E11AFE3372B8691EA9807B11BAE3C4B7536B7CC -B58A3DED042A85AE55ADA24E74A0A50BC5747F9C8E816A132CBB3987FAEBF451 -22FE85DD817E8E6B9DA980F189103C5E972614AE92FD7506CC61589B2284BC84 -A4486A73B619585F82FDE4410A3841729C2A26E7E6FD5052FEEAEFF792EC1B58 -0131564B3C5FF80F3FDB1132BC1D83FD8D0B4961AA68000BFB9A0989036BB0E2 -CDDB585566EADC55623BDEA1F218DFD343324776DD201CDC9AEE023DF5B98195 -AD23DE4BB8EC522DDC094D15A76FD38B85964AAAD1E2DF9513B87281F7106032 -D833B6E2019EA1E9D05C7AB6CB34DA376FD9BA187E8BDA5DF7EE06134DA2F577 -115F6E891601CAE2BFDB23FEB902E2B1A43F7A834632B6A7784EF9E9A659DE56 -5E7E66BD19DC11ED276BC0E117C8968E955629700B639BAE108F342BF38220BC -A4C110641D1F70F6843206711275F5C33A6100CD20825B2ECE39EBA78631E349 -FAAB77A671146B5A712B40F644B86BB1BF3EE8F75E49ABBC757485C1A53BD9B9 -34BCFF603FFF6AE40A641E9626B0F9259F79B06BA573D6A42DCFA21A7D69BF63 -E1BCCFE3816EB1247C9F6DFC07A59656D89D69DB5DAB731BC84B77EFE8860EE2 -AD317C5F30763FF2C1B9C00C0FD480282FC591C84D7E5AB2A795B1D2B3E50E5D -6061F96ADC97AA2DA0B04E96F8E3961CCE37109474963F05E9C15FDF55214DD5 -210DD9C43391D12018AE5480429C9D0738CCB2B0178A8824968536C99CB0BE77 -B649AB272EDCF07F46DE28AC2DB08DEABD47C1EADB1B2193EB614BC26FF58583 -B4543394A1C8DCB80606EE803B273D8E313179922EA334B26E58EDA4C2BDFF7D -3A7D83E0EE66A4FC9C6BC9863F8F9752D66CD473F28194B9F26D624F30FF8DBC -77A700D39436E16839628F46B0F3637AA4E8BF1B6F5B95CFECD5626B13634939 -C46CE51287BCD099E31DADA771D251961E311640C0623956B2AADBD1F18A5F74 -8DAFFBD0C0AD49F4EF2880A60AE0DF30AD1425B79DB0CDCF9472D2EA009E9829 -56EA40DF5941215E176B1AF92C6374AF78D9E6622CB915537EB9F5DD807EFE7C -9749B43CD46272AE2101C1172A5210A4F71421E75C874046540050485E27FC7E -C4A5DF6E3679343F161F3BDEDE5BF274D8B052224E987F4A135D2D8FE7F84EE1 -E0BF07ACF7C40DC3A9C50CEDFB0EB5EDE8FE341E696ADC8710EFA61526629305 -AC390632DE1B80CBE8B55B2A9600D8B94CBB43F4E0728C08B250A8F4FE484720 -E6A260E226D420DE06A87617A3264792743639A0FE4A2ED4D9627E78B0222991 -A583A5A87AEA5D695EBEF083D770C5771D7304E17ED5FDA30485E82FC8C41B86 -4D68C82CC51D87AF64B277E0DF3E97BD5887C7E1D913185D2FA7F29FF0BEC2BE -14A3E6D029DEA2D9DB4A08B5B3ED8157FEDA81F552EF0918ADCDE7580C48FD58 -B0FC972EE053225A5B2264685C7A14AFF0706B13EA016721DAE4F8525B8C1E80 -A3213A33114A3007B7EA5CD2B1AF43487F191D22A5C106D3BA83A22673131EE2 -5B370CC9430E2FCA3B5E3D181FF1FE29DF3A9E6823F243708D19260EC2BF31CB -BCBF8684B4E663F3B93AE10A636CC9E2F075C29F2AC4951E85DEE75B87FE2438 -C389B91443C821D4183C0C35E916FF970B51856FB04B61FF8A265206898EA5AB -CF60214736A9A0A9C320F462E7B6F7CB43C084589B88DF4217C69434107D8DFB -A9F3D9C248D26EC0F1225F842581F27265516AFCD19B9FDB23A18ACBEDA6AE5B -0C8445E30DA6F2611E3173B7E7A6C2BE8BCEE2FC8D688AE82CA35AA85B47C48D -A64FDC522636F50ABFC0B2EA41EA35D67B308CBF6C2A86B0CCB58A025DEF703B -FD186ED17A94B64DE3F9830621D11F0D94F518030A232D7C5927625B2B61F414 -ECEC88EC56CE35BD4AC7F7D4257BA661D2856B8043F236CE60FBAC9186E0B245 -9CA6DAA942CB5E4D5A4A59A48AEDE5EB78FE118F766FA9A16ECBB6CDEB641421 -7267F61338AEC49F83A9DEA6DD1F7FBC53ECF8DF0C6C2EB871518A94CD832E53 -1DA38A4390638D9115136C9D7E3FF7494DD7C2033D39D21FAC65512164664997 -785058E339CBD84ADC911F1FF4633667B7C172748F83235C241EF9083A29B907 -AC96C96B45CB517099E62B7E1DFC89390DBF51D02F1BF2A1AFD3AE38E3026990 -5E9F5A6FA9746C9E61DB1A6EB4F484C4EFCEC8F915F46E196ADBA0D2FDB82E3B -1A97DA40A76874B349BA4D480C360FEC74B1CC187C76128624D1C063D077BB8D -F3E50D3CB072C7ACA0F3346BFB1D112EBED706BC035F8C8A6A23474BC914E551 -1CA4FA8B354772352F7A0EEBDBCE9CBD523CC03E2C5C03084FD372DC9F7113A8 -8ACEBCDA2378AD0570714AD3879C7A05F120D18DC6C0AC7C5950117B9C8D24A1 -D59CBFEAAC8E439E52FE8438B59A7164CAF45C78E8396FE323FF38EA05B2107C -F20D2000F220EDF53987710F0C0E2DF4230391E545C2D21CC810A8E902323A2B -BA82A938A9221298D214BA068ACA55C690B7B7A508BD6595860E880F7AA9F030 -27E4243410CAFFD55BA49F5CA06A8FF416F194D3E3AB7192ACF871C7478DF987 -16540ABBB52520CBAEEB922BF441D940E813995D4ED3D8DD707A631707D5F553 -D73223CDE27A4699C2B377C319C1A0896AA544018FE978F5E65B24B278A108B9 -8F3D7FAEFB97C51F9AC0CC60BD9CC620B315C91027B83F0153BA8F7CF627934D -6D44536CE65F562ABF7A46DD66401FA9158F3B603ED6EE02C14B1919613FEC58 -8243E4215173307F4EAE1FDAB515F26419DE06FF2DF62D0E0E60563BCA2A7634 -4B58344AFFA0F104229A6BBAAB5CC149573A19C5903CBC58009807EB095ED97F -BFC664A073337252DFCF946620B1679778D6EEA5C1015B0F73E4DBC798F90AE1 -5CC47F90690314CDAAF1FA54C47C9DA655DAD56FE577468C6199C346CE0D5C14 -F3190325FEE8CD9F9545625F5F00EBA1B449F55FDD4E53FAE7C5286468677ED6 -2F324DB5A9C804C8A2BEA08625C37E2341E5C5A49C06C15F23BBBD08D56FA07D -2E6FDF1CCB9143BDD8EF3C48079B16324FA502C29DB5120878BDAD0A783CFF92 -19AF72D3844B77A18BF1D2BCE1C41134761176794957AF3B8634D9C5A269671F -5676B9D71F99E56EF7F84374F15099EB73515268827EAE0B114A10FDA6171656 -249A963A32C88761299004EC6848BD76B6D8D68379EB302D2528ABBEB85CA4DB -DCB6B0C376D86530F4FE8E17B93952C50D2136CDFB1E217748CEBF8AA6B46BAB -73034165C62F02628CA60EACBEE01864323CD45EAC63832BDACEE0C39BF6952C -A07095AD3D82C80E2875ED7B998F8D9F5D26D7416AA70E53760C04D2F07CF734 -E9AC0CBE98C1642B93075D96E35AF27717A52EEB4898F148BCD6F792194681E5 -F0A396D7E2FC5676FA380A34EFC2085A7D0A5DDBA1476D0823BB77CEF027B833 -A144BC9D0DDD83A6986D4153664226DEEA70796247B400AB0C53148D61BC69C6 -BA4C4A288ABD172909EDEDB5CE6494B4F86A42572D0BCBCF857A64A13503EC6E -4B495640064B9C4299C0B6AE174DEEB07DB173AB3CD0A00F03E9545386A3AE24 -717387668FD6EDFB94402E3512A7A6F14ED8F079ABD4E161D42B40BE5027E3E4 -22D8EFD20D83D85AEDA43557FC14973ABDA50ED56948FAC97B44BF6EBBB6DAB2 -E05C768D80E843837DAAFE5F4781812CE3364155672C77AB66301A94E2A9E6DB -85EF7C07FA61CB474C2CFC6A2F7D90962B4C0D9B95F391420EA0938BFA21461F -B979C547DD7144D2C73A0DB184D4E1152F82A559F09EBF4620BC1B9313E03FEC -0CA4C8D1EBDE10514F3ED772C73E76E67E3B20805A93BBC4E9646827276C758F -B57CEE6AF20227134072637C357683DE58A7830FA2227FA344860C2E4B332268 -22E6346071A229CA44AF26E180BA8AF72645D356C8AC2DD443F8C9E4775316D4 -F832981E22EBCC3D707DF08F12114D104341F83E27734D81A56005E5C0AA55F9 -DBF4FB0D4B17BDBBDDB80B3EAA35925C70B846BC4C49D0ACFDDAAB55280E838E -A962BB1FB63870089E1670EA0F1E6F810830E100D00759E16688AF88C5E832A7 -01EBEAB36927754AD34FBCF10F6B787B6CB1F90EE1C119A62E88B81BA82E71B2 -97ED389F742FEF4B76CE6A17D0516BCFBEFE6F7185A54397B3538E190CC19E2E -4CCB233AD9126D64977FF2E89C12CBA5EB2ABF6E91289728CEB3CF67950765BD -B6CB85DDBC55A6F452561F0AF5350DFEFAC063CE5F25C6F00C7D2CEF0B880324 -A82CBFF49C6796AA0C943440218E59C2A98E43C2D2764CAD05C0C5C4EA10F598 -F97288CCEE303179D86191444516A79AE6C4FD1E9E60615E3B547CAB7D471F32 -0CD1AF2B3F69C8C047FE1A01845D1F1A6EFED268601F87F8A92211BAB650913A -0A2D98053C511FA63A8B3813E2E2B3FEDC870C5E6206101C4DD70AD1CA223A32 -FB276691EDF2421D12A4B330C4BC655A1218AAF015A384B8057A71B8696FBC73 -CFA6A9CCEC4AD7B0789E290F483E96E741325E6062C5F0B37C50F75A81D00344 -966F1FFDB35329F1653AC58EEE4C4B9E97F89EE4A3DAC15D67B6FA4C814A0995 -7460E20953FBD68438F0FCC139724701242D7C45AD30C72141A695453D003D72 -AFC26291C1F4BF991BEA7404DD85C825B840301B9215060870B1E5177D0AF621 -83FE4365ADF6FF293B7F9627ABA242F0A3E4A608570E46682A0CCF1284961F63 -B3E68FAD31F3452B5ACE03F95505B3BC194C783DE0F8BF66CAB795BAC0544191 -4D98F68ED7E13FA2A535722B667F6DA5E91E74A01D815F8F3CCFB5B4820E0797 -3553604F9341EC1B735D9F96457879D61A216A449D7B8A94C928154358253459 -AF775289AD8E86DA52D05A2C58387ADC92B18E1F0D1C04CFBEE4877F49953FF2 -42A7654DC8812CB057B305A68B6C22C8BAAE86855EC1ADFF0B3E00D60C853807 -20B98B49E7B0A9E1583E685716F6C2CC58162127FC8558AB128B53554A679763 -512DC6999BE36C0110423659F580491D0071B4AC2374D5D305AB506B24E63E44 -BBD84371A903BF4CC762A0E0D3142BAF794A332B629C0C8F87366F0130FB6E7B -84BF4D812759F2AC831D1E3703177215908039D66CF07D17258BA2B34EBC5D68 -E86A5F0252A7FD1EDACB59639A56C710049D5612818EBEE157A773D8AF209CD4 -4A6816A6BA050D5C23B85C53E6C50CD2ACE0B218C8F87A54671E271EA0A8477F -4A1DD5D223C0C644580373A57CD67EF1CCF7FADAFCD53843526AA357F666B835 -4BB78097E85D4D9211DD8F506380056F03D9C9DD9EF63EE9AE3A5FF0F74C654A -EDB34C3E9894E6248A583032501A0C4B3816262300859EDDEFC8B4B095130B91 -A0E583759F16CB9E5B38C42CE172DE2DE760A9E994233F006CD772964A621DDD -686F4DE3DAA62A937ADCE746FADF3BEF3FC2F90C3661FCCCFAD07CD4C22A2F8C -4DF29BEC9C4ED7FB3006301DE829E18EC81C8B7F27EE3AEBE4292548C844523D -A6F07705F4F16891D5C310B62BC698014846F9887925163C732666B6595A19CF -4344B5391DC011EDA337BB0D00891E6CAA8A6DC61C87C467181950BDCF13A7E7 -BECB71FBD2BFCD3D93135D5A508D172C3F63394A741E1F6764735A61B90353F7 -B67797C681A1AB28131E8E29CD12906A9EE1E2844451FE9DD9B0228AB93C7310 -F2FC310DDABB8418B1C29DB475E42233826FD9D0800196D6A825F380165E27EB -EE33F99FCEC55AB289E5D5BC4B02DE34008BA722EF503608673CAEEFC884E36B -2D2BF1B6410DE582CE243523ACDBBBDF75A886CA62C634F99A8216AAC0B762BC -4312371C42DF685CD54923B02A5C7610CFBC2F1AA39F0FB7EEE423B787308DE5 -634071E08F7659C70A6EBB94826EFF8C817AD6A01B13E91F0F15F43100B0DB6D -052DB9CED475535E482A58E3528B50D66BF785454A17DA4E4280AAF58F6441FF -0D18F744E745FCD33024713DA26FD532E640E9BAB1195BCA469E9FF2476E9008 -AEF4A4A68B5114A7C2A29448DB7A9E93AD6B06429D760AAD16B48FD9D5395480 -36315FE778F795CD7B4F4F5081F8636FE81681E643BBE83740B8393E22293B6D -008C845E6B3B5F518B34337644792AC0169B793093D308641F4A4DD3DE51AABE -95E16160C170D0DCA01374D0EF9C0C1138AB40F2DF6E4E7E5C45C8707182F8DD -DD59586336662C831FD0228595D89E5818A85E6D2C461A252BC1A2DC5895D28F -C2CF0BCE8DE71A094B7BFB56A0640AF9274CDF166B0AA5F9E32C5F595ED7CECE -10F6DE434D4CE74211A93C88625E508546DD3715A18800E4829D27A0F1067F0A -31BF17B596F13E728FBCC9FC0EA5D01AA51B5CD8B76258FC9A283D7E7B8CF14C -80D2EAE16E5F6BFE3F773B6609BA7473B9431C7DF9560AD9FC6E4D64DCE17C7E -9AA26089E18C5AD0FCB8F1838E58124B0028B2C2E4D5CDE965D02195C16E968C -51714CCF9206576B6D07128DE08529C4D94A1E2986E9060CCBF3AD61C605035B -F78A0F954F3E1E5227526C47631375202CE7B71F014053C68652EC5DD89001E2 -780310E4BDBE74B38CDABB12B604CA278AF003A951F7361A607A3AF0E1CD8C8D -065668CB80022EB608FFD13A49FFF3DDE556B4F8BB7D8B379120AAB86D71AD8E -64CFFB848D698536EF379DF427309125FDCAF1F521A767B8722DDC88A64F50AF -EA8043686A2BF63A8B447B6B588ED2985C773661881ABC98E09DE56F7F1FA305 -78055AB3C1C99FB40A4FAA548BD9CA0B95C29D74E6A32F3058EBD42AC47B427B -98D24AEEBDC0F957EB5887100659B402AB542EB5EC0A4CD278ACAC36BD87798C -C41B89E8888E23552B06434635D39D6E4011F9E155D648029FBB2D9F8837774D -BB8A7D722A8EBAF520E0CCB55EF124E5E189BD7332E0EA5A90B10AB63FE405A1 -6A40F4B356482ABADD9EFE8E7D2876F5BEE9405EAA684BEFCD179271C29AF089 -097C485E4D7911EDA8997D29A67B9C225D592EE5B3B79C3F8931FD7B1A6E3960 -328E1E2718E7F999714A6439F2DD59B5FA553106F3CA3F82D7247F61020C7440 -F88FE379239A75D25FE3B3F20EAADEE28864FE249EE86664C792D92FB6E0EB6A -9D3F154EE8B06501A347761BEAE8929E122790A718E2389AF824728904A8D449 -8DC150E294B5C9F4607019120F7255944A9A8D269ADB25FA6CF19FC52B50FE7C -B86962C94561EC3386D0D54E476AE255B82A242DF5676D26242C59391D0796E8 -63039DC728F0787DAD489F3DD3F7DE89561892A5E8A38A3B28B7E942CD331E9C -DA010D80EE13169C73F055F2941462B954C1602E2BA63DAD5578DA5ED29F68C5 -50A869EBA6FCE2683FBF6A22EC68D25B306A27B79AAF8E889E82E2986A8088DA -7934ACB4168DF49CB75BDA561940C8DD8A7800E4D0A7C1DA6A23C48AA319FFC9 -3AD59846534F647DA0263EAB436564B6A501473795D2E5B5BD1E071292F958F0 -909A4247E8714F06A959A5FD8407A4B5D701CAAA3D7AA7931E091EADA1821DB9 -A795A21744000A01933981BC2C3382CC6C2878BE0F3C91DAD353C9182ECD3DE0 -C8A7B8921F87CEF6A6124BEA3D7F77A4AE68731C0AA996A9BFD86D7E78BC99F7 -E6B1BA1CB38EB0F4F36CE7537C3476E85123D3DCFE3B925BD5564705E204B101 -FD0DBF5377E44978B52DBA6BCA2780DC42620ADB6EFCB026C148EFDE93DAE351 -9388DCF162AD385FD4F9F3A671FB07570878A52DE86C00255E93B45D928449A0 -36A0E59C8881CC43A72ABF81819AE18FBBACECB668E0F062591EE485CEEEE60D -F4F218CB633F7A0260B4884CF2EECF06E5705A197D2990DA5D9A7456129FB40F -C0C6B3B6B2FC22D4264BB48337A98C375DFCBF80080DF4AA0753293E91C96FA5 -12A0B8136C7C4C80FB032C68EA75660EBD1FFB27491B7A6D984054D35FECA9D1 -5FCCE108B2F3C4C23202CBF5B85BEE7F0F420FCD74CC5D558A016874EEE3B5D7 -8E046B303D46468BEAB588ED948712DE467C5ED1F42DF22C9B402C596D24B72D -2F609E7CACDD293B5BF0C9553D22C47EA88339AFD06EB3AE466EC2333C1C85A1 -00CA808A4264FFC89A485AAD982CE70C5EB9070BE28B380BC239FEE14C455994 -726DD99D74920AFA174CE979BF410E72A22D151FD7BAC732B7BDD1A4142BDB99 -70B521BAFCA51DED5829A9A36F7FAE6E41BFA981FF2F209C9F3DDD617890BA28 -E2CDAB7E51D49C22F338ECAE92B418855FC59577F8F199F5E372AF73701CD030 -273B84196E718BA54284A26D724ABF7E698A94A47CE3917467540AEC57B31E4D -3B8691B200EAEE8444AD5BA8C24A602B7EFAFDE2EF05BE950222229FE68CF9D2 -7B5F40456B0C5A884385AE655B9AA57095B4A0B0199E7C787CCE1E0C1CAB4E18 -506587C792DC259D0EA306972DB6170F008FC9582D4930BEC21D5DEED3670071 -85EB62A3BA27A30C9245F0380F3FD20A085DD77661C3408378172F830AE09837 -8380D1C07DA549314DFA349E9566259888581E212CCABA00BBAFF7FEABD4F848 -6672980B30A1968293CC7E8A6D7DE4A5CFC7BA3708A76122A3D2552F69B6E79C -0D6C120A098404EC2B2B67E80DE56BE7BAC2A05FA3EE6B68596E98E3A997303A -D0A072D846360D0321F3F856A8C7007F489B82BE253435DE87C8163ECD0489E7 -585ECEC657A0E040A9C1FF28C94BE2B2471AE2C5966778FAA120DB1DE340E3BB -9164EB236F63D8663566C306F263A79D03FA3C26F0A3A6DA8D0AA119EF05A515 -CECB66F7D06EE72C00E2AE1363D5DA802AE6FDD5DC07F994B332332FC17A7AB7 -258A0328BEC8F828CD3833F6066DADB4B62C42FE93F07E35D1C8483D12D52954 -42795EB0130CF2A6A2600FEDED32D288DFFEB25FBA5EB70E4B78601A0A653162 -5F6A3D4DB999E0AE48E8CAB9E332048EDE4ED293CC62B7867F3159C28D6D73B1 -3A951C22096D1A77A68E37C2F6CDF58FBA5CE7D6B4E5E3FA78AC2B0845F7CE15 -A27B284DEEAB751B1088C9E190F4B90D3D9E068AFE56EB07ED0C8E332A49E8B4 -65570124F18665724A3E52A204BDB06D68B452A4D63F4B0CA4DFA3CED2FEEA1A -D86ABA5D4B3EC7943FA2DDB74F93D3D4A1CF559D2EB3CBA0B986E939137EE099 -42CB3160219BB791799DDB079A10836EC5AC37E12137FC33266A7A6273987E57 -C97EC1F6207AE4517CA2D4E08CA90A5DD27015C65D22DADC6D06DEBC6BA5989E -F64BB70FC214E1536882F72ECCF238CB5BE51A261CE55661ABA44D00DBDAE487 -ABFE21C5178A131B5CB3 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMR10 -%!PS-AdobeFont-1.1: CMR10 1.00B -%%CreationDate: 1992 Feb 19 19:54:52 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.00B) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMR10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMR10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 11 /ff put -dup 12 /fi put -dup 13 /fl put -dup 14 /ffi put -dup 33 /exclam put -dup 34 /quotedblright put -dup 35 /numbersign put -dup 36 /dollar put -dup 37 /percent put -dup 38 /ampersand put -dup 39 /quoteright put -dup 40 /parenleft put -dup 41 /parenright put -dup 42 /asterisk put -dup 43 /plus put -dup 44 /comma put -dup 45 /hyphen put -dup 46 /period put -dup 47 /slash put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 56 /eight put -dup 57 /nine put -dup 58 /colon put -dup 59 /semicolon put -dup 60 /exclamdown put -dup 61 /equal put -dup 62 /questiondown put -dup 63 /question put -dup 64 /at put -dup 65 /A put -dup 66 /B put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 72 /H put -dup 73 /I put -dup 74 /J put -dup 75 /K put -dup 76 /L put -dup 77 /M put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 81 /Q put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 86 /V put -dup 87 /W put -dup 88 /X put -dup 89 /Y put -dup 90 /Z put -dup 91 /bracketleft put -dup 92 /quotedblleft put -dup 93 /bracketright put -dup 96 /quoteleft put -dup 97 /a put -dup 98 /b put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 102 /f put -dup 103 /g put -dup 104 /h put -dup 105 /i put -dup 106 /j put -dup 107 /k put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 113 /q put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -dup 118 /v put -dup 119 /w put -dup 120 /x put -dup 121 /y put -dup 122 /z put -dup 123 /endash put -readonly def -/FontBBox{-251 -250 1009 969}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5CF7158F1163BC1F3352E22A1452E73FECA8A4 -87100FB1FFC4C8AF409B2067537220E605DA0852CA49839E1386AF9D7A1A455F -D1F017CE45884D76EF2CB9BC5821FD25365DDEA6E45F332B5F68A44AD8A530F0 -92A36FAC8D27F9087AFEEA2096F839A2BC4B937F24E080EF7C0F9374A18D565C -295A05210DB96A23175AC59A9BD0147A310EF49C551A417E0A22703F94FF7B75 -409A5D417DA6730A69E310FA6A4229FC7E4F620B0FC4C63C50E99E179EB51E4C -4BC45217722F1E8E40F1E1428E792EAFE05C5A50D38C52114DFCD24D54027CBF -2512DD116F0463DE4052A7AD53B641A27E81E481947884CE35661B49153FA19E -0A2A860C7B61558671303DE6AE06A80E4E450E17067676E6BBB42A9A24ACBC3E -B0CA7B7A3BFEA84FED39CCFB6D545BB2BCC49E5E16976407AB9D94556CD4F008 -24EF579B6800B6DC3AAF840B3FC6822872368E3B4274DD06CA36AF8F6346C11B -43C772CC242F3B212C4BD7018D71A1A74C9A94ED0093A5FB6557F4E0751047AF -D72098ECA301B8AE68110F983796E581F106144951DF5B750432A230FDA3B575 -5A38B5E7972AABC12306A01A99FCF8189D71B8DBF49550BAEA9CF1B97CBFC7CC -96498ECC938B1A1710B670657DE923A659DB8757147B140A48067328E7E3F9C3 -7D1888B284904301450CE0BC15EEEA00E48CCD6388F3FC3BEFD8D9C400015B65 -0F2F536D035626B1FF0A69D732C7A1836D635C30C06BED4327737029E5BA5830 -B9E88A4024C3326AD2F34F47B54739B48825AD6699F7D117EA4C4AEC4440BF6D -AA0099DEFD326235965C63647921828BF269ECC87A2B1C8CAD6C78B6E561B007 -97BE2BC7CA32B4534075F6491BE959D1F635463E71679E527F4F456F774B2AF8 -FEF3D8C63B2F8B99FE0F73BA44B3CF15A613471EA3C7A1CD783D3EB41F4ACEE5 -20759B6A4C4466E2D80EF7C7866BAD06E5DF0434D2C607FC82C9EBD4D8902EE4 -0A7617C3AEACCB7CCE00319D0677AA6DB7E0250B51908F966977BD8C8D07FDBD -F4D058444E7D7D91788DEA997CBE0545902E67194B7BA3CD0BF454FCA60B9A20 -3E6BB526D2D5B5321EE18DD2A0B15E53BCB8E3E01067B30ED2DD2CB9B06D3122 -A737435305D42DE9C6B614926BFD44DF10D14402EBEDFF0B144B1C9BD22D7379 -5262FEEAFE31C8A721C2D46AA00C10681BA9970D09F1EA4FA77428025D4059BA -2988AC2E3D7246BAAAFB89745F0E38580546045527C8779A254DB08DCC6FB9B9 -0E172209FBE3857AF495A7F2B34BC895A39A30F903DC6E3202D29AC110D868F4 -7184CB78407B8B9D42F6375F67FD4B828592E4A977B9E71854D143CD1A9EDCD1 -767CC2929E071FBA4C3D17500E28A23F697B5D5CC68D5F56EAD14BD504E07182 -3FDC12F5404E74EC1C02AF00C1A6A17F958770ED4A024F5B3644DEFB61F2578E -56013D0B4E7CA3AD255E23DD63369A921D427EEE0E098E8148B16E8A5613A8F8 -A5F1099E15AD16EC554B644DF306F0CF3571055A81F1B464529DB49E919F88E7 -581066BEC4765E31BBE28C245BBF0B74610DBA30C63A71A4F3B60593A6B41C6C -636C980828CFE9A3362FBC02F1967F0F770A4790F90DEF9D56E0A76B0703FC58 -2841E6E8D984FB476D4FEB960FFB6B386EC6CBB9EB83704B0AF63F38C77090A8 -DAA165E6C6BC86601B14F8E9F504A9D578AF05128D8C1BCEA9D21057958D5DCF -653026524A2D101334AA3DF02A3CFA410836E6001561C00FB34AB04FF97302F0 -7CCD024F8C61577E82FF229A45F7FE22ACEDD95AE8052044A41EDF46B8F84346 -7275F5423171DF88188EE93BCFE0A84AE5C999E9C774A32B7A2826CEA8A8560B -2F61A42F967BCBE2081DCA5547D9EC53467ACF8A6AADFC54CEDB7305DD661ECC -3FE33D8C93D2425ED57BA83F360A384F6B94023EF8938DC136ED1F66CDB618EA -F40377CDEE0F17653E011F5CDE11C81A3FA5F7168681C02167B275AC0F73EF89 -521A152823FCFC811C71E5D05D99094EB69E5724B34217D101BAA302B5BFDDF1 -4DE66F7887BFD458C2A97A835C72E7A6EC2500577B0B057BA1B4773094EA1954 -589FE5B1D1B4520FFBEFB6ECD015B606A244E605E78D39EDC316D97D99862CCE -898341583D28F141A02877B76050B07694737E9F107F153E5A5C7393CD479A09 -114F07D12DE0185B971BD526301914EBAE20A38DC804C2319EFF3C8C4186630D -C91141528F408EEB02C718A0A3E0D39D1C9853F71113AC07DD209828B4873031 -3E7A4E45D95025D9C558CC0C313BA3333EFCEB2D95B7BDA88C062E5243DFBD99 -744C678DF4AE3478C68B4F7BF5C52DFD8A81DA0BD2C95229BA43D15986717CB8 -A925638049C2A15A6913B9819B3642F68A07C4FDB2552C97D29211FAE2F16E40 -076342D4C5A72E0D5185CE8EFB7A8D87D7F345E776512E8B41609794052B9A08 -87EE0DECF203189379B9DEFB8DEC9585DEF2B44C7F64B4DEE827C74B975BD1F0 -82D7E511A5A0FEBD52702F7E68157B509F303378B191BAFFB4229495AE65C558 -D72D9AC8286E61633B29CF90917E4A01030D6B82CBF263751BCA8AB219284B04 -80A8F4B34D0592EEAB82D64F9A5EB6A08A6CC5A7F3D3EE2B61710DB386AEA658 -7A059E9633123EFEC39FADEA37C4205112063F7BD3D2F8319A30DA796E55BA23 -00DE2B3C15511F87044ABDD9DDA9247B5E785A01A05B39F1A395E36AEA4D3D4E -ACACCB99E99DDB1AD1329069714FF050311B274E495FFE43D33DB3BE958098AC -61150EBC4F9DB7BFC8F6C81047DF0BABBBE67970D14524C82334B693724A0818 -0007E4E848CE4AC8F07E72F02D74CC5C06DE0A67A63156F9567DEB913E874E56 -B993FF1EF6774A9C582D8DABECD1EE1D1731457305A989E9BCCE8CCA4872B3C7 -7635D840A0FC8FD9A40CB7B2FAAAFAE3274A2BD0CF7F681E877830103D2DD3DB -761F3D925AED45E0427BCCF205201BF0DFC16C0109A4389F37F25AC6E4E70C85 -1BF6A47B91F62079EAD1D983BDD249D0EF82B21F89FE58CCF2612BA50EA48901 -6757149BA3C3FE22E61F80F62CCB355082A71F1C85E8819E71E8997CAD75ABB6 -070F0CEE40E3A9CDBCDE24D59F2DDEA887568EBE585EA8D40BB4D0677097E73C -1C76DE3BD95B2BD843B1522540C5CDBBE4E1E6FA4A77F93E724F4942757B50C4 -40E316CA4DAD1D9D36823BDAA73E3BEC72B03F6DB2E99C89D2C3F840C15CBBAA -0EC7330D23A3EC2780813F0C1F56C891FC040B958C7861DCA654743DB8FFCE0C -EF4EDF238CD820A3EC97CA497B2C2504E43B9F29707D7F92114E8053CE90C494 -4C3E681028257FAE5E2C60C3E1A33E40A7C5920A8E6FBCD4686135296590D866 -1359BCA5B650EF33AB7582BC61158A573F93C4ACD4BE3D0E36EF1A7683B85438 -1FFA47955F8C1EBB80BEBC9427F239EFB50BA42D8C72AC0F77A511AF3832F819 -FC3576C4A28B6154B8B14B9B88A84B2E9DD9AECEC59A9CD717151FAA26CACA64 -FF6B2A5F561F77E9DBD2285695F0B1DD8D1D174EC5ED48DA7324EE88698105B1 -E28FB0EDB30067AAAB1AE5EF6527DD1A83DA04B50E5E2B7F2A63F0E8F924B2B3 -734ED216DFF4E41E2C074741FEBDBB01A103B5A68961A12C571A0A35CEDB11E7 -DB6C9046AA97B45F756EF5B32CD3E1446C9616BB8A7F57308679AD7E5368648C -37F5CB0CB4C95D49C8DF2D30A8C17D8870BE3C4D9A077BAC5EDF794050C793D8 -D26A5DBAB2025FBE4841308D5FFCD592C37514D1EA9F7286EE8789D41BD9E38A -905038AD5FA8405AA7568F9B34F43DD17FD575EAB5067147CAD8E9C0A454B292 -74635B10585CE8D8F891A07360DEED0DAFE9836B006C3ED2B6E10674CC17CD8C -9A862C5C51EFEFB1AA02F313DB95969B90714C62F32BBE3062E2D805989EDA55 -0684402A5FFD3B330B194B1EE4490D05044859619A7A6A7AFEB4909B63CBE907 -34CA9F2B19D27DC59F737344E1298EF87FD4210D08FF55E143319DDDF5E94582 -1FD4C58EFB00CB9C840ACF598F300B9F6BBC4C83A89E7CBDE9F37C0EBC924777 -9337FD42AE2B208FC6CA3E0D9FF9AA07BF7BB68ED07EE307267BE7547020AF1B -B3D65F802A95A69A2CC366B51AD5771EC679B23253F21CDF12E8584ABEA58D92 -38F3B4710D434F5F967A9868BCAB5C4B57F5E1650356F9509050F03FAD247F06 -607D717C4C183CE793BA995DCC37C836BC994465C1785517466DED4A2CCA2AB3 -32F2D92C7DA918D720341298C650B4ECC780A457CF6CFB2120313BEE25A34AD9 -3B2C2B587AA791104E38D27C117C3B4255791862E6750FEC3C32A5B965D72FB6 -E333DBAA452661F88B7CFBF442A9CF467D01B1AEFE817317BE81CE3479E17E71 -6C24D0A6C08978B3DB9EA09567FFD14118259E858E88648222DFEB2A655E0A0A -98F08F3D13539005E85DDFD0B1CA60E48C0DC80FE0AF9550344B07548E9B3039 -E9ACAE903B7A3AB6FE24324319DD792FC5140A2A368D233140DA5690D5A8DE57 -A42AB04F6E9D167CC3D0348FA7CB3EB537AEF89B99C7C93F398C9360A0B1E2CB -CC7E403B1E439CE040F958BAA50E36980FB3EA7F789FDA23F4292E566BCBB731 -38BCA4A234E2A205D815FE2A450DB6586D56E8C1AC62A50DCA49CB76E122D050 -E1A3413CE5BA8BF96F34990DCA2668FCA06BA66D9031AD98650EFF39D881929A -28D99CFCA94FDB163F970F29F3A2617F83F4894EB997EA7AFB67A6293A08E00F -37D5A50FC0C360BC4B7F9C876A6351F9D4B3279C1083D6DC79F5A63EA48CD5F7 -02FB3C581F446AA9F19603AC165BAEE2EAA7B2574268947479540B5801FFB122 -AEA27CE208AE86BFE14B8D139C16ADFD5D7ECED40EB0E258B38E509A8A1E07F6 -EFEED540300ED1EF27AEA5A9B1B0FCF027F626B7258F4485B8A17399188CEDB4 -8CCD037D55F8EE4BA5D2E876DF7083409DCD95F644F43778567B61F3A41894B5 -485A87B1381E9E98C713E2BDE4594977B85C7A4F58D542C634F9F76B9403E23A -87D1091723B30E53CBB97A1406EBB78A7E06DA949505FA40F0D5CD0675EC4B6B -207B7210210E7145ED707377A9A1534FF7ABD8395083EC23928A03E3016F636D -1697B161377879568A752DDBE939BECABDE106790248103F1C6D75D474584F85 -33DD684D3E4927EAE6DA1C2020EB78B226A43708351B8844E4A491E82D018AA5 -AB46821A444373FF2CF81F996193D0C6AC98E2302BD0D7909BE77D97F1A6CC58 -959CDBFE69014EA8F95224F2D2EC70DFCF8A38EDFA77581CABF0921B863A6544 -24740A40AC91E315E97FAAB8D490AD44AE6805A9C7471AE945A40886A2DA1F03 -7B94629ACBFD5C307ECACB6DE6FDD477F439CDBAC935A94679F037F1FD6DEDA4 -F4EABA6C9837CD7679DCF343E823FE70D065D0379ED0EA0C51DF0700B7F97775 -4EEDBD920782FF119223FAA23689358F35C8A68566DA0D9097C6D0FBF163EE2F -656EEE4291F0DF40C5F4910DBBF3A9A33A0B349A2FF1D01811857F9335FF04B6 -EDDCEDA0172528348FED69047FFA80E2EEDB6A612082134CED2E167A061EB226 -CAB50190F731B40DAB9650D4BC581BFEE93A2CEB9E9BBF5860760405127A1E3E -7FBEC40343D0D2E8EB80083B354C095C483A8405B7BC144FCC23E8F25E745A4E -8C527635AC995A1065A7FCFD805C6CA7CF611C06845EEE14D07B81E3B404E727 -20CCC5BD3657D1575949FF993A71F5F8C5236135963F13D8C09B1F3B08CAB6B3 -58460385AE220AE727B0CB9C05020EB678240921E0735D7A28E6C17CE22AE05E -6C9DE888DC5D3E24C60BB94289910B3723F60A74A8B48ADD5E03B6886044DE90 -69236204BB7411A3D9119333D328F3A7BC446AE7C2C4C529D5E3D501EB99C900 -D040D670DA581CF03FE6243093192F5E91A13B79BEF60D605A2EF3BB93B569A6 -9C533A1AAE2CC70151A0BB5992A5B8269472E626D299F66D3DC25952AD9CC205 -25572F56F774E156EB78B0406C4DE584660E1AC7E629DADC0BC41E725BACEE76 -FE217A7B0190A4CB69E9F32F4F7A184BF53EED2B1659DAC33A2EE695A88D9F07 -D076E3ABCEA448A576DB7B0C5549A5A2D63710141F4E539DECF167EFAD871552 -7BC24AE52DF04152173D6E4CA827DEEDEFB7E9C3E72B5934C5DF97BC1EB23749 -F776539AD43E9200A04341EC0594EAB62A0C7050DCA43945E58C4890350F3ECE -5BA67C3D716D5360A5C1FCB6EAE1EC00D59B46402B16B14B821EEAB4758701D4 -4CECA59735D67B099AD9CC4BFF50B846CFE14E35E4D3D1F5A3ED2641ED940775 -0067986ABE6AA117DA321122636AF7FA88AF53A473BDC12A4844F46F43D94ED9 -CBB72CF2CCB37469C2E63661BCA5A298D5E9C6BD3D41853FB4867DF938DF0391 -2F7ADC04FD1B0D6B0D5478581D4A2E51BDA015A4FAA53378696FB50A3297DD3D -20C365B963BBEAC22789E0073AA921F0640F63DE0833764999F02B66E800991A -438223368F1AD8FADC75E2C5130F76148FBB0ABCE3B1270C6F1CAB55259B5290 -A10A1CD5419F9254ACE5834A4B8A71B8068EC21E6C4AFE9E790C74EDF7411289 -3AEF976BB7A42A7CC1AABE4634CC1700272E6B272BC6CA5F1549F3172537FED6 -C4047BBA4FE5776BEB53E8AA82BB17AB4796C1F91264A7B7E95EC14C0F74710F -9E9CFD51DB71C3CFA152D6BAD9E60B38D688C7CC5B587F37BC2301C2938DE2E7 -88E1607E5B0CE6AFD63989315A9AE3BACA1E0C0E0F6CBAFF02685282033A7532 -3E5B0AFB7AF6F4E3FB5801D175D02551F9746503A2E50AE9AA8AB56DE79BDE79 -74B4550F3890818AE801957A3B6A822614EB8D12FCA584EA8C41B814D30856A5 -97C3ABB9F665D1B72B8D19C4D2BEA46AE1332F8BD2A6FD2C2A1183E48F62C4DF -4175B4CD65A9B145D400D1CAD7E00D0D154182126764BFD3A267F85BC623A575 -92FFC5A063A9205A02C89CA4B40C4D489F17D383FAF081A3C0B2C94E21BAED8B -1D06A4495F917C37F8B04070E9A90F60AFE3A8F0073086F00C5A707A96D4E1D2 -BE5A637EC1C614997446262573426452FA5872FF661B519E24A34E3C58D4A07E -BBB6C294D4DED3EE01A853EF8E153D905B0598241F97301CA600C09B7D116901 -77EA1F6C40CBF7CAD5991EAF92890305BC710270FBD575B626A59EBEBE2A9A21 -D02700440C57557225CEAD5FC1EBA1763746A061A7F4DFF5558F6CF9160F7CD8 -7C84BE7407ED508BEB2338DE3C5207A7804FF21C4E0FEED254C0DE812FC8DFF3 -4B5B890B24BE5AC7C00DC1C193C88A6B33A442E184B4F5EFF79F4CACB8A56DC4 -05098C620D63A0135F8FE2959A396398A421FC16F8AFF99F702C1B10F92ECFC2 -2D86DB2489887879926E2AD34DB4F7A9CC460E12812C24FAB08ED0F2C3DF3FCF -AB41034C07225F20ADA5B5AD6AF5349319D3F937DD64B2E0A0887B880BE636CD -F814C498584F19BBB3FC146035E4EB4A3B7EB436E7713D968B24840EE00C019E -D08263764CF0839260BE71F875E5408AF4A8AB1603F7F694C2DB705F6E13E1C9 -4CCB224D0E2B610FDC729EE8E33366D0AFB0A014C3AAC6B915C2268C27A65624 -261E38226363108AB1C12BA960649782D0A02F87404350EB7F58C6C54463C1B1 -334F936DDA18C96B577D4409F18E63A79F708A816096A6FA1071B1FBBA3DD470 -C00F032534140440012988D81DBFFEDD0F6B02827CF76A92F638A685BB1686E5 -D0624C445A765E6527B4D2FA2B8BBF035D9B0BEAA0CA35D937FA9B4A79224387 -CD974CC0A052A5C78C4CA12379413303DBFD11DC6B78507875E6643D36679EC8 -3CBB213B5116E5A262300890D85018D550C69365D717BD3AD5579C906F8BA35F -1C07EE6B17F394FDEEDFF5340A86E28FDA9ABD8803D832117A74BA868326A1D3 -4004DE8942437EC0123075F2C6B97B306AA3C806FBCE7CAFC83C2CBC77E25C3A -082DFAD7D69D36ACE654CD17916062449BDA3C3AF3806416B16C718128326DDB -062CC9FFDE6FEC2D0451C4994F5C681A18D7E5310917B2994756AC8FD055F7D6 -92FBD23FF685754DC09F36AD98201040626C381FBC63217DDDF511ADE6D13101 -0043EFEBFB8C49652EF4FED438B5322D83C6B998BB46BD5B5F31BA2DADD76B78 -ECB3D44A2AD40518C22914CF53AC408E8015F2E828F6F4908FE0C85DFE30B8AF -7A1E91B6AC7E25BE17F971DEE8271DF880E440EC95E45A6C909AB0DD6259AFAE -35B3AF9B04936FCE351DA6D244D34EF22D0B8156A583845423E93A3E5C827287 -EEB8E89E19E4FA0D6406506B73285484A75082DF8E0219FB5543B57AAF63C47A -0C5616682F22DEE96A8CBC70BEB556DF3E719CE0E70FEAB87448B0FBF45EA6E0 -2006416E39CAAC51A4568736D8F0270144CEAA8CFF832AD16907E09E49444BC2 -80306B769125A50595838E76514A7FB0F1392AFE209D8817FDBCA2DBC8CBF8C8 -5948F7E471B6B94D7FAFC382B02824888D3C5860D1AF18F729678899932A1AB6 -A6A7A3FAC08BFFEC6FFA3CD9543D36AECD2AED91B0D8674EBD6A9728FE8BAB6B -4D3E8E175D0941775B3F96144DEA873B48F3F6B7B6A30D2FAB960AB555AA441E -69DA76ACF6894AEFF47BE6BCC094E42D735EC1B9D65474C31F0468FDD3CEAAF4 -333F60053CFEEAABF43569FD1C216FFD77EDD13C344A0024CBDBFAB9CEDEC95C -115192A65A818C166A5C4441FBC0A1379D0F3FE58922EE49BB91857A03BCA8F4 -0067F324EFA67755AC0943EA80D0EED33A817BCE9D5676F9963844F6A2DDA48E -C9B3D9B1E9F8CA3FF805CEE70807B028510D0AC5B13259280021D06260FAB24A -0143CFCEE0C3FDDD6D817C717DF925DF5022C37A19FF63F77D464F699F585E93 -CF29D5AC1F2CD04E992E5E714C1EEA2FD56400E45A42813E4BBF87BF0849834C -F54A730E4B399FF3BB4E14D9CBAAACD79CF06AF35C128CEFCA1C43C8A5ADC1BC -3AB187E52F70A2562F7A705C58396C3B9198C78AFB0BCAD890956F7D463C70FC -0DD0AD6AF96D778AEE93A3A79A514A16C0324421D5DD3F7BD1002252E0F24DDA -3EDB1856E47B979C235BCFE8D6B2FF68864FBAF0CCBC3BCA811760643E0B2E73 -551BA0BCDC4037F497911B8A5CCEA5AC79B2C8229F317B690108ED2C52E7429C -01DFA8C97FD5FF794EA69BCE240C02A9640CB5194CA6AE598C605AA92086AC82 -C983661FE88DB62A3B732F78F43B93E9C22A09B29FCD79E41053D4E27CE6F3EA -FF365338B03B87AA0D48063D02B8E4C88075FB2354A05EC177E3FC76FE4E4DB7 -7337F0AA30608A6775C928A39A515C20A285D0C4541A2A6F06E6844A6CA428B1 -68D522A3EA084A2EFD17E3FE423F2F55C9F19E842D2E30CB79026C2D2DA9CAEB -8C4DE6394771D9C2D071F1B17047FC66A2ADA0FDEFECD6FAD63EA5F2196CCBEA -A4DB2C62A0948DD2A8A0D30E7F6808FCB912704E647E1FCB8E54D27039F67009 -4E995339D198156D3F6522EC70AEB3F22ABD6699C36386B98E0992A57FD9BED5 -D9EBCD492CE373E46A35A906C17AD2C4C490A9F74039075C8AFD8EB52C9631F4 -0CAFAAF50E8C6B4C565D859F6DEB844846D560318367C21967D6100DBE5D3A1B -DD12DF6B8A3633BBD59EE865445D2F1E8814D8D64C3BC913183B59DF20361B66 -6F3DC614B9AC2C2CA4C30E1A01C1C2A2054FB4BE7D58C6BFFEFAA4E13087C434 -ADC6D8F1185F68B2003E7EA12A991128037E54D2A88EEA2E794D89BF531E107C -54278EE82F49454FC13638CD0B83C142BA3E0F5462CF92FDF0FA223EBF69D12F -3D99BA804FC467F40945B1B0AC23DF88BE1BDE21E296A82870F6322630C06823 -27629EA02637E6E3E10F16747B3EB3E479AB8A347FD46D581608D453684278A4 -AA58BC490F673269CBE7356CA4F9E523CDC3F5D98EA1B95CB686BCD17366B609 -72BB6B2167EAA0D66E36EF6A1170EA56A8485A659E55C8D50108F6455F1C4227 -6CB5DED36763E54089C6C04BE71D5B762254EA4374C136F98900F25B239652FA -71A14A43F046EC8171C490A5755F90DE4ED09F8AE5EA1A6A98EC026B612BCC35 -6879F1942C6B45DF7A50F4E49B8C8013164CA04DAC46F1D799071BA6402EDCD8 -F55BC6B064A2264A37D4BFE59754703B2C13BC4C2586A61EE4A9F9915F00FC13 -05072451125EB001CE97BE3933239DF6501A664B45FFB5E63467CDA463A5AA14 -504AFA4C8D4A976B459D8B41046615E06DD43760FFB72488397A34C4648C8B4F -C56454126529C50AB1D3B328136D31F79EFA1EA011C8C6FD6AC27FF2D4218B34 -3F99304558FE4B1C81BBF4807AA89ACF653EB74E9A2C85D8DEAE86F1A7B3B5F4 -077D09031A32E48C069539410F68EEE2A7ACE7B200CA099BE59009268219DB52 -27A2D68DE15C91ADBB30775AD1701708749754BC4F0BADF52540EFEBCEEA9FC0 -E00ED70078142201E897E93EEB6B8C033B2B21617162BB54060D3A14BA41D481 -9B2BCBFA81A176BF324C8425310DE6C313113A9DA8A950C6439996C957ECD22A -BEC6631437954D043A5F0F83508A7EB24EBE9058841DC13E42E5A817928965A1 -0566C3B7A4593733E519AB17F3995C6702E3378822FA575A537E720BF26BD14E -D08755D999FA4AF6D0BBC2A54CBC279C8E75514733DF7F2C19B84F043A4C9A03 -979FEF3A622C92ADC58FE94C3C6C6ED45472D1E48290173613F991036368E036 -1F8A871A66BE125074CAC7887A69AD92D96F157BE10A6604CE0647E5D2F6E4B0 -8E3CB6AD0E830C18B4C239094238357D1D371F643F50E81CAF234EC88E0CD6C7 -BF0B0626895B812E489153B01F94C0D86769A239879CEDBCF2402894B6E79566 -1AA9B48033407926F18C7399C641C3B0C898AC99AE6595E865726374CCE03954 -92D48AD6A336888DC372676F0E1BB9821F638924976163976175D2A687324741 -912DF146F8C7F6EA428814DF6F235728386BD3558CD588BB1699B43C1DD6B4E5 -CC4E75E69FE0158E8666CD4E86BE2E79148680287615041E559DF70923831A27 -63D40F0F873B3DCFCE27E0BA3F396EF61417E77DE37C0D11902FD961CF5174EE -8EB1DBC17A1B0FED2BB385C9475096D7EF37BE12B0D75F6C1883229F3A62A679 -828645A2E71DC2818B037613531463FFB0F84EBC614F6A9C3BDD29807805E580 -0200984E41C66B9C99A62EED7E91DF58C72EEA135B03B08292FF4532728086CB -5ADD2170758529CCFD0E652138B55D545DBFB5C1DD4FFEFFA87DB31F24DCECDC -203A0B9D242B8F0ABFA7484545FA7BC22CC5F30C28629086ABD681555FD8C060 -00F4B5444B0C79EA2F1EBA2CBF0C45689B6D4B09A1292DE9F6E92A9C52A4F601 -924EBAEDC0F478330826DC36A3E3AC35DE0B82145E378108A75D4DB79B78A713 -4A54643465AB3D1127B69467DF7AAB30EA92ECF0B5C475FD5922EE8310F8913B -7B1AD24A93EE946C8E6DAF09C3697934E94DD0074D8DB4582D26F9807786CD8C -D8CF959020822AA23D57077A73126BC5716FCFBFC6271C9F1BBEE9730198EDDC -41BF84898B24CD5A42D6D060C281B1810B323C5AC6032870041F007EFF54BD07 -63F24FED3250E1F67F98E4B73678A5BEFAB99103F09E59E5E80D4BC9A2977FE4 -3AE53E66D4185F52A001E6CFE374CB6A934187664F782F63E3C3359C66017383 -99693E9A5AF425BE05A681BF7073A3108C77C2A31A9ABFCB24384010E36CDAB1 -86219786B68AB2A6A7065167EF57C5EB79D790824A459A137E7CAE466F1EFF55 -8BA7CF2E9382C1BDBBEDB381E7BFF677DF252886AF2BF19B2E2D8C44E0C35957 -A0491E4723DA85E67BC6182EA0803EDF4BAFE302BFD52D84BB888A70232F7D64 -3CA598EF660B77E88A6A8A4A4D63AAEBB88E400D20581F2DB42ED3B2B184DF15 -6DC8E586726B5074EE71F347494C84B2365830A932A4F05F3EF70FAD933EE655 -12834498F3A58AC270D74CBAEF756CB8A499D3EA9B99C37DBD8D84970B188530 -82AFCAE63D692E6A72777CB1BB9523C75F9EBD4DC7F6E5D6F39862BB1D7AE93E -5BBD3E135E919421C3DE94A2EF81914B6EC5224906F83EF47292301C59C3836C -3F359945C40C61D9FC0AEA5A88A9A93DE5CB8DD195725FE145E79B7DF33B1FAA -F14A457C39D12AA5881FE5607251BADC4CA3A1FD901BEB971C765D568803D1D9 -832D5444A1D8332E125B7D865D5B28CD78C7043D8A86AB4DCFA769A183FB4B05 -749DFD67A669B7DBF6A6283CA516B94704D74F64C3FBEEAC15CD1A2D939CCF23 -3A7837791AA06E6167291EC2DB0C34846D7D158EF594C6499288ECB69EDFD50B -4AA7F1E37993781A3933174BDB9F8EA0D41BDF7896BECC4BD9E6FE17738AE1F5 -FC0B9D80D6247E861AA03A36B3BC648FC8610203AB27DB18B48BD494A5798406 -BD74B5D1631C2844DE39ABECFC6518C45A89E117D7C498348FAB6C512DE91210 -1C07826D1D6131AFC8B138B595641D80C8753C45ABA3EA94D2B175F382508B1D -B85D1133FAB93F41187C9399ECA60142A1356B1E5CFD821108C347CEA7ADBF08 -0B124290E9D736E2043039D49D7D297ECF51BB2D2A9BF589761AB8C1E7249722 -BB558C01661AFF993684BEEBD24DA09D0184440581B53FF4BF3C0129422E8F94 -F214FD0FE66F14DE284435437600C6B9CBB80CF7CBD3CECB34757BAC210DA30A -2DE252E3DE81792D101F032EFD210853B4D37CCAF643D71C4733C81202D5212E -4E75DE6E19A3F1905A22B668DEED9A8BCABC2365A1B2C6DA539FFC709B85038F -99A65DE1C6782F0C757D402F59F11968695061FD1EB1293BD54FC33E1C2CA4BB -AEA897043AA9FE619649D835D131E18DF17A9D1ED6163BBA1A9DD12B9BB42A74 -F67DEBE8DAED8AEA55A7F022159138F97FF379566A42354358FD09DC88FA9EAA -5CF2ED8B4D13C1339C07D398E96D0287FFCECA5C5C32218BB43BFE08196D3D1E -23973D34833CD9BACE28436A5FFD4816542473B7CEAAE489D7FC0F5012BCE6F8 -4D28102E67187E50603942FE7514770BB9157E67F1459F77B2D8FBAAE9A4C987 -295D1DACC6AD96A0818C9E875FEB5354BC2A1D28E2A1F45C8628D8D5B0C58651 -5083D10F070C42724CB17BD93D598ACE9762EB5060E2687FF9EFB1F58A95A5CA -1AF7B72010131F0618EF48E9BFD21C17B297812190CC427B569313B025C39843 -57E25E37934EA128680771B49E7A3F1978B3A6238EA54D83CFB84EC2A296791E -3990AC7AA99A9A5EC4A560E59F27DE1680C81E5930C136A83E8E7B4ACE6AAAB5 -57DFB10D605F501081A8808BBE3F6E297A90F5E09A3CDF26FC387399EF4D5C70 -E7A3E9AD46B0305E86DA98263A7F44357D4E950A63D7BEEB9D2E3DF3D066A6B7 -9E940CC10E8007B2CEA1C11521D2095EED15F3152F92B10E0B4E9AB74138F241 -4303245DED32F590E1FA35275F2A0A26FC74F9A04F1CE9280B9A5F136644B77E -9F4A7CD818309F8FF436B07EECB4E6D4168501F32B348446AB6D693C81FBA667 -80FCA9390E36759B14F7A406E66F7BFE7E91BCD495A53097E55EEAD39F8A89DC -FB4CFB345F075FA37C763528DCC7D80FAD8F674B107E60FA76597DE95BAEB3C9 -A3BA95633F1A44F20A2679BAC5D867A8ADE1270B3A87CF973424372BAF552056 -C9C37ED61E8A791D32997F15AA52A1F259FD02267DD7F43A218224DA371093A2 -2945C99A06AE36A43107BEA63FE56A9A2FC0EFDB46DF08C2752AF493035A5595 -EA90BD9847126368DF8E22FE380E50A893FB21914E78BAED3AE5F9F03F7027DC -D10B91264F4459B8D0136A8C4139C416C64E304128104B6EBB0F3978C69FBF5B -E090B5C295B98578A79FAD2AF4233821A08C375DF4C4429C93623C43907B99D4 -527E67CE7A73786E4D2F817A612AAC7B4D9E3F4A79BF382F15008DE76A9A8DF3 -47C60F100B09D971EC4690B1A04173A1CB66A2269BE80708FC29D82C552151CC -385F1F179889059D5D70D252C99D0F84D12FDC13FFDFADC11A731262BC8E2AAC -FD8FA176352F9D114322CAAC7278113C9B48C869D5EACE4215CD50A125EFAC99 -88312CF4E12FC1DA63029140E8EB1BFE1D79A7A338BA2188B599A1C224A0FBA1 -3CF40EFC11D7D3333FF371DED67318D2F6DC8B5F34A5728233AC9BB2EF214D67 -B3F2D0FDAA10F2C932F7AAC4EF557E31909175A3F61B0804CA0C762C53F20A83 -53A8A6FFC37E002EFC441614A8E540921635FE855CBF1338431AC8F66FB1E17E -6770C99ACCE479A366F00211F8915AEF2940F44E43FBDAB05FE2D64565BD2584 -59F65129BD9695C4787C6CEF7FBA70E2E0FE4FB7051F65AA824782F9887E5F96 -DF2527C15E39CD1D5BDDD48765BC0C528037F69F8C5F168810DFC2D974AA0E62 -20104E3F291DB79BFE816FAAC5765BA298797EA491EF82AF07769675D60F4E4D -F088426BF9CF41B0DF5D840BEA5ACFB5382015DD26ABB0851AC610B12553BBD1 -788032FDFAF98C64AF5E2FD0B08FDB9582CDBCCFDA38F256930349697AF7566D -F980076F5E072279EF92BE37DB65AC1D702B0E85C856482A8BA9B44CC43BF3EB -BB7504F1F2696B597A0FB8085E3F6E3BF178837363F750679CF2CCF7B01027F8 -747E1DA4597C8F93CE8F07D304FA72C64972CF08CD8B8F3331285EB0ECEDF8B0 -64B53AD633C6D90340797802DFB81D424DB73D68BADB7811765D83C2C57E3BAB -F543E327CB8B0356D4A84CA1BF0AAAD57FB9EA0E5C70090A04745C916A3EA2E9 -2AEFBFC64AECCA2DDA387A3A8AE1D27C6B031A28E8FB3F871576BBBBF7217CB5 -4ECD354B391D4661B278B1DAD9B3AA0F39883F31537E158075D73A5C4D37FAD0 -4181846C724986DA122D84914611B7C50DC964E21B40ECBCDE2FBCCA5A30E11C -5AF792173E502843DB785CD34583FF25251C712087589EA26D73257EB7B9D484 -72FCB8988317B1F886C5EB9791F4688F087DC8D2D0B82B5EC38CC026C45C406F -F0BDC2C47011AAAFC765C2E520BF3C90C85E0D4AD3D59E75585FA2AD70B3C527 -2383D7582779217F435224718C04EC8467BA8C9319F99F3F033B148B24CA80C8 -C2A35C0B3BB874DE6AA03D3DBED072A45DBC5C8A746F83ABB578F872D535EC21 -D16BE93537193CD36DFCAA9BC9FA95033EECDB3853532452385A71D1E92D12A3 -9AE044E7142F0911125B2C2C881678886AA4E924B5718172A3161C790E2E6F04 -9A28709CB38269D8D460A8415E68F64D6BD3C9ED9D9744DB7AE04B9F19B8DB63 -EF85CEF8DA88F8442E2AC150FDD3A15BCF9740CAE7FFA1DE92E2571CF2C0E0F6 -90F13F5ECB3CB88FE13D4B8963B51ABFB9040A25ACC10B08166441D7275106C7 -D5F58C5A80F4F5472181D985237B431B8DED88BFBE1215B6DB506B7838A26C4E -C129AADF9C36C4177C76930CF6008104E0B5E3A387A13CBBBB8109AEA38FC35B -E7DF40B4734AAF9A7CB819D94DFE944E994DD21EE7E9BC4014BA7F0A1FD7C098 -6F7A699E77867DA25507D723B6CF9174782B58AB59D89BAE119F145D61F83687 -2C2A1653B501E71415A0978D2FF39468686E2481CE4F06B981FC398F93555A87 -E93A098C9FF28BDCBAF0637CD63BEE7FA448538FACC04B11C068A16E687BAF4B -5D722363F7E1EF39B8DDCE5C947DC2A69DF4A4FCF40C397FB446A37E74502E49 -571846E8951AED1102A7B67B7038EA1C7ED210A077D83222E988C0E5D2B88BF2 -C71DF6C9F4400104F2E8DEA364D3A45CA1C1E6651C3972E89E5CF31881322FFE -AED481E2602E19D31A735C14F3C7A8D585C46ABF0C5C64BDD64EDD35D0ACF67A -5C91C26E2D53C47EEE126FCCAC1F7E9A67A0A02DBAC2C3EDFC15F55DD73EE385 -A7A32431AE18BD4F2C612FD5F5AF4380A259C0C38D22FEEE403A7B9CCC4EF62A -6CCFE803F270AA5FB5C4DF8419CCBF6AC611A721688ED51B82C1E5647F2B988E -2B84B5343C26D8495A23908A6EAB2D2376DB03F96D493A892B6548E0369988CA -A2ABCECD47663BFE45F4F3F910952056A5314843DBF4A8862ECF20B9C6427E86 -E90CF8132B2A03E1A0109C2C1973B5830B9AADC952F41D92EC44FA3E79C77155 -AD89D10EA1E3B30126889BA190C86ADD788045D0F933226A4AC2FF91A9406F6F -976F337400FF3921D372AD11C929109E7F2D7C2A494888CD85BD790C8119681D -83B11275991898106C693C0EDF1C19B8731A84A94470D2BF52F0123E5BB89E56 -39D5CCA023BF0625DA16DE7DB7611108CEA00E3CD4B8C03F31787EE00A94B542 -A88B4369139836FAFCFDA51CDD5ACCD351C567663F1140357C1414E3301174F9 -0FAAF917EC9C19DDA2F41C671B3175F49DA30593FA6C93A067560053822D9A9D -0A440C3DE6C4422E0EB2F7E86082F7734BA83D02C30EDA9A22354D1DCBC8D186 -6A43BF3DDC5209DD661A87CEDF97BA43262C6D418DAFFD943846120FC5E1A06A -5C7D847154E41CDBE66B0538189C130DC4094D7F1709F15460AA982DC438F380 -766D6937A65D1E01B70FC903E2D906FC31448FEBDB937051BD538019D849F81D -9C28FD74ADCA7996C9F319EA011A00AD195FFB5149F1B0B550ACB239D6D161A9 -E45FC9F9018F471885D62869831C55EBC118920B864BE49244DAE14794EACD02 -A096A5D16B4800B0A1AF3EAD075EA2476743425FE2214BDE468A20749C6FA35C -9CAC2363798D17891339B28F8BB6D0BE628DB425FAE39D65D3C034D041BBF7CF -4EF74A6AB6F656144930C034E57F02C528E054F65828BDE71083109F43FAF0FF -E520EB4BF5D92932BDE44D54797E58DFAFCBF5C819474A7B9282D087F819AFA7 -F13B47F2CDD0BDDA2D8ABE8D6A0886407EB8550B96844FEE859BB61C799975C7 -056361974EBA586DB2D3DDC859CFA0FF493C5C8DA81B2673AE6C94CAEECE4B0B -498E9F060E9948D0CB5C47040265075BBF6B40382EC26C5822DF3632F1F24973 -DE14BBECF72DD8535F05BF15276DBCD457432FDA386EA8131FE695CF61F11B37 -1C917751B54637348823C481D4C2B0DD4C98671BF1EB42919C6E11554D86490B -8E2823073B9F1DB5B04EE262840352032E1B9E4B688FCFB1144E43BFE455AE25 -F914AD37E6A694900C5CEA010A04631BA180B9D126989E46566101B868EF178B -6BDE396797925C90780A1840369DD3F7AFA7C6A2D46FFC8024B12C356D5FEEA7 -9270B37CD936AF7AA2F041836B00D3DA2F190F4E8C97FB7E9903446F8847BE6D -32A1772991AB24ADD997BB3B97452F21A25591459AA9F15A0B5395DE1D23B038 -07D3B35338E4BA1214570B83D730F9FE2F0C0695A331B8E391D1FD879FA2174D -3F83FCAE5E1441C51B7CC7AE625CE6F6EE29604FAFF1DD5C1FFA48599AA073E4 -E54E56028BD64FDACB47C715566D193332542E7A45F27F87F9BD0E7CFEC8EDD0 -C604549AA0831EE8CA7C68A8A4A6549B1E7C0BF2B6EEA70AFE13024C41557568 -D11E69C2F8D7962F5FFB6367016D93125A92DA39E25F30D5E4B85F66D34B0528 -DCD0D71BB767B7EC0A58272DBB90D0D0D0F661B783F724929CAAD9843E044752 -C5D1F2F6DBA6CBC67410623EC23D7C7EF15B18484315CEA679FC1526B576F54E -D1DFDD0E8ED5F2B1449A05501D0110DB989F62F815A30E84BCB0042A0FA14855 -77D07A326FA8F2B85E67E20935F9DF0068B107572BA80DCFFD90F922B79A85C9 -821363FF5AD881CF7C0212B2E6238B49813FEDCE319FC0FE40A42797235DFCA2 -0F1B939645B97D26A23CC5D1ED56CA253AA1E5C8E88E93C74F410835E3D5C2C9 -731649584619ECCBF3A50F95DD7EF36A8C1B5F63222863F0D8223CB787B88027 -54835558B8E4CD6FA1BD7E4024B6C7267C1266AE9E7D7CACD4448342BEDE1EA2 -717FD60DE846878BA67710AF4508F33E2D8D1827B7AD0A8C94531079BF2550BB -87B73A3848857F32B5D7AF2CC07DF0590D6090B7D820D701E669ACA06BA8F194 -02672D01ECD7E2BD4E29FE18176D8317BF9523D2900B7CCACE98E9B46DEDE394 -0CB3B65538418147C93E77FADEB94B66FD048E47A0F1C3BC92A51633F83E68EE -D239C0F2F5EB9EC68A048EB809B5B9F2DFE41F815CD33623CC2F6AA0C06C9F53 -ADF903E40B50945A7A288A016839EBA12CA78156F617ECF3BFC8AC106A0B1CD9 -9E2474C0DE1B88B5B18117CC68187DF5EF78C5B1AAE36D39946EEE1D931E704A -9D0A315054F5362FDE90A0C04F159F93715B4082554A6FBBC03AC4C2BB6E3A33 -8563FB20B664A350BE0CED555FF8DCF2AEF4FADEE74A09522BC31CF7E4FFA014 -DCA45475437866FAD01AAC47DA6951197066B69E6E850D4076C0F8B3F04355B0 -E26711458BA45DA22AB577B6D71C8697816ACCDCA0C59E1BD92FA8C730D09863 -ACFA216600EEE43FC54E9BBBCB873C64D0C9FE41DDCC573AEDA8A699F780950E -A63B8EA80A78E89724BC77DE5F7ED67FA860EE16D7E847FCFC198CFACF6FD4F5 -7A25146DD526769E6A4080E908C16F7CEB0EBEC4778A6A888414FD67BC2593FA -6D0111E37BE74CA96748A43A7345622CEDA9D1DD5482E8119DBA73E73A35FA0D -ADA16A14CDDB54D76DE1D407BB39C00AB23EA1CECAC9C4DBD64DB5AEC80AC9D7 -FAB6A1A3C4CA84F630A8D3A143A3490818A7BF0C8F16F6220BBEC2B8CCD528A3 -4A5F899039BB3E21B9554E3BD873E2C1DAE37F0700B43CD1939CE5D16773520E -7A915895E74BB21222996FB5623FC6F077F44AAB49FD6E8B6AE3C8A9A93DA0C3 -445FCFA9EC73F98378C5B4EF3E67978B7FED5FED1EDA85BBD4D0108D3E059E63 -28E11EC677315B68DD63C517853C1A65967BF1B859A9203DBC2F03C4AF6A20AA -E17C7103917CDB42303D88E4A1997B34201FCC208C941249624D039D069C2977 -B28AB8D215B245CC115024E3FD2ACB74184C8548DCE81F4D65D4CE268E360C03 -FB719F335050EFE6B13EAB0B9580437C6067F0251660588FB519409390F94326 -97C1C7A485E28C199DFB746BFD1CECE61C6F66D20946A54D9F05CC7F14BC7BE5 -9F0C229CD87F1A35D1AB547EBE307B0A5CB61F8E7661DFE503FF2EB3344EF7B1 -FED24165DAC30B5B6F39D1D1FA414A19E7FFEFCDF93808EDD4493AFDCA0BE31D -03EC07BBF75FFF1654E5D3AA64DAA505454A499E398C2F53DCB93BF548451764 -3E4D7004D97DEA315CB51588F654CDF6FEABADA788D6DCABAC86E3DC9BB7E42B -FBC1381C47277801E353B58400F9B9AA4DE2E1BF4E6433688C8569182F0F4568 -6D5E7931C695A5CC181A815B3D3252AFE7F25EAFCD8B07FB7B127731A25D951F -51506723A896F8DA4027296D11DD4123FE93BCC81914409D2E6381F1F2840852 -4214BDD7C2671B85AB24BF24F895E67A91DF23E21C5663797F049467329F3DB0 -A74763B8C6458A5C9FF1157F9DD08C37351A6F074E1E5A05F9827AC15FFF4A68 -93E1D010E02D82B63C1661BBF9113D415052C4C5070E6542E5E07223745355F7 -3DD76EDECF1C5328A29473B07BDEB0D4223C5D3DAA6BF3E639C2FF860AADA0EF -05A9BBEAABD8389112937B0F282A0D6C50A7CFFB0D214523EB8618583DF0EFBB -D98086ABDF5EC23F57F1101E86AFFD2CE314B4240380C6FFBE4530E6576180C2 -3A3695E4D70DAC730C2057578AA0CF3E8E464500C0F2C7ADFADCB41E1DB62D83 -86DAD27D800C797B01D3A701C62A3A1D0E1C18D76CEE1AC9F581CC1C697A6E50 -62053E7EB21754BA9D9763654CD7FC08B53A12408A4CD4B99F4061C41FD06922 -ADCD8518DFA056B825A24965B576EF1DE31E3A4E2E54AEFBAFC8BDF5E833AE8C -929405416A91A45AF0977E396ACE32C969C87FC93DEA7888A35B7C9E8ECCC350 -C9388F9953925A208E63514E9BCBDB99BD47D146DE4EEF08810C81DD6DC06EBB -DC1F0035A6DA0D99F32696E8B4A226435376E26C0ADC8846D28C8B875BD03663 -73592B3FB5D5A0C927140F27B6CFC0FE2A8DBDC77CBEE70C0E2005EBBAFB8BD0 -5B24447CEC27AD4225DB0DC1CBBBE69AE423F9622A4A8BBD9466962FB54B64AE -726060F18B3EC8D945009E8FB6C2ECA462758A78BE369F00AA4FB8534468F700 -A9376FB42130ED96EF9DA17B7B9589474D1427D0D8FF5152F6306527B12D4329 -3CF929105E04AF564DE552C4F06B466F16A8724945CDA9E098AB31A032CB2D05 -BBC3CD225A51D818A9695D6E32DA429E702632B32FECC25722652F67165695E6 -D9819D5B200EB3626FAE8FF7376DED2B1720CABD8AE2BC1A0A39B7BA427BCEFA -936F934DC88685CAAC7DE19929C9F99984CA938BE0044FB341AED41B19F97F41 -2C31E2C4DB232FF90BC0D15F1991DB60E7E944D90F7FF591136E1F260D3764C8 -8BA791589D455192A19ECEB8A9E80FB5506A479EE444322C4E8E8FF0DD9BCB8F -749C69C488E816625DF57EF673DB1A85BFB19D960461EA8E6718A1325D878D37 -FC7BC693F15D8A85AAF4C42216490BEA3D1638BE006CA2EC9D4DDEBE3C641754 -A78F6EB4B71D7517351A91A711CEE1FFC4FD57B0EF71E2959EAF82AB5494234D -FAAB49B1EC4DA7A2F3657458CC1CF6229901C2AF5339E2E36F92197762A8E446 -5F8F9D24A57B80850DE4264FA9F23C947C35801C2B557CFF02B15637D5B9B059 -9994ACD938E826E4DAAF9581A63EE82995E793ADE573CB2B9628BD7B899A1C1F -D437749137278A36B921206B70495E0DF379B7B7315FC02058EAC7F9128A3B4A -30E20BCFEEE17A99CFC9795F193E4356AEF6DB94A7CAC8880FAC9227A0BF78D8 -B7BC18F6DAC8E5CBA63996CFD5E4F78461AFECE7EF62C585B5E5DD40789AEAD2 -597E24874B3BA77799D67DF746E70FC9DA4CCD9BF40F9897092352B3A12682E9 -4A5A92795C8B52E212FBE7323349E867ED8FE78B8B42325C6AD4BEC036BC891F -0AFDCBDA2A75DB64EDD020A39A4AF0387B68D64BFED1C5FC11C58919C6FA0C96 -F617CA7860D5C10188376F31F1E323A95AB36138D4C8AEABFFF46CB6A3618ED2 -88C3BEC6184BDC2522388424FCAC44EC1DCF68E6B0A19B01A223BD7193EED9C3 -F5B838BE944E6C4CFEE7742EEFCCCF9F60EF632849E3306B990B2CA74B8F6AF3 -465A0BF22E1E59798302338B06682323B19C4E44FEFE84C0A210031F132E015E -E74264B3B0DA6E09E116572E707C45FE7010C8D291BE49657248E416B4F244F6 -E557295AC3633C4B84B5638EDA1B2767D0FD770654C2667EBE9494B1DC28825E -C12B1244900CF0F45EDD038BD90A98497250F897F1221A1733DBD4540D1B374F -827C8C10FA84F5A1F6A4C921426BCD3EAFB1B8C654131F15B4BA3E8D489F00EA -9BCECF58E9D15BFC1B16E4A08F0D5459D26559144278DD721DAC117E4C0F6EE3 -19930DF91DEDD9664287F11ADAD823DBAB597729C554DA905BC72A6686481108 -7FA7B78D41FFEDE9830955C6309749DE1ABD705BD346019D4ABC4C340C9A2A9D -CA7D20D6CEB59E8B7836043C49D33C86469D27CA62851DBB00E6B8F4E28714C4 -B5F277CC2CFF502F0E47352F296EE242318D73197E754E4620A9B7DBD075C93E -5225C68C47BAC50FCB58A6D33E1B55A39D131DBDD4E014C126DD320293BA9748 -4712E66FBBA2BA24BC8F4B1A285AA123F7B8146F4684CD922EBD333A7B493CE4 -F9C7BDE8FEC45429EC26DF8569130F0898C3D43F7CA90C210B103117911B27C1 -A14E0068595867748609ED646B5E08485E7467C36A528C738C1B7CFA362CA720 -C088CB808926A1D895DDFA944468AB702AA7F91D8A4BFA372E6D7640A8E24273 -75C1C8466DA13AC7BC57CC6ADAEC27CDCCB29BFA5473CED983B9E2EC94132E18 -6D77798D59EDAA1BA98A0618A1066374D655D55066BCF81FAB2E4511E1928ED7 -C77FB148D57D8EA24EE0720AB527AA3A76285B696FD2FF3546901E849A5B3802 -F21F7205C80F9A4A102DFE192C5C5A5403C6A8AE106C10746A550F7CDFC992DB -E3A64BE4A2726AF22D403EAD6AC921F48D6535E9E850BEC1E5B0AC79AF04502A -1FBD5043391104C6DD0B09CAA3654A7A21A52D6164FA2E7A4FDBE9CB328C3A53 -05406F4A2F45A1FD4B2CF998E94B7DAF2E3CB584A8AD83CB32844979EA560E0F -6EB5215F705141320F1BAF1504E210D3690FBC58830BACA500624F7A7ED3EEA2 -789738814E197DAAF6DA815029368B28818561F044171ADDCB73B6DE459C3E9B -64196B66F8A12A1BE100124EF86CAB8B7A10822DF4951766AF568D826E0B91E5 -E640EB8D3D8B188912C510D456231E46972B177019A807DA6AE89E76400E82B4 -EF3EC27BCD8F879A5A7A04BB4D5E290514EF7ED3A976A5B2D5B4F9359B283DE1 -1D7BFB356B3F3F02BB45FA93F0B442330A9AA29F8680260D1071BC27829EA312 -0ED69BFF2730E0F550F35CF2CF16AEC7D8CFDECE336F95789FA1C76B4C6BECB4 -D6400166ECB6FA2A44C587F15DD55F55A1F7FFD8F07CA99EDD2052218828B191 -D52CFD56538ECE62E946AF57C39CDAED30DE6FE58491181ED84E700092A061BC -821B6A5C32A0F436DA74826E0790EBC7D55F14223DDA0234680D41A5BAC55EBD -8D657911A3C10F9537AC9D3388EBBD5856F043A544AF4E60CA7243DA6D38BB28 -4646E77BF92BFA763150C7E4543E844B01097CEA61AF0CA802CD8055BEDD63C0 -6D91EE700452A400496DCAB0632DBC58C5285E8722F9BEB4860842B48B1D9FAE -B266B6381548CA943B5EEF047A6805D99AF761A42AA6850CC458E1C147E3ACC4 -E41653EE36F6BF8C938DF808E8DF9220690A1E36BF5C7924DE8944C261955F25 -A7976C3FF10C79A10D8EACBEE51C00E961588131E35B08BD2B07962EF33769D8 -8A7FA9BA8EA90C38B846963030FB463511992396C25B4F83D6E6842BB7408064 -B979DF1E0A1C20719C8F9430C1F46B36DAD548471A37B4328DDA480F3274900C -E33879F1C6AE71A76437DA0F6712297CE10B14552768C06315EB48500514BC14 -AD86EF94E5AE2390B6D9ABC097BF1A9CB666988EC3797A3464930867433F7F95 -D26D8DED9791F0C49EE8AEB9017CCBA02B4B68D639B58C864EAD6067B3D1FD22 -E989551D11DB9BF2A8D833391D25109F007D9E3F7ECDE5F21C64AAE0B0D4C4CC -C511D9E7251286551308E976F1C69422457B9F6544A768188EC36C7964D158C5 -09ED5CF20C62955EEBFB0C4A851943CB1BEDEFC216A5F11051C9074C8971A13C -59EF979D9C6C90E545E7569F16A202E0488548C6AAD14AA2D3F5C15E5807F39A -00752DDE0B2537CEF6F67A921342CD30B85CD65841BA2B92156F2ABA110F9193 -1D8F5C3E7BC15D1F2A1B45FC37DA6EB07B9D77EC0C8F507F49599A3CFFA76C0F -4EE4037576BE710FD8D22424899D80D389FF23B8760FFDCB88B5BBB17345D278 -42286B59AFC25036261678551AF7CB98432D66CB6C49E3ABE73B47B0568839B0 -9820B34D98B0B2312CE07F438A94F7DC4C5D50066AF6FC3399BB9D58AF4E4F7B -8271B178FB44B6C9A286FF4925C920DBC35D5AF5E24B60C5637C4D1343312EE2 -FA5625B6AD5ED764EA7D670761365EFDB46FB8153E23072885C3225ED394EFAE -6B319D543ABA7005821D8B857D06235F83FED9697FDB48074BE3E797D96811F0 -10BC6392B1B9D4A896B3993C0A77E94B57CBBE264C12463687BCEAE30C575B1E -16DE09B2D92E58155BC5AF9339C62F48DC0C66831B7F519B236A7F1AD6E2EF6C -7216A0304F415B8C95E46AC28A0C2EED00A5E22B193338BA67F78735D8C26F7A -994D25DD5FBD72BD3B1DCA1E2B0F7151439313824FA3811C01FEDE345439CC7D -604ED31A684426939CB3F2B9DB05D509A7B0EAAB0583662991FC3ADB4C50A515 -3B881A40DB960A9D6226C4B8BE7DE1CE38363BBF3537A68E269787913EF43FE0 -AEFBCFA0C199AD0337F48564CCA04DBB0442A4C8BC13B0072BE782817F59C8D7 -4A052705029F8986F888C498825819171C12E4CD2A33BEF7FAFC3447FB5CE42B -B3BC34F3F2B61E0E43048E32522CE84FBFD8B7E36F9C83320D5C8692AED52588 -A2359603E13A2F2E43B310D433B83713F94D77557C9C8EFBA9B5E5419B75BE5C -25E87490EFF8A2C54734079826AC3CC2B77B982F3D11141FEA98B417603EFE94 -240F453DD6E62737EFCD0A104ED9009B009C4A62A2188A7FAAA0778F36E3CC25 -D3E6D192B338E69B6C6A63ECB42EB981B08D2B65646EBF09DBCE03940135D76A -E22D04BA3C8293534A9BEC2969B54A12B346AD976FACA36C07376C9A8F2A198E -BF0BE85F63EE43845F761274E0D9CB7531C451516EF085BDF6A02833E38B8B87 -D141D8C9F39F6F032880A6E39022707C2D318613A800E1F5A312B300115EF120 -744D58CFF4C7BD46757945D541C1349225F2C0BB4ED39A2457B7D8E3DBE1C5D1 -D150794D5EB2081B8F4C13F73ED220A7FCF5E2DAB5CD77926FB66CE3063A21DB -1B76BDC2C8B2AA374B9F362404AA707E3E4751848540E83B712DEA3423FE49B6 -0AE4D96AAFCB9D6198918EF460E585BBC2A37B3318643CECF4D3F865E14692D9 -74267716BA6CC117B13CF185717F6FA0C8602041CE79E696CCA1FECA4AA4CD31 -A06916B369B7FAEA1F66AE081DF3D44236F012C557C8076772576CB116783153 -C2DEAB8CD542F0B08C75E00AC57C816B372E20C2660374BF09AC498FB3AC9A3E -1BE52953FA41686599DC7213845478725D54DA531A0375CEC8BA1827C27DBAFD -6555A364CD1AEDA1A5DB57 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMR12 -%!PS-AdobeFont-1.1: CMR12 1.0 -%%CreationDate: 1991 Aug 20 16:38:05 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMR12) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMR12 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 46 /period put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 54 /six put -dup 65 /A put -dup 86 /V put -dup 101 /e put -dup 105 /i put -dup 108 /l put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 114 /r put -dup 115 /s put -readonly def -/FontBBox{-34 -251 988 750}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5CF4E9D2405B169CD5365D6ECED5D768D66D6C -68618B8C482B341F8CA38E9BB9BAFCFAAD9C2F3FD033B62690986ED43D9C9361 -3645B82392D5CAE11A7CB49D7E2E82DCD485CBA04C77322EB2E6A79D73DC194E -59C120A2DABB9BF72E2CF256DD6EB54EECBA588101ABD933B57CE8A3A0D16B28 -51D7494F73096DF53BDC66BBF896B587DF9643317D5F610CD9088F9849126F23 -DDE030F7B277DD99055C8B119CAE9C99158AC4E150CDFC2C66ED92EBB4CC092A -AA078CE16247A1335AD332DAA950D20395A7384C33FF72EAA31A5B89766E635F -45C4C068AD7EE867398F0381B07CB94D29FF097D59FF9961D195A948E3D87C31 -821E9295A56D21875B41988F7A16A1587050C3C71B4E4355BB37F255D6B237CE -96F25467F70FA19E0F85785FF49068949CCC79F2F8AE57D5F79BB9C5CF5EED5D -9857B9967D9B96CDCF73D5D65FF75AFABB66734018BAE264597220C89FD17379 -26764A9302D078B4EB0E29178C878FD61007EEA2DDB119AE88C57ECFEF4B71E4 -140A34951DDC3568A84CC92371A789021A103A1A347050FDA6ECF7903F67D213 -1D0C7C474A9053866E9C88E65E6932BA87A73686EAB0019389F84D159809C498 -1E7A30ED942EB211B00DBFF5BCC720F4E276C3339B31B6EABBB078430E6A09BB -377D3061A20B1EB98796B8607EECBC699445EAA866C38E02DF59F5EDD378303A -0733B90E7835C0AAF32BA04F1566D8161EA89CD4D14DDB953F8B910BFC8A7F03 -5020F55EF8FC2640ADADA156F6CF8F2EB6610F7EE8874A26CBE7CD154469B9F4 -ED76886B3FB679FFDEB59BB6C55AF7087BA48B75EE2FB374B19BCC421A963E15 -FE05ECAAF9EECDF4B2715010A320102E6F8CCAA342FA11532671CEBE01C1B982 -4B1CF704E817814FF9C921A7DF86627623F382208EB0CCEC832D35D9B936CFA7 -3946FA2494DBC51325D4330866D33DD3E546B774EB8ACC089E62AFEE8955A55F -F2B6F74FD94C06C5C71F87938D5295A2ACF34830CD5242B56841A2B4137544A1 -32D98E64AD37F790574845703C739F5BDFB05BFA53B0F4389B0FCCFF03D25AE7 -09DDC79EAB0178EF14D67282335F3AB8B2AFACE2E06433376B2007DEE8B60624 -AE40AA85E30531E640E128CD5F89EBA045D173D10E50C8C0522099DA01F1B00C -542D6FBFA1D372D43C55305F01D70BEC886B96806AC7BA30B76FA28E75717FC8 -AB91CB77949111B50B8566C1C0242A6F73E444877F0A39CC1EA349594E7540FF -AD34A14D43FC327A1517B6B034B322B09347BA663558256046DC0D66DE0099EA -1B33A960B7A3C37FEE174795CA3C975F9D16DD114308ADD38F203B7DE2E8A220 -885A7E036E768FBB3B599E5A76C8E7CE0B75820B269EEE63EEC8156098D183A8 -A6D20104A15BE6558EFD1C9C4F5D230827E102D33E5D96C9522AD0D46B430943 -3B64D20F701A7B064FEA4EA6E28DE141C2BEF2FC6C9F3237694002B9B18789C6 -D157AD81136E8E951CBD0366A5206F05F4A68C7C1017E49F254ED437707E87B6 -6AAD86C83DBC17FBC5FCF9E51DE92CEAE5C6818967AC83A26B3AE2E54AE34218 -0D5C577A0F56115705ADADCE83D89735A71D69E8CAF93A20A22616047C498A1A -0092BC92641DF088AC0C591572F8D719394C19585CD1F03DF4D35F627AFBC502 -A2C36CB17EB20E23835F6E0CB42B1C18532DFFBF0840666FED39C99BDE7DC317 -974DC1D34097CC7B71ACDBCDED56E7EB088B4E7D2AAF4F761745DEE6D371852D -4F51756C97363F7D9AE57D19341CF566C531110F8F04197B207A4BCADA5199D4 -CB86798A5059690E4F1C18A9ADBF9BD3E54AC6BC7B0908DBE211F4E7964CD594 -1C3AD1AA5536E4BF9A0586DDC944D99238E2A3ED0F178F49B1A45BCEB385BC68 -98AEE8041EDF3243ECE88920C04B609A7373E661B0E5ACDB0FD366CC417615B8 -6C35D5FEED5EB88FE43D4688A7ECAB9D1FF5A44DFB75FE133A5C243E2B9F7F77 -B33F05A19C616A5ED4634EEAC2B9E6F9A344ADF85759070E7083FA255EC10296 -E3DEBEC97364554F8CDF3BE4E5E2EEE9E4E45FB96E677F01FA938D0CDA3F5471 -AE69BCF62A767784279F56790C0789646DF52978F125488EDCD6B73EDBB489AF -F811E568EDD1F7CD8B5BF7EBC228245BF2C62A06EB195D8741C76F5DCFE74F80 -FED9A7B976104C0CA2536A4412B89AF59686278B858584AAF32B674E90412EE2 -1C8D0463194B58C61671161578E69FC7CC0FCC62B280055D4FC3043304E9E2CD -5F3318799C0EA5F28EED6D3504E96DFAFAFC4F543F230712C706DE7C45CC9787 -A069D4DF2A2C2FBD6EAA437DF7516A3E4FD3DA89419CC9BCCD2A73AD0FA50294 -CDE5E44A9165E301B5F704365678E92FBDC4510A5DB07FD9AE33D4C84C9FE155 -E37BD11BE772DC9251386845B7BEC43C24C189FFF8BDB7273F62220AE14B1A60 -0AFE4E34818E562F410E77821E76B484F1115BD553DCB16AA903852003EF08F2 -E0F957413F700296B101646D527B5B310F1B91D0BD9E89E6A775A580201E80B8 -7CF3C74957B2A3D1570A2A4916B8A0975F0A81716DBC3951ED697869EBC156E3 -F0A23EEBD4FC396012828EFF16B54612A009DD4995F130D37BE4807F8B245CE2 -BB5A38299450E19188E0C466A7797AB2C212116ACFAEAB012AB7107AA6A2FA37 -728C28CC379BFF030365AC36905415B2DBD212248390F79B7191F2F1DA344F0E -9619C0FA65A2F476272B03C5B796D926B1790F641EB6ADD5D4442C7CA34FD39F -0F07EF7837C5C9E4DBF477CED9AADBFDED496AFF3F1C45F23D7158A56CAF97EF -92C1C497C5A01F715F7E78E0254121B30DC4524D6D5F973A4B57FBF5DB7AEBE6 -9E8434BBFF5AF266ACD0AF8BBD187FCA81C2281F0C91A034F65F1D817C719C5B -0AE0A10EDB2710CC595B4573B65B1B8E98D763439902375896EE49506856F5E2 -51038BBE4FA692FE726887E9A5E065BCB4DA264DF7CD16D67B7ED0996CC4396C -B24053DCAD500585E333CA028CAE126BFB0377D0E8366EA01F735371E3EF5190 -50F0C3BDB1D32BE74968588ECE292B2F5012586265E55AAEBECD3951AE2C9C5F -3D64EAD776C7A4DEF14290037DF2ADE3A2810143A58AB50F5AB48232FF2B1A98 -982CFCFE7A9A52A774E0D9A624BAEEFEE43CF556BAB6ADFBCA7BCDD3F05778BD -F0FBD6EDB44CE80341CFE098F908A099EE3010C7BAF55C5582B053EB0CF5C34E -991FA08EBA1FC5D3B893F8545CC37AABC686FECA16646D81EA85D25F2AA8EA77 -5E8B2FBFF81D86B7C64925E42F9FF75655AA2DC7B5BEECF8BEC424A4C236A415 -6127438B84B02A8BF4D492512634F3AD4992201D7D6C6AE703A7809A77E7767A -3511588FB5B93013A1FCD2B0380C2321B19EE90EDA17B12A0D790E5DAE925B3A -4E026D2B52866C779C83EF5F31F4F54D7A289480C2FAE03138709E503ED81204 -D6287D1711497562A0E28416E75D65D3425560F1CB61104F2A733F15AA0BEF31 -D7308DD1846D6B9B5921D36F994344441189785075F9FF2EE79207AA0E82B5AD -609C387B86EB0ABACD9CEA427B981C30006ECE05BAADF7592F74DED5907FE422 -7D316876A7DEEA4B4053702EFDA2F861490C7034E7A929F0492535503C0837EE -BC80417EAC6704D64B693819FCC0BBBEC2B9BCBD2F5FD6B5FEC468E13BF720CE -EB0BA928A7A92CD4705CA1BF67B3B395148E434029714A75CAF4AED10E45D5DC -163EBCB40CF5C9066CC946B6310B505F8FE89D7F610C9EA4E542BDCC188353CE -90D7BB66398EB5B153AA09A62ECBAD0C8B40BCC4E30280E57B47418FA66A2347 -0CAACE2201AB788595D5B74EFE9BADF5679C6A97E7E714DA8D1E7C50271E072C -AE75962CA72981F6ED551C2C9D322C007234D5DBB570E3C1EBE06DDA2E011B20 -55DD67C1D3E9B3E7AC47C1D15DFE921E8F1FBB6843BBF37D669E637D201B84F0 -9D49E981C6F1A803C1B40FE4DB82C3A53D138795B3816D4B07DE20621D5A644A -57E86C30E7A8096880A02E4723AA31EDB8DB7E95E373F96CE6E41EEC9EF06020 -E11CB902AD80E02892F6733FC715C0957238158AAB70D6FAEF073D0259DC24FD -4B3DC7F0DE52D04B1F479806E7714B73EB1D225E1A83B9BC4177EB0C672BFBFA -CF4CD8EE1C5D8639434D7951537923AB79CB195181019DB1935B705EF6DD9A3D -3F15F7E634554208F4E8E7D775BB4A6E1E0EC05DF40B444B3B8D00A528E80B09 -ED50BCB1407B90D5CB7C3FE49C4420B51FA0DF45436FF5071FDE0E17F14C650A -0785E6CBFF8E6C6A79BB002AED449A16BE91458BF2DFAE96D887DBE264B45C86 -89DD114648E6626197C1D181F63141634346FBC14CF4BB310FBCED5657CDBD54 -D86C098E7A52D9D8A829BF4C700992862434F2FAEFBD7104CE221E8D985A2AA0 -B659BE12D8CFD0BFC998A2CF7409A90690A65D20E3C909B2073D336CAEAD -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -TeXDict begin 40258431 52099146 1000 600 600 (fitsio.dvi) -@start /Fa 193[71 62[{}1 90.9091 /CMMI10 rf /Fb 133[50 -59 59 81 59 62 44 44 46 1[62 56 62 93 31 59 1[31 62 56 -34 51 62 50 62 54 9[116 85 86 78 62 84 1[77 84 88 106 -67 88 1[42 88 88 70 74 86 81 80 85 6[31 1[56 56 56 56 -56 56 56 56 1[56 31 37 32[62 12[{}58 99.6264 /CMBX12 -rf /Fc 149[25 2[45 45 86[45 15[{}4 90.9091 /CMSY10 rf -/Fd 133[60 71 71 97 71 75 52 53 55 1[75 67 75 112 37 -71 1[37 75 67 41 61 75 60 75 65 9[139 102 103 94 75 100 -1[92 101 105 128 81 105 1[50 105 106 85 88 103 97 96 -102 6[37 67 67 67 67 67 67 67 67 67 67 67 37 45 3[52 -52 27[75 78 11[{}63 119.552 /CMBX12 rf /Fe 129[48 48 -48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 1[48 48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 -48 48 33[{}93 90.9091 /CMTT10 rf /Ff 139[75 1[79 1[108 -7[108 2[88 3[94 29[140 9[97 97 97 97 97 97 97 97 97 97 -48[{}17 172.188 /CMBX12 rf /Fg 165[56 68 68 93 68 68 -66 51 67 1[62 71 68 83 57 71 1[33 68 71 59 62 69 66 64 -68 6[25 45 45 45 45 45 45 45 45 45 45 45 25 30 45[{}38 -90.9091 /CMSL10 rf /Fh 134[55 55 1[55 58 41 41 43 1[58 -52 58 87 29 2[29 58 52 32 48 58 46 58 51 11[80 73 58 -78 1[71 79 82 4[40 1[82 66 69 80 76 74 79 7[52 52 52 -52 52 52 52 52 52 52 52 1[35 32[58 12[{}49 90.9091 /CMBX10 -rf /Fi 132[45 40 48 48 66 48 51 35 36 36 48 51 45 51 -76 25 48 28 25 51 45 28 40 51 40 51 45 25 2[25 45 25 -56 68 68 93 68 68 66 51 67 71 62 71 68 83 57 71 47 33 -68 71 59 62 69 66 64 68 71 43 43 71 25 25 25 45 45 45 -45 45 45 45 45 45 45 45 25 30 25 71 45 35 35 25 71 76 -45 76 45 25 18[76 51 51 53 11[{}93 90.9091 /CMR10 rf -/Fj 140[46 46 1[65 59 65 1[33 2[33 3[52 14[88 20[88 10[59 -2[59 59 59 59 1[33 46[{}16 119.552 /CMR12 rf /Fk 138[90 -63 64 66 2[81 90 134 45 2[45 1[81 49 74 1[72 90 78 12[112 -90 2[110 6[60 2[101 4[122 65[{}21 143.462 /CMBX12 rf -/Fl 134[123 123 1[123 129 90 92 95 1[129 116 129 194 -65 2[65 129 116 71 106 129 103 129 113 11[179 162 129 -173 1[159 175 182 4[87 1[183 146 153 178 168 165 175 -17[116 1[77 5[65 26[129 12[{}40 206.559 /CMBX12 rf end -%%EndProlog -%%BeginSetup -%%Feature: *Resolution 600dpi -TeXDict begin -%%BeginPaperSize: Letter -letter -%%EndPaperSize - end -%%EndSetup -%%Page: 1 1 -TeXDict begin 1 0 bop 861 1940 a Fl(FITSIO)76 b(User's)g(Guide)356 -2399 y Fk(A)54 b(Subroutine)d(In)l(terface)i(to)g(FITS)h(F)-13 -b(ormat)54 b(Files)1055 2659 y(for)g(F)-13 b(ortran)53 -b(Programmers)1667 3155 y Fj(V)-10 b(ersion)38 b(3.0)1727 -4058 y Fi(HEASAR)m(C)1764 4170 y(Co)s(de)30 b(662)1363 -4283 y(Go)s(ddard)f(Space)i(Fligh)m(t)h(Cen)m(ter)1522 -4396 y(Green)m(b)s(elt,)f(MD)h(20771)1857 4509 y(USA)1682 -5298 y Fj(April)37 b(2016)p eop end -%%Page: 2 2 -TeXDict begin 2 1 bop 0 299 a Fi(ii)p eop end -%%Page: 3 3 -TeXDict begin 3 2 bop 0 1267 a Fl(Con)-6 b(ten)g(ts)0 -1858 y Fh(1)84 b(In)m(tro)s(duction)3136 b(1)0 2118 y(2)119 -b(Creating)34 b(FITSIO/CFITSIO)2405 b(3)136 2280 y Fi(2.1)94 -b(Building)31 b(the)f(Library)58 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(3)136 2442 -y(2.2)94 b(T)-8 b(esting)32 b(the)e(Library)j(.)46 b(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 -b(6)136 2604 y(2.3)94 b(Linking)31 b(Programs)f(with)g(FITSIO)40 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 -b(7)136 2766 y(2.4)94 b(Getting)32 b(Started)f(with)f(FITSIO)55 -b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 -b(7)136 2928 y(2.5)94 b(Example)31 b(Program)86 b(.)46 -b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -f(.)131 b(8)136 3090 y(2.6)94 b(Legal)32 b(Stu\013)92 -b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(9)136 3252 y(2.7)94 -b(Ac)m(kno)m(wledgmen)m(ts)30 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(10)0 -3511 y Fh(3)119 b(A)35 b(FITS)f(Primer)2918 b(13)0 3771 -y(4)84 b(FITSIO)34 b(Con)m(v)m(en)m(tions)h(and)g(Guidelines)1993 -b(15)136 3933 y Fi(4.1)94 b(CFITSIO)29 b(Size)i(Limitations)42 -b(.)k(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(15)136 4095 y(4.2)94 b(Multiple)32 b(Access)f(to)g(the)g(Same)f(FITS) -g(File)h(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(16)136 -4257 y(4.3)94 b(Curren)m(t)30 b(Header)h(Data)h(Unit)e(\(CHDU\))87 -b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(16)136 4419 -y(4.4)94 b(Subroutine)29 b(Names)79 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(16)136 -4581 y(4.5)94 b(Subroutine)29 b(F)-8 b(amilies)33 b(and)c(Datat)m(yp)s -(es)44 b(.)i(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(17)136 -4742 y(4.6)94 b(Implicit)31 b(Data)h(T)m(yp)s(e)e(Con)m(v)m(ersion)65 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(17)136 4904 y(4.7)94 b(Data)32 b(Scaling)89 b(.)46 -b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)f(.)85 b(18)136 5066 y(4.8)94 b(Error)30 -b(Status)g(V)-8 b(alues)32 b(and)d(the)i(Error)e(Message)j(Stac)m(k)44 -b(.)i(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)f(.)85 b(18)136 5228 y(4.9)94 b(V)-8 b(ariable-Length)33 -b(Arra)m(y)d(F)-8 b(acilit)m(y)34 b(in)c(Binary)g(T)-8 -b(ables)26 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(19)136 5390 y(4.10)49 -b(Supp)s(ort)29 b(for)h(IEEE)g(Sp)s(ecial)g(V)-8 b(alues)68 -b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(20)136 -5552 y(4.11)49 b(When)31 b(the)f(Final)h(Size)g(of)g(the)f(FITS)g(HDU)h -(is)f(Unkno)m(wn)k(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(21)136 5714 y(4.12)49 -b(Lo)s(cal)32 b(FITS)d(Con)m(v)m(en)m(tions)j(supp)s(orted)c(b)m(y)j -(FITSIO)72 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(21)1912 5942 y(iii)p -eop end -%%Page: 4 4 -TeXDict begin 4 3 bop 0 299 a Fi(iv)3311 b Fg(CONTENTS)345 -555 y Fi(4.12.1)61 b(Supp)s(ort)29 b(for)h(Long)g(String)g(Keyw)m(ord)g -(V)-8 b(alues.)62 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(21)345 716 y(4.12.2)61 -b(Arra)m(ys)31 b(of)f(Fixed-Length)h(Strings)f(in)g(Binary)h(T)-8 -b(ables)70 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)85 b(22)345 876 y(4.12.3)61 b(Keyw)m(ord)30 b(Units)h(Strings)i -(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(23)345 1037 y(4.12.4)61 b(HIERAR)m(CH)31 b(Con)m(v)m(en)m(tion)h(for) -e(Extended)g(Keyw)m(ord)g(Names)83 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)f(.)85 b(23)136 1197 y(4.13)49 b(Optimizing)31 -b(Co)s(de)f(for)g(Maxim)m(um)h(Pro)s(cessing)g(Sp)s(eed)44 -b(.)i(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)f(.)85 b(24)345 1358 y(4.13.1)61 b(Bac)m(kground)31 -b(Information:)41 b(Ho)m(w)31 b(CFITSIO)e(Manages)j(Data)g(I/O)91 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(24)345 1518 -y(4.13.2)61 b(Optimization)32 b(Strategies)69 b(.)46 -b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(25)0 -1771 y Fh(5)119 b(Basic)36 b(In)m(terface)e(Routines)2504 -b(29)136 1931 y Fi(5.1)94 b(FITSIO)30 b(Error)f(Status)h(Routines)84 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(29)136 2092 y(5.2)94 b(File)32 b(I/O)e(Routines)e(.)46 -b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)f(.)85 b(30)136 2252 y(5.3)94 b(Keyw)m(ord)31 b(I/O)f(Routines)36 -b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f -(.)85 b(32)136 2412 y(5.4)94 b(Data)32 b(I/O)f(Routines)53 -b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)f(.)85 b(33)0 2665 y Fh(6)119 b(Adv)-6 b(anced)36 -b(In)m(terface)e(Subroutines)2159 b(35)136 2826 y Fi(6.1)94 -b(FITS)30 b(File)i(Op)s(en)d(and)g(Close)i(Subroutines:)76 -b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(35)136 2986 y(6.2)94 -b(HDU-Lev)m(el)33 b(Op)s(erations)108 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(38)136 3146 -y(6.3)94 b(De\014ne)31 b(or)f(Rede\014ne)g(the)h(structure)f(of)g(the)h -(CHDU)99 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(41)136 3307 y(6.4)94 -b(FITS)30 b(Header)h(I/O)f(Subroutines)i(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)f(.)85 b(43)345 3467 y(6.4.1)106 -b(Header)31 b(Space)g(and)f(P)m(osition)h(Routines)60 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)f(.)85 b(43)345 3628 y(6.4.2)106 -b(Read)31 b(or)f(W)-8 b(rite)32 b(Standard)d(Header)i(Routines)67 -b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)f(.)85 b(43)345 3788 y(6.4.3)106 b(W)-8 b(rite)32 -b(Keyw)m(ord)e(Subroutines)116 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) -85 b(45)345 3949 y(6.4.4)106 b(Insert)30 b(Keyw)m(ord)g(Subroutines)108 -b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(47)345 4109 -y(6.4.5)106 b(Read)31 b(Keyw)m(ord)f(Subroutines)64 b(.)46 -b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(47)345 4270 -y(6.4.6)106 b(Mo)s(dify)30 b(Keyw)m(ord)h(Subroutines)55 -b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(49)345 4430 -y(6.4.7)106 b(Up)s(date)31 b(Keyw)m(ord)f(Subroutines)116 -b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(50)345 4591 -y(6.4.8)106 b(Delete)33 b(Keyw)m(ord)d(Subroutines)87 -b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(51)136 4751 -y(6.5)94 b(Data)32 b(Scaling)g(and)d(Unde\014ned)g(Pixel)i(P)m -(arameters)113 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(51)136 4912 y(6.6)94 -b(FITS)30 b(Primary)g(Arra)m(y)h(or)f(IMA)m(GE)h(Extension)g(I/O)f -(Subroutines)117 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f -(.)85 b(52)136 5072 y(6.7)94 b(FITS)30 b(ASCI)s(I)f(and)h(Binary)g(T)-8 -b(able)31 b(Data)h(I/O)e(Subroutines)d(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(55)345 -5232 y(6.7.1)106 b(Column)30 b(Information)g(Subroutines)121 -b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(55)345 5393 y(6.7.2)106 -b(Lo)m(w-Lev)m(el)33 b(T)-8 b(able)31 b(Access)g(Subroutines)60 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)f(.)85 b(58)345 5553 y(6.7.3)106 -b(Edit)31 b(Ro)m(ws)f(or)h(Columns)106 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)f(.)85 b(59)345 5714 y(6.7.4)106 b(Read)31 -b(and)f(W)-8 b(rite)31 b(Column)f(Data)i(Routines)66 -b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)f(.)85 b(60)p eop end -%%Page: 5 5 -TeXDict begin 5 4 bop 0 299 a Fg(CONTENTS)3334 b Fi(v)136 -555 y(6.8)94 b(Ro)m(w)31 b(Selection)h(and)e(Calculator)i(Routines)95 -b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(64)136 717 y(6.9)94 -b(Celestial)33 b(Co)s(ordinate)d(System)g(Subroutines)98 -b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(65)136 879 y(6.10)49 -b(File)32 b(Chec)m(ksum)e(Subroutines)75 b(.)45 b(.)h(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(67)136 1041 y(6.11)80 -b(Date)32 b(and)d(Time)i(Utilit)m(y)h(Routines)69 b(.)45 -b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(68)136 -1204 y(6.12)49 b(General)32 b(Utilit)m(y)g(Subroutines)61 -b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(69)0 1464 y Fh(7)119 b(The)35 b(CFITSIO)e(Iterator)g(F)-9 -b(unction)2154 b(77)0 1725 y(8)119 b(Extended)35 b(File)f(Name)h(Syn)m -(tax)2330 b(79)136 1887 y Fi(8.1)94 b(Ov)m(erview)84 -b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(79)136 2049 y(8.2)94 -b(Filet)m(yp)s(e)62 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 -b(82)345 2211 y(8.2.1)106 b(Notes)32 b(ab)s(out)e(HTTP)g(pro)m(xy)g -(serv)m(ers)k(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(82)345 -2373 y(8.2.2)106 b(Notes)32 b(ab)s(out)e(the)h(stream)f(\014let)m(yp)s -(e)h(driv)m(er)54 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(83)345 2536 -y(8.2.3)106 b(Notes)32 b(ab)s(out)e(the)h(gsiftp)f(\014let)m(yp)s(e)83 -b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(84)345 2698 -y(8.2.4)106 b(Notes)32 b(ab)s(out)e(the)h(ro)s(ot)f(\014let)m(yp)s(e)68 -b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(84)345 2860 -y(8.2.5)106 b(Notes)32 b(ab)s(out)e(the)h(shmem)e(\014let)m(yp)s(e:)70 -b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(86)136 3022 y(8.3)94 -b(Base)32 b(Filename)90 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(86)136 -3184 y(8.4)94 b(Output)30 b(File)h(Name)g(when)f(Op)s(ening)f(an)h -(Existing)h(File)81 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(88)136 3346 y(8.5)94 -b(T)-8 b(emplate)32 b(File)g(Name)f(when)e(Creating)i(a)g(New)f(File)57 -b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)f(.)85 b(90)136 3508 y(8.6)94 b(Image)32 -b(Tile-Compression)e(Sp)s(eci\014cation)91 b(.)45 b(.)h(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)f(.)85 b(90)136 3670 y(8.7)94 b(HDU)32 b(Lo)s(cation)f(Sp)s -(eci\014cation)47 b(.)e(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -f(.)85 b(90)136 3832 y(8.8)94 b(Image)32 b(Section)39 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)f(.)85 b(91)136 3994 y(8.9)94 b(Image)32 -b(T)-8 b(ransform)29 b(Filters)54 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(92)136 4156 y(8.10)49 -b(Column)30 b(and)g(Keyw)m(ord)g(Filtering)h(Sp)s(eci\014cation)91 -b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)f(.)85 b(94)136 4318 y(8.11)49 b(Ro)m(w)31 -b(Filtering)h(Sp)s(eci\014cation)82 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(96)345 4481 y(8.11.1)61 -b(General)32 b(Syn)m(tax)44 b(.)i(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(97)345 4643 y(8.11.2)61 -b(Bit)32 b(Masks)43 b(.)j(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(99)345 4805 y(8.11.3)61 -b(V)-8 b(ector)32 b(Columns)92 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(100)345 4967 y(8.11.4)61 -b(Go)s(o)s(d)30 b(Time)h(In)m(terv)-5 b(al)31 b(Filtering)62 -b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(102)345 -5129 y(8.11.5)61 b(Spatial)31 b(Region)h(Filtering)59 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(103)345 5291 y(8.11.6)61 b(Example)31 b(Ro)m(w)g(Filters)h(.)45 -b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(105)136 5453 y(8.12)80 b(Binning)30 b(or)g(Histogramming)i(Sp)s -(eci\014cation)f(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(106)0 -5714 y Fh(9)84 b(T)-9 b(emplate)35 b(Files)2933 b(109)p -eop end -%%Page: 6 6 -TeXDict begin 6 5 bop 0 299 a Fi(vi)3311 b Fg(CONTENTS)136 -555 y Fi(9.1)94 b(Detailed)33 b(T)-8 b(emplate)31 b(Line)g(F)-8 -b(ormat)48 b(.)e(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(109)136 715 y(9.2)94 b(Auto-indexing)31 b(of)g(Keyw)m(ords)73 -b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(110)136 876 y(9.3)94 b(T)-8 b(emplate)32 b(P)m(arser)f(Directiv)m(es) -87 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 -b(111)136 1036 y(9.4)94 b(F)-8 b(ormal)32 b(T)-8 b(emplate)32 -b(Syn)m(tax)i(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h -(.)g(.)f(.)40 b(112)136 1196 y(9.5)94 b(Errors)63 b(.)46 -b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(112)136 1356 y(9.6)94 -b(Examples)72 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(112)0 -1607 y Fh(10)67 b(Summary)36 b(of)f(all)f(FITSIO)g(User-In)m(terface)h -(Subroutines)1215 b(115)0 1858 y(11)67 b(P)m(arameter)35 -b(De\014nitions)2563 b(123)0 2109 y(12)67 b(FITSIO)33 -b(Error)i(Status)g(Co)s(des)2295 b(129)p eop end -%%Page: 1 7 -TeXDict begin 1 6 bop 0 1225 a Ff(Chapter)65 b(1)0 1687 -y Fl(In)-6 b(tro)6 b(duction)0 2180 y Fi(This)33 b(do)s(cumen)m(t)i -(describ)s(es)e(the)h(F)-8 b(ortran-callable)38 b(subroutine)33 -b(in)m(terface)j(that)f(is)f(pro)m(vided)g(as)g(part)g(of)h(the)0 -2293 y(CFITSIO)f(library)h(\(whic)m(h)h(is)g(written)g(in)f(ANSI)g -(C\).)h(This)f(is)h(a)g(companion)g(do)s(cumen)m(t)f(to)i(the)e -(CFITSIO)0 2406 y(User's)k(Guide)f(whic)m(h)h(should)e(b)s(e)h -(consulted)h(for)f(further)g(information)h(ab)s(out)f(the)h(underlying) -e(CFITSIO)0 2518 y(library)-8 b(.)50 b(In)32 b(the)i(remainder)f(of)g -(this)h(do)s(cumen)m(t,)g(the)g(terms)f(FITSIO)f(and)h(CFITSIO)f(are)i -(in)m(terc)m(hangeable)0 2631 y(and)c(refer)g(to)h(the)g(same)f -(library)-8 b(.)0 2791 y(FITSIO/CFITSIO)31 b(is)j(a)f(mac)m(hine-indep) -s(enden)m(t)g(library)g(of)h(routines)f(for)g(reading)h(and)f(writing)g -(data)h(\014les)0 2904 y(in)c(the)g(FITS)g(\(Flexible)i(Image)f(T)-8 -b(ransp)s(ort)29 b(System\))h(data)h(format.)41 b(It)31 -b(can)f(also)h(read)g(IRAF)f(format)h(image)0 3017 y(\014les)40 -b(and)e(ra)m(w)i(binary)f(data)h(arra)m(ys)g(b)m(y)g(con)m(v)m(erting)h -(them)e(on)h(the)g(\015y)f(in)m(to)h(a)g(virtual)g(FITS)f(format)h -(\014le.)0 3130 y(This)32 b(library)h(w)m(as)g(written)g(to)h(pro)m -(vide)f(a)h(p)s(o)m(w)m(erful)f(y)m(et)h(simple)f(in)m(terface)h(for)f -(accessing)i(FITS)d(\014les)h(whic)m(h)0 3243 y(will)j(run)e(on)h(most) -h(commonly)g(used)e(computers)h(and)g(w)m(orkstations.)57 -b(FITSIO)34 b(supp)s(orts)g(all)i(the)g(features)0 3356 -y(describ)s(ed)j(in)g(the)h(o\016cial)i(de\014nition)d(of)h(the)g(FITS) -f(format)i(and)e(can)h(read)g(and)f(write)h(all)h(the)f(curren)m(tly)0 -3469 y(de\014ned)g(t)m(yp)s(es)h(of)g(extensions,)j(including)d(ASCI)s -(I)e(tables)j(\(T)-8 b(ABLE\),)42 b(Binary)f(tables)h(\(BINT)-8 -b(ABLE\))43 b(and)0 3582 y(IMA)m(GE)36 b(extensions.)56 -b(The)34 b(FITSIO)g(subroutines)g(insulate)i(the)f(programmer)g(from)g -(ha)m(ving)h(to)g(deal)f(with)0 3695 y(the)25 b(complicated)h -(formatting)g(details)f(in)f(the)h(FITS)f(\014le,)i(ho)m(w)m(ev)m(er,)i -(it)d(is)f(assumed)g(that)h(users)f(ha)m(v)m(e)i(a)f(general)0 -3808 y(kno)m(wledge)31 b(ab)s(out)f(the)h(structure)f(and)g(usage)h(of) -f(FITS)g(\014les.)0 3968 y(The)20 b(CFITSIO)f(pac)m(k)-5 -b(age)23 b(w)m(as)e(initially)i(dev)m(elop)s(ed)e(b)m(y)f(the)h(HEASAR) -m(C)g(\(High)h(Energy)e(Astroph)m(ysics)h(Science)0 4081 -y(Arc)m(hiv)m(e)35 b(Researc)m(h)g(Cen)m(ter\))f(at)h(the)f(NASA)g(Go)s -(ddard)e(Space)j(Fligh)m(t)g(Cen)m(ter)f(to)h(con)m(v)m(ert)g(v)-5 -b(arious)34 b(existing)0 4194 y(and)25 b(newly)h(acquired)g -(astronomical)i(data)e(sets)h(in)m(to)g(FITS)e(format)h(and)f(to)i -(further)e(analyze)i(data)g(already)f(in)0 4307 y(FITS)h(format.)41 -b(New)28 b(features)g(con)m(tin)m(ue)h(to)g(b)s(e)e(added)h(to)g -(CFITSIO)f(in)g(large)i(part)f(due)g(to)g(con)m(tributions)h(of)0 -4419 y(ideas)k(or)g(actual)h(co)s(de)f(from)f(users)g(of)h(the)g(pac)m -(k)-5 b(age.)49 b(The)33 b(In)m(tegral)h(Science)f(Data)h(Cen)m(ter)f -(in)g(Switzerland,)0 4532 y(and)g(the)g(XMM/ESTEC)h(pro)5 -b(ject)34 b(in)f(The)g(Netherlands)g(made)g(esp)s(ecially)i -(signi\014can)m(t)f(con)m(tributions)g(that)0 4645 y(resulted)c(in)g -(man)m(y)h(of)f(the)h(new)f(features)g(that)h(app)s(eared)f(in)g(v2.0)i -(of)e(CFITSIO.)0 4805 y(The)22 b(latest)i(v)m(ersion)f(of)g(the)f -(CFITSIO)f(source)i(co)s(de,)h(do)s(cumen)m(tation,)i(and)21 -b(example)j(programs)e(are)h(a)m(v)-5 b(ailable)0 4918 -y(on)30 b(the)h(W)-8 b(orld-Wide)32 b(W)-8 b(eb)31 b(or)f(via)h(anon)m -(ymous)f(ftp)g(from:)382 5178 y Fe(http://heasarc.gsfc.nasa)o(.go)o -(v/fi)o(tsio)382 5291 y(ftp://legacy.gsfc.nasa.g)o(ov/)o(soft)o(ware)o -(/fi)o(tsio)o(/c)1927 5942 y Fi(1)p eop end -%%Page: 2 8 -TeXDict begin 2 7 bop 0 299 a Fi(2)2452 b Fg(CHAPTER)30 -b(1.)71 b(INTR)m(ODUCTION)0 555 y Fi(An)m(y)28 b(questions,)g(bug)f -(rep)s(orts,)h(or)f(suggested)i(enhancemen)m(ts)f(related)g(to)h(the)e -(CFITSIO)f(pac)m(k)-5 b(age)30 b(should)d(b)s(e)0 668 -y(sen)m(t)k(to)g(the)g(FTOOLS)e(Help)h(Desk)h(at)g(the)g(HEASAR)m(C:) -382 928 y Fe(http://heasarc.gsfc.nasa)o(.go)o(v/cg)o(i-bi)o(n/f)o(tool) -o(shel)o(p)0 1188 y Fi(This)40 b(User's)i(Guide)f(assumes)g(that)h -(readers)f(already)g(ha)m(v)m(e)i(a)f(general)g(understanding)d(of)j -(the)f(de\014nition)0 1301 y(and)31 b(structure)g(of)h(FITS)e(format)i -(\014les.)44 b(F)-8 b(urther)32 b(information)f(ab)s(out)h(FITS)f -(formats)g(is)h(a)m(v)-5 b(ailable)34 b(from)d(the)0 -1413 y(FITS)37 b(Supp)s(ort)f(O\016ce)i(at)h Fe -(http://fits.gsfc.nasa.g)o(ov)p Fi(.)57 b(In)37 b(particular,)j(the)e -('FITS)g(Standard')f(giv)m(es)0 1526 y(the)31 b(authoritativ)m(e)j -(de\014nition)d(of)g(the)h(FITS)e(data)i(format.)43 b(Other)31 -b(do)s(cumen)m(ts)g(a)m(v)-5 b(ailable)34 b(at)d(that)h(W)-8 -b(eb)32 b(site)0 1639 y(pro)m(vide)e(additional)i(historical)f(bac)m -(kground)g(and)e(practical)j(advice)g(on)e(using)g(FITS)f(\014les.)0 -1799 y(The)d(HEASAR)m(C)f(also)i(pro)m(vides)f(a)h(v)m(ery)f -(sophisticated)h(FITS)e(\014le)i(analysis)f(program)g(called)h(`Fv')g -(whic)m(h)f(can)0 1912 y(b)s(e)31 b(used)f(to)i(displa)m(y)f(and)g -(edit)g(the)h(con)m(ten)m(ts)g(of)g(an)m(y)f(FITS)g(\014le)g(as)g(w)m -(ell)h(as)g(construct)f(new)g(FITS)f(\014les)h(from)0 -2025 y(scratc)m(h.)56 b(Fv)36 b(is)f(freely)h(a)m(v)-5 -b(ailable)37 b(for)e(most)h(Unix)f(platforms,)i(Mac)f(PCs,)g(and)f -(Windo)m(ws)g(PCs.)54 b(CFITSIO)0 2138 y(users)29 b(ma)m(y)h(also)h(b)s -(e)f(in)m(terested)g(in)g(the)g(FTOOLS)f(pac)m(k)-5 b(age)31 -b(of)g(programs)e(that)h(can)h(b)s(e)e(used)g(to)i(manipulate)0 -2251 y(and)f(analyze)i(FITS)d(format)i(\014les.)41 b(Fv)30 -b(and)g(FTOOLS)f(are)i(a)m(v)-5 b(ailable)32 b(from)e(their)h(resp)s -(ectiv)m(e)g(W)-8 b(eb)31 b(sites)g(at:)382 2511 y Fe -(http://fv.gsfc.nasa.gov)382 2624 y(http://heasarc.gsfc.nasa)o(.go)o -(v/ft)o(ools)p eop end -%%Page: 3 9 -TeXDict begin 3 8 bop 0 1225 a Ff(Chapter)65 b(2)0 1687 -y Fl(Creating)77 b(FITSIO/CFITSIO)0 2216 y Fd(2.1)135 -b(Building)45 b(the)h(Library)0 2467 y Fi(T)-8 b(o)43 -b(use)g(the)g(FITSIO)f(subroutines)f(one)j(m)m(ust)e(\014rst)g(build)g -(the)h(CFITSIO)f(library)-8 b(,)46 b(whic)m(h)d(requires)f(a)h(C)0 -2580 y(compiler.)73 b(gcc)43 b(is)e(ideal,)j(or)d(most)h(other)f -(ANSI-C)g(compilers)g(will)h(also)g(w)m(ork.)73 b(The)40 -b(CFITSIO)g(co)s(de)h(is)0 2692 y(con)m(tained)25 b(in)f(ab)s(out)f(40) -i(C)f(source)g(\014les)f(\(*.c\))j(and)d(header)h(\014les)g(\(*.h\).)39 -b(On)23 b(V)-10 b(AX/VMS)25 b(systems)f(2)g(assem)m(bly-)0 -2805 y(co)s(de)31 b(\014les)f(\(vmsieeed.mar)h(and)f(vmsieeer.mar\))h -(are)g(also)g(needed.)0 2965 y(The)45 b(F)-8 b(ortran)46 -b(in)m(terface)g(subroutines)e(to)i(the)f(C)g(CFITSIO)f(routines)h(are) -g(lo)s(cated)i(in)e(the)g(f77)p 3538 2965 28 4 v 33 w(wrap1.c,)0 -3078 y(through)22 b(f77)p 459 3078 V 33 w(wrap4.c)h(\014les.)38 -b(These)22 b(are)h(relativ)m(ely)i(simple)d('wrapp)s(ers')f(that)i -(translate)h(the)f(argumen)m(ts)g(in)f(the)0 3191 y(F)-8 -b(ortran)26 b(subroutine)e(in)m(to)j(the)e(appropriate)h(format)g(for)f -(the)g(corresp)s(onding)g(C)g(routine.)39 b(This)24 b(translation)j(is) -0 3304 y(p)s(erformed)19 b(transparen)m(tly)i(to)g(the)g(user)f(b)m(y)g -(a)h(set)h(of)e(C)h(macros)g(lo)s(cated)h(in)e(the)h(cfortran.h)f -(\014le.)38 b(Unfortunately)0 3417 y(cfortran.h)28 b(do)s(es)g(not)g -(supp)s(ort)f(ev)m(ery)h(com)m(bination)i(of)e(C)g(and)f(F)-8 -b(ortran)29 b(compilers)g(so)f(the)h(F)-8 b(ortran)28 -b(in)m(terface)0 3530 y(is)i(not)h(supp)s(orted)e(on)h(all)h -(platforms.)41 b(\(see)31 b(further)e(notes)i(b)s(elo)m(w\).)0 -3690 y(A)f(standard)f(com)m(bination)j(of)e(C)f(and)h(F)-8 -b(ortran)30 b(compilers)h(will)f(b)s(e)f(assumed)h(b)m(y)f(default,)i -(but)e(one)h(ma)m(y)h(also)0 3803 y(sp)s(ecify)f(a)h(particular)f(F)-8 -b(ortran)32 b(compiler)e(b)m(y)h(doing:)48 4064 y Fe(>)95 -b(setenv)46 b(CFLAGS)g(-DcompilerName=1)0 4324 y Fi(\(where)33 -b('compilerName')h(is)f(the)g(name)f(of)h(the)g(compiler\))h(b)s(efore) -e(running)f(the)i(con\014gure)f(command.)47 b(The)0 4437 -y(curren)m(tly)30 b(recognized)i(compiler)f(names)f(are:)48 -4698 y Fe(g77Fortran)48 4811 y(IBMR2Fortran)48 4924 y(CLIPPERFortran)48 -5036 y(pgiFortran)48 5149 y(NAGf90Fortran)48 5262 y(f2cFortran)48 -5375 y(hpuxFortran)48 5488 y(apolloFortran)48 5601 y(sunFortran)48 -5714 y(CRAYFortran)1927 5942 y Fi(3)p eop end -%%Page: 4 10 -TeXDict begin 4 9 bop 0 299 a Fi(4)1896 b Fg(CHAPTER)30 -b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)48 555 -y Fe(mipsFortran)48 668 y(DECFortran)48 781 y(vmsFortran)48 -894 y(CONVEXFortran)48 1007 y(PowerStationFortran)48 -1120 y(AbsoftUNIXFortran)48 1233 y(AbsoftProFortran)48 -1346 y(SXFortran)0 1609 y Fi(Alternativ)m(ely)-8 b(,)42 -b(one)c(ma)m(y)g(edit)g(the)f(CFLA)m(GS)h(line)f(in)h(the)f(Mak)m -(e\014le)i(to)f(add)f(the)h('-DcompilerName')i(\015ag)0 -1722 y(after)31 b(running)e(the)h('./con\014gure')h(command.)0 -1882 y(The)f(CFITSIO)f(library)h(is)g(built)g(on)h(Unix)f(systems)g(b)m -(y)g(t)m(yping:)48 2146 y Fe(>)95 b(./configure)45 b -([--prefix=/target/insta)o(llat)o(ion)o(/pat)o(h])764 -2259 y([--enable-sse2])e([--enable-ssse3])48 2372 y(>)95 -b(make)476 b(\(or)95 b('make)46 b(shared'\))48 2485 y(>)95 -b(make)47 b(install)93 b(\(this)46 b(step)h(is)g(optional\))0 -2749 y Fi(at)24 b(the)g(op)s(erating)g(system)g(prompt.)38 -b(The)23 b(con\014gure)g(command)g(customizes)i(the)f(Mak)m(e\014le)h -(for)f(the)g(particular)0 2861 y(system,)g(then)d(the)g(`mak)m(e')i -(command)e(compiles)h(the)f(source)h(\014les)f(and)g(builds)f(the)h -(library)-8 b(.)38 b(T)m(yp)s(e)21 b(`./con\014gure')0 -2974 y(and)34 b(not)h(simply)f(`con\014gure')h(to)h(ensure)e(that)h -(the)g(con\014gure)g(script)f(in)h(the)g(curren)m(t)f(directory)h(is)g -(run)f(and)0 3087 y(not)29 b(some)g(other)g(system-wide)g(con\014gure)f -(script.)40 b(The)29 b(optional)h('pre\014x')e(argumen)m(t)h(to)g -(con\014gure)g(giv)m(es)h(the)0 3200 y(path)e(to)i(the)f(directory)g -(where)f(the)h(CFITSIO)f(library)g(and)g(include)h(\014les)f(should)g -(b)s(e)g(installed)i(via)f(the)g(later)0 3313 y('mak)m(e)j(install')f -(command.)41 b(F)-8 b(or)31 b(example,)143 3577 y Fe(>)48 -b(./configure)c(--prefix=/usr1/local)0 3841 y Fi(will)25 -b(cause)h(the)f('mak)m(e)h(install')g(command)f(to)h(cop)m(y)g(the)f -(CFITSIO)e(lib)s(c\014tsio)i(\014le)h(to)f(/usr1/lo)s(cal/lib)i(and)e -(the)0 3953 y(necessary)33 b(include)e(\014les)i(to)f(/usr1/lo)s -(cal/include)j(\(assuming)d(of)g(course)g(that)h(the)f(pro)s(cess)g -(has)g(p)s(ermission)0 4066 y(to)f(write)g(to)g(these)g(directories\).) -0 4227 y(The)24 b(optional)i({enable-sse2)g(and)e({enable-ssse3)i -(\015ags)e(will)h(cause)g(con\014gure)f(to)h(attempt)h(to)f(build)e -(CFITSIO)0 4339 y(using)31 b(faster)h(b)m(yte-sw)m(apping)g -(algorithms.)46 b(See)32 b(the)g("Optimizing)g(Programs")g(section)h -(of)f(this)f(man)m(ual)h(for)0 4452 y(more)f(information)f(ab)s(out)g -(these)h(options.)0 4613 y(By)37 b(default,)i(the)f(Mak)m(e\014le)g -(will)g(b)s(e)e(con\014gured)g(to)i(build)e(the)h(set)h(of)f(F)-8 -b(ortran-callable)40 b(wrapp)s(er)35 b(routines)0 4725 -y(whose)30 b(calling)i(sequences)f(are)f(describ)s(ed)g(later)h(in)f -(this)g(do)s(cumen)m(t.)0 4886 y(The)e('mak)m(e)h(shared')f(option)h -(builds)e(a)i(shared)e(or)i(dynamic)f(v)m(ersion)h(of)f(the)h(CFITSIO)d -(library)-8 b(.)40 b(When)28 b(using)0 4999 y(the)f(shared)f(library)h -(the)g(executable)h(co)s(de)f(is)g(not)g(copied)g(in)m(to)h(y)m(our)f -(program)g(at)g(link)g(time)g(and)g(instead)g(the)0 5111 -y(program)g(lo)s(cates)i(the)f(necessary)g(library)f(co)s(de)h(at)g -(run)e(time,)j(normally)f(through)e(LD)p 3065 5111 28 -4 v 33 w(LIBRAR)-8 b(Y)p 3514 5111 V 34 w(P)g(A)g(TH)28 -b(or)0 5224 y(some)j(other)f(metho)s(d.)41 b(The)29 b(adv)-5 -b(an)m(tages)33 b(of)d(using)g(a)h(shared)e(library)h(are:)143 -5488 y Fe(1.)95 b(Less)47 b(disk)f(space)h(if)g(you)g(build)f(more)h -(than)f(1)i(program)143 5601 y(2.)95 b(Less)47 b(memory)f(if)h(more)g -(than)f(one)h(copy)g(of)g(a)g(program)f(using)h(the)g(shared)334 -5714 y(library)f(is)h(running)f(at)h(the)g(same)g(time)f(since)h(the)g -(system)f(is)h(smart)p eop end -%%Page: 5 11 -TeXDict begin 5 10 bop 0 299 a Fg(2.1.)72 b(BUILDING)31 -b(THE)f(LIBRAR)-8 b(Y)2507 b Fi(5)334 555 y Fe(enough)46 -b(to)h(share)g(copies)f(of)h(the)g(shared)f(library)g(at)h(run)g(time.) -143 668 y(3.)95 b(Possibly)46 b(easier)g(maintenance)e(since)j(a)g(new) -g(version)f(of)h(the)g(shared)334 781 y(library)f(can)h(be)g(installed) -e(without)h(relinking)f(all)i(the)g(software)334 894 -y(that)g(uses)f(it)i(\(as)e(long)h(as)g(the)g(subroutine)e(names)i(and) -f(calling)334 1007 y(sequences)f(remain)h(unchanged\).)143 -1120 y(4.)95 b(No)47 b(run-time)f(penalty.)0 1534 y Fi(The)30 -b(disadv)-5 b(an)m(tages)32 b(are:)143 1949 y Fe(1.)47 -b(More)g(hassle)f(at)h(runtime.)94 b(You)46 b(have)h(to)g(either)f -(build)h(the)g(programs)286 2062 y(specially)f(or)h(have)f -(LD_LIBRARY_PATH)e(set)j(right.)143 2175 y(2.)g(There)g(may)g(be)g(a)g -(slight)f(start)h(up)g(penalty,)e(depending)h(on)h(where)f(you)h(are) -286 2288 y(reading)f(the)h(shared)f(library)g(and)h(the)g(program)f -(from)g(and)h(if)g(your)g(CPU)g(is)286 2401 y(either)f(really)h(slow)f -(or)h(really)f(heavily)g(loaded.)0 2815 y Fi(On)30 b(HP/UX)i(systems,)g -(the)f(en)m(vironmen)m(t)h(v)-5 b(ariable)32 b(CFLA)m(GS)f(should)f(b)s -(e)h(set)g(to)h(-Ae)g(b)s(efore)f(running)e(con-)0 2928 -y(\014gure)h(to)h(enable)g("extended)g(ANSI")f(features.)0 -3088 y(It)j(ma)m(y)g(not)g(b)s(e)f(p)s(ossible)g(to)h(statically)i -(link)e(programs)f(that)h(use)g(CFITSIO)e(on)h(some)h(platforms)g -(\(namely)-8 b(,)0 3201 y(on)28 b(Solaris)h(2.6\))h(due)e(to)h(the)g -(net)m(w)m(ork)g(driv)m(ers)f(\(whic)m(h)h(pro)m(vide)g(FTP)f(and)g -(HTTP)g(access)h(to)h(FITS)d(\014les\).)41 b(It)0 3314 -y(is)33 b(p)s(ossible)f(to)i(mak)m(e)f(b)s(oth)g(a)g(dynamic)f(and)g(a) -i(static)g(v)m(ersion)f(of)g(the)g(CFITSIO)e(library)-8 -b(,)34 b(but)e(net)m(w)m(ork)i(\014le)0 3427 y(access)e(will)e(not)h(b) -s(e)f(p)s(ossible)g(using)g(the)g(static)i(v)m(ersion.)0 -3587 y(On)c(V)-10 b(AX/VMS)31 b(and)d(ALPHA/VMS)i(systems)f(the)h(mak)m -(e)p 2100 3587 28 4 v 34 w(g\015oat.com)h(command)e(\014le)g(ma)m(y)h -(b)s(e)f(executed)h(to)0 3700 y(build)35 b(the)i(c\014tsio.olb)g(ob)5 -b(ject)37 b(library)f(using)g(the)g(default)h(G-\015oating)g(p)s(oin)m -(t)g(option)f(for)g(double)g(v)-5 b(ariables.)0 3813 -y(The)37 b(mak)m(e)p 405 3813 V 33 w(d\015oat.com)i(and)d(mak)m(e)p -1279 3813 V 34 w(ieee.com)j(\014les)f(ma)m(y)f(b)s(e)g(used)f(instead)i -(to)g(build)e(the)h(library)g(with)g(the)0 3926 y(other)26 -b(\015oating)i(p)s(oin)m(t)e(options.)39 b(Note)28 b(that)f(the)f -(getcwd)h(function)f(that)h(is)f(used)f(in)h(the)h(group.c)f(mo)s(dule) -f(ma)m(y)0 4039 y(require)44 b(that)i(programs)e(using)g(CFITSIO)f(b)s -(e)h(link)m(ed)i(with)e(the)h(ALPHA$LIBRAR)-8 b(Y:V)e(AX)m(CR)i(TL.OLB) -0 4152 y(library)g(.)41 b(See)30 b(the)h(example)g(link)f(line)h(in)f -(the)h(next)f(section)i(of)e(this)h(do)s(cumen)m(t.)0 -4312 y(On)25 b(Windo)m(ws)h(IBM-PC)g(t)m(yp)s(e)g(platforms)f(the)h -(situation)h(is)e(more)h(complicated)i(b)s(ecause)d(of)h(the)g(wide)g -(v)-5 b(ariet)m(y)0 4425 y(of)43 b(F)-8 b(ortran)43 b(compilers)h(that) -f(are)g(a)m(v)-5 b(ailable)45 b(and)d(b)s(ecause)h(of)g(the)g(inheren)m -(t)g(complexities)i(of)d(calling)j(the)0 4538 y(CFITSIO)25 -b(C)g(routines)h(from)g(F)-8 b(ortran.)40 b(Tw)m(o)26 -b(di\013eren)m(t)h(v)m(ersions)f(of)g(the)h(CFITSIO)d(dll)i(library)g -(are)g(a)m(v)-5 b(ailable,)0 4650 y(compiled)28 b(with)e(the)i(Borland) -f(C++)f(compiler)i(and)e(the)i(Microsoft)g(Visual)g(C++)e(compiler,)i -(resp)s(ectiv)m(ely)-8 b(,)30 b(in)0 4763 y(the)g(\014les)g(c\014tsio)s -(dll)p 679 4763 V 33 w(2xxx)p 901 4763 V 34 w(b)s(orland.zip)f(and)g -(c\014tsio)s(dll)p 1924 4763 V 33 w(3xxx)p 2146 4763 -V 33 w(v)m(cc.zip,)j(where)e('3xxx')h(represen)m(ts)f(the)g(curren)m(t) -0 4876 y(release)44 b(n)m(um)m(b)s(er.)76 b(Both)43 b(these)g(dll)g -(libraries)g(con)m(tain)h(a)f(set)g(of)f(F)-8 b(ortran)44 -b(wrapp)s(er)d(routines)h(whic)m(h)g(ma)m(y)0 4989 y(b)s(e)37 -b(compatible)i(with)e(some,)j(but)d(probably)g(not)g(all,)k(a)m(v)-5 -b(ailable)40 b(F)-8 b(ortran)38 b(compilers.)63 b(T)-8 -b(o)38 b(test)g(if)g(they)g(are)0 5102 y(compatible,)29 -b(compile)f(the)f(program)g(testf77.f)h(and)f(try)f(linking)i(to)f -(these)h(dll)e(libraries.)40 b(If)27 b(these)g(libraries)g(do)0 -5215 y(not)22 b(w)m(ork)g(with)g(a)g(particular)g(F)-8 -b(ortran)22 b(compiler,)j(then)c(it)i(ma)m(y)f(b)s(e)f(necessary)i(to)f -(mo)s(dify)f(the)h(\014le)g("cfortran.h")0 5328 y(to)28 -b(supp)s(ort)d(that)j(particular)f(com)m(bination)i(of)e(C)g(and)f(F)-8 -b(ortran)28 b(compilers,)h(and)d(then)h(rebuild)f(the)h(CFITSIO)0 -5441 y(dll)j(library)-8 b(.)41 b(This)30 b(will)g(require,)h(ho)m(w)m -(ev)m(er,)h(some)e(exp)s(ertise)h(in)f(mixed)g(language)i(programming.) -0 5601 y(CFITSIO)f(should)g(b)s(e)g(compatible)j(with)d(most)i(curren)m -(t)f(ANCI)g(C)f(and)h(C++)f(compilers:)44 b(Cra)m(y)33 -b(sup)s(ercom-)0 5714 y(puters)d(are)g(curren)m(tly)h(not)f(supp)s -(orted.)p eop end -%%Page: 6 12 -TeXDict begin 6 11 bop 0 299 a Fi(6)1896 b Fg(CHAPTER)30 -b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)0 555 y -Fd(2.2)135 b(T)-11 b(esting)46 b(the)f(Library)0 805 -y Fi(The)40 b(CFITSIO)e(library)i(should)f(b)s(e)g(tested)i(b)m(y)f -(building)f(and)g(running)g(the)h(testprog.c)h(program)f(that)h(is)0 -918 y(included)30 b(with)g(the)g(release.)42 b(On)30 -b(Unix)g(systems)g(t)m(yp)s(e:)191 1156 y Fe(\045)47 -b(make)g(testprog)191 1269 y(\045)g(testprog)f(>)h(testprog.lis)191 -1382 y(\045)g(diff)g(testprog.lis)d(testprog.out)191 -1495 y(\045)j(cmp)g(testprog.fit)e(testprog.std)0 1733 -y Fi(On)30 b(VMS)g(systems,)g(\(assuming)h(cc)g(is)f(the)h(name)f(of)h -(the)f(C)g(compiler)h(command\),)g(t)m(yp)s(e:)191 1970 -y Fe($)47 b(cc)h(testprog.c)191 2083 y($)f(link)g(testprog,)e -(cfitsio/lib,)g(alpha$library:vaxcrtl/l)o(ib)191 2196 -y($)i(run)g(testprog)0 2434 y Fi(The)30 b(testprog)h(program)g(should)e -(pro)s(duce)g(a)i(FITS)f(\014le)g(called)i(`testprog.\014t')g(that)f -(is)f(iden)m(tical)j(to)e(the)f(`test-)0 2547 y(prog.std')25 -b(FITS)f(\014le)g(included)g(with)g(this)h(release.)40 -b(The)24 b(diagnostic)i(messages)g(\(whic)m(h)e(w)m(ere)h(pip)s(ed)f -(to)h(the)g(\014le)0 2660 y(testprog.lis)h(in)e(the)h(Unix)f(example\)) -i(should)d(b)s(e)h(iden)m(tical)j(to)e(the)g(listing)g(con)m(tained)h -(in)e(the)h(\014le)f(testprog.out.)0 2773 y(The)30 b('di\013)7 -b(')31 b(and)e('cmp')i(commands)f(sho)m(wn)g(ab)s(o)m(v)m(e)h(should)f -(not)g(rep)s(ort)g(an)m(y)h(di\013erences)g(in)f(the)g(\014les.)41 -b(\(There)0 2886 y(ma)m(y)35 b(b)s(e)e(some)h(minor)g(formatting)g -(di\013erences,)i(suc)m(h)d(as)i(the)f(presence)g(or)g(absence)g(of)g -(leading)h(zeros,)h(or)e(3)0 2999 y(digit)d(exp)s(onen)m(ts)f(in)g(n)m -(um)m(b)s(ers,)g(whic)m(h)g(can)g(b)s(e)g(ignored\).)0 -3159 y(The)f(F)-8 b(ortran)31 b(wrapp)s(ers)d(in)h(CFITSIO)f(ma)m(y)j -(b)s(e)e(tested)h(with)g(the)g(testf77)h(program.)40 -b(On)29 b(Unix)h(systems)g(the)0 3272 y(fortran)g(compilation)i(and)e -(link)g(command)g(ma)m(y)h(b)s(e)f(called)h('f77')h(or)e('g77',)j(dep)s -(ending)c(on)h(the)g(system.)143 3509 y Fe(\045)48 b(f77)f(-o)g -(testf77)f(testf77.f)f(-L.)i(-lcfitsio)e(-lnsl)h(-lsocket)48 -3622 y(or)143 3735 y(\045)i(f77)f(-f)g(-o)g(testf77)f(testf77.f)f(-L.)i -(-lcfitsio)188 b(\(under)46 b(SUN)h(O/S\))48 3848 y(or)143 -3961 y(\045)h(f77)f(-o)g(testf77)f(testf77.f)f(-Wl,-L.)h(-lcfitsio)f -(-lm)i(-lnsl)f(-lsocket)g(\(HP/UX\))48 4074 y(or)143 -4187 y(\045)i(g77)f(-o)g(testf77)f(-s)h(testf77.f)e(-lcfitsio)g -(-lcc_dynamic)g(-lncurses)g(\(Mac)i(OS-X\))143 4413 y(\045)h(testf77)d -(>)j(testf77.lis)143 4526 y(\045)g(diff)e(testf77.lis)f(testf77.out)143 -4638 y(\045)j(cmp)f(testf77.fit)d(testf77.std)0 4876 -y Fi(On)31 b(mac)m(hines)h(running)f(SUN)g(O/S,)h(F)-8 -b(ortran)33 b(programs)e(m)m(ust)h(b)s(e)f(compiled)h(with)g(the)g('-f) -7 b(')32 b(option)h(to)f(force)0 4989 y(double)24 b(precision)g(v)-5 -b(ariables)25 b(to)g(b)s(e)e(aligned)i(on)f(8-b)m(yte)i(b)s(oundaries)c -(to)j(mak)m(e)g(the)g(fortran-declared)f(v)-5 b(ariables)0 -5102 y(compatible)34 b(with)e(C.)g(A)h(similar)g(compiler)g(option)g -(ma)m(y)g(b)s(e)f(required)g(on)g(other)h(platforms.)48 -b(F)-8 b(ailing)34 b(to)f(use)0 5215 y(this)26 b(option)g(ma)m(y)g -(cause)h(the)f(program)f(to)i(crash)e(on)h(FITSIO)f(routines)g(that)i -(read)f(or)f(write)h(double)g(precision)0 5328 y(v)-5 -b(ariables.)0 5488 y(On)27 b(Windo)m(ws)h(platforms,)g(linking)g(F)-8 -b(ortran)28 b(programs)f(with)h(a)g(C)f(library)g(often)h(dep)s(ends)e -(on)i(the)g(particular)0 5601 y(compilers)40 b(in)m(v)m(olv)m(ed.)71 -b(Some)40 b(users)f(ha)m(v)m(e)i(found)d(the)i(follo)m(wing)i(commands) -d(w)m(ork)h(when)f(using)g(the)h(In)m(tel)0 5714 y(F)-8 -b(ortran)31 b(compiler:)p eop end -%%Page: 7 13 -TeXDict begin 7 12 bop 0 299 a Fg(2.3.)72 b(LINKING)30 -b(PR)m(OGRAMS)h(WITH)f(FITSIO)2041 b Fi(7)0 555 y Fe(ifort)46 -b(/libs.dll)g(cfitsio.lib)e(/MD)j(testf77.f)f(/Gm)0 781 -y(or)h(possibly,)0 1007 y(ifort)f(/libs:dll)g(cfitsio.lib)e(/MD)j(/fpp) -g(/extfpp:cfortran.h,fitsi)o(o.h)191 1120 y(/iface:cvf)e(testf77.f)0 -1335 y Fi(Also)32 b(note)h(that)f(on)g(some)g(systems)f(the)h(output)g -(listing)g(of)g(the)g(testf77)h(program)f(ma)m(y)g(di\013er)f(sligh)m -(tly)i(from)0 1448 y(the)f(testf77.std)i(template)g(if)e(leading)h -(zeros)g(are)g(not)g(prin)m(ted)e(b)m(y)i(default)f(b)s(efore)g(the)g -(decimal)i(p)s(oin)m(t)e(when)0 1561 y(using)e(F)h(format.)0 -1721 y(A)f(few)h(other)f(utilit)m(y)i(programs)e(are)h(included)e(with) -h(CFITSIO:)191 1937 y Fe(speed)46 b(-)i(measures)d(the)i(maximum)f -(throughput)f(\(in)i(MB)g(per)g(second\))668 2050 y(for)g(writing)f -(and)h(reading)f(FITS)g(files)h(with)f(CFITSIO)191 2275 -y(listhead)f(-)j(lists)e(all)h(the)g(header)f(keywords)g(in)h(any)g -(FITS)f(file)191 2501 y(fitscopy)f(-)j(copies)e(any)h(FITS)g(file)f -(\(especially)f(useful)h(in)h(conjunction)811 2614 y(with)g(the)g -(CFITSIO's)e(extended)h(input)g(filename)g(syntax\))191 -2840 y(cookbook)f(-)j(a)f(sample)f(program)g(that)h(performs)e(common)i -(read)f(and)811 2953 y(write)h(operations)e(on)i(a)g(FITS)g(file.)191 -3179 y(iter_a,)f(iter_b,)g(iter_c)g(-)h(examples)f(of)h(the)g(CFITSIO)f -(iterator)f(routine)0 3394 y Fi(The)30 b(\014rst)f(4)i(of)g(these)g -(utilit)m(y)g(programs)f(can)h(b)s(e)f(compiled)h(and)e(link)m(ed)i(b)m -(y)f(t)m(yping)143 3610 y Fe(\045)95 b(make)47 b(program_name)0 -3936 y Fd(2.3)135 b(Linking)45 b(Programs)h(with)f(FITSIO)0 -4186 y Fi(When)31 b(linking)g(applications)i(soft)m(w)m(are)f(with)f -(the)g(FITSIO)f(library)-8 b(,)32 b(sev)m(eral)h(system)e(libraries)g -(usually)g(need)0 4299 y(to)26 b(b)s(e)f(sp)s(eci\014ed)g(on)g(the)h -(link)g(comman)f(Unix)h(systems,)h(the)e(most)h(reliable)h(w)m(a)m(y)f -(to)h(determine)e(what)h(libraries)0 4412 y(are)32 b(required)f(is)g -(to)i(t)m(yp)s(e)e('mak)m(e)i(testprog')g(and)e(see)h(what)f(libraries) -h(the)g(con\014gure)f(script)h(has)f(added.)43 b(The)0 -4525 y(t)m(ypical)25 b(libraries)f(that)g(ma)m(y)g(need)f(to)h(b)s(e)f -(added)g(are)g(-lm)h(\(the)g(math)f(library\))h(and)f(-lnsl)g(and)g -(-lso)s(c)m(k)m(et)j(\(needed)0 4638 y(only)h(for)f(FTP)g(and)g(HTTP)g -(\014le)h(access\).)41 b(These)26 b(latter)i(2)f(libraries)g(are)g(not) -g(needed)f(on)g(VMS)h(and)f(Windo)m(ws)0 4751 y(platforms,)31 -b(b)s(ecause)f(FTP)g(\014le)h(access)g(is)g(not)f(curren)m(tly)h(supp)s -(orted)d(on)i(those)h(platforms.)0 4911 y(Note)i(that)g(when)e -(upgrading)g(to)i(a)f(new)m(er)g(v)m(ersion)g(of)g(CFITSIO)f(it)h(is)g -(usually)g(necessary)g(to)h(recompile,)h(as)0 5024 y(w)m(ell)d(as)g -(relink,)g(the)f(programs)g(that)h(use)f(CFITSIO,)f(b)s(ecause)i(the)f -(de\014nitions)g(in)g(\014tsio.h)h(often)f(c)m(hange.)0 -5351 y Fd(2.4)135 b(Getting)46 b(Started)g(with)f(FITSIO)0 -5601 y Fi(In)32 b(order)h(to)h(e\013ectiv)m(ely)i(use)d(the)g(FITSIO)f -(library)h(as)h(quic)m(kly)g(as)f(p)s(ossible,)h(it)g(is)f(recommended) -g(that)g(new)0 5714 y(users)d(follo)m(w)h(these)g(steps:)p -eop end -%%Page: 8 14 -TeXDict begin 8 13 bop 0 299 a Fi(8)1896 b Fg(CHAPTER)30 -b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)0 555 y -Fi(1.)62 b(Read)38 b(the)f(follo)m(wing)i(`FITS)e(Primer')g(c)m(hapter) -h(for)g(a)f(brief)g(o)m(v)m(erview)i(of)f(the)g(structure)e(of)i(FITS)f -(\014les.)0 668 y(This)25 b(is)h(esp)s(ecially)h(imp)s(ortan)m(t)g(for) -e(users)h(who)f(ha)m(v)m(e)i(not)g(previously)e(dealt)i(with)f(the)g -(FITS)f(table)i(and)f(image)0 781 y(extensions.)0 941 -y(2.)41 b(W)-8 b(rite)32 b(a)f(simple)f(program)g(to)h(read)g(or)f -(write)g(a)h(FITS)f(\014le)g(using)g(the)h(Basic)g(In)m(terface)h -(routines.)0 1101 y(3.)41 b(Refer)28 b(to)i(the)f(co)s(okb)s(o)s(ok.f)g -(program)f(that)i(is)f(included)f(with)g(this)h(release)h(for)e -(examples)i(of)f(routines)f(that)0 1214 y(p)s(erform)h(v)-5 -b(arious)30 b(common)h(FITS)f(\014le)g(op)s(erations.)0 -1374 y(4.)52 b(Read)34 b(Chapters)g(4)g(and)f(5)i(to)g(b)s(ecome)f -(familiar)h(with)e(the)i(con)m(v)m(en)m(tions)h(and)d(adv)-5 -b(anced)34 b(features)h(of)f(the)0 1487 y(FITSIO)29 b(in)m(terface.)0 -1647 y(5.)47 b(Scan)32 b(through)f(the)h(more)h(extensiv)m(e)g(set)g -(of)g(routines)f(that)g(are)h(pro)m(vided)f(in)g(the)g(`Adv)-5 -b(anced)32 b(In)m(terface'.)0 1760 y(These)22 b(routines)f(p)s(erform)g -(more)h(sp)s(ecialized)h(functions)e(than)g(are)i(pro)m(vided)e(b)m(y)h -(the)g(Basic)h(In)m(terface)g(routines.)0 2124 y Fd(2.5)135 -b(Example)46 b(Program)0 2380 y Fi(The)32 b(follo)m(wing)i(listing)f -(sho)m(ws)f(an)g(example)i(of)e(ho)m(w)h(to)g(use)f(the)g(FITSIO)g -(routines)g(in)g(a)h(F)-8 b(ortran)33 b(program.)0 2493 -y(Refer)38 b(to)h(the)g(co)s(okb)s(o)s(ok.f)f(program)g(that)h(is)f -(included)f(with)h(the)h(FITSIO)e(distribution)g(for)h(examples)h(of)0 -2606 y(other)31 b(FITS)e(programs.)286 2891 y Fe(program)46 -b(writeimage)0 3117 y(C)238 b(Create)46 b(a)i(FITS)f(primary)e(array)i -(containing)e(a)i(2-D)g(image)286 3343 y(integer)f -(status,unit,blocksize,bit)o(pix,)o(nax)o(is,n)o(axes)o(\(2\))286 -3456 y(integer)g(i,j,group,fpixel,nelement)o(s,ar)o(ray)o(\(300)o(,200) -o(\))286 3569 y(character)g(filename*80)286 3681 y(logical)g -(simple,extend)286 3907 y(status=0)0 4020 y(C)238 b(Name)47 -b(of)g(the)g(FITS)g(file)f(to)i(be)f(created:)286 4133 -y(filename='ATESTFILE.FITS')0 4359 y(C)238 b(Get)47 b(an)g(unused)g -(Logical)e(Unit)i(Number)f(to)h(use)g(to)g(create)f(the)h(FITS)g(file) -286 4472 y(call)g(ftgiou\(unit,status\))0 4698 y(C)238 -b(create)46 b(the)h(new)g(empty)g(FITS)f(file)286 4811 -y(blocksize=1)286 4924 y(call)h(ftinit\(unit,filename,blo)o(cksi)o -(ze,s)o(tat)o(us\))0 5149 y(C)238 b(initialize)45 b(parameters)g(about) -i(the)g(FITS)f(image)h(\(300)f(x)i(200)f(16-bit)f(integers\))286 -5262 y(simple=.true.)286 5375 y(bitpix=16)286 5488 y(naxis=2)286 -5601 y(naxes\(1\)=300)286 5714 y(naxes\(2\)=200)p eop -end -%%Page: 9 15 -TeXDict begin 9 14 bop 0 299 a Fg(2.6.)72 b(LEGAL)30 -b(STUFF)2995 b Fi(9)286 555 y Fe(extend=.true.)0 781 -y(C)238 b(write)47 b(the)g(required)e(header)h(keywords)286 -894 y(call)h(ftphpr\(unit,simple,bitpi)o(x,na)o(xis,)o(nax)o(es,0)o -(,1,e)o(xte)o(nd,s)o(tatu)o(s\))0 1120 y(C)238 b(initialize)45 -b(the)i(values)f(in)i(the)e(image)h(with)f(a)i(linear)e(ramp)h -(function)286 1233 y(do)h(j=1,naxes\(2\))477 1346 y(do)f -(i=1,naxes\(1\))668 1458 y(array\(i,j\)=i+j)477 1571 -y(end)g(do)286 1684 y(end)g(do)0 1910 y(C)238 b(write)47 -b(the)g(array)f(to)h(the)g(FITS)g(file)286 2023 y(group=1)286 -2136 y(fpixel=1)286 2249 y(nelements=naxes\(1\)*naxes\(2)o(\))286 -2362 y(call)g(ftpprj\(unit,group,fpixel)o(,nel)o(emen)o(ts,)o(arra)o -(y,st)o(atu)o(s\))0 2588 y(C)238 b(write)47 b(another)f(optional)f -(keyword)h(to)h(the)g(header)286 2700 y(call)g -(ftpkyj\(unit,'EXPOSURE',1)o(500,)o('Tot)o(al)41 b(Exposure)46 -b(Time',status\))0 2926 y(C)238 b(close)47 b(the)g(file)f(and)h(free)g -(the)g(unit)f(number)286 3039 y(call)h(ftclos\(unit,)d(status\))286 -3152 y(call)j(ftfiou\(unit,)d(status\))286 3265 y(end)0 -3623 y Fd(2.6)135 b(Legal)46 b(Stu\013)0 3878 y Fi(Cop)m(yrigh)m(t)37 -b(\(Unpublished{all)g(righ)m(ts)g(reserv)m(ed)g(under)e(the)i(cop)m -(yrigh)m(t)h(la)m(ws)f(of)g(the)g(United)g(States\),)j(U.S.)0 -3991 y(Go)m(v)m(ernmen)m(t)30 b(as)g(represen)m(ted)e(b)m(y)h(the)g -(Administrator)g(of)g(the)g(National)h(Aeronautics)g(and)e(Space)h -(Adminis-)0 4104 y(tration.)42 b(No)31 b(cop)m(yrigh)m(t)g(is)g -(claimed)g(in)f(the)h(United)f(States)h(under)e(Title)j(17,)f(U.S.)f -(Co)s(de.)0 4264 y(P)m(ermission)g(to)g(freely)f(use,)h(cop)m(y)-8 -b(,)31 b(mo)s(dify)-8 b(,)29 b(and)g(distribute)g(this)g(soft)m(w)m -(are)i(and)e(its)h(do)s(cumen)m(tation)g(without)0 4377 -y(fee)f(is)f(hereb)m(y)g(gran)m(ted,)i(pro)m(vided)e(that)h(this)f(cop) -m(yrigh)m(t)i(notice)f(and)f(disclaimer)h(of)f(w)m(arran)m(t)m(y)i(app) -s(ears)d(in)h(all)0 4490 y(copies.)0 4650 y(DISCLAIMER:)0 -4811 y(THE)33 b(SOFTW)-10 b(ARE)32 b(IS)g(PR)m(O)m(VIDED)i('AS)f(IS')g -(WITHOUT)f(ANY)i(W)-10 b(ARRANTY)33 b(OF)g(ANY)h(KIND,)f(EI-)0 -4924 y(THER)42 b(EXPRESSED,)f(IMPLIED,)i(OR)e(ST)-8 b(A)g(TUTOR)g(Y,)43 -b(INCLUDING,)f(BUT)h(NOT)e(LIMITED)h(TO,)0 5036 y(ANY)33 -b(W)-10 b(ARRANTY)33 b(THA)-8 b(T)32 b(THE)g(SOFTW)-10 -b(ARE)32 b(WILL)g(CONF)m(ORM)g(TO)g(SPECIFICA)-8 b(TIONS,)30 -b(ANY)0 5149 y(IMPLIED)38 b(W)-10 b(ARRANTIES)37 b(OF)h(MER)m(CHANT)-8 -b(ABILITY,)38 b(FITNESS)f(F)m(OR)h(A)g(P)-8 b(AR)g(TICULAR)38 -b(PUR-)0 5262 y(POSE,)24 b(AND)i(FREEDOM)f(FR)m(OM)h(INFRINGEMENT,)g -(AND)f(ANY)h(W)-10 b(ARRANTY)25 b(THA)-8 b(T)25 b(THE)g(DOC-)0 -5375 y(UMENT)-8 b(A)g(TION)31 b(WILL)f(CONF)m(ORM)h(TO)e(THE)h(SOFTW) --10 b(ARE,)30 b(OR)g(ANY)h(W)-10 b(ARRANTY)31 b(THA)-8 -b(T)30 b(THE)0 5488 y(SOFTW)-10 b(ARE)31 b(WILL)h(BE)g(ERR)m(OR)g -(FREE.)g(IN)g(NO)g(EVENT)f(SHALL)g(NASA)h(BE)g(LIABLE)g(F)m(OR)g(ANY)0 -5601 y(D)m(AMA)m(GES,)26 b(INCLUDING,)e(BUT)f(NOT)g(LIMITED)h(TO,)f -(DIRECT,)g(INDIRECT,)g(SPECIAL)f(OR)h(CON-)0 5714 y(SEQUENTIAL)28 -b(D)m(AMA)m(GES,)k(ARISING)d(OUT)g(OF,)h(RESUL)-8 b(TING)29 -b(FR)m(OM,)h(OR)f(IN)h(ANY)g(W)-10 b(A)i(Y)30 b(CON-)p -eop end -%%Page: 10 16 -TeXDict begin 10 15 bop 0 299 a Fi(10)1851 b Fg(CHAPTER)30 -b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)0 555 y -Fi(NECTED)25 b(WITH)g(THIS)f(SOFTW)-10 b(ARE,)25 b(WHETHER)g(OR)g(NOT)g -(BASED)g(UPON)g(W)-10 b(ARRANTY,)26 b(CON-)0 668 y(TRA)m(CT,)d(TOR)-8 -b(T)23 b(,)g(OR)g(OTHER)-10 b(WISE,)22 b(WHETHER)i(OR)f(NOT)f(INJUR)-8 -b(Y)24 b(W)-10 b(AS)23 b(SUST)-8 b(AINED)23 b(BY)h(PER-)0 -781 y(SONS)h(OR)i(PR)m(OPER)-8 b(TY)26 b(OR)g(OTHER)-10 -b(WISE,)26 b(AND)h(WHETHER)g(OR)f(NOT)g(LOSS)f(W)-10 -b(AS)26 b(SUST)-8 b(AINED)0 894 y(FR)m(OM,)37 b(OR)e(AR)m(OSE)h(OUT)f -(OF)h(THE)g(RESUL)-8 b(TS)35 b(OF,)h(OR)f(USE)h(OF,)g(THE)g(SOFTW)-10 -b(ARE)35 b(OR)g(SER-)0 1007 y(VICES)29 b(PR)m(O)m(VIDED)j(HEREUNDER.")0 -1451 y Fd(2.7)135 b(Ac)l(kno)l(wledgmen)l(ts)0 1723 y -Fi(The)29 b(dev)m(elopmen)m(t)h(of)g(man)m(y)f(of)h(the)f(p)s(o)m(w)m -(erful)g(features)g(in)g(CFITSIO)f(w)m(as)i(made)f(p)s(ossible)g -(through)f(collab-)0 1836 y(orations)35 b(with)f(man)m(y)h(p)s(eople)f -(or)h(organizations)h(from)e(around)f(the)i(w)m(orld.)52 -b(The)34 b(follo)m(wing,)j(in)d(particular,)0 1949 y(ha)m(v)m(e)e(made) -e(esp)s(ecially)i(signi\014can)m(t)f(con)m(tributions:)0 -2109 y(Programmers)25 b(from)h(the)f(In)m(tegral)i(Science)g(Data)g -(Cen)m(ter,)g(Switzerland)f(\(namely)-8 b(,)28 b(Jurek)c(Bork)m(o)m -(wski,)29 b(Bruce)0 2222 y(O'Neel,)34 b(and)e(Don)h(Jennings\),)f -(designed)g(the)h(concept)g(for)f(the)h(plug-in)f(I/O)g(driv)m(ers)g -(that)h(w)m(as)g(in)m(tro)s(duced)0 2335 y(with)i(CFITSIO)e(2.0.)56 -b(The)34 b(use)h(of)g(`driv)m(ers')g(greatly)h(simpli\014ed)f(the)g(lo) -m(w-lev)m(el)j(I/O,)d(whic)m(h)f(in)h(turn)f(made)0 2448 -y(other)40 b(new)f(features)i(in)e(CFITSIO)f(\(e.g.,)45 -b(supp)s(ort)38 b(for)h(compressed)h(FITS)f(\014les)h(and)f(supp)s(ort) -f(for)i(IRAF)0 2560 y(format)32 b(image)g(\014les\))g(m)m(uc)m(h)f -(easier)i(to)f(implemen)m(t.)44 b(Jurek)31 b(Bork)m(o)m(wski)h(wrote)g -(the)g(Shared)e(Memory)i(driv)m(er,)0 2673 y(and)23 b(Bruce)i(O'Neel)g -(wrote)f(the)g(driv)m(ers)g(for)f(accessing)j(FITS)d(\014les)h(o)m(v)m -(er)h(the)f(net)m(w)m(ork)h(using)e(the)i(FTP)-8 b(,)24 -b(HTTP)-8 b(,)0 2786 y(and)30 b(R)m(OOT)g(proto)s(cols.)0 -2946 y(The)45 b(ISDC)g(also)h(pro)m(vided)f(the)h(template)h(parsing)e -(routines)g(\(written)h(b)m(y)f(Jurek)g(Bork)m(o)m(wski\))i(and)e(the)0 -3059 y(hierarc)m(hical)39 b(grouping)d(routines)h(\(written)h(b)m(y)f -(Don)h(Jennings\).)60 b(The)37 b(ISDC)f(D)m(AL)i(\(Data)h(Access)f(La)m -(y)m(er\))0 3172 y(routines)30 b(are)h(la)m(y)m(ered)h(on)e(top)h(of)f -(CFITSIO)f(and)h(mak)m(e)h(extensiv)m(e)h(use)e(of)h(these)g(features.) -0 3332 y(Uw)m(e)25 b(Lammers)e(\(XMM/ESA/ESTEC,)h(The)g(Netherlands\))g -(designed)g(the)g(high-p)s(erformance)f(lexical)j(pars-)0 -3445 y(ing)42 b(algorithm)h(that)f(is)g(used)f(to)i(do)e(on-the-\015y)h -(\014ltering)g(of)g(FITS)f(tables.)76 b(This)41 b(algorithm)i(essen)m -(tially)0 3558 y(pre-compiles)36 b(the)g(user-supplied)e(selection)k -(expression)d(in)m(to)i(a)f(form)g(that)g(can)g(b)s(e)f(rapidly)g(ev)-5 -b(aluated)37 b(for)0 3671 y(eac)m(h)31 b(ro)m(w.)40 b(P)m(eter)31 -b(Wilson)f(\(RSTX,)f(NASA/GSF)m(C\))i(then)e(wrote)h(the)g(parsing)f -(routines)g(used)g(b)m(y)g(CFITSIO)0 3784 y(based)i(on)f(Lammers')h -(design,)g(com)m(bined)g(with)g(other)g(tec)m(hniques)g(suc)m(h)g(as)g -(the)g(CFITSIO)f(iterator)i(routine)0 3897 y(to)g(further)e(enhance)h -(the)h(data)g(pro)s(cessing)f(throughput.)42 b(This)31 -b(e\013ort)h(also)g(b)s(ene\014ted)e(from)h(a)h(m)m(uc)m(h)f(earlier)0 -4010 y(lexical)25 b(parsing)f(routine)f(that)h(w)m(as)g(dev)m(elop)s -(ed)g(b)m(y)g(Ken)m(t)g(Blac)m(kburn)f(\(NASA/GSF)m(C\).)i(More)g -(recen)m(tly)-8 b(,)27 b(Craig)0 4123 y(Markw)m(ardt)i(\(NASA/GSF)m -(C\))g(implemen)m(ted)g(additional)g(functions)f(\(median,)h(a)m(v)m -(erage,)j(stddev\))c(and)g(other)0 4236 y(enhancemen)m(ts)j(to)g(the)g -(lexical)h(parser.)0 4396 y(The)40 b(CFITSIO)g(iterator)i(function)e -(is)h(lo)s(osely)h(based)f(on)f(similar)i(ideas)f(dev)m(elop)s(ed)g -(for)g(the)g(XMM)g(Data)0 4509 y(Access)31 b(La)m(y)m(er.)0 -4669 y(P)m(eter)25 b(Wilson)g(\(RSTX,)f(NASA/GSF)m(C\))h(wrote)g(the)f -(complete)i(set)e(of)h(F)-8 b(ortran-callable)27 b(wrapp)s(ers)22 -b(for)i(all)h(the)0 4782 y(CFITSIO)k(routines,)h(whic)m(h)g(in)g(turn)g -(rely)g(on)h(the)f(CF)m(OR)-8 b(TRAN)31 b(macro)g(dev)m(elop)s(ed)g(b)m -(y)f(Burkhard)f(Buro)m(w.)0 4942 y(The)h(syn)m(tax)i(used)e(b)m(y)h -(CFITSIO)f(for)g(\014ltering)i(or)f(binning)e(input)h(FITS)h(\014les)g -(is)g(based)f(on)h(ideas)h(dev)m(elop)s(ed)0 5055 y(for)41 -b(the)g(AXAF)h(Science)g(Cen)m(ter)g(Data)h(Mo)s(del)e(b)m(y)g -(Jonathan)g(McDo)m(w)m(ell,)47 b(An)m(tonella)c(F)-8 -b(ruscione,)45 b(Aneta)0 5168 y(Siemigino)m(wsk)-5 b(a)27 -b(and)e(Bill)i(Jo)m(y)m(e.)41 b(See)26 b(h)m -(ttp://heasarc.gsfc.nasa.go)m(v/do)s(cs/journal/axa)q(f7.h)m(t)q(ml)32 -b(for)25 b(further)0 5281 y(description)30 b(of)h(the)g(AXAF)g(Data)h -(Mo)s(del.)0 5441 y(The)j(\014le)g(decompression)g(co)s(de)g(w)m(ere)h -(tak)m(en)g(directly)g(from)e(the)i(gzip)f(\(GNU)h(zip\))g(program)f -(dev)m(elop)s(ed)g(b)m(y)0 5554 y(Jean-loup)30 b(Gailly)i(and)e -(others.)0 5714 y(Doug)h(Mink,)g(SA)m(O,)f(pro)m(vided)g(the)h -(routines)f(for)g(con)m(v)m(erting)i(IRAF)f(format)g(images)g(in)m(to)g -(FITS)f(format.)p eop end -%%Page: 11 17 -TeXDict begin 11 16 bop 0 299 a Fg(2.7.)72 b(A)m(CKNO)m(WLEDGMENTS)2577 -b Fi(11)0 555 y(Martin)33 b(Reinec)m(k)m(e)i(\(Max)f(Planc)m(k)f -(Institute,)h(Garc)m(hing\)\))g(pro)m(vided)f(the)g(mo)s(di\014cations) -f(to)i(cfortran.h)e(that)0 668 y(are)d(necessary)h(to)f(supp)s(ort)e -(64-bit)k(in)m(teger)f(v)-5 b(alues)29 b(when)f(calling)i(C)f(routines) -g(from)f(fortran)h(programs.)39 b(The)0 781 y(cfortran.h)30 -b(macros)h(w)m(ere)g(originally)h(dev)m(elop)s(ed)e(b)m(y)h(Burkhard)e -(Buro)m(w)h(\(CERN\).)0 941 y(Julian)f(T)-8 b(a)m(ylor)31 -b(\(ESO,)e(Garc)m(hing\))i(pro)m(vided)e(the)g(fast)h(b)m(yte-sw)m -(apping)g(algorithms)h(that)f(use)f(the)h(SSE2)f(and)0 -1054 y(SSSE3)g(mac)m(hine)i(instructions)f(a)m(v)-5 b(ailable)33 -b(on)d(x86)p 1784 1054 28 4 v 34 w(64)h(CPUs.)0 1214 -y(In)c(addition,)i(man)m(y)f(other)g(p)s(eople)g(ha)m(v)m(e)h(made)f(v) --5 b(aluable)29 b(con)m(tributions)f(to)h(the)f(dev)m(elopmen)m(t)h(of) -f(CFITSIO.)0 1327 y(These)i(include)g(\(with)h(ap)s(ologies)h(to)f -(others)f(that)h(ma)m(y)g(ha)m(v)m(e)h(inadv)m(erten)m(tly)g(b)s(een)d -(omitted\):)0 1487 y(Stev)m(e)g(Allen,)g(Carl)f(Ak)m(erlof,)h(Keith)f -(Arnaud,)g(Morten)g(Krabb)s(e)e(Barfo)s(ed,)j(Ken)m(t)f(Blac)m(kburn,)h -(G)f(Bo)s(dammer,)0 1600 y(Romk)m(e)h(Bon)m(tek)m(o)s(e,)i(Lucio)d -(Chiapp)s(etti,)g(Keith)g(Costorf,)g(Robin)g(Corb)s(et,)g(John)e(Da)m -(vis,)k(Ric)m(hard)e(Fink,)h(Ning)0 1713 y(Gan,)g(Emily)e(Greene,)i(Jo) -s(e)f(Harrington,)h(Cheng)e(Ho,)i(Phil)e(Ho)s(dge,)i(Jim)f(Ingham,)g(Y) --8 b(oshitak)j(a)29 b(Ishisaki,)f(Diab)0 1826 y(Jerius,)j(Mark)h -(Levine,)g(T)-8 b(o)s(dd)30 b(Karak)-5 b(askian,)32 b(Edw)m(ard)f -(King,)g(Scott)i(Ko)s(c)m(h,)e(Claire)h(Larkin,)f(Rob)h(Managan,)0 -1939 y(Eric)38 b(Mandel,)i(John)d(Matto)m(x,)43 b(Carsten)37 -b(Mey)m(er,)42 b(Emi)37 b(Miy)m(ata,)43 b(Stefan)38 b(Mo)s(c)m(hnac)m -(ki,)j(Mik)m(e)f(Noble,)g(Oliv)m(er)0 2052 y(Ob)s(erdorf,)c(Cliv)m(e)i -(P)m(age,)i(Arvind)35 b(P)m(armar,)j(Je\013)f(P)m(edelt)m(y)-8 -b(,)40 b(Tim)c(P)m(earson,)j(Maren)e(Purv)m(es,)h(Scott)f(Randall,)0 -2165 y(Chris)d(Rogers,)j(Arnold)e(Rots,)i(Barry)f(Sc)m(hlesinger,)h -(Robin)e(Stebbins,)g(Andrew)f(Szymk)m(o)m(wiak,)k(Allyn)e(T)-8 -b(en-)0 2278 y(nan)m(t,)31 b(P)m(eter)g(T)-8 b(eub)s(en,)30 -b(James)g(Theiler,)h(Doug)g(T)-8 b(o)s(dy)g(,)31 b(Shiro)e(Ueno,)j -(Stev)m(e)f(W)-8 b(alton,)33 b(Arc)m(hie)e(W)-8 b(arno)s(c)m(k,)32 -b(Alan)0 2391 y(W)-8 b(atson,)32 b(Dan)f(Whipple,)f(Wim)h(Wimmers,)g(P) -m(eter)g(Y)-8 b(oung,)31 b(Jianjun)e(Xu,)h(and)g(Nelson)h(Zarate.)p -eop end -%%Page: 12 18 -TeXDict begin 12 17 bop 0 299 a Fi(12)1851 b Fg(CHAPTER)30 -b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)p eop end -%%Page: 13 19 -TeXDict begin 13 18 bop 0 1225 a Ff(Chapter)65 b(3)0 -1687 y Fl(A)78 b(FITS)f(Primer)0 2180 y Fi(This)23 b(section)j(giv)m -(es)f(a)g(brief)e(o)m(v)m(erview)j(of)e(the)h(structure)e(of)i(FITS)e -(\014les.)38 b(Users)24 b(should)g(refer)f(to)i(the)g(do)s(cumen-)0 -2293 y(tation)33 b(a)m(v)-5 b(ailable)33 b(from)e(the)g(FITS)g(Supp)s -(ort)e(O\016ce,)j(as)f(describ)s(ed)f(in)h(the)h(in)m(tro)s(duction,)f -(for)g(more)h(detailed)0 2406 y(information)f(on)f(FITS)g(formats.)0 -2566 y(FITS)37 b(w)m(as)g(\014rst)g(dev)m(elop)s(ed)h(in)f(the)g(late)i -(1970's)g(as)f(a)f(standard)g(data)h(in)m(terc)m(hange)h(format)f(b)s -(et)m(w)m(een)g(v)-5 b(ar-)0 2679 y(ious)38 b(astronomical)h(observ)-5 -b(atories.)64 b(Since)37 b(then)g(FITS)g(has)h(b)s(ecome)g(the)g -(defacto)g(standard)f(data)i(format)0 2791 y(supp)s(orted)29 -b(b)m(y)h(most)h(astronomical)h(data)f(analysis)g(soft)m(w)m(are)g(pac) -m(k)-5 b(ages.)0 2952 y(A)34 b(FITS)f(\014le)g(consists)h(of)g(one)g -(or)g(more)g(Header)g(+)f(Data)i(Units)f(\(HDUs\),)i(where)d(the)h -(\014rst)f(HDU)h(is)g(called)0 3065 y(the)j(`Primary)f(HDU',)i(or)f -(`Primary)f(Arra)m(y'.)60 b(The)36 b(primary)g(arra)m(y)h(con)m(tains)h -(an)e(N-dimensional)i(arra)m(y)f(of)0 3177 y(pixels,)32 -b(suc)m(h)g(as)f(a)h(1-D)h(sp)s(ectrum,)e(a)h(2-D)h(image,)g(or)f(a)g -(3-D)g(data)h(cub)s(e.)43 b(Six)31 b(di\013eren)m(t)h(primary)f(datat)m -(yp)s(es)0 3290 y(are)g(supp)s(orted:)39 b(Unsigned)30 -b(8-bit)h(b)m(ytes,)g(16,)g(32,)h(and)e(64-bit)h(signed)g(in)m(tegers,) -h(and)d(32)j(and)d(64-bit)j(\015oating)0 3403 y(p)s(oin)m(t)d(reals.)41 -b(FITS)29 b(also)i(has)e(a)h(con)m(v)m(en)m(tion)h(for)e(storing)h -(unsigned)f(in)m(tegers)h(\(see)h(the)e(later)i(section)f(en)m(titled)0 -3516 y(`Unsigned)h(In)m(tegers')h(for)f(more)g(details\).)43 -b(The)31 b(primary)f(HDU)i(ma)m(y)f(also)h(consist)g(of)f(only)g(a)g -(header)g(with)g(a)0 3629 y(n)m(ull)f(arra)m(y)h(con)m(taining)h(no)e -(data)h(pixels.)0 3789 y(An)m(y)i(n)m(um)m(b)s(er)e(of)h(additional)i -(HDUs)f(ma)m(y)g(follo)m(w)h(the)e(primary)g(arra)m(y;)i(these)f -(additional)h(HDUs)f(are)g(called)0 3902 y(FITS)d(`extensions'.)41 -b(There)30 b(are)h(curren)m(tly)f(3)h(t)m(yp)s(es)g(of)f(extensions)h -(de\014ned)e(b)m(y)h(the)h(FITS)f(standard:)136 4171 -y Fc(\017)46 b Fi(Image)31 b(Extension)g(-)g(a)f(N-dimensional)h(arra)m -(y)g(of)g(pixels,)g(lik)m(e)g(in)f(a)h(primary)e(arra)m(y)136 -4368 y Fc(\017)46 b Fi(ASCI)s(I)29 b(T)-8 b(able)31 b(Extension)g(-)f -(ro)m(ws)h(and)e(columns)h(of)h(data)g(in)f(ASCI)s(I)f(c)m(haracter)j -(format)136 4564 y Fc(\017)46 b Fi(Binary)31 b(T)-8 b(able)31 -b(Extension)f(-)h(ro)m(ws)f(and)g(columns)g(of)h(data)g(in)f(binary)f -(represen)m(tation)0 4833 y(In)k(eac)m(h)i(case)g(the)f(HDU)h(consists) -g(of)f(an)g(ASCI)s(I)e(Header)i(Unit)h(follo)m(w)m(ed)g(b)m(y)f(an)g -(optional)h(Data)g(Unit.)52 b(F)-8 b(or)0 4946 y(historical)37 -b(reasons,)g(eac)m(h)f(Header)g(or)g(Data)h(unit)e(m)m(ust)g(b)s(e)g -(an)g(exact)i(m)m(ultiple)f(of)g(2880)h(8-bit)f(b)m(ytes)g(long.)0 -5059 y(An)m(y)30 b(un)m(used)g(space)g(is)h(padded)e(with)h(\014ll)g(c) -m(haracters)i(\(ASCI)s(I)d(blanks)h(or)h(zeros\).)0 5219 -y(Eac)m(h)i(Header)f(Unit)h(consists)g(of)f(an)m(y)g(n)m(um)m(b)s(er)f -(of)i(80-c)m(haracter)i(k)m(eyw)m(ord)d(records)g(or)g(`card)h(images') -g(whic)m(h)0 5332 y(ha)m(v)m(e)f(the)e(general)i(form:)95 -5601 y Fe(KEYNAME)46 b(=)i(value)e(/)i(comment)d(string)95 -5714 y(NULLKEY)h(=)334 b(/)48 b(comment:)d(This)i(keyword)f(has)g(no)i -(value)1905 5942 y Fi(13)p eop end -%%Page: 14 20 -TeXDict begin 14 19 bop 0 299 a Fi(14)2398 b Fg(CHAPTER)30 -b(3.)112 b(A)30 b(FITS)g(PRIMER)0 555 y Fi(The)35 b(k)m(eyw)m(ord)i -(names)f(ma)m(y)g(b)s(e)g(up)f(to)h(8)h(c)m(haracters)g(long)g(and)e -(can)h(only)h(con)m(tain)g(upp)s(ercase)e(letters,)k(the)0 -668 y(digits)25 b(0-9,)i(the)e(h)m(yphen,)g(and)f(the)h(underscore)e(c) -m(haracter.)41 b(The)24 b(k)m(eyw)m(ord)h(name)g(is)f(\(usually\))h -(follo)m(w)m(ed)i(b)m(y)d(an)0 781 y(equals)29 b(sign)g(and)f(a)g -(space)i(c)m(haracter)g(\(=)e(\))h(in)f(columns)h(9)g(-)f(10)i(of)f -(the)f(record,)h(follo)m(w)m(ed)i(b)m(y)d(the)h(v)-5 -b(alue)29 b(of)g(the)0 894 y(k)m(eyw)m(ord)34 b(whic)m(h)g(ma)m(y)g(b)s -(e)f(either)h(an)g(in)m(teger,)i(a)e(\015oating)g(p)s(oin)m(t)g(n)m(um) -m(b)s(er,)g(a)g(c)m(haracter)h(string)e(\(enclosed)i(in)0 -1007 y(single)28 b(quotes\),)i(or)e(a)g(b)s(o)s(olean)g(v)-5 -b(alue)28 b(\(the)g(letter)h(T)f(or)f(F\).)i(A)f(k)m(eyw)m(ord)g(ma)m -(y)h(also)f(ha)m(v)m(e)h(a)g(n)m(ull)e(or)h(unde\014ned)0 -1120 y(v)-5 b(alue)31 b(if)f(there)h(is)f(no)g(sp)s(eci\014ed)g(v)-5 -b(alue)31 b(string,)g(as)f(in)g(the)h(second)f(example.)0 -1280 y(The)c(last)h(k)m(eyw)m(ord)g(in)g(the)f(header)h(is)f(alw)m(a)m -(ys)i(the)f(`END')g(k)m(eyw)m(ord)g(whic)m(h)g(has)f(no)g(v)-5 -b(alue)27 b(or)g(commen)m(t)g(\014elds.)0 1393 y(There)k(are)g(man)m(y) -g(rules)g(go)m(v)m(erning)h(the)g(exact)g(format)g(of)f(a)g(k)m(eyw)m -(ord)h(record)f(\(see)h(the)f(FITS)f(Standard\))h(so)0 -1506 y(it)c(is)g(b)s(etter)g(to)h(rely)f(on)g(standard)f(in)m(terface)j -(soft)m(w)m(are)f(lik)m(e)g(FITSIO)e(to)i(correctly)g(construct)f(or)g -(to)h(parse)f(the)0 1619 y(k)m(eyw)m(ord)k(records)f(rather)g(than)g -(try)h(to)g(deal)g(directly)g(with)f(the)g(ra)m(w)h(FITS)e(formats.)0 -1779 y(Eac)m(h)37 b(Header)g(Unit)f(b)s(egins)g(with)g(a)g(series)h(of) -f(required)g(k)m(eyw)m(ords)g(whic)m(h)g(dep)s(end)f(on)h(the)g(t)m(yp) -s(e)h(of)f(HDU.)0 1892 y(These)31 b(required)g(k)m(eyw)m(ords)h(sp)s -(ecify)g(the)f(size)i(and)e(format)h(of)g(the)g(follo)m(wing)h(Data)g -(Unit.)45 b(The)31 b(header)g(ma)m(y)0 2005 y(con)m(tain)h(other)f -(optional)g(k)m(eyw)m(ords)g(to)h(describ)s(e)e(other)g(asp)s(ects)h -(of)g(the)g(data,)g(suc)m(h)g(as)g(the)f(units)g(or)h(scaling)0 -2118 y(v)-5 b(alues.)44 b(Other)31 b(COMMENT)g(or)g(HISTOR)-8 -b(Y)30 b(k)m(eyw)m(ords)i(are)g(also)g(frequen)m(tly)g(added)e(to)i -(further)e(do)s(cumen)m(t)0 2230 y(the)h(data)g(\014le.)0 -2391 y(The)36 b(optional)h(Data)h(Unit)f(immediately)g(follo)m(ws)h -(the)e(last)h(2880-b)m(yte)i(blo)s(c)m(k)e(in)f(the)g(Header)h(Unit.)59 -b(Some)0 2503 y(HDUs)31 b(do)f(not)h(ha)m(v)m(e)g(a)g(Data)h(Unit)f -(and)f(only)g(consist)h(of)g(the)f(Header)h(Unit.)0 2664 -y(If)24 b(there)i(is)f(more)g(than)f(one)h(HDU)h(in)f(the)g(FITS)f -(\014le,)i(then)f(the)g(Header)h(Unit)f(of)g(the)g(next)g(HDU)h -(immediately)0 2777 y(follo)m(ws)g(the)e(last)i(2880-b)m(yte)h(blo)s(c) -m(k)e(of)g(the)f(previous)g(Data)j(Unit)d(\(or)h(Header)g(Unit)g(if)f -(there)h(is)g(no)f(Data)i(Unit\).)0 2937 y(The)k(main)g(required)g(k)m -(eyw)m(ords)g(in)g(FITS)g(primary)g(arra)m(ys)g(or)h(image)g -(extensions)g(are:)136 3172 y Fc(\017)46 b Fi(BITPIX)33 -b({)h(de\014nes)e(the)i(datat)m(yp)s(e)g(of)f(the)g(arra)m(y:)47 -b(8,)35 b(16,)g(32,)g(64,)g(-32,)g(-64)g(for)e(unsigned)f(8{bit)i(b)m -(yte,)227 3284 y(16{bit)27 b(signed)e(in)m(teger,)i(32{bit)g(signed)e -(in)m(teger,)j(64{bit)e(signed)f(in)m(teger,)j(32{bit)e(IEEE)f -(\015oating)h(p)s(oin)m(t,)227 3397 y(and)k(64{bit)i(IEEE)e(double)f -(precision)i(\015oating)g(p)s(oin)m(t,)g(resp)s(ectiv)m(ely)-8 -b(.)136 3585 y Fc(\017)46 b Fi(NAXIS)30 b({)h(the)g(n)m(um)m(b)s(er)e -(of)h(dimensions)g(in)g(the)h(arra)m(y)-8 b(,)31 b(usually)f(0,)h(1,)g -(2,)g(3,)g(or)g(4.)136 3773 y Fc(\017)46 b Fi(NAXISn)30 -b({)h(\(n)f(ranges)g(from)g(1)h(to)g(NAXIS\))g(de\014nes)e(the)i(size)g -(of)g(eac)m(h)g(dimension.)0 4008 y(FITS)e(tables)i(start)g(with)f(the) -g(k)m(eyw)m(ord)g(XTENSION)g(=)f(`T)-8 b(ABLE')31 b(\(for)f(ASCI)s(I)f -(tables\))i(or)f(XTENSION)f(=)0 4120 y(`BINT)-8 b(ABLE')32 -b(\(for)e(binary)g(tables\))h(and)f(ha)m(v)m(e)i(the)e(follo)m(wing)i -(main)e(k)m(eyw)m(ords:)136 4355 y Fc(\017)46 b Fi(TFIELDS)30 -b({)h(n)m(um)m(b)s(er)e(of)h(\014elds)g(or)h(columns)f(in)g(the)g -(table)136 4543 y Fc(\017)46 b Fi(NAXIS2)31 b({)g(n)m(um)m(b)s(er)e(of) -h(ro)m(ws)h(in)f(the)g(table)136 4731 y Fc(\017)46 b -Fi(TTYPEn)29 b({)i(for)f(eac)m(h)i(column)e(\(n)g(ranges)h(from)f(1)g -(to)h(TFIELDS\))g(giv)m(es)g(the)g(name)f(of)h(the)f(column)136 -4918 y Fc(\017)46 b Fi(TF)m(ORMn)31 b({)f(the)h(datat)m(yp)s(e)g(of)g -(the)f(column)136 5106 y Fc(\017)46 b Fi(TUNITn)30 b({)g(the)h(ph)m -(ysical)g(units)f(of)g(the)h(column)f(\(optional\))0 -5341 y(Users)k(should)f(refer)h(to)h(the)f(FITS)g(Supp)s(ort)e(O\016ce) -i(at)h Fe(http://fits.gsfc.nasa.gov)27 b Fi(for)34 b(further)f(infor-)0 -5454 y(mation)e(ab)s(out)f(the)h(FITS)e(format)i(and)f(related)h(soft)m -(w)m(are)h(pac)m(k)-5 b(ages.)p eop end -%%Page: 15 21 -TeXDict begin 15 20 bop 0 1225 a Ff(Chapter)65 b(4)0 -1687 y Fl(FITSIO)76 b(Con)-6 b(v)g(en)g(tions)76 b(and)h(Guidelines)0 -2216 y Fd(4.1)135 b(CFITSIO)44 b(Size)h(Limitations)0 -2524 y Fi(CFITSIO)31 b(places)i(few)g(restrictions)g(on)g(the)f(size)i -(of)e(FITS)g(\014les)h(that)g(it)g(reads)f(or)h(writes.)47 -b(There)32 b(are)h(a)g(few)0 2636 y(limits,)e(ho)m(w)m(ev)m(er,)h(whic) -m(h)e(ma)m(y)h(a\013ect)h(some)f(extreme)g(cases:)0 2797 -y(1.)43 b(The)31 b(maxim)m(um)g(n)m(um)m(b)s(er)f(of)h(FITS)f(\014les)h -(that)h(ma)m(y)g(b)s(e)e(sim)m(ultaneously)i(op)s(ened)f(b)m(y)g -(CFITSIO)e(is)i(set)h(b)m(y)0 2910 y(NMAXFILES,)e(as)f(de\014ned)f(in)h -(\014tsio2.h.)41 b(The)29 b(curren)m(t)g(default)g(v)-5 -b(alue)30 b(is)f(1000,)j(but)c(this)h(ma)m(y)h(b)s(e)f(increased)0 -3022 y(if)40 b(necessary)-8 b(.)72 b(Note)42 b(that)f(CFITSIO)e(allo)s -(cates)j(NIOBUF)f(*)g(2880)h(b)m(ytes)f(of)g(I/O)f(bu\013er)g(space)h -(for)f(eac)m(h)0 3135 y(\014le)d(that)h(is)f(op)s(ened.)61 -b(The)37 b(default)g(v)-5 b(alue)38 b(of)f(NIOBUF)h(is)f(40)h -(\(de\014ned)f(in)f(\014tsio.h\),)k(so)e(this)f(amoun)m(ts)g(to)0 -3248 y(more)31 b(than)g(115K)i(of)e(memory)g(for)g(eac)m(h)i(op)s(ened) -d(\014le)i(\(or)f(115)i(MB)f(for)f(1000)i(op)s(ened)d(\014les\).)44 -b(Note)33 b(that)f(the)0 3361 y(underlying)k(op)s(erating)i(system,)h -(ma)m(y)e(ha)m(v)m(e)i(a)e(lo)m(w)m(er)i(limit)f(on)f(the)g(n)m(um)m(b) -s(er)f(of)h(\014les)g(that)h(can)f(b)s(e)g(op)s(ened)0 -3474 y(sim)m(ultaneously)-8 b(.)0 3634 y(2.)54 b(By)35 -b(default,)h(CFITSIO)d(can)i(handle)g(FITS)f(\014les)g(up)g(to)h(2.1)h -(GB)g(in)e(size)i(\(2**31)h(b)m(ytes\).)54 b(This)34 -b(\014le)h(size)0 3747 y(limit)41 b(is)g(often)f(imp)s(osed)g(b)m(y)g -(32-bit)i(op)s(erating)e(systems.)71 b(More)41 b(recen)m(tly)-8 -b(,)45 b(as)c(64-bit)g(op)s(erating)g(systems)0 3860 -y(b)s(ecome)33 b(more)g(common,)g(an)g(industry-wide)e(standard)h(\(at) -i(least)f(on)g(Unix)f(systems\))h(has)g(b)s(een)f(dev)m(elop)s(ed)0 -3973 y(to)39 b(supp)s(ort)d(larger)i(sized)h(\014les)f(\(see)g(h)m -(ttp://ftp.sas.com/standards/large.\014le/\).)69 b(Starting)38 -b(with)f(v)m(ersion)0 4086 y(2.1)45 b(of)e(CFITSIO,)f(larger)i(FITS)f -(\014les)g(up)g(to)h(6)g(terab)m(ytes)h(in)e(size)h(ma)m(y)g(b)s(e)f -(read)g(and)g(written)h(on)f(sup-)0 4199 y(p)s(orted)f(platforms.)76 -b(In)42 b(order)g(to)h(supp)s(ort)e(these)h(larger)h(\014les,)j -(CFITSIO)41 b(m)m(ust)h(b)s(e)g(compiled)h(with)f(the)0 -4312 y('-D)p 129 4312 28 4 v 34 w(LAR)m(GEFILE)p 696 -4312 V 33 w(SOUR)m(CE')g(and)g(`-D)p 1491 4312 V 34 w(FILE)p -1736 4312 V 33 w(OFFSET)p 2137 4312 V 32 w(BITS=64')h(compiler)g -(\015ags.)78 b(Some)43 b(platforms)0 4425 y(ma)m(y)c(also)g(require)f -(the)g(`-D)p 1002 4425 V 34 w(LAR)m(GE)p 1358 4425 V -33 w(FILES')g(compiler)h(\015ag.)64 b(This)38 b(causes)g(the)h -(compiler)g(to)g(allo)s(cate)h(8-)0 4538 y(b)m(ytes)k(instead)g(of)g -(4-b)m(ytes)h(for)f(the)g(`o\013)p 1473 4538 V 33 w(t')g(datat)m(yp)s -(e)h(whic)m(h)f(is)f(used)g(to)i(store)f(\014le)g(o\013set)h(p)s -(ositions.)81 b(It)0 4650 y(app)s(ears)31 b(that)i(in)e(most)i(cases)g -(it)f(is)g(not)g(necessary)h(to)f(also)h(include)f(these)g(compiler)h -(\015ags)f(when)f(compiling)0 4763 y(programs)f(that)h(link)f(to)h(the) -g(CFITSIO)e(library)-8 b(.)0 4924 y(If)21 b(CFITSIO)e(is)i(compiled)h -(with)f(the)g(-D)p 1386 4924 V 33 w(LAR)m(GEFILE)p 1952 -4924 V 34 w(SOUR)m(CE)f(and)g(-D)p 2654 4924 V 34 w(FILE)p -2899 4924 V 33 w(OFFSET)p 3300 4924 V 32 w(BITS=64)h(\015ags)0 -5036 y(on)36 b(a)g(platform)g(that)g(supp)s(orts)e(large)j(\014les,)h -(then)d(it)i(can)f(read)g(and)f(write)h(FITS)f(\014les)h(that)g(con)m -(tain)h(up)e(to)0 5149 y(2**31)k(2880-b)m(yte)g(FITS)d(records,)j(or)d -(appro)m(ximately)i(6)f(terab)m(ytes)h(in)f(size.)60 -b(It)37 b(is)g(still)h(required)d(that)j(the)0 5262 y(v)-5 -b(alue)30 b(of)f(the)g(NAXISn)f(and)h(PCOUNT)f(k)m(eyw)m(ords)h(in)g -(eac)m(h)h(extension)g(b)s(e)e(within)h(the)g(range)h(of)f(a)g(signed)g -(4-)0 5375 y(b)m(yte)c(in)m(teger)h(\(max)f(v)-5 b(alue)26 -b(=)e(2,147,483,648\).)44 b(Th)m(us,)25 b(eac)m(h)h(dimension)e(of)h -(an)f(image)i(\(giv)m(en)g(b)m(y)f(the)g(NAXISn)0 5488 -y(k)m(eyw)m(ords\),)32 b(the)f(total)i(width)d(of)h(a)g(table)h -(\(NAXIS1)g(k)m(eyw)m(ord\),)g(the)f(n)m(um)m(b)s(er)f(of)h(ro)m(ws)g -(in)f(a)h(table)h(\(NAXIS2)0 5601 y(k)m(eyw)m(ord\),)c(and)d(the)h -(total)i(size)f(of)f(the)g(v)-5 b(ariable-length)28 b(arra)m(y)e(heap)g -(in)g(binary)f(tables)i(\(PCOUNT)e(k)m(eyw)m(ord\))0 -5714 y(m)m(ust)30 b(b)s(e)g(less)h(than)f(this)g(limit.)1905 -5942 y(15)p eop end -%%Page: 16 22 -TeXDict begin 16 21 bop 0 299 a Fi(16)1277 b Fg(CHAPTER)29 -b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 -555 y Fi(Curren)m(tly)-8 b(,)31 b(supp)s(ort)e(for)i(large)h(\014les)f -(within)f(CFITSIO)f(has)i(b)s(een)f(tested)i(on)f(the)g(Lin)m(ux,)g -(Solaris,)g(and)f(IBM)0 668 y(AIX)g(op)s(erating)h(systems.)0 -1133 y Fd(4.2)135 b(Multiple)46 b(Access)e(to)i(the)f(Same)g(FITS)f -(File)0 1409 y Fi(CFITSIO)35 b(supp)s(orts)g(sim)m(ultaneous)i(read)f -(and)g(write)h(access)g(to)h(m)m(ultiple)f(HDUs)g(in)f(the)h(same)g -(FITS)f(\014le.)0 1522 y(Th)m(us,)43 b(one)e(can)h(op)s(en)e(the)h -(same)h(FITS)e(\014le)h(t)m(wice)i(within)d(a)i(single)f(program)g(and) -g(mo)m(v)m(e)h(to)g(2)f(di\013eren)m(t)0 1635 y(HDUs)30 -b(in)f(the)h(\014le,)g(and)f(then)g(read)h(and)e(write)i(data)g(or)g(k) -m(eyw)m(ords)g(to)g(the)g(2)f(extensions)i(just)d(as)i(if)g(one)f(w)m -(ere)0 1748 y(accessing)f(2)f(completely)h(separate)f(FITS)f(\014les.) -39 b(Since)27 b(in)f(general)h(it)g(is)g(not)g(p)s(ossible)f(to)h(ph)m -(ysically)g(op)s(en)f(the)0 1861 y(same)36 b(\014le)g(t)m(wice)h(and)e -(then)g(exp)s(ect)h(to)g(b)s(e)f(able)h(to)h(sim)m(ultaneously)f(\(or)g -(in)f(alternating)i(succession\))g(write)0 1974 y(to)e(2)f(di\013eren)m -(t)h(lo)s(cations)h(in)d(the)i(\014le,)g(CFITSIO)e(recognizes)j(when)d -(the)h(\014le)g(to)h(b)s(e)f(op)s(ened)f(\(in)h(the)h(call)g(to)0 -2087 y(\014ts)p 127 2087 28 4 v 32 w(op)s(en)p 349 2087 -V 33 w(\014le\))29 b(has)f(already)h(b)s(een)f(op)s(ened)g(and)g -(instead)h(of)g(actually)h(op)s(ening)e(the)h(\014le)g(again,)h(just)e -(logically)0 2199 y(links)i(the)h(new)f(\014le)h(to)g(the)g(old)f -(\014le.)42 b(\(This)30 b(only)h(applies)f(if)h(the)g(\014le)f(is)h(op) -s(ened)f(more)g(than)g(once)i(within)e(the)0 2312 y(same)e(program,)g -(and)f(do)s(es)h(not)f(prev)m(en)m(t)i(the)f(same)g(\014le)f(from)g(b)s -(eing)h(sim)m(ultaneously)g(op)s(ened)f(b)m(y)g(more)h(than)0 -2425 y(one)h(program\).)40 b(Then)28 b(b)s(efore)g(CFITSIO)f(reads)h -(or)h(writes)g(to)g(either)g(\(logical\))j(\014le,)d(it)g(mak)m(es)h -(sure)d(that)j(an)m(y)0 2538 y(mo)s(di\014cations)i(made)f(to)h(the)g -(other)g(\014le)f(ha)m(v)m(e)i(b)s(een)e(completely)i(\015ushed)c(from) -i(the)h(in)m(ternal)g(bu\013ers)f(to)h(the)0 2651 y(\014le.)44 -b(Th)m(us,)30 b(in)h(principle,)h(one)f(could)g(op)s(en)g(a)h(\014le)f -(t)m(wice,)i(in)e(one)h(case)g(p)s(oin)m(ting)g(to)g(the)f(\014rst)g -(extension)h(and)0 2764 y(in)i(the)h(other)g(p)s(oin)m(ting)f(to)i(the) -e(2nd)g(extension)i(and)d(then)i(write)f(data)i(to)f(b)s(oth)f -(extensions,)i(in)e(an)m(y)h(order,)0 2877 y(without)25 -b(danger)h(of)f(corrupting)h(the)f(\014le,)i(There)e(ma)m(y)h(b)s(e)f -(some)h(e\016ciency)g(p)s(enalties)g(in)f(doing)h(this)f(ho)m(w)m(ev)m -(er,)0 2990 y(since)j(CFITSIO)f(has)h(to)h(\015ush)d(all)j(the)f(in)m -(ternal)h(bu\013ers)e(related)i(to)g(one)f(\014le)g(b)s(efore)g(switc)m -(hing)g(to)h(the)f(other,)0 3103 y(so)i(it)h(w)m(ould)f(still)h(b)s(e)f -(pruden)m(t)f(to)i(minimize)g(the)f(n)m(um)m(b)s(er)f(of)i(times)f(one) -h(switc)m(hes)g(bac)m(k)g(and)e(forth)h(b)s(et)m(w)m(een)0 -3216 y(doing)g(I/O)h(to)g(di\013eren)m(t)g(HDUs)g(in)f(the)g(same)h -(\014le.)0 3680 y Fd(4.3)135 b(Curren)l(t)46 b(Header)f(Data)h(Unit)g -(\(CHDU\))0 3957 y Fi(In)32 b(general,)j(a)f(FITS)e(\014le)i(can)f(con) -m(tain)h(m)m(ultiple)g(Header)g(Data)h(Units,)f(also)g(called)g -(extensions.)49 b(CFITSIO)0 4070 y(only)38 b(op)s(erates)h(within)f -(one)g(HDU)h(at)g(an)m(y)g(giv)m(en)g(time,)i(and)d(the)g(curren)m(tly) -g(selected)i(HDU)f(is)f(called)i(the)0 4183 y(Curren)m(t)f(Header)h -(Data)h(Unit)f(\(CHDU\).)h(When)f(a)g(FITS)f(\014le)h(is)f(\014rst)g -(created)i(or)f(op)s(ened)f(the)h(CHDU)g(is)0 4295 y(automatically)28 -b(de\014ned)23 b(to)j(b)s(e)e(the)h(\014rst)f(HDU)i(\(i.e.,)h(the)e -(primary)f(arra)m(y\).)40 b(CFITSIO)23 b(routines)i(are)g(pro)m(vided)0 -4408 y(to)36 b(mo)m(v)m(e)h(to)g(and)e(op)s(en)g(an)m(y)h(other)g -(existing)g(HDU)h(within)e(the)h(FITS)f(\014le)g(or)h(to)g(app)s(end)e -(or)i(insert)f(a)h(new)0 4521 y(HDU)31 b(in)f(the)h(FITS)e(\014le)i -(whic)m(h)f(then)g(b)s(ecomes)h(the)f(CHDU.)0 4986 y -Fd(4.4)135 b(Subroutine)45 b(Names)0 5262 y Fi(All)26 -b(FITSIO)f(subroutine)g(names)h(b)s(egin)f(with)h(the)g(letters)h('ft') -f(to)h(distinguish)e(them)h(from)f(other)h(subroutines)0 -5375 y(and)34 b(are)h(5)g(or)f(6)h(c)m(haracters)h(long.)54 -b(Users)34 b(should)g(not)g(name)h(their)g(o)m(wn)f(subroutines)f(b)s -(eginning)h(with)g('ft')0 5488 y(to)e(a)m(v)m(oid)i(con\015icts.)45 -b(\(The)32 b(SPP)f(in)m(terface)i(routines)e(all)i(b)s(egin)e(with)h -('fs'\).)45 b(Subroutines)30 b(whic)m(h)h(read)h(or)g(get)0 -5601 y(information)e(from)g(the)h(FITS)e(\014le)h(ha)m(v)m(e)i(names)e -(b)s(eginning)f(with)h('ftg...'.)43 b(Subroutines)28 -b(whic)m(h)i(write)g(or)h(put)0 5714 y(information)g(in)m(to)g(the)g -(FITS)e(\014le)i(ha)m(v)m(e)g(names)g(b)s(eginning)e(with)h('ftp...'.)p -eop end -%%Page: 17 23 -TeXDict begin 17 22 bop 0 299 a Fg(4.5.)72 b(SUBR)m(OUTINE)30 -b(F)-10 b(AMILIES)30 b(AND)h(D)m(A)-8 b(T)g(A)g(TYPES)1697 -b Fi(17)0 555 y Fd(4.5)135 b(Subroutine)45 b(F)-11 b(amilies)46 -b(and)f(Datat)l(yp)t(es)0 805 y Fi(Man)m(y)h(of)g(the)g(subroutines)e -(come)j(in)e(families)h(whic)m(h)g(di\013er)f(only)h(in)f(the)h(datat)m -(yp)s(e)g(of)g(the)f(asso)s(ciated)0 918 y(parameter\(s\))34 -b(.)47 b(The)32 b(datat)m(yp)s(e)i(of)f(these)g(subroutines)e(is)i -(indicated)g(b)m(y)g(the)g(last)g(letter)h(of)f(the)g(subroutine)0 -1031 y(name)d(\(e.g.,)j('j')d(in)g('ftpkyj'\))h(as)f(follo)m(ws:)382 -1284 y Fe(x)47 b(-)h(bit)382 1397 y(b)f(-)h(character*1)c(\(unsigned)i -(byte\))382 1510 y(i)h(-)h(short)e(integer)g(\(I*2\))382 -1623 y(j)h(-)h(integer)e(\(I*4,)g(32-bit)g(integer\))382 -1735 y(k)h(-)h(long)e(long)h(integer)f(\(I*8,)g(64-bit)g(integer\))382 -1848 y(e)h(-)h(real)e(exponential)f(floating)h(point)g(\(R*4\))382 -1961 y(f)h(-)h(real)e(fixed-format)f(floating)g(point)i(\(R*4\))382 -2074 y(d)g(-)h(double)e(precision)f(real)i(floating-point)d(\(R*8\))382 -2187 y(g)j(-)h(double)e(precision)f(fixed-format)g(floating)g(point)h -(\(R*8\))382 2300 y(c)h(-)h(complex)e(reals)g(\(pairs)g(of)h(R*4)g -(values\))382 2413 y(m)g(-)h(double)e(precision)f(complex)h(\(pairs)g -(of)h(R*8)g(values\))382 2526 y(l)g(-)h(logical)e(\(L*4\))382 -2639 y(s)h(-)h(character)d(string)0 2891 y Fi(When)23 -b(dealing)h(with)f(the)g(FITS)g(b)m(yte)g(datat)m(yp)s(e,)j(it)e(is)f -(imp)s(ortan)m(t)h(to)f(remem)m(b)s(er)g(that)h(the)f(ra)m(w)g(v)-5 -b(alues)24 b(\(b)s(efore)0 3004 y(an)m(y)h(scaling)g(b)m(y)f(the)h -(BSCALE)e(and)h(BZER)m(O,)g(or)h(TSCALn)d(and)i(TZER)m(On)f(k)m(eyw)m -(ord)i(v)-5 b(alues\))25 b(in)f(b)m(yte)h(arra)m(ys)0 -3117 y(\(BITPIX)37 b(=)f(8\))h(or)f(b)m(yte)i(columns)e(\(TF)m(ORMn)h -(=)f('B'\))h(are)g(in)m(terpreted)g(as)g(unsigned)e(b)m(ytes)i(with)g -(v)-5 b(alues)0 3230 y(ranging)40 b(from)f(0)i(to)f(255.)71 -b(Some)40 b(F)-8 b(ortran)40 b(compilers)h(supp)s(ort)d(a)i -(non-standard)f(b)m(yte)h(datat)m(yp)s(e)h(suc)m(h)f(as)0 -3343 y(INTEGER*1,)34 b(LOGICAL*1,)g(or)f(BYTE,)g(whic)m(h)f(can)h -(sometimes)h(b)s(e)e(used)g(instead)h(of)g(CHARA)m(CTER*1)0 -3456 y(v)-5 b(ariables.)39 b(Man)m(y)23 b(mac)m(hines)g(p)s(ermit)g -(passing)f(a)h(n)m(umeric)g(datat)m(yp)s(e)g(\(suc)m(h)g(as)g -(INTEGER*1\))h(to)f(the)g(FITSIO)0 3569 y(subroutines)41 -b(whic)m(h)i(are)g(exp)s(ecting)g(a)g(CHARA)m(CTER*1)h(datat)m(yp)s(e,) -j(but)42 b(this)g(tec)m(hnically)j(violates)g(the)0 3682 -y(F)-8 b(ortran-77)29 b(standard)d(and)g(is)h(not)g(supp)s(orted)e(on)i -(all)h(mac)m(hines)f(\(e.g.,)j(on)c(a)i(V)-10 b(AX/VMS)27 -b(mac)m(hine)h(one)f(m)m(ust)0 3795 y(use)j(the)h(V)-10 -b(AX-sp)s(eci\014c)31 b(\045DESCR)e(function\).)0 3955 -y(One)22 b(feature)h(of)g(the)g(CFITSIO)e(routines)i(is)f(that)i(they)f -(can)g(op)s(erate)g(on)f(a)h(`X')h(\(bit\))f(column)g(in)f(a)h(binary)f -(table)0 4068 y(as)35 b(though)e(it)i(w)m(ere)g(a)g(`B')g(\(b)m(yte\))g -(column.)53 b(F)-8 b(or)35 b(example)g(a)f(`11X')i(datat)m(yp)s(e)f -(column)f(can)h(b)s(e)f(in)m(terpreted)0 4181 y(the)28 -b(same)h(as)f(a)g(`2B')i(column)e(\(i.e.,)i(2)e(unsigned)f(8-bit)i(b)m -(ytes\).)41 b(In)27 b(some)i(instances,)g(it)f(can)h(b)s(e)e(more)h -(e\016cien)m(t)0 4294 y(to)j(read)f(and)g(write)h(whole)f(b)m(ytes)h -(at)g(a)g(time,)g(rather)g(than)f(reading)g(or)h(writing)f(eac)m(h)i -(individual)d(bit.)0 4454 y(The)41 b(double)h(precision)g(complex)g -(datat)m(yp)s(e)h(is)f(not)g(a)g(standard)f(F)-8 b(ortran-77)43 -b(datat)m(yp)s(e.)76 b(If)41 b(a)i(particular)0 4567 -y(F)-8 b(ortran)35 b(compiler)g(do)s(es)f(not)h(directly)g(supp)s(ort)e -(this)i(datat)m(yp)s(e,)h(then)f(one)f(ma)m(y)h(instead)g(pass)f(an)h -(arra)m(y)g(of)0 4680 y(pairs)d(of)h(double)f(precision)h(v)-5 -b(alues)32 b(to)i(these)f(subroutines.)45 b(The)33 b(\014rst)e(v)-5 -b(alue)33 b(in)f(eac)m(h)i(pair)e(is)h(the)g(real)g(part,)0 -4792 y(and)d(the)g(second)h(is)f(the)h(imaginary)g(part.)0 -5125 y Fd(4.6)135 b(Implicit)46 b(Data)g(T)l(yp)t(e)f(Con)l(v)l(ersion) -0 5375 y Fi(The)22 b(FITSIO)g(routines)h(that)h(read)e(and)h(write)g(n) -m(umerical)g(data)h(can)f(p)s(erform)f(implicit)i(data)f(t)m(yp)s(e)g -(con)m(v)m(ersion.)0 5488 y(This)i(means)g(that)h(the)g(data)g(t)m(yp)s -(e)g(of)g(the)g(v)-5 b(ariable)26 b(or)g(arra)m(y)g(in)f(the)h(program) -f(do)s(es)g(not)h(need)g(to)g(b)s(e)f(the)h(same)0 5601 -y(as)i(the)f(data)h(t)m(yp)s(e)g(of)f(the)h(v)-5 b(alue)28 -b(in)f(the)g(FITS)g(\014le.)40 b(Data)28 b(t)m(yp)s(e)g(con)m(v)m -(ersion)h(is)e(supp)s(orted)f(for)h(n)m(umerical)h(and)0 -5714 y(string)33 b(data)h(t)m(yp)s(es)f(\(if)h(the)g(string)f(con)m -(tains)h(a)g(v)-5 b(alid)33 b(n)m(um)m(b)s(er)f(enclosed)i(in)f -(quotes\))h(when)f(reading)g(a)h(FITS)p eop end -%%Page: 18 24 -TeXDict begin 18 23 bop 0 299 a Fi(18)1277 b Fg(CHAPTER)29 -b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 -555 y Fi(header)g(k)m(eyw)m(ord)g(v)-5 b(alue)31 b(and)g(for)f(n)m -(umeric)h(v)-5 b(alues)31 b(when)f(reading)h(or)g(writing)g(v)-5 -b(alues)31 b(in)f(the)h(primary)f(arra)m(y)0 668 y(or)40 -b(a)h(table)h(column.)70 b(CFITSIO)39 b(returns)h(status)g(=)h(NUM)p -2185 668 28 4 v 33 w(O)m(VERFLO)m(W)g(if)g(the)f(con)m(v)m(erted)i -(data)f(v)-5 b(alue)0 781 y(exceeds)33 b(the)g(range)g(of)g(the)f -(output)g(data)i(t)m(yp)s(e.)47 b(Implicit)33 b(data)g(t)m(yp)s(e)g -(con)m(v)m(ersion)h(is)e(not)h(supp)s(orted)d(within)0 -894 y(binary)g(tables)h(for)f(string,)g(logical,)k(complex,)d(or)f -(double)g(complex)h(data)g(t)m(yp)s(es.)0 1054 y(In)g(addition,)h(an)m -(y)f(table)h(column)f(ma)m(y)h(b)s(e)f(read)g(as)h(if)f(it)h(con)m -(tained)g(string)f(v)-5 b(alues.)44 b(In)31 b(the)g(case)i(of)e(n)m -(umeric)0 1167 y(columns)f(the)h(returned)e(string)h(will)h(b)s(e)f -(formatted)h(using)e(the)i(TDISPn)e(displa)m(y)i(format)f(if)h(it)g -(exists.)0 1496 y Fd(4.7)135 b(Data)46 b(Scaling)0 1746 -y Fi(When)38 b(reading)f(n)m(umerical)i(data)f(v)-5 b(alues)38 -b(in)f(the)h(primary)f(arra)m(y)h(or)g(a)g(table)h(column,)h(the)d(v)-5 -b(alues)38 b(will)h(b)s(e)0 1859 y(scaled)f(automatically)j(b)m(y)c -(the)h(BSCALE)f(and)g(BZER)m(O)h(\(or)g(TSCALn)d(and)i(TZER)m(On\))g -(header)g(k)m(eyw)m(ord)0 1972 y(v)-5 b(alues)33 b(if)f(they)g(are)h -(presen)m(t)g(in)f(the)g(header.)47 b(The)31 b(scaled)j(data)f(that)g -(is)f(returned)f(to)i(the)g(reading)f(program)0 2085 -y(will)f(ha)m(v)m(e)382 2316 y Fe(output)46 b(value)g(=)i(\(FITS)e -(value\))g(*)i(BSCALE)e(+)h(BZERO)0 2546 y Fi(\(a)30 -b(corresp)s(onding)e(form)m(ula)h(using)g(TSCALn)e(and)i(TZER)m(On)e -(is)i(used)g(when)f(reading)h(from)g(table)h(columns\).)0 -2659 y(In)h(the)i(case)g(of)f(in)m(teger)h(output)f(v)-5 -b(alues)32 b(the)h(\015oating)g(p)s(oin)m(t)f(scaled)g(v)-5 -b(alue)33 b(is)f(truncated)g(to)h(an)f(in)m(teger)h(\(not)0 -2772 y(rounded)38 b(to)i(the)g(nearest)g(in)m(teger\).)70 -b(The)39 b(ftpscl)g(and)g(fttscl)i(subroutines)d(ma)m(y)i(b)s(e)f(used) -g(to)h(o)m(v)m(erride)h(the)0 2885 y(scaling)30 b(parameters)f -(de\014ned)e(in)h(the)h(header)f(\(e.g.,)j(to)e(turn)f(o\013)h(the)f -(scaling)i(so)f(that)g(the)g(program)f(can)h(read)0 2998 -y(the)i(ra)m(w)f(unscaled)g(v)-5 b(alues)31 b(from)f(the)g(FITS)g -(\014le\).)0 3158 y(When)44 b(writing)h(n)m(umerical)g(data)g(to)g(the) -g(primary)f(arra)m(y)h(or)f(to)h(a)g(table)h(column)e(the)h(data)g(v)-5 -b(alues)45 b(will)0 3271 y(generally)29 b(b)s(e)f(automatically)j(in)m -(v)m(ersely)f(scaled)f(b)m(y)f(the)g(v)-5 b(alue)29 b(of)f(the)h -(BSCALE)e(and)h(BZER)m(O)g(\(or)h(TSCALn)0 3384 y(and)h(TZER)m(On\))g -(header)g(k)m(eyw)m(ord)h(v)-5 b(alues)31 b(if)g(they)g(they)g(exist)g -(in)f(the)h(header.)42 b(These)30 b(k)m(eyw)m(ords)h(m)m(ust)g(ha)m(v)m -(e)0 3497 y(b)s(een)f(written)h(to)h(the)g(header)e(b)s(efore)h(an)m(y) -h(data)f(is)g(written)h(for)e(them)i(to)f(ha)m(v)m(e)i(an)m(y)e -(e\013ect.)44 b(Otherwise,)32 b(one)0 3610 y(ma)m(y)i(use)f(the)g -(ftpscl)g(and)g(fttscl)h(subroutines)d(to)j(de\014ne)f(or)g(o)m(v)m -(erride)h(the)f(scaling)i(k)m(eyw)m(ords)e(in)g(the)g(header)0 -3723 y(\(e.g.,)h(to)f(turn)d(o\013)j(the)f(scaling)h(so)f(that)g(the)g -(program)g(can)g(write)g(the)g(ra)m(w)g(unscaled)g(v)-5 -b(alues)32 b(in)m(to)h(the)f(FITS)0 3836 y(\014le\).)43 -b(If)30 b(scaling)i(is)f(p)s(erformed,)e(the)i(in)m(v)m(erse)h(scaled)g -(output)e(v)-5 b(alue)32 b(that)f(is)g(written)g(in)m(to)h(the)f(FITS)f -(\014le)h(will)0 3949 y(ha)m(v)m(e)430 4179 y Fe(FITS)46 -b(value)h(=)g(\(\(input)f(value\))g(-)h(BZERO\))f(/)i(BSCALE)0 -4410 y Fi(\(a)39 b(corresp)s(onding)d(form)m(ula)i(using)g(TSCALn)e -(and)h(TZER)m(On)g(is)h(used)f(when)f(writing)i(to)h(table)g -(columns\).)0 4523 y(Rounding)19 b(to)i(the)g(nearest)g(in)m(teger,)i -(rather)e(than)f(truncation,)j(is)d(p)s(erformed)f(when)g(writing)h(in) -m(teger)i(datat)m(yp)s(es)0 4636 y(to)31 b(the)g(FITS)e(\014le.)0 -4965 y Fd(4.8)135 b(Error)46 b(Status)f(V)-11 b(alues)45 -b(and)g(the)g(Error)g(Message)h(Stac)l(k)0 5215 y Fi(The)33 -b(last)i(parameter)f(in)g(nearly)g(ev)m(ery)g(FITSIO)f(subroutine)g(is) -h(the)g(error)f(status)h(v)-5 b(alue)35 b(whic)m(h)e(is)h(b)s(oth)f(an) -0 5328 y(input)j(and)f(an)i(output)f(parameter.)60 b(A)36 -b(returned)f(p)s(ositiv)m(e)j(v)-5 b(alue)37 b(for)f(this)h(parameter)g -(indicates)g(an)f(error)0 5441 y(w)m(as)31 b(detected.)42 -b(A)30 b(listing)h(of)g(all)g(the)g(FITSIO)e(status)i(co)s(de)f(v)-5 -b(alues)31 b(is)f(giv)m(en)i(at)f(the)f(end)g(of)h(this)f(do)s(cumen)m -(t.)0 5601 y(The)22 b(FITSIO)g(library)g(uses)h(an)f(`inherited)h -(status')g(con)m(v)m(en)m(tion)i(for)e(the)g(status)g(parameter)g(whic) -m(h)g(means)f(that)0 5714 y(if)i(a)h(subroutine)f(is)g(called)i(with)e -(a)h(p)s(ositiv)m(e)g(input)f(v)-5 b(alue)25 b(of)g(the)f(status)h -(parameter,)h(then)f(the)f(subroutine)g(will)p eop end -%%Page: 19 25 -TeXDict begin 19 24 bop 0 299 a Fg(4.9.)72 b(V)-10 b(ARIABLE-LENGTH)31 -b(ARRA)-8 b(Y)31 b(F)-10 b(A)m(CILITY)30 b(IN)h(BINAR)-8 -b(Y)31 b(T)-8 b(ABLES)956 b Fi(19)0 555 y(exit)26 b(immediately)f -(without)g(c)m(hanging)h(the)e(v)-5 b(alue)25 b(of)g(the)g(status)g -(parameter.)39 b(Th)m(us,)25 b(if)g(one)f(passes)h(the)g(status)0 -668 y(v)-5 b(alue)31 b(returned)e(from)h(eac)m(h)i(FITSIO)d(routine)h -(as)h(input)f(to)h(the)f(next)h(FITSIO)e(subroutine,)h(then)g(whenev)m -(er)0 781 y(an)39 b(error)g(is)h(detected)g(all)h(further)d(FITSIO)g -(pro)s(cessing)h(will)h(cease.)69 b(This)39 b(con)m(v)m(en)m(tion)i -(can)f(simplify)f(the)0 894 y(error)30 b(c)m(hec)m(king)j(in)d -(application)i(programs)f(b)s(ecause)g(it)g(is)g(not)g(necessary)g(to)g -(c)m(hec)m(k)i(the)e(v)-5 b(alue)31 b(of)g(the)g(status)0 -1007 y(parameter)j(after)g(ev)m(ery)g(single)h(FITSIO)d(subroutine)g -(call.)52 b(If)33 b(a)h(program)f(con)m(tains)i(a)f(sequence)g(of)g -(sev)m(eral)0 1120 y(FITSIO)23 b(calls,)j(one)e(can)g(just)g(c)m(hec)m -(k)h(the)f(status)g(v)-5 b(alue)24 b(after)h(the)f(last)g(call.)40 -b(Since)24 b(the)g(returned)e(status)j(v)-5 b(alues)0 -1233 y(are)36 b(generally)h(distinctiv)m(e,)i(it)d(should)f(b)s(e)g(p)s -(ossible)g(to)h(determine)g(whic)m(h)f(subroutine)g(originally)i -(returned)0 1346 y(the)31 b(error)f(status.)0 1506 y(FITSIO)i(also)i -(main)m(tains)f(an)g(in)m(ternal)h(stac)m(k)g(of)f(error)g(messages)h -(\(80-c)m(haracter)i(maxim)m(um)d(length\))g(whic)m(h)0 -1619 y(in)j(man)m(y)g(cases)h(pro)m(vide)f(a)g(more)g(detailed)i -(explanation)f(of)f(the)g(cause)h(of)f(the)g(error)g(than)f(is)h(pro)m -(vided)g(b)m(y)0 1732 y(the)k(error)e(status)i(n)m(um)m(b)s(er)e -(alone.)69 b(It)39 b(is)h(recommended)f(that)g(the)h(error)f(message)h -(stac)m(k)h(b)s(e)e(prin)m(ted)g(out)0 1844 y(whenev)m(er)31 -b(a)h(program)g(detects)g(a)g(FITSIO)e(error.)44 b(T)-8 -b(o)32 b(do)f(this,)h(call)h(the)f(FTGMSG)g(routine)f(rep)s(eatedly)h -(to)0 1957 y(get)h(the)g(successiv)m(e)g(messages)h(on)e(the)g(stac)m -(k.)48 b(When)32 b(the)h(stac)m(k)g(is)g(empt)m(y)f(FTGMSG)h(will)g -(return)e(a)h(blank)0 2070 y(string.)41 b(Note)31 b(that)g(this)f(is)g -(a)g(`First)h(In)e({)i(First)f(Out')g(stac)m(k,)i(so)e(the)h(oldest)g -(error)e(message)j(is)e(returned)f(\014rst)0 2183 y(b)m(y)h(ftgmsg.)0 -2557 y Fd(4.9)135 b(V)-11 b(ariable-Length)46 b(Arra)l(y)f(F)-11 -b(acilit)l(y)46 b(in)f(Binary)g(T)-11 b(ables)0 2815 -y Fi(FITSIO)38 b(pro)m(vides)i(easy-to-use)h(supp)s(ort)d(for)h -(reading)g(and)g(writing)h(data)g(in)f(v)-5 b(ariable)40 -b(length)g(\014elds)f(of)h(a)0 2928 y(binary)35 b(table.)56 -b(The)35 b(v)-5 b(ariable)36 b(length)f(columns)g(ha)m(v)m(e)i(TF)m -(ORMn)e(k)m(eyw)m(ord)h(v)-5 b(alues)35 b(of)h(the)f(form)g -(`1Pt\(len\)')0 3041 y(or)30 b(`1Qt\(len\)')h(where)f(`t')g(is)g(the)g -(datat)m(yp)s(e)h(co)s(de)f(\(e.g.,)i(I,)e(J,)f(E,)h(D,)h(etc.\))42 -b(and)29 b(`len')h(is)g(an)g(in)m(teger)h(sp)s(ecifying)0 -3154 y(the)f(maxim)m(um)g(length)g(of)g(the)g(v)m(ector)h(in)f(the)g -(table.)41 b(If)30 b(the)g(v)-5 b(alue)30 b(of)g(`len')g(is)g(not)g(sp) -s(eci\014ed)f(when)g(the)h(table)0 3267 y(is)j(created)g(\(e.g.,)i(if)e -(the)f(TF)m(ORM)h(k)m(eyw)m(ord)g(v)-5 b(alue)33 b(is)g(simply)f(sp)s -(eci\014ed)g(as)h('1PE')g(instead)g(of)f('1PE\(400\))j(\),)0 -3380 y(then)28 b(FITSIO)f(will)h(automatically)k(scan)c(the)g(table)h -(when)f(it)g(is)h(closed)g(to)g(determine)f(the)g(maxim)m(um)h(length)0 -3493 y(of)i(the)f(v)m(ector)i(and)e(will)h(app)s(end)d(this)j(v)-5 -b(alue)30 b(to)i(the)e(TF)m(ORMn)g(v)-5 b(alue.)0 3653 -y(The)25 b(same)h(routines)g(whic)m(h)f(read)h(and)f(write)h(data)g(in) -f(an)h(ordinary)f(\014xed)g(length)h(binary)f(table)h(extension)h(are)0 -3766 y(also)k(used)e(for)h(v)-5 b(ariable)31 b(length)g(\014elds,)e(ho) -m(w)m(ev)m(er,)j(the)e(subroutine)f(parameters)i(tak)m(e)h(on)e(a)g -(sligh)m(tly)h(di\013eren)m(t)0 3878 y(in)m(terpretation)h(as)e -(describ)s(ed)g(b)s(elo)m(w.)0 4039 y(All)37 b(the)f(data)h(in)f(a)h(v) --5 b(ariable)37 b(length)f(\014eld)g(is)g(written)h(in)m(to)g(an)f -(area)h(called)h(the)e(`heap')g(whic)m(h)g(follo)m(ws)i(the)0 -4152 y(main)26 b(\014xed-length)g(FITS)f(binary)h(table.)40 -b(The)25 b(size)i(of)g(the)f(heap,)h(in)f(b)m(ytes,)h(is)f(sp)s -(eci\014ed)g(with)f(the)i(PCOUNT)0 4264 y(k)m(eyw)m(ord)21 -b(in)f(the)h(FITS)f(header.)37 b(When)20 b(creating)i(a)f(new)f(binary) -g(table,)j(the)e(initial)h(v)-5 b(alue)21 b(of)f(PCOUNT)g(should)0 -4377 y(usually)31 b(b)s(e)f(set)i(to)g(zero.)44 b(FITSIO)30 -b(will)h(recompute)h(the)f(size)h(of)g(the)f(heap)g(as)g(the)h(data)g -(is)f(written)g(and)g(will)0 4490 y(automatically)d(up)s(date)c(the)i -(PCOUNT)e(k)m(eyw)m(ord)h(v)-5 b(alue)26 b(when)e(the)h(table)h(is)f -(closed.)40 b(When)25 b(writing)g(v)-5 b(ariable)0 4603 -y(length)34 b(data)g(to)g(a)g(table,)i(CFITSIO)c(will)h(automatically)k -(extend)c(the)h(size)g(of)g(the)g(heap)f(area)h(if)g(necessary)-8 -b(,)0 4716 y(so)31 b(that)g(an)m(y)f(follo)m(wing)i(HDUs)f(do)f(not)h -(get)h(o)m(v)m(erwritten.)0 4876 y(By)e(default)f(the)h(heap)f(data)i -(area)f(starts)g(immediately)h(after)f(the)f(last)i(ro)m(w)e(of)h(the)g -(\014xed-length)f(table.)42 b(This)0 4989 y(default)27 -b(starting)g(lo)s(cation)i(ma)m(y)e(b)s(e)f(o)m(v)m(erridden)h(b)m(y)g -(the)g(THEAP)f(k)m(eyw)m(ord,)i(but)f(this)f(is)h(not)g(recommended.)0 -5102 y(If)34 b(additional)h(ro)m(ws)f(of)g(data)h(are)g(added)e(to)i -(the)f(table,)j(CFITSIO)32 b(will)j(automatically)i(shift)c(the)i(the)f -(heap)0 5215 y(do)m(wn)g(to)i(mak)m(e)f(ro)s(om)g(for)f(the)h(new)f(ro) -m(ws,)i(but)e(it)i(is)e(ob)m(viously)i(b)s(e)e(more)h(e\016cien)m(t)h -(to)f(initially)h(create)h(the)0 5328 y(table)31 b(with)e(the)h -(necessary)g(n)m(um)m(b)s(er)f(of)h(blank)f(ro)m(ws,)h(so)g(that)g(the) -g(heap)g(do)s(es)f(not)h(needed)g(to)g(b)s(e)f(constan)m(tly)0 -5441 y(mo)m(v)m(ed.)0 5601 y(When)40 b(writing)h(to)g(a)g(v)-5 -b(ariable)41 b(length)g(\014eld,)i(the)e(en)m(tire)h(arra)m(y)f(of)f(v) --5 b(alues)41 b(for)f(a)h(giv)m(en)h(ro)m(w)f(of)f(the)h(table)0 -5714 y(m)m(ust)36 b(b)s(e)g(written)g(with)g(a)g(single)h(call)h(to)f -(FTPCLx.)57 b(The)36 b(total)i(length)f(of)f(the)g(arra)m(y)h(is)f -(calculated)i(from)p eop end -%%Page: 20 26 -TeXDict begin 20 25 bop 0 299 a Fi(20)1277 b Fg(CHAPTER)29 -b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 -555 y Fi(\(NELEM+FELEM-1\).)44 b(One)30 b(cannot)i(app)s(end)d(more)i -(elemen)m(ts)h(to)g(an)e(existing)i(\014eld)f(at)g(a)h(later)g(time;)g -(an)m(y)0 668 y(attempt)j(to)f(do)g(so)g(will)g(simply)f(o)m(v)m -(erwrite)j(all)e(the)g(data)h(whic)m(h)e(w)m(as)h(previously)g -(written.)51 b(Note)35 b(also)f(that)0 781 y(the)g(new)g(data)g(will)h -(b)s(e)e(written)h(to)h(a)f(new)g(area)g(of)g(the)h(heap)e(and)h(the)g -(heap)g(space)g(used)f(b)m(y)h(the)g(previous)0 894 y(write)j(cannot)h -(b)s(e)e(reclaimed.)62 b(F)-8 b(or)38 b(this)f(reason)g(it)h(is)f -(advised)g(that)h(eac)m(h)g(ro)m(w)f(of)h(a)f(v)-5 b(ariable)38 -b(length)f(\014eld)0 1007 y(only)c(b)s(e)g(written)g(once.)50 -b(An)33 b(exception)h(to)g(this)f(general)h(rule)f(o)s(ccurs)g(when)f -(setting)i(elemen)m(ts)h(of)e(an)g(arra)m(y)0 1120 y(as)38 -b(unde\014ned.)63 b(One)37 b(m)m(ust)i(\014rst)e(write)h(a)h(dumm)m(y)e -(v)-5 b(alue)39 b(in)m(to)g(the)g(arra)m(y)f(with)g(FTPCLx,)i(and)e -(then)g(call)0 1233 y(FTPCLU)33 b(to)i(\015ag)f(the)f(desired)h(elemen) -m(ts)h(as)e(unde\014ned.)49 b(\(Do)35 b(not)f(use)f(the)h(FTPCNx)f -(family)h(of)g(routines)0 1346 y(with)28 b(v)-5 b(ariable)30 -b(length)f(\014elds\).)40 b(Note)30 b(that)f(the)g(ro)m(ws)g(of)g(a)g -(table,)h(whether)e(\014xed)g(or)h(v)-5 b(ariable)29 -b(length,)h(do)f(not)0 1458 y(ha)m(v)m(e)j(to)f(b)s(e)e(written)i -(consecutiv)m(ely)h(and)e(ma)m(y)h(b)s(e)f(written)g(in)g(an)m(y)h -(order.)0 1619 y(When)40 b(writing)h(to)g(a)g(v)-5 b(ariable)41 -b(length)g(ASCI)s(I)e(c)m(haracter)j(\014eld)e(\(e.g.,)45 -b(TF)m(ORM)c(=)f('1P)-8 b(A'\))43 b(only)d(a)h(single)0 -1732 y(c)m(haracter)33 b(string)f(written.)44 b(FTPCLS)30 -b(writes)i(the)g(whole)f(length)h(of)g(the)g(input)e(string)i(\(min)m -(us)f(an)m(y)h(trailing)0 1844 y(blank)37 b(c)m(haracters\),)42 -b(th)m(us)37 b(the)h(NELEM)f(and)g(FELEM)h(parameters)g(are)g(ignored.) -62 b(If)37 b(the)h(input)e(string)i(is)0 1957 y(completely)28 -b(blank)f(then)f(FITSIO)g(will)h(write)g(one)g(blank)f(c)m(haracter)j -(to)e(the)g(FITS)f(\014le.)40 b(Similarly)-8 b(,)28 b(FTGCVS)0 -2070 y(and)35 b(FTGCFS)g(read)g(the)h(en)m(tire)g(string)g(\(truncated) -f(to)i(the)e(width)g(of)g(the)h(c)m(haracter)h(string)e(argumen)m(t)h -(in)0 2183 y(the)31 b(subroutine)e(call\))j(and)e(also)h(ignore)g(the)f -(NELEM)h(and)f(FELEM)g(parameters.)0 2343 y(The)35 b(FTPDES)h -(subroutine)e(is)i(useful)f(in)g(situations)i(where)e(m)m(ultiple)i(ro) -m(ws)e(of)h(a)g(v)-5 b(ariable)37 b(length)f(column)0 -2456 y(ha)m(v)m(e)c(the)e(iden)m(tical)i(arra)m(y)f(of)g(v)-5 -b(alues.)41 b(One)30 b(can)g(simply)g(write)h(the)f(arra)m(y)h(once)g -(for)g(the)f(\014rst)g(ro)m(w,)g(and)g(then)0 2569 y(use)36 -b(FTPDES)g(to)h(write)g(the)f(same)h(descriptor)g(v)-5 -b(alues)36 b(in)m(to)i(the)e(other)h(ro)m(ws)f(\(use)h(the)f(FTGDES)h -(routine)0 2682 y(to)f(read)f(the)h(\014rst)f(descriptor)g(v)-5 -b(alue\);)39 b(all)d(the)g(ro)m(ws)f(will)h(then)f(p)s(oin)m(t)g(to)h -(the)g(same)f(storage)i(lo)s(cation)g(th)m(us)0 2795 -y(sa)m(ving)31 b(disk)f(space.)0 2955 y(When)35 b(reading)g(from)f(a)i -(v)-5 b(ariable)35 b(length)h(arra)m(y)f(\014eld)g(one)g(can)g(only)h -(read)e(as)i(man)m(y)f(elemen)m(ts)h(as)f(actually)0 -3068 y(exist)i(in)e(that)i(ro)m(w)e(of)h(the)g(table;)k(reading)c(do)s -(es)g(not)g(automatically)i(con)m(tin)m(ue)f(with)f(the)g(next)g(ro)m -(w)g(of)g(the)0 3181 y(table)29 b(as)f(o)s(ccurs)g(when)f(reading)h(an) -g(ordinary)g(\014xed)f(length)h(table)h(\014eld.)40 b(A)m(ttempts)29 -b(to)g(read)f(more)g(than)g(this)0 3294 y(will)k(cause)h(an)e(error)h -(status)g(to)g(b)s(e)f(returned.)44 b(One)32 b(can)g(determine)g(the)g -(n)m(um)m(b)s(er)e(of)i(elemen)m(ts)h(in)f(eac)m(h)h(ro)m(w)0 -3407 y(of)e(a)f(v)-5 b(ariable)31 b(column)g(with)f(the)g(FTGDES)h -(subroutine.)0 3859 y Fd(4.10)136 b(Supp)t(ort)44 b(for)h(IEEE)g(Sp)t -(ecial)h(V)-11 b(alues)0 4133 y Fi(The)26 b(ANSI/IEEE-754)h -(\015oating-p)s(oin)m(t)h(n)m(um)m(b)s(er)d(standard)g(de\014nes)h -(certain)h(sp)s(ecial)g(v)-5 b(alues)26 b(that)h(are)g(used)e(to)0 -4246 y(represen)m(t)j(suc)m(h)g(quan)m(tities)h(as)f(Not-a-Num)m(b)s -(er)h(\(NaN\),)h(denormalized,)f(under\015o)m(w,)e(o)m(v)m(er\015o)m -(w,)j(and)d(in\014nit)m(y)-8 b(.)0 4359 y(\(See)31 b(the)g(App)s(endix) -d(in)j(the)f(FITS)g(standard)f(or)i(the)g(FITS)e(User's)i(Guide)f(for)g -(a)h(list)g(of)g(these)g(v)-5 b(alues\).)41 b(The)0 4472 -y(FITSIO)26 b(subroutines)h(that)h(read)f(\015oating)i(p)s(oin)m(t)e -(data)i(in)e(FITS)g(\014les)g(recognize)j(these)e(IEEE)e(sp)s(ecial)j -(v)-5 b(alues)0 4585 y(and)27 b(b)m(y)h(default)h(in)m(terpret)f(the)h -(o)m(v)m(er\015o)m(w)g(and)f(in\014nit)m(y)f(v)-5 b(alues)29 -b(as)f(b)s(eing)g(equiv)-5 b(alen)m(t)29 b(to)g(a)g(NaN,)g(and)e(con)m -(v)m(ert)0 4698 y(the)37 b(under\015o)m(w)e(and)i(denormalized)g(v)-5 -b(alues)37 b(in)m(to)h(zeros.)60 b(In)36 b(some)i(cases)f(programmers)g -(ma)m(y)g(w)m(an)m(t)h(access)0 4811 y(to)h(the)g(ra)m(w)f(IEEE)g(v)-5 -b(alues,)41 b(without)e(an)m(y)f(mo)s(di\014cation)h(b)m(y)g(FITSIO.)e -(This)h(can)g(b)s(e)g(done)g(b)m(y)h(calling)h(the)0 -4924 y(FTGPVx)27 b(or)g(FTGCVx)h(routines)f(while)g(sp)s(ecifying)g -(0.0)h(as)f(the)g(v)-5 b(alue)28 b(of)f(the)h(NULL)-10 -b(V)g(AL)27 b(parameter.)40 b(This)0 5036 y(will)27 b(force)g(FITSIO)e -(to)i(simply)f(pass)f(the)i(IEEE)f(v)-5 b(alues)26 b(through)g(to)h -(the)f(application)i(program,)f(without)g(an)m(y)0 5149 -y(mo)s(di\014cation.)63 b(This)37 b(do)s(es)g(not)h(w)m(ork)g(for)f -(double)g(precision)h(v)-5 b(alues)38 b(on)g(V)-10 b(AX/VMS)38 -b(mac)m(hines,)i(ho)m(w)m(ev)m(er,)0 5262 y(where)34 -b(there)g(is)g(no)g(easy)h(w)m(a)m(y)g(to)g(b)m(ypass)f(the)g(default)h -(in)m(terpretation)g(of)g(the)f(IEEE)f(sp)s(ecial)i(v)-5 -b(alues.)53 b(This)0 5375 y(is)44 b(also)h(not)f(supp)s(orted)e(when)h -(reading)h(\015oating-p)s(oin)m(t)h(images)h(that)e(ha)m(v)m(e)h(b)s -(een)e(compressed)h(with)g(the)0 5488 y(FITS)33 b(tiled)h(image)g -(compression)f(con)m(v)m(en)m(tion)j(that)e(is)f(discussed)g(in)g -(section)h(5.6;)i(the)e(pixels)f(v)-5 b(alues)34 b(in)f(tile)0 -5601 y(compressed)d(images)i(are)f(represen)m(ted)g(b)m(y)g(scaled)g -(in)m(tegers,)h(and)e(a)i(reserv)m(ed)e(in)m(teger)j(v)-5 -b(alue)31 b(\(not)g(a)g(NaN\))h(is)0 5714 y(used)e(to)h(represen)m(t)f -(unde\014ned)e(pixels.)p eop end -%%Page: 21 27 -TeXDict begin 21 26 bop 0 299 a Fg(4.11.)73 b(WHEN)31 -b(THE)f(FINAL)g(SIZE)f(OF)i(THE)f(FITS)f(HDU)i(IS)f(UNKNO)m(WN)978 -b Fi(21)0 555 y Fd(4.11)136 b(When)44 b(the)h(Final)h(Size)f(of)g(the)g -(FITS)f(HDU)h(is)g(Unkno)l(wn)0 805 y Fi(It)27 b(is)h(not)f(required)f -(to)i(kno)m(w)f(the)h(total)h(size)f(of)f(a)h(FITS)e(data)i(arra)m(y)g -(or)f(table)h(b)s(efore)f(b)s(eginning)f(to)i(write)g(the)0 -918 y(data)k(to)f(the)g(FITS)f(\014le.)43 b(In)30 b(the)h(case)h(of)f -(the)g(primary)f(arra)m(y)h(or)g(an)f(image)j(extension,)e(one)h -(should)d(initially)0 1031 y(create)i(the)e(arra)m(y)h(with)e(the)i -(size)g(of)f(the)g(highest)g(dimension)g(\(largest)i(NAXISn)d(k)m(eyw)m -(ord\))i(set)g(to)g(a)f(dumm)m(y)0 1144 y(v)-5 b(alue,)26 -b(suc)m(h)e(as)g(1.)39 b(Then)23 b(after)i(all)g(the)g(data)f(ha)m(v)m -(e)i(b)s(een)d(written)h(and)g(the)g(true)g(dimensions)g(are)g(kno)m -(wn,)h(then)0 1257 y(the)31 b(NAXISn)e(v)-5 b(alue)31 -b(should)f(b)s(e)g(up)s(dated)f(using)h(the)h(\014ts)p -2051 1257 28 4 v 62 w(up)s(date)p 2389 1257 V 32 w(k)m(ey)h(routine)e -(b)s(efore)g(mo)m(ving)i(to)f(another)0 1370 y(extension)g(or)f -(closing)i(the)e(FITS)g(\014le.)0 1530 y(When)f(writing)g(to)g(FITS)g -(tables,)h(CFITSIO)d(automatically)32 b(k)m(eeps)e(trac)m(k)g(of)f(the) -g(highest)h(ro)m(w)f(n)m(um)m(b)s(er)e(that)0 1643 y(is)32 -b(written)g(to,)h(and)e(will)h(increase)h(the)f(size)h(of)f(the)g -(table)g(if)g(necessary)-8 b(.)46 b(CFITSIO)30 b(will)i(also)h -(automatically)0 1756 y(insert)j(space)h(in)f(the)g(FITS)f(\014le)i(if) -f(necessary)-8 b(,)39 b(to)e(ensure)e(that)i(the)f(data)h('heap',)h(if) -e(it)h(exists,)h(and/or)f(an)m(y)0 1869 y(additional)29 -b(HDUs)g(that)g(follo)m(w)g(the)g(table)g(do)f(not)h(get)g(o)m(v)m -(erwritten)h(as)e(new)g(ro)m(ws)g(are)h(written)f(to)h(the)g(table.)0 -2029 y(As)37 b(a)h(general)g(rule)f(it)h(is)f(b)s(est)g(to)h(sp)s -(ecify)f(the)h(initial)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)f(=)g(0)g(when) -g(the)g(table)h(is)g(created,)0 2142 y(then)g(let)h(CFITSIO)e(k)m(eep)i -(trac)m(k)g(of)g(the)f(n)m(um)m(b)s(er)f(of)i(ro)m(ws)f(that)h(are)f -(actually)i(written.)65 b(The)38 b(application)0 2255 -y(program)e(should)f(not)i(man)m(ually)g(up)s(date)e(the)i(n)m(um)m(b)s -(er)e(of)h(ro)m(ws)g(in)g(the)h(table)g(\(as)g(giv)m(en)g(b)m(y)f(the)h -(NAXIS2)0 2368 y(k)m(eyw)m(ord\))j(since)f(CFITSIO)e(do)s(es)i(this)g -(automatically)-8 b(.)69 b(If)38 b(a)i(table)f(is)g(initially)i -(created)f(with)e(more)h(than)0 2481 y(zero)i(ro)m(ws,)j(then)c(this)h -(will)f(usually)h(b)s(e)f(considered)g(as)h(the)g(minim)m(um)f(size)h -(of)g(the)g(table,)j(ev)m(en)d(if)g(few)m(er)0 2594 y(ro)m(ws)30 -b(are)g(actually)h(written)f(to)h(the)f(table.)41 b(Th)m(us,)30 -b(if)f(a)i(table)f(is)g(initially)h(created)g(with)f(NAXIS2)g(=)g(20,)h -(and)0 2706 y(CFITSIO)g(only)i(writes)f(10)i(ro)m(ws)e(of)h(data)g(b)s -(efore)f(closing)i(the)f(table,)h(then)e(NAXIS2)h(will)g(remain)f -(equal)h(to)0 2819 y(20.)50 b(If)33 b(ho)m(w)m(ev)m(er,)i(30)g(ro)m(ws) -e(of)g(data)h(are)g(written)f(to)h(this)f(table,)i(then)e(NAXIS2)h -(will)f(b)s(e)g(increased)g(from)g(20)0 2932 y(to)f(30.)44 -b(The)31 b(one)g(exception)i(to)f(this)f(automatic)i(up)s(dating)d(of)h -(the)h(NAXIS2)f(k)m(eyw)m(ord)h(is)f(if)g(the)h(application)0 -3045 y(program)c(directly)g(mo)s(di\014es)f(the)i(v)-5 -b(alue)28 b(of)g(NAXIS2)g(\(up)f(or)h(do)m(wn\))g(itself)h(just)e(b)s -(efore)h(closing)h(the)f(table.)41 b(In)0 3158 y(this)28 -b(case,)i(CFITSIO)d(do)s(es)h(not)h(up)s(date)e(NAXIS2)i(again,)h -(since)f(it)g(assumes)f(that)h(the)f(application)i(program)0 -3271 y(m)m(ust)i(ha)m(v)m(e)h(had)f(a)g(go)s(o)s(d)g(reason)h(for)f(c)m -(hanging)h(the)f(v)-5 b(alue)33 b(directly)-8 b(.)47 -b(This)31 b(is)h(not)h(recommended,)f(ho)m(w)m(ev)m(er,)0 -3384 y(and)j(is)h(only)g(pro)m(vided)g(for)f(bac)m(kw)m(ard)h -(compatibilit)m(y)i(with)e(soft)m(w)m(are)h(that)g(initially)g(creates) -g(a)f(table)h(with)0 3497 y(a)d(large)h(n)m(um)m(b)s(er)e(of)h(ro)m -(ws,)h(than)f(decreases)g(the)h(NAXIS2)f(v)-5 b(alue)34 -b(to)h(the)f(actual)h(smaller)g(v)-5 b(alue)34 b(just)f(b)s(efore)0 -3610 y(closing)e(the)g(table.)0 3941 y Fd(4.12)136 b(Lo)t(cal)45 -b(FITS)e(Con)l(v)l(en)l(tions)k(supp)t(orted)d(b)l(y)h(FITSIO)0 -4191 y Fi(CFITSIO)29 b(supp)s(orts)g(sev)m(eral)j(lo)s(cal)g(FITS)e -(con)m(v)m(en)m(tions)i(whic)m(h)f(are)g(not)g(de\014ned)e(in)i(the)f -(o\016cial)j(FITS)d(stan-)0 4304 y(dard)43 b(and)g(whic)m(h)g(are)h -(not)g(necessarily)g(recognized)h(or)f(supp)s(orted)e(b)m(y)h(other)h -(FITS)f(soft)m(w)m(are)i(pac)m(k)-5 b(ages.)0 4417 y(Programmers)36 -b(should)f(b)s(e)g(cautious)i(ab)s(out)e(using)h(these)g(features,)i -(esp)s(ecially)f(if)f(the)g(FITS)f(\014les)h(that)h(are)0 -4530 y(pro)s(duced)31 b(are)i(exp)s(ected)g(to)g(b)s(e)f(pro)s(cessed)g -(b)m(y)h(other)f(soft)m(w)m(are)i(systems)f(whic)m(h)f(do)h(not)f(use)h -(the)f(CFITSIO)0 4642 y(in)m(terface.)0 4930 y Fb(4.12.1)113 -b(Supp)s(ort)37 b(for)h(Long)g(String)f(Keyw)m(ord)h(V)-9 -b(alues.)0 5149 y Fi(The)23 b(length)i(of)f(a)g(standard)f(FITS)g -(string)h(k)m(eyw)m(ord)g(is)g(limited)h(to)f(68)h(c)m(haracters)g(b)s -(ecause)f(it)g(m)m(ust)g(\014t)g(en)m(tirely)0 5262 y(within)35 -b(a)h(single)h(FITS)e(header)h(k)m(eyw)m(ord)g(record.)57 -b(In)35 b(some)h(instances)g(it)h(is)e(necessary)i(to)f(enco)s(de)g -(strings)0 5375 y(longer)27 b(than)f(this)g(limit,)i(so)e(FITSIO)f -(supp)s(orts)f(a)j(lo)s(cal)g(con)m(v)m(en)m(tion)h(in)e(whic)m(h)g -(the)g(string)g(v)-5 b(alue)27 b(is)f(con)m(tin)m(ued)0 -5488 y(o)m(v)m(er)34 b(m)m(ultiple)g(k)m(eyw)m(ords.)49 -b(This)32 b(con)m(tin)m(uation)j(con)m(v)m(en)m(tion)h(uses)c(an)h(amp) -s(ersand)f(c)m(haracter)i(at)g(the)f(end)g(of)0 5601 -y(eac)m(h)c(substring)d(to)i(indicate)h(that)f(it)g(is)g(con)m(tin)m -(ued)g(on)f(the)h(next)g(k)m(eyw)m(ord,)h(and)d(the)i(con)m(tin)m -(uation)i(k)m(eyw)m(ords)0 5714 y(all)44 b(ha)m(v)m(e)h(the)f(name)f -(CONTINUE)g(without)g(an)h(equal)g(sign)f(in)g(column)h(9.)80 -b(The)43 b(string)h(v)-5 b(alue)43 b(ma)m(y)i(b)s(e)p -eop end -%%Page: 22 28 -TeXDict begin 22 27 bop 0 299 a Fi(22)1277 b Fg(CHAPTER)29 -b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 -555 y Fi(con)m(tin)m(ued)e(in)f(this)h(w)m(a)m(y)g(o)m(v)m(er)h(as)e -(man)m(y)h(additional)g(CONTINUE)f(k)m(eyw)m(ords)g(as)h(is)f -(required.)40 b(The)27 b(follo)m(wing)0 668 y(lines)k(illustrate)g -(this)f(con)m(tin)m(uation)j(con)m(v)m(en)m(tion)f(whic)m(h)e(is)h -(used)e(in)h(the)h(v)-5 b(alue)31 b(of)f(the)h(STRKEY)e(k)m(eyw)m(ord:) -0 920 y Fe(LONGSTRN=)45 b('OGIP)i(1.0')524 b(/)47 b(The)g(OGIP)g(Long)f -(String)g(Convention)f(may)i(be)g(used.)0 1033 y(STRKEY)94 -b(=)47 b('This)g(is)g(a)g(very)g(long)g(string)f(keyword&')93 -b(/)47 b(Optional)f(Comment)0 1146 y(CONTINUE)93 b(')48 -b(value)e(that)h(is)g(continued)e(over)i(3)g(keywords)f(in)h(the)g(&)95 -b(')0 1259 y(CONTINUE)e('FITS)47 b(header.')e(/)j(This)e(is)h(another)f -(optional)g(comment.)0 1511 y Fi(It)29 b(is)g(recommended)f(that)h(the) -g(LONGSTRN)f(k)m(eyw)m(ord,)i(as)f(sho)m(wn)f(here,)h(alw)m(a)m(ys)i(b) -s(e)d(included)g(in)g(an)m(y)h(HDU)0 1624 y(that)f(uses)e(this)h -(longstring)h(con)m(v)m(en)m(tion.)42 b(A)27 b(subroutine)f(called)i -(FTPLSW)f(has)g(b)s(een)f(pro)m(vided)h(in)f(CFITSIO)0 -1737 y(to)31 b(write)g(this)f(k)m(eyw)m(ord)h(if)f(it)h(do)s(es)f(not)h -(already)g(exist.)0 1897 y(This)23 b(long)i(string)g(con)m(v)m(en)m -(tion)h(is)e(supp)s(orted)f(b)m(y)h(the)g(follo)m(wing)i(FITSIO)d -(subroutines)g(that)i(deal)g(with)f(string-)0 2010 y(v)-5 -b(alued)30 b(k)m(eyw)m(ords:)286 2262 y Fe(ftgkys)46 -b(-)i(read)f(a)g(string)f(keyword)286 2375 y(ftpkls)g(-)i(write)e -(\(append\))g(a)h(string)f(keyword)286 2488 y(ftikls)g(-)i(insert)e(a)h -(string)g(keyword)286 2601 y(ftmkls)f(-)i(modify)e(the)h(value)f(of)h -(an)h(existing)d(string)h(keyword)286 2714 y(ftukls)g(-)i(update)e(an)h -(existing)f(keyword,)f(or)i(write)g(a)g(new)g(keyword)286 -2827 y(ftdkey)f(-)i(delete)e(a)h(keyword)0 3079 y Fi(These)41 -b(routines)f(will)h(transparen)m(tly)g(read,)j(write,)g(or)d(delete)h -(a)f(long)g(string)g(v)-5 b(alue)41 b(in)g(the)g(FITS)f(\014le,)k(so)0 -3192 y(programmers)36 b(in)g(general)h(do)f(not)h(ha)m(v)m(e)g(to)g(b)s -(e)f(concerned)g(ab)s(out)g(the)g(details)i(of)e(the)h(con)m(v)m(en)m -(tion)h(that)f(is)0 3304 y(used)32 b(to)i(enco)s(de)f(the)g(long)g -(string)g(in)g(the)g(FITS)f(header.)48 b(When)33 b(reading)g(a)g(long)h -(string,)g(one)f(m)m(ust)g(ensure)0 3417 y(that)h(the)f(c)m(haracter)i -(string)f(parameter)g(used)e(in)h(these)h(subroutine)e(calls)j(has)e(b) -s(een)f(declared)i(long)g(enough)0 3530 y(to)d(hold)f(the)h(en)m(tire)g -(string,)g(otherwise)f(the)h(returned)e(string)h(v)-5 -b(alue)31 b(will)g(b)s(e)f(truncated.)0 3690 y(Note)d(that)e(the)h -(more)f(commonly)h(used)e(FITSIO)g(subroutine)h(to)h(write)f(string)g -(v)-5 b(alued)25 b(k)m(eyw)m(ords)h(\(FTPKYS\))0 3803 -y(do)s(es)38 b(NOT)g(supp)s(ort)f(this)h(long)h(string)g(con)m(v)m(en)m -(tion)h(and)e(only)h(supp)s(orts)d(strings)i(up)g(to)h(68)g(c)m -(haracters)h(in)0 3916 y(length.)i(This)30 b(has)g(b)s(een)g(done)h -(delib)s(erately)g(to)h(prev)m(en)m(t)f(programs)g(from)f(inadv)m -(erten)m(tly)i(writing)f(k)m(eyw)m(ords)0 4029 y(using)38 -b(this)h(non-standard)e(con)m(v)m(en)m(tion)k(without)e(the)f(explicit) -i(in)m(ten)m(t)g(of)f(the)g(programmer)f(or)h(user.)64 -b(The)0 4142 y(FTPKLS)28 b(subroutine)g(m)m(ust)h(b)s(e)g(called)h -(instead)g(to)g(write)f(long)h(strings.)40 b(This)28 -b(routine)i(can)f(also)h(b)s(e)f(used)f(to)0 4255 y(write)j(ordinary)e -(string)i(v)-5 b(alues)30 b(less)h(than)f(68)h(c)m(haracters)h(in)e -(length.)0 4544 y Fb(4.12.2)113 b(Arra)m(ys)37 b(of)g(Fixed-Length)j -(Strings)e(in)f(Binary)h(T)-9 b(ables)0 4763 y Fi(CFITSIO)25 -b(supp)s(orts)g(2)i(w)m(a)m(ys)g(to)g(sp)s(ecify)f(that)i(a)f(c)m -(haracter)h(column)e(in)g(a)h(binary)f(table)i(con)m(tains)f(an)g(arra) -m(y)g(of)0 4876 y(\014xed-length)32 b(strings.)46 b(The)32 -b(\014rst)f(w)m(a)m(y)-8 b(,)34 b(whic)m(h)e(is)g(o\016cially)i(supp)s -(orted)c(b)m(y)i(the)h(FITS)e(Standard)g(do)s(cumen)m(t,)0 -4989 y(uses)38 b(the)g(TDIMn)g(k)m(eyw)m(ord.)65 b(F)-8 -b(or)39 b(example,)i(if)d(TF)m(ORMn)g(=)g('60A')h(and)f(TDIMn)g(=)g -('\(12,5\)')i(then)e(that)0 5102 y(column)30 b(will)h(b)s(e)f(in)m -(terpreted)g(as)h(con)m(taining)h(an)e(arra)m(y)h(of)g(5)f(strings,)h -(eac)m(h)g(12)g(c)m(haracters)h(long.)0 5262 y(FITSIO)40 -b(also)i(supp)s(orts)d(a)i(lo)s(cal)h(con)m(v)m(en)m(tion)h(for)e(the)g -(format)h(of)f(the)g(TF)m(ORMn)g(k)m(eyw)m(ord)g(v)-5 -b(alue)42 b(of)f(the)0 5375 y(form)h('rAw')g(where)g('r')g(is)h(an)f -(in)m(teger)i(sp)s(ecifying)e(the)g(total)j(width)c(in)h(c)m(haracters) -i(of)f(the)f(column,)k(and)0 5488 y('w')36 b(is)g(an)g(in)m(teger)h(sp) -s(ecifying)f(the)g(\(\014xed\))g(length)h(of)f(an)g(individual)f(unit)h -(string)f(within)h(the)g(v)m(ector.)59 b(F)-8 b(or)0 -5601 y(example,)47 b(TF)m(ORM1)d(=)f('120A10')j(w)m(ould)d(indicate)h -(that)f(the)h(binary)e(table)i(column)f(is)g(120)h(c)m(haracters)0 -5714 y(wide)32 b(and)g(consists)h(of)g(12)g(10-c)m(haracter)i(length)e -(strings.)47 b(This)31 b(con)m(v)m(en)m(tion)k(is)d(recognized)i(b)m(y) -e(the)h(FITSIO)p eop end -%%Page: 23 29 -TeXDict begin 23 28 bop 0 299 a Fg(4.12.)73 b(LOCAL)29 -b(FITS)h(CONVENTIONS)f(SUPPOR)-8 b(TED)29 b(BY)i(FITSIO)1168 -b Fi(23)0 555 y(subroutines)40 b(that)h(read)g(or)g(write)g(strings)f -(in)h(binary)f(tables.)73 b(The)40 b(Binary)h(T)-8 b(able)42 -b(de\014nition)e(do)s(cumen)m(t)0 668 y(sp)s(eci\014es)31 -b(that)i(other)e(optional)i(c)m(haracters)g(ma)m(y)g(follo)m(w)g(the)e -(datat)m(yp)s(e)i(co)s(de)f(in)f(the)h(TF)m(ORM)g(k)m(eyw)m(ord,)h(so)0 -781 y(this)j(lo)s(cal)i(con)m(v)m(en)m(tion)h(is)e(in)f(compliance)i -(with)e(the)h(FITS)f(standard,)h(although)g(other)g(FITS)f(readers)h -(are)0 894 y(not)31 b(required)e(to)i(recognize)h(this)f(con)m(v)m(en)m -(tion.)0 1183 y Fb(4.12.3)113 b(Keyw)m(ord)37 b(Units)h(Strings)0 -1402 y Fi(One)f(de\014ciency)h(of)g(the)g(curren)m(t)g(FITS)f(Standard) -f(is)i(that)h(it)f(do)s(es)f(not)h(de\014ne)f(a)i(sp)s(eci\014c)e(con)m -(v)m(en)m(tion)j(for)0 1515 y(recording)30 b(the)g(ph)m(ysical)h(units) -f(of)g(a)g(k)m(eyw)m(ord)h(v)-5 b(alue.)41 b(The)30 b(TUNITn)f(k)m(eyw) -m(ord)h(can)g(b)s(e)g(used)f(to)i(sp)s(ecify)f(the)0 -1628 y(ph)m(ysical)36 b(units)f(of)g(the)h(v)-5 b(alues)36 -b(in)f(a)g(table)i(column,)f(but)f(there)g(is)h(no)f(analogous)i(con)m -(v)m(en)m(tion)g(for)e(k)m(eyw)m(ord)0 1741 y(v)-5 b(alues.)42 -b(The)30 b(commen)m(t)h(\014eld)g(of)f(the)h(k)m(eyw)m(ord)g(is)g -(often)g(used)f(for)g(this)g(purp)s(ose,)g(but)f(the)i(units)f(are)h -(usually)0 1854 y(not)g(sp)s(eci\014ed)e(in)h(a)h(w)m(ell)g(de\014ned)f -(format)g(that)h(FITS)f(readers)g(can)h(easily)g(recognize)h(and)e -(extract.)0 2014 y(T)-8 b(o)28 b(solv)m(e)h(this)e(de\014ciency)-8 -b(,)30 b(FITSIO)c(uses)h(a)h(lo)s(cal)h(con)m(v)m(en)m(tion)h(in)d -(whic)m(h)g(the)h(k)m(eyw)m(ord)g(units)f(are)h(enclosed)g(in)0 -2127 y(square)20 b(brac)m(k)m(ets)j(as)e(the)f(\014rst)g(tok)m(en)i(in) -f(the)f(k)m(eyw)m(ord)i(commen)m(t)f(\014eld;)j(more)d(sp)s -(eci\014cally)-8 b(,)24 b(the)d(op)s(ening)f(square)0 -2240 y(brac)m(k)m(et)28 b(immediately)g(follo)m(ws)f(the)g(slash)f('/') -h(commen)m(t)h(\014eld)e(delimiter)h(and)f(a)g(single)h(space)g(c)m -(haracter.)41 b(The)0 2352 y(follo)m(wing)32 b(examples)f(illustrate)g -(k)m(eyw)m(ords)g(that)g(use)f(this)g(con)m(v)m(en)m(tion:)0 -2602 y Fe(EXPOSURE=)713 b(1800.0)47 b(/)g([s])g(elapsed)f(exposure)f -(time)0 2715 y(V_HELIO)h(=)763 b(16.23)47 b(/)g([km)g(s**\(-1\)])e -(heliocentric)g(velocity)0 2828 y(LAMBDA)94 b(=)763 b(5400.)47 -b(/)g([angstrom])e(central)h(wavelength)0 2941 y(FLUX)190 -b(=)47 b(4.9033487787637465E-30)42 b(/)47 b([J/cm**2/s])e(average)h -(flux)0 3191 y Fi(In)28 b(general,)h(the)g(units)e(named)h(in)g(the)h -(IA)m(U\(1988\))i(St)m(yle)e(Guide)f(are)h(recommended,)f(with)g(the)h -(main)f(excep-)0 3304 y(tion)j(that)g(the)f(preferred)g(unit)f(for)i -(angle)g(is)f('deg')i(for)e(degrees.)0 3464 y(The)24 -b(FTPUNT)g(and)g(FTGUNT)h(subroutines)f(in)g(FITSIO)f(write)i(and)f -(read,)i(resp)s(ectiv)m(ely)-8 b(,)28 b(the)c(k)m(eyw)m(ord)h(unit)0 -3577 y(strings)30 b(in)g(an)h(existing)g(k)m(eyw)m(ord.)0 -3866 y Fb(4.12.4)113 b(HIERAR)m(CH)34 b(Con)m(v)m(en)m(tion)k(for)f -(Extended)h(Keyw)m(ord)f(Names)0 4085 y Fi(CFITSIO)k(supp)s(orts)g(the) -i(HIERAR)m(CH)g(k)m(eyw)m(ord)g(con)m(v)m(en)m(tion)i(whic)m(h)e(allo)m -(ws)h(k)m(eyw)m(ord)f(names)g(that)h(are)0 4198 y(longer)34 -b(then)e(8)i(c)m(haracters)g(and)f(ma)m(y)h(con)m(tain)g(the)f(full)g -(range)g(of)h(prin)m(table)f(ASCI)s(I)e(text)j(c)m(haracters.)51 -b(This)0 4311 y(con)m(v)m(en)m(tion)39 b(w)m(as)f(dev)m(elop)s(ed)f(at) -h(the)f(Europ)s(ean)f(Southern)g(Observ)-5 b(atory)37 -b(\(ESO\))f(to)i(supp)s(ort)d(hierarc)m(hical)0 4424 -y(FITS)30 b(k)m(eyw)m(ord)g(suc)m(h)h(as:)0 4674 y Fe(HIERARCH)46 -b(ESO)g(INS)h(FOCU)g(POS)g(=)g(-0.00002500)e(/)j(Focus)e(position)0 -4924 y Fi(Basically)-8 b(,)55 b(this)47 b(con)m(v)m(en)m(tion)j(uses)d -(the)h(FITS)f(k)m(eyw)m(ord)h('HIERAR)m(CH')h(to)f(indicate)h(that)f -(this)f(con)m(v)m(en-)0 5036 y(tion)e(is)f(b)s(eing)g(used,)j(then)d -(the)g(actual)i(k)m(eyw)m(ord)e(name)h(\()p Fe('ESO)i(INS)f(FOCU)h -(POS')c Fi(in)h(this)g(example\))h(b)s(e-)0 5149 y(gins)40 -b(in)f(column)g(10)i(and)e(can)h(con)m(tain)g(an)m(y)g(prin)m(table)g -(ASCI)s(I)e(text)j(c)m(haracters,)i(including)d(spaces.)68 -b(The)0 5262 y(equals)44 b(sign)h(marks)e(the)h(end)g(of)g(the)g(k)m -(eyw)m(ord)h(name)f(and)f(is)i(follo)m(w)m(ed)g(b)m(y)f(the)g(usual)g -(v)-5 b(alue)45 b(and)e(com-)0 5375 y(men)m(t)31 b(\014elds)f(just)g -(as)h(in)f(standard)g(FITS)g(k)m(eyw)m(ords.)41 b(F)-8 -b(urther)30 b(details)i(of)f(this)f(con)m(v)m(en)m(tion)j(are)e -(describ)s(ed)e(at)0 5488 y(h)m(ttp://\014ts.gsfc.nasa.go)m -(v/registry/hierarc)m(h)p 1659 5488 28 4 v 38 w(k)m(eyw)m(ord.h)m(tml)f -(and)f(in)g(Section)g(4.4)h(of)g(the)f(ESO)f(Data)j(In)m(ter-)0 -5601 y(face)c(Con)m(trol)f(Do)s(cumen)m(t)h(that)g(is)f(link)m(ed)g(to) -g(from)g(h)m(ttp://arc)m(hiv)m(e.eso.org/cms/to)s(ols-)q(do)s(cumen)m -(tati)q(on/eso)q(-)0 5714 y(data-in)m(terface-con)m(trol.h)m(tml.)p -eop end -%%Page: 24 30 -TeXDict begin 24 29 bop 0 299 a Fi(24)1277 b Fg(CHAPTER)29 -b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 -555 y Fi(This)43 b(con)m(v)m(en)m(tion)k(allo)m(ws)f(a)e(m)m(uc)m(h)h -(broader)e(range)i(of)f(k)m(eyw)m(ord)h(names)f(than)h(is)f(allo)m(w)m -(ed)i(b)m(y)e(the)h(FITS)0 668 y(Standard.)40 b(Here)30 -b(are)h(more)g(examples)g(of)f(suc)m(h)g(k)m(eyw)m(ords:)0 -941 y Fe(HIERARCH)46 b(LongKeyword)e(=)k(47.5)e(/)i(Keyword)e(has)h(>)g -(8)g(characters,)e(and)i(mixed)f(case)0 1054 y(HIERARCH)g(XTE$TEMP)f(=) -j(98.6)e(/)i(Keyword)d(contains)h(the)h('$')g(character)0 -1167 y(HIERARCH)f(Earth)g(is)h(a)h(star)e(=)i(F)f(/)h(Keyword)d -(contains)h(embedded)f(spaces)0 1440 y Fi(CFITSIO)40 -b(will)i(transparen)m(tly)g(read)g(and)f(write)g(these)i(k)m(eyw)m -(ords,)i(so)d(application)h(programs)e(do)g(not)h(in)0 -1553 y(general)33 b(need)f(to)h(kno)m(w)f(an)m(ything)h(ab)s(out)f(the) -g(sp)s(eci\014c)g(implemen)m(tation)i(details)f(of)g(the)f(HIERAR)m(CH) -g(con-)0 1666 y(v)m(en)m(tion.)50 b(In)32 b(particular,)j(application)f -(programs)e(do)h(not)h(need)e(to)i(sp)s(ecify)f(the)g(`HIERAR)m(CH')h -(part)f(of)g(the)0 1779 y(k)m(eyw)m(ord)g(name)f(when)g(reading)g(or)g -(writing)h(k)m(eyw)m(ords)f(\(although)h(it)g(ma)m(y)g(b)s(e)f -(included)f(if)i(desired\).)46 b(When)0 1892 y(writing)35 -b(a)g(k)m(eyw)m(ord,)h(CFITSIO)d(\014rst)h(c)m(hec)m(ks)i(to)f(see)g -(if)g(the)g(k)m(eyw)m(ord)g(name)f(is)h(legal)h(as)f(a)g(standard)f -(FITS)0 2005 y(k)m(eyw)m(ord)k(\(no)g(more)f(than)h(8)g(c)m(haracters)h -(long)f(and)f(con)m(taining)i(only)e(letters,)k(digits,)f(or)e(a)g(min) -m(us)e(sign)i(or)0 2117 y(underscore\).)68 b(If)39 b(so)h(it)g(writes)g -(it)g(as)f(a)h(standard)f(FITS)g(k)m(eyw)m(ord,)k(otherwise)d(it)g -(uses)f(the)h(hierarc)m(h)f(con-)0 2230 y(v)m(en)m(tion)34 -b(to)f(write)g(the)f(k)m(eyw)m(ord.)48 b(The)32 b(maxim)m(um)g(k)m(eyw) -m(ord)h(name)f(length)h(is)g(67)g(c)m(haracters,)i(whic)m(h)d(lea)m(v)m -(es)0 2343 y(only)c(1)h(space)g(for)f(the)h(v)-5 b(alue)29 -b(\014eld.)39 b(A)29 b(more)f(practical)i(limit)f(is)g(ab)s(out)f(40)h -(c)m(haracters,)i(whic)m(h)d(lea)m(v)m(es)i(enough)0 -2456 y(ro)s(om)e(for)h(most)f(k)m(eyw)m(ord)h(v)-5 b(alues.)41 -b(CFITSIO)27 b(returns)g(an)h(error)h(if)f(there)h(is)f(not)h(enough)f -(ro)s(om)h(for)f(b)s(oth)g(the)0 2569 y(k)m(eyw)m(ord)k(name)f(and)f -(the)i(k)m(eyw)m(ord)f(v)-5 b(alue)32 b(on)f(the)h(80-c)m(haracter)h -(card,)f(except)g(for)f(string-v)-5 b(alued)32 b(k)m(eyw)m(ords)0 -2682 y(whic)m(h)h(are)g(simply)f(truncated)h(so)g(that)h(the)f(closing) -h(quote)g(c)m(haracter)g(falls)f(in)g(column)g(80.)49 -b(In)32 b(the)h(curren)m(t)0 2795 y(implemen)m(tation,)e(CFITSIO)c -(preserv)m(es)i(the)g(case)h(of)f(the)g(letters)h(when)e(writing)h(the) -g(k)m(eyw)m(ord)g(name,)g(but)f(it)0 2908 y(is)d(case-insensitiv)m(e)i -(when)d(reading)h(or)g(searc)m(hing)h(for)f(a)g(k)m(eyw)m(ord.)40 -b(The)24 b(curren)m(t)h(implemen)m(tation)h(allo)m(ws)h(an)m(y)0 -3021 y(ASCI)s(I)i(text)j(c)m(haracter)h(\(ASCI)s(I)c(32)j(to)f(ASCI)s -(I)f(126\))i(in)f(the)g(k)m(eyw)m(ord)g(name)g(except)h(for)e(the)h -('=')g(c)m(haracter.)0 3134 y(A)f(space)h(is)g(also)g(required)f(on)g -(either)h(side)f(of)h(the)f(equal)h(sign.)0 3483 y Fd(4.13)136 -b(Optimizing)45 b(Co)t(de)g(for)h(Maxim)l(um)f(Pro)t(cessing)g(Sp)t -(eed)0 3736 y Fi(CFITSIO)22 b(has)h(b)s(een)f(carefully)i(designed)f -(to)h(obtain)g(the)f(highest)h(p)s(ossible)e(sp)s(eed)h(when)f(reading) -h(and)g(writing)0 3849 y(FITS)33 b(\014les.)51 b(In)33 -b(order)h(to)g(ac)m(hiev)m(e)i(the)e(b)s(est)g(p)s(erformance,)g(ho)m -(w)m(ev)m(er,)i(application)g(programmers)d(m)m(ust)h(b)s(e)0 -3962 y(careful)24 b(to)h(call)g(the)f(CFITSIO)f(routines)g -(appropriately)i(and)e(in)h(an)f(e\016cien)m(t)j(sequence;)h -(inappropriate)c(usage)0 4075 y(of)31 b(CFITSIO)d(routines)j(can)f -(greatly)i(slo)m(w)f(do)m(wn)f(the)h(execution)g(sp)s(eed)f(of)g(a)h -(program.)0 4235 y(The)f(maxim)m(um)h(p)s(ossible)f(I/O)h(sp)s(eed)f -(of)h(CFITSIO)e(dep)s(ends)g(of)i(course)g(on)f(the)h(t)m(yp)s(e)g(of)g -(computer)g(system)0 4348 y(that)j(it)g(is)g(running)d(on.)50 -b(T)-8 b(o)34 b(get)h(a)f(general)g(idea)g(of)g(what)f(data)i(I/O)e(sp) -s(eeds)f(are)i(p)s(ossible)f(on)h(a)g(particular)0 4461 -y(mac)m(hine,)j(build)e(the)g(sp)s(eed.c)g(program)g(that)h(is)g -(distributed)e(with)h(CFITSIO)f(\(t)m(yp)s(e)i('mak)m(e)g(sp)s(eed')f -(in)g(the)0 4574 y(CFITSIO)e(directory\).)54 b(This)33 -b(diagnostic)j(program)e(measures)h(the)f(sp)s(eed)g(of)g(writing)h -(and)f(reading)g(bac)m(k)i(a)0 4687 y(test)31 b(FITS)f(image,)i(a)f -(binary)e(table,)j(and)d(an)i(ASCI)s(I)e(table.)0 4847 -y(The)k(follo)m(wing)h(2)g(sections)g(pro)m(vide)g(some)f(bac)m -(kground)g(on)h(ho)m(w)f(CFITSIO)f(in)m(ternally)i(manages)g(the)f -(data)0 4960 y(I/O)g(and)g(describ)s(es)f(some)i(strategies)h(that)f -(ma)m(y)g(b)s(e)e(used)h(to)h(optimize)g(the)g(pro)s(cessing)f(sp)s -(eed)f(of)h(soft)m(w)m(are)0 5073 y(that)e(uses)f(CFITSIO.)0 -5379 y Fb(4.13.1)113 b(Bac)m(kground)38 b(Information:)50 -b(Ho)m(w)37 b(CFITSIO)h(Manages)h(Data)f(I/O)0 5601 y -Fi(Man)m(y)22 b(CFITSIO)e(op)s(erations)i(in)m(v)m(olv)m(e)i -(transferring)d(only)h(a)g(small)g(n)m(um)m(b)s(er)f(of)h(b)m(ytes)g -(to)g(or)g(from)f(the)h(FITS)f(\014le)0 5714 y(\(e.g,)31 -b(reading)e(a)g(k)m(eyw)m(ord,)h(or)f(writing)g(a)g(ro)m(w)g(in)f(a)h -(table\);)i(it)f(w)m(ould)e(b)s(e)g(v)m(ery)i(ine\016cien)m(t)g(to)f -(ph)m(ysically)h(read)p eop end -%%Page: 25 31 -TeXDict begin 25 30 bop 0 299 a Fg(4.13.)73 b(OPTIMIZING)29 -b(CODE)h(F)m(OR)h(MAXIMUM)g(PR)m(OCESSING)f(SPEED)971 -b Fi(25)0 555 y(or)32 b(write)h(suc)m(h)f(small)g(blo)s(c)m(ks)h(of)f -(data)h(directly)g(in)f(the)g(FITS)g(\014le)g(on)g(disk,)h(therefore)f -(CFITSIO)f(main)m(tains)0 668 y(a)38 b(set)g(of)g(in)m(ternal)h -(Input{Output)c(\(IO\))j(bu\013ers)f(in)g(RAM)h(memory)g(that)g(eac)m -(h)h(con)m(tain)g(one)f(FITS)f(blo)s(c)m(k)0 781 y(\(2880)27 -b(b)m(ytes\))f(of)f(data.)40 b(Whenev)m(er)25 b(CFITSIO)f(needs)g(to)i -(access)g(data)g(in)f(the)g(FITS)f(\014le,)j(it)e(\014rst)f(transfers)h -(the)0 894 y(FITS)30 b(blo)s(c)m(k)h(con)m(taining)h(those)f(b)m(ytes)g -(in)m(to)g(one)g(of)f(the)h(IO)f(bu\013ers)f(in)h(memory)-8 -b(.)42 b(The)30 b(next)g(time)h(CFITSIO)0 1007 y(needs)36 -b(to)g(access)i(b)m(ytes)e(in)g(the)g(same)h(blo)s(c)m(k)f(it)h(can)f -(then)g(go)h(to)f(the)h(fast)f(IO)f(bu\013er)g(rather)h(than)g(using)g -(a)0 1120 y(m)m(uc)m(h)c(slo)m(w)m(er)i(system)e(disk)g(access)h -(routine.)46 b(The)32 b(n)m(um)m(b)s(er)f(of)h(a)m(v)-5 -b(ailable)35 b(IO)d(bu\013ers)f(is)h(determined)g(b)m(y)g(the)0 -1233 y(NIOBUF)f(parameter)g(\(in)f(\014tsio2.h\))h(and)f(is)h(curren)m -(tly)f(set)h(to)g(40.)0 1393 y(Whenev)m(er)24 b(CFITSIO)f(reads)g(or)h -(writes)g(data)g(it)h(\014rst)e(c)m(hec)m(ks)i(to)g(see)f(if)g(that)g -(blo)s(c)m(k)h(of)f(the)g(FITS)f(\014le)g(is)h(already)0 -1506 y(loaded)33 b(in)m(to)g(one)f(of)g(the)g(IO)g(bu\013ers.)44 -b(If)32 b(not,)h(and)e(if)h(there)g(is)g(an)g(empt)m(y)h(IO)e(bu\013er) -g(a)m(v)-5 b(ailable,)35 b(then)d(it)h(will)0 1619 y(load)g(that)h(blo) -s(c)m(k)f(in)m(to)g(the)g(IO)g(bu\013er)e(\(when)h(reading)h(a)g(FITS)f -(\014le\))h(or)g(will)g(initialize)i(a)e(new)f(blo)s(c)m(k)i(\(when)0 -1732 y(writing)j(to)h(a)g(FITS)f(\014le\).)62 b(If)37 -b(all)h(the)g(IO)e(bu\013ers)h(are)g(already)h(full,)h(it)f(m)m(ust)g -(decide)f(whic)m(h)g(one)h(to)g(reuse)0 1844 y(\(generally)c(the)f(one) -g(that)g(has)f(b)s(een)g(accessed)i(least)f(recen)m(tly\),)i(and)d -(\015ush)f(the)i(con)m(ten)m(ts)h(bac)m(k)g(to)f(disk)f(if)g(it)0 -1957 y(has)e(b)s(een)g(mo)s(di\014ed)f(b)s(efore)h(loading)h(the)g(new) -f(blo)s(c)m(k.)0 2118 y(The)g(one)g(ma)5 b(jor)30 b(exception)i(to)f -(the)f(ab)s(o)m(v)m(e)h(pro)s(cess)f(o)s(ccurs)g(whenev)m(er)g(a)g -(large)i(con)m(tiguous)f(set)g(of)f(b)m(ytes)h(are)0 -2230 y(accessed,)37 b(as)d(migh)m(t)i(o)s(ccur)e(when)f(reading)i(or)f -(writing)g(a)h(FITS)f(image.)54 b(In)34 b(this)g(case)h(CFITSIO)e(b)m -(ypasses)0 2343 y(the)i(in)m(ternal)h(IO)f(bu\013ers)f(and)g(simply)h -(reads)g(or)g(writes)h(the)f(desired)g(b)m(ytes)g(directly)h(in)f(the)g -(disk)g(\014le)g(with)0 2456 y(a)i(single)g(call)g(to)g(a)g(lo)m(w-lev) -m(el)i(\014le)d(read)g(or)h(write)f(routine.)58 b(The)36 -b(minim)m(um)g(threshold)f(for)h(the)h(n)m(um)m(b)s(er)e(of)0 -2569 y(b)m(ytes)27 b(to)g(read)f(or)g(write)g(this)g(w)m(a)m(y)i(is)e -(set)g(b)m(y)h(the)f(MINDIRECT)g(parameter)g(and)g(is)g(curren)m(tly)g -(set)h(to)g(3)g(FITS)0 2682 y(blo)s(c)m(ks)36 b(=)g(8640)i(b)m(ytes.)58 -b(This)35 b(is)h(the)g(most)g(e\016cien)m(t)i(w)m(a)m(y)f(to)g(read)e -(or)h(write)h(large)g(c)m(h)m(unks)e(of)h(data.)59 b(Note)0 -2795 y(that)34 b(this)f(fast)h(direct)g(IO)f(pro)s(cess)f(is)i(not)f -(applicable)i(when)d(accessing)j(columns)e(of)h(data)g(in)f(a)g(FITS)g -(table)0 2908 y(b)s(ecause)f(the)h(b)m(ytes)g(are)g(generally)g(not)g -(con)m(tiguous)g(since)g(they)g(are)f(in)m(terlea)m(v)m(ed)j(b)m(y)e -(the)f(other)h(columns)f(of)0 3021 y(data)i(in)e(the)h(table.)49 -b(This)33 b(explains)g(wh)m(y)f(the)h(sp)s(eed)f(for)h(accessing)h -(FITS)e(tables)i(is)f(generally)h(slo)m(w)m(er)g(than)0 -3134 y(accessing)e(FITS)e(images.)0 3294 y(Giv)m(en)i(this)g(bac)m -(kground)f(information,)h(the)g(general)g(strategy)h(for)e(e\016cien)m -(tly)i(accessing)g(FITS)e(\014les)g(should)0 3407 y(no)m(w)36 -b(b)s(e)g(apparen)m(t:)52 b(when)35 b(dealing)i(with)f(FITS)g(images,)j -(read)d(or)g(write)g(large)i(c)m(h)m(unks)e(of)g(data)h(at)g(a)f(time)0 -3520 y(so)30 b(that)h(the)f(direct)h(IO)e(mec)m(hanism)h(will)h(b)s(e)e -(in)m(v)m(ok)m(ed;)j(when)d(accessing)j(FITS)d(headers)h(or)g(FITS)f -(tables,)i(on)0 3633 y(the)k(other)g(hand,)g(once)g(a)g(particular)h -(FITS)e(blo)s(c)m(k)h(has)f(b)s(een)g(loading)i(in)m(to)g(one)f(of)g -(the)f(IO)h(bu\013ers,)g(try)f(to)0 3745 y(access)39 -b(all)f(the)f(needed)g(information)h(in)f(that)h(blo)s(c)m(k)g(b)s -(efore)f(it)h(gets)g(\015ushed)d(out)j(of)g(the)f(IO)g(bu\013er.)60 -b(It)38 b(is)0 3858 y(imp)s(ortan)m(t)31 b(to)h(a)m(v)m(oid)g(the)f -(situation)h(where)f(the)g(same)g(FITS)f(blo)s(c)m(k)i(is)f(b)s(eing)f -(read)h(then)g(\015ushed)e(from)h(a)h(IO)0 3971 y(bu\013er)e(m)m -(ultiple)i(times.)0 4131 y(The)f(follo)m(wing)i(section)f(giv)m(es)h -(more)e(sp)s(eci\014c)h(suggestions)g(for)f(optimizing)i(the)e(use)g -(of)h(CFITSIO.)0 4430 y Fb(4.13.2)113 b(Optimization)38 -b(Strategies)0 4650 y Fi(1.)43 b(Because)32 b(the)f(data)g(in)g(FITS)f -(\014les)h(is)g(alw)m(a)m(ys)h(stored)f(in)g("big-endian")h(b)m(yte)f -(order,)g(where)f(the)h(\014rst)f(b)m(yte)0 4763 y(of)g(n)m(umeric)h(v) --5 b(alues)30 b(con)m(tains)i(the)e(most)h(signi\014can)m(t)g(bits)f -(and)g(the)g(last)i(b)m(yte)e(con)m(tains)i(the)e(least)i(signi\014can) -m(t)0 4876 y(bits,)e(CFITSIO)f(m)m(ust)h(sw)m(ap)g(the)g(order)f(of)h -(the)h(b)m(ytes)f(when)f(reading)h(or)g(writing)g(FITS)g(\014les)g -(when)f(running)0 4989 y(on)k(little-endian)i(mac)m(hines)f(\(e.g.,)i -(Lin)m(ux)d(and)g(Microsoft)i(Windo)m(ws)e(op)s(erating)h(systems)g -(running)d(on)j(PCs)0 5102 y(with)c(x86)h(CPUs\).)0 5262 -y(On)i(fairly)h(new)f(CPUs)g(that)i(supp)s(ort)d("SSSE3")h(mac)m(hine)h -(instructions)g(\(e.g.,)i(starting)f(with)e(In)m(tel)i(Core)f(2)0 -5375 y(CPUs)21 b(in)h(2007,)j(and)d(in)f(AMD)i(CPUs)e(b)s(eginning)g -(in)h(2011\))i(signi\014can)m(tly)f(faster)f(4-b)m(yte)h(and)e(8-b)m -(yte)i(sw)m(apping)0 5488 y(algorithms)k(are)g(a)m(v)-5 -b(ailable.)42 b(These)26 b(faster)h(b)m(yte)g(sw)m(apping)f(functions)g -(are)h(not)g(used)e(b)m(y)i(default)f(in)g(CFITSIO)0 -5601 y(\(b)s(ecause)c(of)f(the)h(p)s(oten)m(tial)g(co)s(de)g(p)s -(ortablilit)m(y)g(issues\),)i(but)c(users)h(can)g(enable)h(them)f(on)h -(supp)s(orted)d(platforms)0 5714 y(b)m(y)38 b(adding)f(the)h -(appropriate)f(compiler)i(\015ags)e(\(-mssse3)i(with)e(gcc)i(or)f(icc)g -(on)g(lin)m(ux\))g(when)e(compiling)j(the)p eop end -%%Page: 26 32 -TeXDict begin 26 31 bop 0 299 a Fi(26)1277 b Fg(CHAPTER)29 -b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 -555 y Fi(sw)m(appro)s(c.c)f(source)g(\014le,)g(whic)m(h)g(will)g(allo)m -(w)i(the)e(compiler)g(to)h(generate)h(co)s(de)e(using)f(the)h(SSSE3)f -(instruction)0 668 y(set.)41 b(A)28 b(con)m(v)m(enien)m(t)i(w)m(a)m(y)f -(to)g(do)g(this)f(is)g(to)h(con\014gure)f(the)g(CFITSIO)f(library)h -(with)g(the)g(follo)m(wing)i(command:)95 894 y Fe(>)96 -b(./configure)44 b(--enable-ssse3)0 1121 y Fi(Note,)37 -b(ho)m(w)m(ev)m(er,)h(that)d(a)g(binary)f(executable)j(\014le)e(that)g -(is)g(created)h(using)e(these)h(faster)g(functions)g(will)g(only)0 -1233 y(run)c(on)h(mac)m(hines)g(that)h(supp)s(ort)d(the)i(SSSE3)f(mac)m -(hine)i(instructions.)45 b(It)33 b(will)f(crash)g(on)g(mac)m(hines)g -(that)h(do)0 1346 y(not)e(supp)s(ort)d(them.)0 1507 y(F)-8 -b(or)36 b(faster)f(2-b)m(yte)i(sw)m(aps)e(on)g(virtually)g(all)h -(x86-64)h(CPUs)e(\(ev)m(en)h(those)g(that)f(do)g(not)h(supp)s(ort)d -(SSSE3\),)j(a)0 1619 y(v)-5 b(arian)m(t)26 b(using)e(only)g(SSE2)g -(instructions)h(exists.)39 b(SSE2)24 b(is)h(enabled)f(b)m(y)h(default)g -(on)f(x86)p 3066 1619 28 4 v 34 w(64)h(CPUs)f(with)h(64-bit)0 -1732 y(op)s(erating)30 b(systems)f(\(and)g(is)g(also)i(automatically)h -(enabled)d(b)m(y)g(the)g({enable-ssse3)i(\015ag\).)41 -b(When)30 b(running)d(on)0 1845 y(x86)p 143 1845 V 34 -w(64)k(CPUs)g(with)f(32-bit)i(op)s(erating)g(systems,)f(these)g(faster) -h(2-b)m(yte)g(sw)m(apping)f(algorithms)g(are)h(not)f(used)0 -1958 y(b)m(y)f(default)h(in)f(CFITSIO,)f(but)h(can)g(b)s(e)g(enabled)g -(explicitly)i(with:)0 2184 y Fe(./configure)45 b(--enable-sse2)0 -2411 y Fi(Preliminary)f(testing)h(indicates)g(that)g(these)f(SSSE3)f -(and)g(SSE2)g(based)h(b)m(yte-sw)m(apping)h(algorithms)g(can)0 -2524 y(b)s(o)s(ost)31 b(the)h(CFITSIO)e(p)s(erformance)h(when)f -(reading)i(or)f(writing)h(FITS)f(images)h(b)m(y)g(20\045)g(-)g(30\045)g -(or)f(more.)45 b(It)0 2636 y(is)36 b(imp)s(ortan)m(t)g(to)g(note,)i(ho) -m(w)m(ev)m(er,)h(that)d(compiler)g(optimization)i(m)m(ust)e(b)s(e)f -(turned)f(on)i(\(e.g.,)j(b)m(y)d(using)f(the)0 2749 y(-O1)f(or)g(-O2)g -(\015ags)g(in)g(gcc\))h(when)e(building)g(programs)h(that)g(use)g -(these)g(fast)g(b)m(yte-sw)m(apping)h(algorithms)f(in)0 -2862 y(order)d(to)h(reap)f(the)h(full)f(b)s(ene\014t)g(of)g(the)h -(SSSE3)e(and)h(SSE2)g(instructions;)h(without)f(optimization,)j(the)e -(co)s(de)0 2975 y(ma)m(y)f(actually)h(run)d(slo)m(w)m(er)i(than)f(when) -g(using)g(more)g(traditional)i(b)m(yte-sw)m(apping)f(tec)m(hniques.)0 -3135 y(2.)54 b(When)34 b(dealing)h(with)g(a)g(FITS)e(primary)h(arra)m -(y)h(or)g(IMA)m(GE)g(extension,)i(it)e(is)f(more)h(e\016cien)m(t)h(to)f -(read)g(or)0 3248 y(write)c(large)g(c)m(h)m(unks)f(of)g(the)h(image)g -(at)h(a)e(time)h(\(at)h(least)f(3)g(FITS)f(blo)s(c)m(ks)g(=)g(8640)i(b) -m(ytes\))f(so)g(that)g(the)f(direct)0 3361 y(IO)j(mec)m(hanism)h(will)f -(b)s(e)g(used)g(as)g(describ)s(ed)g(in)g(the)g(previous)g(section.)51 -b(Smaller)34 b(c)m(h)m(unks)f(of)g(data)h(are)g(read)0 -3474 y(or)d(written)g(via)h(the)f(IO)f(bu\013ers,)g(whic)m(h)h(is)g -(somewhat)g(less)g(e\016cien)m(t)i(b)s(ecause)e(of)g(the)g(extra)h(cop) -m(y)f(op)s(eration)0 3587 y(and)26 b(additional)h(b)s(o)s(okk)m(eeping) -g(steps)g(that)g(are)g(required.)39 b(In)26 b(principle)g(it)h(is)g -(more)f(e\016cien)m(t)i(to)g(read)e(or)h(write)0 3700 -y(as)i(big)g(an)g(arra)m(y)h(of)f(image)h(pixels)f(at)h(one)f(time)g -(as)h(p)s(ossible,)f(ho)m(w)m(ev)m(er,)h(if)f(the)h(arra)m(y)f(b)s -(ecomes)g(so)g(large)h(that)0 3813 y(the)i(op)s(erating)g(system)f -(cannot)h(store)g(it)g(all)h(in)e(RAM,)h(then)f(the)h(p)s(erformance)f -(ma)m(y)h(b)s(e)f(degraded)g(b)s(ecause)0 3926 y(of)g(the)f(increased)h -(sw)m(apping)f(of)g(virtual)h(memory)f(to)h(disk.)0 4086 -y(3.)51 b(When)33 b(dealing)i(with)e(FITS)g(tables,)j(the)e(most)g(imp) -s(ortan)m(t)g(e\016ciency)g(factor)h(in)e(the)h(soft)m(w)m(are)h -(design)f(is)0 4199 y(to)j(read)f(or)g(write)g(the)g(data)h(in)f(the)g -(FITS)g(\014le)g(in)g(a)g(single)h(pass)f(through)f(the)h(\014le.)58 -b(An)36 b(example)h(of)f(p)s(o)s(or)0 4312 y(program)g(design)h(w)m -(ould)f(b)s(e)g(to)h(read)g(a)f(large,)k(3-column)d(table)g(b)m(y)g -(sequen)m(tially)h(reading)f(the)f(en)m(tire)i(\014rst)0 -4425 y(column,)25 b(then)f(going)h(bac)m(k)f(to)h(read)e(the)h(2nd)g -(column,)h(and)e(\014nally)h(the)g(3rd)f(column;)j(this)e(ob)m(viously) -g(requires)0 4538 y(3)h(passes)f(through)f(the)i(\014le)f(whic)m(h)g -(could)h(triple)f(the)h(execution)g(time)g(of)g(an)f(I/O)g(limited)h -(program.)38 b(F)-8 b(or)25 b(small)0 4650 y(tables)31 -b(this)f(is)h(not)f(imp)s(ortan)m(t,)h(but)f(when)f(reading)h(m)m -(ulti-megab)m(yte)j(sized)e(tables)g(these)g(ine\016ciencies)h(can)0 -4763 y(b)s(ecome)d(signi\014can)m(t.)41 b(The)28 b(more)h(e\016cien)m -(t)h(pro)s(cedure)d(in)i(this)f(case)i(is)e(to)i(read)e(or)h(write)g -(only)f(as)h(man)m(y)g(ro)m(ws)0 4876 y(of)g(the)g(table)h(as)f(will)h -(\014t)e(in)m(to)i(the)g(a)m(v)-5 b(ailable)31 b(in)m(ternal)f(I/O)f -(bu\013ers,)f(then)h(access)h(all)g(the)f(necessary)g(columns)0 -4989 y(of)i(data)h(within)e(that)i(range)f(of)g(ro)m(ws.)43 -b(Then)29 b(after)j(the)f(program)g(is)g(completely)h(\014nished)e -(with)g(the)i(data)f(in)0 5102 y(those)i(ro)m(ws)e(it)i(can)f(mo)m(v)m -(e)i(on)e(to)g(the)h(next)f(range)g(of)g(ro)m(ws)g(that)h(will)f(\014t) -g(in)g(the)g(bu\013ers,)f(con)m(tin)m(uing)i(in)f(this)0 -5215 y(w)m(a)m(y)c(un)m(til)f(the)f(en)m(tire)i(\014le)f(has)f(b)s(een) -g(pro)s(cessed.)39 b(By)27 b(using)f(this)h(pro)s(cedure)e(of)i -(accessing)h(all)g(the)e(columns)h(of)0 5328 y(a)j(table)g(in)f -(parallel)h(rather)f(than)g(sequen)m(tially)-8 b(,)32 -b(eac)m(h)e(blo)s(c)m(k)g(of)g(the)f(FITS)g(\014le)g(will)g(only)h(b)s -(e)e(read)i(or)f(written)0 5441 y(once.)0 5601 y(The)g(optimal)h(n)m -(um)m(b)s(er)e(of)i(ro)m(ws)f(to)i(read)e(or)g(write)h(at)g(one)g(time) -g(in)f(a)h(giv)m(en)g(table)h(dep)s(ends)c(on)j(the)f(width)g(of)0 -5714 y(the)j(table)h(ro)m(w,)g(on)f(the)g(n)m(um)m(b)s(er)f(of)h(I/O)g -(bu\013ers)f(that)i(ha)m(v)m(e)g(b)s(een)e(allo)s(cated)j(in)e(FITSIO,) -f(and)h(also)h(on)f(the)p eop end -%%Page: 27 33 -TeXDict begin 27 32 bop 0 299 a Fg(4.13.)73 b(OPTIMIZING)29 -b(CODE)h(F)m(OR)h(MAXIMUM)g(PR)m(OCESSING)f(SPEED)971 -b Fi(27)0 555 y(n)m(um)m(b)s(er)27 b(of)i(other)f(FITS)g(\014les)g -(that)h(are)g(op)s(en)f(at)h(the)g(same)g(time)g(\(since)g(one)g(I/O)f -(bu\013er)f(is)i(alw)m(a)m(ys)h(reserv)m(ed)0 668 y(for)k(eac)m(h)h(op) -s(en)f(FITS)f(\014le\).)53 b(F)-8 b(ortunately)g(,)37 -b(a)e(FITSIO)e(routine)h(is)h(a)m(v)-5 b(ailable)36 b(that)f(will)f -(return)g(the)g(optimal)0 781 y(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(for)g -(a)g(giv)m(en)g(table:)49 b(call)35 b(ftgrsz\(unit,)g(nro)m(ws,)f -(status\).)52 b(It)34 b(is)g(not)g(critical)h(to)g(use)e(exactly)0 -894 y(the)f(v)-5 b(alue)32 b(of)f(nro)m(ws)g(returned)g(b)m(y)g(this)g -(routine,)h(as)g(long)g(as)g(one)g(do)s(es)f(not)h(exceed)g(it.)45 -b(Using)32 b(a)g(v)m(ery)f(small)0 1007 y(v)-5 b(alue)32 -b(ho)m(w)m(ev)m(er)i(can)e(also)h(lead)f(to)h(p)s(o)s(or)e(p)s -(erformance)g(b)s(ecause)h(of)g(the)g(o)m(v)m(erhead)h(from)f(the)g -(larger)g(n)m(um)m(b)s(er)0 1120 y(of)f(subroutine)e(calls.)0 -1280 y(The)36 b(optimal)h(n)m(um)m(b)s(er)f(of)g(ro)m(ws)h(returned)e -(b)m(y)h(ftgrsz)h(is)g(v)-5 b(alid)37 b(only)f(as)h(long)g(as)g(the)f -(application)i(program)0 1393 y(is)c(only)h(reading)g(or)f(writing)g -(data)h(in)g(the)f(sp)s(eci\014ed)g(table.)54 b(An)m(y)34 -b(other)h(calls)g(to)g(access)h(data)f(in)f(the)h(table)0 -1506 y(header)26 b(w)m(ould)f(cause)i(additional)f(blo)s(c)m(ks)h(of)f -(data)g(to)h(b)s(e)e(loaded)h(in)m(to)h(the)f(I/O)g(bu\013ers)f -(displacing)h(data)g(from)0 1619 y(the)j(original)h(table,)g(and)e -(should)f(b)s(e)h(a)m(v)m(oided)i(during)e(the)h(critical)h(p)s(erio)s -(d)e(while)g(the)h(table)h(is)e(b)s(eing)g(read)h(or)0 -1732 y(written.)0 1892 y(4.)39 b(Use)24 b(binary)f(table)h(extensions)g -(rather)f(than)h(ASCI)s(I)e(table)i(extensions)g(for)f(b)s(etter)h -(e\016ciency)h(when)d(dealing)0 2005 y(with)37 b(tabular)h(data.)62 -b(The)37 b(I/O)g(to)h(ASCI)s(I)e(tables)i(is)g(slo)m(w)m(er)g(b)s -(ecause)g(of)f(the)h(o)m(v)m(erhead)h(in)e(formatting)h(or)0 -2118 y(parsing)30 b(the)h(ASCI)s(I)f(data)h(\014elds,)g(and)f(b)s -(ecause)h(ASCI)s(I)e(tables)i(are)g(ab)s(out)g(t)m(wice)h(as)f(large)h -(as)f(binary)f(tables)0 2230 y(with)g(the)h(same)f(information)h(con)m -(ten)m(t.)0 2391 y(5.)64 b(Design)39 b(soft)m(w)m(are)g(so)g(that)f(it) -h(reads)f(the)g(FITS)f(header)h(k)m(eyw)m(ords)g(in)g(the)g(same)h -(order)e(in)h(whic)m(h)g(they)0 2503 y(o)s(ccur)33 b(in)g(the)g -(\014le.)49 b(When)32 b(reading)i(k)m(eyw)m(ords,)g(FITSIO)e(searc)m -(hes)i(forw)m(ard)e(starting)i(from)e(the)i(p)s(osition)f(of)0 -2616 y(the)c(last)i(k)m(eyw)m(ord)e(that)h(w)m(as)g(read.)40 -b(If)29 b(it)g(reac)m(hes)i(the)e(end)g(of)g(the)h(header)f(without)g -(\014nding)f(the)h(k)m(eyw)m(ord,)h(it)0 2729 y(then)j(go)s(es)h(bac)m -(k)g(to)h(the)e(start)h(of)g(the)g(header)f(and)g(con)m(tin)m(ues)h -(the)g(searc)m(h)g(do)m(wn)f(to)h(the)g(p)s(osition)f(where)g(it)0 -2842 y(started.)41 b(In)30 b(practice,)i(as)e(long)h(as)g(the)f(en)m -(tire)i(FITS)d(header)h(can)h(\014t)f(at)h(one)g(time)g(in)f(the)g(a)m -(v)-5 b(ailable)33 b(in)m(ternal)0 2955 y(I/O)g(bu\013ers,)h(then)f -(the)h(header)f(k)m(eyw)m(ord)h(access)h(will)e(b)s(e)g(v)m(ery)h(fast) -g(and)f(it)h(mak)m(es)g(little)h(di\013erence)f(whic)m(h)0 -3068 y(order)c(they)g(are)h(accessed.)0 3228 y(6.)40 -b(Av)m(oid)29 b(the)e(use)h(of)f(scaling)i(\(b)m(y)f(using)f(the)h -(BSCALE)e(and)h(BZER)m(O)h(or)f(TSCAL)g(and)g(TZER)m(O)f(k)m(eyw)m -(ords\))0 3341 y(in)35 b(FITS)f(\014les)g(since)i(the)f(scaling)h(op)s -(erations)f(add)f(to)i(the)f(pro)s(cessing)f(time)i(needed)e(to)i(read) -f(or)g(write)g(the)0 3454 y(data.)60 b(In)36 b(some)i(cases)f(it)g(ma)m -(y)h(b)s(e)e(more)h(e\016cien)m(t)h(to)f(temp)s(orarily)g(turn)f(o\013) -h(the)g(scaling)h(\(using)e(ftpscl)h(or)0 3567 y(fttscl\))32 -b(and)d(then)h(read)h(or)f(write)h(the)f(ra)m(w)h(unscaled)f(v)-5 -b(alues)31 b(in)f(the)g(FITS)g(\014le.)0 3727 y(7.)40 -b(Av)m(oid)27 b(using)g(the)g('implicit)h(datat)m(yp)s(e)f(con)m(v)m -(ersion')h(capabilit)m(y)h(in)d(FITSIO.)g(F)-8 b(or)28 -b(instance,)g(when)e(reading)0 3840 y(a)f(FITS)e(image)j(with)e(BITPIX) -g(=)g(-32)i(\(32-bit)g(\015oating)f(p)s(oin)m(t)f(pixels\),)j(read)d -(the)h(data)g(in)m(to)g(a)g(single)g(precision)0 3953 -y(\015oating)e(p)s(oin)m(t)e(data)i(arra)m(y)f(in)g(the)g(program.)37 -b(F)-8 b(orcing)23 b(FITSIO)e(to)h(con)m(v)m(ert)i(the)e(data)g(to)h(a) -f(di\013eren)m(t)g(datat)m(yp)s(e)0 4066 y(can)31 b(signi\014can)m(tly) -g(slo)m(w)g(the)g(program.)0 4226 y(8.)57 b(Where)36 -b(feasible,)i(design)e(FITS)f(binary)g(tables)h(using)f(v)m(ector)j -(column)d(elemen)m(ts)i(so)f(that)g(the)g(data)h(are)0 -4339 y(written)30 b(as)g(a)g(con)m(tiguous)h(set)f(of)g(b)m(ytes,)g -(rather)g(than)f(as)h(single)g(elemen)m(ts)h(in)f(m)m(ultiple)g(ro)m -(ws.)41 b(F)-8 b(or)30 b(example,)0 4452 y(it)36 b(is)g(faster)g(to)g -(access)h(the)f(data)h(in)e(a)h(table)h(that)f(con)m(tains)h(a)f -(single)g(ro)m(w)g(and)f(2)h(columns)f(with)h(TF)m(ORM)0 -4565 y(k)m(eyw)m(ords)d(equal)h(to)g('10000E')h(and)e('10000J',)j(than) -d(it)g(is)g(to)h(access)g(the)g(same)f(amoun)m(t)h(of)f(data)h(in)f(a)g -(table)0 4678 y(with)40 b(10000)j(ro)m(ws)d(whic)m(h)h(has)f(columns)g -(with)g(the)h(TF)m(ORM)g(k)m(eyw)m(ords)g(equal)g(to)g('1E')h(and)e -('1J'.)h(In)f(the)0 4791 y(former)27 b(case)i(the)f(10000)i(\015oating) -f(p)s(oin)m(t)f(v)-5 b(alues)28 b(in)g(the)g(\014rst)f(column)h(are)g -(all)h(written)f(in)f(a)h(con)m(tiguous)h(blo)s(c)m(k)0 -4903 y(of)d(the)f(\014le)h(whic)m(h)f(can)h(b)s(e)f(read)g(or)g -(written)h(quic)m(kly)-8 b(,)28 b(whereas)d(in)g(the)h(second)f(case)i -(eac)m(h)g(\015oating)f(p)s(oin)m(t)f(v)-5 b(alue)0 5016 -y(in)34 b(the)g(\014rst)f(column)g(is)h(in)m(terlea)m(v)m(ed)j(with)c -(the)h(in)m(teger)i(v)-5 b(alue)34 b(in)g(the)g(second)g(column)f(of)h -(the)g(same)h(ro)m(w)f(so)0 5129 y(CFITSIO)29 b(has)h(to)h(explicitly)h -(mo)m(v)m(e)g(to)f(the)g(p)s(osition)f(of)h(eac)m(h)g(elemen)m(t)h(to)f -(b)s(e)f(read)g(or)g(written.)0 5289 y(9.)52 b(Av)m(oid)35 -b(the)g(use)e(of)i(v)-5 b(ariable)34 b(length)h(v)m(ector)h(columns)d -(in)h(binary)g(tables,)i(since)e(an)m(y)h(reading)f(or)g(writing)0 -5402 y(of)f(these)g(data)g(requires)f(that)h(CFITSIO)f(\014rst)f(lo)s -(ok)j(up)d(or)i(compute)g(the)f(starting)i(address)e(of)g(eac)m(h)i(ro) -m(w)f(of)0 5515 y(data)e(in)f(the)h(heap.)40 b(In)30 -b(practice,)i(this)e(is)g(probably)g(not)h(a)f(signi\014can)m(t)i -(e\016ciency)f(issue.)0 5675 y(10.)39 b(When)24 b(cop)m(ying)h(data)f -(from)f(one)i(FITS)e(table)h(to)h(another,)g(it)g(is)f(faster)g(to)g -(transfer)f(the)h(ra)m(w)g(b)m(ytes)h(instead)p eop end -%%Page: 28 34 -TeXDict begin 28 33 bop 0 299 a Fi(28)1277 b Fg(CHAPTER)29 -b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 -555 y Fi(of)26 b(reading)g(then)g(writing)g(eac)m(h)h(column)e(of)i -(the)f(table.)40 b(The)25 b(FITSIO)g(subroutines)g(FTGTBS)g(and)h -(FTPTBS)0 668 y(\(for)i(ASCI)s(I)f(tables\),)j(and)d(FTGTBB)i(and)e -(FTPTBB)i(\(for)f(binary)f(tables\))i(will)g(p)s(erform)d(lo)m(w-lev)m -(el)31 b(reads)d(or)0 781 y(writes)34 b(of)h(an)m(y)f(con)m(tiguous)i -(range)f(of)f(b)m(ytes)h(in)f(a)h(table)g(extension.)53 -b(These)34 b(routines)g(can)h(b)s(e)e(used)h(to)h(read)0 -894 y(or)29 b(write)g(a)g(whole)g(ro)m(w)f(\(or)i(m)m(ultiple)f(ro)m -(ws\))g(of)g(a)g(table)h(with)e(a)h(single)g(subroutine)f(call.)41 -b(These)29 b(routines)g(are)0 1007 y(fast)38 b(b)s(ecause)f(they)h(b)m -(ypass)f(all)h(the)g(usual)f(data)h(scaling,)j(error)c(c)m(hec)m(king)i -(and)e(mac)m(hine)h(dep)s(enden)m(t)e(data)0 1120 y(con)m(v)m(ersion)41 -b(that)g(is)e(normally)i(done)e(b)m(y)h(FITSIO,)f(and)g(they)h(allo)m -(w)h(the)f(program)g(to)h(write)f(the)g(data)g(to)0 1233 -y(the)34 b(output)g(\014le)g(in)g(exactly)i(the)e(same)h(b)m(yte)g -(order.)51 b(F)-8 b(or)35 b(these)g(same)f(reasons,)i(use)e(of)g(these) -h(routines)f(can)0 1346 y(b)s(e)f(somewhat)h(risky)f(b)s(ecause)g(no)g -(v)-5 b(alidation)35 b(or)f(mac)m(hine)g(dep)s(enden)m(t)e(con)m(v)m -(ersion)j(is)e(p)s(erformed)f(b)m(y)h(these)0 1458 y(routines.)40 -b(In)27 b(general)h(these)h(routines)e(are)h(only)g(recommended)f(for)h -(optimizing)h(critical)g(pieces)g(of)f(co)s(de)g(and)0 -1571 y(should)e(only)i(b)s(e)f(used)f(b)m(y)i(programmers)e(who)h -(thoroughly)h(understand)d(the)j(in)m(ternal)g(b)m(yte)g(structure)f -(of)h(the)0 1684 y(FITS)i(tables)h(they)f(are)h(reading)g(or)f -(writing.)0 1844 y(11.)41 b(Another)30 b(strategy)g(for)g(impro)m(ving) -f(the)h(sp)s(eed)e(of)i(writing)g(a)f(FITS)g(table,)i(similar)f(to)g -(the)f(previous)g(one,)0 1957 y(is)j(to)g(directly)h(construct)f(the)f -(en)m(tire)i(b)m(yte)f(stream)g(for)g(a)g(whole)g(table)g(ro)m(w)g -(\(or)g(m)m(ultiple)h(ro)m(ws\))f(within)f(the)0 2070 -y(application)k(program)f(and)g(then)f(write)i(it)f(to)h(the)f(FITS)f -(\014le)i(with)e(ftptbb.)51 b(This)33 b(a)m(v)m(oids)j(all)f(the)f(o)m -(v)m(erhead)0 2183 y(normally)g(presen)m(t)g(in)f(the)h(column-orien)m -(ted)h(CFITSIO)d(write)i(routines.)51 b(This)33 b(tec)m(hnique)h -(should)f(only)h(b)s(e)0 2296 y(used)26 b(for)h(critical)i -(applications,)g(b)s(ecause)d(it)i(mak)m(es)g(the)f(co)s(de)g(more)g -(di\016cult)g(to)g(understand)e(and)i(main)m(tain,)0 -2409 y(and)d(it)h(mak)m(es)h(the)f(co)s(de)g(more)f(system)h(dep)s -(enden)m(t)f(\(e.g.,)k(do)c(the)h(b)m(ytes)g(need)g(to)g(b)s(e)f(sw)m -(app)s(ed)g(b)s(efore)g(writing)0 2522 y(to)31 b(the)g(FITS)e -(\014le?\).)0 2682 y(12.)53 b(Finally)-8 b(,)37 b(external)e(factors)h -(suc)m(h)e(as)g(the)h(t)m(yp)s(e)f(of)h(magnetic)g(disk)f(con)m -(troller)i(\(SCSI)d(or)i(IDE\),)g(the)f(size)0 2795 y(of)h(the)g(disk)g -(cac)m(he,)j(the)d(a)m(v)m(erage)i(seek)f(sp)s(eed)e(of)h(the)g(disk,)h -(the)f(amoun)m(t)h(of)f(disk)f(fragmen)m(tation,)k(and)d(the)0 -2908 y(amoun)m(t)29 b(of)g(RAM)f(a)m(v)-5 b(ailable)31 -b(on)e(the)f(system)h(can)g(all)g(ha)m(v)m(e)h(a)f(signi\014can)m(t)g -(impact)h(on)e(o)m(v)m(erall)j(I/O)d(e\016ciency)-8 b(.)0 -3021 y(F)g(or)36 b(critical)h(applications,)g(a)f(system)f -(administrator)g(should)f(review)h(the)h(prop)s(osed)d(system)j(hardw)m -(are)e(to)0 3134 y(iden)m(tify)d(an)m(y)g(p)s(oten)m(tial)g(I/O)g(b)s -(ottlenec)m(ks.)p eop end -%%Page: 29 35 -TeXDict begin 29 34 bop 0 1225 a Ff(Chapter)65 b(5)0 -1687 y Fl(Basic)77 b(In)-6 b(terface)77 b(Routines)0 -2180 y Fi(This)27 b(section)h(de\014nes)f(a)h(basic)g(set)g(of)g -(subroutines)e(that)i(can)g(b)s(e)f(used)g(to)h(p)s(erform)e(the)i -(most)g(common)g(t)m(yp)s(es)0 2293 y(of)d(read)g(and)f(write)h(op)s -(erations)g(on)g(FITS)f(\014les.)39 b(New)25 b(users)f(should)g(start)h -(with)g(these)g(subroutines)f(and)g(then,)0 2406 y(as)33 -b(needed,)h(explore)f(the)h(more)f(adv)-5 b(ance)33 b(routines)g -(describ)s(ed)f(in)h(the)g(follo)m(wing)i(c)m(hapter)e(to)h(p)s(erform) -e(more)0 2518 y(complex)f(or)f(sp)s(ecialized)i(op)s(erations.)0 -2679 y(A)e(righ)m(t)g(arro)m(w)g(sym)m(b)s(ol)f(\()p -Fa(>)p Fi(\))h(is)g(used)f(to)h(separate)h(the)e(input)g(parameters)h -(from)f(the)h(output)f(parameters)h(in)0 2791 y(the)i(de\014nition)f -(of)g(eac)m(h)i(routine.)44 b(This)30 b(sym)m(b)s(ol)i(is)f(not)h -(actually)h(part)e(of)h(the)f(calling)i(sequence.)45 -b(Note)32 b(that)0 2904 y(the)f(status)h(parameter)g(is)f(b)s(oth)g(an) -g(input)f(and)h(an)g(output)g(parameter)h(and)e(m)m(ust)h(b)s(e)g -(initialized)i(=)e(0)h(prior)0 3017 y(to)f(calling)h(the)f(FITSIO)e -(subroutines.)0 3177 y(Refer)h(to)i(Chapter)d(9)i(for)f(the)h -(de\014nition)f(of)g(all)i(the)e(parameters)h(used)e(b)m(y)i(these)g -(in)m(terface)g(routines.)0 3525 y Fd(5.1)135 b(FITSIO)44 -b(Error)h(Status)h(Routines)0 3773 y Fh(1)81 b Fi(Return)24 -b(the)i(curren)m(t)f(v)m(ersion)h(n)m(um)m(b)s(er)e(of)i(the)f -(\014tsio)h(library)-8 b(.)39 b(The)25 b(v)m(ersion)h(n)m(um)m(b)s(er)e -(will)i(b)s(e)e(incremen)m(ted)227 3886 y(with)30 b(eac)m(h)i(new)e -(release)h(of)g(CFITSIO.)382 4157 y Fe(FTVERS\()46 b(>)h(version\))0 -4429 y Fh(2)81 b Fi(Return)45 b(the)i(descriptiv)m(e)g(text)g(string)g -(corresp)s(onding)e(to)i(a)g(FITSIO)e(error)h(status)h(co)s(de.)89 -b(The)46 b(30-)227 4541 y(c)m(haracter)32 b(length)f(string)f(con)m -(tains)i(a)f(brief)f(description)g(of)g(the)h(cause)g(of)f(the)h -(error.)382 4813 y Fe(FTGERR\(status,)44 b(>)j(errtext\))0 -5084 y Fh(3)81 b Fi(Return)40 b(the)h(top)g(\(oldest\))h(80-c)m -(haracter)i(error)c(message)i(from)f(the)g(in)m(ternal)g(FITSIO)f(stac) -m(k)i(of)f(error)227 5197 y(messages)29 b(and)f(shift)g(an)m(y)g -(remaining)g(messages)h(on)f(the)g(stac)m(k)i(up)d(one)h(lev)m(el.)42 -b(An)m(y)28 b(FITSIO)f(error)h(will)227 5310 y(generate)h(one)e(or)g -(more)h(messages)g(on)f(the)g(stac)m(k.)41 b(Call)28 -b(this)f(routine)g(rep)s(eatedly)g(to)h(get)h(eac)m(h)f(message)227 -5422 y(in)i(sequence.)41 b(The)30 b(error)g(stac)m(k)i(is)f(empt)m(y)f -(when)g(a)g(blank)g(string)h(is)f(returned.)382 5694 -y Fe(FTGMSG\()46 b(>)h(errmsg\))1905 5942 y Fi(29)p eop -end -%%Page: 30 36 -TeXDict begin 30 35 bop 0 299 a Fi(30)1747 b Fg(CHAPTER)30 -b(5.)111 b(BASIC)30 b(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 -555 y Fh(4)81 b Fi(The)33 b(FTPMRK)h(routine)g(puts)g(an)g(in)m -(visible)h(mark)m(er)f(on)g(the)h(CFITSIO)d(error)i(stac)m(k.)54 -b(The)33 b(FTCMRK)227 668 y(routine)41 b(can)g(then)g(b)s(e)f(used)g -(to)h(delete)h(an)m(y)f(more)g(recen)m(t)h(error)e(messages)i(on)f(the) -g(stac)m(k,)k(bac)m(k)c(to)227 781 y(the)32 b(p)s(osition)f(of)g(the)g -(mark)m(er.)43 b(This)31 b(preserv)m(es)g(an)m(y)g(older)h(error)e -(messages)i(on)f(the)h(stac)m(k.)44 b(FTCMSG)227 894 -y(simply)23 b(clears)g(the)g(en)m(tire)h(error)e(message)i(stac)m(k.)40 -b(These)23 b(routines)f(are)h(called)h(without)f(an)m(y)g(argumen)m -(ts.)382 1152 y Fe(FTPMRK)382 1265 y(FTCMRK)382 1378 -y(FTCMSG)0 1637 y Fh(5)81 b Fi(Prin)m(t)30 b(out)h(the)g(error)f -(message)i(corresp)s(onding)e(to)h(the)g(input)f(status)h(v)-5 -b(alue)31 b(and)f(all)i(the)f(error)f(messages)227 1750 -y(on)g(the)h(FITSIO)e(stac)m(k)i(to)g(the)g(sp)s(eci\014ed)e(\014le)i -(stream)f(\(stream)h(can)g(b)s(e)e(either)i(the)f(string)g('STDOUT')227 -1863 y(or)h('STDERR'\).)f(If)g(the)h(input)e(status)i(v)-5 -b(alue)31 b(=)f(0)h(then)f(this)g(routine)g(do)s(es)g(nothing.)334 -2121 y Fe(FTRPRT)46 b(\(stream,)g(>)h(status\))0 2380 -y Fh(6)81 b Fi(W)-8 b(rite)39 b(an)f(80-c)m(haracter)j(message)e(to)g -(the)f(FITSIO)f(error)h(stac)m(k.)65 b(Application)39 -b(programs)f(should)f(not)227 2493 y(normally)31 b(write)f(to)i(the)e -(stac)m(k,)i(but)e(there)g(ma)m(y)h(b)s(e)f(some)h(situations)g(where)f -(this)g(is)h(desirable.)382 2751 y Fe(FTPMSG\(errmsg\))0 -3085 y Fd(5.2)135 b(File)46 b(I/O)f(Routines)0 3325 y -Fh(1)81 b Fi(Op)s(en)34 b(an)h(existing)i(FITS)d(\014le)i(with)f -(readonly)h(or)f(readwrite)h(access.)58 b(This)34 b(routine)i(alw)m(a)m -(ys)h(op)s(ens)e(the)227 3438 y(primary)30 b(arra)m(y)i(\(the)f -(\014rst)f(HDU\))i(of)f(the)h(\014le,)f(and)f(do)s(es)h(not)g(mo)m(v)m -(e)h(to)g(a)f(follo)m(wing)i(extension,)f(if)f(one)227 -3551 y(w)m(as)c(sp)s(eci\014ed)f(as)g(part)h(of)f(the)h(\014lename.)39 -b(Use)27 b(the)g(FTNOPN)f(routine)g(to)h(automatically)j(mo)m(v)m(e)e -(to)f(the)227 3664 y(extension.)44 b(This)31 b(routine)g(will)h(also)g -(op)s(en)f(IRAF)g(images)i(\(.imh)e(format)h(\014les\))g(and)e(ra)m(w)i -(binary)e(data)227 3776 y(arra)m(ys)e(with)f(READONL)-8 -b(Y)28 b(access)h(b)m(y)e(\014rst)g(con)m(v)m(erting)i(them)e(on)g(the) -h(\015y)f(in)m(to)h(virtual)g(FITS)f(images.)227 3889 -y(See)43 b(the)g(`Extended)f(File)i(Name)f(Syn)m(tax')g(c)m(hapter)g -(for)f(more)h(details.)78 b(The)42 b(FTDK)m(OPN)h(routine)227 -4002 y(simply)37 b(op)s(ens)g(the)h(sp)s(eci\014ed)f(\014le)h(without)f -(trying)h(to)g(in)m(terpret)g(the)g(\014lename)g(using)f(the)h -(extended)227 4115 y(\014lename)31 b(syn)m(tax.)382 4374 -y Fe(FTOPEN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b -(blocksize,status\))382 4487 y(FTDKOPN\(unit,filename,rw)o(mod)o(e,)42 -b(>)47 b(blocksize,status\))0 4745 y Fh(2)81 b Fi(Op)s(en)24 -b(an)i(existing)h(FITS)e(\014le)h(with)f(readonly)h(or)g(readwrite)g -(access)h(and)f(mo)m(v)m(e)h(to)f(a)h(follo)m(wing)g(extension,)227 -4858 y(if)38 b(one)g(w)m(as)g(sp)s(eci\014ed)g(as)g(part)f(of)h(the)h -(\014lename.)63 b(\(e.g.,)42 b('\014lename.\014ts+2')c(or)g -('\014lename.\014ts[2]')i(will)227 4971 y(mo)m(v)m(e)e(to)g(the)e(3rd)g -(HDU)i(in)e(the)h(\014le\).)60 b(Note)37 b(that)h(this)e(routine)h -(di\013ers)f(from)g(FTOPEN)g(in)g(that)h(it)227 5084 -y(do)s(es)30 b(not)h(ha)m(v)m(e)h(the)e(redundan)m(t)f(blo)s(c)m(ksize) -j(argumen)m(t.)382 5342 y Fe(FTNOPN\(unit,filename,rwm)o(ode)o(,)42 -b(>)47 b(status\))0 5601 y Fh(3)81 b Fi(Op)s(en)31 b(an)h(existing)h -(FITS)f(\014le)g(with)g(readonly)h(or)f(readwrite)h(access)g(and)f -(then)g(mo)m(v)m(e)i(to)f(the)g(\014rst)e(HDU)227 5714 -y(con)m(taining)c(signi\014can)m(t)g(data,)g(if)e(a\))i(an)e(HDU)h -(name)g(or)f(n)m(um)m(b)s(er)f(to)i(op)s(en)f(w)m(as)h(not)g -(explicitly)h(sp)s(eci\014ed)p eop end -%%Page: 31 37 -TeXDict begin 31 36 bop 0 299 a Fg(5.2.)72 b(FILE)30 -b(I/O)h(R)m(OUTINES)2693 b Fi(31)227 555 y(as)31 b(part)g(of)g(the)g -(\014lename,)h(and)e(b\))h(if)g(the)g(FITS)f(\014le)h(con)m(tains)h(a)g -(n)m(ull)e(primary)g(arra)m(y)i(\(i.e.,)h(NAXIS)d(=)227 -668 y(0\).)41 b(In)26 b(this)i(case,)h(it)f(will)g(lo)s(ok)g(for)f(the) -h(\014rst)e(IMA)m(GE)j(HDU)f(with)f(NAXIS)g(>)h(0,)g(or)g(the)f -(\014rst)g(table)h(that)227 781 y(do)s(es)g(not)g(con)m(tain)g(the)g -(strings)g(`GTI')g(\(Go)s(o)s(d)f(Time)h(In)m(terv)-5 -b(al\))29 b(or)f(`OBST)-8 b(ABLE')28 b(in)f(the)h(EXTNAME)227 -894 y(k)m(eyw)m(ord)37 b(v)-5 b(alue.)61 b(FTTOPN)36 -b(is)g(similar,)j(except)f(it)f(will)g(mo)m(v)m(e)i(to)e(the)g(\014rst) -f(signi\014can)m(t)i(table)f(HDU)227 1007 y(\(skipping)26 -b(o)m(v)m(er)g(an)m(y)g(image)h(HDUs\))g(in)e(the)h(\014le)g(if)f(a)h -(sp)s(eci\014c)g(HDU)g(name)g(or)g(n)m(um)m(b)s(er)e(is)i(not)f(sp)s -(eci\014ed.)227 1120 y(FTIOPN)30 b(will)h(mo)m(v)m(e)h(to)f(the)f -(\014rst)g(non-n)m(ull)g(image)i(HDU,)f(skipping)f(o)m(v)m(er)h(an)m(y) -g(tables.)382 1376 y Fe(FTDOPN\(unit,filename,rwm)o(ode)o(,)42 -b(>)47 b(status\))382 1489 y(FTTOPN\(unit,filename,rwm)o(ode)o(,)42 -b(>)47 b(status\))382 1602 y(FTIOPN\(unit,filename,rwm)o(ode)o(,)42 -b(>)47 b(status\))0 1858 y Fh(4)81 b Fi(Op)s(en)38 b(and)i(initialize)j -(a)e(new)e(empt)m(y)i(FITS)f(\014le.)70 b(A)41 b(template)h(\014le)e -(ma)m(y)h(also)g(b)s(e)f(sp)s(eci\014ed)g(to)h(de\014ne)227 -1971 y(the)34 b(structure)e(of)h(the)h(new)e(\014le)h(\(see)h(section)g -(4.2.4\).)51 b(The)33 b(FTDKINIT)g(routine)g(simply)f(creates)j(the)227 -2084 y(sp)s(eci\014ed)30 b(\014le)g(without)h(trying)f(to)h(in)m -(terpret)g(the)g(\014lename)f(using)g(the)h(extended)f(\014lename)h -(syn)m(tax.)382 2340 y Fe(FTINIT\(unit,filename,blo)o(cks)o(ize,)41 -b(>)48 b(status\))382 2453 y(FTDKINIT\(unit,filename,b)o(loc)o(ksiz)o -(e,)42 b(>)47 b(status\))0 2709 y Fh(5)81 b Fi(Close)31 -b(a)f(FITS)g(\014le)g(previously)g(op)s(ened)g(with)g(ftop)s(en)g(or)g -(ftinit)382 2965 y Fe(FTCLOS\(unit,)44 b(>)k(status\))0 -3221 y Fh(6)81 b Fi(Mo)m(v)m(e)32 b(to)f(a)g(sp)s(eci\014ed)f -(\(absolute\))h(HDU)g(in)g(the)f(FITS)g(\014le)g(\(nhdu)f(=)h(1)h(for)f -(the)g(FITS)g(primary)f(arra)m(y\))382 3478 y Fe(FTMAHD\(unit,nhdu,)43 -b(>)k(hdutype,status\))0 3734 y Fh(7)81 b Fi(Create)30 -b(a)f(primary)f(arra)m(y)i(\(if)g(none)f(already)g(exists\),)i(or)e -(insert)g(a)h(new)f(IMA)m(GE)h(extension)g(immediately)227 -3847 y(follo)m(wing)25 b(the)e(CHDU,)g(or)g(insert)g(a)g(new)g(Primary) -f(Arra)m(y)h(at)h(the)f(b)s(eginning)f(of)h(the)g(\014le.)38 -b(An)m(y)23 b(follo)m(wing)227 3960 y(extensions)29 b(in)g(the)g -(\014le)f(will)h(b)s(e)f(shifted)h(do)m(wn)f(to)h(mak)m(e)h(ro)s(om)e -(for)h(the)g(new)f(extension.)40 b(If)29 b(the)g(CHDU)227 -4072 y(is)h(the)g(last)g(HDU)g(in)g(the)f(\014le)h(then)f(the)h(new)f -(image)i(extension)f(will)g(simply)f(b)s(e)g(app)s(ended)f(to)i(the)g -(end)227 4185 y(of)k(the)h(\014le.)52 b(One)33 b(can)h(force)h(a)g(new) -e(primary)g(arra)m(y)i(to)g(b)s(e)e(inserted)h(at)h(the)f(b)s(eginning) -f(of)h(the)h(FITS)227 4298 y(\014le)29 b(b)m(y)f(setting)i(status)e(=)h -(-9)g(prior)e(to)j(calling)g(the)e(routine.)40 b(In)28 -b(this)g(case)i(the)e(existing)i(primary)d(arra)m(y)227 -4411 y(will)f(b)s(e)f(con)m(v)m(erted)i(to)g(an)e(IMA)m(GE)h -(extension.)40 b(The)25 b(new)g(extension)i(\(or)f(primary)e(arra)m -(y\))j(will)f(b)s(ecome)227 4524 y(the)32 b(CHDU.)f(The)g(FTI)s(IMGLL)f -(routine)i(is)f(iden)m(tical)i(to)e(the)h(FTI)s(IMG)f(routine)g(except) -h(that)f(the)h(4th)227 4637 y(parameter)25 b(\(the)g(length)g(of)f(eac) -m(h)h(axis\))g(is)g(an)f(arra)m(y)h(of)f(64-bit)i(in)m(tegers)f(rather) -f(than)g(an)g(arra)m(y)h(of)g(32-bit)227 4750 y(in)m(tegers.)382 -5006 y Fe(FTIIMG\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 -b(status\))382 5119 y(FTIIMGLL\(unit,bitpix,nax)o(is,)o(naxe)o(sll,)41 -b(>)47 b(status\))0 5375 y Fh(8)81 b Fi(Insert)30 b(a)i(new)f(ASCI)s(I) -f(T)-8 b(ABLE)31 b(extension)h(immediately)h(follo)m(wing)f(the)g -(CHDU.)g(An)m(y)f(follo)m(wing)i(exten-)227 5488 y(sions)26 -b(will)g(b)s(e)f(shifted)g(do)m(wn)g(to)h(mak)m(e)h(ro)s(om)e(for)h -(the)f(new)g(extension.)40 b(If)25 b(there)h(are)g(no)g(other)f(follo)m -(wing)227 5601 y(extensions)32 b(then)f(the)h(new)f(table)h(extension)g -(will)g(simply)f(b)s(e)g(app)s(ended)f(to)i(the)f(end)g(of)h(the)f -(\014le.)44 b(The)227 5714 y(new)33 b(extension)h(will)f(b)s(ecome)h -(the)f(CHDU.)h(The)f(FTIT)-8 b(ABLL)33 b(routine)g(is)g(iden)m(tical)i -(to)f(the)g(FTIT)-8 b(AB)p eop end -%%Page: 32 38 -TeXDict begin 32 37 bop 0 299 a Fi(32)1747 b Fg(CHAPTER)30 -b(5.)111 b(BASIC)30 b(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 -555 y Fi(routine)36 b(except)g(that)g(the)f(2nd)g(and)g(3rd)g -(parameters)g(\(that)i(giv)m(e)g(the)e(size)h(of)g(the)f(table\))i(are) -f(64-bit)227 668 y(in)m(tegers)43 b(rather)f(than)f(32-bit)i(in)m -(tegers.)76 b(Under)41 b(normal)g(circumstances,)46 b(the)c(nro)m(ws)f -(and)g(nro)m(wsll)227 781 y(paramen)m(ters)f(should)e(ha)m(v)m(e)j(a)f -(v)-5 b(alue)40 b(of)f(0;)45 b(CFITSIO)38 b(will)h(automatically)k(up)s -(date)38 b(the)i(n)m(um)m(b)s(er)e(of)227 894 y(ro)m(ws)31 -b(as)f(data)h(is)g(written)f(to)h(the)g(table.)382 1158 -y Fe(FTITAB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o(ype)o(,tbc)o(ol,t) -o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 1271 -y(status\))382 1384 y(FTITABLL\(unit,rowlenll,n)o(row)o(sll,)o(tfie)o -(lds)o(,tty)o(pe,t)o(bco)o(l,tf)o(orm,)o(tun)o(it,e)o(xtna)o(me,)f(>) -716 1497 y(status\))0 1761 y Fh(9)81 b Fi(Insert)26 b(a)h(new)g(binary) -f(table)h(extension)h(immediately)g(follo)m(wing)h(the)e(CHDU.)g(An)m -(y)g(follo)m(wing)h(extensions)227 1874 y(will)39 b(b)s(e)f(shifted)g -(do)m(wn)g(to)h(mak)m(e)g(ro)s(om)g(for)f(the)g(new)g(extension.)66 -b(If)38 b(there)h(are)f(no)h(other)f(follo)m(wing)227 -1987 y(extensions)f(then)g(the)f(new)g(bin)m(table)h(extension)h(will)f -(simply)f(b)s(e)g(app)s(ended)e(to)k(the)e(end)g(of)h(the)g(\014le.)227 -2100 y(The)23 b(new)g(extension)h(will)f(b)s(ecome)h(the)f(CHDU.)h(The) -f(FTIBINLL)g(routine)g(is)g(iden)m(tical)i(to)f(the)g(FTIBIN)227 -2213 y(routine)30 b(except)i(that)e(the)h(2nd)e(parameter)i(\(that)g -(giv)m(es)g(the)g(length)f(of)h(the)f(table\))h(is)g(a)f(64-bit)i(in)m -(teger)227 2325 y(rather)24 b(than)g(a)g(32-bit)h(in)m(teger.)40 -b(Under)23 b(normal)h(circumstances,)i(the)e(nro)m(ws)f(and)h(nro)m -(wsll)g(paramen)m(ters)227 2438 y(should)31 b(ha)m(v)m(e)i(a)f(v)-5 -b(alue)32 b(of)f(0;)i(CFITSIO)d(will)i(automatically)j(up)s(date)30 -b(the)i(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(as)g(data)g(is)227 -2551 y(written)f(to)g(the)f(table.)382 2815 y Fe -(FTIBIN\(unit,nrows,tfield)o(s,t)o(type)o(,tfo)o(rm,)o(tuni)o(t,ex)o -(tna)o(me,v)o(arid)o(at)41 b(>)48 b(status\))382 2928 -y(FTIBINLL\(unit,nrowsll,tf)o(iel)o(ds,t)o(type)o(,tf)o(orm,)o(tuni)o -(t,e)o(xtna)o(me,v)o(ari)o(dat)41 b(>)48 b(status\))0 -3380 y Fd(5.3)135 b(Keyw)l(ord)46 b(I/O)f(Routines)0 -3624 y Fh(1)81 b Fi(Put)30 b(\(app)s(end\))f(an)h(80-c)m(haracter)j -(record)e(in)m(to)g(the)g(CHU.)382 3888 y Fe(FTPREC\(unit,card,)43 -b(>)k(status\))0 4152 y Fh(2)81 b Fi(Put)28 b(\(app)s(end\))g(a)h(new)g -(k)m(eyw)m(ord)g(of)g(the)g(appropriate)g(datat)m(yp)s(e)h(in)m(to)g -(the)f(CHU.)g(The)f(E)h(and)f(D)i(v)m(ersions)227 4265 -y(of)24 b(this)f(routine)g(ha)m(v)m(e)h(the)g(added)e(feature)i(that)g -(if)f(the)g('decimals')i(parameter)f(is)f(negativ)m(e,)k(then)c(the)g -('G')227 4378 y(displa)m(y)30 b(format)g(rather)f(then)g(the)h('E')f -(format)h(will)g(b)s(e)f(used)f(when)h(constructing)h(the)f(k)m(eyw)m -(ord)h(v)-5 b(alue,)227 4490 y(taking)27 b(the)g(absolute)g(v)-5 -b(alue)26 b(of)h('decimals')g(for)f(the)h(precision.)39 -b(This)26 b(will)g(suppress)e(trailing)k(zeros,)g(and)227 -4603 y(will)37 b(use)g(a)g(\014xed)f(format)h(rather)g(than)f(an)h(exp) -s(onen)m(tial)g(format,)i(dep)s(ending)c(on)i(the)g(magnitude)g(of)227 -4716 y(the)31 b(v)-5 b(alue.)382 4980 y Fe(FTPKY[JKLS]\(unit,keyword)o -(,ke)o(yval)o(,com)o(men)o(t,)42 b(>)47 b(status\))382 -5093 y(FTPKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o -(omme)o(nt,)41 b(>)48 b(status\))0 5357 y Fh(3)81 b Fi(Get)37 -b(the)f(n)m(th)f(80-c)m(haracter)k(header)d(record)g(from)f(the)h(CHU.) -h(The)e(\014rst)g(k)m(eyw)m(ord)i(in)e(the)h(header)g(is)g(at)227 -5470 y(k)m(ey)p 365 5470 28 4 v 34 w(no)42 b(=)f(1;)49 -b(if)42 b(k)m(ey)p 996 5470 V 34 w(no)g(=)f(0)i(then)e(this)h -(subroutine)f(simple)h(mo)m(v)m(es)i(the)e(in)m(ternal)h(p)s(oin)m(ter) -f(to)h(the)227 5583 y(b)s(eginning)35 b(of)h(the)g(header)f(so)h(that)g -(subsequen)m(t)f(k)m(eyw)m(ord)h(op)s(erations)g(will)g(start)g(at)g -(the)g(top)g(of)g(the)227 5696 y(header;)31 b(it)g(also)g(returns)e(a)i -(blank)f(card)g(v)-5 b(alue)31 b(in)f(this)g(case.)p -eop end -%%Page: 33 39 -TeXDict begin 33 38 bop 0 299 a Fg(5.4.)72 b(D)m(A)-8 -b(T)g(A)32 b(I/O)f(R)m(OUTINES)2650 b Fi(33)382 555 y -Fe(FTGREC\(unit,key_no,)42 b(>)48 b(card,status\))0 804 -y Fh(4)81 b Fi(Get)31 b(a)g(k)m(eyw)m(ord)g(v)-5 b(alue)30 -b(\(with)h(the)f(appropriate)h(datat)m(yp)s(e\))g(and)f(commen)m(t)i -(from)e(the)g(CHU)382 1052 y Fe(FTGKY[EDJKLS]\(unit,keywo)o(rd,)41 -b(>)48 b(keyval,comment,status\))0 1301 y Fh(5)81 b Fi(Delete)32 -b(an)e(existing)i(k)m(eyw)m(ord)f(record.)382 1550 y -Fe(FTDKEY\(unit,keyword,)42 b(>)48 b(status\))0 1881 -y Fd(5.4)135 b(Data)46 b(I/O)g(Routines)0 2132 y Fi(The)32 -b(follo)m(wing)i(routines)e(read)h(or)f(write)h(data)g(v)-5 -b(alues)33 b(in)f(the)h(curren)m(t)f(HDU)i(of)e(the)h(FITS)f(\014le.)47 -b(Automatic)0 2245 y(datat)m(yp)s(e)28 b(con)m(v)m(ersion)h(will)e(b)s -(e)g(attempted)h(for)g(n)m(umerical)f(datat)m(yp)s(es)i(if)e(the)g(sp)s -(eci\014ed)g(datat)m(yp)s(e)h(is)f(di\013eren)m(t)0 2357 -y(from)j(the)g(actual)i(datat)m(yp)s(e)g(of)e(the)h(FITS)e(arra)m(y)i -(or)f(table)i(column.)0 2606 y Fh(1)81 b Fi(W)-8 b(rite)31 -b(elemen)m(ts)h(in)m(to)f(the)g(primary)e(data)j(arra)m(y)e(or)h(image) -g(extension.)382 2855 y Fe(FTPPR[BIJKED]\(unit,group)o(,fp)o(ixel)o -(,nel)o(eme)o(nts,)o(valu)o(es,)41 b(>)48 b(status\))0 -3103 y Fh(2)81 b Fi(Read)30 b(elemen)m(ts)j(from)d(the)h(primary)e -(data)j(arra)m(y)f(or)g(image)h(extension.)42 b(Unde\014ned)29 -b(arra)m(y)j(elemen)m(ts)g(will)227 3216 y(b)s(e)f(returned)f(with)h(a) -h(v)-5 b(alue)31 b(=)g(n)m(ullv)-5 b(al,)33 b(unless)d(n)m(ullv)-5 -b(al)32 b(=)f(0)h(in)f(whic)m(h)g(case)h(no)f(c)m(hec)m(ks)i(for)e -(unde\014ned)227 3329 y(pixels)h(will)f(b)s(e)f(p)s(erformed.)42 -b(The)30 b(an)m(yf)i(parameter)f(is)g(set)h(to)g(true)f(\(=)g(.true.\)) -43 b(if)31 b(an)m(y)h(of)f(the)g(returned)227 3442 y(elemen)m(ts)h(w)m -(ere)f(unde\014ned.)382 3691 y Fe(FTGPV[BIJKED]\(unit,group)o(,fp)o -(ixel)o(,nel)o(eme)o(nts,)o(null)o(val)o(,)42 b(>)47 -b(values,anyf,status\))0 3939 y Fh(3)81 b Fi(W)-8 b(rite)36 -b(elemen)m(ts)h(in)m(to)f(an)f(ASCI)s(I)e(or)i(binary)g(table)h -(column.)54 b(The)35 b(`felem')h(parameter)g(applies)f(only)g(to)227 -4052 y(v)m(ector)d(columns)e(in)g(binary)g(tables)h(and)f(is)g(ignored) -h(when)e(writing)i(to)g(ASCI)s(I)d(tables.)382 4301 y -Fe(FTPCL[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o(row,)o(fel)o(em,n)o(elem)o -(ent)o(s,va)o(lues)o(,)42 b(>)47 b(status\))0 4549 y -Fh(4)81 b Fi(Read)22 b(elemen)m(ts)h(from)e(an)g(ASCI)s(I)g(or)g -(binary)g(table)i(column.)38 b(Unde\014ned)20 b(arra)m(y)i(elemen)m(ts) -h(will)f(b)s(e)f(returned)227 4662 y(with)32 b(a)h(v)-5 -b(alue)33 b(=)f(n)m(ullv)-5 b(al,)34 b(unless)e(n)m(ullv)-5 -b(al)32 b(=)h(0)f(\(or)h(=)f(')h(')f(for)g(ftgcvs\))i(in)e(whic)m(h)g -(case)i(no)e(c)m(hec)m(king)i(for)227 4775 y(unde\014ned)23 -b(v)-5 b(alues)25 b(will)g(b)s(e)g(p)s(erformed.)37 b(The)24 -b(ANYF)i(parameter)f(is)g(set)h(to)f(true)g(if)g(an)m(y)g(of)g(the)g -(returned)227 4888 y(elemen)m(ts)32 b(are)f(unde\014ned.)227 -5036 y(An)m(y)d(column,)h(regardless)f(of)g(it's)h(in)m(trinsic)f -(datat)m(yp)s(e,)i(ma)m(y)e(b)s(e)f(read)h(as)g(a)h(string.)40 -b(It)28 b(should)e(b)s(e)i(noted)227 5149 y(ho)m(w)m(ev)m(er)k(that)f -(reading)f(a)h(n)m(umeric)f(column)g(as)h(a)g(string)f(is)g(10)i(-)e -(100)i(times)f(slo)m(w)m(er)g(than)f(reading)h(the)227 -5262 y(same)36 b(column)f(as)h(a)g(n)m(um)m(b)s(er)e(due)g(to)j(the)e -(large)i(o)m(v)m(erhead)f(in)f(constructing)h(the)g(formatted)g -(strings.)227 5375 y(The)i(displa)m(y)g(format)g(of)g(the)g(returned)f -(strings)g(will)h(b)s(e)g(determined)f(b)m(y)h(the)g(TDISPn)f(k)m(eyw)m -(ord,)j(if)227 5488 y(it)d(exists,)h(otherwise)f(b)m(y)f(the)g(datat)m -(yp)s(e)h(of)f(the)h(column.)57 b(The)36 b(length)g(of)h(the)f -(returned)f(strings)h(can)227 5601 y(b)s(e)29 b(determined)f(with)h -(the)g(ftgcdw)g(routine.)40 b(The)28 b(follo)m(wing)j(TDISPn)c(displa)m -(y)j(formats)f(are)g(curren)m(tly)227 5714 y(supp)s(orted:)p -eop end -%%Page: 34 40 -TeXDict begin 34 39 bop 0 299 a Fi(34)1747 b Fg(CHAPTER)30 -b(5.)111 b(BASIC)30 b(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)418 -555 y Fe(Iw.m)142 b(Integer)418 668 y(Ow.m)g(Octal)47 -b(integer)418 781 y(Zw.m)142 b(Hexadecimal)45 b(integer)418 -894 y(Fw.d)142 b(Fixed)47 b(floating)e(point)418 1007 -y(Ew.d)142 b(Exponential)45 b(floating)h(point)418 1120 -y(Dw.d)142 b(Exponential)45 b(floating)h(point)418 1233 -y(Gw.d)142 b(General;)46 b(uses)g(Fw.d)h(if)g(significance)e(not)i -(lost,)f(else)h(Ew.d)227 1483 y Fi(where)24 b(w)h(is)f(the)h(width)f -(in)g(c)m(haracters)i(of)f(the)g(displa)m(y)m(ed)g(v)-5 -b(alues,)27 b(m)d(is)h(the)f(minim)m(um)g(n)m(um)m(b)s(er)g(of)g -(digits)227 1595 y(displa)m(y)m(ed,)31 b(and)e(d)h(is)f(the)i(n)m(um)m -(b)s(er)d(of)i(digits)g(to)h(the)f(righ)m(t)h(of)f(the)g(decimal.)41 -b(The)29 b(.m)h(\014eld)g(is)g(optional.)382 1855 y Fe -(FTGCV[SBIJKEDCM]\(unit,co)o(lnu)o(m,fr)o(ow,f)o(ele)o(m,ne)o(leme)o -(nts)o(,nul)o(lval)o(,)42 b(>)1098 1968 y(values,anyf,status\))0 -2228 y Fh(5)81 b Fi(Get)42 b(the)g(table)h(column)e(n)m(um)m(b)s(er)g -(and)g(full)g(name)h(of)g(the)f(column)h(whose)f(name)h(matc)m(hes)h -(the)f(input)227 2341 y(template)35 b(string.)48 b(See)33 -b(the)h(`Adv)-5 b(anced)33 b(In)m(terface)h(Routines')f(c)m(hapter)h -(for)f(a)g(full)g(description)g(of)g(this)227 2454 y(routine.)382 -2714 y Fe(FTGCNN\(unit,casesen,colt)o(emp)o(late)o(,)42 -b(>)47 b(colname,colnum,status\))p eop end -%%Page: 35 41 -TeXDict begin 35 40 bop 0 1225 a Ff(Chapter)65 b(6)0 -1687 y Fl(Adv)-13 b(anced)78 b(In)-6 b(terface)77 b(Subroutines)0 -2180 y Fi(This)31 b(c)m(hapter)h(de\014nes)f(all)h(the)g(a)m(v)-5 -b(ailable)34 b(subroutines)d(in)g(the)h(FITSIO)e(user)h(in)m(terface.) -46 b(F)-8 b(or)33 b(completeness,)0 2293 y(the)43 b(basic)g -(subroutines)e(describ)s(ed)g(in)i(the)f(previous)h(c)m(hapter)g(are)g -(also)g(rep)s(eated)g(here.)77 b(A)43 b(righ)m(t)g(arro)m(w)0 -2406 y(sym)m(b)s(ol)29 b(is)f(used)g(here)h(to)g(separate)h(the)f -(input)f(parameters)h(from)f(the)h(output)g(parameters)g(in)f(the)h -(de\014nition)0 2518 y(of)k(eac)m(h)h(subroutine.)47 -b(This)32 b(sym)m(b)s(ol)h(is)g(not)g(actually)i(part)d(of)h(the)h -(calling)g(sequence.)49 b(An)32 b(alphab)s(etical)i(list)0 -2631 y(and)c(de\014nition)g(of)g(all)i(the)e(parameters)h(is)f(giv)m -(en)i(at)f(the)f(end)g(of)h(this)f(section.)0 2961 y -Fd(6.1)135 b(FITS)44 b(File)i(Op)t(en)e(and)h(Close)h(Subroutines:)0 -3197 y Fh(1)81 b Fi(Op)s(en)30 b(an)i(existing)g(FITS)g(\014le)f(with)h -(readonly)g(or)g(readwrite)g(access.)46 b(The)31 b(FTDK)m(OPN)i -(routine)e(simply)227 3310 y(op)s(ens)h(the)g(sp)s(eci\014ed)g(\014le)h -(without)f(trying)h(to)g(in)m(terpret)g(the)f(\014lename)h(using)f(the) -g(extended)h(\014lename)227 3423 y(syn)m(tax.)41 b(FTDOPN)28 -b(op)s(ens)e(the)i(\014le)g(and)f(also)i(mo)m(v)m(es)g(to)g(the)f -(\014rst)f(HDU)h(con)m(taining)h(signi\014can)m(t)g(data,)227 -3536 y(if)35 b(no)h(sp)s(eci\014c)f(HDU)h(is)f(sp)s(eci\014ed)f(as)i -(part)f(of)g(the)h(\014lename.)55 b(FTTOPN)35 b(and)f(FTIOPN)h(are)h -(similar)227 3649 y(except)26 b(that)f(they)g(will)g(mo)m(v)m(e)h(to)g -(the)f(\014rst)f(table)h(HDU)h(or)e(image)i(HDU,)g(resp)s(ectiv)m(ely) --8 b(,)28 b(if)c(a)h(HDU)h(name)227 3762 y(or)31 b(n)m(um)m(b)s(er)e -(is)h(not)h(sp)s(eci\014ed)e(as)i(part)f(of)h(the)f(\014lename.)382 -3996 y Fe(FTOPEN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 -b(blocksize,status\))382 4108 y(FTDKOPN\(unit,filename,rw)o(mod)o(e,)42 -b(>)47 b(blocksize,status\))382 4334 y(FTDOPN\(unit,filename,rwm)o(ode) -o(,)42 b(>)47 b(status\))382 4447 y(FTTOPN\(unit,filename,rwm)o(ode)o -(,)42 b(>)47 b(status\))382 4560 y(FTIOPN\(unit,filename,rwm)o(ode)o(,) -42 b(>)47 b(status\))0 4794 y Fh(2)81 b Fi(Op)s(en)24 -b(an)i(existing)h(FITS)e(\014le)h(with)f(readonly)h(or)g(readwrite)g -(access)h(and)f(mo)m(v)m(e)h(to)f(a)h(follo)m(wing)g(extension,)227 -4907 y(if)38 b(one)g(w)m(as)g(sp)s(eci\014ed)g(as)g(part)f(of)h(the)h -(\014lename.)63 b(\(e.g.,)42 b('\014lename.\014ts+2')c(or)g -('\014lename.\014ts[2]')i(will)227 5020 y(mo)m(v)m(e)e(to)g(the)e(3rd)g -(HDU)i(in)e(the)h(\014le\).)60 b(Note)37 b(that)h(this)e(routine)h -(di\013ers)f(from)g(FTOPEN)g(in)g(that)h(it)227 5133 -y(do)s(es)30 b(not)h(ha)m(v)m(e)h(the)e(redundan)m(t)f(blo)s(c)m(ksize) -j(argumen)m(t.)382 5367 y Fe(FTNOPN\(unit,filename,rwm)o(ode)o(,)42 -b(>)47 b(status\))0 5601 y Fh(3)81 b Fi(Reop)s(en)38 -b(a)i(FITS)e(\014le)i(that)f(w)m(as)h(previously)f(op)s(ened)f(with)h -(FTOPEN,)g(FTNOPN,)g(or)h(FTINIT.)e(The)227 5714 y(newunit)f(n)m(um)m -(b)s(er)f(ma)m(y)j(then)e(b)s(e)g(treated)i(as)f(a)g(separate)g -(\014le,)i(and)d(one)h(ma)m(y)h(sim)m(ultaneously)f(read)1905 -5942 y(35)p eop end -%%Page: 36 42 -TeXDict begin 36 41 bop 0 299 a Fi(36)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)227 555 y Fi(or)36 b(write)g(to)g(2)g(\(or)g(more\))g -(di\013eren)m(t)g(extensions)g(in)f(the)h(same)g(\014le.)56 -b(The)35 b(FTOPEN)g(and)g(FTNOPN)227 668 y(routines)f(\(ab)s(o)m(v)m -(e\))h(automatically)h(detects)f(cases)g(where)e(a)g(previously)h(op)s -(ened)e(\014le)i(is)g(b)s(eing)f(op)s(ened)227 781 y(again,)c(and)e -(then)g(in)m(ternally)h(call)g(FTREOPEN,)f(so)h(programs)e(should)h -(rarely)g(need)g(to)h(explicitly)h(call)227 894 y(this)i(routine.)334 -1136 y Fe(FTREOPEN\(unit,)44 b(>)j(newunit,)f(status\))0 -1377 y Fh(4)81 b Fi(Op)s(en)24 b(and)g(initialize)k(a)e(new)f(empt)m(y) -g(FITS)g(\014le.)39 b(The)25 b(FTDKINIT)g(routine)g(simply)g(creates)i -(the)f(sp)s(eci\014ed)227 1490 y(\014le)31 b(without)f(trying)h(to)g -(in)m(terpret)f(the)h(\014lename)g(using)e(the)i(extended)f(\014lename) -h(syn)m(tax.)334 1732 y Fe(FTINIT\(unit,filename,bloc)o(ksi)o(ze,)41 -b(>)48 b(status\))334 1845 y(FTDKINIT\(unit,filename,bl)o(ock)o(size)o -(,)42 b(>)47 b(status\))0 2087 y Fh(5)81 b Fi(Create)24 -b(a)g(new)f(FITS)g(\014le,)i(using)e(a)h(template)h(\014le)e(to)i -(de\014ne)d(its)i(initial)h(size)g(and)e(structure.)37 -b(The)24 b(template)227 2199 y(ma)m(y)39 b(b)s(e)f(another)h(FITS)e -(HDU)i(or)g(an)f(ASCI)s(I)f(template)j(\014le.)64 b(If)38 -b(the)h(input)e(template)j(\014le)e(name)h(is)227 2312 -y(blank,)28 b(then)f(this)g(routine)g(b)s(eha)m(v)m(es)h(the)f(same)h -(as)f(FTINIT.)g(The)f(curren)m(tly)i(supp)s(orted)d(format)i(of)h(the) -227 2425 y(ASCI)s(I)c(template)j(\014le)f(is)f(describ)s(ed)g(under)f -(the)i(\014ts)p 2037 2425 28 4 v 32 w(parse)p 2277 2425 -V 33 w(template)g(routine)g(\(in)g(the)f(general)i(Utilities)227 -2538 y(section\),)32 b(but)e(this)g(ma)m(y)h(c)m(hange)h(sligh)m(tly)g -(later)f(releases)g(of)g(CFITSIO.)334 2780 y Fe(FTTPLT\(unit,)45 -b(filename,)g(tplfilename,)f(>)k(status\))0 3022 y Fh(6)81 -b Fi(Flush)33 b(in)m(ternal)h(bu\013ers)f(of)h(data)g(to)g(the)g -(output)g(FITS)f(\014le)h(previously)f(op)s(ened)g(with)g(ftop)s(en)h -(or)f(ftinit.)227 3135 y(The)j(routine)h(usually)f(nev)m(er)h(needs)f -(to)i(b)s(e)e(called,)j(but)d(doing)h(so)g(will)g(ensure)f(that)h(if)f -(the)h(program)227 3247 y(subsequen)m(tly)30 b(ab)s(orts,)g(then)h(the) -f(FITS)g(\014le)g(will)h(ha)m(v)m(e)h(at)f(least)g(b)s(een)f(closed)h -(prop)s(erly)-8 b(.)382 3489 y Fe(FTFLUS\(unit,)44 b(>)k(status\))0 -3731 y Fh(7)81 b Fi(Close)31 b(a)f(FITS)g(\014le)g(previously)g(op)s -(ened)g(with)g(ftop)s(en)g(or)g(ftinit)382 3973 y Fe(FTCLOS\(unit,)44 -b(>)k(status\))0 4214 y Fh(8)81 b Fi(Close)34 b(and)f(DELETE)g(a)h -(FITS)f(\014le)h(previously)f(op)s(ened)g(with)g(ftop)s(en)g(or)h -(ftinit.)51 b(This)33 b(routine)g(ma)m(y)i(b)s(e)227 -4327 y(useful)29 b(in)h(cases)g(where)g(a)g(FITS)f(\014le)g(is)h -(created,)h(but)e(an)h(error)f(o)s(ccurs)h(whic)m(h)f(prev)m(en)m(ts)i -(the)e(complete)227 4440 y(\014le)i(from)f(b)s(eing)g(written.)382 -4682 y Fe(FTDELT\(unit,)44 b(>)k(status\))0 4924 y Fh(9)81 -b Fi(Get)31 b(the)g(v)-5 b(alue)31 b(of)f(an)g(un)m(used)g(I/O)g(unit)g -(n)m(um)m(b)s(er)f(whic)m(h)h(ma)m(y)h(then)f(b)s(e)g(used)g(as)g -(input)g(to)h(FTOPEN)f(or)227 5036 y(FTINIT.)36 b(This)f(routine)h -(searc)m(hes)h(for)f(the)g(\014rst)f(un)m(used)g(unit)g(n)m(um)m(b)s -(er)g(in)g(the)i(range)f(from)f(with)h(99)227 5149 y(do)m(wn)d(to)h -(50.)50 b(This)32 b(routine)h(just)g(k)m(eeps)h(an)f(in)m(ternal)h -(list)f(of)h(the)f(allo)s(cated)i(unit)e(n)m(um)m(b)s(ers)f(and)g(do)s -(es)227 5262 y(not)26 b(ph)m(ysically)g(c)m(hec)m(k)g(that)g(the)g(F)-8 -b(ortran)25 b(unit)g(is)g(a)m(v)-5 b(ailable)28 b(\(to)e(b)s(e)f -(compatible)h(with)f(the)g(SPP)f(v)m(ersion)227 5375 -y(of)35 b(FITSIO\).)g(Th)m(us)f(users)g(m)m(ust)h(not)g(indep)s(enden)m -(tly)f(allo)s(cate)j(an)m(y)f(unit)e(n)m(um)m(b)s(ers)g(in)h(the)g -(range)g(50)227 5488 y(-)42 b(99)g(if)f(this)g(routine)g(is)g(also)h -(to)g(b)s(e)f(used)f(in)h(the)g(same)h(program.)73 b(This)40 -b(routine)h(is)g(pro)m(vided)g(for)227 5601 y(con)m(v)m(enience)34 -b(only)-8 b(,)32 b(and)e(it)i(is)f(not)h(required)e(that)i(the)f(unit)g -(n)m(um)m(b)s(ers)f(used)g(b)m(y)h(FITSIO)f(b)s(e)h(allo)s(cated)227 -5714 y(b)m(y)g(this)f(routine.)p eop end -%%Page: 37 43 -TeXDict begin 37 42 bop 0 299 a Fg(6.1.)72 b(FITS)30 -b(FILE)g(OPEN)g(AND)h(CLOSE)e(SUBR)m(OUTINES:)1561 b -Fi(37)382 555 y Fe(FTGIOU\()46 b(>)h(iounit,)f(status\))0 -807 y Fh(10)g Fi(F)-8 b(ree)34 b(\(deallo)s(cate\))i(an)d(I/O)g(unit)f -(n)m(um)m(b)s(er)g(whic)m(h)g(w)m(as)h(previously)g(allo)s(cated)i -(with)e(FTGIOU.)g(All)g(pre-)227 919 y(viously)28 b(allo)s(cated)i -(unit)d(n)m(um)m(b)s(ers)f(ma)m(y)i(b)s(e)f(deallo)s(cated)j(at)e(once) -h(b)m(y)e(calling)i(FTFIOU)f(with)f(iounit)h(=)227 1032 -y(-1.)382 1284 y Fe(FTFIOU\(iounit,)44 b(>)j(status\))0 -1535 y Fh(11)f Fi(Return)30 b(the)h(F)-8 b(ortran)31 -b(unit)g(n)m(um)m(b)s(er)e(that)i(corresp)s(onds)f(to)h(the)g(C)g -(\014ts\014le)f(p)s(oin)m(ter)h(v)-5 b(alue,)32 b(or)e(vice)i(v)m -(ersa.)227 1648 y(These)37 b(2)h(C)f(routines)g(ma)m(y)g(b)s(e)g -(useful)f(in)h(mixed)g(language)i(programs)e(where)f(b)s(oth)h(C)g(and) -f(F)-8 b(ortran)227 1761 y(subroutines)25 b(need)g(to)i(access)g(the)f -(same)g(\014le.)40 b(F)-8 b(or)26 b(example,)i(if)e(a)g(FITS)f(\014le)h -(is)g(op)s(ened)f(with)g(unit)g(12)i(b)m(y)227 1874 y(a)k(F)-8 -b(ortran)31 b(subroutine,)f(then)g(a)h(C)f(routine)h(within)f(the)g -(same)h(program)g(could)f(get)i(the)e(\014t\014le)h(p)s(oin)m(ter)227 -1987 y(v)-5 b(alue)39 b(to)f(access)h(the)f(same)h(\014le)f(b)m(y)f -(calling)j('fptr)d(=)h(CUnit2FITS\(12\)'.)64 b(These)38 -b(routines)g(return)f(a)227 2100 y(v)-5 b(alue)31 b(of)g(zero)g(if)f -(an)g(error)g(o)s(ccurs.)286 2351 y Fe(int)334 b(CFITS2Unit\(fitsfile) -42 b(*ptr\);)286 2464 y(fitsfile*)k(CUnit2FITS\(int)e(unit\);)0 -2715 y Fh(11)i Fi(P)m(arse)32 b(the)g(input)e(\014lename)i(and)f -(return)f(the)i(HDU)g(n)m(um)m(b)s(er)e(that)i(w)m(ould)f(b)s(e)g(mo)m -(v)m(ed)i(to)f(if)f(the)h(\014le)f(w)m(ere)227 2828 y(op)s(ened)i(with) -g(FTNOPN.)g(The)f(returned)g(HDU)i(n)m(um)m(b)s(er)e(b)s(egins)h(with)g -(1)g(for)g(the)g(primary)g(arra)m(y)-8 b(,)35 b(so)227 -2941 y(for)d(example,)g(if)g(the)g(input)f(\014lename)g(=)h(`m)m -(y\014le.\014ts[2]')h(then)e(hdun)m(um)e(=)j(3)g(will)g(b)s(e)f -(returned.)43 b(FIT-)227 3054 y(SIO)35 b(do)s(es)h(not)g(op)s(en)g(the) -g(\014le)g(to)h(c)m(hec)m(k)h(if)e(the)g(extension)h(actually)h(exists) -e(if)h(an)e(extension)i(n)m(um)m(b)s(er)227 3167 y(is)43 -b(sp)s(eci\014ed.)75 b(If)42 b(an)g(extension)h(*name*)g(is)f(included) -g(in)g(the)g(\014le)g(name)h(sp)s(eci\014cation)g(\(e.g.)77 -b(`m)m(y-)227 3280 y(\014le.\014ts[EVENTS]')30 b(then)f(this)h(routine) -g(will)g(ha)m(v)m(e)h(to)f(op)s(en)f(the)h(FITS)f(\014le)h(and)f(lo)s -(ok)h(for)g(the)g(p)s(osition)227 3393 y(of)38 b(the)h(named)e -(extension,)k(then)d(close)h(\014le)f(again.)64 b(This)38 -b(is)g(not)g(p)s(ossible)f(if)h(the)g(\014le)g(is)g(b)s(eing)g(read)227 -3506 y(from)e(the)g(stdin)f(stream,)j(and)d(an)h(error)f(will)h(b)s(e)g -(returned)e(in)i(this)g(case.)58 b(If)35 b(the)h(\014lename)g(do)s(es)g -(not)227 3619 y(sp)s(ecify)29 b(an)g(explicit)h(extension)g(\(e.g.)42 -b('m)m(y\014le.\014ts'\))30 b(then)f(hdun)m(um)e(=)h(-99)j(will)e(b)s -(e)g(returned,)f(whic)m(h)h(is)227 3731 y(functionally)34 -b(equiv)-5 b(alen)m(t)35 b(to)g(hdun)m(um)c(=)i(1.)50 -b(This)33 b(routine)g(is)h(mainly)g(used)e(for)i(bac)m(kw)m(ard)g -(compati-)227 3844 y(bilit)m(y)g(in)e(the)g(fto)s(ols)h(soft)m(w)m(are) -h(pac)m(k)-5 b(age)34 b(and)e(is)g(not)g(recommended)g(for)g(general)i -(use.)46 b(It)32 b(is)h(generally)227 3957 y(b)s(etter)i(and)g(more)g -(e\016cien)m(t)h(to)g(\014rst)e(op)s(en)g(the)h(FITS)f(\014le)h(with)g -(FTNOPN,)g(then)g(use)f(FTGHDN)i(to)227 4070 y(determine)30 -b(whic)m(h)g(HDU)g(in)f(the)h(\014le)g(has)g(b)s(een)f(op)s(ened,)g -(rather)g(than)h(calling)h(FTEXTN)f(follo)m(w)m(ed)h(b)m(y)227 -4183 y(a)g(call)h(to)f(FTNOPN.)382 4434 y Fe(FTEXTN\(filename,)43 -b(>)48 b(nhdu,)e(status\))0 4686 y Fh(12)g Fi(Return)30 -b(the)g(name)h(of)f(the)h(op)s(ened)e(FITS)h(\014le.)382 -4937 y Fe(FTFLNM\(unit,)44 b(>)k(filename,)d(status\))0 -5188 y Fh(13)h Fi(Return)30 b(the)g(I/O)g(mo)s(de)g(of)h(the)g(op)s(en) -e(FITS)h(\014le)g(\(READONL)-8 b(Y)32 b(=)e(0,)h(READ)m(WRITE)g(=)f -(1\).)382 5440 y Fe(FTFLMD\(unit,)44 b(>)k(iomode,)e(status\))0 -5691 y Fh(14)g Fi(Return)30 b(the)g(\014le)h(t)m(yp)s(e)f(of)h(the)f -(op)s(ened)g(FITS)g(\014le)g(\(e.g.)42 b('\014le://',)32 -b('ftp://',)g(etc.\).)p eop end -%%Page: 38 44 -TeXDict begin 38 43 bop 0 299 a Fi(38)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)382 555 y Fe(FTURLT\(unit,)44 b(>)k(urltype,)d -(status\))0 819 y Fh(15)h Fi(P)m(arse)27 b(the)f(input)f(\014lename)i -(or)f(URL)g(in)m(to)h(its)g(comp)s(onen)m(t)f(parts:)39 -b(the)26 b(\014le)g(t)m(yp)s(e)h(\(\014le://,)h(ftp://,)g(h)m(ttp://,) -227 932 y(etc\),)34 b(the)e(base)g(input)e(\014le)i(name,)g(the)g(name) -g(of)g(the)g(output)f(\014le)h(that)g(the)g(input)f(\014le)g(is)h(to)g -(b)s(e)f(copied)227 1045 y(to)38 b(prior)e(to)h(op)s(ening,)h(the)f -(HDU)g(or)f(extension)i(sp)s(eci\014cation,)h(the)e(\014ltering)f(sp)s -(eci\014er,)i(the)f(binning)227 1157 y(sp)s(eci\014er,)e(and)e(the)i -(column)f(sp)s(eci\014er.)51 b(Blank)34 b(strings)g(will)h(b)s(e)e -(returned)g(for)h(an)m(y)g(comp)s(onen)m(ts)g(that)227 -1270 y(are)d(not)g(presen)m(t)f(in)g(the)h(input)e(\014le)i(name.)334 -1534 y Fe(FTIURL\(filename,)43 b(>)48 b(filetype,)d(infile,)h(outfile,) -g(extspec,)f(filter,)716 1647 y(binspec,)g(colspec,)h(status\))0 -1910 y Fh(16)g Fi(P)m(arse)e(the)g(input)f(\014le)h(name)f(and)g -(return)g(the)h(ro)s(ot)g(\014le)f(name.)81 b(The)43 -b(ro)s(ot)h(name)g(includes)f(the)h(\014le)227 2023 y(t)m(yp)s(e)35 -b(if)g(sp)s(eci\014ed,)h(\(e.g.)56 b('ftp://')37 b(or)e('h)m(ttp://'\)) -i(and)d(the)h(full)g(path)g(name,)h(to)g(the)f(exten)m(t)i(that)e(it)h -(is)227 2136 y(sp)s(eci\014ed)26 b(in)f(the)i(input)e(\014lename.)39 -b(It)26 b(do)s(es)g(not)g(include)g(the)g(HDU)h(name)f(or)g(n)m(um)m(b) -s(er,)g(or)g(an)m(y)h(\014ltering)227 2249 y(sp)s(eci\014cations.)334 -2513 y Fe(FTRTNM\(filename,)43 b(>)48 b(rootname,)d(status\))0 -2776 y Fh(16)h Fi(T)-8 b(est)36 b(if)g(the)g(input)f(\014le)h(or)f(a)i -(compressed)e(v)m(ersion)h(of)g(the)g(\014le)g(\(with)g(a)g(.gz,)i(.Z,) -e(.z,)i(or)e(.zip)g(extension\))227 2889 y(exists)j(on)f(disk.)63 -b(The)37 b(returned)g(v)-5 b(alue)38 b(of)g(the)h('exists')g(parameter) -f(will)g(ha)m(v)m(e)i(1)e(of)g(the)g(4)g(follo)m(wing)227 -3002 y(v)-5 b(alues:)370 3257 y Fe(2:)95 b(the)47 b(file)g(does)g(not)f -(exist,)h(but)f(a)i(compressed)d(version)h(does)g(exist)370 -3370 y(1:)95 b(the)47 b(disk)g(file)g(does)f(exist)370 -3483 y(0:)95 b(neither)46 b(the)h(file)g(nor)g(a)g(compressed)e -(version)h(of)h(the)g(file)g(exist)323 3596 y(-1:)94 -b(the)47 b(input)g(file)f(name)h(is)g(not)g(a)g(disk)g(file)g(\(could)f -(be)h(a)g(ftp,)g(http,)561 3709 y(smem,)g(or)g(mem)g(file,)f(or)h(a)h -(file)e(piped)h(in)g(on)g(the)g(STDIN)f(stream\))286 -3973 y(FTEXIST\(filename,)d(>)48 b(exists,)e(status\);)0 -4311 y Fd(6.2)135 b(HDU-Lev)l(el)47 b(Op)t(erations)0 -4562 y Fi(When)30 b(a)h(FITS)f(\014le)g(is)h(\014rst)e(op)s(ened)h(or)g -(created,)i(the)f(in)m(ternal)g(bu\013ers)e(in)h(FITSIO)f -(automatically)34 b(p)s(oin)m(t)c(to)0 4675 y(the)g(\014rst)g(HDU)h(in) -f(the)g(\014le.)41 b(The)29 b(follo)m(wing)j(routines)e(ma)m(y)h(b)s(e) -e(used)h(to)h(mo)m(v)m(e)g(to)g(another)f(HDU)h(in)f(the)h(\014le.)0 -4788 y(Note)j(that)f(the)g(HDU)g(n)m(um)m(b)s(ering)f(con)m(v)m(en)m -(tion)i(used)e(in)g(FITSIO)g(denotes)h(the)f(primary)g(arra)m(y)h(as)g -(the)g(\014rst)0 4901 y(HDU,)e(the)g(\014rst)f(extension)h(in)f(a)g -(FITS)g(\014le)g(is)h(the)f(second)h(HDU,)g(and)f(so)h(on.)0 -5164 y Fh(1)81 b Fi(Mo)m(v)m(e)32 b(to)f(a)g(sp)s(eci\014ed)f -(\(absolute\))h(HDU)g(in)g(the)f(FITS)g(\014le)g(\(nhdu)f(=)h(1)h(for)f -(the)g(FITS)g(primary)f(arra)m(y\))382 5428 y Fe(FTMAHD\(unit,nhdu,)43 -b(>)k(hdutype,status\))0 5691 y Fh(2)81 b Fi(Mo)m(v)m(e)32 -b(to)f(a)g(new)f(\(existing\))i(HDU)f(forw)m(ard)f(or)g(bac)m(kw)m -(ards)h(relativ)m(e)h(to)f(the)g(CHDU)p eop end -%%Page: 39 45 -TeXDict begin 39 44 bop 0 299 a Fg(6.2.)72 b(HDU-LEVEL)31 -b(OPERA)-8 b(TIONS)2414 b Fi(39)382 555 y Fe(FTMRHD\(unit,nmove,)43 -b(>)k(hdutype,status\))0 797 y Fh(3)81 b Fi(Mo)m(v)m(e)22 -b(to)f(the)f(\(\014rst\))h(HDU)g(whic)m(h)f(has)g(the)g(sp)s(eci\014ed) -g(extension)h(t)m(yp)s(e)f(and)g(EXTNAME)g(\(or)h(HDUNAME\))227 -910 y(and)34 b(EXTVER)g(k)m(eyw)m(ord)h(v)-5 b(alues.)53 -b(The)34 b(hdut)m(yp)s(e)f(parameter)i(ma)m(y)g(ha)m(v)m(e)g(a)g(v)-5 -b(alue)35 b(of)f(IMA)m(GE)p 3665 910 28 4 v 34 w(HDU)227 -1023 y(\(0\),)43 b(ASCI)s(I)p 669 1023 V 31 w(TBL)c(\(1\),)j(BINAR)-8 -b(Y)p 1468 1023 V 34 w(TBL)39 b(\(2\),)j(or)d(ANY)p 2234 -1023 V 34 w(HDU)g(\(-1\))i(where)d(ANY)p 3173 1023 V -34 w(HDU)h(means)g(that)227 1136 y(only)30 b(the)g(extname)h(and)e -(extv)m(er)i(v)-5 b(alues)30 b(will)g(b)s(e)f(used)g(to)i(lo)s(cate)g -(the)f(correct)h(extension.)42 b(If)29 b(the)h(input)227 -1249 y(v)-5 b(alue)27 b(of)f(extv)m(er)h(is)f(0)g(then)g(the)g(EXTVER)g -(k)m(eyw)m(ord)g(is)g(ignored)g(and)g(the)g(\014rst)f(HDU)i(with)e(a)i -(matc)m(hing)227 1361 y(EXTNAME)g(\(or)g(HDUNAME\))h(k)m(eyw)m(ord)f -(will)g(b)s(e)f(found.)38 b(If)26 b(no)h(matc)m(hing)h(HDU)f(is)g -(found)e(in)h(the)h(\014le)227 1474 y(then)i(the)g(curren)m(t)g(HDU)h -(will)f(remain)g(unc)m(hanged)g(and)g(a)g(status)g(=)g(BAD)p -2884 1474 V 34 w(HDU)p 3123 1474 V 33 w(NUM)h(\(301\))h(will)f(b)s(e) -227 1587 y(returned.)382 1829 y Fe(FTMNHD\(unit,)44 b(hdutype,)i -(extname,)f(extver,)h(>)i(status\))0 2071 y Fh(4)81 b -Fi(Get)31 b(the)g(n)m(um)m(b)s(er)e(of)h(the)h(curren)m(t)f(HDU)h(in)f -(the)h(FITS)e(\014le)i(\(primary)f(arra)m(y)g(=)g(1\))382 -2312 y Fe(FTGHDN\(unit,)44 b(>)k(nhdu\))0 2554 y Fh(5)81 -b Fi(Return)39 b(the)i(t)m(yp)s(e)g(of)g(the)g(curren)m(t)f(HDU)i(in)e -(the)h(FITS)f(\014le.)71 b(The)41 b(p)s(ossible)f(v)-5 -b(alues)41 b(for)f(hdut)m(yp)s(e)g(are)227 2667 y(IMA)m(GE)p -546 2667 V 34 w(HDU)31 b(\(0\),)h(ASCI)s(I)p 1242 2667 -V 31 w(TBL)e(\(1\),)i(or)e(BINAR)-8 b(Y)p 2133 2667 V -34 w(TBL)30 b(\(2\).)382 2909 y Fe(FTGHDT\(unit,)44 b(>)k(hdutype,)d -(status\))0 3150 y Fh(6)81 b Fi(Return)29 b(the)i(total)h(n)m(um)m(b)s -(er)d(of)i(HDUs)f(in)h(the)f(FITS)g(\014le.)41 b(The)29 -b(CHDU)i(remains)f(unc)m(hanged.)382 3392 y Fe(FTTHDU\(unit,)44 -b(>)k(hdunum,)e(status\))0 3634 y Fh(7)81 b Fi(Create)34 -b(\(app)s(end\))f(a)i(new)e(empt)m(y)h(HDU)h(at)g(the)f(end)f(of)h(the) -h(FITS)e(\014le.)51 b(This)33 b(new)h(HDU)h(b)s(ecomes)f(the)227 -3747 y(Curren)m(t)j(HDU,)i(but)e(it)h(is)g(completely)h(empt)m(y)f(and) -g(con)m(tains)h(no)e(header)h(k)m(eyw)m(ords)g(or)g(data.)63 -b(It)38 b(is)227 3860 y(recommended)30 b(that)h(FTI)s(IMG,)g(FTIT)-8 -b(AB)30 b(or)h(FTIBIN)f(b)s(e)g(used)g(instead)g(of)h(this)f(routine.) -382 4101 y Fe(FTCRHD\(unit,)44 b(>)k(status\))0 4343 -y Fh(8)81 b Fi(Create)30 b(a)f(primary)f(arra)m(y)i(\(if)g(none)f -(already)g(exists\),)i(or)e(insert)g(a)h(new)f(IMA)m(GE)h(extension)g -(immediately)227 4456 y(follo)m(wing)25 b(the)e(CHDU,)g(or)g(insert)g -(a)g(new)g(Primary)f(Arra)m(y)h(at)h(the)f(b)s(eginning)f(of)h(the)g -(\014le.)38 b(An)m(y)23 b(follo)m(wing)227 4569 y(extensions)29 -b(in)g(the)g(\014le)f(will)h(b)s(e)f(shifted)h(do)m(wn)f(to)h(mak)m(e)h -(ro)s(om)e(for)h(the)g(new)f(extension.)40 b(If)29 b(the)g(CHDU)227 -4682 y(is)h(the)g(last)g(HDU)g(in)g(the)f(\014le)h(then)f(the)h(new)f -(image)i(extension)f(will)g(simply)f(b)s(e)g(app)s(ended)f(to)i(the)g -(end)227 4795 y(of)k(the)h(\014le.)52 b(One)33 b(can)h(force)h(a)g(new) -e(primary)g(arra)m(y)i(to)g(b)s(e)e(inserted)h(at)h(the)f(b)s(eginning) -f(of)h(the)h(FITS)227 4908 y(\014le)29 b(b)m(y)f(setting)i(status)e(=)h -(-9)g(prior)e(to)j(calling)g(the)e(routine.)40 b(In)28 -b(this)g(case)i(the)e(existing)i(primary)d(arra)m(y)227 -5021 y(will)f(b)s(e)f(con)m(v)m(erted)i(to)g(an)e(IMA)m(GE)h -(extension.)40 b(The)25 b(new)g(extension)i(\(or)f(primary)e(arra)m -(y\))j(will)f(b)s(ecome)227 5133 y(the)32 b(CHDU.)f(The)g(FTI)s(IMGLL)f -(routine)i(is)f(iden)m(tical)i(to)e(the)h(FTI)s(IMG)f(routine)g(except) -h(that)f(the)h(4th)227 5246 y(parameter)25 b(\(the)g(length)g(of)f(eac) -m(h)h(axis\))g(is)g(an)f(arra)m(y)h(of)f(64-bit)i(in)m(tegers)f(rather) -f(than)g(an)g(arra)m(y)h(of)g(32-bit)227 5359 y(in)m(tegers.)382 -5601 y Fe(FTIIMG\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 -b(status\))382 5714 y(FTIIMGLL\(unit,bitpix,nax)o(is,)o(naxe)o(sll,)41 -b(>)47 b(status\))p eop end -%%Page: 40 46 -TeXDict begin 40 45 bop 0 299 a Fi(40)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)0 555 y Fh(9)81 b Fi(Insert)30 b(a)i(new)f(ASCI)s(I)f -(T)-8 b(ABLE)31 b(extension)h(immediately)h(follo)m(wing)f(the)g(CHDU.) -g(An)m(y)f(follo)m(wing)i(exten-)227 668 y(sions)26 b(will)g(b)s(e)f -(shifted)g(do)m(wn)g(to)h(mak)m(e)h(ro)s(om)e(for)h(the)f(new)g -(extension.)40 b(If)25 b(there)h(are)g(no)g(other)f(follo)m(wing)227 -781 y(extensions)32 b(then)f(the)h(new)f(table)h(extension)g(will)g -(simply)f(b)s(e)g(app)s(ended)f(to)i(the)f(end)g(of)h(the)f(\014le.)44 -b(The)227 894 y(new)33 b(extension)h(will)f(b)s(ecome)h(the)f(CHDU.)h -(The)f(FTIT)-8 b(ABLL)33 b(routine)g(is)g(iden)m(tical)i(to)f(the)g -(FTIT)-8 b(AB)227 1007 y(routine)36 b(except)g(that)g(the)f(2nd)g(and)g -(3rd)g(parameters)g(\(that)i(giv)m(e)g(the)e(size)h(of)g(the)f(table\)) -i(are)f(64-bit)227 1120 y(in)m(tegers)c(rather)e(than)g(32-bit)i(in)m -(tegers.)382 1374 y Fe(FTITAB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o -(ype)o(,tbc)o(ol,t)o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 -b(>)716 1487 y(status\))382 1600 y(FTITABLL\(unit,rowlenll,n)o(row)o -(sll,)o(tfie)o(lds)o(,tty)o(pe,t)o(bco)o(l,tf)o(orm,)o(tun)o(it,e)o -(xtna)o(me,)f(>)716 1713 y(status\))0 1968 y Fh(10)46 -b Fi(Insert)25 b(a)h(new)f(binary)f(table)j(extension)f(immediately)g -(follo)m(wing)h(the)f(CHDU.)g(An)m(y)g(follo)m(wing)g(extensions)227 -2081 y(will)39 b(b)s(e)f(shifted)g(do)m(wn)g(to)h(mak)m(e)g(ro)s(om)g -(for)f(the)g(new)g(extension.)66 b(If)38 b(there)h(are)f(no)h(other)f -(follo)m(wing)227 2194 y(extensions)f(then)g(the)f(new)g(bin)m(table)h -(extension)h(will)f(simply)f(b)s(e)g(app)s(ended)e(to)k(the)e(end)g(of) -h(the)g(\014le.)227 2307 y(The)23 b(new)g(extension)h(will)f(b)s(ecome) -h(the)f(CHDU.)h(The)f(FTIBINLL)g(routine)g(is)g(iden)m(tical)i(to)f -(the)g(FTIBIN)227 2419 y(routine)30 b(except)i(that)e(the)h(2nd)e -(parameter)i(\(that)g(giv)m(es)g(the)g(length)f(of)h(the)f(table\))h -(is)g(a)f(64-bit)i(in)m(teger)227 2532 y(rather)f(than)f(a)g(32-bit)i -(in)m(teger.)382 2787 y Fe(FTIBIN\(unit,nrows,tfield)o(s,t)o(type)o -(,tfo)o(rm,)o(tuni)o(t,ex)o(tna)o(me,v)o(arid)o(at)41 -b(>)48 b(status\))382 2900 y(FTIBINLL\(unit,nrowsll,tf)o(iel)o(ds,t)o -(type)o(,tf)o(orm,)o(tuni)o(t,e)o(xtna)o(me,v)o(ari)o(dat)41 -b(>)48 b(status\))0 3267 y Fh(11)e Fi(Resize)26 b(an)e(image)i(b)m(y)e -(mo)s(di\014ng)f(the)i(size,)i(dimensions,)e(and/or)f(datat)m(yp)s(e)h -(of)g(the)g(curren)m(t)f(primary)f(arra)m(y)227 3380 -y(or)29 b(image)i(extension.)40 b(If)29 b(the)g(new)g(image,)i(as)e(sp) -s(eci\014ed)f(b)m(y)h(the)g(input)f(argumen)m(ts,)i(is)f(larger)h(than) -f(the)227 3493 y(curren)m(t)34 b(existing)h(image)g(in)f(the)g(FITS)f -(\014le)h(then)f(zero)i(\014ll)f(data)h(will)f(b)s(e)f(inserted)h(at)g -(the)g(end)g(of)g(the)227 3606 y(curren)m(t)25 b(image)h(and)e(an)m(y)i -(follo)m(wing)g(extensions)g(will)f(b)s(e)f(mo)m(v)m(ed)i(further)e -(bac)m(k)h(in)g(the)g(\014le.)39 b(Similarly)-8 b(,)27 -b(if)227 3719 y(the)h(new)e(image)j(is)e(smaller)h(than)f(the)g(curren) -m(t)g(image)h(then)f(an)m(y)h(follo)m(wing)h(extensions)e(will)h(b)s(e) -e(shifted)227 3832 y(up)32 b(to)m(w)m(ards)i(the)g(b)s(eginning)e(of)h -(the)h(FITS)e(\014le)h(and)g(the)g(image)h(data)g(will)g(b)s(e)e -(truncated)h(to)h(the)f(new)227 3945 y(size.)41 b(This)25 -b(routine)h(rewrites)h(the)f(BITPIX,)h(NAXIS,)f(and)g(NAXISn)g(k)m(eyw) -m(ords)g(with)g(the)h(appropriate)227 4058 y(v)-5 b(alues)37 -b(for)f(new)h(image.)60 b(The)36 b(FTRSIMLL)g(routine)g(is)h(iden)m -(tical)h(to)g(the)e(FTRSIM)g(routine)h(except)227 4171 -y(that)30 b(the)g(4th)g(parameter)g(\(the)g(length)g(of)f(eac)m(h)i -(axis\))f(is)g(an)f(arra)m(y)h(of)g(64-bit)h(in)m(tegers)f(rather)g -(than)f(an)227 4284 y(arra)m(y)i(of)g(32-bit)g(in)m(tegers.)382 -4538 y Fe(FTRSIM\(unit,bitpix,naxis)o(,na)o(xes,)o(stat)o(us\))382 -4651 y(FTRSIMLL\(unit,bitpix,nax)o(is,)o(naxe)o(sll,)o(sta)o(tus\))0 -4906 y Fh(12)46 b Fi(Delete)34 b(the)f(CHDU)g(in)f(the)g(FITS)f -(\014le.)47 b(An)m(y)32 b(follo)m(wing)i(HDUs)f(will)g(b)s(e)e(shifted) -h(forw)m(ard)g(in)g(the)g(\014le,)h(to)227 5019 y(\014ll)38 -b(in)f(the)g(gap)h(created)g(b)m(y)g(the)f(deleted)h(HDU.)h(In)d(the)i -(case)g(of)g(deleting)g(the)g(primary)e(arra)m(y)i(\(the)227 -5132 y(\014rst)30 b(HDU)h(in)f(the)h(\014le\))g(then)f(the)h(curren)m -(t)f(primary)f(arra)m(y)i(will)g(b)s(e)f(replace)h(b)m(y)g(a)g(n)m(ull) -f(primary)f(arra)m(y)227 5245 y(con)m(taining)k(the)f(minim)m(um)e(set) -i(of)g(required)e(k)m(eyw)m(ords)i(and)e(no)i(data.)44 -b(If)31 b(there)g(are)h(more)f(extensions)227 5357 y(in)f(the)g(\014le) -g(follo)m(wing)i(the)e(one)g(that)h(is)f(deleted,)h(then)f(the)g(the)g -(CHDU)h(will)f(b)s(e)g(rede\014ned)e(to)j(p)s(oin)m(t)f(to)227 -5470 y(the)d(follo)m(wing)h(extension.)41 b(If)26 b(there)h(are)g(no)g -(follo)m(wing)h(extensions)f(then)g(the)g(CHDU)g(will)g(b)s(e)f -(rede\014ned)227 5583 y(to)35 b(p)s(oin)m(t)f(to)h(the)f(previous)f -(HDU.)i(The)e(output)h(HDUTYPE)g(parameter)h(indicates)f(the)h(t)m(yp)s -(e)f(of)g(the)227 5696 y(new)c(CHDU)h(after)g(the)f(previous)g(CHDU)h -(has)f(b)s(een)g(deleted.)p eop end -%%Page: 41 47 -TeXDict begin 41 46 bop 0 299 a Fg(6.3.)72 b(DEFINE)31 -b(OR)f(REDEFINE)h(THE)f(STR)m(UCTURE)f(OF)h(THE)g(CHDU)1042 -b Fi(41)382 555 y Fe(FTDHDU\(unit,)44 b(>)k(hdutype,status\))0 -828 y Fh(13)e Fi(Cop)m(y)36 b(all)h(or)f(part)g(of)g(the)g(input)f -(FITS)g(\014le)h(and)g(app)s(end)e(it)i(to)h(the)f(end)g(of)g(the)g -(output)g(FITS)f(\014le.)57 b(If)227 941 y('previous')39 -b(\(an)g(in)m(teger)h(parameter\))g(is)f(not)g(equal)g(to)h(0,)h(then)e -(an)m(y)g(HDUs)g(preceding)g(the)g(curren)m(t)227 1054 -y(HDU)f(in)e(the)h(input)e(\014le)i(will)g(b)s(e)f(copied)h(to)g(the)g -(output)f(\014le.)60 b(Similarly)-8 b(,)39 b('curren)m(t')e(and)f -('follo)m(wing')227 1167 y(determine)j(whether)f(the)h(curren)m(t)g -(HDU,)h(and/or)e(an)m(y)i(follo)m(wing)g(HDUs)f(in)g(the)g(input)f -(\014le)g(will)i(b)s(e)227 1280 y(copied)32 b(to)g(the)g(output)f -(\014le.)43 b(If)31 b(all)h(3)g(parameters)g(are)g(not)f(equal)h(to)g -(zero,)h(then)e(the)g(en)m(tire)h(input)f(\014le)227 -1393 y(will)g(b)s(e)e(copied.)41 b(On)30 b(return,)f(the)h(curren)m(t)g -(HDU)h(in)f(the)g(input)f(\014le)h(will)h(b)s(e)e(unc)m(hanged,)h(and)g -(the)g(last)227 1506 y(copied)h(HDU)g(will)g(b)s(e)f(the)g(curren)m(t)g -(HDU)i(in)e(the)g(output)g(\014le.)382 1779 y Fe(FTCPFL\(iunit,)44 -b(ounit,)i(previous,)f(current,)h(following,)f(>)i(status\))0 -2052 y Fh(14)f Fi(Cop)m(y)35 b(the)f(en)m(tire)i(CHDU)f(from)f(the)g -(FITS)g(\014le)h(asso)s(ciated)h(with)e(IUNIT)g(to)i(the)e(CHDU)h(of)g -(the)g(FITS)227 2165 y(\014le)g(asso)s(ciated)h(with)e(OUNIT.)g(The)g -(output)g(HDU)h(m)m(ust)f(b)s(e)g(empt)m(y)h(and)e(not)i(already)g(con) -m(tain)h(an)m(y)227 2278 y(k)m(eyw)m(ords.)41 b(Space)29 -b(will)g(b)s(e)g(reserv)m(ed)g(for)g(MOREKEYS)f(additional)h(k)m(eyw)m -(ords)h(in)e(the)i(output)e(header)227 2391 y(if)j(there)f(is)h(not)f -(already)h(enough)f(space.)382 2664 y Fe(FTCOPY\(iunit,ounit,morek)o -(eys)o(,)42 b(>)47 b(status\))0 2937 y Fh(15)f Fi(Cop)m(y)27 -b(the)h(header)f(\(and)g(not)g(the)g(data\))i(from)d(the)i(CHDU)g(asso) -s(ciated)g(with)f(in)m(unit)g(to)h(the)f(CHDU)h(asso-)227 -3050 y(ciated)f(with)e(outunit.)39 b(If)25 b(the)g(curren)m(t)h(output) -f(HDU)h(is)f(not)h(completely)h(empt)m(y)-8 b(,)27 b(then)e(the)h(CHDU) -g(will)227 3163 y(b)s(e)e(closed)i(and)e(a)i(new)e(HDU)h(will)h(b)s(e)e -(app)s(ended)f(to)j(the)f(output)f(\014le.)39 b(This)24 -b(routine)h(will)g(automatically)227 3276 y(transform)31 -b(the)g(necessary)h(k)m(eyw)m(ords)f(when)g(cop)m(ying)h(a)f(primary)g -(arra)m(y)h(to)f(and)g(image)i(extension,)f(or)227 3389 -y(an)27 b(image)h(extension)f(to)g(a)h(primary)d(arra)m(y)-8 -b(.)41 b(An)26 b(empt)m(y)h(output)f(data)i(unit)e(will)h(b)s(e)f -(created)i(\(all)g(v)-5 b(alues)227 3501 y(=)30 b(0\).)382 -3775 y Fe(FTCPHD\(inunit,)44 b(outunit,)h(>)j(status\))0 -4048 y Fh(16)e Fi(Cop)m(y)d(just)g(the)g(data)h(from)f(the)g(CHDU)h -(asso)s(ciated)g(with)f(IUNIT)g(to)h(the)f(CHDU)h(asso)s(ciated)g(with) -227 4161 y(OUNIT.)26 b(This)f(will)h(o)m(v)m(erwrite)h(an)m(y)f(data)g -(previously)g(in)f(the)h(OUNIT)f(CHDU.)h(This)f(lo)m(w)i(lev)m(el)g -(routine)227 4274 y(is)g(used)e(b)m(y)i(FTCOPY,)f(but)g(it)g(ma)m(y)i -(also)f(b)s(e)f(useful)f(in)i(certain)g(application)h(programs)e(whic)m -(h)g(w)m(an)m(t)h(to)227 4386 y(cop)m(y)j(the)f(data)h(from)f(one)g -(FITS)f(\014le)h(to)h(another)f(but)g(also)h(w)m(an)m(t)g(to)g(mo)s -(dify)e(the)h(header)g(k)m(eyw)m(ords)g(in)227 4499 y(the)j(pro)s -(cess.)44 b(all)33 b(the)f(required)f(header)g(k)m(eyw)m(ords)h(m)m -(ust)g(b)s(e)f(written)h(to)g(the)g(OUNIT)f(CHDU)h(b)s(efore)227 -4612 y(calling)g(this)e(routine)382 4885 y Fe(FTCPDT\(iunit,ounit,)42 -b(>)48 b(status\))0 5235 y Fd(6.3)135 b(De\014ne)45 b(or)g(Rede\014ne)h -(the)f(structure)g(of)g(the)g(CHDU)0 5488 y Fi(It)32 -b(should)f(rarely)h(b)s(e)g(necessary)g(to)h(call)g(the)f(subroutines)f -(in)g(this)h(section.)47 b(FITSIO)30 b(in)m(ternally)j(calls)g(these)0 -5601 y(routines)h(whenev)m(er)g(necessary)-8 b(,)36 b(so)e(an)m(y)g -(calls)h(to)g(these)f(routines)g(b)m(y)g(application)h(programs)f(will) -g(lik)m(ely)i(b)s(e)0 5714 y(redundan)m(t.)p eop end -%%Page: 42 48 -TeXDict begin 42 47 bop 0 299 a Fi(42)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)0 555 y Fh(1)81 b Fi(This)36 b(routine)h(forces)h -(FITSIO)e(to)i(scan)f(the)g(curren)m(t)g(header)g(k)m(eyw)m(ords)h -(that)f(de\014ne)g(the)g(structure)g(of)227 668 y(the)31 -b(HDU)f(\(suc)m(h)g(as)h(the)f(NAXISn,)g(PCOUNT)f(and)g(GCOUNT)h(k)m -(eyw)m(ords\))h(so)f(that)h(it)f(can)h(initialize)227 -781 y(the)36 b(in)m(ternal)g(bu\013ers)e(that)i(describ)s(e)f(the)h -(HDU)g(structure.)55 b(This)35 b(routine)h(ma)m(y)g(b)s(e)e(used)h -(instead)h(of)227 894 y(the)j(more)g(complicated)i(calls)f(to)f(ftp)s -(def,)h(ftadef)f(or)g(ftb)s(def.)65 b(This)38 b(routine)h(is)g(also)h -(v)m(ery)f(useful)f(for)227 1007 y(reinitializing)e(the)e(structure)g -(of)g(an)f(HDU,)i(if)f(the)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(in)g(a)g -(table,)i(as)e(sp)s(eci\014ed)f(b)m(y)h(the)227 1120 -y(NAXIS2)d(k)m(eyw)m(ord,)g(has)f(b)s(een)g(mo)s(di\014ed)f(from)h(its) -h(initial)g(v)-5 b(alue.)382 1361 y Fe(FTRDEF\(unit,)44 -b(>)k(status\))141 b(\(DEPRECATED\))0 1602 y Fh(2)81 -b Fi(De\014ne)27 b(the)g(structure)g(of)g(the)g(primary)f(arra)m(y)i -(or)f(IMA)m(GE)h(extension.)40 b(When)27 b(writing)g(GR)m(OUP)m(ed)h -(FITS)227 1715 y(\014les)43 b(that)h(b)m(y)e(con)m(v)m(en)m(tion)k(set) -d(the)g(NAXIS1)g(k)m(eyw)m(ord)h(equal)f(to)h(0,)i(ftp)s(def)c(m)m(ust) -h(b)s(e)f(called)i(with)227 1828 y(naxes\(1\))27 b(=)e(1,)i(NOT)e(0,)i -(otherwise)f(FITSIO)e(will)i(rep)s(ort)f(an)g(error)g(status=308)i -(when)d(trying)i(to)g(write)227 1941 y(data)31 b(to)g(a)g(group.)40 -b(Note:)i(it)31 b(is)g(usually)f(simpler)g(to)h(call)h(FTRDEF)e(rather) -h(than)f(this)g(routine.)382 2182 y Fe(FTPDEF\(unit,bitpix,naxis)o(,na) -o(xes,)o(pcou)o(nt,)o(gcou)o(nt,)41 b(>)48 b(status\))93 -b(\(DEPRECATED\))0 2424 y Fh(3)81 b Fi(De\014ne)32 b(the)h(structure)f -(of)g(an)h(ASCI)s(I)e(table)i(\(T)-8 b(ABLE\))33 b(extension.)48 -b(Note:)e(it)33 b(is)f(usually)g(simpler)g(to)i(call)227 -2537 y(FTRDEF)d(rather)f(than)h(this)f(routine.)382 2778 -y Fe(FTADEF\(unit,rowlen,tfiel)o(ds,)o(tbco)o(l,tf)o(orm)o(,nro)o(ws)42 -b(>)47 b(status\))f(\(DEPRECATED\))0 3019 y Fh(4)81 b -Fi(De\014ne)35 b(the)h(structure)f(of)g(a)h(binary)f(table)h(\(BINT)-8 -b(ABLE\))37 b(extension.)56 b(Note:)d(it)36 b(is)f(usually)g(simpler)g -(to)227 3132 y(call)d(FTRDEF)f(rather)f(than)g(this)g(routine.)382 -3373 y Fe(FTBDEF\(unit,tfields,tfor)o(m,v)o(arid)o(at,n)o(row)o(s)42 -b(>)47 b(status\))f(\(DEPRECATED\))0 3615 y Fh(5)81 b -Fi(De\014ne)34 b(the)g(size)h(of)f(the)g(Curren)m(t)f(Data)i(Unit,)h(o) -m(v)m(erriding)e(the)g(length)h(of)f(the)g(data)h(unit)e(as)h -(previously)227 3728 y(de\014ned)e(b)m(y)h(ftp)s(def,)g(ftadef,)i(or)e -(ftb)s(def.)48 b(This)33 b(is)g(useful)f(if)i(one)f(do)s(es)g(not)h -(kno)m(w)f(the)g(total)i(size)f(of)g(the)227 3841 y(data)f(unit)f(un)m -(til)h(after)f(the)h(data)g(ha)m(v)m(e)g(b)s(een)f(written.)46 -b(The)32 b(size)h(\(in)f(b)m(ytes\))h(of)g(an)f(ASCI)s(I)f(or)h(Binary) -227 3954 y(table)27 b(is)f(giv)m(en)g(b)m(y)g(NAXIS1)g(*)g(NAXIS2.)40 -b(\(Note)27 b(that)f(to)h(determine)f(the)f(v)-5 b(alue)27 -b(of)f(NAXIS1)f(it)i(is)f(often)227 4066 y(more)32 b(con)m(v)m(enien)m -(t)h(to)f(read)f(the)g(v)-5 b(alue)32 b(of)f(the)h(NAXIS1)f(k)m(eyw)m -(ord)h(from)e(the)i(output)e(\014le,)i(rather)f(than)227 -4179 y(computing)f(the)g(ro)m(w)g(length)h(directly)f(from)f(all)i(the) -f(TF)m(ORM)h(k)m(eyw)m(ord)f(v)-5 b(alues\).)41 b(Note:)h(it)30 -b(is)g(usually)227 4292 y(simpler)g(to)h(call)h(FTRDEF)f(rather)f(than) -g(this)g(routine.)382 4534 y Fe(FTDDEF\(unit,bytlen,)42 -b(>)48 b(status\))e(\(DEPRECATED\))0 4775 y Fh(6)81 b -Fi(De\014ne)22 b(the)g(zero)i(indexed)d(b)m(yte)i(o\013set)g(of)g(the)f -('heap')h(measured)e(from)h(the)h(start)g(of)f(the)g(binary)g(table)h -(data.)227 4888 y(By)30 b(default)g(the)f(heap)h(is)f(assumed)g(to)h -(start)g(immediately)h(follo)m(wing)g(the)f(regular)f(table)i(data,)f -(i.e.,)h(at)227 5001 y(lo)s(cation)38 b(NAXIS1)f(x)g(NAXIS2.)59 -b(This)36 b(routine)g(is)h(only)f(relev)-5 b(an)m(t)38 -b(for)e(binary)g(tables)h(whic)m(h)g(con)m(tain)227 5114 -y(v)-5 b(ariable)36 b(length)g(arra)m(y)f(columns)g(\(with)h(TF)m(ORMn) -f(=)f('Pt'\).)57 b(This)34 b(subroutine)g(also)i(automatically)227 -5227 y(writes)23 b(the)g(v)-5 b(alue)23 b(of)g(theap)g(to)h(a)f(k)m -(eyw)m(ord)g(in)g(the)g(extension)g(header.)38 b(This)22 -b(subroutine)g(m)m(ust)h(b)s(e)f(called)227 5339 y(after)27 -b(the)f(required)f(k)m(eyw)m(ords)i(ha)m(v)m(e)g(b)s(een)e(written)h -(\(with)g(ftph)m(bn\))f(and)h(after)g(the)h(table)g(structure)e(has)227 -5452 y(b)s(een)30 b(de\014ned)f(\(with)h(ftb)s(def)7 -b(\))30 b(but)g(b)s(efore)g(an)m(y)g(data)h(is)g(written)f(to)h(the)g -(table.)382 5694 y Fe(FTPTHP\(unit,theap,)43 b(>)k(status\))p -eop end -%%Page: 43 49 -TeXDict begin 43 48 bop 0 299 a Fg(6.4.)72 b(FITS)30 -b(HEADER)h(I/O)f(SUBR)m(OUTINES)2086 b Fi(43)0 555 y -Fd(6.4)135 b(FITS)44 b(Header)i(I/O)f(Subroutines)0 809 -y Fb(6.4.1)112 b(Header)38 b(Space)h(and)f(P)m(osition)f(Routines)0 -1019 y Fh(1)81 b Fi(Reserv)m(e)37 b(space)g(in)f(the)h(CHU)f(for)h -(MOREKEYS)e(more)i(header)f(k)m(eyw)m(ords.)59 b(This)36 -b(subroutine)f(ma)m(y)j(b)s(e)227 1132 y(called)e(to)g(reserv)m(e)g -(space)f(for)g(k)m(eyw)m(ords)g(whic)m(h)g(are)g(to)h(b)s(e)e(written)h -(at)g(a)h(later)g(time,)h(after)e(the)g(data)227 1245 -y(unit)h(or)g(subsequen)m(t)f(extensions)h(ha)m(v)m(e)h(b)s(een)e -(written)h(to)h(the)f(FITS)f(\014le.)58 b(If)35 b(this)h(subroutine)f -(is)h(not)227 1358 y(explicitly)29 b(called,)g(then)e(the)g(initial)i -(size)e(of)h(the)f(FITS)f(header)h(will)h(b)s(e)e(limited)i(to)g(the)f -(space)h(a)m(v)-5 b(ailable)227 1471 y(at)24 b(the)g(time)g(that)g(the) -g(\014rst)f(data)h(is)g(written)f(to)h(the)g(asso)s(ciated)h(data)f -(unit.)38 b(FITSIO)22 b(has)i(the)f(abilit)m(y)i(to)227 -1584 y(dynamically)g(add)e(more)h(space)h(to)g(the)f(header)g(if)g -(needed,)h(ho)m(w)m(ev)m(er)g(it)g(is)f(more)g(e\016cien)m(t)h(to)g -(preallo)s(cate)227 1697 y(the)31 b(required)e(space)i(if)g(the)f(size) -h(is)g(kno)m(wn)f(in)g(adv)-5 b(ance.)382 1958 y Fe -(FTHDEF\(unit,morekeys,)42 b(>)47 b(status\))0 2219 y -Fh(2)81 b Fi(Return)23 b(the)i(n)m(um)m(b)s(er)e(of)h(existing)i(k)m -(eyw)m(ords)e(in)h(the)f(CHU)g(\(NOT)h(including)f(the)g(END)h(k)m(eyw) -m(ord)g(whic)m(h)f(is)227 2332 y(not)g(considered)f(a)g(real)h(k)m(eyw) -m(ord\))g(and)f(the)g(remaining)h(space)f(a)m(v)-5 b(ailable)26 -b(to)e(write)f(additional)i(k)m(eyw)m(ords)227 2445 y(in)39 -b(the)h(CHU.)f(\(returns)f(KEYSADD)i(=)f(-1)h(if)f(the)g(header)g(has)g -(not)h(y)m(et)g(b)s(een)e(closed\).)69 b(Note)40 b(that)227 -2558 y(FITSIO)23 b(will)i(attempt)g(to)g(dynamically)g(add)e(space)i -(for)f(more)g(k)m(eyw)m(ords)h(if)f(required)f(when)g(app)s(ending)227 -2671 y(new)30 b(k)m(eyw)m(ords)h(to)g(a)g(header.)382 -2932 y Fe(FTGHSP\(iunit,)44 b(>)j(keysexist,keysadd,status\))0 -3194 y Fh(3)81 b Fi(Return)38 b(the)i(n)m(um)m(b)s(er)e(of)h(k)m(eyw)m -(ords)h(in)f(the)g(header)g(and)g(the)g(curren)m(t)h(p)s(osition)f(in)g -(the)g(header.)68 b(This)227 3307 y(returns)37 b(the)g(n)m(um)m(b)s(er) -f(of)i(the)g(k)m(eyw)m(ord)g(record)f(that)h(will)g(b)s(e)f(read)g -(next)h(\(or)g(one)g(greater)g(than)g(the)227 3420 y(p)s(osition)29 -b(of)f(the)h(last)g(k)m(eyw)m(ord)g(that)g(w)m(as)f(read)g(or)h -(written\).)40 b(A)29 b(v)-5 b(alue)28 b(of)h(1)g(is)f(returned)f(if)h -(the)h(p)s(oin)m(ter)227 3533 y(is)i(p)s(ositioned)f(at)h(the)g(b)s -(eginning)e(of)i(the)g(header.)382 3794 y Fe(FTGHPS\(iunit,)44 -b(>)j(keysexist,key_no,status\))0 4086 y Fb(6.4.2)112 -b(Read)38 b(or)f(W)-9 b(rite)37 b(Standard)i(Header)e(Routines)0 -4306 y Fi(These)31 b(subroutines)e(pro)m(vide)i(a)g(simple)g(metho)s(d) -f(of)h(reading)g(or)g(writing)g(most)g(of)g(the)g(k)m(eyw)m(ord)g(v)-5 -b(alues)31 b(that)0 4419 y(are)d(normally)g(required)f(in)h(a)g(FITS)f -(\014les.)40 b(These)27 b(subroutines)g(are)h(pro)m(vided)f(for)h(con)m -(v)m(enience)h(only)f(and)g(are)0 4532 y(not)36 b(required)e(to)i(b)s -(e)f(used.)55 b(If)35 b(preferred,)h(users)e(ma)m(y)i(call)h(the)f(lo)m -(w)m(er-lev)m(el)i(subroutines)c(describ)s(ed)h(in)g(the)0 -4644 y(previous)30 b(section)i(to)g(individually)f(read)f(or)h(write)g -(the)g(required)f(k)m(eyw)m(ords.)43 b(Note)32 b(that)g(in)e(most)i -(cases,)g(the)0 4757 y(required)26 b(k)m(eyw)m(ords)h(suc)m(h)g(as)g -(NAXIS,)f(TFIELD,)h(TTYPEn,)g(etc,)i(whic)m(h)d(de\014ne)g(the)h -(structure)f(of)h(the)g(HDU)0 4870 y(m)m(ust)j(b)s(e)g(written)g(to)i -(the)e(header)g(b)s(efore)g(an)m(y)h(data)g(can)g(b)s(e)e(written)i(to) -g(the)g(image)g(or)g(table.)0 5132 y Fh(1)81 b Fi(Put)37 -b(the)i(primary)e(header)h(or)g(IMA)m(GE)h(extension)f(k)m(eyw)m(ords)h -(in)m(to)g(the)f(CHU.)g(There)g(are)g(2)h(a)m(v)-5 b(ailable)227 -5245 y(routines:)39 b(The)27 b(simpler)f(FTPHPS)h(routine)g(is)g(equiv) --5 b(alen)m(t)29 b(to)e(calling)i(ftphpr)c(with)i(the)g(default)h(v)-5 -b(alues)227 5357 y(of)35 b(SIMPLE)f(=)g(true,)i(p)s(coun)m(t)e(=)g(0,)i -(gcoun)m(t)g(=)e(1,)i(and)e(EXTEND)h(=)f(true.)53 b(PCOUNT,)34 -b(GCOUNT)227 5470 y(and)23 b(EXTEND)h(k)m(eyw)m(ords)g(are)h(not)f -(required)f(in)g(the)h(primary)f(header)g(and)h(are)g(only)g(written)g -(if)f(p)s(coun)m(t)227 5583 y(is)31 b(not)g(equal)h(to)g(zero,)g(gcoun) -m(t)g(is)f(not)g(equal)g(to)h(zero)g(or)f(one,)g(and)g(if)g(extend)g -(is)g(TR)m(UE,)g(resp)s(ectiv)m(ely)-8 b(.)227 5696 y(When)30 -b(writing)h(to)g(an)f(IMA)m(GE)i(extension,)f(the)f(SIMPLE)g(and)g -(EXTEND)g(parameters)h(are)g(ignored.)p eop end -%%Page: 44 50 -TeXDict begin 44 49 bop 0 299 a Fi(44)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)382 555 y Fe(FTPHPS\(unit,bitpix,naxis)o(,na)o(xes,)41 -b(>)48 b(status\))382 781 y(FTPHPR\(unit,simple,bitpi)o(x,n)o(axis)o -(,nax)o(es,)o(pcou)o(nt,g)o(cou)o(nt,e)o(xten)o(d,)41 -b(>)48 b(status\))0 1082 y Fh(2)81 b Fi(Get)44 b(primary)e(header)h(or) -h(IMA)m(GE)g(extension)g(k)m(eyw)m(ords)g(from)f(the)g(CHU.)h(When)f -(reading)g(from)g(an)227 1195 y(IMA)m(GE)32 b(extension)f(the)f(SIMPLE) -g(and)f(EXTEND)i(parameters)g(are)f(ignored.)382 1495 -y Fe(FTGHPR\(unit,maxdim,)42 b(>)48 b(simple,bitpix,naxis,naxe)o(s,p)o -(coun)o(t,gc)o(oun)o(t,ex)o(tend)o(,)716 1608 y(status\))0 -1909 y Fh(3)81 b Fi(Put)34 b(the)h(ASCI)s(I)f(table)i(header)f(k)m(eyw) -m(ords)g(in)m(to)h(the)f(CHU.)h(The)e(optional)i(TUNITn)e(and)h -(EXTNAME)227 2021 y(k)m(eyw)m(ords)c(are)g(written)f(only)h(if)f(the)h -(input)e(string)h(v)-5 b(alues)31 b(are)g(not)f(blank.)382 -2322 y Fe(FTPHTB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o(ype)o(,tbc)o -(ol,t)o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 -2435 y(status\))0 2736 y Fh(4)81 b Fi(Get)31 b(the)g(ASCI)s(I)d(table)k -(header)e(k)m(eyw)m(ords)h(from)e(the)i(CHU)382 3036 -y Fe(FTGHTB\(unit,maxdim,)42 b(>)48 b(rowlen,nrows,tfields,tty)o(pe,)o -(tbco)o(l,tf)o(orm)o(,tun)o(it,)716 3149 y(extname,status\))0 -3450 y Fh(5)81 b Fi(Put)34 b(the)h(binary)f(table)i(header)e(k)m(eyw)m -(ords)i(in)m(to)f(the)g(CHU.)g(The)g(optional)h(TUNITn)e(and)g(EXTNAME) -227 3563 y(k)m(eyw)m(ords)i(are)g(written)f(only)g(if)h(the)f(input)f -(string)i(v)-5 b(alues)35 b(are)h(not)f(blank.)55 b(The)35 -b(p)s(coun)m(t)g(parameter,)227 3675 y(whic)m(h)f(sp)s(eci\014es)g(the) -h(size)g(of)g(the)f(v)-5 b(ariable)35 b(length)g(arra)m(y)g(heap,)g -(should)f(initially)h(=)f(0;)j(FITSIO)d(will)227 3788 -y(automatically)27 b(up)s(date)c(the)h(PCOUNT)f(k)m(eyw)m(ord)h(v)-5 -b(alue)24 b(if)g(an)m(y)g(v)-5 b(ariable)25 b(length)f(arra)m(y)h(data) -f(is)g(written)227 3901 y(to)31 b(the)e(heap.)41 b(The)29 -b(TF)m(ORM)g(k)m(eyw)m(ord)h(v)-5 b(alue)30 b(for)g(v)-5 -b(ariable)30 b(length)g(v)m(ector)h(columns)e(should)g(ha)m(v)m(e)i -(the)227 4014 y(form)c('Pt\(len\)')j(or)d('1Pt\(len\)')j(where)d(`t')h -(is)g(the)g(data)g(t)m(yp)s(e)g(co)s(de)f(letter)i(\(A,I,J,E,D,)g -(etc.\))42 b(and)27 b(`len')h(is)227 4127 y(an)g(in)m(teger)i(sp)s -(ecifying)e(the)g(maxim)m(um)g(length)g(of)h(the)f(v)m(ectors)h(in)f -(that)h(column)f(\(len)g(m)m(ust)g(b)s(e)g(greater)227 -4240 y(than)j(or)h(equal)f(to)i(the)e(longest)i(v)m(ector)f(in)f(the)h -(column\).)44 b(If)30 b(`len')i(is)g(not)f(sp)s(eci\014ed)g(when)f(the) -i(table)g(is)227 4353 y(created)27 b(\(e.g.,)i(the)d(input)f(TF)m(ORMn) -h(v)-5 b(alue)26 b(is)g(just)f('1Pt'\))j(then)d(FITSIO)g(will)h(scan)g -(the)g(column)g(when)227 4466 y(the)k(table)g(is)f(\014rst)g(closed)h -(and)f(will)g(app)s(end)f(the)h(maxim)m(um)h(length)f(to)h(the)g(TF)m -(ORM)f(k)m(eyw)m(ord)h(v)-5 b(alue.)227 4579 y(Note)28 -b(that)e(if)g(the)g(table)h(is)f(subsequen)m(tly)g(mo)s(di\014ed)f(to)i -(increase)f(the)h(maxim)m(um)f(length)g(of)g(the)g(v)m(ectors)227 -4692 y(then)k(the)h(mo)s(difying)f(program)g(is)g(resp)s(onsible)g(for) -g(also)h(up)s(dating)e(the)i(TF)m(ORM)g(k)m(eyw)m(ord)g(v)-5 -b(alue.)382 4992 y Fe(FTPHBN\(unit,nrows,tfield)o(s,t)o(type)o(,tfo)o -(rm,)o(tuni)o(t,ex)o(tna)o(me,v)o(arid)o(at,)41 b(>)48 -b(status\))0 5293 y Fh(6)81 b Fi(Get)31 b(the)g(binary)e(table)i -(header)g(k)m(eyw)m(ords)f(from)g(the)h(CHU)382 5593 -y Fe(FTGHBN\(unit,maxdim,)42 b(>)48 b(nrows,tfields,ttype,tfor)o(m,t)o -(unit)o(,ext)o(nam)o(e,va)o(rida)o(t,)716 5706 y(status\))p -eop end -%%Page: 45 51 -TeXDict begin 45 50 bop 0 299 a Fg(6.4.)72 b(FITS)30 -b(HEADER)h(I/O)f(SUBR)m(OUTINES)2086 b Fi(45)0 555 y -Fb(6.4.3)112 b(W)-9 b(rite)37 b(Keyw)m(ord)g(Subroutines)0 -764 y Fh(1)81 b Fi(Put)30 b(\(app)s(end\))f(an)h(80-c)m(haracter)j -(record)e(in)m(to)g(the)g(CHU.)382 1020 y Fe(FTPREC\(unit,card,)43 -b(>)k(status\))0 1276 y Fh(2)81 b Fi(Put)36 b(\(app)s(end\))g(a)i -(COMMENT)f(k)m(eyw)m(ord)g(in)m(to)h(the)g(CHU.)f(Multiple)h(COMMENT)f -(k)m(eyw)m(ords)g(will)h(b)s(e)227 1389 y(written)31 -b(if)f(the)h(input)e(commen)m(t)i(string)g(is)f(longer)h(than)f(72)i(c) -m(haracters.)382 1645 y Fe(FTPCOM\(unit,comment,)42 b(>)48 -b(status\))0 1901 y Fh(3)81 b Fi(Put)24 b(\(app)s(end\))g(a)h(HISTOR)-8 -b(Y)25 b(k)m(eyw)m(ord)g(in)m(to)h(the)f(CHU.)g(Multiple)h(HISTOR)-8 -b(Y)24 b(k)m(eyw)m(ords)h(will)h(b)s(e)e(written)227 -2014 y(if)31 b(the)f(input)g(history)g(string)g(is)h(longer)g(than)f -(72)h(c)m(haracters.)382 2270 y Fe(FTPHIS\(unit,history,)42 -b(>)48 b(status\))0 2526 y Fh(4)81 b Fi(Put)36 b(\(app)s(end\))f(the)h -(D)m(A)-8 b(TE)38 b(k)m(eyw)m(ord)f(in)m(to)g(the)f(CHU.)h(The)f(k)m -(eyw)m(ord)g(v)-5 b(alue)37 b(will)g(con)m(tain)h(the)e(curren)m(t)227 -2639 y(system)c(date)g(as)g(a)f(c)m(haracter)i(string)f(in)f -('dd/mm/yy')g(format.)44 b(If)31 b(a)h(D)m(A)-8 b(TE)32 -b(k)m(eyw)m(ord)g(already)g(exists)227 2752 y(in)j(the)g(header,)i -(then)d(this)h(subroutine)f(will)i(simply)e(up)s(date)h(the)g(k)m(eyw)m -(ord)g(v)-5 b(alue)36 b(in-place)g(with)f(the)227 2865 -y(curren)m(t)30 b(date.)382 3121 y Fe(FTPDAT\(unit,)44 -b(>)k(status\))0 3377 y Fh(5)81 b Fi(Put)22 b(\(app)s(end\))f(a)i(new)f -(k)m(eyw)m(ord)h(of)g(the)f(appropriate)h(datat)m(yp)s(e)g(in)m(to)h -(the)e(CHU.)h(Note)h(that)f(FTPKYS)f(will)227 3490 y(only)33 -b(write)g(string)f(v)-5 b(alues)33 b(up)e(to)j(68)f(c)m(haracters)h(in) -e(length;)i(longer)f(strings)g(will)f(b)s(e)g(truncated.)47 -b(The)227 3603 y(FTPKLS)27 b(routine)h(can)h(b)s(e)f(used)f(to)i(write) -f(longer)h(strings,)g(using)e(a)i(non-standard)e(FITS)h(con)m(v)m(en)m -(tion.)227 3716 y(The)23 b(E)h(and)f(D)h(v)m(ersions)g(of)g(this)f -(routine)h(ha)m(v)m(e)h(the)f(added)f(feature)h(that)g(if)g(the)g -('decimals')h(parameter)f(is)227 3829 y(negativ)m(e,)i(then)20 -b(the)i('G')g(displa)m(y)f(format)g(rather)g(then)g(the)g('E')h(format) -f(will)h(b)s(e)e(used)g(when)g(constructing)227 3942 -y(the)25 b(k)m(eyw)m(ord)f(v)-5 b(alue,)26 b(taking)f(the)g(absolute)g -(v)-5 b(alue)24 b(of)h('decimals')g(for)f(the)g(precision.)39 -b(This)23 b(will)i(suppress)227 4055 y(trailing)35 b(zeros,)h(and)d -(will)i(use)e(a)i(\014xed)e(format)h(rather)g(than)f(an)h(exp)s(onen)m -(tial)h(format,)h(dep)s(ending)c(on)227 4168 y(the)f(magnitude)f(of)h -(the)f(v)-5 b(alue.)382 4424 y Fe(FTPKY[JKLS]\(unit,keyword)o(,ke)o -(yval)o(,com)o(men)o(t,)42 b(>)47 b(status\))382 4537 -y(FTPKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o(omme)o -(nt,)41 b(>)48 b(status\))0 4793 y Fh(6)81 b Fi(Put)33 -b(\(app)s(end\))h(a)g(string)g(v)-5 b(alued)34 b(k)m(eyw)m(ord)h(in)m -(to)g(the)g(CHU)f(whic)m(h)g(ma)m(y)g(b)s(e)g(longer)h(than)e(68)i(c)m -(haracters)227 4906 y(in)j(length.)64 b(This)37 b(uses)h(the)g(Long)g -(String)g(Keyw)m(ord)g(con)m(v)m(en)m(tion)i(that)e(is)g(describ)s(ed)f -(in)h(the)g("Usage)227 5019 y(Guidelines)33 b(and)e(Suggestions")j -(section)f(of)g(this)f(do)s(cumen)m(t.)46 b(Since)33 -b(this)f(uses)g(a)g(non-standard)g(FITS)227 5132 y(con)m(v)m(en)m(tion) -38 b(to)d(enco)s(de)h(the)f(long)h(k)m(eyw)m(ord)f(string,)i(programs)d -(whic)m(h)h(use)g(this)g(routine)g(should)f(also)227 -5245 y(call)e(the)e(FTPLSW)g(routine)h(to)g(add)e(some)i(COMMENT)f(k)m -(eyw)m(ords)h(to)g(w)m(arn)f(users)f(of)i(the)f(FITS)g(\014le)227 -5357 y(that)36 b(this)f(con)m(v)m(en)m(tion)j(is)d(b)s(eing)g(used.)55 -b(FTPLSW)35 b(also)h(writes)g(a)f(k)m(eyw)m(ord)h(called)h(LONGSTRN)d -(to)227 5470 y(record)c(the)h(v)m(ersion)f(of)h(the)f(longstring)h(con) -m(v)m(en)m(tion)h(that)f(has)f(b)s(een)g(used,)f(in)h(case)h(a)g(new)f -(con)m(v)m(en)m(tion)227 5583 y(is)f(adopted)g(at)g(some)g(p)s(oin)m(t) -f(in)h(the)f(future.)40 b(If)28 b(the)g(LONGSTRN)g(k)m(eyw)m(ord)h(is)g -(already)g(presen)m(t)f(in)h(the)227 5696 y(header,)i(then)f(FTPLSW)g -(will)g(simply)g(return)g(and)f(will)i(not)g(write)f(duplicate)h(k)m -(eyw)m(ords.)p eop end -%%Page: 46 52 -TeXDict begin 46 51 bop 0 299 a Fi(46)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)382 555 y Fe(FTPKLS\(unit,keyword,keyv)o(al,)o(comm)o -(ent,)41 b(>)47 b(status\))382 668 y(FTPLSW\(unit,)d(>)k(status\))0 -889 y Fh(7)81 b Fi(Put)30 b(\(app)s(end\))g(a)h(new)f(k)m(eyw)m(ord)h -(with)f(an)h(unde\014ned,)e(or)h(n)m(ull,)h(v)-5 b(alue)31 -b(in)m(to)h(the)f(CHU.)g(The)f(v)-5 b(alue)31 b(string)227 -1002 y(of)g(the)f(k)m(eyw)m(ord)h(is)g(left)g(blank)f(in)g(this)g -(case.)382 1223 y Fe(FTPKYU\(unit,keyword,comm)o(ent)o(,)42 -b(>)47 b(status\))0 1445 y Fh(8)81 b Fi(Put)41 b(\(app)s(end\))g(a)i(n) -m(um)m(b)s(ered)d(sequence)j(of)f(k)m(eyw)m(ords)g(in)m(to)h(the)g -(CHU.)f(One)f(ma)m(y)i(app)s(end)d(the)j(same)227 1558 -y(commen)m(t)37 b(to)g(ev)m(ery)g(k)m(eyw)m(ord)g(\(and)f(eliminate)h -(the)g(need)f(to)h(ha)m(v)m(e)g(an)f(arra)m(y)h(of)f(iden)m(tical)i -(commen)m(t)227 1670 y(strings,)g(one)e(for)g(eac)m(h)h(k)m(eyw)m -(ord\))g(b)m(y)f(including)g(the)g(amp)s(ersand)e(c)m(haracter)k(as)e -(the)h(last)g(non-blank)227 1783 y(c)m(haracter)g(in)e(the)h -(\(\014rst\))f(COMMENTS)f(string)h(parameter.)56 b(This)35 -b(same)g(string)h(will)f(then)g(b)s(e)g(used)227 1896 -y(for)30 b(the)g(commen)m(t)h(\014eld)f(in)f(all)i(the)f(k)m(eyw)m -(ords.)41 b(\(Note)32 b(that)e(the)g(SPP)f(v)m(ersion)i(of)f(these)g -(routines)g(only)227 2009 y(supp)s(orts)f(a)i(single)g(commen)m(t)g -(string\).)382 2230 y Fe(FTPKN[JKLS]\(unit,keyroot)o(,st)o(artn)o(o,no) -o(_ke)o(ys,k)o(eyva)o(ls,)o(comm)o(ents)o(,)42 b(>)47 -b(status\))382 2343 y(FTPKN[EDFG]\(unit,keyroot)o(,st)o(artn)o(o,no)o -(_ke)o(ys,k)o(eyva)o(ls,)o(deci)o(mals)o(,co)o(mmen)o(ts,)41 -b(>)907 2456 y(status\))0 2677 y Fh(9)81 b Fi(Cop)m(y)21 -b(an)h(indexed)f(k)m(eyw)m(ord)i(from)e(one)h(HDU)h(to)f(another,)i(mo) -s(difying)e(the)g(index)f(n)m(um)m(b)s(er)f(of)i(the)g(k)m(eyw)m(ord) -227 2790 y(name)37 b(in)f(the)g(pro)s(cess.)58 b(F)-8 -b(or)37 b(example,)i(this)d(routine)h(could)f(read)g(the)h(TLMIN3)f(k)m -(eyw)m(ord)h(from)f(the)227 2903 y(input)28 b(HDU)h(\(b)m(y)f(giving)h -(k)m(eyro)s(ot)h(=)d("TLMIN")i(and)f(inn)m(um)f(=)h(3\))h(and)f(write)g -(it)h(to)g(the)f(output)g(HDU)227 3016 y(with)36 b(the)g(k)m(eyw)m(ord) -h(name)f(TLMIN4)g(\(b)m(y)g(setting)i(outn)m(um)d(=)h(4\).)58 -b(If)36 b(the)g(input)f(k)m(eyw)m(ord)i(do)s(es)f(not)227 -3129 y(exist,)c(then)e(this)g(routine)g(simply)g(returns)f(without)i -(indicating)g(an)f(error.)382 3350 y Fe(FTCPKY\(inunit,)44 -b(outunit,)h(innum,)h(outnum,)g(keyroot,)g(>)h(status\))0 -3571 y Fh(10)f Fi(Put)33 b(\(app)s(end\))f(a)h('triple)h(precision')g -(k)m(eyw)m(ord)f(in)m(to)h(the)g(CHU)f(in)g(F28.16)i(format.)49 -b(The)33 b(\015oating)h(p)s(oin)m(t)227 3684 y(k)m(eyw)m(ord)c(v)-5 -b(alue)30 b(is)f(constructed)h(b)m(y)f(concatenating)j(the)d(input)g -(in)m(teger)i(v)-5 b(alue)29 b(with)g(the)h(input)e(double)227 -3797 y(precision)22 b(fraction)h(v)-5 b(alue)23 b(\(whic)m(h)f(m)m(ust) -g(ha)m(v)m(e)h(a)f(v)-5 b(alue)23 b(b)s(et)m(w)m(een)g(0.0)g(and)e -(1.0\).)40 b(The)21 b(FTGKYT)h(routine)227 3910 y(should)35 -b(b)s(e)h(used)f(to)i(read)f(this)f(k)m(eyw)m(ord)i(v)-5 -b(alue,)38 b(b)s(ecause)e(the)g(other)h(k)m(eyw)m(ord)f(reading)g -(subroutines)227 4023 y(will)31 b(not)g(preserv)m(e)f(the)h(full)f -(precision)g(of)h(the)f(v)-5 b(alue.)382 4244 y Fe -(FTPKYT\(unit,keyword,intv)o(al,)o(dblv)o(al,c)o(omm)o(ent,)41 -b(>)48 b(status\))0 4466 y Fh(11)e Fi(W)-8 b(rite)36 -b(k)m(eyw)m(ords)g(to)f(the)h(CHDU)f(that)h(are)f(de\014ned)f(in)g(an)h -(ASCI)s(I)f(template)i(\014le.)55 b(The)34 b(format)i(of)f(the)227 -4578 y(template)d(\014le)f(is)f(describ)s(ed)f(under)g(the)i(ftgthd)f -(routine)g(b)s(elo)m(w.)382 4800 y Fe(FTPKTP\(unit,)44 -b(filename,)i(>)h(status\))0 5021 y Fh(12)f Fi(App)s(end)28 -b(the)i(ph)m(ysical)g(units)g(string)g(to)g(an)g(existing)h(k)m(eyw)m -(ord.)41 b(This)29 b(routine)h(uses)f(a)h(lo)s(cal)i(con)m(v)m(en)m -(tion,)227 5134 y(sho)m(wn)g(in)g(the)h(follo)m(wing)h(example,)g(in)e -(whic)m(h)g(the)h(k)m(eyw)m(ord)g(units)f(are)h(enclosed)g(in)f(square) -g(brac)m(k)m(ets)227 5247 y(in)e(the)h(b)s(eginning)f(of)g(the)h(k)m -(eyw)m(ord)g(commen)m(t)g(\014eld.)239 5468 y Fe(VELOCITY=)809 -b(12.3)46 b(/)i([km/s])e(orbital)g(speed)382 5694 y -(FTPUNT\(unit,keyword,unit)o(s,)41 b(>)48 b(status\))p -eop end -%%Page: 47 53 -TeXDict begin 47 52 bop 0 299 a Fg(6.4.)72 b(FITS)30 -b(HEADER)h(I/O)f(SUBR)m(OUTINES)2086 b Fi(47)0 555 y -Fb(6.4.4)112 b(Insert)38 b(Keyw)m(ord)f(Subroutines)0 -762 y Fh(1)81 b Fi(Insert)26 b(a)h(new)f(k)m(eyw)m(ord)h(record)g(in)m -(to)g(the)g(CHU)g(at)g(the)g(sp)s(eci\014ed)f(p)s(osition)h(\(i.e.,)i -(immediately)f(preceding)227 875 y(the)34 b(\(k)m(eyno\)th)g(k)m(eyw)m -(ord)g(in)f(the)h(header.\))49 b(This)33 b('insert)g(record')h -(subroutine)e(is)h(somewhat)h(less)g(e\016-)227 988 y(cien)m(t)28 -b(then)f(the)g('app)s(end)e(record')i(subroutine)f(\(FTPREC\))g -(describ)s(ed)g(ab)s(o)m(v)m(e)i(b)s(ecause)f(the)g(remaining)227 -1101 y(k)m(eyw)m(ords)k(in)f(the)h(header)f(ha)m(v)m(e)h(to)g(b)s(e)f -(shifted)g(do)m(wn)g(one)h(slot.)382 1349 y Fe -(FTIREC\(unit,key_no,card,)41 b(>)47 b(status\))0 1598 -y Fh(2)81 b Fi(Insert)36 b(a)h(new)f(k)m(eyw)m(ord)i(in)m(to)g(the)f -(CHU.)g(The)f(new)g(k)m(eyw)m(ord)i(is)f(inserted)f(immediately)i -(follo)m(wing)h(the)227 1711 y(last)27 b(k)m(eyw)m(ord)g(that)f(has)g -(b)s(een)g(read)g(from)f(the)h(header.)40 b(The)25 b(FTIKLS)g -(subroutine)g(w)m(orks)h(the)g(same)h(as)227 1824 y(the)h(FTIKYS)e -(subroutine,)h(except)i(it)f(also)g(supp)s(orts)e(long)i(string)f(v)-5 -b(alues)28 b(greater)g(than)f(68)h(c)m(haracters)227 -1937 y(in)36 b(length.)59 b(These)36 b('insert)g(k)m(eyw)m(ord')h -(subroutines)e(are)i(somewhat)g(less)f(e\016cien)m(t)i(then)e(the)g -('app)s(end)227 2049 y(k)m(eyw)m(ord')30 b(subroutines)e(describ)s(ed)g -(ab)s(o)m(v)m(e)i(b)s(ecause)f(the)g(remaining)h(k)m(eyw)m(ords)f(in)g -(the)g(header)g(ha)m(v)m(e)h(to)227 2162 y(b)s(e)g(shifted)g(do)m(wn)g -(one)h(slot.)382 2411 y Fe(FTIKEY\(unit,)44 b(card,)j(>)g(status\))382 -2524 y(FTIKY[JKLS]\(unit,keyword)o(,ke)o(yval)o(,com)o(men)o(t,)42 -b(>)47 b(status\))382 2637 y(FTIKLS\(unit,keyword,keyv)o(al,)o(comm)o -(ent,)41 b(>)47 b(status\))382 2750 y(FTIKY[EDFG]\(unit,keyword)o(,ke)o -(yval)o(,dec)o(ima)o(ls,c)o(omme)o(nt,)41 b(>)48 b(status\))0 -2998 y Fh(3)81 b Fi(Insert)32 b(a)i(new)f(k)m(eyw)m(ord)h(with)f(an)h -(unde\014ned,)e(or)h(n)m(ull,)h(v)-5 b(alue)34 b(in)m(to)h(the)e(CHU.)h -(The)f(v)-5 b(alue)34 b(string)f(of)h(the)227 3111 y(k)m(eyw)m(ord)d -(is)g(left)g(blank)f(in)g(this)g(case.)382 3359 y Fe -(FTIKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 -3648 y Fb(6.4.5)112 b(Read)38 b(Keyw)m(ord)g(Subroutines)0 -3867 y Fi(These)29 b(routines)f(return)g(the)h(v)-5 b(alue)29 -b(of)g(the)g(sp)s(eci\014ed)f(k)m(eyw)m(ord\(s\).)41 -b(Wild)30 b(card)e(c)m(haracters)i(\(*,)h(?,)e(or)g(#\))f(ma)m(y)0 -3980 y(b)s(e)f(used)h(when)f(sp)s(ecifying)h(the)g(name)g(of)g(the)g(k) -m(eyw)m(ord)h(to)g(b)s(e)e(read:)39 b(a)29 b(')10 b(?')40 -b(will)28 b(matc)m(h)h(an)m(y)g(single)f(c)m(haracter)0 -4093 y(at)38 b(that)g(p)s(osition)f(in)g(the)h(k)m(eyw)m(ord)g(name)f -(and)g(a)g('*')i(will)e(matc)m(h)h(an)m(y)g(length)g(\(including)f -(zero\))h(string)g(of)0 4206 y(c)m(haracters.)65 b(The)37 -b('#')h(c)m(haracter)h(will)f(matc)m(h)h(an)m(y)f(consecutiv)m(e)i -(string)e(of)g(decimal)h(digits)f(\(0)h(-)f(9\).)64 b(Note)0 -4319 y(that)30 b(when)f(a)g(wild)g(card)h(is)f(used)g(in)g(the)h(input) -e(k)m(eyw)m(ord)i(name,)g(the)g(routine)f(will)h(only)g(searc)m(h)g -(for)f(a)h(matc)m(h)0 4432 y(from)h(the)h(curren)m(t)g(header)g(p)s -(osition)g(to)g(the)h(end)e(of)h(the)g(header.)45 b(It)32 -b(will)g(not)g(resume)g(the)g(searc)m(h)g(from)g(the)0 -4545 y(top)i(of)h(the)f(header)g(bac)m(k)h(to)g(the)f(original)h -(header)f(p)s(osition)g(as)h(is)f(done)g(when)f(no)h(wildcards)f(are)i -(included)0 4657 y(in)f(the)g(k)m(eyw)m(ord)h(name.)52 -b(If)33 b(the)h(desired)g(k)m(eyw)m(ord)h(string)f(is)g(8-c)m -(haracters)i(long)f(\(the)f(maxim)m(um)g(length)h(of)0 -4770 y(a)h(k)m(eyw)m(ord)g(name\))g(then)g(a)g('*')g(ma)m(y)h(b)s(e)e -(app)s(ended)f(as)h(the)h(nin)m(th)g(c)m(haracter)h(of)f(the)f(input)g -(name)h(to)g(force)0 4883 y(the)31 b(k)m(eyw)m(ord)g(searc)m(h)h(to)f -(stop)g(at)g(the)g(end)f(of)h(the)g(header)g(\(e.g.,)i('COMMENT)d(*')i -(will)f(searc)m(h)g(for)g(the)g(next)0 4996 y(COMMENT)37 -b(k)m(eyw)m(ord\).)64 b(The)37 b(\013grec)i(routine)f(ma)m(y)g(b)s(e)f -(used)g(to)i(set)f(the)g(starting)g(p)s(osition)g(when)f(doing)0 -5109 y(wild)30 b(card)g(searc)m(hes.)0 5357 y Fh(1)81 -b Fi(Get)37 b(the)f(n)m(th)f(80-c)m(haracter)k(header)d(record)g(from)f -(the)h(CHU.)h(The)e(\014rst)g(k)m(eyw)m(ord)i(in)e(the)h(header)g(is)g -(at)227 5470 y(k)m(ey)p 365 5470 28 4 v 34 w(no)42 b(=)f(1;)49 -b(if)42 b(k)m(ey)p 996 5470 V 34 w(no)g(=)f(0)i(then)e(this)h -(subroutine)f(simple)h(mo)m(v)m(es)i(the)e(in)m(ternal)h(p)s(oin)m(ter) -f(to)h(the)227 5583 y(b)s(eginning)35 b(of)h(the)g(header)f(so)h(that)g -(subsequen)m(t)f(k)m(eyw)m(ord)h(op)s(erations)g(will)g(start)g(at)g -(the)g(top)g(of)g(the)227 5696 y(header;)31 b(it)g(also)g(returns)e(a)i -(blank)f(card)g(v)-5 b(alue)31 b(in)f(this)g(case.)p -eop end -%%Page: 48 54 -TeXDict begin 48 53 bop 0 299 a Fi(48)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)382 555 y Fe(FTGREC\(unit,key_no,)42 -b(>)48 b(card,status\))0 797 y Fh(2)81 b Fi(Get)31 b(the)g(name,)f(v)-5 -b(alue)31 b(\(as)g(a)g(string\),)g(and)f(commen)m(t)i(of)e(the)h(n)m -(th)f(k)m(eyw)m(ord)h(in)f(CHU.)h(This)f(routine)g(also)227 -910 y(c)m(hec)m(ks)h(that)f(the)g(returned)e(k)m(eyw)m(ord)i(name)f -(\(KEYW)m(ORD\))i(con)m(tains)g(only)e(legal)i(ASCI)s(I)d(c)m -(haracters.)227 1023 y(Call)j(FTGREC)f(and)g(FTPSV)m(C)g(to)h(b)m -(ypass)f(this)g(error)g(c)m(hec)m(k.)382 1264 y Fe -(FTGKYN\(unit,key_no,)42 b(>)48 b(keyword,value,comment,st)o(atu)o(s\)) -0 1506 y Fh(3)81 b Fi(Get)31 b(the)g(80-c)m(haracter)i(header)d(record) -g(for)g(the)h(named)f(k)m(eyw)m(ord)382 1748 y Fe -(FTGCRD\(unit,keyword,)42 b(>)48 b(card,status\))0 1990 -y Fh(4)81 b Fi(Get)26 b(the)f(next)h(k)m(eyw)m(ord)f(whose)g(name)h -(matc)m(hes)g(one)f(of)h(the)f(strings)g(in)g('inclist')i(but)d(do)s -(es)h(not)g(matc)m(h)i(an)m(y)227 2102 y(of)32 b(the)f(strings)g(in)g -('exclist'.)45 b(The)30 b(strings)h(in)g(inclist)h(and)f(exclist)h(ma)m -(y)g(con)m(tain)h(wild)d(card)h(c)m(haracters)227 2215 -y(\(*,)38 b(?,)e(and)e(#\))i(as)f(describ)s(ed)f(at)i(the)f(b)s -(eginning)f(of)i(this)f(section.)56 b(This)34 b(routine)h(searc)m(hes)h -(from)f(the)227 2328 y(curren)m(t)28 b(header)f(p)s(osition)h(to)g(the) -g(end)f(of)h(the)g(header,)g(only)-8 b(,)29 b(and)e(do)s(es)g(not)h -(con)m(tin)m(ue)h(the)f(searc)m(h)g(from)227 2441 y(the)41 -b(top)g(of)g(the)g(header)g(bac)m(k)h(to)f(the)g(original)h(p)s -(osition.)73 b(The)40 b(curren)m(t)h(header)f(p)s(osition)h(ma)m(y)h(b) -s(e)227 2554 y(reset)33 b(with)e(the)h(ftgrec)h(routine.)44 -b(Note)33 b(that)g(nexc)f(ma)m(y)g(b)s(e)f(set)h(=)g(0)g(if)f(there)h -(are)g(no)g(k)m(eyw)m(ords)g(to)h(b)s(e)227 2667 y(excluded.)41 -b(This)29 b(routine)i(returns)e(status)i(=)f(202)h(if)g(a)f(matc)m -(hing)i(k)m(eyw)m(ord)f(is)f(not)h(found.)382 2909 y -Fe(FTGNXK\(unit,inclist,ninc)o(,ex)o(clis)o(t,ne)o(xc,)41 -b(>)48 b(card,status\))0 3150 y Fh(5)81 b Fi(Get)30 b(the)g(literal)i -(k)m(eyw)m(ord)e(v)-5 b(alue)30 b(as)g(a)g(c)m(haracter)i(string.)40 -b(Regardless)31 b(of)f(the)g(datat)m(yp)s(e)g(of)g(the)g(k)m(eyw)m -(ord,)227 3263 y(this)37 b(routine)g(simply)g(returns)f(the)h(string)g -(of)g(c)m(haracters)i(in)d(the)i(v)-5 b(alue)37 b(\014eld)g(of)g(the)g -(k)m(eyw)m(ord)h(along)227 3376 y(with)30 b(the)h(commen)m(t)g -(\014eld.)382 3618 y Fe(FTGKEY\(unit,keyword,)42 b(>)48 -b(value,comment,status\))0 3860 y Fh(6)81 b Fi(Get)31 -b(a)g(k)m(eyw)m(ord)g(v)-5 b(alue)30 b(\(with)h(the)f(appropriate)h -(datat)m(yp)s(e\))g(and)f(commen)m(t)i(from)e(the)g(CHU)382 -4101 y Fe(FTGKY[EDJKLS]\(unit,keywo)o(rd,)41 b(>)48 b -(keyval,comment,status\))0 4343 y Fh(7)81 b Fi(Read)22 -b(a)g(string-v)-5 b(alued)23 b(k)m(eyw)m(ord)f(and)g(return)e(the)j -(string)f(length,)i(the)e(v)-5 b(alue)23 b(string,)h(and/or)e(the)g -(commen)m(t)227 4456 y(\014eld.)47 b(The)32 b(\014rst)g(routine,)h -(FTGKSL,)f(simply)g(returns)f(the)i(length)g(of)g(the)f(c)m(haracter)i -(string)f(v)-5 b(alue)33 b(of)227 4569 y(the)c(sp)s(eci\014ed)g(k)m -(eyw)m(ord.)40 b(The)29 b(second)g(routine,)h(FTGSKY,)f(also)g(returns) -f(up)g(to)i(maxc)m(har)f(c)m(haracters)227 4682 y(of)i(the)f(k)m(eyw)m -(ord)h(v)-5 b(alue)31 b(string,)g(starting)g(with)f(the)g(\014rstc)m -(har)g(c)m(haracter,)j(and)c(the)i(k)m(eyw)m(ord)g(commen)m(t)227 -4795 y(string.)49 b(The)32 b(length)i(argumen)m(t)f(returns)f(the)h -(total)i(length)e(of)h(the)f(k)m(eyw)m(ord)g(v)-5 b(alue)34 -b(string)f(regardless)227 4908 y(of)i(ho)m(w)f(m)m(uc)m(h)g(of)g(the)h -(string)f(is)g(actually)i(returned)d(\(whic)m(h)h(dep)s(ends)e(on)j -(the)f(v)-5 b(alue)35 b(of)f(the)g(\014rstc)m(har)227 -5021 y(and)c(maxc)m(har)h(argumen)m(ts\).)41 b(These)30 -b(routines)h(supp)s(ort)d(string)j(k)m(eyw)m(ords)f(that)h(use)f(the)h -(CONTINUE)227 5133 y(con)m(v)m(en)m(tion)25 b(to)e(con)m(tin)m(ue)g -(long)g(string)f(v)-5 b(alues)23 b(o)m(v)m(er)h(m)m(ultiple)f(FITS)e -(header)h(records.)38 b(Normally)-8 b(,)26 b(string-)227 -5246 y(v)-5 b(alued)40 b(k)m(eyw)m(ords)h(ha)m(v)m(e)g(a)g(maxim)m(um)f -(length)h(of)f(68)h(c)m(haracters,)k(ho)m(w)m(ev)m(er,)f(CONTINUE'd)39 -b(string)227 5359 y(k)m(eyw)m(ords)31 b(ma)m(y)g(b)s(e)f(arbitrarily)g -(long.)334 5601 y Fe(FTGKSL\(unit,keyword,)42 b(>)48 -b(length,status\))334 5714 y(FTGSKY\(unit,keyword,first)o(cha)o(r,ma)o -(xcha)o(r,>)41 b(keyval,length,comment,sta)o(tus\))p -eop end -%%Page: 49 55 -TeXDict begin 49 54 bop 0 299 a Fg(6.4.)72 b(FITS)30 -b(HEADER)h(I/O)f(SUBR)m(OUTINES)2086 b Fi(49)0 555 y -Fh(8)81 b Fi(Get)24 b(a)g(sequence)g(of)g(n)m(um)m(b)s(ered)e(k)m(eyw)m -(ord)i(v)-5 b(alues.)38 b(These)24 b(routines)f(do)g(not)h(supp)s(ort)e -(wild)h(card)g(c)m(haracters)227 668 y(in)30 b(the)h(ro)s(ot)g(name.) -382 929 y Fe(FTGKN[EDJKLS]\(unit,keyro)o(ot,)o(star)o(tno,)o(max)o -(_key)o(s,)42 b(>)47 b(keyvals,nfound,status\))0 1189 -y Fh(9)81 b Fi(Get)27 b(the)f(v)-5 b(alue)26 b(of)h(a)f(\015oating)h(p) -s(oin)m(t)f(k)m(eyw)m(ord,)i(returning)d(the)h(in)m(teger)h(and)f -(fractional)h(parts)f(of)g(the)g(v)-5 b(alue)227 1302 -y(in)32 b(separate)g(subroutine)f(argumen)m(ts.)45 b(This)31 -b(subroutine)f(ma)m(y)j(b)s(e)e(used)g(to)h(read)g(an)m(y)g(k)m(eyw)m -(ord)g(but)f(is)227 1415 y(esp)s(ecially)h(useful)d(for)i(reading)f -(the)h('triple)g(precision')f(k)m(eyw)m(ords)h(written)g(b)m(y)f -(FTPKYT.)382 1675 y Fe(FTGKYT\(unit,keyword,)42 b(>)48 -b(intval,dblval,comment,s)o(tat)o(us\))0 1936 y Fh(10)e -Fi(Get)c(the)e(ph)m(ysical)i(units)e(string)g(in)h(an)f(existing)i(k)m -(eyw)m(ord.)72 b(This)40 b(routine)g(uses)h(a)g(lo)s(cal)h(con)m(v)m -(en)m(tion,)227 2049 y(sho)m(wn)32 b(in)g(the)h(follo)m(wing)h -(example,)g(in)e(whic)m(h)g(the)h(k)m(eyw)m(ord)g(units)f(are)h -(enclosed)g(in)f(square)g(brac)m(k)m(ets)227 2162 y(in)37 -b(the)h(b)s(eginning)e(of)i(the)f(k)m(eyw)m(ord)h(commen)m(t)g -(\014eld.)61 b(A)38 b(blank)f(string)g(is)g(returned)f(if)i(no)f(units) -g(are)227 2274 y(de\014ned)29 b(for)i(the)f(k)m(eyw)m(ord.)191 -2535 y Fe(VELOCITY=)809 b(12.3)46 b(/)i([km/s])e(orbital)g(speed)382 -2761 y(FTGUNT\(unit,keyword,)c(>)48 b(units,status\))0 -3052 y Fb(6.4.6)112 b(Mo)s(dify)39 b(Keyw)m(ord)e(Subroutines)0 -3271 y Fi(Wild)32 b(card)f(c)m(haracters,)j(as)e(describ)s(ed)e(in)h -(the)h(Read)g(Keyw)m(ord)f(section,)i(ab)s(o)m(v)m(e,)g(ma)m(y)g(b)s(e) -d(used)h(when)g(sp)s(eci-)0 3384 y(fying)f(the)h(name)f(of)h(the)f(k)m -(eyw)m(ord)h(to)g(b)s(e)f(mo)s(di\014ed.)0 3645 y Fh(1)81 -b Fi(Mo)s(dify)30 b(\(o)m(v)m(erwrite\))i(the)f(n)m(th)f(80-c)m -(haracter)j(header)d(record)h(in)f(the)g(CHU)382 3905 -y Fe(FTMREC\(unit,key_no,card,)41 b(>)47 b(status\))0 -4166 y Fh(2)81 b Fi(Mo)s(dify)37 b(\(o)m(v)m(erwrite\))j(the)e(80-c)m -(haracter)j(header)c(record)h(for)f(the)h(named)f(k)m(eyw)m(ord)h(in)g -(the)g(CHU.)g(This)227 4278 y(can)31 b(b)s(e)f(used)f(to)i(o)m(v)m -(erwrite)h(the)f(name)f(of)h(the)f(k)m(eyw)m(ord)h(as)g(w)m(ell)g(as)g -(its)g(v)-5 b(alue)30 b(and)g(commen)m(t)i(\014elds.)382 -4539 y Fe(FTMCRD\(unit,keyword,card)o(,)42 b(>)47 b(status\))0 -4799 y Fh(3)81 b Fi(Mo)s(dify)33 b(\(o)m(v)m(erwrite\))k(the)d(name)g -(of)h(an)f(existing)h(k)m(eyw)m(ord)f(in)g(the)h(CHU)f(preserving)f -(the)i(curren)m(t)e(v)-5 b(alue)227 4912 y(and)30 b(commen)m(t)h -(\014elds.)382 5173 y Fe(FTMNAM\(unit,oldkey,keywo)o(rd,)41 -b(>)48 b(status\))0 5433 y Fh(4)81 b Fi(Mo)s(dify)30 -b(\(o)m(v)m(erwrite\))i(the)f(commen)m(t)g(\014eld)f(of)h(an)f -(existing)h(k)m(eyw)m(ord)g(in)f(the)h(CHU)382 5694 y -Fe(FTMCOM\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))p -eop end -%%Page: 50 56 -TeXDict begin 50 55 bop 0 299 a Fi(50)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)0 555 y Fh(5)81 b Fi(Mo)s(dify)24 b(the)h(v)-5 -b(alue)25 b(and)f(commen)m(t)i(\014elds)e(of)h(an)f(existing)i(k)m(eyw) -m(ord)f(in)f(the)h(CHU.)g(The)f(FTMKLS)g(subrou-)227 -668 y(tine)35 b(w)m(orks)e(the)h(same)h(as)f(the)g(FTMKYS)f -(subroutine,)h(except)h(it)g(also)f(supp)s(orts)e(long)j(string)f(v)-5 -b(alues)227 781 y(greater)38 b(than)f(68)h(c)m(haracters)g(in)f -(length.)60 b(Optionally)-8 b(,)40 b(one)d(ma)m(y)h(mo)s(dify)e(only)h -(the)g(v)-5 b(alue)37 b(\014eld)g(and)227 894 y(lea)m(v)m(e)32 -b(the)d(commen)m(t)i(\014eld)e(unc)m(hanged)g(b)m(y)g(setting)h(the)g -(input)e(COMMENT)h(parameter)h(equal)g(to)g(the)227 1007 -y(amp)s(ersand)f(c)m(haracter)k(\(&\).)42 b(The)30 b(E)g(and)g(D)h(v)m -(ersions)g(of)g(this)g(routine)f(ha)m(v)m(e)i(the)f(added)f(feature)h -(that)227 1120 y(if)26 b(the)h('decimals')g(parameter)g(is)f(negativ)m -(e,)k(then)c(the)g('G')h(displa)m(y)f(format)h(rather)f(then)g(the)g -('E')h(format)227 1233 y(will)i(b)s(e)f(used)f(when)h(constructing)h -(the)f(k)m(eyw)m(ord)h(v)-5 b(alue,)30 b(taking)f(the)g(absolute)g(v)-5 -b(alue)29 b(of)f('decimals')i(for)227 1346 y(the)37 b(precision.)60 -b(This)35 b(will)i(suppress)e(trailing)i(zeros,)i(and)d(will)h(use)g(a) -g(\014xed)e(format)i(rather)g(than)f(an)227 1458 y(exp)s(onen)m(tial)c -(format,)f(dep)s(ending)d(on)j(the)f(magnitude)h(of)f(the)h(v)-5 -b(alue.)382 1687 y Fe(FTMKY[JKLS]\(unit,keyword)o(,ke)o(yval)o(,com)o -(men)o(t,)42 b(>)47 b(status\))382 1800 y(FTMKLS\(unit,keyword,keyv)o -(al,)o(comm)o(ent,)41 b(>)47 b(status\))382 1913 y -(FTMKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o(omme)o -(nt,)41 b(>)48 b(status\))0 2141 y Fh(6)81 b Fi(Mo)s(dify)22 -b(the)g(v)-5 b(alue)23 b(of)f(an)g(existing)i(k)m(eyw)m(ord)e(to)h(b)s -(e)f(unde\014ned,)g(or)g(n)m(ull.)38 b(The)22 b(v)-5 -b(alue)22 b(string)h(of)f(the)g(k)m(eyw)m(ord)227 2254 -y(is)30 b(set)h(to)g(blank.)40 b(Optionally)-8 b(,)31 -b(one)f(ma)m(y)h(lea)m(v)m(e)h(the)f(commen)m(t)g(\014eld)e(unc)m -(hanged)h(b)m(y)g(setting)h(the)f(input)227 2367 y(COMMENT)g(parameter) -h(equal)g(to)g(the)g(amp)s(ersand)e(c)m(haracter)j(\(&\).)382 -2595 y Fe(FTMKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 -b(status\))0 2881 y Fb(6.4.7)112 b(Up)s(date)39 b(Keyw)m(ord)e -(Subroutines)0 3084 y Fh(1)81 b Fi(Up)s(date)36 b(an)g(80-c)m(haracter) -j(record)d(in)g(the)h(CHU.)f(If)g(the)g(sp)s(eci\014ed)g(k)m(eyw)m(ord) -h(already)f(exists)h(then)f(that)227 3197 y(header)j(record)f(will)h(b) -s(e)f(replaced)i(with)e(the)h(input)f(CARD)g(string.)66 -b(If)38 b(it)i(do)s(es)e(not)h(exist)g(then)g(the)227 -3310 y(new)f(record)g(will)g(b)s(e)f(added)h(to)g(the)g(header.)64 -b(The)37 b(FTUKLS)g(subroutine)g(w)m(orks)h(the)g(same)h(as)f(the)227 -3423 y(FTUKYS)28 b(subroutine,)g(except)i(it)f(also)h(supp)s(orts)c -(long)j(string)g(v)-5 b(alues)29 b(greater)h(than)e(68)h(c)m(haracters) -h(in)227 3536 y(length.)382 3764 y Fe(FTUCRD\(unit,keyword,card)o(,)42 -b(>)47 b(status\))0 3993 y Fh(2)81 b Fi(Up)s(date)44 -b(the)i(v)-5 b(alue)45 b(and)g(commen)m(t)h(\014elds)e(of)h(a)h(k)m -(eyw)m(ord)f(in)g(the)g(CHU.)h(The)e(sp)s(eci\014ed)g(k)m(eyw)m(ord)i -(is)227 4106 y(mo)s(di\014ed)38 b(if)g(it)h(already)g(exists)g(\(b)m(y) -g(calling)h(FTMKYx\))f(otherwise)f(a)h(new)f(k)m(eyw)m(ord)h(is)g -(created)g(b)m(y)227 4218 y(calling)f(FTPKYx.)58 b(The)36 -b(E)g(and)f(D)i(v)m(ersions)f(of)h(this)f(routine)g(ha)m(v)m(e)h(the)g -(added)e(feature)i(that)g(if)f(the)227 4331 y('decimals')c(parameter)g -(is)f(negativ)m(e,)i(then)d(the)h('G')h(displa)m(y)f(format)g(rather)g -(then)f(the)h('E')g(format)h(will)227 4444 y(b)s(e)41 -b(used)f(when)h(constructing)h(the)f(k)m(eyw)m(ord)h(v)-5 -b(alue,)45 b(taking)d(the)f(absolute)h(v)-5 b(alue)42 -b(of)g('decimals')g(for)227 4557 y(the)37 b(precision.)60 -b(This)35 b(will)i(suppress)e(trailing)i(zeros,)i(and)d(will)h(use)g(a) -g(\014xed)e(format)i(rather)g(than)f(an)227 4670 y(exp)s(onen)m(tial)c -(format,)f(dep)s(ending)d(on)j(the)f(magnitude)h(of)f(the)h(v)-5 -b(alue.)382 4898 y Fe(FTUKY[JKLS]\(unit,keyword)o(,ke)o(yval)o(,com)o -(men)o(t,)42 b(>)47 b(status\))382 5011 y(FTUKLS\(unit,keyword,keyv)o -(al,)o(comm)o(ent,)41 b(>)47 b(status\))382 5124 y -(FTUKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o(omme)o -(nt,)41 b(>)48 b(status\))0 5352 y Fh(3)81 b Fi(Up)s(date)23 -b(the)g(v)-5 b(alue)24 b(of)g(an)f(existing)i(k)m(eyw)m(ord)f(to)g(b)s -(e)f(unde\014ned,)f(or)i(n)m(ull,)h(or)e(insert)h(a)f(new)g -(unde\014ned-v)-5 b(alue)227 5465 y(k)m(eyw)m(ord)30 -b(if)f(it)h(do)s(esn't)f(already)h(exist.)41 b(The)29 -b(v)-5 b(alue)30 b(string)f(of)g(the)h(k)m(eyw)m(ord)f(is)h(left)g -(blank)f(in)f(this)i(case.)382 5694 y Fe(FTUKYU\(unit,keyword,comm)o -(ent)o(,)42 b(>)47 b(status\))p eop end -%%Page: 51 57 -TeXDict begin 51 56 bop 0 299 a Fg(6.5.)72 b(D)m(A)-8 -b(T)g(A)32 b(SCALING)e(AND)h(UNDEFINED)h(PIXEL)e(P)-8 -b(ARAMETERS)1083 b Fi(51)0 555 y Fb(6.4.8)112 b(Delete)38 -b(Keyw)m(ord)f(Subroutines)0 763 y Fh(1)81 b Fi(Delete)32 -b(an)e(existing)h(k)m(eyw)m(ord)g(record.)40 b(The)30 -b(space)h(previously)f(o)s(ccupied)g(b)m(y)g(the)g(k)m(eyw)m(ord)h(is)f -(reclaimed)227 876 y(b)m(y)c(mo)m(ving)h(all)g(the)f(follo)m(wing)i -(header)e(records)g(up)f(one)h(ro)m(w)h(in)e(the)i(header.)39 -b(The)25 b(\014rst)h(routine)g(deletes)227 989 y(a)34 -b(k)m(eyw)m(ord)f(at)h(a)g(sp)s(eci\014ed)e(p)s(osition)h(in)g(the)g -(header)g(\(the)h(\014rst)e(k)m(eyw)m(ord)i(is)f(at)h(p)s(osition)f -(1\),)i(whereas)227 1102 y(the)d(second)g(routine)g(deletes)h(a)f(sp)s -(eci\014cally)g(named)f(k)m(eyw)m(ord.)46 b(Wild)32 b(card)f(c)m -(haracters,)j(as)e(describ)s(ed)227 1215 y(in)f(the)g(Read)g(Keyw)m -(ord)f(section,)i(ab)s(o)m(v)m(e,)g(ma)m(y)g(b)s(e)e(used)g(when)f(sp)s -(ecifying)i(the)g(name)g(of)g(the)f(k)m(eyw)m(ord)227 -1328 y(to)h(b)s(e)f(deleted)h(\(b)s(e)f(careful!\).)382 -1582 y Fe(FTDREC\(unit,key_no,)42 b(>)48 b(status\))382 -1695 y(FTDKEY\(unit,keyword,)42 b(>)48 b(status\))0 2028 -y Fd(6.5)135 b(Data)46 b(Scaling)g(and)e(Unde\014ned)h(Pixel)h(P)l -(arameters)0 2278 y Fi(These)24 b(subroutines)f(de\014ne)h(or)h(mo)s -(dify)e(the)i(in)m(ternal)g(parameters)g(used)f(b)m(y)g(FITSIO)g(to)h -(either)g(scale)h(the)e(data)0 2391 y(or)33 b(to)i(represen)m(t)e -(unde\014ned)e(pixels.)50 b(Generally)35 b(FITSIO)d(will)i(scale)g(the) -g(data)g(according)g(to)g(the)g(v)-5 b(alues)34 b(of)0 -2504 y(the)e(BSCALE)g(and)f(BZER)m(O)h(\(or)h(TSCALn)d(and)i(TZER)m -(On\))f(k)m(eyw)m(ords,)i(ho)m(w)m(ev)m(er)h(these)e(subroutines)f(ma)m -(y)0 2617 y(b)s(e)h(used)h(to)h(o)m(v)m(erride)g(the)f(k)m(eyw)m(ord)h -(v)-5 b(alues.)49 b(This)32 b(ma)m(y)i(b)s(e)f(useful)f(when)g(one)i(w) -m(an)m(ts)f(to)h(read)f(or)g(write)h(the)0 2730 y(ra)m(w)c(unscaled)f -(v)-5 b(alues)29 b(in)h(the)f(FITS)g(\014le.)40 b(Similarly)-8 -b(,)31 b(FITSIO)d(generally)j(uses)e(the)g(v)-5 b(alue)30 -b(of)g(the)f(BLANK)h(or)0 2843 y(TNULLn)35 b(k)m(eyw)m(ord)h(to)g -(signify)f(an)h(unde\014ned)d(pixel,)k(but)e(these)h(routines)g(ma)m(y) -g(b)s(e)e(used)h(to)h(o)m(v)m(erride)h(this)0 2956 y(v)-5 -b(alue.)41 b(These)30 b(subroutines)f(do)i(not)f(create)i(or)f(mo)s -(dify)e(the)i(corresp)s(onding)e(header)h(k)m(eyw)m(ord)h(v)-5 -b(alues.)0 3210 y Fh(1)81 b Fi(Reset)26 b(the)g(scaling)g(factors)g(in) -f(the)h(primary)f(arra)m(y)h(or)f(image)i(extension;)h(do)s(es)d(not)g -(c)m(hange)i(the)f(BSCALE)227 3323 y(and)i(BZER)m(O)g(k)m(eyw)m(ord)h -(v)-5 b(alues)28 b(and)g(only)g(a\013ects)i(the)e(automatic)j(scaling)e -(p)s(erformed)e(when)g(the)h(data)227 3436 y(elemen)m(ts)f(are)f -(written/read)g(to/from)g(the)g(FITS)f(\014le.)39 b(When)25 -b(reading)h(from)f(a)h(FITS)f(\014le)g(the)h(returned)227 -3549 y(data)i(v)-5 b(alue)28 b(=)f(\(the)h(v)-5 b(alue)28 -b(giv)m(en)h(in)e(the)g(FITS)g(arra)m(y\))h(*)g(BSCALE)f(+)g(BZER)m(O.) -g(The)g(in)m(v)m(erse)i(form)m(ula)227 3662 y(is)34 b(used)f(when)g -(writing)h(data)h(v)-5 b(alues)34 b(to)g(the)g(FITS)g(\014le.)51 -b(\(NOTE:)34 b(BSCALE)f(and)g(BZER)m(O)h(m)m(ust)g(b)s(e)227 -3775 y(declared)d(as)g(Double)g(Precision)g(v)-5 b(ariables\).)382 -4029 y Fe(FTPSCL\(unit,bscale,bzero)o(,)42 b(>)47 b(status\))0 -4284 y Fh(2)81 b Fi(Reset)39 b(the)f(scaling)i(parameters)e(for)h(a)f -(table)h(column;)k(do)s(es)38 b(not)g(c)m(hange)i(the)e(TSCALn)f(or)h -(TZER)m(On)227 4397 y(k)m(eyw)m(ord)29 b(v)-5 b(alues)29 -b(and)e(only)i(a\013ects)g(the)g(automatic)h(scaling)f(p)s(erformed)e -(when)g(the)i(data)g(elemen)m(ts)h(are)227 4510 y(written/read)i -(to/from)g(the)g(FITS)f(\014le.)44 b(When)31 b(reading)g(from)g(a)h -(FITS)f(\014le)g(the)h(returned)e(data)i(v)-5 b(alue)227 -4623 y(=)40 b(\(the)h(v)-5 b(alue)40 b(giv)m(en)h(in)f(the)g(FITS)g -(arra)m(y\))g(*)h(TSCAL)e(+)g(TZER)m(O.)h(The)f(in)m(v)m(erse)i(form)m -(ula)g(is)f(used)227 4736 y(when)33 b(writing)h(data)h(v)-5 -b(alues)35 b(to)f(the)h(FITS)e(\014le.)52 b(\(NOTE:)34 -b(TSCAL)f(and)g(TZER)m(O)g(m)m(ust)h(b)s(e)f(declared)227 -4848 y(as)e(Double)g(Precision)g(v)-5 b(ariables\).)382 -5103 y Fe(FTTSCL\(unit,colnum,tscal)o(,tz)o(ero,)41 b(>)48 -b(status\))0 5357 y Fh(3)81 b Fi(De\014ne)36 b(the)g(in)m(teger)i(v)-5 -b(alue)36 b(to)h(b)s(e)e(used)h(to)h(signify)f(unde\014ned)e(pixels)i -(in)g(the)g(primary)f(arra)m(y)i(or)f(image)227 5470 -y(extension.)59 b(This)35 b(is)h(only)g(used)g(if)g(BITPIX)g(=)f(8,)j -(16,)h(32.)59 b(or)36 b(64)h(This)e(do)s(es)h(not)g(create)i(or)e(c)m -(hange)227 5583 y(the)27 b(v)-5 b(alue)28 b(of)f(the)g(BLANK)g(k)m(eyw) -m(ord)h(in)e(the)i(header.)39 b(FTPNULLL)27 b(is)g(iden)m(tical)h(to)g -(FTPNUL)f(except)227 5696 y(that)k(the)g(blank)f(v)-5 -b(alue)31 b(is)f(a)h(64-bit)g(in)m(teger)h(instead)f(of)f(a)h(32-bit)h -(in)m(teger.)p eop end -%%Page: 52 58 -TeXDict begin 52 57 bop 0 299 a Fi(52)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)382 555 y Fe(FTPNUL\(unit,blank,)43 -b(>)k(status\))382 668 y(FTPNULLL\(unit,blankll,)42 b(>)47 -b(status\))0 919 y Fh(4)81 b Fi(De\014ne)36 b(the)g(string)g(to)g(b)s -(e)f(used)g(to)i(signify)f(unde\014ned)e(pixels)i(in)f(a)h(column)g(in) -g(an)f(ASCI)s(I)g(table.)58 b(This)227 1032 y(do)s(es)30 -b(not)h(create)h(or)e(c)m(hange)i(the)e(v)-5 b(alue)31 -b(of)g(the)f(TNULLn)g(k)m(eyw)m(ord.)382 1283 y Fe -(FTSNUL\(unit,colnum,snull)41 b(>)47 b(status\))0 1534 -y Fh(5)81 b Fi(De\014ne)34 b(the)h(v)-5 b(alue)34 b(to)h(b)s(e)f(used)g -(to)h(signify)f(unde\014ned)e(pixels)j(in)f(an)g(in)m(teger)i(column)e -(in)g(a)g(binary)g(table)227 1647 y(\(where)42 b(TF)m(ORMn)f(=)g('B',)i -('I',)f('J',)f(or)h('K'\).)g(This)f(do)s(es)g(not)h(create)h(or)e(c)m -(hange)i(the)e(v)-5 b(alue)42 b(of)g(the)227 1760 y(TNULLn)d(k)m(eyw)m -(ord.)71 b(FTTNULLL)39 b(is)i(iden)m(tical)h(to)e(FTTNUL)g(except)h -(that)g(the)f(tn)m(ull)h(v)-5 b(alue)40 b(is)h(a)227 -1872 y(64-bit)32 b(in)m(teger)g(instead)e(of)h(a)g(32-bit)g(in)m -(teger.)382 2123 y Fe(FTTNUL\(unit,colnum,tnull)41 b(>)47 -b(status\))382 2236 y(FTTNULLL\(unit,colnum,tnu)o(lll)o(l)42 -b(>)47 b(status\))0 2569 y Fd(6.6)135 b(FITS)44 b(Primary)h(Arra)l(y)g -(or)g(IMA)l(GE)g(Extension)h(I/O)f(Subroutines)0 2819 -y Fi(These)26 b(subroutines)f(put)h(or)h(get)g(data)h(v)-5 -b(alues)26 b(in)h(the)f(primary)g(data)h(arra)m(y)g(\(i.e.,)i(the)e -(\014rst)f(HDU)h(in)f(the)h(FITS)0 2932 y(\014le\))35 -b(or)g(an)f(IMA)m(GE)i(extension.)54 b(The)34 b(data)i(arra)m(y)f(is)f -(represen)m(ted)h(as)g(a)g(single)g(one-dimensional)h(arra)m(y)f(of)0 -3045 y(pixels)h(regardless)h(of)f(the)g(actual)h(dimensionalit)m(y)g -(of)g(the)f(arra)m(y)-8 b(,)38 b(and)e(the)g(FPIXEL)g(parameter)g(giv)m -(es)i(the)0 3158 y(p)s(osition)28 b(within)e(this)i(1-D)g(arra)m(y)g -(of)g(the)g(\014rst)e(pixel)i(to)g(read)g(or)f(write.)40 -b(Automatic)29 b(data)f(t)m(yp)s(e)g(con)m(v)m(ersion)h(is)0 -3270 y(p)s(erformed)g(for)i(n)m(umeric)g(data)g(\(except)i(for)d -(complex)i(data)f(t)m(yp)s(es\))h(if)f(the)g(data)g(t)m(yp)s(e)g(of)g -(the)g(primary)f(arra)m(y)0 3383 y(\(de\014ned)e(b)m(y)g(the)h(BITPIX)f -(k)m(eyw)m(ord\))h(di\013ers)g(from)f(the)g(data)i(t)m(yp)s(e)e(of)h -(the)g(arra)m(y)g(in)f(the)h(calling)h(subroutine.)0 -3496 y(The)41 b(data)i(v)-5 b(alues)42 b(are)g(also)h(scaled)f(b)m(y)g -(the)g(BSCALE)f(and)g(BZER)m(O)h(header)f(v)-5 b(alues)42 -b(as)g(they)g(are)g(b)s(eing)0 3609 y(written)32 b(or)g(read)g(from)g -(the)g(FITS)g(arra)m(y)-8 b(.)47 b(The)31 b(ftpscl)i(subroutine)e(MUST) -g(b)s(e)h(called)h(to)g(de\014ne)e(the)i(scaling)0 3722 -y(parameters)h(when)e(writing)i(data)g(to)g(the)g(FITS)f(arra)m(y)h(or) -f(to)h(o)m(v)m(erride)h(the)f(default)f(scaling)i(v)-5 -b(alue)34 b(giv)m(en)g(in)0 3835 y(the)d(header)f(when)f(reading)i(the) -f(FITS)g(arra)m(y)-8 b(.)0 3995 y(Tw)m(o)41 b(sets)f(of)h(subroutines)e -(are)i(pro)m(vided)f(to)h(read)g(the)f(data)i(arra)m(y)f(whic)m(h)f -(di\013er)g(in)g(the)h(w)m(a)m(y)g(unde\014ned)0 4108 -y(pixels)35 b(are)h(handled.)55 b(The)35 b(\014rst)f(set)i(of)g -(routines)f(\(FTGPVx\))h(simply)f(return)f(an)h(arra)m(y)h(of)g(data)g -(elemen)m(ts)0 4221 y(in)c(whic)m(h)g(unde\014ned)e(pixels)i(are)h(set) -f(equal)h(to)g(a)g(v)-5 b(alue)32 b(sp)s(eci\014ed)g(b)m(y)g(the)g -(user)g(in)g(the)g('n)m(ullv)-5 b(al')33 b(parameter.)0 -4334 y(An)h(additional)i(feature)f(of)f(these)h(subroutines)f(is)g -(that)i(if)e(the)h(user)f(sets)h(n)m(ullv)-5 b(al)35 -b(=)f(0,)i(then)f(no)f(c)m(hec)m(ks)i(for)0 4447 y(unde\014ned)d -(pixels)j(will)g(b)s(e)e(p)s(erformed,)i(th)m(us)f(increasing)h(the)g -(sp)s(eed)e(of)i(the)g(program.)55 b(The)35 b(second)h(set)g(of)0 -4560 y(routines)31 b(\(FTGPFx\))i(returns)d(the)i(data)g(elemen)m(t)h -(arra)m(y)f(and,)f(in)h(addition,)g(a)g(logical)i(arra)m(y)e(whic)m(h)f -(de\014nes)0 4673 y(whether)40 b(the)g(corresp)s(onding)f(data)i(pixel) -g(is)f(unde\014ned.)69 b(The)39 b(latter)j(set)f(of)f(subroutines)f(ma) -m(y)i(b)s(e)f(more)0 4785 y(con)m(v)m(enien)m(t)33 b(to)g(use)e(in)g -(some)g(circumstances,)i(ho)m(w)m(ev)m(er,)g(it)f(requires)f(an)g -(additional)h(arra)m(y)g(of)g(logical)i(v)-5 b(alues)0 -4898 y(whic)m(h)36 b(can)g(b)s(e)g(un)m(wieldy)f(when)h(w)m(orking)g -(with)g(large)h(data)g(arra)m(ys.)58 b(Also)37 b(for)f(programmer)g -(con)m(v)m(enience,)0 5011 y(sets)j(of)g(subroutines)f(to)h(directly)h -(read)e(or)h(write)g(2)g(and)g(3)g(dimensional)g(arra)m(ys)g(ha)m(v)m -(e)h(b)s(een)e(pro)m(vided,)j(as)0 5124 y(w)m(ell)31 -b(as)f(a)g(set)g(of)g(subroutines)e(to)i(read)g(or)g(write)f(an)m(y)h -(con)m(tiguous)h(rectangular)g(subset)e(of)h(pixels)g(within)f(the)0 -5237 y(n-dimensional)h(arra)m(y)-8 b(.)0 5488 y Fh(1)81 -b Fi(Get)39 b(the)g(data)h(t)m(yp)s(e)e(of)h(the)g(image)h(\(=)f -(BITPIX)f(v)-5 b(alue\).)67 b(P)m(ossible)39 b(returned)f(v)-5 -b(alues)39 b(are:)58 b(8,)41 b(16,)h(32,)227 5601 y(64,)36 -b(-32,)h(or)d(-64)h(corresp)s(onding)e(to)h(unsigned)f(b)m(yte,)j -(signed)e(2-b)m(yte)h(in)m(teger,)i(signed)d(4-b)m(yte)h(in)m(teger,) -227 5714 y(signed)c(8-b)m(yte)g(in)m(teger,)h(real,)g(and)d(double.)p -eop end -%%Page: 53 59 -TeXDict begin 53 58 bop 0 299 a Fg(6.6.)72 b(FITS)30 -b(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)31 b(OR)f(IMA)m(GE)h(EXTENSION)e(I/O)i -(SUBR)m(OUTINES)589 b Fi(53)227 555 y(The)26 b(second)f(subroutine)g -(is)h(similar)g(to)g(FTGIDT,)h(except)f(that)h(if)f(the)f(image)j -(pixel)e(v)-5 b(alues)26 b(are)g(scaled,)227 668 y(with)h(non-default)g -(v)-5 b(alues)27 b(for)g(the)h(BZER)m(O)f(and)f(BSCALE)g(k)m(eyw)m -(ords,)j(then)e(this)g(routine)g(will)g(return)227 781 -y(the)32 b('equiv)-5 b(alen)m(t')33 b(data)e(t)m(yp)s(e)h(that)f(is)g -(needed)g(to)h(store)g(the)f(scaled)h(v)-5 b(alues.)43 -b(F)-8 b(or)32 b(example,)g(if)f(BITPIX)227 894 y(=)39 -b(16)g(and)g(BSCALE)f(=)g(0.1)i(then)f(the)g(equiv)-5 -b(alen)m(t)40 b(data)f(t)m(yp)s(e)g(is)g(\015oating)h(p)s(oin)m(t,)h -(and)d(-32)i(will)g(b)s(e)227 1007 y(returned.)65 b(There)39 -b(are)g(2)g(sp)s(ecial)h(cases:)58 b(if)39 b(the)g(image)h(con)m(tains) -g(unsigned)e(2-b)m(yte)i(in)m(teger)g(v)-5 b(alues,)227 -1120 y(with)40 b(BITPIX)g(=)f(16,)44 b(BSCALE)39 b(=)h(1,)j(and)c(BZER) -m(O)h(=)g(32768,)45 b(then)39 b(this)h(routine)g(will)h(return)e(a)227 -1233 y(non-standard)26 b(v)-5 b(alue)27 b(of)g(20)h(for)f(the)g(bitpix) -g(v)-5 b(alue.)40 b(Similarly)27 b(if)f(the)i(image)g(con)m(tains)g -(unsigned)e(4-b)m(yte)227 1346 y(in)m(tegers,)32 b(then)e(bitpix)g -(will)h(b)s(e)f(returned)f(with)h(a)h(v)-5 b(alue)31 -b(of)f(40.)382 1602 y Fe(FTGIDT\(unit,)44 b(>)k(bitpix,status\))382 -1715 y(FTGIET\(unit,)c(>)k(bitpix,status\))0 1971 y Fh(2)81 -b Fi(Get)31 b(the)g(dimension)e(\(n)m(um)m(b)s(er)h(of)g(axes)h(=)f -(NAXIS\))h(of)f(the)h(image)382 2227 y Fe(FTGIDM\(unit,)44 -b(>)k(naxis,status\))0 2484 y Fh(3)81 b Fi(Get)38 b(the)f(size)h(of)f -(all)h(the)f(dimensions)g(of)g(the)g(image.)62 b(The)37 -b(FTGISZLL)e(routine)i(returns)f(an)h(arra)m(y)h(of)227 -2597 y(64-bit)32 b(in)m(tegers)g(instead)e(of)h(32-bit)g(in)m(tegers.) -382 2853 y Fe(FTGISZ\(unit,)44 b(maxdim,)i(>)i(naxes,status\))382 -2966 y(FTGISZLL\(unit,)c(maxdim,)i(>)h(naxesll,status\))0 -3222 y Fh(4)81 b Fi(Get)35 b(the)f(parameters)g(that)h(de\014ne)e(the)h -(t)m(yp)s(e)g(and)g(size)g(of)h(the)f(image.)53 b(This)33 -b(routine)h(simply)f(com)m(bines)227 3335 y(calls)40 -b(to)f(the)g(ab)s(o)m(v)m(e)h(3)f(routines.)65 b(The)38 -b(FTGIPRLL)g(routine)h(returns)e(an)i(arra)m(y)g(of)g(64-bit)h(in)m -(tegers)227 3448 y(instead)31 b(of)f(32-bit)i(in)m(tegers.)382 -3704 y Fe(FTGIPR\(unit,)44 b(maxdim,)i(>)i(bitpix,)d(naxis,)h(naxes,)h -(int)f(*status\))382 3817 y(FTGIPRLL\(unit,)e(maxdim,)i(>)h(bitpix,)f -(naxis,)g(naxesll,)f(int)i(*status\))0 4073 y Fh(5)81 -b Fi(Put)30 b(elemen)m(ts)h(in)m(to)h(the)e(data)h(arra)m(y)382 -4330 y Fe(FTPPR[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o(eme)o(nts,)o -(valu)o(es,)41 b(>)48 b(status\))0 4586 y Fh(6)81 b Fi(Put)30 -b(elemen)m(ts)i(in)m(to)f(the)g(data)g(arra)m(y)-8 b(,)32 -b(substituting)e(the)g(appropriate)h(FITS)f(n)m(ull)g(v)-5 -b(alue)31 b(for)f(all)i(elemen)m(ts)227 4699 y(whic)m(h)c(are)f(equal)i -(to)f(the)f(v)-5 b(alue)28 b(of)g(NULL)-10 b(V)g(AL.)28 -b(F)-8 b(or)28 b(in)m(teger)h(FITS)e(arra)m(ys,)i(the)e(n)m(ull)h(v)-5 -b(alue)28 b(de\014ned)e(b)m(y)227 4812 y(the)k(previous)f(call)i(to)g -(FTPNUL)e(will)h(b)s(e)f(substituted;)h(for)f(\015oating)i(p)s(oin)m(t) -f(FITS)f(arra)m(ys)h(\(BITPIX)f(=)227 4925 y(-32)j(or)e(-64\))i(then)e -(the)h(sp)s(ecial)g(IEEE)e(NaN)i(\(Not-a-Num)m(b)s(er\))h(v)-5 -b(alue)31 b(will)g(b)s(e)f(substituted.)382 5181 y Fe -(FTPPN[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o(eme)o(nts,)o(valu)o -(es,)o(null)o(val)41 b(>)48 b(status\))0 5437 y Fh(7)81 -b Fi(Set)30 b(data)h(arra)m(y)g(elemen)m(ts)h(as)e(unde\014ned)382 -5694 y Fe(FTPPRU\(unit,group,fpixel)o(,ne)o(leme)o(nts,)41 -b(>)47 b(status\))p eop end -%%Page: 54 60 -TeXDict begin 54 59 bop 0 299 a Fi(54)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)0 555 y Fh(8)81 b Fi(Get)36 b(elemen)m(ts)g(from)f -(the)g(data)h(arra)m(y)-8 b(.)55 b(Unde\014ned)34 b(arra)m(y)h(elemen)m -(ts)i(will)e(b)s(e)g(returned)f(with)g(a)i(v)-5 b(alue)35 -b(=)227 668 y(n)m(ullv)-5 b(al,)31 b(unless)f(n)m(ullv)-5 -b(al)31 b(=)f(0)h(in)f(whic)m(h)g(case)h(no)g(c)m(hec)m(ks)g(for)g -(unde\014ned)d(pixels)i(will)h(b)s(e)f(p)s(erformed.)382 -914 y Fe(FTGPV[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o(eme)o(nts,)o -(null)o(val)o(,)42 b(>)47 b(values,anyf,status\))0 1160 -y Fh(9)81 b Fi(Get)32 b(elemen)m(ts)g(and)f(n)m(ull\015ags)g(from)g -(data)h(arra)m(y)-8 b(.)44 b(An)m(y)32 b(unde\014ned)d(arra)m(y)i -(elemen)m(ts)i(will)e(ha)m(v)m(e)i(the)e(corre-)227 1273 -y(sp)s(onding)e(\015agv)-5 b(als)31 b(elemen)m(t)h(set)f(equal)g(to)g -(.TR)m(UE.)382 1519 y Fe(FTGPF[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel) -o(eme)o(nts,)41 b(>)48 b(values,flagvals,anyf,st)o(atu)o(s\))0 -1765 y Fh(10)e Fi(Put)30 b(v)-5 b(alues)31 b(in)m(to)g(group)f -(parameters)382 2011 y Fe(FTPGP[BIJKED]\(unit,group)o(,fp)o(arm,)o -(npar)o(m,v)o(alue)o(s,)42 b(>)47 b(status\))0 2257 y -Fh(11)f Fi(Get)31 b(v)-5 b(alues)31 b(from)f(group)g(parameters)382 -2503 y Fe(FTGGP[BIJKED]\(unit,group)o(,fp)o(arm,)o(npar)o(m,)41 -b(>)48 b(values,status\))0 2749 y Fi(The)32 b(follo)m(wing)h(4)g -(subroutines)e(transfer)g(FITS)h(images)h(with)f(2)g(or)g(3)h -(dimensions)e(to)i(or)f(from)g(a)h(data)f(arra)m(y)0 -2862 y(whic)m(h)h(has)g(b)s(een)g(declared)g(in)g(the)h(calling)h -(program.)49 b(The)33 b(dimensionalit)m(y)h(of)g(the)f(FITS)g(image)h -(is)f(passed)0 2975 y(b)m(y)26 b(the)g(naxis1,)h(naxis2,)h(and)d -(naxis3)i(parameters)f(and)f(the)h(declared)h(dimensions)e(of)h(the)g -(program)g(arra)m(y)h(are)0 3088 y(passed)k(in)f(the)i(dim1)e(and)h -(dim2)g(parameters.)43 b(Note)32 b(that)g(the)f(program)g(arra)m(y)g -(do)s(es)g(not)g(ha)m(v)m(e)i(to)e(ha)m(v)m(e)i(the)0 -3201 y(same)28 b(dimensions)f(as)h(the)g(FITS)e(arra)m(y)-8 -b(,)30 b(but)d(m)m(ust)g(b)s(e)g(at)i(least)f(as)g(big.)40 -b(F)-8 b(or)29 b(example)f(if)f(a)h(FITS)f(image)i(with)0 -3314 y(NAXIS1)i(=)f(NAXIS2)h(=)f(400)i(is)e(read)h(in)m(to)g(a)g -(program)f(arra)m(y)h(whic)m(h)f(is)h(dimensioned)f(as)g(512)i(x)f(512) -g(pixels,)0 3427 y(then)d(the)g(image)i(will)e(just)g(\014ll)g(the)h -(lo)m(w)m(er)g(left)g(corner)f(of)h(the)f(arra)m(y)h(with)f(pixels)g -(in)g(the)h(range)f(1)h(-)f(400)i(in)e(the)0 3540 y(X)k(an)g(Y)h -(directions.)47 b(This)31 b(has)h(the)h(e\013ect)g(of)g(taking)g(a)g -(con)m(tiguous)g(set)g(of)f(pixel)h(v)-5 b(alue)33 b(in)e(the)i(FITS)e -(arra)m(y)0 3653 y(and)k(writing)g(them)g(to)h(a)g(non-con)m(tiguous)g -(arra)m(y)f(in)g(program)g(memory)g(\(i.e.,)j(there)e(are)f(no)m(w)h -(some)f(blank)0 3766 y(pixels)c(around)e(the)h(edge)i(of)e(the)h(image) -g(in)f(the)h(program)f(arra)m(y\).)0 4012 y Fh(11)46 -b Fi(Put)30 b(2-D)i(image)f(in)m(to)h(the)e(data)h(arra)m(y)382 -4258 y Fe(FTP2D[BIJKED]\(unit,group)o(,di)o(m1,n)o(axis)o(1,n)o(axis)o -(2,im)o(age)o(,)42 b(>)47 b(status\))0 4504 y Fh(12)f -Fi(Put)30 b(3-D)i(cub)s(e)d(in)m(to)j(the)e(data)h(arra)m(y)382 -4750 y Fe(FTP3D[BIJKED]\(unit,group)o(,di)o(m1,d)o(im2,)o(nax)o(is1,)o -(naxi)o(s2,)o(naxi)o(s3,c)o(ube)o(,)42 b(>)47 b(status\))0 -4996 y Fh(13)f Fi(Get)29 b(2-D)f(image)h(from)f(the)f(data)i(arra)m(y) --8 b(.)41 b(Unde\014ned)26 b(pixels)h(in)h(the)g(arra)m(y)g(will)g(b)s -(e)f(set)h(equal)g(to)h(the)e(v)-5 b(alue)227 5109 y(of)31 -b('n)m(ullv)-5 b(al',)31 b(unless)f(n)m(ullv)-5 b(al=0)31 -b(in)f(whic)m(h)g(case)i(no)e(testing)i(for)e(unde\014ned)e(pixels)i -(will)h(b)s(e)f(p)s(erformed.)382 5355 y Fe(FTG2D[BIJKED]\(unit,group)o -(,nu)o(llva)o(l,di)o(m1,)o(naxi)o(s1,n)o(axi)o(s2,)41 -b(>)48 b(image,anyf,status\))0 5601 y Fh(14)e Fi(Get)31 -b(3-D)h(cub)s(e)e(from)g(the)g(data)h(arra)m(y)-8 b(.)42 -b(Unde\014ned)29 b(pixels)i(in)f(the)g(arra)m(y)h(will)g(b)s(e)f(set)h -(equal)g(to)g(the)f(v)-5 b(alue)227 5714 y(of)31 b('n)m(ullv)-5 -b(al',)31 b(unless)f(n)m(ullv)-5 b(al=0)31 b(in)f(whic)m(h)g(case)i(no) -e(testing)i(for)e(unde\014ned)e(pixels)i(will)h(b)s(e)f(p)s(erformed.)p -eop end -%%Page: 55 61 -TeXDict begin 55 60 bop 0 299 a Fg(6.7.)72 b(FITS)30 -b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 -b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fi(55)382 555 -y Fe(FTG3D[BIJKED]\(unit,group)o(,nu)o(llva)o(l,di)o(m1,)o(dim2)o(,nax) -o(is1)o(,nax)o(is2,)o(nax)o(is3,)41 b(>)1002 668 y(cube,anyf,status\))0 -933 y Fi(The)i(follo)m(wing)h(subroutines)e(transfer)h(a)h(rectangular) -g(subset)e(of)i(the)f(pixels)g(in)g(a)h(FITS)e(N-dimensional)0 -1045 y(image)31 b(to)g(or)f(from)f(an)h(arra)m(y)g(whic)m(h)g(has)g(b)s -(een)f(declared)h(in)g(the)g(calling)i(program.)40 b(The)29 -b(fpixels)h(and)f(lpixels)0 1158 y(parameters)e(are)h(in)m(teger)g -(arra)m(ys)g(whic)m(h)f(sp)s(ecify)f(the)i(starting)g(and)e(ending)h -(pixels)g(in)g(eac)m(h)h(dimension)e(of)i(the)0 1271 -y(FITS)36 b(image)i(that)f(are)g(to)h(b)s(e)e(read)g(or)h(written.)60 -b(\(Note)38 b(that)g(these)f(are)g(the)g(starting)g(and)f(ending)h -(pixels)0 1384 y(in)d(the)h(FITS)f(image,)k(not)d(in)f(the)h(declared)g -(arra)m(y\).)55 b(The)34 b(arra)m(y)i(parameter)f(is)g(treated)g -(simply)g(as)g(a)g(large)0 1497 y(one-dimensional)c(arra)m(y)f(of)h -(the)f(appropriate)g(datat)m(yp)s(e)h(con)m(taining)h(the)e(pixel)g(v) --5 b(alues;)31 b(The)e(pixel)i(v)-5 b(alues)30 b(in)0 -1610 y(the)c(FITS)f(arra)m(y)i(are)f(read/written)g(from/to)h(this)f -(program)f(arra)m(y)i(in)e(strict)i(sequence)f(without)g(an)m(y)h -(gaps;)g(it)0 1723 y(is)i(up)e(to)j(the)f(calling)h(routine)f(to)g -(correctly)h(in)m(terpret)f(the)g(dimensionalit)m(y)h(of)f(this)g(arra) -m(y)-8 b(.)41 b(The)28 b(t)m(w)m(o)i(families)0 1836 -y(of)d(FITS)g(reading)g(routines)g(\(FTGSVx)g(and)g(FTGSFx)g -(subroutines\))f(also)j(ha)m(v)m(e)f(an)f('incs')h(parameter)f(whic)m -(h)0 1949 y(de\014nes)j(the)h(data)h(sampling)e(in)m(terv)-5 -b(al)32 b(in)f(eac)m(h)h(dimension)e(of)h(the)g(FITS)f(arra)m(y)-8 -b(.)43 b(F)-8 b(or)32 b(example,)g(if)f(incs\(1\)=2)0 -2062 y(and)i(incs\(2\)=3)h(when)f(reading)g(a)h(2-dimensional)g(FITS)f -(image,)i(then)e(only)h(ev)m(ery)g(other)f(pixel)h(in)f(the)h(\014rst)0 -2175 y(dimension)e(and)h(ev)m(ery)h(3rd)e(pixel)i(in)f(the)g(second)g -(dimension)f(will)i(b)s(e)e(returned)g(in)h(the)g('arra)m(y')h -(parameter.)0 2287 y([Note:)39 b(the)25 b(FTGSSx)f(family)i(of)e -(routines)h(whic)m(h)g(w)m(ere)g(presen)m(t)g(in)f(previous)g(v)m -(ersions)h(of)g(FITSIO)f(ha)m(v)m(e)i(b)s(een)0 2400 -y(sup)s(erseded)i(b)m(y)j(the)f(more)h(general)g(FTGSVx)f(family)h(of)g -(routines.])0 2665 y Fh(15)46 b Fi(Put)30 b(an)g(arbitrary)g(data)h -(subsection)g(in)m(to)g(the)g(data)g(arra)m(y)-8 b(.)382 -2929 y Fe(FTPSS[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o(s,f)o(pixe)o -(ls,l)o(pix)o(els,)o(arra)o(y,)41 b(>)48 b(status\))0 -3194 y Fh(16)e Fi(Get)30 b(an)e(arbitrary)g(data)i(subsection)e(from)g -(the)h(data)g(arra)m(y)-8 b(.)42 b(Unde\014ned)27 b(pixels)h(in)h(the)f -(arra)m(y)i(will)e(b)s(e)g(set)227 3306 y(equal)k(to)h(the)e(v)-5 -b(alue)33 b(of)e('n)m(ullv)-5 b(al',)33 b(unless)e(n)m(ullv)-5 -b(al=0)33 b(in)e(whic)m(h)g(case)i(no)e(testing)i(for)e(unde\014ned)f -(pixels)227 3419 y(will)h(b)s(e)f(p)s(erformed.)382 3684 -y Fe(FTGSV[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o(s,f)o(pixe)o(ls,l) -o(pix)o(els,)o(incs)o(,nu)o(llva)o(l,)42 b(>)1002 3797 -y(array,anyf,status\))0 4061 y Fh(17)k Fi(Get)34 b(an)f(arbitrary)g -(data)g(subsection)g(from)g(the)g(data)g(arra)m(y)-8 -b(.)50 b(An)m(y)33 b(Unde\014ned)e(pixels)i(in)g(the)g(arra)m(y)h(will) -227 4174 y(ha)m(v)m(e)e(the)e(corresp)s(onding)g('\015agv)-5 -b(als')31 b(elemen)m(t)h(set)f(equal)g(to)g(.TR)m(UE.)382 -4438 y Fe(FTGSF[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o(s,f)o(pixe)o -(ls,l)o(pix)o(els,)o(incs)o(,)42 b(>)1002 4551 y -(array,flagvals,anyf,statu)o(s\))0 4890 y Fd(6.7)135 -b(FITS)44 b(ASCI)t(I)g(and)h(Binary)g(T)-11 b(able)45 -b(Data)h(I/O)f(Subroutines)0 5145 y Fb(6.7.1)112 b(Column)39 -b(Information)f(Subroutines)0 5357 y Fh(1)81 b Fi(Get)37 -b(the)f(n)m(um)m(b)s(er)f(of)i(ro)m(ws)f(or)g(columns)g(in)g(the)h -(curren)m(t)f(FITS)g(table.)59 b(The)36 b(n)m(um)m(b)s(er)f(of)h(ro)m -(ws)h(is)f(giv)m(en)227 5470 y(b)m(y)f(the)h(NAXIS2)f(k)m(eyw)m(ord)h -(and)f(the)g(n)m(um)m(b)s(er)f(of)h(columns)g(is)g(giv)m(en)h(b)m(y)g -(the)f(TFIELDS)g(k)m(eyw)m(ord)g(in)227 5583 y(the)d(header)f(of)h(the) -g(table.)45 b(The)31 b(FTGNR)-10 b(WLL)32 b(routine)g(is)f(iden)m -(tical)i(to)g(FTGNR)-10 b(W)32 b(except)h(that)f(the)227 -5696 y(n)m(um)m(b)s(er)d(of)i(ro)m(ws)f(is)h(returned)e(as)h(a)h -(64-bit)h(in)m(teger)g(rather)e(than)g(a)h(32-bit)g(in)m(teger.)p -eop end -%%Page: 56 62 -TeXDict begin 56 61 bop 0 299 a Fi(56)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)382 555 y Fe(FTGNRW\(unit,)44 b(>)k(nrows,)e(status\)) -382 668 y(FTGNRWLL\(unit,)e(>)j(nrowsll,)f(status\))382 -781 y(FTGNCL\(unit,)e(>)k(ncols,)e(status\))0 1044 y -Fh(2)81 b Fi(Get)25 b(the)f(table)i(column)e(n)m(um)m(b)s(er)f(\(and)h -(name\))h(of)f(the)h(column)f(whose)g(name)g(matc)m(hes)i(an)e(input)g -(template)227 1157 y(name.)38 b(The)21 b(table)i(column)e(names)h(are)g -(de\014ned)e(b)m(y)i(the)g(TTYPEn)e(k)m(eyw)m(ords)i(in)f(the)h(FITS)f -(header.)37 b(If)22 b(a)227 1270 y(column)i(do)s(es)g(not)g(ha)m(v)m(e) -h(a)f(TTYPEn)f(k)m(eyw)m(ord,)j(then)d(these)h(routines)g(assume)g -(that)g(the)h(name)e(consists)227 1383 y(of)i(all)h(blank)f(c)m -(haracters.)40 b(These)25 b(2)g(subroutines)e(p)s(erform)h(the)h(same)g -(function)g(except)h(that)f(FTGCNO)227 1496 y(only)j(returns)e(the)h(n) -m(um)m(b)s(er)f(of)h(the)g(matc)m(hing)i(column)e(whereas)g(FTGCNN)g -(also)h(returns)e(the)i(name)f(of)227 1609 y(the)k(column.)40 -b(If)30 b(CASESEN)f(=)h(.true.)41 b(then)30 b(the)h(column)f(name)g -(matc)m(h)i(will)e(b)s(e)g(case-sensitiv)m(e.)227 1761 -y(The)41 b(input)e(column)i(name)g(template)h(\(COL)-8 -b(TEMPLA)g(TE\))41 b(is)g(\(1\))g(either)h(the)f(exact)h(name)f(of)g -(the)227 1874 y(column)36 b(to)i(b)s(e)d(searc)m(hed)i(for,)h(or)e -(\(2\))i(it)f(ma)m(y)g(con)m(tain)g(wild)f(cards)g(c)m(haracters)i -(\(*,)h(?,)f(or)e(#\),)i(or)f(\(3\))227 1987 y(it)d(ma)m(y)g(con)m -(tain)g(the)f(n)m(um)m(b)s(er)f(of)h(the)g(desired)g(column)g(\(where)g -(the)g(n)m(um)m(b)s(er)f(is)h(expressed)f(as)h(ASCI)s(I)227 -2100 y(digits\).)41 b(The)28 b(\014rst)g(2)h(wild)f(cards)g(b)s(eha)m -(v)m(e)h(similarly)g(to)g(UNIX)g(\014lename)g(matc)m(hing:)40 -b(the)29 b('*')g(c)m(haracter)227 2213 y(matc)m(hes)e(an)m(y)g -(sequence)f(of)h(c)m(haracters)g(\(including)f(zero)h(c)m(haracters\))h -(and)d(the)i(')10 b(?')39 b(c)m(haracter)28 b(matc)m(hes)227 -2325 y(an)m(y)40 b(single)h(c)m(haracter.)71 b(The)39 -b(#)h(wildcard)f(will)h(matc)m(h)h(an)m(y)f(consecutiv)m(e)i(string)e -(of)g(decimal)g(digits)227 2438 y(\(0-9\).)45 b(As)31 -b(an)g(example,)h(the)f(template)h(strings)f('AB?DE',)h('AB*E',)h(and)d -('AB*CDE')j(will)e(all)h(matc)m(h)227 2551 y(the)26 b(string)g -('ABCDE'.)i(If)d(more)h(than)g(one)g(column)g(name)g(in)g(the)g(table)h -(matc)m(hes)g(the)f(template)i(string,)227 2664 y(then)33 -b(the)h(\014rst)f(matc)m(h)h(is)f(returned)g(and)f(the)i(status)g(v)-5 -b(alue)34 b(will)f(b)s(e)g(set)h(to)g(237)h(as)f(a)f(w)m(arning)h(that) -g(a)227 2777 y(unique)g(matc)m(h)i(w)m(as)f(not)g(found.)53 -b(T)-8 b(o)35 b(\014nd)f(the)h(other)g(cases)g(that)h(matc)m(h)g(the)f -(template,)i(simply)e(call)227 2890 y(the)27 b(subroutine)f(again)i -(lea)m(ving)h(the)e(input)f(status)h(v)-5 b(alue)28 b(equal)f(to)h(237) -g(and)f(the)g(next)g(matc)m(hing)h(name)227 3003 y(will)k(then)g(b)s(e) -f(returned.)43 b(Rep)s(eat)32 b(this)g(pro)s(cess)f(un)m(til)h(a)g -(status)g(=)g(219)h(\(column)e(name)h(not)g(found\))f(is)227 -3116 y(returned.)40 b(If)30 b(these)h(subroutines)e(fail)i(to)g(matc)m -(h)g(the)g(template)h(to)f(an)m(y)g(of)f(the)h(columns)f(in)g(the)h -(table,)227 3229 y(they)i(lastly)g(c)m(hec)m(k)h(if)f(the)f(template)i -(can)f(b)s(e)e(in)m(terpreted)i(as)g(a)g(simple)f(p)s(ositiv)m(e)h(in)m -(teger)h(\(e.g.,)h('7',)f(or)227 3342 y('512'\))i(and)d(if)g(so,)i -(they)f(return)e(that)j(column)e(n)m(um)m(b)s(er.)49 -b(If)33 b(no)g(matc)m(hes)i(are)f(found)e(then)h(a)h(status)g(=)227 -3455 y(219)e(error)e(is)g(returned.)227 3607 y(Note)h(that)e(the)h -(FITS)e(Standard)g(recommends)g(that)i(only)f(letters,)i(digits,)f(and) -f(the)g(underscore)f(c)m(har-)227 3719 y(acter)44 b(b)s(e)e(used)g(in)h -(column)f(names)h(\(with)g(no)f(em)m(b)s(edded)g(spaces)h(in)g(the)g -(name\).)78 b(T)-8 b(railing)43 b(blank)227 3832 y(c)m(haracters)32 -b(are)f(not)f(signi\014can)m(t.)382 4096 y Fe -(FTGCNO\(unit,casesen,colt)o(emp)o(late)o(,)42 b(>)47 -b(colnum,status\))382 4209 y(FTGCNN\(unit,casesen,colt)o(emp)o(late)o -(,)42 b(>)47 b(colname,colnum,status\))0 4472 y Fh(3)81 -b Fi(Get)39 b(the)g(datat)m(yp)s(e)h(of)e(a)h(column)g(in)f(an)g(ASCI)s -(I)g(or)g(binary)g(table.)66 b(This)38 b(routine)h(returns)e(an)i(in)m -(teger)227 4585 y(co)s(de)34 b(v)-5 b(alue)33 b(corresp)s(onding)f(to)i -(the)g(datat)m(yp)s(e)g(of)f(the)g(column.)49 b(\(See)34 -b(the)f(FTBNFM)i(and)d(FT)-8 b(ASFM)227 4698 y(subroutines)27 -b(in)h(the)g(Utilities)j(section)e(of)f(this)g(do)s(cumen)m(t)g(for)g -(a)h(list)g(of)f(the)h(co)s(de)f(v)-5 b(alues\).)41 b(The)27 -b(v)m(ector)227 4811 y(rep)s(eat)38 b(coun)m(t)g(\(whic)m(h)g(is)g(alw) -m(a)m(y)h(1)f(for)g(ASCI)s(I)e(table)i(columns\))g(is)g(also)g -(returned.)62 b(If)37 b(the)h(sp)s(eci\014ed)227 4924 -y(column)32 b(has)f(an)g(ASCI)s(I)f(c)m(haracter)j(datat)m(yp)s(e)g -(\(co)s(de)f(=)f(16\))i(then)e(the)h(width)e(of)i(a)g(unit)f(string)h -(in)f(the)227 5036 y(column)i(is)g(also)h(returned.)48 -b(Note)34 b(that)g(this)e(routine)h(supp)s(orts)f(the)h(lo)s(cal)h(con) -m(v)m(en)m(tion)h(for)e(sp)s(ecifying)227 5149 y(arra)m(ys)f(of)f -(strings)g(within)f(a)i(binary)e(table)i(c)m(haracter)g(column,)g -(using)e(the)h(syn)m(tax)h(TF)m(ORM)f(=)g('rAw')227 5262 -y(where)f('r')g(is)h(the)f(total)i(n)m(um)m(b)s(er)d(of)i(c)m -(haracters)g(\(=)g(the)f(width)g(of)g(the)g(column\))h(and)f('w')g(is)g -(the)h(width)227 5375 y(of)39 b(a)f(unit)g(string)g(within)g(the)g -(column.)64 b(Th)m(us)37 b(if)h(the)g(column)g(has)g(TF)m(ORM)h(=)f -('60A12')i(then)e(this)227 5488 y(routine)29 b(will)g(return)f(dataco)s -(de)i(=)e(16,)i(rep)s(eat)f(=)f(60,)j(and)d(width)g(=)g(12.)41 -b(\(The)29 b(TDIMn)f(k)m(eyw)m(ord)h(ma)m(y)227 5601 -y(also)35 b(b)s(e)e(used)g(to)h(sp)s(ecify)f(the)h(unit)f(string)h -(length;)i(The)d(pair)g(of)h(k)m(eyw)m(ords)g(TF)m(ORMn)f(=)g('60A')j -(and)227 5714 y(TDIMn)30 b(=)g('\(12,5\)')j(w)m(ould)e(ha)m(v)m(e)g -(the)g(same)g(e\013ect)g(as)g(TF)m(ORMn)f(=)g('60A12'\).)p -eop end -%%Page: 57 63 -TeXDict begin 57 62 bop 0 299 a Fg(6.7.)72 b(FITS)30 -b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 -b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fi(57)227 555 -y(The)31 b(second)h(routine,)g(FTEQTY)f(is)g(similar)h(except)h(that)f -(in)f(the)h(case)g(of)g(scaled)g(in)m(teger)h(columns)e(it)227 -668 y(returns)23 b(the)h('equiv)-5 b(alen)m(t')25 b(data)f(t)m(yp)s(e)g -(that)h(is)e(needed)h(to)g(store)g(the)g(scaled)g(v)-5 -b(alues,)26 b(and)d(not)h(necessarily)227 781 y(the)38 -b(ph)m(ysical)h(data)f(t)m(yp)s(e)g(of)g(the)g(unscaled)g(v)-5 -b(alues)38 b(as)g(stored)g(in)g(the)g(FITS)f(table.)64 -b(F)-8 b(or)38 b(example)h(if)227 894 y(a)c('1I')g(column)f(in)g(a)g -(binary)g(table)h(has)f(TSCALn)f(=)g(1)i(and)f(TZER)m(On)f(=)g(32768,) -38 b(then)c(this)g(column)227 1007 y(e\013ectiv)m(ely)27 -b(con)m(tains)e(unsigned)e(short)g(in)m(teger)j(v)-5 -b(alues,)25 b(and)f(th)m(us)f(the)h(returned)f(v)-5 b(alue)24 -b(of)g(t)m(yp)s(eco)s(de)h(will)227 1120 y(b)s(e)32 b(the)h(co)s(de)g -(for)g(an)f(unsigned)g(short)g(in)m(teger,)j(not)e(a)g(signed)g(short)f -(in)m(teger.)49 b(Similarly)-8 b(,)34 b(if)f(a)g(column)227 -1233 y(has)d(TTYPEn)g(=)g('1I')h(and)f(TSCALn)e(=)i(0.12,)j(then)d(the) -g(returned)g(t)m(yp)s(eco)s(de)g(will)h(b)s(e)f(the)h(co)s(de)f(for)h -(a)227 1346 y('real')h(column.)382 1611 y Fe(FTGTCL\(unit,colnum,)42 -b(>)48 b(datacode,repeat,width,st)o(atu)o(s\))382 1724 -y(FTEQTY\(unit,colnum,)42 b(>)48 b(datacode,repeat,width,st)o(atu)o -(s\))0 1989 y Fh(4)81 b Fi(Return)22 b(the)i(displa)m(y)g(width)f(of)g -(a)h(column.)39 b(This)22 b(is)i(the)g(length)g(of)f(the)h(string)g -(that)g(will)g(b)s(e)f(returned)f(when)227 2102 y(reading)33 -b(the)g(column)g(as)g(a)g(formatted)g(string.)48 b(The)32 -b(displa)m(y)h(width)f(is)h(determined)g(b)m(y)f(the)h(TDISPn)227 -2215 y(k)m(eyw)m(ord,)e(if)g(presen)m(t,)f(otherwise)h(b)m(y)f(the)h -(data)g(t)m(yp)s(e)g(of)f(the)h(column.)382 2480 y Fe(FTGCDW\(unit,)44 -b(colnum,)i(>)i(dispwidth,)d(status\))0 2745 y Fh(5)81 -b Fi(Get)29 b(information)f(ab)s(out)g(an)g(existing)h(ASCI)s(I)e -(table)i(column.)40 b(\(NOTE:)28 b(TSCAL)f(and)g(TZER)m(O)h(m)m(ust)g -(b)s(e)227 2858 y(declared)j(as)g(Double)g(Precision)g(v)-5 -b(ariables\).)41 b(All)31 b(the)g(returned)e(parameters)i(are)f(scalar) -i(quan)m(tities.)382 3123 y Fe(FTGACL\(unit,colnum,)42 -b(>)716 3236 y(ttype,tbcol,tunit,tform,)o(tsca)o(l,t)o(zero)o(,snu)o -(ll,)o(tdis)o(p,st)o(atu)o(s\))0 3501 y Fh(6)81 b Fi(Get)29 -b(information)f(ab)s(out)f(an)h(existing)h(binary)e(table)i(column.)40 -b(\(NOTE:)28 b(TSCAL)e(and)i(TZER)m(O)f(m)m(ust)h(b)s(e)227 -3614 y(declared)j(as)f(Double)g(Precision)h(v)-5 b(ariables\).)41 -b(D)m(A)-8 b(T)g(A)g(TYPE)32 b(is)e(a)g(c)m(haracter)i(string)d(whic)m -(h)h(returns)f(the)227 3727 y(datat)m(yp)s(e)35 b(of)g(the)f(column)g -(as)g(de\014ned)f(b)m(y)h(the)g(TF)m(ORMn)g(k)m(eyw)m(ord)h(\(e.g.,)i -('I',)e('J','E',)g('D',)g(etc.\).)54 b(In)227 3840 y(the)27 -b(case)g(of)g(an)f(ASCI)s(I)f(c)m(haracter)j(column,)f(D)m(A)-8 -b(T)g(A)g(TYPE)29 b(will)d(ha)m(v)m(e)i(a)f(v)-5 b(alue)27 -b(of)f(the)h(form)f('An')g(where)227 3953 y('n')34 b(is)g(an)g(in)m -(teger)i(expressing)e(the)g(width)f(of)h(the)h(\014eld)e(in)h(c)m -(haracters.)53 b(F)-8 b(or)35 b(example,)h(if)e(TF)m(ORM)g(=)227 -4066 y('160A8')39 b(then)e(FTGBCL)f(will)h(return)f(D)m(A)-8 -b(T)g(A)g(TYPE='A8')39 b(and)d(REPEA)-8 b(T=20.)60 b(All)37 -b(the)g(returned)227 4179 y(parameters)31 b(are)g(scalar)g(quan)m -(tities.)382 4444 y Fe(FTGBCL\(unit,colnum,)42 b(>)716 -4557 y(ttype,tunit,datatype,rep)o(eat,)o(tsc)o(al,t)o(zero)o(,tn)o -(ull,)o(tdis)o(p,s)o(tatu)o(s\))0 4822 y Fh(7)81 b Fi(Put)31 -b(\(app)s(end\))g(a)i(TDIMn)f(k)m(eyw)m(ord)g(whose)g(v)-5 -b(alue)33 b(has)f(the)g(form)g('\(l,m,n...\)')47 b(where)32 -b(l,)h(m,)f(n...)46 b(are)33 b(the)227 4935 y(dimensions)d(of)g(a)h(m)m -(ultidimensional)g(arra)m(y)g(column)f(in)g(a)h(binary)f(table.)382 -5200 y Fe(FTPTDM\(unit,colnum,naxis)o(,na)o(xes,)41 b(>)48 -b(status\))0 5465 y Fh(8)81 b Fi(Return)29 b(the)h(n)m(um)m(b)s(er)e -(of)i(and)g(size)g(of)g(the)g(dimensions)g(of)g(a)g(table)h(column.)40 -b(Normally)31 b(this)f(information)227 5578 y(is)h(giv)m(en)h(b)m(y)f -(the)g(TDIMn)f(k)m(eyw)m(ord,)i(but)e(if)h(this)g(k)m(eyw)m(ord)g(is)g -(not)g(presen)m(t)g(then)g(this)f(routine)h(returns)227 -5691 y(NAXIS)f(=)g(1)h(and)f(NAXES\(1\))h(equal)g(to)g(the)g(rep)s(eat) -g(coun)m(t)g(in)f(the)g(TF)m(ORM)h(k)m(eyw)m(ord.)p eop -end -%%Page: 58 64 -TeXDict begin 58 63 bop 0 299 a Fi(58)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)382 555 y Fe(FTGTDM\(unit,colnum,maxdi)o(m,)41 -b(>)48 b(naxis,naxes,status\))0 808 y Fh(9)81 b Fi(Deco)s(de)33 -b(the)g(input)f(TDIMn)h(k)m(eyw)m(ord)g(string)f(\(e.g.)50 -b('\(100,200\)'\))37 b(and)32 b(return)g(the)h(n)m(um)m(b)s(er)e(of)i -(and)f(size)227 921 y(of)c(the)g(dimensions)f(of)h(a)g(binary)f(table)h -(column.)40 b(If)27 b(the)h(input)f(tdimstr)g(c)m(haracter)i(string)f -(is)g(n)m(ull,)g(then)227 1034 y(this)d(routine)f(returns)f(naxis)h(=)h -(1)f(and)g(naxes[0])i(equal)e(to)i(the)e(rep)s(eat)h(coun)m(t)g(in)f -(the)g(TF)m(ORM)h(k)m(eyw)m(ord.)227 1147 y(This)30 b(routine)g(is)h -(called)g(b)m(y)f(FTGTDM.)382 1400 y Fe(FTDTDM\(unit,tdimstr,coln)o -(um,)o(maxd)o(im,)41 b(>)48 b(naxis,naxes,)c(status\))0 -1654 y Fh(10)i Fi(Return)32 b(the)h(optimal)h(n)m(um)m(b)s(er)e(of)h -(ro)m(ws)g(to)h(read)f(or)g(write)g(at)h(one)f(time)h(for)e(maxim)m(um) -h(I/O)g(e\016ciency)-8 b(.)227 1767 y(Refer)31 b(to)g(the)g -(\\Optimizing)g(Co)s(de")f(section)i(in)e(Chapter)g(5)g(for)h(more)f -(discussion)g(on)g(ho)m(w)h(to)g(use)f(this)227 1879 -y(routine.)382 2133 y Fe(FTGRSZ\(unit,)44 b(>)k(nrows,status\))0 -2422 y Fb(6.7.2)112 b(Lo)m(w-Lev)m(el)39 b(T)-9 b(able)38 -b(Access)f(Subroutines)0 2641 y Fi(The)d(follo)m(wing)h(subroutines)e -(pro)m(vide)i(lo)m(w-lev)m(el)i(access)e(to)g(the)g(data)g(in)f(ASCI)s -(I)e(or)i(binary)g(tables)h(and)f(are)0 2754 y(mainly)29 -b(useful)f(as)i(an)f(e\016cien)m(t)h(w)m(a)m(y)g(to)g(cop)m(y)g(all)g -(or)f(part)g(of)g(a)g(table)h(from)f(one)g(lo)s(cation)i(to)f(another.) -40 b(These)0 2867 y(routines)24 b(simply)g(read)g(or)h(write)f(the)h -(sp)s(eci\014ed)e(n)m(um)m(b)s(er)g(of)i(consecutiv)m(e)h(b)m(ytes)f -(in)f(an)g(ASCI)s(I)f(or)h(binary)g(table,)0 2980 y(without)37 -b(regard)g(for)f(column)h(b)s(oundaries)e(or)i(the)g(ro)m(w)g(length)h -(in)e(the)h(table.)61 b(The)37 b(\014rst)f(t)m(w)m(o)i(subroutines)0 -3093 y(read)29 b(or)h(write)g(consecutiv)m(e)h(b)m(ytes)f(in)f(a)h -(table)g(to)h(or)e(from)g(a)h(c)m(haracter)h(string)e(v)-5 -b(ariable,)31 b(while)f(the)f(last)i(t)m(w)m(o)0 3206 -y(subroutines)f(read)i(or)g(write)g(consecutiv)m(e)h(b)m(ytes)g(to)f -(or)g(from)f(a)h(v)-5 b(ariable)33 b(declared)f(as)g(a)g(n)m(umeric)f -(data)i(t)m(yp)s(e)0 3319 y(\(e.g.,)40 b(INTEGER,)d(INTEGER*2,)i(REAL,) -d(DOUBLE)h(PRECISION\).)f(These)g(routines)h(do)f(not)h(p)s(erform)0 -3432 y(an)m(y)c(mac)m(hine)g(dep)s(enden)m(t)f(data)i(con)m(v)m(ersion) -g(or)e(b)m(yte)i(sw)m(apping,)f(except)h(that)f(con)m(v)m(ersion)h -(to/from)f(ASCI)s(I)0 3544 y(format)d(is)g(p)s(erformed)e(b)m(y)h(the)h -(FTGTBS)f(and)g(FTPTBS)g(routines)h(on)f(mac)m(hines)h(whic)m(h)g(do)f -(not)h(use)f(ASCI)s(I)0 3657 y(c)m(haracter)j(co)s(des)e(in)g(the)h(in) -m(ternal)g(data)g(represen)m(tations)h(\(e.g.,)g(on)e(IBM)h(mainframe)f -(computers\).)0 3911 y Fh(1)81 b Fi(Read)26 b(a)h(consecutiv)m(e)h -(string)f(of)f(c)m(haracters)i(from)e(an)g(ASCI)s(I)f(table)i(in)m(to)h -(a)e(c)m(haracter)i(v)-5 b(ariable)28 b(\(spanning)227 -4024 y(columns)k(and)g(m)m(ultiple)h(ro)m(ws)f(if)g(necessary\))h(This) -f(routine)g(should)f(not)i(b)s(e)e(used)h(with)g(binary)f(tables)227 -4136 y(b)s(ecause)g(of)f(complications)i(related)g(to)f(passing)f -(string)g(v)-5 b(ariables)31 b(b)s(et)m(w)m(een)g(C)f(and)g(F)-8 -b(ortran.)382 4390 y Fe(FTGTBS\(unit,frow,startch)o(ar,)o(ncha)o(rs,)41 -b(>)48 b(string,status\))0 4643 y Fh(2)81 b Fi(W)-8 b(rite)31 -b(a)g(consecutiv)m(e)h(string)e(of)h(c)m(haracters)g(to)g(an)f(ASCI)s -(I)f(table)i(from)f(a)h(c)m(haracter)h(v)-5 b(ariable)31 -b(\(spanning)227 4756 y(columns)h(and)g(m)m(ultiple)h(ro)m(ws)f(if)g -(necessary\))h(This)f(routine)g(should)f(not)i(b)s(e)e(used)h(with)g -(binary)f(tables)227 4869 y(b)s(ecause)g(of)f(complications)i(related)g -(to)f(passing)f(string)g(v)-5 b(ariables)31 b(b)s(et)m(w)m(een)g(C)f -(and)g(F)-8 b(ortran.)382 5122 y Fe(FTPTBS\(unit,frow,startch)o(ar,)o -(ncha)o(rs,s)o(tri)o(ng,)41 b(>)48 b(status\))0 5375 -y Fh(3)81 b Fi(Read)27 b(a)h(consecutiv)m(e)i(arra)m(y)e(of)g(b)m(ytes) -g(from)f(an)g(ASCI)s(I)f(or)i(binary)e(table)j(in)m(to)f(a)g(n)m -(umeric)g(v)-5 b(ariable)28 b(\(span-)227 5488 y(ning)k(columns)f(and)h -(m)m(ultiple)g(ro)m(ws)g(if)g(necessary\).)46 b(The)32 -b(arra)m(y)g(parameter)g(ma)m(y)h(b)s(e)e(declared)h(as)h(an)m(y)227 -5601 y(n)m(umerical)i(datat)m(yp)s(e)g(as)g(long)g(as)g(the)f(arra)m(y) -h(is)f(at)h(least)h('nc)m(hars')f(b)m(ytes)f(long,)j(e.g.,)f(if)f(nc)m -(hars)f(=)g(17,)227 5714 y(then)c(declare)i(the)e(arra)m(y)h(as)g -(INTEGER*4)g(ARRA)-8 b(Y\(5\).)p eop end -%%Page: 59 65 -TeXDict begin 59 64 bop 0 299 a Fg(6.7.)72 b(FITS)30 -b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 -b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fi(59)382 555 -y Fe(FTGTBB\(unit,frow,startch)o(ar,)o(ncha)o(rs,)41 -b(>)48 b(array,status\))0 813 y Fh(4)81 b Fi(W)-8 b(rite)32 -b(a)f(consecutiv)m(e)i(arra)m(y)f(of)f(b)m(ytes)g(to)h(an)e(ASCI)s(I)g -(or)h(binary)f(table)i(from)e(a)i(n)m(umeric)e(v)-5 b(ariable)32 -b(\(span-)227 926 y(ning)j(columns)f(and)g(m)m(ultiple)h(ro)m(ws)g(if)f -(necessary\))i(The)e(arra)m(y)h(parameter)g(ma)m(y)h(b)s(e)e(declared)h -(as)g(an)m(y)227 1039 y(n)m(umerical)g(datat)m(yp)s(e)g(as)g(long)g(as) -g(the)f(arra)m(y)h(is)f(at)h(least)h('nc)m(hars')f(b)m(ytes)f(long,)j -(e.g.,)f(if)f(nc)m(hars)f(=)g(17,)227 1152 y(then)c(declare)i(the)e -(arra)m(y)h(as)g(INTEGER*4)g(ARRA)-8 b(Y\(5\).)382 1410 -y Fe(FTPTBB\(unit,frow,startch)o(ar,)o(ncha)o(rs,a)o(rra)o(y,)42 -b(>)47 b(status\))0 1700 y Fb(6.7.3)112 b(Edit)37 b(Ro)m(ws)g(or)h -(Columns)0 1909 y Fh(1)81 b Fi(Insert)26 b(blank)h(ro)m(ws)h(in)m(to)g -(an)f(existing)h(ASCI)s(I)e(or)h(binary)g(table)h(\(in)g(the)f(CDU\).)h -(All)g(the)g(ro)m(ws)f(F)m(OLLO)m(W-)227 2022 y(ING)35 -b(ro)m(w)g(FR)m(O)m(W)g(are)g(shifted)f(do)m(wn)g(b)m(y)h(NR)m(O)m(WS)g -(ro)m(ws.)53 b(If)34 b(FR)m(O)m(W)i(or)e(FR)m(O)m(WLL)i(equals)e(0)h -(then)227 2134 y(the)27 b(blank)f(ro)m(ws)h(are)g(inserted)f(at)h(the)g -(b)s(eginning)f(of)g(the)h(table.)41 b(These)26 b(routines)g(mo)s(dify) -g(the)h(NAXIS2)227 2247 y(k)m(eyw)m(ord)35 b(to)h(re\015ect)f(the)g -(new)f(n)m(um)m(b)s(er)f(of)i(ro)m(ws)g(in)f(the)h(table.)54 -b(Note)36 b(that)f(it)h(is)e(*not*)i(necessary)f(to)227 -2360 y(insert)c(ro)m(ws)f(in)g(a)h(table)g(b)s(efore)f(writing)g(data)i -(to)f(those)g(ro)m(ws)f(\(indeed,)g(it)h(w)m(ould)g(b)s(e)e -(ine\016cien)m(t)j(to)f(do)227 2473 y(so\).)54 b(Instead,)35 -b(one)g(ma)m(y)g(simply)f(write)h(data)g(to)g(an)m(y)g(ro)m(w)f(of)h -(the)g(table,)h(whether)e(that)h(ro)m(w)g(of)f(data)227 -2586 y(already)d(exists)g(or)g(not.)382 2844 y Fe -(FTIROW\(unit,frow,nrows,)41 b(>)48 b(status\))382 2957 -y(FTIROWLL\(unit,frowll,nro)o(wsl)o(l,)42 b(>)47 b(status\))0 -3215 y Fh(2)81 b Fi(Delete)25 b(ro)m(ws)f(from)f(an)g(existing)i(ASCI)s -(I)c(or)j(binary)f(table)h(\(in)f(the)h(CDU\).)g(The)f(NR)m(O)m(WS)h -(\(or)g(NR)m(O)m(WSLL\))227 3328 y(is)e(the)g(n)m(um)m(b)s(er)f(of)h -(ro)m(ws)g(are)g(deleted,)i(starting)f(with)f(ro)m(w)g(FR)m(O)m(W)h -(\(or)f(FR)m(O)m(WLL\),)h(and)f(an)m(y)g(remaining)227 -3441 y(ro)m(ws)f(in)g(the)f(table)i(are)f(shifted)g(up)e(to)j(\014ll)f -(in)f(the)h(space.)38 b(These)21 b(routines)f(mo)s(dify)g(the)h(NAXIS2) -g(k)m(eyw)m(ord)227 3553 y(to)31 b(re\015ect)g(the)g(new)f(n)m(um)m(b)s -(er)f(of)h(ro)m(ws)h(in)f(the)g(table.)382 3811 y Fe -(FTDROW\(unit,frow,nrows,)41 b(>)48 b(status\))382 3924 -y(FTDROWLL\(unit,frowll,nro)o(wsl)o(l,)42 b(>)47 b(status\))0 -4182 y Fh(3)81 b Fi(Delete)26 b(a)f(list)g(of)g(ro)m(ws)f(from)g(an)h -(ASCI)s(I)e(or)h(binary)g(table)h(\(in)g(the)f(CDU\).)i(In)e(the)g -(\014rst)g(routine,)i('ro)m(wrange')227 4295 y(is)i(a)g(c)m(haracter)h -(string)f(listing)h(the)f(ro)m(ws)f(or)h(ro)m(w)g(ranges)g(to)g(delete) -h(\(e.g.,)i('2-4,)e(5,)g(8-9'\).)42 b(In)27 b(the)h(second)227 -4408 y(routine,)37 b('ro)m(wlist')f(is)f(an)f(in)m(teger)j(arra)m(y)e -(of)g(ro)m(w)g(n)m(um)m(b)s(ers)e(to)j(b)s(e)e(deleted)i(from)e(the)h -(table.)56 b(nro)m(ws)34 b(is)227 4521 y(the)e(n)m(um)m(b)s(er)e(of)h -(ro)m(w)h(n)m(um)m(b)s(ers)e(in)h(the)g(list.)45 b(The)31 -b(\014rst)f(ro)m(w)i(in)f(the)g(table)i(is)e(1)h(not)f(0.)44 -b(The)31 b(list)h(of)g(ro)m(w)227 4634 y(n)m(um)m(b)s(ers)d(m)m(ust)h -(b)s(e)g(sorted)h(in)f(ascending)g(order.)382 4891 y -Fe(FTDRRG\(unit,rowrange,)42 b(>)47 b(status\))382 5004 -y(FTDRWS\(unit,rowlist,nrow)o(s,)41 b(>)48 b(status\))0 -5262 y Fh(4)81 b Fi(Insert)43 b(a)i(blank)f(column)h(\(or)f(columns\))h -(in)m(to)g(an)f(existing)i(ASCI)s(I)d(or)h(binary)g(table)h(\(in)g(the) -f(CDU\).)227 5375 y(COLNUM)c(sp)s(eci\014es)g(the)h(column)f(n)m(um)m -(b)s(er)f(that)i(the)f(\(\014rst\))g(new)g(column)g(should)f(o)s(ccup)m -(y)i(in)f(the)227 5488 y(table.)58 b(NCOLS)34 b(sp)s(eci\014es)h(ho)m -(w)h(man)m(y)g(columns)f(are)h(to)g(b)s(e)f(inserted.)57 -b(An)m(y)35 b(existing)i(columns)e(from)227 5601 y(this)k(p)s(osition)f -(and)g(higher)g(are)h(mo)m(v)m(ed)g(o)m(v)m(er)h(to)f(allo)m(w)h(ro)s -(om)e(for)h(the)f(new)g(column\(s\).)65 b(The)38 b(index)227 -5714 y(n)m(um)m(b)s(er)j(on)h(all)h(the)f(follo)m(wing)h(k)m(eyw)m -(ords)g(will)f(b)s(e)f(incremen)m(ted)i(if)f(necessary)g(to)h -(re\015ect)f(the)g(new)p eop end -%%Page: 60 66 -TeXDict begin 60 65 bop 0 299 a Fi(60)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)227 555 y Fi(p)s(osition)i(of)f(the)g(column\(s\))h -(in)f(the)g(table:)43 b(TBCOLn,)30 b(TF)m(ORMn,)i(TTYPEn,)e(TUNITn,)h -(TNULLn,)227 668 y(TSCALn,)22 b(TZER)m(On,)g(TDISPn,)g(TDIMn,)h -(TLMINn,)g(TLMAXn,)f(TDMINn,)i(TDMAXn,)f(TCTYPn,)227 -781 y(TCRPXn,)30 b(TCR)-10 b(VLn,)29 b(TCDL)-8 b(Tn,)30 -b(TCR)m(OTn,)f(and)g(TCUNIn.)382 1035 y Fe(FTICOL\(unit,colnum,ttype)o -(,tf)o(orm,)41 b(>)48 b(status\))382 1148 y(FTICLS\(unit,colnum,ncols)o -(,tt)o(ype,)o(tfor)o(m,)41 b(>)48 b(status\))0 1403 y -Fh(5)81 b Fi(Mo)s(dify)37 b(the)g(v)m(ector)i(length)f(of)f(a)h(binary) -e(table)i(column)f(\(e.g.,)k(c)m(hange)e(a)e(column)g(from)g(TF)m(ORMn) -g(=)227 1515 y('1E')31 b(to)h('20E'\).)g(The)e(v)m(ector)i(length)e(ma) -m(y)h(b)s(e)f(increased)h(or)f(decreased)h(from)f(the)g(curren)m(t)h(v) --5 b(alue.)382 1770 y Fe(FTMVEC\(unit,colnum,newve)o(cle)o(n,)42 -b(>)47 b(status\))0 2024 y Fh(6)81 b Fi(Delete)29 b(a)f(column)g(from)f -(an)g(existing)i(ASCI)s(I)d(or)i(binary)e(table)j(\(in)f(the)f(CDU\).)i -(The)e(index)g(n)m(um)m(b)s(er)f(of)i(all)227 2137 y(the)k(k)m(eyw)m -(ords)h(listed)f(ab)s(o)m(v)m(e)i(\(for)e(FTICOL\))f(will)h(b)s(e)g -(decremen)m(ted)g(if)g(necessary)h(to)g(re\015ect)f(the)g(new)227 -2250 y(p)s(osition)26 b(of)g(the)g(column\(s\))g(in)f(the)h(table.)40 -b(Those)26 b(index)f(k)m(eyw)m(ords)h(that)g(refer)f(to)i(the)f -(deleted)g(column)227 2363 y(will)33 b(also)g(b)s(e)f(deleted.)47 -b(Note)33 b(that)g(the)g(ph)m(ysical)g(size)g(of)f(the)h(FITS)e(\014le) -i(will)f(not)h(b)s(e)e(reduced)h(b)m(y)g(this)227 2476 -y(op)s(eration,)e(and)e(the)h(empt)m(y)g(FITS)f(blo)s(c)m(ks)h(if)g(an) -m(y)g(at)g(the)g(end)f(of)h(the)g(\014le)g(will)g(b)s(e)f(padded)g -(with)g(zeros.)382 2730 y Fe(FTDCOL\(unit,colnum,)42 -b(>)48 b(status\))0 2984 y Fh(7)81 b Fi(Cop)m(y)30 b(a)g(column)g(from) -g(one)g(HDU)h(to)g(another)f(\(or)h(to)g(the)f(same)h(HDU\).)g(If)f -(createcol)j(=)c(TR)m(UE,)i(then)f(a)227 3097 y(new)20 -b(column)g(will)h(b)s(e)f(inserted)g(in)g(the)h(output)f(table,)k(at)d -(p)s(osition)f(`outcolumn',)j(otherwise)e(the)g(existing)227 -3210 y(output)29 b(column)f(will)h(b)s(e)f(o)m(v)m(erwritten)i(\(in)f -(whic)m(h)f(case)i(it)f(m)m(ust)f(ha)m(v)m(e)i(a)f(compatible)h(datat)m -(yp)s(e\).)42 b(Note)227 3323 y(that)31 b(the)g(\014rst)e(column)i(in)f -(a)g(table)i(is)e(at)h(coln)m(um)g(=)f(1.)382 3577 y -Fe(FTCPCL\(inunit,outunit,in)o(col)o(num,)o(outc)o(oln)o(um,c)o(reat)o -(eco)o(l,)42 b(>)47 b(status\);)0 3867 y Fb(6.7.4)112 -b(Read)38 b(and)h(W)-9 b(rite)36 b(Column)j(Data)e(Routines)0 -4086 y Fi(These)22 b(subroutines)f(put)h(or)g(get)i(data)f(v)-5 -b(alues)22 b(in)g(the)h(curren)m(t)f(ASCI)s(I)f(or)h(Binary)g(table)i -(extension.)38 b(Automatic)0 4199 y(data)21 b(t)m(yp)s(e)g(con)m(v)m -(ersion)g(is)f(p)s(erformed)f(for)h(n)m(umerical)h(data)g(t)m(yp)s(es)g -(\(B,I,J,E,D\))h(if)e(the)h(data)g(t)m(yp)s(e)f(of)h(the)f(column)0 -4312 y(\(de\014ned)32 b(b)m(y)i(the)f(TF)m(ORM)h(k)m(eyw)m(ord\))g -(di\013ers)f(from)f(the)i(data)g(t)m(yp)s(e)f(of)h(the)f(calling)i -(subroutine.)48 b(The)33 b(data)0 4425 y(v)-5 b(alues)30 -b(are)h(also)g(scaled)f(b)m(y)g(the)g(TSCALn)f(and)g(TZER)m(On)g -(header)h(v)-5 b(alues)30 b(as)g(they)g(are)h(b)s(eing)e(written)h(to)h -(or)0 4538 y(read)j(from)f(the)h(FITS)f(arra)m(y)-8 b(.)51 -b(The)33 b(fttscl)i(subroutine)d(MUST)i(b)s(e)f(used)g(to)h(de\014ne)f -(the)h(scaling)h(parameters)0 4650 y(when)d(writing)h(data)h(to)g(the)f -(table)h(or)f(to)h(o)m(v)m(erride)g(the)g(default)f(scaling)h(v)-5 -b(alues)34 b(giv)m(en)g(in)f(the)g(header)g(when)0 4763 -y(reading)27 b(from)g(the)g(table.)40 b(Note)29 b(that)e(it)h(is)f -(*not*)h(necessary)f(to)h(insert)f(ro)m(ws)g(in)f(a)i(table)g(b)s -(efore)e(writing)h(data)0 4876 y(to)j(those)h(ro)m(ws)e(\(indeed,)h(it) -g(w)m(ould)g(b)s(e)f(ine\016cien)m(t)i(to)f(do)g(so\).)41 -b(Instead,)30 b(one)g(ma)m(y)g(simply)f(write)h(data)g(to)h(an)m(y)0 -4989 y(ro)m(w)f(of)h(the)g(table,)g(whether)f(that)h(ro)m(w)f(of)h -(data)g(already)g(exists)g(or)f(not.)0 5149 y(In)i(the)i(case)g(of)f -(binary)g(tables)h(with)f(v)m(ector)h(elemen)m(ts,)i(the)d('felem')h -(parameter)g(de\014nes)e(the)i(starting)g(pixel)0 5262 -y(within)k(the)g(elemen)m(t)i(v)m(ector.)65 b(This)38 -b(parameter)g(is)g(ignored)h(with)e(ASCI)s(I)g(tables.)65 -b(Similarly)-8 b(,)41 b(in)d(the)g(case)0 5375 y(of)45 -b(binary)e(tables)i(the)g('nelemen)m(ts')h(parameter)f(sp)s(eci\014es)f -(the)g(total)i(n)m(um)m(b)s(er)d(of)i(v)m(ector)h(v)-5 -b(alues)45 b(read)f(or)0 5488 y(written)36 b(\(con)m(tin)m(uing)h(on)f -(subsequen)m(t)f(ro)m(ws)g(if)h(required\))f(and)h(not)g(the)g(n)m(um)m -(b)s(er)e(of)i(table)h(elemen)m(ts.)58 b(Tw)m(o)0 5601 -y(sets)36 b(of)f(subroutines)g(are)g(pro)m(vided)g(to)i(get)f(the)g -(column)f(data)h(whic)m(h)f(di\013er)g(in)h(the)f(w)m(a)m(y)i -(unde\014ned)c(pixels)0 5714 y(are)f(handled.)42 b(The)31 -b(\014rst)g(set)h(of)f(routines)h(\(FTGCV\))g(simply)f(return)f(an)h -(arra)m(y)h(of)f(data)h(elemen)m(ts)h(in)e(whic)m(h)p -eop end -%%Page: 61 67 -TeXDict begin 61 66 bop 0 299 a Fg(6.7.)72 b(FITS)30 -b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 -b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fi(61)0 555 y(unde\014ned)41 -b(pixels)j(are)g(set)g(equal)g(to)h(a)f(v)-5 b(alue)44 -b(sp)s(eci\014ed)f(b)m(y)g(the)h(user)f(in)g(the)h('n)m(ullv)-5 -b(al')44 b(parameter.)81 b(An)0 668 y(additional)44 b(feature)g(of)g -(these)g(subroutines)e(is)i(that)g(if)f(the)h(user)e(sets)i(n)m(ullv)-5 -b(al)44 b(=)f(0,)48 b(then)43 b(no)g(c)m(hec)m(ks)i(for)0 -781 y(unde\014ned)33 b(pixels)j(will)g(b)s(e)e(p)s(erformed,)i(th)m(us) -f(increasing)h(the)g(sp)s(eed)e(of)i(the)g(program.)55 -b(The)35 b(second)h(set)g(of)0 894 y(routines)h(\(FTGCF\))h(returns)d -(the)i(data)h(elemen)m(t)g(arra)m(y)g(and)e(in)h(addition)g(a)g -(logical)j(arra)m(y)d(of)g(\015ags)g(whic)m(h)0 1007 -y(de\014nes)29 b(whether)h(the)h(corresp)s(onding)e(data)i(pixel)g(is)f -(unde\014ned.)0 1167 y(An)m(y)41 b(column,)i(regardless)e(of)g(it's)g -(in)m(trinsic)g(datat)m(yp)s(e,)k(ma)m(y)c(b)s(e)f(read)h(as)g(a)g -(string.)71 b(It)41 b(should)f(b)s(e)g(noted)0 1280 y(ho)m(w)m(ev)m(er) -32 b(that)f(reading)f(a)h(n)m(umeric)f(column)g(as)h(a)f(string)h(is)f -(10)h(-)g(100)g(times)g(slo)m(w)m(er)h(than)e(reading)g(the)h(same)0 -1393 y(column)g(as)h(a)g(n)m(um)m(b)s(er)e(due)h(to)h(the)g(large)h(o)m -(v)m(erhead)f(in)g(constructing)g(the)g(formatted)g(strings.)44 -b(The)31 b(displa)m(y)0 1506 y(format)26 b(of)g(the)h(returned)d -(strings)i(will)g(b)s(e)g(determined)f(b)m(y)h(the)g(TDISPn)f(k)m(eyw)m -(ord,)j(if)d(it)i(exists,)h(otherwise)e(b)m(y)0 1619 -y(the)i(datat)m(yp)s(e)h(of)g(the)f(column.)40 b(The)28 -b(length)g(of)h(the)f(returned)f(strings)h(can)g(b)s(e)g(determined)g -(with)f(the)i(ftgcdw)0 1732 y(routine.)41 b(The)30 b(follo)m(wing)h -(TDISPn)f(displa)m(y)g(formats)h(are)f(curren)m(tly)h(supp)s(orted:)191 -1952 y Fe(Iw.m)142 b(Integer)191 2065 y(Ow.m)g(Octal)46 -b(integer)191 2178 y(Zw.m)142 b(Hexadecimal)45 b(integer)191 -2291 y(Fw.d)142 b(Fixed)46 b(floating)g(point)191 2404 -y(Ew.d)142 b(Exponential)45 b(floating)g(point)191 2517 -y(Dw.d)142 b(Exponential)45 b(floating)g(point)191 2630 -y(Gw.d)142 b(General;)46 b(uses)g(Fw.d)h(if)g(significance)d(not)j -(lost,)g(else)f(Ew.d)0 2850 y Fi(where)37 b(w)h(is)g(the)g(width)f(in)h -(c)m(haracters)h(of)f(the)h(displa)m(y)m(ed)f(v)-5 b(alues,)41 -b(m)c(is)h(the)g(minim)m(um)g(n)m(um)m(b)s(er)e(of)i(digits)0 -2963 y(displa)m(y)m(ed,)31 b(and)f(d)g(is)g(the)h(n)m(um)m(b)s(er)e(of) -h(digits)h(to)g(the)g(righ)m(t)g(of)g(the)f(decimal.)42 -b(The)30 b(.m)g(\014eld)g(is)g(optional.)0 3184 y Fh(1)81 -b Fi(Put)30 b(elemen)m(ts)i(in)m(to)g(an)e(ASCI)s(I)f(or)i(binary)f -(table)i(column)e(\(in)h(the)g(CDU\).)g(\(The)g(SPP)f(FSPCLS)f(routine) -227 3297 y(has)38 b(an)f(additional)i(in)m(teger)g(argumen)m(t)f(after) -h(the)f(V)-10 b(ALUES)37 b(c)m(haracter)i(string)f(whic)m(h)f(sp)s -(eci\014es)h(the)227 3410 y(size)31 b(of)g(the)g(1st)g(dimension)e(of)i -(this)f(2-D)i(CHAR)e(arra)m(y\).)227 3553 y(The)24 b(alternate)i(v)m -(ersion)f(of)g(these)g(routines,)h(whose)e(names)g(end)g(in)g('LL')h -(after)g(the)g(datat)m(yp)s(e)g(c)m(haracter,)227 3666 -y(supp)s(ort)34 b(large)j(tables)f(with)g(more)f(then)h(2*31)h(ro)m -(ws.)57 b(When)35 b(calling)i(these)f(routines,)h(the)f(fro)m(w)g(and) -227 3779 y(felem)31 b(parameters)g(*m)m(ust*)g(b)s(e)f(64-bit)h(in)m -(teger*8)i(v)-5 b(ariables,)31 b(instead)g(of)g(normal)f(4-b)m(yte)i -(in)m(tegers.)382 4000 y Fe(FTPCL[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o -(row,)o(fel)o(em,n)o(elem)o(ent)o(s,va)o(lues)o(,)42 -b(>)47 b(status\))382 4113 y(FTPCL[LBIJKEDCM]LL\(unit,)o(col)o(num,)o -(frow)o(,fe)o(lem,)o(nele)o(men)o(ts,v)o(alue)o(s,)41 -b(>)48 b(status\))0 4333 y Fh(2)81 b Fi(Put)29 b(elemen)m(ts)i(in)m(to) -g(an)f(ASCI)s(I)e(or)i(binary)f(table)i(column)e(\(in)h(the)g(CDU\))g -(substituting)g(the)g(appropriate)227 4446 y(FITS)c(n)m(ull)g(v)-5 -b(alue)26 b(for)g(an)m(y)h(elemen)m(ts)g(that)g(are)f(equal)h(to)g -(NULL)-10 b(V)g(AL.)26 b(F)-8 b(or)27 b(ASCI)s(I)e(T)-8 -b(ABLE)26 b(extensions,)227 4559 y(the)31 b(n)m(ull)f(v)-5 -b(alue)31 b(de\014ned)e(b)m(y)h(the)g(previous)g(call)i(to)f(FTSNUL)f -(will)g(b)s(e)g(substituted;)g(F)-8 b(or)31 b(in)m(teger)h(FITS)227 -4672 y(columns,)39 b(in)e(a)h(binary)f(table)h(the)f(n)m(ull)h(v)-5 -b(alue)37 b(de\014ned)g(b)m(y)g(the)g(previous)g(call)i(to)f(FTTNUL)f -(will)h(b)s(e)227 4785 y(substituted;)28 b(F)-8 b(or)28 -b(\015oating)h(p)s(oin)m(t)e(FITS)f(columns)h(a)h(sp)s(ecial)g(IEEE)f -(NaN)h(\(Not-a-Num)m(b)s(er\))h(v)-5 b(alue)28 b(will)227 -4898 y(b)s(e)i(substituted.)227 5042 y(The)24 b(alternate)i(v)m(ersion) -f(of)g(these)g(routines,)h(whose)e(names)g(end)g(in)g('LL')h(after)g -(the)g(datat)m(yp)s(e)g(c)m(haracter,)227 5155 y(supp)s(ort)34 -b(large)j(tables)f(with)g(more)f(then)h(2*31)h(ro)m(ws.)57 -b(When)35 b(calling)i(these)f(routines,)h(the)f(fro)m(w)g(and)227 -5267 y(felem)31 b(parameters)g(*m)m(ust*)g(b)s(e)f(64-bit)h(in)m -(teger*8)i(v)-5 b(ariables,)31 b(instead)g(of)g(normal)f(4-b)m(yte)i -(in)m(tegers.)382 5488 y Fe(FTPCN[SBIJKED]\(unit,coln)o(um,)o(frow)o -(,fel)o(em,)o(nele)o(ment)o(s,v)o(alue)o(s,nu)o(llv)o(al)42 -b(>)47 b(status\))382 5601 y(FTPCN[SBIJKED]LL\(unit,co)o(lnu)o(m,\(I)o -(*8\))41 b(frow,\(I*8\))k(felem,nelements,values,)764 -5714 y(nullval)g(>)j(status\))p eop end -%%Page: 62 68 -TeXDict begin 62 67 bop 0 299 a Fi(62)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)0 555 y Fh(3)81 b Fi(Put)37 b(bit)h(v)-5 -b(alues)38 b(in)m(to)h(a)f(binary)f(b)m(yte)h(\('B'\))i(or)d(bit)h -(\('X'\))h(table)g(column)f(\(in)f(the)h(CDU\).)h(LRA)-8 -b(Y)38 b(is)g(an)227 668 y(arra)m(y)c(of)g(logical)h(v)-5 -b(alues)34 b(corresp)s(onding)e(to)i(the)g(sequence)f(of)h(bits)f(to)h -(b)s(e)f(written.)49 b(If)33 b(LRA)-8 b(Y)34 b(is)f(true)227 -781 y(then)f(the)g(corresp)s(onding)f(bit)h(is)g(set)g(to)h(1,)g -(otherwise)f(the)g(bit)g(is)g(set)h(to)g(0.)45 b(Note)34 -b(that)e(in)g(the)g(case)h(of)227 894 y('X')g(columns,)g(FITSIO)e(will) -i(write)f(to)h(all)g(8)g(bits)f(of)g(eac)m(h)i(b)m(yte)f(whether)e -(they)i(are)g(formally)f(v)-5 b(alid)33 b(or)227 1007 -y(not.)46 b(Th)m(us)31 b(if)h(the)g(column)g(is)f(de\014ned)g(as)h -('4X',)i(and)d(one)h(calls)h(FTPCLX)f(with)f(fbit=1)h(and)f(n)m(bit=8,) -227 1120 y(then)j(all)h(8)f(bits)g(will)g(b)s(e)f(written)h(in)m(to)h -(the)f(\014rst)g(b)m(yte)g(\(as)h(opp)s(osed)e(to)i(writing)e(the)i -(\014rst)e(4)h(bits)g(in)m(to)227 1233 y(the)d(\014rst)f(ro)m(w)g(and)g -(then)g(the)h(next)f(4)h(bits)f(in)m(to)i(the)e(next)h(ro)m(w\),)g(ev)m -(en)g(though)f(the)h(last)g(4)g(bits)f(of)h(eac)m(h)227 -1346 y(b)m(yte)g(are)g(formally)g(not)g(de\014ned.)382 -1604 y Fe(FTPCLX\(unit,colnum,frow,)o(fbi)o(t,nb)o(it,l)o(ray)o(,)42 -b(>)47 b(status\))0 1863 y Fh(4)81 b Fi(Set)30 b(table)h(elemen)m(ts)h -(in)e(a)h(column)f(as)h(unde\014ned)382 2121 y Fe -(FTPCLU\(unit,colnum,frow,)o(fel)o(em,n)o(elem)o(ent)o(s,)42 -b(>)47 b(status\))0 2380 y Fh(5)81 b Fi(Get)34 b(elemen)m(ts)g(from)f -(an)g(ASCI)s(I)f(or)h(binary)g(table)h(column)f(\(in)g(the)g(CDU\).)i -(These)e(routines)g(return)f(the)227 2493 y(v)-5 b(alues)30 -b(of)g(the)g(table)h(column)f(arra)m(y)g(elemen)m(ts.)42 -b(Unde\014ned)28 b(arra)m(y)j(elemen)m(ts)g(will)f(b)s(e)f(returned)g -(with)h(a)227 2606 y(v)-5 b(alue)26 b(=)g(n)m(ullv)-5 -b(al,)27 b(unless)e(n)m(ullv)-5 b(al)26 b(=)f(0)h(\(or)g(=)f(')h(')g -(for)f(ftgcvs\))i(in)e(whic)m(h)g(case)i(no)e(c)m(hec)m(king)j(for)d -(unde\014ned)227 2719 y(v)-5 b(alues)28 b(will)g(b)s(e)f(p)s(erformed.) -39 b(The)27 b(ANYF)h(parameter)g(is)g(set)g(to)g(true)g(if)g(an)m(y)f -(of)h(the)g(returned)f(elemen)m(ts)227 2831 y(are)f(unde\014ned.)37 -b(\(Note:)i(the)26 b(ftgcl)g(routine)f(simple)g(gets)h(an)g(arra)m(y)f -(of)g(logical)j(data)e(v)-5 b(alues)25 b(without)h(an)m(y)227 -2944 y(c)m(hec)m(ks)39 b(for)e(unde\014ned)e(v)-5 b(alues;)41 -b(use)c(the)g(ftgc\015)h(routine)f(to)h(c)m(hec)m(k)g(for)f -(unde\014ned)e(logical)40 b(elemen)m(ts\).)227 3057 y(\(The)29 -b(SPP)f(FSGCVS)g(routine)g(has)h(an)f(additional)i(in)m(teger)g -(argumen)m(t)f(after)g(the)g(V)-10 b(ALUES)28 b(c)m(haracter)227 -3170 y(string)j(whic)m(h)f(sp)s(eci\014es)g(the)g(size)i(of)e(the)h -(1st)g(dimension)e(of)i(this)f(2-D)i(CHAR)e(arra)m(y\).)227 -3320 y(The)24 b(alternate)i(v)m(ersion)f(of)g(these)g(routines,)h -(whose)e(names)g(end)g(in)g('LL')h(after)g(the)g(datat)m(yp)s(e)g(c)m -(haracter,)227 3433 y(supp)s(ort)34 b(large)j(tables)f(with)g(more)f -(then)h(2*31)h(ro)m(ws.)57 b(When)35 b(calling)i(these)f(routines,)h -(the)f(fro)m(w)g(and)227 3546 y(felem)31 b(parameters)g(*m)m(ust*)g(b)s -(e)f(64-bit)h(in)m(teger*8)i(v)-5 b(ariables,)31 b(instead)g(of)g -(normal)f(4-b)m(yte)i(in)m(tegers.)382 3805 y Fe -(FTGCL\(unit,colnum,frow,f)o(ele)o(m,ne)o(leme)o(nts)o(,)42 -b(>)47 b(values,status\))382 3918 y(FTGCV[SBIJKEDCM]\(unit,co)o(lnu)o -(m,fr)o(ow,f)o(ele)o(m,ne)o(leme)o(nts)o(,nul)o(lval)o(,)42 -b(>)1098 4030 y(values,anyf,status\))382 4143 y -(FTGCV[BIJKEDCM]LL\(unit,c)o(oln)o(um,\()o(I*8\))f(frow,)46 -b(\(I*8\))h(felem,)f(nelements,)716 4256 y(nullval,)f(>)j -(values,anyf,status\))0 4515 y Fh(6)81 b Fi(Get)44 b(elemen)m(ts)h(and) -d(n)m(ull)i(\015ags)f(from)g(an)h(ASCI)s(I)d(or)j(binary)e(table)j -(column)e(\(in)g(the)h(CHDU\).)g(These)227 4628 y(routines)29 -b(return)e(the)i(v)-5 b(alues)29 b(of)g(the)g(table)h(column)e(arra)m -(y)i(elemen)m(ts.)41 b(An)m(y)29 b(unde\014ned)d(arra)m(y)k(elemen)m -(ts)227 4741 y(will)37 b(ha)m(v)m(e)h(the)f(corresp)s(onding)f(\015agv) --5 b(als)37 b(elemen)m(t)i(set)e(equal)g(to)h(.TR)m(UE.)f(The)f(ANYF)i -(parameter)f(is)227 4854 y(set)30 b(to)g(true)g(if)f(an)m(y)h(of)f(the) -h(returned)e(elemen)m(ts)j(are)f(unde\014ned.)38 b(\(The)29 -b(SPP)f(FSGCFS)h(routine)h(has)f(an)227 4967 y(additional)e(in)m(teger) -h(argumen)m(t)e(after)h(the)f(V)-10 b(ALUES)26 b(c)m(haracter)i(string) -e(whic)m(h)f(sp)s(eci\014es)h(the)h(size)f(of)h(the)227 -5079 y(1st)k(dimension)f(of)h(this)f(2-D)h(CHAR)g(arra)m(y\).)227 -5229 y(The)24 b(alternate)i(v)m(ersion)f(of)g(these)g(routines,)h -(whose)e(names)g(end)g(in)g('LL')h(after)g(the)g(datat)m(yp)s(e)g(c)m -(haracter,)227 5342 y(supp)s(ort)34 b(large)j(tables)f(with)g(more)f -(then)h(2*31)h(ro)m(ws.)57 b(When)35 b(calling)i(these)f(routines,)h -(the)f(fro)m(w)g(and)227 5455 y(felem)31 b(parameters)g(*m)m(ust*)g(b)s -(e)f(64-bit)h(in)m(teger*8)i(v)-5 b(ariables,)31 b(instead)g(of)g -(normal)f(4-b)m(yte)i(in)m(tegers.)382 5714 y Fe -(FTGCF[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o(row,)o(fel)o(em,n)o(elem)o -(ent)o(s,)42 b(>)p eop end -%%Page: 63 69 -TeXDict begin 63 68 bop 0 299 a Fg(6.7.)72 b(FITS)30 -b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 -b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fi(63)1193 555 -y Fe(values,flagvals,anyf,stat)o(us\))382 668 y -(FTGCF[BIJKED]LL\(unit,col)o(num)o(,)42 b(\(I*8\))k(frow,)h(\(I*8\))f -(felem,nelements,)d(>)1193 781 y(values,flagvals,anyf,stat)o(us\))0 -1034 y Fh(7)81 b Fi(Get)29 b(an)f(arbitrary)g(data)h(subsection)f(from) -g(an)g(N-dimensional)h(arra)m(y)g(in)f(a)g(binary)g(table)h(v)m(ector)h -(column.)227 1147 y(Unde\014ned)k(pixels)h(in)g(the)h(arra)m(y)g(will)f -(b)s(e)g(set)h(equal)f(to)h(the)g(v)-5 b(alue)36 b(of)f('n)m(ullv)-5 -b(al',)38 b(unless)c(n)m(ullv)-5 b(al=0)36 b(in)227 1260 -y(whic)m(h)d(case)i(no)e(testing)i(for)e(unde\014ned)e(pixels)j(will)f -(b)s(e)g(p)s(erformed.)49 b(The)32 b(\014rst)h(and)g(last)h(ro)m(ws)g -(in)f(the)227 1373 y(table)28 b(to)f(b)s(e)f(read)g(are)h(sp)s -(eci\014ed)e(b)m(y)i(fpixels\(naxis+1\))g(and)f(lpixels\(naxis+1\),)j -(and)d(hence)g(are)h(treated)227 1486 y(as)f(the)f(next)h(higher)f -(dimension)g(of)g(the)h(FITS)e(N-dimensional)i(arra)m(y)-8 -b(.)40 b(The)25 b(INCS)f(parameter)i(sp)s(eci\014es)227 -1599 y(the)31 b(sampling)f(in)m(terv)-5 b(al)32 b(in)e(eac)m(h)h -(dimension)f(b)s(et)m(w)m(een)h(the)g(data)g(elemen)m(ts)g(that)g(will) -g(b)s(e)f(returned.)382 1852 y Fe(FTGSV[BIJKED]\(unit,colnu)o(m,n)o -(axis)o(,nax)o(es,)o(fpix)o(els,)o(lpi)o(xels)o(,inc)o(s,n)o(ullv)o -(al,)41 b(>)1002 1965 y(array,anyf,status\))0 2218 y -Fh(8)81 b Fi(Get)29 b(an)f(arbitrary)g(data)h(subsection)f(from)g(an)g -(N-dimensional)h(arra)m(y)g(in)f(a)g(binary)g(table)h(v)m(ector)h -(column.)227 2331 y(An)m(y)39 b(Unde\014ned)e(pixels)i(in)g(the)g(arra) -m(y)g(will)g(ha)m(v)m(e)h(the)f(corresp)s(onding)f('\015agv)-5 -b(als')40 b(elemen)m(t)g(set)f(equal)227 2443 y(to)d(.TR)m(UE.)f(The)f -(\014rst)g(and)g(last)i(ro)m(ws)f(in)f(the)h(table)h(to)f(b)s(e)g(read) -f(are)h(sp)s(eci\014ed)f(b)m(y)h(fpixels\(naxis+1\))227 -2556 y(and)k(lpixels\(naxis+1\),)k(and)38 b(hence)i(are)f(treated)i(as) -e(the)g(next)h(higher)f(dimension)f(of)i(the)f(FITS)g(N-)227 -2669 y(dimensional)g(arra)m(y)-8 b(.)66 b(The)38 b(INCS)g(parameter)h -(sp)s(eci\014es)f(the)g(sampling)h(in)m(terv)-5 b(al)40 -b(in)e(eac)m(h)i(dimension)227 2782 y(b)s(et)m(w)m(een)31 -b(the)g(data)g(elemen)m(ts)h(that)f(will)f(b)s(e)g(returned.)382 -3035 y Fe(FTGSF[BIJKED]\(unit,colnu)o(m,n)o(axis)o(,nax)o(es,)o(fpix)o -(els,)o(lpi)o(xels)o(,inc)o(s,)41 b(>)1002 3148 y -(array,flagvals,anyf,statu)o(s\))0 3401 y Fh(9)81 b Fi(Get)33 -b(bit)g(v)-5 b(alues)34 b(from)e(a)h(b)m(yte)h(\('B'\))g(or)f(bit)g -(\(`X`\))h(table)g(column)f(\(in)g(the)g(CDU\).)g(LRA)-8 -b(Y)34 b(is)f(an)f(arra)m(y)i(of)227 3514 y(logical)41 -b(v)-5 b(alues)39 b(corresp)s(onding)f(to)h(the)g(sequence)f(of)h(bits) -g(to)g(b)s(e)f(read.)65 b(If)38 b(LRA)-8 b(Y)39 b(is)f(true)h(then)f -(the)227 3627 y(corresp)s(onding)c(bit)g(w)m(as)g(set)h(to)g(1,)h -(otherwise)f(the)f(bit)h(w)m(as)f(set)h(to)g(0.)53 b(Note)35 -b(that)g(in)f(the)h(case)g(of)f('X')227 3740 y(columns,)41 -b(FITSIO)d(will)h(read)f(all)i(8)f(bits)g(of)g(eac)m(h)h(b)m(yte)f -(whether)f(they)h(are)g(formally)h(v)-5 b(alid)39 b(or)f(not.)227 -3853 y(Th)m(us)c(if)g(the)h(column)f(is)g(de\014ned)f(as)i('4X',)h(and) -d(one)i(calls)h(FTGCX)e(with)g(fbit=1)h(and)e(n)m(bit=8,)j(then)227 -3966 y(all)30 b(8)g(bits)f(will)g(b)s(e)g(read)g(from)g(the)g(\014rst)f -(b)m(yte)i(\(as)g(opp)s(osed)e(to)i(reading)f(the)h(\014rst)e(4)i(bits) -f(from)f(the)i(\014rst)227 4079 y(ro)m(w)g(and)e(then)h(the)h(\014rst)e -(4)i(bits)f(from)g(the)g(next)g(ro)m(w\),)i(ev)m(en)f(though)f(the)g -(last)h(4)g(bits)f(of)g(eac)m(h)i(b)m(yte)f(are)227 4192 -y(formally)h(not)g(de\014ned.)382 4445 y Fe(FTGCX\(unit,colnum,frow,f)o -(bit)o(,nbi)o(t,)42 b(>)47 b(lray,status\))0 4698 y Fh(10)f -Fi(Read)31 b(an)m(y)g(consecutiv)m(e)h(set)f(of)g(bits)g(from)f(an)g -('X')i(or)e('B')i(column)e(and)g(in)m(terpret)h(them)g(as)g(an)f -(unsigned)227 4811 y(n-bit)k(in)m(teger.)54 b(NBIT)35 -b(m)m(ust)f(b)s(e)f(less)i(than)f(or)g(equal)h(to)g(16)g(when)f -(calling)h(FTGCXI,)g(and)f(less)g(than)227 4924 y(or)e(equal)g(to)g(32) -g(when)e(calling)j(FTGCXJ;)f(there)f(is)h(no)f(limit)h(on)g(the)f(v)-5 -b(alue)32 b(of)g(NBIT)f(for)g(FTGCXD,)227 5036 y(but)38 -b(the)h(returned)e(double)i(precision)f(v)-5 b(alue)39 -b(only)g(has)f(48)i(bits)e(of)h(precision)g(on)f(most)h(32-bit)h(w)m -(ord)227 5149 y(mac)m(hines.)64 b(The)37 b(NBITS)g(bits)h(are)g(in)m -(terpreted)g(as)g(an)g(unsigned)e(in)m(teger)k(unless)d(NBITS)g(=)g(16) -i(\(in)227 5262 y(FTGCXI\))e(or)g(32)g(\(in)g(FTGCXJ\))f(in)g(whic)m(h) -h(case)g(the)g(string)g(of)f(bits)h(are)g(in)m(terpreted)f(as)h(16-bit) -h(or)227 5375 y(32-bit)j(2's)f(complemen)m(t)h(signed)e(in)m(tegers.)69 -b(If)39 b(NR)m(O)m(WS)i(is)e(greater)i(than)e(1)h(then)f(the)h(same)g -(set)g(of)227 5488 y(bits)34 b(will)g(b)s(e)f(read)h(from)f(sequen)m -(tial)i(ro)m(ws)f(in)f(the)h(table)g(starting)h(with)e(ro)m(w)h(FR)m(O) -m(W.)h(Note)g(that)g(the)227 5601 y(n)m(um)m(b)s(ering)27 -b(con)m(v)m(en)m(tion)j(used)d(here)g(for)h(the)g(FBIT)f(parameter)i -(adopts)e(1)h(for)g(the)g(\014rst)f(elemen)m(t)i(of)f(the)227 -5714 y(v)m(ector)k(of)f(bits;)f(this)h(is)f(the)h(Most)g(Signi\014can)m -(t)g(Bit)g(of)g(the)f(in)m(teger)i(v)-5 b(alue.)p eop -end -%%Page: 64 70 -TeXDict begin 64 69 bop 0 299 a Fi(64)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)382 555 y Fe(FTGCX[IJD]\(unit,colnum,f)o(row)o(,nro)o -(ws,f)o(bit)o(,nbi)o(t,)42 b(>)47 b(array,status\))0 -788 y Fh(11)f Fi(Get)37 b(the)e(descriptor)h(for)f(a)h(v)-5 -b(ariable)37 b(length)f(column)f(in)g(a)h(binary)f(table.)57 -b(The)35 b(descriptor)h(consists)g(of)227 901 y(2)c(in)m(teger)g -(parameters:)42 b(the)31 b(n)m(um)m(b)s(er)f(of)h(elemen)m(ts)i(in)d -(the)h(arra)m(y)h(and)e(the)h(starting)h(o\013set)g(relativ)m(e)h(to) -227 1014 y(the)28 b(start)f(of)g(the)h(heap.)39 b(The)27 -b(\014rst)f(routine)h(returns)f(a)h(single)h(descriptor)f(whereas)g -(the)g(second)g(routine)227 1127 y(returns)i(the)i(descriptors)f(for)g -(a)h(range)g(of)f(ro)m(ws)h(in)f(the)g(table.)382 1359 -y Fe(FTGDES\(unit,colnum,rownu)o(m,)41 b(>)48 b -(nelements,offset,status\))382 1472 y(FTGDESLL\(unit,colnum,row)o(num)o -(,)42 b(>)47 b(nelementsll,offsetll,statu)o(s\))382 1698 -y(FTGDESS\(unit,colnum,firs)o(tro)o(w,nr)o(ows)41 b(>)48 -b(nelements,offset,)43 b(status\))382 1811 y(FTGDESSLL\(unit,colnum,fi) -o(rst)o(row,)o(nrow)o(s)f(>)47 b(nelementsll,offsetll,)42 -b(status\))0 2044 y Fh(12)k Fi(W)-8 b(rite)33 b(the)f(descriptor)g(for) -f(a)i(v)-5 b(ariable)32 b(length)g(column)g(in)f(a)i(binary)e(table.)45 -b(These)32 b(subroutines)e(can)j(b)s(e)227 2157 y(used)f(in)h -(conjunction)g(with)g(FTGDES)g(to)g(enable)h(2)f(or)g(more)g(arra)m(ys) -h(to)f(p)s(oin)m(t)g(to)h(the)f(same)g(storage)227 2270 -y(lo)s(cation)f(to)f(sa)m(v)m(e)h(storage)g(space)f(if)f(the)h(arra)m -(ys)g(are)g(iden)m(tical.)382 2503 y Fe(FTPDES\(unit,colnum,rownu)o -(m,n)o(elem)o(ents)o(,of)o(fset)o(,)42 b(>)47 b(status\))382 -2615 y(FTPDESLL\(unit,colnum,row)o(num)o(,nel)o(emen)o(tsl)o(l,of)o -(fset)o(ll,)41 b(>)48 b(status\))0 2945 y Fd(6.8)135 -b(Ro)l(w)46 b(Selection)g(and)f(Calculator)h(Routines)0 -3195 y Fi(These)21 b(routines)f(all)i(parse)f(and)f(ev)-5 -b(aluate)23 b(an)d(input)g(string)h(con)m(taining)i(a)e(user)f -(de\014ned)g(arithmetic)i(expression.)0 3308 y(The)29 -b(\014rst)f(3)i(routines)f(select)i(ro)m(ws)e(in)g(a)h(FITS)e(table,)j -(based)e(on)g(whether)g(the)g(expression)g(ev)-5 b(aluates)31 -b(to)f(true)0 3421 y(\(not)e(equal)f(to)h(zero\))g(or)f(false)h -(\(zero\).)41 b(The)27 b(other)g(routines)g(ev)-5 b(aluate)29 -b(the)e(expression)g(and)f(calculate)k(a)d(v)-5 b(alue)0 -3534 y(for)35 b(eac)m(h)h(ro)m(w)g(of)f(the)h(table.)56 -b(The)35 b(allo)m(w)m(ed)i(expression)e(syn)m(tax)g(is)h(describ)s(ed)e -(in)h(the)g(ro)m(w)h(\014lter)f(section)h(in)0 3647 y(the)h(earlier)h -(`Extended)e(File)i(Name)f(Syn)m(tax')g(c)m(hapter)h(of)f(this)f(do)s -(cumen)m(t.)60 b(The)36 b(expression)h(ma)m(y)g(also)h(b)s(e)0 -3760 y(written)28 b(to)i(a)e(text)i(\014le,)f(and)f(the)h(name)f(of)h -(the)f(\014le,)h(prep)s(ended)e(with)h(a)h('@')f(c)m(haracter)i(ma)m(y) -f(b)s(e)f(supplied)f(for)0 3873 y(the)34 b('expr')g(parameter)g(\(e.g.) -53 b('@\014lename.txt'\).)f(The)34 b(expression)f(in)h(the)g(\014le)g -(can)g(b)s(e)f(arbitrarily)h(complex)0 3985 y(and)h(extend)h(o)m(v)m -(er)h(m)m(ultiple)f(lines)g(of)g(the)f(\014le.)57 b(Lines)36 -b(that)g(b)s(egin)f(with)g(2)h(slash)g(c)m(haracters)h(\('//'\))h(will) -e(b)s(e)0 4098 y(ignored)30 b(and)g(ma)m(y)h(b)s(e)f(used)g(to)h(add)e -(commen)m(ts)j(to)f(the)f(\014le.)0 4331 y Fh(1)81 b -Fi(Ev)-5 b(aluate)38 b(a)f(b)s(o)s(olean)g(expression)g(o)m(v)m(er)h -(the)g(indicated)f(ro)m(ws,)i(returning)d(an)h(arra)m(y)h(of)f(\015ags) -g(indicating)227 4444 y(whic)m(h)30 b(ro)m(ws)h(ev)-5 -b(aluated)31 b(to)g(TR)m(UE/F)-10 b(ALSE)430 4677 y Fe -(FTFROW\(unit,expr,firstr)o(ow,)41 b(nrows,)46 b(>)i(n_good_rows,)c -(row_status,)h(status\))0 4910 y Fh(2)81 b Fi(Find)29 -b(the)i(\014rst)f(ro)m(w)g(whic)m(h)g(satis\014es)h(the)g(input)e(b)s -(o)s(olean)h(expression)430 5142 y Fe(FTFFRW\(unit,)44 -b(expr,)i(>)i(rownum,)e(status\))0 5375 y Fh(3)81 b Fi(Ev)-5 -b(aluate)35 b(an)f(expression)h(on)f(all)h(ro)m(ws)g(of)f(a)h(table.)54 -b(If)34 b(the)g(input)g(and)g(output)g(\014les)g(are)h(not)g(the)f -(same,)227 5488 y(cop)m(y)i(the)g(TR)m(UE)f(ro)m(ws)g(to)h(the)f -(output)g(\014le;)j(if)d(the)g(output)g(table)h(is)f(not)h(empt)m(y)-8 -b(,)37 b(then)e(this)g(routine)227 5601 y(will)28 b(app)s(end)e(the)i -(new)f(selected)i(ro)m(ws)e(after)h(the)g(existing)h(ro)m(ws.)39 -b(If)27 b(the)h(\014les)g(are)f(the)h(same,)h(delete)g(the)227 -5714 y(F)-10 b(ALSE)30 b(ro)m(ws)h(\(preserv)m(e)f(the)h(TR)m(UE)f(ro)m -(ws\).)p eop end -%%Page: 65 71 -TeXDict begin 65 70 bop 0 299 a Fg(6.9.)72 b(CELESTIAL)29 -b(COORDINA)-8 b(TE)30 b(SYSTEM)f(SUBR)m(OUTINES)1307 -b Fi(65)430 555 y Fe(FTSROW\(inunit,)43 b(outunit,)j(expr,)g(>)i -(status\))0 816 y Fh(4)81 b Fi(Calculate)28 b(an)f(expression)f(for)h -(the)f(indicated)i(ro)m(ws)e(of)h(a)g(table,)i(returning)d(the)h -(results,)g(cast)h(as)f(datat)m(yp)s(e)227 929 y(\(TSHOR)-8 -b(T,)32 b(TDOUBLE,)h(etc\),)h(in)e(arra)m(y)-8 b(.)48 -b(If)31 b(n)m(ulv)-5 b(al==NULL,)33 b(UNDEFs)g(will)f(b)s(e)g(zero)s -(ed)g(out.)47 b(F)-8 b(or)227 1042 y(v)m(ector)37 b(results,)f(the)f(n) -m(um)m(b)s(er)e(of)i(elemen)m(ts)i(returned)c(ma)m(y)j(b)s(e)e(less)h -(than)g(nelemen)m(ts)g(if)g(nelemen)m(ts)h(is)227 1155 -y(not)30 b(an)g(ev)m(en)h(m)m(ultiple)f(of)g(the)g(result)g(dimension.) -40 b(Call)30 b(FTTEXP)g(to)g(obtain)h(the)f(dimensions)f(of)h(the)227 -1268 y(results.)430 1529 y Fe(FTCROW\(unit,datatype,ex)o(pr,)o(firs)o -(trow)o(,ne)o(leme)o(nts,)o(nul)o(val,)41 b(>)620 1642 -y(array,anynul,status\))0 1903 y Fh(5)81 b Fi(Ev)-5 b(aluate)33 -b(an)g(expression)f(and)h(write)f(the)h(result)g(either)g(to)h(a)f -(column)f(\(if)h(the)g(expression)f(is)h(a)g(function)227 -2016 y(of)d(other)g(columns)g(in)f(the)h(table\))h(or)f(to)g(a)h(k)m -(eyw)m(ord)f(\(if)g(the)g(expression)f(ev)-5 b(aluates)32 -b(to)e(a)g(constan)m(t)i(and)227 2129 y(is)f(not)f(a)h(function)f(of)h -(other)f(columns)h(in)f(the)g(table\).)42 b(In)30 b(the)h(former)e -(case,)j(the)f(parName)f(parameter)227 2242 y(is)40 b(the)g(name)f(of)h -(the)g(column)f(\(whic)m(h)h(ma)m(y)g(or)f(ma)m(y)h(not)g(already)g -(exist\))h(in)m(to)f(whic)m(h)g(to)g(write)g(the)227 -2355 y(results,)e(and)f(parInfo)e(con)m(tains)j(an)f(optional)g(TF)m -(ORM)g(k)m(eyw)m(ord)g(v)-5 b(alue)38 b(if)e(a)h(new)f(column)h(is)f(b) -s(eing)227 2468 y(created.)42 b(If)28 b(a)h(TF)m(ORM)h(v)-5 -b(alue)29 b(is)g(not)g(sp)s(eci\014ed)g(then)f(a)i(default)f(format)g -(will)h(b)s(e)e(used,)h(dep)s(ending)e(on)227 2581 y(the)35 -b(expression.)54 b(If)34 b(the)h(expression)f(ev)-5 b(aluates)37 -b(to)e(a)g(constan)m(t,)i(then)e(the)g(result)f(will)h(b)s(e)f(written) -h(to)227 2693 y(the)28 b(k)m(eyw)m(ord)g(name)f(giv)m(en)h(b)m(y)g(the) -f(parName)h(parameter,)h(and)d(the)i(parInfo)e(parameter)i(ma)m(y)g(b)s -(e)f(used)227 2806 y(to)k(supply)e(an)h(optional)i(commen)m(t)f(for)f -(the)g(k)m(eyw)m(ord.)42 b(If)29 b(the)i(k)m(eyw)m(ord)g(do)s(es)f(not) -g(already)h(exist,)g(then)227 2919 y(the)f(name)f(of)h(the)g(k)m(eyw)m -(ord)g(m)m(ust)f(b)s(e)g(preceded)g(with)g(a)h('#')f(c)m(haracter,)j -(otherwise)e(the)f(result)h(will)g(b)s(e)227 3032 y(written)h(to)g(a)g -(column)f(with)g(that)h(name.)430 3293 y Fe(FTCALC\(inunit,)43 -b(expr,)k(outunit,)e(parName,)h(parInfo,)f(>)j(status\))0 -3554 y Fh(6)81 b Fi(This)38 b(calculator)k(routine)e(is)f(similar)h(to) -g(the)g(previous)f(routine,)j(except)f(that)f(the)g(expression)f(is)h -(only)227 3667 y(ev)-5 b(aluated)42 b(o)m(v)m(er)f(the)f(sp)s -(eci\014ed)g(ro)m(w)g(ranges.)70 b(nranges)39 b(sp)s(eci\014es)h(the)g -(n)m(um)m(b)s(er)f(of)h(ro)m(w)h(ranges,)i(and)227 3780 -y(\014rstro)m(w)30 b(and)g(lastro)m(w)h(giv)m(e)h(the)f(starting)g(and) -f(ending)g(ro)m(w)g(n)m(um)m(b)s(er)f(of)i(eac)m(h)g(range.)430 -4041 y Fe(FTCALC_RNG\(inunit,)42 b(expr,)47 b(outunit,)e(parName,)h -(parInfo,)573 4154 y(nranges,)f(firstrow,)h(lastrow,)f(>)j(status\))0 -4415 y Fh(7)81 b Fi(Ev)-5 b(aluate)36 b(the)f(giv)m(en)h(expression)f -(and)g(return)f(dimension)g(and)h(t)m(yp)s(e)g(information)g(on)g(the)h -(result.)54 b(The)227 4528 y(returned)37 b(dimensions)f(corresp)s(ond)g -(to)j(a)e(single)i(ro)m(w)e(en)m(try)h(of)f(the)h(requested)f -(expression,)j(and)d(are)227 4641 y(equiv)-5 b(alen)m(t)26 -b(to)f(the)g(result)f(of)g(\014ts)p 1380 4641 28 4 v -33 w(read)p 1585 4641 V 32 w(tdim\(\).)40 b(Note)25 b(that)g(strings)f -(are)h(considered)f(to)h(b)s(e)f(one)g(elemen)m(t)227 -4754 y(regardless)31 b(of)g(string)f(length.)41 b(If)30 -b(maxdim)g(==)g(0,)h(then)f(naxes)g(is)h(optional.)430 -5015 y Fe(FTTEXP\(unit,)44 b(expr,)i(maxdim)g(>)i(datatype,)d(nelem,)h -(naxis,)g(naxes,)g(status\))0 5350 y Fd(6.9)135 b(Celestial)48 -b(Co)t(ordinate)e(System)f(Subroutines)0 5601 y Fi(The)36 -b(FITS)g(comm)m(unit)m(y)h(has)f(adopted)h(a)g(set)g(of)g(k)m(eyw)m -(ord)g(con)m(v)m(en)m(tions)h(that)f(de\014ne)f(the)h(transformations)0 -5714 y(needed)30 b(to)i(con)m(v)m(ert)g(b)s(et)m(w)m(een)f(pixel)g(lo)s -(cations)h(in)e(an)h(image)h(and)e(the)g(corresp)s(onding)g(celestial)j -(co)s(ordinates)p eop end -%%Page: 66 72 -TeXDict begin 66 71 bop 0 299 a Fi(66)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)0 555 y Fi(on)25 b(the)h(sky)-8 b(,)27 -b(or)e(more)g(generally)-8 b(,)29 b(that)d(de\014ne)e(w)m(orld)h(co)s -(ordinates)i(that)e(are)h(to)g(b)s(e)f(asso)s(ciated)i(with)e(an)m(y)h -(pixel)0 668 y(lo)s(cation)36 b(in)e(an)h(n-dimensional)f(FITS)g(arra)m -(y)-8 b(.)54 b(CFITSIO)33 b(is)h(distributed)g(with)g(a)h(couple)f(of)h -(self-con)m(tained)0 781 y(W)-8 b(orld)28 b(Co)s(ordinate)f(System)f -(\(W)m(CS\))i(routines,)g(ho)m(w)m(ev)m(er,)h(these)f(routines)f(DO)g -(NOT)f(supp)s(ort)f(all)j(the)f(latest)0 894 y(W)m(CS)38 -b(con)m(v)m(en)m(tions,)k(so)d(it)g(is)f(STR)m(ONGL)-8 -b(Y)38 b(RECOMMENDED)h(that)f(soft)m(w)m(are)i(dev)m(elop)s(ers)e(use)g -(a)h(more)0 1007 y(robust)30 b(external)h(W)m(CS)f(library)-8 -b(.)41 b(Sev)m(eral)31 b(recommended)f(libraries)h(are:)95 -1285 y Fe(WCSLIB)47 b(-)95 b(supported)45 b(by)i(Mark)g(Calabretta)95 -1398 y(WCSTools)f(-)h(supported)f(by)h(Doug)g(Mink)95 -1511 y(AST)g(library)f(-)i(developed)d(by)i(the)g(U.K.)g(Starlink)e -(project)0 1788 y Fi(More)30 b(information)f(ab)s(out)g(the)g(W)m(CS)g -(k)m(eyw)m(ord)h(con)m(v)m(en)m(tions)h(and)d(links)h(to)h(all)g(of)f -(these)g(W)m(CS)g(libraries)h(can)0 1901 y(b)s(e)g(found)f(on)h(the)h -(FITS)e(Supp)s(ort)g(O\016ce)h(w)m(eb)g(site)i(at)f(h)m -(ttp://\014ts.gsfc.nasa.go)m(v)j(under)29 b(the)h(W)m(CS)h(link.)0 -2061 y(The)i(functions)h(pro)m(vided)g(in)f(these)i(external)f(W)m(CS)g -(libraries)h(will)f(need)g(access)h(to)g(the)f(W)m(CS)g(information)0 -2174 y(con)m(tained)i(in)f(the)h(FITS)e(\014le)i(headers.)55 -b(One)35 b(con)m(v)m(enien)m(t)i(w)m(a)m(y)f(to)g(pass)f(this)g -(information)h(to)g(the)f(external)0 2287 y(library)k(is)h(to)h(use)e -(FITSIO)g(to)h(cop)m(y)h(the)f(header)f(k)m(eyw)m(ords)h(in)m(to)h(one) -f(long)g(c)m(haracter)i(string,)g(and)d(then)0 2400 y(pass)29 -b(this)h(string)g(to)g(an)g(in)m(terface)h(routine)f(in)g(the)g -(external)g(library)g(that)g(will)g(extract)i(the)e(necessary)g(W)m(CS) -0 2513 y(information)h(\(e.g.,)h(see)f(the)f(astFitsChan)h(and)f -(astPutCards)g(routines)g(in)g(the)h(Starlink)f(AST)g(library\).)0 -2673 y(The)24 b(follo)m(wing)j(FITSIO)c(routines)i(DO)g(NOT)f(supp)s -(ort)f(the)i(more)g(recen)m(t)h(W)m(CS)f(con)m(v)m(en)m(tions)i(that)f -(ha)m(v)m(e)g(b)s(een)0 2786 y(appro)m(v)m(ed)37 b(as)h(part)f(of)g -(the)h(FITS)e(standard.)61 b(Consequen)m(tly)-8 b(,)39 -b(the)f(follo)m(wing)g(routines)g(ARE)f(NO)m(W)h(DEP-)0 -2899 y(RECA)-8 b(TED.)29 b(It)f(is)h(STR)m(ONGL)-8 b(Y)28 -b(RECOMMENDED)h(that)g(soft)m(w)m(are)h(dev)m(elop)s(ers)f(not)g(use)f -(these)h(routines,)0 3012 y(and)h(instead)g(use)g(an)h(external)g(W)m -(CS)f(library)-8 b(,)31 b(as)g(describ)s(ed)e(ab)s(o)m(v)m(e.)0 -3172 y(These)21 b(routines)g(are)g(included)f(mainly)h(for)g(bac)m(kw)m -(ard)g(compatibilit)m(y)j(with)c(existing)i(soft)m(w)m(are.)39 -b(They)21 b(supp)s(ort)0 3285 y(the)30 b(follo)m(wing)i(standard)d(map) -g(pro)5 b(jections:)41 b(-SIN,)30 b(-T)-8 b(AN,)31 b(-AR)m(C,)g(-NCP)-8 -b(,)30 b(-GLS,)g(-MER,)h(and)e(-AIT)h(\(these)0 3398 -y(are)f(the)g(legal)h(v)-5 b(alues)29 b(for)f(the)h(co)s(ordt)m(yp)s(e) -f(parameter\).)41 b(These)28 b(routines)h(are)g(based)f(on)g(similar)h -(functions)f(in)0 3511 y(Classic)j(AIPS.)f(All)h(the)g(angular)f(quan)m -(tities)i(are)f(giv)m(en)g(in)f(units)g(of)g(degrees.)0 -3789 y Fh(1)81 b Fi(Get)22 b(the)g(v)-5 b(alues)21 b(of)h(all)g(the)g -(standard)f(FITS)f(celestial)k(co)s(ordinate)f(system)e(k)m(eyw)m(ords) -h(from)f(the)h(header)f(of)h(a)227 3902 y(FITS)j(image)i(\(i.e.,)h(the) -d(primary)g(arra)m(y)h(or)f(an)h(image)g(extension\).)40 -b(These)26 b(v)-5 b(alues)25 b(ma)m(y)h(then)g(b)s(e)e(passed)227 -4015 y(to)39 b(the)e(subroutines)g(that)h(p)s(erform)e(the)i(co)s -(ordinate)g(transformations.)63 b(If)37 b(an)m(y)h(or)g(all)g(of)g(the) -g(W)m(CS)227 4127 y(k)m(eyw)m(ords)32 b(are)f(not)g(presen)m(t,)h(then) -f(default)g(v)-5 b(alues)31 b(will)h(b)s(e)e(returned.)41 -b(If)31 b(the)g(\014rst)g(co)s(ordinate)g(axis)h(is)227 -4240 y(the)d(declination-lik)m(e)j(co)s(ordinate,)e(then)e(this)g -(routine)h(will)g(sw)m(ap)f(them)h(so)g(that)g(the)g(longitudinal-lik)m -(e)227 4353 y(co)s(ordinate)i(is)g(returned)e(as)i(the)f(\014rst)g -(axis.)227 4513 y(If)35 b(the)h(\014le)f(uses)g(the)g(new)m(er)h('CDj)p -1454 4513 28 4 v 32 w(i')g(W)m(CS)f(transformation)h(matrix)g(k)m(eyw)m -(ords)f(instead)h(of)f(old)h(st)m(yle)227 4625 y('CDEL)-8 -b(Tn')37 b(and)f('CR)m(OT)-8 b(A2')38 b(k)m(eyw)m(ords,)h(then)e(this)f -(routine)h(will)g(calculate)j(and)c(return)g(the)h(v)-5 -b(alues)227 4738 y(of)33 b(the)g(equiv)-5 b(alen)m(t)35 -b(old-st)m(yle)f(k)m(eyw)m(ords.)49 b(Note)34 b(that)g(the)f(con)m(v)m -(ersion)h(from)e(the)i(new-st)m(yle)g(k)m(eyw)m(ords)227 -4851 y(to)e(the)f(old-st)m(yle)h(v)-5 b(alues)31 b(is)g(sometimes)g -(only)g(an)g(appro)m(ximation,)h(so)e(if)h(the)g(appro)m(ximation)h(is) -e(larger)227 4964 y(than)37 b(an)h(in)m(ternally)g(de\014ned)e -(threshold)h(lev)m(el,)k(then)c(CFITSIO)f(will)i(still)g(return)e(the)i -(appro)m(ximate)227 5077 y(W)m(CS)f(k)m(eyw)m(ord)g(v)-5 -b(alues,)39 b(but)d(will)h(also)h(return)d(with)i(status)g(=)f(506,)k -(to)e(w)m(arn)e(the)h(calling)h(program)227 5190 y(that)30 -b(appro)m(ximations)f(ha)m(v)m(e)h(b)s(een)e(made.)40 -b(It)29 b(is)g(then)f(up)g(to)h(the)g(calling)i(program)d(to)h(decide)h -(whether)227 5303 y(the)k(appro)m(ximations)g(are)g(su\016cien)m(tly)g -(accurate)i(for)d(the)h(particular)f(application,)j(or)e(whether)f -(more)227 5416 y(precise)e(W)m(CS)f(transformations)h(m)m(ust)f(b)s(e)g -(p)s(erformed)f(using)h(new-st)m(yle)h(W)m(CS)g(k)m(eyw)m(ords)f -(directly)-8 b(.)382 5694 y Fe(FTGICS\(unit,)44 b(>)k -(xrval,yrval,xrpix,yrpix)o(,xin)o(c,yi)o(nc,)o(rot,)o(coor)o(dty)o -(pe,s)o(tatu)o(s\))p eop end -%%Page: 67 73 -TeXDict begin 67 72 bop 0 299 a Fg(6.10.)73 b(FILE)30 -b(CHECKSUM)f(SUBR)m(OUTINES)2080 b Fi(67)0 555 y Fh(2)81 -b Fi(Get)34 b(the)f(v)-5 b(alues)33 b(of)g(all)h(the)f(standard)f(FITS) -h(celestial)i(co)s(ordinate)f(system)f(k)m(eyw)m(ords)g(from)g(the)g -(header)227 668 y(of)j(a)h(FITS)e(table)h(where)g(the)g(X)g(and)f(Y)h -(\(or)g(RA)g(and)g(DEC)f(co)s(ordinates)i(are)f(stored)g(in)g(2)g -(separate)227 781 y(columns)c(of)g(the)g(table.)46 b(These)31 -b(v)-5 b(alues)32 b(ma)m(y)h(then)e(b)s(e)h(passed)f(to)h(the)g -(subroutines)f(that)h(p)s(erform)f(the)227 894 y(co)s(ordinate)g -(transformations.)382 1114 y Fe(FTGTCS\(unit,xcol,ycol,)42 -b(>)716 1227 y(xrval,yrval,xrpix,yrpix,)o(xinc)o(,yi)o(nc,r)o(ot,c)o -(oor)o(dtyp)o(e,st)o(atu)o(s\))0 1446 y Fh(3)81 b Fi(Calculate)42 -b(the)g(celestial)h(co)s(ordinate)f(corresp)s(onding)e(to)i(the)f -(input)f(X)h(and)g(Y)g(pixel)g(lo)s(cation)i(in)e(the)227 -1559 y(image.)382 1779 y Fe(FTWLDP\(xpix,ypix,xrval,y)o(rva)o(l,xr)o -(pix,)o(yrp)o(ix,x)o(inc,)o(yin)o(c,ro)o(t,)1241 1892 -y(coordtype,)k(>)i(xpos,ypos,status\))0 2112 y Fh(4)81 -b Fi(Calculate)42 b(the)g(X)f(and)f(Y)h(pixel)h(lo)s(cation)g(corresp)s -(onding)e(to)i(the)f(input)f(celestial)k(co)s(ordinate)e(in)f(the)227 -2225 y(image.)382 2445 y Fe(FTXYPX\(xpos,ypos,xrval,y)o(rva)o(l,xr)o -(pix,)o(yrp)o(ix,x)o(inc,)o(yin)o(c,ro)o(t,)1241 2557 -y(coordtype,)k(>)i(xpix,ypix,status\))0 2885 y Fd(6.10)136 -b(File)45 b(Chec)l(ksum)g(Subroutines)0 3135 y Fi(The)33 -b(follo)m(wing)h(routines)f(either)h(compute)f(or)h(v)-5 -b(alidate)34 b(the)g(c)m(hec)m(ksums)f(for)g(the)h(CHDU.)g(The)e(D)m(A) --8 b(T)g(ASUM)0 3248 y(k)m(eyw)m(ord)33 b(is)f(used)f(to)i(store)f(the) -h(n)m(umerical)f(v)-5 b(alue)33 b(of)f(the)g(32-bit,)i(1's)f(complemen) -m(t)g(c)m(hec)m(ksum)g(for)f(the)g(data)0 3361 y(unit)26 -b(alone.)40 b(If)25 b(there)h(is)h(no)e(data)i(unit)f(then)f(the)h(v)-5 -b(alue)27 b(is)f(set)g(to)h(zero.)40 b(The)26 b(n)m(umerical)g(v)-5 -b(alue)27 b(is)f(stored)g(as)g(an)0 3474 y(ASCI)s(I)20 -b(string)i(of)h(digits,)h(enclosed)f(in)e(quotes,)k(b)s(ecause)d(the)g -(v)-5 b(alue)23 b(ma)m(y)f(b)s(e)f(to)s(o)i(large)g(to)g(represen)m(t)f -(as)g(a)h(32-bit)0 3587 y(signed)28 b(in)m(teger.)41 -b(The)27 b(CHECKSUM)g(k)m(eyw)m(ord)i(is)f(used)f(to)h(store)h(the)f -(ASCI)s(I)e(enco)s(ded)i(COMPLEMENT)f(of)0 3700 y(the)f(c)m(hec)m(ksum) -h(for)f(the)h(en)m(tire)g(HDU.)g(Storing)f(the)h(complemen)m(t,)h -(rather)e(than)g(the)h(actual)g(c)m(hec)m(ksum,)h(forces)0 -3812 y(the)k(c)m(hec)m(ksum)h(for)f(the)h(whole)f(HDU)h(to)g(equal)g -(zero.)47 b(If)31 b(the)i(\014le)f(has)g(b)s(een)f(mo)s(di\014ed)g -(since)i(the)f(c)m(hec)m(ksums)0 3925 y(w)m(ere)39 b(computed,)i(then)e -(the)g(HDU)g(c)m(hec)m(ksum)h(will)f(usually)f(not)h(equal)h(zero.)66 -b(These)39 b(c)m(hec)m(ksum)g(k)m(eyw)m(ord)0 4038 y(con)m(v)m(en)m -(tions)34 b(are)f(based)f(on)g(a)g(pap)s(er)f(b)m(y)h(Rob)g(Seaman)g -(published)f(in)h(the)g(pro)s(ceedings)g(of)g(the)h(AD)m(ASS)f(IV)0 -4151 y(conference)f(in)f(Baltimore)i(in)f(No)m(v)m(em)m(b)s(er)g(1994)h -(and)e(a)h(later)g(revision)g(in)f(June)f(1995.)0 4371 -y Fh(1)81 b Fi(Compute)33 b(and)g(write)h(the)g(D)m(A)-8 -b(T)g(ASUM)35 b(and)e(CHECKSUM)g(k)m(eyw)m(ord)h(v)-5 -b(alues)34 b(for)f(the)h(CHDU)g(in)m(to)h(the)227 4484 -y(curren)m(t)25 b(header.)38 b(The)24 b(D)m(A)-8 b(T)g(ASUM)27 -b(v)-5 b(alue)25 b(is)f(the)h(32-bit)h(c)m(hec)m(ksum)f(for)f(the)h -(data)g(unit,)h(expressed)e(as)h(a)227 4597 y(decimal)32 -b(in)m(teger)f(enclosed)g(in)f(single)h(quotes.)41 b(The)30 -b(CHECKSUM)g(k)m(eyw)m(ord)g(v)-5 b(alue)31 b(is)f(a)h(16-c)m(haracter) -227 4710 y(string)j(whic)m(h)f(is)h(the)f(ASCI)s(I-enco)s(ded)f(v)-5 -b(alue)34 b(for)g(the)f(complemen)m(t)i(of)f(the)f(c)m(hec)m(ksum)i -(for)e(the)h(whole)227 4823 y(HDU.)h(If)e(these)g(k)m(eyw)m(ords)h -(already)g(exist,)h(their)e(v)-5 b(alues)34 b(will)g(b)s(e)f(up)s -(dated)f(only)h(if)g(necessary)h(\(i.e.,)i(if)227 4936 -y(the)31 b(\014le)f(has)g(b)s(een)g(mo)s(di\014ed)f(since)i(the)g -(original)g(k)m(eyw)m(ord)g(v)-5 b(alues)31 b(w)m(ere)g(computed\).)382 -5155 y Fe(FTPCKS\(unit,)44 b(>)k(status\))0 5375 y Fh(2)81 -b Fi(Up)s(date)28 b(the)h(CHECKSUM)e(k)m(eyw)m(ord)i(v)-5 -b(alue)29 b(in)f(the)h(CHDU,)g(assuming)f(that)h(the)f(D)m(A)-8 -b(T)g(ASUM)30 b(k)m(eyw)m(ord)227 5488 y(exists)36 b(and)f(already)h -(has)f(the)h(correct)g(v)-5 b(alue.)56 b(This)35 b(routine)g -(calculates)j(the)e(new)f(c)m(hec)m(ksum)h(for)f(the)227 -5601 y(curren)m(t)40 b(header)g(unit,)j(adds)c(it)i(to)g(the)f(data)h -(unit)f(c)m(hec)m(ksum,)k(enco)s(des)c(the)g(v)-5 b(alue)41 -b(in)m(to)g(an)f(ASCI)s(I)227 5714 y(string,)31 b(and)f(writes)g(the)h -(string)f(to)h(the)g(CHECKSUM)e(k)m(eyw)m(ord.)p eop -end -%%Page: 68 74 -TeXDict begin 68 73 bop 0 299 a Fi(68)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)382 555 y Fe(FTUCKS\(unit,)44 b(>)k(status\))0 -807 y Fh(3)81 b Fi(V)-8 b(erify)35 b(the)f(CHDU)h(b)m(y)g(computing)f -(the)h(c)m(hec)m(ksums)g(and)f(comparing)h(them)f(with)g(the)h(k)m(eyw) -m(ords.)53 b(The)227 920 y(data)34 b(unit)f(is)g(v)m(eri\014ed)g -(correctly)h(if)f(the)h(computed)f(c)m(hec)m(ksum)g(equals)h(the)f(v)-5 -b(alue)34 b(of)f(the)g(D)m(A)-8 b(T)g(ASUM)227 1033 y(k)m(eyw)m(ord.)64 -b(The)37 b(c)m(hec)m(ksum)i(for)f(the)g(en)m(tire)g(HDU)h(\(header)f -(plus)f(data)i(unit\))e(is)h(correct)h(if)f(it)h(equals)227 -1146 y(zero.)55 b(The)34 b(output)g(D)m(A)-8 b(T)g(A)m(OK)37 -b(and)d(HDUOK)h(parameters)g(in)f(this)h(subroutine)e(are)i(in)m -(tegers)h(whic)m(h)227 1259 y(will)27 b(ha)m(v)m(e)g(a)f(v)-5 -b(alue)27 b(=)f(1)g(if)g(the)h(data)f(or)g(HDU)h(is)f(v)m(eri\014ed)h -(correctly)-8 b(,)29 b(a)d(v)-5 b(alue)27 b(=)e(0)i(if)f(the)g(D)m(A)-8 -b(T)g(ASUM)28 b(or)227 1372 y(CHECKSUM)h(k)m(eyw)m(ord)g(is)h(not)f -(presen)m(t,)h(or)f(v)-5 b(alue)30 b(=)f(-1)h(if)f(the)h(computed)f(c)m -(hec)m(ksum)h(is)f(not)h(correct.)382 1623 y Fe(FTVCKS\(unit,)44 -b(>)k(dataok,hduok,status\))0 1875 y Fh(4)81 b Fi(Compute)25 -b(and)h(return)f(the)i(c)m(hec)m(ksum)g(v)-5 b(alues)26 -b(for)g(the)h(CHDU)f(\(as)h(double)f(precision)h(v)-5 -b(ariables\))27 b(without)227 1988 y(creating)46 b(or)e(mo)s(difying)g -(the)h(CHECKSUM)e(and)h(D)m(A)-8 b(T)g(ASUM)46 b(k)m(eyw)m(ords.)83 -b(This)44 b(routine)g(is)h(used)227 2101 y(in)m(ternally)32 -b(b)m(y)e(FTV)m(CKS,)g(but)g(ma)m(y)h(b)s(e)e(useful)h(in)g(other)h -(situations)g(as)f(w)m(ell.)382 2353 y Fe(FTGCKS\(unit,)44 -b(>)k(datasum,hdusum,status\))0 2604 y Fh(5)81 b Fi(Enco)s(de)33 -b(a)h(c)m(hec)m(ksum)h(v)-5 b(alue)34 b(\(stored)g(in)g(a)g(double)g -(precision)g(v)-5 b(ariable\))35 b(in)m(to)f(a)h(16-c)m(haracter)h -(string.)51 b(If)227 2717 y(COMPLEMENT)30 b(=)g(.true.)41 -b(then)30 b(the)g(32-bit)i(sum)d(v)-5 b(alue)31 b(will)g(b)s(e)f -(complemen)m(ted)h(b)s(efore)f(enco)s(ding.)382 2969 -y Fe(FTESUM\(sum,complement,)42 b(>)47 b(checksum\))0 -3221 y Fh(6)81 b Fi(Deco)s(de)39 b(a)f(16)h(c)m(haracter)h(c)m(hec)m -(ksum)e(string)g(in)m(to)h(a)g(double)e(precision)h(v)-5 -b(alue.)65 b(If)37 b(COMPLEMENT)g(=)227 3334 y(.true.)k(then)30 -b(the)h(32-bit)g(sum)f(v)-5 b(alue)31 b(will)f(b)s(e)g(complemen)m(ted) -i(after)e(deco)s(ding.)382 3586 y Fe(FTDSUM\(checksum,compleme)o(nt,)41 -b(>)48 b(sum\))0 3918 y Fd(6.11)180 b(Date)46 b(and)f(Time)g(Utilit)l -(y)i(Routines)0 4168 y Fi(The)29 b(follo)m(wing)i(routines)f(help)f(to) -i(construct)f(or)f(parse)h(the)g(FITS)f(date/time)i(strings.)41 -b(Starting)30 b(in)f(the)h(y)m(ear)0 4281 y(2000,)k(the)d(FITS)g(D)m(A) --8 b(TE)32 b(k)m(eyw)m(ord)g(v)-5 b(alues)31 b(\(and)h(the)f(v)-5 -b(alues)32 b(of)f(other)h(`D)m(A)-8 b(TE-')33 b(k)m(eyw)m(ords\))f(m)m -(ust)f(ha)m(v)m(e)i(the)0 4394 y(form)j('YYYY-MM-DD')k(\(date)e(only\)) -f(or)g('YYYY-MM-DDThh:mm:ss.ddd...')61 b(\(date)38 b(and)e(time\))h -(where)0 4507 y(the)30 b(n)m(um)m(b)s(er)f(of)i(decimal)g(places)g(in)f -(the)g(seconds)g(v)-5 b(alue)31 b(is)f(optional.)42 b(These)30 -b(times)h(are)f(in)g(UTC.)g(The)g(older)0 4620 y('dd/mm/yy')g(date)h -(format)g(ma)m(y)g(not)g(b)s(e)e(used)h(for)g(dates)h(after)g(01)g(Jan) -m(uary)f(2000.)0 4872 y Fh(1)81 b Fi(Get)31 b(the)g(curren)m(t)f -(system)g(date.)42 b(The)29 b(returned)h(y)m(ear)h(has)f(4)h(digits)g -(\(1999,)h(2000,)h(etc.\))382 5123 y Fe(FTGSDT\()46 b(>)h(day,)g -(month,)f(year,)g(status)g(\))0 5375 y Fh(2)81 b Fi(Get)34 -b(the)g(curren)m(t)g(system)f(date)i(and)e(time)h(string)g -(\('YYYY-MM-DDThh:mm:ss'\).)53 b(The)33 b(time)i(will)f(b)s(e)227 -5488 y(in)26 b(UTC/GMT)g(if)g(a)m(v)-5 b(ailable,)29 -b(as)e(indicated)f(b)m(y)g(a)g(returned)f(timeref)h(v)-5 -b(alue)27 b(=)e(0.)40 b(If)26 b(the)g(returned)e(v)-5 -b(alue)227 5601 y(of)31 b(timeref)g(=)g(1)g(then)f(this)h(indicates)g -(that)h(it)f(w)m(as)g(not)g(p)s(ossible)f(to)h(con)m(v)m(ert)i(the)d -(lo)s(cal)i(time)g(to)f(UTC,)227 5714 y(and)f(th)m(us)g(the)h(lo)s(cal) -g(time)g(w)m(as)g(returned.)p eop end -%%Page: 69 75 -TeXDict begin 69 74 bop 0 299 a Fg(6.12.)73 b(GENERAL)30 -b(UTILITY)g(SUBR)m(OUTINES)1979 b Fi(69)382 555 y Fe(FTGSTM\(>)45 -b(datestr,)h(timeref,)f(status\))0 821 y Fh(3)81 b Fi(Construct)26 -b(a)i(date)g(string)f(from)g(the)g(input)f(date)i(v)-5 -b(alues.)40 b(If)27 b(the)g(y)m(ear)h(is)g(b)s(et)m(w)m(een)f(1900)i -(and)e(1998,)j(inclu-)227 934 y(siv)m(e,)38 b(then)c(the)i(returned)d -(date)j(string)f(will)g(ha)m(v)m(e)i(the)e(old)g(FITS)f(format)i -(\('dd/mm/yy'\),)h(otherwise)227 1047 y(the)32 b(date)g(string)f(will)g -(ha)m(v)m(e)i(the)e(new)g(FITS)g(format)g(\('YYYY-MM-DD'\).)36 -b(Use)c(FTTM2S)f(instead)g(to)227 1160 y(alw)m(a)m(ys)h(return)d(a)i -(date)g(string)g(using)e(the)i(new)f(FITS)g(format.)382 -1426 y Fe(FTDT2S\()46 b(year,)g(month,)g(day,)h(>)g(datestr,)f -(status\))0 1692 y Fh(4)81 b Fi(Construct)34 b(a)i(new-format)f(date)h -(+)f(time)h(string)f(\('YYYY-MM-DDThh:mm:ss.ddd...'\).)57 -b(If)34 b(the)i(y)m(ear,)227 1805 y(mon)m(th,)d(and)e(da)m(y)h(v)-5 -b(alues)32 b(all)h(=)e(0)h(then)g(only)g(the)g(time)g(is)g(enco)s(ded)f -(with)h(format)g('hh:mm:ss.ddd...'.)227 1918 y(The)j(decimals)h -(parameter)g(sp)s(eci\014es)e(ho)m(w)i(man)m(y)f(decimal)h(places)g(of) -f(fractional)i(seconds)e(to)h(include)227 2030 y(in)30 -b(the)h(string.)41 b(If)29 b(`decimals')j(is)f(negativ)m(e,)h(then)f -(only)f(the)h(date)g(will)f(b)s(e)g(return)f(\('YYYY-MM-DD'\).)382 -2296 y Fe(FTTM2S\()46 b(year,)g(month,)g(day,)h(hour,)f(minute,)g -(second,)g(decimals,)764 2409 y(>)h(datestr,)f(status\))0 -2675 y Fh(5)81 b Fi(Return)44 b(the)g(date)i(as)f(read)f(from)h(the)g -(input)e(string,)49 b(where)44 b(the)h(string)g(ma)m(y)g(b)s(e)f(in)h -(either)g(the)g(old)227 2788 y(\('dd/mm/yy'\))31 b(or)g(new)e -(\('YYYY-MM-DDThh:mm:ss')k(or)d('YYYY-MM-DD'\))k(FITS)c(format.)382 -3054 y Fe(FTS2DT\(datestr,)43 b(>)48 b(year,)e(month,)g(day,)h -(status\))0 3320 y Fh(6)81 b Fi(Return)30 b(the)h(date)h(and)f(time)h -(as)f(read)g(from)g(the)h(input)e(string,)h(where)g(the)h(string)f(ma)m -(y)h(b)s(e)e(in)h(either)h(the)227 3433 y(old)d(or)f(new)g(FITS)g -(format.)40 b(The)28 b(returned)f(hours,)h(min)m(utes,)h(and)f(seconds) -g(v)-5 b(alues)29 b(will)f(b)s(e)g(set)h(to)g(zero)227 -3546 y(if)k(the)h(input)e(string)h(do)s(es)g(not)h(include)f(the)g -(time)h(\('dd/mm/yy')f(or)h('YYYY-MM-DD'\))j(.)c(Similarly)-8 -b(,)227 3659 y(the)36 b(returned)e(y)m(ear,)j(mon)m(th,)g(and)d(date)i -(v)-5 b(alues)36 b(will)f(b)s(e)g(set)h(to)g(zero)g(if)f(the)g(date)h -(is)f(not)h(included)e(in)227 3772 y(the)d(input)e(string)i -(\('hh:mm:ss.ddd...'\).)382 4037 y Fe(FTS2TM\(datestr,)43 -b(>)48 b(year,)e(month,)g(day,)h(hour,)f(minute,)g(second,)g(status\))0 -4378 y Fd(6.12)136 b(General)45 b(Utilit)l(y)i(Subroutines)0 -4630 y Fi(The)30 b(follo)m(wing)i(utilit)m(y)f(subroutines)f(ma)m(y)h -(b)s(e)e(useful)h(for)g(certain)h(applications:)0 4896 -y Fh(1)81 b Fi(Return)29 b(the)i(starting)g(b)m(yte)g(address)e(of)i -(the)f(CHDU)h(and)f(the)h(next)f(HDU.)382 5162 y Fe(FTGHAD\(iunit,)44 -b(>)j(curaddr,)f(nextaddr\))0 5428 y Fh(2)81 b Fi(Con)m(v)m(ert)31 -b(a)g(c)m(haracter)h(string)e(to)h(upp)s(ercase)e(\(op)s(erates)j(in)e -(place\).)382 5694 y Fe(FTUPCH\(string\))p eop end -%%Page: 70 76 -TeXDict begin 70 75 bop 0 299 a Fi(70)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)0 555 y Fh(3)81 b Fi(Compare)43 b(the)i(input)e -(template)i(string)f(against)h(the)g(reference)f(string)g(to)h(see)g -(if)f(they)g(matc)m(h.)82 b(The)227 668 y(template)36 -b(string)f(ma)m(y)g(con)m(tain)g(wildcard)f(c)m(haracters:)51 -b('*')35 b(will)g(matc)m(h)g(an)m(y)g(sequence)g(of)f(c)m(haracters)227 -781 y(\(including)j(zero)h(c)m(haracters\))g(and)e(')10 -b(?')60 b(will)38 b(matc)m(h)f(an)m(y)g(single)h(c)m(haracter)g(in)f -(the)g(reference)g(string.)227 894 y(The)31 b('#')g(c)m(haracter)i -(will)f(matc)m(h)g(an)m(y)f(consecutiv)m(e)j(string)d(of)g(decimal)h -(digits)g(\(0)g(-)g(9\).)43 b(If)31 b(CASESN)f(=)227 -1007 y(.true.)45 b(then)31 b(the)g(matc)m(h)i(will)f(b)s(e)f(case)h -(sensitiv)m(e.)46 b(The)31 b(returned)f(MA)-8 b(TCH)32 -b(parameter)g(will)g(b)s(e)f(.true.)227 1120 y(if)j(the)h(2)f(strings)g -(matc)m(h,)j(and)c(EXA)m(CT)h(will)h(b)s(e)e(.true.)53 -b(if)34 b(the)g(matc)m(h)h(is)g(exact)g(\(i.e.,)i(if)d(no)g(wildcard) -227 1233 y(c)m(haracters)e(w)m(ere)f(used)f(in)g(the)g(matc)m(h\).)42 -b(Both)31 b(strings)f(m)m(ust)h(b)s(e)e(68)j(c)m(haracters)f(or)g(less) -f(in)g(length.)382 1505 y Fe(FTCMPS\(str_template,)42 -b(string,)k(casesen,)f(>)j(match,)e(exact\))0 1778 y -Fh(4)81 b Fi(T)-8 b(est)31 b(that)g(the)f(k)m(eyw)m(ord)h(name)f(con)m -(tains)i(only)e(legal)j(c)m(haracters:)42 b(A-Z,0-9,)32 -b(h)m(yphen,)d(and)h(underscore.)382 2051 y Fe(FTTKEY\(keyword,)43 -b(>)48 b(status\))0 2324 y Fh(5)81 b Fi(T)-8 b(est)31 -b(that)g(the)f(k)m(eyw)m(ord)h(record)f(con)m(tains)i(only)e(legal)i -(prin)m(table)f(ASCI)s(I)e(c)m(haracters)382 2597 y Fe(FTTREC\(card,)44 -b(>)k(status\))0 2869 y Fh(6)81 b Fi(T)-8 b(est)25 b(whether)f(the)h -(curren)m(t)f(header)h(con)m(tains)g(an)m(y)g(NULL)g(\(ASCI)s(I)e(0\))j -(c)m(haracters.)40 b(These)24 b(c)m(haracters)j(are)227 -2982 y(illegal)37 b(in)d(the)h(header,)g(but)f(they)g(will)h(go)g -(undetected)g(b)m(y)f(most)h(of)g(the)f(CFITSIO)f(k)m(eyw)m(ord)i -(header)227 3095 y(routines,)29 b(b)s(ecause)f(the)h(n)m(ull)f(is)g(in) -m(terpreted)g(as)h(the)f(normal)g(end-of-string)h(terminator.)41 -b(This)27 b(routine)227 3208 y(returns)h(the)g(p)s(osition)h(of)g(the)g -(\014rst)f(n)m(ull)g(c)m(haracter)i(in)f(the)f(header,)h(or)g(zero)g -(if)g(there)g(are)g(no)f(n)m(ulls.)40 b(F)-8 b(or)227 -3321 y(example)37 b(a)f(returned)f(v)-5 b(alue)37 b(of)f(110)h(w)m -(ould)f(indicate)h(that)g(the)f(\014rst)f(NULL)h(is)g(lo)s(cated)h(in)f -(the)g(30th)227 3434 y(c)m(haracter)28 b(of)f(the)g(second)f(k)m(eyw)m -(ord)h(in)f(the)h(header)f(\(recall)i(that)f(eac)m(h)h(header)e(record) -h(is)f(80)h(c)m(haracters)227 3547 y(long\).)56 b(Note)36 -b(that)g(this)f(is)g(one)g(of)g(the)g(few)g(FITSIO)f(routines)h(in)f -(whic)m(h)h(the)g(returned)f(v)-5 b(alue)36 b(is)f(not)227 -3660 y(necessarily)d(equal)e(to)i(the)e(status)h(v)-5 -b(alue\).)382 3933 y Fe(FTNCHK\(unit,)44 b(>)k(status\))0 -4205 y Fh(7)81 b Fi(P)m(arse)27 b(a)f(header)h(k)m(eyw)m(ord)g(record)f -(and)g(return)f(the)i(name)f(of)h(the)f(k)m(eyw)m(ord)h(and)f(the)h -(length)f(of)h(the)g(name.)227 4318 y(The)34 b(k)m(eyw)m(ord)h(name)f -(normally)h(o)s(ccupies)f(the)h(\014rst)e(8)i(c)m(haracters)g(of)g(the) -f(record,)i(except)f(under)e(the)227 4431 y(HIERAR)m(CH)e(con)m(v)m(en) -m(tion)h(where)e(the)h(name)f(can)h(b)s(e)f(up)f(to)i(70)g(c)m -(haracters)h(in)e(length.)382 4704 y Fe(FTGKNM\(card,)44 -b(>)k(keyname,)d(keylength,)g(staThe)h('\\#')h(character)e(will)i -(match)f(any)h(consecutive)e(string)191 4817 y(of)i(decimal)f(digits)g -(\(0)h(-)h(9\).)f(tus\))0 5090 y Fh(8)81 b Fi(P)m(arse)34 -b(a)h(header)f(k)m(eyw)m(ord)h(record.)52 b(This)33 b(subroutine)g -(parses)h(the)g(input)g(header)g(record)g(to)h(return)e(the)227 -5203 y(v)-5 b(alue)27 b(\(as)g(a)g(c)m(haracter)g(string\))g(and)f -(commen)m(t)h(strings.)39 b(If)26 b(the)g(k)m(eyw)m(ord)h(has)f(no)g(v) --5 b(alue)27 b(\(columns)f(9-10)227 5316 y(not)h(equal)f(to)h('=)f -('\),)i(then)e(the)g(v)-5 b(alue)27 b(string)f(is)g(returned)f(blank)h -(and)f(the)h(commen)m(t)i(string)e(is)g(set)g(equal)227 -5428 y(to)31 b(column)g(9)f(-)h(80)g(of)g(the)f(input)g(string.)382 -5701 y Fe(FTPSVC\(card,)44 b(>)k(value,comment,status\))p -eop end -%%Page: 71 77 -TeXDict begin 71 76 bop 0 299 a Fg(6.12.)73 b(GENERAL)30 -b(UTILITY)g(SUBR)m(OUTINES)1979 b Fi(71)0 555 y Fh(9)81 -b Fi(Construct)41 b(a)h(prop)s(erly)f(formated)h(80-c)m(haracter)i -(header)e(k)m(eyw)m(ord)g(record)f(from)h(the)g(input)e(k)m(eyw)m(ord) -227 668 y(name,)25 b(k)m(eyw)m(ord)f(v)-5 b(alue,)25 -b(and)e(k)m(eyw)m(ord)h(commen)m(t)g(strings.)38 b(Hierarc)m(hical)26 -b(k)m(eyw)m(ord)e(names)f(\(e.g.,)j("ESO)227 781 y(TELE)e(CAM"\))i(are) -f(supp)s(orted.)37 b(The)25 b(v)-5 b(alue)25 b(string)g(ma)m(y)h(con)m -(tain)g(an)f(in)m(teger,)i(\015oating)f(p)s(oin)m(t,)g(logical,)227 -894 y(or)31 b(quoted)f(c)m(haracter)i(string)e(\(e.g.,)j("12",)f -("15.7",)h("T",)e(or)g("'NGC)g(1313'"\).)382 1153 y Fe -(FTMKKY\(keyname,)43 b(value,)k(comment,)e(>)j(card,)e(status\))0 -1413 y Fh(10)g Fi(Construct)35 b(a)g(sequence)g(k)m(eyw)m(ord)g(name)g -(\(R)m(OOT)g(+)f(nnn\).)54 b(This)34 b(subroutine)f(app)s(ends)g(the)j -(sequence)227 1526 y(n)m(um)m(b)s(er)29 b(to)i(the)g(ro)s(ot)g(string)f -(to)h(create)h(a)f(k)m(eyw)m(ord)g(name)f(\(e.g.,)i('NAXIS')f(+)f(2)h -(=)f('NAXIS2'\))382 1785 y Fe(FTKEYN\(keyroot,seq_no,)42 -b(>)47 b(keyword,status\))0 2045 y Fh(11)f Fi(Construct)30 -b(a)g(sequence)g(k)m(eyw)m(ord)h(name)f(\(n)f(+)h(R)m(OOT\).)g(This)f -(subroutine)g(concatenates)j(the)f(sequence)227 2158 -y(n)m(um)m(b)s(er)20 b(to)j(the)e(fron)m(t)h(of)g(the)f(ro)s(ot)h -(string)g(to)g(create)h(a)f(k)m(eyw)m(ord)g(name)g(\(e.g.,)j(1)d(+)f -('CTYP')g(=)g('1CTYP'\))382 2417 y Fe(FTNKEY\(seq_no,keyroot,)42 -b(>)47 b(keyword,status\))0 2677 y Fh(12)f Fi(Determine)35 -b(the)f(datat)m(yp)s(e)g(of)g(a)g(k)m(eyw)m(ord)h(v)-5 -b(alue)34 b(string.)50 b(This)33 b(subroutine)g(parses)g(the)h(k)m(eyw) -m(ord)g(v)-5 b(alue)227 2790 y(string)31 b(\(usually)f(columns)g(11-30) -j(of)d(the)h(header)f(record\))g(to)i(determine)e(its)h(datat)m(yp)s -(e.)382 3049 y Fe(FTDTYP\(value,)44 b(>)j(dtype,status\))0 -3309 y Fh(13)f Fi(Return)c(the)i(class)g(of)f(input)f(header)h(record.) -79 b(The)43 b(record)g(is)g(classi\014ed)g(in)m(to)h(one)g(of)f(the)g -(follo)m(wing)227 3422 y(categories)36 b(\(the)e(class)f(v)-5 -b(alues)34 b(are)f(de\014ned)f(in)h(\014tsio.h\).)49 -b(Note)35 b(that)e(this)g(is)g(one)h(of)f(the)g(few)g(FITSIO)227 -3535 y(routines)e(that)f(do)s(es)h(not)f(return)f(a)i(status)g(v)-5 -b(alue.)334 3794 y Fe(Class)94 b(Value)619 b(Keywords)95 -3907 y(TYP_STRUC_KEY)92 b(10)j(SIMPLE,)46 b(BITPIX,)g(NAXIS,)g(NAXISn,) -g(EXTEND,)g(BLOCKED,)1002 4020 y(GROUPS,)g(PCOUNT,)g(GCOUNT,)g(END)1002 -4133 y(XTENSION,)g(TFIELDS,)f(TTYPEn,)h(TBCOLn,)g(TFORMn,)g(THEAP,)1002 -4246 y(and)h(the)g(first)f(4)i(COMMENT)e(keywords)f(in)i(the)g(primary) -f(array)1002 4359 y(that)h(define)f(the)h(FITS)g(format.)95 -4472 y(TYP_CMPRS_KEY)92 b(20)j(The)47 b(keywords)f(used)g(in)i(the)e -(compressed)f(image)95 b(or)47 b(table)1002 4585 y(format,)f(including) -f(ZIMAGE,)h(ZCMPTYPE,)f(ZNAMEn,)h(ZVALn,)1002 4698 y(ZTILEn,)g -(ZBITPIX,)g(ZNAXISn,)f(ZSCALE,)h(ZZERO,)g(ZBLANK)95 4811 -y(TYP_SCAL_KEY)140 b(30)95 b(BSCALE,)46 b(BZERO,)g(TSCALn,)g(TZEROn)95 -4924 y(TYP_NULL_KEY)140 b(40)95 b(BLANK,)46 b(TNULLn)95 -5036 y(TYP_DIM_KEY)188 b(50)95 b(TDIMn)95 5149 y(TYP_RANG_KEY)140 -b(60)95 b(TLMINn,)46 b(TLMAXn,)g(TDMINn,)g(TDMAXn,)g(DATAMIN,)f -(DATAMAX)95 5262 y(TYP_UNIT_KEY)140 b(70)95 b(BUNIT,)46 -b(TUNITn)95 5375 y(TYP_DISP_KEY)140 b(80)95 b(TDISPn)95 -5488 y(TYP_HDUID_KEY)d(90)j(EXTNAME,)46 b(EXTVER,)g(EXTLEVEL,)f -(HDUNAME,)g(HDUVER,)h(HDULEVEL)95 5601 y(TYP_CKSUM_KEY)f(100)94 -b(CHECKSUM,)46 b(DATASUM)95 5714 y(TYP_WCS_KEY)141 b(110)94 -b(CTYPEn,)46 b(CUNITn,)g(CRVALn,)g(CRPIXn,)g(CROTAn,)f(CDELTn)p -eop end -%%Page: 72 78 -TeXDict begin 72 77 bop 0 299 a Fi(72)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)1002 555 y Fe(CDj_is,)46 b(PVj_ms,)g(LONPOLEs,)f -(LATPOLEs)1002 668 y(TCTYPn,)h(TCTYns,)g(TCUNIn,)g(TCUNns,)g(TCRVLn,)f -(TCRVns,)h(TCRPXn,)1002 781 y(TCRPks,)g(TCDn_k,)g(TCn_ks,)g(TPVn_m,)g -(TPn_ms,)f(TCDLTn,)h(TCROTn)1002 894 y(jCTYPn,)g(jCTYns,)g(jCUNIn,)g -(jCUNns,)g(jCRVLn,)f(jCRVns,)h(iCRPXn,)1002 1007 y(iCRPns,)g(jiCDn,)94 -b(jiCDns,)46 b(jPVn_m,)g(jPn_ms,)f(jCDLTn,)h(jCROTn)1002 -1120 y(\(i,j,m,n)g(are)h(integers,)e(s)i(is)h(any)f(letter\))95 -1233 y(TYP_REFSYS_KEY)d(120)j(EQUINOXs,)f(EPOCH,)g(MJD-OBSs,)f -(RADECSYS,)g(RADESYSs)95 1346 y(TYP_COMM_KEY)140 b(130)47 -b(COMMENT,)f(HISTORY,)f(\(blank)h(keyword\))95 1458 y(TYP_CONT_KEY)140 -b(140)47 b(CONTINUE)95 1571 y(TYP_USER_KEY)140 b(150)47 -b(all)g(other)g(keywords)430 1797 y(class)f(=)h(FTGKCL)f(\(char)h -(*card\))0 2042 y Fh(14)f Fi(P)m(arse)f(the)g('TF)m(ORM')h(binary)e -(table)i(column)e(format)h(string.)84 b(This)44 b(subroutine)g(parses)g -(the)h(input)227 2155 y(TF)m(ORM)27 b(c)m(haracter)g(string)f(and)g -(returns)f(the)h(in)m(teger)h(datat)m(yp)s(e)g(co)s(de,)h(the)e(rep)s -(eat)g(coun)m(t)h(of)f(the)g(\014eld,)227 2268 y(and,)f(in)e(the)h -(case)g(of)g(c)m(haracter)h(string)e(\014elds,)i(the)e(length)h(of)g -(the)g(unit)f(string.)38 b(The)23 b(follo)m(wing)i(datat)m(yp)s(e)227 -2381 y(co)s(des)e(are)h(returned)e(\(the)h(negativ)m(e)i(of)f(the)f(v) --5 b(alue)23 b(is)g(returned)f(if)h(the)g(column)g(con)m(tains)h(v)-5 -b(ariable-length)227 2494 y(arra)m(ys\):)764 2739 y Fe(Datatype)761 -b(DATACODE)46 b(value)764 2852 y(bit,)g(X)907 b(1)764 -2965 y(byte,)46 b(B)811 b(11)764 3078 y(logical,)45 b(L)668 -b(14)764 3191 y(ASCII)46 b(character,)f(A)286 b(16)764 -3304 y(short)46 b(integer,)g(I)381 b(21)764 3417 y(integer,)45 -b(J)668 b(41)764 3530 y(real,)46 b(E)811 b(42)764 3643 -y(double)46 b(precision,)f(D)238 b(82)764 3756 y(complex)809 -b(83)764 3868 y(double)46 b(complex)475 b(163)382 4094 -y(FTBNFM\(tform,)44 b(>)j(datacode,repeat,width,stat)o(us\))0 -4340 y Fh(15)f Fi(P)m(arse)38 b(the)f('TF)m(ORM')h(k)m(eyw)m(ord)g(v)-5 -b(alue)37 b(that)h(de\014nes)e(the)h(column)g(format)h(in)e(an)h(ASCI)s -(I)f(table.)62 b(This)227 4452 y(routine)31 b(parses)g(the)g(input)g -(TF)m(ORM)g(c)m(haracter)i(string)e(and)f(returns)g(the)i(datat)m(yp)s -(e)g(co)s(de,)f(the)h(width)227 4565 y(of)40 b(the)h(column,)h(and)e -(\(if)g(it)g(is)h(a)f(\015oating)h(p)s(oin)m(t)f(column\))g(the)g(n)m -(um)m(b)s(er)f(of)h(decimal)h(places)g(to)g(the)227 4678 -y(righ)m(t)28 b(of)g(the)f(decimal)h(p)s(oin)m(t.)40 -b(The)27 b(returned)f(datat)m(yp)s(e)i(co)s(des)f(are)h(the)g(same)f -(as)h(for)f(the)g(binary)g(table,)227 4791 y(listed)41 -b(ab)s(o)m(v)m(e,)j(with)c(the)g(follo)m(wing)i(additional)f(rules:)60 -b(in)m(teger)42 b(columns)e(that)g(are)h(b)s(et)m(w)m(een)g(1)g(and)227 -4904 y(4)36 b(c)m(haracters)i(wide)d(are)i(de\014ned)d(to)j(b)s(e)e -(short)h(in)m(tegers)h(\(co)s(de)f(=)g(21\).)58 b(Wider)36 -b(in)m(teger)h(columns)f(are)227 5017 y(de\014ned)j(to)i(b)s(e)e -(regular)h(in)m(tegers)i(\(co)s(de)e(=)g(41\).)71 b(Similarly)-8 -b(,)43 b(Fixed)d(decimal)h(p)s(oin)m(t)f(columns)g(\(with)227 -5130 y(TF)m(ORM)30 b(=)g('Fw.d'\))g(are)g(de\014ned)f(to)h(b)s(e)g -(single)g(precision)g(reals)g(\(co)s(de)h(=)e(42\))i(if)f(w)f(is)h(b)s -(et)m(w)m(een)g(1)h(and)227 5243 y(7)i(c)m(haracters)h(wide,)f -(inclusiv)m(e.)47 b(Wider)32 b('F')h(columns)f(will)h(return)e(a)i -(double)f(precision)g(data)h(co)s(de)g(\(=)227 5356 y(82\).)54 -b('Ew.d')34 b(format)g(columns)g(will)h(ha)m(v)m(e)g(dataco)s(de)g(=)f -(42,)j(and)c('Dw.d')i(format)f(columns)g(will)h(ha)m(v)m(e)227 -5469 y(dataco)s(de)d(=)e(82.)382 5714 y Fe(FTASFM\(tform,)44 -b(>)j(datacode,width,decimals,st)o(atus)o(\))p eop end -%%Page: 73 79 -TeXDict begin 73 78 bop 0 299 a Fg(6.12.)73 b(GENERAL)30 -b(UTILITY)g(SUBR)m(OUTINES)1979 b Fi(73)0 555 y Fh(16)46 -b Fi(Calculate)32 b(the)f(starting)g(column)g(p)s(ositions)f(and)g -(total)i(ASCI)s(I)d(table)j(width)d(based)i(on)f(the)h(input)e(arra)m -(y)227 668 y(of)e(ASCI)s(I)e(table)i(TF)m(ORM)g(v)-5 -b(alues.)40 b(The)26 b(SP)-8 b(A)m(CE)27 b(input)e(parameter)i -(de\014nes)f(ho)m(w)h(man)m(y)f(blank)h(spaces)227 781 -y(to)40 b(lea)m(v)m(e)i(b)s(et)m(w)m(een)e(eac)m(h)g(column)g(\(it)g -(is)f(recommended)g(to)h(ha)m(v)m(e)h(one)e(space)h(b)s(et)m(w)m(een)g -(columns)f(for)227 894 y(b)s(etter)31 b(h)m(uman)e(readabilit)m(y\).) -382 1153 y Fe(FTGABC\(tfields,tform,spa)o(ce,)41 b(>)48 -b(rowlen,tbcol,status\))0 1413 y Fh(17)e Fi(P)m(arse)36 -b(a)f(template)h(string)f(and)g(return)f(a)h(formatted)h(80-c)m -(haracter)h(string)e(suitable)h(for)f(app)s(ending)e(to)227 -1526 y(\(or)40 b(deleting)h(from\))e(a)h(FITS)f(header)h(\014le.)68 -b(This)39 b(subroutine)f(is)i(useful)f(for)g(parsing)g(lines)h(from)f -(an)227 1639 y(ASCI)s(I)34 b(template)j(\014le)f(and)e(reformatting)j -(them)e(in)m(to)i(legal)g(FITS)d(header)i(records.)55 -b(The)35 b(formatted)227 1752 y(string)c(ma)m(y)g(then)f(b)s(e)g -(passed)g(to)i(the)e(FTPREC,)h(FTMCRD,)g(or)f(FTDKEY)h(subroutines)e -(to)j(app)s(end)227 1865 y(or)f(mo)s(dify)e(a)i(FITS)f(header)g -(record.)382 2124 y Fe(FTGTHD\(template,)43 b(>)48 b -(card,hdtype,status\))0 2384 y Fi(The)23 b(input)h(TEMPLA)-8 -b(TE)23 b(c)m(haracter)j(string)e(generally)h(should)e(con)m(tain)i(3)g -(tok)m(ens:)38 b(\(1\))25 b(the)f(KEYNAME,)h(\(2\))0 -2497 y(the)h(V)-10 b(ALUE,)26 b(and)f(\(3\))i(the)f(COMMENT)g(string.) -39 b(The)25 b(TEMPLA)-8 b(TE)26 b(string)g(m)m(ust)f(adhere)h(to)g(the) -g(follo)m(wing)0 2610 y(format:)0 2869 y Fh(-)80 b Fi(The)24 -b(KEYNAME)g(tok)m(en)h(m)m(ust)e(b)s(egin)h(in)f(columns)h(1-8)h(and)e -(b)s(e)h(a)g(maxim)m(um)g(of)g(8)g(c)m(haracters)h(long.)39 -b(If)24 b(the)227 2982 y(\014rst)32 b(8)h(c)m(haracters)h(of)e(the)h -(template)h(line)e(are)h(blank)f(then)g(the)h(remainder)f(of)g(the)h -(line)g(is)f(considered)227 3095 y(to)42 b(b)s(e)e(a)h(FITS)f(commen)m -(t)h(\(with)g(a)g(blank)f(k)m(eyw)m(ord)h(name\).)72 -b(A)41 b(legal)i(FITS)d(k)m(eyw)m(ord)h(name)f(ma)m(y)227 -3208 y(only)35 b(con)m(tain)i(the)e(c)m(haracters)h(A-Z,)f(0-9,)j(and)c -('-')i(\(min)m(us)f(sign\))g(and)f(underscore.)54 b(This)34 -b(subroutine)227 3321 y(will)42 b(automatically)i(con)m(v)m(ert)f(an)m -(y)f(lo)m(w)m(ercase)i(c)m(haracters)e(to)h(upp)s(ercase)d(in)h(the)h -(output)f(string.)73 b(If)227 3434 y(KEYNAME)33 b(=)f('COMMENT')h(or)g -('HISTOR)-8 b(Y')32 b(then)h(the)f(remainder)g(of)h(the)g(line)g(is)g -(considered)f(to)227 3547 y(b)s(e)e(a)h(FITS)e(COMMENT)h(or)h(HISTOR)-8 -b(Y)30 b(record,)g(resp)s(ectiv)m(ely)-8 b(.)0 3806 y -Fh(-)80 b Fi(The)26 b(V)-10 b(ALUE)26 b(tok)m(en)h(m)m(ust)e(b)s(e)h -(separated)g(from)f(the)i(KEYNAME)f(tok)m(en)h(b)m(y)f(one)g(or)g(more) -g(spaces)g(and/or)227 3919 y(an)i('=')g(c)m(haracter.)41 -b(The)27 b(datat)m(yp)s(e)i(of)f(the)g(V)-10 b(ALUE)27 -b(tok)m(en)i(\(n)m(umeric,)g(logical,)i(or)d(c)m(haracter)h(string\))f -(is)227 4032 y(automatically)35 b(determined)c(and)h(the)g(output)f -(CARD)h(string)g(is)g(formatted)g(accordingly)-8 b(.)47 -b(The)31 b(v)-5 b(alue)227 4145 y(tok)m(en)34 b(ma)m(y)f(b)s(e)f -(forced)g(to)i(b)s(e)e(in)m(terpreted)g(as)h(a)g(string)g(\(e.g.)48 -b(if)33 b(it)g(is)f(a)h(string)g(of)f(n)m(umeric)h(digits\))g(b)m(y)227 -4258 y(enclosing)g(it)f(in)f(single)h(quotes.)45 b(If)31 -b(the)h(v)-5 b(alue)32 b(tok)m(en)g(is)g(a)g(c)m(haracter)h(string)e -(that)i(con)m(tains)f(1)g(or)g(more)227 4371 y(em)m(b)s(edded)39 -b(blank)g(space)h(c)m(haracters)h(or)e(slash)h(\('/'\))h(c)m(haracters) -g(then)e(the)g(en)m(tire)i(c)m(haracter)g(string)227 -4484 y(m)m(ust)31 b(b)s(e)e(enclosed)i(in)f(single)h(quotes.)0 -4743 y Fh(-)80 b Fi(The)28 b(COMMENT)g(tok)m(en)h(is)f(optional,)i(but) -e(if)g(presen)m(t)g(m)m(ust)g(b)s(e)g(separated)g(from)g(the)h(V)-10 -b(ALUE)28 b(tok)m(en)h(b)m(y)227 4856 y(a)i(blank)f(space)h(or)f(a)h -('/')g(c)m(haracter.)0 5116 y Fh(-)80 b Fi(One)32 b(exception)i(to)f -(the)g(ab)s(o)m(v)m(e)h(rules)e(is)g(that)h(if)g(the)f(\014rst)g -(non-blank)g(c)m(haracter)i(in)e(the)h(template)h(string)227 -5229 y(is)h(a)g(min)m(us)f(sign)h(\('-'\))h(follo)m(w)m(ed)g(b)m(y)f(a) -g(single)g(tok)m(en,)i(or)e(a)g(single)g(tok)m(en)h(follo)m(w)m(ed)g(b) -m(y)f(an)f(equal)i(sign,)227 5341 y(then)29 b(it)g(is)g(in)m(terpreted) -f(as)h(the)g(name)g(of)g(a)g(k)m(eyw)m(ord)g(whic)m(h)f(is)h(to)g(b)s -(e)f(deleted)i(from)e(the)h(FITS)f(header.)0 5601 y Fh(-)80 -b Fi(The)40 b(second)g(exception)h(is)f(that)h(if)f(the)g(template)h -(string)f(starts)g(with)g(a)h(min)m(us)e(sign)h(and)f(is)h(follo)m(w)m -(ed)227 5714 y(b)m(y)33 b(2)g(tok)m(ens)g(then)g(the)f(second)h(tok)m -(en)h(is)e(in)m(terpreted)h(as)g(the)g(new)f(name)g(for)h(the)g(k)m -(eyw)m(ord)g(sp)s(eci\014ed)p eop end -%%Page: 74 80 -TeXDict begin 74 79 bop 0 299 a Fi(74)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)227 555 y Fi(b)m(y)k(\014rst)e(tok)m(en.)52 -b(In)33 b(this)g(case)i(the)e(old)h(k)m(eyw)m(ord)g(name)g(\(\014rst)f -(tok)m(en\))i(is)e(returned)g(in)g(c)m(haracters)i(1-8)227 -668 y(of)e(the)g(returned)e(CARD)i(string,)g(and)f(the)h(new)f(k)m(eyw) -m(ord)h(name)g(\(the)g(second)f(tok)m(en\))i(is)f(returned)e(in)227 -781 y(c)m(haracters)c(41-48)h(of)e(the)f(returned)g(CARD)g(string.)40 -b(These)25 b(old)h(and)f(new)g(names)g(ma)m(y)h(then)f(b)s(e)g(passed) -227 894 y(to)31 b(the)g(FTMNAM)g(subroutine)f(whic)m(h)g(will)g(c)m -(hange)i(the)e(k)m(eyw)m(ord)h(name.)0 1158 y(The)f(HDTYPE)g(output)g -(parameter)h(indicates)g(ho)m(w)g(the)f(returned)g(CARD)g(string)g -(should)g(b)s(e)g(in)m(terpreted:)382 1422 y Fe(hdtype)857 -b(interpretation)382 1535 y(------)523 b(-------------------------)o -(----)o(---)o(----)o(----)o(---)o(----)o(--)525 1648 -y(-2)572 b(Modify)46 b(the)h(name)g(of)g(the)g(keyword)f(given)g(in)h -(CARD\(1:8\))1193 1761 y(to)g(the)g(new)g(name)g(given)f(in)h -(CARD\(41:48\))525 1986 y(-1)572 b(CARD\(1:8\))45 b(contains)h(the)h -(name)g(of)g(a)g(keyword)f(to)h(be)g(deleted)1193 2099 -y(from)g(the)g(FITS)f(header.)573 2325 y(0)572 b(append)46 -b(the)h(CARD)g(string)f(to)h(the)g(FITS)g(header)f(if)h(the)1193 -2438 y(keyword)f(does)h(not)g(already)e(exist,)h(otherwise)g(update) -1193 2551 y(the)h(value/comment)d(if)j(the)g(keyword)f(is)h(already)f -(present)1193 2664 y(in)h(the)g(header.)573 2890 y(1)572 -b(simply)46 b(append)g(this)h(keyword)f(to)h(the)g(FITS)g(header)f -(\(CARD)1193 3003 y(is)h(either)f(a)i(HISTORY)e(or)h(COMMENT)f -(keyword\).)573 3228 y(2)572 b(This)47 b(is)g(a)g(FITS)g(END)g(record;) -f(it)h(should)f(not)h(be)g(written)1193 3341 y(to)g(the)g(FITS)g -(header)f(because)g(FITSIO)g(automatically)1193 3454 -y(appends)g(the)h(END)g(record)f(when)h(the)f(header)h(is)g(closed.)0 -3718 y Fi(EXAMPLES:)30 b(The)g(follo)m(wing)i(lines)e(illustrate)i(v)-5 -b(alid)31 b(input)e(template)j(strings:)286 3982 y Fe(INTVAL)46 -b(7)i(This)f(is)g(an)g(integer)f(keyword)286 4095 y(RVAL)524 -b(34.6)142 b(/)239 b(This)46 b(is)i(a)f(floating)f(point)g(keyword)286 -4208 y(EVAL=-12.45E-03)92 b(This)46 b(is)i(a)f(floating)f(point)g -(keyword)g(in)h(exponential)e(notation)286 4321 y(lval)i(F)g(This)g(is) -g(a)h(boolean)e(keyword)859 4434 y(This)h(is)g(a)g(comment)f(keyword)g -(with)h(a)g(blank)f(keyword)g(name)286 4547 y(SVAL1)h(=)g('Hello)f -(world')142 b(/)95 b(this)47 b(is)g(a)g(string)f(keyword)286 -4660 y(SVAL2)94 b('123.5')g(this)47 b(is)g(also)f(a)i(string)e(keyword) -286 4772 y(sval3)94 b(123+)h(/)g(this)47 b(is)g(also)f(a)i(string)e -(keyword)g(with)g(the)h(value)g('123+)189 b(')286 4885 -y(#)48 b(the)f(following)e(template)h(line)g(deletes)g(the)h(DATE)g -(keyword)286 4998 y(-)h(DATE)286 5111 y(#)g(the)f(following)e(template) -h(line)g(modifies)g(the)h(NAME)f(keyword)g(to)h(OBJECT)286 -5224 y(-)h(NAME)e(OBJECT)0 5488 y Fh(18)g Fi(P)m(arse)35 -b(the)g(input)f(string)h(con)m(taining)h(a)f(list)h(of)f(ro)m(ws)f(or)h -(ro)m(w)g(ranges,)h(and)e(return)g(in)m(teger)i(arra)m(ys)f(con-)227 -5601 y(taining)27 b(the)f(\014rst)f(and)g(last)i(ro)m(w)f(in)f(eac)m(h) -i(range.)40 b(F)-8 b(or)26 b(example,)i(if)d(ro)m(wlist)i(=)e("3-5,)k -(6,)e(8-9")h(then)d(it)i(will)227 5714 y(return)34 b(n)m(umranges)h(=)g -(3,)h(rangemin)f(=)g(3,)i(6,)g(8)e(and)g(rangemax)g(=)g(5,)i(6,)g(9.)55 -b(A)m(t)36 b(most,)h('maxranges')p eop end -%%Page: 75 81 -TeXDict begin 75 80 bop 0 299 a Fg(6.12.)73 b(GENERAL)30 -b(UTILITY)g(SUBR)m(OUTINES)1979 b Fi(75)227 555 y(n)m(um)m(b)s(er)31 -b(of)h(ranges)f(will)h(b)s(e)g(returned.)43 b('maxro)m(ws')32 -b(is)g(the)g(maxim)m(um)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(in)f(the)h -(table;)227 668 y(an)m(y)e(ro)m(ws)f(or)g(ranges)g(larger)h(than)f -(this)g(will)g(b)s(e)g(ignored.)40 b(The)29 b(ro)m(ws)g(m)m(ust)g(b)s -(e)f(sp)s(eci\014ed)h(in)f(increasing)227 781 y(order,)33 -b(and)f(the)g(ranges)h(m)m(ust)f(not)g(o)m(v)m(erlap.)48 -b(A)33 b(min)m(us)e(sign)i(ma)m(y)g(b)s(e)e(use)h(to)h(sp)s(ecify)f -(all)h(the)g(ro)m(ws)f(to)227 894 y(the)h(upp)s(er)d(or)j(lo)m(w)m(er)h -(b)s(ound,)d(so)i("50-")h(means)e(all)i(the)f(ro)m(ws)f(from)g(50)h(to) -h(the)e(end)g(of)h(the)f(table,)j(and)227 1007 y("-")d(means)e(all)h -(the)g(ro)m(ws)f(in)g(the)h(table,)g(from)f(1)h(-)g(maxro)m(ws.)191 -1267 y Fe(FTRWRG\(rowlist,)44 b(maxrows,)h(maxranges,)g(>)525 -1380 y(numranges,)g(rangemin,)g(rangemax,)h(status\))p -eop end -%%Page: 76 82 -TeXDict begin 76 81 bop 0 299 a Fi(76)1319 b Fg(CHAPTER)29 -b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 -b(SUBR)m(OUTINES)p eop end -%%Page: 77 83 -TeXDict begin 77 82 bop 0 1225 a Ff(Chapter)65 b(7)0 -1687 y Fl(The)77 b(CFITSIO)f(Iterator)i(F)-19 b(unction)0 -2180 y Fi(The)41 b(\014ts)p 325 2180 28 4 v 33 w(iterate)p -614 2180 V 34 w(data)i(function)e(in)h(CFITSIO)e(pro)m(vides)i(a)g -(unique)e(metho)s(d)i(of)g(executing)h(an)e(arbitrary)0 -2293 y(user-supplied)35 b(`w)m(ork')i(function)f(that)h(op)s(erates)g -(on)g(ro)m(ws)f(of)h(data)g(in)f(FITS)g(tables)h(or)f(on)h(pixels)f(in) -h(FITS)0 2406 y(images.)i(Rather)24 b(than)e(explicitly)j(reading)e -(and)g(writing)g(the)g(FITS)g(images)h(or)f(columns)g(of)g(data,)i(one) -f(instead)0 2518 y(calls)36 b(the)g(CFITSIO)d(iterator)k(routine,)g -(passing)e(to)h(it)g(the)f(name)g(of)h(the)f(user's)g(w)m(ork)g -(function)g(that)h(is)f(to)0 2631 y(b)s(e)30 b(executed)h(along)g(with) -f(a)h(list)g(of)f(all)h(the)f(table)i(columns)e(or)g(image)h(arra)m(ys) -g(that)g(are)f(to)h(b)s(e)f(passed)g(to)h(the)0 2744 -y(w)m(ork)37 b(function.)61 b(The)37 b(CFITSIO)e(iterator)k(function)e -(then)g(do)s(es)g(all)h(the)f(w)m(ork)g(of)h(allo)s(cating)h(memory)e -(for)0 2857 y(the)28 b(arra)m(ys,)h(reading)f(the)g(input)e(data)j -(from)e(the)h(FITS)f(\014le,)h(passing)g(them)g(to)g(the)g(w)m(ork)g -(function,)g(and)f(then)0 2970 y(writing)36 b(an)m(y)h(output)f(data)h -(bac)m(k)h(to)f(the)f(FITS)g(\014le)g(after)h(the)g(w)m(ork)g(function) -f(exits.)59 b(Because)38 b(it)f(is)g(often)0 3083 y(more)g(e\016cien)m -(t)i(to)f(pro)s(cess)f(only)g(a)h(subset)f(of)g(the)g(total)i(table)g -(ro)m(ws)e(at)h(one)f(time,)j(the)e(iterator)g(function)0 -3196 y(can)31 b(determine)f(the)h(optim)m(um)f(amoun)m(t)h(of)f(data)h -(to)g(pass)f(in)g(eac)m(h)i(iteration)f(and)f(rep)s(eatedly)h(call)g -(the)g(w)m(ork)0 3309 y(function)f(un)m(til)h(the)f(en)m(tire)i(table)f -(b)s(een)e(pro)s(cessed.)0 3469 y(F)-8 b(or)37 b(man)m(y)f -(applications)h(this)e(single)i(CFITSIO)d(iterator)k(function)d(can)h -(e\013ectiv)m(ely)j(replace)e(all)g(the)f(other)0 3582 -y(CFITSIO)g(routines)i(for)f(reading)h(or)f(writing)h(data)g(in)f(FITS) -g(images)i(or)e(tables.)64 b(Using)37 b(the)h(iterator)h(has)0 -3695 y(sev)m(eral)32 b(imp)s(ortan)m(t)e(adv)-5 b(an)m(tages)32 -b(o)m(v)m(er)g(the)f(traditional)g(metho)s(d)f(of)h(reading)f(and)g -(writing)g(FITS)g(data)h(\014les:)136 3961 y Fc(\017)46 -b Fi(It)33 b(cleanly)h(separates)g(the)f(data)h(I/O)f(from)f(the)h -(routine)g(that)h(op)s(erates)f(on)g(the)g(data.)49 b(This)32 -b(leads)h(to)227 4074 y(a)e(more)g(mo)s(dular)e(and)h(`ob)5 -b(ject)31 b(orien)m(ted')h(programming)e(st)m(yle.)136 -4268 y Fc(\017)46 b Fi(It)27 b(simpli\014es)f(the)h(application)h -(program)f(b)m(y)f(eliminating)i(the)f(need)g(to)g(allo)s(cate)i -(memory)e(for)f(the)h(data)227 4381 y(arra)m(ys)e(and)f(eliminates)i -(most)e(of)h(the)f(calls)i(to)f(the)g(CFITSIO)d(routines)j(that)g -(explicitly)h(read)e(and)g(write)227 4494 y(the)31 b(data.)136 -4689 y Fc(\017)46 b Fi(It)32 b(ensures)e(that)i(the)g(data)g(are)g(pro) -s(cessed)f(as)h(e\016cien)m(tly)h(as)e(p)s(ossible.)44 -b(This)31 b(is)g(esp)s(ecially)i(imp)s(ortan)m(t)227 -4801 y(when)44 b(pro)s(cessing)g(tabular)h(data)h(since)f(the)g -(iterator)h(function)e(will)h(calculate)i(the)e(most)g(e\016cien)m(t) -227 4914 y(n)m(um)m(b)s(er)36 b(of)i(ro)m(ws)g(in)f(the)h(table)g(to)g -(b)s(e)f(passed)g(at)i(one)e(time)i(to)f(the)g(user's)e(w)m(ork)i -(function)f(on)h(eac)m(h)227 5027 y(iteration.)136 5222 -y Fc(\017)46 b Fi(Mak)m(es)39 b(it)e(p)s(ossible)g(for)g(larger)h(pro)5 -b(jects)37 b(to)h(dev)m(elop)g(a)g(library)e(of)i(w)m(ork)f(functions)f -(that)i(all)g(ha)m(v)m(e)h(a)227 5335 y(uniform)29 b(calling)j -(sequence)f(and)f(are)h(all)g(indep)s(enden)m(t)e(of)i(the)f(details)i -(of)e(the)h(FITS)e(\014le)i(format.)0 5601 y(There)f(are)h(basically)h -(2)g(steps)e(in)h(using)f(the)h(CFITSIO)e(iterator)j(function.)42 -b(The)30 b(\014rst)g(step)h(is)g(to)g(design)g(the)0 -5714 y(w)m(ork)26 b(function)f(itself)h(whic)m(h)f(m)m(ust)h(ha)m(v)m -(e)g(a)g(prescrib)s(ed)e(set)i(of)g(input)f(parameters.)39 -b(One)25 b(of)h(these)g(parameters)1905 5942 y(77)p eop -end -%%Page: 78 84 -TeXDict begin 78 83 bop 0 299 a Fi(78)1455 b Fg(CHAPTER)30 -b(7.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)0 -555 y Fi(is)f(a)g(structure)g(con)m(taining)i(p)s(oin)m(ters)d(to)i -(the)f(arra)m(ys)h(of)f(data;)h(the)f(w)m(ork)h(function)e(can)i(p)s -(erform)d(an)m(y)i(desired)0 668 y(op)s(erations)k(on)h(these)f(arra)m -(ys)h(and)e(do)s(es)h(not)g(need)g(to)h(w)m(orry)f(ab)s(out)g(ho)m(w)g -(the)h(input)e(data)i(w)m(ere)f(read)g(from)0 781 y(the)e(\014le)f(or)g -(ho)m(w)h(the)f(output)g(data)h(get)h(written)e(bac)m(k)h(to)h(the)e -(\014le.)0 941 y(The)24 b(second)h(step)g(is)f(to)i(design)e(the)h -(driv)m(er)g(routine)f(that)i(op)s(ens)e(all)h(the)g(necessary)g(FITS)f -(\014les)h(and)f(initializes)0 1054 y(the)41 b(input)g(parameters)g(to) -h(the)g(iterator)g(function.)73 b(The)41 b(driv)m(er)g(program)g(calls) -h(the)g(CFITSIO)e(iterator)0 1167 y(function)30 b(whic)m(h)g(then)g -(reads)g(the)h(data)g(and)f(passes)g(it)h(to)g(the)g(user's)e(w)m(ork)i -(function.)0 1327 y(F)-8 b(urther)41 b(details)i(on)f(using)f(the)h -(iterator)h(function)f(can)g(b)s(e)f(found)f(in)i(the)g(companion)g -(CFITSIO)e(User's)0 1440 y(Guide,)31 b(and)e(in)h(the)h(iter)p -874 1440 28 4 v 33 w(a.f,)g(iter)p 1197 1440 V 34 w(b.f)f(and)f(iter)p -1677 1440 V 34 w(c.f)h(example)h(programs.)p eop end -%%Page: 79 85 -TeXDict begin 79 84 bop 0 1225 a Ff(Chapter)65 b(8)0 -1687 y Fl(Extended)77 b(File)g(Name)g(Syn)-6 b(tax)0 -2216 y Fd(8.1)135 b(Ov)l(erview)0 2466 y Fi(CFITSIO)30 -b(supp)s(orts)f(an)j(extended)f(syn)m(tax)h(when)f(sp)s(ecifying)g(the) -h(name)f(of)h(the)g(data)g(\014le)f(to)h(b)s(e)f(op)s(ened)g(or)0 -2579 y(created)g(that)g(includes)f(the)h(follo)m(wing)h(features:)136 -2813 y Fc(\017)46 b Fi(CFITSIO)40 b(can)i(read)f(IRAF)h(format)g -(images)g(whic)m(h)f(ha)m(v)m(e)i(header)e(\014le)h(names)f(that)h(end) -f(with)g(the)227 2926 y('.imh')d(extension,)i(as)e(w)m(ell)g(as)g -(reading)f(and)g(writing)g(FITS)g(\014les,)i(This)e(feature)h(is)f -(implemen)m(ted)h(in)227 3039 y(CFITSIO)29 b(b)m(y)i(\014rst)e(con)m(v) -m(erting)k(the)d(IRAF)h(image)h(in)m(to)f(a)g(temp)s(orary)f(FITS)g -(format)h(\014le)f(in)g(memory)-8 b(,)227 3152 y(then)35 -b(op)s(ening)f(the)h(FITS)f(\014le.)54 b(An)m(y)35 b(of)g(the)g(usual)f -(CFITSIO)g(routines)g(then)h(ma)m(y)g(b)s(e)f(used)g(to)i(read)227 -3265 y(the)31 b(image)g(header)f(or)h(data.)41 b(Similarly)-8 -b(,)31 b(ra)m(w)f(binary)g(data)h(arra)m(ys)f(can)h(b)s(e)f(read)g(b)m -(y)g(con)m(v)m(erting)i(them)227 3378 y(on)f(the)f(\015y)g(in)m(to)h -(virtual)g(FITS)f(images.)136 3557 y Fc(\017)46 b Fi(FITS)37 -b(\014les)g(on)g(the)g(In)m(ternet)h(can)f(b)s(e)g(read)g(\(and)g -(sometimes)h(written\))f(using)g(the)g(FTP)-8 b(,)38 -b(HTTP)-8 b(,)37 b(or)227 3670 y(R)m(OOT)30 b(proto)s(cols.)136 -3849 y Fc(\017)46 b Fi(FITS)30 b(\014les)g(can)h(b)s(e)f(pip)s(ed)f(b)s -(et)m(w)m(een)i(tasks)f(on)h(the)f(stdin)g(and)g(stdout)g(streams.)136 -4028 y Fc(\017)46 b Fi(FITS)20 b(\014les)h(can)g(b)s(e)f(read)g(and)g -(written)h(in)f(shared)g(memory)-8 b(.)38 b(This)20 b(can)h(p)s(oten)m -(tially)h(ac)m(hiev)m(e)h(m)m(uc)m(h)e(b)s(etter)227 -4141 y(data)26 b(I/O)e(p)s(erformance)g(compared)h(to)h(reading)f(and)f -(writing)g(the)h(same)h(FITS)e(\014les)g(on)h(magnetic)h(disk.)136 -4320 y Fc(\017)46 b Fi(Compressed)30 b(FITS)f(\014les)i(in)f(gzip)h(or) -f(Unix)g(COMPRESS)f(format)h(can)h(b)s(e)f(directly)h(read.)136 -4499 y Fc(\017)46 b Fi(Output)28 b(FITS)h(\014les)g(can)g(b)s(e)g -(written)g(directly)h(in)e(compressed)h(gzip)h(format,)g(th)m(us)e(sa)m -(ving)i(disk)f(space.)136 4678 y Fc(\017)46 b Fi(FITS)26 -b(table)h(columns)f(can)h(b)s(e)f(created,)i(mo)s(di\014ed,)f(or)f -(deleted)h('on-the-\015y')g(as)g(the)g(table)g(is)f(op)s(ened)g(b)m(y) -227 4791 y(CFITSIO.)32 b(This)h(creates)i(a)e(virtual)h(FITS)f(\014le)g -(con)m(taining)i(the)f(mo)s(di\014cations)f(that)h(is)g(then)f(op)s -(ened)227 4904 y(b)m(y)e(the)f(application)i(program.)136 -5083 y Fc(\017)46 b Fi(T)-8 b(able)29 b(ro)m(ws)e(ma)m(y)i(b)s(e)e -(selected,)j(or)e(\014ltered)g(out,)g(on)g(the)g(\015y)f(when)g(the)h -(table)h(is)f(op)s(ened)f(b)m(y)g(CFITSIO,)227 5196 y(based)f(on)h(an)f -(arbitrary)h(user-sp)s(eci\014ed)e(expression.)39 b(Only)26 -b(ro)m(ws)h(for)f(whic)m(h)g(the)h(expression)f(ev)-5 -b(aluates)227 5309 y(to)31 b('TR)m(UE')g(are)g(retained)g(in)f(the)g -(cop)m(y)i(of)e(the)h(table)g(that)g(is)f(op)s(ened)g(b)m(y)g(the)h -(application)g(program.)136 5488 y Fc(\017)46 b Fi(Histogram)28 -b(images)g(ma)m(y)f(b)s(e)f(created)h(on)f(the)h(\015y)f(b)m(y)g -(binning)g(the)g(v)-5 b(alues)27 b(in)f(table)i(columns,)f(resulting) -227 5601 y(in)36 b(a)g(virtual)h(N-dimensional)f(FITS)g(image.)59 -b(The)35 b(application)i(program)f(then)g(only)g(sees)g(the)h(FITS)227 -5714 y(image)32 b(\(in)e(the)h(primary)e(arra)m(y\))j(instead)e(of)h -(the)f(original)i(FITS)d(table.)1905 5942 y(79)p eop -end -%%Page: 80 86 -TeXDict begin 80 85 bop 0 299 a Fi(80)1618 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fi(The)43 b(latter)i(3)f(features)g(in)f(particular)h(add)f(v)m -(ery)h(p)s(o)m(w)m(erful)f(data)h(pro)s(cessing)f(capabilities)j -(directly)e(in)m(to)0 668 y(CFITSIO,)29 b(and)g(hence)h(in)m(to)h(ev)m -(ery)f(task)h(that)f(uses)g(CFITSIO)e(to)j(read)f(or)g(write)g(FITS)f -(\014les.)40 b(F)-8 b(or)31 b(example,)0 781 y(these)d(features)f -(transform)f(a)i(v)m(ery)f(simple)g(program)g(that)h(just)f(copies)h -(an)f(input)f(FITS)g(\014le)h(to)h(a)g(new)e(output)0 -894 y(\014le)36 b(\(lik)m(e)h(the)f(`\014tscop)m(y')h(program)f(that)g -(is)g(distributed)f(with)g(CFITSIO\))g(in)m(to)i(a)f(m)m(ultipurp)s -(ose)f(FITS)g(\014le)0 1007 y(pro)s(cessing)24 b(to)s(ol.)40 -b(By)25 b(app)s(ending)f(fairly)g(simple)h(quali\014ers)g(on)m(to)g -(the)g(name)g(of)g(the)g(input)f(FITS)g(\014le,)i(the)f(user)0 -1120 y(can)37 b(p)s(erform)f(quite)i(complex)g(table)g(editing)g(op)s -(erations)f(\(e.g.,)k(create)e(new)d(columns,)j(or)e(\014lter)h(out)f -(ro)m(ws)0 1233 y(in)g(a)g(table\))h(or)f(create)h(FITS)f(images)h(b)m -(y)f(binning)e(or)i(histogramming)h(the)f(v)-5 b(alues)37 -b(in)g(table)h(columns.)60 b(In)0 1346 y(addition,)33 -b(these)g(functions)e(ha)m(v)m(e)j(b)s(een)d(co)s(ded)h(using)f(new)h -(state-of-the)i(art)f(algorithms)g(that)g(are,)g(in)f(some)0 -1458 y(cases,)g(10)f(-)f(100)i(times)f(faster)g(than)f(previous)g -(widely)g(used)g(implemen)m(tations.)0 1619 y(Before)k(describing)f -(the)h(complete)h(syn)m(tax)f(for)f(the)h(extended)f(FITS)g(\014le)g -(names)g(in)g(the)h(next)g(section,)h(here)0 1732 y(are)c(a)g(few)f -(examples)h(of)f(FITS)g(\014le)g(names)h(that)f(giv)m(e)i(a)f(quic)m(k) -g(o)m(v)m(erview)h(of)f(the)f(allo)m(w)m(ed)i(syn)m(tax:)136 -1960 y Fc(\017)46 b Fe('myfile.fits')p Fi(:)37 b(the)31 -b(simplest)f(case)i(of)e(a)h(FITS)f(\014le)g(on)h(disk)e(in)i(the)f -(curren)m(t)g(directory)-8 b(.)136 2137 y Fc(\017)46 -b Fe('myfile.imh')p Fi(:)37 b(op)s(ens)28 b(an)h(IRAF)g(format)g(image) -i(\014le)e(and)f(con)m(v)m(erts)i(it)g(on)f(the)g(\015y)f(in)m(to)i(a)f -(temp)s(orary)227 2250 y(FITS)h(format)h(image)g(in)f(memory)h(whic)m -(h)f(can)g(then)g(b)s(e)g(read)g(with)g(an)m(y)h(other)g(CFITSIO)e -(routine.)136 2427 y Fc(\017)46 b Fe(rawfile.dat[i512,512])p -Fi(:)35 b(op)s(ens)30 b(a)g(ra)m(w)h(binary)e(data)i(arra)m(y)g(\(a)g -(512)g(x)f(512)i(short)e(in)m(teger)h(arra)m(y)g(in)227 -2540 y(this)i(case\))i(and)d(con)m(v)m(erts)j(it)e(on)g(the)g(\015y)g -(in)m(to)h(a)f(temp)s(orary)g(FITS)f(format)h(image)i(in)d(memory)h -(whic)m(h)227 2652 y(can)e(then)f(b)s(e)g(read)g(with)g(an)m(y)h(other) -f(CFITSIO)f(routine.)136 2830 y Fc(\017)46 b Fe(myfile.fits.gz)p -Fi(:)d(if)33 b(this)g(is)g(the)g(name)g(of)h(a)f(new)g(output)g -(\014le,)h(the)f('.gz')i(su\016x)d(will)h(cause)h(it)g(to)g(b)s(e)227 -2942 y(compressed)c(in)g(gzip)h(format)g(when)e(it)i(is)g(written)f(to) -h(disk.)136 3120 y Fc(\017)46 b Fe('myfile.fits.gz[events,)c(2]')p -Fi(:)59 b(op)s(ens)40 b(and)f(uncompresses)g(the)i(gzipp)s(ed)e(\014le) -i(m)m(y\014le.\014ts)f(then)227 3232 y(mo)m(v)m(es)34 -b(to)f(the)f(extension)h(whic)m(h)f(has)f(the)i(k)m(eyw)m(ords)f -(EXTNAME)g(=)g('EVENTS')g(and)g(EXTVER)f(=)227 3345 y(2.)136 -3522 y Fc(\017)46 b Fe('-')p Fi(:)40 b(a)31 b(dash)f(\(min)m(us)g -(sign\))h(signi\014es)f(that)h(the)g(input)f(\014le)g(is)h(to)g(b)s(e)f -(read)g(from)g(the)h(stdin)f(\014le)g(stream,)227 3635 -y(or)h(that)g(the)f(output)g(\014le)h(is)f(to)h(b)s(e)f(written)g(to)h -(the)g(stdout)f(stream.)136 3812 y Fc(\017)46 b Fe -('ftp://legacy.gsfc.nasa.g)o(ov/t)o(est/)o(vel)o(a.fi)o(ts')p -Fi(:)33 b(FITS)28 b(\014les)g(in)g(an)m(y)g(ftp)g(arc)m(hiv)m(e)i(site) -f(on)f(the)227 3925 y(In)m(ternet)j(ma)m(y)g(b)s(e)f(directly)h(op)s -(ened)e(with)h(read-only)h(access.)136 4102 y Fc(\017)46 -b Fe('http://legacy.gsfc.nasa.)o(gov/)o(soft)o(war)o(e/te)o(st.f)o(its) -o(')p Fi(:)d(an)m(y)34 b(v)-5 b(alid)35 b(URL)f(to)h(a)f(FITS)g(\014le) -g(on)227 4215 y(the)d(W)-8 b(eb)31 b(ma)m(y)g(b)s(e)f(op)s(ened)f(with) -h(read-only)h(access.)136 4392 y Fc(\017)46 b Fe -('root://legacy.gsfc.nasa.)o(gov/)o(test)o(/ve)o(la.f)o(its')o -Fi(:)32 b(similar)24 b(to)g(ftp)f(access)i(except)g(that)f(it)g(pro-) -227 4505 y(vides)30 b(write)h(as)f(w)m(ell)h(as)g(read)f(access)h(to)g -(the)f(\014les)h(across)f(the)h(net)m(w)m(ork.)41 b(This)29 -b(uses)h(the)h(ro)s(ot)f(proto)s(col)227 4618 y(dev)m(elop)s(ed)h(at)g -(CERN.)136 4795 y Fc(\017)46 b Fe('shmem://h2[events]')p -Fi(:)35 b(op)s(ens)30 b(the)g(FITS)f(\014le)i(in)f(a)g(shared)f(memory) -i(segmen)m(t)g(and)e(mo)m(v)m(es)j(to)f(the)227 4908 -y(EVENTS)f(extension.)136 5085 y Fc(\017)46 b Fe('mem://')p -Fi(:)52 b(creates)39 b(a)e(scratc)m(h)i(output)d(\014le)i(in)e(core)i -(computer)f(memory)-8 b(.)62 b(The)37 b(resulting)g('\014le')h(will)227 -5198 y(disapp)s(ear)25 b(when)f(the)i(program)f(exits,)i(so)f(this)f -(is)h(mainly)f(useful)g(for)g(testing)i(purp)s(oses)c(when)i(one)g(do)s -(es)227 5311 y(not)31 b(w)m(an)m(t)g(a)g(p)s(ermanen)m(t)f(cop)m(y)h -(of)f(the)h(output)f(\014le.)136 5488 y Fc(\017)46 b -Fe('myfile.fits[3;)e(Images\(10\)]')p Fi(:)49 b(op)s(ens)35 -b(a)i(cop)m(y)g(of)f(the)g(image)i(con)m(tained)f(in)f(the)h(10th)f(ro) -m(w)h(of)227 5601 y(the)26 b('Images')i(column)d(in)h(the)g(binary)g -(table)g(in)g(the)g(3th)h(extension)f(of)g(the)h(FITS)e(\014le.)39 -b(The)26 b(application)227 5714 y(just)k(sees)h(this)f(single)h(image)h -(as)e(the)h(primary)e(arra)m(y)-8 b(.)p eop end -%%Page: 81 87 -TeXDict begin 81 86 bop 0 299 a Fg(8.1.)72 b(O)m(VER)-10 -b(VIEW)3086 b Fi(81)136 555 y Fc(\017)46 b Fe('myfile.fits[1:512:2,)c -(1:512:2]')p Fi(:)49 b(op)s(ens)35 b(a)h(section)h(of)e(the)h(input)f -(image)i(ranging)f(from)f(the)227 668 y(1st)26 b(to)g(the)f(512th)h -(pixel)g(in)e(X)i(and)e(Y,)i(and)e(selects)j(ev)m(ery)e(second)h(pixel) -f(in)g(b)s(oth)f(dimensions,)i(resulting)227 781 y(in)k(a)h(256)h(x)e -(256)i(pixel)e(image)i(in)e(this)g(case.)136 981 y Fc(\017)46 -b Fe('myfile.fits[EVENTS][col)41 b(Rad)47 b(=)h(sqrt\(X**2)d(+)j -(Y**2\)]')p Fi(:)38 b(creates)30 b(and)f(op)s(ens)f(a)h(temp)s(orary) -227 1094 y(\014le)f(on)f(the)g(\015y)g(\(in)g(memory)g(or)g(on)h -(disk\))f(that)g(is)h(iden)m(tical)h(to)f(m)m(y\014le.\014ts)f(except)h -(that)g(it)g(will)g(con)m(tain)227 1207 y(a)41 b(new)f(column)g(in)h -(the)f(EVENTS)g(extension)h(called)h('Rad')f(whose)f(v)-5 -b(alue)41 b(is)f(computed)h(using)f(the)227 1320 y(indicated)31 -b(expression)f(whic)m(h)g(is)h(a)g(function)f(of)g(the)h(v)-5 -b(alues)30 b(in)h(the)f(X)h(and)e(Y)i(columns.)136 1520 -y Fc(\017)46 b Fe('myfile.fits[EVENTS][PHA)41 b(>)48 -b(5]')p Fi(:)37 b(creates)27 b(and)e(op)s(ens)g(a)h(temp)s(orary)f -(FITS)g(\014les)g(that)h(is)g(iden)m(ti-)227 1633 y(cal)k(to)g('m)m -(y\014le.\014ts')f(except)h(that)f(the)g(EVENTS)f(table)i(will)f(only)g -(con)m(tain)h(the)f(ro)m(ws)g(that)h(ha)m(v)m(e)g(v)-5 -b(alues)227 1746 y(of)28 b(the)g(PHA)f(column)g(greater)i(than)e(5.)40 -b(In)27 b(general,)i(an)m(y)f(arbitrary)f(b)s(o)s(olean)h(expression)f -(using)g(a)h(C)f(or)227 1859 y(F)-8 b(ortran-lik)m(e)31 -b(syn)m(tax,)e(whic)m(h)f(ma)m(y)h(com)m(bine)g(AND)g(and)f(OR)f(op)s -(erators,)i(ma)m(y)g(b)s(e)f(used)f(to)i(select)h(ro)m(ws)227 -1972 y(from)g(a)h(table.)136 2172 y Fc(\017)46 b Fe -('myfile.fits[EVENTS][bin)41 b(\(X,Y\)=1,2048,4]')p Fi(:)46 -b(creates)37 b(a)e(temp)s(orary)g(FITS)f(primary)g(arra)m(y)227 -2285 y(image)c(whic)m(h)f(is)g(computed)f(on)h(the)g(\015y)f(b)m(y)g -(binning)g(\(i.e,)j(computing)d(the)h(2-dimensional)h(histogram\))227 -2398 y(of)k(the)f(v)-5 b(alues)34 b(in)f(the)h(X)g(and)e(Y)i(columns)f -(of)h(the)f(EVENTS)g(extension.)50 b(In)33 b(this)g(case)i(the)e(X)h -(and)f(Y)227 2511 y(co)s(ordinates)h(range)g(from)f(1)h(to)g(2048)h -(and)e(the)h(image)g(pixel)g(size)g(is)g(4)f(units)g(in)g(b)s(oth)g -(dimensions,)h(so)227 2624 y(the)d(resulting)f(image)i(is)e(512)i(x)e -(512)i(pixels)f(in)f(size.)136 2824 y Fc(\017)46 b Fi(The)31 -b(\014nal)g(example)i(com)m(bines)f(man)m(y)f(of)h(these)g(feature)g -(in)m(to)g(one)g(complex)g(expression)f(\(it)i(is)e(brok)m(en)227 -2937 y(in)m(to)h(sev)m(eral)f(lines)g(for)f(clarit)m(y\):)323 -3206 y Fe('ftp://legacy.gsfc.nasa)o(.gov)o(/dat)o(a/s)o(ampl)o(e.fi)o -(ts.)o(gz[E)o(VENT)o(S])370 3319 y([col)47 b(phacorr)f(=)h(pha)g(*)h -(1.1)f(-)g(0.3][phacorr)e(>=)i(5.0)g(&&)g(phacorr)f(<=)h(14.0])370 -3432 y([bin)g(\(X,Y\)=32]')227 3701 y Fi(In)37 b(this)h(case,)j -(CFITSIO)36 b(\(1\))j(copies)g(and)e(uncompresses)g(the)h(FITS)f -(\014le)h(from)f(the)h(ftp)f(site)i(on)f(the)227 3814 -y(legacy)g(mac)m(hine,)h(\(2\))e(mo)m(v)m(es)g(to)g(the)g('EVENTS')f -(extension,)i(\(3\))f(calculates)i(a)d(new)g(column)g(called)227 -3927 y('phacorr',)30 b(\(4\))f(selects)h(the)f(ro)m(ws)g(in)f(the)h -(table)h(that)f(ha)m(v)m(e)h(phacorr)e(in)g(the)h(range)g(5)g(to)h(14,) -g(and)e(\014nally)227 4040 y(\(5\))35 b(bins)d(the)h(remaining)g(ro)m -(ws)g(on)h(the)f(X)g(and)g(Y)g(column)g(co)s(ordinates,)i(using)d(a)i -(pixel)f(size)h(=)f(32)h(to)227 4153 y(create)d(a)f(2D)g(image.)42 -b(All)30 b(this)f(pro)s(cessing)g(is)h(completely)h(transparen)m(t)e -(to)i(the)e(application)i(program,)227 4266 y(whic)m(h)f(simply)g(sees) -h(the)g(\014nal)f(2-D)h(image)h(in)e(the)g(primary)g(arra)m(y)h(of)f -(the)h(op)s(ened)f(\014le.)0 4538 y(The)c(full)h(extended)g(CFITSIO)e -(FITS)h(\014le)h(name)g(can)g(con)m(tain)h(sev)m(eral)g(di\013eren)m(t) -g(comp)s(onen)m(ts)f(dep)s(ending)e(on)0 4651 y(the)31 -b(con)m(text.)42 b(These)30 b(comp)s(onen)m(ts)h(are)g(describ)s(ed)e -(in)h(the)g(follo)m(wing)i(sections:)0 4924 y Fe(When)47 -b(creating)e(a)j(new)f(file:)143 5036 y(filetype://BaseFilename\(t)o -(empl)o(ate)o(Name)o(\))0 5262 y(When)g(opening)e(an)j(existing)d -(primary)h(array)g(or)i(image)e(HDU:)143 5375 y -(filetype://BaseFilename\(o)o(utNa)o(me\))o([HDU)o(loca)o(tio)o(n][I)o -(mage)o(Sec)o(tion)o(])0 5601 y(When)h(opening)e(an)j(existing)d(table) -i(HDU:)143 5714 y(filetype://BaseFilename\(o)o(utNa)o(me\))o([HDU)o -(loca)o(tio)o(n][c)o(olFi)o(lte)o(r][r)o(owFi)o(lte)o(r][b)o(inSp)o -(ec])p eop end -%%Page: 82 88 -TeXDict begin 82 87 bop 0 299 a Fi(82)1618 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fi(The)41 b(\014let)m(yp)s(e,)k(BaseFilename,)i(outName,)e(HDUlo) -s(cation,)i(and)41 b(ImageSection)i(comp)s(onen)m(ts,)i(if)d(presen)m -(t,)0 668 y(m)m(ust)30 b(b)s(e)g(giv)m(en)i(in)e(that)h(order,)g(but)f -(the)g(colFilter,)j(ro)m(wFilter,)g(and)c(binSp)s(ec)h(sp)s(eci\014ers) -f(ma)m(y)j(follo)m(w)f(in)g(an)m(y)0 781 y(order.)39 -b(Regardless)29 b(of)g(the)f(order,)g(ho)m(w)m(ev)m(er,)i(the)f -(colFilter)h(sp)s(eci\014er,)e(if)g(presen)m(t,)h(will)g(b)s(e)e(pro)s -(cessed)h(\014rst)f(b)m(y)0 894 y(CFITSIO,)i(follo)m(w)m(ed)j(b)m(y)e -(the)h(ro)m(wFilter)h(sp)s(eci\014er,)e(and)f(\014nally)i(b)m(y)f(the)g -(binSp)s(ec)f(sp)s(eci\014er.)0 1253 y Fd(8.2)135 b(Filet)l(yp)t(e)0 -1508 y Fi(The)37 b(t)m(yp)s(e)g(of)g(\014le)g(determines)g(the)g -(medium)f(on)h(whic)m(h)g(the)g(\014le)g(is)h(lo)s(cated)g(\(e.g.,)i -(disk)d(or)g(net)m(w)m(ork\))h(and,)0 1621 y(hence,)f(whic)m(h)e(in)m -(ternal)h(device)g(driv)m(er)f(is)g(used)f(b)m(y)h(CFITSIO)f(to)i(read) -f(and/or)g(write)g(the)g(\014le.)56 b(Curren)m(tly)0 -1734 y(supp)s(orted)29 b(t)m(yp)s(es)h(are)382 2015 y -Fe(file://)93 b(-)48 b(file)e(on)i(local)e(magnetic)g(disk)g -(\(default\))382 2128 y(ftp://)141 b(-)48 b(a)f(readonly)f(file)g -(accessed)g(with)h(the)g(anonymous)e(FTP)i(protocol.)907 -2241 y(It)g(also)g(supports)93 b(ftp://username:password@)o(host)o(nam) -o(e/..)o(.)907 2354 y(for)47 b(accessing)e(password-protected)e(ftp)k -(sites.)382 2467 y(http://)93 b(-)48 b(a)f(readonly)f(file)g(accessed)g -(with)h(the)g(HTTP)f(protocol.)93 b(It)907 2579 y(supports)45 -b(username:password)e(just)k(like)g(the)g(ftp)g(driver.)907 -2692 y(Proxy)f(HTTP)h(servers)f(are)h(supported)e(using)h(the)h -(http_proxy)907 2805 y(environment)e(variable)g(\(see)i(following)e -(note\).)286 2918 y(stream://)93 b(-)48 b(special)e(driver)g(to)h(read) -g(an)g(input)f(FITS)h(file)f(from)h(the)g(stdin)907 3031 -y(stream,)f(and/or)g(write)g(an)h(output)f(FITS)h(file)g(to)g(the)g -(stdout)143 3144 y(stream.)94 b(This)46 b(driver)g(is)i(fragile)d(and)i -(has)g(limited)143 3257 y(functionality)d(\(see)j(the)g(following)e -(note\).)286 3370 y(gsiftp://)93 b(-)48 b(access)e(files)g(on)h(a)h -(computational)c(grid)j(using)f(the)h(gridftp)907 3483 -y(protocol)e(in)j(the)e(Globus)h(toolkit)e(\(see)i(following)e(note\).) -382 3596 y(root://)93 b(-)48 b(uses)e(the)h(CERN)g(root)g(protocol)e -(for)i(writing)f(as)h(well)g(as)907 3709 y(reading)f(files)g(over)h -(the)g(network.)382 3821 y(shmem://)e(-)j(opens)e(or)h(creates)f(a)i -(file)e(which)h(persists)e(in)i(the)g(computer's)907 -3934 y(shared)f(memory.)382 4047 y(mem://)141 b(-)48 -b(opens)e(a)i(temporary)d(file)i(in)g(core)f(memory.)94 -b(The)47 b(file)907 4160 y(disappears)e(when)h(the)h(program)f(exits)h -(so)g(this)f(is)i(mainly)907 4273 y(useful)e(for)h(test)f(purposes)g -(when)h(a)g(permanent)e(output)h(file)907 4386 y(is)h(not)g(desired.)0 -4667 y Fi(If)35 b(the)h(\014let)m(yp)s(e)g(is)f(not)h(sp)s(eci\014ed,)h -(then)e(t)m(yp)s(e)h(\014le://)h(is)e(assumed.)56 b(The)35 -b(double)g(slashes)h('//')h(are)f(optional)0 4780 y(and)30 -b(ma)m(y)h(b)s(e)e(omitted)j(in)e(most)h(cases.)0 5096 -y Fb(8.2.1)112 b(Notes)37 b(ab)s(out)i(HTTP)d(pro)m(xy)i(serv)m(ers)0 -5320 y Fi(A)32 b(pro)m(xy)g(HTTP)f(serv)m(er)h(ma)m(y)h(b)s(e)e(used)g -(b)m(y)h(de\014ning)f(the)h(address)f(\(URL\))i(and)e(p)s(ort)g(n)m(um) -m(b)s(er)g(of)h(the)g(pro)m(xy)0 5433 y(serv)m(er)f(with)f(the)g(h)m -(ttp)p 801 5433 28 4 v 33 w(pro)m(xy)g(en)m(vironmen)m(t)h(v)-5 -b(ariable.)42 b(F)-8 b(or)31 b(example)191 5714 y Fe(setenv)46 -b(http_proxy)f(http://heasarc.gsfc.nasa)o(.gov)o(:312)o(8)p -eop end -%%Page: 83 89 -TeXDict begin 83 88 bop 0 299 a Fg(8.2.)72 b(FILETYPE)3128 -b Fi(83)0 555 y(will)38 b(cause)g(CFITSIO)f(to)h(use)g(p)s(ort)f(3128)i -(on)f(the)g(heasarc)g(pro)m(xy)g(serv)m(er)g(whenev)m(er)g(reading)g(a) -g(FITS)f(\014le)0 668 y(with)30 b(HTTP)-8 b(.)0 987 y -Fb(8.2.2)112 b(Notes)37 b(ab)s(out)i(the)e(stream)h(\014let)m(yp)s(e)g -(driv)m(er)0 1212 y Fi(The)e(stream)h(driv)m(er)f(can)h(b)s(e)f(used)g -(to)h(e\016cien)m(tly)i(read)d(a)h(FITS)f(\014le)h(from)f(the)h(stdin)f -(\014le)g(stream)h(or)g(write)0 1324 y(a)44 b(FITS)e(to)i(the)g(stdout) -f(\014le)g(stream.)80 b(Ho)m(w)m(ev)m(er,)49 b(b)s(ecause)43 -b(these)h(input)e(and)h(output)g(streams)g(m)m(ust)h(b)s(e)0 -1437 y(accessed)30 b(sequen)m(tially)-8 b(,)31 b(the)e(FITS)f(\014le)g -(reading)h(or)f(writing)h(application)h(m)m(ust)e(also)i(read)e(and)g -(write)h(the)g(\014le)0 1550 y(sequen)m(tially)-8 b(,)33 -b(at)e(least)g(within)f(the)h(tolerances)h(describ)s(ed)d(b)s(elo)m(w.) -0 1710 y(CFITSIO)34 b(supp)s(orts)f(2)j(di\013eren)m(t)f(metho)s(ds)g -(for)g(accessing)i(FITS)d(\014les)h(on)h(the)f(stdin)g(and)f(stdout)h -(streams.)0 1823 y(The)c(original)i(metho)s(d,)f(whic)m(h)f(is)h(in)m -(v)m(ok)m(ed)h(b)m(y)f(sp)s(ecifying)f(a)h(dash)f(c)m(haracter,)j("-",) -g(as)d(the)h(name)g(of)g(the)g(\014le)0 1936 y(when)g(op)s(ening)g(or)h -(creating)h(it,)g(w)m(orks)e(b)m(y)h(storing)g(a)g(complete)h(cop)m(y)g -(of)f(the)g(en)m(tire)g(FITS)f(\014le)h(in)f(memory)-8 -b(.)0 2049 y(In)35 b(this)g(case,)k(when)34 b(reading)i(from)f(stdin,)i -(CFITSIO)d(will)i(cop)m(y)h(the)e(en)m(tire)i(stream)f(in)m(to)h -(memory)e(b)s(efore)0 2162 y(doing)c(an)m(y)h(pro)s(cessing)f(of)h(the) -f(\014le.)44 b(Similarly)-8 b(,)32 b(when)f(writing)g(to)h(stdout,)g -(CFITSIO)d(will)j(create)h(a)f(cop)m(y)g(of)0 2275 y(the)h(en)m(tire)g -(FITS)f(\014le)g(in)h(memory)-8 b(,)33 b(b)s(efore)f(\014nally)h -(\015ushing)e(it)i(out)f(to)i(the)e(stdout)h(stream)g(when)e(the)i -(FITS)0 2388 y(\014le)g(is)g(closed.)49 b(Bu\013ering)33 -b(the)g(en)m(tire)h(FITS)e(\014le)h(in)g(this)f(w)m(a)m(y)i(allo)m(ws)g -(the)f(application)i(to)e(randomly)g(access)0 2501 y(an)m(y)h(part)f -(of)h(the)f(FITS)g(\014le,)i(in)e(an)m(y)h(order,)f(but)g(it)h(also)h -(requires)e(that)h(the)f(user)g(ha)m(v)m(e)i(su\016cien)m(t)f(a)m(v)-5 -b(ailable)0 2614 y(memory)30 b(\(or)g(virtual)g(memory\))g(to)h(store)f -(the)g(en)m(tire)h(\014le,)f(whic)m(h)f(ma)m(y)i(not)f(b)s(e)f(p)s -(ossible)g(in)h(the)g(case)h(of)f(v)m(ery)0 2727 y(large)h(\014les.)0 -2887 y(The)e(new)m(er)g(stream)h(\014let)m(yp)s(e)g(pro)m(vides)f(a)h -(more)f(memory-e\016cien)m(t)i(metho)s(d)e(of)h(accessing)h(FITS)d -(\014les)h(on)h(the)0 3000 y(stdin)37 b(or)h(stdout)g(streams.)64 -b(Instead)38 b(of)g(storing)g(a)g(cop)m(y)h(of)f(the)g(en)m(tire)h -(FITS)e(\014le)h(in)g(memory)-8 b(,)40 b(CFITSIO)0 3113 -y(only)32 b(uses)g(a)g(set)h(of)f(in)m(ternal)h(bu\013er)e(whic)m(h)h -(b)m(y)g(default)g(can)g(store)h(40)g(FITS)e(blo)s(c)m(ks,)i(or)g(ab)s -(out)e(100K)i(b)m(ytes)0 3225 y(of)f(the)f(FITS)g(\014le.)43 -b(The)31 b(application)i(program)e(m)m(ust)g(pro)s(cess)g(the)h(FITS)e -(\014le)i(sequen)m(tially)h(from)e(b)s(eginning)0 3338 -y(to)h(end,)e(within)g(this)h(100K)h(bu\013er.)41 b(Generally)32 -b(sp)s(eaking)f(the)g(application)h(program)f(m)m(ust)f(conform)h(to)h -(the)0 3451 y(follo)m(wing)g(restrictions:)136 3735 y -Fc(\017)46 b Fi(The)36 b(program)f(m)m(ust)h(\014nish)e(reading)i(or)g -(writing)f(the)h(header)g(k)m(eyw)m(ords)g(b)s(efore)f(reading)h(or)g -(writing)227 3848 y(an)m(y)31 b(data)g(in)f(the)h(HDU.)136 -4060 y Fc(\017)46 b Fi(The)24 b(HDU)h(can)f(con)m(tain)i(at)e(most)h -(ab)s(out)f(1400)h(header)f(k)m(eyw)m(ords.)39 b(This)24 -b(is)g(the)g(maxim)m(um)g(that)h(can)f(\014t)227 4172 -y(in)g(the)g(nominal)h(40)g(FITS)e(blo)s(c)m(k)i(bu\013er.)37 -b(In)24 b(principle,)h(this)f(limit)h(could)f(b)s(e)g(increased)g(b)m -(y)g(recompiling)227 4285 y(CFITSIO)29 b(with)h(a)h(larger)g(bu\013er)e -(limit,)j(whic)m(h)e(is)g(set)h(b)m(y)f(the)h(NIOBUF)g(parameter)g(in)f -(\014tsio2.h.)136 4497 y Fc(\017)46 b Fi(The)32 b(program)g(m)m(ust)f -(read)h(or)g(write)h(the)f(data)g(in)g(a)g(sequen)m(tial)i(manner)d -(from)h(the)g(b)s(eginning)f(to)i(the)227 4610 y(end)26 -b(of)g(the)h(HDU.)g(Note)h(that)f(CFITSIO's)e(in)m(ternal)i(100K)g -(bu\013er)e(allo)m(ws)j(a)e(little)j(latitude)e(in)f(meeting)227 -4723 y(this)31 b(requiremen)m(t.)136 4934 y Fc(\017)46 -b Fi(The)30 b(program)g(cannot)h(mo)m(v)m(e)h(bac)m(k)f(to)g(a)g -(previous)f(HDU)h(in)f(the)h(FITS)e(\014le.)136 5146 -y Fc(\017)46 b Fi(Reading)c(or)f(writing)f(of)h(v)-5 -b(ariable)42 b(length)f(arra)m(y)h(columns)e(in)h(binary)f(tables)i(is) -f(not)g(supp)s(orted)e(on)227 5259 y(streams,)29 b(b)s(ecause)f(this)g -(requires)g(mo)m(ving)g(bac)m(k)h(and)f(forth)f(b)s(et)m(w)m(een)i(the) -f(\014xed-length)g(p)s(ortion)g(of)g(the)227 5372 y(binary)i(table)h -(and)f(the)g(follo)m(wing)i(heap)e(area)i(where)e(the)g(arra)m(ys)h -(are)g(actually)h(stored.)136 5583 y Fc(\017)46 b Fi(Reading)25 -b(or)g(writing)f(of)h(tile-compressed)h(images)g(is)e(not)h(supp)s -(orted)e(on)h(streams,)i(b)s(ecause)f(the)g(images)227 -5696 y(are)31 b(in)m(ternally)g(stored)g(using)f(v)-5 -b(ariable)31 b(length)g(arra)m(ys.)p eop end -%%Page: 84 90 -TeXDict begin 84 89 bop 0 299 a Fi(84)1618 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fb(8.2.3)112 b(Notes)37 b(ab)s(out)i(the)e(gsiftp)h(\014let)m(yp) -s(e)0 774 y Fi(DEPENDENCIES:)c(Globus)h(to)s(olkit)h(\(2.4.3)g(or)f -(higher\))f(\(GT\))h(should)f(b)s(e)g(installed.)53 b(There)34 -b(are)h(t)m(w)m(o)h(dif-)0 887 y(feren)m(t)31 b(w)m(a)m(ys)g(to)g -(install)g(GT:)0 1047 y(1\))43 b(goto)h(the)f(globus)f(to)s(olkit)i(w)m -(eb)e(page)i(www.globus.org)e(and)g(follo)m(w)h(the)g(do)m(wnload)g -(and)e(compilation)0 1160 y(instructions;)0 1320 y(2\))j(goto)i(the)d -(Virtual)i(Data)g(T)-8 b(o)s(olkit)45 b(w)m(eb)e(page)i(h)m -(ttp://vdt.cs.wisc.edu/)g(and)e(follo)m(w)i(the)f(instructions)0 -1433 y(\(STR)m(ONGL)-8 b(Y)31 b(SUGGESTED\);)0 1593 y(Once)23 -b(a)h(globus)f(clien)m(t)h(has)f(b)s(een)g(installed)h(in)e(y)m(our)i -(system)f(with)g(a)g(sp)s(eci\014c)g(\015a)m(v)m(our)h(it)f(is)g(p)s -(ossible)g(to)h(compile)0 1706 y(and)30 b(install)h(the)g(CFITSIO)d -(libraries.)41 b(Sp)s(eci\014c)30 b(con\014guration)h(\015ags)f(m)m -(ust)h(b)s(e)e(used:)0 1866 y(1\))21 b({with-gsiftp[[=P)-8 -b(A)g(TH]])22 b(Enable)f(Globus)f(T)-8 b(o)s(olkit)21 -b(gsiftp)g(proto)s(col)g(supp)s(ort)d(P)-8 b(A)g(TH=GLOBUS)p -3532 1866 28 4 v 33 w(LOCA)g(TION)0 1979 y(i.e.)42 b(the)30 -b(lo)s(cation)i(of)f(y)m(our)f(globus)g(installation)0 -2139 y(2\))h({with-gsiftp-\015a)m(v)m(our[[=P)-8 b(A)g(TH])33 -b(de\014nes)d(the)g(sp)s(eci\014c)g(Globus)h(\015a)m(v)m(our)f(ex.)41 -b(gcc32)0 2300 y(Both)31 b(the)g(\015ags)f(m)m(ust)g(b)s(e)g(used)g -(and)f(it)i(is)g(mandatory)f(to)h(set)g(b)s(oth)f(the)g(P)-8 -b(A)g(TH)31 b(and)f(the)h(\015a)m(v)m(our.)0 2460 y(USA)m(GE:)g(T)-8 -b(o)31 b(access)h(\014les)e(on)g(a)h(gridftp)f(serv)m(er)g(it)h(is)g -(necessary)f(to)i(use)e(a)g(gsiftp)h(pre\014x:)0 2620 -y(example:)41 b(gsiftp://remote)p 1003 2620 V 35 w(serv)m(er)p -1271 2620 V 34 w(fqhn/directory/\014lename)0 2780 y(The)f(gridftp)g -(driv)m(er)g(uses)g(a)g(lo)s(cal)i(bu\013er)d(on)i(a)f(temp)s(orary)g -(\014le)h(the)f(\014le)h(is)f(lo)s(cated)i(in)e(the)g(/tmp)h(direc-)0 -2893 y(tory)-8 b(.)73 b(If)40 b(y)m(ou)h(ha)m(v)m(e)h(sp)s(ecial)g(p)s -(ermissions)d(on)i(/tmp)g(or)g(y)m(ou)g(do)f(not)i(ha)m(v)m(e)g(a)f -(/tmp)g(directory)-8 b(,)44 b(it)e(is)e(p)s(os-)0 3006 -y(sible)d(to)h(force)g(another)g(lo)s(cation)g(setting)h(the)e(GSIFTP)p -2068 3006 V 32 w(TMPFILE)g(en)m(vironmen)m(t)h(v)-5 b(ariable)38 -b(\(ex.)62 b(exp)s(ort)0 3119 y(GSIFTP)p 347 3119 V 32 -w(TMPFILE=/y)m(our/lo)s(cation/y)m(ourtmp\014le\).)0 -3279 y(Grid)34 b(FTP)g(supp)s(orts)f(m)m(ulti)h(c)m(hannel)h(transfer.) -52 b(By)35 b(default)f(a)h(single)g(c)m(hannel)g(transmission)f(is)g(a) -m(v)-5 b(ailable.)0 3392 y(Ho)m(w)m(ev)m(er,)34 b(it)d(is)h(p)s -(ossible)e(to)i(mo)s(dify)e(this)i(b)s(eha)m(vior)f(setting)h(the)f -(GSIFTP)p 2691 3392 V 33 w(STREAMS)f(en)m(vironmen)m(t)h(v)-5 -b(ari-)0 3505 y(able)31 b(\(ex.)41 b(exp)s(ort)30 b(GSIFTP)p -1016 3505 V 33 w(STREAMS=8\).)0 3790 y Fb(8.2.4)112 b(Notes)37 -b(ab)s(out)i(the)e(ro)s(ot)g(\014let)m(yp)s(e)0 4009 -y Fi(The)20 b(original)j(ro)s(otd)d(serv)m(er)h(can)h(b)s(e)e(obtained) -h(from:)36 b Fe(ftp://root.cern.ch/root)o(/roo)o(td.t)o(ar.)o(gz)15 -b Fi(but,)22 b(for)0 4122 y(it)33 b(to)h(w)m(ork)f(correctly)h(with)e -(CFITSIO)g(one)h(has)f(to)i(use)e(a)i(mo)s(di\014ed)d(v)m(ersion)j -(whic)m(h)e(supp)s(orts)f(a)i(command)0 4235 y(to)41 -b(return)d(the)j(length)f(of)g(the)g(\014le.)70 b(This)39 -b(mo)s(di\014ed)f(v)m(ersion)j(is)f(a)m(v)-5 b(ailable)42 -b(in)e(ro)s(otd)f(sub)s(directory)g(in)h(the)0 4348 y(CFITSIO)29 -b(ftp)h(area)h(at)286 4577 y Fe(ftp://legacy.gsfc.nasa.gov)o(/so)o -(ftwa)o(re/f)o(its)o(io/c)o(/roo)o(t/r)o(ootd)o(.tar)o(.gz)o(.)0 -4805 y Fi(This)j(small)g(serv)m(er)h(is)g(started)f(either)h(b)m(y)g -(inetd)f(when)f(a)i(clien)m(t)h(requests)e(a)h(connection)h(to)f(a)f -(ro)s(otd)h(serv)m(er)0 4918 y(or)30 b(b)m(y)g(hand)f(\(i.e.)42 -b(from)30 b(the)g(command)g(line\).)42 b(The)29 b(ro)s(otd)h(serv)m(er) -h(w)m(orks)f(with)g(the)g(R)m(OOT)g(TNetFile)i(class.)0 -5031 y(It)e(allo)m(ws)g(remote)h(access)f(to)h(R)m(OOT)e(database)h -(\014les)f(in)g(either)h(read)g(or)f(write)h(mo)s(de.)40 -b(By)30 b(default)f(TNetFile)0 5144 y(assumes)38 b(p)s(ort)g(432)h -(\(whic)m(h)f(requires)g(ro)s(otd)g(to)h(b)s(e)f(started)h(as)f(ro)s -(ot\).)65 b(T)-8 b(o)39 b(run)e(ro)s(otd)h(via)h(inetd)f(add)g(the)0 -5257 y(follo)m(wing)32 b(line)f(to)g(/etc/services:)95 -5485 y Fe(rootd)238 b(432/tcp)0 5714 y Fi(and)30 b(to)h -(/etc/inetd.conf,)i(add)d(the)g(follo)m(wing)i(line:)p -eop end -%%Page: 85 91 -TeXDict begin 85 90 bop 0 299 a Fg(8.2.)72 b(FILETYPE)3128 -b Fi(85)95 555 y Fe(rootd)47 b(stream)f(tcp)h(nowait)f(root)h -(/user/rdm/root/bin/root)o(d)42 b(rootd)k(-i)0 829 y -Fi(F)-8 b(orce)34 b(inetd)e(to)i(reread)e(its)h(conf)f(\014le)h(with)f -("kill)h(-HUP)g(".)47 b(Y)-8 b(ou)33 b(can)g(also)g(start) -g(ro)s(otd)g(b)m(y)f(hand)0 942 y(running)j(directly)i(under)d(y)m(our) -j(priv)-5 b(ate)37 b(accoun)m(t)g(\(no)g(ro)s(ot)g(system)f(privileges) -h(needed\).)59 b(F)-8 b(or)37 b(example)g(to)0 1054 y(start)e(ro)s(otd) -e(listening)i(on)f(p)s(ort)f(5151)j(just)d(t)m(yp)s(e:)49 -b Fe(rootd)d(-p)h(5151)33 b Fi(Notice:)50 b(no)34 b(&)f(is)h(needed.)51 -b(Ro)s(otd)35 b(will)0 1167 y(go)c(in)m(to)h(bac)m(kground)e(b)m(y)g -(itself.)95 1441 y Fe(Rootd)47 b(arguments:)191 1554 -y(-i)763 b(says)47 b(we)g(were)f(started)g(by)h(inetd)191 -1667 y(-p)g(port#)476 b(specifies)45 b(a)j(different)d(port)i(to)g -(listen)f(on)191 1780 y(-d)h(level)476 b(level)46 b(of)i(debug)e(info)h -(written)e(to)j(syslog)1050 1893 y(0)f(=)h(no)f(debug)f(\(default\)) -1050 2005 y(1)h(=)h(minimum)1050 2118 y(2)f(=)h(medium)1050 -2231 y(3)f(=)h(maximum)0 2505 y Fi(Ro)s(otd)29 b(can)f(also)h(b)s(e)f -(con\014gured)g(for)g(anon)m(ymous)g(usage)h(\(lik)m(e)h(anon)m(ymous)e -(ftp\).)40 b(T)-8 b(o)29 b(setup)f(ro)s(otd)g(to)h(accept)0 -2618 y(anon)m(ymous)h(logins)h(do)g(the)f(follo)m(wing)i(\(while)f(b)s -(eing)f(logged)i(in)e(as)g(ro)s(ot\):)143 2891 y Fe(-)48 -b(Add)f(the)f(following)g(line)g(to)i(/etc/passwd:)239 -3117 y(rootd:*:71:72:Anonymous)41 b(rootd:/var/spool/rootd:/b)o(in/)o -(fals)o(e)239 3343 y(where)46 b(you)h(may)g(modify)f(the)h(uid,)f(gid)h -(\(71,)g(72\))g(and)g(the)g(home)f(directory)239 3456 -y(to)h(suite)f(your)h(system.)143 3681 y(-)h(Add)f(the)f(following)g -(line)g(to)i(/etc/group:)239 3907 y(rootd:*:72:rootd)239 -4133 y(where)e(the)h(gid)g(must)f(match)h(the)g(gid)g(in)g -(/etc/passwd.)143 4359 y(-)h(Create)e(the)h(directories:)239 -4585 y(mkdir)f(/var/spool/rootd)239 4698 y(mkdir)g -(/var/spool/rootd/tmp)239 4811 y(chmod)g(777)h(/var/spool/rootd/tmp)239 -5036 y(Where)f(/var/spool/rootd)d(must)k(match)f(the)h(rootd)g(home)f -(directory)g(as)239 5149 y(specified)f(in)i(the)g(rootd)f(/etc/passwd)f -(entry.)143 5375 y(-)j(To)f(make)f(writeable)g(directories)e(for)j -(anonymous)f(do,)h(for)f(example:)239 5601 y(mkdir)g -(/var/spool/rootd/pub)239 5714 y(chown)g(rootd:rootd)f -(/var/spool/rootd/pub)p eop end -%%Page: 86 92 -TeXDict begin 86 91 bop 0 299 a Fi(86)1618 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fi(That's)42 b(all.)76 b(Sev)m(eral)43 b(additional)g(remarks:)64 -b(y)m(ou)42 b(can)g(login)h(to)g(an)f(anon)m(ymous)f(serv)m(er)i -(either)f(with)g(the)0 668 y(names)31 b("anon)m(ymous")h(or)f("ro)s -(otd".)43 b(The)31 b(passw)m(ord)f(should)g(b)s(e)h(of)g(t)m(yp)s(e)g -(user@host.do.main.)43 b(Only)30 b(the)h(@)0 781 y(is)e(enforced)f(for) -h(the)f(time)i(b)s(eing.)39 b(In)28 b(anon)m(ymous)h(mo)s(de)f(the)g -(top)h(of)g(the)g(\014le)f(tree)i(is)e(set)h(to)h(the)e(ro)s(otd)h -(home)0 894 y(directory)-8 b(,)39 b(therefore)e(only)f(\014les)h(b)s -(elo)m(w)f(the)h(home)f(directory)h(can)f(b)s(e)g(accessed.)60 -b(Anon)m(ymous)36 b(mo)s(de)g(only)0 1007 y(w)m(orks)30 -b(when)g(the)g(serv)m(er)h(is)f(started)h(via)g(inetd.)0 -1296 y Fb(8.2.5)112 b(Notes)37 b(ab)s(out)i(the)e(shmem)i(\014let)m(yp) -s(e:)0 1515 y Fi(Shared)34 b(memory)h(\014les)g(are)g(curren)m(tly)g -(supp)s(orted)e(on)i(most)h(Unix)f(platforms,)h(where)f(the)g(shared)f -(memory)0 1627 y(segmen)m(ts)d(are)g(managed)g(b)m(y)f(the)g(op)s -(erating)h(system)g(k)m(ernel)f(and)g(`liv)m(e')i(indep)s(enden)m(tly)d -(of)i(pro)s(cesses.)40 b(They)0 1740 y(are)34 b(not)g(deleted)h(\(b)m -(y)f(default\))g(when)f(the)h(pro)s(cess)f(whic)m(h)h(created)h(them)f -(terminates,)h(although)g(they)f(will)0 1853 y(disapp)s(ear)e(if)h(the) -h(system)f(is)g(reb)s(o)s(oted.)49 b(Applications)34 -b(can)g(create)h(shared)d(memory)h(\014les)g(in)g(CFITSIO)f(b)m(y)0 -1966 y(calling:)143 2214 y Fe(fit_create_file\(&fitsfile)o(ptr,)41 -b("shmem://h2",)j(&status\);)0 2462 y Fi(where)25 b(the)g(ro)s(ot)h -(`\014le')f(names)h(are)f(curren)m(tly)g(restricted)h(to)g(b)s(e)f -('h0',)i('h1',)g('h2',)g('h3',)f(etc.,)i(up)d(to)g(a)h(maxim)m(um)0 -2575 y(n)m(um)m(b)s(er)20 b(de\014ned)f(b)m(y)i(the)g(the)g(v)-5 -b(alue)22 b(of)f(SHARED)p 1746 2575 28 4 v 33 w(MAXSEG)g(\(equal)h(to)f -(16)h(b)m(y)f(default\).)38 b(This)20 b(is)h(a)g(protot)m(yp)s(e)0 -2688 y(implemen)m(tation)30 b(of)f(the)g(shared)f(memory)g(in)m -(terface)i(and)e(a)h(more)g(robust)f(in)m(terface,)j(whic)m(h)d(will)h -(ha)m(v)m(e)h(few)m(er)0 2801 y(restrictions)h(on)f(the)h(n)m(um)m(b)s -(er)e(of)i(\014les)f(and)g(on)g(their)g(names,)h(ma)m(y)g(b)s(e)f(dev)m -(elop)s(ed)g(in)g(the)h(future.)0 2961 y(When)23 b(op)s(ening)h(an)f -(already)h(existing)h(FITS)e(\014le)h(in)f(shared)g(memory)h(one)g -(calls)g(the)g(usual)g(CFITSIO)e(routine:)143 3209 y -Fe(fits_open_file\(&fitsfilep)o(tr,)41 b("shmem://h7",)j(mode,)j -(&status\))0 3457 y Fi(The)26 b(\014le)h(mo)s(de)g(can)g(b)s(e)f(READ)m -(WRITE)h(or)g(READONL)-8 b(Y)28 b(just)e(as)h(with)f(disk)h(\014les.)39 -b(More)28 b(than)e(one)h(pro)s(cess)0 3570 y(can)35 b(op)s(erate)g(on)f -(READONL)-8 b(Y)35 b(mo)s(de)f(\014les)h(at)g(the)f(same)h(time.)54 -b(CFITSIO)33 b(supp)s(orts)f(prop)s(er)h(\014le)i(lo)s(c)m(king)0 -3682 y(\(b)s(oth)27 b(in)h(READONL)-8 b(Y)29 b(and)e(READ)m(WRITE)h(mo) -s(des\),)h(so)f(calls)h(to)f(\014ts)p 2572 3682 V 33 -w(op)s(en)p 2795 3682 V 32 w(\014le)g(ma)m(y)g(b)s(e)f(lo)s(c)m(k)m(ed) -j(out)e(un)m(til)0 3795 y(another)j(other)f(pro)s(cess)g(closes)i(the)e -(\014le.)0 3956 y(When)g(an)g(application)i(is)e(\014nished)f -(accessing)j(a)e(FITS)g(\014le)g(in)g(a)h(shared)e(memory)h(segmen)m -(t,)i(it)f(ma)m(y)g(close)g(it)0 4068 y(\(and)j(the)g(\014le)g(will)g -(remain)f(in)h(the)g(system\))g(with)g(\014ts)p 1955 -4068 V 32 w(close)p 2173 4068 V 34 w(\014le,)h(or)f(delete)h(it)g(with) -e(\014ts)p 3191 4068 V 33 w(delete)p 3455 4068 V 34 w(\014le.)51 -b(Ph)m(ys-)0 4181 y(ical)36 b(deletion)g(is)f(p)s(ostp)s(oned)e(un)m -(til)j(the)f(last)g(pro)s(cess)g(calls)h(\013clos/\013delt.)56 -b(\014ts)p 2801 4181 V 32 w(delete)p 3064 4181 V 34 w(\014le)35 -b(tries)h(to)f(obtain)h(a)0 4294 y(READ)m(WRITE)e(lo)s(c)m(k)g(on)f -(the)g(\014le)h(to)g(b)s(e)e(deleted,)j(th)m(us)e(it)h(can)f(b)s(e)g -(blo)s(c)m(k)m(ed)h(if)f(the)h(ob)5 b(ject)34 b(w)m(as)f(not)h(op)s -(ened)0 4407 y(in)c(READ)m(WRITE)h(mo)s(de.)0 4567 y(A)i(shared)f -(memory)h(managemen)m(t)h(utilit)m(y)g(program)f(called)h(`smem',)f(is) -g(included)f(with)h(the)g(CFITSIO)e(dis-)0 4680 y(tribution.)39 -b(It)27 b(can)g(b)s(e)f(built)h(b)m(y)g(t)m(yping)g(`mak)m(e)h(smem';)g -(then)f(t)m(yp)s(e)g(`smem)f(-h')h(to)h(get)g(a)f(list)g(of)g(v)-5 -b(alid)27 b(options.)0 4793 y(Executing)37 b(smem)f(without)g(an)m(y)h -(options)g(causes)f(it)h(to)g(list)g(all)g(the)g(shared)e(memory)i -(segmen)m(ts)g(curren)m(tly)0 4906 y(residing)c(in)g(the)g(system)h -(and)e(managed)i(b)m(y)f(the)h(shared)e(memory)h(driv)m(er.)49 -b(T)-8 b(o)34 b(get)g(a)g(list)g(of)f(all)h(the)g(shared)0 -5019 y(memory)c(ob)5 b(jects,)32 b(run)d(the)h(system)h(utilit)m(y)g -(program)f(`ip)s(cs)h([-a]'.)0 5351 y Fd(8.3)135 b(Base)46 -b(Filename)0 5601 y Fi(The)31 b(base)g(\014lename)h(is)f(the)h(name)f -(of)h(the)f(\014le)h(optionally)g(including)f(the)h(director/sub)s -(directory)f(path,)h(and)0 5714 y(in)e(the)h(case)g(of)g(`ftp',)f(`h)m -(ttp',)i(and)d(`ro)s(ot')j(\014let)m(yp)s(es,)e(the)h(mac)m(hine)g -(iden)m(ti\014er.)41 b(Examples:)p eop end -%%Page: 87 93 -TeXDict begin 87 92 bop 0 299 a Fg(8.3.)72 b(BASE)30 -b(FILENAME)2830 b Fi(87)191 555 y Fe(myfile.fits)191 -668 y(!data.fits)191 781 y(/data/myfile.fits)191 894 -y(fits.gsfc.nasa.gov/ftp/s)o(ampl)o(eda)o(ta/m)o(yfil)o(e.f)o(its.)o -(gz)0 1120 y Fi(When)29 b(creating)h(a)f(new)f(output)h(\014le)g(on)g -(magnetic)h(disk)e(\(of)i(t)m(yp)s(e)f(\014le://\))h(if)f(the)g(base)g -(\014lename)g(b)s(egins)f(with)0 1233 y(an)34 b(exclamation)j(p)s(oin)m -(t)d(\(!\))54 b(then)34 b(an)m(y)g(existing)i(\014le)e(with)g(that)h -(same)g(basename)g(will)g(b)s(e)e(deleted)i(prior)f(to)0 -1346 y(creating)h(the)f(new)g(FITS)f(\014le.)51 b(Otherwise)34 -b(if)g(the)g(\014le)g(to)g(b)s(e)g(created)h(already)f(exists,)i(then)d -(CFITSIO)g(will)0 1459 y(return)g(an)h(error)f(and)g(will)i(not)f(o)m -(v)m(erwrite)h(the)f(existing)h(\014le.)52 b(Note)35 -b(that)g(the)f(exclamation)i(p)s(oin)m(t,)f(')10 b(!',)36 -b(is)e(a)0 1572 y(sp)s(ecial)28 b(UNIX)g(c)m(haracter,)j(so)d(if)f(it)i -(is)f(used)f(on)g(the)h(command)g(line)g(rather)g(than)f(en)m(tered)h -(at)h(a)f(task)h(prompt,)0 1685 y(it)j(m)m(ust)f(b)s(e)g(preceded)g(b)m -(y)h(a)g(bac)m(kslash)g(to)g(force)g(the)g(UNIX)g(shell)f(to)h(pass)f -(it)i(v)m(erbatim)f(to)g(the)g(application)0 1798 y(program.)0 -1958 y(If)24 b(the)i(output)e(disk)h(\014le)g(name)g(ends)f(with)g(the) -h(su\016x)f('.gz',)k(then)d(CFITSIO)e(will)i(compress)g(the)g(\014le)g -(using)g(the)0 2071 y(gzip)g(compression)f(algorithm)h(b)s(efore)f -(writing)g(it)h(to)g(disk.)38 b(This)23 b(can)i(reduce)f(the)g(amoun)m -(t)h(of)f(disk)g(space)h(used)0 2184 y(b)m(y)34 b(the)h(\014le.)53 -b(Note)36 b(that)f(this)g(feature)g(requires)f(that)h(the)f -(uncompressed)g(\014le)g(b)s(e)g(constructed)h(in)f(memory)0 -2297 y(b)s(efore)c(it)h(is)f(compressed)g(and)g(written)h(to)g(disk,)f -(so)g(it)h(can)g(fail)g(if)f(there)h(is)f(insu\016cien)m(t)h(a)m(v)-5 -b(ailable)33 b(memory)-8 b(.)0 2457 y(An)45 b(input)g(FITS)f(\014le)i -(ma)m(y)g(b)s(e)f(compressed)g(with)h(the)f(gzip)h(or)g(Unix)f -(compress)h(algorithms,)k(in)45 b(whic)m(h)0 2570 y(case)38 -b(CFITSIO)e(will)i(uncompress)e(the)i(\014le)g(on)f(the)h(\015y)e(in)m -(to)j(a)f(temp)s(orary)f(\014le)g(\(in)h(memory)f(or)g(on)h(disk\).)0 -2683 y(Compressed)32 b(\014les)i(ma)m(y)g(only)f(b)s(e)g(op)s(ened)f -(with)h(read-only)h(p)s(ermission.)49 b(When)33 b(sp)s(ecifying)g(the)h -(name)f(of)h(a)0 2796 y(compressed)h(FITS)g(\014le)h(it)g(is)g(not)g -(necessary)g(to)g(app)s(end)e(the)i(\014le)g(su\016x)e(\(e.g.,)39 -b(`.gz')e(or)f(`.Z'\).)g(If)f(CFITSIO)0 2908 y(cannot)24 -b(\014nd)e(the)h(input)f(\014le)i(name)f(without)g(the)g(su\016x,)h -(then)f(it)h(will)g(automatically)i(searc)m(h)e(for)f(a)g(compressed)0 -3021 y(\014le)36 b(with)f(the)h(same)g(ro)s(ot)g(name.)57 -b(In)35 b(the)h(case)h(of)f(reading)g(ftp)f(and)g(h)m(ttp)h(t)m(yp)s(e) -g(\014les,)h(CFITSIO)e(generally)0 3134 y(lo)s(oks)j(for)g(a)g -(compressed)g(v)m(ersion)g(of)g(the)g(\014le)g(\014rst,)h(b)s(efore)e -(trying)h(to)h(op)s(en)e(the)h(uncompressed)e(\014le.)64 -b(By)0 3247 y(default,)37 b(CFITSIO)e(copies)h(\(and)g(uncompressed)e -(if)i(necessary\))g(the)g(ftp)f(or)h(h)m(ttp)g(FITS)f(\014le)g(in)m(to) -i(memory)0 3360 y(on)f(the)g(lo)s(cal)h(mac)m(hine)f(b)s(efore)g(op)s -(ening)f(it.)58 b(This)35 b(will)h(fail)g(if)g(the)g(lo)s(cal)h(mac)m -(hine)g(do)s(es)e(not)h(ha)m(v)m(e)h(enough)0 3473 y(memory)g(to)h -(hold)f(the)g(whole)h(FITS)e(\014le,)k(so)d(in)g(this)g(case,)k(the)c -(output)g(\014lename)g(sp)s(eci\014er)g(\(see)h(the)g(next)0 -3586 y(section\))32 b(can)f(b)s(e)e(used)h(to)h(further)e(con)m(trol)j -(ho)m(w)e(CFITSIO)f(reads)h(ftp)g(and)g(h)m(ttp)g(\014les.)0 -3746 y(If)i(the)h(input)f(\014le)h(is)g(an)g(IRAF)g(image)h(\014le)f -(\(*.imh)g(\014le\))h(then)e(CFITSIO)f(will)j(automatically)h(con)m(v)m -(ert)g(it)e(on)0 3859 y(the)27 b(\015y)g(in)m(to)h(a)g(virtual)f(FITS)f -(image)j(b)s(efore)e(it)g(is)g(op)s(ened)g(b)m(y)g(the)g(application)i -(program.)39 b(IRAF)27 b(images)i(can)0 3972 y(only)h(b)s(e)g(op)s -(ened)g(with)g(READONL)-8 b(Y)31 b(\014le)f(access.)0 -4132 y(Similarly)-8 b(,)32 b(if)f(the)g(input)f(\014le)i(is)f(a)g(ra)m -(w)g(binary)f(data)i(arra)m(y)-8 b(,)33 b(then)d(CFITSIO)g(will)h(con)m -(v)m(ert)i(it)e(on)g(the)h(\015y)e(in)m(to)0 4245 y(a)38 -b(virtual)g(FITS)g(image)h(with)e(the)h(basic)h(set)f(of)g(required)f -(header)h(k)m(eyw)m(ords)g(b)s(efore)g(it)g(is)g(op)s(ened)f(b)m(y)h -(the)0 4358 y(application)32 b(program)f(\(with)g(READONL)-8 -b(Y)31 b(access\).)44 b(In)30 b(this)h(case)h(the)f(data)g(t)m(yp)s(e)g -(and)g(dimensions)f(of)h(the)0 4471 y(image)d(m)m(ust)f(b)s(e)f(sp)s -(eci\014ed)g(in)h(square)g(brac)m(k)m(ets)h(follo)m(wing)g(the)f -(\014lename)g(\(e.g.)41 b(ra)m(w\014le.dat[ib512,512]\).)j(The)0 -4584 y(\014rst)30 b(c)m(haracter)i(\(case)f(insensitiv)m(e\))h -(de\014nes)e(the)g(datat)m(yp)s(e)h(of)g(the)g(arra)m(y:)239 -4810 y Fe(b)429 b(8-bit)46 b(unsigned)g(byte)239 4923 -y(i)381 b(16-bit)46 b(signed)g(integer)239 5036 y(u)381 -b(16-bit)46 b(unsigned)g(integer)239 5149 y(j)381 b(32-bit)46 -b(signed)g(integer)239 5262 y(r)h(or)g(f)143 b(32-bit)46 -b(floating)g(point)239 5375 y(d)381 b(64-bit)46 b(floating)g(point)0 -5601 y Fi(An)40 b(optional)h(second)f(c)m(haracter)i(sp)s(eci\014es)e -(the)h(b)m(yte)f(order)g(of)g(the)h(arra)m(y)g(v)-5 b(alues:)60 -b(b)40 b(or)g(B)h(indicates)g(big)0 5714 y(endian)f(\(as)h(in)f(FITS)f -(\014les)i(and)f(the)g(nativ)m(e)i(format)e(of)h(SUN)f(UNIX)h(w)m -(orkstations)g(and)f(Mac)i(PCs\))e(and)p eop end -%%Page: 88 94 -TeXDict begin 88 93 bop 0 299 a Fi(88)1618 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fi(l)41 b(or)g(L)g(indicates)g(little)i(endian)e(\(nativ)m(e)h -(format)g(of)f(DEC)f(OSF)h(w)m(orkstations)h(and)e(IBM)i(PCs\).)72 -b(If)40 b(this)0 668 y(c)m(haracter)32 b(is)e(omitted)i(then)e(the)g -(arra)m(y)h(is)g(assumed)e(to)i(ha)m(v)m(e)h(the)f(nativ)m(e)g(b)m(yte) -g(order)f(of)h(the)f(lo)s(cal)i(mac)m(hine.)0 781 y(These)d(datat)m(yp) -s(e)h(c)m(haracters)h(are)e(then)g(follo)m(w)m(ed)i(b)m(y)e(a)h(series) -f(of)g(one)h(or)f(more)g(in)m(teger)i(v)-5 b(alues)29 -b(separated)h(b)m(y)0 894 y(commas)h(whic)m(h)g(de\014ne)e(the)i(size)h -(of)e(eac)m(h)i(dimension)e(of)h(the)g(ra)m(w)f(arra)m(y)-8 -b(.)43 b(Arra)m(ys)30 b(with)h(up)e(to)j(5)f(dimensions)0 -1007 y(are)f(curren)m(tly)g(supp)s(orted.)38 b(Finally)-8 -b(,)32 b(a)e(b)m(yte)g(o\013set)g(to)h(the)e(p)s(osition)h(of)g(the)g -(\014rst)e(pixel)i(in)g(the)f(data)i(\014le)e(ma)m(y)0 -1120 y(b)s(e)d(sp)s(eci\014ed)g(b)m(y)h(separating)h(it)f(with)g(a)g -(':')39 b(from)27 b(the)g(last)g(dimension)g(v)-5 b(alue.)40 -b(If)26 b(omitted,)j(it)e(is)g(assumed)f(that)0 1233 -y(the)35 b(o\013set)h(=)f(0.)54 b(This)35 b(parameter)g(ma)m(y)h(b)s(e) -e(used)g(to)i(skip)e(o)m(v)m(er)i(an)m(y)g(header)e(information)i(in)e -(the)h(\014le)g(that)0 1346 y(precedes)30 b(the)h(binary)f(data.)41 -b(F)-8 b(urther)30 b(examples:)95 1603 y Fe(raw.dat[b10000])521 -b(1-dimensional)45 b(10000)h(pixel)g(byte)h(array)95 -1715 y(raw.dat[rb400,400,12])233 b(3-dimensional)45 b(floating)g(point) -h(big-endian)f(array)95 1828 y(img.fits[ib512,512:2880])89 -b(reads)47 b(the)g(512)g(x)g(512)g(short)f(integer)g(array)g(in)1336 -1941 y(a)i(FITS)e(file,)h(skipping)e(over)i(the)g(2880)g(byte)f(header) -0 2198 y Fi(One)25 b(sp)s(ecial)g(case)h(of)f(input)f(\014le)h(is)g -(where)g(the)g(\014lename)g(=)g(`-')h(\(a)f(dash)g(or)g(min)m(us)f -(sign\))h(or)g('stdin')g(or)g('stdout',)0 2311 y(whic)m(h)d -(signi\014es)h(that)h(the)f(input)e(\014le)i(is)g(to)h(b)s(e)e(read)g -(from)h(the)g(stdin)f(stream,)j(or)e(written)f(to)i(the)f(stdout)g -(stream)0 2424 y(if)34 b(a)g(new)g(output)f(\014le)h(is)g(b)s(eing)g -(created.)52 b(In)33 b(the)h(case)h(of)f(reading)h(from)e(stdin,)h -(CFITSIO)f(\014rst)g(copies)i(the)0 2537 y(whole)g(stream)h(in)m(to)g -(a)f(temp)s(orary)g(FITS)f(\014le)i(\(in)f(memory)g(or)g(on)g(disk\),)h -(and)f(subsequen)m(t)f(reading)h(of)h(the)0 2650 y(FITS)c(\014le)h(o)s -(ccurs)g(in)f(this)h(cop)m(y)-8 b(.)49 b(When)33 b(writing)g(to)g -(stdout,)h(CFITSIO)d(\014rst)h(constructs)h(the)g(whole)g(\014le)g(in)0 -2763 y(memory)h(\(since)i(random)d(access)j(is)e(required\),)i(then)e -(\015ushes)f(it)i(out)g(to)g(the)f(stdout)h(stream)g(when)e(the)i -(\014le)0 2876 y(is)30 b(closed.)42 b(In)29 b(addition,)i(if)f(the)g -(output)g(\014lename)g(=)g('-.gz')i(or)e('stdout.gz')h(then)f(it)h -(will)f(b)s(e)g(gzip)g(compressed)0 2989 y(b)s(efore)g(b)s(eing)g -(written)g(to)h(stdout.)0 3149 y(This)25 b(abilit)m(y)j(to)e(read)g -(and)f(write)h(on)g(the)g(stdin)g(and)f(stdout)h(steams)g(allo)m(ws)i -(FITS)d(\014les)h(to)g(b)s(e)g(pip)s(ed)e(b)s(et)m(w)m(een)0 -3262 y(tasks)42 b(in)f(memory)g(rather)g(than)h(ha)m(ving)g(to)g -(create)h(temp)s(orary)e(in)m(termediate)i(FITS)d(\014les)i(on)f(disk.) -73 b(F)-8 b(or)0 3375 y(example)28 b(if)e(task1)i(creates)h(an)e -(output)f(FITS)g(\014le,)i(and)f(task2)g(reads)g(an)g(input)f(FITS)g -(\014le,)i(the)f(FITS)f(\014le)h(ma)m(y)0 3487 y(b)s(e)j(pip)s(ed)f(b)s -(et)m(w)m(een)i(the)f(2)h(tasks)g(b)m(y)f(sp)s(ecifying)143 -3744 y Fe(task1)47 b(-)g(|)g(task2)g(-)0 4001 y Fi(where)30 -b(the)h(v)m(ertical)i(bar)e(is)f(the)h(Unix)g(piping)f(sym)m(b)s(ol.)42 -b(This)30 b(assumes)g(that)i(the)f(2)g(tasks)g(read)g(the)g(name)g(of)0 -4114 y(the)g(FITS)e(\014le)i(o\013)f(of)h(the)g(command)f(line.)0 -4448 y Fd(8.4)135 b(Output)45 b(File)g(Name)h(when)f(Op)t(ening)g(an)g -(Existing)h(File)0 4698 y Fi(An)36 b(optional)i(output)e(\014lename)h -(ma)m(y)h(b)s(e)e(sp)s(eci\014ed)g(in)g(paren)m(theses)h(immediately)h -(follo)m(wing)g(the)f(base)g(\014le)0 4811 y(name)28 -b(to)h(b)s(e)f(op)s(ened.)39 b(This)28 b(is)g(mainly)g(useful)g(in)g -(those)g(cases)i(where)d(CFITSIO)g(creates)j(a)e(temp)s(orary)g(cop)m -(y)0 4924 y(of)i(the)f(input)g(FITS)f(\014le)i(b)s(efore)f(it)h(is)f -(op)s(ened)g(and)f(passed)h(to)h(the)g(application)h(program.)40 -b(This)28 b(happ)s(ens)g(b)m(y)0 5036 y(default)i(when)g(op)s(ening)g -(a)g(net)m(w)m(ork)h(FTP)g(or)f(HTTP-t)m(yp)s(e)g(\014le,)h(when)e -(reading)h(a)h(compressed)f(FITS)g(\014le)g(on)0 5149 -y(a)36 b(lo)s(cal)h(disk,)g(when)e(reading)h(from)g(the)g(stdin)f -(stream,)j(or)d(when)g(a)i(column)e(\014lter,)j(ro)m(w)e(\014lter,)h -(or)f(binning)0 5262 y(sp)s(eci\014er)29 b(is)g(included)g(as)h(part)f -(of)g(the)h(input)f(\014le)g(sp)s(eci\014cation.)41 b(By)30 -b(default)g(this)f(temp)s(orary)g(\014le)g(is)h(created)0 -5375 y(in)g(memory)-8 b(.)41 b(If)29 b(there)h(is)g(not)g(enough)g -(memory)g(to)h(create)g(the)g(\014le)f(cop)m(y)-8 b(,)31 -b(then)f(CFITSIO)e(will)i(exit)h(with)f(an)0 5488 y(error.)45 -b(In)32 b(these)g(cases)h(one)g(can)f(force)h(a)f(p)s(ermanen)m(t)g -(\014le)g(to)h(b)s(e)e(created)i(on)f(disk,)g(instead)h(of)f(a)g(temp)s -(orary)0 5601 y(\014le)38 b(in)f(memory)-8 b(,)40 b(b)m(y)d(supplying)f -(the)i(name)g(in)f(paren)m(theses)h(immediately)h(follo)m(wing)g(the)e -(base)h(\014le)g(name.)0 5714 y(The)30 b(output)g(\014lename)g(can)h -(include)f(the)h(')10 b(!')41 b(clobb)s(er)30 b(\015ag.)p -eop end -%%Page: 89 95 -TeXDict begin 89 94 bop 0 299 a Fg(8.4.)72 b(OUTPUT)30 -b(FILE)g(NAME)h(WHEN)g(OPENING)f(AN)h(EXISTING)e(FILE)967 -b Fi(89)0 555 y(Th)m(us,)48 b(if)d(the)g(input)f(\014lename)h(to)g -(CFITSIO)f(is:)70 b Fe(file1.fits.gz\(file2.fit)o(s\))39 -b Fi(then)44 b(CFITSIO)g(will)0 668 y(uncompress)39 b -(`\014le1.\014ts.gz')j(in)m(to)f(the)f(lo)s(cal)h(disk)e(\014le)h -(`\014le2.\014ts')h(b)s(efore)f(op)s(ening)f(it.)70 b(CFITSIO)38 -b(do)s(es)i(not)0 781 y(automatically)33 b(delete)f(the)e(output)g -(\014le,)h(so)g(it)g(will)f(still)i(exist)f(after)g(the)f(application)i -(program)e(exits.)0 941 y(In)35 b(some)i(cases,)h(sev)m(eral)f -(di\013eren)m(t)g(temp)s(orary)e(FITS)h(\014les)g(will)g(b)s(e)f -(created)i(in)f(sequence,)i(for)e(instance,)i(if)0 1054 -y(one)f(op)s(ens)g(a)g(remote)h(\014le)f(using)g(FTP)-8 -b(,)37 b(then)g(\014lters)g(ro)m(ws)g(in)g(a)h(binary)e(table)i -(extension,)i(then)c(create)j(an)0 1167 y(image)f(b)m(y)f(binning)f(a)h -(pair)g(of)g(columns.)60 b(In)36 b(this)h(case,)j(the)d(remote)h -(\014le)f(will)g(b)s(e)f(copied)h(to)h(a)f(temp)s(orary)0 -1280 y(lo)s(cal)j(\014le,)h(then)d(a)h(second)f(temp)s(orary)h(\014le)f -(will)h(b)s(e)f(created)i(con)m(taining)g(the)e(\014ltered)h(ro)m(ws)f -(of)h(the)g(table,)0 1393 y(and)c(\014nally)g(a)h(third)e(temp)s(orary) -h(\014le)h(con)m(taining)g(the)g(binned)e(image)i(will)g(b)s(e)f -(created.)57 b(In)34 b(cases)i(lik)m(e)h(this)0 1506 -y(where)28 b(m)m(ultiple)h(\014les)f(are)h(created,)h(the)e(out\014le)h -(sp)s(eci\014er)f(will)g(b)s(e)g(in)m(terpreted)h(the)f(name)g(of)h -(the)f(\014nal)g(\014le)h(as)0 1619 y(describ)s(ed)g(b)s(elo)m(w,)i(in) -f(descending)g(priorit)m(y:)136 1869 y Fc(\017)46 b Fi(as)29 -b(the)g(name)g(of)g(the)g(\014nal)f(image)i(\014le)f(if)f(an)h(image)h -(within)e(a)h(single)g(binary)f(table)i(cell)g(is)e(op)s(ened)g(or)h -(if)227 1982 y(an)i(image)g(is)g(created)g(b)m(y)f(binning)g(a)g(table) -i(column.)136 2167 y Fc(\017)46 b Fi(as)33 b(the)f(name)h(of)f(the)h -(\014le)f(con)m(taining)i(the)e(\014ltered)g(table)i(if)e(a)h(column)f -(\014lter)g(and/or)g(a)h(ro)m(w)f(\014lter)h(are)227 -2280 y(sp)s(eci\014ed.)136 2464 y Fc(\017)46 b Fi(as)31 -b(the)f(name)h(of)f(the)h(lo)s(cal)h(cop)m(y)f(of)f(the)h(remote)g(FTP) -f(or)h(HTTP)e(\014le.)136 2649 y Fc(\017)46 b Fi(as)31 -b(the)g(name)g(of)g(the)f(uncompressed)g(v)m(ersion)h(of)g(the)f(FITS)g -(\014le,)h(if)g(a)g(compressed)f(FITS)g(\014le)h(on)g(lo)s(cal)227 -2762 y(disk)f(has)g(b)s(een)g(op)s(ened.)136 2946 y Fc(\017)46 -b Fi(otherwise,)31 b(the)g(output)f(\014lename)g(is)h(ignored.)0 -3197 y(The)e(output)f(\014le)h(sp)s(eci\014er)g(is)g(useful)f(when)g -(reading)h(FTP)g(or)g(HTTP-t)m(yp)s(e)g(FITS)f(\014les)h(since)g(it)h -(can)f(b)s(e)g(used)0 3310 y(to)34 b(create)i(a)e(lo)s(cal)h(disk)e -(cop)m(y)i(of)f(the)g(\014le)f(that)i(can)f(b)s(e)f(reused)g(in)g(the)h -(future.)50 b(If)33 b(the)h(output)g(\014le)f(name)h(=)0 -3423 y(`*')i(then)e(a)i(lo)s(cal)g(\014le)f(with)g(the)g(same)g(name)g -(as)g(the)h(net)m(w)m(ork)f(\014le)g(will)h(b)s(e)e(created.)56 -b(Note)36 b(that)f(CFITSIO)0 3535 y(will)30 b(b)s(eha)m(v)m(e)g -(di\013eren)m(tly)h(dep)s(ending)d(on)i(whether)f(the)h(remote)g -(\014le)g(is)g(compressed)f(or)h(not)g(as)g(sho)m(wn)f(b)m(y)h(the)0 -3648 y(follo)m(wing)i(examples:)136 3876 y Fc(\017)46 -b Fi(`ftp://remote.mac)m(hine/tmp/m)m(y\014le.\014ts.gz\(*\)')k(-)43 -b(the)g(remote)h(compressed)f(\014le)g(is)g(copied)h(to)g(the)227 -3988 y(lo)s(cal)26 b(compressed)e(\014le)g(`m)m(y\014le.\014ts.gz',)k -(whic)m(h)c(is)g(then)h(uncompressed)e(in)h(lo)s(cal)h(memory)f(b)s -(efore)g(b)s(eing)227 4101 y(op)s(ened)30 b(and)g(passed)g(to)h(the)f -(application)i(program.)136 4286 y Fc(\017)46 b Fi(`ftp://remote.mac)m -(hine/tmp/m)m(y\014le.\014ts.gz\(m)m(y\014le.\014ts\)')d(-)37 -b(the)g(remote)g(compressed)f(\014le)h(is)f(copied)227 -4399 y(and)h(uncompressed)g(in)m(to)h(the)g(lo)s(cal)h(\014le)f(`m)m -(y\014le.\014ts'.)64 b(This)36 b(example)j(requires)e(less)h(lo)s(cal)h -(memory)227 4512 y(than)30 b(the)h(previous)f(example)h(since)g(the)f -(\014le)h(is)f(uncompressed)f(on)h(disk)g(instead)h(of)f(in)h(memory)-8 -b(.)136 4696 y Fc(\017)46 b Fi(`ftp://remote.mac)m(hine/tmp/m)m -(y\014le.\014ts\(m)m(y\014le.\014ts.gz\)')28 b(-)21 b(this)g(will)h -(usually)f(pro)s(duce)f(an)h(error)g(since)227 4809 y(CFITSIO)29 -b(itself)i(cannot)g(compress)f(\014les.)0 5036 y(The)36 -b(exact)i(b)s(eha)m(vior)e(of)h(CFITSIO)e(in)h(the)h(latter)g(case)h -(dep)s(ends)c(on)j(the)f(t)m(yp)s(e)h(of)g(ftp)f(serv)m(er)g(running)f -(on)0 5149 y(the)c(remote)g(mac)m(hine)g(and)f(ho)m(w)g(it)h(is)f -(con\014gured.)40 b(In)30 b(some)h(cases,)g(if)f(the)h(\014le)f(`m)m -(y\014le.\014ts.gz')j(exists)e(on)f(the)0 5262 y(remote)38 -b(mac)m(hine,)h(then)e(the)g(serv)m(er)g(will)h(cop)m(y)f(it)h(to)f -(the)h(lo)s(cal)g(mac)m(hine.)61 b(In)36 b(other)h(cases)h(the)f(ftp)g -(serv)m(er)0 5375 y(will)f(automatically)j(create)e(and)f(transmit)g(a) -g(compressed)g(v)m(ersion)g(of)g(the)g(\014le)g(if)g(only)g(the)g -(uncompressed)0 5488 y(v)m(ersion)27 b(exists.)41 b(This)26 -b(can)h(get)h(rather)f(confusing,)h(so)f(users)f(should)g(use)h(a)g -(certain)h(amoun)m(t)g(of)f(caution)h(when)0 5601 y(using)34 -b(the)h(output)f(\014le)h(sp)s(eci\014er)f(with)h(FTP)f(or)h(HTTP)f -(\014le)h(t)m(yp)s(es,)h(to)f(mak)m(e)h(sure)e(they)h(get)h(the)f(b)s -(eha)m(vior)0 5714 y(that)c(they)g(exp)s(ect.)p eop end -%%Page: 90 96 -TeXDict begin 90 95 bop 0 299 a Fi(90)1618 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fd(8.5)135 b(T)-11 b(emplate)46 b(File)g(Name)f(when)g(Creating)h -(a)g(New)f(File)0 808 y Fi(When)38 b(a)h(new)f(FITS)g(\014le)h(is)g -(created)g(with)g(a)f(call)i(to)g(\014ts)p 2101 808 28 -4 v 32 w(create)p 2369 808 V 35 w(\014le,)g(the)f(name)g(of)g(a)g -(template)h(\014le)e(ma)m(y)0 921 y(b)s(e)h(supplied)g(in)h(paren)m -(theses)g(immediately)h(follo)m(wing)g(the)g(name)f(of)g(the)g(new)f -(\014le)h(to)h(b)s(e)e(created.)71 b(This)0 1034 y(template)27 -b(is)e(used)g(to)h(de\014ne)f(the)h(structure)f(of)h(one)f(or)h(more)g -(HDUs)g(in)f(the)h(new)f(\014le.)39 b(The)25 b(template)i(\014le)e(ma)m -(y)0 1147 y(b)s(e)32 b(another)h(FITS)f(\014le,)i(in)f(whic)m(h)f(case) -i(the)f(newly)g(created)h(\014le)f(will)g(ha)m(v)m(e)h(exactly)h(the)e -(same)g(k)m(eyw)m(ords)g(in)0 1260 y(eac)m(h)25 b(HDU)g(as)g(in)f(the)g -(template)i(FITS)d(\014le,)j(but)d(all)j(the)e(data)h(units)e(will)i(b) -s(e)f(\014lled)g(with)f(zeros.)40 b(The)24 b(template)0 -1373 y(\014le)i(ma)m(y)h(also)g(b)s(e)e(an)h(ASCI)s(I)e(text)j(\014le,) -g(where)f(eac)m(h)h(line)f(\(in)g(general\))i(describ)s(es)d(one)h -(FITS)f(k)m(eyw)m(ord)i(record.)0 1486 y(The)j(format)h(of)f(the)h -(ASCI)s(I)e(template)i(\014le)g(is)f(describ)s(ed)f(b)s(elo)m(w.)0 -1833 y Fd(8.6)135 b(Image)46 b(Tile-Compression)h(Sp)t(eci\014cation)0 -2086 y Fi(When)28 b(sp)s(ecifying)g(the)h(name)g(of)f(the)h(output)f -(FITS)g(\014le)g(to)h(b)s(e)f(created,)i(the)f(user)f(can)g(indicate)i -(that)f(images)0 2198 y(should)d(b)s(e)h(written)g(in)g -(tile-compressed)h(format)g(\(see)g(section)g(5.5,)h(\\Primary)e(Arra)m -(y)h(or)f(IMA)m(GE)h(Extension)0 2311 y(I/O)f(Routines"\))i(b)m(y)e -(enclosing)h(the)g(compression)f(parameters)h(in)f(square)g(brac)m(k)m -(ets)i(follo)m(wing)g(the)f(ro)s(ot)f(disk)0 2424 y(\014le)j(name.)41 -b(Here)31 b(are)g(some)g(examples)g(of)f(the)h(syn)m(tax)g(for)f(sp)s -(ecifying)g(tile-compressed)i(output)e(images:)191 2695 -y Fe(myfile.fit[compress])185 b(-)48 b(use)f(Rice)f(algorithm)g(and)h -(default)e(tile)i(size)191 2921 y(myfile.fit[compress)42 -b(GZIP])47 b(-)g(use)g(the)g(specified)e(compression)g(algorithm;)191 -3034 y(myfile.fit[compress)d(Rice])238 b(only)46 b(the)h(first)g -(letter)f(of)h(the)g(algorithm)191 3147 y(myfile.fit[compress)42 -b(PLIO])238 b(name)46 b(is)i(required.)191 3373 y(myfile.fit[compress) -42 b(Rice)47 b(100,100])141 b(-)48 b(use)e(100)h(x)h(100)f(pixel)f -(tile)h(size)191 3486 y(myfile.fit[compress)42 b(Rice)47 -b(100,100;2])e(-)j(as)f(above,)f(and)h(use)g(noisebits)e(=)i(2)0 -3833 y Fd(8.7)135 b(HDU)46 b(Lo)t(cation)f(Sp)t(eci\014cation)0 -4086 y Fi(The)c(optional)h(HDU)h(lo)s(cation)g(sp)s(eci\014er)d -(de\014nes)h(whic)m(h)g(HDU)h(\(Header-Data)i(Unit,)h(also)d(kno)m(wn)f -(as)h(an)0 4199 y(`extension'\))36 b(within)d(the)i(FITS)e(\014le)h(to) -h(initially)h(op)s(en.)51 b(It)34 b(m)m(ust)g(immediately)i(follo)m(w)f -(the)f(base)h(\014le)f(name)0 4312 y(\(or)g(the)g(output)g(\014le)g -(name)f(if)h(presen)m(t\).)52 b(If)33 b(it)h(is)g(not)g(sp)s(eci\014ed) -g(then)f(the)h(\014rst)f(HDU)i(\(the)f(primary)f(arra)m(y\))0 -4425 y(is)g(op)s(ened.)46 b(The)32 b(HDU)h(lo)s(cation)h(sp)s -(eci\014er)e(is)h(required)f(if)g(the)h(colFilter,)i(ro)m(wFilter,)g -(or)e(binSp)s(ec)e(sp)s(eci\014ers)0 4538 y(are)f(presen)m(t,)f(b)s -(ecause)h(the)f(primary)f(arra)m(y)i(is)f(not)h(a)f(v)-5 -b(alid)30 b(HDU)g(for)f(these)g(op)s(erations.)41 b(The)29 -b(HDU)h(ma)m(y)g(b)s(e)0 4650 y(sp)s(eci\014ed)e(either)i(b)m(y)e -(absolute)i(p)s(osition)f(n)m(um)m(b)s(er,)f(starting)i(with)e(0)i(for) -e(the)h(primary)f(arra)m(y)-8 b(,)31 b(or)e(b)m(y)f(reference)0 -4763 y(to)h(the)g(HDU)g(name,)g(and)f(optionally)-8 b(,)31 -b(the)e(v)m(ersion)g(n)m(um)m(b)s(er)e(and)h(the)h(HDU)g(t)m(yp)s(e)g -(of)f(the)h(desired)f(extension.)0 4876 y(The)k(lo)s(cation)h(of)f(an)g -(image)i(within)d(a)i(single)f(cell)i(of)e(a)g(binary)g(table)h(ma)m(y) -f(also)h(b)s(e)f(sp)s(eci\014ed,)g(as)g(describ)s(ed)0 -4989 y(b)s(elo)m(w.)0 5149 y(The)26 b(absolute)h(p)s(osition)f(of)g -(the)h(extension)g(is)f(sp)s(eci\014ed)f(either)i(b)m(y)f(enclosed)h -(the)g(n)m(um)m(b)s(er)e(in)h(square)f(brac)m(k)m(ets)0 -5262 y(\(e.g.,)k(`[1]')g(=)d(the)h(\014rst)f(extension)h(follo)m(wing)i -(the)e(primary)e(arra)m(y\))j(or)f(b)m(y)f(preceded)h(the)g(n)m(um)m(b) -s(er)e(with)i(a)g(plus)0 5375 y(sign)37 b(\(`+1'\).)63 -b(T)-8 b(o)38 b(sp)s(ecify)f(the)g(HDU)h(b)m(y)g(name,)h(giv)m(e)g(the) -e(name)h(of)f(the)h(desired)f(HDU)h(\(the)f(v)-5 b(alue)38 -b(of)g(the)0 5488 y(EXTNAME)e(or)g(HDUNAME)h(k)m(eyw)m(ord\))g(and)f -(optionally)h(the)f(extension)h(v)m(ersion)f(n)m(um)m(b)s(er)f(\(v)-5 -b(alue)37 b(of)f(the)0 5601 y(EXTVER)27 b(k)m(eyw)m(ord\))i(and)e(the)h -(extension)h(t)m(yp)s(e)e(\(v)-5 b(alue)29 b(of)f(the)g(XTENSION)f(k)m -(eyw)m(ord:)40 b(IMA)m(GE,)29 b(ASCI)s(I)d(or)0 5714 -y(T)-8 b(ABLE,)36 b(or)f(BINT)-8 b(ABLE\),)36 b(separated)f(b)m(y)g -(commas)h(and)e(all)i(enclosed)g(in)f(square)g(brac)m(k)m(ets.)56 -b(If)34 b(the)h(v)-5 b(alue)p eop end -%%Page: 91 97 -TeXDict begin 91 96 bop 0 299 a Fg(8.8.)72 b(IMA)m(GE)31 -b(SECTION)2835 b Fi(91)0 555 y(of)34 b(EXTVER)f(and)f(XTENSION)h(are)h -(not)f(sp)s(eci\014ed,)h(then)f(the)h(\014rst)e(extension)j(with)e(the) -g(correct)i(v)-5 b(alue)34 b(of)0 668 y(EXTNAME)39 b(is)g(op)s(ened.)67 -b(The)38 b(extension)i(name)f(and)f(t)m(yp)s(e)i(are)f(not)h(case)g -(sensitiv)m(e,)j(and)38 b(the)h(extension)0 781 y(t)m(yp)s(e)29 -b(ma)m(y)g(b)s(e)f(abbreviated)h(to)g(a)g(single)g(letter)h(\(e.g.,)h -(I)d(=)g(IMA)m(GE)i(extension)f(or)f(primary)g(arra)m(y)-8 -b(,)30 b(A)f(or)f(T)g(=)0 894 y(ASCI)s(I)d(table)i(extension,)h(and)e -(B)h(=)f(binary)g(table)h(BINT)-8 b(ABLE)27 b(extension\).)41 -b(If)26 b(the)g(HDU)h(lo)s(cation)i(sp)s(eci\014er)0 -1007 y(is)h(equal)h(to)g(`[PRIMAR)-8 b(Y]')32 b(or)f(`[P]',)g(then)f -(the)h(primary)e(arra)m(y)i(\(the)g(\014rst)f(HDU\))h(will)g(b)s(e)f -(op)s(ened.)0 1167 y(FITS)k(images)i(are)f(most)h(commonly)f(stored)g -(in)g(the)g(primary)f(arra)m(y)h(or)g(an)g(image)h(extension,)h(but)d -(images)0 1280 y(can)d(also)h(b)s(e)e(stored)h(as)h(a)f(v)m(ector)h(in) -f(a)g(single)h(cell)g(of)f(a)h(binary)e(table)i(\(i.e.)43 -b(eac)m(h)32 b(ro)m(w)f(of)g(the)h(v)m(ector)g(column)0 -1393 y(con)m(tains)d(a)g(di\013eren)m(t)f(image\).)42 -b(Suc)m(h)27 b(an)h(image)i(can)e(b)s(e)g(op)s(ened)f(with)h(CFITSIO)e -(b)m(y)i(sp)s(ecifying)g(the)g(desired)0 1506 y(column)k(name)g(and)f -(the)h(ro)m(w)g(n)m(um)m(b)s(er)f(after)h(the)g(binary)f(table)i(HDU)g -(sp)s(eci\014er)e(as)h(sho)m(wn)g(in)f(the)h(follo)m(wing)0 -1619 y(examples.)71 b(The)40 b(column)g(name)h(is)f(separated)h(from)f -(the)h(HDU)g(sp)s(eci\014er)f(b)m(y)g(a)h(semicolon)g(and)f(the)h(ro)m -(w)0 1732 y(n)m(um)m(b)s(er)29 b(is)h(enclosed)h(in)e(paren)m(theses.) -41 b(In)30 b(this)g(case)h(CFITSIO)d(copies)j(the)f(image)i(from)d(the) -i(table)g(cell)g(in)m(to)0 1844 y(a)h(temp)s(orary)e(primary)h(arra)m -(y)g(b)s(efore)g(it)h(is)f(op)s(ened.)43 b(The)30 b(application)j -(program)e(then)g(just)g(sees)g(the)h(image)0 1957 y(in)i(the)h -(primary)e(arra)m(y)-8 b(,)37 b(without)d(an)m(y)h(extensions.)53 -b(The)34 b(particular)g(ro)m(w)h(to)g(b)s(e)e(op)s(ened)h(ma)m(y)h(b)s -(e)f(sp)s(eci\014ed)0 2070 y(either)28 b(b)m(y)f(giving)h(an)f -(absolute)h(in)m(teger)h(ro)m(w)f(n)m(um)m(b)s(er)e(\(starting)i(with)f -(1)h(for)f(the)g(\014rst)g(ro)m(w\),)i(or)e(b)m(y)g(sp)s(ecifying)0 -2183 y(a)33 b(b)s(o)s(olean)f(expression)g(that)h(ev)-5 -b(aluates)34 b(to)f(TR)m(UE)g(for)f(the)g(desired)g(ro)m(w.)47 -b(The)32 b(\014rst)f(ro)m(w)i(that)g(satis\014es)g(the)0 -2296 y(expression)28 b(will)g(b)s(e)g(used.)39 b(The)28 -b(ro)m(w)g(selection)i(expression)e(has)g(the)g(same)g(syn)m(tax)h(as)f -(describ)s(ed)f(in)h(the)g(Ro)m(w)0 2409 y(Filter)k(Sp)s(eci\014er)d -(section,)j(b)s(elo)m(w.)0 2569 y(Examples:)143 2811 -y Fe(myfile.fits[3])44 b(-)k(open)e(the)h(3rd)g(HDU)g(following)e(the)i -(primary)f(array)143 2924 y(myfile.fits+3)92 b(-)48 b(same)e(as)h -(above,)f(but)h(using)g(the)g(FTOOLS-style)d(notation)143 -3037 y(myfile.fits[EVENTS])f(-)k(open)g(the)g(extension)e(that)i(has)g -(EXTNAME)e(=)j('EVENTS')143 3150 y(myfile.fits[EVENTS,)43 -b(2])95 b(-)47 b(same)g(as)g(above,)f(but)h(also)g(requires)e(EXTVER)h -(=)i(2)143 3263 y(myfile.fits[events,2,b])42 b(-)47 b(same,)f(but)h -(also)g(requires)f(XTENSION)f(=)j('BINTABLE')143 3376 -y(myfile.fits[3;)c(images\(17\)])h(-)i(opens)g(the)g(image)f(in)h(row)g -(17)g(of)g(the)g('images')1527 3489 y(column)f(in)i(the)e(3rd)h -(extension)f(of)h(the)g(file.)143 3602 y(myfile.fits[3;)d -(images\(exposure)g(>)j(100\)])g(-)g(as)g(above,)f(but)h(opens)g(the)f -(image)907 3714 y(in)h(the)g(first)f(row)h(that)g(has)g(an)g -('exposure')e(column)h(value)907 3827 y(greater)g(than)g(100.)0 -4158 y Fd(8.8)135 b(Image)46 b(Section)0 4408 y Fi(A)41 -b(virtual)g(\014le)f(con)m(taining)i(a)f(rectangular)h(subsection)e(of) -h(an)g(image)g(can)g(b)s(e)f(extracted)i(and)e(op)s(ened)g(b)m(y)0 -4521 y(sp)s(ecifying)32 b(the)h(range)g(of)g(pixels)g(\(start:end\))g -(along)h(eac)m(h)g(axis)f(to)g(b)s(e)f(extracted)i(from)e(the)h -(original)g(image.)0 4634 y(One)d(can)h(also)h(sp)s(ecify)e(an)h -(optional)h(pixel)f(incremen)m(t)g(\(start:end:step\))h(for)f(eac)m(h)h -(axis)f(of)g(the)g(input)e(image.)0 4747 y(A)f(pixel)f(step)h(=)f(1)h -(will)g(b)s(e)f(assumed)f(if)i(it)g(is)f(not)h(sp)s(eci\014ed.)39 -b(If)27 b(the)h(start)g(pixel)g(is)f(larger)i(then)e(the)h(end)e -(pixel,)0 4860 y(then)32 b(the)g(image)h(will)f(b)s(e)f(\015ipp)s(ed)f -(\(pro)s(ducing)h(a)h(mirror)g(image\))h(along)g(that)f(dimension.)45 -b(An)32 b(asterisk,)h('*',)0 4973 y(ma)m(y)39 b(b)s(e)e(used)h(to)h(sp) -s(ecify)f(the)g(en)m(tire)h(range)g(of)f(an)h(axis,)i(and)c('-*')j -(will)e(\015ip)g(the)g(en)m(tire)h(axis.)65 b(The)38 -b(input)0 5086 y(image)31 b(can)f(b)s(e)f(in)g(the)h(primary)f(arra)m -(y)-8 b(,)31 b(in)e(an)g(image)i(extension,)g(or)f(con)m(tained)g(in)g -(a)g(v)m(ector)h(cell)g(of)f(a)g(binary)0 5199 y(table.)40 -b(In)25 b(the)h(later)h(2)f(cases)h(the)f(extension)h(name)f(or)f(n)m -(um)m(b)s(er)g(m)m(ust)h(b)s(e)f(sp)s(eci\014ed)g(b)s(efore)h(the)g -(image)h(section)0 5312 y(sp)s(eci\014er.)0 5472 y(Examples:)95 -5714 y Fe(myfile.fits[1:512:2,)43 b(2:512:2])i(-)95 b(open)47 -b(a)h(256x256)d(pixel)i(image)p eop end -%%Page: 92 98 -TeXDict begin 92 97 bop 0 299 a Fi(92)1618 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)668 -555 y Fe(consisting)45 b(of)i(the)g(odd)g(numbered)f(columns)g(\(1st)g -(axis\))h(and)668 668 y(the)g(even)g(numbered)e(rows)i(\(2nd)g(axis\))f -(of)h(the)g(image)f(in)i(the)668 781 y(primary)e(array)g(of)i(the)e -(file.)95 1007 y(myfile.fits[*,)e(512:256])i(-)h(open)g(an)g(image)g -(consisting)e(of)i(all)g(the)g(columns)668 1120 y(in)g(the)g(input)g -(image,)f(but)h(only)f(rows)h(256)g(through)f(512.)668 -1233 y(The)h(image)f(will)h(be)g(flipped)f(along)g(the)h(2nd)g(axis)g -(since)668 1346 y(the)g(starting)f(pixel)g(is)h(greater)f(than)h(the)g -(ending)f(pixel.)95 1571 y(myfile.fits[*:2,)e(512:256:2])h(-)i(same)g -(as)g(above)f(but)h(keeping)f(only)668 1684 y(every)h(other)f(row)h -(and)g(column)f(in)h(the)g(input)f(image.)95 1910 y(myfile.fits[-*,)e -(*])j(-)h(copy)e(the)h(entire)f(image,)g(flipping)g(it)h(along)668 -2023 y(the)g(first)f(axis.)95 2249 y(myfile.fits[3][1:256,1:256)o(])c -(-)47 b(opens)g(a)g(subsection)e(of)i(the)g(image)g(that)668 -2362 y(is)g(in)h(the)e(3rd)h(extension)f(of)h(the)g(file.)95 -2588 y(myfile.fits[4;)d(images\(12\)][1:10,1:10])e(-)48 -b(open)e(an)h(image)g(consisting)286 2700 y(of)h(the)e(first)h(10)g -(pixels)f(in)h(both)g(dimensions.)e(The)i(original)286 -2813 y(image)g(resides)f(in)h(the)g(12th)f(row)h(of)g(the)g('images')f -(vector)286 2926 y(column)g(in)i(the)f(table)f(in)h(the)g(4th)g -(extension)e(of)i(the)g(file.)0 3203 y Fi(When)23 b(CFITSIO)f(op)s(ens) -h(an)g(image)h(section)h(it)f(\014rst)f(creates)h(a)g(temp)s(orary)f -(\014le)h(con)m(taining)h(the)e(image)i(section)0 3315 -y(plus)32 b(a)i(cop)m(y)g(of)g(an)m(y)g(other)f(HDUs)h(in)f(the)h -(\014le.)50 b(This)32 b(temp)s(orary)h(\014le)h(is)f(then)g(op)s(ened)g -(b)m(y)g(the)h(application)0 3428 y(program,)28 b(so)g(it)g(is)f(not)h -(p)s(ossible)f(to)h(write)g(to)g(or)g(mo)s(dify)f(the)g(input)g(\014le) -g(when)g(sp)s(ecifying)g(an)h(image)h(section.)0 3541 -y(Note)39 b(that)f(CFITSIO)e(automatically)k(up)s(dates)d(the)g(w)m -(orld)h(co)s(ordinate)g(system)g(k)m(eyw)m(ords)f(in)g(the)h(header)0 -3654 y(of)33 b(the)h(image)g(section,)h(if)e(they)h(exist,)h(so)e(that) -h(the)f(co)s(ordinate)h(asso)s(ciated)h(with)e(eac)m(h)h(pixel)f(in)g -(the)h(image)0 3767 y(section)e(will)e(b)s(e)g(computed)g(correctly)-8 -b(.)0 4120 y Fd(8.9)135 b(Image)46 b(T)-11 b(ransform)45 -b(Filters)0 4374 y Fi(CFITSIO)33 b(can)h(apply)g(a)h(user-sp)s -(eci\014ed)e(mathematical)j(function)e(to)h(the)g(v)-5 -b(alue)34 b(of)h(ev)m(ery)g(pixel)f(in)g(a)h(FITS)0 4487 -y(image,)29 b(th)m(us)e(creating)h(a)g(new)e(virtual)h(image)i(in)d -(computer)h(memory)g(that)h(is)f(then)f(op)s(ened)h(and)f(read)h(b)m(y) -g(the)0 4600 y(application)32 b(program.)40 b(The)30 -b(original)i(FITS)d(image)j(is)e(not)h(mo)s(di\014ed)e(b)m(y)h(this)h -(pro)s(cess.)0 4760 y(The)20 b(image)j(transformation)e(sp)s(eci\014er) -f(is)h(app)s(ended)e(to)j(the)f(input)f(FITS)h(\014le)g(name)g(and)f -(is)h(enclosed)h(in)e(square)0 4873 y(brac)m(k)m(ets.)42 -b(It)29 b(b)s(egins)f(with)h(the)g(letters)i('PIX')e(to)h(distinguish)e -(it)i(from)e(other)i(t)m(yp)s(es)f(of)g(FITS)f(\014le)h(\014lters)g -(that)0 4986 y(are)36 b(recognized)i(b)m(y)e(CFITSIO.)e(The)i(image)h -(transforming)f(function)f(ma)m(y)i(use)f(an)m(y)g(of)g(the)h -(mathematical)0 5099 y(op)s(erators)44 b(listed)h(in)f(the)h(follo)m -(wing)h('Ro)m(w)f(Filtering)g(Sp)s(eci\014cation')g(section)h(of)e -(this)h(do)s(cumen)m(t.)82 b(Some)0 5212 y(examples)31 -b(of)f(image)i(transform)e(\014lters)g(are:)48 5488 y -Fe([pix)46 b(X)i(*)f(2.0])715 b(-)48 b(multiply)d(each)i(pixel)f(by)h -(2.0)48 5601 y([pix)f(sqrt\(X\)])714 b(-)48 b(take)e(the)h(square)f -(root)h(of)g(each)g(pixel)48 5714 y([pix)f(X)i(+)f(#ZEROPT)571 -b(-)48 b(add)e(the)h(value)g(of)g(the)g(ZEROPT)f(keyword)p -eop end -%%Page: 93 99 -TeXDict begin 93 98 bop 0 299 a Fg(8.9.)72 b(IMA)m(GE)31 -b(TRANSF)m(ORM)g(FIL)-8 b(TERS)2237 b Fi(93)48 555 y -Fe([pix)46 b(X>0)h(?)h(log10\(X\))d(:)j(-99.])e(-)i(if)f(the)g(pixel)f -(value)g(is)i(greater)1480 668 y(than)e(0,)h(compute)f(the)h(base)g(10) -g(log,)1480 781 y(else)f(set)h(the)g(pixel)f(=)i(-99.)0 -1013 y Fi(Use)24 b(the)g(letter)h('X')f(in)f(the)h(expression)g(to)g -(represen)m(t)g(the)g(curren)m(t)f(pixel)h(v)-5 b(alue)24 -b(in)f(the)h(image.)40 b(The)23 b(expression)0 1126 y(is)38 -b(ev)-5 b(aluated)39 b(indep)s(enden)m(tly)e(for)g(eac)m(h)i(pixel)f -(in)g(the)g(image)h(and)e(ma)m(y)h(b)s(e)g(a)g(function)f(of)h(1\))h -(the)f(original)0 1239 y(pixel)32 b(v)-5 b(alue,)32 b(2\))g(the)f(v)-5 -b(alue)32 b(of)f(other)h(pixels)f(in)g(the)g(image)i(at)f(a)f(giv)m(en) -i(relativ)m(e)g(o\013set)f(from)f(the)g(p)s(osition)h(of)0 -1352 y(the)d(pixel)f(that)h(is)g(b)s(eing)f(ev)-5 b(aluated,)30 -b(and)e(3\))h(the)g(v)-5 b(alue)29 b(of)f(an)m(y)h(header)f(k)m(eyw)m -(ords.)41 b(Header)29 b(k)m(eyw)m(ord)g(v)-5 b(alues)0 -1465 y(are)31 b(represen)m(ted)f(b)m(y)g(the)h(name)f(of)h(the)f(k)m -(eyw)m(ord)h(preceded)f(b)m(y)h(the)f('#')h(sign.)0 1625 -y(T)-8 b(o)35 b(access)h(the)f(the)g(v)-5 b(alue)35 b(of)g(adjacen)m(t) -h(pixels)f(in)f(the)h(image,)i(sp)s(ecify)e(the)g(\(1-D\))h(o\013set)g -(from)e(the)h(curren)m(t)0 1738 y(pixel)c(in)f(curly)g(brac)m(k)m(ets.) -42 b(F)-8 b(or)31 b(example)48 1970 y Fe([pix)94 b(\(x{-1})46 -b(+)i(x)f(+)h(x{+1}\))e(/)h(3])0 2202 y Fi(will)25 b(replace)g(eac)m(h) -h(pixel)f(v)-5 b(alue)25 b(with)f(the)h(running)e(mean)i(of)f(the)h(v) --5 b(alues)25 b(of)g(that)g(pixel)g(and)f(it's)h(2)g(neigh)m(b)s(oring) -0 2314 y(pixels.)40 b(Note)30 b(that)g(in)e(this)g(notation)i(the)f -(image)h(is)f(treated)g(as)g(a)g(1-D)h(arra)m(y)-8 b(,)30 -b(where)e(eac)m(h)i(ro)m(w)f(of)g(the)g(image)0 2427 -y(\(or)c(higher)f(dimensional)g(cub)s(e\))h(is)f(app)s(ended)f(one)h -(after)h(another)g(in)f(one)h(long)g(arra)m(y)g(of)f(pixels.)39 -b(It)25 b(is)f(p)s(ossible)0 2540 y(to)35 b(refer)f(to)h(pixels)f(in)g -(the)g(ro)m(ws)g(ab)s(o)m(v)m(e)h(or)g(b)s(elo)m(w)f(the)g(curren)m(t)g -(pixel)h(b)m(y)f(using)f(the)h(v)-5 b(alue)35 b(of)f(the)h(NAXIS1)0 -2653 y(header)30 b(k)m(eyw)m(ord.)41 b(F)-8 b(or)32 b(example)48 -2885 y Fe([pix)46 b(\(x{-#NAXIS1})f(+)i(x)h(+)f(x{#NAXIS1}\))e(/)i(3])0 -3117 y Fi(will)34 b(compute)f(the)h(mean)f(of)g(eac)m(h)i(image)f -(pixel)g(and)e(the)i(pixels)f(immediately)i(ab)s(o)m(v)m(e)f(and)f(b)s -(elo)m(w)g(it)h(in)f(the)0 3230 y(adjacen)m(t)27 b(ro)m(ws)f(of)g(the)f -(image.)41 b(The)25 b(follo)m(wing)i(more)f(complex)h(example)f -(creates)h(a)f(smo)s(othed)g(virtual)g(image)0 3343 y(where)k(eac)m(h)h -(pixel)g(is)g(a)f(3)h(x)f(3)h(b)s(o)m(xcar)g(a)m(v)m(erage)i(of)d(the)h -(input)e(image)j(pixels:)95 3575 y Fe([pix)47 b(\(X)g(+)h(X{-1})e(+)i -(X{+1})286 3688 y(+)g(X{-#NAXIS1})d(+)i(X{-#NAXIS1)e(-)i(1})h(+)f -(X{-#NAXIS1)e(+)j(1})286 3801 y(+)g(X{#NAXIS1})d(+)i(X{#NAXIS1)f(-)h -(1})g(+)h(X{#NAXIS1)d(+)i(1}\))g(/)h(9.])0 4033 y Fi(If)31 -b(the)h(pixel)g(o\013set)h(extends)f(b)s(ey)m(ond)f(the)h(\014rst)f(or) -h(last)h(pixel)f(in)f(the)h(image,)i(the)e(function)g(will)g(ev)-5 -b(aluate)33 b(to)0 4145 y(unde\014ned,)28 b(or)j(NULL.)0 -4306 y(F)-8 b(or)39 b(complex)g(or)g(commonly)g(used)e(image)j -(\014ltering)f(op)s(erations,)i(one)d(can)h(write)g(the)f(expression)h -(in)m(to)g(an)0 4419 y(external)i(text)h(\014le)f(and)f(then)g(imp)s -(ort)g(it)h(in)m(to)h(the)e(\014lter)h(using)f(the)h(syn)m(tax)g('[pix) -g(@\014lename.txt]'.)72 b(The)0 4531 y(mathematical)29 -b(expression)e(can)g(extend)g(o)m(v)m(er)i(m)m(ultiple)e(lines)g(of)h -(text)g(in)e(the)h(\014le.)40 b(An)m(y)27 b(lines)g(in)g(the)g -(external)0 4644 y(text)h(\014le)e(that)i(b)s(egin)e(with)g(2)h(slash)f -(c)m(haracters)i(\('//'\))h(will)e(b)s(e)f(ignored)h(and)f(ma)m(y)h(b)s -(e)f(used)g(to)h(add)f(commen)m(ts)0 4757 y(in)m(to)31 -b(the)g(\014le.)0 4917 y(By)c(default,)g(the)f(datat)m(yp)s(e)i(of)e -(the)g(resulting)h(image)g(will)g(b)s(e)e(the)i(same)f(as)h(the)f -(original)i(image,)g(but)e(one)g(ma)m(y)0 5030 y(force)31 -b(a)g(di\013eren)m(t)g(datat)m(yp)s(e)g(b)m(y)f(app)s(ended)f(a)h(co)s -(de)h(letter)h(to)f(the)f('pix')h(k)m(eyw)m(ord:)286 -5262 y Fe(pixb)95 b(-)g(8-bit)46 b(byte)190 b(image)46 -b(with)h(BITPIX)f(=)143 b(8)286 5375 y(pixi)95 b(-)47 -b(16-bit)f(integer)g(image)g(with)h(BITPIX)f(=)95 b(16)286 -5488 y(pixj)g(-)47 b(32-bit)f(integer)g(image)g(with)h(BITPIX)f(=)95 -b(32)286 5601 y(pixr)g(-)47 b(32-bit)f(float)142 b(image)46 -b(with)h(BITPIX)f(=)i(-32)286 5714 y(pixd)95 b(-)47 b(64-bit)f(float) -142 b(image)46 b(with)h(BITPIX)f(=)i(-64)p eop end -%%Page: 94 100 -TeXDict begin 94 99 bop 0 299 a Fi(94)1618 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fi(Also)23 b(b)m(y)f(default,)j(an)m(y)d(other)h(HDUs)g(in)f(the) -g(input)g(\014le)g(will)h(b)s(e)e(copied)i(without)g(c)m(hange)g(to)g -(the)g(output)f(virtual)0 668 y(FITS)k(\014le,)h(but)f(one)g(ma)m(y)h -(discard)f(the)h(other)f(HDUs)h(b)m(y)f(adding)g(the)h(n)m(um)m(b)s(er) -e('1')i(to)g(the)g('pix')f(k)m(eyw)m(ord)h(\(and)0 781 -y(follo)m(wing)32 b(an)m(y)f(optional)g(datat)m(yp)s(e)g(co)s(de)g -(letter\).)42 b(F)-8 b(or)32 b(example:)239 1044 y Fe -(myfile.fits[3][pixr1)90 b(sqrt\(X\)])0 1307 y Fi(will)23 -b(create)i(a)e(virtual)g(FITS)f(\014le)h(con)m(taining)h(only)f(a)g -(primary)f(arra)m(y)i(image)g(with)e(32-bit)i(\015oating)g(p)s(oin)m(t) -f(pixels)0 1420 y(that)29 b(ha)m(v)m(e)h(a)f(v)-5 b(alue)30 -b(equal)f(to)g(the)g(square)g(ro)s(ot)g(of)g(the)g(pixels)f(in)h(the)g -(image)h(that)f(is)g(in)f(the)h(3rd)f(extension)i(of)0 -1533 y(the)h('m)m(y\014le.\014ts')g(\014le.)0 1870 y -Fd(8.10)136 b(Column)45 b(and)f(Keyw)l(ord)i(Filtering)g(Sp)t -(eci\014cation)0 2121 y Fi(The)27 b(optional)i(column/k)m(eyw)m(ord)g -(\014ltering)f(sp)s(eci\014er)f(is)h(used)f(to)i(mo)s(dify)e(the)h -(column)g(structure)f(and/or)h(the)0 2234 y(header)38 -b(k)m(eyw)m(ords)h(in)f(the)h(HDU)g(that)h(w)m(as)f(selected)h(with)e -(the)h(previous)f(HDU)h(lo)s(cation)h(sp)s(eci\014er.)65 -b(This)0 2347 y(\014ltering)42 b(sp)s(eci\014er)f(m)m(ust)h(b)s(e)f -(enclosed)i(in)e(square)h(brac)m(k)m(ets)h(and)e(can)h(b)s(e)f -(distinguished)g(from)h(a)g(general)0 2460 y(ro)m(w)d(\014lter)g(sp)s -(eci\014er)f(\(describ)s(ed)g(b)s(elo)m(w\))h(b)m(y)g(the)g(fact)h -(that)f(it)g(b)s(egins)f(with)h(the)g(string)g('col)h(')f(and)f(is)h -(not)0 2573 y(immediately)30 b(follo)m(w)m(ed)g(b)m(y)e(an)g(equals)h -(sign.)40 b(The)28 b(original)h(\014le)f(is)h(not)f(c)m(hanged)h(b)m(y) -f(this)h(\014ltering)f(op)s(eration,)0 2686 y(and)40 -b(instead)h(the)g(mo)s(di\014cations)g(are)g(made)f(on)h(a)g(cop)m(y)g -(of)g(the)g(input)f(FITS)g(\014le)g(\(usually)h(in)f(memory\),)0 -2799 y(whic)m(h)33 b(also)h(con)m(tains)g(a)f(cop)m(y)h(of)f(all)h(the) -g(other)f(HDUs)h(in)e(the)h(\014le.)49 b(This)33 b(temp)s(orary)f -(\014le)h(is)g(passed)g(to)h(the)0 2912 y(application)f(program)f(and)f -(will)h(p)s(ersist)f(only)h(un)m(til)g(the)g(\014le)g(is)g(closed)h(or) -f(un)m(til)g(the)g(program)f(exits,)j(unless)0 3025 y(the)d(out\014le)f -(sp)s(eci\014er)g(\(see)h(ab)s(o)m(v)m(e\))h(is)f(also)g(supplied.)0 -3185 y(The)g(column/k)m(eyw)m(ord)h(\014lter)f(can)g(b)s(e)g(used)f(to) -i(p)s(erform)e(the)i(follo)m(wing)g(op)s(erations.)44 -b(More)32 b(than)f(one)g(op)s(er-)0 3298 y(ation)g(ma)m(y)g(b)s(e)f(sp) -s(eci\014ed)g(b)m(y)g(separating)h(them)f(with)h(commas)f(or)h -(semi-colons.)136 3561 y Fc(\017)46 b Fi(Cop)m(y)36 b(only)g(a)g(sp)s -(eci\014ed)g(list)g(of)g(columns)g(columns)f(to)i(the)f(\014ltered)g -(input)f(\014le.)57 b(The)36 b(list)g(of)g(column)227 -3673 y(name)41 b(should)e(b)s(e)g(separated)i(b)m(y)f(commas)h(or)f -(semi-colons.)72 b(Wild)41 b(card)f(c)m(haracters)h(ma)m(y)g(b)s(e)f -(used)227 3786 y(in)e(the)f(column)h(names)g(to)g(matc)m(h)g(m)m -(ultiple)h(columns.)62 b(If)37 b(the)h(expression)g(con)m(tains)g(b)s -(oth)f(a)h(list)h(of)227 3899 y(columns)29 b(to)h(b)s(e)f(included)g -(and)g(columns)g(to)h(b)s(e)e(deleted,)j(then)e(all)h(the)g(columns)f -(in)g(the)h(original)g(table)227 4012 y(except)36 b(the)e(explicitly)i -(deleted)f(columns)f(will)h(app)s(ear)e(in)h(the)h(\014ltered)f(table)h -(\(i.e.,)i(there)e(is)f(no)g(need)227 4125 y(to)d(explicitly)h(list)f -(the)g(columns)f(to)h(b)s(e)f(included)f(if)i(an)m(y)f(columns)h(are)f -(b)s(eing)g(deleted\).)136 4316 y Fc(\017)46 b Fi(Delete)32 -b(a)d(column)g(or)g(k)m(eyw)m(ord)h(b)m(y)f(listing)h(the)f(name)g -(preceded)g(b)m(y)g(a)g(min)m(us)g(sign)g(or)g(an)g(exclamation)227 -4429 y(mark)c(\(!\),)h(e.g.,)i('-TIME')d(will)g(delete)h(the)e(TIME)h -(column)f(if)g(it)i(exists,)g(otherwise)f(the)g(TIME)f(k)m(eyw)m(ord.) -227 4542 y(An)35 b(error)f(is)h(returned)e(if)i(neither)f(a)i(column)e -(nor)g(k)m(eyw)m(ord)h(with)g(this)f(name)h(exists.)54 -b(Note)36 b(that)g(the)227 4655 y(exclamation)27 b(p)s(oin)m(t,)g(')10 -b(!',)27 b(is)e(a)g(sp)s(ecial)h(UNIX)f(c)m(haracter,)j(so)d(if)g(it)h -(is)f(used)f(on)h(the)g(command)g(line)g(rather)227 4768 -y(than)33 b(en)m(tered)h(at)g(a)g(task)g(prompt,)f(it)h(m)m(ust)f(b)s -(e)g(preceded)g(b)m(y)g(a)h(bac)m(kslash)g(to)g(force)g(the)f(UNIX)h -(shell)227 4881 y(to)d(ignore)g(it.)136 5071 y Fc(\017)46 -b Fi(Rename)29 b(an)g(existing)g(column)f(or)h(k)m(eyw)m(ord)g(with)f -(the)h(syn)m(tax)g('NewName)h(==)e(OldName'.)40 b(An)28 -b(error)227 5184 y(is)j(returned)e(if)h(neither)h(a)f(column)g(nor)g(k) -m(eyw)m(ord)h(with)f(this)h(name)f(exists.)136 5375 y -Fc(\017)46 b Fi(App)s(end)37 b(a)j(new)f(column)f(or)i(k)m(eyw)m(ord)f -(to)h(the)f(table.)68 b(T)-8 b(o)40 b(create)g(a)g(column,)h(giv)m(e)g -(the)e(new)g(name,)227 5488 y(optionally)e(follo)m(w)m(ed)g(b)m(y)e -(the)g(datat)m(yp)s(e)h(in)f(paren)m(theses,)i(follo)m(w)m(ed)g(b)m(y)e -(a)h(single)g(equals)f(sign)g(and)g(an)227 5601 y(expression)g(to)h(b)s -(e)e(used)g(to)i(compute)f(the)g(v)-5 b(alue)35 b(\(e.g.,)j('new)m -(col\(1J\))f(=)e(0')g(will)h(create)g(a)f(new)g(32-bit)227 -5714 y(in)m(teger)k(column)e(called)i('new)m(col')f(\014lled)g(with)f -(zeros\).)62 b(The)37 b(datat)m(yp)s(e)h(is)g(sp)s(eci\014ed)e(using)h -(the)h(same)p eop end -%%Page: 95 101 -TeXDict begin 95 100 bop 0 299 a Fg(8.10.)73 b(COLUMN)30 -b(AND)h(KEYW)m(ORD)g(FIL)-8 b(TERING)30 b(SPECIFICA)-8 -b(TION)1075 b Fi(95)227 555 y(syn)m(tax)28 b(that)h(is)e(allo)m(w)m(ed) -j(for)d(the)h(v)-5 b(alue)28 b(of)g(the)g(FITS)f(TF)m(ORMn)g(k)m(eyw)m -(ord)h(\(e.g.,)i('I',)f('J',)f('E',)g('D',)h(etc.)227 -668 y(for)37 b(binary)f(tables,)k(and)c('I8',)k(F12.3',)h('E20.12',)g -(etc.)62 b(for)37 b(ASCI)s(I)e(tables\).)62 b(If)37 b(the)g(datat)m(yp) -s(e)h(is)f(not)227 781 y(sp)s(eci\014ed)24 b(then)f(an)h(appropriate)h -(datat)m(yp)s(e)g(will)f(b)s(e)g(c)m(hosen)g(dep)s(ending)f(on)h(the)g -(form)g(of)g(the)g(expression)227 894 y(\(ma)m(y)f(b)s(e)d(a)i(c)m -(haracter)h(string,)h(logical,)h(bit,)f(long)e(in)m(teger,)j(or)c -(double)g(column\).)38 b(An)21 b(appropriate)g(v)m(ector)227 -1007 y(coun)m(t)31 b(\(in)g(the)f(case)i(of)e(binary)g(tables\))h(will) -g(also)g(b)s(e)f(added)g(if)g(not)h(explicitly)h(sp)s(eci\014ed.)227 -1154 y(When)26 b(creating)h(a)f(new)f(k)m(eyw)m(ord,)j(the)e(k)m(eyw)m -(ord)g(name)g(m)m(ust)g(b)s(e)f(preceded)g(b)m(y)h(a)g(p)s(ound)e(sign) -h('#',)j(and)227 1267 y(the)h(expression)f(m)m(ust)g(ev)-5 -b(aluate)30 b(to)f(a)g(scalar)g(\(i.e.,)h(cannot)f(ha)m(v)m(e)h(a)f -(column)f(name)g(in)g(the)h(expression\).)227 1380 y(The)j(commen)m(t)i -(string)f(for)f(the)h(k)m(eyw)m(ord)h(ma)m(y)f(b)s(e)f(sp)s(eci\014ed)g -(in)g(paren)m(theses)h(immediately)h(follo)m(wing)227 -1493 y(the)29 b(k)m(eyw)m(ord)f(name)g(\(instead)h(of)f(supplying)f(a)h -(datat)m(yp)s(e)h(as)g(in)e(the)i(case)g(of)f(creating)h(a)g(new)f -(column\).)227 1606 y(If)c(the)h(k)m(eyw)m(ord)g(name)f(ends)g(with)g -(a)h(p)s(ound)d(sign)i('#',)i(then)e(c\014tsio)i(will)e(substitute)h -(the)f(n)m(um)m(b)s(er)f(of)i(the)227 1719 y(most)31 -b(recen)m(tly)h(referenced)e(column)h(for)f(the)h(#)f(c)m(haracter)i(.) -41 b(This)29 b(is)i(esp)s(ecially)h(useful)d(when)h(writing)227 -1831 y(a)c(column-related)g(k)m(eyw)m(ord)g(lik)m(e)g(TUNITn)e(for)h(a) -h(newly)f(created)h(column,)g(as)g(sho)m(wn)e(in)h(the)g(follo)m(wing) -227 1944 y(examples.)227 2092 y(COMMENT)30 b(and)g(HISTOR)-8 -b(Y)30 b(k)m(eyw)m(ords)g(ma)m(y)h(also)h(b)s(e)e(created)h(with)f(the) -h(follo)m(wing)g(syn)m(tax:)370 2320 y Fe(#COMMENT)46 -b(=)h('This)g(is)g(a)g(comment)f(keyword')370 2433 y(#HISTORY)g(=)h -('This)g(is)g(a)g(history)f(keyword')227 2661 y Fi(Note)d(that)f(the)f -(equal)h(sign)f(and)f(the)i(quote)f(c)m(haracters)i(will)f(b)s(e)e -(remo)m(v)m(ed,)45 b(so)d(that)f(the)h(resulting)227 -2774 y(header)30 b(k)m(eyw)m(ords)h(in)f(these)h(cases)g(will)g(lo)s -(ok)g(lik)m(e)h(this:)370 3002 y Fe(COMMENT)46 b(This)h(is)g(a)h -(comment)d(keyword)370 3115 y(HISTORY)h(This)h(is)g(a)h(history)d -(keyword)227 3343 y Fi(These)29 b(t)m(w)m(o)h(sp)s(ecial)f(k)m(eyw)m -(ords)h(are)f(alw)m(a)m(ys)h(app)s(ended)d(to)j(the)f(end)f(of)h(the)g -(header)g(and)f(will)h(not)g(a\013ect)227 3456 y(an)m(y)i(previously)f -(existing)h(COMMENT)f(or)h(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords.)136 -3637 y Fc(\017)46 b Fi(Recompute)f(\(o)m(v)m(erwrite\))i(the)d(v)-5 -b(alues)44 b(in)g(an)g(existing)i(column)e(or)g(k)m(eyw)m(ord)g(b)m(y)g -(giving)i(the)e(name)227 3750 y(follo)m(w)m(ed)32 b(b)m(y)f(an)f -(equals)h(sign)f(and)g(an)g(arithmetic)i(expression.)0 -3991 y(The)23 b(expression)g(that)i(is)e(used)g(when)g(app)s(ending)f -(or)h(recomputing)h(columns)f(or)h(k)m(eyw)m(ords)g(can)g(b)s(e)f -(arbitrarily)0 4104 y(complex)36 b(and)g(ma)m(y)g(b)s(e)f(a)h(function) -g(of)g(other)g(header)g(k)m(eyw)m(ord)g(v)-5 b(alues)36 -b(and)f(other)h(columns)g(\(in)g(the)g(same)0 4217 y(ro)m(w\).)63 -b(The)37 b(full)g(syn)m(tax)i(and)e(a)m(v)-5 b(ailable)40 -b(functions)d(for)g(the)h(expression)f(are)h(describ)s(ed)f(b)s(elo)m -(w)h(in)f(the)h(ro)m(w)0 4330 y(\014lter)30 b(sp)s(eci\014cation)i -(section.)0 4490 y(If)27 b(the)h(expression)g(con)m(tains)g(b)s(oth)f -(a)h(list)h(of)f(columns)f(to)h(b)s(e)g(included)e(and)i(columns)f(to)h -(b)s(e)f(deleted,)j(then)d(all)0 4603 y(the)34 b(columns)g(in)g(the)g -(original)h(table)g(except)g(the)f(explicitly)i(deleted)f(columns)e -(will)i(app)s(ear)e(in)h(the)g(\014ltered)0 4716 y(table.)40 -b(If)26 b(no)g(columns)f(to)i(b)s(e)f(deleted)g(are)h(sp)s(eci\014ed,)f -(then)g(only)g(the)h(columns)e(that)i(are)f(explicitly)i(listed)f(will) -0 4829 y(b)s(e)k(included)g(in)g(the)h(\014ltered)f(output)h(table.)45 -b(T)-8 b(o)32 b(include)f(all)i(the)e(columns,)h(add)f(the)h('*')g -(wildcard)g(sp)s(eci\014er)0 4942 y(at)f(the)g(end)e(of)i(the)f(list,)i -(as)e(sho)m(wn)g(in)g(the)h(examples.)0 5102 y(F)-8 b(or)30 -b(complex)h(or)e(commonly)h(used)f(op)s(erations,)i(one)e(can)h(also)h -(place)g(the)e(op)s(erations)h(in)m(to)h(an)e(external)i(text)0 -5215 y(\014le)g(and)f(imp)s(ort)g(it)h(in)m(to)h(the)f(column)g -(\014lter)f(using)h(the)g(syn)m(tax)g('[col)h(@\014lename.txt]'.)43 -b(The)31 b(op)s(erations)g(can)0 5328 y(extend)k(o)m(v)m(er)h(m)m -(ultiple)g(lines)f(of)g(the)g(\014le,)h(but)e(m)m(ultiple)i(op)s -(erations)f(m)m(ust)f(still)i(b)s(e)e(separated)i(b)m(y)e(commas)0 -5441 y(or)e(semi-colons.)47 b(An)m(y)32 b(lines)h(in)f(the)g(external)h -(text)g(\014le)f(that)h(b)s(egin)e(with)h(2)h(slash)e(c)m(haracters)j -(\('//'\))g(will)f(b)s(e)0 5554 y(ignored)d(and)g(ma)m(y)h(b)s(e)f -(used)g(to)h(add)e(commen)m(ts)j(in)m(to)f(the)g(\014le.)0 -5714 y(Examples:)p eop end -%%Page: 96 102 -TeXDict begin 96 101 bop 0 299 a Fi(96)1618 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)143 -555 y Fe([col)47 b(Time,)f(rate])667 b(-)47 b(only)g(the)g(Time)g(and)g -(rate)f(columns)g(will)1670 668 y(appear)h(in)g(the)g(filtered)e(input) -i(file.)143 894 y([col)g(Time,)f(*raw])667 b(-)47 b(include)f(the)h -(Time)g(column)f(and)h(any)g(other)1670 1007 y(columns)f(whose)h(name)f -(ends)h(with)g('raw'.)143 1233 y([col)g(-TIME;)f(Good)h(==)g(STATUS]) -141 b(-)47 b(deletes)f(the)h(TIME)g(column)f(and)1670 -1346 y(renames)g(the)h(status)f(column)g(to)i('Good')143 -1571 y([col)f(PI=PHA)f(*)h(1.1)g(+)h(0.2;)e(#TUNIT#\(column)e(units\))i -(=)i('counts';*])1575 1684 y(-)f(creates)f(new)h(PI)g(column)f(from)h -(PHA)g(values)1670 1797 y(and)g(also)g(writes)f(the)h(TUNITn)f(keyword) -1670 1910 y(for)h(the)g(new)g(column.)94 b(The)47 b(final)f('*')1670 -2023 y(expression)f(means)i(preserve)e(all)i(the)1670 -2136 y(columns)f(in)h(the)g(input)g(table)f(in)h(the)1670 -2249 y(virtual)f(output)g(table;)94 b(without)46 b(the)h('*')1670 -2362 y(the)g(output)f(table)h(would)f(only)h(contain)1670 -2475 y(the)g(single)f('PI')h(column.)143 2700 y([col)g(rate)f(=)i -(rate/exposure,)c(TUNIT#\(&\))h(=)j('counts/s';*])1575 -2813 y(-)f(recomputes)e(the)i(rate)g(column)f(by)h(dividing)1670 -2926 y(it)h(by)f(the)g(EXPOSURE)e(keyword)h(value.)g(This)1670 -3039 y(also)h(modifies)f(the)h(value)f(of)h(the)g(TUNITn)1670 -3152 y(keyword)f(for)h(this)g(column.)f(The)h(use)f(of)i(the)1670 -3265 y('&')f(character)f(for)h(the)f(keyword)g(comment)1670 -3378 y(string)h(means)f(preserve)f(the)i(existing)1670 -3491 y(comment)f(string)g(for)h(that)g(keyword.)e(The)1670 -3604 y(final)i('*')g(preserves)e(all)i(the)g(columns)1670 -3717 y(in)h(the)f(input)f(table)g(in)h(the)g(virtual)1670 -3830 y(output)g(table.)0 4400 y Fd(8.11)136 b(Ro)l(w)45 -b(Filtering)h(Sp)t(eci\014cation)0 4698 y Fi(When)29 -b(en)m(tering)h(the)f(name)g(of)g(a)g(FITS)f(table)i(that)g(is)e(to)i -(b)s(e)e(op)s(ened)h(b)m(y)f(a)i(program,)f(an)g(optional)h(ro)m(w)f -(\014lter)0 4811 y(ma)m(y)i(b)s(e)g(sp)s(eci\014ed)f(to)h(select)h(a)g -(subset)e(of)h(the)g(ro)m(ws)f(in)h(the)g(table.)43 b(A)31 -b(temp)s(orary)f(new)g(FITS)g(\014le)h(is)g(created)0 -4924 y(on)25 b(the)h(\015y)e(whic)m(h)h(con)m(tains)h(only)g(those)g -(ro)m(ws)f(for)g(whic)m(h)g(the)g(ro)m(w)g(\014lter)h(expression)f(ev) --5 b(aluates)26 b(to)g(true.)39 b(\(The)0 5036 y(primary)26 -b(arra)m(y)h(and)f(an)m(y)g(other)h(extensions)g(in)f(the)h(input)f -(\014le)g(are)h(also)h(copied)f(to)g(the)f(temp)s(orary)h(\014le\).)39 -b(The)0 5149 y(original)30 b(FITS)f(\014le)g(is)g(closed)h(and)e(the)i -(new)e(virtual)i(\014le)f(is)g(op)s(ened)f(b)m(y)h(the)h(application)g -(program.)40 b(The)29 b(ro)m(w)0 5262 y(\014lter)37 b(expression)g(is)h -(enclosed)g(in)f(square)g(brac)m(k)m(ets)i(follo)m(wing)g(the)e(\014le) -h(name)f(and)g(extension)h(name)f(\(e.g.,)0 5375 y('\014le.\014ts[ev)m -(en)m(ts][GRADE==50]')29 b(selects)d(only)f(those)h(ro)m(ws)f(where)f -(the)h(GRADE)h(column)f(v)-5 b(alue)25 b(equals)g(50\).)0 -5488 y(When)33 b(dealing)h(with)f(tables)g(where)g(eac)m(h)h(ro)m(w)f -(has)g(an)g(asso)s(ciated)i(time)f(and/or)f(2D)g(spatial)i(p)s -(osition,)f(the)0 5601 y(ro)m(w)e(\014lter)h(expression)e(can)i(also)g -(b)s(e)f(used)f(to)i(select)h(ro)m(ws)e(based)g(on)g(the)g(times)h(in)f -(a)g(Go)s(o)s(d)g(Time)g(In)m(terv)-5 b(als)0 5714 y(\(GTI\))31 -b(extension,)g(or)f(on)h(spatial)g(p)s(osition)g(as)f(giv)m(en)i(in)e -(a)g(SA)m(O-st)m(yle)i(region)f(\014le.)p eop end -%%Page: 97 103 -TeXDict begin 97 102 bop 0 299 a Fg(8.11.)73 b(R)m(O)m(W)31 -b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)2027 b Fi(97)0 -555 y Fb(8.11.1)113 b(General)38 b(Syn)m(tax)0 774 y -Fi(The)32 b(ro)m(w)h(\014ltering)g(expression)g(can)g(b)s(e)f(an)h -(arbitrarily)g(complex)g(series)g(of)g(op)s(erations)g(p)s(erformed)f -(on)g(con-)0 887 y(stan)m(ts,)39 b(k)m(eyw)m(ord)e(v)-5 -b(alues,)38 b(and)e(column)g(data)i(tak)m(en)f(from)f(the)h(sp)s -(eci\014ed)e(FITS)h(T)-8 b(ABLE)37 b(extension.)59 b(The)0 -1000 y(expression)37 b(m)m(ust)h(ev)-5 b(aluate)39 b(to)g(a)f(b)s(o)s -(olean)g(v)-5 b(alue)38 b(for)f(eac)m(h)i(ro)m(w)f(of)g(the)f(table,)k -(where)c(a)h(v)-5 b(alue)39 b(of)e(F)-10 b(ALSE)0 1113 -y(means)30 b(that)h(the)g(ro)m(w)f(will)h(b)s(e)f(excluded.)0 -1273 y(F)-8 b(or)34 b(complex)g(or)g(commonly)f(used)g(\014lters,)h -(one)g(can)g(place)g(the)g(expression)f(in)m(to)h(a)g(text)g(\014le)g -(and)f(imp)s(ort)f(it)0 1386 y(in)m(to)38 b(the)e(ro)m(w)h(\014lter)g -(using)f(the)h(syn)m(tax)g('[@\014lename.txt]'.)61 b(The)36 -b(expression)h(can)f(b)s(e)g(arbitrarily)h(complex)0 -1499 y(and)27 b(extend)i(o)m(v)m(er)g(m)m(ultiple)g(lines)f(of)g(the)h -(\014le.)40 b(An)m(y)28 b(lines)g(in)g(the)g(external)h(text)g(\014le)f -(that)h(b)s(egin)f(with)g(2)g(slash)0 1612 y(c)m(haracters)k(\('//'\))g -(will)f(b)s(e)f(ignored)g(and)g(ma)m(y)h(b)s(e)f(used)f(to)i(add)f -(commen)m(ts)h(in)m(to)h(the)e(\014le.)0 1772 y(Keyw)m(ord)37 -b(and)f(column)g(data)i(are)f(referenced)g(b)m(y)g(name.)60 -b(An)m(y)37 b(string)f(of)h(c)m(haracters)i(not)e(surrounded)d(b)m(y)0 -1885 y(quotes)41 b(\(ie,)j(a)d(constan)m(t)h(string\))f(or)f(follo)m(w) -m(ed)i(b)m(y)f(an)f(op)s(en)g(paren)m(theses)h(\(ie,)j(a)d(function)f -(name\))h(will)g(b)s(e)0 1998 y(initially)d(in)m(terpreted)e(as)h(a)g -(column)f(name)g(and)g(its)h(con)m(ten)m(ts)h(for)e(the)h(curren)m(t)f -(ro)m(w)g(inserted)g(in)m(to)i(the)e(ex-)0 2111 y(pression.)k(If)28 -b(no)h(suc)m(h)g(column)g(exists,)h(a)g(k)m(eyw)m(ord)f(of)h(that)f -(name)g(will)h(b)s(e)e(searc)m(hed)i(for)f(and)f(its)i(v)-5 -b(alue)29 b(used,)0 2223 y(if)36 b(found.)55 b(T)-8 b(o)36 -b(force)g(the)g(name)g(to)h(b)s(e)e(in)m(terpreted)h(as)g(a)g(k)m(eyw)m -(ord)g(\(in)g(case)g(there)g(is)g(b)s(oth)f(a)h(column)g(and)0 -2336 y(k)m(eyw)m(ord)41 b(with)e(the)i(same)f(name\),)j(precede)d(the)h -(k)m(eyw)m(ord)f(name)g(with)g(a)h(single)f(p)s(ound)e(sign,)43 -b('#',)g(as)d(in)0 2449 y('#NAXIS2'.)g(Due)27 b(to)g(the)f -(generalities)j(of)d(FITS)g(column)g(and)g(k)m(eyw)m(ord)h(names,)g(if) -f(the)h(column)f(or)g(k)m(eyw)m(ord)0 2562 y(name)33 -b(con)m(tains)h(a)f(space)h(or)f(a)g(c)m(haracter)h(whic)m(h)f(migh)m -(t)h(app)s(ear)e(as)h(an)g(arithmetic)h(term)f(then)g(enclose)h(the)0 -2675 y(name)c(in)g('$')i(c)m(haracters)g(as)e(in)g($MAX)i(PHA$)f(or)f -(#$MAX-PHA$.)43 b(Names)31 b(are)f(case)i(insensitiv)m(e.)0 -2835 y(T)-8 b(o)32 b(access)g(a)g(table)g(en)m(try)g(in)f(a)h(ro)m(w)f -(other)h(than)f(the)g(curren)m(t)g(one,)h(follo)m(w)h(the)e(column's)h -(name)f(with)g(a)h(ro)m(w)0 2948 y(o\013set)37 b(within)e(curly)g -(braces.)57 b(F)-8 b(or)36 b(example,)i('PHA)p Fc(f)p -Fi(-3)p Fc(g)p Fi(')g(will)e(ev)-5 b(aluate)38 b(to)e(the)g(v)-5 -b(alue)36 b(of)g(column)f(PHA,)i(3)0 3061 y(ro)m(ws)28 -b(ab)s(o)m(v)m(e)i(the)e(ro)m(w)h(curren)m(tly)f(b)s(eing)g(pro)s -(cessed.)40 b(One)28 b(cannot)h(sp)s(ecify)f(an)g(absolute)h(ro)m(w)f -(n)m(um)m(b)s(er,)g(only)h(a)0 3174 y(relativ)m(e)j(o\013set.)42 -b(Ro)m(ws)31 b(that)g(fall)g(outside)g(the)f(table)h(will)g(b)s(e)f -(treated)h(as)g(unde\014ned,)d(or)j(NULLs.)0 3334 y(Bo)s(olean)h(op)s -(erators)f(can)g(b)s(e)f(used)f(in)i(the)f(expression)h(in)f(either)h -(their)g(F)-8 b(ortran)31 b(or)f(C)h(forms.)40 b(The)30 -b(follo)m(wing)0 3447 y(b)s(o)s(olean)g(op)s(erators)h(are)g(a)m(v)-5 -b(ailable:)191 3698 y Fe("equal")428 b(.eq.)46 b(.EQ.)h(==)95 -b("not)46 b(equal")476 b(.ne.)94 b(.NE.)h(!=)191 3811 -y("less)46 b(than")238 b(.lt.)46 b(.LT.)h(<)143 b("less)46 -b(than/equal")188 b(.le.)94 b(.LE.)h(<=)47 b(=<)191 3923 -y("greater)e(than")95 b(.gt.)46 b(.GT.)h(>)143 b("greater)45 -b(than/equal")g(.ge.)94 b(.GE.)h(>=)47 b(=>)191 4036 -y("or")572 b(.or.)46 b(.OR.)h(||)95 b("and")762 b(.and.)46 -b(.AND.)h(&&)191 4149 y("negation")236 b(.not.)46 b(.NOT.)h(!)95 -b("approx.)45 b(equal\(1e-7\)")92 b(~)0 4400 y Fi(Note)32 -b(that)g(the)f(exclamation)i(p)s(oin)m(t,)e(')10 b(!',)33 -b(is)e(a)g(sp)s(ecial)g(UNIX)h(c)m(haracter,)h(so)e(if)g(it)g(is)g -(used)f(on)h(the)g(command)0 4513 y(line)i(rather)f(than)h(en)m(tered)g -(at)g(a)g(task)g(prompt,)g(it)g(m)m(ust)f(b)s(e)g(preceded)h(b)m(y)f(a) -h(bac)m(kslash)g(to)h(force)f(the)g(UNIX)0 4626 y(shell)e(to)g(ignore)g -(it.)0 4786 y(The)h(expression)g(ma)m(y)i(also)f(include)f(arithmetic)i -(op)s(erators)f(and)f(functions.)47 b(T)-8 b(rigonometric)34 -b(functions)e(use)0 4899 y(radians,)23 b(not)g(degrees.)38 -b(The)22 b(follo)m(wing)h(arithmetic)g(op)s(erators)g(and)e(functions)g -(can)i(b)s(e)e(used)g(in)h(the)g(expression)0 5012 y(\(function)38 -b(names)f(are)h(case)g(insensitiv)m(e\).)64 b(A)37 b(n)m(ull)h(v)-5 -b(alue)38 b(will)f(b)s(e)g(returned)g(in)g(case)h(of)g(illegal)i(op)s -(erations)0 5125 y(suc)m(h)30 b(as)h(divide)f(b)m(y)g(zero,)i -(sqrt\(negativ)m(e\))h(log\(negativ)m(e\),)h(log10\(negativ)m(e\),)i -(arccos\(.gt.)43 b(1\),)32 b(arcsin\(.gt.)42 b(1\).)191 -5375 y Fe("addition")522 b(+)477 b("subtraction")d(-)191 -5488 y("multiplication")234 b(*)477 b("division")618 -b(/)191 5601 y("negation")522 b(-)477 b("exponentiation")330 -b(**)143 b(^)191 5714 y("absolute)45 b(value")237 b(abs\(x\))g -("cosine")714 b(cos\(x\))p eop end -%%Page: 98 104 -TeXDict begin 98 103 bop 0 299 a Fi(98)1618 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)191 -555 y Fe("sine")714 b(sin\(x\))237 b("tangent")666 b(tan\(x\))191 -668 y("arc)47 b(cosine")427 b(arccos\(x\))93 b("arc)47 -b(sine")619 b(arcsin\(x\))191 781 y("arc)47 b(tangent")379 -b(arctan\(x\))93 b("arc)47 b(tangent")475 b(arctan2\(y,x\))191 -894 y("hyperbolic)45 b(cos")237 b(cosh\(x\))189 b("hyperbolic)45 -b(sin")333 b(sinh\(x\))191 1007 y("hyperbolic)45 b(tan")237 -b(tanh\(x\))189 b("round)46 b(to)h(nearest)f(int")h(round\(x\))191 -1120 y("round)f(down)h(to)g(int")94 b(floor\(x\))141 -b("round)46 b(up)h(to)h(int")285 b(ceil\(x\))191 1233 -y("exponential")378 b(exp\(x\))237 b("square)46 b(root")476 -b(sqrt\(x\))191 1346 y("natural)45 b(log")381 b(log\(x\))237 -b("common)46 b(log")524 b(log10\(x\))191 1458 y("modulus")570 -b(x)48 b(\045)f(y)286 b("random)46 b(#)h([0.0,1.0\)")141 -b(random\(\))191 1571 y("random)46 b(Gaussian")188 b(randomn\(\))93 -b("random)46 b(Poisson")332 b(randomp\(x\))191 1684 y("minimum")570 -b(min\(x,y\))141 b("maximum")666 b(max\(x,y\))191 1797 -y("cumulative)45 b(sum")237 b(accum\(x\))93 b("sequential)45 -b(difference")g(seqdiff\(x\))191 1910 y("if-then-else")330 -b(b?x:y)191 2023 y("angular)45 b(separation")93 b -(angsep\(ra1,dec1,ra2,de2\))41 b(\(all)47 b(in)g(degrees\))191 -2136 y("substring")283 b(strmid\(s,p,n\))44 b("string)i(search")428 -b(strstr\(s,r\))0 2382 y Fi(Three)30 b(di\013eren)m(t)h(random)f(n)m -(um)m(b)s(er)f(functions)h(are)h(pro)m(vided:)41 b(random\(\),)30 -b(with)h(no)f(argumen)m(ts,)h(pro)s(duces)f(a)0 2495 -y(uniform)g(random)f(deviate)k(b)s(et)m(w)m(een)e(0)g(and)f(1;)i -(randomn\(\),)e(also)i(with)e(no)h(argumen)m(ts,)g(pro)s(duces)f(a)h -(normal)0 2608 y(\(Gaussian\))k(random)e(deviate)j(with)e(zero)h(mean)f -(and)g(unit)f(standard)h(deviation;)j(randomp\(x\))d(pro)s(duces)f(a)0 -2721 y(P)m(oisson)27 b(random)f(deviate)h(whose)f(exp)s(ected)h(n)m(um) -m(b)s(er)e(of)h(coun)m(ts)h(is)g(X.)f(X)h(ma)m(y)g(b)s(e)e(an)m(y)i(p)s -(ositiv)m(e)g(real)g(n)m(um)m(b)s(er)0 2833 y(of)k(exp)s(ected)f(coun)m -(ts,)h(including)f(fractional)i(v)-5 b(alues,)31 b(but)f(the)g(return)g -(v)-5 b(alue)31 b(is)f(an)g(in)m(teger.)0 2994 y(When)d(the)g(random)g -(functions)f(are)i(used)e(in)h(a)h(v)m(ector)g(expression,)g(b)m(y)f -(default)h(the)f(same)h(random)e(v)-5 b(alue)28 b(will)0 -3107 y(b)s(e)g(used)f(when)h(ev)-5 b(aluating)30 b(eac)m(h)f(elemen)m -(t)h(of)f(the)g(v)m(ector.)41 b(If)28 b(di\013eren)m(t)h(random)f(n)m -(um)m(b)s(ers)f(are)i(desired,)f(then)0 3219 y(the)37 -b(name)g(of)g(a)g(v)m(ector)i(column)e(should)e(b)s(e)i(supplied)e(as)i -(the)h(single)f(argumen)m(t)g(to)h(the)f(random)f(function)0 -3332 y(\(e.g.,)31 b("\015ux)c(+)h(0.1)h(*)g(random\(\015ux\)",)f(where) -g("\015ux')g(is)g(the)g(name)h(of)f(a)h(v)m(ector)h(column\).)40 -b(This)27 b(will)i(create)h(a)0 3445 y(v)m(ector)d(of)f(random)f(n)m -(um)m(b)s(ers)f(that)i(will)g(b)s(e)f(used)f(in)i(sequence)g(when)e(ev) --5 b(aluating)27 b(eac)m(h)g(elemen)m(t)g(of)f(the)f(v)m(ector)0 -3558 y(expression.)0 3718 y(An)31 b(alternate)i(syn)m(tax)f(for)f(the)g -(min)g(and)g(max)g(functions)g(has)g(only)g(a)h(single)g(argumen)m(t)g -(whic)m(h)f(should)f(b)s(e)h(a)0 3831 y(v)m(ector)g(v)-5 -b(alue)30 b(\(see)g(b)s(elo)m(w\).)41 b(The)29 b(result)g(will)h(b)s(e) -e(the)i(minim)m(um/maxim)m(um)f(elemen)m(t)h(con)m(tained)h(within)e -(the)0 3944 y(v)m(ector.)0 4104 y(The)35 b(accum\(x\))i(function)f -(forms)f(the)h(cum)m(ulativ)m(e)i(sum)d(of)h(x,)h(elemen)m(t)h(b)m(y)e -(elemen)m(t.)58 b(V)-8 b(ector)38 b(columns)e(are)0 4217 -y(supp)s(orted)h(simply)h(b)m(y)g(p)s(erforming)f(the)i(summation)g -(pro)s(cess)f(through)f(all)j(the)f(v)-5 b(alues.)65 -b(Null)39 b(v)-5 b(alues)39 b(are)0 4330 y(treated)30 -b(as)f(0.)41 b(The)29 b(seqdi\013\(x\))h(function)e(forms)h(the)g -(sequen)m(tial)i(di\013erence)e(of)h(x,)f(elemen)m(t)i(b)m(y)e(elemen)m -(t.)41 b(The)0 4443 y(\014rst)36 b(v)-5 b(alue)38 b(of)f(seqdi\013)g -(is)g(the)g(\014rst)g(v)-5 b(alue)37 b(of)g(x.)61 b(A)37 -b(single)h(n)m(ull)f(v)-5 b(alue)38 b(in)e(x)h(causes)h(a)f(pair)g(of)g -(n)m(ulls)g(in)g(the)0 4556 y(output.)55 b(The)35 b(seqdi\013)g(and)g -(accum)g(functions)g(are)h(functional)f(in)m(v)m(erses,)j(i.e.,)g -(seqdi\013\(accum\(x\)\))f(==)e(x)g(as)0 4669 y(long)c(as)g(no)f(n)m -(ull)g(v)-5 b(alues)31 b(are)g(presen)m(t.)0 4829 y(In)36 -b(the)h(if-then-else)i(expression,)f("b?x:y",)i(b)c(is)h(an)g(explicit) -h(b)s(o)s(olean)f(v)-5 b(alue)37 b(or)g(expression.)61 -b(There)36 b(is)h(no)0 4942 y(automatic)d(t)m(yp)s(e)e(con)m(v)m -(ersion)h(from)e(n)m(umeric)h(to)g(b)s(o)s(olean)g(v)-5 -b(alues,)33 b(so)f(one)g(needs)f(to)i(use)e("iV)-8 b(al!=0")35 -b(instead)0 5055 y(of)30 b(merely)g("iV)-8 b(al")32 b(as)e(the)g(b)s(o) -s(olean)g(argumen)m(t.)41 b(x)30 b(and)f(y)h(can)g(b)s(e)f(an)m(y)h -(scalar)h(data)g(t)m(yp)s(e)f(\(including)f(string\).)0 -5215 y(The)22 b(angsep)g(function)f(computes)i(the)f(angular)g -(separation)h(in)e(degrees)i(b)s(et)m(w)m(een)g(2)f(celestial)j(p)s -(ositions,)e(where)0 5328 y(the)36 b(\014rst)f(2)h(parameters)g(giv)m -(e)h(the)f(RA-lik)m(e)i(and)d(Dec-lik)m(e)j(co)s(ordinates)f(\(in)f -(decimal)g(degrees\))h(of)f(the)g(\014rst)0 5441 y(p)s(osition,)31 -b(and)e(the)i(3rd)f(and)g(4th)g(parameters)h(giv)m(e)h(the)e(co)s -(ordinates)i(of)e(the)h(second)f(p)s(osition.)0 5601 -y(The)38 b(substring)f(function)i(strmid\(S,P)-8 b(,N\))39 -b(extracts)g(a)g(substring)f(from)g(S,)g(starting)h(at)g(string)g(p)s -(osition)f(P)-8 b(,)0 5714 y(with)33 b(a)h(substring)f(length)h(N.)g -(The)f(\014rst)g(c)m(haracter)j(p)s(osition)d(in)h(S)f(is)h(lab)s(eled) -g(as)g(1.)51 b(If)33 b(P)g(is)h(0,)h(or)f(refers)f(to)p -eop end -%%Page: 99 105 -TeXDict begin 99 104 bop 0 299 a Fg(8.11.)73 b(R)m(O)m(W)31 -b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)2027 b Fi(99)0 -555 y(a)35 b(p)s(osition)g(b)s(ey)m(ond)f(the)h(end)e(of)i(S,)g(then)f -(the)h(extracted)h(substring)d(will)i(b)s(e)f(NULL.)h(S,)f(P)-8 -b(,)36 b(and)e(N)g(ma)m(y)i(b)s(e)0 668 y(functions)30 -b(of)g(other)h(columns.)0 828 y(The)39 b(string)h(searc)m(h)h(function) -e(strstr\(S,R\))h(searc)m(hes)h(for)f(the)g(\014rst)f(o)s(ccurrence)h -(of)g(the)g(substring)f(R)h(in)f(S.)0 941 y(The)c(result)h(is)f(an)h -(in)m(teger,)i(indicating)f(the)e(c)m(haracter)i(p)s(osition)f(of)g -(the)g(\014rst)e(matc)m(h)j(\(where)e(1)h(is)g(the)g(\014rst)0 -1054 y(c)m(haracter)c(p)s(osition)e(of)h(S\).)f(If)g(no)h(matc)m(h)g -(is)f(found,)g(then)g(strstr\(\))g(returns)f(a)i(NULL)f(v)-5 -b(alue.)0 1214 y(The)37 b(follo)m(wing)i(t)m(yp)s(e)f(casting)g(op)s -(erators)g(are)g(a)m(v)-5 b(ailable,)42 b(where)37 b(the)h(enclosing)g -(paren)m(theses)g(are)g(required)0 1327 y(and)30 b(tak)m(en)h(from)f -(the)h(C)f(language)h(usage.)42 b(Also,)31 b(the)g(in)m(teger)g(to)h -(real)f(casts)g(v)-5 b(alues)30 b(to)i(double)e(precision:)764 -1593 y Fe("real)46 b(to)h(integer")189 b(\(int\))46 b(x)239 -b(\(INT\))46 b(x)764 1706 y("integer)f(to)i(real")190 -b(\(float\))46 b(i)143 b(\(FLOAT\))45 b(i)0 1972 y Fi(In)30 -b(addition,)g(sev)m(eral)i(constan)m(ts)g(are)f(built)f(in)g(for)g(use) -g(in)g(n)m(umerical)h(expressions:)382 2238 y Fe(#pi)667 -b(3.1415...)284 b(#e)620 b(2.7182...)382 2351 y(#deg)f(#pi/180)380 -b(#row)524 b(current)46 b(row)h(number)382 2464 y(#null)428 -b(undefined)45 b(value)142 b(#snull)428 b(undefined)45 -b(string)0 2730 y Fi(A)40 b(string)f(constan)m(t)i(m)m(ust)e(b)s(e)g -(enclosed)h(in)g(quotes)g(as)f(in)h('Crab'.)67 b(The)39 -b("n)m(ull")i(constan)m(ts)f(are)g(useful)f(for)0 2843 -y(conditionally)g(setting)g(table)g(v)-5 b(alues)38 b(to)g(a)g(NULL,)g -(or)g(unde\014ned,)f(v)-5 b(alue)39 b(\(eg.,)i("col1==-99)f(?)62 -b(#NULL)38 b(:)0 2955 y(col1"\).)0 3116 y(There)27 b(is)g(also)i(a)e -(function)g(for)h(testing)g(if)f(t)m(w)m(o)i(v)-5 b(alues)28 -b(are)g(close)g(to)h(eac)m(h)f(other,)h(i.e.,)g(if)e(they)h(are)g -("near")g(eac)m(h)0 3229 y(other)c(to)h(within)e(a)h(user)g(sp)s -(eci\014ed)f(tolerance.)40 b(The)24 b(argumen)m(ts,)h(v)-5 -b(alue)p 2502 3229 28 4 v 34 w(1)24 b(and)f(v)-5 b(alue)p -2979 3229 V 33 w(2)25 b(can)f(b)s(e)f(in)m(teger)i(or)f(real)0 -3341 y(and)32 b(represen)m(t)h(the)g(t)m(w)m(o)h(v)-5 -b(alues)33 b(who's)f(pro)m(ximit)m(y)i(is)f(b)s(eing)f(tested)h(to)h(b) -s(e)e(within)g(the)h(sp)s(eci\014ed)f(tolerance,)0 3454 -y(also)f(an)g(in)m(teger)g(or)g(real:)955 3720 y Fe(near\(value_1,)44 -b(value_2,)h(tolerance\))0 3986 y Fi(When)24 b(a)i(NULL,)e(or)h -(unde\014ned,)f(v)-5 b(alue)25 b(is)g(encoun)m(tered)g(in)g(the)f(FITS) -g(table,)j(the)e(expression)g(will)g(ev)-5 b(aluate)26 -b(to)0 4099 y(NULL)31 b(unless)f(the)h(unde\014ned)e(v)-5 -b(alue)31 b(is)g(not)g(actually)h(required)e(for)h(ev)-5 -b(aluation,)33 b(e.g.)43 b("TR)m(UE)31 b(.or.)43 b(NULL")0 -4212 y(ev)-5 b(aluates)32 b(to)f(TR)m(UE.)g(The)f(follo)m(wing)h(t)m(w) -m(o)h(functions)e(allo)m(w)i(some)f(NULL)f(detection)i(and)e(handling:) -430 4478 y Fe("a)47 b(null)f(value?")667 b(ISNULL\(x\))430 -4591 y("define)45 b(a)j(value)e(for)h(null")190 b(DEFNULL\(x,y\))0 -4857 y Fi(The)36 b(former)h(returns)e(a)i(b)s(o)s(olean)g(v)-5 -b(alue)37 b(of)g(TR)m(UE)g(if)g(the)g(argumen)m(t)g(x)g(is)g(NULL.)g -(The)f(later)i("de\014nes")f(a)0 4970 y(v)-5 b(alue)35 -b(to)g(b)s(e)e(substituted)h(for)g(NULL)g(v)-5 b(alues;)37 -b(it)e(returns)e(the)h(v)-5 b(alue)35 b(of)f(x)g(if)g(x)h(is)f(not)g -(NULL,)h(otherwise)f(it)0 5083 y(returns)29 b(the)i(v)-5 -b(alue)31 b(of)f(y)-8 b(.)0 5381 y Fb(8.11.2)113 b(Bit)36 -b(Masks)0 5601 y Fi(Bit)g(masks)f(can)h(b)s(e)f(used)f(to)i(select)h -(out)e(ro)m(ws)h(from)e(bit)i(columns)f(\(TF)m(ORMn)g(=)g(#X\))h(in)f -(FITS)f(\014les.)55 b(T)-8 b(o)0 5714 y(represen)m(t)30 -b(the)h(mask,)g(binary)-8 b(,)30 b(o)s(ctal,)i(and)e(hex)g(formats)g -(are)h(allo)m(w)m(ed:)p eop end -%%Page: 100 106 -TeXDict begin 100 105 bop 0 299 a Fi(100)1573 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)811 -555 y Fe(binary:)142 b(b0110xx1010000101xxxx00)o(01)811 -668 y(octal:)190 b(o720x1)46 b(->)h(\(b111010000xxx001\))811 -781 y(hex:)286 b(h0FxD)94 b(->)47 b(\(b00001111xxxx1101\))0 -1038 y Fi(In)22 b(all)i(the)f(represen)m(tations,)j(an)c(x)h(or)g(X)g -(is)g(allo)m(w)m(ed)i(in)d(the)h(mask)g(as)g(a)h(wild)e(card.)38 -b(Note)25 b(that)e(the)g(x)g(represen)m(ts)0 1151 y(a)k(di\013eren)m(t) -h(n)m(um)m(b)s(er)e(of)h(wild)f(card)h(bits)g(in)g(eac)m(h)h(represen)m -(tation.)41 b(All)27 b(represen)m(tations)h(are)g(case)g(insensitiv)m -(e.)0 1311 y(T)-8 b(o)28 b(construct)g(the)g(b)s(o)s(olean)f -(expression)h(using)f(the)h(mask)f(as)h(the)g(b)s(o)s(olean)f(equal)h -(op)s(erator)g(describ)s(ed)f(ab)s(o)m(v)m(e)0 1424 y(on)34 -b(a)h(bit)g(table)h(column.)53 b(F)-8 b(or)35 b(example,)i(if)d(y)m(ou) -h(had)f(a)h(7)g(bit)g(column)f(named)g(\015ags)h(in)f(a)h(FITS)f(table) -i(and)0 1537 y(w)m(an)m(ted)31 b(all)g(ro)m(ws)g(ha)m(ving)g(the)f(bit) -h(pattern)f(0010011,)k(the)c(selection)j(expression)d(w)m(ould)g(b)s -(e:)1336 1794 y Fe(flags)47 b(==)g(b0010011)191 1907 -y(or)1336 2019 y(flags)g(.eq.)f(b10011)0 2276 y Fi(It)35 -b(is)g(also)h(p)s(ossible)e(to)i(test)g(if)f(a)g(range)g(of)g(bits)g -(is)g(less)g(than,)h(less)f(than)g(equal,)i(greater)f(than)e(and)h -(greater)0 2389 y(than)30 b(equal)h(to)g(a)g(particular)g(b)s(o)s -(olean)f(v)-5 b(alue:)1336 2646 y Fe(flags)47 b(<=)g(bxxx010xx)1336 -2759 y(flags)g(.gt.)f(bxxx100xx)1336 2872 y(flags)h(.le.)f(b1xxxxxxx)0 -3129 y Fi(Notice)32 b(the)f(use)f(of)h(the)f(x)g(bit)h(v)-5 -b(alue)31 b(to)g(limit)g(the)f(range)h(of)g(bits)f(b)s(eing)g -(compared.)0 3289 y(It)i(is)h(not)f(necessary)h(to)g(sp)s(ecify)f(the)h -(leading)g(\(most)g(signi\014can)m(t\))h(zero)f(\(0\))g(bits)f(in)g -(the)h(mask,)g(as)g(sho)m(wn)e(in)0 3402 y(the)g(second)f(expression)g -(ab)s(o)m(v)m(e.)0 3562 y(Bit)44 b(wise)f(AND,)h(OR)e(and)g(NOT)h(op)s -(erations)g(are)g(also)h(p)s(ossible)e(on)h(t)m(w)m(o)h(or)f(more)g -(bit)g(\014elds)f(using)h(the)0 3675 y('&'\(AND\),)35 -b(')p Fc(j)p Fi('\(OR\),)g(and)e(the)h(')10 b(!'\(NOT\))34 -b(op)s(erators.)51 b(All)34 b(of)f(these)h(op)s(erators)g(result)f(in)h -(a)g(bit)f(\014eld)g(whic)m(h)0 3788 y(can)e(then)f(b)s(e)f(used)h -(with)g(the)h(equal)g(op)s(erator.)41 b(F)-8 b(or)31 -b(example:)1241 4045 y Fe(\(!flags\))45 b(==)j(b1101100)1241 -4158 y(\(flags)e(&)h(b1000001\))f(==)h(bx000001)0 4414 -y Fi(Bit)35 b(\014elds)f(can)g(b)s(e)f(app)s(ended)g(as)h(w)m(ell)h -(using)f(the)g('+')g(op)s(erator.)53 b(Strings)33 b(can)i(b)s(e)e -(concatenated)j(this)e(w)m(a)m(y)-8 b(,)0 4527 y(to)s(o.)0 -4818 y Fb(8.11.3)113 b(V)-9 b(ector)36 b(Columns)0 5036 -y Fi(V)-8 b(ector)37 b(columns)e(can)h(also)g(b)s(e)f(used)f(in)h -(building)g(the)g(expression.)56 b(No)36 b(sp)s(ecial)g(syn)m(tax)f(is) -h(required)e(if)i(one)0 5149 y(w)m(an)m(ts)46 b(to)f(op)s(erate)h(on)f -(all)h(elemen)m(ts)g(of)f(the)h(v)m(ector.)86 b(Simply)44 -b(use)h(the)g(column)g(name)g(as)g(for)g(a)g(scalar)0 -5262 y(column.)d(V)-8 b(ector)32 b(columns)f(can)g(b)s(e)f(freely)h(in) -m(termixed)h(with)e(scalar)i(columns)e(or)h(constan)m(ts)h(in)f -(virtually)g(all)0 5375 y(expressions.)40 b(The)29 b(result)g(will)g(b) -s(e)g(of)g(the)g(same)h(dimension)e(as)i(the)f(v)m(ector.)42 -b(Tw)m(o)29 b(v)m(ectors)i(in)e(an)g(expression,)0 5488 -y(though,)f(need)e(to)i(ha)m(v)m(e)g(the)f(same)g(n)m(um)m(b)s(er)f(of) -h(elemen)m(ts)h(and)e(ha)m(v)m(e)j(the)e(same)g(dimensions.)39 -b(The)26 b(only)h(places)0 5601 y(a)35 b(v)m(ector)h(column)e(cannot)h -(b)s(e)f(used)f(\(for)i(no)m(w,)g(an)m(yw)m(a)m(y\))h(are)f(the)g(SA)m -(O)f(region)h(functions)f(and)f(the)i(NEAR)0 5714 y(b)s(o)s(olean)30 -b(function.)p eop end -%%Page: 101 107 -TeXDict begin 101 106 bop 0 299 a Fg(8.11.)73 b(R)m(O)m(W)31 -b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)1982 b Fi(101)0 -555 y(Arithmetic)24 b(and)e(logical)k(op)s(erations)d(are)h(all)g(p)s -(erformed)d(on)i(an)g(elemen)m(t)h(b)m(y)f(elemen)m(t)i(basis.)38 -b(Comparing)23 b(t)m(w)m(o)0 668 y(v)m(ector)32 b(columns,)e(eg)h -("COL1)f(==)g(COL2",)g(th)m(us)g(results)g(in)g(another)g(v)m(ector)i -(of)e(b)s(o)s(olean)h(v)-5 b(alues)30 b(indicating)0 -781 y(whic)m(h)g(elemen)m(ts)i(of)e(the)h(t)m(w)m(o)h(v)m(ectors)f(are) -g(equal.)0 941 y(Eigh)m(t)g(functions)f(are)h(a)m(v)-5 -b(ailable)33 b(that)e(op)s(erate)g(on)f(a)h(v)m(ector)h(and)d(return)h -(a)g(scalar)i(result:)191 1172 y Fe("minimum")284 b(MIN\(V\))475 -b("maximum")714 b(MAX\(V\))191 1285 y("average")284 b(AVERAGE\(V\))f -("median")762 b(MEDIAN\(V\))191 1398 y("summation")188 -b(SUM\(V\))475 b("standard)46 b(deviation")188 b(STDDEV\(V\))191 -1511 y("#)47 b(of)g(values")94 b(NELEM\(V\))379 b("#)48 -b(of)f(non-null)e(values")94 b(NVALID\(V\))0 1742 y Fi(where)40 -b(V)h(represen)m(ts)g(the)g(name)g(of)h(a)f(v)m(ector)h(column)f(or)g -(a)h(man)m(ually)f(constructed)g(v)m(ector)i(using)d(curly)0 -1854 y(brac)m(k)m(ets)27 b(as)f(describ)s(ed)e(b)s(elo)m(w.)39 -b(The)25 b(\014rst)g(6)h(of)g(these)g(functions)f(ignore)h(an)m(y)g(n)m -(ull)f(v)-5 b(alues)26 b(in)f(the)h(v)m(ector)h(when)0 -1967 y(computing)k(the)f(result.)41 b(The)30 b(STDDEV\(\))h(function)g -(computes)f(the)h(sample)g(standard)e(deviation,)j(i.e.)42 -b(it)31 b(is)0 2080 y(prop)s(ortional)f(to)h(1/SQR)-8 -b(T\(N-1\))32 b(instead)f(of)g(1/SQR)-8 b(T\(N\),)31 -b(where)f(N)h(is)f(NV)-10 b(ALID\(V\).)0 2240 y(The)32 -b(SUM)h(function)f(literally)j(sums)c(all)j(the)f(elemen)m(ts)h(in)f -(x,)g(returning)f(a)h(scalar)h(v)-5 b(alue.)48 b(If)32 -b(x)h(is)g(a)g(b)s(o)s(olean)0 2353 y(v)m(ector,)40 b(SUM)c(returns)f -(the)h(n)m(um)m(b)s(er)f(of)i(TR)m(UE)f(elemen)m(ts.)60 -b(The)36 b(NELEM)g(function)g(returns)f(the)h(n)m(um)m(b)s(er)0 -2466 y(of)i(elemen)m(ts)h(in)f(v)m(ector)h(x)f(whereas)f(NV)-10 -b(ALID)39 b(return)d(the)i(n)m(um)m(b)s(er)f(of)h(non-n)m(ull)f(elemen) -m(ts)j(in)d(the)h(v)m(ector.)0 2579 y(\(NELEM)28 b(also)h(op)s(erates)f -(on)g(bit)f(and)g(string)h(columns,)g(returning)f(their)h(column)f -(widths.\))40 b(As)27 b(an)h(example,)0 2692 y(to)42 -b(test)g(whether)f(all)h(elemen)m(ts)h(of)f(t)m(w)m(o)g(v)m(ectors)h -(satisfy)f(a)g(giv)m(en)g(logical)i(comparison,)g(one)e(can)g(use)f -(the)0 2805 y(expression)668 3036 y Fe(SUM\()47 b(COL1)f(>)i(COL2)f(\)) -g(==)g(NELEM\()f(COL1)h(\))0 3267 y Fi(whic)m(h)32 b(will)g(return)f -(TR)m(UE)h(if)g(all)h(elemen)m(ts)g(of)f(COL1)g(are)g(greater)h(than)f -(their)g(corresp)s(onding)f(elemen)m(ts)i(in)0 3380 y(COL2.)0 -3540 y(T)-8 b(o)32 b(sp)s(ecify)f(a)i(single)f(elemen)m(t)h(of)f(a)g(v) -m(ector,)i(giv)m(e)f(the)f(column)f(name)h(follo)m(w)m(ed)h(b)m(y)f(a)g -(comma-separated)h(list)0 3653 y(of)c(co)s(ordinates)g(enclosed)h(in)e -(square)h(brac)m(k)m(ets.)41 b(F)-8 b(or)30 b(example,)g(if)e(a)h(v)m -(ector)i(column)d(named)h(PHAS)f(exists)h(in)0 3766 y(the)e(table)g(as) -g(a)g(one)g(dimensional,)h(256)g(comp)s(onen)m(t)f(list)g(of)g(n)m(um)m -(b)s(ers)e(from)h(whic)m(h)h(y)m(ou)g(w)m(an)m(ted)g(to)g(select)i(the) -0 3878 y(57th)j(comp)s(onen)m(t)g(for)f(use)g(in)g(the)h(expression,)f -(then)h(PHAS[57])g(w)m(ould)f(do)h(the)f(tric)m(k.)45 -b(Higher)32 b(dimensional)0 3991 y(arra)m(ys)41 b(of)h(data)f(ma)m(y)h -(app)s(ear)f(in)f(a)i(column.)73 b(But)41 b(in)g(order)f(to)i(in)m -(terpret)f(them,)j(the)e(TDIMn)e(k)m(eyw)m(ord)0 4104 -y(m)m(ust)34 b(app)s(ear)g(in)g(the)g(header.)52 b(Assuming)34 -b(that)h(a)f(\(4,4,4,4\))k(arra)m(y)c(is)h(pac)m(k)m(ed)g(in)m(to)g -(eac)m(h)h(ro)m(w)e(of)g(a)h(column)0 4217 y(named)26 -b(ARRA)-8 b(Y4D,)28 b(the)f(\(1,2,3,4\))i(comp)s(onen)m(t)e(elemen)m(t) -g(of)g(eac)m(h)g(ro)m(w)g(is)f(accessed)i(b)m(y)e(ARRA)-8 -b(Y4D[1,2,3,4].)0 4330 y(Arra)m(ys)33 b(up)e(to)j(dimension)e(5)h(are)f -(curren)m(tly)h(supp)s(orted.)46 b(Eac)m(h)33 b(v)m(ector)h(index)e -(can)h(itself)g(b)s(e)f(an)h(expression,)0 4443 y(although)39 -b(it)g(m)m(ust)g(ev)-5 b(aluate)40 b(to)f(an)g(in)m(teger)h(v)-5 -b(alue)39 b(within)f(the)h(b)s(ounds)d(of)j(the)g(v)m(ector.)67 -b(V)-8 b(ector)40 b(columns)0 4556 y(whic)m(h)31 b(con)m(tain)h(spaces) -g(or)f(arithmetic)h(op)s(erators)g(m)m(ust)f(ha)m(v)m(e)h(their)f -(names)g(enclosed)h(in)f("$")h(c)m(haracters)h(as)0 4669 -y(with)d($ARRA)-8 b(Y-4D$[1,2,3,4].)0 4829 y(A)45 b(more)f(C-lik)m(e)i -(syn)m(tax)g(for)e(sp)s(ecifying)g(v)m(ector)j(indices)d(is)h(also)h(a) -m(v)-5 b(ailable.)85 b(The)45 b(elemen)m(t)h(used)d(in)i(the)0 -4942 y(preceding)28 b(example)h(alternativ)m(ely)i(could)d(b)s(e)g(sp)s -(eci\014ed)g(with)f(the)i(syn)m(tax)g(ARRA)-8 b(Y4D[4][3][2][1].)45 -b(Note)30 b(the)0 5055 y(rev)m(erse)40 b(order)f(of)h(indices)f(\(as)h -(in)f(C\),)h(as)f(w)m(ell)i(as)e(the)h(fact)g(that)g(the)g(v)-5 -b(alues)40 b(are)f(still)i(ones-based)e(\(as)h(in)0 5168 -y(F)-8 b(ortran)39 b({)g(adopted)g(to)g(a)m(v)m(oid)h(am)m(biguit)m(y)g -(for)f(1D)g(v)m(ectors\).)67 b(With)39 b(this)g(syn)m(tax,)i(one)e(do)s -(es)f(not)h(need)f(to)0 5281 y(sp)s(ecify)30 b(all)h(of)g(the)f -(indices.)41 b(T)-8 b(o)31 b(extract)h(a)f(3D)g(slice)g(of)g(this)f(4D) -h(arra)m(y)-8 b(,)32 b(use)e(ARRA)-8 b(Y4D[4].)0 5441 -y(V)g(ariable-length)33 b(v)m(ector)f(columns)e(are)g(not)h(supp)s -(orted.)0 5601 y(V)-8 b(ectors)24 b(can)e(b)s(e)f(man)m(ually)h -(constructed)h(within)e(the)h(expression)g(using)f(a)h(comma-separated) -i(list)f(of)f(elemen)m(ts)0 5714 y(surrounded)35 b(b)m(y)j(curly)g -(braces)h(\(')p Fc(fg)p Fi('\).)66 b(F)-8 b(or)38 b(example,)j(')p -Fc(f)p Fi(1,3,6,1)p Fc(g)p Fi(')h(is)d(a)f(4-elemen)m(t)i(v)m(ector)g -(con)m(taining)g(the)p eop end -%%Page: 102 108 -TeXDict begin 102 107 bop 0 299 a Fi(102)1573 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fi(v)j(alues)26 b(1,)h(3,)g(6,)g(and)e(1.)40 b(The)25 -b(v)m(ector)i(can)f(con)m(tain)h(only)f(b)s(o)s(olean,)g(in)m(teger,)j -(and)c(real)h(v)-5 b(alues)26 b(\(or)g(expressions\).)0 -668 y(The)e(elemen)m(ts)h(will)g(b)s(e)f(promoted)g(to)h(the)g(highest) -f(datat)m(yp)s(e)h(presen)m(t.)39 b(An)m(y)24 b(elemen)m(ts)i(whic)m(h) -e(are)h(themselv)m(es)0 781 y(v)m(ectors,)40 b(will)d(b)s(e)f(expanded) -g(out)h(with)g(eac)m(h)g(of)g(its)g(elemen)m(ts)i(b)s(ecoming)d(an)h -(elemen)m(t)h(in)f(the)g(constructed)0 894 y(v)m(ector.)0 -1247 y Fb(8.11.4)113 b(Go)s(o)s(d)38 b(Time)g(In)m(terv)-6 -b(al)37 b(Filtering)0 1479 y Fi(A)44 b(common)g(\014ltering)h(metho)s -(d)e(in)m(v)m(olv)m(es)j(selecting)g(ro)m(ws)e(whic)m(h)f(ha)m(v)m(e)j -(a)e(time)h(v)-5 b(alue)44 b(whic)m(h)g(lies)g(within)0 -1592 y(what)37 b(is)g(called)i(a)f(Go)s(o)s(d)f(Time)g(In)m(terv)-5 -b(al)38 b(or)f(GTI.)g(The)g(time)h(in)m(terv)-5 b(als)38 -b(are)g(de\014ned)e(in)h(a)g(separate)i(FITS)0 1705 y(table)i -(extension)g(whic)m(h)e(con)m(tains)i(2)g(columns)f(giving)g(the)h -(start)f(and)g(stop)g(time)g(of)g(eac)m(h)i(go)s(o)s(d)e(in)m(terv)-5 -b(al.)0 1818 y(The)34 b(\014ltering)h(op)s(eration)h(accepts)g(only)e -(those)i(ro)m(ws)e(of)h(the)g(input)f(table)i(whic)m(h)e(ha)m(v)m(e)i -(an)f(asso)s(ciated)h(time)0 1930 y(whic)m(h)f(falls)i(within)e(one)h -(of)g(the)g(time)g(in)m(terv)-5 b(als)37 b(de\014ned)e(in)g(the)h(GTI)g -(extension.)57 b(A)36 b(high)g(lev)m(el)h(function,)0 -2043 y(gti\014lter\(a,b,c,d\),)44 b(is)c(a)m(v)-5 b(ailable)42 -b(whic)m(h)d(ev)-5 b(aluates)41 b(eac)m(h)g(ro)m(w)e(of)h(the)f(input)g -(table)h(and)f(returns)f(TR)m(UE)i(or)0 2156 y(F)-10 -b(ALSE)30 b(dep)s(ending)f(whether)h(the)g(ro)m(w)h(is)f(inside)g(or)g -(outside)h(the)g(go)s(o)s(d)f(time)h(in)m(terv)-5 b(al.)42 -b(The)30 b(syn)m(tax)h(is)286 2469 y Fe(gtifilter\()45 -b([)j("gtifile")d([,)i(expr)g([,)g("STARTCOL",)e("STOPCOL")g(])j(])f(]) -g(\))0 2782 y Fi(where)20 b(eac)m(h)h("[]")h(demarks)e(optional)h -(parameters.)38 b(Note)21 b(that)g(the)g(quotes)f(around)g(the)g -(gti\014le)i(and)d(ST)-8 b(AR)g(T/STOP)0 2895 y(column)33 -b(are)h(required.)50 b(Either)34 b(single)g(or)g(double)f(quotes)h(ma)m -(y)g(b)s(e)f(used.)50 b(In)33 b(cases)h(where)g(this)f(expression)0 -3008 y(is)d(en)m(tered)g(on)g(the)g(Unix)g(command)g(line,)g(enclose)h -(the)f(en)m(tire)h(expression)f(in)f(double)h(quotes,)g(and)g(then)f -(use)0 3121 y(single)c(quotes)g(within)e(the)i(expression)f(to)h -(enclose)g(the)g('gti\014le')h(and)d(other)i(terms.)38 -b(It)25 b(is)f(also)h(usually)f(p)s(ossible)0 3234 y(to)38 -b(do)e(the)h(rev)m(erse,)j(and)c(enclose)i(the)f(whole)g(expression)g -(in)f(single)i(quotes)f(and)f(then)h(use)f(double)g(quotes)0 -3347 y(within)d(the)g(expression.)50 b(The)33 b(gti\014le,)i(if)f(sp)s -(eci\014ed,)f(can)h(b)s(e)f(blank)g(\(""\))i(whic)m(h)e(will)g(mean)h -(to)g(use)f(the)h(\014rst)0 3460 y(extension)g(with)g(the)f(name)h -("*GTI*")h(in)f(the)f(curren)m(t)h(\014le,)h(a)f(plain)f(extension)h -(sp)s(eci\014er)f(\(eg,)j("+2",)g("[2]",)0 3573 y(or)30 -b("[STDGTI]"\))i(whic)m(h)e(will)h(b)s(e)f(used)f(to)j(select)g(an)e -(extension)h(in)f(the)h(curren)m(t)f(\014le,)h(or)f(a)h(regular)g -(\014lename)0 3686 y(with)f(or)h(without)f(an)h(extension)g(sp)s -(eci\014er)f(whic)m(h)g(in)g(the)h(latter)h(case)f(will)g(mean)f(to)i -(use)e(the)h(\014rst)e(extension)0 3799 y(with)37 b(an)g(extension)g -(name)h("*GTI*".)62 b(Expr)36 b(can)h(b)s(e)g(an)m(y)g(arithmetic)i -(expression,)f(including)f(simply)g(the)0 3911 y(time)f(column)g(name.) -57 b(A)36 b(v)m(ector)h(time)g(expression)e(will)h(pro)s(duce)f(a)h(v)m -(ector)h(b)s(o)s(olean)f(result.)57 b(ST)-8 b(AR)g(TCOL)0 -4024 y(and)27 b(STOPCOL)f(are)i(the)g(names)g(of)g(the)g(ST)-8 -b(AR)g(T/STOP)26 b(columns)i(in)f(the)h(GTI)g(extension.)41 -b(If)27 b(one)h(of)g(them)0 4137 y(is)i(sp)s(eci\014ed,)g(they)h(b)s -(oth)f(m)m(ust)g(b)s(e.)0 4297 y(In)21 b(its)h(simplest)g(form,)i(no)d -(parameters)h(need)g(to)h(b)s(e)e(pro)m(vided)g({)h(default)g(v)-5 -b(alues)22 b(will)h(b)s(e)e(used.)37 b(The)21 b(expression)0 -4410 y("gti\014lter\(\)")33 b(is)e(equiv)-5 b(alen)m(t)31 -b(to)334 4723 y Fe(gtifilter\()45 b("",)i(TIME,)f("*START*",)f -("*STOP*")h(\))0 5036 y Fi(This)31 b(will)g(searc)m(h)h(the)g(curren)m -(t)f(\014le)g(for)g(a)h(GTI)f(extension,)h(\014lter)g(the)f(TIME)g -(column)g(in)g(the)h(curren)m(t)f(table,)0 5149 y(using)j(ST)-8 -b(AR)g(T/STOP)34 b(times)i(tak)m(en)f(from)g(columns)f(in)h(the)g(GTI)g -(extension)g(with)g(names)f(con)m(taining)j(the)0 5262 -y(strings)32 b("ST)-8 b(AR)g(T")33 b(and)e("STOP".)46 -b(The)32 b(wildcards)f(\('*'\))j(allo)m(w)g(sligh)m(t)f(v)-5 -b(ariations)33 b(in)f(naming)g(con)m(v)m(en)m(tions)0 -5375 y(suc)m(h)38 b(as)g("TST)-8 b(AR)g(T")39 b(or)f("ST)-8 -b(AR)g(TTIME".)65 b(The)37 b(same)i(default)g(v)-5 b(alues)38 -b(apply)g(for)g(unsp)s(eci\014ed)f(parame-)0 5488 y(ters)f(when)f(the)h -(\014rst)f(one)i(or)f(t)m(w)m(o)h(parameters)f(are)h(sp)s(eci\014ed.)56 -b(The)36 b(function)f(automatically)k(searc)m(hes)e(for)0 -5601 y(TIMEZER)m(O/I/F)g(k)m(eyw)m(ords)f(in)g(the)h(curren)m(t)f(and)g -(GTI)g(extensions,)i(applying)f(a)f(relativ)m(e)j(time)e(o\013set,)i -(if)0 5714 y(necessary)-8 b(.)p eop end -%%Page: 103 109 -TeXDict begin 103 108 bop 0 299 a Fg(8.11.)73 b(R)m(O)m(W)31 -b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)1982 b Fi(103)0 -555 y Fb(8.11.5)113 b(Spatial)38 b(Region)g(Filtering)0 -775 y Fi(Another)g(common)g(\014ltering)g(metho)s(d)f(selects)i(ro)m -(ws)f(based)g(on)f(whether)h(the)g(spatial)h(p)s(osition)e(asso)s -(ciated)0 887 y(with)32 b(eac)m(h)i(ro)m(w)e(is)h(lo)s(cated)h(within)e -(a)h(giv)m(en)g(2-dimensional)g(region.)48 b(The)32 b(syn)m(tax)h(for)f -(this)h(high-lev)m(el)h(\014lter)0 1000 y(is)334 1262 -y Fe(regfilter\()45 b("regfilename")f([)k(,)f(Xexpr,)f(Yexpr)h([)g(,)h -("wcs)e(cols")h(])g(])g(\))0 1524 y Fi(where)22 b(eac)m(h)i("[]")g -(demarks)e(optional)i(parameters.)38 b(The)22 b(region)h(\014le)g(name) -f(is)h(required)f(and)g(m)m(ust)g(b)s(e)g(enclosed)0 -1637 y(in)34 b(quotes.)51 b(The)33 b(remaining)h(parameters)h(are)f -(optional.)52 b(There)33 b(are)i(2)f(supp)s(orted)e(formats)i(for)f -(the)h(region)0 1750 y(\014le:)62 b(ASCI)s(I)39 b(\014le)h(or)h(FITS)f -(binary)g(table.)73 b(The)40 b(region)h(\014le)g(con)m(tains)h(a)f -(list)g(of)g(one)g(or)g(more)g(geometric)0 1863 y(shap)s(es)30 -b(\(circle,)j(ellipse,)g(b)s(o)m(x,)e(etc.\))44 b(whic)m(h)31 -b(de\014nes)f(a)i(region)g(on)f(the)g(celestial)j(sphere)c(or)h(an)g -(area)h(within)f(a)0 1975 y(particular)36 b(2D)g(image.)57 -b(The)35 b(region)h(\014le)f(is)g(t)m(ypically)j(generated)e(using)f -(an)g(image)i(displa)m(y)e(program)g(suc)m(h)0 2088 y(as)e(fv/PO)m(W)g -(\(distribute)f(b)m(y)h(the)f(HEASAR)m(C\),)h(or)g(ds9)f(\(distributed) -g(b)m(y)g(the)h(Smithsonian)f(Astroph)m(ysical)0 2201 -y(Observ)-5 b(atory\).)69 b(Users)39 b(should)g(refer)g(to)h(the)g(do)s -(cumen)m(tation)h(pro)m(vided)e(with)g(these)h(programs)f(for)h(more)0 -2314 y(details)29 b(on)f(the)g(syn)m(tax)h(used)e(in)h(the)h(region)f -(\014les.)40 b(The)28 b(FITS)f(region)i(\014le)f(format)h(is)f -(de\014ned)f(in)h(a)g(do)s(cumen)m(t)0 2427 y(a)m(v)-5 -b(ailable)33 b(from)d(the)g(FITS)g(Supp)s(ort)e(O\016ce)j(at)g(h)m -(ttp://\014ts.gsfc.nasa.go)m(v/)k(registry/)c(region.h)m(tml)0 -2587 y(In)21 b(its)h(simplest)g(form,)i(\(e.g.,)h -(reg\014lter\("region.reg"\))h(\))c(the)g(co)s(ordinates)g(in)g(the)g -(default)g('X')h(and)e('Y')h(columns)0 2700 y(will)43 -b(b)s(e)g(used)f(to)i(determine)f(if)g(eac)m(h)h(ro)m(w)f(is)g(inside)g -(or)g(outside)g(the)g(area)h(sp)s(eci\014ed)e(in)h(the)g(region)h -(\014le.)0 2813 y(Alternate)32 b(p)s(osition)e(column)g(names,)h(or)f -(expressions,)h(ma)m(y)g(b)s(e)e(en)m(tered)i(if)g(needed,)f(as)h(in) -382 3075 y Fe(regfilter\("region.reg",)41 b(XPOS,)47 -b(YPOS\))0 3337 y Fi(Region)37 b(\014ltering)f(can)g(b)s(e)f(applied)g -(most)h(unam)m(biguously)f(if)h(the)g(p)s(ositions)g(in)f(the)h(region) -g(\014le)g(and)f(in)h(the)0 3449 y(table)g(to)g(b)s(e)e(\014ltered)h -(are)h(b)s(oth)e(giv)m(e)j(in)e(terms)g(of)g(absolute)h(celestial)i(co) -s(ordinate)e(units.)54 b(In)35 b(this)g(case)h(the)0 -3562 y(lo)s(cations)26 b(and)d(sizes)i(of)g(the)f(geometric)i(shap)s -(es)e(in)g(the)g(region)h(\014le)f(are)h(sp)s(eci\014ed)f(in)g(angular) -g(units)g(on)g(the)g(sky)0 3675 y(\(e.g.,)32 b(p)s(ositions)e(giv)m(en) -i(in)e(R.A.)g(and)g(Dec.)42 b(and)30 b(sizes)h(in)f(arcseconds)g(or)h -(arcmin)m(utes\).)41 b(Similarly)-8 b(,)31 b(eac)m(h)h(ro)m(w)0 -3788 y(of)h(the)h(\014ltered)f(table)h(will)f(ha)m(v)m(e)i(a)e -(celestial)j(co)s(ordinate)e(asso)s(ciated)g(with)f(it.)50 -b(This)32 b(asso)s(ciation)j(is)e(usually)0 3901 y(implemen)m(ted)39 -b(using)e(a)i(set)g(of)f(so-called)i('W)-8 b(orld)39 -b(Co)s(ordinate)g(System')f(\(or)h(W)m(CS\))f(FITS)g(k)m(eyw)m(ords)g -(that)0 4014 y(de\014ne)27 b(the)g(co)s(ordinate)h(transformation)g -(that)g(m)m(ust)f(b)s(e)f(applied)h(to)h(the)g(v)-5 b(alues)27 -b(in)g(the)h('X')g(and)e('Y')i(columns)0 4127 y(to)j(calculate)i(the)d -(co)s(ordinate.)0 4287 y(Alternativ)m(ely)-8 b(,)30 b(one)d(can)g(p)s -(erform)e(spatial)j(\014ltering)e(using)g(unitless)h('pixel')g(co)s -(ordinates)h(for)e(the)h(regions)g(and)0 4400 y(ro)m(w)33 -b(p)s(ositions.)49 b(In)33 b(this)g(case)h(the)f(user)g(m)m(ust)g(b)s -(e)f(careful)h(to)h(ensure)f(that)g(the)h(p)s(ositions)f(in)g(the)g(2)g -(\014les)h(are)0 4513 y(self-consisten)m(t.)54 b(A)34 -b(t)m(ypical)i(problem)d(is)h(that)h(the)f(region)h(\014le)f(ma)m(y)h -(b)s(e)e(generated)j(using)d(a)i(binned)d(image,)0 4626 -y(but)g(the)h(un)m(binned)e(co)s(ordinates)i(are)g(giv)m(en)h(in)e(the) -h(ev)m(en)m(t)i(table.)48 b(The)32 b(R)m(OSA)-8 b(T)33 -b(ev)m(en)m(ts)h(\014les,)g(for)e(example,)0 4739 y(ha)m(v)m(e)f(X)f -(and)f(Y)g(pixel)h(co)s(ordinates)g(that)h(range)f(from)f(1)h(-)g -(15360.)42 b(These)30 b(co)s(ordinates)g(are)g(t)m(ypically)h(binned)0 -4852 y(b)m(y)i(a)h(factor)g(of)f(32)h(to)g(pro)s(duce)e(a)i(480x480)i -(pixel)d(image.)51 b(If)32 b(one)i(then)f(uses)g(a)g(region)h(\014le)f -(generated)h(from)0 4965 y(this)c(image)i(\(in)f(image)g(pixel)g -(units\))g(to)g(\014lter)f(the)h(R)m(OSA)-8 b(T)30 b(ev)m(en)m(ts)i -(\014le,)f(then)f(the)h(X)g(and)f(Y)g(column)h(v)-5 b(alues)0 -5077 y(m)m(ust)30 b(b)s(e)g(con)m(v)m(erted)i(to)f(corresp)s(onding)e -(pixel)i(units)f(as)g(in:)382 5339 y Fe(regfilter\("rosat.reg",)42 -b(X/32.+.5,)j(Y/32.+.5\))0 5601 y Fi(Note)h(that)f(this)f(binning)f -(con)m(v)m(ersion)j(is)e(not)h(necessary)g(if)f(the)h(region)g(\014le)f -(is)h(sp)s(eci\014ed)e(using)h(celestial)0 5714 y(co)s(ordinate)h -(units)f(instead)g(of)g(pixel)h(units)f(b)s(ecause)g(CFITSIO)e(is)j -(then)e(able)i(to)g(directly)g(compare)g(the)p eop end -%%Page: 104 110 -TeXDict begin 104 109 bop 0 299 a Fi(104)1573 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fi(celestial)30 b(co)s(ordinate)f(of)e(eac)m(h)i(ro)m(w)f(in)f -(the)h(table)g(with)g(the)f(celestial)k(co)s(ordinates)d(in)f(the)h -(region)g(\014le)g(without)0 668 y(ha)m(ving)j(to)g(kno)m(w)f(an)m -(ything)h(ab)s(out)f(ho)m(w)h(the)f(image)i(ma)m(y)f(ha)m(v)m(e)g(b)s -(een)f(binned.)0 828 y(The)f(last)h("w)m(cs)g(cols")h(parameter)f -(should)e(rarely)h(b)s(e)g(needed.)40 b(If)29 b(supplied,)f(this)i -(string)f(con)m(tains)i(the)e(names)0 941 y(of)37 b(the)g(2)h(columns)f -(\(space)h(or)f(comma)g(separated\))h(whic)m(h)f(ha)m(v)m(e)h(the)g -(asso)s(ciated)g(W)m(CS)f(k)m(eyw)m(ords.)61 b(If)37 -b(not)0 1054 y(supplied,)f(the)g(\014lter)g(will)h(scan)f(the)g(X)g -(and)f(Y)h(expressions)g(for)g(column)f(names.)58 b(If)35 -b(only)h(one)h(is)f(found)e(in)0 1167 y(eac)m(h)e(expression,)e(those)h -(columns)f(will)h(b)s(e)e(used,)h(otherwise)h(an)f(error)g(will)h(b)s -(e)f(returned.)0 1327 y(These)g(region)h(shap)s(es)f(are)g(supp)s -(orted)f(\(names)h(are)h(case)h(insensitiv)m(e\):)334 -1591 y Fe(Point)428 b(\()48 b(X1,)f(Y1)g(\))715 b(<-)48 -b(One)f(pixel)f(square)g(region)334 1704 y(Line)476 b(\()48 -b(X1,)f(Y1,)g(X2,)f(Y2)i(\))333 b(<-)48 b(One)f(pixel)f(wide)h(region) -334 1817 y(Polygon)332 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(...)g(\))95 -b(<-)48 b(Rest)e(are)h(interiors)e(with)334 1930 y(Rectangle)236 -b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(A)h(\))334 b(|)47 b(boundaries)e -(considered)334 2043 y(Box)524 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A) -i(\))143 b(V)47 b(within)f(the)h(region)334 2156 y(Diamond)332 -b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A)i(\))334 2269 -y(Circle)380 b(\()48 b(Xc,)f(Yc,)g(R)g(\))334 2382 y(Annulus)332 -b(\()48 b(Xc,)f(Yc,)g(Rin,)f(Rout)h(\))334 2494 y(Ellipse)332 -b(\()48 b(Xc,)f(Yc,)g(Rx,)f(Ry,)h(A)h(\))334 2607 y(Elliptannulus)c(\() -k(Xc,)f(Yc,)g(Rinx,)f(Riny,)g(Routx,)g(Routy,)g(Ain,)h(Aout)g(\))334 -2720 y(Sector)380 b(\()48 b(Xc,)f(Yc,)g(Amin,)f(Amax)h(\))0 -2984 y Fi(where)28 b(\(Xc,Yc\))j(is)d(the)h(co)s(ordinate)h(of)e(the)h -(shap)s(e's)f(cen)m(ter;)j(\(X#,Y#\))e(are)g(the)g(co)s(ordinates)g(of) -g(the)g(shap)s(e's)0 3097 y(edges;)36 b(Rxxx)d(are)h(the)f(shap)s(es')g -(v)-5 b(arious)34 b(Radii)f(or)h(semi-ma)5 b(jor/minor)34 -b(axes;)i(and)d(Axxx)g(are)h(the)f(angles)i(of)0 3210 -y(rotation)e(\(or)e(b)s(ounding)f(angles)i(for)f(Sector\))h(in)f -(degrees.)44 b(F)-8 b(or)32 b(rotated)h(shap)s(es,)e(the)g(rotation)i -(angle)f(can)g(b)s(e)0 3323 y(left)g(o\013,)h(indicating)f(no)f -(rotation.)46 b(Common)31 b(alternate)i(names)e(for)h(the)f(regions)h -(can)g(also)h(b)s(e)d(used:)43 b(rotb)s(o)m(x)0 3436 -y(=)29 b(b)s(o)m(x;)g(rotrectangle)i(=)e(rectangle;)i(\(rot\)rhom)m -(bus)e(=)f(\(rot\)diamond;)j(and)d(pie)h(=)f(sector.)42 -b(When)28 b(a)i(shap)s(e's)0 3549 y(name)e(is)g(preceded)f(b)m(y)h(a)g -(min)m(us)g(sign,)g('-',)i(the)e(de\014ned)e(region)j(is)f(instead)g -(the)g(area)h(*outside*)g(its)f(b)s(oundary)0 3662 y(\(ie,)36 -b(the)e(region)h(is)f(in)m(v)m(erted\).)53 b(All)34 b(the)g(shap)s(es)f -(within)h(a)g(single)h(region)f(\014le)h(are)f(OR'd)f(together)j(to)e -(create)0 3775 y(the)29 b(region,)i(and)d(the)i(order)f(is)g -(signi\014can)m(t.)41 b(The)29 b(o)m(v)m(erall)i(w)m(a)m(y)g(of)e(lo)s -(oking)h(at)g(region)g(\014les)f(is)g(that)h(if)f(the)h(\014rst)0 -3888 y(region)f(is)g(an)g(excluded)g(region)g(then)f(a)i(dumm)m(y)d -(included)h(region)i(of)f(the)g(whole)g(detector)h(is)f(inserted)f(in)h -(the)0 4000 y(fron)m(t.)40 b(Then)25 b(eac)m(h)j(region)f(sp)s -(eci\014cation)h(as)f(it)g(is)g(pro)s(cessed)f(o)m(v)m(errides)h(an)m -(y)g(selections)i(inside)d(of)h(that)g(region)0 4113 -y(sp)s(eci\014ed)36 b(b)m(y)g(previous)g(regions.)59 -b(Another)37 b(w)m(a)m(y)g(of)g(thinking)f(ab)s(out)g(this)g(is)h(that) -g(if)f(a)h(previous)f(excluded)0 4226 y(region)31 b(is)f(completely)i -(inside)f(of)f(a)h(subsequen)m(t)e(included)h(region)h(the)g(excluded)f -(region)h(is)f(ignored.)0 4386 y(The)44 b(p)s(ositional)i(co)s -(ordinates)g(ma)m(y)f(b)s(e)g(giv)m(en)h(either)f(in)g(pixel)g(units,)j -(decimal)e(degrees)g(or)f(hh:mm:ss.s,)0 4499 y(dd:mm:ss.s)25 -b(units.)38 b(The)26 b(shap)s(e)f(sizes)i(ma)m(y)f(b)s(e)g(giv)m(en)h -(in)e(pixels,)j(degrees,)f(arcmin)m(utes,)h(or)e(arcseconds.)40 -b(Lo)s(ok)0 4612 y(at)31 b(examples)g(of)f(region)h(\014le)g(pro)s -(duced)d(b)m(y)i(fv/PO)m(W)h(or)g(ds9)f(for)g(further)f(details)i(of)g -(the)f(region)h(\014le)f(format.)0 4772 y(There)37 b(are)g(three)g -(functions)g(that)g(are)h(primarily)f(for)f(use)h(with)g(SA)m(O)g -(region)g(\014les)g(and)g(the)g(FSA)m(OI)g(task,)0 4885 -y(but)e(they)h(can)h(b)s(e)e(used)g(directly)-8 b(.)59 -b(They)36 b(return)f(a)h(b)s(o)s(olean)g(true)g(or)g(false)g(dep)s -(ending)f(on)h(whether)f(a)i(t)m(w)m(o)0 4998 y(dimensional)31 -b(p)s(oin)m(t)f(is)g(in)g(the)h(region)g(or)f(not:)191 -5262 y Fe("point)46 b(in)h(a)h(circular)d(region")477 -5375 y(circle\(xcntr,ycntr,radius)o(,Xco)o(lumn)o(,Yc)o(olum)o(n\))191 -5601 y("point)h(in)h(an)g(elliptical)e(region")430 5714 -y(ellipse\(xcntr,ycntr,xhl)o(f_w)o(dth,)o(yhlf)o(_wd)o(th,r)o(otat)o -(ion)o(,Xco)o(lumn)o(,Yc)o(olum)o(n\))p eop end -%%Page: 105 111 -TeXDict begin 105 110 bop 0 299 a Fg(8.11.)73 b(R)m(O)m(W)31 -b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)1982 b Fi(105)191 -668 y Fe("point)46 b(in)h(a)h(rectangular)c(region")620 -781 y(box\(xcntr,ycntr,xfll_wdth,)o(yfll)o(_wd)o(th,r)o(otat)o(ion)o -(,Xco)o(lumn)o(,Yc)o(olum)o(n\))191 1007 y(where)334 -1120 y(\(xcntr,ycntr\))g(are)j(the)g(\(x,y\))f(position)g(of)h(the)g -(center)f(of)h(the)g(region)334 1233 y(\(xhlf_wdth,yhlf_wdth\))42 -b(are)47 b(the)g(\(x,y\))f(half)h(widths)f(of)h(the)g(region)334 -1346 y(\(xfll_wdth,yfll_wdth\))42 b(are)47 b(the)g(\(x,y\))f(full)h -(widths)f(of)h(the)g(region)334 1458 y(\(radius\))f(is)h(half)f(the)h -(diameter)f(of)h(the)g(circle)334 1571 y(\(rotation\))e(is)i(the)g -(angle\(degrees\))d(that)j(the)g(region)f(is)h(rotated)f(with)620 -1684 y(respect)g(to)h(\(xcntr,ycntr\))334 1797 y(\(Xcoord,Ycoord\))d -(are)j(the)g(\(x,y\))f(coordinates)f(to)i(test,)f(usually)g(column)620 -1910 y(names)334 2023 y(NOTE:)g(each)h(parameter)e(can)i(itself)f(be)i -(an)f(expression,)d(not)j(merely)f(a)620 2136 y(column)h(name)f(or)h -(constant.)0 2443 y Fb(8.11.6)113 b(Example)38 b(Ro)m(w)f(Filters)191 -2665 y Fe([)47 b(binary)f(&&)i(mag)f(<=)g(5.0])380 b(-)48 -b(Extract)e(all)h(binary)f(stars)g(brighter)1766 2778 -y(than)94 b(fifth)47 b(magnitude)e(\(note)h(that)1766 -2891 y(the)h(initial)f(space)g(is)h(necessary)e(to)1766 -3004 y(prevent)h(it)h(from)g(being)f(treated)g(as)h(a)1766 -3117 y(binning)f(specification\))191 3343 y([#row)g(>=)h(125)g(&&)h -(#row)e(<=)h(175])142 b(-)48 b(Extract)e(row)h(numbers)e(125)i(through) -f(175)191 3569 y([IMAGE[4,5])f(.gt.)h(100])476 b(-)48 -b(Extract)e(all)h(rows)f(that)h(have)g(the)1766 3681 -y(\(4,5\))f(component)g(of)h(the)g(IMAGE)f(column)1766 -3794 y(greater)g(than)g(100)191 4020 y([abs\(sin\(theta)e(*)j(#deg\)\)) -f(<)i(0.5])e(-)i(Extract)e(all)h(rows)f(having)g(the)1766 -4133 y(absolute)f(value)i(of)g(the)g(sine)g(of)g(theta)1766 -4246 y(less)94 b(than)47 b(a)g(half)g(where)f(the)h(angles)1766 -4359 y(are)g(tabulated)e(in)i(degrees)191 4585 y([SUM\()f(SPEC)h(>)g -(3*BACKGRND)e(\)>=1])94 b(-)48 b(Extract)e(all)h(rows)f(containing)f(a) -1766 4698 y(spectrum,)g(held)i(in)g(vector)f(column)1766 -4811 y(SPEC,)g(with)h(at)g(least)f(one)h(value)g(3)1766 -4924 y(times)f(greater)g(than)h(the)g(background)1766 -5036 y(level)f(held)h(in)g(a)h(keyword,)d(BACKGRND)191 -5262 y([VCOL=={1,4,2}])759 b(-)48 b(Extract)e(all)h(rows)f(whose)h -(vector)f(column)1766 5375 y(VCOL)h(contains)e(the)i(3-elements)e(1,)i -(4,)g(and)1766 5488 y(2.)191 5714 y([@rowFilter.txt])711 -b(-)48 b(Extract)e(rows)g(using)h(the)g(expression)p -eop end -%%Page: 106 112 -TeXDict begin 106 111 bop 0 299 a Fi(106)1573 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)1766 -555 y Fe(contained)45 b(within)h(the)h(text)g(file)1766 -668 y(rowFilter.txt)191 894 y([gtifilter\(\)])855 b(-)48 -b(Search)e(the)h(current)f(file)g(for)h(a)h(GTI)239 1007 -y(extension,)92 b(filter)i(the)47 b(TIME)239 1120 y(column)f(in)h(the)g -(current)f(table,)g(using)239 1233 y(START/STOP)f(times)h(taken)g(from) -239 1346 y(columns)f(in)j(the)f(GTI)94 b(extension)191 -1571 y([regfilter\("pow.reg"\)])423 b(-)48 b(Extract)e(rows)g(which)h -(have)f(a)i(coordinate)1766 1684 y(\(as)f(given)f(in)h(the)g(X)h(and)f -(Y)g(columns\))1766 1797 y(within)f(the)h(spatial)f(region)g(specified) -1766 1910 y(in)h(the)g(pow.reg)f(region)g(file.)191 2136 -y([regfilter\("pow.reg",)c(Xs,)47 b(Ys\)])f(-)i(Same)f(as)g(above,)f -(except)g(that)h(the)1766 2249 y(Xs)g(and)g(Ys)g(columns)f(will)h(be)g -(used)f(to)1766 2362 y(determine)f(the)i(coordinate)e(of)i(each)1766 -2475 y(row)g(in)g(the)g(table.)0 2811 y Fd(8.12)180 b(Binning)45 -b(or)g(Histogramming)i(Sp)t(eci\014cation)0 3062 y Fi(The)22 -b(optional)i(binning)e(sp)s(eci\014er)g(is)h(enclosed)h(in)f(square)f -(brac)m(k)m(ets)j(and)d(can)h(b)s(e)f(distinguished)g(from)h(a)g -(general)0 3175 y(ro)m(w)32 b(\014lter)h(sp)s(eci\014cation)g(b)m(y)f -(the)h(fact)g(that)g(it)g(b)s(egins)f(with)g(the)g(k)m(eyw)m(ord)h -('bin')f(not)h(immediately)g(follo)m(w)m(ed)0 3288 y(b)m(y)41 -b(an)f(equals)i(sign.)72 b(When)41 b(binning)e(is)i(sp)s(eci\014ed,)i -(a)e(temp)s(orary)g(N-dimensional)g(FITS)f(primary)g(arra)m(y)0 -3401 y(is)j(created)h(b)m(y)f(computing)h(the)f(histogram)h(of)f(the)g -(v)-5 b(alues)44 b(in)e(the)i(sp)s(eci\014ed)e(columns)h(of)g(a)h(FITS) -e(table)0 3514 y(extension.)f(After)30 b(the)f(histogram)h(is)g -(computed)f(the)h(input)e(FITS)h(\014le)h(con)m(taining)h(the)e(table)i -(is)e(then)g(closed)0 3627 y(and)34 b(the)h(temp)s(orary)f(FITS)g -(primary)g(arra)m(y)h(is)g(op)s(ened)f(and)g(passed)g(to)h(the)g -(application)h(program.)54 b(Th)m(us,)0 3740 y(the)39 -b(application)h(program)f(nev)m(er)g(sees)g(the)g(original)h(FITS)e -(table)i(and)e(only)h(sees)h(the)f(image)h(in)e(the)h(new)0 -3853 y(temp)s(orary)32 b(\014le)h(\(whic)m(h)g(has)f(no)h(additional)g -(extensions\).)49 b(Ob)m(viously)-8 b(,)34 b(the)f(application)h -(program)e(m)m(ust)h(b)s(e)0 3966 y(exp)s(ecting)e(to)g(op)s(en)f(a)h -(FITS)e(image)j(and)e(not)g(a)h(FITS)f(table)h(in)f(this)g(case.)0 -4126 y(The)g(data)h(t)m(yp)s(e)f(of)h(the)f(FITS)g(histogram)g(image)i -(ma)m(y)f(b)s(e)f(sp)s(eci\014ed)f(b)m(y)h(app)s(ending)f('b')h(\(for)h -(8-bit)g(b)m(yte\),)g('i')0 4239 y(\(for)g(16-bit)g(in)m(tegers\),)h -('j')f(\(for)g(32-bit)g(in)m(teger\),)i('r')d(\(for)h(32-bit)g -(\015oating)h(p)s(oin)m(ts\),)e(or)h('d')f(\(for)h(64-bit)g(double)0 -4351 y(precision)d(\015oating)h(p)s(oin)m(t\))g(to)f(the)h('bin')e(k)m -(eyw)m(ord)i(\(e.g.)41 b('[binr)28 b(X]')g(creates)i(a)e(real)h -(\015oating)g(p)s(oin)m(t)f(image\).)41 b(If)0 4464 y(the)26 -b(datat)m(yp)s(e)h(is)f(not)g(explicitly)i(sp)s(eci\014ed)d(then)h(a)g -(32-bit)h(in)m(teger)h(image)f(will)f(b)s(e)f(created)i(b)m(y)f -(default,)i(unless)0 4577 y(the)h(w)m(eigh)m(ting)h(option)f(is)g(also) -h(sp)s(eci\014ed)e(in)g(whic)m(h)h(case)g(the)g(image)h(will)f(ha)m(v)m -(e)h(a)f(32-bit)h(\015oating)g(p)s(oin)m(t)e(data)0 4690 -y(t)m(yp)s(e)j(b)m(y)f(default.)0 4850 y(The)24 b(histogram)g(image)i -(ma)m(y)f(ha)m(v)m(e)g(from)f(1)g(to)h(4)g(dimensions)e(\(axes\),)k -(dep)s(ending)c(on)h(the)g(n)m(um)m(b)s(er)f(of)h(columns)0 -4963 y(that)31 b(are)g(sp)s(eci\014ed.)40 b(The)30 b(general)h(form)f -(of)g(the)h(binning)e(sp)s(eci\014cation)i(is:)48 5226 -y Fe([bin{bijrd})92 b(Xcol=min:max:binsize,)42 b(Ycol=)47 -b(...,)f(Zcol=...,)f(Tcol=...;)h(weight])0 5488 y Fi(in)39 -b(whic)m(h)g(up)f(to)i(4)g(columns,)h(eac)m(h)f(corresp)s(onding)e(to)i -(an)g(axis)f(of)h(the)f(image,)k(are)d(listed.)67 b(The)39 -b(column)0 5601 y(names)27 b(are)h(case)h(insensitiv)m(e,)g(and)e(the)h -(column)f(n)m(um)m(b)s(er)f(ma)m(y)i(b)s(e)f(giv)m(en)h(instead)g(of)g -(the)g(name,)g(preceded)f(b)m(y)0 5714 y(a)32 b(p)s(ound)e(sign)i -(\(e.g.,)i([bin)d(#4=1:512]\).)47 b(If)31 b(the)h(column)g(name)g(is)f -(not)h(sp)s(eci\014ed,)g(then)f(CFITSIO)g(will)h(\014rst)p -eop end -%%Page: 107 113 -TeXDict begin 107 112 bop 0 299 a Fg(8.12.)113 b(BINNING)31 -b(OR)f(HISTOGRAMMING)h(SPECIFICA)-8 b(TION)1268 b Fi(107)0 -555 y(try)37 b(to)h(use)f(the)g('preferred)f(column')i(as)f(sp)s -(eci\014ed)g(b)m(y)g(the)g(CPREF)g(k)m(eyw)m(ord)h(if)f(it)g(exists)h -(\(e.g.,)j('CPREF)0 668 y(=)i('DETX,DETY'\),)h(otherwise)g(column)f -(names)g('X',)h('Y',)g('Z',)f(and)f('T')i(will)f(b)s(e)f(assumed)h(for) -g(eac)m(h)h(of)0 781 y(the)37 b(4)h(axes,)i(resp)s(ectiv)m(ely)-8 -b(.)62 b(In)37 b(cases)h(where)e(the)i(column)f(name)g(could)g(b)s(e)f -(confused)h(with)g(an)g(arithmetic)0 894 y(expression,)30 -b(enclose)i(the)f(column)f(name)g(in)g(paren)m(theses)h(to)g(force)g -(the)f(name)h(to)g(b)s(e)f(in)m(terpreted)g(literally)-8 -b(.)0 1054 y(Eac)m(h)33 b(column)f(name)g(ma)m(y)h(b)s(e)f(follo)m(w)m -(ed)h(b)m(y)g(an)f(equals)g(sign)h(and)e(then)h(the)g(lo)m(w)m(er)i -(and)e(upp)s(er)e(range)i(of)h(the)0 1167 y(histogram,)f(and)e(the)h -(size)h(of)f(the)g(histogram)h(bins,)e(separated)h(b)m(y)g(colons.)43 -b(Spaces)31 b(are)g(allo)m(w)m(ed)i(b)s(efore)e(and)0 -1280 y(after)e(the)g(equals)g(sign)f(but)g(not)h(within)f(the)h -('min:max:binsize')g(string.)40 b(The)29 b(min,)f(max)h(and)f(binsize)h -(v)-5 b(alues)0 1393 y(ma)m(y)32 b(b)s(e)e(in)m(teger)i(or)f -(\015oating)h(p)s(oin)m(t)f(n)m(um)m(b)s(ers,)f(or)h(they)g(ma)m(y)g(b) -s(e)g(the)g(names)g(of)g(k)m(eyw)m(ords)g(in)g(the)g(header)g(of)0 -1506 y(the)g(table.)41 b(If)30 b(the)h(latter,)h(then)e(the)g(v)-5 -b(alue)31 b(of)g(that)g(k)m(eyw)m(ord)f(is)h(substituted)f(in)m(to)h -(the)g(expression.)0 1666 y(Default)37 b(v)-5 b(alues)36 -b(for)g(the)g(min,)h(max)f(and)g(binsize)g(quan)m(tities)h(will)f(b)s -(e)f(used)h(if)f(not)i(explicitly)g(giv)m(en)g(in)f(the)0 -1779 y(binning)29 b(expression)h(as)h(sho)m(wn)f(in)g(these)h -(examples:)191 2033 y Fe([bin)47 b(x)g(=)g(:512:2])94 -b(-)47 b(use)g(default)f(minimum)g(value)191 2146 y([bin)h(x)g(=)g -(1::2])190 b(-)47 b(use)g(default)f(maximum)g(value)191 -2259 y([bin)h(x)g(=)g(1:512])142 b(-)47 b(use)g(default)f(bin)h(size) -191 2372 y([bin)g(x)g(=)g(1:])286 b(-)47 b(use)g(default)f(maximum)g -(value)g(and)h(bin)g(size)191 2485 y([bin)g(x)g(=)g(:512])190 -b(-)47 b(use)g(default)f(minimum)g(value)g(and)h(bin)g(size)191 -2598 y([bin)g(x)g(=)g(2])334 b(-)47 b(use)g(default)f(minimum)g(and)h -(maximum)f(values)191 2711 y([bin)h(x])524 b(-)47 b(use)g(default)f -(minimum,)g(maximum)g(and)g(bin)h(size)191 2824 y([bin)g(4])524 -b(-)47 b(default)f(2-D)h(image,)f(bin)h(size)g(=)g(4)h(in)f(both)g -(axes)191 2937 y([bin])619 b(-)47 b(default)f(2-D)h(image)0 -3191 y Fi(CFITSIO)31 b(will)i(use)f(the)h(v)-5 b(alue)33 -b(of)g(the)g(TLMINn,)f(TLMAXn,)h(and)f(TDBINn)h(k)m(eyw)m(ords,)h(if)e -(they)h(exist,)h(for)0 3304 y(the)j(default)f(min,)i(max,)g(and)e -(binsize,)i(resp)s(ectiv)m(ely)-8 b(.)61 b(If)36 b(they)h(do)f(not)h -(exist)g(then)f(CFITSIO)f(will)i(use)f(the)0 3417 y(actual)d(minim)m -(um)e(and)h(maxim)m(um)g(v)-5 b(alues)32 b(in)g(the)g(column)f(for)h -(the)g(histogram)h(min)e(and)h(max)g(v)-5 b(alues.)45 -b(The)0 3530 y(default)34 b(binsize)f(will)h(b)s(e)f(set)h(to)h(1,)g -(or)e(\(max)h(-)g(min\))f(/)h(10.,)i(whic)m(hev)m(er)e(is)g(smaller,)h -(so)e(that)i(the)e(histogram)0 3643 y(will)e(ha)m(v)m(e)g(at)g(least)h -(10)f(bins)f(along)h(eac)m(h)h(axis.)0 3803 y(A)41 b(shortcut)g -(notation)h(is)f(allo)m(w)m(ed)i(if)e(all)h(the)f(columns/axes)h(ha)m -(v)m(e)g(the)f(same)g(binning)f(sp)s(eci\014cation.)74 -b(In)0 3916 y(this)33 b(case)g(all)h(the)f(column)f(names)h(ma)m(y)g(b) -s(e)f(listed)h(within)f(paren)m(theses,)i(follo)m(w)m(ed)h(b)m(y)d(the) -h(\(single\))h(binning)0 4029 y(sp)s(eci\014cation,)d(as)g(in:)191 -4283 y Fe([bin)47 b(\(X,Y\)=1:512:2])191 4396 y([bin)g(\(X,Y\))f(=)h -(5])0 4650 y Fi(The)31 b(optional)i(w)m(eigh)m(ting)h(factor)e(is)g -(the)g(last)g(item)h(in)e(the)h(binning)f(sp)s(eci\014er)g(and,)h(if)f -(presen)m(t,)i(is)e(separated)0 4763 y(from)38 b(the)g(list)h(of)f -(columns)g(b)m(y)g(a)h(semi-colon.)65 b(As)39 b(the)f(histogram)h(is)f -(accum)m(ulated,)k(this)c(w)m(eigh)m(t)i(is)e(used)0 -4876 y(to)d(incremen)m(ted)f(the)g(v)-5 b(alue)35 b(of)f(the)g -(appropriated)f(bin)h(in)f(the)h(histogram.)52 b(If)34 -b(the)g(w)m(eigh)m(ting)i(factor)f(is)f(not)0 4989 y(sp)s(eci\014ed,)24 -b(then)f(the)g(default)g(w)m(eigh)m(t)i(=)d(1)i(is)f(assumed.)37 -b(The)23 b(w)m(eigh)m(ting)i(factor)f(ma)m(y)f(b)s(e)g(a)g(constan)m(t) -i(in)m(teger)f(or)0 5102 y(\015oating)30 b(p)s(oin)m(t)f(n)m(um)m(b)s -(er,)f(or)h(the)g(name)g(of)g(a)g(k)m(eyw)m(ord)h(con)m(taining)g(the)g -(w)m(eigh)m(ting)g(v)-5 b(alue.)41 b(Or)28 b(the)h(w)m(eigh)m(ting)0 -5215 y(factor)g(ma)m(y)g(b)s(e)e(the)h(name)g(of)h(a)f(table)h(column)f -(in)g(whic)m(h)f(case)j(the)e(v)-5 b(alue)28 b(in)g(that)h(column,)f -(on)g(a)h(ro)m(w)f(b)m(y)g(ro)m(w)0 5328 y(basis,)i(will)h(b)s(e)f -(used.)0 5488 y(In)35 b(some)h(cases,)i(the)d(column)h(or)f(k)m(eyw)m -(ord)h(ma)m(y)g(giv)m(e)h(the)f(recipro)s(cal)g(of)g(the)g(actual)h(w)m -(eigh)m(t)g(v)-5 b(alue)36 b(that)g(is)0 5601 y(needed.)49 -b(In)32 b(this)h(case,)i(precede)e(the)h(w)m(eigh)m(t)g(k)m(eyw)m(ord)g -(or)f(column)g(name)g(b)m(y)g(a)g(slash)g('/')h(to)g(tell)g(CFITSIO)0 -5714 y(to)d(use)f(the)h(recipro)s(cal)g(of)f(the)h(v)-5 -b(alue)31 b(when)e(constructing)i(the)g(histogram.)p -eop end -%%Page: 108 114 -TeXDict begin 108 113 bop 0 299 a Fi(108)1573 b Fg(CHAPTER)30 -b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 -555 y Fi(F)g(or)35 b(complex)f(or)g(commonly)g(used)f(histograms,)j -(one)e(can)g(also)h(place)g(its)f(description)g(in)m(to)h(a)f(text)h -(\014le)f(and)0 668 y(imp)s(ort)44 b(it)g(in)m(to)i(the)e(binning)f(sp) -s(eci\014cation)i(using)f(the)h(syn)m(tax)f('[bin)g(@\014lename.txt]'.) -84 b(The)44 b(\014le's)g(con-)0 781 y(ten)m(ts)37 b(can)e(extend)h(o)m -(v)m(er)h(m)m(ultiple)f(lines,)i(although)e(it)g(m)m(ust)f(still)i -(conform)f(to)g(the)g(no-spaces)g(rule)f(for)h(the)0 -894 y(min:max:binsize)h(syn)m(tax)h(and)e(eac)m(h)i(axis)g(sp)s -(eci\014cation)g(m)m(ust)f(still)g(b)s(e)g(comma-separated.)62 -b(An)m(y)37 b(lines)g(in)0 1007 y(the)32 b(external)h(text)g(\014le)f -(that)h(b)s(egin)e(with)h(2)g(slash)g(c)m(haracters)h(\('//'\))h(will)e -(b)s(e)g(ignored)g(and)f(ma)m(y)i(b)s(e)e(used)g(to)0 -1120 y(add)f(commen)m(ts)h(in)m(to)g(the)g(\014le.)0 -1280 y(Examples:)191 1540 y Fe([bini)46 b(detx,)h(dety])762 -b(-)47 b(2-D,)g(16-bit)f(integer)g(histogram)1861 1653 -y(of)i(DETX)e(and)h(DETY)g(columns,)e(using)1861 1766 -y(default)h(values)g(for)h(the)g(histogram)1861 1878 -y(range)g(and)g(binsize)191 2104 y([bin)g(\(detx,)f(dety\)=16;)f -(/exposure])g(-)i(2-D,)g(32-bit)f(real)h(histogram)e(of)i(DETX)1861 -2217 y(and)g(DETY)g(columns)f(with)g(a)i(bin)f(size)f(=)i(16)1861 -2330 y(in)g(both)e(axes.)h(The)f(histogram)g(values)1861 -2443 y(are)h(divided)f(by)h(the)g(EXPOSURE)f(keyword)1861 -2556 y(value.)191 2782 y([bin)h(time=TSTART:TSTOP:0.1])280 -b(-)47 b(1-D)g(lightcurve,)e(range)h(determined)f(by)1861 -2895 y(the)i(TSTART)f(and)h(TSTOP)g(keywords,)1861 3008 -y(with)g(0.1)g(unit)g(size)f(bins.)191 3233 y([bin)h(pha,)f -(time=8000.:8100.:0.1])90 b(-)47 b(2-D)g(image)g(using)f(default)g -(binning)1861 3346 y(of)i(the)e(PHA)h(column)f(for)h(the)g(X)h(axis,) -1861 3459 y(and)f(1000)g(bins)g(in)g(the)g(range)1861 -3572 y(8000.)g(to)g(8100.)f(for)h(the)g(Y)h(axis.)191 -3798 y([bin)f(@binFilter.txt])616 b(-)47 b(Use)g(the)g(contents)f(of)h -(the)g(text)f(file)1861 3911 y(binFilter.txt)f(for)h(the)h(binning)1861 -4024 y(specifications.)p eop end -%%Page: 109 115 -TeXDict begin 109 114 bop 0 1225 a Ff(Chapter)65 b(9)0 -1687 y Fl(T)-19 b(emplate)76 b(Files)0 2180 y Fi(When)38 -b(a)h(new)f(FITS)g(\014le)h(is)g(created)g(with)g(a)f(call)i(to)g -(\014ts)p 2101 2180 28 4 v 32 w(create)p 2369 2180 V -35 w(\014le,)g(the)f(name)g(of)g(a)g(template)h(\014le)e(ma)m(y)0 -2293 y(b)s(e)h(supplied)g(in)h(paren)m(theses)g(immediately)h(follo)m -(wing)g(the)g(name)f(of)g(the)g(new)f(\014le)h(to)h(b)s(e)e(created.)71 -b(This)0 2406 y(template)27 b(is)e(used)g(to)h(de\014ne)f(the)h -(structure)f(of)h(one)f(or)h(more)g(HDUs)g(in)f(the)h(new)f(\014le.)39 -b(The)25 b(template)i(\014le)e(ma)m(y)0 2518 y(b)s(e)32 -b(another)h(FITS)f(\014le,)i(in)f(whic)m(h)f(case)i(the)f(newly)g -(created)h(\014le)f(will)g(ha)m(v)m(e)h(exactly)h(the)e(same)g(k)m(eyw) -m(ords)g(in)0 2631 y(eac)m(h)25 b(HDU)g(as)g(in)f(the)g(template)i -(FITS)d(\014le,)j(but)d(all)j(the)e(data)h(units)e(will)i(b)s(e)f -(\014lled)g(with)f(zeros.)40 b(The)24 b(template)0 2744 -y(\014le)i(ma)m(y)h(also)g(b)s(e)e(an)h(ASCI)s(I)e(text)j(\014le,)g -(where)f(eac)m(h)h(line)f(\(in)g(general\))i(describ)s(es)d(one)h(FITS) -f(k)m(eyw)m(ord)i(record.)0 2857 y(The)j(format)h(of)f(the)h(ASCI)s(I)e -(template)i(\014le)g(is)f(describ)s(ed)f(in)i(the)f(follo)m(wing)i -(sections.)0 3188 y Fd(9.1)135 b(Detailed)47 b(T)-11 -b(emplate)46 b(Line)f(F)-11 b(ormat)0 3438 y Fi(The)30 -b(format)h(of)f(eac)m(h)i(ASCI)s(I)c(template)k(line)f(closely)h(follo) -m(ws)f(the)g(format)g(of)f(a)h(FITS)f(k)m(eyw)m(ord)g(record:)95 -3682 y Fe(KEYWORD)46 b(=)i(KEYVALUE)d(/)j(COMMENT)0 3926 -y Fi(except)22 b(that)g(free)g(format)f(ma)m(y)h(b)s(e)f(used)f -(\(e.g.,)25 b(the)d(equals)f(sign)h(ma)m(y)f(app)s(ear)g(at)h(an)m(y)g -(p)s(osition)f(in)g(the)h(line\))g(and)0 4039 y(T)-8 -b(AB)34 b(c)m(haracters)g(are)g(allo)m(w)m(ed)h(and)e(are)g(treated)h -(the)g(same)f(as)h(space)f(c)m(haracters.)51 b(The)33 -b(KEYV)-10 b(ALUE)33 b(and)0 4152 y(COMMENT)d(\014elds)g(are)h -(optional.)43 b(The)30 b(equals)h(sign)f(c)m(haracter)j(is)d(also)i -(optional,)g(but)e(it)h(is)f(recommended)0 4264 y(that)42 -b(it)f(b)s(e)g(included)f(for)h(clarit)m(y)-8 b(.)75 -b(An)m(y)41 b(template)i(line)e(that)h(b)s(egins)f(with)f(the)i(p)s -(ound)d('#')i(c)m(haracter)i(is)0 4377 y(ignored)30 b(b)m(y)h(the)f -(template)i(parser)e(and)g(ma)m(y)h(b)s(e)e(use)h(to)h(insert)g(commen) -m(ts)g(in)m(to)g(the)g(template)h(\014le)e(itself.)0 -4538 y(The)c(KEYW)m(ORD)g(name)g(\014eld)g(is)g(limited)h(to)g(8)f(c)m -(haracters)h(in)f(length)h(and)e(only)h(the)g(letters)i(A-Z,)e(digits)h -(0-9,)0 4650 y(and)h(the)g(h)m(yphen)f(and)h(underscore)g(c)m -(haracters)h(ma)m(y)g(b)s(e)f(used,)g(without)h(an)m(y)f(em)m(b)s -(edded)g(spaces.)40 b(Lo)m(w)m(ercase)0 4763 y(letters)22 -b(in)f(the)h(template)g(k)m(eyw)m(ord)g(name)f(will)g(b)s(e)g(con)m(v)m -(erted)i(to)f(upp)s(ercase.)36 b(Leading)22 b(spaces)f(in)g(the)h -(template)0 4876 y(line)k(preceding)g(the)f(k)m(eyw)m(ord)h(name)g(are) -g(generally)h(ignored,)g(except)f(if)g(the)g(\014rst)f(8)h(c)m -(haracters)h(of)f(a)g(template)0 4989 y(line)f(are)h(all)g(blank,)g -(then)f(the)g(en)m(tire)h(line)g(is)f(treated)h(as)f(a)h(FITS)e(commen) -m(t)i(k)m(eyw)m(ord)g(\(with)f(a)h(blank)e(k)m(eyw)m(ord)0 -5102 y(name\))31 b(and)f(is)g(copied)h(v)m(erbatim)g(in)m(to)g(the)g -(FITS)e(header.)0 5262 y(The)37 b(KEYV)-10 b(ALUE)37 -b(\014eld)g(ma)m(y)h(ha)m(v)m(e)g(an)m(y)g(allo)m(w)m(ed)h(FITS)e(data) -h(t)m(yp)s(e:)54 b(c)m(haracter)39 b(string,)h(logical,)h(in)m(teger,)0 -5375 y(real,)28 b(complex)g(in)m(teger,)h(or)d(complex)i(real.)40 -b(In)m(teger)28 b(v)-5 b(alues)27 b(m)m(ust)f(b)s(e)g(within)g(the)h -(allo)m(w)m(ed)i(range)e(of)g(a)g('signed)0 5488 y(long')h(v)-5 -b(ariable;)29 b(some)f(C)e(compilers)i(only)f(suppp)s(ort)e(4-b)m(yte)j -(long)g(in)m(tegers)g(with)f(a)g(range)h(from)e(-2147483648)0 -5601 y(to)31 b(+2147483647,)k(whereas)30 b(other)h(C)f(compilers)h -(supp)s(ort)e(8-b)m(yte)j(in)m(tegers)f(with)f(a)h(range)g(of)g(plus)e -(or)i(min)m(us)0 5714 y(2**63.)1882 5942 y(109)p eop -end -%%Page: 110 116 -TeXDict begin 110 115 bop 0 299 a Fi(110)2295 b Fg(CHAPTER)30 -b(9.)71 b(TEMPLA)-8 b(TE)30 b(FILES)0 555 y Fi(The)23 -b(c)m(haracter)h(string)f(v)-5 b(alues)24 b(need)f(not)g(b)s(e)g -(enclosed)g(in)g(single)h(quote)g(c)m(haracters)g(unless)f(they)g(are)h -(necessary)0 668 y(to)37 b(distinguish)e(the)i(string)f(from)f(a)i -(di\013eren)m(t)g(data)f(t)m(yp)s(e)h(\(e.g.)59 b(2.0)38 -b(is)e(a)g(real)h(but)f('2.0')h(is)f(a)h(string\).)58 -b(The)0 781 y(k)m(eyw)m(ord)38 b(has)g(an)g(unde\014ned)d(\(n)m(ull\))k -(v)-5 b(alue)38 b(if)g(the)g(template)h(record)f(only)g(con)m(tains)h -(blanks)e(follo)m(wing)j(the)0 894 y("=")31 b(or)f(b)s(et)m(w)m(een)h -(the)g("=")g(and)f(the)g("/")i(commen)m(t)f(\014eld)f(delimiter.)0 -1054 y(String)c(k)m(eyw)m(ord)h(v)-5 b(alues)27 b(longer)g(than)f(68)h -(c)m(haracters)h(\(the)f(maxim)m(um)f(length)h(that)g(will)g(\014t)f -(in)g(a)h(single)g(FITS)0 1167 y(k)m(eyw)m(ord)41 b(record\))g(are)g(p) -s(ermitted)f(using)g(the)h(CFITSIO)e(long)i(string)g(con)m(v)m(en)m -(tion.)74 b(They)40 b(can)h(either)g(b)s(e)0 1280 y(sp)s(eci\014ed)28 -b(as)i(a)f(single)h(long)f(line)h(in)e(the)i(template,)h(or)e(b)m(y)f -(using)h(m)m(ultiple)h(lines)f(where)f(the)i(con)m(tin)m(uing)g(lines)0 -1393 y(con)m(tain)i(the)e('CONTINUE')g(k)m(eyw)m(ord,)h(as)g(in)f(this) -g(example:)95 1657 y Fe(LONGKEY)46 b(=)i('This)e(is)h(a)h(long)e -(string)g(value)h(that)f(is)i(contin&')95 1770 y(CONTINUE)94 -b('ued)46 b(over)h(2)g(records')f(/)h(comment)f(field)h(goes)f(here)0 -2035 y Fi(The)29 b(format)h(of)g(template)h(lines)e(with)h(CONTINUE)e -(k)m(eyw)m(ord)i(is)g(v)m(ery)g(strict:)41 b(3)30 b(spaces)g(m)m(ust)f -(follo)m(w)i(CON-)0 2147 y(TINUE)f(and)g(the)g(rest)h(of)f(the)h(line)g -(is)f(copied)h(v)m(erbatim)g(to)g(the)g(FITS)e(\014le.)0 -2308 y(The)i(start)h(of)g(the)f(optional)i(COMMENT)e(\014eld)g(m)m(ust) -h(b)s(e)e(preceded)i(b)m(y)f("/",)i(whic)m(h)e(is)h(used)f(to)h -(separate)g(it)0 2421 y(from)e(the)g(k)m(eyw)m(ord)h(v)-5 -b(alue)30 b(\014eld.)41 b(Exceptions)30 b(are)h(if)f(the)h(KEYW)m(ORD)g -(name)f(\014eld)g(con)m(tains)h(COMMENT,)0 2533 y(HISTOR)-8 -b(Y,)30 b(CONTINUE,)g(or)g(if)g(the)h(\014rst)f(8)g(c)m(haracters)i(of) -f(the)f(template)i(line)f(are)g(blanks.)0 2694 y(More)c(than)f(one)h -(Header-Data)i(Unit)e(\(HDU\))g(ma)m(y)g(b)s(e)f(de\014ned)f(in)h(the)h -(template)h(\014le.)39 b(The)26 b(start)h(of)g(an)f(HDU)0 -2806 y(de\014nition)k(is)g(denoted)h(with)f(a)h(SIMPLE)e(or)i(XTENSION) -e(template)j(line:)0 2967 y(1\))i(SIMPLE)f(b)s(egins)g(a)h(Primary)g -(HDU)g(de\014nition.)50 b(SIMPLE)33 b(ma)m(y)h(only)g(app)s(ear)f(as)h -(the)g(\014rst)f(k)m(eyw)m(ord)h(in)0 3080 y(the)e(template)i(\014le.) -45 b(If)32 b(the)g(template)i(\014le)e(b)s(egins)f(with)h(XTENSION)f -(instead)h(of)g(SIMPLE,)g(then)f(a)i(default)0 3192 y(empt)m(y)d -(Primary)e(HDU)i(is)g(created,)h(and)d(the)i(template)h(is)e(then)g -(assumed)f(to)i(de\014ne)f(the)h(k)m(eyw)m(ords)f(starting)0 -3305 y(with)h(the)h(\014rst)e(extension)i(follo)m(wing)h(the)f(Primary) -f(HDU.)0 3466 y(2\))35 b(XTENSION)e(marks)g(the)i(b)s(eginning)e(of)h -(a)h(new)e(extension)i(HDU)f(de\014nition.)52 b(The)33 -b(previous)h(HDU)h(will)0 3578 y(b)s(e)30 b(closed)h(at)g(this)f(p)s -(oin)m(t)h(and)e(pro)s(cessing)i(of)f(the)h(next)f(extension)h(b)s -(egins.)0 3918 y Fd(9.2)135 b(Auto-indexing)45 b(of)h(Keyw)l(ords)0 -4169 y Fi(If)31 b(a)h(template)g(k)m(eyw)m(ord)g(name)f(ends)g(with)g -(a)g("#")h(c)m(haracter,)i(it)e(is)f(said)g(to)h(b)s(e)f -('auto-indexed'.)44 b(Eac)m(h)32 b("#")0 4282 y(c)m(haracter)i(will)f -(b)s(e)f(replaced)i(b)m(y)e(the)h(curren)m(t)g(in)m(teger)h(index)e(v) --5 b(alue,)34 b(whic)m(h)f(gets)g(reset)h(=)e(1)h(at)h(the)e(start)i -(of)0 4395 y(eac)m(h)h(new)f(HDU)g(in)g(the)g(\014le)g(\(or)g(7)h(in)e -(the)h(sp)s(ecial)h(case)g(of)f(a)g(GR)m(OUP)h(de\014nition\).)51 -b(The)33 b(FIRST)g(indexed)0 4508 y(k)m(eyw)m(ord)c(in)f(eac)m(h)h -(template)h(HDU)f(de\014nition)f(is)g(used)f(as)i(the)f('incremen)m -(tor';)j(eac)m(h)e(subsequen)m(t)f(o)s(ccurrence)0 4620 -y(of)k(this)f(SAME)g(k)m(eyw)m(ord)h(will)g(cause)g(the)g(index)f(v)-5 -b(alue)32 b(to)g(b)s(e)f(incremen)m(ted.)44 b(This)31 -b(b)s(eha)m(vior)g(can)h(b)s(e)f(rather)0 4733 y(subtle,)d(as)g -(illustrated)h(in)e(the)h(follo)m(wing)h(examples)f(in)f(whic)m(h)h -(the)g(TTYPE)e(k)m(eyw)m(ord)i(is)g(the)g(incremen)m(tor)g(in)0 -4846 y(b)s(oth)i(cases:)95 5111 y Fe(TTYPE#)47 b(=)g(TIME)95 -5224 y(TFORM#)g(=)g(1D)95 5337 y(TTYPE#)g(=)g(RATE)95 -5449 y(TFORM#)g(=)g(1E)0 5714 y Fi(will)26 b(create)i(TTYPE1,)e(TF)m -(ORM1,)i(TTYPE2,)f(and)e(TF)m(ORM2)i(k)m(eyw)m(ords.)40 -b(But)26 b(if)g(the)g(template)h(lo)s(oks)f(lik)m(e,)p -eop end -%%Page: 111 117 -TeXDict begin 111 116 bop 0 299 a Fg(9.3.)72 b(TEMPLA)-8 -b(TE)30 b(P)-8 b(ARSER)30 b(DIRECTIVES)2028 b Fi(111)95 -555 y Fe(TTYPE#)47 b(=)g(TIME)95 668 y(TTYPE#)g(=)g(RATE)95 -781 y(TFORM#)g(=)g(1D)95 894 y(TFORM#)g(=)g(1E)0 1202 -y Fi(this)31 b(results)f(in)h(a)g(FITS)f(\014les)h(with)f(TTYPE1,)h -(TTYPE2,)g(TF)m(ORM2,)h(and)e(TF)m(ORM2,)i(whic)m(h)f(is)g(probably)0 -1315 y(not)g(what)f(w)m(as)h(in)m(tended!)0 1706 y Fd(9.3)135 -b(T)-11 b(emplate)46 b(P)l(arser)g(Directiv)l(es)0 1968 -y Fi(In)29 b(addition)i(to)f(the)g(template)i(lines)e(whic)m(h)g -(de\014ne)f(individual)h(k)m(eyw)m(ords,)g(the)g(template)i(parser)d -(recognizes)0 2081 y(3)h(sp)s(ecial)h(directiv)m(es)g(whic)m(h)f(are)g -(eac)m(h)h(preceded)f(b)m(y)f(the)h(bac)m(kslash)h(c)m(haracter:)90 -b Fe(\\include,)45 b(\\group)p Fi(,)29 b(and)48 2194 -y Fe(\\end)p Fi(.)0 2354 y(The)37 b('include')h(directiv)m(e)i(m)m(ust) -d(b)s(e)h(follo)m(w)m(ed)h(b)m(y)f(a)g(\014lename.)63 -b(It)38 b(forces)g(the)g(parser)f(to)i(temp)s(orarily)f(stop)0 -2467 y(reading)d(the)g(curren)m(t)g(template)h(\014le)f(and)f(b)s(egin) -h(reading)g(the)g(include)f(\014le.)55 b(Once)35 b(the)g(parser)f(reac) -m(hes)i(the)0 2579 y(end)f(of)h(the)g(include)f(\014le)h(it)g(con)m -(tin)m(ues)g(parsing)g(the)f(curren)m(t)h(template)h(\014le.)56 -b(Include)35 b(\014les)h(can)g(b)s(e)f(nested,)0 2692 -y(and)30 b(HDU)h(de\014nitions)f(can)g(span)g(m)m(ultiple)h(template)h -(\014les.)0 2853 y(The)f(start)h(of)g(a)g(GR)m(OUP)h(de\014nition)e(is) -h(denoted)g(with)f(the)h('group')g(directiv)m(e,)h(and)f(the)f(end)h -(of)f(a)i(GR)m(OUP)0 2965 y(de\014nition)k(is)h(denoted)f(with)g(the)h -('end')f(directiv)m(e.)63 b(Eac)m(h)39 b(GR)m(OUP)e(con)m(tains)i(0)f -(or)f(more)h(mem)m(b)s(er)f(blo)s(c)m(ks)0 3078 y(\(HDUs)44 -b(or)f(GR)m(OUPs\).)79 b(Mem)m(b)s(er)42 b(blo)s(c)m(ks)i(of)f(t)m(yp)s -(e)g(GR)m(OUP)g(can)g(con)m(tain)h(their)f(o)m(wn)g(mem)m(b)s(er)f(blo) -s(c)m(ks.)0 3191 y(The)32 b(GR)m(OUP)g(de\014nition)g(itself)h(o)s -(ccupies)g(one)f(FITS)g(\014le)g(HDU)h(of)f(sp)s(ecial)h(t)m(yp)s(e)f -(\(GR)m(OUP)h(HDU\),)h(so)e(if)h(a)0 3304 y(template)f(sp)s(eci\014es)e -(1)h(group)e(with)h(1)h(mem)m(b)s(er)f(HDU)h(lik)m(e:)0 -3613 y Fe(\\group)0 3725 y(grpdescr)46 b(=)h('demo')0 -3838 y(xtension)f(bintable)0 3951 y(#)h(this)g(bintable)f(has)h(0)g -(cols,)f(0)i(rows)0 4064 y(\\end)0 4373 y Fi(then)30 -b(the)h(parser)e(creates)j(a)f(FITS)f(\014le)g(with)g(3)h(HDUs)g(:)0 -4681 y Fe(1\))47 b(dummy)g(PHDU)0 4794 y(2\))g(GROUP)g(HDU)f(\(has)h(1) -h(member,)d(which)i(is)g(bintable)e(in)j(HDU)f(number)f(3\))0 -4907 y(3\))h(bintable)f(\(member)g(of)h(GROUP)f(in)h(HDU)g(number)f -(2\))0 5215 y Fi(T)-8 b(ec)m(hnically)32 b(sp)s(eaking,)e(the)f(GR)m -(OUP)i(HDU)f(is)g(a)g(BINT)-8 b(ABLE)30 b(with)g(6)g(columns.)40 -b(Applications)31 b(can)f(de\014ne)0 5328 y(additional)23 -b(columns)f(in)f(a)i(GR)m(OUP)f(HDU)h(using)f(TF)m(ORMn)f(and)h(TTYPEn) -f(\(where)g(n)h(is)g(7,)i(8,)h(....\))39 b(k)m(eyw)m(ords)0 -5441 y(or)30 b(their)h(auto-indexing)g(equiv)-5 b(alen)m(ts.)0 -5601 y(F)d(or)26 b(a)f(more)g(complicated)h(example)f(of)g(a)h -(template)g(\014le)f(using)f(the)h(group)f(directiv)m(es,)k(lo)s(ok)d -(at)g(the)g(sample.tpl)0 5714 y(\014le)30 b(that)h(is)g(included)e(in)i -(the)f(CFITSIO)f(distribution.)p eop end -%%Page: 112 118 -TeXDict begin 112 117 bop 0 299 a Fi(112)2295 b Fg(CHAPTER)30 -b(9.)71 b(TEMPLA)-8 b(TE)30 b(FILES)0 555 y Fd(9.4)135 -b(F)-11 b(ormal)46 b(T)-11 b(emplate)45 b(Syn)l(tax)0 -805 y Fi(The)30 b(template)i(syn)m(tax)f(can)f(formally)h(b)s(e)f -(de\014ned)f(as)i(follo)m(ws:)191 1063 y Fe(TEMPLATE)45 -b(=)j(BLOCK)e([)i(BLOCK)e(...)h(])334 1289 y(BLOCK)f(=)i({)f(HDU)g(|)h -(GROUP)e(})334 1515 y(GROUP)g(=)i(\\GROUP)e([)h(BLOCK)g(...)g(])g -(\\END)430 1741 y(HDU)f(=)i(XTENSION)d([)j(LINE)f(...)f(])i({)f -(XTENSION)f(|)h(\\GROUP)f(|)i(\\END)f(|)g(EOF)g(})382 -1967 y(LINE)f(=)i([)f(KEYWORD)f([)i(=)f(])h(])f([)g(VALUE)g(])g([)h(/)f -(COMMENT)f(])191 2192 y(X)h(...)238 b(-)48 b(X)f(can)g(be)g(present)f -(1)h(or)h(more)e(times)191 2305 y({)h(X)h(|)f(Y)h(})f(-)h(X)f(or)g(Y) -191 2418 y([)g(X)h(])238 b(-)48 b(X)f(is)g(optional)0 -2676 y Fi(A)m(t)34 b(the)f(topmost)g(lev)m(el,)i(the)e(template)i -(de\014nes)c(1)j(or)e(more)h(template)h(blo)s(c)m(ks.)49 -b(Blo)s(c)m(ks)34 b(can)f(b)s(e)f(either)h(HDU)0 2789 -y(\(Header)27 b(Data)h(Unit\))g(or)e(a)h(GR)m(OUP)-8 -b(.)28 b(F)-8 b(or)27 b(eac)m(h)g(blo)s(c)m(k)g(the)g(parser)f(creates) -i(1)f(\(or)g(more)f(for)h(GR)m(OUPs\))g(FITS)0 2902 y(\014le)j(HDUs.)0 -3235 y Fd(9.5)135 b(Errors)0 3485 y Fi(In)24 b(general)h(the)f(\014ts)p -692 3485 28 4 v 33 w(execute)p 1019 3485 V 34 w(template\(\))i -(function)e(tries)h(to)g(b)s(e)f(as)g(atomic)i(as)f(p)s(ossible,)g(so)f -(either)h(ev)m(erything)0 3598 y(is)f(done)g(or)g(nothing)f(is)h(done.) -39 b(If)23 b(an)h(error)f(o)s(ccurs)h(during)f(parsing)g(of)h(the)g -(template,)j(\014ts)p 3125 3598 V 33 w(execute)p 3452 -3598 V 34 w(template\(\))0 3711 y(will)k(\(try)g(to\))h(delete)g(the)f -(top)g(lev)m(el)h(BLOCK)e(\(with)h(all)g(its)h(c)m(hildren)e(if)h(an)m -(y\))g(in)g(whic)m(h)f(the)h(error)f(o)s(ccurred,)0 3824 -y(then)g(it)h(will)g(stop)f(reading)h(the)f(template)i(\014le)e(and)g -(it)h(will)g(return)e(with)h(an)g(error.)0 4158 y Fd(9.6)135 -b(Examples)0 4408 y Fi(1.)54 b(This)34 b(template)i(\014le)f(will)g -(create)h(a)f(200)h(x)e(300)i(pixel)f(image,)j(with)c(4-b)m(yte)i(in)m -(teger)g(pixel)f(v)-5 b(alues,)36 b(in)f(the)0 4521 y(primary)29 -b(HDU:)95 4779 y Fe(SIMPLE)47 b(=)g(T)95 4891 y(BITPIX)g(=)g(32)95 -5004 y(NAXIS)g(=)g(2)239 b(/)47 b(number)f(of)h(dimensions)95 -5117 y(NAXIS1)g(=)g(100)95 b(/)47 b(length)f(of)h(first)g(axis)95 -5230 y(NAXIS2)g(=)g(200)95 b(/)47 b(length)f(of)h(second)f(axis)95 -5343 y(OBJECT)h(=)g(NGC)g(253)g(/)g(name)g(of)g(observed)f(object)0 -5601 y Fi(The)35 b(allo)m(w)m(ed)i(v)-5 b(alues)36 b(of)f(BITPIX)g(are) -h(8,)h(16,)h(32,)g(-32,)g(or)d(-64,)j(represen)m(ting,)f(resp)s(ectiv)m -(ely)-8 b(,)39 b(8-bit)d(in)m(teger,)0 5714 y(16-bit)c(in)m(teger,)g -(32-bit)f(in)m(teger,)h(32-bit)g(\015oating)f(p)s(oin)m(t,)g(or)f(64)h -(bit)g(\015oating)g(p)s(oin)m(t)f(pixels.)p eop end -%%Page: 113 119 -TeXDict begin 113 118 bop 0 299 a Fg(9.6.)72 b(EXAMPLES)3039 -b Fi(113)0 555 y(2.)39 b(T)-8 b(o)23 b(create)h(a)f(FITS)e(table,)26 -b(the)c(template)i(\014rst)e(needs)g(to)i(include)e(XTENSION)g(=)g(T)-8 -b(ABLE)23 b(or)f(BINT)-8 b(ABLE)0 668 y(to)31 b(de\014ne)e(whether)g -(it)h(is)g(an)f(ASCI)s(I)g(or)g(binary)g(table,)i(and)f(NAXIS2)g(to)g -(de\014ne)f(the)h(n)m(um)m(b)s(er)f(of)h(ro)m(ws)f(in)h(the)0 -781 y(table.)50 b(Tw)m(o)34 b(template)g(lines)g(are)g(then)f(needed)f -(to)i(de\014ne)f(the)g(name)h(\(TTYPEn\))e(and)h(FITS)g(data)h(format)0 -894 y(\(TF)m(ORMn\))d(of)f(the)h(columns,)f(as)h(in)f(this)g(example:) -95 1154 y Fe(xtension)46 b(=)h(bintable)95 1267 y(naxis2)g(=)g(40)95 -1380 y(ttype#)g(=)g(Name)95 1492 y(tform#)g(=)g(10a)95 -1605 y(ttype#)g(=)g(Npoints)95 1718 y(tform#)g(=)g(j)95 -1831 y(ttype#)g(=)g(Rate)95 1944 y(tunit#)g(=)g(counts/s)95 -2057 y(tform#)g(=)g(e)0 2317 y Fi(The)26 b(ab)s(o)m(v)m(e)j(example)e -(de\014nes)f(a)i(n)m(ull)f(primary)f(arra)m(y)h(follo)m(w)m(ed)i(b)m(y) -e(a)g(40-ro)m(w)h(binary)e(table)i(extension)g(with)f(3)0 -2430 y(columns)h(called)h('Name',)h('Np)s(oin)m(ts',)f(and)f('Rate',)i -(with)e(data)h(formats)f(of)g('10A')i(\(ASCI)s(I)d(c)m(haracter)i -(string\),)0 2543 y('1J')k(\(in)m(teger\))i(and)d('1E')i(\(\015oating)f -(p)s(oin)m(t\),)h(resp)s(ectiv)m(ely)-8 b(.)50 b(Note)34 -b(that)f(the)g(other)g(required)f(FITS)g(k)m(eyw)m(ords)0 -2655 y(\(BITPIX,)37 b(NAXIS,)g(NAXIS1,)h(PCOUNT,)e(GCOUNT,)h(TFIELDS,)f -(and)g(END\))h(do)g(not)g(need)f(to)h(b)s(e)f(ex-)0 2768 -y(plicitly)j(de\014ned)d(in)i(the)f(template)i(b)s(ecause)f(their)g(v) --5 b(alues)38 b(can)g(b)s(e)f(inferred)f(from)i(the)f(other)h(k)m(eyw)m -(ords)g(in)0 2881 y(the)d(template.)55 b(This)34 b(example)i(also)g -(illustrates)f(that)h(the)f(templates)h(are)f(generally)h -(case-insensitiv)m(e)h(\(the)0 2994 y(k)m(eyw)m(ord)29 -b(names)g(and)g(TF)m(ORMn)f(v)-5 b(alues)30 b(are)f(con)m(v)m(erted)i -(to)e(upp)s(er-case)g(in)f(the)h(FITS)g(\014le\))g(and)f(that)i(string) -0 3107 y(k)m(eyw)m(ord)h(v)-5 b(alues)31 b(generally)g(do)f(not)h(need) -f(to)h(b)s(e)f(enclosed)h(in)f(quotes.)p eop end -%%Page: 114 120 -TeXDict begin 114 119 bop 0 299 a Fi(114)2295 b Fg(CHAPTER)30 -b(9.)71 b(TEMPLA)-8 b(TE)30 b(FILES)p eop end -%%Page: 115 121 -TeXDict begin 115 120 bop 0 1225 a Ff(Chapter)65 b(10)0 -1687 y Fl(Summary)76 b(of)i(all)f(FITSIO)0 1937 y(User-In)-6 -b(terface)77 b(Subroutines)0 2429 y Fi(Error)29 b(Status)i(Routines)f -(page)h(29)382 2696 y Fe(FTVERS\()46 b(>)h(version\))382 -2809 y(FTGERR\(status,)d(>)j(errtext\))382 2922 y(FTGMSG\()f(>)h -(errmsg\))382 3035 y(FTRPRT)f(\(stream,)f(>)j(status\))382 -3147 y(FTPMSG\(errmsg\))382 3260 y(FTPMRK)382 3373 y(FTCMSG)382 -3486 y(FTCMRK)0 3753 y Fi(FITS)30 b(File)h(Op)s(en)e(and)h(Close)h -(Subroutines:)39 b(page)31 b(35)382 4020 y Fe -(FTOPEN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(blocksize,status\))382 -4133 y(FTDKOPN\(unit,filename,rw)o(mod)o(e,)42 b(>)47 -b(blocksize,status\))382 4246 y(FTNOPN\(unit,filename,rwm)o(ode)o(,)42 -b(>)47 b(status\))382 4359 y(FTDOPN\(unit,filename,rwm)o(ode)o(,)42 -b(>)47 b(status\))382 4472 y(FTTOPN\(unit,filename,rwm)o(ode)o(,)42 -b(>)47 b(status\))382 4585 y(FTIOPN\(unit,filename,rwm)o(ode)o(,)42 -b(>)47 b(status\))382 4698 y(FTREOPEN\(unit,)d(>)j(newunit,)f(status\)) -382 4811 y(FTINIT\(unit,filename,blo)o(cks)o(ize,)41 -b(>)48 b(status\))382 4924 y(FTDKINIT\(unit,filename,b)o(loc)o(ksiz)o -(e,)42 b(>)47 b(status\))382 5036 y(FTTPLT\(unit,)d(filename,)i -(tplfilename,)e(>)j(status\))382 5149 y(FTFLUS\(unit,)d(>)k(status\)) -382 5262 y(FTCLOS\(unit,)c(>)k(status\))382 5375 y(FTDELT\(unit,)c(>)k -(status\))382 5488 y(FTGIOU\()e(>)h(iounit,)f(status\))382 -5601 y(FTFIOU\(iounit,)e(>)j(status\))0 5714 y(CFITS2Unit\(fitsfile)c -(*ptr\))141 b(\(C)48 b(routine\))1882 5942 y Fi(115)p -eop end -%%Page: 116 122 -TeXDict begin 116 121 bop 0 299 a Fi(116)281 b Fg(CHAPTER)30 -b(10.)112 b(SUMMAR)-8 b(Y)32 b(OF)e(ALL)g(FITSIO)f(USER-INTERF)-10 -b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(CUnit2FITS\(int)44 -b(unit\))380 b(\(C)47 b(routine\))382 668 y(FTEXTN\(filename,)c(>)48 -b(nhdu,)e(status\))382 781 y(FTFLNM\(unit,)e(>)k(filename,)d(status\)) -382 894 y(FTFLMD\(unit,)f(>)k(iomode,)e(status\))382 -1007 y(FTURLT\(unit,)e(>)k(urltype,)d(status\))382 1120 -y(FTIURL\(filename,)e(>)48 b(filetype,)d(infile,)h(outfile,)f(extspec,) -h(filter,)716 1233 y(binspec,)f(colspec,)h(status\))382 -1346 y(FTRTNM\(filename,)d(>)48 b(rootname,)d(status\))382 -1458 y(FTEXIST\(filename,)e(>)k(exist,)f(status\))0 1695 -y Fi(HDU-Lev)m(el)33 b(Op)s(erations:)40 b(page)31 b(38)382 -1932 y Fe(FTMAHD\(unit,nhdu,)43 b(>)k(hdutype,status\))382 -2045 y(FTMRHD\(unit,nmove,)c(>)k(hdutype,status\))382 -2158 y(FTGHDN\(unit,)d(>)k(nhdu\))382 2271 y(FTMNHD\(unit,)c(hdutype,)i -(extname,)f(extver,)h(>)i(status\))382 2384 y(FTGHDT\(unit,)c(>)k -(hdutype,)d(status\))382 2497 y(FTTHDU\(unit,)f(>)k(hdunum,)e(status\)) -382 2610 y(FTCRHD\(unit,)e(>)k(status\))382 2723 y -(FTIIMG\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 b(status\))382 -2836 y(FTITAB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o(ype)o(,tbc)o -(ol,t)o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 -2949 y(status\))382 3061 y(FTIBIN\(unit,nrows,tfield)o(s,t)o(type)o -(,tfo)o(rm,)o(tuni)o(t,ex)o(tna)o(me,v)o(arid)o(at)f(>)48 -b(status\))382 3174 y(FTRSIM\(unit,bitpix,naxis)o(,na)o(xes,)o(stat)o -(us\))382 3287 y(FTDHDU\(unit,)c(>)k(hdutype,status\))382 -3400 y(FTCPFL\(iunit,ounit,previ)o(ous)o(,)42 b(current,)j(following,)g -(>)j(status\))382 3513 y(FTCOPY\(iunit,ounit,morek)o(eys)o(,)42 -b(>)47 b(status\))382 3626 y(FTCPHD\(inunit,)d(outunit,)h(>)j(status\)) -382 3739 y(FTCPDT\(iunit,ounit,)42 b(>)48 b(status\))0 -3976 y Fi(Subroutines)29 b(to)i(sp)s(ecify)f(or)g(mo)s(dify)g(the)g -(structure)g(of)h(the)f(CHDU:)h(page)h(41)382 4213 y -Fe(FTRDEF\(unit,)44 b(>)k(status\))93 b(\(DEPRECATED\))382 -4326 y(FTPDEF\(unit,bitpix,naxis)o(,na)o(xes,)o(pcou)o(nt,)o(gcou)o -(nt,)41 b(>)48 b(status\))93 b(\(DEPRECATED\))382 4439 -y(FTADEF\(unit,rowlen,tfiel)o(ds,)o(tbco)o(l,tf)o(orm)o(,nro)o(ws)42 -b(>)47 b(status\))94 b(\(DEPRECATED\))382 4551 y -(FTBDEF\(unit,tfields,tfor)o(m,v)o(arid)o(at,n)o(row)o(s)42 -b(>)47 b(status\))94 b(\(DEPRECATED\))382 4664 y(FTDDEF\(unit,bytlen,) -42 b(>)48 b(status\))93 b(\(DEPRECATED\))382 4777 y -(FTPTHP\(unit,theap,)43 b(>)k(status\))0 5014 y Fi(Header)31 -b(Space)f(and)g(P)m(osition)i(Subroutines:)39 b(page)31 -b(43)382 5251 y Fe(FTHDEF\(unit,morekeys,)42 b(>)47 b(status\))382 -5364 y(FTGHSP\(iunit,)d(>)j(keysexist,keysadd,status\))382 -5477 y(FTGHPS\(iunit,)d(>)j(keysexist,key_no,status\))0 -5714 y Fi(Read)31 b(or)f(W)-8 b(rite)32 b(Standard)d(Header)i -(Subroutines:)39 b(page)31 b(43)p eop end -%%Page: 117 123 -TeXDict begin 117 122 bop 3764 299 a Fi(117)382 555 y -Fe(FTPHPS\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 b(status\))382 -668 y(FTPHPR\(unit,simple,bitpi)o(x,n)o(axis)o(,nax)o(es,)o(pcou)o -(nt,g)o(cou)o(nt,e)o(xten)o(d,)41 b(>)48 b(status\))382 -781 y(FTGHPR\(unit,maxdim,)42 b(>)48 b(simple,bitpix,naxis,naxe)o(s,p)o -(coun)o(t,gc)o(oun)o(t,ex)o(tend)o(,)716 894 y(status\))382 -1007 y(FTPHTB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o(ype)o(,tbc)o -(ol,t)o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 -1120 y(status\))382 1233 y(FTGHTB\(unit,maxdim,)g(>)48 -b(rowlen,nrows,tfields,tty)o(pe,)o(tbco)o(l,tf)o(orm)o(,tun)o(it,)716 -1346 y(extname,status\))382 1458 y(FTPHBN\(unit,nrows,tfield)o(s,t)o -(type)o(,tfo)o(rm,)o(tuni)o(t,ex)o(tna)o(me,v)o(arid)o(at)41 -b(>)48 b(status\))382 1571 y(FTGHBN\(unit,maxdim,)42 -b(>)48 b(nrows,tfields,ttype,tfor)o(m,t)o(unit)o(,ext)o(nam)o(e,va)o -(rida)o(t,)716 1684 y(status\))0 1942 y Fi(W)-8 b(rite)32 -b(Keyw)m(ord)e(Subroutines:)39 b(page)31 b(45)382 2199 -y Fe(FTPREC\(unit,card,)43 b(>)k(status\))382 2312 y -(FTPCOM\(unit,comment,)42 b(>)48 b(status\))382 2425 -y(FTPHIS\(unit,history,)42 b(>)48 b(status\))382 2538 -y(FTPDAT\(unit,)c(>)k(status\))382 2651 y(FTPKY[JKLS]\(unit,keyword)o -(,ke)o(yval)o(,com)o(men)o(t,)42 b(>)47 b(status\))382 -2764 y(FTPKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o -(omme)o(nt,)41 b(>)48 b(status\))382 2877 y(FTPKLS\(unit,keyword,keyv)o -(al,)o(comm)o(ent,)41 b(>)47 b(status\))382 2990 y(FTPLSW\(unit,)d(>)k -(status\))382 3103 y(FTPKYU\(unit,keyword,comm)o(ent)o(,)42 -b(>)47 b(status\))382 3216 y(FTPKN[JKLS]\(unit,keyroot)o(,st)o(artn)o -(o,no)o(_ke)o(ys,k)o(eyva)o(ls,)o(comm)o(ents)o(,)42 -b(>)47 b(status\))382 3329 y(FTPKN[EDFG]\(unit,keyroot)o(,st)o(artn)o -(o,no)o(_ke)o(ys,k)o(eyva)o(ls,)o(deci)o(mals)o(,co)o(mmen)o(ts,)41 -b(>)907 3441 y(status\))382 3554 y(FTCPKYinunit,)j(outunit,)i(innum,)g -(outnum,)f(keyroot,)h(>)h(status\))382 3667 y -(FTPKYT\(unit,keyword,intv)o(al,)o(dblv)o(al,c)o(omm)o(ent,)41 -b(>)48 b(status\))382 3780 y(FTPKTP\(unit,)c(filename,)i(>)h(status\)) -382 3893 y(FTPUNT\(unit,keyword,unit)o(s,)41 b(>)48 b(status\))0 -4151 y Fi(Insert)30 b(Keyw)m(ord)g(Subroutines:)39 b(page)31 -b(47)382 4408 y Fe(FTIREC\(unit,key_no,card,)41 b(>)47 -b(status\))382 4521 y(FTIKY[JKLS]\(unit,keyword)o(,ke)o(yval)o(,com)o -(men)o(t,)42 b(>)47 b(status\))382 4634 y(FTIKLS\(unit,keyword,keyv)o -(al,)o(comm)o(ent,)41 b(>)47 b(status\))382 4747 y -(FTIKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o(omme)o -(nt,)41 b(>)48 b(status\))382 4860 y(FTIKYU\(unit,keyword,comm)o(ent)o -(,)42 b(>)47 b(status\))0 5118 y Fi(Read)31 b(Keyw)m(ord)f -(Subroutines:)39 b(page)31 b(47)382 5375 y Fe(FTGREC\(unit,key_no,)42 -b(>)48 b(card,status\))382 5488 y(FTGKYN\(unit,key_no,)42 -b(>)48 b(keyword,value,comment,st)o(atu)o(s\))382 5601 -y(FTGCRD\(unit,keyword,)42 b(>)48 b(card,status\))382 -5714 y(FTGNXK\(unit,inclist,ninc)o(,ex)o(clis)o(t,ne)o(xc,)41 -b(>)48 b(card,status\))p eop end -%%Page: 118 124 -TeXDict begin 118 123 bop 0 299 a Fi(118)281 b Fg(CHAPTER)30 -b(10.)112 b(SUMMAR)-8 b(Y)32 b(OF)e(ALL)g(FITSIO)f(USER-INTERF)-10 -b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTGKEY\(unit,keyword,)42 -b(>)48 b(value,comment,status\))382 668 y(FTGKY[EDJKLS]\(unit,keywo)o -(rd,)41 b(>)48 b(keyval,comment,status\))382 781 y -(FTGKSL\(unit,keyword,)42 b(>)48 b(length,status\))382 -894 y(FTGSKY\(unit,keyword,firs)o(tch)o(ar,m)o(axch)o(ar,)o(>)42 -b(keyval,length,comment,st)o(atus)o(\))382 1007 y -(FTGKN[EDJKLS]\(unit,keyro)o(ot,)o(star)o(tno,)o(max)o(_key)o(s,)g(>)47 -b(keyvals,nfound,status\))382 1120 y(FTGKYT\(unit,keyword,)42 -b(>)48 b(intval,dblval,comment,s)o(tat)o(us\))382 1233 -y(FTGUNT\(unit,keyword,)42 b(>)48 b(units,status\))0 -1489 y Fi(Mo)s(dify)30 b(Keyw)m(ord)g(Subroutines:)39 -b(page)31 b(49)382 1745 y Fe(FTMREC\(unit,key_no,card,)41 -b(>)47 b(status\))382 1858 y(FTMCRD\(unit,keyword,card)o(,)42 -b(>)47 b(status\))382 1971 y(FTMNAM\(unit,oldkey,keywo)o(rd,)41 -b(>)48 b(status\))382 2084 y(FTMCOM\(unit,keyword,comm)o(ent)o(,)42 -b(>)47 b(status\))382 2197 y(FTMKY[JKLS]\(unit,keyword)o(,ke)o(yval)o -(,com)o(men)o(t,)42 b(>)47 b(status\))382 2310 y -(FTMKLS\(unit,keyword,keyv)o(al,)o(comm)o(ent,)41 b(>)47 -b(status\))382 2422 y(FTMKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o -(ima)o(ls,c)o(omme)o(nt,)41 b(>)48 b(status\))382 2535 -y(FTMKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 -2792 y Fi(Up)s(date)30 b(Keyw)m(ord)g(Subroutines:)39 -b(page)32 b(50)382 3048 y Fe(FTUCRD\(unit,keyword,card)o(,)42 -b(>)47 b(status\))382 3161 y(FTUKY[JKLS]\(unit,keyword)o(,ke)o(yval)o -(,com)o(men)o(t,)42 b(>)47 b(status\))382 3274 y -(FTUKLS\(unit,keyword,keyv)o(al,)o(comm)o(ent,)41 b(>)47 -b(status\))382 3386 y(FTUKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o -(ima)o(ls,c)o(omme)o(nt,)41 b(>)48 b(status\))382 3499 -y(FTUKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 -3756 y Fi(Delete)33 b(Keyw)m(ord)d(Subroutines:)39 b(page)31 -b(51)382 4012 y Fe(FTDREC\(unit,key_no,)42 b(>)48 b(status\))382 -4125 y(FTDKEY\(unit,keyword,)42 b(>)48 b(status\))0 4381 -y Fi(De\014ne)31 b(Data)h(Scaling)f(P)m(arameters)g(and)f(Unde\014ned)f -(Pixel)i(Flags:)42 b(page)31 b(51)382 4637 y Fe -(FTPSCL\(unit,bscale,bzero)o(,)42 b(>)47 b(status\))382 -4750 y(FTTSCL\(unit,colnum,tscal)o(,tz)o(ero,)41 b(>)48 -b(status\))382 4863 y(FTPNUL\(unit,blank,)43 b(>)k(status\))382 -4976 y(FTSNUL\(unit,colnum,snull)41 b(>)47 b(status\))382 -5089 y(FTTNUL\(unit,colnum,tnull)41 b(>)47 b(status\))0 -5345 y Fi(FITS)30 b(Primary)f(Arra)m(y)i(or)f(IMA)m(GE)i(Extension)e -(I/O)h(Subroutines:)39 b(page)31 b(52)382 5601 y Fe(FTGIDT\(unit,)44 -b(>)k(bitpix,status\))382 5714 y(FTGIET\(unit,)c(>)k(bitpix,status\))p -eop end -%%Page: 119 125 -TeXDict begin 119 124 bop 3764 299 a Fi(119)382 555 y -Fe(FTGIDM\(unit,)44 b(>)k(naxis,status\))382 668 y(FTGISZ\(unit,)c -(maxdim,)i(>)i(naxes,status\))382 781 y(FTGIPR\(unit,)c(maxdim,)i(>)i -(bitpix,naxis,naxes,stat)o(us\))382 894 y(FTPPR[BIJKED]\(unit,group)o -(,fp)o(ixel)o(,nel)o(eme)o(nts,)o(valu)o(es,)41 b(>)48 -b(status\))382 1007 y(FTPPN[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o -(eme)o(nts,)o(valu)o(es,)o(null)o(val)41 b(>)48 b(status\))382 -1120 y(FTPPRU\(unit,group,fpixel)o(,ne)o(leme)o(nts,)41 -b(>)47 b(status\))382 1233 y(FTGPV[BIJKED]\(unit,group)o(,fp)o(ixel)o -(,nel)o(eme)o(nts,)o(null)o(val)o(,)42 b(>)47 b(values,anyf,status\)) -382 1346 y(FTGPF[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o(eme)o(nts,) -41 b(>)48 b(values,flagvals,anyf,st)o(atu)o(s\))382 1458 -y(FTPGP[BIJKED]\(unit,group)o(,fp)o(arm,)o(npar)o(m,v)o(alue)o(s,)42 -b(>)47 b(status\))382 1571 y(FTGGP[BIJKED]\(unit,group)o(,fp)o(arm,)o -(npar)o(m,)41 b(>)48 b(values,status\))382 1684 y -(FTP2D[BIJKED]\(unit,group)o(,di)o(m1,n)o(axis)o(1,n)o(axis)o(2,im)o -(age)o(,)42 b(>)47 b(status\))382 1797 y(FTP3D[BIJKED]\(unit,group)o -(,di)o(m1,d)o(im2,)o(nax)o(is1,)o(naxi)o(s2,)o(naxi)o(s3,c)o(ube)o(,)42 -b(>)47 b(status\))382 1910 y(FTG2D[BIJKED]\(unit,group)o(,nu)o(llva)o -(l,di)o(m1,)o(naxi)o(s1,n)o(axi)o(s2,)41 b(>)48 b(image,anyf,status\)) -382 2023 y(FTG3D[BIJKED]\(unit,group)o(,nu)o(llva)o(l,di)o(m1,)o(dim2)o -(,nax)o(is1)o(,nax)o(is2,)o(nax)o(is3,)41 b(>)1002 2136 -y(cube,anyf,status\))382 2249 y(FTPSS[BIJKED]\(unit,group)o(,na)o(xis,) -o(naxe)o(s,f)o(pixe)o(ls,l)o(pix)o(els,)o(arra)o(y,)g(>)48 -b(status\))382 2362 y(FTGSV[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o -(s,f)o(pixe)o(ls,l)o(pix)o(els,)o(incs)o(,nu)o(llva)o(l,)42 -b(>)1002 2475 y(array,anyf,status\))382 2588 y -(FTGSF[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o(s,f)o(pixe)o(ls,l)o -(pix)o(els,)o(incs)o(,)g(>)1002 2700 y(array,flagvals,anyf,statu)o(s\)) -0 2974 y Fi(T)-8 b(able)31 b(Column)e(Information)i(Subroutines:)39 -b(page)31 b(55)382 3247 y Fe(FTGNRW\(unit,)44 b(>)k(nrows,)e(status\)) -382 3360 y(FTGNCL\(unit,)e(>)k(ncols,)e(status\))382 -3473 y(FTGCNO\(unit,casesen,colt)o(emp)o(late)o(,)c(>)47 -b(colnum,status\))382 3586 y(FTGCNN\(unit,casesen,colt)o(emp)o(late)o -(,)42 b(>)47 b(colnam,colnum,status\))382 3699 y(FTGTCL\(unit,colnum,) -42 b(>)48 b(datacode,repeat,width,st)o(atu)o(s\))382 -3812 y(FTEQTY\(unit,colnum,)42 b(>)48 b(datacode,repeat,width,st)o(atu) -o(s\))382 3925 y(FTGCDW\(unit,colnum,)42 b(>)48 b(dispwidth,status\)) -382 4038 y(FTGACL\(unit,colnum,)42 b(>)716 4151 y -(ttype,tbcol,tunit,tform,)o(tsca)o(l,t)o(zero)o(,snu)o(ll,)o(tdis)o -(p,st)o(atu)o(s\))382 4264 y(FTGBCL\(unit,colnum,)g(>)716 -4377 y(ttype,tunit,datatype,rep)o(eat,)o(tsc)o(al,t)o(zero)o(,tn)o -(ull,)o(tdis)o(p,s)o(tatu)o(s\))382 4489 y(FTPTDM\(unit,colnum,naxis)o -(,na)o(xes,)f(>)48 b(status\))382 4602 y(FTGTDM\(unit,colnum,maxdi)o -(m,)41 b(>)48 b(naxis,naxes,status\))382 4715 y -(FTDTDM\(unit,tdimstr,coln)o(um,)o(maxd)o(im,)41 b(>)48 -b(naxis,naxes,)c(status\))382 4828 y(FTGRSZ\(unit,)g(>)k -(nrows,status\))0 5102 y Fi(Lo)m(w-Lev)m(el)32 b(T)-8 -b(able)31 b(Access)h(Subroutines:)39 b(page)31 b(58)382 -5375 y Fe(FTGTBS\(unit,frow,startch)o(ar,)o(ncha)o(rs,)41 -b(>)48 b(string,status\))382 5488 y(FTPTBS\(unit,frow,startch)o(ar,)o -(ncha)o(rs,s)o(tri)o(ng,)41 b(>)48 b(status\))382 5601 -y(FTGTBB\(unit,frow,startch)o(ar,)o(ncha)o(rs,)41 b(>)48 -b(array,status\))382 5714 y(FTPTBB\(unit,frow,startch)o(ar,)o(ncha)o -(rs,a)o(rra)o(y,)42 b(>)47 b(status\))p eop end -%%Page: 120 126 -TeXDict begin 120 125 bop 0 299 a Fi(120)281 b Fg(CHAPTER)30 -b(10.)112 b(SUMMAR)-8 b(Y)32 b(OF)e(ALL)g(FITSIO)f(USER-INTERF)-10 -b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fi(Edit)g(Ro)m(ws)h(or)f(Columns)g -(page)h(59)382 813 y Fe(FTIROW\(unit,frow,nrows,)41 b(>)48 -b(status\))382 926 y(FTDROW\(unit,frow,nrows,)41 b(>)48 -b(status\))382 1039 y(FTDRRG\(unit,rowrange,)42 b(>)47 -b(status\))382 1152 y(FTDRWS\(unit,rowlist,nrow)o(s,)41 -b(>)48 b(status\))382 1264 y(FTICOL\(unit,colnum,ttype)o(,tf)o(orm,)41 -b(>)48 b(status\))382 1377 y(FTICLS\(unit,colnum,ncols)o(,tt)o(ype,)o -(tfor)o(m,)41 b(>)48 b(status\))382 1490 y(FTMVEC\(unit,colnum,newve)o -(cle)o(n,)42 b(>)47 b(status\))382 1603 y(FTDCOL\(unit,colnum,)42 -b(>)48 b(status\))382 1716 y(FTCPCL\(inunit,outunit,in)o(col)o(num,)o -(outc)o(oln)o(um,c)o(reat)o(eco)o(l,)42 b(>)47 b(status\);)0 -1974 y Fi(Read)31 b(and)e(W)-8 b(rite)32 b(Column)e(Data)i(Routines)e -(page)h(60)382 2231 y Fe(FTPCL[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o(row,) -o(fel)o(em,n)o(elem)o(ent)o(s,va)o(lues)o(,)42 b(>)47 -b(status\))382 2344 y(FTPCN[BIJKED]\(unit,colnu)o(m,f)o(row,)o(fele)o -(m,n)o(elem)o(ents)o(,va)o(lues)o(,nul)o(lva)o(l)42 b(>)47 -b(status\))382 2457 y(FTPCLX\(unit,colnum,frow,)o(fbi)o(t,nb)o(it,l)o -(ray)o(,)42 b(>)47 b(status\))382 2570 y(FTPCLU\(unit,colnum,frow,)o -(fel)o(em,n)o(elem)o(ent)o(s,)42 b(>)47 b(status\))382 -2683 y(FTGCL\(unit,colnum,frow,f)o(ele)o(m,ne)o(leme)o(nts)o(,)42 -b(>)47 b(values,status\))382 2796 y(FTGCV[SBIJKEDCM]\(unit,co)o(lnu)o -(m,fr)o(ow,f)o(ele)o(m,ne)o(leme)o(nts)o(,nul)o(lval)o(,)42 -b(>)1098 2909 y(values,anyf,status\))382 3022 y -(FTGCF[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o(row,)o(fel)o(em,n)o(elem)o -(ent)o(s,)g(>)1193 3135 y(values,flagvals,anyf,stat)o(us\))382 -3247 y(FTGSV[BIJKED]\(unit,colnu)o(m,n)o(axis)o(,nax)o(es,)o(fpix)o -(els,)o(lpi)o(xels)o(,inc)o(s,n)o(ullv)o(al,)f(>)1002 -3360 y(array,anyf,status\))382 3473 y(FTGSF[BIJKED]\(unit,colnu)o(m,n)o -(axis)o(,nax)o(es,)o(fpix)o(els,)o(lpi)o(xels)o(,inc)o(s,)g(>)1002 -3586 y(array,flagvals,anyf,statu)o(s\))382 3699 y -(FTGCX\(unit,colnum,frow,f)o(bit)o(,nbi)o(t,)h(>)47 b(lray,status\))382 -3812 y(FTGCX[IJD]\(unit,colnum,f)o(row)o(,nro)o(ws,f)o(bit)o(,nbi)o(t,) -42 b(>)47 b(array,status\))382 3925 y(FTGDES\(unit,colnum,rownu)o(m,)41 -b(>)48 b(nelements,offset,status\))382 4038 y -(FTPDES\(unit,colnum,rownu)o(m,n)o(elem)o(ents)o(,of)o(fset)o(,)42 -b(>)47 b(status\))0 4295 y Fi(Ro)m(w)31 b(Selection)h(and)d(Calculator) -j(Routines:)41 b(page)31 b(64)382 4553 y Fe(FTFROW\(unit,expr,firstro)o -(w,)41 b(nrows,)47 b(>)g(n_good_rows,)d(row_status,)h(status\))382 -4666 y(FTFFRW\(unit,)f(expr,)j(>)g(rownum,)f(status\))382 -4779 y(FTSROW\(inunit,)e(outunit,)h(expr,)i(>)g(status)f(\))382 -4892 y(FTCROW\(unit,datatype,exp)o(r,f)o(irst)o(row,)o(nel)o(emen)o -(ts,n)o(ulv)o(al,)41 b(>)620 5005 y(array,anynul,status\))382 -5118 y(FTCALC\(inunit,)j(expr,)i(outunit,)g(parName,)f(parInfo,)h(>)h -(status\))382 5230 y(FTCALC_RNG\(inunit,)c(expr,)j(outunit,)g(parName,) -f(parInfo,)573 5343 y(nranges,)g(firstrow,)h(lastrow,)f(>)j(status\)) -382 5456 y(FTTEXP\(unit,)c(expr,)j(>)g(datatype,)e(nelem,)h(naxis,)h -(naxes,)f(status\))0 5714 y Fi(Celestial)32 b(Co)s(ordinate)f(System)f -(Subroutines:)39 b(page)31 b(65)p eop end -%%Page: 121 127 -TeXDict begin 121 126 bop 3764 299 a Fi(121)382 555 y -Fe(FTGICS\(unit,)44 b(>)k(xrval,yrval,xrpix,yrpix)o(,xin)o(c,yi)o(nc,)o -(rot,)o(coor)o(dty)o(pe,s)o(tatu)o(s\))382 668 y -(FTGTCS\(unit,xcol,ycol,)42 b(>)716 781 y(xrval,yrval,xrpix,yrpix,)o -(xinc)o(,yi)o(nc,r)o(ot,c)o(oor)o(dtyp)o(e,st)o(atu)o(s\))382 -894 y(FTWLDP\(xpix,ypix,xrval,y)o(rva)o(l,xr)o(pix,)o(yrp)o(ix,x)o -(inc,)o(yin)o(c,ro)o(t,)1241 1007 y(coordtype,)j(>)i -(xpos,ypos,status\))382 1120 y(FTXYPX\(xpos,ypos,xrval,y)o(rva)o(l,xr)o -(pix,)o(yrp)o(ix,x)o(inc,)o(yin)o(c,ro)o(t,)1241 1233 -y(coordtype,)e(>)i(xpix,ypix,status\))0 1490 y Fi(File)32 -b(Chec)m(ksum)d(Subroutines:)40 b(page)31 b(67)382 1748 -y Fe(FTPCKS\(unit,)44 b(>)k(status\))382 1861 y(FTUCKS\(unit,)c(>)k -(status\))382 1974 y(FTVCKS\(unit,)c(>)k(dataok,hduok,status\))382 -2087 y(FTGCKS\(unit,)c(>)k(datasum,hdusum,status\))382 -2199 y(FTESUM\(sum,complement,)42 b(>)47 b(checksum\))382 -2312 y(FTDSUM\(checksum,compleme)o(nt,)41 b(>)48 b(sum\))0 -2683 y Fi(Time)30 b(and)g(Date)i(Utilit)m(y)h(Subroutines:)39 -b(page)31 b(68)382 2940 y Fe(FTGSDT\()46 b(>)h(day,)g(month,)f(year,)g -(status)g(\))382 3053 y(FTGSTM\(>)f(datestr,)h(timeref,)f(status\))382 -3166 y(FTDT2S\()h(year,)g(month,)g(day,)h(>)g(datestr,)f(status\))382 -3279 y(FTTM2S\()g(year,)g(month,)g(day,)h(hour,)f(minute,)g(second,)g -(decimals,)764 3392 y(>)h(datestr,)f(status\))382 3505 -y(FTS2DT\(datestr,)d(>)48 b(year,)e(month,)g(day,)h(status\))382 -3618 y(FTS2TM\(datestr,)c(>)48 b(year,)e(month,)g(day,)h(hour,)f -(minute,)g(second,)g(status\))0 3876 y Fi(General)31 -b(Utilit)m(y)i(Subroutines:)39 b(page)31 b(69)382 4133 -y Fe(FTGHAD\(unit,)44 b(>)k(curaddr,nextaddr\))382 4246 -y(FTUPCH\(string\))382 4359 y(FTCMPS\(str_template,stri)o(ng,)o(case)o -(sen,)41 b(>)47 b(match,exact\))382 4472 y(FTTKEY\(keyword,)c(>)48 -b(status\))382 4585 y(FTTREC\(card,)c(>)k(status\))382 -4698 y(FTNCHK\(unit,)c(>)k(status\))382 4811 y(FTGKNM\(unit,)c(>)k -(keyword,)d(keylength,)g(status\))382 4924 y(FTMKKY\(keyword,)e -(value,comment,)h(>)k(card,)e(status\))382 5036 y(FTPSVC\(card,)e(>)k -(value,comment,status\))382 5149 y(FTKEYN\(keyroot,seq_no,)42 -b(>)47 b(keyword,status\))382 5262 y(FTNKEY\(seq_no,keyroot,)42 -b(>)47 b(keyword,status\))382 5375 y(FTDTYP\(value,)d(>)j -(dtype,status\))382 5488 y(class)f(=)i(FTGKCL\(card\))382 -5601 y(FTASFM\(tform,)c(>)j(datacode,width,decimals,st)o(atus)o(\))382 -5714 y(FTBNFM\(tform,)d(>)j(datacode,repeat,width,stat)o(us\))p -eop end -%%Page: 122 128 -TeXDict begin 122 127 bop 0 299 a Fi(122)281 b Fg(CHAPTER)30 -b(10.)112 b(SUMMAR)-8 b(Y)32 b(OF)e(ALL)g(FITSIO)f(USER-INTERF)-10 -b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTGABC\(tfields,tform,spa)o -(ce,)41 b(>)48 b(rowlen,tbcol,status\))382 668 y(FTGTHD\(template,)43 -b(>)48 b(card,hdtype,status\))382 781 y(FTRWRG\(rowlist,)43 -b(maxrows,)j(maxranges,)f(>)i(numranges,)e(rangemin,)716 -894 y(rangemax,)g(status\))p eop end -%%Page: 123 129 -TeXDict begin 123 128 bop 0 1225 a Ff(Chapter)65 b(11)0 -1687 y Fl(P)-6 b(arameter)77 b(De\014nitions)0 2180 y -Fe(anyf)47 b(-)g(\(logical\))e(set)i(to)g(TRUE)g(if)g(any)g(of)g(the)g -(returned)f(data)g(values)h(are)f(undefined)0 2293 y(array)g(-)i(\(any) -e(datatype)g(except)g(character\))f(array)h(of)i(bytes)e(to)h(be)g -(read)g(or)g(written.)0 2406 y(bitpix)f(-)i(\(integer\))d(bits)h(per)h -(pixel:)f(8,)i(16,)f(32,)f(-32,)h(or)g(-64)0 2518 y(blank)f(-)i -(\(integer\))d(value)h(used)h(for)g(undefined)e(pixels)h(in)i(integer)d -(primary)h(array)0 2631 y(blank)g(-)i(\(integer*8\))d(value)h(used)h -(for)f(undefined)g(pixels)g(in)h(integer)f(primary)g(array)0 -2744 y(blocksize)f(-)j(\(integer\))d(2880-byte)g(logical)h(record)g -(blocking)g(factor)477 2857 y(\(if)h(0)h(<)f(blocksize)e(<)j(11\))f(or) -g(the)g(actual)f(block)g(size)h(in)g(bytes)477 2970 y(\(if)g(10)g(<)h -(blocksize)d(<)j(28800\).)93 b(As)47 b(of)g(version)f(3.3)h(of)g -(FITSIO,)477 3083 y(blocksizes)e(greater)h(than)h(2880)f(are)h(no)g -(longer)g(supported.)0 3196 y(bscale)f(-)i(\(double)d(precision\))g -(scaling)h(factor)g(for)h(the)g(primary)f(array)0 3309 -y(bytlen)g(-)i(\(integer\))d(length)h(of)h(the)g(data)g(unit,)f(in)h -(bytes)0 3422 y(bzero)f(-)i(\(double)e(precision\))f(zero)h(point)h -(for)g(primary)e(array)i(scaling)0 3535 y(card)g(-)g(\(character*80\))d -(header)i(record)g(to)h(be)h(read)e(or)h(written)0 3648 -y(casesen)f(-)h(\(logical\))f(will)g(string)g(matching)g(be)h(case)g -(sensitive?)0 3760 y(checksum)f(-)h(\(character*16\))d(encoded)i -(checksum)f(string)0 3873 y(colname)h(-)h(\(character\))e(ASCII)h(name) -h(of)g(the)g(column)0 3986 y(colnum)f(-)i(\(integer\))d(number)h(of)h -(the)g(column)f(\(first)g(column)g(=)i(1\))0 4099 y(coltemplate)d(-)i -(\(character\))e(template)g(string)i(to)g(be)g(matched)f(to)h(column)f -(names)0 4212 y(comment)g(-)h(\(character\))e(the)i(keyword)f(comment)g -(field)0 4325 y(comments)g(-)h(\(character)e(array\))h(keyword)g -(comment)g(fields)0 4438 y(compid)g(-)i(\(integer\))d(the)i(type)f(of)i -(computer)d(that)i(the)g(program)e(is)j(running)d(on)0 -4551 y(complement)g(-)i(\(logical\))f(should)g(the)h(checksum)e(be)i -(complemented?)0 4664 y(coordtype)e(-)j(\(character\))c(type)j(of)g -(coordinate)e(projection)g(\(-SIN,)h(-TAN,)h(-ARC,)477 -4777 y(-NCP,)g(-GLS,)f(-MER,)g(or)i(-AIT\))0 4890 y(cube)f(-)g(3D)g -(data)g(cube)g(of)g(the)g(appropriate)d(datatype)0 5002 -y(curaddr)i(-)h(\(integer\))f(starting)f(address)h(\(in)h(bytes\))f(of) -h(the)g(CHDU)0 5115 y(current)f(-)h(\(integer\))f(if)h(not)g(equal)f -(to)h(0,)g(copy)g(the)g(current)f(HDU)0 5228 y(datacode)g(-)h -(\(integer\))e(symbolic)h(code)g(of)i(the)f(binary)f(table)g(column)g -(datatype)0 5341 y(dataok)g(-)i(\(integer\))d(was)i(the)g(data)f(unit)h -(verification)d(successful)h(\(=1\))i(or)430 5454 y(not)f(\(=)i(-1\).) -94 b(Equals)46 b(zero)h(if)g(the)g(DATASUM)f(keyword)f(is)j(not)f -(present.)0 5567 y(datasum)f(-)h(\(double)f(precision\))f(32-bit)h(1's) -h(complement)e(checksum)h(for)h(the)f(data)h(unit)0 5680 -y(datatype)f(-)h(\(character\))e(datatype)g(\(format\))h(of)h(the)g -(binary)f(table)g(column)1882 5942 y Fi(123)p eop end -%%Page: 124 130 -TeXDict begin 124 129 bop 0 299 a Fi(124)1779 b Fg(CHAPTER)30 -b(11.)112 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)0 555 y -Fe(datestr)94 b(-)47 b(\(string\))f(FITS)g(date/time)f(string:)h -('YYYY-MM-DDThh:mm:ss.ddd')o(,)525 668 y('YYYY-MM-dd',)e(or)j -('dd/mm/yy')0 781 y(day)g(-)g(\(integer\))f(current)f(day)i(of)h(the)e -(month)0 894 y(dblval)g(-)i(\(double)d(precision\))g(fractional)g(part) -i(of)g(the)g(keyword)f(value)0 1007 y(decimals)g(-)h(\(integer\))e -(number)h(of)i(decimal)d(places)h(to)i(be)f(displayed)0 -1120 y(dim1)g(-)g(\(integer\))e(actual)h(size)h(of)g(the)g(first)g -(dimension)e(of)i(the)g(image)f(or)h(cube)g(array)0 1233 -y(dim2)g(-)g(\(integer\))e(actual)h(size)h(of)g(the)g(second)f -(dimension)g(of)h(the)g(cube)f(array)0 1346 y(dispwidth)f(-)j -(\(integer\))d(-)i(the)g(display)f(width)h(\(length)e(of)j(string\))d -(for)i(a)h(column)0 1458 y(dtype)e(-)i(\(character\))d(datatype)g(of)i -(the)g(keyword)f(\('C',)g('L',)h('I',)94 b(or)48 b('F'\))764 -1571 y(C)f(=)h(character)d(string)764 1684 y(L)i(=)h(logical)764 -1797 y(I)f(=)h(integer)764 1910 y(F)f(=)h(floating)d(point)h(number)0 -2023 y(errmsg)g(-)i(\(character*80\))43 b(oldest)k(error)f(message)g -(on)h(the)g(internal)e(stack)0 2136 y(errtext)h(-)h(\(character*30\))d -(descriptive)h(error)h(message)g(corresponding)e(to)j(error)g(number)0 -2249 y(casesen)f(-)h(\(logical\))f(true)g(if)h(column)f(name)h -(matching)f(is)h(case)f(sensitive)0 2362 y(exact)g(-)i(\(logical\))d -(do)i(the)g(strings)f(match)g(exactly,)g(or)h(were)g(wildcards)e(used?) -0 2475 y(exclist)94 b(\(character)45 b(array\))h(list)g(of)h(names)g -(to)g(be)g(excluded)f(from)g(search)0 2588 y(exists)142 -b(-)47 b(flag)g(indicating)e(whether)g(the)i(file)g(or)g(compressed)e -(file)i(exists)f(on)h(disk)0 2700 y(extend)f(-)i(\(logical\))d(true)h -(if)i(there)e(may)h(be)g(extensions)e(following)g(the)i(primary)f(data) -0 2813 y(extname)g(-)h(\(character\))e(value)h(of)i(the)e(EXTNAME)g -(keyword)g(\(if)h(not)g(blank\))0 2926 y(fbit)g(-)g(\(integer\))e -(first)i(bit)g(in)g(the)g(field)f(to)h(be)g(read)g(or)g(written)0 -3039 y(felem)f(-)i(\(integer\))d(first)h(pixel)h(of)g(the)g(element)f -(vector)g(\(ignored)f(for)i(ASCII)g(tables\))0 3152 y(filename)f(-)h -(\(character\))e(name)h(of)i(the)e(FITS)h(file)0 3265 -y(flagvals)f(-)h(\(logical)f(array\))g(True)g(if)h(corresponding)e -(data)h(element)g(is)h(undefined)0 3378 y(following)e(-)j(\(integer\))d -(if)i(not)g(equal)f(to)i(0,)f(copy)f(all)h(following)f(HDUs)g(in)h(the) -g(input)g(file)0 3491 y(fparm)f(-)i(\(integer\))d(sequence)h(number)g -(of)h(the)g(first)f(group)h(parameter)e(to)i(read)g(or)g(write)0 -3604 y(fpixel)f(-)i(\(integer\))d(the)i(first)f(pixel)g(position)0 -3717 y(fpixels)g(-)h(\(integer)f(array\))g(the)h(first)f(included)g -(pixel)g(in)h(each)g(dimension)0 3830 y(frow)g(-)g(\(integer\))e -(beginning)h(row)h(number)f(\(first)g(row)h(of)g(table)f(=)i(1\))0 -3942 y(frowll)e(-)i(\(integer*8\))c(beginning)i(row)g(number)h(\(first) -f(row)h(of)g(table)f(=)i(1\))0 4055 y(gcount)e(-)i(\(integer\))d(value) -h(of)h(the)g(GCOUNT)f(keyword)g(\(usually)g(=)h(1\))0 -4168 y(group)f(-)i(\(integer\))d(sequence)h(number)g(of)h(the)g(data)f -(group)h(\(=0)g(for)g(non-grouped)d(data\))0 4281 y(hdtype)i(-)i -(\(integer\))d(header)h(record)g(type:)g(-1=delete;)93 -b(0=append)46 b(or)h(replace;)907 4394 y(1=append;)e(2=this)h(is)h(the) -g(END)g(keyword)0 4507 y(hduok)f(-)i(\(integer\))d(was)i(the)g(HDU)g -(verification)d(successful)h(\(=1\))i(or)430 4620 y(not)f(\(=)i(-1\).) -94 b(Equals)46 b(zero)h(if)g(the)g(CHECKSUM)e(keyword)h(is)h(not)g -(present.)0 4733 y(hdusum)f(-)i(\(double)d(precision\))g(32)j(bit)e -(1's)h(complement)e(checksum)h(for)h(the)g(entire)f(CHDU)0 -4846 y(hdutype)g(-)h(\(integer\))f(type)g(of)h(HDU:)g(0)g(=)h(primary)e -(array)g(or)h(IMAGE,)f(1)i(=)f(ASCII)g(table,)907 4959 -y(2)g(=)h(binary)e(table,)g(-1)h(=)h(any)e(HDU)h(type)g(or)g(unknown)f -(type)0 5072 y(history)g(-)h(\(character\))e(the)i(HISTORY)f(keyword)g -(comment)f(string)0 5185 y(hour)i(-)g(\(integer\))e(hour)i(from)g(0)g -(-)h(23)0 5297 y(image)e(-)i(2D)f(image)f(of)i(the)e(appropriate)f -(datatype)0 5410 y(inclist)94 b(\(character)45 b(array\))h(list)g(of)h -(names)g(to)g(be)g(included)f(in)h(search)0 5523 y(incs)g(-)g -(\(integer)f(array\))g(sampling)f(interval)h(for)h(pixels)f(in)h(each)g -(FITS)f(dimension)0 5636 y(intval)g(-)i(\(integer\))d(integer)h(part)g -(of)h(the)g(keyword)f(value)p eop end -%%Page: 125 131 -TeXDict begin 125 130 bop 3764 299 a Fi(125)0 555 y Fe(iounit)46 -b(-)i(\(integer\))d(value)h(of)h(an)h(unused)e(I/O)h(unit)f(number)0 -668 y(iunit)g(-)i(\(integer\))d(logical)h(unit)h(number)f(associated)f -(with)h(the)h(input)g(FITS)f(file,)h(1-300)0 781 y(key_no)f(-)i -(\(integer\))d(sequence)g(number)h(\(starting)g(with)g(1\))i(of)f(the)g -(keyword)e(record)0 894 y(keylength)g(-)j(\(integer\))d(length)h(of)h -(the)g(keyword)f(name)0 1007 y(keyroot)g(-)h(\(character\))e(root)i -(string)f(for)h(the)g(keyword)e(name)0 1120 y(keysadd)h(-\(integer\))f -(number)h(of)h(new)g(keyword)f(records)g(which)g(can)h(fit)g(in)g(the)g -(CHU)0 1233 y(keysexist)e(-)j(\(integer\))d(number)h(of)h(existing)f -(keyword)g(records)f(in)j(the)f(CHU)0 1346 y(keyval)f(-)i(value)e(of)h -(the)g(keyword)f(in)h(the)g(appropriate)e(datatype)0 -1458 y(keyvals)h(-)h(\(array\))f(value)g(of)i(the)f(keywords)e(in)i -(the)g(appropriate)e(datatype)0 1571 y(keyword)h(-)h(\(character*8\))d -(name)j(of)g(a)h(keyword)0 1684 y(lray)f(-)g(\(logical)f(array\))g -(array)g(of)h(logical)f(values)g(corresponding)e(to)k(the)e(bit)h -(array)0 1797 y(lpixels)f(-)h(\(integer)f(array\))g(the)h(last)f -(included)g(pixel)g(in)i(each)e(dimension)0 1910 y(match)g(-)i -(\(logical\))d(do)i(the)g(2)h(strings)d(match?)0 2023 -y(maxdim)h(-)i(\(integer\))d(dimensioned)g(size)h(of)h(the)g(NAXES,)f -(TTYPE,)g(TFORM)h(or)g(TUNIT)f(arrays)0 2136 y(max_keys)g(-)h -(\(integer\))e(maximum)h(number)g(of)h(keywords)f(to)h(search)f(for)0 -2249 y(minute)g(-)i(\(integer\))d(minute)h(of)h(an)g(hour)g(\(0)g(-)h -(59\))0 2362 y(month)e(-)i(\(integer\))d(current)h(month)g(of)h(the)g -(year)g(\(1)g(-)h(12\))0 2475 y(morekeys)e(-)h(\(integer\))e(will)i -(leave)f(space)h(in)g(the)g(header)f(for)h(this)f(many)h(more)g -(keywords)0 2588 y(naxes)f(-)i(\(integer)d(array\))h(size)h(of)g(each)g -(dimension)e(in)i(the)g(FITS)g(array)0 2700 y(naxesll)f(-)h -(\(integer*8)e(array\))h(size)h(of)g(each)g(dimension)e(in)i(the)g -(FITS)g(array)0 2813 y(naxis)f(-)i(\(integer\))d(number)h(of)h -(dimensions)e(in)j(the)e(FITS)h(array)0 2926 y(naxis1)f(-)i -(\(integer\))d(length)h(of)h(the)g(X/first)f(axis)g(of)i(the)f(FITS)f -(array)0 3039 y(naxis2)g(-)i(\(integer\))d(length)h(of)h(the)g -(Y/second)f(axis)g(of)h(the)g(FITS)g(array)0 3152 y(naxis3)f(-)i -(\(integer\))d(length)h(of)h(the)g(Z/third)f(axis)g(of)i(the)f(FITS)f -(array)0 3265 y(nbit)h(-)g(\(integer\))e(number)h(of)i(bits)e(in)h(the) -g(field)g(to)g(read)g(or)g(write)0 3378 y(nchars)f(-)i(\(integer\))d -(number)h(of)h(characters)e(to)i(read)g(and)g(return)0 -3491 y(ncols)f(-)i(\(integer\))d(number)h(of)h(columns)0 -3604 y(nelements)e(-)j(\(integer\))d(number)h(of)h(data)g(elements)e -(to)j(read)e(or)h(write)0 3717 y(nelementsll)e(-)i(\(integer*8\))e -(number)h(of)h(data)g(elements)e(to)j(read)e(or)h(write)0 -3830 y(nexc)142 b(\(integer\))93 b(number)46 b(of)h(names)g(in)g(the)g -(exclusion)e(list)i(\(may)f(=)i(0\))0 3942 y(nhdu)f(-)g(\(integer\))e -(absolute)h(number)g(of)h(the)g(HDU)g(\(1st)g(HDU)g(=)g(1\))0 -4055 y(ninc)142 b(\(integer\))93 b(number)46 b(of)h(names)g(in)g(the)g -(inclusion)e(list)0 4168 y(nmove)h(-)i(\(integer\))d(number)h(of)h -(HDUs)g(to)g(move)g(\(+)g(or)g(-\),)g(relative)f(to)h(current)f -(position)0 4281 y(nfound)g(-)i(\(integer\))d(number)h(of)h(keywords)f -(found)g(\(highest)g(keyword)f(number\))0 4394 y(no_keys)h(-)h -(\(integer\))f(number)g(of)h(keywords)e(to)j(write)e(in)h(the)g -(sequence)0 4507 y(nparm)f(-)i(\(integer\))d(number)h(of)h(group)g -(parameters)e(to)i(read)g(or)g(write)0 4620 y(nrows)f(-)i(\(integer\))d -(number)h(of)h(rows)g(in)g(the)g(table)0 4733 y(nrowsll)f(-)h -(\(integer*8\))e(number)h(of)h(rows)g(in)g(the)g(table)0 -4846 y(nullval)f(-)h(value)g(to)g(represent)e(undefined)g(pixels,)h(of) -h(the)g(appropriate)e(datatype)0 4959 y(nextaddr)h(-)h(\(integer\))e -(starting)h(address)g(\(in)h(bytes\))f(of)h(the)g(HDU)g(following)e -(the)i(CHDU)0 5072 y(offset)f(-)i(\(integer\))d(byte)h(offset)h(in)g -(the)g(heap)f(to)h(the)g(first)g(element)f(of)h(the)g(array)0 -5185 y(offsetll)f(-)h(\(integer*8\))e(byte)h(offset)g(in)i(the)f(heap)f -(to)h(the)g(first)g(element)e(of)j(the)f(array)0 5297 -y(oldkey)f(-)i(\(character\))c(old)j(name)g(of)g(keyword)f(to)h(be)g -(modified)0 5410 y(ounit)f(-)i(\(integer\))d(logical)h(unit)h(number)f -(associated)f(with)h(the)h(output)f(FITS)h(file)g(1-300)0 -5523 y(pcount)f(-)i(\(integer\))d(value)h(of)h(the)g(PCOUNT)f(keyword)g -(\(usually)g(=)h(0\))0 5636 y(previous)f(-)h(\(integer\))e(if)i(not)g -(equal)g(to)g(0,)g(copy)g(all)g(previous)e(HDUs)i(in)g(the)g(input)f -(file)p eop end -%%Page: 126 132 -TeXDict begin 126 131 bop 0 299 a Fi(126)1779 b Fg(CHAPTER)30 -b(11.)112 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)0 555 y -Fe(repeat)46 b(-)i(\(integer\))d(length)h(of)h(element)f(vector)g -(\(e.g.)g(12J\);)h(ignored)f(for)g(ASCII)h(table)0 668 -y(rot)g(-)g(\(double)f(precision\))f(celestial)g(coordinate)g(rotation) -h(angle)g(\(degrees\))0 781 y(rowlen)g(-)i(\(integer\))d(length)h(of)h -(a)h(table)e(row,)h(in)g(characters)e(or)i(bytes)0 894 -y(rowlenll)f(-)h(\(integer*8\))e(length)h(of)h(a)g(table)g(row,)f(in)i -(characters)d(or)i(bytes)0 1007 y(rowlist)f(-)h(\(integer)f(array\))g -(list)h(of)g(row)g(numbers)e(to)j(be)f(deleted)f(in)h(increasing)e -(order)0 1120 y(rownum)h(-)i(\(integer\))d(number)h(of)h(the)g(row)g -(\(first)f(row)h(=)g(1\))0 1233 y(rowrange-)e(\(string\))h(list)g(of)i -(rows)e(or)h(row)g(ranges)f(to)i(be)f(deleted)0 1346 -y(rwmode)f(-)i(\(integer\))d(file)h(access)h(mode:)f(0)h(=)h(readonly,) -d(1)j(=)f(readwrite)0 1458 y(second)142 b(\(double\)-)45 -b(second)h(within)g(minute)g(\(0)h(-)h(60.9999999999\))c(\(leap)i -(second!\))0 1571 y(seq_no)g(-)i(\(integer\))d(the)i(sequence)e(number) -h(to)i(append)e(to)h(the)g(keyword)f(root)g(name)0 1684 -y(simple)g(-)i(\(logical\))d(does)h(the)h(FITS)g(file)g(conform)e(to)j -(all)f(the)f(FITS)h(standards)0 1797 y(snull)f(-)i(\(character\))d -(value)h(used)h(to)g(represent)e(undefined)g(values)h(in)i(ASCII)e -(table)0 1910 y(space)g(-)i(\(integer\))d(number)h(of)h(blank)g(spaces) -f(to)h(leave)f(between)g(ASCII)h(table)f(columns)0 2023 -y(startchar)f(-)j(\(integer\))d(first)h(character)g(in)h(the)g(row)g -(to)g(be)g(read)0 2136 y(startno)f(-)h(\(integer\))f(value)g(of)h(the)g -(first)f(keyword)g(sequence)g(number)g(\(usually)f(1\))0 -2249 y(status)h(-)i(\(integer\))d(returned)g(error)i(status)f(code)g -(\(0)i(=)f(OK\))0 2362 y(str_template)d(\(character\))h(template)h -(string)g(to)h(be)g(matched)f(to)h(reference)e(string)0 -2475 y(stream)h(-)i(\(character\))c(output)i(stream)g(for)h(the)g -(report:)f(either)g('STDOUT')g(or)h('STDERR')0 2588 y(string)f(-)i -(\(character\))c(character)i(string)0 2700 y(sum)h(-)g(\(double)f -(precision\))f(32)i(bit)g(unsigned)f(checksum)f(value)0 -2813 y(tbcol)h(-)i(\(integer)d(array\))h(column)h(number)f(of)h(the)g -(first)f(character)f(in)j(the)e(field\(s\))0 2926 y(tdisp)g(-)i -(\(character\))d(Fortran)g(type)i(display)f(format)g(for)h(the)g(table) -f(column)0 3039 y(template-\(character\))c(template)k(string)g(for)h(a) -g(FITS)g(header)f(record)0 3152 y(tfields)g(-)h(\(integer\))f(number)g -(of)h(fields)f(\(columns\))f(in)i(the)g(table)0 3265 -y(tform)f(-)i(\(character)d(array\))h(format)g(of)h(the)g(column\(s\);) -e(allowed)h(values)g(are:)430 3378 y(For)g(ASCII)h(tables:)93 -b(Iw,)47 b(Aw,)g(Fww.dd,)f(Eww.dd,)g(or)h(Dww.dd)430 -3491 y(For)f(binary)h(tables:)e(rL,)i(rX,)g(rB,)g(rI,)g(rJ,)g(rA,)g -(rAw,)f(rE,)h(rD,)g(rC,)g(rM)430 3604 y(where)f('w'=width)f(of)i(the)g -(field,)f('d'=no.)g(of)h(decimals,)f('r'=repeat)f(count)430 -3717 y(Note)h(that)h(the)g('rAw')f(form)h(is)g(non-standard)d -(extension)i(to)h(the)430 3830 y(TFORM)f(keyword)g(syntax)g(that)g(is)i -(not)f(specifically)d(defined)i(in)h(the)430 3942 y(Binary)f(Tables)g -(definition)f(document.)0 4055 y(theap)h(-)i(\(integer\))d(zero)i -(indexed)f(byte)g(offset)g(of)h(starting)f(address)g(of)h(the)g(heap) -430 4168 y(relative)e(to)i(the)g(beginning)e(of)j(the)f(binary)f(table) -g(data)0 4281 y(tnull)g(-)i(\(integer\))d(value)h(used)h(to)g -(represent)f(undefined)f(values)h(in)h(binary)f(table)0 -4394 y(tnullll)g(-)h(\(integer*8\))e(value)h(used)h(to)g(represent)e -(undefined)h(values)g(in)h(binary)f(table)0 4507 y(ttype)g(-)i -(\(character)d(array\))h(label)g(for)h(table)g(column\(s\))0 -4620 y(tscal)f(-)i(\(double)e(precision\))f(scaling)g(factor)i(for)f -(table)h(column)0 4733 y(tunit)f(-)i(\(character)d(array\))h(physical)f -(unit)i(for)g(table)f(column\(s\))0 4846 y(tzero)g(-)i(\(double)e -(precision\))f(scaling)g(zero)i(point)f(for)h(table)g(column)0 -4959 y(unit)94 b(-)48 b(\(integer\))d(logical)h(unit)h(number)f -(associated)f(with)h(the)h(FITS)g(file)f(\(1-300\))0 -5072 y(units)g(-)i(\(character\))d(the)h(keyword)g(units)h(string)f -(\(e.g.,)g('km/s'\))0 5185 y(value)g(-)i(\(character\))d(the)h(keyword) -g(value)h(string)0 5297 y(values)f(-)i(array)e(of)h(data)g(values)f(of) -h(the)g(appropriate)e(datatype)0 5410 y(varidat)h(-)h(\(integer\))f -(size)g(in)h(bytes)g(of)g(the)g('variable)e(length)h(data)h(area')525 -5523 y(following)e(the)i(binary)f(table)h(data)f(\(usually)g(=)h(0\))0 -5636 y(version)f(-)h(\(real\))f(current)g(revision)g(number)g(of)h(the) -g(library)p eop end -%%Page: 127 133 -TeXDict begin 127 132 bop 3764 299 a Fi(127)0 555 y Fe(width)46 -b(-)i(\(integer\))d(width)h(of)i(the)f(character)e(string)h(field)0 -668 y(xcol)h(-)g(\(integer\))e(number)h(of)i(the)f(column)f(containing) -f(the)i(X)g(coordinate)e(values)0 781 y(xinc)i(-)g(\(double)f -(precision\))f(X)i(axis)g(coordinate)e(increment)g(at)i(reference)f -(pixel)g(\(deg\))0 894 y(xpix)h(-)g(\(double)f(precision\))f(X)i(axis)g -(pixel)f(location)0 1007 y(xpos)h(-)g(\(double)f(precision\))f(X)i -(axis)g(celestial)e(coordinate)g(\(usually)h(RA\))h(\(deg\))0 -1120 y(xrpix)f(-)i(\(double)e(precision\))f(X)i(axis)g(reference)e -(pixel)h(array)h(location)0 1233 y(xrval)f(-)i(\(double)e(precision\))f -(X)i(axis)g(coordinate)e(value)h(at)h(the)g(reference)e(pixel)i -(\(deg\))0 1346 y(ycol)g(-)g(\(integer\))e(number)h(of)i(the)f(column)f -(containing)f(the)i(X)g(coordinate)e(values)0 1458 y(year)i(-)g -(\(integer\))e(last)i(2)g(digits)g(of)g(the)g(year)f(\(00)h(-)h(99\))0 -1571 y(yinc)f(-)g(\(double)f(precision\))f(Y)i(axis)g(coordinate)e -(increment)g(at)i(reference)f(pixel)g(\(deg\))0 1684 -y(ypix)h(-)g(\(double)f(precision\))f(y)i(axis)g(pixel)f(location)0 -1797 y(ypos)h(-)g(\(double)f(precision\))f(y)i(axis)g(celestial)e -(coordinate)g(\(usually)h(DEC\))g(\(deg\))0 1910 y(yrpix)g(-)i -(\(double)e(precision\))f(Y)i(axis)g(reference)e(pixel)h(array)h -(location)0 2023 y(yrval)f(-)i(\(double)e(precision\))f(Y)i(axis)g -(coordinate)e(value)h(at)h(the)g(reference)e(pixel)i(\(deg\))p -eop end -%%Page: 128 134 -TeXDict begin 128 133 bop 0 299 a Fi(128)1779 b Fg(CHAPTER)30 -b(11.)112 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)p eop end -%%Page: 129 135 -TeXDict begin 129 134 bop 0 1225 a Ff(Chapter)65 b(12)0 -1687 y Fl(FITSIO)76 b(Error)h(Status)h(Co)6 b(des)0 2180 -y Fe(Status)46 b(codes)g(in)i(the)f(range)f(-99)h(to)g(-999)94 -b(and)47 b(1)h(to)f(999)g(are)g(reserved)e(for)i(future)0 -2293 y(FITSIO)f(use.)95 2518 y(0)96 b(OK,)47 b(no)g(error)0 -2631 y(101)95 b(input)46 b(and)h(output)f(files)g(are)h(the)g(same)0 -2744 y(103)95 b(too)47 b(many)f(FITS)h(files)f(open)h(at)g(once;)f(all) -h(internal)f(buffers)g(full)0 2857 y(104)95 b(error)46 -b(opening)g(existing)f(file)0 2970 y(105)95 b(error)46 -b(creating)g(new)g(FITS)h(file;)f(\(does)h(a)g(file)g(with)g(this)f -(name)h(already)f(exist?\))0 3083 y(106)95 b(error)46 -b(writing)g(record)g(to)h(FITS)g(file)0 3196 y(107)95 -b(end-of-file)44 b(encountered)h(while)h(reading)g(record)g(from)h -(FITS)g(file)0 3309 y(108)95 b(error)46 b(reading)g(record)g(from)h -(file)0 3422 y(110)95 b(error)46 b(closing)g(FITS)g(file)0 -3535 y(111)95 b(internal)45 b(array)i(dimensions)e(exceeded)0 -3648 y(112)95 b(Cannot)46 b(modify)g(file)g(with)h(readonly)f(access)0 -3760 y(113)95 b(Could)46 b(not)h(allocate)e(memory)0 -3873 y(114)95 b(illegal)45 b(logical)h(unit)h(number;)f(must)g(be)i -(between)d(1)j(-)f(300,)g(inclusive)0 3986 y(115)95 b(NULL)46 -b(input)h(pointer)e(to)j(routine)0 4099 y(116)95 b(error)46 -b(seeking)g(position)f(in)j(file)0 4325 y(121)95 b(invalid)45 -b(URL)i(prefix)f(on)i(file)e(name)0 4438 y(122)95 b(tried)46 -b(to)h(register)f(too)h(many)f(IO)h(drivers)0 4551 y(123)95 -b(driver)46 b(initialization)e(failed)0 4664 y(124)95 -b(matching)45 b(driver)h(is)h(not)g(registered)0 4777 -y(125)95 b(failed)46 b(to)h(parse)f(input)h(file)f(URL)0 -4890 y(126)95 b(parse)46 b(error)g(in)i(range)e(list)0 -5115 y(151)95 b(bad)47 b(argument)e(in)i(shared)f(memory)g(driver)0 -5228 y(152)95 b(null)46 b(pointer)g(passed)g(as)h(an)h(argument)0 -5341 y(153)95 b(no)47 b(more)f(free)h(shared)f(memory)g(handles)0 -5454 y(154)95 b(shared)46 b(memory)g(driver)g(is)h(not)g(initialized)0 -5567 y(155)95 b(IPC)47 b(error)f(returned)f(by)j(a)f(system)f(call)0 -5680 y(156)95 b(no)47 b(memory)f(in)h(shared)f(memory)g(driver)1882 -5942 y Fi(129)p eop end -%%Page: 130 136 -TeXDict begin 130 135 bop 0 299 a Fi(130)1613 b Fg(CHAPTER)30 -b(12.)112 b(FITSIO)30 b(ERR)m(OR)g(ST)-8 b(A)g(TUS)30 -b(CODES)0 555 y Fe(157)95 b(resource)45 b(deadlock)h(would)g(occur)0 -668 y(158)95 b(attempt)45 b(to)j(open/create)c(lock)j(file)g(failed)0 -781 y(159)95 b(shared)46 b(memory)g(block)g(cannot)g(be)h(resized)f(at) -h(the)g(moment)0 1120 y(201)95 b(header)46 b(not)h(empty;)f(can't)g -(write)g(required)g(keywords)0 1233 y(202)95 b(specified)45 -b(keyword)h(name)g(was)h(not)g(found)g(in)g(the)g(header)0 -1346 y(203)95 b(specified)45 b(header)h(record)g(number)g(is)h(out)g -(of)g(bounds)0 1458 y(204)95 b(keyword)45 b(value)i(field)f(is)h(blank) -0 1571 y(205)95 b(keyword)45 b(value)i(string)f(is)h(missing)f(the)h -(closing)f(quote)g(character)0 1684 y(206)95 b(illegal)45 -b(indexed)h(keyword)g(name)h(\(e.g.)f('TFORM1000'\))0 -1797 y(207)95 b(illegal)45 b(character)h(in)h(keyword)f(name)g(or)i -(header)e(record)0 1910 y(208)95 b(keyword)45 b(does)i(not)g(have)g -(expected)e(name.)i(Keyword)e(out)i(of)g(sequence?)0 -2023 y(209)95 b(keyword)45 b(does)i(not)g(have)g(expected)e(integer)h -(value)0 2136 y(210)95 b(could)46 b(not)h(find)g(the)f(required)g(END)h -(header)f(keyword)0 2249 y(211)95 b(illegal)45 b(BITPIX)i(keyword)e -(value)0 2362 y(212)95 b(illegal)45 b(NAXIS)i(keyword)f(value)0 -2475 y(213)95 b(illegal)45 b(NAXISn)i(keyword)e(value:)h(must)h(be)g(0) -h(or)f(positive)e(integer)0 2588 y(214)95 b(illegal)45 -b(PCOUNT)i(keyword)e(value)0 2700 y(215)95 b(illegal)45 -b(GCOUNT)i(keyword)e(value)0 2813 y(216)95 b(illegal)45 -b(TFIELDS)h(keyword)g(value)0 2926 y(217)95 b(negative)45 -b(ASCII)i(or)g(binary)f(table)g(width)h(value)f(\(NAXIS1\))0 -3039 y(218)95 b(negative)45 b(number)h(of)h(rows)g(in)g(ASCII)g(or)g -(binary)f(table)g(\(NAXIS2\))0 3152 y(219)95 b(column)46 -b(name)g(\(TTYPE)g(keyword\))g(not)h(found)0 3265 y(220)95 -b(illegal)45 b(SIMPLE)i(keyword)e(value)0 3378 y(221)95 -b(could)46 b(not)h(find)g(the)f(required)g(SIMPLE)g(header)g(keyword)0 -3491 y(222)95 b(could)46 b(not)h(find)g(the)f(required)g(BITPIX)g -(header)g(keyword)0 3604 y(223)95 b(could)46 b(not)h(find)g(the)f -(required)g(NAXIS)g(header)g(keyword)0 3717 y(224)95 -b(could)46 b(not)h(find)g(all)f(the)h(required)f(NAXISn)g(keywords)g -(in)h(the)g(header)0 3830 y(225)95 b(could)46 b(not)h(find)g(the)f -(required)g(XTENSION)g(header)g(keyword)0 3942 y(226)95 -b(the)47 b(CHDU)f(is)h(not)g(an)g(ASCII)g(table)f(extension)0 -4055 y(227)95 b(the)47 b(CHDU)f(is)h(not)g(a)h(binary)e(table)g -(extension)0 4168 y(228)95 b(could)46 b(not)h(find)g(the)f(required)g -(PCOUNT)g(header)g(keyword)0 4281 y(229)95 b(could)46 -b(not)h(find)g(the)f(required)g(GCOUNT)g(header)g(keyword)0 -4394 y(230)95 b(could)46 b(not)h(find)g(the)f(required)g(TFIELDS)g -(header)g(keyword)0 4507 y(231)95 b(could)46 b(not)h(find)g(all)f(the)h -(required)f(TBCOLn)g(keywords)g(in)h(the)g(header)0 4620 -y(232)95 b(could)46 b(not)h(find)g(all)f(the)h(required)f(TFORMn)g -(keywords)g(in)h(the)g(header)0 4733 y(233)95 b(the)47 -b(CHDU)f(is)h(not)g(an)g(IMAGE)g(extension)0 4846 y(234)95 -b(illegal)45 b(TBCOL)i(keyword)f(value;)g(out)h(of)g(range)0 -4959 y(235)95 b(this)46 b(operation)g(only)g(allowed)g(for)h(ASCII)f -(or)h(BINARY)g(table)f(extension)0 5072 y(236)95 b(column)46 -b(is)h(too)g(wide)f(to)i(fit)f(within)f(the)h(specified)e(width)h(of)h -(the)g(ASCII)g(table)0 5185 y(237)95 b(the)47 b(specified)e(column)h -(name)h(template)e(matched)h(more)h(than)f(one)h(column)f(name)0 -5297 y(241)95 b(binary)46 b(table)g(row)h(width)f(is)i(not)e(equal)h -(to)g(the)g(sum)g(of)g(the)g(field)f(widths)0 5410 y(251)95 -b(unrecognizable)44 b(type)i(of)h(FITS)g(extension)0 -5523 y(252)95 b(unrecognizable)44 b(FITS)i(record)0 5636 -y(253)95 b(END)47 b(keyword)e(contains)h(non-blank)f(characters)g(in)i -(columns)f(9-80)p eop end -%%Page: 131 137 -TeXDict begin 131 136 bop 3764 299 a Fi(131)0 555 y Fe(254)95 -b(Header)46 b(fill)g(area)h(contains)f(non-blank)f(characters)0 -668 y(255)95 b(Data)46 b(fill)h(area)g(contains)e(non-blank)g(on)j -(non-zero)d(values)0 781 y(261)95 b(unable)46 b(to)h(parse)f(the)h -(TFORM)g(keyword)e(value)i(string)0 894 y(262)95 b(unrecognizable)44 -b(TFORM)i(datatype)f(code)0 1007 y(263)95 b(illegal)45 -b(TDIMn)i(keyword)f(value)0 1233 y(301)95 b(illegal)45 -b(HDU)i(number;)f(less)h(than)f(1)i(or)f(greater)f(than)h(internal)e -(buffer)h(size)0 1346 y(302)95 b(column)46 b(number)g(out)h(of)g(range) -f(\(1)h(-)h(999\))0 1458 y(304)95 b(attempt)45 b(to)j(move)e(to)h -(negative)f(file)h(record)f(number)0 1571 y(306)95 b(attempted)45 -b(to)i(read)g(or)g(write)f(a)i(negative)d(number)h(of)i(bytes)e(in)h -(the)g(FITS)g(file)0 1684 y(307)95 b(illegal)45 b(starting)h(row)h -(number)f(for)h(table)f(read)h(or)g(write)f(operation)0 -1797 y(308)95 b(illegal)45 b(starting)h(element)g(number)g(for)h(table) -f(read)h(or)g(write)f(operation)0 1910 y(309)95 b(attempted)45 -b(to)i(read)g(or)g(write)f(character)g(string)g(in)h(non-character)d -(table)i(column)0 2023 y(310)95 b(attempted)45 b(to)i(read)g(or)g -(write)f(logical)g(value)g(in)i(non-logical)c(table)j(column)0 -2136 y(311)95 b(illegal)45 b(ASCII)i(table)f(TFORM)h(format)f(code)g -(for)h(attempted)e(operation)0 2249 y(312)95 b(illegal)45 -b(binary)i(table)f(TFORM)g(format)g(code)h(for)g(attempted)e(operation) -0 2362 y(314)95 b(value)46 b(for)h(undefined)e(pixels)h(has)h(not)g -(been)g(defined)0 2475 y(317)95 b(attempted)45 b(to)i(read)g(or)g -(write)f(descriptor)f(in)i(a)h(non-descriptor)c(field)0 -2588 y(320)95 b(number)46 b(of)h(array)f(dimensions)f(out)i(of)g(range) -0 2700 y(321)95 b(first)46 b(pixel)g(number)g(is)i(greater)d(than)i -(the)g(last)g(pixel)f(number)0 2813 y(322)95 b(attempt)45 -b(to)j(set)f(BSCALE)f(or)h(TSCALn)f(scaling)g(parameter)f(=)i(0)0 -2926 y(323)95 b(illegal)45 b(axis)i(length)f(less)h(than)f(1)0 -3152 y(340)h(NOT_GROUP_TABLE)d(340)142 b(Grouping)45 -b(function)h(error)0 3265 y(341)h(HDU_ALREADY_MEMBER)0 -3378 y(342)g(MEMBER_NOT_FOUND)0 3491 y(343)g(GROUP_NOT_FOUND)0 -3604 y(344)g(BAD_GROUP_ID)0 3717 y(345)g(TOO_MANY_HDUS_TRACKED)0 -3830 y(346)g(HDU_ALREADY_TRACKED)0 3942 y(347)g(BAD_OPTION)0 -4055 y(348)g(IDENTICAL_POINTERS)0 4168 y(349)g(BAD_GROUP_ATTACH)0 -4281 y(350)g(BAD_GROUP_DETACH)0 4507 y(360)g(NGP_NO_MEMORY)665 -b(malloc)46 b(failed)0 4620 y(361)h(NGP_READ_ERR)713 -b(read)46 b(error)h(from)f(file)0 4733 y(362)h(NGP_NUL_PTR)761 -b(null)46 b(pointer)g(passed)g(as)h(an)g(argument.)1575 -4846 y(Passing)f(null)g(pointer)g(as)h(a)h(name)f(of)1575 -4959 y(template)f(file)g(raises)g(this)h(error)0 5072 -y(363)g(NGP_EMPTY_CURLINE)473 b(line)46 b(read)h(seems)f(to)h(be)h -(empty)e(\(used)1575 5185 y(internally\))0 5297 y(364)h -(NGP_UNREAD_QUEUE_FULL)281 b(cannot)46 b(unread)g(more)g(then)h(1)g -(line)g(\(or)g(single)1575 5410 y(line)g(twice\))0 5523 -y(365)g(NGP_INC_NESTING)569 b(too)46 b(deep)h(include)f(file)h(nesting) -e(\(infinite)1575 5636 y(loop,)h(template)g(includes)f(itself)i(?\))p -eop end -%%Page: 132 138 -TeXDict begin 132 137 bop 0 299 a Fi(132)1613 b Fg(CHAPTER)30 -b(12.)112 b(FITSIO)30 b(ERR)m(OR)g(ST)-8 b(A)g(TUS)30 -b(CODES)0 555 y Fe(366)47 b(NGP_ERR_FOPEN)665 b(fopen\(\))45 -b(failed,)h(cannot)g(open)h(template)e(file)0 668 y(367)i(NGP_EOF)953 -b(end)46 b(of)i(file)e(encountered)f(and)i(not)g(expected)0 -781 y(368)g(NGP_BAD_ARG)761 b(bad)46 b(arguments)g(passed.)g(Usually)f -(means)1575 894 y(internal)h(parser)g(error.)g(Should)g(not)h(happen)0 -1007 y(369)g(NGP_TOKEN_NOT_EXPECT)329 b(token)46 b(not)h(expected)e -(here)0 1233 y(401)95 b(error)46 b(attempting)f(to)i(convert)f(an)h -(integer)f(to)h(a)h(formatted)d(character)g(string)0 -1346 y(402)95 b(error)46 b(attempting)f(to)i(convert)f(a)h(real)g -(value)f(to)i(a)f(formatted)e(character)h(string)0 1458 -y(403)95 b(cannot)46 b(convert)g(a)h(quoted)f(string)g(keyword)g(to)h -(an)g(integer)0 1571 y(404)95 b(attempted)45 b(to)i(read)g(a)g -(non-logical)e(keyword)h(value)g(as)h(a)h(logical)e(value)0 -1684 y(405)95 b(cannot)46 b(convert)g(a)h(quoted)f(string)g(keyword)g -(to)h(a)h(real)e(value)0 1797 y(406)95 b(cannot)46 b(convert)g(a)h -(quoted)f(string)g(keyword)g(to)h(a)h(double)e(precision)f(value)0 -1910 y(407)95 b(error)46 b(attempting)f(to)i(read)g(character)e(string) -h(as)h(an)h(integer)0 2023 y(408)95 b(error)46 b(attempting)f(to)i -(read)g(character)e(string)h(as)h(a)h(real)e(value)0 -2136 y(409)95 b(error)46 b(attempting)f(to)i(read)g(character)e(string) -h(as)h(a)h(double)e(precision)f(value)0 2249 y(410)95 -b(bad)47 b(keyword)e(datatype)h(code)0 2362 y(411)95 -b(illegal)45 b(number)i(of)g(decimal)f(places)g(while)g(formatting)f -(floating)h(point)g(value)0 2475 y(412)95 b(numerical)45 -b(overflow)g(during)i(implicit)e(datatype)h(conversion)0 -2588 y(413)95 b(error)46 b(compressing)f(image)0 2700 -y(414)95 b(error)46 b(uncompressing)e(image)0 2813 y(420)95 -b(error)46 b(in)h(date)g(or)g(time)g(conversion)0 3039 -y(431)95 b(syntax)46 b(error)g(in)h(parser)f(expression)0 -3152 y(432)95 b(expression)45 b(did)i(not)f(evaluate)g(to)h(desired)f -(type)0 3265 y(433)95 b(vector)46 b(result)g(too)h(large)f(to)h(return) -f(in)i(array)0 3378 y(434)95 b(data)46 b(parser)g(failed)g(not)h(sent)g -(an)g(out)g(column)0 3491 y(435)95 b(bad)47 b(data)f(encounter)f(while) -i(parsing)f(column)0 3604 y(436)95 b(parse)46 b(error:)g(output)g(file) -h(not)g(of)g(proper)f(type)0 3830 y(501)95 b(celestial)45 -b(angle)h(too)h(large)g(for)f(projection)0 3942 y(502)95 -b(bad)47 b(celestial)e(coordinate)g(or)i(pixel)f(value)0 -4055 y(503)95 b(error)46 b(in)h(celestial)e(coordinate)g(calculation)0 -4168 y(504)95 b(unsupported)44 b(type)j(of)g(celestial)e(projection)0 -4281 y(505)95 b(required)45 b(celestial)g(coordinate)g(keywords)h(not)h -(found)0 4394 y(506)95 b(approximate)44 b(wcs)j(keyword)f(values)g -(were)h(returned)p eop end -%%Trailer - -userdict /end-hook known{end-hook}if -%%EOF diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.tex b/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.tex deleted file mode 100644 index 4ceeeb96c..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.tex +++ /dev/null @@ -1,7705 +0,0 @@ -\documentclass[11pt]{book} -\input{html.sty} -\htmladdtonavigation - {\begin{rawhtml} - FITSIO Home - \end{rawhtml}} -%\oddsidemargin=0.25in -\oddsidemargin=0.00in -\evensidemargin=0.00in -\textwidth=6.5in -%\topmargin=0.0in -\textheight=8.75in -\parindent=0cm -\parskip=0.2cm -\begin{document} -\pagenumbering{roman} - -\begin{titlepage} -\normalsize -\vspace*{4.6cm} -\begin{center} -{\Huge \bf FITSIO User's Guide}\\ -\end{center} -\medskip -\medskip -\begin{center} -{\LARGE \bf A Subroutine Interface to FITS Format Files}\\ -\end{center} -\begin{center} -{\LARGE \bf for Fortran Programmers}\\ -\end{center} -\medskip -\medskip -\begin{center} -{\Large Version 3.0\\} -\end{center} -\bigskip -\vskip 2.5cm -\begin{center} -{HEASARC\\ -Code 662\\ -Goddard Space Flight Center\\ -Greenbelt, MD 20771\\ -USA} -\end{center} - -\vfill -\bigskip -\begin{center} -{\Large April 2016\\} -\end{center} -\vfill -\end{titlepage} - -\clearpage - -\tableofcontents - -\chapter{Introduction } -\pagenumbering{arabic} - -This document describes the Fortran-callable subroutine interface that -is provided as part of the CFITSIO library (which is written in ANSI -C). This is a companion document to the CFITSIO User's Guide which -should be consulted for further information about the underlying -CFITSIO library. In the remainder of this document, the terms FITSIO -and CFITSIO are interchangeable and refer to the same library. - -FITSIO/CFITSIO is a machine-independent library of routines for reading -and writing data files in the FITS (Flexible Image Transport System) -data format. It can also read IRAF format image files and raw binary -data arrays by converting them on the fly into a virtual FITS format -file. This library was written to provide a powerful yet simple -interface for accessing FITS files which will run on most commonly used -computers and workstations. FITSIO supports all the features described -in the official definition of the FITS format and can read and -write all the currently defined types of extensions, including ASCII -tables (TABLE), Binary tables (BINTABLE) and IMAGE extensions. The -FITSIO subroutines insulate the programmer from having to deal with the -complicated formatting details in the FITS file, however, it is assumed -that users have a general knowledge about the structure and usage of -FITS files. - -The CFITSIO package was initially developed by the HEASARC (High Energy -Astrophysics Science Archive Research Center) at the NASA Goddard Space -Flight Center to convert various existing and newly acquired -astronomical data sets into FITS format and to further analyze data -already in FITS format. New features continue to be added to CFITSIO -in large part due to contributions of ideas or actual code from users -of the package. The Integral Science Data Center in Switzerland, and -the XMM/ESTEC project in The Netherlands made especially significant -contributions that resulted in many of the new features that appeared -in v2.0 of CFITSIO. - -The latest version of the CFITSIO source code, documentation, and -example programs are available on the World-Wide Web or via anonymous -ftp from: - -\begin{verbatim} - http://heasarc.gsfc.nasa.gov/fitsio - ftp://legacy.gsfc.nasa.gov/software/fitsio/c -\end{verbatim} -\newpage -Any questions, bug reports, or suggested enhancements related to the CFITSIO -package should be sent to the FTOOLS Help Desk at the HEASARC: - -\begin{verbatim} - http://heasarc.gsfc.nasa.gov/cgi-bin/ftoolshelp -\end{verbatim} - -This User's Guide assumes that readers already have a general -understanding of the definition and structure of FITS format files. -Further information about FITS formats is available from the FITS Support -Office at {\tt http://fits.gsfc.nasa.gov}. In particular, the -'FITS Standard' gives the authoritative definition of the FITS data -format. Other documents available at that Web site -provide additional historical background -and practical advice on using FITS files. - -The HEASARC also provides a very sophisticated FITS file analysis -program called `Fv' which can be used to display and edit the contents -of any FITS file as well as construct new FITS files from scratch. -Fv is freely available for -most Unix platforms, Mac PCs, and Windows PCs. -CFITSIO users may also be interested in the FTOOLS package of programs -that can be used to manipulate and analyze FITS format files. -Fv and FTOOLS are available from their respective Web sites at: - -\begin{verbatim} - http://fv.gsfc.nasa.gov - http://heasarc.gsfc.nasa.gov/ftools -\end{verbatim} - - -\chapter{ Creating FITSIO/CFITSIO } - - -\section{Building the Library} - -To use the FITSIO subroutines one must first build the CFITSIO library, -which requires a C compiler. gcc is ideal, or most other ANSI-C -compilers will also work. The CFITSIO code is contained in about 40 C -source files (*.c) and header files (*.h). On VAX/VMS systems 2 -assembly-code files (vmsieeed.mar and vmsieeer.mar) are also needed. - -The Fortran interface subroutines to the C CFITSIO routines are located -in the f77\_wrap1.c, through f77\_wrap4.c files. These are relatively simple -'wrappers' that translate the arguments in the Fortran subroutine into -the appropriate format for the corresponding C routine. This -translation is performed transparently to the user by a set of C macros -located in the cfortran.h file. Unfortunately cfortran.h does not -support every combination of C and Fortran compilers so the Fortran -interface is not supported on all platforms. (see further notes below). - -A standard combination of C and Fortran compilers will be assumed by -default, but one may also specify a particular Fortran compiler by -doing: - -\begin{verbatim} - > setenv CFLAGS -DcompilerName=1 -\end{verbatim} -(where 'compilerName' is the name of the compiler) before running -the configure command. The currently recognized compiler -names are: - -\begin{verbatim} - g77Fortran - IBMR2Fortran - CLIPPERFortran - pgiFortran - NAGf90Fortran - f2cFortran - hpuxFortran - apolloFortran - sunFortran - CRAYFortran - mipsFortran - DECFortran - vmsFortran - CONVEXFortran - PowerStationFortran - AbsoftUNIXFortran - AbsoftProFortran - SXFortran -\end{verbatim} -Alternatively, one may edit the CFLAGS line in the Makefile to add the -'-DcompilerName' flag after running the './configure' command. - -The CFITSIO library is built on Unix systems by typing: - -\begin{verbatim} - > ./configure [--prefix=/target/installation/path] - [--enable-sse2] [--enable-ssse3] - > make (or 'make shared') - > make install (this step is optional) -\end{verbatim} -at the operating system prompt. The configure command customizes the -Makefile for the particular system, then the `make' command compiles the -source files and builds the library. Type `./configure' and not simply -`configure' to ensure that the configure script in the current directory -is run and not some other system-wide configure script. The optional -'prefix' argument to configure gives the path to the directory where -the CFITSIO library and include files should be installed via the later -'make install' command. For example, - -\begin{verbatim} - > ./configure --prefix=/usr1/local -\end{verbatim} -will cause the 'make install' command to copy the CFITSIO libcfitsio file -to /usr1/local/lib and the necessary include files to /usr1/local/include -(assuming of course that the process has permission to write to these -directories). - -The optional --enable-sse2 and --enable-ssse3 flags will cause configure to -attempt to build CFITSIO using faster byte-swapping algorithms. -See the "Optimizing Programs" section of this manual for -more information about these options. - -By default, the Makefile will be configured to build the set of Fortran-callable -wrapper routines whose calling sequences are described later in this -document. - -The 'make shared' option builds a shared or dynamic version of the -CFITSIO library. When using the shared library the executable code is -not copied into your program at link time and instead the program -locates the necessary library code at run time, normally through -LD\_LIBRARY\_PATH or some other method. The advantages of using a shared -library are: - -\begin{verbatim} - 1. Less disk space if you build more than 1 program - 2. Less memory if more than one copy of a program using the shared - library is running at the same time since the system is smart - enough to share copies of the shared library at run time. - 3. Possibly easier maintenance since a new version of the shared - library can be installed without relinking all the software - that uses it (as long as the subroutine names and calling - sequences remain unchanged). - 4. No run-time penalty. -\end{verbatim} -The disadvantages are: - -\begin{verbatim} - 1. More hassle at runtime. You have to either build the programs - specially or have LD_LIBRARY_PATH set right. - 2. There may be a slight start up penalty, depending on where you are - reading the shared library and the program from and if your CPU is - either really slow or really heavily loaded. -\end{verbatim} - -On HP/UX systems, the environment variable CFLAGS should be set -to -Ae before running configure to enable "extended ANSI" features. - -It may not be possible to statically link programs that use CFITSIO on -some platforms (namely, on Solaris 2.6) due to the network drivers -(which provide FTP and HTTP access to FITS files). It is possible to -make both a dynamic and a static version of the CFITSIO library, but -network file access will not be possible using the static version. - -On VAX/VMS and ALPHA/VMS systems the make\_gfloat.com command file may -be executed to build the cfitsio.olb object library using the default -G-floating point option for double variables. The make\_dfloat.com and -make\_ieee.com files may be used instead to build the library with the -other floating point options. Note that the getcwd function that is -used in the group.c module may require that programs using CFITSIO be -linked with the ALPHA\$LIBRARY:VAXCRTL.OLB library. See the example -link line in the next section of this document. - -On Windows IBM-PC type platforms the situation is more complicated -because of the wide variety of Fortran compilers that are available and -because of the inherent complexities of calling the CFITSIO C routines -from Fortran. Two different versions of the CFITSIO dll library are -available, compiled with the Borland C++ compiler and the Microsoft -Visual C++ compiler, respectively, in the files -cfitsiodll\_2xxx\_borland.zip and cfitsiodll\_3xxx\_vcc.zip, where -'3xxx' represents the current release number. Both these dll libraries -contain a set of Fortran wrapper routines which may be compatible with -some, but probably not all, available Fortran compilers. To test if -they are compatible, compile the program testf77.f and try linking to -these dll libraries. If these libraries do not work with a particular -Fortran compiler, then it may be necessary to modify the file -"cfortran.h" to support that particular -combination of C and Fortran compilers, and then rebuild the CFITSIO -dll library. This will require, however, some expertise in -mixed language programming. - -CFITSIO should be compatible with most current ANCI C and C++ compilers: -Cray supercomputers are currently not supported. - - -\section{Testing the Library} - -The CFITSIO library should be tested by building and running -the testprog.c program that is included with the release. -On Unix systems type: - -\begin{verbatim} - % make testprog - % testprog > testprog.lis - % diff testprog.lis testprog.out - % cmp testprog.fit testprog.std -\end{verbatim} - On VMS systems, -(assuming cc is the name of the C compiler command), type: - -\begin{verbatim} - $ cc testprog.c - $ link testprog, cfitsio/lib, alpha$library:vaxcrtl/lib - $ run testprog -\end{verbatim} -The testprog program should produce a FITS file called `testprog.fit' -that is identical to the `testprog.std' FITS file included with this -release. The diagnostic messages (which were piped to the file -testprog.lis in the Unix example) should be identical to the listing -contained in the file testprog.out. The 'diff' and 'cmp' commands -shown above should not report any differences in the files. (There -may be some minor formatting differences, such as the presence or -absence of leading zeros, or 3 digit exponents in numbers, -which can be ignored). - -The Fortran wrappers in CFITSIO may be tested with the testf77 -program. On Unix systems the fortran compilation and link command -may be called 'f77' or 'g77', depending on the system. - -\begin{verbatim} - % f77 -o testf77 testf77.f -L. -lcfitsio -lnsl -lsocket - or - % f77 -f -o testf77 testf77.f -L. -lcfitsio (under SUN O/S) - or - % f77 -o testf77 testf77.f -Wl,-L. -lcfitsio -lm -lnsl -lsocket (HP/UX) - or - % g77 -o testf77 -s testf77.f -lcfitsio -lcc_dynamic -lncurses (Mac OS-X) - - % testf77 > testf77.lis - % diff testf77.lis testf77.out - % cmp testf77.fit testf77.std -\end{verbatim} -On machines running SUN O/S, Fortran programs must be compiled with the -'-f' option to force double precision variables to be aligned on 8-byte -boundaries to make the fortran-declared variables compatible with C. A -similar compiler option may be required on other platforms. Failing to -use this option may cause the program to crash on FITSIO routines that -read or write double precision variables. - -On Windows platforms, linking Fortran programs with a C library -often depends on the particular compilers involved. Some users have -found the following commands work when using the Intel Fortran compiler: - -\begin{verbatim} -ifort /libs.dll cfitsio.lib /MD testf77.f /Gm - -or possibly, - -ifort /libs:dll cfitsio.lib /MD /fpp /extfpp:cfortran.h,fitsio.h - /iface:cvf testf77.f -\end{verbatim} -Also note that on some systems the output listing of the testf77 -program may differ slightly from the testf77.std template if leading -zeros are not printed by default before the decimal point when using F -format. - -A few other utility programs are included with CFITSIO: - -\begin{verbatim} - speed - measures the maximum throughput (in MB per second) - for writing and reading FITS files with CFITSIO - - listhead - lists all the header keywords in any FITS file - - fitscopy - copies any FITS file (especially useful in conjunction - with the CFITSIO's extended input filename syntax) - - cookbook - a sample program that performs common read and - write operations on a FITS file. - - iter_a, iter_b, iter_c - examples of the CFITSIO iterator routine -\end{verbatim} - -The first 4 of these utility programs can be compiled and linked by typing - -\begin{verbatim} - % make program_name -\end{verbatim} - - -\section{Linking Programs with FITSIO} - -When linking applications software with the FITSIO library, several system libraries usually need to be specified on the link comman -Unix systems, the most reliable way to determine what libraries are required -is to type 'make testprog' and see what libraries the configure script has -added. The typical libraries that may need to be added are -lm (the math -library) and -lnsl and -lsocket (needed only for FTP and HTTP file access). -These latter 2 libraries are not needed on VMS and Windows platforms, -because FTP file access is not currently supported on those platforms. - -Note that when upgrading to a newer version of CFITSIO it is usually -necessary to recompile, as well as relink, the programs that use CFITSIO, -because the definitions in fitsio.h often change. - - -\section{Getting Started with FITSIO} - -In order to effectively use the FITSIO library as quickly as possible, -it is recommended that new users follow these steps: - -1. Read the following `FITS Primer' chapter for a brief -overview of the structure of FITS files. This is especially important -for users who have not previously dealt with the FITS table and image -extensions. - -2. Write a simple program to read or write a FITS file using the Basic -Interface routines. - -3. Refer to the cookbook.f program that is included with this release -for examples of routines that perform various common FITS file -operations. - -4. Read Chapters 4 and 5 to become familiar with the conventions and -advanced features of the FITSIO interface. - -5. Scan through the more extensive set of routines that are provided -in the `Advanced Interface'. These routines perform more specialized -functions than are provided by the Basic Interface routines. - - -\section{Example Program} - -The following listing shows an example of how to use the FITSIO -routines in a Fortran program. Refer to the cookbook.f program that -is included with the FITSIO distribution for examples of other -FITS programs. - -\begin{verbatim} - program writeimage - -C Create a FITS primary array containing a 2-D image - - integer status,unit,blocksize,bitpix,naxis,naxes(2) - integer i,j,group,fpixel,nelements,array(300,200) - character filename*80 - logical simple,extend - - status=0 -C Name of the FITS file to be created: - filename='ATESTFILE.FITS' - -C Get an unused Logical Unit Number to use to create the FITS file - call ftgiou(unit,status) - -C create the new empty FITS file - blocksize=1 - call ftinit(unit,filename,blocksize,status) - -C initialize parameters about the FITS image (300 x 200 16-bit integers) - simple=.true. - bitpix=16 - naxis=2 - naxes(1)=300 - naxes(2)=200 - extend=.true. - -C write the required header keywords - call ftphpr(unit,simple,bitpix,naxis,naxes,0,1,extend,status) - -C initialize the values in the image with a linear ramp function - do j=1,naxes(2) - do i=1,naxes(1) - array(i,j)=i+j - end do - end do - -C write the array to the FITS file - group=1 - fpixel=1 - nelements=naxes(1)*naxes(2) - call ftpprj(unit,group,fpixel,nelements,array,status) - -C write another optional keyword to the header - call ftpkyj(unit,'EXPOSURE',1500,'Total Exposure Time',status) - -C close the file and free the unit number - call ftclos(unit, status) - call ftfiou(unit, status) - end -\end{verbatim} - - -\section{Legal Stuff} - -Copyright (Unpublished--all rights reserved under the copyright laws of -the United States), U.S. Government as represented by the Administrator -of the National Aeronautics and Space Administration. No copyright is -claimed in the United States under Title 17, U.S. Code. - -Permission to freely use, copy, modify, and distribute this software -and its documentation without fee is hereby granted, provided that this -copyright notice and disclaimer of warranty appears in all copies. - -DISCLAIMER: - -THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, -EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, -ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY -IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE -DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE -SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY -DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR -CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY -CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, -CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY -PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED -FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR -SERVICES PROVIDED HEREUNDER." - - -\section{Acknowledgments} - -The development of many of the powerful features in CFITSIO was made -possible through collaborations with many people or organizations from -around the world. The following, in particular, have made especially -significant contributions: - -Programmers from the Integral Science Data Center, Switzerland (namely, -Jurek Borkowski, Bruce O'Neel, and Don Jennings), designed the concept -for the plug-in I/O drivers that was introduced with CFITSIO 2.0. The -use of `drivers' greatly simplified the low-level I/O, which in turn -made other new features in CFITSIO (e.g., support for compressed FITS -files and support for IRAF format image files) much easier to -implement. Jurek Borkowski wrote the Shared Memory driver, and Bruce -O'Neel wrote the drivers for accessing FITS files over the network -using the FTP, HTTP, and ROOT protocols. - -The ISDC also provided the template parsing routines (written by Jurek -Borkowski) and the hierarchical grouping routines (written by Don -Jennings). The ISDC DAL (Data Access Layer) routines are layered on -top of CFITSIO and make extensive use of these features. - -Uwe Lammers (XMM/ESA/ESTEC, The Netherlands) designed the -high-performance lexical parsing algorithm that is used to do -on-the-fly filtering of FITS tables. This algorithm essentially -pre-compiles the user-supplied selection expression into a form that -can be rapidly evaluated for each row. Peter Wilson (RSTX, NASA/GSFC) -then wrote the parsing routines used by CFITSIO based on Lammers' -design, combined with other techniques such as the CFITSIO iterator -routine to further enhance the data processing throughput. This effort -also benefited from a much earlier lexical parsing routine that was -developed by Kent Blackburn (NASA/GSFC). More recently, Craig Markwardt -(NASA/GSFC) implemented additional functions (median, average, stddev) -and other enhancements to the lexical parser. - -The CFITSIO iterator function is loosely based on similar ideas -developed for the XMM Data Access Layer. - -Peter Wilson (RSTX, NASA/GSFC) wrote the complete set of -Fortran-callable wrappers for all the CFITSIO routines, which in turn -rely on the CFORTRAN macro developed by Burkhard Burow. - -The syntax used by CFITSIO for filtering or binning input FITS files is -based on ideas developed for the AXAF Science Center Data Model by -Jonathan McDowell, Antonella Fruscione, Aneta Siemiginowska and Bill -Joye. See http://heasarc.gsfc.nasa.gov/docs/journal/axaf7.html for -further description of the AXAF Data Model. - -The file decompression code were taken directly from the gzip (GNU zip) -program developed by Jean-loup Gailly and others. - -Doug Mink, SAO, provided the routines for converting IRAF format -images into FITS format. - -Martin Reinecke (Max Planck Institute, Garching)) provided the modifications to -cfortran.h that are necessary to support 64-bit integer values when calling -C routines from fortran programs. The cfortran.h macros were originally developed -by Burkhard Burow (CERN). - -Julian Taylor (ESO, Garching) provided the fast byte-swapping algorithms -that use the SSE2 and SSSE3 machine instructions available on x86\_64 CPUs. - -In addition, many other people have made valuable contributions to the -development of CFITSIO. These include (with apologies to others that may -have inadvertently been omitted): - -Steve Allen, Carl Akerlof, Keith Arnaud, Morten Krabbe Barfoed, Kent -Blackburn, G Bodammer, Romke Bontekoe, Lucio Chiappetti, Keith Costorf, -Robin Corbet, John Davis, Richard Fink, Ning Gan, Emily Greene, Joe -Harrington, Cheng Ho, Phil Hodge, Jim Ingham, Yoshitaka Ishisaki, Diab -Jerius, Mark Levine, Todd Karakaskian, Edward King, Scott Koch, Claire -Larkin, Rob Managan, Eric Mandel, John Mattox, Carsten Meyer, Emi -Miyata, Stefan Mochnacki, Mike Noble, Oliver Oberdorf, Clive Page, -Arvind Parmar, Jeff Pedelty, Tim Pearson, Maren Purves, Scott Randall, -Chris Rogers, Arnold Rots, Barry Schlesinger, Robin Stebbins, Andrew -Szymkowiak, Allyn Tennant, Peter Teuben, James Theiler, Doug Tody, -Shiro Ueno, Steve Walton, Archie Warnock, Alan Watson, Dan Whipple, Wim -Wimmers, Peter Young, Jianjun Xu, and Nelson Zarate. - - -\chapter{ A FITS Primer } - -This section gives a brief overview of the structure of FITS files. -Users should refer to the documentation available from the FITS Support Office, as -described in the introduction, for more detailed information on FITS -formats. - -FITS was first developed in the late 1970's as a standard data -interchange format between various astronomical observatories. Since -then FITS has become the defacto standard data format supported by most -astronomical data analysis software packages. - -A FITS file consists of one or more Header + Data Units (HDUs), where -the first HDU is called the `Primary HDU', or `Primary Array'. The -primary array contains an N-dimensional array of pixels, such as a 1-D -spectrum, a 2-D image, or a 3-D data cube. Six different primary -datatypes are supported: Unsigned 8-bit bytes, 16, 32, and 64-bit signed -integers, and 32 and 64-bit floating point reals. FITS also has a -convention for storing unsigned integers (see the later -section entitled `Unsigned Integers' for more details). The primary HDU -may also consist of only a header with a null array containing no -data pixels. - -Any number of additional HDUs may follow the primary array; these -additional HDUs are called FITS `extensions'. There are currently 3 -types of extensions defined by the FITS standard: - -\begin{itemize} -\item - Image Extension - a N-dimensional array of pixels, like in a primary array -\item - ASCII Table Extension - rows and columns of data in ASCII character format -\item - Binary Table Extension - rows and columns of data in binary representation -\end{itemize} - -In each case the HDU consists of an ASCII Header Unit followed by an optional -Data Unit. For historical reasons, each Header or Data unit must be an -exact multiple of 2880 8-bit bytes long. Any unused space is padded -with fill characters (ASCII blanks or zeros). - -Each Header Unit consists of any number of 80-character keyword records -or `card images' which have the general form: - -\begin{verbatim} - KEYNAME = value / comment string - NULLKEY = / comment: This keyword has no value -\end{verbatim} -The keyword names may be up to 8 characters long and can only contain -uppercase letters, the digits 0-9, the hyphen, and the underscore -character. The keyword name is (usually) followed by an equals sign and -a space character (= ) in columns 9 - 10 of the record, followed by the -value of the keyword which may be either an integer, a floating point -number, a character string (enclosed in single quotes), or a boolean -value (the letter T or F). A keyword may also have a null or undefined -value if there is no specified value string, as in the second example. - -The last keyword in the header is always the `END' keyword which has no -value or comment fields. There are many rules governing the exact -format of a keyword record (see the FITS Standard) so it is better -to rely on standard interface software like FITSIO to correctly -construct or to parse the keyword records rather than try to deal -directly with the raw FITS formats. - -Each Header Unit begins with a series of required keywords which depend -on the type of HDU. These required keywords specify the size and -format of the following Data Unit. The header may contain other -optional keywords to describe other aspects of the data, such as the -units or scaling values. Other COMMENT or HISTORY keywords are also -frequently added to further document the data file. - -The optional Data Unit immediately follows the last 2880-byte block in -the Header Unit. Some HDUs do not have a Data Unit and only consist of -the Header Unit. - -If there is more than one HDU in the FITS file, then the Header Unit of -the next HDU immediately follows the last 2880-byte block of the -previous Data Unit (or Header Unit if there is no Data Unit). - -The main required keywords in FITS primary arrays or image extensions are: -\begin{itemize} -\item -BITPIX -- defines the datatype of the array: 8, 16, 32, 64, -32, -64 for -unsigned 8--bit byte, 16--bit signed integer, 32--bit signed integer, -64--bit signed integer, -32--bit IEEE floating point, and 64--bit IEEE double precision floating -point, respectively. -\item -NAXIS -- the number of dimensions in the array, usually 0, 1, 2, 3, or 4. -\item -NAXISn -- (n ranges from 1 to NAXIS) defines the size of each dimension. -\end{itemize} - -FITS tables start with the keyword XTENSION = `TABLE' (for ASCII -tables) or XTENSION = `BINTABLE' (for binary tables) and have the -following main keywords: -\begin{itemize} -\item -TFIELDS -- number of fields or columns in the table -\item -NAXIS2 -- number of rows in the table -\item -TTYPEn -- for each column (n ranges from 1 to TFIELDS) gives the -name of the column -\item -TFORMn -- the datatype of the column -\item -TUNITn -- the physical units of the column (optional) -\end{itemize} - -Users should refer to the FITS Support Office at {\tt http://fits.gsfc.nasa.gov} -for further information about the FITS format and related software -packages. - - - -\chapter{FITSIO Conventions and Guidelines } - - -\section{CFITSIO Size Limitations} - -CFITSIO places few restrictions on the size of FITS files that it -reads or writes. There are a few limits, however, which may affect -some extreme cases: - -1. The maximum number of FITS files that may be simultaneously opened by -CFITSIO is set by NMAXFILES, as defined in fitsio2.h. The current default -value is 1000, but this may be increased if necessary. Note that CFITSIO -allocates NIOBUF * 2880 bytes of I/O buffer space for each file that is -opened. The default value of NIOBUF is 40 (defined in fitsio.h), so this -amounts to more than 115K of memory for each opened file (or 115 MB for -1000 opened files). Note that the underlying operating system, may have a -lower limit on the number of files that can be opened simultaneously. - -2. By default, CFITSIO can handle FITS files up to 2.1 GB in size (2**31 -bytes). This file size limit is often imposed by 32-bit operating -systems. More recently, as 64-bit operating systems become more common, an -industry-wide standard (at least on Unix systems) has been developed to -support larger sized files (see http://ftp.sas.com/standards/large.file/). -Starting with version 2.1 of CFITSIO, larger FITS files up to 6 terabytes -in size may be read and written on supported platforms. In order -to support these larger files, CFITSIO must be compiled with the -'-D\_LARGEFILE\_SOURCE' and `-D\_FILE\_OFFSET\_BITS=64' compiler flags. -Some platforms may also require the `-D\_LARGE\_FILES' compiler flag. - This causes the compiler to allocate 8-bytes instead of -4-bytes for the `off\_t' datatype which is used to store file offset -positions. It appears that in most cases it is not necessary to -also include these compiler flags when compiling programs that link to -the CFITSIO library. - -If CFITSIO is compiled with the -D\_LARGEFILE\_SOURCE -and -D\_FILE\_OFFSET\_BITS=64 flags on a -platform that supports large files, then it can read and write FITS -files that contain up to 2**31 2880-byte FITS records, or approximately -6 terabytes in size. It is still required that the value of the NAXISn -and PCOUNT keywords in each extension be within the range of a signed -4-byte integer (max value = 2,147,483,648). Thus, each dimension of an -image (given by the NAXISn keywords), the total width of a table -(NAXIS1 keyword), the number of rows in a table (NAXIS2 keyword), and -the total size of the variable-length array heap in binary tables -(PCOUNT keyword) must be less than this limit. - -Currently, support for large files within CFITSIO has been tested -on the Linux, Solaris, and IBM AIX operating systems. - - -\section{Multiple Access to the Same FITS File} - -CFITSIO supports simultaneous read and write access to multiple HDUs in -the same FITS file. Thus, one can open the same FITS file twice within -a single program and move to 2 different HDUs in the file, and then -read and write data or keywords to the 2 extensions just as if one were -accessing 2 completely separate FITS files. Since in general it is -not possible to physically open the same file twice and then expect to -be able to simultaneously (or in alternating succession) write to 2 -different locations in the file, CFITSIO recognizes when the file to be -opened (in the call to fits\_open\_file) has already been opened and -instead of actually opening the file again, just logically links the -new file to the old file. (This only applies if the file is opened -more than once within the same program, and does not prevent the same -file from being simultaneously opened by more than one program). Then -before CFITSIO reads or writes to either (logical) file, it makes sure -that any modifications made to the other file have been completely -flushed from the internal buffers to the file. Thus, in principle, one -could open a file twice, in one case pointing to the first extension -and in the other pointing to the 2nd extension and then write data to -both extensions, in any order, without danger of corrupting the file, -There may be some efficiency penalties in doing this however, since -CFITSIO has to flush all the internal buffers related to one file -before switching to the other, so it would still be prudent to -minimize the number of times one switches back and forth between doing -I/O to different HDUs in the same file. - - -\section{Current Header Data Unit (CHDU)} - -In general, a FITS file can contain multiple Header Data Units, also -called extensions. CFITSIO only operates within one HDU at any given -time, and the currently selected HDU is called the Current Header Data -Unit (CHDU). When a FITS file is first created or opened the CHDU is -automatically defined to be the first HDU (i.e., the primary array). -CFITSIO routines are provided to move to and open any other existing -HDU within the FITS file or to append or insert a new HDU in the FITS -file which then becomes the CHDU. - - -\section{Subroutine Names} - -All FITSIO subroutine names begin with the letters 'ft' to distinguish -them from other subroutines and are 5 or 6 characters long. Users should -not name their own subroutines beginning with 'ft' to avoid conflicts. -(The SPP interface routines all begin with 'fs'). Subroutines which read -or get information from the FITS file have names beginning with -'ftg...'. Subroutines which write or put information into the FITS file -have names beginning with 'ftp...'. - - -\section{Subroutine Families and Datatypes} - -Many of the subroutines come in families which differ only in the -datatype of the associated parameter(s) . The datatype of these -subroutines is indicated by the last letter of the subroutine name -(e.g., 'j' in 'ftpkyj') as follows: - -\begin{verbatim} - x - bit - b - character*1 (unsigned byte) - i - short integer (I*2) - j - integer (I*4, 32-bit integer) - k - long long integer (I*8, 64-bit integer) - e - real exponential floating point (R*4) - f - real fixed-format floating point (R*4) - d - double precision real floating-point (R*8) - g - double precision fixed-format floating point (R*8) - c - complex reals (pairs of R*4 values) - m - double precision complex (pairs of R*8 values) - l - logical (L*4) - s - character string -\end{verbatim} - -When dealing with the FITS byte datatype, it is important to remember -that the raw values (before any scaling by the BSCALE and BZERO, or -TSCALn and TZEROn keyword values) in byte arrays (BITPIX = 8) or byte -columns (TFORMn = 'B') are interpreted as unsigned bytes with values -ranging from 0 to 255. Some Fortran compilers support a non-standard -byte datatype such as INTEGER*1, LOGICAL*1, or BYTE, which can sometimes -be used instead of CHARACTER*1 variables. Many machines permit passing a -numeric datatype (such as INTEGER*1) to the FITSIO subroutines which are -expecting a CHARACTER*1 datatype, but this technically violates the -Fortran-77 standard and is not supported on all machines (e.g., on a VAX/VMS -machine one must use the VAX-specific \%DESCR function). - -One feature of the CFITSIO routines is that they can operate on a `X' -(bit) column in a binary table as though it were a `B' (byte) column. -For example a `11X' datatype column can be interpreted the same as a -`2B' column (i.e., 2 unsigned 8-bit bytes). In some instances, it can -be more efficient to read and write whole bytes at a time, rather than -reading or writing each individual bit. - -The double precision complex datatype is not a standard Fortran-77 -datatype. If a particular Fortran compiler does not directly support -this datatype, then one may instead pass an array of pairs of double -precision values to these subroutines. The first value in each pair -is the real part, and the second is the imaginary part. - - -\section{Implicit Data Type Conversion} - -The FITSIO routines that read and write numerical data can perform -implicit data type conversion. This means that the data type of the -variable or array in the program does not need to be the same as the -data type of the value in the FITS file. Data type conversion is -supported for numerical and string data types (if the string contains a -valid number enclosed in quotes) when reading a FITS header keyword -value and for numeric values when reading or writing values in the -primary array or a table column. CFITSIO returns status = -NUM\_OVERFLOW if the converted data value exceeds the range of the -output data type. Implicit data type conversion is not supported -within binary tables for string, logical, complex, or double complex -data types. - -In addition, any table column may be read as if it contained string values. -In the case of numeric columns the returned string will be formatted -using the TDISPn display format if it exists. - - -\section{Data Scaling} - -When reading numerical data values in the primary array or a -table column, the values will be scaled automatically by the BSCALE and -BZERO (or TSCALn and TZEROn) header keyword values if they are -present in the header. The scaled data that is returned to the reading -program will have - -\begin{verbatim} - output value = (FITS value) * BSCALE + BZERO -\end{verbatim} -(a corresponding formula using TSCALn and TZEROn is used when reading -from table columns). In the case of integer output values the floating -point scaled value is truncated to an integer (not rounded to the -nearest integer). The ftpscl and fttscl subroutines may be used to -override the scaling parameters defined in the header (e.g., to turn -off the scaling so that the program can read the raw unscaled values -from the FITS file). - -When writing numerical data to the primary array or to a table -column the data values will generally be automatically inversely scaled -by the value of the BSCALE and BZERO (or TSCALn and TZEROn) header -keyword values if they they exist in the header. These keywords must -have been written to the header before any data is written for them to -have any effect. Otherwise, one may use the ftpscl and fttscl -subroutines to define or override the scaling keywords in the header -(e.g., to turn off the scaling so that the program can write the raw -unscaled values into the FITS file). If scaling is performed, the -inverse scaled output value that is written into the FITS file will -have - -\begin{verbatim} - FITS value = ((input value) - BZERO) / BSCALE -\end{verbatim} -(a corresponding formula using TSCALn and TZEROn is used when -writing to table columns). Rounding to the nearest integer, rather -than truncation, is performed when writing integer datatypes to the -FITS file. - - -\section{Error Status Values and the Error Message Stack} - -The last parameter in nearly every FITSIO subroutine is the error -status value which is both an input and an output parameter. A -returned positive value for this parameter indicates an error was -detected. A listing of all the FITSIO status code values is given at -the end of this document. - -The FITSIO library uses an `inherited status' convention for the status -parameter which means that if a subroutine is called with a positive -input value of the status parameter, then the subroutine will exit -immediately without changing the value of the status parameter. Thus, -if one passes the status value returned from each FITSIO routine as -input to the next FITSIO subroutine, then whenever an error is detected -all further FITSIO processing will cease. This convention can simplify -the error checking in application programs because it is not necessary -to check the value of the status parameter after every single FITSIO -subroutine call. If a program contains a sequence of several FITSIO -calls, one can just check the status value after the last call. Since -the returned status values are generally distinctive, it should be -possible to determine which subroutine originally returned the error -status. - -FITSIO also maintains an internal stack of error messages (80-character -maximum length) which in many cases provide a more detailed explanation -of the cause of the error than is provided by the error status number -alone. It is recommended that the error message stack be printed out -whenever a program detects a FITSIO error. To do this, call the FTGMSG -routine repeatedly to get the successive messages on the stack. When the -stack is empty FTGMSG will return a blank string. Note that this is a -`First In -- First Out' stack, so the oldest error message is returned -first by ftgmsg. - - -\section{Variable-Length Array Facility in Binary Tables} - -FITSIO provides easy-to-use support for reading and writing data in -variable length fields of a binary table. The variable length columns -have TFORMn keyword values of the form `1Pt(len)' or `1Qt(len)' where `t' is the -datatype code (e.g., I, J, E, D, etc.) and `len' is an integer -specifying the maximum length of the vector in the table. If the value -of `len' is not specified when the table is created (e.g., if the TFORM -keyword value is simply specified as '1PE' instead of '1PE(400) ), then -FITSIO will automatically scan the table when it is closed to -determine the maximum length of the vector and will append this value -to the TFORMn value. - -The same routines which read and write data in an ordinary fixed length -binary table extension are also used for variable length fields, -however, the subroutine parameters take on a slightly different -interpretation as described below. - -All the data in a variable length field is written into an area called -the `heap' which follows the main fixed-length FITS binary table. The -size of the heap, in bytes, is specified with the PCOUNT keyword in the -FITS header. When creating a new binary table, the initial value of -PCOUNT should usually be set to zero. FITSIO will recompute the size -of the heap as the data is written and will automatically update the -PCOUNT keyword value when the table is closed. When writing variable -length data to a table, CFITSIO will automatically extend the size -of the heap area if necessary, so that any following HDUs do not -get overwritten. - -By default the heap data area starts immediately after the last row of -the fixed-length table. This default starting location may be -overridden by the THEAP keyword, but this is not recommended. -If additional rows of data are added to the table, CFITSIO will -automatically shift the the heap down to make room for the new -rows, but it is obviously be more efficient to initially -create the table with the necessary number of blank rows, so that -the heap does not needed to be constantly moved. - -When writing to a variable length field, the entire array of values for -a given row of the table must be written with a single call to FTPCLx. -The total length of the array is calculated from (NELEM+FELEM-1). One -cannot append more elements to an existing field at a later time; any -attempt to do so will simply overwrite all the data which was previously -written. Note also that the new data will be written to a new area of -the heap and the heap space used by the previous write cannot be -reclaimed. For this reason it is advised that each row of a variable -length field only be written once. An exception to this general rule -occurs when setting elements of an array as undefined. One must first -write a dummy value into the array with FTPCLx, and then call FTPCLU to -flag the desired elements as undefined. (Do not use the FTPCNx family -of routines with variable length fields). Note that the rows of a table, -whether fixed or variable length, do not have to be written -consecutively and may be written in any order. - -When writing to a variable length ASCII character field (e.g., TFORM = -'1PA') only a single character string written. FTPCLS writes the whole -length of the input string (minus any trailing blank characters), thus -the NELEM and FELEM parameters are ignored. If the input string is -completely blank then FITSIO will write one blank character to the FITS -file. Similarly, FTGCVS and FTGCFS read the entire string (truncated -to the width of the character string argument in the subroutine call) -and also ignore the NELEM and FELEM parameters. - -The FTPDES subroutine is useful in situations where multiple rows of a -variable length column have the identical array of values. One can -simply write the array once for the first row, and then use FTPDES to -write the same descriptor values into the other rows (use the FTGDES -routine to read the first descriptor value); all the rows will then -point to the same storage location thus saving disk space. - -When reading from a variable length array field one can only read as -many elements as actually exist in that row of the table; reading does -not automatically continue with the next row of the table as occurs -when reading an ordinary fixed length table field. Attempts to read -more than this will cause an error status to be returned. One can -determine the number of elements in each row of a variable column with -the FTGDES subroutine. - - -\section{Support for IEEE Special Values} - -The ANSI/IEEE-754 floating-point number standard defines certain -special values that are used to represent such quantities as -Not-a-Number (NaN), denormalized, underflow, overflow, and infinity. -(See the Appendix in the FITS standard or the FITS User's -Guide for a list of these values). The FITSIO subroutines that read -floating point data in FITS files recognize these IEEE special values -and by default interpret the overflow and infinity values as being -equivalent to a NaN, and convert the underflow and denormalized values -into zeros. In some cases programmers may want access to the raw IEEE -values, without any modification by FITSIO. This can be done by -calling the FTGPVx or FTGCVx routines while specifying 0.0 as the value -of the NULLVAL parameter. This will force FITSIO to simply pass the -IEEE values through to the application program, without any -modification. This does not work for double precision values on -VAX/VMS machines, however, where there is no easy way to bypass the -default interpretation of the IEEE special values. This is also not -supported when reading floating-point images that have been compressed -with the FITS tiled image compression convention that is discussed in -section 5.6; the pixels values in tile compressed images are -represented by scaled integers, and a reserved integer value -(not a NaN) is used to represent undefined pixels. - - - -\section{When the Final Size of the FITS HDU is Unknown} - -It is not required to know the total size of a FITS data array or table -before beginning to write the data to the FITS file. In the case of -the primary array or an image extension, one should initially create -the array with the size of the highest dimension (largest NAXISn -keyword) set to a dummy value, such as 1. Then after all the data have -been written and the true dimensions are known, then the NAXISn value -should be updated using the fits\_ update\_key routine before moving to -another extension or closing the FITS file. - -When writing to FITS tables, CFITSIO automatically keeps track of the -highest row number that is written to, and will increase the size of -the table if necessary. CFITSIO will also automatically insert space -in the FITS file if necessary, to ensure that the data 'heap', if it -exists, and/or any additional HDUs that follow the table do not get -overwritten as new rows are written to the table. - -As a general rule it is best to specify the initial number of rows = 0 -when the table is created, then let CFITSIO keep track of the number of -rows that are actually written. The application program should not -manually update the number of rows in the table (as given by the NAXIS2 -keyword) since CFITSIO does this automatically. If a table is -initially created with more than zero rows, then this will usually be -considered as the minimum size of the table, even if fewer rows are -actually written to the table. Thus, if a table is initially created -with NAXIS2 = 20, and CFITSIO only writes 10 rows of data before -closing the table, then NAXIS2 will remain equal to 20. If however, 30 -rows of data are written to this table, then NAXIS2 will be increased -from 20 to 30. The one exception to this automatic updating of the -NAXIS2 keyword is if the application program directly modifies the -value of NAXIS2 (up or down) itself just before closing the table. In this -case, CFITSIO does not update NAXIS2 again, since it assumes that the -application program must have had a good reason for changing the value -directly. This is not recommended, however, and is only provided for -backward compatibility with software that initially creates a table -with a large number of rows, than decreases the NAXIS2 value to the -actual smaller value just before closing the table. - - -\section{Local FITS Conventions supported by FITSIO} - -CFITSIO supports several local FITS conventions which are not -defined in the official FITS standard and which are not -necessarily recognized or supported by other FITS software packages. -Programmers should be cautious about using these features, especially -if the FITS files that are produced are expected to be processed by -other software systems which do not use the CFITSIO interface. - - -\subsection{Support for Long String Keyword Values.} - -The length of a standard FITS string keyword is limited to 68 -characters because it must fit entirely within a single FITS header -keyword record. In some instances it is necessary to encode strings -longer than this limit, so FITSIO supports a local convention in which -the string value is continued over multiple keywords. This -continuation convention uses an ampersand character at the end of each -substring to indicate that it is continued on the next keyword, and the -continuation keywords all have the name CONTINUE without an equal sign -in column 9. The string value may be continued in this way over as many -additional CONTINUE keywords as is required. The following lines -illustrate this continuation convention which is used in the value of -the STRKEY keyword: - -\begin{verbatim} -LONGSTRN= 'OGIP 1.0' / The OGIP Long String Convention may be used. -STRKEY = 'This is a very long string keyword&' / Optional Comment -CONTINUE ' value that is continued over 3 keywords in the & ' -CONTINUE 'FITS header.' / This is another optional comment. -\end{verbatim} -It is recommended that the LONGSTRN keyword, as shown -here, always be included in any HDU that uses this longstring -convention. A subroutine called FTPLSW -has been provided in CFITSIO to write this keyword if it does not -already exist. - -This long string convention is supported by the following FITSIO -subroutines that deal with string-valued keywords: - -\begin{verbatim} - ftgkys - read a string keyword - ftpkls - write (append) a string keyword - ftikls - insert a string keyword - ftmkls - modify the value of an existing string keyword - ftukls - update an existing keyword, or write a new keyword - ftdkey - delete a keyword -\end{verbatim} -These routines will transparently read, write, or delete a long string -value in the FITS file, so programmers in general do not have to be -concerned about the details of the convention that is used to encode -the long string in the FITS header. When reading a long string, one -must ensure that the character string parameter used in these -subroutine calls has been declared long enough to hold the entire -string, otherwise the returned string value will be truncated. - -Note that the more commonly used FITSIO subroutine to write string -valued keywords (FTPKYS) does NOT support this long string convention -and only supports strings up to 68 characters in length. This has been -done deliberately to prevent programs from inadvertently writing -keywords using this non-standard convention without the explicit intent -of the programmer or user. The FTPKLS subroutine must be called -instead to write long strings. This routine can also be used to write -ordinary string values less than 68 characters in length. - - -\subsection{Arrays of Fixed-Length Strings in Binary Tables} - -CFITSIO supports 2 ways to specify that a character column in a binary -table contains an array of fixed-length strings. The first way, which -is officially supported by the FITS Standard document, uses the TDIMn keyword. -For example, if TFORMn = '60A' and TDIMn = '(12,5)' then that -column will be interpreted as containing an array of 5 strings, each 12 -characters long. - -FITSIO also supports a -local convention for the format of the TFORMn keyword value of the form -'rAw' where 'r' is an integer specifying the total width in characters -of the column, and 'w' is an integer specifying the (fixed) length of -an individual unit string within the vector. For example, TFORM1 = -'120A10' would indicate that the binary table column is 120 characters -wide and consists of 12 10-character length strings. This convention -is recognized by the FITSIO subroutines that read or write strings in -binary tables. The Binary Table definition document specifies that -other optional characters may follow the datatype code in the TFORM -keyword, so this local convention is in compliance with the -FITS standard, although other FITS readers are not required to -recognize this convention. - - -\subsection{Keyword Units Strings} - -One deficiency of the current FITS Standard is that it does not define -a specific convention for recording the physical units of a keyword -value. The TUNITn keyword can be used to specify the physical units of -the values in a table column, but there is no analogous convention for -keyword values. The comment field of the keyword is often used for -this purpose, but the units are usually not specified in a well defined -format that FITS readers can easily recognize and extract. - -To solve this deficiency, FITSIO uses a local convention in which the -keyword units are enclosed in square brackets as the first token in the -keyword comment field; more specifically, the opening square bracket -immediately follows the slash '/' comment field delimiter and a single -space character. The following examples illustrate keywords that use -this convention: - - -\begin{verbatim} -EXPOSURE= 1800.0 / [s] elapsed exposure time -V_HELIO = 16.23 / [km s**(-1)] heliocentric velocity -LAMBDA = 5400. / [angstrom] central wavelength -FLUX = 4.9033487787637465E-30 / [J/cm**2/s] average flux -\end{verbatim} - -In general, the units named in the IAU(1988) Style Guide are -recommended, with the main exception that the preferred unit for angle -is 'deg' for degrees. - -The FTPUNT and FTGUNT subroutines in FITSIO write and read, -respectively, the keyword unit strings in an existing keyword. - - -\subsection{HIERARCH Convention for Extended Keyword Names} - -CFITSIO supports the HIERARCH keyword convention which allows keyword -names that are longer then 8 characters and may contain the full range -of printable ASCII text characters. This convention -was developed at the European Southern Observatory (ESO) to support -hierarchical FITS keyword such as: - -\begin{verbatim} -HIERARCH ESO INS FOCU POS = -0.00002500 / Focus position -\end{verbatim} -Basically, this convention uses the FITS keyword 'HIERARCH' to indicate -that this convention is being used, then the actual keyword name -({\tt'ESO INS FOCU POS'} in this example) begins in column 10 and can -contain any printable ASCII text characters, including spaces. The -equals sign marks the end of the keyword name and is followed by the -usual value and comment fields just as in standard FITS keywords. -Further details of this convention are described at -http://fits.gsfc.nasa.gov/registry/hierarch\_keyword.html -and in Section 4.4 of the ESO Data Interface Control Document that -is linked to from -http://archive.eso.org/cms/tools-documentation/eso-data-interface-control.html. - -This convention allows a much broader range of keyword names -than is allowed by the FITS Standard. Here are more examples -of such keywords: - -\begin{verbatim} -HIERARCH LongKeyword = 47.5 / Keyword has > 8 characters, and mixed case -HIERARCH XTE$TEMP = 98.6 / Keyword contains the '$' character -HIERARCH Earth is a star = F / Keyword contains embedded spaces -\end{verbatim} -CFITSIO will transparently read and write these keywords, so application -programs do not in general need to know anything about the specific -implementation details of the HIERARCH convention. In particular, -application programs do not need to specify the `HIERARCH' part of the -keyword name when reading or writing keywords (although it -may be included if desired). When writing a keyword, CFITSIO first -checks to see if the keyword name is legal as a standard FITS keyword -(no more than 8 characters long and containing only letters, digits, or -a minus sign or underscore). If so it writes it as a standard FITS -keyword, otherwise it uses the hierarch convention to write the -keyword. The maximum keyword name length is 67 characters, which -leaves only 1 space for the value field. A more practical limit is -about 40 characters, which leaves enough room for most keyword values. -CFITSIO returns an error if there is not enough room for both the -keyword name and the keyword value on the 80-character card, except for -string-valued keywords which are simply truncated so that the closing -quote character falls in column 80. In the current implementation, -CFITSIO preserves the case of the letters when writing the keyword -name, but it is case-insensitive when reading or searching for a -keyword. The current implementation allows any ASCII text character -(ASCII 32 to ASCII 126) in the keyword name except for the '=' -character. A space is also required on either side of the equal sign. - - -\section{Optimizing Code for Maximum Processing Speed} - -CFITSIO has been carefully designed to obtain the highest possible -speed when reading and writing FITS files. In order to achieve the -best performance, however, application programmers must be careful to -call the CFITSIO routines appropriately and in an efficient sequence; -inappropriate usage of CFITSIO routines can greatly slow down the -execution speed of a program. - -The maximum possible I/O speed of CFITSIO depends of course on the type -of computer system that it is running on. To get a general idea of what -data I/O speeds are possible on a particular machine, build the speed.c -program that is distributed with CFITSIO (type 'make speed' in the CFITSIO -directory). This diagnostic program measures the speed of writing and reading -back a test FITS image, a binary table, and an ASCII table. - -The following 2 sections provide some background on how CFITSIO -internally manages the data I/O and describes some strategies that may -be used to optimize the processing speed of software that uses -CFITSIO. - - -\subsection{Background Information: How CFITSIO Manages Data I/O} - -Many CFITSIO operations involve transferring only a small number of -bytes to or from the FITS file (e.g, reading a keyword, or writing a -row in a table); it would be very inefficient to physically read or -write such small blocks of data directly in the FITS file on disk, -therefore CFITSIO maintains a set of internal Input--Output (IO) -buffers in RAM memory that each contain one FITS block (2880 bytes) of -data. Whenever CFITSIO needs to access data in the FITS file, it first -transfers the FITS block containing those bytes into one of the IO -buffers in memory. The next time CFITSIO needs to access bytes in the -same block it can then go to the fast IO buffer rather than using a -much slower system disk access routine. The number of available IO -buffers is determined by the NIOBUF parameter (in fitsio2.h) and is -currently set to 40. - -Whenever CFITSIO reads or writes data it first checks to see if that -block of the FITS file is already loaded into one of the IO buffers. -If not, and if there is an empty IO buffer available, then it will load -that block into the IO buffer (when reading a FITS file) or will -initialize a new block (when writing to a FITS file). If all the IO -buffers are already full, it must decide which one to reuse (generally -the one that has been accessed least recently), and flush the contents -back to disk if it has been modified before loading the new block. - -The one major exception to the above process occurs whenever a large -contiguous set of bytes are accessed, as might occur when reading or -writing a FITS image. In this case CFITSIO bypasses the internal IO -buffers and simply reads or writes the desired bytes directly in the -disk file with a single call to a low-level file read or write -routine. The minimum threshold for the number of bytes to read or -write this way is set by the MINDIRECT parameter and is currently set -to 3 FITS blocks = 8640 bytes. This is the most efficient way to read -or write large chunks of data. Note that this fast direct IO process is not -applicable when accessing columns of data in a FITS table because the -bytes are generally not contiguous since they are interleaved by the -other columns of data in the table. This explains why the speed for -accessing FITS tables is generally slower than accessing -FITS images. - -Given this background information, the general strategy for efficiently -accessing FITS files should now be apparent: when dealing with FITS -images, read or write large chunks of data at a time so that the direct -IO mechanism will be invoked; when accessing FITS headers or FITS -tables, on the other hand, once a particular FITS block has been -loading into one of the IO buffers, try to access all the needed -information in that block before it gets flushed out of the IO buffer. -It is important to avoid the situation where the same FITS block is -being read then flushed from a IO buffer multiple times. - -The following section gives more specific suggestions for optimizing -the use of CFITSIO. - - -\subsection{Optimization Strategies} - -1. Because the data in FITS files is always stored in "big-endian" byte order, -where the first byte of numeric values contains the most significant bits and the -last byte contains the least significant bits, CFITSIO must swap the order of the bytes -when reading or writing FITS files when running on little-endian machines (e.g., -Linux and Microsoft Windows operating systems running on PCs with x86 CPUs). - -On fairly new CPUs that support "SSSE3" machine instructions -(e.g., starting with Intel Core 2 CPUs in 2007, and in AMD CPUs -beginning in 2011) significantly faster 4-byte and 8-byte swapping -algorithms are available. These faster byte swapping functions are -not used by default in CFITSIO (because of the potential code -portablility issues), but users can enable them on supported -platforms by adding the appropriate compiler flags (-mssse3 with gcc -or icc on linux) when compiling the swapproc.c source file, which will -allow the compiler to generate code using the SSSE3 instruction set. -A convenient way to do this is to configure the CFITSIO library -with the following command: - -\begin{verbatim} - > ./configure --enable-ssse3 -\end{verbatim} -Note, however, that a binary executable file that is -created using these faster functions will only run on -machines that support the SSSE3 machine instructions. It will -crash on machines that do not support them. - -For faster 2-byte swaps on virtually all x86-64 CPUs (even those that -do not support SSSE3), a variant using only SSE2 instructions exists. -SSE2 is enabled by default on x86\_64 CPUs with 64-bit operating systems -(and is also automatically enabled by the --enable-ssse3 flag). -When running on x86\_64 CPUs with 32-bit operating systems, these faster -2-byte swapping algorithms are not used by default in CFITSIO, but can be -enabled explicitly with: - -\begin{verbatim} -./configure --enable-sse2 -\end{verbatim} -Preliminary testing indicates that these SSSE3 and SSE2 based -byte-swapping algorithms can boost the CFITSIO performance when -reading or writing FITS images by 20\% - 30\% or more. -It is important to note, however, that compiler optimization must be -turned on (e.g., by using the -O1 or -O2 flags in gcc) when building -programs that use these fast byte-swapping algorithms in order -to reap the full benefit of the SSSE3 and SSE2 instructions; without -optimization, the code may actually run slower than when using -more traditional byte-swapping techniques. - -2. When dealing with a FITS primary array or IMAGE extension, it is -more efficient to read or write large chunks of the image at a time -(at least 3 FITS blocks = 8640 bytes) so that the direct IO mechanism -will be used as described in the previous section. Smaller chunks of -data are read or written via the IO buffers, which is somewhat less -efficient because of the extra copy operation and additional -bookkeeping steps that are required. In principle it is more efficient -to read or write as big an array of image pixels at one time as -possible, however, if the array becomes so large that the operating -system cannot store it all in RAM, then the performance may be degraded -because of the increased swapping of virtual memory to disk. - -3. When dealing with FITS tables, the most important efficiency factor -in the software design is to read or write the data in the FITS file in -a single pass through the file. An example of poor program design -would be to read a large, 3-column table by sequentially reading the -entire first column, then going back to read the 2nd column, and -finally the 3rd column; this obviously requires 3 passes through the -file which could triple the execution time of an I/O limited program. -For small tables this is not important, but when reading multi-megabyte -sized tables these inefficiencies can become significant. The more -efficient procedure in this case is to read or write only as many rows -of the table as will fit into the available internal I/O buffers, then -access all the necessary columns of data within that range of rows. -Then after the program is completely finished with the data in those -rows it can move on to the next range of rows that will fit in the -buffers, continuing in this way until the entire file has been -processed. By using this procedure of accessing all the columns of a -table in parallel rather than sequentially, each block of the FITS file -will only be read or written once. - -The optimal number of rows to read or write at one time in a given -table depends on the width of the table row, on the number of I/O -buffers that have been allocated in FITSIO, and also on the number of -other FITS files that are open at the same time (since one I/O buffer -is always reserved for each open FITS file). Fortunately, a FITSIO -routine is available that will return the optimal number of rows for a -given table: call ftgrsz(unit, nrows, status). It is not critical to -use exactly the value of nrows returned by this routine, as long as one -does not exceed it. Using a very small value however can also lead to -poor performance because of the overhead from the larger number of -subroutine calls. - -The optimal number of rows returned by ftgrsz is valid only as long as -the application program is only reading or writing data in the -specified table. Any other calls to access data in the table header -would cause additional blocks of data to be -loaded into the I/O buffers displacing data from the original table, -and should be avoided during the critical period while the table is -being read or written. - -4. Use binary table extensions rather than ASCII table -extensions for better efficiency when dealing with tabular data. The -I/O to ASCII tables is slower because of the overhead in formatting or -parsing the ASCII data fields, and because ASCII tables are about twice -as large as binary tables with the same information content. - -5. Design software so that it reads the FITS header keywords in the -same order in which they occur in the file. When reading keywords, -FITSIO searches forward starting from the position of the last keyword -that was read. If it reaches the end of the header without finding the -keyword, it then goes back to the start of the header and continues the -search down to the position where it started. In practice, as long as -the entire FITS header can fit at one time in the available internal I/O -buffers, then the header keyword access will be very fast and it makes -little difference which order they are accessed. - -6. Avoid the use of scaling (by using the BSCALE and BZERO or TSCAL and -TZERO keywords) in FITS files since the scaling operations add to the -processing time needed to read or write the data. In some cases it may -be more efficient to temporarily turn off the scaling (using ftpscl or -fttscl) and then read or write the raw unscaled values in the FITS -file. - -7. Avoid using the 'implicit datatype conversion' capability in -FITSIO. For instance, when reading a FITS image with BITPIX = -32 -(32-bit floating point pixels), read the data into a single precision -floating point data array in the program. Forcing FITSIO to convert -the data to a different datatype can significantly slow the program. - -8. Where feasible, design FITS binary tables using vector column -elements so that the data are written as a contiguous set of bytes, -rather than as single elements in multiple rows. For example, it is -faster to access the data in a table that contains a single row -and 2 columns with TFORM keywords equal to '10000E' and '10000J', than -it is to access the same amount of data in a table with 10000 rows -which has columns with the TFORM keywords equal to '1E' and '1J'. In -the former case the 10000 floating point values in the first column are -all written in a contiguous block of the file which can be read or -written quickly, whereas in the second case each floating point value -in the first column is interleaved with the integer value in the second -column of the same row so CFITSIO has to explicitly move to the -position of each element to be read or written. - -9. Avoid the use of variable length vector columns in binary tables, -since any reading or writing of these data requires that CFITSIO first -look up or compute the starting address of each row of data in the -heap. In practice, this is probably not a significant efficiency issue. - -10. When copying data from one FITS table to another, it is faster to -transfer the raw bytes instead of reading then writing each column of -the table. The FITSIO subroutines FTGTBS and FTPTBS (for ASCII -tables), and FTGTBB and FTPTBB (for binary tables) will perform -low-level reads or writes of any contiguous range of bytes in a table -extension. These routines can be used to read or write a whole row (or -multiple rows) of a table with a single subroutine call. These -routines are fast because they bypass all the usual data scaling, error -checking and machine dependent data conversion that is normally done by -FITSIO, and they allow the program to write the data to the output file -in exactly the same byte order. For these same reasons, use of these -routines can be somewhat risky because no validation or machine -dependent conversion is performed by these routines. In general these -routines are only recommended for optimizing critical pieces of code -and should only be used by programmers who thoroughly understand the -internal byte structure of the FITS tables they are reading or -writing. - -11. Another strategy for improving the speed of writing a FITS table, -similar to the previous one, is to directly construct the entire byte -stream for a whole table row (or multiple rows) within the application -program and then write it to the FITS file with -ftptbb. This avoids all the overhead normally present -in the column-oriented CFITSIO write routines. This technique should -only be used for critical applications, because it makes the code more -difficult to understand and maintain, and it makes the code more system -dependent (e.g., do the bytes need to be swapped before writing to the -FITS file?). - -12. Finally, external factors such as the type of magnetic disk -controller (SCSI or IDE), the size of the disk cache, the average seek -speed of the disk, the amount of disk fragmentation, and the amount of -RAM available on the system can all have a significant impact on -overall I/O efficiency. For critical applications, a system -administrator should review the proposed system hardware to identify any -potential I/O bottlenecks. - - - -\chapter{ Basic Interface Routines } - -This section defines a basic set of subroutines that can be -used to perform the most common types of read and write operations -on FITS files. New users should start with these subroutines and -then, as needed, explore the more advance routines described in -the following chapter to perform more complex or specialized operations. - -A right arrow symbol ($>$) is used to separate the input parameters from -the output parameters in the definition of each routine. This symbol -is not actually part of the calling sequence. Note that -the status parameter is both an input and an output parameter -and must be initialized = 0 prior to calling the FITSIO subroutines. - -Refer to Chapter 9 for the definition of all the parameters -used by these interface routines. - - -\section{FITSIO Error Status Routines \label{FTVERS}} - - -\begin{description} -\item[1 ] Return the current version number of the fitsio library. - The version number will be incremented with each new - release of CFITSIO. -\end{description} - -\begin{verbatim} - FTVERS( > version) -\end{verbatim} - -\begin{description} -\item[2 ] Return the descriptive text string corresponding to a FITSIO error - status code. The 30-character length string contains a brief - description of the cause of the error. -\end{description} - -\begin{verbatim} - FTGERR(status, > errtext) -\end{verbatim} - -\begin{description} -\item[3 ] Return the top (oldest) 80-character error message from the - internal FITSIO stack of error messages and shift any remaining - messages on the stack up one level. Any FITSIO error will - generate one or more messages on the stack. Call this routine - repeatedly to get each message in sequence. The error stack is empty - when a blank string is returned. -\end{description} - -\begin{verbatim} - FTGMSG( > errmsg) -\end{verbatim} - -\begin{description} -\item[4 ]The FTPMRK routine puts an invisible marker on the - CFITSIO error stack. The FTCMRK routine can then be - used to delete any more recent error messages on the stack, back to - the position of the marker. This preserves any older error messages - on the stack. FTCMSG simply clears the entire error message stack. - These routines are called without any arguments. -\end{description} - -\begin{verbatim} - FTPMRK - FTCMRK - FTCMSG -\end{verbatim} - - -\begin{description} -\item[5 ] Print out the error message corresponding to the input status - value and all the error messages on the FITSIO stack to the specified - file stream (stream can be either the string 'STDOUT' or 'STDERR'). - If the input status value = 0 then this routine does nothing. -\end{description} - -\begin{verbatim} - FTRPRT (stream, > status) -\end{verbatim} - -\begin{description} -\item[6 ] Write an 80-character message to the FITSIO error stack. Application - programs should not normally write to the stack, but there may be - some situations where this is desirable. -\end{description} - -\begin{verbatim} - FTPMSG(errmsg) -\end{verbatim} - - -\section{File I/O Routines} - - -\begin{description} -\item[1 ]Open an existing FITS file with readonly or readwrite access. - This routine always opens the primary array (the first HDU) of - the file, and does not move to a following extension, if one was - specified as part of the filename. Use the FTNOPN routine to - automatically move to the extension. This routine will also - open IRAF images (.imh format files) and raw binary data arrays - with READONLY access by first converting them on the fly into - virtual FITS images. See the `Extended File Name Syntax' chapter - for more details. The FTDKOPN routine simply opens the specified - file without trying to interpret the filename using the extended - filename syntax. -\end{description} - -\begin{verbatim} - FTOPEN(unit,filename,rwmode, > blocksize,status) - FTDKOPN(unit,filename,rwmode, > blocksize,status) -\end{verbatim} - -\begin{description} -\item[2 ]Open an existing FITS file with readonly or readwrite access - and move to a following extension, if one was specified as - part of the filename. (e.g., 'filename.fits+2' or - 'filename.fits[2]' will move to the 3rd HDU in the file). - Note that this routine differs from FTOPEN in that it does not - have the redundant blocksize argument. -\end{description} - -\begin{verbatim} - FTNOPN(unit,filename,rwmode, > status) -\end{verbatim} - -\begin{description} -\item[3 ]Open an existing FITS file with readonly or readwrite access - and then move to the first HDU containing significant data, if a) an HDU - name or number to open was not explicitly specified as part of the - filename, and b) if the FITS file contains a null primary array (i.e., - NAXIS = 0). In this case, it will look for the first IMAGE HDU with - NAXIS > 0, or the first table that does not contain the strings `GTI' - (Good Time Interval) or `OBSTABLE' in the EXTNAME keyword value. FTTOPN - is similar, except it will move to the first significant table HDU - (skipping over any image HDUs) in the file if a specific HDU name - or number is not specified. FTIOPN will move to the first non-null - image HDU, skipping over any tables. -\end{description} - -\begin{verbatim} - FTDOPN(unit,filename,rwmode, > status) - FTTOPN(unit,filename,rwmode, > status) - FTIOPN(unit,filename,rwmode, > status) -\end{verbatim} - -\begin{description} -\item[4 ]Open and initialize a new empty FITS file. A template file may also be - specified to define the structure of the new file (see section 4.2.4). - The FTDKINIT routine simply creates the specified - file without trying to interpret the filename using the extended - filename syntax. -\end{description} - -\begin{verbatim} - FTINIT(unit,filename,blocksize, > status) - FTDKINIT(unit,filename,blocksize, > status) -\end{verbatim} - -\begin{description} -\item[5 ]Close a FITS file previously opened with ftopen or ftinit -\end{description} - -\begin{verbatim} - FTCLOS(unit, > status) -\end{verbatim} - -\begin{description} -\item[6 ] Move to a specified (absolute) HDU in the FITS file (nhdu = 1 for the - FITS primary array) -\end{description} - -\begin{verbatim} - FTMAHD(unit,nhdu, > hdutype,status) -\end{verbatim} - -\begin{description} -\item[7 ] Create a primary array (if none already exists), or insert a - new IMAGE extension immediately following the CHDU, or - insert a new Primary Array at the beginning of the file. Any - following extensions in the file will be shifted down to make room - for the new extension. If the CHDU is the last HDU in the file - then the new image extension will simply be appended to the end of - the file. One can force a new primary array to be inserted at the - beginning of the FITS file by setting status = -9 prior - to calling the routine. In this case the existing primary array will be - converted to an IMAGE extension. The new extension (or primary - array) will become the CHDU. The FTIIMGLL routine is identical - to the FTIIMG routine except that the 4th parameter (the length - of each axis) is an array of 64-bit integers rather than an array - of 32-bit integers. -\end{description} - -\begin{verbatim} - FTIIMG(unit,bitpix,naxis,naxes, > status) - FTIIMGLL(unit,bitpix,naxis,naxesll, > status) -\end{verbatim} - -\begin{description} -\item[8 ] Insert a new ASCII TABLE extension immediately following the CHDU. - Any following extensions will be shifted down to make room for - the new extension. If there are no other following extensions - then the new table extension will simply be appended to the - end of the file. The new extension will become the CHDU. The FTITABLL - routine is identical - to the FTITAB routine except that the 2nd and 3rd parameters (that give - the size of the table) are 64-bit integers rather than - 32-bit integers. Under normal circumstances, the nrows and nrowsll - paramenters should have a value of 0; CFITSIO will automatically update - the number of rows as data is written to the table. -\end{description} - -\begin{verbatim} - FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > - status) - FTITABLL(unit,rowlenll,nrowsll,tfields,ttype,tbcol,tform,tunit,extname, > - status) -\end{verbatim} - -\begin{description} -\item[9 ] Insert a new binary table extension immediately following the CHDU. - Any following extensions will be shifted down to make room for - the new extension. If there are no other following extensions - then the new bintable extension will simply be appended to the - end of the file. The new extension will become the CHDU. The FTIBINLL - routine is identical - to the FTIBIN routine except that the 2nd parameter (that gives - the length of the table) is a 64-bit integer rather than - a 32-bit integer. Under normal circumstances, the nrows and nrowsll - paramenters should have a value of 0; CFITSIO will automatically update - the number of rows as data is written to the table. -\end{description} - -\begin{verbatim} - FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) - FTIBINLL(unit,nrowsll,tfields,ttype,tform,tunit,extname,varidat > status) - -\end{verbatim} - -\section{Keyword I/O Routines} - - -\begin{description} -\item[1 ]Put (append) an 80-character record into the CHU. -\end{description} - -\begin{verbatim} - FTPREC(unit,card, > status) -\end{verbatim} - -\begin{description} -\item[2 ] Put (append) a new keyword of the appropriate datatype into the CHU. - The E and D versions of this routine have the added feature that - if the 'decimals' parameter is negative, then the 'G' display - format rather then the 'E' format will be used when constructing - the keyword value, taking the absolute value of 'decimals' for the - precision. This will suppress trailing zeros, and will use a - fixed format rather than an exponential format, - depending on the magnitude of the value. -\end{description} - -\begin{verbatim} - FTPKY[JKLS](unit,keyword,keyval,comment, > status) - FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) -\end{verbatim} - -\begin{description} -\item[3 ]Get the nth 80-character header record from the CHU. The first keyword - in the header is at key\_no = 1; if key\_no = 0 then this subroutine - simple moves the internal pointer to the beginning of the header - so that subsequent keyword operations will start at the top of - the header; it also returns a blank card value in this case. -\end{description} - -\begin{verbatim} - FTGREC(unit,key_no, > card,status) -\end{verbatim} - -\begin{description} -\item[4 ] Get a keyword value (with the appropriate datatype) and comment from - the CHU -\end{description} - -\begin{verbatim} - FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) -\end{verbatim} - -\begin{description} -\item[5 ] Delete an existing keyword record. -\end{description} - -\begin{verbatim} - FTDKEY(unit,keyword, > status) -\end{verbatim} - - -\section{Data I/O Routines} - -The following routines read or write data values in the current HDU of -the FITS file. Automatic datatype conversion -will be attempted for numerical datatypes if the specified datatype is -different from the actual datatype of the FITS array or table column. - - -\begin{description} -\item[1 ]Write elements into the primary data array or image extension. -\end{description} - -\begin{verbatim} - FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) -\end{verbatim} - -\begin{description} -\item[2 ] Read elements from the primary data array or image extension. - Undefined array elements will be - returned with a value = nullval, unless nullval = 0 in which case no - checks for undefined pixels will be performed. The anyf parameter is - set to true (= .true.) if any of the returned - elements were undefined. -\end{description} - -\begin{verbatim} - FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) -\end{verbatim} - -\begin{description} -\item[3 ] Write elements into an ASCII or binary table column. The `felem' - parameter applies only to vector columns in binary tables and is - ignored when writing to ASCII tables. -\end{description} - -\begin{verbatim} - FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) -\end{verbatim} - -\begin{description} -\item[4 ] Read elements from an ASCII or binary table column. Undefined - array elements will be returned with a value = nullval, unless nullval = 0 - (or = ' ' for ftgcvs) in which case no checking for undefined values will - be performed. The ANYF parameter is set to true if any of the returned - elements are undefined. - - Any column, regardless of it's intrinsic datatype, may be read as a - string. It should be noted however that reading a numeric column - as a string is 10 - 100 times slower than reading the same column - as a number due to the large overhead in constructing the formatted - strings. The display format of the returned strings will be - determined by the TDISPn keyword, if it exists, otherwise by the - datatype of the column. The length of the returned strings can be - determined with the ftgcdw routine. The following TDISPn display - formats are currently supported: - -\begin{verbatim} - Iw.m Integer - Ow.m Octal integer - Zw.m Hexadecimal integer - Fw.d Fixed floating point - Ew.d Exponential floating point - Dw.d Exponential floating point - Gw.d General; uses Fw.d if significance not lost, else Ew.d -\end{verbatim} - where w is the width in characters of the displayed values, m is the minimum - number of digits displayed, and d is the number of digits to the right of the - decimal. The .m field is optional. -\end{description} - - -\begin{verbatim} - FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > - values,anyf,status) -\end{verbatim} - -\begin{description} -\item[5 ] Get the table column number and full name of the column whose name - matches the input template string. See the `Advanced Interface Routines' - chapter for a full description of this routine. -\end{description} - -\begin{verbatim} - FTGCNN(unit,casesen,coltemplate, > colname,colnum,status) -\end{verbatim} - - -\chapter{ Advanced Interface Subroutines } - -This chapter defines all the available subroutines in the FITSIO user -interface. For completeness, the basic subroutines described in the -previous chapter are also repeated here. A right arrow symbol is used -here to separate the input parameters from the output parameters in the -definition of each subroutine. This symbol is not actually part of the -calling sequence. An alphabetical list and definition of all the -parameters is given at the end of this section. - - -\section{FITS File Open and Close Subroutines: \label{FTOPEN}} - - -\begin{description} -\item[1 ]Open an existing FITS file with readonly or readwrite access. The -FTDKOPN routine simply opens the specified file without trying to -interpret the filename using the extended filename syntax. FTDOPN opens -the file and -also moves to the first HDU containing significant data, if no specific -HDU is specified as part of the filename. FTTOPN and FTIOPN are similar -except that they will move to the first table HDU or image HDU, respectively, -if a HDU name or number is not specified as part of the filename. -\end{description} - -\begin{verbatim} - FTOPEN(unit,filename,rwmode, > blocksize,status) - FTDKOPN(unit,filename,rwmode, > blocksize,status) - - FTDOPN(unit,filename,rwmode, > status) - FTTOPN(unit,filename,rwmode, > status) - FTIOPN(unit,filename,rwmode, > status) -\end{verbatim} - - -\begin{description} -\item[2 ]Open an existing FITS file with readonly or readwrite access - and move to a following extension, if one was specified as - part of the filename. (e.g., 'filename.fits+2' or - 'filename.fits[2]' will move to the 3rd HDU in the file). - Note that this routine differs from FTOPEN in that it does not - have the redundant blocksize argument. -\end{description} - -\begin{verbatim} - FTNOPN(unit,filename,rwmode, > status) -\end{verbatim} - -\begin{description} -\item[3 ] Reopen a FITS file that was previously opened with - FTOPEN, FTNOPN, or FTINIT. The newunit number - may then be treated as a separate file, and one may - simultaneously read or write to 2 (or more) different extensions in - the same file. The FTOPEN and FTNOPN routines (above) automatically - detects cases where a previously opened file is being opened again, - and then internally call FTREOPEN, so programs should rarely - need to explicitly call this routine. -\end{description} - -\begin{verbatim} - FTREOPEN(unit, > newunit, status) -\end{verbatim} - -\begin{description} -\item[4 ]Open and initialize a new empty FITS file. - The FTDKINIT routine simply creates the specified - file without trying to interpret the filename using the extended - filename syntax. -\end{description} - -\begin{verbatim} - FTINIT(unit,filename,blocksize, > status) - FTDKINIT(unit,filename,blocksize, > status) -\end{verbatim} - - -\begin{description} -\item[5 ] Create a new FITS file, using a template file to define its - initial size and structure. The template may be another FITS HDU - or an ASCII template file. If the input template file name - is blank, then this routine behaves the same as FTINIT. - The currently supported format of the ASCII template file is described - under the fits\_parse\_template routine (in the general Utilities - section), but this may change slightly later releases of - CFITSIO. -\end{description} - -\begin{verbatim} - FTTPLT(unit, filename, tplfilename, > status) -\end{verbatim} - -\begin{description} -\item[6 ]Flush internal buffers of data to the output FITS file - previously opened with ftopen or ftinit. The routine usually - never needs to be called, but doing so will ensure that - if the program subsequently aborts, then the FITS file will - have at least been closed properly. -\end{description} - -\begin{verbatim} - FTFLUS(unit, > status) -\end{verbatim} - -\begin{description} -\item[7 ]Close a FITS file previously opened with ftopen or ftinit -\end{description} - -\begin{verbatim} - FTCLOS(unit, > status) -\end{verbatim} - -\begin{description} -\item[8 ] Close and DELETE a FITS file previously opened with ftopen or ftinit. - This routine may be useful in cases where a FITS file is created, but - an error occurs which prevents the complete file from being written. -\end{description} - -\begin{verbatim} - FTDELT(unit, > status) -\end{verbatim} - -\begin{description} -\item[9 ] Get the value of an unused I/O unit number which may then be used - as input to FTOPEN or FTINIT. This routine searches for the first - unused unit number in the range from with 99 down to 50. This - routine just keeps an internal list of the allocated unit numbers - and does not physically check that the Fortran unit is available (to be - compatible with the SPP version of FITSIO). Thus users must not - independently allocate any unit numbers in the range 50 - 99 - if this routine is also to be used in the same program. This - routine is provided for convenience only, and it is not required - that the unit numbers used by FITSIO be allocated by this routine. -\end{description} - -\begin{verbatim} - FTGIOU( > iounit, status) -\end{verbatim} - -\begin{description} -\item[10] Free (deallocate) an I/O unit number which was previously allocated - with FTGIOU. All previously allocated unit numbers may be - deallocated at once by calling FTFIOU with iounit = -1. -\end{description} - -\begin{verbatim} - FTFIOU(iounit, > status) -\end{verbatim} - -\begin{description} -\item[11] Return the Fortran unit number that corresponds to the C fitsfile -pointer value, or vice versa. These 2 C routines may be useful in -mixed language programs where both C and Fortran subroutines need -to access the same file. For example, if a FITS file is opened -with unit 12 by a Fortran subroutine, then a C routine within the -same program could get the fitfile pointer value to access the same file -by calling 'fptr = CUnit2FITS(12)'. These routines return a value -of zero if an error occurs. -\end{description} - -\begin{verbatim} - int CFITS2Unit(fitsfile *ptr); - fitsfile* CUnit2FITS(int unit); -\end{verbatim} - - -\begin{description} -\item[11] Parse the input filename and return the HDU number that would be -moved to if the file were opened with FTNOPN. The returned HDU -number begins with 1 for the primary array, so for example, if the -input filename = `myfile.fits[2]' then hdunum = 3 will be returned. -FITSIO does not open the file to check if the extension actually exists -if an extension number is specified. If an extension *name* is included -in the file name specification (e.g. `myfile.fits[EVENTS]' then this -routine will have to open the FITS file and look for the position of -the named extension, then close file again. This is not possible if -the file is being read from the stdin stream, and an error will be -returned in this case. If the filename does not specify an explicit -extension (e.g. 'myfile.fits') then hdunum = -99 will be returned, -which is functionally equivalent to hdunum = 1. This routine is mainly -used for backward compatibility in the ftools software package and is -not recommended for general use. It is generally better and more -efficient to first open the FITS file with FTNOPN, then use FTGHDN to -determine which HDU in the file has been opened, rather than calling - FTEXTN followed by a call to FTNOPN. -\end{description} - -\begin{verbatim} - FTEXTN(filename, > nhdu, status) -\end{verbatim} - -\begin{description} -\item[12] Return the name of the opened FITS file. -\end{description} - -\begin{verbatim} - FTFLNM(unit, > filename, status) -\end{verbatim} - -\begin{description} -\item[13] Return the I/O mode of the open FITS file (READONLY = 0, READWRITE = 1). -\end{description} - -\begin{verbatim} - FTFLMD(unit, > iomode, status) -\end{verbatim} - -\begin{description} -\item[14] Return the file type of the opened FITS file (e.g. 'file://', 'ftp://', - etc.). -\end{description} - -\begin{verbatim} - FTURLT(unit, > urltype, status) -\end{verbatim} - -\begin{description} -\item[15] Parse the input filename or URL into its component parts: the file -type (file://, ftp://, http://, etc), the base input file name, the -name of the output file that the input file is to be copied to prior -to opening, the HDU or extension specification, the filtering -specifier, the binning specifier, and the column specifier. Blank -strings will be returned for any components that are not present -in the input file name. -\end{description} - -\begin{verbatim} - FTIURL(filename, > filetype, infile, outfile, extspec, filter, - binspec, colspec, status) -\end{verbatim} - -\begin{description} -\item[16] Parse the input file name and return the root file name. The root -name includes the file type if specified, (e.g. 'ftp://' or 'http://') -and the full path name, to the extent that it is specified in the input -filename. It does not include the HDU name or number, or any filtering -specifications. -\end{description} - -\begin{verbatim} - FTRTNM(filename, > rootname, status) -\end{verbatim} - - -\begin{description} -\item[16] Test if the input file or a compressed version of the file (with -a .gz, .Z, .z, or .zip extension) exists on disk. The returned value of -the 'exists' parameter will have 1 of the 4 following values: - -\begin{verbatim} - 2: the file does not exist, but a compressed version does exist - 1: the disk file does exist - 0: neither the file nor a compressed version of the file exist - -1: the input file name is not a disk file (could be a ftp, http, - smem, or mem file, or a file piped in on the STDIN stream) -\end{verbatim} - -\end{description} - -\begin{verbatim} - FTEXIST(filename, > exists, status); -\end{verbatim} - -\section{HDU-Level Operations \label{FTMAHD}} - -When a FITS file is first opened or created, the internal buffers in -FITSIO automatically point to the first HDU in the file. The following -routines may be used to move to another HDU in the file. Note that -the HDU numbering convention used in FITSIO denotes the primary array -as the first HDU, the first extension in a FITS file is the second HDU, -and so on. - - -\begin{description} -\item[1 ] Move to a specified (absolute) HDU in the FITS file (nhdu = 1 for the - FITS primary array) -\end{description} - -\begin{verbatim} - FTMAHD(unit,nhdu, > hdutype,status) -\end{verbatim} - -\begin{description} -\item[2 ]Move to a new (existing) HDU forward or backwards relative to the CHDU -\end{description} - -\begin{verbatim} - FTMRHD(unit,nmove, > hdutype,status) -\end{verbatim} - -\begin{description} -\item[3 ] Move to the (first) HDU which has the specified extension type and - EXTNAME (or HDUNAME) and EXTVER keyword values. The hdutype parameter - may have - a value of IMAGE\_HDU (0), ASCII\_TBL (1), BINARY\_TBL (2), or ANY\_HDU (-1) - where ANY\_HDU means that only the extname and extver values will be - used to locate the correct extension. If the input value of - extver is 0 then the EXTVER keyword is ignored and the first HDU - with a matching EXTNAME (or HDUNAME) keyword will be found. If no - matching HDU is found in the file then the current HDU will remain - unchanged - and a status = BAD\_HDU\_NUM (301) will be returned. -\end{description} - -\begin{verbatim} - FTMNHD(unit, hdutype, extname, extver, > status) -\end{verbatim} - -\begin{description} -\item[4 ]Get the number of the current HDU in the FITS file (primary array = 1) -\end{description} - -\begin{verbatim} - FTGHDN(unit, > nhdu) -\end{verbatim} - -\begin{description} -\item[5 ] Return the type of the current HDU in the FITS file. The possible - values for hdutype are IMAGE\_HDU (0), ASCII\_TBL (1), or BINARY\_TBL (2). -\end{description} - -\begin{verbatim} - FTGHDT(unit, > hdutype, status) -\end{verbatim} - -\begin{description} -\item[6 ] Return the total number of HDUs in the FITS file. - The CHDU remains unchanged. -\end{description} - -\begin{verbatim} - FTTHDU(unit, > hdunum, status) -\end{verbatim} - -\begin{description} -\item[7 ]Create (append) a new empty HDU at the end of the FITS file. This - new HDU becomes the Current HDU, but it is completely empty and contains - no header keywords or data. It is recommended that FTIIMG, FTITAB or - FTIBIN be used instead of this routine. -\end{description} - -\begin{verbatim} - FTCRHD(unit, > status) -\end{verbatim} - - -\begin{description} -\item[8 ] Create a primary array (if none already exists), or insert a - new IMAGE extension immediately following the CHDU, or - insert a new Primary Array at the beginning of the file. Any - following extensions in the file will be shifted down to make room - for the new extension. If the CHDU is the last HDU in the file - then the new image extension will simply be appended to the end of - the file. One can force a new primary array to be inserted at the - beginning of the FITS file by setting status = -9 prior - to calling the routine. In this case the existing primary array will be - converted to an IMAGE extension. The new extension (or primary - array) will become the CHDU. The FTIIMGLL routine is identical - to the FTIIMG routine except that the 4th parameter (the length - of each axis) is an array of 64-bit integers rather than an array - of 32-bit integers. -\end{description} - -\begin{verbatim} - FTIIMG(unit,bitpix,naxis,naxes, > status) - FTIIMGLL(unit,bitpix,naxis,naxesll, > status) -\end{verbatim} - -\begin{description} -\item[9 ] Insert a new ASCII TABLE extension immediately following the CHDU. - Any following extensions will be shifted down to make room for - the new extension. If there are no other following extensions - then the new table extension will simply be appended to the - end of the file. The new extension will become the CHDU. The FTITABLL - routine is identical - to the FTITAB routine except that the 2nd and 3rd parameters (that give - the size of the table) are 64-bit integers rather than - 32-bit integers. -\end{description} - -\begin{verbatim} - FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > - status) - FTITABLL(unit,rowlenll,nrowsll,tfields,ttype,tbcol,tform,tunit,extname, > - status) -\end{verbatim} - - -\begin{description} -\item[10] Insert a new binary table extension immediately following the CHDU. - Any following extensions will be shifted down to make room for - the new extension. If there are no other following extensions - then the new bintable extension will simply be appended to the - end of the file. The new extension will become the CHDU. The FTIBINLL - routine is identical - to the FTIBIN routine except that the 2nd parameter (that gives - the length of the table) is a 64-bit integer rather than - a 32-bit integer. -\end{description} - -\begin{verbatim} - FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) - FTIBINLL(unit,nrowsll,tfields,ttype,tform,tunit,extname,varidat > status) - -\end{verbatim} - - -\begin{description} -\item[11] Resize an image by modifing the size, dimensions, and/or datatype of the - current primary array or image extension. If the new image, as specified - by the input arguments, is larger than the current existing image - in the FITS file then zero fill data will be inserted at the end - of the current image and any following extensions will be moved - further back in the file. Similarly, if the new image is - smaller than the current image then any following extensions - will be shifted up towards the beginning of the FITS file - and the image data will be truncated to the new size. - This routine rewrites the BITPIX, NAXIS, and NAXISn keywords - with the appropriate values for new image. The FTRSIMLL routine is identical - to the FTRSIM routine except that the 4th parameter (the length - of each axis) is an array of 64-bit integers rather than an array - of 32-bit integers. -\end{description} - -\begin{verbatim} - FTRSIM(unit,bitpix,naxis,naxes,status) - FTRSIMLL(unit,bitpix,naxis,naxesll,status) -\end{verbatim} - -\begin{description} -\item[12] Delete the CHDU in the FITS file. Any following HDUs will be shifted - forward in the file, to fill in the gap created by the deleted - HDU. In the case of deleting the primary array (the first HDU in - the file) then the current primary array will be replace by a null - primary array containing the minimum set of required keywords and - no data. If there are more extensions in the file following the - one that is deleted, then the the CHDU will be redefined to point - to the following extension. If there are no following extensions - then the CHDU will be redefined to point to the previous HDU. The - output HDUTYPE parameter indicates the type of the new CHDU after - the previous CHDU has been deleted. -\end{description} - -\begin{verbatim} - FTDHDU(unit, > hdutype,status) -\end{verbatim} - -\begin{description} -\item[13] Copy all or part of the input FITS file and append it - to the end of the output FITS file. If 'previous' (an integer parameter) is - not equal to 0, then any HDUs preceding the current HDU in the input file - will be copied to the output file. Similarly, 'current' and 'following' - determine whether the current HDU, and/or any following HDUs in the input - file will be copied to the output file. If all 3 parameters are not equal - to zero, then the entire input file will be copied. On return, the current - HDU in the input file will be unchanged, and the last copied HDU will be the - current HDU in the output file. -\end{description} - -\begin{verbatim} - FTCPFL(iunit, ounit, previous, current, following, > status) -\end{verbatim} - -\begin{description} -\item[14] Copy the entire CHDU from the FITS file associated with IUNIT to the CHDU - of the FITS file associated with OUNIT. The output HDU must be empty and - not already contain any keywords. Space will be reserved for MOREKEYS - additional keywords in the output header if there is not already enough - space. -\end{description} - -\begin{verbatim} - FTCOPY(iunit,ounit,morekeys, > status) -\end{verbatim} - -\begin{description} -\item[15] Copy the header (and not the data) from the CHDU associated with inunit - to the CHDU associated with outunit. If the current output HDU - is not completely empty, then the CHDU will be closed and a new - HDU will be appended to the output file. This routine will automatically - transform the necessary keywords when copying a primary array to - and image extension, or an image extension to a primary array. - An empty output data unit will be created (all values = 0). -\end{description} - -\begin{verbatim} - FTCPHD(inunit, outunit, > status) -\end{verbatim} - -\begin{description} -\item[16] Copy just the data from the CHDU associated with IUNIT - to the CHDU associated with OUNIT. This will overwrite - any data previously in the OUNIT CHDU. This low level routine is used - by FTCOPY, but it may also be useful in certain application programs - which want to copy the data from one FITS file to another but also - want to modify the header keywords in the process. all the required - header keywords must be written to the OUNIT CHDU before calling - this routine -\end{description} - -\begin{verbatim} - FTCPDT(iunit,ounit, > status) -\end{verbatim} - - -\section{Define or Redefine the structure of the CHDU \label{FTRDEF}} - -It should rarely be necessary to call the subroutines in this section. -FITSIO internally calls these routines whenever necessary, so any calls -to these routines by application programs will likely be redundant. - - -\begin{description} -\item[1 ] This routine forces FITSIO to scan the current header keywords that - define the structure of the HDU (such as the NAXISn, PCOUNT and GCOUNT - keywords) so that it can initialize the internal buffers that describe - the HDU structure. This routine may be used instead of the more - complicated calls to ftpdef, ftadef or ftbdef. This routine is - also very useful for reinitializing the structure of an HDU, - if the number of rows in a table, as specified by the NAXIS2 keyword, - has been modified from its initial value. -\end{description} - -\begin{verbatim} - FTRDEF(unit, > status) (DEPRECATED) -\end{verbatim} - -\begin{description} -\item[2 ]Define the structure of the primary array or IMAGE extension. When - writing GROUPed FITS files that by convention set the NAXIS1 keyword - equal to 0, ftpdef must be called with naxes(1) = 1, NOT 0, otherwise - FITSIO will report an error status=308 when trying to write data - to a group. Note: it is usually simpler to call FTRDEF rather - than this routine. -\end{description} - -\begin{verbatim} - FTPDEF(unit,bitpix,naxis,naxes,pcount,gcount, > status) (DEPRECATED) -\end{verbatim} - -\begin{description} -\item[3 ] Define the structure of an ASCII table (TABLE) extension. Note: it - is usually simpler to call FTRDEF rather than this routine. -\end{description} - -\begin{verbatim} - FTADEF(unit,rowlen,tfields,tbcol,tform,nrows > status) (DEPRECATED) -\end{verbatim} - -\begin{description} -\item[4 ] Define the structure of a binary table (BINTABLE) extension. Note: it - is usually simpler to call FTRDEF rather than this routine. -\end{description} - -\begin{verbatim} - FTBDEF(unit,tfields,tform,varidat,nrows > status) (DEPRECATED) -\end{verbatim} - -\begin{description} -\item[5 ] Define the size of the Current Data Unit, overriding the length - of the data unit as previously defined by ftpdef, ftadef, or ftbdef. - This is useful if one does not know the total size of the data unit until - after the data have been written. The size (in bytes) of an ASCII or - Binary table is given by NAXIS1 * NAXIS2. (Note that to determine the - value of NAXIS1 it is often more convenient to read the value of the - NAXIS1 keyword from the output file, rather than computing the row - length directly from all the TFORM keyword values). Note: it - is usually simpler to call FTRDEF rather than this routine. -\end{description} - -\begin{verbatim} - FTDDEF(unit,bytlen, > status) (DEPRECATED) -\end{verbatim} - -\begin{description} -\item[6 ] Define the zero indexed byte offset of the 'heap' measured from - the start of the binary table data. By default the heap is assumed - to start immediately following the regular table data, i.e., at - location NAXIS1 x NAXIS2. This routine is only relevant for - binary tables which contain variable length array columns (with - TFORMn = 'Pt'). This subroutine also automatically writes - the value of theap to a keyword in the extension header. This - subroutine must be called after the required keywords have been - written (with ftphbn) and after the table structure has been defined - (with ftbdef) but before any data is written to the table. -\end{description} - -\begin{verbatim} - FTPTHP(unit,theap, > status) -\end{verbatim} - - -\section{FITS Header I/O Subroutines} - - -\subsection{Header Space and Position Routines \label{FTHDEF}} - - -\begin{description} -\item[1 ] Reserve space in the CHU for MOREKEYS more header keywords. - This subroutine may be called to reserve space for keywords which are - to be written at a later time, after the data unit or subsequent - extensions have been written to the FITS file. If this subroutine is - not explicitly called, then the initial size of the FITS header will be - limited to the space available at the time that the first data is written - to the associated data unit. FITSIO has the ability to dynamically - add more space to the header if needed, however it is more efficient - to preallocate the required space if the size is known in advance. -\end{description} - -\begin{verbatim} - FTHDEF(unit,morekeys, > status) -\end{verbatim} - -\begin{description} -\item[2 ] Return the number of existing keywords in the CHU (NOT including the - END keyword which is not considered a real keyword) and the remaining - space available to write additional keywords in the CHU. (returns - KEYSADD = -1 if the header has not yet been closed). - Note that FITSIO will attempt to dynamically add space for more - keywords if required when appending new keywords to a header. -\end{description} - -\begin{verbatim} - FTGHSP(iunit, > keysexist,keysadd,status) -\end{verbatim} - -\begin{description} -\item[3 ] Return the number of keywords in the header and the current position - in the header. This returns the number of the keyword record that - will be read next (or one greater than the position of the last keyword - that was read or written). A value of 1 is returned if the pointer is - positioned at the beginning of the header. -\end{description} - -\begin{verbatim} - FTGHPS(iunit, > keysexist,key_no,status) -\end{verbatim} - -\subsection{Read or Write Standard Header Routines \label{FTPHPR}} - -These subroutines provide a simple method of reading or writing most of -the keyword values that are normally required in a FITS files. These -subroutines are provided for convenience only and are not required to -be used. If preferred, users may call the lower-level subroutines -described in the previous section to individually read or write the -required keywords. Note that in most cases, the required keywords such -as NAXIS, TFIELD, TTYPEn, etc, which define the structure of the HDU -must be written to the header before any data can be written to the -image or table. - - -\begin{description} -\item[1 ] Put the primary header or IMAGE extension keywords into the CHU. -There are 2 available routines: The simpler FTPHPS routine is -equivalent to calling ftphpr with the default values of SIMPLE = true, -pcount = 0, gcount = 1, and EXTEND = true. PCOUNT, GCOUNT and EXTEND -keywords are not required in the primary header and are only written if -pcount is not equal to zero, gcount is not equal to zero or one, and if -extend is TRUE, respectively. When writing to an IMAGE extension, the -SIMPLE and EXTEND parameters are ignored. -\end{description} - -\begin{verbatim} - FTPHPS(unit,bitpix,naxis,naxes, > status) - - FTPHPR(unit,simple,bitpix,naxis,naxes,pcount,gcount,extend, > status) -\end{verbatim} - -\begin{description} -\item[2 ] Get primary header or IMAGE extension keywords from the CHU. When - reading from an IMAGE extension the SIMPLE and EXTEND parameters are - ignored. -\end{description} - -\begin{verbatim} - FTGHPR(unit,maxdim, > simple,bitpix,naxis,naxes,pcount,gcount,extend, - status) -\end{verbatim} - -\begin{description} -\item[3 ] Put the ASCII table header keywords into the CHU. The optional -TUNITn and EXTNAME keywords are written only if the input string -values are not blank. -\end{description} - -\begin{verbatim} - FTPHTB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > - status) -\end{verbatim} - -\begin{description} -\item[4 ] Get the ASCII table header keywords from the CHU -\end{description} - -\begin{verbatim} - FTGHTB(unit,maxdim, > rowlen,nrows,tfields,ttype,tbcol,tform,tunit, - extname,status) -\end{verbatim} - -\begin{description} -\item[5 ]Put the binary table header keywords into the CHU. The optional - TUNITn and EXTNAME keywords are written only if the input string - values are not blank. The pcount parameter, which specifies the - size of the variable length array heap, should initially = 0; - FITSIO will automatically update the PCOUNT keyword value if any - variable length array data is written to the heap. The TFORM keyword - value for variable length vector columns should have the form 'Pt(len)' - or '1Pt(len)' where `t' is the data type code letter (A,I,J,E,D, etc.) - and `len' is an integer specifying the maximum length of the vectors - in that column (len must be greater than or equal to the longest - vector in the column). If `len' is not specified when the table is - created (e.g., the input TFORMn value is just '1Pt') then FITSIO will - scan the column when the table is first closed and will append the - maximum length to the TFORM keyword value. Note that if the table - is subsequently modified to increase the maximum length of the vectors - then the modifying program is responsible for also updating the TFORM - keyword value. -\end{description} - - -\begin{verbatim} - FTPHBN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat, > status) -\end{verbatim} - -\begin{description} -\item[6 ]Get the binary table header keywords from the CHU -\end{description} - -\begin{verbatim} - FTGHBN(unit,maxdim, > nrows,tfields,ttype,tform,tunit,extname,varidat, - status) -\end{verbatim} - -\subsection{Write Keyword Subroutines \label{FTPREC}} - - -\begin{description} -\item[1 ]Put (append) an 80-character record into the CHU. -\end{description} - -\begin{verbatim} - FTPREC(unit,card, > status) -\end{verbatim} - -\begin{description} -\item[2 ] Put (append) a COMMENT keyword into the CHU. Multiple COMMENT keywords - will be written if the input comment string is longer than 72 characters. -\end{description} - -\begin{verbatim} - FTPCOM(unit,comment, > status) -\end{verbatim} - -\begin{description} -\item[3 ]Put (append) a HISTORY keyword into the CHU. Multiple HISTORY keywords - will be written if the input history string is longer than 72 characters. -\end{description} - -\begin{verbatim} - FTPHIS(unit,history, > status) -\end{verbatim} - -\begin{description} -\item[4 ] Put (append) the DATE keyword into the CHU. The keyword value will contain - the current system date as a character string in 'dd/mm/yy' format. If - a DATE keyword already exists in the header, then this subroutine will - simply update the keyword value in-place with the current date. -\end{description} - -\begin{verbatim} - FTPDAT(unit, > status) -\end{verbatim} - -\begin{description} -\item[5 ] Put (append) a new keyword of the appropriate datatype into the CHU. - Note that FTPKYS will only write string values up to 68 characters in - length; longer strings will be truncated. The FTPKLS routine can be - used to write longer strings, using a non-standard FITS convention. - The E and D versions of this routine have the added feature that - if the 'decimals' parameter is negative, then the 'G' display - format rather then the 'E' format will be used when constructing - the keyword value, taking the absolute value of 'decimals' for the - precision. This will suppress trailing zeros, and will use a - fixed format rather than an exponential format, - depending on the magnitude of the value. -\end{description} - -\begin{verbatim} - FTPKY[JKLS](unit,keyword,keyval,comment, > status) - FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) -\end{verbatim} - -\begin{description} -\item[6 ] Put (append) a string valued keyword into the CHU which may be longer - than 68 characters in length. This uses the Long String Keyword - convention that is described in the "Usage Guidelines and Suggestions" - section of this document. Since this uses a non-standard FITS - convention to encode the long keyword string, programs which use - this routine should also call the FTPLSW routine to add some COMMENT - keywords to warn users of the FITS file that this convention is - being used. FTPLSW also writes a keyword called LONGSTRN to record - the version of the longstring convention that has been used, in case - a new convention is adopted at some point in the future. If the - LONGSTRN keyword is already present in the header, then FTPLSW will - simply return and will not write duplicate keywords. -\end{description} - -\begin{verbatim} - FTPKLS(unit,keyword,keyval,comment, > status) - FTPLSW(unit, > status) -\end{verbatim} - -\begin{description} -\item[7 ] Put (append) a new keyword with an undefined, or null, value into the CHU. - The value string of the keyword is left blank in this case. -\end{description} - -\begin{verbatim} - FTPKYU(unit,keyword,comment, > status) -\end{verbatim} - -\begin{description} -\item[8 ] Put (append) a numbered sequence of keywords into the CHU. One may - append the same comment to every keyword (and eliminate the need - to have an array of identical comment strings, one for each keyword) by - including the ampersand character as the last non-blank character in the - (first) COMMENTS string parameter. This same string - will then be used for the comment field in all the keywords. (Note - that the SPP version of these routines only supports a single comment - string). -\end{description} - -\begin{verbatim} - FTPKN[JKLS](unit,keyroot,startno,no_keys,keyvals,comments, > status) - FTPKN[EDFG](unit,keyroot,startno,no_keys,keyvals,decimals,comments, > - status) -\end{verbatim} - -\begin{description} -\item[9 ]Copy an indexed keyword from one HDU to another, modifying - the index number of the keyword name in the process. For example, - this routine could read the TLMIN3 keyword from the input HDU - (by giving keyroot = "TLMIN" and innum = 3) and write it to the - output HDU with the keyword name TLMIN4 (by setting outnum = 4). - If the input keyword does not exist, then this routine simply - returns without indicating an error. -\end{description} - -\begin{verbatim} - FTCPKY(inunit, outunit, innum, outnum, keyroot, > status) -\end{verbatim} - -\begin{description} -\item[10] Put (append) a 'triple precision' keyword into the CHU in F28.16 format. - The floating point keyword value is constructed by concatenating the - input integer value with the input double precision fraction value - (which must have a value between 0.0 and 1.0). The FTGKYT routine should - be used to read this keyword value, because the other keyword reading - subroutines will not preserve the full precision of the value. -\end{description} - -\begin{verbatim} - FTPKYT(unit,keyword,intval,dblval,comment, > status) -\end{verbatim} - -\begin{description} -\item[11] Write keywords to the CHDU that are defined in an ASCII template file. - The format of the template file is described under the ftgthd - routine below. -\end{description} - -\begin{verbatim} - FTPKTP(unit, filename, > status) -\end{verbatim} - -\begin{description} -\item[12] Append the physical units string to an existing keyword. This - routine uses a local convention, shown in the following example, - in which the keyword units are enclosed in square brackets in the - beginning of the keyword comment field. -\end{description} - - -\begin{verbatim} - VELOCITY= 12.3 / [km/s] orbital speed - - FTPUNT(unit,keyword,units, > status) -\end{verbatim} - -\subsection{Insert Keyword Subroutines \label{FTIREC}} - - -\begin{description} -\item[1 ] Insert a new keyword record into the CHU at the specified position - (i.e., immediately preceding the (keyno)th keyword in the header.) - This 'insert record' subroutine is somewhat less efficient - then the 'append record' subroutine (FTPREC) described above because - the remaining keywords in the header have to be shifted down one slot. -\end{description} - -\begin{verbatim} - FTIREC(unit,key_no,card, > status) -\end{verbatim} - -\begin{description} -\item[2 ] Insert a new keyword into the CHU. The new keyword is inserted - immediately following the last keyword that has been read from the header. - The FTIKLS subroutine works the same as the FTIKYS subroutine, except - it also supports long string values greater than 68 characters in length. - These 'insert keyword' subroutines are somewhat less efficient then - the 'append keyword' subroutines described above because the remaining - keywords in the header have to be shifted down one slot. -\end{description} - -\begin{verbatim} - FTIKEY(unit, card, > status) - FTIKY[JKLS](unit,keyword,keyval,comment, > status) - FTIKLS(unit,keyword,keyval,comment, > status) - FTIKY[EDFG](unit,keyword,keyval,decimals,comment, > status) -\end{verbatim} - -\begin{description} -\item[3 ] Insert a new keyword with an undefined, or null, value into the CHU. - The value string of the keyword is left blank in this case. -\end{description} - -\begin{verbatim} - FTIKYU(unit,keyword,comment, > status) -\end{verbatim} - -\subsection{Read Keyword Subroutines \label{FTGREC}} - -These routines return the value of the specified keyword(s). Wild card -characters (*, ?, or \#) may be used when specifying the name of the keyword -to be read: a '?' will match any single character at that position in the -keyword name and a '*' will match any length (including zero) string of -characters. The '\#' character will match any consecutive string of -decimal digits (0 - 9). Note that when a wild card is used in the input -keyword name, the routine will only search for a match from the current -header position to the end of the header. It will not resume the search -from the top of the header back to the original header position as is done -when no wildcards are included in the keyword name. If the desired -keyword string is 8-characters long (the maximum length of a keyword -name) then a '*' may be appended as the ninth character of the input -name to force the keyword search to stop at the end of the header -(e.g., 'COMMENT *' will search for the next COMMENT keyword). The -ffgrec routine may be used to set the starting position when doing -wild card searches. - - -\begin{description} -\item[1 ]Get the nth 80-character header record from the CHU. The first keyword - in the header is at key\_no = 1; if key\_no = 0 then this subroutine - simple moves the internal pointer to the beginning of the header - so that subsequent keyword operations will start at the top of - the header; it also returns a blank card value in this case. -\end{description} - -\begin{verbatim} - FTGREC(unit,key_no, > card,status) -\end{verbatim} - -\begin{description} -\item[2 ] Get the name, value (as a string), and comment of the nth keyword in CHU. - This routine also checks that the returned keyword name (KEYWORD) contains - only legal ASCII characters. Call FTGREC and FTPSVC to bypass this error - check. -\end{description} - -\begin{verbatim} - FTGKYN(unit,key_no, > keyword,value,comment,status) -\end{verbatim} - -\begin{description} -\item[3 ] Get the 80-character header record for the named keyword -\end{description} - -\begin{verbatim} - FTGCRD(unit,keyword, > card,status) -\end{verbatim} - -\begin{description} -\item[4 ] Get the next keyword whose name matches one of the strings in - 'inclist' but does not match any of the strings in 'exclist'. - The strings in inclist and exclist may contain wild card characters - (*, ?, and \#) as described at the beginning of this section. - This routine searches from the current header position to the - end of the header, only, and does not continue the search from - the top of the header back to the original position. The current - header position may be reset with the ftgrec routine. Note - that nexc may be set = 0 if there are no keywords to be excluded. - This routine returns status = 202 if a matching - keyword is not found. -\end{description} - -\begin{verbatim} - FTGNXK(unit,inclist,ninc,exclist,nexc, > card,status) -\end{verbatim} - -\begin{description} -\item[5 ] Get the literal keyword value as a character string. Regardless - of the datatype of the keyword, this routine simply returns the - string of characters in the value field of the keyword along with - the comment field. -\end{description} - -\begin{verbatim} - FTGKEY(unit,keyword, > value,comment,status) -\end{verbatim} - -\begin{description} -\item[6 ] Get a keyword value (with the appropriate datatype) and comment from - the CHU -\end{description} - -\begin{verbatim} - FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) -\end{verbatim} - -\begin{description} -\item[7 ] Read a string-valued keyword and return the string length, the value string, - and/or the comment field. The first routine, FTGKSL, simply - returns the length of the character string value of the specified keyword. - The second routine, FTGSKY, also returns up to maxchar characters - of the keyword value string, starting with the firstchar character, - and the keyword comment string. - The length argument returns the total length of the keyword value string - regardless of how much of the string is actually returned (which - depends on the value of the firstchar and maxchar arguments). These - routines support string keywords that use the CONTINUE convention to - continue long string values over multiple FITS header records. Normally, - string-valued keywords have a maximum length of 68 characters, however, - CONTINUE'd string keywords may be arbitrarily long. -\end{description} - -\begin{verbatim} - FTGKSL(unit,keyword, > length,status) - FTGSKY(unit,keyword,firstchar,maxchar,> keyval,length,comment,status) -\end{verbatim} - -\begin{description} -\item[8 ] Get a sequence of numbered keyword values. These - routines do not support wild card characters in the root name. -\end{description} - -\begin{verbatim} - FTGKN[EDJKLS](unit,keyroot,startno,max_keys, > keyvals,nfound,status) -\end{verbatim} - -\begin{description} -\item[9 ] Get the value of a floating point keyword, returning the integer and - fractional parts of the value in separate subroutine arguments. - This subroutine may be used to read any keyword but is especially - useful for reading the 'triple precision' keywords written by FTPKYT. -\end{description} - -\begin{verbatim} - FTGKYT(unit,keyword, > intval,dblval,comment,status) -\end{verbatim} - -\begin{description} -\item[10] Get the physical units string in an existing keyword. This - routine uses a local convention, shown in the following example, - in which the keyword units are - enclosed in square brackets in the beginning of the keyword comment - field. A blank string is returned if no units are defined - for the keyword. -\end{description} - -\begin{verbatim} - VELOCITY= 12.3 / [km/s] orbital speed - - FTGUNT(unit,keyword, > units,status) -\end{verbatim} - -\subsection{Modify Keyword Subroutines \label{FTMREC}} - -Wild card characters, as described in the Read Keyword section, above, -may be used when specifying the name of the keyword to be modified. - - -\begin{description} -\item[1 ] Modify (overwrite) the nth 80-character header record in the CHU -\end{description} - -\begin{verbatim} - FTMREC(unit,key_no,card, > status) -\end{verbatim} - -\begin{description} -\item[2 ] Modify (overwrite) the 80-character header record for the named keyword - in the CHU. This can be used to overwrite the name of the keyword as - well as its value and comment fields. -\end{description} - -\begin{verbatim} - FTMCRD(unit,keyword,card, > status) -\end{verbatim} - -\begin{description} -\item[3 ] Modify (overwrite) the name of an existing keyword in the CHU - preserving the current value and comment fields. -\end{description} - -\begin{verbatim} - FTMNAM(unit,oldkey,keyword, > status) -\end{verbatim} - -\begin{description} -\item[4 ] Modify (overwrite) the comment field of an existing keyword in the CHU -\end{description} - -\begin{verbatim} - FTMCOM(unit,keyword,comment, > status) -\end{verbatim} - -\begin{description} -\item[5 ] Modify the value and comment fields of an existing keyword in the CHU. - The FTMKLS subroutine works the same as the FTMKYS subroutine, except - it also supports long string values greater than 68 characters in length. - Optionally, one may modify only the value field and leave the comment - field unchanged by setting the input COMMENT parameter equal to - the ampersand character (\&). - The E and D versions of this routine have the added feature that - if the 'decimals' parameter is negative, then the 'G' display - format rather then the 'E' format will be used when constructing - the keyword value, taking the absolute value of 'decimals' for the - precision. This will suppress trailing zeros, and will use a - fixed format rather than an exponential format, - depending on the magnitude of the value. -\end{description} - -\begin{verbatim} - FTMKY[JKLS](unit,keyword,keyval,comment, > status) - FTMKLS(unit,keyword,keyval,comment, > status) - FTMKY[EDFG](unit,keyword,keyval,decimals,comment, > status) -\end{verbatim} - -\begin{description} -\item[6 ] Modify the value of an existing keyword to be undefined, or null. - The value string of the keyword is set to blank. - Optionally, one may leave the comment field unchanged by setting the - input COMMENT parameter equal to the ampersand character (\&). -\end{description} - -\begin{verbatim} - FTMKYU(unit,keyword,comment, > status) -\end{verbatim} - -\subsection{Update Keyword Subroutines \label{FTUCRD}} - - -\begin{description} -\item[1 ] Update an 80-character record in the CHU. If the specified keyword - already exists then that header record will be replaced with - the input CARD string. If it does not exist then the new record will - be added to the header. - The FTUKLS subroutine works the same as the FTUKYS subroutine, except - it also supports long string values greater than 68 characters in length. -\end{description} - -\begin{verbatim} - FTUCRD(unit,keyword,card, > status) -\end{verbatim} - -\begin{description} -\item[2 ] Update the value and comment fields of a keyword in the CHU. - The specified keyword is modified if it already exists (by calling - FTMKYx) otherwise a new keyword is created by calling FTPKYx. - The E and D versions of this routine have the added feature that - if the 'decimals' parameter is negative, then the 'G' display - format rather then the 'E' format will be used when constructing - the keyword value, taking the absolute value of 'decimals' for the - precision. This will suppress trailing zeros, and will use a - fixed format rather than an exponential format, - depending on the magnitude of the value. -\end{description} - -\begin{verbatim} - FTUKY[JKLS](unit,keyword,keyval,comment, > status) - FTUKLS(unit,keyword,keyval,comment, > status) - FTUKY[EDFG](unit,keyword,keyval,decimals,comment, > status) -\end{verbatim} - -\begin{description} -\item[3 ] Update the value of an existing keyword to be undefined, or null, - or insert a new undefined-value keyword if it doesn't already exist. - The value string of the keyword is left blank in this case. -\end{description} - -\begin{verbatim} - FTUKYU(unit,keyword,comment, > status) -\end{verbatim} - -\subsection{Delete Keyword Subroutines \label{FTDREC}} - - -\begin{description} -\item[1 ] Delete an existing keyword record. The space previously occupied by - the keyword is reclaimed by moving all the following header records up - one row in the header. The first routine deletes a keyword at a - specified position in the header (the first keyword is at position 1), - whereas the second routine deletes a specifically named keyword. - Wild card characters, as described in the Read Keyword section, above, - may be used when specifying the name of the keyword to be deleted - (be careful!). -\end{description} - -\begin{verbatim} - FTDREC(unit,key_no, > status) - FTDKEY(unit,keyword, > status) -\end{verbatim} - - -\section{Data Scaling and Undefined Pixel Parameters \label{FTPSCL}} - -These subroutines define or modify the internal parameters used by -FITSIO to either scale the data or to represent undefined pixels. -Generally FITSIO will scale the data according to the values of the BSCALE -and BZERO (or TSCALn and TZEROn) keywords, however these subroutines -may be used to override the keyword values. This may be useful when -one wants to read or write the raw unscaled values in the FITS file. -Similarly, FITSIO generally uses the value of the BLANK or TNULLn -keyword to signify an undefined pixel, but these routines may be used -to override this value. These subroutines do not create or modify the -corresponding header keyword values. - - -\begin{description} -\item[1 ] Reset the scaling factors in the primary array or image extension; does - not change the BSCALE and BZERO keyword values and only affects the - automatic scaling performed when the data elements are written/read - to/from the FITS file. When reading from a FITS file the returned - data value = (the value given in the FITS array) * BSCALE + BZERO. - The inverse formula is used when writing data values to the FITS - file. (NOTE: BSCALE and BZERO must be declared as Double Precision - variables). -\end{description} - -\begin{verbatim} - FTPSCL(unit,bscale,bzero, > status) -\end{verbatim} - -\begin{description} -\item[2 ] Reset the scaling parameters for a table column; does not change - the TSCALn or TZEROn keyword values and only affects the automatic - scaling performed when the data elements are written/read to/from - the FITS file. When reading from a FITS file the returned data - value = (the value given in the FITS array) * TSCAL + TZERO. The - inverse formula is used when writing data values to the FITS file. - (NOTE: TSCAL and TZERO must be declared as Double Precision - variables). -\end{description} - -\begin{verbatim} - FTTSCL(unit,colnum,tscal,tzero, > status) -\end{verbatim} - -\begin{description} -\item[3 ] Define the integer value to be used to signify undefined pixels in the - primary array or image extension. This is only used if BITPIX = 8, 16, - 32. or 64 This does not create or change the value of the BLANK keyword in - the header. FTPNULLL is identical to FTPNUL except that the blank - value is a 64-bit integer instead of a 32-bit integer. -\end{description} - -\begin{verbatim} - FTPNUL(unit,blank, > status) - FTPNULLL(unit,blankll, > status) -\end{verbatim} - -\begin{description} -\item[4 ] Define the string to be used to signify undefined pixels in - a column in an ASCII table. This does not create or change the value - of the TNULLn keyword. -\end{description} - -\begin{verbatim} - FTSNUL(unit,colnum,snull > status) -\end{verbatim} - -\begin{description} -\item[5 ] Define the value to be used to signify undefined pixels in - an integer column in a binary table (where TFORMn = 'B', 'I', 'J', or 'K'). - This does not create or change the value of the TNULLn keyword. - FTTNULLL is identical to FTTNUL except that the tnull - value is a 64-bit integer instead of a 32-bit integer. -\end{description} - -\begin{verbatim} - FTTNUL(unit,colnum,tnull > status) - FTTNULLL(unit,colnum,tnullll > status) -\end{verbatim} - - -\section{FITS Primary Array or IMAGE Extension I/O Subroutines \label{FTPPR}} - - These subroutines put or get data values in the primary data array -(i.e., the first HDU in the FITS file) or an IMAGE extension. The -data array is represented as a single one-dimensional array of -pixels regardless of the actual dimensionality of the array, and the -FPIXEL parameter gives the position within this 1-D array of the first -pixel to read or write. Automatic data type conversion is performed -for numeric data (except for complex data types) if the data type of -the primary array (defined by the BITPIX keyword) differs from the data -type of the array in the calling subroutine. The data values are also -scaled by the BSCALE and BZERO header values as they are being written -or read from the FITS array. The ftpscl subroutine MUST be -called to define the scaling parameters when writing data to the FITS -array or to override the default scaling value given in the header when -reading the FITS array. - - Two sets of subroutines are provided to read the data array which -differ in the way undefined pixels are handled. The first set of -routines (FTGPVx) simply return an array of data elements in which -undefined pixels are set equal to a value specified by the user in the -'nullval' parameter. An additional feature of these subroutines is -that if the user sets nullval = 0, then no checks for undefined pixels -will be performed, thus increasing the speed of the program. The -second set of routines (FTGPFx) returns the data element array and, in -addition, a logical array which defines whether the corresponding data -pixel is undefined. The latter set of subroutines may be more -convenient to use in some circumstances, however, it requires an -additional array of logical values which can be unwieldy when working -with large data arrays. Also for programmer convenience, sets of -subroutines to directly read or write 2 and 3 dimensional arrays have -been provided, as well as a set of subroutines to read or write any -contiguous rectangular subset of pixels within the n-dimensional array. - - -\begin{description} -\item[1 ] Get the data type of the image (= BITPIX value). Possible returned - values are: 8, 16, 32, 64, -32, or -64 corresponding to unsigned byte, - signed 2-byte integer, signed 4-byte integer, signed 8-byte integer, - real, and double. - - The second subroutine is similar to FTGIDT, except that if the image - pixel values are scaled, with non-default values for the BZERO and - BSCALE keywords, then this routine will return the 'equivalent' - data type that is needed to store the scaled values. For example, - if BITPIX = 16 and BSCALE = 0.1 then the equivalent data type is - floating point, and -32 will be returned. There are 2 special cases: - if the image contains unsigned 2-byte integer values, with BITPIX = - 16, BSCALE = 1, and BZERO = 32768, then this routine will return - a non-standard value of 20 for the bitpix value. Similarly if the - image contains unsigned 4-byte integers, then bitpix will - be returned with a value of 40. -\end{description} - - -\begin{verbatim} - FTGIDT(unit, > bitpix,status) - FTGIET(unit, > bitpix,status) -\end{verbatim} - -\begin{description} -\item[2 ] Get the dimension (number of axes = NAXIS) of the image -\end{description} - -\begin{verbatim} - FTGIDM(unit, > naxis,status) -\end{verbatim} - -\begin{description} -\item[3 ] Get the size of all the dimensions of the image. The FTGISZLL - routine returns an array of 64-bit integers instead of 32-bit integers. -\end{description} - -\begin{verbatim} - FTGISZ(unit, maxdim, > naxes,status) - FTGISZLL(unit, maxdim, > naxesll,status) -\end{verbatim} - -\begin{description} -\item[4 ] Get the parameters that define the type and size of the image. This - routine simply combines calls to the above 3 routines. The FTGIPRLL - routine returns an array of 64-bit integers instead of 32-bit integers. -\end{description} - - -\begin{verbatim} - FTGIPR(unit, maxdim, > bitpix, naxis, naxes, int *status) - FTGIPRLL(unit, maxdim, > bitpix, naxis, naxesll, int *status) -\end{verbatim} - -\begin{description} -\item[5 ]Put elements into the data array -\end{description} - -\begin{verbatim} - FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) -\end{verbatim} - -\begin{description} -\item[6 ]Put elements into the data array, substituting the appropriate FITS null - value for all elements which are equal to the value of NULLVAL. For - integer FITS arrays, the null value defined by the previous call to FTPNUL - will be substituted; for floating point FITS arrays (BITPIX = -32 - or -64) then the special IEEE NaN (Not-a-Number) value will be - substituted. -\end{description} - -\begin{verbatim} - FTPPN[BIJKED](unit,group,fpixel,nelements,values,nullval > status) -\end{verbatim} - -\begin{description} -\item[7 ]Set data array elements as undefined -\end{description} - -\begin{verbatim} - FTPPRU(unit,group,fpixel,nelements, > status) -\end{verbatim} - -\begin{description} -\item[8 ] Get elements from the data array. Undefined array elements will be - returned with a value = nullval, unless nullval = 0 in which case no - checks for undefined pixels will be performed. -\end{description} - -\begin{verbatim} - FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) -\end{verbatim} - -\begin{description} -\item[9 ] Get elements and nullflags from data array. - Any undefined array elements will have the corresponding flagvals element - set equal to .TRUE. -\end{description} - -\begin{verbatim} - FTGPF[BIJKED](unit,group,fpixel,nelements, > values,flagvals,anyf,status) -\end{verbatim} - -\begin{description} -\item[10] Put values into group parameters -\end{description} - -\begin{verbatim} - FTPGP[BIJKED](unit,group,fparm,nparm,values, > status) -\end{verbatim} - -\begin{description} -\item[11] Get values from group parameters -\end{description} - -\begin{verbatim} - FTGGP[BIJKED](unit,group,fparm,nparm, > values,status) -\end{verbatim} -The following 4 subroutines transfer FITS images with 2 or 3 dimensions -to or from a data array which has been declared in the calling program. -The dimensionality of the FITS image is passed by the naxis1, naxis2, -and naxis3 parameters and the declared dimensions of the program array -are passed in the dim1 and dim2 parameters. Note that the program array -does not have to have the same dimensions as the FITS array, but must -be at least as big. For example if a FITS image with NAXIS1 = NAXIS2 = 400 -is read into a program array which is dimensioned as 512 x 512 pixels, -then the image will just fill the lower left corner of the array -with pixels in the range 1 - 400 in the X an Y directions. This has -the effect of taking a contiguous set of pixel value in the FITS array -and writing them to a non-contiguous array in program memory -(i.e., there are now some blank pixels around the edge of the image -in the program array). - - -\begin{description} -\item[11] Put 2-D image into the data array -\end{description} - -\begin{verbatim} - FTP2D[BIJKED](unit,group,dim1,naxis1,naxis2,image, > status) -\end{verbatim} - -\begin{description} -\item[12] Put 3-D cube into the data array -\end{description} - -\begin{verbatim} - FTP3D[BIJKED](unit,group,dim1,dim2,naxis1,naxis2,naxis3,cube, > status) -\end{verbatim} - -\begin{description} -\item[13] Get 2-D image from the data array. Undefined - pixels in the array will be set equal to the value of 'nullval', - unless nullval=0 in which case no testing for undefined pixels will - be performed. -\end{description} - -\begin{verbatim} - FTG2D[BIJKED](unit,group,nullval,dim1,naxis1,naxis2, > image,anyf,status) -\end{verbatim} - -\begin{description} -\item[14] Get 3-D cube from the data array. Undefined - pixels in the array will be set equal to the value of 'nullval', - unless nullval=0 in which case no testing for undefined pixels will - be performed. -\end{description} - -\begin{verbatim} - FTG3D[BIJKED](unit,group,nullval,dim1,dim2,naxis1,naxis2,naxis3, > - cube,anyf,status) -\end{verbatim} - -The following subroutines transfer a rectangular subset of the pixels -in a FITS N-dimensional image to or from an array which has been -declared in the calling program. The fpixels and lpixels parameters -are integer arrays which specify the starting and ending pixels in each -dimension of the FITS image that are to be read or written. (Note that -these are the starting and ending pixels in the FITS image, not in the -declared array). The array parameter is treated simply as a large -one-dimensional array of the appropriate datatype containing the pixel -values; The pixel values in the FITS array are read/written from/to -this program array in strict sequence without any gaps; it is up to -the calling routine to correctly interpret the dimensionality of this -array. The two families of FITS reading routines (FTGSVx and FTGSFx -subroutines) also have an 'incs' parameter which defines the -data sampling interval in each dimension of the FITS array. For -example, if incs(1)=2 and incs(2)=3 when reading a 2-dimensional -FITS image, then only every other pixel in the first dimension -and every 3rd pixel in the second dimension will be returned in -the 'array' parameter. [Note: the FTGSSx family of routines which -were present in previous versions of FITSIO have been superseded -by the more general FTGSVx family of routines.] - - -\begin{description} -\item[15] Put an arbitrary data subsection into the data array. -\end{description} - -\begin{verbatim} - FTPSS[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,array, > status) -\end{verbatim} - -\begin{description} -\item[16] Get an arbitrary data subsection from the data array. Undefined - pixels in the array will be set equal to the value of 'nullval', - unless nullval=0 in which case no testing for undefined pixels will - be performed. -\end{description} - -\begin{verbatim} - FTGSV[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs,nullval, > - array,anyf,status) -\end{verbatim} - -\begin{description} -\item[17] Get an arbitrary data subsection from the data array. Any Undefined - pixels in the array will have the corresponding 'flagvals' - element set equal to .TRUE. -\end{description} - -\begin{verbatim} - FTGSF[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs, > - array,flagvals,anyf,status) -\end{verbatim} - - -\section{FITS ASCII and Binary Table Data I/O Subroutines} - - -\subsection{Column Information Subroutines \label{FTGCNO}} - - -\begin{description} -\item[1 ] Get the number of rows or columns in the current FITS table. - The number of rows is given by the NAXIS2 keyword and the - number of columns is given by the TFIELDS keyword in the header - of the table. The FTGNRWLL routine is identical to FTGNRW except - that the number of rows is returned as a 64-bit integer rather - than a 32-bit integer. -\end{description} - -\begin{verbatim} - FTGNRW(unit, > nrows, status) - FTGNRWLL(unit, > nrowsll, status) - FTGNCL(unit, > ncols, status) -\end{verbatim} - -\begin{description} -\item[2 ] Get the table column number (and name) of the column whose name -matches an input template name. The table column names are defined by -the TTYPEn keywords in the FITS header. If a column does not have a -TTYPEn keyword, then these routines assume that the name consists of -all blank characters. These 2 subroutines perform the same function -except that FTGCNO only returns the number of the matching column whereas -FTGCNN also returns the name of the column. If CASESEN = .true. then -the column name match will be case-sensitive. - -The input column name template (COLTEMPLATE) is (1) either the exact -name of the column to be searched for, or (2) it may contain wild cards -characters (*, ?, or \#), or (3) it may contain the number of the desired -column (where the number is expressed as ASCII digits). The first 2 wild -cards behave similarly to UNIX filename matching: the '*' character matches -any sequence of characters (including zero characters) and the '?' -character matches any single character. The \# wildcard will match -any consecutive string of decimal digits (0-9). As an example, the template -strings 'AB?DE', 'AB*E', and 'AB*CDE' will all match the string -'ABCDE'. If more than one column name in the table matches the -template string, then the first match is returned and the status value -will be set to 237 as a warning that a unique match was not found. To -find the other cases that match the template, simply call the -subroutine again leaving the input status value equal to 237 and the -next matching name will then be returned. Repeat this process until a -status = 219 (column name not found) is returned. If these subroutines -fail to match the template to any of the columns in the table, they -lastly check if the template can be interpreted as a simple positive -integer (e.g., '7', or '512') and if so, they return that column -number. If no matches are found then a status = 219 error is -returned. - -Note that the FITS Standard recommends that only letters, digits, and -the underscore character be used in column names (with no embedded -spaces in the name). Trailing blank characters are not significant. -\end{description} - -\begin{verbatim} - FTGCNO(unit,casesen,coltemplate, > colnum,status) - FTGCNN(unit,casesen,coltemplate, > colname,colnum,status) -\end{verbatim} - -\begin{description} -\item[3 ] Get the datatype of a column in an ASCII or binary table. This - routine returns an integer code value corresponding to the datatype - of the column. (See the FTBNFM and FTASFM subroutines in the Utilities - section of this document for a list of the code values). The vector - repeat count (which is alway 1 for ASCII table columns) is also returned. - If the specified column has an ASCII character datatype (code = 16) then - the width of a unit string in the column is also returned. Note that - this routine supports the local convention for specifying arrays of - strings within a binary table character column, using the syntax - TFORM = 'rAw' where 'r' is the total number of characters (= the width - of the column) and 'w' is the width of a unit string within the column. - Thus if the column has TFORM = '60A12' then this routine will return - datacode = 16, repeat = 60, and width = 12. (The TDIMn - keyword may also be used to specify the unit string length; The pair - of keywords TFORMn = '60A' and TDIMn = '(12,5)' would have the - same effect as TFORMn = '60A12'). - - The second routine, FTEQTY is similar except that in - the case of scaled integer columns it returns the 'equivalent' data - type that is needed to store the scaled values, and not necessarily - the physical data type of the unscaled values as stored in the FITS - table. For example if a '1I' column in a binary table has TSCALn = - 1 and TZEROn = 32768, then this column effectively contains unsigned - short integer values, and thus the returned value of typecode will - be the code for an unsigned short integer, not a signed short integer. - Similarly, if a column has TTYPEn = '1I' - and TSCALn = 0.12, then the returned typecode - will be the code for a 'real' column. -\end{description} - -\begin{verbatim} - FTGTCL(unit,colnum, > datacode,repeat,width,status) - FTEQTY(unit,colnum, > datacode,repeat,width,status) -\end{verbatim} - -\begin{description} -\item[4 ] Return the display width of a column. This is the length - of the string that will be returned - when reading the column as a formatted string. The display width is - determined by the TDISPn keyword, if present, otherwise by the data - type of the column. -\end{description} - -\begin{verbatim} - FTGCDW(unit, colnum, > dispwidth, status) -\end{verbatim} - -\begin{description} -\item[5 ] Get information about an existing ASCII table column. (NOTE: TSCAL and - TZERO must be declared as Double Precision variables). All the - returned parameters are scalar quantities. -\end{description} - -\begin{verbatim} - FTGACL(unit,colnum, > - ttype,tbcol,tunit,tform,tscal,tzero,snull,tdisp,status) -\end{verbatim} - -\begin{description} -\item[6 ] Get information about an existing binary table column. (NOTE: TSCAL and - TZERO must be declared as Double Precision variables). DATATYPE is a - character string which returns the datatype of the column as defined - by the TFORMn keyword (e.g., 'I', 'J','E', 'D', etc.). In the case - of an ASCII character column, DATATYPE will have a value of the - form 'An' where 'n' is an integer expressing the width of the field - in characters. For example, if TFORM = '160A8' then FTGBCL will return - DATATYPE='A8' and REPEAT=20. All the returned parameters are scalar - quantities. -\end{description} - -\begin{verbatim} - FTGBCL(unit,colnum, > - ttype,tunit,datatype,repeat,tscal,tzero,tnull,tdisp,status) -\end{verbatim} - -\begin{description} -\item[7 ] Put (append) a TDIMn keyword whose value has the form '(l,m,n...)' - where l, m, n... are the dimensions of a multidimensional array - column in a binary table. -\end{description} - -\begin{verbatim} - FTPTDM(unit,colnum,naxis,naxes, > status) -\end{verbatim} - -\begin{description} -\item[8 ] Return the number of and size of the dimensions of a table column. - Normally this information is given by the TDIMn keyword, but if - this keyword is not present then this routine returns NAXIS = 1 - and NAXES(1) equal to the repeat count in the TFORM keyword. -\end{description} - -\begin{verbatim} - FTGTDM(unit,colnum,maxdim, > naxis,naxes,status) -\end{verbatim} - -\begin{description} -\item[9 ] Decode the input TDIMn keyword string (e.g. '(100,200)') and return the - number of and size of the dimensions of a binary table column. If the input - tdimstr character string is null, then this routine returns naxis = 1 - and naxes[0] equal to the repeat count in the TFORM keyword. This routine - is called by FTGTDM. -\end{description} - -\begin{verbatim} - FTDTDM(unit,tdimstr,colnum,maxdim, > naxis,naxes, status) -\end{verbatim} - -\begin{description} -\item[10] Return the optimal number of rows to read or write at one time for - maximum I/O efficiency. Refer to the ``Optimizing Code'' section - in Chapter 5 for more discussion on how to use this routine. -\end{description} - - -\begin{verbatim} - FTGRSZ(unit, > nrows,status) -\end{verbatim} - - -\subsection{Low-Level Table Access Subroutines \label{FTGTBS}} - -The following subroutines provide low-level access to the data in ASCII -or binary tables and are mainly useful as an efficient way to copy all -or part of a table from one location to another. These routines simply -read or write the specified number of consecutive bytes in an ASCII or -binary table, without regard for column boundaries or the row length in -the table. The first two subroutines read or write consecutive bytes -in a table to or from a character string variable, while the last two -subroutines read or write consecutive bytes to or from a variable -declared as a numeric data type (e.g., INTEGER, INTEGER*2, REAL, DOUBLE -PRECISION). These routines do not perform any machine dependent data -conversion or byte swapping, except that conversion to/from ASCII -format is performed by the FTGTBS and FTPTBS routines on machines which -do not use ASCII character codes in the internal data representations -(e.g., on IBM mainframe computers). - - -\begin{description} -\item[1 ] Read a consecutive string of characters from an ASCII table - into a character variable (spanning columns and multiple rows if necessary) - This routine should not be used with binary tables because of - complications related to passing string variables between C and Fortran. -\end{description} - -\begin{verbatim} - FTGTBS(unit,frow,startchar,nchars, > string,status) -\end{verbatim} - -\begin{description} -\item[2 ] Write a consecutive string of characters to an ASCII table - from a character variable (spanning columns and multiple rows if necessary) - This routine should not be used with binary tables because of - complications related to passing string variables between C and Fortran. -\end{description} - -\begin{verbatim} - FTPTBS(unit,frow,startchar,nchars,string, > status) -\end{verbatim} - -\begin{description} -\item[3 ] Read a consecutive array of bytes from an ASCII or binary table - into a numeric variable (spanning columns and multiple rows if necessary). - The array parameter may be declared as any numerical datatype as long - as the array is at least 'nchars' bytes long, e.g., if nchars = 17, - then declare the array as INTEGER*4 ARRAY(5). -\end{description} - -\begin{verbatim} - FTGTBB(unit,frow,startchar,nchars, > array,status) -\end{verbatim} - -\begin{description} -\item[4 ] Write a consecutive array of bytes to an ASCII or binary table - from a numeric variable (spanning columns and multiple rows if necessary) - The array parameter may be declared as any numerical datatype as long - as the array is at least 'nchars' bytes long, e.g., if nchars = 17, - then declare the array as INTEGER*4 ARRAY(5). -\end{description} - -\begin{verbatim} - FTPTBB(unit,frow,startchar,nchars,array, > status) -\end{verbatim} - - -\subsection{Edit Rows or Columns \label{FTIROW}} - - -\begin{description} -\item[1 ] Insert blank rows into an existing ASCII or binary table (in the CDU). - All the rows FOLLOWING row FROW are shifted down by NROWS rows. If - FROW or FROWLL equals 0 then the blank rows are inserted at the beginning of the - table. These routines modify the NAXIS2 keyword to reflect the new - number of rows in the table. Note that it is *not* necessary to insert rows in a table before - writing data to those rows (indeed, it would be inefficient to do so). - Instead, one may simply write data to any row of the table, whether that - row of data already exists or not. -\end{description} - -\begin{verbatim} - FTIROW(unit,frow,nrows, > status) - FTIROWLL(unit,frowll,nrowsll, > status) -\end{verbatim} - -\begin{description} -\item[2 ] Delete rows from an existing ASCII or binary table (in the CDU). - The NROWS (or NROWSLL) is the number of rows are deleted, starting - with row FROW (or FROWLL), and - any remaining rows in the table are shifted up to fill in the space. - These routines modify the NAXIS2 keyword to reflect the new number - of rows in the table. -\end{description} - -\begin{verbatim} - FTDROW(unit,frow,nrows, > status) - FTDROWLL(unit,frowll,nrowsll, > status) -\end{verbatim} - -\begin{description} -\item[3 ] Delete a list of rows from an ASCII or binary table (in the CDU). - In the first routine, 'rowrange' is a character string listing the - rows or row ranges to delete (e.g., '2-4, 5, 8-9'). In the second - routine, 'rowlist' is an integer array of row numbers to be deleted - from the table. nrows is the number of row numbers in the list. - The first row in the table is 1 not 0. The list of row numbers - must be sorted in ascending order. -\end{description} - -\begin{verbatim} - FTDRRG(unit,rowrange, > status) - FTDRWS(unit,rowlist,nrows, > status) -\end{verbatim} - -\begin{description} -\item[4 ] Insert a blank column (or columns) into an existing ASCII or binary - table (in the CDU). COLNUM specifies the column number that the (first) - new column should occupy in the table. NCOLS specifies how many - columns are to be inserted. Any existing columns from this position and - higher are moved over to allow room for the new column(s). - The index number on all the following keywords will be incremented - if necessary to reflect the new position of the column(s) in the table: - TBCOLn, TFORMn, TTYPEn, TUNITn, TNULLn, TSCALn, TZEROn, TDISPn, TDIMn, - TLMINn, TLMAXn, TDMINn, TDMAXn, TCTYPn, TCRPXn, TCRVLn, TCDLTn, TCROTn, - and TCUNIn. -\end{description} - -\begin{verbatim} - FTICOL(unit,colnum,ttype,tform, > status) - FTICLS(unit,colnum,ncols,ttype,tform, > status) -\end{verbatim} - -\begin{description} -\item[5 ] Modify the vector length of a binary table column (e.g., - change a column from TFORMn = '1E' to '20E'). The vector - length may be increased or decreased from the current value. -\end{description} - -\begin{verbatim} - FTMVEC(unit,colnum,newveclen, > status) -\end{verbatim} - -\begin{description} -\item[6 ] Delete a column from an existing ASCII or binary table (in the CDU). - The index number of all the keywords listed above (for FTICOL) will be - decremented if necessary to reflect the new position of the column(s) in - the table. Those index keywords that refer to the deleted column will - also be deleted. Note that the physical size of the FITS file will - not be reduced by this operation, and the empty FITS blocks if any - at the end of the file will be padded with zeros. -\end{description} - -\begin{verbatim} - FTDCOL(unit,colnum, > status) -\end{verbatim} - -\begin{description} -\item[7 ] Copy a column from one HDU to another (or to the same HDU). If - createcol = TRUE, then a new column will be inserted in the output - table, at position `outcolumn', otherwise the existing output column will - be overwritten (in which case it must have a compatible datatype). - Note that the first column in a table is at colnum = 1. -\end{description} - -\begin{verbatim} - FTCPCL(inunit,outunit,incolnum,outcolnum,createcol, > status); -\end{verbatim} - -\subsection{Read and Write Column Data Routines \label{FTPCLS}} - -These subroutines put or get data values in the current ASCII or Binary table -extension. Automatic data type conversion is performed for numerical data -types (B,I,J,E,D) if the data type of the column (defined by the TFORM keyword) -differs from the data type of the calling subroutine. The data values are also -scaled by the TSCALn and TZEROn header values as they are being written to -or read from the FITS array. The fttscl subroutine MUST be used to define the -scaling parameters when writing data to the table or to override the default -scaling values given in the header when reading from the table. -Note that it is *not* necessary to insert rows in a table before -writing data to those rows (indeed, it would be inefficient to do so). -Instead, one may simply write data to any row of the table, whether that -row of data already exists or not. - - In the case of binary tables with vector elements, the 'felem' -parameter defines the starting pixel within the element vector. This -parameter is ignored with ASCII tables. Similarly, in the case of -binary tables the 'nelements' parameter specifies the total number of -vector values read or written (continuing on subsequent rows if -required) and not the number of table elements. Two sets of -subroutines are provided to get the column data which differ in the way -undefined pixels are handled. The first set of routines (FTGCV) -simply return an array of data elements in which undefined pixels are -set equal to a value specified by the user in the 'nullval' parameter. -An additional feature of these subroutines is that if the user sets -nullval = 0, then no checks for undefined pixels will be performed, -thus increasing the speed of the program. The second set of routines -(FTGCF) returns the data element array and in addition a logical array -of flags which defines whether the corresponding data pixel is undefined. - - Any column, regardless of it's intrinsic datatype, may be read as a - string. It should be noted however that reading a numeric column - as a string is 10 - 100 times slower than reading the same column as - a number due to the large overhead in constructing the formatted - strings. The display format of the returned strings will be - determined by the TDISPn keyword, if it exists, otherwise by the - datatype of the column. The length of the returned strings can be - determined with the ftgcdw routine. The following TDISPn display - formats are currently supported: - -\begin{verbatim} - Iw.m Integer - Ow.m Octal integer - Zw.m Hexadecimal integer - Fw.d Fixed floating point - Ew.d Exponential floating point - Dw.d Exponential floating point - Gw.d General; uses Fw.d if significance not lost, else Ew.d -\end{verbatim} - where w is the width in characters of the displayed values, m is the minimum - number of digits displayed, and d is the number of digits to the right of the - decimal. The .m field is optional. - - -\begin{description} -\item[1 ] Put elements into an ASCII or binary table column (in the CDU). - (The SPP FSPCLS routine has an additional integer argument after - the VALUES character string which specifies the size of the 1st - dimension of this 2-D CHAR array). - - The alternate version of these routines, whose names end in 'LL' - after the datatype character, support large tables with more then - 2*31 rows. When calling these routines, the frow and felem parameters - *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. -\end{description} - -\begin{verbatim} - FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) - FTPCL[LBIJKEDCM]LL(unit,colnum,frow,felem,nelements,values, > status) -\end{verbatim} - -\begin{description} -\item[2 ] Put elements into an ASCII or binary table column (in the CDU) - substituting the appropriate FITS null value for any elements that - are equal to NULLVAL. For ASCII TABLE extensions, the - null value defined by the previous call to FTSNUL will be substituted; - For integer FITS columns, in a binary table the null value - defined by the previous call to FTTNUL will be substituted; - For floating point FITS columns a special IEEE NaN (Not-a-Number) - value will be substituted. - - The alternate version of these routines, whose names end in 'LL' - after the datatype character, support large tables with more then - 2*31 rows. When calling these routines, the frow and felem parameters - *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. -\end{description} - -\begin{verbatim} - FTPCN[SBIJKED](unit,colnum,frow,felem,nelements,values,nullval > status) - FTPCN[SBIJKED]LL(unit,colnum,(I*8) frow,(I*8) felem,nelements,values, - nullval > status) -\end{verbatim} - -\begin{description} -\item[3 ] Put bit values into a binary byte ('B') or bit ('X') table column (in the - CDU). LRAY is an array of logical values corresponding to the sequence of - bits to be written. If LRAY is true then the corresponding bit is - set to 1, otherwise the bit is set to 0. Note that in the case of - 'X' columns, FITSIO will write to all 8 bits of each byte whether - they are formally valid or not. Thus if the column is defined as - '4X', and one calls FTPCLX with fbit=1 and nbit=8, then all 8 bits - will be written into the first byte (as opposed to writing the - first 4 bits into the first row and then the next 4 bits into the - next row), even though the last 4 bits of each byte are formally - not defined. -\end{description} - -\begin{verbatim} - FTPCLX(unit,colnum,frow,fbit,nbit,lray, > status) -\end{verbatim} - -\begin{description} -\item[4 ] Set table elements in a column as undefined -\end{description} - -\begin{verbatim} - FTPCLU(unit,colnum,frow,felem,nelements, > status) -\end{verbatim} - -\begin{description} -\item[5 ] Get elements from an ASCII or binary table column (in the CDU). These - routines return the values of the table column array elements. Undefined - array elements will be returned with a value = nullval, unless nullval = 0 - (or = ' ' for ftgcvs) in which case no checking for undefined values will - be performed. The ANYF parameter is set to true if any of the returned - elements are undefined. (Note: the ftgcl routine simple gets an array - of logical data values without any checks for undefined values; use - the ftgcfl routine to check for undefined logical elements). - (The SPP FSGCVS routine has an additional integer argument after - the VALUES character string which specifies the size of the 1st - dimension of this 2-D CHAR array). - - The alternate version of these routines, whose names end in 'LL' - after the datatype character, support large tables with more then - 2*31 rows. When calling these routines, the frow and felem parameters - *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. -\end{description} - -\begin{verbatim} - FTGCL(unit,colnum,frow,felem,nelements, > values,status) - FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > - values,anyf,status) - FTGCV[BIJKEDCM]LL(unit,colnum,(I*8) frow, (I*8) felem, nelements, - nullval, > values,anyf,status) -\end{verbatim} - -\begin{description} -\item[6 ] Get elements and null flags from an ASCII or binary table column (in the - CHDU). These routines return the values of the table column array elements. - Any undefined array elements will have the corresponding flagvals element - set equal to .TRUE. The ANYF parameter is set to true if any of the - returned elements are undefined. - (The SPP FSGCFS routine has an additional integer argument after - the VALUES character string which specifies the size of the 1st - dimension of this 2-D CHAR array). - - The alternate version of these routines, whose names end in 'LL' - after the datatype character, support large tables with more then - 2*31 rows. When calling these routines, the frow and felem parameters - *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. -\end{description} - -\begin{verbatim} - FTGCF[SLBIJKEDCM](unit,colnum,frow,felem,nelements, > - values,flagvals,anyf,status) - FTGCF[BIJKED]LL(unit,colnum, (I*8) frow, (I*8) felem,nelements, > - values,flagvals,anyf,status) -\end{verbatim} - -\begin{description} -\item[7 ] Get an arbitrary data subsection from an N-dimensional array - in a binary table vector column. Undefined pixels - in the array will be set equal to the value of 'nullval', - unless nullval=0 in which case no testing for undefined pixels will - be performed. The first and last rows in the table to be read - are specified by fpixels(naxis+1) and lpixels(naxis+1), and hence - are treated as the next higher dimension of the FITS N-dimensional - array. The INCS parameter specifies the sampling interval in - each dimension between the data elements that will be returned. -\end{description} - -\begin{verbatim} - FTGSV[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs,nullval, > - array,anyf,status) -\end{verbatim} - -\begin{description} -\item[8 ] Get an arbitrary data subsection from an N-dimensional array - in a binary table vector column. Any Undefined - pixels in the array will have the corresponding 'flagvals' - element set equal to .TRUE. The first and last rows in the table - to be read are specified by fpixels(naxis+1) and lpixels(naxis+1), - and hence are treated as the next higher dimension of the FITS - N-dimensional array. The INCS parameter specifies the sampling - interval in each dimension between the data elements that will be - returned. -\end{description} - -\begin{verbatim} - FTGSF[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs, > - array,flagvals,anyf,status) -\end{verbatim} - -\begin{description} -\item[9 ] Get bit values from a byte ('B') or bit (`X`) table column (in the - CDU). LRAY is an array of logical values corresponding to the - sequence of bits to be read. If LRAY is true then the - corresponding bit was set to 1, otherwise the bit was set to 0. - Note that in the case of 'X' columns, FITSIO will read all 8 bits - of each byte whether they are formally valid or not. Thus if the - column is defined as '4X', and one calls FTGCX with fbit=1 and - nbit=8, then all 8 bits will be read from the first byte (as - opposed to reading the first 4 bits from the first row and then the - first 4 bits from the next row), even though the last 4 bits of - each byte are formally not defined. -\end{description} - -\begin{verbatim} - FTGCX(unit,colnum,frow,fbit,nbit, > lray,status) -\end{verbatim} - -\begin{description} -\item[10] Read any consecutive set of bits from an 'X' or 'B' column and - interpret them as an unsigned n-bit integer. NBIT must be less than - or equal to 16 when calling FTGCXI, and less than or equal to 32 when - calling FTGCXJ; there is no limit on the value of NBIT for FTGCXD, but - the returned double precision value only has 48 bits of precision on - most 32-bit word machines. The NBITS bits are interpreted as an - unsigned integer unless NBITS = 16 (in FTGCXI) or 32 (in FTGCXJ) in which - case the string of bits are interpreted as 16-bit or 32-bit 2's - complement signed integers. If NROWS is greater than 1 then the - same set of bits will be read from sequential rows in the table - starting with row FROW. Note that the numbering convention - used here for the FBIT parameter adopts 1 for the first element of the - vector of bits; this is the Most Significant Bit of the integer value. -\end{description} - -\begin{verbatim} - FTGCX[IJD](unit,colnum,frow,nrows,fbit,nbit, > array,status) -\end{verbatim} - -\begin{description} -\item[11] Get the descriptor for a variable length column in a binary table. - The descriptor consists of 2 integer parameters: the number of elements - in the array and the starting offset relative to the start of the heap. - The first routine returns a single descriptor whereas the second routine - returns the descriptors for a range of rows in the table. -\end{description} - -\begin{verbatim} - FTGDES(unit,colnum,rownum, > nelements,offset,status) - FTGDESLL(unit,colnum,rownum, > nelementsll,offsetll,status) - - FTGDESS(unit,colnum,firstrow,nrows > nelements,offset, status) - FTGDESSLL(unit,colnum,firstrow,nrows > nelementsll,offsetll, status) -\end{verbatim} - -\begin{description} -\item[12] Write the descriptor for a variable length column in a binary table. - These subroutines can be used in conjunction with FTGDES to enable - 2 or more arrays to point to the same storage location to save - storage space if the arrays are identical. -\end{description} - -\begin{verbatim} - FTPDES(unit,colnum,rownum,nelements,offset, > status) - FTPDESLL(unit,colnum,rownum,nelementsll,offsetll, > status) -\end{verbatim} - - -\section{Row Selection and Calculator Routines \label{FTFROW}} - -These routines all parse and evaluate an input string containing a user -defined arithmetic expression. The first 3 routines select rows in a -FITS table, based on whether the expression evaluates to true (not -equal to zero) or false (zero). The other routines evaluate the -expression and calculate a value for each row of the table. The -allowed expression syntax is described in the row filter section in the -earlier `Extended File Name Syntax' chapter of this document. The -expression may also be written to a text file, and the name of the -file, prepended with a '@' character may be supplied for the 'expr' -parameter (e.g. '@filename.txt'). The expression in the file can -be arbitrarily complex and extend over multiple lines of the file. -Lines that begin with 2 slash characters ('//') will be ignored and -may be used to add comments to the file. - - -\begin{description} -\item[1 ] Evaluate a boolean expression over the indicated rows, returning an - array of flags indicating which rows evaluated to TRUE/FALSE -\end{description} - -\begin{verbatim} - FTFROW(unit,expr,firstrow, nrows, > n_good_rows, row_status, status) -\end{verbatim} - -\begin{description} -\item[2 ] Find the first row which satisfies the input boolean expression -\end{description} - -\begin{verbatim} - FTFFRW(unit, expr, > rownum, status) -\end{verbatim} - -\begin{description} -\item[3 ]Evaluate an expression on all rows of a table. If the input and output -files are not the same, copy the TRUE rows to the output file; if the output -table is not empty, then this routine will append the new -selected rows after the existing rows. If the -files are the same, delete the FALSE rows (preserve the TRUE rows). -\end{description} - -\begin{verbatim} - FTSROW(inunit, outunit, expr, > status) -\end{verbatim} - -\begin{description} -\item[4 ] Calculate an expression for the indicated rows of a table, returning -the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If -nulval==NULL, UNDEFs will be zeroed out. For vector results, the number -of elements returned may be less than nelements if nelements is not an -even multiple of the result dimension. Call FTTEXP to obtain -the dimensions of the results. -\end{description} - -\begin{verbatim} - FTCROW(unit,datatype,expr,firstrow,nelements,nulval, > - array,anynul,status) -\end{verbatim} - -\begin{description} -\item[5 ]Evaluate an expression and write the result either to a column (if -the expression is a function of other columns in the table) or to a -keyword (if the expression evaluates to a constant and is not a -function of other columns in the table). In the former case, the -parName parameter is the name of the column (which may or may not already -exist) into which to write the results, and parInfo contains an -optional TFORM keyword value if a new column is being created. If a -TFORM value is not specified then a default format will be used, -depending on the expression. If the expression evaluates to a constant, -then the result will be written to the keyword name given by the -parName parameter, and the parInfo parameter may be used to supply an -optional comment for the keyword. If the keyword does not already -exist, then the name of the keyword must be preceded with a '\#' character, -otherwise the result will be written to a column with that name. -\end{description} - - -\begin{verbatim} - FTCALC(inunit, expr, outunit, parName, parInfo, > status) -\end{verbatim} - -\begin{description} -\item[6 ] This calculator routine is similar to the previous routine, except -that the expression is only evaluated over the specified -row ranges. nranges specifies the number of row ranges, and firstrow -and lastrow give the starting and ending row number of each range. -\end{description} - -\begin{verbatim} - FTCALC_RNG(inunit, expr, outunit, parName, parInfo, - nranges, firstrow, lastrow, > status) -\end{verbatim} - -\begin{description} -\item[7 ]Evaluate the given expression and return dimension and type information -on the result. The returned dimensions correspond to a single row entry -of the requested expression, and are equivalent to the result of fits\_read\_tdim(). -Note that strings are considered to be one element regardless of string length. -If maxdim == 0, then naxes is optional. -\end{description} - -\begin{verbatim} - FTTEXP(unit, expr, maxdim > datatype, nelem, naxis, naxes, status) -\end{verbatim} - - - -\section{Celestial Coordinate System Subroutines \label{FTGICS}} - -The FITS community has adopted a set of keyword conventions that define -the transformations needed to convert between pixel locations in an -image and the corresponding celestial coordinates on the sky, or more -generally, that define world coordinates that are to be associated with -any pixel location in an n-dimensional FITS array. CFITSIO is distributed -with a couple of self-contained World Coordinate System (WCS) routines, -however, these routines DO NOT support all the latest WCS conventions, -so it is STRONGLY RECOMMENDED that software developers use a more robust -external WCS library. Several recommended libraries are: - -\begin{verbatim} - WCSLIB - supported by Mark Calabretta - WCSTools - supported by Doug Mink - AST library - developed by the U.K. Starlink project -\end{verbatim} - -More information about the WCS keyword conventions and links to all of -these WCS libraries can be found on the FITS Support Office web site at -http://fits.gsfc.nasa.gov under the WCS link. - -The functions provided in these external WCS libraries will need access to -the WCS information contained in the FITS file headers. One convenient -way to pass this information to the external library is to use FITSIO -to copy the header keywords into one long character string, and then -pass this string to an interface routine in the external library that -will extract the necessary WCS information (e.g., see the astFitsChan -and astPutCards routines in the Starlink AST library). - -The following FITSIO routines DO NOT support the more recent WCS conventions -that have been approved as part of the FITS standard. Consequently, -the following routines ARE NOW DEPRECATED. It is STRONGLY RECOMMENDED -that software developers not use these routines, and instead use an -external WCS library, as described above. - -These routines are included mainly for backward compatibility with -existing software. They support the following standard map -projections: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, and -AIT (these are the -legal values for the coordtype parameter). These routines are based -on similar functions in Classic AIPS. All the angular quantities are -given in units of degrees. - - -\begin{description} -\item[1 ] Get the values of all the standard FITS celestial coordinate system - keywords from the header of a FITS image (i.e., the primary array or - an image extension). These values may then be passed to the subroutines - that perform the coordinate transformations. If any or all of the WCS - keywords are not present, then default values will be returned. If - the first coordinate axis is the declination-like coordinate, then - this routine will swap them so that the longitudinal-like coordinate - is returned as the first axis. - - If the file uses the newer 'CDj\_i' WCS transformation matrix - keywords instead of old style 'CDELTn' and 'CROTA2' keywords, then - this routine will calculate and return the values of the equivalent - old-style keywords. Note that the conversion from the new-style - keywords to the old-style values is sometimes only an - approximation, so if the approximation is larger than an internally - defined threshold level, then CFITSIO will still return the - approximate WCS keyword values, but will also return with status = - 506, to warn the calling program that approximations have been - made. It is then up to the calling program to decide whether the - approximations are sufficiently accurate for the particular - application, or whether more precise WCS transformations must be - performed using new-style WCS keywords directly. -\end{description} - -\begin{verbatim} - FTGICS(unit, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) -\end{verbatim} - -\begin{description} -\item[2 ] Get the values of all the standard FITS celestial coordinate system - keywords from the header of a FITS table where the X and Y (or RA and - DEC coordinates are stored in 2 separate columns of the table. - These values may then be passed to the subroutines that perform the - coordinate transformations. -\end{description} - -\begin{verbatim} - FTGTCS(unit,xcol,ycol, > - xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) -\end{verbatim} - -\begin{description} -\item[3 ] Calculate the celestial coordinate corresponding to the input - X and Y pixel location in the image. -\end{description} - -\begin{verbatim} - FTWLDP(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, - coordtype, > xpos,ypos,status) -\end{verbatim} - -\begin{description} -\item[4 ] Calculate the X and Y pixel location corresponding to the input - celestial coordinate in the image. -\end{description} - -\begin{verbatim} - FTXYPX(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, - coordtype, > xpix,ypix,status) -\end{verbatim} - - -\section{File Checksum Subroutines \label{FTPCKS}} - -The following routines either compute or validate the checksums for the -CHDU. The DATASUM keyword is used to store the numerical value of the -32-bit, 1's complement checksum for the data unit alone. If there is -no data unit then the value is set to zero. The numerical value is -stored as an ASCII string of digits, enclosed in quotes, because the -value may be too large to represent as a 32-bit signed integer. The -CHECKSUM keyword is used to store the ASCII encoded COMPLEMENT of the -checksum for the entire HDU. Storing the complement, rather than the -actual checksum, forces the checksum for the whole HDU to equal zero. -If the file has been modified since the checksums were computed, then -the HDU checksum will usually not equal zero. These checksum keyword -conventions are based on a paper by Rob Seaman published in the -proceedings of the ADASS IV conference in Baltimore in November 1994 -and a later revision in June 1995. - - -\begin{description} -\item[1 ] Compute and write the DATASUM and CHECKSUM keyword values for the CHDU - into the current header. The DATASUM value is the 32-bit checksum - for the data unit, expressed as a decimal integer enclosed in single - quotes. The CHECKSUM keyword value is a 16-character string which - is the ASCII-encoded value for the complement of the checksum for - the whole HDU. If these keywords already exist, their values - will be updated only if necessary (i.e., if the file has been modified - since the original keyword values were computed). -\end{description} - -\begin{verbatim} - FTPCKS(unit, > status) -\end{verbatim} - -\begin{description} -\item[2 ] Update the CHECKSUM keyword value in the CHDU, assuming that the - DATASUM keyword exists and already has the correct value. This routine - calculates the new checksum for the current header unit, adds it to the - data unit checksum, encodes the value into an ASCII string, and writes - the string to the CHECKSUM keyword. -\end{description} - -\begin{verbatim} - FTUCKS(unit, > status) -\end{verbatim} - -\begin{description} -\item[3 ] Verify the CHDU by computing the checksums and comparing - them with the keywords. The data unit is verified correctly - if the computed checksum equals the value of the DATASUM - keyword. The checksum for the entire HDU (header plus data unit) is - correct if it equals zero. The output DATAOK and HDUOK parameters - in this subroutine are integers which will have a value = 1 - if the data or HDU is verified correctly, a value = 0 - if the DATASUM or CHECKSUM keyword is not present, or value = -1 - if the computed checksum is not correct. -\end{description} - -\begin{verbatim} - FTVCKS(unit, > dataok,hduok,status) -\end{verbatim} - -\begin{description} -\item[4 ] Compute and return the checksum values for the CHDU (as - double precision variables) without creating or modifying the - CHECKSUM and DATASUM keywords. This routine is used internally by - FTVCKS, but may be useful in other situations as well. -\end{description} - -\begin{verbatim} - FTGCKS(unit, > datasum,hdusum,status) -\end{verbatim} - -\begin{description} -\item[5 ] Encode a checksum value (stored in a double precision variable) - into a 16-character string. If COMPLEMENT = .true. then the 32-bit - sum value will be complemented before encoding. -\end{description} - -\begin{verbatim} - FTESUM(sum,complement, > checksum) -\end{verbatim} - -\begin{description} -\item[6 ] Decode a 16 character checksum string into a double precision value. - If COMPLEMENT = .true. then the 32-bit sum value will be complemented - after decoding. -\end{description} - -\begin{verbatim} - FTDSUM(checksum,complement, > sum) -\end{verbatim} - - -\section{ Date and Time Utility Routines \label{FTGSDT}} - -The following routines help to construct or parse the FITS date/time -strings. Starting in the year 2000, the FITS DATE keyword values (and -the values of other `DATE-' keywords) must have the form 'YYYY-MM-DD' -(date only) or 'YYYY-MM-DDThh:mm:ss.ddd...' (date and time) where the -number of decimal places in the seconds value is optional. These times -are in UTC. The older 'dd/mm/yy' date format may not be used for dates -after 01 January 2000. - - -\begin{description} -\item[1 ] Get the current system date. The returned year has 4 digits - (1999, 2000, etc.) -\end{description} - -\begin{verbatim} - FTGSDT( > day, month, year, status ) -\end{verbatim} - - -\begin{description} -\item[2 ] Get the current system date and time string ('YYYY-MM-DDThh:mm:ss'). -The time will be in UTC/GMT if available, as indicated by a returned timeref -value = 0. If the returned value of timeref = 1 then this indicates that -it was not possible to convert the local time to UTC, and thus the local -time was returned. -\end{description} - -\begin{verbatim} - FTGSTM(> datestr, timeref, status) -\end{verbatim} - - -\begin{description} -\item[3 ] Construct a date string from the input date values. If the year -is between 1900 and 1998, inclusive, then the returned date string will -have the old FITS format ('dd/mm/yy'), otherwise the date string will -have the new FITS format ('YYYY-MM-DD'). Use FTTM2S instead - to always return a date string using the new FITS format. -\end{description} - -\begin{verbatim} - FTDT2S( year, month, day, > datestr, status) -\end{verbatim} - - -\begin{description} -\item[4 ] Construct a new-format date + time string ('YYYY-MM-DDThh:mm:ss.ddd...'). - If the year, month, and day values all = 0 then only the time is encoded - with format 'hh:mm:ss.ddd...'. The decimals parameter specifies how many - decimal places of fractional seconds to include in the string. If `decimals' - is negative, then only the date will be return ('YYYY-MM-DD'). -\end{description} - -\begin{verbatim} - FTTM2S( year, month, day, hour, minute, second, decimals, - > datestr, status) -\end{verbatim} - - -\begin{description} -\item[5 ] Return the date as read from the input string, where the string may be -in either the old ('dd/mm/yy') or new ('YYYY-MM-DDThh:mm:ss' or -'YYYY-MM-DD') FITS format. -\end{description} - -\begin{verbatim} - FTS2DT(datestr, > year, month, day, status) -\end{verbatim} - - -\begin{description} -\item[6 ] Return the date and time as read from the input string, where the -string may be in either the old or new FITS format. The returned hours, -minutes, and seconds values will be set to zero if the input string -does not include the time ('dd/mm/yy' or 'YYYY-MM-DD') . Similarly, -the returned year, month, and date values will be set to zero if the -date is not included in the input string ('hh:mm:ss.ddd...'). -\end{description} - -\begin{verbatim} - FTS2TM(datestr, > year, month, day, hour, minute, second, status) -\end{verbatim} - - -\section{General Utility Subroutines \label{FTGHAD}} - -The following utility subroutines may be useful for certain applications: - - -\begin{description} -\item[1 ] Return the starting byte address of the CHDU and the next HDU. -\end{description} - -\begin{verbatim} - FTGHAD(iunit, > curaddr, nextaddr) -\end{verbatim} - -\begin{description} -\item[2 ] Convert a character string to uppercase (operates in place). -\end{description} - -\begin{verbatim} - FTUPCH(string) -\end{verbatim} - -\begin{description} -\item[3 ] Compare the input template string against the reference string - to see if they match. The template string may contain wildcard - characters: '*' will match any sequence of characters (including - zero characters) and '?' will match any single character in the - reference string. The '\#' character will match any consecutive string - of decimal digits (0 - 9). If CASESN = .true. then the match will be - case sensitive. The returned MATCH parameter will be .true. if - the 2 strings match, and EXACT will be .true. if the match is - exact (i.e., if no wildcard characters were used in the match). - Both strings must be 68 characters or less in length. -\end{description} - -\begin{verbatim} - FTCMPS(str_template, string, casesen, > match, exact) -\end{verbatim} - - -\begin{description} -\item[4 ] Test that the keyword name contains only legal characters: A-Z,0-9, - hyphen, and underscore. -\end{description} - -\begin{verbatim} - FTTKEY(keyword, > status) -\end{verbatim} - -\begin{description} -\item[5 ] Test that the keyword record contains only legal printable ASCII - characters -\end{description} - -\begin{verbatim} - FTTREC(card, > status) -\end{verbatim} - -\begin{description} -\item[6 ] Test whether the current header contains any NULL (ASCII 0) characters. - These characters are illegal in the header, but they will go undetected - by most of the CFITSIO keyword header routines, because the null is - interpreted as the normal end-of-string terminator. This routine returns - the position of the first null character in the header, or zero if there - are no nulls. For example a returned value of 110 would indicate that - the first NULL is located in the 30th character of the second keyword - in the header (recall that each header record is 80 characters long). - Note that this is one of the few FITSIO routines in which the returned - value is not necessarily equal to the status value). -\end{description} - -\begin{verbatim} - FTNCHK(unit, > status) -\end{verbatim} - -\begin{description} -\item[7 ] Parse a header keyword record and return the name of the keyword - and the length of the name. - The keyword name normally occupies the first 8 characters of the - record, except under the HIERARCH convention where the name can - be up to 70 characters in length. -\end{description} - -\begin{verbatim} - FTGKNM(card, > keyname, keylength, staThe '\#' character will match any consecutive string - of decimal digits (0 - 9). tus) -\end{verbatim} - -\begin{description} -\item[8 ] Parse a header keyword record. - This subroutine parses the input header record to return the value (as - a character string) and comment strings. If the keyword has no - value (columns 9-10 not equal to '= '), then the value string is returned - blank and the comment string is set equal to column 9 - 80 of the - input string. -\end{description} - -\begin{verbatim} - FTPSVC(card, > value,comment,status) -\end{verbatim} - -\begin{description} -\item[9 ] Construct a properly formated 80-character header keyword record from the - input keyword name, keyword value, and keyword comment strings. - Hierarchical keyword names (e.g., "ESO TELE CAM") are supported. - The value string may contain an integer, floating point, logical, or - quoted character string (e.g., "12", "15.7", "T", - or "'NGC 1313'"). -\end{description} - -\begin{verbatim} - FTMKKY(keyname, value, comment, > card, status) -\end{verbatim} - -\begin{description} -\item[10] Construct a sequence keyword name (ROOT + nnn). - This subroutine appends the sequence number to the root string to create - a keyword name (e.g., 'NAXIS' + 2 = 'NAXIS2') -\end{description} - -\begin{verbatim} - FTKEYN(keyroot,seq_no, > keyword,status) -\end{verbatim} - -\begin{description} -\item[11] Construct a sequence keyword name (n + ROOT). - This subroutine concatenates the sequence number to the front of the - root string to create a keyword name (e.g., 1 + 'CTYP' = '1CTYP') -\end{description} - -\begin{verbatim} - FTNKEY(seq_no,keyroot, > keyword,status) -\end{verbatim} - -\begin{description} -\item[12] Determine the datatype of a keyword value string. - This subroutine parses the keyword value string (usually columns 11-30 - of the header record) to determine its datatype. -\end{description} - -\begin{verbatim} - FTDTYP(value, > dtype,status) -\end{verbatim} - -\begin{description} -\item[13] Return the class of input header record. The record is classified - into one of the following categories (the class values are - defined in fitsio.h). Note that this is one of the few FITSIO - routines that does not return a status value. -\end{description} - -\begin{verbatim} - Class Value Keywords - TYP_STRUC_KEY 10 SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, - GROUPS, PCOUNT, GCOUNT, END - XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, - and the first 4 COMMENT keywords in the primary array - that define the FITS format. - TYP_CMPRS_KEY 20 The keywords used in the compressed image or table - format, including ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, - ZTILEn, ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK - TYP_SCAL_KEY 30 BSCALE, BZERO, TSCALn, TZEROn - TYP_NULL_KEY 40 BLANK, TNULLn - TYP_DIM_KEY 50 TDIMn - TYP_RANG_KEY 60 TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX - TYP_UNIT_KEY 70 BUNIT, TUNITn - TYP_DISP_KEY 80 TDISPn - TYP_HDUID_KEY 90 EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL - TYP_CKSUM_KEY 100 CHECKSUM, DATASUM - TYP_WCS_KEY 110 CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn - CDj_is, PVj_ms, LONPOLEs, LATPOLEs - TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, - TCRPks, TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn - jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, - iCRPns, jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn - (i,j,m,n are integers, s is any letter) - TYP_REFSYS_KEY 120 EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs - TYP_COMM_KEY 130 COMMENT, HISTORY, (blank keyword) - TYP_CONT_KEY 140 CONTINUE - TYP_USER_KEY 150 all other keywords - - class = FTGKCL (char *card) -\end{verbatim} - -\begin{description} -\item[14] Parse the 'TFORM' binary table column format string. - This subroutine parses the input TFORM character string and returns the - integer datatype code, the repeat count of the field, and, in the case - of character string fields, the length of the unit string. The following - datatype codes are returned (the negative of the value is returned - if the column contains variable-length arrays): -\end{description} - -\begin{verbatim} - Datatype DATACODE value - bit, X 1 - byte, B 11 - logical, L 14 - ASCII character, A 16 - short integer, I 21 - integer, J 41 - real, E 42 - double precision, D 82 - complex 83 - double complex 163 - - FTBNFM(tform, > datacode,repeat,width,status) -\end{verbatim} - -\begin{description} -\item[15] Parse the 'TFORM' keyword value that defines the column format in - an ASCII table. This routine parses the input TFORM character - string and returns the datatype code, the width of the column, - and (if it is a floating point column) the number of decimal places - to the right of the decimal point. The returned datatype codes are - the same as for the binary table, listed above, with the following - additional rules: integer columns that are between 1 and 4 characters - wide are defined to be short integers (code = 21). Wider integer - columns are defined to be regular integers (code = 41). Similarly, - Fixed decimal point columns (with TFORM = 'Fw.d') are defined to - be single precision reals (code = 42) if w is between 1 and 7 characters - wide, inclusive. Wider 'F' columns will return a double precision - data code (= 82). 'Ew.d' format columns will have datacode = 42, - and 'Dw.d' format columns will have datacode = 82. -\end{description} - -\begin{verbatim} - FTASFM(tform, > datacode,width,decimals,status) -\end{verbatim} - -\begin{description} -\item[16] Calculate the starting column positions and total ASCII table width - based on the input array of ASCII table TFORM values. The SPACE input - parameter defines how many blank spaces to leave between each column - (it is recommended to have one space between columns for better human - readability). -\end{description} - -\begin{verbatim} - FTGABC(tfields,tform,space, > rowlen,tbcol,status) -\end{verbatim} - -\begin{description} -\item[17] Parse a template string and return a formatted 80-character string - suitable for appending to (or deleting from) a FITS header file. - This subroutine is useful for parsing lines from an ASCII template file - and reformatting them into legal FITS header records. The formatted - string may then be passed to the FTPREC, FTMCRD, or FTDKEY subroutines - to append or modify a FITS header record. -\end{description} - -\begin{verbatim} - FTGTHD(template, > card,hdtype,status) -\end{verbatim} - The input TEMPLATE character string generally should contain 3 tokens: - (1) the KEYNAME, (2) the VALUE, and (3) the COMMENT string. The - TEMPLATE string must adhere to the following format: - - -\begin{description} -\item[- ] The KEYNAME token must begin in columns 1-8 and be a maximum of 8 - characters long. If the first 8 characters of the template line are - blank then the remainder of the line is considered to be a FITS comment - (with a blank keyword name). A legal FITS keyword name may only - contain the characters A-Z, 0-9, and '-' (minus sign) and - underscore. This subroutine will automatically convert any lowercase - characters to uppercase in the output string. If KEYNAME = 'COMMENT' - or 'HISTORY' then the remainder of the line is considered to be a FITS - COMMENT or HISTORY record, respectively. -\end{description} - - -\begin{description} -\item[- ] The VALUE token must be separated from the KEYNAME token by one or more - spaces and/or an '=' character. The datatype of the VALUE token - (numeric, logical, or character string) is automatically determined - and the output CARD string is formatted accordingly. The value - token may be forced to be interpreted as a string (e.g. if it is a - string of numeric digits) by enclosing it in single quotes. - If the value token is a character string that contains 1 or more - embedded blank space characters or slash ('/') characters then the - entire character string must be enclosed in single quotes. -\end{description} - - -\begin{description} -\item[- ] The COMMENT token is optional, but if present must be separated from - the VALUE token by a blank space or a '/' character. -\end{description} - - -\begin{description} -\item[- ] One exception to the above rules is that if the first non-blank - character in the template string is a minus sign ('-') followed - by a single token, or a single token followed by an equal sign, - then it is interpreted as the name of a keyword which is to be - deleted from the FITS header. -\end{description} - - -\begin{description} -\item[- ] The second exception is that if the template string starts with - a minus sign and is followed by 2 tokens then the second token - is interpreted as the new name for the keyword specified by - first token. In this case the old keyword name (first token) - is returned in characters 1-8 of the returned CARD string, and - the new keyword name (the second token) is returned in characters - 41-48 of the returned CARD string. These old and new names - may then be passed to the FTMNAM subroutine which will change - the keyword name. -\end{description} - - The HDTYPE output parameter indicates how the returned CARD string - should be interpreted: - -\begin{verbatim} - hdtype interpretation - ------ ------------------------------------------------- - -2 Modify the name of the keyword given in CARD(1:8) - to the new name given in CARD(41:48) - - -1 CARD(1:8) contains the name of a keyword to be deleted - from the FITS header. - - 0 append the CARD string to the FITS header if the - keyword does not already exist, otherwise update - the value/comment if the keyword is already present - in the header. - - 1 simply append this keyword to the FITS header (CARD - is either a HISTORY or COMMENT keyword). - - 2 This is a FITS END record; it should not be written - to the FITS header because FITSIO automatically - appends the END record when the header is closed. -\end{verbatim} - EXAMPLES: The following lines illustrate valid input template strings: - -\begin{verbatim} - INTVAL 7 This is an integer keyword - RVAL 34.6 / This is a floating point keyword - EVAL=-12.45E-03 This is a floating point keyword in exponential notation - lval F This is a boolean keyword - This is a comment keyword with a blank keyword name - SVAL1 = 'Hello world' / this is a string keyword - SVAL2 '123.5' this is also a string keyword - sval3 123+ / this is also a string keyword with the value '123+ ' - # the following template line deletes the DATE keyword - - DATE - # the following template line modifies the NAME keyword to OBJECT - - NAME OBJECT -\end{verbatim} - -\begin{description} -\item[18] Parse the input string containing a list of rows or row ranges, and - return integer arrays containing the first and last row in each - range. For example, if rowlist = "3-5, 6, 8-9" then it will - return numranges = 3, rangemin = 3, 6, 8 and rangemax = 5, 6, 9. - At most, 'maxranges' number of ranges will be returned. 'maxrows' - is the maximum number of rows in the table; any rows or ranges - larger than this will be ignored. The rows must be specified in - increasing order, and the ranges must not overlap. A minus sign - may be use to specify all the rows to the upper or lower bound, so - "50-" means all the rows from 50 to the end of the table, and "-" - means all the rows in the table, from 1 - maxrows. -\end{description} - -\begin{verbatim} - FTRWRG(rowlist, maxrows, maxranges, > - numranges, rangemin, rangemax, status) -\end{verbatim} - - - -\chapter{ The CFITSIO Iterator Function } - -The fits\_iterate\_data function in CFITSIO provides a unique method of -executing an arbitrary user-supplied `work' function that operates on -rows of data in FITS tables or on pixels in FITS images. Rather than -explicitly reading and writing the FITS images or columns of data, one -instead calls the CFITSIO iterator routine, passing to it the name of -the user's work function that is to be executed along with a list of -all the table columns or image arrays that are to be passed to the work -function. The CFITSIO iterator function then does all the work of -allocating memory for the arrays, reading the input data from the FITS -file, passing them to the work function, and then writing any output -data back to the FITS file after the work function exits. Because -it is often more efficient to process only a subset of the total table -rows at one time, the iterator function can determine the optimum -amount of data to pass in each iteration and repeatedly call the work -function until the entire table been processed. - -For many applications this single CFITSIO iterator function can -effectively replace all the other CFITSIO routines for reading or -writing data in FITS images or tables. Using the iterator has several -important advantages over the traditional method of reading and writing -FITS data files: - -\begin{itemize} -\item -It cleanly separates the data I/O from the routine that operates on -the data. This leads to a more modular and `object oriented' -programming style. - -\item -It simplifies the application program by eliminating the need to allocate -memory for the data arrays and eliminates most of the calls to the CFITSIO -routines that explicitly read and write the data. - -\item -It ensures that the data are processed as efficiently as possible. -This is especially important when processing tabular data since -the iterator function will calculate the most efficient number -of rows in the table to be passed at one time to the user's work -function on each iteration. - -\item -Makes it possible for larger projects to develop a library of work -functions that all have a uniform calling sequence and are all -independent of the details of the FITS file format. - -\end{itemize} - -There are basically 2 steps in using the CFITSIO iterator function. -The first step is to design the work function itself which must have a -prescribed set of input parameters. One of these parameters is a -structure containing pointers to the arrays of data; the work function -can perform any desired operations on these arrays and does not need to -worry about how the input data were read from the file or how the -output data get written back to the file. - -The second step is to design the driver routine that opens all the -necessary FITS files and initializes the input parameters to the -iterator function. The driver program calls the CFITSIO iterator -function which then reads the data and passes it to the user's work -function. - -Further details on using the iterator function can be found in the -companion CFITSIO User's Guide, and in the iter\_a.f, iter\_b.f and -iter\_c.f example programs. - - - -\chapter{ Extended File Name Syntax } - - -\section{Overview} - -CFITSIO supports an extended syntax when specifying the name of the -data file to be opened or created that includes the following -features: - -\begin{itemize} -\item -CFITSIO can read IRAF format images which have header file names that -end with the '.imh' extension, as well as reading and writing FITS -files, This feature is implemented in CFITSIO by first converting the -IRAF image into a temporary FITS format file in memory, then opening -the FITS file. Any of the usual CFITSIO routines then may be used to -read the image header or data. Similarly, raw binary data arrays can -be read by converting them on the fly into virtual FITS images. - -\item -FITS files on the Internet can be read (and sometimes written) using the FTP, -HTTP, or ROOT protocols. - -\item -FITS files can be piped between tasks on the stdin and stdout streams. - -\item -FITS files can be read and written in shared memory. This can potentially -achieve much better data I/O performance compared to reading and -writing the same FITS files on magnetic disk. - -\item -Compressed FITS files in gzip or Unix COMPRESS format can be directly read. - -\item -Output FITS files can be written directly in compressed gzip format, -thus saving disk space. - -\item -FITS table columns can be created, modified, or deleted 'on-the-fly' as -the table is opened by CFITSIO. This creates a virtual FITS file containing -the modifications that is then opened by the application program. - -\item -Table rows may be selected, or filtered out, on the fly when the table -is opened by CFITSIO, based on an arbitrary user-specified expression. -Only rows for which the expression evaluates to 'TRUE' are retained -in the copy of the table that is opened by the application program. - -\item -Histogram images may be created on the fly by binning the values in -table columns, resulting in a virtual N-dimensional FITS image. The -application program then only sees the FITS image (in the primary -array) instead of the original FITS table. -\end{itemize} - -The latter 3 features in particular add very powerful data processing -capabilities directly into CFITSIO, and hence into every task that uses -CFITSIO to read or write FITS files. For example, these features -transform a very simple program that just copies an input FITS file to -a new output file (like the `fitscopy' program that is distributed with -CFITSIO) into a multipurpose FITS file processing tool. By appending -fairly simple qualifiers onto the name of the input FITS file, the user -can perform quite complex table editing operations (e.g., create new -columns, or filter out rows in a table) or create FITS images by -binning or histogramming the values in table columns. In addition, -these functions have been coded using new state-of-the art algorithms -that are, in some cases, 10 - 100 times faster than previous widely -used implementations. - -Before describing the complete syntax for the extended FITS file names -in the next section, here are a few examples of FITS file names that -give a quick overview of the allowed syntax: - -\begin{itemize} -\item -{\tt 'myfile.fits'}: the simplest case of a FITS file on disk in the current -directory. - -\item -{\tt 'myfile.imh'}: opens an IRAF format image file and converts it on the -fly into a temporary FITS format image in memory which can then be read with -any other CFITSIO routine. - -\item -{\tt rawfile.dat[i512,512]}: opens a raw binary data array (a 512 x 512 -short integer array in this case) and converts it on the fly into a -temporary FITS format image in memory which can then be read with any -other CFITSIO routine. - -\item -{\tt myfile.fits.gz}: if this is the name of a new output file, the '.gz' -suffix will cause it to be compressed in gzip format when it is written to -disk. - -\item -{\tt 'myfile.fits.gz[events, 2]'}: opens and uncompresses the gzipped file -myfile.fits then moves to the extension which has the keywords EXTNAME -= 'EVENTS' and EXTVER = 2. - -\item -{\tt '-'}: a dash (minus sign) signifies that the input file is to be read -from the stdin file stream, or that the output file is to be written to -the stdout stream. - -\item -{\tt 'ftp://legacy.gsfc.nasa.gov/test/vela.fits'}: FITS files in any ftp -archive site on the Internet may be directly opened with read-only -access. - -\item -{\tt 'http://legacy.gsfc.nasa.gov/software/test.fits'}: any valid URL to a -FITS file on the Web may be opened with read-only access. - -\item -{\tt 'root://legacy.gsfc.nasa.gov/test/vela.fits'}: similar to ftp access -except that it provides write as well as read access to the files -across the network. This uses the root protocol developed at CERN. - -\item -{\tt 'shmem://h2[events]'}: opens the FITS file in a shared memory segment and -moves to the EVENTS extension. - -\item -{\tt 'mem://'}: creates a scratch output file in core computer memory. The -resulting 'file' will disappear when the program exits, so this -is mainly useful for testing purposes when one does not want a -permanent copy of the output file. - -\item -{\tt 'myfile.fits[3; Images(10)]'}: opens a copy of the image contained in the -10th row of the 'Images' column in the binary table in the 3th extension -of the FITS file. The application just sees this single image as the -primary array. - -\item -{\tt 'myfile.fits[1:512:2, 1:512:2]'}: opens a section of the input image -ranging from the 1st to the 512th pixel in X and Y, and selects every -second pixel in both dimensions, resulting in a 256 x 256 pixel image -in this case. - -\item -{\tt 'myfile.fits[EVENTS][col Rad = sqrt(X**2 + Y**2)]'}: creates and opens -a temporary file on the fly (in memory or on disk) that is identical to -myfile.fits except that it will contain a new column in the EVENTS -extension called 'Rad' whose value is computed using the indicated -expression which is a function of the values in the X and Y columns. - -\item -{\tt 'myfile.fits[EVENTS][PHA > 5]'}: creates and opens a temporary FITS -files that is identical to 'myfile.fits' except that the EVENTS table -will only contain the rows that have values of the PHA column greater -than 5. In general, any arbitrary boolean expression using a C or -Fortran-like syntax, which may combine AND and OR operators, -may be used to select rows from a table. - -\item -{\tt 'myfile.fits[EVENTS][bin (X,Y)=1,2048,4]'}: creates a temporary FITS -primary array image which is computed on the fly by binning (i.e, -computing the 2-dimensional histogram) of the values in the X and Y -columns of the EVENTS extension. In this case the X and Y coordinates -range from 1 to 2048 and the image pixel size is 4 units in both -dimensions, so the resulting image is 512 x 512 pixels in size. - -\item -The final example combines many of these feature into one complex -expression (it is broken into several lines for clarity): - -\begin{verbatim} - 'ftp://legacy.gsfc.nasa.gov/data/sample.fits.gz[EVENTS] - [col phacorr = pha * 1.1 - 0.3][phacorr >= 5.0 && phacorr <= 14.0] - [bin (X,Y)=32]' -\end{verbatim} -In this case, CFITSIO (1) copies and uncompresses the FITS file from -the ftp site on the legacy machine, (2) moves to the 'EVENTS' -extension, (3) calculates a new column called 'phacorr', (4) selects -the rows in the table that have phacorr in the range 5 to 14, and -finally (5) bins the remaining rows on the X and Y column coordinates, -using a pixel size = 32 to create a 2D image. All this processing is -completely transparent to the application program, which simply sees -the final 2-D image in the primary array of the opened file. -\end{itemize} - -The full extended CFITSIO FITS file name can contain several different -components depending on the context. These components are described in -the following sections: - -\begin{verbatim} -When creating a new file: - filetype://BaseFilename(templateName) - -When opening an existing primary array or image HDU: - filetype://BaseFilename(outName)[HDUlocation][ImageSection] - -When opening an existing table HDU: - filetype://BaseFilename(outName)[HDUlocation][colFilter][rowFilter][binSpec] -\end{verbatim} -The filetype, BaseFilename, outName, HDUlocation, and ImageSection -components, if present, must be given in that order, but the colFilter, -rowFilter, and binSpec specifiers may follow in any order. Regardless -of the order, however, the colFilter specifier, if present, will be -processed first by CFITSIO, followed by the rowFilter specifier, and -finally by the binSpec specifier. - - -\section{Filetype} - -The type of file determines the medium on which the file is located -(e.g., disk or network) and, hence, which internal device driver is used by -CFITSIO to read and/or write the file. Currently supported types are - -\begin{verbatim} - file:// - file on local magnetic disk (default) - ftp:// - a readonly file accessed with the anonymous FTP protocol. - It also supports ftp://username:password@hostname/... - for accessing password-protected ftp sites. - http:// - a readonly file accessed with the HTTP protocol. It - supports username:password just like the ftp driver. - Proxy HTTP servers are supported using the http_proxy - environment variable (see following note). - stream:// - special driver to read an input FITS file from the stdin - stream, and/or write an output FITS file to the stdout - stream. This driver is fragile and has limited - functionality (see the following note). - gsiftp:// - access files on a computational grid using the gridftp - protocol in the Globus toolkit (see following note). - root:// - uses the CERN root protocol for writing as well as - reading files over the network. - shmem:// - opens or creates a file which persists in the computer's - shared memory. - mem:// - opens a temporary file in core memory. The file - disappears when the program exits so this is mainly - useful for test purposes when a permanent output file - is not desired. -\end{verbatim} -If the filetype is not specified, then type file:// is assumed. -The double slashes '//' are optional and may be omitted in most cases. - - -\subsection{Notes about HTTP proxy servers} - -A proxy HTTP server may be used by defining the address (URL) and port -number of the proxy server with the http\_proxy environment variable. -For example - -\begin{verbatim} - setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 -\end{verbatim} -will cause CFITSIO to use port 3128 on the heasarc proxy server whenever -reading a FITS file with HTTP. - - -\subsection{Notes about the stream filetype driver} - -The stream driver can be used to efficiently read a FITS file from the stdin -file stream or write a FITS to the stdout file stream. However, because these -input and output streams must be accessed sequentially, the FITS file reading or -writing application must also read and write the file sequentially, at least -within the tolerances described below. - -CFITSIO supports 2 different methods for accessing FITS files on the stdin and -stdout streams. The original method, which is invoked by specifying a dash -character, "-", as the name of the file when opening or creating it, works by -storing a complete copy of the entire FITS file in memory. In this case, when -reading from stdin, CFITSIO will copy the entire stream into memory before doing -any processing of the file. Similarly, when writing to stdout, CFITSIO will -create a copy of the entire FITS file in memory, before finally flushing it out -to the stdout stream when the FITS file is closed. Buffering the entire FITS -file in this way allows the application to randomly access any part of the FITS -file, in any order, but it also requires that the user have sufficient available -memory (or virtual memory) to store the entire file, which may not be possible -in the case of very large files. - -The newer stream filetype provides a more memory-efficient method of accessing -FITS files on the stdin or stdout streams. Instead of storing a copy of the -entire FITS file in memory, CFITSIO only uses a set of internal buffer which by -default can store 40 FITS blocks, or about 100K bytes of the FITS file. The -application program must process the FITS file sequentially from beginning to -end, within this 100K buffer. Generally speaking the application program must -conform to the following restrictions: - -\begin{itemize} -\item -The program must finish reading or writing the header keywords -before reading or writing any data in the HDU. -\item -The HDU can contain at most about 1400 header keywords. This is the -maximum that can fit in the nominal 40 FITS block buffer. In principle, -this limit could be increased by recompiling CFITSIO with a larger -buffer limit, which is set by the NIOBUF parameter in fitsio2.h. -\item -The program must read or write the data in a sequential manner from the -beginning to the end of the HDU. Note that CFITSIO's internal -100K buffer allows a little latitude in meeting this requirement. -\item -The program cannot move back to a previous HDU in the FITS file. -\item -Reading or writing of variable length array columns in binary tables is not -supported on streams, because this requires moving back and forth between the -fixed-length portion of the binary table and the following heap area where the -arrays are actually stored. -\item -Reading or writing of tile-compressed images is not supported on streams, -because the images are internally stored using variable length arrays. -\end{itemize} - - -\subsection{Notes about the gsiftp filetype} - -DEPENDENCIES: Globus toolkit (2.4.3 or higher) (GT) should be installed. -There are two different ways to install GT: - -1) goto the globus toolkit web page www.globus.org and follow the - download and compilation instructions; - -2) goto the Virtual Data Toolkit web page http://vdt.cs.wisc.edu/ - and follow the instructions (STRONGLY SUGGESTED); - -Once a globus client has been installed in your system with a specific flavour -it is possible to compile and install the CFITSIO libraries. -Specific configuration flags must be used: - -1) --with-gsiftp[[=PATH]] Enable Globus Toolkit gsiftp protocol support - PATH=GLOBUS\_LOCATION i.e. the location of your globus installation - -2) --with-gsiftp-flavour[[=PATH] defines the specific Globus flavour - ex. gcc32 - -Both the flags must be used and it is mandatory to set both the PATH and the -flavour. - -USAGE: To access files on a gridftp server it is necessary to use a gsiftp prefix: - -example: gsiftp://remote\_server\_fqhn/directory/filename - -The gridftp driver uses a local buffer on a temporary file the file is located -in the /tmp directory. If you have special permissions on /tmp or you do not have a /tmp -directory, it is possible to force another location setting the GSIFTP\_TMPFILE environment -variable (ex. export GSIFTP\_TMPFILE=/your/location/yourtmpfile). - -Grid FTP supports multi channel transfer. By default a single channel transmission is -available. However, it is possible to modify this behavior setting the GSIFTP\_STREAMS -environment variable (ex. export GSIFTP\_STREAMS=8). - - -\subsection{Notes about the root filetype} - -The original rootd server can be obtained from: -\verb-ftp://root.cern.ch/root/rootd.tar.gz- -but, for it to work correctly with CFITSIO one has to use a modified -version which supports a command to return the length of the file. -This modified version is available in rootd subdirectory -in the CFITSIO ftp area at - -\begin{verbatim} - ftp://legacy.gsfc.nasa.gov/software/fitsio/c/root/rootd.tar.gz. -\end{verbatim} - -This small server is started either by inetd when a client requests a -connection to a rootd server or by hand (i.e. from the command line). -The rootd server works with the ROOT TNetFile class. It allows remote -access to ROOT database files in either read or write mode. By default -TNetFile assumes port 432 (which requires rootd to be started as root). -To run rootd via inetd add the following line to /etc/services: - -\begin{verbatim} - rootd 432/tcp -\end{verbatim} -and to /etc/inetd.conf, add the following line: - -\begin{verbatim} - rootd stream tcp nowait root /user/rdm/root/bin/rootd rootd -i -\end{verbatim} -Force inetd to reread its conf file with "kill -HUP ". -You can also start rootd by hand running directly under your private -account (no root system privileges needed). For example to start -rootd listening on port 5151 just type: \verb+rootd -p 5151+ -Notice: no \& is needed. Rootd will go into background by itself. - -\begin{verbatim} - Rootd arguments: - -i says we were started by inetd - -p port# specifies a different port to listen on - -d level level of debug info written to syslog - 0 = no debug (default) - 1 = minimum - 2 = medium - 3 = maximum -\end{verbatim} -Rootd can also be configured for anonymous usage (like anonymous ftp). -To setup rootd to accept anonymous logins do the following (while being -logged in as root): - -\begin{verbatim} - - Add the following line to /etc/passwd: - - rootd:*:71:72:Anonymous rootd:/var/spool/rootd:/bin/false - - where you may modify the uid, gid (71, 72) and the home directory - to suite your system. - - - Add the following line to /etc/group: - - rootd:*:72:rootd - - where the gid must match the gid in /etc/passwd. - - - Create the directories: - - mkdir /var/spool/rootd - mkdir /var/spool/rootd/tmp - chmod 777 /var/spool/rootd/tmp - - Where /var/spool/rootd must match the rootd home directory as - specified in the rootd /etc/passwd entry. - - - To make writeable directories for anonymous do, for example: - - mkdir /var/spool/rootd/pub - chown rootd:rootd /var/spool/rootd/pub -\end{verbatim} -That's all. Several additional remarks: you can login to an anonymous -server either with the names "anonymous" or "rootd". The password should -be of type user@host.do.main. Only the @ is enforced for the time -being. In anonymous mode the top of the file tree is set to the rootd -home directory, therefore only files below the home directory can be -accessed. Anonymous mode only works when the server is started via -inetd. - - -\subsection{Notes about the shmem filetype:} - -Shared memory files are currently supported on most Unix platforms, -where the shared memory segments are managed by the operating system -kernel and `live' independently of processes. They are not deleted (by -default) when the process which created them terminates, although they -will disappear if the system is rebooted. Applications can create -shared memory files in CFITSIO by calling: - -\begin{verbatim} - fit_create_file(&fitsfileptr, "shmem://h2", &status); -\end{verbatim} -where the root `file' names are currently restricted to be 'h0', 'h1', -'h2', 'h3', etc., up to a maximum number defined by the the value of -SHARED\_MAXSEG (equal to 16 by default). This is a prototype -implementation of the shared memory interface and a more robust -interface, which will have fewer restrictions on the number of files -and on their names, may be developed in the future. - -When opening an already existing FITS file in shared memory one calls -the usual CFITSIO routine: - -\begin{verbatim} - fits_open_file(&fitsfileptr, "shmem://h7", mode, &status) -\end{verbatim} -The file mode can be READWRITE or READONLY just as with disk files. -More than one process can operate on READONLY mode files at the same -time. CFITSIO supports proper file locking (both in READONLY and -READWRITE modes), so calls to fits\_open\_file may be locked out until -another other process closes the file. - -When an application is finished accessing a FITS file in a shared -memory segment, it may close it (and the file will remain in the -system) with fits\_close\_file, or delete it with fits\_delete\_file. -Physical deletion is postponed until the last process calls -ffclos/ffdelt. fits\_delete\_file tries to obtain a READWRITE lock on -the file to be deleted, thus it can be blocked if the object was not -opened in READWRITE mode. - -A shared memory management utility program called `smem', is included -with the CFITSIO distribution. It can be built by typing `make smem'; -then type `smem -h' to get a list of valid options. Executing smem -without any options causes it to list all the shared memory segments -currently residing in the system and managed by the shared memory -driver. To get a list of all the shared memory objects, run the system -utility program `ipcs [-a]'. - - -\section{Base Filename} - -The base filename is the name of the file optionally including the -director/subdirectory path, and in the case of `ftp', `http', and `root' -filetypes, the machine identifier. Examples: - -\begin{verbatim} - myfile.fits - !data.fits - /data/myfile.fits - fits.gsfc.nasa.gov/ftp/sampledata/myfile.fits.gz -\end{verbatim} - -When creating a new output file on magnetic disk (of type file://) if -the base filename begins with an exclamation point (!) then any -existing file with that same basename will be deleted prior to creating -the new FITS file. Otherwise if the file to be created already exists, -then CFITSIO will return an error and will not overwrite the existing -file. Note that the exclamation point, '!', is a special UNIX character, -so if it is used on the command line rather than entered at a task -prompt, it must be preceded by a backslash to force the UNIX -shell to pass it verbatim to the application program. - -If the output disk file name ends with the suffix '.gz', then CFITSIO -will compress the file using the gzip compression algorithm before -writing it to disk. This can reduce the amount of disk space used by -the file. Note that this feature requires that the uncompressed file -be constructed in memory before it is compressed and written to disk, -so it can fail if there is insufficient available memory. - -An input FITS file may be compressed with the gzip or Unix compress -algorithms, in which case CFITSIO will uncompress the file on the fly -into a temporary file (in memory or on disk). Compressed files may -only be opened with read-only permission. When specifying the name of -a compressed FITS file it is not necessary to append the file suffix -(e.g., `.gz' or `.Z'). If CFITSIO cannot find the input file name -without the suffix, then it will automatically search for a compressed -file with the same root name. In the case of reading ftp and http type -files, CFITSIO generally looks for a compressed version of the file -first, before trying to open the uncompressed file. By default, -CFITSIO copies (and uncompressed if necessary) the ftp or http FITS -file into memory on the local machine before opening it. This will -fail if the local machine does not have enough memory to hold the whole -FITS file, so in this case, the output filename specifier (see the next -section) can be used to further control how CFITSIO reads ftp and http -files. - -If the input file is an IRAF image file (*.imh file) then CFITSIO will -automatically convert it on the fly into a virtual FITS image before it -is opened by the application program. IRAF images can only be opened -with READONLY file access. - -Similarly, if the input file is a raw binary data array, then CFITSIO -will convert it on the fly into a virtual FITS image with the basic set -of required header keywords before it is opened by the application -program (with READONLY access). In this case the data type and -dimensions of the image must be specified in square brackets following -the filename (e.g. rawfile.dat[ib512,512]). The first character (case -insensitive) defines the datatype of the array: - -\begin{verbatim} - b 8-bit unsigned byte - i 16-bit signed integer - u 16-bit unsigned integer - j 32-bit signed integer - r or f 32-bit floating point - d 64-bit floating point -\end{verbatim} -An optional second character specifies the byte order of the array -values: b or B indicates big endian (as in FITS files and the native -format of SUN UNIX workstations and Mac PCs) and l or L indicates -little endian (native format of DEC OSF workstations and IBM PCs). If -this character is omitted then the array is assumed to have the native -byte order of the local machine. These datatype characters are then -followed by a series of one or more integer values separated by commas -which define the size of each dimension of the raw array. Arrays with -up to 5 dimensions are currently supported. Finally, a byte offset to -the position of the first pixel in the data file may be specified by -separating it with a ':' from the last dimension value. If omitted, it -is assumed that the offset = 0. This parameter may be used to skip -over any header information in the file that precedes the binary data. -Further examples: - -\begin{verbatim} - raw.dat[b10000] 1-dimensional 10000 pixel byte array - raw.dat[rb400,400,12] 3-dimensional floating point big-endian array - img.fits[ib512,512:2880] reads the 512 x 512 short integer array in - a FITS file, skipping over the 2880 byte header -\end{verbatim} - -One special case of input file is where the filename = `-' (a dash or -minus sign) or 'stdin' or 'stdout', which signifies that the input file -is to be read from the stdin stream, or written to the stdout stream if -a new output file is being created. In the case of reading from stdin, -CFITSIO first copies the whole stream into a temporary FITS file (in -memory or on disk), and subsequent reading of the FITS file occurs in -this copy. When writing to stdout, CFITSIO first constructs the whole -file in memory (since random access is required), then flushes it out -to the stdout stream when the file is closed. In addition, if the -output filename = '-.gz' or 'stdout.gz' then it will be gzip compressed -before being written to stdout. - -This ability to read and write on the stdin and stdout steams allows -FITS files to be piped between tasks in memory rather than having to -create temporary intermediate FITS files on disk. For example if task1 -creates an output FITS file, and task2 reads an input FITS file, the -FITS file may be piped between the 2 tasks by specifying - -\begin{verbatim} - task1 - | task2 - -\end{verbatim} -where the vertical bar is the Unix piping symbol. This assumes that the 2 -tasks read the name of the FITS file off of the command line. - - -\section{Output File Name when Opening an Existing File} - -An optional output filename may be specified in parentheses immediately -following the base file name to be opened. This is mainly useful in -those cases where CFITSIO creates a temporary copy of the input FITS -file before it is opened and passed to the application program. This -happens by default when opening a network FTP or HTTP-type file, when -reading a compressed FITS file on a local disk, when reading from the -stdin stream, or when a column filter, row filter, or binning specifier -is included as part of the input file specification. By default this -temporary file is created in memory. If there is not enough memory to -create the file copy, then CFITSIO will exit with an error. In these -cases one can force a permanent file to be created on disk, instead of -a temporary file in memory, by supplying the name in parentheses -immediately following the base file name. The output filename can -include the '!' clobber flag. - -Thus, if the input filename to CFITSIO is: -\verb+file1.fits.gz(file2.fits)+ -then CFITSIO will uncompress `file1.fits.gz' into the local disk file -`file2.fits' before opening it. CFITSIO does not automatically delete -the output file, so it will still exist after the application program -exits. - -In some cases, several different temporary FITS files will be created -in sequence, for instance, if one opens a remote file using FTP, then -filters rows in a binary table extension, then create an image by -binning a pair of columns. In this case, the remote file will be -copied to a temporary local file, then a second temporary file will be -created containing the filtered rows of the table, and finally a third -temporary file containing the binned image will be created. In cases -like this where multiple files are created, the outfile specifier will -be interpreted the name of the final file as described below, in descending -priority: - -\begin{itemize} -\item -as the name of the final image file if an image within a single binary -table cell is opened or if an image is created by binning a table column. -\item -as the name of the file containing the filtered table if a column filter -and/or a row filter are specified. -\item -as the name of the local copy of the remote FTP or HTTP file. -\item -as the name of the uncompressed version of the FITS file, if a -compressed FITS file on local disk has been opened. -\item -otherwise, the output filename is ignored. -\end{itemize} - - -The output file specifier is useful when reading FTP or HTTP-type -FITS files since it can be used to create a local disk copy of the file -that can be reused in the future. If the output file name = `*' then a -local file with the same name as the network file will be created. -Note that CFITSIO will behave differently depending on whether the -remote file is compressed or not as shown by the following examples: -\begin{itemize} -\item -`ftp://remote.machine/tmp/myfile.fits.gz(*)' - the remote compressed -file is copied to the local compressed file `myfile.fits.gz', which -is then uncompressed in local memory before being opened and passed -to the application program. - -\item -`ftp://remote.machine/tmp/myfile.fits.gz(myfile.fits)' - the remote -compressed file is copied and uncompressed into the local file -`myfile.fits'. This example requires less local memory than the -previous example since the file is uncompressed on disk instead of -in memory. - -\item -`ftp://remote.machine/tmp/myfile.fits(myfile.fits.gz)' - this will -usually produce an error since CFITSIO itself cannot compress files. -\end{itemize} - -The exact behavior of CFITSIO in the latter case depends on the type of -ftp server running on the remote machine and how it is configured. In -some cases, if the file `myfile.fits.gz' exists on the remote machine, -then the server will copy it to the local machine. In other cases the -ftp server will automatically create and transmit a compressed version -of the file if only the uncompressed version exists. This can get -rather confusing, so users should use a certain amount of caution when -using the output file specifier with FTP or HTTP file types, to make -sure they get the behavior that they expect. - - -\section{Template File Name when Creating a New File} - -When a new FITS file is created with a call to fits\_create\_file, the -name of a template file may be supplied in parentheses immediately -following the name of the new file to be created. This template is -used to define the structure of one or more HDUs in the new file. The -template file may be another FITS file, in which case the newly created -file will have exactly the same keywords in each HDU as in the template -FITS file, but all the data units will be filled with zeros. The -template file may also be an ASCII text file, where each line (in -general) describes one FITS keyword record. The format of the ASCII -template file is described below. - - -\section{Image Tile-Compression Specification} - -When specifying the name of the output FITS file to be created, the -user can indicate that images should be written in tile-compressed -format (see section 5.5, ``Primary Array or IMAGE Extension I/O -Routines'') by enclosing the compression parameters in square brackets -following the root disk file name. Here are some examples of the -syntax for specifying tile-compressed output images: - -\begin{verbatim} - myfile.fit[compress] - use Rice algorithm and default tile size - - myfile.fit[compress GZIP] - use the specified compression algorithm; - myfile.fit[compress Rice] only the first letter of the algorithm - myfile.fit[compress PLIO] name is required. - - myfile.fit[compress Rice 100,100] - use 100 x 100 pixel tile size - myfile.fit[compress Rice 100,100;2] - as above, and use noisebits = 2 -\end{verbatim} - - -\section{HDU Location Specification} - -The optional HDU location specifier defines which HDU (Header-Data -Unit, also known as an `extension') within the FITS file to initially -open. It must immediately follow the base file name (or the output -file name if present). If it is not specified then the first HDU (the -primary array) is opened. The HDU location specifier is required if -the colFilter, rowFilter, or binSpec specifiers are present, because -the primary array is not a valid HDU for these operations. The HDU may -be specified either by absolute position number, starting with 0 for -the primary array, or by reference to the HDU name, and optionally, the -version number and the HDU type of the desired extension. The location -of an image within a single cell of a binary table may also be -specified, as described below. - -The absolute position of the extension is specified either by enclosed -the number in square brackets (e.g., `[1]' = the first extension -following the primary array) or by preceded the number with a plus sign -(`+1'). To specify the HDU by name, give the name of the desired HDU -(the value of the EXTNAME or HDUNAME keyword) and optionally the -extension version number (value of the EXTVER keyword) and the -extension type (value of the XTENSION keyword: IMAGE, ASCII or TABLE, -or BINTABLE), separated by commas and all enclosed in square brackets. -If the value of EXTVER and XTENSION are not specified, then the first -extension with the correct value of EXTNAME is opened. The extension -name and type are not case sensitive, and the extension type may be -abbreviated to a single letter (e.g., I = IMAGE extension or primary -array, A or T = ASCII table extension, and B = binary table BINTABLE -extension). If the HDU location specifier is equal to `[PRIMARY]' or -`[P]', then the primary array (the first HDU) will be opened. - -FITS images are most commonly stored in the primary array or an image -extension, but images can also be stored as a vector in a single cell -of a binary table (i.e. each row of the vector column contains a -different image). Such an image can be opened with CFITSIO by -specifying the desired column name and the row number after the binary -table HDU specifier as shown in the following examples. The column name -is separated from the HDU specifier by a semicolon and the row number -is enclosed in parentheses. In this case CFITSIO copies the image from -the table cell into a temporary primary array before it is opened. The -application program then just sees the image in the primary array, -without any extensions. The particular row to be opened may be -specified either by giving an absolute integer row number (starting -with 1 for the first row), or by specifying a boolean expression that -evaluates to TRUE for the desired row. The first row that satisfies -the expression will be used. The row selection expression has the same -syntax as described in the Row Filter Specifier section, below. - - Examples: - -\begin{verbatim} - myfile.fits[3] - open the 3rd HDU following the primary array - myfile.fits+3 - same as above, but using the FTOOLS-style notation - myfile.fits[EVENTS] - open the extension that has EXTNAME = 'EVENTS' - myfile.fits[EVENTS, 2] - same as above, but also requires EXTVER = 2 - myfile.fits[events,2,b] - same, but also requires XTENSION = 'BINTABLE' - myfile.fits[3; images(17)] - opens the image in row 17 of the 'images' - column in the 3rd extension of the file. - myfile.fits[3; images(exposure > 100)] - as above, but opens the image - in the first row that has an 'exposure' column value - greater than 100. -\end{verbatim} - - -\section{Image Section} - -A virtual file containing a rectangular subsection of an image can be -extracted and opened by specifying the range of pixels (start:end) -along each axis to be extracted from the original image. One can also -specify an optional pixel increment (start:end:step) for each axis of -the input image. A pixel step = 1 will be assumed if it is not -specified. If the start pixel is larger then the end pixel, then the -image will be flipped (producing a mirror image) along that dimension. -An asterisk, '*', may be used to specify the entire range of an axis, -and '-*' will flip the entire axis. The input image can be in the -primary array, in an image extension, or contained in a vector cell of -a binary table. In the later 2 cases the extension name or number must -be specified before the image section specifier. - - Examples: - -\begin{verbatim} - myfile.fits[1:512:2, 2:512:2] - open a 256x256 pixel image - consisting of the odd numbered columns (1st axis) and - the even numbered rows (2nd axis) of the image in the - primary array of the file. - - myfile.fits[*, 512:256] - open an image consisting of all the columns - in the input image, but only rows 256 through 512. - The image will be flipped along the 2nd axis since - the starting pixel is greater than the ending pixel. - - myfile.fits[*:2, 512:256:2] - same as above but keeping only - every other row and column in the input image. - - myfile.fits[-*, *] - copy the entire image, flipping it along - the first axis. - - myfile.fits[3][1:256,1:256] - opens a subsection of the image that - is in the 3rd extension of the file. - - myfile.fits[4; images(12)][1:10,1:10] - open an image consisting - of the first 10 pixels in both dimensions. The original - image resides in the 12th row of the 'images' vector - column in the table in the 4th extension of the file. -\end{verbatim} - -When CFITSIO opens an image section it first creates a temporary file -containing the image section plus a copy of any other HDUs in the -file. This temporary file is then opened by the application program, -so it is not possible to write to or modify the input file when -specifying an image section. Note that CFITSIO automatically updates -the world coordinate system keywords in the header of the image -section, if they exist, so that the coordinate associated with each -pixel in the image section will be computed correctly. - - -\section{Image Transform Filters} - -CFITSIO can apply a user-specified mathematical function to the value -of every pixel in a FITS image, thus creating a new virtual image -in computer memory that is then opened and read by the application -program. The original FITS image is not modified by this process. - -The image transformation specifier is appended to the input -FITS file name and is enclosed in square brackets. It begins with the -letters 'PIX' to distinguish it from other types of FITS file filters -that are recognized by CFITSIO. The image transforming function may -use any of the mathematical operators listed in the following -'Row Filtering Specification' section of this document. -Some examples of image transform filters are: - -\begin{verbatim} - [pix X * 2.0] - multiply each pixel by 2.0 - [pix sqrt(X)] - take the square root of each pixel - [pix X + #ZEROPT - add the value of the ZEROPT keyword - [pix X>0 ? log10(X) : -99.] - if the pixel value is greater - than 0, compute the base 10 log, - else set the pixel = -99. -\end{verbatim} -Use the letter 'X' in the expression to represent the current pixel value -in the image. The expression is evaluated -independently for each pixel in the image and may be a function of 1) the -original pixel value, 2) the value of other pixels in the image at -a given relative offset from the position of the pixel that is being -evaluated, and 3) the value of -any header keywords. Header keyword values are represented -by the name of the keyword preceded by the '\#' sign. - - -To access the the value of adjacent pixels in the image, -specify the (1-D) offset from the current pixel in curly brackets. -For example - -\begin{verbatim} - [pix (x{-1} + x + x{+1}) / 3] -\end{verbatim} -will replace each pixel value with the running mean of the values of that -pixel and it's 2 neighboring pixels. Note that in this notation the image -is treated as a 1-D array, where each row of the image (or higher dimensional -cube) is appended one after another in one long array of pixels. -It is possible to refer to pixels -in the rows above or below the current pixel by using the value of the -NAXIS1 header keyword. For example - -\begin{verbatim} - [pix (x{-#NAXIS1} + x + x{#NAXIS1}) / 3] -\end{verbatim} -will compute the mean of each image pixel and the pixels immediately -above and below it in the adjacent rows of the image. -The following more complex example -creates a smoothed virtual image where each pixel -is a 3 x 3 boxcar average of the input image pixels: - -\begin{verbatim} - [pix (X + X{-1} + X{+1} - + X{-#NAXIS1} + X{-#NAXIS1 - 1} + X{-#NAXIS1 + 1} - + X{#NAXIS1} + X{#NAXIS1 - 1} + X{#NAXIS1 + 1}) / 9.] -\end{verbatim} -If the pixel offset -extends beyond the first or last pixel in the image, the function will -evaluate to undefined, or NULL. - -For complex or commonly used image filtering operations, -one can write the expression into an external text file and -then import it into the -filter using the syntax '[pix @filename.txt]'. The mathematical -expression can -extend over multiple lines of text in the file. -Any lines in the external text file -that begin with 2 slash characters ('//') will be ignored and may be -used to add comments into the file. - -By default, the datatype of the resulting image will be the same as -the original image, but one may force a different datatype by appended -a code letter to the 'pix' keyword: - -\begin{verbatim} - pixb - 8-bit byte image with BITPIX = 8 - pixi - 16-bit integer image with BITPIX = 16 - pixj - 32-bit integer image with BITPIX = 32 - pixr - 32-bit float image with BITPIX = -32 - pixd - 64-bit float image with BITPIX = -64 -\end{verbatim} -Also by default, any other HDUs in the input file will be copied without -change to the -output virtual FITS file, but one may discard the other HDUs by adding -the number '1' to the 'pix' keyword (and following any optional datatype code -letter). For example: - -\begin{verbatim} - myfile.fits[3][pixr1 sqrt(X)] -\end{verbatim} -will create a virtual FITS file containing only a primary array image -with 32-bit floating point pixels that have a value equal to the square -root of the pixels in the image that is in the 3rd extension -of the 'myfile.fits' file. - - - - -\section{Column and Keyword Filtering Specification} - -The optional column/keyword filtering specifier is used to modify the -column structure and/or the header keywords in the HDU that was -selected with the previous HDU location specifier. This filtering -specifier must be enclosed in square brackets and can be distinguished -from a general row filter specifier (described below) by the fact that -it begins with the string 'col ' and is not immediately followed by an -equals sign. The original file is not changed by this filtering -operation, and instead the modifications are made on a copy of the -input FITS file (usually in memory), which also contains a copy of all -the other HDUs in the file. This temporary file is passed to the -application program and will persist only until the file is closed or -until the program exits, unless the outfile specifier (see above) is -also supplied. - -The column/keyword filter can be used to perform the following -operations. More than one operation may be specified by separating -them with commas or semi-colons. - -\begin{itemize} - -\item -Copy only a specified list of columns columns to the filtered input file. -The list of column name should be separated by commas or semi-colons. Wild card -characters may be used in the column names to match multiple columns. -If the expression contains both a list of columns to be included and -columns to be deleted, then all the columns in the original table -except the explicitly deleted columns will appear in the filtered -table (i.e., there is no need to explicitly list the columns to -be included if any columns are being deleted). - -\item -Delete a column or keyword by listing the name preceded by a minus -sign or an exclamation mark (!), e.g., '-TIME' will delete the TIME -column if it exists, otherwise the TIME keyword. An error is returned -if neither a column nor keyword with this name exists. Note that the -exclamation point, '!', is a special UNIX character, so if it is used -on the command line rather than entered at a task prompt, it must be -preceded by a backslash to force the UNIX shell to ignore it. - -\item -Rename an existing column or keyword with the syntax 'NewName == -OldName'. An error is returned if neither a column nor keyword with -this name exists. - -\item -Append a new column or keyword to the table. To create a column, -give the new name, optionally followed by the datatype in parentheses, -followed by a single equals sign and an expression to be used to -compute the value (e.g., 'newcol(1J) = 0' will create a new 32-bit -integer column called 'newcol' filled with zeros). The datatype is -specified using the same syntax that is allowed for the value of the -FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for binary tables, -and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If the datatype is -not specified then an appropriate datatype will be chosen depending on -the form of the expression (may be a character string, logical, bit, long -integer, or double column). An appropriate vector count (in the case -of binary tables) will also be added if not explicitly specified. - -When creating a new keyword, the keyword name must be preceded by a -pound sign '\#', and the expression must evaluate to a scalar -(i.e., cannot have a column name in the expression). The comment -string for the keyword may be specified in parentheses immediately -following the keyword name (instead of supplying a datatype as in -the case of creating a new column). If the keyword name ends with a -pound sign '\#', then cfitsio will substitute the number of the -most recently referenced column for the \# character . -This is especially useful when writing -a column-related keyword like TUNITn for a newly created column, -as shown in the following examples. - -COMMENT and HISTORY keywords may also be created with the following syntax: - -\begin{verbatim} - #COMMENT = 'This is a comment keyword' - #HISTORY = 'This is a history keyword' -\end{verbatim} -Note that the equal sign and the quote characters will be removed, so -that the resulting header keywords in these cases will look like this: - -\begin{verbatim} - COMMENT This is a comment keyword - HISTORY This is a history keyword -\end{verbatim} -These two special keywords are always appended to the end of the header -and will not affect any previously existing COMMENT or HISTORY keywords. - -\item -Recompute (overwrite) the values in an existing column or keyword by -giving the name followed by an equals sign and an arithmetic -expression. -\end{itemize} - -The expression that is used when appending or recomputing columns or -keywords can be arbitrarily complex and may be a function of other -header keyword values and other columns (in the same row). The full -syntax and available functions for the expression are described below -in the row filter specification section. - -If the expression contains both a list of columns to be included and -columns to be deleted, then all the columns in the original table -except the explicitly deleted columns will appear in the filtered -table. If no columns to be deleted are specified, then only the -columns that are explicitly listed will be included in the filtered -output table. To include all the columns, add the '*' wildcard -specifier at the end of the list, as shown in the examples. - -For complex or commonly used operations, one can also place the -operations into an external text file and import it into the column -filter using the syntax '[col @filename.txt]'. The operations can -extend over multiple lines of the file, but multiple operations must -still be separated by commas or semi-colons. Any lines in the external text file -that begin with 2 slash characters ('//') will be ignored and may be -used to add comments into the file. - -Examples: - -\begin{verbatim} - [col Time, rate] - only the Time and rate columns will - appear in the filtered input file. - - [col Time, *raw] - include the Time column and any other - columns whose name ends with 'raw'. - - [col -TIME; Good == STATUS] - deletes the TIME column and - renames the status column to 'Good' - - [col PI=PHA * 1.1 + 0.2; #TUNIT#(column units) = 'counts';*] - - creates new PI column from PHA values - and also writes the TUNITn keyword - for the new column. The final '*' - expression means preserve all the - columns in the input table in the - virtual output table; without the '*' - the output table would only contain - the single 'PI' column. - - [col rate = rate/exposure, TUNIT#(&) = 'counts/s';*] - - recomputes the rate column by dividing - it by the EXPOSURE keyword value. This - also modifies the value of the TUNITn - keyword for this column. The use of the - '&' character for the keyword comment - string means preserve the existing - comment string for that keyword. The - final '*' preserves all the columns - in the input table in the virtual - output table. -\end{verbatim} - - -\section{Row Filtering Specification} - - When entering the name of a FITS table that is to be opened by a - program, an optional row filter may be specified to select a subset - of the rows in the table. A temporary new FITS file is created on - the fly which contains only those rows for which the row filter - expression evaluates to true. (The primary array and any other - extensions in the input file are also copied to the temporary - file). The original FITS file is closed and the new virtual file - is opened by the application program. The row filter expression is - enclosed in square brackets following the file name and extension - name (e.g., 'file.fits[events][GRADE==50]' selects only those rows - where the GRADE column value equals 50). When dealing with tables - where each row has an associated time and/or 2D spatial position, - the row filter expression can also be used to select rows based on - the times in a Good Time Intervals (GTI) extension, or on spatial - position as given in a SAO-style region file. - - -\subsection{General Syntax} - - The row filtering expression can be an arbitrarily complex series - of operations performed on constants, keyword values, and column - data taken from the specified FITS TABLE extension. The expression - must evaluate to a boolean value for each row of the table, where - a value of FALSE means that the row will be excluded. - - For complex or commonly used filters, one can place the expression - into a text file and import it into the row filter using the syntax - '[@filename.txt]'. The expression can be arbitrarily complex and - extend over multiple lines of the file. Any lines in the external - text file that begin with 2 slash characters ('//') will be ignored - and may be used to add comments into the file. - - Keyword and column data are referenced by name. Any string of - characters not surrounded by quotes (ie, a constant string) or - followed by an open parentheses (ie, a function name) will be - initially interpreted as a column name and its contents for the - current row inserted into the expression. If no such column exists, - a keyword of that name will be searched for and its value used, if - found. To force the name to be interpreted as a keyword (in case - there is both a column and keyword with the same name), precede the - keyword name with a single pound sign, '\#', as in '\#NAXIS2'. Due to - the generalities of FITS column and keyword names, if the column or - keyword name contains a space or a character which might appear as - an arithmetic term then enclose the name in '\$' characters as in - \$MAX PHA\$ or \#\$MAX-PHA\$. Names are case insensitive. - - To access a table entry in a row other than the current one, follow - the column's name with a row offset within curly braces. For - example, 'PHA\{-3\}' will evaluate to the value of column PHA, 3 rows - above the row currently being processed. One cannot specify an - absolute row number, only a relative offset. Rows that fall outside - the table will be treated as undefined, or NULLs. - - Boolean operators can be used in the expression in either their - Fortran or C forms. The following boolean operators are available: - -\begin{verbatim} - "equal" .eq. .EQ. == "not equal" .ne. .NE. != - "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< - "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => - "or" .or. .OR. || "and" .and. .AND. && - "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ -\end{verbatim} - -Note that the exclamation -point, '!', is a special UNIX character, so if it is used on the -command line rather than entered at a task prompt, it must be preceded -by a backslash to force the UNIX shell to ignore it. - - The expression may also include arithmetic operators and functions. - Trigonometric functions use radians, not degrees. The following - arithmetic operators and functions can be used in the expression - (function names are case insensitive). A null value will be returned - in case of illegal operations such as divide by zero, sqrt(negative) - log(negative), log10(negative), arccos(.gt. 1), arcsin(.gt. 1). - - -\begin{verbatim} - "addition" + "subtraction" - - "multiplication" * "division" / - "negation" - "exponentiation" ** ^ - "absolute value" abs(x) "cosine" cos(x) - "sine" sin(x) "tangent" tan(x) - "arc cosine" arccos(x) "arc sine" arcsin(x) - "arc tangent" arctan(x) "arc tangent" arctan2(y,x) - "hyperbolic cos" cosh(x) "hyperbolic sin" sinh(x) - "hyperbolic tan" tanh(x) "round to nearest int" round(x) - "round down to int" floor(x) "round up to int" ceil(x) - "exponential" exp(x) "square root" sqrt(x) - "natural log" log(x) "common log" log10(x) - "modulus" x % y "random # [0.0,1.0)" random() - "random Gaussian" randomn() "random Poisson" randomp(x) - "minimum" min(x,y) "maximum" max(x,y) - "cumulative sum" accum(x) "sequential difference" seqdiff(x) - "if-then-else" b?x:y - "angular separation" angsep(ra1,dec1,ra2,de2) (all in degrees) - "substring" strmid(s,p,n) "string search" strstr(s,r) -\end{verbatim} -Three different random number functions are provided: random(), with no -arguments, produces a uniform random deviate between 0 and 1; randomn(), -also with no arguments, produces a normal (Gaussian) random deviate with -zero mean and unit standard deviation; randomp(x) produces a Poisson random -deviate whose expected number of counts is X. X may be any positive real -number of expected counts, including fractional values, but the return value -is an integer. - -When the random functions are used in a vector expression, by default -the same random value will be used when evaluating each element of the vector. -If different random numbers are desired, then the name of a vector -column should be supplied as the single argument to the random -function (e.g., "flux + 0.1 * random(flux)", where "flux' is the -name of a vector column). This will create a vector of -random numbers that will be used in sequence when evaluating each -element of the vector expression. - - An alternate syntax for the min and max functions has only a single - argument which should be a vector value (see below). The result - will be the minimum/maximum element contained within the vector. - - The accum(x) function forms the cumulative sum of x, element by element. - Vector columns are supported simply by performing the summation process - through all the values. Null values are treated as 0. The seqdiff(x) - function forms the sequential difference of x, element by element. - The first value of seqdiff is the first value of x. A single null - value in x causes a pair of nulls in the output. The seqdiff and - accum functions are functional inverses, i.e., seqdiff(accum(x)) == x - as long as no null values are present. - -In the if-then-else expression, "b?x:y", b is an explicit boolean -value or expression. There is no automatic type conversion from -numeric to boolean values, so one needs to use "iVal!=0" instead of -merely "iVal" as the boolean argument. x and y can be any scalar data -type (including string). - - The angsep function computes the angular separation in degrees - between 2 celestial positions, where the first 2 parameters - give the RA-like and Dec-like coordinates (in decimal degrees) - of the first position, and the 3rd and 4th parameters give the - coordinates of the second position. - -The substring function strmid(S,P,N) extracts a substring from S, -starting at string position P, with a substring length N. The first -character position in S is labeled as 1. If P is 0, or refers to a -position beyond the end of S, then the extracted substring will be -NULL. S, P, and N may be functions of other columns. - -The string search function strstr(S,R) searches for the first occurrence -of the substring R in S. The result is an integer, indicating the -character position of the first match (where 1 is the first character -position of S). If no match is found, then strstr() returns a NULL -value. - - The following type casting operators are available, where the - enclosing parentheses are required and taken from the C language - usage. Also, the integer to real casts values to double precision: - -\begin{verbatim} - "real to integer" (int) x (INT) x - "integer to real" (float) i (FLOAT) i -\end{verbatim} - - In addition, several constants are built in for use in numerical - expressions: - - -\begin{verbatim} - #pi 3.1415... #e 2.7182... - #deg #pi/180 #row current row number - #null undefined value #snull undefined string -\end{verbatim} - - A string constant must be enclosed in quotes as in 'Crab'. The - "null" constants are useful for conditionally setting table values - to a NULL, or undefined, value (eg., "col1==-99 ? \#NULL : col1"). - - There is also a function for testing if two values are close to - each other, i.e., if they are "near" each other to within a user - specified tolerance. The arguments, value\_1 and value\_2 can be - integer or real and represent the two values who's proximity is - being tested to be within the specified tolerance, also an integer - or real: - -\begin{verbatim} - near(value_1, value_2, tolerance) -\end{verbatim} - When a NULL, or undefined, value is encountered in the FITS table, - the expression will evaluate to NULL unless the undefined value is - not actually required for evaluation, e.g. "TRUE .or. NULL" - evaluates to TRUE. The following two functions allow some NULL - detection and handling: - -\begin{verbatim} - "a null value?" ISNULL(x) - "define a value for null" DEFNULL(x,y) -\end{verbatim} - The former - returns a boolean value of TRUE if the argument x is NULL. The - later "defines" a value to be substituted for NULL values; it - returns the value of x if x is not NULL, otherwise it returns the - value of y. - - -\subsection{Bit Masks} - - Bit masks can be used to select out rows from bit columns (TFORMn = - \#X) in FITS files. To represent the mask, binary, octal, and hex - formats are allowed: - - -\begin{verbatim} - binary: b0110xx1010000101xxxx0001 - octal: o720x1 -> (b111010000xxx001) - hex: h0FxD -> (b00001111xxxx1101) -\end{verbatim} - - In all the representations, an x or X is allowed in the mask as a - wild card. Note that the x represents a different number of wild - card bits in each representation. All representations are case - insensitive. - - To construct the boolean expression using the mask as the boolean - equal operator described above on a bit table column. For example, - if you had a 7 bit column named flags in a FITS table and wanted - all rows having the bit pattern 0010011, the selection expression - would be: - - -\begin{verbatim} - flags == b0010011 - or - flags .eq. b10011 -\end{verbatim} - - It is also possible to test if a range of bits is less than, less - than equal, greater than and greater than equal to a particular - boolean value: - - -\begin{verbatim} - flags <= bxxx010xx - flags .gt. bxxx100xx - flags .le. b1xxxxxxx -\end{verbatim} - - Notice the use of the x bit value to limit the range of bits being - compared. - - It is not necessary to specify the leading (most significant) zero - (0) bits in the mask, as shown in the second expression above. - - Bit wise AND, OR and NOT operations are also possible on two or - more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) - operators. All of these operators result in a bit field which can - then be used with the equal operator. For example: - - -\begin{verbatim} - (!flags) == b1101100 - (flags & b1000001) == bx000001 -\end{verbatim} - - Bit fields can be appended as well using the '+' operator. Strings - can be concatenated this way, too. - - -\subsection{Vector Columns} - - Vector columns can also be used in building the expression. No - special syntax is required if one wants to operate on all elements - of the vector. Simply use the column name as for a scalar column. - Vector columns can be freely intermixed with scalar columns or - constants in virtually all expressions. The result will be of the - same dimension as the vector. Two vectors in an expression, though, - need to have the same number of elements and have the same - dimensions. The only places a vector column cannot be used (for - now, anyway) are the SAO region functions and the NEAR boolean - function. - - Arithmetic and logical operations are all performed on an element by - element basis. Comparing two vector columns, eg "COL1 == COL2", - thus results in another vector of boolean values indicating which - elements of the two vectors are equal. - - Eight functions are available that operate on a vector and return a - scalar result: - -\begin{verbatim} - "minimum" MIN(V) "maximum" MAX(V) - "average" AVERAGE(V) "median" MEDIAN(V) - "summation" SUM(V) "standard deviation" STDDEV(V) - "# of values" NELEM(V) "# of non-null values" NVALID(V) -\end{verbatim} - where V represents the name of a vector column or a manually - constructed vector using curly brackets as described below. The - first 6 of these functions ignore any null values in the vector when - computing the result. The STDDEV() function computes the sample - standard deviation, i.e. it is proportional to 1/SQRT(N-1) instead - of 1/SQRT(N), where N is NVALID(V). - - The SUM function literally sums all the elements in x, returning a - scalar value. If x is a boolean vector, SUM returns the number - of TRUE elements. The NELEM function returns the number of elements - in vector x whereas NVALID return the number of non-null elements in - the vector. (NELEM also operates on bit and string columns, - returning their column widths.) As an example, to test whether all - elements of two vectors satisfy a given logical comparison, one can - use the expression - -\begin{verbatim} - SUM( COL1 > COL2 ) == NELEM( COL1 ) -\end{verbatim} - - which will return TRUE if all elements of COL1 are greater than - their corresponding elements in COL2. - - To specify a single element of a vector, give the column name - followed by a comma-separated list of coordinates enclosed in - square brackets. For example, if a vector column named PHAS exists - in the table as a one dimensional, 256 component list of numbers - from which you wanted to select the 57th component for use in the - expression, then PHAS[57] would do the trick. Higher dimensional - arrays of data may appear in a column. But in order to interpret - them, the TDIMn keyword must appear in the header. Assuming that a - (4,4,4,4) array is packed into each row of a column named ARRAY4D, - the (1,2,3,4) component element of each row is accessed by - ARRAY4D[1,2,3,4]. Arrays up to dimension 5 are currently - supported. Each vector index can itself be an expression, although - it must evaluate to an integer value within the bounds of the - vector. Vector columns which contain spaces or arithmetic operators - must have their names enclosed in "\$" characters as with - \$ARRAY-4D\$[1,2,3,4]. - - A more C-like syntax for specifying vector indices is also - available. The element used in the preceding example alternatively - could be specified with the syntax ARRAY4D[4][3][2][1]. Note the - reverse order of indices (as in C), as well as the fact that the - values are still ones-based (as in Fortran -- adopted to avoid - ambiguity for 1D vectors). With this syntax, one does not need to - specify all of the indices. To extract a 3D slice of this 4D - array, use ARRAY4D[4]. - - Variable-length vector columns are not supported. - - Vectors can be manually constructed within the expression using a - comma-separated list of elements surrounded by curly braces ('\{\}'). - For example, '\{1,3,6,1\}' is a 4-element vector containing the values - 1, 3, 6, and 1. The vector can contain only boolean, integer, and - real values (or expressions). The elements will be promoted to the - highest datatype present. Any elements which are themselves - vectors, will be expanded out with each of its elements becoming an - element in the constructed vector. - - -\subsection{Good Time Interval Filtering} - - A common filtering method involves selecting rows which have a time - value which lies within what is called a Good Time Interval or GTI. - The time intervals are defined in a separate FITS table extension - which contains 2 columns giving the start and stop time of each - good interval. The filtering operation accepts only those rows of - the input table which have an associated time which falls within - one of the time intervals defined in the GTI extension. A high - level function, gtifilter(a,b,c,d), is available which evaluates - each row of the input table and returns TRUE or FALSE depending - whether the row is inside or outside the good time interval. The - syntax is - -\begin{verbatim} - gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) -\end{verbatim} - where each "[]" demarks optional parameters. Note that the quotes - around the gtifile and START/STOP column are required. Either single - or double quotes may be used. In cases where this expression is - entered on the Unix command line, enclose the entire expression in - double quotes, and then use single quotes within the expression to - enclose the 'gtifile' and other terms. It is also usually possible - to do the reverse, and enclose the whole expression in single quotes - and then use double quotes within the expression. The gtifile, - if specified, can be blank ("") which will mean to use the first - extension with the name "*GTI*" in the current file, a plain - extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be - used to select an extension in the current file, or a regular - filename with or without an extension specifier which in the latter - case will mean to use the first extension with an extension name - "*GTI*". Expr can be any arithmetic expression, including simply - the time column name. A vector time expression will produce a - vector boolean result. STARTCOL and STOPCOL are the names of the - START/STOP columns in the GTI extension. If one of them is - specified, they both must be. - - In its simplest form, no parameters need to be provided -- default - values will be used. The expression "gtifilter()" is equivalent to - -\begin{verbatim} - gtifilter( "", TIME, "*START*", "*STOP*" ) -\end{verbatim} - This will search the current file for a GTI extension, filter the - TIME column in the current table, using START/STOP times taken from - columns in the GTI extension with names containing the strings - "START" and "STOP". The wildcards ('*') allow slight variations in - naming conventions such as "TSTART" or "STARTTIME". The same - default values apply for unspecified parameters when the first one - or two parameters are specified. The function automatically - searches for TIMEZERO/I/F keywords in the current and GTI - extensions, applying a relative time offset, if necessary. - - -\subsection{Spatial Region Filtering} - - Another common filtering method selects rows based on whether the - spatial position associated with each row is located within a given - 2-dimensional region. The syntax for this high-level filter is - -\begin{verbatim} - regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) -\end{verbatim} - where each "[]" demarks optional parameters. The region file name - is required and must be enclosed in quotes. The remaining - parameters are optional. There are 2 supported formats for the - region file: ASCII file or FITS binary table. The region file - contains a list of one or more geometric shapes (circle, - ellipse, box, etc.) which defines a region on the celestial sphere - or an area within a particular 2D image. The region file is - typically generated using an image display program such as fv/POW - (distribute by the HEASARC), or ds9 (distributed by the Smithsonian - Astrophysical Observatory). Users should refer to the documentation - provided with these programs for more details on the syntax used in - the region files. The FITS region file format is defined in a document - available from the FITS Support Office at - http://fits.gsfc.nasa.gov/ registry/ region.html - - In its simplest form, (e.g., regfilter("region.reg") ) the - coordinates in the default 'X' and 'Y' columns will be used to - determine if each row is inside or outside the area specified in - the region file. Alternate position column names, or expressions, - may be entered if needed, as in - -\begin{verbatim} - regfilter("region.reg", XPOS, YPOS) -\end{verbatim} - Region filtering can be applied most unambiguously if the positions - in the region file and in the table to be filtered are both give in - terms of absolute celestial coordinate units. In this case the - locations and sizes of the geometric shapes in the region file are - specified in angular units on the sky (e.g., positions given in - R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, - each row of the filtered table will have a celestial coordinate - associated with it. This association is usually implemented using - a set of so-called 'World Coordinate System' (or WCS) FITS keywords - that define the coordinate transformation that must be applied to - the values in the 'X' and 'Y' columns to calculate the coordinate. - - Alternatively, one can perform spatial filtering using unitless - 'pixel' coordinates for the regions and row positions. In this - case the user must be careful to ensure that the positions in the 2 - files are self-consistent. A typical problem is that the region - file may be generated using a binned image, but the unbinned - coordinates are given in the event table. The ROSAT events files, - for example, have X and Y pixel coordinates that range from 1 - - 15360. These coordinates are typically binned by a factor of 32 to - produce a 480x480 pixel image. If one then uses a region file - generated from this image (in image pixel units) to filter the - ROSAT events file, then the X and Y column values must be converted - to corresponding pixel units as in: - -\begin{verbatim} - regfilter("rosat.reg", X/32.+.5, Y/32.+.5) -\end{verbatim} - Note that this binning conversion is not necessary if the region - file is specified using celestial coordinate units instead of pixel - units because CFITSIO is then able to directly compare the - celestial coordinate of each row in the table with the celestial - coordinates in the region file without having to know anything - about how the image may have been binned. - - The last "wcs cols" parameter should rarely be needed. If supplied, - this string contains the names of the 2 columns (space or comma - separated) which have the associated WCS keywords. If not supplied, - the filter will scan the X and Y expressions for column names. - If only one is found in each expression, those columns will be - used, otherwise an error will be returned. - - These region shapes are supported (names are case insensitive): - -\begin{verbatim} - Point ( X1, Y1 ) <- One pixel square region - Line ( X1, Y1, X2, Y2 ) <- One pixel wide region - Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with - Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered - Box ( Xc, Yc, Wdth, Hght, A ) V within the region - Diamond ( Xc, Yc, Wdth, Hght, A ) - Circle ( Xc, Yc, R ) - Annulus ( Xc, Yc, Rin, Rout ) - Ellipse ( Xc, Yc, Rx, Ry, A ) - Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) - Sector ( Xc, Yc, Amin, Amax ) -\end{verbatim} - where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are - the coordinates of the shape's edges; Rxxx are the shapes' various - Radii or semi-major/minor axes; and Axxx are the angles of rotation - (or bounding angles for Sector) in degrees. For rotated shapes, the - rotation angle can be left off, indicating no rotation. Common - alternate names for the regions can also be used: rotbox = box; - rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie - = sector. When a shape's name is preceded by a minus sign, '-', - the defined region is instead the area *outside* its boundary (ie, - the region is inverted). All the shapes within a single region - file are OR'd together to create the region, and the order is - significant. The overall way of looking at region files is that if - the first region is an excluded region then a dummy included region - of the whole detector is inserted in the front. Then each region - specification as it is processed overrides any selections inside of - that region specified by previous regions. Another way of thinking - about this is that if a previous excluded region is completely - inside of a subsequent included region the excluded region is - ignored. - - The positional coordinates may be given either in pixel units, - decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes - may be given in pixels, degrees, arcminutes, or arcseconds. Look - at examples of region file produced by fv/POW or ds9 for further - details of the region file format. - - There are three functions that are primarily for use with SAO region - files and the FSAOI task, but they can be used directly. They - return a boolean true or false depending on whether a two - dimensional point is in the region or not: - -\begin{verbatim} - "point in a circular region" - circle(xcntr,ycntr,radius,Xcolumn,Ycolumn) - - "point in an elliptical region" - ellipse(xcntr,ycntr,xhlf_wdth,yhlf_wdth,rotation,Xcolumn,Ycolumn) - - "point in a rectangular region" - box(xcntr,ycntr,xfll_wdth,yfll_wdth,rotation,Xcolumn,Ycolumn) - - where - (xcntr,ycntr) are the (x,y) position of the center of the region - (xhlf_wdth,yhlf_wdth) are the (x,y) half widths of the region - (xfll_wdth,yfll_wdth) are the (x,y) full widths of the region - (radius) is half the diameter of the circle - (rotation) is the angle(degrees) that the region is rotated with - respect to (xcntr,ycntr) - (Xcoord,Ycoord) are the (x,y) coordinates to test, usually column - names - NOTE: each parameter can itself be an expression, not merely a - column name or constant. -\end{verbatim} - - -\subsection{Example Row Filters} - -\begin{verbatim} - [ binary && mag <= 5.0] - Extract all binary stars brighter - than fifth magnitude (note that - the initial space is necessary to - prevent it from being treated as a - binning specification) - - [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 - - [IMAGE[4,5] .gt. 100] - Extract all rows that have the - (4,5) component of the IMAGE column - greater than 100 - - [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the - absolute value of the sine of theta - less than a half where the angles - are tabulated in degrees - - [SUM( SPEC > 3*BACKGRND )>=1] - Extract all rows containing a - spectrum, held in vector column - SPEC, with at least one value 3 - times greater than the background - level held in a keyword, BACKGRND - - [VCOL=={1,4,2}] - Extract all rows whose vector column - VCOL contains the 3-elements 1, 4, and - 2. - - [@rowFilter.txt] - Extract rows using the expression - contained within the text file - rowFilter.txt - - [gtifilter()] - Search the current file for a GTI - extension, filter the TIME - column in the current table, using - START/STOP times taken from - columns in the GTI extension - - [regfilter("pow.reg")] - Extract rows which have a coordinate - (as given in the X and Y columns) - within the spatial region specified - in the pow.reg region file. - - [regfilter("pow.reg", Xs, Ys)] - Same as above, except that the - Xs and Ys columns will be used to - determine the coordinate of each - row in the table. -\end{verbatim} - - -\section{ Binning or Histogramming Specification} - -The optional binning specifier is enclosed in square brackets and can -be distinguished from a general row filter specification by the fact -that it begins with the keyword 'bin' not immediately followed by an -equals sign. When binning is specified, a temporary N-dimensional FITS -primary array is created by computing the histogram of the values in -the specified columns of a FITS table extension. After the histogram -is computed the input FITS file containing the table is then closed and -the temporary FITS primary array is opened and passed to the -application program. Thus, the application program never sees the -original FITS table and only sees the image in the new temporary file -(which has no additional extensions). Obviously, the application -program must be expecting to open a FITS image and not a FITS table in -this case. - -The data type of the FITS histogram image may be specified by appending -'b' (for 8-bit byte), 'i' (for 16-bit integers), 'j' (for 32-bit -integer), 'r' (for 32-bit floating points), or 'd' (for 64-bit double -precision floating point) to the 'bin' keyword (e.g. '[binr X]' -creates a real floating point image). If the datatype is not -explicitly specified then a 32-bit integer image will be created by -default, unless the weighting option is also specified in which case -the image will have a 32-bit floating point data type by default. - -The histogram image may have from 1 to 4 dimensions (axes), depending -on the number of columns that are specified. The general form of the -binning specification is: - -\begin{verbatim} - [bin{bijrd} Xcol=min:max:binsize, Ycol= ..., Zcol=..., Tcol=...; weight] -\end{verbatim} -in which up to 4 columns, each corresponding to an axis of the image, -are listed. The column names are case insensitive, and the column -number may be given instead of the name, preceded by a pound sign -(e.g., [bin \#4=1:512]). If the column name is not specified, then -CFITSIO will first try to use the 'preferred column' as specified by -the CPREF keyword if it exists (e.g., 'CPREF = 'DETX,DETY'), otherwise -column names 'X', 'Y', 'Z', and 'T' will be assumed for each of the 4 -axes, respectively. In cases where the column name could be confused -with an arithmetic expression, enclose the column name in parentheses to -force the name to be interpreted literally. - -Each column name may be followed by an equals sign and then the lower -and upper range of the histogram, and the size of the histogram bins, -separated by colons. Spaces are allowed before and after the equals -sign but not within the 'min:max:binsize' string. The min, max and -binsize values may be integer or floating point numbers, or they may be -the names of keywords in the header of the table. If the latter, then -the value of that keyword is substituted into the expression. - -Default values for the min, max and binsize quantities will be -used if not explicitly given in the binning expression as shown -in these examples: - -\begin{verbatim} - [bin x = :512:2] - use default minimum value - [bin x = 1::2] - use default maximum value - [bin x = 1:512] - use default bin size - [bin x = 1:] - use default maximum value and bin size - [bin x = :512] - use default minimum value and bin size - [bin x = 2] - use default minimum and maximum values - [bin x] - use default minimum, maximum and bin size - [bin 4] - default 2-D image, bin size = 4 in both axes - [bin] - default 2-D image -\end{verbatim} -CFITSIO will use the value of the TLMINn, TLMAXn, and TDBINn keywords, -if they exist, for the default min, max, and binsize, respectively. If -they do not exist then CFITSIO will use the actual minimum and maximum -values in the column for the histogram min and max values. The default -binsize will be set to 1, or (max - min) / 10., whichever is smaller, -so that the histogram will have at least 10 bins along each axis. - -A shortcut notation is allowed if all the columns/axes have the same -binning specification. In this case all the column names may be listed -within parentheses, followed by the (single) binning specification, as -in: - -\begin{verbatim} - [bin (X,Y)=1:512:2] - [bin (X,Y) = 5] -\end{verbatim} - -The optional weighting factor is the last item in the binning specifier -and, if present, is separated from the list of columns by a -semi-colon. As the histogram is accumulated, this weight is used to -incremented the value of the appropriated bin in the histogram. If the -weighting factor is not specified, then the default weight = 1 is -assumed. The weighting factor may be a constant integer or floating -point number, or the name of a keyword containing the weighting value. -Or the weighting factor may be the name of a table column in which case -the value in that column, on a row by row basis, will be used. - -In some cases, the column or keyword may give the reciprocal of the -actual weight value that is needed. In this case, precede the weight -keyword or column name by a slash '/' to tell CFITSIO to use the -reciprocal of the value when constructing the histogram. - -For complex or commonly used histograms, one can also place its -description into a text file and import it into the binning -specification using the syntax '[bin @filename.txt]'. The file's -contents can extend over multiple lines, although it must still -conform to the no-spaces rule for the min:max:binsize syntax and each -axis specification must still be comma-separated. Any lines in the -external text file that begin with 2 slash characters ('//') will be -ignored and may be used to add comments into the file. - - Examples: - - -\begin{verbatim} - [bini detx, dety] - 2-D, 16-bit integer histogram - of DETX and DETY columns, using - default values for the histogram - range and binsize - - [bin (detx, dety)=16; /exposure] - 2-D, 32-bit real histogram of DETX - and DETY columns with a bin size = 16 - in both axes. The histogram values - are divided by the EXPOSURE keyword - value. - - [bin time=TSTART:TSTOP:0.1] - 1-D lightcurve, range determined by - the TSTART and TSTOP keywords, - with 0.1 unit size bins. - - [bin pha, time=8000.:8100.:0.1] - 2-D image using default binning - of the PHA column for the X axis, - and 1000 bins in the range - 8000. to 8100. for the Y axis. - - [bin @binFilter.txt] - Use the contents of the text file - binFilter.txt for the binning - specifications. - -\end{verbatim} - - -\chapter{Template Files } - -When a new FITS file is created with a call to fits\_create\_file, the -name of a template file may be supplied in parentheses immediately -following the name of the new file to be created. This template is -used to define the structure of one or more HDUs in the new file. The -template file may be another FITS file, in which case the newly created -file will have exactly the same keywords in each HDU as in the template -FITS file, but all the data units will be filled with zeros. The -template file may also be an ASCII text file, where each line (in -general) describes one FITS keyword record. The format of the ASCII -template file is described in the following sections. - - -\section{Detailed Template Line Format} - -The format of each ASCII template line closely follows the format of a -FITS keyword record: - -\begin{verbatim} - KEYWORD = KEYVALUE / COMMENT -\end{verbatim} -except that free format may be used (e.g., the equals sign may appear -at any position in the line) and TAB characters are allowed and are -treated the same as space characters. The KEYVALUE and COMMENT fields -are optional. The equals sign character is also optional, but it is -recommended that it be included for clarity. Any template line that -begins with the pound '\#' character is ignored by the template parser -and may be use to insert comments into the template file itself. - -The KEYWORD name field is limited to 8 characters in length and only -the letters A-Z, digits 0-9, and the hyphen and underscore characters -may be used, without any embedded spaces. Lowercase letters in the -template keyword name will be converted to uppercase. Leading spaces -in the template line preceding the keyword name are generally ignored, -except if the first 8 characters of a template line are all blank, then -the entire line is treated as a FITS comment keyword (with a blank -keyword name) and is copied verbatim into the FITS header. - -The KEYVALUE field may have any allowed FITS data type: character -string, logical, integer, real, complex integer, or complex real. Integer -values must be within the allowed range of a 'signed long' variable; -some C compilers only suppport 4-byte long integers with a range -from -2147483648 to +2147483647, whereas other C compilers support 8-byte -integers with a range of plus or minus 2**63. - -The character string values need not be enclosed in single quote characters -unless they are necessary to distinguish the string from a different -data type (e.g. 2.0 is a real but '2.0' is a string). The keyword has -an undefined (null) value if the template record only contains blanks -following the "=" or between the "=" and the "/" comment field -delimiter. - -String keyword values longer than 68 characters (the maximum length -that will fit in a single FITS keyword record) are permitted using the -CFITSIO long string convention. They can either be specified as a -single long line in the template, or by using multiple lines where the -continuing lines contain the 'CONTINUE' keyword, as in this example: - -\begin{verbatim} - LONGKEY = 'This is a long string value that is contin&' - CONTINUE 'ued over 2 records' / comment field goes here -\end{verbatim} -The format of template lines with CONTINUE keyword is very strict: 3 -spaces must follow CONTINUE and the rest of the line is copied verbatim -to the FITS file. - -The start of the optional COMMENT field must be preceded by "/", which -is used to separate it from the keyword value field. Exceptions are if -the KEYWORD name field contains COMMENT, HISTORY, CONTINUE, or if the -first 8 characters of the template line are blanks. - -More than one Header-Data Unit (HDU) may be defined in the template -file. The start of an HDU definition is denoted with a SIMPLE or -XTENSION template line: - -1) SIMPLE begins a Primary HDU definition. SIMPLE may only appear as -the first keyword in the template file. If the template file begins -with XTENSION instead of SIMPLE, then a default empty Primary HDU is -created, and the template is then assumed to define the keywords -starting with the first extension following the Primary HDU. - -2) XTENSION marks the beginning of a new extension HDU definition. The -previous HDU will be closed at this point and processing of the next -extension begins. - - -\section{Auto-indexing of Keywords} - -If a template keyword name ends with a "\#" character, it is said to be -'auto-indexed'. Each "\#" character will be replaced by the current -integer index value, which gets reset = 1 at the start of each new HDU -in the file (or 7 in the special case of a GROUP definition). The -FIRST indexed keyword in each template HDU definition is used as the -'incrementor'; each subsequent occurrence of this SAME keyword will -cause the index value to be incremented. This behavior can be rather -subtle, as illustrated in the following examples in which the TTYPE -keyword is the incrementor in both cases: - -\begin{verbatim} - TTYPE# = TIME - TFORM# = 1D - TTYPE# = RATE - TFORM# = 1E -\end{verbatim} -will create TTYPE1, TFORM1, TTYPE2, and TFORM2 keywords. But if the -template looks like, - -\begin{verbatim} - TTYPE# = TIME - TTYPE# = RATE - TFORM# = 1D - TFORM# = 1E -\end{verbatim} -this results in a FITS files with TTYPE1, TTYPE2, TFORM2, and TFORM2, -which is probably not what was intended! - - -\section{Template Parser Directives} - -In addition to the template lines which define individual keywords, the -template parser recognizes 3 special directives which are each preceded -by the backslash character: \verb+ \include, \group+, and \verb+ \end+. - -The 'include' directive must be followed by a filename. It forces the -parser to temporarily stop reading the current template file and begin -reading the include file. Once the parser reaches the end of the -include file it continues parsing the current template file. Include -files can be nested, and HDU definitions can span multiple template -files. - -The start of a GROUP definition is denoted with the 'group' directive, -and the end of a GROUP definition is denoted with the 'end' directive. -Each GROUP contains 0 or more member blocks (HDUs or GROUPs). Member -blocks of type GROUP can contain their own member blocks. The GROUP -definition itself occupies one FITS file HDU of special type (GROUP -HDU), so if a template specifies 1 group with 1 member HDU like: - -\begin{verbatim} -\group -grpdescr = 'demo' -xtension bintable -# this bintable has 0 cols, 0 rows -\end -\end{verbatim} -then the parser creates a FITS file with 3 HDUs : - -\begin{verbatim} -1) dummy PHDU -2) GROUP HDU (has 1 member, which is bintable in HDU number 3) -3) bintable (member of GROUP in HDU number 2) -\end{verbatim} -Technically speaking, the GROUP HDU is a BINTABLE with 6 columns. Applications -can define additional columns in a GROUP HDU using TFORMn and TTYPEn -(where n is 7, 8, ....) keywords or their auto-indexing equivalents. - -For a more complicated example of a template file using the group directives, -look at the sample.tpl file that is included in the CFITSIO distribution. - - -\section{Formal Template Syntax} - -The template syntax can formally be defined as follows: - -\begin{verbatim} - TEMPLATE = BLOCK [ BLOCK ... ] - - BLOCK = { HDU | GROUP } - - GROUP = \GROUP [ BLOCK ... ] \END - - HDU = XTENSION [ LINE ... ] { XTENSION | \GROUP | \END | EOF } - - LINE = [ KEYWORD [ = ] ] [ VALUE ] [ / COMMENT ] - - X ... - X can be present 1 or more times - { X | Y } - X or Y - [ X ] - X is optional -\end{verbatim} - -At the topmost level, the template defines 1 or more template blocks. Blocks -can be either HDU (Header Data Unit) or a GROUP. For each block the parser -creates 1 (or more for GROUPs) FITS file HDUs. - - - -\section{Errors} - -In general the fits\_execute\_template() function tries to be as atomic -as possible, so either everything is done or nothing is done. If an -error occurs during parsing of the template, fits\_execute\_template() -will (try to) delete the top level BLOCK (with all its children if any) -in which the error occurred, then it will stop reading the template file -and it will return with an error. - - -\section{Examples} - -1. This template file will create a 200 x 300 pixel image, with 4-byte -integer pixel values, in the primary HDU: - -\begin{verbatim} - SIMPLE = T - BITPIX = 32 - NAXIS = 2 / number of dimensions - NAXIS1 = 100 / length of first axis - NAXIS2 = 200 / length of second axis - OBJECT = NGC 253 / name of observed object -\end{verbatim} -The allowed values of BITPIX are 8, 16, 32, -32, or -64, -representing, respectively, 8-bit integer, 16-bit integer, 32-bit -integer, 32-bit floating point, or 64 bit floating point pixels. - -2. To create a FITS table, the template first needs to include -XTENSION = TABLE or BINTABLE to define whether it is an ASCII or binary -table, and NAXIS2 to define the number of rows in the table. Two -template lines are then needed to define the name (TTYPEn) and FITS data -format (TFORMn) of the columns, as in this example: - -\begin{verbatim} - xtension = bintable - naxis2 = 40 - ttype# = Name - tform# = 10a - ttype# = Npoints - tform# = j - ttype# = Rate - tunit# = counts/s - tform# = e -\end{verbatim} -The above example defines a null primary array followed by a 40-row -binary table extension with 3 columns called 'Name', 'Npoints', and -'Rate', with data formats of '10A' (ASCII character string), '1J' -(integer) and '1E' (floating point), respectively. Note that the other -required FITS keywords (BITPIX, NAXIS, NAXIS1, PCOUNT, GCOUNT, TFIELDS, -and END) do not need to be explicitly defined in the template because -their values can be inferred from the other keywords in the template. -This example also illustrates that the templates are generally -case-insensitive (the keyword names and TFORMn values are converted to -upper-case in the FITS file) and that string keyword values generally -do not need to be enclosed in quotes. - - -\chapter{ Summary of all FITSIO User-Interface Subroutines } - - Error Status Routines page~\pageref{FTVERS} - -\begin{verbatim} - FTVERS( > version) - FTGERR(status, > errtext) - FTGMSG( > errmsg) - FTRPRT (stream, > status) - FTPMSG(errmsg) - FTPMRK - FTCMSG - FTCMRK -\end{verbatim} - FITS File Open and Close Subroutines: page~\pageref{FTOPEN} - -\begin{verbatim} - FTOPEN(unit,filename,rwmode, > blocksize,status) - FTDKOPN(unit,filename,rwmode, > blocksize,status) - FTNOPN(unit,filename,rwmode, > status) - FTDOPN(unit,filename,rwmode, > status) - FTTOPN(unit,filename,rwmode, > status) - FTIOPN(unit,filename,rwmode, > status) - FTREOPEN(unit, > newunit, status) - FTINIT(unit,filename,blocksize, > status) - FTDKINIT(unit,filename,blocksize, > status) - FTTPLT(unit, filename, tplfilename, > status) - FTFLUS(unit, > status) - FTCLOS(unit, > status) - FTDELT(unit, > status) - FTGIOU( > iounit, status) - FTFIOU(iounit, > status) - CFITS2Unit(fitsfile *ptr) (C routine) - CUnit2FITS(int unit) (C routine) - FTEXTN(filename, > nhdu, status) - FTFLNM(unit, > filename, status) - FTFLMD(unit, > iomode, status) - FTURLT(unit, > urltype, status) - FTIURL(filename, > filetype, infile, outfile, extspec, filter, - binspec, colspec, status) - FTRTNM(filename, > rootname, status) - FTEXIST(filename, > exist, status) -\end{verbatim} - HDU-Level Operations: page~\pageref{FTMAHD} - -\begin{verbatim} - FTMAHD(unit,nhdu, > hdutype,status) - FTMRHD(unit,nmove, > hdutype,status) - FTGHDN(unit, > nhdu) - FTMNHD(unit, hdutype, extname, extver, > status) - FTGHDT(unit, > hdutype, status) - FTTHDU(unit, > hdunum, status) - FTCRHD(unit, > status) - FTIIMG(unit,bitpix,naxis,naxes, > status) - FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > - status) - FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) - FTRSIM(unit,bitpix,naxis,naxes,status) - FTDHDU(unit, > hdutype,status) - FTCPFL(iunit,ounit,previous, current, following, > status) - FTCOPY(iunit,ounit,morekeys, > status) - FTCPHD(inunit, outunit, > status) - FTCPDT(iunit,ounit, > status) -\end{verbatim} - Subroutines to specify or modify the structure of the CHDU: page~\pageref{FTRDEF} - -\begin{verbatim} - FTRDEF(unit, > status) (DEPRECATED) - FTPDEF(unit,bitpix,naxis,naxes,pcount,gcount, > status) (DEPRECATED) - FTADEF(unit,rowlen,tfields,tbcol,tform,nrows > status) (DEPRECATED) - FTBDEF(unit,tfields,tform,varidat,nrows > status) (DEPRECATED) - FTDDEF(unit,bytlen, > status) (DEPRECATED) - FTPTHP(unit,theap, > status) -\end{verbatim} - Header Space and Position Subroutines: page~\pageref{FTHDEF} - -\begin{verbatim} - FTHDEF(unit,morekeys, > status) - FTGHSP(iunit, > keysexist,keysadd,status) - FTGHPS(iunit, > keysexist,key_no,status) -\end{verbatim} - Read or Write Standard Header Subroutines: page~\pageref{FTPHPR} - -\begin{verbatim} - FTPHPS(unit,bitpix,naxis,naxes, > status) - FTPHPR(unit,simple,bitpix,naxis,naxes,pcount,gcount,extend, > status) - FTGHPR(unit,maxdim, > simple,bitpix,naxis,naxes,pcount,gcount,extend, - status) - FTPHTB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > - status) - FTGHTB(unit,maxdim, > rowlen,nrows,tfields,ttype,tbcol,tform,tunit, - extname,status) - FTPHBN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) - FTGHBN(unit,maxdim, > nrows,tfields,ttype,tform,tunit,extname,varidat, - status) -\end{verbatim} - Write Keyword Subroutines: page~\pageref{FTPREC} - -\begin{verbatim} - FTPREC(unit,card, > status) - FTPCOM(unit,comment, > status) - FTPHIS(unit,history, > status) - FTPDAT(unit, > status) - FTPKY[JKLS](unit,keyword,keyval,comment, > status) - FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - FTPKLS(unit,keyword,keyval,comment, > status) - FTPLSW(unit, > status) - FTPKYU(unit,keyword,comment, > status) - FTPKN[JKLS](unit,keyroot,startno,no_keys,keyvals,comments, > status) - FTPKN[EDFG](unit,keyroot,startno,no_keys,keyvals,decimals,comments, > - status) - FTCPKYinunit, outunit, innum, outnum, keyroot, > status) - FTPKYT(unit,keyword,intval,dblval,comment, > status) - FTPKTP(unit, filename, > status) - FTPUNT(unit,keyword,units, > status) -\end{verbatim} - Insert Keyword Subroutines: page~\pageref{FTIREC} - -\begin{verbatim} - FTIREC(unit,key_no,card, > status) - FTIKY[JKLS](unit,keyword,keyval,comment, > status) - FTIKLS(unit,keyword,keyval,comment, > status) - FTIKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - FTIKYU(unit,keyword,comment, > status) -\end{verbatim} - Read Keyword Subroutines: page~\pageref{FTGREC} - -\begin{verbatim} - FTGREC(unit,key_no, > card,status) - FTGKYN(unit,key_no, > keyword,value,comment,status) - FTGCRD(unit,keyword, > card,status) - FTGNXK(unit,inclist,ninc,exclist,nexc, > card,status) - FTGKEY(unit,keyword, > value,comment,status) - FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) - FTGKSL(unit,keyword, > length,status) - FTGSKY(unit,keyword,firstchar,maxchar,> keyval,length,comment,status) - FTGKN[EDJKLS](unit,keyroot,startno,max_keys, > keyvals,nfound,status) - FTGKYT(unit,keyword, > intval,dblval,comment,status) - FTGUNT(unit,keyword, > units,status) -\end{verbatim} - Modify Keyword Subroutines: page~\pageref{FTMREC} - -\begin{verbatim} - FTMREC(unit,key_no,card, > status) - FTMCRD(unit,keyword,card, > status) - FTMNAM(unit,oldkey,keyword, > status) - FTMCOM(unit,keyword,comment, > status) - FTMKY[JKLS](unit,keyword,keyval,comment, > status) - FTMKLS(unit,keyword,keyval,comment, > status) - FTMKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - FTMKYU(unit,keyword,comment, > status) -\end{verbatim} - Update Keyword Subroutines: page~\pageref{FTUCRD} - -\begin{verbatim} - FTUCRD(unit,keyword,card, > status) - FTUKY[JKLS](unit,keyword,keyval,comment, > status) - FTUKLS(unit,keyword,keyval,comment, > status) - FTUKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - FTUKYU(unit,keyword,comment, > status) -\end{verbatim} - Delete Keyword Subroutines: page~\pageref{FTDREC} - -\begin{verbatim} - FTDREC(unit,key_no, > status) - FTDKEY(unit,keyword, > status) -\end{verbatim} - Define Data Scaling Parameters and Undefined Pixel Flags: page~\pageref{FTPSCL} - -\begin{verbatim} - FTPSCL(unit,bscale,bzero, > status) - FTTSCL(unit,colnum,tscal,tzero, > status) - FTPNUL(unit,blank, > status) - FTSNUL(unit,colnum,snull > status) - FTTNUL(unit,colnum,tnull > status) -\end{verbatim} - FITS Primary Array or IMAGE Extension I/O Subroutines: page~\pageref{FTPPR} - -\begin{verbatim} - FTGIDT(unit, > bitpix,status) - FTGIET(unit, > bitpix,status) - FTGIDM(unit, > naxis,status) - FTGISZ(unit, maxdim, > naxes,status) - FTGIPR(unit, maxdim, > bitpix,naxis,naxes,status) - FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) - FTPPN[BIJKED](unit,group,fpixel,nelements,values,nullval > status) - FTPPRU(unit,group,fpixel,nelements, > status) - FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) - FTGPF[BIJKED](unit,group,fpixel,nelements, > values,flagvals,anyf,status) - FTPGP[BIJKED](unit,group,fparm,nparm,values, > status) - FTGGP[BIJKED](unit,group,fparm,nparm, > values,status) - FTP2D[BIJKED](unit,group,dim1,naxis1,naxis2,image, > status) - FTP3D[BIJKED](unit,group,dim1,dim2,naxis1,naxis2,naxis3,cube, > status) - FTG2D[BIJKED](unit,group,nullval,dim1,naxis1,naxis2, > image,anyf,status) - FTG3D[BIJKED](unit,group,nullval,dim1,dim2,naxis1,naxis2,naxis3, > - cube,anyf,status) - FTPSS[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,array, > status) - FTGSV[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs,nullval, > - array,anyf,status) - FTGSF[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs, > - array,flagvals,anyf,status) -\end{verbatim} - Table Column Information Subroutines: page~\pageref{FTGCNO} - -\begin{verbatim} - FTGNRW(unit, > nrows, status) - FTGNCL(unit, > ncols, status) - FTGCNO(unit,casesen,coltemplate, > colnum,status) - FTGCNN(unit,casesen,coltemplate, > colnam,colnum,status) - FTGTCL(unit,colnum, > datacode,repeat,width,status) - FTEQTY(unit,colnum, > datacode,repeat,width,status) - FTGCDW(unit,colnum, > dispwidth,status) - FTGACL(unit,colnum, > - ttype,tbcol,tunit,tform,tscal,tzero,snull,tdisp,status) - FTGBCL(unit,colnum, > - ttype,tunit,datatype,repeat,tscal,tzero,tnull,tdisp,status) - FTPTDM(unit,colnum,naxis,naxes, > status) - FTGTDM(unit,colnum,maxdim, > naxis,naxes,status) - FTDTDM(unit,tdimstr,colnum,maxdim, > naxis,naxes, status) - FTGRSZ(unit, > nrows,status) -\end{verbatim} - Low-Level Table Access Subroutines: page~\pageref{FTGTBS} - -\begin{verbatim} - FTGTBS(unit,frow,startchar,nchars, > string,status) - FTPTBS(unit,frow,startchar,nchars,string, > status) - FTGTBB(unit,frow,startchar,nchars, > array,status) - FTPTBB(unit,frow,startchar,nchars,array, > status) -\end{verbatim} - Edit Rows or Columns page~\pageref{FTIROW} - -\begin{verbatim} - FTIROW(unit,frow,nrows, > status) - FTDROW(unit,frow,nrows, > status) - FTDRRG(unit,rowrange, > status) - FTDRWS(unit,rowlist,nrows, > status) - FTICOL(unit,colnum,ttype,tform, > status) - FTICLS(unit,colnum,ncols,ttype,tform, > status) - FTMVEC(unit,colnum,newveclen, > status) - FTDCOL(unit,colnum, > status) - FTCPCL(inunit,outunit,incolnum,outcolnum,createcol, > status); -\end{verbatim} - Read and Write Column Data Routines page~\pageref{FTPCLS} - -\begin{verbatim} - FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) - FTPCN[BIJKED](unit,colnum,frow,felem,nelements,values,nullval > status) - FTPCLX(unit,colnum,frow,fbit,nbit,lray, > status) - FTPCLU(unit,colnum,frow,felem,nelements, > status) - FTGCL(unit,colnum,frow,felem,nelements, > values,status) - FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > - values,anyf,status) - FTGCF[SLBIJKEDCM](unit,colnum,frow,felem,nelements, > - values,flagvals,anyf,status) - FTGSV[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs,nullval, > - array,anyf,status) - FTGSF[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs, > - array,flagvals,anyf,status) - FTGCX(unit,colnum,frow,fbit,nbit, > lray,status) - FTGCX[IJD](unit,colnum,frow,nrows,fbit,nbit, > array,status) - FTGDES(unit,colnum,rownum, > nelements,offset,status) - FTPDES(unit,colnum,rownum,nelements,offset, > status) -\end{verbatim} - Row Selection and Calculator Routines: page~\pageref{FTFROW} - -\begin{verbatim} - FTFROW(unit,expr,firstrow, nrows, > n_good_rows, row_status, status) - FTFFRW(unit, expr, > rownum, status) - FTSROW(inunit, outunit, expr, > status ) - FTCROW(unit,datatype,expr,firstrow,nelements,nulval, > - array,anynul,status) - FTCALC(inunit, expr, outunit, parName, parInfo, > status) - FTCALC_RNG(inunit, expr, outunit, parName, parInfo, - nranges, firstrow, lastrow, > status) - FTTEXP(unit, expr, > datatype, nelem, naxis, naxes, status) -\end{verbatim} - Celestial Coordinate System Subroutines: page~\pageref{FTGICS} - -\begin{verbatim} - FTGICS(unit, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) - FTGTCS(unit,xcol,ycol, > - xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) - FTWLDP(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, - coordtype, > xpos,ypos,status) - FTXYPX(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, - coordtype, > xpix,ypix,status) -\end{verbatim} - File Checksum Subroutines: page~\pageref{FTPCKS} - -\begin{verbatim} - FTPCKS(unit, > status) - FTUCKS(unit, > status) - FTVCKS(unit, > dataok,hduok,status) - FTGCKS(unit, > datasum,hdusum,status) - FTESUM(sum,complement, > checksum) - FTDSUM(checksum,complement, > sum) - -\end{verbatim} - Time and Date Utility Subroutines: page~\pageref{FTGSDT} - -\begin{verbatim} - FTGSDT( > day, month, year, status ) - FTGSTM(> datestr, timeref, status) - FTDT2S( year, month, day, > datestr, status) - FTTM2S( year, month, day, hour, minute, second, decimals, - > datestr, status) - FTS2DT(datestr, > year, month, day, status) - FTS2TM(datestr, > year, month, day, hour, minute, second, status) -\end{verbatim} - General Utility Subroutines: page~\pageref{FTGHAD} - -\begin{verbatim} - FTGHAD(unit, > curaddr,nextaddr) - FTUPCH(string) - FTCMPS(str_template,string,casesen, > match,exact) - FTTKEY(keyword, > status) - FTTREC(card, > status) - FTNCHK(unit, > status) - FTGKNM(unit, > keyword, keylength, status) - FTMKKY(keyword, value,comment, > card, status) - FTPSVC(card, > value,comment,status) - FTKEYN(keyroot,seq_no, > keyword,status) - FTNKEY(seq_no,keyroot, > keyword,status) - FTDTYP(value, > dtype,status) - class = FTGKCL(card) - FTASFM(tform, > datacode,width,decimals,status) - FTBNFM(tform, > datacode,repeat,width,status) - FTGABC(tfields,tform,space, > rowlen,tbcol,status) - FTGTHD(template, > card,hdtype,status) - FTRWRG(rowlist, maxrows, maxranges, > numranges, rangemin, - rangemax, status) -\end{verbatim} - -\chapter{ Parameter Definitions } - -\begin{verbatim} -anyf - (logical) set to TRUE if any of the returned data values are undefined -array - (any datatype except character) array of bytes to be read or written. -bitpix - (integer) bits per pixel: 8, 16, 32, -32, or -64 -blank - (integer) value used for undefined pixels in integer primary array -blank - (integer*8) value used for undefined pixels in integer primary array -blocksize - (integer) 2880-byte logical record blocking factor - (if 0 < blocksize < 11) or the actual block size in bytes - (if 10 < blocksize < 28800). As of version 3.3 of FITSIO, - blocksizes greater than 2880 are no longer supported. -bscale - (double precision) scaling factor for the primary array -bytlen - (integer) length of the data unit, in bytes -bzero - (double precision) zero point for primary array scaling -card - (character*80) header record to be read or written -casesen - (logical) will string matching be case sensitive? -checksum - (character*16) encoded checksum string -colname - (character) ASCII name of the column -colnum - (integer) number of the column (first column = 1) -coltemplate - (character) template string to be matched to column names -comment - (character) the keyword comment field -comments - (character array) keyword comment fields -compid - (integer) the type of computer that the program is running on -complement - (logical) should the checksum be complemented? -coordtype - (character) type of coordinate projection (-SIN, -TAN, -ARC, - -NCP, -GLS, -MER, or -AIT) -cube - 3D data cube of the appropriate datatype -curaddr - (integer) starting address (in bytes) of the CHDU -current - (integer) if not equal to 0, copy the current HDU -datacode - (integer) symbolic code of the binary table column datatype -dataok - (integer) was the data unit verification successful (=1) or - not (= -1). Equals zero if the DATASUM keyword is not present. -datasum - (double precision) 32-bit 1's complement checksum for the data unit -datatype - (character) datatype (format) of the binary table column -datestr - (string) FITS date/time string: 'YYYY-MM-DDThh:mm:ss.ddd', - 'YYYY-MM-dd', or 'dd/mm/yy' -day - (integer) current day of the month -dblval - (double precision) fractional part of the keyword value -decimals - (integer) number of decimal places to be displayed -dim1 - (integer) actual size of the first dimension of the image or cube array -dim2 - (integer) actual size of the second dimension of the cube array -dispwidth - (integer) - the display width (length of string) for a column -dtype - (character) datatype of the keyword ('C', 'L', 'I', or 'F') - C = character string - L = logical - I = integer - F = floating point number -errmsg - (character*80) oldest error message on the internal stack -errtext - (character*30) descriptive error message corresponding to error number -casesen - (logical) true if column name matching is case sensitive -exact - (logical) do the strings match exactly, or were wildcards used? -exclist (character array) list of names to be excluded from search -exists - flag indicating whether the file or compressed file exists on disk -extend - (logical) true if there may be extensions following the primary data -extname - (character) value of the EXTNAME keyword (if not blank) -fbit - (integer) first bit in the field to be read or written -felem - (integer) first pixel of the element vector (ignored for ASCII tables) -filename - (character) name of the FITS file -flagvals - (logical array) True if corresponding data element is undefined -following - (integer) if not equal to 0, copy all following HDUs in the input file -fparm - (integer) sequence number of the first group parameter to read or write -fpixel - (integer) the first pixel position -fpixels - (integer array) the first included pixel in each dimension -frow - (integer) beginning row number (first row of table = 1) -frowll - (integer*8) beginning row number (first row of table = 1) -gcount - (integer) value of the GCOUNT keyword (usually = 1) -group - (integer) sequence number of the data group (=0 for non-grouped data) -hdtype - (integer) header record type: -1=delete; 0=append or replace; - 1=append; 2=this is the END keyword -hduok - (integer) was the HDU verification successful (=1) or - not (= -1). Equals zero if the CHECKSUM keyword is not present. -hdusum - (double precision) 32 bit 1's complement checksum for the entire CHDU -hdutype - (integer) type of HDU: 0 = primary array or IMAGE, 1 = ASCII table, - 2 = binary table, -1 = any HDU type or unknown type -history - (character) the HISTORY keyword comment string -hour - (integer) hour from 0 - 23 -image - 2D image of the appropriate datatype -inclist (character array) list of names to be included in search -incs - (integer array) sampling interval for pixels in each FITS dimension -intval - (integer) integer part of the keyword value -iounit - (integer) value of an unused I/O unit number -iunit - (integer) logical unit number associated with the input FITS file, 1-300 -key_no - (integer) sequence number (starting with 1) of the keyword record -keylength - (integer) length of the keyword name -keyroot - (character) root string for the keyword name -keysadd -(integer) number of new keyword records which can fit in the CHU -keysexist - (integer) number of existing keyword records in the CHU -keyval - value of the keyword in the appropriate datatype -keyvals - (array) value of the keywords in the appropriate datatype -keyword - (character*8) name of a keyword -lray - (logical array) array of logical values corresponding to the bit array -lpixels - (integer array) the last included pixel in each dimension -match - (logical) do the 2 strings match? -maxdim - (integer) dimensioned size of the NAXES, TTYPE, TFORM or TUNIT arrays -max_keys - (integer) maximum number of keywords to search for -minute - (integer) minute of an hour (0 - 59) -month - (integer) current month of the year (1 - 12) -morekeys - (integer) will leave space in the header for this many more keywords -naxes - (integer array) size of each dimension in the FITS array -naxesll - (integer*8 array) size of each dimension in the FITS array -naxis - (integer) number of dimensions in the FITS array -naxis1 - (integer) length of the X/first axis of the FITS array -naxis2 - (integer) length of the Y/second axis of the FITS array -naxis3 - (integer) length of the Z/third axis of the FITS array -nbit - (integer) number of bits in the field to read or write -nchars - (integer) number of characters to read and return -ncols - (integer) number of columns -nelements - (integer) number of data elements to read or write -nelementsll - (integer*8) number of data elements to read or write -nexc (integer) number of names in the exclusion list (may = 0) -nhdu - (integer) absolute number of the HDU (1st HDU = 1) -ninc (integer) number of names in the inclusion list -nmove - (integer) number of HDUs to move (+ or -), relative to current position -nfound - (integer) number of keywords found (highest keyword number) -no_keys - (integer) number of keywords to write in the sequence -nparm - (integer) number of group parameters to read or write -nrows - (integer) number of rows in the table -nrowsll - (integer*8) number of rows in the table -nullval - value to represent undefined pixels, of the appropriate datatype -nextaddr - (integer) starting address (in bytes) of the HDU following the CHDU -offset - (integer) byte offset in the heap to the first element of the array -offsetll - (integer*8) byte offset in the heap to the first element of the array -oldkey - (character) old name of keyword to be modified -ounit - (integer) logical unit number associated with the output FITS file 1-300 -pcount - (integer) value of the PCOUNT keyword (usually = 0) -previous - (integer) if not equal to 0, copy all previous HDUs in the input file -repeat - (integer) length of element vector (e.g. 12J); ignored for ASCII table -rot - (double precision) celestial coordinate rotation angle (degrees) -rowlen - (integer) length of a table row, in characters or bytes -rowlenll - (integer*8) length of a table row, in characters or bytes -rowlist - (integer array) list of row numbers to be deleted in increasing order -rownum - (integer) number of the row (first row = 1) -rowrange- (string) list of rows or row ranges to be deleted -rwmode - (integer) file access mode: 0 = readonly, 1 = readwrite -second (double)- second within minute (0 - 60.9999999999) (leap second!) -seq_no - (integer) the sequence number to append to the keyword root name -simple - (logical) does the FITS file conform to all the FITS standards -snull - (character) value used to represent undefined values in ASCII table -space - (integer) number of blank spaces to leave between ASCII table columns -startchar - (integer) first character in the row to be read -startno - (integer) value of the first keyword sequence number (usually 1) -status - (integer) returned error status code (0 = OK) -str_template (character) template string to be matched to reference string -stream - (character) output stream for the report: either 'STDOUT' or 'STDERR' -string - (character) character string -sum - (double precision) 32 bit unsigned checksum value -tbcol - (integer array) column number of the first character in the field(s) -tdisp - (character) Fortran type display format for the table column -template-(character) template string for a FITS header record -tfields - (integer) number of fields (columns) in the table -tform - (character array) format of the column(s); allowed values are: - For ASCII tables: Iw, Aw, Fww.dd, Eww.dd, or Dww.dd - For binary tables: rL, rX, rB, rI, rJ, rA, rAw, rE, rD, rC, rM - where 'w'=width of the field, 'd'=no. of decimals, 'r'=repeat count - Note that the 'rAw' form is non-standard extension to the - TFORM keyword syntax that is not specifically defined in the - Binary Tables definition document. -theap - (integer) zero indexed byte offset of starting address of the heap - relative to the beginning of the binary table data -tnull - (integer) value used to represent undefined values in binary table -tnullll - (integer*8) value used to represent undefined values in binary table -ttype - (character array) label for table column(s) -tscal - (double precision) scaling factor for table column -tunit - (character array) physical unit for table column(s) -tzero - (double precision) scaling zero point for table column -unit - (integer) logical unit number associated with the FITS file (1-300) -units - (character) the keyword units string (e.g., 'km/s') -value - (character) the keyword value string -values - array of data values of the appropriate datatype -varidat - (integer) size in bytes of the 'variable length data area' - following the binary table data (usually = 0) -version - (real) current revision number of the library -width - (integer) width of the character string field -xcol - (integer) number of the column containing the X coordinate values -xinc - (double precision) X axis coordinate increment at reference pixel (deg) -xpix - (double precision) X axis pixel location -xpos - (double precision) X axis celestial coordinate (usually RA) (deg) -xrpix - (double precision) X axis reference pixel array location -xrval - (double precision) X axis coordinate value at the reference pixel (deg) -ycol - (integer) number of the column containing the X coordinate values -year - (integer) last 2 digits of the year (00 - 99) -yinc - (double precision) Y axis coordinate increment at reference pixel (deg) -ypix - (double precision) y axis pixel location -ypos - (double precision) y axis celestial coordinate (usually DEC) (deg) -yrpix - (double precision) Y axis reference pixel array location -yrval - (double precision) Y axis coordinate value at the reference pixel (deg) -\end{verbatim} - -\chapter{ FITSIO Error Status Codes } - -\begin{verbatim} -Status codes in the range -99 to -999 and 1 to 999 are reserved for future -FITSIO use. - - 0 OK, no error -101 input and output files are the same -103 too many FITS files open at once; all internal buffers full -104 error opening existing file -105 error creating new FITS file; (does a file with this name already exist?) -106 error writing record to FITS file -107 end-of-file encountered while reading record from FITS file -108 error reading record from file -110 error closing FITS file -111 internal array dimensions exceeded -112 Cannot modify file with readonly access -113 Could not allocate memory -114 illegal logical unit number; must be between 1 - 300, inclusive -115 NULL input pointer to routine -116 error seeking position in file - -121 invalid URL prefix on file name -122 tried to register too many IO drivers -123 driver initialization failed -124 matching driver is not registered -125 failed to parse input file URL -126 parse error in range list - -151 bad argument in shared memory driver -152 null pointer passed as an argument -153 no more free shared memory handles -154 shared memory driver is not initialized -155 IPC error returned by a system call -156 no memory in shared memory driver -157 resource deadlock would occur -158 attempt to open/create lock file failed -159 shared memory block cannot be resized at the moment - - -201 header not empty; can't write required keywords -202 specified keyword name was not found in the header -203 specified header record number is out of bounds -204 keyword value field is blank -205 keyword value string is missing the closing quote character -206 illegal indexed keyword name (e.g. 'TFORM1000') -207 illegal character in keyword name or header record -208 keyword does not have expected name. Keyword out of sequence? -209 keyword does not have expected integer value -210 could not find the required END header keyword -211 illegal BITPIX keyword value -212 illegal NAXIS keyword value -213 illegal NAXISn keyword value: must be 0 or positive integer -214 illegal PCOUNT keyword value -215 illegal GCOUNT keyword value -216 illegal TFIELDS keyword value -217 negative ASCII or binary table width value (NAXIS1) -218 negative number of rows in ASCII or binary table (NAXIS2) -219 column name (TTYPE keyword) not found -220 illegal SIMPLE keyword value -221 could not find the required SIMPLE header keyword -222 could not find the required BITPIX header keyword -223 could not find the required NAXIS header keyword -224 could not find all the required NAXISn keywords in the header -225 could not find the required XTENSION header keyword -226 the CHDU is not an ASCII table extension -227 the CHDU is not a binary table extension -228 could not find the required PCOUNT header keyword -229 could not find the required GCOUNT header keyword -230 could not find the required TFIELDS header keyword -231 could not find all the required TBCOLn keywords in the header -232 could not find all the required TFORMn keywords in the header -233 the CHDU is not an IMAGE extension -234 illegal TBCOL keyword value; out of range -235 this operation only allowed for ASCII or BINARY table extension -236 column is too wide to fit within the specified width of the ASCII table -237 the specified column name template matched more than one column name -241 binary table row width is not equal to the sum of the field widths -251 unrecognizable type of FITS extension -252 unrecognizable FITS record -253 END keyword contains non-blank characters in columns 9-80 -254 Header fill area contains non-blank characters -255 Data fill area contains non-blank on non-zero values -261 unable to parse the TFORM keyword value string -262 unrecognizable TFORM datatype code -263 illegal TDIMn keyword value - -301 illegal HDU number; less than 1 or greater than internal buffer size -302 column number out of range (1 - 999) -304 attempt to move to negative file record number -306 attempted to read or write a negative number of bytes in the FITS file -307 illegal starting row number for table read or write operation -308 illegal starting element number for table read or write operation -309 attempted to read or write character string in non-character table column -310 attempted to read or write logical value in non-logical table column -311 illegal ASCII table TFORM format code for attempted operation -312 illegal binary table TFORM format code for attempted operation -314 value for undefined pixels has not been defined -317 attempted to read or write descriptor in a non-descriptor field -320 number of array dimensions out of range -321 first pixel number is greater than the last pixel number -322 attempt to set BSCALE or TSCALn scaling parameter = 0 -323 illegal axis length less than 1 - -340 NOT_GROUP_TABLE 340 Grouping function error -341 HDU_ALREADY_MEMBER -342 MEMBER_NOT_FOUND -343 GROUP_NOT_FOUND -344 BAD_GROUP_ID -345 TOO_MANY_HDUS_TRACKED -346 HDU_ALREADY_TRACKED -347 BAD_OPTION -348 IDENTICAL_POINTERS -349 BAD_GROUP_ATTACH -350 BAD_GROUP_DETACH - -360 NGP_NO_MEMORY malloc failed -361 NGP_READ_ERR read error from file -362 NGP_NUL_PTR null pointer passed as an argument. - Passing null pointer as a name of - template file raises this error -363 NGP_EMPTY_CURLINE line read seems to be empty (used - internally) -364 NGP_UNREAD_QUEUE_FULL cannot unread more then 1 line (or single - line twice) -365 NGP_INC_NESTING too deep include file nesting (infinite - loop, template includes itself ?) -366 NGP_ERR_FOPEN fopen() failed, cannot open template file -367 NGP_EOF end of file encountered and not expected -368 NGP_BAD_ARG bad arguments passed. Usually means - internal parser error. Should not happen -369 NGP_TOKEN_NOT_EXPECT token not expected here - -401 error attempting to convert an integer to a formatted character string -402 error attempting to convert a real value to a formatted character string -403 cannot convert a quoted string keyword to an integer -404 attempted to read a non-logical keyword value as a logical value -405 cannot convert a quoted string keyword to a real value -406 cannot convert a quoted string keyword to a double precision value -407 error attempting to read character string as an integer -408 error attempting to read character string as a real value -409 error attempting to read character string as a double precision value -410 bad keyword datatype code -411 illegal number of decimal places while formatting floating point value -412 numerical overflow during implicit datatype conversion -413 error compressing image -414 error uncompressing image -420 error in date or time conversion - -431 syntax error in parser expression -432 expression did not evaluate to desired type -433 vector result too large to return in array -434 data parser failed not sent an out column -435 bad data encounter while parsing column -436 parse error: output file not of proper type - -501 celestial angle too large for projection -502 bad celestial coordinate or pixel value -503 error in celestial coordinate calculation -504 unsupported type of celestial projection -505 required celestial coordinate keywords not found -506 approximate wcs keyword values were returned -\end{verbatim} -\end{document} diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.toc b/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.toc deleted file mode 100644 index f74d515fb..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/fitsio.toc +++ /dev/null @@ -1,95 +0,0 @@ -\contentsline {chapter}{\numberline {1}Introduction }{1} -\contentsline {chapter}{\numberline {2} Creating FITSIO/CFITSIO }{3} -\contentsline {section}{\numberline {2.1}Building the Library}{3} -\contentsline {section}{\numberline {2.2}Testing the Library}{6} -\contentsline {section}{\numberline {2.3}Linking Programs with FITSIO}{7} -\contentsline {section}{\numberline {2.4}Getting Started with FITSIO}{7} -\contentsline {section}{\numberline {2.5}Example Program}{8} -\contentsline {section}{\numberline {2.6}Legal Stuff}{9} -\contentsline {section}{\numberline {2.7}Acknowledgments}{10} -\contentsline {chapter}{\numberline {3} A FITS Primer }{13} -\contentsline {chapter}{\numberline {4}FITSIO Conventions and Guidelines }{15} -\contentsline {section}{\numberline {4.1}CFITSIO Size Limitations}{15} -\contentsline {section}{\numberline {4.2}Multiple Access to the Same FITS File}{16} -\contentsline {section}{\numberline {4.3}Current Header Data Unit (CHDU)}{16} -\contentsline {section}{\numberline {4.4}Subroutine Names}{16} -\contentsline {section}{\numberline {4.5}Subroutine Families and Datatypes}{17} -\contentsline {section}{\numberline {4.6}Implicit Data Type Conversion}{17} -\contentsline {section}{\numberline {4.7}Data Scaling}{18} -\contentsline {section}{\numberline {4.8}Error Status Values and the Error Message Stack}{18} -\contentsline {section}{\numberline {4.9}Variable-Length Array Facility in Binary Tables}{19} -\contentsline {section}{\numberline {4.10}Support for IEEE Special Values}{20} -\contentsline {section}{\numberline {4.11}When the Final Size of the FITS HDU is Unknown}{21} -\contentsline {section}{\numberline {4.12}Local FITS Conventions supported by FITSIO}{21} -\contentsline {subsection}{\numberline {4.12.1}Support for Long String Keyword Values.}{21} -\contentsline {subsection}{\numberline {4.12.2}Arrays of Fixed-Length Strings in Binary Tables}{22} -\contentsline {subsection}{\numberline {4.12.3}Keyword Units Strings}{23} -\contentsline {subsection}{\numberline {4.12.4}HIERARCH Convention for Extended Keyword Names}{23} -\contentsline {section}{\numberline {4.13}Optimizing Code for Maximum Processing Speed}{24} -\contentsline {subsection}{\numberline {4.13.1}Background Information: How CFITSIO Manages Data I/O}{24} -\contentsline {subsection}{\numberline {4.13.2}Optimization Strategies}{25} -\contentsline {chapter}{\numberline {5} Basic Interface Routines }{29} -\contentsline {section}{\numberline {5.1}FITSIO Error Status Routines }{29} -\contentsline {section}{\numberline {5.2}File I/O Routines}{30} -\contentsline {section}{\numberline {5.3}Keyword I/O Routines}{32} -\contentsline {section}{\numberline {5.4}Data I/O Routines}{33} -\contentsline {chapter}{\numberline {6} Advanced Interface Subroutines }{35} -\contentsline {section}{\numberline {6.1}FITS File Open and Close Subroutines: }{35} -\contentsline {section}{\numberline {6.2}HDU-Level Operations }{38} -\contentsline {section}{\numberline {6.3}Define or Redefine the structure of the CHDU }{41} -\contentsline {section}{\numberline {6.4}FITS Header I/O Subroutines}{43} -\contentsline {subsection}{\numberline {6.4.1}Header Space and Position Routines }{43} -\contentsline {subsection}{\numberline {6.4.2}Read or Write Standard Header Routines }{43} -\contentsline {subsection}{\numberline {6.4.3}Write Keyword Subroutines }{45} -\contentsline {subsection}{\numberline {6.4.4}Insert Keyword Subroutines }{47} -\contentsline {subsection}{\numberline {6.4.5}Read Keyword Subroutines }{47} -\contentsline {subsection}{\numberline {6.4.6}Modify Keyword Subroutines }{49} -\contentsline {subsection}{\numberline {6.4.7}Update Keyword Subroutines }{50} -\contentsline {subsection}{\numberline {6.4.8}Delete Keyword Subroutines }{51} -\contentsline {section}{\numberline {6.5}Data Scaling and Undefined Pixel Parameters }{51} -\contentsline {section}{\numberline {6.6}FITS Primary Array or IMAGE Extension I/O Subroutines }{52} -\contentsline {section}{\numberline {6.7}FITS ASCII and Binary Table Data I/O Subroutines}{55} -\contentsline {subsection}{\numberline {6.7.1}Column Information Subroutines }{55} -\contentsline {subsection}{\numberline {6.7.2}Low-Level Table Access Subroutines }{58} -\contentsline {subsection}{\numberline {6.7.3}Edit Rows or Columns }{59} -\contentsline {subsection}{\numberline {6.7.4}Read and Write Column Data Routines }{60} -\contentsline {section}{\numberline {6.8}Row Selection and Calculator Routines }{64} -\contentsline {section}{\numberline {6.9}Celestial Coordinate System Subroutines }{65} -\contentsline {section}{\numberline {6.10}File Checksum Subroutines }{67} -\contentsline {section}{\numberline {6.11} Date and Time Utility Routines }{68} -\contentsline {section}{\numberline {6.12}General Utility Subroutines }{69} -\contentsline {chapter}{\numberline {7} The CFITSIO Iterator Function }{77} -\contentsline {chapter}{\numberline {8} Extended File Name Syntax }{79} -\contentsline {section}{\numberline {8.1}Overview}{79} -\contentsline {section}{\numberline {8.2}Filetype}{82} -\contentsline {subsection}{\numberline {8.2.1}Notes about HTTP proxy servers}{82} -\contentsline {subsection}{\numberline {8.2.2}Notes about the stream filetype driver}{83} -\contentsline {subsection}{\numberline {8.2.3}Notes about the gsiftp filetype}{84} -\contentsline {subsection}{\numberline {8.2.4}Notes about the root filetype}{84} -\contentsline {subsection}{\numberline {8.2.5}Notes about the shmem filetype:}{86} -\contentsline {section}{\numberline {8.3}Base Filename}{86} -\contentsline {section}{\numberline {8.4}Output File Name when Opening an Existing File}{88} -\contentsline {section}{\numberline {8.5}Template File Name when Creating a New File}{90} -\contentsline {section}{\numberline {8.6}Image Tile-Compression Specification}{90} -\contentsline {section}{\numberline {8.7}HDU Location Specification}{90} -\contentsline {section}{\numberline {8.8}Image Section}{91} -\contentsline {section}{\numberline {8.9}Image Transform Filters}{92} -\contentsline {section}{\numberline {8.10}Column and Keyword Filtering Specification}{94} -\contentsline {section}{\numberline {8.11}Row Filtering Specification}{96} -\contentsline {subsection}{\numberline {8.11.1}General Syntax}{97} -\contentsline {subsection}{\numberline {8.11.2}Bit Masks}{99} -\contentsline {subsection}{\numberline {8.11.3}Vector Columns}{100} -\contentsline {subsection}{\numberline {8.11.4}Good Time Interval Filtering}{102} -\contentsline {subsection}{\numberline {8.11.5}Spatial Region Filtering}{103} -\contentsline {subsection}{\numberline {8.11.6}Example Row Filters}{105} -\contentsline {section}{\numberline {8.12} Binning or Histogramming Specification}{106} -\contentsline {chapter}{\numberline {9}Template Files }{109} -\contentsline {section}{\numberline {9.1}Detailed Template Line Format}{109} -\contentsline {section}{\numberline {9.2}Auto-indexing of Keywords}{110} -\contentsline {section}{\numberline {9.3}Template Parser Directives}{111} -\contentsline {section}{\numberline {9.4}Formal Template Syntax}{112} -\contentsline {section}{\numberline {9.5}Errors}{112} -\contentsline {section}{\numberline {9.6}Examples}{112} -\contentsline {chapter}{\numberline {10} Summary of all FITSIO User-Interface Subroutines }{115} -\contentsline {chapter}{\numberline {11} Parameter Definitions }{123} -\contentsline {chapter}{\numberline {12} FITSIO Error Status Codes }{129} diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/fpackguide.pdf b/src/external/OpenGR/3rdparty/cfitsio/docs/fpackguide.pdf deleted file mode 100644 index 7e09fc7cc..000000000 Binary files a/src/external/OpenGR/3rdparty/cfitsio/docs/fpackguide.pdf and /dev/null differ diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/quick.pdf b/src/external/OpenGR/3rdparty/cfitsio/docs/quick.pdf deleted file mode 100644 index 83611cf88..000000000 Binary files a/src/external/OpenGR/3rdparty/cfitsio/docs/quick.pdf and /dev/null differ diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/quick.ps b/src/external/OpenGR/3rdparty/cfitsio/docs/quick.ps deleted file mode 100644 index ed76f1eb7..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/quick.ps +++ /dev/null @@ -1,5291 +0,0 @@ -%!PS-Adobe-2.0 -%%Creator: dvips(k) 5.96.1 Copyright 2007 Radical Eye Software -%%Title: quick.dvi -%%CreationDate: Mon May 12 15:50:42 2014 -%%Pages: 41 -%%PageOrder: Ascend -%%BoundingBox: 0 0 612 792 -%%DocumentFonts: CMR17 CMR12 CMSY8 CMBX12 CMBX10 CMR10 CMSY6 CMR9 CMTT10 -%%+ CMSY10 -%%DocumentPaperSizes: Letter -%%EndComments -%DVIPSWebPage: (www.radicaleye.com) -%DVIPSCommandLine: dvips -o quick.ps quick.dvi -%DVIPSParameters: dpi=600 -%DVIPSSource: TeX output 2014.05.12:1550 -%%BeginProcSet: tex.pro 0 0 -%! -/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S -N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 -mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 -0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ -landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize -mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ -matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round -exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ -statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] -N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin -/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array -/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 -array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N -df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A -definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get -}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} -B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr -1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S -/BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy -setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask -restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn -/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put -}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ -bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A -mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ -SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ -userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X -1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 -index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N -/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ -/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) -(LaserWriter 16/600)]{A length product length le{A length product exch 0 -exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse -end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask -grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} -imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round -exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto -fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p -delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} -B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ -p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S -rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end - -%%EndProcSet -%%BeginProcSet: texps.pro 0 0 -%! -TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 -index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll -exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 -ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ -pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get -div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type -/nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end -definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup -sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll -mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ -exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} -forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def -end - -%%EndProcSet -%%BeginFont: CMSY10 -%!PS-AdobeFont-1.1: CMSY10 1.0 -%%CreationDate: 1991 Aug 15 07:20:57 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMSY10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle -14.035 def -/isFixedPitch false def -end readonly def -/FontName /CMSY10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 15 /bullet put -dup 102 /braceleft put -dup 103 /braceright put -dup 106 /bar put -readonly def -/FontBBox{-29 -960 1116 775}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 -7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 -A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 -E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A -221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A -27D1663E0B62F461F6E40A5D6676D1D12B51E641C1D4E8E2771864FC104F8CBF -5B78EC1D88228725F1C453A678F58A7E1B7BD7CA700717D288EB8DA1F57C4F09 -0ABF1D42C5DDD0C384C7E22F8F8047BE1D4C1CC8E33368FB1AC82B4E96146730 -DE3302B2E6B819CB6AE455B1AF3187FFE8071AA57EF8A6616B9CB7941D44EC7A -71A7BB3DF755178D7D2E4BB69859EFA4BBC30BD6BB1531133FD4D9438FF99F09 -4ECC068A324D75B5F696B8688EEB2F17E5ED34CCD6D047A4E3806D000C199D7C -515DB70A8D4F6146FE068DC1E5DE8BC57030ACE57A0A31C99BEDB251A0ECAD78 -253AB321023D15FF7F55A3CE81514C1E7E76240C1FB36CD4874DDB761CC325F5 -D588700B294849D690F93526EF438A42B9B5B0508584EA3766D35F5B8D51C458 -ECB9FBD23A49576EAB06BACB7EA6D300985500835F4FE597D4A1110C8EABE6FC -CE3E1F95CFD3A42446F25355381D476B2FFB6EF247BF58A6FFC5EC0E4CC207BE -46485F8E07350B37DCA8C1864E62614332A1D3C9DEDDD6492181949A2C3498C9 -EC2A81C1F4FF989A4654E375F509D24D969B97D2A9940FAF43BBB286E08559C0 -F8D9674B0A294B36D3A050F7DED8C80E1D230812F6B8387B17948FD29FF050E2 -AAC5EBE5D96AFD0879534E2F4BB81613A1571750F9CF4215199F93813D815B5D -1C79E11A0FCBB627CDE569F88C741CD502627777BB058ECAC09B6ACCFACA69B9 -8F8168B0B5A1A6EB13E884B348FBB2ACF9EB180F6E27D57F8503710CE037A34A -F8B157201657C825E2A4B4A7696B58B7A988C05E43E66F0FF277A7694C555C54 -AFB1D32F6DE102136FC810E1F3B5CEA42476EAC7AAFB390E3252B2169DCDEE6E -328507BD0E24734A85AAA263E0D2F64BE1607455BC855785BC27F8B30FE917B4 -23AB3C812975355942E955501AF85A3C0CE836911AF679EA44AD6A7D042A6549 -0C471FE294E8490024D93ADCADED460FAB7FBCDC29EFEBD2A9A127E11869E659 -961B29206CE63944B6FA4B9315BCC528EB1E0223CE94C795A5D5231A7FC8545D -6B287B965F8EEDDB67A6774129DD01D5A21694ABE320BB2553043D4C42ACFF91 -1009372CB03381035BEEEEFD05631E026A0980A72A67B3703323A4E7C94FFCEE -8D0B7407F9CCC043D3D184BEA4728385D6AB2FB0641DD8F5BA7E04035D30D628 -7E97D31C1486DFD5B1D076B84B4ABA4829ED4310321F1F24B847C44E00185A69 -37711A -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMBX12 -%!PS-AdobeFont-1.1: CMBX12 1.0 -%%CreationDate: 1991 Aug 20 16:34:54 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMBX12) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Bold) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMBX12 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 45 /hyphen put -dup 46 /period put -dup 47 /slash put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 72 /H put -dup 73 /I put -dup 75 /K put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 97 /a put -dup 98 /b put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 103 /g put -dup 105 /i put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -dup 118 /v put -dup 119 /w put -dup 120 /x put -dup 121 /y put -readonly def -/FontBBox{-53 -251 1139 750}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5F0364CD5660F74BEE96790DE35AFA90CCF712 -B1805DA88AE375A04D99598EADFC625BDC1F9C315B6CF28C9BD427F32C745C99 -AEBE70DAAED49EA45AF94F081934AA47894A370D698ABABDA4215500B190AF26 -7FCFB7DDA2BC68605A4EF61ECCA3D61C684B47FFB5887A3BEDE0B4D30E8EBABF -20980C23312618EB0EAF289B2924FF4A334B85D98FD68545FDADB47F991E7390 -B10EE86A46A5AF8866C010225024D5E5862D49DEB5D8ECCB95D94283C50A363D -68A49071445610F03CE3600945118A6BC0B3AA4593104E727261C68C4A47F809 -D77E4CF27B3681F6B6F3AC498E45361BF9E01FAF5527F5E3CC790D3084674B3E -26296F3E03321B5C555D2458578A89E72D3166A3C5D740B3ABB127CF420C316D -F957873DA04CF0DB25A73574A4DE2E4F2D5D4E8E0B430654CF7F341A1BDB3E26 -77C194764EAD58C585F49EF10843FE020F9FDFD9008D660DE50B9BD7A2A87299 -BC319E66D781101BB956E30643A19B93C8967E1AE4719F300BFE5866F0D6DA5E -C55E171A24D3B707EFA325D47F473764E99BC8B1108D815CF2ACADFA6C4663E8 -30855D673CE98AB78F5F829F7FA226AB57F07B3E7D4E7CE30ED3B7EB0D3035C5 -148DA8D9FA34483414FDA8E3DC9E6C479E3EEE9A11A0547FC9085FA4631AD19C -E936E0598E3197207FA7BB6E55CFD5EF72AEC12D9A9675241C7A71316B2E148D -E2A1732B3627109EA446CB320EBBE2E78281CDF0890E2E72B6711335857F1E23 -337C75E729701E93D5BEC0630CDC7F4E957233EC09F917E5CA703C7E93841598 -0E73843FC6619DE017C8473A6D1B2BE5142DEBA285B98FA1CC5E64D2ADB981E6 -472971848451A245DDF6AA3B8225E9AC8E4630B0FF32D679EC27ACAD85C6394E -A6F71023B660EE883D8B676837E9EBA4E42BA8F365433A900F1DC3A9F0E88A26 -326BC603CD28B9A6E511975D39BF5957AC2D66D48E75D233CC1B78B0BDE71C21 -DF00ADE87769BAF3FF3896F1FE5A8786C78F798741CB0F38300E98711F994F13 -37994AF499D5BEF056FCC6F2BEBE3923EE7AC09AC246F5C63106DB4C92DB5DA2 -47D1016490CE3A3D571211DA35CA7A7E6FA4CE92074E44590F0E4B4C90834406 -EE27172A83A5F1C53F8E474448B21598395590F38D23697E65441DC75FB7294B -B560D82E1DDE2EC994ECDCB7F362E60E108B09EEBB71078B84C9070FEAD4F1C4 -2332D28EF482E89F064A5F32D95FA80AA2D84CAA27F7B61D457B0DBC7102D70B -3D6274006BA0C4D4731E03CD99E792A76E888922B1DBBB7AFAB73EB3B8306423 -25C6856218DA59FA5EB6EFE9FED08048D04842E4D18C13D6DF5F3D92CD3B0706 -ABC2024946EA8DDE0ADFFBDD693C08FED862012C73CF7491E1677ADBBDEB1C78 -C4791859D9FCF9B153A2A5C3B4B3436254BAF92984DE37309E384D8827978CE7 -2B9EF2E4034DDB15418C9C765FECE6FE63BE00659B226092C926F8D652E510C5 -B2632A691B7FF8C1ED57C720423CA5BF6F27DAF0C0B90A1C7A568E1C3C21FB0E -EB2336F01B06D047EB9E17BFEC91E7994A40165D4DBD085E47C310C0DC0D69C1 -FEF02C68B548FD04A31571B0A0ECDF246FB628C9C470B615DC5946D081938DBA -62C43AB08053AE7E3886C50426C64DFA698D9016F6E4421433B2F057FFC237F1 -1260F9CA7240208CF50B00AFDA29ABB70231B0886D657F143AF25529AD866823 -64D025895B10D19A63C9F07D2730661490DA4E3C3871F38268F5134DD8B67F9A -24A34E18C062E606B06D6287FA2E0336960A11F6B181752772323659BDB9ED0E -96453ED61C7A3CEE10778226B944B46459F36029D48D7A83799979F2162BAF61 -83178AB7DEDD28DB42F4CCB6C5F065F4D6F0F97C75D48C2CD500BCC746F45F97 -00BB3B543D368B5604B994005587E8158B43CFEB22A43515EF9EDBE9AAC13EB1 -6119EB67621D3BD51DDED406D7C7219953BD21F3E8312182CE62BB9F6AEF9199 -B64CDBA4C22760D9BE412AFC6E179EBB295A627871A82E88D92FAE94C00BE7EA -581712D8D85FFDA4C8A4EA7421DB198356DCD58F5F2C7058D87959B16199672B -897D985FCBBBCF691A97F9631DD8F5F51134144D3F0BFF482F24C397F3CA59C6 -FE739D2D3139574B068E0E7C96B7E1159B79BC024BDE17B54AE59BBD2B0E37A0 -F5442F6375D4ADC1D795202B1DA5EE38D0EBE98EE62866718830446C29CB1DCE -E31C449C0EC11E936D9F2BC2E38964803852C6550C6E591D3111763BD79B7D14 -BECB90421A01B6E242B3D08F90C63815689A90CB904C07BA1D224F790950997A -0AEAE5AC6AE2F213C8E7A418B3F6EADD3BC67596654692F4A61895DAF6D4FA61 -459E7E24F2A0E027A5501632188B9348EE4E0D9FCE65FEA80F4281697053210E -73664CDD8A7E2825A308EC570CF22034A51026E13BB004B9F563E3E3F45ACD4A -BD3A60D29C82869474E8B523461BA062D2D6A9C98B99B081EEF2DC2739A2860E -769323E29266E24452B9C96FA2B5B6D14FFC5CB45CE9BED68D5DFB5FE278B85C -0E2E0B454A3E657608170E1E0830FA07D09B454F2B1A7792F4BB96E6FE43ED14 -4977BBBF88C912DCDFD3D4DEB06B6D1EEA1BB019D19BDC57840A4A3F92AA29D4 -AC8A0840A73BB3F118F668D9D4E4C136DFA73CEF0344C2E32C02CEB865FDBEBF -3DBD44B9B6F63EF01C2691F9C7F43309C9EE45DBB423E50505CC6A7165B47ED5 -A0311E24203E4CE075F50B36DD2A7DDC85077BC599CC3E00A29C483F1DEB4218 -32262EE6B07E54EBA32BE65240B3A47E2B5606674FBC33EB8372B7D39CB2D8FF -6495F31BB367301FC5BAEBE1ED5B854571D4544595D18628C0C789B4AA86CAA7 -42C26E3C9CFFF98D224E05E94F5DD426203199FC1DD7B9347B044ED1116D7378 -496D80454518EF2A7DC3D2BFBF77EA8227C91E2A8C41B3118E7BCA38B5E8C38A -52587793FA7D5A7B2DBBD8AEB61ADF5F75115DBE4741EEBC0EDE1D74975DF021 -49C5E3C4000FA4E4D9E8E6644F21572AB30F6E8CD1886B020198DB7F94F8C722 -EC0123D49783351D36BF1AFBB12717E3DFC23063B77388C409A4157C89D552F7 -E5B3A2F825A1C8A8524936C2C7872A87C158AAF6AC142D529F0A66CD5495DFA1 -BACE93058E8B9D6FD1C62AD19DABEFC18BD047256DFD19B29D88C63ADE376DB2 -DC51939606E3EBA52798D23831BBC8E5DC8E6A0DD40D1F434B70CD292EA5E1FE -DE034CBC40C250758A3E5300B99CC4342167A4D44784471216C8028E7DC9BA9F -E6F540EAE0E87FEFC5BCB5E19650C68FD642F82F3292710AC357F6FCEA4EFD88 -6F1049CAE4CCEFFAF6CCC82DDD484D4F7C8F8A825436A6CE713B0A697832BF9B -9BC9BB3A674C608E2913CB52C9471B4F3027124EDB6AAA9A975424A0DB8D63C1 -2FEFE0B08D3493A79D685006BEF07C8DD1F2F635309F463025666F2EBCDECC42 -B9FFC43D93AD2D4B7F2C0AD302336E8FD7E670E4378BF2052D9B70D25E9D2301 -C97C2B9AE8FA1009F7DE7D5AD311F4672CA62775AE5D045E010A031EAC6B266E -7EA68D21B569770452D665DE101075E10E6CEEAF15A6961872A797F9A2E702D7 -8FCC9CC526B9764E264FF987591E96482527CE200A0B2D7603BD25547AD258C9 -6D8459BAB17C74DDA7101CD13EB38C8DF5A2C9BF87A8D22545B6E8EE6C5D5BB8 -F958F433DC59B75F5318882634A85A9FDD941BCD026B75FCC64F068090BC5972 -F25E08155D46288E4AD897D72BD07234E04CABEFF5ED56D036786CC07016D92E -A638B3BBC6CF15BB6001943D18AB42292A2A8B72FAE9157D2427D375673520D1 -850AD7C2A24748951566C61D6B2CFC1818ED0A67F44D07CF80DB914D283E19B7 -0A1E167D19FB0BBDDBF65C79BD171B17545CA156096032A60EE45160F77C88A6 -9DABD8E12857C244BA0B43394CF491D17C07813B9174EF9D89C9748EABB0F938 -157758BAE4E2A4A69C9E460B9E4AD99F23048D258B0D321108EE9B96F843F864 -DBD079685328F02EEA46F946A7EF927A1D49DE6DD5D9766420E74C7930895AAD -C95C60AC4A1D2FCA0F85072FAE3675EB4DBEC07255C1C0891F87C3DFAF219EF5 -1A64166BFA2E77D1ABCCF87DFB1A3BE7F83FCA5FD0F73586D6B0E66B6415EF63 -2A7B085D9D61DEEE88BF1A180968C784B175B3D9856A3F9479FDFA071343E654 -202EF4CB01815987E628973BC140EEF476CA4CF3E4FB62E657D10E3EBB76CCC6 -EB03E73DB444C674EC7737301D62AE46F26A22E049B7AE657194AF8EE17E47BB -2E16CA163719EF4AB0BA827185E862BDEB8E22845FEB1ACE2960E94256D7FBCF -05F2EA5541B861BE2B0D97576E2440555C388B2B3A906DED36206ED6578D1563 -8BCD8FFDAE85CF16918B2747CFB5D61DBE55F0E5154910E00CAA6DDF27F8016C -25311A7379F820566CE9D9B27FAA27AA37901EE2A4E72CB77F74879E00140927 -89A71148CB996F35E4D2DA6DE9E4B419F1D2387279135677502E169048171730 -59ABF7B6EC751302663320C108861037834E28E4457410A2E7BCD9EBA553E4C9 -A1927FB48707FF104678AF51681ABB7B728478BBE37726E26A3C545F267FFE88 -8E4F2A0EFE2902510D6739A4B201BB1EC21E8CC1E693C7D14819CBD3512A8BEA -3A936897E9EBA3FCDCF0F13A9525F80B182EF1423C5E5A3C82850BE2F7520CE3 -0834D1E448235C68F246CBE9420E853F5F22F1404C7A3DE38B8C3D288F7FE595 -2D09071B6D22988D80D46D3666E2AEB88872B37B5D5B535D07F61DCF0A29A059 -F4E533BC39A06FDB2B45ADDB0190BBB9CA8100EAC30FCC212BE0A475CA57248F -E2DF1BAA0729A4A97A479DDBC64573E00DD22FBEABF86F15C60227BC2D074B32 -E6F73778F13FA9959FB62F1EA5B2B687F870A7BCA4670C038200D4674E168F9F -684FD2D8C626EDF0465CA01B27978D141722C3FEBF42D86FEF470541590CC184 -B487E5816400FD06FFB8C30FED82BACA4671315A7610496DFEB5867A6883DB99 -BF42E232663A17F27BDB01C4E2072A7725C02E631B3F85518A00B6E4BFAAD763 -8C9E89D64B35F754DAAF4549D4E528941403FF224ACF62E172126CFFCCC4FB6B -68FF632DC25971C19AD4AE284075A7A2DBCC894B5515B5CB914185F388AB124E -A1E8BA75BFA9B601724A84A8BBC0CA23716CD9F5B37D0F1DADABF475F23EC122 -162BF687970F2E9720B4CF355C5829E395F526FE538CC265C43C916AC1323BDB -543E0DFD699AF2D3AF09BA03B9B7F458FC9073DD02378AA9B70D90A6CCBB2D40 -DBF2F4E111C65F8F561BD2004E0DC6BB4DA203D79D11848DB7E224CAF034FACB -AF3446FF041FD26C403F31A00DAFDB13BE1CE58B9CE9CE7056C8C2E0C9221987 -8E13BD744FC4502135270FF93F8B476A53066B2BD1F7CA457F39B0544C993470 -9475861C6B0324C3F9687C0BE4CED83AD7D7B2C2F6D28F4C11F9D61592E6C599 -42C152B7204B81F5A64FAF76D0E0CE099F597FED59F4D5EF4947D7994340CA9F -D5B0ECBC1B73207A06248B774140E38846BA0B5E6A7A8F88BE3DD277C768FD3A -E0D289A8C87CD2F61150EB0F9F30C0745978D3EAF105FA555485877050AC1FC6 -A879987588713AE7C38E3639A020382DBFD279AB3236401A954EE71003B9BDD4 -95A51D4797188EDFD0144009E3381D7A6A63CCB6E2020F9FD86AB2853407D8EC -ADA5D3E7B58066AA797F88FBA287F2C323D340F5E687BA4A08FEA9154ED4F784 -5AE1650DC0FDBBA07F733DD26BECD42003F40058DA772D696C4556BE0B9369F6 -3E9226DD203FF16C1B38DC8FD4ABDF248EF005295BC9E560598352D2645CEA9B -71A510701EBF4594B2EB118F65426DC4270798402797DB94124CD4079686DF91 -9971CCE83DB9DC53A84ECB899FC619D275E7B4F458E80AA3234CF5CAFE573334 -D00DC2F92631670510535D8AE7AE12AF46A6208F851ADE39B425E18B65C18072 -DFC2816EBC7FBF5D9FAC1C787822B072B739AB88F7FD8DEE48114B45D0E30F71 -63A174D8EBAB7C7FE646A6038F7F16A4AB483DD983E57C7DE881F7DBC406AA0A -0BD9B02F1ABF43F390CC750FDED74EB3AE170ECE0468D7DD525543C8DC07AC43 -D568BD8749005E1558A811A1A67E2ABC3B8A2680A6EA5E930AA53757897CBACD -DC223939F3E07B0BCBD73702A69DC8EFB34896ED2F80523AFCF9E02C37E997F1 -9438363D34ED456DBECBC021C4F88CCC95D30F576C026EF40E8886D0F3E11E11 -1D28CF7A48786FDC4B2B51B34F19C1D85D118ED41E89F184DD98CE91A33DC5E6 -DFB4C390661562E03E83430AB585F4B1247207D22AEF9EAB794E8E2A41C8604B -F905C3EC9857FF9D597836999560EF1940A7C64B8FBA9D6B81F4D847E2696F79 -B71E7C5CF4AA19F65F9C2CD290ECEE979F7B373F74434D821545F78D295A4536 -7045828EC0135DEC4BDC7E7D0E25F90BB531CDD88BB04D16B7DB32231A86B253 -AED0F6E049E3601D8CF82B86E55711B1D0DEA05E40ABC9FE0F55F2366B0C2919 -051DDB4963B2063FDF8C95AE22AD9CC6F64C78AE0927738CD56492731E54EAB6 -C1FE7535949CB688B6D36F1C5D09077C6848631E7CCAEF6BA8B6D09E449DF25C -A2E1CB85F5EEEABBB0D892830556D609B1940CDE70ED6C073E1F914D975EF7D4 -B7E66E6B6998648AEBC849340619360D69FF7648320E583200740798B2FF1767 -E8B46453E37612E7CCDB90E87FA3E1607228AA669263649808BD322EBF924C53 -17F38ABFD0740A8A69D86CFEF9EABD0A01A4443B27CF8ACA8A29BAE0EFCBB3F5 -A85FE3D3CEEC5962EE8E7368D0140A3E15DE2EC239449F64D7074D2F24215BF2 -C71E142773DB4293FC234820E52F1B9E068E86D80DF6F08691A2B4B8694B584D -D575CCBFA92640B644697BF687644DFB0E150FF04AE0FB6AA6FF6240A050107D -C5F6E4316BEFF51948803156F7C4ADC3D40841982526F125F589D398FA95DCEB -80ADC11560465096F0D5C1C74902CFB4A04C7127BBEEDD068939AD1D345F06E2 -D4F7D7AF180E8811716D6F69506FCE9DBFF3EE7FCCD96E745181B24847DC9BE4 -F62B1907B0B7612A611578FB82916EBA3717F8F2912D608C4052D2B2B5DCC04F -50524A820AD3D2AC158CAB7E67FA96729A5C22945D5176AB5C276E883FD48294 -EF2E1E97EB49FA82D566650259CD9686ADF6D285C4A40F5048BCEEA56EF3EDA3 -9F541300644FBCE3CD5F2DD631C1908D2BBAEF439CFD86A577EEDE2EA6AE420C -450A6CF28DE4BCADE38BD15A4C5FCFEC295A2C14A7C99F78D75A7151CC6B5FC1 -A95441D26FADF69B58B589B13D3294D6B4167C0A0D39B74FAC3DF4F78ACD895D -5B5B7F4D7925ED66323A408C417DDECFBE5E35527509682E74A9E81F208261F6 -443716499B5131978288E6ECCD744F621A0341E400E99B4C4CDBFC764C0209B0 -F602296E6F6AAC228282DB7CBD51AFF102A6C7B31EAAC95108DCAD3C97FCC0EF -52CB3B343B5B2F4DDFC39B9BB1D2B2C47955218094DC1374594448205B04F702 -6B16F57344D3FABEBEC4387A79D4F135B92F5CCC4D713B1B3EE3F9614F9B9C3E -0E8CC8A1BF6981BCA87E341741224F10FA7A1F74B80D679497C47BDDF3F6F21C -8863E66172417B347E4E19F53998EA8202582B16CDC53906537181BC0640F535 -BAB91426DECF471FA5DF51755B0875910C894768C252199554ABD01051380599 -4C522244F32179A7104442577AC317ACC38287EADBDCD530C20159431C4BF2CF -1E2AECD88D0521C338B3BC44BAF8233A7E175E6B9DBEB9250309FB3ED820EF83 -07F6FEE0A61FFB1E988DF80D11E3F0F62AD3551E0F41CD758BB904C88F816A0D -03D109B3DFBBB87536011EBEBFE0AEBD8EC4FA50EF20C2F256EDC1D7F0A3AF6F -8D10C2F7BE71F206CA45D00A6A34D2786EBDBDB8188BBCB727775AFDB3A49524 -CCCFA7AABAED170E1E7EC4D28AADC153A5759830311FB7F25631A90426226517 -4FFDD1EA98363A59CC089311D9601B398FC70503669FCCCB1B0D03AA4FA5BF9E -7C176E1CE75A2F1C7D9CFFBD77F8031E4E96C4EECA264B8892801193F1F701D1 -573575F9751FCD28BF995E77AF7A72394C442329DE642413F1B647671F573E97 -8F4BFB6FF576BEE0C8FB6F0C69A0F4E63719BC5D9568FA1D4F312048BE5604CB -FE837ADE17F9D3AC9B443DCC48277D7BC9A8A2E61CF50420DDB4E902791D4753 -720D284FFC5A720F0C4278E8FEE55192A28DD49B48A34E4DD203995026B34D2C -0175EBD90BE3F4231A3E28CA35702B6BC05CC6945D804B097D3587A1343935AE -063541A6B114486C87A6EDC4CC6D3C4A82729D3280CF29384F0884AA68954B83 -237088C86D58AA5E443CE266681C94D1264207A10FF5E0D274C95F9190EFD560 -F0D2D14090D2EF11AED9BB5B64A4FD4BE18DD7EE118DB3014E8F78E8298CAAA7 -59C56D8DD2EDCCB625B528DF2C3F52D9092B8C16BF77CF463569F32BECC3FBB7 -6D813A2A2E1BC4C4B087BA4C22588349E8DFE84FDC6C94924972C147757AF4D3 -6A8CF31BAEC00D5A2F7C7D5CB6062EE8A5B25343843B7F09C001FF5CA1CD3798 -03968680DFF00740CB879F36F2536BC35C67DA1ED7FD799F4A71771CC9465B4A -FEBAF71098146848359D2FD208B9788F60DBF0E0BDEE9616DFEA61238D49290E -C721F0D4253352B1C56387EC8D4DE1E70EE1E30E90F78402261895A74166D150 -A82277535A5331CCC170467B469A8D36BC6860A525EF9269CC7A9059D7D29C62 -73099824E6B3A08410BAD07601B75DAA79A58D295849BE35BE56F26846D62A7C -B523578CB4210E31C61FC784B7F4BE773E78AA4CA142D1A010153F81AC1CAA88 -E59E094516F4B8E1D3E183ED5AF7AE7970C2389A78362490379DCA0BD16B9C2D -6CB15F823DDEE982F453C151DB9A4335EDF95DB8EFBA8926CB1751831DC17BF9 -9D44041777B5744D4877B57F7EC8D9B1C667F20B6536316801524451089EA76B -EFF2691B26676E5B01F86B5FA1FA302FE1529DE451EA1518F4C74EE8215E50AD -386D7E916B1D6C46210228B0CEBD8BBDD8BB90D766DBCC40E31279E7FF519A1C -1B393AD1FAD738BE72E47D40743622A3EAA68B28BB62C816B11903F854FE9ED1 -717FB82AFCB6C5AB7EFA6B57B687B2928790F99FEBED5C6153C4EBE542474433 -4BCC7DCE4285D3109594339D98E1627C43D1CA82D66F24C0F1AE779D5A84929B -644F23AB2490202E9153756D806A983F4BD669130D7E3E1E112B80EB1F9A2E61 -0A57EEBF0D421234DDB6801DA9263E5B7AEF9055F6DD2CA80A4DCB018D1BE7EA -4944FFFDF62F83295CB02931F2AAA43C70D153AC573842833521F7092F390F67 -01ACB0D063567FF45192F96D62D95CF756756E1CC4E94AB7D316A831CCC87173 -2C0B7DCAB227F4FC95D8F3FA706431B5E0C3361882544F21D5797E65928D1954 -64E011ED2FBDA05CEAF274A6BC5F5B0DEF498423C060B386F010FE87CB44587E -CDC0D322CA0C0CC9C7E153A463DCBC231C16AA8FBA2D9B893AD442F954391BA4 -3C580FB9A98335AB9E28394775D5113DCF63D5A2531E17BDF5554EAA1D4562D0 -855779D1DBBF4D065FEA1BB746B2D211A03F7EEF809EC999A7D32A8732505E70 -9810C8A4249F87F455A3BAF29A3AAA820E4374E29736A960AEDCF962CB14AD04 -06D9AA7722A79EE2894C690F8895F274A9BA733F0C1B7A6AEC56FF1238EADD0C -BFA6B7A283D0CD175DFB6153DB8C3B8590421AEF02F8A549C62A9494A06763B4 -0D9E865736B91F9022F7047F58498670C533F98E961872339A298A0ABC7CD422 -97F0C48DA54EA126B45538584B14599634C6B883602EC1093166A010A740A62A -528150DF94584717C23C1B346D078189320538CB31AF029DB8ACD77DE35921AD -A02E3C69497575CD8BCF5B94CFCB84F91CBBFEC7D01E5F1CCA520CBFCA1B85C8 -8F4567A6D9569BCDCD573DDE6E78FD88851DB77C61E07C0236F433C69D64AD68 -9A31B2FFC998689264B5C8EFA7AB4B41287799DDFC544838A58458B9A39DAD9D -9B30B1E5344F95DEFE5B32D163DF5A671333D6491B5DE96E9E2DB5DC475FA62B -0833525DAC164392A442D0A4ACC95BCEC20994B4FE363C32C34828BE8DBD7F06 -EBB3B9E79AED47AEB5C7291EF28BEAFC7457B85C077F6FD1BE613365BC191477 -607D6847424C8A25FC6D1F1D5C1E7255309102E1821EFAF81E6AEB3B9DB9D2AB -60490EA74D6E251028BC9C7C8F593319A00D8C1D25D296EBD536352653770268 -6F575ADA2CCC98D3C393B046BAE30C833A6BFD12251BB3B5DA36B63EB502A369 -3C94C87B26BA40DADDE1162DC60FFF11DE6FF88E1ADE26300B6EAFA3B4E884CB -FD5745951839A3ED75436B022326888EF1546263EDD8FF7CACC4D569 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMTT10 -%!PS-AdobeFont-1.1: CMTT10 1.00B -%%CreationDate: 1992 Apr 26 10:42:42 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.00B) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMTT10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle 0 def -/isFixedPitch true def -end readonly def -/FontName /CMTT10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 33 /exclam put -dup 34 /quotedbl put -dup 35 /numbersign put -dup 36 /dollar put -dup 37 /percent put -dup 38 /ampersand put -dup 39 /quoteright put -dup 40 /parenleft put -dup 41 /parenright put -dup 42 /asterisk put -dup 43 /plus put -dup 44 /comma put -dup 45 /hyphen put -dup 46 /period put -dup 47 /slash put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 56 /eight put -dup 57 /nine put -dup 58 /colon put -dup 59 /semicolon put -dup 60 /less put -dup 61 /equal put -dup 62 /greater put -dup 63 /question put -dup 64 /at put -dup 65 /A put -dup 66 /B put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 72 /H put -dup 73 /I put -dup 74 /J put -dup 75 /K put -dup 76 /L put -dup 77 /M put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 81 /Q put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 86 /V put -dup 87 /W put -dup 88 /X put -dup 89 /Y put -dup 90 /Z put -dup 91 /bracketleft put -dup 92 /backslash put -dup 93 /bracketright put -dup 94 /asciicircum put -dup 95 /underscore put -dup 96 /quoteleft put -dup 97 /a put -dup 98 /b put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 102 /f put -dup 103 /g put -dup 104 /h put -dup 105 /i put -dup 106 /j put -dup 107 /k put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 113 /q put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -dup 118 /v put -dup 119 /w put -dup 120 /x put -dup 121 /y put -dup 122 /z put -dup 123 /braceleft put -dup 124 /bar put -dup 125 /braceright put -dup 126 /asciitilde put -readonly def -/FontBBox{-4 -235 731 800}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5F00F963068B8232429ED8B7CF6A3D879A2D19 -38DD5C4467F9DD8C5D1A2000B3A6BF2F25629BAEC199AE8BD4BA6ED9BBF7DABF -D0E153BAB1C17900D4FCE209622ACD19E7C74C2807D0397357ED07AB460D5204 -EB3A45B7AC4D106B7303AD8348853032A745F417943F9B4FED652B835AA49727 -A8B4117AFF1D4BCE831EB510B6851796D0BE6982B76620CB3CE0C22CACDD4593 -F244C14EEC0E5A7C4AC42392F81C01BC4257FE12AF33F4BFEA9108FF11CF9714 -4DD6EC70A2C4C1E4F328A1EB25E43525FB1E16C07E28CC359DF61F426B7D41EA -6A0C84DD63275395A503AAE908E1C82D389FD12A21E86999799E7F24A994472E -A10EAE77096709BE0D11AAD24A30D96E15A51D720AFB3B10D2E0AC8DC1A1204B -E8725E00D7E3A96F9978BC19377034D93D080C4391E579C34FF9FC2379CB119F -1E5BBEA91AE20F343C6420BE1E2BD0636B04FCCC0BEE0DC2D56D66F06DB22438 -452822CBEAF03EE9EAA8398F276EC0D92A7FB978C17805DB2F4A7DFBA56FD6AF -8670EB364F01DE8FCAFBAF657D68C3A03112915736CEABAA8BA5C0AC25288369 -5D49BD891FABEFE8699A0AE3ED85B48ACB22229E15623399C93DE7D935734ADA -DA7A1462C111D44AD53EA35B57E5D0B5FC0B481820E43222DB8EFCD5D30E15F9 -BA304FA879392EE0BCC0E1A61E74B3A1FC3A3D170218D7244580C7AA0DC65D19 -741FA5FE6F8CBF60250ACC27454BBF0897CA4B909C83A56672958752ED4B5E79 -E18660764F155E86F09EFA9F7685F2F5027EC85A775287B30E2069DE4E4D5712 -E7D033481A53A2702BA7542C71062173039030CF28D8B9C63B5596A9B42B33E7 -D922944A38713383D3648A4AF160A3B0C8F3379BA4372BE2E7EA49AABA75AEEE -C5DDE1D8BF68483C3D21271280ABB91D54CC819680322EAB72E1250A760BC8DA -726405EFE420635B5B7F0B48752C06083E92BDE06401C42A2C528C8A60381227 -CEBEF0C9440DC034DAD9C19FB27DB399BDAEE22053591D6538587C768C1B7B0B -7D1E222D2D8AF3A6473CC4C0D6C3E0DB49068CEB8C9BD1C5CD486A50DAA10BC7 -7D6286142355E3F21DD254E27C00C442728A0BAEC9D3F17AE9CE320D365152E9 -EB0D5E3874F2BCEDA98521D23FCFC30B4B69DAD2ADBE80E5964ED0ABEF6C73B6 -DAD30E2C5061E3747FE536E1A5D190D028F2130AF608F5DDF9DDDF1E77DC8437 -ECB3EC93B33505DF47884DDBD1DC6BBE4098DF04A29AF6FA3AE344600D0AAB53 -B3820DD7ECB600A3B8001C51AF2CA7A39AE1485A087FD1752DF68F55B52B4DA7 -48030F2AA7E570B3D56C4EAD367B9B73FBC0A7356253233006178B9A6BC19081 -B815B5988AE76FE6FAFD7AC239072B1106A3F509381AAEE79B2F2154CAC4727B -D199CDC8B4D05DF4BA006982512ABD7539E28D937B0F87FF79A3F84C29ECF943 -A8DCB8BDF8EA9E7A0E7CD60BC2308C96B3E889C797D0FF28FF4847016B3DA141 -E76FC6BE78A6EE9CE07E651FF86E720A1A1F075972D36E5C55162E3FE26BCE3A -814BFEB12D4C5FD24340CFFED499C7CA183E57EC4F12CFFBE3291D43F7270575 -C6C3306F832EF182ADD0AA14C4D8669A17C09F632406AFA195F90C4DDC39779E -EC0A77E590211592D6EE19563963225C06C2F13265EBB5A6CFB7C17D9E77650D -11958305727AF662AE73AD0E3ED5F7E7086C5A0C3548A8129575980B06C715AF -DD55C8DF869BED0A7883491030B1A7E82C5EB04E5A7D952E716DD8F2EF6275EE -087614CFAB55FCE2BBECD7E8D9C90FD8359E929D5E0A416A23BD58158318B4FF -87B095EB63F7F052B3A77F136FD66EB2C52BD46CD7DB3091A4B78A607112B12C -4D171B2A00B78B0E1C44B0D90C20D9244281F5123DC1F6063F91E9E3E48DE78B -C862D848BAD073A4FCB5EEC9FF54B5AB8E234CCC3C7439C62ABC4A13EF1B8897 -ABBF21F900C564C9A305FC36FC7224932F766E6E72C2EBB55953DFE2AFC2E3FD -33A0C6F0FDFF086E9FD796E7242596AE85B877223532667625E371D2156E4C04 -0D7FFCD3337B93DF066CB6FE1E13960719EB7CB409EE805C08ACD2C06303ED9C -E34C898787A43C1B428B896551C6FEB50A831C6F8CE2073EFC662EC286CB7555 -A3B42E58772E82FEE206948B8C439FEC5E4ECB9E11DC3A4CBC7611E30890E408 -637A01A2118441B4F9467A98BB2A1B03BB2F5D8E3DB7D1D15C188D9E856088EC -B762F07B1C06024F7EF53A2FBD60C0A1F4C0275D07164545250ECEEF8CB15B04 -A2D8AC44DDE818C4E23DFF5B846F412C1D28C52DA1EC7F6B68D2E63E6586EA41 -0B01DFF80C744F65C069047200AFBD969234842863A2CF78DD48BC0BA686C91F -3B1382C42DC044F539B7089E055DDDE9E76F7EC4A120B4D8D3E14FEAD686B0F5 -3EB80AD386901D788C51B61A9C04955BE06E75B24FB77F501D9937DC244B7446 -60E9453930286D8112EDA6EB6291C0BDB909AA3B3EA0578815A4CE3AFC9C699C -54C86466BA0F2FC9BF260DB773E29B2D4AF20562C31E83E45950A3A777E06C18 -0F29343F91938126514FB2B4A81C98E9CC420F54C8CCD614FC7AA290B7D42FF0 -429259B32D92836F4B71D517C130240B63949875D2423339FDEB14B1F1FEC58D -49BC8B826DFD0C2DF5E94A4B4088A7E4029EF2B97B970A53A43F0D280CCDB41F -8F9F3573F522404F634212E534EF3B2FA648D9BF218BAFA1135F6800478D711B -9E3FC435C0D12C845F0B3E77DDA804A75EA9BE82DCB9435BF16A2B94CF7684E6 -748B2BB7C5EB08C5728DE734125E6E48B895FF3483E07558714F68F2FDC0F4F3 -D195335C8216499611CF9355764266CFB43B77B30E90BA64BC8EB301B5E2D060 -B1C053E8071EE600A76C8309801C7927F77D1FF4CBBDB83573EAF13DB5588412 -23B6F8EF8C388136CA0BD33DA6043043163E34E1B647A549136C33DCF3A816B4 -BFF8424CBC2C9EA6FBFFD26B7789815EE0D3576FB50A3D0D2101D4C43C0F67BF -16984BAF98F16F7652BD26329516CF3979539C902F5BB43BFA0B1DE623E26CA0 -521BE8F6908E249743D1F7E62350986EF4385E7E617B1EC50F7408CB18A0352A -9CF70E0FC30958BD6335211756B872801AA86C2F43801FDD42BE49F16DD74849 -40E5F5FE77FF2948CBCC494E3D9259938F26C916EF34919924CEBEA9315B603C -5D618FEA13211BD46B019852FE26E305A4EF2362536C9FEA7475769262D3C2EB -E4E5C2334FC9E57F57BA7CFB29AD573D3FC5CB5781419899DED8B473385280A0 -B375271DC9550455D9AFE5171CA247F90902D62F65F84D05B5F65B8BC80376EF -A0DA23DEE61AEE96577629DA3835F2D50C36D181D714E5CEA92198F4EDBC4A3F -17995EBCA8A6B3C86EFF6EBEA1991D3A3BC2EF33833103F462CDA92BCA15974C -49B3F1E7D585E056666A2CB937B7B49572A12E9953438F334B727200C9D7A86F -F995C454EFA2D0A5B6043E85A5D282F6C6CEBF5781A59AC4DEA90A6E4F2BCC54 -B77584E08B6FB01CD73D5BAE1AFB220EF723C9F99F0F8ED7EA821FF9BFC9D57B -1F84B91A3CDE5B158D3DB7D1369D51CD9A2822D4CCF0DB935B56CF3A52866394 -0899E7A965B08BB808186D885D12335BDF0095C476462297D3AC3BE208B1CA01 -54CF223348B87BF3472AA2966C208D7BCC2AA07BE712AB448824D7DE9968C6F5 -7B6C957577BEBF7EDCFC01EE0D276501830548E6604D50E4C534CE727BADF7D3 -BBEC9CE7E326DCEFF2B5908BCF60495C7CD9E47448434353363A82096FA9E1F2 -1F8C780C4917DE4EC79CF95A42CD2D15E3D51BBDB9CD624F9C358390748A9A95 -5AB4DFEB92EFEF7FB8907751FA44DA024FA91C6C064B5E61069B2796590202F1 -2DFF657471BADB7A62F2ABCB770815750378DDF973CD4E11EFC3D19C27C02171 -4AD74C3CC0B96793A7E0EB9A0AA40C7A6D426100FF3FECF3E3CB60ADA80DCDCE -870F74D04ED5B167D965F8AD2677298548FBD803C716488925CCBC9A3C515D3D -86C03CDC708D2F95F403008963361C8E7EE7C5C62C15DBE6B22C2CDB249C4445 -21C8AD0C014BBE4B28827A5C84D714327904518E36EFBF4356DE0750B52035E9 -2E06426EA0395C4852AD2ED3129F4D43E3BB75B546F092C1E7CDFCFEC2F00331 -D9D0BBA5D76287C4CA7088332D5BCCBDBFD20B7A07DC6619A4AD3894C699B01B -045D803FC5E36061648DD13B6BCD95844E171F4380CA89F7A7F948715630A623 -DD5E011B419FAAB28B814DAFBD3DA2EBC7B6CA635D62145E87679FC56843AC49 -FF421EFC70F30062D749120D1C492EF1070EAA096E283CECD8411964DEA10390 -147718F191A0A786C3A9862EDEE74767762BCB27D5621A5562EE1D22BE784FB4 -0BEACE3F8A806ED5257A038C8DD59D3D52CDB4EBC501C13CC9DC9BD89A51CF86 -B6C3F769C470912FFDA75C99C2EF55D78874558397C923C330CCAC3C149BA314 -C6CBCA464B176721E9C04D0C08ADA8BDEFEA62E3231FCA6A646F837115D0F479 -E51C7E509BB81045FE2F3DCD4A761E956BAF0561BCE5A0D20C0F1C45F40306B5 -B6A834974281675F2A33F258B6BF7F7AB717FB72A96C0D50DA6B6E4D3EDF9416 -6640E77C36BC882A09024789FA969E730CAC7948640EC203B610D8B02B0E8897 -6E0395D5C45E7D414331145412115E3DDD7D137716192A10F8D1F6E134210034 -0AC5572B33F6FD9D2B95D7D62D12919B23F7CBF114A5E1FF5C3C310CB947B914 -E7729E00E22E2F5E4614CE226310306FEFA46DC9ACD671478C026A15FD6668D3 -3562902F13842676E2A15F813364FBF3751A6BCA132596BB02DC0BCB18463F0F -28C1A0E1DD23BBAB471ED0A91788353A27BDB2D3DF7F547A2E401DD536417F74 -5CF1285AACD4D96642200201BAB9EB201272A1D102FA7B4C293787CA1DB59847 -482B209F980BA3107F7538C5FA1CDC5DB36C5F0A7917FB0BF90F185CFDEDCDA7 -3B1D584F43CE6CFC46EEA3907B6E81BABC903DA628077D83A1F18C291729A92F -77607547D61D0CE06750F927EA4F37AA39C1FFA07EDABD3147228D161F0D0FDA -771EF1F476174134A27076EF9AE92D3F6DA91C9568C0E27BB954E27CA09345FD -2AFB9150ADB7AEE906AEE84C5375F25C2210D3F5A3C57298BE1B6AE3CD38DEB2 -97904795D70A9F2082DAA0C6071AB9E8FF71508AC77052A242DF4D01C9139805 -C2F5BDEFD7BFA42D3B3335332B37983D213B6F7DDEA6217186A93B911DCC0FE6 -42957686973CA3E07AD6EA4895AAAD5D5CD878AD776FB9975EDC7EE3934EB131 -37EE8F063BC1EBC11D807BEE136A31A70EF2A46B36D99B98B8B1B933F032FB54 -B9EAFB5CFED5D813488D6A28250605034BBF2BEF55108CA0D6FF94BCB1650F91 -99071E1A1B3B2F1E8E7C89A5E4DA1F77DBF6AA289D331C35C2C2BFDE4A391C6E -FB679CA42BCB2AF018303A3F55EBD657AAD46815B45DD067823B4BC3FE3B4245 -C9940627467C5F9AE0EAE53CB7CC118984272BCC5E1B8548494E812676FBCA78 -A70C417C270EB6E435A6A75CAB4AE742B1194E3F9811A7B581D9C552A3EE5B1B -98E997DE7F74B3D85B46825B620B19357E4A7D82AE97C3B85609335B1B41A532 -FB2F53C79A4064C88C84FCE693FA6EDB086732B6F76D31F8A6FF27DD850DD1CE -B9C29258680CE73A371B3613F17A3533C5EF5D4E3F833E563E976FD58B381643 -F097AD8D3BBD1E4F0C22A79F464FB1168E6B12E503DEE9D1D563B6F9B5A8D6DB -D1FD6BF4A90DA086275F7F7AB784F8F945569601AE0499EFCBC5F5585A759D09 -6829A9649317B8C53F66C083170EAD52494006623FFED560D382CE663A1B4BC0 -D68B544A2D3F4AF0C1A6E50A4603CD433329F379B960A2E6822A381D91DADA65 -E5D973E67820C6AFDFB917126A4C4C7CCE0C00EA9762059E3BA7C3BA56F739CA -2F89F58A2F058A78FA9F0F040A8B04B77F300343CEFEBF9357243118D9B62B83 -2EC312A4AEBD8BEEDE4DBF3CBA2F574BF9AD66B43C19615961A00D70ECE67C17 -6C93C248AAB0D3F9580ABDC833D52A5BE4A5C7F06C12E934BCB99C8D484A0CB3 -BC75FE276F26C6AC861A17CCE8EAE60AD5E4573D4DC2FCE59477702AEA956B2A -0DB471C240961BF1402F6ADC61C3D7B72C78145B5FEB9853485C862FC428BE26 -F2FCA109EC1D6F77284C5ABA95359FDB4507D921934DAF4EDE1A1071F7157982 -3A9799E17F5377F27700EE7CB253ADB2371B228647FD11DC38F4FCD9D75ACC96 -D6B5508773BF71AD6B9D49829D6872CE8271A17C6FC89994159850529D5A8A32 -206A8BD5E688D5AEEDBE8E0195DFDD5ED07D11DC54131B7E22958959CD35E529 -F9DB957C31AEA4F25811C7E0B9ADCBFCD7AE1BB84D65C7EB2BE322E245F50CE9 -D611E6D52493244E89003784149E23DCE1624930D53B937405064775D2CF8103 -66D2FE6F360D5AFF017C7CD773F0303CA4F8C9FD08B91E414546CECECC770884 -87FA3D4EDA2E7D8474D5C30EBF966C9F40F4707E939C22779BC757DB50E9BACA -80E0AD329BABE0AABBCD5C1C59E80CF55E63F84F49FB24D5F8F953D028568083 -015973AD8921C03794814AF609FEE8A5466BB982A15644C00BEDD08D351F661A -AB6DE4FD2715935A73399ED21B074120B214C8E6BBDD346CE84E704A8DF4EB4A -73C5ACF8E106D56287BF82A4C04C8AD092B9643CC1512154D04AA5213EC06B2E -6B8A5452428EF353C92B18855E9C7BE2BFE82B568AA0A4B620EAE77EA0D60755 -E78C6FF41E2503A3868195127619E97805A628A0348CC7C92C3EBE700EF008A5 -86B6B5736A275BEB0431FD754D9866829C9B8218552737AE357B6DEB6DE5B17D -5D86DFE33C9A4C93CAE5DC1777EA1DD2D810FC772C8855B4055A1B520BB0EF02 -9B1C32FFFEA106BDE7EEFD7C05FEBEA882C2FE39993EA2BB7CB9DDF009C08642 -B3B12A2752F8F6BDFDFDF83B0F8648C309248AC9274C823CEC96A0766C58488B -EF98089D39CFFC48DB5076BC1DF598C450E76E32EAC21E2A63ED2F4CD9BFD34A -23731B4BCE26D3500339CE43CCA5FB9FD2CE1BF78DE258A270490158921A8430 -BA9F37EA3BAE30895A57D8BE8A3DEA3DA9E35E3AFB9E650815E81F9252427FBD -4B27B5C81F4F6D98CC7B7E289231FDEA58E629C4A414C5635B69B7ED30BD3583 -2C0CE0A350FA686F91C11AC4EF37F651FF61BB9D087E42A7ECABB2073D930C03 -E206ADC510961C03634984D380EE3604635695DB7B240CC9D60E31E684867FB0 -C7AF5D477F96C24D377970A9B0431780F0EADC1FCF162245EEBB2C99946C28D8 -E85A85CE650089EDDE2C11C224B3BBC65835D33D25DCDE8C9ECF38FC58D24972 -EB715C666E5598E6F6ED4268BBAC9F99D725B95F81B3A93EDEAEA3B33EC2025B -C944E72BDEBEB532A01D263064123E1514EA9778E34DAD260C3EFB820E9B7B2C -005FB6B60E44782CBB9AAAD0D84E2A7FB9B9A003B2E9C4BE6528537B909FA590 -F2AE7CA038C6912DD59455C76BFA330BD5801BB94B2869F9F4011DC70BD31FEC -A18F3944CEE997E9D984425D95C28DD02D8E0E0DED0D1FAF045C6BA250868E80 -730180003EEE66D87118E677DB28B9F54AEF115FC1F1BDE48DC42BADB2F70A05 -0112E3E69AE8F24E90D2C020131BCB703D4BE761B59237786AA2565B1FBE6F13 -66F74844A3B2BD29F9BC483BF9931838BD701F8FE96B0751A3C2E93E326FF14A -037BED6C2D42D93E06082DEF985E39557D9A0A607D5DA570E084CE011B3F96B6 -2F3633344FB5DEF35A48F468C019A9A881C036F095A4516AF9289085217C2556 -62808AEB100B2D3D049629C688392CC8A62BBC7494881B5F64F71F6A280F86DC -288C82510A59277BBC18751679448EFDDB168F3BD63947E6C96897DDFF56A60E -747AF59AE10C996931ED47E0567A0FB1EB9C2A7F062E04CB75174E05D9571D1C -FA2EFBA213E13CA73D9FF1CC4661E04E4D1267CF8E792F6AC270F03C38B7DDFB -9155F17C13DC7EFBEDD541AA9FD866F3214FB78FC78DFD68A4B8819144D9A28C -DA70DF8489B06196672EAAA63953DC4987FE1BC025CFC38CAA8DD29A19E0B007 -F99DF8D4D56FF048A53A5A4919256A3918ED9C87A681B168120E65E24EBA3060 -EBB79FE24DBFCA590B47A732B5A84F68392E5CCD7F0AAF8AE46E8B2F7B9B629D -984BE10229CE058AEBF5A5625F3EDAFC37D75C087BBA244FCDA5C6CA4D02EA1F -3F64D397F84FE2AC9ED7D8F03BB56BB25DAFE7E691DC2F7F42B82B79EDA8111F -B98941BF10B58EAF2D86FECA8239774A6AE2AF22F8A4103D0CAA22ED11E639EA -899DC81867C0E3C42F6FEB53370D06AF2975843410C8114F5C1057D53F078FB5 -96E572702A18C71E09DD607BD6CCCB2CE9D3C84E9D626CE715805C0697204A81 -DBB43CD0B952BCD9EADA1FE80EE1E24B1C328FE08783FE66C8A1F615EAF8CFAA -DD5A57695ED5BF8866603CFCB4EDF22FB010CE429278CCCD13B39C7AF2135FE1 -DEFED11CD2275ED4C51DAE380DF3CBD87A5502AB213D816FF6ADF4BDFC53F18B -1BA97CCC685B11BB417FEFB94140FCE2733949AC3E2E1D25BEB6E6D2E5D83144 -463283C90090E110280FC2C220DA957E4F74568CADA115E02BA45417C09CC34B -EE51F2452A50D20A5B8D532C283E46E6AFBBA38DECEB61836673F76E8B20FC0E -238CE894EA5EA7C7D0AD342F87831DBDB01586AF952CA32796A6276B2AFE3269 -0A26B0D6473A5FBB2A7FDD47EB4CB0AECFE2EB581146A37B403EDF0E53C2F969 -450DD44BB534B0D1F8161CB2B04FBD5FB691FFBFF6AEA8664FD8F776A2C328A7 -30E745E7F8D46289C8CB4FCDAF7A42371604E47AA073B7200173E1D0075A7895 -747C48506669C5FB8EA2EDAC1BA526BF2A3629C7457CECEC6D8F0296C2107BB4 -AB5E3895B2DA8C0B2DD14E756EAE39CC14480AC37EF83226903389C6AE3A4109 -C93577F97BC888773C24DD888767B11C9628204AA55DFF463AE17936E6BCDD15 -F93C818EB1DF9F2664B1BC06BEEFD54A913448E69BDCBC969B7653B868D54B81 -8934B0E26F35BA405917D207E2C02266F89261C2566261D204DF7BE4E4FD30F8 -E5914FC6956A02F641A478DCF80C02A2B42BA2A326D2202673C65647475460EC -99999A568C1B4C259E3B7A16B741004FF2901AF4F186D02F44B0C6D3F53A6F5F -B4066C137C8687ACDD32F7062884391D6861FF0543A377F06B4F85490F096A1C -6213247A6F0C7DFD5EF4940ACB1562927FC7EC5FFCB07A393CBF6FC21C94BF73 -453B75ABAD9FBEDC164EBAA111108CCA28F219C0003C488A54BB9B2BF0858419 -538058DEBA6C22CB17B7786C34D3F569B42D7065ED309A5AE6F8D457B9655ABC -BF4AB6BA6BA1EB95AFE3CD45B37BCAAD8A715629142D9D1138CD3314CF2E777D -BC790A63DD1B724741F23B4D3B39C2D3BED0023BD240C19E129B6CF5741A6ACC -D6C0310DF5A560D7CA26AB6AF212131073CDA02C770A275F7DDED8C52D673019 -AC4A4D4F036F94FBAA1448A0BE735C2CA1193B0B3795B3B4AB693C5B97EE0DE0 -CA05AD896B47D71CE613090AB4B0F5FAFFAC48A7F52EC247ACC0CCB10A9DF052 -6D19E742A514CCFD71ED7EC2C7D86118990C93748459293FD21BFBBA03C57C59 -18572EAED78F8E0A39A03A7C8C1ACE30AB791FB6C477A4B74F21DBEC1DE8F611 -B1C849F0A01F93C4E1D76F5E0AF2537624C2A263EE163734F71701E05D77C1B6 -AD220682785BDE886373582908664529C9D081667C7354AB745600E3A610F672 -53AF7D1DFBF502594B2B50194406F831251EFE156C063B458BD4F42E7DA02833 -23CF0005BE43376DECD1A306F75261D6248A6DEDF5F56AFDC8CD410BE0213C4C -BB9304DD363D0D60AB2B2D645A8ADAFAC099847344A7C010CD16E61236DBC4F6 -D9EA4FB7563A01E3F799123FAB7977699D1134E49A5E079A69D8E9296A062F30 -2F163064A215845D0D65B815FE0082852CABE0481120CFAA3B687B32EECA8F62 -CC327D1D7BD071F9945AB8B9539AE8E8C5A717FDA594DEFE8511BBBAAD08D7A2 -4072A4E4ECA0F3EA8FAB76883439ACB4727A36DF72DE574418B13CAEB099E9FB -466DED499B8E01942E2D6F72035222BC90E6BBE16ED4FB2DBEFC64CD371A6FE5 -97D70A6E6319DAF2AF90064B7A240A6B11493984E63B84DD3D59B4243DE9160F -D2657C215AADB68343D6ADA3268E20CD294301ED7C46F137DC50B152A2718BBF -8EBF5880626E9DCA1DFABF1AF6828E8D5AA9150BDAF9701F288F864D8C91E976 -9E9BE865B6DEB2796C6C3FFA603A947B9F43790A98058936B3109610B502B2C2 -320E75318B535D194D764C0AC7A322B5DD0D4520F96036908CBB808212A7B27E -CE14671E77725B8EC619C68EB5657863D3663208D21318F7F9415B93B1E72BB7 -83612E137E85645CC4A1327859818781CB1DF455AD4BFC77E49A90F893179F5D -ECF976993082E64B63ED0533008AE77515453DA9B07AB2F1F0B1CE816E6E1D4E -D0D7A445F75F126538FE849BE9A9CA6BF221DDF53BD7E9A45017D919A46B9287 -1D1D98703C6622F41A997BCE4F77456A23418E6BB7C0F9FA957FE88A449DBD23 -D713F39CFB2D4A639AB99409DC6DDA631A53CF8F5F617159E03BCBC89C688A22 -971129FD158E8AD10D39AD3D2E6A8A469BB27AB8F929B28A3459928FBBD0C33C -4DE82E1E1DBC8DDB977706FC4B5C14087456D9634A65BF0C97D5C49593350CFD -826633734D9B96E850FBD5F3F319ABBA61397724E8D21B14FE56B6367ECEBBE8 -2D7D0CCE1C2FBBE5817C3D60CF93CAEDF9886632B27DA37F7C1A0342911D160B -E520A5D20B4013983021365E2BA6792766B0541F3262A83C4E863A94FAE921E0 -57EB7E291DBE76944B7CF7F0D7363681586B405EEDD879BB508FA7E4203C8854 -44027B509D69E1CAF1BAA5C1A239999E190C7B91D315AA81B289FE88E5C43D0B -251FAB17BBF7D49A71F75364C6DCECAC2C22ABD8D215AFD535C9EFD9629F178A -A75E11332FF6B05A4B1569306E3F3616EE35D8338F65B6601D3535B2C6EF7EAC -C71EF79C4EE2A862A75531E4131866D6836F7569B1659A734F35C78FDA7F3DEF -39397290CF54AA9C263E7AEF736798672CFD722612716938391A1053B727C7B1 -BEA9DA04AD5B47C42E7B8A53F98AF379F3353F0FD438D215B517A69DB1CA5F27 -B567D55144197A840F0BCF876AF832CF3F620A1E2EB286E45794ACF216062F88 -D70270FA4453AE510543FB2E62CAB84A3BD7E2F5881B20B5BFE7FAC1125F075A -84070D639DDF28A73E73478FD27FFDDFC0246B3AAE90143AAA71DEC5E440C660 -857432CAB7E1E0DE1F6ECBA47F0E0448E21EA69126434DE576DD22996B9C4671 -1B5B07B923B59A56A39F22396B2BE68B14283BC384F7EC76C90DC17BF57AE82E -AB5BC5D2F39C916F68167A22824BBDAEF18501224005E4E63D8A357F85CDAC2E -1F7FA28FC65DC65FF10059A658F64A06E98152D580385B2DAA906ADC3840245C -7AAA12C0945F8E14BDD097A4BA5F2BE5F6C1704C256FDE77DE6671FC25B05400 -61EB206F67B7C752E406CE88205485A27E626161E3FFEE0153BCA76E4F474E22 -57DECDFB9294B874FC26D354787AE7D53389C77AFDF711FA5D7552FE3FCFA9B7 -DAC7564C749913F4020389E4C7F4DC4FE13ED85AC8F57D0477D752BE1722B02E -E2B54C21DA7A976EAF928B142D2E0A5591DCF14420BABDC027E06CE3CE027336 -C20703A85CD2D290AD1DC4D347A05FE5E3BB87889B74B7E0CC251A58B2F999B2 -F04EA13EF3C6CE11D6FFDE47712BE6C84428E7D95E26DE1BC6142876868B6929 -A8F88012693A34E2740818DE3FA7458EE6160364795A3DF3CE46A3BAEDB5E361 -B1BF48DCC0B9B9045F65A4E9D61BDB537FD76AB51C39CC123DDB09534FB63C1E -A5F85BA1DF0EC2736D029EBBFA7D935A20B087832EE66475FC2AF6E938363F3F -708949FCCCD04CB56E8A00628106F12D7D6B31D08D8A047C5B9E39F4C8F1A7E9 -8A06D46ACF7ABE91EF88322FC5C8346310953F9C61CAAB6B8AF4C489447D6A08 -125F9E06EA30D6B07DB76E305626581D69929EA0B06E104674747A436637D015 -34A880E798BB653C9AE9E8BD619FFA875FDE8F488CD798DCDB0C63532D0D1A7C -C866EB30FAE071B43C02EE5C01198E81CADFF0686839C2D44FED8257A2BE9E88 -32A38671E067BE2A49D3BC5C0E7893E12A04355315FB0B46EB033DFB8C101EDD -84749263790C308966FE76F6789F21CBDF83A280C6D6FE8BDB669E2F30795E46 -C6EDD896F762C9F3E647BB51E43A7BB4A949F51D5599C25DB872F75D72E9BBA1 -616BEA9E026069F0262868FAAA16B44DFD016F80A6DE44A4A69B5AA6AB8C0424 -C2932BB816DF4F7F74145AE2A0CCEBB71DDF61B2208823E42D3AEB663E3206F2 -340F7369C6645397100FE513FDBA478C5DE5C9A0839B5DD2430725529939B414 -89BA91759A62625E40B92E834A9EFB3C68005876010F9CAA8BABEEDB06B6A554 -21609C50731E2435361AB8F53BF71B878591F8E0BDECC464736D96271F8872AE -ADBE8BE4A26B8145480F7EA4AFBA97EA46F6EFE3A52A20711ACF947EF3F8B580 -500DC99468972BB657E57245D4FC01F8665C939D385BEC9126193E1DB54E1078 -042F0B0984E812A44726C4B369EE9CE54083A417BC8ABB50A6F2B185E3B8BCBD -53A75936812779305A859E533617E5192DA6C3531189CD57DB856B29807F383B -530DE0218926F7A6FFAA401D3864931FDA344BDA891E32359EC567739B25CEC1 -A4C8169F251ADF4594215549F7F225DD1F20F1269CEBFC88CBA7CFF4B7214B3A -C111FE9B511A8703810E222406D86F41996815618661ABB2C69F663AB97797B3 -81D7BA0172D90246E5B076662ADAA4D2BC8FA1BDA20F13F9CB5A70465667B32F -EE2A1FE5DBB8BF41ADA4B7D3970DCE1972508929AB078E35391BD8D8C0FA2FC9 -A0C63973A0236E7582D4EF32D3213BEC05DF0ABF760767CC5020B609E8225CAD -E64A95D1E7D032833DD90ACCE8B5E40A3D57D6D5F0B36617644E83AD6BB70DF0 -DCD7D9410B7F47763F7FE5533806A1DE39BE6241C07B2BEBCE630CF7550B1595 -81EE53E4C92D15FE69B8591DDA933337F7F789B3BBDCC5526B10BB959E76225B -2569292E55B90B4465A44624AA45A4327E23650D4C9A941E8D86A2D619CDA196 -EEA705015C6EA8330D3C04F293512955F38C4170C12D709C55A2832C58930C13 -D9B37FB7D4C8B0FDCAB5BA07FFBFCD805FA6089DC09D2CEBF1DC3C894CFD93C9 -9BC945C25591C38596062BCF218F28DE9B4EE244182FDA170A07A7A6CFFFDD8F -B08F7AD8857066E582F48C596F3C3B3AF67294D1C45C5E5E6C2B7BF67C8AE472 -79835988AAB90BFF38E234EB1F49E67200F77BA40CFE10463DF43FEF5FB13F1A -7CBEDA0B168FB8DF78C793CE54D309AD9212A1EB5883C5FF17CB637390D2DBD6 -07F05E04CE60D3211C1A32304D1DF076EFEAEE3ABA07DB78D9C13F58FB5B3DF8 -1A92DBEDB9EA5C55E3752855AC1225A2345D3B9E37F4068272AA3E465C74D122 -782864FEC675506304AFE1EBF79D0972A652D452FA8F70F9C6BB5F7B521E534B -1EC7CC493DE8D55C2F0007B2204D1E59383FD1380519DC4E699BF7AF8D81DA1F -8B0E9626F17C2F620117230E9BF7C4A58F42F8CC037182D73D7DD884A04E0C38 -C9B7B80589278B76C2C858C9735A5816A0CEA72F099E038895151004E1DC8CBC -B8D53BDA668D8F985BF4FECA6E8646042DBEAEF1AD6579B60FACA93175F3DA04 -40F034036E621E1C7F31A376B3765B285B7E4CA83CB8CC1014658C2004D777E2 -2D08F4B307A0E63DBB23B21D2A49101BB7CEACD2B40A686DD7C66F4FBC5B6163 -24F3A4F48706C45D54FE0056B5C4E748FF43EE41D34563867E41D8160500122A -2115AB57213917F5B1BEFFDA531DEE363AE61D480B05F7F2F440B851B6CE6265 -2FFA0A0FCDACA7C1FB9948A63967B3E4E106A7D2194844E368623FA61D327321 -C0949D6495FD37433D8157365435FC316539671407676D347F7841CAF39E315D -00B2F5878D64D0BD920D3E418CBEBE3EF5717D509F0AD20C2B9BF8B481F8D7ED -B1ABF3595255DBF1DA8AE4FEB4EF00FCA5E681AC5C80F71ED707CE5B6D0DD8B3 -800B87042E1CA1C3FE1AC461FB47E7A8AF5977DEDEBD2B1FAE57780342CAD7B6 -205770B6D14E8C4387DF27056D3E3AD60FE0811A1F9D2D7DFB6D1D52CA8F8E6C -3EDF8F78AE862AF1D75546E4C0C624CC57A18FD61968CF742FEA4B45C758CD53 -78DA3A32960328BD4079C7280F19AC3FB66D24DA8C9235AE7ECEBA537F09A958 -F5FD63C4E3A0C49F44F8CB0A828D2A7DE24949138C7206354D6BE8CDB99BA5D7 -C60CB286AE290268214AC0A0C3F775BC92DD5326A100CF4842EDC00AEC236CDC -E4F8F8448596B7E59BCB5EFFCB7D8C90837FA5BA690B9FB4D4F24BE0EF5EE864 -717394793E045BA233A7B146AFECA0664577795ECACF06E811E1A0147A38A3B9 -2941416AFB19B4C82A73921AA970B08D68818AB2F159E527EB7C48B64C43AA2D -D5DD0DAD15AD0161667D273BFD59BA13D7AFD709F43DA9E1E5B3B5CCFE7EB38F -08DDDD02CC0CA2A60CEDB070D54AFD8F8EEF0B460E839A2904A8DE16CE73F632 -3CBA9A65DDC7DFF06E5FD2B074A6312D01F8D75491B87EDBDAF045FD2093AE79 -0C2CDF2CD7677D4639E412812A7E95224C3995631589DCFB5363C82E7D1F66D8 -3224A7172E5F0DBB88275EA86428DF0D223AD4079C9D233CCF7C83D3D488EA8E -0D1A5710DB03D00B4729E51803322DB1C649D2C0FD6D3ECDD66DF8EF0FA80B1C -C447EBBAFFFE5BCA6262F252CAA42FDB90837425645E57637A4FE5DE5CDF423F -85E41136A2DB6EEF9FF48965C73E07A1FA4C9C0DB88E5FDD963E55528C8986E1 -030CD62EF13B3DCD4936080F90EDD2CFBBC294E666E0D78D448CA04113EFF2D9 -C467D9E7616C426F93C1AA8C3D31D26B2F14C4B1ED42390E613B4881D137F79C -07A1E8874FB91F8C3F561945FD8903D4BE99F18212E8DB95BE4220E57876DA3F -5D502316602D0CD1B1121FC930F08BCAC9D6E5B9ADF80B3C1CA1215756F11ECC -7D2DA3D97ED094920C38CC4A68D7BFB6F75E8431A3840D5845CA8752F14AAF8D -F5A80ACF8E703D88EDCBE251C10238BBAAA923DC490049E76DACCD2FD320C349 -7FF97E3E2A9EC49C5EBA951F0EEA06D48727CCEC45DFE86D667725454B700F97 -06B1A6521B25A0B5034BB64EFD4C7AD11E83F24BF7ED607789A1AE805881E4FA -A5A8610DB42BC7341F81D63CE70A7E37715449BD850A4CA83A0C0EB1A33A29D3 -82630F9F62CAA98AF0AEAE3E0F450B925E24A82907A642366EF798CC064FF67A -D3BC3D3CF3BD23641A91F2DB09680BBED2586A8869FC8015134901F7F4684B70 -73E4D6A466F013F76619BE61A4B9F66BF167EA7FF7DCCFDBDDE96DE78EBBC0C4 -A4DAC9DE8D709078F4C134FC1BBF53315977ED4C9C41CC4A02026E4C3443653F -39B23880391A2320170337F211CD83794118E5A014922CFBD8482D88F5622059 -3DE77CCE12C636241FAE4F5B91EFEBEFF1EA36C91465BB15A49EE3202451B862 -BECD7D819A56F7D7E46F981BD96FF1FC2587943D90F4B0F7B4C6ED4B76D6050B -01C551C265BCFADE1E2D72A0FD4C8AE9559C7F2723769B1E3254E33B7725321A -1E57D149D9A3091EC5714180DD68B89D7BE2AEFEADCA9585069CEF9D5FBC51F6 -B526E00E168E72F5CC9A70349DE30D46C50D30536821A4D988488C72AA9A8E87 -52DF5FD0ACDBC377A37AB3140D89EE5803A70886696176D2CB7D226443866046 -174AF7D525A28D851AE35BC42A2FC7EE4777EFD0E1650F7BCBEF9DF1AB64870B -CA1E15C7D67B3FC527B86723054D6C1EF1A869A9FCD5244D0BCE4182BAFF60BA -C7DC0ABB04C31C92741C14627D5ABE692403C6624B6CA64544E905B11C6D8FD7 -1F28055E4BAA5CB25996FE88F502742F42E11D087F61117F9730652F493329A2 -453D9508DE874DD92BE4185F6A7BF99E562EB614DF01385B86F6F271F355FF1E -ED5A84D534446E834B5435D483DC20A729E81CEB96EDAEE53D2E431BD905046D -712133BB30F33DAF2FC62BDB3A171BAC8E33297C08360CF255050DDAD58DC96D -280AEE9F9B66D2D8806E2CD32F8A08434FE91B7451AC5948A1DAAFD2D28CCA24 -8184E20D0F00EA9F2C663E7C4ECA2F9AF6EEA56F282AF32DBD960D40D4CF055F -F33D5C25602C2D6040BDAFBED1926120464F183124F48D34BB54A06A6724DCBD -DB2CD715999302DA068272B4E5742DD8D017E604C4114B1DB529A841F633160F -CFE80EA9B3B52B940AC0F685DA509ECA4B420A996E8488933EAA721B562450B6 -554302451C9AD6A56A84B85EAC18F03535099C8363599D4397454E19C0AB2A34 -9EE7A3C94165E396B9EFB97067315FC4762F2BB4EFD7FC635FFF0593528D9079 -69A5556D34927059A46525E6445A881CFF4B5B790ECF680068973A47EB6849A0 -52B9F18FB039050940EA4F9B51A3B9A099F33147569AE9254322ED47A6C7612C -46EA207F0A0FCB785E1DAEB571BB99C97D296CA1DE3838CAAD06A98FF8146056 -ED014E14180D505B17AFAE35F58696C16D8C46F13290F1600075A363489C9D63 -6CB4DB7FDCCF49E15B6825CBC4E04A2D6BA136289D198E2C851D794A9A3E8E45 -7790862DDC9EC0D12DF50176A194F39C7C13C88150D2DD1208F386BBA3B0FC1A -77F94819F12D78D5C59139A1DE0F2DFB3A7FFEC4FC38067455003968A57F73B3 -6C15268401F75B5C843D46EC956AA677A8DB075B61E547DEC35A63124769324D -BD64C1B1D38777BE93F60BF4D92C85CB8C9ED2C8A77EEE0A4EBFF3A44F237305 -EC57E50E3120CFB0DF8D573A96A740E1260A26C3174AD869CF2EEB226ECD812C -480D45502C3A4BE2B4EF9A8EAC7DB836F0C843971067F690B653D9C722655066 -D113AAFB04FBDC5BCEE0FF67A38C1808943882E4CE60A6969939BEFE16C09B59 -CE50B529C3BE6377368C3E827E9441D96BB174BAAC8B518671E3A9B95D4F1722 -A26F4FFF48348CEDACCC4FD98F71147D0B760B320705C1C13C9815E2CE82C5F9 -D6CF04C81F1BCB9F12A188F9828498C220C6DF1738CA9F236B6D6A01D747BB6D -F322F38D0D60A2E07E0BF1E259214C3F3EF0A72074C261ED09B05DB3915D0835 -B2BB52B6ECCB04E712B6BFE1A0DA7437DDD8C4C05CA45B1D5CA17EA99BCE6428 -7E635AAB8F2BA639F28C52CD0800BC348990D0E3832B0303A272D6C99D8A6044 -C5093A422D646898EF85ADB647544B2CE33DB5DC66717506CC90ACB01CF58830 -D50F4CF7BACAFA2311819C3F50A9F91249C624EEE17EF5752C6AF77D6B852703 -81F95A42593045A69334D6DC1280384CDFA0D8088D97332FDB06A02E5DE9F962 -1B41C68A0139BC5F03FF841D8E93FAD2DC08E645F476034919C218693989244F -DBAFFDB4FC0436DA9D43C8A2D55CF8DDB0E7ACDF9D564BCBE38073E74D65C8AB -0E89D87275D680F0FBC2389D1AABA196474E26BB4BA01527A72E554C29EDD3FE -7B17BEF3AB22F2C7C0EFA69C708C36CDDA24C38A845EBA9E9A3E6052B54C188D -2743EF1487B6DF0E6E622A697BBE91D5627DB3F32A57C0AC98368FE53BD09844 -A326B096D01FA3547FAF440D44E079EC0EFC2A482B05052B2D57DA79B8B811E6 -DD9D0E46E838F1402F32EC5FB127DF771049F7B79BCF62C14E3FB4D6D7BBDB80 -975272E6DEE0109857F51D57E304B74DE4AE99ECFCD0A40E57C5E51283D8F270 -291665EE714A6596DBBB5285FDDC4B6328BA6745998EAEF40EE717C63AEF8A59 -E87D8E3AC8161B6638FB5D0963F8795587949FFD6F58C5FD18741BA3483B7FD3 -FC31F188B096FEC566BA23ABC2B34B79DC293909C9E8393AC9A26E6538672756 -3FE2EEF3E04ABA6D344F2DF359AE718C7D0EB5CDA5AB3D09C62C990BD5BD7E73 -3F1F8AF93ED0FF3222D7411CB9AD3C3AE9EDA04DD1AFD21A4653AE6A890E6C07 -1607F1668E4B62730DA65DF88C3C63FD7816C32F26D21A87522C2097BB925D92 -CBB694A7F77E91F3FAB14D0A493384DF902DE5D5F4FEAB5F5BDF567878AC8B4F -98FBFE8FD16D07A58E2211B87983D40D5CE6349A207FF195B7F09B914CB6D688 -B103A5206380A90713D3C872EF8C026D2E302BEA473BAB705DE58D802A47C249 -9C40EE6F20398E591A3878D4A9DE9F6EC097521DDB694503AA8FE3BBCF24A5FB -3DD6CCF1247B5D9724508C63A3E107DE56F0802CB083399BFC3A9DA62E7575E2 -58AA589E85ABFF222717335997260A7F56965DE4DE551885BA8A1DAA5C97AC34 -ECDB36FEBE3D8428A4681871FEF7CBF2B5DCFE747550D296B419140C39EB3AD9 -D65B6146705DC3FEF0131533283A100D9DBCAEDB8A10CAE4C431136FD94089D7 -64402322603B7049D4D10F97FD54D03D81B7B134293004BFB852D50DE5C6C5A8 -29F3FC4855C34AE134EF939755B88270B114106573415FB185E395F6FB0A4698 -B105964A9F374AF011972D67BBE0B3CDBBD0D9918A0E0D2653726C630FC8A63D -7C5BE82A965EDC1E0A57652688375FA60463EDEF222D4A6D726B768D8EA06584 -BE7D23F6FE42CF8541F4BCAE1B01C73D6500207B211720DF98B72D016CC513FF -9109B59C4DBE5108CAE19687C1682A36F39AA8AD09C5AB7D69A13EB0BF2F50A4 -0766AC191B105EE28BF0A87862C377E47EDAA69F99B7793F5F76114940848E50 -CE05005B4E2C91103DB7BA7BCE79755E4324C0D0305EE203294CC82451EF3780 -106156CC6C6BD07296CA7B927B869F8A9755CF9173F22D30EBD3217A98616E3C -8525AC8ACDB07F9311558AB53805673411836886A919BBB916416DC1C2061CF7 -448ADED96B2933FD25C207BD374AB495DF564F25554274A3D2129CF7E6562F56 -E3D7234B8660A536DF464418BD08E3DB7CC2A2A8B80A0CEA897505ED6367A460 -3B6C0CE70E7C5F482C6B3FCFDD8C8266E023C421481CDBD041469219AFAFF611 -97F1A2D6B13A90A76AF1FB2520D973DB1CA53BBB11A81115605A9ECEB0AA60CB -972E5FC2C431F1A5EB305D09C8B4C6D5CE1E397CE7FE9DA819F132192B2B91D1 -2832F636D75DFC3A82143BDEE17461D536B13D21CDDC295EB617AFD850D59356 -7172AD007B843AA74DB797099AB440C40BE561612B4506A8E26D1C4C5A8DD4D6 -2B8DA07722FA903A6ADD179E0214071F1AA8A21022283E7380AF0B2656DAF629 -50E8EB7C686EDCBAB6E56C5198041DEB47AE8BCDB4C30D318D2CF076491894E9 -C9BBA0C6D9DC4B5962350AEF5B9DC1EFFB0C9B8F562660D677F376B2279089D0 -294FD57B5ED589C1D28C6E9F02C821134A221334E1B4AFCD618FD86BAEBB31CC -28FF741E785DA99568AC909B091BDDEA56D6E3B75F4307E3A989C1BE6C92546C -F518EE6BFA37355BF3A752C26A014FFD48B98F7C1B11B625A43E677DD04B16B5 -B1B5F666AA67EBD602583D810578ADF8FBCE669C3913DDFECB2F64745EFDF7DA -13E21B44417230EA477D2E13452EE0E048FFBC3B3F3E32687948361AE63B2F3A -C2393837699C356E580C995217D2BCADFDCCE3A6276B86DDA6DF06884B153369 -327D3461E0493B6CDAC5102E62040437522DBA5DB6B6A4B30BE8AF1E9AD4DA47 -AA79B1AC528F44184C40B9FC2E402F602FA679EFBF9F374BEE06E6332B112399 -D18B8822C21B3B1DA3A84B31023D39508C1F0C97CFB05298E67DDF6EE891E261 -67C5A17051C6DAEC3924E7E9FC00C98225CCDF01D885724122CBFD1354A59CC2 -35EF7E987F633164341E2074B26689C6797F81618EC137BA7AE502904A211920 -D7FA213A6F0BE82D49F7237690413AD381F5D2A3BB67D027C48455F48E717DCB -E1D0ED373D62E180BF0AE16B91605EBB768E97242CA8DB982AC0C2DCFD4B5EE8 -95BDC8910A12F20439946D3CA70A5F67A62B82BEC253FF1C68B1DB9BE887923C -1B4F803DEDBC42CB12082ED81E92F657D30E8652E76C6D93B1C7196BB77C0DBD -C2DCB9E8734272157E4BD32B57FAD22278DF0B98DA7ACCE25626F453E8A7387E -F75FB71ABECBCE09E6D35C7CDCD550EC6907A8832D6831B8F16C6FF757E3733A -3D028A0456B64C686A35EFFED2BEC9A9A1D93E98745DD6036FD954AAC48ECCC5 -470FE468CC4AEEEC6D6E650378E5561990EF37879B517DA5D550B5DABF216D27 -26941BDBE7286F95F3DB4673BEA513C8AE8FAABD78ACF6AB6918308627EE223A -BFCD0B05C18134AB378AA07512D71E7AF987C925AD05686B6891EA8573FD13E2 -790918687BD4DA3C12A9E0F33FCB6AA2BE3E3397B970E80338E5338F0F603B86 -A42FA5A6285CDEF0739EBEB1B9133E86BAEE66E1AC48F83BECD4FA2CA3F1D5EE -8EA02DA4925191191A953FE68C13398E2D80796714C07FE16CAE171AC6BB0870 -0AA402B06C310DC99F0A07669C57B5292530FB8DF265DB909A86B8D076468B4A -B24AA398EE42F29BB41E7A640883F9D6021F4CC7E949670DACA3233FFCBD64F6 -AAE2DFBB7B1E69F24A6C0A8D86081B2B09270D561B20EAD4D6B1D40B7F333A0A -F1B2E915DA6709BA159E81455907510390AE7C870A4F38BC8DD19149558B9687 -37B0777DC5D7964E3B50F4CEF6EF43F38BE9F01A68B60FBAC4BEE09E197C2554 -C413B003ED8D8A095BEDCB291ACC0FB3AEC024D779BA9D69FD3D0F5D105F95E0 -EA00C1483DC52F2A37BDD09F1F416BF99C1299784AA46D36515387FBD61C1C27 -A2B6E55C6B086E87B32921BD7441F10E49DD10D7D82E81AED5FE4C5AC09F617B -9BEED75211D3FED854D9414ADC9B6AA0529863DD90FD48A3F82DF1F7C634D83A -261AB18F257A389AE958DC7315251E670296B0F415AB99D1FFB56AC1E7E61BBE -0DD2A5C6DCB7E270957BAC7584BFA9A6E21CFB293F0F51C58199D2EB431037D2 -C44DB61F55B46B3F034CE7127628B7A3549AA2CA1FF18DD7AECFC4EE7B3AEC3D -D0A1EBF2F7E045BCF177FFEC6A32B8BD47EDF924EDE5FAE04FFAE9904F4229AA -DF5B82485C624F0B7319B147CAB299A6FC7EE302DB985DACE5B13F8FA8E73504 -96E522B8D32869418AFE99B2EE70F52CCFE638419454432B9688E631272806CA -FDC72B2F2971931F3D32AEE7B8979EF969E122CFB6D7AE0C314C3CF64859DADA -99AF547DF83E7B74AC852752D25B6EE4A29B6CBA28CB35FDCE44C0CF816E1420 -9456518D9DC7A31DDA813F7ECE178F6C80A53010BF2272F50E93F5EC18E91D6A -BA5DD888E1E9FBAB51276F78875DC0E6EBF759FD1C92A7D9E86D57B9632E5D3B -823FCB477610DEBF376FF0DAAF01A47E0CCBC52F0052C93C35EDAC9BD26C0CC6 -5D62756F5476CD1BD7581567F55A6F04352AFB226DC7087F9D5B254E454126DA -1C12C7ECD608698A0B2E3595CAF63B8BB3C1DC9AC379FDB7F99F255C8AC29A46 -AA322BD508021592969A16DCBA6959C5B92D0510AC400844405C810D6E34D41F -DC8867E6A9 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMR9 -%!PS-AdobeFont-1.1: CMR9 1.0 -%%CreationDate: 1991 Aug 20 16:39:59 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMR9) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMR9 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 44 /comma put -dup 65 /A put -dup 67 /C put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 72 /H put -dup 78 /N put -dup 82 /R put -dup 83 /S put -dup 97 /a put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 103 /g put -dup 104 /h put -dup 105 /i put -dup 108 /l put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 114 /r put -dup 116 /t put -readonly def -/FontBBox{-39 -250 1036 750}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5CF7158F1163BC1F3352E22A1452E73FECA8A4 -87100FB1FFC4C8AF409B2067537220E605DA0852CA49839E1386AF9D7A1A455F -D1F017CE45884D76EF2CB9BC5821FD25365DDEA6E45F332B5F68A44AD8A530F0 -92A36FADB679CF58BAFDD3E51DFDD314B91A605515D729EE20C42505FD4E0835 -3C9D365B14C003BC6DD352F0228A8C161F172D2551CD1C67CD0B1B21DED53203 -046FAFF9B1129167921DD82C5964F9DDDFE0D2686875BD075FC81831A941F20E -C5CD90040A092E559F6D1D3B0E9BB71733595AE0EA6093F986377A96060BF12A -A1B525CD9FA741FE051DD54A32BECD55A868DD63119A4370F8322CCBEC889BC2 -A723CB4015FC4AA90AE873EA14DE13382CA9CF0D8DFB65F0ABEDFD9A64BB3F4D -731E2E1C9A1789228FF44116230A70C339C9819676022AB31B5C9C589AE9094B -09882051AD4637C1710D93E8DD117B4E7B478493B91EA6306FDB3FA6D738AAB1 -49FBB21A00AC2A999C21445DE3177F21D8B6AAB33869C882613EA6B5EC56476B -5634181ECBF03BFEDB57F079EACE3B334F6F384BDF9D70AEBD592C8ECF21378B -54A8B5DBF7CB9282E16AA517E14843909339B5E7C55B038BF3BB493F3B884A1C -C25F9E8FB912CBE23199AD9D2C3E573727701BA301526C66C3617B9514D6F11F -11930B1D97C17816C85B1BFD9B973A191B33CC3B391815AC46268691C741B2D4 -48A840F1128D9B2F9CF07D0709FE796B23A836417BF7B5B12D67F74453C82F5F -25F7B30701D6F6D4F4DC623C0C27D6A6FBECC7312A3CD10932FC7C10851C3C52 -24B75DEA8A648B7F34F5711DB0E843C914E25663C510185BC37BDB7593C1C259 -21D8DDAD33982C336BF272BAB2F48E68217403FE9F54877B243614A87E64784D -2796EE4179FBF96123D1BEE3EF89D682B427BA4F12A1318A57F18BE5DD903815 -2613667F0F25922C8476E353296B5FC2300FB8AE7CE38FF3CE3217A905E88E03 -E2B4A68A22673EF30CEB2393FDF6387D8AF7EE943A23A81393BEB6D7033E6D90 -A1D645FD1BC4965E6441C6336D5389E0C8EB790F1C97033C7470D8809199A090 -63C898472D46F75F3990E561489CACE837690C938A7879B21FBF83AC6E268CFB -03AFBAD3FC5281BC608A9D7B613DBBE356BC7532175E2F8598E647D7F4947DCF -1D9EB823F13E4AFEB0BF3258692EBB2D2F11DF1396852DAD24650A51F63FBA4B -0F74B5294F62BFDDBB56BCD47A4428CD4F2EE44190651208DCB3C6E437971971 -8979A4EC9F636B164FE1389FDC539ED9283B76E84266BF0E3EFB8A3C54F52174 -E5BE4FF05E7190E4B3655DFAD9FC974681FB61502D974A70BA8949CE6B6D1659 -DD840F16AB744D39C53B0753C4EAAB13EE3818898A0DE422FC8A6924CCDE45D7 -161678E8F9F7C8BAC0246476A83B413ABDDC8033B5D1BD7C35E8701F0DC63CD1 -BDEEE0FEE322C2CB2DDF84D10F97A24FC79E8EFCC492807B07B0E9A887B976E6 -820010C4293F27C8B075DC9D1AE3CEDA7BC8B9EC9BB7C4388FD3A78D48FB8556 -E49D309C8A1DDD38A1A149E6D39F7F4CC7EC293329B22F88598229196F1587F4 -12D9BD35E5FEBC0D2A5813944E6651B7C4E5150C4D7C8AEEE4410F818B70D8C6 -CBEFCDDB9B8F47B81B0C15A3054923057AC6D244EF133BBBFAD4EF41D6F41596 -28195A27563D3AB6A62FEEE584F9AF0CD0253B7D7BB5E599081EA6657101E980 -A558B9531CDC5DADA0D47F1CBB6DE4AC107A5D3AC24D69D0EC9609CC1762A583 -121D6D0A48167E60C447D47AF8693A0E7B2796B839500CCE022FCEC5D2C1CA0D -8E8286CD2F31A756E0F3AA641C38ADF5E4926B3C41DB21B320F2EA5BE5D16E71 -491B6CD80858B1F44A780DD7F6B77060FCC070FE625A196BD6DDCA6E40015DBD -378FCE94246918B68EDADA6F54B169F0535EF084923DB99FFDCDB9CBA30EFA21 -EAE1F01B9AB170E6A1D92859BB2AA023E78D50601D9F33944D50104394EA45E9 -EABD98646890231B2B7A5563A099212D51391746B21DE612301614B18E4493E6 -BC78BB2D62EDED4D1384D85E7DF873E3A3F8C16FEB39B0EDCDB2CEBEC619E718 -DA6EDE026FDCBBEBE75D47EFE7361C91C0B28118EBABE2C2B6078F4F82D925CB -4FE56054E9039C69AE61A0F1E5355E8B590405D36E3D2A2A2A51EF95777D433A -1EA1AFBBB14E0C68E8B751E7BBD06731573197AD614CC21DE871692FBA52BA34 -D50E59B29207BCFA4556641ED3E868CB706C373073DA93FF91B2E6242D8A5E80 -0F4DC93D6E7E6286D8E66D9126157EB7718B5C57496F3184192A0C61988D0946 -2D4335FB6673F2EC4190CEC8C0E501517D1BC92693A73B02A6F6CE64BF7AB782 -CFAB7E0BCA8DA23B10DC337CA184CF59C391A3F6399518C76AA0D9199A8614BB -5F0045C05233CC68A0B3DBA0F9D7F9DB81586954D5724B79F765F6BB51A4D330 -53B753D84A14E2E4AC83262019E3018AB2EFAE580ED2F6093C0A1787756B33C8 -9190925D0CF343543AB8011463206786871B4DFA4BB0CBC408C98DF27C4B70FF -C04DA33A6E06259B0226B2DD479D2AD9A9AD51961AB9D861309E73662E78CF01 -0979D545153EBC51FF9812BA01F652508505F4A82132331F3E3C74E00E52942C -D8FCD78212A74A37247DF714338962F6585B8DB09E1BD63FDC2FC1C5FDFAE77F -D12489A28366289F912890BFE5CDADAC498E10F9BCE6D05E1AC790171A484868 -1CF5BD642B29E4355E18E3D48D6D5A9D63DC763D50E03C38C98BB908C05BD1C4 -5D495B84C6AC10081C83B50B2B5BAAC285210D7D3D79C2151157B8A69839C5E1 -691ABE5790C282037A98CA60D2C5E7627640607C35C285E39F3F4AE64533D4BF -65CCB9A11A79260B87F567C7AE128AC2C63C6A1F10C56E82AC562ED2C3A13B6B -D7A5A06481890A93B8B2912E5AD052779D909EC758443A79C92535518B61D9AD -0ED1451E969C8E19BD78D3E51AD4B8C72EFD7FEFE8FD3ADE5157AF86CA3DA2D6 -1E2B8D5154BF6BFBD8B45A52A095EF38480354F644A41F863119F882C07E48CD -2B64EF986CBBC000706F5B2ADC79D2411E1776F3067DD0CDB73F2B097A09D413 -3C2659698D66F86082708B23D87DC0274DCB16EAB89170AEF3C6189DEA0ABC28 -3691DA6C145EA5D191073041FA338AF636C4B817E5709D4B367F66A5CA9DCB1A -291F4231B3BECA853D6622E3500FD1842C8999D6412BB35985712C173B1D0684 -EE50F6D36DAE6839A625EB242818A7F7D7E88CF3D20D000CC3789912E3FBF566 -88F200B29B9422011CBF2EA1EACACADF2E0A44BF84DC296F6D4A7420F44A10AF -FE9323E87BC10CC10752266E5EBB9F8DFB805930B77CA360B513A02E6F8D6826 -C38F625C95606B5EA05B475DE83149DF464CA3D83C7095427784F6C10B353FD6 -5885CA83C893FA30A28D45C69BBBB3F0498CA3B585DF4FCC18D5F55754553D7B -B2CA38472D4A2BDB58C811C840FA82BF1A585AE685E848D222B3437D874E0A4C -6BC67DE7EC0F3E34A5A204AC7C4AA41A99503DF5CDD4E8B442212DD94A650A8D -706A0DA0379804FBB248FBC03FBEDD55705654C1962DC7124B4BABE0060EE47E -66F7FE127A645D9D05A88EF0FB573E4F86313C25B78081F2892012E3D429C7C2 -322A20B4C11E6F4F54A8888F32C9ACF5A29F996C30BF35A10E15E4DE7E36D64F -530C3B766C110BD64AB6EDA4E7F3AEDB1E2DAA8EC41DA74E57C28284B98833F9 -C0FEA33453C4A6BD3E62F488C46141BC8EECB66E291BE50F5017E822AFBB333A -30FD1B0F9F9E66CAC5F58A9B7BD6A4EFA43E74CA4CCEF7920F1128E51ECCCBF2 -BB44236C4E4C047C87330822DACAE4F8FEB14C8CC0EF0D7F525CD1A08D07192A -AFE999A4B565231B500D0BFC33114E0F6446F7E651D61489BB72EF88FEB7A436 -3E04E8B69BEC231DFB97CD6EEBBE7D5E47F39E2121104BD3D6FA169AC8E86DEF -A8AFF077E12F7CE025AB3C309D7F81D3196B4D14F3C7F8E2AF906C94CEC37D11 -6B4D466A02B4BE6B0B7C9B4BA7A0399950E4D101CAC2C205385DC432ACCC8B76 -59C0F9C82DB43C9A9B847997540698FB74107DFF24D1415C7EC8CD9A852AE85B -6EE981A4AECCC1C5123B486770FE6290CF1B3FC5F9B01526F9E9DB2C92C49259 -3B9FF825A3C241EC51C85A2273E683B8B8E3ACDAC09D15C2BC69AE4DAC0ABD14 -96BA077EAB7DFBE745718B859C711FAE6E3F47FD31E61E31BB7FFD0F467F14D6 -6CE8AD12181EAF72449F8E57B2C102C8140F15B7B192DC31A12874BCE4A7AB86 -0C4FBCA801F871CD67C92900C720582A59310A3E1A448404CBD62C0C1041A151 -9E308E98F470051A07D0832139A4785D5CB07616D16E207E6838EC4A21F85327 -F9432A7228EE66B1E989C7DB3B6F9B33AD1F5F0B4393EF820A2AF2517661F287 -2BE4466C15E205E5557A0B70736E55F524B8645372AB001F540A3A0AB00CF7DE -1640B3C0CA275E6C75EFCF7A1AD7AEBE7F5CE88DEA735D8313281BF3B6BB0AEC -63F291F499321E58E390E11F7565081506DD5DE9FA7978A76221618185FE1E04 -39D9DAC487CFB00EB6DD6E689FDB53C0219FE237F6EEA9C1F042843D3123C144 -95CAF35CA462B0D8488D04B656EE64AECCD89AC054801E2463EF52FEE08B730B -58BF9F8600A8E0459D4284D99C009B05733A0302B67234E93735D5D02F1C88B6 -65F48C5A80F4D566A4308ADD39C52D53EB6F016483AFA997A4EFF397F64732E6 -1702B6D91C73D4FD49D438B9D7B3B770ED5DF0C3ED2891E29B26F5E5AA54B8A4 -095CC7A7258E64D14CE7631591FC8C4657532E4431774890ED7C21B5232F4F7D -E476260C734FFC1161D8EDB81766B7A85F4982B0007148BA232A5497AF5ECFBF -0C5C52ABAE562097A6170446FFA7DA4C816513A46CD44C1BC551A9153207D132 -F77F4EC4FB69723148F9391026B8D694C922947368F5C3EAA437C75722971F1F -F250848701DEA51D0E0BCC2003B2968586B2F5186B22B071A3323C92688E7314 -6330B2EFC89CD6EE8DA5187C5B9E87C9DCAA7B295D80EFC26BA1CFA8CD89BD45 -812C87F043E9CBF8BF047E1D800595C1ECADF24103FEAE5FCE32A9945C2297F5 -A431B252800EB9CC44896BF15CF7754A54844DE09701EB22011DE9091C10B55D -9E6737C59654F68369A577C6C3D200DDEBA8BD4FF09915A5A015745809B20E45 -04B6B0CE900472B2540CB1D18E60FF8ABA079A81D532395FFDA2FB03AE01999D -FF7F199EDEAE47BA5BE4668E1D9B994C565890D4CE2FD7E9646CD3626AAB94CF -CB1355CC2D54482F6C5B5745007AEF876C836E7B18D9B5C58448ED7F7ABF1BF2 -8EDECB1A18D7DF20ECB502E15B5D471CAEA64EB2182F00F5B5B7BB72E358DA99 -CDFF5BD7E274496774EF1155A6F09FDFA539E26BEDA3913D3B6405C9321C9D1B -E5A0CE080F57BFE2CF3C80BCF2FF7A7C4924F96B627CFD45E5889996EDFD4E3A -9351034F1277B2D54C0D37783C9B8B07D2976ECE08DAD78FF7DE849DC077BE48 -BA4FF934C2749765D4E27D679F94539611F98FE1CA92C52246AD2778652A6BA5 -DEE57AAF3854424A78A23B36DB9E6F3364918BE5EE6CEEA1D6D40F8F00A9C116 -3E6FDC117CF5B47B5BE09290686EE57D5A9C989F42C0946147B52C10B6996920 -6AACAACC50E256B641D12ABF9F6F8546BBE525D57DD449F819A9A678746213FE -AD49897C02A4DADE4721B1E1B11EEE9320240B05E9A74B02577DE56780EBAE18 -4D810C4142026B75E4545DEF0FFB267DC1F44CE328749B121FA989760108BEF0 -C21CB7CD0860B5E215133F66F88E0CB19109D36F47115298ABE66672708CB761 -CD0C45CE5A12C237758F3D435F7D310DBF952F149090E9FD8A902AB674CE6A7D -08290FCF67CFA594F322360305C16A060D263D2F0CB6FA9E52CDD10A54F185FF -A9AF4F97F64869515EE1DF31C64031DEE3627F46FF45ACB91F0BF272D7DF4D19 -693BD2BD45F5308D5C9F71D78BDA39F7D2D0468E9E0548E16A2552C715F1DA8E -849AF2604E4CEF5021D4EA480E255087CE350A139F995BD23FC035EDA3DCC5EB -11FAE15DAD4CE711E12507A630445632FEC5BD2C35CA0F6894A168366207846D -570ADC67DB3BF684C15FFC064E9309F2D2CD794716995E7CB9F804F1955903E6 -77D461A24BDEF84D03B167AAF05B8F86DB050D9EC43FB79C7A97AC86E32E0E82 -FDC7B0EA5B8E13F09969DB412CB8CD5BC9C61205661EC3565139315DC3E67004 -A4AD81E1140EAF34A51DAA72051247A64CD8A321283B05985AACAC914517CE14 -AD6324E598C38FF0ECFE3B8DB05D9F6EB6B3C0471C34AC1CF8D9A6380B9D23E4 -5A372AD76BEAE61C808DA495B7312F322BAE0C52A312485E4569DF0B8C0D365B -2E9C813851C10F0AAB4ADFF3A6A2B2 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMSY6 -%!PS-AdobeFont-1.1: CMSY6 1.0 -%%CreationDate: 1991 Aug 15 07:21:34 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMSY6) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle -14.035 def -/isFixedPitch false def -end readonly def -/FontName /CMSY6 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 3 /asteriskmath put -readonly def -/FontBBox{-4 -948 1329 786}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 -7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 -A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 -E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A -221A37D9A807DD01161779DDE7D5FC1B2109839E5B52DFB7605D7BA557CC35D6 -49F6EB651B83771034BA0C39DB8D426A24543EF4529E2D939125B5157482688E -9045C2242F4AFA4C489D975C029177CD6497EACD181FF151A45F521A4C4043C2 -1F3E76EF5B3291A941583E27DFC68B9211105827590393ABFB8AA4D1623D1761 -6AC0DF1D3154B0277BE821712BE7B33385E7A4105E8F3370F981B8FE9E3CF3E0 -007B8C9F2D934F24D591C330487DDF179CECEC5258C47E4B32538F948AB00673 -F9D549C971B0822056B339600FC1E3A5E51844CC8A75B857F15E7276260ED115 -C5FD550F53CE5583743B50B0F9B7C4F836DEF7499F439A6EBE9BF559D2EE0571 -CE54AEC463244B0F8EAB9E96CB18BD39259CC1FEC10F47FB56A38588CE634209 -8F77258607212EE1DCA4F0667B152875B2CF5AC44B930B888ACD9D4B55662542 -71239286D82E14CAABE7276AB199E2429C4C3BC32713106A10F5F16C8045A580 -86EE21E7783B70FAE03D8D47B5AA13A881D478232DD65DBCD1EB9811C440E362 -527EF73FC86FE664ACED80DCD6806CFD932BDEE102B89C22F423992249FC2273 -F39C59AEF75B2088527AA973C71A6B134D26EF1ABAB75721971A0E4E52639DA9 -2E1C3B2A6FB552CA834F6443E0628DD9CE69E92DA0B9B8ACAF3641FA0A7F1126 -8DF8803E683ACCCCDE88C9F6C1838BCE7E8B56A0BC8C5F0300D81479A5087FFD -B8B66527B87F7977C31A54E0506C6D33EBC902841AB7B8D75BC8ADE5397905EF -BCB96AE4B57D308DCF0F74A93177F2DDF3486642A43834DB5B123CFA402E4BA1 -6EB4C27AF21C96932E05B79CF951354FF66668C6503CA6FD2089A91A8D -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMR10 -%!PS-AdobeFont-1.1: CMR10 1.00B -%%CreationDate: 1992 Feb 19 19:54:52 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.00B) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMR10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMR10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 11 /ff put -dup 12 /fi put -dup 13 /fl put -dup 14 /ffi put -dup 33 /exclam put -dup 34 /quotedblright put -dup 35 /numbersign put -dup 36 /dollar put -dup 38 /ampersand put -dup 39 /quoteright put -dup 40 /parenleft put -dup 41 /parenright put -dup 42 /asterisk put -dup 43 /plus put -dup 44 /comma put -dup 45 /hyphen put -dup 46 /period put -dup 47 /slash put -dup 48 /zero put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 55 /seven put -dup 56 /eight put -dup 57 /nine put -dup 58 /colon put -dup 59 /semicolon put -dup 61 /equal put -dup 63 /question put -dup 64 /at put -dup 65 /A put -dup 66 /B put -dup 67 /C put -dup 68 /D put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 72 /H put -dup 73 /I put -dup 74 /J put -dup 75 /K put -dup 76 /L put -dup 77 /M put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 86 /V put -dup 87 /W put -dup 88 /X put -dup 89 /Y put -dup 90 /Z put -dup 91 /bracketleft put -dup 92 /quotedblleft put -dup 93 /bracketright put -dup 96 /quoteleft put -dup 97 /a put -dup 98 /b put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 102 /f put -dup 103 /g put -dup 104 /h put -dup 105 /i put -dup 106 /j put -dup 107 /k put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 113 /q put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -dup 118 /v put -dup 119 /w put -dup 120 /x put -dup 121 /y put -dup 122 /z put -dup 123 /endash put -readonly def -/FontBBox{-251 -250 1009 969}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5CF7158F1163BC1F3352E22A1452E73FECA8A4 -87100FB1FFC4C8AF409B2067537220E605DA0852CA49839E1386AF9D7A1A455F -D1F017CE45884D76EF2CB9BC5821FD25365DDEA6E45F332B5F68A44AD8A530F0 -92A36FAC8D27F9087AFEEA2096F839A2BC4B937F24E080EF7C0F9374A18D565C -295A05210DB96A23175AC59A9BD0147A310EF49C551A417E0A22703F94FF7B75 -409A5D417DA6730A69E310FA6A4229FC7E4F620B0FC4C63C50E99E179EB51E4C -4BC45217722F1E8E40F1E1428E792EAFE05C5A50D38C52114DFCD24D54027CBF -2512DD116F0463DE4052A7AD53B641A27E81E481947884CE35661B49153FA19E -0A2A860C7B61558671303DE6AE06A80E4E450E17067676E6BBB42A9A24ACBC3E -B0CA7B7A3BFEA84FED39CCFB6D545BB2BCC49E5E16976407AB9D94556CD4F008 -24EF579B6800B6DC3AAF840B3FC6822872368E3B4274DD06CA36AF8F6346C11B -43C772CC242F3B212C4BD7018D71A1A74C9A94ED0093A5FB6557F4E0751047AF -D72098ECA301B8AE68110F983796E581F106144951DF5B750432A230FDA3B575 -5A38B5E7972AABC12306A01A99FCF8189D71B8DBF49550BAEA9CF1B97CBFC7CC -96498ECC938B1A1710B670657DE923A659DB8757147B140A48067328E7E3F9C3 -7D1888B284904301450CE0BC15EEEA00E48CCD6388F3FC3BEFD8D9C400015B65 -0F2F536D035626B1FF0A69D732C7A1836D635C30C06BED4327737029E5BA5830 -B9E88A4024C3326AD2F34F47B54739B48825AD6699F7D117EA4C4AEC4440BF6D -AA0099DEFD326235965C63647921828BF269ECC87A2B1C8CAD6C78B6E561B007 -97BE2BC7CA32B4534075F6491BE959D1F635463E71679E527F4F456F774B2AF8 -FEF3D8C63B2F8B99FE0F73BA44B3CF15A613471EA3C7A1CD783D3EB41F4ACEE5 -20759B6A4C4466E2D80EF7C7866BAD06E5DF0434D2C607FC82C9EBD4D8902EE4 -0A7617C3AEACCB7CCE00319D0677AA6DB7E0250B51908F966977BD8C8D07FDBD -F4D058444E7D7D91788DEA997CBE0545902E67194B7BA3CD0BF454FCA60B9A20 -3E6BB526D2D5B5321EE18DD2A0B15E53BCB8E3E01067B30ED2DD2CB9B06D3122 -A737435305D42DE9C6B614926BFD44DF10D14402EBEDFF0B144B1C9BD22D7379 -5262FEEAFE31C8A721C2D46AA00C10681BA9970D09F1EA4FA77428025D4059BA -2988AC2E3D7246BAAAFB89745F0E38580546045527C8779A254DB08DCC6FB9B9 -0E172209FBE3857AF495A7F2B34BC893D942C145C2204CFCD6A5C69FEFC25B60 -E412CB2BEAE7F7FAD03AF46344F6A7D483BBB1E896BF16B0F4C363799DF23CE2 -E8127996DE841B6F9D8A9E56BD799B6A938582988AF87151BB8D3AEA85C49857 -DD862B5E10D9F33D57795D656FB616BC9B8397B3612131A2B0F472656700958F -739A548F7C3A348698AF9F6F9821D7A9FD4131781ACBF7EAB885A3AC254DBF94 -02FA697941A0F97F048861788BEACC20DE829764413CA58F9D045A6B38BCD6E6 -E4827247EDF1171F64E3B041A69B244308DC07F66643FCD7D5FD37F36EC4CB5F -957D4ADAF91850A3B1A765E0E580EDC77556593D1B2E1C22685268469298688A -45C474C9D0472D019CE1E83F25182D084AD85A49C502E8D679C227DA8E32045F -8055D1622C478F8FDA342685F858DE3F53F1CEA0D70BF54A4B35884FD75D8B36 -E54B9393BDC9E020D16B0C20E943CF4E22C0380840DC7628B70C3CE570EE2060 -34708F5531EA5E286384292A5BD0E04ABD1165CDDF8C0ED8899A82F64D2C2DD9 -90C50E0FD6180D25ED5EF2746914E41E859EDE14FE652EBC40BA85F56F625947 -805E6854520522135276AA0AB3956E65553012A51DBA92C0BE18D9A974109FCC -24F2F7EADBEADF14359BB85A0516BF482639761B7C4134B68E863A71DC8C76A8 -F7DA8AD952F9428B6B492FD55D800C3FF266774D9807C268FE482333BC9B70FB -C55DE4418DC3AB396B4150C4774E01A035DC2EF956FC2A0BD0BFCFDADDCFA8E8 -299D6610014F4A73D5641A82528DD45935EAF72CFBB6C95CE320FD5EBE8A9F7A -2BFF5C3A5EEDBAE186F86B95AC394FEA62EC3A756E5DA7AFF8145444A7D632BF -F8F6B211BD2D7E4A5A56B235C3912249F53683F9A12AC5E8AEE324000781157E -739C254AD437934D7B83ACDC2D5D7E6779EB15BECAA10B662A8B8A1CC0D6CA60 -FEC9AE92613561A80ECB2AEEA335B5BDE2EE3FFFDA3D144DE40B82F93664F07A -7265281680C3153A10DC16C13A3715BAAEE70345F509661D04FE872F66420B6A -FD94B36FB9565C4BEF9EDC71B0CFF58437FC06ECA3B15B875AC3690F0D2E596A -55C05FBA3B348B097C1453F27CD6AFD2CA38D3A6002A0ABC3655AC52EC9207D5 -6B74AF8B9931BEC0C18E2F1BFD273293AB3593D553A0194D694C4E7036D98DD4 -CF5A800D9E729515FF910E63CB3E1060D7F7562F79FE18D45CA52FCE85DA9039 -5C414211F00A20DEA60B26994B05D9F5DF57D97EF5086824B4A074C78BF7F845 -9C92908BA9F903BEB71D0F70249D69B1A75759225143C842566C031A2D15FF07 -2EAB20883AFF604886616903D8B95293F48C1A821C5F2096E88C7CC13EDFFEE6 -B0992152E4D6625C612511EE6254D9154E1B7EEB4C64CA40BC6C5BBB3584D7AB -06A2D217BC95F8514FF2FFF8F1D31069E6DD6C215ED4AEA0FBB275161353D2BB -9148067B9C1C0DAEF86F43E907E2BFDBA15788EB4851AFA5900FDBEAC07EF37C -F5117A1EDDD3F2C318B7AD11E4813F28E202202AB4B6041138EB93B973E2630F -9FB42C8AE50B8E22CD0A649BD154E965D6F0C378C721FDA4336DFF873BA9EFD9 -70D180CACD57A935D5A2053CB80CD378046DCA9C33326BBA1565665D666894DB -AC59A68F5A8779738BF5905482D37C304618365B90D8F2425101151993C08F26 -B3FBD83D88FE9F5B599CE1D81D10A8E7329409771993331C65FEB8F8C9318B2B -06734219028EC64B67DA6C9EE1EE60DA0E98B762E788D9A670CEC85B1B3111D7 -0491C6170259A4644A5B6B31F3C0DC0FFFED687B4D662BE20EDF460636729D16 -DCADF1E56B9C92CF29A1BACFB5BF3399A7D8D26C459FED717712065843163C55 -516DDEFDFE83E65794C4978393950E703FA69A86987DB4985C4358A52C1654F5 -0C8157DD644FB4933CEF46D76F7CD1FC00261C538DDB6650782C98EF66AE0C7B -5DD6CBFC9B1D928F789BAEDE464A3D24548FCE78E1E9C0623B265D8387D2AF84 -B95633228DF728614C79AC5C4E311759EAAF4963AE31009BB3543057FB921994 -C6E3398260E44A36093277A0926A2A896AD272745C95CADB395EB062B597BCDC -E9DEC016EB1BD5DDFA1BA1D1AE892E1FD36E2621716AB74976AD19C95343AC17 -7E3B43388419EE16356F1F27FAB39B8B61E0CD78EC781C0A4FFE5376B3DC2728 -66B51B26F2E598AE017DB1D3BFCAE34D526FF09DBBB0290C579AE1634EE91A1B -9080E9FC10CC70A925F9AFDC45CE2F14B682AEF58D40319B3FCA0C11D5FD51BF -14C2444E41A92312861C35A4046FF806F01819466244DA99A92C40268E4F0ECE -55981D227074FE1FA9970C21DDF336E901B67DB28CCD3B39F1A7B9F96FCF3379 -3336D67B9054C7A8B70F54EFE987915AE2EB57A91126FA770C600EF56B3921B5 -14A2754A01319C568882C984D2C383E60FFF9173C172761469BFD19808890843 -451E381498EF49EA8B16E5475C932E0311202224194D14DD30A243FEEF7345D4 -BF288C6E2B81F4E69224275F2422337BE9A1F794C9BD5A6518EAA88D8524F631 -99CD511EA841A35E2EEE8AA366C8A83E2C97CF4A7D71C4CF6BB5F0A60A27FD32 -38C860BBD86CEC4250BC156FB8C21B6DB40E627CD537602484E52259DA98E315 -605BB00E57E58EFD5C73FB9B2A6410CA3F0E04D3CADA88BD06EB548151DB4956 -081E3FBA9551DF06C51273CC8C54E3578C0A345309C2D45F7B6F6DECC9437169 -14CDFB887CFF01A102BE870E653961F95483184DF4F23BB6A5E248B18DB2647D -60B3651467CA2BF2A4A2D0AFF286E23A90439FC6CF8FD2C8753EDB90EFF684FA -41FA29F8B2E0B3A27AD75C2001F32FECD8A10973919F3D0C1BC0C9E5EC63D862 -5CA28C834B502D01B4CC0731E2043E759A23BEAAB499A032AF9E6804EDF54064 -843BCB48501F7EA6C7FA3560A125DA0D737AFD1B95B1DA2F3B750D3051A4F4A0 -E53997F0AD82FA4B6B9D74C89DABA8E58C6C00D0439CC48C948EB359A08819D0 -48C7D4CD5E25E9E12F6AB3B29FDB31DB521DD21405CA3DF6383F3E056B4FBEDF -E12CECB2E3F2107E834A7D97345B55069A9ADBA55A33501F16C426D6ECD3DC89 -CF6506A13DB053F87FBA8C4EE8ED91B41879B0422FC897DB3BDEA8CB43DA0358 -048997B7A29E967EECF2CC9B72D5F17C5233787DC1D8C622F758DD294D329533 -D429D8BC22D8FB3D70AF1A9B56CEA7A99C9425E769AE254B14F243808BA07166 -FD066C320202B682AD3E355E351E3A85F1F7CCB4206DED1E073D275A3AE42DF3 -282E4556F4D9699BF08243AEA49E49B46C4F6DD498BD95051B5ECACFD7F9E24F -C68D7F1129B32A9A8A6105B90D0A13525610780A306D3D08FEA04006EB0D25A0 -A0221A02FA7CCD653FFC8A4681E61E119DFBE38F586465DB76E4E448831B4909 -C159F6FAACD08EE361DBA21F0562D64FFEF7119343F756DDA0BFDF02D0D522CB -3AAB2050B1AE27D54AA650AA491476766FD9629FBBF8289D43C3EE1EEAF95274 -1F211E8BA70CE9E05625BDDA24D9E223D6C61EFEB1630DB948759EB7A4C47DBE -510253CF41BBDD251E3313428C15F8CFA4D91C1B3F3DC222B4A1F59FE1DB20B4 -00CFC1130449B672D9BEE105B668BBAD1ABC7DB1D178B3452398F3D5F744E610 -5CABB91FC124609C46223554694C982FBB3DF11E7EC223D49796ED707DB63D8D -0EB76516EF6337BBE1C0DF28165736D101433C1AEC5CC5E0506D10B526CA9895 -DA3212C6CA69C4E22F3C4EEA3A8BEF8784F4AE2834DD1B0CCEC94E9F558AFE07 -3C55181A3DD4B59D66E74077F08A936482664A9788573B4F52D1F83B4B9569BB -1F4CD6047483AD6CC99997D934C437C8F331513C2954368BEEB76F0B9813ED45 -6F99BBEE05502EE9CFF20194E5C80DDF2D54AE35400DC46B8EB305B2B1FAA969 -0D50193138997801200C9CB2C01DA51131219686AFC5061FD07D65A0A48B679C -B53999377CC8D41E5B01166137D0089F7528BA27D956BAE5E2287C5BA4B0A0D1 -624CC04BC099FB64C7488BE0A59AEA1897896424A178943EC2DBE462F06273E1 -A7D820E895B2139C33A508DBEB9D5DA3DB0B9F386871CA37C2ECD3968FD273DD -3D4D2E44549C2C5A071599627685D416A58EE6F3451E0062123131FCEDF49477 -94B0D48AE7272952CB3FE673B1894BA6A3DF9D5513577E4F45C339E68EF964F8 -CCA0678E74DA23FFA685812BF4DA30FDBFDA2934CA99292CFCF7EC8823834D1D -57105CF20BC4F51BC677C204038E35AE858B95C8F18613B610DAD20D58F5A7F7 -32A339FBF48E60ABE863B5DC39F18CF214CB3B9394D02B5F0E0116EF923F4386 -CDBC71A65E88B340B961D78EDBD2188F7378441C1595A9372B3E4A9F3987B1C0 -09118E50F4507807077B0712C75C07AD8D79A4E1F372FA47E1D2C16D52BDE1E9 -6D5DC79007B6EC2B54CF2DCB26C391A49355050DA57C1FFD90930D63811D78FE -4106E9D8EF7F019AC306B021BC73ECEE85813DBC2E5142C11C414087C11D044F -642920B7102ECFF2D43C0E2965CBAF13104C293B106C2721190372BD666CDD17 -5A506CF6C991A9912C213D2FB1321C186FEA1F62DB678B80C948ACB252D364F3 -92FD93099D65209786CAFFD0380BB432D9023122ABFE579B71224BD99E5C6929 -44164CB829C4796774FED8C762B19C327AFF66606620D7651D32224FD5BEAAA1 -40711364D630C023C94AF8D959692A5E973A69E7074A0BA92B52D2BCDDD9A8B4 -311601A7407695F370F55E951D4873B8B7864DEB94C591A682393A519676D415 -C9D48CF9BB5919CDE4FFEDE5EBE1E31C19B963FB3E4514C97227E772868B7E78 -2DD1F64B8A1A59F5270035D286EA7A8A2E9819C5D2EA09F4710F662B32F56125 -5A74841A8BC247977AB2DA5A870A24936CA3584CE542E281F0914CD9F58E141A -BE8E434304666063BB6521C944B1AE674B623A7155A813FC624359E229E4F24E -A7A8C08255B220A300A52ADB791F8A44D1BC46D3983677D60CC5B2A8419AEE66 -7ADCD92EFFB7C3BC90410947CA4F9E8292FF2B72ED99D220AD00E2DBB8CBEA25 -C000E01C497F94746C68C3C0CD040FB12D59AD7E9CAEB9B63510C56732312C39 -AEC21A76E6A16BA4A7A3BA0C1DCDC25ACE7FAE968AB6FF1749D3B0D32BAA78C1 -AE9997EF7ADDAF34A9FE3BE747EB44CCC1975F004A053B686BE11889A802CDC1 -D2176AAAB3CD0BE0AA56235524D691978A4D4D4080F1F66819DF8324DECB0EFC -264E10E60690E31AFE1E41DFCDFF8533E8ECA0CDE4A399354B055BBCA4032B19 -C607B196BC1A1E5A337D4E7FBD723AF1D6A288277EC83A7FF297727DA311FD4F -667ECE9C649A43A6C3863035EF823E71DDBE22DDC00416B3B1857D4C54ED15FC -664ABBD089B1ED429710815DB71927311E2CB28F2DD32AC556C4774FAC84FBBC -8B02D9D5362AAF3D2BA23E9A407763386F94B19C5AC87EDE226D8FF2FD44527D -4C930CF193CFD628D4A611E178F66DD1548B4EDAC700618259406D0D5083484B -41CA554BB87DA00D1764A502807D3C489E56CED505518F73099C9B5E5FA9537C -13F20C4A83931C9A3143E90ADD4E72DBC5006017ABCA949F2EE79138BA6782AD -2A5ECEC5746402681EE1977BB077BB1BC68A8A63E677C602197530EC172EBAA0 -FA8131A5FC6F10E6994D7E623D77F4EA5A61E3CB66613A212E2947F63E49E94D -1E612EC3A99FF6A604F3AE1218C5ABFF453026269307061E5FC9CF1250CD45D3 -636965F97AE53FF8F8330C6FB1D7721EB3A071E145A2154D31409CACF1C560C4 -F898358C4AA08E456178C3E7CF59A83EA098657D8253E64819E5F6E5BE5851B3 -AD9109EEC894F8DEFE366C4C9C16781DE0E14B1D51424B6ED025C91DB0FEAD34 -930E47F9C11D6B50814AB6109019F20A6D030ADABF57E8EF567F718CFDD9AB3C -EC02AE3EA1D1E84BA84CE1A505AD35BFD762F2E12E24CDDF4DC9A0C49AE2B91D -149A89B8279DB8474CE8E1B24C257EE32DC5CF94580131A57B80167E901A057C -F1236233EE28368B160196FFF63AE7D42737EA6DCD90C9158D7AC59F399654DE -7034546051E2E5F9AD18B292FABE9556BDC152DD842922CC182F09B65F6D464E -9C50218E2ED2F1FFEE92B14963D06CEBA5AFD9A0A75441B09AA87AF2B4D253F6 -340E831087DD7552A5322A3375D0BF870A773D36082AC8D0A0AE309D4E8DF387 -26B7767EC42002A9D4EC80A5FCDEB57EBB86A4AD383C1BF85E873DCB73A7DCDE -077745D63CABC0B737550828F7C789470B358586C04395740DE69EBBA502CC2C -A79EE29EA969D1986C9C55878E70320ABC50E46DF6362DCD9FAC8A4CE9CD95F4 -9041D407809C25F4FDF04EB59BC9F008B34364EBF30BFAB3D2B965A892B9594F -CBDDBB718C2D403BF678F998ABD78DAC10AC02D71AE1755DE8DD47CD8B06C0E1 -0062A6C1FB2322BE6A26F86CB3A9C9EC950E37BC711D4F32BC878F2801485309 -94FFFB772AD0167EC95AABDF0B82CC96FAC9CF45580638CAE52FF27A5853F6DF -13939DF00240882C9AF2DA83D08ECF7A6A40BBBCAB4D9E81700ADC65361E1736 -DC0B4D69B52B9BB481061E06FD261EF05D22A1CCFDF59DC63779B4FCE6FBF25D -1243D54B3337D1EFB8F6C68C7CA33EA2392B5C034F514378BCA88CE84AB0C586 -F6940D0DCFD14249733A8D4EEC25D494B41EB76F8944B6591A1D69F42A9064A4 -4BA19CA154EF1850A4AE3E7F52E6CBC2B6A948740154E159FBB036A21069D105 -03C2BD76B5D4930FF4B55593A282071015A7B9C739CB7FD6465AB557DDEF6763 -F120F93EA6FAFD06FC2CDD1445A77C43C1F4B765538BF0440CC4C57A97FAF64D -1FADC38AD58E260EF5677ABA6D56A1F0D05639EA526EC7CE1F427CAB2B95AE97 -9AB54683F08D3EAA25A9077A9E20162E62E0A32EA3BB577E77DEFDCD7117B53A -E891E4A63DB284C45571E82AAE871580CE240E76FF8E0984B31BF119660CF391 -41B6DC288A6A171F5270D2E3B0F64373DF64F472B02B7231F0DFD334B1355919 -C1C489E2DBC11A2663A173713A6D220A5B25D34F15788640AFE26A9704AF2CFB -F839E74BCDB0EF554049319B271BDCB736D775491FAF0D9FABD77E1250DF0AE2 -084693EFC96A234331EF04EB85B976DD77AE513507B6669F6FD4BF5FA64E22A1 -45A9894ED778FCDF3FE72AFDABE83F7D7E648FB8EC7FF219823088ABCE39211F -8DDB2FFF4793DF5FCDB25183D800ED0357AF5EEA5823CEFA7BC8A99248F91C71 -EF0B218ACC2FF17E59C41DBBBF24312A92793829DE450A962033F5EC81F75E6B -9CE808EA804882618F4BB84D241C3E69FBAA333B540132B0466EBFA4B15D8ECA -445B2C013268E00AF58A33B05D6A8FC6931EBA68A5D1EB19BDEB8D6A13D75FC9 -8F80ADD36DDAAF016C6E7F60B6726FDD9A9EE8BD042AB26C9E7BFB513FB16198 -54566D34BED609703AF75C92D68081B40EDDD8F150CFB6E0A7EFA3A04502A04C -C07ECF2136F294A0F9066A2F84C739F1A821FC202E3CBC6D8BFDD4D98C51753F -6400E1A38E91A628710BF3016933910A65913FCCB32E80A422F1432E0DC07145 -D519A159053719183BA4AD772F708F86B4074DBE9E2A7DBB7EDA7A707CDDDF16 -A4ED69D6A90DF8DB09E06917BE7BF1FAFA8148B2D4DF39C418F81166A0EF337D -78891C561FA087193CFA1D31C2DC7393F6A10786E09A7EDC0018D370071C3EDB -BFB42B40AF7199F5CB901CDEFBCAF011ECEC8E390D372CE5D4EA30DDA53CB86B -E69B1EC8DE69E84F5F3BABE2632576E7912831836E36DF7AFD3C7794009903E9 -D6C0DE85044C3A69AFD7488F586C47B064DC3CEB8BB395FCCC3CF217F4C92CED -3014B8F8ED0D2B38FE1555CE4F026AEE85E4A31E657D8818034E5ABFBED828D8 -7FE0E372F506E4EB3A539E738AF1FA5EDC1183C80170023E86AB36B7FFCA23B9 -6CB86A39E4F57A3B9E4CC725F13C2C54B8A3E640328B8C0CEA0F95DA5288B615 -F068DA3668272764C0CD9347DC0DD834D0D9259AEAB049E7BE906878FDA12C29 -47F00E7825BE00DE8CFD5678EA7AE1726F5D665C8F5AE7318A4B65BACB0E8599 -6E91BD9406898E88C2C524253A61AB8025DC8A873C53340F3D531718ACFF3218 -DB61F8C4D321A343EF919657ACC0CF23AA411799D9DA0BBED27FBCA58B5EC49B -2D00F6B179C72141ECC41626BE0EBB55771546553FC052A858FC06987F5C3E7F -7076838EB3E284D00A5D394083C61CED195B0B7C9B8007C8A6A347EE98261AA9 -644CABD5693D277241F3F6FE0ED9B661226F191E8DAADF48E15C63A2BD64B33F -A0B5A8BD0AEDD3608ACE5E3F7038DAF3F9BAB659DD2EA4CD13CADAC984DCB03C -0B8D848666D54D21C788F95B400CF6EC834594C8275F51C941A1F5687D5A427E -5E9A93EAAD048F5D141778BFA3792EED2B0B3C37D06605BFA91FE8271CEDC1DD -1E8F3C374AA4BA92F2C9521D87AE6DA5D7791F38ADA438ACFCE4365229930215 -894690C75D27BAD65579C588C2872FD26D49FFA96F7937E6FEB5A3820C1AB38B -574C86F272FF25EB6E70BD944635B186DE2AD84A74AE8FF76BCF22B01FB11343 -CFB142CA4C3B0068F7215BA640766B2716BF3DF57D830D7AD9B00B39C998ADAE -436FC8B9730151A9C5D080EF2E41171EEB56E9F35A2EEEDD5481349D9AAA1E91 -1C10F45F5E5BAC3592326EC5BB841DC70706455954F9827D987158AB480FF3AC -34C0410A9D1CAEC8C6B62A79AC582A75078E63A164387D23E076C54F4471BD88 -0248CBD81A2FFAB7926F415E2B237694167BACADA7A71D9017D3200D2874D22D -A2129B24F936F750ED529DA69A1A8F6F057338DB2209F221D03F22B383ED29B1 -DD71FC1C5036997C0C879E78B542F3918003A7B55370288216F15DB91FE7578E -8C8CFA8E6BFF32C57ED566ADFEF0197826F073D45AF8580BF6B4DCC3F5856F44 -2428C6450D2B471F6E1A67C511DD94DAB9273A506D7109DCB33888B76D2F2257 -DC6DF167457BDD003DDAB6F3FC1C1121E4E59550A950FD4F713A2AA7CBE97941 -5D78F7F17EB30A5CA883D17642E2334D7194A80961F0E2C26091360B805B4CC1 -6CD14A722C1A144BBF7FC4061E417148C1E9B750CA0E18EE05485FFF19545794 -311472B0EF215EABF1E7A8681CA71FD43FB0301A859CEAC0361B3E0C41736C53 -7A9F938B39070AA29F9EA5A7C9219EDBDFA2E9132BF0E49B670057FB23B86B9B -B3CC7C0FD12EB309DCF8D1D5967C235CFBCF541B5C191DA128D1DA4BEB088BDC -B6ED683BDE7EE18598B9B2B1D233F26693A66B3FC2285444721107C7313F7FB3 -201905B38DE3BFED9BA661AD4A3D940C6BFF8A74807F4A6D8348A6246D2CB9F1 -D3E4DDE6D7460EDA0026E919EBD0E7305F66FA37D2C7EAFA415E67BE00399C5F -4BFF7851DC10B44A696B2F0952007736416CA5F02D8DF73B60BA764D2C1E978D -3F4DEE50CB7764FF586D1B719E726734625984657FE810FEA022CBFD09F16487 -E6033B38A1E111F73B8566E60145A6E6D76E98CBD3F2F70692266012C9204A73 -309578178217A109DCAFE3747AE4DDF549737B4DC9647A56D9D3A399663BC417 -D83D252E7407E60270D2F592127B5DF30603482F1C17E20F2BFDB2B29E17E55B -100DF6F1E76963B086FF0729AEFEEE7B1283516C6254F0B54B3AE11E456ABF79 -9E09F2D983E2F7CD3D056926DDF26E5A6B7E003029536DCB2FDB0BEBB6878448 -444EE80334344CA7E42B5371E7C632EF9BFEE36AE2E22E713E7EA69BB2C8B4C3 -B5E204981EC1DA73A72E0B0A26406E904DB16DE7303606D4D5F3538E095F5BC2 -06917400DD909F3D880F5E6A07B0ADF0E61352872D4A52FC3C8D18293A4B2F94 -5D32030E7B925B951F5FE050335123BC96BB5C8D6B6B9C7DBE7C049516854637 -82AED9C2D708A8A8137F59F099A7BAF3254E4ADFC81CEFBA89D6C0D11C9A7B10 -2F19ED50BCD3521AAB052185BC45EF2F2BDA547C57688219D038D1E5458B2877 -7B20CEA17D4EFC5EBEFA32B99AA1BE19FD7AD6255F7E12450DA48C3A7947E5CA -95CADBCF440B38212FF36A840AD4BEF61438F4C08611C2919C1DEBE0B916887F -CCF3918EEA989BF0F15FBA52906DA77BD57BA0CCCDE6CFCDAC76A75503040BF9 -9728DAEAE729F7DAF8E7511C5F92C10DB4764421F8D968612FE1E01AEB35B067 -2CC2D5D1386C0666885750E9F04E1A0407157F60FFE84E585A36714C844A6386 -09EC06111CBDA2F6C561694D409D93933EF5A0E25FD7D2BF5A1E5267BD9267B0 -151FF2A06D7B7085B8016DD4943AEF5A3274F0828E22CC6C9E68BF182CE6D474 -3274F74E64565BF8E64FE4AFD4C98F05487C31A249D5C90F94F9CAC398B2F496 -15CC249D62F0C9B9B9F71AD29479E69D5B449D2564802D6576C7584368381F36 -E3C22F01AAAFC85D22617D6F6A4E598FA8DF1FACD4C7F205E88026D12F7C509E -38D29C65141EB2D397797FCDA3D2F54651F70FC52E8F4E12C5AA200495825FEB -54855AE33A8ABB57E61394902CAABFD06D42BD1ACA57DD9B81614CD44C822A55 -88EBFD1DD771EFD92876B60131D4B86D3617863A1399A8CC1F2FE9EB1AC4C614 -1989A0E2960CD5F830D33CE422D5BC52BD7DEE31D2C668E65ADE9220206136D5 -7696FA00C4857CBBCE675A0B163AA73EC04A75598D18D82422A54FCA9A27CEE1 -B922A0F52968D27616667F660EA1B5BD3BF25519E391FF9958D4A491A9308854 -967312DB3174EA973FB5052ED4274F449F3D579EE90B54188F910AC3C69655A1 -FBE9E3D09FB0233E3C7A80EEFE4FEDE817A7AFAFFC84E1D48F6E70C41D0226AC -31F46F7B29E99B562E9C4AEC9CF4558321DA229C3A7738B0CAF03C93EE489A2D -72458368E300FE0BCDEF04E7EDA685BEDCCE622C59EA429DDD81356BDB22E830 -F65C8904824135F82A1A524C317153B103A0BC804FD186FEBED4AFCE8706EB4F -32DBD3BF2F40C5DF5B85E324D8C140D47F4D2E2DF2304424C327C6D12EE63E15 -27BD4EDF53E355AE9A58A4AE77525B70DAA373CE7968CE286967B43F685C267E -7972594FD36DE1E0989111A30F43AF8B63EDAE180502A0D5873029770764B933 -F7E43DF0B70A0DEC500AD685A57399DB8433BC975A90B0707C8BCD466D7C657B -EC0D58E7CA755BF41D684CBF75D1941DCC4BACCDB5D0E1C0855E8C4C368E535B -327290B67D8CF7E12A2460E6294943BDD6E9BF9CF5A6AF70AD1B96BB33C70195 -56AEAE0B1DABB09485C282D79C30517BC34583D16FD2B268F024E0D9654AAF3B -3D8AB3496E7D0622D0455BF82C2BFDE912500E6D5DBBD9546D54362922C9A46C -B6D7A01363AF3699466875A416CCA72F97DD327264B3EA16BBBF7E088B47216F -626FEF9AD1034AB0CA82099509C9AF9B70599929CE3D21F612CD40577E9CB7AB -A4A79A15A0B03A8B90A424B64E7414196B72ECC9D2632B4D7586700D495DDC0D -367F415737612CB6BA03D726004F8D49B2C5E155464B826349470D9499B60DF7 -84764156762F2E38B9440CCE89A9555DB43328B59ED6AE0E53B015492D2455D5 -C66E4DB65871164547C34E5D41FC3B9D5440E8D6B7B6E09FCF916BE674A43E36 -6FA7A912481905177D896EC126DA80E125ABD27B9BD6D81B474F909DC8590571 -6A815BB1F27853BC47EDE4718950C3702A9D27C28D3A0FE73381445B60BB1887 -DE62F57BE2E473B1263877A11D766945ACD5310C4B9D2EDBDB5D3DA070814969 -7F086E8EF24920F37A23FD09CFDE87F854808DA8FE7E5F2E54BC13CB936D498A -5CE1A7202EABF663BBA01BDBB0B479264BDE90A30543B7CFB8887B52D0F28BD7 -8DB8A8438418D50BA775EA58624DE3055B394A9B7D31E268B45E4BE6304C3B3D -CB9DDFBF78ACEB72082F2895B99AF925421472DDDCD0C2846E945797284FB405 -74A05BE373C99648D46F0911A984AF9F726F28BE6534E2D1838FA129E508F81F -B4490FC684E446659151B446B13331D0542223D0F7609A8925808F16E9992FCE -42983CDFDA4C8F3BA175E47F630534B706A3BC38CB3AD3D4AE304EFB9C00BEB2 -A830A35B2FFC25F6BA978C28AC71B875C25A7808EC8A5BF619673CF8B8518368 -852BC0AB7ADF6CC29D7CF4C31F0D606267DA15469DBFF23DEF654384E6074A55 -A5AD235991F25EFB4973E03CC19305EDCF3B46314F1584B7216366C324D1D182 -8CB2F48B836CBA52042005C67951904FE2889BEE51B90973202E6280FE134F80 -C0EE88917639F293EA1840DE5D654665D5B38FD57B89B3807714FCD9A2510B03 -4CFFB3DC6BDB2E5427FC725A91551F2615A5A9C1FD625FAD049CDF42AAF1F98D -9B6E9C29A1C35B51D14608DDECD76BDE9AD08F4D14B3BAAFB4ADE2B2D24E833D -9B520976E1345FDCAEB2FC5A6A7A47DB0EEDC35B0AC9B143C7066DAC1A9F1A3A -6759FCA1AFF0C9C14D7134EDC9AB838DB1A854C10309E456F8571B9DC87EE342 -C1B703FFF292EEE81C043C6ABC32F31802981E734B15FA87A6BAA95FD4D4D9E0 -7896ED06ED4A60DE13A62CB6C7190AA73D9520AFA10A6827E45BC35F4AE730C5 -AD837CEE455989A3EF8B5920A4278082C7CA8582594231614029D6D084474864 -3D96D86A4F31E258A49C4771262A64F7445B20E159C024D7A40B623D565A5CCD -E4AC3E832F95BB8BA3B9FBBADA1A9DC928035B9FD5D81681362FC7F5E9004050 -6538F992ECC8CC0F9A468621546153BB29ABE17CFB7FF412EB4FF42A4E6438A4 -01F4D4C6264B4B815572E90327646FE756DAC90C9AB78402F791CB2669AC60F8 -39F7902B6A95BD4EF3041C631D37E939518EE97E9B2E52BAB3BA8F2A26C8A9FB -EBCE5C7306A617104C0D0C74A4FE03B94390A393498C1619932CC3EE1650404F -AB16E40CD3B4870C9F687D11DDAE5C15B0AD50C727B34DED6C37925F1798FA5D -8AA565ABF2D368242F2985EDC4E299E5F93DB82656BBFDA364E2FAEA9893AC3C -DDA311C7D6ABC7CA6C759C5DD2DEF44C675F7538EF35AAA5503BC12F311A1058 -8DB47F91E9B56CDA671EFDDBFF09AE3D75E30272CA099A7DDEF518DF908687F4 -BBBACDF9486E3FAB7B909199A258B6CA6E3B64F30EB8F6F907E7239F0BB4339B -519E733BE3239221256C20854881C6D0F9B974E1C4AE67C5E84BBC72152D7579 -40036923F671F9B5C6D7BBA52C145664BC3F10B294A4BD345E019E95A7D7D93C -C1DD7AF0929280D01A1AFC83D4FB0AD268502B1811F874AA648F40F5AEBCCB85 -5C4C485F5B1031F3FE4B038581E9C0912CC3A877672F3889C32F72219A9A071F -7268F19AAE2F8F6FA3A02287D64E64FAB91252A1534DFD7338AFB26D3ADAA770 -F89A63D3FBED4B0914D3A1D64D21864C561CF681D38ECA5AB013BC8E4A3D8E63 -4FACA1387B57055E12AEB6E28330B7E679B211D108D6237215D34E8E8475FDC5 -D291E6B3A00C1080923642062D15E1DC258D018F9E9138BEC0D1FFF34BEB39A9 -573AB74F63651E0CBC8F12D965E255085DBBB4E8BCECCF0B4B5D58EA07C3C69B -97EBC9904E9A4E6F361635FDD544C88120AE84CCF5416E9EE6E9D534780ABF32 -8A6EFCFFF3EC1F46E969E97C0F79AC02E2A0CFB7662EE288498182456452E0E3 -62B24F03B95E0E70406033353FA3B0DFBB1741024E131710E3355FF2EF1848EC -26AE602D8806E44E38019F7D9865F7EE35A56082403BE5B4D3FFF0D485E5C718 -389F5283C688EC02574ECE4C757CEDB01CC8596C6462E19261C6B32867ED7553 -0EE2E171CA3ACD4C092AACD751F698E9B18C56FA5A9BC0A8DE405F08C9AF304D -D4D481D2A1E93BEE9725025935D71408AABD74F3BAB3AAB21004155FFE19F551 -E0E1B682C2F54C92F6B9ED91A38442CFACE98368AEEDA68BD8A28E91B1FAE708 -6672771D26AADA36F30EB709FD01683A11B817FF646ED2C3A6FB1101913CB8CC -64C68E37148FEFDDC74F2FBDD70CD8000733D3BC44B6C787D1C7E49AC1D2E2C6 -C2ECC696A9722F473EDF681863575E1FB1A54735F5C8136516AFB9A6D4E9A7AA -310A6118B3EF9349D1E96E6EB384D206DBC45B188BA8445738729DE24D48A159 -80DABB850435C0A03359291C332C78C1656BE622FF734144AC17BE19D38F9F54 -59CFF8FADB2D0164AFC718268AA4B94EE7CCCA7B479A0DC70D9B838D916833D3 -6923D4B22126BAA2237DBC3515EEE6111F6F078C904EA4FC5EF00364455976FA -E00E5D79C5B57DB1ACC73640A9E37C200A530430E0D7F899AC67F7EFB2F906D2 -24722B0A9A35E7DA6571373E2BCB5DC0D5E5D1398B9BE20A2F2A5EBE0464E101 -30BE52CF8C12D85B09F5DB9DEBD3ACF320DF140EC32ACACD0DA56642F44BB965 -BB769C0AAA298E671A0371DD2CB06ACE542DBB79031312A482B86BE124801EF9 -52D425F8F2F3B31598B93C2330E8B08BD1F6A4DB245A19B803EA947A2119DA5D -52A83D5637F85B4ACAA1373930A4674C354EA46BF19B439C764FFEB82F249514 -ABE74189D9BFBDA3A8F81CA4A8DB1BF63E10AC6B5B5E0D6FF8CA45ECE9536571 -A9E32433CBD5F04D2EFC1BC92D18CEC88D700121BD4923CBA73051595261307A -7B00D14A2300CF78C93EC96326C0D10E58E91A86FCAD94E1A47E34FCFC5C65BC -BB7316ECBAA3E35C7D3C0814BF6A2AE8B18121BD68722CB277712D118F1CA88D -31D5EDBFD64D74318E5DA451D12F5CDD0F97258ED25157B1A0ED1994706EDED5 -FF6293C9E4F20EDD1315FBE90446A5ED621B4898E4EB9F23927F9D33DFDC62B1 -A38C8E7B247BE8511ABA17A2CC52D4AE3A6D7A87220FE1745620A4B3A56F3520 -D718E0015A0606E4D187856647CB189D0DFCD96968890561843A9FA21DC5D508 -C74D9E33F21EA57B90DFD7637128ED958AC4EE480901F96ADF4FA833143BD85A -C7D0B1D132D5C000E1223CCCFCB5AC84A42052FC10113B6AA88189502B56431C -7CAD3A8DBB8D096569314ADC4236129F00A65E1C0B5EF666268AF208006F6A75 -136970EAC3A2904C7426A018B751861BB6C46D4D74FDF9A162BB85546F22CF80 -B7BBE9C846E8910289EEA599BCD5FF4075C30AA88F93450654EF831645D7383C -CC7FEBBA9C0DDF8109581C4A85224F7C9223581FBB201951169DCA18FEE81B48 -F2E916BE7E275CF75990102FFFC1DBEB859237F9AA511D4C884419E421DEA2EB -418C6A9318D45D858468323DD803918FA6497A4CE6E7FBF188A67297040712F8 -FA68387D28D239AFEC749ACF53A5F72B21AF2C8DE24EDCE7230934E324AC2C89 -F35E2F349E92D3927A367C942A9A685A4C28F364D7E61D2DA2604FA80C31BF40 -5AC6DD6EFDD8799471B3D8890D93D451306E481CDB71C471D670369CBAB789FE -EAFAAB9D94ECECD08F6C8F82BB4DF09BCB02F3E06A126E4E468F059089255F37 -7488E957B2B5521A36FF62E26838E06E38719ED72D2A0C7FC560A5ADB530CF22 -518CC4B715D7B6DA08217328C4A09C53AE70A7339514B56D13A2F7ECE09220D8 -E2EE66CEF5E5D07B1B30BF15C3BEDE12CB52C974198C8F097C3DFC69A3AC2545 -41A3913094A42F4A2BBF2CE0CEE9AD7E5A6CD79814CD5DC55C8F3A99FBA341FF -7D844AC9CB0E5BB3FED72ECDD97A8B22183EA6B9D13CDF6EC3DDA3D42515E94A -CD45D8FB4CCA4DAB7138E8FC837C89C3E78C2541550F229A4AA9A836A449CA47 -B2D77BAB5A7B4D53B3D2F35530523338AD7FFE86A0BD3B0842DA686A4B9B732F -4E81E47D2DA475BE2FBA41F05B9595BAC506F2D8F9C2EB22398342C77E79AFEF -763BDF8269B7688CF98F7823E5096AE4D644D5249F7EA1266ACFE9949AC8A288 -D57AB37F51FAF7937F47E41CA2F51EB249A525E91040CC5F4E9322475FE14E87 -2444BFE2BCB136FCDC23BDBC4981632CF1FEFBB494F1A3BA16F50DD9BA26DBD3 -0CA3C7113A364D0EEFE600C47BD90DF257CECA68B3D173211380487FC90503BC -C9FFC27435BDC41EEEF08A8BB309CB2B0C8BC86DA1AA3514B07E97582F3FE4A2 -32BF7BAB02CDBA5930DFF4BAEE6F00A21916C9D1D0EE21AEA51AF561EB0113D5 -3A0A251D173A77C1795BCC56863200338933817AA0AD96FDD6CE740213CA207C -864A97762A9FCD3EC94FC518E0B9CF871854BE2CCDE4C21C1AB11F6BE66A44F6 -7D6751471D4BD779C949CBEF803B4E7672D5D399525FAA9252FF78BF7E7E81AE -10FE4DCFD6BD3CC4C99B2CE818B2B8B45B6C4B131ABF2FC61B71EB3E2BE21D84 -F3A5F90B39D76D1618063E8EEC04992AA29CA3216217CAEE3E27B3916E5310DC -5C4E2B489822FE4D6AE8A12FB1589A3790F9FBD105F451637F396E04A13FE1CB -7E1E936F3EE1F37C9B4AEA80994EF8A217DEF96C747B8EDAF048EE8EACBE4757 -3A6BA4B9297A4229CECB2719A9346B0D34FCFB9AB7575335EB477F0EA9AE54C8 -063F5B3C4E40D158D44CCCA4BC7C7B55687FB89BE7DB9279E34F144247737AAB -D3EFFD448FDD211DD3EFDF6750D9232C4AED40C8DCAC19A19CAD81FDC6A02470 -7B0F5B743465E0910F67C559A5B25EF09C80BAA80486F04107559D253A9A62ED -7A25BAF326D8569E2DDC14688723C245CD694FBAF14B8BFDFC35038CE3A1BF0E -5D8FA4FD381BDFE34F68C81FA1E87D3A760F48998A443F70D6E38910354E23A6 -4449FE903E50D30DF066972927585A61EE674F89B28B7AA90FDB1B94A6A5F1E1 -9D6D7313A5389D5BE005CFC1CD4F35A0458B06D62EAAA5DEE8117FDE9BAEB25E -A38E0886FEE01E0170C5B6351736816FBEF0351E5471697428F25239953E7FBE -B16F4D7E00E81BEA0CA12AF27DC98B3BA32A2A504C8C4B523740FFAF29EA504D -D747111DD946EC2034AD209B6645A6F3CB5CF0149A2C9635AA41E88A0938EB87 -BB442A48D4B942A08212D1EA498E0C7106C458C857E003E5DD7635B0CC6344D1 -C1D4C05A8263414C0340AF765282CAC8367B89FCB66D9D4B958FC981E9CC7785 -E993DD791F9CD6B3557FD2F0B87023B6D60BE63DBDABA57C975EE37F44E5DD4F -DA1159378A67B6E3D5ADA8E40D59816A584A456AA4D61B3373BF048C3BE6B806 -8549DBE89116FCD001D507B7CF32F87B0887705BA11F8DFAABBFDCAA721D38BF -94C61F70A58891E577D7030491D60132C93DA3A80A856111549E02B317CE1035 -DA5D9AA8EDC8A63F065EB93032B48869CAE47E94A805F395CFEB064905674633 -4D0CED3373E67B52F127A58DD7C2770BF9FAA294C62B9F76F6D47BCA510E11EF -3DC37F5C317442821B2D056993E67646D9B1E5CA929FF709ABA27A27404EC2CB -6EBA02B7A2839955F8E2BB7F59449C1CF39449EF1E94759E6957F1BBB1E4516F -9C07F7578CD268C9D90111648AA654526A5E8351CE12FD3B5FA2DBBAEF8ABCD3 -5882795FD9FADEBC8F3B7F9505CD9938D465360157D6DFD90E13D21DAEECE587 -43E13F92BE4EB0980319CEB35C11C19B32A5D57B6CA259D4D8921BED9576CB01 -4F2AD03704644F1E3C6E50477916D193EC3AE2E82FB86880765CB7E4F69A0F66 -D39189F5E7E76136D7CC5E33102572FFC5BC1E2849243C43902F77462C36D42D -8E51F67A343A4070FC2F192E4C2A19C97526C01152A745FC60D4149B3566820B -4F45492B4D3304154F917081A0C7BD0838BEFC96ECD5BF1ADDC743D190FCAB15 -77A24B3E0CB72C16F698F8ABDF2A653C8AF374582B3631035A61572421BD9B9F -E630BBBF2C4D31C15C608950E5EB054F08C4BFD8C55E9346A023B5A6E384CE5A -D45D147AD6A0D83E507D6E7CB4DB9D79BCDBD4DBAC53E4F2F54BC43E6604FF41 -694998160DFE2ECE261A4258E6181962B3DF7511FCCBC1AA4BDA31FACB8352B6 -00A20481D66FDF1D570C015AC07240E94A41D827BA17D9CEF845715EF094955C -63CD05D6C8F3D68AC0C0C46CFFB463C5E2EE902D6B866D374F01C7C33C42EB6B -AEC6044F93F94DFF85ADE2626DEEF3EC73563C6EB2762D3A8E565A4E6FCA4026 -9F33EB916C4CEBAC10ACF046C3C2F78397622EBCA2C19002B0BA6C6D74EB8235 -AF5ADC77907D394ABF82C7C720D00A71F8C3BD25167F68939C3A61BDE015F57C -15DE3C8E3C211B8C68E6889879062A07E0B6B894D46BB2E0DF34BAD3775FE4C9 -4DA40F0218232F7441D78D12611F2438580F4CB4C1E75AEA59898E6056FACFBC -5451492F6E3570287BA00F4EC9DB9A5C2491229324AF55AA7D30AE5420461B9F -CEC74BE8C9B9131659625749C7DB4AC76BCD602EC1F8E598C53CCA21826BB99D -B448D11D4F03537A14A97D50DE9478DCAE1FEA581EFA9B0E89C7539C09D231DB -748C8329C68B5E9DFBD7319ADE1AD03DB62C8D515F62C37CD84A3155FB80FCA6 -474FA2DA6E10139EEFE6D979E8EABE053EA6CE44F447F098485588C92DD71169 -F859DA274DE1385BA200EB34E3E612E12B433EE3D8A865B688C38664A0BF64B5 -86E0ED0988031BBEEE9817433A39A2EEEB31BF3BA541E52A834F0C227E8AF023 -1CEDFAE842A8DFE5CF5300792DC580079B337FA6EC58E12772B08294E75B8332 -C827647CBF35832E687FC840EC24825AA13323DA00B2BCD7747C258FE67A5D47 -4F26738DDB11A1B0A747EBE8440FD0CE69AF5156FD001136FA1629A048AA1F11 -C1C043BB4A938B8D110EE8295571BBE468743D4CD63B8A9FCD8CD5EAF7AE5A6D -92F571A8953AF7C9A94E7B3A2B5D475760F8DA457D8E971BEB4217B626982D43 -921EB2495D43846EDC899656D68F10353250F6FD091653FB9DC28192AA6A3D67 -257C05AE25B98B1AA908330EC7236D87D9C52CA25B57B5BD5E9268CE92079712 -F78911193C69210E5D533CE127B18D98EBFD6A1B27EBF418E9625BB14B478B47 -4880A9B11180CCD6C72DEBFB26CD814BA5A70BCDDB7DC75232F1C67BCAC346AE -48608E977D3EA87289F49D51E2EF9BB68803911AF5B377F50B9120A9C825CE10 -467FE5351241C8D382BE8D72D4330CAF4A9B39CF1848A1858118CEBF10AA5548 -945638D4512D33F0E5CFBFAC4449CEBD93F1F8FC9EAD36F1899A5113920BB91B -F7D1EBBC5B1D4BAE4B8766DA0A19644BD7576D4F3E202E157B4C27116A4939AF -E8603DD5C3F6D83DE489C04B358AD6B099A1C4D84296CDA43A30FC1DDF90862E -8BE3B80E3A369C8BB4E92A88D6064900D62E95DA803CECDD5290C2B17BB198DD -741E52F6F018CA007FC8641E5233E9C5BFA590E4934B43D375E7B81C4F825F5D -DCEB827E5A275F0ACE7AD79CF960F83258A709EE0F43364F5D3BD9DAD16A0881 -85B4A339A1FF47A4B99D0367B523C1E290C336E823494A182B221E1D98E29647 -43BF0A6438047179D7C8349D99C5317E455666BACECEFE59EEBFA802BE644BAC -E8BB4E75C45634D873E6AB3ECDAE27AA3A5E3EA9F940A0E9CA41FDEB43C0ADDF -BDE41162E016804DD7565E7E1AE954366E047F3EEB7DB01AE9841D2A56210956 -F98D6260643B184E4AD42D6624C42B9001B197685773786B161C2D6054DA48C1 -3C15F17B3D2E4A7398385D3AE8D4EE186257848AD0CADBE2F75B4AFE76B688C6 -D8EA280780ED1CB990BE38267F3B735066E943A915FA42F29BBEE5E6FC1B4C4D -6F2A674564C5821F57F486B1E9018CD8D17D1E1876ED97F1EA76CDB98F05D9E8 -65035F0EDA2CC69C97C8155BF0ADA6A1B2918E185F5FF3A06EF5D1FD4EEDF7A5 -9150A04092CBD78E06101F9A47780D6B8BE95BEF38387523BCA92E1DCD2AA0C7 -9A264081FFE7590A1402B9AF14522519FF03E6E685E66547F2EE341D99FB971C -826CB8E08AAB90139D1B8D5C9099AFCDD6972FDBE96D3E61F8E05A8AA04CF0F0 -92C51CB4E2DF5AEB638EAC13304F09221FC53D95FF5EB888F3148AE6E466E75F -028DCF215DB6CEA0FA674048C5718A5B76137613F0662D5307887B3B4E38674E -DFEEB1280F8C8F27E3493D6A7F207F46B4BCE140BF755DD97C183692EA46034A -BEB413D09EDD53D247D61BA648EDE7F9EDB327632AB44AAFA8B296E5E70B7876 -8CD9F8430A40F33220E92B036D1288B3E014F3BB824FCA9E94B82717F8390EEB -33E9325ABC989C7B8F4EFADE04B06EA3B62DA015E0CA00529FB6FA0D99B01106 -5BF61B53ECA3416342C78184F24FA7B6C3587FED766C5E0CD8F9A8F74636095F -C500B8883073FC260BF19739373B2C7C7601BC40708931FE8431904683FDDBA4 -8656D76F8657DE79F9D6FB1089EFD8CD2EF801DF4576AC25E6B139DD4B376904 -A5F0F08AAE17025F7D253A312FB988EEF658F71BA27AC2A5B87B8F8AB72294F9 -C4A70110C08EF78F5C32DBFA317C22A91205C75481DDC96CA8BC08C40CE6D3DC -93584F6F75F14110BCD5AF322749B8010522BCBF6BFBA4AE147F116C1402A8D9 -1E508ED3D65743BC6EE2C8D4C88545E97286C01CDB0A6953D85348EB082E4069 -CAED3F907312DCF53C921C46371B054086CBA983E7CE06C1CF00DC2E4DD80F27 -6FE999834EDFF088FE277193B813E231160B5EFD05B456AE9B20F993B2A67D71 -9A5C954785FE6A1EC900F764F208553E79192DCE9A8D547D13FB277D28F4E2C5 -9C62401D3EE1DC2EAF220F1AAF84C79D6EED2B8DF7E31E53669270C7DB9BCF9F -BE74329F292817D2EE2777096BACEC1D52D4098A935B262A2BAE58169730BF90 -478D83E60CEFE7E249A39A6CF370B721CA1476246665775213B547D9E9F89BFA -1B58EE8B5F475A7FE4FF94B1646FF075198930700660C0FE16546637E1D80F87 -C39381E4DE2379DB83C7A6A5908D523B3D7B9264B8973F78770297C0D31F4B77 -BBE4380FF20B0C4909A0CA6141ECF11A2ED1DACBCCBA0E72DBEF51CD8E2D8384 -7DC963394F52840C1D70B7ED99E2931CCC36C5AB5451B1529215943C934894AD -C1883A86B8C7684ABB0C115625F2ED431252EC74BD4396567344AEADCDBE47D9 -389C4F6BD94FD2A8A0374F84C636549974C3B99626AA7CE2A19D5C69117EE444 -0811B2CDB5D684E181D1899E33DCF7508BEA8D28EF90659AFE8EA18B5BBE9FC4 -2F30348FDA1DD26C216AF5B2B35BD658F6B2F8C42569D2708C69F89B154111E1 -F0C98EDDE70C937CC306493FDE8517C1245B2DA6D1583ABE196029CD4CBC54F8 -F474FB10937C9121E33CC960DBC1C04E94BD0609BBB0F1216893C7B188223AD6 -E9CD2FFA0257B35FA98F9A557865D99E4EA3ECE43461FCEA49277BB4A1BAE648 -3E7C022D064240DC00B48AEBF69BC9074E29AF869CB37F4790DC8C4628AEA7C0 -D5B96F78A60639863B0C37ABE636A2C2612DF83E47FC5808AAFD014C281A464B -CD0F6CCE1941B8D847D488E6D425A7563E1BEA0EA77EF9ED2A1A1080B8E4FE12 -0B34DFAFD4F9C324DE3A6E61753F524AACF5352FF05B8D3B2845883286F8AF57 -C1E2E0CCD66B06945EC60DEFFBAEACC7FEC78F3165C38785DC2BCD874FB1668C -AC46BCD6E09EDC69DDBBDE37FC061014A6252B5D1D52CFF5C8BD65CC3F854686 -5724BB70C371E235CB710E18BE356D019DA9B6B70E0A4560A54F0B7A3CA934F0 -040A901E078BE86CA8F02E898D99CC62BF056A9CBA3BF3004C885D6419AC5C21 -43CF5C84C67EFBA1BE3F645E21FB1BAA00B67464372F04AFA2D88AFB0CE82CE1 -A158B26B35C5FA3CEA597C73DD5204AC2F4F2E37A7788B80EC14E9CEB2D3BBE3 -178376E87BB14F7C9A75EAD1BE571C01804BC18B1BE136D11E66CDE40FEC9A03 -ADF328B9A0A3CCA9421052EF6281E7B7C0DE1DBEC4BC4E64D5EF2226318A54AF -61F4EDEFE8448783E5E32C86DF12AE1B79F7125EBB1C99049C8E8638982FDF77 -93E5B8AC73665AC45819B7FC6CFD9A57811C33D018C9AE779281AB249A149CE1 -45A4DD65254D1F6ABD1F28123E86D3EEAFEBEB4F9560F0F7256CB1911EF9D1B6 -410B48FFADC02E2C7CAC032579E75C369854435051555F99252F757C64A2EFC4 -55A09A67342CB362C91BD3E0315B584568873E5377C84272C3995A8D5B1ADF70 -A9C4F91972C1E5BB289D407D24FA7744D33FC6D92BDE47E04322DC7EB83B6BAA -442E93178F13036E40BAC6E20E8CF2920F8A1610FBEF3F865D5D177C21422B11 -4F160DBF271595289089478E31F9991C85D651A4F2BFBE09933C63DFDCF84D27 -34812C6952B2E33F650EACFB44713D635225F83A2C3E8421B2FA9D85C4E31952 -FC9594239D48C2F73C3FF5596EFA852B68030AA7BA5577FCEB -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMBX10 -%!PS-AdobeFont-1.1: CMBX10 1.00B -%%CreationDate: 1992 Feb 19 19:54:06 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.00B) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMBX10) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Bold) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMBX10 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 46 /period put -dup 49 /one put -dup 50 /two put -dup 51 /three put -dup 52 /four put -dup 53 /five put -dup 54 /six put -dup 56 /eight put -dup 66 /B put -dup 67 /C put -dup 69 /E put -dup 70 /F put -dup 71 /G put -dup 73 /I put -dup 75 /K put -dup 78 /N put -dup 79 /O put -dup 80 /P put -dup 82 /R put -dup 83 /S put -dup 84 /T put -dup 85 /U put -dup 97 /a put -dup 98 /b put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 102 /f put -dup 103 /g put -dup 105 /i put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 111 /o put -dup 112 /p put -dup 114 /r put -dup 115 /s put -dup 116 /t put -dup 117 /u put -dup 118 /v put -dup 119 /w put -dup 120 /x put -dup 121 /y put -readonly def -/FontBBox{-301 -250 1164 946}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5F00F963068B8B731A88D7740B0DDAED1B3F82 -7DB9DFB4372D3935C286E39EE7AC9FB6A9B5CE4D2FAE1BC0E55AE02BFC464378 -77B9F65C23E3BAB41EFAE344DDC9AB1B3CCBC0618290D83DC756F9D5BEFECB18 -2DB0E39997F264D408BD076F65A50E7E94C9C88D849AB2E92005CFA316ACCD91 -FF524AAD7262B10351C50EBAD08FB4CD55D2E369F6E836C82C591606E1E5C73F -DE3FA3CAD272C67C6CBF43B66FE4B8677DAFEEA19288428D07FEB1F4001BAA68 -7AAD6DDBE432714E799CFA49D8A1A128F32E8B280524BC8041F1E64ECE4053C4 -9F0AEC699A75B827002E9F95826DB3F643338F858011008E338A899020962176 -CF66A62E3AEF046D91C88C87DEB03CE6CCDF4FB651990F0E86D17409F121773D -6877DF0085DFB269A3C07AA6660419BD0F0EF3C53DA2318BA1860AB34E28BAC6 -E82DDB1C43E5203AC9DF9277098F2E42C0F7BD03C6D90B629DE97730245B8E8E -8903B9225098079C55A37E4E59AE2A9E36B6349FA2C09BB1F5F4433E4EEFC75E -3F9830EB085E7E6FBE2666AC5A398C2DF228062ACF9FCA5656390A15837C4A99 -EC3740D873CFEF2E248B44CA134693A782594DD0692B4DBF1F16C4CDECA692C4 -0E44FDBEF704101118BC53575BF22731E7F7717934AD715AC33B5D3679B784C9 -4046E6CD3C0AD80ED1F65626B14E33CFDA6EB2825DC444FA6209615BC08173FF -1805BDFCCA4B11F50D6BD483FD8639F9E8D0245B463D65A0F12C26C8A8EE2910 -757696C3F13144D8EA5649816AAD61A949C3A723ABB585990593F20A35CD6B7E -0FA0AD8551CEE41F61924DC36A464A10A1B14C33FAFB04862E30C66C1BC55665 -6D07D93B8C0D596E109EE2B1AAB479F7FAA35279ADB468A624BE26D527BFF5ED -E067598E1B8B781EB59569E3D0D54D8EFAE0F3EDE26279776ABA15341E42E636 -6E02817082BE6FE0B04249A4840C11F95F8ADEFF72173E9A5F2AB2F62C427E5B -DC010E18641EAC906A5EF0F9BC2108062134A7F10956219C5847C0D82F0E8663 -12D963E012DF0DD899911EC5D8096F80B49CA3444CF1294FBFAB57DFACC9D01C -46F3BA2F3D1C14EC30CBF83E5729F1C074D4F1665405C9AAFADB8BE41EEE43AA -16966E2C0CCC853C4C09F245ABFD4603C4AA55EADC0A59AA6E9F5895FAF3D3FA -83EDC6E2540417530AE7DDA8EF33DEB81444316FB3F93EF944D9FB06745BACE4 -848398BEB747E58310BBA39C64E341185C82CB77E9D4439EC15BEFF1335F22F8 -F036517C436225F4125ED67ACA7A84230D4E2B6CA713FD6B3CA54BEB540D4604 -D58A8335BC20052440C4903786FE3E335E331CCE36A13F05F71126F680077AAD -ECAE10CB7C057C2D55F384723D58EF3AAE83E9E0B39D6A522667CC5B3257DAFA -AC1C3C981B9415967F7F4DECD492A52D35BA7B396815CECCA18146C96709CFF8 -62E8552A78B12788A80F068ACBB0C15C55B19DCE5100BF525A59D34EBA5D3A13 -73692ED7E2A03532244FA23261C8E5702629C7BE1F33A09F93AFBF3AC607A7F6 -FD3D8B19098655B4DED97B03E39E463CAA9DD92C9048EBA53AA76B0BC5C48741 -AE3010D21B329E9E6C77CDE3E7C23AAE0B2F5FDD647F031623497C468C4ADA7C -A6ECEFC0828FF8214FC6C2605626514112B610FCDE6E3174912BD93E116537F1 -5A51218896CB80229A42DC94734B633C98207B81F871FCAE1DA58E4E9F7F0AE6 -318F68EC0C22047DF931BFE6838CF1325D3CDE7E16708C02FDA7F4B85C04B987 -7C51C13CB4DB516EF9E98538208CFEA698F392BCFF13D221B7497195A0D094FC -9E72EDF09FCBAE6C6FDDEC0518E1CB8D826BDCD34C59FC1E82231670879CE2B9 -3E7D5243FABF7CABD16B39C45BB7C243DC390DCF64F899F9537B14005EDDB0D7 -F98E90BD5D778E3EFE2616E93D67F52670BB3F476E21ADBB8FCE74076B7457E0 -4BBA0B06CEA5BB324B30C5F22BB65FA337951FF7F4345A961FDF86CB5FDB3B5C -19EC0187D603393B63186C84C83A82E55C33BD018456156C0CC12AE262F04F34 -8BDFAB8210BA22E314EA054E364844F0BF03BE50426089EC7071143F51776C3D -F19EE3CA885FBAE5E0D4A5334D0E957CFD25095B28726D663375530A635E4B8E -7C4743B67C00FB8A600F088414D8992ECDA0ACC39AB210921930855FBCC2E72B -7679DCDC16C306CBAC3C0663A120E5B34F7EE20EA7A172A1EE0D13C2960C12C8 -1DB42ADEE49AB99BC309CFD51B5644CEB809BCEB184AF69E06BE34187EBF6F45 -6E03911CF01F71E6355631E5A8D5CD2F3B6BF8B78FE5A3E69465E58CF73E5607 -B0B18E8749626DD295BF9A8EEF2D106D587DD28F85833BC375462A944F0C5D6E -2B4C9795FF0B0F87E0ECE86CFC8D7D71D73F8FAB6D0BDCA8250D0E561CB64E84 -8E1A67E3FF6F3C662158EFC73CBE917A024FF406B6FBE6739CB663D0C9922640 -E5FAEF847679EA07ADCF51C43C25FBFF1EC5A742CC0303AD21E70FDFC7D47E8E -426BA2387436930557ED1A11712C9DDC1233AB4ACE7135CF296FD17A81EB3DBE -8F4087D8253365227A41364D01903377F2F0278BE0D7DF9943DED57976E6159B -58DDA467640451D54B35E682993A36718B141979811679C11D5F274542802CD6 -CA4C437B6D4C239EE3692F55D3C3CC2B675E18668A8015EA23B6EDF8679114DD -89955A03E23849A40D2D6F29D27F9F7CBC12FC1AA470E554B9089ED64CFC75FB -F4A1A3D8337A9D4F313854A2D9C050FF5E3072C65B15FDF82C202F68FB700C14 -94CB0BEAC49177A2EC2371EA7AA515534385265044118C801A159351F7A1D71D -0EB50570DF4093E459D3B067823AA3F43F9E72BFB2F77AE2BDFBD917782C5406 -03673D21EA2563994CC49D8A2A947808AEADDC87F23E92CF0C0F7B4AAE346C78 -536FB8F4A91DCCA4817AB4EAC3EF585A8287A6A6A628E5F0A53C78140EB9FC5A -EFB93F761D6ABF9EA3065590CD95903801BE9372B76F1ED79B75D71B9124E643 -BA7B5F6BEC678D080058C0489943440360D8F100890F26196F82F88E61BFBF6B -CC6907531DE5D5CA4B91E4F9D634A9DD0CD8DE6402E94C756F5904A5BC37A179 -A9CC8CC6061ED3BCD51B08C746DBF5D8385AF7389AF4ECC4981D33ED4BC37ACF -BD70E1474BAEFC098AA9BF862F153237B0D2EE97E604F8B41741BC38A0B2403C -92B238FE8A3C1456473B6AF6D8F9FD32421B61440B9209B1484F3276BFDABF24 -570BAA113D0E06C146B8771F399FCD6906310B8ECEBABDBECD1BCF21EC03D053 -60E500F91B4FBB5005D6F4DB331D1B534C15D5C5C04DE155F2808BA11A547E2D -F4B6DC0A2A938EAC4612427490F92ECAF7103F55DFCECAD39E76B1355C8EC989 -124A09FC9090192F78EDC8E54ECEA741BDBDB8EE8CAB4BA00CBFF9BF98818A65 -37CFD9F4302BEC0A7D4E5D770546D77A95D6EE406BDEDC3CDAB1D229A6957474 -DD11AFF676C19E4E328C133455152719E95026D4CE07C8DE5E939A69CB8C5D2B -CC72BA63102A44B92235A1EBCC109CB8ECA42D9AEF2D7B95EABFD64F3EB225EF -E4EBC3FB687CB00513E4014CE228FA3352DEE01A567014F375B77EA45B029451 -D8A8E85CD7E3BC527A5E8C44707EDF2E1DE4D476682C609ECDACEE5B5D9284FE -2FCE66AC8900FA34510A458B2EF57CD2E87527CF4C88AD298083D44FCBAF9B98 -882614B8B91639DDD9E3D1EDDDB2C137C85455992DC331D6117366B3CEDA8466 -071842D5633D709467FD6E44F48C0FDB5528B0AAD26B3958D626569E14EFAA58 -B592DBE04142D9B40377F8DF83920C7D979E78F5B63B54B8A478F4A73B5B5905 -A06C80E750152AE7C89DC2BCC3A8A7EF592C43FD4624D295A761ED5AE94ABB29 -C8B308E10EDB40ADFEABC931078D5C888A85C72451BFD587E73E0491EFBD80BE -B0F1E6D9FA7F3DD52561A1D59133EC64BCF2212C82BE4AEE81CF3A20180D032A -267EFDE0D9237B58A48D0E70C92C0C0CC3C46801689118DB38938E7C88C71CFA -91935C2CD9DCC7ABE8F55C74BE28D669F2B51F31838C80ED20BF83291DE67F32 -0BD507BD5F27A4C92CD5C2E2ACAC4545B4B62B6040C75F99021E62ACCADD7621 -5334B605570F0EBAC7AC6E5E8E7968A8DF189DD604D1CA7D3020551B9189DBEE -079A6D1EE22FBBE1E43BF8D42BB8FB91DD3C1C63E10E99B53CF3135C4553D977 -0A7456BE3ED2E2251AD5482F4F51083C8CE3DD2F9348FB6B78233EBB14550E61 -E6C598AFED884A6DB3B8D7DF288BE2044CEA11F418EF3B2E6294D9C346564B1B -068C623B971047F0612ECB7157655A06958DACACAFACC0C14CD990FDBFE98C33 -024F9D19F939E8A4B7CAE47E0C6F3BD57A2C798243EEDC60195F72DB7C6C13A5 -E7968D7436E5962BE4413BC173A4310DB1D012AE618F4C446D40CC395365B7AA -6480A6764396B5093A02C88DB727823721B19CBEECAE261A6F150CDDF3CFEB40 -4BBF329CB53724772B35F73DF6B0565A305F2C0BF144750E76624A0EA80786DD -A7460E442086D9E463DF4781165AF8D64F5693039903BA8793E8947890823FDE -A641E42C221FDCF6832F3744AA1A03717DB22776B34DD116B9AC17A841A3FB3E -D627822C0BC41544EE864FA8BACED0FA8C1CB1D1576428269DD2226AEDE06CB9 -E2EE674E00B5C43C60D6354340392A8A3A99DCBAE08C2A860AB4AB61C1B5FA27 -37987CC398084B20C56C0F7A46305CB266A4128C800F12E5930201D5E7568453 -B02D947517639E438DF3306F60F35CBEC1F74335F3F39E803BCE81ED306553C6 -6FB6E25837CD62F7B3C573A9547D14998398DEE75CE4ECF0D59AA711AA7C0FA8 -2D9F4F7157054C69EAFCAD5C2BD34DECE8411AE76F6140187B34F7159AEA9EAF -BFF54D43B9569BF69DEE57D2B72B2FFD226DE355C83E4A2255EC3BF88A36CE9B -26674E8A200B2E8BFC959F8436E01B31483D142D318E221E5A40E637D4760E9A -CA70407F57097E56465DD18464CFAE5FA02945D3EC6C45DB6472A2848EC98A66 -301C63A761A9F68A23A84A9B01BCA1999AB48318D5556DE86B286127C2FFBFF8 -EF6ADE0D8535FEDD63676CA4F2F50FAC64B620DBE16FA0A7BC9F964669ED7E35 -B6A9B87C893D96B275FC589770AFE82CA0FC9A5968CD514B778C21F99DEB59C2 -1B3F75AA347B576BAA32CF97C0EE9B422CAA852F900212166F0B9CF715F820DC -FE222F55980C61F3E6ADB2D6E6268DCBDC2B74A011B41C260EFFE4BFA189D94C -6ABEDC2FC79B8F0807F123D1D928F85775DD2B281C50263E87880A0E60A015D7 -3D39C6851D7BEF1E7E0626F4F2579DE80238B932AD5F578D5BFDD585AC3C5BA1 -4D013A681B9131C473ED99A248A0B08283A4048B9E5B1A9495389F05E35B9C64 -525884AAB12E5A8E058D2E5CF549B11BEB5D084A38CF6C10D393F6BE73D6AFB9 -7B2BDDE416711F63A2A06F5ED3D3D065CC139F5392737F59801DC1A2F6B3E712 -9EBDE49DD68F804EC60000F3A858182E92DE46DFC5CD036C85613FAEC9694DCF -96A2D8EA8FD5A497406713319809A919BC6185B82FB2BA05BE0D69B7FF2EAA8D -7448E5456C5F241D43517059117587BEF12511472050019422E6CBD2013DC2BE -5B0A099545DA84C8CE959718ACB689AE0DC3C9E96497A108732218BF8AE2BD56 -5391BFF57D1F2831B9418AA5FE63608D31EE37361272BA669A7534213EBB09A3 -0065C49E4A8EA4FF40181205D3109ACEBBDD8DC9D46F4560BB3250E43320E567 -C76836DD711AEABA26BEF38A4244673D1ECD3F13A10C2C3404C823F45ADBEA56 -3373BB5C4BCF08FB8F20A8D6E05561381D6ACA2178EC37DF744FFAF9E8E1C2FB -A039F33BA035EAF2EB4D4F928274947A0D296454B3905B931C1A3822302A93FE -D5131A8FB03BDAE23A1B5F0212F57292C4593480C139C56235696CDA7673B14F -465C951D2369E361E1A39DDC3492D9C5C663268FC6EFE6D6CD7E7CD68FDD996C -CA3BC0E32FC249A57C095076A7142B57B48C4BD5C5D056083FE81080E8ECFC2B -87635AD52F0D6A52FDC4AA0029BB9662781E7B0271C9DCD0F1F88436C30E5C1A -3919F6BEC574E5B905E36665CE0EEC42CA0DC0ADED2D3A4707EFF4051F584CF3 -321A4DCA23FE91484079FDA322C3421E1F1C9BB5C04338F4C6081426D479F29E -7E819C6C039F2C2FDD140DC5FB836BA352418600AB78ADE5BED20099698C821A -D95DB2D024D995F3794021879225B8595E694ACAA2E889B205CDDCAAB4BD95C0 -0BC24BC520C5DAD90EA6BBF4AB76310B98DFF30694AD15ABB7E0867D526636B7 -EB1F8635A09D3F559EF332201EA72C2C0E752B64DE4CB063DA0E9CB1EA1CCC4A -D6C5919D2D86F3870C852B39A61D290D6E64FF77AE711F9D5631553ED0EE0CF8 -C430BDA64264EC7085DCAAEACBD2D5BD8CF74157793A1AD75D3DA2912B58BDB9 -D47FA8355AE7893F2E316504AFF0787342BA28B5412C5B2C92FA1E1011D2227F -52700351C0660CD64240E6A380ED7E532FB9DAF37DDD353DAB7AA31F005DD9F8 -3339C1EE6D184833619538C5FC0EB09CF161E8E0F7BDEF34ACDC2A7AA7DB91B6 -6D70DD3C73BFF9CEE0BEF6D6EA61ACF225E8E3768368C638D2C38B81E234A24F -2822E61F61D2BAB5D42222AD8BDC75CE1C19459B4AAA49D8FB785CCA4C1779EE -33D7AB8159C41192AB4E5F6B9217171746BA9A3147D40231B32C6D8C8857ED2C -A5E5653B2748E64AFAE309794DFCF61CE1BF97A7DA067E6EB443A41C68CFB47F -1FB598AC5B411F2145769D0EC1CFBEE2C4BD4036E8CE214C5B9A91BE8231B920 -7CBA80DEB3029701E61C53DF812A8D4CE9ED206E044B38D0F0651BA2B0D57A65 -4D5894C0E934634242420E015F34F24F91275F3B55C4CC76CA06CE07BD0C014D -771070FD248C2F836AE35E2F5BFA2B6EA04983C5B0804ECE338147BEE6BAF694 -3CFE3E50410A29D4261FF9B3506B7BE83292D631232438B231BC45EAAF35AF60 -CA264092C9A1F30E72EA7AC1A47BDEE830F2318A4F450B6FDCB610BEEB2B2415 -4054F4B96962744C23A99EEC2946DD3C27C52268A8992061C746ADF78E34464C -D0709A4EC946CA29557F2651B62D4DB764EB51AC8D5F6A9251C67C7358660B64 -AEF35020BD35731EA2A3A221E678F222A7A18B35960BB11146AD42A3B7755432 -4B8E399C9C73190D55DD532A42C806E61F0376D139733BF8C95AF47894F96C55 -C13371B4C23DCE32A9D669F42F1EC62F5B7EDADE0E43E52AD35E64FC2B63419D -6962C4EFAE49EE0171469486A071E124FC152281D42907863987B3298CDAC70F -40227B7EB91B3D2500B5B52C67B0E1C00C00B0FD1C32A31A637488C196A45A68 -0796214B5C292308A510AC9F9835829AFFF1D4F0F5070C76BB4D62C43C787EC9 -64973716583C3E56CC26D9375AE76BA815E179527D41B08AD9A4799FF43ECFF8 -504FF729101081E8297B63FD3E2E4A8A60C2187D56E80AD9BDF773C9DBE12022 -D7EED3406C5461A0079837A953A5BD6D856E10CDA9DDCEA668E1A9EF548EAA7F -6323A2581C6F2C3CEFF7AA95990FBAF5CF3C470DB2103A8F613182C40EC2C25E -83FA8BC39B49E89FE2E0F88D1004EF1793D5F1D5FBD7D13CBB8E8314FD2271F5 -172B4F0663471BB39112E022156BF755AFCE5539EEA584B38CE90110F5AF981D -E38F3C9E0DB13471A69F190F01623CE560631E543D8DD4CD8BF7E8067E2B024D -7844BCB9367B9E9CDF6AB1E051AE7C6AF8BBF0279AB76F91E3096A9B596CD481 -ABC06548BBF56D87D68CE8F73CFE1658015612D08B09F9D8A8A94224F3F32306 -3A488EF579B9B01F5A20DEDB30461F036C56909A76FA24584B58D1E791DCAB19 -A2B879D6CD08433F7B143C34E12E5E6A017FE5A3CED564851F500A2FEA591A73 -1402ABA57032E377E88E7D5F7B7667356873639B6576A91EC449679D8A2CFF11 -5F06B9EE2AE1F2BA2F2EBE3C679375FE9B552B3387B840DE370E5BCD403AA781 -95747DC5B54070B274F63E4CC7CBEBEDECC026F1BA45E0815EA806168B4FCF4A -561B540AFEBF5F20E7900077D3B8B98E2B30542DDCCEF75D31523F6DBDC925DF -A219AAEF9050643026C49FF555FA2D545ABCF0C0B583DE9096EF351817993010 -A6775D37D4326001B6A514581E2CADF0E90A49D0FC594E77491EFE76166023AF -F60B0EEEA9BB4FE37C94C79E4AC5089579CCD9401601BB88842A46B8A889A53C -5AF0DDFAA07309D3709E9B04808E52B65A85C85D4327A70981E43AEAAF8510E4 -56633D257C343457094A59410F99ED970EF0650530C9ECF94F54847686F21E79 -5E02D132E45F1F430CFC5D5DAD19D075BFAA38699EED9C73276EA7C381A03B1A -4162806EF6E13969EEA1FBC89966B0745BDE1114CE32DBED470F4751DEC36D38 -BB1BE46E7E162660DDABA0A9B1EC983DCC7C914AFFE334D658FFF5064A01F6E7 -E23D4955DB4AFD2EA0E371F003E68957915893DA2626780FD111EB90CEDB2BF5 -CF596382A55F28C43A525E461C8AA9744DB5820AB314B0183B48D1F801509825 -FE331F9736D366BB658CBDDF6A4564DA618DECF9CEE7EBFCF1544B1EA1746C51 -2E5F7B3A2B2EFCE6C9DB26011523FDD6FA32FC3615CEF4B0739F659D03AB26C3 -21728BED1BD965BCF894B654D352B12254F6B204B27611BDD82A2E2DE60CABD9 -6EE36EB6D6642D7AB158F8AAE1697CA540C2889BDD9A245BA34440DB21EFF755 -15F766B02FB5E6D80AA19982AB19D7F8DA443919848859B103F4EBA3496769AD -496B7E78B3ABD7A95C516854AA97A8F574788729BDD7E04E1D34B640F3080EEC -8F0D6EBD83C496015575FCF9B002BE9AA6BFB7CA9E7CB1B1753B0C95FC9D561B -E47D7A5D5A537DA5970C8792488733A277A1AB68F849553BE06E053567E27E75 -3AD0FF5A5E249AD9208BB26E948FC9BF854F36CFDE63C2C6EAF3AE98D7A09BCA -93A1E1BDB84617D011DA89F90B350F133F387E734E4B8B70D3F9A6959BCD0679 -1914693A5493F7C764507DD95BB903FED1A13289E61AA7CF12DA6D015BCB1E9C -188A823B9B01BDB31F7BDA8000FD5F80FCF92D5A3C199319B6D6863C81C9E0FC -A10BA14F42652CAED0F1F7D7642D2EFD4D92B3E781AC03BA7696A87A4553152A -3520C9ED887A3A2535AA2D1F0CEB1D1DAE0708CA0238DE36AC55C535AFABFCAD -E30CA91A3A09ADDE7D26281310DB8466E18CA33B43DFBD0FADD4B83016680851 -BA9C3CE282ED28F7A200F3FD675D0561FDA731D6AF89045EB5E1F8F9E6C4FE94 -2F0FCC80D9BC10A1B6C884F36DE8ABA0BF508F5BD45893B25FDFA559106B067C -DF54EB9A3063A15F4769C513B146C382A0AE5429D7C7A912F4A075FC69F58149 -B463A4C05CA69B0BF543DE43A11FA9D0B198AF6CAD0743013FA5685EB29C51FB -1CDF0F25D849864B676348D46B843E5AA5F32B5DDC8FD1F583FA666384918A39 -50B7643B713C2CF845999B33993CB0928193BDDA2CBCE235C6AE3568EC3B49F6 -7A85264646A237758E16CEF056BA5582600D0E269A6F7325DFC3AB3E9D3093C1 -352D2D38CF7D20E38297F391D0484B378AD4E52396261EC2DAC5FE88CD47FE05 -1A5ACEA9251468753B2889AD6AD61B70821121DA16A547EA99BECA292D8B1EF8 -0C3F7AEF8B881E2246F7BF6D1A90E9CA285E7B06423A7012EBD1B224DBA27FDA -2F8E96798705CBDFB1DB849C9376689F6BDE02B9121BA1D2BEB3D1C30B03597D -BDC559122BF28348FD4CCB1F0B9761D38C210B8A216937FE2EABBE2E0AD84AC8 -E8A18BB49DE6FCB61DC3F92D56A2E932F6F085A9C40F52F734FF3A19F783DF0E -230D2101AA11F06CF5FA6E6A6B7791A6C8B2610B3CB66355C468A7C9C3EAB192 -6F8BEBABC4BAE93DC632638DB829DAB434D9E6AF218FCD4BE65BE2DF86AAAF31 -E481F80359AFBE9126388BFAED6989F931483CD14FB2500E3233D5539BDE3736 -BCBAA1900D8163F501B178C0C2548434C3F68388B19D376F89766123BB78A08C -70BE85F8EB6955C114C9A7C11CFEF270B8BAD791AF4F9B6AF09AD577C28D5758 -7ABCB4583129FBEC5E8942BD62A39989731469A762EF902C14AD17E47364658F -6E8DD5726F160024D231440727F1C36448FF44C27BDCA082798AD41456B66957 -6FABACD1FAF8311092DC73285C0C6FDD11E974087BF0A987CF8F33A7766C4A76 -6A9EEBD28D7E36FCA5A7C97EDBC62360A960220C495709A4BBC799AE67EEAB44 -D770D0F38D24E8186A96FBFDBACCFFC67BD72DEBF1A055ADB21CEA9098540C8A -D3A2B200963F54BC889CBD250C38065E61588516A25D5E1C502C1835FCD32559 -08B04FD75BC68C7A7F90F1EDBA6FBBD166EDEAECF4756CB716A583D2E1438D9A -679EAC8073EF23B44127922BB92227A57B61AD03E8C128EA41E8E91DD30EE885 -CF46A93741DCA7F351C98F7EBD4934675F4753798615579B28D7367C65CF012A -A960AA3F1D3A9C903EF47A38ACC2434C47E2006F189C10BF5978D7E4978F18AF -382D0A5FB3708A0392A8A87B2FD8C20171DE23BA0C14BE83EB472DF4CC58988F -B0D8959109D88C5EA5DF0BF962109263197A51738A00D1A709F3770C691D5E6C -F66EDF8F2FA2629F59788B7D811083A8071E6E4D7185117661B366EF5964AC8A -AED0F515A063728089FAD3D7586DFB85F0ADBA08517F3C434409300F74DB672E -6DF6BE832D1564C06988DC1469219A24F0233F38C84D721990353B90B2C0EDE7 -9F0C3A540D14FA1B7F1CB74936A7B88321CC841CAB20A1E7A92273596A82496E -D2401D7456AF4234BB36F7819232C4AB06DBE3F97542CEC05B38B6546269B791 -ED2AF1DCB4061D7791F694EE1CCF051590C7F26EE59355DB084E5F609B928A58 -B954BCA3E7463BFE064BB7B3DB09773DF3F0ABAEA53AD56F98D7F7BA263304CB -AF3390CEF90555746B797084CC0C4996B4F30F54563298A69FBB4013184A1F35 -969FF96AE7B3BB247709CB2320A0AD5D619A3E31F49F4CBD03B69C56098A83B3 -E4D837861386A976DDFB2DA2A9472F1559943B9794B761898E7375FB2C55E3B5 -E605C02952C46F537B2BBFA0B3B357340704448363FC4F20F0245A746E9A18F2 -08425531F826E8FCA78866F0402F6D755B39574F57BFFDBB321D435502E0FB60 -FBA64BF650EDF8033A246D8544E31C373DB2F250AE2BC5233B85A1290511E588 -512035A383C14A2B27363E7C0B2E4DEB8E780FA2A4440CB653CEDF4BDA90945A -4AE0D6343D1B646934DA14505B99E522EE55E02E700B018483E6D10B3E8A6F2D -1001021FB17BDEA02A213BE8A3E33D6200213FDA458D25E8713C18B4EC7E4C6F -98DD981863188AB4EF4846717B770FA9D732C0388C411A0C393713CB4B1549AD -1494D73C958F4DE348C25AF9F845535F111AB37A31874926BAD2ABAF1C9FA2D8 -EF4E1EC33232225457B465ECDB466F89BC9DD2A9E82EA7CD2E9BD90403258147 -F3F094D3B7F63B576DCFF5E324C82C6801235D0DF850CC6FF7A070EC92456321 -BBF4175403ADE97D1F62FD6B1358B7DE7473FF03959C0DD8731D7367D173DA56 -170A2F3677A3CBBF9F4D351500860FA504F55FBA655ED5F79AE0E404FC5EA41D -BE1334B65CD93468D3B365EF3406777B6CDEB5454945798E6B1FFDA470B089F7 -3222BFD4002B7F1E8711E4D1865529C2045B7FD98069CD0674AC9DBC7F31C277 -EB88F8BDA01AB9D67611B078D3A72083B6D92F8E96105C15844139424361A983 -4B5CD4BE172478E1320D008E73CEB0B5D7DD07C65EAA231B884F822E613ED7C0 -A3E24E90BCB4DD0E324A38D133A45704E818ECAFE0C59E420FF122CC71D6E96A -A5D5EDD9DBE33296CE6AF62D797F558B884960250F13D11F6DB57BB264A12D89 -88856C6B73202A54E9FDFFB7E3FA7E81B21C734B42B44BF2BBA5E8046FDD40FD -923A00084CC2111107D1B8186CD8287FFE1F26993F7D650D73D3A06C93B4B22C -4C64709E8D803BB9A8A3500791260AA785DCF3300E7BE08CAFCBE64A85711461 -77543E4117B15B1215DBBAFB64CD4D90B606E42DE9EEA813884CDF19A9AE563D -4D506725A2CEB6D65452E8862D0EAF37AE2D799B7C959D00AFA2AE8C0DC184F5 -56780C5EBC3E8AD7D720DA703529CD555CD25491ACA3FE8D9578B07E75FD0F44 -98E43F871FCAD2A3F3EDA423A9A2C41B8C388234C9BB7A7D78AF6E5C74B56A42 -3D8D31EAAFC3CC1BEB1967859EB33DCE2A51B88A9B5F5B85D13C619BEC3F6CC9 -05F02C7C850A341B4B9B4DF952AA66DAB17308CD46913DAC7496CF31A30BB235 -997E8D718C6CC2EBD503E131CE11664F4EBF5A0AC3AC0C3BFB2EA6C221AFC902 -ABE0DCA95B14F26C7CA969199EE72FB6D2DFF8635703C8EF31C1A934D6BB9164 -27C198F43AE7A54E6869E939DE2DBB183766D9F90C7C270EEE0854C72D296A3B -10174961017318135CA16F54C2BB2C422DDA5F -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMSY8 -%!PS-AdobeFont-1.1: CMSY8 1.0 -%%CreationDate: 1991 Aug 15 07:22:10 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMSY8) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle -14.035 def -/isFixedPitch false def -end readonly def -/FontName /CMSY8 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 3 /asteriskmath put -readonly def -/FontBBox{-30 -955 1185 779}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 -7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 -A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 -E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A -221A37D9A807DD01161779DDE7D5FC1B2109839E5B52DFBB2A7C1B5D8E7E8AA0 -5B10EA43D6A8ED61AF5B23D49920D8F79DAB6A59062134D84AC0100187A6CD1F -80F5DDD9D222ACB1C23326A7656A635C4A241CCD32CBFDF8363206B8AA36E107 -1477F5496111E055C7491002AFF272E46ECC46422F0380D093284870022523FB -DA1716CC4F2E2CCAD5F173FCBE6EDDB874AD255CD5E5C0F86214393FCB5F5C20 -9C3C2BB5886E36FC3CCC21483C3AC193485A46E9D22BD7201894E4D45ADD9BF1 -CC5CF6A5010B5654AC0BE0DA903DB563B13840BA3015F72E51E3BC80156388BA -F83C7D393392BCBC227771CDCB976E93302531886DDA73EBC9178917EFD0C20B -133F1E59AA9B568B69ECCFC0900517036FE3D4C09BBFD937BC5A9C0B89894A8F -63BCCA3746BA056D1B408B16E976D7BAA7D0F7693814ECF52D90BDB3398CF007 -CAD14DF246B4D1886070D41A28110F88C9D3EB1F30B1823E0EAA1A35733AD321 -E6338D62C26AB6FCD4BBB703248CD7C5CEE83E0167A63F89ACC9D09117C4D017 -E773665CB7FA79D22231C8F858735B554E2ED612A436D299491FD31F810F202C -C865B87083F980C8DF6A3DD43D437617A69D3E58FFE85F106F7E7F6E50D4D25E -328F7A76B73078B3604C51CCDEAEFA74ADFB9A6C3A5A0EBDCFB578CCBC3553F8 -44D4B2853DC7C8415AE3174A4C2209F4107C23000ECC343882C5E2ECA42D8B33 -F4846EB85076770BD7E5AF795E1EEEFDC5F0229761DE6BA728FA78549D6E31AC -55ECFE0C64351DCC357F619E3771692B7DF8FFD7FAF48B4299C702F866374FDC -696E83BF09BDB1C40B -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMR12 -%!PS-AdobeFont-1.1: CMR12 1.0 -%%CreationDate: 1991 Aug 20 16:38:05 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMR12) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMR12 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 48 /zero put -dup 50 /two put -dup 51 /three put -dup 74 /J put -dup 80 /P put -dup 87 /W put -dup 97 /a put -dup 99 /c put -dup 101 /e put -dup 105 /i put -dup 108 /l put -dup 109 /m put -dup 110 /n put -dup 114 /r put -dup 117 /u put -dup 121 /y put -readonly def -/FontBBox{-34 -251 988 750}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5CF4E9D2405B169CD5365D6ECED5D768D66D6C -68618B8C482B341F8CA38E9BB9BAFCFAAD9C2F3FD033B62690986ED43D9C9361 -3645B82392D5CAE11A7CB49D7E2E82DCD485CBA04C77322EB2E6A79D73DC194E -59C120A2DABB9BF72E2CF256DD6EB54EECBA588101ABD933B57CE8A3A0D16B28 -51D7494F73096DF53BDC66BBF896B587DF9643317D5F610CD9088F9849126F23 -DDE030F7B277DD99055C8B119CAE9C99158AC4E150CDFC2C66ED92EBB4CC092A -AA078CE16247A1335AD332DAA950D20395A7384C33FF72EAA31A5B89766E635F -45C4C068AD7EE867398F0381B07CB94D29FF097D59FF9961D195A948E3D87C31 -821E9295A56D21875B41988F7A16A1587050C3C71B4E4355BB37F255D6B237CE -96F25467F70FA19E0F85785FF49068949CCC79F2F8AE57D5F79BB9C5CF5EED5D -9857B9967D9B96CDCF73D5D65FF75AFABB66734018BAE264597220C89FD17379 -26764A9302D078B4EB0E29178C878FD61007EEA2DDB119AE88C57ECFEF4B71E4 -140A34951DDC3568A84CC92371A789021A103A1A347050FDA6ECF7903F67D213 -1D0C7C474A9053866E9C88E65E6932BA87A73686EAB0019389F84D159809C498 -1E7A30ED942EB211B00DBFF5BCC720F4E276C3339B31B6EABBB078430E6A09BB -377D3061A20B1EB98796B8607EECBC699445EAA866C38E02DF59F5EDD378303A -0733B90E7835C0AAF32BA04F1566D8161EA89CD4D14DDB953F8B910BFC8A7F03 -5020F55EF8FC2640ADADA156F6CF8F2EB6610F7EE8874A26CBE7CD154469B9F4 -ED76886B3FB679FFDEB59BB6C55AF7087BA48B75EE2FB374B19BCC421A963E15 -FE05ECAAF9EECDF4B2715010A320102E6F8CCAA342FA11532671CEBE01C1B982 -4B1CF704E817814FF9C921A7DF8CB8898733795DC5382F10417D349D3A7D24B7 -E093F2E23BA2C1EE337477E6D51957FEE9206BF92BA12FE5ED4056C4FAB42BCB -B9E96E640C88DB1810A0BEC0F3E9F4BF00E642ACEBEF5781F8E57F9B9AF15B57 -53572D8E00BEB804C5B7587FF816874FCEE012EE5CCF317AE25E9B3A801A805C -5EA4B24EFB92E54CF85F048BE9DF31C77AB6132EBAC1C124EF5C0DA0719EE902 -BFB550602C5A8EA7E31F72207161530AE5DE53624E60A6383DE04E085E20E328 -2D3B8009E90861D7309BCAD915694CC31FEABA2FB3DFE8E2C61DC65AB2FEDE93 -02327D5B24B0537DA1B1299C9F8D03D6A10055CE522CE067381FFCD4D1E3E173 -21CC73B94423D2D44E035E1CDB53846964AD93EB1EB99E6BF51167EFF6A4E33E -71277273918B7F4FCCE3796ACC9725B293CDBF517885C38D66DDDF8FE9D5C98F -771EB2DE9C0993E84AC0486F9361270031C246BBCC721E2D872E45230BFE7B8A -1817A8FAB0C82C2A5B002C9208FD316333C451D59243D312193F38FE79731FA2 -BD4FE2DD6A3E4B4FFAABE064F8D2D97628C9FB2428BAAEC5E2AEA4BB1D609B85 -2394287D1AA46D8E4B4018A4877F03F6A9E40277EA94C462404537694208AE33 -45D7AB349A1916683BFD35479190FDB8E8E1E5F4E5C61774A1D966928E7AE59C -301D1C7D41DB96A94C23F41A650257297F87E726155BE35E84BE5554D97137E6 -C0DB7D48CC0B5D6A78428A63A3E594ED30A6F33D6FACD6CD77F69EB2AEDD6767 -403F5069AFB93BA02E40A13E9A5899EB68B5FBFB655610CE2FFFD76F0C7C6595 -0D8F7BAF05232E793BA4C8C0A8AAA682DFE3E4F4189F9F9EF5785CCFDEE5CA8D -E5685C89B52AC73837BC5C6712E4B8480D7EBAD4F54755F8BF549F0B6DEB32BF -7B8A98295BD62F14921F80D98C79BFDBBC84C6EBCDD598B54BD790925C72B0EF -1AE6086B1ACCAE8F9BF52C0AF6DD5FC38190A1457CEEE48DC5193DD6EA1A526F -3EE4CFB5E5EF88A803563D69A720ABFD9FB3AA77CEC8E29F49A9BFADEBA19588 -01D88B45D250106F673D7A3F42F0F2539B28D0E6C57DA35B38335DD112CFE6BA -D78289AD0B51D642BA212114C64432B8CD80D899FB60BEC1B2887E8AB5E48C58 -91D0D4D559ED781196599006B2E3846D836D80DE176660DD8C9ACCD72883B2B4 -77D9B991777561D77975456E8D4A7E2ED85FCC0884EB9553A7CD37AB92CE1AA8 -009895B4AC7B00DF43FFBA9D96EC702914FFEF294C865B63B2498A54C97F1144 -7CBD4DC79C8BD47984A4562F8A6AC40D8DE955EFEFCF78BC66CA604C96161251 -420096A2264D7E22B8A3869839FBE8C8CA10082B0253E205500E7F47A03F027A -C352CC0FB38F71AAE11F452A3560C63C844018619594C9DB2238162C23083DA6 -22A2D92896B83272BE70340A93A08E15834C338077D933AF074372E4B2156190 -992182D6AF62272AF7A9C80573D40E5BCD630AECA44FF51531F0028D8F38C91C -0421996D04B5B8FF3FC6435698633A37A84D2C39DF003CB018596F81639B3E86 -93CD0F84B1934BAB24DCD0BBB3917E0B44FD109DFC2E437B0B79D37EC708BE69 -09DA3B6B9F007B793000AD17A7D351417B6F26E02AD4A6F8BFE1A8C4317F8318 -910C5024C8E2C03AAB963055C22D17764C9CEC7DA42FCFBC586DF4F27CB97EDF -91E4533A3151FBCABBF65E59D990719D9282F3CA8AA92D63E3ADDE7A50490CE6 -FB007A2A55050A249D0F8A9072F46C99E07FAD9D5F4FC3C8C8B22F6303A1F66A -2F6F1309A9634760C3FE022D0F409D8CA59708FF8E1B719D93385CF45DBF0163 -07A656241714503F4B36710123A458BA644307D21FB127E6E5C58BF02B61EDAF -EB501080C38A3A8FF84F44B89FF04D247A332B271641B51A7E144437C3061D27 -7696FAC42105CB57EF8A9CF333C47A421DC932A6B43D9CCEF85A3411ED5864F9 -B298D46E912BBD32B6786E022BAF2ADC7AB7F8BB0C6620CC3214F537D5566B56 -3B231615570AF593EE0549761DE550811271E1119CC8D243CD0471A77E7E0EED -D8EF19FAE8BF32CAA225305222253C92C38DF2DDDD7AAE446D5458149A190122 -A0191DF1015F768D48F3D2178E0C23E1F10317E80302466303A45615A3407436 -DA93795EFAA90933030021B6AF5E51D192A3DEB83BBA00736D34F285018980E7 -7ED75E6A08CD036B7E5C23C26A2E830B3C80D6CC389D9CD1B2771A87DE65F364 -724E7D38003ED421540C5913F7B9011A60FAAF2B8A1A5F23ED9C52B1E109FC76 -5C7B5C32328DF9F5568559B6ABFA3027735330B018A1608420FC7ED24A2E15CE -1FFD450A6F30A96B2DFFB53BD7ED444082A11B56291BB7D4314F341BA50E7D3D -F9B3EE0EA5644811868C03108E15A6C7205DE872E64E2EE1236B93FC2F67FC40 -3BD90F9D5F701AC1341DC7B4CA23551EAE479E1E157198A9F9D769CA701C2F81 -0F6DEA36D65978BAD6982DDD54064D3CA2EAC8A92D91C67CFEF3031133D30516 -544A4C047D0FAEB451C84DE160382877F7CED5BAE8B0E35B11CBD630999CF4C3 -DD0563183FE38F2184BB79A1ED8D8CC73F69840672CCA0691EEFEBFBFD7FE954 -ED86CC20598988A79B18766DC512F900775F2822268948701F4CFEF2E401F59C -7F256EFCBE807B84ABE4897D2AF421A1414DDE91124C371DC0A3353B0101F4F7 -B1C420A1E72FD9264C626749838A3B708280E7920272DEEF0AA8DA45E0770540 -7E86D3C94486AFE3AF466912059792DF482CD577F5C3787262E3ACE8DC9DFE54 -96B92F4B030C162FB06E5F27B1CF0AED009EEADCA116694B39AB4EE9524ABFD9 -617E98ED071E7E73E7F44005CA35363BD0241BAF45DFC2E4F667A21F9E9BF405 -B8E36DEAC34CAF7FA7A6CF3C8BB6AB36F95486824D732818BFAAD9BBA4D455DF -E36539DB08E528CA3888C1C59A2A85E0A2BA4CD7BF5C3543B65512BDB08FC111 -A2F6A057955C6F707EA439C2AC6C4FB384FFBA470D94EB2487E9801A6AD0B852 -557344D11B32B75400EA521DAE97403E8944C3F53E8200CCA04025633B999B82 -443115C1FEC7B23A88C01B6CDDF535D284641D2907E108EDD2DF8219B08FCE78 -13BBAC3F7AF36ED59F7749B402731F5B5C45517794349397506D893133AC20FA -9638418357ED6BCFBB08D8397661A3B6769A2B3F9A3884977197EACAA0B79F69 -7FA986A578B631B64D33AC14946654E88165BD3650CBA76DAF505353AA5903E0 -25D21068E4B22A9225A22DD8B1C543E24E3C899F8A23326BA8E47725F0566DE4 -F8339574973D0E332853E558CEDB98EDB1E5974070BA39F770A206753178048A -63FD85278038789231B253D8AA40DFBF9F9BD4C6B7AD7004411947DD57ED4136 -27746F0D7FC2EDEA705DAD77A20B7DA96312CEA8FDA0F0BB2372E6F3C40B6A21 -0877D53D9CBF2EE9655C72D71F98268DF6F5DAF50992E161B2AE95BC12C395BF -2514307964F9A0E0F2F9506E9CDDE5EC3E99B73C3BAC69A0B57FA2A326D3BDEB -3781BE127BEF9D3F5884F21B91491762C545823F756301D0969E74390361D073 -C370C66841F77D1D24E00B582DF2AEBD4E100252248C164DEBFAD4BDEEEF8DC0 -188C3ED0AE0F97BD176527B68E7D2A7955AA0675A639A42BF5881C282A03B5D9 -BEE37474797FFE8B4A1DF9623D7EBFBC7DEEA4AD3F1166547B3F32AF680B9500 -1C86D08B4626E26E5C77B1AC7B0CEAC99BF6EED52519BEB561FEE2CB0FE9576C -B194B32896B832B4388841C92A80685DB51D72274938 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -%%BeginFont: CMR17 -%!PS-AdobeFont-1.1: CMR17 1.0 -%%CreationDate: 1991 Aug 20 16:38:24 -% Copyright (C) 1997 American Mathematical Society. All Rights Reserved. -11 dict begin -/FontInfo 7 dict dup begin -/version (1.0) readonly def -/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def -/FullName (CMR17) readonly def -/FamilyName (Computer Modern) readonly def -/Weight (Medium) readonly def -/ItalicAngle 0 def -/isFixedPitch false def -end readonly def -/FontName /CMR17 def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] readonly def -/Encoding 256 array -0 1 255 {1 index exch /.notdef put} for -dup 67 /C put -dup 70 /F put -dup 71 /G put -dup 73 /I put -dup 79 /O put -dup 81 /Q put -dup 83 /S put -dup 84 /T put -dup 97 /a put -dup 99 /c put -dup 100 /d put -dup 101 /e put -dup 105 /i put -dup 107 /k put -dup 114 /r put -dup 116 /t put -dup 117 /u put -readonly def -/FontBBox{-33 -250 945 749}readonly def -currentdict end -currentfile eexec -D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 -016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 -9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F -D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 -469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 -2BDBF16FBC7512FAA308A093FE5F075EA0A10A15B0ED05D5039DA41B32B16E95 -A3CE9725A429B35BAD796912FC328E3A28F96FCADA20A598E247755E7E7FF801 -BDB00E9B9B086BDBE6EDCF841A3EAFC6F5284FED3C634085BA4EE0FC6A026E96 -96D55575481B007BF93CA452EE3F71D83FAAB3D9DEDD2A8F96C5840EAE5BE5DC -9322E81DFF5E250DEB386E12A49FC9FBF9B4C25C3283F3CEA74B8278A1B09DA7 -E9AE4FBAAF23EDF5A3E07D39385D521547C3AAAB8EB70549756EBA8EF445AF4A -497CA924ACCC3DD5456F8E2C7E36946A5BF14E2E959895F7C94F49137256BE46 -4A238684D52792234869EAE1A6D8ADF4E138B79472D2A90A6CA99E2394CC20CD -3841733046175B20CEBE372327BF13428EED6A3E2FDF84C2DBA4B0AD584EE9DF -B51828D3B8F385846158C29C9AC3496CB9692DD10219697B2ED4D425C3957FD8 -C4600D76E045C561216EF05D38177243C314877A69A1C22E3BEC611A2EE5A216 -9B7C264CF6D1839DBBD78A40610F2C0D7C2FE09FFA9822FF55035AD52546970F -83EED2D30EABB1F303091EBC11A5379B12BB3F405E371519A53EA9D66174ED25 -A2E55463EC71A97BE4C04B39E68112956117C8252DB6FB14AB64534B4BCD568B -246DB833982B38CDE7268BBF74B6B0C18091E1B1F87D32D66F4DD023D1F10D2A -7736A960F72AC01F733A11023832CD68FB6288A5977743F781214D8FA9C0C3F7 -80001321D4397771F728FD9EE57CFE7D9192B887EC883EB1505068261DC40089 -7B7D2820F06515CD74513521F6397FEAB3AD3572D9A8269430E407E357422461 -1785FC2782047F4C0339D79B16862D939F3A37F78E4E2174E4FBF132539CB760 -207999FF86F6A3EBE48EB0A1CA635450FDEEF79EB16D853F3BF4B4156F735FAF -A48459456EC1B4D72FF323BEC9D55791F10081E94A83ECDDEE2A3911BE6690D1 -2BEDC34E7FB692B36A078DF52E761DA5BCDFFE8C6A64B6E6C633D4656CDB0CEC -198EC18DDD3031695D98888F72AEECD5CFE83260790707C3B471C17575127E2B -4BBAB487E96CEB7AA9346CB3B0C577D55226E44493EA8325E60BA821D9A6A9EE -0F81F3B3B43F30717553D92FE2F68BDEAF47C2C333F2889BA57F977A25424887 -F947351DA7609E7D8D22C4F82415A63B83984B040C4C5944C6E36BD9898B0B18 -F901B49A3FC5DA8D8DDC72210897B71E4D7DF418A7880B9B174B2A4F328DA7C8 -FAD975E5657AF208A8381491BB159576CA96B54D235E6DB1FB320202DE6FE50D -7222DF9D4B745AAA1DC99D233ACEA2308CA87B7672F3057D3AAA3B8EA845F953 -404C98E0985BA0BC8B6821F0089F6DB6BADD771406884672C9CEEE3E3136A32A -A9DB459E705E041D98756ECB474D11BE8BD55ACCAB3C167B1EA11B7ED5AE6694 -91197E9FB37E6AF997D1FF15B186505830789C19821DE5DA62FA888CC2C5AFD3 -C0A243E39C48B98F837C87730BBB9A03E8BBDFE260DEB47822BBEA03C0F21FEA -B644B1CDD2AEF52E5F2494676DEDEACD9ED89E2FB5FB5FFD14661A8701680FDE -F27E716E1FB901227058A4C5C7CCCF9132D643409B46D6AC86828DF63FD40B8A -5D22F0D9B6F00216E3BA318C5B9EFDAD04FD6B1677A5C2A3AB503A436F6A2F55 -EE37E9643259976A0A8425ABF863D4C66257E086B6F7811195FC8B20103C40C5 -0329309E5C45253372762CA78ADF69AA56B3D642B2D5EAA092369865A2BCBB34 -00E9924E31833320B636719A514B977F00261C4F782F63E3CED4B7AB7F58A685 -6E529975417F43F801C3205449D4B95B2B1FEFBF1442F33B8A570E30350DB2D2 -71CD7E333032367CF335B789D81202E1FE3CEA11382E5BCE751C51396A99FF9F -085D4FBF967AC8452EE633CF741011609A2DF3EB88A35DC3D8B47D1FBDAA8FAA -01EB756739B6AF9462DA13B3CD4DF3DDEE6E682B6500F2BDB6540E7EF295BE67 -99D2F86B5A1EC89F20D88DF00962606E0BA15A6BFC772C72E50D4D67DC4B71EF -A94FF2339E9377AF27A92BB8B9011338410D30CBCA33C5C90D22BC6C64153708 -8EECF6CD2AB2143C6E19F865B11B561B28E5BD2A9271CEB846A588BC34784074 -90757581B8DC08CC8D75184991532E9F0D3EA2A142213F0EB8DE2BFEA732B77C -4D854AF02B92AB046123EA0F96544A241BDAFB02B2A9095C342945468C50903D -8E6E8EAE6E72B8F4946DE02DAB91864B53359AE741F095A9D118C42DAD62BC01 -DFBB386111F9BFD37B0E8BF85708EEB1B39CE3935288197A5658D74AF4B0E5BA -AB39E1B33C8C7021680647E6298B5976C5E7E5A41C478A07A6DF0227630FD1B1 -FB3E5E671177D2654598F3EB5393202CE28559AEABD64E343A18AB1664472080 -6626EA9B789FC0BB90FA1977514D3C3848163C7CFBCFEBDE0F62C184F83955E4 -9306CBE4715809D6789D0A65522229E6D08A139624932EA705229EF99E243DED -E125C95EB549BBB9D91B68CD1438EB23BAD1C41762973DC781F324672C3AF537 -706A63CBA3090575530CBE5ADA9658C8AB664E475D3F4E83308E82E256A7AD95 -E323BB6A94CC0ED154304EAE95EC4175AA24E44C2257B471F14CA9CB6F57BB4D -445E256BA592017F89D45221D3B33A2617C680F5E5292AD80B62DF74195F0FD5 -751BCAA8C8D62E0F81AAEE4FCB75A2E12C9C396BB5AD47207ED46FD39C2F03C0 -7BE1A50F88BAAA4F639A5DB9807524DED9AEB5FDD9853308CAE5CCCA1D686F7B -65F742D0AD1784A1BF7464373ED630D9DFFD90DE75D664087BED3FB64002FC09 -D608A8FB8BEFB9826A20616FA062B878DD536A6698A16107C2BAEAD4DC4A1F9A -762C8BED80715A1CB9280B59C8A239F93817DBAFB78877AB8EBE6D0E06CD47D5 -40DA9F1586B227F8F0ABDBDCD2CC96EB61021726CA1C64F06FE173FDE1BFEF53 -FE922E4EF539F2F608C745DCFEF232F9E31E4422CC7D234B4199570EEE1A851A -48CB3C0548E5EC973642C70F2341CE45CE1CEDFF5C9CF52E6CE5AE642F20FC76 -42FF3636B821A9D200D4917E649C851B79BB6DB61B7BC1FA5DF3574AFAEDB447 -F67057131C96B7453F879D0FE8AF4D5291FA4037C4C76CA7BD6C0D9181EE09AA -5C60C008E8A7C4D15748CA6F6FD2B7C6A55CBD816409299616FD4153EF63E121 -BDE077D2AF5D2FAEE8B6D6004EB569B398A3ADEE957B2003F524BA8DC248ACC3 -9A813584955514610F5ED6CE54ECB06FEAE5638EE92AEDF446D23CB3F7F3F580 -B11145C03146D73FA56920AC873813CA164089B9A6C19BAE482B8C94726EAE04 -2805019DFF8E8F648FAA35EC7DB1AE3DDAC526ACE937F1DEB3E165699BA5879C -3703AF8BB30CE970E961B253024F82E73356B778BA2B52EF8ED83840E58F35E9 -2C3864F74BB81FA96462393371827A3A495F7863B511080A6BEF0F358FC74C3A -B69FE66AB8883E2146B42F2B3830F81A320C95CA68A39D7F477E44DBD8E2479B -56D0F614BBE4CC4601C878C8062902FE58978C9C5AD39A6D1F994ED4D0924522 -25B011B5FBB553DAAD10CF3A6E26D8DD05F4844028D27DA0838BF0B2BF1B911B -7767E654A897D1C8CA4CAF8350986E853539561E927BC1A080AC4B469B78ED39 -A69B5DC9B0D574BDF455EFC6BFA57C51052EBE883EBA245C8CCC570937436480 -68BCD6219DB49CD850B41F40829C6F371A8E30249339229560425E452648DC34 -FB7F26F92B75C9041F39F535B6755C957008118C634EE6D9109724F0AB20394C -15EDDE5EBA22D8C2FB8ECD7DF64213489A9BE1C7D7349A7564698908F31D40FD -801744BB39011DD455DB7E8D5DC9132FBF394307B6CEF020126C27D09C3B8A94 -A48F670A18629AF96288C661284F0255A738E5878D18C0935E5C8979AF0DB055 -E40A1E1B43C54743CD0C580CC8816FA290F5607580701433E7D3E478790E601E -3C9FD14BBE364AF5B74709EE37917F2B951A8CE286168981D1C7F47373E2F890 -48EE22E3DD583A4FCCF20C5EDF82913664C528AC123F605600505D2A5081EBEB -CD70C429F653753449900BD5CFDC00DCDAFFD97DE63002E1501799B7DBD221AE -D0CD6AD33125FF1FAF59CF8B4D5E198BCA1C979440C2F9DE7D6C6AD842CA772E -2D8F9F65B1DC63CC3C491ED6AB32E9A215B0A769B44EA1CAC6CFA0E1510DE47E -C212486745C14DF4E25EF7BBF691399099B7784329906133CC5196E775FB118E -7B7B0874E7ED63D09BDF212AC3539D13AF2502D417C91D8B32BD547E1D9A6A83 -DCFEB61AB6685EF508C4C2501C2595E34ABA0591E6EBBA8CC280EFF9A8E98B41 -11B7719DAF2D47900127DDFE0C8E53175F7A47189AFD3D2EB44A7999D7121F44 -14A52FDEEC074C08CAF1DAE24CC9409E49E14D5FEE182733A7034293193BEBF7 -DD577E6BF8849F541785363CA81DADDCC5F647FB2F9439E6A235E191D56D267C -75BD4FB3A4DB698C89D01E0F2FC151C5CE77C78ABF166532E506AFDF95991554 -9E0A103B5059038358CB5E6CAC08201D62B319E2CE16EE236163679DDA3588FB -2BA260BE394C947BE83F2E6355A05A2AE2BB83D857535A75483F247028033D64 -EF8657CB9C0ADB35721ABF0120E94750DA098EB448506BABADAC2E57658F7B35 -991A4876C41924F45B24D28B9999EC06AFB581A49E2246F19B15CE492F318AE3 -364C07D85229D41B91C9156639022FB0845E8E7EA20C1D3E48824842010550B6 -4A60DC177B7D081F9FDF00E739C9EEA814A0B7A9F94C67896889367B21D4B8B1 -E4916222E5FFD7B01001201F5B820597A872BD8C273EF291D10E1CB3C1EA2078 -698B93975D06D3CFDCA014E72059873320E6B3601261A976125F67 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000000000 -cleartomark -%%EndFont -TeXDict begin 40258431 52099146 1000 600 600 (quick.dvi) -@start /Fa 149[25 2[45 45 86[45 15[{}4 90.9091 /CMSY10 -rf /Fb 134[59 59 81 59 62 44 44 46 1[62 56 62 93 31 2[31 -1[56 1[51 62 1[62 54 11[86 78 1[84 2[84 88 2[88 1[42 -88 1[70 74 86 81 11[56 56 56 56 56 56 56 1[56 31 37 45[{}41 -99.6264 /CMBX12 rf /Fc 129[48 48 48 48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 -48 48 48 48 48 48 48 48 48 48 48 48 48 33[{}94 90.9091 -/CMTT10 rf /Fd 139[30 1[30 1[43 38 43 1[21 2[21 43 38 -1[34 43 34 1[38 13[43 57 3[58 5[58 60 50 52 1[55 1[58 -20[21 44[{}23 74.7198 /CMR9 rf /Fe 252[32 3[{}1 49.8132 -/CMSY6 rf /Ff 132[45 40 48 48 66 48 51 35 36 36 48 51 -45 51 76 25 48 28 25 51 45 28 40 51 40 51 45 25 2[25 -45 25 56 68 68 93 68 68 66 51 67 1[62 71 68 83 57 71 -47 33 68 71 59 62 69 66 64 68 71 43 1[71 1[25 25 45 45 -45 45 45 45 45 45 45 45 45 25 30 25 71 45 35 35 25 71 -1[45 76 45 25 18[76 51 51 53 11[{}89 90.9091 /CMR10 rf -/Fg 134[55 55 76 55 58 41 41 43 1[58 52 58 87 29 2[29 -1[52 32 48 58 46 58 51 11[80 73 58 78 1[71 79 82 2[82 -1[40 1[82 66 69 1[76 74 9[52 1[52 52 52 52 52 52 2[29 -46[{}43 90.9091 /CMBX10 rf /Fh 135[71 2[75 52 53 55 1[75 -67 75 112 37 2[37 1[67 1[61 75 60 1[65 11[103 94 75 100 -1[92 101 105 4[50 2[85 88 1[97 12[67 67 67 67 67 67 49[{}33 -119.552 /CMBX12 rf /Fi 252[35 3[{}1 66.4176 /CMSY8 rf -/Fj 134[51 3[54 2[38 3[54 81 27 2[27 3[43 1[43 1[49 9[100 -6[66 5[50 22[49 49 1[49 48[{}16 99.6264 /CMR12 rf /Fk -138[73 51 1[51 6[70 1[36 3[58 73 58 1[66 12[96 73 1[103 -1[103 5[47 1[104 86 2[96 67[{}17 143.462 /CMR17 rf end -%%EndProlog -%%BeginSetup -%%Feature: *Resolution 600dpi -TeXDict begin -%%BeginPaperSize: Letter -letter -%%EndPaperSize - end -%%EndSetup -%%Page: 1 1 -TeXDict begin 1 0 bop 1125 937 a Fk(CFITSIO)44 b(Quic)l(k)g(Start)e -(Guide)1625 1190 y Fj(William)33 b(P)m(ence)2277 1154 -y Fi(\003)1666 1394 y Fj(Jan)m(uary)g(2003)120 1916 y -Fh(Con)l(ten)l(ts)120 2120 y Fg(1)84 b(In)m(tro)s(duction)2897 -b(2)120 2324 y(2)84 b(Installing)35 b(and)g(Using)h(CFITSIO)2080 -b(3)120 2528 y(3)84 b(Example)35 b(Programs)2601 b(4)120 -2731 y(4)84 b(CFITSIO)33 b(Routines)2603 b(6)256 2844 -y Ff(4.1)94 b(Error)30 b(Rep)s(orting)25 b(.)45 b(.)h(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)174 b(6)256 -2957 y(4.2)94 b(File)32 b(Op)s(en/Close)e(Routines)58 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) -g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)174 b(6)256 -3070 y(4.3)94 b(HDU-lev)m(el)34 b(Routines)86 b(.)45 -b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)174 -b(7)256 3183 y(4.4)94 b(Image)32 b(I/O)e(Routines)80 -b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)174 -b(9)256 3296 y(4.5)94 b(T)-8 b(able)31 b(I/O)g(Routines)e(.)46 -b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 -b(12)256 3409 y(4.6)94 b(Header)31 b(Keyw)m(ord)f(I/O)h(Routines)79 -b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) -h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(19)256 3522 -y(4.7)94 b(Utilit)m(y)33 b(Routines)27 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g -(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(22)120 -3726 y Fg(5)84 b(CFITSIO)33 b(File)i(Names)g(and)f(Filters)1907 -b(23)256 3839 y Ff(5.1)94 b(Creating)31 b(New)g(Files)45 -b(.)h(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 -b(23)256 3951 y(5.2)94 b(Op)s(ening)30 b(Existing)g(Files)41 -b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 -b(24)256 4064 y(5.3)94 b(Image)32 b(Filtering)56 b(.)45 -b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 -b(26)465 4177 y(5.3.1)106 b(Extracting)32 b(a)f(subsection)f(of)h(an)f -(image)77 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)129 b(26)465 4290 y(5.3.2)106 b(Create)32 -b(an)e(Image)h(b)m(y)f(Binning)g(T)-8 b(able)31 b(Columns)i(.)45 -b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 -b(26)256 4403 y(5.4)94 b(T)-8 b(able)31 b(Filtering)77 -b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) -g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g -(.)129 b(28)465 4516 y(5.4.1)106 b(Column)30 b(and)g(Keyw)m(ord)g -(Filtering)50 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h -(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(28)465 4629 -y(5.4.2)106 b(Ro)m(w)31 b(Filtering)42 b(.)j(.)h(.)g(.)g(.)f(.)h(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f -(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(29)465 4742 y(5.4.3)106 -b(Go)s(o)s(d)30 b(Time)h(In)m(terv)-5 b(al)31 b(Filtering)62 -b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) -h(.)g(.)g(.)f(.)h(.)g(.)129 b(32)465 4855 y(5.4.4)106 -b(Spatial)31 b(Region)h(Filtering)59 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g -(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) -g(.)129 b(32)465 4968 y(5.4.5)106 b(Example)31 b(Ro)m(w)g(Filters)h(.) -45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) -f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(34)256 -5081 y(5.5)94 b(Com)m(bined)30 b(Filtering)i(Examples)45 -b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f -(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(36)120 5284 -y Fg(6)84 b(CFITSIO)33 b(Error)i(Status)f(Co)s(des)2069 -b(38)p 120 5346 1465 4 v 222 5400 a Fe(\003)258 5431 -y Fd(HEASAR)n(C,)25 b(NASA)f(Go)r(ddard)i(Space)f(Fligh)n(t)h(Cen)n -(ter)1928 5809 y Ff(1)p eop end -%%Page: 2 2 -TeXDict begin 2 1 bop 120 573 a Fh(1)135 b(In)l(tro)t(duction)120 -776 y Ff(This)34 b(do)s(cumen)m(t)g(is)g(in)m(tended)g(to)h(help)f(y)m -(ou)h(quic)m(kly)g(start)g(writing)f(C)g(programs)g(to)h(read)f(and)g -(write)120 889 y(FITS)45 b(\014les)g(using)g(the)g(CFITSIO)f(library)-8 -b(.)86 b(It)45 b(co)m(v)m(ers)i(the)f(most)f(imp)s(ortan)m(t)h(CFITSIO) -d(routines)120 1002 y(that)i(are)f(needed)g(to)h(p)s(erform)d(most)i(t) -m(yp)s(es)h(of)f(op)s(erations)g(on)g(FITS)f(\014les.)82 -b(F)-8 b(or)45 b(more)f(complete)120 1115 y(information)d(ab)s(out)e -(these)i(and)f(all)h(the)f(other)h(a)m(v)-5 b(ailable)42 -b(routines)e(in)g(the)h(library)f(please)h(refer)f(to)120 -1227 y(the)c(\\CFITSIO)e(User's)i(Reference)g(Guide",)i(whic)m(h)d(is)g -(a)m(v)-5 b(ailable)38 b(from)d(the)h(CFITSIO)e(W)-8 -b(eb)36 b(site)h(at)120 1340 y Fc(http://heasarc.gsfc.nasa)o(.gov)o -(/fit)o(sio)o Ff(.)261 1453 y(F)-8 b(or)41 b(more)f(general)g -(information)g(ab)s(out)g(the)g(FITS)f(data)h(format,)j(refer)d(to)g -(the)g(follo)m(wing)h(w)m(eb)120 1566 y(page:)g(h)m -(ttp://heasarc.gsfc.nasa.go)m(v/do)s(cs/heasa)q(rc/\014ts.h)m(t)q(ml) -261 1679 y(FITS)27 b(stands)h(for)g(Flexible)h(Image)g(T)-8 -b(ransp)s(ort)27 b(System)h(and)f(is)h(the)h(standard)e(\014le)h -(format)g(used)g(to)120 1792 y(store)j(most)g(astronomical)h(data)g -(\014les.)41 b(There)30 b(are)h(2)g(basic)g(t)m(yp)s(es)f(of)h(FITS)f -(\014les:)41 b(images)31 b(and)f(tables.)120 1905 y(FITS)j(images)i -(often)f(con)m(tain)h(a)f(2-dimensional)g(arra)m(y)h(of)e(pixels)h -(represen)m(ting)g(an)g(image)h(of)e(a)h(piece)120 2018 -y(of)f(the)f(sky)-8 b(,)34 b(but)e(FITS)g(images)h(can)g(also)h(con)m -(tain)g(1-D)f(arra)m(ys)g(\(i.e,)i(a)e(sp)s(ectrum)e(or)i(ligh)m(t)g -(curv)m(e\),)h(or)120 2131 y(3-D)40 b(arra)m(ys)f(\(a)g(data)g(cub)s -(e\),)i(or)d(ev)m(en)i(higher)e(dimensional)h(arra)m(ys)f(of)h(data.)66 -b(An)38 b(image)i(ma)m(y)f(also)120 2244 y(ha)m(v)m(e)30 -b(zero)g(dimensions,)e(in)h(whic)m(h)f(case)i(it)f(is)g(referred)f(to)i -(as)f(a)g(n)m(ull)g(or)g(empt)m(y)g(arra)m(y)-8 b(.)41 -b(The)28 b(supp)s(orted)120 2357 y(datat)m(yp)s(es)f(for)f(the)h(image) -h(arra)m(ys)e(are)h(8,)h(16,)g(and)e(32-bit)i(in)m(tegers,)h(and)c(32)j -(and)d(64-bit)j(\015oating)f(p)s(oin)m(t)120 2469 y(real)k(n)m(um)m(b)s -(ers.)39 b(Both)31 b(signed)g(and)e(unsigned)h(in)m(tegers)h(are)g -(supp)s(orted.)261 2582 y(FITS)j(tables)h(con)m(tain)g(ro)m(ws)f(and)g -(columns)g(of)g(data,)i(similar)f(to)g(a)g(spreadsheet.)52 -b(All)35 b(the)f(v)-5 b(alues)120 2695 y(in)31 b(a)g(particular)g -(column)g(m)m(ust)f(ha)m(v)m(e)j(the)e(same)g(datat)m(yp)s(e.)43 -b(A)31 b(cell)h(of)f(a)g(column)g(is)g(not)g(restricted)h(to)120 -2808 y(a)g(single)f(n)m(um)m(b)s(er,)g(and)f(instead)i(can)f(con)m -(tain)i(an)e(arra)m(y)g(or)h(v)m(ector)g(of)g(n)m(um)m(b)s(ers.)41 -b(There)31 b(are)h(actually)120 2921 y(2)43 b(subt)m(yp)s(es)f(of)h -(FITS)f(tables:)66 b(ASCI)s(I)41 b(and)i(binary)-8 b(.)77 -b(As)43 b(the)g(names)g(imply)-8 b(,)46 b(ASCI)s(I)41 -b(tables)j(store)120 3034 y(the)37 b(data)h(v)-5 b(alues)37 -b(in)g(an)f(ASCI)s(I)g(represen)m(tation)i(whereas)e(binary)h(tables)g -(store)h(the)f(data)g(v)-5 b(alues)38 b(in)120 3147 y(a)33 -b(more)f(e\016cien)m(t)i(mac)m(hine-readable)f(binary)f(format.)46 -b(Binary)33 b(tables)g(are)f(generally)i(more)e(compact)120 -3260 y(and)25 b(supp)s(ort)e(more)j(features)f(\(e.g.,)j(a)e(wider)f -(range)g(of)h(datat)m(yp)s(es,)h(and)e(v)m(ector)i(columns\))e(than)g -(ASCI)s(I)120 3373 y(tables.)261 3486 y(A)31 b(single)g(FITS)f(\014le)h -(man)m(y)g(con)m(tain)h(m)m(ultiple)f(images)h(or)f(tables.)42 -b(Eac)m(h)31 b(table)h(or)e(image)i(is)f(called)120 3599 -y(a)j(Header-Data)j(Unit,)e(or)f(HDU.)h(The)f(\014rst)f(HDU)i(in)e(a)i -(FITS)e(\014le)h(m)m(ust)g(b)s(e)f(an)h(image)i(\(but)d(it)i(ma)m(y)120 -3711 y(ha)m(v)m(e)30 b(zero)f(axes\))h(and)e(is)h(called)h(the)f -(Primary)f(Arra)m(y)-8 b(.)41 b(An)m(y)28 b(additional)i(HDUs)f(in)g -(the)f(\014le)h(\(whic)m(h)g(are)120 3824 y(also)i(referred)f(to)h(as)g -(`extensions'\))g(ma)m(y)g(con)m(tain)h(either)f(an)f(image)i(or)e(a)h -(table.)261 3937 y(Ev)m(ery)38 b(HDU)g(con)m(tains)h(a)f(header)g(con)m -(taining)h(k)m(eyw)m(ord)f(records.)62 b(Eac)m(h)38 b(k)m(eyw)m(ord)g -(record)g(is)g(80)120 4050 y(ASCI)s(I)29 b(c)m(haracters)j(long)f(and)e -(has)i(the)f(follo)m(wing)i(format:)120 4263 y Fc(KEYWORD)46 -b(=)h(value)g(/)g(comment)f(string)261 4475 y Ff(The)23 -b(k)m(eyw)m(ord)i(name)f(can)g(b)s(e)f(up)g(to)h(8)g(c)m(haracters)i -(long)e(\(all)h(upp)s(ercase\).)38 b(The)23 b(v)-5 b(alue)25 -b(can)f(b)s(e)f(either)120 4588 y(an)k(in)m(teger)h(or)e(\015oating)i -(p)s(oin)m(t)e(n)m(um)m(b)s(er,)h(a)g(logical)i(v)-5 -b(alue)27 b(\(T)g(or)f(F\),)i(or)e(a)h(c)m(haracter)i(string)d -(enclosed)i(in)120 4701 y(single)e(quotes.)40 b(Eac)m(h)26 -b(header)f(b)s(egins)g(with)g(a)h(series)g(of)g(required)f(k)m(eyw)m -(ords)g(to)i(describ)s(e)e(the)g(datat)m(yp)s(e)120 4814 -y(and)35 b(format)h(of)f(the)h(follo)m(wing)h(data)f(unit,)g(if)f(an)m -(y)-8 b(.)57 b(An)m(y)35 b(n)m(um)m(b)s(er)g(of)g(other)h(optional)g(k) -m(eyw)m(ords)g(can)120 4927 y(b)s(e)d(included)g(in)g(the)g(header)h -(to)g(pro)m(vide)f(other)h(descriptiv)m(e)h(information)e(ab)s(out)h -(the)f(data.)51 b(F)-8 b(or)34 b(the)120 5040 y(most)g(part,)g(the)g -(CFITSIO)d(routines)j(automatically)i(write)d(the)h(required)f(FITS)f -(k)m(eyw)m(ords)i(for)f(eac)m(h)120 5153 y(HDU,)e(so)g(y)m(ou,)g(the)g -(programmer,)f(usually)g(do)g(not)h(need)f(to)h(w)m(orry)f(ab)s(out)g -(them.)1928 5809 y(2)p eop end -%%Page: 3 3 -TeXDict begin 3 2 bop 120 573 a Fh(2)135 b(Installing)46 -b(and)f(Using)g(CFITSIO)120 776 y Ff(First,)33 b(y)m(ou)f(should)e(do)m -(wnload)i(the)g(CFITSIO)e(soft)m(w)m(are)j(and)e(the)h(set)g(of)g -(example)h(FITS)e(utilit)m(y)i(pro-)120 889 y(grams)e(from)f(the)g(w)m -(eb)h(site)g(at)h(h)m(ttp://heasarc.gsfc.nasa.go)m(v/\014tsio.)47 -b(The)30 b(example)h(programs)f(illus-)120 1002 y(trate)g(ho)m(w)e(to)h -(p)s(erform)f(man)m(y)g(common)h(t)m(yp)s(es)f(of)h(op)s(erations)g(on) -f(FITS)g(\014les)h(using)f(CFITSIO.)f(They)120 1115 y(are)h(also)h -(useful)d(when)h(writing)h(a)g(new)f(program)g(b)s(ecause)h(it)g(is)g -(often)g(easier)g(to)h(tak)m(e)g(a)f(cop)m(y)g(of)g(one)g(of)120 -1227 y(these)k(utilit)m(y)h(programs)e(as)g(a)h(template)h(and)e(then)g -(mo)s(dify)f(it)i(for)f(y)m(our)h(o)m(wn)f(purp)s(oses,)f(rather)i -(than)120 1340 y(writing)e(the)h(new)f(program)g(completely)i(from)e -(scratc)m(h.)261 1453 y(T)-8 b(o)28 b(build)e(the)i(CFITSIO)d(library)i -(on)g(Unix)g(platforms,)i(`un)m(tar')e(the)h(source)f(co)s(de)h -(distribution)e(\014le)120 1566 y(and)k(then)g(execute)i(the)e(follo)m -(wing)i(commands)e(in)g(the)h(directory)f(con)m(taining)i(the)f(source) -g(co)s(de:)120 1779 y Fc(>)95 b(./configure)45 b -([--prefix=/target/instal)o(lati)o(on/)o(path)o(])120 -1892 y(>)95 b(make)524 b(\(or)47 b('make)f(shared'\))120 -2005 y(>)95 b(make)47 b(install)141 b(\(this)46 b(step)h(is)g -(optional\))261 2217 y Ff(The)40 b(optional)i('pre\014x')e(argumen)m(t) -h(to)g(con\014gure)f(giv)m(es)i(the)f(path)f(to)h(the)g(directory)g -(where)f(the)120 2330 y(CFITSIO)30 b(library)i(and)f(include)h(\014les) -g(should)f(b)s(e)g(installed)i(via)g(the)f(later)h('mak)m(e)g(install') -g(command.)120 2443 y(F)-8 b(or)31 b(example,)120 2655 -y Fc(>)95 b(./configure)45 b(--prefix=/usr1/local)261 -2868 y Ff(will)21 b(cause)g(the)g('mak)m(e)h(install')g(command)e(to)h -(cop)m(y)h(the)e(CFITSIO)f(lib)s(c\014tsio)i(\014le)g(to)g(/usr1/lo)s -(cal/lib)120 2981 y(and)35 b(the)h(necessary)g(include)g(\014les)g(to)g -(/usr1/lo)s(cal/include)i(\(assuming)e(of)f(course)h(that)h(the)f(pro)s -(cess)120 3094 y(has)30 b(p)s(ermission)f(to)j(write)e(to)h(these)g -(directories\).)261 3207 y(Pre-compiled)f(v)m(ersions)g(of)g(the)g -(CFITSIO)e(DLL)i(library)f(are)h(a)m(v)-5 b(ailable)32 -b(for)d(PCs.)40 b(On)29 b(Macin)m(tosh)120 3320 y(mac)m(hines,)46 -b(refer)c(to)g(the)h(README.MacOS)g(\014le)f(for)g(instructions)g(on)g -(building)f(CFITSIO)g(using)120 3432 y(Co)s(deW)-8 b(arrior.)261 -3545 y(An)m(y)40 b(programs)g(that)h(use)f(CFITSIO)f(m)m(ust)h(of)g -(course)h(b)s(e)e(link)m(ed)i(with)f(the)g(CFITSIO)f(library)120 -3658 y(when)e(creating)i(the)f(executable)i(\014le.)64 -b(The)37 b(exact)j(pro)s(cedure)c(for)i(linking)g(a)h(program)e(dep)s -(ends)f(on)120 3771 y(y)m(our)31 b(soft)m(w)m(are)i(en)m(vironmen)m(t,) -f(but)f(on)g(Unix)g(platforms,)h(the)f(command)g(line)h(to)g(compile)g -(and)f(link)g(a)120 3884 y(program)f(will)h(lo)s(ok)g(something)g(lik)m -(e)g(this:)120 4097 y Fc(gcc)47 b(-o)g(myprog)f(myprog.c)g(-L.)h -(-lcfitsio)e(-lm)i(-lnsl)f(-lsocket)261 4309 y Ff(Y)-8 -b(ou)37 b(ma)m(y)g(not)f(need)g(to)h(include)g(all)g(of)f(the)h('m',)h -('nsl',)g(and)e('so)s(c)m(k)m(et')i(system)f(libraries)f(on)g(y)m(our) -120 4422 y(particular)41 b(mac)m(hine.)73 b(T)-8 b(o)42 -b(\014nd)d(out)i(what)g(libraries)g(are)g(required)f(on)h(y)m(our)g -(\(Unix\))g(system,)j(t)m(yp)s(e)120 4535 y Fc('make)i(testprog')28 -b Ff(and)i(see)h(what)f(libraries)h(are)f(then)h(included)e(on)h(the)h -(resulting)g(link)f(line.)1928 5809 y(3)p eop end -%%Page: 4 4 -TeXDict begin 4 3 bop 120 573 a Fh(3)135 b(Example)46 -b(Programs)120 776 y Ff(Before)32 b(describing)f(the)h(individual)f -(CFITSIO)e(routines)j(in)f(detail,)i(it)e(is)h(instructiv)m(e)g(to)g -(\014rst)f(lo)s(ok)h(at)120 889 y(an)27 b(actual)h(program.)40 -b(The)26 b(names)h(of)g(the)g(CFITSIO)f(routines)h(are)g(fairly)g -(descriptiv)m(e)h(\(they)g(all)g(b)s(egin)120 1002 y(with)i -Fc(fits)p 525 1002 29 4 v 33 w Ff(,)h(so)g(it)f(should)g(b)s(e)g -(reasonably)g(clear)i(what)e(this)g(program)g(do)s(es:)120 -1202 y Fc(------------------------)o(----)o(----)o(---)o(----)o(----)o -(---)o(----)o(----)o(---)o(----)o(---)311 1315 y(#include)45 -b()311 1428 y(#include)g()120 1541 -y(1:)95 b(#include)45 b("fitsio.h")311 1767 y(int)i(main\(int)e(argc,)i -(char)f(*argv[]\))311 1879 y({)120 1992 y(2:)286 b(fitsfile)45 -b(*fptr;)502 2105 y(char)h(card[FLEN_CARD];)120 2218 -y(3:)286 b(int)47 b(status)f(=)h(0,)95 b(nkeys,)46 b(ii;)95 -b(/*)47 b(MUST)g(initialize)e(status)h(*/)120 2444 y(4:)286 -b(fits_open_file\(&fptr,)42 b(argv[1],)j(READONLY,)h(&status\);)502 -2557 y(fits_get_hdrspace\(fptr,)41 b(&nkeys,)46 b(NULL,)g(&status\);) -502 2783 y(for)h(\(ii)g(=)g(1;)g(ii)g(<=)h(nkeys;)e(ii++\))94 -b({)597 2896 y(fits_read_record\(fptr,)42 b(ii,)47 b(card,)f -(&status\);)g(/*)h(read)f(keyword)g(*/)597 3009 y(printf\("\045s\\n",)e -(card\);)502 3121 y(})502 3234 y(printf\("END\\n\\n"\);)90 -b(/*)48 b(terminate)d(listing)h(with)g(END)h(*/)502 3347 -y(fits_close_file\(fptr,)42 b(&status\);)502 3573 y(if)47 -b(\(status\))475 b(/*)47 b(print)g(any)g(error)f(messages)f(*/)120 -3686 y(5:)477 b(fits_report_error\(stder)o(r,)42 b(status\);)502 -3799 y(return\(status\);)311 3912 y(})120 4025 y -(------------------------)o(----)o(----)o(---)o(----)o(----)o(---)o -(----)o(----)o(---)o(----)o(---)261 4225 y Ff(This)29 -b(program)g(op)s(ens)f(the)h(sp)s(eci\014ed)g(FITS)f(\014le)i(and)e -(prin)m(ts)h(out)g(all)h(the)g(header)f(k)m(eyw)m(ords)g(in)g(the)120 -4338 y(curren)m(t)h(HDU.)i(Some)e(other)h(p)s(oin)m(ts)f(to)h(notice)h -(ab)s(out)e(the)g(program)g(are:)231 4516 y(1.)46 b(The)30 -b Fc(fitsio.h)e Ff(header)i(\014le)g(m)m(ust)h(b)s(e)e(included)h(to)h -(de\014ne)e(the)i(v)-5 b(arious)30 b(routines)g(and)g(sym)m(b)s(ols)347 -4629 y(used)g(in)g(CFITSIO.)231 4812 y(2.)46 b(The)37 -b Fc(fitsfile)e Ff(parameter)i(is)g(the)g(\014rst)g(argumen)m(t)g(in)g -(almost)h(ev)m(ery)g(CFITSIO)d(routine.)61 b(It)347 4925 -y(is)41 b(a)h(p)s(oin)m(ter)f(to)h(a)g(structure)e(\(de\014ned)g(in)h -Fc(fitsio.h)p Ff(\))f(that)h(stores)h(information)f(ab)s(out)g(the)347 -5038 y(particular)i(FITS)e(\014le)h(that)h(the)g(routine)f(will)g(op)s -(erate)h(on.)76 b(Memory)43 b(for)f(this)g(structure)f(is)347 -5151 y(automatically)36 b(allo)s(cated)e(when)e(the)h(\014le)g(is)f -(\014rst)g(op)s(ened)g(or)h(created,)h(and)e(is)h(freed)f(when)g(the) -347 5264 y(\014le)f(is)f(closed.)231 5447 y(3.)46 b(Almost)41 -b(ev)m(ery)f(CFITSIO)e(routine)h(has)h(a)g Fc(status)d -Ff(parameter)j(as)g(the)g(last)g(argumen)m(t.)69 b(The)347 -5560 y(status)28 b(v)-5 b(alue)28 b(is)g(also)h(usually)e(returned)g -(as)h(the)g(v)-5 b(alue)28 b(of)g(the)f(function)h(itself.)40 -b(Normally)29 b(status)1928 5809 y(4)p eop end -%%Page: 5 5 -TeXDict begin 5 4 bop 347 573 a Ff(=)22 b(0,)i(and)d(a)h(p)s(ositiv)m -(e)h(status)f(v)-5 b(alue)22 b(indicates)h(an)f(error)f(of)h(some)g -(sort.)38 b(The)22 b(status)g(v)-5 b(ariable)22 b(m)m(ust)347 -686 y(alw)m(a)m(ys)33 b(b)s(e)d(initialized)j(to)f(zero)g(b)s(efore)f -(use,)g(b)s(ecause)g(if)g(status)g(is)g(greater)i(than)d(zero)i(on)f -(input)347 799 y(then)e(the)g(CFITSIO)f(routines)h(will)g(simply)f -(return)g(without)h(doing)g(an)m(ything.)41 b(This)28 -b(`inherited)347 912 y(status')46 b(feature,)j(where)44 -b(eac)m(h)i(CFITSIO)e(routine)h(inherits)f(the)h(status)g(from)g(the)g -(previous)347 1024 y(routine,)f(mak)m(es)d(it)g(unnecessary)f(to)i(c)m -(hec)m(k)g(the)f(status)g(v)-5 b(alue)41 b(after)g(ev)m(ery)h(single)f -(CFITSIO)347 1137 y(routine)e(call.)66 b(Generally)40 -b(y)m(ou)f(should)f(c)m(hec)m(k)i(the)e(status)h(after)g(an)g(esp)s -(ecially)h(imp)s(ortan)m(t)e(or)347 1250 y(complicated)33 -b(routine)e(has)g(b)s(een)g(called,)i(or)e(after)h(a)f(blo)s(c)m(k)h -(of)f(closely)i(related)f(CFITSIO)e(calls.)347 1363 y(This)c(example)h -(program)g(has)f(tak)m(en)i(this)f(feature)g(to)g(the)g(extreme)g(and)f -(only)h(c)m(hec)m(ks)h(the)f(status)347 1476 y(v)-5 b(alue)31 -b(at)g(the)g(v)m(ery)g(end)e(of)i(the)f(program.)231 -1664 y(4.)46 b(In)37 b(this)f(example)i(program)f(the)g(\014le)g(name)g -(to)h(b)s(e)e(op)s(ened)h(is)g(giv)m(en)h(as)f(an)g(argumen)m(t)g(on)g -(the)347 1777 y(command)e(line)h(\()p Fc(arg[1])p Ff(\).)53 -b(If)35 b(the)g(\014le)h(con)m(tains)g(more)f(than)g(1)g(HDU)h(or)f -(extension,)j(y)m(ou)d(can)347 1890 y(sp)s(ecify)20 b(whic)m(h)g -(particular)h(HDU)g(to)g(b)s(e)f(op)s(ened)f(b)m(y)h(enclosing)i(the)e -(name)g(or)h(n)m(um)m(b)s(er)e(of)h(the)h(HDU)347 2002 -y(in)k(square)h(brac)m(k)m(ets)h(follo)m(wing)g(the)e(ro)s(ot)h(name)g -(of)f(the)h(\014le.)39 b(F)-8 b(or)26 b(example,)i Fc(file.fts[0])22 -b Ff(op)s(ens)347 2115 y(the)31 b(primary)e(arra)m(y)-8 -b(,)32 b(while)f Fc(file.fts[2])c Ff(will)k(mo)m(v)m(e)h(to)f(and)f(op) -s(en)f(the)i(2nd)f(extension)h(in)f(the)347 2228 y(\014le,)37 -b(and)d Fc(file.fit[EVENTS])d Ff(will)k(op)s(en)g(the)g(extension)g -(that)h(has)f(a)g Fc(EXTNAME)46 b(=)i('EVENTS')347 2341 -y Ff(k)m(eyw)m(ord)31 b(in)f(the)g(header.)41 b(Note)31 -b(that)g(on)f(the)h(Unix)f(command)g(line)h(y)m(ou)f(m)m(ust)g(enclose) -i(the)e(\014le)347 2454 y(name)h(in)f(single)h(or)g(double)f(quote)i(c) -m(haracters)g(if)e(the)h(name)g(con)m(tains)g(sp)s(ecial)h(c)m -(haracters)g(suc)m(h)347 2567 y(as)f(`[')g(or)f(`]'.)347 -2717 y(All)44 b(of)f(the)h(CFITSIO)d(routines)i(whic)m(h)g(read)g(or)g -(write)h(header)f(k)m(eyw)m(ords,)k(image)d(data,)j(or)347 -2830 y(table)32 b(data)f(op)s(erate)g(only)g(within)f(the)h(curren)m -(tly)g(op)s(ened)f(HDU)h(in)f(the)h(\014le.)42 b(T)-8 -b(o)31 b(read)g(or)f(write)347 2943 y(information)38 -b(in)f(a)h(di\013eren)m(t)g(HDU)g(y)m(ou)g(m)m(ust)f(\014rst)g -(explicitly)i(mo)m(v)m(e)f(to)h(that)f(HDU)g(\(see)g(the)347 -3056 y Fc(fits)p 545 3056 29 4 v 34 w(movabs)p 867 3056 -V 32 w(hdu)30 b Ff(and)g Fc(fits)p 1442 3056 V 33 w(movrel)p -1763 3056 V 33 w(hdu)f Ff(routines)h(in)g(section)i(4.3\).)231 -3244 y(5.)46 b(The)25 b Fc(fits)p 727 3244 V 33 w(report)p -1048 3244 V 33 w(error)e Ff(routine)i(pro)m(vides)g(a)g(con)m(v)m -(enien)m(t)i(w)m(a)m(y)f(to)g(prin)m(t)f(out)g(diagnostic)h(mes-)347 -3357 y(sages)32 b(ab)s(out)e(an)m(y)g(error)g(that)h(ma)m(y)g(ha)m(v)m -(e)h(o)s(ccurred.)261 3544 y(A)f(set)g(of)f(example)h(FITS)f(utilit)m -(y)i(programs)e(are)g(a)m(v)-5 b(ailable)33 b(from)d(the)g(CFITSIO)f(w) -m(eb)i(site)g(at)120 3657 y(h)m(ttp://heasarc.gsfc.nasa.go)m(v/do)s -(cs/soft)n(w)m(are/)q(\014tsio/c)q(exa)q(mples.h)m(tml.)89 -b(These)45 b(are)g(real)g(w)m(orking)120 3770 y(programs)d(whic)m(h)f -(illustrate)i(ho)m(w)f(to)h(read,)i(write,)g(and)c(mo)s(dify)g(FITS)h -(\014les)f(using)h(the)g(CFITSIO)120 3883 y(library)-8 -b(.)38 b(Most)24 b(of)g(these)f(programs)g(are)h(v)m(ery)f(short,)i -(con)m(taining)g(only)e(a)h(few)f(10s)h(of)f(lines)g(of)h(executable) -120 3996 y(co)s(de)32 b(or)g(less,)h(y)m(et)g(they)f(p)s(erform)e -(quite)i(useful)f(op)s(erations)h(on)g(FITS)f(\014les.)45 -b(Running)31 b(eac)m(h)i(program)120 4109 y(without)41 -b(an)m(y)g(command)f(line)h(argumen)m(ts)g(will)g(pro)s(duce)e(a)i -(short)f(description)h(of)g(ho)m(w)g(to)g(use)f(the)120 -4222 y(program.)g(The)30 b(curren)m(tly)h(a)m(v)-5 b(ailable)32 -b(programs)e(are:)347 4409 y(\014tscop)m(y)h(-)g(cop)m(y)g(a)g(\014le) -347 4522 y(listhead)g(-)g(list)g(header)f(k)m(eyw)m(ords)347 -4635 y(liststruc)h(-)g(sho)m(w)f(the)g(structure)g(of)h(a)g(FITS)e -(\014le.)347 4748 y(mo)s(dhead)h(-)g(write)h(or)f(mo)s(dify)g(a)h -(header)f(k)m(eyw)m(ord)347 4861 y(imarith)h(-)f(add,)g(subtract,)h(m)m -(ultiply)-8 b(,)31 b(or)g(divide)f(2)h(images)347 4974 -y(imlist)g(-)g(list)g(pixel)g(v)-5 b(alues)30 b(in)g(an)h(image)347 -5087 y(imstat)h(-)e(compute)h(mean,)g(min,)f(and)f(max)i(pixel)g(v)-5 -b(alues)30 b(in)g(an)h(image)347 5200 y(tablist)h(-)e(displa)m(y)h(the) -f(con)m(ten)m(ts)i(of)f(a)g(FITS)e(table)347 5313 y(tab)s(calc)j(-)f -(general)g(table)g(calculator)1928 5809 y(5)p eop end -%%Page: 6 6 -TeXDict begin 6 5 bop 120 573 a Fh(4)135 b(CFITSIO)44 -b(Routines)120 776 y Ff(This)37 b(c)m(hapter)h(describ)s(es)f(the)g -(main)h(CFITSIO)e(routines)h(that)h(can)g(b)s(e)f(used)g(to)h(p)s -(erform)e(the)i(most)120 889 y(common)31 b(t)m(yp)s(es)f(of)h(op)s -(erations)f(on)h(FITS)e(\014les.)120 1136 y Fb(4.1)112 -b(Error)37 b(Rep)s(orting)120 1310 y Fc(void)47 b -(fits_report_error\(FILE)41 b(*stream,)46 b(int)h(status\))120 -1423 y(void)g(fits_get_errstatus\(int)41 b(status,)46 -b(char)h(*err_text\))120 1536 y(float)f(fits_get_version\(float)c -(*version\))261 1748 y Ff(The)24 b(\014rst)g(routine)g(prin)m(ts)g(out) -h(information)g(ab)s(out)f(an)m(y)h(error)f(that)h(has)g(o)s(ccurred.) -38 b(Whenev)m(er)25 b(an)m(y)120 1861 y(CFITSIO)f(routine)i(encoun)m -(ters)h(an)f(error)f(it)i(usually)e(writes)h(a)h(message)g(describing)e -(the)h(nature)g(of)g(the)120 1974 y(error)g(to)i(an)e(in)m(ternal)h -(error)g(message)g(stac)m(k)h(and)e(then)h(returns)e(with)h(a)h(p)s -(ositiv)m(e)h(in)m(teger)g(status)f(v)-5 b(alue.)120 -2087 y(P)m(assing)28 b(the)g(error)f(status)h(v)-5 b(alue)28 -b(to)g(this)g(routine)f(will)h(cause)g(a)g(generic)h(description)e(of)h -(the)g(error)f(and)120 2200 y(all)g(the)g(messages)h(from)e(the)h(in)m -(ternal)g(CFITSIO)e(error)h(stac)m(k)i(to)g(b)s(e)e(prin)m(ted)g(to)h -(the)g(sp)s(eci\014ed)f(stream.)120 2313 y(The)k Fc(stream)f -Ff(parameter)h(is)h(usually)f(set)h(equal)g(to)g Fc("stdout")d -Ff(or)i Fc("stderr")p Ff(.)261 2426 y(The)25 b(second)g(routine)g -(simply)f(returns)g(a)h(30-c)m(haracter)j(descriptiv)m(e)e(error)e -(message)i(corresp)s(onding)120 2538 y(to)31 b(the)g(input)e(status)i -(v)-5 b(alue.)261 2651 y(The)30 b(last)h(routine)g(returns)e(the)h -(curren)m(t)g(CFITSIO)f(library)h(v)m(ersion)h(n)m(um)m(b)s(er.)120 -2899 y Fb(4.2)112 b(File)39 b(Op)s(en/Close)f(Routines)120 -3072 y Fc(int)47 b(fits_open_file\()d(fitsfile)h(**fptr,)h(char)h -(*filename,)e(int)h(mode,)h(int)g(*status\))120 3185 -y(int)g(fits_open_data\()d(fitsfile)h(**fptr,)h(char)h(*filename,)e -(int)h(mode,)h(int)g(*status\))120 3298 y(int)g -(fits_open_table\(fitsfile)41 b(**fptr,)46 b(char)h(*filename,)e(int)h -(mode,)h(int)g(*status\))120 3411 y(int)g(fits_open_image\(fitsfile)41 -b(**fptr,)46 b(char)h(*filename,)e(int)h(mode,)h(int)g(*status\))120 -3637 y(int)g(fits_create_file\(fitsfil)o(e)42 b(**fptr,)k(char)g -(*filename,)f(int)i(*status\))120 3750 y(int)g -(fits_close_file\(fitsfile)41 b(*fptr,)46 b(int)h(*status\))261 -3962 y Ff(These)38 b(routines)f(op)s(en)h(or)f(close)j(a)e(\014le.)63 -b(The)37 b(\014rst)g Fc(fitsfile)f Ff(parameter)i(in)g(these)g(and)f -(nearly)120 4075 y(ev)m(ery)28 b(other)g(CFITSIO)f(routine)g(is)h(a)g -(p)s(oin)m(ter)g(to)g(a)g(structure)g(that)g(CFITSIO)e(uses)h(to)i -(store)f(relev)-5 b(an)m(t)120 4188 y(parameters)31 b(ab)s(out)f(eac)m -(h)i(op)s(ened)e(\014le.)42 b(Y)-8 b(ou)31 b(should)f(nev)m(er)h -(directly)g(read)g(or)f(write)h(an)m(y)g(information)120 -4301 y(in)24 b(this)h(structure.)38 b(Memory)26 b(for)e(this)h -(structure)f(is)h(allo)s(cated)h(automatically)i(when)c(the)h(\014le)f -(is)h(op)s(ened)120 4414 y(or)30 b(created,)i(and)e(is)g(freed)g(when)g -(the)g(\014le)h(is)f(closed.)261 4527 y(The)e Fc(mode)e -Ff(parameter)j(in)e(the)h Fc(fits)p 1552 4527 29 4 v -34 w(open)p 1778 4527 V 33 w(xxxx)f Ff(set)h(of)g(routines)g(can)g(b)s -(e)f(set)i(to)f(either)h Fc(READONLY)120 4640 y Ff(or)h -Fc(READWRITE)d Ff(to)j(select)h(the)f(t)m(yp)s(e)f(of)h(\014le)g -(access)h(that)f(will)g(b)s(e)f(allo)m(w)m(ed.)42 b(These)29 -b(sym)m(b)s(olic)h(constan)m(ts)120 4753 y(are)h(de\014ned)e(in)h -Fc(fitsio.h)p Ff(.)261 4866 y(The)j Fc(fits)p 649 4866 -V 33 w(open)p 874 4866 V 34 w(file)f Ff(routine)i(op)s(ens)e(the)i -(\014le)g(and)e(p)s(ositions)i(the)g(in)m(ternal)g(\014le)f(p)s(oin)m -(ter)h(to)g(the)120 4979 y(b)s(eginning)23 b(of)h(the)g(\014le,)h(or)f -(to)h(the)f(sp)s(eci\014ed)f(extension)h(if)g(an)g(extension)g(name)g -(or)g(n)m(um)m(b)s(er)e(is)i(app)s(ended)120 5092 y(to)j(the)f(\014le)h -(name)f(\(see)h(the)g(later)g(section)h(on)e(\\CFITSIO)f(File)i(Names)g -(and)f(Filters")i(for)e(a)g(description)120 5204 y(of)32 -b(the)f(syn)m(tax\).)45 b Fc(fits)p 945 5204 V 33 w(open)p -1170 5204 V 33 w(data)31 b Ff(b)s(eha)m(v)m(es)g(similarly)h(except)h -(that)f(it)g(will)f(mo)m(v)m(e)i(to)f(the)g(\014rst)f(HDU)120 -5317 y(con)m(taining)37 b(signi\014can)m(t)f(data)g(if)f(a)h(HDU)g -(name)g(or)f(n)m(um)m(b)s(er)f(to)i(op)s(en)f(is)g(not)h(explicitly)g -(sp)s(eci\014ed)f(as)120 5430 y(part)23 b(of)h(the)g(\014lename.)39 -b(It)23 b(will)h(mo)m(v)m(e)h(to)g(the)e(\014rst)g(IMA)m(GE)i(HDU)f -(with)f(NAXIS)h(greater)h(than)e(0,)j(or)d(the)1928 5809 -y(6)p eop end -%%Page: 7 7 -TeXDict begin 7 6 bop 120 573 a Ff(\014rst)29 b(table)h(that)h(do)s(es) -e(not)h(con)m(tain)h(the)f(strings)f(`GTI')h(\(a)g(Go)s(o)s(d)g(Time)f -(In)m(terv)-5 b(al)31 b(extension\))f(or)g(`OB-)120 686 -y(ST)-8 b(ABLE')37 b(in)g(the)g(EXTNAME)h(k)m(eyw)m(ord)f(v)-5 -b(alue.)62 b(The)36 b Fc(fits)p 2380 686 29 4 v 34 w(open)p -2606 686 V 33 w(table)g Ff(and)g Fc(fits)p 3290 686 V -34 w(open)p 3516 686 V 33 w(image)120 799 y Ff(routines)f(are)h -(similar)f(except)i(that)f(they)f(will)h(mo)m(v)m(e)g(to)g(the)g -(\014rst)e(signi\014can)m(t)j(table)f(HDU)g(or)f(image)120 -912 y(HDU,)c(resp)s(ectiv)m(ely)h(if)e(a)h(HDU)g(name)g(of)f(n)m(um)m -(b)s(er)f(is)i(not)f(sp)s(eci\014ed)g(as)h(part)f(of)g(the)h(input)e -(\014le)i(name.)261 1024 y(When)d(op)s(ening)g(an)g(existing)h(\014le,) -g(the)g Fc(filename)d Ff(can)i(include)g(optional)i(argumen)m(ts,)f -(enclosed)g(in)120 1137 y(square)g(brac)m(k)m(ets)i(that)f(sp)s(ecify)f -(\014ltering)h(op)s(erations)f(that)h(should)f(b)s(e)g(applied)g(to)h -(the)g(input)e(\014le.)41 b(F)-8 b(or)120 1250 y(example,)263 -1428 y Fc(myfile.fit[EVENTS][counts)41 b(>)48 b(0])120 -1605 y Ff(op)s(ens)27 b(the)i(table)g(in)f(the)h(EVENTS)e(extension)i -(and)f(creates)i(a)e(virtual)h(table)g(b)m(y)f(selecting)i(only)f -(those)120 1718 y(ro)m(ws)f(where)f(the)i(COUNTS)d(column)i(v)-5 -b(alue)29 b(is)f(greater)h(than)f(0.)40 b(See)28 b(section)h(5)g(for)f -(more)g(examples)g(of)120 1831 y(these)j(p)s(o)m(w)m(erful)f -(\014ltering)g(capabilities.)261 1944 y(In)38 b Fc(fits)p -581 1944 V 33 w(create)p 902 1944 V 33 w(file)p Ff(,)h(the)g -Fc(filename)d Ff(is)j(simply)f(the)g(ro)s(ot)h(name)f(of)h(the)g -(\014le)f(to)h(b)s(e)f(created.)120 2057 y(Y)-8 b(ou)36 -b(can)g(o)m(v)m(erwrite)h(an)f(existing)g(\014le)g(b)m(y)f(pre\014xing) -g(the)h(name)g(with)f(a)h(`!')57 b(c)m(haracter)37 b(\(on)f(the)f(Unix) -120 2170 y(command)30 b(line)g(this)g(m)m(ust)f(b)s(e)g(pre\014xed)g -(with)h(a)g(bac)m(kslash,)h(as)f(in)f Fc(`\\!file.fit')p -Ff(\).)38 b(If)29 b(the)h(\014le)g(name)120 2282 y(ends)e(with)g -Fc(.gz)g Ff(the)h(\014le)g(will)g(b)s(e)f(compressed)g(using)g(the)h -(gzip)g(algorithm.)41 b(If)29 b(the)f(\014lename)h(is)g -Fc(stdout)120 2395 y Ff(or)g Fc("-")e Ff(\(a)j(single)f(dash)f(c)m -(haracter\))j(then)d(the)h(output)f(\014le)h(will)g(b)s(e)f(pip)s(ed)f -(to)j(the)f(stdout)f(stream.)41 b(Y)-8 b(ou)120 2508 -y(can)27 b(c)m(hain)g(sev)m(eral)g(tasks)g(together)h(b)m(y)f(writing)f -(the)h(output)f(from)g(the)g(\014rst)g(task)h(to)g Fc(stdout)e -Ff(and)h(then)120 2621 y(reading)k(the)h(input)e(\014le)i(in)f(the)h -(2nd)e(task)i(from)f Fc(stdin)f Ff(or)h Fc("-")p Ff(.)120 -2867 y Fb(4.3)112 b(HDU-lev)m(el)38 b(Routines)261 3040 -y Ff(The)30 b(routines)g(listed)h(in)f(this)h(section)g(op)s(erate)g -(on)f(Header-Data)j(Units)e(\(HDUs\))g(in)f(a)h(\014le.)120 -3153 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o -(___)o(____)o(____)o(___)o(____)o(__)120 3266 y(int)47 -b(fits_get_num_hdus\(fitsfi)o(le)42 b(*fptr,)k(int)h(*hdunum,)e(int)i -(*status\))120 3379 y(int)g(fits_get_hdu_num\(fitsfil)o(e)42 -b(*fptr,)94 b(int)47 b(*hdunum\))261 3579 y Ff(The)39 -b(\014rst)f(routines)h(returns)f(the)h(total)i(n)m(um)m(b)s(er)d(of)h -(HDUs)h(in)e(the)i(FITS)e(\014le,)k(and)c(the)h(second)120 -3692 y(routine)33 b(returns)e(the)i(p)s(osition)g(of)g(the)g(curren)m -(tly)f(op)s(ened)g(HDU)i(in)e(the)h(FITS)f(\014le)h(\(starting)g(with)g -(1,)120 3805 y(not)e(0\).)120 4005 y Fc(________________________)o -(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o -(____)o(___)o(____)o(__)120 4118 y(int)47 b(fits_movabs_hdu\(fitsfile) -41 b(*fptr,)46 b(int)h(hdunum,)f(int)h(*hdutype,)e(int)i(*status\))120 -4231 y(int)g(fits_movrel_hdu\(fitsfile)41 b(*fptr,)46 -b(int)h(nmove,)94 b(int)47 b(*hdutype,)e(int)i(*status\))120 -4344 y(int)g(fits_movnam_hdu\(fitsfile)41 b(*fptr,)46 -b(int)h(hdutype,)f(char)g(*extname,)1075 4457 y(int)g(extver,)g(int)h -(*status\))261 4657 y Ff(These)31 b(routines)g(enable)h(y)m(ou)f(to)h -(mo)m(v)m(e)g(to)g(a)g(di\013eren)m(t)f(HDU)h(in)f(the)g(\014le.)43 -b(Most)32 b(of)g(the)f(CFITSIO)120 4770 y(functions)h(whic)m(h)h(read)g -(or)g(write)g(k)m(eyw)m(ords)g(or)g(data)h(op)s(erate)f(only)h(on)e -(the)h(curren)m(tly)g(op)s(ened)g(HDU)120 4883 y(in)i(the)g(\014le.)54 -b(The)34 b(\014rst)g(routine)h(mo)m(v)m(es)h(to)g(the)f(sp)s(eci\014ed) -f(absolute)i(HDU)f(n)m(um)m(b)s(er)f(in)g(the)h(FITS)f(\014le)120 -4996 y(\(the)e(\014rst)f(HDU)i(=)e(1\),)i(whereas)f(the)g(second)f -(routine)h(mo)m(v)m(es)h(a)f(relativ)m(e)i(n)m(um)m(b)s(er)d(of)h(HDUs) -g(forw)m(ard)120 5109 y(or)f(bac)m(kw)m(ard)h(from)e(the)i(curren)m -(tly)f(op)s(en)f(HDU.)i(The)f Fc(hdutype)e Ff(parameter)i(returns)f -(the)i(t)m(yp)s(e)f(of)g(the)120 5222 y(newly)e(op)s(ened)g(HDU,)i(and) -e(will)h(b)s(e)f(equal)h(to)g(one)g(of)g(these)g(sym)m(b)s(olic)g -(constan)m(t)h(v)-5 b(alues:)41 b Fc(IMAGE)p 3564 5222 -V 33 w(HDU,)120 5334 y(ASCII)p 366 5334 V 33 w(TBL,)47 -b(or)g(BINARY)p 1069 5334 V 33 w(TBL)p Ff(.)37 b Fc(hdutype)g -Ff(ma)m(y)h(b)s(e)g(set)h(to)g(NULL)f(if)g(it)h(is)g(not)f(needed.)64 -b(The)38 b(third)120 5447 y(routine)31 b(mo)m(v)m(es)i(to)f(the)f -(\(\014rst\))h(HDU)g(that)f(matc)m(hes)i(the)e(input)g(extension)h(t)m -(yp)s(e,)f(name,)h(and)f(v)m(ersion)120 5560 y(n)m(um)m(b)s(er,)23 -b(as)f(giv)m(en)i(b)m(y)e(the)g Fc(XTENSION,)46 b(EXTNAME)20 -b Ff(\(or)j Fc(HDUNAME)p Ff(\))d(and)i Fc(EXTVER)f Ff(k)m(eyw)m(ords.) -38 b(If)22 b(the)g(input)1928 5809 y(7)p eop end -%%Page: 8 8 -TeXDict begin 8 7 bop 120 573 a Ff(v)-5 b(alue)34 b(of)f -Fc(extver)e Ff(=)i(0,)i(then)e(the)g(v)m(ersion)h(n)m(um)m(b)s(er)d -(will)j(b)s(e)e(ignored)i(when)e(lo)s(oking)i(for)f(a)g(matc)m(hing)120 -686 y(HDU.)120 898 y Fc(________________________)o(____)o(____)o(___)o -(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)120 -1011 y(int)47 b(fits_get_hdu_type\(fitsfi)o(le)42 b(*fptr,)93 -b(int)47 b(*hdutype,)f(int)g(*status\))261 1224 y Ff(Get)21 -b(the)g(t)m(yp)s(e)f(of)h(the)f(curren)m(t)g(HDU)h(in)f(the)h(FITS)e -(\014le:)36 b Fc(IMAGE)p 2435 1224 29 4 v 33 w(HDU,)47 -b(ASCII)p 2947 1224 V 33 w(TBL,)f(or)h(BINARY)p 3649 -1224 V 33 w(TBL)p Ff(.)120 1436 y Fc(________________________)o(____)o -(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o -(___)120 1549 y(int)g(fits_copy_hdu\(fitsfile)42 b(*infptr,)j(fitsfile) -h(*outfptr,)f(int)i(morekeys,)979 1662 y(int)g(*status\))120 -1775 y(int)g(fits_copy_file\(fitsfile)41 b(*infptr,)46 -b(fitsfile)f(*outfptr,)h(int)h(previous,)979 1888 y(int)g(current,)f -(int)g(following,)f(>)j(int)f(*status\))261 2100 y Ff(The)34 -b(\014rst)g(routine)g(copies)i(the)e(curren)m(t)g(HDU)i(from)e(the)g -(FITS)g(\014le)h(asso)s(ciated)g(with)g(infptr)e(and)120 -2213 y(app)s(ends)h(it)j(to)g(the)f(end)f(of)h(the)g(FITS)g(\014le)g -(asso)s(ciated)h(with)f(outfptr.)57 b(Space)36 b(ma)m(y)h(b)s(e)e -(reserv)m(ed)i(for)120 2326 y Fc(morekeys)32 b Ff(additional)k(k)m(eyw) -m(ords)f(in)g(the)f(output)h(header.)53 b(The)35 b(second)f(routine)h -(copies)h(an)m(y)f(HDUs)120 2439 y(previous)42 b(to)i(the)e(curren)m(t) -h(HDU,)h(and/or)e(the)h(curren)m(t)f(HDU,)i(and/or)f(an)m(y)g(HDUs)g -(follo)m(wing)h(the)120 2552 y(curren)m(t)22 b(HDU,)h(dep)s(ending)d -(on)i(the)g(v)-5 b(alue)23 b(\(T)-8 b(rue)22 b(or)g(F)-8 -b(alse\))24 b(of)e Fc(previous,)45 b(current)p Ff(,)22 -b(and)g Fc(following)p Ff(,)120 2665 y(resp)s(ectiv)m(ely)-8 -b(.)42 b(F)-8 b(or)32 b(example,)215 2853 y Fc(fits_copy_file\(infptr,) -42 b(outfptr,)k(0,)h(1,)g(1,)g(&status\);)120 3040 y -Ff(will)35 b(cop)m(y)h(the)f(curren)m(t)g(HDU)g(and)g(an)m(y)g(HDUs)g -(that)h(follo)m(w)g(it)f(from)g(the)g(input)f(to)h(the)h(output)e -(\014le,)120 3153 y(but)c(it)h(will)f(not)h(cop)m(y)g(an)m(y)g(HDUs)g -(preceding)f(the)h(curren)m(t)f(HDU.)1928 5809 y(8)p -eop end -%%Page: 9 9 -TeXDict begin 9 8 bop 120 573 a Fb(4.4)112 b(Image)38 -b(I/O)g(Routines)120 744 y Ff(This)30 b(section)h(lists)g(the)g(more)f -(imp)s(ortan)m(t)h(CFITSIO)d(routines)j(whic)m(h)f(op)s(erate)h(on)f -(FITS)g(images.)120 956 y Fc(________________________)o(____)o(____)o -(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(__)120 -1069 y(int)47 b(fits_get_img_type\(fitsfi)o(le)42 b(*fptr,)k(int)h -(*bitpix,)e(int)i(*status\))120 1181 y(int)g(fits_get_img_dim\()c -(fitsfile)j(*fptr,)g(int)h(*naxis,)93 b(int)47 b(*status\))120 -1294 y(int)g(fits_get_img_size\(fitsfi)o(le)42 b(*fptr,)k(int)h -(maxdim,)93 b(long)47 b(*naxes,)1170 1407 y(int)g(*status\))120 -1520 y(int)g(fits_get_img_param\(fitsf)o(ile)41 b(*fptr,)46 -b(int)h(maxdim,)94 b(int)47 b(*bitpix,)1218 1633 y(int)g(*naxis,)e -(long)i(*naxes,)f(int)h(*status\))261 1844 y Ff(Get)38 -b(information)g(ab)s(out)f(the)g(curren)m(tly)g(op)s(ened)g(image)h -(HDU.)g(The)f(\014rst)f(routine)h(returns)f(the)120 1957 -y(datat)m(yp)s(e)41 b(of)e(the)h(image)h(as)f(\(de\014ned)f(b)m(y)g -(the)h Fc(BITPIX)e Ff(k)m(eyw)m(ord\),)43 b(whic)m(h)c(can)h(ha)m(v)m -(e)h(the)f(follo)m(wing)120 2070 y(sym)m(b)s(olic)31 -b(constan)m(t)g(v)-5 b(alues:)311 2256 y Fc(BYTE_IMG)284 -b(=)143 b(8)g(\()47 b(8-bit)g(byte)f(pixels,)g(0)i(-)f(255\))311 -2369 y(SHORT_IMG)236 b(=)95 b(16)143 b(\(16)47 b(bit)g(integer)f -(pixels\))311 2482 y(LONG_IMG)284 b(=)95 b(32)143 b(\(32-bit)46 -b(integer)g(pixels\))311 2595 y(LONGLONG_IMG)92 b(=)j(64)143 -b(\(64-bit)46 b(integer)g(pixels\))311 2708 y(FLOAT_IMG)236 -b(=)48 b(-32)142 b(\(32-bit)46 b(floating)f(point)i(pixels\))311 -2821 y(DOUBLE_IMG)188 b(=)48 b(-64)142 b(\(64-bit)46 -b(floating)f(point)i(pixels\))261 3007 y Ff(The)34 b(second)g(and)f -(third)g(routines)h(return)f(the)h(n)m(um)m(b)s(er)e(of)i(dimensions)f -(in)h(the)g(image)h(\(from)f(the)120 3120 y Fc(NAXIS)25 -b Ff(k)m(eyw)m(ord\),)j(and)e(the)h(sizes)g(of)f(eac)m(h)i(dimension)e -(\(from)g(the)g Fc(NAXIS1,)46 b(NAXIS2)p Ff(,)26 b(etc.)40 -b(k)m(eyw)m(ords\).)120 3233 y(The)g(last)i(routine)f(simply)g(com)m -(bines)g(the)h(function)e(of)h(the)h(\014rst)e(3)h(routines.)73 -b(The)40 b(input)g Fc(maxdim)120 3346 y Ff(parameter)28 -b(in)g(this)f(routine)h(giv)m(es)h(the)f(maxim)m(um)g(n)m(um)m(b)s(er)e -(dimensions)h(that)i(ma)m(y)f(b)s(e)f(returned)g(\(i.e.,)120 -3459 y(the)k(dimension)e(of)i(the)f Fc(naxes)f Ff(arra)m(y\))120 -3670 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o -(___)o(____)o(____)o(___)o(_)120 3783 y(int)47 b -(fits_create_img\(fitsfile)41 b(*fptr,)46 b(int)h(bitpix,)f(int)h -(naxis,)1075 3896 y(long)f(*naxes,)g(int)h(*status\))261 -4107 y Ff(Create)28 b(an)f(image)i(HDU)f(b)m(y)f(writing)g(the)g -(required)g(k)m(eyw)m(ords)g(whic)m(h)g(de\014ne)g(the)g(structure)g -(of)g(the)120 4220 y(image.)51 b(The)33 b(2nd)f(through)h(4th)h -(parameters)f(sp)s(eci\014ed)g(the)g(datat)m(yp)s(e,)j(the)d(n)m(um)m -(b)s(er)f(of)i(dimensions,)120 4333 y(and)26 b(the)h(sizes)g(of)f(the)h -(dimensions.)39 b(The)26 b(allo)m(w)m(ed)i(v)-5 b(alues)27 -b(of)g(the)f Fc(bitpix)f Ff(parameter)i(are)g(listed)g(ab)s(o)m(v)m(e) -120 4446 y(in)33 b(the)g(description)g(of)g(the)g Fc(fits)p -1319 4446 29 4 v 33 w(get)p 1496 4446 V 33 w(img)p 1673 -4446 V 34 w(type)f Ff(routine.)48 b(If)32 b(the)h(FITS)f(\014le)h(p)s -(oin)m(ted)g(to)h(b)m(y)f Fc(fptr)e Ff(is)120 4559 y(empt)m(y)c -(\(previously)f(created)h(with)f Fc(fits)p 1575 4559 -V 33 w(create)p 1896 4559 V 33 w(file)p Ff(\))f(then)h(this)g(routine)g -(creates)i(a)f(primary)e(arra)m(y)120 4672 y(in)37 b(the)g(\014le,)i -(otherwise)f(a)f(new)g(IMA)m(GE)h(extension)g(is)f(app)s(ended)e(to)j -(end)f(of)g(the)g(\014le)h(follo)m(wing)g(the)120 4785 -y(other)31 b(HDUs)g(in)f(the)g(\014le.)120 4996 y Fc -(________________________)o(____)o(____)o(___)o(____)o(____)o(___)o -(____)o(____)o(___)o(____)o(_)120 5109 y(int)47 b -(fits_write_pix\(fitsfile)41 b(*fptr,)46 b(int)h(datatype,)f(long)g -(*fpixel,)836 5222 y(long)h(nelements,)e(void)h(*array,)g(int)h -(*status\);)120 5447 y(int)g(fits_write_pixnull\(fitsf)o(ile)41 -b(*fptr,)46 b(int)h(datatype,)f(long)g(*fpixel,)836 5560 -y(long)h(nelements,)e(void)h(*array,)g(void)h(*nulval,)e(int)i -(*status\);)1928 5809 y Ff(9)p eop end -%%Page: 10 10 -TeXDict begin 10 9 bop 120 686 a Fc(int)47 b(fits_read_pix\(fitsfile)42 -b(*fptr,)k(int)94 b(datatype,)46 b(long)g(*fpixel,)979 -799 y(long)h(nelements,)e(void)h(*nulval,)g(void)h(*array,)979 -912 y(int)g(*anynul,)f(int)g(*status\))261 1124 y Ff(Read)32 -b(or)f(write)g(all)h(or)f(part)h(of)f(the)g(FITS)g(image.)44 -b(There)31 b(are)h(2)f(di\013eren)m(t)h('write')g(pixel)f(routines:)120 -1237 y(The)23 b(\014rst)g(simply)g(writes)h(the)g(input)f(arra)m(y)h -(of)g(pixels)g(to)g(the)g(FITS)f(\014le.)39 b(The)23 -b(second)h(is)g(similar,)h(except)120 1350 y(that)30 -b(it)f(substitutes)g(the)g(appropriate)g(n)m(ull)g(pixel)g(v)-5 -b(alue)30 b(in)f(the)g(FITS)f(\014le)h(for)g(an)m(y)g(pixels)g(whic)m -(h)g(ha)m(v)m(e)120 1463 y(a)i(v)-5 b(alue)30 b(equal)h(to)g -Fc(*nulval)d Ff(\(note)j(that)g(this)f(parameter)g(giv)m(es)i(the)e -(address)f(of)i(the)f(n)m(ull)g(pixel)h(v)-5 b(alue,)120 -1576 y(not)35 b(the)g(v)-5 b(alue)35 b(itself)7 b(\).)54 -b(Similarly)-8 b(,)37 b(when)c(reading)i(an)g(image,)i(CFITSIO)c(will)i -(substitute)f(the)h(v)-5 b(alue)120 1689 y(giv)m(en)30 -b(b)m(y)e Fc(nulval)f Ff(for)i(an)m(y)g(unde\014ned)d(pixels)j(in)g -(the)g(image,)h(unless)e Fc(nulval)46 b(=)i(NULL)p Ff(,)27 -b(in)i(whic)m(h)f(case)120 1802 y(no)i(c)m(hec)m(ks)i(will)f(b)s(e)f -(made)g(for)g(unde\014ned)e(pixels)j(when)e(reading)i(the)f(FITS)g -(image.)261 1914 y(The)35 b Fc(fpixel)f Ff(parameter)i(in)f(these)h -(routines)f(is)h(an)f(arra)m(y)h(whic)m(h)f(giv)m(es)i(the)f(co)s -(ordinate)g(in)f(eac)m(h)120 2027 y(dimension)24 b(of)i(the)f(\014rst)f -(pixel)i(to)f(b)s(e)g(read)g(or)g(written,)h(and)f Fc(nelements)d -Ff(is)j(the)g(total)i(n)m(um)m(b)s(er)d(of)h(pixels)120 -2140 y(to)i(read)g(or)f(write.)40 b Fc(array)25 b Ff(is)i(the)f -(address)g(of)h(an)f(arra)m(y)h(whic)m(h)f(either)h(con)m(tains)h(the)f -(pixel)g(v)-5 b(alues)27 b(to)g(b)s(e)120 2253 y(written,)32 -b(or)f(will)h(hold)e(the)i(v)-5 b(alues)31 b(of)h(the)f(pixels)h(that)g -(are)f(read.)43 b(When)31 b(reading,)h Fc(array)e Ff(m)m(ust)h(ha)m(v)m -(e)120 2366 y(b)s(een)k(allo)s(cated)j(large)f(enough)e(to)i(hold)e -(all)i(the)f(returned)f(pixel)h(v)-5 b(alues.)57 b(These)36 -b(routines)f(starts)i(at)120 2479 y(the)e Fc(fpixel)d -Ff(lo)s(cation)k(and)e(then)g(read)h(or)f(write)h(the)f -Fc(nelements)e Ff(pixels,)k(con)m(tin)m(uing)g(on)e(successiv)m(e)120 -2592 y(ro)m(ws)f(of)g(the)g(image)h(if)f(necessary)-8 -b(.)49 b(F)-8 b(or)34 b(example,)h(to)e(write)g(an)g(en)m(tire)h(2D)g -(image,)h(set)e Fc(fpixel[0])46 b(=)120 2705 y(fpixel[1])f(=)j(1)p -Ff(,)35 b(and)f Fc(nelements)46 b(=)h(NAXIS1)f(*)i(NAXIS2)p -Ff(.)j(Or)34 b(to)i(read)e(just)g(the)h(10th)h(ro)m(w)e(of)h(the)120 -2818 y(image,)50 b(set)45 b Fc(fpixel[0])g(=)j(1,)f(fpixel[1])e(=)j(10) -p Ff(,)g(and)c Fc(nelements)h(=)i(NAXIS1)p Ff(.)82 b(The)45 -b Fc(datatype)120 2931 y Ff(parameter)28 b(sp)s(eci\014es)e(the)i -(datat)m(yp)s(e)g(of)f(the)g(C)g Fc(array)e Ff(in)i(the)g(program,)h -(whic)m(h)f(need)g(not)g(b)s(e)g(the)g(same)120 3044 -y(as)32 b(the)f(datat)m(yp)s(e)i(of)e(the)h(FITS)f(image)h(itself.)45 -b(If)31 b(the)h(datat)m(yp)s(es)g(di\013er)f(then)g(CFITSIO)f(will)i -(con)m(v)m(ert)120 3156 y(the)f(data)h(as)f(it)h(is)f(read)g(or)g -(written.)42 b(The)31 b(follo)m(wing)h(sym)m(b)s(olic)g(constan)m(ts)g -(are)f(allo)m(w)m(ed)i(for)e(the)g(v)-5 b(alue)120 3269 -y(of)31 b Fc(datatype)p Ff(:)215 3457 y Fc(TBYTE)238 -b(unsigned)45 b(char)215 3570 y(TSBYTE)190 b(signed)46 -b(char)215 3683 y(TSHORT)190 b(signed)46 b(short)215 -3796 y(TUSHORT)142 b(unsigned)45 b(short)215 3909 y(TINT)286 -b(signed)46 b(int)215 4022 y(TUINT)238 b(unsigned)45 -b(int)215 4134 y(TLONG)238 b(signed)46 b(long)215 4247 -y(TLONGLONG)g(signed)g(8-byte)g(integer)215 4360 y(TULONG)190 -b(unsigned)45 b(long)215 4473 y(TFLOAT)190 b(float)215 -4586 y(TDOUBLE)142 b(double)120 4799 y(________________________)o(____) -o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)120 -4912 y(int)47 b(fits_write_subset\(fitsfi)o(le)42 b(*fptr,)k(int)h -(datatype,)e(long)h(*fpixel,)740 5024 y(long)h(*lpixel,)f(DTYPE)g -(*array,)g(>)h(int)g(*status\))120 5250 y(int)g -(fits_read_subset\(fitsfil)o(e)42 b(*fptr,)k(int)95 b(datatype,)45 -b(long)h(*fpixel,)740 5363 y(long)h(*lpixel,)f(long)g(*inc,)h(void)f -(*nulval,)94 b(void)46 b(*array,)740 5476 y(int)h(*anynul,)f(int)h -(*status\))1905 5809 y Ff(10)p eop end -%%Page: 11 11 -TeXDict begin 11 10 bop 261 573 a Ff(Read)49 b(or)g(write)f(a)h -(rectangular)h(section)g(of)f(the)f(FITS)g(image.)97 -b(These)49 b(are)g(v)m(ery)g(similar)g(to)120 686 y Fc(fits)p -318 686 29 4 v 33 w(write)p 591 686 V 33 w(pix)37 b Ff(and)f -Fc(fits)p 1180 686 V 34 w(read)p 1406 686 V 33 w(pix)g -Ff(except)j(that)f(y)m(ou)f(sp)s(ecify)g(the)h(last)g(pixel)g(co)s -(ordinate)g(\(the)120 799 y(upp)s(er)22 b(righ)m(t)i(corner)g(of)g(the) -h(section\))g(instead)f(of)g(the)h(n)m(um)m(b)s(er)d(of)i(pixels)h(to)f -(b)s(e)g(read.)38 b(The)23 b(read)h(routine)120 912 y(also)39 -b(has)e(an)h Fc(inc)f Ff(parameter)h(whic)m(h)f(can)i(b)s(e)e(used)g -(to)h(read)g(only)g(ev)m(ery)g Fc(inc-th)e Ff(pixel)i(along)h(eac)m(h) -120 1024 y(dimension)28 b(of)h(the)g(image.)41 b(Normally)30 -b Fc(inc[0])46 b(=)h(inc[1])f(=)i(1)28 b Ff(to)i(read)e(ev)m(ery)i -(pixel)f(in)f(a)h(2D)h(image.)120 1137 y(T)-8 b(o)31 -b(read)f(ev)m(ery)h(other)g(pixel)g(in)f(the)g(en)m(tire)i(2D)f(image,) -h(set)311 1325 y Fc(fpixel[0])45 b(=)j(fpixel[1])d(=)i(1)311 -1438 y(lpixel[0])e(=)j({NAXIS1})311 1551 y(lpixel[1])d(=)j({NAXIS2})311 -1664 y(inc[0])e(=)h(inc[1])g(=)g(2)261 1851 y Ff(Or,)30 -b(to)h(read)f(the)h(8th)g(ro)m(w)f(of)h(a)f(2D)i(image,)f(set)311 -2039 y Fc(fpixel[0])45 b(=)j(1)311 2152 y(fpixel[1])d(=)j(8)311 -2265 y(lpixel[0])d(=)j({NAXIS1})311 2378 y(lpixel[1])d(=)j(8)311 -2491 y(inc[0])e(=)h(inc[1])g(=)g(1)1905 5809 y Ff(11)p -eop end -%%Page: 12 12 -TeXDict begin 12 11 bop 120 573 a Fb(4.5)112 b(T)-9 b(able)38 -b(I/O)g(Routines)120 744 y Ff(This)30 b(section)h(lists)g(the)g(most)f -(imp)s(ortan)m(t)h(CFITSIO)e(routines)h(whic)m(h)g(op)s(erate)h(on)f -(FITS)g(tables.)120 957 y Fc(________________________)o(____)o(____)o -(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o -(____)o(__)120 1070 y(int)47 b(fits_create_tbl\(fitsfile)41 -b(*fptr,)46 b(int)h(tbltype,)f(long)g(nrows,)g(int)h(tfields,)311 -1183 y(char)g(*ttype[],char)d(*tform[],)h(char)i(*tunit[],)e(char)i -(*extname,)e(int)i(*status\))261 1395 y Ff(Create)e(a)f(new)f(table)i -(extension)f(b)m(y)g(writing)g(the)g(required)f(k)m(eyw)m(ords)h(that)g -(de\014ne)f(the)h(table)120 1508 y(structure.)38 b(The)22 -b(required)f(n)m(ull)i(primary)e(arra)m(y)i(will)g(b)s(e)f(created)i -(\014rst)d(if)i(the)g(\014le)f(is)h(initially)h(completely)120 -1621 y(empt)m(y)-8 b(.)41 b Fc(tbltype)26 b Ff(de\014nes)i(the)g(t)m -(yp)s(e)h(of)g(table)g(and)f(can)g(ha)m(v)m(e)i(v)-5 -b(alues)29 b(of)f Fc(ASCII)p 2931 1621 29 4 v 33 w(TBL)47 -b(or)g(BINARY)p 3586 1621 V 33 w(TBL)p Ff(.)120 1734 -y(Binary)34 b(tables)h(are)g(generally)g(preferred)e(b)s(ecause)h(they) -h(are)f(more)h(e\016cien)m(t)g(and)f(supp)s(ort)f(a)h(greater)120 -1847 y(range)d(of)f(column)g(datat)m(yp)s(es)i(than)e(ASCI)s(I)f -(tables.)261 1960 y(The)c Fc(nrows)f Ff(parameter)i(giv)m(es)h(the)e -(initial)i(n)m(um)m(b)s(er)d(of)i(empt)m(y)g(ro)m(ws)f(to)h(b)s(e)f -(allo)s(cated)i(for)f(the)f(table;)120 2073 y(this)h(should)g(normally) -g(b)s(e)g(set)h(to)g(0.)40 b(The)26 b Fc(tfields)f Ff(parameter)i(giv)m -(es)g(the)g(n)m(um)m(b)s(er)e(of)i(columns)f(in)g(the)120 -2186 y(table)e(\(maxim)m(um)f(=)f(999\).)40 b(The)22 -b Fc(ttype,)46 b(tform)p Ff(,)24 b(and)e Fc(tunit)f Ff(parameters)i -(giv)m(e)i(the)e(name,)h(datat)m(yp)s(e,)120 2299 y(and)34 -b(ph)m(ysical)h(units)g(of)f(eac)m(h)i(column,)g(and)e -Fc(extname)f Ff(giv)m(es)j(the)f(name)g(for)f(the)h(table)h(\(the)f(v) --5 b(alue)35 b(of)120 2412 y(the)i Fc(EXTNAME)e Ff(k)m(eyw)m(ord\).)61 -b(The)36 b(FITS)g(Standard)g(recommends)g(that)i(only)f(letters,)j -(digits,)f(and)d(the)120 2524 y(underscore)27 b(c)m(haracter)h(b)s(e)f -(used)g(in)g(column)g(names)g(with)g(no)g(em)m(b)s(edded)g(spaces.)40 -b(It)27 b(is)h(recommended)120 2637 y(that)j(all)g(the)g(column)f -(names)g(in)g(a)h(giv)m(en)g(table)h(b)s(e)d(unique)h(within)g(the)g -(\014rst)g(8)h(c)m(haracters.)261 2750 y(The)g(follo)m(wing)i(table)g -(sho)m(ws)e(the)h(TF)m(ORM)g(column)f(format)h(v)-5 b(alues)32 -b(that)g(are)g(allo)m(w)m(ed)i(in)d(ASCI)s(I)120 2863 -y(tables)g(and)f(in)g(binary)g(tables:)502 3051 y Fc(ASCII)46 -b(Table)h(Column)f(Format)g(Codes)502 3164 y(------------------------)o -(---)o(----)502 3277 y(\(w)h(=)g(column)g(width,)f(d)h(=)h(no.)e(of)i -(decimal)d(places)i(to)g(display\))693 3390 y(Aw)142 -b(-)48 b(character)d(string)693 3502 y(Iw)142 b(-)48 -b(integer)693 3615 y(Fw.d)e(-)i(fixed)e(floating)g(point)693 -3728 y(Ew.d)g(-)i(exponential)d(floating)g(point)693 -3841 y(Dw.d)h(-)i(exponential)d(floating)g(point)502 -4067 y(Binary)h(Table)g(Column)g(Format)g(Codes)502 4180 -y(------------------------)o(---)o(----)o(-)502 4293 -y(\(r)h(=)g(vector)g(length,)e(default)h(=)i(1\))693 -4406 y(rA)95 b(-)47 b(character)e(string)693 4519 y(rAw)i(-)g(array)f -(of)i(strings,)d(each)i(of)g(length)f(w)693 4632 y(rL)95 -b(-)47 b(logical)693 4744 y(rX)95 b(-)47 b(bit)693 4857 -y(rB)95 b(-)47 b(unsigned)f(byte)693 4970 y(rS)95 b(-)47 -b(signed)f(byte)h(**)693 5083 y(rI)95 b(-)47 b(signed)f(16-bit)g -(integer)693 5196 y(rU)95 b(-)47 b(unsigned)f(16-bit)g(integer)g(**)693 -5309 y(rJ)95 b(-)47 b(signed)f(32-bit)g(integer)693 5422 -y(rV)95 b(-)47 b(unsigned)f(32-bit)g(integer)g(**)693 -5535 y(rK)95 b(-)47 b(signed)f(64-bit)g(integer)1905 -5809 y Ff(12)p eop end -%%Page: 13 13 -TeXDict begin 13 12 bop 693 573 a Fc(rE)95 b(-)47 b(32-bit)f(floating)g -(point)693 686 y(rD)95 b(-)47 b(64-bit)f(floating)g(point)693 -799 y(rC)95 b(-)47 b(32-bit)f(complex)g(pair)693 912 -y(rM)95 b(-)47 b(64-bit)f(complex)g(pair)359 1137 y(**)h(The)g(S,)g(U)g -(and)g(V)h(format)e(codes)g(are)h(not)g(actual)f(legal)g(TFORMn)h -(values.)502 1250 y(CFITSIO)f(substitutes)e(the)j(somewhat)f(more)g -(complicated)f(set)i(of)502 1363 y(keywords)e(that)i(are)g(used)g(to)g -(represent)e(unsigned)h(integers)f(or)502 1476 y(signed)h(bytes.)261 -1777 y Ff(The)27 b Fc(tunit)e Ff(and)h Fc(extname)f Ff(parameters)j -(are)f(optional)h(and)f(ma)m(y)g(b)s(e)g(set)g(to)h(NULL)f(if)g(they)g -(are)g(not)120 1890 y(needed.)261 2002 y(Note)41 b(that)f(it)f(ma)m(y)h -(b)s(e)f(easier)h(to)g(create)h(a)f(new)e(table)i(b)m(y)g(cop)m(ying)g -(the)f(header)g(from)g(another)120 2115 y(existing)31 -b(table)h(with)e Fc(fits)p 1089 2115 29 4 v 33 w(copy)p -1314 2115 V 33 w(header)f Ff(rather)h(than)g(calling)i(this)e(routine.) -120 2328 y Fc(________________________)o(____)o(____)o(___)o(____)o -(____)o(___)o(____)o(____)o(___)o(____)o(__)120 2441 -y(int)47 b(fits_get_num_rows\(fitsfi)o(le)42 b(*fptr,)k(long)g(*nrows,) -g(int)h(*status\))120 2554 y(int)g(fits_get_num_cols\(fitsfi)o(le)42 -b(*fptr,)k(int)94 b(*ncols,)46 b(int)h(*status\))261 -2766 y Ff(Get)37 b(the)g(n)m(um)m(b)s(er)d(of)j(ro)m(ws)f(or)g(columns) -g(in)f(the)i(curren)m(t)e(FITS)h(table.)59 b(The)35 b(n)m(um)m(b)s(er)g -(of)h(ro)m(ws)g(is)120 2879 y(giv)m(en)e(b)m(y)f(the)g -Fc(NAXIS2)e Ff(k)m(eyw)m(ord)j(and)e(the)h(n)m(um)m(b)s(er)f(of)h -(columns)g(is)g(giv)m(en)h(b)m(y)f(the)g Fc(TFIELDS)e -Ff(k)m(eyw)m(ord)120 2992 y(in)f(the)h(header)f(of)g(the)h(table.)120 -3205 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o -(___)o(____)o(____)o(___)o(____)o(__)120 3318 y(int)47 -b(fits_get_colnum\(fitsfile)41 b(*fptr,)46 b(int)h(casesen,)f(char)g -(*template,)1075 3430 y(int)g(*colnum,)g(int)h(*status\))120 -3543 y(int)g(fits_get_colname\(fitsfil)o(e)42 b(*fptr,)k(int)h -(casesen,)e(char)i(*template,)1075 3656 y(char)f(*colname,)f(int)i -(*colnum,)f(int)h(*status\))261 3869 y Ff(Get)33 b(the)e(column)g(n)m -(um)m(b)s(er)f(\(starting)j(with)e(1,)h(not)g(0\))g(of)f(the)h(column)f -(whose)g(name)h(matc)m(hes)g(the)120 3982 y(sp)s(eci\014ed)38 -b(template)i(name.)66 b(The)38 b(only)h(di\013erence)g(in)f(these)h(2)g -(routines)g(is)f(that)i(the)e(2nd)g(one)h(also)120 4095 -y(returns)29 b(the)i(name)f(of)h(the)f(column)g(that)h(matc)m(hed)h -(the)e(template)i(string.)261 4208 y(Normally)-8 b(,)29 -b Fc(casesen)24 b Ff(should)h(b)s(e)h(set)h(to)g Fc(CASEINSEN)p -Ff(,)d(but)i(it)g(ma)m(y)h(b)s(e)f(set)h(to)g Fc(CASESEN)d -Ff(to)j(force)g(the)120 4320 y(name)j(matc)m(hing)i(to)f(b)s(e)f -(case-sensitiv)m(e.)261 4433 y(The)22 b(input)f Fc(template)f -Ff(string)i(giv)m(es)i(the)e(name)h(of)f(the)h(desired)e(column)h(and)g -(ma)m(y)h(include)f(wildcard)120 4546 y(c)m(haracters:)41 -b(a)30 b(`*')g(matc)m(hes)g(an)m(y)f(sequence)g(of)h(c)m(haracters)g -(\(including)f(zero)h(c)m(haracters\),)h(`?')40 b(matc)m(hes)120 -4659 y(an)m(y)45 b(single)g(c)m(haracter,)50 b(and)44 -b(`#')h(matc)m(hes)g(an)m(y)g(consecutiv)m(e)i(string)d(of)h(decimal)h -(digits)f(\(0-9\).)85 b(If)120 4772 y(more)27 b(than)g(one)g(column)g -(name)g(in)g(the)g(table)h(matc)m(hes)g(the)f(template)h(string,)g -(then)f(the)g(\014rst)f(matc)m(h)i(is)120 4885 y(returned)22 -b(and)h(the)h(status)f(v)-5 b(alue)24 b(will)g(b)s(e)f(set)h(to)g -Fc(COL)p 1962 4885 V 33 w(NOT)p 2139 4885 V 34 w(UNIQUE)e -Ff(as)h(a)h(w)m(arning)f(that)h(a)g(unique)e(matc)m(h)120 -4998 y(w)m(as)34 b(not)g(found.)50 b(T)-8 b(o)35 b(\014nd)d(the)i(next) -g(column)g(that)h(matc)m(hes)g(the)f(template,)i(call)g(this)d(routine) -h(again)120 5111 y(lea)m(ving)e(the)f(input)e(status)i(v)-5 -b(alue)31 b(equal)g(to)g Fc(COL)p 1832 5111 V 33 w(NOT)p -2009 5111 V 34 w(UNIQUE)p Ff(.)e(Rep)s(eat)i(this)f(pro)s(cess)g(un)m -(til)h Fc(status)46 b(=)120 5224 y(COL)p 270 5224 V 34 -w(NOT)p 448 5224 V 33 w(FOUND)29 b Ff(is)h(returned.)120 -5436 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o -(___)o(____)o(____)o(___)o(____)o(__)120 5549 y(int)47 -b(fits_get_coltype\(fitsfil)o(e)42 b(*fptr,)k(int)h(colnum,)f(int)h -(*typecode,)1905 5809 y Ff(13)p eop end -%%Page: 14 14 -TeXDict begin 14 13 bop 1122 573 a Fc(long)47 b(*repeat,)e(long)i -(*width,)f(int)h(*status\))120 799 y(int)g(fits_get_eqcoltype\(fitsf)o -(ile)41 b(*fptr,)46 b(int)h(colnum,)f(int)h(*typecode,)1122 -912 y(long)g(*repeat,)e(long)i(*width,)f(int)h(*status\))261 -1106 y Ff(Return)41 b(the)h(datat)m(yp)s(e,)k(v)m(ector)d(rep)s(eat)f -(coun)m(t,)j(and)c(the)h(width)f(in)g(b)m(ytes)h(of)g(a)g(single)h -(column)120 1219 y(elemen)m(t)h(for)d(column)h(n)m(um)m(b)s(er)f -Fc(colnum)p Ff(.)74 b(Allo)m(w)m(ed)44 b(v)-5 b(alues)42 -b(for)g(the)g(returned)f(datat)m(yp)s(e)i(in)f(ASCI)s(I)120 -1332 y(tables)31 b(are:)42 b Fc(TSTRING,)j(TSHORT,)h(TLONG,)g(TFLOAT,)g -(and)h(TDOUBLE)p Ff(.)29 b(Binary)i(tables)g(supp)s(ort)e(these)120 -1445 y(additional)22 b(t)m(yp)s(es:)36 b Fc(TLOGICAL,)45 -b(TBIT,)h(TBYTE,)g(TINT32BIT,)f(TCOMPLEX)h(and)h(TDBLCOMPLEX)p -Ff(.)18 b(The)120 1558 y(negativ)m(e)33 b(of)d(the)h(datat)m(yp)s(e)g -(co)s(de)g(v)-5 b(alue)30 b(is)h(returned)e(if)h(it)h(is)g(a)f(v)-5 -b(ariable)32 b(length)e(arra)m(y)h(column.)261 1671 y(These)36 -b(2)h(routines)f(are)h(similar,)h(except)f(that)g(in)f(the)g(case)i(of) -e(scaled)h(in)m(teger)h(columns)e(the)g(2nd)120 1784 -y(routine,)28 b(\014t)p 547 1784 28 4 v 33 w(get)p 700 -1784 V 34 w(eqcolt)m(yp)s(e,)i(returns)c(the)i('equiv)-5 -b(alen)m(t')29 b(datat)m(yp)s(e)g(that)f(is)f(needed)h(to)g(store)g -(the)g(scaled)120 1897 y(v)-5 b(alues,)34 b(whic)m(h)e(is)h(not)g -(necessarily)g(the)g(same)g(as)g(the)g(ph)m(ysical)g(datat)m(yp)s(e)h -(of)f(the)g(unscaled)f(v)-5 b(alues)33 b(as)120 2010 -y(stored)h(in)g(the)h(FITS)e(table.)54 b(F)-8 b(or)35 -b(example)f(if)h(a)f('1I')h(column)f(in)g(a)h(binary)e(table)j(has)e -(TSCALn)e(=)i(1)120 2122 y(and)f(TZER)m(On)f(=)h(32768,)k(then)d(this)f -(column)h(e\013ectiv)m(ely)i(con)m(tains)f(unsigned)d(short)i(in)m -(teger)h(v)-5 b(alues,)120 2235 y(and)32 b(th)m(us)h(the)g(returned)f -(v)-5 b(alue)34 b(of)f(t)m(yp)s(eco)s(de)g(will)h(b)s(e)e(TUSHOR)-8 -b(T,)32 b(not)i(TSHOR)-8 b(T.)32 b(Or,)h(if)g(TSCALn)120 -2348 y(or)g(TZER)m(On)e(are)j(not)f(in)m(tegers,)i(then)d(the)h(equiv) --5 b(alen)m(t)34 b(datat)m(yp)s(e)g(will)f(b)s(e)g(returned)e(as)i -(TFLO)m(A)-8 b(T)33 b(or)120 2461 y(TDOUBLE,)e(dep)s(ending)d(on)j(the) -f(size)i(of)e(the)h(in)m(teger.)261 2574 y(The)e(rep)s(eat)h(coun)m(t)h -(is)e(alw)m(a)m(ys)j(1)e(in)f(ASCI)s(I)f(tables.)42 b(The)29 -b('rep)s(eat')h(parameter)g(returns)f(the)h(v)m(ector)120 -2687 y(rep)s(eat)23 b(coun)m(t)h(on)f(the)h(binary)e(table)j(TF)m(ORMn) -e(k)m(eyw)m(ord)g(v)-5 b(alue.)39 b(\(ASCI)s(I)22 b(table)i(columns)f -(alw)m(a)m(ys)i(ha)m(v)m(e)120 2800 y(rep)s(eat)35 b(=)f(1\).)55 -b(The)34 b('width')h(parameter)g(returns)f(the)h(width)f(in)g(b)m(ytes) -i(of)f(a)g(single)g(column)g(elemen)m(t)120 2913 y(\(e.g.,)h(a)e('10D') -h(binary)d(table)i(column)f(will)h(ha)m(v)m(e)g(width)f(=)g(8,)h(an)f -(ASCI)s(I)f(table)i('F12.2')i(column)d(will)120 3026 -y(ha)m(v)m(e)39 b(width)d(=)h(12,)j(and)d(a)h(binary)f(table'60A')i(c)m -(haracter)g(string)f(column)f(will)h(ha)m(v)m(e)g(width)f(=)g(60\);)120 -3139 y(Note)43 b(that)g(this)f(routine)f(supp)s(orts)g(the)h(lo)s(cal)h -(con)m(v)m(en)m(tion)h(for)e(sp)s(ecifying)f(arra)m(ys)i(of)f(\014xed)f -(length)120 3252 y(strings)32 b(within)f(a)h(binary)f(table)i(c)m -(haracter)h(column)d(using)h(the)g(syn)m(tax)g(TF)m(ORM)h(=)e('rAw')h -(where)f('r')120 3364 y(is)f(the)g(total)i(n)m(um)m(b)s(er)d(of)h(c)m -(haracters)i(\(=)e(the)g(width)g(of)g(the)g(column\))h(and)e('w')h(is)g -(the)h(width)e(of)h(a)h(unit)120 3477 y(string)h(within)f(the)h -(column.)45 b(Th)m(us)31 b(if)h(the)g(column)f(has)h(TF)m(ORM)g(=)f -('60A12')k(then)c(this)h(means)g(that)120 3590 y(eac)m(h)38 -b(ro)m(w)f(of)g(the)g(table)h(con)m(tains)g(5)g(12-c)m(haracter)i -(substrings)35 b(within)i(the)g(60-c)m(haracter)j(\014eld,)e(and)120 -3703 y(th)m(us)33 b(in)g(this)h(case)g(this)g(routine)f(will)h(return)e -(t)m(yp)s(eco)s(de)i(=)f(TSTRING,)g(rep)s(eat)h(=)f(60,)i(and)e(width)g -(=)120 3816 y(12.)47 b(The)31 b(n)m(um)m(b)s(er)g(of)h(substings)g(in)f -(an)m(y)i(binary)e(table)i(c)m(haracter)h(string)e(\014eld)g(can)g(b)s -(e)f(calculated)j(b)m(y)120 3929 y(\(rep)s(eat/width\).)47 -b(A)33 b(n)m(ull)f(p)s(oin)m(ter)g(ma)m(y)h(b)s(e)f(giv)m(en)h(for)f -(an)m(y)h(of)f(the)h(output)f(parameters)g(that)h(are)g(not)120 -4042 y(needed.)120 4237 y Fc(________________________)o(____)o(____)o -(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o -(____)o(____)120 4349 y(int)47 b(fits_insert_rows\(fitsfil)o(e)42 -b(*fptr,)k(long)h(firstrow,)e(long)h(nrows,)h(int)f(*status\))120 -4462 y(int)h(fits_delete_rows\(fitsfil)o(e)42 b(*fptr,)k(long)h -(firstrow,)e(long)h(nrows,)h(int)f(*status\))120 4575 -y(int)h(fits_delete_rowrange\(fit)o(sfil)o(e)42 b(*fptr,)k(char)g -(*rangelist,)f(int)i(*status\))120 4688 y(int)g -(fits_delete_rowlist\(fits)o(file)41 b(*fptr,)46 b(long)h(*rowlist,)e -(long)i(nrows,)f(int)h(*stat\))261 4883 y Ff(Insert)33 -b(or)g(delete)h(ro)m(ws)f(in)f(a)i(table.)49 b(The)33 -b(blank)f(ro)m(ws)h(are)h(inserted)e(immediately)j(follo)m(wing)f(ro)m -(w)120 4996 y Fc(frow)p Ff(.)54 b(Set)35 b Fc(frow)f -Ff(=)g(0)i(to)f(insert)g(ro)m(ws)g(at)h(the)f(b)s(eginning)g(of)g(the)g -(table.)56 b(The)34 b(\014rst)h('delete')h(routine)120 -5109 y(deletes)k Fc(nrows)d Ff(ro)m(ws)i(b)s(eginning)f(with)h(ro)m(w)g -Fc(firstrow)p Ff(.)64 b(The)38 b(2nd)g(delete)i(routine)f(tak)m(es)i -(an)d(input)120 5222 y(string)27 b(listing)h(the)f(ro)m(ws)f(or)h(ro)m -(w)g(ranges)g(to)h(b)s(e)e(deleted)i(\(e.g.,)h('2,4-7,)h(9-12'\).)42 -b(The)26 b(last)i(delete)g(routine)120 5334 y(tak)m(es)35 -b(an)f(input)e(long)i(in)m(teger)h(arra)m(y)g(that)f(sp)s(eci\014es)f -(eac)m(h)i(individual)e(ro)m(w)h(to)g(b)s(e)f(deleted.)51 -b(The)33 b(ro)m(w)120 5447 y(lists)j(m)m(ust)f(b)s(e)f(sorted)i(in)f -(ascending)g(order.)55 b(All)36 b(these)g(routines)f(up)s(date)f(the)i -(v)-5 b(alue)35 b(of)h(the)f Fc(NAXIS2)120 5560 y Ff(k)m(eyw)m(ord)c -(to)g(re\015ect)g(the)f(new)g(n)m(um)m(b)s(er)f(of)i(ro)m(ws)f(in)g -(the)h(table.)1905 5809 y(14)p eop end -%%Page: 15 15 -TeXDict begin 15 14 bop 120 573 a Fc(________________________)o(____)o -(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o -(___)o(____)o(_)120 686 y(int)47 b(fits_insert_col\(fitsfile)41 -b(*fptr,)46 b(int)h(colnum,)f(char)h(*ttype,)e(char)i(*tform,)1075 -799 y(int)f(*status\))120 912 y(int)h(fits_insert_cols\(fitsfil)o(e)42 -b(*fptr,)k(int)h(colnum,)f(int)h(ncols,)f(char)g(**ttype,)1122 -1024 y(char)h(**tform,)e(int)i(*status\))120 1250 y(int)g -(fits_delete_col\(fitsfile)41 b(*fptr,)46 b(int)h(colnum,)f(int)h -(*status\))261 1457 y Ff(Insert)25 b(or)g(delete)h(columns)f(in)f(a)i -(table.)39 b Fc(colnum)24 b Ff(giv)m(es)i(the)f(p)s(osition)g(of)g(the) -h(column)e(to)i(b)s(e)f(inserted)120 1570 y(or)34 b(deleted)g(\(where)g -(the)g(\014rst)f(column)h(of)g(the)g(table)h(is)e(at)i(p)s(osition)f -(1\).)52 b Fc(ttype)32 b Ff(and)h Fc(tform)g Ff(giv)m(e)i(the)120 -1683 y(column)j(name)h(and)f(column)g(format,)j(where)d(the)h(allo)m(w) -m(ed)i(format)d(co)s(des)h(are)g(listed)g(ab)s(o)m(v)m(e)h(in)e(the)120 -1796 y(description)45 b(of)g(the)h Fc(fits)p 1088 1796 -29 4 v 33 w(create)p 1409 1796 V 33 w(table)d Ff(routine.)85 -b(The)45 b(2nd)f('insert')i(routine)f(inserts)g(m)m(ultiple)120 -1909 y(columns,)33 b(where)g Fc(ncols)e Ff(is)i(the)g(n)m(um)m(b)s(er)e -(of)i(columns)g(to)g(insert,)h(and)e Fc(ttype)f Ff(and)h -Fc(tform)g Ff(are)h(arra)m(ys)120 2022 y(of)e(string)f(p)s(oin)m(ters)g -(in)g(this)g(case.)120 2229 y Fc(________________________)o(____)o -(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o -(___)120 2342 y(int)47 b(fits_copy_col\(fitsfile)42 b(*infptr,)j -(fitsfile)h(*outfptr,)f(int)i(incolnum,)502 2455 y(int)g(outcolnum,)e -(int)i(create_col,)d(int)j(*status\);)261 2662 y Ff(Cop)m(y)31 -b(a)g(column)g(from)f(one)i(table)f(HDU)h(to)g(another.)42 -b(If)31 b Fc(create)p 2609 2662 V 32 w(col)f Ff(=)h(TR)m(UE)g(\(i.e.,)i -(not)e(equal)120 2775 y(to)42 b(zero\),)k(then)41 b(a)h(new)f(column)g -(will)h(b)s(e)f(inserted)g(in)h(the)f(output)g(table)i(at)f(p)s -(osition)g Fc(outcolumn)p Ff(,)120 2888 y(otherwise)31 -b(the)f(v)-5 b(alues)31 b(in)f(the)h(existing)g(output)f(column)g(will) -h(b)s(e)f(o)m(v)m(erwritten.)120 3095 y Fc(________________________)o -(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o -(____)o(___)o(____)o(__)120 3208 y(int)47 b(fits_write_col\(fitsfile)41 -b(*fptr,)46 b(int)h(datatype,)f(int)h(colnum,)e(long)i(firstrow,)979 -3321 y(long)g(firstelem,)e(long)h(nelements,)f(void)i(*array,)f(int)h -(*status\))120 3434 y(int)g(fits_write_colnull\(fitsf)o(ile)41 -b(*fptr,)46 b(int)h(datatype,)f(int)g(colnum,)979 3547 -y(long)h(firstrow,)e(long)i(firstelem,)e(long)h(nelements,)979 -3660 y(void)h(*array,)f(void)g(*nulval,)g(int)h(*status\))120 -3772 y(int)g(fits_write_col_null\(fits)o(file)41 b(*fptr,)46 -b(int)h(colnum,)f(long)g(firstrow,)979 3885 y(long)h(firstelem,)e(long) -h(nelements,)f(int)i(*status\))120 4111 y(int)g -(fits_read_col\(fitsfile)42 b(*fptr,)k(int)h(datatype,)e(int)i(colnum,) -f(long)g(firstrow,)454 4224 y(long)h(firstelem,)e(long)h(nelements,)f -(void)i(*nulval,)f(void)g(*array,)454 4337 y(int)h(*anynul,)f(int)g -(*status\))261 4657 y Ff(W)-8 b(rite)45 b(or)e(read)g(elemen)m(ts)i(in) -e(column)g(n)m(um)m(b)s(er)f Fc(colnum)p Ff(,)j(starting)f(with)f(ro)m -(w)g Fc(firstsrow)e Ff(and)120 4770 y(elemen)m(t)34 b -Fc(firstelem)c Ff(\(if)j(it)g(is)g(a)g(v)m(ector)h(column\).)47 -b Fc(firstelem)30 b Ff(is)j(ignored)g(if)f(it)h(is)g(a)g(scalar)g -(column.)120 4883 y(The)c Fc(nelements)f Ff(n)m(um)m(b)s(er)g(of)i -(elemen)m(ts)i(are)e(read)g(or)f(written)h(con)m(tin)m(uing)h(on)f -(successiv)m(e)h(ro)m(ws)f(of)g(the)120 4996 y(table)37 -b(if)f(necessary)-8 b(.)59 b Fc(array)35 b Ff(is)h(the)h(address)e(of)h -(an)g(arra)m(y)h(whic)m(h)f(either)h(con)m(tains)g(the)g(v)-5 -b(alues)36 b(to)h(b)s(e)120 5109 y(written,)28 b(or)e(will)h(hold)g -(the)f(returned)g(v)-5 b(alues)27 b(that)g(are)g(read.)39 -b(When)27 b(reading,)h Fc(array)d Ff(m)m(ust)h(ha)m(v)m(e)i(b)s(een)120 -5222 y(allo)s(cated)k(large)g(enough)e(to)h(hold)f(all)h(the)g -(returned)e(v)-5 b(alues.)261 5334 y(There)40 b(are)h(3)h(di\013eren)m -(t)f('write')g(column)g(routines:)61 b(The)40 b(\014rst)g(simply)g -(writes)h(the)g(input)f(arra)m(y)120 5447 y(in)m(to)33 -b(the)f(column.)44 b(The)31 b(second)h(is)g(similar,)g(except)h(that)f -(it)g(substitutes)g(the)g(appropriate)f(n)m(ull)h(pixel)120 -5560 y(v)-5 b(alue)36 b(in)e(the)i(column)e(for)h(an)m(y)h(input)e -(arra)m(y)h(v)-5 b(alues)36 b(whic)m(h)f(are)g(equal)h(to)g -Fc(*nulval)d Ff(\(note)j(that)f(this)1905 5809 y(15)p -eop end -%%Page: 16 16 -TeXDict begin 16 15 bop 120 573 a Ff(parameter)39 b(giv)m(es)g(the)g -(address)e(of)i(the)f(n)m(ull)g(pixel)h(v)-5 b(alue,)41 -b(not)d(the)h(v)-5 b(alue)38 b(itself)7 b(\).)66 b(The)38 -b(third)f(write)120 686 y(routine)28 b(sets)g(the)g(sp)s(eci\014ed)f -(table)i(elemen)m(ts)g(to)g(a)f(n)m(ull)g(v)-5 b(alue.)40 -b(New)28 b(ro)m(ws)g(will)g(b)s(e)g(automatical)i(added)120 -799 y(to)h(the)g(table)g(if)f(the)h(write)f(op)s(eration)h(extends)g(b) -s(ey)m(ond)e(the)i(curren)m(t)f(size)h(of)g(the)f(table.)261 -912 y(When)42 b(reading)g(a)h(column,)i(CFITSIO)40 b(will)j(substitute) -f(the)g(v)-5 b(alue)43 b(giv)m(en)g(b)m(y)f Fc(nulval)e -Ff(for)i(an)m(y)120 1024 y(unde\014ned)25 b(elemen)m(ts)j(in)f(the)g -(FITS)f(column,)i(unless)e Fc(nulval)f Ff(or)i Fc(*nulval)46 -b(=)h(NULL)p Ff(,)26 b(in)h(whic)m(h)f(case)i(no)120 -1137 y(c)m(hec)m(ks)k(will)f(b)s(e)e(made)i(for)f(unde\014ned)e(v)-5 -b(alues)31 b(when)e(reading)i(the)f(column.)261 1250 -y Fc(datatype)i Ff(sp)s(eci\014es)i(the)g(datat)m(yp)s(e)h(of)g(the)f -(C)g Fc(array)e Ff(in)i(the)g(program,)i(whic)m(h)d(need)h(not)h(b)s(e) -e(the)120 1363 y(same)42 b(as)f(the)g(in)m(trinsic)h(datat)m(yp)s(e)g -(of)f(the)h(column)f(in)g(the)g(FITS)g(table.)74 b(The)40 -b(follo)m(wing)j(sym)m(b)s(olic)120 1476 y(constan)m(ts)32 -b(are)e(allo)m(w)m(ed)j(for)d(the)g(v)-5 b(alue)31 b(of)g -Fc(datatype)p Ff(:)215 1650 y Fc(TSTRING)142 b(array)46 -b(of)h(character)f(string)g(pointers)215 1763 y(TBYTE)238 -b(unsigned)45 b(char)215 1876 y(TSHORT)190 b(signed)46 -b(short)215 1989 y(TUSHORT)142 b(unsigned)45 b(short)215 -2102 y(TINT)286 b(signed)46 b(int)215 2215 y(TUINT)238 -b(unsigned)45 b(int)215 2328 y(TLONG)238 b(signed)46 -b(long)215 2441 y(TLONGLONG)g(signed)g(8-byte)g(integer)215 -2554 y(TULONG)190 b(unsigned)45 b(long)215 2667 y(TFLOAT)190 -b(float)215 2779 y(TDOUBLE)142 b(double)261 2954 y Ff(Note)35 -b(that)e Fc(TSTRING)f Ff(corresp)s(onds)g(to)h(the)h(C)f -Fc(char**)e Ff(datat)m(yp)s(e,)k(i.e.,)h(a)d(p)s(oin)m(ter)g(to)h(an)f -(arra)m(y)h(of)120 3067 y(p)s(oin)m(ters)c(to)h(an)g(arra)m(y)f(of)h(c) -m(haracters.)261 3179 y(An)m(y)38 b(column,)j(regardless)d(of)h(it's)g -(in)m(trinsic)f(datat)m(yp)s(e,)k(ma)m(y)d(b)s(e)e(read)h(as)h(a)f -Fc(TSTRING)f Ff(c)m(haracter)120 3292 y(string.)i(The)24 -b(displa)m(y)i(format)f(of)g(the)h(returned)e(strings)g(will)i(b)s(e)e -(determined)h(b)m(y)g(the)g Fc(TDISPn)f Ff(k)m(eyw)m(ord,)120 -3405 y(if)j(it)h(exists,)h(otherwise)f(a)f(default)h(format)g(will)f(b) -s(e)g(used)f(dep)s(ending)g(on)i(the)f(datat)m(yp)s(e)h(of)g(the)f -(column.)120 3518 y(The)22 b Fc(tablist)e Ff(example)j(utilit)m(y)h -(program)e(\(a)m(v)-5 b(ailable)25 b(from)d(the)h(CFITSIO)e(w)m(eb)h -(site\))i(uses)e(this)g(feature)120 3631 y(to)31 b(displa)m(y)g(all)g -(the)g(v)-5 b(alues)30 b(in)g(a)h(FITS)f(table.)120 3805 -y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o(___)o -(____)o(____)o(___)o(____)o(____)o(___)o(_)120 3918 y(int)47 -b(fits_select_rows\(fitsfil)o(e)42 b(*infptr,)j(fitsfile)h(*outfptr,)f -(char)i(*expr,)1122 4031 y(int)g(*status\))120 4144 y(int)g -(fits_calculator\(fitsfile)41 b(*infptr,)46 b(char)g(*expr,)g(fitsfile) -g(*outfptr,)1075 4257 y(char)g(*colname,)f(char)i(*tform,)f(int)h -(*status\))261 4431 y Ff(These)26 b(are)h(2)g(of)g(the)f(most)h(p)s(o)m -(w)m(erful)f(routines)h(in)f(the)h(CFITSIO)d(library)-8 -b(.)40 b(\(See)27 b(the)g(full)f(CFITSIO)120 4544 y(Reference)37 -b(Guide)f(for)g(a)h(description)f(of)g(sev)m(eral)i(related)f -(routines\).)58 b(These)36 b(routines)g(can)h(p)s(erform)120 -4657 y(complicated)47 b(transformations)f(on)f(tables)h(based)f(on)g -(an)g(input)g(arithmetic)h(expression)f(whic)m(h)g(is)120 -4770 y(ev)-5 b(aluated)38 b(for)e(eac)m(h)h(ro)m(w)g(of)g(the)f(table.) -60 b(The)36 b(\014rst)g(routine)g(will)h(select)h(or)f(cop)m(y)g(ro)m -(ws)f(of)h(the)f(table)120 4883 y(for)i(whic)m(h)g(the)g(expression)g -(ev)-5 b(aluates)40 b(to)f(TR)m(UE)g(\(i.e.,)i(not)e(equal)g(to)g -(zero\).)65 b(The)38 b(second)g(routine)120 4996 y(writes)d(the)g(v)-5 -b(alue)35 b(of)g(the)g(expression)g(to)h(a)f(column)g(in)f(the)h -(output)g(table.)55 b(Rather)35 b(than)g(supplying)120 -5109 y(the)j(expression)f(directly)h(to)g(these)g(routines,)i(the)d -(expression)h(ma)m(y)g(also)g(b)s(e)f(written)h(to)g(a)g(text)g(\014le) -120 5222 y(\(con)m(tin)m(ued)f(o)m(v)m(er)f(m)m(ultiple)h(lines)e(if)h -(necessary\))g(and)f(the)h(name)f(of)h(the)g(\014le,)h(prep)s(ended)c -(with)i(a)h('@')120 5334 y(c)m(haracter,)c(ma)m(y)f(b)s(e)f(supplied)f -(as)i(the)f(v)-5 b(alue)31 b(of)g(the)f('expr')g(parameter)h(\(e.g.)42 -b('@\014lename.txt'\).)261 5447 y(The)26 b(arithmetic)h(expression)f -(ma)m(y)h(b)s(e)f(a)g(function)g(of)g(an)m(y)h(column)f(or)g(k)m(eyw)m -(ord)h(in)f(the)g(input)f(table)120 5560 y(as)31 b(sho)m(wn)e(in)h -(these)h(examples:)1905 5809 y(16)p eop end -%%Page: 17 17 -TeXDict begin 17 16 bop 120 573 a Fc(Row)47 b(Selection)e(Expressions:) -263 686 y(counts)h(>)i(0)1240 b(uses)47 b(COUNTS)f(column)g(value)263 -799 y(sqrt\()h(X**2)f(+)i(Y**2\))e(<)h(10.)572 b(uses)47 -b(X)g(and)g(Y)h(column)e(values)263 912 y(\(X)h(>)h(10\))f(||)g(\(X)g -(<)h(-10\))e(&&)h(\(Y)h(==)f(0\))142 b(used)47 b('or')g(and)g('and')f -(operators)263 1024 y(gtifilter\(\))1190 b(filter)46 -b(on)i(Good)e(Time)h(Intervals)263 1137 y(regfilter\("myregion.reg"\)) -518 b(filter)46 b(using)h(a)g(region)f(file)263 1250 -y(@select.txt)1190 b(reads)47 b(expression)e(from)h(a)i(text)e(file)120 -1363 y(Calculator)f(Expressions:)263 1476 y(#row)i(\045)g(10)1145 -b(modulus)46 b(of)h(the)g(row)g(number)263 1589 y(counts/#exposure)807 -b(Fn)47 b(of)h(COUNTS)e(column)g(and)h(EXPOSURE)e(keyword)263 -1702 y(dec)i(<)h(85)f(?)g(cos\(dec)f(*)h(#deg\))g(:)g(0)143 -b(Conditional)45 b(expression:)g(evaluates)g(to)1934 -1815 y(cos\(dec\))g(if)i(dec)g(<)h(85,)f(else)f(0)263 -1928 y(\(count{-1}+count+count{+1)o(}\)/3)o(.)137 b(running)46 -b(mean)h(of)g(the)g(count)f(values)g(in)h(the)1934 2041 -y(previous,)e(current,)g(and)i(next)g(rows)263 2154 y(max\(0,)f -(min\(X,)g(1000\)\))619 b(returns)46 b(a)h(value)g(between)f(0)h(-)h -(1000)263 2267 y(@calc.txt)1143 b(reads)47 b(expression)e(from)h(a)i -(text)e(file)261 2479 y Ff(Most)40 b(standard)d(mathematical)k(op)s -(erators)e(and)f(functions)g(are)h(supp)s(orted.)64 b(If)38 -b(the)h(expression)120 2592 y(includes)34 b(the)h(name)f(of)h(a)f -(column,)i(than)e(the)h(v)-5 b(alue)35 b(in)f(the)g(curren)m(t)h(ro)m -(w)f(of)h(the)f(table)i(will)e(b)s(e)g(used)120 2705 -y(when)f(ev)-5 b(aluating)35 b(the)f(expression)g(on)g(eac)m(h)h(ro)m -(w.)51 b(An)34 b(o\013set)h(to)g(an)e(adjacen)m(t)j(ro)m(w)e(can)g(b)s -(e)f(sp)s(eci\014ed)120 2818 y(b)m(y)d(including)g(the)g(o\013set)h(v) --5 b(alue)30 b(in)g(curly)g(brac)m(k)m(ets)h(after)g(the)f(column)g -(name)g(as)g(sho)m(wn)g(in)g(one)g(of)g(the)120 2931 -y(examples.)40 b(Keyw)m(ord)27 b(v)-5 b(alues)28 b(can)f(b)s(e)g -(included)f(in)h(the)h(expression)f(b)m(y)g(preceding)g(the)h(k)m(eyw)m -(ord)f(name)120 3044 y(with)h(a)h(`#')f(sign.)40 b(See)28 -b(Section)i(5)e(of)h(this)f(do)s(cumen)m(t)g(for)g(more)g(discussion)g -(of)g(the)h(expression)f(syn)m(tax.)261 3156 y Fc(gtifilter)h -Ff(is)i(a)h(sp)s(ecial)g(function)f(whic)m(h)g(tests)h(whether)f(the)h -Fc(TIME)e Ff(column)h(v)-5 b(alue)32 b(in)f(the)g(input)120 -3269 y(table)39 b(falls)g(within)f(one)h(or)f(more)h(Go)s(o)s(d)f(Time) -g(In)m(terv)-5 b(als.)66 b(By)39 b(default,)h(this)f(function)f(lo)s -(oks)h(for)f(a)120 3382 y('GTI')27 b(extension)g(in)f(the)h(same)g -(\014le)f(as)h(the)g(input)e(table.)41 b(The)26 b('GTI')g(table)i(con)m -(tains)g Fc(START)d Ff(and)h Fc(STOP)120 3495 y Ff(columns)g(whic)m(h)h -(de\014ne)f(the)g(range)h(of)g(eac)m(h)h(go)s(o)s(d)f(time)g(in)m(terv) --5 b(al.)41 b(See)27 b(section)g(5.4.3)i(for)d(more)h(details.)261 -3608 y Fc(regfilter)35 b Ff(is)i(another)g(sp)s(ecial)h(function)f -(whic)m(h)g(selects)h(ro)m(ws)g(based)e(on)h(whether)g(the)g(spatial) -120 3721 y(p)s(osition)23 b(asso)s(ciated)i(with)e(eac)m(h)i(ro)m(w)e -(is)g(lo)s(cated)i(within)e(in)g(a)g(sp)s(eci\014ed)g(region)h(of)f -(the)h(sky)-8 b(.)38 b(By)24 b(default,)120 3834 y(the)35 -b Fc(X)g Ff(and)f Fc(Y)h Ff(columns)g(in)g(the)g(input)f(table)i(are)f -(assumed)g(to)h(giv)m(e)g(the)f(p)s(osition)g(of)h(eac)m(h)g(ro)m(w.)55 -b(The)120 3947 y(spatial)37 b(region)f(is)f(de\014ned)g(in)g(an)g(ASCI) -s(I)f(text)j(\014le)e(whose)h(name)f(is)h(giv)m(en)g(as)g(the)g -(argumen)m(t)g(to)g(the)120 4060 y Fc(regfilter)28 b -Ff(function.)40 b(See)31 b(section)g(5.4.4)i(for)d(more)g(details.)261 -4173 y(The)e Fc(infptr)e Ff(and)i Fc(outfptr)e Ff(parameters)j(in)f -(these)g(routines)g(ma)m(y)h(p)s(oin)m(t)f(to)h(the)g(same)f(table)h -(or)g(to)120 4286 y(di\013eren)m(t)i(tables.)43 b(In)31 -b Fc(fits)p 1092 4286 29 4 v 33 w(select)p 1413 4286 -V 33 w(rows)p Ff(,)f(if)g(the)i(input)d(and)i(output)f(tables)i(are)f -(the)g(same)h(then)e(the)120 4399 y(ro)m(ws)e(that)h(do)f(not)g -(satisfy)h(the)f(selection)i(expression)e(will)g(b)s(e)f(deleted)i -(from)f(the)g(table.)41 b(Otherwise,)28 b(if)120 4511 -y(the)j(output)g(table)h(is)f(di\013eren)m(t)h(from)f(the)g(input)f -(table)i(then)f(the)g(selected)i(ro)m(ws)e(will)h(b)s(e)e(copied)i -(from)120 4624 y(the)f(input)e(table)i(to)g(the)g(output)f(table.)261 -4737 y(The)i(output)g(column)g(in)g Fc(fits)p 1376 4737 -V 33 w(calculator)e Ff(ma)m(y)i(or)h(ma)m(y)g(not)f(already)h(exist.)47 -b(If)32 b(it)h(exists)g(then)120 4850 y(the)44 b(calculated)h(v)-5 -b(alues)44 b(will)g(b)s(e)f(written)h(to)g(that)h(column,)i(o)m(v)m -(erwriting)e(the)e(existing)i(v)-5 b(alues.)81 b(If)120 -4963 y(the)36 b(column)g(do)s(esn't)g(exist)g(then)g(the)g(new)g -(column)f(will)i(b)s(e)e(app)s(ended)f(to)j(the)f(output)g(table.)58 -b(The)120 5076 y Fc(tform)37 b Ff(parameter)i(can)f(b)s(e)g(used)g(to)h -(sp)s(ecify)f(the)g(datat)m(yp)s(e)i(of)e(the)h(new)f(column)g(\(e.g.,) -k(the)d Fc(TFORM)120 5189 y Ff(k)m(eyw)m(ord)26 b(v)-5 -b(alue)26 b(as)g(in)g Fc('1E',)46 b(or)h('1J')p Ff(\).)25 -b(If)h Fc(tform)e Ff(=)h(NULL)h(then)f(a)h(default)g(datat)m(yp)s(e)h -(will)f(b)s(e)f(used,)120 5302 y(dep)s(ending)k(on)h(the)h(expression.) -120 5514 y Fc(________________________)o(____)o(____)o(___)o(____)o -(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(_)1905 -5809 y Ff(17)p eop end -%%Page: 18 18 -TeXDict begin 18 17 bop 120 573 a Fc(int)47 b -(fits_read_tblbytes\(fitsf)o(ile)41 b(*fptr,)46 b(long)h(firstrow,)e -(long)i(firstchar,)1122 686 y(long)g(nchars,)f(unsigned)f(char)i -(*array,)f(int)h(*status\))120 799 y(int)g(fits_write_tblbytes)42 -b(\(fitsfile)k(*fptr,)g(long)g(firstrow,)g(long)g(firstchar,)1122 -912 y(long)h(nchars,)f(unsigned)f(char)i(*array,)f(int)h(*status\))261 -1124 y Ff(These)35 b(2)g(routines)f(pro)m(vide)h(lo)m(w-lev)m(el)j -(access)e(to)f(tables)h(and)e(are)h(mainly)g(useful)f(as)h(an)g -(e\016cien)m(t)120 1237 y(w)m(a)m(y)i(to)g(cop)m(y)g(ro)m(ws)f(of)g(a)h -(table)g(from)f(one)g(\014le)g(to)h(another.)58 b(These)36 -b(routines)g(simply)g(read)g(or)g(write)120 1350 y(the)30 -b(sp)s(eci\014ed)g(n)m(um)m(b)s(er)f(of)h(consecutiv)m(e)j(c)m -(haracters)e(\(b)m(ytes\))h(in)e(a)h(table,)g(without)f(regard)g(for)h -(column)120 1463 y(b)s(oundaries.)84 b(F)-8 b(or)47 b(example,)j(to)c -(read)f(or)h(write)f(the)h(\014rst)f(ro)m(w)g(of)h(a)g(table,)k(set)c -Fc(firstrow)g(=)h(1,)120 1576 y(firstchar)e(=)j(1)p Ff(,)38 -b(and)e Fc(nchars)46 b(=)i(NAXIS1)35 b Ff(where)h(the)h(length)g(of)g -(a)h(ro)m(w)f(is)f(giv)m(en)i(b)m(y)f(the)g(v)-5 b(alue)37 -b(of)120 1689 y(the)31 b Fc(NAXIS1)f Ff(header)h(k)m(eyw)m(ord.)43 -b(When)31 b(reading)h(a)f(table,)i Fc(array)d Ff(m)m(ust)h(ha)m(v)m(e)h -(b)s(een)f(declared)g(at)h(least)120 1802 y Fc(nchars)d -Ff(b)m(ytes)i(long)g(to)g(hold)f(the)g(returned)f(string)i(of)f(b)m -(ytes.)1905 5809 y(18)p eop end -%%Page: 19 19 -TeXDict begin 19 18 bop 120 573 a Fb(4.6)112 b(Header)38 -b(Keyw)m(ord)f(I/O)h(Routines)120 744 y Ff(The)30 b(follo)m(wing)i -(routines)e(read)g(and)g(write)h(header)f(k)m(eyw)m(ords)g(in)h(the)f -(curren)m(t)g(HDU.)120 957 y Fc(________________________)o(____)o(____) -o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)120 -1070 y(int)47 b(fits_get_hdrspace\(fitsfi)o(le)42 b(*fptr,)k(int)h -(*keysexist,)d(int)j(*morekeys,)1170 1183 y(int)g(*status\))120 -1395 y Ff(Return)36 b(the)g(n)m(um)m(b)s(er)f(of)i(existing)g(k)m(eyw)m -(ords)g(\(not)g(coun)m(ting)g(the)g(mandatory)f(END)h(k)m(eyw)m(ord\))g -(and)120 1508 y(the)29 b(amoun)m(t)h(of)f(empt)m(y)h(space)g(curren)m -(tly)f(a)m(v)-5 b(ailable)31 b(for)e(more)h(k)m(eyw)m(ords.)40 -b(The)29 b Fc(morekeys)e Ff(parameter)120 1621 y(ma)m(y)k(b)s(e)f(set)h -(to)g(NULL)f(if)g(it's)h(v)-5 b(alue)31 b(is)g(not)f(needed.)120 -1834 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o -(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(___)120 -1947 y(int)47 b(fits_read_record\(fitsfil)o(e)42 b(*fptr,)k(int)h -(keynum,)f(char)g(*record,)g(int)h(*status\))120 2060 -y(int)g(fits_read_card\(fitsfile)41 b(*fptr,)46 b(char)h(*keyname,)e -(char)i(*record,)f(int)g(*status\))120 2172 y(int)h -(fits_read_key\(fitsfile)42 b(*fptr,)k(int)h(datatype,)e(char)i -(*keyname,)979 2285 y(void)g(*value,)f(char)g(*comment,)f(int)i -(*status\))120 2511 y(int)g(fits_find_nextkey\(fitsfi)o(le)42 -b(*fptr,)k(char)g(**inclist,)f(int)i(ninc,)1170 2624 -y(char)g(**exclist,)e(int)i(nexc,)f(char)h(*card,)f(int)h(*status\))120 -2850 y(int)g(fits_read_key_unit\(fitsf)o(ile)41 b(*fptr,)46 -b(char)h(*keyname,)e(char)i(*unit,)1218 2963 y(int)g(*status\))261 -3175 y Ff(These)d(routines)h(all)g(read)f(a)h(header)f(record)g(in)g -(the)h(curren)m(t)f(HDU.)i(The)e(\014rst)f(routine)i(reads)120 -3288 y(k)m(eyw)m(ord)40 b(n)m(um)m(b)s(er)f Fc(keynum)f -Ff(\(where)i(the)g(\014rst)f(k)m(eyw)m(ord)i(is)f(at)h(p)s(osition)f -(1\).)70 b(This)39 b(routine)h(is)g(most)120 3401 y(commonly)29 -b(used)f(when)f(sequen)m(tially)j(reading)e(ev)m(ery)i(record)e(in)g -(the)h(header)f(from)g(b)s(eginning)g(to)h(end.)120 3514 -y(The)d(2nd)f(and)g(3rd)h(routines)g(read)g(the)g(named)f(k)m(eyw)m -(ord)i(and)e(return)g(either)i(the)f(whole)g(record,)h(or)f(the)120 -3627 y(k)m(eyw)m(ord)g(v)-5 b(alue)26 b(and)e(commen)m(t)j(string.)39 -b(In)25 b(eac)m(h)h(case)h(an)m(y)e(non-signi\014can)m(t)h(trailing)h -(blank)e(c)m(haracters)120 3740 y(in)30 b(the)h(strings)f(are)h -(truncated.)261 3853 y(Wild)c(card)e(c)m(haracters)j(\(*,)g(?,)f(and)e -(#\))h(ma)m(y)h(b)s(e)e(used)g(when)g(sp)s(ecifying)h(the)g(name)h(of)f -(the)g(k)m(eyw)m(ord)120 3966 y(to)31 b(b)s(e)f(read,)g(in)g(whic)m(h)h -(case)g(the)g(\014rst)e(matc)m(hing)j(k)m(eyw)m(ord)e(is)h(returned.) -261 4079 y(The)41 b Fc(datatype)e Ff(parameter)j(sp)s(eci\014es)f(the)g -(C)g(datat)m(yp)s(e)h(of)g(the)f(returned)f(k)m(eyw)m(ord)i(v)-5 -b(alue)42 b(and)120 4192 y(can)48 b(ha)m(v)m(e)h(one)f(of)g(the)f -(follo)m(wing)i(sym)m(b)s(olic)f(constan)m(t)h(v)-5 b(alues:)76 -b Fc(TSTRING,)46 b(TLOGICAL)f Ff(\(==)i(in)m(t\),)120 -4304 y Fc(TBYTE)p Ff(,)d Fc(TSHORT)p Ff(,)f Fc(TUSHORT)p -Ff(,)g Fc(TINT)p Ff(,)h Fc(TUINT)p Ff(,)f Fc(TLONG)p -Ff(,)h Fc(TULONG)p Ff(,)f Fc(TFLOAT)p Ff(,)g Fc(TDOUBLE)p -Ff(,)g Fc(TCOMPLEX)p Ff(,)g(and)120 4417 y Fc(TDBLCOMPLEX)p -Ff(.)e(Data)k(t)m(yp)s(e)f(con)m(v)m(ersion)h(will)f(b)s(e)f(p)s -(erformed)f(for)i(n)m(umeric)f(v)-5 b(alues)44 b(if)g(the)g(in)m -(trinsic)120 4530 y(FITS)32 b(k)m(eyw)m(ord)h(v)-5 b(alue)33 -b(do)s(es)f(not)g(ha)m(v)m(e)i(the)f(same)g(datat)m(yp)s(e.)48 -b(The)32 b Fc(comment)e Ff(parameter)j(ma)m(y)g(b)s(e)f(set)120 -4643 y(equal)f(to)g(NULL)f(if)h(the)f(commen)m(t)i(string)e(is)g(not)h -(needed.)261 4756 y(The)21 b(4th)h(routine)g(pro)m(vides)g(an)g(easy)g -(w)m(a)m(y)h(to)f(\014nd)e(all)j(the)f(k)m(eyw)m(ords)g(in)g(the)f -(header)h(that)g(matc)m(h)h(one)120 4869 y(of)29 b(the)h(name)f -(templates)h(in)f Fc(inclist)e Ff(and)h(do)h(not)h(matc)m(h)g(an)m(y)f -(of)g(the)h(name)f(templates)h(in)f Fc(exclist)p Ff(.)120 -4982 y Fc(ninc)37 b Ff(and)h Fc(nexc)f Ff(are)i(the)g(n)m(um)m(b)s(er)e -(of)h(template)i(strings)e(in)g Fc(inclist)f Ff(and)h -Fc(exclist)p Ff(,)g(resp)s(ectiv)m(ely)-8 b(.)120 5095 -y(Wild)35 b(cards)f(\(*,)i(?,)f(and)f(#\))g(ma)m(y)h(b)s(e)f(used)f(in) -h(the)g(templates)i(to)f(matc)m(h)g(m)m(ultiple)g(k)m(eyw)m(ords.)53 -b(Eac)m(h)120 5208 y(time)36 b(this)f(routine)g(is)g(called)h(it)f -(returns)f(the)h(next)h(matc)m(hing)g(80-b)m(yte)g(k)m(eyw)m(ord)g -(record.)54 b(It)36 b(returns)120 5321 y(status)31 b(=)f -Fc(KEY)p 640 5321 29 4 v 33 w(NO)p 769 5321 V 34 w(EXIST)f -Ff(if)h(there)h(are)g(no)f(more)g(matc)m(hes.)261 5434 -y(The)f(5th)g(routine)g(returns)f(the)i(k)m(eyw)m(ord)g(v)-5 -b(alue)29 b(units)g(string,)g(if)h(an)m(y)-8 b(.)41 b(The)28 -b(units)h(are)h(recorded)f(at)120 5546 y(the)i(b)s(eginning)e(of)i(the) -f(k)m(eyw)m(ord)h(commen)m(t)h(\014eld)e(enclosed)h(in)f(square)g(brac) -m(k)m(ets.)1905 5809 y(19)p eop end -%%Page: 20 20 -TeXDict begin 20 19 bop 120 573 a Fc(________________________)o(____)o -(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(__)120 -686 y(int)47 b(fits_write_key\(fitsfile)41 b(*fptr,)46 -b(int)h(datatype,)f(char)g(*keyname,)502 799 y(void)g(*value,)g(char)h -(*comment,)e(int)i(*status\))120 912 y(int)g(fits_update_key\(fitsfile) -41 b(*fptr,)46 b(int)h(datatype,)e(char)i(*keyname,)502 -1024 y(void)f(*value,)g(char)h(*comment,)e(int)i(*status\))120 -1137 y(int)g(fits_write_record\(fitsfi)o(le)42 b(*fptr,)k(char)g -(*card,)g(int)h(*status\))120 1363 y(int)g(fits_modify_comment\(fits)o -(file)41 b(*fptr,)46 b(char)h(*keyname,)e(char)i(*comment,)502 -1476 y(int)g(*status\))120 1589 y(int)g(fits_write_key_unit\(fits)o -(file)41 b(*fptr,)46 b(char)h(*keyname,)e(char)i(*unit,)502 -1702 y(int)g(*status\))261 1975 y Ff(W)-8 b(rite)32 b(or)f(mo)s(dify)g -(a)g(k)m(eyw)m(ord)g(in)g(the)g(header)g(of)g(the)g(curren)m(t)g(HDU.)h -(The)e(\014rst)g(routine)h(app)s(ends)120 2087 y(the)f(new)g(k)m(eyw)m -(ord)g(to)h(the)f(end)g(of)g(the)g(header,)h(whereas)e(the)i(second)f -(routine)g(will)g(up)s(date)g(the)g(v)-5 b(alue)120 2200 -y(and)40 b(commen)m(t)h(\014elds)f(of)h(the)g(k)m(eyw)m(ord)g(if)f(it)h -(already)h(exists,)h(otherwise)e(it)h(b)s(eha)m(v)m(es)f(lik)m(e)g(the) -g(\014rst)120 2313 y(routine)33 b(and)f(app)s(ends)f(the)h(new)h(k)m -(eyw)m(ord.)48 b(Note)34 b(that)f Fc(value)e Ff(giv)m(es)j(the)f -(address)f(to)h(the)g(v)-5 b(alue)33 b(and)120 2426 y(not)e(the)g(v)-5 -b(alue)32 b(itself.)43 b(The)31 b Fc(datatype)d Ff(parameter)k(sp)s -(eci\014es)e(the)i(C)e(datat)m(yp)s(e)i(of)f(the)g(k)m(eyw)m(ord)h(v)-5 -b(alue)120 2539 y(and)38 b(ma)m(y)g(ha)m(v)m(e)i(an)m(y)f(of)f(the)g(v) --5 b(alues)39 b(listed)g(in)f(the)g(description)g(of)h(the)f(k)m(eyw)m -(ord)h(reading)f(routines,)120 2652 y(ab)s(o)m(v)m(e.)71 -b(A)40 b(NULL)g(ma)m(y)h(b)s(e)e(en)m(tered)i(for)f(the)g(commen)m(t)h -(parameter,)i(in)d(whic)m(h)g(case)h(the)f(k)m(eyw)m(ord)120 -2765 y(commen)m(t)31 b(\014eld)f(will)h(b)s(e)f(unmo)s(di\014ed)e(or)i -(left)i(blank.)261 2878 y(The)25 b(third)g(routine)h(is)g(more)g -(primitiv)m(e)h(and)e(simply)g(writes)h(the)g(80-c)m(haracter)j -Fc(card)c Ff(record)h(to)g(the)120 2991 y(header.)40 -b(It)30 b(is)g(the)g(programmer's)f(resp)s(onsibilit)m(y)h(in)f(this)h -(case)g(to)h(ensure)e(that)h(the)g(record)g(conforms)120 -3104 y(to)h(all)g(the)g(FITS)f(format)g(requiremen)m(ts)h(for)f(a)h -(header)f(record.)261 3217 y(The)42 b(fourth)f(routine)h(mo)s(di\014es) -f(the)h(commen)m(t)h(string)f(in)g(an)f(existing)i(k)m(eyw)m(ord,)j -(and)41 b(the)h(last)120 3329 y(routine)34 b(writes)g(or)g(up)s(dates)f -(the)h(k)m(eyw)m(ord)h(units)e(string)h(for)g(an)g(existing)h(k)m(eyw)m -(ord.)52 b(\(The)34 b(units)f(are)120 3442 y(recorded)d(at)h(the)g(b)s -(eginning)f(of)g(the)h(k)m(eyw)m(ord)f(commen)m(t)i(\014eld)e(enclosed) -h(in)f(square)g(brac)m(k)m(ets\).)120 3621 y Fc -(________________________)o(____)o(____)o(___)o(____)o(____)o(___)o -(____)o(____)o(___)o(____)o(____)o(__)120 3734 y(int)47 -b(fits_write_comment\(fitsf)o(ile)41 b(*fptr,)46 b(char)h(*comment,)93 -b(int)47 b(*status\))120 3847 y(int)g(fits_write_history\(fitsf)o(ile) -41 b(*fptr,)46 b(char)h(*history,)93 b(int)47 b(*status\))120 -3960 y(int)g(fits_write_date\(fitsfile)41 b(*fptr,)94 -b(int)47 b(*status\))261 4139 y Ff(W)-8 b(rite)22 b(a)f -Fc(COMMENT,)46 b(HISTORY)p Ff(,)18 b(or)j Fc(DATE)e Ff(k)m(eyw)m(ord)i -(to)h(the)f(curren)m(t)f(header.)37 b(The)20 b Fc(COMMENT)f -Ff(k)m(eyw)m(ord)120 4252 y(is)38 b(t)m(ypically)i(used)d(to)h(write)h -(a)f(commen)m(t)h(ab)s(out)e(the)i(\014le)f(or)f(the)i(data.)64 -b(The)37 b Fc(HISTORY)f Ff(k)m(eyw)m(ord)i(is)120 4365 -y(t)m(ypically)25 b(used)c(to)j(pro)m(vide)f(information)g(ab)s(out)f -(the)h(history)f(of)h(the)g(pro)s(cessing)f(pro)s(cedures)g(that)h(ha)m -(v)m(e)120 4478 y(b)s(een)36 b(applied)h(to)g(the)g(data.)61 -b(The)36 b Fc(comment)f Ff(or)i Fc(history)e Ff(string)i(will)g(b)s(e)f -(con)m(tin)m(ued)i(o)m(v)m(er)g(m)m(ultiple)120 4591 -y(k)m(eyw)m(ords)31 b(if)f(it)h(is)f(more)h(than)f(70)h(c)m(haracters)h -(long.)261 4704 y(The)k Fc(DATE)f Ff(k)m(eyw)m(ord)i(is)f(used)g(to)h -(record)f(the)h(date)g(and)f(time)h(that)g(the)f(FITS)g(\014le)g(w)m -(as)h(created.)120 4817 y(Note)f(that)f(this)f(\014le)h(creation)h -(date)f(is)g(usually)f(di\013eren)m(t)h(from)f(the)h(date)g(of)g(the)f -(observ)-5 b(ation)36 b(whic)m(h)120 4930 y(obtained)e(the)g(data)h(in) -e(the)i(FITS)e(\014le.)51 b(The)33 b Fc(DATE)g Ff(k)m(eyw)m(ord)h(v)-5 -b(alue)35 b(is)f(a)g(c)m(haracter)i(string)d(in)h('yyyy-)120 -5042 y(mm-ddThh:mm:ss')27 b(format.)40 b(If)29 b(a)g -Fc(DATE)f Ff(k)m(eyw)m(ord)i(already)f(exists)h(in)f(the)g(header,)h -(then)e(this)h(routine)120 5155 y(will)i(up)s(date)e(the)i(v)-5 -b(alue)31 b(with)f(the)g(curren)m(t)g(system)h(date.)120 -5334 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o -(___)o(____)o(____)o(___)o(____)o(____)o(__)120 5447 -y(int)47 b(fits_delete_record\(fitsf)o(ile)41 b(*fptr,)46 -b(int)h(keynum,)94 b(int)47 b(*status\))120 5560 y(int)g -(fits_delete_key\(fitsfile)41 b(*fptr,)46 b(char)h(*keyname,)93 -b(int)47 b(*status\))1905 5809 y Ff(20)p eop end -%%Page: 21 21 -TeXDict begin 21 20 bop 261 573 a Ff(Delete)33 b(a)e(k)m(eyw)m(ord)h -(record.)42 b(The)30 b(\014rst)g(routine)h(deletes)h(a)f(k)m(eyw)m(ord) -h(at)f(a)h(sp)s(eci\014ed)e(p)s(osition)h(\(the)120 686 -y(\014rst)c(k)m(eyw)m(ord)h(is)f(at)h(p)s(osition)g(1,)h(not)e(0\),)i -(whereas)f(the)f(second)h(routine)f(deletes)i(the)f(named)f(k)m(eyw)m -(ord.)120 898 y Fc(________________________)o(____)o(____)o(___)o(____) -o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(___)120 -1011 y(int)47 b(fits_copy_header\(fitsfil)o(e)42 b(*infptr,)j(fitsfile) -h(*outfptr,)93 b(int)47 b(*status\))261 1224 y Ff(Cop)m(y)26 -b(all)h(the)f(header)g(k)m(eyw)m(ords)h(from)e(the)i(curren)m(t)e(HDU)i -(asso)s(ciated)h(with)d(infptr)g(to)i(the)g(curren)m(t)120 -1337 y(HDU)h(asso)s(ciated)g(with)e(outfptr.)39 b(If)27 -b(the)g(curren)m(t)f(output)h(HDU)g(is)g(not)g(empt)m(y)-8 -b(,)29 b(then)d(a)h(new)f(HDU)i(will)120 1450 y(b)s(e)34 -b(app)s(ended)f(to)j(the)f(output)f(\014le.)54 b(The)35 -b(output)f(HDU)i(will)f(then)f(ha)m(v)m(e)i(the)f(iden)m(tical)i -(structure)d(as)120 1562 y(the)d(input)e(HDU,)i(but)f(will)h(con)m -(tain)g(no)g(data.)1905 5809 y(21)p eop end -%%Page: 22 22 -TeXDict begin 22 21 bop 120 573 a Fb(4.7)112 b(Utilit)m(y)37 -b(Routines)120 744 y Ff(This)30 b(section)h(lists)g(the)g(most)f(imp)s -(ortan)m(t)h(CFITSIO)e(general)i(utilit)m(y)h(routines.)120 -957 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o -(___)o(____)o(____)o(___)o(____)o(____)o(__)120 1070 -y(int)47 b(fits_write_chksum\()c(fitsfile)i(*fptr,)h(int)h(*status\)) -120 1183 y(int)g(fits_verify_chksum\(fitsf)o(ile)41 b(*fptr,)46 -b(int)h(*dataok,)f(int)h(*hduok,)f(int)g(*status\))261 -1395 y Ff(These)35 b(routines)g(compute)g(or)g(v)-5 b(alidate)36 -b(the)g(c)m(hec)m(ksums)f(for)g(the)g(currenrt)f(HDU.)i(The)e -Fc(DATASUM)120 1508 y Ff(k)m(eyw)m(ord)d(is)f(used)f(to)i(store)g(the)f -(n)m(umerical)h(v)-5 b(alue)30 b(of)h(the)f(32-bit,)i(1's)e(complemen)m -(t)h(c)m(hec)m(ksum)g(for)f(the)120 1621 y(data)25 b(unit)f(alone.)40 -b(The)24 b Fc(CHECKSUM)f Ff(k)m(eyw)m(ord)i(is)g(used)e(to)j(store)f -(the)g(ASCI)s(I)e(enco)s(ded)h(COMPLEMENT)120 1734 y(of)32 -b(the)f(c)m(hec)m(ksum)h(for)f(the)h(en)m(tire)g(HDU.)h(Storing)e(the)h -(complemen)m(t,)h(rather)e(than)g(the)h(actual)g(c)m(hec)m(k-)120 -1847 y(sum,)26 b(forces)g(the)g(c)m(hec)m(ksum)g(for)f(the)h(whole)g -(HDU)g(to)g(equal)g(zero.)40 b(If)25 b(the)h(\014le)g(has)f(b)s(een)g -(mo)s(di\014ed)f(since)120 1960 y(the)31 b(c)m(hec)m(ksums)f(w)m(ere)h -(computed,)g(then)f(the)g(HDU)i(c)m(hec)m(ksum)f(will)f(usually)g(not)h -(equal)g(zero.)261 2073 y(The)f(returned)g Fc(dataok)f -Ff(and)h Fc(hduok)g Ff(parameters)h(will)g(ha)m(v)m(e)h(a)f(v)-5 -b(alue)31 b(=)g(1)g(if)g(the)g(data)g(or)g(HDU)g(is)120 -2186 y(v)m(eri\014ed)d(correctly)-8 b(,)31 b(a)d(v)-5 -b(alue)29 b(=)f(0)g(if)g(the)h Fc(DATASUM)d Ff(or)i Fc(CHECKSUM)e -Ff(k)m(eyw)m(ord)j(is)f(not)g(presen)m(t,)h(or)f(v)-5 -b(alue)29 b(=)120 2299 y(-1)i(if)f(the)h(computed)f(c)m(hec)m(ksum)h -(is)g(not)f(correct.)120 2511 y Fc(________________________)o(____)o -(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(__) -120 2624 y(int)47 b(fits_parse_value\(char)42 b(*card,)k(char)h -(*value,)e(char)i(*comment,)e(int)i(*status\))120 2737 -y(int)g(fits_get_keytype\(char)42 b(*value,)k(char)g(*dtype,)g(int)h -(*status\))120 2850 y(int)g(fits_get_keyclass\(char)42 -b(*card\))120 2963 y(int)47 b(fits_parse_template\(char)41 -b(*template,)k(char)i(*card,)f(int)h(*keytype,)e(int)i(*status\))261 -3288 y(fits)p 459 3288 29 4 v 33 w(parse)p 732 3288 V -33 w(value)29 b Ff(parses)h(the)h(input)e(80-c)m(hararacter)k(header)d -(k)m(eyw)m(ord)h(record,)g(returning)e(the)120 3401 y(v)-5 -b(alue)21 b(\(as)h(a)f(literal)h(c)m(haracter)h(string\))e(and)f -(commen)m(t)i(strings.)38 b(If)20 b(the)h(k)m(eyw)m(ord)h(has)e(no)h(v) --5 b(alue)21 b(\(columns)120 3514 y(9-10)38 b(not)e(equal)h(to)g('=)f -('\),)j(then)d(a)g(n)m(ull)h(v)-5 b(alue)36 b(string)h(is)f(returned)f -(and)h(the)g(commen)m(t)h(string)g(is)f(set)120 3627 -y(equal)31 b(to)g(column)f(9)h(-)g(80)g(of)f(the)h(input)e(string.)261 -3740 y Fc(fits)p 459 3740 V 33 w(get)p 636 3740 V 34 -w(keytype)41 b Ff(parses)i(the)g(k)m(eyw)m(ord)h(v)-5 -b(alue)43 b(string)g(to)h(determine)f(its)h(datat)m(yp)s(e.)80 -b Fc(dtype)120 3853 y Ff(returns)34 b(with)g(a)h(v)-5 -b(alue)36 b(of)f('C',)g('L',)g('I',)h('F')f(or)g('X',)h(for)f(c)m -(haracter)h(string,)g(logical,)j(in)m(teger,)e(\015oating)120 -3966 y(p)s(oin)m(t,)31 b(or)f(complex,)h(resp)s(ectiv)m(ely)-8 -b(.)261 4079 y Fc(fits)p 459 4079 V 33 w(get)p 636 4079 -V 34 w(keyclass)31 b Ff(returns)i(a)h(classi\014cation)h(co)s(de)f -(that)g(indicates)h(the)f(classi\014cation)h(t)m(yp)s(e)f(of)120 -4192 y(the)41 b(input)e(k)m(eyw)m(ord)i(record)f(\(e.g.,)45 -b(a)40 b(required)g(structural)g(k)m(eyw)m(ord,)k(a)d(TDIM)f(k)m(eyw)m -(ord,)k(a)c(W)m(CS)120 4304 y(k)m(eyw)m(ord,)49 b(a)d(commen)m(t)g(k)m -(eyw)m(ord,)j(etc.)85 b(See)45 b(the)h(CFITSIO)d(Reference)j(Guide)e -(for)h(a)g(list)h(of)f(the)120 4417 y(di\013eren)m(t)31 -b(classi\014cation)h(co)s(des.)261 4530 y Fc(fits)p 459 -4530 V 33 w(parse)p 732 4530 V 33 w(template)37 b Ff(tak)m(es)j(an)e -(input)g(free)g(format)h(k)m(eyw)m(ord)g(template)h(string)f(and)f -(returns)120 4643 y(a)i(formatted)g(80*c)m(har)h(record)e(that)h -(satis\014es)g(all)h(the)e(FITS)g(requiremen)m(ts)h(for)f(a)h(header)f -(k)m(eyw)m(ord)120 4756 y(record.)65 b(The)38 b(template)i(should)d -(generally)j(con)m(tain)g(3)f(tok)m(ens:)58 b(the)38 -b(k)m(eyw)m(ord)h(name,)i(the)e(k)m(eyw)m(ord)120 4869 -y(v)-5 b(alue,)29 b(and)e(the)g(k)m(eyw)m(ord)h(commen)m(t)h(string.)40 -b(The)27 b(returned)f Fc(keytype)g Ff(parameter)i(indicates)g(whether) -120 4982 y(the)33 b(k)m(eyw)m(ord)g(is)g(a)g(COMMENT)g(k)m(eyw)m(ord)g -(or)g(not.)48 b(See)33 b(the)g(CFITSIO)e(Reference)j(Guide)f(for)f -(more)120 5095 y(details.)1905 5809 y(22)p eop end -%%Page: 23 23 -TeXDict begin 23 22 bop 120 573 a Fh(5)135 b(CFITSIO)44 -b(File)h(Names)h(and)f(Filters)120 779 y Fb(5.1)112 b(Creating)38 -b(New)f(Files)120 951 y Ff(When)43 b(creating)h(a)f(new)g(output)f -(\014le)h(on)g(magnetic)i(disk)d(with)h Fc(fits)p 2677 -951 29 4 v 33 w(create)p 2998 951 V 33 w(file)f Ff(the)h(follo)m(wing) -120 1064 y(features)31 b(are)f(supp)s(orted.)256 1251 -y Fa(\017)46 b Ff(Ov)m(erwriting,)31 b(or)f('Clobb)s(ering')g(an)h -(Existing)f(File)347 1402 y(If)d(the)h(\014lename)g(is)g(preceded)f(b)m -(y)g(an)h(exclamation)i(p)s(oin)m(t)d(\(!\))41 b(then)27 -b(if)h(that)g(\014le)f(already)i(exists)f(it)347 1514 -y(will)h(b)s(e)e(deleted)i(prior)e(to)i(creating)g(the)f(new)g(FITS)f -(\014le.)40 b(Otherwise)27 b(if)h(there)g(is)g(an)g(existing)h(\014le) -347 1627 y(with)36 b(the)f(same)h(name,)i(CFITSIO)c(will)i(not)g(o)m(v) -m(erwrite)h(the)f(existing)g(\014le)g(and)f(will)h(return)e(an)347 -1740 y(error)28 b(status)h(co)s(de.)40 b(Note)30 b(that)f(the)f -(exclamation)j(p)s(oin)m(t)d(is)g(a)h(sp)s(ecial)g(UNIX)f(c)m -(haracter,)j(so)e(if)f(it)347 1853 y(is)f(used)f(on)g(the)h(command)g -(line)g(rather)f(than)g(en)m(tered)i(at)f(a)g(task)g(prompt,)g(it)g(m)m -(ust)g(b)s(e)f(preceded)347 1966 y(b)m(y)j(a)h(bac)m(kslash)g(to)g -(force)g(the)f(UNIX)h(shell)f(to)i(pass)d(it)i(v)m(erbatim)g(to)g(the)g -(application)g(program.)256 2154 y Fa(\017)46 b Ff(Compressed)30 -b(Output)f(Files)347 2304 y(If)g(the)g(output)f(disk)h(\014le)g(name)g -(ends)f(with)g(the)h(su\016x)f('.gz',)j(then)e(CFITSIO)e(will)i -(compress)g(the)347 2417 y(\014le)39 b(using)g(the)g(gzip)h -(compression)f(algorithm)h(b)s(efore)e(writing)h(it)h(to)g(disk.)66 -b(This)38 b(can)i(reduce)347 2530 y(the)h(amoun)m(t)g(of)g(disk)f -(space)h(used)f(b)m(y)g(the)h(\014le.)71 b(Note)42 b(that)f(this)g -(feature)g(requires)f(that)h(the)347 2643 y(uncompressed)e(\014le)i(b)s -(e)f(constructed)h(in)f(memory)g(b)s(efore)g(it)h(is)g(compressed)f -(and)g(written)h(to)347 2756 y(disk,)30 b(so)h(it)g(can)g(fail)g(if)f -(there)h(is)f(insu\016cien)m(t)h(a)m(v)-5 b(ailable)32 -b(memory)-8 b(.)347 2906 y(One)32 b(can)h(also)h(sp)s(ecify)e(that)h -(an)m(y)g(images)h(written)f(to)g(the)g(output)f(\014le)h(should)f(b)s -(e)g(compressed)347 3019 y(using)23 b(the)g(newly)g(dev)m(elop)s(ed)h -(`tile-compression')h(algorithm)f(b)m(y)f(app)s(ending)f(`[compress]')i -(to)g(the)347 3132 y(name)36 b(of)h(the)f(disk)g(\014le)g(\(as)h(in)f -Fc(myfile.fits[compress])p Ff(\).)52 b(Refer)36 b(to)h(the)g(CFITSIO)d -(User's)347 3245 y(Reference)d(Guide)g(for)f(more)g(information)h(ab)s -(out)f(this)g(new)g(image)i(compression)e(format.)256 -3432 y Fa(\017)46 b Ff(Using)31 b(a)g(T)-8 b(emplate)31 -b(to)g(Create)g(a)g(New)g(FITS)e(File)347 3583 y(The)k(structure)g(of)g -(an)m(y)h(new)f(FITS)f(\014le)i(that)g(is)f(to)h(b)s(e)f(created)h(ma)m -(y)g(b)s(e)f(de\014ned)f(in)h(an)g(ASCI)s(I)347 3695 -y(template)d(\014le.)40 b(If)29 b(the)f(name)h(of)g(the)f(template)i -(\014le)f(is)g(app)s(ended)d(to)k(the)e(name)h(of)g(the)f(FITS)g -(\014le)347 3808 y(itself,)38 b(enclosed)e(in)f(paren)m(thesis)g -(\(e.g.,)j Fc('newfile.fits\(template.tx)o(t\)')p Ff(\))29 -b(then)35 b(CFITSIO)347 3921 y(will)c(create)i(a)e(FITS)f(\014le)h -(with)f(that)i(structure)e(b)s(efore)h(op)s(ening)f(it)h(for)g(the)g -(application)h(to)f(use.)347 4034 y(The)h(template)i(\014le)f -(basically)g(de\014nes)f(the)h(dimensions)e(and)h(data)h(t)m(yp)s(e)g -(of)g(the)f(primary)g(arra)m(y)347 4147 y(and)23 b(an)m(y)h(IMA)m(GE)g -(extensions,)i(and)d(the)g(names)g(and)g(data)h(t)m(yp)s(es)g(of)f(the) -h(columns)f(in)g(an)m(y)h(ASCI)s(I)347 4260 y(or)35 b(binary)g(table)h -(extensions.)55 b(The)35 b(template)h(\014le)f(can)h(also)g(b)s(e)e -(used)h(to)g(de\014ne)g(an)m(y)g(optional)347 4373 y(k)m(eyw)m(ords)g -(that)g(should)e(b)s(e)h(written)g(in)h(an)m(y)f(of)h(the)f(HDU)h -(headers.)53 b(The)34 b(image)h(pixel)g(v)-5 b(alues)347 -4486 y(and)38 b(table)i(en)m(try)e(v)-5 b(alues)39 b(are)g(all)g -(initialized)i(to)e(zero.)66 b(The)38 b(application)i(program)e(can)h -(then)347 4599 y(write)28 b(actual)g(data)g(in)m(to)h(the)e(HDUs.)40 -b(See)28 b(the)f(CFITSIO)f(Reference)i(Guide)f(for)g(for)g(a)h -(complete)347 4712 y(description)j(of)f(the)h(template)h(\014le)e(syn)m -(tax.)256 4899 y Fa(\017)46 b Ff(Creating)31 b(a)g(T)-8 -b(emp)s(orary)30 b(Scratc)m(h)h(File)g(in)f(Memory)347 -5050 y(It)38 b(is)g(sometimes)h(useful)e(to)i(create)g(a)f(temp)s -(orary)g(output)f(\014le)h(when)f(testing)i(an)f(application)347 -5162 y(program.)45 b(If)31 b(the)h(name)g(of)g(the)g(\014le)g(to)h(b)s -(e)e(created)i(is)f(sp)s(eci\014ed)f(as)h Fc(mem:)42 -b Ff(then)32 b(CFITSIO)e(will)347 5275 y(create)39 b(the)e(\014le)h(in) -f(memory)g(where)f(it)i(will)g(p)s(ersist)e(only)h(un)m(til)h(the)f -(program)g(closes)i(the)e(\014le.)347 5388 y(Use)e(of)g(this)g -Fc(mem:)48 b Ff(output)34 b(\014le)h(usually)f(enables)h(the)g(program) -f(to)i(run)d(faster,)j(and)e(of)h(course)347 5501 y(the)c(output)f -(\014le)g(do)s(es)g(not)h(use)f(up)f(an)m(y)i(disk)f(space.)1905 -5809 y(23)p eop end -%%Page: 24 24 -TeXDict begin 24 23 bop 120 573 a Fb(5.2)112 b(Op)s(ening)39 -b(Existing)e(Files)120 744 y Ff(When)h(op)s(ening)f(a)i(\014le)f(with)g -Fc(fits)p 1392 744 29 4 v 33 w(open)p 1617 744 V 33 w(file)p -Ff(,)h(CFITSIO)e(can)h(read)g(a)g(v)-5 b(ariet)m(y)40 -b(of)e(di\013eren)m(t)g(input)120 857 y(\014le)31 b(formats)g(and)g(is) -g(not)g(restricted)h(to)g(only)f(reading)g(FITS)g(format)g(\014les)g -(from)g(magnetic)h(disk.)43 b(The)120 970 y(follo)m(wing)32 -b(t)m(yp)s(es)e(of)h(input)e(\014les)i(are)f(all)i(supp)s(orted:)256 -1183 y Fa(\017)46 b Ff(FITS)30 b(\014les)g(compressed)g(with)g -Fc(zip,)47 b(gzip)29 b Ff(or)i Fc(compress)347 1333 y -Ff(If)36 b(CFITSIO)f(cannot)i(\014nd)e(the)i(sp)s(eci\014ed)f(\014le)g -(to)h(op)s(en)f(it)h(will)g(automatically)i(lo)s(ok)e(for)f(a)h(\014le) -347 1446 y(with)k(the)f(same)h(ro)s(otname)h(but)d(with)i(a)g -Fc(.gz,)46 b(.zip)p Ff(,)d(or)d Fc(.Z)g Ff(extension.)72 -b(If)41 b(it)g(\014nds)e(suc)m(h)h(a)347 1559 y(compressed)d(\014le,)h -(it)g(will)f(allo)s(cate)i(a)e(blo)s(c)m(k)g(of)g(memory)g(and)f -(uncompress)f(the)i(\014le)g(in)m(to)h(that)347 1672 -y(memory)25 b(space.)39 b(The)25 b(application)h(program)e(will)i(then) -e(transparen)m(tly)h(op)s(en)f(this)h(virtual)g(FITS)347 -1785 y(\014le)36 b(in)f(memory)-8 b(.)56 b(Compressed)35 -b(\014les)g(can)h(only)g(b)s(e)e(op)s(ened)h(with)g('readonly',)j(not)e -('readwrite')347 1898 y(\014le)31 b(access.)256 2085 -y Fa(\017)46 b Ff(FITS)30 b(\014les)g(on)g(the)h(in)m(ternet,)g(using)f -Fc(ftp)g Ff(or)g Fc(http)f Ff(URLs)347 2236 y(Simply)22 -b(pro)m(vide)h(the)h(full)e(URL)h(as)g(the)g(name)g(of)h(the)f(\014le)g -(that)g(y)m(ou)h(w)m(an)m(t)f(to)h(op)s(en.)38 b(F)-8 -b(or)23 b(example,)347 2348 y Fc(ftp://legacy.gsfc.nasa.go)o(v/so)o -(ftwa)o(re/)o(fits)o(io/c)o(/te)o(stpr)o(og.s)o(td)347 -2461 y Ff(will)37 b(op)s(en)e(the)h(CFITSIO)e(test)j(FITS)e(\014le)h -(that)h(is)e(lo)s(cated)j(on)d(the)h Fc(legacy)f Ff(mac)m(hine.)58 -b(These)347 2574 y(\014les)31 b(can)f(only)h(b)s(e)e(op)s(ened)h(with)g -('readonly')h(\014le)g(access.)256 2762 y Fa(\017)46 -b Ff(FITS)30 b(\014les)g(on)g Fc(stdin)f Ff(or)i Fc(stdout)d -Ff(\014le)j(streams)347 2912 y(If)j(the)g(name)h(of)f(the)h(\014le)f -(to)h(b)s(e)f(op)s(ened)f(is)h Fc('stdin')f Ff(or)h Fc('-')f -Ff(\(a)i(single)g(dash)e(c)m(haracter\))k(then)347 3025 -y(CFITSIO)f(will)i(read)g(the)f(\014le)h(from)f(the)h(standard)f(input) -f(stream.)63 b(Similarly)-8 b(,)40 b(if)e(the)g(output)347 -3138 y(\014le)43 b(name)g(is)g Fc('stdout')e Ff(or)i -Fc('-')p Ff(,)j(then)c(the)i(\014le)f(will)g(b)s(e)g(written)g(to)g -(the)h(standard)e(output)347 3251 y(stream.)54 b(In)34 -b(addition,)i(if)e(the)h(output)f(\014lename)h(is)g Fc('stdout.gz')c -Ff(or)k Fc('-.gz')e Ff(then)h(it)h(will)g(b)s(e)347 3364 -y(gzip)f(compressed)f(b)s(efore)g(b)s(eing)f(written)h(to)h(stdout.)49 -b(This)33 b(mec)m(hanism)g(can)h(b)s(e)e(used)g(to)i(pip)s(e)347 -3477 y(FITS)c(\014les)g(from)g(one)h(task)g(to)g(another)f(without)h -(ha)m(ving)g(to)g(write)f(an)h(in)m(termediary)g(FITS)e(\014le)347 -3590 y(on)i(magnetic)g(disk.)256 3777 y Fa(\017)46 b -Ff(FITS)30 b(\014les)g(that)h(exist)g(only)g(in)f(memory)-8 -b(,)31 b(or)f(shared)g(memory)-8 b(.)347 3928 y(In)38 -b(some)i(applications,)i(suc)m(h)d(as)g(real)g(time)h(data)f -(acquisition,)k(y)m(ou)c(ma)m(y)h(w)m(an)m(t)f(to)h(ha)m(v)m(e)g(one) -347 4040 y(pro)s(cess)31 b(write)g(a)h(FITS)e(\014le)h(in)m(to)h(a)g -(certain)g(section)g(of)f(computer)g(memory)-8 b(,)32 -b(and)f(then)f(b)s(e)h(able)347 4153 y(to)26 b(op)s(en)f(that)g(\014le) -g(in)g(memory)g(with)g(another)g(pro)s(cess.)39 b(There)25 -b(is)g(a)g(sp)s(ecialized)h(CFITSIO)e(op)s(en)347 4266 -y(routine)f(called)i Fc(fits)p 1102 4266 V 33 w(open)p -1327 4266 V 33 w(memfile)d Ff(that)h(can)h(b)s(e)e(used)h(for)g(this)g -(purp)s(ose.)37 b(See)23 b(the)g(\\CFITSIO)347 4379 y(User's)31 -b(Reference)g(Guide")g(for)f(more)g(details.)256 4567 -y Fa(\017)46 b Ff(IRAF)31 b(format)g(images)g(\(with)f -Fc(.imh)g Ff(\014le)g(extensions\))347 4717 y(CFITSIO)38 -b(supp)s(orts)g(reading)i(IRAF)g(format)g(images)h(b)m(y)f(con)m(v)m -(erting)h(them)f(on)f(the)h(\015y)f(in)m(to)347 4830 -y(FITS)27 b(images)i(in)e(memory)-8 b(.)40 b(The)28 b(application)g -(program)g(then)f(reads)h(this)f(virtual)h(FITS)f(format)347 -4943 y(image)36 b(in)f(memory)-8 b(.)55 b(There)34 b(is)h(curren)m(tly) -g(no)g(supp)s(ort)e(for)i(writing)g(IRAF)g(format)g(images,)i(or)347 -5056 y(for)30 b(reading)h(or)f(writing)h(IRAF)f(tables.)256 -5243 y Fa(\017)46 b Ff(Image)31 b(arra)m(ys)g(in)f(ra)m(w)h(binary)e -(format)347 5394 y(If)23 b(the)h(input)e(\014le)i(is)f(a)h(ra)m(w)f -(binary)g(data)h(arra)m(y)-8 b(,)26 b(then)d(CFITSIO)f(will)h(con)m(v)m -(ert)i(it)f(on)f(the)h(\015y)f(in)m(to)h(a)347 5507 y(virtual)g(FITS)e -(image)j(with)e(the)h(basic)f(set)h(of)g(required)e(header)h(k)m(eyw)m -(ords)h(b)s(efore)f(it)h(is)f(op)s(ened)f(b)m(y)1905 -5809 y(24)p eop end -%%Page: 25 25 -TeXDict begin 25 24 bop 347 573 a Ff(the)31 b(application)g(program.)40 -b(In)30 b(this)g(case)h(the)f(data)h(t)m(yp)s(e)g(and)e(dimensions)g -(of)i(the)f(image)h(m)m(ust)347 686 y(b)s(e)c(sp)s(eci\014ed)f(in)h -(square)g(brac)m(k)m(ets)h(follo)m(wing)h(the)e(\014lename)h(\(e.g.)41 -b Fc(rawfile.dat[ib512,512])p Ff(\).)347 799 y(The)30 -b(\014rst)g(c)m(haracter)i(inside)e(the)g(brac)m(k)m(ets)i(de\014nes)e -(the)g(datat)m(yp)s(e)i(of)e(the)h(arra)m(y:)586 1049 -y Fc(b)429 b(8-bit)47 b(unsigned)e(byte)586 1161 y(i)381 -b(16-bit)47 b(signed)f(integer)586 1274 y(u)381 b(16-bit)47 -b(unsigned)e(integer)586 1387 y(j)381 b(32-bit)47 b(signed)f(integer) -586 1500 y(r)h(or)h(f)142 b(32-bit)47 b(floating)e(point)586 -1613 y(d)381 b(64-bit)47 b(floating)e(point)347 1863 -y Ff(An)32 b(optional)g(second)g(c)m(haracter)h(sp)s(eci\014es)e(the)h -(b)m(yte)h(order)e(of)g(the)h(arra)m(y)g(v)-5 b(alues:)44 -b(b)31 b(or)h(B)g(indi-)347 1976 y(cates)27 b(big)e(endian)f(\(as)i(in) -f(FITS)f(\014les)h(and)f(the)i(nativ)m(e)g(format)f(of)h(SUN)e(UNIX)i -(w)m(orkstations)g(and)347 2089 y(Mac)35 b(PCs\))d(and)h(l)g(or)g(L)g -(indicates)h(little)h(endian)e(\(nativ)m(e)i(format)e(of)g(DEC)h(OSF)e -(w)m(orkstations)347 2202 y(and)41 b(IBM)g(PCs\).)73 -b(If)41 b(this)g(c)m(haracter)h(is)g(omitted)g(then)e(the)i(arra)m(y)f -(is)h(assumed)e(to)i(ha)m(v)m(e)g(the)347 2315 y(nativ)m(e)30 -b(b)m(yte)f(order)e(of)h(the)h(lo)s(cal)g(mac)m(hine.)41 -b(These)28 b(datat)m(yp)s(e)h(c)m(haracters)g(are)g(then)f(follo)m(w)m -(ed)h(b)m(y)347 2428 y(a)d(series)g(of)f(one)h(or)f(more)h(in)m(teger)g -(v)-5 b(alues)26 b(separated)g(b)m(y)f(commas)h(whic)m(h)f(de\014ne)g -(the)g(size)i(of)e(eac)m(h)347 2540 y(dimension)30 b(of)h(the)f(ra)m(w) -h(arra)m(y)-8 b(.)41 b(Arra)m(ys)31 b(with)f(up)f(to)i(5)g(dimensions)f -(are)g(curren)m(tly)h(supp)s(orted.)347 2691 y(Finally)-8 -b(,)35 b(a)e(b)m(yte)g(o\013set)g(to)g(the)g(p)s(osition)f(of)g(the)h -(\014rst)f(pixel)g(in)g(the)h(data)g(\014le)f(ma)m(y)h(b)s(e)f(sp)s -(eci\014ed)347 2804 y(b)m(y)c(separating)h(it)g(with)e(a)i(':')40 -b(from)27 b(the)i(last)f(dimension)g(v)-5 b(alue.)40 -b(If)28 b(omitted,)i(it)e(is)g(assumed)g(that)347 2917 -y(the)h(o\013set)g(=)f(0.)41 b(This)27 b(parameter)i(ma)m(y)g(b)s(e)f -(used)f(to)i(skip)f(o)m(v)m(er)i(an)m(y)e(header)g(information)h(in)f -(the)347 3029 y(\014le)j(that)g(precedes)f(the)h(binary)e(data.)42 -b(F)-8 b(urther)30 b(examples:)443 3279 y Fc(raw.dat[b10000])473 -b(1-dimensional)44 b(10000)i(pixel)h(byte)f(array)443 -3392 y(raw.dat[rb400,400,12])185 b(3-dimensional)44 b(floating)i(point) -g(big-endian)f(array)443 3505 y(img.fits[ib512,512:2880)o(])d(reads)k -(the)h(512)g(x)h(512)e(short)h(integer)f(array)g(in)h(a)1636 -3618 y(FITS)g(file,)f(skipping)f(over)i(the)g(2880)g(byte)f(header)1905 -5809 y Ff(25)p eop end -%%Page: 26 26 -TeXDict begin 26 25 bop 120 573 a Fb(5.3)112 b(Image)38 -b(Filtering)120 744 y Fg(5.3.1)105 b(Extracting)35 b(a)g(subsection)h -(of)f(an)g(image)120 916 y Ff(When)21 b(sp)s(ecifying)g(the)h(name)f -(of)g(an)g(image)i(to)f(b)s(e)f(op)s(ened,)h(y)m(ou)g(can)f(select)i(a) -f(rectangular)g(subsection)f(of)120 1029 y(the)29 b(image)g(to)g(b)s(e) -f(extracted)i(and)e(op)s(ened)f(b)m(y)i(the)f(application)i(program.)40 -b(The)28 b(application)i(program)120 1142 y(then)h(op)s(ens)f(a)i -(virtual)g(image)g(that)g(only)f(con)m(tains)i(the)e(pixels)h(within)e -(the)i(sp)s(eci\014ed)e(subsection.)44 b(T)-8 b(o)120 -1255 y(do)33 b(this,)h(sp)s(ecify)f(the)h(the)f(range)h(of)f(pixels)g -(\(start:end\))i(along)f(eac)m(h)g(axis)g(to)g(b)s(e)f(extracted)h -(from)f(the)120 1368 y(original)e(image)h(enclosed)f(in)f(square)g -(brac)m(k)m(ets.)42 b(Y)-8 b(ou)31 b(can)f(also)i(sp)s(ecify)e(an)g -(optional)h(pixel)g(incremen)m(t)120 1481 y(\(start:end:step\))37 -b(for)f(eac)m(h)g(axis)h(of)e(the)h(input)f(image.)58 -b(A)36 b(pixel)g(step)g(=)f(1)h(will)g(b)s(e)f(assumed)g(if)h(it)g(is) -120 1594 y(not)29 b(sp)s(eci\014ed.)39 b(If)28 b(the)h(starting)g -(pixel)g(is)f(larger)i(then)e(the)h(end)e(pixel,)j(then)e(the)h(image)h -(will)e(b)s(e)g(\015ipp)s(ed)120 1706 y(\(pro)s(ducing)34 -b(a)h(mirror)e(image\))j(along)g(that)f(dimension.)53 -b(An)34 b(asterisk,)j('*',)g(ma)m(y)e(b)s(e)f(used)f(to)j(sp)s(ecify) -120 1819 y(the)25 b(en)m(tire)h(range)f(of)g(an)g(axis,)i(and)d('-*')i -(will)g(\015ip)e(the)h(en)m(tire)h(axis.)39 b(In)24 b(the)h(follo)m -(wing)i(examples,)g(assume)120 1932 y(that)k Fc(myfile.fits)c -Ff(con)m(tains)32 b(a)f(512)g(x)g(512)g(pixel)g(2D)g(image.)215 -2130 y Fc(myfile.fits[201:210,)43 b(251:260])i(-)j(opens)e(a)i(10)f(x)g -(10)g(pixel)g(subimage.)215 2356 y(myfile.fits[*,)d(512:257])i(-)h -(opens)g(a)g(512)g(x)h(256)e(image)h(consisting)e(of)406 -2469 y(all)i(the)g(columns)f(in)h(the)g(input)f(image,)h(but)f(only)h -(rows)g(257)406 2582 y(through)f(512.)95 b(The)46 b(image)h(will)f(be)i -(flipped)d(along)i(the)g(Y)g(axis)406 2695 y(since)g(the)g(starting)e -(row)i(is)g(greater)f(than)h(the)g(ending)406 2808 y(row.)215 -3033 y(myfile.fits[*:2,)d(512:257:2])h(-)i(creates)f(a)i(256)e(x)i(128) -f(pixel)f(image.)406 3146 y(Similar)g(to)h(the)g(previous)f(example,)f -(but)i(only)g(every)f(other)h(row)406 3259 y(and)g(column)f(is)i(read)e -(from)h(the)g(input)f(image.)215 3485 y(myfile.fits[-*,)e(*])j(-)h -(creates)e(an)h(image)f(containing)f(all)i(the)g(rows)g(and)406 -3598 y(columns)f(in)h(the)g(input)g(image,)f(but)h(flips)f(it)h(along)g -(the)f(X)406 3711 y(axis.)261 3909 y Ff(If)33 b(the)g(arra)m(y)h(to)g -(b)s(e)f(op)s(ened)f(is)i(in)f(an)g(Image)h(extension,)h(and)e(not)g -(in)g(the)h(primary)e(arra)m(y)i(of)f(the)120 4022 y(\014le,)d(then)f -(y)m(ou)g(need)g(to)h(sp)s(ecify)e(the)i(extension)g(name)f(or)g(n)m -(um)m(b)s(er)f(in)g(square)h(brac)m(k)m(ets)i(b)s(efore)e(giving)120 -4135 y(the)h(subsection)f(range,)h(as)g(in)f Fc(myfile.fits[1][-*,)42 -b(*])29 b Ff(to)h(read)f(the)h(image)h(in)e(the)g(\014rst)g(extension) -120 4248 y(in)h(the)h(\014le.)120 4485 y Fg(5.3.2)105 -b(Create)34 b(an)h(Image)g(b)m(y)g(Binning)h(T)-9 b(able)34 -b(Columns)120 4657 y Ff(Y)-8 b(ou)40 b(can)f(also)h(create)h(and)d(op)s -(en)h(a)g(virtual)h(image)g(b)m(y)f(binning)f(the)i(v)-5 -b(alues)39 b(in)g(a)g(pair)g(of)h(columns)120 4770 y(of)f(a)h(FITS)f -(table)h(\(in)f(other)h(w)m(ords,)h(create)g(a)e(2-D)i(histogram)f(of)f -(the)g(v)-5 b(alues)40 b(in)f(the)g(2)h(columns\).)120 -4883 y(This)34 b(tec)m(hnique)h(is)g(often)g(used)f(in)h(X-ra)m(y)h -(astronom)m(y)f(where)f(eac)m(h)i(detected)g(X-ra)m(y)g(photon)f -(during)120 4996 y(an)29 b(observ)-5 b(ation)29 b(is)g(recorded)g(in)f -(a)h(FITS)f(table.)41 b(There)29 b(are)g(t)m(ypically)h(2)g(columns)e -(in)g(the)h(table)h(called)120 5109 y Fc(X)35 b Ff(and)h -Fc(Y)f Ff(whic)m(h)h(record)f(the)i(pixel)f(lo)s(cation)h(of)f(that)h -(ev)m(en)m(t)g(in)e(a)i(virtual)f(2D)g(image.)59 b(T)-8 -b(o)36 b(create)h(an)120 5222 y(image)28 b(from)e(this)h(table,)i(one)e -(just)f(scans)h(the)g(X)g(and)f(Y)h(columns)g(and)f(coun)m(ts)h(up)f -(ho)m(w)h(man)m(y)g(photons)120 5334 y(w)m(ere)k(recorded)g(in)g(eac)m -(h)h(pixel)f(of)g(the)g(image.)44 b(When)30 b(table)i(binning)e(is)h -(sp)s(eci\014ed,)g(CFITSIO)e(creates)120 5447 y(a)38 -b(temp)s(orary)e(FITS)h(primary)f(arra)m(y)i(in)f(memory)g(b)m(y)g -(computing)h(the)f(histogram)h(of)g(the)f(v)-5 b(alues)38 -b(in)120 5560 y(the)29 b(sp)s(eci\014ed)f(columns.)40 -b(After)29 b(the)g(histogram)g(is)g(computed)g(the)g(original)h(FITS)e -(\014le)h(con)m(taining)h(the)1905 5809 y(26)p eop end -%%Page: 27 27 -TeXDict begin 27 26 bop 120 573 a Ff(table)25 b(is)e(closed)i(and)e -(the)g(temp)s(orary)h(FITS)e(primary)h(arra)m(y)h(is)g(op)s(ened)f(and) -g(passed)g(to)h(the)g(application)120 686 y(program.)39 -b(Th)m(us,)27 b(the)g(application)h(program)f(nev)m(er)g(sees)h(the)f -(original)h(FITS)e(table)i(and)e(only)h(sees)g(the)120 -799 y(image)32 b(in)e(the)g(new)g(temp)s(orary)g(\014le)h(\(whic)m(h)f -(has)g(no)g(extensions\).)261 912 y(The)f(table)h(binning)e(sp)s -(eci\014er)h(is)h(enclosed)g(in)f(square)g(brac)m(k)m(ets)h(follo)m -(wing)h(the)f(ro)s(ot)f(\014lename)h(and)120 1024 y(table)h(extension)g -(name)g(or)f(n)m(um)m(b)s(er)f(and)h(b)s(egins)g(with)g(the)g(k)m(eyw)m -(ord)h('bin',)g(as)f(in:)120 1137 y Fc('myfile.fits[events][bin)41 -b(\(X,Y\)]')p Ff(.)20 b(In)h(this)h(case,)j(the)d(X)g(and)f(Y)h -(columns)g(in)g(the)g('ev)m(en)m(ts')h(table)120 1250 -y(extension)30 b(are)g(binned)f(up)f(to)j(create)g(the)f(image.)42 -b(The)29 b(size)h(of)g(the)g(image)h(is)f(usually)f(determined)g(b)m(y) -120 1363 y(the)22 b Fc(TLMINn)d Ff(and)i Fc(TLMAXn)f -Ff(header)h(k)m(eyw)m(ords)h(whic)m(h)f(giv)m(e)i(the)e(minim)m(um)g -(and)g(maxim)m(um)g(allo)m(w)m(ed)i(pixel)120 1476 y(v)-5 -b(alues)38 b(in)f(the)h(columns.)62 b(F)-8 b(or)38 b(instance)g(if)g -Fc(TLMINn)46 b(=)h(1)37 b Ff(and)g Fc(TLMAXn)46 b(=)i(4096)36 -b Ff(for)i(b)s(oth)e(columns,)120 1589 y(this)f(w)m(ould)g(generate)h -(a)f(4096)i(x)e(4096)h(pixel)g(image)g(b)m(y)f(default.)54 -b(This)34 b(is)h(rather)g(large,)j(so)d(y)m(ou)g(can)120 -1702 y(also)e(sp)s(ecify)f(a)h(pixel)f(binning)f(factor)j(to)f(reduce)f -(the)g(image)i(size.)47 b(F)-8 b(or)33 b(example)g(sp)s(ecifying)f(,)h -Fc('[bin)120 1815 y(\(X,Y\))46 b(=)i(16]')29 b Ff(will)h(use)f(a)i -(binning)d(factor)j(of)f(16,)h(whic)m(h)f(will)g(pro)s(duce)f(a)h(256)h -(x)f(256)h(pixel)g(image)g(in)120 1928 y(the)g(previous)e(example.)261 -2041 y(If)35 b(the)g(TLMIN)g(and)g(TLMAX)g(k)m(eyw)m(ords)g(don't)g -(exist,)j(or)d(y)m(ou)g(w)m(an)m(t)h(to)g(o)m(v)m(erride)h(their)e(v)-5 -b(alues,)120 2154 y(y)m(ou)36 b(can)h(sp)s(ecify)e(the)h(image)i(range) -e(and)f(binning)g(factor)i(directly)-8 b(,)39 b(as)d(in)g -Fc('[bin)46 b(X)i(=)f(1:4096:16,)120 2267 y(Y=1:4096:16]')p -Ff(.)36 b(Y)-8 b(ou)28 b(can)g(also)g(sp)s(ecify)f(the)h(datat)m(yp)s -(e)g(of)g(the)g(created)g(image)h(b)m(y)e(app)s(ending)f(a)i(b,)g(i,) -120 2379 y(j,)f(r,)g(or)f(d)f(\(for)h(8-bit)h(b)m(yte,)h(16-bit)g(in)m -(tegers,)g(32-bit)f(in)m(teger,)i(32-bit)e(\015oating)g(p)s(oin)m(ts,)g -(or)f(64-bit)i(double)120 2492 y(precision)36 b(\015oating)g(p)s(oin)m -(t,)h(resp)s(ectiv)m(ely\))g(to)f(the)g('bin')f(k)m(eyw)m(ord)g(\(e.g.) -58 b Fc('[binr)46 b(\(X,Y\)]')33 b Ff(creates)k(a)120 -2605 y(\015oating)j(p)s(oin)m(t)e(image\).)67 b(If)38 -b(the)h(datat)m(yp)s(e)h(is)e(not)h(sp)s(eci\014ed)f(then)g(a)h(32-bit) -h(in)m(teger)g(image)g(will)f(b)s(e)120 2718 y(created)31 -b(b)m(y)g(default.)261 2831 y(If)39 b(the)h(column)f(name)g(is)h(not)f -(sp)s(eci\014ed,)i(then)e(CFITSIO)f(will)i(\014rst)e(try)i(to)g(use)f -(the)g('preferred)120 2944 y(column')c(as)g(sp)s(eci\014ed)f(b)m(y)h -(the)g(CPREF)g(k)m(eyw)m(ord)g(if)g(it)h(exists)f(\(e.g.,)j('CPREF)d(=) -g('DETX,DETY'\),)120 3057 y(otherwise)c(column)f(names)g('X',)i('Y')e -(will)h(b)s(e)f(assumed)g(for)g(the)g(2)h(axes.)261 3170 -y(Note)37 b(that)f(this)f(binning)f(sp)s(eci\014er)h(is)g(not)g -(restricted)h(to)g(only)g(2D)g(images)g(and)f(can)g(b)s(e)g(used)g(to) -120 3283 y(create)f(1D,)f(3D,)g(or)g(4D)g(images)g(as)f(w)m(ell.)48 -b(It)32 b(is)g(also)h(p)s(ossible)f(to)h(sp)s(ecify)f(a)g(w)m(eigh)m -(ting)i(factor)g(that)e(is)120 3396 y(applied)d(during)g(the)g -(binning.)40 b(Please)30 b(refer)g(to)g(the)g(\\CFITSIO)e(User's)i -(Reference)g(Guide")g(for)f(more)120 3509 y(details)i(on)g(these)f(adv) --5 b(anced)31 b(features.)1905 5809 y(27)p eop end -%%Page: 28 28 -TeXDict begin 28 27 bop 120 573 a Fb(5.4)112 b(T)-9 b(able)38 -b(Filtering)120 744 y Fg(5.4.1)105 b(Column)35 b(and)g(Keyw)m(ord)g -(Filtering)120 916 y Ff(The)29 b(column)g(or)g(k)m(eyw)m(ord)h -(\014ltering)g(sp)s(eci\014er)f(is)g(used)g(to)h(mo)s(dify)e(the)i -(column)f(structure)g(and/or)g(the)120 1029 y(header)h(k)m(eyw)m(ords)h -(in)f(the)h(HDU)g(that)g(w)m(as)g(selected)h(with)e(the)h(previous)f -(HDU)h(lo)s(cation)h(sp)s(eci\014er.)40 b(It)120 1142 -y(can)31 b(b)s(e)e(used)h(to)h(p)s(erform)e(the)i(follo)m(wing)g(t)m -(yp)s(es)g(of)f(op)s(erations.)256 1354 y Fa(\017)46 -b Ff(App)s(end)35 b(a)h(new)g(column)g(to)h(a)f(table)h(b)m(y)g(giving) -g(the)f(column)g(name,)i(optionally)g(follo)m(w)m(ed)f(b)m(y)347 -1467 y(the)c(datat)m(yp)s(e)h(in)e(paren)m(theses,)i(follo)m(w)m(ed)g -(b)m(y)f(an)g(equals)g(sign)g(and)f(the)h(arithmetic)h(expression)347 -1580 y(to)c(b)s(e)e(used)g(to)i(compute)f(the)g(v)-5 -b(alue.)41 b(The)28 b(datat)m(yp)s(e)i(is)f(sp)s(eci\014ed)f(using)h -(the)g(same)g(syn)m(tax)h(that)347 1693 y(is)k(allo)m(w)m(ed)h(for)e -(the)g(v)-5 b(alue)34 b(of)g(the)f(FITS)g(TF)m(ORMn)g(k)m(eyw)m(ord)h -(\(e.g.,)i('I',)e('J',)g('E',)f('D',)i(etc.)51 b(for)347 -1806 y(binary)32 b(tables,)h(and)f('I8',)h(F12.3',)i('E20.12',)g(etc.) -47 b(for)32 b(ASCI)s(I)f(tables\).)47 b(If)32 b(the)g(datat)m(yp)s(e)h -(is)f(not)347 1919 y(sp)s(eci\014ed)e(then)g(a)h(default)f(datat)m(yp)s -(e)i(will)e(b)s(e)g(c)m(hosen)h(dep)s(ending)e(on)h(the)h(expression.) -256 2107 y Fa(\017)46 b Ff(Create)33 b(a)g(new)f(header)g(k)m(eyw)m -(ord)h(b)m(y)f(giving)h(the)g(k)m(eyw)m(ord)g(name,)g(preceded)f(b)m(y) -g(a)h(p)s(ound)d(sign)347 2220 y('#',)24 b(follo)m(w)m(ed)e(b)m(y)f(an) -g(equals)g(sign)g(and)f(an)h(arithmetic)h(expression)f(for)g(the)g(v)-5 -b(alue)21 b(of)g(the)h(k)m(eyw)m(ord.)347 2332 y(The)k(expression)g(ma) -m(y)h(b)s(e)f(a)h(function)f(of)h(other)f(header)g(k)m(eyw)m(ord)h(v)-5 -b(alues.)40 b(The)26 b(commen)m(t)h(string)347 2445 y(for)40 -b(the)h(k)m(eyw)m(ord)g(ma)m(y)g(b)s(e)f(sp)s(eci\014ed)g(in)g(paren)m -(theses)h(immediately)g(follo)m(wing)h(the)f(k)m(eyw)m(ord)347 -2558 y(name.)256 2746 y Fa(\017)46 b Ff(Ov)m(erwrite)30 -b(the)f(v)-5 b(alues)30 b(in)e(an)h(existing)i(column)d(or)i(k)m(eyw)m -(ord)f(b)m(y)g(giving)h(the)g(name)f(follo)m(w)m(ed)h(b)m(y)347 -2859 y(an)h(equals)f(sign)h(and)e(an)i(arithmetic)g(expression.)256 -3046 y Fa(\017)46 b Ff(Select)36 b(a)e(set)g(of)h(columns)e(to)i(b)s(e) -e(included)h(in)f(the)i(\014ltered)f(\014le)g(b)m(y)g(listing)g(the)h -(column)e(names)347 3159 y(separated)c(with)f(semi-colons.)41 -b(Wild)29 b(card)f(c)m(haracters)i(ma)m(y)e(b)s(e)g(used)f(in)h(the)h -(column)f(names)g(to)347 3272 y(matc)m(h)33 b(m)m(ultiple)g(columns.)46 -b(An)m(y)32 b(other)h(columns)e(in)h(the)h(input)e(table)i(will)f(not)h -(app)s(ear)e(in)h(the)347 3385 y(\014ltered)f(\014le.)256 -3573 y Fa(\017)46 b Ff(Delete)32 b(a)e(column)g(or)f(k)m(eyw)m(ord)h(b) -m(y)g(listing)g(the)g(name)g(preceded)f(b)m(y)h(a)g(min)m(us)f(sign)g -(or)h(an)g(excla-)347 3686 y(mation)h(mark)f(\(!\))256 -3873 y Fa(\017)46 b Ff(Rename)31 b(an)f(existing)i(column)e(or)g(k)m -(eyw)m(ord)h(with)f(the)h(syn)m(tax)g('NewName)g(==)f(OldName'.)261 -4086 y(The)20 b(column)g(\014ltering)h(sp)s(eci\014er)e(is)i(enclosed)g -(in)f(square)g(brac)m(k)m(ets)h(and)f(b)s(egins)g(with)g(the)g(string)h -('col'.)120 4199 y(Multiple)32 b(op)s(erations)f(can)g(b)s(e)f(p)s -(erformed)f(b)m(y)i(separating)g(them)g(with)f(semi-colons.)43 -b(F)-8 b(or)32 b(complex)f(or)120 4312 y(commonly)g(used)g(op)s -(erations,)g(y)m(ou)h(can)f(write)g(the)g(column)g(\014lter)g(to)h(a)f -(text)h(\014le,)f(and)g(then)f(use)h(it)g(b)m(y)120 4425 -y(giving)g(the)g(name)f(of)h(the)f(text)i(\014le,)e(preceded)g(b)m(y)h -(a)f('@')h(c)m(haracter.)261 4538 y(Some)g(examples:)215 -4750 y Fc([col)47 b(PI=PHA)f(*)i(1.1)f(+)g(0.2])285 b(-)48 -b(creates)e(new)g(PI)i(column)e(from)g(PHA)h(values)215 -4976 y([col)g(rate)g(=)g(counts/exposure])91 b(-)48 b(creates)e(or)h -(overwrites)e(the)i(rate)f(column)g(by)1743 5089 y(dividing)f(the)i -(counts)f(column)g(by)i(the)1743 5202 y(EXPOSURE)d(keyword)h(value.)215 -5428 y([col)h(TIME;)f(X;)i(Y])667 b(-)48 b(only)e(the)h(listed)f -(columns)g(will)h(appear)1743 5540 y(in)g(the)g(filtered)e(file)1905 -5809 y Ff(28)p eop end -%%Page: 29 29 -TeXDict begin 29 28 bop 215 686 a Fc([col)47 b(Time;*raw])713 -b(-)48 b(include)e(the)g(Time)h(column)f(and)h(any)g(other)1743 -799 y(columns)f(whose)g(name)h(ends)f(with)h('raw'.)215 -1024 y([col)g(-TIME;)f(Good)h(==)g(STATUS])141 b(-)48 -b(deletes)e(the)g(TIME)h(column)f(and)1743 1137 y(renames)g(the)g -(STATUS)h(column)f(to)h(GOOD)215 1363 y([col)g(@colfilt.txt])569 -b(-)48 b(uses)e(the)h(filtering)f(expression)f(in)1743 -1476 y(the)i(colfilt.txt)d(text)j(file)261 1689 y Ff(The)30 -b(original)i(\014le)f(is)g(not)g(c)m(hanged)g(b)m(y)g(this)g -(\014ltering)g(op)s(eration,)g(and)f(instead)h(the)g(mo)s -(di\014cations)120 1802 y(are)36 b(made)f(on)h(a)f(temp)s(orary)h(cop)m -(y)g(of)f(the)h(input)e(FITS)h(\014le)h(\(usually)f(in)g(memory\),)j -(whic)m(h)d(includes)120 1914 y(a)42 b(cop)m(y)g(of)g(all)g(the)g -(other)g(HDUs)g(in)f(the)h(input)f(\014le.)74 b(The)41 -b(original)i(input)e(\014le)g(is)h(closed)g(and)f(the)120 -2027 y(application)32 b(program)e(op)s(ens)f(the)i(\014ltered)f(cop)m -(y)h(of)g(the)g(\014le.)120 2268 y Fg(5.4.2)105 b(Ro)m(w)36 -b(Filtering)120 2439 y Ff(The)22 b(ro)m(w)h(\014lter)g(is)g(used)f(to)h -(select)h(a)g(subset)e(of)h(the)g(ro)m(ws)f(from)h(a)g(table)g(based)g -(on)f(a)i(b)s(o)s(olean)e(expression.)120 2552 y(A)37 -b(temp)s(orary)g(new)f(FITS)g(\014le)i(is)f(created)h(on)f(the)g(\015y) -f(\(usually)h(in)g(memory\))g(whic)m(h)g(con)m(tains)h(only)120 -2665 y(those)30 b(ro)m(ws)g(for)g(whic)m(h)g(the)g(ro)m(w)g(\014lter)g -(expression)f(ev)-5 b(aluates)32 b(to)e(true)g(\(i.e.,)i(not)e(equal)g -(to)h(zero\).)42 b(The)120 2778 y(primary)25 b(arra)m(y)i(and)e(an)m(y) -h(other)h(extensions)f(in)g(the)g(input)f(\014le)h(are)h(also)g(copied) -f(to)h(the)f(temp)s(orary)g(\014le.)120 2891 y(The)h(original)i(FITS)e -(\014le)h(is)g(closed)g(and)g(the)g(new)f(temp)s(orary)g(\014le)h(is)g -(then)f(op)s(ened)g(b)m(y)h(the)g(application)120 3004 -y(program.)261 3117 y(The)f(ro)m(w)g(\014lter)g(expression)g(is)g -(enclosed)g(in)g(square)g(brac)m(k)m(ets)h(follo)m(wing)h(the)e(\014le) -g(name)g(and)f(exten-)120 3230 y(sion)32 b(name.)48 b(F)-8 -b(or)33 b(example,)h Fc('file.fits[events][GRAD)o(E==5)o(0]')26 -b Ff(selects)34 b(only)f(those)g(ro)m(ws)f(in)g(the)120 -3342 y(EVENTS)e(table)h(where)f(the)g(GRADE)h(column)g(v)-5 -b(alue)30 b(is)h(equal)g(to)g(50\).)261 3455 y(The)d(ro)m(w)h -(\014ltering)f(expression)h(can)f(b)s(e)g(an)h(arbitrarily)f(complex)i -(series)e(of)h(op)s(erations)g(p)s(erformed)120 3568 -y(on)d(constan)m(ts,)i(k)m(eyw)m(ord)e(v)-5 b(alues,)27 -b(and)e(column)h(data)g(tak)m(en)h(from)e(the)h(sp)s(eci\014ed)f(FITS)g -(T)-8 b(ABLE)26 b(exten-)120 3681 y(sion.)40 b(The)27 -b(expression)g(also)i(can)e(b)s(e)g(written)h(in)m(to)h(a)e(text)i -(\014le)f(and)f(then)g(used)g(b)m(y)g(giving)h(the)g(\014lename)120 -3794 y(preceded)i(b)m(y)g(a)h('@')g(c)m(haracter,)h(as)e(in)g -Fc('[@rowfilt.txt]')p Ff(.)261 3907 y(Keyw)m(ord)40 b(and)f(column)h -(data)g(are)h(referenced)f(b)m(y)f(name.)70 b(An)m(y)40 -b(string)g(of)g(c)m(haracters)h(not)f(sur-)120 4020 y(rounded)30 -b(b)m(y)i(quotes)g(\(ie,)h(a)g(constan)m(t)g(string\))f(or)f(follo)m(w) -m(ed)j(b)m(y)d(an)h(op)s(en)f(paren)m(theses)h(\(ie,)i(a)e(function)120 -4133 y(name\))e(will)f(b)s(e)g(initially)h(in)m(terpreted)g(as)f(a)h -(column)f(name)g(and)g(its)h(con)m(ten)m(ts)h(for)e(the)g(curren)m(t)g -(ro)m(w)g(in-)120 4246 y(serted)e(in)m(to)h(the)g(expression.)39 -b(If)27 b(no)g(suc)m(h)g(column)g(exists,)i(a)e(k)m(eyw)m(ord)h(of)g -(that)f(name)h(will)f(b)s(e)g(searc)m(hed)120 4359 y(for)34 -b(and)f(its)h(v)-5 b(alue)35 b(used,)f(if)g(found.)50 -b(T)-8 b(o)35 b(force)f(the)g(name)g(to)h(b)s(e)e(in)m(terpreted)h(as)h -(a)f(k)m(eyw)m(ord)g(\(in)g(case)120 4472 y(there)28 -b(is)g(b)s(oth)f(a)h(column)g(and)f(k)m(eyw)m(ord)h(with)g(the)g(same)g -(name\),)h(precede)f(the)g(k)m(eyw)m(ord)h(name)e(with)h(a)120 -4584 y(single)k(p)s(ound)d(sign,)j('#',)g(as)g(in)f Fc(#NAXIS2)p -Ff(.)41 b(Due)32 b(to)g(the)f(generalities)j(of)d(FITS)g(column)g(and)g -(k)m(eyw)m(ord)120 4697 y(names,)c(if)e(the)h(column)g(or)f(k)m(eyw)m -(ord)h(name)g(con)m(tains)h(a)f(space)g(or)g(a)g(c)m(haracter)h(whic)m -(h)f(migh)m(t)g(app)s(ear)f(as)120 4810 y(an)32 b(arithmetic)h(term)f -(then)g(inclose)h(the)f(name)g(in)f('$')i(c)m(haracters)h(as)e(in)g -Fc($MAX)46 b(PHA$)31 b Ff(or)h Fc(#$MAX-PHA$)p Ff(.)120 -4923 y(The)e(names)g(are)h(case)g(insensitiv)m(e.)261 -5036 y(T)-8 b(o)37 b(access)g(a)g(table)g(en)m(try)g(in)f(a)g(ro)m(w)h -(other)f(than)g(the)h(curren)m(t)f(one,)i(follo)m(w)g(the)e(column's)g -(name)120 5149 y(with)j(a)g(ro)m(w)g(o\013set)g(within)g(curly)f -(braces.)66 b(F)-8 b(or)40 b(example,)i Fc('PHA)p Fa(f)p -Fc(-3)p Fa(g)p Fc(')c Ff(will)h(ev)-5 b(aluate)40 b(to)g(the)f(v)-5 -b(alue)120 5262 y(of)40 b(column)f(PHA,)h(3)g(ro)m(ws)f(ab)s(o)m(v)m(e) -i(the)f(ro)m(w)g(curren)m(tly)f(b)s(eing)g(pro)s(cessed.)68 -b(One)39 b(cannot)h(sp)s(ecify)f(an)120 5375 y(absolute)33 -b(ro)m(w)f(n)m(um)m(b)s(er,)f(only)h(a)h(relativ)m(e)h(o\013set.)47 -b(Ro)m(ws)32 b(that)h(fall)f(outside)g(the)h(table)g(will)f(b)s(e)f -(treated)120 5488 y(as)g(unde\014ned,)d(or)i(NULLs.)1905 -5809 y(29)p eop end -%%Page: 30 30 -TeXDict begin 30 29 bop 261 573 a Ff(Bo)s(olean)32 b(op)s(erators)f -(can)g(b)s(e)g(used)f(in)g(the)h(expression)g(in)f(either)i(their)f(F) --8 b(ortran)31 b(or)g(C)f(forms.)42 b(The)120 686 y(follo)m(wing)32 -b(b)s(o)s(olean)e(op)s(erators)h(are)g(a)m(v)-5 b(ailable:)311 -886 y Fc("equal")428 b(.eq.)46 b(.EQ.)h(==)95 b("not)46 -b(equal")476 b(.ne.)94 b(.NE.)h(!=)311 999 y("less)46 -b(than")238 b(.lt.)46 b(.LT.)h(<)143 b("less)46 b(than/equal")188 -b(.le.)94 b(.LE.)h(<=)47 b(=<)311 1112 y("greater)e(than")95 -b(.gt.)46 b(.GT.)h(>)143 b("greater)45 b(than/equal")g(.ge.)94 -b(.GE.)h(>=)47 b(=>)311 1225 y("or")572 b(.or.)46 b(.OR.)h(||)95 -b("and")762 b(.and.)46 b(.AND.)h(&&)311 1337 y("negation")236 -b(.not.)46 b(.NOT.)h(!)95 b("approx.)45 b(equal\(1e-7\)")92 -b(~)261 1537 y Ff(Note)34 b(that)g(the)f(exclamation)i(p)s(oin)m(t,)f -(')10 b(!',)34 b(is)f(a)h(sp)s(ecial)f(UNIX)g(c)m(haracter,)j(so)d(if)g -(it)g(is)g(used)f(on)h(the)120 1650 y(command)f(line)h(rather)f(than)g -(en)m(tered)h(at)g(a)g(task)g(prompt,)f(it)h(m)m(ust)f(b)s(e)g -(preceded)g(b)m(y)g(a)h(bac)m(kslash)g(to)120 1763 y(force)e(the)g -(UNIX)f(shell)h(to)g(ignore)g(it.)261 1876 y(The)c(expression)f(ma)m(y) -i(also)g(include)f(arithmetic)h(op)s(erators)f(and)f(functions.)39 -b(T)-8 b(rigonometric)29 b(func-)120 1989 y(tions)f(use)g(radians,)h -(not)f(degrees.)40 b(The)28 b(follo)m(wing)i(arithmetic)f(op)s(erators) -f(and)g(functions)f(can)i(b)s(e)e(used)120 2102 y(in)j(the)h -(expression)f(\(function)g(names)g(are)h(case)h(insensitiv)m(e\):)311 -2302 y Fc("addition")522 b(+)477 b("subtraction")d(-)311 -2415 y("multiplication")234 b(*)477 b("division")618 -b(/)311 2528 y("negation")522 b(-)477 b("exponentiation")330 -b(**)143 b(^)311 2641 y("absolute)45 b(value")237 b(abs\(x\))g -("cosine")714 b(cos\(x\))311 2754 y("sine")g(sin\(x\))237 -b("tangent")666 b(tan\(x\))311 2867 y("arc)47 b(cosine")427 -b(arccos\(x\))93 b("arc)47 b(sine")619 b(arcsin\(x\))311 -2979 y("arc)47 b(tangent")379 b(arctan\(x\))93 b("arc)47 -b(tangent")475 b(arctan2\(x,y\))311 3092 y("exponential")378 -b(exp\(x\))237 b("square)46 b(root")476 b(sqrt\(x\))311 -3205 y("natural)45 b(log")381 b(log\(x\))237 b("common)46 -b(log")524 b(log10\(x\))311 3318 y("modulus")570 b(i)48 -b(\045)f(j)286 b("random)46 b(#)h([0.0,1.0\)")141 b(random\(\))311 -3431 y("minimum")570 b(min\(x,y\))141 b("maximum")666 -b(max\(x,y\))311 3544 y("if-then-else")330 b(b?x:y)261 -3744 y Ff(The)37 b(follo)m(wing)i(t)m(yp)s(e)f(casting)g(op)s(erators)g -(are)g(a)m(v)-5 b(ailable,)41 b(where)c(the)h(inclosing)g(paren)m -(theses)g(are)120 3857 y(required)23 b(and)h(tak)m(en)h(from)f(the)h(C) -f(language)h(usage.)40 b(Also,)26 b(the)e(in)m(teger)i(to)f(real)g -(casts)g(v)-5 b(alues)25 b(to)g(double)120 3970 y(precision:)884 -4170 y Fc("real)46 b(to)h(integer")189 b(\(int\))46 b(x)239 -b(\(INT\))46 b(x)884 4283 y("integer)f(to)i(real")190 -b(\(float\))46 b(i)143 b(\(FLOAT\))45 b(i)261 4483 y -Ff(Sev)m(eral)32 b(constan)m(ts)f(are)g(built)f(in)g(for)g(use)g(in)g -(n)m(umerical)h(expressions:)502 4683 y Fc(#pi)667 b(3.1415...)284 -b(#e)620 b(2.7182...)502 4796 y(#deg)f(#pi/180)380 b(#row)524 -b(current)46 b(row)h(number)502 4909 y(#null)428 b(undefined)45 -b(value)142 b(#snull)428 b(undefined)45 b(string)261 -5109 y Ff(A)d(string)g(constan)m(t)h(m)m(ust)f(b)s(e)f(enclosed)i(in)f -(quotes)g(as)g(in)g('Crab'.)75 b(The)41 b("n)m(ull")i(constan)m(ts)g -(are)120 5222 y(useful)37 b(for)g(conditionally)i(setting)g(table)f(v) --5 b(alues)38 b(to)g(a)g(NULL,)g(or)f(unde\014ned,)h(v)-5 -b(alue)38 b(\(F)-8 b(or)38 b(example,)120 5334 y Fc("col1==-99)45 -b(?)95 b(#NULL)47 b(:)g(col1")p Ff(\).)261 5447 y(There)33 -b(is)h(also)g(a)g(function)g(for)f(testing)i(if)e(t)m(w)m(o)i(v)-5 -b(alues)34 b(are)g(close)h(to)f(eac)m(h)h(other,)g(i.e.,)h(if)d(they)h -(are)120 5560 y("near")29 b(eac)m(h)g(other)f(to)g(within)g(a)g(user)f -(sp)s(eci\014ed)g(tolerance.)42 b(The)27 b(argumen)m(ts,)i -Fc(value)p 3184 5560 29 4 v 33 w(1)e Ff(and)h Fc(value)p -3707 5560 V 33 w(2)1905 5809 y Ff(30)p eop end -%%Page: 31 31 -TeXDict begin 31 30 bop 120 573 a Ff(can)39 b(b)s(e)g(in)m(teger)h(or)f -(real)g(and)g(represen)m(t)g(the)g(t)m(w)m(o)h(v)-5 b(alues)39 -b(who's)g(pro)m(ximit)m(y)h(is)f(b)s(eing)g(tested)g(to)h(b)s(e)120 -686 y(within)30 b(the)g(sp)s(eci\014ed)g(tolerance,)i(also)g(an)e(in)m -(teger)i(or)e(real:)1075 880 y Fc(near\(value_1,)44 b(value_2,)h -(tolerance\))261 1074 y Ff(When)30 b(a)h(NULL,)f(or)h(unde\014ned,)d(v) --5 b(alue)31 b(is)f(encoun)m(tered)h(in)f(the)g(FITS)g(table,)h(the)g -(expression)f(will)120 1186 y(ev)-5 b(aluate)43 b(to)f(NULL)g(unless)e -(the)i(unde\014ned)d(v)-5 b(alue)42 b(is)g(not)f(actually)i(required)e -(for)g(ev)-5 b(aluation,)46 b(e.g.)120 1299 y("TR)m(UE)c(.or.)76 -b(NULL")42 b(ev)-5 b(aluates)44 b(to)f(TR)m(UE.)f(The)f(follo)m(wing)j -(t)m(w)m(o)f(functions)f(allo)m(w)h(some)f(NULL)120 1412 -y(detection)32 b(and)e(handling:)1027 1606 y Fc(ISNULL\(x\))1027 -1719 y(DEFNULL\(x,y\))261 1913 y Ff(The)43 b(former)g(returns)f(a)i(b)s -(o)s(olean)f(v)-5 b(alue)44 b(of)f(TR)m(UE)h(if)f(the)h(argumen)m(t)f -(x)h(is)f(NULL.)h(The)e(later)120 2026 y("de\014nes")e(a)g(v)-5 -b(alue)40 b(to)g(b)s(e)g(substituted)f(for)g(NULL)h(v)-5 -b(alues;)45 b(it)40 b(returns)e(the)i(v)-5 b(alue)41 -b(of)e(x)h(if)g(x)f(is)h(not)120 2139 y(NULL,)31 b(otherwise)f(it)h -(returns)e(the)i(v)-5 b(alue)31 b(of)f(y)-8 b(.)261 2252 -y(Bit)32 b(masks)f(can)g(b)s(e)f(used)g(to)h(select)i(out)e(ro)m(ws)g -(from)f(bit)h(columns)f(\()p Fc(TFORMn)47 b(=)g(#X)p -Ff(\))31 b(in)f(FITS)g(\014les.)120 2365 y(T)-8 b(o)31 -b(represen)m(t)f(the)h(mask,)f(binary)-8 b(,)31 b(o)s(ctal,)h(and)d -(hex)i(formats)f(are)h(allo)m(w)m(ed:)931 2558 y Fc(binary:)142 -b(b0110xx1010000101xxxx00)o(01)931 2671 y(octal:)190 -b(o720x1)46 b(->)h(\(b111010000xxx001\))931 2784 y(hex:)286 -b(h0FxD)94 b(->)47 b(\(b00001111xxxx1101\))261 2978 y -Ff(In)28 b(all)i(the)g(represen)m(tations,)g(an)f(x)g(or)g(X)g(is)g -(allo)m(w)m(ed)i(in)e(the)g(mask)g(as)h(a)f(wild)g(card.)40 -b(Note)30 b(that)g(the)120 3091 y(x)i(represen)m(ts)f(a)h(di\013eren)m -(t)g(n)m(um)m(b)s(er)f(of)h(wild)f(card)h(bits)f(in)g(eac)m(h)i -(represen)m(tation.)46 b(All)32 b(represen)m(tations)120 -3204 y(are)f(case)g(insensitiv)m(e.)261 3317 y(T)-8 b(o)38 -b(construct)f(the)h(b)s(o)s(olean)f(expression)g(using)g(the)g(mask)h -(as)f(the)h(b)s(o)s(olean)f(equal)h(op)s(erator)f(de-)120 -3430 y(scrib)s(ed)30 b(ab)s(o)m(v)m(e)h(on)g(a)g(bit)g(table)g(column.) -41 b(F)-8 b(or)32 b(example,)f(if)g(y)m(ou)g(had)f(a)h(7)g(bit)f -(column)h(named)f(\015ags)h(in)120 3543 y(a)36 b(FITS)e(table)j(and)e -(w)m(an)m(ted)h(all)g(ro)m(ws)f(ha)m(ving)h(the)g(bit)f(pattern)h -(0010011,)k(the)35 b(selection)j(expression)120 3656 -y(w)m(ould)30 b(b)s(e:)1456 3850 y Fc(flags)47 b(==)g(b0010011)311 -3962 y(or)1456 4075 y(flags)g(.eq.)f(b10011)261 4269 -y Ff(It)32 b(is)f(also)i(p)s(ossible)e(to)h(test)g(if)g(a)g(range)f(of) -h(bits)f(is)h(less)g(than,)f(less)h(than)g(equal,)g(greater)h(than)e -(and)120 4382 y(greater)h(than)e(equal)h(to)g(a)f(particular)h(b)s(o)s -(olean)g(v)-5 b(alue:)1456 4576 y Fc(flags)47 b(<=)g(bxxx010xx)1456 -4689 y(flags)g(.gt.)f(bxxx100xx)1456 4802 y(flags)h(.le.)f(b1xxxxxxx) -261 4996 y Ff(Notice)32 b(the)f(use)f(of)h(the)f(x)h(bit)f(v)-5 -b(alue)31 b(to)g(limit)g(the)g(range)f(of)h(bits)f(b)s(eing)g -(compared.)261 5109 y(It)j(is)g(not)g(necessary)g(to)g(sp)s(ecify)g -(the)f(leading)i(\(most)f(signi\014can)m(t\))h(zero)g(\(0\))g(bits)e -(in)h(the)g(mask,)g(as)120 5222 y(sho)m(wn)d(in)g(the)g(second)h -(expression)f(ab)s(o)m(v)m(e.)261 5334 y(Bit)h(wise)f(AND,)g(OR)g(and)f -(NOT)g(op)s(erations)h(are)g(also)h(p)s(ossible)e(on)g(t)m(w)m(o)i(or)f -(more)g(bit)g(\014elds)f(using)120 5447 y(the)38 b('&'\(AND\),)h(')p -Fa(j)p Ff('\(OR\),)g(and)e(the)h(')10 b(!'\(NOT\))38 -b(op)s(erators.)63 b(All)38 b(of)g(these)g(op)s(erators)g(result)f(in)g -(a)h(bit)120 5560 y(\014eld)30 b(whic)m(h)g(can)h(then)f(b)s(e)g(used)f -(with)h(the)h(equal)g(op)s(erator.)41 b(F)-8 b(or)31 -b(example:)1905 5809 y(31)p eop end -%%Page: 32 32 -TeXDict begin 32 31 bop 1361 573 a Fc(\(!flags\))45 b(==)j(b1101100) -1361 686 y(\(flags)e(&)h(b1000001\))f(==)h(bx000001)261 -887 y Ff(Bit)36 b(\014elds)e(can)g(b)s(e)g(app)s(ended)f(as)i(w)m(ell)g -(using)f(the)h('+')g(op)s(erator.)53 b(Strings)34 b(can)h(b)s(e)f -(concatenated)120 1000 y(this)c(w)m(a)m(y)-8 b(,)32 b(to)s(o.)120 -1238 y Fg(5.4.3)105 b(Go)s(o)s(d)36 b(Time)f(In)m(terv)-6 -b(al)34 b(Filtering)120 1410 y Ff(A)27 b(common)g(\014ltering)g(metho)s -(d)g(in)m(v)m(olv)m(es)i(selecting)g(ro)m(ws)d(whic)m(h)h(ha)m(v)m(e)h -(a)g(time)f(v)-5 b(alue)28 b(whic)m(h)e(lies)i(within)120 -1523 y(what)38 b(is)f(called)i(a)f(Go)s(o)s(d)g(Time)f(In)m(terv)-5 -b(al)39 b(or)e(GTI.)h(The)f(time)i(in)m(terv)-5 b(als)38 -b(are)g(de\014ned)f(in)g(a)h(separate)120 1636 y(FITS)31 -b(table)i(extension)f(whic)m(h)g(con)m(tains)h(2)f(columns)f(giving)i -(the)f(start)g(and)f(stop)h(time)h(of)f(eac)m(h)g(go)s(o)s(d)120 -1749 y(in)m(terv)-5 b(al.)61 b(The)37 b(\014ltering)g(op)s(eration)g -(accepts)h(only)f(those)g(ro)m(ws)g(of)g(the)g(input)f(table)i(whic)m -(h)e(ha)m(v)m(e)i(an)120 1861 y(asso)s(ciated)32 b(time)g(whic)m(h)f -(falls)g(within)f(one)i(of)f(the)g(time)g(in)m(terv)-5 -b(als)32 b(de\014ned)e(in)h(the)g(GTI)f(extension.)43 -b(A)120 1974 y(high)29 b(lev)m(el)j(function,)e -(gti\014lter\(a,b,c,d\),)j(is)c(a)m(v)-5 b(ailable)33 -b(whic)m(h)c(ev)-5 b(aluates)32 b(eac)m(h)f(ro)m(w)f(of)g(the)g(input)e -(table)120 2087 y(and)i(returns)g(TR)m(UE)g(or)h(F)-10 -b(ALSE)30 b(dep)s(ending)g(whether)g(the)g(ro)m(w)h(is)g(inside)f(or)h -(outside)g(the)g(go)s(o)s(d)g(time)120 2200 y(in)m(terv)-5 -b(al.)42 b(The)30 b(syn)m(tax)h(is)406 2401 y Fc(gtifilter\()45 -b([)j("gtifile")d([,)i(expr)g([,)g("STARTCOL",)e("STOPCOL")g(])j(])f(]) -g(\))120 2603 y Ff(where)35 b(eac)m(h)i("[]")g(demarks)e(optional)h -(parameters.)57 b(Note)37 b(that)f(the)g(quotes)g(around)e(the)i -(gti\014le)h(and)120 2716 y(ST)-8 b(AR)g(T/STOP)31 b(column)i(are)g -(required.)46 b(Either)33 b(single)g(or)f(double)h(quote)g(c)m -(haracters)h(ma)m(y)f(b)s(e)f(used.)120 2828 y(The)c(gti\014le,)i(if)e -(sp)s(eci\014ed,)h(can)f(b)s(e)g(blank)g(\(""\))i(whic)m(h)e(will)h -(mean)g(to)g(use)f(the)g(\014rst)g(extension)h(with)f(the)120 -2941 y(name)23 b("*GTI*")i(in)e(the)g(curren)m(t)g(\014le,)i(a)e(plain) -g(extension)h(sp)s(eci\014er)f(\(eg,)j("+2",)f("[2]",)i(or)c -("[STDGTI]"\))120 3054 y(whic)m(h)g(will)h(b)s(e)f(used)g(to)i(select)g -(an)f(extension)g(in)f(the)h(curren)m(t)g(\014le,)h(or)f(a)g(regular)f -(\014lename)h(with)g(or)f(with-)120 3167 y(out)j(an)g(extension)h(sp)s -(eci\014er)e(whic)m(h)h(in)f(the)i(latter)g(case)g(will)f(mean)g(to)h -(use)f(the)g(\014rst)f(extension)i(with)e(an)120 3280 -y(extension)30 b(name)g("*GTI*".)42 b(Expr)28 b(can)i(b)s(e)f(an)m(y)g -(arithmetic)i(expression,)f(including)f(simply)g(the)h(time)120 -3393 y(column)k(name.)52 b(A)34 b(v)m(ector)i(time)f(expression)f(will) -g(pro)s(duce)f(a)i(v)m(ector)g(b)s(o)s(olean)g(result.)51 -b(ST)-8 b(AR)g(TCOL)120 3506 y(and)33 b(STOPCOL)f(are)j(the)f(names)g -(of)g(the)g(ST)-8 b(AR)g(T/STOP)33 b(columns)h(in)f(the)i(GTI)e -(extension.)53 b(If)33 b(one)120 3619 y(of)e(them)f(is)g(sp)s -(eci\014ed,)g(they)h(b)s(oth)e(m)m(ust)i(b)s(e.)261 3732 -y(In)37 b(its)i(simplest)f(form,)i(no)e(parameters)g(need)g(to)h(b)s(e) -e(pro)m(vided)h({)g(default)h(v)-5 b(alues)38 b(will)g(b)s(e)g(used.) -120 3845 y(The)30 b(expression)g Fc("gtifilter\(\)")d -Ff(is)j(equiv)-5 b(alen)m(t)32 b(to)454 4046 y Fc(gtifilter\()45 -b("",)i(TIME,)f("*START*",)f("*STOP*")h(\))120 4247 y -Ff(This)31 b(will)i(searc)m(h)g(the)f(curren)m(t)g(\014le)h(for)f(a)g -(GTI)g(extension,)i(\014lter)e(the)g(TIME)g(column)g(in)g(the)h(curren) -m(t)120 4360 y(table,)48 b(using)c(ST)-8 b(AR)g(T/STOP)43 -b(times)h(tak)m(en)h(from)e(columns)h(in)g(the)g(GTI)f(extension)i -(with)e(names)120 4473 y(con)m(taining)32 b(the)f(strings)f("ST)-8 -b(AR)g(T")31 b(and)f("STOP".)41 b(The)30 b(wildcards)g(\('*'\))i(allo)m -(w)g(sligh)m(t)f(v)-5 b(ariations)32 b(in)120 4586 y(naming)g(con)m(v)m -(en)m(tions)h(suc)m(h)f(as)g("TST)-8 b(AR)g(T")32 b(or)g("ST)-8 -b(AR)g(TTIME".)45 b(The)31 b(same)i(default)f(v)-5 b(alues)32 -b(apply)120 4699 y(for)f(unsp)s(eci\014ed)f(parameters)i(when)e(the)i -(\014rst)e(one)i(or)f(t)m(w)m(o)i(parameters)f(are)g(sp)s(eci\014ed.)43 -b(The)31 b(function)120 4812 y(automatically)44 b(searc)m(hes)d(for)g -(TIMEZER)m(O/I/F)g(k)m(eyw)m(ords)g(in)f(the)h(curren)m(t)g(and)f(GTI)h -(extensions,)120 4924 y(applying)30 b(a)h(relativ)m(e)h(time)g -(o\013set,)f(if)g(necessary)-8 b(.)120 5163 y Fg(5.4.4)105 -b(Spatial)35 b(Region)h(Filtering)120 5334 y Ff(Another)f(common)h -(\014ltering)g(metho)s(d)f(selects)h(ro)m(ws)g(based)f(on)g(whether)g -(the)h(spatial)g(p)s(osition)f(asso-)120 5447 y(ciated)41 -b(with)f(eac)m(h)i(ro)m(w)e(is)g(lo)s(cated)h(within)f(a)g(giv)m(en)i -(2-dimensional)f(region.)70 b(The)40 b(syn)m(tax)h(for)e(this)120 -5560 y(high-lev)m(el)32 b(\014lter)f(is)1905 5809 y(32)p -eop end -%%Page: 33 33 -TeXDict begin 33 32 bop 454 573 a Fc(regfilter\()45 b("regfilename")f -([)k(,)f(Xexpr,)f(Yexpr)h([)g(,)h("wcs)e(cols")h(])g(])g(\))120 -757 y Ff(where)28 b(eac)m(h)i("[)g(]")f(demarks)g(optional)h -(parameters.)40 b(The)29 b(region)g(\014le)g(name)g(is)g(required)f -(and)g(m)m(ust)h(b)s(e)120 870 y(enclosed)h(in)f(quotes.)41 -b(The)29 b(remaining)g(parameters)h(are)f(optional.)42 -b(The)29 b(region)h(\014le)f(is)g(an)h(ASCI)s(I)d(text)120 -983 y(\014le)37 b(whic)m(h)f(con)m(tains)i(a)f(list)h(of)e(one)h(or)g -(more)g(geometric)i(shap)s(es)c(\(circle,)41 b(ellipse,)e(b)s(o)m(x,)f -(etc.\))62 b(whic)m(h)120 1096 y(de\014nes)30 b(a)i(region)g(on)f(the)h -(celestial)i(sphere)d(or)g(an)g(area)h(within)f(a)h(particular)g(2D)g -(image.)45 b(The)31 b(region)120 1209 y(\014le)38 b(is)g(t)m(ypically)i -(generated)f(using)f(an)g(image)h(displa)m(y)g(program)f(suc)m(h)f(as)i -(fv/PO)m(W)f(\(distribute)g(b)m(y)120 1322 y(the)32 b(HEASAR)m(C\),)g -(or)g(ds9)g(\(distributed)f(b)m(y)g(the)h(Smithsonian)g(Astroph)m -(ysical)g(Observ)-5 b(atory\).)46 b(Users)120 1435 y(should)41 -b(refer)h(to)h(the)f(do)s(cumen)m(tation)h(pro)m(vided)f(with)g(these)g -(programs)g(for)g(more)g(details)h(on)f(the)120 1548 -y(syn)m(tax)31 b(used)e(in)i(the)f(region)h(\014les.)261 -1661 y(In)k(its)h(simpliest)g(form,)h(\(e.g.,)i Fc -(regfilter\("region.reg"\))30 b Ff(\))36 b(the)f(co)s(ordinates)i(in)e -(the)h(default)120 1774 y('X')24 b(and)e('Y')i(columns)e(will)i(b)s(e)e -(used)g(to)i(determine)f(if)g(eac)m(h)h(ro)m(w)f(is)g(inside)g(or)g -(outside)g(the)g(area)h(sp)s(eci\014ed)120 1886 y(in)h(the)h(region)g -(\014le.)39 b(Alternate)27 b(p)s(osition)e(column)g(names,)i(or)e -(expressions,)h(ma)m(y)g(b)s(e)f(en)m(tered)h(if)f(needed,)120 -1999 y(as)31 b(in)502 2184 y Fc(regfilter\("region.reg",)41 -b(XPOS,)47 b(YPOS\))120 2368 y Ff(Region)39 b(\014ltering)g(can)f(b)s -(e)g(applied)g(most)g(unam)m(biguously)g(if)g(the)g(p)s(ositions)h(in)e -(the)i(region)g(\014le)f(and)120 2481 y(in)e(the)h(table)h(to)g(b)s(e)e -(\014ltered)h(are)g(b)s(oth)f(giv)m(e)i(in)f(terms)f(of)h(absolute)h -(celestial)h(co)s(ordinate)f(units.)59 b(In)120 2594 -y(this)38 b(case)h(the)g(lo)s(cations)h(and)d(sizes)i(of)g(the)f -(geometric)i(shap)s(es)e(in)g(the)g(region)h(\014le)f(are)h(sp)s -(eci\014ed)f(in)120 2707 y(angular)d(units)f(on)g(the)h(sky)f(\(e.g.,)j -(p)s(ositions)e(giv)m(en)h(in)e(R.A.)h(and)f(Dec.)54 -b(and)34 b(sizes)h(in)f(arcseconds)h(or)120 2820 y(arcmin)m(utes\).)k -(Similarly)-8 b(,)24 b(eac)m(h)f(ro)m(w)g(of)f(the)g(\014ltered)g -(table)h(will)f(ha)m(v)m(e)h(a)g(celestial)h(co)s(ordinate)f(asso)s -(ciated)120 2933 y(with)33 b(it.)51 b(This)33 b(asso)s(ciation)i(is)f -(usually)f(implemen)m(ted)h(using)g(a)f(set)i(of)e(so-called)j('W)-8 -b(orld)34 b(Co)s(ordinate)120 3046 y(System')i(\(or)h(W)m(CS\))f(FITS)f -(k)m(eyw)m(ords)i(that)f(de\014ne)g(the)g(co)s(ordinate)h -(transformation)f(that)h(m)m(ust)f(b)s(e)120 3159 y(applied)30 -b(to)h(the)g(v)-5 b(alues)31 b(in)f(the)g('X')h(and)f('Y')h(columns)f -(to)h(calculate)i(the)d(co)s(ordinate.)261 3272 y(Alternativ)m(ely)-8 -b(,)40 b(one)c(can)f(p)s(erform)f(spatial)j(\014ltering)e(using)g -(unitless)h('pixel')g(co)s(ordinates)g(for)f(the)120 -3385 y(regions)c(and)f(ro)m(w)h(p)s(ositions.)42 b(In)30 -b(this)g(case)i(the)f(user)f(m)m(ust)h(b)s(e)f(careful)h(to)g(ensure)f -(that)h(the)g(p)s(ositions)120 3498 y(in)i(the)g(2)h(\014les)f(are)h -(self-consisten)m(t.)51 b(A)34 b(t)m(ypical)g(problem)f(is)g(that)h -(the)g(region)g(\014le)f(ma)m(y)h(b)s(e)e(generated)120 -3610 y(using)23 b(a)h(binned)f(image,)j(but)d(the)h(un)m(binned)e(co)s -(ordinates)i(are)h(giv)m(en)f(in)g(the)g(ev)m(en)m(t)h(table.)39 -b(The)24 b(R)m(OSA)-8 b(T)120 3723 y(ev)m(en)m(ts)34 -b(\014les,)g(for)f(example,)i(ha)m(v)m(e)f(X)f(and)g(Y)g(pixel)g(co)s -(ordinates)h(that)g(range)f(from)g(1)g(-)h(15360.)51 -b(These)120 3836 y(co)s(ordinates)33 b(are)g(t)m(ypically)i(binned)c(b) -m(y)i(a)g(factor)g(of)g(32)h(to)f(pro)s(duce)f(a)h(480x480)i(pixel)e -(image.)49 b(If)32 b(one)120 3949 y(then)f(uses)g(a)g(region)h(\014le)f -(generated)i(from)d(this)h(image)i(\(in)e(image)h(pixel)g(units\))f(to) -h(\014lter)f(the)h(R)m(OSA)-8 b(T)120 4062 y(ev)m(en)m(ts)33 -b(\014le,)f(then)f(the)g(X)g(and)g(Y)h(column)f(v)-5 -b(alues)31 b(m)m(ust)h(b)s(e)e(con)m(v)m(erted)j(to)f(corresp)s(onding) -e(pixel)i(units)120 4175 y(as)f(in:)502 4360 y Fc -(regfilter\("rosat.reg",)42 b(X/32.+.5,)j(Y/32.+.5\))120 -4544 y Ff(Note)30 b(that)f(this)f(binning)g(con)m(v)m(ersion)h(is)g -(not)g(necessary)g(if)f(the)h(region)g(\014le)f(is)h(sp)s(eci\014ed)f -(using)g(celestial)120 4657 y(co)s(ordinate)g(units)f(instead)g(of)g -(pixel)h(units)e(b)s(ecause)h(CFITSIO)f(is)h(then)g(able)h(to)g -(directly)f(compare)h(the)120 4770 y(celestial)37 b(co)s(ordinate)e(of) -f(eac)m(h)h(ro)m(w)f(in)g(the)g(table)h(with)f(the)g(celestial)j(co)s -(ordinates)e(in)e(the)i(region)f(\014le)120 4883 y(without)c(ha)m(ving) -h(to)g(kno)m(w)g(an)m(ything)g(ab)s(out)f(ho)m(w)g(the)h(image)g(ma)m -(y)g(ha)m(v)m(e)h(b)s(een)d(binned.)261 4996 y(The)k(last)h("w)m(cs)f -(cols")i(parameter)e(should)f(rarely)h(b)s(e)g(needed.)48 -b(If)33 b(supplied,)f(this)h(string)g(con)m(tains)120 -5109 y(the)39 b(names)g(of)h(the)f(2)g(columns)g(\(space)h(or)f(comma)h -(separated\))g(whic)m(h)f(ha)m(v)m(e)h(the)g(asso)s(ciated)g(W)m(CS)120 -5222 y(k)m(eyw)m(ords.)j(If)30 b(not)h(supplied,)f(the)h(\014lter)g -(will)g(scan)g(the)g(X)g(and)g(Y)g(expressions)f(for)h(column)g(names.) -42 b(If)120 5334 y(only)33 b(one)f(is)h(found)e(in)h(eac)m(h)i -(expression,)f(those)g(columns)f(will)h(b)s(e)f(used,)h(otherwise)g(an) -f(error)g(will)h(b)s(e)120 5447 y(returned.)261 5560 -y(These)d(region)h(shap)s(es)f(are)g(supp)s(orted)f(\(names)i(are)f -(case)i(insensitiv)m(e\):)1905 5809 y(33)p eop end -%%Page: 34 34 -TeXDict begin 34 33 bop 454 573 a Fc(Point)428 b(\()48 -b(X1,)f(Y1)g(\))715 b(<-)48 b(One)f(pixel)f(square)g(region)454 -686 y(Line)476 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2)i(\))333 -b(<-)48 b(One)f(pixel)f(wide)h(region)454 799 y(Polygon)332 -b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(...)g(\))95 b(<-)48 -b(Rest)e(are)h(interiors)e(with)454 912 y(Rectangle)236 -b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(A)h(\))334 b(|)47 b(boundaries)e -(considered)454 1024 y(Box)524 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A) -i(\))143 b(V)47 b(within)f(the)h(region)454 1137 y(Diamond)332 -b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A)i(\))454 1250 -y(Circle)380 b(\()48 b(Xc,)f(Yc,)g(R)g(\))454 1363 y(Annulus)332 -b(\()48 b(Xc,)f(Yc,)g(Rin,)f(Rout)h(\))454 1476 y(Ellipse)332 -b(\()48 b(Xc,)f(Yc,)g(Rx,)f(Ry,)h(A)h(\))454 1589 y(Elliptannulus)c(\() -k(Xc,)f(Yc,)g(Rinx,)f(Riny,)g(Routx,)g(Routy,)g(Ain,)h(Aout)g(\))454 -1702 y(Sector)380 b(\()48 b(Xc,)f(Yc,)g(Amin,)f(Amax)h(\))120 -1914 y Ff(where)33 b(\(Xc,Yc\))j(is)e(the)h(co)s(ordinate)f(of)h(the)f -(shap)s(e's)f(cen)m(ter;)k(\(X#,Y#\))e(are)f(the)g(co)s(ordinates)h(of) -f(the)120 2027 y(shap)s(e's)22 b(edges;)k(Rxxx)d(are)g(the)h(shap)s -(es')e(v)-5 b(arious)23 b(Radii)g(or)g(semima)5 b(jor/minor)23 -b(axes;)k(and)22 b(Axxx)h(are)g(the)120 2140 y(angles)j(of)f(rotation)h -(\(or)f(b)s(ounding)e(angles)j(for)f(Sector\))h(in)e(degrees.)40 -b(F)-8 b(or)26 b(rotated)g(shap)s(es,)f(the)g(rotation)120 -2253 y(angle)37 b(can)g(b)s(e)e(left)i(o\013,)h(indicating)f(no)f -(rotation.)60 b(Common)35 b(alternate)j(names)e(for)g(the)g(regions)h -(can)120 2366 y(also)28 b(b)s(e)e(used:)39 b(rotb)s(o)m(x)27 -b(=)f(b)s(o)m(x;)j(rotrectangle)g(=)e(rectangle;)j(\(rot\)rhom)m(bus)c -(=)h(\(rot\)diamond;)i(and)d(pie)120 2479 y(=)h(sector.)41 -b(When)28 b(a)g(shap)s(e's)f(name)g(is)h(preceded)f(b)m(y)h(a)g(min)m -(us)f(sign,)i('-',)g(the)f(de\014ned)e(region)i(is)g(instead)120 -2592 y(the)36 b(area)g(*outside*)h(its)f(b)s(oundary)d(\(ie,)38 -b(the)e(region)g(is)g(in)m(v)m(erted\).)57 b(All)36 b(the)g(shap)s(es)f -(within)g(a)h(single)120 2705 y(region)f(\014le)g(are)g(OR'd)g -(together)h(to)f(create)i(the)e(region,)h(and)f(the)g(order)f(is)h -(signi\014can)m(t.)55 b(The)34 b(o)m(v)m(erall)120 2818 -y(w)m(a)m(y)g(of)g(lo)s(oking)g(at)g(region)g(\014les)f(is)g(that)h(if) -f(the)h(\014rst)e(region)i(is)g(an)f(excluded)g(region)h(then)f(a)g -(dumm)m(y)120 2931 y(included)c(region)i(of)f(the)g(whole)g(detector)i -(is)e(inserted)f(in)h(the)g(fron)m(t.)41 b(Then)29 b(eac)m(h)i(region)g -(sp)s(eci\014cation)120 3044 y(as)g(it)h(is)f(pro)s(cessed)g(o)m(v)m -(errides)h(an)m(y)f(selections)i(inside)e(of)g(that)h(region)g(sp)s -(eci\014ed)e(b)m(y)h(previous)g(regions.)120 3156 y(Another)e(w)m(a)m -(y)i(of)e(thinking)g(ab)s(out)g(this)g(is)h(that)f(if)h(a)f(previous)g -(excluded)g(region)h(is)g(completely)h(inside)120 3269 -y(of)g(a)f(subsequen)m(t)g(included)g(region)h(the)f(excluded)g(region) -h(is)g(ignored.)261 3382 y(The)20 b(p)s(ositional)h(co)s(ordinates)g -(ma)m(y)g(b)s(e)e(giv)m(en)j(either)e(in)g(pixel)h(units,)h(decimal)f -(degrees)g(or)f(hh:mm:ss.s,)120 3495 y(dd:mm:ss.s)25 -b(units.)38 b(The)26 b(shap)s(e)f(sizes)h(ma)m(y)h(b)s(e)e(giv)m(en)i -(in)e(pixels,)j(degrees,)f(arcmin)m(utes,)h(or)e(arcseconds.)120 -3608 y(Lo)s(ok)k(at)i(examples)e(of)h(region)g(\014le)f(pro)s(duced)f -(b)m(y)h(fv/PO)m(W)h(or)f(ds9)g(for)g(further)f(details)j(of)e(the)h -(region)120 3721 y(\014le)f(format.)120 3961 y Fg(5.4.5)105 -b(Example)35 b(Ro)m(w)g(Filters)311 4133 y Fc([double)46 -b(&&)h(mag)g(<=)g(5.0])381 b(-)95 b(Extract)46 b(all)h(double)f(stars)g -(brighter)1886 4246 y(than)94 b(fifth)47 b(magnitude)311 -4472 y([#row)f(>=)h(125)g(&&)h(#row)e(<=)h(175])142 b(-)48 -b(Extract)e(row)h(numbers)e(125)i(through)f(175)311 4697 -y([abs\(sin\(theta)e(*)j(#deg\)\))f(<)i(0.5])e(-)i(Extract)e(all)h -(rows)f(having)g(the)1886 4810 y(absolute)f(value)i(of)g(the)g(sine)g -(of)g(theta)1886 4923 y(less)94 b(than)47 b(a)g(half)g(where)f(the)h -(angles)1886 5036 y(are)g(tabulated)e(in)i(degrees)311 -5262 y([@rowFilter.txt])711 b(-)48 b(Extract)e(rows)g(using)h(the)g -(expression)1886 5375 y(contained)e(within)h(the)h(text)g(file)1886 -5488 y(rowFilter.txt)1905 5809 y Ff(34)p eop end -%%Page: 35 35 -TeXDict begin 35 34 bop 311 686 a Fc([gtifilter\(\)])855 -b(-)48 b(Search)e(the)h(current)f(file)g(for)h(a)h(GTI)359 -799 y(extension,)92 b(filter)i(the)47 b(TIME)359 912 -y(column)f(in)h(the)g(current)f(table,)g(using)359 1024 -y(START/STOP)f(times)h(taken)g(from)359 1137 y(columns)f(in)j(the)f -(GTI)94 b(extension)311 1363 y([regfilter\("pow.reg"\)])423 -b(-)48 b(Extract)e(rows)g(which)h(have)f(a)i(coordinate)1886 -1476 y(\(as)f(given)f(in)h(the)g(X)h(and)f(Y)g(columns\))1886 -1589 y(within)f(the)h(spatial)f(region)g(specified)1886 -1702 y(in)h(the)g(pow.reg)f(region)g(file.)1905 5809 -y Ff(35)p eop end -%%Page: 36 36 -TeXDict begin 36 35 bop 120 573 a Fb(5.5)112 b(Com)m(bined)39 -b(Filtering)f(Examples)120 744 y Ff(The)29 b(previous)h(sections)g -(describ)s(ed)f(all)i(the)f(individual)f(t)m(yp)s(es)h(of)g(\014lters)f -(that)i(ma)m(y)f(b)s(e)f(applied)h(to)g(the)120 857 y(input)j(\014le.) -50 b(In)33 b(this)g(section)i(w)m(e)f(sho)m(w)g(examples)g(whic)m(h)f -(com)m(bine)i(sev)m(eral)f(di\013eren)m(t)h(\014lters)e(at)h(once.)120 -970 y(These)h(examples)g(all)h(use)f(the)g Fc(fitscopy)e -Ff(program)i(that)g(is)g(distributed)f(with)h(the)g(CFITSIO)f(co)s(de.) -120 1083 y(It)c(simply)g(copies)i(the)e(input)g(\014le)g(to)h(the)g -(output)f(\014le.)120 1268 y Fc(fitscopy)46 b(rosat.fit)f(out.fit)261 -1453 y Ff(This)26 b(trivial)i(example)f(simply)g(mak)m(es)g(an)g(iden)m -(tical)i(cop)m(y)e(of)g(the)g(input)f(rosat.\014t)h(\014le)g(without)g -(an)m(y)120 1566 y(\014ltering.)120 1751 y Fc(fitscopy)46 -b('rosat.fit[events][col)41 b(Time;X;Y][#row)j(<)k(1000]')e(out.fit)261 -1936 y Ff(The)34 b(output)g(\014le)h(con)m(tains)h(only)e(the)h(Time,)h -(X,)f(and)e(Y)i(columns,)h(and)d(only)i(the)g(\014rst)f(999)h(ro)m(ws) -120 2049 y(from)g(the)g('EVENTS')f(table)i(extension)g(of)f(the)g -(input)f(\014le.)55 b(All)35 b(the)h(other)f(HDUs)g(in)g(the)g(input)f -(\014le)120 2162 y(are)d(copied)g(to)g(the)f(output)g(\014le)h(without) -f(an)m(y)h(mo)s(di\014cation.)120 2346 y Fc(fitscopy)46 -b('rosat.fit[events][PI)c(<)47 b(50][bin)f(\(Xdet,Ydet\))f(=)i(16]')g -(image.fit)261 2531 y Ff(This)30 b(creates)h(an)f(output)g(image)i(b)m -(y)e(binning)f(the)h(Xdet)h(and)f(Ydet)g(columns)g(of)g(the)h(ev)m(en)m -(ts)g(table)120 2644 y(with)26 b(a)h(pixel)g(binning)e(factor)i(of)g -(16.)40 b(Only)26 b(the)h(ro)m(ws)f(whic)m(h)g(ha)m(v)m(e)i(a)e(PI)h -(energy)f(less)h(than)f(50)h(are)g(used)120 2757 y(to)33 -b(construct)f(this)f(image.)46 b(The)32 b(output)f(image)i(\014le)f -(con)m(tains)h(a)f(primary)f(arra)m(y)h(image)h(without)f(an)m(y)120 -2870 y(extensions.)120 3055 y Fc(fitscopy)46 b('rosat.fit[events][gtif) -o(ilt)o(er\(\))41 b(&&)47 b(regfilter\("pow.reg"\)]')42 -b(out.fit)261 3240 y Ff(The)29 b(\014ltering)h(expression)f(in)g(this)h -(example)g(uses)f(the)h Fc(gtifilter)d Ff(function)i(to)h(test)g -(whether)f(the)120 3353 y(TIME)e(column)g(v)-5 b(alue)27 -b(in)g(eac)m(h)i(ro)m(w)e(is)g(within)g(one)g(of)g(the)h(Go)s(o)s(d)f -(Time)g(In)m(terv)-5 b(als)27 b(de\014ned)f(in)h(the)h(GTI)120 -3466 y(extension)i(in)f(the)h(same)g(input)e(\014le,)i(and)f(also)i -(uses)e(the)g Fc(regfilter)e Ff(function)j(to)g(test)g(if)g(the)f(p)s -(osition)120 3579 y(asso)s(ciated)j(with)d(eac)m(h)i(ro)m(w)g(\(deriv)m -(ed)f(b)m(y)g(default)g(from)g(the)g(v)-5 b(alues)30 -b(in)g(the)g(X)h(and)e(Y)h(columns)g(of)g(the)120 3692 -y(ev)m(en)m(ts)38 b(table\))f(is)g(lo)s(cated)h(within)d(the)i(area)g -(de\014ned)e(in)i(the)f Fc(pow.reg)f Ff(text)i(region)g(\014le)f -(\(whic)m(h)h(w)m(as)120 3804 y(previously)h(created)i(with)f(the)f -Fc(fv/POW)f Ff(image)j(displa)m(y)f(program\).)66 b(Only)38 -b(the)h(ro)m(ws)f(whic)m(h)h(satisfy)120 3917 y(b)s(oth)30 -b(tests)h(are)g(copied)f(to)h(the)g(output)f(table.)120 -4102 y Fc(fitscopy)46 b('r.fit[evt][PI<50]')c(stdout)k(|)i(fitscopy)d -(stdin[evt][col)f(X,Y])j(out.fit)261 4287 y Ff(In)25 -b(this)g(somewhat)h(con)m(v)m(oluted)g(example,)i(\014tscop)m(y)d(is)h -(used)e(to)i(\014rst)f(select)i(the)e(ro)m(ws)g(from)g(the)h(evt)120 -4400 y(extension)k(whic)m(h)g(ha)m(v)m(e)h(PI)e(less)h(than)g(50)g(and) -f(write)h(the)g(resulting)g(table)h(out)f(to)g(the)g(stdout)g(stream.) -120 4513 y(This)37 b(is)g(pip)s(ed)f(to)i(a)g(2nd)f(instance)h(of)g -(\014tscop)m(y)g(\(with)f(the)h(Unix)f(`)p Fa(j)p Ff(')h(pip)s(e)f -(command\))g(whic)m(h)h(reads)120 4626 y(that)31 b(\014ltered)g(FITS)e -(\014le)i(from)f(the)h(stdin)f(stream)h(and)f(copies)h(only)g(the)g(X)f -(and)g(Y)h(columns)f(from)g(the)120 4739 y(evt)h(table)g(to)g(the)g -(output)f(\014le.)120 4924 y Fc(fitscopy)46 b('r.fit[evt][col)d -(RAD=sqrt\(\(X-#XCEN\)**2+\(Y-)o(#YCE)o(N\)*)o(*2\)])o([rad)o(<10)o -(0]')e(out.fit)261 5109 y Ff(This)24 b(example)i(\014rst)e(creates)i(a) -f(new)f(column)h(called)h(RAD)f(whic)m(h)f(giv)m(es)i(the)f(distance)h -(b)s(et)m(w)m(een)f(the)120 5222 y(X,Y)k(co)s(ordinate)g(of)f(eac)m(h)i -(ev)m(en)m(t)g(and)d(the)i(co)s(ordinate)g(de\014ned)e(b)m(y)h(the)h(X) -m(CEN)f(and)g(YCEN)g(k)m(eyw)m(ords)120 5334 y(in)k(the)h(header.)47 -b(Then,)32 b(only)h(those)g(ro)m(ws)g(whic)m(h)f(ha)m(v)m(e)i(a)f -(distance)g(less)g(than)f(100)i(are)f(copied)g(to)g(the)120 -5447 y(output)e(table.)46 b(In)31 b(other)h(w)m(ords,)f(only)h(the)g -(ev)m(en)m(ts)h(whic)m(h)f(are)g(lo)s(cated)h(within)e(100)i(pixel)f -(units)f(from)120 5560 y(the)g(\(X)m(CEN,)g(YCEN\))f(co)s(ordinate)i -(are)e(copied)h(to)g(the)g(output)f(table.)1905 5809 -y(36)p eop end -%%Page: 37 37 -TeXDict begin 37 36 bop 120 573 a Fc(fitscopy)46 b -('ftp://heasarc.gsfc.nas)o(a.g)o(ov/r)o(osat)o(.fi)o(t[ev)o(ents)o(][b) -o(in)c(\(X,Y\)=16]')j(img.fit)261 785 y Ff(This)23 b(example)h(bins)e -(the)h(X)h(and)f(Y)g(columns)g(of)g(the)h(h)m(yp)s(othetical)g(R)m(OSA) --8 b(T)24 b(\014le)f(at)h(the)f(HEASAR)m(C)120 898 y(ftp)30 -b(site)h(to)g(create)h(the)f(output)f(image.)120 1111 -y Fc(fitscopy)46 b('raw.fit[i512,512][101:)o(110)o(,51:)o(60]')41 -b(image.fit)261 1323 y Ff(This)29 b(example)h(con)m(v)m(erts)h(the)e -(512)i(x)e(512)i(pixel)f(ra)m(w)f(binary)g(16-bit)h(in)m(teger)h(image) -g(to)f(a)g(FITS)e(\014le)120 1436 y(and)i(copies)h(a)g(10)g(x)f(10)h -(pixel)g(subimage)g(from)f(it)g(to)i(the)e(output)g(FITS)g(image.)1905 -5809 y(37)p eop end -%%Page: 38 38 -TeXDict begin 38 37 bop 120 573 a Fh(6)135 b(CFITSIO)44 -b(Error)h(Status)g(Co)t(des)120 776 y Ff(The)34 b(follo)m(wing)h(table) -g(lists)g(all)g(the)f(error)g(status)g(co)s(des)h(used)e(b)m(y)h -(CFITSIO.)f(Programmers)h(are)g(en-)120 889 y(couraged)f(to)g(use)g -(the)f(sym)m(b)s(olic)h(mnemonics)g(\(de\014ned)e(in)h(the)h(\014le)g -(\014tsio.h\))g(rather)f(than)g(the)h(actual)120 1002 -y(in)m(teger)f(status)e(v)-5 b(alues)31 b(to)g(impro)m(v)m(e)g(the)g -(readabilit)m(y)h(of)e(their)h(co)s(de.)168 1214 y Fc(Symbolic)45 -b(Const)190 b(Value)237 b(Meaning)168 1327 y(--------------)187 -b(-----)94 b(------------------------)o(----)o(---)o(----)o(----)o(--) -1122 1440 y(0)191 b(OK,)47 b(no)g(error)168 1553 y(SAME_FILE)427 -b(101)190 b(input)46 b(and)h(output)f(files)h(are)g(the)f(same)168 -1666 y(TOO_MANY_FILES)187 b(103)j(tried)46 b(to)h(open)g(too)g(many)g -(FITS)f(files)h(at)g(once)168 1779 y(FILE_NOT_OPENED)139 -b(104)190 b(could)46 b(not)h(open)g(the)g(named)f(file)168 -1892 y(FILE_NOT_CREATED)91 b(105)190 b(could)46 b(not)h(create)f(the)h -(named)g(file)168 2005 y(WRITE_ERROR)331 b(106)190 b(error)46 -b(writing)g(to)h(FITS)g(file)168 2117 y(END_OF_FILE)331 -b(107)190 b(tried)46 b(to)h(move)g(past)g(end)g(of)g(file)168 -2230 y(READ_ERROR)379 b(108)190 b(error)46 b(reading)g(from)h(FITS)f -(file)168 2343 y(FILE_NOT_CLOSED)139 b(110)190 b(could)46 -b(not)h(close)g(the)f(file)168 2456 y(ARRAY_TOO_BIG)235 -b(111)190 b(array)46 b(dimensions)f(exceed)h(internal)g(limit)168 -2569 y(READONLY_FILE)235 b(112)190 b(Cannot)46 b(write)g(to)i(readonly) -d(file)168 2682 y(MEMORY_ALLOCATION)e(113)190 b(Could)46 -b(not)h(allocate)f(memory)168 2795 y(BAD_FILEPTR)331 -b(114)190 b(invalid)46 b(fitsfile)f(pointer)168 2908 -y(NULL_INPUT_PTR)187 b(115)j(NULL)47 b(input)f(pointer)g(to)h(routine) -168 3021 y(SEEK_ERROR)379 b(116)190 b(error)46 b(seeking)g(position)g -(in)h(file)168 3247 y(BAD_URL_PREFIX)235 b(121)142 b(invalid)46 -b(URL)h(prefix)f(on)h(file)g(name)168 3359 y(TOO_MANY_DRIVERS)139 -b(122)j(tried)46 b(to)h(register)f(too)h(many)g(IO)g(drivers)168 -3472 y(DRIVER_INIT_FAILED)c(123)142 b(driver)46 b(initialization)e -(failed)168 3585 y(NO_MATCHING_DRIVER)f(124)142 b(matching)45 -b(driver)i(is)g(not)g(registered)168 3698 y(URL_PARSE_ERROR)187 -b(125)142 b(failed)46 b(to)h(parse)g(input)f(file)h(URL)168 -3924 y(SHARED_BADARG)235 b(151)190 b(bad)47 b(argument)e(in)j(shared)e -(memory)g(driver)168 4037 y(SHARED_NULPTR)235 b(152)190 -b(null)47 b(pointer)e(passed)h(as)i(an)f(argument)168 -4150 y(SHARED_TABFULL)187 b(153)j(no)47 b(more)g(free)f(shared)g -(memory)h(handles)168 4263 y(SHARED_NOTINIT)187 b(154)j(shared)46 -b(memory)g(driver)g(is)h(not)g(initialized)168 4376 y(SHARED_IPCERR)235 -b(155)190 b(IPC)47 b(error)f(returned)g(by)h(a)g(system)f(call)168 -4489 y(SHARED_NOMEM)283 b(156)190 b(no)47 b(memory)f(in)h(shared)f -(memory)h(driver)168 4601 y(SHARED_AGAIN)283 b(157)190 -b(resource)45 b(deadlock)h(would)g(occur)168 4714 y(SHARED_NOFILE)235 -b(158)190 b(attempt)46 b(to)h(open/create)e(lock)h(file)h(failed)168 -4827 y(SHARED_NORESIZE)139 b(159)190 b(shared)46 b(memory)g(block)g -(cannot)h(be)g(resized)f(at)h(the)g(moment)168 5053 y(HEADER_NOT_EMPTY) -91 b(201)190 b(header)46 b(already)g(contains)f(keywords)168 -5166 y(KEY_NO_EXIST)283 b(202)190 b(keyword)46 b(not)h(found)f(in)h -(header)168 5279 y(KEY_OUT_BOUNDS)187 b(203)j(keyword)46 -b(record)g(number)g(is)h(out)g(of)g(bounds)168 5392 y(VALUE_UNDEFINED) -139 b(204)190 b(keyword)46 b(value)g(field)g(is)i(blank)168 -5505 y(NO_QUOTE)475 b(205)190 b(string)46 b(is)h(missing)f(the)h -(closing)f(quote)1905 5809 y Ff(38)p eop end -%%Page: 39 39 -TeXDict begin 39 38 bop 168 573 a Fc(BAD_KEYCHAR)331 -b(207)190 b(illegal)46 b(character)f(in)i(keyword)f(name)h(or)g(card) -168 686 y(BAD_ORDER)427 b(208)190 b(required)45 b(keywords)h(out)h(of)g -(order)168 799 y(NOT_POS_INT)331 b(209)190 b(keyword)46 -b(value)g(is)h(not)g(a)h(positive)d(integer)168 912 y(NO_END)571 -b(210)190 b(couldn't)45 b(find)i(END)g(keyword)168 1024 -y(BAD_BITPIX)379 b(211)190 b(illegal)46 b(BITPIX)g(keyword)g(value)168 -1137 y(BAD_NAXIS)427 b(212)190 b(illegal)46 b(NAXIS)g(keyword)g(value) -168 1250 y(BAD_NAXES)427 b(213)190 b(illegal)46 b(NAXISn)g(keyword)g -(value)168 1363 y(BAD_PCOUNT)379 b(214)190 b(illegal)46 -b(PCOUNT)g(keyword)g(value)168 1476 y(BAD_GCOUNT)379 -b(215)190 b(illegal)46 b(GCOUNT)g(keyword)g(value)168 -1589 y(BAD_TFIELDS)331 b(216)190 b(illegal)46 b(TFIELDS)g(keyword)f -(value)168 1702 y(NEG_WIDTH)427 b(217)190 b(negative)45 -b(table)i(row)g(size)168 1815 y(NEG_ROWS)475 b(218)190 -b(negative)45 b(number)i(of)g(rows)f(in)i(table)168 1928 -y(COL_NOT_FOUND)235 b(219)190 b(column)46 b(with)h(this)f(name)h(not)g -(found)f(in)h(table)168 2041 y(BAD_SIMPLE)379 b(220)190 -b(illegal)46 b(value)g(of)h(SIMPLE)f(keyword)168 2154 -y(NO_SIMPLE)427 b(221)190 b(Primary)46 b(array)g(doesn't)g(start)g -(with)h(SIMPLE)168 2267 y(NO_BITPIX)427 b(222)190 b(Second)46 -b(keyword)g(not)h(BITPIX)168 2379 y(NO_NAXIS)475 b(223)190 -b(Third)46 b(keyword)g(not)h(NAXIS)168 2492 y(NO_NAXES)475 -b(224)190 b(Couldn't)45 b(find)i(all)g(the)g(NAXISn)f(keywords)168 -2605 y(NO_XTENSION)331 b(225)190 b(HDU)47 b(doesn't)f(start)g(with)h -(XTENSION)e(keyword)168 2718 y(NOT_ATABLE)379 b(226)190 -b(the)47 b(CHDU)f(is)i(not)f(an)g(ASCII)f(table)g(extension)168 -2831 y(NOT_BTABLE)379 b(227)190 b(the)47 b(CHDU)f(is)i(not)f(a)g -(binary)f(table)g(extension)168 2944 y(NO_PCOUNT)427 -b(228)190 b(couldn't)45 b(find)i(PCOUNT)f(keyword)168 -3057 y(NO_GCOUNT)427 b(229)190 b(couldn't)45 b(find)i(GCOUNT)f(keyword) -168 3170 y(NO_TFIELDS)379 b(230)190 b(couldn't)45 b(find)i(TFIELDS)f -(keyword)168 3283 y(NO_TBCOL)475 b(231)190 b(couldn't)45 -b(find)i(TBCOLn)f(keyword)168 3396 y(NO_TFORM)475 b(232)190 -b(couldn't)45 b(find)i(TFORMn)f(keyword)168 3509 y(NOT_IMAGE)427 -b(233)190 b(the)47 b(CHDU)f(is)i(not)f(an)g(IMAGE)f(extension)168 -3621 y(BAD_TBCOL)427 b(234)190 b(TBCOLn)46 b(keyword)g(value)g(<)i(0)f -(or)g(>)h(rowlength)168 3734 y(NOT_TABLE)427 b(235)190 -b(the)47 b(CHDU)f(is)i(not)f(a)g(table)168 3847 y(COL_TOO_WIDE)283 -b(236)190 b(column)46 b(is)h(too)g(wide)g(to)g(fit)g(in)g(table)168 -3960 y(COL_NOT_UNIQUE)187 b(237)j(more)47 b(than)f(1)i(column)e(name)g -(matches)g(template)168 4073 y(BAD_ROW_WIDTH)235 b(241)190 -b(sum)47 b(of)g(column)f(widths)g(not)h(=)h(NAXIS1)168 -4186 y(UNKNOWN_EXT)331 b(251)190 b(unrecognizable)44 -b(FITS)i(extension)g(type)168 4299 y(UNKNOWN_REC)331 -b(252)190 b(unknown)46 b(record;)g(1st)g(keyword)g(not)h(SIMPLE)f(or)h -(XTENSION)168 4412 y(END_JUNK)475 b(253)190 b(END)47 -b(keyword)f(is)h(not)g(blank)168 4525 y(BAD_HEADER_FILL)139 -b(254)190 b(Header)46 b(fill)h(area)f(contains)g(non-blank)f(chars)168 -4638 y(BAD_DATA_FILL)235 b(255)190 b(Illegal)46 b(data)g(fill)h(bytes)f -(\(not)h(zero)g(or)g(blank\))168 4751 y(BAD_TFORM)427 -b(261)190 b(illegal)46 b(TFORM)g(format)g(code)168 4863 -y(BAD_TFORM_DTYPE)139 b(262)190 b(unrecognizable)44 b(TFORM)i(datatype) -g(code)168 4976 y(BAD_TDIM)475 b(263)190 b(illegal)46 -b(TDIMn)g(keyword)g(value)168 5089 y(BAD_HEAP_PTR)283 -b(264)190 b(invalid)46 b(BINTABLE)f(heap)i(pointer)f(is)h(out)g(of)g -(range)168 5315 y(BAD_HDU_NUM)331 b(301)190 b(HDU)47 -b(number)f(<)h(1)h(or)f(>)g(MAXHDU)168 5428 y(BAD_COL_NUM)331 -b(302)190 b(column)46 b(number)g(<)i(1)f(or)g(>)h(tfields)168 -5541 y(NEG_FILE_POS)283 b(304)190 b(tried)46 b(to)h(move)g(to)g -(negative)f(byte)g(location)g(in)h(file)1905 5809 y Ff(39)p -eop end -%%Page: 40 40 -TeXDict begin 40 39 bop 168 573 a Fc(NEG_BYTES)427 b(306)190 -b(tried)46 b(to)h(read)g(or)g(write)g(negative)e(number)h(of)h(bytes) -168 686 y(BAD_ROW_NUM)331 b(307)190 b(illegal)46 b(starting)f(row)i -(number)f(in)h(table)168 799 y(BAD_ELEM_NUM)283 b(308)190 -b(illegal)46 b(starting)f(element)h(number)g(in)h(vector)168 -912 y(NOT_ASCII_COL)235 b(309)190 b(this)47 b(is)g(not)g(an)g(ASCII)f -(string)g(column)168 1024 y(NOT_LOGICAL_COL)139 b(310)190 -b(this)47 b(is)g(not)g(a)g(logical)f(datatype)f(column)168 -1137 y(BAD_ATABLE_FORMAT)e(311)190 b(ASCII)46 b(table)h(column)f(has)h -(wrong)f(format)168 1250 y(BAD_BTABLE_FORMAT)d(312)190 -b(Binary)46 b(table)g(column)g(has)h(wrong)g(format)168 -1363 y(NO_NULL)523 b(314)190 b(null)47 b(value)f(has)h(not)g(been)f -(defined)168 1476 y(NOT_VARI_LEN)283 b(317)190 b(this)47 -b(is)g(not)g(a)g(variable)f(length)g(column)168 1589 -y(BAD_DIMEN)427 b(320)190 b(illegal)46 b(number)g(of)h(dimensions)e(in) -i(array)168 1702 y(BAD_PIX_NUM)331 b(321)190 b(first)46 -b(pixel)h(number)f(greater)g(than)g(last)h(pixel)168 -1815 y(ZERO_SCALE)379 b(322)190 b(illegal)46 b(BSCALE)g(or)h(TSCALn)f -(keyword)g(=)h(0)168 1928 y(NEG_AXIS)475 b(323)190 b(illegal)46 -b(axis)g(length)g(<)i(1)168 2154 y(NOT_GROUP_TABLE)330 -b(340)142 b(Grouping)46 b(function)f(error)168 2267 y -(HDU_ALREADY_MEMBER)186 b(341)168 2379 y(MEMBER_NOT_FOUND)282 -b(342)168 2492 y(GROUP_NOT_FOUND)330 b(343)168 2605 y(BAD_GROUP_ID)474 -b(344)168 2718 y(TOO_MANY_HDUS_TRACKED)42 b(345)168 2831 -y(HDU_ALREADY_TRACKED)138 b(346)168 2944 y(BAD_OPTION)570 -b(347)168 3057 y(IDENTICAL_POINTERS)186 b(348)168 3170 -y(BAD_GROUP_ATTACH)282 b(349)168 3283 y(BAD_GROUP_DETACH)g(350)168 -3509 y(NGP_NO_MEMORY)426 b(360)238 b(malloc)46 b(failed)168 -3621 y(NGP_READ_ERR)474 b(361)238 b(read)46 b(error)h(from)f(file)168 -3734 y(NGP_NUL_PTR)522 b(362)238 b(null)46 b(pointer)g(passed)g(as)h -(an)g(argument.)1695 3847 y(Passing)f(null)g(pointer)g(as)h(a)h(name)f -(of)1695 3960 y(template)f(file)g(raises)g(this)h(error)168 -4073 y(NGP_EMPTY_CURLINE)234 b(363)k(line)46 b(read)h(seems)f(to)h(be)h -(empty)e(\(used)1695 4186 y(internally\))168 4299 y -(NGP_UNREAD_QUEUE_FULL)c(364)238 b(cannot)46 b(unread)g(more)g(then)h -(1)g(line)g(\(or)g(single)1695 4412 y(line)g(twice\))168 -4525 y(NGP_INC_NESTING)330 b(365)238 b(too)46 b(deep)h(include)f(file)h -(nesting)e(\(infinite)1695 4638 y(loop,)h(template)g(includes)f(itself) -i(?\))168 4751 y(NGP_ERR_FOPEN)426 b(366)238 b(fopen\(\))45 -b(failed,)h(cannot)g(open)h(template)e(file)168 4863 -y(NGP_EOF)714 b(367)238 b(end)46 b(of)i(file)e(encountered)f(and)i(not) -g(expected)168 4976 y(NGP_BAD_ARG)522 b(368)238 b(bad)46 -b(arguments)g(passed.)g(Usually)f(means)1695 5089 y(internal)h(parser)g -(error.)g(Should)g(not)h(happen)168 5202 y(NGP_TOKEN_NOT_EXPECT)90 -b(369)238 b(token)46 b(not)h(expected)e(here)168 5428 -y(BAD_I2C)523 b(401)190 b(bad)47 b(int)g(to)g(formatted)e(string)h -(conversion)168 5541 y(BAD_F2C)523 b(402)190 b(bad)47 -b(float)f(to)h(formatted)f(string)g(conversion)1905 5809 -y Ff(40)p eop end -%%Page: 41 41 -TeXDict begin 41 40 bop 168 573 a Fc(BAD_INTKEY)379 b(403)190 -b(can't)46 b(interpret)g(keyword)f(value)i(as)g(integer)168 -686 y(BAD_LOGICALKEY)187 b(404)j(can't)46 b(interpret)g(keyword)f -(value)i(as)g(logical)168 799 y(BAD_FLOATKEY)283 b(405)190 -b(can't)46 b(interpret)g(keyword)f(value)i(as)g(float)168 -912 y(BAD_DOUBLEKEY)235 b(406)190 b(can't)46 b(interpret)g(keyword)f -(value)i(as)g(double)168 1024 y(BAD_C2I)523 b(407)190 -b(bad)47 b(formatted)e(string)h(to)h(int)g(conversion)168 -1137 y(BAD_C2F)523 b(408)190 b(bad)47 b(formatted)e(string)h(to)h -(float)g(conversion)168 1250 y(BAD_C2D)523 b(409)190 -b(bad)47 b(formatted)e(string)h(to)h(double)f(conversion)168 -1363 y(BAD_DATATYPE)283 b(410)190 b(illegal)46 b(datatype)f(code)i -(value)168 1476 y(BAD_DECIM)427 b(411)190 b(bad)47 b(number)f(of)h -(decimal)f(places)g(specified)168 1589 y(NUM_OVERFLOW)283 -b(412)190 b(overflow)45 b(during)i(datatype)e(conversion)168 -1702 y(DATA_COMPRESSION_ERR)137 b(413)95 b(error)46 b(compressing)f -(image)168 1815 y(DATA_DECOMPRESSION_ERR)c(414)95 b(error)46 -b(uncompressing)f(image)168 2041 y(BAD_DATE)475 b(420)190 -b(error)46 b(in)h(date)g(or)g(time)g(conversion)168 2267 -y(PARSE_SYNTAX_ERR)91 b(431)190 b(syntax)46 b(error)g(in)i(parser)e -(expression)168 2379 y(PARSE_BAD_TYPE)187 b(432)j(expression)45 -b(did)i(not)g(evaluate)e(to)i(desired)f(type)168 2492 -y(PARSE_LRG_VECTOR)91 b(433)190 b(vector)46 b(result)g(too)h(large)f -(to)i(return)e(in)h(array)168 2605 y(PARSE_NO_OUTPUT)139 -b(434)190 b(data)47 b(parser)f(failed)g(not)h(sent)f(an)h(out)g(column) -168 2718 y(PARSE_BAD_COL)235 b(435)190 b(bad)47 b(data)f(encounter)g -(while)g(parsing)g(column)168 2831 y(PARSE_BAD_OUTPUT)91 -b(436)190 b(Output)46 b(file)h(not)g(of)g(proper)f(type)168 -3057 y(ANGLE_TOO_BIG)235 b(501)190 b(celestial)45 b(angle)i(too)f -(large)h(for)g(projection)168 3170 y(BAD_WCS_VAL)331 -b(502)190 b(bad)47 b(celestial)e(coordinate)g(or)i(pixel)g(value)168 -3283 y(WCS_ERROR)427 b(503)190 b(error)46 b(in)h(celestial)f -(coordinate)f(calculation)168 3396 y(BAD_WCS_PROJ)283 -b(504)190 b(unsupported)45 b(type)h(of)h(celestial)f(projection)168 -3509 y(NO_WCS_KEY)379 b(505)190 b(celestial)45 b(coordinate)g(keywords) -h(not)h(found)168 3621 y(APPROX_WCS_KEY)187 b(506)j(approximate)45 -b(wcs)i(keyword)e(values)h(were)h(returned)1905 5809 -y Ff(41)p eop end -%%Trailer - -userdict /end-hook known{end-hook}if -%%EOF diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/quick.tex b/src/external/OpenGR/3rdparty/cfitsio/docs/quick.tex deleted file mode 100644 index 4934828eb..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/quick.tex +++ /dev/null @@ -1,2157 +0,0 @@ -\documentclass[11pt]{article} -\input{html.sty} -\htmladdtonavigation - {\begin{rawhtml} - FITSIO Home - \end{rawhtml}} - -\oddsidemargin=0.20in -\evensidemargin=0.20in -\textwidth=15.5truecm -\textheight=21.5truecm - -\title{CFITSIO Quick Start Guide} -\author{William Pence \thanks{HEASARC, NASA Goddard Space Flight Center}} - -\date{January 2003} - -\begin{document} - -\maketitle -\tableofcontents - -% =================================================================== -\section{Introduction} - -This document is intended to help you quickly start writing C programs -to read and write FITS files using the CFITSIO library. It covers the -most important CFITSIO routines that are needed to perform most types -of operations on FITS files. For more complete information about these -and all the other available routines in the library please refer to -the ``CFITSIO User's Reference Guide'', which is available from the -CFITSIO Web site at {\tt http://heasarc.gsfc.nasa.gov/fitsio}. - -For more general information about the FITS data format, refer to the -following web page: -http://heasarc.gsfc.nasa.gov/docs/heasarc/fits.html - -FITS stands for Flexible Image Transport System and is the standard -file format used to store most astronomical data files. There are 2 -basic types of FITS files: images and tables. FITS images often -contain a 2-dimensional array of pixels representing an image of a -piece of the sky, but FITS images can also contain 1-D arrays (i.e, -a spectrum or light curve), or 3-D arrays (a data cube), or -even higher dimensional arrays of data. An image may also have zero -dimensions, in which case it is referred to as a null or empty array. -The supported datatypes for the image arrays are 8, 16, and 32-bit -integers, and 32 and 64-bit floating point real numbers. Both signed -and unsigned integers are supported. - -FITS tables contain rows and columns of data, similar to a -spreadsheet. All the values in a particular column must have the same -datatype. A cell of a column is not restricted to a single number, and -instead can contain an array or vector of numbers. There are actually -2 subtypes of FITS tables: ASCII and binary. As the names imply, ASCII -tables store the data values in an ASCII representation whereas binary -tables store the data values in a more efficient machine-readable -binary format. Binary tables are generally more compact and support -more features (e.g., a wider range of datatypes, and vector columns) -than ASCII tables. - -A single FITS file many contain multiple images or tables. Each table -or image is called a Header-Data Unit, or HDU. The first HDU in a FITS -file must be an image (but it may have zero axes) and is called the -Primary Array. Any additional HDUs in the file (which are also -referred to as `extensions') may contain either an image or a table. - -Every HDU contains a header containing keyword records. Each keyword -record is 80 ASCII characters long and has the following format: - -\begin{verbatim} -KEYWORD = value / comment string -\end{verbatim} - -The keyword name can be up to 8 characters long (all uppercase). The -value can be either an integer or floating point number, a logical -value (T or F), or a character string enclosed in single quotes. Each -header begins with a series of required keywords to describe the -datatype and format of the following data unit, if any. Any number of -other optional keywords can be included in the header to provide other -descriptive information about the data. For the most part, the CFITSIO -routines automatically write the required FITS keywords for each HDU, -so you, the programmer, usually do not need to worry about them. - -% =================================================================== -\section{Installing and Using CFITSIO} - -First, you should download the CFITSIO software and the set of example -FITS utility programs from the web site at -http://heasarc.gsfc.nasa.gov/fitsio. The example programs illustrate -how to perform many common types of operations on FITS files using -CFITSIO. They are also useful when writing a new program because it is -often easier to take a copy of one of these utility programs as a -template and then modify it for your own purposes, rather than writing -the new program completely from scratch. - -To build the CFITSIO library on Unix platforms, `untar' the source code -distribution file and then execute the following commands in the -directory containing the source code: - -\begin{verbatim} -> ./configure [--prefix=/target/installation/path] -> make (or 'make shared') -> make install (this step is optional) -\end{verbatim} - -The optional -'prefix' argument to configure gives the path to the directory where -the CFITSIO library and include files should be installed via the later -'make install' command. For example, - -\begin{verbatim} -> ./configure --prefix=/usr1/local -\end{verbatim} - -will cause the 'make install' command to copy the CFITSIO libcfitsio file -to /usr1/local/lib and the necessary include files to /usr1/local/include -(assuming of course that the process has permission to write to these -directories). - -Pre-compiled versions of the CFITSIO DLL library are available for -PCs. On Macintosh machines, refer to the README.MacOS file for -instructions on building CFITSIO using CodeWarrior. - -Any programs that use CFITSIO must of course be linked with the CFITSIO -library when creating the executable file. The exact procedure for -linking a program depends on your software environment, but on Unix -platforms, the command line to compile and link a program will look -something like this: - -\begin{verbatim} -gcc -o myprog myprog.c -L. -lcfitsio -lm -lnsl -lsocket -\end{verbatim} - -You may not need to include all of the 'm', 'nsl', and 'socket' system -libraries on your particular machine. To find out what libraries are -required on your (Unix) system, type {\tt'make testprog'} and see what -libraries are then included on the resulting link line. - -\newpage -% =================================================================== -\section{Example Programs} - -Before describing the individual CFITSIO routines in detail, it is -instructive to first look at an actual program. The names of the -CFITSIO routines are fairly descriptive (they all begin with {\tt -fits\_}, so it should be reasonably clear what this program does: - -\begin{verbatim} ----------------------------------------------------------------- - #include - #include -1: #include "fitsio.h" - - int main(int argc, char *argv[]) - { -2: fitsfile *fptr; - char card[FLEN_CARD]; -3: int status = 0, nkeys, ii; /* MUST initialize status */ - -4: fits_open_file(&fptr, argv[1], READONLY, &status); - fits_get_hdrspace(fptr, &nkeys, NULL, &status); - - for (ii = 1; ii <= nkeys; ii++) { - fits_read_record(fptr, ii, card, &status); /* read keyword */ - printf("%s\n", card); - } - printf("END\n\n"); /* terminate listing with END */ - fits_close_file(fptr, &status); - - if (status) /* print any error messages */ -5: fits_report_error(stderr, status); - return(status); - } ----------------------------------------------------------------- -\end{verbatim} - -This program opens the specified FITS file and prints -out all the header keywords in the current HDU. -Some other points to notice about the program are: -\begin{enumerate} - -\item -The {\tt fitsio.h} header file must be included to define the -various routines and symbols used in CFITSIO. - -\item - -The {\tt fitsfile} parameter is the first argument in almost every -CFITSIO routine. It is a pointer to a structure (defined in {\tt -fitsio.h}) that stores information about the particular FITS file that -the routine will operate on. Memory for this structure is -automatically allocated when the file is first opened or created, and -is freed when the file is closed. - -\item -Almost every CFITSIO routine has a {\tt status} parameter as the last -argument. The status value is also usually returned as the value of the -function itself. Normally status = 0, and a positive status value -indicates an error of some sort. The status variable must always be -initialized to zero before use, because if status is greater than zero -on input then the CFITSIO routines will simply return without doing -anything. This `inherited status' feature, where each CFITSIO routine -inherits the status from the previous routine, makes it unnecessary to -check the status value after every single CFITSIO routine call. -Generally you should check the status after an especially important or -complicated routine has been called, or after a block of -closely related CFITSIO calls. This example program has taken this -feature to the extreme and only checks the status value at the -very end of the program. - -\item - -In this example program the file name to be opened is given as an -argument on the command line ({\tt arg[1]}). If the file contains more -than 1 HDU or extension, you can specify which particular HDU to be -opened by enclosing the name or number of the HDU in square brackets -following the root name of the file. For example, {\tt file.fts[0]} -opens the primary array, while {\tt file.fts[2]} will move to and open -the 2nd extension in the file, and {\tt file.fit[EVENTS]} will open the -extension that has a {\tt EXTNAME = 'EVENTS'} keyword in the header. -Note that on the Unix command line you must enclose the file name in -single or double quote characters if the name contains special -characters such as `[' or `]'. - -All of the CFITSIO routines which read or write header keywords, -image data, or table data operate only within the currently opened -HDU in the file. To read or write information in a different HDU you must -first explicitly move to that HDU (see the {\tt fits\_movabs\_hdu} and -{\tt fits\_movrel\_hdu} routines in section 4.3). - -\item - -The {\tt fits\_report\_error} routine provides a convenient way to print out -diagnostic messages about any error that may have occurred. - -\end{enumerate} - -A set of example FITS utility programs are available from the CFITSIO -web site at \newline -http://heasarc.gsfc.nasa.gov/docs/software/fitsio/cexamples.html. -These are real working programs which illustrate how to read, write, -and modify FITS files using the CFITSIO library. Most of these -programs are very short, containing only a few 10s of lines of -executable code or less, yet they perform quite useful operations on -FITS files. Running each program without any command line arguments -will produce a short description of how to use the program. -The currently available programs are: -\begin{quote} -fitscopy - copy a file -\newline -listhead - list header keywords -\newline -liststruc - show the structure of a FITS file. -\newline -modhead - write or modify a header keyword -\newline -imarith - add, subtract, multiply, or divide 2 images -\newline -imlist - list pixel values in an image -\newline -imstat - compute mean, min, and max pixel values in an image -\newline -tablist - display the contents of a FITS table -\newline -tabcalc - general table calculator -\end{quote} - -\newpage - -% =================================================================== -\section{CFITSIO Routines} - -This chapter describes the main CFITSIO routines that can be used to -perform the most common types of operations on FITS files. - -% =================================================================== -{\bf \subsection{Error Reporting}} - -\begin{verbatim} -void fits_report_error(FILE *stream, int status) -void fits_get_errstatus(int status, char *err_text) -float fits_get_version(float *version) -\end{verbatim} - -The first routine prints out information about any error that -has occurred. Whenever any CFITSIO routine encounters an error it -usually writes a message describing the nature of the error to an -internal error message stack and then returns with a positive integer -status value. Passing the error status value to this routine will -cause a generic description of the error and all the messages -from the internal CFITSIO error stack to be printed to the specified -stream. The {\tt stream} parameter is usually set equal to -{\tt "stdout"} or {\tt "stderr"}. - -The second routine simply returns a 30-character descriptive -error message corresponding to the input status value. - -The last routine returns the current CFITSIO library version number. - -% =================================================================== -{\bf \subsection{File Open/Close Routines}} - -\begin{verbatim} -int fits_open_file( fitsfile **fptr, char *filename, int mode, int *status) -int fits_open_data( fitsfile **fptr, char *filename, int mode, int *status) -int fits_open_table(fitsfile **fptr, char *filename, int mode, int *status) -int fits_open_image(fitsfile **fptr, char *filename, int mode, int *status) - -int fits_create_file(fitsfile **fptr, char *filename, int *status) -int fits_close_file(fitsfile *fptr, int *status) -\end{verbatim} - -These routines open or close a file. The first {\tt fitsfile} -parameter in these and nearly every other CFITSIO routine is a pointer -to a structure that CFITSIO uses to store relevant parameters about -each opened file. You should never directly read or write any -information in this structure. Memory for this structure is allocated -automatically when the file is opened or created, and is freed when the -file is closed. - -The {\tt mode} parameter in the {\tt fits\_open\_xxxx} set of routines -can be set to either {\tt READONLY} or {\tt READWRITE} to select the -type of file access that will be allowed. These symbolic constants are -defined in {\tt fitsio.h}. - -The {\tt fits\_open\_file} routine opens the file and positions the internal -file pointer to the beginning of the file, or to the specified -extension if an extension name or number is appended to the file name -(see the later section on ``CFITSIO File Names and Filters'' for a -description of the syntax). {\tt fits\_open\_data} behaves similarly except -that it will move to the first HDU containing significant data if a HDU -name or number to open is not explicitly specified as part of the -filename. It will move to the first IMAGE HDU with NAXIS greater than -0, or the first table that does not contain the strings `GTI' (a Good -Time Interval extension) or `OBSTABLE' in the EXTNAME keyword value. -The {\tt fits\_open\_table} and {\tt fits\_open\_image} routines are similar -except that they will move to the first significant table HDU or image -HDU, respectively if a HDU name of number is not specified as part of -the input file name. - -When opening an existing file, the {\tt filename} can include optional -arguments, enclosed in square brackets that specify filtering -operations that should be applied to the input file. For example, -\begin{verbatim} - myfile.fit[EVENTS][counts > 0] -\end{verbatim} -opens the table in the EVENTS extension and creates a virtual table by -selecting only those rows where the COUNTS column value is greater than -0. See section 5 for more examples of these powerful filtering -capabilities. - -In {\tt fits\_create\_file}, the {\tt filename} is simply the root name of -the file to be created. You can overwrite an existing file by -prefixing the name with a `!' character (on the Unix command line this -must be prefixed with a backslash, as in \verb+`\!file.fit'+). -If the file name ends with {\tt .gz} the file will be compressed -using the gzip algorithm. If the -filename is {\tt stdout} or {\tt "-"} (a single dash character) -then the output file will be piped to the stdout stream. You can -chain several tasks together by writing the output from the first task -to {\tt stdout} and then reading the input file in the 2nd task from -{\tt stdin} or {\tt "-"}. - - -% =================================================================== -{\bf \subsection{HDU-level Routines}} - -The routines listed in this section operate on Header-Data Units (HDUs) in a file. - -\begin{verbatim} -_______________________________________________________________ -int fits_get_num_hdus(fitsfile *fptr, int *hdunum, int *status) -int fits_get_hdu_num(fitsfile *fptr, int *hdunum) -\end{verbatim} - -The first routines returns the total number of HDUs in the FITS file, -and the second routine returns the position of the currently opened HDU in -the FITS file (starting with 1, not 0). - -\begin{verbatim} -__________________________________________________________________________ -int fits_movabs_hdu(fitsfile *fptr, int hdunum, int *hdutype, int *status) -int fits_movrel_hdu(fitsfile *fptr, int nmove, int *hdutype, int *status) -int fits_movnam_hdu(fitsfile *fptr, int hdutype, char *extname, - int extver, int *status) -\end{verbatim} - -These routines enable you to move to a different HDU in the file. -Most of the CFITSIO functions which read or write keywords or data -operate only on the currently opened HDU in the file. The first -routine moves to the specified absolute HDU number in the FITS -file (the first HDU = 1), whereas the second routine moves a relative -number of HDUs forward or backward from the currently open HDU. The -{\tt hdutype} parameter returns the type of the newly opened HDU, and will -be equal to one of these symbolic constant values: {\tt IMAGE\_HDU, -ASCII\_TBL, or BINARY\_TBL}. {\tt hdutype} may be set to NULL -if it is not needed. The third routine moves to the (first) HDU -that matches the input extension type, name, and version number, -as given by the {\tt XTENSION, EXTNAME} (or {\tt HDUNAME}) and {\tt EXTVER} keywords. -If the input value of {\tt extver} = 0, then the version number will -be ignored when looking for a matching HDU. - -\begin{verbatim} -_________________________________________________________________ -int fits_get_hdu_type(fitsfile *fptr, int *hdutype, int *status) -\end{verbatim} - -Get the type of the current HDU in the FITS file: {\tt IMAGE\_HDU, -ASCII\_TBL, or BINARY\_TBL}. - -\begin{verbatim} -____________________________________________________________________ -int fits_copy_hdu(fitsfile *infptr, fitsfile *outfptr, int morekeys, - int *status) -int fits_copy_file(fitsfile *infptr, fitsfile *outfptr, int previous, - int current, int following, > int *status) -\end{verbatim} - -The first routine copies the current HDU from the FITS file associated -with infptr and appends it to the end of the FITS file associated with -outfptr. Space may be reserved for {\tt morekeys} additional keywords -in the output header. The second routine copies any HDUs previous -to the current HDU, and/or the current HDU, and/or any HDUs following the -current HDU, depending on the value (True or False) of {\tt previous, -current}, and {\tt following}, respectively. For example, -\begin{verbatim} - fits_copy_file(infptr, outfptr, 0, 1, 1, &status); -\end{verbatim} -will copy the current HDU and any HDUs that follow it from the input -to the output file, but it will not copy any HDUs preceding the -current HDU. - - -\newpage -% =================================================================== -\subsection{Image I/O Routines} - -This section lists the more important CFITSIO routines which operate on -FITS images. - -\begin{verbatim} -_______________________________________________________________ -int fits_get_img_type(fitsfile *fptr, int *bitpix, int *status) -int fits_get_img_dim( fitsfile *fptr, int *naxis, int *status) -int fits_get_img_size(fitsfile *fptr, int maxdim, long *naxes, - int *status) -int fits_get_img_param(fitsfile *fptr, int maxdim, int *bitpix, - int *naxis, long *naxes, int *status) -\end{verbatim} - -Get information about the currently opened image HDU. The first routine -returns the datatype of the image as (defined by the {\tt BITPIX} -keyword), which can have the following symbolic constant values: -\begin{verbatim} - BYTE_IMG = 8 ( 8-bit byte pixels, 0 - 255) - SHORT_IMG = 16 (16 bit integer pixels) - LONG_IMG = 32 (32-bit integer pixels) - LONGLONG_IMG = 64 (64-bit integer pixels) - FLOAT_IMG = -32 (32-bit floating point pixels) - DOUBLE_IMG = -64 (64-bit floating point pixels) -\end{verbatim} - -The second and third routines return the number of dimensions in the -image (from the {\tt NAXIS} keyword), and the sizes of each dimension -(from the {\tt NAXIS1, NAXIS2}, etc. keywords). The last routine -simply combines the function of the first 3 routines. The input {\tt -maxdim} parameter in this routine gives the maximum number dimensions -that may be returned (i.e., the dimension of the {\tt naxes} -array) - -\begin{verbatim} -__________________________________________________________ -int fits_create_img(fitsfile *fptr, int bitpix, int naxis, - long *naxes, int *status) -\end{verbatim} - -Create an image HDU by writing the required keywords which define the -structure of the image. The 2nd through 4th parameters specified the -datatype, the number of dimensions, and the sizes of the dimensions. -The allowed values of the {\tt bitpix} parameter are listed above in -the description of the {\tt fits\_get\_img\_type} routine. If the FITS -file pointed to by {\tt fptr} is empty (previously created with -{\tt fits\_create\_file}) then this routine creates a primary array in -the file, otherwise a new IMAGE extension is appended to end of the -file following the other HDUs in the file. - -\begin{verbatim} -______________________________________________________________ -int fits_write_pix(fitsfile *fptr, int datatype, long *fpixel, - long nelements, void *array, int *status); - -int fits_write_pixnull(fitsfile *fptr, int datatype, long *fpixel, - long nelements, void *array, void *nulval, int *status); - -int fits_read_pix(fitsfile *fptr, int datatype, long *fpixel, - long nelements, void *nulval, void *array, - int *anynul, int *status) -\end{verbatim} - -Read or write all or part of the FITS image. There are 2 different -'write' pixel routines: The first simply writes the input array of pixels -to the FITS file. The second is similar, except that it substitutes -the appropriate null pixel value in the FITS file for any pixels -which have a value equal to {\tt *nulval} (note that this parameter -gives the address of the null pixel value, not the value itself). -Similarly, when reading an image, CFITSIO will substitute the value -given by {\tt nulval} for any undefined pixels in the image, unless -{\tt nulval = NULL}, in which case no checks will be made for undefined -pixels when reading the FITS image. - -The {\tt fpixel} parameter in these routines is an array which gives -the coordinate in each dimension of the first pixel to be read or -written, and {\tt nelements} is the total number of pixels to read or -write. {\tt array} is the address of an array which either contains -the pixel values to be written, or will hold the values of the pixels -that are read. When reading, {\tt array} must have been allocated -large enough to hold all the returned pixel values. These routines -starts at the {\tt fpixel} location and then read or write the {\tt -nelements} pixels, continuing on successive rows of the image if -necessary. For example, to write an entire 2D image, set {\tt -fpixel[0] = fpixel[1] = 1}, and {\tt nelements = NAXIS1 * NAXIS2}. Or -to read just the 10th row of the image, set {\tt fpixel[0] = 1, -fpixel[1] = 10}, and {\tt nelements = NAXIS1}. The {\tt datatype} -parameter specifies the datatype of the C {\tt array} in the program, -which need not be the same as the datatype of the FITS image itself. -If the datatypes differ then CFITSIO will convert the data as it is -read or written. The following symbolic constants are allowed for the -value of {\tt datatype}: -\begin{verbatim} - TBYTE unsigned char - TSBYTE signed char - TSHORT signed short - TUSHORT unsigned short - TINT signed int - TUINT unsigned int - TLONG signed long - TLONGLONG signed 8-byte integer - TULONG unsigned long - TFLOAT float - TDOUBLE double -\end{verbatim} - - -\begin{verbatim} -_________________________________________________________________ -int fits_write_subset(fitsfile *fptr, int datatype, long *fpixel, - long *lpixel, DTYPE *array, > int *status) - -int fits_read_subset(fitsfile *fptr, int datatype, long *fpixel, - long *lpixel, long *inc, void *nulval, void *array, - int *anynul, int *status) -\end{verbatim} - -Read or write a rectangular section of the FITS image. These are very -similar to {\tt fits\_write\_pix} and {\tt fits\_read\_pix} except that -you specify the last pixel coordinate (the upper right corner of the -section) instead of the number of pixels to be read. The read routine -also has an {\tt inc} parameter which can be used to read only every -{\tt inc-th} pixel along each dimension of the image. Normally {\tt -inc[0] = inc[1] = 1} to read every pixel in a 2D image. To read every -other pixel in the entire 2D image, set -\begin{verbatim} - fpixel[0] = fpixel[1] = 1 - lpixel[0] = {NAXIS1} - lpixel[1] = {NAXIS2} - inc[0] = inc[1] = 2 -\end{verbatim} - -Or, to read the 8th row of a 2D image, set -\begin{verbatim} - fpixel[0] = 1 - fpixel[1] = 8 - lpixel[0] = {NAXIS1} - lpixel[1] = 8 - inc[0] = inc[1] = 1 -\end{verbatim} - -\newpage -% =================================================================== -\subsection{Table I/O Routines} - -This section lists the most important CFITSIO routines which operate on -FITS tables. - -\begin{verbatim} -__________________________________________________________________________ -int fits_create_tbl(fitsfile *fptr, int tbltype, long nrows, int tfields, - char *ttype[],char *tform[], char *tunit[], char *extname, int *status) -\end{verbatim} - -Create a new table extension by writing the required keywords that -define the table structure. The required null primary array -will be created first if the file is initially completely empty. {\tt -tbltype} defines the type of table and can have values of {\tt -ASCII\_TBL or BINARY\_TBL}. Binary tables are generally preferred -because they are more efficient and support a greater range of column -datatypes than ASCII tables. - -The {\tt nrows} parameter gives the initial number of empty rows to be -allocated for the table; this should normally be set to 0. The {\tt tfields} -parameter gives the number of columns in the table (maximum = 999). -The {\tt -ttype, tform}, and {\tt tunit} parameters give the name, datatype, and -physical units of each column, and {\tt extname} gives the name for the -table (the value of the {\tt EXTNAME} keyword). -The FITS Standard recommends that only -letters, digits, and the underscore character be used in column names -with no embedded spaces. It is recommended that all the column names -in a given table be unique within the first 8 characters. - -The following table -shows the TFORM column format values that are allowed in ASCII tables -and in binary tables: -\begin{verbatim} - ASCII Table Column Format Codes - ------------------------------- - (w = column width, d = no. of decimal places to display) - Aw - character string - Iw - integer - Fw.d - fixed floating point - Ew.d - exponential floating point - Dw.d - exponential floating point - - Binary Table Column Format Codes - -------------------------------- - (r = vector length, default = 1) - rA - character string - rAw - array of strings, each of length w - rL - logical - rX - bit - rB - unsigned byte - rS - signed byte ** - rI - signed 16-bit integer - rU - unsigned 16-bit integer ** - rJ - signed 32-bit integer - rV - unsigned 32-bit integer ** - rK - signed 64-bit integer - rE - 32-bit floating point - rD - 64-bit floating point - rC - 32-bit complex pair - rM - 64-bit complex pair - - ** The S, U and V format codes are not actual legal TFORMn values. - CFITSIO substitutes the somewhat more complicated set of - keywords that are used to represent unsigned integers or - signed bytes. - -\end{verbatim} - -The {\tt tunit} and {\tt extname} parameters are optional and -may be set to NULL -if they are not needed. - -Note that it may be easier to create a new table by copying the -header from another existing table with {\tt fits\_copy\_header} rather -than calling this routine. - -\begin{verbatim} -_______________________________________________________________ -int fits_get_num_rows(fitsfile *fptr, long *nrows, int *status) -int fits_get_num_cols(fitsfile *fptr, int *ncols, int *status) -\end{verbatim} - -Get the number of rows or columns in the current FITS table. The -number of rows is given by the {\tt NAXIS2} keyword and the number of columns -is given by the {\tt TFIELDS} keyword in the header of the table. - -\begin{verbatim} -_______________________________________________________________ -int fits_get_colnum(fitsfile *fptr, int casesen, char *template, - int *colnum, int *status) -int fits_get_colname(fitsfile *fptr, int casesen, char *template, - char *colname, int *colnum, int *status) -\end{verbatim} - -Get the column number (starting with 1, not 0) of the column whose -name matches the specified template name. The only difference in -these 2 routines is that the 2nd one also returns the name of the -column that matched the template string. - -Normally, {\tt casesen} should -be set to {\tt CASEINSEN}, but it may be set to {\tt CASESEN} to force -the name matching to be case-sensitive. - -The input {\tt template} string gives the name of the desired column and -may include wildcard characters: a `*' matches any sequence of -characters (including zero characters), `?' matches any single -character, and `\#' matches any consecutive string of decimal digits -(0-9). If more than one column name in the table matches the template -string, then the first match is returned and the status value will be -set to {\tt COL\_NOT\_UNIQUE} as a warning that a unique match was not -found. To find the next column that matches the template, call this -routine again leaving the input status value equal to {\tt -COL\_NOT\_UNIQUE}. Repeat this process until {\tt status = -COL\_NOT\_FOUND} is returned. - -\begin{verbatim} -_______________________________________________________________ -int fits_get_coltype(fitsfile *fptr, int colnum, int *typecode, - long *repeat, long *width, int *status) - -int fits_get_eqcoltype(fitsfile *fptr, int colnum, int *typecode, - long *repeat, long *width, int *status) -\end{verbatim} - -Return the datatype, vector repeat count, and the width in bytes of a -single column element for column number {\tt colnum}. Allowed values -for the returned datatype in ASCII tables are: {\tt TSTRING, TSHORT, -TLONG, TFLOAT, and TDOUBLE}. Binary tables support these additional -types: {\tt TLOGICAL, TBIT, TBYTE, TINT32BIT, TCOMPLEX and TDBLCOMPLEX}. The -negative of the datatype code value is returned if it is a variable -length array column. - -These 2 routines are similar, except that in the case of scaled -integer columns the 2nd routine, fit\_get\_eqcoltype, returns the -'equivalent' datatype that is needed to store the scaled values, which -is not necessarily the same as the physical datatype of the unscaled values -as stored in the FITS table. For example if a '1I' column in a binary -table has TSCALn = 1 and TZEROn = 32768, then this column effectively -contains unsigned short integer values, and thus the returned value of -typecode will be TUSHORT, not TSHORT. Or, if TSCALn or TZEROn are not -integers, then the equivalent datatype will be returned as TFLOAT or -TDOUBLE, depending on the size of the integer. - -The repeat count is always 1 in ASCII tables. -The 'repeat' parameter returns the vector repeat count on the binary -table TFORMn keyword value. (ASCII table columns always have repeat -= 1). The 'width' parameter returns the width in bytes of a single -column element (e.g., a '10D' binary table column will have width = -8, an ASCII table 'F12.2' column will have width = 12, and a binary -table'60A' character string column will have width = 60); Note that -this routine supports the local convention for specifying arrays of -fixed length strings within a binary table character column using -the syntax TFORM = 'rAw' where 'r' is the total number of -characters (= the width of the column) and 'w' is the width of a -unit string within the column. Thus if the column has TFORM = -'60A12' then this means that each row of the table contains -5 12-character substrings within the 60-character field, and thus -in this case this routine will return typecode = TSTRING, repeat = -60, and width = 12. The number of substings in any binary table -character string field can be calculated by (repeat/width). -A null pointer may be given for any of the output parameters that - are not needed. - -\begin{verbatim} -____________________________________________________________________________ -int fits_insert_rows(fitsfile *fptr, long firstrow, long nrows, int *status) -int fits_delete_rows(fitsfile *fptr, long firstrow, long nrows, int *status) -int fits_delete_rowrange(fitsfile *fptr, char *rangelist, int *status) -int fits_delete_rowlist(fitsfile *fptr, long *rowlist, long nrows, int *stat) -\end{verbatim} - -Insert or delete rows in a table. The blank rows are inserted -immediately following row {\tt frow}. Set {\tt frow} = 0 to insert rows -at the beginning of the table. The first 'delete' routine deletes {\tt -nrows} rows beginning with row {\tt firstrow}. The 2nd delete routine -takes an input string listing the rows or row ranges to be deleted -(e.g., '2,4-7, 9-12'). The last delete routine takes an input long -integer array that specifies each individual row to be deleted. The -row lists must be sorted in ascending order. All these routines update -the value of the {\tt NAXIS2} keyword to reflect the new number of rows -in the table. - -\begin{verbatim} -_________________________________________________________________________ -int fits_insert_col(fitsfile *fptr, int colnum, char *ttype, char *tform, - int *status) -int fits_insert_cols(fitsfile *fptr, int colnum, int ncols, char **ttype, - char **tform, int *status) - -int fits_delete_col(fitsfile *fptr, int colnum, int *status) -\end{verbatim} - -Insert or delete columns in a table. {\tt colnum} gives the position -of the column to be inserted or deleted (where the first column of the -table is at position 1). {\tt ttype} and {\tt tform} give the column -name and column format, where the allowed format codes are listed above -in the description of the {\tt fits\_create\_table} routine. The 2nd -'insert' routine inserts multiple columns, where {\tt ncols} is the -number of columns to insert, and {\tt ttype} and {\tt tform} are -arrays of string pointers in this case. - -\begin{verbatim} -____________________________________________________________________ -int fits_copy_col(fitsfile *infptr, fitsfile *outfptr, int incolnum, - int outcolnum, int create_col, int *status); -\end{verbatim} - -Copy a column from one table HDU to another. If {\tt create\_col} = TRUE (i.e., not equal to zero), -then a new column will be inserted in the output table at position -{\tt outcolumn}, otherwise the values in the existing output column will be -overwritten. - -\begin{verbatim} -__________________________________________________________________________ -int fits_write_col(fitsfile *fptr, int datatype, int colnum, long firstrow, - long firstelem, long nelements, void *array, int *status) -int fits_write_colnull(fitsfile *fptr, int datatype, int colnum, - long firstrow, long firstelem, long nelements, - void *array, void *nulval, int *status) -int fits_write_col_null(fitsfile *fptr, int colnum, long firstrow, - long firstelem, long nelements, int *status) - -int fits_read_col(fitsfile *fptr, int datatype, int colnum, long firstrow, - long firstelem, long nelements, void *nulval, void *array, - int *anynul, int *status) - -\end{verbatim} - -Write or read elements in column number {\tt colnum}, starting with row -{\tt firstsrow} and element {\tt firstelem} (if it is a vector -column). {\tt firstelem} is ignored if it is a scalar column. The {\tt -nelements} number of elements are read or written continuing on -successive rows of the table if necessary. {\tt array} is the address -of an array which either contains the values to be written, or will -hold the returned values that are read. When reading, {\tt array} must -have been allocated large enough to hold all the returned values. - -There are 3 different 'write' column routines: The first simply writes -the input array into the column. The second is similar, except that it -substitutes the appropriate null pixel value in the column for any -input array values which are equal to {\tt *nulval} (note that this -parameter gives the address of the null pixel value, not the value -itself). The third write routine sets the specified table elements -to a null value. New rows will be automatical added to the table -if the write operation extends beyond the current size of the table. - -When reading a column, CFITSIO will substitute the value given by {\tt -nulval} for any undefined elements in the FITS column, unless {\tt -nulval} or {\tt *nulval = NULL}, in which case no checks will be made -for undefined values when reading the column. - -{\tt datatype} specifies the datatype of the C {\tt array} in the program, -which need not be the same as the intrinsic datatype of the column in -the FITS table. The following symbolic constants are allowed for the -value of {\tt datatype}: - -\begin{verbatim} - TSTRING array of character string pointers - TBYTE unsigned char - TSHORT signed short - TUSHORT unsigned short - TINT signed int - TUINT unsigned int - TLONG signed long - TLONGLONG signed 8-byte integer - TULONG unsigned long - TFLOAT float - TDOUBLE double -\end{verbatim} - -Note that {\tt TSTRING} corresponds to the C {\tt -char**} datatype, i.e., a pointer to an array of pointers to an array -of characters. - -Any column, regardless of it's intrinsic datatype, may be read as a -{\tt TSTRING} character string. The display format of the returned -strings will be determined by the {\tt TDISPn} keyword, if it exists, -otherwise a default format will be used depending on the datatype of -the column. The {\tt tablist} example utility program (available from -the CFITSIO web site) uses this feature to display all the values in a -FITS table. - -\begin{verbatim} -_____________________________________________________________________ -int fits_select_rows(fitsfile *infptr, fitsfile *outfptr, char *expr, - int *status) -int fits_calculator(fitsfile *infptr, char *expr, fitsfile *outfptr, - char *colname, char *tform, int *status) -\end{verbatim} - -These are 2 of the most powerful routines in the CFITSIO library. (See -the full CFITSIO Reference Guide for a description of several related -routines). These routines can perform complicated transformations on -tables based on an input arithmetic expression which is evaluated for -each row of the table. The first routine will select or copy rows of -the table for which the expression evaluates to TRUE (i.e., not equal -to zero). The second routine writes the value of the expression to a -column in the output table. Rather than supplying the expression -directly to these routines, the expression may also be written to a -text file (continued over multiple lines if necessary) and the name of -the file, prepended with a '@' character, may be supplied as the value -of the 'expr' parameter (e.g. '@filename.txt'). - -The arithmetic expression may be a function of any column or keyword in -the input table as shown in these examples: - -\begin{verbatim} -Row Selection Expressions: - counts > 0 uses COUNTS column value - sqrt( X**2 + Y**2) < 10. uses X and Y column values - (X > 10) || (X < -10) && (Y == 0) used 'or' and 'and' operators - gtifilter() filter on Good Time Intervals - regfilter("myregion.reg") filter using a region file - @select.txt reads expression from a text file -Calculator Expressions: - #row % 10 modulus of the row number - counts/#exposure Fn of COUNTS column and EXPOSURE keyword - dec < 85 ? cos(dec * #deg) : 0 Conditional expression: evaluates to - cos(dec) if dec < 85, else 0 - (count{-1}+count+count{+1})/3. running mean of the count values in the - previous, current, and next rows - max(0, min(X, 1000)) returns a value between 0 - 1000 - @calc.txt reads expression from a text file -\end{verbatim} - -Most standard mathematical operators and functions are supported. If -the expression includes the name of a column, than the value in the -current row of the table will be used when evaluating the expression on -each row. An offset to an adjacent row can be specified by including -the offset value in curly brackets after the column name as shown in -one of the examples. Keyword values can be included in the expression -by preceding the keyword name with a `\#' sign. See Section 5 of this -document for more discussion of the expression syntax. - -{\tt gtifilter} is a special function which tests whether the {\tt -TIME} column value in the input table falls within one or more Good -Time Intervals. By default, this function looks for a 'GTI' extension -in the same file as the input table. The 'GTI' table contains {\tt START} -and {\tt STOP} columns which define the range of -each good time interval. See section 5.4.3 for more details. - -{\tt regfilter} is another special function which selects rows based on -whether the spatial position associated with each row is located within -in a specified region of the sky. By default, the {\tt X} and {\tt Y} -columns in the input table are assumed to give the position of each row. -The spatial region is defined in an ASCII text file whose name is given -as the argument to the {\tt regfilter} function. See section 5.4.4 for -more details. - -The {\tt infptr} and {\tt outfptr} parameters in these routines may -point to the same table or to different tables. In {\tt -fits\_select\_rows}, if the input and output tables are the same then -the rows that do not satisfy the selection expression will be deleted -from the table. Otherwise, if the output table is different from the -input table then the selected rows will be copied from the input table -to the output table. - -The output column in {\tt fits\_calculator} may or may not already -exist. If it exists then the calculated values will be written to that -column, overwriting the existing values. If the column doesn't exist -then the new column will be appended to the output table. The {\tt tform} -parameter can be used to specify the datatype of the new column (e.g., -the {\tt TFORM} keyword value as in {\tt '1E', or '1J'}). If {\tt -tform} = NULL then a default datatype will be used, depending on the -expression. - -\begin{verbatim} -_____________________________________________________________________ -int fits_read_tblbytes(fitsfile *fptr, long firstrow, long firstchar, - long nchars, unsigned char *array, int *status) -int fits_write_tblbytes (fitsfile *fptr, long firstrow, long firstchar, - long nchars, unsigned char *array, int *status) -\end{verbatim} - -These 2 routines provide low-level access to tables and are mainly -useful as an efficient way to copy rows of a table from one file to -another. These routines simply read or write the specified number of -consecutive characters (bytes) in a table, without regard for column -boundaries. For example, to read or write the first row of a table, -set {\tt firstrow = 1, firstchar = 1}, and {\tt nchars = NAXIS1} where -the length of a row is given by the value of the {\tt NAXIS1} header -keyword. When reading a table, {\tt array} must have been declared at -least {\tt nchars} bytes long to hold the returned string of bytes. - -\newpage -% =================================================================== -\subsection{Header Keyword I/O Routines} -\nopagebreak -The following routines read and write header keywords in the current HDU. -\nopagebreak - -\begin{verbatim} -____________________________________________________________________ -int fits_get_hdrspace(fitsfile *fptr, int *keysexist, int *morekeys, - int *status) -\end{verbatim} -\nopagebreak -Return the number of existing keywords (not counting the mandatory END -keyword) and the amount of empty space currently available for more -keywords. The {\tt morekeys} parameter may be set to NULL if it's value is -not needed. - -\begin{verbatim} -___________________________________________________________________________ -int fits_read_record(fitsfile *fptr, int keynum, char *record, int *status) -int fits_read_card(fitsfile *fptr, char *keyname, char *record, int *status) -int fits_read_key(fitsfile *fptr, int datatype, char *keyname, - void *value, char *comment, int *status) - -int fits_find_nextkey(fitsfile *fptr, char **inclist, int ninc, - char **exclist, int nexc, char *card, int *status) - -int fits_read_key_unit(fitsfile *fptr, char *keyname, char *unit, - int *status) -\end{verbatim} - -These routines all read a header record in the current HDU. The first -routine reads keyword number {\tt keynum} (where the first keyword is -at position 1). This routine is most commonly used when sequentially -reading every record in the header from beginning to end. The 2nd and -3rd routines read the named keyword and return either the whole -record, or the keyword value and comment string. In each case any -non-significant trailing blank characters in the strings are truncated. - -Wild card characters (*, ?, and \#) may be used when specifying the name -of the keyword to be read, in which case the first matching keyword is -returned. - -The {\tt datatype} parameter specifies the C datatype of the returned -keyword value and can have one of the following symbolic constant -values: {\tt TSTRING, TLOGICAL} (== int), {\tt TBYTE}, {\tt TSHORT}, -{\tt TUSHORT}, {\tt TINT}, {\tt TUINT}, {\tt TLONG}, {\tt TULONG}, {\tt -TFLOAT}, {\tt TDOUBLE}, {\tt TCOMPLEX}, and {\tt TDBLCOMPLEX}. Data -type conversion will be performed for numeric values if the intrinsic -FITS keyword value does not have the same datatype. The {\tt comment} -parameter may be set equal to NULL if the comment string is not -needed. - -The 4th routine provides an easy way to find all the keywords in the -header that match one of the name templates in {\tt inclist} and do not -match any of the name templates in {\tt exclist}. {\tt ninc} and {\tt -nexc} are the number of template strings in {\tt inclist} and {\tt -exclist}, respectively. Wild cards (*, ?, and \#) may be used in the -templates to match multiple keywords. Each time this routine is called -it returns the next matching 80-byte keyword record. It returns status -= {\tt KEY\_NO\_EXIST} if there are no more matches. - -The 5th routine returns the keyword value units string, if any. -The units are recorded at the beginning of the keyword comment field -enclosed in square brackets. -\begin{verbatim} -_______________________________________________________________ -int fits_write_key(fitsfile *fptr, int datatype, char *keyname, - void *value, char *comment, int *status) -int fits_update_key(fitsfile *fptr, int datatype, char *keyname, - void *value, char *comment, int *status) -int fits_write_record(fitsfile *fptr, char *card, int *status) - -int fits_modify_comment(fitsfile *fptr, char *keyname, char *comment, - int *status) -int fits_write_key_unit(fitsfile *fptr, char *keyname, char *unit, - int *status) - -\end{verbatim} - -Write or modify a keyword in the header of the current HDU. The -first routine appends the new keyword to the end of the header, whereas -the second routine will update the value and comment fields of the -keyword if it already exists, otherwise it behaves like the first -routine and appends the new keyword. Note that {\tt value} gives the -address to the value and not the value itself. The {\tt datatype} -parameter specifies the C datatype of the keyword value and may have -any of the values listed in the description of the keyword reading -routines, above. A NULL may be entered for the comment parameter, in -which case the keyword comment field will be unmodified or left -blank. - -The third routine is more primitive and simply writes the 80-character -{\tt card} record to the header. It is the programmer's responsibility -in this case to ensure that the record conforms to all the FITS format -requirements for a header record. - -The fourth routine modifies the comment string in an existing keyword, -and the last routine writes or updates the keyword units string for an -existing keyword. (The units are recorded at the beginning of the -keyword comment field enclosed in square brackets). - -\begin{verbatim} -___________________________________________________________________ -int fits_write_comment(fitsfile *fptr, char *comment, int *status) -int fits_write_history(fitsfile *fptr, char *history, int *status) -int fits_write_date(fitsfile *fptr, int *status) -\end{verbatim} - -Write a {\tt COMMENT, HISTORY}, or {\tt DATE} keyword to the current -header. The {\tt COMMENT} keyword is typically used to write a comment -about the file or the data. The {\tt HISTORY} keyword is typically -used to provide information about the history of the processing -procedures that have been applied to the data. The {\tt comment} or -{\tt history} string will be continued over multiple keywords if it is -more than 70 characters long. - -The {\tt DATE} keyword is used to record the date and time that the -FITS file was created. Note that this file creation date is usually -different from the date of the observation which obtained the data in -the FITS file. The {\tt DATE} keyword value is a character string in -'yyyy-mm-ddThh:mm:ss' format. If a {\tt DATE} keyword already exists in -the header, then this routine will update the value with the current -system date. - -\begin{verbatim} -___________________________________________________________________ -int fits_delete_record(fitsfile *fptr, int keynum, int *status) -int fits_delete_key(fitsfile *fptr, char *keyname, int *status) -\end{verbatim} - -Delete a keyword record. The first routine deletes a keyword at a -specified position (the first keyword is at position 1, not 0), -whereas the second routine deletes the named keyword. - -\begin{verbatim} -_______________________________________________________________________ -int fits_copy_header(fitsfile *infptr, fitsfile *outfptr, int *status) -\end{verbatim} - -Copy all the header keywords from the current HDU associated with -infptr to the current HDU associated with outfptr. If the current -output HDU is not empty, then a new HDU will be appended to the output -file. The output HDU will then have the identical structure as the -input HDU, but will contain no data. - -\newpage -% =================================================================== -\subsection{Utility Routines} - -This section lists the most important CFITSIO general utility routines. - -\begin{verbatim} -___________________________________________________________________ -int fits_write_chksum( fitsfile *fptr, int *status) -int fits_verify_chksum(fitsfile *fptr, int *dataok, int *hduok, int *status) -\end{verbatim} - -These routines compute or validate the checksums for the currenrt -HDU. The {\tt DATASUM} keyword is used to store the numerical value of -the 32-bit, 1's complement checksum for the data unit alone. The {\tt -CHECKSUM} keyword is used to store the ASCII encoded COMPLEMENT of the -checksum for the entire HDU. Storing the complement, rather than the -actual checksum, forces the checksum for the whole HDU to equal zero. -If the file has been modified since the checksums were computed, then -the HDU checksum will usually not equal zero. - -The returned {\tt dataok} and {\tt hduok} parameters will have a value -= 1 if the data or HDU is verified correctly, a value = 0 if the -{\tt DATASUM} or {\tt CHECKSUM} keyword is not present, or value = -1 if the -computed checksum is not correct. - - -\begin{verbatim} -___________________________________________________________________ -int fits_parse_value(char *card, char *value, char *comment, int *status) -int fits_get_keytype(char *value, char *dtype, int *status) -int fits_get_keyclass(char *card) -int fits_parse_template(char *template, char *card, int *keytype, int *status) - -\end{verbatim} - -{\tt fits\_parse\_value} parses the input 80-chararacter header keyword record, returning -the value (as a literal character string) and comment strings. If the -keyword has no value (columns 9-10 not equal to '= '), then a null -value string is returned and the comment string is set equal to column -9 - 80 of the input string. - -{\tt fits\_get\_keytype} parses the keyword value string to determine its -datatype. {\tt dtype} returns with a value of 'C', 'L', 'I', 'F' or -'X', for character string, logical, integer, floating point, or -complex, respectively. - -{\tt fits\_get\_keyclass} returns a classification code that indicates -the classification type of the input keyword record (e.g., a required -structural keyword, a TDIM keyword, a WCS keyword, a comment keyword, -etc. See the CFITSIO Reference Guide for a list of the different -classification codes. - -{\tt fits\_parse\_template} takes an input free format keyword template -string and returns a formatted 80*char record that satisfies all the -FITS requirements for a header keyword record. The template should -generally contain 3 tokens: the keyword name, the keyword value, and -the keyword comment string. The returned {\tt keytype} parameter -indicates whether the keyword is a COMMENT keyword or not. See the -CFITSIO Reference Guide for more details. - -\newpage -% =================================================================== -\section{CFITSIO File Names and Filters} - -\subsection{Creating New Files} - -When creating a new output file on magnetic disk with {\tt -fits\_create\_file} the following features are supported. -\begin{itemize} -\item Overwriting, or 'Clobbering' an Existing File - -If the filename is preceded by an exclamation -point (!) then if that file already exists it will be deleted prior to -creating the new FITS file. Otherwise if there is an existing file -with the same name, CFITSIO will not overwrite the existing file and -will return an error status code. Note that the exclamation point is -a special UNIX character, so if it is used on the command line rather -than entered at a task prompt, it must be preceded by a backslash to -force the UNIX shell to pass it verbatim to the application program. - -\item Compressed Output Files - -If the output disk file name ends with the suffix '.gz', then CFITSIO -will compress the file using the gzip compression algorithm before -writing it to disk. This can reduce the amount of disk space used by -the file. Note that this feature requires that the uncompressed file -be constructed in memory before it is compressed and written to disk, -so it can fail if there is insufficient available memory. - -One can also specify that any images written to the output file should -be compressed using the newly developed `tile-compression' algorithm by -appending `[compress]' to the name of the disk file (as in -{\tt myfile.fits[compress]}). Refer to the CFITSIO User's Reference Guide -for more information about this new image compression format. - -\item Using a Template to Create a New FITS File - -The structure of any new FITS file that is to be created may be defined -in an ASCII template file. If the name of the template file is -appended to the name of the FITS file itself, enclosed in parenthesis -(e.g., {\tt 'newfile.fits(template.txt)'}) then CFITSIO will create a -FITS file with that structure before opening it for the application to -use. The template file basically defines the dimensions and data type -of the primary array and any IMAGE extensions, and the names and data -types of the columns in any ASCII or binary table extensions. The -template file can also be used to define any optional keywords that -should be written in any of the HDU headers. The image pixel values -and table entry values are all initialized to zero. The application -program can then write actual data into the HDUs. See the CFITSIO -Reference Guide for for a complete description of the template file -syntax. - -\item Creating a Temporary Scratch File in Memory - -It is sometimes useful to create a temporary output file when testing -an application program. If the name of the file to be created is -specified as {\tt mem:} then CFITSIO will create the file in -memory where it will persist only until the program closes the file. -Use of this {\tt mem:} output file usually enables the program to run -faster, and of course the output file does not use up any disk space. - - -\end{itemize} - -\subsection{Opening Existing Files} - -When opening a file with {\tt fits\_open\_file}, CFITSIO can read a -variety of different input file formats and is not restricted to only -reading FITS format files from magnetic disk. The following types of -input files are all supported: - -\begin{itemize} -\item FITS files compressed with {\tt zip, gzip} or {\tt compress} - -If CFITSIO cannot find the specified file to open it will automatically -look for a file with the same rootname but with a {\tt .gz, .zip}, or -{\tt .Z} extension. If it finds such a compressed file, it will -allocate a block of memory and uncompress the file into that memory -space. The application program will then transparently open this -virtual FITS file in memory. Compressed -files can only be opened with 'readonly', not 'readwrite' file access. - -\item FITS files on the internet, using {\tt ftp} or {\tt http} URLs - -Simply provide the full URL as the name of the file that you want to -open. For example,\linebreak {\tt -ftp://legacy.gsfc.nasa.gov/software/fitsio/c/testprog.std}\linebreak -will open the CFITSIO test FITS file that is located on the {\tt -legacy} machine. These files can only be opened with 'readonly' file -access. - -\item FITS files on {\tt stdin} or {\tt stdout} file streams - -If the name of the file to be opened is {\tt 'stdin'} or {\tt '-'} (a -single dash character) then CFITSIO will read the file from the -standard input stream. Similarly, if the output file name is {\tt -'stdout'} or {\tt '-'}, then the file will be written to the standard -output stream. In addition, if the output filename is {\tt -'stdout.gz'} or {\tt '-.gz'} then it will be gzip compressed before -being written to stdout. This mechanism can be used to pipe FITS files -from one task to another without having to write an intermediary FITS -file on magnetic disk. - -\item FITS files that exist only in memory, or shared memory. - -In some applications, such as real time data acquisition, you may want -to have one process write a FITS file into a certain section of -computer memory, and then be able to open that file in memory with -another process. There is a specialized CFITSIO open routine called -{\tt fits\_open\_memfile} that can be used for this purpose. See the -``CFITSIO User's Reference Guide'' for more details. - -\item IRAF format images (with {\tt .imh} file extensions) - -CFITSIO supports reading IRAF format images by converting them on the -fly into FITS images in memory. The application program then reads -this virtual FITS format image in memory. There is currently no -support for writing IRAF format images, or for reading or writing IRAF -tables. - -\item Image arrays in raw binary format - -If the input file is a raw binary data array, then CFITSIO will convert -it on the fly into a virtual FITS image with the basic set of required -header keywords before it is opened by the application program. In -this case the data type and dimensions of the image must be specified -in square brackets following the filename (e.g. {\tt -rawfile.dat[ib512,512]}). The first character inside the brackets -defines the datatype of the array: - -\begin{verbatim} - b 8-bit unsigned byte - i 16-bit signed integer - u 16-bit unsigned integer - j 32-bit signed integer - r or f 32-bit floating point - d 64-bit floating point -\end{verbatim} -An optional second character specifies the byte order of the array -values: b or B indicates big endian (as in FITS files and the native -format of SUN UNIX workstations and Mac PCs) and l or L indicates -little endian (native format of DEC OSF workstations and IBM PCs). If -this character is omitted then the array is assumed to have the native -byte order of the local machine. These datatype characters are then -followed by a series of one or more integer values separated by commas -which define the size of each dimension of the raw array. Arrays with -up to 5 dimensions are currently supported. - -Finally, a byte offset to the position of the first pixel in the data -file may be specified by separating it with a ':' from the last -dimension value. If omitted, it is assumed that the offset = 0. This -parameter may be used to skip over any header information in the file -that precedes the binary data. Further examples: - -\begin{verbatim} - raw.dat[b10000] 1-dimensional 10000 pixel byte array - raw.dat[rb400,400,12] 3-dimensional floating point big-endian array - img.fits[ib512,512:2880] reads the 512 x 512 short integer array in a - FITS file, skipping over the 2880 byte header -\end{verbatim} - -\end{itemize} -\newpage - -\subsection{Image Filtering} - -\subsubsection{Extracting a subsection of an image} - -When specifying the name of an image to be opened, you can select a -rectangular subsection of the image to be extracted and opened by the -application program. The application program then opens a virtual -image that only contains the pixels within the specified subsection. -To do this, specify the the range of pixels (start:end) along each axis -to be extracted from the original image enclosed in square brackets. -You can also specify an optional pixel increment (start:end:step) for -each axis of the input image. A pixel step = 1 will be assumed if it -is not specified. If the starting pixel is larger then the end pixel, -then the image will be flipped (producing a mirror image) along that -dimension. An asterisk, '*', may be used to specify the entire range -of an axis, and '-*' will flip the entire axis. In the following -examples, assume that {\tt myfile.fits} contains a 512 x 512 pixel 2D -image. - -\begin{verbatim} - myfile.fits[201:210, 251:260] - opens a 10 x 10 pixel subimage. - - myfile.fits[*, 512:257] - opens a 512 x 256 image consisting of - all the columns in the input image, but only rows 257 - through 512. The image will be flipped along the Y axis - since the starting row is greater than the ending - row. - - myfile.fits[*:2, 512:257:2] - creates a 256 x 128 pixel image. - Similar to the previous example, but only every other row - and column is read from the input image. - - myfile.fits[-*, *] - creates an image containing all the rows and - columns in the input image, but flips it along the X - axis. -\end{verbatim} - -If the array to be opened is in an Image extension, and not in the -primary array of the file, then you need to specify the extension -name or number in square brackets before giving the subsection range, -as in {\tt myfile.fits[1][-*, *]} to read the image in the -first extension in the file. - -\subsubsection{Create an Image by Binning Table Columns} - -You can also create and open a virtual image by binning the values in a -pair of columns of a FITS table (in other words, create a 2-D histogram -of the values in the 2 columns). This technique is often used in X-ray -astronomy where each detected X-ray photon during an observation is -recorded in a FITS table. There are typically 2 columns in the table -called {\tt X} and {\tt Y} which record the pixel location of that -event in a virtual 2D image. To create an image from this table, one -just scans the X and Y columns and counts up how many photons were -recorded in each pixel of the image. When table binning is specified, -CFITSIO creates a temporary FITS primary array in memory by computing -the histogram of the values in the specified columns. After the -histogram is computed the original FITS file containing the table is -closed and the temporary FITS primary array is opened and passed to the -application program. Thus, the application program never sees the -original FITS table and only sees the image in the new temporary file -(which has no extensions). - -The table binning specifier is enclosed in square brackets following -the root filename and table extension name or number and begins with -the keyword 'bin', as in: \newline -{\tt 'myfile.fits[events][bin (X,Y)]'}. In -this case, the X and Y columns in the 'events' table extension are -binned up to create the image. The size of the image is usually -determined by the {\tt TLMINn} and {\tt TLMAXn} header keywords which -give the minimum and maximum allowed pixel values in the columns. For -instance if {\tt TLMINn = 1} and {\tt TLMAXn = 4096} for both columns, this would -generate a 4096 x 4096 pixel image by default. This is rather large, -so you can also specify a pixel binning factor to reduce the image -size. For example specifying , {\tt '[bin (X,Y) = 16]'} will use a -binning factor of 16, which will produce a 256 x 256 pixel image in the -previous example. - -If the TLMIN and TLMAX keywords don't exist, or you want to override -their values, you can specify the image range and binning factor -directly, as in {\tt '[bin X = 1:4096:16, Y=1:4096:16]'}. You can also -specify the datatype of the created image by appending a b, i, j, r, or -d (for 8-bit byte, 16-bit integers, 32-bit integer, 32-bit floating -points, or 64-bit double precision floating point, respectively) to -the 'bin' keyword (e.g. {\tt '[binr (X,Y)]'} creates a floating point -image). If the datatype is not specified then a 32-bit integer image -will be created by default. - -If the column name is not specified, then CFITSIO will first try to use -the 'preferred column' as specified by the CPREF keyword if it exists -(e.g., 'CPREF = 'DETX,DETY'), otherwise column names 'X', 'Y' will be -assumed for the 2 axes. - -Note that this binning specifier is not restricted to only 2D images -and can be used to create 1D, 3D, or 4D images as well. It is also -possible to specify a weighting factor that is applied during the -binning. Please refer to the ``CFITSIO User's Reference Guide'' for -more details on these advanced features. -\newpage - -\subsection{Table Filtering} - -\subsubsection{Column and Keyword Filtering} - -The column or keyword filtering specifier is used to modify the -column structure and/or the header keywords in the HDU that was -selected with the previous HDU location specifier. It can -be used to perform the following types of operations. - -\begin{itemize} -\item -Append a new column to a table by giving the column name, optionally -followed by the datatype in parentheses, followed by an equals sign and -the arithmetic expression to be used to compute the value. The -datatype is specified using the same syntax that is allowed for the -value of the FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for -binary tables, and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If -the datatype is not specified then a default datatype will be chosen -depending on the expression. - -\item -Create a new header keyword by giving the keyword name, preceded by a -pound sign '\#', followed by an equals sign and an arithmetic -expression for the value of the keyword. The expression may be a -function of other header keyword values. The comment string for the -keyword may be specified in parentheses immediately following the -keyword name. - -\item -Overwrite the values in an existing column or keyword by giving the -name followed by an equals sign and an arithmetic expression. - -\item -Select a set of columns to be included in the filtered file by listing -the column names separated with semi-colons. Wild card characters may -be used in the column names to match multiple columns. Any other -columns in the input table will not appear in the filtered file. - -\item -Delete a column or keyword by listing the name preceded by a minus sign -or an exclamation mark (!) - -\item -Rename an existing column or keyword with the syntax 'NewName == -OldName'. - -\end{itemize} - -The column filtering specifier is enclosed in square brackets and -begins with the string 'col'. Multiple operations can be performed -by separating them with semi-colons. For complex or commonly used -operations, you can write the column filter to a text file, and then -use it by giving the name of the text file, preceded by a '@' -character. - -Some examples: - -\begin{verbatim} - [col PI=PHA * 1.1 + 0.2] - creates new PI column from PHA values - - [col rate = counts/exposure] - creates or overwrites the rate column by - dividing the counts column by the - EXPOSURE keyword value. - - [col TIME; X; Y] - only the listed columns will appear - in the filtered file - - [col Time;*raw] - include the Time column and any other - columns whose name ends with 'raw'. - - [col -TIME; Good == STATUS] - deletes the TIME column and - renames the STATUS column to GOOD - - [col @colfilt.txt] - uses the filtering expression in - the colfilt.txt text file -\end{verbatim} - -The original file is not changed by this filtering operation, and -instead the modifications are made on a temporary copy of the input -FITS file (usually in memory), which includes a copy of all the other -HDUs in the input file. The original input file is closed and the -application program opens the filtered copy of the file. - -\subsubsection{Row Filtering} - -The row filter is used to select a subset of the rows from a table -based on a boolean expression. A temporary new FITS file is created on -the fly (usually in memory) which contains only those rows for which -the row filter expression evaluates to true (i.e., not equal to zero). -The primary array and any other extensions in the input file are also -copied to the temporary file. The original FITS file is closed and the -new temporary file is then opened by the application program. - -The row filter expression is enclosed in square brackets following the -file name and extension name. For example, {\tt -'file.fits[events][GRADE==50]'} selects only those rows in the EVENTS -table where the GRADE column value is equal to 50). - -The row filtering expression can be an arbitrarily complex series of -operations performed on constants, keyword values, and column data -taken from the specified FITS TABLE extension. The expression -also can be written into a text file and then used by giving the -filename preceded by a '@' character, as in -{\tt '[@rowfilt.txt]'}. - -Keyword and column data are referenced by name. Any string of -characters not surrounded by quotes (ie, a constant string) or -followed by an open parentheses (ie, a function name) will be -initially interpreted as a column name and its contents for the -current row inserted into the expression. If no such column exists, -a keyword of that name will be searched for and its value used, if -found. To force the name to be interpreted as a keyword (in case -there is both a column and keyword with the same name), precede the -keyword name with a single pound sign, '\#', as in {\tt \#NAXIS2}. Due to -the generalities of FITS column and keyword names, if the column or -keyword name contains a space or a character which might appear as -an arithmetic term then inclose the name in '\$' characters as in -{\tt \$MAX PHA\$} or {\tt \#\$MAX-PHA\$}. The names are case insensitive. - -To access a table entry in a row other than the current one, follow -the column's name with a row offset within curly braces. For -example, {\tt'PHA\{-3\}'} will evaluate to the value of column PHA, 3 rows -above the row currently being processed. One cannot specify an -absolute row number, only a relative offset. Rows that fall outside -the table will be treated as undefined, or NULLs. - -Boolean operators can be used in the expression in either their -Fortran or C forms. The following boolean operators are available: - -\begin{verbatim} - "equal" .eq. .EQ. == "not equal" .ne. .NE. != - "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< - "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => - "or" .or. .OR. || "and" .and. .AND. && - "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ -\end{verbatim} - -Note that the exclamation point, '!', is a special UNIX character, so -if it is used on the command line rather than entered at a task -prompt, it must be preceded by a backslash to force the UNIX shell to -ignore it. - -The expression may also include arithmetic operators and functions. -Trigonometric functions use radians, not degrees. The following -arithmetic operators and functions can be used in the expression -(function names are case insensitive): - - -\begin{verbatim} - "addition" + "subtraction" - - "multiplication" * "division" / - "negation" - "exponentiation" ** ^ - "absolute value" abs(x) "cosine" cos(x) - "sine" sin(x) "tangent" tan(x) - "arc cosine" arccos(x) "arc sine" arcsin(x) - "arc tangent" arctan(x) "arc tangent" arctan2(x,y) - "exponential" exp(x) "square root" sqrt(x) - "natural log" log(x) "common log" log10(x) - "modulus" i % j "random # [0.0,1.0)" random() - "minimum" min(x,y) "maximum" max(x,y) - "if-then-else" b?x:y -\end{verbatim} - - -The following type casting operators are available, where the -inclosing parentheses are required and taken from the C language -usage. Also, the integer to real casts values to double precision: - -\begin{verbatim} - "real to integer" (int) x (INT) x - "integer to real" (float) i (FLOAT) i -\end{verbatim} - - -Several constants are built in for use in numerical -expressions: - - -\begin{verbatim} - #pi 3.1415... #e 2.7182... - #deg #pi/180 #row current row number - #null undefined value #snull undefined string -\end{verbatim} - -A string constant must be enclosed in quotes as in 'Crab'. The -"null" constants are useful for conditionally setting table values to -a NULL, or undefined, value (For example, {\tt "col1==-99 ? \#NULL : -col1"}). - -There is also a function for testing if two values are close to -each other, i.e., if they are "near" each other to within a user -specified tolerance. The arguments, {\tt value\_1} and {\tt value\_2} can be -integer or real and represent the two values who's proximity is -being tested to be within the specified tolerance, also an integer -or real: - -\begin{verbatim} - near(value_1, value_2, tolerance) -\end{verbatim} - -When a NULL, or undefined, value is encountered in the FITS table, -the expression will evaluate to NULL unless the undefined value is -not actually required for evaluation, e.g. "TRUE .or. NULL" -evaluates to TRUE. The following two functions allow some NULL -detection and handling: - -\begin{verbatim} - ISNULL(x) - DEFNULL(x,y) -\end{verbatim} - -The former returns a boolean value of TRUE if the argument x is -NULL. The later "defines" a value to be substituted for NULL -values; it returns the value of x if x is not NULL, otherwise it -returns the value of y. - -Bit masks can be used to select out rows from bit columns ({\tt TFORMn = -\#X}) in FITS files. To represent the mask, binary, octal, and hex -formats are allowed: - -\begin{verbatim} - binary: b0110xx1010000101xxxx0001 - octal: o720x1 -> (b111010000xxx001) - hex: h0FxD -> (b00001111xxxx1101) -\end{verbatim} - -In all the representations, an x or X is allowed in the mask as a -wild card. Note that the x represents a different number of wild -card bits in each representation. All representations are case -insensitive. - -To construct the boolean expression using the mask as the boolean -equal operator described above on a bit table column. For example, -if you had a 7 bit column named flags in a FITS table and wanted -all rows having the bit pattern 0010011, the selection expression -would be: - - -\begin{verbatim} - flags == b0010011 - or - flags .eq. b10011 -\end{verbatim} - -It is also possible to test if a range of bits is less than, less -than equal, greater than and greater than equal to a particular -boolean value: - - -\begin{verbatim} - flags <= bxxx010xx - flags .gt. bxxx100xx - flags .le. b1xxxxxxx -\end{verbatim} - -Notice the use of the x bit value to limit the range of bits being -compared. - -It is not necessary to specify the leading (most significant) zero -(0) bits in the mask, as shown in the second expression above. - -Bit wise AND, OR and NOT operations are also possible on two or -more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) -operators. All of these operators result in a bit field which can -then be used with the equal operator. For example: - - -\begin{verbatim} - (!flags) == b1101100 - (flags & b1000001) == bx000001 -\end{verbatim} - -Bit fields can be appended as well using the '+' operator. Strings -can be concatenated this way, too. - -\subsubsection{Good Time Interval Filtering} - - A common filtering method involves selecting rows which have a time - value which lies within what is called a Good Time Interval or GTI. - The time intervals are defined in a separate FITS table extension - which contains 2 columns giving the start and stop time of each - good interval. The filtering operation accepts only those rows of - the input table which have an associated time which falls within - one of the time intervals defined in the GTI extension. A high - level function, gtifilter(a,b,c,d), is available which evaluates - each row of the input table and returns TRUE or FALSE depending - whether the row is inside or outside the good time interval. The - syntax is - -\begin{verbatim} - gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) -\end{verbatim} - where each "[]" demarks optional parameters. Note that the quotes - around the gtifile and START/STOP column are required. Either single - or double quote characters may be used. The gtifile, - if specified, can be blank ("") which will mean to use the first - extension with the name "*GTI*" in the current file, a plain - extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be - used to select an extension in the current file, or a regular - filename with or without an extension specifier which in the latter - case will mean to use the first extension with an extension name - "*GTI*". Expr can be any arithmetic expression, including simply - the time column name. A vector time expression will produce a - vector boolean result. STARTCOL and STOPCOL are the names of the - START/STOP columns in the GTI extension. If one of them is - specified, they both must be. - - In its simplest form, no parameters need to be provided -- default - values will be used. The expression {\tt "gtifilter()"} is equivalent to - -\begin{verbatim} - gtifilter( "", TIME, "*START*", "*STOP*" ) -\end{verbatim} - This will search the current file for a GTI extension, filter the - TIME column in the current table, using START/STOP times taken from - columns in the GTI extension with names containing the strings - "START" and "STOP". The wildcards ('*') allow slight variations in - naming conventions such as "TSTART" or "STARTTIME". The same - default values apply for unspecified parameters when the first one - or two parameters are specified. The function automatically - searches for TIMEZERO/I/F keywords in the current and GTI - extensions, applying a relative time offset, if necessary. - -\subsubsection{Spatial Region Filtering} - - Another common filtering method selects rows based on whether the - spatial position associated with each row is located within a given - 2-dimensional region. The syntax for this high-level filter is - -\begin{verbatim} - regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) -\end{verbatim} - where each "[ ]" demarks optional parameters. The region file name - is required and must be enclosed in quotes. The remaining - parameters are optional. The region file is an ASCII text file - which contains a list of one or more geometric shapes (circle, - ellipse, box, etc.) which defines a region on the celestial sphere - or an area within a particular 2D image. The region file is - typically generated using an image display program such as fv/POW - (distribute by the HEASARC), or ds9 (distributed by the Smithsonian - Astrophysical Observatory). Users should refer to the documentation - provided with these programs for more details on the syntax used in - the region files. - - In its simpliest form, (e.g., {\tt regfilter("region.reg")} ) the - coordinates in the default 'X' and 'Y' columns will be used to - determine if each row is inside or outside the area specified in - the region file. Alternate position column names, or expressions, - may be entered if needed, as in - -\begin{verbatim} - regfilter("region.reg", XPOS, YPOS) -\end{verbatim} - Region filtering can be applied most unambiguously if the positions - in the region file and in the table to be filtered are both give in - terms of absolute celestial coordinate units. In this case the - locations and sizes of the geometric shapes in the region file are - specified in angular units on the sky (e.g., positions given in - R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, - each row of the filtered table will have a celestial coordinate - associated with it. This association is usually implemented using - a set of so-called 'World Coordinate System' (or WCS) FITS keywords - that define the coordinate transformation that must be applied to - the values in the 'X' and 'Y' columns to calculate the coordinate. - - Alternatively, one can perform spatial filtering using unitless - 'pixel' coordinates for the regions and row positions. In this - case the user must be careful to ensure that the positions in the 2 - files are self-consistent. A typical problem is that the region - file may be generated using a binned image, but the unbinned - coordinates are given in the event table. The ROSAT events files, - for example, have X and Y pixel coordinates that range from 1 - - 15360. These coordinates are typically binned by a factor of 32 to - produce a 480x480 pixel image. If one then uses a region file - generated from this image (in image pixel units) to filter the - ROSAT events file, then the X and Y column values must be converted - to corresponding pixel units as in: - -\begin{verbatim} - regfilter("rosat.reg", X/32.+.5, Y/32.+.5) -\end{verbatim} - Note that this binning conversion is not necessary if the region - file is specified using celestial coordinate units instead of pixel - units because CFITSIO is then able to directly compare the - celestial coordinate of each row in the table with the celestial - coordinates in the region file without having to know anything - about how the image may have been binned. - - The last "wcs cols" parameter should rarely be needed. If supplied, - this string contains the names of the 2 columns (space or comma - separated) which have the associated WCS keywords. If not supplied, - the filter will scan the X and Y expressions for column names. - If only one is found in each expression, those columns will be - used, otherwise an error will be returned. - - These region shapes are supported (names are case insensitive): - -\begin{verbatim} - Point ( X1, Y1 ) <- One pixel square region - Line ( X1, Y1, X2, Y2 ) <- One pixel wide region - Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with - Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered - Box ( Xc, Yc, Wdth, Hght, A ) V within the region - Diamond ( Xc, Yc, Wdth, Hght, A ) - Circle ( Xc, Yc, R ) - Annulus ( Xc, Yc, Rin, Rout ) - Ellipse ( Xc, Yc, Rx, Ry, A ) - Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) - Sector ( Xc, Yc, Amin, Amax ) -\end{verbatim} - where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are - the coordinates of the shape's edges; Rxxx are the shapes' various - Radii or semimajor/minor axes; and Axxx are the angles of rotation - (or bounding angles for Sector) in degrees. For rotated shapes, the - rotation angle can be left off, indicating no rotation. Common - alternate names for the regions can also be used: rotbox = box; - rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie - = sector. When a shape's name is preceded by a minus sign, '-', - the defined region is instead the area *outside* its boundary (ie, - the region is inverted). All the shapes within a single region - file are OR'd together to create the region, and the order is - significant. The overall way of looking at region files is that if - the first region is an excluded region then a dummy included region - of the whole detector is inserted in the front. Then each region - specification as it is processed overrides any selections inside of - that region specified by previous regions. Another way of thinking - about this is that if a previous excluded region is completely - inside of a subsequent included region the excluded region is - ignored. - - The positional coordinates may be given either in pixel units, - decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes - may be given in pixels, degrees, arcminutes, or arcseconds. Look - at examples of region file produced by fv/POW or ds9 for further - details of the region file format. - -\subsubsection{Example Row Filters} - -\begin{verbatim} - [double && mag <= 5.0] - Extract all double stars brighter - than fifth magnitude - - [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 - - [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the - absolute value of the sine of theta - less than a half where the angles - are tabulated in degrees - - [@rowFilter.txt] - Extract rows using the expression - contained within the text file - rowFilter.txt - - [gtifilter()] - Search the current file for a GTI - extension, filter the TIME - column in the current table, using - START/STOP times taken from - columns in the GTI extension - - [regfilter("pow.reg")] - Extract rows which have a coordinate - (as given in the X and Y columns) - within the spatial region specified - in the pow.reg region file. -\end{verbatim} - -\newpage -\subsection{Combined Filtering Examples} - -The previous sections described all the individual types of filters -that may be applied to the input file. In this section we show -examples which combine several different filters at once. These -examples all use the {\tt fitscopy} program that is distributed with -the CFITSIO code. It simply copies the input file to the output file. - -\begin{verbatim} -fitscopy rosat.fit out.fit -\end{verbatim} - -This trivial example simply makes an identical copy of the input -rosat.fit file without any filtering. - -\begin{verbatim} -fitscopy 'rosat.fit[events][col Time;X;Y][#row < 1000]' out.fit -\end{verbatim} - -The output file contains only the Time, X, and Y columns, and only -the first 999 rows from the 'EVENTS' table extension of the input file. -All the other HDUs in the input file are copied to the output file -without any modification. - -\begin{verbatim} -fitscopy 'rosat.fit[events][PI < 50][bin (Xdet,Ydet) = 16]' image.fit -\end{verbatim} - -This creates an output image by binning the Xdet and Ydet columns of -the events table with a pixel binning factor of 16. Only the rows -which have a PI energy less than 50 are used to construct this image. -The output image file contains a primary array image without any -extensions. - -\begin{verbatim} -fitscopy 'rosat.fit[events][gtifilter() && regfilter("pow.reg")]' out.fit -\end{verbatim} - -The filtering expression in this example uses the {\tt gtifilter} -function to test whether the TIME column value in each row is within -one of the Good Time Intervals defined in the GTI extension in the same -input file, and also uses the {\tt regfilter} function to test if the -position associated with each row (derived by default from the values -in the X and Y columns of the events table) is located within the area -defined in the {\tt pow.reg} text region file (which was previously -created with the {\tt fv/POW} image display program). Only the rows -which satisfy both tests are copied to the output table. - -\begin{verbatim} -fitscopy 'r.fit[evt][PI<50]' stdout | fitscopy stdin[evt][col X,Y] out.fit -\end{verbatim} - -In this somewhat convoluted example, fitscopy is used to first select -the rows from the evt extension which have PI less than 50 and write the -resulting table out to the stdout stream. This is piped to a 2nd -instance of fitscopy (with the Unix `$|$' pipe command) which reads that -filtered FITS file from the stdin stream and copies only the X and Y -columns from the evt table to the output file. - -\begin{verbatim} -fitscopy 'r.fit[evt][col RAD=sqrt((X-#XCEN)**2+(Y-#YCEN)**2)][rad<100]' out.fit -\end{verbatim} - -This example first creates a new column called RAD which gives the -distance between the X,Y coordinate of each event and the coordinate -defined by the XCEN and YCEN keywords in the header. Then, only those -rows which have a distance less than 100 are copied to the output -table. In other words, only the events which are located within 100 -pixel units from the (XCEN, YCEN) coordinate are copied to the output -table. - -\begin{verbatim} -fitscopy 'ftp://heasarc.gsfc.nasa.gov/rosat.fit[events][bin (X,Y)=16]' img.fit -\end{verbatim} - -This example bins the X and Y columns of the hypothetical ROSAT file -at the HEASARC ftp site to create the output image. - -\begin{verbatim} -fitscopy 'raw.fit[i512,512][101:110,51:60]' image.fit -\end{verbatim} - -This example converts the 512 x 512 pixel raw binary 16-bit integer -image to a FITS file and copies a 10 x 10 pixel subimage from it to the -output FITS image. - -\newpage -\section{CFITSIO Error Status Codes} - -The following table lists all the error status codes used by CFITSIO. -Programmers are encouraged to use the symbolic mnemonics (defined in -the file fitsio.h) rather than the actual integer status values to -improve the readability of their code. - -\begin{verbatim} - Symbolic Const Value Meaning - -------------- ----- ----------------------------------------- - 0 OK, no error - SAME_FILE 101 input and output files are the same - TOO_MANY_FILES 103 tried to open too many FITS files at once - FILE_NOT_OPENED 104 could not open the named file - FILE_NOT_CREATED 105 could not create the named file - WRITE_ERROR 106 error writing to FITS file - END_OF_FILE 107 tried to move past end of file - READ_ERROR 108 error reading from FITS file - FILE_NOT_CLOSED 110 could not close the file - ARRAY_TOO_BIG 111 array dimensions exceed internal limit - READONLY_FILE 112 Cannot write to readonly file - MEMORY_ALLOCATION 113 Could not allocate memory - BAD_FILEPTR 114 invalid fitsfile pointer - NULL_INPUT_PTR 115 NULL input pointer to routine - SEEK_ERROR 116 error seeking position in file - - BAD_URL_PREFIX 121 invalid URL prefix on file name - TOO_MANY_DRIVERS 122 tried to register too many IO drivers - DRIVER_INIT_FAILED 123 driver initialization failed - NO_MATCHING_DRIVER 124 matching driver is not registered - URL_PARSE_ERROR 125 failed to parse input file URL - - SHARED_BADARG 151 bad argument in shared memory driver - SHARED_NULPTR 152 null pointer passed as an argument - SHARED_TABFULL 153 no more free shared memory handles - SHARED_NOTINIT 154 shared memory driver is not initialized - SHARED_IPCERR 155 IPC error returned by a system call - SHARED_NOMEM 156 no memory in shared memory driver - SHARED_AGAIN 157 resource deadlock would occur - SHARED_NOFILE 158 attempt to open/create lock file failed - SHARED_NORESIZE 159 shared memory block cannot be resized at the moment - - HEADER_NOT_EMPTY 201 header already contains keywords - KEY_NO_EXIST 202 keyword not found in header - KEY_OUT_BOUNDS 203 keyword record number is out of bounds - VALUE_UNDEFINED 204 keyword value field is blank - NO_QUOTE 205 string is missing the closing quote - BAD_KEYCHAR 207 illegal character in keyword name or card - BAD_ORDER 208 required keywords out of order - NOT_POS_INT 209 keyword value is not a positive integer - NO_END 210 couldn't find END keyword - BAD_BITPIX 211 illegal BITPIX keyword value - BAD_NAXIS 212 illegal NAXIS keyword value - BAD_NAXES 213 illegal NAXISn keyword value - BAD_PCOUNT 214 illegal PCOUNT keyword value - BAD_GCOUNT 215 illegal GCOUNT keyword value - BAD_TFIELDS 216 illegal TFIELDS keyword value - NEG_WIDTH 217 negative table row size - NEG_ROWS 218 negative number of rows in table - COL_NOT_FOUND 219 column with this name not found in table - BAD_SIMPLE 220 illegal value of SIMPLE keyword - NO_SIMPLE 221 Primary array doesn't start with SIMPLE - NO_BITPIX 222 Second keyword not BITPIX - NO_NAXIS 223 Third keyword not NAXIS - NO_NAXES 224 Couldn't find all the NAXISn keywords - NO_XTENSION 225 HDU doesn't start with XTENSION keyword - NOT_ATABLE 226 the CHDU is not an ASCII table extension - NOT_BTABLE 227 the CHDU is not a binary table extension - NO_PCOUNT 228 couldn't find PCOUNT keyword - NO_GCOUNT 229 couldn't find GCOUNT keyword - NO_TFIELDS 230 couldn't find TFIELDS keyword - NO_TBCOL 231 couldn't find TBCOLn keyword - NO_TFORM 232 couldn't find TFORMn keyword - NOT_IMAGE 233 the CHDU is not an IMAGE extension - BAD_TBCOL 234 TBCOLn keyword value < 0 or > rowlength - NOT_TABLE 235 the CHDU is not a table - COL_TOO_WIDE 236 column is too wide to fit in table - COL_NOT_UNIQUE 237 more than 1 column name matches template - BAD_ROW_WIDTH 241 sum of column widths not = NAXIS1 - UNKNOWN_EXT 251 unrecognizable FITS extension type - UNKNOWN_REC 252 unknown record; 1st keyword not SIMPLE or XTENSION - END_JUNK 253 END keyword is not blank - BAD_HEADER_FILL 254 Header fill area contains non-blank chars - BAD_DATA_FILL 255 Illegal data fill bytes (not zero or blank) - BAD_TFORM 261 illegal TFORM format code - BAD_TFORM_DTYPE 262 unrecognizable TFORM datatype code - BAD_TDIM 263 illegal TDIMn keyword value - BAD_HEAP_PTR 264 invalid BINTABLE heap pointer is out of range - - BAD_HDU_NUM 301 HDU number < 1 or > MAXHDU - BAD_COL_NUM 302 column number < 1 or > tfields - NEG_FILE_POS 304 tried to move to negative byte location in file - NEG_BYTES 306 tried to read or write negative number of bytes - BAD_ROW_NUM 307 illegal starting row number in table - BAD_ELEM_NUM 308 illegal starting element number in vector - NOT_ASCII_COL 309 this is not an ASCII string column - NOT_LOGICAL_COL 310 this is not a logical datatype column - BAD_ATABLE_FORMAT 311 ASCII table column has wrong format - BAD_BTABLE_FORMAT 312 Binary table column has wrong format - NO_NULL 314 null value has not been defined - NOT_VARI_LEN 317 this is not a variable length column - BAD_DIMEN 320 illegal number of dimensions in array - BAD_PIX_NUM 321 first pixel number greater than last pixel - ZERO_SCALE 322 illegal BSCALE or TSCALn keyword = 0 - NEG_AXIS 323 illegal axis length < 1 - - NOT_GROUP_TABLE 340 Grouping function error - HDU_ALREADY_MEMBER 341 - MEMBER_NOT_FOUND 342 - GROUP_NOT_FOUND 343 - BAD_GROUP_ID 344 - TOO_MANY_HDUS_TRACKED 345 - HDU_ALREADY_TRACKED 346 - BAD_OPTION 347 - IDENTICAL_POINTERS 348 - BAD_GROUP_ATTACH 349 - BAD_GROUP_DETACH 350 - - NGP_NO_MEMORY 360 malloc failed - NGP_READ_ERR 361 read error from file - NGP_NUL_PTR 362 null pointer passed as an argument. - Passing null pointer as a name of - template file raises this error - NGP_EMPTY_CURLINE 363 line read seems to be empty (used - internally) - NGP_UNREAD_QUEUE_FULL 364 cannot unread more then 1 line (or single - line twice) - NGP_INC_NESTING 365 too deep include file nesting (infinite - loop, template includes itself ?) - NGP_ERR_FOPEN 366 fopen() failed, cannot open template file - NGP_EOF 367 end of file encountered and not expected - NGP_BAD_ARG 368 bad arguments passed. Usually means - internal parser error. Should not happen - NGP_TOKEN_NOT_EXPECT 369 token not expected here - - BAD_I2C 401 bad int to formatted string conversion - BAD_F2C 402 bad float to formatted string conversion - BAD_INTKEY 403 can't interpret keyword value as integer - BAD_LOGICALKEY 404 can't interpret keyword value as logical - BAD_FLOATKEY 405 can't interpret keyword value as float - BAD_DOUBLEKEY 406 can't interpret keyword value as double - BAD_C2I 407 bad formatted string to int conversion - BAD_C2F 408 bad formatted string to float conversion - BAD_C2D 409 bad formatted string to double conversion - BAD_DATATYPE 410 illegal datatype code value - BAD_DECIM 411 bad number of decimal places specified - NUM_OVERFLOW 412 overflow during datatype conversion - DATA_COMPRESSION_ERR 413 error compressing image - DATA_DECOMPRESSION_ERR 414 error uncompressing image - - BAD_DATE 420 error in date or time conversion - - PARSE_SYNTAX_ERR 431 syntax error in parser expression - PARSE_BAD_TYPE 432 expression did not evaluate to desired type - PARSE_LRG_VECTOR 433 vector result too large to return in array - PARSE_NO_OUTPUT 434 data parser failed not sent an out column - PARSE_BAD_COL 435 bad data encounter while parsing column - PARSE_BAD_OUTPUT 436 Output file not of proper type - - ANGLE_TOO_BIG 501 celestial angle too large for projection - BAD_WCS_VAL 502 bad celestial coordinate or pixel value - WCS_ERROR 503 error in celestial coordinate calculation - BAD_WCS_PROJ 504 unsupported type of celestial projection - NO_WCS_KEY 505 celestial coordinate keywords not found - APPROX_WCS_KEY 506 approximate wcs keyword values were returned -\end{verbatim} - -\end{document} diff --git a/src/external/OpenGR/3rdparty/cfitsio/docs/quick.toc b/src/external/OpenGR/3rdparty/cfitsio/docs/quick.toc deleted file mode 100644 index 9d7c7da6b..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/docs/quick.toc +++ /dev/null @@ -1,25 +0,0 @@ -\contentsline {section}{\numberline {1}Introduction}{2} -\contentsline {section}{\numberline {2}Installing and Using CFITSIO}{3} -\contentsline {section}{\numberline {3}Example Programs}{4} -\contentsline {section}{\numberline {4}CFITSIO Routines}{6} -\contentsline {subsection}{\numberline {4.1}Error Reporting}{6} -\contentsline {subsection}{\numberline {4.2}File Open/Close Routines}{6} -\contentsline {subsection}{\numberline {4.3}HDU-level Routines}{7} -\contentsline {subsection}{\numberline {4.4}Image I/O Routines}{9} -\contentsline {subsection}{\numberline {4.5}Table I/O Routines}{12} -\contentsline {subsection}{\numberline {4.6}Header Keyword I/O Routines}{19} -\contentsline {subsection}{\numberline {4.7}Utility Routines}{22} -\contentsline {section}{\numberline {5}CFITSIO File Names and Filters}{23} -\contentsline {subsection}{\numberline {5.1}Creating New Files}{23} -\contentsline {subsection}{\numberline {5.2}Opening Existing Files}{24} -\contentsline {subsection}{\numberline {5.3}Image Filtering}{26} -\contentsline {subsubsection}{\numberline {5.3.1}Extracting a subsection of an image}{26} -\contentsline {subsubsection}{\numberline {5.3.2}Create an Image by Binning Table Columns}{26} -\contentsline {subsection}{\numberline {5.4}Table Filtering}{28} -\contentsline {subsubsection}{\numberline {5.4.1}Column and Keyword Filtering}{28} -\contentsline {subsubsection}{\numberline {5.4.2}Row Filtering}{29} -\contentsline {subsubsection}{\numberline {5.4.3}Good Time Interval Filtering}{32} -\contentsline {subsubsection}{\numberline {5.4.4}Spatial Region Filtering}{32} -\contentsline {subsubsection}{\numberline {5.4.5}Example Row Filters}{34} -\contentsline {subsection}{\numberline {5.5}Combined Filtering Examples}{36} -\contentsline {section}{\numberline {6}CFITSIO Error Status Codes}{38} diff --git a/src/external/OpenGR/3rdparty/cfitsio/drvrfile.c b/src/external/OpenGR/3rdparty/cfitsio/drvrfile.c deleted file mode 100644 index db962990e..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/drvrfile.c +++ /dev/null @@ -1,1003 +0,0 @@ -/* This file, drvrfile.c contains driver routines for disk files. */ - -/* The FITSIO software was written by William Pence at the High Energy */ -/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ -/* Goddard Space Flight Center. */ - -#include -#include -#include "fitsio2.h" -#include "group.h" /* needed for fits_get_cwd in file_create */ - -#if defined(unix) || defined(__unix__) || defined(__unix) -#include /* needed in file_openfile */ - -#ifdef REPLACE_LINKS -#include -#include -#endif - -#endif - -#ifdef HAVE_FTRUNCATE -#if defined(unix) || defined(__unix__) || defined(__unix) || defined(HAVE_UNISTD_H) -#include /* needed for getcwd prototype on unix machines */ -#endif -#endif - -#define IO_SEEK 0 /* last file I/O operation was a seek */ -#define IO_READ 1 /* last file I/O operation was a read */ -#define IO_WRITE 2 /* last file I/O operation was a write */ - -static char file_outfile[FLEN_FILENAME]; - -typedef struct /* structure containing disk file structure */ -{ - FILE *fileptr; - LONGLONG currentpos; - int last_io_op; -} diskdriver; - -static diskdriver handleTable[NMAXFILES]; /* allocate diskfile handle tables */ - -/*--------------------------------------------------------------------------*/ -int file_init(void) -{ - int ii; - - for (ii = 0; ii < NMAXFILES; ii++) /* initialize all empty slots in table */ - { - handleTable[ii].fileptr = 0; - } - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_setoptions(int options) -{ - /* do something with the options argument, to stop compiler warning */ - options = 0; - return(options); -} -/*--------------------------------------------------------------------------*/ -int file_getoptions(int *options) -{ - *options = 0; - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_getversion(int *version) -{ - *version = 10; - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_shutdown(void) -{ - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_open(char *filename, int rwmode, int *handle) -{ - FILE *diskfile; - int copyhandle, ii, status; - char recbuf[2880]; - size_t nread; - - /* - if an output filename has been specified as part of the input - file, as in "inputfile.fits(outputfile.fit)" then we have to - create the output file, copy the input to it, then reopen the - the new copy. - */ - - if (*file_outfile) - { - /* open the original file, with readonly access */ - status = file_openfile(filename, READONLY, &diskfile); - if (status) { - file_outfile[0] = '\0'; - return(status); - } - - /* create the output file */ - status = file_create(file_outfile,handle); - if (status) - { - ffpmsg("Unable to create output file for copy of input file:"); - ffpmsg(file_outfile); - file_outfile[0] = '\0'; - return(status); - } - - /* copy the file from input to output */ - while(0 != (nread = fread(recbuf,1,2880, diskfile))) - { - status = file_write(*handle, recbuf, nread); - if (status) { - file_outfile[0] = '\0'; - return(status); - } - } - - /* close both files */ - fclose(diskfile); - copyhandle = *handle; - file_close(*handle); - *handle = copyhandle; /* reuse the old file handle */ - - /* reopen the new copy, with correct rwmode */ - status = file_openfile(file_outfile, rwmode, &diskfile); - file_outfile[0] = '\0'; - } - else - { - *handle = -1; - for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in table */ - { - if (handleTable[ii].fileptr == 0) - { - *handle = ii; - break; - } - } - - if (*handle == -1) - return(TOO_MANY_FILES); /* too many files opened */ - - /*open the file */ - status = file_openfile(filename, rwmode, &diskfile); - } - - handleTable[*handle].fileptr = diskfile; - handleTable[*handle].currentpos = 0; - handleTable[*handle].last_io_op = IO_SEEK; - - return(status); -} -/*--------------------------------------------------------------------------*/ -int file_openfile(char *filename, int rwmode, FILE **diskfile) -/* - lowest level routine to physically open a disk file -*/ -{ - char mode[4]; - -#if defined(unix) || defined(__unix__) || defined(__unix) - char tempname[1024], *cptr, user[80]; - struct passwd *pwd; - int ii = 0; - -#if defined(REPLACE_LINKS) - struct stat stbuf; - int success = 0; - size_t n; - FILE *f1, *f2; - char buf[BUFSIZ]; -#endif - -#endif - - if (rwmode == READWRITE) - { - strcpy(mode, "r+b"); /* open existing file with read-write */ - } - else - { - strcpy(mode, "rb"); /* open existing file readonly */ - } - -#if MACHINE == ALPHAVMS || MACHINE == VAXVMS - /* specify VMS record structure: fixed format, 2880 byte records */ - /* but force stream mode access to enable random I/O access */ - *diskfile = fopen(filename, mode, "rfm=fix", "mrs=2880", "ctx=stm"); - -#elif defined(unix) || defined(__unix__) || defined(__unix) - - /* support the ~user/file.fits or ~/file.fits filenames in UNIX */ - - if (*filename == '~') - { - if (filename[1] == '/') - { - cptr = getenv("HOME"); - if (cptr) - { - if (strlen(cptr) + strlen(filename+1) > 1023) - return(FILE_NOT_OPENED); - - strcpy(tempname, cptr); - strcat(tempname, filename+1); - } - else - { - if (strlen(filename) > 1023) - return(FILE_NOT_OPENED); - - strcpy(tempname, filename); - } - } - else - { - /* copy user name */ - cptr = filename+1; - while (*cptr && (*cptr != '/')) - { - user[ii] = *cptr; - cptr++; - ii++; - } - user[ii] = '\0'; - - /* get structure that includes name of user's home directory */ - pwd = getpwnam(user); - - /* copy user's home directory */ - if (strlen(pwd->pw_dir) + strlen(cptr) > 1023) - return(FILE_NOT_OPENED); - - strcpy(tempname, pwd->pw_dir); - strcat(tempname, cptr); - } - - *diskfile = fopen(tempname, mode); - } - else - { - /* don't need to expand the input file name */ - *diskfile = fopen(filename, mode); - -#if defined(REPLACE_LINKS) - - if (!(*diskfile) && (rwmode == READWRITE)) - { - /* failed to open file with READWRITE privilege. Test if */ - /* the file we are trying to open is a soft link to a file that */ - /* doesn't have write privilege. */ - - lstat(filename, &stbuf); - if ((stbuf.st_mode & S_IFMT) == S_IFLNK) /* is this a soft link? */ - { - if ((f1 = fopen(filename, "rb")) != 0) /* try opening READONLY */ - { - - if (strlen(filename) + 7 > 1023) - return(FILE_NOT_OPENED); - - strcpy(tempname, filename); - strcat(tempname, ".TmxFil"); - if ((f2 = fopen(tempname, "wb")) != 0) /* create temp file */ - { - success = 1; - while ((n = fread(buf, 1, BUFSIZ, f1)) > 0) - { - /* copy linked file to local temporary file */ - if (fwrite(buf, 1, n, f2) != n) - { - success = 0; - break; - } - } - fclose(f2); - } - fclose(f1); - - if (success) - { - /* delete link and rename temp file to previous link name */ - remove(filename); - rename(tempname, filename); - - /* try once again to open the file with write access */ - *diskfile = fopen(filename, mode); - } - else - remove(tempname); /* clean up the failed copy */ - } - } - } -#endif - - } - -#else - - /* other non-UNIX machines */ - *diskfile = fopen(filename, mode); - -#endif - - if (!(*diskfile)) /* couldn't open file */ - { - return(FILE_NOT_OPENED); - } - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_create(char *filename, int *handle) -{ - FILE *diskfile; - int ii; - char mode[4]; - - int status = 0, rootlen, rootlen2, slen; - char *cptr, *cpos; - char cwd[FLEN_FILENAME], absURL[FLEN_FILENAME]; - char rootstring[256], rootstring2[256]; - char username[FLEN_FILENAME], userroot[FLEN_FILENAME], userroot2[FLEN_FILENAME]; - - cptr = getenv("HERA_DATA_DIRECTORY"); - if (cptr) { - /* This environment variable is defined in the Hera data analysis environment. */ - /* It specifies the root directory path to the users data directories. */ - /* CFITSIO will verify that the path to the file that is to be created */ - /* is within this root directory + the user's home directory name. */ - -/* -printf("env = %s\n",cptr); -*/ - if (strlen(cptr) > 200) /* guard against possible string overflows */ - return(FILE_NOT_CREATED); - - /* environment variable has the form "path/one/;/path/two/" where the */ - /* second path is optional */ - - strcpy(rootstring, cptr); - cpos = strchr(rootstring, ';'); - if (cpos) { - *cpos = '\0'; - cpos++; - strcpy(rootstring2, cpos); - } else { - *rootstring2 = '\0'; - } -/* -printf("%s, %s\n", rootstring, rootstring2); -printf("CWD = %s\n", cwd); -printf("rootstring=%s, cwd=%s.\n", rootstring, cwd); -*/ - /* Get the current working directory */ - fits_get_cwd(cwd, &status); - slen = strlen(cwd); - if (cwd[slen-1] != '/') strcat(cwd,"/"); /* make sure the CWD ends with slash */ - - - /* check that CWD string matches the rootstring */ - rootlen = strlen(rootstring); - if (strncmp(rootstring, cwd, rootlen)) { - ffpmsg("invalid CWD: does not match root data directory"); - return(FILE_NOT_CREATED); - } else { - - /* get the user name from CWD (it follows the root string) */ - strncpy(username, cwd+rootlen, 50); /* limit length of user name */ - cpos=strchr(username, '/'); - if (!cpos) { - ffpmsg("invalid CWD: not equal to root data directory + username"); - return(FILE_NOT_CREATED); - } else { - *(cpos+1) = '\0'; /* truncate user name string */ - - /* construct full user root name */ - strcpy(userroot, rootstring); - strcat(userroot, username); - rootlen = strlen(userroot); - - /* construct alternate full user root name */ - strcpy(userroot2, rootstring2); - strcat(userroot2, username); - rootlen2 = strlen(userroot2); - - /* convert the input filename to absolute path relative to the CWD */ - fits_relurl2url(cwd, filename, absURL, &status); - -/* -printf("username = %s\n", username); -printf("userroot = %s\n", userroot); -printf("userroot2 = %s\n", userroot2); -printf("filename = %s\n", filename); -printf("ABS = %s\n", absURL); -*/ - /* check that CWD string matches the rootstring or alternate root string */ - - if ( strncmp(userroot, absURL, rootlen) && - strncmp(userroot2, absURL, rootlen2) ) { - ffpmsg("invalid filename: path not within user directory"); - return(FILE_NOT_CREATED); - } - } - } - /* if we got here, then the input filename appears to be valid */ - } - - *handle = -1; - for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in table */ - { - if (handleTable[ii].fileptr == 0) - { - *handle = ii; - break; - } - } - if (*handle == -1) - return(TOO_MANY_FILES); /* too many files opened */ - - strcpy(mode, "w+b"); /* create new file with read-write */ - - diskfile = fopen(filename, "r"); /* does file already exist? */ - - if (diskfile) - { - fclose(diskfile); /* close file and exit with error */ - return(FILE_NOT_CREATED); - } - -#if MACHINE == ALPHAVMS || MACHINE == VAXVMS - /* specify VMS record structure: fixed format, 2880 byte records */ - /* but force stream mode access to enable random I/O access */ - diskfile = fopen(filename, mode, "rfm=fix", "mrs=2880", "ctx=stm"); -#else - diskfile = fopen(filename, mode); -#endif - - if (!(diskfile)) /* couldn't create file */ - { - return(FILE_NOT_CREATED); - } - - handleTable[ii].fileptr = diskfile; - handleTable[ii].currentpos = 0; - handleTable[ii].last_io_op = IO_SEEK; - - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_truncate(int handle, LONGLONG filesize) -/* - truncate the diskfile to a new smaller size -*/ -{ - -#ifdef HAVE_FTRUNCATE - int fdesc; - - fdesc = fileno(handleTable[handle].fileptr); - ftruncate(fdesc, (OFF_T) filesize); - file_seek(handle, filesize); - - handleTable[handle].currentpos = filesize; - handleTable[handle].last_io_op = IO_SEEK; - -#endif - - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_size(int handle, LONGLONG *filesize) -/* - return the size of the file in bytes -*/ -{ - OFF_T position1,position2; - FILE *diskfile; - - diskfile = handleTable[handle].fileptr; - -#if defined(_MSC_VER) && (_MSC_VER >= 1400) - -/* call the VISUAL C++ version of the routines which support */ -/* Large Files (> 2GB) if they are supported (since VC 8.0) */ - - position1 = _ftelli64(diskfile); /* save current postion */ - if (position1 < 0) - return(SEEK_ERROR); - - if (_fseeki64(diskfile, 0, 2) != 0) /* seek to end of file */ - return(SEEK_ERROR); - - position2 = _ftelli64(diskfile); /* get file size */ - if (position2 < 0) - return(SEEK_ERROR); - - if (_fseeki64(diskfile, position1, 0) != 0) /* seek back to original pos */ - return(SEEK_ERROR); - -#elif _FILE_OFFSET_BITS - 0 == 64 - -/* call the newer ftello and fseeko routines , which support */ -/* Large Files (> 2GB) if they are supported. */ - - position1 = ftello(diskfile); /* save current postion */ - if (position1 < 0) - return(SEEK_ERROR); - - if (fseeko(diskfile, 0, 2) != 0) /* seek to end of file */ - return(SEEK_ERROR); - - position2 = ftello(diskfile); /* get file size */ - if (position2 < 0) - return(SEEK_ERROR); - - if (fseeko(diskfile, position1, 0) != 0) /* seek back to original pos */ - return(SEEK_ERROR); - -#else - - position1 = ftell(diskfile); /* save current postion */ - if (position1 < 0) - return(SEEK_ERROR); - - if (fseek(diskfile, 0, 2) != 0) /* seek to end of file */ - return(SEEK_ERROR); - - position2 = ftell(diskfile); /* get file size */ - if (position2 < 0) - return(SEEK_ERROR); - - if (fseek(diskfile, position1, 0) != 0) /* seek back to original pos */ - return(SEEK_ERROR); - -#endif - - *filesize = (LONGLONG) position2; - - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_close(int handle) -/* - close the file -*/ -{ - - if (fclose(handleTable[handle].fileptr) ) - return(FILE_NOT_CLOSED); - - handleTable[handle].fileptr = 0; - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_remove(char *filename) -/* - delete the file from disk -*/ -{ - remove(filename); - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_flush(int handle) -/* - flush the file -*/ -{ - if (fflush(handleTable[handle].fileptr) ) - return(WRITE_ERROR); - - /* The flush operation is not supposed to move the internal */ - /* file pointer, but it does on some Windows-95 compilers and */ - /* perhaps others, so seek to original position to be sure. */ - /* This seek will do no harm on other systems. */ - -#if MACHINE == IBMPC - - if (file_seek(handle, handleTable[handle].currentpos)) - return(SEEK_ERROR); - -#endif - - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_seek(int handle, LONGLONG offset) -/* - seek to position relative to start of the file -*/ -{ - -#if defined(_MSC_VER) && (_MSC_VER >= 1400) - - /* Microsoft visual studio C++ */ - /* _fseeki64 supported beginning with version 8.0 */ - - if (_fseeki64(handleTable[handle].fileptr, (OFF_T) offset, 0) != 0) - return(SEEK_ERROR); - -#elif _FILE_OFFSET_BITS - 0 == 64 - - if (fseeko(handleTable[handle].fileptr, (OFF_T) offset, 0) != 0) - return(SEEK_ERROR); - -#else - - if (fseek(handleTable[handle].fileptr, (OFF_T) offset, 0) != 0) - return(SEEK_ERROR); - -#endif - - handleTable[handle].currentpos = offset; - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_read(int hdl, void *buffer, long nbytes) -/* - read bytes from the current position in the file -*/ -{ - long nread; - char *cptr; - - if (handleTable[hdl].last_io_op == IO_WRITE) - { - if (file_seek(hdl, handleTable[hdl].currentpos)) - return(SEEK_ERROR); - } - - nread = (long) fread(buffer, 1, nbytes, handleTable[hdl].fileptr); - - if (nread == 1) - { - cptr = (char *) buffer; - - /* some editors will add a single end-of-file character to a file */ - /* Ignore it if the character is a zero, 10, or 32 */ - if (*cptr == 0 || *cptr == 10 || *cptr == 32) - return(END_OF_FILE); - else - return(READ_ERROR); - } - else if (nread != nbytes) - { - return(READ_ERROR); - } - - handleTable[hdl].currentpos += nbytes; - handleTable[hdl].last_io_op = IO_READ; - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_write(int hdl, void *buffer, long nbytes) -/* - write bytes at the current position in the file -*/ -{ - if (handleTable[hdl].last_io_op == IO_READ) - { - if (file_seek(hdl, handleTable[hdl].currentpos)) - return(SEEK_ERROR); - } - - if((long) fwrite(buffer, 1, nbytes, handleTable[hdl].fileptr) != nbytes) - return(WRITE_ERROR); - - handleTable[hdl].currentpos += nbytes; - handleTable[hdl].last_io_op = IO_WRITE; - return(0); -} -/*--------------------------------------------------------------------------*/ -int file_compress_open(char *filename, int rwmode, int *hdl) -/* - This routine opens the compressed diskfile by creating a new uncompressed - file then opening it. The input file name (the name of the compressed - file) gets replaced with the name of the uncompressed file, which is - initially stored in the global file_outfile string. file_outfile - then gets set to a null string. -*/ -{ - FILE *indiskfile, *outdiskfile; - int status; - char *cptr; - - /* open the compressed disk file */ - status = file_openfile(filename, READONLY, &indiskfile); - if (status) - { - ffpmsg("failed to open compressed disk file (file_compress_open)"); - ffpmsg(filename); - return(status); - } - - /* name of the output uncompressed file is stored in the */ - /* global variable called 'file_outfile'. */ - - cptr = file_outfile; - if (*cptr == '!') - { - /* clobber any existing file with the same name */ - cptr++; - remove(cptr); - } - else - { - outdiskfile = fopen(file_outfile, "r"); /* does file already exist? */ - - if (outdiskfile) - { - ffpmsg("uncompressed file already exists: (file_compress_open)"); - ffpmsg(file_outfile); - fclose(outdiskfile); /* close file and exit with error */ - file_outfile[0] = '\0'; - return(FILE_NOT_CREATED); - } - } - - outdiskfile = fopen(cptr, "w+b"); /* create new file */ - if (!outdiskfile) - { - ffpmsg("could not create uncompressed file: (file_compress_open)"); - ffpmsg(file_outfile); - file_outfile[0] = '\0'; - return(FILE_NOT_CREATED); - } - - /* uncompress file into another file */ - uncompress2file(filename, indiskfile, outdiskfile, &status); - fclose(indiskfile); - fclose(outdiskfile); - - if (status) - { - ffpmsg("error in file_compress_open: failed to uncompressed file:"); - ffpmsg(filename); - ffpmsg(" into new output file:"); - ffpmsg(file_outfile); - file_outfile[0] = '\0'; - return(status); - } - - strcpy(filename, cptr); /* switch the names */ - file_outfile[0] = '\0'; - - status = file_open(filename, rwmode, hdl); - - return(status); -} -/*--------------------------------------------------------------------------*/ -int file_is_compressed(char *filename) /* I - FITS file name */ -/* - Test if the disk file is compressed. Returns 1 if compressed, 0 if not. - This may modify the filename string by appending a compression suffex. -*/ -{ - FILE *diskfile; - unsigned char buffer[2]; - char tmpfilename[FLEN_FILENAME]; - - /* Open file. Try various suffix combinations */ - if (file_openfile(filename, 0, &diskfile)) - { - if (strlen(filename) > FLEN_FILENAME - 1) - return(0); - - strcpy(tmpfilename,filename); - strcat(filename,".gz"); - if (file_openfile(filename, 0, &diskfile)) - { -#if HAVE_BZIP2 - strcpy(tmpfilename,filename); - strcat(filename,".bz2"); - if (file_openfile(filename, 0, &diskfile)) - { -#endif - strcpy(filename, tmpfilename); - strcat(filename,".Z"); - if (file_openfile(filename, 0, &diskfile)) - { - strcpy(filename, tmpfilename); - strcat(filename,".z"); /* it's often lower case on CDROMs */ - if (file_openfile(filename, 0, &diskfile)) - { - strcpy(filename, tmpfilename); - strcat(filename,".zip"); - if (file_openfile(filename, 0, &diskfile)) - { - strcpy(filename, tmpfilename); - strcat(filename,"-z"); /* VMS suffix */ - if (file_openfile(filename, 0, &diskfile)) - { - strcpy(filename, tmpfilename); - strcat(filename,"-gz"); /* VMS suffix */ - if (file_openfile(filename, 0, &diskfile)) - { - strcpy(filename,tmpfilename); /* restore original name */ - return(0); /* file not found */ - } - } - } - } - } -#if HAVE_BZIP2 - } -#endif - } - } - - if (fread(buffer, 1, 2, diskfile) != 2) /* read 2 bytes */ - { - fclose(diskfile); /* error reading file so just return */ - return(0); - } - - fclose(diskfile); - - /* see if the 2 bytes have the magic values for a compressed file */ - if ( (memcmp(buffer, "\037\213", 2) == 0) || /* GZIP */ - (memcmp(buffer, "\120\113", 2) == 0) || /* PKZIP */ - (memcmp(buffer, "\037\036", 2) == 0) || /* PACK */ - (memcmp(buffer, "\037\235", 2) == 0) || /* LZW */ -#if HAVE_BZIP2 - (memcmp(buffer, "BZ", 2) == 0) || /* BZip2 */ -#endif - (memcmp(buffer, "\037\240", 2) == 0)) /* LZH */ - { - return(1); /* this is a compressed file */ - } - else - { - return(0); /* not a compressed file */ - } -} -/*--------------------------------------------------------------------------*/ -int file_checkfile (char *urltype, char *infile, char *outfile) -{ - /* special case: if file:// driver, check if the file is compressed */ - if ( file_is_compressed(infile) ) - { - /* if output file has been specified, save the name for future use: */ - /* This is the name of the uncompressed file to be created on disk. */ - if (strlen(outfile)) - { - if (!strncmp(outfile, "mem:", 4) ) - { - /* uncompress the file in memory, with READ and WRITE access */ - strcpy(urltype, "compressmem://"); /* use special driver */ - *file_outfile = '\0'; - } - else - { - strcpy(urltype, "compressfile://"); /* use special driver */ - - /* don't copy the "file://" prefix, if present. */ - if (!strncmp(outfile, "file://", 7) ) - strcpy(file_outfile,outfile+7); - else - strcpy(file_outfile,outfile); - } - } - else - { - /* uncompress the file in memory */ - strcpy(urltype, "compress://"); /* use special driver */ - *file_outfile = '\0'; /* no output file was specified */ - } - } - else /* an ordinary, uncompressed FITS file on disk */ - { - /* save the output file name for later use when opening the file. */ - /* In this case, the file to be opened will be opened READONLY, */ - /* and copied to this newly created output file. The original file */ - /* will be closed, and the copy will be opened by CFITSIO for */ - /* subsequent processing (possibly with READWRITE access). */ - if (strlen(outfile)) { - file_outfile[0] = '\0'; - strncat(file_outfile,outfile,FLEN_FILENAME-1); - } - } - - return 0; -} -/**********************************************************************/ -/**********************************************************************/ -/**********************************************************************/ - -/**** driver routines for stream//: device (stdin or stdout) ********/ - - -/*--------------------------------------------------------------------------*/ -int stream_open(char *filename, int rwmode, int *handle) -{ - /* - read from stdin - */ - if (filename) - rwmode = 1; /* dummy statement to suppress unused parameter compiler warning */ - - *handle = 1; /* 1 = stdin */ - - return(0); -} -/*--------------------------------------------------------------------------*/ -int stream_create(char *filename, int *handle) -{ - /* - write to stdout - */ - - if (filename) /* dummy statement to suppress unused parameter compiler warning */ - *handle = 2; - else - *handle = 2; /* 2 = stdout */ - - return(0); -} -/*--------------------------------------------------------------------------*/ -int stream_size(int handle, LONGLONG *filesize) -/* - return the size of the file in bytes -*/ -{ - handle = 0; /* suppress unused parameter compiler warning */ - - /* this operation is not supported in a stream; return large value */ - *filesize = LONG_MAX; - return(0); -} -/*--------------------------------------------------------------------------*/ -int stream_close(int handle) -/* - don't have to close stdin or stdout -*/ -{ - handle = 0; /* suppress unused parameter compiler warning */ - - return(0); -} -/*--------------------------------------------------------------------------*/ -int stream_flush(int handle) -/* - flush the file -*/ -{ - if (handle == 2) - fflush(stdout); - - return(0); -} -/*--------------------------------------------------------------------------*/ -int stream_seek(int handle, LONGLONG offset) - /* - seeking is not allowed in a stream - */ -{ - offset = handle; /* suppress unused parameter compiler warning */ - return(1); -} -/*--------------------------------------------------------------------------*/ -int stream_read(int hdl, void *buffer, long nbytes) -/* - reading from stdin stream -*/ - -{ - long nread; - - if (hdl != 1) - return(1); /* can only read from stdin */ - - nread = (long) fread(buffer, 1, nbytes, stdin); - - if (nread != nbytes) - { -/* return(READ_ERROR); */ - return(END_OF_FILE); - } - - return(0); -} -/*--------------------------------------------------------------------------*/ -int stream_write(int hdl, void *buffer, long nbytes) -/* - write bytes at the current position in the file -*/ -{ - if (hdl != 2) - return(1); /* can only write to stdout */ - - if((long) fwrite(buffer, 1, nbytes, stdout) != nbytes) - return(WRITE_ERROR); - - return(0); -} - - - - diff --git a/src/external/OpenGR/3rdparty/cfitsio/drvrgsiftp.c b/src/external/OpenGR/3rdparty/cfitsio/drvrgsiftp.c deleted file mode 100644 index ab9aaed4e..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/drvrgsiftp.c +++ /dev/null @@ -1,522 +0,0 @@ - -/* This file, drvrgsiftp.c contains driver routines for gsiftp files. */ -/* Andrea Barisani */ -/* Taffoni Giuliano */ -#ifdef HAVE_NET_SERVICES -#ifdef HAVE_GSIFTP - -#include -#include -#include -#include -#include -#include "fitsio2.h" - -#include - -#define MAXLEN 1200 -#define NETTIMEOUT 80 -#define MAX_BUFFER_SIZE_R 1024 -#define MAX_BUFFER_SIZE_W (64*1024) - -static int gsiftpopen = 0; -static int global_offset = 0; -static int gsiftp_get(char *filename, FILE **gsiftpfile, int num_streams); - -static globus_mutex_t lock; -static globus_cond_t cond; -static globus_bool_t done; - -static char *gsiftp_tmpfile; -static char *gsiftpurl = NULL; -static char gsiftp_tmpdir[MAXLEN]; - -static jmp_buf env; /* holds the jump buffer for setjmp/longjmp pairs */ -static void signal_handler(int sig); - -int gsiftp_init(void) -{ - - if (getenv("GSIFTP_TMPFILE")) { - gsiftp_tmpfile = getenv("GSIFTP_TMPFILE"); - } else { - strncpy(gsiftp_tmpdir, "/tmp/gsiftp_XXXXXX", sizeof gsiftp_tmpdir); - if (mkdtemp(gsiftp_tmpdir) == NULL) { - ffpmsg("Cannot create temporary directory!"); - return (FILE_NOT_OPENED); - } - gsiftp_tmpfile = malloc(strlen(gsiftp_tmpdir) + strlen("/gsiftp_buffer.tmp")); - strcat(gsiftp_tmpfile, gsiftp_tmpdir); - strcat(gsiftp_tmpfile, "/gsiftp_buffer.tmp"); - } - - return file_init(); -} - -int gsiftp_shutdown(void) -{ - free(gsiftpurl); - free(gsiftp_tmpfile); - free(gsiftp_tmpdir); - - return file_shutdown(); -} - -int gsiftp_setoptions(int options) -{ - return file_setoptions(options); -} - -int gsiftp_getoptions(int *options) -{ - return file_getoptions(options); -} - -int gsiftp_getversion(int *version) -{ - return file_getversion(version); -} - -int gsiftp_checkfile(char *urltype, char *infile, char *outfile) -{ - return file_checkfile(urltype, infile, outfile); -} - -int gsiftp_open(char *filename, int rwmode, int *handle) -{ - FILE *gsiftpfile; - int num_streams; - - if (getenv("GSIFTP_STREAMS")) { - num_streams = (int)getenv("GSIFTP_STREAMS"); - } else { - num_streams = 1; - } - - if (rwmode) { - gsiftpopen = 2; - } else { - gsiftpopen = 1; - } - - if (gsiftpurl) - free(gsiftpurl); - - gsiftpurl = strdup(filename); - - if (setjmp(env) != 0) { - ffpmsg("Timeout (gsiftp_open)"); - goto error; - } - - signal(SIGALRM, signal_handler); - alarm(NETTIMEOUT); - - if (gsiftp_get(filename,&gsiftpfile,num_streams)) { - alarm(0); - ffpmsg("Unable to open gsiftp file (gsiftp_open)"); - ffpmsg(filename); - goto error; - } - - fclose(gsiftpfile); - - signal(SIGALRM, SIG_DFL); - alarm(0); - - return file_open(gsiftp_tmpfile, rwmode, handle); - - error: - alarm(0); - signal(SIGALRM, SIG_DFL); - return (FILE_NOT_OPENED); -} - -int gsiftp_create(char *filename, int *handle) -{ - if (gsiftpurl) - free(gsiftpurl); - - gsiftpurl = strdup(filename); - - return file_create(gsiftp_tmpfile, handle); -} - -int gsiftp_truncate(int handle, LONGLONG filesize) -{ - return file_truncate(handle, filesize); -} - -int gsiftp_size(int handle, LONGLONG *filesize) -{ - return file_size(handle, filesize); -} - -int gsiftp_flush(int handle) -{ - FILE *gsiftpfile; - int num_streams; - - if (getenv("GSIFTP_STREAMS")) { - num_streams = (int)getenv("GSIFTP_STREAMS"); - } else { - num_streams = 1; - } - - int rc = file_flush(handle); - - if (gsiftpopen != 1) { - - if (setjmp(env) != 0) { - ffpmsg("Timeout (gsiftp_write)"); - goto error; - } - - signal(SIGALRM, signal_handler); - alarm(NETTIMEOUT); - - if (gsiftp_put(gsiftpurl,&gsiftpfile,num_streams)) { - alarm(0); - ffpmsg("Unable to open gsiftp file (gsiftp_flush)"); - ffpmsg(gsiftpurl); - goto error; - } - - fclose(gsiftpfile); - - signal(SIGALRM, SIG_DFL); - alarm(0); - } - - return rc; - - error: - alarm(0); - signal(SIGALRM, SIG_DFL); - return (FILE_NOT_OPENED); -} - -int gsiftp_seek(int handle, LONGLONG offset) -{ - return file_seek(handle, offset); -} - -int gsiftp_read(int hdl, void *buffer, long nbytes) -{ - return file_read(hdl, buffer, nbytes); -} - -int gsiftp_write(int hdl, void *buffer, long nbytes) -{ - return file_write(hdl, buffer, nbytes); -} - -int gsiftp_close(int handle) -{ - unlink(gsiftp_tmpfile); - - if (gsiftp_tmpdir) - rmdir(gsiftp_tmpdir); - - return file_close(handle); -} - -static void done_cb( void * user_arg, - globus_ftp_client_handle_t * handle, - globus_object_t * err) -{ - - if(err){ - fprintf(stderr, "%s", globus_object_printable_to_string(err)); - } - - globus_mutex_lock(&lock); - done = GLOBUS_TRUE; - globus_cond_signal(&cond); - globus_mutex_unlock(&lock); - return; -} - -static void data_cb_read( void * user_arg, - globus_ftp_client_handle_t * handle, - globus_object_t * err, - globus_byte_t * buffer, - globus_size_t length, - globus_off_t offset, - globus_bool_t eof) -{ - if(err) { - fprintf(stderr, "%s", globus_object_printable_to_string(err)); - } - else { - FILE* fd = (FILE*) user_arg; - int rc = fwrite(buffer, 1, length, fd); - if (ferror(fd)) { - printf("Read error in function data_cb_read; errno = %d\n", errno); - return; - } - - if (!eof) { - globus_ftp_client_register_read(handle, - buffer, - MAX_BUFFER_SIZE_R, - data_cb_read, - (void*) fd); - } - } - return; -} - -static void data_cb_write( void * user_arg, - globus_ftp_client_handle_t * handle, - globus_object_t * err, - globus_byte_t * buffer, - globus_size_t length, - globus_off_t offset, - globus_bool_t eof) -{ - int curr_offset; - if(err) { - fprintf(stderr, "%s", globus_object_printable_to_string(err)); - } - else { - if (!eof) { - FILE* fd = (FILE*) user_arg; - int rc; - globus_mutex_lock(&lock); - curr_offset = global_offset; - rc = fread(buffer, 1, MAX_BUFFER_SIZE_W, fd); - global_offset += rc; - globus_mutex_unlock(&lock); - if (ferror(fd)) { - printf("Read error in function data_cb_write; errno = %d\n", errno); - return; - } - - globus_ftp_client_register_write(handle, - buffer, - rc, - curr_offset, - feof(fd) != 0, - data_cb_write, - (void*) fd); - } else { - globus_libc_free(buffer); - } - } - return; -} - -int gsiftp_get(char *filename, FILE **gsiftpfile, int num_streams) -{ - char gsiurl[MAXLEN]; - - globus_ftp_client_handle_t handle; - globus_ftp_client_operationattr_t attr; - globus_ftp_client_handleattr_t handle_attr; - globus_ftp_control_parallelism_t parallelism; - globus_ftp_control_layout_t layout; - globus_byte_t buffer[MAX_BUFFER_SIZE_R]; - globus_size_t buffer_length = sizeof(buffer); - globus_result_t result; - globus_ftp_client_restart_marker_t restart; - globus_ftp_control_type_t filetype; - - globus_module_activate(GLOBUS_FTP_CLIENT_MODULE); - globus_mutex_init(&lock, GLOBUS_NULL); - globus_cond_init(&cond, GLOBUS_NULL); - globus_ftp_client_handle_init(&handle, GLOBUS_NULL); - globus_ftp_client_handleattr_init(&handle_attr); - globus_ftp_client_operationattr_init(&attr); - layout.mode = GLOBUS_FTP_CONTROL_STRIPING_NONE; - globus_ftp_client_restart_marker_init(&restart); - globus_ftp_client_operationattr_set_mode( - &attr, - GLOBUS_FTP_CONTROL_MODE_EXTENDED_BLOCK); - - if (num_streams >= 1) - { - parallelism.mode = GLOBUS_FTP_CONTROL_PARALLELISM_FIXED; - parallelism.fixed.size = num_streams; - - globus_ftp_client_operationattr_set_parallelism( - &attr, - ¶llelism); - } - - globus_ftp_client_operationattr_set_layout(&attr, - &layout); - - filetype = GLOBUS_FTP_CONTROL_TYPE_IMAGE; - globus_ftp_client_operationattr_set_type (&attr, - filetype); - - globus_ftp_client_handle_init(&handle, &handle_attr); - - done = GLOBUS_FALSE; - - strcpy(gsiurl,"gsiftp://"); - strcat(gsiurl,filename); - - *gsiftpfile = fopen(gsiftp_tmpfile,"w+"); - - if (!*gsiftpfile) { - ffpmsg("Unable to open temporary file!"); - return (FILE_NOT_OPENED); - } - - result = globus_ftp_client_get(&handle, - gsiurl, - &attr, - &restart, - done_cb, - 0); - if(result != GLOBUS_SUCCESS) { - globus_object_t * err; - err = globus_error_get(result); - fprintf(stderr, "%s", globus_object_printable_to_string(err)); - done = GLOBUS_TRUE; - } - else { - globus_ftp_client_register_read(&handle, - buffer, - buffer_length, - data_cb_read, - (void*) *gsiftpfile); - } - - globus_mutex_lock(&lock); - - while(!done) { - globus_cond_wait(&cond, &lock); - } - - globus_mutex_unlock(&lock); - globus_ftp_client_handle_destroy(&handle); - globus_module_deactivate_all(); - - return 0; -} - -int gsiftp_put(char *filename, FILE **gsiftpfile, int num_streams) -{ - int i; - char gsiurl[MAXLEN]; - - globus_ftp_client_handle_t handle; - globus_ftp_client_operationattr_t attr; - globus_ftp_client_handleattr_t handle_attr; - globus_ftp_control_parallelism_t parallelism; - globus_ftp_control_layout_t layout; - globus_byte_t * buffer; - globus_size_t buffer_length = sizeof(buffer); - globus_result_t result; - globus_ftp_client_restart_marker_t restart; - globus_ftp_control_type_t filetype; - - globus_module_activate(GLOBUS_FTP_CLIENT_MODULE); - globus_mutex_init(&lock, GLOBUS_NULL); - globus_cond_init(&cond, GLOBUS_NULL); - globus_ftp_client_handle_init(&handle, GLOBUS_NULL); - globus_ftp_client_handleattr_init(&handle_attr); - globus_ftp_client_operationattr_init(&attr); - layout.mode = GLOBUS_FTP_CONTROL_STRIPING_NONE; - globus_ftp_client_restart_marker_init(&restart); - globus_ftp_client_operationattr_set_mode( - &attr, - GLOBUS_FTP_CONTROL_MODE_EXTENDED_BLOCK); - - if (num_streams >= 1) - { - parallelism.mode = GLOBUS_FTP_CONTROL_PARALLELISM_FIXED; - parallelism.fixed.size = num_streams; - - globus_ftp_client_operationattr_set_parallelism( - &attr, - ¶llelism); - } - - globus_ftp_client_operationattr_set_layout(&attr, - &layout); - - filetype = GLOBUS_FTP_CONTROL_TYPE_IMAGE; - globus_ftp_client_operationattr_set_type (&attr, - filetype); - - globus_ftp_client_handle_init(&handle, &handle_attr); - - done = GLOBUS_FALSE; - - strcpy(gsiurl,"gsiftp://"); - strcat(gsiurl,filename); - - *gsiftpfile = fopen(gsiftp_tmpfile,"r"); - - if (!*gsiftpfile) { - ffpmsg("Unable to open temporary file!"); - return (FILE_NOT_OPENED); - } - - result = globus_ftp_client_put(&handle, - gsiurl, - &attr, - &restart, - done_cb, - 0); - if(result != GLOBUS_SUCCESS) { - globus_object_t * err; - err = globus_error_get(result); - fprintf(stderr, "%s", globus_object_printable_to_string(err)); - done = GLOBUS_TRUE; - } - else { - int rc; - int curr_offset; - - for (i = 0; i< 2 * num_streams && feof(*gsiftpfile) == 0; i++) - { - buffer = malloc(MAX_BUFFER_SIZE_W); - globus_mutex_lock(&lock); - curr_offset = global_offset; - rc = fread(buffer, 1, MAX_BUFFER_SIZE_W, *gsiftpfile); - global_offset += rc; - globus_mutex_unlock(&lock); - globus_ftp_client_register_write( - &handle, - buffer, - rc, - curr_offset, - feof(*gsiftpfile) != 0, - data_cb_write, - (void*) *gsiftpfile); - } - } - - globus_mutex_lock(&lock); - - while(!done) { - globus_cond_wait(&cond, &lock); - } - - globus_mutex_unlock(&lock); - globus_ftp_client_handle_destroy(&handle); - globus_module_deactivate_all(); - - return 0; -} - -static void signal_handler(int sig) { - - switch (sig) { - case SIGALRM: /* process for alarm */ - longjmp(env,sig); - - default: { - /* Hmm, shouldn't have happend */ - exit(sig); - } - } -} - -#endif -#endif diff --git a/src/external/OpenGR/3rdparty/cfitsio/drvrgsiftp.h b/src/external/OpenGR/3rdparty/cfitsio/drvrgsiftp.h deleted file mode 100644 index bd0ec0d4a..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/drvrgsiftp.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _GSIFTP_H -#define _GSIFTP_H - -int gsiftp_init(void); -int gsiftp_setoptions(int options); -int gsiftp_getoptions(int *options); -int gsiftp_getversion(int *version); -int gsiftp_shutdown(void); -int gsiftp_checkfile(char *urltype, char *infile, char *outfile); -int gsiftp_open(char *filename, int rwmode, int *driverhandle); -int gsiftp_create(char *filename, int *driverhandle); -int gsiftp_truncate(int driverhandle, LONGLONG filesize); -int gsiftp_size(int driverhandle, LONGLONG *filesize); -int gsiftp_close(int driverhandle); -int gsiftp_remove(char *filename); -int gsiftp_flush(int driverhandle); -int gsiftp_seek(int driverhandle, LONGLONG offset); -int gsiftp_read (int driverhandle, void *buffer, long nbytes); -int gsiftp_write(int driverhandle, void *buffer, long nbytes); - -#endif diff --git a/src/external/OpenGR/3rdparty/cfitsio/drvrmem.c b/src/external/OpenGR/3rdparty/cfitsio/drvrmem.c deleted file mode 100644 index 371e62066..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/drvrmem.c +++ /dev/null @@ -1,1301 +0,0 @@ -/* This file, drvrmem.c, contains driver routines for memory files. */ - -/* The FITSIO software was written by William Pence at the High Energy */ -/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ -/* Goddard Space Flight Center. */ - -#include -#include -#include /* apparently needed to define size_t */ -#include "fitsio2.h" - -#if HAVE_BZIP2 -#include "bzlib.h" -#endif - -/* prototype for .Z file uncompression function in zuncompress.c */ -int zuncompress2mem(char *filename, - FILE *diskfile, - char **buffptr, - size_t *buffsize, - void *(*mem_realloc)(void *p, size_t newsize), - size_t *filesize, - int *status); - -#if HAVE_BZIP2 -/* prototype for .bz2 uncompression function (in this file) */ -void bzip2uncompress2mem(char *filename, FILE *diskfile, int hdl, - size_t* filesize, int* status); -#endif - - -#define RECBUFLEN 1000 - -static char stdin_outfile[FLEN_FILENAME]; - -typedef struct /* structure containing mem file structure */ -{ - char **memaddrptr; /* Pointer to memory address pointer; */ - /* This may or may not point to memaddr. */ - char *memaddr; /* Pointer to starting memory address; may */ - /* not always be used, so use *memaddrptr instead */ - size_t *memsizeptr; /* Pointer to the size of the memory allocation. */ - /* This may or may not point to memsize. */ - size_t memsize; /* Size of the memory allocation; this may not */ - /* always be used, so use *memsizeptr instead. */ - size_t deltasize; /* Suggested increment for reallocating memory */ - void *(*mem_realloc)(void *p, size_t newsize); /* realloc function */ - LONGLONG currentpos; /* current file position, relative to start */ - LONGLONG fitsfilesize; /* size of the FITS file (always <= *memsizeptr) */ - FILE *fileptr; /* pointer to compressed output disk file */ -} memdriver; - -static memdriver memTable[NMAXFILES]; /* allocate mem file handle tables */ - -/*--------------------------------------------------------------------------*/ -int mem_init(void) -{ - int ii; - - for (ii = 0; ii < NMAXFILES; ii++) /* initialize all empty slots in table */ - { - memTable[ii].memaddrptr = 0; - memTable[ii].memaddr = 0; - } - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_setoptions(int options) -{ - /* do something with the options argument, to stop compiler warning */ - options = 0; - return(options); -} -/*--------------------------------------------------------------------------*/ -int mem_getoptions(int *options) -{ - *options = 0; - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_getversion(int *version) -{ - *version = 10; - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_shutdown(void) -{ - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_create(char *filename, int *handle) -/* - Create a new empty memory file for subsequent writes. - The file name is ignored in this case. -*/ -{ - int status; - - /* initially allocate 1 FITS block = 2880 bytes */ - status = mem_createmem(2880L, handle); - - if (status) - { - ffpmsg("failed to create empty memory file (mem_create)"); - return(status); - } - - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_create_comp(char *filename, int *handle) -/* - Create a new empty memory file for subsequent writes. - Also create an empty compressed .gz file. The memory file - will be compressed and written to the disk file when the file is closed. -*/ -{ - FILE *diskfile; - char mode[4]; - int status; - - /* first, create disk file for the compressed output */ - - - if ( !strcmp(filename, "-.gz") || !strcmp(filename, "stdout.gz") || - !strcmp(filename, "STDOUT.gz") ) - { - /* special case: create uncompressed FITS file in memory, then - compress it an write it out to 'stdout' when it is closed. */ - - diskfile = stdout; - } - else - { - /* normal case: create disk file for the compressed output */ - - strcpy(mode, "w+b"); /* create file with read-write */ - - diskfile = fopen(filename, "r"); /* does file already exist? */ - - if (diskfile) - { - fclose(diskfile); /* close file and exit with error */ - return(FILE_NOT_CREATED); - } - -#if MACHINE == ALPHAVMS || MACHINE == VAXVMS - /* specify VMS record structure: fixed format, 2880 byte records */ - /* but force stream mode access to enable random I/O access */ - diskfile = fopen(filename, mode, "rfm=fix", "mrs=2880", "ctx=stm"); -#else - diskfile = fopen(filename, mode); -#endif - - if (!(diskfile)) /* couldn't create file */ - { - return(FILE_NOT_CREATED); - } - } - - /* now create temporary memory file */ - - /* initially allocate 1 FITS block = 2880 bytes */ - status = mem_createmem(2880L, handle); - - if (status) - { - ffpmsg("failed to create empty memory file (mem_create_comp)"); - return(status); - } - - memTable[*handle].fileptr = diskfile; - - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_openmem(void **buffptr, /* I - address of memory pointer */ - size_t *buffsize, /* I - size of buffer, in bytes */ - size_t deltasize, /* I - increment for future realloc's */ - void *(*memrealloc)(void *p, size_t newsize), /* function */ - int *handle) -/* - lowest level routine to open a pre-existing memory file. -*/ -{ - int ii; - - *handle = -1; - for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in handle table */ - { - if (memTable[ii].memaddrptr == 0) - { - *handle = ii; - break; - } - } - if (*handle == -1) - return(TOO_MANY_FILES); /* too many files opened */ - - memTable[ii].memaddrptr = (char **) buffptr; /* pointer to start addres */ - memTable[ii].memsizeptr = buffsize; /* allocated size of memory */ - memTable[ii].deltasize = deltasize; /* suggested realloc increment */ - memTable[ii].fitsfilesize = *buffsize; /* size of FITS file (upper limit) */ - memTable[ii].currentpos = 0; /* at beginning of the file */ - memTable[ii].mem_realloc = memrealloc; /* memory realloc function */ - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_createmem(size_t msize, int *handle) -/* - lowest level routine to allocate a memory file. -*/ -{ - int ii; - - *handle = -1; - for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in handle table */ - { - if (memTable[ii].memaddrptr == 0) - { - *handle = ii; - break; - } - } - if (*handle == -1) - return(TOO_MANY_FILES); /* too many files opened */ - - /* use the internally allocated memaddr and memsize variables */ - memTable[ii].memaddrptr = &memTable[ii].memaddr; - memTable[ii].memsizeptr = &memTable[ii].memsize; - - /* allocate initial block of memory for the file */ - if (msize > 0) - { - memTable[ii].memaddr = (char *) malloc(msize); - if ( !(memTable[ii].memaddr) ) - { - ffpmsg("malloc of initial memory failed (mem_createmem)"); - return(FILE_NOT_OPENED); - } - } - - /* set initial state of the file */ - memTable[ii].memsize = msize; - memTable[ii].deltasize = 2880; - memTable[ii].fitsfilesize = 0; - memTable[ii].currentpos = 0; - memTable[ii].mem_realloc = realloc; - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_truncate(int handle, LONGLONG filesize) -/* - truncate the file to a new size -*/ -{ - char *ptr; - - /* call the memory reallocation function, if defined */ - if ( memTable[handle].mem_realloc ) - { /* explicit LONGLONG->size_t cast */ - ptr = (memTable[handle].mem_realloc)( - *(memTable[handle].memaddrptr), - (size_t) filesize); - if (!ptr) - { - ffpmsg("Failed to reallocate memory (mem_truncate)"); - return(MEMORY_ALLOCATION); - } - - /* if allocated more memory, initialize it to zero */ - if ( filesize > *(memTable[handle].memsizeptr) ) - { - memset(ptr + *(memTable[handle].memsizeptr), - 0, - ((size_t) filesize) - *(memTable[handle].memsizeptr) ); - } - - *(memTable[handle].memaddrptr) = ptr; - *(memTable[handle].memsizeptr) = (size_t) (filesize); - } - - memTable[handle].currentpos = filesize; - memTable[handle].fitsfilesize = filesize; - return(0); -} -/*--------------------------------------------------------------------------*/ -int stdin_checkfile(char *urltype, char *infile, char *outfile) -/* - do any special case checking when opening a file on the stdin stream -*/ -{ - if (strlen(outfile)) - { - stdin_outfile[0] = '\0'; - strncat(stdin_outfile,outfile,FLEN_FILENAME-1); /* an output file is specified */ - strcpy(urltype,"stdinfile://"); - } - else - *stdin_outfile = '\0'; /* no output file was specified */ - - return(0); -} -/*--------------------------------------------------------------------------*/ -int stdin_open(char *filename, int rwmode, int *handle) -/* - open a FITS file from the stdin file stream by copying it into memory - The file name is ignored in this case. -*/ -{ - int status; - char cbuff; - - if (*stdin_outfile) - { - /* copy the stdin stream to the specified disk file then open the file */ - - /* Create the output file */ - status = file_create(stdin_outfile,handle); - - if (status) - { - ffpmsg("Unable to create output file to copy stdin (stdin_open):"); - ffpmsg(stdin_outfile); - return(status); - } - - /* copy the whole stdin stream to the file */ - status = stdin2file(*handle); - file_close(*handle); - - if (status) - { - ffpmsg("failed to copy stdin to file (stdin_open)"); - ffpmsg(stdin_outfile); - return(status); - } - - /* reopen file with proper rwmode attribute */ - status = file_open(stdin_outfile, rwmode, handle); - } - else - { - - /* get the first character, then put it back */ - cbuff = fgetc(stdin); - ungetc(cbuff, stdin); - - /* compressed files begin with 037 or 'P' */ - if (cbuff == 31 || cbuff == 75) - { - /* looks like the input stream is compressed */ - status = mem_compress_stdin_open(filename, rwmode, handle); - - } - else - { - /* copy the stdin stream into memory then open file in memory */ - - if (rwmode != READONLY) - { - ffpmsg("cannot open stdin with WRITE access"); - return(READONLY_FILE); - } - - status = mem_createmem(2880L, handle); - - if (status) - { - ffpmsg("failed to create empty memory file (stdin_open)"); - return(status); - } - - /* copy the whole stdin stream into memory */ - status = stdin2mem(*handle); - - if (status) - { - ffpmsg("failed to copy stdin into memory (stdin_open)"); - free(memTable[*handle].memaddr); - } - } - } - - return(status); -} -/*--------------------------------------------------------------------------*/ -int stdin2mem(int hd) /* handle number */ -/* - Copy the stdin stream into memory. Fill whatever amount of memory - has already been allocated, then realloc more memory if necessary. -*/ -{ - size_t nread, memsize, delta; - LONGLONG filesize; - char *memptr; - char simple[] = "SIMPLE"; - int c, ii, jj; - - memptr = *memTable[hd].memaddrptr; - memsize = *memTable[hd].memsizeptr; - delta = memTable[hd].deltasize; - - filesize = 0; - ii = 0; - - for(jj = 0; (c = fgetc(stdin)) != EOF && jj < 2000; jj++) - { - /* Skip over any garbage at the beginning of the stdin stream by */ - /* reading 1 char at a time, looking for 'S', 'I', 'M', 'P', 'L', 'E' */ - /* Give up if not found in the first 2000 characters */ - - if (c == simple[ii]) - { - ii++; - if (ii == 6) /* found the complete string? */ - { - memcpy(memptr, simple, 6); /* copy "SIMPLE" to buffer */ - filesize = 6; - break; - } - } - else - ii = 0; /* reset search to beginning of the string */ - } - - if (filesize == 0) - { - ffpmsg("Couldn't find the string 'SIMPLE' in the stdin stream."); - ffpmsg("This does not look like a FITS file."); - return(FILE_NOT_OPENED); - } - - /* fill up the remainder of the initial memory allocation */ - nread = fread(memptr + 6, 1, memsize - 6, stdin); - nread += 6; /* add in the 6 characters in 'SIMPLE' */ - - if (nread < memsize) /* reached the end? */ - { - memTable[hd].fitsfilesize = nread; - return(0); - } - - filesize = nread; - - while (1) - { - /* allocate memory for another FITS block */ - memptr = realloc(memptr, memsize + delta); - - if (!memptr) - { - ffpmsg("realloc failed while copying stdin (stdin2mem)"); - return(MEMORY_ALLOCATION); - } - memsize += delta; - - /* read another FITS block */ - nread = fread(memptr + filesize, 1, delta, stdin); - - filesize += nread; - - if (nread < delta) /* reached the end? */ - break; - } - - memTable[hd].fitsfilesize = filesize; - *memTable[hd].memaddrptr = memptr; - *memTable[hd].memsizeptr = memsize; - - return(0); -} -/*--------------------------------------------------------------------------*/ -int stdin2file(int handle) /* handle number */ -/* - Copy the stdin stream to a file. . -*/ -{ - size_t nread; - char simple[] = "SIMPLE"; - int c, ii, jj, status; - char recbuf[RECBUFLEN]; - - ii = 0; - for(jj = 0; (c = fgetc(stdin)) != EOF && jj < 2000; jj++) - { - /* Skip over any garbage at the beginning of the stdin stream by */ - /* reading 1 char at a time, looking for 'S', 'I', 'M', 'P', 'L', 'E' */ - /* Give up if not found in the first 2000 characters */ - - if (c == simple[ii]) - { - ii++; - if (ii == 6) /* found the complete string? */ - { - memcpy(recbuf, simple, 6); /* copy "SIMPLE" to buffer */ - break; - } - } - else - ii = 0; /* reset search to beginning of the string */ - } - - if (ii != 6) - { - ffpmsg("Couldn't find the string 'SIMPLE' in the stdin stream"); - return(FILE_NOT_OPENED); - } - - /* fill up the remainder of the buffer */ - nread = fread(recbuf + 6, 1, RECBUFLEN - 6, stdin); - nread += 6; /* add in the 6 characters in 'SIMPLE' */ - - status = file_write(handle, recbuf, nread); - if (status) - return(status); - - /* copy the rest of stdin stream */ - while(0 != (nread = fread(recbuf,1,RECBUFLEN, stdin))) - { - status = file_write(handle, recbuf, nread); - if (status) - return(status); - } - - return(status); -} -/*--------------------------------------------------------------------------*/ -int stdout_close(int handle) -/* - copy the memory file to stdout, then free the memory -*/ -{ - int status = 0; - - /* copy from memory to standard out. explicit LONGLONG->size_t cast */ - if(fwrite(memTable[handle].memaddr, 1, - ((size_t) memTable[handle].fitsfilesize), stdout) != - (size_t) memTable[handle].fitsfilesize ) - { - ffpmsg("failed to copy memory file to stdout (stdout_close)"); - status = WRITE_ERROR; - } - - free( memTable[handle].memaddr ); /* free the memory */ - memTable[handle].memaddrptr = 0; - memTable[handle].memaddr = 0; - return(status); -} -/*--------------------------------------------------------------------------*/ -int mem_compress_openrw(char *filename, int rwmode, int *hdl) -/* - This routine opens the compressed diskfile and creates an empty memory - buffer with an appropriate size, then calls mem_uncompress2mem. It allows - the memory 'file' to be opened with READWRITE access. -*/ -{ - return(mem_compress_open(filename, READONLY, hdl)); -} -/*--------------------------------------------------------------------------*/ -int mem_compress_open(char *filename, int rwmode, int *hdl) -/* - This routine opens the compressed diskfile and creates an empty memory - buffer with an appropriate size, then calls mem_uncompress2mem. -*/ -{ - FILE *diskfile; - int status, estimated = 1; - unsigned char buffer[4]; - size_t finalsize, filesize; - LONGLONG llsize = 0; - unsigned int modulosize; - char *ptr; - - if (rwmode != READONLY) - { - ffpmsg( - "cannot open compressed file with WRITE access (mem_compress_open)"); - ffpmsg(filename); - return(READONLY_FILE); - } - - /* open the compressed disk file */ - status = file_openfile(filename, READONLY, &diskfile); - if (status) - { - ffpmsg("failed to open compressed disk file (compress_open)"); - ffpmsg(filename); - return(status); - } - - if (fread(buffer, 1, 2, diskfile) != 2) /* read 2 bytes */ - { - fclose(diskfile); - return(READ_ERROR); - } - - if (memcmp(buffer, "\037\213", 2) == 0) /* GZIP */ - { - /* the uncompressed file size is give at the end */ - /* of the file in the ISIZE field (modulo 2^32) */ - - fseek(diskfile, 0, 2); /* move to end of file */ - filesize = ftell(diskfile); /* position = size of file */ - fseek(diskfile, -4L, 1); /* move back 4 bytes */ - fread(buffer, 1, 4L, diskfile); /* read 4 bytes */ - - /* have to worry about integer byte order */ - modulosize = buffer[0]; - modulosize |= buffer[1] << 8; - modulosize |= buffer[2] << 16; - modulosize |= buffer[3] << 24; - -/* - the field ISIZE in the gzipped file header only stores 4 bytes and contains - the uncompressed file size modulo 2^32. If the uncompressed file size - is less than the compressed file size (filesize), then one probably needs to - add 2^32 = 4294967296 to the uncompressed file size, assuming that the gzip - produces a compressed file that is smaller than the original file. - - But one must allow for the case of very small files, where the - gzipped file may actually be larger then the original uncompressed file. - Therefore, only perform the modulo 2^32 correction test if the compressed - file is greater than 10,000 bytes in size. (Note: this threhold would - fail only if the original file was greater than 2^32 bytes in size AND gzip - was able to compress it by more than a factor of 400,000 (!) which seems - highly unlikely.) - - Also, obviously, this 2^32 modulo correction cannot be performed if the - finalsize variable is only 32-bits long. Typically, the 'size_t' integer - type must be 8 bytes or larger in size to support data files that are - greater than 2 GB (2^31 bytes) in size. -*/ - finalsize = modulosize; - - if (sizeof(size_t) > 4 && filesize > 10000) { - llsize = (LONGLONG) finalsize; - /* use LONGLONG variable to suppress compiler warning */ - while (llsize < (LONGLONG) filesize) llsize += 4294967296; - - finalsize = (size_t) llsize; - } - - estimated = 0; /* file size is known, not estimated */ - } - else if (memcmp(buffer, "\120\113", 2) == 0) /* PKZIP */ - { - /* the uncompressed file size is give at byte 22 the file */ - - fseek(diskfile, 22L, 0); /* move to byte 22 */ - fread(buffer, 1, 4L, diskfile); /* read 4 bytes */ - - /* have to worry about integer byte order */ - modulosize = buffer[0]; - modulosize |= buffer[1] << 8; - modulosize |= buffer[2] << 16; - modulosize |= buffer[3] << 24; - finalsize = modulosize; - - estimated = 0; /* file size is known, not estimated */ - } - else if (memcmp(buffer, "\037\036", 2) == 0) /* PACK */ - finalsize = 0; /* for most methods we can't determine final size */ - else if (memcmp(buffer, "\037\235", 2) == 0) /* LZW */ - finalsize = 0; /* for most methods we can't determine final size */ - else if (memcmp(buffer, "\037\240", 2) == 0) /* LZH */ - finalsize = 0; /* for most methods we can't determine final size */ -#if HAVE_BZIP2 - else if (memcmp(buffer, "BZ", 2) == 0) /* BZip2 */ - finalsize = 0; /* for most methods we can't determine final size */ -#endif - else - { - /* not a compressed file; this should never happen */ - fclose(diskfile); - return(1); - } - - if (finalsize == 0) /* estimate uncompressed file size */ - { - fseek(diskfile, 0, 2); /* move to end of the compressed file */ - finalsize = ftell(diskfile); /* position = size of file */ - finalsize = finalsize * 3; /* assume factor of 3 compression */ - } - - fseek(diskfile, 0, 0); /* move back to beginning of file */ - - /* create a memory file big enough (hopefully) for the uncompressed file */ - status = mem_createmem(finalsize, hdl); - - if (status && estimated) - { - /* memory allocation failed, so try a smaller estimated size */ - finalsize = finalsize / 3; - status = mem_createmem(finalsize, hdl); - } - - if (status) - { - fclose(diskfile); - ffpmsg("failed to create empty memory file (compress_open)"); - return(status); - } - - /* uncompress file into memory */ - status = mem_uncompress2mem(filename, diskfile, *hdl); - - fclose(diskfile); - - if (status) - { - mem_close_free(*hdl); /* free up the memory */ - ffpmsg("failed to uncompress file into memory (compress_open)"); - return(status); - } - - /* if we allocated too much memory initially, then free it */ - if (*(memTable[*hdl].memsizeptr) > - (( (size_t) memTable[*hdl].fitsfilesize) + 256L) ) - { - ptr = realloc(*(memTable[*hdl].memaddrptr), - ((size_t) memTable[*hdl].fitsfilesize) ); - if (!ptr) - { - ffpmsg("Failed to reduce size of allocated memory (compress_open)"); - return(MEMORY_ALLOCATION); - } - - *(memTable[*hdl].memaddrptr) = ptr; - *(memTable[*hdl].memsizeptr) = (size_t) (memTable[*hdl].fitsfilesize); - } - - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_compress_stdin_open(char *filename, int rwmode, int *hdl) -/* - This routine reads the compressed input stream and creates an empty memory - buffer, then calls mem_uncompress2mem. -*/ -{ - int status; - char *ptr; - - if (rwmode != READONLY) - { - ffpmsg( - "cannot open compressed input stream with WRITE access (mem_compress_stdin_open)"); - return(READONLY_FILE); - } - - /* create a memory file for the uncompressed file */ - status = mem_createmem(28800, hdl); - - if (status) - { - ffpmsg("failed to create empty memory file (compress_stdin_open)"); - return(status); - } - - /* uncompress file into memory */ - status = mem_uncompress2mem(filename, stdin, *hdl); - - if (status) - { - mem_close_free(*hdl); /* free up the memory */ - ffpmsg("failed to uncompress stdin into memory (compress_stdin_open)"); - return(status); - } - - /* if we allocated too much memory initially, then free it */ - if (*(memTable[*hdl].memsizeptr) > - (( (size_t) memTable[*hdl].fitsfilesize) + 256L) ) - { - ptr = realloc(*(memTable[*hdl].memaddrptr), - ((size_t) memTable[*hdl].fitsfilesize) ); - if (!ptr) - { - ffpmsg("Failed to reduce size of allocated memory (compress_stdin_open)"); - return(MEMORY_ALLOCATION); - } - - *(memTable[*hdl].memaddrptr) = ptr; - *(memTable[*hdl].memsizeptr) = (size_t) (memTable[*hdl].fitsfilesize); - } - - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_iraf_open(char *filename, int rwmode, int *hdl) -/* - This routine creates an empty memory buffer, then calls iraf2mem to - open the IRAF disk file and convert it to a FITS file in memeory. -*/ -{ - int status; - size_t filesize = 0; - - /* create a memory file with size = 0 for the FITS converted IRAF file */ - status = mem_createmem(filesize, hdl); - if (status) - { - ffpmsg("failed to create empty memory file (mem_iraf_open)"); - return(status); - } - - /* convert the iraf file into a FITS file in memory */ - status = iraf2mem(filename, memTable[*hdl].memaddrptr, - memTable[*hdl].memsizeptr, &filesize, &status); - - if (status) - { - mem_close_free(*hdl); /* free up the memory */ - ffpmsg("failed to convert IRAF file into memory (mem_iraf_open)"); - return(status); - } - - memTable[*hdl].currentpos = 0; /* save starting position */ - memTable[*hdl].fitsfilesize=filesize; /* and initial file size */ - - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_rawfile_open(char *filename, int rwmode, int *hdl) -/* - This routine creates an empty memory buffer, writes a minimal - image header, then copies the image data from the raw file into - memory. It will byteswap the pixel values if the raw array - is in little endian byte order. -*/ -{ - FILE *diskfile; - fitsfile *fptr; - short *sptr; - int status, endian, datatype, bytePerPix, naxis; - long dim[5] = {1,1,1,1,1}, ii, nvals, offset = 0; - size_t filesize = 0, datasize; - char rootfile[FLEN_FILENAME], *cptr = 0, *cptr2 = 0; - void *ptr; - - if (rwmode != READONLY) - { - ffpmsg( - "cannot open raw binary file with WRITE access (mem_rawfile_open)"); - ffpmsg(filename); - return(READONLY_FILE); - } - - cptr = strchr(filename, '['); /* search for opening bracket [ */ - - if (!cptr) - { - ffpmsg("binary file name missing '[' character (mem_rawfile_open)"); - ffpmsg(filename); - return(URL_PARSE_ERROR); - } - - *rootfile = '\0'; - strncat(rootfile, filename, cptr - filename); /* store the rootname */ - - cptr++; - - while (*cptr == ' ') - cptr++; /* skip leading blanks */ - - /* Get the Data Type of the Image */ - - if (*cptr == 'b' || *cptr == 'B') - { - datatype = BYTE_IMG; - bytePerPix = 1; - } - else if (*cptr == 'i' || *cptr == 'I') - { - datatype = SHORT_IMG; - bytePerPix = 2; - } - else if (*cptr == 'u' || *cptr == 'U') - { - datatype = USHORT_IMG; - bytePerPix = 2; - - } - else if (*cptr == 'j' || *cptr == 'J') - { - datatype = LONG_IMG; - bytePerPix = 4; - } - else if (*cptr == 'r' || *cptr == 'R' || *cptr == 'f' || *cptr == 'F') - { - datatype = FLOAT_IMG; - bytePerPix = 4; - } - else if (*cptr == 'd' || *cptr == 'D') - { - datatype = DOUBLE_IMG; - bytePerPix = 8; - } - else - { - ffpmsg("error in raw binary file datatype (mem_rawfile_open)"); - ffpmsg(filename); - return(URL_PARSE_ERROR); - } - - cptr++; - - /* get Endian: Big or Little; default is same as the local machine */ - - if (*cptr == 'b' || *cptr == 'B') - { - endian = 0; - cptr++; - } - else if (*cptr == 'l' || *cptr == 'L') - { - endian = 1; - cptr++; - } - else - endian = BYTESWAPPED; /* byteswapped machines are little endian */ - - /* read each dimension (up to 5) */ - - naxis = 1; - dim[0] = strtol(cptr, &cptr2, 10); - - if (cptr2 && *cptr2 == ',') - { - naxis = 2; - dim[1] = strtol(cptr2+1, &cptr, 10); - - if (cptr && *cptr == ',') - { - naxis = 3; - dim[2] = strtol(cptr+1, &cptr2, 10); - - if (cptr2 && *cptr2 == ',') - { - naxis = 4; - dim[3] = strtol(cptr2+1, &cptr, 10); - - if (cptr && *cptr == ',') - naxis = 5; - dim[4] = strtol(cptr+1, &cptr2, 10); - } - } - } - - cptr = maxvalue(cptr, cptr2); - - if (*cptr == ':') /* read starting offset value */ - offset = strtol(cptr+1, 0, 10); - - nvals = dim[0] * dim[1] * dim[2] * dim[3] * dim[4]; - datasize = nvals * bytePerPix; - filesize = nvals * bytePerPix + 2880; - filesize = ((filesize - 1) / 2880 + 1) * 2880; - - /* open the raw binary disk file */ - status = file_openfile(rootfile, READONLY, &diskfile); - if (status) - { - ffpmsg("failed to open raw binary file (mem_rawfile_open)"); - ffpmsg(rootfile); - return(status); - } - - /* create a memory file with corrct size for the FITS converted raw file */ - status = mem_createmem(filesize, hdl); - if (status) - { - ffpmsg("failed to create memory file (mem_rawfile_open)"); - fclose(diskfile); - return(status); - } - - /* open this piece of memory as a new FITS file */ - ffimem(&fptr, (void **) memTable[*hdl].memaddrptr, &filesize, 0, 0, &status); - - /* write the required header keywords */ - ffcrim(fptr, datatype, naxis, dim, &status); - - /* close the FITS file, but keep the memory allocated */ - ffclos(fptr, &status); - - if (status > 0) - { - ffpmsg("failed to write basic image header (mem_rawfile_open)"); - fclose(diskfile); - mem_close_free(*hdl); /* free up the memory */ - return(status); - } - - if (offset > 0) - fseek(diskfile, offset, 0); /* offset to start of the data */ - - /* read the raw data into memory */ - ptr = *memTable[*hdl].memaddrptr + 2880; - - if (fread((char *) ptr, 1, datasize, diskfile) != datasize) - status = READ_ERROR; - - fclose(diskfile); /* close the raw binary disk file */ - - if (status) - { - mem_close_free(*hdl); /* free up the memory */ - ffpmsg("failed to copy raw file data into memory (mem_rawfile_open)"); - return(status); - } - - if (datatype == USHORT_IMG) /* have to subtract 32768 from each unsigned */ - { /* value to conform to FITS convention. More */ - /* efficient way to do this is to just flip */ - /* the most significant bit. */ - - sptr = (short *) ptr; - - if (endian == BYTESWAPPED) /* working with native format */ - { - for (ii = 0; ii < nvals; ii++, sptr++) - { - *sptr = ( *sptr ) ^ 0x8000; - } - } - else /* pixels are byteswapped WRT the native format */ - { - for (ii = 0; ii < nvals; ii++, sptr++) - { - *sptr = ( *sptr ) ^ 0x80; - } - } - } - - if (endian) /* swap the bytes if array is in little endian byte order */ - { - if (datatype == SHORT_IMG || datatype == USHORT_IMG) - { - ffswap2( (short *) ptr, nvals); - } - else if (datatype == LONG_IMG || datatype == FLOAT_IMG) - { - ffswap4( (INT32BIT *) ptr, nvals); - } - - else if (datatype == DOUBLE_IMG) - { - ffswap8( (double *) ptr, nvals); - } - } - - memTable[*hdl].currentpos = 0; /* save starting position */ - memTable[*hdl].fitsfilesize=filesize; /* and initial file size */ - - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_uncompress2mem(char *filename, FILE *diskfile, int hdl) -{ -/* - lower level routine to uncompress a file into memory. The file - has already been opened and the memory buffer has been allocated. -*/ - - size_t finalsize; - int status; - /* uncompress file into memory */ - status = 0; - - if (strstr(filename, ".Z")) { - zuncompress2mem(filename, diskfile, - memTable[hdl].memaddrptr, /* pointer to memory address */ - memTable[hdl].memsizeptr, /* pointer to size of memory */ - realloc, /* reallocation function */ - &finalsize, &status); /* returned file size nd status*/ -#if HAVE_BZIP2 - } else if (strstr(filename, ".bz2")) { - bzip2uncompress2mem(filename, diskfile, hdl, &finalsize, &status); -#endif - } else { - uncompress2mem(filename, diskfile, - memTable[hdl].memaddrptr, /* pointer to memory address */ - memTable[hdl].memsizeptr, /* pointer to size of memory */ - realloc, /* reallocation function */ - &finalsize, &status); /* returned file size nd status*/ - } - - memTable[hdl].currentpos = 0; /* save starting position */ - memTable[hdl].fitsfilesize=finalsize; /* and initial file size */ - return status; -} -/*--------------------------------------------------------------------------*/ -int mem_size(int handle, LONGLONG *filesize) -/* - return the size of the file; only called when the file is first opened -*/ -{ - *filesize = memTable[handle].fitsfilesize; - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_close_free(int handle) -/* - close the file and free the memory. -*/ -{ - free( *(memTable[handle].memaddrptr) ); - - memTable[handle].memaddrptr = 0; - memTable[handle].memaddr = 0; - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_close_keep(int handle) -/* - close the memory file but do not free the memory. -*/ -{ - memTable[handle].memaddrptr = 0; - memTable[handle].memaddr = 0; - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_close_comp(int handle) -/* - compress the memory file, writing it out to the fileptr (which might - be stdout) -*/ -{ - int status = 0; - size_t compsize; - - /* compress file in memory to a .gz disk file */ - - if(compress2file_from_mem(memTable[handle].memaddr, - (size_t) (memTable[handle].fitsfilesize), - memTable[handle].fileptr, - &compsize, &status ) ) - { - ffpmsg("failed to copy memory file to file (mem_close_comp)"); - status = WRITE_ERROR; - } - - free( memTable[handle].memaddr ); /* free the memory */ - memTable[handle].memaddrptr = 0; - memTable[handle].memaddr = 0; - - /* close the compressed disk file (except if it is 'stdout' */ - if (memTable[handle].fileptr != stdout) - fclose(memTable[handle].fileptr); - - return(status); -} -/*--------------------------------------------------------------------------*/ -int mem_seek(int handle, LONGLONG offset) -/* - seek to position relative to start of the file. -*/ -{ - if (offset > memTable[handle].fitsfilesize ) - return(END_OF_FILE); - - memTable[handle].currentpos = offset; - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_read(int hdl, void *buffer, long nbytes) -/* - read bytes from the current position in the file -*/ -{ - if (memTable[hdl].currentpos + nbytes > memTable[hdl].fitsfilesize) - return(END_OF_FILE); - - memcpy(buffer, - *(memTable[hdl].memaddrptr) + memTable[hdl].currentpos, - nbytes); - - memTable[hdl].currentpos += nbytes; - return(0); -} -/*--------------------------------------------------------------------------*/ -int mem_write(int hdl, void *buffer, long nbytes) -/* - write bytes at the current position in the file -*/ -{ - size_t newsize; - char *ptr; - - if ((size_t) (memTable[hdl].currentpos + nbytes) > - *(memTable[hdl].memsizeptr) ) - { - - if (!(memTable[hdl].mem_realloc)) - { - ffpmsg("realloc function not defined (mem_write)"); - return(WRITE_ERROR); - } - - /* - Attempt to reallocate additional memory: - the memory buffer size is incremented by the larger of: - 1 FITS block (2880 bytes) or - the defined 'deltasize' parameter - */ - - newsize = maxvalue( (size_t) - (((memTable[hdl].currentpos + nbytes - 1) / 2880) + 1) * 2880, - *(memTable[hdl].memsizeptr) + memTable[hdl].deltasize); - - /* call the realloc function */ - ptr = (memTable[hdl].mem_realloc)( - *(memTable[hdl].memaddrptr), - newsize); - if (!ptr) - { - ffpmsg("Failed to reallocate memory (mem_write)"); - return(MEMORY_ALLOCATION); - } - - *(memTable[hdl].memaddrptr) = ptr; - *(memTable[hdl].memsizeptr) = newsize; - } - - /* now copy the bytes from the buffer into memory */ - memcpy( *(memTable[hdl].memaddrptr) + memTable[hdl].currentpos, - buffer, - nbytes); - - memTable[hdl].currentpos += nbytes; - memTable[hdl].fitsfilesize = - maxvalue(memTable[hdl].fitsfilesize, - memTable[hdl].currentpos); - return(0); -} - - -#if HAVE_BZIP2 -void bzip2uncompress2mem(char *filename, FILE *diskfile, int hdl, - size_t* filesize, int* status) { - BZFILE* b; - int bzerror; - char buf[8192]; - size_t total_read = 0; - char* errormsg = NULL; - - *filesize = 0; - *status = 0; - b = BZ2_bzReadOpen(&bzerror, diskfile, 0, 0, NULL, 0); - if (bzerror != BZ_OK) { - BZ2_bzReadClose(&bzerror, b); - if (bzerror == BZ_MEM_ERROR) - ffpmsg("failed to open a bzip2 file: out of memory\n"); - else if (bzerror == BZ_CONFIG_ERROR) - ffpmsg("failed to open a bzip2 file: miscompiled bzip2 library\n"); - else if (bzerror == BZ_IO_ERROR) - ffpmsg("failed to open a bzip2 file: I/O error"); - else - ffpmsg("failed to open a bzip2 file"); - *status = READ_ERROR; - return; - } - bzerror = BZ_OK; - while (bzerror == BZ_OK) { - int nread; - nread = BZ2_bzRead(&bzerror, b, buf, sizeof(buf)); - if (bzerror == BZ_OK || bzerror == BZ_STREAM_END) { - *status = mem_write(hdl, buf, nread); - if (*status) { - BZ2_bzReadClose(&bzerror, b); - if (*status == MEMORY_ALLOCATION) - ffpmsg("Failed to reallocate memory while uncompressing bzip2 file"); - return; - } - total_read += nread; - } else { - if (bzerror == BZ_IO_ERROR) - errormsg = "failed to read bzip2 file: I/O error"; - else if (bzerror == BZ_UNEXPECTED_EOF) - errormsg = "failed to read bzip2 file: unexpected end-of-file"; - else if (bzerror == BZ_DATA_ERROR) - errormsg = "failed to read bzip2 file: data integrity error"; - else if (bzerror == BZ_MEM_ERROR) - errormsg = "failed to read bzip2 file: insufficient memory"; - } - } - BZ2_bzReadClose(&bzerror, b); - if (bzerror != BZ_OK) { - if (errormsg) - ffpmsg(errormsg); - else - ffpmsg("failure closing bzip2 file after reading\n"); - *status = READ_ERROR; - return; - } - *filesize = total_read; -} -#endif diff --git a/src/external/OpenGR/3rdparty/cfitsio/drvrnet.c b/src/external/OpenGR/3rdparty/cfitsio/drvrnet.c deleted file mode 100644 index c9f1faea4..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/drvrnet.c +++ /dev/null @@ -1,2743 +0,0 @@ -/* This file, drvrhttp.c contains driver routines for http, ftp and root - files. */ - -/* This file was written by Bruce O'Neel at the ISDC, Switzerland */ -/* The FITSIO software is maintained by William Pence at the High Energy */ -/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ -/* Goddard Space Flight Center. */ - - -/* Notes on the drivers: - - The ftp driver uses passive mode exclusivly. If your remote system can't - deal with passive mode then it'll fail. Since Netscape Navigator uses - passive mode as well there shouldn't be too many ftp servers which have - problems. - - - The http driver works properly with 301 and 302 redirects. For many more - gory details see http://www.w3c.org/Protocols/rfc2068/rfc2068. The only - catch to the 301/302 redirects is that they have to redirect to another - http:// url. If not, things would have to change a lot in cfitsio and this - was thought to be too difficult. - - Redirects look like - - - - 301 Moved Permanently - -

Moved Permanently

- The document has moved here.

- - - This redirect was from apache 1.2.5 but most of the other servers produce - something very similiar. The parser for the redirects finds the first - anchor tag in the body and goes there. If that wasn't what was intended - by the remote system then hopefully the error stack, which includes notes - about the redirect will help the user fix the problem. - - - - Root protocal doesn't have any real docs, so, the emperical docs are as - follows. - - First, you must use a slightly modified rootd server. The modifications - include implimentation of the stat command which returns the size of the - remote file. Without that it's impossible for cfitsio to work properly - since fitsfiles don't include any information about the size of the files - in the headers. The rootd server closes the connections on any errors, - including reading beyond the end of the file or seeking beyond the end - of the file. The rootd:// driver doesn't reopen a closed connection, if - the connection is closed you're pretty much done. - - The messages are of the form - - - - All binary information is transfered in network format, so use htonl and - ntohl to convert back and forth. - - :== 4 byte length, in network format, the len doesn't include the - length of - :== one of the message opcodes below, 4 bytes, network format - :== depends on opcode - - The response is of the same form with the same opcode sent. Success is - indicated by being 0. - - Root is a NFSish protocol where each read/write includes the byte - offset to read or write to. As a result, seeks will always succeed - in the driver even if they would cause a fatal error when you try - to read because you're beyond the end of the file. - - There is file locking on the host such that you need to possibly - create /usr/tmp/rootdtab on the host system. There is one file per - socket connection, though the rootd daemon can support multiple - files open at once. - - The messages are sent in the following order: - - ROOTD_USER - user name, is the user name, trailing - null is sent though it's not required it seems. A ROOTD_AUTH - message is returned with any sort of error meaning that the user - name is wrong. - - ROOTD_PASS - password, ones complemented, stored in . Once - again the trailing null is sent. Once again a ROOTD_AUTH message is - returned - - ROOTD_OPEN - includes filename and one of - {create|update|read} as the file mode. ~ seems to be dealt with - as the username's login directory. A ROOTD_OPEN message is - returned. - - Once the file is opened any of the following can be sent: - - ROOTD_STAT - file status and size - returns a message where is the file length in bytes - - ROOTD_FLUSH - flushes the file, not sure this has any real effect - on the daemon since the daemon uses open/read/write/close rather - than the buffered fopen/fread/fwrite/fclose. - - ROOTD_GET - on send includes a text message of - offset and length to get. Return is a status message first with a - status value, then, the raw bytes for the length that you - requested. It's an error to seek or read past the end of the file, - and, the rootd daemon exits and won't respond anymore. Ie, don't - do this. - - ROOTD_PUT - on send includes a text message of - offset and length to put. Then send the raw bytes you want to - write. Then recieve a status message - - - When you are finished then you send the message: - - ROOTD_CLOSE - closes the file - - Once the file is closed then the socket is closed. - - -Revision 1.56 2000/01/04 11:58:31 oneel -Updates so that compressed network files are dealt with regardless of -their file names and/or mime types. - -Revision 1.55 2000/01/04 10:52:40 oneel -cfitsio 2.034 - -Revision 1.51 1999/08/10 12:13:40 oneel -Make the http code a bit less picky about the types of files it -uncompresses. Now it also uncompresses files which end in .Z or .gz. - -Revision 1.50 1999/08/04 12:38:46 oneel -Don's 2.0.32 patch with dal 1.3 - -Revision 1.39 1998/12/02 15:31:33 oneel -Updates to drvrnet.c so that less compiler warnings would be -generated. Fixes the signal handling. - -Revision 1.38 1998/11/23 10:03:24 oneel -Added in a useragent string, as suggested by: -Tim Kimball Data Systems Division kimball@stsci.edu 410-338-4417 -Space Telescope Science Institute http://www.stsci.edu/~kimball/ -3700 San Martin Drive http://archive.stsci.edu/ -Baltimore MD 21218 USA http://faxafloi.stsci.edu:4547/ - - - */ - -#ifdef HAVE_NET_SERVICES -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(unix) || defined(__unix__) || defined(__unix) || defined(HAVE_UNISTD_H) -#include -#endif - -#include -#include -#include "fitsio2.h" - -static jmp_buf env; /* holds the jump buffer for setjmp/longjmp pairs */ -static void signal_handler(int sig); - -/* Network routine error codes */ -#define NET_OK 0 -#define NOT_INET_ADDRESS -1000 -#define UNKNOWN_INET_HOST -1001 -#define CONNECTION_ERROR -1002 - -/* Network routine constants */ -#define NET_DEFAULT 0 -#define NET_OOB 1 -#define NET_PEEK 2 - -#define NETTIMEOUT 180 /* in secs */ - -/* local defines and variables */ -#define MAXLEN 1200 -#define SHORTLEN 100 -static char netoutfile[MAXLEN]; - - -#define ROOTD_USER 2000 /*user id follows */ -#define ROOTD_PASS 2001 /*passwd follows */ -#define ROOTD_AUTH 2002 /*authorization status (to client) */ -#define ROOTD_FSTAT 2003 /*filename follows */ -#define ROOTD_OPEN 2004 /*filename follows + mode */ -#define ROOTD_PUT 2005 /*offset, number of bytes and buffer */ -#define ROOTD_GET 2006 /*offset, number of bytes */ -#define ROOTD_FLUSH 2007 /*flush file */ -#define ROOTD_CLOSE 2008 /*close file */ -#define ROOTD_STAT 2009 /*return rootd statistics */ -#define ROOTD_ACK 2010 /*acknowledgement (all OK) */ -#define ROOTD_ERR 2011 /*error code and message follow */ - -typedef struct /* structure containing disk file structure */ -{ - int sock; - LONGLONG currentpos; -} rootdriver; - -static rootdriver handleTable[NMAXFILES]; /* allocate diskfile handle tables */ - -/* static prototypes */ - -static int NET_TcpConnect(char *hostname, int port); -static int NET_SendRaw(int sock, const void *buf, int length, int opt); -static int NET_RecvRaw(int sock, void *buffer, int length); -static int NET_ParseUrl(const char *url, char *proto, char *host, int *port, - char *fn); -static int CreateSocketAddress(struct sockaddr_in *sockaddrPtr, - char *host,int port); -static int ftp_status(FILE *ftp, char *statusstr); -static int http_open_network(char *url, FILE **httpfile, char *contentencoding, - int *contentlength); -static int ftp_open_network(char *url, FILE **ftpfile, FILE **command, - int *sock); - -static int root_send_buffer(int sock, int op, char *buffer, int buflen); -static int root_recv_buffer(int sock, int *op, char *buffer,int buflen); -static int root_openfile(char *filename, char *rwmode, int *sock); -static int encode64(unsigned s_len, char *src, unsigned d_len, char *dst); - -/***************************/ -/* Static variables */ - -static int closehttpfile; -static int closememfile; -static int closefdiskfile; -static int closediskfile; -static int closefile; -static int closeoutfile; -static int closecommandfile; -static int closeftpfile; -static FILE *diskfile; -static FILE *outfile; - -/*--------------------------------------------------------------------------*/ -/* This creates a memory file handle with a copy of the URL in filename. The - file is uncompressed if necessary */ - -int http_open(char *filename, int rwmode, int *handle) -{ - - FILE *httpfile; - char contentencoding[SHORTLEN]; - char newfilename[MAXLEN]; - char errorstr[MAXLEN]; - char recbuf[MAXLEN]; - long len; - int contentlength; - int status; - char firstchar; - - closehttpfile = 0; - closememfile = 0; - - /* don't do r/w files */ - if (rwmode != 0) { - ffpmsg("Can't open http:// type file with READWRITE access"); - ffpmsg(" Specify an outfile for r/w access (http_open)"); - goto error; - } - - /* do the signal handler bits */ - if (setjmp(env) != 0) { - /* feels like the second time */ - /* this means something bad happened */ - ffpmsg("Timeout (http_open)"); - goto error; - } - - (void) signal(SIGALRM, signal_handler); - - /* Open the network connection */ - - /* Does the file have a .Z or .gz in it */ - /* Also, if file has a '?' in it (probably cgi script) */ - if (strstr(filename,".Z") || strstr(filename,".gz") || - strstr(filename,"?")) { - alarm(NETTIMEOUT); - if (http_open_network(filename,&httpfile,contentencoding, - &contentlength)) { - alarm(0); - ffpmsg("Unable to open http file (http_open):"); - ffpmsg(filename); - goto error; - } - } else { - - if (strlen(filename) >= MAXLEN - 4) { - ffpmsg("http file name is too long (http_open)"); - ffpmsg(filename); - goto error; - } - - alarm(NETTIMEOUT); - /* Try the .gz one */ - strcpy(newfilename,filename); - strcat(newfilename,".gz"); - - if (http_open_network(newfilename,&httpfile,contentencoding, - &contentlength)) { - alarm(0); - /* Now the .Z one */ - strcpy(newfilename,filename); - strcat(newfilename,".Z"); - alarm(NETTIMEOUT); - if (http_open_network(newfilename,&httpfile,contentencoding, - &contentlength)) { - alarm(0); - alarm(NETTIMEOUT); - if (http_open_network(filename,&httpfile,contentencoding, - &contentlength)) { - alarm(0); - ffpmsg("Unable to open http file (http_open)"); - ffpmsg(filename); - goto error; - } - } - } - } - - closehttpfile++; - - /* Create the memory file */ - if ((status = mem_create(filename,handle))) { - ffpmsg("Unable to create memory file (http_open)"); - goto error; - } - - closememfile++; - - /* Now, what do we do with the file */ - /* Check to see what the first character is */ - firstchar = fgetc(httpfile); - ungetc(firstchar,httpfile); - if (!strcmp(contentencoding,"x-gzip") || - !strcmp(contentencoding,"x-compress") || - strstr(filename,".gz") || - strstr(filename,".Z") || - ('\037' == firstchar)) { - /* do the compress dance, which is the same as the gzip dance */ - /* Using the cfitsio routine */ - - status = 0; - /* Ok, this is a tough case, let's be arbritary and say 10*NETTIMEOUT, - Given the choices for nettimeout above they'll probaby ^C before, but - it's always worth a shot*/ - - alarm(NETTIMEOUT*10); - status = mem_uncompress2mem(filename, httpfile, *handle); - alarm(0); - if (status) { - ffpmsg("Error writing compressed memory file (http_open)"); - ffpmsg(filename); - goto error; - } - - } else { - /* It's not compressed, bad choice, but we'll copy it anyway */ - if (contentlength % 2880) { - sprintf(errorstr,"Content-Length not a multiple of 2880 (http_open) %d", - contentlength); - ffpmsg(errorstr); - } - - /* write a memory file */ - alarm(NETTIMEOUT); - while(0 != (len = fread(recbuf,1,MAXLEN,httpfile))) { - alarm(0); /* cancel alarm */ - status = mem_write(*handle,recbuf,len); - if (status) { - ffpmsg("Error copying http file into memory (http_open)"); - ffpmsg(filename); - goto error; - } - alarm(NETTIMEOUT); /* rearm the alarm */ - } - } - - fclose(httpfile); - - signal(SIGALRM, SIG_DFL); - alarm(0); - return mem_seek(*handle,0); - - error: - alarm(0); /* clear it */ - if (closehttpfile) { - fclose(httpfile); - } - if (closememfile) { - mem_close_free(*handle); - } - - signal(SIGALRM, SIG_DFL); - return (FILE_NOT_OPENED); -} -/*--------------------------------------------------------------------------*/ -/* This creates a memory file handle with a copy of the URL in filename. The - file must be compressed and is copied (still compressed) to disk first. - The compressed disk file is then uncompressed into memory (READONLY). -*/ - -int http_compress_open(char *url, int rwmode, int *handle) -{ - FILE *httpfile; - char contentencoding[SHORTLEN]; - char recbuf[MAXLEN]; - long len; - int contentlength; - int ii, flen, status; - char firstchar; - - closehttpfile = 0; - closediskfile = 0; - closefdiskfile = 0; - closememfile = 0; - - /* cfileio made a mistake, should set the netoufile first otherwise - we don't know where to write the output file */ - - flen = strlen(netoutfile); - if (!flen) { - ffpmsg - ("Output file not set, shouldn't have happened (http_compress_open)"); - goto error; - } - - if (rwmode != 0) { - ffpmsg("Can't open compressed http:// type file with READWRITE access"); - ffpmsg(" Specify an UNCOMPRESSED outfile (http_compress_open)"); - goto error; - } - /* do the signal handler bits */ - if (setjmp(env) != 0) { - /* feels like the second time */ - /* this means something bad happened */ - ffpmsg("Timeout (http_open)"); - goto error; - } - - signal(SIGALRM, signal_handler); - - /* Open the http connectin */ - alarm(NETTIMEOUT); - if ((status = http_open_network(url,&httpfile,contentencoding, - &contentlength))) { - alarm(0); - ffpmsg("Unable to open http file (http_compress_open)"); - ffpmsg(url); - goto error; - } - - closehttpfile++; - - /* Better be compressed */ - - firstchar = fgetc(httpfile); - ungetc(firstchar,httpfile); - if (!strcmp(contentencoding,"x-gzip") || - !strcmp(contentencoding,"x-compress") || - ('\037' == firstchar)) { - - if (*netoutfile == '!') - { - /* user wants to clobber file, if it already exists */ - for (ii = 0; ii < flen; ii++) - netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ - - status = file_remove(netoutfile); - } - - /* Create the new file */ - if ((status = file_create(netoutfile,handle))) { - ffpmsg("Unable to create output disk file (http_compress_open):"); - ffpmsg(netoutfile); - goto error; - } - - closediskfile++; - - /* write a file */ - alarm(NETTIMEOUT); - while(0 != (len = fread(recbuf,1,MAXLEN,httpfile))) { - alarm(0); - status = file_write(*handle,recbuf,len); - if (status) { - ffpmsg("Error writing disk file (http_compres_open)"); - ffpmsg(netoutfile); - goto error; - } - alarm(NETTIMEOUT); - } - file_close(*handle); - fclose(httpfile); - closehttpfile--; - closediskfile--; - - /* File is on disk, let's uncompress it into memory */ - - if (NULL == (diskfile = fopen(netoutfile,"r"))) { - ffpmsg("Unable to reopen disk file (http_compress_open)"); - ffpmsg(netoutfile); - goto error; - } - closefdiskfile++; - - /* Create the memory handle to hold it */ - if ((status = mem_create(url,handle))) { - ffpmsg("Unable to create memory file (http_compress_open)"); - goto error; - } - closememfile++; - - /* Uncompress it */ - status = 0; - status = mem_uncompress2mem(url,diskfile,*handle); - fclose(diskfile); - closefdiskfile--; - if (status) { - ffpmsg("Error uncompressing disk file to memory (http_compress_open)"); - ffpmsg(netoutfile); - goto error; - } - - } else { - /* Opps, this should not have happened */ - ffpmsg("Can only have compressed files here (http_compress_open)"); - goto error; - } - - signal(SIGALRM, SIG_DFL); - alarm(0); - return mem_seek(*handle,0); - - error: - alarm(0); /* clear it */ - if (closehttpfile) { - fclose(httpfile); - } - if (closefdiskfile) { - fclose(diskfile); - } - if (closememfile) { - mem_close_free(*handle); - } - if (closediskfile) { - file_close(*handle); - } - - signal(SIGALRM, SIG_DFL); - return (FILE_NOT_OPENED); -} - -/*--------------------------------------------------------------------------*/ -/* This creates a file handle with a copy of the URL in filename. The http - file is copied to disk first. If it's compressed then it is - uncompressed when copying to the disk */ - -int http_file_open(char *url, int rwmode, int *handle) -{ - FILE *httpfile; - char contentencoding[SHORTLEN]; - char errorstr[MAXLEN]; - char recbuf[MAXLEN]; - long len; - int contentlength; - int ii, flen, status; - char firstchar; - - /* Check if output file is actually a memory file */ - if (!strncmp(netoutfile, "mem:", 4) ) - { - /* allow the memory file to be opened with write access */ - return( http_open(url, READONLY, handle) ); - } - - closehttpfile = 0; - closefile = 0; - closeoutfile = 0; - - /* cfileio made a mistake, we need to know where to write the file */ - flen = strlen(netoutfile); - if (!flen) { - ffpmsg("Output file not set, shouldn't have happened (http_file_open)"); - return (FILE_NOT_OPENED); - } - - /* do the signal handler bits */ - if (setjmp(env) != 0) { - /* feels like the second time */ - /* this means something bad happened */ - ffpmsg("Timeout (http_open)"); - goto error; - } - - signal(SIGALRM, signal_handler); - - /* Open the network connection */ - alarm(NETTIMEOUT); - if ((status = http_open_network(url,&httpfile,contentencoding, - &contentlength))) { - alarm(0); - ffpmsg("Unable to open http file (http_file_open)"); - ffpmsg(url); - goto error; - } - - closehttpfile++; - - if (*netoutfile == '!') - { - /* user wants to clobber disk file, if it already exists */ - for (ii = 0; ii < flen; ii++) - netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ - - status = file_remove(netoutfile); - } - - firstchar = fgetc(httpfile); - ungetc(firstchar,httpfile); - if (!strcmp(contentencoding,"x-gzip") || - !strcmp(contentencoding,"x-compress") || - ('\037' == firstchar)) { - - /* to make this more cfitsioish we use the file driver calls to create - the disk file */ - - /* Create the output file */ - if ((status = file_create(netoutfile,handle))) { - ffpmsg("Unable to create output file (http_file_open)"); - ffpmsg(netoutfile); - goto error; - } - - file_close(*handle); - if (NULL == (outfile = fopen(netoutfile,"w"))) { - ffpmsg("Unable to reopen the output file (http_file_open)"); - ffpmsg(netoutfile); - goto error; - } - closeoutfile++; - status = 0; - - /* Ok, this is a tough case, let's be arbritary and say 10*NETTIMEOUT, - Given the choices for nettimeout above they'll probaby ^C before, but - it's always worth a shot*/ - - alarm(NETTIMEOUT*10); - status = uncompress2file(url,httpfile,outfile,&status); - alarm(0); - if (status) { - ffpmsg("Error uncompressing http file to disk file (http_file_open)"); - ffpmsg(url); - ffpmsg(netoutfile); - goto error; - } - fclose(outfile); - closeoutfile--; - } else { - - /* Create the output file */ - if ((status = file_create(netoutfile,handle))) { - ffpmsg("Unable to create output file (http_file_open)"); - ffpmsg(netoutfile); - goto error; - } - - /* Give a warning message. This could just be bad padding at the end - so don't treat it like an error. */ - closefile++; - - if (contentlength % 2880) { - sprintf(errorstr, - "Content-Length not a multiple of 2880 (http_file_open) %d", - contentlength); - ffpmsg(errorstr); - } - - /* write a file */ - alarm(NETTIMEOUT); - while(0 != (len = fread(recbuf,1,MAXLEN,httpfile))) { - alarm(0); - status = file_write(*handle,recbuf,len); - if (status) { - ffpmsg("Error copying http file to disk file (http_file_open)"); - ffpmsg(url); - ffpmsg(netoutfile); - goto error; - } - } - file_close(*handle); - closefile--; - } - - fclose(httpfile); - closehttpfile--; - - signal(SIGALRM, SIG_DFL); - alarm(0); - - return file_open(netoutfile,rwmode,handle); - - error: - alarm(0); /* clear it */ - if (closehttpfile) { - fclose(httpfile); - } - if (closeoutfile) { - fclose(outfile); - } - if (closefile) { - file_close(*handle); - } - - signal(SIGALRM, SIG_DFL); - return (FILE_NOT_OPENED); -} - -/*--------------------------------------------------------------------------*/ -/* This is the guts of the code to get a file via http. - url is the input url - httpfile is set to be the file connected to the socket which you can - read the file from - contentencoding is the mime type of the file, returned if the http server - returns it - contentlength is the lenght of the file, returned if the http server returns - it -*/ -static int http_open_network(char *url, FILE **httpfile, char *contentencoding, - int *contentlength) -{ - - int status; - int sock; - int tmpint; - char recbuf[MAXLEN]; - char tmpstr[MAXLEN]; - char tmpstr1[SHORTLEN]; - char tmpstr2[MAXLEN]; - char errorstr[MAXLEN]; - char proto[SHORTLEN]; - char host[SHORTLEN]; - char userpass[MAXLEN]; - char fn[MAXLEN]; - char turl[MAXLEN]; - char *scratchstr; - char *saveptr; - int port; - float version; - - char pproto[SHORTLEN]; - char phost[SHORTLEN]; /* address of the proxy server */ - int pport; /* port number of the proxy server */ - char pfn[MAXLEN]; - char *proxy; /* URL of the proxy server */ - - /* Parse the URL apart again */ - strcpy(turl,"http://"); - strncat(turl,url,MAXLEN - 8); - if (NET_ParseUrl(turl,proto,host,&port,fn)) { - sprintf(errorstr,"URL Parse Error (http_open) %s",url); - ffpmsg(errorstr); - return (FILE_NOT_OPENED); - } - - /* Do we have a user:password combo ? */ - strcpy(userpass, url); - if ((scratchstr = strchr(userpass, '@')) != NULL) { - *scratchstr = '\0'; - } else - strcpy(userpass, ""); - - /* Ph. Prugniel 2003/04/03 - Are we using a proxy? - - We use a proxy if the environment variable "http_proxy" is set to an - address, eg. http://wwwcache.nottingham.ac.uk:3128 - ("http_proxy" is also used by wget) - */ - proxy = getenv("http_proxy"); - - /* Connect to the remote host */ - if (proxy) { - if (NET_ParseUrl(proxy,pproto,phost,&pport,pfn)) { - sprintf(errorstr,"URL Parse Error (http_open) %s",proxy); - ffpmsg(errorstr); - return (FILE_NOT_OPENED); - } - sock = NET_TcpConnect(phost,pport); - } - else - sock = NET_TcpConnect(host,port); - - if (sock < 0) { - if (proxy) { - ffpmsg("Couldn't connect to host via proxy server (http_open_network)"); - ffpmsg(proxy); - } - return (FILE_NOT_OPENED); - } - - /* Make the socket a stdio file */ - if (NULL == (*httpfile = fdopen(sock,"r"))) { - ffpmsg ("fdopen failed to convert socket to file (http_open_network)"); - close(sock); - return (FILE_NOT_OPENED); - } - - /* Send the GET request to the remote server */ - /* Ph. Prugniel 2003/04/03 - One must add the Host: command because of HTTP 1.1 servers (ie. virtual - hosts) */ - - if (proxy) - sprintf(tmpstr,"GET http://%s:%-d%s HTTP/1.0\r\n",host,port,fn); - else - sprintf(tmpstr,"GET %s HTTP/1.0\r\n",fn); - - if (strcmp(userpass, "")) { - encode64(strlen(userpass), userpass, MAXLEN, tmpstr2); - sprintf(tmpstr1, "Authorization: Basic %s\r\n", tmpstr2); - - if (strlen(tmpstr) + strlen(tmpstr1) > MAXLEN - 1) - return (FILE_NOT_OPENED); - - strcat(tmpstr,tmpstr1); - } - - sprintf(tmpstr1,"User-Agent: HEASARC/CFITSIO/%-8.3f\r\n",ffvers(&version)); - - if (strlen(tmpstr) + strlen(tmpstr1) > MAXLEN - 1) - return (FILE_NOT_OPENED); - - strcat(tmpstr,tmpstr1); - - /* HTTP 1.1 servers require the following 'Host: ' string */ - sprintf(tmpstr1,"Host: %s:%-d\r\n\r\n",host,port); - - if (strlen(tmpstr) + strlen(tmpstr1) > MAXLEN - 1) - return (FILE_NOT_OPENED); - - strcat(tmpstr,tmpstr1); - - status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); - - /* read the header */ - if (!(fgets(recbuf,MAXLEN,*httpfile))) { - sprintf (errorstr,"http header short (http_open_network) %s",recbuf); - ffpmsg(errorstr); - fclose(*httpfile); - return (FILE_NOT_OPENED); - } - *contentlength = 0; - contentencoding[0] = '\0'; - - /* Our choices are 200, ok, 301, temporary redirect, or 302 perm redirect */ - sscanf(recbuf,"%s %d",tmpstr,&status); - if (status != 200){ - if (status == 301 || status == 302) { - /* got a redirect */ - if (status == 301) { - ffpmsg("Note: Web server replied with a temporary redirect from"); - } else { - ffpmsg("Note: Web server replied with a redirect from"); - } - ffpmsg(turl); - /* now, let's not write the most sophisticated parser here */ - - while (fgets(recbuf,MAXLEN,*httpfile)) { - scratchstr = strstr(recbuf," 3) { - recbuf[strlen(recbuf)-1] = '\0'; - recbuf[strlen(recbuf)-1] = '\0'; - } - sscanf(recbuf,"%s %d",tmpstr,&tmpint); - /* Did we get a content-length header ? */ - if (!strcmp(tmpstr,"Content-Length:")) { - *contentlength = tmpint; - } - /* Did we get the content-encoding header ? */ - if (!strcmp(tmpstr,"Content-Encoding:")) { - if (NULL != (scratchstr = strstr(recbuf,":"))) { - /* Found the : */ - scratchstr++; /* skip the : */ - scratchstr++; /* skip the extra space */ - strcpy(contentencoding,scratchstr); - } - } - } - - /* we're done, so return */ - return 0; -} - - -/*--------------------------------------------------------------------------*/ -/* This creates a memory file handle with a copy of the URL in filename. The - file is uncompressed if necessary */ - -int ftp_open(char *filename, int rwmode, int *handle) -{ - - FILE *ftpfile; - FILE *command; - int sock; - char newfilename[MAXLEN]; - char recbuf[MAXLEN]; - long len; - int status; - char firstchar; - - closememfile = 0; - closecommandfile = 0; - closeftpfile = 0; - - /* don't do r/w files */ - if (rwmode != 0) { - ffpmsg("Can't open ftp:// type file with READWRITE access"); - ffpmsg("Specify an outfile for r/w access (ftp_open)"); - return (FILE_NOT_OPENED); - } - - /* do the signal handler bits */ - if (setjmp(env) != 0) { - /* feels like the second time */ - /* this means something bad happened */ - ffpmsg("Timeout (http_open)"); - goto error; - } - - signal(SIGALRM, signal_handler); - - /* Open the ftp connetion. ftpfile is connected to the file port, - command is connected to port 21. sock is the socket on port 21 */ - - if (strlen(filename) > MAXLEN - 4) { - ffpmsg("filename too long (ftp_open)"); - ffpmsg(filename); - goto error; - } - - alarm(NETTIMEOUT); - strcpy(newfilename,filename); - /* Does the file have a .Z or .gz in it */ - if (strstr(newfilename,".Z") || strstr(newfilename,".gz")) { - alarm(NETTIMEOUT); - if (ftp_open_network(filename,&ftpfile,&command,&sock)) { - - alarm(0); - ffpmsg("Unable to open ftp file (ftp_open)"); - ffpmsg(filename); - goto error; - } - } else { - /* Try the .gz one */ - strcpy(newfilename,filename); - strcat(newfilename,".gz"); - alarm(NETTIMEOUT); - if (ftp_open_network(newfilename,&ftpfile,&command,&sock)) { - - alarm(0); - strcpy(newfilename,filename); - strcat(newfilename,".Z"); - alarm(NETTIMEOUT); - if (ftp_open_network(newfilename,&ftpfile,&command,&sock)) { - - /* Now as given */ - alarm(0); - strcpy(newfilename,filename); - alarm(NETTIMEOUT); - if (ftp_open_network(newfilename,&ftpfile,&command,&sock)) { - alarm(0); - ffpmsg("Unable to open ftp file (ftp_open)"); - ffpmsg(newfilename); - goto error; - } - } - } - } - - closeftpfile++; - closecommandfile++; - - /* create the memory file */ - if ((status = mem_create(filename,handle))) { - ffpmsg ("Could not create memory file to passive port (ftp_open)"); - ffpmsg(filename); - goto error; - } - closememfile++; - /* This isn't quite right, it'll fail if the file has .gzabc at the end - for instance */ - - /* Decide if the file is compressed */ - firstchar = fgetc(ftpfile); - ungetc(firstchar,ftpfile); - - if (strstr(newfilename,".gz") || - strstr(newfilename,".Z") || - ('\037' == firstchar)) { - - status = 0; - /* A bit arbritary really, the user will probably hit ^C */ - alarm(NETTIMEOUT*10); - status = mem_uncompress2mem(filename, ftpfile, *handle); - alarm(0); - if (status) { - ffpmsg("Error writing compressed memory file (ftp_open)"); - ffpmsg(filename); - goto error; - } - } else { - /* write a memory file */ - alarm(NETTIMEOUT); - while(0 != (len = fread(recbuf,1,MAXLEN,ftpfile))) { - alarm(0); - status = mem_write(*handle,recbuf,len); - if (status) { - ffpmsg("Error writing memory file (http_open)"); - ffpmsg(filename); - goto error; - } - alarm(NETTIMEOUT); - } - } - - /* close and clean up */ - fclose(ftpfile); - closeftpfile--; - - NET_SendRaw(sock,"QUIT\n",5,NET_DEFAULT); - fclose(command); - closecommandfile--; - - signal(SIGALRM, SIG_DFL); - alarm(0); - - return mem_seek(*handle,0); - - error: - alarm(0); /* clear it */ - if (closecommandfile) { - fclose(command); - } - if (closeftpfile) { - fclose(ftpfile); - } - if (closememfile) { - mem_close_free(*handle); - } - - signal(SIGALRM, SIG_DFL); - return (FILE_NOT_OPENED); -} -/*--------------------------------------------------------------------------*/ -/* This creates a file handle with a copy of the URL in filename. The - file must be uncompressed and is copied to disk first */ - -int ftp_file_open(char *url, int rwmode, int *handle) -{ - FILE *ftpfile; - FILE *command; - char recbuf[MAXLEN]; - long len; - int sock; - int ii, flen, status; - char firstchar; - - /* Check if output file is actually a memory file */ - if (!strncmp(netoutfile, "mem:", 4) ) - { - /* allow the memory file to be opened with write access */ - return( ftp_open(url, READONLY, handle) ); - } - - closeftpfile = 0; - closecommandfile = 0; - closefile = 0; - closeoutfile = 0; - - /* cfileio made a mistake, need to know where to write the output file */ - flen = strlen(netoutfile); - if (!flen) - { - ffpmsg("Output file not set, shouldn't have happened (ftp_file_open)"); - return (FILE_NOT_OPENED); - } - - /* do the signal handler bits */ - if (setjmp(env) != 0) { - /* feels like the second time */ - /* this means something bad happened */ - ffpmsg("Timeout (http_open)"); - goto error; - } - - signal(SIGALRM, signal_handler); - - /* open the network connection to url. ftpfile holds the connection to - the input file, command holds the connection to port 21, and sock is - the socket connected to port 21 */ - - alarm(NETTIMEOUT); - if ((status = ftp_open_network(url,&ftpfile,&command,&sock))) { - alarm(0); - ffpmsg("Unable to open http file (ftp_file_open)"); - ffpmsg(url); - goto error; - } - closeftpfile++; - closecommandfile++; - - if (*netoutfile == '!') - { - /* user wants to clobber file, if it already exists */ - for (ii = 0; ii < flen; ii++) - netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ - - status = file_remove(netoutfile); - } - - /* Now, what do we do with the file */ - firstchar = fgetc(ftpfile); - ungetc(firstchar,ftpfile); - - if (strstr(url,".gz") || - strstr(url,".Z") || - ('\037' == firstchar)) { - - /* to make this more cfitsioish we use the file driver calls to create - the file */ - /* Create the output file */ - if ((status = file_create(netoutfile,handle))) { - ffpmsg("Unable to create output file (ftp_file_open)"); - ffpmsg(netoutfile); - goto error; - } - - file_close(*handle); - if (NULL == (outfile = fopen(netoutfile,"w"))) { - ffpmsg("Unable to reopen the output file (ftp_file_open)"); - ffpmsg(netoutfile); - goto error; - } - closeoutfile++; - status = 0; - - /* Ok, this is a tough case, let's be arbritary and say 10*NETTIMEOUT, - Given the choices for nettimeout above they'll probaby ^C before, but - it's always worth a shot*/ - - alarm(NETTIMEOUT*10); - status = uncompress2file(url,ftpfile,outfile,&status); - alarm(0); - if (status) { - ffpmsg("Unable to uncompress the output file (ftp_file_open)"); - ffpmsg(url); - ffpmsg(netoutfile); - goto error; - } - fclose(outfile); - closeoutfile--; - - } else { - - /* Create the output file */ - if ((status = file_create(netoutfile,handle))) { - ffpmsg("Unable to create output file (ftp_file_open)"); - ffpmsg(netoutfile); - goto error; - } - closefile++; - - /* write a file */ - alarm(NETTIMEOUT); - while(0 != (len = fread(recbuf,1,MAXLEN,ftpfile))) { - alarm(0); - status = file_write(*handle,recbuf,len); - if (status) { - ffpmsg("Error writing file (ftp_file_open)"); - ffpmsg(url); - ffpmsg(netoutfile); - goto error; - } - alarm(NETTIMEOUT); - } - file_close(*handle); - } - fclose(ftpfile); - closeftpfile--; - - NET_SendRaw(sock,"QUIT\n",5,NET_DEFAULT); - fclose(command); - closecommandfile--; - - signal(SIGALRM, SIG_DFL); - alarm(0); - - return file_open(netoutfile,rwmode,handle); - - error: - alarm(0); /* clear it */ - if (closeftpfile) { - fclose(ftpfile); - } - if (closecommandfile) { - fclose(command); - } - if (closeoutfile) { - fclose(outfile); - } - if (closefile) { - file_close(*handle); - } - - signal(SIGALRM, SIG_DFL); - return (FILE_NOT_OPENED); -} - -/*--------------------------------------------------------------------------*/ -/* This creates a memory handle with a copy of the URL in filename. The - file must be compressed and is copied to disk first */ - -int ftp_compress_open(char *url, int rwmode, int *handle) -{ - FILE *ftpfile; - FILE *command; - char recbuf[MAXLEN]; - long len; - int ii, flen, status; - int sock; - char firstchar; - - closeftpfile = 0; - closecommandfile = 0; - closememfile = 0; - closefdiskfile = 0; - closediskfile = 0; - - /* don't do r/w files */ - if (rwmode != 0) { - ffpmsg("Compressed files must be r/o"); - return (FILE_NOT_OPENED); - } - - /* Need to know where to write the output file */ - flen = strlen(netoutfile); - if (!flen) - { - ffpmsg( - "Output file not set, shouldn't have happened (ftp_compress_open)"); - return (FILE_NOT_OPENED); - } - - /* do the signal handler bits */ - if (setjmp(env) != 0) { - /* feels like the second time */ - /* this means something bad happened */ - ffpmsg("Timeout (http_open)"); - goto error; - } - - signal(SIGALRM, signal_handler); - - /* Open the network connection to url, ftpfile is connected to the file - port, command is connected to port 21. sock is for writing to port 21 */ - alarm(NETTIMEOUT); - - if ((status = ftp_open_network(url,&ftpfile,&command,&sock))) { - alarm(0); - ffpmsg("Unable to open ftp file (ftp_compress_open)"); - ffpmsg(url); - goto error; - } - closeftpfile++; - closecommandfile++; - - /* Now, what do we do with the file */ - firstchar = fgetc(ftpfile); - ungetc(firstchar,ftpfile); - - if (strstr(url,".gz") || - strstr(url,".Z") || - ('\037' == firstchar)) { - - if (*netoutfile == '!') - { - /* user wants to clobber file, if it already exists */ - for (ii = 0; ii < flen; ii++) - netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ - - status = file_remove(netoutfile); - } - - /* Create the output file */ - if ((status = file_create(netoutfile,handle))) { - ffpmsg("Unable to create output file (ftp_compress_open)"); - ffpmsg(netoutfile); - goto error; - } - closediskfile++; - - /* write a file */ - alarm(NETTIMEOUT); - while(0 != (len = fread(recbuf,1,MAXLEN,ftpfile))) { - alarm(0); - status = file_write(*handle,recbuf,len); - if (status) { - ffpmsg("Error writing file (ftp_compres_open)"); - ffpmsg(url); - ffpmsg(netoutfile); - goto error; - } - alarm(NETTIMEOUT); - } - - file_close(*handle); - closediskfile--; - fclose(ftpfile); - closeftpfile--; - /* Close down the ftp connection */ - NET_SendRaw(sock,"QUIT\n",5,NET_DEFAULT); - fclose(command); - closecommandfile--; - - /* File is on disk, let's uncompress it into memory */ - - if (NULL == (diskfile = fopen(netoutfile,"r"))) { - ffpmsg("Unable to reopen disk file (ftp_compress_open)"); - ffpmsg(netoutfile); - return (FILE_NOT_OPENED); - } - closefdiskfile++; - - if ((status = mem_create(url,handle))) { - ffpmsg("Unable to create memory file (ftp_compress_open)"); - ffpmsg(url); - goto error; - } - closememfile++; - - status = 0; - status = mem_uncompress2mem(url,diskfile,*handle); - fclose(diskfile); - closefdiskfile--; - - if (status) { - ffpmsg("Error writing compressed memory file (ftp_compress_open)"); - goto error; - } - - } else { - /* Opps, this should not have happened */ - ffpmsg("Can only compressed files here (ftp_compress_open)"); - goto error; - } - - - signal(SIGALRM, SIG_DFL); - alarm(0); - return mem_seek(*handle,0); - - error: - alarm(0); /* clear it */ - if (closeftpfile) { - fclose(ftpfile); - } - if (closecommandfile) { - fclose(command); - } - if (closefdiskfile) { - fclose(diskfile); - } - if (closememfile) { - mem_close_free(*handle); - } - if (closediskfile) { - file_close(*handle); - } - - signal(SIGALRM, SIG_DFL); - return (FILE_NOT_OPENED); -} - -/*--------------------------------------------------------------------------*/ -/* Open a ftp connection to filename (really a URL), return ftpfile set to - the file connection, and command set to the control connection, with sock - also set to the control connection */ - -int ftp_open_network(char *filename, FILE **ftpfile, FILE **command, int *sock) -{ - int status; - int sock1; - int tmpint; - char recbuf[MAXLEN]; - char errorstr[MAXLEN]; - char tmpstr[MAXLEN]; - char proto[SHORTLEN]; - char host[SHORTLEN]; - char *newhost; - char *username; - char *password; - char fn[MAXLEN]; - char *newfn; - char *passive; - char *tstr; - char *saveptr; - char ip[SHORTLEN]; - char turl[MAXLEN]; - int port; - - /* parse the URL */ - if (strlen(filename) > MAXLEN - 7) { - ffpmsg("ftp filename is too long (ftp_open)"); - return (FILE_NOT_OPENED); - } - - strcpy(turl,"ftp://"); - strcat(turl,filename); - if (NET_ParseUrl(turl,proto,host,&port,fn)) { - sprintf(errorstr,"URL Parse Error (ftp_open) %s",filename); - ffpmsg(errorstr); - return (FILE_NOT_OPENED); - } -#ifdef DEBUG - printf ("proto, %s, host, %s, port %d, fn %s\n",proto,host,port,fn); -#endif - - port = 21; - /* we might have a user name */ - username = "anonymous"; - password = "user@host.com"; - /* is there an @ sign */ - if (NULL != (newhost = strrchr(host,'@'))) { - *newhost = '\0'; /* make it a null, */ - newhost++; /* Now newhost points to the host name and host points to the - user name, password combo */ - username = host; - /* is there a : for a password */ - if (NULL != strchr(username,':')) { - password = strchr(username,':'); - *password = '\0'; - password++; - } - } else { - newhost = host; - } - -#ifdef DEBUG - printf("User %s pass %s\n",username,password); -#endif - - /* Connect to the host on the required port */ - *sock = NET_TcpConnect(newhost,port); - /* convert it to a stdio file */ - if (NULL == (*command = fdopen(*sock,"r"))) { - ffpmsg ("fdopen failed to convert socket to stdio file (ftp_open)"); - return (FILE_NOT_OPENED); - - } - - /* Wait for the 220 response */ - if (ftp_status(*command,"220 ")) { - ffpmsg ("error connecting to remote server, no 220 seen (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - - /* Send the user name and wait for the right response */ - sprintf(tmpstr,"USER %s\n",username); - status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); - - if (ftp_status(*command,"331 ")) { - ffpmsg ("USER error no 331 seen (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - - } - - /* Send the password and wait for the right response */ - sprintf(tmpstr,"PASS %s\n",password); - status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); - - if (ftp_status(*command,"230 ")) { - ffpmsg ("PASS error, no 230 seen (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - - - /* now do the cwd command */ - newfn = strrchr(fn,'/'); - if (newfn == NULL) { - strcpy(tmpstr,"CWD /\n"); - newfn = fn; - } else { - *newfn = '\0'; - newfn++; - if (strlen(fn) == 0) { - strcpy(tmpstr,"CWD /\n"); - } else { - /* remove the leading slash */ - if (fn[0] == '/') { - sprintf(tmpstr,"CWD %s\n",&fn[1]); - } else { - sprintf(tmpstr,"CWD %s\n",fn); - } - } - } - -#ifdef DEBUG - printf("CWD command is %s\n",tmpstr); -#endif - status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); - - if (ftp_status(*command,"250 ")) { - ffpmsg ("CWD error, no 250 seen (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - - if (!strlen(newfn)) { - ffpmsg("Null file name (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - - - /* Always use binary mode */ - sprintf(tmpstr,"TYPE I\n"); - status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); - - if (ftp_status(*command,"200 ")) { - ffpmsg ("TYPE I error, 200 not seen (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - - status = NET_SendRaw(*sock,"PASV\n",5,NET_DEFAULT); - if (!(fgets(recbuf,MAXLEN,*command))) { - ffpmsg ("PASV error (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - - /* Passive mode response looks like - 227 Entering Passive Mode (129,194,67,8,210,80) */ - if (recbuf[0] == '2' && recbuf[1] == '2' && recbuf[2] == '7') { - /* got a good passive mode response, find the opening ( */ - - if (!(passive = strchr(recbuf,'('))) { - ffpmsg ("PASV error (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - - *passive = '\0'; - passive++; - ip[0] = '\0'; - - /* Messy parsing of response from PASV *command */ - - if (!(tstr = ffstrtok(passive,",)",&saveptr))) { - ffpmsg ("PASV error (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - strcpy(ip,tstr); - strcat(ip,"."); - - if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { - ffpmsg ("PASV error (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - strcat(ip,tstr); - strcat(ip,"."); - - if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { - ffpmsg ("PASV error (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - strcat(ip,tstr); - strcat(ip,"."); - - if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { - ffpmsg ("PASV error (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - strcat(ip,tstr); - - /* Done the ip number, now do the port # */ - if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { - ffpmsg ("PASV error (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - sscanf(tstr,"%d",&port); - port *= 256; - - if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { - ffpmsg ("PASV error (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - sscanf(tstr,"%d",&tmpint); - port += tmpint; - - - if (!strlen(newfn)) { - ffpmsg("Null file name (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - - -#ifdef DEBUG - puts("connection to passive port"); -#endif - /* COnnect to the data port */ - sock1 = NET_TcpConnect(ip,port); - if (NULL == (*ftpfile = fdopen(sock1,"r"))) { - ffpmsg ("Could not connect to passive port (ftp_open)"); - fclose(*command); - return (FILE_NOT_OPENED); - } - - /* now we return */ - - /* Send the retrieve command */ - sprintf(tmpstr,"RETR %s\n",newfn); - status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); - -#ifdef DEBUG - puts("Sent RETR command"); -#endif - if (ftp_status(*command,"150 ")) { - /* ffpmsg ("RETR error, most likely file is not there (ftp_open)"); */ - fclose(*command); -#ifdef DEBUG - puts("File not there"); -#endif - return (FILE_NOT_OPENED); - } - return 0; - } - - /* no passive mode */ - - NET_SendRaw(*sock,"QUIT\n",5,NET_DEFAULT); - fclose(*command); - return (FILE_NOT_OPENED); -} - -/*--------------------------------------------------------------------------*/ -/* return a socket which results from connection to hostname on port port */ -static int NET_TcpConnect(char *hostname, int port) -{ - /* Connect to hostname on port */ - - struct sockaddr_in sockaddr; - int sock; - int stat; - int val = 1; - - CreateSocketAddress(&sockaddr,hostname,port); - /* Create socket */ - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - ffpmsg("Can't create socket"); - return CONNECTION_ERROR; - } - - if ((stat = connect(sock, (struct sockaddr*) &sockaddr, - sizeof(sockaddr))) - < 0) { - close(sock); -/* - perror("NET_Tcpconnect - Connection error"); - ffpmsg("Can't connect to host, connection error"); -*/ - return CONNECTION_ERROR; - } - setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); - setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&val, sizeof(val)); - - val = 65536; - setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&val, sizeof(val)); - setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&val, sizeof(val)); - return sock; -} - -/*--------------------------------------------------------------------------*/ -/* Write len bytes from buffer to socket sock */ -static int NET_SendRaw(int sock, const void *buffer, int length, int opt) -{ - - char * buf = (char *) buffer; - - int flag; - int n, nsent = 0; - - switch (opt) { - case NET_DEFAULT: - flag = 0; - break; - case NET_OOB: - flag = MSG_OOB; - break; - case NET_PEEK: - default: - flag = 0; - break; - } - - if (sock < 0) return -1; - - for (n = 0; n < length; n += nsent) { - if ((nsent = send(sock, buf+n, length-n, flag)) <= 0) { - return nsent; - } -#ifdef DEBUG - printf ("send raw, sent %d bytes\n",nsent); -#endif - } -#ifdef DEBUG - printf ("send raw end, sent %d bytes\n",n); -#endif - return n; -} - -/*--------------------------------------------------------------------------*/ - -static int NET_RecvRaw(int sock, void *buffer, int length) -{ - /* Receive exactly length bytes into buffer. Returns number of bytes */ - /* received. Returns -1 in case of error. */ - - - int nrecv, n; - char *buf = (char *)buffer; - - if (sock < 0) return -1; - for (n = 0; n < length; n += nrecv) { - while ((nrecv = recv(sock, buf+n, length-n, 0)) == -1 && errno == EINTR) - errno = 0; /* probably a SIGCLD that was caught */ - if (nrecv < 0) - return nrecv; - else if (nrecv == 0) - break; /*/ EOF */ - } - - return n; -} - -/*--------------------------------------------------------------------------*/ -/* Yet Another URL Parser - url - input url - proto - input protocol - host - output host - port - output port - fn - output filename -*/ - -static int NET_ParseUrl(const char *url, char *proto, char *host, int *port, - char *fn) -{ - /* parses urls into their bits */ - /* returns 1 if error, else 0 */ - - char *urlcopy, *urlcopyorig; - char *ptrstr; - char *thost; - int isftp = 0; - - /* figure out if there is a http: or ftp: */ - - urlcopyorig = urlcopy = (char *) malloc(strlen(url)+1); - strcpy(urlcopy,url); - - /* set some defaults */ - *port = 80; - strcpy(proto,"http:"); - strcpy(host,"localhost"); - strcpy(fn,"/"); - - ptrstr = strstr(urlcopy,"http:"); - if (ptrstr == NULL) { - /* Nope, not http: */ - ptrstr = strstr(urlcopy,"root:"); - if (ptrstr == NULL) { - /* Nope, not root either */ - ptrstr = strstr(urlcopy,"ftp:"); - if (ptrstr != NULL) { - if (ptrstr == urlcopy) { - strcpy(proto,"ftp:"); - *port = 21; - isftp++; - urlcopy += 4; /* move past ftp: */ - } else { - /* not at the beginning, bad url */ - free(urlcopyorig); - return 1; - } - } - } else { - if (ptrstr == urlcopy) { - urlcopy += 5; /* move past root: */ - } else { - /* not at the beginning, bad url */ - free(urlcopyorig); - return 1; - } - } - } else { - if (ptrstr == urlcopy) { - urlcopy += 5; /* move past http: */ - } else { - free(urlcopyorig); - return 1; - } - } - - /* got the protocol */ - /* get the hostname */ - if (urlcopy[0] == '/' && urlcopy[1] == '/') { - /* we have a hostname */ - urlcopy += 2; /* move past the // */ - } - /* do this only if http */ - if (!strcmp(proto,"http:")) { - - /* Move past any user:password */ - if ((thost = strchr(urlcopy, '@')) != NULL) - urlcopy = thost+1; - - strcpy(host,urlcopy); - thost = host; - while (*urlcopy != '/' && *urlcopy != ':' && *urlcopy) { - thost++; - urlcopy++; - } - /* we should either be at the end of the string, have a /, or have a : */ - *thost = '\0'; - if (*urlcopy == ':') { - /* follows a port number */ - urlcopy++; - sscanf(urlcopy,"%d",port); - while (*urlcopy != '/' && *urlcopy) urlcopy++; /* step to the */ - } - } else { - /* do this for ftp */ - strcpy(host,urlcopy); - thost = host; - while (*urlcopy != '/' && *urlcopy) { - thost++; - urlcopy++; - } - *thost = '\0'; - /* Now, we should either be at the end of the string, or have a / */ - - } - /* Now the rest is a fn */ - - if (*urlcopy) { - strcpy(fn,urlcopy); - } - free(urlcopyorig); - return 0; -} - -/*--------------------------------------------------------------------------*/ - -/* Small helper functions to set the netoutfile static string */ -/* Called by cfileio after parsing the output file off of the input file url */ - -int http_checkfile (char *urltype, char *infile, char *outfile1) -{ - char newinfile[MAXLEN]; - FILE *httpfile; - char contentencoding[MAXLEN]; - int contentlength; - - /* default to http:// if there is no output file */ - - strcpy(urltype,"http://"); - - if (strlen(outfile1)) { - /* there is an output file */ - - /* don't copy the "file://" prefix, if present. */ - if (!strncmp(outfile1, "file://", 7) ) - strcpy(netoutfile,outfile1+7); - else - strcpy(netoutfile,outfile1); - - if (!strncmp(outfile1, "mem:", 4) ) { - /* copy the file to memory, with READ and WRITE access - In this case, it makes no difference whether the http file - and or the output file are compressed or not. */ - - strcpy(urltype, "httpmem://"); /* use special driver */ - return 0; - } - - if (strstr(infile, "?")) { - /* file name contains a '?' so probably a cgi string; don't open it */ - strcpy(urltype,"httpfile://"); - return 0; - } - - if (!http_open_network(infile,&httpfile,contentencoding,&contentlength)) { - fclose(httpfile); - /* It's there, we're happy */ - if (strstr(infile,".gz") || (strstr(infile,".Z"))) { - /* It's compressed */ - if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { - strcpy(urltype,"httpcompress://"); - } else { - strcpy(urltype,"httpfile://"); - } - } else { - strcpy(urltype,"httpfile://"); - } - return 0; - } - - /* Ok, let's try the .gz one */ - strcpy(newinfile,infile); - strcat(newinfile,".gz"); - if (!http_open_network(newinfile,&httpfile,contentencoding, - &contentlength)) { - fclose(httpfile); - strcpy(infile,newinfile); - /* It's there, we're happy, and, it's compressed */ - /* It's compressed */ - if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { - strcpy(urltype,"httpcompress://"); - } else { - strcpy(urltype,"httpfile://"); - } - return 0; - } - - /* Ok, let's try the .Z one */ - strcpy(newinfile,infile); - strcat(newinfile,".Z"); - if (!http_open_network(newinfile,&httpfile,contentencoding, - &contentlength)) { - fclose(httpfile); - strcpy(infile,newinfile); - /* It's there, we're happy, and, it's compressed */ - if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { - strcpy(urltype,"httpcompress://"); - } else { - strcpy(urltype,"httpfile://"); - } - return 0; - } - - } - return 0; -} -/*--------------------------------------------------------------------------*/ -int ftp_checkfile (char *urltype, char *infile, char *outfile1) -{ - char newinfile[MAXLEN]; - FILE *ftpfile; - FILE *command; - int sock; - - - /* default to ftp:// */ - - strcpy(urltype,"ftp://"); - - if (strlen(outfile1)) { - /* there is an output file */ - - /* don't copy the "file://" prefix, if present. */ - if (!strncmp(outfile1, "file://", 7) ) - strcpy(netoutfile,outfile1+7); - else - strcpy(netoutfile,outfile1); - - if (!strncmp(outfile1, "mem:", 4) ) { - /* copy the file to memory, with READ and WRITE access - In this case, it makes no difference whether the ftp file - and or the output file are compressed or not. */ - - strcpy(urltype, "ftpmem://"); /* use special driver */ - return 0; - } - - if (!ftp_open_network(infile,&ftpfile,&command,&sock)) { - fclose(ftpfile); - fclose(command); - /* It's there, we're happy */ - if (strstr(infile,".gz") || (strstr(infile,".Z"))) { - /* It's compressed */ - if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { - strcpy(urltype,"ftpcompress://"); - } else { - strcpy(urltype,"ftpfile://"); - } - } else { - strcpy(urltype,"ftpfile://"); - } - return 0; - } - - /* Ok, let's try the .gz one */ - strcpy(newinfile,infile); - strcat(newinfile,".gz"); - if (!ftp_open_network(newinfile,&ftpfile,&command,&sock)) { - fclose(ftpfile); - fclose(command); - strcpy(infile,newinfile); - /* It's there, we're happy, and, it's compressed */ - if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { - strcpy(urltype,"ftpcompress://"); - } else { - strcpy(urltype,"ftpfile://"); - } - return 0; - } - - /* Ok, let's try the .Z one */ - strcpy(newinfile,infile); - strcat(newinfile,".Z"); - if (!ftp_open_network(newinfile,&ftpfile,&command,&sock)) { - fclose(ftpfile); - fclose(command); - strcpy(infile,newinfile); - if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { - strcpy(urltype,"ftpcompress://"); - } else { - strcpy(urltype,"ftpfile://"); - } - return 0; - } - - } - return 0; -} -/*--------------------------------------------------------------------------*/ -/* A small helper function to wait for a particular status on the ftp - connectino */ -static int ftp_status(FILE *ftp, char *statusstr) -{ - /* read through until we find a string beginning with statusstr */ - /* This needs a timeout */ - - char recbuf[MAXLEN]; - int len; - - len = strlen(statusstr); - while (1) { - if (!(fgets(recbuf,MAXLEN,ftp))) { -#ifdef DEBUG - puts("error reading response in ftp_status"); -#endif - return 1; /* error reading */ - } - -#ifdef DEBUG - printf("ftp_status, return string was %s\n",recbuf); -#endif - - recbuf[len] = '\0'; /* make it short */ - if (!strcmp(recbuf,statusstr)) { - return 0; /* we're ok */ - } - if (recbuf[0] > '3') { - /* oh well, some sort of error */ - return 1; - } - } -} - - -/* - *---------------------------------------------------------------------- - * - * CreateSocketAddress -- - * - * This function initializes a sockaddr structure for a host and port. - * - * Results: - * 1 if the host was valid, 0 if the host could not be converted to - * an IP address. - * - * Side effects: - * Fills in the *sockaddrPtr structure. - * - *---------------------------------------------------------------------- - */ - -static int -CreateSocketAddress( - struct sockaddr_in *sockaddrPtr, /* Socket address */ - char *host, /* Host. NULL implies INADDR_ANY */ - int port) /* Port number */ -{ - struct hostent *hostent; /* Host database entry */ - struct in_addr addr; /* For 64/32 bit madness */ - char localhost[MAXLEN]; - - strcpy(localhost,host); - - memset((void *) sockaddrPtr, '\0', sizeof(struct sockaddr_in)); - sockaddrPtr->sin_family = AF_INET; - sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF)); - if (host == NULL) { - addr.s_addr = INADDR_ANY; - } else { - addr.s_addr = inet_addr(localhost); - if (addr.s_addr == 0xFFFFFFFF) { - hostent = gethostbyname(localhost); - if (hostent != NULL) { - memcpy((void *) &addr, - (void *) hostent->h_addr_list[0], - (size_t) hostent->h_length); - } else { -#ifdef EHOSTUNREACH - errno = EHOSTUNREACH; -#else -#ifdef ENXIO - errno = ENXIO; -#endif -#endif - return 0; /* error */ - } - } - } - - /* - * NOTE: On 64 bit machines the assignment below is rumored to not - * do the right thing. Please report errors related to this if you - * observe incorrect behavior on 64 bit machines such as DEC Alphas. - * Should we modify this code to do an explicit memcpy? - */ - - sockaddrPtr->sin_addr.s_addr = addr.s_addr; - return 1; /* Success. */ -} - -/* Signal handler for timeouts */ - -static void signal_handler(int sig) { - - switch (sig) { - case SIGALRM: /* process for alarm */ - longjmp(env,sig); - - default: { - /* Hmm, shouldn't have happend */ - exit(sig); - } - } -} - -/**************************************************************/ - -/* Root driver */ - -/*--------------------------------------------------------------------------*/ -int root_init(void) -{ - int ii; - - for (ii = 0; ii < NMAXFILES; ii++) /* initialize all empty slots in table */ - { - handleTable[ii].sock = 0; - handleTable[ii].currentpos = 0; - } - return(0); -} -/*--------------------------------------------------------------------------*/ -int root_setoptions(int options) -{ - /* do something with the options argument, to stop compiler warning */ - options = 0; - return(options); -} -/*--------------------------------------------------------------------------*/ -int root_getoptions(int *options) -{ - *options = 0; - return(0); -} -/*--------------------------------------------------------------------------*/ -int root_getversion(int *version) -{ - *version = 10; - return(0); -} -/*--------------------------------------------------------------------------*/ -int root_shutdown(void) -{ - return(0); -} -/*--------------------------------------------------------------------------*/ -int root_open(char *url, int rwmode, int *handle) -{ - int ii, status; - int sock; - - *handle = -1; - for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in table */ - { - if (handleTable[ii].sock == 0) - { - *handle = ii; - break; - } - } - - if (*handle == -1) - return(TOO_MANY_FILES); /* too many files opened */ - - /*open the file */ - if (rwmode) { - status = root_openfile(url, "update", &sock); - } else { - status = root_openfile(url, "read", &sock); - } - if (status) - return(status); - - handleTable[ii].sock = sock; - handleTable[ii].currentpos = 0; - - return(0); -} -/*--------------------------------------------------------------------------*/ -int root_create(char *filename, int *handle) -{ - int ii, status; - int sock; - - *handle = -1; - for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in table */ - { - if (handleTable[ii].sock == 0) - { - *handle = ii; - break; - } - } - - if (*handle == -1) - return(TOO_MANY_FILES); /* too many files opened */ - - /*open the file */ - status = root_openfile(filename, "create", &sock); - - if (status) { - ffpmsg("Unable to create file"); - return(status); - } - - handleTable[ii].sock = sock; - handleTable[ii].currentpos = 0; - - return(0); -} -/*--------------------------------------------------------------------------*/ -int root_size(int handle, LONGLONG *filesize) -/* - return the size of the file in bytes -*/ -{ - - int sock; - int offset; - int status; - int op; - - sock = handleTable[handle].sock; - - status = root_send_buffer(sock,ROOTD_STAT,NULL,0); - status = root_recv_buffer(sock,&op,(char *)&offset, 4); - *filesize = (LONGLONG) ntohl(offset); - - return(0); -} -/*--------------------------------------------------------------------------*/ -int root_close(int handle) -/* - close the file -*/ -{ - - int status; - int sock; - - sock = handleTable[handle].sock; - status = root_send_buffer(sock,ROOTD_CLOSE,NULL,0); - close(sock); - handleTable[handle].sock = 0; - return(0); -} -/*--------------------------------------------------------------------------*/ -int root_flush(int handle) -/* - flush the file -*/ -{ - int status; - int sock; - - sock = handleTable[handle].sock; - status = root_send_buffer(sock,ROOTD_FLUSH,NULL,0); - return(0); -} -/*--------------------------------------------------------------------------*/ -int root_seek(int handle, LONGLONG offset) -/* - seek to position relative to start of the file -*/ -{ - handleTable[handle].currentpos = offset; - return(0); -} -/*--------------------------------------------------------------------------*/ -int root_read(int hdl, void *buffer, long nbytes) -/* - read bytes from the current position in the file -*/ -{ - char msg[SHORTLEN]; - int op; - int status; - int astat; - - /* we presume here that the file position will never be > 2**31 = 2.1GB */ - sprintf(msg,"%ld %ld ",(long) handleTable[hdl].currentpos,nbytes); - status = root_send_buffer(handleTable[hdl].sock,ROOTD_GET,msg,strlen(msg)); - if ((unsigned) status != strlen(msg)) { - return (READ_ERROR); - } - astat = 0; - status = root_recv_buffer(handleTable[hdl].sock,&op,(char *) &astat,4); - if (astat != 0) { - return (READ_ERROR); - } -#ifdef DEBUG - printf("root_read, op %d astat %d\n",op,astat); -#endif - status = NET_RecvRaw(handleTable[hdl].sock,buffer,nbytes); - if (status != nbytes) { - return (READ_ERROR); - } - handleTable[hdl].currentpos += nbytes; - - return(0); -} -/*--------------------------------------------------------------------------*/ -int root_write(int hdl, void *buffer, long nbytes) -/* - write bytes at the current position in the file -*/ -{ - - char msg[SHORTLEN]; - int len; - int sock; - int status; - int astat; - int op; - - sock = handleTable[hdl].sock; - /* we presume here that the file position will never be > 2**31 = 2.1GB */ - sprintf(msg,"%ld %ld ",(long) handleTable[hdl].currentpos,nbytes); - - len = strlen(msg); - status = root_send_buffer(sock,ROOTD_PUT,msg,len+1); - if (status != len+1) { - return (WRITE_ERROR); - } - status = NET_SendRaw(sock,buffer,nbytes,NET_DEFAULT); - if (status != nbytes) { - return (WRITE_ERROR); - } - astat = 0; - status = root_recv_buffer(handleTable[hdl].sock,&op,(char *) &astat,4); -#ifdef DEBUG - printf("root_read, op %d astat %d\n",op,astat); -#endif - if (astat != 0) { - return (WRITE_ERROR); - } - handleTable[hdl].currentpos += nbytes; - return(0); -} - -/*--------------------------------------------------------------------------*/ -int root_openfile(char *url, char *rwmode, int *sock) - /* - lowest level routine to physically open a root file - */ -{ - - int status; - char recbuf[MAXLEN]; - char errorstr[MAXLEN]; - char proto[SHORTLEN]; - char host[SHORTLEN]; - char fn[MAXLEN]; - char turl[MAXLEN]; - int port; - int op; - int ii; - int authstat; - - - /* Parse the URL apart again */ - strcpy(turl,"root://"); - strcat(turl,url); - if (NET_ParseUrl(turl,proto,host,&port,fn)) { - sprintf(errorstr,"URL Parse Error (root_open) %s",url); - ffpmsg(errorstr); - return (FILE_NOT_OPENED); - } - -#ifdef DEBUG - printf("Connecting to %s on port %d\n",host,port); -#endif - /* Connect to the remote host */ - *sock = NET_TcpConnect(host,port); - if (*sock < 0) { - ffpmsg("Couldn't connect to host (http_open_network)"); - return (FILE_NOT_OPENED); - } - - /* get the username */ - if (NULL != getenv("ROOTUSERNAME")) { - strcpy(recbuf,getenv("ROOTUSERNAME")); - } else { - printf("Username: "); - fgets(recbuf,MAXLEN,stdin); - recbuf[strlen(recbuf)-1] = '\0'; - } - - status = root_send_buffer(*sock, ROOTD_USER, recbuf,strlen(recbuf)); - if (status < 0) { - ffpmsg("error talking to remote system on username "); - return (FILE_NOT_OPENED); - } - - status = root_recv_buffer(*sock,&op,(char *)&authstat,4); - if (!status) { - ffpmsg("error talking to remote system on username"); - return (FILE_NOT_OPENED); - } - -#ifdef DEBUG - printf("op is %d and authstat is %d\n",op,authstat); -#endif - - if (op != ROOTD_AUTH) { - ffpmsg("ERROR on ROOTD_USER"); - ffpmsg(recbuf); - return (FILE_NOT_OPENED); - } - - - /* now the password */ - if (NULL != getenv("ROOTPASSWORD")) { - strcpy(recbuf,getenv("ROOTPASSWORD")); - } else { - printf("Password: "); - fgets(recbuf,MAXLEN,stdin); - recbuf[strlen(recbuf)-1] = '\0'; - } - /* ones complement the password */ - for (ii=0;(unsigned) ii - - - - includes the 4 bytes for the op, the length bytes (4) are implicit - - - if buffer is null don't send it, not everything needs something sent */ - - int len; - int status; - - int hdr[2]; - - len = 4; - - if (buffer != NULL) { - len += buflen; - } - - hdr[0] = htonl(len); - -#ifdef DEBUG - printf("len sent is %x\n",hdr[0]); -#endif - - hdr[1] = htonl(op); -#ifdef DEBUG - printf("op sent is %x\n",hdr[1]); -#endif - - -#ifdef DEBUG - printf("Sending op %d and length of %d\n",op,len); -#endif - - status = NET_SendRaw(sock,hdr,sizeof(hdr),NET_DEFAULT); - if (status < 0) { - return status; - } - if (buffer != NULL) { - status = NET_SendRaw(sock,buffer,buflen,NET_DEFAULT); - } - return status; -} - -static int root_recv_buffer(int sock, int *op, char *buffer, int buflen) -{ - /* recv a buffer, the form is - - - - - */ - - int recv1 = 0; - int len; - int status; - char recbuf[MAXLEN]; - - status = NET_RecvRaw(sock,&len,4); -#ifdef DEBUG - printf("Recv: status from rec is %d\n",status); -#endif - if (status < 0) { - return status; - } - recv1 += status; - - len = ntohl(len); -#ifdef DEBUG - printf ("Recv: length is %d\n",len); -#endif - - /* ok, have the length, recive the operation */ - len -= 4; - status = NET_RecvRaw(sock,op,4); - if (status < 0) { - return status; - } - - recv1 += status; - - *op = ntohl(*op); -#ifdef DEBUG - printf ("Recv: Operation is %d\n",*op); -#endif - - if (len > MAXLEN) { - len = MAXLEN; - } - - if (len > 0) { /* Get the rest of the message */ - status = NET_RecvRaw(sock,recbuf,len); - if (len > buflen) { - len = buflen; - } - memcpy(buffer,recbuf,len); - if (status < 0) { - return status; - } - } - - recv1 += status; - return recv1; - -} - -/*****************************************************************************/ -/* - Encode a string into MIME Base64 format string -*/ - - -static int encode64(unsigned s_len, char *src, unsigned d_len, char *dst) { - - static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -"abcdefghijklmnopqrstuvwxyz" -"0123456789" -"+/"; - - unsigned triad; - - - for (triad = 0; triad < s_len; triad += 3) { - unsigned long int sr; - unsigned byte; - - for (byte = 0; (byte<3) && (triad+byte -#include -#include -#include -#include -#include -#include - -#if defined(unix) || defined(__unix__) || defined(__unix) || defined(HAVE_UNISTD_H) -#include -#endif - - -static int shared_kbase = 0; /* base for shared memory handles */ -static int shared_maxseg = 0; /* max number of shared memory blocks */ -static int shared_range = 0; /* max number of tried entries */ -static int shared_fd = SHARED_INVALID; /* handle of global access lock file */ -static int shared_gt_h = SHARED_INVALID; /* handle of global table segment */ -static SHARED_LTAB *shared_lt = NULL; /* local table pointer */ -static SHARED_GTAB *shared_gt = NULL; /* global table pointer */ -static int shared_create_mode = 0666; /* permission flags for created objects */ -static int shared_debug = 1; /* simple debugging tool, set to 0 to disable messages */ -static int shared_init_called = 0; /* flag whether shared_init() has been called, used for delayed init */ - - /* static support routines prototypes */ - -static int shared_clear_entry(int idx); /* unconditionally clear entry */ -static int shared_destroy_entry(int idx); /* unconditionally destroy sema & shseg and clear entry */ -static int shared_mux(int idx, int mode); /* obtain exclusive access to specified segment */ -static int shared_demux(int idx, int mode); /* free exclusive access to specified segment */ - -static int shared_process_count(int sem); /* valid only for time of invocation */ -static int shared_delta_process(int sem, int delta); /* change number of processes hanging on segment */ -static int shared_attach_process(int sem); -static int shared_detach_process(int sem); -static int shared_get_free_entry(int newhandle); /* get free entry in shared_key, or -1, entry is set rw locked */ -static int shared_get_hash(long size, int idx);/* return hash value for malloc */ -static long shared_adjust_size(long size); /* size must be >= 0 !!! */ -static int shared_check_locked_index(int idx); /* verify that given idx is valid */ -static int shared_map(int idx); /* map all tables for given idx, check for validity */ -static int shared_validate(int idx, int mode); /* use intrnally inside crit.sect !!! */ - - /* support routines - initialization */ - - -static int shared_clear_entry(int idx) /* unconditionally clear entry */ - { if ((idx < 0) || (idx >= shared_maxseg)) return(SHARED_BADARG); - shared_gt[idx].key = SHARED_INVALID; /* clear entries in global table */ - shared_gt[idx].handle = SHARED_INVALID; - shared_gt[idx].sem = SHARED_INVALID; - shared_gt[idx].semkey = SHARED_INVALID; - shared_gt[idx].nprocdebug = 0; - shared_gt[idx].size = 0; - shared_gt[idx].attr = 0; - - return(SHARED_OK); - } - -static int shared_destroy_entry(int idx) /* unconditionally destroy sema & shseg and clear entry */ - { int r, r2; - union semun filler; - - if ((idx < 0) || (idx >= shared_maxseg)) return(SHARED_BADARG); - r2 = r = SHARED_OK; - filler.val = 0; /* this is to make cc happy (warning otherwise) */ - if (SHARED_INVALID != shared_gt[idx].sem) r = semctl(shared_gt[idx].sem, 0, IPC_RMID, filler); /* destroy semaphore */ - if (SHARED_INVALID != shared_gt[idx].handle) r2 = shmctl(shared_gt[idx].handle, IPC_RMID, 0); /* destroy shared memory segment */ - if (SHARED_OK == r) r = r2; /* accumulate error code in r, free r2 */ - r2 = shared_clear_entry(idx); - return((SHARED_OK == r) ? r2 : r); - } - -void shared_cleanup(void) /* this must (should) be called during exit/abort */ - { int i, j, r, oktodelete, filelocked, segmentspresent; - flock_t flk; - struct shmid_ds ds; - - if (shared_debug) printf("shared_cleanup:"); - if (NULL != shared_lt) - { if (shared_debug) printf(" deleting segments:"); - for (i=0; i>\n"); - return; - } - - -int shared_init(int debug_msgs) /* initialize shared memory stuff, you have to call this routine once */ - { int i; - char buf[1000], *p; - mode_t oldumask; - - shared_init_called = 1; /* tell everybody no need to call us for the 2nd time */ - shared_debug = debug_msgs; /* set required debug mode */ - - if (shared_debug) printf("shared_init:"); - - shared_kbase = 0; /* adapt to current env. settings */ - if (NULL != (p = getenv(SHARED_ENV_KEYBASE))) shared_kbase = atoi(p); - if (0 == shared_kbase) shared_kbase = SHARED_KEYBASE; - if (shared_debug) printf(" keybase=%d", shared_kbase); - - shared_maxseg = 0; - if (NULL != (p = getenv(SHARED_ENV_MAXSEG))) shared_maxseg = atoi(p); - if (0 == shared_maxseg) shared_maxseg = SHARED_MAXSEG; - if (shared_debug) printf(" maxseg=%d", shared_maxseg); - - shared_range = 3 * shared_maxseg; - - if (SHARED_INVALID == shared_fd) /* create rw locking file (this file is never deleted) */ - { if (shared_debug) printf(" lockfileinit="); - sprintf(buf, "%s.%d.%d", SHARED_FDNAME, shared_kbase, shared_maxseg); - oldumask = umask(0); - - shared_fd = open(buf, O_TRUNC | O_EXCL | O_CREAT | O_RDWR, shared_create_mode); - umask(oldumask); - if (SHARED_INVALID == shared_fd) /* or just open rw locking file, in case it already exists */ - { shared_fd = open(buf, O_TRUNC | O_RDWR, shared_create_mode); - if (SHARED_INVALID == shared_fd) return(SHARED_NOFILE); - if (shared_debug) printf("slave"); - - } - else - { if (shared_debug) printf("master"); - } - } - - if (SHARED_INVALID == shared_gt_h) /* global table not attached, try to create it in shared memory */ - { if (shared_debug) printf(" globalsharedtableinit="); - shared_gt_h = shmget(shared_kbase, shared_maxseg * sizeof(SHARED_GTAB), IPC_CREAT | IPC_EXCL | shared_create_mode); /* try open as a master */ - if (SHARED_INVALID == shared_gt_h) /* if failed, try to open as a slave */ - { shared_gt_h = shmget(shared_kbase, shared_maxseg * sizeof(SHARED_GTAB), shared_create_mode); - if (SHARED_INVALID == shared_gt_h) return(SHARED_IPCERR); /* means deleted ID residing in system, shared mem unusable ... */ - shared_gt = (SHARED_GTAB *)shmat(shared_gt_h, 0, 0); /* attach segment */ - if (((SHARED_GTAB *)SHARED_INVALID) == shared_gt) return(SHARED_IPCERR); - if (shared_debug) printf("slave"); - } - else - { shared_gt = (SHARED_GTAB *)shmat(shared_gt_h, 0, 0); /* attach segment */ - if (((SHARED_GTAB *)SHARED_INVALID) == shared_gt) return(SHARED_IPCERR); - for (i=0; i>\n"); - return(SHARED_OK); - } - - -int shared_recover(int id) /* try to recover dormant segments after applic crash */ - { int i, r, r2; - - if (NULL == shared_gt) return(SHARED_NOTINIT); /* not initialized */ - if (NULL == shared_lt) return(SHARED_NOTINIT); /* not initialized */ - r = SHARED_OK; - for (i=0; i r2) || (0 == r2)) - { if (shared_debug) printf("Bogus handle=%d nproc=%d sema=%d:", i, shared_gt[i].nprocdebug, r2); - r = shared_destroy_entry(i); - if (shared_debug) - { printf("%s", r ? "error couldn't clear handle" : "handle cleared"); - } - } - shared_demux(i, SHARED_RDWRITE); - } - return(r); /* table full */ - } - - /* API routines - mutexes and locking */ - -static int shared_mux(int idx, int mode) /* obtain exclusive access to specified segment */ - { flock_t flk; - - int r; - - if (0 == shared_init_called) /* delayed initialization */ - { if (SHARED_OK != (r = shared_init(0))) return(r); - - } - if (SHARED_INVALID == shared_fd) return(SHARED_NOTINIT); - if ((idx < 0) || (idx >= shared_maxseg)) return(SHARED_BADARG); - flk.l_type = ((mode & SHARED_RDWRITE) ? F_WRLCK : F_RDLCK); - flk.l_whence = 0; - flk.l_start = idx; - flk.l_len = 1; - if (shared_debug) printf(" [mux (%d): ", idx); - if (-1 == fcntl(shared_fd, ((mode & SHARED_NOWAIT) ? F_SETLK : F_SETLKW), &flk)) - { switch (errno) - { case EAGAIN: ; - - case EACCES: if (shared_debug) printf("again]"); - return(SHARED_AGAIN); - default: if (shared_debug) printf("err]"); - return(SHARED_IPCERR); - } - } - if (shared_debug) printf("ok]"); - return(SHARED_OK); - } - - - -static int shared_demux(int idx, int mode) /* free exclusive access to specified segment */ - { flock_t flk; - - if (SHARED_INVALID == shared_fd) return(SHARED_NOTINIT); - if ((idx < 0) || (idx >= shared_maxseg)) return(SHARED_BADARG); - flk.l_type = F_UNLCK; - flk.l_whence = 0; - flk.l_start = idx; - flk.l_len = 1; - if (shared_debug) printf(" [demux (%d): ", idx); - if (-1 == fcntl(shared_fd, F_SETLKW, &flk)) - { switch (errno) - { case EAGAIN: ; - case EACCES: if (shared_debug) printf("again]"); - return(SHARED_AGAIN); - default: if (shared_debug) printf("err]"); - return(SHARED_IPCERR); - } - - } - if (shared_debug) printf("mode=%d ok]", mode); - return(SHARED_OK); - } - - - -static int shared_process_count(int sem) /* valid only for time of invocation */ - { union semun su; - - su.val = 0; /* to force compiler not to give warning messages */ - return(semctl(sem, 0, GETVAL, su)); /* su is unused here */ - } - - -static int shared_delta_process(int sem, int delta) /* change number of processes hanging on segment */ - { struct sembuf sb; - - if (SHARED_INVALID == sem) return(SHARED_BADARG); /* semaphore not attached */ - sb.sem_num = 0; - sb.sem_op = delta; - sb.sem_flg = SEM_UNDO; - return((-1 == semop(sem, &sb, 1)) ? SHARED_IPCERR : SHARED_OK); - } - - -static int shared_attach_process(int sem) - { if (shared_debug) printf(" [attach process]"); - return(shared_delta_process(sem, 1)); - } - - -static int shared_detach_process(int sem) - { if (shared_debug) printf(" [detach process]"); - return(shared_delta_process(sem, -1)); - } - - /* API routines - hashing and searching */ - - -static int shared_get_free_entry(int newhandle) /* get newhandle, or -1, entry is set rw locked */ - { - if (NULL == shared_gt) return(-1); /* not initialized */ - if (NULL == shared_lt) return(-1); /* not initialized */ - if (newhandle < 0) return(-1); - if (newhandle >= shared_maxseg) return(-1); - if (shared_lt[newhandle].tcnt) return(-1); /* somebody (we) is using it */ - if (shared_mux(newhandle, SHARED_NOWAIT | SHARED_RDWRITE)) return(-1); /* used by others */ - if (SHARED_INVALID == shared_gt[newhandle].key) return(newhandle); /* we have found free slot, lock it and return index */ - shared_demux(newhandle, SHARED_RDWRITE); - if (shared_debug) printf("[free_entry - ERROR - entry unusable]"); - return(-1); /* table full */ - } - - -static int shared_get_hash(long size, int idx) /* return hash value for malloc */ - { static int counter = 0; - int hash; - - hash = (counter + size * idx) % shared_range; - counter = (counter + 1) % shared_range; - return(hash); - } - - -static long shared_adjust_size(long size) /* size must be >= 0 !!! */ - { return(((size + sizeof(BLKHEAD) + SHARED_GRANUL - 1) / SHARED_GRANUL) * SHARED_GRANUL); } - - - /* API routines - core : malloc/realloc/free/attach/detach/lock/unlock */ - -int shared_malloc(long size, int mode, int newhandle) /* return idx or SHARED_INVALID */ - { int h, i, r, idx, key; - union semun filler; - BLKHEAD *bp; - - if (0 == shared_init_called) /* delayed initialization */ - { if (SHARED_OK != (r = shared_init(0))) return(r); - } - if (shared_debug) printf("malloc (size = %ld, mode = %d):", size, mode); - if (size < 0) return(SHARED_INVALID); - if (-1 == (idx = shared_get_free_entry(newhandle))) return(SHARED_INVALID); - if (shared_debug) printf(" idx=%d", idx); - for (i = 0; ; i++) - { if (i >= shared_range) /* table full, signal error & exit */ - { shared_demux(idx, SHARED_RDWRITE); - return(SHARED_INVALID); - } - key = shared_kbase + ((i + shared_get_hash(size, idx)) % shared_range); - if (shared_debug) printf(" key=%d", key); - h = shmget(key, shared_adjust_size(size), IPC_CREAT | IPC_EXCL | shared_create_mode); - if (shared_debug) printf(" handle=%d", h); - if (SHARED_INVALID == h) continue; /* segment already accupied */ - bp = (BLKHEAD *)shmat(h, 0, 0); /* try attach */ - if (shared_debug) printf(" p=%p", bp); - if (((BLKHEAD *)SHARED_INVALID) == bp) /* cannot attach, delete segment, try with another key */ - { shmctl(h, IPC_RMID, 0); - continue; - } /* now create semaphor counting number of processes attached */ - if (SHARED_INVALID == (shared_gt[idx].sem = semget(key, 1, IPC_CREAT | IPC_EXCL | shared_create_mode))) - { shmdt((void *)bp); /* cannot create segment, delete everything */ - shmctl(h, IPC_RMID, 0); - continue; /* try with another key */ - } - if (shared_debug) printf(" sem=%d", shared_gt[idx].sem); - if (shared_attach_process(shared_gt[idx].sem)) /* try attach process */ - { semctl(shared_gt[idx].sem, 0, IPC_RMID, filler); /* destroy semaphore */ - shmdt((char *)bp); /* detach shared mem segment */ - shmctl(h, IPC_RMID, 0); /* destroy shared mem segment */ - continue; /* try with another key */ - } - bp->s.tflag = BLOCK_SHARED; /* fill in data in segment's header (this is really not necessary) */ - bp->s.ID[0] = SHARED_ID_0; - bp->s.ID[1] = SHARED_ID_1; - bp->s.handle = idx; /* used in yorick */ - if (mode & SHARED_RESIZE) - { if (shmdt((char *)bp)) r = SHARED_IPCERR; /* if segment is resizable, then detach segment */ - shared_lt[idx].p = NULL; - } - else { shared_lt[idx].p = bp; } - shared_lt[idx].tcnt = 1; /* one thread using segment */ - shared_lt[idx].lkcnt = 0; /* no locks at the moment */ - shared_lt[idx].seekpos = 0L; /* r/w pointer positioned at beg of block */ - shared_gt[idx].handle = h; /* fill in data in global table */ - shared_gt[idx].size = size; - shared_gt[idx].attr = mode; - shared_gt[idx].semkey = key; - shared_gt[idx].key = key; - shared_gt[idx].nprocdebug = 0; - - break; - } - shared_demux(idx, SHARED_RDWRITE); /* hope this will not fail */ - return(idx); - } - - -int shared_attach(int idx) - { int r, r2; - - if (SHARED_OK != (r = shared_mux(idx, SHARED_RDWRITE | SHARED_WAIT))) return(r); - if (SHARED_OK != (r = shared_map(idx))) - { shared_demux(idx, SHARED_RDWRITE); - return(r); - } - if (shared_attach_process(shared_gt[idx].sem)) /* try attach process */ - { shmdt((char *)(shared_lt[idx].p)); /* cannot attach process, detach everything */ - shared_lt[idx].p = NULL; - shared_demux(idx, SHARED_RDWRITE); - return(SHARED_BADARG); - } - shared_lt[idx].tcnt++; /* one more thread is using segment */ - if (shared_gt[idx].attr & SHARED_RESIZE) /* if resizeable, detach and return special pointer */ - { if (shmdt((char *)(shared_lt[idx].p))) r = SHARED_IPCERR; /* if segment is resizable, then detach segment */ - shared_lt[idx].p = NULL; - } - shared_lt[idx].seekpos = 0L; /* r/w pointer positioned at beg of block */ - r2 = shared_demux(idx, SHARED_RDWRITE); - return(r ? r : r2); - } - - - -static int shared_check_locked_index(int idx) /* verify that given idx is valid */ - { int r; - - if (0 == shared_init_called) /* delayed initialization */ - { if (SHARED_OK != (r = shared_init(0))) return(r); - - } - if ((idx < 0) || (idx >= shared_maxseg)) return(SHARED_BADARG); - if (NULL == shared_lt[idx].p) return(SHARED_BADARG); /* NULL pointer, not attached ?? */ - if (0 == shared_lt[idx].lkcnt) return(SHARED_BADARG); /* not locked ?? */ - if ((SHARED_ID_0 != (shared_lt[idx].p)->s.ID[0]) || (SHARED_ID_1 != (shared_lt[idx].p)->s.ID[1]) || - (BLOCK_SHARED != (shared_lt[idx].p)->s.tflag)) /* invalid data in segment */ - return(SHARED_BADARG); - return(SHARED_OK); - } - - - -static int shared_map(int idx) /* map all tables for given idx, check for validity */ - { int h; /* have to obtain excl. access before calling shared_map */ - BLKHEAD *bp; - - if ((idx < 0) || (idx >= shared_maxseg)) return(SHARED_BADARG); - if (SHARED_INVALID == shared_gt[idx].key) return(SHARED_BADARG); - if (SHARED_INVALID == (h = shmget(shared_gt[idx].key, 1, shared_create_mode))) return(SHARED_BADARG); - if (((BLKHEAD *)SHARED_INVALID) == (bp = (BLKHEAD *)shmat(h, 0, 0))) return(SHARED_BADARG); - if ((SHARED_ID_0 != bp->s.ID[0]) || (SHARED_ID_1 != bp->s.ID[1]) || (BLOCK_SHARED != bp->s.tflag) || (h != shared_gt[idx].handle)) - { shmdt((char *)bp); /* invalid segment, detach everything */ - return(SHARED_BADARG); - - } - if (shared_gt[idx].sem != semget(shared_gt[idx].semkey, 1, shared_create_mode)) /* check if sema is still there */ - { shmdt((char *)bp); /* cannot attach semaphore, detach everything */ - return(SHARED_BADARG); - } - shared_lt[idx].p = bp; /* store pointer to shmem data */ - return(SHARED_OK); - } - - -static int shared_validate(int idx, int mode) /* use intrnally inside crit.sect !!! */ - { int r; - - if (SHARED_OK != (r = shared_mux(idx, mode))) return(r); /* idx checked by shared_mux */ - if (NULL == shared_lt[idx].p) - if (SHARED_OK != (r = shared_map(idx))) - { shared_demux(idx, mode); - return(r); - } - if ((SHARED_ID_0 != (shared_lt[idx].p)->s.ID[0]) || (SHARED_ID_1 != (shared_lt[idx].p)->s.ID[1]) || (BLOCK_SHARED != (shared_lt[idx].p)->s.tflag)) - { shared_demux(idx, mode); - return(r); - } - return(SHARED_OK); - } - - -SHARED_P shared_realloc(int idx, long newsize) /* realloc shared memory segment */ - { int h, key, i, r; - BLKHEAD *bp; - long transfersize; - - r = SHARED_OK; - if (newsize < 0) return(NULL); - if (shared_check_locked_index(idx)) return(NULL); - if (0 == (shared_gt[idx].attr & SHARED_RESIZE)) return(NULL); - if (-1 != shared_lt[idx].lkcnt) return(NULL); /* check for RW lock */ - if (shared_adjust_size(shared_gt[idx].size) == shared_adjust_size(newsize)) - { shared_gt[idx].size = newsize; - - return((SHARED_P)((shared_lt[idx].p) + 1)); - } - for (i = 0; ; i++) - { if (i >= shared_range) return(NULL); /* table full, signal error & exit */ - key = shared_kbase + ((i + shared_get_hash(newsize, idx)) % shared_range); - h = shmget(key, shared_adjust_size(newsize), IPC_CREAT | IPC_EXCL | shared_create_mode); - if (SHARED_INVALID == h) continue; /* segment already accupied */ - bp = (BLKHEAD *)shmat(h, 0, 0); /* try attach */ - if (((BLKHEAD *)SHARED_INVALID) == bp) /* cannot attach, delete segment, try with another key */ - { shmctl(h, IPC_RMID, 0); - continue; - } - *bp = *(shared_lt[idx].p); /* copy header, then data */ - transfersize = ((newsize < shared_gt[idx].size) ? newsize : shared_gt[idx].size); - if (transfersize > 0) - memcpy((void *)(bp + 1), (void *)((shared_lt[idx].p) + 1), transfersize); - if (shmdt((char *)(shared_lt[idx].p))) r = SHARED_IPCERR; /* try to detach old segment */ - if (shmctl(shared_gt[idx].handle, IPC_RMID, 0)) if (SHARED_OK == r) r = SHARED_IPCERR; /* destroy old shared memory segment */ - shared_gt[idx].size = newsize; /* signal new size */ - shared_gt[idx].handle = h; /* signal new handle */ - shared_gt[idx].key = key; /* signal new key */ - shared_lt[idx].p = bp; - break; - } - return((SHARED_P)(bp + 1)); - } - - -int shared_free(int idx) /* detach segment, if last process & !PERSIST, destroy segment */ - { int cnt, r, r2; - - if (SHARED_OK != (r = shared_validate(idx, SHARED_RDWRITE | SHARED_WAIT))) return(r); - if (SHARED_OK != (r = shared_detach_process(shared_gt[idx].sem))) /* update number of processes using segment */ - { shared_demux(idx, SHARED_RDWRITE); - return(r); - } - shared_lt[idx].tcnt--; /* update number of threads using segment */ - if (shared_lt[idx].tcnt > 0) return(shared_demux(idx, SHARED_RDWRITE)); /* if more threads are using segment we are done */ - if (shmdt((char *)(shared_lt[idx].p))) /* if, we are the last thread, try to detach segment */ - { shared_demux(idx, SHARED_RDWRITE); - return(SHARED_IPCERR); - } - shared_lt[idx].p = NULL; /* clear entry in local table */ - shared_lt[idx].seekpos = 0L; /* r/w pointer positioned at beg of block */ - if (-1 == (cnt = shared_process_count(shared_gt[idx].sem))) /* get number of processes hanging on segment */ - { shared_demux(idx, SHARED_RDWRITE); - return(SHARED_IPCERR); - } - if ((0 == cnt) && (0 == (shared_gt[idx].attr & SHARED_PERSIST))) r = shared_destroy_entry(idx); /* no procs on seg, destroy it */ - r2 = shared_demux(idx, SHARED_RDWRITE); - return(r ? r : r2); - } - - -SHARED_P shared_lock(int idx, int mode) /* lock given segment for exclusive access */ - { int r; - - if (shared_mux(idx, mode)) return(NULL); /* idx checked by shared_mux */ - if (0 != shared_lt[idx].lkcnt) /* are we already locked ?? */ - if (SHARED_OK != (r = shared_map(idx))) - { shared_demux(idx, mode); - return(NULL); - } - if (NULL == shared_lt[idx].p) /* stupid pointer ?? */ - if (SHARED_OK != (r = shared_map(idx))) - { shared_demux(idx, mode); - return(NULL); - } - if ((SHARED_ID_0 != (shared_lt[idx].p)->s.ID[0]) || (SHARED_ID_1 != (shared_lt[idx].p)->s.ID[1]) || (BLOCK_SHARED != (shared_lt[idx].p)->s.tflag)) - { shared_demux(idx, mode); - return(NULL); - } - if (mode & SHARED_RDWRITE) - { shared_lt[idx].lkcnt = -1; - - shared_gt[idx].nprocdebug++; - } - - else shared_lt[idx].lkcnt++; - shared_lt[idx].seekpos = 0L; /* r/w pointer positioned at beg of block */ - return((SHARED_P)((shared_lt[idx].p) + 1)); - } - - -int shared_unlock(int idx) /* unlock given segment, assumes seg is locked !! */ - { int r, r2, mode; - - if (SHARED_OK != (r = shared_check_locked_index(idx))) return(r); - if (shared_lt[idx].lkcnt > 0) - { shared_lt[idx].lkcnt--; /* unlock read lock */ - mode = SHARED_RDONLY; - } - else - { shared_lt[idx].lkcnt = 0; /* unlock write lock */ - shared_gt[idx].nprocdebug--; - mode = SHARED_RDWRITE; - } - if (0 == shared_lt[idx].lkcnt) if (shared_gt[idx].attr & SHARED_RESIZE) - { if (shmdt((char *)(shared_lt[idx].p))) r = SHARED_IPCERR; /* segment is resizable, then detach segment */ - shared_lt[idx].p = NULL; /* signal detachment in local table */ - } - r2 = shared_demux(idx, mode); /* unlock segment, rest is only parameter checking */ - return(r ? r : r2); - } - - /* API routines - support and info routines */ - - -int shared_attr(int idx) /* get the attributes of the shared memory segment */ - { int r; - - if (shared_check_locked_index(idx)) return(SHARED_INVALID); - r = shared_gt[idx].attr; - return(r); - } - - -int shared_set_attr(int idx, int newattr) /* get the attributes of the shared memory segment */ - { int r; - - if (shared_check_locked_index(idx)) return(SHARED_INVALID); - if (-1 != shared_lt[idx].lkcnt) return(SHARED_INVALID); /* ADDED - check for RW lock */ - r = shared_gt[idx].attr; - shared_gt[idx].attr = newattr; - return(r); - - } - - -int shared_set_debug(int mode) /* set/reset debug mode */ - { int r = shared_debug; - - shared_debug = mode; - return(r); - } - - -int shared_set_createmode(int mode) /* set/reset debug mode */ - { int r = shared_create_mode; - - shared_create_mode = mode; - return(r); - } - - - - -int shared_list(int id) - { int i, r; - - if (NULL == shared_gt) return(SHARED_NOTINIT); /* not initialized */ - if (NULL == shared_lt) return(SHARED_NOTINIT); /* not initialized */ - if (shared_debug) printf("shared_list:"); - r = SHARED_OK; - printf(" Idx Key Nproc Size Flags\n"); - printf("==============================================\n"); - for (i=0; i= SHARED_ERRBASE) - { printf(" cannot clear PERSIST attribute"); - } - if (shared_free(i)) - { printf(" delete failed\n"); - } - else - { printf(" deleted\n"); - } - } - if (shared_debug) printf(" done\n"); - return(r); /* table full */ - } - - -/************************* CFITSIO DRIVER FUNCTIONS ***************************/ - -int smem_init(void) - { return(0); - } - -int smem_shutdown(void) - - { if (shared_init_called) shared_cleanup(); - return(0); - } - -int smem_setoptions(int option) - { option = 0; - return(0); - } - - -int smem_getoptions(int *options) - { if (NULL == options) return(SHARED_NULPTR); - *options = 0; - return(0); - } - -int smem_getversion(int *version) - { if (NULL == version) return(SHARED_NULPTR); - *version = 10; - return(0); - } - - -int smem_open(char *filename, int rwmode, int *driverhandle) - { int h, nitems, r; - DAL_SHM_SEGHEAD *sp; - - - if (NULL == filename) return(SHARED_NULPTR); - if (NULL == driverhandle) return(SHARED_NULPTR); - nitems = sscanf(filename, "h%d", &h); - if (1 != nitems) return(SHARED_BADARG); - - if (SHARED_OK != (r = shared_attach(h))) return(r); - - if (NULL == (sp = (DAL_SHM_SEGHEAD *)shared_lock(h, - ((READWRITE == rwmode) ? SHARED_RDWRITE : SHARED_RDONLY)))) - { shared_free(h); - return(SHARED_BADARG); - } - - if ((h != sp->h) || (DAL_SHM_SEGHEAD_ID != sp->ID)) - { shared_unlock(h); - shared_free(h); - - return(SHARED_BADARG); - } - - *driverhandle = h; - return(0); - } - - -int smem_create(char *filename, int *driverhandle) - { DAL_SHM_SEGHEAD *sp; - int h, sz, nitems; - - if (NULL == filename) return(SHARED_NULPTR); /* currently ignored */ - if (NULL == driverhandle) return(SHARED_NULPTR); - nitems = sscanf(filename, "h%d", &h); - if (1 != nitems) return(SHARED_BADARG); - - if (SHARED_INVALID == (h = shared_malloc(sz = 2880 + sizeof(DAL_SHM_SEGHEAD), - SHARED_RESIZE | SHARED_PERSIST, h))) - return(SHARED_NOMEM); - - if (NULL == (sp = (DAL_SHM_SEGHEAD *)shared_lock(h, SHARED_RDWRITE))) - { shared_free(h); - return(SHARED_BADARG); - } - - sp->ID = DAL_SHM_SEGHEAD_ID; - sp->h = h; - sp->size = sz; - sp->nodeidx = -1; - - *driverhandle = h; - - return(0); - } - - -int smem_close(int driverhandle) - { int r; - - if (SHARED_OK != (r = shared_unlock(driverhandle))) return(r); - return(shared_free(driverhandle)); - } - -int smem_remove(char *filename) - { int nitems, h, r; - - if (NULL == filename) return(SHARED_NULPTR); - nitems = sscanf(filename, "h%d", &h); - if (1 != nitems) return(SHARED_BADARG); - - if (0 == shared_check_locked_index(h)) /* are we locked ? */ - - { if (-1 != shared_lt[h].lkcnt) /* are we locked RO ? */ - { if (SHARED_OK != (r = shared_unlock(h))) return(r); /* yes, so relock in RW */ - if (NULL == shared_lock(h, SHARED_RDWRITE)) return(SHARED_BADARG); - } - - } - else /* not locked */ - { if (SHARED_OK != (r = smem_open(filename, READWRITE, &h))) - return(r); /* so open in RW mode */ - } - - shared_set_attr(h, SHARED_RESIZE); /* delete PERSIST attribute */ - return(smem_close(h)); /* detach segment (this will delete it) */ - } - -int smem_size(int driverhandle, LONGLONG *size) - { - if (NULL == size) return(SHARED_NULPTR); - if (shared_check_locked_index(driverhandle)) return(SHARED_INVALID); - *size = (LONGLONG) (shared_gt[driverhandle].size - sizeof(DAL_SHM_SEGHEAD)); - return(0); - } - -int smem_flush(int driverhandle) - { - if (shared_check_locked_index(driverhandle)) return(SHARED_INVALID); - return(0); - } - -int smem_seek(int driverhandle, LONGLONG offset) - { - if (offset < 0) return(SHARED_BADARG); - if (shared_check_locked_index(driverhandle)) return(SHARED_INVALID); - shared_lt[driverhandle].seekpos = offset; - return(0); - } - -int smem_read(int driverhandle, void *buffer, long nbytes) - { - if (NULL == buffer) return(SHARED_NULPTR); - if (shared_check_locked_index(driverhandle)) return(SHARED_INVALID); - if (nbytes < 0) return(SHARED_BADARG); - if ((shared_lt[driverhandle].seekpos + nbytes) > shared_gt[driverhandle].size) - return(SHARED_BADARG); /* read beyond EOF */ - - memcpy(buffer, - ((char *)(((DAL_SHM_SEGHEAD *)(shared_lt[driverhandle].p + 1)) + 1)) + - shared_lt[driverhandle].seekpos, - nbytes); - - shared_lt[driverhandle].seekpos += nbytes; - return(0); - } - -int smem_write(int driverhandle, void *buffer, long nbytes) - { - if (NULL == buffer) return(SHARED_NULPTR); - if (shared_check_locked_index(driverhandle)) return(SHARED_INVALID); - if (-1 != shared_lt[driverhandle].lkcnt) return(SHARED_INVALID); /* are we locked RW ? */ - - if (nbytes < 0) return(SHARED_BADARG); - if ((unsigned long)(shared_lt[driverhandle].seekpos + nbytes) > (unsigned long)(shared_gt[driverhandle].size - sizeof(DAL_SHM_SEGHEAD))) - { /* need to realloc shmem */ - if (NULL == shared_realloc(driverhandle, shared_lt[driverhandle].seekpos + nbytes + sizeof(DAL_SHM_SEGHEAD))) - return(SHARED_NOMEM); - } - - memcpy(((char *)(((DAL_SHM_SEGHEAD *)(shared_lt[driverhandle].p + 1)) + 1)) + - shared_lt[driverhandle].seekpos, - buffer, - nbytes); - - shared_lt[driverhandle].seekpos += nbytes; - return(0); - } -#endif diff --git a/src/external/OpenGR/3rdparty/cfitsio/drvrsmem.h b/src/external/OpenGR/3rdparty/cfitsio/drvrsmem.h deleted file mode 100644 index 52ac7d7c8..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/drvrsmem.h +++ /dev/null @@ -1,179 +0,0 @@ -/* S H A R E D M E M O R Y D R I V E R - ======================================= - - by Jerzy.Borkowski@obs.unige.ch - -09-Mar-98 : initial version 1.0 released -23-Mar-98 : shared_malloc now accepts new handle as an argument -*/ - - -#include /* this is necessary for Solaris/Linux */ -#include -#include - -#ifdef _AIX -#include -#else -#include -#endif - - /* configuration parameters */ - -#define SHARED_MAXSEG (16) /* maximum number of shared memory blocks */ - -#define SHARED_KEYBASE (14011963) /* base for shared memory keys, may be overriden by getenv */ -#define SHARED_FDNAME ("/tmp/.shmem-lockfile") /* template for lock file name */ - -#define SHARED_ENV_KEYBASE ("SHMEM_LIB_KEYBASE") /* name of environment variable */ -#define SHARED_ENV_MAXSEG ("SHMEM_LIB_MAXSEG") /* name of environment variable */ - - /* useful constants */ - -#define SHARED_RDONLY (0) /* flag for shared_(un)lock, lock for read */ -#define SHARED_RDWRITE (1) /* flag for shared_(un)lock, lock for write */ -#define SHARED_WAIT (0) /* flag for shared_lock, block if cannot lock immediate */ -#define SHARED_NOWAIT (2) /* flag for shared_lock, fail if cannot lock immediate */ -#define SHARED_NOLOCK (0x100) /* flag for shared_validate function */ - -#define SHARED_RESIZE (4) /* flag for shared_malloc, object is resizeable */ -#define SHARED_PERSIST (8) /* flag for shared_malloc, object is not deleted after last proc detaches */ - -#define SHARED_INVALID (-1) /* invalid handle for semaphore/shared memory */ - -#define SHARED_EMPTY (0) /* entries for shared_used table */ -#define SHARED_USED (1) - -#define SHARED_GRANUL (16384) /* granularity of shared_malloc allocation = phys page size, system dependent */ - - - - /* checkpoints in shared memory segments - might be omitted */ - -#define SHARED_ID_0 ('J') /* first byte of identifier in BLKHEAD */ -#define SHARED_ID_1 ('B') /* second byte of identifier in BLKHEAD */ - -#define BLOCK_REG (0) /* value for tflag member of BLKHEAD */ -#define BLOCK_SHARED (1) /* value for tflag member of BLKHEAD */ - - /* generic error codes */ - -#define SHARED_OK (0) - -#define SHARED_ERR_MIN_IDX SHARED_BADARG -#define SHARED_ERR_MAX_IDX SHARED_NORESIZE - - -#define DAL_SHM_FREE (0) -#define DAL_SHM_USED (1) - -#define DAL_SHM_ID0 ('D') -#define DAL_SHM_ID1 ('S') -#define DAL_SHM_ID2 ('M') - -#define DAL_SHM_SEGHEAD_ID (0x19630114) - - - - /* data types */ - -/* BLKHEAD object is placed at the beginning of every memory segment (both - shared and regular) to allow automatic recognition of segments type */ - -typedef union - { struct BLKHEADstruct - { char ID[2]; /* ID = 'JB', just as a checkpoint */ - char tflag; /* is it shared memory or regular one ? */ - int handle; /* this is not necessary, used only for non-resizeable objects via ptr */ - } s; - double d; /* for proper alignment on every machine */ - } BLKHEAD; - -typedef void *SHARED_P; /* generic type of shared memory pointer */ - -typedef struct SHARED_GTABstruct /* data type used in global table */ - { int sem; /* access semaphore (1 field): process count */ - int semkey; /* key value used to generate semaphore handle */ - int key; /* key value used to generate shared memory handle (realloc changes it) */ - int handle; /* handle of shared memory segment */ - int size; /* size of shared memory segment */ - int nprocdebug; /* attached proc counter, helps remove zombie segments */ - char attr; /* attributes of shared memory object */ - } SHARED_GTAB; - -typedef struct SHARED_LTABstruct /* data type used in local table */ - { BLKHEAD *p; /* pointer to segment (may be null) */ - int tcnt; /* number of threads in this process attached to segment */ - int lkcnt; /* >=0 <- number of read locks, -1 - write lock */ - long seekpos; /* current pointer position, read/write/seek operations change it */ - } SHARED_LTAB; - - - /* system dependent definitions */ - -#ifndef HAVE_FLOCK_T -typedef struct flock flock_t; -#define HAVE_FLOCK_T -#endif - -#ifndef HAVE_UNION_SEMUN -union semun - { int val; - struct semid_ds *buf; - unsigned short *array; - }; -#define HAVE_UNION_SEMUN -#endif - - -typedef struct DAL_SHM_SEGHEAD_STRUCT DAL_SHM_SEGHEAD; - -struct DAL_SHM_SEGHEAD_STRUCT - { int ID; /* ID for debugging */ - int h; /* handle of sh. mem */ - int size; /* size of data area */ - int nodeidx; /* offset of root object (node struct typically) */ - }; - - /* API routines */ - -#ifdef __cplusplus -extern "C" { -#endif - -void shared_cleanup(void); /* must be called at exit/abort */ -int shared_init(int debug_msgs); /* must be called before any other shared memory routine */ -int shared_recover(int id); /* try to recover dormant segment(s) after applic crash */ -int shared_malloc(long size, int mode, int newhandle); /* allocate n-bytes of shared memory */ -int shared_attach(int idx); /* attach to segment given index to table */ -int shared_free(int idx); /* release shared memory */ -SHARED_P shared_lock(int idx, int mode); /* lock segment for reading */ -SHARED_P shared_realloc(int idx, long newsize); /* reallocate n-bytes of shared memory (ON LOCKED SEGMENT ONLY) */ -int shared_size(int idx); /* get size of attached shared memory segment (ON LOCKED SEGMENT ONLY) */ -int shared_attr(int idx); /* get attributes of attached shared memory segment (ON LOCKED SEGMENT ONLY) */ -int shared_set_attr(int idx, int newattr); /* set attributes of attached shared memory segment (ON LOCKED SEGMENT ONLY) */ -int shared_unlock(int idx); /* unlock segment (ON LOCKED SEGMENT ONLY) */ -int shared_set_debug(int debug_msgs); /* set/reset debug mode */ -int shared_set_createmode(int mode); /* set/reset debug mode */ -int shared_list(int id); /* list segment(s) */ -int shared_uncond_delete(int id); /* uncondintionally delete (NOWAIT operation) segment(s) */ -int shared_getaddr(int id, char **address); /* get starting address of FITS file in segment */ - -int smem_init(void); -int smem_shutdown(void); -int smem_setoptions(int options); -int smem_getoptions(int *options); -int smem_getversion(int *version); -int smem_open(char *filename, int rwmode, int *driverhandle); -int smem_create(char *filename, int *driverhandle); -int smem_close(int driverhandle); -int smem_remove(char *filename); -int smem_size(int driverhandle, LONGLONG *size); -int smem_flush(int driverhandle); -int smem_seek(int driverhandle, LONGLONG offset); -int smem_read(int driverhandle, void *buffer, long nbytes); -int smem_write(int driverhandle, void *buffer, long nbytes); - -#ifdef __cplusplus -} -#endif diff --git a/src/external/OpenGR/3rdparty/cfitsio/editcol.c b/src/external/OpenGR/3rdparty/cfitsio/editcol.c deleted file mode 100644 index b280c4b1c..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/editcol.c +++ /dev/null @@ -1,2493 +0,0 @@ -/* This file, editcol.c, contains the set of FITSIO routines that */ -/* insert or delete rows or columns in a table or resize an image */ - -/* The FITSIO software was written by William Pence at the High Energy */ -/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ -/* Goddard Space Flight Center. */ - -#include -#include -#include -#include "fitsio2.h" -/*--------------------------------------------------------------------------*/ -int ffrsim(fitsfile *fptr, /* I - FITS file pointer */ - int bitpix, /* I - bits per pixel */ - int naxis, /* I - number of axes in the array */ - long *naxes, /* I - size of each axis */ - int *status) /* IO - error status */ -/* - resize an existing primary array or IMAGE extension. -*/ -{ - LONGLONG tnaxes[99]; - int ii; - - if (*status > 0) - return(*status); - - for (ii = 0; (ii < naxis) && (ii < 99); ii++) - tnaxes[ii] = naxes[ii]; - - ffrsimll(fptr, bitpix, naxis, tnaxes, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffrsimll(fitsfile *fptr, /* I - FITS file pointer */ - int bitpix, /* I - bits per pixel */ - int naxis, /* I - number of axes in the array */ - LONGLONG *naxes, /* I - size of each axis */ - int *status) /* IO - error status */ -/* - resize an existing primary array or IMAGE extension. -*/ -{ - int ii, simple, obitpix, onaxis, extend, nmodify; - long nblocks, longval; - long pcount, gcount, longbitpix; - LONGLONG onaxes[99], newsize, oldsize; - char comment[FLEN_COMMENT], keyname[FLEN_KEYWORD], message[FLEN_ERRMSG]; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - } - /* rescan header if data structure is undefined */ - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) - return(*status); - - /* get current image size parameters */ - if (ffghprll(fptr, 99, &simple, &obitpix, &onaxis, onaxes, &pcount, - &gcount, &extend, status) > 0) - return(*status); - - longbitpix = bitpix; - - /* test for the 2 special cases that represent unsigned integers */ - if (longbitpix == USHORT_IMG) - longbitpix = SHORT_IMG; - else if (longbitpix == ULONG_IMG) - longbitpix = LONG_IMG; - - /* test that the new values are legal */ - - if (longbitpix != BYTE_IMG && longbitpix != SHORT_IMG && - longbitpix != LONG_IMG && longbitpix != LONGLONG_IMG && - longbitpix != FLOAT_IMG && longbitpix != DOUBLE_IMG) - { - sprintf(message, - "Illegal value for BITPIX keyword: %d", bitpix); - ffpmsg(message); - return(*status = BAD_BITPIX); - } - - if (naxis < 0 || naxis > 999) - { - sprintf(message, - "Illegal value for NAXIS keyword: %d", naxis); - ffpmsg(message); - return(*status = BAD_NAXIS); - } - - if (naxis == 0) - newsize = 0; - else - newsize = 1; - - for (ii = 0; ii < naxis; ii++) - { - if (naxes[ii] < 0) - { - sprintf(message, - "Illegal value for NAXIS%d keyword: %.0f", ii + 1, (double) (naxes[ii])); - ffpmsg(message); - return(*status = BAD_NAXES); - } - - newsize *= naxes[ii]; /* compute new image size, in pixels */ - } - - /* compute size of old image, in bytes */ - - if (onaxis == 0) - oldsize = 0; - else - { - oldsize = 1; - for (ii = 0; ii < onaxis; ii++) - oldsize *= onaxes[ii]; - oldsize = (oldsize + pcount) * gcount * (abs(obitpix) / 8); - } - - oldsize = (oldsize + 2879) / 2880; /* old size, in blocks */ - - newsize = (newsize + pcount) * gcount * (abs(longbitpix) / 8); - newsize = (newsize + 2879) / 2880; /* new size, in blocks */ - - if (newsize > oldsize) /* have to insert new blocks for image */ - { - nblocks = (long) (newsize - oldsize); - if (ffiblk(fptr, nblocks, 1, status) > 0) - return(*status); - } - else if (oldsize > newsize) /* have to delete blocks from image */ - { - nblocks = (long) (oldsize - newsize); - if (ffdblk(fptr, nblocks, status) > 0) - return(*status); - } - - /* now update the header keywords */ - - strcpy(comment,"&"); /* special value to leave comments unchanged */ - - if (longbitpix != obitpix) - { /* update BITPIX value */ - ffmkyj(fptr, "BITPIX", longbitpix, comment, status); - } - - if (naxis != onaxis) - { /* update NAXIS value */ - longval = naxis; - ffmkyj(fptr, "NAXIS", longval, comment, status); - } - - /* modify the existing NAXISn keywords */ - nmodify = minvalue(naxis, onaxis); - for (ii = 0; ii < nmodify; ii++) - { - ffkeyn("NAXIS", ii+1, keyname, status); - ffmkyj(fptr, keyname, naxes[ii], comment, status); - } - - if (naxis > onaxis) /* insert additional NAXISn keywords */ - { - strcpy(comment,"length of data axis"); - for (ii = onaxis; ii < naxis; ii++) - { - ffkeyn("NAXIS", ii+1, keyname, status); - ffikyj(fptr, keyname, naxes[ii], comment, status); - } - } - else if (onaxis > naxis) /* delete old NAXISn keywords */ - { - for (ii = naxis; ii < onaxis; ii++) - { - ffkeyn("NAXIS", ii+1, keyname, status); - ffdkey(fptr, keyname, status); - } - } - - /* Update the BSCALE and BZERO keywords, if an unsigned integer image */ - if (bitpix == USHORT_IMG) - { - strcpy(comment, "offset data range to that of unsigned short"); - ffukyg(fptr, "BZERO", 32768., 0, comment, status); - strcpy(comment, "default scaling factor"); - ffukyg(fptr, "BSCALE", 1.0, 0, comment, status); - } - else if (bitpix == ULONG_IMG) - { - strcpy(comment, "offset data range to that of unsigned long"); - ffukyg(fptr, "BZERO", 2147483648., 0, comment, status); - strcpy(comment, "default scaling factor"); - ffukyg(fptr, "BSCALE", 1.0, 0, comment, status); - } - - /* re-read the header, to make sure structures are updated */ - ffrdef(fptr, status); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffirow(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG firstrow, /* I - insert space AFTER this row */ - /* 0 = insert space at beginning of table */ - LONGLONG nrows, /* I - number of rows to insert */ - int *status) /* IO - error status */ -/* - insert NROWS blank rows immediated after row firstrow (1 = first row). - Set firstrow = 0 to insert space at the beginning of the table. -*/ -{ - int tstatus; - LONGLONG naxis1, naxis2; - LONGLONG datasize, firstbyte, nshift, nbytes; - LONGLONG freespace; - long nblock; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - } - /* rescan header if data structure is undefined */ - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - { - ffpmsg("Can only add rows to TABLE or BINTABLE extension (ffirow)"); - return(*status = NOT_TABLE); - } - - if (nrows < 0 ) - return(*status = NEG_BYTES); - else if (nrows == 0) - return(*status); /* no op, so just return */ - - /* get the current size of the table */ - /* use internal structure since NAXIS2 keyword may not be up to date */ - naxis1 = (fptr->Fptr)->rowlength; - naxis2 = (fptr->Fptr)->numrows; - - if (firstrow > naxis2) - { - ffpmsg( - "Insert position greater than the number of rows in the table (ffirow)"); - return(*status = BAD_ROW_NUM); - } - else if (firstrow < 0) - { - ffpmsg("Insert position is less than 0 (ffirow)"); - return(*status = BAD_ROW_NUM); - } - - /* current data size */ - datasize = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; - freespace = ( ( (datasize + 2879) / 2880) * 2880) - datasize; - nshift = naxis1 * nrows; /* no. of bytes to add to table */ - - if ( (freespace - nshift) < 0) /* not enough existing space? */ - { - nblock = (long) ((nshift - freespace + 2879) / 2880); /* number of blocks */ - ffiblk(fptr, nblock, 1, status); /* insert the blocks */ - } - - firstbyte = naxis1 * firstrow; /* relative insert position */ - nbytes = datasize - firstbyte; /* no. of bytes to shift down */ - firstbyte += ((fptr->Fptr)->datastart); /* absolute insert position */ - - ffshft(fptr, firstbyte, nbytes, nshift, status); /* shift rows and heap */ - - /* update the heap starting address */ - (fptr->Fptr)->heapstart += nshift; - - /* update the THEAP keyword if it exists */ - tstatus = 0; - ffmkyj(fptr, "THEAP", (fptr->Fptr)->heapstart, "&", &tstatus); - - /* update the NAXIS2 keyword */ - ffmkyj(fptr, "NAXIS2", naxis2 + nrows, "&", status); - ((fptr->Fptr)->numrows) += nrows; - ((fptr->Fptr)->origrows) += nrows; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffdrow(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG firstrow, /* I - first row to delete (1 = first) */ - LONGLONG nrows, /* I - number of rows to delete */ - int *status) /* IO - error status */ -/* - delete NROWS rows from table starting with firstrow (1 = first row of table). -*/ -{ - int tstatus; - LONGLONG naxis1, naxis2; - LONGLONG datasize, firstbyte, nbytes, nshift; - LONGLONG freespace; - long nblock; - char comm[FLEN_COMMENT]; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - } - /* rescan header if data structure is undefined */ - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - { - ffpmsg("Can only delete rows in TABLE or BINTABLE extension (ffdrow)"); - return(*status = NOT_TABLE); - } - - if (nrows < 0 ) - return(*status = NEG_BYTES); - else if (nrows == 0) - return(*status); /* no op, so just return */ - - ffgkyjj(fptr, "NAXIS1", &naxis1, comm, status); /* get the current */ - - /* ffgkyj(fptr, "NAXIS2", &naxis2, comm, status);*/ /* size of the table */ - - /* the NAXIS2 keyword may not be up to date, so use the structure value */ - naxis2 = (fptr->Fptr)->numrows; - - if (firstrow > naxis2) - { - ffpmsg( - "Delete position greater than the number of rows in the table (ffdrow)"); - return(*status = BAD_ROW_NUM); - } - else if (firstrow < 1) - { - ffpmsg("Delete position is less than 1 (ffdrow)"); - return(*status = BAD_ROW_NUM); - } - else if (firstrow + nrows - 1 > naxis2) - { - ffpmsg("No. of rows to delete exceeds size of table (ffdrow)"); - return(*status = BAD_ROW_NUM); - } - - nshift = naxis1 * nrows; /* no. of bytes to delete from table */ - /* cur size of data */ - datasize = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; - - firstbyte = naxis1 * (firstrow + nrows - 1); /* relative del pos */ - nbytes = datasize - firstbyte; /* no. of bytes to shift up */ - firstbyte += ((fptr->Fptr)->datastart); /* absolute delete position */ - - ffshft(fptr, firstbyte, nbytes, nshift * (-1), status); /* shift data */ - - freespace = ( ( (datasize + 2879) / 2880) * 2880) - datasize; - nblock = (long) ((nshift + freespace) / 2880); /* number of blocks */ - - /* delete integral number blocks */ - if (nblock > 0) - ffdblk(fptr, nblock, status); - - /* update the heap starting address */ - (fptr->Fptr)->heapstart -= nshift; - - /* update the THEAP keyword if it exists */ - tstatus = 0; - ffmkyj(fptr, "THEAP", (long)(fptr->Fptr)->heapstart, "&", &tstatus); - - /* update the NAXIS2 keyword */ - ffmkyj(fptr, "NAXIS2", naxis2 - nrows, "&", status); - ((fptr->Fptr)->numrows) -= nrows; - ((fptr->Fptr)->origrows) -= nrows; - - /* Update the heap data, if any. This will remove any orphaned data */ - /* that was only pointed to by the rows that have been deleted */ - ffcmph(fptr, status); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffdrrg(fitsfile *fptr, /* I - FITS file pointer to table */ - char *ranges, /* I - ranges of rows to delete (1 = first) */ - int *status) /* IO - error status */ -/* - delete the ranges of rows from the table (1 = first row of table). - -The 'ranges' parameter typically looks like: - '10-20, 30 - 40, 55' or '50-' -and gives a list of rows or row ranges separated by commas. -*/ -{ - char *cptr; - int nranges, nranges2, ii; - long *minrow, *maxrow, nrows, *rowarray, jj, kk; - LONGLONG naxis2; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - } - /* rescan header if data structure is undefined */ - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - { - ffpmsg("Can only delete rows in TABLE or BINTABLE extension (ffdrrg)"); - return(*status = NOT_TABLE); - } - - /* the NAXIS2 keyword may not be up to date, so use the structure value */ - naxis2 = (fptr->Fptr)->numrows; - - /* find how many ranges were specified ( = no. of commas in string + 1) */ - cptr = ranges; - for (nranges = 1; (cptr = strchr(cptr, ',')); nranges++) - cptr++; - - minrow = calloc(nranges, sizeof(long)); - maxrow = calloc(nranges, sizeof(long)); - - if (!minrow || !maxrow) { - *status = MEMORY_ALLOCATION; - ffpmsg("failed to allocate memory for row ranges (ffdrrg)"); - if (maxrow) free(maxrow); - if (minrow) free(minrow); - return(*status); - } - - /* parse range list into array of range min and max values */ - ffrwrg(ranges, naxis2, nranges, &nranges2, minrow, maxrow, status); - if (*status > 0 || nranges2 == 0) { - free(maxrow); - free(minrow); - return(*status); - } - - /* determine total number or rows to delete */ - nrows = 0; - for (ii = 0; ii < nranges2; ii++) { - nrows = nrows + maxrow[ii] - minrow[ii] + 1; - } - - rowarray = calloc(nrows, sizeof(long)); - if (!rowarray) { - *status = MEMORY_ALLOCATION; - ffpmsg("failed to allocate memory for row array (ffdrrg)"); - return(*status); - } - - for (kk = 0, ii = 0; ii < nranges2; ii++) { - for (jj = minrow[ii]; jj <= maxrow[ii]; jj++) { - rowarray[kk] = jj; - kk++; - } - } - - /* delete the rows */ - ffdrws(fptr, rowarray, nrows, status); - - free(rowarray); - free(maxrow); - free(minrow); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffdrws(fitsfile *fptr, /* I - FITS file pointer */ - long *rownum, /* I - list of rows to delete (1 = first) */ - long nrows, /* I - number of rows to delete */ - int *status) /* IO - error status */ -/* - delete the list of rows from the table (1 = first row of table). -*/ -{ - LONGLONG naxis1, naxis2, insertpos, nextrowpos; - long ii, nextrow; - char comm[FLEN_COMMENT]; - unsigned char *buffer; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - /* rescan header if data structure is undefined */ - if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - { - ffpmsg("Can only delete rows in TABLE or BINTABLE extension (ffdrws)"); - return(*status = NOT_TABLE); - } - - if (nrows < 0 ) - return(*status = NEG_BYTES); - else if (nrows == 0) - return(*status); /* no op, so just return */ - - ffgkyjj(fptr, "NAXIS1", &naxis1, comm, status); /* row width */ - ffgkyjj(fptr, "NAXIS2", &naxis2, comm, status); /* number of rows */ - - /* check that input row list is in ascending order */ - for (ii = 1; ii < nrows; ii++) - { - if (rownum[ii - 1] >= rownum[ii]) - { - ffpmsg("row numbers are not in increasing order (ffdrws)"); - return(*status = BAD_ROW_NUM); - } - } - - if (rownum[0] < 1) - { - ffpmsg("first row to delete is less than 1 (ffdrws)"); - return(*status = BAD_ROW_NUM); - } - else if (rownum[nrows - 1] > naxis2) - { - ffpmsg("last row to delete exceeds size of table (ffdrws)"); - return(*status = BAD_ROW_NUM); - } - - buffer = (unsigned char *) malloc( (size_t) naxis1); /* buffer for one row */ - - if (!buffer) - { - ffpmsg("malloc failed (ffdrws)"); - return(*status = MEMORY_ALLOCATION); - } - - /* byte location to start of first row to delete, and the next row */ - insertpos = (fptr->Fptr)->datastart + ((rownum[0] - 1) * naxis1); - nextrowpos = insertpos + naxis1; - nextrow = rownum[0] + 1; - - /* work through the list of rows to delete */ - for (ii = 1; ii < nrows; nextrow++, nextrowpos += naxis1) - { - if (nextrow < rownum[ii]) - { /* keep this row, so copy it to the new position */ - - ffmbyt(fptr, nextrowpos, REPORT_EOF, status); - ffgbyt(fptr, naxis1, buffer, status); /* read the bytes */ - - ffmbyt(fptr, insertpos, IGNORE_EOF, status); - ffpbyt(fptr, naxis1, buffer, status); /* write the bytes */ - - if (*status > 0) - { - ffpmsg("error while copying good rows in table (ffdrws)"); - free(buffer); - return(*status); - } - insertpos += naxis1; - } - else - { /* skip over this row since it is in the list */ - ii++; - } - } - - /* finished with all the rows to delete; copy remaining rows */ - while(nextrow <= naxis2) - { - ffmbyt(fptr, nextrowpos, REPORT_EOF, status); - ffgbyt(fptr, naxis1, buffer, status); /* read the bytes */ - - ffmbyt(fptr, insertpos, IGNORE_EOF, status); - ffpbyt(fptr, naxis1, buffer, status); /* write the bytes */ - - if (*status > 0) - { - ffpmsg("failed to copy remaining rows in table (ffdrws)"); - free(buffer); - return(*status); - } - insertpos += naxis1; - nextrowpos += naxis1; - nextrow++; - } - free(buffer); - - /* now delete the empty rows at the end of the table */ - ffdrow(fptr, naxis2 - nrows + 1, nrows, status); - - /* Update the heap data, if any. This will remove any orphaned data */ - /* that was only pointed to by the rows that have been deleted */ - ffcmph(fptr, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffdrwsll(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG *rownum, /* I - list of rows to delete (1 = first) */ - LONGLONG nrows, /* I - number of rows to delete */ - int *status) /* IO - error status */ -/* - delete the list of rows from the table (1 = first row of table). -*/ -{ - LONGLONG insertpos, nextrowpos; - LONGLONG naxis1, naxis2, ii, nextrow; - char comm[FLEN_COMMENT]; - unsigned char *buffer; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - /* rescan header if data structure is undefined */ - if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - { - ffpmsg("Can only delete rows in TABLE or BINTABLE extension (ffdrws)"); - return(*status = NOT_TABLE); - } - - if (nrows < 0 ) - return(*status = NEG_BYTES); - else if (nrows == 0) - return(*status); /* no op, so just return */ - - ffgkyjj(fptr, "NAXIS1", &naxis1, comm, status); /* row width */ - ffgkyjj(fptr, "NAXIS2", &naxis2, comm, status); /* number of rows */ - - /* check that input row list is in ascending order */ - for (ii = 1; ii < nrows; ii++) - { - if (rownum[ii - 1] >= rownum[ii]) - { - ffpmsg("row numbers are not in increasing order (ffdrws)"); - return(*status = BAD_ROW_NUM); - } - } - - if (rownum[0] < 1) - { - ffpmsg("first row to delete is less than 1 (ffdrws)"); - return(*status = BAD_ROW_NUM); - } - else if (rownum[nrows - 1] > naxis2) - { - ffpmsg("last row to delete exceeds size of table (ffdrws)"); - return(*status = BAD_ROW_NUM); - } - - buffer = (unsigned char *) malloc( (size_t) naxis1); /* buffer for one row */ - - if (!buffer) - { - ffpmsg("malloc failed (ffdrwsll)"); - return(*status = MEMORY_ALLOCATION); - } - - /* byte location to start of first row to delete, and the next row */ - insertpos = (fptr->Fptr)->datastart + ((rownum[0] - 1) * naxis1); - nextrowpos = insertpos + naxis1; - nextrow = rownum[0] + 1; - - /* work through the list of rows to delete */ - for (ii = 1; ii < nrows; nextrow++, nextrowpos += naxis1) - { - if (nextrow < rownum[ii]) - { /* keep this row, so copy it to the new position */ - - ffmbyt(fptr, nextrowpos, REPORT_EOF, status); - ffgbyt(fptr, naxis1, buffer, status); /* read the bytes */ - - ffmbyt(fptr, insertpos, IGNORE_EOF, status); - ffpbyt(fptr, naxis1, buffer, status); /* write the bytes */ - - if (*status > 0) - { - ffpmsg("error while copying good rows in table (ffdrws)"); - free(buffer); - return(*status); - } - insertpos += naxis1; - } - else - { /* skip over this row since it is in the list */ - ii++; - } - } - - /* finished with all the rows to delete; copy remaining rows */ - while(nextrow <= naxis2) - { - ffmbyt(fptr, nextrowpos, REPORT_EOF, status); - ffgbyt(fptr, naxis1, buffer, status); /* read the bytes */ - - ffmbyt(fptr, insertpos, IGNORE_EOF, status); - ffpbyt(fptr, naxis1, buffer, status); /* write the bytes */ - - if (*status > 0) - { - ffpmsg("failed to copy remaining rows in table (ffdrws)"); - free(buffer); - return(*status); - } - insertpos += naxis1; - nextrowpos += naxis1; - nextrow++; - } - free(buffer); - - /* now delete the empty rows at the end of the table */ - ffdrow(fptr, naxis2 - nrows + 1, nrows, status); - - /* Update the heap data, if any. This will remove any orphaned data */ - /* that was only pointed to by the rows that have been deleted */ - ffcmph(fptr, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffrwrg( - char *rowlist, /* I - list of rows and row ranges */ - LONGLONG maxrows, /* I - number of rows in the table */ - int maxranges, /* I - max number of ranges to be returned */ - int *numranges, /* O - number ranges returned */ - long *minrow, /* O - first row in each range */ - long *maxrow, /* O - last row in each range */ - int *status) /* IO - status value */ -{ -/* - parse the input list of row ranges, returning the number of ranges, - and the min and max row value in each range. - - The only characters allowed in the input rowlist are - decimal digits, minus sign, and comma (and non-significant spaces) - - Example: - - list = "10-20, 30-35,50" - - would return numranges = 3, minrow[] = {10, 30, 50}, maxrow[] = {20, 35, 50} - - error is returned if min value of range is > max value of range or if the - ranges are not monotonically increasing. -*/ - char *next; - long minval, maxval; - - if (*status > 0) - return(*status); - - if (maxrows <= 0 ) { - *status = RANGE_PARSE_ERROR; - ffpmsg("Input maximum range value is <= 0 (fits_parse_ranges)"); - return(*status); - } - - next = rowlist; - *numranges = 0; - - while (*next == ' ')next++; /* skip spaces */ - - while (*next != '\0') { - - /* find min value of next range; *next must be '-' or a digit */ - if (*next == '-') { - minval = 1; /* implied minrow value = 1 */ - } else if ( isdigit((int) *next) ) { - minval = strtol(next, &next, 10); - } else { - *status = RANGE_PARSE_ERROR; - ffpmsg("Syntax error in this row range list:"); - ffpmsg(rowlist); - return(*status); - } - - while (*next == ' ')next++; /* skip spaces */ - - /* find max value of next range; *next must be '-', or ',' */ - if (*next == '-') { - next++; - while (*next == ' ')next++; /* skip spaces */ - - if ( isdigit((int) *next) ) { - maxval = strtol(next, &next, 10); - } else if (*next == ',' || *next == '\0') { - maxval = (long) maxrows; /* implied max value */ - } else { - *status = RANGE_PARSE_ERROR; - ffpmsg("Syntax error in this row range list:"); - ffpmsg(rowlist); - return(*status); - } - } else if (*next == ',' || *next == '\0') { - maxval = minval; /* only a single integer in this range */ - } else { - *status = RANGE_PARSE_ERROR; - ffpmsg("Syntax error in this row range list:"); - ffpmsg(rowlist); - return(*status); - } - - if (*numranges + 1 > maxranges) { - *status = RANGE_PARSE_ERROR; - ffpmsg("Overflowed maximum number of ranges (fits_parse_ranges)"); - return(*status); - } - - if (minval < 1 ) { - *status = RANGE_PARSE_ERROR; - ffpmsg("Syntax error in this row range list: row number < 1"); - ffpmsg(rowlist); - return(*status); - } - - if (maxval < minval) { - *status = RANGE_PARSE_ERROR; - ffpmsg("Syntax error in this row range list: min > max"); - ffpmsg(rowlist); - return(*status); - } - - if (*numranges > 0) { - if (minval <= maxrow[(*numranges) - 1]) { - *status = RANGE_PARSE_ERROR; - ffpmsg("Syntax error in this row range list. Range minimum is"); - ffpmsg(" less than or equal to previous range maximum"); - ffpmsg(rowlist); - return(*status); - } - } - - if (minval <= maxrows) { /* ignore range if greater than maxrows */ - if (maxval > maxrows) - maxval = (long) maxrows; - - minrow[*numranges] = minval; - maxrow[*numranges] = maxval; - - (*numranges)++; - } - - while (*next == ' ')next++; /* skip spaces */ - if (*next == ',') { - next++; - while (*next == ' ')next++; /* skip more spaces */ - } - } - - if (*numranges == 0) { /* a null string was entered */ - minrow[0] = 1; - maxrow[0] = (long) maxrows; - *numranges = 1; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffrwrgll( - char *rowlist, /* I - list of rows and row ranges */ - LONGLONG maxrows, /* I - number of rows in the list */ - int maxranges, /* I - max number of ranges to be returned */ - int *numranges, /* O - number ranges returned */ - LONGLONG *minrow, /* O - first row in each range */ - LONGLONG *maxrow, /* O - last row in each range */ - int *status) /* IO - status value */ -{ -/* - parse the input list of row ranges, returning the number of ranges, - and the min and max row value in each range. - - The only characters allowed in the input rowlist are - decimal digits, minus sign, and comma (and non-significant spaces) - - Example: - - list = "10-20, 30-35,50" - - would return numranges = 3, minrow[] = {10, 30, 50}, maxrow[] = {20, 35, 50} - - error is returned if min value of range is > max value of range or if the - ranges are not monotonically increasing. -*/ - char *next; - LONGLONG minval, maxval; - double dvalue; - - if (*status > 0) - return(*status); - - if (maxrows <= 0 ) { - *status = RANGE_PARSE_ERROR; - ffpmsg("Input maximum range value is <= 0 (fits_parse_ranges)"); - return(*status); - } - - next = rowlist; - *numranges = 0; - - while (*next == ' ')next++; /* skip spaces */ - - while (*next != '\0') { - - /* find min value of next range; *next must be '-' or a digit */ - if (*next == '-') { - minval = 1; /* implied minrow value = 1 */ - } else if ( isdigit((int) *next) ) { - - /* read as a double, because the string to LONGLONG function */ - /* is platform dependent (strtoll, strtol, _atoI64) */ - - dvalue = strtod(next, &next); - minval = (LONGLONG) (dvalue + 0.1); - - } else { - *status = RANGE_PARSE_ERROR; - ffpmsg("Syntax error in this row range list:"); - ffpmsg(rowlist); - return(*status); - } - - while (*next == ' ')next++; /* skip spaces */ - - /* find max value of next range; *next must be '-', or ',' */ - if (*next == '-') { - next++; - while (*next == ' ')next++; /* skip spaces */ - - if ( isdigit((int) *next) ) { - - /* read as a double, because the string to LONGLONG function */ - /* is platform dependent (strtoll, strtol, _atoI64) */ - - dvalue = strtod(next, &next); - maxval = (LONGLONG) (dvalue + 0.1); - - } else if (*next == ',' || *next == '\0') { - maxval = maxrows; /* implied max value */ - } else { - *status = RANGE_PARSE_ERROR; - ffpmsg("Syntax error in this row range list:"); - ffpmsg(rowlist); - return(*status); - } - } else if (*next == ',' || *next == '\0') { - maxval = minval; /* only a single integer in this range */ - } else { - *status = RANGE_PARSE_ERROR; - ffpmsg("Syntax error in this row range list:"); - ffpmsg(rowlist); - return(*status); - } - - if (*numranges + 1 > maxranges) { - *status = RANGE_PARSE_ERROR; - ffpmsg("Overflowed maximum number of ranges (fits_parse_ranges)"); - return(*status); - } - - if (minval < 1 ) { - *status = RANGE_PARSE_ERROR; - ffpmsg("Syntax error in this row range list: row number < 1"); - ffpmsg(rowlist); - return(*status); - } - - if (maxval < minval) { - *status = RANGE_PARSE_ERROR; - ffpmsg("Syntax error in this row range list: min > max"); - ffpmsg(rowlist); - return(*status); - } - - if (*numranges > 0) { - if (minval <= maxrow[(*numranges) - 1]) { - *status = RANGE_PARSE_ERROR; - ffpmsg("Syntax error in this row range list. Range minimum is"); - ffpmsg(" less than or equal to previous range maximum"); - ffpmsg(rowlist); - return(*status); - } - } - - if (minval <= maxrows) { /* ignore range if greater than maxrows */ - if (maxval > maxrows) - maxval = maxrows; - - minrow[*numranges] = minval; - maxrow[*numranges] = maxval; - - (*numranges)++; - } - - while (*next == ' ')next++; /* skip spaces */ - if (*next == ',') { - next++; - while (*next == ' ')next++; /* skip more spaces */ - } - } - - if (*numranges == 0) { /* a null string was entered */ - minrow[0] = 1; - maxrow[0] = maxrows; - *numranges = 1; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fficol(fitsfile *fptr, /* I - FITS file pointer */ - int numcol, /* I - position for new col. (1 = 1st) */ - char *ttype, /* I - name of column (TTYPE keyword) */ - char *tform, /* I - format of column (TFORM keyword) */ - int *status) /* IO - error status */ -/* - Insert a new column into an existing table at position numcol. If - numcol is greater than the number of existing columns in the table - then the new column will be appended as the last column in the table. -*/ -{ - char *name, *format; - - name = ttype; - format = tform; - - fficls(fptr, numcol, 1, &name, &format, status); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fficls(fitsfile *fptr, /* I - FITS file pointer */ - int fstcol, /* I - position for first new col. (1 = 1st) */ - int ncols, /* I - number of columns to insert */ - char **ttype, /* I - array of column names(TTYPE keywords) */ - char **tform, /* I - array of formats of column (TFORM) */ - int *status) /* IO - error status */ -/* - Insert 1 or more new columns into an existing table at position numcol. If - fstcol is greater than the number of existing columns in the table - then the new column will be appended as the last column in the table. -*/ -{ - int colnum, datacode, decims, tfields, tstatus, ii; - LONGLONG datasize, firstbyte, nbytes, nadd, naxis1, naxis2, freespace; - LONGLONG tbcol, firstcol, delbyte; - long nblock, width, repeat; - char tfm[FLEN_VALUE], keyname[FLEN_KEYWORD], comm[FLEN_COMMENT], *cptr; - tcolumn *colptr; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - } - /* rescan header if data structure is undefined */ - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - { - ffpmsg("Can only add columns to TABLE or BINTABLE extension (fficol)"); - return(*status = NOT_TABLE); - } - - /* is the column number valid? */ - tfields = (fptr->Fptr)->tfield; - if (fstcol < 1 ) - return(*status = BAD_COL_NUM); - else if (fstcol > tfields) - colnum = tfields + 1; /* append as last column */ - else - colnum = fstcol; - - /* parse the tform value and calc number of bytes to add to each row */ - delbyte = 0; - for (ii = 0; ii < ncols; ii++) - { - strcpy(tfm, tform[ii]); - ffupch(tfm); /* make sure format is in upper case */ - - if ((fptr->Fptr)->hdutype == ASCII_TBL) - { - ffasfm(tfm, &datacode, &width, &decims, status); - delbyte += width + 1; /* add one space between the columns */ - } - else - { - ffbnfm(tfm, &datacode, &repeat, &width, status); - - if (datacode < 0) { /* variable length array column */ - if (strchr(tfm, 'Q')) - delbyte += 16; - else - delbyte += 8; - } else if (datacode == 1) /* bit column; round up */ - delbyte += (repeat + 7) / 8; /* to multiple of 8 bits */ - else if (datacode == 16) /* ASCII string column */ - delbyte += repeat; - else /* numerical data type */ - delbyte += (datacode / 10) * repeat; - } - } - - if (*status > 0) - return(*status); - - /* get the current size of the table */ - /* use internal structure since NAXIS2 keyword may not be up to date */ - naxis1 = (fptr->Fptr)->rowlength; - naxis2 = (fptr->Fptr)->numrows; - - /* current size of data */ - datasize = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; - freespace = ( ( (datasize + 2879) / 2880) * 2880) - datasize; - nadd = delbyte * naxis2; /* no. of bytes to add to table */ - - if ( (freespace - nadd) < 0) /* not enough existing space? */ - { - nblock = (long) ((nadd - freespace + 2879) / 2880); /* number of blocks */ - if (ffiblk(fptr, nblock, 1, status) > 0) /* insert the blocks */ - return(*status); - } - - /* shift heap down (if it exists) */ - if ((fptr->Fptr)->heapsize > 0) - { - nbytes = (fptr->Fptr)->heapsize; /* no. of bytes to shift down */ - - /* absolute heap pos */ - firstbyte = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; - - if (ffshft(fptr, firstbyte, nbytes, nadd, status) > 0) /* move heap */ - return(*status); - } - - /* update the heap starting address */ - (fptr->Fptr)->heapstart += nadd; - - /* update the THEAP keyword if it exists */ - tstatus = 0; - ffmkyj(fptr, "THEAP", (fptr->Fptr)->heapstart, "&", &tstatus); - - /* calculate byte position in the row where to insert the new column */ - if (colnum > tfields) - firstcol = naxis1; - else - { - colptr = (fptr->Fptr)->tableptr; - colptr += (colnum - 1); - firstcol = colptr->tbcol; - } - - /* insert delbyte bytes in every row, at byte position firstcol */ - ffcins(fptr, naxis1, naxis2, delbyte, firstcol, status); - - if ((fptr->Fptr)->hdutype == ASCII_TBL) - { - /* adjust the TBCOL values of the existing columns */ - for(ii = 0; ii < tfields; ii++) - { - ffkeyn("TBCOL", ii + 1, keyname, status); - ffgkyjj(fptr, keyname, &tbcol, comm, status); - if (tbcol > firstcol) - { - tbcol += delbyte; - ffmkyj(fptr, keyname, tbcol, "&", status); - } - } - } - - /* update the mandatory keywords */ - ffmkyj(fptr, "TFIELDS", tfields + ncols, "&", status); - ffmkyj(fptr, "NAXIS1", naxis1 + delbyte, "&", status); - - /* increment the index value on any existing column keywords */ - if(colnum <= tfields) - ffkshf(fptr, colnum, tfields, ncols, status); - - /* add the required keywords for the new columns */ - for (ii = 0; ii < ncols; ii++, colnum++) - { - strcpy(comm, "label for field"); - ffkeyn("TTYPE", colnum, keyname, status); - ffpkys(fptr, keyname, ttype[ii], comm, status); - - strcpy(comm, "format of field"); - strcpy(tfm, tform[ii]); - ffupch(tfm); /* make sure format is in upper case */ - ffkeyn("TFORM", colnum, keyname, status); - - if (abs(datacode) == TSBYTE) - { - /* Replace the 'S' with an 'B' in the TFORMn code */ - cptr = tfm; - while (*cptr != 'S') - cptr++; - - *cptr = 'B'; - ffpkys(fptr, keyname, tfm, comm, status); - - /* write the TZEROn and TSCALn keywords */ - ffkeyn("TZERO", colnum, keyname, status); - strcpy(comm, "offset for signed bytes"); - - ffpkyg(fptr, keyname, -128., 0, comm, status); - - ffkeyn("TSCAL", colnum, keyname, status); - strcpy(comm, "data are not scaled"); - ffpkyg(fptr, keyname, 1., 0, comm, status); - } - else if (abs(datacode) == TUSHORT) - { - /* Replace the 'U' with an 'I' in the TFORMn code */ - cptr = tfm; - while (*cptr != 'U') - cptr++; - - *cptr = 'I'; - ffpkys(fptr, keyname, tfm, comm, status); - - /* write the TZEROn and TSCALn keywords */ - ffkeyn("TZERO", colnum, keyname, status); - strcpy(comm, "offset for unsigned integers"); - - ffpkyg(fptr, keyname, 32768., 0, comm, status); - - ffkeyn("TSCAL", colnum, keyname, status); - strcpy(comm, "data are not scaled"); - ffpkyg(fptr, keyname, 1., 0, comm, status); - } - else if (abs(datacode) == TULONG) - { - /* Replace the 'V' with an 'J' in the TFORMn code */ - cptr = tfm; - while (*cptr != 'V') - cptr++; - - *cptr = 'J'; - ffpkys(fptr, keyname, tfm, comm, status); - - /* write the TZEROn and TSCALn keywords */ - ffkeyn("TZERO", colnum, keyname, status); - strcpy(comm, "offset for unsigned integers"); - - ffpkyg(fptr, keyname, 2147483648., 0, comm, status); - - ffkeyn("TSCAL", colnum, keyname, status); - strcpy(comm, "data are not scaled"); - ffpkyg(fptr, keyname, 1., 0, comm, status); - } - else - { - ffpkys(fptr, keyname, tfm, comm, status); - } - - if ((fptr->Fptr)->hdutype == ASCII_TBL) /* write the TBCOL keyword */ - { - if (colnum == tfields + 1) - tbcol = firstcol + 2; /* allow space between preceding col */ - else - tbcol = firstcol + 1; - - strcpy(comm, "beginning column of field"); - ffkeyn("TBCOL", colnum, keyname, status); - ffpkyj(fptr, keyname, tbcol, comm, status); - - /* increment the column starting position for the next column */ - ffasfm(tfm, &datacode, &width, &decims, status); - firstcol += width + 1; /* add one space between the columns */ - } - } - ffrdef(fptr, status); /* initialize the new table structure */ - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffmvec(fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - position of col to be modified */ - LONGLONG newveclen, /* I - new vector length of column (TFORM) */ - int *status) /* IO - error status */ -/* - Modify the vector length of a column in a binary table, larger or smaller. - E.g., change a column from TFORMn = '1E' to '20E'. -*/ -{ - int datacode, tfields, tstatus; - LONGLONG datasize, size, firstbyte, nbytes, nadd, ndelete; - LONGLONG naxis1, naxis2, firstcol, freespace; - LONGLONG width, delbyte, repeat; - long nblock; - char tfm[FLEN_VALUE], keyname[FLEN_KEYWORD], tcode[2]; - tcolumn *colptr; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - } - /* rescan header if data structure is undefined */ - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) - return(*status); - - if ((fptr->Fptr)->hdutype != BINARY_TBL) - { - ffpmsg( - "Can only change vector length of a column in BINTABLE extension (ffmvec)"); - return(*status = NOT_TABLE); - } - - /* is the column number valid? */ - tfields = (fptr->Fptr)->tfield; - if (colnum < 1 || colnum > tfields) - return(*status = BAD_COL_NUM); - - /* look up the current vector length and element width */ - - colptr = (fptr->Fptr)->tableptr; - colptr += (colnum - 1); - - datacode = colptr->tdatatype; /* datatype of the column */ - repeat = colptr->trepeat; /* field repeat count */ - width = colptr->twidth; /* width of a single element in chars */ - - if (datacode < 0) - { - ffpmsg( - "Can't modify vector length of variable length column (ffmvec)"); - return(*status = BAD_TFORM); - } - - if (repeat == newveclen) - return(*status); /* column already has the desired vector length */ - - if (datacode == TSTRING) - width = 1; /* width was equal to width of unit string */ - - naxis1 = (fptr->Fptr)->rowlength; /* current width of the table */ - naxis2 = (fptr->Fptr)->numrows; - - delbyte = (newveclen - repeat) * width; /* no. of bytes to insert */ - if (datacode == TBIT) /* BIT column is a special case */ - delbyte = ((newveclen + 7) / 8) - ((repeat + 7) / 8); - - if (delbyte > 0) /* insert space for more elements */ - { - /* current size of data */ - datasize = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; - freespace = ( ( (datasize + 2879) / 2880) * 2880) - datasize; - - nadd = (LONGLONG)delbyte * naxis2; /* no. of bytes to add to table */ - - if ( (freespace - nadd) < 0) /* not enough existing space? */ - { - nblock = (long) ((nadd - freespace + 2879) / 2880); /* number of blocks */ - if (ffiblk(fptr, nblock, 1, status) > 0) /* insert the blocks */ - return(*status); - } - - /* shift heap down (if it exists) */ - if ((fptr->Fptr)->heapsize > 0) - { - nbytes = (fptr->Fptr)->heapsize; /* no. of bytes to shift down */ - - /* absolute heap pos */ - firstbyte = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; - - if (ffshft(fptr, firstbyte, nbytes, nadd, status) > 0) /* move heap */ - return(*status); - } - - /* update the heap starting address */ - (fptr->Fptr)->heapstart += nadd; - - /* update the THEAP keyword if it exists */ - tstatus = 0; - ffmkyj(fptr, "THEAP", (fptr->Fptr)->heapstart, "&", &tstatus); - - firstcol = colptr->tbcol + (repeat * width); /* insert position */ - - /* insert delbyte bytes in every row, at byte position firstcol */ - ffcins(fptr, naxis1, naxis2, delbyte, firstcol, status); - } - else if (delbyte < 0) - { - /* current size of table */ - size = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; - freespace = ((size + 2879) / 2880) * 2880 - size - ((LONGLONG)delbyte * naxis2); - nblock = (long) (freespace / 2880); /* number of empty blocks to delete */ - firstcol = colptr->tbcol + (newveclen * width); /* delete position */ - - /* delete elements from the vector */ - ffcdel(fptr, naxis1, naxis2, -delbyte, firstcol, status); - - /* abs heap pos */ - firstbyte = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; - ndelete = (LONGLONG)delbyte * naxis2; /* size of shift (negative) */ - - /* shift heap up (if it exists) */ - if ((fptr->Fptr)->heapsize > 0) - { - nbytes = (fptr->Fptr)->heapsize; /* no. of bytes to shift up */ - if (ffshft(fptr, firstbyte, nbytes, ndelete, status) > 0) - return(*status); - } - - /* delete the empty blocks at the end of the HDU */ - if (nblock > 0) - ffdblk(fptr, nblock, status); - - /* update the heap starting address */ - (fptr->Fptr)->heapstart += ndelete; /* ndelete is negative */ - - /* update the THEAP keyword if it exists */ - tstatus = 0; - ffmkyj(fptr, "THEAP", (fptr->Fptr)->heapstart, "&", &tstatus); - } - - /* construct the new TFORM keyword for the column */ - if (datacode == TBIT) - strcpy(tcode,"X"); - else if (datacode == TBYTE) - strcpy(tcode,"B"); - else if (datacode == TLOGICAL) - strcpy(tcode,"L"); - else if (datacode == TSTRING) - strcpy(tcode,"A"); - else if (datacode == TSHORT) - strcpy(tcode,"I"); - else if (datacode == TLONG) - strcpy(tcode,"J"); - else if (datacode == TLONGLONG) - strcpy(tcode,"K"); - else if (datacode == TFLOAT) - strcpy(tcode,"E"); - else if (datacode == TDOUBLE) - strcpy(tcode,"D"); - else if (datacode == TCOMPLEX) - strcpy(tcode,"C"); - else if (datacode == TDBLCOMPLEX) - strcpy(tcode,"M"); - - /* write as a double value because the LONGLONG conversion */ - /* character in sprintf is platform dependent ( %lld, %ld, %I64d ) */ - - sprintf(tfm,"%.0f%s",(double) newveclen, tcode); - - ffkeyn("TFORM", colnum, keyname, status); /* Keyword name */ - ffmkys(fptr, keyname, tfm, "&", status); /* modify TFORM keyword */ - - ffmkyj(fptr, "NAXIS1", naxis1 + delbyte, "&", status); /* modify NAXIS1 */ - - ffrdef(fptr, status); /* reinitialize the new table structure */ - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffcpcl(fitsfile *infptr, /* I - FITS file pointer to input file */ - fitsfile *outfptr, /* I - FITS file pointer to output file */ - int incol, /* I - number of input column */ - int outcol, /* I - number for output column */ - int create_col, /* I - create new col if TRUE, else overwrite */ - int *status) /* IO - error status */ -/* - copy a column from infptr and insert it in the outfptr table. -*/ -{ - int tstatus, colnum, typecode, otypecode, anynull; - int inHduType, outHduType; - long tfields, repeat, orepeat, width, owidth, nrows, outrows; - long inloop, outloop, maxloop, ndone, ntodo, npixels; - long firstrow, firstelem, ii; - char keyname[FLEN_KEYWORD], ttype[FLEN_VALUE], tform[FLEN_VALUE]; - char ttype_comm[FLEN_COMMENT],tform_comm[FLEN_COMMENT]; - char *lvalues = 0, nullflag, **strarray = 0; - char nulstr[] = {'\5', '\0'}; /* unique null string value */ - double dnull = 0.l, *dvalues = 0; - float fnull = 0., *fvalues = 0; - - if (*status > 0) - return(*status); - - if (infptr->HDUposition != (infptr->Fptr)->curhdu) - { - ffmahd(infptr, (infptr->HDUposition) + 1, NULL, status); - } - else if ((infptr->Fptr)->datastart == DATA_UNDEFINED) - ffrdef(infptr, status); /* rescan header */ - inHduType = (infptr->Fptr)->hdutype; - - if (outfptr->HDUposition != (outfptr->Fptr)->curhdu) - { - ffmahd(outfptr, (outfptr->HDUposition) + 1, NULL, status); - } - else if ((outfptr->Fptr)->datastart == DATA_UNDEFINED) - ffrdef(outfptr, status); /* rescan header */ - outHduType = (outfptr->Fptr)->hdutype; - - if (*status > 0) - return(*status); - - if (inHduType == IMAGE_HDU || outHduType == IMAGE_HDU) - { - ffpmsg - ("Can not copy columns to or from IMAGE HDUs (ffcpcl)"); - return(*status = NOT_TABLE); - } - - if ( inHduType == BINARY_TBL && outHduType == ASCII_TBL) - { - ffpmsg - ("Copying from Binary table to ASCII table is not supported (ffcpcl)"); - return(*status = NOT_BTABLE); - } - - /* get the datatype and vector repeat length of the column */ - ffgtcl(infptr, incol, &typecode, &repeat, &width, status); - - if (typecode < 0) - { - ffpmsg("Variable-length columns are not supported (ffcpcl)"); - return(*status = BAD_TFORM); - } - - if (create_col) /* insert new column in output table? */ - { - tstatus = 0; - ffkeyn("TTYPE", incol, keyname, &tstatus); - ffgkys(infptr, keyname, ttype, ttype_comm, &tstatus); - ffkeyn("TFORM", incol, keyname, &tstatus); - - if (ffgkys(infptr, keyname, tform, tform_comm, &tstatus) ) - { - ffpmsg - ("Could not find TTYPE and TFORM keywords in input table (ffcpcl)"); - return(*status = NO_TFORM); - } - - if (inHduType == ASCII_TBL && outHduType == BINARY_TBL) - { - /* convert from ASCII table to BINARY table format string */ - if (typecode == TSTRING) - ffnkey(width, "A", tform, status); - - else if (typecode == TLONG) - strcpy(tform, "1J"); - - else if (typecode == TSHORT) - strcpy(tform, "1I"); - - else if (typecode == TFLOAT) - strcpy(tform,"1E"); - - else if (typecode == TDOUBLE) - strcpy(tform,"1D"); - } - - if (ffgkyj(outfptr, "TFIELDS", &tfields, 0, &tstatus)) - { - ffpmsg - ("Could not read TFIELDS keyword in output table (ffcpcl)"); - return(*status = NO_TFIELDS); - } - - colnum = minvalue((int) tfields + 1, outcol); /* output col. number */ - - /* create the empty column */ - if (fficol(outfptr, colnum, ttype, tform, status) > 0) - { - ffpmsg - ("Could not append new column to output file (ffcpcl)"); - return(*status); - } - - if ((infptr->Fptr == outfptr->Fptr) - && (infptr->HDUposition == outfptr->HDUposition) - && (colnum <= incol)) { - incol++; /* the input column has been shifted over */ - } - - /* copy the comment strings from the input file for TTYPE and TFORM */ - tstatus = 0; - ffkeyn("TTYPE", colnum, keyname, &tstatus); - ffmcom(outfptr, keyname, ttype_comm, &tstatus); - ffkeyn("TFORM", colnum, keyname, &tstatus); - ffmcom(outfptr, keyname, tform_comm, &tstatus); - - /* copy other column-related keywords if they exist */ - - ffcpky(infptr, outfptr, incol, colnum, "TUNIT", status); - ffcpky(infptr, outfptr, incol, colnum, "TSCAL", status); - ffcpky(infptr, outfptr, incol, colnum, "TZERO", status); - ffcpky(infptr, outfptr, incol, colnum, "TDISP", status); - ffcpky(infptr, outfptr, incol, colnum, "TLMIN", status); - ffcpky(infptr, outfptr, incol, colnum, "TLMAX", status); - ffcpky(infptr, outfptr, incol, colnum, "TDIM", status); - - /* WCS keywords */ - ffcpky(infptr, outfptr, incol, colnum, "TCTYP", status); - ffcpky(infptr, outfptr, incol, colnum, "TCUNI", status); - ffcpky(infptr, outfptr, incol, colnum, "TCRVL", status); - ffcpky(infptr, outfptr, incol, colnum, "TCRPX", status); - ffcpky(infptr, outfptr, incol, colnum, "TCDLT", status); - ffcpky(infptr, outfptr, incol, colnum, "TCROT", status); - - if (inHduType == ASCII_TBL && outHduType == BINARY_TBL) - { - /* binary tables only have TNULLn keyword for integer columns */ - if (typecode == TLONG || typecode == TSHORT) - { - /* check if null string is defined; replace with integer */ - ffkeyn("TNULL", incol, keyname, &tstatus); - if (ffgkys(infptr, keyname, ttype, 0, &tstatus) <= 0) - { - ffkeyn("TNULL", colnum, keyname, &tstatus); - if (typecode == TLONG) - ffpkyj(outfptr, keyname, -9999999L, "Null value", status); - else - ffpkyj(outfptr, keyname, -32768L, "Null value", status); - } - } - } - else - { - ffcpky(infptr, outfptr, incol, colnum, "TNULL", status); - } - - /* rescan header to recognize the new keywords */ - if (ffrdef(outfptr, status) ) - return(*status); - } - else - { - colnum = outcol; - /* get the datatype and vector repeat length of the output column */ - ffgtcl(outfptr, outcol, &otypecode, &orepeat, &owidth, status); - - if (orepeat != repeat) { - ffpmsg("Input and output vector columns must have same length (ffcpcl)"); - return(*status = BAD_TFORM); - } - } - - ffgkyj(infptr, "NAXIS2", &nrows, 0, status); /* no. of input rows */ - ffgkyj(outfptr, "NAXIS2", &outrows, 0, status); /* no. of output rows */ - nrows = minvalue(nrows, outrows); - - if (typecode == TBIT) - repeat = (repeat + 7) / 8; /* convert from bits to bytes */ - else if (typecode == TSTRING && inHduType == BINARY_TBL) - repeat = repeat / width; /* convert from chars to unit strings */ - - /* get optimum number of rows to copy at one time */ - ffgrsz(infptr, &inloop, status); - ffgrsz(outfptr, &outloop, status); - - /* adjust optimum number, since 2 tables are open at once */ - maxloop = minvalue(inloop, outloop); /* smallest of the 2 tables */ - maxloop = maxvalue(1, maxloop / 2); /* at least 1 row */ - maxloop = minvalue(maxloop, nrows); /* max = nrows to be copied */ - maxloop *= repeat; /* mult by no of elements in a row */ - - /* allocate memory for arrays */ - if (typecode == TLOGICAL) - { - lvalues = (char *) calloc(maxloop, sizeof(char) ); - if (!lvalues) - { - ffpmsg - ("malloc failed to get memory for logicals (ffcpcl)"); - return(*status = ARRAY_TOO_BIG); - } - } - else if (typecode == TSTRING) - { - /* allocate array of pointers */ - strarray = (char **) calloc(maxloop, sizeof(strarray)); - - /* allocate space for each string */ - for (ii = 0; ii < maxloop; ii++) - strarray[ii] = (char *) calloc(width+1, sizeof(char)); - } - else if (typecode == TCOMPLEX) - { - fvalues = (float *) calloc(maxloop * 2, sizeof(float) ); - if (!fvalues) - { - ffpmsg - ("malloc failed to get memory for complex (ffcpcl)"); - return(*status = ARRAY_TOO_BIG); - } - fnull = 0.; - } - else if (typecode == TDBLCOMPLEX) - { - dvalues = (double *) calloc(maxloop * 2, sizeof(double) ); - if (!dvalues) - { - ffpmsg - ("malloc failed to get memory for dbl complex (ffcpcl)"); - return(*status = ARRAY_TOO_BIG); - } - dnull = 0.; - } - else /* numerical datatype; read them all as doubles */ - { - dvalues = (double *) calloc(maxloop, sizeof(double) ); - if (!dvalues) - { - ffpmsg - ("malloc failed to get memory for doubles (ffcpcl)"); - return(*status = ARRAY_TOO_BIG); - } - dnull = -9.99991999E31; /* use an unlikely value for nulls */ - } - - npixels = nrows * repeat; /* total no. of pixels to copy */ - ntodo = minvalue(npixels, maxloop); /* no. to copy per iteration */ - ndone = 0; /* total no. of pixels that have been copied */ - - while (ntodo) /* iterate through the table */ - { - firstrow = ndone / repeat + 1; - firstelem = ndone - ((firstrow - 1) * repeat) + 1; - - /* read from input table */ - if (typecode == TLOGICAL) - ffgcl(infptr, incol, firstrow, firstelem, ntodo, - lvalues, status); - else if (typecode == TSTRING) - ffgcvs(infptr, incol, firstrow, firstelem, ntodo, - nulstr, strarray, &anynull, status); - - else if (typecode == TCOMPLEX) - ffgcvc(infptr, incol, firstrow, firstelem, ntodo, fnull, - fvalues, &anynull, status); - - else if (typecode == TDBLCOMPLEX) - ffgcvm(infptr, incol, firstrow, firstelem, ntodo, dnull, - dvalues, &anynull, status); - - else /* all numerical types */ - ffgcvd(infptr, incol, firstrow, firstelem, ntodo, dnull, - dvalues, &anynull, status); - - if (*status > 0) - { - ffpmsg("Error reading input copy of column (ffcpcl)"); - break; - } - - /* write to output table */ - if (typecode == TLOGICAL) - { - nullflag = 2; - - ffpcnl(outfptr, colnum, firstrow, firstelem, ntodo, - lvalues, nullflag, status); - - } - - else if (typecode == TSTRING) - { - if (anynull) - ffpcns(outfptr, colnum, firstrow, firstelem, ntodo, - strarray, nulstr, status); - else - ffpcls(outfptr, colnum, firstrow, firstelem, ntodo, - strarray, status); - } - - else if (typecode == TCOMPLEX) - { /* doesn't support writing nulls */ - ffpclc(outfptr, colnum, firstrow, firstelem, ntodo, - fvalues, status); - } - - else if (typecode == TDBLCOMPLEX) - { /* doesn't support writing nulls */ - ffpclm(outfptr, colnum, firstrow, firstelem, ntodo, - dvalues, status); - } - - else /* all other numerical types */ - { - if (anynull) - ffpcnd(outfptr, colnum, firstrow, firstelem, ntodo, - dvalues, dnull, status); - else - ffpcld(outfptr, colnum, firstrow, firstelem, ntodo, - dvalues, status); - } - - if (*status > 0) - { - ffpmsg("Error writing output copy of column (ffcpcl)"); - break; - } - - npixels -= ntodo; - ndone += ntodo; - ntodo = minvalue(npixels, maxloop); - } - - /* free the previously allocated memory */ - if (typecode == TLOGICAL) - { - free(lvalues); - } - else if (typecode == TSTRING) - { - for (ii = 0; ii < maxloop; ii++) - free(strarray[ii]); - - free(strarray); - } - else - { - free(dvalues); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffcprw(fitsfile *infptr, /* I - FITS file pointer to input file */ - fitsfile *outfptr, /* I - FITS file pointer to output file */ - LONGLONG firstrow, /* I - number of first row to copy (1 based) */ - LONGLONG nrows, /* I - number of rows to copy */ - int *status) /* IO - error status */ -/* - copy consecutive set of rows from infptr and append it in the outfptr table. -*/ -{ - LONGLONG innaxis1, innaxis2, outnaxis1, outnaxis2, ii, jj; - unsigned char *buffer; - - if (*status > 0) - return(*status); - - if (infptr->HDUposition != (infptr->Fptr)->curhdu) - { - ffmahd(infptr, (infptr->HDUposition) + 1, NULL, status); - } - else if ((infptr->Fptr)->datastart == DATA_UNDEFINED) - ffrdef(infptr, status); /* rescan header */ - - if (outfptr->HDUposition != (outfptr->Fptr)->curhdu) - { - ffmahd(outfptr, (outfptr->HDUposition) + 1, NULL, status); - } - else if ((outfptr->Fptr)->datastart == DATA_UNDEFINED) - ffrdef(outfptr, status); /* rescan header */ - - if (*status > 0) - return(*status); - - if ((infptr->Fptr)->hdutype == IMAGE_HDU || (outfptr->Fptr)->hdutype == IMAGE_HDU) - { - ffpmsg - ("Can not copy rows to or from IMAGE HDUs (ffcprw)"); - return(*status = NOT_TABLE); - } - - if ( ((infptr->Fptr)->hdutype == BINARY_TBL && (outfptr->Fptr)->hdutype == ASCII_TBL) || - ((infptr->Fptr)->hdutype == ASCII_TBL && (outfptr->Fptr)->hdutype == BINARY_TBL) ) - { - ffpmsg - ("Copying rows between Binary and ASCII tables is not supported (ffcprw)"); - return(*status = NOT_BTABLE); - } - - ffgkyjj(infptr, "NAXIS1", &innaxis1, 0, status); /* width of input rows */ - ffgkyjj(infptr, "NAXIS2", &innaxis2, 0, status); /* no. of input rows */ - ffgkyjj(outfptr, "NAXIS1", &outnaxis1, 0, status); /* width of output rows */ - ffgkyjj(outfptr, "NAXIS2", &outnaxis2, 0, status); /* no. of output rows */ - - if (*status > 0) - return(*status); - - if (outnaxis1 > innaxis1) { - ffpmsg - ("Input and output tables do not have same width (ffcprw)"); - return(*status = BAD_ROW_WIDTH); - } - - if (firstrow + nrows - 1 > innaxis2) { - ffpmsg - ("Not enough rows in input table to copy (ffcprw)"); - return(*status = BAD_ROW_NUM); - } - - /* allocate buffer to hold 1 row of data */ - buffer = malloc( (size_t) innaxis1); - if (!buffer) { - ffpmsg - ("Unable to allocate memory (ffcprw)"); - return(*status = MEMORY_ALLOCATION); - } - - /* copy the rows, 1 at a time */ - jj = outnaxis2 + 1; - for (ii = firstrow; ii < firstrow + nrows; ii++) { - fits_read_tblbytes (infptr, ii, 1, innaxis1, buffer, status); - fits_write_tblbytes(outfptr, jj, 1, innaxis1, buffer, status); - jj++; - } - - outnaxis2 += nrows; - fits_update_key(outfptr, TLONGLONG, "NAXIS2", &outnaxis2, 0, status); - - free(buffer); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffcpky(fitsfile *infptr, /* I - FITS file pointer to input file */ - fitsfile *outfptr, /* I - FITS file pointer to output file */ - int incol, /* I - input index number */ - int outcol, /* I - output index number */ - char *rootname, /* I - root name of the keyword to be copied */ - int *status) /* IO - error status */ -/* - copy an indexed keyword from infptr to outfptr. -*/ -{ - int tstatus = 0; - char keyname[FLEN_KEYWORD]; - char value[FLEN_VALUE], comment[FLEN_COMMENT], card[FLEN_CARD]; - - ffkeyn(rootname, incol, keyname, &tstatus); - if (ffgkey(infptr, keyname, value, comment, &tstatus) <= 0) - { - ffkeyn(rootname, outcol, keyname, &tstatus); - ffmkky(keyname, value, comment, card, status); - ffprec(outfptr, card, status); - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffdcol(fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column to delete (1 = 1st) */ - int *status) /* IO - error status */ -/* - Delete a column from a table. -*/ -{ - int ii, tstatus; - LONGLONG firstbyte, size, ndelete, nbytes, naxis1, naxis2, firstcol, delbyte, freespace; - LONGLONG tbcol; - long nblock, nspace; - char keyname[FLEN_KEYWORD], comm[FLEN_COMMENT]; - tcolumn *colptr, *nextcol; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - } - /* rescan header if data structure is undefined */ - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - { - ffpmsg - ("Can only delete column from TABLE or BINTABLE extension (ffdcol)"); - return(*status = NOT_TABLE); - } - - if (colnum < 1 || colnum > (fptr->Fptr)->tfield ) - return(*status = BAD_COL_NUM); - - colptr = (fptr->Fptr)->tableptr; - colptr += (colnum - 1); - firstcol = colptr->tbcol; /* starting byte position of the column */ - - /* use column width to determine how many bytes to delete in each row */ - if ((fptr->Fptr)->hdutype == ASCII_TBL) - { - delbyte = colptr->twidth; /* width of ASCII column */ - - if (colnum < (fptr->Fptr)->tfield) /* check for space between next column */ - { - nextcol = colptr + 1; - nspace = (long) ((nextcol->tbcol) - (colptr->tbcol) - delbyte); - if (nspace > 0) - delbyte++; - } - else if (colnum > 1) /* check for space between last 2 columns */ - { - nextcol = colptr - 1; - nspace = (long) ((colptr->tbcol) - (nextcol->tbcol) - (nextcol->twidth)); - if (nspace > 0) - { - delbyte++; - firstcol--; /* delete the leading space */ - } - } - } - else /* a binary table */ - { - if (colnum < (fptr->Fptr)->tfield) - { - nextcol = colptr + 1; - delbyte = (nextcol->tbcol) - (colptr->tbcol); - } - else - { - delbyte = ((fptr->Fptr)->rowlength) - (colptr->tbcol); - } - } - - naxis1 = (fptr->Fptr)->rowlength; /* current width of the table */ - naxis2 = (fptr->Fptr)->numrows; - - /* current size of table */ - size = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; - freespace = ((LONGLONG)delbyte * naxis2) + ((size + 2879) / 2880) * 2880 - size; - nblock = (long) (freespace / 2880); /* number of empty blocks to delete */ - - ffcdel(fptr, naxis1, naxis2, delbyte, firstcol, status); /* delete col */ - - /* absolute heap position */ - firstbyte = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; - ndelete = (LONGLONG)delbyte * naxis2; /* size of shift */ - - /* shift heap up (if it exists) */ - if ((fptr->Fptr)->heapsize > 0) - { - nbytes = (fptr->Fptr)->heapsize; /* no. of bytes to shift up */ - - if (ffshft(fptr, firstbyte, nbytes, -ndelete, status) > 0) /* mv heap */ - return(*status); - } - - /* delete the empty blocks at the end of the HDU */ - if (nblock > 0) - ffdblk(fptr, nblock, status); - - /* update the heap starting address */ - (fptr->Fptr)->heapstart -= ndelete; - - /* update the THEAP keyword if it exists */ - tstatus = 0; - ffmkyj(fptr, "THEAP", (long)(fptr->Fptr)->heapstart, "&", &tstatus); - - if ((fptr->Fptr)->hdutype == ASCII_TBL) - { - /* adjust the TBCOL values of the remaining columns */ - for (ii = 1; ii <= (fptr->Fptr)->tfield; ii++) - { - ffkeyn("TBCOL", ii, keyname, status); - ffgkyjj(fptr, keyname, &tbcol, comm, status); - if (tbcol > firstcol) - { - tbcol = tbcol - delbyte; - ffmkyj(fptr, keyname, tbcol, "&", status); - } - } - } - - /* update the mandatory keywords */ - ffmkyj(fptr, "TFIELDS", ((fptr->Fptr)->tfield) - 1, "&", status); - ffmkyj(fptr, "NAXIS1", naxis1 - delbyte, "&", status); - /* - delete the index keywords starting with 'T' associated with the - deleted column and subtract 1 from index of all higher keywords - */ - ffkshf(fptr, colnum, (fptr->Fptr)->tfield, -1, status); - - ffrdef(fptr, status); /* initialize the new table structure */ - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffcins(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG naxis1, /* I - width of the table, in bytes */ - LONGLONG naxis2, /* I - number of rows in the table */ - LONGLONG ninsert, /* I - number of bytes to insert in each row */ - LONGLONG bytepos, /* I - rel. position in row to insert bytes */ - int *status) /* IO - error status */ -/* - Insert 'ninsert' bytes into each row of the table at position 'bytepos'. -*/ -{ - unsigned char buffer[10000], cfill; - LONGLONG newlen, fbyte, nbytes, irow, nseg, ii; - - if (*status > 0) - return(*status); - - if (naxis2 == 0) - return(*status); /* just return if there are 0 rows in the table */ - - /* select appropriate fill value */ - if ((fptr->Fptr)->hdutype == ASCII_TBL) - cfill = 32; /* ASCII tables use blank fill */ - else - cfill = 0; /* primary array and binary tables use zero fill */ - - newlen = naxis1 + ninsert; - - if (newlen <= 10000) - { - /******************************************************************* - CASE #1: optimal case where whole new row fits in the work buffer - *******************************************************************/ - - for (ii = 0; ii < ninsert; ii++) - buffer[ii] = cfill; /* initialize buffer with fill value */ - - /* first move the trailing bytes (if any) in the last row */ - fbyte = bytepos + 1; - nbytes = naxis1 - bytepos; - ffgtbb(fptr, naxis2, fbyte, nbytes, &buffer[ninsert], status); - (fptr->Fptr)->rowlength = newlen; /* new row length */ - - /* write the row (with leading fill bytes) in the new place */ - nbytes += ninsert; - ffptbb(fptr, naxis2, fbyte, nbytes, buffer, status); - (fptr->Fptr)->rowlength = naxis1; /* reset to orig. value */ - - /* now move the rest of the rows */ - for (irow = naxis2 - 1; irow > 0; irow--) - { - /* read the row to be shifted (work backwards thru the table) */ - ffgtbb(fptr, irow, fbyte, naxis1, &buffer[ninsert], status); - (fptr->Fptr)->rowlength = newlen; /* new row length */ - - /* write the row (with the leading fill bytes) in the new place */ - ffptbb(fptr, irow, fbyte, newlen, buffer, status); - (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ - } - } - else - { - /***************************************************************** - CASE #2: whole row doesn't fit in work buffer; move row in pieces - ****************************************************************** - first copy the data, then go back and write fill into the new column - start by copying the trailing bytes (if any) in the last row. */ - - nbytes = naxis1 - bytepos; - nseg = (nbytes + 9999) / 10000; - fbyte = (nseg - 1) * 10000 + bytepos + 1; - nbytes = naxis1 - fbyte + 1; - - for (ii = 0; ii < nseg; ii++) - { - ffgtbb(fptr, naxis2, fbyte, nbytes, buffer, status); - (fptr->Fptr)->rowlength = newlen; /* new row length */ - - ffptbb(fptr, naxis2, fbyte + ninsert, nbytes, buffer, status); - (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ - - fbyte -= 10000; - nbytes = 10000; - } - - /* now move the rest of the rows */ - nseg = (naxis1 + 9999) / 10000; - for (irow = naxis2 - 1; irow > 0; irow--) - { - fbyte = (nseg - 1) * 10000 + bytepos + 1; - nbytes = naxis1 - (nseg - 1) * 10000; - for (ii = 0; ii < nseg; ii++) - { - /* read the row to be shifted (work backwards thru the table) */ - ffgtbb(fptr, irow, fbyte, nbytes, buffer, status); - (fptr->Fptr)->rowlength = newlen; /* new row length */ - - /* write the row in the new place */ - ffptbb(fptr, irow, fbyte + ninsert, nbytes, buffer, status); - (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ - - fbyte -= 10000; - nbytes = 10000; - } - } - - /* now write the fill values into the new column */ - nbytes = minvalue(ninsert, 10000); - memset(buffer, cfill, (size_t) nbytes); /* initialize with fill value */ - - nseg = (ninsert + 9999) / 10000; - (fptr->Fptr)->rowlength = newlen; /* new row length */ - - for (irow = 1; irow <= naxis2; irow++) - { - fbyte = bytepos + 1; - nbytes = ninsert - ((nseg - 1) * 10000); - for (ii = 0; ii < nseg; ii++) - { - ffptbb(fptr, irow, fbyte, nbytes, buffer, status); - fbyte += nbytes; - nbytes = 10000; - } - } - (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffcdel(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG naxis1, /* I - width of the table, in bytes */ - LONGLONG naxis2, /* I - number of rows in the table */ - LONGLONG ndelete, /* I - number of bytes to delete in each row */ - LONGLONG bytepos, /* I - rel. position in row to delete bytes */ - int *status) /* IO - error status */ -/* - delete 'ndelete' bytes from each row of the table at position 'bytepos'. */ -{ - unsigned char buffer[10000]; - LONGLONG i1, i2, ii, irow, nseg; - LONGLONG newlen, remain, nbytes; - - if (*status > 0) - return(*status); - - if (naxis2 == 0) - return(*status); /* just return if there are 0 rows in the table */ - - newlen = naxis1 - ndelete; - - if (newlen <= 10000) - { - /******************************************************************* - CASE #1: optimal case where whole new row fits in the work buffer - *******************************************************************/ - i1 = bytepos + 1; - i2 = i1 + ndelete; - for (irow = 1; irow < naxis2; irow++) - { - ffgtbb(fptr, irow, i2, newlen, buffer, status); /* read row */ - (fptr->Fptr)->rowlength = newlen; /* new row length */ - - ffptbb(fptr, irow, i1, newlen, buffer, status); /* write row */ - (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ - } - - /* now do the last row */ - remain = naxis1 - (bytepos + ndelete); - - if (remain > 0) - { - ffgtbb(fptr, naxis2, i2, remain, buffer, status); /* read row */ - (fptr->Fptr)->rowlength = newlen; /* new row length */ - - ffptbb(fptr, naxis2, i1, remain, buffer, status); /* write row */ - (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ - } - } - else - { - /***************************************************************** - CASE #2: whole row doesn't fit in work buffer; move row in pieces - ******************************************************************/ - - nseg = (newlen + 9999) / 10000; - for (irow = 1; irow < naxis2; irow++) - { - i1 = bytepos + 1; - i2 = i1 + ndelete; - - nbytes = newlen - (nseg - 1) * 10000; - for (ii = 0; ii < nseg; ii++) - { - ffgtbb(fptr, irow, i2, nbytes, buffer, status); /* read bytes */ - (fptr->Fptr)->rowlength = newlen; /* new row length */ - - ffptbb(fptr, irow, i1, nbytes, buffer, status); /* rewrite bytes */ - (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ - - i1 += nbytes; - i2 += nbytes; - nbytes = 10000; - } - } - - /* now do the last row */ - remain = naxis1 - (bytepos + ndelete); - - if (remain > 0) - { - nseg = (remain + 9999) / 10000; - i1 = bytepos + 1; - i2 = i1 + ndelete; - nbytes = remain - (nseg - 1) * 10000; - for (ii = 0; ii < nseg; ii++) - { - ffgtbb(fptr, naxis2, i2, nbytes, buffer, status); - (fptr->Fptr)->rowlength = newlen; /* new row length */ - - ffptbb(fptr, naxis2, i1, nbytes, buffer, status); /* write row */ - (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ - - i1 += nbytes; - i2 += nbytes; - nbytes = 10000; - } - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffkshf(fitsfile *fptr, /* I - FITS file pointer */ - int colmin, /* I - starting col. to be incremented; 1 = 1st */ - int colmax, /* I - last column to be incremented */ - int incre, /* I - shift index number by this amount */ - int *status) /* IO - error status */ -/* - shift the index value on any existing column keywords - This routine will modify the name of any keyword that begins with 'T' - and has an index number in the range COLMIN - COLMAX, inclusive. - - if incre is positive, then the index values will be incremented. - if incre is negative, then the kewords with index = COLMIN - will be deleted and the index of higher numbered keywords will - be decremented. -*/ -{ - int nkeys, nmore, nrec, tstatus, i1; - long ivalue; - char rec[FLEN_CARD], q[FLEN_KEYWORD], newkey[FLEN_KEYWORD]; - - ffghsp(fptr, &nkeys, &nmore, status); /* get number of keywords */ - - /* go thru header starting with the 9th keyword looking for 'TxxxxNNN' */ - - for (nrec = 9; nrec <= nkeys; nrec++) - { - ffgrec(fptr, nrec, rec, status); - - if (rec[0] == 'T') - { - i1 = 0; - strncpy(q, &rec[1], 4); - if (!strncmp(q, "BCOL", 4) || !strncmp(q, "FORM", 4) || - !strncmp(q, "TYPE", 4) || !strncmp(q, "SCAL", 4) || - !strncmp(q, "UNIT", 4) || !strncmp(q, "NULL", 4) || - !strncmp(q, "ZERO", 4) || !strncmp(q, "DISP", 4) || - !strncmp(q, "LMIN", 4) || !strncmp(q, "LMAX", 4) || - !strncmp(q, "DMIN", 4) || !strncmp(q, "DMAX", 4) || - !strncmp(q, "CTYP", 4) || !strncmp(q, "CRPX", 4) || - !strncmp(q, "CRVL", 4) || !strncmp(q, "CDLT", 4) || - !strncmp(q, "CROT", 4) || !strncmp(q, "CUNI", 4) ) - i1 = 5; - else if (!strncmp(rec, "TDIM", 4) ) - i1 = 4; - - if (i1) - { - /* try reading the index number suffix */ - q[0] = '\0'; - strncat(q, &rec[i1], 8 - i1); - - tstatus = 0; - ffc2ii(q, &ivalue, &tstatus); - - if (tstatus == 0 && ivalue >= colmin && ivalue <= colmax) - { - if (incre <= 0 && ivalue == colmin) - { - ffdrec(fptr, nrec, status); /* delete keyword */ - nkeys = nkeys - 1; - nrec = nrec - 1; - } - else - { - ivalue = ivalue + incre; - q[0] = '\0'; - strncat(q, rec, i1); - - ffkeyn(q, ivalue, newkey, status); - strncpy(rec, " ", 8); /* erase old keyword name */ - i1 = strlen(newkey); - strncpy(rec, newkey, i1); /* overwrite new keyword name */ - ffmrec(fptr, nrec, rec, status); /* modify the record */ - } - } - } - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffshft(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG firstbyte, /* I - position of first byte in block to shift */ - LONGLONG nbytes, /* I - size of block of bytes to shift */ - LONGLONG nshift, /* I - size of shift in bytes (+ or -) */ - int *status) /* IO - error status */ -/* - Shift block of bytes by nshift bytes (positive or negative). - A positive nshift value moves the block down further in the file, while a - negative value shifts the block towards the beginning of the file. -*/ -{ -#define shftbuffsize 100000 - long ntomov; - LONGLONG ptr, ntodo; - char buffer[shftbuffsize]; - - if (*status > 0) - return(*status); - - ntodo = nbytes; /* total number of bytes to shift */ - - if (nshift > 0) - /* start at the end of the block and work backwards */ - ptr = firstbyte + nbytes; - else - /* start at the beginning of the block working forwards */ - ptr = firstbyte; - - while (ntodo) - { - /* number of bytes to move at one time */ - ntomov = (long) (minvalue(ntodo, shftbuffsize)); - - if (nshift > 0) /* if moving block down ... */ - ptr -= ntomov; - - /* move to position and read the bytes to be moved */ - - ffmbyt(fptr, ptr, REPORT_EOF, status); - ffgbyt(fptr, ntomov, buffer, status); - - /* move by shift amount and write the bytes */ - ffmbyt(fptr, ptr + nshift, IGNORE_EOF, status); - if (ffpbyt(fptr, ntomov, buffer, status) > 0) - { - ffpmsg("Error while shifting block (ffshft)"); - return(*status); - } - - ntodo -= ntomov; - if (nshift < 0) /* if moving block up ... */ - ptr += ntomov; - } - - /* now overwrite the old data with fill */ - if ((fptr->Fptr)->hdutype == ASCII_TBL) - memset(buffer, 32, shftbuffsize); /* fill ASCII tables with spaces */ - else - memset(buffer, 0, shftbuffsize); /* fill other HDUs with zeros */ - - - if (nshift < 0) - { - ntodo = -nshift; - /* point to the end of the shifted block */ - ptr = firstbyte + nbytes + nshift; - } - else - { - ntodo = nshift; - /* point to original beginning of the block */ - ptr = firstbyte; - } - - ffmbyt(fptr, ptr, REPORT_EOF, status); - - while (ntodo) - { - ntomov = (long) (minvalue(ntodo, shftbuffsize)); - ffpbyt(fptr, ntomov, buffer, status); - ntodo -= ntomov; - } - return(*status); -} diff --git a/src/external/OpenGR/3rdparty/cfitsio/edithdu.c b/src/external/OpenGR/3rdparty/cfitsio/edithdu.c deleted file mode 100644 index 7e5d17aac..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/edithdu.c +++ /dev/null @@ -1,883 +0,0 @@ -/* This file, edithdu.c, contains the FITSIO routines related to */ -/* copying, inserting, or deleting HDUs in a FITS file */ - -/* The FITSIO software was written by William Pence at the High Energy */ -/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ -/* Goddard Space Flight Center. */ - -#include -#include -#include "fitsio2.h" -/*--------------------------------------------------------------------------*/ -int ffcopy(fitsfile *infptr, /* I - FITS file pointer to input file */ - fitsfile *outfptr, /* I - FITS file pointer to output file */ - int morekeys, /* I - reserve space in output header */ - int *status) /* IO - error status */ -/* - copy the CHDU from infptr to the CHDU of outfptr. - This will also allocate space in the output header for MOREKY keywords -*/ -{ - int nspace; - - if (*status > 0) - return(*status); - - if (infptr == outfptr) - return(*status = SAME_FILE); - - if (ffcphd(infptr, outfptr, status) > 0) /* copy the header keywords */ - return(*status); - - if (morekeys > 0) { - ffhdef(outfptr, morekeys, status); /* reserve space for more keywords */ - - } else { - if (ffghsp(infptr, NULL, &nspace, status) > 0) /* get existing space */ - return(*status); - - if (nspace > 0) { - ffhdef(outfptr, nspace, status); /* preserve same amount of space */ - if (nspace >= 35) { - - /* There is at least 1 full empty FITS block in the header. */ - /* Physically write the END keyword at the beginning of the */ - /* last block to preserve this extra space now rather than */ - /* later. This is needed by the stream: driver which cannot */ - /* seek back to the header to write the END keyword later. */ - - ffwend(outfptr, status); - } - } - } - - ffcpdt(infptr, outfptr, status); /* now copy the data unit */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffcpfl(fitsfile *infptr, /* I - FITS file pointer to input file */ - fitsfile *outfptr, /* I - FITS file pointer to output file */ - int previous, /* I - copy any previous HDUs? */ - int current, /* I - copy the current HDU? */ - int following, /* I - copy any following HDUs? */ - int *status) /* IO - error status */ -/* - copy all or part of the input file to the output file. -*/ -{ - int hdunum, ii; - - if (*status > 0) - return(*status); - - if (infptr == outfptr) - return(*status = SAME_FILE); - - ffghdn(infptr, &hdunum); - - if (previous) { /* copy any previous HDUs */ - for (ii=1; ii < hdunum; ii++) { - ffmahd(infptr, ii, NULL, status); - ffcopy(infptr, outfptr, 0, status); - } - } - - if (current && (*status <= 0) ) { /* copy current HDU */ - ffmahd(infptr, hdunum, NULL, status); - ffcopy(infptr, outfptr, 0, status); - } - - if (following && (*status <= 0) ) { /* copy any remaining HDUs */ - ii = hdunum + 1; - while (1) - { - if (ffmahd(infptr, ii, NULL, status) ) { - /* reset expected end of file status */ - if (*status == END_OF_FILE) - *status = 0; - break; - } - - if (ffcopy(infptr, outfptr, 0, status)) - break; /* quit on unexpected error */ - - ii++; - } - } - - ffmahd(infptr, hdunum, NULL, status); /* restore initial position */ - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffcphd(fitsfile *infptr, /* I - FITS file pointer to input file */ - fitsfile *outfptr, /* I - FITS file pointer to output file */ - int *status) /* IO - error status */ -/* - copy the header keywords from infptr to outfptr. -*/ -{ - int nkeys, ii, inPrim = 0, outPrim = 0; - long naxis, naxes[1]; - char *card, comm[FLEN_COMMENT]; - char *tmpbuff; - - if (*status > 0) - return(*status); - - if (infptr == outfptr) - return(*status = SAME_FILE); - - /* set the input pointer to the correct HDU */ - if (infptr->HDUposition != (infptr->Fptr)->curhdu) - ffmahd(infptr, (infptr->HDUposition) + 1, NULL, status); - - if (ffghsp(infptr, &nkeys, NULL, status) > 0) /* get no. of keywords */ - return(*status); - - /* create a memory buffer to hold the header records */ - tmpbuff = (char*) malloc(nkeys*FLEN_CARD*sizeof(char)); - if (!tmpbuff) - return(*status = MEMORY_ALLOCATION); - - /* read all of the header records in the input HDU */ - for (ii = 0; ii < nkeys; ii++) - ffgrec(infptr, ii+1, tmpbuff + (ii * FLEN_CARD), status); - - if (infptr->HDUposition == 0) /* set flag if this is the Primary HDU */ - inPrim = 1; - - /* if input is an image hdu, get the number of axes */ - naxis = -1; /* negative if HDU is a table */ - if ((infptr->Fptr)->hdutype == IMAGE_HDU) - ffgkyj(infptr, "NAXIS", &naxis, NULL, status); - - /* set the output pointer to the correct HDU */ - if (outfptr->HDUposition != (outfptr->Fptr)->curhdu) - ffmahd(outfptr, (outfptr->HDUposition) + 1, NULL, status); - - /* check if output header is empty; if not create new empty HDU */ - if ((outfptr->Fptr)->headend != - (outfptr->Fptr)->headstart[(outfptr->Fptr)->curhdu] ) - ffcrhd(outfptr, status); - - if (outfptr->HDUposition == 0) - { - if (naxis < 0) - { - /* the input HDU is a table, so we have to create */ - /* a dummy Primary array before copying it to the output */ - ffcrim(outfptr, 8, 0, naxes, status); - ffcrhd(outfptr, status); /* create new empty HDU */ - } - else - { - /* set flag that this is the Primary HDU */ - outPrim = 1; - } - } - - if (*status > 0) /* check for errors before proceeding */ - { - free(tmpbuff); - return(*status); - } - if ( inPrim == 1 && outPrim == 0 ) - { - /* copying from primary array to image extension */ - strcpy(comm, "IMAGE extension"); - ffpkys(outfptr, "XTENSION", "IMAGE", comm, status); - - /* copy BITPIX through NAXISn keywords */ - for (ii = 1; ii < 3 + naxis; ii++) - { - card = tmpbuff + (ii * FLEN_CARD); - ffprec(outfptr, card, status); - } - - strcpy(comm, "number of random group parameters"); - ffpkyj(outfptr, "PCOUNT", 0, comm, status); - - strcpy(comm, "number of random groups"); - ffpkyj(outfptr, "GCOUNT", 1, comm, status); - - - /* copy remaining keywords, excluding EXTEND, and reference COMMENT keywords */ - for (ii = 3 + naxis ; ii < nkeys; ii++) - { - card = tmpbuff+(ii * FLEN_CARD); - if (FSTRNCMP(card, "EXTEND ", 8) && - FSTRNCMP(card, "COMMENT FITS (Flexible Image Transport System) format is", 58) && - FSTRNCMP(card, "COMMENT and Astrophysics', volume 376, page 3", 47) ) - { - ffprec(outfptr, card, status); - } - } - } - else if ( inPrim == 0 && outPrim == 1 ) - { - /* copying between image extension and primary array */ - strcpy(comm, "file does conform to FITS standard"); - ffpkyl(outfptr, "SIMPLE", TRUE, comm, status); - - /* copy BITPIX through NAXISn keywords */ - for (ii = 1; ii < 3 + naxis; ii++) - { - card = tmpbuff + (ii * FLEN_CARD); - ffprec(outfptr, card, status); - } - - /* add the EXTEND keyword */ - strcpy(comm, "FITS dataset may contain extensions"); - ffpkyl(outfptr, "EXTEND", TRUE, comm, status); - - /* write standard block of self-documentating comments */ - ffprec(outfptr, - "COMMENT FITS (Flexible Image Transport System) format is defined in 'Astronomy", - status); - ffprec(outfptr, - "COMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H", - status); - - /* copy remaining keywords, excluding pcount, gcount */ - for (ii = 3 + naxis; ii < nkeys; ii++) - { - card = tmpbuff+(ii * FLEN_CARD); - if (FSTRNCMP(card, "PCOUNT ", 8) && FSTRNCMP(card, "GCOUNT ", 8)) - { - ffprec(outfptr, card, status); - } - } - } - else - { - /* input and output HDUs are same type; simply copy all keywords */ - for (ii = 0; ii < nkeys; ii++) - { - card = tmpbuff+(ii * FLEN_CARD); - ffprec(outfptr, card, status); - } - } - - free(tmpbuff); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffcpdt(fitsfile *infptr, /* I - FITS file pointer to input file */ - fitsfile *outfptr, /* I - FITS file pointer to output file */ - int *status) /* IO - error status */ -{ -/* - copy the data unit from the CHDU of infptr to the CHDU of outfptr. - This will overwrite any data already in the outfptr CHDU. -*/ - long nb, ii; - LONGLONG indatastart, indataend, outdatastart; - char buffer[2880]; - - if (*status > 0) - return(*status); - - if (infptr == outfptr) - return(*status = SAME_FILE); - - ffghadll(infptr, NULL, &indatastart, &indataend, status); - ffghadll(outfptr, NULL, &outdatastart, NULL, status); - - /* Calculate the number of blocks to be copied */ - nb = (long) ((indataend - indatastart) / 2880); - - if (nb > 0) - { - if (infptr->Fptr == outfptr->Fptr) - { - /* copying between 2 HDUs in the SAME file */ - for (ii = 0; ii < nb; ii++) - { - ffmbyt(infptr, indatastart, REPORT_EOF, status); - ffgbyt(infptr, 2880L, buffer, status); /* read input block */ - - ffmbyt(outfptr, outdatastart, IGNORE_EOF, status); - ffpbyt(outfptr, 2880L, buffer, status); /* write output block */ - - indatastart += 2880; /* move address */ - outdatastart += 2880; /* move address */ - } - } - else - { - /* copying between HDUs in separate files */ - /* move to the initial copy position in each of the files */ - ffmbyt(infptr, indatastart, REPORT_EOF, status); - ffmbyt(outfptr, outdatastart, IGNORE_EOF, status); - - for (ii = 0; ii < nb; ii++) - { - ffgbyt(infptr, 2880L, buffer, status); /* read input block */ - ffpbyt(outfptr, 2880L, buffer, status); /* write output block */ - } - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffwrhdu(fitsfile *infptr, /* I - FITS file pointer to input file */ - FILE *outstream, /* I - stream to write HDU to */ - int *status) /* IO - error status */ -{ -/* - write the data unit from the CHDU of infptr to the output file stream -*/ - long nb, ii; - LONGLONG hdustart, hduend; - char buffer[2880]; - - if (*status > 0) - return(*status); - - ffghadll(infptr, &hdustart, NULL, &hduend, status); - - nb = (long) ((hduend - hdustart) / 2880); /* number of blocks to copy */ - - if (nb > 0) - { - - /* move to the start of the HDU */ - ffmbyt(infptr, hdustart, REPORT_EOF, status); - - for (ii = 0; ii < nb; ii++) - { - ffgbyt(infptr, 2880L, buffer, status); /* read input block */ - fwrite(buffer, 1, 2880, outstream ); /* write to output stream */ - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffiimg(fitsfile *fptr, /* I - FITS file pointer */ - int bitpix, /* I - bits per pixel */ - int naxis, /* I - number of axes in the array */ - long *naxes, /* I - size of each axis */ - int *status) /* IO - error status */ -/* - insert an IMAGE extension following the current HDU -*/ -{ - LONGLONG tnaxes[99]; - int ii; - - if (*status > 0) - return(*status); - - if (naxis > 99) { - ffpmsg("NAXIS value is too large (>99) (ffiimg)"); - return(*status = 212); - } - - for (ii = 0; (ii < naxis); ii++) - tnaxes[ii] = naxes[ii]; - - ffiimgll(fptr, bitpix, naxis, tnaxes, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffiimgll(fitsfile *fptr, /* I - FITS file pointer */ - int bitpix, /* I - bits per pixel */ - int naxis, /* I - number of axes in the array */ - LONGLONG *naxes, /* I - size of each axis */ - int *status) /* IO - error status */ -/* - insert an IMAGE extension following the current HDU -*/ -{ - int bytlen, nexthdu, maxhdu, ii, onaxis; - long nblocks; - LONGLONG npixels, newstart, datasize; - char errmsg[FLEN_ERRMSG], card[FLEN_CARD], naxiskey[FLEN_KEYWORD]; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - maxhdu = (fptr->Fptr)->maxhdu; - - if (*status != PREPEND_PRIMARY) - { - /* if the current header is completely empty ... */ - if (( (fptr->Fptr)->headend == (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) - /* or, if we are at the end of the file, ... */ - || ( (((fptr->Fptr)->curhdu) == maxhdu ) && - ((fptr->Fptr)->headstart[maxhdu + 1] >= (fptr->Fptr)->logfilesize ) ) ) - { - /* then simply append new image extension */ - ffcrimll(fptr, bitpix, naxis, naxes, status); - return(*status); - } - } - - if (bitpix == 8) - bytlen = 1; - else if (bitpix == 16) - bytlen = 2; - else if (bitpix == 32 || bitpix == -32) - bytlen = 4; - else if (bitpix == 64 || bitpix == -64) - bytlen = 8; - else - { - sprintf(errmsg, - "Illegal value for BITPIX keyword: %d", bitpix); - ffpmsg(errmsg); - return(*status = BAD_BITPIX); /* illegal bitpix value */ - } - if (naxis < 0 || naxis > 999) - { - sprintf(errmsg, - "Illegal value for NAXIS keyword: %d", naxis); - ffpmsg(errmsg); - return(*status = BAD_NAXIS); - } - - for (ii = 0; ii < naxis; ii++) - { - if (naxes[ii] < 0) - { - sprintf(errmsg, - "Illegal value for NAXIS%d keyword: %ld", ii + 1, (long) naxes[ii]); - ffpmsg(errmsg); - return(*status = BAD_NAXES); - } - } - - /* calculate number of pixels in the image */ - if (naxis == 0) - npixels = 0; - else - npixels = naxes[0]; - - for (ii = 1; ii < naxis; ii++) - npixels = npixels * naxes[ii]; - - datasize = npixels * bytlen; /* size of image in bytes */ - nblocks = (long) (((datasize + 2879) / 2880) + 1); /* +1 for the header */ - - if ((fptr->Fptr)->writemode == READWRITE) /* must have write access */ - { /* close the CHDU */ - ffrdef(fptr, status); /* scan header to redefine structure */ - ffpdfl(fptr, status); /* insure correct data file values */ - } - else - return(*status = READONLY_FILE); - - if (*status == PREPEND_PRIMARY) - { - /* inserting a new primary array; the current primary */ - /* array must be transformed into an image extension. */ - - *status = 0; - ffmahd(fptr, 1, NULL, status); /* move to the primary array */ - - ffgidm(fptr, &onaxis, status); - if (onaxis > 0) - ffkeyn("NAXIS",onaxis, naxiskey, status); - else - strcpy(naxiskey, "NAXIS"); - - ffgcrd(fptr, naxiskey, card, status); /* read last NAXIS keyword */ - - ffikyj(fptr, "PCOUNT", 0, "required keyword", status); /* add PCOUNT and */ - ffikyj(fptr, "GCOUNT", 1, "required keyword", status); /* GCOUNT keywords */ - - if (*status > 0) - return(*status); - - if (ffdkey(fptr, "EXTEND", status) ) /* delete the EXTEND keyword */ - *status = 0; - - /* redefine internal structure for this HDU */ - ffrdef(fptr, status); - - - /* insert space for the primary array */ - if (ffiblk(fptr, nblocks, -1, status) > 0) /* insert the blocks */ - return(*status); - - nexthdu = 0; /* number of the new hdu */ - newstart = 0; /* starting addr of HDU */ - } - else - { - nexthdu = ((fptr->Fptr)->curhdu) + 1; /* number of the next (new) hdu */ - newstart = (fptr->Fptr)->headstart[nexthdu]; /* save starting addr of HDU */ - - (fptr->Fptr)->hdutype = IMAGE_HDU; /* so that correct fill value is used */ - /* ffiblk also increments headstart for all following HDUs */ - if (ffiblk(fptr, nblocks, 1, status) > 0) /* insert the blocks */ - return(*status); - } - - ((fptr->Fptr)->maxhdu)++; /* increment known number of HDUs in the file */ - for (ii = (fptr->Fptr)->maxhdu; ii > (fptr->Fptr)->curhdu; ii--) - (fptr->Fptr)->headstart[ii + 1] = (fptr->Fptr)->headstart[ii]; /* incre start addr */ - - if (nexthdu == 0) - (fptr->Fptr)->headstart[1] = nblocks * 2880; /* start of the old Primary array */ - - (fptr->Fptr)->headstart[nexthdu] = newstart; /* set starting addr of HDU */ - - /* set default parameters for this new empty HDU */ - (fptr->Fptr)->curhdu = nexthdu; /* we are now located at the next HDU */ - fptr->HDUposition = nexthdu; /* we are now located at the next HDU */ - (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[nexthdu]; - (fptr->Fptr)->headend = (fptr->Fptr)->headstart[nexthdu]; - (fptr->Fptr)->datastart = ((fptr->Fptr)->headstart[nexthdu]) + 2880; - (fptr->Fptr)->hdutype = IMAGE_HDU; /* might need to be reset... */ - - /* write the required header keywords */ - ffphprll(fptr, TRUE, bitpix, naxis, naxes, 0, 1, TRUE, status); - - /* redefine internal structure for this HDU */ - ffrdef(fptr, status); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffitab(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG naxis1, /* I - width of row in the table */ - LONGLONG naxis2, /* I - number of rows in the table */ - int tfields, /* I - number of columns in the table */ - char **ttype, /* I - name of each column */ - long *tbcol, /* I - byte offset in row to each column */ - char **tform, /* I - value of TFORMn keyword for each column */ - char **tunit, /* I - value of TUNITn keyword for each column */ - const char *extnmx, /* I - value of EXTNAME keyword, if any */ - int *status) /* IO - error status */ -/* - insert an ASCII table extension following the current HDU -*/ -{ - int nexthdu, maxhdu, ii, nunit, nhead, ncols, gotmem = 0; - long nblocks, rowlen; - LONGLONG datasize, newstart; - char errmsg[81], extnm[FLEN_VALUE]; - - if (*status > 0) - return(*status); - - extnm[0] = '\0'; - if (extnmx) - strncat(extnm, extnmx, FLEN_VALUE-1); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - maxhdu = (fptr->Fptr)->maxhdu; - /* if the current header is completely empty ... */ - if (( (fptr->Fptr)->headend == (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) - /* or, if we are at the end of the file, ... */ - || ( (((fptr->Fptr)->curhdu) == maxhdu ) && - ((fptr->Fptr)->headstart[maxhdu + 1] >= (fptr->Fptr)->logfilesize ) ) ) - { - /* then simply append new image extension */ - ffcrtb(fptr, ASCII_TBL, naxis2, tfields, ttype, tform, tunit, - extnm, status); - return(*status); - } - - if (naxis1 < 0) - return(*status = NEG_WIDTH); - else if (naxis2 < 0) - return(*status = NEG_ROWS); - else if (tfields < 0 || tfields > 999) - { - sprintf(errmsg, - "Illegal value for TFIELDS keyword: %d", tfields); - ffpmsg(errmsg); - return(*status = BAD_TFIELDS); - } - - /* count number of optional TUNIT keywords to be written */ - nunit = 0; - for (ii = 0; ii < tfields; ii++) - { - if (tunit && *tunit && *tunit[ii]) - nunit++; - } - - if (*extnm) - nunit++; /* add one for the EXTNAME keyword */ - - rowlen = (long) naxis1; - - if (!tbcol || !tbcol[0] || (!naxis1 && tfields)) /* spacing not defined? */ - { - /* allocate mem for tbcol; malloc may have problems allocating small */ - /* arrays, so allocate at least 20 bytes */ - - ncols = maxvalue(5, tfields); - tbcol = (long *) calloc(ncols, sizeof(long)); - - if (tbcol) - { - gotmem = 1; - - /* calculate width of a row and starting position of each column. */ - /* Each column will be separated by 1 blank space */ - ffgabc(tfields, tform, 1, &rowlen, tbcol, status); - } - } - - nhead = (9 + (3 * tfields) + nunit + 35) / 36; /* no. of header blocks */ - datasize = (LONGLONG)rowlen * naxis2; /* size of table in bytes */ - nblocks = (long) (((datasize + 2879) / 2880) + nhead); /* size of HDU */ - - if ((fptr->Fptr)->writemode == READWRITE) /* must have write access */ - { /* close the CHDU */ - ffrdef(fptr, status); /* scan header to redefine structure */ - ffpdfl(fptr, status); /* insure correct data file values */ - } - else - return(*status = READONLY_FILE); - - nexthdu = ((fptr->Fptr)->curhdu) + 1; /* number of the next (new) hdu */ - newstart = (fptr->Fptr)->headstart[nexthdu]; /* save starting addr of HDU */ - - (fptr->Fptr)->hdutype = ASCII_TBL; /* so that correct fill value is used */ - /* ffiblk also increments headstart for all following HDUs */ - if (ffiblk(fptr, nblocks, 1, status) > 0) /* insert the blocks */ - { - if (gotmem) - free(tbcol); - return(*status); - } - - ((fptr->Fptr)->maxhdu)++; /* increment known number of HDUs in the file */ - for (ii = (fptr->Fptr)->maxhdu; ii > (fptr->Fptr)->curhdu; ii--) - (fptr->Fptr)->headstart[ii + 1] = (fptr->Fptr)->headstart[ii]; /* incre start addr */ - - (fptr->Fptr)->headstart[nexthdu] = newstart; /* set starting addr of HDU */ - - /* set default parameters for this new empty HDU */ - (fptr->Fptr)->curhdu = nexthdu; /* we are now located at the next HDU */ - fptr->HDUposition = nexthdu; /* we are now located at the next HDU */ - (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[nexthdu]; - (fptr->Fptr)->headend = (fptr->Fptr)->headstart[nexthdu]; - (fptr->Fptr)->datastart = ((fptr->Fptr)->headstart[nexthdu]) + (nhead * 2880); - (fptr->Fptr)->hdutype = ASCII_TBL; /* might need to be reset... */ - - /* write the required header keywords */ - - ffphtb(fptr, rowlen, naxis2, tfields, ttype, tbcol, tform, tunit, - extnm, status); - - if (gotmem) - free(tbcol); - - /* redefine internal structure for this HDU */ - - ffrdef(fptr, status); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffibin(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG naxis2, /* I - number of rows in the table */ - int tfields, /* I - number of columns in the table */ - char **ttype, /* I - name of each column */ - char **tform, /* I - value of TFORMn keyword for each column */ - char **tunit, /* I - value of TUNITn keyword for each column */ - const char *extnmx, /* I - value of EXTNAME keyword, if any */ - LONGLONG pcount, /* I - size of special data area (heap) */ - int *status) /* IO - error status */ -/* - insert a Binary table extension following the current HDU -*/ -{ - int nexthdu, maxhdu, ii, nunit, nhead, datacode; - LONGLONG naxis1; - long nblocks, repeat, width; - LONGLONG datasize, newstart; - char errmsg[81], extnm[FLEN_VALUE]; - - if (*status > 0) - return(*status); - - extnm[0] = '\0'; - if (extnmx) - strncat(extnm, extnmx, FLEN_VALUE-1); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - maxhdu = (fptr->Fptr)->maxhdu; - /* if the current header is completely empty ... */ - if (( (fptr->Fptr)->headend == (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) - /* or, if we are at the end of the file, ... */ - || ( (((fptr->Fptr)->curhdu) == maxhdu ) && - ((fptr->Fptr)->headstart[maxhdu + 1] >= (fptr->Fptr)->logfilesize ) ) ) - { - /* then simply append new image extension */ - ffcrtb(fptr, BINARY_TBL, naxis2, tfields, ttype, tform, tunit, - extnm, status); - return(*status); - } - - if (naxis2 < 0) - return(*status = NEG_ROWS); - else if (tfields < 0 || tfields > 999) - { - sprintf(errmsg, - "Illegal value for TFIELDS keyword: %d", tfields); - ffpmsg(errmsg); - return(*status = BAD_TFIELDS); - } - - /* count number of optional TUNIT keywords to be written */ - nunit = 0; - for (ii = 0; ii < tfields; ii++) - { - if (tunit && *tunit && *tunit[ii]) - nunit++; - } - - if (*extnm) - nunit++; /* add one for the EXTNAME keyword */ - - nhead = (9 + (2 * tfields) + nunit + 35) / 36; /* no. of header blocks */ - - /* calculate total width of the table */ - naxis1 = 0; - for (ii = 0; ii < tfields; ii++) - { - ffbnfm(tform[ii], &datacode, &repeat, &width, status); - - if (datacode == TBIT) - naxis1 = naxis1 + ((repeat + 7) / 8); - else if (datacode == TSTRING) - naxis1 += repeat; - else - naxis1 = naxis1 + (repeat * width); - } - - datasize = ((LONGLONG)naxis1 * naxis2) + pcount; /* size of table in bytes */ - nblocks = (long) ((datasize + 2879) / 2880) + nhead; /* size of HDU */ - - if ((fptr->Fptr)->writemode == READWRITE) /* must have write access */ - { /* close the CHDU */ - ffrdef(fptr, status); /* scan header to redefine structure */ - ffpdfl(fptr, status); /* insure correct data file values */ - } - else - return(*status = READONLY_FILE); - - nexthdu = ((fptr->Fptr)->curhdu) + 1; /* number of the next (new) hdu */ - newstart = (fptr->Fptr)->headstart[nexthdu]; /* save starting addr of HDU */ - - (fptr->Fptr)->hdutype = BINARY_TBL; /* so that correct fill value is used */ - - /* ffiblk also increments headstart for all following HDUs */ - if (ffiblk(fptr, nblocks, 1, status) > 0) /* insert the blocks */ - return(*status); - - ((fptr->Fptr)->maxhdu)++; /* increment known number of HDUs in the file */ - for (ii = (fptr->Fptr)->maxhdu; ii > (fptr->Fptr)->curhdu; ii--) - (fptr->Fptr)->headstart[ii + 1] = (fptr->Fptr)->headstart[ii]; /* incre start addr */ - - (fptr->Fptr)->headstart[nexthdu] = newstart; /* set starting addr of HDU */ - - /* set default parameters for this new empty HDU */ - (fptr->Fptr)->curhdu = nexthdu; /* we are now located at the next HDU */ - fptr->HDUposition = nexthdu; /* we are now located at the next HDU */ - (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[nexthdu]; - (fptr->Fptr)->headend = (fptr->Fptr)->headstart[nexthdu]; - (fptr->Fptr)->datastart = ((fptr->Fptr)->headstart[nexthdu]) + (nhead * 2880); - (fptr->Fptr)->hdutype = BINARY_TBL; /* might need to be reset... */ - - /* write the required header keywords. This will write PCOUNT = 0 */ - /* so that the variable length data will be written at the right place */ - ffphbn(fptr, naxis2, tfields, ttype, tform, tunit, extnm, pcount, - status); - - /* redefine internal structure for this HDU (with PCOUNT = 0) */ - ffrdef(fptr, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffdhdu(fitsfile *fptr, /* I - FITS file pointer */ - int *hdutype, /* O - type of the new CHDU after deletion */ - int *status) /* IO - error status */ -/* - Delete the CHDU. If the CHDU is the primary array, then replace the HDU - with an empty primary array with no data. Return the - type of the new CHDU after the old CHDU is deleted. -*/ -{ - int tmptype = 0; - long nblocks, ii, naxes[1]; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - if ((fptr->Fptr)->curhdu == 0) /* replace primary array with null image */ - { - /* ignore any existing keywords */ - (fptr->Fptr)->headend = 0; - (fptr->Fptr)->nextkey = 0; - - /* write default primary array header */ - ffphpr(fptr,1,8,0,naxes,0,1,1,status); - - /* calc number of blocks to delete (leave just 1 block) */ - nblocks = (long) (( (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu + 1] - - 2880 ) / 2880); - - /* ffdblk also updates the starting address of all following HDUs */ - if (nblocks > 0) - { - if (ffdblk(fptr, nblocks, status) > 0) /* delete the HDU */ - return(*status); - } - - /* this might not be necessary, but is doesn't hurt */ - (fptr->Fptr)->datastart = DATA_UNDEFINED; - - ffrdef(fptr, status); /* reinitialize the primary array */ - } - else - { - - /* calc number of blocks to delete */ - nblocks = (long) (( (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu + 1] - - (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) / 2880); - - /* ffdblk also updates the starting address of all following HDUs */ - if (ffdblk(fptr, nblocks, status) > 0) /* delete the HDU */ - return(*status); - - /* delete the CHDU from the list of HDUs */ - for (ii = (fptr->Fptr)->curhdu + 1; ii <= (fptr->Fptr)->maxhdu; ii++) - (fptr->Fptr)->headstart[ii] = (fptr->Fptr)->headstart[ii + 1]; - - (fptr->Fptr)->headstart[(fptr->Fptr)->maxhdu + 1] = 0; - ((fptr->Fptr)->maxhdu)--; /* decrement the known number of HDUs */ - - if (ffrhdu(fptr, &tmptype, status) > 0) /* initialize next HDU */ - { - /* failed (end of file?), so move back one HDU */ - *status = 0; - ffcmsg(); /* clear extraneous error messages */ - ffgext(fptr, ((fptr->Fptr)->curhdu) - 1, &tmptype, status); - } - } - - if (hdutype) - *hdutype = tmptype; - - return(*status); -} - diff --git a/src/external/OpenGR/3rdparty/cfitsio/eval.l b/src/external/OpenGR/3rdparty/cfitsio/eval.l deleted file mode 100644 index 0601cc1f7..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/eval.l +++ /dev/null @@ -1,504 +0,0 @@ -%{ -/************************************************************************/ -/* */ -/* CFITSIO Lexical Parser */ -/* */ -/* This file is one of 3 files containing code which parses an */ -/* arithmetic expression and evaluates it in the context of an input */ -/* FITS file table extension. The CFITSIO lexical parser is divided */ -/* into the following 3 parts/files: the CFITSIO "front-end", */ -/* eval_f.c, contains the interface between the user/CFITSIO and the */ -/* real core of the parser; the FLEX interpreter, eval_l.c, takes the */ -/* input string and parses it into tokens and identifies the FITS */ -/* information required to evaluate the expression (ie, keywords and */ -/* columns); and, the BISON grammar and evaluation routines, eval_y.c, */ -/* receives the FLEX output and determines and performs the actual */ -/* operations. The files eval_l.c and eval_y.c are produced from */ -/* running flex and bison on the files eval.l and eval.y, respectively. */ -/* (flex and bison are available from any GNU archive: see www.gnu.org) */ -/* */ -/* The grammar rules, rather than evaluating the expression in situ, */ -/* builds a tree, or Nodal, structure mapping out the order of */ -/* operations and expression dependencies. This "compilation" process */ -/* allows for much faster processing of multiple rows. This technique */ -/* was developed by Uwe Lammers of the XMM Science Analysis System, */ -/* although the CFITSIO implementation is entirely code original. */ -/* */ -/* */ -/* Modification History: */ -/* */ -/* Kent Blackburn c1992 Original parser code developed for the */ -/* FTOOLS software package, in particular, */ -/* the fselect task. */ -/* Kent Blackburn c1995 BIT column support added */ -/* Peter D Wilson Feb 1998 Vector column support added */ -/* Peter D Wilson May 1998 Ported to CFITSIO library. User */ -/* interface routines written, in essence */ -/* making fselect, fcalc, and maketime */ -/* capabilities available to all tools */ -/* via single function calls. */ -/* Peter D Wilson Jun 1998 Major rewrite of parser core, so as to */ -/* create a run-time evaluation tree, */ -/* inspired by the work of Uwe Lammers, */ -/* resulting in a speed increase of */ -/* 10-100 times. */ -/* Peter D Wilson Jul 1998 gtifilter(a,b,c,d) function added */ -/* Peter D Wilson Aug 1998 regfilter(a,b,c,d) function added */ -/* Peter D Wilson Jul 1999 Make parser fitsfile-independent, */ -/* allowing a purely vector-based usage */ -/* */ -/************************************************************************/ - -#include -#include -#include -#ifdef sparc -#include -#else -#include -#endif -#include "eval_defs.h" - -ParseData gParse; /* Global structure holding all parser information */ - -/***** Internal functions *****/ - - int yyGetVariable( char *varName, YYSTYPE *varVal ); - -static int find_variable( char *varName ); -static int expr_read( char *buf, int nbytes ); - -/***** Definitions *****/ - -#define YY_NO_UNPUT /* Don't include YYUNPUT function */ -#define YY_NEVER_INTERACTIVE 1 - -#define MAXCHR 256 -#define MAXBIT 128 - -#define OCT_0 "000" -#define OCT_1 "001" -#define OCT_2 "010" -#define OCT_3 "011" -#define OCT_4 "100" -#define OCT_5 "101" -#define OCT_6 "110" -#define OCT_7 "111" -#define OCT_X "xxx" - -#define HEX_0 "0000" -#define HEX_1 "0001" -#define HEX_2 "0010" -#define HEX_3 "0011" -#define HEX_4 "0100" -#define HEX_5 "0101" -#define HEX_6 "0110" -#define HEX_7 "0111" -#define HEX_8 "1000" -#define HEX_9 "1001" -#define HEX_A "1010" -#define HEX_B "1011" -#define HEX_C "1100" -#define HEX_D "1101" -#define HEX_E "1110" -#define HEX_F "1111" -#define HEX_X "xxxx" - -/* - MJT - 13 June 1996 - read from buffer instead of stdin - (as per old ftools.skel) -*/ -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( (result = expr_read( (char *) buf, max_size )) < 0 ) \ - YY_FATAL_ERROR( "read() in flex scanner failed" ); - -%} -bit ([bB][01xX]+) -oct ([oO][01234567xX]+) -hex ([hH][0123456789aAbBcCdDeEfFxX]+) -integer [0-9]+ -boolean (t|f|T|F) -real ([0-9]*"."[0-9]+)|([0-9]*"."*[0-9]+[eEdD][+-]?[0-9]+)|([0-9]*".") -constant ("#"[a-zA-Z0-9_]+)|("#""$"[^\n]*"$") -string ([\"][^\"\n]*[\"])|([\'][^\'\n]*[\']) -variable ([a-zA-Z_][a-zA-Z0-9_]*)|("$"[^$\n]*"$") -function [a-zA-Z][a-zA-Z0-9]+"(" -intcast ("(int)"|"(INT)") -fltcast ("(float)"|"(FLOAT)"|"(double)"|"(DOUBLE)") -power ("^"|"**") -not ("!"|".not."|".NOT."|"not."|"NOT.") -or ("||"|".or."|".OR."|"or."|"OR.") -and ("&&"|".and."|".AND."|"and."|"AND.") -equal ("=="|".eq."|".EQ."|"eq."|"EQ.") -not_equal ("!="|".ne."|".NE."|"ne."|"NE.") -greater (">"|".gt."|".GT."|"gt."|"GT.") -lesser ("<"|".lt."|".LT."|"lt."|"LT.") -greater_eq (">="|"=>"|".ge."|".GE."|"ge."|"GE.") -lesser_eq ("<="|"=<"|".le."|".LE."|"le."|"LE.") -nl \n - -%% - -[ \t]+ ; -{bit} { - int len; - len = strlen(yytext); - while (yytext[len] == ' ') - len--; - len = len - 1; - strncpy(yylval.str,&yytext[1],len); - yylval.str[len] = '\0'; - return( BITSTR ); - } -{oct} { - int len; - char tmpstring[256]; - char bitstring[256]; - len = strlen(yytext); - if (len >= 256) { - char errMsg[100]; - gParse.status = PARSE_SYNTAX_ERR; - strcpy (errMsg,"Bit string exceeds maximum length: '"); - strncat(errMsg, &(yytext[0]), 20); - strcat (errMsg,"...'"); - ffpmsg (errMsg); - len = 0; - } else { - while (yytext[len] == ' ') - len--; - len = len - 1; - strncpy(tmpstring,&yytext[1],len); - } - tmpstring[len] = '\0'; - bitstring[0] = '\0'; - len = 0; - while ( tmpstring[len] != '\0') - { - switch ( tmpstring[len] ) - { - case '0': - strcat(bitstring,OCT_0); - break; - case '1': - strcat(bitstring,OCT_1); - break; - case '2': - strcat(bitstring,OCT_2); - break; - case '3': - strcat(bitstring,OCT_3); - break; - case '4': - strcat(bitstring,OCT_4); - break; - case '5': - strcat(bitstring,OCT_5); - break; - case '6': - strcat(bitstring,OCT_6); - break; - case '7': - strcat(bitstring,OCT_7); - break; - case 'x': - case 'X': - strcat(bitstring,OCT_X); - break; - } - len++; - } - strcpy( yylval.str, bitstring ); - return( BITSTR ); - } -{hex} { - int len; - char tmpstring[256]; - char bitstring[256]; - len = strlen(yytext); - if (len >= 256) { - char errMsg[100]; - gParse.status = PARSE_SYNTAX_ERR; - strcpy (errMsg,"Hex string exceeds maximum length: '"); - strncat(errMsg, &(yytext[0]), 20); - strcat (errMsg,"...'"); - ffpmsg (errMsg); - len = 0; - } else { - while (yytext[len] == ' ') - len--; - len = len - 1; - strncpy(tmpstring,&yytext[1],len); - } - tmpstring[len] = '\0'; - bitstring[0] = '\0'; - len = 0; - while ( tmpstring[len] != '\0') - { - switch ( tmpstring[len] ) - { - case '0': - strcat(bitstring,HEX_0); - break; - case '1': - strcat(bitstring,HEX_1); - break; - case '2': - strcat(bitstring,HEX_2); - break; - case '3': - strcat(bitstring,HEX_3); - break; - case '4': - strcat(bitstring,HEX_4); - break; - case '5': - strcat(bitstring,HEX_5); - break; - case '6': - strcat(bitstring,HEX_6); - break; - case '7': - strcat(bitstring,HEX_7); - break; - case '8': - strcat(bitstring,HEX_8); - break; - case '9': - strcat(bitstring,HEX_9); - break; - case 'a': - case 'A': - strcat(bitstring,HEX_A); - break; - case 'b': - case 'B': - strcat(bitstring,HEX_B); - break; - case 'c': - case 'C': - strcat(bitstring,HEX_C); - break; - case 'd': - case 'D': - strcat(bitstring,HEX_D); - break; - case 'e': - case 'E': - strcat(bitstring,HEX_E); - break; - case 'f': - case 'F': - strcat(bitstring,HEX_F); - break; - case 'x': - case 'X': - strcat(bitstring,HEX_X); - break; - } - len++; - } - - strcpy( yylval.str, bitstring ); - return( BITSTR ); - } -{integer} { - yylval.lng = atol(yytext); - return( LONG ); - } -{boolean} { - if ((yytext[0] == 't') || (yytext[0] == 'T')) - yylval.log = 1; - else - yylval.log = 0; - return( BOOLEAN ); - } -{real} { - yylval.dbl = atof(yytext); - return( DOUBLE ); - } -{constant} { - if( !fits_strcasecmp(yytext,"#PI") ) { - yylval.dbl = (double)(4) * atan((double)(1)); - return( DOUBLE ); - } else if( !fits_strcasecmp(yytext,"#E") ) { - yylval.dbl = exp((double)(1)); - return( DOUBLE ); - } else if( !fits_strcasecmp(yytext,"#DEG") ) { - yylval.dbl = ((double)4)*atan((double)1)/((double)180); - return( DOUBLE ); - } else if( !fits_strcasecmp(yytext,"#ROW") ) { - return( ROWREF ); - } else if( !fits_strcasecmp(yytext,"#NULL") ) { - return( NULLREF ); - } else if( !fits_strcasecmp(yytext,"#SNULL") ) { - return( SNULLREF ); - } else { - int len; - if (yytext[1] == '$') { - len = strlen(yytext) - 3; - yylval.str[0] = '#'; - strncpy(yylval.str+1,&yytext[2],len); - yylval.str[len+1] = '\0'; - yytext = yylval.str; - } - return( (*gParse.getData)(yytext, &yylval) ); - } - } -{string} { - int len; - len = strlen(yytext) - 2; - if (len >= MAX_STRLEN) { - char errMsg[100]; - gParse.status = PARSE_SYNTAX_ERR; - strcpy (errMsg,"String exceeds maximum length: '"); - strncat(errMsg, &(yytext[1]), 20); - strcat (errMsg,"...'"); - ffpmsg (errMsg); - len = 0; - } else { - strncpy(yylval.str,&yytext[1],len); - } - yylval.str[len] = '\0'; - return( STRING ); - } -{variable} { - int len,type; - - if (yytext[0] == '$') { - len = strlen(yytext) - 2; - strncpy(yylval.str,&yytext[1],len); - yylval.str[len] = '\0'; - yytext = yylval.str; - } - type = yyGetVariable(yytext, &yylval); - return( type ); - } -{function} { - char *fname; - int len=0; - fname = &yylval.str[0]; - while( (fname[len]=toupper(yytext[len])) ) len++; - - if( FSTRCMP(fname,"BOX(")==0 - || FSTRCMP(fname,"CIRCLE(")==0 - || FSTRCMP(fname,"ELLIPSE(")==0 - || FSTRCMP(fname,"NEAR(")==0 - || FSTRCMP(fname,"ISNULL(")==0 - ) - /* Return type is always boolean */ - return( BFUNCTION ); - - else if( FSTRCMP(fname,"GTIFILTER(")==0 ) - return( GTIFILTER ); - - else if( FSTRCMP(fname,"REGFILTER(")==0 ) - return( REGFILTER ); - - else if( FSTRCMP(fname,"STRSTR(")==0 ) - return( IFUNCTION ); /* Returns integer */ - - else - return( FUNCTION ); - } -{intcast} { return( INTCAST ); } -{fltcast} { return( FLTCAST ); } -{power} { return( POWER ); } -{not} { return( NOT ); } -{or} { return( OR ); } -{and} { return( AND ); } -{equal} { return( EQ ); } -{not_equal} { return( NE ); } -{greater} { return( GT ); } -{lesser} { return( LT ); } -{greater_eq} { return( GTE ); } -{lesser_eq} { return( LTE ); } -{nl} { return( '\n' ); } -. { return( yytext[0] ); } -%% - -int yywrap() -{ - /* MJT -- 13 June 1996 - Supplied for compatibility with - pre-2.5.1 versions of flex which - do not recognize %option noyywrap - */ - return(1); -} - -/* - expr_read is lifted from old ftools.skel. - Now we can use any version of flex with - no .skel file necessary! MJT - 13 June 1996 - - keep a memory of how many bytes have been - read previously, so that an unlimited-sized - buffer can be supported. PDW - 28 Feb 1998 -*/ - -static int expr_read(char *buf, int nbytes) -{ - int n; - - n = 0; - if( !gParse.is_eobuf ) { - do { - buf[n++] = gParse.expr[gParse.index++]; - } while ((nlng = varNum; - } - return( type ); -} - -static int find_variable(char *varName) -{ - int i; - - if( gParse.nCols ) - for( i=0; i - -#include - -#ifndef alloca -#define alloca malloc -#endif - -/* Random number generators for various distributions */ -#include "simplerng.h" - - /* Shrink the initial stack depth to keep local data <32K (mac limit) */ - /* yacc will allocate more space if needed, though. */ -#define YYINITDEPTH 100 - -/***************************************************************/ -/* Replace Bison's BACKUP macro with one that fixes a bug -- */ -/* must update state after popping the stack -- and allows */ -/* popping multiple terms at one time. */ -/***************************************************************/ - -#define YYNEWBACKUP(token, value) \ - do \ - if (yychar == YYEMPTY ) \ - { yychar = (token); \ - memcpy( &yylval, &(value), sizeof(value) ); \ - yychar1 = YYTRANSLATE (yychar); \ - while (yylen--) YYPOPSTACK; \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { yyerror ("syntax error: cannot back up"); YYERROR; } \ - while (0) - -/***************************************************************/ -/* Useful macros for accessing/testing Nodes */ -/***************************************************************/ - -#define TEST(a) if( (a)<0 ) YYERROR -#define SIZE(a) gParse.Nodes[ a ].value.nelem -#define TYPE(a) gParse.Nodes[ a ].type -#define OPER(a) gParse.Nodes[ a ].operation -#define PROMOTE(a,b) if( TYPE(a) > TYPE(b) ) \ - b = New_Unary( TYPE(a), 0, b ); \ - else if( TYPE(a) < TYPE(b) ) \ - a = New_Unary( TYPE(b), 0, a ); - -/***** Internal functions *****/ - -#ifdef __cplusplus -extern "C" { -#endif - -static int Alloc_Node ( void ); -static void Free_Last_Node( void ); -static void Evaluate_Node ( int thisNode ); - -static int New_Const ( int returnType, void *value, long len ); -static int New_Column( int ColNum ); -static int New_Offset( int ColNum, int offset ); -static int New_Unary ( int returnType, int Op, int Node1 ); -static int New_BinOp ( int returnType, int Node1, int Op, int Node2 ); -static int New_Func ( int returnType, funcOp Op, int nNodes, - int Node1, int Node2, int Node3, int Node4, - int Node5, int Node6, int Node7 ); -static int New_FuncSize( int returnType, funcOp Op, int nNodes, - int Node1, int Node2, int Node3, int Node4, - int Node5, int Node6, int Node7, int Size); -static int New_Deref ( int Var, int nDim, - int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 ); -static int New_GTI ( char *fname, int Node1, char *start, char *stop ); -static int New_REG ( char *fname, int NodeX, int NodeY, char *colNames ); -static int New_Vector( int subNode ); -static int Close_Vec ( int vecNode ); -static int Locate_Col( Node *this ); -static int Test_Dims ( int Node1, int Node2 ); -static void Copy_Dims ( int Node1, int Node2 ); - -static void Allocate_Ptrs( Node *this ); -static void Do_Unary ( Node *this ); -static void Do_Offset ( Node *this ); -static void Do_BinOp_bit ( Node *this ); -static void Do_BinOp_str ( Node *this ); -static void Do_BinOp_log ( Node *this ); -static void Do_BinOp_lng ( Node *this ); -static void Do_BinOp_dbl ( Node *this ); -static void Do_Func ( Node *this ); -static void Do_Deref ( Node *this ); -static void Do_GTI ( Node *this ); -static void Do_REG ( Node *this ); -static void Do_Vector ( Node *this ); - -static long Search_GTI ( double evtTime, long nGTI, double *start, - double *stop, int ordered ); - -static char saobox (double xcen, double ycen, double xwid, double ywid, - double rot, double xcol, double ycol); -static char ellipse(double xcen, double ycen, double xrad, double yrad, - double rot, double xcol, double ycol); -static char circle (double xcen, double ycen, double rad, - double xcol, double ycol); -static char bnear (double x, double y, double tolerance); -static char bitcmp (char *bitstrm1, char *bitstrm2); -static char bitlgte(char *bits1, int oper, char *bits2); - -static void bitand(char *result, char *bitstrm1, char *bitstrm2); -static void bitor (char *result, char *bitstrm1, char *bitstrm2); -static void bitnot(char *result, char *bits); -static int cstrmid(char *dest_str, int dest_len, - char *src_str, int src_len, int pos); - -static void yyerror(char *msg); - -#ifdef __cplusplus - } -#endif - -%} - -%union { - int Node; /* Index of Node */ - double dbl; /* real value */ - long lng; /* integer value */ - char log; /* logical value */ - char str[MAX_STRLEN]; /* string value */ -} - -%token BOOLEAN /* First 3 must be in order of */ -%token LONG /* increasing promotion for later use */ -%token DOUBLE -%token STRING -%token BITSTR -%token FUNCTION -%token BFUNCTION /* Bit function */ -%token IFUNCTION /* Integer function */ -%token GTIFILTER -%token REGFILTER -%token COLUMN -%token BCOLUMN -%token SCOLUMN -%token BITCOL -%token ROWREF -%token NULLREF -%token SNULLREF - -%type expr -%type bexpr -%type sexpr -%type bits -%type vector -%type bvector - -%left ',' '=' ':' '{' '}' -%right '?' -%left OR -%left AND -%left EQ NE '~' -%left GT LT LTE GTE -%left '+' '-' '%' -%left '*' '/' -%left '|' '&' -%right POWER -%left NOT -%left INTCAST FLTCAST -%left UMINUS -%left '[' - -%right ACCUM DIFF - -%% - -lines: /* nothing ; was | lines line */ - | lines line - ; - -line: '\n' {} - | expr '\n' - { if( $1<0 ) { - yyerror("Couldn't build node structure: out of memory?"); - YYERROR; } - gParse.resultNode = $1; - } - | bexpr '\n' - { if( $1<0 ) { - yyerror("Couldn't build node structure: out of memory?"); - YYERROR; } - gParse.resultNode = $1; - } - | sexpr '\n' - { if( $1<0 ) { - yyerror("Couldn't build node structure: out of memory?"); - YYERROR; } - gParse.resultNode = $1; - } - | bits '\n' - { if( $1<0 ) { - yyerror("Couldn't build node structure: out of memory?"); - YYERROR; } - gParse.resultNode = $1; - } - | error '\n' { yyerrok; } - ; - -bvector: '{' bexpr - { $$ = New_Vector( $2 ); TEST($$); } - | bvector ',' bexpr - { - if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) { - $1 = Close_Vec( $1 ); TEST($1); - $$ = New_Vector( $1 ); TEST($$); - } else { - $$ = $1; - } - gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ] - = $3; - } - ; - -vector: '{' expr - { $$ = New_Vector( $2 ); TEST($$); } - | vector ',' expr - { - if( TYPE($1) < TYPE($3) ) - TYPE($1) = TYPE($3); - if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) { - $1 = Close_Vec( $1 ); TEST($1); - $$ = New_Vector( $1 ); TEST($$); - } else { - $$ = $1; - } - gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ] - = $3; - } - | vector ',' bexpr - { - if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) { - $1 = Close_Vec( $1 ); TEST($1); - $$ = New_Vector( $1 ); TEST($$); - } else { - $$ = $1; - } - gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ] - = $3; - } - | bvector ',' expr - { - TYPE($1) = TYPE($3); - if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) { - $1 = Close_Vec( $1 ); TEST($1); - $$ = New_Vector( $1 ); TEST($$); - } else { - $$ = $1; - } - gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ] - = $3; - } - ; - -expr: vector '}' - { $$ = Close_Vec( $1 ); TEST($$); } - ; - -bexpr: bvector '}' - { $$ = Close_Vec( $1 ); TEST($$); } - ; - -bits: BITSTR - { - $$ = New_Const( BITSTR, $1, strlen($1)+1 ); TEST($$); - SIZE($$) = strlen($1); } - | BITCOL - { $$ = New_Column( $1 ); TEST($$); } - | BITCOL '{' expr '}' - { - if( TYPE($3) != LONG - || OPER($3) != CONST_OP ) { - yyerror("Offset argument must be a constant integer"); - YYERROR; - } - $$ = New_Offset( $1, $3 ); TEST($$); - } - | bits '&' bits - { $$ = New_BinOp( BITSTR, $1, '&', $3 ); TEST($$); - SIZE($$) = ( SIZE($1)>SIZE($3) ? SIZE($1) : SIZE($3) ); } - | bits '|' bits - { $$ = New_BinOp( BITSTR, $1, '|', $3 ); TEST($$); - SIZE($$) = ( SIZE($1)>SIZE($3) ? SIZE($1) : SIZE($3) ); } - | bits '+' bits - { - if (SIZE($1)+SIZE($3) >= MAX_STRLEN) { - yyerror("Combined bit string size exceeds " MAX_STRLEN_S " bits"); - YYERROR; - } - $$ = New_BinOp( BITSTR, $1, '+', $3 ); TEST($$); - SIZE($$) = SIZE($1) + SIZE($3); - } - | bits '[' expr ']' - { $$ = New_Deref( $1, 1, $3, 0, 0, 0, 0 ); TEST($$); } - | bits '[' expr ',' expr ']' - { $$ = New_Deref( $1, 2, $3, $5, 0, 0, 0 ); TEST($$); } - | bits '[' expr ',' expr ',' expr ']' - { $$ = New_Deref( $1, 3, $3, $5, $7, 0, 0 ); TEST($$); } - | bits '[' expr ',' expr ',' expr ',' expr ']' - { $$ = New_Deref( $1, 4, $3, $5, $7, $9, 0 ); TEST($$); } - | bits '[' expr ',' expr ',' expr ',' expr ',' expr ']' - { $$ = New_Deref( $1, 5, $3, $5, $7, $9, $11 ); TEST($$); } - | NOT bits - { $$ = New_Unary( BITSTR, NOT, $2 ); TEST($$); } - - | '(' bits ')' - { $$ = $2; } - ; - -expr: LONG - { $$ = New_Const( LONG, &($1), sizeof(long) ); TEST($$); } - | DOUBLE - { $$ = New_Const( DOUBLE, &($1), sizeof(double) ); TEST($$); } - | COLUMN - { $$ = New_Column( $1 ); TEST($$); } - | COLUMN '{' expr '}' - { - if( TYPE($3) != LONG - || OPER($3) != CONST_OP ) { - yyerror("Offset argument must be a constant integer"); - YYERROR; - } - $$ = New_Offset( $1, $3 ); TEST($$); - } - | ROWREF - { $$ = New_Func( LONG, row_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); } - | NULLREF - { $$ = New_Func( LONG, null_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); } - | expr '%' expr - { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '%', $3 ); - TEST($$); } - | expr '+' expr - { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '+', $3 ); - TEST($$); } - | expr '-' expr - { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '-', $3 ); - TEST($$); } - | expr '*' expr - { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '*', $3 ); - TEST($$); } - | expr '/' expr - { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '/', $3 ); - TEST($$); } - | expr POWER expr - { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, POWER, $3 ); - TEST($$); } - | '+' expr %prec UMINUS - { $$ = $2; } - | '-' expr %prec UMINUS - { $$ = New_Unary( TYPE($2), UMINUS, $2 ); TEST($$); } - | '(' expr ')' - { $$ = $2; } - | expr '*' bexpr - { $3 = New_Unary( TYPE($1), 0, $3 ); - $$ = New_BinOp( TYPE($1), $1, '*', $3 ); - TEST($$); } - | bexpr '*' expr - { $1 = New_Unary( TYPE($3), 0, $1 ); - $$ = New_BinOp( TYPE($3), $1, '*', $3 ); - TEST($$); } - | bexpr '?' expr ':' expr - { - PROMOTE($3,$5); - if( ! Test_Dims($3,$5) ) { - yyerror("Incompatible dimensions in '?:' arguments"); - YYERROR; - } - $$ = New_Func( 0, ifthenelse_fct, 3, $3, $5, $1, - 0, 0, 0, 0 ); - TEST($$); - if( SIZE($3)=SIZE($4) && Test_Dims( $2, $4 ) ) { - PROMOTE($2,$4); - $$ = New_Func( 0, defnull_fct, 2, $2, $4, 0, - 0, 0, 0, 0 ); - TEST($$); - } else { - yyerror("Dimensions of DEFNULL arguments " - "are not compatible"); - YYERROR; - } - } else if (FSTRCMP($1,"ARCTAN2(") == 0) { - if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 ); - if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 ); - if( Test_Dims( $2, $4 ) ) { - $$ = New_Func( 0, atan2_fct, 2, $2, $4, 0, 0, 0, 0, 0 ); - TEST($$); - if( SIZE($2)=SIZE($4) && Test_Dims( $2, $4 ) ) { - $$ = New_Func( 0, defnull_fct, 2, $2, $4, 0, - 0, 0, 0, 0 ); - TEST($$); - } else { - yyerror("Dimensions of DEFNULL arguments are not compatible"); - YYERROR; - } - } else { - yyerror("Boolean Function(expr,expr) not supported"); - YYERROR; - } - } - | BFUNCTION expr ',' expr ',' expr ')' - { - if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 ); - if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 ); - if( TYPE($6) != DOUBLE ) $6 = New_Unary( DOUBLE, 0, $6 ); - if( ! (Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) ) ) { - yyerror("Dimensions of NEAR arguments " - "are not compatible"); - YYERROR; - } else { - if (FSTRCMP($1,"NEAR(") == 0) { - $$ = New_Func( BOOLEAN, near_fct, 3, $2, $4, $6, - 0, 0, 0, 0 ); - } else { - yyerror("Boolean Function not supported"); - YYERROR; - } - TEST($$); - - if( SIZE($$)= MAX_STRLEN) { - yyerror("Combined string size exceeds " MAX_STRLEN_S " characters"); - YYERROR; - } - $$ = New_BinOp( STRING, $1, '+', $3 ); TEST($$); - SIZE($$) = SIZE($1) + SIZE($3); - } - | bexpr '?' sexpr ':' sexpr - { - int outSize; - if( SIZE($1)!=1 ) { - yyerror("Cannot have a vector string column"); - YYERROR; - } - /* Since the output can be calculated now, as a constant - scalar, we must precalculate the output size, in - order to avoid an overflow. */ - outSize = SIZE($3); - if (SIZE($5) > outSize) outSize = SIZE($5); - $$ = New_FuncSize( 0, ifthenelse_fct, 3, $3, $5, $1, - 0, 0, 0, 0, outSize); - - TEST($$); - if( SIZE($3) outSize) outSize = SIZE($4); - - $$ = New_FuncSize( 0, defnull_fct, 2, $2, $4, 0, - 0, 0, 0, 0, outSize ); - TEST($$); - if( SIZE($4)>SIZE($2) ) SIZE($$) = SIZE($4); - } else { - yyerror("Function(string,string) not supported"); - YYERROR; - } - } - | FUNCTION sexpr ',' expr ',' expr ')' - { - if (FSTRCMP($1,"STRMID(") == 0) { - int len; - if( TYPE($4) != LONG || SIZE($4) != 1 || - TYPE($6) != LONG || SIZE($6) != 1) { - yyerror("When using STRMID(S,P,N), P and N must be integers (and not vector columns)"); - YYERROR; - } - if (OPER($6) == CONST_OP) { - /* Constant value: use that directly */ - len = (gParse.Nodes[$6].value.data.lng); - } else { - /* Variable value: use the maximum possible (from $2) */ - len = SIZE($2); - } - if (len <= 0 || len >= MAX_STRLEN) { - yyerror("STRMID(S,P,N), N must be 1-" MAX_STRLEN_S); - YYERROR; - } - $$ = New_FuncSize( 0, strmid_fct, 3, $2, $4,$6,0,0,0,0,len); - TEST($$); - } else { - yyerror("Function(string,expr,expr) not supported"); - YYERROR; - } - } - - ; - -%% - -/*************************************************************************/ -/* Start of "New" routines which build the expression Nodal structure */ -/*************************************************************************/ - -static int Alloc_Node( void ) -{ - /* Use this for allocation to guarantee *Nodes */ - Node *newNodePtr; /* survives on failure, making it still valid */ - /* while working our way out of this error */ - - if( gParse.nNodes == gParse.nNodesAlloc ) { - if( gParse.Nodes ) { - gParse.nNodesAlloc += gParse.nNodesAlloc; - newNodePtr = (Node *)realloc( gParse.Nodes, - sizeof(Node)*gParse.nNodesAlloc ); - } else { - gParse.nNodesAlloc = 100; - newNodePtr = (Node *)malloc ( sizeof(Node)*gParse.nNodesAlloc ); - } - - if( newNodePtr ) { - gParse.Nodes = newNodePtr; - } else { - gParse.status = MEMORY_ALLOCATION; - return( -1 ); - } - } - - return ( gParse.nNodes++ ); -} - -static void Free_Last_Node( void ) -{ - if( gParse.nNodes ) gParse.nNodes--; -} - -static int New_Const( int returnType, void *value, long len ) -{ - Node *this; - int n; - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->operation = CONST_OP; /* Flag a constant */ - this->DoOp = NULL; - this->nSubNodes = 0; - this->type = returnType; - memcpy( &(this->value.data), value, len ); - this->value.undef = NULL; - this->value.nelem = 1; - this->value.naxis = 1; - this->value.naxes[0] = 1; - } - return(n); -} - -static int New_Column( int ColNum ) -{ - Node *this; - int n, i; - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->operation = -ColNum; - this->DoOp = NULL; - this->nSubNodes = 0; - this->type = gParse.varData[ColNum].type; - this->value.nelem = gParse.varData[ColNum].nelem; - this->value.naxis = gParse.varData[ColNum].naxis; - for( i=0; ivalue.naxes[i] = gParse.varData[ColNum].naxes[i]; - } - return(n); -} - -static int New_Offset( int ColNum, int offsetNode ) -{ - Node *this; - int n, i, colNode; - - colNode = New_Column( ColNum ); - if( colNode<0 ) return(-1); - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->operation = '{'; - this->DoOp = Do_Offset; - this->nSubNodes = 2; - this->SubNodes[0] = colNode; - this->SubNodes[1] = offsetNode; - this->type = gParse.varData[ColNum].type; - this->value.nelem = gParse.varData[ColNum].nelem; - this->value.naxis = gParse.varData[ColNum].naxis; - for( i=0; ivalue.naxes[i] = gParse.varData[ColNum].naxes[i]; - } - return(n); -} - -static int New_Unary( int returnType, int Op, int Node1 ) -{ - Node *this, *that; - int i,n; - - if( Node1<0 ) return(-1); - that = gParse.Nodes + Node1; - - if( !Op ) Op = returnType; - - if( (Op==DOUBLE || Op==FLTCAST) && that->type==DOUBLE ) return( Node1 ); - if( (Op==LONG || Op==INTCAST) && that->type==LONG ) return( Node1 ); - if( (Op==BOOLEAN ) && that->type==BOOLEAN ) return( Node1 ); - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->operation = Op; - this->DoOp = Do_Unary; - this->nSubNodes = 1; - this->SubNodes[0] = Node1; - this->type = returnType; - - that = gParse.Nodes + Node1; /* Reset in case .Nodes mv'd */ - this->value.nelem = that->value.nelem; - this->value.naxis = that->value.naxis; - for( i=0; ivalue.naxis; i++ ) - this->value.naxes[i] = that->value.naxes[i]; - - if( that->operation==CONST_OP ) this->DoOp( this ); - } - return( n ); -} - -static int New_BinOp( int returnType, int Node1, int Op, int Node2 ) -{ - Node *this,*that1,*that2; - int n,i,constant; - - if( Node1<0 || Node2<0 ) return(-1); - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->operation = Op; - this->nSubNodes = 2; - this->SubNodes[0]= Node1; - this->SubNodes[1]= Node2; - this->type = returnType; - - that1 = gParse.Nodes + Node1; - that2 = gParse.Nodes + Node2; - constant = (that1->operation==CONST_OP - && that2->operation==CONST_OP); - if( that1->type!=STRING && that1->type!=BITSTR ) - if( !Test_Dims( Node1, Node2 ) ) { - Free_Last_Node(); - yyerror("Array sizes/dims do not match for binary operator"); - return(-1); - } - if( that1->value.nelem == 1 ) that1 = that2; - - this->value.nelem = that1->value.nelem; - this->value.naxis = that1->value.naxis; - for( i=0; ivalue.naxis; i++ ) - this->value.naxes[i] = that1->value.naxes[i]; - - if ( Op == ACCUM && that1->type == BITSTR ) { - /* ACCUM is rank-reducing on bit strings */ - this->value.nelem = 1; - this->value.naxis = 1; - this->value.naxes[0] = 1; - } - - /* Both subnodes should be of same time */ - switch( that1->type ) { - case BITSTR: this->DoOp = Do_BinOp_bit; break; - case STRING: this->DoOp = Do_BinOp_str; break; - case BOOLEAN: this->DoOp = Do_BinOp_log; break; - case LONG: this->DoOp = Do_BinOp_lng; break; - case DOUBLE: this->DoOp = Do_BinOp_dbl; break; - } - if( constant ) this->DoOp( this ); - } - return( n ); -} - -static int New_Func( int returnType, funcOp Op, int nNodes, - int Node1, int Node2, int Node3, int Node4, - int Node5, int Node6, int Node7 ) -{ - return New_FuncSize(returnType, Op, nNodes, - Node1, Node2, Node3, Node4, - Node5, Node6, Node7, 0); -} - -static int New_FuncSize( int returnType, funcOp Op, int nNodes, - int Node1, int Node2, int Node3, int Node4, - int Node5, int Node6, int Node7, int Size ) -/* If returnType==0 , use Node1's type and vector sizes as returnType, */ -/* else return a single value of type returnType */ -{ - Node *this, *that; - int i,n,constant; - - if( Node1<0 || Node2<0 || Node3<0 || Node4<0 || - Node5<0 || Node6<0 || Node7<0 ) return(-1); - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->operation = (int)Op; - this->DoOp = Do_Func; - this->nSubNodes = nNodes; - this->SubNodes[0] = Node1; - this->SubNodes[1] = Node2; - this->SubNodes[2] = Node3; - this->SubNodes[3] = Node4; - this->SubNodes[4] = Node5; - this->SubNodes[5] = Node6; - this->SubNodes[6] = Node7; - i = constant = nNodes; /* Functions with zero params are not const */ - if (Op == poirnd_fct) constant = 0; /* Nor is Poisson deviate */ - - while( i-- ) - constant = ( constant && OPER(this->SubNodes[i]) == CONST_OP ); - - if( returnType ) { - this->type = returnType; - this->value.nelem = 1; - this->value.naxis = 1; - this->value.naxes[0] = 1; - } else { - that = gParse.Nodes + Node1; - this->type = that->type; - this->value.nelem = that->value.nelem; - this->value.naxis = that->value.naxis; - for( i=0; ivalue.naxis; i++ ) - this->value.naxes[i] = that->value.naxes[i]; - } - /* Force explicit size before evaluating */ - if (Size > 0) this->value.nelem = Size; - - if( constant ) this->DoOp( this ); - } - return( n ); -} - -static int New_Deref( int Var, int nDim, - int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 ) -{ - int n, idx, constant; - long elem=0; - Node *this, *theVar, *theDim[MAXDIMS]; - - if( Var<0 || Dim1<0 || Dim2<0 || Dim3<0 || Dim4<0 || Dim5<0 ) return(-1); - - theVar = gParse.Nodes + Var; - if( theVar->operation==CONST_OP || theVar->value.nelem==1 ) { - yyerror("Cannot index a scalar value"); - return(-1); - } - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->nSubNodes = nDim+1; - theVar = gParse.Nodes + (this->SubNodes[0]=Var); - theDim[0] = gParse.Nodes + (this->SubNodes[1]=Dim1); - theDim[1] = gParse.Nodes + (this->SubNodes[2]=Dim2); - theDim[2] = gParse.Nodes + (this->SubNodes[3]=Dim3); - theDim[3] = gParse.Nodes + (this->SubNodes[4]=Dim4); - theDim[4] = gParse.Nodes + (this->SubNodes[5]=Dim5); - constant = theVar->operation==CONST_OP; - for( idx=0; idxoperation==CONST_OP); - - for( idx=0; idxvalue.nelem>1 ) { - Free_Last_Node(); - yyerror("Cannot use an array as an index value"); - return(-1); - } else if( theDim[idx]->type!=LONG ) { - Free_Last_Node(); - yyerror("Index value must be an integer type"); - return(-1); - } - - this->operation = '['; - this->DoOp = Do_Deref; - this->type = theVar->type; - - if( theVar->value.naxis == nDim ) { /* All dimensions specified */ - this->value.nelem = 1; - this->value.naxis = 1; - this->value.naxes[0] = 1; - } else if( nDim==1 ) { /* Dereference only one dimension */ - elem=1; - this->value.naxis = theVar->value.naxis-1; - for( idx=0; idxvalue.naxis; idx++ ) { - elem *= ( this->value.naxes[idx] = theVar->value.naxes[idx] ); - } - this->value.nelem = elem; - } else { - Free_Last_Node(); - yyerror("Must specify just one or all indices for vector"); - return(-1); - } - if( constant ) this->DoOp( this ); - } - return(n); -} - -extern int yyGetVariable( char *varName, YYSTYPE *varVal ); - -static int New_GTI( char *fname, int Node1, char *start, char *stop ) -{ - fitsfile *fptr; - Node *this, *that0, *that1; - int type,i,n, startCol, stopCol, Node0; - int hdutype, hdunum, evthdu, samefile, extvers, movetotype, tstat; - char extname[100]; - long nrows; - double timeZeroI[2], timeZeroF[2], dt, timeSpan; - char xcol[20], xexpr[20]; - YYSTYPE colVal; - - if( Node1==-99 ) { - type = yyGetVariable( "TIME", &colVal ); - if( type==COLUMN ) { - Node1 = New_Column( (int)colVal.lng ); - } else { - yyerror("Could not build TIME column for GTIFILTER"); - return(-1); - } - } - Node1 = New_Unary( DOUBLE, 0, Node1 ); - Node0 = Alloc_Node(); /* This will hold the START/STOP times */ - if( Node1<0 || Node0<0 ) return(-1); - - /* Record current HDU number in case we need to move within this file */ - - fptr = gParse.def_fptr; - ffghdn( fptr, &evthdu ); - - /* Look for TIMEZERO keywords in current extension */ - - tstat = 0; - if( ffgkyd( fptr, "TIMEZERO", timeZeroI, NULL, &tstat ) ) { - tstat = 0; - if( ffgkyd( fptr, "TIMEZERI", timeZeroI, NULL, &tstat ) ) { - timeZeroI[0] = timeZeroF[0] = 0.0; - } else if( ffgkyd( fptr, "TIMEZERF", timeZeroF, NULL, &tstat ) ) { - timeZeroF[0] = 0.0; - } - } else { - timeZeroF[0] = 0.0; - } - - /* Resolve filename parameter */ - - switch( fname[0] ) { - case '\0': - samefile = 1; - hdunum = 1; - break; - case '[': - samefile = 1; - i = 1; - while( fname[i] != '\0' && fname[i] != ']' ) i++; - if( fname[i] ) { - fname[i] = '\0'; - fname++; - ffexts( fname, &hdunum, extname, &extvers, &movetotype, - xcol, xexpr, &gParse.status ); - if( *extname ) { - ffmnhd( fptr, movetotype, extname, extvers, &gParse.status ); - ffghdn( fptr, &hdunum ); - } else if( hdunum ) { - ffmahd( fptr, ++hdunum, &hdutype, &gParse.status ); - } else if( !gParse.status ) { - yyerror("Cannot use primary array for GTI filter"); - return( -1 ); - } - } else { - yyerror("File extension specifier lacks closing ']'"); - return( -1 ); - } - break; - case '+': - samefile = 1; - hdunum = atoi( fname ) + 1; - if( hdunum>1 ) - ffmahd( fptr, hdunum, &hdutype, &gParse.status ); - else { - yyerror("Cannot use primary array for GTI filter"); - return( -1 ); - } - break; - default: - samefile = 0; - if( ! ffopen( &fptr, fname, READONLY, &gParse.status ) ) - ffghdn( fptr, &hdunum ); - break; - } - if( gParse.status ) return(-1); - - /* If at primary, search for GTI extension */ - - if( hdunum==1 ) { - while( 1 ) { - hdunum++; - if( ffmahd( fptr, hdunum, &hdutype, &gParse.status ) ) break; - if( hdutype==IMAGE_HDU ) continue; - tstat = 0; - if( ffgkys( fptr, "EXTNAME", extname, NULL, &tstat ) ) continue; - ffupch( extname ); - if( strstr( extname, "GTI" ) ) break; - } - if( gParse.status ) { - if( gParse.status==END_OF_FILE ) - yyerror("GTI extension not found in this file"); - return(-1); - } - } - - /* Locate START/STOP Columns */ - - ffgcno( fptr, CASEINSEN, start, &startCol, &gParse.status ); - ffgcno( fptr, CASEINSEN, stop, &stopCol, &gParse.status ); - if( gParse.status ) return(-1); - - /* Look for TIMEZERO keywords in GTI extension */ - - tstat = 0; - if( ffgkyd( fptr, "TIMEZERO", timeZeroI+1, NULL, &tstat ) ) { - tstat = 0; - if( ffgkyd( fptr, "TIMEZERI", timeZeroI+1, NULL, &tstat ) ) { - timeZeroI[1] = timeZeroF[1] = 0.0; - } else if( ffgkyd( fptr, "TIMEZERF", timeZeroF+1, NULL, &tstat ) ) { - timeZeroF[1] = 0.0; - } - } else { - timeZeroF[1] = 0.0; - } - - n = Alloc_Node(); - if( n >= 0 ) { - this = gParse.Nodes + n; - this->nSubNodes = 2; - this->SubNodes[1] = Node1; - this->operation = (int)gtifilt_fct; - this->DoOp = Do_GTI; - this->type = BOOLEAN; - that1 = gParse.Nodes + Node1; - this->value.nelem = that1->value.nelem; - this->value.naxis = that1->value.naxis; - for( i=0; i < that1->value.naxis; i++ ) - this->value.naxes[i] = that1->value.naxes[i]; - - /* Init START/STOP node to be treated as a "constant" */ - - this->SubNodes[0] = Node0; - that0 = gParse.Nodes + Node0; - that0->operation = CONST_OP; - that0->DoOp = NULL; - that0->value.data.ptr= NULL; - - /* Read in START/STOP times */ - - if( ffgkyj( fptr, "NAXIS2", &nrows, NULL, &gParse.status ) ) - return(-1); - that0->value.nelem = nrows; - if( nrows ) { - - that0->value.data.dblptr = (double*)malloc( 2*nrows*sizeof(double) ); - if( !that0->value.data.dblptr ) { - gParse.status = MEMORY_ALLOCATION; - return(-1); - } - - ffgcvd( fptr, startCol, 1L, 1L, nrows, 0.0, - that0->value.data.dblptr, &i, &gParse.status ); - ffgcvd( fptr, stopCol, 1L, 1L, nrows, 0.0, - that0->value.data.dblptr+nrows, &i, &gParse.status ); - if( gParse.status ) { - free( that0->value.data.dblptr ); - return(-1); - } - - /* Test for fully time-ordered GTI... both START && STOP */ - - that0->type = 1; /* Assume yes */ - i = nrows; - while( --i ) - if( that0->value.data.dblptr[i-1] - >= that0->value.data.dblptr[i] - || that0->value.data.dblptr[i-1+nrows] - >= that0->value.data.dblptr[i+nrows] ) { - that0->type = 0; - break; - } - - /* Handle TIMEZERO offset, if any */ - - dt = (timeZeroI[1] - timeZeroI[0]) + (timeZeroF[1] - timeZeroF[0]); - timeSpan = that0->value.data.dblptr[nrows+nrows-1] - - that0->value.data.dblptr[0]; - - if( fabs( dt / timeSpan ) > 1e-12 ) { - for( i=0; i<(nrows+nrows); i++ ) - that0->value.data.dblptr[i] += dt; - } - } - if( OPER(Node1)==CONST_OP ) - this->DoOp( this ); - } - - if( samefile ) - ffmahd( fptr, evthdu, &hdutype, &gParse.status ); - else - ffclos( fptr, &gParse.status ); - - return( n ); -} - -static int New_REG( char *fname, int NodeX, int NodeY, char *colNames ) -{ - Node *this, *that0; - int type, n, Node0; - int Xcol, Ycol, tstat; - WCSdata wcs; - SAORegion *Rgn; - char *cX, *cY; - YYSTYPE colVal; - - if( NodeX==-99 ) { - type = yyGetVariable( "X", &colVal ); - if( type==COLUMN ) { - NodeX = New_Column( (int)colVal.lng ); - } else { - yyerror("Could not build X column for REGFILTER"); - return(-1); - } - } - if( NodeY==-99 ) { - type = yyGetVariable( "Y", &colVal ); - if( type==COLUMN ) { - NodeY = New_Column( (int)colVal.lng ); - } else { - yyerror("Could not build Y column for REGFILTER"); - return(-1); - } - } - NodeX = New_Unary( DOUBLE, 0, NodeX ); - NodeY = New_Unary( DOUBLE, 0, NodeY ); - Node0 = Alloc_Node(); /* This will hold the Region Data */ - if( NodeX<0 || NodeY<0 || Node0<0 ) return(-1); - - if( ! (Test_Dims( NodeX, NodeY ) ) ) { - yyerror("Dimensions of REGFILTER arguments are not compatible"); - return (-1); - } - - n = Alloc_Node(); - if( n >= 0 ) { - this = gParse.Nodes + n; - this->nSubNodes = 3; - this->SubNodes[0] = Node0; - this->SubNodes[1] = NodeX; - this->SubNodes[2] = NodeY; - this->operation = (int)regfilt_fct; - this->DoOp = Do_REG; - this->type = BOOLEAN; - this->value.nelem = 1; - this->value.naxis = 1; - this->value.naxes[0] = 1; - - Copy_Dims(n, NodeX); - if( SIZE(NodeX)operation = CONST_OP; - that0->DoOp = NULL; - - /* Identify what columns to use for WCS information */ - - Xcol = Ycol = 0; - if( *colNames ) { - /* Use the column names in this string for WCS info */ - while( *colNames==' ' ) colNames++; - cX = cY = colNames; - while( *cY && *cY!=' ' && *cY!=',' ) cY++; - if( *cY ) - *(cY++) = '\0'; - while( *cY==' ' ) cY++; - if( !*cY ) { - yyerror("Could not extract valid pair of column names from REGFILTER"); - Free_Last_Node(); - return( -1 ); - } - fits_get_colnum( gParse.def_fptr, CASEINSEN, cX, &Xcol, - &gParse.status ); - fits_get_colnum( gParse.def_fptr, CASEINSEN, cY, &Ycol, - &gParse.status ); - if( gParse.status ) { - yyerror("Could not locate columns indicated for WCS info"); - Free_Last_Node(); - return( -1 ); - } - - } else { - /* Try to find columns used in X/Y expressions */ - Xcol = Locate_Col( gParse.Nodes + NodeX ); - Ycol = Locate_Col( gParse.Nodes + NodeY ); - if( Xcol<0 || Ycol<0 ) { - yyerror("Found multiple X/Y column references in REGFILTER"); - Free_Last_Node(); - return( -1 ); - } - } - - /* Now, get the WCS info, if it exists, from the indicated columns */ - wcs.exists = 0; - if( Xcol>0 && Ycol>0 ) { - tstat = 0; - ffgtcs( gParse.def_fptr, Xcol, Ycol, - &wcs.xrefval, &wcs.yrefval, - &wcs.xrefpix, &wcs.yrefpix, - &wcs.xinc, &wcs.yinc, - &wcs.rot, wcs.type, - &tstat ); - if( tstat==NO_WCS_KEY ) { - wcs.exists = 0; - } else if( tstat ) { - gParse.status = tstat; - Free_Last_Node(); - return( -1 ); - } else { - wcs.exists = 1; - } - } - - /* Read in Region file */ - - fits_read_rgnfile( fname, &wcs, &Rgn, &gParse.status ); - if( gParse.status ) { - Free_Last_Node(); - return( -1 ); - } - - that0->value.data.ptr = Rgn; - - if( OPER(NodeX)==CONST_OP && OPER(NodeY)==CONST_OP ) - this->DoOp( this ); - } - - return( n ); -} - -static int New_Vector( int subNode ) -{ - Node *this, *that; - int n; - - n = Alloc_Node(); - if( n >= 0 ) { - this = gParse.Nodes + n; - that = gParse.Nodes + subNode; - this->type = that->type; - this->nSubNodes = 1; - this->SubNodes[0] = subNode; - this->operation = '{'; - this->DoOp = Do_Vector; - } - - return( n ); -} - -static int Close_Vec( int vecNode ) -{ - Node *this; - int n, nelem=0; - - this = gParse.Nodes + vecNode; - for( n=0; n < this->nSubNodes; n++ ) { - if( TYPE( this->SubNodes[n] ) != this->type ) { - this->SubNodes[n] = New_Unary( this->type, 0, this->SubNodes[n] ); - if( this->SubNodes[n]<0 ) return(-1); - } - nelem += SIZE(this->SubNodes[n]); - } - this->value.naxis = 1; - this->value.nelem = nelem; - this->value.naxes[0] = nelem; - - return( vecNode ); -} - -static int Locate_Col( Node *this ) -/* Locate the TABLE column number of any columns in "this" calculation. */ -/* Return ZERO if none found, or negative if more than 1 found. */ -{ - Node *that; - int i, col=0, newCol, nfound=0; - - if( this->nSubNodes==0 - && this->operation<=0 && this->operation!=CONST_OP ) - return gParse.colData[ - this->operation].colnum; - - for( i=0; inSubNodes; i++ ) { - that = gParse.Nodes + this->SubNodes[i]; - if( that->operation>0 ) { - newCol = Locate_Col( that ); - if( newCol<=0 ) { - nfound += -newCol; - } else { - if( !nfound ) { - col = newCol; - nfound++; - } else if( col != newCol ) { - nfound++; - } - } - } else if( that->operation!=CONST_OP ) { - /* Found a Column */ - newCol = gParse.colData[- that->operation].colnum; - if( !nfound ) { - col = newCol; - nfound++; - } else if( col != newCol ) { - nfound++; - } - } - } - if( nfound!=1 ) - return( - nfound ); - else - return( col ); -} - -static int Test_Dims( int Node1, int Node2 ) -{ - Node *that1, *that2; - int valid, i; - - if( Node1<0 || Node2<0 ) return(0); - - that1 = gParse.Nodes + Node1; - that2 = gParse.Nodes + Node2; - - if( that1->value.nelem==1 || that2->value.nelem==1 ) - valid = 1; - else if( that1->type==that2->type - && that1->value.nelem==that2->value.nelem - && that1->value.naxis==that2->value.naxis ) { - valid = 1; - for( i=0; ivalue.naxis; i++ ) { - if( that1->value.naxes[i]!=that2->value.naxes[i] ) - valid = 0; - } - } else - valid = 0; - return( valid ); -} - -static void Copy_Dims( int Node1, int Node2 ) -{ - Node *that1, *that2; - int i; - - if( Node1<0 || Node2<0 ) return; - - that1 = gParse.Nodes + Node1; - that2 = gParse.Nodes + Node2; - - that1->value.nelem = that2->value.nelem; - that1->value.naxis = that2->value.naxis; - for( i=0; ivalue.naxis; i++ ) - that1->value.naxes[i] = that2->value.naxes[i]; -} - -/********************************************************************/ -/* Routines for actually evaluating the expression start here */ -/********************************************************************/ - -void Evaluate_Parser( long firstRow, long nRows ) - /***********************************************************************/ - /* Reset the parser for processing another batch of data... */ - /* firstRow: Row number of the first element to evaluate */ - /* nRows: Number of rows to be processed */ - /* Initialize each COLUMN node so that its UNDEF and DATA pointers */ - /* point to the appropriate column arrays. */ - /* Finally, call Evaluate_Node for final node. */ - /***********************************************************************/ -{ - int i, column; - long offset, rowOffset; - static int rand_initialized = 0; - - /* Initialize the random number generator once and only once */ - if (rand_initialized == 0) { - simplerng_srand( (unsigned int) time(NULL) ); - rand_initialized = 1; - } - - gParse.firstRow = firstRow; - gParse.nRows = nRows; - - /* Reset Column Nodes' pointers to point to right data and UNDEF arrays */ - - rowOffset = firstRow - gParse.firstDataRow; - for( i=0; i 0 || OPER(i) == CONST_OP ) continue; - - column = -OPER(i); - offset = gParse.varData[column].nelem * rowOffset; - - gParse.Nodes[i].value.undef = gParse.varData[column].undef + offset; - - switch( gParse.Nodes[i].type ) { - case BITSTR: - gParse.Nodes[i].value.data.strptr = - (char**)gParse.varData[column].data + rowOffset; - gParse.Nodes[i].value.undef = NULL; - break; - case STRING: - gParse.Nodes[i].value.data.strptr = - (char**)gParse.varData[column].data + rowOffset; - gParse.Nodes[i].value.undef = gParse.varData[column].undef + rowOffset; - break; - case BOOLEAN: - gParse.Nodes[i].value.data.logptr = - (char*)gParse.varData[column].data + offset; - break; - case LONG: - gParse.Nodes[i].value.data.lngptr = - (long*)gParse.varData[column].data + offset; - break; - case DOUBLE: - gParse.Nodes[i].value.data.dblptr = - (double*)gParse.varData[column].data + offset; - break; - } - } - - Evaluate_Node( gParse.resultNode ); -} - -static void Evaluate_Node( int thisNode ) - /**********************************************************************/ - /* Recursively evaluate thisNode's subNodes, then call one of the */ - /* Do_ functions pointed to by thisNode's DoOp element. */ - /**********************************************************************/ -{ - Node *this; - int i; - - if( gParse.status ) return; - - this = gParse.Nodes + thisNode; - if( this->operation>0 ) { /* <=0 indicate constants and columns */ - i = this->nSubNodes; - while( i-- ) { - Evaluate_Node( this->SubNodes[i] ); - if( gParse.status ) return; - } - this->DoOp( this ); - } -} - -static void Allocate_Ptrs( Node *this ) -{ - long elem, row, size; - - if( this->type==BITSTR || this->type==STRING ) { - - this->value.data.strptr = (char**)malloc( gParse.nRows - * sizeof(char*) ); - if( this->value.data.strptr ) { - this->value.data.strptr[0] = (char*)malloc( gParse.nRows - * (this->value.nelem+2) - * sizeof(char) ); - if( this->value.data.strptr[0] ) { - row = 0; - while( (++row)value.data.strptr[row] = - this->value.data.strptr[row-1] + this->value.nelem+1; - } - if( this->type==STRING ) { - this->value.undef = this->value.data.strptr[row-1] - + this->value.nelem+1; - } else { - this->value.undef = NULL; /* BITSTRs don't use undef array */ - } - } else { - gParse.status = MEMORY_ALLOCATION; - free( this->value.data.strptr ); - } - } else { - gParse.status = MEMORY_ALLOCATION; - } - - } else { - - elem = this->value.nelem * gParse.nRows; - switch( this->type ) { - case DOUBLE: size = sizeof( double ); break; - case LONG: size = sizeof( long ); break; - case BOOLEAN: size = sizeof( char ); break; - default: size = 1; break; - } - - this->value.data.ptr = calloc(size+1, elem); - - if( this->value.data.ptr==NULL ) { - gParse.status = MEMORY_ALLOCATION; - } else { - this->value.undef = (char *)this->value.data.ptr + elem*size; - } - } -} - -static void Do_Unary( Node *this ) -{ - Node *that; - long elem; - - that = gParse.Nodes + this->SubNodes[0]; - - if( that->operation==CONST_OP ) { /* Operating on a constant! */ - switch( this->operation ) { - case DOUBLE: - case FLTCAST: - if( that->type==LONG ) - this->value.data.dbl = (double)that->value.data.lng; - else if( that->type==BOOLEAN ) - this->value.data.dbl = ( that->value.data.log ? 1.0 : 0.0 ); - break; - case LONG: - case INTCAST: - if( that->type==DOUBLE ) - this->value.data.lng = (long)that->value.data.dbl; - else if( that->type==BOOLEAN ) - this->value.data.lng = ( that->value.data.log ? 1L : 0L ); - break; - case BOOLEAN: - if( that->type==DOUBLE ) - this->value.data.log = ( that->value.data.dbl != 0.0 ); - else if( that->type==LONG ) - this->value.data.log = ( that->value.data.lng != 0L ); - break; - case UMINUS: - if( that->type==DOUBLE ) - this->value.data.dbl = - that->value.data.dbl; - else if( that->type==LONG ) - this->value.data.lng = - that->value.data.lng; - break; - case NOT: - if( that->type==BOOLEAN ) - this->value.data.log = ( ! that->value.data.log ); - else if( that->type==BITSTR ) - bitnot( this->value.data.str, that->value.data.str ); - break; - } - this->operation = CONST_OP; - - } else { - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - - if( this->type!=BITSTR ) { - elem = gParse.nRows; - if( this->type!=STRING ) - elem *= this->value.nelem; - while( elem-- ) - this->value.undef[elem] = that->value.undef[elem]; - } - - elem = gParse.nRows * this->value.nelem; - - switch( this->operation ) { - - case BOOLEAN: - if( that->type==DOUBLE ) - while( elem-- ) - this->value.data.logptr[elem] = - ( that->value.data.dblptr[elem] != 0.0 ); - else if( that->type==LONG ) - while( elem-- ) - this->value.data.logptr[elem] = - ( that->value.data.lngptr[elem] != 0L ); - break; - - case DOUBLE: - case FLTCAST: - if( that->type==LONG ) - while( elem-- ) - this->value.data.dblptr[elem] = - (double)that->value.data.lngptr[elem]; - else if( that->type==BOOLEAN ) - while( elem-- ) - this->value.data.dblptr[elem] = - ( that->value.data.logptr[elem] ? 1.0 : 0.0 ); - break; - - case LONG: - case INTCAST: - if( that->type==DOUBLE ) - while( elem-- ) - this->value.data.lngptr[elem] = - (long)that->value.data.dblptr[elem]; - else if( that->type==BOOLEAN ) - while( elem-- ) - this->value.data.lngptr[elem] = - ( that->value.data.logptr[elem] ? 1L : 0L ); - break; - - case UMINUS: - if( that->type==DOUBLE ) { - while( elem-- ) - this->value.data.dblptr[elem] = - - that->value.data.dblptr[elem]; - } else if( that->type==LONG ) { - while( elem-- ) - this->value.data.lngptr[elem] = - - that->value.data.lngptr[elem]; - } - break; - - case NOT: - if( that->type==BOOLEAN ) { - while( elem-- ) - this->value.data.logptr[elem] = - ( ! that->value.data.logptr[elem] ); - } else if( that->type==BITSTR ) { - elem = gParse.nRows; - while( elem-- ) - bitnot( this->value.data.strptr[elem], - that->value.data.strptr[elem] ); - } - break; - } - } - } - - if( that->operation>0 ) { - free( that->value.data.ptr ); - } -} - -static void Do_Offset( Node *this ) -{ - Node *col; - long fRow, nRowOverlap, nRowReload, rowOffset; - long nelem, elem, offset, nRealElem; - int status; - - col = gParse.Nodes + this->SubNodes[0]; - rowOffset = gParse.Nodes[ this->SubNodes[1] ].value.data.lng; - - Allocate_Ptrs( this ); - - fRow = gParse.firstRow + rowOffset; - if( this->type==STRING || this->type==BITSTR ) - nRealElem = 1; - else - nRealElem = this->value.nelem; - - nelem = nRealElem; - - if( fRow < gParse.firstDataRow ) { - - /* Must fill in data at start of array */ - - nRowReload = gParse.firstDataRow - fRow; - if( nRowReload > gParse.nRows ) nRowReload = gParse.nRows; - nRowOverlap = gParse.nRows - nRowReload; - - offset = 0; - - /* NULLify any values falling out of bounds */ - - while( fRow<1 && nRowReload>0 ) { - if( this->type == BITSTR ) { - nelem = this->value.nelem; - this->value.data.strptr[offset][ nelem ] = '\0'; - while( nelem-- ) this->value.data.strptr[offset][nelem] = '0'; - offset++; - } else { - while( nelem-- ) - this->value.undef[offset++] = 1; - } - nelem = nRealElem; - fRow++; - nRowReload--; - } - - } else if( fRow + gParse.nRows > gParse.firstDataRow + gParse.nDataRows ) { - - /* Must fill in data at end of array */ - - nRowReload = (fRow+gParse.nRows) - (gParse.firstDataRow+gParse.nDataRows); - if( nRowReload>gParse.nRows ) { - nRowReload = gParse.nRows; - } else { - fRow = gParse.firstDataRow + gParse.nDataRows; - } - nRowOverlap = gParse.nRows - nRowReload; - - offset = nRowOverlap * nelem; - - /* NULLify any values falling out of bounds */ - - elem = gParse.nRows * nelem; - while( fRow+nRowReload>gParse.totalRows && nRowReload>0 ) { - if( this->type == BITSTR ) { - nelem = this->value.nelem; - elem--; - this->value.data.strptr[elem][ nelem ] = '\0'; - while( nelem-- ) this->value.data.strptr[elem][nelem] = '0'; - } else { - while( nelem-- ) - this->value.undef[--elem] = 1; - } - nelem = nRealElem; - nRowReload--; - } - - } else { - - nRowReload = 0; - nRowOverlap = gParse.nRows; - offset = 0; - - } - - if( nRowReload>0 ) { - switch( this->type ) { - case BITSTR: - case STRING: - status = (*gParse.loadData)( -col->operation, fRow, nRowReload, - this->value.data.strptr+offset, - this->value.undef+offset ); - break; - case BOOLEAN: - status = (*gParse.loadData)( -col->operation, fRow, nRowReload, - this->value.data.logptr+offset, - this->value.undef+offset ); - break; - case LONG: - status = (*gParse.loadData)( -col->operation, fRow, nRowReload, - this->value.data.lngptr+offset, - this->value.undef+offset ); - break; - case DOUBLE: - status = (*gParse.loadData)( -col->operation, fRow, nRowReload, - this->value.data.dblptr+offset, - this->value.undef+offset ); - break; - } - } - - /* Now copy over the overlapping region, if any */ - - if( nRowOverlap <= 0 ) return; - - if( rowOffset>0 ) - elem = nRowOverlap * nelem; - else - elem = gParse.nRows * nelem; - - offset = nelem * rowOffset; - while( nRowOverlap-- && !gParse.status ) { - while( nelem-- && !gParse.status ) { - elem--; - if( this->type != BITSTR ) - this->value.undef[elem] = col->value.undef[elem+offset]; - switch( this->type ) { - case BITSTR: - strcpy( this->value.data.strptr[elem ], - col->value.data.strptr[elem+offset] ); - break; - case STRING: - strcpy( this->value.data.strptr[elem ], - col->value.data.strptr[elem+offset] ); - break; - case BOOLEAN: - this->value.data.logptr[elem] = col->value.data.logptr[elem+offset]; - break; - case LONG: - this->value.data.lngptr[elem] = col->value.data.lngptr[elem+offset]; - break; - case DOUBLE: - this->value.data.dblptr[elem] = col->value.data.dblptr[elem+offset]; - break; - } - } - nelem = nRealElem; - } -} - -static void Do_BinOp_bit( Node *this ) -{ - Node *that1, *that2; - char *sptr1=NULL, *sptr2=NULL; - int const1, const2; - long rows; - - that1 = gParse.Nodes + this->SubNodes[0]; - that2 = gParse.Nodes + this->SubNodes[1]; - - const1 = ( that1->operation==CONST_OP ); - const2 = ( that2->operation==CONST_OP ); - sptr1 = ( const1 ? that1->value.data.str : NULL ); - sptr2 = ( const2 ? that2->value.data.str : NULL ); - - if( const1 && const2 ) { - switch( this->operation ) { - case NE: - this->value.data.log = !bitcmp( sptr1, sptr2 ); - break; - case EQ: - this->value.data.log = bitcmp( sptr1, sptr2 ); - break; - case GT: - case LT: - case LTE: - case GTE: - this->value.data.log = bitlgte( sptr1, this->operation, sptr2 ); - break; - case '|': - bitor( this->value.data.str, sptr1, sptr2 ); - break; - case '&': - bitand( this->value.data.str, sptr1, sptr2 ); - break; - case '+': - strcpy( this->value.data.str, sptr1 ); - strcat( this->value.data.str, sptr2 ); - break; - case ACCUM: - this->value.data.lng = 0; - while( *sptr1 ) { - if ( *sptr1 == '1' ) this->value.data.lng ++; - sptr1 ++; - } - break; - - } - this->operation = CONST_OP; - - } else { - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - rows = gParse.nRows; - switch( this->operation ) { - - /* BITSTR comparisons */ - - case NE: - case EQ: - case GT: - case LT: - case LTE: - case GTE: - while( rows-- ) { - if( !const1 ) - sptr1 = that1->value.data.strptr[rows]; - if( !const2 ) - sptr2 = that2->value.data.strptr[rows]; - switch( this->operation ) { - case NE: this->value.data.logptr[rows] = - !bitcmp( sptr1, sptr2 ); - break; - case EQ: this->value.data.logptr[rows] = - bitcmp( sptr1, sptr2 ); - break; - case GT: - case LT: - case LTE: - case GTE: this->value.data.logptr[rows] = - bitlgte( sptr1, this->operation, sptr2 ); - break; - } - this->value.undef[rows] = 0; - } - break; - - /* BITSTR AND/ORs ... no UNDEFS in or out */ - - case '|': - case '&': - case '+': - while( rows-- ) { - if( !const1 ) - sptr1 = that1->value.data.strptr[rows]; - if( !const2 ) - sptr2 = that2->value.data.strptr[rows]; - if( this->operation=='|' ) - bitor( this->value.data.strptr[rows], sptr1, sptr2 ); - else if( this->operation=='&' ) - bitand( this->value.data.strptr[rows], sptr1, sptr2 ); - else { - strcpy( this->value.data.strptr[rows], sptr1 ); - strcat( this->value.data.strptr[rows], sptr2 ); - } - } - break; - - /* Accumulate 1 bits */ - case ACCUM: - { - long i, previous, curr; - - previous = that2->value.data.lng; - - /* Cumulative sum of this chunk */ - for (i=0; ivalue.data.strptr[i]; - for (curr = 0; *sptr1; sptr1 ++) { - if ( *sptr1 == '1' ) curr ++; - } - previous += curr; - this->value.data.lngptr[i] = previous; - this->value.undef[i] = 0; - } - - /* Store final cumulant for next pass */ - that2->value.data.lng = previous; - } - } - } - } - - if( that1->operation>0 ) { - free( that1->value.data.strptr[0] ); - free( that1->value.data.strptr ); - } - if( that2->operation>0 ) { - free( that2->value.data.strptr[0] ); - free( that2->value.data.strptr ); - } -} - -static void Do_BinOp_str( Node *this ) -{ - Node *that1, *that2; - char *sptr1, *sptr2, null1=0, null2=0; - int const1, const2, val; - long rows; - - that1 = gParse.Nodes + this->SubNodes[0]; - that2 = gParse.Nodes + this->SubNodes[1]; - - const1 = ( that1->operation==CONST_OP ); - const2 = ( that2->operation==CONST_OP ); - sptr1 = ( const1 ? that1->value.data.str : NULL ); - sptr2 = ( const2 ? that2->value.data.str : NULL ); - - if( const1 && const2 ) { /* Result is a constant */ - switch( this->operation ) { - - /* Compare Strings */ - - case NE: - case EQ: - val = ( FSTRCMP( sptr1, sptr2 ) == 0 ); - this->value.data.log = ( this->operation==EQ ? val : !val ); - break; - case GT: - this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) > 0 ); - break; - case LT: - this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) < 0 ); - break; - case GTE: - this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) >= 0 ); - break; - case LTE: - this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) <= 0 ); - break; - - /* Concat Strings */ - - case '+': - strcpy( this->value.data.str, sptr1 ); - strcat( this->value.data.str, sptr2 ); - break; - } - this->operation = CONST_OP; - - } else { /* Not a constant */ - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - - rows = gParse.nRows; - switch( this->operation ) { - - /* Compare Strings */ - - case NE: - case EQ: - while( rows-- ) { - if( !const1 ) null1 = that1->value.undef[rows]; - if( !const2 ) null2 = that2->value.undef[rows]; - this->value.undef[rows] = (null1 || null2); - if( ! this->value.undef[rows] ) { - if( !const1 ) sptr1 = that1->value.data.strptr[rows]; - if( !const2 ) sptr2 = that2->value.data.strptr[rows]; - val = ( FSTRCMP( sptr1, sptr2 ) == 0 ); - this->value.data.logptr[rows] = - ( this->operation==EQ ? val : !val ); - } - } - break; - - case GT: - case LT: - while( rows-- ) { - if( !const1 ) null1 = that1->value.undef[rows]; - if( !const2 ) null2 = that2->value.undef[rows]; - this->value.undef[rows] = (null1 || null2); - if( ! this->value.undef[rows] ) { - if( !const1 ) sptr1 = that1->value.data.strptr[rows]; - if( !const2 ) sptr2 = that2->value.data.strptr[rows]; - val = ( FSTRCMP( sptr1, sptr2 ) ); - this->value.data.logptr[rows] = - ( this->operation==GT ? val>0 : val<0 ); - } - } - break; - - case GTE: - case LTE: - while( rows-- ) { - if( !const1 ) null1 = that1->value.undef[rows]; - if( !const2 ) null2 = that2->value.undef[rows]; - this->value.undef[rows] = (null1 || null2); - if( ! this->value.undef[rows] ) { - if( !const1 ) sptr1 = that1->value.data.strptr[rows]; - if( !const2 ) sptr2 = that2->value.data.strptr[rows]; - val = ( FSTRCMP( sptr1, sptr2 ) ); - this->value.data.logptr[rows] = - ( this->operation==GTE ? val>=0 : val<=0 ); - } - } - break; - - /* Concat Strings */ - - case '+': - while( rows-- ) { - if( !const1 ) null1 = that1->value.undef[rows]; - if( !const2 ) null2 = that2->value.undef[rows]; - this->value.undef[rows] = (null1 || null2); - if( ! this->value.undef[rows] ) { - if( !const1 ) sptr1 = that1->value.data.strptr[rows]; - if( !const2 ) sptr2 = that2->value.data.strptr[rows]; - strcpy( this->value.data.strptr[rows], sptr1 ); - strcat( this->value.data.strptr[rows], sptr2 ); - } - } - break; - } - } - } - - if( that1->operation>0 ) { - free( that1->value.data.strptr[0] ); - free( that1->value.data.strptr ); - } - if( that2->operation>0 ) { - free( that2->value.data.strptr[0] ); - free( that2->value.data.strptr ); - } -} - -static void Do_BinOp_log( Node *this ) -{ - Node *that1, *that2; - int vector1, vector2; - char val1=0, val2=0, null1=0, null2=0; - long rows, nelem, elem; - - that1 = gParse.Nodes + this->SubNodes[0]; - that2 = gParse.Nodes + this->SubNodes[1]; - - vector1 = ( that1->operation!=CONST_OP ); - if( vector1 ) - vector1 = that1->value.nelem; - else { - val1 = that1->value.data.log; - } - - vector2 = ( that2->operation!=CONST_OP ); - if( vector2 ) - vector2 = that2->value.nelem; - else { - val2 = that2->value.data.log; - } - - if( !vector1 && !vector2 ) { /* Result is a constant */ - switch( this->operation ) { - case OR: - this->value.data.log = (val1 || val2); - break; - case AND: - this->value.data.log = (val1 && val2); - break; - case EQ: - this->value.data.log = ( (val1 && val2) || (!val1 && !val2) ); - break; - case NE: - this->value.data.log = ( (val1 && !val2) || (!val1 && val2) ); - break; - case ACCUM: - this->value.data.lng = val1; - break; - } - this->operation=CONST_OP; - } else if (this->operation == ACCUM) { - long i, previous, curr; - rows = gParse.nRows; - nelem = this->value.nelem; - elem = this->value.nelem * rows; - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - previous = that2->value.data.lng; - - /* Cumulative sum of this chunk */ - for (i=0; ivalue.undef[i]) { - curr = that1->value.data.logptr[i]; - previous += curr; - } - this->value.data.lngptr[i] = previous; - this->value.undef[i] = 0; - } - - /* Store final cumulant for next pass */ - that2->value.data.lng = previous; - } - - } else { - rows = gParse.nRows; - nelem = this->value.nelem; - elem = this->value.nelem * rows; - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - - if (this->operation == ACCUM) { - long i, previous, curr; - - previous = that2->value.data.lng; - - /* Cumulative sum of this chunk */ - for (i=0; ivalue.undef[i]) { - curr = that1->value.data.logptr[i]; - previous += curr; - } - this->value.data.lngptr[i] = previous; - this->value.undef[i] = 0; - } - - /* Store final cumulant for next pass */ - that2->value.data.lng = previous; - } - - while( rows-- ) { - while( nelem-- ) { - elem--; - - if( vector1>1 ) { - val1 = that1->value.data.logptr[elem]; - null1 = that1->value.undef[elem]; - } else if( vector1 ) { - val1 = that1->value.data.logptr[rows]; - null1 = that1->value.undef[rows]; - } - - if( vector2>1 ) { - val2 = that2->value.data.logptr[elem]; - null2 = that2->value.undef[elem]; - } else if( vector2 ) { - val2 = that2->value.data.logptr[rows]; - null2 = that2->value.undef[rows]; - } - - this->value.undef[elem] = (null1 || null2); - switch( this->operation ) { - - case OR: - /* This is more complicated than others to suppress UNDEFs */ - /* in those cases where the other argument is DEF && TRUE */ - - if( !null1 && !null2 ) { - this->value.data.logptr[elem] = (val1 || val2); - } else if( (null1 && !null2 && val2) - || ( !null1 && null2 && val1 ) ) { - this->value.data.logptr[elem] = 1; - this->value.undef[elem] = 0; - } - break; - - case AND: - /* This is more complicated than others to suppress UNDEFs */ - /* in those cases where the other argument is DEF && FALSE */ - - if( !null1 && !null2 ) { - this->value.data.logptr[elem] = (val1 && val2); - } else if( (null1 && !null2 && !val2) - || ( !null1 && null2 && !val1 ) ) { - this->value.data.logptr[elem] = 0; - this->value.undef[elem] = 0; - } - break; - - case EQ: - this->value.data.logptr[elem] = - ( (val1 && val2) || (!val1 && !val2) ); - break; - - case NE: - this->value.data.logptr[elem] = - ( (val1 && !val2) || (!val1 && val2) ); - break; - } - } - nelem = this->value.nelem; - } - } - } - - if( that1->operation>0 ) { - free( that1->value.data.ptr ); - } - if( that2->operation>0 ) { - free( that2->value.data.ptr ); - } -} - -static void Do_BinOp_lng( Node *this ) -{ - Node *that1, *that2; - int vector1, vector2; - long val1=0, val2=0; - char null1=0, null2=0; - long rows, nelem, elem; - - that1 = gParse.Nodes + this->SubNodes[0]; - that2 = gParse.Nodes + this->SubNodes[1]; - - vector1 = ( that1->operation!=CONST_OP ); - if( vector1 ) - vector1 = that1->value.nelem; - else { - val1 = that1->value.data.lng; - } - - vector2 = ( that2->operation!=CONST_OP ); - if( vector2 ) - vector2 = that2->value.nelem; - else { - val2 = that2->value.data.lng; - } - - if( !vector1 && !vector2 ) { /* Result is a constant */ - - switch( this->operation ) { - case '~': /* Treat as == for LONGS */ - case EQ: this->value.data.log = (val1 == val2); break; - case NE: this->value.data.log = (val1 != val2); break; - case GT: this->value.data.log = (val1 > val2); break; - case LT: this->value.data.log = (val1 < val2); break; - case LTE: this->value.data.log = (val1 <= val2); break; - case GTE: this->value.data.log = (val1 >= val2); break; - - case '+': this->value.data.lng = (val1 + val2); break; - case '-': this->value.data.lng = (val1 - val2); break; - case '*': this->value.data.lng = (val1 * val2); break; - - case '%': - if( val2 ) this->value.data.lng = (val1 % val2); - else yyerror("Divide by Zero"); - break; - case '/': - if( val2 ) this->value.data.lng = (val1 / val2); - else yyerror("Divide by Zero"); - break; - case POWER: - this->value.data.lng = (long)pow((double)val1,(double)val2); - break; - case ACCUM: - this->value.data.lng = val1; - break; - case DIFF: - this->value.data.lng = 0; - break; - } - this->operation=CONST_OP; - - } else if ((this->operation == ACCUM) || (this->operation == DIFF)) { - long i, previous, curr; - long undef; - rows = gParse.nRows; - nelem = this->value.nelem; - elem = this->value.nelem * rows; - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - previous = that2->value.data.lng; - undef = (long) that2->value.undef; - - if (this->operation == ACCUM) { - /* Cumulative sum of this chunk */ - for (i=0; ivalue.undef[i]) { - curr = that1->value.data.lngptr[i]; - previous += curr; - } - this->value.data.lngptr[i] = previous; - this->value.undef[i] = 0; - } - } else { - /* Sequential difference for this chunk */ - for (i=0; ivalue.data.lngptr[i]; - if (that1->value.undef[i] || undef) { - /* Either this, or previous, value was undefined */ - this->value.data.lngptr[i] = 0; - this->value.undef[i] = 1; - } else { - /* Both defined, we are okay! */ - this->value.data.lngptr[i] = curr - previous; - this->value.undef[i] = 0; - } - - previous = curr; - undef = that1->value.undef[i]; - } - } - - /* Store final cumulant for next pass */ - that2->value.data.lng = previous; - that2->value.undef = (char *) undef; /* XXX evil, but no harm here */ - } - - } else { - - rows = gParse.nRows; - nelem = this->value.nelem; - elem = this->value.nelem * rows; - - Allocate_Ptrs( this ); - - while( rows-- && !gParse.status ) { - while( nelem-- && !gParse.status ) { - elem--; - - if( vector1>1 ) { - val1 = that1->value.data.lngptr[elem]; - null1 = that1->value.undef[elem]; - } else if( vector1 ) { - val1 = that1->value.data.lngptr[rows]; - null1 = that1->value.undef[rows]; - } - - if( vector2>1 ) { - val2 = that2->value.data.lngptr[elem]; - null2 = that2->value.undef[elem]; - } else if( vector2 ) { - val2 = that2->value.data.lngptr[rows]; - null2 = that2->value.undef[rows]; - } - - this->value.undef[elem] = (null1 || null2); - switch( this->operation ) { - case '~': /* Treat as == for LONGS */ - case EQ: this->value.data.logptr[elem] = (val1 == val2); break; - case NE: this->value.data.logptr[elem] = (val1 != val2); break; - case GT: this->value.data.logptr[elem] = (val1 > val2); break; - case LT: this->value.data.logptr[elem] = (val1 < val2); break; - case LTE: this->value.data.logptr[elem] = (val1 <= val2); break; - case GTE: this->value.data.logptr[elem] = (val1 >= val2); break; - - case '+': this->value.data.lngptr[elem] = (val1 + val2); break; - case '-': this->value.data.lngptr[elem] = (val1 - val2); break; - case '*': this->value.data.lngptr[elem] = (val1 * val2); break; - - case '%': - if( val2 ) this->value.data.lngptr[elem] = (val1 % val2); - else { - this->value.data.lngptr[elem] = 0; - this->value.undef[elem] = 1; - } - break; - case '/': - if( val2 ) this->value.data.lngptr[elem] = (val1 / val2); - else { - this->value.data.lngptr[elem] = 0; - this->value.undef[elem] = 1; - } - break; - case POWER: - this->value.data.lngptr[elem] = (long)pow((double)val1,(double)val2); - break; - } - } - nelem = this->value.nelem; - } - } - - if( that1->operation>0 ) { - free( that1->value.data.ptr ); - } - if( that2->operation>0 ) { - free( that2->value.data.ptr ); - } -} - -static void Do_BinOp_dbl( Node *this ) -{ - Node *that1, *that2; - int vector1, vector2; - double val1=0.0, val2=0.0; - char null1=0, null2=0; - long rows, nelem, elem; - - that1 = gParse.Nodes + this->SubNodes[0]; - that2 = gParse.Nodes + this->SubNodes[1]; - - vector1 = ( that1->operation!=CONST_OP ); - if( vector1 ) - vector1 = that1->value.nelem; - else { - val1 = that1->value.data.dbl; - } - - vector2 = ( that2->operation!=CONST_OP ); - if( vector2 ) - vector2 = that2->value.nelem; - else { - val2 = that2->value.data.dbl; - } - - if( !vector1 && !vector2 ) { /* Result is a constant */ - - switch( this->operation ) { - case '~': this->value.data.log = ( fabs(val1-val2) < APPROX ); break; - case EQ: this->value.data.log = (val1 == val2); break; - case NE: this->value.data.log = (val1 != val2); break; - case GT: this->value.data.log = (val1 > val2); break; - case LT: this->value.data.log = (val1 < val2); break; - case LTE: this->value.data.log = (val1 <= val2); break; - case GTE: this->value.data.log = (val1 >= val2); break; - - case '+': this->value.data.dbl = (val1 + val2); break; - case '-': this->value.data.dbl = (val1 - val2); break; - case '*': this->value.data.dbl = (val1 * val2); break; - - case '%': - if( val2 ) this->value.data.dbl = val1 - val2*((int)(val1/val2)); - else yyerror("Divide by Zero"); - break; - case '/': - if( val2 ) this->value.data.dbl = (val1 / val2); - else yyerror("Divide by Zero"); - break; - case POWER: - this->value.data.dbl = (double)pow(val1,val2); - break; - case ACCUM: - this->value.data.dbl = val1; - break; - case DIFF: - this->value.data.dbl = 0; - break; - } - this->operation=CONST_OP; - - } else if ((this->operation == ACCUM) || (this->operation == DIFF)) { - long i; - long undef; - double previous, curr; - rows = gParse.nRows; - nelem = this->value.nelem; - elem = this->value.nelem * rows; - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - previous = that2->value.data.dbl; - undef = (long) that2->value.undef; - - if (this->operation == ACCUM) { - /* Cumulative sum of this chunk */ - for (i=0; ivalue.undef[i]) { - curr = that1->value.data.dblptr[i]; - previous += curr; - } - this->value.data.dblptr[i] = previous; - this->value.undef[i] = 0; - } - } else { - /* Sequential difference for this chunk */ - for (i=0; ivalue.data.dblptr[i]; - if (that1->value.undef[i] || undef) { - /* Either this, or previous, value was undefined */ - this->value.data.dblptr[i] = 0; - this->value.undef[i] = 1; - } else { - /* Both defined, we are okay! */ - this->value.data.dblptr[i] = curr - previous; - this->value.undef[i] = 0; - } - - previous = curr; - undef = that1->value.undef[i]; - } - } - - /* Store final cumulant for next pass */ - that2->value.data.dbl = previous; - that2->value.undef = (char *) undef; /* XXX evil, but no harm here */ - } - - } else { - - rows = gParse.nRows; - nelem = this->value.nelem; - elem = this->value.nelem * rows; - - Allocate_Ptrs( this ); - - while( rows-- && !gParse.status ) { - while( nelem-- && !gParse.status ) { - elem--; - - if( vector1>1 ) { - val1 = that1->value.data.dblptr[elem]; - null1 = that1->value.undef[elem]; - } else if( vector1 ) { - val1 = that1->value.data.dblptr[rows]; - null1 = that1->value.undef[rows]; - } - - if( vector2>1 ) { - val2 = that2->value.data.dblptr[elem]; - null2 = that2->value.undef[elem]; - } else if( vector2 ) { - val2 = that2->value.data.dblptr[rows]; - null2 = that2->value.undef[rows]; - } - - this->value.undef[elem] = (null1 || null2); - switch( this->operation ) { - case '~': this->value.data.logptr[elem] = - ( fabs(val1-val2) < APPROX ); break; - case EQ: this->value.data.logptr[elem] = (val1 == val2); break; - case NE: this->value.data.logptr[elem] = (val1 != val2); break; - case GT: this->value.data.logptr[elem] = (val1 > val2); break; - case LT: this->value.data.logptr[elem] = (val1 < val2); break; - case LTE: this->value.data.logptr[elem] = (val1 <= val2); break; - case GTE: this->value.data.logptr[elem] = (val1 >= val2); break; - - case '+': this->value.data.dblptr[elem] = (val1 + val2); break; - case '-': this->value.data.dblptr[elem] = (val1 - val2); break; - case '*': this->value.data.dblptr[elem] = (val1 * val2); break; - - case '%': - if( val2 ) this->value.data.dblptr[elem] = - val1 - val2*((int)(val1/val2)); - else { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } - break; - case '/': - if( val2 ) this->value.data.dblptr[elem] = (val1 / val2); - else { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } - break; - case POWER: - this->value.data.dblptr[elem] = (double)pow(val1,val2); - break; - } - } - nelem = this->value.nelem; - } - } - - if( that1->operation>0 ) { - free( that1->value.data.ptr ); - } - if( that2->operation>0 ) { - free( that2->value.data.ptr ); - } -} - -/* - * This Quickselect routine is based on the algorithm described in - * "Numerical recipes in C", Second Edition, - * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5 - * This code by Nicolas Devillard - 1998. Public domain. - * http://ndevilla.free.fr/median/median/src/quickselect.c - */ - -#define ELEM_SWAP(a,b) { register long t=(a);(a)=(b);(b)=t; } - -/* - * qselect_median_lng - select the median value of a long array - * - * This routine selects the median value of the long integer array - * arr[]. If there are an even number of elements, the "lower median" - * is selected. - * - * The array arr[] is scrambled, so users must operate on a scratch - * array if they wish the values to be preserved. - * - * long arr[] - array of values - * int n - number of elements in arr - * - * RETURNS: the lower median value of arr[] - * - */ -long qselect_median_lng(long arr[], int n) -{ - int low, high ; - int median; - int middle, ll, hh; - - low = 0 ; high = n-1 ; median = (low + high) / 2; - for (;;) { - - if (high <= low) { /* One element only */ - return arr[median]; - } - - if (high == low + 1) { /* Two elements only */ - if (arr[low] > arr[high]) - ELEM_SWAP(arr[low], arr[high]) ; - return arr[median]; - } - - /* Find median of low, middle and high items; swap into position low */ - middle = (low + high) / 2; - if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; - if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; - if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; - - /* Swap low item (now in position middle) into position (low+1) */ - ELEM_SWAP(arr[middle], arr[low+1]) ; - - /* Nibble from each end towards middle, swapping items when stuck */ - ll = low + 1; - hh = high; - for (;;) { - do ll++; while (arr[low] > arr[ll]) ; - do hh--; while (arr[hh] > arr[low]) ; - - if (hh < ll) - break; - - ELEM_SWAP(arr[ll], arr[hh]) ; - } - - /* Swap middle item (in position low) back into correct position */ - ELEM_SWAP(arr[low], arr[hh]) ; - - /* Re-set active partition */ - if (hh <= median) - low = ll; - if (hh >= median) - high = hh - 1; - } -} - -#undef ELEM_SWAP - -#define ELEM_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; } - -/* - * qselect_median_dbl - select the median value of a double array - * - * This routine selects the median value of the double array - * arr[]. If there are an even number of elements, the "lower median" - * is selected. - * - * The array arr[] is scrambled, so users must operate on a scratch - * array if they wish the values to be preserved. - * - * double arr[] - array of values - * int n - number of elements in arr - * - * RETURNS: the lower median value of arr[] - * - */ -double qselect_median_dbl(double arr[], int n) -{ - int low, high ; - int median; - int middle, ll, hh; - - low = 0 ; high = n-1 ; median = (low + high) / 2; - for (;;) { - if (high <= low) { /* One element only */ - return arr[median] ; - } - - if (high == low + 1) { /* Two elements only */ - if (arr[low] > arr[high]) - ELEM_SWAP(arr[low], arr[high]) ; - return arr[median] ; - } - - /* Find median of low, middle and high items; swap into position low */ - middle = (low + high) / 2; - if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; - if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; - if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; - - /* Swap low item (now in position middle) into position (low+1) */ - ELEM_SWAP(arr[middle], arr[low+1]) ; - - /* Nibble from each end towards middle, swapping items when stuck */ - ll = low + 1; - hh = high; - for (;;) { - do ll++; while (arr[low] > arr[ll]) ; - do hh--; while (arr[hh] > arr[low]) ; - - if (hh < ll) - break; - - ELEM_SWAP(arr[ll], arr[hh]) ; - } - - /* Swap middle item (in position low) back into correct position */ - ELEM_SWAP(arr[low], arr[hh]) ; - - /* Re-set active partition */ - if (hh <= median) - low = ll; - if (hh >= median) - high = hh - 1; - } -} - -#undef ELEM_SWAP - -/* - * angsep_calc - compute angular separation between celestial coordinates - * - * This routine computes the angular separation between to coordinates - * on the celestial sphere (i.e. RA and Dec). Note that all units are - * in DEGREES, unlike the other trig functions in the calculator. - * - * double ra1, dec1 - RA and Dec of the first position in degrees - * double ra2, dec2 - RA and Dec of the second position in degrees - * - * RETURNS: (double) angular separation in degrees - * - */ -double angsep_calc(double ra1, double dec1, double ra2, double dec2) -{ -/* double cd; */ - static double deg = 0; - double a, sdec, sra; - - if (deg == 0) deg = ((double)4)*atan((double)1)/((double)180); - /* deg = 1.0; **** UNCOMMENT IF YOU WANT RADIANS */ - - /* The algorithm is the law of Haversines. This algorithm is - stable even when the points are close together. The normal - Law of Cosines fails for angles around 0.1 arcsec. */ - - sra = sin( (ra2 - ra1)*deg / 2 ); - sdec = sin( (dec2 - dec1)*deg / 2); - a = sdec*sdec + cos(dec1*deg)*cos(dec2*deg)*sra*sra; - - /* Sanity checking to avoid a range error in the sqrt()'s below */ - if (a < 0) { a = 0; } - if (a > 1) { a = 1; } - - return 2.0*atan2(sqrt(a), sqrt(1.0 - a)) / deg; -} - -static void Do_Func( Node *this ) -{ - Node *theParams[MAXSUBS]; - int vector[MAXSUBS], allConst; - lval pVals[MAXSUBS]; - char pNull[MAXSUBS]; - long ival; - double dval; - int i, valInit; - long row, elem, nelem; - - i = this->nSubNodes; - allConst = 1; - while( i-- ) { - theParams[i] = gParse.Nodes + this->SubNodes[i]; - vector[i] = ( theParams[i]->operation!=CONST_OP ); - if( vector[i] ) { - allConst = 0; - vector[i] = theParams[i]->value.nelem; - } else { - if( theParams[i]->type==DOUBLE ) { - pVals[i].data.dbl = theParams[i]->value.data.dbl; - } else if( theParams[i]->type==LONG ) { - pVals[i].data.lng = theParams[i]->value.data.lng; - } else if( theParams[i]->type==BOOLEAN ) { - pVals[i].data.log = theParams[i]->value.data.log; - } else - strcpy(pVals[i].data.str, theParams[i]->value.data.str); - pNull[i] = 0; - } - } - - if( this->nSubNodes==0 ) allConst = 0; /* These do produce scalars */ - /* Random numbers are *never* constant !! */ - if( this->operation == poirnd_fct ) allConst = 0; - if( this->operation == gasrnd_fct ) allConst = 0; - if( this->operation == rnd_fct ) allConst = 0; - - if( allConst ) { - - switch( this->operation ) { - - /* Non-Trig single-argument functions */ - - case sum_fct: - if( theParams[0]->type==BOOLEAN ) - this->value.data.lng = ( pVals[0].data.log ? 1 : 0 ); - else if( theParams[0]->type==LONG ) - this->value.data.lng = pVals[0].data.lng; - else if( theParams[0]->type==DOUBLE ) - this->value.data.dbl = pVals[0].data.dbl; - else if( theParams[0]->type==BITSTR ) - strcpy(this->value.data.str, pVals[0].data.str); - break; - case average_fct: - if( theParams[0]->type==LONG ) - this->value.data.dbl = pVals[0].data.lng; - else if( theParams[0]->type==DOUBLE ) - this->value.data.dbl = pVals[0].data.dbl; - break; - case stddev_fct: - this->value.data.dbl = 0; /* Standard deviation of a constant = 0 */ - break; - case median_fct: - if( theParams[0]->type==BOOLEAN ) - this->value.data.lng = ( pVals[0].data.log ? 1 : 0 ); - else if( theParams[0]->type==LONG ) - this->value.data.lng = pVals[0].data.lng; - else - this->value.data.dbl = pVals[0].data.dbl; - break; - - case poirnd_fct: - if( theParams[0]->type==DOUBLE ) - this->value.data.lng = simplerng_getpoisson(pVals[0].data.dbl); - else - this->value.data.lng = simplerng_getpoisson(pVals[0].data.lng); - break; - - case abs_fct: - if( theParams[0]->type==DOUBLE ) { - dval = pVals[0].data.dbl; - this->value.data.dbl = (dval>0.0 ? dval : -dval); - } else { - ival = pVals[0].data.lng; - this->value.data.lng = (ival> 0 ? ival : -ival); - } - break; - - /* Special Null-Handling Functions */ - - case nonnull_fct: - this->value.data.lng = 1; /* Constants are always 1-element and defined */ - break; - case isnull_fct: /* Constants are always defined */ - this->value.data.log = 0; - break; - case defnull_fct: - if( this->type==BOOLEAN ) - this->value.data.log = pVals[0].data.log; - else if( this->type==LONG ) - this->value.data.lng = pVals[0].data.lng; - else if( this->type==DOUBLE ) - this->value.data.dbl = pVals[0].data.dbl; - else if( this->type==STRING ) - strcpy(this->value.data.str,pVals[0].data.str); - break; - - /* Math functions with 1 double argument */ - - case sin_fct: - this->value.data.dbl = sin( pVals[0].data.dbl ); - break; - case cos_fct: - this->value.data.dbl = cos( pVals[0].data.dbl ); - break; - case tan_fct: - this->value.data.dbl = tan( pVals[0].data.dbl ); - break; - case asin_fct: - dval = pVals[0].data.dbl; - if( dval<-1.0 || dval>1.0 ) - yyerror("Out of range argument to arcsin"); - else - this->value.data.dbl = asin( dval ); - break; - case acos_fct: - dval = pVals[0].data.dbl; - if( dval<-1.0 || dval>1.0 ) - yyerror("Out of range argument to arccos"); - else - this->value.data.dbl = acos( dval ); - break; - case atan_fct: - this->value.data.dbl = atan( pVals[0].data.dbl ); - break; - case sinh_fct: - this->value.data.dbl = sinh( pVals[0].data.dbl ); - break; - case cosh_fct: - this->value.data.dbl = cosh( pVals[0].data.dbl ); - break; - case tanh_fct: - this->value.data.dbl = tanh( pVals[0].data.dbl ); - break; - case exp_fct: - this->value.data.dbl = exp( pVals[0].data.dbl ); - break; - case log_fct: - dval = pVals[0].data.dbl; - if( dval<=0.0 ) - yyerror("Out of range argument to log"); - else - this->value.data.dbl = log( dval ); - break; - case log10_fct: - dval = pVals[0].data.dbl; - if( dval<=0.0 ) - yyerror("Out of range argument to log10"); - else - this->value.data.dbl = log10( dval ); - break; - case sqrt_fct: - dval = pVals[0].data.dbl; - if( dval<0.0 ) - yyerror("Out of range argument to sqrt"); - else - this->value.data.dbl = sqrt( dval ); - break; - case ceil_fct: - this->value.data.dbl = ceil( pVals[0].data.dbl ); - break; - case floor_fct: - this->value.data.dbl = floor( pVals[0].data.dbl ); - break; - case round_fct: - this->value.data.dbl = floor( pVals[0].data.dbl + 0.5 ); - break; - - /* Two-argument Trig Functions */ - - case atan2_fct: - this->value.data.dbl = - atan2( pVals[0].data.dbl, pVals[1].data.dbl ); - break; - - /* Four-argument ANGSEP function */ - case angsep_fct: - this->value.data.dbl = - angsep_calc(pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl); - - /* Min/Max functions taking 1 or 2 arguments */ - - case min1_fct: - /* No constant vectors! */ - if( this->type == DOUBLE ) - this->value.data.dbl = pVals[0].data.dbl; - else if( this->type == LONG ) - this->value.data.lng = pVals[0].data.lng; - else if( this->type == BITSTR ) - strcpy(this->value.data.str, pVals[0].data.str); - break; - case min2_fct: - if( this->type == DOUBLE ) - this->value.data.dbl = - minvalue( pVals[0].data.dbl, pVals[1].data.dbl ); - else if( this->type == LONG ) - this->value.data.lng = - minvalue( pVals[0].data.lng, pVals[1].data.lng ); - break; - case max1_fct: - /* No constant vectors! */ - if( this->type == DOUBLE ) - this->value.data.dbl = pVals[0].data.dbl; - else if( this->type == LONG ) - this->value.data.lng = pVals[0].data.lng; - else if( this->type == BITSTR ) - strcpy(this->value.data.str, pVals[0].data.str); - break; - case max2_fct: - if( this->type == DOUBLE ) - this->value.data.dbl = - maxvalue( pVals[0].data.dbl, pVals[1].data.dbl ); - else if( this->type == LONG ) - this->value.data.lng = - maxvalue( pVals[0].data.lng, pVals[1].data.lng ); - break; - - /* Boolean SAO region Functions... scalar or vector dbls */ - - case near_fct: - this->value.data.log = bnear( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl ); - break; - case circle_fct: - this->value.data.log = circle( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl, - pVals[4].data.dbl ); - break; - case box_fct: - this->value.data.log = saobox( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl, - pVals[4].data.dbl, pVals[5].data.dbl, - pVals[6].data.dbl ); - break; - case elps_fct: - this->value.data.log = - ellipse( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl, - pVals[4].data.dbl, pVals[5].data.dbl, - pVals[6].data.dbl ); - break; - - /* C Conditional expression: bool ? expr : expr */ - - case ifthenelse_fct: - switch( this->type ) { - case BOOLEAN: - this->value.data.log = ( pVals[2].data.log ? - pVals[0].data.log : pVals[1].data.log ); - break; - case LONG: - this->value.data.lng = ( pVals[2].data.log ? - pVals[0].data.lng : pVals[1].data.lng ); - break; - case DOUBLE: - this->value.data.dbl = ( pVals[2].data.log ? - pVals[0].data.dbl : pVals[1].data.dbl ); - break; - case STRING: - strcpy(this->value.data.str, ( pVals[2].data.log ? - pVals[0].data.str : - pVals[1].data.str ) ); - break; - } - break; - - /* String functions */ - case strmid_fct: - cstrmid(this->value.data.str, this->value.nelem, - pVals[0].data.str, pVals[0].nelem, - pVals[1].data.lng); - break; - case strpos_fct: - { - char *res = strstr(pVals[0].data.str, pVals[1].data.str); - if (res == NULL) { - this->value.data.lng = 0; - } else { - this->value.data.lng = (res - pVals[0].data.str) + 1; - } - break; - } - - } - this->operation = CONST_OP; - - } else { - - Allocate_Ptrs( this ); - - row = gParse.nRows; - elem = row * this->value.nelem; - - if( !gParse.status ) { - switch( this->operation ) { - - /* Special functions with no arguments */ - - case row_fct: - while( row-- ) { - this->value.data.lngptr[row] = gParse.firstRow + row; - this->value.undef[row] = 0; - } - break; - case null_fct: - if( this->type==LONG ) { - while( row-- ) { - this->value.data.lngptr[row] = 0; - this->value.undef[row] = 1; - } - } else if( this->type==STRING ) { - while( row-- ) { - this->value.data.strptr[row][0] = '\0'; - this->value.undef[row] = 1; - } - } - break; - case rnd_fct: - while( elem-- ) { - this->value.data.dblptr[elem] = simplerng_getuniform(); - this->value.undef[elem] = 0; - } - break; - - case gasrnd_fct: - while( elem-- ) { - this->value.data.dblptr[elem] = simplerng_getnorm(); - this->value.undef[elem] = 0; - } - break; - - case poirnd_fct: - if( theParams[0]->type==DOUBLE ) { - if (theParams[0]->operation == CONST_OP) { - while( elem-- ) { - this->value.undef[elem] = (pVals[0].data.dbl < 0); - if (! this->value.undef[elem]) { - this->value.data.lngptr[elem] = simplerng_getpoisson(pVals[0].data.dbl); - } - } - } else { - while( elem-- ) { - this->value.undef[elem] = theParams[0]->value.undef[elem]; - if (theParams[0]->value.data.dblptr[elem] < 0) - this->value.undef[elem] = 1; - if (! this->value.undef[elem]) { - this->value.data.lngptr[elem] = - simplerng_getpoisson(theParams[0]->value.data.dblptr[elem]); - } - } /* while */ - } /* ! CONST_OP */ - } else { - /* LONG */ - if (theParams[0]->operation == CONST_OP) { - while( elem-- ) { - this->value.undef[elem] = (pVals[0].data.lng < 0); - if (! this->value.undef[elem]) { - this->value.data.lngptr[elem] = simplerng_getpoisson(pVals[0].data.lng); - } - } - } else { - while( elem-- ) { - this->value.undef[elem] = theParams[0]->value.undef[elem]; - if (theParams[0]->value.data.lngptr[elem] < 0) - this->value.undef[elem] = 1; - if (! this->value.undef[elem]) { - this->value.data.lngptr[elem] = - simplerng_getpoisson(theParams[0]->value.data.lngptr[elem]); - } - } /* while */ - } /* ! CONST_OP */ - } /* END LONG */ - break; - - - /* Non-Trig single-argument functions */ - - case sum_fct: - elem = row * theParams[0]->value.nelem; - if( theParams[0]->type==BOOLEAN ) { - while( row-- ) { - this->value.data.lngptr[row] = 0; - /* Default is UNDEF until a defined value is found */ - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( ! theParams[0]->value.undef[elem] ) { - this->value.data.lngptr[row] += - ( theParams[0]->value.data.logptr[elem] ? 1 : 0 ); - this->value.undef[row] = 0; - } - } - } - } else if( theParams[0]->type==LONG ) { - while( row-- ) { - this->value.data.lngptr[row] = 0; - /* Default is UNDEF until a defined value is found */ - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( ! theParams[0]->value.undef[elem] ) { - this->value.data.lngptr[row] += - theParams[0]->value.data.lngptr[elem]; - this->value.undef[row] = 0; - } - } - } - } else if( theParams[0]->type==DOUBLE ){ - while( row-- ) { - this->value.data.dblptr[row] = 0.0; - /* Default is UNDEF until a defined value is found */ - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( ! theParams[0]->value.undef[elem] ) { - this->value.data.dblptr[row] += - theParams[0]->value.data.dblptr[elem]; - this->value.undef[row] = 0; - } - } - } - } else { /* BITSTR */ - nelem = theParams[0]->value.nelem; - while( row-- ) { - char *sptr1 = theParams[0]->value.data.strptr[row]; - this->value.data.lngptr[row] = 0; - this->value.undef[row] = 0; - while (*sptr1) { - if (*sptr1 == '1') this->value.data.lngptr[row] ++; - sptr1++; - } - } - } - break; - - case average_fct: - elem = row * theParams[0]->value.nelem; - if( theParams[0]->type==LONG ) { - while( row-- ) { - int count = 0; - this->value.data.dblptr[row] = 0; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if (theParams[0]->value.undef[elem] == 0) { - this->value.data.dblptr[row] += - theParams[0]->value.data.lngptr[elem]; - count ++; - } - } - if (count == 0) { - this->value.undef[row] = 1; - } else { - this->value.undef[row] = 0; - this->value.data.dblptr[row] /= count; - } - } - } else if( theParams[0]->type==DOUBLE ){ - while( row-- ) { - int count = 0; - this->value.data.dblptr[row] = 0; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if (theParams[0]->value.undef[elem] == 0) { - this->value.data.dblptr[row] += - theParams[0]->value.data.dblptr[elem]; - count ++; - } - } - if (count == 0) { - this->value.undef[row] = 1; - } else { - this->value.undef[row] = 0; - this->value.data.dblptr[row] /= count; - } - } - } - break; - case stddev_fct: - elem = row * theParams[0]->value.nelem; - if( theParams[0]->type==LONG ) { - - /* Compute the mean value */ - while( row-- ) { - int count = 0; - double sum = 0, sum2 = 0; - - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if (theParams[0]->value.undef[elem] == 0) { - sum += theParams[0]->value.data.lngptr[elem]; - count ++; - } - } - if (count > 1) { - sum /= count; - - /* Compute the sum of squared deviations */ - nelem = theParams[0]->value.nelem; - elem += nelem; /* Reset elem for second pass */ - while( nelem-- ) { - elem--; - if (theParams[0]->value.undef[elem] == 0) { - double dx = (theParams[0]->value.data.lngptr[elem] - sum); - sum2 += (dx*dx); - } - } - - sum2 /= (double)count-1; - - this->value.undef[row] = 0; - this->value.data.dblptr[row] = sqrt(sum2); - } else { - this->value.undef[row] = 0; /* STDDEV => 0 */ - this->value.data.dblptr[row] = 0; - } - } - } else if( theParams[0]->type==DOUBLE ){ - - /* Compute the mean value */ - while( row-- ) { - int count = 0; - double sum = 0, sum2 = 0; - - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if (theParams[0]->value.undef[elem] == 0) { - sum += theParams[0]->value.data.dblptr[elem]; - count ++; - } - } - if (count > 1) { - sum /= count; - - /* Compute the sum of squared deviations */ - nelem = theParams[0]->value.nelem; - elem += nelem; /* Reset elem for second pass */ - while( nelem-- ) { - elem--; - if (theParams[0]->value.undef[elem] == 0) { - double dx = (theParams[0]->value.data.dblptr[elem] - sum); - sum2 += (dx*dx); - } - } - - sum2 /= (double)count-1; - - this->value.undef[row] = 0; - this->value.data.dblptr[row] = sqrt(sum2); - } else { - this->value.undef[row] = 0; /* STDDEV => 0 */ - this->value.data.dblptr[row] = 0; - } - } - } - break; - - case median_fct: - elem = row * theParams[0]->value.nelem; - nelem = theParams[0]->value.nelem; - if( theParams[0]->type==LONG ) { - long *dptr = theParams[0]->value.data.lngptr; - char *uptr = theParams[0]->value.undef; - long *mptr = (long *) malloc(sizeof(long)*nelem); - int irow; - - /* Allocate temporary storage for this row, since the - quickselect function will scramble the contents */ - if (mptr == 0) { - yyerror("Could not allocate temporary memory in median function"); - free( this->value.data.ptr ); - break; - } - - for (irow=0; irow 0) { - this->value.undef[irow] = 0; - this->value.data.lngptr[irow] = qselect_median_lng(mptr, nelem1); - } else { - this->value.undef[irow] = 1; - this->value.data.lngptr[irow] = 0; - } - - } - - free(mptr); - } else { - double *dptr = theParams[0]->value.data.dblptr; - char *uptr = theParams[0]->value.undef; - double *mptr = (double *) malloc(sizeof(double)*nelem); - int irow; - - /* Allocate temporary storage for this row, since the - quickselect function will scramble the contents */ - if (mptr == 0) { - yyerror("Could not allocate temporary memory in median function"); - free( this->value.data.ptr ); - break; - } - - for (irow=0; irow 0) { - this->value.undef[irow] = 0; - this->value.data.dblptr[irow] = qselect_median_dbl(mptr, nelem1); - } else { - this->value.undef[irow] = 1; - this->value.data.dblptr[irow] = 0; - } - - } - free(mptr); - } - break; - case abs_fct: - if( theParams[0]->type==DOUBLE ) - while( elem-- ) { - dval = theParams[0]->value.data.dblptr[elem]; - this->value.data.dblptr[elem] = (dval>0.0 ? dval : -dval); - this->value.undef[elem] = theParams[0]->value.undef[elem]; - } - else - while( elem-- ) { - ival = theParams[0]->value.data.lngptr[elem]; - this->value.data.lngptr[elem] = (ival> 0 ? ival : -ival); - this->value.undef[elem] = theParams[0]->value.undef[elem]; - } - break; - - /* Special Null-Handling Functions */ - - case nonnull_fct: - nelem = theParams[0]->value.nelem; - if ( theParams[0]->type==STRING ) nelem = 1; - elem = row * nelem; - while( row-- ) { - int nelem1 = nelem; - - this->value.undef[row] = 0; /* Initialize to 0 (defined) */ - this->value.data.lngptr[row] = 0; - while( nelem1-- ) { - elem --; - if ( theParams[0]->value.undef[elem] == 0 ) this->value.data.lngptr[row] ++; - } - } - break; - case isnull_fct: - if( theParams[0]->type==STRING ) elem = row; - while( elem-- ) { - this->value.data.logptr[elem] = theParams[0]->value.undef[elem]; - this->value.undef[elem] = 0; - } - break; - case defnull_fct: - switch( this->type ) { - case BOOLEAN: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pNull[i] = theParams[i]->value.undef[elem]; - pVals[i].data.log = - theParams[i]->value.data.logptr[elem]; - } else if( vector[i] ) { - pNull[i] = theParams[i]->value.undef[row]; - pVals[i].data.log = - theParams[i]->value.data.logptr[row]; - } - if( pNull[0] ) { - this->value.undef[elem] = pNull[1]; - this->value.data.logptr[elem] = pVals[1].data.log; - } else { - this->value.undef[elem] = 0; - this->value.data.logptr[elem] = pVals[0].data.log; - } - } - } - break; - case LONG: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pNull[i] = theParams[i]->value.undef[elem]; - pVals[i].data.lng = - theParams[i]->value.data.lngptr[elem]; - } else if( vector[i] ) { - pNull[i] = theParams[i]->value.undef[row]; - pVals[i].data.lng = - theParams[i]->value.data.lngptr[row]; - } - if( pNull[0] ) { - this->value.undef[elem] = pNull[1]; - this->value.data.lngptr[elem] = pVals[1].data.lng; - } else { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = pVals[0].data.lng; - } - } - } - break; - case DOUBLE: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pNull[i] = theParams[i]->value.undef[elem]; - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - } else if( vector[i] ) { - pNull[i] = theParams[i]->value.undef[row]; - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - } - if( pNull[0] ) { - this->value.undef[elem] = pNull[1]; - this->value.data.dblptr[elem] = pVals[1].data.dbl; - } else { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = pVals[0].data.dbl; - } - } - } - break; - case STRING: - while( row-- ) { - i=2; while( i-- ) - if( vector[i] ) { - pNull[i] = theParams[i]->value.undef[row]; - strcpy(pVals[i].data.str, - theParams[i]->value.data.strptr[row]); - } - if( pNull[0] ) { - this->value.undef[row] = pNull[1]; - strcpy(this->value.data.strptr[row],pVals[1].data.str); - } else { - this->value.undef[elem] = 0; - strcpy(this->value.data.strptr[row],pVals[0].data.str); - } - } - } - break; - - /* Math functions with 1 double argument */ - - case sin_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - sin( theParams[0]->value.data.dblptr[elem] ); - } - break; - case cos_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - cos( theParams[0]->value.data.dblptr[elem] ); - } - break; - case tan_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - tan( theParams[0]->value.data.dblptr[elem] ); - } - break; - case asin_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - if( dval<-1.0 || dval>1.0 ) { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } else - this->value.data.dblptr[elem] = asin( dval ); - } - break; - case acos_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - if( dval<-1.0 || dval>1.0 ) { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } else - this->value.data.dblptr[elem] = acos( dval ); - } - break; - case atan_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - this->value.data.dblptr[elem] = atan( dval ); - } - break; - case sinh_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - sinh( theParams[0]->value.data.dblptr[elem] ); - } - break; - case cosh_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - cosh( theParams[0]->value.data.dblptr[elem] ); - } - break; - case tanh_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - tanh( theParams[0]->value.data.dblptr[elem] ); - } - break; - case exp_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - this->value.data.dblptr[elem] = exp( dval ); - } - break; - case log_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - if( dval<=0.0 ) { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } else - this->value.data.dblptr[elem] = log( dval ); - } - break; - case log10_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - if( dval<=0.0 ) { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } else - this->value.data.dblptr[elem] = log10( dval ); - } - break; - case sqrt_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - if( dval<0.0 ) { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } else - this->value.data.dblptr[elem] = sqrt( dval ); - } - break; - case ceil_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - ceil( theParams[0]->value.data.dblptr[elem] ); - } - break; - case floor_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - floor( theParams[0]->value.data.dblptr[elem] ); - } - break; - case round_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - floor( theParams[0]->value.data.dblptr[elem] + 0.5); - } - break; - - /* Two-argument Trig Functions */ - - case atan2_fct: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = (pNull[0] || pNull[1]) ) ) - this->value.data.dblptr[elem] = - atan2( pVals[0].data.dbl, pVals[1].data.dbl ); - } - } - break; - - /* Four-argument ANGSEP Function */ - - case angsep_fct: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=4; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || - pNull[2] || pNull[3]) ) ) - this->value.data.dblptr[elem] = - angsep_calc(pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl); - } - } - break; - - - - /* Min/Max functions taking 1 or 2 arguments */ - - case min1_fct: - elem = row * theParams[0]->value.nelem; - if( this->type==LONG ) { - long minVal=0; - while( row-- ) { - valInit = 1; - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( !theParams[0]->value.undef[elem] ) { - if ( valInit ) { - valInit = 0; - minVal = theParams[0]->value.data.lngptr[elem]; - } else { - minVal = minvalue( minVal, - theParams[0]->value.data.lngptr[elem] ); - } - this->value.undef[row] = 0; - } - } - this->value.data.lngptr[row] = minVal; - } - } else if( this->type==DOUBLE ) { - double minVal=0.0; - while( row-- ) { - valInit = 1; - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( !theParams[0]->value.undef[elem] ) { - if ( valInit ) { - valInit = 0; - minVal = theParams[0]->value.data.dblptr[elem]; - } else { - minVal = minvalue( minVal, - theParams[0]->value.data.dblptr[elem] ); - } - this->value.undef[row] = 0; - } - } - this->value.data.dblptr[row] = minVal; - } - } else if( this->type==BITSTR ) { - char minVal; - while( row-- ) { - char *sptr1 = theParams[0]->value.data.strptr[row]; - minVal = '1'; - while (*sptr1) { - if (*sptr1 == '0') minVal = '0'; - sptr1++; - } - this->value.data.strptr[row][0] = minVal; - this->value.data.strptr[row][1] = 0; /* Null terminate */ - } - } - break; - case min2_fct: - if( this->type==LONG ) { - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.lng = - theParams[i]->value.data.lngptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.lng = - theParams[i]->value.data.lngptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( pNull[0] && pNull[1] ) { - this->value.undef[elem] = 1; - this->value.data.lngptr[elem] = 0; - } else if (pNull[0]) { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = pVals[1].data.lng; - } else if (pNull[1]) { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = pVals[0].data.lng; - } else { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = - minvalue( pVals[0].data.lng, pVals[1].data.lng ); - } - } - } - } else if( this->type==DOUBLE ) { - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( pNull[0] && pNull[1] ) { - this->value.undef[elem] = 1; - this->value.data.dblptr[elem] = 0; - } else if (pNull[0]) { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = pVals[1].data.dbl; - } else if (pNull[1]) { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = pVals[0].data.dbl; - } else { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = - minvalue( pVals[0].data.dbl, pVals[1].data.dbl ); - } - } - } - } - break; - - case max1_fct: - elem = row * theParams[0]->value.nelem; - if( this->type==LONG ) { - long maxVal=0; - while( row-- ) { - valInit = 1; - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( !theParams[0]->value.undef[elem] ) { - if ( valInit ) { - valInit = 0; - maxVal = theParams[0]->value.data.lngptr[elem]; - } else { - maxVal = maxvalue( maxVal, - theParams[0]->value.data.lngptr[elem] ); - } - this->value.undef[row] = 0; - } - } - this->value.data.lngptr[row] = maxVal; - } - } else if( this->type==DOUBLE ) { - double maxVal=0.0; - while( row-- ) { - valInit = 1; - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( !theParams[0]->value.undef[elem] ) { - if ( valInit ) { - valInit = 0; - maxVal = theParams[0]->value.data.dblptr[elem]; - } else { - maxVal = maxvalue( maxVal, - theParams[0]->value.data.dblptr[elem] ); - } - this->value.undef[row] = 0; - } - } - this->value.data.dblptr[row] = maxVal; - } - } else if( this->type==BITSTR ) { - char maxVal; - while( row-- ) { - char *sptr1 = theParams[0]->value.data.strptr[row]; - maxVal = '0'; - while (*sptr1) { - if (*sptr1 == '1') maxVal = '1'; - sptr1++; - } - this->value.data.strptr[row][0] = maxVal; - this->value.data.strptr[row][1] = 0; /* Null terminate */ - } - } - break; - case max2_fct: - if( this->type==LONG ) { - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.lng = - theParams[i]->value.data.lngptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.lng = - theParams[i]->value.data.lngptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( pNull[0] && pNull[1] ) { - this->value.undef[elem] = 1; - this->value.data.lngptr[elem] = 0; - } else if (pNull[0]) { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = pVals[1].data.lng; - } else if (pNull[1]) { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = pVals[0].data.lng; - } else { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = - maxvalue( pVals[0].data.lng, pVals[1].data.lng ); - } - } - } - } else if( this->type==DOUBLE ) { - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( pNull[0] && pNull[1] ) { - this->value.undef[elem] = 1; - this->value.data.dblptr[elem] = 0; - } else if (pNull[0]) { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = pVals[1].data.dbl; - } else if (pNull[1]) { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = pVals[0].data.dbl; - } else { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = - maxvalue( pVals[0].data.dbl, pVals[1].data.dbl ); - } - } - } - } - break; - - /* Boolean SAO region Functions... scalar or vector dbls */ - - case near_fct: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=3; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || - pNull[2]) ) ) - this->value.data.logptr[elem] = - bnear( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl ); - } - } - break; - - case circle_fct: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=5; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || - pNull[2] || pNull[3] || - pNull[4]) ) ) - this->value.data.logptr[elem] = - circle( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl, - pVals[4].data.dbl ); - } - } - break; - - case box_fct: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=7; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || - pNull[2] || pNull[3] || - pNull[4] || pNull[5] || - pNull[6] ) ) ) - this->value.data.logptr[elem] = - saobox( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl, - pVals[4].data.dbl, pVals[5].data.dbl, - pVals[6].data.dbl ); - } - } - break; - - case elps_fct: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=7; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || - pNull[2] || pNull[3] || - pNull[4] || pNull[5] || - pNull[6] ) ) ) - this->value.data.logptr[elem] = - ellipse( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl, - pVals[4].data.dbl, pVals[5].data.dbl, - pVals[6].data.dbl ); - } - } - break; - - /* C Conditional expression: bool ? expr : expr */ - - case ifthenelse_fct: - switch( this->type ) { - case BOOLEAN: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - if( vector[2]>1 ) { - pVals[2].data.log = - theParams[2]->value.data.logptr[elem]; - pNull[2] = theParams[2]->value.undef[elem]; - } else if( vector[2] ) { - pVals[2].data.log = - theParams[2]->value.data.logptr[row]; - pNull[2] = theParams[2]->value.undef[row]; - } - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.log = - theParams[i]->value.data.logptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.log = - theParams[i]->value.data.logptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = pNull[2]) ) { - if( pVals[2].data.log ) { - this->value.data.logptr[elem] = pVals[0].data.log; - this->value.undef[elem] = pNull[0]; - } else { - this->value.data.logptr[elem] = pVals[1].data.log; - this->value.undef[elem] = pNull[1]; - } - } - } - } - break; - case LONG: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - if( vector[2]>1 ) { - pVals[2].data.log = - theParams[2]->value.data.logptr[elem]; - pNull[2] = theParams[2]->value.undef[elem]; - } else if( vector[2] ) { - pVals[2].data.log = - theParams[2]->value.data.logptr[row]; - pNull[2] = theParams[2]->value.undef[row]; - } - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.lng = - theParams[i]->value.data.lngptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.lng = - theParams[i]->value.data.lngptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = pNull[2]) ) { - if( pVals[2].data.log ) { - this->value.data.lngptr[elem] = pVals[0].data.lng; - this->value.undef[elem] = pNull[0]; - } else { - this->value.data.lngptr[elem] = pVals[1].data.lng; - this->value.undef[elem] = pNull[1]; - } - } - } - } - break; - case DOUBLE: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - if( vector[2]>1 ) { - pVals[2].data.log = - theParams[2]->value.data.logptr[elem]; - pNull[2] = theParams[2]->value.undef[elem]; - } else if( vector[2] ) { - pVals[2].data.log = - theParams[2]->value.data.logptr[row]; - pNull[2] = theParams[2]->value.undef[row]; - } - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = pNull[2]) ) { - if( pVals[2].data.log ) { - this->value.data.dblptr[elem] = pVals[0].data.dbl; - this->value.undef[elem] = pNull[0]; - } else { - this->value.data.dblptr[elem] = pVals[1].data.dbl; - this->value.undef[elem] = pNull[1]; - } - } - } - } - break; - case STRING: - while( row-- ) { - if( vector[2] ) { - pVals[2].data.log = theParams[2]->value.data.logptr[row]; - pNull[2] = theParams[2]->value.undef[row]; - } - i=2; while( i-- ) - if( vector[i] ) { - strcpy( pVals[i].data.str, - theParams[i]->value.data.strptr[row] ); - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[row] = pNull[2]) ) { - if( pVals[2].data.log ) { - strcpy( this->value.data.strptr[row], - pVals[0].data.str ); - this->value.undef[row] = pNull[0]; - } else { - strcpy( this->value.data.strptr[row], - pVals[1].data.str ); - this->value.undef[row] = pNull[1]; - } - } else { - this->value.data.strptr[row][0] = '\0'; - } - } - break; - - } - break; - - /* String functions */ - case strmid_fct: - { - int strconst = theParams[0]->operation == CONST_OP; - int posconst = theParams[1]->operation == CONST_OP; - int lenconst = theParams[2]->operation == CONST_OP; - int dest_len = this->value.nelem; - int src_len = theParams[0]->value.nelem; - - while (row--) { - int pos; - int len; - char *str; - int undef = 0; - - if (posconst) { - pos = theParams[1]->value.data.lng; - } else { - pos = theParams[1]->value.data.lngptr[row]; - if (theParams[1]->value.undef[row]) undef = 1; - } - if (strconst) { - str = theParams[0]->value.data.str; - if (src_len == 0) src_len = strlen(str); - } else { - str = theParams[0]->value.data.strptr[row]; - if (theParams[0]->value.undef[row]) undef = 1; - } - if (lenconst) { - len = dest_len; - } else { - len = theParams[2]->value.data.lngptr[row]; - if (theParams[2]->value.undef[row]) undef = 1; - } - this->value.data.strptr[row][0] = '\0'; - if (pos == 0) undef = 1; - if (! undef ) { - if (cstrmid(this->value.data.strptr[row], len, - str, src_len, pos) < 0) break; - } - this->value.undef[row] = undef; - } - } - break; - - /* String functions */ - case strpos_fct: - { - int const1 = theParams[0]->operation == CONST_OP; - int const2 = theParams[1]->operation == CONST_OP; - - while (row--) { - char *str1, *str2; - int undef = 0; - - if (const1) { - str1 = theParams[0]->value.data.str; - } else { - str1 = theParams[0]->value.data.strptr[row]; - if (theParams[0]->value.undef[row]) undef = 1; - } - if (const2) { - str2 = theParams[1]->value.data.str; - } else { - str2 = theParams[1]->value.data.strptr[row]; - if (theParams[1]->value.undef[row]) undef = 1; - } - this->value.data.lngptr[row] = 0; - if (! undef ) { - char *res = strstr(str1, str2); - if (res == NULL) { - undef = 1; - this->value.data.lngptr[row] = 0; - } else { - this->value.data.lngptr[row] = (res - str1) + 1; - } - } - this->value.undef[row] = undef; - } - } - break; - - - } /* End switch(this->operation) */ - } /* End if (!gParse.status) */ - } /* End non-constant operations */ - - i = this->nSubNodes; - while( i-- ) { - if( theParams[i]->operation>0 ) { - /* Currently only numeric params allowed */ - free( theParams[i]->value.data.ptr ); - } - } -} - -static void Do_Deref( Node *this ) -{ - Node *theVar, *theDims[MAXDIMS]; - int isConst[MAXDIMS], allConst; - long dimVals[MAXDIMS]; - int i, nDims; - long row, elem, dsize; - - theVar = gParse.Nodes + this->SubNodes[0]; - - i = nDims = this->nSubNodes-1; - allConst = 1; - while( i-- ) { - theDims[i] = gParse.Nodes + this->SubNodes[i+1]; - isConst[i] = ( theDims[i]->operation==CONST_OP ); - if( isConst[i] ) - dimVals[i] = theDims[i]->value.data.lng; - else - allConst = 0; - } - - if( this->type==DOUBLE ) { - dsize = sizeof( double ); - } else if( this->type==LONG ) { - dsize = sizeof( long ); - } else if( this->type==BOOLEAN ) { - dsize = sizeof( char ); - } else - dsize = 0; - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - - if( allConst && theVar->value.naxis==nDims ) { - - /* Dereference completely using constant indices */ - - elem = 0; - i = nDims; - while( i-- ) { - if( dimVals[i]<1 || dimVals[i]>theVar->value.naxes[i] ) break; - elem = theVar->value.naxes[i]*elem + dimVals[i]-1; - } - if( i<0 ) { - for( row=0; rowtype==STRING ) - this->value.undef[row] = theVar->value.undef[row]; - else if( this->type==BITSTR ) - this->value.undef; /* Dummy - BITSTRs do not have undefs */ - else - this->value.undef[row] = theVar->value.undef[elem]; - - if( this->type==DOUBLE ) - this->value.data.dblptr[row] = - theVar->value.data.dblptr[elem]; - else if( this->type==LONG ) - this->value.data.lngptr[row] = - theVar->value.data.lngptr[elem]; - else if( this->type==BOOLEAN ) - this->value.data.logptr[row] = - theVar->value.data.logptr[elem]; - else { - /* XXX Note, the below expression uses knowledge of - the layout of the string format, namely (nelem+1) - characters per string, followed by (nelem+1) - "undef" values. */ - this->value.data.strptr[row][0] = - theVar->value.data.strptr[0][elem+row]; - this->value.data.strptr[row][1] = 0; /* Null terminate */ - } - elem += theVar->value.nelem; - } - } else { - yyerror("Index out of range"); - free( this->value.data.ptr ); - } - - } else if( allConst && nDims==1 ) { - - /* Reduce dimensions by 1, using a constant index */ - - if( dimVals[0] < 1 || - dimVals[0] > theVar->value.naxes[ theVar->value.naxis-1 ] ) { - yyerror("Index out of range"); - free( this->value.data.ptr ); - } else if ( this->type == BITSTR || this->type == STRING ) { - elem = this->value.nelem * (dimVals[0]-1); - for( row=0; rowvalue.undef) - this->value.undef[row] = theVar->value.undef[row]; - memcpy( (char*)this->value.data.strptr[0] - + row*sizeof(char)*(this->value.nelem+1), - (char*)theVar->value.data.strptr[0] + elem*sizeof(char), - this->value.nelem * sizeof(char) ); - /* Null terminate */ - this->value.data.strptr[row][this->value.nelem] = 0; - elem += theVar->value.nelem+1; - } - } else { - elem = this->value.nelem * (dimVals[0]-1); - for( row=0; rowvalue.undef + row*this->value.nelem, - theVar->value.undef + elem, - this->value.nelem * sizeof(char) ); - memcpy( (char*)this->value.data.ptr - + row*dsize*this->value.nelem, - (char*)theVar->value.data.ptr + elem*dsize, - this->value.nelem * dsize ); - elem += theVar->value.nelem; - } - } - - } else if( theVar->value.naxis==nDims ) { - - /* Dereference completely using an expression for the indices */ - - for( row=0; rowvalue.undef[row] ) { - yyerror("Null encountered as vector index"); - free( this->value.data.ptr ); - break; - } else - dimVals[i] = theDims[i]->value.data.lngptr[row]; - } - } - if( gParse.status ) break; - - elem = 0; - i = nDims; - while( i-- ) { - if( dimVals[i]<1 || dimVals[i]>theVar->value.naxes[i] ) break; - elem = theVar->value.naxes[i]*elem + dimVals[i]-1; - } - if( i<0 ) { - elem += row*theVar->value.nelem; - - if( this->type==STRING ) - this->value.undef[row] = theVar->value.undef[row]; - else if( this->type==BITSTR ) - this->value.undef; /* Dummy - BITSTRs do not have undefs */ - else - this->value.undef[row] = theVar->value.undef[elem]; - - if( this->type==DOUBLE ) - this->value.data.dblptr[row] = - theVar->value.data.dblptr[elem]; - else if( this->type==LONG ) - this->value.data.lngptr[row] = - theVar->value.data.lngptr[elem]; - else if( this->type==BOOLEAN ) - this->value.data.logptr[row] = - theVar->value.data.logptr[elem]; - else { - /* XXX Note, the below expression uses knowledge of - the layout of the string format, namely (nelem+1) - characters per string, followed by (nelem+1) - "undef" values. */ - this->value.data.strptr[row][0] = - theVar->value.data.strptr[0][elem+row]; - this->value.data.strptr[row][1] = 0; /* Null terminate */ - } - } else { - yyerror("Index out of range"); - free( this->value.data.ptr ); - } - } - - } else { - - /* Reduce dimensions by 1, using a nonconstant expression */ - - for( row=0; rowvalue.undef[row] ) { - yyerror("Null encountered as vector index"); - free( this->value.data.ptr ); - break; - } else - dimVals[0] = theDims[0]->value.data.lngptr[row]; - - if( dimVals[0] < 1 || - dimVals[0] > theVar->value.naxes[ theVar->value.naxis-1 ] ) { - yyerror("Index out of range"); - free( this->value.data.ptr ); - } else if ( this->type == BITSTR || this->type == STRING ) { - elem = this->value.nelem * (dimVals[0]-1); - elem += row*(theVar->value.nelem+1); - if (this->value.undef) - this->value.undef[row] = theVar->value.undef[row]; - memcpy( (char*)this->value.data.strptr[0] - + row*sizeof(char)*(this->value.nelem+1), - (char*)theVar->value.data.strptr[0] + elem*sizeof(char), - this->value.nelem * sizeof(char) ); - /* Null terminate */ - this->value.data.strptr[row][this->value.nelem] = 0; - } else { - elem = this->value.nelem * (dimVals[0]-1); - elem += row*theVar->value.nelem; - memcpy( this->value.undef + row*this->value.nelem, - theVar->value.undef + elem, - this->value.nelem * sizeof(char) ); - memcpy( (char*)this->value.data.ptr - + row*dsize*this->value.nelem, - (char*)theVar->value.data.ptr + elem*dsize, - this->value.nelem * dsize ); - } - } - } - } - - if( theVar->operation>0 ) { - if (theVar->type == STRING || theVar->type == BITSTR) - free(theVar->value.data.strptr[0] ); - else - free( theVar->value.data.ptr ); - } - for( i=0; ioperation>0 ) { - free( theDims[i]->value.data.ptr ); - } -} - -static void Do_GTI( Node *this ) -{ - Node *theExpr, *theTimes; - double *start, *stop, *times; - long elem, nGTI, gti; - int ordered; - - theTimes = gParse.Nodes + this->SubNodes[0]; - theExpr = gParse.Nodes + this->SubNodes[1]; - - nGTI = theTimes->value.nelem; - start = theTimes->value.data.dblptr; - stop = theTimes->value.data.dblptr + nGTI; - ordered = theTimes->type; - - if( theExpr->operation==CONST_OP ) { - - this->value.data.log = - (Search_GTI( theExpr->value.data.dbl, nGTI, start, stop, ordered )>=0); - this->operation = CONST_OP; - - } else { - - Allocate_Ptrs( this ); - - times = theExpr->value.data.dblptr; - if( !gParse.status ) { - - elem = gParse.nRows * this->value.nelem; - if( nGTI ) { - gti = -1; - while( elem-- ) { - if( (this->value.undef[elem] = theExpr->value.undef[elem]) ) - continue; - - /* Before searching entire GTI, check the GTI found last time */ - if( gti<0 || times[elem]stop[gti] ) { - gti = Search_GTI( times[elem], nGTI, start, stop, ordered ); - } - this->value.data.logptr[elem] = ( gti>=0 ); - } - } else - while( elem-- ) { - this->value.data.logptr[elem] = 0; - this->value.undef[elem] = 0; - } - } - } - - if( theExpr->operation>0 ) - free( theExpr->value.data.ptr ); -} - -static long Search_GTI( double evtTime, long nGTI, double *start, - double *stop, int ordered ) -{ - long gti, step; - - if( ordered && nGTI>15 ) { /* If time-ordered and lots of GTIs, */ - /* use "FAST" Binary search algorithm */ - if( evtTime>=start[0] && evtTime<=stop[nGTI-1] ) { - gti = step = (nGTI >> 1); - while(1) { - if( step>1L ) step >>= 1; - - if( evtTime>stop[gti] ) { - if( evtTime>=start[gti+1] ) - gti += step; - else { - gti = -1L; - break; - } - } else if( evtTime=start[gti] && evtTime<=stop[gti] ) - break; - } - return( gti ); -} - -static void Do_REG( Node *this ) -{ - Node *theRegion, *theX, *theY; - double Xval=0.0, Yval=0.0; - char Xnull=0, Ynull=0; - int Xvector, Yvector; - long nelem, elem, rows; - - theRegion = gParse.Nodes + this->SubNodes[0]; - theX = gParse.Nodes + this->SubNodes[1]; - theY = gParse.Nodes + this->SubNodes[2]; - - Xvector = ( theX->operation!=CONST_OP ); - if( Xvector ) - Xvector = theX->value.nelem; - else { - Xval = theX->value.data.dbl; - } - - Yvector = ( theY->operation!=CONST_OP ); - if( Yvector ) - Yvector = theY->value.nelem; - else { - Yval = theY->value.data.dbl; - } - - if( !Xvector && !Yvector ) { - - this->value.data.log = - ( fits_in_region( Xval, Yval, (SAORegion *)theRegion->value.data.ptr ) - != 0 ); - this->operation = CONST_OP; - - } else { - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - - rows = gParse.nRows; - nelem = this->value.nelem; - elem = rows*nelem; - - while( rows-- ) { - while( nelem-- ) { - elem--; - - if( Xvector>1 ) { - Xval = theX->value.data.dblptr[elem]; - Xnull = theX->value.undef[elem]; - } else if( Xvector ) { - Xval = theX->value.data.dblptr[rows]; - Xnull = theX->value.undef[rows]; - } - - if( Yvector>1 ) { - Yval = theY->value.data.dblptr[elem]; - Ynull = theY->value.undef[elem]; - } else if( Yvector ) { - Yval = theY->value.data.dblptr[rows]; - Ynull = theY->value.undef[rows]; - } - - this->value.undef[elem] = ( Xnull || Ynull ); - if( this->value.undef[elem] ) - continue; - - this->value.data.logptr[elem] = - ( fits_in_region( Xval, Yval, - (SAORegion *)theRegion->value.data.ptr ) - != 0 ); - } - nelem = this->value.nelem; - } - } - } - - if( theX->operation>0 ) - free( theX->value.data.ptr ); - if( theY->operation>0 ) - free( theY->value.data.ptr ); -} - -static void Do_Vector( Node *this ) -{ - Node *that; - long row, elem, idx, jdx, offset=0; - int node; - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - - for( node=0; nodenSubNodes; node++ ) { - - that = gParse.Nodes + this->SubNodes[node]; - - if( that->operation == CONST_OP ) { - - idx = gParse.nRows*this->value.nelem + offset; - while( (idx-=this->value.nelem)>=0 ) { - - this->value.undef[idx] = 0; - - switch( this->type ) { - case BOOLEAN: - this->value.data.logptr[idx] = that->value.data.log; - break; - case LONG: - this->value.data.lngptr[idx] = that->value.data.lng; - break; - case DOUBLE: - this->value.data.dblptr[idx] = that->value.data.dbl; - break; - } - } - - } else { - - row = gParse.nRows; - idx = row * that->value.nelem; - while( row-- ) { - elem = that->value.nelem; - jdx = row*this->value.nelem + offset; - while( elem-- ) { - this->value.undef[jdx+elem] = - that->value.undef[--idx]; - - switch( this->type ) { - case BOOLEAN: - this->value.data.logptr[jdx+elem] = - that->value.data.logptr[idx]; - break; - case LONG: - this->value.data.lngptr[jdx+elem] = - that->value.data.lngptr[idx]; - break; - case DOUBLE: - this->value.data.dblptr[jdx+elem] = - that->value.data.dblptr[idx]; - break; - } - } - } - } - offset += that->value.nelem; - } - - } - - for( node=0; node < this->nSubNodes; node++ ) - if( OPER(this->SubNodes[node])>0 ) - free( gParse.Nodes[this->SubNodes[node]].value.data.ptr ); -} - -/*****************************************************************************/ -/* Utility routines which perform the calculations on bits and SAO regions */ -/*****************************************************************************/ - -static char bitlgte(char *bits1, int oper, char *bits2) -{ - int val1, val2, nextbit; - char result; - int i, l1, l2, length, ldiff; - char *stream=0; - char chr1, chr2; - - l1 = strlen(bits1); - l2 = strlen(bits2); - length = (l1 > l2) ? l1 : l2; - stream = (char *)malloc(sizeof(char)*(length+1)); - if (l1 < l2) - { - ldiff = l2 - l1; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l1-- ) stream[i++] = *(bits1++); - stream[i] = '\0'; - bits1 = stream; - } - else if (l2 < l1) - { - ldiff = l1 - l2; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l2-- ) stream[i++] = *(bits2++); - stream[i] = '\0'; - bits2 = stream; - } - - val1 = val2 = 0; - nextbit = 1; - - while( length-- ) - { - chr1 = bits1[length]; - chr2 = bits2[length]; - if ((chr1 != 'x')&&(chr1 != 'X')&&(chr2 != 'x')&&(chr2 != 'X')) - { - if (chr1 == '1') val1 += nextbit; - if (chr2 == '1') val2 += nextbit; - nextbit *= 2; - } - } - result = 0; - switch (oper) - { - case LT: - if (val1 < val2) result = 1; - break; - case LTE: - if (val1 <= val2) result = 1; - break; - case GT: - if (val1 > val2) result = 1; - break; - case GTE: - if (val1 >= val2) result = 1; - break; - } - free(stream); - return (result); -} - -static void bitand(char *result,char *bitstrm1,char *bitstrm2) -{ - int i, l1, l2, ldiff, largestStream; - char *stream=0; - char chr1, chr2; - - l1 = strlen(bitstrm1); - l2 = strlen(bitstrm2); - largestStream = (l1 > l2) ? l1 : l2; - stream = (char *)malloc(sizeof(char)*(largestStream+1)); - if (l1 < l2) - { - ldiff = l2 - l1; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l1-- ) stream[i++] = *(bitstrm1++); - stream[i] = '\0'; - bitstrm1 = stream; - } - else if (l2 < l1) - { - ldiff = l1 - l2; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l2-- ) stream[i++] = *(bitstrm2++); - stream[i] = '\0'; - bitstrm2 = stream; - } - while ( (chr1 = *(bitstrm1++)) ) - { - chr2 = *(bitstrm2++); - if ((chr1 == 'x') || (chr2 == 'x')) - *result = 'x'; - else if ((chr1 == '1') && (chr2 == '1')) - *result = '1'; - else - *result = '0'; - result++; - } - free(stream); - *result = '\0'; -} - -static void bitor(char *result,char *bitstrm1,char *bitstrm2) -{ - int i, l1, l2, ldiff, largestStream; - char *stream=0; - char chr1, chr2; - - l1 = strlen(bitstrm1); - l2 = strlen(bitstrm2); - largestStream = (l1 > l2) ? l1 : l2; - stream = (char *)malloc(sizeof(char)*(largestStream+1)); - if (l1 < l2) - { - ldiff = l2 - l1; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l1-- ) stream[i++] = *(bitstrm1++); - stream[i] = '\0'; - bitstrm1 = stream; - } - else if (l2 < l1) - { - ldiff = l1 - l2; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l2-- ) stream[i++] = *(bitstrm2++); - stream[i] = '\0'; - bitstrm2 = stream; - } - while ( (chr1 = *(bitstrm1++)) ) - { - chr2 = *(bitstrm2++); - if ((chr1 == '1') || (chr2 == '1')) - *result = '1'; - else if ((chr1 == '0') || (chr2 == '0')) - *result = '0'; - else - *result = 'x'; - result++; - } - free(stream); - *result = '\0'; -} - -static void bitnot(char *result,char *bits) -{ - int length; - char chr; - - length = strlen(bits); - while( length-- ) { - chr = *(bits++); - *(result++) = ( chr=='1' ? '0' : ( chr=='0' ? '1' : chr ) ); - } - *result = '\0'; -} - -static char bitcmp(char *bitstrm1, char *bitstrm2) -{ - int i, l1, l2, ldiff, largestStream; - char *stream=0; - char chr1, chr2; - - l1 = strlen(bitstrm1); - l2 = strlen(bitstrm2); - largestStream = (l1 > l2) ? l1 : l2; - stream = (char *)malloc(sizeof(char)*(largestStream+1)); - if (l1 < l2) - { - ldiff = l2 - l1; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l1-- ) stream[i++] = *(bitstrm1++); - stream[i] = '\0'; - bitstrm1 = stream; - } - else if (l2 < l1) - { - ldiff = l1 - l2; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l2-- ) stream[i++] = *(bitstrm2++); - stream[i] = '\0'; - bitstrm2 = stream; - } - while( (chr1 = *(bitstrm1++)) ) - { - chr2 = *(bitstrm2++); - if ( ((chr1 == '0') && (chr2 == '1')) - || ((chr1 == '1') && (chr2 == '0')) ) - { - free(stream); - return( 0 ); - } - } - free(stream); - return( 1 ); -} - -static char bnear(double x, double y, double tolerance) -{ - if (fabs(x - y) < tolerance) - return ( 1 ); - else - return ( 0 ); -} - -static char saobox(double xcen, double ycen, double xwid, double ywid, - double rot, double xcol, double ycol) -{ - double x,y,xprime,yprime,xmin,xmax,ymin,ymax,theta; - - theta = (rot / 180.0) * myPI; - xprime = xcol - xcen; - yprime = ycol - ycen; - x = xprime * cos(theta) + yprime * sin(theta); - y = -xprime * sin(theta) + yprime * cos(theta); - xmin = - 0.5 * xwid; xmax = 0.5 * xwid; - ymin = - 0.5 * ywid; ymax = 0.5 * ywid; - if ((x >= xmin) && (x <= xmax) && (y >= ymin) && (y <= ymax)) - return ( 1 ); - else - return ( 0 ); -} - -static char circle(double xcen, double ycen, double rad, - double xcol, double ycol) -{ - double r2,dx,dy,dlen; - - dx = xcol - xcen; - dy = ycol - ycen; - dx *= dx; dy *= dy; - dlen = dx + dy; - r2 = rad * rad; - if (dlen <= r2) - return ( 1 ); - else - return ( 0 ); -} - -static char ellipse(double xcen, double ycen, double xrad, double yrad, - double rot, double xcol, double ycol) -{ - double x,y,xprime,yprime,dx,dy,dlen,theta; - - theta = (rot / 180.0) * myPI; - xprime = xcol - xcen; - yprime = ycol - ycen; - x = xprime * cos(theta) + yprime * sin(theta); - y = -xprime * sin(theta) + yprime * cos(theta); - dx = x / xrad; dy = y / yrad; - dx *= dx; dy *= dy; - dlen = dx + dy; - if (dlen <= 1.0) - return ( 1 ); - else - return ( 0 ); -} - -/* - * Extract substring - */ -int cstrmid(char *dest_str, int dest_len, - char *src_str, int src_len, - int pos) -{ - /* char fill_char = ' '; */ - char fill_char = '\0'; - if (src_len == 0) { src_len = strlen(src_str); } /* .. if constant */ - - /* Fill destination with blanks */ - if (pos < 0) { - yyerror("STRMID(S,P,N) P must be 0 or greater"); - return -1; - } - if (pos > src_len || pos == 0) { - /* pos==0: blank string requested */ - memset(dest_str, fill_char, dest_len); - } else if (pos+dest_len > src_len) { - /* Copy a subset */ - int nsub = src_len-pos+1; - int npad = dest_len - nsub; - memcpy(dest_str, src_str+pos-1, nsub); - /* Fill remaining string with blanks */ - memset(dest_str+nsub, fill_char, npad); - } else { - /* Full string copy */ - memcpy(dest_str, src_str+pos-1, dest_len); - } - dest_str[dest_len] = '\0'; /* Null-terminate */ - - return 0; -} - - -static void yyerror(char *s) -{ - char msg[80]; - - if( !gParse.status ) gParse.status = PARSE_SYNTAX_ERR; - - strncpy(msg, s, 80); - msg[79] = '\0'; - ffpmsg(msg); -} diff --git a/src/external/OpenGR/3rdparty/cfitsio/eval_defs.h b/src/external/OpenGR/3rdparty/cfitsio/eval_defs.h deleted file mode 100644 index 09c066b1d..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/eval_defs.h +++ /dev/null @@ -1,163 +0,0 @@ -#include -#include -#include -#include -#if defined(__sgi) || defined(__hpux) -#include -#endif -#ifdef sparc -#include -#endif -#include "fitsio2.h" - -#define MAXDIMS 5 -#define MAXSUBS 10 -#define MAXVARNAME 80 -#define CONST_OP -1000 -#define pERROR -1 -#define MAX_STRLEN 256 -#define MAX_STRLEN_S "255" - -#ifndef FFBISON -#include "eval_tab.h" -#endif - - -typedef struct { - char name[MAXVARNAME+1]; - int type; - long nelem; - int naxis; - long naxes[MAXDIMS]; - char *undef; - void *data; - } DataInfo; - -typedef struct { - long nelem; - int naxis; - long naxes[MAXDIMS]; - char *undef; - union { - double dbl; - long lng; - char log; - char str[MAX_STRLEN]; - double *dblptr; - long *lngptr; - char *logptr; - char **strptr; - void *ptr; - } data; - } lval; - -typedef struct Node { - int operation; - void (*DoOp)(struct Node *this); - int nSubNodes; - int SubNodes[MAXSUBS]; - int type; - lval value; - } Node; - -typedef struct { - fitsfile *def_fptr; - int (*getData)( char *dataName, void *dataValue ); - int (*loadData)( int varNum, long fRow, long nRows, - void *data, char *undef ); - - int compressed; - int timeCol; - int parCol; - int valCol; - - char *expr; - int index; - int is_eobuf; - - Node *Nodes; - int nNodes; - int nNodesAlloc; - int resultNode; - - long firstRow; - long nRows; - - int nCols; - iteratorCol *colData; - DataInfo *varData; - PixelFilter *pixFilter; - - long firstDataRow; - long nDataRows; - long totalRows; - - int datatype; - int hdutype; - - int status; - } ParseData; - -typedef enum { - rnd_fct = 1001, - sum_fct, - nelem_fct, - sin_fct, - cos_fct, - tan_fct, - asin_fct, - acos_fct, - atan_fct, - sinh_fct, - cosh_fct, - tanh_fct, - exp_fct, - log_fct, - log10_fct, - sqrt_fct, - abs_fct, - atan2_fct, - ceil_fct, - floor_fct, - round_fct, - min1_fct, - min2_fct, - max1_fct, - max2_fct, - near_fct, - circle_fct, - box_fct, - elps_fct, - isnull_fct, - defnull_fct, - gtifilt_fct, - regfilt_fct, - ifthenelse_fct, - row_fct, - null_fct, - median_fct, - average_fct, - stddev_fct, - nonnull_fct, - angsep_fct, - gasrnd_fct, - poirnd_fct, - strmid_fct, - strpos_fct - } funcOp; - -extern ParseData gParse; - -#ifdef __cplusplus -extern "C" { -#endif - - int ffparse(void); - int fflex(void); - void ffrestart(FILE*); - - void Evaluate_Parser( long firstRow, long nRows ); - -#ifdef __cplusplus - } -#endif diff --git a/src/external/OpenGR/3rdparty/cfitsio/eval_f.c b/src/external/OpenGR/3rdparty/cfitsio/eval_f.c deleted file mode 100644 index 6d7e72dc4..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/eval_f.c +++ /dev/null @@ -1,2839 +0,0 @@ -/************************************************************************/ -/* */ -/* CFITSIO Lexical Parser */ -/* */ -/* This file is one of 3 files containing code which parses an */ -/* arithmetic expression and evaluates it in the context of an input */ -/* FITS file table extension. The CFITSIO lexical parser is divided */ -/* into the following 3 parts/files: the CFITSIO "front-end", */ -/* eval_f.c, contains the interface between the user/CFITSIO and the */ -/* real core of the parser; the FLEX interpreter, eval_l.c, takes the */ -/* input string and parses it into tokens and identifies the FITS */ -/* information required to evaluate the expression (ie, keywords and */ -/* columns); and, the BISON grammar and evaluation routines, eval_y.c, */ -/* receives the FLEX output and determines and performs the actual */ -/* operations. The files eval_l.c and eval_y.c are produced from */ -/* running flex and bison on the files eval.l and eval.y, respectively. */ -/* (flex and bison are available from any GNU archive: see www.gnu.org) */ -/* */ -/* The grammar rules, rather than evaluating the expression in situ, */ -/* builds a tree, or Nodal, structure mapping out the order of */ -/* operations and expression dependencies. This "compilation" process */ -/* allows for much faster processing of multiple rows. This technique */ -/* was developed by Uwe Lammers of the XMM Science Analysis System, */ -/* although the CFITSIO implementation is entirely code original. */ -/* */ -/* */ -/* Modification History: */ -/* */ -/* Kent Blackburn c1992 Original parser code developed for the */ -/* FTOOLS software package, in particular, */ -/* the fselect task. */ -/* Kent Blackburn c1995 BIT column support added */ -/* Peter D Wilson Feb 1998 Vector column support added */ -/* Peter D Wilson May 1998 Ported to CFITSIO library. User */ -/* interface routines written, in essence */ -/* making fselect, fcalc, and maketime */ -/* capabilities available to all tools */ -/* via single function calls. */ -/* Peter D Wilson Jun 1998 Major rewrite of parser core, so as to */ -/* create a run-time evaluation tree, */ -/* inspired by the work of Uwe Lammers, */ -/* resulting in a speed increase of */ -/* 10-100 times. */ -/* Peter D Wilson Jul 1998 gtifilter(a,b,c,d) function added */ -/* Peter D Wilson Aug 1998 regfilter(a,b,c,d) function added */ -/* Peter D Wilson Jul 1999 Make parser fitsfile-independent, */ -/* allowing a purely vector-based usage */ -/* Peter D Wilson Aug 1999 Add row-offset capability */ -/* Peter D Wilson Sep 1999 Add row-range capability to ffcalc_rng */ -/* */ -/************************************************************************/ - -#include -#include -#include "eval_defs.h" -#include "region.h" - -typedef struct { - int datatype; /* Data type to cast parse results into for user */ - void *dataPtr; /* Pointer to array of results, NULL if to use iterCol */ - void *nullPtr; /* Pointer to nulval, use zero if NULL */ - long maxRows; /* Max No. of rows to process, -1=all, 0=1 iteration */ - int anyNull; /* Flag indicating at least 1 undef value encountered */ -} parseInfo; - -/* Internal routines needed to allow the evaluator to operate on FITS data */ - -static void Setup_DataArrays( int nCols, iteratorCol *cols, - long fRow, long nRows ); -static int find_column( char *colName, void *itslval ); -static int find_keywd ( char *key, void *itslval ); -static int allocateCol( int nCol, int *status ); -static int load_column( int varNum, long fRow, long nRows, - void *data, char *undef ); - -static int DEBUG_PIXFILTER; - -#define FREE(x) { if (x) free(x); else printf("invalid free(" #x ") at %s:%d\n", __FILE__, __LINE__); } - -/*---------------------------------------------------------------------------*/ -int fffrow( fitsfile *fptr, /* I - Input FITS file */ - char *expr, /* I - Boolean expression */ - long firstrow, /* I - First row of table to eval */ - long nrows, /* I - Number of rows to evaluate */ - long *n_good_rows, /* O - Number of rows eval to True */ - char *row_status, /* O - Array of boolean results */ - int *status ) /* O - Error status */ -/* */ -/* Evaluate a boolean expression using the indicated rows, returning an */ -/* array of flags indicating which rows evaluated to TRUE/FALSE */ -/*---------------------------------------------------------------------------*/ -{ - parseInfo Info; - int naxis, constant; - long nelem, naxes[MAXDIMS], elem; - char result; - - if( *status ) return( *status ); - - FFLOCK; - if( ffiprs( fptr, 0, expr, MAXDIMS, &Info.datatype, &nelem, &naxis, - naxes, status ) ) { - ffcprs(); - FFUNLOCK; - return( *status ); - } - if( nelem<0 ) { - constant = 1; - nelem = -nelem; - } else - constant = 0; - - if( Info.datatype!=TLOGICAL || nelem!=1 ) { - ffcprs(); - ffpmsg("Expression does not evaluate to a logical scalar."); - FFUNLOCK; - return( *status = PARSE_BAD_TYPE ); - } - - if( constant ) { /* No need to call parser... have result from ffiprs */ - result = gParse.Nodes[gParse.resultNode].value.data.log; - *n_good_rows = nrows; - for( elem=0; elem1 ? firstrow : 1); - Info.dataPtr = row_status; - Info.nullPtr = NULL; - Info.maxRows = nrows; - - if( ffiter( gParse.nCols, gParse.colData, firstrow-1, 0, - parse_data, (void*)&Info, status ) == -1 ) - *status = 0; /* -1 indicates exitted without error before end... OK */ - - if( *status ) { - - /***********************/ - /* Error... Do nothing */ - /***********************/ - - } else { - - /***********************************/ - /* Count number of good rows found */ - /***********************************/ - - *n_good_rows = 0L; - for( elem=0; elemHDUposition != (infptr->Fptr)->curhdu ) - ffmahd( infptr, (infptr->HDUposition) + 1, NULL, status ); - if( *status ) { - ffcprs(); - FFUNLOCK; - return( *status ); - } - inExt.rowLength = (long) (infptr->Fptr)->rowlength; - inExt.numRows = (infptr->Fptr)->numrows; - inExt.heapSize = (infptr->Fptr)->heapsize; - if( inExt.numRows == 0 ) { /* Nothing to copy */ - ffcprs(); - FFUNLOCK; - return( *status ); - } - - if( outfptr->HDUposition != (outfptr->Fptr)->curhdu ) - ffmahd( outfptr, (outfptr->HDUposition) + 1, NULL, status ); - if( (outfptr->Fptr)->datastart < 0 ) - ffrdef( outfptr, status ); - if( *status ) { - ffcprs(); - FFUNLOCK; - return( *status ); - } - outExt.rowLength = (long) (outfptr->Fptr)->rowlength; - outExt.numRows = (outfptr->Fptr)->numrows; - if( !outExt.numRows ) - (outfptr->Fptr)->heapsize = 0L; - outExt.heapSize = (outfptr->Fptr)->heapsize; - - if( inExt.rowLength != outExt.rowLength ) { - ffpmsg("Output table has different row length from input"); - ffcprs(); - FFUNLOCK; - return( *status = PARSE_BAD_OUTPUT ); - } - - /***********************************/ - /* Fill out Info data for parser */ - /***********************************/ - - Info.dataPtr = (char *)malloc( (size_t) ((inExt.numRows + 1) * sizeof(char)) ); - Info.nullPtr = NULL; - Info.maxRows = (long) inExt.numRows; - if( !Info.dataPtr ) { - ffpmsg("Unable to allocate memory for row selection"); - ffcprs(); - FFUNLOCK; - return( *status = MEMORY_ALLOCATION ); - } - - /* make sure array is zero terminated */ - ((char*)Info.dataPtr)[inExt.numRows] = 0; - - if( constant ) { /* Set all rows to the same value from constant result */ - - result = gParse.Nodes[gParse.resultNode].value.data.log; - for( ntodo = 0; ntodo 1) - ffirow( outfptr, outExt.numRows, nGood, status ); - } - - do { - if( ((char*)Info.dataPtr)[inloc-1] ) { - ffgtbb( infptr, inloc, 1L, rdlen, buffer+rdlen*nbuff, status ); - nbuff++; - if( nbuff==maxrows ) { - ffptbb( outfptr, outloc, 1L, rdlen*nbuff, buffer, status ); - outloc += nbuff; - nbuff = 0; - } - } - inloc++; - } while( !*status && inloc<=inExt.numRows ); - - if( nbuff ) { - ffptbb( outfptr, outloc, 1L, rdlen*nbuff, buffer, status ); - outloc += nbuff; - } - - if( infptr==outfptr ) { - - if( outloc<=inExt.numRows ) - ffdrow( infptr, outloc, inExt.numRows-outloc+1, status ); - - } else if( inExt.heapSize && nGood ) { - - /* Copy heap, if it exists and at least one row copied */ - - /********************************************************/ - /* Get location information from the output extension */ - /********************************************************/ - - if( outfptr->HDUposition != (outfptr->Fptr)->curhdu ) - ffmahd( outfptr, (outfptr->HDUposition) + 1, NULL, status ); - outExt.dataStart = (outfptr->Fptr)->datastart; - outExt.heapStart = (outfptr->Fptr)->heapstart; - - /*************************************************/ - /* Insert more space into outfptr if necessary */ - /*************************************************/ - - hsize = outExt.heapStart + outExt.heapSize; - freespace = (long) (( ( (hsize + 2879) / 2880) * 2880) - hsize); - ntodo = inExt.heapSize; - - if ( (freespace - ntodo) < 0) { /* not enough existing space? */ - ntodo = (ntodo - freespace + 2879) / 2880; /* number of blocks */ - ffiblk(outfptr, (long) ntodo, 1, status); /* insert the blocks */ - } - ffukyj( outfptr, "PCOUNT", inExt.heapSize+outExt.heapSize, - NULL, status ); - - /*******************************************************/ - /* Get location information from the input extension */ - /*******************************************************/ - - if( infptr->HDUposition != (infptr->Fptr)->curhdu ) - ffmahd( infptr, (infptr->HDUposition) + 1, NULL, status ); - inExt.dataStart = (infptr->Fptr)->datastart; - inExt.heapStart = (infptr->Fptr)->heapstart; - - /**********************************/ - /* Finally copy heap to outfptr */ - /**********************************/ - - ntodo = inExt.heapSize; - inbyteloc = inExt.heapStart + inExt.dataStart; - outbyteloc = outExt.heapStart + outExt.dataStart + outExt.heapSize; - - while ( ntodo && !*status ) { - rdlen = (long) minvalue(ntodo,500000); - ffmbyt( infptr, inbyteloc, REPORT_EOF, status ); - ffgbyt( infptr, rdlen, buffer, status ); - ffmbyt( outfptr, outbyteloc, IGNORE_EOF, status ); - ffpbyt( outfptr, rdlen, buffer, status ); - inbyteloc += rdlen; - outbyteloc += rdlen; - ntodo -= rdlen; - } - - /***********************************************************/ - /* But must update DES if data is being appended to a */ - /* pre-existing heap space. Edit each new entry in file */ - /***********************************************************/ - - if( outExt.heapSize ) { - LONGLONG repeat, offset, j; - int i; - for( i=1; i<=(outfptr->Fptr)->tfield; i++ ) { - if( (outfptr->Fptr)->tableptr[i-1].tdatatype<0 ) { - for( j=outExt.numRows+1; j<=outExt.numRows+nGood; j++ ) { - ffgdesll( outfptr, i, j, &repeat, &offset, status ); - offset += outExt.heapSize; - ffpdes( outfptr, i, j, repeat, offset, status ); - } - } - } - } - - } /* End of HEAP copy */ - - FREE(buffer); - } - - FREE(Info.dataPtr); - ffcprs(); - - ffcmph(outfptr, status); /* compress heap, deleting any orphaned data */ - FFUNLOCK; - return(*status); -} - -/*---------------------------------------------------------------------------*/ -int ffcrow( fitsfile *fptr, /* I - Input FITS file */ - int datatype, /* I - Datatype to return results as */ - char *expr, /* I - Arithmetic expression */ - long firstrow, /* I - First row to evaluate */ - long nelements, /* I - Number of elements to return */ - void *nulval, /* I - Ptr to value to use as UNDEF */ - void *array, /* O - Array of results */ - int *anynul, /* O - Were any UNDEFs encountered? */ - int *status ) /* O - Error status */ -/* */ -/* Calculate an expression for the indicated rows of a table, returning */ -/* the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If */ -/* nulval==NULL, UNDEFs will be zeroed out. For vector results, the number */ -/* of elements returned may be less than nelements if nelements is not an */ -/* even multiple of the result dimension. Call fftexp to obtain the */ -/* dimensions of the results. */ -/*---------------------------------------------------------------------------*/ -{ - parseInfo Info; - int naxis; - long nelem1, naxes[MAXDIMS]; - - if( *status ) return( *status ); - - FFLOCK; - if( ffiprs( fptr, 0, expr, MAXDIMS, &Info.datatype, &nelem1, &naxis, - naxes, status ) ) { - ffcprs(); - FFUNLOCK; - return( *status ); - } - if( nelem1<0 ) nelem1 = - nelem1; - - if( nelements1 ? firstrow : 1); - - if( datatype ) Info.datatype = datatype; - - Info.dataPtr = array; - Info.nullPtr = nulval; - Info.maxRows = nelements / nelem1; - - if( ffiter( gParse.nCols, gParse.colData, firstrow-1, 0, - parse_data, (void*)&Info, status ) == -1 ) - *status=0; /* -1 indicates exitted without error before end... OK */ - - *anynul = Info.anyNull; - ffcprs(); - FFUNLOCK; - return( *status ); -} - -/*--------------------------------------------------------------------------*/ -int ffcalc( fitsfile *infptr, /* I - Input FITS file */ - char *expr, /* I - Arithmetic expression */ - fitsfile *outfptr, /* I - Output fits file */ - char *parName, /* I - Name of output parameter */ - char *parInfo, /* I - Extra information on parameter */ - int *status ) /* O - Error status */ -/* */ -/* Evaluate an expression for all rows of a table. Call ffcalc_rng with */ -/* a row range of 1-MAX. */ -{ - long start=1, end=LONG_MAX; - - return ffcalc_rng( infptr, expr, outfptr, parName, parInfo, - 1, &start, &end, status ); -} - -/*--------------------------------------------------------------------------*/ -int ffcalc_rng( fitsfile *infptr, /* I - Input FITS file */ - char *expr, /* I - Arithmetic expression */ - fitsfile *outfptr, /* I - Output fits file */ - char *parName, /* I - Name of output parameter */ - char *parInfo, /* I - Extra information on parameter */ - int nRngs, /* I - Row range info */ - long *start, /* I - Row range info */ - long *end, /* I - Row range info */ - int *status ) /* O - Error status */ -/* */ -/* Evaluate an expression using the data in the input FITS file and place */ -/* the results into either a column or keyword in the output fits file, */ -/* depending on the value of parName (keywords normally prefixed with '#') */ -/* and whether the expression evaluates to a constant or a table column. */ -/* The logic is as follows: */ -/* (1) If a column exists with name, parName, put results there. */ -/* (2) If parName starts with '#', as in #NAXIS, put result there, */ -/* with parInfo used as the comment. If expression does not evaluate */ -/* to a constant, flag an error. */ -/* (3) If a keyword exists with name, parName, and expression is a */ -/* constant, put result there, using parInfo as the new comment. */ -/* (4) Else, create a new column with name parName and TFORM parInfo. */ -/* If parInfo is NULL, use a default data type for the column. */ -/*--------------------------------------------------------------------------*/ -{ - parseInfo Info; - int naxis, constant, typecode, newNullKwd=0; - long nelem, naxes[MAXDIMS], repeat, width; - int col_cnt, colNo; - Node *result; - char card[81], tform[16], nullKwd[9], tdimKwd[9]; - - if( *status ) return( *status ); - - FFLOCK; - if( ffiprs( infptr, 0, expr, MAXDIMS, &Info.datatype, &nelem, &naxis, - naxes, status ) ) { - - ffcprs(); - FFUNLOCK; - return( *status ); - } - if( nelem<0 ) { - constant = 1; - nelem = -nelem; - } else - constant = 0; - - /* Case (1): If column exists put it there */ - - colNo = 0; - if( ffgcno( outfptr, CASEINSEN, parName, &colNo, status )==COL_NOT_FOUND ) { - - /* Output column doesn't exist. Test for keyword. */ - - /* Case (2): Does parName indicate result should be put into keyword */ - - *status = 0; - if( parName[0]=='#' ) { - if( ! constant ) { - ffcprs(); - ffpmsg( "Cannot put tabular result into keyword (ffcalc)" ); - FFUNLOCK; - return( *status = PARSE_BAD_TYPE ); - } - parName++; /* Advance past '#' */ - if ( (fits_strcasecmp(parName,"HISTORY") == 0 || fits_strcasecmp(parName,"COMMENT") == 0) && - Info.datatype != TSTRING ) { - ffcprs(); - ffpmsg( "HISTORY and COMMENT values must be strings (ffcalc)" ); - FFUNLOCK; - return( *status = PARSE_BAD_TYPE ); - } - - } else if( constant ) { - - /* Case (3): Does a keyword named parName already exist */ - - if( ffgcrd( outfptr, parName, card, status )==KEY_NO_EXIST ) { - colNo = -1; - } else if( *status ) { - ffcprs(); - FFUNLOCK; - return( *status ); - } - - } else - colNo = -1; - - if( colNo<0 ) { - - /* Case (4): Create new column */ - - *status = 0; - ffgncl( outfptr, &colNo, status ); - colNo++; - if( parInfo==NULL || *parInfo=='\0' ) { - /* Figure out best default column type */ - if( gParse.hdutype==BINARY_TBL ) { - sprintf(tform,"%ld",nelem); - switch( Info.datatype ) { - case TLOGICAL: strcat(tform,"L"); break; - case TLONG: strcat(tform,"J"); break; - case TDOUBLE: strcat(tform,"D"); break; - case TSTRING: strcat(tform,"A"); break; - case TBIT: strcat(tform,"X"); break; - case TLONGLONG: strcat(tform,"K"); break; - } - } else { - switch( Info.datatype ) { - case TLOGICAL: - ffcprs(); - ffpmsg("Cannot create LOGICAL column in ASCII table"); - FFUNLOCK; - return( *status = NOT_BTABLE ); - case TLONG: strcpy(tform,"I11"); break; - case TDOUBLE: strcpy(tform,"D23.15"); break; - case TSTRING: - case TBIT: sprintf(tform,"A%ld",nelem); break; - } - } - parInfo = tform; - } else if( !(isdigit((int) *parInfo)) && gParse.hdutype==BINARY_TBL ) { - if( Info.datatype==TBIT && *parInfo=='B' ) - nelem = (nelem+7)/8; - sprintf(tform,"%ld%s",nelem,parInfo); - parInfo = tform; - } - fficol( outfptr, colNo, parName, parInfo, status ); - if( naxis>1 ) - ffptdm( outfptr, colNo, naxis, naxes, status ); - - /* Setup TNULLn keyword in case NULLs are encountered */ - - ffkeyn("TNULL", colNo, nullKwd, status); - if( ffgcrd( outfptr, nullKwd, card, status )==KEY_NO_EXIST ) { - *status = 0; - if( gParse.hdutype==BINARY_TBL ) { - LONGLONG nullVal=0; - fits_binary_tform( parInfo, &typecode, &repeat, &width, status ); - if( typecode==TBYTE ) - nullVal = UCHAR_MAX; - else if( typecode==TSHORT ) - nullVal = SHRT_MIN; - else if( typecode==TINT ) - nullVal = INT_MIN; - else if( typecode==TLONG ) - nullVal = LONG_MIN; - else if( typecode==TLONGLONG ) - nullVal = LONGLONG_MIN; - - if( nullVal ) { - ffpkyj( outfptr, nullKwd, nullVal, "Null value", status ); - fits_set_btblnull( outfptr, colNo, nullVal, status ); - newNullKwd = 1; - } - } else if( gParse.hdutype==ASCII_TBL ) { - ffpkys( outfptr, nullKwd, "NULL", "Null value string", status ); - fits_set_atblnull( outfptr, colNo, "NULL", status ); - newNullKwd = 1; - } - } - - } - - } else if( *status ) { - ffcprs(); - FFUNLOCK; - return( *status ); - } else { - - /********************************************************/ - /* Check if a TDIM keyword should be written/updated. */ - /********************************************************/ - - ffkeyn("TDIM", colNo, tdimKwd, status); - ffgcrd( outfptr, tdimKwd, card, status ); - if( *status==0 ) { - /* TDIM exists, so update it with result's dimension */ - ffptdm( outfptr, colNo, naxis, naxes, status ); - } else if( *status==KEY_NO_EXIST ) { - /* TDIM does not exist, so clear error stack and */ - /* write a TDIM only if result is multi-dimensional */ - *status = 0; - ffcmsg(); - if( naxis>1 ) - ffptdm( outfptr, colNo, naxis, naxes, status ); - } - if( *status ) { - /* Either some other error happened in ffgcrd */ - /* or one happened in ffptdm */ - ffcprs(); - FFUNLOCK; - return( *status ); - } - - } - - if( colNo>0 ) { - - /* Output column exists (now)... put results into it */ - - int anyNull = 0; - int nPerLp, i; - long totaln; - - ffgkyj(infptr, "NAXIS2", &totaln, 0, status); - - /*************************************/ - /* Create new iterator Output Column */ - /*************************************/ - - col_cnt = gParse.nCols; - if( allocateCol( col_cnt, status ) ) { - ffcprs(); - FFUNLOCK; - return( *status ); - } - - fits_iter_set_by_num( gParse.colData+col_cnt, outfptr, - colNo, 0, OutputCol ); - gParse.nCols++; - - for( i=0; i= 10) && (nRngs == 1) && - (start[0] == 1) && (end[0] == totaln)) - nPerLp = 0; - else - nPerLp = Info.maxRows; - - if( ffiter( gParse.nCols, gParse.colData, start[i]-1, - nPerLp, parse_data, (void*)&Info, status ) == -1 ) - *status = 0; - else if( *status ) { - ffcprs(); - FFUNLOCK; - return( *status ); - } - if( Info.anyNull ) anyNull = 1; - } - - if( newNullKwd && !anyNull ) { - ffdkey( outfptr, nullKwd, status ); - } - - } else { - - /* Put constant result into keyword */ - - result = gParse.Nodes + gParse.resultNode; - switch( Info.datatype ) { - case TDOUBLE: - ffukyd( outfptr, parName, result->value.data.dbl, 15, - parInfo, status ); - break; - case TLONG: - ffukyj( outfptr, parName, result->value.data.lng, parInfo, status ); - break; - case TLOGICAL: - ffukyl( outfptr, parName, result->value.data.log, parInfo, status ); - break; - case TBIT: - case TSTRING: - if (fits_strcasecmp(parName,"HISTORY") == 0) { - ffphis( outfptr, result->value.data.str, status); - } else if (fits_strcasecmp(parName,"COMMENT") == 0) { - ffpcom( outfptr, result->value.data.str, status); - } else { - ffukys( outfptr, parName, result->value.data.str, parInfo, status ); - } - break; - } - } - - ffcprs(); - FFUNLOCK; - return( *status ); -} - -/*--------------------------------------------------------------------------*/ -int fftexp( fitsfile *fptr, /* I - Input FITS file */ - char *expr, /* I - Arithmetic expression */ - int maxdim, /* I - Max Dimension of naxes */ - int *datatype, /* O - Data type of result */ - long *nelem, /* O - Vector length of result */ - int *naxis, /* O - # of dimensions of result */ - long *naxes, /* O - Size of each dimension */ - int *status ) /* O - Error status */ -/* */ -/* Evaluate the given expression and return information on the result. */ -/*--------------------------------------------------------------------------*/ -{ - FFLOCK; - ffiprs( fptr, 0, expr, maxdim, datatype, nelem, naxis, naxes, status ); - ffcprs(); - FFUNLOCK; - return( *status ); -} - -/*--------------------------------------------------------------------------*/ -int ffiprs( fitsfile *fptr, /* I - Input FITS file */ - int compressed, /* I - Is FITS file hkunexpanded? */ - char *expr, /* I - Arithmetic expression */ - int maxdim, /* I - Max Dimension of naxes */ - int *datatype, /* O - Data type of result */ - long *nelem, /* O - Vector length of result */ - int *naxis, /* O - # of dimensions of result */ - long *naxes, /* O - Size of each dimension */ - int *status ) /* O - Error status */ -/* */ -/* Initialize the parser and determine what type of result the expression */ -/* produces. */ -/*--------------------------------------------------------------------------*/ -{ - Node *result; - int i,lexpr, tstatus = 0; - int xaxis, bitpix; - long xaxes[9]; - static iteratorCol dmyCol; - - if( *status ) return( *status ); - - /* make sure all internal structures for this HDU are current */ - if ( ffrdef(fptr, status) ) return(*status); - - /* Initialize the Parser structure */ - - gParse.def_fptr = fptr; - gParse.compressed = compressed; - gParse.nCols = 0; - gParse.colData = NULL; - gParse.varData = NULL; - gParse.getData = find_column; - gParse.loadData = load_column; - gParse.Nodes = NULL; - gParse.nNodesAlloc= 0; - gParse.nNodes = 0; - gParse.hdutype = 0; - gParse.status = 0; - - fits_get_hdu_type(fptr, &gParse.hdutype, status ); - - if (gParse.hdutype == IMAGE_HDU) { - - fits_get_img_param(fptr, 9, &bitpix, &xaxis, xaxes, status); - if (*status) { - ffpmsg("ffiprs: unable to get image dimensions"); - return( *status ); - } - gParse.totalRows = xaxis > 0 ? 1 : 0; - for (i = 0; i < xaxis; ++i) - gParse.totalRows *= xaxes[i]; - if (DEBUG_PIXFILTER) - printf("naxis=%d, gParse.totalRows=%ld\n", xaxis, gParse.totalRows); - } - else if( ffgkyj(fptr, "NAXIS2", &gParse.totalRows, 0, &tstatus) ) - { - /* this might be a 1D or null image with no NAXIS2 keyword */ - gParse.totalRows = 0; - } - - - /* Copy expression into parser... read from file if necessary */ - - - if( expr[0]=='@' ) { - if( ffimport_file( expr+1, &gParse.expr, status ) ) return( *status ); - lexpr = strlen(gParse.expr); - } else { - lexpr = strlen(expr); - gParse.expr = (char*)malloc( (2+lexpr)*sizeof(char)); - strcpy(gParse.expr,expr); - } - strcat(gParse.expr + lexpr,"\n"); - gParse.index = 0; - gParse.is_eobuf = 0; - - /* Parse the expression, building the Nodes and determing */ - /* which columns are needed and what data type is returned */ - - ffrestart(NULL); - if( ffparse() ) { - return( *status = PARSE_SYNTAX_ERR ); - } - /* Check results */ - - *status = gParse.status; - if( *status ) return(*status); - - if( !gParse.nNodes ) { - ffpmsg("Blank expression"); - return( *status = PARSE_SYNTAX_ERR ); - } - if( !gParse.nCols ) { - dmyCol.fptr = fptr; /* This allows iterator to know value of */ - gParse.colData = &dmyCol; /* fptr when no columns are referenced */ - } - - result = gParse.Nodes + gParse.resultNode; - - *naxis = result->value.naxis; - *nelem = result->value.nelem; - for( i=0; i<*naxis && ivalue.naxes[i]; - - switch( result->type ) { - case BOOLEAN: - *datatype = TLOGICAL; - break; - case LONG: - *datatype = TLONG; - break; - case DOUBLE: - *datatype = TDOUBLE; - break; - case BITSTR: - *datatype = TBIT; - break; - case STRING: - *datatype = TSTRING; - break; - default: - *datatype = 0; - ffpmsg("Bad return data type"); - *status = gParse.status = PARSE_BAD_TYPE; - break; - } - gParse.datatype = *datatype; - FREE(gParse.expr); - - if( result->operation==CONST_OP ) *nelem = - *nelem; - return(*status); -} - -/*--------------------------------------------------------------------------*/ -void ffcprs( void ) /* No parameters */ -/* */ -/* Clear the parser, making it ready to accept a new expression. */ -/*--------------------------------------------------------------------------*/ -{ - int col, node, i; - - if( gParse.nCols > 0 ) { - FREE( gParse.colData ); - for( col=0; col 0 ) { - node = gParse.nNodes; - while( node-- ) { - if( gParse.Nodes[node].operation==gtifilt_fct ) { - i = gParse.Nodes[node].SubNodes[0]; - if (gParse.Nodes[ i ].value.data.ptr) - FREE( gParse.Nodes[ i ].value.data.ptr ); - } - else if( gParse.Nodes[node].operation==regfilt_fct ) { - i = gParse.Nodes[node].SubNodes[0]; - fits_free_region( (SAORegion *)gParse.Nodes[ i ].value.data.ptr ); - } - } - gParse.nNodes = 0; - } - if( gParse.Nodes ) free( gParse.Nodes ); - gParse.Nodes = NULL; - - gParse.hdutype = ANY_HDU; - gParse.pixFilter = 0; -} - -/*---------------------------------------------------------------------------*/ -int parse_data( long totalrows, /* I - Total rows to be processed */ - long offset, /* I - Number of rows skipped at start*/ - long firstrow, /* I - First row of this iteration */ - long nrows, /* I - Number of rows in this iter */ - int nCols, /* I - Number of columns in use */ - iteratorCol *colData, /* IO- Column information/data */ - void *userPtr ) /* I - Data handling instructions */ -/* */ -/* Iterator work function which calls the parser and copies the results */ -/* into either an OutputCol or a data pointer supplied in the userPtr */ -/* structure. */ -/*---------------------------------------------------------------------------*/ -{ - int status, constant=0, anyNullThisTime=0; - long jj, kk, idx, remain, ntodo; - Node *result; - iteratorCol * outcol; - - /* declare variables static to preserve their values between calls */ - static void *Data, *Null; - static int datasize; - static long lastRow, repeat, resDataSize; - static LONGLONG jnull; - static parseInfo *userInfo; - static long zeros[4] = {0,0,0,0}; - - if (DEBUG_PIXFILTER) - printf("parse_data(total=%ld, offset=%ld, first=%ld, rows=%ld, cols=%d)\n", - totalrows, offset, firstrow, nrows, nCols); - /*--------------------------------------------------------*/ - /* Initialization procedures: execute on the first call */ - /*--------------------------------------------------------*/ - outcol = colData + (nCols - 1); - if (firstrow == offset+1) - { - userInfo = (parseInfo*)userPtr; - userInfo->anyNull = 0; - - if( userInfo->maxRows>0 ) - userInfo->maxRows = minvalue(totalrows,userInfo->maxRows); - else if( userInfo->maxRows<0 ) - userInfo->maxRows = totalrows; - else - userInfo->maxRows = nrows; - - lastRow = firstrow + userInfo->maxRows - 1; - - if( userInfo->dataPtr==NULL ) { - - if( outcol->iotype == InputCol ) { - ffpmsg("Output column for parser results not found!"); - return( PARSE_NO_OUTPUT ); - } - /* Data gets set later */ - Null = outcol->array; - userInfo->datatype = outcol->datatype; - - /* Check for a TNULL/BLANK keyword for output column/image */ - - status = 0; - jnull = 0; - if (gParse.hdutype == IMAGE_HDU) { - if (gParse.pixFilter->blank) - jnull = (LONGLONG) gParse.pixFilter->blank; - } - else { - ffgknjj( outcol->fptr, "TNULL", outcol->colnum, - 1, &jnull, (int*)&jj, &status ); - - if( status==BAD_INTKEY ) { - /* Probably ASCII table with text TNULL keyword */ - switch( userInfo->datatype ) { - case TSHORT: jnull = (LONGLONG) SHRT_MIN; break; - case TINT: jnull = (LONGLONG) INT_MIN; break; - case TLONG: jnull = (LONGLONG) LONG_MIN; break; - } - } - } - repeat = outcol->repeat; -/* - if (DEBUG_PIXFILTER) - printf("parse_data: using null value %ld\n", jnull); -*/ - } else { - - Data = userInfo->dataPtr; - Null = (userInfo->nullPtr ? userInfo->nullPtr : zeros); - repeat = gParse.Nodes[gParse.resultNode].value.nelem; - - } - - /* Determine the size of each element of the returned result */ - - switch( userInfo->datatype ) { - case TBIT: /* Fall through to TBYTE */ - case TLOGICAL: /* Fall through to TBYTE */ - case TBYTE: datasize = sizeof(char); break; - case TSHORT: datasize = sizeof(short); break; - case TINT: datasize = sizeof(int); break; - case TLONG: datasize = sizeof(long); break; - case TLONGLONG: datasize = sizeof(LONGLONG); break; - case TFLOAT: datasize = sizeof(float); break; - case TDOUBLE: datasize = sizeof(double); break; - case TSTRING: datasize = sizeof(char*); break; - } - - /* Determine the size of each element of the calculated result */ - /* (only matters for numeric/logical data) */ - - switch( gParse.Nodes[gParse.resultNode].type ) { - case BOOLEAN: resDataSize = sizeof(char); break; - case LONG: resDataSize = sizeof(long); break; - case DOUBLE: resDataSize = sizeof(double); break; - } - } - - /*-------------------------------------------*/ - /* Main loop: process all the rows of data */ - /*-------------------------------------------*/ - - /* If writing to output column, set first element to appropriate */ - /* null value. If no NULLs encounter, zero out before returning. */ -/* - if (DEBUG_PIXFILTER) - printf("parse_data: using null value %ld\n", jnull); -*/ - - if( userInfo->dataPtr == NULL ) { - /* First, reset Data pointer to start of output array */ - Data = (char*) outcol->array + datasize; - - switch( userInfo->datatype ) { - case TLOGICAL: *(char *)Null = 'U'; break; - case TBYTE: *(char *)Null = (char )jnull; break; - case TSHORT: *(short *)Null = (short)jnull; break; - case TINT: *(int *)Null = (int )jnull; break; - case TLONG: *(long *)Null = (long )jnull; break; - case TLONGLONG: *(LONGLONG *)Null = (LONGLONG )jnull; break; - case TFLOAT: *(float *)Null = FLOATNULLVALUE; break; - case TDOUBLE: *(double*)Null = DOUBLENULLVALUE; break; - case TSTRING: (*(char **)Null)[0] = '\1'; - (*(char **)Null)[1] = '\0'; break; - } - } - - /* Alter nrows in case calling routine didn't want to do all rows */ - - nrows = minvalue(nrows,lastRow-firstrow+1); - - Setup_DataArrays( nCols, colData, firstrow, nrows ); - - /* Parser allocates arrays for each column and calculation it performs. */ - /* Limit number of rows processed during each pass to reduce memory */ - /* requirements... In most cases, iterator will limit rows to less */ - /* than 2500 rows per iteration, so this is really only relevant for */ - /* hk-compressed files which must be decompressed in memory and sent */ - /* whole to parse_data in a single iteration. */ - - remain = nrows; - while( remain ) { - ntodo = minvalue(remain,2500); - Evaluate_Parser ( firstrow, ntodo ); - if( gParse.status ) break; - - firstrow += ntodo; - remain -= ntodo; - - /* Copy results into data array */ - - result = gParse.Nodes + gParse.resultNode; - if( result->operation==CONST_OP ) constant = 1; - - switch( result->type ) { - - case BOOLEAN: - case LONG: - case DOUBLE: - if( constant ) { - char undef=0; - for( kk=0; kkvalue.data), - &undef, result->value.nelem /* 1 */, - userInfo->datatype, Null, - (char*)Data + (kk*repeat+jj)*datasize, - &anyNullThisTime, &gParse.status ); - } else { - if ( repeat == result->value.nelem ) { - ffcvtn( gParse.datatype, - result->value.data.ptr, - result->value.undef, - result->value.nelem*ntodo, - userInfo->datatype, Null, Data, - &anyNullThisTime, &gParse.status ); - } else if( result->value.nelem == 1 ) { - for( kk=0; kkvalue.data.ptr + kk*resDataSize, - (char*)result->value.undef + kk, - 1, userInfo->datatype, Null, - (char*)Data + (kk*repeat+jj)*datasize, - &anyNullThisTime, &gParse.status ); - } - } else { - int nCopy; - nCopy = minvalue( repeat, result->value.nelem ); - for( kk=0; kkvalue.data.ptr - + kk*result->value.nelem*resDataSize, - (char*)result->value.undef - + kk*result->value.nelem, - nCopy, userInfo->datatype, Null, - (char*)Data + (kk*repeat)*datasize, - &anyNullThisTime, &gParse.status ); - if( nCopy < repeat ) { - memset( (char*)Data + (kk*repeat+nCopy)*datasize, - 0, (repeat-nCopy)*datasize); - } - } - - } - if( result->operation>0 ) { - FREE( result->value.data.ptr ); - } - } - if( gParse.status==OVERFLOW_ERR ) { - gParse.status = NUM_OVERFLOW; - ffpmsg("Numerical overflow while converting expression to necessary datatype"); - } - break; - - case BITSTR: - switch( userInfo->datatype ) { - case TBYTE: - idx = -1; - for( kk=0; kkvalue.nelem; jj++ ) { - if( jj%8 == 0 ) - ((char*)Data)[++idx] = 0; - if( constant ) { - if( result->value.data.str[jj]=='1' ) - ((char*)Data)[idx] |= 128>>(jj%8); - } else { - if( result->value.data.strptr[kk][jj]=='1' ) - ((char*)Data)[idx] |= 128>>(jj%8); - } - } - } - break; - case TBIT: - case TLOGICAL: - if( constant ) { - for( kk=0; kkvalue.nelem; jj++ ) { - ((char*)Data)[ jj+kk*result->value.nelem ] = - ( result->value.data.str[jj]=='1' ); - } - } else { - for( kk=0; kkvalue.nelem; jj++ ) { - ((char*)Data)[ jj+kk*result->value.nelem ] = - ( result->value.data.strptr[kk][jj]=='1' ); - } - } - break; - case TSTRING: - if( constant ) { - for( jj=0; jjvalue.data.str ); - } - } else { - for( jj=0; jjvalue.data.strptr[jj] ); - } - } - break; - default: - ffpmsg("Cannot convert bit expression to desired type."); - gParse.status = PARSE_BAD_TYPE; - break; - } - if( result->operation>0 ) { - FREE( result->value.data.strptr[0] ); - FREE( result->value.data.strptr ); - } - break; - - case STRING: - if( userInfo->datatype==TSTRING ) { - if( constant ) { - for( jj=0; jjvalue.data.str ); - } else { - for( jj=0; jjvalue.undef[jj] ) { - anyNullThisTime = 1; - strcpy( ((char**)Data)[jj], - *(char **)Null ); - } else { - strcpy( ((char**)Data)[jj], - result->value.data.strptr[jj] ); - } - } - } else { - ffpmsg("Cannot convert string expression to desired type."); - gParse.status = PARSE_BAD_TYPE; - } - if( result->operation>0 ) { - FREE( result->value.data.strptr[0] ); - FREE( result->value.data.strptr ); - } - break; - } - - if( gParse.status ) break; - - /* Increment Data to point to where the next block should go */ - - if( result->type==BITSTR && userInfo->datatype==TBYTE ) - Data = (char*)Data - + datasize * ( (result->value.nelem+7)/8 ) * ntodo; - else if( result->type==STRING ) - Data = (char*)Data + datasize * ntodo; - else - Data = (char*)Data + datasize * ntodo * repeat; - } - - /* If no NULLs encountered during this pass, set Null value to */ - /* zero to make the writing of the output column data faster */ - - if( anyNullThisTime ) - userInfo->anyNull = 1; - else if( userInfo->dataPtr == NULL ) { - if( userInfo->datatype == TSTRING ) - memcpy( *(char **)Null, zeros, 2 ); - else - memcpy( Null, zeros, datasize ); - } - - /*-------------------------------------------------------*/ - /* Clean up procedures: after processing all the rows */ - /*-------------------------------------------------------*/ - - /* if the calling routine specified that only a limited number */ - /* of rows in the table should be processed, return a value of -1 */ - /* once all the rows have been done, if no other error occurred. */ - - if (gParse.hdutype != IMAGE_HDU && firstrow - 1 == lastRow) { - if (!gParse.status && userInfo->maxRowsiotype == OutputCol ) continue; - - nelem = varData->nelem; - len = nelem * nRows; - - switch ( varData->type ) { - - case BITSTR: - /* No need for UNDEF array, but must make string DATA array */ - len = (nelem+1)*nRows; /* Count '\0' */ - bitStrs = (char**)varData->data; - if( bitStrs ) FREE( bitStrs[0] ); - free( bitStrs ); - bitStrs = (char**)malloc( nRows*sizeof(char*) ); - if( bitStrs==NULL ) { - varData->data = varData->undef = NULL; - gParse.status = MEMORY_ALLOCATION; - break; - } - bitStrs[0] = (char*)malloc( len*sizeof(char) ); - if( bitStrs[0]==NULL ) { - free( bitStrs ); - varData->data = varData->undef = NULL; - gParse.status = MEMORY_ALLOCATION; - break; - } - - for( row=0; rowarray)[idx] & (1<<(7-len%8)) ) - bitStrs[row][len] = '1'; - else - bitStrs[row][len] = '0'; - if( len%8==7 ) idx++; - } - bitStrs[row][len] = '\0'; - } - varData->undef = (char*)bitStrs; - varData->data = (char*)bitStrs; - break; - - case STRING: - sptr = (char**)icol->array; - if (varData->undef) - free( varData->undef ); - varData->undef = (char*)malloc( nRows*sizeof(char) ); - if( varData->undef==NULL ) { - gParse.status = MEMORY_ALLOCATION; - break; - } - row = nRows; - while( row-- ) - varData->undef[row] = - ( **sptr != '\0' && FSTRCMP( sptr[0], sptr[row+1] )==0 ); - varData->data = sptr + 1; - break; - - case BOOLEAN: - barray = (char*)icol->array; - if (varData->undef) - free( varData->undef ); - varData->undef = (char*)malloc( len*sizeof(char) ); - if( varData->undef==NULL ) { - gParse.status = MEMORY_ALLOCATION; - break; - } - while( len-- ) { - varData->undef[len] = - ( barray[0]!=0 && barray[0]==barray[len+1] ); - } - varData->data = barray + 1; - break; - - case LONG: - iarray = (long*)icol->array; - if (varData->undef) - free( varData->undef ); - varData->undef = (char*)malloc( len*sizeof(char) ); - if( varData->undef==NULL ) { - gParse.status = MEMORY_ALLOCATION; - break; - } - while( len-- ) { - varData->undef[len] = - ( iarray[0]!=0L && iarray[0]==iarray[len+1] ); - } - varData->data = iarray + 1; - break; - - case DOUBLE: - rarray = (double*)icol->array; - if (varData->undef) - free( varData->undef ); - varData->undef = (char*)malloc( len*sizeof(char) ); - if( varData->undef==NULL ) { - gParse.status = MEMORY_ALLOCATION; - break; - } - while( len-- ) { - varData->undef[len] = - ( rarray[0]!=0.0 && rarray[0]==rarray[len+1]); - } - varData->data = rarray + 1; - break; - - default: - sprintf(msg, "SetupDataArrays, unhandled type %d\n", - varData->type); - ffpmsg(msg); - } - - if( gParse.status ) { /* Deallocate NULL arrays of previous columns */ - while( i-- ) { - varData = gParse.varData + i; - if( varData->type==BITSTR ) - FREE( ((char**)varData->data)[0] ); - FREE( varData->undef ); - varData->undef = NULL; - } - return; - } - } -} - -/*--------------------------------------------------------------------------*/ -int ffcvtn( int inputType, /* I - Data type of input array */ - void *input, /* I - Input array of type inputType */ - char *undef, /* I - Array of flags indicating UNDEF elems */ - long ntodo, /* I - Number of elements to process */ - int outputType, /* I - Data type of output array */ - void *nulval, /* I - Ptr to value to use for UNDEF elements */ - void *output, /* O - Output array of type outputType */ - int *anynull, /* O - Any nulls flagged? */ - int *status ) /* O - Error status */ -/* */ -/* Convert an array of any input data type to an array of any output */ -/* data type, using an array of UNDEF flags to assign nulvals to */ -/*--------------------------------------------------------------------------*/ -{ - long i; - - switch( outputType ) { - - case TLOGICAL: - switch( inputType ) { - case TLOGICAL: - case TBYTE: - for( i=0; i UCHAR_MAX ) { - *status = OVERFLOW_ERR; - ((unsigned char*)output)[i] = UCHAR_MAX; - } else - ((unsigned char*)output)[i] = - (unsigned char) ((long*)input)[i]; - } - } - return( *status ); - case TFLOAT: - fffr4i1((float*)input,ntodo,1.,0.,0,0,NULL,NULL, - (unsigned char*)output,status); - break; - case TDOUBLE: - fffr8i1((double*)input,ntodo,1.,0.,0,0,NULL,NULL, - (unsigned char*)output,status); - break; - default: - *status = BAD_DATATYPE; - break; - } - for(i=0;i SHRT_MAX ) { - *status = OVERFLOW_ERR; - ((short*)output)[i] = SHRT_MAX; - } else - ((short*)output)[i] = (short) ((long*)input)[i]; - } - } - return( *status ); - case TFLOAT: - fffr4i2((float*)input,ntodo,1.,0.,0,0,NULL,NULL, - (short*)output,status); - break; - case TDOUBLE: - fffr8i2((double*)input,ntodo,1.,0.,0,0,NULL,NULL, - (short*)output,status); - break; - default: - *status = BAD_DATATYPE; - break; - } - for(i=0;i=0 ) { - found[parNo] = 1; /* Flag this parameter as found */ - switch( gParse.colData[parNo].datatype ) { - case TLONG: - ffgcvj( fptr, gParse.valCol, row, 1L, 1L, - ((long*)gParse.colData[parNo].array)[0], - ((long*)gParse.colData[parNo].array)+currelem, - &anynul, status ); - break; - case TDOUBLE: - ffgcvd( fptr, gParse.valCol, row, 1L, 1L, - ((double*)gParse.colData[parNo].array)[0], - ((double*)gParse.colData[parNo].array)+currelem, - &anynul, status ); - break; - case TSTRING: - ffgcvs( fptr, gParse.valCol, row, 1L, 1L, - ((char**)gParse.colData[parNo].array)[0], - ((char**)gParse.colData[parNo].array)+currelem, - &anynul, status ); - break; - } - if( *status ) return( *status ); - } - } - - if( currelemoperation==CONST_OP ) { - - if( result->value.data.log ) { - *(long*)userPtr = firstrow; - return( -1 ); - } - - } else { - - for( idx=0; idxvalue.data.logptr[idx] && !result->value.undef[idx] ) { - *(long*)userPtr = firstrow + idx; - return( -1 ); - } - } - } - - return( gParse.status ); -} - - -static int set_image_col_types (fitsfile * fptr, const char * name, int bitpix, - DataInfo * varInfo, iteratorCol *colIter) { - - int istatus; - double tscale, tzero; - char temp[80]; - - switch (bitpix) { - case BYTE_IMG: - case SHORT_IMG: - case LONG_IMG: - istatus = 0; - if (fits_read_key(fptr, TDOUBLE, "BZERO", &tzero, NULL, &istatus)) - tzero = 0.0; - - istatus = 0; - if (fits_read_key(fptr, TDOUBLE, "BSCALE", &tscale, NULL, &istatus)) - tscale = 1.0; - - if (tscale == 1.0 && (tzero == 0.0 || tzero == 32768.0 )) { - varInfo->type = LONG; - colIter->datatype = TLONG; - } - else { - varInfo->type = DOUBLE; - colIter->datatype = TDOUBLE; - if (DEBUG_PIXFILTER) - printf("use DOUBLE for %s with BSCALE=%g/BZERO=%g\n", - name, tscale, tzero); - } - break; - - case LONGLONG_IMG: - case FLOAT_IMG: - case DOUBLE_IMG: - varInfo->type = DOUBLE; - colIter->datatype = TDOUBLE; - break; - default: - sprintf(temp, "set_image_col_types: unrecognized image bitpix [%d]\n", - bitpix); - ffpmsg(temp); - return gParse.status = PARSE_BAD_TYPE; - } - return 0; -} - - -/************************************************************************* - - Functions used by the evaluator to access FITS data - (find_column, find_keywd, allocateCol, load_column) - - *************************************************************************/ - -static int find_column( char *colName, void *itslval ) -{ - FFSTYPE *thelval = (FFSTYPE*)itslval; - int col_cnt, status; - int colnum, typecode, type; - long repeat, width; - fitsfile *fptr; - char temp[80]; - double tzero,tscale; - int istatus; - DataInfo *varInfo; - iteratorCol *colIter; - -if (DEBUG_PIXFILTER) - printf("find_column(%s)\n", colName); - - if( *colName == '#' ) - return( find_keywd( colName + 1, itslval ) ); - - fptr = gParse.def_fptr; - - status = 0; - col_cnt = gParse.nCols; - -if (gParse.hdutype == IMAGE_HDU) { - int i; - if (!gParse.pixFilter) { - gParse.status = COL_NOT_FOUND; - ffpmsg("find_column: IMAGE_HDU but no PixelFilter"); - return pERROR; - } - - colnum = -1; - for (i = 0; i < gParse.pixFilter->count; ++i) { - if (!fits_strcasecmp(colName, gParse.pixFilter->tag[i])) - colnum = i; - } - if (colnum < 0) { - sprintf(temp, "find_column: PixelFilter tag %s not found", colName); - ffpmsg(temp); - gParse.status = COL_NOT_FOUND; - return pERROR; - } - - if( allocateCol( col_cnt, &gParse.status ) ) return pERROR; - - varInfo = gParse.varData + col_cnt; - colIter = gParse.colData + col_cnt; - - fptr = gParse.pixFilter->ifptr[colnum]; - fits_get_img_param(fptr, - MAXDIMS, - &typecode, /* actually bitpix */ - &varInfo->naxis, - &varInfo->naxes[0], - &status); - varInfo->nelem = 1; - type = COLUMN; - if (set_image_col_types(fptr, colName, typecode, varInfo, colIter)) - return pERROR; - colIter->fptr = fptr; - colIter->iotype = InputCol; -} -else { /* HDU holds a table */ - if( gParse.compressed ) - colnum = gParse.valCol; - else - if( fits_get_colnum( fptr, CASEINSEN, colName, &colnum, &status ) ) { - if( status == COL_NOT_FOUND ) { - type = find_keywd( colName, itslval ); - if( type != pERROR ) ffcmsg(); - return( type ); - } - gParse.status = status; - return pERROR; - } - - if( fits_get_coltype( fptr, colnum, &typecode, - &repeat, &width, &status ) ) { - gParse.status = status; - return pERROR; - } - - if( allocateCol( col_cnt, &gParse.status ) ) return pERROR; - - varInfo = gParse.varData + col_cnt; - colIter = gParse.colData + col_cnt; - - fits_iter_set_by_num( colIter, fptr, colnum, 0, InputCol ); -} - - /* Make sure we don't overflow variable name array */ - strncpy(varInfo->name,colName,MAXVARNAME); - varInfo->name[MAXVARNAME] = '\0'; - -if (gParse.hdutype != IMAGE_HDU) { - switch( typecode ) { - case TBIT: - varInfo->type = BITSTR; - colIter->datatype = TBYTE; - type = BITCOL; - break; - case TBYTE: - case TSHORT: - case TLONG: - /* The datatype of column with TZERO and TSCALE keywords might be - float or double. - */ - sprintf(temp,"TZERO%d",colnum); - istatus = 0; - if(fits_read_key(fptr,TDOUBLE,temp,&tzero,NULL,&istatus)) { - tzero = 0.0; - } - sprintf(temp,"TSCAL%d",colnum); - istatus = 0; - if(fits_read_key(fptr,TDOUBLE,temp,&tscale,NULL,&istatus)) { - tscale = 1.0; - } - if (tscale == 1.0 && (tzero == 0.0 || tzero == 32768.0 )) { - varInfo->type = LONG; - colIter->datatype = TLONG; -/* Reading an unsigned long column as a long can cause overflow errors. - Treat the column as a double instead. - } else if (tscale == 1.0 && tzero == 2147483648.0 ) { - varInfo->type = LONG; - colIter->datatype = TULONG; - */ - - } - else { - varInfo->type = DOUBLE; - colIter->datatype = TDOUBLE; - } - type = COLUMN; - break; -/* - For now, treat 8-byte integer columns as type double. - This can lose precision, so the better long term solution - will be to add support for TLONGLONG as a separate datatype. -*/ - case TLONGLONG: - case TFLOAT: - case TDOUBLE: - varInfo->type = DOUBLE; - colIter->datatype = TDOUBLE; - type = COLUMN; - break; - case TLOGICAL: - varInfo->type = BOOLEAN; - colIter->datatype = TLOGICAL; - type = BCOLUMN; - break; - case TSTRING: - varInfo->type = STRING; - colIter->datatype = TSTRING; - type = SCOLUMN; - if ( width >= MAX_STRLEN ) { - sprintf(temp, "column %d is wider than maximum %d characters", - colnum, MAX_STRLEN-1); - ffpmsg(temp); - gParse.status = PARSE_LRG_VECTOR; - return pERROR; - } - if( gParse.hdutype == ASCII_TBL ) repeat = width; - break; - default: - if (typecode < 0) { - sprintf(temp, "variable-length array columns are not supported. typecode = %d", typecode); - ffpmsg(temp); - } - gParse.status = PARSE_BAD_TYPE; - return pERROR; - } - varInfo->nelem = repeat; - if( repeat>1 && typecode!=TSTRING ) { - if( fits_read_tdim( fptr, colnum, MAXDIMS, - &varInfo->naxis, - &varInfo->naxes[0], &status ) - ) { - gParse.status = status; - return pERROR; - } - } else { - varInfo->naxis = 1; - varInfo->naxes[0] = 1; - } -} - gParse.nCols++; - thelval->lng = col_cnt; - - return( type ); -} - -static int find_keywd(char *keyname, void *itslval ) -{ - FFSTYPE *thelval = (FFSTYPE*)itslval; - int status, type; - char keyvalue[FLEN_VALUE], dtype; - fitsfile *fptr; - double rval; - int bval; - long ival; - - status = 0; - fptr = gParse.def_fptr; - if( fits_read_keyword( fptr, keyname, keyvalue, NULL, &status ) ) { - if( status == KEY_NO_EXIST ) { - /* Do this since ffgkey doesn't put an error message on stack */ - sprintf(keyvalue, "ffgkey could not find keyword: %s",keyname); - ffpmsg(keyvalue); - } - gParse.status = status; - return( pERROR ); - } - - if( fits_get_keytype( keyvalue, &dtype, &status ) ) { - gParse.status = status; - return( pERROR ); - } - - switch( dtype ) { - case 'C': - fits_read_key_str( fptr, keyname, keyvalue, NULL, &status ); - type = STRING; - strcpy( thelval->str , keyvalue ); - break; - case 'L': - fits_read_key_log( fptr, keyname, &bval, NULL, &status ); - type = BOOLEAN; - thelval->log = bval; - break; - case 'I': - fits_read_key_lng( fptr, keyname, &ival, NULL, &status ); - type = LONG; - thelval->lng = ival; - break; - case 'F': - fits_read_key_dbl( fptr, keyname, &rval, NULL, &status ); - type = DOUBLE; - thelval->dbl = rval; - break; - default: - type = pERROR; - break; - } - - if( status ) { - gParse.status=status; - return pERROR; - } - - return( type ); -} - -static int allocateCol( int nCol, int *status ) -{ - if( (nCol%25)==0 ) { - if( nCol ) { - gParse.colData = (iteratorCol*) realloc( gParse.colData, - (nCol+25)*sizeof(iteratorCol) ); - gParse.varData = (DataInfo *) realloc( gParse.varData, - (nCol+25)*sizeof(DataInfo) ); - } else { - gParse.colData = (iteratorCol*) malloc( 25*sizeof(iteratorCol) ); - gParse.varData = (DataInfo *) malloc( 25*sizeof(DataInfo) ); - } - if( gParse.colData == NULL - || gParse.varData == NULL ) { - if( gParse.colData ) free(gParse.colData); - if( gParse.varData ) free(gParse.varData); - gParse.colData = NULL; - gParse.varData = NULL; - return( *status = MEMORY_ALLOCATION ); - } - } - gParse.varData[nCol].data = NULL; - gParse.varData[nCol].undef = NULL; - return 0; -} - -static int load_column( int varNum, long fRow, long nRows, - void *data, char *undef ) -{ - iteratorCol *var = gParse.colData+varNum; - long nelem,nbytes,row,len,idx; - char **bitStrs, msg[80]; - unsigned char *bytes; - int status = 0, anynul; - - if (gParse.hdutype == IMAGE_HDU) { - /* This test would need to be on a per varNum basis to support - * cross HDU operations */ - fits_read_imgnull(var->fptr, var->datatype, fRow, nRows, - data, undef, &anynul, &status); - if (DEBUG_PIXFILTER) - printf("load_column: IMAGE_HDU fRow=%ld, nRows=%ld => %d\n", - fRow, nRows, status); - } else { - - nelem = nRows * var->repeat; - - switch( var->datatype ) { - case TBYTE: - nbytes = ((var->repeat+7)/8) * nRows; - bytes = (unsigned char *)malloc( nbytes * sizeof(char) ); - - ffgcvb(var->fptr, var->colnum, fRow, 1L, nbytes, - 0, bytes, &anynul, &status); - - nelem = var->repeat; - bitStrs = (char **)data; - for( row=0; rowfptr, var->colnum, fRow, 1L, nRows, - (char **)data, undef, &anynul, &status); - break; - case TLOGICAL: - ffgcfl(var->fptr, var->colnum, fRow, 1L, nelem, - (char *)data, undef, &anynul, &status); - break; - case TLONG: - ffgcfj(var->fptr, var->colnum, fRow, 1L, nelem, - (long *)data, undef, &anynul, &status); - break; - case TDOUBLE: - ffgcfd(var->fptr, var->colnum, fRow, 1L, nelem, - (double *)data, undef, &anynul, &status); - break; - default: - sprintf(msg,"load_column: unexpected datatype %d", var->datatype); - ffpmsg(msg); - } - } - if( status ) { - gParse.status = status; - return pERROR; - } - - return 0; -} - - -/*--------------------------------------------------------------------------*/ -int fits_pixel_filter (PixelFilter * filter, int * status) -/* Evaluate an expression using the data in the input FITS file(s) */ -/*--------------------------------------------------------------------------*/ -{ - parseInfo Info = { 0 }; - int naxis, bitpix; - long nelem, naxes[MAXDIMS]; - int col_cnt; - Node *result; - int datatype; - fitsfile * infptr; - fitsfile * outfptr; - char * DEFAULT_TAGS[] = { "X" }; - char msg[256]; - int writeBlankKwd = 0; /* write BLANK if any output nulls? */ - - DEBUG_PIXFILTER = getenv("DEBUG_PIXFILTER") ? 1 : 0; - - if (*status) - return (*status); - - FFLOCK; - if (!filter->tag || !filter->tag[0] || !filter->tag[0][0]) { - filter->tag = DEFAULT_TAGS; - if (DEBUG_PIXFILTER) - printf("using default tag '%s'\n", filter->tag[0]); - } - - infptr = filter->ifptr[0]; - outfptr = filter->ofptr; - gParse.pixFilter = filter; - - if (ffiprs(infptr, 0, filter->expression, MAXDIMS, - &Info.datatype, &nelem, &naxis, naxes, status)) { - goto CLEANUP; - } - - if (nelem < 0) { - nelem = -nelem; - } - - { - /* validate result type */ - const char * type = 0; - switch (Info.datatype) { - case TLOGICAL: type = "LOGICAL"; break; - case TLONG: type = "LONG"; break; - case TDOUBLE: type = "DOUBLE"; break; - case TSTRING: type = "STRING"; - *status = pERROR; - ffpmsg("pixel_filter: cannot have string image"); - case TBIT: type = "BIT"; - if (DEBUG_PIXFILTER) - printf("hmm, image from bits?\n"); - break; - default: type = "UNKNOWN?!"; - *status = pERROR; - ffpmsg("pixel_filter: unexpected result datatype"); - } - if (DEBUG_PIXFILTER) - printf("result type is %s [%d]\n", type, Info.datatype); - if (*status) - goto CLEANUP; - } - - if (fits_get_img_param(infptr, MAXDIMS, - &bitpix, &naxis, &naxes[0], status)) { - ffpmsg("pixel_filter: unable to read input image parameters"); - goto CLEANUP; - } - - if (DEBUG_PIXFILTER) - printf("input bitpix %d\n", bitpix); - - if (Info.datatype == TDOUBLE) { - /* for floating point expressions, set the default output image to - bitpix = -32 (float) unless the default is already a double */ - if (bitpix != DOUBLE_IMG) - bitpix = FLOAT_IMG; - } - - /* override output image bitpix if specified by caller */ - if (filter->bitpix) - bitpix = filter->bitpix; - if (DEBUG_PIXFILTER) - printf("output bitpix %d\n", bitpix); - - if (fits_create_img(outfptr, bitpix, naxis, naxes, status)) { - ffpmsg("pixel_filter: unable to create output image"); - goto CLEANUP; - } - - /* transfer keycards */ - { - int i, ncards, more; - if (fits_get_hdrspace(infptr, &ncards, &more, status)) { - ffpmsg("pixel_filter: unable to determine number of keycards"); - goto CLEANUP; - } - - for (i = 1; i <= ncards; ++i) { - - int keyclass; - char card[FLEN_CARD]; - - if (fits_read_record(infptr, i, card, status)) { - sprintf(msg, "pixel_filter: unable to read keycard %d", i); - ffpmsg(msg); - goto CLEANUP; - } - - keyclass = fits_get_keyclass(card); - if (keyclass == TYP_STRUC_KEY) { - /* output structure defined by fits_create_img */ - } - else if (keyclass == TYP_COMM_KEY && i < 12) { - /* assume this is one of the FITS standard comments */ - } - else if (keyclass == TYP_NULL_KEY && bitpix < 0) { - /* do not transfer BLANK to real output image */ - } - else if (keyclass == TYP_SCAL_KEY && bitpix < 0) { - /* do not transfer BZERO, BSCALE to real output image */ - } - else if (fits_write_record(outfptr, card, status)) { - sprintf(msg, "pixel_filter: unable to write keycard '%s' [%d]\n", - card, *status); - ffpmsg(msg); - goto CLEANUP; - } - } - } - - switch (bitpix) { - case BYTE_IMG: datatype = TLONG; Info.datatype = TBYTE; break; - case SHORT_IMG: datatype = TLONG; Info.datatype = TSHORT; break; - case LONG_IMG: datatype = TLONG; Info.datatype = TLONG; break; - case FLOAT_IMG: datatype = TDOUBLE; Info.datatype = TFLOAT; break; - case DOUBLE_IMG: datatype = TDOUBLE; Info.datatype = TDOUBLE; break; - - default: - sprintf(msg, "pixel_filter: unexpected output bitpix %d\n", bitpix); - ffpmsg(msg); - *status = pERROR; - goto CLEANUP; - } - - if (bitpix > 0) { /* arrange for NULLs in output */ - long nullVal = filter->blank; - if (!filter->blank) { - int tstatus = 0; - if (fits_read_key_lng(infptr, "BLANK", &nullVal, 0, &tstatus)) { - - writeBlankKwd = 1; - - if (bitpix == BYTE_IMG) - nullVal = UCHAR_MAX; - else if (bitpix == SHORT_IMG) - nullVal = SHRT_MIN; - else if (bitpix == LONG_IMG) - nullVal = LONG_MIN; - else - printf("unhandled positive output BITPIX %d\n", bitpix); - } - - filter->blank = nullVal; - } - - fits_set_imgnull(outfptr, filter->blank, status); - if (DEBUG_PIXFILTER) - printf("using blank %ld\n", nullVal); - - } - - if (!filter->keyword[0]) { - iteratorCol * colIter; - DataInfo * varInfo; - - /*************************************/ - /* Create new iterator Output Column */ - /*************************************/ - col_cnt = gParse.nCols; - if (allocateCol(col_cnt, status)) - goto CLEANUP; - gParse.nCols++; - - colIter = &gParse.colData[col_cnt]; - colIter->fptr = filter->ofptr; - colIter->iotype = OutputCol; - varInfo = &gParse.varData[col_cnt]; - set_image_col_types(colIter->fptr, "CREATED", bitpix, varInfo, colIter); - - Info.maxRows = -1; - - if (ffiter(gParse.nCols, gParse.colData, 0, - 0, parse_data, &Info, status) == -1) - *status = 0; - else if (*status) - goto CLEANUP; - - if (Info.anyNull) { - if (writeBlankKwd) { - fits_update_key_lng(outfptr, "BLANK", filter->blank, "NULL pixel value", status); - if (*status) - ffpmsg("pixel_filter: unable to write BLANK keyword"); - if (DEBUG_PIXFILTER) { - printf("output has NULLs\n"); - printf("wrote blank [%d]\n", *status); - } - } - } - else if (bitpix > 0) /* never used a null */ - if (fits_set_imgnull(outfptr, -1234554321, status)) - ffpmsg("pixel_filter: unable to reset imgnull"); - } - else { - - /* Put constant result into keyword */ - char * parName = filter->keyword; - char * parInfo = filter->comment; - - result = gParse.Nodes + gParse.resultNode; - switch (Info.datatype) { - case TDOUBLE: - ffukyd(outfptr, parName, result->value.data.dbl, 15, parInfo, status); - break; - case TLONG: - ffukyj(outfptr, parName, result->value.data.lng, parInfo, status); - break; - case TLOGICAL: - ffukyl(outfptr, parName, result->value.data.log, parInfo, status); - break; - case TBIT: - case TSTRING: - ffukys(outfptr, parName, result->value.data.str, parInfo, status); - break; - default: - sprintf(msg, "pixel_filter: unexpected constant result type [%d]\n", - Info.datatype); - ffpmsg(msg); - } - } - -CLEANUP: - ffcprs(); - FFUNLOCK; - return (*status); -} diff --git a/src/external/OpenGR/3rdparty/cfitsio/eval_l.c b/src/external/OpenGR/3rdparty/cfitsio/eval_l.c deleted file mode 100644 index 4beab08e0..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/eval_l.c +++ /dev/null @@ -1,2446 +0,0 @@ - -#line 3 "" - -#define FF_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define FLEX_SCANNER -#define FF_FLEX_MAJOR_VERSION 2 -#define FF_FLEX_MINOR_VERSION 5 -#define FF_FLEX_SUBMINOR_VERSION 35 -#if FF_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include -#include -#include -#include - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have . Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; -#endif /* ! C99 */ - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#endif /* ! FLEXINT_H */ - -#ifdef __cplusplus - -/* The "const" storage-class-modifier is valid. */ -#define FF_USE_CONST - -#else /* ! __cplusplus */ - -/* C99 requires __STDC__ to be defined as 1. */ -#if defined (__STDC__) - -#define FF_USE_CONST - -#endif /* defined (__STDC__) */ -#endif /* ! __cplusplus */ - -#ifdef FF_USE_CONST -#define ffconst const -#else -#define ffconst -#endif - -/* Returned upon end-of-file. */ -#define FF_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define FF_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN (ff_start) = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The FFSTATE alias is for lex - * compatibility. - */ -#define FF_START (((ff_start) - 1) / 2) -#define FFSTATE FF_START - -/* Action number for EOF rule of a given start state. */ -#define FF_STATE_EOF(state) (FF_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define FF_NEW_FILE ffrestart(ffin ) - -#define FF_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef FF_BUF_SIZE -#define FF_BUF_SIZE 16384 -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define FF_STATE_BUF_SIZE ((FF_BUF_SIZE + 2) * sizeof(ff_state_type)) - -#ifndef FF_TYPEDEF_FF_BUFFER_STATE -#define FF_TYPEDEF_FF_BUFFER_STATE -typedef struct ff_buffer_state *FF_BUFFER_STATE; -#endif - -extern int ffleng; - -extern FILE *ffin, *ffout; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - #define FF_LESS_LINENO(n) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define ffless(n) \ - do \ - { \ - /* Undo effects of setting up fftext. */ \ - int ffless_macro_arg = (n); \ - FF_LESS_LINENO(ffless_macro_arg);\ - *ff_cp = (ff_hold_char); \ - FF_RESTORE_FF_MORE_OFFSET \ - (ff_c_buf_p) = ff_cp = ff_bp + ffless_macro_arg - FF_MORE_ADJ; \ - FF_DO_BEFORE_ACTION; /* set up fftext again */ \ - } \ - while ( 0 ) - -#define unput(c) ffunput( c, (fftext_ptr) ) - -#ifndef FF_TYPEDEF_FF_SIZE_T -#define FF_TYPEDEF_FF_SIZE_T -typedef size_t ff_size_t; -#endif - -#ifndef FF_STRUCT_FF_BUFFER_STATE -#define FF_STRUCT_FF_BUFFER_STATE -struct ff_buffer_state - { - FILE *ff_input_file; - - char *ff_ch_buf; /* input buffer */ - char *ff_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - ff_size_t ff_buf_size; - - /* Number of characters read into ff_ch_buf, not including EOB - * characters. - */ - int ff_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int ff_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int ff_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int ff_at_bol; - - int ff_bs_lineno; /**< The line count. */ - int ff_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int ff_fill_buffer; - - int ff_buffer_status; - -#define FF_BUFFER_NEW 0 -#define FF_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as FF_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via ffrestart()), so that the user can continue scanning by - * just pointing ffin at a new input file. - */ -#define FF_BUFFER_EOF_PENDING 2 - - }; -#endif /* !FF_STRUCT_FF_BUFFER_STATE */ - -/* Stack of input buffers. */ -static size_t ff_buffer_stack_top = 0; /**< index of top of stack. */ -static size_t ff_buffer_stack_max = 0; /**< capacity of stack. */ -static FF_BUFFER_STATE * ff_buffer_stack = 0; /**< Stack as an array. */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define FF_CURRENT_BUFFER ( (ff_buffer_stack) \ - ? (ff_buffer_stack)[(ff_buffer_stack_top)] \ - : NULL) - -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define FF_CURRENT_BUFFER_LVALUE (ff_buffer_stack)[(ff_buffer_stack_top)] - -/* ff_hold_char holds the character lost when fftext is formed. */ -static char ff_hold_char; -static int ff_n_chars; /* number of characters read into ff_ch_buf */ -int ffleng; - -/* Points to current character in buffer. */ -static char *ff_c_buf_p = (char *) 0; -static int ff_init = 0; /* whether we need to initialize */ -static int ff_start = 0; /* start state number */ - -/* Flag which is used to allow ffwrap()'s to do buffer switches - * instead of setting up a fresh ffin. A bit of a hack ... - */ -static int ff_did_buffer_switch_on_eof; - -void ffrestart (FILE *input_file ); -void ff_switch_to_buffer (FF_BUFFER_STATE new_buffer ); -FF_BUFFER_STATE ff_create_buffer (FILE *file,int size ); -void ff_delete_buffer (FF_BUFFER_STATE b ); -void ff_flush_buffer (FF_BUFFER_STATE b ); -void ffpush_buffer_state (FF_BUFFER_STATE new_buffer ); -void ffpop_buffer_state (void ); - -static void ffensure_buffer_stack (void ); -static void ff_load_buffer_state (void ); -static void ff_init_buffer (FF_BUFFER_STATE b,FILE *file ); - -#define FF_FLUSH_BUFFER ff_flush_buffer(FF_CURRENT_BUFFER ) - -FF_BUFFER_STATE ff_scan_buffer (char *base,ff_size_t size ); -FF_BUFFER_STATE ff_scan_string (ffconst char *ff_str ); -FF_BUFFER_STATE ff_scan_bytes (ffconst char *bytes,int len ); - -void *ffalloc (ff_size_t ); -void *ffrealloc (void *,ff_size_t ); -void yyfffree (void * ); - -#define ff_new_buffer ff_create_buffer - -#define ff_set_interactive(is_interactive) \ - { \ - if ( ! FF_CURRENT_BUFFER ){ \ - ffensure_buffer_stack (); \ - FF_CURRENT_BUFFER_LVALUE = \ - ff_create_buffer(ffin,FF_BUF_SIZE ); \ - } \ - FF_CURRENT_BUFFER_LVALUE->ff_is_interactive = is_interactive; \ - } - -#define ff_set_bol(at_bol) \ - { \ - if ( ! FF_CURRENT_BUFFER ){\ - ffensure_buffer_stack (); \ - FF_CURRENT_BUFFER_LVALUE = \ - ff_create_buffer(ffin,FF_BUF_SIZE ); \ - } \ - FF_CURRENT_BUFFER_LVALUE->ff_at_bol = at_bol; \ - } - -#define FF_AT_BOL() (FF_CURRENT_BUFFER_LVALUE->ff_at_bol) - -/* Begin user sect3 */ - -typedef unsigned char FF_CHAR; - -FILE *ffin = (FILE *) 0, *ffout = (FILE *) 0; - -typedef int ff_state_type; - -extern int fflineno; - -int fflineno = 1; - -extern char *fftext; -#define fftext_ptr fftext - -static ff_state_type ff_get_previous_state (void ); -static ff_state_type ff_try_NUL_trans (ff_state_type current_state ); -static int ff_get_next_buffer (void ); -static void ff_fatal_error (ffconst char msg[] ); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up fftext. - */ -#define FF_DO_BEFORE_ACTION \ - (fftext_ptr) = ff_bp; \ - ffleng = (size_t) (ff_cp - ff_bp); \ - (ff_hold_char) = *ff_cp; \ - *ff_cp = '\0'; \ - (ff_c_buf_p) = ff_cp; - -#define FF_NUM_RULES 26 -#define FF_END_OF_BUFFER 27 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct ff_trans_info - { - flex_int32_t ff_verify; - flex_int32_t ff_nxt; - }; -static ffconst flex_int16_t ff_accept[160] = - { 0, - 0, 0, 27, 25, 1, 24, 15, 25, 25, 25, - 25, 25, 25, 25, 7, 5, 21, 25, 20, 10, - 10, 10, 10, 6, 10, 10, 10, 10, 10, 14, - 10, 10, 10, 10, 10, 10, 10, 25, 1, 19, - 0, 9, 0, 8, 0, 10, 17, 0, 0, 0, - 0, 0, 0, 0, 14, 0, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, - 5, 0, 23, 18, 22, 10, 10, 10, 2, 10, - 10, 10, 4, 10, 10, 10, 10, 3, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 16, 0, - - 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 7, 11, 10, - 20, 21, 10, 10, 10, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 15, 0, 0, 12, 0, - 0, 0, 0, 0, 0, 0, 13, 0, 0 - } ; - -static ffconst flex_int32_t ff_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 4, 5, 6, 7, 1, 8, 9, 10, - 11, 12, 13, 1, 13, 14, 1, 15, 15, 16, - 16, 16, 16, 16, 16, 17, 17, 1, 1, 18, - 19, 20, 1, 1, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 30, 31, 30, 32, 33, 30, - 34, 35, 30, 36, 37, 30, 30, 38, 30, 30, - 1, 1, 1, 39, 40, 1, 41, 42, 23, 43, - - 44, 45, 46, 28, 47, 30, 30, 48, 30, 49, - 50, 30, 51, 52, 30, 53, 54, 30, 30, 38, - 30, 30, 1, 55, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -static ffconst flex_int32_t ff_meta[56] = - { 0, - 1, 1, 2, 1, 1, 1, 3, 1, 1, 1, - 1, 1, 1, 1, 4, 4, 4, 1, 1, 1, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 1, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 1 - } ; - -static ffconst flex_int16_t ff_base[167] = - { 0, - 0, 0, 367, 368, 364, 368, 346, 359, 356, 355, - 353, 351, 32, 347, 66, 103, 339, 44, 338, 25, - 52, 316, 26, 315, 34, 133, 48, 61, 125, 368, - 0, 29, 45, 60, 81, 82, 93, 299, 351, 368, - 347, 368, 344, 343, 342, 368, 368, 339, 314, 315, - 313, 294, 295, 293, 368, 121, 164, 307, 301, 70, - 117, 43, 296, 276, 271, 58, 86, 79, 269, 152, - 168, 181, 368, 368, 368, 151, 162, 0, 180, 189, - 190, 191, 309, 196, 199, 205, 204, 211, 214, 207, - 223, 224, 232, 238, 243, 245, 222, 246, 368, 311, - - 310, 279, 282, 278, 259, 262, 258, 252, 286, 295, - 294, 293, 292, 291, 290, 267, 288, 258, 285, 284, - 278, 270, 268, 259, 218, 252, 264, 272, 368, 251, - 368, 368, 260, 280, 283, 236, 222, 230, 193, 184, - 212, 208, 202, 173, 156, 368, 133, 126, 368, 104, - 98, 119, 132, 80, 94, 92, 368, 78, 368, 323, - 325, 329, 333, 68, 67, 337 - } ; - -static ffconst flex_int16_t ff_def[167] = - { 0, - 159, 1, 159, 159, 159, 159, 159, 160, 161, 162, - 159, 163, 159, 159, 159, 159, 159, 159, 159, 164, - 164, 164, 164, 164, 164, 164, 164, 164, 164, 159, - 165, 164, 164, 164, 164, 164, 164, 159, 159, 159, - 160, 159, 166, 161, 162, 159, 159, 163, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 164, 164, 165, 164, 164, - 164, 164, 26, 164, 164, 164, 164, 164, 164, 164, - 164, 164, 164, 164, 164, 164, 164, 164, 159, 166, - - 166, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 164, - 159, 159, 164, 164, 164, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 0, 159, - 159, 159, 159, 159, 159, 159 - } ; - -static ffconst flex_int16_t ff_nxt[424] = - { 0, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 4, 14, 4, 15, 16, 16, 16, 17, 18, 19, - 20, 21, 22, 22, 23, 24, 25, 26, 22, 22, - 27, 28, 29, 22, 22, 24, 22, 22, 30, 31, - 32, 21, 22, 33, 24, 34, 22, 35, 36, 37, - 22, 22, 24, 22, 38, 49, 77, 50, 81, 80, - 51, 73, 74, 75, 78, 78, 79, 115, 78, 82, - 78, 76, 84, 78, 52, 116, 53, 90, 54, 56, - 57, 57, 57, 85, 78, 86, 58, 78, 157, 79, - 59, 78, 60, 87, 111, 91, 61, 62, 63, 78, - - 78, 120, 157, 92, 157, 112, 64, 88, 88, 65, - 121, 66, 93, 67, 68, 69, 70, 71, 71, 71, - 78, 78, 124, 158, 94, 96, 72, 72, 125, 122, - 88, 97, 78, 95, 56, 108, 108, 108, 123, 88, - 88, 113, 157, 156, 98, 72, 72, 83, 83, 83, - 155, 154, 114, 83, 83, 83, 83, 83, 83, 89, - 129, 153, 88, 152, 78, 56, 57, 57, 57, 146, - 83, 129, 78, 83, 83, 83, 83, 83, 57, 57, - 57, 70, 71, 71, 71, 130, 47, 72, 72, 129, - 78, 72, 72, 127, 79, 128, 128, 128, 129, 129, - - 129, 78, 74, 75, 131, 129, 72, 72, 129, 73, - 72, 72, 132, 129, 129, 146, 129, 79, 40, 78, - 129, 47, 149, 129, 151, 88, 88, 99, 78, 78, - 78, 129, 129, 129, 150, 78, 74, 75, 78, 133, - 149, 129, 148, 78, 78, 131, 78, 129, 88, 134, - 78, 73, 129, 78, 129, 129, 132, 147, 40, 99, - 129, 78, 78, 78, 47, 99, 108, 108, 108, 129, - 145, 78, 40, 146, 135, 72, 72, 78, 128, 128, - 128, 132, 78, 73, 78, 78, 128, 128, 128, 129, - 78, 131, 129, 47, 72, 72, 146, 75, 74, 78, - - 144, 99, 143, 40, 132, 73, 131, 75, 74, 142, - 141, 140, 139, 138, 137, 136, 101, 101, 129, 78, - 126, 119, 78, 41, 118, 41, 41, 44, 44, 45, - 117, 45, 45, 48, 110, 48, 48, 100, 109, 100, - 100, 107, 106, 105, 104, 103, 102, 42, 46, 159, - 101, 42, 39, 99, 78, 78, 75, 73, 55, 42, - 47, 46, 43, 42, 40, 39, 159, 3, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159 - } ; - -static ffconst flex_int16_t ff_chk[424] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 13, 20, 13, 25, 23, - 13, 18, 18, 18, 20, 23, 21, 62, 32, 25, - 165, 164, 27, 25, 13, 62, 13, 32, 13, 15, - 15, 15, 15, 27, 33, 28, 15, 27, 158, 21, - 15, 21, 15, 28, 60, 33, 15, 15, 15, 34, - - 28, 66, 156, 34, 155, 60, 15, 37, 37, 15, - 66, 15, 34, 15, 15, 15, 16, 16, 16, 16, - 35, 36, 68, 154, 35, 36, 16, 16, 68, 67, - 37, 36, 37, 35, 56, 56, 56, 56, 67, 29, - 29, 61, 153, 152, 37, 16, 16, 26, 26, 26, - 151, 150, 61, 26, 26, 26, 26, 26, 26, 29, - 76, 148, 29, 147, 29, 70, 70, 70, 70, 145, - 26, 77, 26, 26, 26, 26, 26, 26, 57, 57, - 57, 71, 71, 71, 71, 77, 144, 57, 57, 79, - 76, 71, 71, 72, 79, 72, 72, 72, 80, 81, - - 82, 77, 80, 81, 82, 84, 57, 57, 85, 84, - 71, 71, 85, 87, 86, 143, 90, 79, 86, 79, - 88, 142, 141, 89, 140, 88, 88, 89, 80, 81, - 82, 97, 91, 92, 139, 84, 91, 92, 85, 87, - 138, 93, 137, 87, 86, 93, 90, 94, 88, 90, - 88, 94, 95, 89, 96, 98, 95, 136, 96, 98, - 130, 97, 91, 92, 130, 126, 108, 108, 108, 133, - 125, 93, 124, 133, 97, 108, 108, 94, 127, 127, - 127, 123, 95, 122, 96, 98, 128, 128, 128, 134, - 130, 121, 135, 134, 108, 108, 135, 120, 119, 133, - - 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, - 107, 106, 105, 104, 103, 102, 101, 100, 83, 134, - 69, 65, 135, 160, 64, 160, 160, 161, 161, 162, - 63, 162, 162, 163, 59, 163, 163, 166, 58, 166, - 166, 54, 53, 52, 51, 50, 49, 48, 45, 44, - 43, 41, 39, 38, 24, 22, 19, 17, 14, 12, - 11, 10, 9, 8, 7, 5, 3, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, - 159, 159, 159 - } ; - -static ff_state_type ff_last_accepting_state; -static char *ff_last_accepting_cpos; - -extern int ff_flex_debug; -int ff_flex_debug = 0; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define ffmore() ffmore_used_but_not_detected -#define FF_MORE_ADJ 0 -#define FF_RESTORE_FF_MORE_OFFSET -char *fftext; -#line 1 "eval.l" -#line 2 "eval.l" -/************************************************************************/ -/* */ -/* CFITSIO Lexical Parser */ -/* */ -/* This file is one of 3 files containing code which parses an */ -/* arithmetic expression and evaluates it in the context of an input */ -/* FITS file table extension. The CFITSIO lexical parser is divided */ -/* into the following 3 parts/files: the CFITSIO "front-end", */ -/* eval_f.c, contains the interface between the user/CFITSIO and the */ -/* real core of the parser; the FLEX interpreter, eval_l.c, takes the */ -/* input string and parses it into tokens and identifies the FITS */ -/* information required to evaluate the expression (ie, keywords and */ -/* columns); and, the BISON grammar and evaluation routines, eval_y.c, */ -/* receives the FLEX output and determines and performs the actual */ -/* operations. The files eval_l.c and eval_y.c are produced from */ -/* running flex and bison on the files eval.l and eval.y, respectively. */ -/* (flex and bison are available from any GNU archive: see www.gnu.org) */ -/* */ -/* The grammar rules, rather than evaluating the expression in situ, */ -/* builds a tree, or Nodal, structure mapping out the order of */ -/* operations and expression dependencies. This "compilation" process */ -/* allows for much faster processing of multiple rows. This technique */ -/* was developed by Uwe Lammers of the XMM Science Analysis System, */ -/* although the CFITSIO implementation is entirely code original. */ -/* */ -/* */ -/* Modification History: */ -/* */ -/* Kent Blackburn c1992 Original parser code developed for the */ -/* FTOOLS software package, in particular, */ -/* the fselect task. */ -/* Kent Blackburn c1995 BIT column support added */ -/* Peter D Wilson Feb 1998 Vector column support added */ -/* Peter D Wilson May 1998 Ported to CFITSIO library. User */ -/* interface routines written, in essence */ -/* making fselect, fcalc, and maketime */ -/* capabilities available to all tools */ -/* via single function calls. */ -/* Peter D Wilson Jun 1998 Major rewrite of parser core, so as to */ -/* create a run-time evaluation tree, */ -/* inspired by the work of Uwe Lammers, */ -/* resulting in a speed increase of */ -/* 10-100 times. */ -/* Peter D Wilson Jul 1998 gtifilter(a,b,c,d) function added */ -/* Peter D Wilson Aug 1998 regfilter(a,b,c,d) function added */ -/* Peter D Wilson Jul 1999 Make parser fitsfile-independent, */ -/* allowing a purely vector-based usage */ -/* */ -/************************************************************************/ - -#include -#include -#include -#ifdef sparc -#include -#else -#include -#endif -#include "eval_defs.h" - -ParseData gParse; /* Global structure holding all parser information */ - -/***** Internal functions *****/ - - int ffGetVariable( char *varName, FFSTYPE *varVal ); - -static int find_variable( char *varName ); -static int expr_read( char *buf, int nbytes ); - -/***** Definitions *****/ - -#define FF_NO_UNPUT /* Don't include FFUNPUT function */ -#define FF_NEVER_INTERACTIVE 1 - -#define MAXCHR 256 -#define MAXBIT 128 - -#define OCT_0 "000" -#define OCT_1 "001" -#define OCT_2 "010" -#define OCT_3 "011" -#define OCT_4 "100" -#define OCT_5 "101" -#define OCT_6 "110" -#define OCT_7 "111" -#define OCT_X "xxx" - -#define HEX_0 "0000" -#define HEX_1 "0001" -#define HEX_2 "0010" -#define HEX_3 "0011" -#define HEX_4 "0100" -#define HEX_5 "0101" -#define HEX_6 "0110" -#define HEX_7 "0111" -#define HEX_8 "1000" -#define HEX_9 "1001" -#define HEX_A "1010" -#define HEX_B "1011" -#define HEX_C "1100" -#define HEX_D "1101" -#define HEX_E "1110" -#define HEX_F "1111" -#define HEX_X "xxxx" - -/* - MJT - 13 June 1996 - read from buffer instead of stdin - (as per old ftools.skel) -*/ -#undef FF_INPUT -#define FF_INPUT(buf,result,max_size) \ - if ( (result = expr_read( (char *) buf, max_size )) < 0 ) \ - FF_FATAL_ERROR( "read() in flex scanner failed" ); - -#line 712 "" - -#define INITIAL 0 - -#ifndef FF_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include -#endif - -#ifndef FF_EXTRA_TYPE -#define FF_EXTRA_TYPE void * -#endif - -static int ff_init_globals (void ); - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int fflex_destroy (void ); - -int ffget_debug (void ); - -void ffset_debug (int debug_flag ); - -FF_EXTRA_TYPE ffget_extra (void ); - -void ffset_extra (FF_EXTRA_TYPE user_defined ); - -FILE *ffget_in (void ); - -void ffset_in (FILE * in_str ); - -FILE *ffget_out (void ); - -void ffset_out (FILE * out_str ); - -int ffget_leng (void ); - -char *ffget_text (void ); - -int ffget_lineno (void ); - -void ffset_lineno (int line_number ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef FF_SKIP_FFWRAP -#ifdef __cplusplus -extern "C" int ffwrap (void ); -#else -extern int ffwrap (void ); -#endif -#endif - - static void ffunput (int c,char *buf_ptr ); - -#ifndef fftext_ptr -static void ff_flex_strncpy (char *,ffconst char *,int ); -#endif - -#ifdef FF_NEED_STRLEN -static int ff_flex_strlen (ffconst char * ); -#endif - -#ifndef FF_NO_INPUT - -#ifdef __cplusplus -static int ffinput (void ); -#else -static int input (void ); -#endif - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef FF_READ_BUF_SIZE -#define FF_READ_BUF_SIZE 8192 -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO do { if (fwrite( fftext, ffleng, 1, ffout )) {} } while (0) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or FF_NULL, - * is returned in "result". - */ -#ifndef FF_INPUT -#define FF_INPUT(buf,result,max_size) \ - if ( FF_CURRENT_BUFFER_LVALUE->ff_is_interactive ) \ - { \ - int c = '*'; \ - unsigned n; \ - for ( n = 0; n < max_size && \ - (c = getc( ffin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( ffin ) ) \ - FF_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else \ - { \ - errno=0; \ - while ( (result = fread(buf, 1, max_size, ffin))==0 && ferror(ffin)) \ - { \ - if( errno != EINTR) \ - { \ - FF_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(ffin); \ - } \ - }\ -\ - -#endif - -/* No semi-colon after return; correct usage is to write "ffterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef ffterminate -#define ffterminate() return FF_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef FF_START_STACK_INCR -#define FF_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef FF_FATAL_ERROR -#define FF_FATAL_ERROR(msg) ff_fatal_error( msg ) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef FF_DECL -#define FF_DECL_IS_OURS 1 - -extern int fflex (void); - -#define FF_DECL int fflex (void) -#endif /* !FF_DECL */ - -/* Code executed at the beginning of each rule, after fftext and ffleng - * have been set up. - */ -#ifndef FF_USER_ACTION -#define FF_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef FF_BREAK -#define FF_BREAK break; -#endif - -#define FF_RULE_SETUP \ - FF_USER_ACTION - -/** The main scanner function which does all the work. - */ -FF_DECL -{ - register ff_state_type ff_current_state; - register char *ff_cp, *ff_bp; - register int ff_act; - -#line 142 "eval.l" - - -#line 897 "" - - if ( !(ff_init) ) - { - (ff_init) = 1; - -#ifdef FF_USER_INIT - FF_USER_INIT; -#endif - - if ( ! (ff_start) ) - (ff_start) = 1; /* first start state */ - - if ( ! ffin ) - ffin = stdin; - - if ( ! ffout ) - ffout = stdout; - - if ( ! FF_CURRENT_BUFFER ) { - ffensure_buffer_stack (); - FF_CURRENT_BUFFER_LVALUE = - ff_create_buffer(ffin,FF_BUF_SIZE ); - } - - ff_load_buffer_state( ); - } - - while ( 1 ) /* loops until end-of-file is reached */ - { - ff_cp = (ff_c_buf_p); - - /* Support of fftext. */ - *ff_cp = (ff_hold_char); - - /* ff_bp points to the position in ff_ch_buf of the start of - * the current run. - */ - ff_bp = ff_cp; - - ff_current_state = (ff_start); -ff_match: - do - { - register FF_CHAR ff_c = ff_ec[FF_SC_TO_UI(*ff_cp)]; - if ( ff_accept[ff_current_state] ) - { - (ff_last_accepting_state) = ff_current_state; - (ff_last_accepting_cpos) = ff_cp; - } - while ( ff_chk[ff_base[ff_current_state] + ff_c] != ff_current_state ) - { - ff_current_state = (int) ff_def[ff_current_state]; - if ( ff_current_state >= 160 ) - ff_c = ff_meta[(unsigned int) ff_c]; - } - ff_current_state = ff_nxt[ff_base[ff_current_state] + (unsigned int) ff_c]; - ++ff_cp; - } - while ( ff_base[ff_current_state] != 368 ); - -ff_find_action: - ff_act = ff_accept[ff_current_state]; - if ( ff_act == 0 ) - { /* have to back up */ - ff_cp = (ff_last_accepting_cpos); - ff_current_state = (ff_last_accepting_state); - ff_act = ff_accept[ff_current_state]; - } - - FF_DO_BEFORE_ACTION; - -do_action: /* This label is used only to access EOF actions. */ - - switch ( ff_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of FF_DO_BEFORE_ACTION */ - *ff_cp = (ff_hold_char); - ff_cp = (ff_last_accepting_cpos); - ff_current_state = (ff_last_accepting_state); - goto ff_find_action; - -case 1: -FF_RULE_SETUP -#line 144 "eval.l" -; - FF_BREAK -case 2: -FF_RULE_SETUP -#line 145 "eval.l" -{ - int len; - len = strlen(fftext); - while (fftext[len] == ' ') - len--; - len = len - 1; - strncpy(fflval.str,&fftext[1],len); - fflval.str[len] = '\0'; - return( BITSTR ); - } - FF_BREAK -case 3: -FF_RULE_SETUP -#line 155 "eval.l" -{ - int len; - char tmpstring[256]; - char bitstring[256]; - len = strlen(fftext); - if (len >= 256) { - char errMsg[100]; - gParse.status = PARSE_SYNTAX_ERR; - strcpy (errMsg,"Bit string exceeds maximum length: '"); - strncat(errMsg, &(fftext[0]), 20); - strcat (errMsg,"...'"); - ffpmsg (errMsg); - len = 0; - } else { - while (fftext[len] == ' ') - len--; - len = len - 1; - strncpy(tmpstring,&fftext[1],len); - } - tmpstring[len] = '\0'; - bitstring[0] = '\0'; - len = 0; - while ( tmpstring[len] != '\0') - { - switch ( tmpstring[len] ) - { - case '0': - strcat(bitstring,OCT_0); - break; - case '1': - strcat(bitstring,OCT_1); - break; - case '2': - strcat(bitstring,OCT_2); - break; - case '3': - strcat(bitstring,OCT_3); - break; - case '4': - strcat(bitstring,OCT_4); - break; - case '5': - strcat(bitstring,OCT_5); - break; - case '6': - strcat(bitstring,OCT_6); - break; - case '7': - strcat(bitstring,OCT_7); - break; - case 'x': - case 'X': - strcat(bitstring,OCT_X); - break; - } - len++; - } - strcpy( fflval.str, bitstring ); - return( BITSTR ); - } - FF_BREAK -case 4: -FF_RULE_SETUP -#line 215 "eval.l" -{ - int len; - char tmpstring[256]; - char bitstring[256]; - len = strlen(fftext); - if (len >= 256) { - char errMsg[100]; - gParse.status = PARSE_SYNTAX_ERR; - strcpy (errMsg,"Hex string exceeds maximum length: '"); - strncat(errMsg, &(fftext[0]), 20); - strcat (errMsg,"...'"); - ffpmsg (errMsg); - len = 0; - } else { - while (fftext[len] == ' ') - len--; - len = len - 1; - strncpy(tmpstring,&fftext[1],len); - } - tmpstring[len] = '\0'; - bitstring[0] = '\0'; - len = 0; - while ( tmpstring[len] != '\0') - { - switch ( tmpstring[len] ) - { - case '0': - strcat(bitstring,HEX_0); - break; - case '1': - strcat(bitstring,HEX_1); - break; - case '2': - strcat(bitstring,HEX_2); - break; - case '3': - strcat(bitstring,HEX_3); - break; - case '4': - strcat(bitstring,HEX_4); - break; - case '5': - strcat(bitstring,HEX_5); - break; - case '6': - strcat(bitstring,HEX_6); - break; - case '7': - strcat(bitstring,HEX_7); - break; - case '8': - strcat(bitstring,HEX_8); - break; - case '9': - strcat(bitstring,HEX_9); - break; - case 'a': - case 'A': - strcat(bitstring,HEX_A); - break; - case 'b': - case 'B': - strcat(bitstring,HEX_B); - break; - case 'c': - case 'C': - strcat(bitstring,HEX_C); - break; - case 'd': - case 'D': - strcat(bitstring,HEX_D); - break; - case 'e': - case 'E': - strcat(bitstring,HEX_E); - break; - case 'f': - case 'F': - strcat(bitstring,HEX_F); - break; - case 'x': - case 'X': - strcat(bitstring,HEX_X); - break; - } - len++; - } - - strcpy( fflval.str, bitstring ); - return( BITSTR ); - } - FF_BREAK -case 5: -FF_RULE_SETUP -#line 306 "eval.l" -{ - fflval.lng = atol(fftext); - return( LONG ); - } - FF_BREAK -case 6: -FF_RULE_SETUP -#line 310 "eval.l" -{ - if ((fftext[0] == 't') || (fftext[0] == 'T')) - fflval.log = 1; - else - fflval.log = 0; - return( BOOLEAN ); - } - FF_BREAK -case 7: -FF_RULE_SETUP -#line 317 "eval.l" -{ - fflval.dbl = atof(fftext); - return( DOUBLE ); - } - FF_BREAK -case 8: -FF_RULE_SETUP -#line 321 "eval.l" -{ - if( !fits_strcasecmp(fftext,"#PI") ) { - fflval.dbl = (double)(4) * atan((double)(1)); - return( DOUBLE ); - } else if( !fits_strcasecmp(fftext,"#E") ) { - fflval.dbl = exp((double)(1)); - return( DOUBLE ); - } else if( !fits_strcasecmp(fftext,"#DEG") ) { - fflval.dbl = ((double)4)*atan((double)1)/((double)180); - return( DOUBLE ); - } else if( !fits_strcasecmp(fftext,"#ROW") ) { - return( ROWREF ); - } else if( !fits_strcasecmp(fftext,"#NULL") ) { - return( NULLREF ); - } else if( !fits_strcasecmp(fftext,"#SNULL") ) { - return( SNULLREF ); - } else { - int len; - if (fftext[1] == '$') { - len = strlen(fftext) - 3; - fflval.str[0] = '#'; - strncpy(fflval.str+1,&fftext[2],len); - fflval.str[len+1] = '\0'; - fftext = fflval.str; - } - return( (*gParse.getData)(fftext, &fflval) ); - } - } - FF_BREAK -case 9: -FF_RULE_SETUP -#line 349 "eval.l" -{ - int len; - len = strlen(fftext) - 2; - if (len >= MAX_STRLEN) { - char errMsg[100]; - gParse.status = PARSE_SYNTAX_ERR; - strcpy (errMsg,"String exceeds maximum length: '"); - strncat(errMsg, &(fftext[1]), 20); - strcat (errMsg,"...'"); - ffpmsg (errMsg); - len = 0; - } else { - strncpy(fflval.str,&fftext[1],len); - } - fflval.str[len] = '\0'; - return( STRING ); - } - FF_BREAK -case 10: -FF_RULE_SETUP -#line 366 "eval.l" -{ - int len,type; - - if (fftext[0] == '$') { - len = strlen(fftext) - 2; - strncpy(fflval.str,&fftext[1],len); - fflval.str[len] = '\0'; - fftext = fflval.str; - } - type = ffGetVariable(fftext, &fflval); - return( type ); - } - FF_BREAK -case 11: -FF_RULE_SETUP -#line 378 "eval.l" -{ - char *fname; - int len=0; - fname = &fflval.str[0]; - while( (fname[len]=toupper(fftext[len])) ) len++; - - if( FSTRCMP(fname,"BOX(")==0 - || FSTRCMP(fname,"CIRCLE(")==0 - || FSTRCMP(fname,"ELLIPSE(")==0 - || FSTRCMP(fname,"NEAR(")==0 - || FSTRCMP(fname,"ISNULL(")==0 - ) - /* Return type is always boolean */ - return( BFUNCTION ); - - else if( FSTRCMP(fname,"GTIFILTER(")==0 ) - return( GTIFILTER ); - - else if( FSTRCMP(fname,"REGFILTER(")==0 ) - return( REGFILTER ); - - else if( FSTRCMP(fname,"STRSTR(")==0 ) - return( IFUNCTION ); /* Returns integer */ - - else - return( FUNCTION ); - } - FF_BREAK -case 12: -FF_RULE_SETUP -#line 405 "eval.l" -{ return( INTCAST ); } - FF_BREAK -case 13: -FF_RULE_SETUP -#line 406 "eval.l" -{ return( FLTCAST ); } - FF_BREAK -case 14: -FF_RULE_SETUP -#line 407 "eval.l" -{ return( POWER ); } - FF_BREAK -case 15: -FF_RULE_SETUP -#line 408 "eval.l" -{ return( NOT ); } - FF_BREAK -case 16: -FF_RULE_SETUP -#line 409 "eval.l" -{ return( OR ); } - FF_BREAK -case 17: -FF_RULE_SETUP -#line 410 "eval.l" -{ return( AND ); } - FF_BREAK -case 18: -FF_RULE_SETUP -#line 411 "eval.l" -{ return( EQ ); } - FF_BREAK -case 19: -FF_RULE_SETUP -#line 412 "eval.l" -{ return( NE ); } - FF_BREAK -case 20: -FF_RULE_SETUP -#line 413 "eval.l" -{ return( GT ); } - FF_BREAK -case 21: -FF_RULE_SETUP -#line 414 "eval.l" -{ return( LT ); } - FF_BREAK -case 22: -FF_RULE_SETUP -#line 415 "eval.l" -{ return( GTE ); } - FF_BREAK -case 23: -FF_RULE_SETUP -#line 416 "eval.l" -{ return( LTE ); } - FF_BREAK -case 24: -/* rule 24 can match eol */ -FF_RULE_SETUP -#line 417 "eval.l" -{ return( '\n' ); } - FF_BREAK -case 25: -FF_RULE_SETUP -#line 418 "eval.l" -{ return( fftext[0] ); } - FF_BREAK -case 26: -FF_RULE_SETUP -#line 419 "eval.l" -ECHO; - FF_BREAK -#line 1361 "" -case FF_STATE_EOF(INITIAL): - ffterminate(); - - case FF_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int ff_amount_of_matched_text = (int) (ff_cp - (fftext_ptr)) - 1; - - /* Undo the effects of FF_DO_BEFORE_ACTION. */ - *ff_cp = (ff_hold_char); - FF_RESTORE_FF_MORE_OFFSET - - if ( FF_CURRENT_BUFFER_LVALUE->ff_buffer_status == FF_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed ffin at a new source and called - * fflex(). If so, then we have to assure - * consistency between FF_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - (ff_n_chars) = FF_CURRENT_BUFFER_LVALUE->ff_n_chars; - FF_CURRENT_BUFFER_LVALUE->ff_input_file = ffin; - FF_CURRENT_BUFFER_LVALUE->ff_buffer_status = FF_BUFFER_NORMAL; - } - - /* Note that here we test for ff_c_buf_p "<=" to the position - * of the first EOB in the buffer, since ff_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( (ff_c_buf_p) <= &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[(ff_n_chars)] ) - { /* This was really a NUL. */ - ff_state_type ff_next_state; - - (ff_c_buf_p) = (fftext_ptr) + ff_amount_of_matched_text; - - ff_current_state = ff_get_previous_state( ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * ff_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - ff_next_state = ff_try_NUL_trans( ff_current_state ); - - ff_bp = (fftext_ptr) + FF_MORE_ADJ; - - if ( ff_next_state ) - { - /* Consume the NUL. */ - ff_cp = ++(ff_c_buf_p); - ff_current_state = ff_next_state; - goto ff_match; - } - - else - { - ff_cp = (ff_c_buf_p); - goto ff_find_action; - } - } - - else switch ( ff_get_next_buffer( ) ) - { - case EOB_ACT_END_OF_FILE: - { - (ff_did_buffer_switch_on_eof) = 0; - - if ( ffwrap( ) ) - { - /* Note: because we've taken care in - * ff_get_next_buffer() to have set up - * fftext, we can now set up - * ff_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * FF_NULL, it'll still work - another - * FF_NULL will get returned. - */ - (ff_c_buf_p) = (fftext_ptr) + FF_MORE_ADJ; - - ff_act = FF_STATE_EOF(FF_START); - goto do_action; - } - - else - { - if ( ! (ff_did_buffer_switch_on_eof) ) - FF_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - (ff_c_buf_p) = - (fftext_ptr) + ff_amount_of_matched_text; - - ff_current_state = ff_get_previous_state( ); - - ff_cp = (ff_c_buf_p); - ff_bp = (fftext_ptr) + FF_MORE_ADJ; - goto ff_match; - - case EOB_ACT_LAST_MATCH: - (ff_c_buf_p) = - &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[(ff_n_chars)]; - - ff_current_state = ff_get_previous_state( ); - - ff_cp = (ff_c_buf_p); - ff_bp = (fftext_ptr) + FF_MORE_ADJ; - goto ff_find_action; - } - break; - } - - default: - FF_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ -} /* end of fflex */ - -/* ff_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -static int ff_get_next_buffer (void) -{ - register char *dest = FF_CURRENT_BUFFER_LVALUE->ff_ch_buf; - register char *source = (fftext_ptr); - register int number_to_move, i; - int ret_val; - - if ( (ff_c_buf_p) > &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[(ff_n_chars) + 1] ) - FF_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( FF_CURRENT_BUFFER_LVALUE->ff_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( (ff_c_buf_p) - (fftext_ptr) - FF_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) ((ff_c_buf_p) - (fftext_ptr)) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( FF_CURRENT_BUFFER_LVALUE->ff_buffer_status == FF_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - FF_CURRENT_BUFFER_LVALUE->ff_n_chars = (ff_n_chars) = 0; - - else - { - int num_to_read = - FF_CURRENT_BUFFER_LVALUE->ff_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - /* just a shorter name for the current buffer */ - FF_BUFFER_STATE b = FF_CURRENT_BUFFER; - - int ff_c_buf_p_offset = - (int) ((ff_c_buf_p) - b->ff_ch_buf); - - if ( b->ff_is_our_buffer ) - { - int new_size = b->ff_buf_size * 2; - - if ( new_size <= 0 ) - b->ff_buf_size += b->ff_buf_size / 8; - else - b->ff_buf_size *= 2; - - b->ff_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - ffrealloc((void *) b->ff_ch_buf,b->ff_buf_size + 2 ); - } - else - /* Can't grow it, we don't own it. */ - b->ff_ch_buf = 0; - - if ( ! b->ff_ch_buf ) - FF_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - (ff_c_buf_p) = &b->ff_ch_buf[ff_c_buf_p_offset]; - - num_to_read = FF_CURRENT_BUFFER_LVALUE->ff_buf_size - - number_to_move - 1; - - } - - if ( num_to_read > FF_READ_BUF_SIZE ) - num_to_read = FF_READ_BUF_SIZE; - - /* Read in more data. */ - FF_INPUT( (&FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[number_to_move]), - (ff_n_chars), (size_t) num_to_read ); - - FF_CURRENT_BUFFER_LVALUE->ff_n_chars = (ff_n_chars); - } - - if ( (ff_n_chars) == 0 ) - { - if ( number_to_move == FF_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - ffrestart(ffin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - FF_CURRENT_BUFFER_LVALUE->ff_buffer_status = - FF_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - if ((ff_size_t) ((ff_n_chars) + number_to_move) > FF_CURRENT_BUFFER_LVALUE->ff_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - ff_size_t new_size = (ff_n_chars) + number_to_move + ((ff_n_chars) >> 1); - FF_CURRENT_BUFFER_LVALUE->ff_ch_buf = (char *) ffrealloc((void *) FF_CURRENT_BUFFER_LVALUE->ff_ch_buf,new_size ); - if ( ! FF_CURRENT_BUFFER_LVALUE->ff_ch_buf ) - FF_FATAL_ERROR( "out of dynamic memory in ff_get_next_buffer()" ); - } - - (ff_n_chars) += number_to_move; - FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[(ff_n_chars)] = FF_END_OF_BUFFER_CHAR; - FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[(ff_n_chars) + 1] = FF_END_OF_BUFFER_CHAR; - - (fftext_ptr) = &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[0]; - - return ret_val; -} - -/* ff_get_previous_state - get the state just before the EOB char was reached */ - - static ff_state_type ff_get_previous_state (void) -{ - register ff_state_type ff_current_state; - register char *ff_cp; - - ff_current_state = (ff_start); - - for ( ff_cp = (fftext_ptr) + FF_MORE_ADJ; ff_cp < (ff_c_buf_p); ++ff_cp ) - { - register FF_CHAR ff_c = (*ff_cp ? ff_ec[FF_SC_TO_UI(*ff_cp)] : 1); - if ( ff_accept[ff_current_state] ) - { - (ff_last_accepting_state) = ff_current_state; - (ff_last_accepting_cpos) = ff_cp; - } - while ( ff_chk[ff_base[ff_current_state] + ff_c] != ff_current_state ) - { - ff_current_state = (int) ff_def[ff_current_state]; - if ( ff_current_state >= 160 ) - ff_c = ff_meta[(unsigned int) ff_c]; - } - ff_current_state = ff_nxt[ff_base[ff_current_state] + (unsigned int) ff_c]; - } - - return ff_current_state; -} - -/* ff_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = ff_try_NUL_trans( current_state ); - */ - static ff_state_type ff_try_NUL_trans (ff_state_type ff_current_state ) -{ - register int ff_is_jam; - register char *ff_cp = (ff_c_buf_p); - - register FF_CHAR ff_c = 1; - if ( ff_accept[ff_current_state] ) - { - (ff_last_accepting_state) = ff_current_state; - (ff_last_accepting_cpos) = ff_cp; - } - while ( ff_chk[ff_base[ff_current_state] + ff_c] != ff_current_state ) - { - ff_current_state = (int) ff_def[ff_current_state]; - if ( ff_current_state >= 160 ) - ff_c = ff_meta[(unsigned int) ff_c]; - } - ff_current_state = ff_nxt[ff_base[ff_current_state] + (unsigned int) ff_c]; - ff_is_jam = (ff_current_state == 159); - - return ff_is_jam ? 0 : ff_current_state; -} - - static void ffunput (int c, register char * ff_bp ) -{ - register char *ff_cp; - - ff_cp = (ff_c_buf_p); - - /* undo effects of setting up fftext */ - *ff_cp = (ff_hold_char); - - if ( ff_cp < FF_CURRENT_BUFFER_LVALUE->ff_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - register int number_to_move = (ff_n_chars) + 2; - register char *dest = &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[ - FF_CURRENT_BUFFER_LVALUE->ff_buf_size + 2]; - register char *source = - &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[number_to_move]; - - while ( source > FF_CURRENT_BUFFER_LVALUE->ff_ch_buf ) - *--dest = *--source; - - ff_cp += (int) (dest - source); - ff_bp += (int) (dest - source); - FF_CURRENT_BUFFER_LVALUE->ff_n_chars = - (ff_n_chars) = FF_CURRENT_BUFFER_LVALUE->ff_buf_size; - - if ( ff_cp < FF_CURRENT_BUFFER_LVALUE->ff_ch_buf + 2 ) - FF_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--ff_cp = (char) c; - - (fftext_ptr) = ff_bp; - (ff_hold_char) = *ff_cp; - (ff_c_buf_p) = ff_cp; -} - -#ifndef FF_NO_INPUT -#ifdef __cplusplus - static int ffinput (void) -#else - static int input (void) -#endif - -{ - int c; - - *(ff_c_buf_p) = (ff_hold_char); - - if ( *(ff_c_buf_p) == FF_END_OF_BUFFER_CHAR ) - { - /* ff_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( (ff_c_buf_p) < &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[(ff_n_chars)] ) - /* This was really a NUL. */ - *(ff_c_buf_p) = '\0'; - - else - { /* need more input */ - int offset = (ff_c_buf_p) - (fftext_ptr); - ++(ff_c_buf_p); - - switch ( ff_get_next_buffer( ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because ff_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - ffrestart(ffin ); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( ffwrap( ) ) - return EOF; - - if ( ! (ff_did_buffer_switch_on_eof) ) - FF_NEW_FILE; -#ifdef __cplusplus - return ffinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - (ff_c_buf_p) = (fftext_ptr) + offset; - break; - } - } - } - - c = *(unsigned char *) (ff_c_buf_p); /* cast for 8-bit char's */ - *(ff_c_buf_p) = '\0'; /* preserve fftext */ - (ff_hold_char) = *++(ff_c_buf_p); - - return c; -} -#endif /* ifndef FF_NO_INPUT */ - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ - void ffrestart (FILE * input_file ) -{ - - if ( ! FF_CURRENT_BUFFER ){ - ffensure_buffer_stack (); - FF_CURRENT_BUFFER_LVALUE = - ff_create_buffer(ffin,FF_BUF_SIZE ); - } - - ff_init_buffer(FF_CURRENT_BUFFER,input_file ); - ff_load_buffer_state( ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * - */ - void ff_switch_to_buffer (FF_BUFFER_STATE new_buffer ) -{ - - /* TODO. We should be able to replace this entire function body - * with - * ffpop_buffer_state(); - * ffpush_buffer_state(new_buffer); - */ - ffensure_buffer_stack (); - if ( FF_CURRENT_BUFFER == new_buffer ) - return; - - if ( FF_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(ff_c_buf_p) = (ff_hold_char); - FF_CURRENT_BUFFER_LVALUE->ff_buf_pos = (ff_c_buf_p); - FF_CURRENT_BUFFER_LVALUE->ff_n_chars = (ff_n_chars); - } - - FF_CURRENT_BUFFER_LVALUE = new_buffer; - ff_load_buffer_state( ); - - /* We don't actually know whether we did this switch during - * EOF (ffwrap()) processing, but the only time this flag - * is looked at is after ffwrap() is called, so it's safe - * to go ahead and always set it. - */ - (ff_did_buffer_switch_on_eof) = 1; -} - -static void ff_load_buffer_state (void) -{ - (ff_n_chars) = FF_CURRENT_BUFFER_LVALUE->ff_n_chars; - (fftext_ptr) = (ff_c_buf_p) = FF_CURRENT_BUFFER_LVALUE->ff_buf_pos; - ffin = FF_CURRENT_BUFFER_LVALUE->ff_input_file; - (ff_hold_char) = *(ff_c_buf_p); -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c FF_BUF_SIZE. - * - * @return the allocated buffer state. - */ - FF_BUFFER_STATE ff_create_buffer (FILE * file, int size ) -{ - FF_BUFFER_STATE b; - - b = (FF_BUFFER_STATE) ffalloc(sizeof( struct ff_buffer_state ) ); - if ( ! b ) - FF_FATAL_ERROR( "out of dynamic memory in ff_create_buffer()" ); - - b->ff_buf_size = size; - - /* ff_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->ff_ch_buf = (char *) ffalloc(b->ff_buf_size + 2 ); - if ( ! b->ff_ch_buf ) - FF_FATAL_ERROR( "out of dynamic memory in ff_create_buffer()" ); - - b->ff_is_our_buffer = 1; - - ff_init_buffer(b,file ); - - return b; -} - -/** Destroy the buffer. - * @param b a buffer created with ff_create_buffer() - * - */ - void ff_delete_buffer (FF_BUFFER_STATE b ) -{ - - if ( ! b ) - return; - - if ( b == FF_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - FF_CURRENT_BUFFER_LVALUE = (FF_BUFFER_STATE) 0; - - if ( b->ff_is_our_buffer ) - yyfffree((void *) b->ff_ch_buf ); - - yyfffree((void *) b ); -} - -#ifndef __cplusplus -extern int isatty (int ); -#endif /* __cplusplus */ - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a ffrestart() or at EOF. - */ - static void ff_init_buffer (FF_BUFFER_STATE b, FILE * file ) - -{ - int oerrno = errno; - - ff_flush_buffer(b ); - - b->ff_input_file = file; - b->ff_fill_buffer = 1; - - /* If b is the current buffer, then ff_init_buffer was _probably_ - * called from ffrestart() or through ff_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != FF_CURRENT_BUFFER){ - b->ff_bs_lineno = 1; - b->ff_bs_column = 0; - } - - b->ff_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; - - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, FF_INPUT will be called. - * @param b the buffer state to be flushed, usually @c FF_CURRENT_BUFFER. - * - */ - void ff_flush_buffer (FF_BUFFER_STATE b ) -{ - if ( ! b ) - return; - - b->ff_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->ff_ch_buf[0] = FF_END_OF_BUFFER_CHAR; - b->ff_ch_buf[1] = FF_END_OF_BUFFER_CHAR; - - b->ff_buf_pos = &b->ff_ch_buf[0]; - - b->ff_at_bol = 1; - b->ff_buffer_status = FF_BUFFER_NEW; - - if ( b == FF_CURRENT_BUFFER ) - ff_load_buffer_state( ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * - */ -void ffpush_buffer_state (FF_BUFFER_STATE new_buffer ) -{ - if (new_buffer == NULL) - return; - - ffensure_buffer_stack(); - - /* This block is copied from ff_switch_to_buffer. */ - if ( FF_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(ff_c_buf_p) = (ff_hold_char); - FF_CURRENT_BUFFER_LVALUE->ff_buf_pos = (ff_c_buf_p); - FF_CURRENT_BUFFER_LVALUE->ff_n_chars = (ff_n_chars); - } - - /* Only push if top exists. Otherwise, replace top. */ - if (FF_CURRENT_BUFFER) - (ff_buffer_stack_top)++; - FF_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from ff_switch_to_buffer. */ - ff_load_buffer_state( ); - (ff_did_buffer_switch_on_eof) = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * - */ -void ffpop_buffer_state (void) -{ - if (!FF_CURRENT_BUFFER) - return; - - ff_delete_buffer(FF_CURRENT_BUFFER ); - FF_CURRENT_BUFFER_LVALUE = NULL; - if ((ff_buffer_stack_top) > 0) - --(ff_buffer_stack_top); - - if (FF_CURRENT_BUFFER) { - ff_load_buffer_state( ); - (ff_did_buffer_switch_on_eof) = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void ffensure_buffer_stack (void) -{ - int num_to_alloc; - - if (!(ff_buffer_stack)) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; - (ff_buffer_stack) = (struct ff_buffer_state**)ffalloc - (num_to_alloc * sizeof(struct ff_buffer_state*) - ); - if ( ! (ff_buffer_stack) ) - FF_FATAL_ERROR( "out of dynamic memory in ffensure_buffer_stack()" ); - - memset((ff_buffer_stack), 0, num_to_alloc * sizeof(struct ff_buffer_state*)); - - (ff_buffer_stack_max) = num_to_alloc; - (ff_buffer_stack_top) = 0; - return; - } - - if ((ff_buffer_stack_top) >= ((ff_buffer_stack_max)) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - int grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = (ff_buffer_stack_max) + grow_size; - (ff_buffer_stack) = (struct ff_buffer_state**)ffrealloc - ((ff_buffer_stack), - num_to_alloc * sizeof(struct ff_buffer_state*) - ); - if ( ! (ff_buffer_stack) ) - FF_FATAL_ERROR( "out of dynamic memory in ffensure_buffer_stack()" ); - - /* zero only the new slots.*/ - memset((ff_buffer_stack) + (ff_buffer_stack_max), 0, grow_size * sizeof(struct ff_buffer_state*)); - (ff_buffer_stack_max) = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * - * @return the newly allocated buffer state object. - */ -FF_BUFFER_STATE ff_scan_buffer (char * base, ff_size_t size ) -{ - FF_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != FF_END_OF_BUFFER_CHAR || - base[size-1] != FF_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; - - b = (FF_BUFFER_STATE) ffalloc(sizeof( struct ff_buffer_state ) ); - if ( ! b ) - FF_FATAL_ERROR( "out of dynamic memory in ff_scan_buffer()" ); - - b->ff_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->ff_buf_pos = b->ff_ch_buf = base; - b->ff_is_our_buffer = 0; - b->ff_input_file = 0; - b->ff_n_chars = b->ff_buf_size; - b->ff_is_interactive = 0; - b->ff_at_bol = 1; - b->ff_fill_buffer = 0; - b->ff_buffer_status = FF_BUFFER_NEW; - - ff_switch_to_buffer(b ); - - return b; -} - -/** Setup the input buffer state to scan a string. The next call to fflex() will - * scan from a @e copy of @a str. - * @param ffstr a NUL-terminated string to scan - * - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * ff_scan_bytes() instead. - */ -FF_BUFFER_STATE ff_scan_string (ffconst char * ffstr ) -{ - - return ff_scan_bytes(ffstr,strlen(ffstr) ); -} - -/** Setup the input buffer state to scan the given bytes. The next call to fflex() will - * scan from a @e copy of @a bytes. - * @param bytes the byte buffer to scan - * @param len the number of bytes in the buffer pointed to by @a bytes. - * - * @return the newly allocated buffer state object. - */ -FF_BUFFER_STATE ff_scan_bytes (ffconst char * ffbytes, int _ffbytes_len ) -{ - FF_BUFFER_STATE b; - char *buf; - ff_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = _ffbytes_len + 2; - buf = (char *) ffalloc(n ); - if ( ! buf ) - FF_FATAL_ERROR( "out of dynamic memory in ff_scan_bytes()" ); - - for ( i = 0; i < _ffbytes_len; ++i ) - buf[i] = ffbytes[i]; - - buf[_ffbytes_len] = buf[_ffbytes_len+1] = FF_END_OF_BUFFER_CHAR; - - b = ff_scan_buffer(buf,n ); - if ( ! b ) - FF_FATAL_ERROR( "bad buffer in ff_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->ff_is_our_buffer = 1; - - return b; -} - -#ifndef FF_EXIT_FAILURE -#define FF_EXIT_FAILURE 2 -#endif - -static void ff_fatal_error (ffconst char* msg ) -{ - (void) fprintf( stderr, "%s\n", msg ); - exit( FF_EXIT_FAILURE ); -} - -/* Redefine ffless() so it works in section 3 code. */ - -#undef ffless -#define ffless(n) \ - do \ - { \ - /* Undo effects of setting up fftext. */ \ - int ffless_macro_arg = (n); \ - FF_LESS_LINENO(ffless_macro_arg);\ - fftext[ffleng] = (ff_hold_char); \ - (ff_c_buf_p) = fftext + ffless_macro_arg; \ - (ff_hold_char) = *(ff_c_buf_p); \ - *(ff_c_buf_p) = '\0'; \ - ffleng = ffless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/** Get the current line number. - * - */ -int ffget_lineno (void) -{ - - return fflineno; -} - -/** Get the input stream. - * - */ -FILE *ffget_in (void) -{ - return ffin; -} - -/** Get the output stream. - * - */ -FILE *ffget_out (void) -{ - return ffout; -} - -/** Get the length of the current token. - * - */ -int ffget_leng (void) -{ - return ffleng; -} - -/** Get the current token. - * - */ - -char *ffget_text (void) -{ - return fftext; -} - -/** Set the current line number. - * @param line_number - * - */ -void ffset_lineno (int line_number ) -{ - - fflineno = line_number; -} - -/** Set the input stream. This does not discard the current - * input buffer. - * @param in_str A readable stream. - * - * @see ff_switch_to_buffer - */ -void ffset_in (FILE * in_str ) -{ - ffin = in_str ; -} - -void ffset_out (FILE * out_str ) -{ - ffout = out_str ; -} - -int ffget_debug (void) -{ - return ff_flex_debug; -} - -void ffset_debug (int bdebug ) -{ - ff_flex_debug = bdebug ; -} - -static int ff_init_globals (void) -{ - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from fflex_destroy(), so don't allocate here. - */ - - (ff_buffer_stack) = 0; - (ff_buffer_stack_top) = 0; - (ff_buffer_stack_max) = 0; - (ff_c_buf_p) = (char *) 0; - (ff_init) = 0; - (ff_start) = 0; - -/* Defined in main.c */ -#ifdef FF_STDINIT - ffin = stdin; - ffout = stdout; -#else - ffin = (FILE *) 0; - ffout = (FILE *) 0; -#endif - - /* For future reference: Set errno on error, since we are called by - * fflex_init() - */ - return 0; -} - -/* fflex_destroy is for both reentrant and non-reentrant scanners. */ -int fflex_destroy (void) -{ - - /* Pop the buffer stack, destroying each element. */ - while(FF_CURRENT_BUFFER){ - ff_delete_buffer(FF_CURRENT_BUFFER ); - FF_CURRENT_BUFFER_LVALUE = NULL; - ffpop_buffer_state(); - } - - /* Destroy the stack itself. */ - yyfffree((ff_buffer_stack) ); - (ff_buffer_stack) = NULL; - - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * fflex() is called, initialization will occur. */ - ff_init_globals( ); - - return 0; -} - -/* - * Internal utility routines. - */ - -#ifndef fftext_ptr -static void ff_flex_strncpy (char* s1, ffconst char * s2, int n ) -{ - register int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef FF_NEED_STRLEN -static int ff_flex_strlen (ffconst char * s ) -{ - register int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *ffalloc (ff_size_t size ) -{ - return (void *) malloc( size ); -} - -void *ffrealloc (void * ptr, ff_size_t size ) -{ - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return (void *) realloc( (char *) ptr, size ); -} - -void yyfffree (void * ptr ) -{ - free( (char *) ptr ); /* see ffrealloc() for (char *) cast */ -} - -#define FFTABLES_NAME "fftables" - -#line 419 "eval.l" - - - -int ffwrap() -{ - /* MJT -- 13 June 1996 - Supplied for compatibility with - pre-2.5.1 versions of flex which - do not recognize %option noffwrap - */ - return(1); -} - -/* - expr_read is lifted from old ftools.skel. - Now we can use any version of flex with - no .skel file necessary! MJT - 13 June 1996 - - keep a memory of how many bytes have been - read previously, so that an unlimited-sized - buffer can be supported. PDW - 28 Feb 1998 -*/ - -static int expr_read(char *buf, int nbytes) -{ - int n; - - n = 0; - if( !gParse.is_eobuf ) { - do { - buf[n++] = gParse.expr[gParse.index++]; - } while ((nlng = varNum; - } - return( type ); -} - -static int find_variable(char *varName) -{ - int i; - - if( gParse.nCols ) - for( i=0; i. */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - - -/* Tokens. */ -#ifndef FFTOKENTYPE -# define FFTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum fftokentype { - BOOLEAN = 258, - LONG = 259, - DOUBLE = 260, - STRING = 261, - BITSTR = 262, - FUNCTION = 263, - BFUNCTION = 264, - IFUNCTION = 265, - GTIFILTER = 266, - REGFILTER = 267, - COLUMN = 268, - BCOLUMN = 269, - SCOLUMN = 270, - BITCOL = 271, - ROWREF = 272, - NULLREF = 273, - SNULLREF = 274, - OR = 275, - AND = 276, - NE = 277, - EQ = 278, - GTE = 279, - LTE = 280, - LT = 281, - GT = 282, - POWER = 283, - NOT = 284, - FLTCAST = 285, - INTCAST = 286, - UMINUS = 287, - DIFF = 288, - ACCUM = 289 - }; -#endif -/* Tokens. */ -#define BOOLEAN 258 -#define LONG 259 -#define DOUBLE 260 -#define STRING 261 -#define BITSTR 262 -#define FUNCTION 263 -#define BFUNCTION 264 -#define IFUNCTION 265 -#define GTIFILTER 266 -#define REGFILTER 267 -#define COLUMN 268 -#define BCOLUMN 269 -#define SCOLUMN 270 -#define BITCOL 271 -#define ROWREF 272 -#define NULLREF 273 -#define SNULLREF 274 -#define OR 275 -#define AND 276 -#define NE 277 -#define EQ 278 -#define GTE 279 -#define LTE 280 -#define LT 281 -#define GT 282 -#define POWER 283 -#define NOT 284 -#define FLTCAST 285 -#define INTCAST 286 -#define UMINUS 287 -#define DIFF 288 -#define ACCUM 289 - - - - -#if ! defined FFSTYPE && ! defined FFSTYPE_IS_DECLARED -typedef union FFSTYPE -{ - -/* Line 1676 of yacc.c */ -#line 192 "eval.y" - - int Node; /* Index of Node */ - double dbl; /* real value */ - long lng; /* integer value */ - char log; /* logical value */ - char str[MAX_STRLEN]; /* string value */ - - - -/* Line 1676 of yacc.c */ -#line 130 "y.tab.h" -} FFSTYPE; -# define FFSTYPE_IS_TRIVIAL 1 -# define ffstype FFSTYPE /* obsolescent; will be withdrawn */ -# define FFSTYPE_IS_DECLARED 1 -#endif - -extern FFSTYPE fflval; - - diff --git a/src/external/OpenGR/3rdparty/cfitsio/eval_y.c b/src/external/OpenGR/3rdparty/cfitsio/eval_y.c deleted file mode 100644 index 84cca9918..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/eval_y.c +++ /dev/null @@ -1,8376 +0,0 @@ - -/* A Bison parser, made by GNU Bison 2.4.1. */ - -/* Skeleton implementation for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with ff or FF, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define FFBISON 1 - -/* Bison version. */ -#define FFBISON_VERSION "2.4.1" - -/* Skeleton name. */ -#define FFSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define FFPURE 0 - -/* Push parsers. */ -#define FFPUSH 0 - -/* Pull parsers. */ -#define FFPULL 1 - -/* Using locations. */ -#define FFLSP_NEEDED 0 - - - -/* Copy the first part of user declarations. */ - -/* Line 189 of yacc.c */ -#line 1 "eval.y" - -/************************************************************************/ -/* */ -/* CFITSIO Lexical Parser */ -/* */ -/* This file is one of 3 files containing code which parses an */ -/* arithmetic expression and evaluates it in the context of an input */ -/* FITS file table extension. The CFITSIO lexical parser is divided */ -/* into the following 3 parts/files: the CFITSIO "front-end", */ -/* eval_f.c, contains the interface between the user/CFITSIO and the */ -/* real core of the parser; the FLEX interpreter, eval_l.c, takes the */ -/* input string and parses it into tokens and identifies the FITS */ -/* information required to evaluate the expression (ie, keywords and */ -/* columns); and, the BISON grammar and evaluation routines, eval_y.c, */ -/* receives the FLEX output and determines and performs the actual */ -/* operations. The files eval_l.c and eval_y.c are produced from */ -/* running flex and bison on the files eval.l and eval.y, respectively. */ -/* (flex and bison are available from any GNU archive: see www.gnu.org) */ -/* */ -/* The grammar rules, rather than evaluating the expression in situ, */ -/* builds a tree, or Nodal, structure mapping out the order of */ -/* operations and expression dependencies. This "compilation" process */ -/* allows for much faster processing of multiple rows. This technique */ -/* was developed by Uwe Lammers of the XMM Science Analysis System, */ -/* although the CFITSIO implementation is entirely code original. */ -/* */ -/* */ -/* Modification History: */ -/* */ -/* Kent Blackburn c1992 Original parser code developed for the */ -/* FTOOLS software package, in particular, */ -/* the fselect task. */ -/* Kent Blackburn c1995 BIT column support added */ -/* Peter D Wilson Feb 1998 Vector column support added */ -/* Peter D Wilson May 1998 Ported to CFITSIO library. User */ -/* interface routines written, in essence */ -/* making fselect, fcalc, and maketime */ -/* capabilities available to all tools */ -/* via single function calls. */ -/* Peter D Wilson Jun 1998 Major rewrite of parser core, so as to */ -/* create a run-time evaluation tree, */ -/* inspired by the work of Uwe Lammers, */ -/* resulting in a speed increase of */ -/* 10-100 times. */ -/* Peter D Wilson Jul 1998 gtifilter(a,b,c,d) function added */ -/* Peter D Wilson Aug 1998 regfilter(a,b,c,d) function added */ -/* Peter D Wilson Jul 1999 Make parser fitsfile-independent, */ -/* allowing a purely vector-based usage */ -/* Craig B Markwardt Jun 2004 Add MEDIAN() function */ -/* Craig B Markwardt Jun 2004 Add SUM(), and MIN/MAX() for bit arrays */ -/* Craig B Markwardt Jun 2004 Allow subscripting of nX bit arrays */ -/* Craig B Markwardt Jun 2004 Implement statistical functions */ -/* NVALID(), AVERAGE(), and STDDEV() */ -/* for integer and floating point vectors */ -/* Craig B Markwardt Jun 2004 Use NULL values for range errors instead*/ -/* of throwing a parse error */ -/* Craig B Markwardt Oct 2004 Add ACCUM() and SEQDIFF() functions */ -/* Craig B Markwardt Feb 2005 Add ANGSEP() function */ -/* Craig B Markwardt Aug 2005 CIRCLE, BOX, ELLIPSE, NEAR and REGFILTER*/ -/* functions now accept vector arguments */ -/* Craig B Markwardt Sum 2006 Add RANDOMN() and RANDOMP() functions */ -/* Craig B Markwardt Mar 2007 Allow arguments to RANDOM and RANDOMN to*/ -/* determine the output dimensions */ -/* Craig B Markwardt Aug 2009 Add substring STRMID() and string search*/ -/* STRSTR() functions; more overflow checks*/ -/* */ -/************************************************************************/ - -#define APPROX 1.0e-7 -#include "eval_defs.h" -#include "region.h" -#include - -#include - -#ifndef alloca -#define alloca malloc -#endif - -/* Random number generators for various distributions */ -#include "simplerng.h" - - /* Shrink the initial stack depth to keep local data <32K (mac limit) */ - /* yacc will allocate more space if needed, though. */ -#define FFINITDEPTH 100 - -/***************************************************************/ -/* Replace Bison's BACKUP macro with one that fixes a bug -- */ -/* must update state after popping the stack -- and allows */ -/* popping multiple terms at one time. */ -/***************************************************************/ - -#define FFNEWBACKUP(token, value) \ - do \ - if (ffchar == FFEMPTY ) \ - { ffchar = (token); \ - memcpy( &fflval, &(value), sizeof(value) ); \ - ffchar1 = FFTRANSLATE (ffchar); \ - while (fflen--) FFPOPSTACK; \ - ffstate = *ffssp; \ - goto ffbackup; \ - } \ - else \ - { fferror ("syntax error: cannot back up"); FFERROR; } \ - while (0) - -/***************************************************************/ -/* Useful macros for accessing/testing Nodes */ -/***************************************************************/ - -#define TEST(a) if( (a)<0 ) FFERROR -#define SIZE(a) gParse.Nodes[ a ].value.nelem -#define TYPE(a) gParse.Nodes[ a ].type -#define OPER(a) gParse.Nodes[ a ].operation -#define PROMOTE(a,b) if( TYPE(a) > TYPE(b) ) \ - b = New_Unary( TYPE(a), 0, b ); \ - else if( TYPE(a) < TYPE(b) ) \ - a = New_Unary( TYPE(b), 0, a ); - -/***** Internal functions *****/ - -#ifdef __cplusplus -extern "C" { -#endif - -static int Alloc_Node ( void ); -static void Free_Last_Node( void ); -static void Evaluate_Node ( int thisNode ); - -static int New_Const ( int returnType, void *value, long len ); -static int New_Column( int ColNum ); -static int New_Offset( int ColNum, int offset ); -static int New_Unary ( int returnType, int Op, int Node1 ); -static int New_BinOp ( int returnType, int Node1, int Op, int Node2 ); -static int New_Func ( int returnType, funcOp Op, int nNodes, - int Node1, int Node2, int Node3, int Node4, - int Node5, int Node6, int Node7 ); -static int New_FuncSize( int returnType, funcOp Op, int nNodes, - int Node1, int Node2, int Node3, int Node4, - int Node5, int Node6, int Node7, int Size); -static int New_Deref ( int Var, int nDim, - int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 ); -static int New_GTI ( char *fname, int Node1, char *start, char *stop ); -static int New_REG ( char *fname, int NodeX, int NodeY, char *colNames ); -static int New_Vector( int subNode ); -static int Close_Vec ( int vecNode ); -static int Locate_Col( Node *this ); -static int Test_Dims ( int Node1, int Node2 ); -static void Copy_Dims ( int Node1, int Node2 ); - -static void Allocate_Ptrs( Node *this ); -static void Do_Unary ( Node *this ); -static void Do_Offset ( Node *this ); -static void Do_BinOp_bit ( Node *this ); -static void Do_BinOp_str ( Node *this ); -static void Do_BinOp_log ( Node *this ); -static void Do_BinOp_lng ( Node *this ); -static void Do_BinOp_dbl ( Node *this ); -static void Do_Func ( Node *this ); -static void Do_Deref ( Node *this ); -static void Do_GTI ( Node *this ); -static void Do_REG ( Node *this ); -static void Do_Vector ( Node *this ); - -static long Search_GTI ( double evtTime, long nGTI, double *start, - double *stop, int ordered ); - -static char saobox (double xcen, double ycen, double xwid, double ywid, - double rot, double xcol, double ycol); -static char ellipse(double xcen, double ycen, double xrad, double yrad, - double rot, double xcol, double ycol); -static char circle (double xcen, double ycen, double rad, - double xcol, double ycol); -static char bnear (double x, double y, double tolerance); -static char bitcmp (char *bitstrm1, char *bitstrm2); -static char bitlgte(char *bits1, int oper, char *bits2); - -static void bitand(char *result, char *bitstrm1, char *bitstrm2); -static void bitor (char *result, char *bitstrm1, char *bitstrm2); -static void bitnot(char *result, char *bits); -static int cstrmid(char *dest_str, int dest_len, - char *src_str, int src_len, int pos); - -static void fferror(char *msg); - -#ifdef __cplusplus - } -#endif - - - -/* Line 189 of yacc.c */ -#line 265 "y.tab.c" - -/* Enabling traces. */ -#ifndef FFDEBUG -# define FFDEBUG 0 -#endif - -/* Enabling verbose error messages. */ -#ifdef FFERROR_VERBOSE -# undef FFERROR_VERBOSE -# define FFERROR_VERBOSE 1 -#else -# define FFERROR_VERBOSE 0 -#endif - -/* Enabling the token table. */ -#ifndef FFTOKEN_TABLE -# define FFTOKEN_TABLE 0 -#endif - - -/* Tokens. */ -#ifndef FFTOKENTYPE -# define FFTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum fftokentype { - BOOLEAN = 258, - LONG = 259, - DOUBLE = 260, - STRING = 261, - BITSTR = 262, - FUNCTION = 263, - BFUNCTION = 264, - IFUNCTION = 265, - GTIFILTER = 266, - REGFILTER = 267, - COLUMN = 268, - BCOLUMN = 269, - SCOLUMN = 270, - BITCOL = 271, - ROWREF = 272, - NULLREF = 273, - SNULLREF = 274, - OR = 275, - AND = 276, - NE = 277, - EQ = 278, - GTE = 279, - LTE = 280, - LT = 281, - GT = 282, - POWER = 283, - NOT = 284, - FLTCAST = 285, - INTCAST = 286, - UMINUS = 287, - DIFF = 288, - ACCUM = 289 - }; -#endif -/* Tokens. */ -#define BOOLEAN 258 -#define LONG 259 -#define DOUBLE 260 -#define STRING 261 -#define BITSTR 262 -#define FUNCTION 263 -#define BFUNCTION 264 -#define IFUNCTION 265 -#define GTIFILTER 266 -#define REGFILTER 267 -#define COLUMN 268 -#define BCOLUMN 269 -#define SCOLUMN 270 -#define BITCOL 271 -#define ROWREF 272 -#define NULLREF 273 -#define SNULLREF 274 -#define OR 275 -#define AND 276 -#define NE 277 -#define EQ 278 -#define GTE 279 -#define LTE 280 -#define LT 281 -#define GT 282 -#define POWER 283 -#define NOT 284 -#define FLTCAST 285 -#define INTCAST 286 -#define UMINUS 287 -#define DIFF 288 -#define ACCUM 289 - - - - -#if ! defined FFSTYPE && ! defined FFSTYPE_IS_DECLARED -typedef union FFSTYPE -{ - -/* Line 214 of yacc.c */ -#line 192 "eval.y" - - int Node; /* Index of Node */ - double dbl; /* real value */ - long lng; /* integer value */ - char log; /* logical value */ - char str[MAX_STRLEN]; /* string value */ - - - -/* Line 214 of yacc.c */ -#line 379 "y.tab.c" -} FFSTYPE; -# define FFSTYPE_IS_TRIVIAL 1 -# define ffstype FFSTYPE /* obsolescent; will be withdrawn */ -# define FFSTYPE_IS_DECLARED 1 -#endif - - -/* Copy the second part of user declarations. */ - - -/* Line 264 of yacc.c */ -#line 391 "y.tab.c" - -#ifdef short -# undef short -#endif - -#ifdef FFTYPE_UINT8 -typedef FFTYPE_UINT8 fftype_uint8; -#else -typedef unsigned char fftype_uint8; -#endif - -#ifdef FFTYPE_INT8 -typedef FFTYPE_INT8 fftype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -typedef signed char fftype_int8; -#else -typedef short int fftype_int8; -#endif - -#ifdef FFTYPE_UINT16 -typedef FFTYPE_UINT16 fftype_uint16; -#else -typedef unsigned short int fftype_uint16; -#endif - -#ifdef FFTYPE_INT16 -typedef FFTYPE_INT16 fftype_int16; -#else -typedef short int fftype_int16; -#endif - -#ifndef FFSIZE_T -# ifdef __SIZE_TYPE__ -# define FFSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define FFSIZE_T size_t -# elif ! defined FFSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# define FFSIZE_T size_t -# else -# define FFSIZE_T unsigned int -# endif -#endif - -#define FFSIZE_MAXIMUM ((FFSIZE_T) -1) - -#ifndef FF_ -# if FFENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define FF_(msgid) dgettext ("bison-runtime", msgid) -# endif -# endif -# ifndef FF_ -# define FF_(msgid) msgid -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define FFUSE(e) ((void) (e)) -#else -# define FFUSE(e) /* empty */ -#endif - -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define FFID(n) (n) -#else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -FFID (int ffi) -#else -static int -FFID (ffi) - int ffi; -#endif -{ - return ffi; -} -#endif - -#if ! defined ffoverflow || FFERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef FFSTACK_USE_ALLOCA -# if FFSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define FFSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define FFSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define FFSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# endif -# endif -# endif - -# ifdef FFSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define FFSTACK_FREE(Ptr) do { /* empty */; } while (FFID (0)) -# ifndef FFSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define FFSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define FFSTACK_ALLOC FFMALLOC -# define FFSTACK_FREE FFFREE -# ifndef FFSTACK_ALLOC_MAXIMUM -# define FFSTACK_ALLOC_MAXIMUM FFSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined _STDLIB_H \ - && ! ((defined FFMALLOC || defined malloc) \ - && (defined FFFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# ifndef FFMALLOC -# define FFMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void *malloc (FFSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef FFFREE -# define FFFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined ffoverflow || FFERROR_VERBOSE */ - - -#if (! defined ffoverflow \ - && (! defined __cplusplus \ - || (defined FFSTYPE_IS_TRIVIAL && FFSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union ffalloc -{ - fftype_int16 ffss_alloc; - FFSTYPE ffvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define FFSTACK_GAP_MAXIMUM (sizeof (union ffalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define FFSTACK_BYTES(N) \ - ((N) * (sizeof (fftype_int16) + sizeof (FFSTYPE)) \ - + FFSTACK_GAP_MAXIMUM) - -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef FFCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define FFCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define FFCOPY(To, From, Count) \ - do \ - { \ - FFSIZE_T ffi; \ - for (ffi = 0; ffi < (Count); ffi++) \ - (To)[ffi] = (From)[ffi]; \ - } \ - while (FFID (0)) -# endif -# endif - -/* Relocate STACK from its old location to the new one. The - local variables FFSIZE and FFSTACKSIZE give the old and new number of - elements in the stack, and FFPTR gives the new location of the - stack. Advance FFPTR to a properly aligned location for the next - stack. */ -# define FFSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - FFSIZE_T ffnewbytes; \ - FFCOPY (&ffptr->Stack_alloc, Stack, ffsize); \ - Stack = &ffptr->Stack_alloc; \ - ffnewbytes = ffstacksize * sizeof (*Stack) + FFSTACK_GAP_MAXIMUM; \ - ffptr += ffnewbytes / sizeof (*ffptr); \ - } \ - while (FFID (0)) - -#endif - -/* FFFINAL -- State number of the termination state. */ -#define FFFINAL 2 -/* FFLAST -- Last index in FFTABLE. */ -#define FFLAST 1603 - -/* FFNTOKENS -- Number of terminals. */ -#define FFNTOKENS 54 -/* FFNNTS -- Number of nonterminals. */ -#define FFNNTS 9 -/* FFNRULES -- Number of rules. */ -#define FFNRULES 125 -/* FFNRULES -- Number of states. */ -#define FFNSTATES 290 - -/* FFTRANSLATE(FFLEX) -- Bison symbol number corresponding to FFLEX. */ -#define FFUNDEFTOK 2 -#define FFMAXUTOK 289 - -#define FFTRANSLATE(FFX) \ - ((unsigned int) (FFX) <= FFMAXUTOK ? fftranslate[FFX] : FFUNDEFTOK) - -/* FFTRANSLATE[FFLEX] -- Bison symbol number corresponding to FFLEX. */ -static const fftype_uint8 fftranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 50, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 37, 41, 2, - 52, 53, 38, 35, 20, 36, 2, 39, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, - 2, 21, 2, 25, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 47, 2, 51, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 23, 40, 24, 28, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 26, 27, 29, 30, 31, - 32, 33, 34, 42, 43, 44, 45, 46, 48, 49 -}; - -#if FFDEBUG -/* FFPRHS[FFN] -- Index of the first RHS symbol of rule number FFN in - FFRHS. */ -static const fftype_uint16 ffprhs[] = -{ - 0, 0, 3, 4, 7, 9, 12, 15, 18, 21, - 24, 27, 31, 34, 38, 42, 46, 49, 52, 54, - 56, 61, 65, 69, 73, 78, 85, 94, 105, 118, - 121, 125, 127, 129, 131, 136, 138, 140, 144, 148, - 152, 156, 160, 164, 167, 170, 174, 178, 182, 188, - 194, 200, 203, 207, 211, 215, 219, 225, 231, 241, - 246, 253, 262, 273, 286, 289, 292, 295, 298, 300, - 302, 307, 311, 315, 319, 323, 327, 331, 335, 339, - 343, 347, 351, 355, 359, 363, 367, 371, 375, 379, - 383, 387, 391, 395, 399, 405, 411, 415, 419, 423, - 429, 437, 449, 465, 468, 472, 478, 488, 492, 500, - 510, 515, 522, 531, 542, 555, 558, 562, 564, 566, - 571, 573, 577, 581, 587, 593 -}; - -/* FFRHS -- A `-1'-separated list of the rules' RHS. */ -static const fftype_int8 ffrhs[] = -{ - 55, 0, -1, -1, 55, 56, -1, 50, -1, 59, - 50, -1, 60, 50, -1, 62, 50, -1, 61, 50, - -1, 1, 50, -1, 23, 60, -1, 57, 20, 60, - -1, 23, 59, -1, 58, 20, 59, -1, 58, 20, - 60, -1, 57, 20, 59, -1, 58, 24, -1, 57, - 24, -1, 7, -1, 16, -1, 16, 23, 59, 24, - -1, 61, 41, 61, -1, 61, 40, 61, -1, 61, - 35, 61, -1, 61, 47, 59, 51, -1, 61, 47, - 59, 20, 59, 51, -1, 61, 47, 59, 20, 59, - 20, 59, 51, -1, 61, 47, 59, 20, 59, 20, - 59, 20, 59, 51, -1, 61, 47, 59, 20, 59, - 20, 59, 20, 59, 20, 59, 51, -1, 43, 61, - -1, 52, 61, 53, -1, 4, -1, 5, -1, 13, - -1, 13, 23, 59, 24, -1, 17, -1, 18, -1, - 59, 37, 59, -1, 59, 35, 59, -1, 59, 36, - 59, -1, 59, 38, 59, -1, 59, 39, 59, -1, - 59, 42, 59, -1, 35, 59, -1, 36, 59, -1, - 52, 59, 53, -1, 59, 38, 60, -1, 60, 38, - 59, -1, 60, 25, 59, 22, 59, -1, 60, 25, - 60, 22, 59, -1, 60, 25, 59, 22, 60, -1, - 8, 53, -1, 8, 60, 53, -1, 8, 62, 53, - -1, 8, 61, 53, -1, 8, 59, 53, -1, 10, - 62, 20, 62, 53, -1, 8, 59, 20, 59, 53, - -1, 8, 59, 20, 59, 20, 59, 20, 59, 53, - -1, 59, 47, 59, 51, -1, 59, 47, 59, 20, - 59, 51, -1, 59, 47, 59, 20, 59, 20, 59, - 51, -1, 59, 47, 59, 20, 59, 20, 59, 20, - 59, 51, -1, 59, 47, 59, 20, 59, 20, 59, - 20, 59, 20, 59, 51, -1, 45, 59, -1, 45, - 60, -1, 44, 59, -1, 44, 60, -1, 3, -1, - 14, -1, 14, 23, 59, 24, -1, 61, 30, 61, - -1, 61, 29, 61, -1, 61, 33, 61, -1, 61, - 32, 61, -1, 61, 34, 61, -1, 61, 31, 61, - -1, 59, 34, 59, -1, 59, 33, 59, -1, 59, - 31, 59, -1, 59, 32, 59, -1, 59, 28, 59, - -1, 59, 30, 59, -1, 59, 29, 59, -1, 62, - 30, 62, -1, 62, 29, 62, -1, 62, 34, 62, - -1, 62, 31, 62, -1, 62, 33, 62, -1, 62, - 32, 62, -1, 60, 27, 60, -1, 60, 26, 60, - -1, 60, 30, 60, -1, 60, 29, 60, -1, 59, - 21, 59, 22, 59, -1, 60, 25, 60, 22, 60, - -1, 9, 59, 53, -1, 9, 60, 53, -1, 9, - 62, 53, -1, 8, 60, 20, 60, 53, -1, 9, - 59, 20, 59, 20, 59, 53, -1, 9, 59, 20, - 59, 20, 59, 20, 59, 20, 59, 53, -1, 9, - 59, 20, 59, 20, 59, 20, 59, 20, 59, 20, - 59, 20, 59, 53, -1, 11, 53, -1, 11, 6, - 53, -1, 11, 6, 20, 59, 53, -1, 11, 6, - 20, 59, 20, 6, 20, 6, 53, -1, 12, 6, - 53, -1, 12, 6, 20, 59, 20, 59, 53, -1, - 12, 6, 20, 59, 20, 59, 20, 6, 53, -1, - 60, 47, 59, 51, -1, 60, 47, 59, 20, 59, - 51, -1, 60, 47, 59, 20, 59, 20, 59, 51, - -1, 60, 47, 59, 20, 59, 20, 59, 20, 59, - 51, -1, 60, 47, 59, 20, 59, 20, 59, 20, - 59, 20, 59, 51, -1, 43, 60, -1, 52, 60, - 53, -1, 6, -1, 15, -1, 15, 23, 59, 24, - -1, 19, -1, 52, 62, 53, -1, 62, 35, 62, - -1, 60, 25, 62, 22, 62, -1, 8, 62, 20, - 62, 53, -1, 8, 62, 20, 59, 20, 59, 53, - -1 -}; - -/* FFRLINE[FFN] -- source line where rule number FFN was defined. */ -static const fftype_uint16 ffrline[] = -{ - 0, 244, 244, 245, 248, 249, 255, 261, 267, 273, - 276, 278, 291, 293, 306, 317, 331, 335, 339, 343, - 345, 354, 357, 360, 369, 371, 373, 375, 377, 379, - 382, 386, 388, 390, 392, 401, 403, 405, 408, 411, - 414, 417, 420, 423, 425, 427, 429, 433, 437, 456, - 475, 494, 505, 519, 531, 562, 657, 665, 727, 751, - 753, 755, 757, 759, 761, 763, 765, 767, 771, 773, - 775, 784, 787, 790, 793, 796, 799, 802, 805, 808, - 811, 814, 817, 820, 823, 826, 829, 832, 835, 838, - 841, 843, 845, 847, 850, 857, 874, 887, 900, 911, - 927, 951, 979, 1016, 1020, 1024, 1027, 1031, 1035, 1038, - 1042, 1044, 1046, 1048, 1050, 1052, 1054, 1058, 1061, 1063, - 1072, 1074, 1076, 1085, 1104, 1123 -}; -#endif - -#if FFDEBUG || FFERROR_VERBOSE || FFTOKEN_TABLE -/* FFTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at FFNTOKENS, nonterminals. */ -static const char *const fftname[] = -{ - "$end", "error", "$undefined", "BOOLEAN", "LONG", "DOUBLE", "STRING", - "BITSTR", "FUNCTION", "BFUNCTION", "IFUNCTION", "GTIFILTER", "REGFILTER", - "COLUMN", "BCOLUMN", "SCOLUMN", "BITCOL", "ROWREF", "NULLREF", - "SNULLREF", "','", "'='", "':'", "'{'", "'}'", "'?'", "OR", "AND", "'~'", - "NE", "EQ", "GTE", "LTE", "LT", "GT", "'+'", "'-'", "'%'", "'*'", "'/'", - "'|'", "'&'", "POWER", "NOT", "FLTCAST", "INTCAST", "UMINUS", "'['", - "DIFF", "ACCUM", "'\\n'", "']'", "'('", "')'", "$accept", "lines", - "line", "bvector", "vector", "expr", "bexpr", "bits", "sexpr", 0 -}; -#endif - -# ifdef FFPRINT -/* FFTOKNUM[FFLEX-NUM] -- Internal token number corresponding to - token FFLEX-NUM. */ -static const fftype_uint16 fftoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 44, 61, 58, 123, 125, 63, 275, 276, 126, 277, - 278, 279, 280, 281, 282, 43, 45, 37, 42, 47, - 124, 38, 283, 284, 285, 286, 287, 91, 288, 289, - 10, 93, 40, 41 -}; -# endif - -/* FFR1[FFN] -- Symbol number of symbol that rule FFN derives. */ -static const fftype_uint8 ffr1[] = -{ - 0, 54, 55, 55, 56, 56, 56, 56, 56, 56, - 57, 57, 58, 58, 58, 58, 59, 60, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 62, 62, 62, - 62, 62, 62, 62, 62, 62 -}; - -/* FFR2[FFN] -- Number of symbols composing right hand side of rule FFN. */ -static const fftype_uint8 ffr2[] = -{ - 0, 2, 0, 2, 1, 2, 2, 2, 2, 2, - 2, 3, 2, 3, 3, 3, 2, 2, 1, 1, - 4, 3, 3, 3, 4, 6, 8, 10, 12, 2, - 3, 1, 1, 1, 4, 1, 1, 3, 3, 3, - 3, 3, 3, 2, 2, 3, 3, 3, 5, 5, - 5, 2, 3, 3, 3, 3, 5, 5, 9, 4, - 6, 8, 10, 12, 2, 2, 2, 2, 1, 1, - 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 5, 5, 3, 3, 3, 5, - 7, 11, 15, 2, 3, 5, 9, 3, 7, 9, - 4, 6, 8, 10, 12, 2, 3, 1, 1, 4, - 1, 3, 3, 5, 5, 7 -}; - -/* FFDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when FFTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const fftype_uint8 ffdefact[] = -{ - 2, 0, 1, 0, 68, 31, 32, 117, 18, 0, - 0, 0, 0, 0, 33, 69, 118, 19, 35, 36, - 120, 0, 0, 0, 0, 0, 0, 4, 0, 3, - 0, 0, 0, 0, 0, 0, 9, 51, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 103, 0, 0, 0, 0, 0, 12, 10, 0, 43, - 44, 115, 29, 66, 67, 64, 65, 0, 0, 0, - 0, 0, 17, 0, 16, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 7, 0, 55, - 0, 52, 54, 0, 53, 0, 96, 97, 98, 0, - 0, 104, 0, 107, 0, 0, 0, 0, 45, 116, - 30, 121, 15, 11, 13, 14, 0, 81, 83, 82, - 79, 80, 78, 77, 38, 39, 37, 40, 46, 41, - 42, 0, 0, 0, 0, 91, 90, 93, 92, 47, - 0, 0, 0, 72, 71, 76, 74, 73, 75, 23, - 22, 21, 0, 85, 84, 87, 89, 88, 86, 122, - 0, 0, 0, 0, 0, 0, 0, 0, 34, 70, - 119, 20, 0, 0, 59, 0, 0, 0, 0, 110, - 29, 0, 0, 24, 0, 57, 99, 0, 124, 0, - 56, 0, 105, 0, 94, 0, 48, 50, 49, 95, - 123, 0, 0, 0, 0, 0, 0, 0, 0, 60, - 0, 111, 0, 25, 0, 125, 0, 100, 0, 0, - 108, 0, 0, 0, 0, 0, 0, 0, 0, 61, - 0, 112, 0, 26, 58, 0, 106, 109, 0, 0, - 0, 0, 0, 62, 0, 113, 0, 27, 0, 101, - 0, 0, 0, 0, 63, 114, 28, 0, 0, 102 -}; - -/* FFDEFGOTO[NTERM-NUM]. */ -static const fftype_int8 ffdefgoto[] = -{ - -1, 1, 29, 30, 31, 46, 47, 44, 58 -}; - -/* FFPACT[STATE-NUM] -- Index in FFTABLE of the portion describing - STATE-NUM. */ -#define FFPACT_NINF -46 -static const fftype_int16 ffpact[] = -{ - -46, 297, -46, -45, -46, -46, -46, -46, -46, 347, - 398, 398, -5, 0, -4, 5, 19, 23, -46, -46, - -46, 398, 398, 398, 398, 398, 398, -46, 398, -46, - 6, 17, 1088, 296, 1468, 1490, -46, -46, 424, 9, - 1374, 135, 452, 168, 1518, 344, 1355, 1449, 1555, -10, - -46, -9, 398, 398, 398, 398, 1355, 1449, 250, -2, - -2, 10, 11, -2, 10, -2, 10, 619, 240, 1399, - 1424, 398, -46, 398, -46, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - -46, 398, 398, 398, 398, 398, 398, 398, -46, -3, - -3, -3, -3, -3, -3, -3, -3, -3, 398, -46, - 398, 398, 398, 398, 398, 398, 398, -46, 398, -46, - 398, -46, -46, 398, -46, 398, -46, -46, -46, 398, - 398, -46, 398, -46, 1231, 1251, 1271, 1291, -46, -46, - -46, -46, 1355, 1449, 1355, 1449, 1313, 1535, 1535, 1535, - 1556, 1556, 1556, 1556, 55, 55, 55, -40, 10, -40, - -40, 728, 1335, 400, 201, 74, 111, -35, -35, -40, - 752, -3, -3, 24, 24, 24, 24, 24, 24, 79, - 11, 11, 776, -17, -17, 28, 28, 28, 28, -46, - 480, 342, 1111, 1431, 1131, 1438, 508, 1151, -46, -46, - -46, -46, 398, 398, -46, 398, 398, 398, 398, -46, - 11, 20, 398, -46, 398, -46, -46, 398, -46, 398, - -46, 60, -46, 398, 1499, 800, 1499, 1449, 1499, 1449, - 250, 824, 848, 1171, 646, 536, 48, 564, 398, -46, - 398, -46, 398, -46, 398, -46, 398, -46, 63, 83, - -46, 872, 896, 920, 673, 1191, 39, 45, 398, -46, - 398, -46, 398, -46, -46, 398, -46, -46, 944, 968, - 992, 592, 398, -46, 398, -46, 398, -46, 398, -46, - 1016, 1040, 1064, 1211, -46, -46, -46, 398, 700, -46 -}; - -/* FFPGOTO[NTERM-NUM]. */ -static const fftype_int16 ffpgoto[] = -{ - -46, -46, -46, -46, -46, -1, 90, 147, 22 -}; - -/* FFTABLE[FFPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what FFDEFACT says. - If FFTABLE_NINF, syntax error. */ -#define FFTABLE_NINF -1 -static const fftype_uint16 fftable[] = -{ - 32, 49, 88, 96, 8, 36, 51, 89, 38, 42, - 130, 132, 97, 17, 112, 113, 114, 115, 116, 52, - 56, 59, 60, 35, 63, 65, 71, 67, 53, 120, - 72, 41, 45, 48, 91, 92, 93, 73, 94, 95, - 171, 74, 54, 131, 133, 89, 55, 96, 50, 172, - 70, 134, 135, 136, 137, 105, 97, 97, 108, 105, - 106, 107, 121, 116, 106, 107, 236, 108, 248, 256, - 142, 108, 144, 140, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 159, 160, 161, 257, - 162, 33, 266, 86, 87, 169, 170, 88, 267, 39, - 43, 93, 89, 94, 95, 0, 0, 182, 0, 0, - 0, 57, 96, 164, 61, 64, 66, 190, 68, 106, - 107, 97, 192, 0, 194, 0, 108, 0, 0, 196, - 0, 197, 183, 184, 185, 186, 187, 188, 189, 0, - 94, 95, 0, 0, 0, 193, 0, 0, 34, 96, - 0, 195, 0, 0, 0, 123, 40, 0, 97, 0, - 0, 143, 0, 145, 110, 111, 112, 113, 114, 115, - 116, 62, 0, 0, 0, 69, 158, 0, 0, 0, - 0, 163, 165, 166, 167, 168, 0, 0, 124, 0, - 0, 0, 0, 91, 92, 93, 0, 94, 95, 0, - 0, 224, 225, 0, 226, 228, 96, 231, 0, 0, - 191, 232, 0, 233, 0, 97, 234, 0, 235, 0, - 0, 127, 237, 207, 0, 0, 0, 0, 0, 230, - 110, 111, 112, 113, 114, 115, 116, 251, 0, 252, - 0, 253, 0, 254, 0, 255, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 0, 0, 268, 0, 269, - 0, 270, 0, 0, 271, 91, 92, 93, 0, 94, - 95, 280, 0, 281, 0, 282, 0, 283, 96, 110, - 111, 112, 113, 114, 115, 116, 288, 97, 0, 0, - 0, 0, 0, 139, 0, 227, 229, 2, 3, 0, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 0, 210, 211, - 21, 91, 92, 93, 0, 94, 95, 0, 0, 0, - 0, 0, 22, 23, 96, 0, 0, 0, 0, 0, - 24, 25, 26, 97, 0, 0, 98, 27, 0, 28, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 91, 92, 93, - 21, 94, 95, 110, 111, 112, 113, 114, 115, 116, - 96, 0, 22, 23, 0, 0, 0, 0, 0, 97, - 24, 25, 26, 0, 0, 216, 0, 128, 0, 28, - 37, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, - 0, 21, 206, 0, 0, 91, 92, 93, 0, 94, - 95, 0, 0, 22, 23, 0, 0, 0, 96, 0, - 0, 24, 25, 26, 118, 75, 0, 97, 0, 0, - 28, 0, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, - 0, 89, 125, 75, 0, 0, 0, 119, 0, 0, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, - 214, 75, 0, 0, 0, 126, 0, 0, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 0, 0, 88, 0, 0, 0, 0, 89, 221, 75, - 0, 0, 0, 215, 0, 0, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, - 88, 0, 0, 0, 0, 89, 246, 75, 0, 0, - 0, 222, 0, 0, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, - 0, 0, 0, 89, 249, 75, 0, 0, 0, 247, - 0, 0, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, - 0, 89, 278, 75, 0, 0, 0, 250, 0, 0, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, - 75, 0, 0, 0, 0, 279, 0, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, - 0, 88, 0, 0, 0, 0, 89, 75, 0, 0, - 0, 0, 138, 0, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, - 0, 0, 0, 89, 75, 0, 0, 0, 0, 245, - 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, - 89, 75, 0, 0, 0, 0, 264, 0, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 0, 0, 88, 0, 0, 0, 0, 89, 203, 75, - 0, 0, 0, 289, 0, 0, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, - 88, 0, 208, 75, 0, 89, 0, 0, 0, 204, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 0, 0, 88, 0, 212, 75, 0, 89, - 0, 0, 0, 209, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, - 238, 75, 0, 89, 0, 0, 0, 213, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 0, 0, 88, 0, 240, 75, 0, 89, 0, 0, - 0, 239, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 0, 0, 88, 0, 242, 75, - 0, 89, 0, 0, 0, 241, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, - 88, 0, 258, 75, 0, 89, 0, 0, 0, 243, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 0, 0, 88, 0, 260, 75, 0, 89, - 0, 0, 0, 259, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, - 262, 75, 0, 89, 0, 0, 0, 261, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 0, 0, 88, 0, 272, 75, 0, 89, 0, 0, - 0, 263, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 0, 0, 88, 0, 274, 75, - 0, 89, 0, 0, 0, 273, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, - 88, 0, 276, 75, 0, 89, 0, 0, 0, 275, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 0, 0, 88, 0, 0, 75, 0, 89, - 0, 0, 0, 277, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, - 0, 75, 0, 89, 0, 0, 0, 284, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 0, 0, 88, 0, 0, 75, 0, 89, 0, 0, - 0, 285, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 0, 0, 88, 0, 0, 75, - 0, 89, 0, 0, 0, 286, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, - 88, 217, 75, 0, 0, 89, 0, 0, 90, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 219, 75, 88, 0, 0, 0, 0, 89, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 223, 75, 88, 0, 0, 0, 0, 89, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 244, 75, 88, 0, 0, 0, 0, 89, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 265, 75, 88, 0, 0, 0, 0, 89, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 287, 75, 88, 0, 0, 0, 0, 89, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 0, 75, 88, 0, 198, 0, 0, 89, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 0, 75, 88, 0, 199, 0, 0, 89, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 0, 75, 88, 0, 200, 0, 0, 89, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 0, 75, 88, 0, 201, 0, 0, 89, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 0, 0, 88, 75, 202, 0, 0, 89, 0, - 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 0, 0, 88, 75, 205, 0, 0, - 89, 0, 0, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 0, 75, 88, 0, 0, - 0, 0, 89, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, - 0, 0, 89, 99, 100, 101, 102, 103, 104, 105, - 0, 0, 0, 0, 106, 107, 0, 0, 0, 0, - 0, 108, 0, 0, 0, 0, 0, 122, 99, 100, - 101, 102, 103, 104, 105, 0, 0, 0, 0, 106, - 107, 0, 0, 0, 0, 0, 108, 0, 0, 0, - 0, 0, 140, 110, 111, 112, 113, 114, 115, 116, - 110, 111, 112, 113, 114, 115, 116, 110, 111, 112, - 113, 114, 115, 116, 91, 92, 93, 141, 94, 95, - 0, 0, 0, 0, 218, 0, 0, 96, 0, 0, - 0, 220, 0, 0, 0, 0, 97, 99, 100, 101, - 102, 103, 104, 105, 0, 0, 0, 0, 106, 107, - 0, 0, 0, 0, 0, 108, 0, 0, 109, 110, - 111, 112, 113, 114, 115, 116, 0, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, - 117, 88, 0, 0, 0, 0, 89, 99, 100, 101, - 102, 103, 104, 105, 0, 0, 0, 0, 106, 107, - 0, 0, 0, 0, 0, 108, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 129, 0, 88, 0, 0, - 0, 0, 89, 0, 110, 111, 112, 113, 114, 115, - 116, 83, 84, 85, 86, 87, 0, 0, 88, 0, - 0, 0, 0, 89 -}; - -static const fftype_int16 ffcheck[] = -{ - 1, 6, 42, 38, 7, 50, 6, 47, 9, 10, - 20, 20, 47, 16, 31, 32, 33, 34, 35, 23, - 21, 22, 23, 1, 25, 26, 20, 28, 23, 20, - 24, 9, 10, 11, 25, 26, 27, 20, 29, 30, - 43, 24, 23, 53, 53, 47, 23, 38, 53, 52, - 28, 52, 53, 54, 55, 35, 47, 47, 47, 35, - 40, 41, 53, 35, 40, 41, 6, 47, 20, 6, - 71, 47, 73, 53, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 6, - 91, 1, 53, 38, 39, 96, 97, 42, 53, 9, - 10, 27, 47, 29, 30, -1, -1, 108, -1, -1, - -1, 21, 38, 91, 24, 25, 26, 118, 28, 40, - 41, 47, 123, -1, 125, -1, 47, -1, -1, 130, - -1, 132, 110, 111, 112, 113, 114, 115, 116, -1, - 29, 30, -1, -1, -1, 123, -1, -1, 1, 38, - -1, 129, -1, -1, -1, 20, 9, -1, 47, -1, - -1, 71, -1, 73, 29, 30, 31, 32, 33, 34, - 35, 24, -1, -1, -1, 28, 86, -1, -1, -1, - -1, 91, 92, 93, 94, 95, -1, -1, 53, -1, - -1, -1, -1, 25, 26, 27, -1, 29, 30, -1, - -1, 202, 203, -1, 205, 206, 38, 208, -1, -1, - 120, 212, -1, 214, -1, 47, 217, -1, 219, -1, - -1, 53, 223, 22, -1, -1, -1, -1, -1, 207, - 29, 30, 31, 32, 33, 34, 35, 238, -1, 240, - -1, 242, -1, 244, -1, 246, 99, 100, 101, 102, - 103, 104, 105, 106, 107, -1, -1, 258, -1, 260, - -1, 262, -1, -1, 265, 25, 26, 27, -1, 29, - 30, 272, -1, 274, -1, 276, -1, 278, 38, 29, - 30, 31, 32, 33, 34, 35, 287, 47, -1, -1, - -1, -1, -1, 53, -1, 205, 206, 0, 1, -1, - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, -1, 171, 172, - 23, 25, 26, 27, -1, 29, 30, -1, -1, -1, - -1, -1, 35, 36, 38, -1, -1, -1, -1, -1, - 43, 44, 45, 47, -1, -1, 50, 50, -1, 52, - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 25, 26, 27, - 23, 29, 30, 29, 30, 31, 32, 33, 34, 35, - 38, -1, 35, 36, -1, -1, -1, -1, -1, 47, - 43, 44, 45, -1, -1, 53, -1, 53, -1, 52, - 53, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, -1, -1, - -1, 23, 22, -1, -1, 25, 26, 27, -1, 29, - 30, -1, -1, 35, 36, -1, -1, -1, 38, -1, - -1, 43, 44, 45, 20, 21, -1, 47, -1, -1, - 52, -1, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, - -1, 47, 20, 21, -1, -1, -1, 53, -1, -1, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, - 20, 21, -1, -1, -1, 53, -1, -1, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - -1, -1, 42, -1, -1, -1, -1, 47, 20, 21, - -1, -1, -1, 53, -1, -1, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, - 42, -1, -1, -1, -1, 47, 20, 21, -1, -1, - -1, 53, -1, -1, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, - -1, -1, -1, 47, 20, 21, -1, -1, -1, 53, - -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, - -1, 47, 20, 21, -1, -1, -1, 53, -1, -1, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, - 21, -1, -1, -1, -1, 53, -1, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, - -1, 42, -1, -1, -1, -1, 47, 21, -1, -1, - -1, -1, 53, -1, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, - -1, -1, -1, 47, 21, -1, -1, -1, -1, 53, - -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, - 47, 21, -1, -1, -1, -1, 53, -1, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - -1, -1, 42, -1, -1, -1, -1, 47, 20, 21, - -1, -1, -1, 53, -1, -1, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, - 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, - -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, - 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, - -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, - -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, - 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, - -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, - 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, - -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, - -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, - 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, -1, -1, 42, -1, -1, 21, -1, 47, - -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, - -1, 21, -1, 47, -1, -1, -1, 51, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - -1, -1, 42, -1, -1, 21, -1, 47, -1, -1, - -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, -1, -1, 42, -1, -1, 21, - -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, - 42, 20, 21, -1, -1, 47, -1, -1, 50, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 20, 21, 42, -1, -1, -1, -1, 47, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 20, 21, 42, -1, -1, -1, -1, 47, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 20, 21, 42, -1, -1, -1, -1, 47, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 20, 21, 42, -1, -1, -1, -1, 47, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 20, 21, 42, -1, -1, -1, -1, 47, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, -1, 21, 42, -1, 24, -1, -1, 47, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, -1, 21, 42, -1, 24, -1, -1, 47, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, -1, 21, 42, -1, 24, -1, -1, 47, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, -1, 21, 42, -1, 24, -1, -1, 47, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, -1, -1, 42, 21, 22, -1, -1, 47, -1, - -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, -1, -1, 42, 21, 22, -1, -1, - 47, -1, -1, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, -1, 21, 42, -1, -1, - -1, -1, 47, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, - -1, -1, 47, 29, 30, 31, 32, 33, 34, 35, - -1, -1, -1, -1, 40, 41, -1, -1, -1, -1, - -1, 47, -1, -1, -1, -1, -1, 53, 29, 30, - 31, 32, 33, 34, 35, -1, -1, -1, -1, 40, - 41, -1, -1, -1, -1, -1, 47, -1, -1, -1, - -1, -1, 53, 29, 30, 31, 32, 33, 34, 35, - 29, 30, 31, 32, 33, 34, 35, 29, 30, 31, - 32, 33, 34, 35, 25, 26, 27, 53, 29, 30, - -1, -1, -1, -1, 53, -1, -1, 38, -1, -1, - -1, 53, -1, -1, -1, -1, 47, 29, 30, 31, - 32, 33, 34, 35, -1, -1, -1, -1, 40, 41, - -1, -1, -1, -1, -1, 47, -1, -1, 50, 29, - 30, 31, 32, 33, 34, 35, -1, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, - 50, 42, -1, -1, -1, -1, 47, 29, 30, 31, - 32, 33, 34, 35, -1, -1, -1, -1, 40, 41, - -1, -1, -1, -1, -1, 47, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 20, -1, 42, -1, -1, - -1, -1, 47, -1, 29, 30, 31, 32, 33, 34, - 35, 35, 36, 37, 38, 39, -1, -1, 42, -1, - -1, -1, -1, 47 -}; - -/* FFSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const fftype_uint8 ffstos[] = -{ - 0, 55, 0, 1, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 23, 35, 36, 43, 44, 45, 50, 52, 56, - 57, 58, 59, 60, 61, 62, 50, 53, 59, 60, - 61, 62, 59, 60, 61, 62, 59, 60, 62, 6, - 53, 6, 23, 23, 23, 23, 59, 60, 62, 59, - 59, 60, 61, 59, 60, 59, 60, 59, 60, 61, - 62, 20, 24, 20, 24, 21, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 42, 47, - 50, 25, 26, 27, 29, 30, 38, 47, 50, 29, - 30, 31, 32, 33, 34, 35, 40, 41, 47, 50, - 29, 30, 31, 32, 33, 34, 35, 50, 20, 53, - 20, 53, 53, 20, 53, 20, 53, 53, 53, 20, - 20, 53, 20, 53, 59, 59, 59, 59, 53, 53, - 53, 53, 59, 60, 59, 60, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 60, 59, - 59, 59, 59, 60, 62, 60, 60, 60, 60, 59, - 59, 43, 52, 61, 61, 61, 61, 61, 61, 61, - 61, 61, 59, 62, 62, 62, 62, 62, 62, 62, - 59, 60, 59, 62, 59, 62, 59, 59, 24, 24, - 24, 24, 22, 20, 51, 22, 22, 22, 20, 51, - 61, 61, 20, 51, 20, 53, 53, 20, 53, 20, - 53, 20, 53, 20, 59, 59, 59, 60, 59, 60, - 62, 59, 59, 59, 59, 59, 6, 59, 20, 51, - 20, 51, 20, 51, 20, 53, 20, 53, 20, 20, - 53, 59, 59, 59, 59, 59, 6, 6, 20, 51, - 20, 51, 20, 51, 53, 20, 53, 53, 59, 59, - 59, 59, 20, 51, 20, 51, 20, 51, 20, 53, - 59, 59, 59, 59, 51, 51, 51, 20, 59, 53 -}; - -#define fferrok (fferrstatus = 0) -#define ffclearin (ffchar = FFEMPTY) -#define FFEMPTY (-2) -#define FFEOF 0 - -#define FFACCEPT goto ffacceptlab -#define FFABORT goto ffabortlab -#define FFERROR goto fferrorlab - - -/* Like FFERROR except do call fferror. This remains here temporarily - to ease the transition to the new meaning of FFERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ - -#define FFFAIL goto fferrlab - -#define FFRECOVERING() (!!fferrstatus) - -#define FFBACKUP(Token, Value) \ -do \ - if (ffchar == FFEMPTY && fflen == 1) \ - { \ - ffchar = (Token); \ - fflval = (Value); \ - fftoken = FFTRANSLATE (ffchar); \ - FFPOPSTACK (1); \ - goto ffbackup; \ - } \ - else \ - { \ - fferror (FF_("syntax error: cannot back up")); \ - FFERROR; \ - } \ -while (FFID (0)) - - -#define FFTERROR 1 -#define FFERRCODE 256 - - -/* FFLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define FFRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef FFLLOC_DEFAULT -# define FFLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (FFID (N)) \ - { \ - (Current).first_line = FFRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = FFRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = FFRHSLOC (Rhs, N).last_line; \ - (Current).last_column = FFRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - FFRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - FFRHSLOC (Rhs, 0).last_column; \ - } \ - while (FFID (0)) -#endif - - -/* FF_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef FF_LOCATION_PRINT -# if FFLTYPE_IS_TRIVIAL -# define FF_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define FF_LOCATION_PRINT(File, Loc) ((void) 0) -# endif -#endif - - -/* FFLEX -- calling `fflex' with the right arguments. */ - -#ifdef FFLEX_PARAM -# define FFLEX fflex (FFLEX_PARAM) -#else -# define FFLEX fflex () -#endif - -/* Enable debugging if requested. */ -#if FFDEBUG - -# ifndef FFFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define FFFPRINTF fprintf -# endif - -# define FFDPRINTF(Args) \ -do { \ - if (ffdebug) \ - FFFPRINTF Args; \ -} while (FFID (0)) - -# define FF_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (ffdebug) \ - { \ - FFFPRINTF (stderr, "%s ", Title); \ - ff_symbol_print (stderr, \ - Type, Value); \ - FFFPRINTF (stderr, "\n"); \ - } \ -} while (FFID (0)) - - -/*--------------------------------. -| Print this symbol on FFOUTPUT. | -`--------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -ff_symbol_value_print (FILE *ffoutput, int fftype, FFSTYPE const * const ffvaluep) -#else -static void -ff_symbol_value_print (ffoutput, fftype, ffvaluep) - FILE *ffoutput; - int fftype; - FFSTYPE const * const ffvaluep; -#endif -{ - if (!ffvaluep) - return; -# ifdef FFPRINT - if (fftype < FFNTOKENS) - FFPRINT (ffoutput, fftoknum[fftype], *ffvaluep); -# else - FFUSE (ffoutput); -# endif - switch (fftype) - { - default: - break; - } -} - - -/*--------------------------------. -| Print this symbol on FFOUTPUT. | -`--------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -ff_symbol_print (FILE *ffoutput, int fftype, FFSTYPE const * const ffvaluep) -#else -static void -ff_symbol_print (ffoutput, fftype, ffvaluep) - FILE *ffoutput; - int fftype; - FFSTYPE const * const ffvaluep; -#endif -{ - if (fftype < FFNTOKENS) - FFFPRINTF (ffoutput, "token %s (", fftname[fftype]); - else - FFFPRINTF (ffoutput, "nterm %s (", fftname[fftype]); - - ff_symbol_value_print (ffoutput, fftype, ffvaluep); - FFFPRINTF (ffoutput, ")"); -} - -/*------------------------------------------------------------------. -| ff_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -ff_stack_print (fftype_int16 *ffbottom, fftype_int16 *fftop) -#else -static void -ff_stack_print (ffbottom, fftop) - fftype_int16 *ffbottom; - fftype_int16 *fftop; -#endif -{ - FFFPRINTF (stderr, "Stack now"); - for (; ffbottom <= fftop; ffbottom++) - { - int ffbot = *ffbottom; - FFFPRINTF (stderr, " %d", ffbot); - } - FFFPRINTF (stderr, "\n"); -} - -# define FF_STACK_PRINT(Bottom, Top) \ -do { \ - if (ffdebug) \ - ff_stack_print ((Bottom), (Top)); \ -} while (FFID (0)) - - -/*------------------------------------------------. -| Report that the FFRULE is going to be reduced. | -`------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -ff_reduce_print (FFSTYPE *ffvsp, int ffrule) -#else -static void -ff_reduce_print (ffvsp, ffrule) - FFSTYPE *ffvsp; - int ffrule; -#endif -{ - int ffnrhs = ffr2[ffrule]; - int ffi; - unsigned long int fflno = ffrline[ffrule]; - FFFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - ffrule - 1, fflno); - /* The symbols being reduced. */ - for (ffi = 0; ffi < ffnrhs; ffi++) - { - FFFPRINTF (stderr, " $%d = ", ffi + 1); - ff_symbol_print (stderr, ffrhs[ffprhs[ffrule] + ffi], - &(ffvsp[(ffi + 1) - (ffnrhs)]) - ); - FFFPRINTF (stderr, "\n"); - } -} - -# define FF_REDUCE_PRINT(Rule) \ -do { \ - if (ffdebug) \ - ff_reduce_print (ffvsp, Rule); \ -} while (FFID (0)) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int ffdebug; -#else /* !FFDEBUG */ -# define FFDPRINTF(Args) -# define FF_SYMBOL_PRINT(Title, Type, Value, Location) -# define FF_STACK_PRINT(Bottom, Top) -# define FF_REDUCE_PRINT(Rule) -#endif /* !FFDEBUG */ - - -/* FFINITDEPTH -- initial size of the parser's stacks. */ -#ifndef FFINITDEPTH -# define FFINITDEPTH 200 -#endif - -/* FFMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - FFSTACK_ALLOC_MAXIMUM < FFSTACK_BYTES (FFMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef FFMAXDEPTH -# define FFMAXDEPTH 10000 -#endif - - - -#if FFERROR_VERBOSE - -# ifndef ffstrlen -# if defined __GLIBC__ && defined _STRING_H -# define ffstrlen strlen -# else -/* Return the length of FFSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static FFSIZE_T -ffstrlen (const char *ffstr) -#else -static FFSIZE_T -ffstrlen (ffstr) - const char *ffstr; -#endif -{ - FFSIZE_T fflen; - for (fflen = 0; ffstr[fflen]; fflen++) - continue; - return fflen; -} -# endif -# endif - -# ifndef ffstpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define ffstpcpy stpcpy -# else -/* Copy FFSRC to FFDEST, returning the address of the terminating '\0' in - FFDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static char * -ffstpcpy (char *ffdest, const char *ffsrc) -#else -static char * -ffstpcpy (ffdest, ffsrc) - char *ffdest; - const char *ffsrc; -#endif -{ - char *ffd = ffdest; - const char *ffs = ffsrc; - - while ((*ffd++ = *ffs++) != '\0') - continue; - - return ffd - 1; -} -# endif -# endif - -# ifndef fftnamerr -/* Copy to FFRES the contents of FFSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for fferror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). FFSTR is taken from fftname. If FFRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static FFSIZE_T -fftnamerr (char *ffres, const char *ffstr) -{ - if (*ffstr == '"') - { - FFSIZE_T ffn = 0; - char const *ffp = ffstr; - - for (;;) - switch (*++ffp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++ffp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (ffres) - ffres[ffn] = *ffp; - ffn++; - break; - - case '"': - if (ffres) - ffres[ffn] = '\0'; - return ffn; - } - do_not_strip_quotes: ; - } - - if (! ffres) - return ffstrlen (ffstr); - - return ffstpcpy (ffres, ffstr) - ffres; -} -# endif - -/* Copy into FFRESULT an error message about the unexpected token - FFCHAR while in state FFSTATE. Return the number of bytes copied, - including the terminating null byte. If FFRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return FFSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static FFSIZE_T -ffsyntax_error (char *ffresult, int ffstate, int ffchar) -{ - int ffn = ffpact[ffstate]; - - if (! (FFPACT_NINF < ffn && ffn <= FFLAST)) - return 0; - else - { - int fftype = FFTRANSLATE (ffchar); - FFSIZE_T ffsize0 = fftnamerr (0, fftname[fftype]); - FFSIZE_T ffsize = ffsize0; - FFSIZE_T ffsize1; - int ffsize_overflow = 0; - enum { FFERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *ffarg[FFERROR_VERBOSE_ARGS_MAXIMUM]; - int ffx; - -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - FF_("syntax error, unexpected %s"); - FF_("syntax error, unexpected %s, expecting %s"); - FF_("syntax error, unexpected %s, expecting %s or %s"); - FF_("syntax error, unexpected %s, expecting %s or %s or %s"); - FF_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *fffmt; - char const *fff; - static char const ffunexpected[] = "syntax error, unexpected %s"; - static char const ffexpecting[] = ", expecting %s"; - static char const ffor[] = " or %s"; - char ffformat[sizeof ffunexpected - + sizeof ffexpecting - 1 - + ((FFERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof ffor - 1))]; - char const *ffprefix = ffexpecting; - - /* Start FFX at -FFN if negative to avoid negative indexes in - FFCHECK. */ - int ffxbegin = ffn < 0 ? -ffn : 0; - - /* Stay within bounds of both ffcheck and fftname. */ - int ffchecklim = FFLAST - ffn + 1; - int ffxend = ffchecklim < FFNTOKENS ? ffchecklim : FFNTOKENS; - int ffcount = 1; - - ffarg[0] = fftname[fftype]; - fffmt = ffstpcpy (ffformat, ffunexpected); - - for (ffx = ffxbegin; ffx < ffxend; ++ffx) - if (ffcheck[ffx + ffn] == ffx && ffx != FFTERROR) - { - if (ffcount == FFERROR_VERBOSE_ARGS_MAXIMUM) - { - ffcount = 1; - ffsize = ffsize0; - ffformat[sizeof ffunexpected - 1] = '\0'; - break; - } - ffarg[ffcount++] = fftname[ffx]; - ffsize1 = ffsize + fftnamerr (0, fftname[ffx]); - ffsize_overflow |= (ffsize1 < ffsize); - ffsize = ffsize1; - fffmt = ffstpcpy (fffmt, ffprefix); - ffprefix = ffor; - } - - fff = FF_(ffformat); - ffsize1 = ffsize + ffstrlen (fff); - ffsize_overflow |= (ffsize1 < ffsize); - ffsize = ffsize1; - - if (ffsize_overflow) - return FFSIZE_MAXIMUM; - - if (ffresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *ffp = ffresult; - int ffi = 0; - while ((*ffp = *fff) != '\0') - { - if (*ffp == '%' && fff[1] == 's' && ffi < ffcount) - { - ffp += fftnamerr (ffp, ffarg[ffi++]); - fff += 2; - } - else - { - ffp++; - fff++; - } - } - } - return ffsize; - } -} -#endif /* FFERROR_VERBOSE */ - - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -ffdestruct (const char *ffmsg, int fftype, FFSTYPE *ffvaluep) -#else -static void -ffdestruct (ffmsg, fftype, ffvaluep) - const char *ffmsg; - int fftype; - FFSTYPE *ffvaluep; -#endif -{ - FFUSE (ffvaluep); - - if (!ffmsg) - ffmsg = "Deleting"; - FF_SYMBOL_PRINT (ffmsg, fftype, ffvaluep, fflocationp); - - switch (fftype) - { - - default: - break; - } -} - -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef FFPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int ffparse (void *FFPARSE_PARAM); -#else -int ffparse (); -#endif -#else /* ! FFPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int ffparse (void); -#else -int ffparse (); -#endif -#endif /* ! FFPARSE_PARAM */ - - -/* The lookahead symbol. */ -int ffchar; - -/* The semantic value of the lookahead symbol. */ -FFSTYPE fflval; - -/* Number of syntax errors so far. */ -int ffnerrs; - - - -/*-------------------------. -| ffparse or ffpush_parse. | -`-------------------------*/ - -#ifdef FFPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -ffparse (void *FFPARSE_PARAM) -#else -int -ffparse (FFPARSE_PARAM) - void *FFPARSE_PARAM; -#endif -#else /* ! FFPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -ffparse (void) -#else -int -ffparse () - -#endif -#endif -{ - - - int ffstate; - /* Number of tokens to shift before error messages enabled. */ - int fferrstatus; - - /* The stacks and their tools: - `ffss': related to states. - `ffvs': related to semantic values. - - Refer to the stacks thru separate pointers, to allow ffoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - fftype_int16 ffssa[FFINITDEPTH]; - fftype_int16 *ffss; - fftype_int16 *ffssp; - - /* The semantic value stack. */ - FFSTYPE ffvsa[FFINITDEPTH]; - FFSTYPE *ffvs; - FFSTYPE *ffvsp; - - FFSIZE_T ffstacksize; - - int ffn; - int ffresult; - /* Lookahead token as an internal (translated) token number. */ - int fftoken; - /* The variables used to return semantic value and location from the - action routines. */ - FFSTYPE ffval; - -#if FFERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char ffmsgbuf[128]; - char *ffmsg = ffmsgbuf; - FFSIZE_T ffmsg_alloc = sizeof ffmsgbuf; -#endif - -#define FFPOPSTACK(N) (ffvsp -= (N), ffssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int fflen = 0; - - fftoken = 0; - ffss = ffssa; - ffvs = ffvsa; - ffstacksize = FFINITDEPTH; - - FFDPRINTF ((stderr, "Starting parse\n")); - - ffstate = 0; - fferrstatus = 0; - ffnerrs = 0; - ffchar = FFEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - ffssp = ffss; - ffvsp = ffvs; - - goto ffsetstate; - -/*------------------------------------------------------------. -| ffnewstate -- Push a new state, which is found in ffstate. | -`------------------------------------------------------------*/ - ffnewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - ffssp++; - - ffsetstate: - *ffssp = ffstate; - - if (ffss + ffstacksize - 1 <= ffssp) - { - /* Get the current used size of the three stacks, in elements. */ - FFSIZE_T ffsize = ffssp - ffss + 1; - -#ifdef ffoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - FFSTYPE *ffvs1 = ffvs; - fftype_int16 *ffss1 = ffss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if ffoverflow is a macro. */ - ffoverflow (FF_("memory exhausted"), - &ffss1, ffsize * sizeof (*ffssp), - &ffvs1, ffsize * sizeof (*ffvsp), - &ffstacksize); - - ffss = ffss1; - ffvs = ffvs1; - } -#else /* no ffoverflow */ -# ifndef FFSTACK_RELOCATE - goto ffexhaustedlab; -# else - /* Extend the stack our own way. */ - if (FFMAXDEPTH <= ffstacksize) - goto ffexhaustedlab; - ffstacksize *= 2; - if (FFMAXDEPTH < ffstacksize) - ffstacksize = FFMAXDEPTH; - - { - fftype_int16 *ffss1 = ffss; - union ffalloc *ffptr = - (union ffalloc *) FFSTACK_ALLOC (FFSTACK_BYTES (ffstacksize)); - if (! ffptr) - goto ffexhaustedlab; - FFSTACK_RELOCATE (ffss_alloc, ffss); - FFSTACK_RELOCATE (ffvs_alloc, ffvs); -# undef FFSTACK_RELOCATE - if (ffss1 != ffssa) - FFSTACK_FREE (ffss1); - } -# endif -#endif /* no ffoverflow */ - - ffssp = ffss + ffsize - 1; - ffvsp = ffvs + ffsize - 1; - - FFDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) ffstacksize)); - - if (ffss + ffstacksize - 1 <= ffssp) - FFABORT; - } - - FFDPRINTF ((stderr, "Entering state %d\n", ffstate)); - - if (ffstate == FFFINAL) - FFACCEPT; - - goto ffbackup; - -/*-----------. -| ffbackup. | -`-----------*/ -ffbackup: - - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - ffn = ffpact[ffstate]; - if (ffn == FFPACT_NINF) - goto ffdefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* FFCHAR is either FFEMPTY or FFEOF or a valid lookahead symbol. */ - if (ffchar == FFEMPTY) - { - FFDPRINTF ((stderr, "Reading a token: ")); - ffchar = FFLEX; - } - - if (ffchar <= FFEOF) - { - ffchar = fftoken = FFEOF; - FFDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - fftoken = FFTRANSLATE (ffchar); - FF_SYMBOL_PRINT ("Next token is", fftoken, &fflval, &fflloc); - } - - /* If the proper action on seeing token FFTOKEN is to reduce or to - detect an error, take that action. */ - ffn += fftoken; - if (ffn < 0 || FFLAST < ffn || ffcheck[ffn] != fftoken) - goto ffdefault; - ffn = fftable[ffn]; - if (ffn <= 0) - { - if (ffn == 0 || ffn == FFTABLE_NINF) - goto fferrlab; - ffn = -ffn; - goto ffreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (fferrstatus) - fferrstatus--; - - /* Shift the lookahead token. */ - FF_SYMBOL_PRINT ("Shifting", fftoken, &fflval, &fflloc); - - /* Discard the shifted token. */ - ffchar = FFEMPTY; - - ffstate = ffn; - *++ffvsp = fflval; - - goto ffnewstate; - - -/*-----------------------------------------------------------. -| ffdefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -ffdefault: - ffn = ffdefact[ffstate]; - if (ffn == 0) - goto fferrlab; - goto ffreduce; - - -/*-----------------------------. -| ffreduce -- Do a reduction. | -`-----------------------------*/ -ffreduce: - /* ffn is the number of a rule to reduce with. */ - fflen = ffr2[ffn]; - - /* If FFLEN is nonzero, implement the default value of the action: - `$$ = $1'. - - Otherwise, the following line sets FFVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to FFVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that FFVAL may be used uninitialized. */ - ffval = ffvsp[1-fflen]; - - - FF_REDUCE_PRINT (ffn); - switch (ffn) - { - case 4: - -/* Line 1455 of yacc.c */ -#line 248 "eval.y" - {} - break; - - case 5: - -/* Line 1455 of yacc.c */ -#line 250 "eval.y" - { if( (ffvsp[(1) - (2)].Node)<0 ) { - fferror("Couldn't build node structure: out of memory?"); - FFERROR; } - gParse.resultNode = (ffvsp[(1) - (2)].Node); - } - break; - - case 6: - -/* Line 1455 of yacc.c */ -#line 256 "eval.y" - { if( (ffvsp[(1) - (2)].Node)<0 ) { - fferror("Couldn't build node structure: out of memory?"); - FFERROR; } - gParse.resultNode = (ffvsp[(1) - (2)].Node); - } - break; - - case 7: - -/* Line 1455 of yacc.c */ -#line 262 "eval.y" - { if( (ffvsp[(1) - (2)].Node)<0 ) { - fferror("Couldn't build node structure: out of memory?"); - FFERROR; } - gParse.resultNode = (ffvsp[(1) - (2)].Node); - } - break; - - case 8: - -/* Line 1455 of yacc.c */ -#line 268 "eval.y" - { if( (ffvsp[(1) - (2)].Node)<0 ) { - fferror("Couldn't build node structure: out of memory?"); - FFERROR; } - gParse.resultNode = (ffvsp[(1) - (2)].Node); - } - break; - - case 9: - -/* Line 1455 of yacc.c */ -#line 273 "eval.y" - { fferrok; } - break; - - case 10: - -/* Line 1455 of yacc.c */ -#line 277 "eval.y" - { (ffval.Node) = New_Vector( (ffvsp[(2) - (2)].Node) ); TEST((ffval.Node)); } - break; - - case 11: - -/* Line 1455 of yacc.c */ -#line 279 "eval.y" - { - if( gParse.Nodes[(ffvsp[(1) - (3)].Node)].nSubNodes >= MAXSUBS ) { - (ffvsp[(1) - (3)].Node) = Close_Vec( (ffvsp[(1) - (3)].Node) ); TEST((ffvsp[(1) - (3)].Node)); - (ffval.Node) = New_Vector( (ffvsp[(1) - (3)].Node) ); TEST((ffval.Node)); - } else { - (ffval.Node) = (ffvsp[(1) - (3)].Node); - } - gParse.Nodes[(ffval.Node)].SubNodes[ gParse.Nodes[(ffval.Node)].nSubNodes++ ] - = (ffvsp[(3) - (3)].Node); - } - break; - - case 12: - -/* Line 1455 of yacc.c */ -#line 292 "eval.y" - { (ffval.Node) = New_Vector( (ffvsp[(2) - (2)].Node) ); TEST((ffval.Node)); } - break; - - case 13: - -/* Line 1455 of yacc.c */ -#line 294 "eval.y" - { - if( TYPE((ffvsp[(1) - (3)].Node)) < TYPE((ffvsp[(3) - (3)].Node)) ) - TYPE((ffvsp[(1) - (3)].Node)) = TYPE((ffvsp[(3) - (3)].Node)); - if( gParse.Nodes[(ffvsp[(1) - (3)].Node)].nSubNodes >= MAXSUBS ) { - (ffvsp[(1) - (3)].Node) = Close_Vec( (ffvsp[(1) - (3)].Node) ); TEST((ffvsp[(1) - (3)].Node)); - (ffval.Node) = New_Vector( (ffvsp[(1) - (3)].Node) ); TEST((ffval.Node)); - } else { - (ffval.Node) = (ffvsp[(1) - (3)].Node); - } - gParse.Nodes[(ffval.Node)].SubNodes[ gParse.Nodes[(ffval.Node)].nSubNodes++ ] - = (ffvsp[(3) - (3)].Node); - } - break; - - case 14: - -/* Line 1455 of yacc.c */ -#line 307 "eval.y" - { - if( gParse.Nodes[(ffvsp[(1) - (3)].Node)].nSubNodes >= MAXSUBS ) { - (ffvsp[(1) - (3)].Node) = Close_Vec( (ffvsp[(1) - (3)].Node) ); TEST((ffvsp[(1) - (3)].Node)); - (ffval.Node) = New_Vector( (ffvsp[(1) - (3)].Node) ); TEST((ffval.Node)); - } else { - (ffval.Node) = (ffvsp[(1) - (3)].Node); - } - gParse.Nodes[(ffval.Node)].SubNodes[ gParse.Nodes[(ffval.Node)].nSubNodes++ ] - = (ffvsp[(3) - (3)].Node); - } - break; - - case 15: - -/* Line 1455 of yacc.c */ -#line 318 "eval.y" - { - TYPE((ffvsp[(1) - (3)].Node)) = TYPE((ffvsp[(3) - (3)].Node)); - if( gParse.Nodes[(ffvsp[(1) - (3)].Node)].nSubNodes >= MAXSUBS ) { - (ffvsp[(1) - (3)].Node) = Close_Vec( (ffvsp[(1) - (3)].Node) ); TEST((ffvsp[(1) - (3)].Node)); - (ffval.Node) = New_Vector( (ffvsp[(1) - (3)].Node) ); TEST((ffval.Node)); - } else { - (ffval.Node) = (ffvsp[(1) - (3)].Node); - } - gParse.Nodes[(ffval.Node)].SubNodes[ gParse.Nodes[(ffval.Node)].nSubNodes++ ] - = (ffvsp[(3) - (3)].Node); - } - break; - - case 16: - -/* Line 1455 of yacc.c */ -#line 332 "eval.y" - { (ffval.Node) = Close_Vec( (ffvsp[(1) - (2)].Node) ); TEST((ffval.Node)); } - break; - - case 17: - -/* Line 1455 of yacc.c */ -#line 336 "eval.y" - { (ffval.Node) = Close_Vec( (ffvsp[(1) - (2)].Node) ); TEST((ffval.Node)); } - break; - - case 18: - -/* Line 1455 of yacc.c */ -#line 340 "eval.y" - { - (ffval.Node) = New_Const( BITSTR, (ffvsp[(1) - (1)].str), strlen((ffvsp[(1) - (1)].str))+1 ); TEST((ffval.Node)); - SIZE((ffval.Node)) = strlen((ffvsp[(1) - (1)].str)); } - break; - - case 19: - -/* Line 1455 of yacc.c */ -#line 344 "eval.y" - { (ffval.Node) = New_Column( (ffvsp[(1) - (1)].lng) ); TEST((ffval.Node)); } - break; - - case 20: - -/* Line 1455 of yacc.c */ -#line 346 "eval.y" - { - if( TYPE((ffvsp[(3) - (4)].Node)) != LONG - || OPER((ffvsp[(3) - (4)].Node)) != CONST_OP ) { - fferror("Offset argument must be a constant integer"); - FFERROR; - } - (ffval.Node) = New_Offset( (ffvsp[(1) - (4)].lng), (ffvsp[(3) - (4)].Node) ); TEST((ffval.Node)); - } - break; - - case 21: - -/* Line 1455 of yacc.c */ -#line 355 "eval.y" - { (ffval.Node) = New_BinOp( BITSTR, (ffvsp[(1) - (3)].Node), '&', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); - SIZE((ffval.Node)) = ( SIZE((ffvsp[(1) - (3)].Node))>SIZE((ffvsp[(3) - (3)].Node)) ? SIZE((ffvsp[(1) - (3)].Node)) : SIZE((ffvsp[(3) - (3)].Node)) ); } - break; - - case 22: - -/* Line 1455 of yacc.c */ -#line 358 "eval.y" - { (ffval.Node) = New_BinOp( BITSTR, (ffvsp[(1) - (3)].Node), '|', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); - SIZE((ffval.Node)) = ( SIZE((ffvsp[(1) - (3)].Node))>SIZE((ffvsp[(3) - (3)].Node)) ? SIZE((ffvsp[(1) - (3)].Node)) : SIZE((ffvsp[(3) - (3)].Node)) ); } - break; - - case 23: - -/* Line 1455 of yacc.c */ -#line 361 "eval.y" - { - if (SIZE((ffvsp[(1) - (3)].Node))+SIZE((ffvsp[(3) - (3)].Node)) >= MAX_STRLEN) { - fferror("Combined bit string size exceeds " MAX_STRLEN_S " bits"); - FFERROR; - } - (ffval.Node) = New_BinOp( BITSTR, (ffvsp[(1) - (3)].Node), '+', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); - SIZE((ffval.Node)) = SIZE((ffvsp[(1) - (3)].Node)) + SIZE((ffvsp[(3) - (3)].Node)); - } - break; - - case 24: - -/* Line 1455 of yacc.c */ -#line 370 "eval.y" - { (ffval.Node) = New_Deref( (ffvsp[(1) - (4)].Node), 1, (ffvsp[(3) - (4)].Node), 0, 0, 0, 0 ); TEST((ffval.Node)); } - break; - - case 25: - -/* Line 1455 of yacc.c */ -#line 372 "eval.y" - { (ffval.Node) = New_Deref( (ffvsp[(1) - (6)].Node), 2, (ffvsp[(3) - (6)].Node), (ffvsp[(5) - (6)].Node), 0, 0, 0 ); TEST((ffval.Node)); } - break; - - case 26: - -/* Line 1455 of yacc.c */ -#line 374 "eval.y" - { (ffval.Node) = New_Deref( (ffvsp[(1) - (8)].Node), 3, (ffvsp[(3) - (8)].Node), (ffvsp[(5) - (8)].Node), (ffvsp[(7) - (8)].Node), 0, 0 ); TEST((ffval.Node)); } - break; - - case 27: - -/* Line 1455 of yacc.c */ -#line 376 "eval.y" - { (ffval.Node) = New_Deref( (ffvsp[(1) - (10)].Node), 4, (ffvsp[(3) - (10)].Node), (ffvsp[(5) - (10)].Node), (ffvsp[(7) - (10)].Node), (ffvsp[(9) - (10)].Node), 0 ); TEST((ffval.Node)); } - break; - - case 28: - -/* Line 1455 of yacc.c */ -#line 378 "eval.y" - { (ffval.Node) = New_Deref( (ffvsp[(1) - (12)].Node), 5, (ffvsp[(3) - (12)].Node), (ffvsp[(5) - (12)].Node), (ffvsp[(7) - (12)].Node), (ffvsp[(9) - (12)].Node), (ffvsp[(11) - (12)].Node) ); TEST((ffval.Node)); } - break; - - case 29: - -/* Line 1455 of yacc.c */ -#line 380 "eval.y" - { (ffval.Node) = New_Unary( BITSTR, NOT, (ffvsp[(2) - (2)].Node) ); TEST((ffval.Node)); } - break; - - case 30: - -/* Line 1455 of yacc.c */ -#line 383 "eval.y" - { (ffval.Node) = (ffvsp[(2) - (3)].Node); } - break; - - case 31: - -/* Line 1455 of yacc.c */ -#line 387 "eval.y" - { (ffval.Node) = New_Const( LONG, &((ffvsp[(1) - (1)].lng)), sizeof(long) ); TEST((ffval.Node)); } - break; - - case 32: - -/* Line 1455 of yacc.c */ -#line 389 "eval.y" - { (ffval.Node) = New_Const( DOUBLE, &((ffvsp[(1) - (1)].dbl)), sizeof(double) ); TEST((ffval.Node)); } - break; - - case 33: - -/* Line 1455 of yacc.c */ -#line 391 "eval.y" - { (ffval.Node) = New_Column( (ffvsp[(1) - (1)].lng) ); TEST((ffval.Node)); } - break; - - case 34: - -/* Line 1455 of yacc.c */ -#line 393 "eval.y" - { - if( TYPE((ffvsp[(3) - (4)].Node)) != LONG - || OPER((ffvsp[(3) - (4)].Node)) != CONST_OP ) { - fferror("Offset argument must be a constant integer"); - FFERROR; - } - (ffval.Node) = New_Offset( (ffvsp[(1) - (4)].lng), (ffvsp[(3) - (4)].Node) ); TEST((ffval.Node)); - } - break; - - case 35: - -/* Line 1455 of yacc.c */ -#line 402 "eval.y" - { (ffval.Node) = New_Func( LONG, row_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); } - break; - - case 36: - -/* Line 1455 of yacc.c */ -#line 404 "eval.y" - { (ffval.Node) = New_Func( LONG, null_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); } - break; - - case 37: - -/* Line 1455 of yacc.c */ -#line 406 "eval.y" - { PROMOTE((ffvsp[(1) - (3)].Node),(ffvsp[(3) - (3)].Node)); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), '%', (ffvsp[(3) - (3)].Node) ); - TEST((ffval.Node)); } - break; - - case 38: - -/* Line 1455 of yacc.c */ -#line 409 "eval.y" - { PROMOTE((ffvsp[(1) - (3)].Node),(ffvsp[(3) - (3)].Node)); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), '+', (ffvsp[(3) - (3)].Node) ); - TEST((ffval.Node)); } - break; - - case 39: - -/* Line 1455 of yacc.c */ -#line 412 "eval.y" - { PROMOTE((ffvsp[(1) - (3)].Node),(ffvsp[(3) - (3)].Node)); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), '-', (ffvsp[(3) - (3)].Node) ); - TEST((ffval.Node)); } - break; - - case 40: - -/* Line 1455 of yacc.c */ -#line 415 "eval.y" - { PROMOTE((ffvsp[(1) - (3)].Node),(ffvsp[(3) - (3)].Node)); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), '*', (ffvsp[(3) - (3)].Node) ); - TEST((ffval.Node)); } - break; - - case 41: - -/* Line 1455 of yacc.c */ -#line 418 "eval.y" - { PROMOTE((ffvsp[(1) - (3)].Node),(ffvsp[(3) - (3)].Node)); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), '/', (ffvsp[(3) - (3)].Node) ); - TEST((ffval.Node)); } - break; - - case 42: - -/* Line 1455 of yacc.c */ -#line 421 "eval.y" - { PROMOTE((ffvsp[(1) - (3)].Node),(ffvsp[(3) - (3)].Node)); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), POWER, (ffvsp[(3) - (3)].Node) ); - TEST((ffval.Node)); } - break; - - case 43: - -/* Line 1455 of yacc.c */ -#line 424 "eval.y" - { (ffval.Node) = (ffvsp[(2) - (2)].Node); } - break; - - case 44: - -/* Line 1455 of yacc.c */ -#line 426 "eval.y" - { (ffval.Node) = New_Unary( TYPE((ffvsp[(2) - (2)].Node)), UMINUS, (ffvsp[(2) - (2)].Node) ); TEST((ffval.Node)); } - break; - - case 45: - -/* Line 1455 of yacc.c */ -#line 428 "eval.y" - { (ffval.Node) = (ffvsp[(2) - (3)].Node); } - break; - - case 46: - -/* Line 1455 of yacc.c */ -#line 430 "eval.y" - { (ffvsp[(3) - (3)].Node) = New_Unary( TYPE((ffvsp[(1) - (3)].Node)), 0, (ffvsp[(3) - (3)].Node) ); - (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), '*', (ffvsp[(3) - (3)].Node) ); - TEST((ffval.Node)); } - break; - - case 47: - -/* Line 1455 of yacc.c */ -#line 434 "eval.y" - { (ffvsp[(1) - (3)].Node) = New_Unary( TYPE((ffvsp[(3) - (3)].Node)), 0, (ffvsp[(1) - (3)].Node) ); - (ffval.Node) = New_BinOp( TYPE((ffvsp[(3) - (3)].Node)), (ffvsp[(1) - (3)].Node), '*', (ffvsp[(3) - (3)].Node) ); - TEST((ffval.Node)); } - break; - - case 48: - -/* Line 1455 of yacc.c */ -#line 438 "eval.y" - { - PROMOTE((ffvsp[(3) - (5)].Node),(ffvsp[(5) - (5)].Node)); - if( ! Test_Dims((ffvsp[(3) - (5)].Node),(ffvsp[(5) - (5)].Node)) ) { - fferror("Incompatible dimensions in '?:' arguments"); - FFERROR; - } - (ffval.Node) = New_Func( 0, ifthenelse_fct, 3, (ffvsp[(3) - (5)].Node), (ffvsp[(5) - (5)].Node), (ffvsp[(1) - (5)].Node), - 0, 0, 0, 0 ); - TEST((ffval.Node)); - if( SIZE((ffvsp[(3) - (5)].Node))=SIZE((ffvsp[(4) - (5)].Node)) && Test_Dims( (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node) ) ) { - PROMOTE((ffvsp[(2) - (5)].Node),(ffvsp[(4) - (5)].Node)); - (ffval.Node) = New_Func( 0, defnull_fct, 2, (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node), 0, - 0, 0, 0, 0 ); - TEST((ffval.Node)); - } else { - fferror("Dimensions of DEFNULL arguments " - "are not compatible"); - FFERROR; - } - } else if (FSTRCMP((ffvsp[(1) - (5)].str),"ARCTAN2(") == 0) { - if( TYPE((ffvsp[(2) - (5)].Node)) != DOUBLE ) (ffvsp[(2) - (5)].Node) = New_Unary( DOUBLE, 0, (ffvsp[(2) - (5)].Node) ); - if( TYPE((ffvsp[(4) - (5)].Node)) != DOUBLE ) (ffvsp[(4) - (5)].Node) = New_Unary( DOUBLE, 0, (ffvsp[(4) - (5)].Node) ); - if( Test_Dims( (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node) ) ) { - (ffval.Node) = New_Func( 0, atan2_fct, 2, (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node), 0, 0, 0, 0, 0 ); - TEST((ffval.Node)); - if( SIZE((ffvsp[(2) - (5)].Node))=SIZE((ffvsp[(4) - (5)].Node)) && Test_Dims( (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node) ) ) { - (ffval.Node) = New_Func( 0, defnull_fct, 2, (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node), 0, - 0, 0, 0, 0 ); - TEST((ffval.Node)); - } else { - fferror("Dimensions of DEFNULL arguments are not compatible"); - FFERROR; - } - } else { - fferror("Boolean Function(expr,expr) not supported"); - FFERROR; - } - } - break; - - case 100: - -/* Line 1455 of yacc.c */ -#line 928 "eval.y" - { - if( TYPE((ffvsp[(2) - (7)].Node)) != DOUBLE ) (ffvsp[(2) - (7)].Node) = New_Unary( DOUBLE, 0, (ffvsp[(2) - (7)].Node) ); - if( TYPE((ffvsp[(4) - (7)].Node)) != DOUBLE ) (ffvsp[(4) - (7)].Node) = New_Unary( DOUBLE, 0, (ffvsp[(4) - (7)].Node) ); - if( TYPE((ffvsp[(6) - (7)].Node)) != DOUBLE ) (ffvsp[(6) - (7)].Node) = New_Unary( DOUBLE, 0, (ffvsp[(6) - (7)].Node) ); - if( ! (Test_Dims( (ffvsp[(2) - (7)].Node), (ffvsp[(4) - (7)].Node) ) && Test_Dims( (ffvsp[(4) - (7)].Node), (ffvsp[(6) - (7)].Node) ) ) ) { - fferror("Dimensions of NEAR arguments " - "are not compatible"); - FFERROR; - } else { - if (FSTRCMP((ffvsp[(1) - (7)].str),"NEAR(") == 0) { - (ffval.Node) = New_Func( BOOLEAN, near_fct, 3, (ffvsp[(2) - (7)].Node), (ffvsp[(4) - (7)].Node), (ffvsp[(6) - (7)].Node), - 0, 0, 0, 0 ); - } else { - fferror("Boolean Function not supported"); - FFERROR; - } - TEST((ffval.Node)); - - if( SIZE((ffval.Node))= MAX_STRLEN) { - fferror("Combined string size exceeds " MAX_STRLEN_S " characters"); - FFERROR; - } - (ffval.Node) = New_BinOp( STRING, (ffvsp[(1) - (3)].Node), '+', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); - SIZE((ffval.Node)) = SIZE((ffvsp[(1) - (3)].Node)) + SIZE((ffvsp[(3) - (3)].Node)); - } - break; - - case 123: - -/* Line 1455 of yacc.c */ -#line 1086 "eval.y" - { - int outSize; - if( SIZE((ffvsp[(1) - (5)].Node))!=1 ) { - fferror("Cannot have a vector string column"); - FFERROR; - } - /* Since the output can be calculated now, as a constant - scalar, we must precalculate the output size, in - order to avoid an overflow. */ - outSize = SIZE((ffvsp[(3) - (5)].Node)); - if (SIZE((ffvsp[(5) - (5)].Node)) > outSize) outSize = SIZE((ffvsp[(5) - (5)].Node)); - (ffval.Node) = New_FuncSize( 0, ifthenelse_fct, 3, (ffvsp[(3) - (5)].Node), (ffvsp[(5) - (5)].Node), (ffvsp[(1) - (5)].Node), - 0, 0, 0, 0, outSize); - - TEST((ffval.Node)); - if( SIZE((ffvsp[(3) - (5)].Node)) outSize) outSize = SIZE((ffvsp[(4) - (5)].Node)); - - (ffval.Node) = New_FuncSize( 0, defnull_fct, 2, (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node), 0, - 0, 0, 0, 0, outSize ); - TEST((ffval.Node)); - if( SIZE((ffvsp[(4) - (5)].Node))>SIZE((ffvsp[(2) - (5)].Node)) ) SIZE((ffval.Node)) = SIZE((ffvsp[(4) - (5)].Node)); - } else { - fferror("Function(string,string) not supported"); - FFERROR; - } - } - break; - - case 125: - -/* Line 1455 of yacc.c */ -#line 1124 "eval.y" - { - if (FSTRCMP((ffvsp[(1) - (7)].str),"STRMID(") == 0) { - int len; - if( TYPE((ffvsp[(4) - (7)].Node)) != LONG || SIZE((ffvsp[(4) - (7)].Node)) != 1 || - TYPE((ffvsp[(6) - (7)].Node)) != LONG || SIZE((ffvsp[(6) - (7)].Node)) != 1) { - fferror("When using STRMID(S,P,N), P and N must be integers (and not vector columns)"); - FFERROR; - } - if (OPER((ffvsp[(6) - (7)].Node)) == CONST_OP) { - /* Constant value: use that directly */ - len = (gParse.Nodes[(ffvsp[(6) - (7)].Node)].value.data.lng); - } else { - /* Variable value: use the maximum possible (from $2) */ - len = SIZE((ffvsp[(2) - (7)].Node)); - } - if (len <= 0 || len >= MAX_STRLEN) { - fferror("STRMID(S,P,N), N must be 1-" MAX_STRLEN_S); - FFERROR; - } - (ffval.Node) = New_FuncSize( 0, strmid_fct, 3, (ffvsp[(2) - (7)].Node), (ffvsp[(4) - (7)].Node),(ffvsp[(6) - (7)].Node),0,0,0,0,len); - TEST((ffval.Node)); - } else { - fferror("Function(string,expr,expr) not supported"); - FFERROR; - } - } - break; - - - -/* Line 1455 of yacc.c */ -#line 3584 "y.tab.c" - default: break; - } - FF_SYMBOL_PRINT ("-> $$ =", ffr1[ffn], &ffval, &ffloc); - - FFPOPSTACK (fflen); - fflen = 0; - FF_STACK_PRINT (ffss, ffssp); - - *++ffvsp = ffval; - - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - ffn = ffr1[ffn]; - - ffstate = ffpgoto[ffn - FFNTOKENS] + *ffssp; - if (0 <= ffstate && ffstate <= FFLAST && ffcheck[ffstate] == *ffssp) - ffstate = fftable[ffstate]; - else - ffstate = ffdefgoto[ffn - FFNTOKENS]; - - goto ffnewstate; - - -/*------------------------------------. -| fferrlab -- here on detecting error | -`------------------------------------*/ -fferrlab: - /* If not already recovering from an error, report this error. */ - if (!fferrstatus) - { - ++ffnerrs; -#if ! FFERROR_VERBOSE - fferror (FF_("syntax error")); -#else - { - FFSIZE_T ffsize = ffsyntax_error (0, ffstate, ffchar); - if (ffmsg_alloc < ffsize && ffmsg_alloc < FFSTACK_ALLOC_MAXIMUM) - { - FFSIZE_T ffalloc = 2 * ffsize; - if (! (ffsize <= ffalloc && ffalloc <= FFSTACK_ALLOC_MAXIMUM)) - ffalloc = FFSTACK_ALLOC_MAXIMUM; - if (ffmsg != ffmsgbuf) - FFSTACK_FREE (ffmsg); - ffmsg = (char *) FFSTACK_ALLOC (ffalloc); - if (ffmsg) - ffmsg_alloc = ffalloc; - else - { - ffmsg = ffmsgbuf; - ffmsg_alloc = sizeof ffmsgbuf; - } - } - - if (0 < ffsize && ffsize <= ffmsg_alloc) - { - (void) ffsyntax_error (ffmsg, ffstate, ffchar); - fferror (ffmsg); - } - else - { - fferror (FF_("syntax error")); - if (ffsize != 0) - goto ffexhaustedlab; - } - } -#endif - } - - - - if (fferrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (ffchar <= FFEOF) - { - /* Return failure if at end of input. */ - if (ffchar == FFEOF) - FFABORT; - } - else - { - ffdestruct ("Error: discarding", - fftoken, &fflval); - ffchar = FFEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto fferrlab1; - - -/*---------------------------------------------------. -| fferrorlab -- error raised explicitly by FFERROR. | -`---------------------------------------------------*/ -fferrorlab: - - /* Pacify compilers like GCC when the user code never invokes - FFERROR and the label fferrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto fferrorlab; - - /* Do not reclaim the symbols of the rule which action triggered - this FFERROR. */ - FFPOPSTACK (fflen); - fflen = 0; - FF_STACK_PRINT (ffss, ffssp); - ffstate = *ffssp; - goto fferrlab1; - - -/*-------------------------------------------------------------. -| fferrlab1 -- common code for both syntax error and FFERROR. | -`-------------------------------------------------------------*/ -fferrlab1: - fferrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - ffn = ffpact[ffstate]; - if (ffn != FFPACT_NINF) - { - ffn += FFTERROR; - if (0 <= ffn && ffn <= FFLAST && ffcheck[ffn] == FFTERROR) - { - ffn = fftable[ffn]; - if (0 < ffn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (ffssp == ffss) - FFABORT; - - - ffdestruct ("Error: popping", - ffstos[ffstate], ffvsp); - FFPOPSTACK (1); - ffstate = *ffssp; - FF_STACK_PRINT (ffss, ffssp); - } - - *++ffvsp = fflval; - - - /* Shift the error token. */ - FF_SYMBOL_PRINT ("Shifting", ffstos[ffn], ffvsp, fflsp); - - ffstate = ffn; - goto ffnewstate; - - -/*-------------------------------------. -| ffacceptlab -- FFACCEPT comes here. | -`-------------------------------------*/ -ffacceptlab: - ffresult = 0; - goto ffreturn; - -/*-----------------------------------. -| ffabortlab -- FFABORT comes here. | -`-----------------------------------*/ -ffabortlab: - ffresult = 1; - goto ffreturn; - -#if !defined(ffoverflow) || FFERROR_VERBOSE -/*-------------------------------------------------. -| ffexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -ffexhaustedlab: - fferror (FF_("memory exhausted")); - ffresult = 2; - /* Fall through. */ -#endif - -ffreturn: - if (ffchar != FFEMPTY) - ffdestruct ("Cleanup: discarding lookahead", - fftoken, &fflval); - /* Do not reclaim the symbols of the rule which action triggered - this FFABORT or FFACCEPT. */ - FFPOPSTACK (fflen); - FF_STACK_PRINT (ffss, ffssp); - while (ffssp != ffss) - { - ffdestruct ("Cleanup: popping", - ffstos[*ffssp], ffvsp); - FFPOPSTACK (1); - } -#ifndef ffoverflow - if (ffss != ffssa) - FFSTACK_FREE (ffss); -#endif -#if FFERROR_VERBOSE - if (ffmsg != ffmsgbuf) - FFSTACK_FREE (ffmsg); -#endif - /* Make sure FFID is used. */ - return FFID (ffresult); -} - - - -/* Line 1675 of yacc.c */ -#line 1153 "eval.y" - - -/*************************************************************************/ -/* Start of "New" routines which build the expression Nodal structure */ -/*************************************************************************/ - -static int Alloc_Node( void ) -{ - /* Use this for allocation to guarantee *Nodes */ - Node *newNodePtr; /* survives on failure, making it still valid */ - /* while working our way out of this error */ - - if( gParse.nNodes == gParse.nNodesAlloc ) { - if( gParse.Nodes ) { - gParse.nNodesAlloc += gParse.nNodesAlloc; - newNodePtr = (Node *)realloc( gParse.Nodes, - sizeof(Node)*gParse.nNodesAlloc ); - } else { - gParse.nNodesAlloc = 100; - newNodePtr = (Node *)malloc ( sizeof(Node)*gParse.nNodesAlloc ); - } - - if( newNodePtr ) { - gParse.Nodes = newNodePtr; - } else { - gParse.status = MEMORY_ALLOCATION; - return( -1 ); - } - } - - return ( gParse.nNodes++ ); -} - -static void Free_Last_Node( void ) -{ - if( gParse.nNodes ) gParse.nNodes--; -} - -static int New_Const( int returnType, void *value, long len ) -{ - Node *this; - int n; - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->operation = CONST_OP; /* Flag a constant */ - this->DoOp = NULL; - this->nSubNodes = 0; - this->type = returnType; - memcpy( &(this->value.data), value, len ); - this->value.undef = NULL; - this->value.nelem = 1; - this->value.naxis = 1; - this->value.naxes[0] = 1; - } - return(n); -} - -static int New_Column( int ColNum ) -{ - Node *this; - int n, i; - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->operation = -ColNum; - this->DoOp = NULL; - this->nSubNodes = 0; - this->type = gParse.varData[ColNum].type; - this->value.nelem = gParse.varData[ColNum].nelem; - this->value.naxis = gParse.varData[ColNum].naxis; - for( i=0; ivalue.naxes[i] = gParse.varData[ColNum].naxes[i]; - } - return(n); -} - -static int New_Offset( int ColNum, int offsetNode ) -{ - Node *this; - int n, i, colNode; - - colNode = New_Column( ColNum ); - if( colNode<0 ) return(-1); - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->operation = '{'; - this->DoOp = Do_Offset; - this->nSubNodes = 2; - this->SubNodes[0] = colNode; - this->SubNodes[1] = offsetNode; - this->type = gParse.varData[ColNum].type; - this->value.nelem = gParse.varData[ColNum].nelem; - this->value.naxis = gParse.varData[ColNum].naxis; - for( i=0; ivalue.naxes[i] = gParse.varData[ColNum].naxes[i]; - } - return(n); -} - -static int New_Unary( int returnType, int Op, int Node1 ) -{ - Node *this, *that; - int i,n; - - if( Node1<0 ) return(-1); - that = gParse.Nodes + Node1; - - if( !Op ) Op = returnType; - - if( (Op==DOUBLE || Op==FLTCAST) && that->type==DOUBLE ) return( Node1 ); - if( (Op==LONG || Op==INTCAST) && that->type==LONG ) return( Node1 ); - if( (Op==BOOLEAN ) && that->type==BOOLEAN ) return( Node1 ); - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->operation = Op; - this->DoOp = Do_Unary; - this->nSubNodes = 1; - this->SubNodes[0] = Node1; - this->type = returnType; - - that = gParse.Nodes + Node1; /* Reset in case .Nodes mv'd */ - this->value.nelem = that->value.nelem; - this->value.naxis = that->value.naxis; - for( i=0; ivalue.naxis; i++ ) - this->value.naxes[i] = that->value.naxes[i]; - - if( that->operation==CONST_OP ) this->DoOp( this ); - } - return( n ); -} - -static int New_BinOp( int returnType, int Node1, int Op, int Node2 ) -{ - Node *this,*that1,*that2; - int n,i,constant; - - if( Node1<0 || Node2<0 ) return(-1); - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->operation = Op; - this->nSubNodes = 2; - this->SubNodes[0]= Node1; - this->SubNodes[1]= Node2; - this->type = returnType; - - that1 = gParse.Nodes + Node1; - that2 = gParse.Nodes + Node2; - constant = (that1->operation==CONST_OP - && that2->operation==CONST_OP); - if( that1->type!=STRING && that1->type!=BITSTR ) - if( !Test_Dims( Node1, Node2 ) ) { - Free_Last_Node(); - fferror("Array sizes/dims do not match for binary operator"); - return(-1); - } - if( that1->value.nelem == 1 ) that1 = that2; - - this->value.nelem = that1->value.nelem; - this->value.naxis = that1->value.naxis; - for( i=0; ivalue.naxis; i++ ) - this->value.naxes[i] = that1->value.naxes[i]; - - if ( Op == ACCUM && that1->type == BITSTR ) { - /* ACCUM is rank-reducing on bit strings */ - this->value.nelem = 1; - this->value.naxis = 1; - this->value.naxes[0] = 1; - } - - /* Both subnodes should be of same time */ - switch( that1->type ) { - case BITSTR: this->DoOp = Do_BinOp_bit; break; - case STRING: this->DoOp = Do_BinOp_str; break; - case BOOLEAN: this->DoOp = Do_BinOp_log; break; - case LONG: this->DoOp = Do_BinOp_lng; break; - case DOUBLE: this->DoOp = Do_BinOp_dbl; break; - } - if( constant ) this->DoOp( this ); - } - return( n ); -} - -static int New_Func( int returnType, funcOp Op, int nNodes, - int Node1, int Node2, int Node3, int Node4, - int Node5, int Node6, int Node7 ) -{ - return New_FuncSize(returnType, Op, nNodes, - Node1, Node2, Node3, Node4, - Node5, Node6, Node7, 0); -} - -static int New_FuncSize( int returnType, funcOp Op, int nNodes, - int Node1, int Node2, int Node3, int Node4, - int Node5, int Node6, int Node7, int Size ) -/* If returnType==0 , use Node1's type and vector sizes as returnType, */ -/* else return a single value of type returnType */ -{ - Node *this, *that; - int i,n,constant; - - if( Node1<0 || Node2<0 || Node3<0 || Node4<0 || - Node5<0 || Node6<0 || Node7<0 ) return(-1); - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->operation = (int)Op; - this->DoOp = Do_Func; - this->nSubNodes = nNodes; - this->SubNodes[0] = Node1; - this->SubNodes[1] = Node2; - this->SubNodes[2] = Node3; - this->SubNodes[3] = Node4; - this->SubNodes[4] = Node5; - this->SubNodes[5] = Node6; - this->SubNodes[6] = Node7; - i = constant = nNodes; /* Functions with zero params are not const */ - if (Op == poirnd_fct) constant = 0; /* Nor is Poisson deviate */ - - while( i-- ) - constant = ( constant && OPER(this->SubNodes[i]) == CONST_OP ); - - if( returnType ) { - this->type = returnType; - this->value.nelem = 1; - this->value.naxis = 1; - this->value.naxes[0] = 1; - } else { - that = gParse.Nodes + Node1; - this->type = that->type; - this->value.nelem = that->value.nelem; - this->value.naxis = that->value.naxis; - for( i=0; ivalue.naxis; i++ ) - this->value.naxes[i] = that->value.naxes[i]; - } - /* Force explicit size before evaluating */ - if (Size > 0) this->value.nelem = Size; - - if( constant ) this->DoOp( this ); - } - return( n ); -} - -static int New_Deref( int Var, int nDim, - int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 ) -{ - int n, idx, constant; - long elem=0; - Node *this, *theVar, *theDim[MAXDIMS]; - - if( Var<0 || Dim1<0 || Dim2<0 || Dim3<0 || Dim4<0 || Dim5<0 ) return(-1); - - theVar = gParse.Nodes + Var; - if( theVar->operation==CONST_OP || theVar->value.nelem==1 ) { - fferror("Cannot index a scalar value"); - return(-1); - } - - n = Alloc_Node(); - if( n>=0 ) { - this = gParse.Nodes + n; - this->nSubNodes = nDim+1; - theVar = gParse.Nodes + (this->SubNodes[0]=Var); - theDim[0] = gParse.Nodes + (this->SubNodes[1]=Dim1); - theDim[1] = gParse.Nodes + (this->SubNodes[2]=Dim2); - theDim[2] = gParse.Nodes + (this->SubNodes[3]=Dim3); - theDim[3] = gParse.Nodes + (this->SubNodes[4]=Dim4); - theDim[4] = gParse.Nodes + (this->SubNodes[5]=Dim5); - constant = theVar->operation==CONST_OP; - for( idx=0; idxoperation==CONST_OP); - - for( idx=0; idxvalue.nelem>1 ) { - Free_Last_Node(); - fferror("Cannot use an array as an index value"); - return(-1); - } else if( theDim[idx]->type!=LONG ) { - Free_Last_Node(); - fferror("Index value must be an integer type"); - return(-1); - } - - this->operation = '['; - this->DoOp = Do_Deref; - this->type = theVar->type; - - if( theVar->value.naxis == nDim ) { /* All dimensions specified */ - this->value.nelem = 1; - this->value.naxis = 1; - this->value.naxes[0] = 1; - } else if( nDim==1 ) { /* Dereference only one dimension */ - elem=1; - this->value.naxis = theVar->value.naxis-1; - for( idx=0; idxvalue.naxis; idx++ ) { - elem *= ( this->value.naxes[idx] = theVar->value.naxes[idx] ); - } - this->value.nelem = elem; - } else { - Free_Last_Node(); - fferror("Must specify just one or all indices for vector"); - return(-1); - } - if( constant ) this->DoOp( this ); - } - return(n); -} - -extern int ffGetVariable( char *varName, FFSTYPE *varVal ); - -static int New_GTI( char *fname, int Node1, char *start, char *stop ) -{ - fitsfile *fptr; - Node *this, *that0, *that1; - int type,i,n, startCol, stopCol, Node0; - int hdutype, hdunum, evthdu, samefile, extvers, movetotype, tstat; - char extname[100]; - long nrows; - double timeZeroI[2], timeZeroF[2], dt, timeSpan; - char xcol[20], xexpr[20]; - FFSTYPE colVal; - - if( Node1==-99 ) { - type = ffGetVariable( "TIME", &colVal ); - if( type==COLUMN ) { - Node1 = New_Column( (int)colVal.lng ); - } else { - fferror("Could not build TIME column for GTIFILTER"); - return(-1); - } - } - Node1 = New_Unary( DOUBLE, 0, Node1 ); - Node0 = Alloc_Node(); /* This will hold the START/STOP times */ - if( Node1<0 || Node0<0 ) return(-1); - - /* Record current HDU number in case we need to move within this file */ - - fptr = gParse.def_fptr; - ffghdn( fptr, &evthdu ); - - /* Look for TIMEZERO keywords in current extension */ - - tstat = 0; - if( ffgkyd( fptr, "TIMEZERO", timeZeroI, NULL, &tstat ) ) { - tstat = 0; - if( ffgkyd( fptr, "TIMEZERI", timeZeroI, NULL, &tstat ) ) { - timeZeroI[0] = timeZeroF[0] = 0.0; - } else if( ffgkyd( fptr, "TIMEZERF", timeZeroF, NULL, &tstat ) ) { - timeZeroF[0] = 0.0; - } - } else { - timeZeroF[0] = 0.0; - } - - /* Resolve filename parameter */ - - switch( fname[0] ) { - case '\0': - samefile = 1; - hdunum = 1; - break; - case '[': - samefile = 1; - i = 1; - while( fname[i] != '\0' && fname[i] != ']' ) i++; - if( fname[i] ) { - fname[i] = '\0'; - fname++; - ffexts( fname, &hdunum, extname, &extvers, &movetotype, - xcol, xexpr, &gParse.status ); - if( *extname ) { - ffmnhd( fptr, movetotype, extname, extvers, &gParse.status ); - ffghdn( fptr, &hdunum ); - } else if( hdunum ) { - ffmahd( fptr, ++hdunum, &hdutype, &gParse.status ); - } else if( !gParse.status ) { - fferror("Cannot use primary array for GTI filter"); - return( -1 ); - } - } else { - fferror("File extension specifier lacks closing ']'"); - return( -1 ); - } - break; - case '+': - samefile = 1; - hdunum = atoi( fname ) + 1; - if( hdunum>1 ) - ffmahd( fptr, hdunum, &hdutype, &gParse.status ); - else { - fferror("Cannot use primary array for GTI filter"); - return( -1 ); - } - break; - default: - samefile = 0; - if( ! ffopen( &fptr, fname, READONLY, &gParse.status ) ) - ffghdn( fptr, &hdunum ); - break; - } - if( gParse.status ) return(-1); - - /* If at primary, search for GTI extension */ - - if( hdunum==1 ) { - while( 1 ) { - hdunum++; - if( ffmahd( fptr, hdunum, &hdutype, &gParse.status ) ) break; - if( hdutype==IMAGE_HDU ) continue; - tstat = 0; - if( ffgkys( fptr, "EXTNAME", extname, NULL, &tstat ) ) continue; - ffupch( extname ); - if( strstr( extname, "GTI" ) ) break; - } - if( gParse.status ) { - if( gParse.status==END_OF_FILE ) - fferror("GTI extension not found in this file"); - return(-1); - } - } - - /* Locate START/STOP Columns */ - - ffgcno( fptr, CASEINSEN, start, &startCol, &gParse.status ); - ffgcno( fptr, CASEINSEN, stop, &stopCol, &gParse.status ); - if( gParse.status ) return(-1); - - /* Look for TIMEZERO keywords in GTI extension */ - - tstat = 0; - if( ffgkyd( fptr, "TIMEZERO", timeZeroI+1, NULL, &tstat ) ) { - tstat = 0; - if( ffgkyd( fptr, "TIMEZERI", timeZeroI+1, NULL, &tstat ) ) { - timeZeroI[1] = timeZeroF[1] = 0.0; - } else if( ffgkyd( fptr, "TIMEZERF", timeZeroF+1, NULL, &tstat ) ) { - timeZeroF[1] = 0.0; - } - } else { - timeZeroF[1] = 0.0; - } - - n = Alloc_Node(); - if( n >= 0 ) { - this = gParse.Nodes + n; - this->nSubNodes = 2; - this->SubNodes[1] = Node1; - this->operation = (int)gtifilt_fct; - this->DoOp = Do_GTI; - this->type = BOOLEAN; - that1 = gParse.Nodes + Node1; - this->value.nelem = that1->value.nelem; - this->value.naxis = that1->value.naxis; - for( i=0; i < that1->value.naxis; i++ ) - this->value.naxes[i] = that1->value.naxes[i]; - - /* Init START/STOP node to be treated as a "constant" */ - - this->SubNodes[0] = Node0; - that0 = gParse.Nodes + Node0; - that0->operation = CONST_OP; - that0->DoOp = NULL; - that0->value.data.ptr= NULL; - - /* Read in START/STOP times */ - - if( ffgkyj( fptr, "NAXIS2", &nrows, NULL, &gParse.status ) ) - return(-1); - that0->value.nelem = nrows; - if( nrows ) { - - that0->value.data.dblptr = (double*)malloc( 2*nrows*sizeof(double) ); - if( !that0->value.data.dblptr ) { - gParse.status = MEMORY_ALLOCATION; - return(-1); - } - - ffgcvd( fptr, startCol, 1L, 1L, nrows, 0.0, - that0->value.data.dblptr, &i, &gParse.status ); - ffgcvd( fptr, stopCol, 1L, 1L, nrows, 0.0, - that0->value.data.dblptr+nrows, &i, &gParse.status ); - if( gParse.status ) { - free( that0->value.data.dblptr ); - return(-1); - } - - /* Test for fully time-ordered GTI... both START && STOP */ - - that0->type = 1; /* Assume yes */ - i = nrows; - while( --i ) - if( that0->value.data.dblptr[i-1] - >= that0->value.data.dblptr[i] - || that0->value.data.dblptr[i-1+nrows] - >= that0->value.data.dblptr[i+nrows] ) { - that0->type = 0; - break; - } - - /* Handle TIMEZERO offset, if any */ - - dt = (timeZeroI[1] - timeZeroI[0]) + (timeZeroF[1] - timeZeroF[0]); - timeSpan = that0->value.data.dblptr[nrows+nrows-1] - - that0->value.data.dblptr[0]; - - if( fabs( dt / timeSpan ) > 1e-12 ) { - for( i=0; i<(nrows+nrows); i++ ) - that0->value.data.dblptr[i] += dt; - } - } - if( OPER(Node1)==CONST_OP ) - this->DoOp( this ); - } - - if( samefile ) - ffmahd( fptr, evthdu, &hdutype, &gParse.status ); - else - ffclos( fptr, &gParse.status ); - - return( n ); -} - -static int New_REG( char *fname, int NodeX, int NodeY, char *colNames ) -{ - Node *this, *that0; - int type, n, Node0; - int Xcol, Ycol, tstat; - WCSdata wcs; - SAORegion *Rgn; - char *cX, *cY; - FFSTYPE colVal; - - if( NodeX==-99 ) { - type = ffGetVariable( "X", &colVal ); - if( type==COLUMN ) { - NodeX = New_Column( (int)colVal.lng ); - } else { - fferror("Could not build X column for REGFILTER"); - return(-1); - } - } - if( NodeY==-99 ) { - type = ffGetVariable( "Y", &colVal ); - if( type==COLUMN ) { - NodeY = New_Column( (int)colVal.lng ); - } else { - fferror("Could not build Y column for REGFILTER"); - return(-1); - } - } - NodeX = New_Unary( DOUBLE, 0, NodeX ); - NodeY = New_Unary( DOUBLE, 0, NodeY ); - Node0 = Alloc_Node(); /* This will hold the Region Data */ - if( NodeX<0 || NodeY<0 || Node0<0 ) return(-1); - - if( ! (Test_Dims( NodeX, NodeY ) ) ) { - fferror("Dimensions of REGFILTER arguments are not compatible"); - return (-1); - } - - n = Alloc_Node(); - if( n >= 0 ) { - this = gParse.Nodes + n; - this->nSubNodes = 3; - this->SubNodes[0] = Node0; - this->SubNodes[1] = NodeX; - this->SubNodes[2] = NodeY; - this->operation = (int)regfilt_fct; - this->DoOp = Do_REG; - this->type = BOOLEAN; - this->value.nelem = 1; - this->value.naxis = 1; - this->value.naxes[0] = 1; - - Copy_Dims(n, NodeX); - if( SIZE(NodeX)operation = CONST_OP; - that0->DoOp = NULL; - - /* Identify what columns to use for WCS information */ - - Xcol = Ycol = 0; - if( *colNames ) { - /* Use the column names in this string for WCS info */ - while( *colNames==' ' ) colNames++; - cX = cY = colNames; - while( *cY && *cY!=' ' && *cY!=',' ) cY++; - if( *cY ) - *(cY++) = '\0'; - while( *cY==' ' ) cY++; - if( !*cY ) { - fferror("Could not extract valid pair of column names from REGFILTER"); - Free_Last_Node(); - return( -1 ); - } - fits_get_colnum( gParse.def_fptr, CASEINSEN, cX, &Xcol, - &gParse.status ); - fits_get_colnum( gParse.def_fptr, CASEINSEN, cY, &Ycol, - &gParse.status ); - if( gParse.status ) { - fferror("Could not locate columns indicated for WCS info"); - Free_Last_Node(); - return( -1 ); - } - - } else { - /* Try to find columns used in X/Y expressions */ - Xcol = Locate_Col( gParse.Nodes + NodeX ); - Ycol = Locate_Col( gParse.Nodes + NodeY ); - if( Xcol<0 || Ycol<0 ) { - fferror("Found multiple X/Y column references in REGFILTER"); - Free_Last_Node(); - return( -1 ); - } - } - - /* Now, get the WCS info, if it exists, from the indicated columns */ - wcs.exists = 0; - if( Xcol>0 && Ycol>0 ) { - tstat = 0; - ffgtcs( gParse.def_fptr, Xcol, Ycol, - &wcs.xrefval, &wcs.yrefval, - &wcs.xrefpix, &wcs.yrefpix, - &wcs.xinc, &wcs.yinc, - &wcs.rot, wcs.type, - &tstat ); - if( tstat==NO_WCS_KEY ) { - wcs.exists = 0; - } else if( tstat ) { - gParse.status = tstat; - Free_Last_Node(); - return( -1 ); - } else { - wcs.exists = 1; - } - } - - /* Read in Region file */ - - fits_read_rgnfile( fname, &wcs, &Rgn, &gParse.status ); - if( gParse.status ) { - Free_Last_Node(); - return( -1 ); - } - - that0->value.data.ptr = Rgn; - - if( OPER(NodeX)==CONST_OP && OPER(NodeY)==CONST_OP ) - this->DoOp( this ); - } - - return( n ); -} - -static int New_Vector( int subNode ) -{ - Node *this, *that; - int n; - - n = Alloc_Node(); - if( n >= 0 ) { - this = gParse.Nodes + n; - that = gParse.Nodes + subNode; - this->type = that->type; - this->nSubNodes = 1; - this->SubNodes[0] = subNode; - this->operation = '{'; - this->DoOp = Do_Vector; - } - - return( n ); -} - -static int Close_Vec( int vecNode ) -{ - Node *this; - int n, nelem=0; - - this = gParse.Nodes + vecNode; - for( n=0; n < this->nSubNodes; n++ ) { - if( TYPE( this->SubNodes[n] ) != this->type ) { - this->SubNodes[n] = New_Unary( this->type, 0, this->SubNodes[n] ); - if( this->SubNodes[n]<0 ) return(-1); - } - nelem += SIZE(this->SubNodes[n]); - } - this->value.naxis = 1; - this->value.nelem = nelem; - this->value.naxes[0] = nelem; - - return( vecNode ); -} - -static int Locate_Col( Node *this ) -/* Locate the TABLE column number of any columns in "this" calculation. */ -/* Return ZERO if none found, or negative if more than 1 found. */ -{ - Node *that; - int i, col=0, newCol, nfound=0; - - if( this->nSubNodes==0 - && this->operation<=0 && this->operation!=CONST_OP ) - return gParse.colData[ - this->operation].colnum; - - for( i=0; inSubNodes; i++ ) { - that = gParse.Nodes + this->SubNodes[i]; - if( that->operation>0 ) { - newCol = Locate_Col( that ); - if( newCol<=0 ) { - nfound += -newCol; - } else { - if( !nfound ) { - col = newCol; - nfound++; - } else if( col != newCol ) { - nfound++; - } - } - } else if( that->operation!=CONST_OP ) { - /* Found a Column */ - newCol = gParse.colData[- that->operation].colnum; - if( !nfound ) { - col = newCol; - nfound++; - } else if( col != newCol ) { - nfound++; - } - } - } - if( nfound!=1 ) - return( - nfound ); - else - return( col ); -} - -static int Test_Dims( int Node1, int Node2 ) -{ - Node *that1, *that2; - int valid, i; - - if( Node1<0 || Node2<0 ) return(0); - - that1 = gParse.Nodes + Node1; - that2 = gParse.Nodes + Node2; - - if( that1->value.nelem==1 || that2->value.nelem==1 ) - valid = 1; - else if( that1->type==that2->type - && that1->value.nelem==that2->value.nelem - && that1->value.naxis==that2->value.naxis ) { - valid = 1; - for( i=0; ivalue.naxis; i++ ) { - if( that1->value.naxes[i]!=that2->value.naxes[i] ) - valid = 0; - } - } else - valid = 0; - return( valid ); -} - -static void Copy_Dims( int Node1, int Node2 ) -{ - Node *that1, *that2; - int i; - - if( Node1<0 || Node2<0 ) return; - - that1 = gParse.Nodes + Node1; - that2 = gParse.Nodes + Node2; - - that1->value.nelem = that2->value.nelem; - that1->value.naxis = that2->value.naxis; - for( i=0; ivalue.naxis; i++ ) - that1->value.naxes[i] = that2->value.naxes[i]; -} - -/********************************************************************/ -/* Routines for actually evaluating the expression start here */ -/********************************************************************/ - -void Evaluate_Parser( long firstRow, long nRows ) - /***********************************************************************/ - /* Reset the parser for processing another batch of data... */ - /* firstRow: Row number of the first element to evaluate */ - /* nRows: Number of rows to be processed */ - /* Initialize each COLUMN node so that its UNDEF and DATA pointers */ - /* point to the appropriate column arrays. */ - /* Finally, call Evaluate_Node for final node. */ - /***********************************************************************/ -{ - int i, column; - long offset, rowOffset; - static int rand_initialized = 0; - - /* Initialize the random number generator once and only once */ - if (rand_initialized == 0) { - simplerng_srand( (unsigned int) time(NULL) ); - rand_initialized = 1; - } - - gParse.firstRow = firstRow; - gParse.nRows = nRows; - - /* Reset Column Nodes' pointers to point to right data and UNDEF arrays */ - - rowOffset = firstRow - gParse.firstDataRow; - for( i=0; i 0 || OPER(i) == CONST_OP ) continue; - - column = -OPER(i); - offset = gParse.varData[column].nelem * rowOffset; - - gParse.Nodes[i].value.undef = gParse.varData[column].undef + offset; - - switch( gParse.Nodes[i].type ) { - case BITSTR: - gParse.Nodes[i].value.data.strptr = - (char**)gParse.varData[column].data + rowOffset; - gParse.Nodes[i].value.undef = NULL; - break; - case STRING: - gParse.Nodes[i].value.data.strptr = - (char**)gParse.varData[column].data + rowOffset; - gParse.Nodes[i].value.undef = gParse.varData[column].undef + rowOffset; - break; - case BOOLEAN: - gParse.Nodes[i].value.data.logptr = - (char*)gParse.varData[column].data + offset; - break; - case LONG: - gParse.Nodes[i].value.data.lngptr = - (long*)gParse.varData[column].data + offset; - break; - case DOUBLE: - gParse.Nodes[i].value.data.dblptr = - (double*)gParse.varData[column].data + offset; - break; - } - } - - Evaluate_Node( gParse.resultNode ); -} - -static void Evaluate_Node( int thisNode ) - /**********************************************************************/ - /* Recursively evaluate thisNode's subNodes, then call one of the */ - /* Do_ functions pointed to by thisNode's DoOp element. */ - /**********************************************************************/ -{ - Node *this; - int i; - - if( gParse.status ) return; - - this = gParse.Nodes + thisNode; - if( this->operation>0 ) { /* <=0 indicate constants and columns */ - i = this->nSubNodes; - while( i-- ) { - Evaluate_Node( this->SubNodes[i] ); - if( gParse.status ) return; - } - this->DoOp( this ); - } -} - -static void Allocate_Ptrs( Node *this ) -{ - long elem, row, size; - - if( this->type==BITSTR || this->type==STRING ) { - - this->value.data.strptr = (char**)malloc( gParse.nRows - * sizeof(char*) ); - if( this->value.data.strptr ) { - this->value.data.strptr[0] = (char*)malloc( gParse.nRows - * (this->value.nelem+2) - * sizeof(char) ); - if( this->value.data.strptr[0] ) { - row = 0; - while( (++row)value.data.strptr[row] = - this->value.data.strptr[row-1] + this->value.nelem+1; - } - if( this->type==STRING ) { - this->value.undef = this->value.data.strptr[row-1] - + this->value.nelem+1; - } else { - this->value.undef = NULL; /* BITSTRs don't use undef array */ - } - } else { - gParse.status = MEMORY_ALLOCATION; - free( this->value.data.strptr ); - } - } else { - gParse.status = MEMORY_ALLOCATION; - } - - } else { - - elem = this->value.nelem * gParse.nRows; - switch( this->type ) { - case DOUBLE: size = sizeof( double ); break; - case LONG: size = sizeof( long ); break; - case BOOLEAN: size = sizeof( char ); break; - default: size = 1; break; - } - - this->value.data.ptr = calloc(size+1, elem); - - if( this->value.data.ptr==NULL ) { - gParse.status = MEMORY_ALLOCATION; - } else { - this->value.undef = (char *)this->value.data.ptr + elem*size; - } - } -} - -static void Do_Unary( Node *this ) -{ - Node *that; - long elem; - - that = gParse.Nodes + this->SubNodes[0]; - - if( that->operation==CONST_OP ) { /* Operating on a constant! */ - switch( this->operation ) { - case DOUBLE: - case FLTCAST: - if( that->type==LONG ) - this->value.data.dbl = (double)that->value.data.lng; - else if( that->type==BOOLEAN ) - this->value.data.dbl = ( that->value.data.log ? 1.0 : 0.0 ); - break; - case LONG: - case INTCAST: - if( that->type==DOUBLE ) - this->value.data.lng = (long)that->value.data.dbl; - else if( that->type==BOOLEAN ) - this->value.data.lng = ( that->value.data.log ? 1L : 0L ); - break; - case BOOLEAN: - if( that->type==DOUBLE ) - this->value.data.log = ( that->value.data.dbl != 0.0 ); - else if( that->type==LONG ) - this->value.data.log = ( that->value.data.lng != 0L ); - break; - case UMINUS: - if( that->type==DOUBLE ) - this->value.data.dbl = - that->value.data.dbl; - else if( that->type==LONG ) - this->value.data.lng = - that->value.data.lng; - break; - case NOT: - if( that->type==BOOLEAN ) - this->value.data.log = ( ! that->value.data.log ); - else if( that->type==BITSTR ) - bitnot( this->value.data.str, that->value.data.str ); - break; - } - this->operation = CONST_OP; - - } else { - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - - if( this->type!=BITSTR ) { - elem = gParse.nRows; - if( this->type!=STRING ) - elem *= this->value.nelem; - while( elem-- ) - this->value.undef[elem] = that->value.undef[elem]; - } - - elem = gParse.nRows * this->value.nelem; - - switch( this->operation ) { - - case BOOLEAN: - if( that->type==DOUBLE ) - while( elem-- ) - this->value.data.logptr[elem] = - ( that->value.data.dblptr[elem] != 0.0 ); - else if( that->type==LONG ) - while( elem-- ) - this->value.data.logptr[elem] = - ( that->value.data.lngptr[elem] != 0L ); - break; - - case DOUBLE: - case FLTCAST: - if( that->type==LONG ) - while( elem-- ) - this->value.data.dblptr[elem] = - (double)that->value.data.lngptr[elem]; - else if( that->type==BOOLEAN ) - while( elem-- ) - this->value.data.dblptr[elem] = - ( that->value.data.logptr[elem] ? 1.0 : 0.0 ); - break; - - case LONG: - case INTCAST: - if( that->type==DOUBLE ) - while( elem-- ) - this->value.data.lngptr[elem] = - (long)that->value.data.dblptr[elem]; - else if( that->type==BOOLEAN ) - while( elem-- ) - this->value.data.lngptr[elem] = - ( that->value.data.logptr[elem] ? 1L : 0L ); - break; - - case UMINUS: - if( that->type==DOUBLE ) { - while( elem-- ) - this->value.data.dblptr[elem] = - - that->value.data.dblptr[elem]; - } else if( that->type==LONG ) { - while( elem-- ) - this->value.data.lngptr[elem] = - - that->value.data.lngptr[elem]; - } - break; - - case NOT: - if( that->type==BOOLEAN ) { - while( elem-- ) - this->value.data.logptr[elem] = - ( ! that->value.data.logptr[elem] ); - } else if( that->type==BITSTR ) { - elem = gParse.nRows; - while( elem-- ) - bitnot( this->value.data.strptr[elem], - that->value.data.strptr[elem] ); - } - break; - } - } - } - - if( that->operation>0 ) { - free( that->value.data.ptr ); - } -} - -static void Do_Offset( Node *this ) -{ - Node *col; - long fRow, nRowOverlap, nRowReload, rowOffset; - long nelem, elem, offset, nRealElem; - int status; - - col = gParse.Nodes + this->SubNodes[0]; - rowOffset = gParse.Nodes[ this->SubNodes[1] ].value.data.lng; - - Allocate_Ptrs( this ); - - fRow = gParse.firstRow + rowOffset; - if( this->type==STRING || this->type==BITSTR ) - nRealElem = 1; - else - nRealElem = this->value.nelem; - - nelem = nRealElem; - - if( fRow < gParse.firstDataRow ) { - - /* Must fill in data at start of array */ - - nRowReload = gParse.firstDataRow - fRow; - if( nRowReload > gParse.nRows ) nRowReload = gParse.nRows; - nRowOverlap = gParse.nRows - nRowReload; - - offset = 0; - - /* NULLify any values falling out of bounds */ - - while( fRow<1 && nRowReload>0 ) { - if( this->type == BITSTR ) { - nelem = this->value.nelem; - this->value.data.strptr[offset][ nelem ] = '\0'; - while( nelem-- ) this->value.data.strptr[offset][nelem] = '0'; - offset++; - } else { - while( nelem-- ) - this->value.undef[offset++] = 1; - } - nelem = nRealElem; - fRow++; - nRowReload--; - } - - } else if( fRow + gParse.nRows > gParse.firstDataRow + gParse.nDataRows ) { - - /* Must fill in data at end of array */ - - nRowReload = (fRow+gParse.nRows) - (gParse.firstDataRow+gParse.nDataRows); - if( nRowReload>gParse.nRows ) { - nRowReload = gParse.nRows; - } else { - fRow = gParse.firstDataRow + gParse.nDataRows; - } - nRowOverlap = gParse.nRows - nRowReload; - - offset = nRowOverlap * nelem; - - /* NULLify any values falling out of bounds */ - - elem = gParse.nRows * nelem; - while( fRow+nRowReload>gParse.totalRows && nRowReload>0 ) { - if( this->type == BITSTR ) { - nelem = this->value.nelem; - elem--; - this->value.data.strptr[elem][ nelem ] = '\0'; - while( nelem-- ) this->value.data.strptr[elem][nelem] = '0'; - } else { - while( nelem-- ) - this->value.undef[--elem] = 1; - } - nelem = nRealElem; - nRowReload--; - } - - } else { - - nRowReload = 0; - nRowOverlap = gParse.nRows; - offset = 0; - - } - - if( nRowReload>0 ) { - switch( this->type ) { - case BITSTR: - case STRING: - status = (*gParse.loadData)( -col->operation, fRow, nRowReload, - this->value.data.strptr+offset, - this->value.undef+offset ); - break; - case BOOLEAN: - status = (*gParse.loadData)( -col->operation, fRow, nRowReload, - this->value.data.logptr+offset, - this->value.undef+offset ); - break; - case LONG: - status = (*gParse.loadData)( -col->operation, fRow, nRowReload, - this->value.data.lngptr+offset, - this->value.undef+offset ); - break; - case DOUBLE: - status = (*gParse.loadData)( -col->operation, fRow, nRowReload, - this->value.data.dblptr+offset, - this->value.undef+offset ); - break; - } - } - - /* Now copy over the overlapping region, if any */ - - if( nRowOverlap <= 0 ) return; - - if( rowOffset>0 ) - elem = nRowOverlap * nelem; - else - elem = gParse.nRows * nelem; - - offset = nelem * rowOffset; - while( nRowOverlap-- && !gParse.status ) { - while( nelem-- && !gParse.status ) { - elem--; - if( this->type != BITSTR ) - this->value.undef[elem] = col->value.undef[elem+offset]; - switch( this->type ) { - case BITSTR: - strcpy( this->value.data.strptr[elem ], - col->value.data.strptr[elem+offset] ); - break; - case STRING: - strcpy( this->value.data.strptr[elem ], - col->value.data.strptr[elem+offset] ); - break; - case BOOLEAN: - this->value.data.logptr[elem] = col->value.data.logptr[elem+offset]; - break; - case LONG: - this->value.data.lngptr[elem] = col->value.data.lngptr[elem+offset]; - break; - case DOUBLE: - this->value.data.dblptr[elem] = col->value.data.dblptr[elem+offset]; - break; - } - } - nelem = nRealElem; - } -} - -static void Do_BinOp_bit( Node *this ) -{ - Node *that1, *that2; - char *sptr1=NULL, *sptr2=NULL; - int const1, const2; - long rows; - - that1 = gParse.Nodes + this->SubNodes[0]; - that2 = gParse.Nodes + this->SubNodes[1]; - - const1 = ( that1->operation==CONST_OP ); - const2 = ( that2->operation==CONST_OP ); - sptr1 = ( const1 ? that1->value.data.str : NULL ); - sptr2 = ( const2 ? that2->value.data.str : NULL ); - - if( const1 && const2 ) { - switch( this->operation ) { - case NE: - this->value.data.log = !bitcmp( sptr1, sptr2 ); - break; - case EQ: - this->value.data.log = bitcmp( sptr1, sptr2 ); - break; - case GT: - case LT: - case LTE: - case GTE: - this->value.data.log = bitlgte( sptr1, this->operation, sptr2 ); - break; - case '|': - bitor( this->value.data.str, sptr1, sptr2 ); - break; - case '&': - bitand( this->value.data.str, sptr1, sptr2 ); - break; - case '+': - strcpy( this->value.data.str, sptr1 ); - strcat( this->value.data.str, sptr2 ); - break; - case ACCUM: - this->value.data.lng = 0; - while( *sptr1 ) { - if ( *sptr1 == '1' ) this->value.data.lng ++; - sptr1 ++; - } - break; - - } - this->operation = CONST_OP; - - } else { - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - rows = gParse.nRows; - switch( this->operation ) { - - /* BITSTR comparisons */ - - case NE: - case EQ: - case GT: - case LT: - case LTE: - case GTE: - while( rows-- ) { - if( !const1 ) - sptr1 = that1->value.data.strptr[rows]; - if( !const2 ) - sptr2 = that2->value.data.strptr[rows]; - switch( this->operation ) { - case NE: this->value.data.logptr[rows] = - !bitcmp( sptr1, sptr2 ); - break; - case EQ: this->value.data.logptr[rows] = - bitcmp( sptr1, sptr2 ); - break; - case GT: - case LT: - case LTE: - case GTE: this->value.data.logptr[rows] = - bitlgte( sptr1, this->operation, sptr2 ); - break; - } - this->value.undef[rows] = 0; - } - break; - - /* BITSTR AND/ORs ... no UNDEFS in or out */ - - case '|': - case '&': - case '+': - while( rows-- ) { - if( !const1 ) - sptr1 = that1->value.data.strptr[rows]; - if( !const2 ) - sptr2 = that2->value.data.strptr[rows]; - if( this->operation=='|' ) - bitor( this->value.data.strptr[rows], sptr1, sptr2 ); - else if( this->operation=='&' ) - bitand( this->value.data.strptr[rows], sptr1, sptr2 ); - else { - strcpy( this->value.data.strptr[rows], sptr1 ); - strcat( this->value.data.strptr[rows], sptr2 ); - } - } - break; - - /* Accumulate 1 bits */ - case ACCUM: - { - long i, previous, curr; - - previous = that2->value.data.lng; - - /* Cumulative sum of this chunk */ - for (i=0; ivalue.data.strptr[i]; - for (curr = 0; *sptr1; sptr1 ++) { - if ( *sptr1 == '1' ) curr ++; - } - previous += curr; - this->value.data.lngptr[i] = previous; - this->value.undef[i] = 0; - } - - /* Store final cumulant for next pass */ - that2->value.data.lng = previous; - } - } - } - } - - if( that1->operation>0 ) { - free( that1->value.data.strptr[0] ); - free( that1->value.data.strptr ); - } - if( that2->operation>0 ) { - free( that2->value.data.strptr[0] ); - free( that2->value.data.strptr ); - } -} - -static void Do_BinOp_str( Node *this ) -{ - Node *that1, *that2; - char *sptr1, *sptr2, null1=0, null2=0; - int const1, const2, val; - long rows; - - that1 = gParse.Nodes + this->SubNodes[0]; - that2 = gParse.Nodes + this->SubNodes[1]; - - const1 = ( that1->operation==CONST_OP ); - const2 = ( that2->operation==CONST_OP ); - sptr1 = ( const1 ? that1->value.data.str : NULL ); - sptr2 = ( const2 ? that2->value.data.str : NULL ); - - if( const1 && const2 ) { /* Result is a constant */ - switch( this->operation ) { - - /* Compare Strings */ - - case NE: - case EQ: - val = ( FSTRCMP( sptr1, sptr2 ) == 0 ); - this->value.data.log = ( this->operation==EQ ? val : !val ); - break; - case GT: - this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) > 0 ); - break; - case LT: - this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) < 0 ); - break; - case GTE: - this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) >= 0 ); - break; - case LTE: - this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) <= 0 ); - break; - - /* Concat Strings */ - - case '+': - strcpy( this->value.data.str, sptr1 ); - strcat( this->value.data.str, sptr2 ); - break; - } - this->operation = CONST_OP; - - } else { /* Not a constant */ - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - - rows = gParse.nRows; - switch( this->operation ) { - - /* Compare Strings */ - - case NE: - case EQ: - while( rows-- ) { - if( !const1 ) null1 = that1->value.undef[rows]; - if( !const2 ) null2 = that2->value.undef[rows]; - this->value.undef[rows] = (null1 || null2); - if( ! this->value.undef[rows] ) { - if( !const1 ) sptr1 = that1->value.data.strptr[rows]; - if( !const2 ) sptr2 = that2->value.data.strptr[rows]; - val = ( FSTRCMP( sptr1, sptr2 ) == 0 ); - this->value.data.logptr[rows] = - ( this->operation==EQ ? val : !val ); - } - } - break; - - case GT: - case LT: - while( rows-- ) { - if( !const1 ) null1 = that1->value.undef[rows]; - if( !const2 ) null2 = that2->value.undef[rows]; - this->value.undef[rows] = (null1 || null2); - if( ! this->value.undef[rows] ) { - if( !const1 ) sptr1 = that1->value.data.strptr[rows]; - if( !const2 ) sptr2 = that2->value.data.strptr[rows]; - val = ( FSTRCMP( sptr1, sptr2 ) ); - this->value.data.logptr[rows] = - ( this->operation==GT ? val>0 : val<0 ); - } - } - break; - - case GTE: - case LTE: - while( rows-- ) { - if( !const1 ) null1 = that1->value.undef[rows]; - if( !const2 ) null2 = that2->value.undef[rows]; - this->value.undef[rows] = (null1 || null2); - if( ! this->value.undef[rows] ) { - if( !const1 ) sptr1 = that1->value.data.strptr[rows]; - if( !const2 ) sptr2 = that2->value.data.strptr[rows]; - val = ( FSTRCMP( sptr1, sptr2 ) ); - this->value.data.logptr[rows] = - ( this->operation==GTE ? val>=0 : val<=0 ); - } - } - break; - - /* Concat Strings */ - - case '+': - while( rows-- ) { - if( !const1 ) null1 = that1->value.undef[rows]; - if( !const2 ) null2 = that2->value.undef[rows]; - this->value.undef[rows] = (null1 || null2); - if( ! this->value.undef[rows] ) { - if( !const1 ) sptr1 = that1->value.data.strptr[rows]; - if( !const2 ) sptr2 = that2->value.data.strptr[rows]; - strcpy( this->value.data.strptr[rows], sptr1 ); - strcat( this->value.data.strptr[rows], sptr2 ); - } - } - break; - } - } - } - - if( that1->operation>0 ) { - free( that1->value.data.strptr[0] ); - free( that1->value.data.strptr ); - } - if( that2->operation>0 ) { - free( that2->value.data.strptr[0] ); - free( that2->value.data.strptr ); - } -} - -static void Do_BinOp_log( Node *this ) -{ - Node *that1, *that2; - int vector1, vector2; - char val1=0, val2=0, null1=0, null2=0; - long rows, nelem, elem; - - that1 = gParse.Nodes + this->SubNodes[0]; - that2 = gParse.Nodes + this->SubNodes[1]; - - vector1 = ( that1->operation!=CONST_OP ); - if( vector1 ) - vector1 = that1->value.nelem; - else { - val1 = that1->value.data.log; - } - - vector2 = ( that2->operation!=CONST_OP ); - if( vector2 ) - vector2 = that2->value.nelem; - else { - val2 = that2->value.data.log; - } - - if( !vector1 && !vector2 ) { /* Result is a constant */ - switch( this->operation ) { - case OR: - this->value.data.log = (val1 || val2); - break; - case AND: - this->value.data.log = (val1 && val2); - break; - case EQ: - this->value.data.log = ( (val1 && val2) || (!val1 && !val2) ); - break; - case NE: - this->value.data.log = ( (val1 && !val2) || (!val1 && val2) ); - break; - case ACCUM: - this->value.data.lng = val1; - break; - } - this->operation=CONST_OP; - } else if (this->operation == ACCUM) { - long i, previous, curr; - rows = gParse.nRows; - nelem = this->value.nelem; - elem = this->value.nelem * rows; - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - previous = that2->value.data.lng; - - /* Cumulative sum of this chunk */ - for (i=0; ivalue.undef[i]) { - curr = that1->value.data.logptr[i]; - previous += curr; - } - this->value.data.lngptr[i] = previous; - this->value.undef[i] = 0; - } - - /* Store final cumulant for next pass */ - that2->value.data.lng = previous; - } - - } else { - rows = gParse.nRows; - nelem = this->value.nelem; - elem = this->value.nelem * rows; - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - - if (this->operation == ACCUM) { - long i, previous, curr; - - previous = that2->value.data.lng; - - /* Cumulative sum of this chunk */ - for (i=0; ivalue.undef[i]) { - curr = that1->value.data.logptr[i]; - previous += curr; - } - this->value.data.lngptr[i] = previous; - this->value.undef[i] = 0; - } - - /* Store final cumulant for next pass */ - that2->value.data.lng = previous; - } - - while( rows-- ) { - while( nelem-- ) { - elem--; - - if( vector1>1 ) { - val1 = that1->value.data.logptr[elem]; - null1 = that1->value.undef[elem]; - } else if( vector1 ) { - val1 = that1->value.data.logptr[rows]; - null1 = that1->value.undef[rows]; - } - - if( vector2>1 ) { - val2 = that2->value.data.logptr[elem]; - null2 = that2->value.undef[elem]; - } else if( vector2 ) { - val2 = that2->value.data.logptr[rows]; - null2 = that2->value.undef[rows]; - } - - this->value.undef[elem] = (null1 || null2); - switch( this->operation ) { - - case OR: - /* This is more complicated than others to suppress UNDEFs */ - /* in those cases where the other argument is DEF && TRUE */ - - if( !null1 && !null2 ) { - this->value.data.logptr[elem] = (val1 || val2); - } else if( (null1 && !null2 && val2) - || ( !null1 && null2 && val1 ) ) { - this->value.data.logptr[elem] = 1; - this->value.undef[elem] = 0; - } - break; - - case AND: - /* This is more complicated than others to suppress UNDEFs */ - /* in those cases where the other argument is DEF && FALSE */ - - if( !null1 && !null2 ) { - this->value.data.logptr[elem] = (val1 && val2); - } else if( (null1 && !null2 && !val2) - || ( !null1 && null2 && !val1 ) ) { - this->value.data.logptr[elem] = 0; - this->value.undef[elem] = 0; - } - break; - - case EQ: - this->value.data.logptr[elem] = - ( (val1 && val2) || (!val1 && !val2) ); - break; - - case NE: - this->value.data.logptr[elem] = - ( (val1 && !val2) || (!val1 && val2) ); - break; - } - } - nelem = this->value.nelem; - } - } - } - - if( that1->operation>0 ) { - free( that1->value.data.ptr ); - } - if( that2->operation>0 ) { - free( that2->value.data.ptr ); - } -} - -static void Do_BinOp_lng( Node *this ) -{ - Node *that1, *that2; - int vector1, vector2; - long val1=0, val2=0; - char null1=0, null2=0; - long rows, nelem, elem; - - that1 = gParse.Nodes + this->SubNodes[0]; - that2 = gParse.Nodes + this->SubNodes[1]; - - vector1 = ( that1->operation!=CONST_OP ); - if( vector1 ) - vector1 = that1->value.nelem; - else { - val1 = that1->value.data.lng; - } - - vector2 = ( that2->operation!=CONST_OP ); - if( vector2 ) - vector2 = that2->value.nelem; - else { - val2 = that2->value.data.lng; - } - - if( !vector1 && !vector2 ) { /* Result is a constant */ - - switch( this->operation ) { - case '~': /* Treat as == for LONGS */ - case EQ: this->value.data.log = (val1 == val2); break; - case NE: this->value.data.log = (val1 != val2); break; - case GT: this->value.data.log = (val1 > val2); break; - case LT: this->value.data.log = (val1 < val2); break; - case LTE: this->value.data.log = (val1 <= val2); break; - case GTE: this->value.data.log = (val1 >= val2); break; - - case '+': this->value.data.lng = (val1 + val2); break; - case '-': this->value.data.lng = (val1 - val2); break; - case '*': this->value.data.lng = (val1 * val2); break; - - case '%': - if( val2 ) this->value.data.lng = (val1 % val2); - else fferror("Divide by Zero"); - break; - case '/': - if( val2 ) this->value.data.lng = (val1 / val2); - else fferror("Divide by Zero"); - break; - case POWER: - this->value.data.lng = (long)pow((double)val1,(double)val2); - break; - case ACCUM: - this->value.data.lng = val1; - break; - case DIFF: - this->value.data.lng = 0; - break; - } - this->operation=CONST_OP; - - } else if ((this->operation == ACCUM) || (this->operation == DIFF)) { - long i, previous, curr; - long undef; - rows = gParse.nRows; - nelem = this->value.nelem; - elem = this->value.nelem * rows; - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - previous = that2->value.data.lng; - undef = (long) that2->value.undef; - - if (this->operation == ACCUM) { - /* Cumulative sum of this chunk */ - for (i=0; ivalue.undef[i]) { - curr = that1->value.data.lngptr[i]; - previous += curr; - } - this->value.data.lngptr[i] = previous; - this->value.undef[i] = 0; - } - } else { - /* Sequential difference for this chunk */ - for (i=0; ivalue.data.lngptr[i]; - if (that1->value.undef[i] || undef) { - /* Either this, or previous, value was undefined */ - this->value.data.lngptr[i] = 0; - this->value.undef[i] = 1; - } else { - /* Both defined, we are okay! */ - this->value.data.lngptr[i] = curr - previous; - this->value.undef[i] = 0; - } - - previous = curr; - undef = that1->value.undef[i]; - } - } - - /* Store final cumulant for next pass */ - that2->value.data.lng = previous; - that2->value.undef = (char *) undef; /* XXX evil, but no harm here */ - } - - } else { - - rows = gParse.nRows; - nelem = this->value.nelem; - elem = this->value.nelem * rows; - - Allocate_Ptrs( this ); - - while( rows-- && !gParse.status ) { - while( nelem-- && !gParse.status ) { - elem--; - - if( vector1>1 ) { - val1 = that1->value.data.lngptr[elem]; - null1 = that1->value.undef[elem]; - } else if( vector1 ) { - val1 = that1->value.data.lngptr[rows]; - null1 = that1->value.undef[rows]; - } - - if( vector2>1 ) { - val2 = that2->value.data.lngptr[elem]; - null2 = that2->value.undef[elem]; - } else if( vector2 ) { - val2 = that2->value.data.lngptr[rows]; - null2 = that2->value.undef[rows]; - } - - this->value.undef[elem] = (null1 || null2); - switch( this->operation ) { - case '~': /* Treat as == for LONGS */ - case EQ: this->value.data.logptr[elem] = (val1 == val2); break; - case NE: this->value.data.logptr[elem] = (val1 != val2); break; - case GT: this->value.data.logptr[elem] = (val1 > val2); break; - case LT: this->value.data.logptr[elem] = (val1 < val2); break; - case LTE: this->value.data.logptr[elem] = (val1 <= val2); break; - case GTE: this->value.data.logptr[elem] = (val1 >= val2); break; - - case '+': this->value.data.lngptr[elem] = (val1 + val2); break; - case '-': this->value.data.lngptr[elem] = (val1 - val2); break; - case '*': this->value.data.lngptr[elem] = (val1 * val2); break; - - case '%': - if( val2 ) this->value.data.lngptr[elem] = (val1 % val2); - else { - this->value.data.lngptr[elem] = 0; - this->value.undef[elem] = 1; - } - break; - case '/': - if( val2 ) this->value.data.lngptr[elem] = (val1 / val2); - else { - this->value.data.lngptr[elem] = 0; - this->value.undef[elem] = 1; - } - break; - case POWER: - this->value.data.lngptr[elem] = (long)pow((double)val1,(double)val2); - break; - } - } - nelem = this->value.nelem; - } - } - - if( that1->operation>0 ) { - free( that1->value.data.ptr ); - } - if( that2->operation>0 ) { - free( that2->value.data.ptr ); - } -} - -static void Do_BinOp_dbl( Node *this ) -{ - Node *that1, *that2; - int vector1, vector2; - double val1=0.0, val2=0.0; - char null1=0, null2=0; - long rows, nelem, elem; - - that1 = gParse.Nodes + this->SubNodes[0]; - that2 = gParse.Nodes + this->SubNodes[1]; - - vector1 = ( that1->operation!=CONST_OP ); - if( vector1 ) - vector1 = that1->value.nelem; - else { - val1 = that1->value.data.dbl; - } - - vector2 = ( that2->operation!=CONST_OP ); - if( vector2 ) - vector2 = that2->value.nelem; - else { - val2 = that2->value.data.dbl; - } - - if( !vector1 && !vector2 ) { /* Result is a constant */ - - switch( this->operation ) { - case '~': this->value.data.log = ( fabs(val1-val2) < APPROX ); break; - case EQ: this->value.data.log = (val1 == val2); break; - case NE: this->value.data.log = (val1 != val2); break; - case GT: this->value.data.log = (val1 > val2); break; - case LT: this->value.data.log = (val1 < val2); break; - case LTE: this->value.data.log = (val1 <= val2); break; - case GTE: this->value.data.log = (val1 >= val2); break; - - case '+': this->value.data.dbl = (val1 + val2); break; - case '-': this->value.data.dbl = (val1 - val2); break; - case '*': this->value.data.dbl = (val1 * val2); break; - - case '%': - if( val2 ) this->value.data.dbl = val1 - val2*((int)(val1/val2)); - else fferror("Divide by Zero"); - break; - case '/': - if( val2 ) this->value.data.dbl = (val1 / val2); - else fferror("Divide by Zero"); - break; - case POWER: - this->value.data.dbl = (double)pow(val1,val2); - break; - case ACCUM: - this->value.data.dbl = val1; - break; - case DIFF: - this->value.data.dbl = 0; - break; - } - this->operation=CONST_OP; - - } else if ((this->operation == ACCUM) || (this->operation == DIFF)) { - long i; - long undef; - double previous, curr; - rows = gParse.nRows; - nelem = this->value.nelem; - elem = this->value.nelem * rows; - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - previous = that2->value.data.dbl; - undef = (long) that2->value.undef; - - if (this->operation == ACCUM) { - /* Cumulative sum of this chunk */ - for (i=0; ivalue.undef[i]) { - curr = that1->value.data.dblptr[i]; - previous += curr; - } - this->value.data.dblptr[i] = previous; - this->value.undef[i] = 0; - } - } else { - /* Sequential difference for this chunk */ - for (i=0; ivalue.data.dblptr[i]; - if (that1->value.undef[i] || undef) { - /* Either this, or previous, value was undefined */ - this->value.data.dblptr[i] = 0; - this->value.undef[i] = 1; - } else { - /* Both defined, we are okay! */ - this->value.data.dblptr[i] = curr - previous; - this->value.undef[i] = 0; - } - - previous = curr; - undef = that1->value.undef[i]; - } - } - - /* Store final cumulant for next pass */ - that2->value.data.dbl = previous; - that2->value.undef = (char *) undef; /* XXX evil, but no harm here */ - } - - } else { - - rows = gParse.nRows; - nelem = this->value.nelem; - elem = this->value.nelem * rows; - - Allocate_Ptrs( this ); - - while( rows-- && !gParse.status ) { - while( nelem-- && !gParse.status ) { - elem--; - - if( vector1>1 ) { - val1 = that1->value.data.dblptr[elem]; - null1 = that1->value.undef[elem]; - } else if( vector1 ) { - val1 = that1->value.data.dblptr[rows]; - null1 = that1->value.undef[rows]; - } - - if( vector2>1 ) { - val2 = that2->value.data.dblptr[elem]; - null2 = that2->value.undef[elem]; - } else if( vector2 ) { - val2 = that2->value.data.dblptr[rows]; - null2 = that2->value.undef[rows]; - } - - this->value.undef[elem] = (null1 || null2); - switch( this->operation ) { - case '~': this->value.data.logptr[elem] = - ( fabs(val1-val2) < APPROX ); break; - case EQ: this->value.data.logptr[elem] = (val1 == val2); break; - case NE: this->value.data.logptr[elem] = (val1 != val2); break; - case GT: this->value.data.logptr[elem] = (val1 > val2); break; - case LT: this->value.data.logptr[elem] = (val1 < val2); break; - case LTE: this->value.data.logptr[elem] = (val1 <= val2); break; - case GTE: this->value.data.logptr[elem] = (val1 >= val2); break; - - case '+': this->value.data.dblptr[elem] = (val1 + val2); break; - case '-': this->value.data.dblptr[elem] = (val1 - val2); break; - case '*': this->value.data.dblptr[elem] = (val1 * val2); break; - - case '%': - if( val2 ) this->value.data.dblptr[elem] = - val1 - val2*((int)(val1/val2)); - else { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } - break; - case '/': - if( val2 ) this->value.data.dblptr[elem] = (val1 / val2); - else { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } - break; - case POWER: - this->value.data.dblptr[elem] = (double)pow(val1,val2); - break; - } - } - nelem = this->value.nelem; - } - } - - if( that1->operation>0 ) { - free( that1->value.data.ptr ); - } - if( that2->operation>0 ) { - free( that2->value.data.ptr ); - } -} - -/* - * This Quickselect routine is based on the algorithm described in - * "Numerical recipes in C", Second Edition, - * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5 - * This code by Nicolas Devillard - 1998. Public domain. - * http://ndevilla.free.fr/median/median/src/quickselect.c - */ - -#define ELEM_SWAP(a,b) { register long t=(a);(a)=(b);(b)=t; } - -/* - * qselect_median_lng - select the median value of a long array - * - * This routine selects the median value of the long integer array - * arr[]. If there are an even number of elements, the "lower median" - * is selected. - * - * The array arr[] is scrambled, so users must operate on a scratch - * array if they wish the values to be preserved. - * - * long arr[] - array of values - * int n - number of elements in arr - * - * RETURNS: the lower median value of arr[] - * - */ -long qselect_median_lng(long arr[], int n) -{ - int low, high ; - int median; - int middle, ll, hh; - - low = 0 ; high = n-1 ; median = (low + high) / 2; - for (;;) { - - if (high <= low) { /* One element only */ - return arr[median]; - } - - if (high == low + 1) { /* Two elements only */ - if (arr[low] > arr[high]) - ELEM_SWAP(arr[low], arr[high]) ; - return arr[median]; - } - - /* Find median of low, middle and high items; swap into position low */ - middle = (low + high) / 2; - if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; - if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; - if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; - - /* Swap low item (now in position middle) into position (low+1) */ - ELEM_SWAP(arr[middle], arr[low+1]) ; - - /* Nibble from each end towards middle, swapping items when stuck */ - ll = low + 1; - hh = high; - for (;;) { - do ll++; while (arr[low] > arr[ll]) ; - do hh--; while (arr[hh] > arr[low]) ; - - if (hh < ll) - break; - - ELEM_SWAP(arr[ll], arr[hh]) ; - } - - /* Swap middle item (in position low) back into correct position */ - ELEM_SWAP(arr[low], arr[hh]) ; - - /* Re-set active partition */ - if (hh <= median) - low = ll; - if (hh >= median) - high = hh - 1; - } -} - -#undef ELEM_SWAP - -#define ELEM_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; } - -/* - * qselect_median_dbl - select the median value of a double array - * - * This routine selects the median value of the double array - * arr[]. If there are an even number of elements, the "lower median" - * is selected. - * - * The array arr[] is scrambled, so users must operate on a scratch - * array if they wish the values to be preserved. - * - * double arr[] - array of values - * int n - number of elements in arr - * - * RETURNS: the lower median value of arr[] - * - */ -double qselect_median_dbl(double arr[], int n) -{ - int low, high ; - int median; - int middle, ll, hh; - - low = 0 ; high = n-1 ; median = (low + high) / 2; - for (;;) { - if (high <= low) { /* One element only */ - return arr[median] ; - } - - if (high == low + 1) { /* Two elements only */ - if (arr[low] > arr[high]) - ELEM_SWAP(arr[low], arr[high]) ; - return arr[median] ; - } - - /* Find median of low, middle and high items; swap into position low */ - middle = (low + high) / 2; - if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; - if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; - if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; - - /* Swap low item (now in position middle) into position (low+1) */ - ELEM_SWAP(arr[middle], arr[low+1]) ; - - /* Nibble from each end towards middle, swapping items when stuck */ - ll = low + 1; - hh = high; - for (;;) { - do ll++; while (arr[low] > arr[ll]) ; - do hh--; while (arr[hh] > arr[low]) ; - - if (hh < ll) - break; - - ELEM_SWAP(arr[ll], arr[hh]) ; - } - - /* Swap middle item (in position low) back into correct position */ - ELEM_SWAP(arr[low], arr[hh]) ; - - /* Re-set active partition */ - if (hh <= median) - low = ll; - if (hh >= median) - high = hh - 1; - } -} - -#undef ELEM_SWAP - -/* - * angsep_calc - compute angular separation between celestial coordinates - * - * This routine computes the angular separation between to coordinates - * on the celestial sphere (i.e. RA and Dec). Note that all units are - * in DEGREES, unlike the other trig functions in the calculator. - * - * double ra1, dec1 - RA and Dec of the first position in degrees - * double ra2, dec2 - RA and Dec of the second position in degrees - * - * RETURNS: (double) angular separation in degrees - * - */ -double angsep_calc(double ra1, double dec1, double ra2, double dec2) -{ -/* double cd; */ - static double deg = 0; - double a, sdec, sra; - - if (deg == 0) deg = ((double)4)*atan((double)1)/((double)180); - /* deg = 1.0; **** UNCOMMENT IF YOU WANT RADIANS */ - - /* The algorithm is the law of Haversines. This algorithm is - stable even when the points are close together. The normal - Law of Cosines fails for angles around 0.1 arcsec. */ - - sra = sin( (ra2 - ra1)*deg / 2 ); - sdec = sin( (dec2 - dec1)*deg / 2); - a = sdec*sdec + cos(dec1*deg)*cos(dec2*deg)*sra*sra; - - /* Sanity checking to avoid a range error in the sqrt()'s below */ - if (a < 0) { a = 0; } - if (a > 1) { a = 1; } - - return 2.0*atan2(sqrt(a), sqrt(1.0 - a)) / deg; -} - -static void Do_Func( Node *this ) -{ - Node *theParams[MAXSUBS]; - int vector[MAXSUBS], allConst; - lval pVals[MAXSUBS]; - char pNull[MAXSUBS]; - long ival; - double dval; - int i, valInit; - long row, elem, nelem; - - i = this->nSubNodes; - allConst = 1; - while( i-- ) { - theParams[i] = gParse.Nodes + this->SubNodes[i]; - vector[i] = ( theParams[i]->operation!=CONST_OP ); - if( vector[i] ) { - allConst = 0; - vector[i] = theParams[i]->value.nelem; - } else { - if( theParams[i]->type==DOUBLE ) { - pVals[i].data.dbl = theParams[i]->value.data.dbl; - } else if( theParams[i]->type==LONG ) { - pVals[i].data.lng = theParams[i]->value.data.lng; - } else if( theParams[i]->type==BOOLEAN ) { - pVals[i].data.log = theParams[i]->value.data.log; - } else - strcpy(pVals[i].data.str, theParams[i]->value.data.str); - pNull[i] = 0; - } - } - - if( this->nSubNodes==0 ) allConst = 0; /* These do produce scalars */ - /* Random numbers are *never* constant !! */ - if( this->operation == poirnd_fct ) allConst = 0; - if( this->operation == gasrnd_fct ) allConst = 0; - if( this->operation == rnd_fct ) allConst = 0; - - if( allConst ) { - - switch( this->operation ) { - - /* Non-Trig single-argument functions */ - - case sum_fct: - if( theParams[0]->type==BOOLEAN ) - this->value.data.lng = ( pVals[0].data.log ? 1 : 0 ); - else if( theParams[0]->type==LONG ) - this->value.data.lng = pVals[0].data.lng; - else if( theParams[0]->type==DOUBLE ) - this->value.data.dbl = pVals[0].data.dbl; - else if( theParams[0]->type==BITSTR ) - strcpy(this->value.data.str, pVals[0].data.str); - break; - case average_fct: - if( theParams[0]->type==LONG ) - this->value.data.dbl = pVals[0].data.lng; - else if( theParams[0]->type==DOUBLE ) - this->value.data.dbl = pVals[0].data.dbl; - break; - case stddev_fct: - this->value.data.dbl = 0; /* Standard deviation of a constant = 0 */ - break; - case median_fct: - if( theParams[0]->type==BOOLEAN ) - this->value.data.lng = ( pVals[0].data.log ? 1 : 0 ); - else if( theParams[0]->type==LONG ) - this->value.data.lng = pVals[0].data.lng; - else - this->value.data.dbl = pVals[0].data.dbl; - break; - - case poirnd_fct: - if( theParams[0]->type==DOUBLE ) - this->value.data.lng = simplerng_getpoisson(pVals[0].data.dbl); - else - this->value.data.lng = simplerng_getpoisson(pVals[0].data.lng); - break; - - case abs_fct: - if( theParams[0]->type==DOUBLE ) { - dval = pVals[0].data.dbl; - this->value.data.dbl = (dval>0.0 ? dval : -dval); - } else { - ival = pVals[0].data.lng; - this->value.data.lng = (ival> 0 ? ival : -ival); - } - break; - - /* Special Null-Handling Functions */ - - case nonnull_fct: - this->value.data.lng = 1; /* Constants are always 1-element and defined */ - break; - case isnull_fct: /* Constants are always defined */ - this->value.data.log = 0; - break; - case defnull_fct: - if( this->type==BOOLEAN ) - this->value.data.log = pVals[0].data.log; - else if( this->type==LONG ) - this->value.data.lng = pVals[0].data.lng; - else if( this->type==DOUBLE ) - this->value.data.dbl = pVals[0].data.dbl; - else if( this->type==STRING ) - strcpy(this->value.data.str,pVals[0].data.str); - break; - - /* Math functions with 1 double argument */ - - case sin_fct: - this->value.data.dbl = sin( pVals[0].data.dbl ); - break; - case cos_fct: - this->value.data.dbl = cos( pVals[0].data.dbl ); - break; - case tan_fct: - this->value.data.dbl = tan( pVals[0].data.dbl ); - break; - case asin_fct: - dval = pVals[0].data.dbl; - if( dval<-1.0 || dval>1.0 ) - fferror("Out of range argument to arcsin"); - else - this->value.data.dbl = asin( dval ); - break; - case acos_fct: - dval = pVals[0].data.dbl; - if( dval<-1.0 || dval>1.0 ) - fferror("Out of range argument to arccos"); - else - this->value.data.dbl = acos( dval ); - break; - case atan_fct: - this->value.data.dbl = atan( pVals[0].data.dbl ); - break; - case sinh_fct: - this->value.data.dbl = sinh( pVals[0].data.dbl ); - break; - case cosh_fct: - this->value.data.dbl = cosh( pVals[0].data.dbl ); - break; - case tanh_fct: - this->value.data.dbl = tanh( pVals[0].data.dbl ); - break; - case exp_fct: - this->value.data.dbl = exp( pVals[0].data.dbl ); - break; - case log_fct: - dval = pVals[0].data.dbl; - if( dval<=0.0 ) - fferror("Out of range argument to log"); - else - this->value.data.dbl = log( dval ); - break; - case log10_fct: - dval = pVals[0].data.dbl; - if( dval<=0.0 ) - fferror("Out of range argument to log10"); - else - this->value.data.dbl = log10( dval ); - break; - case sqrt_fct: - dval = pVals[0].data.dbl; - if( dval<0.0 ) - fferror("Out of range argument to sqrt"); - else - this->value.data.dbl = sqrt( dval ); - break; - case ceil_fct: - this->value.data.dbl = ceil( pVals[0].data.dbl ); - break; - case floor_fct: - this->value.data.dbl = floor( pVals[0].data.dbl ); - break; - case round_fct: - this->value.data.dbl = floor( pVals[0].data.dbl + 0.5 ); - break; - - /* Two-argument Trig Functions */ - - case atan2_fct: - this->value.data.dbl = - atan2( pVals[0].data.dbl, pVals[1].data.dbl ); - break; - - /* Four-argument ANGSEP function */ - case angsep_fct: - this->value.data.dbl = - angsep_calc(pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl); - - /* Min/Max functions taking 1 or 2 arguments */ - - case min1_fct: - /* No constant vectors! */ - if( this->type == DOUBLE ) - this->value.data.dbl = pVals[0].data.dbl; - else if( this->type == LONG ) - this->value.data.lng = pVals[0].data.lng; - else if( this->type == BITSTR ) - strcpy(this->value.data.str, pVals[0].data.str); - break; - case min2_fct: - if( this->type == DOUBLE ) - this->value.data.dbl = - minvalue( pVals[0].data.dbl, pVals[1].data.dbl ); - else if( this->type == LONG ) - this->value.data.lng = - minvalue( pVals[0].data.lng, pVals[1].data.lng ); - break; - case max1_fct: - /* No constant vectors! */ - if( this->type == DOUBLE ) - this->value.data.dbl = pVals[0].data.dbl; - else if( this->type == LONG ) - this->value.data.lng = pVals[0].data.lng; - else if( this->type == BITSTR ) - strcpy(this->value.data.str, pVals[0].data.str); - break; - case max2_fct: - if( this->type == DOUBLE ) - this->value.data.dbl = - maxvalue( pVals[0].data.dbl, pVals[1].data.dbl ); - else if( this->type == LONG ) - this->value.data.lng = - maxvalue( pVals[0].data.lng, pVals[1].data.lng ); - break; - - /* Boolean SAO region Functions... scalar or vector dbls */ - - case near_fct: - this->value.data.log = bnear( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl ); - break; - case circle_fct: - this->value.data.log = circle( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl, - pVals[4].data.dbl ); - break; - case box_fct: - this->value.data.log = saobox( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl, - pVals[4].data.dbl, pVals[5].data.dbl, - pVals[6].data.dbl ); - break; - case elps_fct: - this->value.data.log = - ellipse( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl, - pVals[4].data.dbl, pVals[5].data.dbl, - pVals[6].data.dbl ); - break; - - /* C Conditional expression: bool ? expr : expr */ - - case ifthenelse_fct: - switch( this->type ) { - case BOOLEAN: - this->value.data.log = ( pVals[2].data.log ? - pVals[0].data.log : pVals[1].data.log ); - break; - case LONG: - this->value.data.lng = ( pVals[2].data.log ? - pVals[0].data.lng : pVals[1].data.lng ); - break; - case DOUBLE: - this->value.data.dbl = ( pVals[2].data.log ? - pVals[0].data.dbl : pVals[1].data.dbl ); - break; - case STRING: - strcpy(this->value.data.str, ( pVals[2].data.log ? - pVals[0].data.str : - pVals[1].data.str ) ); - break; - } - break; - - /* String functions */ - case strmid_fct: - cstrmid(this->value.data.str, this->value.nelem, - pVals[0].data.str, pVals[0].nelem, - pVals[1].data.lng); - break; - case strpos_fct: - { - char *res = strstr(pVals[0].data.str, pVals[1].data.str); - if (res == NULL) { - this->value.data.lng = 0; - } else { - this->value.data.lng = (res - pVals[0].data.str) + 1; - } - break; - } - - } - this->operation = CONST_OP; - - } else { - - Allocate_Ptrs( this ); - - row = gParse.nRows; - elem = row * this->value.nelem; - - if( !gParse.status ) { - switch( this->operation ) { - - /* Special functions with no arguments */ - - case row_fct: - while( row-- ) { - this->value.data.lngptr[row] = gParse.firstRow + row; - this->value.undef[row] = 0; - } - break; - case null_fct: - if( this->type==LONG ) { - while( row-- ) { - this->value.data.lngptr[row] = 0; - this->value.undef[row] = 1; - } - } else if( this->type==STRING ) { - while( row-- ) { - this->value.data.strptr[row][0] = '\0'; - this->value.undef[row] = 1; - } - } - break; - case rnd_fct: - while( elem-- ) { - this->value.data.dblptr[elem] = simplerng_getuniform(); - this->value.undef[elem] = 0; - } - break; - - case gasrnd_fct: - while( elem-- ) { - this->value.data.dblptr[elem] = simplerng_getnorm(); - this->value.undef[elem] = 0; - } - break; - - case poirnd_fct: - if( theParams[0]->type==DOUBLE ) { - if (theParams[0]->operation == CONST_OP) { - while( elem-- ) { - this->value.undef[elem] = (pVals[0].data.dbl < 0); - if (! this->value.undef[elem]) { - this->value.data.lngptr[elem] = simplerng_getpoisson(pVals[0].data.dbl); - } - } - } else { - while( elem-- ) { - this->value.undef[elem] = theParams[0]->value.undef[elem]; - if (theParams[0]->value.data.dblptr[elem] < 0) - this->value.undef[elem] = 1; - if (! this->value.undef[elem]) { - this->value.data.lngptr[elem] = - simplerng_getpoisson(theParams[0]->value.data.dblptr[elem]); - } - } /* while */ - } /* ! CONST_OP */ - } else { - /* LONG */ - if (theParams[0]->operation == CONST_OP) { - while( elem-- ) { - this->value.undef[elem] = (pVals[0].data.lng < 0); - if (! this->value.undef[elem]) { - this->value.data.lngptr[elem] = simplerng_getpoisson(pVals[0].data.lng); - } - } - } else { - while( elem-- ) { - this->value.undef[elem] = theParams[0]->value.undef[elem]; - if (theParams[0]->value.data.lngptr[elem] < 0) - this->value.undef[elem] = 1; - if (! this->value.undef[elem]) { - this->value.data.lngptr[elem] = - simplerng_getpoisson(theParams[0]->value.data.lngptr[elem]); - } - } /* while */ - } /* ! CONST_OP */ - } /* END LONG */ - break; - - - /* Non-Trig single-argument functions */ - - case sum_fct: - elem = row * theParams[0]->value.nelem; - if( theParams[0]->type==BOOLEAN ) { - while( row-- ) { - this->value.data.lngptr[row] = 0; - /* Default is UNDEF until a defined value is found */ - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( ! theParams[0]->value.undef[elem] ) { - this->value.data.lngptr[row] += - ( theParams[0]->value.data.logptr[elem] ? 1 : 0 ); - this->value.undef[row] = 0; - } - } - } - } else if( theParams[0]->type==LONG ) { - while( row-- ) { - this->value.data.lngptr[row] = 0; - /* Default is UNDEF until a defined value is found */ - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( ! theParams[0]->value.undef[elem] ) { - this->value.data.lngptr[row] += - theParams[0]->value.data.lngptr[elem]; - this->value.undef[row] = 0; - } - } - } - } else if( theParams[0]->type==DOUBLE ){ - while( row-- ) { - this->value.data.dblptr[row] = 0.0; - /* Default is UNDEF until a defined value is found */ - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( ! theParams[0]->value.undef[elem] ) { - this->value.data.dblptr[row] += - theParams[0]->value.data.dblptr[elem]; - this->value.undef[row] = 0; - } - } - } - } else { /* BITSTR */ - nelem = theParams[0]->value.nelem; - while( row-- ) { - char *sptr1 = theParams[0]->value.data.strptr[row]; - this->value.data.lngptr[row] = 0; - this->value.undef[row] = 0; - while (*sptr1) { - if (*sptr1 == '1') this->value.data.lngptr[row] ++; - sptr1++; - } - } - } - break; - - case average_fct: - elem = row * theParams[0]->value.nelem; - if( theParams[0]->type==LONG ) { - while( row-- ) { - int count = 0; - this->value.data.dblptr[row] = 0; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if (theParams[0]->value.undef[elem] == 0) { - this->value.data.dblptr[row] += - theParams[0]->value.data.lngptr[elem]; - count ++; - } - } - if (count == 0) { - this->value.undef[row] = 1; - } else { - this->value.undef[row] = 0; - this->value.data.dblptr[row] /= count; - } - } - } else if( theParams[0]->type==DOUBLE ){ - while( row-- ) { - int count = 0; - this->value.data.dblptr[row] = 0; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if (theParams[0]->value.undef[elem] == 0) { - this->value.data.dblptr[row] += - theParams[0]->value.data.dblptr[elem]; - count ++; - } - } - if (count == 0) { - this->value.undef[row] = 1; - } else { - this->value.undef[row] = 0; - this->value.data.dblptr[row] /= count; - } - } - } - break; - case stddev_fct: - elem = row * theParams[0]->value.nelem; - if( theParams[0]->type==LONG ) { - - /* Compute the mean value */ - while( row-- ) { - int count = 0; - double sum = 0, sum2 = 0; - - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if (theParams[0]->value.undef[elem] == 0) { - sum += theParams[0]->value.data.lngptr[elem]; - count ++; - } - } - if (count > 1) { - sum /= count; - - /* Compute the sum of squared deviations */ - nelem = theParams[0]->value.nelem; - elem += nelem; /* Reset elem for second pass */ - while( nelem-- ) { - elem--; - if (theParams[0]->value.undef[elem] == 0) { - double dx = (theParams[0]->value.data.lngptr[elem] - sum); - sum2 += (dx*dx); - } - } - - sum2 /= (double)count-1; - - this->value.undef[row] = 0; - this->value.data.dblptr[row] = sqrt(sum2); - } else { - this->value.undef[row] = 0; /* STDDEV => 0 */ - this->value.data.dblptr[row] = 0; - } - } - } else if( theParams[0]->type==DOUBLE ){ - - /* Compute the mean value */ - while( row-- ) { - int count = 0; - double sum = 0, sum2 = 0; - - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if (theParams[0]->value.undef[elem] == 0) { - sum += theParams[0]->value.data.dblptr[elem]; - count ++; - } - } - if (count > 1) { - sum /= count; - - /* Compute the sum of squared deviations */ - nelem = theParams[0]->value.nelem; - elem += nelem; /* Reset elem for second pass */ - while( nelem-- ) { - elem--; - if (theParams[0]->value.undef[elem] == 0) { - double dx = (theParams[0]->value.data.dblptr[elem] - sum); - sum2 += (dx*dx); - } - } - - sum2 /= (double)count-1; - - this->value.undef[row] = 0; - this->value.data.dblptr[row] = sqrt(sum2); - } else { - this->value.undef[row] = 0; /* STDDEV => 0 */ - this->value.data.dblptr[row] = 0; - } - } - } - break; - - case median_fct: - elem = row * theParams[0]->value.nelem; - nelem = theParams[0]->value.nelem; - if( theParams[0]->type==LONG ) { - long *dptr = theParams[0]->value.data.lngptr; - char *uptr = theParams[0]->value.undef; - long *mptr = (long *) malloc(sizeof(long)*nelem); - int irow; - - /* Allocate temporary storage for this row, since the - quickselect function will scramble the contents */ - if (mptr == 0) { - fferror("Could not allocate temporary memory in median function"); - free( this->value.data.ptr ); - break; - } - - for (irow=0; irow 0) { - this->value.undef[irow] = 0; - this->value.data.lngptr[irow] = qselect_median_lng(mptr, nelem1); - } else { - this->value.undef[irow] = 1; - this->value.data.lngptr[irow] = 0; - } - - } - - free(mptr); - } else { - double *dptr = theParams[0]->value.data.dblptr; - char *uptr = theParams[0]->value.undef; - double *mptr = (double *) malloc(sizeof(double)*nelem); - int irow; - - /* Allocate temporary storage for this row, since the - quickselect function will scramble the contents */ - if (mptr == 0) { - fferror("Could not allocate temporary memory in median function"); - free( this->value.data.ptr ); - break; - } - - for (irow=0; irow 0) { - this->value.undef[irow] = 0; - this->value.data.dblptr[irow] = qselect_median_dbl(mptr, nelem1); - } else { - this->value.undef[irow] = 1; - this->value.data.dblptr[irow] = 0; - } - - } - free(mptr); - } - break; - case abs_fct: - if( theParams[0]->type==DOUBLE ) - while( elem-- ) { - dval = theParams[0]->value.data.dblptr[elem]; - this->value.data.dblptr[elem] = (dval>0.0 ? dval : -dval); - this->value.undef[elem] = theParams[0]->value.undef[elem]; - } - else - while( elem-- ) { - ival = theParams[0]->value.data.lngptr[elem]; - this->value.data.lngptr[elem] = (ival> 0 ? ival : -ival); - this->value.undef[elem] = theParams[0]->value.undef[elem]; - } - break; - - /* Special Null-Handling Functions */ - - case nonnull_fct: - nelem = theParams[0]->value.nelem; - if ( theParams[0]->type==STRING ) nelem = 1; - elem = row * nelem; - while( row-- ) { - int nelem1 = nelem; - - this->value.undef[row] = 0; /* Initialize to 0 (defined) */ - this->value.data.lngptr[row] = 0; - while( nelem1-- ) { - elem --; - if ( theParams[0]->value.undef[elem] == 0 ) this->value.data.lngptr[row] ++; - } - } - break; - case isnull_fct: - if( theParams[0]->type==STRING ) elem = row; - while( elem-- ) { - this->value.data.logptr[elem] = theParams[0]->value.undef[elem]; - this->value.undef[elem] = 0; - } - break; - case defnull_fct: - switch( this->type ) { - case BOOLEAN: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pNull[i] = theParams[i]->value.undef[elem]; - pVals[i].data.log = - theParams[i]->value.data.logptr[elem]; - } else if( vector[i] ) { - pNull[i] = theParams[i]->value.undef[row]; - pVals[i].data.log = - theParams[i]->value.data.logptr[row]; - } - if( pNull[0] ) { - this->value.undef[elem] = pNull[1]; - this->value.data.logptr[elem] = pVals[1].data.log; - } else { - this->value.undef[elem] = 0; - this->value.data.logptr[elem] = pVals[0].data.log; - } - } - } - break; - case LONG: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pNull[i] = theParams[i]->value.undef[elem]; - pVals[i].data.lng = - theParams[i]->value.data.lngptr[elem]; - } else if( vector[i] ) { - pNull[i] = theParams[i]->value.undef[row]; - pVals[i].data.lng = - theParams[i]->value.data.lngptr[row]; - } - if( pNull[0] ) { - this->value.undef[elem] = pNull[1]; - this->value.data.lngptr[elem] = pVals[1].data.lng; - } else { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = pVals[0].data.lng; - } - } - } - break; - case DOUBLE: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pNull[i] = theParams[i]->value.undef[elem]; - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - } else if( vector[i] ) { - pNull[i] = theParams[i]->value.undef[row]; - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - } - if( pNull[0] ) { - this->value.undef[elem] = pNull[1]; - this->value.data.dblptr[elem] = pVals[1].data.dbl; - } else { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = pVals[0].data.dbl; - } - } - } - break; - case STRING: - while( row-- ) { - i=2; while( i-- ) - if( vector[i] ) { - pNull[i] = theParams[i]->value.undef[row]; - strcpy(pVals[i].data.str, - theParams[i]->value.data.strptr[row]); - } - if( pNull[0] ) { - this->value.undef[row] = pNull[1]; - strcpy(this->value.data.strptr[row],pVals[1].data.str); - } else { - this->value.undef[elem] = 0; - strcpy(this->value.data.strptr[row],pVals[0].data.str); - } - } - } - break; - - /* Math functions with 1 double argument */ - - case sin_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - sin( theParams[0]->value.data.dblptr[elem] ); - } - break; - case cos_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - cos( theParams[0]->value.data.dblptr[elem] ); - } - break; - case tan_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - tan( theParams[0]->value.data.dblptr[elem] ); - } - break; - case asin_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - if( dval<-1.0 || dval>1.0 ) { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } else - this->value.data.dblptr[elem] = asin( dval ); - } - break; - case acos_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - if( dval<-1.0 || dval>1.0 ) { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } else - this->value.data.dblptr[elem] = acos( dval ); - } - break; - case atan_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - this->value.data.dblptr[elem] = atan( dval ); - } - break; - case sinh_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - sinh( theParams[0]->value.data.dblptr[elem] ); - } - break; - case cosh_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - cosh( theParams[0]->value.data.dblptr[elem] ); - } - break; - case tanh_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - tanh( theParams[0]->value.data.dblptr[elem] ); - } - break; - case exp_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - this->value.data.dblptr[elem] = exp( dval ); - } - break; - case log_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - if( dval<=0.0 ) { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } else - this->value.data.dblptr[elem] = log( dval ); - } - break; - case log10_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - if( dval<=0.0 ) { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } else - this->value.data.dblptr[elem] = log10( dval ); - } - break; - case sqrt_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - dval = theParams[0]->value.data.dblptr[elem]; - if( dval<0.0 ) { - this->value.data.dblptr[elem] = 0.0; - this->value.undef[elem] = 1; - } else - this->value.data.dblptr[elem] = sqrt( dval ); - } - break; - case ceil_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - ceil( theParams[0]->value.data.dblptr[elem] ); - } - break; - case floor_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - floor( theParams[0]->value.data.dblptr[elem] ); - } - break; - case round_fct: - while( elem-- ) - if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { - this->value.data.dblptr[elem] = - floor( theParams[0]->value.data.dblptr[elem] + 0.5); - } - break; - - /* Two-argument Trig Functions */ - - case atan2_fct: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = (pNull[0] || pNull[1]) ) ) - this->value.data.dblptr[elem] = - atan2( pVals[0].data.dbl, pVals[1].data.dbl ); - } - } - break; - - /* Four-argument ANGSEP Function */ - - case angsep_fct: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=4; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || - pNull[2] || pNull[3]) ) ) - this->value.data.dblptr[elem] = - angsep_calc(pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl); - } - } - break; - - - - /* Min/Max functions taking 1 or 2 arguments */ - - case min1_fct: - elem = row * theParams[0]->value.nelem; - if( this->type==LONG ) { - long minVal=0; - while( row-- ) { - valInit = 1; - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( !theParams[0]->value.undef[elem] ) { - if ( valInit ) { - valInit = 0; - minVal = theParams[0]->value.data.lngptr[elem]; - } else { - minVal = minvalue( minVal, - theParams[0]->value.data.lngptr[elem] ); - } - this->value.undef[row] = 0; - } - } - this->value.data.lngptr[row] = minVal; - } - } else if( this->type==DOUBLE ) { - double minVal=0.0; - while( row-- ) { - valInit = 1; - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( !theParams[0]->value.undef[elem] ) { - if ( valInit ) { - valInit = 0; - minVal = theParams[0]->value.data.dblptr[elem]; - } else { - minVal = minvalue( minVal, - theParams[0]->value.data.dblptr[elem] ); - } - this->value.undef[row] = 0; - } - } - this->value.data.dblptr[row] = minVal; - } - } else if( this->type==BITSTR ) { - char minVal; - while( row-- ) { - char *sptr1 = theParams[0]->value.data.strptr[row]; - minVal = '1'; - while (*sptr1) { - if (*sptr1 == '0') minVal = '0'; - sptr1++; - } - this->value.data.strptr[row][0] = minVal; - this->value.data.strptr[row][1] = 0; /* Null terminate */ - } - } - break; - case min2_fct: - if( this->type==LONG ) { - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.lng = - theParams[i]->value.data.lngptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.lng = - theParams[i]->value.data.lngptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( pNull[0] && pNull[1] ) { - this->value.undef[elem] = 1; - this->value.data.lngptr[elem] = 0; - } else if (pNull[0]) { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = pVals[1].data.lng; - } else if (pNull[1]) { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = pVals[0].data.lng; - } else { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = - minvalue( pVals[0].data.lng, pVals[1].data.lng ); - } - } - } - } else if( this->type==DOUBLE ) { - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( pNull[0] && pNull[1] ) { - this->value.undef[elem] = 1; - this->value.data.dblptr[elem] = 0; - } else if (pNull[0]) { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = pVals[1].data.dbl; - } else if (pNull[1]) { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = pVals[0].data.dbl; - } else { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = - minvalue( pVals[0].data.dbl, pVals[1].data.dbl ); - } - } - } - } - break; - - case max1_fct: - elem = row * theParams[0]->value.nelem; - if( this->type==LONG ) { - long maxVal=0; - while( row-- ) { - valInit = 1; - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( !theParams[0]->value.undef[elem] ) { - if ( valInit ) { - valInit = 0; - maxVal = theParams[0]->value.data.lngptr[elem]; - } else { - maxVal = maxvalue( maxVal, - theParams[0]->value.data.lngptr[elem] ); - } - this->value.undef[row] = 0; - } - } - this->value.data.lngptr[row] = maxVal; - } - } else if( this->type==DOUBLE ) { - double maxVal=0.0; - while( row-- ) { - valInit = 1; - this->value.undef[row] = 1; - nelem = theParams[0]->value.nelem; - while( nelem-- ) { - elem--; - if ( !theParams[0]->value.undef[elem] ) { - if ( valInit ) { - valInit = 0; - maxVal = theParams[0]->value.data.dblptr[elem]; - } else { - maxVal = maxvalue( maxVal, - theParams[0]->value.data.dblptr[elem] ); - } - this->value.undef[row] = 0; - } - } - this->value.data.dblptr[row] = maxVal; - } - } else if( this->type==BITSTR ) { - char maxVal; - while( row-- ) { - char *sptr1 = theParams[0]->value.data.strptr[row]; - maxVal = '0'; - while (*sptr1) { - if (*sptr1 == '1') maxVal = '1'; - sptr1++; - } - this->value.data.strptr[row][0] = maxVal; - this->value.data.strptr[row][1] = 0; /* Null terminate */ - } - } - break; - case max2_fct: - if( this->type==LONG ) { - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.lng = - theParams[i]->value.data.lngptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.lng = - theParams[i]->value.data.lngptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( pNull[0] && pNull[1] ) { - this->value.undef[elem] = 1; - this->value.data.lngptr[elem] = 0; - } else if (pNull[0]) { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = pVals[1].data.lng; - } else if (pNull[1]) { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = pVals[0].data.lng; - } else { - this->value.undef[elem] = 0; - this->value.data.lngptr[elem] = - maxvalue( pVals[0].data.lng, pVals[1].data.lng ); - } - } - } - } else if( this->type==DOUBLE ) { - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( pNull[0] && pNull[1] ) { - this->value.undef[elem] = 1; - this->value.data.dblptr[elem] = 0; - } else if (pNull[0]) { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = pVals[1].data.dbl; - } else if (pNull[1]) { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = pVals[0].data.dbl; - } else { - this->value.undef[elem] = 0; - this->value.data.dblptr[elem] = - maxvalue( pVals[0].data.dbl, pVals[1].data.dbl ); - } - } - } - } - break; - - /* Boolean SAO region Functions... scalar or vector dbls */ - - case near_fct: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=3; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || - pNull[2]) ) ) - this->value.data.logptr[elem] = - bnear( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl ); - } - } - break; - - case circle_fct: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=5; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || - pNull[2] || pNull[3] || - pNull[4]) ) ) - this->value.data.logptr[elem] = - circle( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl, - pVals[4].data.dbl ); - } - } - break; - - case box_fct: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=7; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || - pNull[2] || pNull[3] || - pNull[4] || pNull[5] || - pNull[6] ) ) ) - this->value.data.logptr[elem] = - saobox( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl, - pVals[4].data.dbl, pVals[5].data.dbl, - pVals[6].data.dbl ); - } - } - break; - - case elps_fct: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - i=7; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || - pNull[2] || pNull[3] || - pNull[4] || pNull[5] || - pNull[6] ) ) ) - this->value.data.logptr[elem] = - ellipse( pVals[0].data.dbl, pVals[1].data.dbl, - pVals[2].data.dbl, pVals[3].data.dbl, - pVals[4].data.dbl, pVals[5].data.dbl, - pVals[6].data.dbl ); - } - } - break; - - /* C Conditional expression: bool ? expr : expr */ - - case ifthenelse_fct: - switch( this->type ) { - case BOOLEAN: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - if( vector[2]>1 ) { - pVals[2].data.log = - theParams[2]->value.data.logptr[elem]; - pNull[2] = theParams[2]->value.undef[elem]; - } else if( vector[2] ) { - pVals[2].data.log = - theParams[2]->value.data.logptr[row]; - pNull[2] = theParams[2]->value.undef[row]; - } - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.log = - theParams[i]->value.data.logptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.log = - theParams[i]->value.data.logptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = pNull[2]) ) { - if( pVals[2].data.log ) { - this->value.data.logptr[elem] = pVals[0].data.log; - this->value.undef[elem] = pNull[0]; - } else { - this->value.data.logptr[elem] = pVals[1].data.log; - this->value.undef[elem] = pNull[1]; - } - } - } - } - break; - case LONG: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - if( vector[2]>1 ) { - pVals[2].data.log = - theParams[2]->value.data.logptr[elem]; - pNull[2] = theParams[2]->value.undef[elem]; - } else if( vector[2] ) { - pVals[2].data.log = - theParams[2]->value.data.logptr[row]; - pNull[2] = theParams[2]->value.undef[row]; - } - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.lng = - theParams[i]->value.data.lngptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.lng = - theParams[i]->value.data.lngptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = pNull[2]) ) { - if( pVals[2].data.log ) { - this->value.data.lngptr[elem] = pVals[0].data.lng; - this->value.undef[elem] = pNull[0]; - } else { - this->value.data.lngptr[elem] = pVals[1].data.lng; - this->value.undef[elem] = pNull[1]; - } - } - } - } - break; - case DOUBLE: - while( row-- ) { - nelem = this->value.nelem; - while( nelem-- ) { - elem--; - if( vector[2]>1 ) { - pVals[2].data.log = - theParams[2]->value.data.logptr[elem]; - pNull[2] = theParams[2]->value.undef[elem]; - } else if( vector[2] ) { - pVals[2].data.log = - theParams[2]->value.data.logptr[row]; - pNull[2] = theParams[2]->value.undef[row]; - } - i=2; while( i-- ) - if( vector[i]>1 ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[elem]; - pNull[i] = theParams[i]->value.undef[elem]; - } else if( vector[i] ) { - pVals[i].data.dbl = - theParams[i]->value.data.dblptr[row]; - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[elem] = pNull[2]) ) { - if( pVals[2].data.log ) { - this->value.data.dblptr[elem] = pVals[0].data.dbl; - this->value.undef[elem] = pNull[0]; - } else { - this->value.data.dblptr[elem] = pVals[1].data.dbl; - this->value.undef[elem] = pNull[1]; - } - } - } - } - break; - case STRING: - while( row-- ) { - if( vector[2] ) { - pVals[2].data.log = theParams[2]->value.data.logptr[row]; - pNull[2] = theParams[2]->value.undef[row]; - } - i=2; while( i-- ) - if( vector[i] ) { - strcpy( pVals[i].data.str, - theParams[i]->value.data.strptr[row] ); - pNull[i] = theParams[i]->value.undef[row]; - } - if( !(this->value.undef[row] = pNull[2]) ) { - if( pVals[2].data.log ) { - strcpy( this->value.data.strptr[row], - pVals[0].data.str ); - this->value.undef[row] = pNull[0]; - } else { - strcpy( this->value.data.strptr[row], - pVals[1].data.str ); - this->value.undef[row] = pNull[1]; - } - } else { - this->value.data.strptr[row][0] = '\0'; - } - } - break; - - } - break; - - /* String functions */ - case strmid_fct: - { - int strconst = theParams[0]->operation == CONST_OP; - int posconst = theParams[1]->operation == CONST_OP; - int lenconst = theParams[2]->operation == CONST_OP; - int dest_len = this->value.nelem; - int src_len = theParams[0]->value.nelem; - - while (row--) { - int pos; - int len; - char *str; - int undef = 0; - - if (posconst) { - pos = theParams[1]->value.data.lng; - } else { - pos = theParams[1]->value.data.lngptr[row]; - if (theParams[1]->value.undef[row]) undef = 1; - } - if (strconst) { - str = theParams[0]->value.data.str; - if (src_len == 0) src_len = strlen(str); - } else { - str = theParams[0]->value.data.strptr[row]; - if (theParams[0]->value.undef[row]) undef = 1; - } - if (lenconst) { - len = dest_len; - } else { - len = theParams[2]->value.data.lngptr[row]; - if (theParams[2]->value.undef[row]) undef = 1; - } - this->value.data.strptr[row][0] = '\0'; - if (pos == 0) undef = 1; - if (! undef ) { - if (cstrmid(this->value.data.strptr[row], len, - str, src_len, pos) < 0) break; - } - this->value.undef[row] = undef; - } - } - break; - - /* String functions */ - case strpos_fct: - { - int const1 = theParams[0]->operation == CONST_OP; - int const2 = theParams[1]->operation == CONST_OP; - - while (row--) { - char *str1, *str2; - int undef = 0; - - if (const1) { - str1 = theParams[0]->value.data.str; - } else { - str1 = theParams[0]->value.data.strptr[row]; - if (theParams[0]->value.undef[row]) undef = 1; - } - if (const2) { - str2 = theParams[1]->value.data.str; - } else { - str2 = theParams[1]->value.data.strptr[row]; - if (theParams[1]->value.undef[row]) undef = 1; - } - this->value.data.lngptr[row] = 0; - if (! undef ) { - char *res = strstr(str1, str2); - if (res == NULL) { - undef = 1; - this->value.data.lngptr[row] = 0; - } else { - this->value.data.lngptr[row] = (res - str1) + 1; - } - } - this->value.undef[row] = undef; - } - } - break; - - - } /* End switch(this->operation) */ - } /* End if (!gParse.status) */ - } /* End non-constant operations */ - - i = this->nSubNodes; - while( i-- ) { - if( theParams[i]->operation>0 ) { - /* Currently only numeric params allowed */ - free( theParams[i]->value.data.ptr ); - } - } -} - -static void Do_Deref( Node *this ) -{ - Node *theVar, *theDims[MAXDIMS]; - int isConst[MAXDIMS], allConst; - long dimVals[MAXDIMS]; - int i, nDims; - long row, elem, dsize; - - theVar = gParse.Nodes + this->SubNodes[0]; - - i = nDims = this->nSubNodes-1; - allConst = 1; - while( i-- ) { - theDims[i] = gParse.Nodes + this->SubNodes[i+1]; - isConst[i] = ( theDims[i]->operation==CONST_OP ); - if( isConst[i] ) - dimVals[i] = theDims[i]->value.data.lng; - else - allConst = 0; - } - - if( this->type==DOUBLE ) { - dsize = sizeof( double ); - } else if( this->type==LONG ) { - dsize = sizeof( long ); - } else if( this->type==BOOLEAN ) { - dsize = sizeof( char ); - } else - dsize = 0; - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - - if( allConst && theVar->value.naxis==nDims ) { - - /* Dereference completely using constant indices */ - - elem = 0; - i = nDims; - while( i-- ) { - if( dimVals[i]<1 || dimVals[i]>theVar->value.naxes[i] ) break; - elem = theVar->value.naxes[i]*elem + dimVals[i]-1; - } - if( i<0 ) { - for( row=0; rowtype==STRING ) - this->value.undef[row] = theVar->value.undef[row]; - else if( this->type==BITSTR ) - this->value.undef; /* Dummy - BITSTRs do not have undefs */ - else - this->value.undef[row] = theVar->value.undef[elem]; - - if( this->type==DOUBLE ) - this->value.data.dblptr[row] = - theVar->value.data.dblptr[elem]; - else if( this->type==LONG ) - this->value.data.lngptr[row] = - theVar->value.data.lngptr[elem]; - else if( this->type==BOOLEAN ) - this->value.data.logptr[row] = - theVar->value.data.logptr[elem]; - else { - /* XXX Note, the below expression uses knowledge of - the layout of the string format, namely (nelem+1) - characters per string, followed by (nelem+1) - "undef" values. */ - this->value.data.strptr[row][0] = - theVar->value.data.strptr[0][elem+row]; - this->value.data.strptr[row][1] = 0; /* Null terminate */ - } - elem += theVar->value.nelem; - } - } else { - fferror("Index out of range"); - free( this->value.data.ptr ); - } - - } else if( allConst && nDims==1 ) { - - /* Reduce dimensions by 1, using a constant index */ - - if( dimVals[0] < 1 || - dimVals[0] > theVar->value.naxes[ theVar->value.naxis-1 ] ) { - fferror("Index out of range"); - free( this->value.data.ptr ); - } else if ( this->type == BITSTR || this->type == STRING ) { - elem = this->value.nelem * (dimVals[0]-1); - for( row=0; rowvalue.undef) - this->value.undef[row] = theVar->value.undef[row]; - memcpy( (char*)this->value.data.strptr[0] - + row*sizeof(char)*(this->value.nelem+1), - (char*)theVar->value.data.strptr[0] + elem*sizeof(char), - this->value.nelem * sizeof(char) ); - /* Null terminate */ - this->value.data.strptr[row][this->value.nelem] = 0; - elem += theVar->value.nelem+1; - } - } else { - elem = this->value.nelem * (dimVals[0]-1); - for( row=0; rowvalue.undef + row*this->value.nelem, - theVar->value.undef + elem, - this->value.nelem * sizeof(char) ); - memcpy( (char*)this->value.data.ptr - + row*dsize*this->value.nelem, - (char*)theVar->value.data.ptr + elem*dsize, - this->value.nelem * dsize ); - elem += theVar->value.nelem; - } - } - - } else if( theVar->value.naxis==nDims ) { - - /* Dereference completely using an expression for the indices */ - - for( row=0; rowvalue.undef[row] ) { - fferror("Null encountered as vector index"); - free( this->value.data.ptr ); - break; - } else - dimVals[i] = theDims[i]->value.data.lngptr[row]; - } - } - if( gParse.status ) break; - - elem = 0; - i = nDims; - while( i-- ) { - if( dimVals[i]<1 || dimVals[i]>theVar->value.naxes[i] ) break; - elem = theVar->value.naxes[i]*elem + dimVals[i]-1; - } - if( i<0 ) { - elem += row*theVar->value.nelem; - - if( this->type==STRING ) - this->value.undef[row] = theVar->value.undef[row]; - else if( this->type==BITSTR ) - this->value.undef; /* Dummy - BITSTRs do not have undefs */ - else - this->value.undef[row] = theVar->value.undef[elem]; - - if( this->type==DOUBLE ) - this->value.data.dblptr[row] = - theVar->value.data.dblptr[elem]; - else if( this->type==LONG ) - this->value.data.lngptr[row] = - theVar->value.data.lngptr[elem]; - else if( this->type==BOOLEAN ) - this->value.data.logptr[row] = - theVar->value.data.logptr[elem]; - else { - /* XXX Note, the below expression uses knowledge of - the layout of the string format, namely (nelem+1) - characters per string, followed by (nelem+1) - "undef" values. */ - this->value.data.strptr[row][0] = - theVar->value.data.strptr[0][elem+row]; - this->value.data.strptr[row][1] = 0; /* Null terminate */ - } - } else { - fferror("Index out of range"); - free( this->value.data.ptr ); - } - } - - } else { - - /* Reduce dimensions by 1, using a nonconstant expression */ - - for( row=0; rowvalue.undef[row] ) { - fferror("Null encountered as vector index"); - free( this->value.data.ptr ); - break; - } else - dimVals[0] = theDims[0]->value.data.lngptr[row]; - - if( dimVals[0] < 1 || - dimVals[0] > theVar->value.naxes[ theVar->value.naxis-1 ] ) { - fferror("Index out of range"); - free( this->value.data.ptr ); - } else if ( this->type == BITSTR || this->type == STRING ) { - elem = this->value.nelem * (dimVals[0]-1); - elem += row*(theVar->value.nelem+1); - if (this->value.undef) - this->value.undef[row] = theVar->value.undef[row]; - memcpy( (char*)this->value.data.strptr[0] - + row*sizeof(char)*(this->value.nelem+1), - (char*)theVar->value.data.strptr[0] + elem*sizeof(char), - this->value.nelem * sizeof(char) ); - /* Null terminate */ - this->value.data.strptr[row][this->value.nelem] = 0; - } else { - elem = this->value.nelem * (dimVals[0]-1); - elem += row*theVar->value.nelem; - memcpy( this->value.undef + row*this->value.nelem, - theVar->value.undef + elem, - this->value.nelem * sizeof(char) ); - memcpy( (char*)this->value.data.ptr - + row*dsize*this->value.nelem, - (char*)theVar->value.data.ptr + elem*dsize, - this->value.nelem * dsize ); - } - } - } - } - - if( theVar->operation>0 ) { - if (theVar->type == STRING || theVar->type == BITSTR) - free(theVar->value.data.strptr[0] ); - else - free( theVar->value.data.ptr ); - } - for( i=0; ioperation>0 ) { - free( theDims[i]->value.data.ptr ); - } -} - -static void Do_GTI( Node *this ) -{ - Node *theExpr, *theTimes; - double *start, *stop, *times; - long elem, nGTI, gti; - int ordered; - - theTimes = gParse.Nodes + this->SubNodes[0]; - theExpr = gParse.Nodes + this->SubNodes[1]; - - nGTI = theTimes->value.nelem; - start = theTimes->value.data.dblptr; - stop = theTimes->value.data.dblptr + nGTI; - ordered = theTimes->type; - - if( theExpr->operation==CONST_OP ) { - - this->value.data.log = - (Search_GTI( theExpr->value.data.dbl, nGTI, start, stop, ordered )>=0); - this->operation = CONST_OP; - - } else { - - Allocate_Ptrs( this ); - - times = theExpr->value.data.dblptr; - if( !gParse.status ) { - - elem = gParse.nRows * this->value.nelem; - if( nGTI ) { - gti = -1; - while( elem-- ) { - if( (this->value.undef[elem] = theExpr->value.undef[elem]) ) - continue; - - /* Before searching entire GTI, check the GTI found last time */ - if( gti<0 || times[elem]stop[gti] ) { - gti = Search_GTI( times[elem], nGTI, start, stop, ordered ); - } - this->value.data.logptr[elem] = ( gti>=0 ); - } - } else - while( elem-- ) { - this->value.data.logptr[elem] = 0; - this->value.undef[elem] = 0; - } - } - } - - if( theExpr->operation>0 ) - free( theExpr->value.data.ptr ); -} - -static long Search_GTI( double evtTime, long nGTI, double *start, - double *stop, int ordered ) -{ - long gti, step; - - if( ordered && nGTI>15 ) { /* If time-ordered and lots of GTIs, */ - /* use "FAST" Binary search algorithm */ - if( evtTime>=start[0] && evtTime<=stop[nGTI-1] ) { - gti = step = (nGTI >> 1); - while(1) { - if( step>1L ) step >>= 1; - - if( evtTime>stop[gti] ) { - if( evtTime>=start[gti+1] ) - gti += step; - else { - gti = -1L; - break; - } - } else if( evtTime=start[gti] && evtTime<=stop[gti] ) - break; - } - return( gti ); -} - -static void Do_REG( Node *this ) -{ - Node *theRegion, *theX, *theY; - double Xval=0.0, Yval=0.0; - char Xnull=0, Ynull=0; - int Xvector, Yvector; - long nelem, elem, rows; - - theRegion = gParse.Nodes + this->SubNodes[0]; - theX = gParse.Nodes + this->SubNodes[1]; - theY = gParse.Nodes + this->SubNodes[2]; - - Xvector = ( theX->operation!=CONST_OP ); - if( Xvector ) - Xvector = theX->value.nelem; - else { - Xval = theX->value.data.dbl; - } - - Yvector = ( theY->operation!=CONST_OP ); - if( Yvector ) - Yvector = theY->value.nelem; - else { - Yval = theY->value.data.dbl; - } - - if( !Xvector && !Yvector ) { - - this->value.data.log = - ( fits_in_region( Xval, Yval, (SAORegion *)theRegion->value.data.ptr ) - != 0 ); - this->operation = CONST_OP; - - } else { - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - - rows = gParse.nRows; - nelem = this->value.nelem; - elem = rows*nelem; - - while( rows-- ) { - while( nelem-- ) { - elem--; - - if( Xvector>1 ) { - Xval = theX->value.data.dblptr[elem]; - Xnull = theX->value.undef[elem]; - } else if( Xvector ) { - Xval = theX->value.data.dblptr[rows]; - Xnull = theX->value.undef[rows]; - } - - if( Yvector>1 ) { - Yval = theY->value.data.dblptr[elem]; - Ynull = theY->value.undef[elem]; - } else if( Yvector ) { - Yval = theY->value.data.dblptr[rows]; - Ynull = theY->value.undef[rows]; - } - - this->value.undef[elem] = ( Xnull || Ynull ); - if( this->value.undef[elem] ) - continue; - - this->value.data.logptr[elem] = - ( fits_in_region( Xval, Yval, - (SAORegion *)theRegion->value.data.ptr ) - != 0 ); - } - nelem = this->value.nelem; - } - } - } - - if( theX->operation>0 ) - free( theX->value.data.ptr ); - if( theY->operation>0 ) - free( theY->value.data.ptr ); -} - -static void Do_Vector( Node *this ) -{ - Node *that; - long row, elem, idx, jdx, offset=0; - int node; - - Allocate_Ptrs( this ); - - if( !gParse.status ) { - - for( node=0; nodenSubNodes; node++ ) { - - that = gParse.Nodes + this->SubNodes[node]; - - if( that->operation == CONST_OP ) { - - idx = gParse.nRows*this->value.nelem + offset; - while( (idx-=this->value.nelem)>=0 ) { - - this->value.undef[idx] = 0; - - switch( this->type ) { - case BOOLEAN: - this->value.data.logptr[idx] = that->value.data.log; - break; - case LONG: - this->value.data.lngptr[idx] = that->value.data.lng; - break; - case DOUBLE: - this->value.data.dblptr[idx] = that->value.data.dbl; - break; - } - } - - } else { - - row = gParse.nRows; - idx = row * that->value.nelem; - while( row-- ) { - elem = that->value.nelem; - jdx = row*this->value.nelem + offset; - while( elem-- ) { - this->value.undef[jdx+elem] = - that->value.undef[--idx]; - - switch( this->type ) { - case BOOLEAN: - this->value.data.logptr[jdx+elem] = - that->value.data.logptr[idx]; - break; - case LONG: - this->value.data.lngptr[jdx+elem] = - that->value.data.lngptr[idx]; - break; - case DOUBLE: - this->value.data.dblptr[jdx+elem] = - that->value.data.dblptr[idx]; - break; - } - } - } - } - offset += that->value.nelem; - } - - } - - for( node=0; node < this->nSubNodes; node++ ) - if( OPER(this->SubNodes[node])>0 ) - free( gParse.Nodes[this->SubNodes[node]].value.data.ptr ); -} - -/*****************************************************************************/ -/* Utility routines which perform the calculations on bits and SAO regions */ -/*****************************************************************************/ - -static char bitlgte(char *bits1, int oper, char *bits2) -{ - int val1, val2, nextbit; - char result; - int i, l1, l2, length, ldiff; - char *stream=0; - char chr1, chr2; - - l1 = strlen(bits1); - l2 = strlen(bits2); - length = (l1 > l2) ? l1 : l2; - stream = (char *)malloc(sizeof(char)*(length+1)); - if (l1 < l2) - { - ldiff = l2 - l1; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l1-- ) stream[i++] = *(bits1++); - stream[i] = '\0'; - bits1 = stream; - } - else if (l2 < l1) - { - ldiff = l1 - l2; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l2-- ) stream[i++] = *(bits2++); - stream[i] = '\0'; - bits2 = stream; - } - - val1 = val2 = 0; - nextbit = 1; - - while( length-- ) - { - chr1 = bits1[length]; - chr2 = bits2[length]; - if ((chr1 != 'x')&&(chr1 != 'X')&&(chr2 != 'x')&&(chr2 != 'X')) - { - if (chr1 == '1') val1 += nextbit; - if (chr2 == '1') val2 += nextbit; - nextbit *= 2; - } - } - result = 0; - switch (oper) - { - case LT: - if (val1 < val2) result = 1; - break; - case LTE: - if (val1 <= val2) result = 1; - break; - case GT: - if (val1 > val2) result = 1; - break; - case GTE: - if (val1 >= val2) result = 1; - break; - } - free(stream); - return (result); -} - -static void bitand(char *result,char *bitstrm1,char *bitstrm2) -{ - int i, l1, l2, ldiff, largestStream; - char *stream=0; - char chr1, chr2; - - l1 = strlen(bitstrm1); - l2 = strlen(bitstrm2); - largestStream = (l1 > l2) ? l1 : l2; - stream = (char *)malloc(sizeof(char)*(largestStream+1)); - if (l1 < l2) - { - ldiff = l2 - l1; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l1-- ) stream[i++] = *(bitstrm1++); - stream[i] = '\0'; - bitstrm1 = stream; - } - else if (l2 < l1) - { - ldiff = l1 - l2; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l2-- ) stream[i++] = *(bitstrm2++); - stream[i] = '\0'; - bitstrm2 = stream; - } - while ( (chr1 = *(bitstrm1++)) ) - { - chr2 = *(bitstrm2++); - if ((chr1 == 'x') || (chr2 == 'x')) - *result = 'x'; - else if ((chr1 == '1') && (chr2 == '1')) - *result = '1'; - else - *result = '0'; - result++; - } - free(stream); - *result = '\0'; -} - -static void bitor(char *result,char *bitstrm1,char *bitstrm2) -{ - int i, l1, l2, ldiff, largestStream; - char *stream=0; - char chr1, chr2; - - l1 = strlen(bitstrm1); - l2 = strlen(bitstrm2); - largestStream = (l1 > l2) ? l1 : l2; - stream = (char *)malloc(sizeof(char)*(largestStream+1)); - if (l1 < l2) - { - ldiff = l2 - l1; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l1-- ) stream[i++] = *(bitstrm1++); - stream[i] = '\0'; - bitstrm1 = stream; - } - else if (l2 < l1) - { - ldiff = l1 - l2; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l2-- ) stream[i++] = *(bitstrm2++); - stream[i] = '\0'; - bitstrm2 = stream; - } - while ( (chr1 = *(bitstrm1++)) ) - { - chr2 = *(bitstrm2++); - if ((chr1 == '1') || (chr2 == '1')) - *result = '1'; - else if ((chr1 == '0') || (chr2 == '0')) - *result = '0'; - else - *result = 'x'; - result++; - } - free(stream); - *result = '\0'; -} - -static void bitnot(char *result,char *bits) -{ - int length; - char chr; - - length = strlen(bits); - while( length-- ) { - chr = *(bits++); - *(result++) = ( chr=='1' ? '0' : ( chr=='0' ? '1' : chr ) ); - } - *result = '\0'; -} - -static char bitcmp(char *bitstrm1, char *bitstrm2) -{ - int i, l1, l2, ldiff, largestStream; - char *stream=0; - char chr1, chr2; - - l1 = strlen(bitstrm1); - l2 = strlen(bitstrm2); - largestStream = (l1 > l2) ? l1 : l2; - stream = (char *)malloc(sizeof(char)*(largestStream+1)); - if (l1 < l2) - { - ldiff = l2 - l1; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l1-- ) stream[i++] = *(bitstrm1++); - stream[i] = '\0'; - bitstrm1 = stream; - } - else if (l2 < l1) - { - ldiff = l1 - l2; - i=0; - while( ldiff-- ) stream[i++] = '0'; - while( l2-- ) stream[i++] = *(bitstrm2++); - stream[i] = '\0'; - bitstrm2 = stream; - } - while( (chr1 = *(bitstrm1++)) ) - { - chr2 = *(bitstrm2++); - if ( ((chr1 == '0') && (chr2 == '1')) - || ((chr1 == '1') && (chr2 == '0')) ) - { - free(stream); - return( 0 ); - } - } - free(stream); - return( 1 ); -} - -static char bnear(double x, double y, double tolerance) -{ - if (fabs(x - y) < tolerance) - return ( 1 ); - else - return ( 0 ); -} - -static char saobox(double xcen, double ycen, double xwid, double ywid, - double rot, double xcol, double ycol) -{ - double x,y,xprime,yprime,xmin,xmax,ymin,ymax,theta; - - theta = (rot / 180.0) * myPI; - xprime = xcol - xcen; - yprime = ycol - ycen; - x = xprime * cos(theta) + yprime * sin(theta); - y = -xprime * sin(theta) + yprime * cos(theta); - xmin = - 0.5 * xwid; xmax = 0.5 * xwid; - ymin = - 0.5 * ywid; ymax = 0.5 * ywid; - if ((x >= xmin) && (x <= xmax) && (y >= ymin) && (y <= ymax)) - return ( 1 ); - else - return ( 0 ); -} - -static char circle(double xcen, double ycen, double rad, - double xcol, double ycol) -{ - double r2,dx,dy,dlen; - - dx = xcol - xcen; - dy = ycol - ycen; - dx *= dx; dy *= dy; - dlen = dx + dy; - r2 = rad * rad; - if (dlen <= r2) - return ( 1 ); - else - return ( 0 ); -} - -static char ellipse(double xcen, double ycen, double xrad, double yrad, - double rot, double xcol, double ycol) -{ - double x,y,xprime,yprime,dx,dy,dlen,theta; - - theta = (rot / 180.0) * myPI; - xprime = xcol - xcen; - yprime = ycol - ycen; - x = xprime * cos(theta) + yprime * sin(theta); - y = -xprime * sin(theta) + yprime * cos(theta); - dx = x / xrad; dy = y / yrad; - dx *= dx; dy *= dy; - dlen = dx + dy; - if (dlen <= 1.0) - return ( 1 ); - else - return ( 0 ); -} - -/* - * Extract substring - */ -int cstrmid(char *dest_str, int dest_len, - char *src_str, int src_len, - int pos) -{ - /* char fill_char = ' '; */ - char fill_char = '\0'; - if (src_len == 0) { src_len = strlen(src_str); } /* .. if constant */ - - /* Fill destination with blanks */ - if (pos < 0) { - fferror("STRMID(S,P,N) P must be 0 or greater"); - return -1; - } - if (pos > src_len || pos == 0) { - /* pos==0: blank string requested */ - memset(dest_str, fill_char, dest_len); - } else if (pos+dest_len > src_len) { - /* Copy a subset */ - int nsub = src_len-pos+1; - int npad = dest_len - nsub; - memcpy(dest_str, src_str+pos-1, nsub); - /* Fill remaining string with blanks */ - memset(dest_str+nsub, fill_char, npad); - } else { - /* Full string copy */ - memcpy(dest_str, src_str+pos-1, dest_len); - } - dest_str[dest_len] = '\0'; /* Null-terminate */ - - return 0; -} - - -static void fferror(char *s) -{ - char msg[80]; - - if( !gParse.status ) gParse.status = PARSE_SYNTAX_ERR; - - strncpy(msg, s, 80); - msg[79] = '\0'; - ffpmsg(msg); -} - diff --git a/src/external/OpenGR/3rdparty/cfitsio/f77.inc b/src/external/OpenGR/3rdparty/cfitsio/f77.inc deleted file mode 100644 index 51e05e498..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/f77.inc +++ /dev/null @@ -1,31 +0,0 @@ -C Codes for FITS extension types - integer IMAGE_HDU, ASCII_TBL, BINARY_TBL - parameter ( - & IMAGE_HDU = 0, - & ASCII_TBL = 1, - & BINARY_TBL = 2 ) - -C Codes for FITS table data types - - integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT - integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX - parameter ( - & TBIT = 1, - & TBYTE = 11, - & TLOGICAL = 14, - & TSTRING = 16, - & TSHORT = 21, - & TINT = 31, - & TFLOAT = 42, - & TDOUBLE = 82, - & TCOMPLEX = 83, - & TDBLCOMPLEX = 163 ) - -C Codes for iterator column types - - integer InputCol, InputOutputCol, OutputCol - parameter ( - & InputCol = 0, - & InputOutputCol = 1, - & OutputCol = 2 ) - diff --git a/src/external/OpenGR/3rdparty/cfitsio/f77_wrap.h b/src/external/OpenGR/3rdparty/cfitsio/f77_wrap.h deleted file mode 100644 index 8b0049360..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/f77_wrap.h +++ /dev/null @@ -1,287 +0,0 @@ -#define UNSIGNED_BYTE - -#include "cfortran.h" - -/************************************************************************ - Some platforms creates longs as 8-byte integers. On other machines, ints - and longs are both 4-bytes, so both are compatible with Fortrans - default integer which is 4-bytes. To support 8-byte longs, we must redefine - LONGs and convert them to 8-bytes when going to C, and restore them - to 4-bytes when returning to Fortran. Ugh!!! -*************************************************************************/ - -#if defined(DECFortran) || (defined(__alpha) && defined(g77Fortran)) \ - || (defined(mipsFortran) && _MIPS_SZLONG==64) \ - || (defined(IBMR2Fortran) && defined(__64BIT__)) \ - || defined(__ia64__) \ - || defined (__sparcv9) || (defined(__sparc__) && defined(__arch64__)) \ - || defined (__x86_64__) \ - || defined (_SX) \ - || defined (__powerpc64__)\ - || defined (__s390x__) - -#define LONG8BYTES_INT4BYTES - -#undef LONGV_cfSTR -#undef PLONG_cfSTR -#undef LONGVVVVVVV_cfTYPE -#undef PLONG_cfTYPE -#undef LONGV_cfT -#undef PLONG_cfT - -#define LONGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,LONGV,A,B,C,D,E) -#define PLONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PLONG,A,B,C,D,E) -#define LONGVVVVVVV_cfTYPE int -#define PLONG_cfTYPE int -#define LONGV_cfQ(B) long *B, _(B,N); -#define PLONG_cfQ(B) long B; -#define LONGV_cfT(M,I,A,B,D) ( (_(B,N) = * _3(M,_LONGV_A,I)), \ - B = F2Clongv(_(B,N),A) ) -#define PLONG_cfT(M,I,A,B,D) ((B=*A),&B) -#define LONGV_cfR(A,B,D) C2Flongv(_(B,N),A,B); -#define PLONG_cfR(A,B,D) *A=B; -#define LONGV_cfH(S,U,B) -#define PLONG_cfH(S,U,B) - -static long *F2Clongv(long size, int *A) -{ - long i; - long *B; - - B=(long *)malloc( size*sizeof(long) ); - for(i=0;idsc$a_pointer - -/* We want single strings to be equivalent to string vectors with */ -/* a single element, so ignore the number of elements info in the */ -/* vector structure, and rely on the NUM_ELEM definitions. */ - -#undef STRINGV_cfT -#define STRINGV_cfT(M,I,A,B,D) TTTTSTRV(A->dsc$a_pointer, B, \ - A->dsc$w_length, \ - num_elem(A->dsc$a_pointer, \ - A->dsc$w_length, \ - _3(M,_STRV_A,I) ) ) -#else -#ifdef CRAYFortran -#define PPSTRING_cfT(M,I,A,B,D) (unsigned char*)_fcdtocp(A) -#else -#define PPSTRING_cfT(M,I,A,B,D) (unsigned char*)A -#endif -#endif - -#define _cfMAX(A,B) ( (A>B) ? A : B ) -#define STRINGV_cfQ(B) char **B; unsigned int _(B,N), _(B,M); -#define STRINGV_cfR(A,B,D) free(B[0]); free(B); -#define TTSTR( A,B,D) \ - ((B=(char*)malloc(_cfMAX(D,gMinStrLen)+1))[D]='\0',memcpy(B,A,D), \ - kill_trailing(B,' ')) -#define TTTTSTRV( A,B,D,E) ( \ - _(B,N)=_cfMAX(E,1), \ - _(B,M)=_cfMAX(D,gMinStrLen)+1, \ - B=(char**)malloc(_(B,N)*sizeof(char*)), \ - B[0]=(char*)malloc(_(B,N)*_(B,M)), \ - vindex(B,_(B,M),_(B,N),f2cstrv2(A,B[0],D,_(B,M),_(B,N))) \ - ) -#define RRRRPSTRV(A,B,D) \ - c2fstrv2(B[0],A,_(B,M),D,_(B,N)), \ - free(B[0]), \ - free(B); - -static char **vindex(char **B, int elem_len, int nelem, char *B0) -{ - int i; - if( nelem ) - for( i=0;idsc$a_pointer)[0]) -#define BYTEV_cfT(M,I,A,B,D) (INTEGER_BYTE*)A->dsc$a_pointer -#else -#ifdef CRAYFortran -#define BYTE_cfN(T,A) _fcd A -#define BYTEV_cfN(T,A) _fcd A -#define BYTE_cfT(M,I,A,B,D) (INTEGER_BYTE)((_fcdtocp(A))[0]) -#define BYTEV_cfT(M,I,A,B,D) (INTEGER_BYTE*)_fcdtocp(A) -#else -#define BYTE_cfN(T,A) INTEGER_BYTE * A -#define BYTEV_cfN(T,A) INTEGER_BYTE * A -#define BYTE_cfT(M,I,A,B,D) A[0] -#define BYTEV_cfT(M,I,A,B,D) A -#endif -#endif - -/************************************************************************ - The following definitions and functions handle conversions between - C and Fortran arrays of LOGICALS. Individually, LOGICALS are - treated as int's but as char's when in an array. cfortran defines - (F2C/C2F)LOGICALV but never uses them, so these routines also - handle TRUE/FALSE conversions. -*************************************************************************/ - -#undef LOGICALV_cfSTR -#undef LOGICALV_cfT -#define LOGICALV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,LOGICALV,A,B,C,D,E) -#define LOGICALV_cfQ(B) char *B; unsigned int _(B,N); -#define LOGICALV_cfT(M,I,A,B,D) (_(B,N)= * _3(M,_LOGV_A,I), \ - B=F2CcopyLogVect(_(B,N),A)) -#define LOGICALV_cfR(A,B,D) C2FcopyLogVect(_(B,N),A,B); -#define LOGICALV_cfH(S,U,B) - -static char *F2CcopyLogVect(long size, int *A) -{ - long i; - char *B; - - B=(char *)malloc(size*sizeof(char)); - for( i=0; i0 ) return; - for( i=50;i0 ) return; - if( unit == -1 ) { - int i; for( i=50; i=NMAXFILES ) { - *status = BAD_FILEPTR; - ffpmsg("Cfffiou was sent an unacceptable unit number."); - } else gFitsFiles[unit]=NULL; -} -FCALLSCSUB2(Cfffiou,FTFIOU,ftfiou,INT,PINT) - - -int CFITS2Unit( fitsfile *fptr ) - /* Utility routine to convert a fitspointer to a Fortran unit number */ - /* for use when a C program is calling a Fortran routine which could */ - /* in turn call CFITSIO... Modelled after code by Ning Gan. */ -{ - static fitsfile *last_fptr = (fitsfile *)NULL; /* Remember last fptr */ - static int last_unit = 0; /* Remember last unit */ - int status = 0; - - /* Test whether we are repeating the last lookup */ - - if( last_unit && fptr==gFitsFiles[last_unit] ) - return( last_unit ); - - /* Check if gFitsFiles has an entry for this fptr. */ - /* Allows Fortran to call C to call Fortran to */ - /* call CFITSIO... OUCH!!! */ - - last_fptr = fptr; - for( last_unit=1; last_unit=NMAXFILES ) - return(0); - - return(gFitsFiles[unit]); -} - - /**************************************************/ - /* Start of wrappers for routines in fitsio.h */ - /**************************************************/ - -/*---------------- FITS file URL parsing routines -------------*/ - -FCALLSCSUB9(ffiurl,FTIURL,ftiurl,STRING,PSTRING,PSTRING,PSTRING,PSTRING,PSTRING,PSTRING,PSTRING,PINT) -FCALLSCSUB3(ffrtnm,FTRTNM,ftrtnm,STRING,PSTRING,PINT) -FCALLSCSUB3(ffexist,FTEXIST,ftexist,STRING,PINT,PINT) -FCALLSCSUB3(ffextn,FTEXTN,ftextn,STRING,PINT,PINT) -FCALLSCSUB7(ffrwrg,FTRWRG,ftrwrg,STRING,LONG,INT,PINT,PLONG,PLONG,PINT) - -/*---------------- FITS file I/O routines ---------------*/ - -void Cffopen( fitsfile **fptr, const char *filename, int iomode, int *blocksize, int *status ); -void Cffopen( fitsfile **fptr, const char *filename, int iomode, int *blocksize, int *status ) -{ - int hdutype; - - if( *fptr==NULL || *fptr==(fitsfile*)1 ) { - ffopen( fptr, filename, iomode, status ); - ffmahd( *fptr, 1, &hdutype, status ); - *blocksize = 1; - } else { - *status = FILE_NOT_OPENED; - ffpmsg("Cffopen tried to use an already opened unit."); - } -} -FCALLSCSUB5(Cffopen,FTOPEN,ftopen,PFITSUNIT,STRING,INT,PINT,PINT) - -void Cffdkopn( fitsfile **fptr, const char *filename, int iomode, int *blocksize, int *status ); -void Cffdkopn( fitsfile **fptr, const char *filename, int iomode, int *blocksize, int *status ) -{ - int hdutype; - - if( *fptr==NULL || *fptr==(fitsfile*)1 ) { - ffdkopn( fptr, filename, iomode, status ); - ffmahd( *fptr, 1, &hdutype, status ); - *blocksize = 1; - } else { - *status = FILE_NOT_OPENED; - ffpmsg("Cffdkopn tried to use an already opened unit."); - } -} -FCALLSCSUB5(Cffdkopn,FTDKOPN,ftdkopn,PFITSUNIT,STRING,INT,PINT,PINT) - - -void Cffnopn( fitsfile **fptr, const char *filename, int iomode, int *status ); -void Cffnopn( fitsfile **fptr, const char *filename, int iomode, int *status ) -{ - if( *fptr==NULL || *fptr==(fitsfile*)1 ) { - ffopen( fptr, filename, iomode, status ); - } else { - *status = FILE_NOT_OPENED; - ffpmsg("Cffnopn tried to use an already opened unit."); - } -} -FCALLSCSUB4(Cffnopn,FTNOPN,ftnopn,PFITSUNIT,STRING,INT,PINT) - -void Cffdopn( fitsfile **fptr, const char *filename, int iomode, int *status ); -void Cffdopn( fitsfile **fptr, const char *filename, int iomode, int *status ) -{ - if( *fptr==NULL || *fptr==(fitsfile*)1 ) { - ffdopn( fptr, filename, iomode, status ); - } else { - *status = FILE_NOT_OPENED; - ffpmsg("Cffdopn tried to use an already opened unit."); - } -} -FCALLSCSUB4(Cffdopn,FTDOPN,ftdopn,PFITSUNIT,STRING,INT,PINT) - -void Cfftopn( fitsfile **fptr, const char *filename, int iomode, int *status ); -void Cfftopn( fitsfile **fptr, const char *filename, int iomode, int *status ) -{ - if( *fptr==NULL || *fptr==(fitsfile*)1 ) { - fftopn( fptr, filename, iomode, status ); - } else { - *status = FILE_NOT_OPENED; - ffpmsg("Cfftopn tried to use an already opened unit."); - } -} -FCALLSCSUB4(Cfftopn,FTTOPN,fttopn,PFITSUNIT,STRING,INT,PINT) - -void Cffiopn( fitsfile **fptr, const char *filename, int iomode, int *status ); -void Cffiopn( fitsfile **fptr, const char *filename, int iomode, int *status ) -{ - if( *fptr==NULL || *fptr==(fitsfile*)1 ) { - ffiopn( fptr, filename, iomode, status ); - } else { - *status = FILE_NOT_OPENED; - ffpmsg("Cffiopn tried to use an already opened unit."); - } -} -FCALLSCSUB4(Cffiopn,FTIOPN,ftiopn,PFITSUNIT,STRING,INT,PINT) - -void Cffreopen( fitsfile *openfptr, fitsfile **newfptr, int *status ); -void Cffreopen( fitsfile *openfptr, fitsfile **newfptr, int *status ) -{ - if( *newfptr==NULL || *newfptr==(fitsfile*)1 ) { - ffreopen( openfptr, newfptr, status ); - } else { - *status = FILE_NOT_OPENED; - ffpmsg("Cffreopen tried to use an already opened unit."); - } -} -FCALLSCSUB3(Cffreopen,FTREOPEN,ftreopen,FITSUNIT,PFITSUNIT,PINT) - -void Cffinit( fitsfile **fptr, const char *filename, int blocksize, int *status ); -void Cffinit( fitsfile **fptr, const char *filename, int blocksize, int *status ) -{ - if( *fptr==NULL || *fptr==(fitsfile*)1 ) { - ffinit( fptr, filename, status ); - } else { - *status = FILE_NOT_CREATED; - ffpmsg("Cffinit tried to use an already opened unit."); - } -} -FCALLSCSUB4(Cffinit,FTINIT,ftinit,PFITSUNIT,STRING,INT,PINT) - -void Cffdkinit( fitsfile **fptr, const char *filename, int blocksize, int *status ); -void Cffdkinit( fitsfile **fptr, const char *filename, int blocksize, int *status ) -{ - if( *fptr==NULL || *fptr==(fitsfile*)1 ) { - ffdkinit( fptr, filename, status ); - } else { - *status = FILE_NOT_CREATED; - ffpmsg("Cffdkinit tried to use an already opened unit."); - } -} -FCALLSCSUB4(Cffdkinit,FTDKINIT,ftdkinit,PFITSUNIT,STRING,INT,PINT) - -void Cfftplt( fitsfile **fptr, const char *filename, const char *tempname, - int *status ); -void Cfftplt( fitsfile **fptr, const char *filename, const char *tempname, - int *status ) -{ - if( *fptr==NULL || *fptr==(fitsfile*)1 ) { - fftplt( fptr, filename, tempname, status ); - } else { - *status = FILE_NOT_CREATED; - ffpmsg("Cfftplt tried to use an already opened unit."); - } -} -FCALLSCSUB4(Cfftplt,FTTPLT,fttplt,PFITSUNIT,STRING,STRING,PINT) - -FCALLSCSUB2(ffflus,FTFLUS,ftflus,FITSUNIT,PINT) -FCALLSCSUB3(ffflsh,FTFLSH,ftflsh,FITSUNIT, INT, PINT) - -void Cffclos( int unit, int *status ); -void Cffclos( int unit, int *status ) -{ - if( gFitsFiles[unit]!=NULL && gFitsFiles[unit]!=(void*)1 ) { - ffclos( gFitsFiles[unit], status ); /* Flag unit number as unavailable */ - gFitsFiles[unit]=(fitsfile*)1; /* in case want to reuse it */ - } -} -FCALLSCSUB2(Cffclos,FTCLOS,ftclos,INT,PINT) - -void Cffdelt( int unit, int *status ); -void Cffdelt( int unit, int *status ) -{ - if( gFitsFiles[unit]!=NULL && gFitsFiles[unit]!=(void*)1 ) { - ffdelt( gFitsFiles[unit], status ); /* Flag unit number as unavailable */ - gFitsFiles[unit]=(fitsfile*)1; /* in case want to reuse it */ - } -} -FCALLSCSUB2(Cffdelt,FTDELT,ftdelt,INT,PINT) - -FCALLSCSUB3(ffflnm,FTFLNM,ftflnm,FITSUNIT,PSTRING,PINT) -FCALLSCSUB3(ffflmd,FTFLMD,ftflmd,FITSUNIT,PINT,PINT) - -/*--------------- utility routines ---------------*/ -FCALLSCSUB1(ffvers,FTVERS,ftvers,PFLOAT) -FCALLSCSUB1(ffupch,FTUPCH,ftupch,PSTRING) -FCALLSCSUB2(ffgerr,FTGERR,ftgerr,INT,PSTRING) -FCALLSCSUB1(ffpmsg,FTPMSG,ftpmsg,STRING) -FCALLSCSUB1(ffgmsg,FTGMSG,ftgmsg,PSTRING) -FCALLSCSUB0(ffcmsg,FTCMSG,ftcmsg) -FCALLSCSUB0(ffpmrk,FTPMRK,ftpmrk) -FCALLSCSUB0(ffcmrk,FTCMRK,ftcmrk) - -void Cffrprt( char *fname, int status ); -void Cffrprt( char *fname, int status ) -{ - if( !strcmp(fname,"STDOUT") || !strcmp(fname,"stdout") ) - ffrprt( stdout, status ); - else if( !strcmp(fname,"STDERR") || !strcmp(fname,"stderr") ) - ffrprt( stderr, status ); - else { - FILE *fptr; - - fptr = fopen(fname, "a"); - if (fptr==NULL) - printf("file pointer is null.\n"); - else { - ffrprt(fptr,status); - fclose(fptr); - } - } -} -FCALLSCSUB2(Cffrprt,FTRPRT,ftrprt,STRING,INT) - -FCALLSCSUB5(ffcmps,FTCMPS,ftcmps,STRING,STRING,LOGICAL,PLOGICAL,PLOGICAL) -FCALLSCSUB2(fftkey,FTTKEY,fttkey,STRING,PINT) -FCALLSCSUB2(fftrec,FTTREC,fttrec,STRING,PINT) -FCALLSCSUB2(ffnchk,FTNCHK,ftnchk,FITSUNIT,PINT) -FCALLSCSUB4(ffkeyn,FTKEYN,ftkeyn,STRING,INT,PSTRING,PINT) -FCALLSCSUB4(ffgknm,FTGKNM,ftgknm,STRING,PSTRING, PINT, PINT) -FCALLSCSUB4(ffnkey,FTNKEY,ftnkey,INT,STRING,PSTRING,PINT) -FCALLSCSUB3(ffdtyp,FTDTYP,ftdtyp,STRING,PSTRING,PINT) -FCALLSCFUN1(INT,ffgkcl,FTGKCL,ftgkcl,STRING) -FCALLSCSUB5(ffmkky,FTMKKY,ftmkky,STRING,STRING,STRING,PSTRING,PINT) -FCALLSCSUB4(ffpsvc,FTPSVC,ftpsvc,STRING,PSTRING,PSTRING,PINT) -FCALLSCSUB4(ffgthd,FTGTHD,ftgthd,STRING,PSTRING,PINT,PINT) -FCALLSCSUB5(ffasfm,FTASFM,ftasfm,STRING,PINT,PLONG,PINT,PINT) -FCALLSCSUB5(ffbnfm,FTBNFM,ftbnfm,STRING,PINT,PLONG,PLONG,PINT) - -#define ftgabc_STRV_A2 NUM_ELEM_ARG(1) -#define ftgabc_LONGV_A5 A1 -FCALLSCSUB6(ffgabc,FTGABC,ftgabc,INT,STRINGV,INT,PLONG,LONGV,PINT) - diff --git a/src/external/OpenGR/3rdparty/cfitsio/f77_wrap2.c b/src/external/OpenGR/3rdparty/cfitsio/f77_wrap2.c deleted file mode 100644 index 8b7de365e..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/f77_wrap2.c +++ /dev/null @@ -1,711 +0,0 @@ -/************************************************************************ - - f77_wrap1.c and f77_wrap2.c have now been split into 4 files to - prevent compile-time memory errors (from expansion of compiler commands). - f77_wrap1.c was split into f77_wrap1.c and f77_wrap3.c, and - f77_wrap2.c was split into f77_wrap2.c and f77_wrap4.c: - - f77_wrap1.c contains routines operating on whole files and some - utility routines. - - f77_wrap2.c contains routines operating on primary array, image, - or column elements. - - f77_wrap3.c contains routines operating on headers & keywords. - - f77_wrap4.c contains miscellaneous routines. - - Peter's original comments: - - Together, f77_wrap1.c and f77_wrap2.c contain C wrappers for all - the CFITSIO routines prototyped in fitsio.h, except for the - generic datatype routines and features not supported in fortran - (eg, unsigned integers), a few routines prototyped in fitsio2.h, - which only a handful of FTOOLS use, plus a few obsolete FITSIO - routines not present in CFITSIO. This file allows Fortran code - to use the CFITSIO library instead of the FITSIO library without - modification. It also gives access to new routines not present - in FITSIO. Fortran FTOOLS must continue using the old routine - names from FITSIO (ie, ftxxxx), but most of the C-wrappers simply - redirect those calls to the corresponding CFITSIO routines (ie, - ffxxxx), with appropriate parameter massaging where necessary. - The main exception are read/write routines ending in j (ie, long - data) which get redirected to C routines ending in k (ie, int - data). This is more consistent with the default integer type in - Fortran. f77_wrap1.c primarily holds routines operating on whole - files and extension headers. f77_wrap2.c handle routines which - read and write the data portion, plus miscellaneous extra routines. - - File created by Peter Wilson (HSTX), Oct-Dec. 1997 -************************************************************************/ - -#include "fitsio2.h" -#include "f77_wrap.h" - - -FCALLSCSUB5(ffgextn,FTGEXTN,ftgextn,FITSUNIT,LONG,LONG,BYTEV,PINT) -FCALLSCSUB5(ffpextn,FTPEXTN,ftpextn,FITSUNIT,LONG,LONG,BYTEV,PINT) - -/*------------ read primary array or image elements -------------*/ -FCALLSCSUB8(ffgpvb,FTGPVB,ftgpvb,FITSUNIT,LONG,LONG,LONG,BYTE,BYTEV,PLOGICAL,PINT) -FCALLSCSUB8(ffgpvi,FTGPVI,ftgpvi,FITSUNIT,LONG,LONG,LONG,SHORT,SHORTV,PLOGICAL,PINT) -FCALLSCSUB8(ffgpvk,FTGPVJ,ftgpvj,FITSUNIT,LONG,LONG,LONG,INT,INTV,PLOGICAL,PINT) -FCALLSCSUB8(ffgpvjj,FTGPVK,ftgpvk,FITSUNIT,LONG,LONG,LONG,LONGLONG,LONGLONGV,PLOGICAL,PINT) -FCALLSCSUB8(ffgpve,FTGPVE,ftgpve,FITSUNIT,LONG,LONG,LONG,FLOAT,FLOATV,PLOGICAL,PINT) -FCALLSCSUB8(ffgpvd,FTGPVD,ftgpvd,FITSUNIT,LONG,LONG,LONG,DOUBLE,DOUBLEV,PLOGICAL,PINT) - - -#define ftgpfb_LOGV_A6 A4 -FCALLSCSUB8(ffgpfb,FTGPFB,ftgpfb,FITSUNIT,LONG,LONG,LONG,BYTEV,LOGICALV,PLOGICAL,PINT) - -#define ftgpfi_LOGV_A6 A4 -FCALLSCSUB8(ffgpfi,FTGPFI,ftgpfi,FITSUNIT,LONG,LONG,LONG,SHORTV,LOGICALV,PLOGICAL,PINT) - -#define ftgpfj_LOGV_A6 A4 -FCALLSCSUB8(ffgpfk,FTGPFJ,ftgpfj,FITSUNIT,LONG,LONG,LONG,INTV,LOGICALV,PLOGICAL,PINT) - -#define ftgpfk_LOGV_A6 A4 -FCALLSCSUB8(ffgpfjj,FTGPFK,ftgpfk,FITSUNIT,LONG,LONG,LONG,LONGLONGV,LOGICALV,PLOGICAL,PINT) - -#define ftgpfe_LOGV_A6 A4 -FCALLSCSUB8(ffgpfe,FTGPFE,ftgpfe,FITSUNIT,LONG,LONG,LONG,FLOATV,LOGICALV,PLOGICAL,PINT) - -#define ftgpfd_LOGV_A6 A4 -FCALLSCSUB8(ffgpfd,FTGPFD,ftgpfd,FITSUNIT,LONG,LONG,LONG,DOUBLEV,LOGICALV,PLOGICAL,PINT) - -FCALLSCSUB9(ffg2db,FTG2DB,ftg2db,FITSUNIT,LONG,BYTE,LONG,LONG,LONG,BYTEV,PLOGICAL,PINT) -FCALLSCSUB9(ffg2di,FTG2DI,ftg2di,FITSUNIT,LONG,SHORT,LONG,LONG,LONG,SHORTV,PLOGICAL,PINT) -FCALLSCSUB9(ffg2dk,FTG2DJ,ftg2dj,FITSUNIT,LONG,INT,LONG,LONG,LONG,INTV,PLOGICAL,PINT) -FCALLSCSUB9(ffg2djj,FTG2DK,ftg2dk,FITSUNIT,LONG,LONGLONG,LONG,LONG,LONG,LONGLONGV,PLOGICAL,PINT) -FCALLSCSUB9(ffg2de,FTG2DE,ftg2de,FITSUNIT,LONG,FLOAT,LONG,LONG,LONG,FLOATV,PLOGICAL,PINT) -FCALLSCSUB9(ffg2dd,FTG2DD,ftg2dd,FITSUNIT,LONG,DOUBLE,LONG,LONG,LONG,DOUBLEV,PLOGICAL,PINT) - -FCALLSCSUB11(ffg3db,FTG3DB,ftg3db,FITSUNIT,LONG,BYTE,LONG,LONG,LONG,LONG,LONG,BYTEV,PLOGICAL,PINT) -FCALLSCSUB11(ffg3di,FTG3DI,ftg3di,FITSUNIT,LONG,SHORT,LONG,LONG,LONG,LONG,LONG,SHORTV,PLOGICAL,PINT) -FCALLSCSUB11(ffg3dk,FTG3DJ,ftg3dj,FITSUNIT,LONG,INT,LONG,LONG,LONG,LONG,LONG,INTV,PLOGICAL,PINT) -FCALLSCSUB11(ffg3djj,FTG3DK,ftg3dk,FITSUNIT,LONG,LONGLONG,LONG,LONG,LONG,LONG,LONG,LONGLONGV,PLOGICAL,PINT) -FCALLSCSUB11(ffg3de,FTG3DE,ftg3de,FITSUNIT,LONG,FLOAT,LONG,LONG,LONG,LONG,LONG,FLOATV,PLOGICAL,PINT) -FCALLSCSUB11(ffg3dd,FTG3DD,ftg3dd,FITSUNIT,LONG,DOUBLE,LONG,LONG,LONG,LONG,LONG,DOUBLEV,PLOGICAL,PINT) - - /* The follow LONGV definitions have +1 appended because the */ - /* routines use of NAXIS+1 elements of the long vectors. */ - -#define ftgsvb_LONGV_A4 A3+1 -#define ftgsvb_LONGV_A5 A3+1 -#define ftgsvb_LONGV_A6 A3+1 -#define ftgsvb_LONGV_A7 A3+1 -FCALLSCSUB11(ffgsvb,FTGSVB,ftgsvb,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,BYTE,BYTEV,PLOGICAL,PINT) - -#define ftgsvi_LONGV_A4 A3+1 -#define ftgsvi_LONGV_A5 A3+1 -#define ftgsvi_LONGV_A6 A3+1 -#define ftgsvi_LONGV_A7 A3+1 -FCALLSCSUB11(ffgsvi,FTGSVI,ftgsvi,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,SHORT,SHORTV,PLOGICAL,PINT) - -#define ftgsvj_LONGV_A4 A3+1 -#define ftgsvj_LONGV_A5 A3+1 -#define ftgsvj_LONGV_A6 A3+1 -#define ftgsvj_LONGV_A7 A3+1 -FCALLSCSUB11(ffgsvk,FTGSVJ,ftgsvj,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,INT,INTV,PLOGICAL,PINT) - -#define ftgsvk_LONGV_A4 A3+1 -#define ftgsvk_LONGV_A5 A3+1 -#define ftgsvk_LONGV_A6 A3+1 -#define ftgsvk_LONGV_A7 A3+1 -FCALLSCSUB11(ffgsvjj,FTGSVK,ftgsvk,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,LONGLONG,LONGLONGV,PLOGICAL,PINT) - -#define ftgsve_LONGV_A4 A3+1 -#define ftgsve_LONGV_A5 A3+1 -#define ftgsve_LONGV_A6 A3+1 -#define ftgsve_LONGV_A7 A3+1 -FCALLSCSUB11(ffgsve,FTGSVE,ftgsve,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,FLOAT,FLOATV,PLOGICAL,PINT) - -#define ftgsvd_LONGV_A4 A3+1 -#define ftgsvd_LONGV_A5 A3+1 -#define ftgsvd_LONGV_A6 A3+1 -#define ftgsvd_LONGV_A7 A3+1 -FCALLSCSUB11(ffgsvd,FTGSVD,ftgsvd,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,DOUBLE,DOUBLEV,PLOGICAL,PINT) - - -/* Must handle LOGICALV conversion manually */ -void Cffgsfb( fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned char *array, int *flagval, int *anynul, int *status ); -void Cffgsfb( fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned char *array, int *flagval, int *anynul, int *status ) -{ - char *Cflagval; - long nflagval; - int i; - - for( nflagval=1, i=0; iFwork_fn(&a1,&a2,&a3,&a4,&n_cols,units,colnum,datatype, - iotype,repeat,&status,f->userData, - ptrs[ 0], ptrs[ 1], ptrs[ 2], ptrs[ 3], ptrs[ 4], - ptrs[ 5], ptrs[ 6], ptrs[ 7], ptrs[ 8], ptrs[ 9], - ptrs[10], ptrs[11], ptrs[12], ptrs[13], ptrs[14], - ptrs[15], ptrs[16], ptrs[17], ptrs[18], ptrs[19], - ptrs[20], ptrs[21], ptrs[22], ptrs[23], ptrs[24] ); - } - - /* Check whether there are any LOGICAL or STRING columns being outputted */ - nstr=0; - for( i=0;i -#include -#include -#include -#include "fitsio2.h" - -static long noutchar; -static long noutmax; - -static int htrans(int a[],int nx,int ny); -static void digitize(int a[], int nx, int ny, int scale); -static int encode(char *outfile, long *nlen, int a[], int nx, int ny, int scale); -static void shuffle(int a[], int n, int n2, int tmp[]); - -static int htrans64(LONGLONG a[],int nx,int ny); -static void digitize64(LONGLONG a[], int nx, int ny, int scale); -static int encode64(char *outfile, long *nlen, LONGLONG a[], int nx, int ny, int scale); -static void shuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[]); - -static void writeint(char *outfile, int a); -static void writelonglong(char *outfile, LONGLONG a); -static int doencode(char *outfile, int a[], int nx, int ny, unsigned char nbitplanes[3]); -static int doencode64(char *outfile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3]); -static int qwrite(char *file, char buffer[], int n); - -static int qtree_encode(char *outfile, int a[], int n, int nqx, int nqy, int nbitplanes); -static int qtree_encode64(char *outfile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes); -static void start_outputing_bits(void); -static void done_outputing_bits(char *outfile); -static void output_nbits(char *outfile, int bits, int n); - -static void qtree_onebit(int a[], int n, int nx, int ny, unsigned char b[], int bit); -static void qtree_onebit64(LONGLONG a[], int n, int nx, int ny, unsigned char b[], int bit); -static void qtree_reduce(unsigned char a[], int n, int nx, int ny, unsigned char b[]); -static int bufcopy(unsigned char a[], int n, unsigned char buffer[], int *b, int bmax); -static void write_bdirect(char *outfile, int a[], int n,int nqx, int nqy, unsigned char scratch[], int bit); -static void write_bdirect64(char *outfile, LONGLONG a[], int n,int nqx, int nqy, unsigned char scratch[], int bit); - -/* #define output_nybble(outfile,c) output_nbits(outfile,c,4) */ -static void output_nybble(char *outfile, int bits); -static void output_nnybble(char *outfile, int n, unsigned char array[]); - -#define output_huffman(outfile,c) output_nbits(outfile,code[c],ncode[c]) - -/* ---------------------------------------------------------------------- */ -int fits_hcompress(int *a, int ny, int nx, int scale, char *output, - long *nbytes, int *status) -{ - /* - compress the input image using the H-compress algorithm - - a - input image array - nx - size of X axis of image - ny - size of Y axis of image - scale - quantization scale factor. Larger values results in more (lossy) compression - scale = 0 does lossless compression - output - pre-allocated array to hold the output compressed stream of bytes - nbyts - input value = size of the output buffer; - returned value = size of the compressed byte stream, in bytes - - NOTE: the nx and ny dimensions as defined within this code are reversed from - the usual FITS notation. ny is the fastest varying dimension, which is - usually considered the X axis in the FITS image display - - */ - - int stat; - - if (*status > 0) return(*status); - - /* H-transform */ - stat = htrans(a, nx, ny); - if (stat) { - *status = stat; - return(*status); - } - - /* digitize */ - digitize(a, nx, ny, scale); - - /* encode and write to output array */ - - FFLOCK; - noutmax = *nbytes; /* input value is the allocated size of the array */ - *nbytes = 0; /* reset */ - - stat = encode(output, nbytes, a, nx, ny, scale); - FFUNLOCK; - - *status = stat; - return(*status); -} -/* ---------------------------------------------------------------------- */ -int fits_hcompress64(LONGLONG *a, int ny, int nx, int scale, char *output, - long *nbytes, int *status) -{ - /* - compress the input image using the H-compress algorithm - - a - input image array - nx - size of X axis of image - ny - size of Y axis of image - scale - quantization scale factor. Larger values results in more (lossy) compression - scale = 0 does lossless compression - output - pre-allocated array to hold the output compressed stream of bytes - nbyts - size of the compressed byte stream, in bytes - - NOTE: the nx and ny dimensions as defined within this code are reversed from - the usual FITS notation. ny is the fastest varying dimension, which is - usually considered the X axis in the FITS image display - - */ - - int stat; - - if (*status > 0) return(*status); - - /* H-transform */ - stat = htrans64(a, nx, ny); - if (stat) { - *status = stat; - return(*status); - } - - /* digitize */ - digitize64(a, nx, ny, scale); - - /* encode and write to output array */ - - FFLOCK; - noutmax = *nbytes; /* input value is the allocated size of the array */ - *nbytes = 0; /* reset */ - - stat = encode64(output, nbytes, a, nx, ny, scale); - FFUNLOCK; - - *status = stat; - return(*status); -} - - -/* Copyright (c) 1993 Association of Universities for Research - * in Astronomy. All rights reserved. Produced under National - * Aeronautics and Space Administration Contract No. NAS5-26555. - */ -/* htrans.c H-transform of NX x NY integer image - * - * Programmer: R. White Date: 11 May 1992 - */ - -/* ######################################################################### */ -static int htrans(int a[],int nx,int ny) -{ -int nmax, log2n, h0, hx, hy, hc, nxtop, nytop, i, j, k; -int oddx, oddy; -int shift, mask, mask2, prnd, prnd2, nrnd2; -int s10, s00; -int *tmp; - - /* - * log2n is log2 of max(nx,ny) rounded up to next power of 2 - */ - nmax = (nx>ny) ? nx : ny; - log2n = (int) (log((float) nmax)/log(2.0)+0.5); - if ( nmax > (1<> shift; - hx = (a[s10+1] + a[s10] - a[s00+1] - a[s00]) >> shift; - hy = (a[s10+1] - a[s10] + a[s00+1] - a[s00]) >> shift; - hc = (a[s10+1] - a[s10] - a[s00+1] + a[s00]) >> shift; - - /* - * Throw away the 2 bottom bits of h0, bottom bit of hx,hy. - * To get rounding to be same for positive and negative - * numbers, nrnd2 = prnd2 - 1. - */ - a[s10+1] = hc; - a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ; - a[s00+1] = ( (hy>=0) ? (hy+prnd) : hy ) & mask ; - a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; - s00 += 2; - s10 += 2; - } - if (oddy) { - /* - * do last element in row if row length is odd - * s00+1, s10+1 are off edge - */ - h0 = (a[s10] + a[s00]) << (1-shift); - hx = (a[s10] - a[s00]) << (1-shift); - a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ; - a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; - s00 += 1; - s10 += 1; - } - } - if (oddx) { - /* - * do last row if column length is odd - * s10, s10+1 are off edge - */ - s00 = i*ny; - for (j = 0; j=0) ? (hy+prnd) : hy ) & mask ; - a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; - s00 += 2; - } - if (oddy) { - /* - * do corner element if both row and column lengths are odd - * s00+1, s10, s10+1 are off edge - */ - h0 = a[s00] << (2-shift); - a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; - } - } - /* - * now shuffle in each dimension to group coefficients by order - */ - for (i = 0; i>1; - nytop = (nytop+1)>>1; - /* - * divisor doubles after first reduction - */ - shift = 1; - /* - * masks, rounding values double after each iteration - */ - mask = mask2; - prnd = prnd2; - mask2 = mask2 << 1; - prnd2 = prnd2 << 1; - nrnd2 = prnd2 - 1; - } - free(tmp); - return(0); -} -/* ######################################################################### */ - -static int htrans64(LONGLONG a[],int nx,int ny) -{ -int nmax, log2n, nxtop, nytop, i, j, k; -int oddx, oddy; -int shift; -int s10, s00; -LONGLONG h0, hx, hy, hc, prnd, prnd2, nrnd2, mask, mask2; -LONGLONG *tmp; - - /* - * log2n is log2 of max(nx,ny) rounded up to next power of 2 - */ - nmax = (nx>ny) ? nx : ny; - log2n = (int) (log((float) nmax)/log(2.0)+0.5); - if ( nmax > (1<> shift; - hx = (a[s10+1] + a[s10] - a[s00+1] - a[s00]) >> shift; - hy = (a[s10+1] - a[s10] + a[s00+1] - a[s00]) >> shift; - hc = (a[s10+1] - a[s10] - a[s00+1] + a[s00]) >> shift; - - /* - * Throw away the 2 bottom bits of h0, bottom bit of hx,hy. - * To get rounding to be same for positive and negative - * numbers, nrnd2 = prnd2 - 1. - */ - a[s10+1] = hc; - a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ; - a[s00+1] = ( (hy>=0) ? (hy+prnd) : hy ) & mask ; - a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; - s00 += 2; - s10 += 2; - } - if (oddy) { - /* - * do last element in row if row length is odd - * s00+1, s10+1 are off edge - */ - h0 = (a[s10] + a[s00]) << (1-shift); - hx = (a[s10] - a[s00]) << (1-shift); - a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ; - a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; - s00 += 1; - s10 += 1; - } - } - if (oddx) { - /* - * do last row if column length is odd - * s10, s10+1 are off edge - */ - s00 = i*ny; - for (j = 0; j=0) ? (hy+prnd) : hy ) & mask ; - a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; - s00 += 2; - } - if (oddy) { - /* - * do corner element if both row and column lengths are odd - * s00+1, s10, s10+1 are off edge - */ - h0 = a[s00] << (2-shift); - a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; - } - } - /* - * now shuffle in each dimension to group coefficients by order - */ - for (i = 0; i>1; - nytop = (nytop+1)>>1; - /* - * divisor doubles after first reduction - */ - shift = 1; - /* - * masks, rounding values double after each iteration - */ - mask = mask2; - prnd = prnd2; - mask2 = mask2 << 1; - prnd2 = prnd2 << 1; - nrnd2 = prnd2 - 1; - } - free(tmp); - return(0); -} - -/* ######################################################################### */ -static void -shuffle(int a[], int n, int n2, int tmp[]) -{ - -/* -int a[]; array to shuffle -int n; number of elements to shuffle -int n2; second dimension -int tmp[]; scratch storage -*/ - -int i; -int *p1, *p2, *pt; - - /* - * copy odd elements to tmp - */ - pt = tmp; - p1 = &a[n2]; - for (i=1; i < n; i += 2) { - *pt = *p1; - pt += 1; - p1 += (n2+n2); - } - /* - * compress even elements into first half of A - */ - p1 = &a[n2]; - p2 = &a[n2+n2]; - for (i=2; i0) ? (*p+d) : (*p-d))/scale; -} - -/* ######################################################################### */ -static void -digitize64(LONGLONG a[], int nx, int ny, int scale) -{ -LONGLONG d, *p, scale64; - - /* - * round to multiple of scale - */ - if (scale <= 1) return; - d=(scale+1)/2-1; - scale64 = scale; /* use a 64-bit int for efficiency in the big loop */ - - for (p=a; p <= &a[nx*ny-1]; p++) *p = ((*p>0) ? (*p+d) : (*p-d))/scale64; -} -/* ######################################################################### */ -/* ######################################################################### */ -/* Copyright (c) 1993 Association of Universities for Research - * in Astronomy. All rights reserved. Produced under National - * Aeronautics and Space Administration Contract No. NAS5-26555. - */ -/* encode.c encode H-transform and write to outfile - * - * Programmer: R. White Date: 2 February 1994 - */ - -static char code_magic[2] = { (char)0xDD, (char)0x99 }; - - -/* ######################################################################### */ -static int encode(char *outfile, long *nlength, int a[], int nx, int ny, int scale) -{ - -/* FILE *outfile; - change outfile to a char array */ -/* - long * nlength returned length (in bytes) of the encoded array) - int a[]; input H-transform array (nx,ny) - int nx,ny; size of H-transform array - int scale; scale factor for digitization -*/ -int nel, nx2, ny2, i, j, k, q, vmax[3], nsign, bits_to_go; -unsigned char nbitplanes[3]; -unsigned char *signbits; -int stat; - - noutchar = 0; /* initialize the number of compressed bytes that have been written */ - nel = nx*ny; - /* - * write magic value - */ - qwrite(outfile, code_magic, sizeof(code_magic)); - writeint(outfile, nx); /* size of image */ - writeint(outfile, ny); - writeint(outfile, scale); /* scale factor for digitization */ - /* - * write first value of A (sum of all pixels -- the only value - * which does not compress well) - */ - writelonglong(outfile, (LONGLONG) a[0]); - - a[0] = 0; - /* - * allocate array for sign bits and save values, 8 per byte - (initialize to all zeros) - */ - signbits = (unsigned char *) calloc(1, (nel+7)/8); - if (signbits == (unsigned char *) NULL) { - ffpmsg("encode: insufficient memory"); - return(DATA_COMPRESSION_ERR); - } - nsign = 0; - bits_to_go = 8; -/* signbits[0] = 0; */ - for (i=0; i 0) { - /* - * positive element, put zero at end of buffer - */ - signbits[nsign] <<= 1; - bits_to_go -= 1; - } else if (a[i] < 0) { - /* - * negative element, shift in a one - */ - signbits[nsign] <<= 1; - signbits[nsign] |= 1; - bits_to_go -= 1; - /* - * replace a by absolute value - */ - a[i] = -a[i]; - } - if (bits_to_go == 0) { - /* - * filled up this byte, go to the next one - */ - bits_to_go = 8; - nsign += 1; -/* signbits[nsign] = 0; */ - } - } - if (bits_to_go != 8) { - /* - * some bits in last element - * move bits in last byte to bottom and increment nsign - */ - signbits[nsign] <<= bits_to_go; - nsign += 1; - } - /* - * calculate number of bit planes for 3 quadrants - * - * quadrant 0=bottom left, 1=bottom right or top left, 2=top right, - */ - for (q=0; q<3; q++) { - vmax[q] = 0; - } - /* - * get maximum absolute value in each quadrant - */ - nx2 = (nx+1)/2; - ny2 = (ny+1)/2; - j=0; /* column counter */ - k=0; /* row counter */ - for (i=0; i=ny2) + (k>=nx2); - if (vmax[q] < a[i]) vmax[q] = a[i]; - if (++j >= ny) { - j = 0; - k += 1; - } - } - /* - * now calculate number of bits for each quadrant - */ - - /* this is a more efficient way to do this, */ - - - for (q = 0; q < 3; q++) { - for (nbitplanes[q] = 0; vmax[q]>0; vmax[q] = vmax[q]>>1, nbitplanes[q]++) ; - } - - -/* - for (q = 0; q < 3; q++) { - nbitplanes[q] = (int) (log((float) (vmax[q]+1))/log(2.0)+0.5); - if ( (vmax[q]+1) > (1< 0) { - - if ( 0 == qwrite(outfile, (char *) signbits, nsign)) { - free(signbits); - *nlength = noutchar; - ffpmsg("encode: output buffer too small"); - return(DATA_COMPRESSION_ERR); - } - } - - free(signbits); - *nlength = noutchar; - - if (noutchar >= noutmax) { - ffpmsg("encode: output buffer too small"); - return(DATA_COMPRESSION_ERR); - } - - return(stat); -} -/* ######################################################################### */ -static int encode64(char *outfile, long *nlength, LONGLONG a[], int nx, int ny, int scale) -{ - -/* FILE *outfile; - change outfile to a char array */ -/* - long * nlength returned length (in bytes) of the encoded array) - LONGLONG a[]; input H-transform array (nx,ny) - int nx,ny; size of H-transform array - int scale; scale factor for digitization -*/ -int nel, nx2, ny2, i, j, k, q, nsign, bits_to_go; -LONGLONG vmax[3]; -unsigned char nbitplanes[3]; -unsigned char *signbits; -int stat; - - noutchar = 0; /* initialize the number of compressed bytes that have been written */ - nel = nx*ny; - /* - * write magic value - */ - qwrite(outfile, code_magic, sizeof(code_magic)); - writeint(outfile, nx); /* size of image */ - writeint(outfile, ny); - writeint(outfile, scale); /* scale factor for digitization */ - /* - * write first value of A (sum of all pixels -- the only value - * which does not compress well) - */ - writelonglong(outfile, a[0]); - - a[0] = 0; - /* - * allocate array for sign bits and save values, 8 per byte - */ - signbits = (unsigned char *) calloc(1, (nel+7)/8); - if (signbits == (unsigned char *) NULL) { - ffpmsg("encode64: insufficient memory"); - return(DATA_COMPRESSION_ERR); - } - nsign = 0; - bits_to_go = 8; -/* signbits[0] = 0; */ - for (i=0; i 0) { - /* - * positive element, put zero at end of buffer - */ - signbits[nsign] <<= 1; - bits_to_go -= 1; - } else if (a[i] < 0) { - /* - * negative element, shift in a one - */ - signbits[nsign] <<= 1; - signbits[nsign] |= 1; - bits_to_go -= 1; - /* - * replace a by absolute value - */ - a[i] = -a[i]; - } - if (bits_to_go == 0) { - /* - * filled up this byte, go to the next one - */ - bits_to_go = 8; - nsign += 1; -/* signbits[nsign] = 0; */ - } - } - if (bits_to_go != 8) { - /* - * some bits in last element - * move bits in last byte to bottom and increment nsign - */ - signbits[nsign] <<= bits_to_go; - nsign += 1; - } - /* - * calculate number of bit planes for 3 quadrants - * - * quadrant 0=bottom left, 1=bottom right or top left, 2=top right, - */ - for (q=0; q<3; q++) { - vmax[q] = 0; - } - /* - * get maximum absolute value in each quadrant - */ - nx2 = (nx+1)/2; - ny2 = (ny+1)/2; - j=0; /* column counter */ - k=0; /* row counter */ - for (i=0; i=ny2) + (k>=nx2); - if (vmax[q] < a[i]) vmax[q] = a[i]; - if (++j >= ny) { - j = 0; - k += 1; - } - } - /* - * now calculate number of bits for each quadrant - */ - - /* this is a more efficient way to do this, */ - - - for (q = 0; q < 3; q++) { - for (nbitplanes[q] = 0; vmax[q]>0; vmax[q] = vmax[q]>>1, nbitplanes[q]++) ; - } - - -/* - for (q = 0; q < 3; q++) { - nbitplanes[q] = log((float) (vmax[q]+1))/log(2.0)+0.5; - if ( (vmax[q]+1) > (((LONGLONG) 1)< 0) { - - if ( 0 == qwrite(outfile, (char *) signbits, nsign)) { - free(signbits); - *nlength = noutchar; - ffpmsg("encode: output buffer too small"); - return(DATA_COMPRESSION_ERR); - } - } - - free(signbits); - *nlength = noutchar; - - if (noutchar >= noutmax) { - ffpmsg("encode64: output buffer too small"); - return(DATA_COMPRESSION_ERR); - } - - return(stat); -} -/* ######################################################################### */ -/* ######################################################################### */ -/* Copyright (c) 1993 Association of Universities for Research - * in Astronomy. All rights reserved. Produced under National - * Aeronautics and Space Administration Contract No. NAS5-26555. - */ -/* qwrite.c Write binary data - * - * Programmer: R. White Date: 11 March 1991 - */ - -/* ######################################################################### */ -static void -writeint(char *outfile, int a) -{ -int i; -unsigned char b[4]; - - /* Write integer A one byte at a time to outfile. - * - * This is portable from Vax to Sun since it eliminates the - * need for byte-swapping. - */ - for (i=3; i>=0; i--) { - b[i] = a & 0x000000ff; - a >>= 8; - } - for (i=0; i<4; i++) qwrite(outfile, (char *) &b[i],1); -} - -/* ######################################################################### */ -static void -writelonglong(char *outfile, LONGLONG a) -{ -int i; -unsigned char b[8]; - - /* Write integer A one byte at a time to outfile. - * - * This is portable from Vax to Sun since it eliminates the - * need for byte-swapping. - */ - for (i=7; i>=0; i--) { - b[i] = (unsigned char) (a & 0x000000ff); - a >>= 8; - } - for (i=0; i<8; i++) qwrite(outfile, (char *) &b[i],1); -} -/* ######################################################################### */ -static int -qwrite(char *file, char buffer[], int n){ - /* - * write n bytes from buffer into file - * returns number of bytes read (=n) if successful, <=0 if not - */ - - if (noutchar + n > noutmax) return(0); /* buffer overflow */ - - memcpy(&file[noutchar], buffer, n); - noutchar += n; - - return(n); -} -/* ######################################################################### */ -/* ######################################################################### */ -/* Copyright (c) 1993 Association of Universities for Research - * in Astronomy. All rights reserved. Produced under National - * Aeronautics and Space Administration Contract No. NAS5-26555. - */ -/* doencode.c Encode 2-D array and write stream of characters on outfile - * - * This version assumes that A is positive. - * - * Programmer: R. White Date: 7 May 1991 - */ - -/* ######################################################################### */ -static int -doencode(char *outfile, int a[], int nx, int ny, unsigned char nbitplanes[3]) -{ -/* char *outfile; output data stream -int a[]; Array of values to encode -int nx,ny; Array dimensions [nx][ny] -unsigned char nbitplanes[3]; Number of bit planes in quadrants -*/ - -int nx2, ny2, stat; - - nx2 = (nx+1)/2; - ny2 = (ny+1)/2; - /* - * Initialize bit output - */ - start_outputing_bits(); - /* - * write out the bit planes for each quadrant - */ - stat = qtree_encode(outfile, &a[0], ny, nx2, ny2, nbitplanes[0]); - - if (!stat) - stat = qtree_encode(outfile, &a[ny2], ny, nx2, ny/2, nbitplanes[1]); - - if (!stat) - stat = qtree_encode(outfile, &a[ny*nx2], ny, nx/2, ny2, nbitplanes[1]); - - if (!stat) - stat = qtree_encode(outfile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]); - /* - * Add zero as an EOF symbol - */ - output_nybble(outfile, 0); - done_outputing_bits(outfile); - - return(stat); -} -/* ######################################################################### */ -static int -doencode64(char *outfile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3]) -{ -/* char *outfile; output data stream -LONGLONG a[]; Array of values to encode -int nx,ny; Array dimensions [nx][ny] -unsigned char nbitplanes[3]; Number of bit planes in quadrants -*/ - -int nx2, ny2, stat; - - nx2 = (nx+1)/2; - ny2 = (ny+1)/2; - /* - * Initialize bit output - */ - start_outputing_bits(); - /* - * write out the bit planes for each quadrant - */ - stat = qtree_encode64(outfile, &a[0], ny, nx2, ny2, nbitplanes[0]); - - if (!stat) - stat = qtree_encode64(outfile, &a[ny2], ny, nx2, ny/2, nbitplanes[1]); - - if (!stat) - stat = qtree_encode64(outfile, &a[ny*nx2], ny, nx/2, ny2, nbitplanes[1]); - - if (!stat) - stat = qtree_encode64(outfile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]); - /* - * Add zero as an EOF symbol - */ - output_nybble(outfile, 0); - done_outputing_bits(outfile); - - return(stat); -} -/* ######################################################################### */ -/* ######################################################################### */ -/* Copyright (c) 1993 Association of Universities for Research - * in Astronomy. All rights reserved. Produced under National - * Aeronautics and Space Administration Contract No. NAS5-26555. - */ -/* BIT OUTPUT ROUTINES */ - - -static LONGLONG bitcount; - -/* THE BIT BUFFER */ - -static int buffer2; /* Bits buffered for output */ -static int bits_to_go2; /* Number of bits free in buffer */ - - -/* ######################################################################### */ -/* INITIALIZE FOR BIT OUTPUT */ - -static void -start_outputing_bits(void) -{ - buffer2 = 0; /* Buffer is empty to start */ - bits_to_go2 = 8; /* with */ - bitcount = 0; -} - -/* ######################################################################### */ -/* OUTPUT N BITS (N must be <= 8) */ - -static void -output_nbits(char *outfile, int bits, int n) -{ - /* AND mask for the right-most n bits */ - static int mask[9] = {0, 1, 3, 7, 15, 31, 63, 127, 255}; - /* - * insert bits at end of buffer - */ - buffer2 <<= n; -/* buffer2 |= ( bits & ((1<>(-bits_to_go2)) & 0xff); - - if (noutchar < noutmax) noutchar++; - - bits_to_go2 += 8; - } - bitcount += n; -} -/* ######################################################################### */ -/* OUTPUT a 4 bit nybble */ -static void -output_nybble(char *outfile, int bits) -{ - /* - * insert 4 bits at end of buffer - */ - buffer2 = (buffer2<<4) | ( bits & 15 ); - bits_to_go2 -= 4; - if (bits_to_go2 <= 0) { - /* - * buffer2 full, put out top 8 bits - */ - - outfile[noutchar] = ((buffer2>>(-bits_to_go2)) & 0xff); - - if (noutchar < noutmax) noutchar++; - - bits_to_go2 += 8; - } - bitcount += 4; -} -/* ############################################################################ */ -/* OUTPUT array of 4 BITS */ - -static void output_nnybble(char *outfile, int n, unsigned char array[]) -{ - /* pack the 4 lower bits in each element of the array into the outfile array */ - -int ii, jj, kk = 0, shift; - - if (n == 1) { - output_nybble(outfile, (int) array[0]); - return; - } -/* forcing byte alignment doesn;t help, and even makes it go slightly slower -if (bits_to_go2 != 8) - output_nbits(outfile, kk, bits_to_go2); -*/ - if (bits_to_go2 <= 4) - { - /* just room for 1 nybble; write it out separately */ - output_nybble(outfile, array[0]); - kk++; /* index to next array element */ - - if (n == 2) /* only 1 more nybble to write out */ - { - output_nybble(outfile, (int) array[1]); - return; - } - } - - - /* bits_to_go2 is now in the range 5 - 8 */ - shift = 8 - bits_to_go2; - - /* now write out pairs of nybbles; this does not affect value of bits_to_go2 */ - jj = (n - kk) / 2; - - if (bits_to_go2 == 8) { - /* special case if nybbles are aligned on byte boundary */ - /* this actually seems to make very little differnece in speed */ - buffer2 = 0; - for (ii = 0; ii < jj; ii++) - { - outfile[noutchar] = ((array[kk] & 15)<<4) | (array[kk+1] & 15); - kk += 2; - noutchar++; - } - } else { - for (ii = 0; ii < jj; ii++) - { - buffer2 = (buffer2<<8) | ((array[kk] & 15)<<4) | (array[kk+1] & 15); - kk += 2; - - /* - buffer2 full, put out top 8 bits - */ - - outfile[noutchar] = ((buffer2>>shift) & 0xff); - noutchar++; - } - } - - bitcount += (8 * (ii - 1)); - - /* write out last odd nybble, if present */ - if (kk != n) output_nybble(outfile, (int) array[n - 1]); - - return; -} - - -/* ######################################################################### */ -/* FLUSH OUT THE LAST BITS */ - -static void -done_outputing_bits(char *outfile) -{ - if(bits_to_go2 < 8) { -/* putc(buffer2<nqy) ? nqx : nqy; - log2n = (int) (log((float) nqmax)/log(2.0)+0.5); - if (nqmax > (1<= 0; bit--) { - /* - * initial bit buffer - */ - b = 0; - bitbuffer = 0; - bits_to_go3 = 0; - /* - * on first pass copy A to scratch array - */ - qtree_onebit(a,n,nqx,nqy,scratch,bit); - nx = (nqx+1)>>1; - ny = (nqy+1)>>1; - /* - * copy non-zero values to output buffer, which will be written - * in reverse order - */ - if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) { - /* - * quadtree is expanding data, - * change warning code and just fill buffer with bit-map - */ - write_bdirect(outfile,a,n,nqx,nqy,scratch,bit); - goto bitplane_done; - } - /* - * do log2n reductions - */ - for (k = 1; k>1; - ny = (ny+1)>>1; - if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) { - write_bdirect(outfile,a,n,nqx,nqy,scratch,bit); - goto bitplane_done; - } - } - /* - * OK, we've got the code in buffer - * Write quadtree warning code, then write buffer in reverse order - */ - output_nybble(outfile,0xF); - if (b==0) { - if (bits_to_go3>0) { - /* - * put out the last few bits - */ - output_nbits(outfile, bitbuffer & ((1<0) { - /* - * put out the last few bits - */ - output_nbits(outfile, bitbuffer & ((1<=0; i--) { - output_nbits(outfile,buffer[i],8); - } - } - bitplane_done: ; - } - free(buffer); - free(scratch); - return(0); -} -/* ######################################################################### */ -static int -qtree_encode64(char *outfile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes) -{ - -/* -LONGLONG a[]; -int n; physical dimension of row in a -int nqx; length of row -int nqy; length of column (<=n) -int nbitplanes; number of bit planes to output -*/ - -int log2n, i, k, bit, b, nqmax, nqx2, nqy2, nx, ny; -int bmax; /* this potentially needs to be made a 64-bit int to support large arrays */ -unsigned char *scratch, *buffer; - - /* - * log2n is log2 of max(nqx,nqy) rounded up to next power of 2 - */ - nqmax = (nqx>nqy) ? nqx : nqy; - log2n = (int) (log((float) nqmax)/log(2.0)+0.5); - if (nqmax > (1<= 0; bit--) { - /* - * initial bit buffer - */ - b = 0; - bitbuffer = 0; - bits_to_go3 = 0; - /* - * on first pass copy A to scratch array - */ - qtree_onebit64(a,n,nqx,nqy,scratch,bit); - nx = (nqx+1)>>1; - ny = (nqy+1)>>1; - /* - * copy non-zero values to output buffer, which will be written - * in reverse order - */ - if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) { - /* - * quadtree is expanding data, - * change warning code and just fill buffer with bit-map - */ - write_bdirect64(outfile,a,n,nqx,nqy,scratch,bit); - goto bitplane_done; - } - /* - * do log2n reductions - */ - for (k = 1; k>1; - ny = (ny+1)>>1; - if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) { - write_bdirect64(outfile,a,n,nqx,nqy,scratch,bit); - goto bitplane_done; - } - } - /* - * OK, we've got the code in buffer - * Write quadtree warning code, then write buffer in reverse order - */ - output_nybble(outfile,0xF); - if (b==0) { - if (bits_to_go3>0) { - /* - * put out the last few bits - */ - output_nbits(outfile, bitbuffer & ((1<0) { - /* - * put out the last few bits - */ - output_nbits(outfile, bitbuffer & ((1<=0; i--) { - output_nbits(outfile,buffer[i],8); - } - } - bitplane_done: ; - } - free(buffer); - free(scratch); - return(0); -} - -/* ######################################################################### */ -/* - * copy non-zero codes from array to buffer - */ -static int -bufcopy(unsigned char a[], int n, unsigned char buffer[], int *b, int bmax) -{ -int i; - - for (i = 0; i < n; i++) { - if (a[i] != 0) { - /* - * add Huffman code for a[i] to buffer - */ - bitbuffer |= code[a[i]] << bits_to_go3; - bits_to_go3 += ncode[a[i]]; - if (bits_to_go3 >= 8) { - buffer[*b] = bitbuffer & 0xFF; - *b += 1; - /* - * return warning code if we fill buffer - */ - if (*b >= bmax) return(1); - bitbuffer >>= 8; - bits_to_go3 -= 8; - } - } - } - return(0); -} - -/* ######################################################################### */ -/* - * Do first quadtree reduction step on bit BIT of array A. - * Results put into B. - * - */ -static void -qtree_onebit(int a[], int n, int nx, int ny, unsigned char b[], int bit) -{ -int i, j, k; -int b0, b1, b2, b3; -int s10, s00; - - /* - * use selected bit to get amount to shift - */ - b0 = 1<> bit; - - k += 1; - s00 += 2; - s10 += 2; - } - if (j < ny) { - /* - * row size is odd, do last element in row - * s00+1,s10+1 are off edge - */ - b[k] = ( ((a[s10 ]<<1) & b1) - | ((a[s00 ]<<3) & b3) ) >> bit; - k += 1; - } - } - if (i < nx) { - /* - * column size is odd, do last row - * s10,s10+1 are off edge - */ - s00 = n*i; - for (j = 0; j> bit; - k += 1; - s00 += 2; - } - if (j < ny) { - /* - * both row and column size are odd, do corner element - * s00+1, s10, s10+1 are off edge - */ - b[k] = ( ((a[s00 ]<<3) & b3) ) >> bit; - k += 1; - } - } -} -/* ######################################################################### */ -/* - * Do first quadtree reduction step on bit BIT of array A. - * Results put into B. - * - */ -static void -qtree_onebit64(LONGLONG a[], int n, int nx, int ny, unsigned char b[], int bit) -{ -int i, j, k; -LONGLONG b0, b1, b2, b3; -int s10, s00; - - /* - * use selected bit to get amount to shift - */ - b0 = ((LONGLONG) 1)<> bit); - k += 1; - s00 += 2; - s10 += 2; - } - if (j < ny) { - /* - * row size is odd, do last element in row - * s00+1,s10+1 are off edge - */ - b[k] = (unsigned char) (( ((a[s10 ]<<1) & b1) - | ((a[s00 ]<<3) & b3) ) >> bit); - k += 1; - } - } - if (i < nx) { - /* - * column size is odd, do last row - * s10,s10+1 are off edge - */ - s00 = n*i; - for (j = 0; j> bit); - k += 1; - s00 += 2; - } - if (j < ny) { - /* - * both row and column size are odd, do corner element - * s00+1, s10, s10+1 are off edge - */ - b[k] = (unsigned char) (( ((a[s00 ]<<3) & b3) ) >> bit); - k += 1; - } - } -} - -/* ######################################################################### */ -/* - * do one quadtree reduction step on array a - * results put into b (which may be the same as a) - */ -static void -qtree_reduce(unsigned char a[], int n, int nx, int ny, unsigned char b[]) -{ -int i, j, k; -int s10, s00; - - k = 0; /* k is index of b[i/2,j/2] */ - for (i = 0; i -#include -#include -#include -#include "fitsio2.h" - -/* WDP added test to see if min and max are already defined */ -#ifndef min -#define min(a,b) (((a)<(b))?(a):(b)) -#endif -#ifndef max -#define max(a,b) (((a)>(b))?(a):(b)) -#endif - -static long nextchar; - -static int decode(unsigned char *infile, int *a, int *nx, int *ny, int *scale); -static int decode64(unsigned char *infile, LONGLONG *a, int *nx, int *ny, int *scale); -static int hinv(int a[], int nx, int ny, int smooth ,int scale); -static int hinv64(LONGLONG a[], int nx, int ny, int smooth ,int scale); -static void undigitize(int a[], int nx, int ny, int scale); -static void undigitize64(LONGLONG a[], int nx, int ny, int scale); -static void unshuffle(int a[], int n, int n2, int tmp[]); -static void unshuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[]); -static void hsmooth(int a[], int nxtop, int nytop, int ny, int scale); -static void hsmooth64(LONGLONG a[], int nxtop, int nytop, int ny, int scale); -static void qread(unsigned char *infile,char *a, int n); -static int readint(unsigned char *infile); -static LONGLONG readlonglong(unsigned char *infile); -static int dodecode(unsigned char *infile, int a[], int nx, int ny, unsigned char nbitplanes[3]); -static int dodecode64(unsigned char *infile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3]); -static int qtree_decode(unsigned char *infile, int a[], int n, int nqx, int nqy, int nbitplanes); -static int qtree_decode64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes); -static void start_inputing_bits(void); -static int input_bit(unsigned char *infile); -static int input_nbits(unsigned char *infile, int n); -/* make input_nybble a separate routine, for added effiency */ -/* #define input_nybble(infile) input_nbits(infile,4) */ -static int input_nybble(unsigned char *infile); -static int input_nnybble(unsigned char *infile, int n, unsigned char *array); - -static void qtree_expand(unsigned char *infile, unsigned char a[], int nx, int ny, unsigned char b[]); -static void qtree_bitins(unsigned char a[], int nx, int ny, int b[], int n, int bit); -static void qtree_bitins64(unsigned char a[], int nx, int ny, LONGLONG b[], int n, int bit); -static void qtree_copy(unsigned char a[], int nx, int ny, unsigned char b[], int n); -static void read_bdirect(unsigned char *infile, int a[], int n, int nqx, int nqy, unsigned char scratch[], int bit); -static void read_bdirect64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, unsigned char scratch[], int bit); -static int input_huffman(unsigned char *infile); - -/* ---------------------------------------------------------------------- */ -int fits_hdecompress(unsigned char *input, int smooth, int *a, int *ny, int *nx, - int *scale, int *status) -{ - /* - decompress the input byte stream using the H-compress algorithm - - input - input array of compressed bytes - a - pre-allocated array to hold the output uncompressed image - nx - returned X axis size - ny - returned Y axis size - - NOTE: the nx and ny dimensions as defined within this code are reversed from - the usual FITS notation. ny is the fastest varying dimension, which is - usually considered the X axis in the FITS image display - - */ -int stat; - - if (*status > 0) return(*status); - - /* decode the input array */ - - FFLOCK; /* decode uses the nextchar global variable */ - stat = decode(input, a, nx, ny, scale); - FFUNLOCK; - - *status = stat; - if (stat) return(*status); - - /* - * Un-Digitize - */ - undigitize(a, *nx, *ny, *scale); - - /* - * Inverse H-transform - */ - stat = hinv(a, *nx, *ny, smooth, *scale); - *status = stat; - - return(*status); -} -/* ---------------------------------------------------------------------- */ -int fits_hdecompress64(unsigned char *input, int smooth, LONGLONG *a, int *ny, int *nx, - int *scale, int *status) -{ - /* - decompress the input byte stream using the H-compress algorithm - - input - input array of compressed bytes - a - pre-allocated array to hold the output uncompressed image - nx - returned X axis size - ny - returned Y axis size - - NOTE: the nx and ny dimensions as defined within this code are reversed from - the usual FITS notation. ny is the fastest varying dimension, which is - usually considered the X axis in the FITS image display - - */ - int stat, *iarray, ii, nval; - - if (*status > 0) return(*status); - - /* decode the input array */ - - FFLOCK; /* decode uses the nextchar global variable */ - stat = decode64(input, a, nx, ny, scale); - FFUNLOCK; - - *status = stat; - if (stat) return(*status); - - /* - * Un-Digitize - */ - undigitize64(a, *nx, *ny, *scale); - - /* - * Inverse H-transform - */ - stat = hinv64(a, *nx, *ny, smooth, *scale); - - *status = stat; - - /* pack the I*8 values back into an I*4 array */ - iarray = (int *) a; - nval = (*nx) * (*ny); - - for (ii = 0; ii < nval; ii++) - iarray[ii] = (int) a[ii]; - - return(*status); -} - -/* ############################################################################ */ -/* ############################################################################ */ - -/* Copyright (c) 1993 Association of Universities for Research - * in Astronomy. All rights reserved. Produced under National - * Aeronautics and Space Administration Contract No. NAS5-26555. - */ -/* hinv.c Inverse H-transform of NX x NY integer image - * - * Programmer: R. White Date: 23 July 1993 - */ - -/* ############################################################################ */ -static int -hinv(int a[], int nx, int ny, int smooth ,int scale) -/* -int smooth; 0 for no smoothing, else smooth during inversion -int scale; used if smoothing is specified -*/ -{ -int nmax, log2n, i, j, k; -int nxtop,nytop,nxf,nyf,c; -int oddx,oddy; -int shift, bit0, bit1, bit2, mask0, mask1, mask2, - prnd0, prnd1, prnd2, nrnd0, nrnd1, nrnd2, lowbit0, lowbit1; -int h0, hx, hy, hc; -int s10, s00; -int *tmp; - - /* - * log2n is log2 of max(nx,ny) rounded up to next power of 2 - */ - nmax = (nx>ny) ? nx : ny; - log2n = (int) (log((float) nmax)/log(2.0)+0.5); - if ( nmax > (1<> 1; - prnd1 = bit1 >> 1; - prnd2 = bit2 >> 1; - nrnd0 = prnd0 - 1; - nrnd1 = prnd1 - 1; - nrnd2 = prnd2 - 1; - /* - * round h0 to multiple of bit2 - */ - a[0] = (a[0] + ((a[0] >= 0) ? prnd2 : nrnd2)) & mask2; - /* - * do log2n expansions - * - * We're indexing a as a 2-D array with dimensions (nx,ny). - */ - nxtop = 1; - nytop = 1; - nxf = nx; - nyf = ny; - c = 1<=0; k--) { - /* - * this somewhat cryptic code generates the sequence - * ntop[k-1] = (ntop[k]+1)/2, where ntop[log2n] = n - */ - c = c>>1; - nxtop = nxtop<<1; - nytop = nytop<<1; - if (nxf <= c) { nxtop -= 1; } else { nxf -= c; } - if (nyf <= c) { nytop -= 1; } else { nyf -= c; } - /* - * double shift and fix nrnd0 (because prnd0=0) on last pass - */ - if (k == 0) { - nrnd0 = 0; - shift = 2; - } - /* - * unshuffle in each dimension to interleave coefficients - */ - for (i = 0; i= 0) ? prnd1 : nrnd1)) & mask1; - hy = (hy + ((hy >= 0) ? prnd1 : nrnd1)) & mask1; - hc = (hc + ((hc >= 0) ? prnd0 : nrnd0)) & mask0; - /* - * propagate bit0 of hc to hx,hy - */ - lowbit0 = hc & bit0; - hx = (hx >= 0) ? (hx - lowbit0) : (hx + lowbit0); - hy = (hy >= 0) ? (hy - lowbit0) : (hy + lowbit0); - /* - * Propagate bits 0 and 1 of hc,hx,hy to h0. - * This could be simplified if we assume h0>0, but then - * the inversion would not be lossless for images with - * negative pixels. - */ - lowbit1 = (hc ^ hx ^ hy) & bit1; - h0 = (h0 >= 0) - ? (h0 + lowbit0 - lowbit1) - : (h0 + ((lowbit0 == 0) ? lowbit1 : (lowbit0-lowbit1))); - /* - * Divide sums by 2 (4 last time) - */ - a[s10+1] = (h0 + hx + hy + hc) >> shift; - a[s10 ] = (h0 + hx - hy - hc) >> shift; - a[s00+1] = (h0 - hx + hy - hc) >> shift; - a[s00 ] = (h0 - hx - hy + hc) >> shift; - s00 += 2; - s10 += 2; - } - if (oddy) { - /* - * do last element in row if row length is odd - * s00+1, s10+1 are off edge - */ - h0 = a[s00 ]; - hx = a[s10 ]; - hx = ((hx >= 0) ? (hx+prnd1) : (hx+nrnd1)) & mask1; - lowbit1 = hx & bit1; - h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1); - a[s10 ] = (h0 + hx) >> shift; - a[s00 ] = (h0 - hx) >> shift; - } - } - if (oddx) { - /* - * do last row if column length is odd - * s10, s10+1 are off edge - */ - s00 = ny*i; - for (j = 0; j= 0) ? (hy+prnd1) : (hy+nrnd1)) & mask1; - lowbit1 = hy & bit1; - h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1); - a[s00+1] = (h0 + hy) >> shift; - a[s00 ] = (h0 - hy) >> shift; - s00 += 2; - } - if (oddy) { - /* - * do corner element if both row and column lengths are odd - * s00+1, s10, s10+1 are off edge - */ - h0 = a[s00 ]; - a[s00 ] = h0 >> shift; - } - } - /* - * divide all the masks and rounding values by 2 - */ - bit2 = bit1; - bit1 = bit0; - bit0 = bit0 >> 1; - mask1 = mask0; - mask0 = mask0 >> 1; - prnd1 = prnd0; - prnd0 = prnd0 >> 1; - nrnd1 = nrnd0; - nrnd0 = prnd0 - 1; - } - free(tmp); - return(0); -} -/* ############################################################################ */ -static int -hinv64(LONGLONG a[], int nx, int ny, int smooth ,int scale) -/* -int smooth; 0 for no smoothing, else smooth during inversion -int scale; used if smoothing is specified -*/ -{ -int nmax, log2n, i, j, k; -int nxtop,nytop,nxf,nyf,c; -int oddx,oddy; -int shift; -LONGLONG mask0, mask1, mask2, prnd0, prnd1, prnd2, bit0, bit1, bit2; -LONGLONG nrnd0, nrnd1, nrnd2, lowbit0, lowbit1; -LONGLONG h0, hx, hy, hc; -int s10, s00; -LONGLONG *tmp; - - /* - * log2n is log2 of max(nx,ny) rounded up to next power of 2 - */ - nmax = (nx>ny) ? nx : ny; - log2n = (int) (log((float) nmax)/log(2.0)+0.5); - if ( nmax > (1<> 1; - prnd1 = bit1 >> 1; - prnd2 = bit2 >> 1; - nrnd0 = prnd0 - 1; - nrnd1 = prnd1 - 1; - nrnd2 = prnd2 - 1; - /* - * round h0 to multiple of bit2 - */ - a[0] = (a[0] + ((a[0] >= 0) ? prnd2 : nrnd2)) & mask2; - /* - * do log2n expansions - * - * We're indexing a as a 2-D array with dimensions (nx,ny). - */ - nxtop = 1; - nytop = 1; - nxf = nx; - nyf = ny; - c = 1<=0; k--) { - /* - * this somewhat cryptic code generates the sequence - * ntop[k-1] = (ntop[k]+1)/2, where ntop[log2n] = n - */ - c = c>>1; - nxtop = nxtop<<1; - nytop = nytop<<1; - if (nxf <= c) { nxtop -= 1; } else { nxf -= c; } - if (nyf <= c) { nytop -= 1; } else { nyf -= c; } - /* - * double shift and fix nrnd0 (because prnd0=0) on last pass - */ - if (k == 0) { - nrnd0 = 0; - shift = 2; - } - /* - * unshuffle in each dimension to interleave coefficients - */ - for (i = 0; i= 0) ? prnd1 : nrnd1)) & mask1; - hy = (hy + ((hy >= 0) ? prnd1 : nrnd1)) & mask1; - hc = (hc + ((hc >= 0) ? prnd0 : nrnd0)) & mask0; - /* - * propagate bit0 of hc to hx,hy - */ - lowbit0 = hc & bit0; - hx = (hx >= 0) ? (hx - lowbit0) : (hx + lowbit0); - hy = (hy >= 0) ? (hy - lowbit0) : (hy + lowbit0); - /* - * Propagate bits 0 and 1 of hc,hx,hy to h0. - * This could be simplified if we assume h0>0, but then - * the inversion would not be lossless for images with - * negative pixels. - */ - lowbit1 = (hc ^ hx ^ hy) & bit1; - h0 = (h0 >= 0) - ? (h0 + lowbit0 - lowbit1) - : (h0 + ((lowbit0 == 0) ? lowbit1 : (lowbit0-lowbit1))); - /* - * Divide sums by 2 (4 last time) - */ - a[s10+1] = (h0 + hx + hy + hc) >> shift; - a[s10 ] = (h0 + hx - hy - hc) >> shift; - a[s00+1] = (h0 - hx + hy - hc) >> shift; - a[s00 ] = (h0 - hx - hy + hc) >> shift; - s00 += 2; - s10 += 2; - } - if (oddy) { - /* - * do last element in row if row length is odd - * s00+1, s10+1 are off edge - */ - h0 = a[s00 ]; - hx = a[s10 ]; - hx = ((hx >= 0) ? (hx+prnd1) : (hx+nrnd1)) & mask1; - lowbit1 = hx & bit1; - h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1); - a[s10 ] = (h0 + hx) >> shift; - a[s00 ] = (h0 - hx) >> shift; - } - } - if (oddx) { - /* - * do last row if column length is odd - * s10, s10+1 are off edge - */ - s00 = ny*i; - for (j = 0; j= 0) ? (hy+prnd1) : (hy+nrnd1)) & mask1; - lowbit1 = hy & bit1; - h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1); - a[s00+1] = (h0 + hy) >> shift; - a[s00 ] = (h0 - hy) >> shift; - s00 += 2; - } - if (oddy) { - /* - * do corner element if both row and column lengths are odd - * s00+1, s10, s10+1 are off edge - */ - h0 = a[s00 ]; - a[s00 ] = h0 >> shift; - } - } - /* - * divide all the masks and rounding values by 2 - */ - bit2 = bit1; - bit1 = bit0; - bit0 = bit0 >> 1; - mask1 = mask0; - mask0 = mask0 >> 1; - prnd1 = prnd0; - prnd0 = prnd0 >> 1; - nrnd1 = nrnd0; - nrnd0 = prnd0 - 1; - } - free(tmp); - return(0); -} - -/* ############################################################################ */ -static void -unshuffle(int a[], int n, int n2, int tmp[]) -/* -int a[]; array to shuffle -int n; number of elements to shuffle -int n2; second dimension -int tmp[]; scratch storage -*/ -{ -int i; -int nhalf; -int *p1, *p2, *pt; - - /* - * copy 2nd half of array to tmp - */ - nhalf = (n+1)>>1; - pt = tmp; - p1 = &a[n2*nhalf]; /* pointer to a[i] */ - for (i=nhalf; i= 0; i--) { - *p1 = *p2; - p2 -= n2; - p1 -= (n2+n2); - } - /* - * now distribute 2nd half of array (in tmp) to odd elements - */ - pt = tmp; - p1 = &a[n2]; /* pointer to a[i] */ - for (i=1; i>1; - pt = tmp; - p1 = &a[n2*nhalf]; /* pointer to a[i] */ - for (i=nhalf; i= 0; i--) { - *p1 = *p2; - p2 -= n2; - p1 -= (n2+n2); - } - /* - * now distribute 2nd half of array (in tmp) to odd elements - */ - pt = tmp; - p1 = &a[n2]; /* pointer to a[i] */ - for (i=1; i> 1); - if (smax <= 0) return; - ny2 = ny << 1; - /* - * We're indexing a as a 2-D array with dimensions (nxtop,ny) of which - * only (nxtop,nytop) are used. The coefficients on the edge of the - * array are not adjusted (which is why the loops below start at 2 - * instead of 0 and end at nxtop-2 instead of nxtop.) - */ - /* - * Adjust x difference hx - */ - for (i = 2; i=0, dmin<=0. - */ - if (dmin < dmax) { - diff = max( min(diff, dmax), dmin); - /* - * Compute change in slope limited to range +/- smax. - * Careful with rounding negative numbers when using - * shift for divide by 8. - */ - s = diff-(a[s10]<<3); - s = (s>=0) ? (s>>3) : ((s+7)>>3) ; - s = max( min(s, smax), -smax); - a[s10] = a[s10]+s; - } - s00 += 2; - s10 += 2; - } - } - /* - * Adjust y difference hy - */ - for (i = 0; i=0) ? (s>>3) : ((s+7)>>3) ; - s = max( min(s, smax), -smax); - a[s00+1] = a[s00+1]+s; - } - s00 += 2; - s10 += 2; - } - } - /* - * Adjust curvature difference hc - */ - for (i = 2; i=0, dmin<=0. - */ - if (dmin < dmax) { - diff = max( min(diff, dmax), dmin); - /* - * Compute change in slope limited to range +/- smax. - * Careful with rounding negative numbers when using - * shift for divide by 64. - */ - s = diff-(a[s10+1]<<6); - s = (s>=0) ? (s>>6) : ((s+63)>>6) ; - s = max( min(s, smax), -smax); - a[s10+1] = a[s10+1]+s; - } - s00 += 2; - s10 += 2; - } - } -} -/* ############################################################################ */ -static void -hsmooth64(LONGLONG a[], int nxtop, int nytop, int ny, int scale) -/* -LONGLONG a[]; array of H-transform coefficients -int nxtop,nytop; size of coefficient block to use -int ny; actual 1st dimension of array -int scale; truncation scale factor that was used -*/ -{ -int i, j; -int ny2, s10, s00; -LONGLONG hm, h0, hp, hmm, hpm, hmp, hpp, hx2, hy2, diff, dmax, dmin, s, smax, m1, m2; - - /* - * Maximum change in coefficients is determined by scale factor. - * Since we rounded during division (see digitize.c), the biggest - * permitted change is scale/2. - */ - smax = (scale >> 1); - if (smax <= 0) return; - ny2 = ny << 1; - /* - * We're indexing a as a 2-D array with dimensions (nxtop,ny) of which - * only (nxtop,nytop) are used. The coefficients on the edge of the - * array are not adjusted (which is why the loops below start at 2 - * instead of 0 and end at nxtop-2 instead of nxtop.) - */ - /* - * Adjust x difference hx - */ - for (i = 2; i=0, dmin<=0. - */ - if (dmin < dmax) { - diff = max( min(diff, dmax), dmin); - /* - * Compute change in slope limited to range +/- smax. - * Careful with rounding negative numbers when using - * shift for divide by 8. - */ - s = diff-(a[s10]<<3); - s = (s>=0) ? (s>>3) : ((s+7)>>3) ; - s = max( min(s, smax), -smax); - a[s10] = a[s10]+s; - } - s00 += 2; - s10 += 2; - } - } - /* - * Adjust y difference hy - */ - for (i = 0; i=0) ? (s>>3) : ((s+7)>>3) ; - s = max( min(s, smax), -smax); - a[s00+1] = a[s00+1]+s; - } - s00 += 2; - s10 += 2; - } - } - /* - * Adjust curvature difference hc - */ - for (i = 2; i=0, dmin<=0. - */ - if (dmin < dmax) { - diff = max( min(diff, dmax), dmin); - /* - * Compute change in slope limited to range +/- smax. - * Careful with rounding negative numbers when using - * shift for divide by 64. - */ - s = diff-(a[s10+1]<<6); - s = (s>=0) ? (s>>6) : ((s+63)>>6) ; - s = max( min(s, smax), -smax); - a[s10+1] = a[s10+1]+s; - } - s00 += 2; - s10 += 2; - } - } -} - - -/* ############################################################################ */ -/* ############################################################################ */ -/* Copyright (c) 1993 Association of Universities for Research - * in Astronomy. All rights reserved. Produced under National - * Aeronautics and Space Administration Contract No. NAS5-26555. - */ -/* undigitize.c undigitize H-transform - * - * Programmer: R. White Date: 9 May 1991 - */ - -/* ############################################################################ */ -static void -undigitize(int a[], int nx, int ny, int scale) -{ -int *p; - - /* - * multiply by scale - */ - if (scale <= 1) return; - for (p=a; p <= &a[nx*ny-1]; p++) *p = (*p)*scale; -} -/* ############################################################################ */ -static void -undigitize64(LONGLONG a[], int nx, int ny, int scale) -{ -LONGLONG *p, scale64; - - /* - * multiply by scale - */ - if (scale <= 1) return; - scale64 = (LONGLONG) scale; /* use a 64-bit int for efficiency in the big loop */ - - for (p=a; p <= &a[nx*ny-1]; p++) *p = (*p)*scale64; -} - -/* ############################################################################ */ -/* ############################################################################ */ -/* Copyright (c) 1993 Association of Universities for Research - * in Astronomy. All rights reserved. Produced under National - * Aeronautics and Space Administration Contract No. NAS5-26555. - */ -/* decode.c read codes from infile and construct array - * - * Programmer: R. White Date: 2 February 1994 - */ - - -static char code_magic[2] = { (char)0xDD, (char)0x99 }; - -/* ############################################################################ */ -static int decode(unsigned char *infile, int *a, int *nx, int *ny, int *scale) -/* -char *infile; input file -int *a; address of output array [nx][ny] -int *nx,*ny; size of output array -int *scale; scale factor for digitization -*/ -{ -LONGLONG sumall; -int stat; -unsigned char nbitplanes[3]; -char tmagic[2]; - - /* initialize the byte read position to the beginning of the array */; - nextchar = 0; - - /* - * File starts either with special 2-byte magic code or with - * FITS keyword "SIMPLE =" - */ - qread(infile, tmagic, sizeof(tmagic)); - /* - * check for correct magic code value - */ - if (memcmp(tmagic,code_magic,sizeof(code_magic)) != 0) { - ffpmsg("bad file format"); - return(DATA_DECOMPRESSION_ERR); - } - *nx =readint(infile); /* x size of image */ - *ny =readint(infile); /* y size of image */ - *scale=readint(infile); /* scale factor for digitization */ - - /* sum of all pixels */ - sumall=readlonglong(infile); - /* # bits in quadrants */ - - qread(infile, (char *) nbitplanes, sizeof(nbitplanes)); - - stat = dodecode(infile, a, *nx, *ny, nbitplanes); - /* - * put sum of all pixels back into pixel 0 - */ - a[0] = (int) sumall; - return(stat); -} -/* ############################################################################ */ -static int decode64(unsigned char *infile, LONGLONG *a, int *nx, int *ny, int *scale) -/* -char *infile; input file -LONGLONG *a; address of output array [nx][ny] -int *nx,*ny; size of output array -int *scale; scale factor for digitization -*/ -{ -int stat; -LONGLONG sumall; -unsigned char nbitplanes[3]; -char tmagic[2]; - - /* initialize the byte read position to the beginning of the array */; - nextchar = 0; - - /* - * File starts either with special 2-byte magic code or with - * FITS keyword "SIMPLE =" - */ - qread(infile, tmagic, sizeof(tmagic)); - /* - * check for correct magic code value - */ - if (memcmp(tmagic,code_magic,sizeof(code_magic)) != 0) { - ffpmsg("bad file format"); - return(DATA_DECOMPRESSION_ERR); - } - *nx =readint(infile); /* x size of image */ - *ny =readint(infile); /* y size of image */ - *scale=readint(infile); /* scale factor for digitization */ - - /* sum of all pixels */ - sumall=readlonglong(infile); - /* # bits in quadrants */ - - qread(infile, (char *) nbitplanes, sizeof(nbitplanes)); - - stat = dodecode64(infile, a, *nx, *ny, nbitplanes); - /* - * put sum of all pixels back into pixel 0 - */ - a[0] = sumall; - - return(stat); -} - - -/* ############################################################################ */ -/* ############################################################################ */ -/* Copyright (c) 1993 Association of Universities for Research - * in Astronomy. All rights reserved. Produced under National - * Aeronautics and Space Administration Contract No. NAS5-26555. - */ -/* dodecode.c Decode stream of characters on infile and return array - * - * This version encodes the different quadrants separately - * - * Programmer: R. White Date: 9 May 1991 - */ - -/* ############################################################################ */ -static int -dodecode(unsigned char *infile, int a[], int nx, int ny, unsigned char nbitplanes[3]) - -/* int a[]; - int nx,ny; Array dimensions are [nx][ny] - unsigned char nbitplanes[3]; Number of bit planes in quadrants -*/ -{ -int i, nel, nx2, ny2, stat; - - nel = nx*ny; - nx2 = (nx+1)/2; - ny2 = (ny+1)/2; - - /* - * initialize a to zero - */ - for (i=0; inqy) ? nqx : nqy; - log2n = (int) (log((float) nqmax)/log(2.0)+0.5); - if (nqmax > (1<= 0; bit--) { - /* - * Was bitplane was quadtree-coded or written directly? - */ - b = input_nybble(infile); - - if(b == 0) { - /* - * bit map was written directly - */ - read_bdirect(infile,a,n,nqx,nqy,scratch,bit); - } else if (b != 0xf) { - ffpmsg("qtree_decode: bad format code"); - return(DATA_DECOMPRESSION_ERR); - } else { - /* - * bitmap was quadtree-coded, do log2n expansions - * - * read first code - */ - scratch[0] = input_huffman(infile); - /* - * now do log2n expansions, reading codes from file as necessary - */ - nx = 1; - ny = 1; - nfx = nqx; - nfy = nqy; - c = 1<>1; - nx = nx<<1; - ny = ny<<1; - if (nfx <= c) { nx -= 1; } else { nfx -= c; } - if (nfy <= c) { ny -= 1; } else { nfy -= c; } - qtree_expand(infile,scratch,nx,ny,scratch); - } - /* - * now copy last set of 4-bit codes to bitplane bit of array a - */ - qtree_bitins(scratch,nqx,nqy,a,n,bit); - } - } - free(scratch); - return(0); -} -/* ############################################################################ */ -static int -qtree_decode64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes) - -/* -char *infile; -LONGLONG a[]; a is 2-D array with dimensions (n,n) -int n; length of full row in a -int nqx; partial length of row to decode -int nqy; partial length of column (<=n) -int nbitplanes; number of bitplanes to decode -*/ -{ -int log2n, k, bit, b, nqmax; -int nx,ny,nfx,nfy,c; -int nqx2, nqy2; -unsigned char *scratch; - - /* - * log2n is log2 of max(nqx,nqy) rounded up to next power of 2 - */ - nqmax = (nqx>nqy) ? nqx : nqy; - log2n = (int) (log((float) nqmax)/log(2.0)+0.5); - if (nqmax > (1<= 0; bit--) { - /* - * Was bitplane was quadtree-coded or written directly? - */ - b = input_nybble(infile); - - if(b == 0) { - /* - * bit map was written directly - */ - read_bdirect64(infile,a,n,nqx,nqy,scratch,bit); - } else if (b != 0xf) { - ffpmsg("qtree_decode64: bad format code"); - return(DATA_DECOMPRESSION_ERR); - } else { - /* - * bitmap was quadtree-coded, do log2n expansions - * - * read first code - */ - scratch[0] = input_huffman(infile); - /* - * now do log2n expansions, reading codes from file as necessary - */ - nx = 1; - ny = 1; - nfx = nqx; - nfy = nqy; - c = 1<>1; - nx = nx<<1; - ny = ny<<1; - if (nfx <= c) { nx -= 1; } else { nfx -= c; } - if (nfy <= c) { ny -= 1; } else { nfy -= c; } - qtree_expand(infile,scratch,nx,ny,scratch); - } - /* - * now copy last set of 4-bit codes to bitplane bit of array a - */ - qtree_bitins64(scratch,nqx,nqy,a,n,bit); - } - } - free(scratch); - return(0); -} - - -/* ############################################################################ */ -/* - * do one quadtree expansion step on array a[(nqx+1)/2,(nqy+1)/2] - * results put into b[nqx,nqy] (which may be the same as a) - */ -static void -qtree_expand(unsigned char *infile, unsigned char a[], int nx, int ny, unsigned char b[]) -{ -int i; - - /* - * first copy a to b, expanding each 4-bit value - */ - qtree_copy(a,nx,ny,b,ny); - /* - * now read new 4-bit values into b for each non-zero element - */ - for (i = nx*ny-1; i >= 0; i--) { - if (b[i]) b[i] = input_huffman(infile); - } -} - -/* ############################################################################ */ -/* - * copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding - * each value to 2x2 pixels - * a,b may be same array - */ -static void -qtree_copy(unsigned char a[], int nx, int ny, unsigned char b[], int n) -/* int n; declared y dimension of b */ -{ -int i, j, k, nx2, ny2; -int s00, s10; - - /* - * first copy 4-bit values to b - * start at end in case a,b are same array - */ - nx2 = (nx+1)/2; - ny2 = (ny+1)/2; - k = ny2*(nx2-1)+ny2-1; /* k is index of a[i,j] */ - for (i = nx2-1; i >= 0; i--) { - s00 = 2*(n*i+ny2-1); /* s00 is index of b[2*i,2*j] */ - for (j = ny2-1; j >= 0; j--) { - b[s00] = a[k]; - k -= 1; - s00 -= 2; - } - } - /* - * now expand each 2x2 block - */ - for (i = 0; i>1) & 1; - b[s00+1] = (b[s00]>>2) & 1; - b[s00 ] = (b[s00]>>3) & 1; -*/ - - s00 += 2; - s10 += 2; - } - - if (j < ny) { - /* - * row size is odd, do last element in row - * s00+1, s10+1 are off edge - */ - /* not worth converting this to use 16 case statements */ - b[s10 ] = (b[s00]>>1) & 1; - b[s00 ] = (b[s00]>>3) & 1; - } - } - if (i < nx) { - /* - * column size is odd, do last row - * s10, s10+1 are off edge - */ - s00 = n*i; - for (j = 0; j>2) & 1; - b[s00 ] = (b[s00]>>3) & 1; - s00 += 2; - } - if (j < ny) { - /* - * both row and column size are odd, do corner element - * s00+1, s10, s10+1 are off edge - */ - /* not worth converting this to use 16 case statements */ - b[s00 ] = (b[s00]>>3) & 1; - } - } -} - -/* ############################################################################ */ -/* - * Copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding - * each value to 2x2 pixels and inserting into bitplane BIT of B. - * A,B may NOT be same array (it wouldn't make sense to be inserting - * bits into the same array anyway.) - */ -static void -qtree_bitins(unsigned char a[], int nx, int ny, int b[], int n, int bit) -/* - int n; declared y dimension of b -*/ -{ -int i, j, k; -int s00; -int plane_val; - - plane_val = 1 << bit; - - /* - * expand each 2x2 block - */ - k = 0; /* k is index of a[i/2,j/2] */ - for (i = 0; i>1) & 1) << bit; - b[s00+1] |= ((a[k]>>2) & 1) << bit; - b[s00 ] |= ((a[k]>>3) & 1) << bit; -*/ - s00 += 2; -/* s10 += 2; */ - k += 1; - } - if (j < ny) { - /* - * row size is odd, do last element in row - * s00+1, s10+1 are off edge - */ - - switch (a[k]) { - case(0): - break; - case(1): - break; - case(2): - b[s00+n ] |= plane_val; - break; - case(3): - b[s00+n ] |= plane_val; - break; - case(4): - break; - case(5): - break; - case(6): - b[s00+n ] |= plane_val; - break; - case(7): - b[s00+n ] |= plane_val; - break; - case(8): - b[s00 ] |= plane_val; - break; - case(9): - b[s00 ] |= plane_val; - break; - case(10): - b[s00+n ] |= plane_val; - b[s00 ] |= plane_val; - break; - case(11): - b[s00+n ] |= plane_val; - b[s00 ] |= plane_val; - break; - case(12): - b[s00 ] |= plane_val; - break; - case(13): - b[s00 ] |= plane_val; - break; - case(14): - b[s00+n ] |= plane_val; - b[s00 ] |= plane_val; - break; - case(15): - b[s00+n ] |= plane_val; - b[s00 ] |= plane_val; - break; - } - -/* - b[s10 ] |= ((a[k]>>1) & 1) << bit; - b[s00 ] |= ((a[k]>>3) & 1) << bit; -*/ - k += 1; - } - } - if (i < nx) { - /* - * column size is odd, do last row - * s10, s10+1 are off edge - */ - s00 = n*i; - for (j = 0; j>2) & 1) << bit; - b[s00 ] |= ((a[k]>>3) & 1) << bit; -*/ - - s00 += 2; - k += 1; - } - if (j < ny) { - /* - * both row and column size are odd, do corner element - * s00+1, s10, s10+1 are off edge - */ - - switch (a[k]) { - case(0): - break; - case(1): - break; - case(2): - break; - case(3): - break; - case(4): - break; - case(5): - break; - case(6): - break; - case(7): - break; - case(8): - b[s00 ] |= plane_val; - break; - case(9): - b[s00 ] |= plane_val; - break; - case(10): - b[s00 ] |= plane_val; - break; - case(11): - b[s00 ] |= plane_val; - break; - case(12): - b[s00 ] |= plane_val; - break; - case(13): - b[s00 ] |= plane_val; - break; - case(14): - b[s00 ] |= plane_val; - break; - case(15): - b[s00 ] |= plane_val; - break; - } - -/* - b[s00 ] |= ((a[k]>>3) & 1) << bit; -*/ - k += 1; - } - } -} -/* ############################################################################ */ -/* - * Copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding - * each value to 2x2 pixels and inserting into bitplane BIT of B. - * A,B may NOT be same array (it wouldn't make sense to be inserting - * bits into the same array anyway.) - */ -static void -qtree_bitins64(unsigned char a[], int nx, int ny, LONGLONG b[], int n, int bit) -/* - int n; declared y dimension of b -*/ -{ -int i, j, k; -int s00; -LONGLONG plane_val; - - plane_val = ((LONGLONG) 1) << bit; - - /* - * expand each 2x2 block - */ - k = 0; /* k is index of a[i/2,j/2] */ - for (i = 0; i>1) & 1) << bit; - b[s00+1] |= ((((LONGLONG)a[k])>>2) & 1) << bit; - b[s00 ] |= ((((LONGLONG)a[k])>>3) & 1) << bit; -*/ - s00 += 2; -/* s10 += 2; */ - k += 1; - } - if (j < ny) { - /* - * row size is odd, do last element in row - * s00+1, s10+1 are off edge - */ - - switch (a[k]) { - case(0): - break; - case(1): - break; - case(2): - b[s00+n ] |= plane_val; - break; - case(3): - b[s00+n ] |= plane_val; - break; - case(4): - break; - case(5): - break; - case(6): - b[s00+n ] |= plane_val; - break; - case(7): - b[s00+n ] |= plane_val; - break; - case(8): - b[s00 ] |= plane_val; - break; - case(9): - b[s00 ] |= plane_val; - break; - case(10): - b[s00+n ] |= plane_val; - b[s00 ] |= plane_val; - break; - case(11): - b[s00+n ] |= plane_val; - b[s00 ] |= plane_val; - break; - case(12): - b[s00 ] |= plane_val; - break; - case(13): - b[s00 ] |= plane_val; - break; - case(14): - b[s00+n ] |= plane_val; - b[s00 ] |= plane_val; - break; - case(15): - b[s00+n ] |= plane_val; - b[s00 ] |= plane_val; - break; - } -/* - b[s10 ] |= ((((LONGLONG)a[k])>>1) & 1) << bit; - b[s00 ] |= ((((LONGLONG)a[k])>>3) & 1) << bit; -*/ - k += 1; - } - } - if (i < nx) { - /* - * column size is odd, do last row - * s10, s10+1 are off edge - */ - s00 = n*i; - for (j = 0; j>2) & 1) << bit; - b[s00 ] |= ((((LONGLONG)a[k])>>3) & 1) << bit; -*/ - s00 += 2; - k += 1; - } - if (j < ny) { - /* - * both row and column size are odd, do corner element - * s00+1, s10, s10+1 are off edge - */ - - switch (a[k]) { - case(0): - break; - case(1): - break; - case(2): - break; - case(3): - break; - case(4): - break; - case(5): - break; - case(6): - break; - case(7): - break; - case(8): - b[s00 ] |= plane_val; - break; - case(9): - b[s00 ] |= plane_val; - break; - case(10): - b[s00 ] |= plane_val; - break; - case(11): - b[s00 ] |= plane_val; - break; - case(12): - b[s00 ] |= plane_val; - break; - case(13): - b[s00 ] |= plane_val; - break; - case(14): - b[s00 ] |= plane_val; - break; - case(15): - b[s00 ] |= plane_val; - break; - } -/* - b[s00 ] |= ((((LONGLONG)a[k])>>3) & 1) << bit; -*/ - k += 1; - } - } -} - -/* ############################################################################ */ -static void -read_bdirect(unsigned char *infile, int a[], int n, int nqx, int nqy, unsigned char scratch[], int bit) -{ - /* - * read bit image packed 4 pixels/nybble - */ -/* -int i; - for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) { - scratch[i] = input_nybble(infile); - } -*/ - input_nnybble(infile, ((nqx+1)/2) * ((nqy+1)/2), scratch); - - /* - * insert in bitplane BIT of image A - */ - qtree_bitins(scratch,nqx,nqy,a,n,bit); -} -/* ############################################################################ */ -static void -read_bdirect64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, unsigned char scratch[], int bit) -{ - /* - * read bit image packed 4 pixels/nybble - */ -/* -int i; - for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) { - scratch[i] = input_nybble(infile); - } -*/ - input_nnybble(infile, ((nqx+1)/2) * ((nqy+1)/2), scratch); - - /* - * insert in bitplane BIT of image A - */ - qtree_bitins64(scratch,nqx,nqy,a,n,bit); -} - -/* ############################################################################ */ -/* - * Huffman decoding for fixed codes - * - * Coded values range from 0-15 - * - * Huffman code values (hex): - * - * 3e, 00, 01, 08, 02, 09, 1a, 1b, - * 03, 1c, 0a, 1d, 0b, 1e, 3f, 0c - * - * and number of bits in each code: - * - * 6, 3, 3, 4, 3, 4, 5, 5, - * 3, 5, 4, 5, 4, 5, 6, 4 - */ -static int input_huffman(unsigned char *infile) -{ -int c; - - /* - * get first 3 bits to start - */ - c = input_nbits(infile,3); - if (c < 4) { - /* - * this is all we need - * return 1,2,4,8 for c=0,1,2,3 - */ - return(1<>bits_to_go) & 1); -} - -/* ############################################################################ */ -/* INPUT N BITS (N must be <= 8) */ - -static int input_nbits(unsigned char *infile, int n) -{ - /* AND mask for retreiving the right-most n bits */ - static int mask[9] = {0, 1, 3, 7, 15, 31, 63, 127, 255}; - - if (bits_to_go < n) { - /* - * need another byte's worth of bits - */ - - buffer2 = (buffer2<<8) | (int) infile[nextchar]; - nextchar++; - bits_to_go += 8; - } - /* - * now pick off the first n bits - */ - bits_to_go -= n; - - /* there was a slight gain in speed by replacing the following line */ -/* return( (buffer2>>bits_to_go) & ((1<>bits_to_go) & (*(mask+n)) ); -} -/* ############################################################################ */ -/* INPUT 4 BITS */ - -static int input_nybble(unsigned char *infile) -{ - if (bits_to_go < 4) { - /* - * need another byte's worth of bits - */ - - buffer2 = (buffer2<<8) | (int) infile[nextchar]; - nextchar++; - bits_to_go += 8; - } - /* - * now pick off the first 4 bits - */ - bits_to_go -= 4; - - return( (buffer2>>bits_to_go) & 15 ); -} -/* ############################################################################ */ -/* INPUT array of 4 BITS */ - -static int input_nnybble(unsigned char *infile, int n, unsigned char array[]) -{ - /* copy n 4-bit nybbles from infile to the lower 4 bits of array */ - -int ii, kk, shift1, shift2; - -/* forcing byte alignment doesn;t help, and even makes it go slightly slower -if (bits_to_go != 8) input_nbits(infile, bits_to_go); -*/ - if (n == 1) { - array[0] = input_nybble(infile); - return(0); - } - - if (bits_to_go == 8) { - /* - already have 2 full nybbles in buffer2, so - backspace the infile array to reuse last char - */ - nextchar--; - bits_to_go = 0; - } - - /* bits_to_go now has a value in the range 0 - 7. After adding */ - /* another byte, bits_to_go effectively will be in range 8 - 15 */ - - shift1 = bits_to_go + 4; /* shift1 will be in range 4 - 11 */ - shift2 = bits_to_go; /* shift2 will be in range 0 - 7 */ - kk = 0; - - /* special case */ - if (bits_to_go == 0) - { - for (ii = 0; ii < n/2; ii++) { - /* - * refill the buffer with next byte - */ - buffer2 = (buffer2<<8) | (int) infile[nextchar]; - nextchar++; - array[kk] = (int) ((buffer2>>4) & 15); - array[kk + 1] = (int) ((buffer2) & 15); /* no shift required */ - kk += 2; - } - } - else - { - for (ii = 0; ii < n/2; ii++) { - /* - * refill the buffer with next byte - */ - buffer2 = (buffer2<<8) | (int) infile[nextchar]; - nextchar++; - array[kk] = (int) ((buffer2>>shift1) & 15); - array[kk + 1] = (int) ((buffer2>>shift2) & 15); - kk += 2; - } - } - - - if (ii * 2 != n) { /* have to read last odd byte */ - array[n-1] = input_nybble(infile); - } - - return( (buffer2>>bits_to_go) & 15 ); -} diff --git a/src/external/OpenGR/3rdparty/cfitsio/fitscopy.c b/src/external/OpenGR/3rdparty/cfitsio/fitscopy.c deleted file mode 100644 index 67e32295e..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/fitscopy.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include "fitsio.h" - -int main(int argc, char *argv[]) -{ - fitsfile *infptr, *outfptr; /* FITS file pointers defined in fitsio.h */ - int status = 0; /* status must always be initialized = 0 */ - - if (argc != 3) - { - printf("Usage: fitscopy inputfile outputfile\n"); - printf("\n"); - printf("Copy an input file to an output file, optionally filtering\n"); - printf("the file in the process. This seemingly simple program can\n"); - printf("apply powerful filters which transform the input file as\n"); - printf("it is being copied. Filters may be used to extract a\n"); - printf("subimage from a larger image, select rows from a table,\n"); - printf("filter a table with a GTI time extension or a SAO region file,\n"); - printf("create or delete columns in a table, create an image by\n"); - printf("binning (histogramming) 2 table columns, and convert IRAF\n"); - printf("format *.imh or raw binary data files into FITS images.\n"); - printf("See the CFITSIO User's Guide for a complete description of\n"); - printf("the Extended File Name filtering syntax.\n"); - printf("\n"); - printf("Examples:\n"); - printf("\n"); - printf("fitscopy in.fit out.fit (simple file copy)\n"); - printf("fitscopy - - (stdin to stdout)\n"); - printf("fitscopy in.fit[11:50,21:60] out.fit (copy a subimage)\n"); - printf("fitscopy iniraf.imh out.fit (IRAF image to FITS)\n"); - printf("fitscopy in.dat[i512,512] out.fit (raw array to FITS)\n"); - printf("fitscopy in.fit[events][pi>35] out.fit (copy rows with pi>35)\n"); - printf("fitscopy in.fit[events][bin X,Y] out.fit (bin an image) \n"); - printf("fitscopy in.fit[events][col x=.9*y] out.fit (new x column)\n"); - printf("fitscopy in.fit[events][gtifilter()] out.fit (time filter)\n"); - printf("fitscopy in.fit[2][regfilter(\"pow.reg\")] out.fit (spatial filter)\n"); - printf("\n"); - printf("Note that it may be necessary to enclose the input file name\n"); - printf("in single quote characters on the Unix command line.\n"); - return(0); - } - /* Open the input file */ - if ( !fits_open_file(&infptr, argv[1], READONLY, &status) ) - { - /* Create the output file */ - if ( !fits_create_file(&outfptr, argv[2], &status) ) - { - - /* copy the previous, current, and following HDUs */ - fits_copy_file(infptr, outfptr, 1, 1, 1, &status); - - fits_close_file(outfptr, &status); - } - fits_close_file(infptr, &status); - } - - /* if error occured, print out error message */ - if (status) fits_report_error(stderr, status); - return(status); -} diff --git a/src/external/OpenGR/3rdparty/cfitsio/fitscore.c b/src/external/OpenGR/3rdparty/cfitsio/fitscore.c deleted file mode 100644 index bfa2602ae..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/fitscore.c +++ /dev/null @@ -1,9499 +0,0 @@ -/* This file, fitscore.c, contains the core set of FITSIO routines. */ - -/* The FITSIO software was written by William Pence at the High Energy */ -/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ -/* Goddard Space Flight Center. */ -/* - -Copyright (Unpublished--all rights reserved under the copyright laws of -the United States), U.S. Government as represented by the Administrator -of the National Aeronautics and Space Administration. No copyright is -claimed in the United States under Title 17, U.S. Code. - -Permission to freely use, copy, modify, and distribute this software -and its documentation without fee is hereby granted, provided that this -copyright notice and disclaimer of warranty appears in all copies. - -DISCLAIMER: - -THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, -EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, -ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY -IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE -DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE -SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY -DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR -CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY -CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, -CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY -PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED -FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR -SERVICES PROVIDED HEREUNDER." - -*/ - - -#include -#include -#include -#include -#include -#include -/* stddef.h is apparently needed to define size_t with some compilers ?? */ -#include -#include -#include "fitsio2.h" - -#define errmsgsiz 25 -#define ESMARKER 27 /* Escape character is used as error stack marker */ - -#define DelAll 1 /* delete all messages on the error stack */ -#define DelMark 2 /* delete newest messages back to and including marker */ -#define DelNewest 3 /* delete the newest message from the stack */ -#define GetMesg 4 /* pop and return oldest message, ignoring marks */ -#define PutMesg 5 /* add a new message to the stack */ -#define PutMark 6 /* add a marker to the stack */ - -#ifdef _REENTRANT -/* - Fitsio_Lock and Fitsio_Pthread_Status are declared in fitsio2.h. -*/ -pthread_mutex_t Fitsio_Lock; -int Fitsio_Pthread_Status = 0; - -#endif - -int STREAM_DRIVER = 0; -struct lconv *lcxxx; - -/*--------------------------------------------------------------------------*/ -float ffvers(float *version) /* IO - version number */ -/* - return the current version number of the FITSIO software -*/ -{ - *version = (float) 3.41; - -/* Nov 2016 - - Previous releases: - *version = 3.40 Oct 2016 - *version = 3.39 Apr 2016 - *version = 3.38 Feb 2016 - *version = 3.37 3 Jun 2014 - *version = 3.36 6 Dec 2013 - *version = 3.35 23 May 2013 - *version = 3.34 20 Mar 2013 - *version = 3.33 14 Feb 2013 - *version = 3.32 Oct 2012 - *version = 3.31 18 Jul 2012 - *version = 3.30 11 Apr 2012 - *version = 3.29 22 Sep 2011 - *version = 3.28 12 May 2011 - *version = 3.27 3 Mar 2011 - *version = 3.26 30 Dec 2010 - *version = 3.25 9 June 2010 - *version = 3.24 26 Jan 2010 - *version = 3.23 7 Jan 2010 - *version = 3.22 28 Oct 2009 - *version = 3.21 24 Sep 2009 - *version = 3.20 31 Aug 2009 - *version = 3.18 12 May 2009 (beta version) - *version = 3.14 18 Mar 2009 - *version = 3.13 5 Jan 2009 - *version = 3.12 8 Oct 2008 - *version = 3.11 19 Sep 2008 - *version = 3.10 20 Aug 2008 - *version = 3.09 3 Jun 2008 - *version = 3.08 15 Apr 2007 (internal release) - *version = 3.07 5 Nov 2007 (internal release) - *version = 3.06 27 Aug 2007 - *version = 3.05 12 Jul 2007 (internal release) - *version = 3.03 11 Dec 2006 - *version = 3.02 18 Sep 2006 - *version = 3.01 May 2006 included in FTOOLS 6.1 release - *version = 3.006 20 Feb 2006 - *version = 3.005 20 Dec 2005 (beta, in heasoft swift release - *version = 3.004 16 Sep 2005 (beta, in heasoft swift release - *version = 3.003 28 Jul 2005 (beta, in heasoft swift release - *version = 3.002 15 Apr 2005 (beta) - *version = 3.001 15 Mar 2005 (beta) released with heasoft 6.0 - *version = 3.000 1 Mar 2005 (internal release only) - *version = 2.51 2 Dec 2004 - *version = 2.50 28 Jul 2004 - *version = 2.49 11 Feb 2004 - *version = 2.48 28 Jan 2004 - *version = 2.470 18 Aug 2003 - *version = 2.460 20 May 2003 - *version = 2.450 30 Apr 2003 (internal release only) - *version = 2.440 8 Jan 2003 - *version = 2.430; 4 Nov 2002 - *version = 2.420; 19 Jul 2002 - *version = 2.410; 22 Apr 2002 used in ftools v5.2 - *version = 2.401; 28 Jan 2002 - *version = 2.400; 18 Jan 2002 - *version = 2.301; 7 Dec 2001 - *version = 2.300; 23 Oct 2001 - *version = 2.204; 26 Jul 2001 - *version = 2.203; 19 Jul 2001 used in ftools v5.1 - *version = 2.202; 22 May 2001 - *version = 2.201; 15 Mar 2001 - *version = 2.200; 26 Jan 2001 - *version = 2.100; 26 Sep 2000 - *version = 2.037; 6 Jul 2000 - *version = 2.036; 1 Feb 2000 - *version = 2.035; 7 Dec 1999 (internal release only) - *version = 2.034; 23 Nov 1999 - *version = 2.033; 17 Sep 1999 - *version = 2.032; 25 May 1999 - *version = 2.031; 31 Mar 1999 - *version = 2.030; 24 Feb 1999 - *version = 2.029; 11 Feb 1999 - *version = 2.028; 26 Jan 1999 - *version = 2.027; 12 Jan 1999 - *version = 2.026; 23 Dec 1998 - *version = 2.025; 1 Dec 1998 - *version = 2.024; 9 Nov 1998 - *version = 2.023; 1 Nov 1998 first full release of V2.0 - *version = 1.42; 30 Apr 1998 - *version = 1.40; 6 Feb 1998 - *version = 1.33; 16 Dec 1997 (internal release only) - *version = 1.32; 21 Nov 1997 (internal release only) - *version = 1.31; 4 Nov 1997 (internal release only) - *version = 1.30; 11 Sep 1997 - *version = 1.27; 3 Sep 1997 (internal release only) - *version = 1.25; 2 Jul 1997 - *version = 1.24; 2 May 1997 - *version = 1.23; 24 Apr 1997 - *version = 1.22; 18 Apr 1997 - *version = 1.21; 26 Mar 1997 - *version = 1.2; 29 Jan 1997 - *version = 1.11; 04 Dec 1996 - *version = 1.101; 13 Nov 1996 - *version = 1.1; 6 Nov 1996 - *version = 1.04; 17 Sep 1996 - *version = 1.03; 20 Aug 1996 - *version = 1.02; 15 Aug 1996 - *version = 1.01; 12 Aug 1996 -*/ - - return(*version); -} -/*--------------------------------------------------------------------------*/ -int ffflnm(fitsfile *fptr, /* I - FITS file pointer */ - char *filename, /* O - name of the file */ - int *status) /* IO - error status */ -/* - return the name of the FITS file -*/ -{ - strcpy(filename,(fptr->Fptr)->filename); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffflmd(fitsfile *fptr, /* I - FITS file pointer */ - int *filemode, /* O - open mode of the file */ - int *status) /* IO - error status */ -/* - return the access mode of the FITS file -*/ -{ - *filemode = (fptr->Fptr)->writemode; - return(*status); -} -/*--------------------------------------------------------------------------*/ -void ffgerr(int status, /* I - error status value */ - char *errtext) /* O - error message (max 30 char long + null) */ -/* - Return a short descriptive error message that corresponds to the input - error status value. The message may be up to 30 characters long, plus - the terminating null character. -*/ -{ - errtext[0] = '\0'; - - if (status >= 0 && status < 300) - { - switch (status) { - - case 0: - strcpy(errtext, "OK - no error"); - break; - case 1: - strcpy(errtext, "non-CFITSIO program error"); - break; - case 101: - strcpy(errtext, "same input and output files"); - break; - case 103: - strcpy(errtext, "attempt to open too many files"); - break; - case 104: - strcpy(errtext, "could not open the named file"); - break; - case 105: - strcpy(errtext, "couldn't create the named file"); - break; - case 106: - strcpy(errtext, "error writing to FITS file"); - break; - case 107: - strcpy(errtext, "tried to move past end of file"); - break; - case 108: - strcpy(errtext, "error reading from FITS file"); - break; - case 110: - strcpy(errtext, "could not close the file"); - break; - case 111: - strcpy(errtext, "array dimensions too big"); - break; - case 112: - strcpy(errtext, "cannot write to readonly file"); - break; - case 113: - strcpy(errtext, "could not allocate memory"); - break; - case 114: - strcpy(errtext, "invalid fitsfile pointer"); - break; - case 115: - strcpy(errtext, "NULL input pointer"); - break; - case 116: - strcpy(errtext, "error seeking file position"); - break; - case 121: - strcpy(errtext, "invalid URL prefix"); - break; - case 122: - strcpy(errtext, "too many I/O drivers"); - break; - case 123: - strcpy(errtext, "I/O driver init failed"); - break; - case 124: - strcpy(errtext, "no I/O driver for this URLtype"); - break; - case 125: - strcpy(errtext, "parse error in input file URL"); - break; - case 126: - strcpy(errtext, "parse error in range list"); - break; - case 151: - strcpy(errtext, "bad argument (shared mem drvr)"); - break; - case 152: - strcpy(errtext, "null ptr arg (shared mem drvr)"); - break; - case 153: - strcpy(errtext, "no free shared memory handles"); - break; - case 154: - strcpy(errtext, "share mem drvr not initialized"); - break; - case 155: - strcpy(errtext, "IPC system error (shared mem)"); - break; - case 156: - strcpy(errtext, "no memory (shared mem drvr)"); - break; - case 157: - strcpy(errtext, "share mem resource deadlock"); - break; - case 158: - strcpy(errtext, "lock file open/create failed"); - break; - case 159: - strcpy(errtext, "can't resize share mem block"); - break; - case 201: - strcpy(errtext, "header already has keywords"); - break; - case 202: - strcpy(errtext, "keyword not found in header"); - break; - case 203: - strcpy(errtext, "keyword number out of bounds"); - break; - case 204: - strcpy(errtext, "keyword value is undefined"); - break; - case 205: - strcpy(errtext, "string missing closing quote"); - break; - case 206: - strcpy(errtext, "error in indexed keyword name"); - break; - case 207: - strcpy(errtext, "illegal character in keyword"); - break; - case 208: - strcpy(errtext, "required keywords out of order"); - break; - case 209: - strcpy(errtext, "keyword value not positive int"); - break; - case 210: - strcpy(errtext, "END keyword not found"); - break; - case 211: - strcpy(errtext, "illegal BITPIX keyword value"); - break; - case 212: - strcpy(errtext, "illegal NAXIS keyword value"); - break; - case 213: - strcpy(errtext, "illegal NAXISn keyword value"); - break; - case 214: - strcpy(errtext, "illegal PCOUNT keyword value"); - break; - case 215: - strcpy(errtext, "illegal GCOUNT keyword value"); - break; - case 216: - strcpy(errtext, "illegal TFIELDS keyword value"); - break; - case 217: - strcpy(errtext, "negative table row size"); - break; - case 218: - strcpy(errtext, "negative number of rows"); - break; - case 219: - strcpy(errtext, "named column not found"); - break; - case 220: - strcpy(errtext, "illegal SIMPLE keyword value"); - break; - case 221: - strcpy(errtext, "first keyword not SIMPLE"); - break; - case 222: - strcpy(errtext, "second keyword not BITPIX"); - break; - case 223: - strcpy(errtext, "third keyword not NAXIS"); - break; - case 224: - strcpy(errtext, "missing NAXISn keywords"); - break; - case 225: - strcpy(errtext, "first keyword not XTENSION"); - break; - case 226: - strcpy(errtext, "CHDU not an ASCII table"); - break; - case 227: - strcpy(errtext, "CHDU not a binary table"); - break; - case 228: - strcpy(errtext, "PCOUNT keyword not found"); - break; - case 229: - strcpy(errtext, "GCOUNT keyword not found"); - break; - case 230: - strcpy(errtext, "TFIELDS keyword not found"); - break; - case 231: - strcpy(errtext, "missing TBCOLn keyword"); - break; - case 232: - strcpy(errtext, "missing TFORMn keyword"); - break; - case 233: - strcpy(errtext, "CHDU not an IMAGE extension"); - break; - case 234: - strcpy(errtext, "illegal TBCOLn keyword value"); - break; - case 235: - strcpy(errtext, "CHDU not a table extension"); - break; - case 236: - strcpy(errtext, "column exceeds width of table"); - break; - case 237: - strcpy(errtext, "more than 1 matching col. name"); - break; - case 241: - strcpy(errtext, "row width not = field widths"); - break; - case 251: - strcpy(errtext, "unknown FITS extension type"); - break; - case 252: - strcpy(errtext, "1st key not SIMPLE or XTENSION"); - break; - case 253: - strcpy(errtext, "END keyword is not blank"); - break; - case 254: - strcpy(errtext, "Header fill area not blank"); - break; - case 255: - strcpy(errtext, "Data fill area invalid"); - break; - case 261: - strcpy(errtext, "illegal TFORM format code"); - break; - case 262: - strcpy(errtext, "unknown TFORM datatype code"); - break; - case 263: - strcpy(errtext, "illegal TDIMn keyword value"); - break; - case 264: - strcpy(errtext, "invalid BINTABLE heap pointer"); - break; - default: - strcpy(errtext, "unknown error status"); - break; - } - } - else if (status < 600) - { - switch(status) { - - case 301: - strcpy(errtext, "illegal HDU number"); - break; - case 302: - strcpy(errtext, "column number < 1 or > tfields"); - break; - case 304: - strcpy(errtext, "negative byte address"); - break; - case 306: - strcpy(errtext, "negative number of elements"); - break; - case 307: - strcpy(errtext, "bad first row number"); - break; - case 308: - strcpy(errtext, "bad first element number"); - break; - case 309: - strcpy(errtext, "not an ASCII (A) column"); - break; - case 310: - strcpy(errtext, "not a logical (L) column"); - break; - case 311: - strcpy(errtext, "bad ASCII table datatype"); - break; - case 312: - strcpy(errtext, "bad binary table datatype"); - break; - case 314: - strcpy(errtext, "null value not defined"); - break; - case 317: - strcpy(errtext, "not a variable length column"); - break; - case 320: - strcpy(errtext, "illegal number of dimensions"); - break; - case 321: - strcpy(errtext, "1st pixel no. > last pixel no."); - break; - case 322: - strcpy(errtext, "BSCALE or TSCALn = 0."); - break; - case 323: - strcpy(errtext, "illegal axis length < 1"); - break; - case 340: - strcpy(errtext, "not group table"); - break; - case 341: - strcpy(errtext, "HDU already member of group"); - break; - case 342: - strcpy(errtext, "group member not found"); - break; - case 343: - strcpy(errtext, "group not found"); - break; - case 344: - strcpy(errtext, "bad group id"); - break; - case 345: - strcpy(errtext, "too many HDUs tracked"); - break; - case 346: - strcpy(errtext, "HDU alread tracked"); - break; - case 347: - strcpy(errtext, "bad Grouping option"); - break; - case 348: - strcpy(errtext, "identical pointers (groups)"); - break; - case 360: - strcpy(errtext, "malloc failed in parser"); - break; - case 361: - strcpy(errtext, "file read error in parser"); - break; - case 362: - strcpy(errtext, "null pointer arg (parser)"); - break; - case 363: - strcpy(errtext, "empty line (parser)"); - break; - case 364: - strcpy(errtext, "cannot unread > 1 line"); - break; - case 365: - strcpy(errtext, "parser too deeply nested"); - break; - case 366: - strcpy(errtext, "file open failed (parser)"); - break; - case 367: - strcpy(errtext, "hit EOF (parser)"); - break; - case 368: - strcpy(errtext, "bad argument (parser)"); - break; - case 369: - strcpy(errtext, "unexpected token (parser)"); - break; - case 401: - strcpy(errtext, "bad int to string conversion"); - break; - case 402: - strcpy(errtext, "bad float to string conversion"); - break; - case 403: - strcpy(errtext, "keyword value not integer"); - break; - case 404: - strcpy(errtext, "keyword value not logical"); - break; - case 405: - strcpy(errtext, "keyword value not floating pt"); - break; - case 406: - strcpy(errtext, "keyword value not double"); - break; - case 407: - strcpy(errtext, "bad string to int conversion"); - break; - case 408: - strcpy(errtext, "bad string to float conversion"); - break; - case 409: - strcpy(errtext, "bad string to double convert"); - break; - case 410: - strcpy(errtext, "illegal datatype code value"); - break; - case 411: - strcpy(errtext, "illegal no. of decimals"); - break; - case 412: - strcpy(errtext, "datatype conversion overflow"); - break; - case 413: - strcpy(errtext, "error compressing image"); - break; - case 414: - strcpy(errtext, "error uncompressing image"); - break; - case 420: - strcpy(errtext, "bad date or time conversion"); - break; - case 431: - strcpy(errtext, "syntax error in expression"); - break; - case 432: - strcpy(errtext, "expression result wrong type"); - break; - case 433: - strcpy(errtext, "vector result too large"); - break; - case 434: - strcpy(errtext, "missing output column"); - break; - case 435: - strcpy(errtext, "bad data in parsed column"); - break; - case 436: - strcpy(errtext, "output extension of wrong type"); - break; - case 501: - strcpy(errtext, "WCS angle too large"); - break; - case 502: - strcpy(errtext, "bad WCS coordinate"); - break; - case 503: - strcpy(errtext, "error in WCS calculation"); - break; - case 504: - strcpy(errtext, "bad WCS projection type"); - break; - case 505: - strcpy(errtext, "WCS keywords not found"); - break; - default: - strcpy(errtext, "unknown error status"); - break; - } - } - else - { - strcpy(errtext, "unknown error status"); - } - return; -} -/*--------------------------------------------------------------------------*/ -void ffpmsg(const char *err_message) -/* - put message on to error stack -*/ -{ - ffxmsg(PutMesg, (char *)err_message); - return; -} -/*--------------------------------------------------------------------------*/ -void ffpmrk(void) -/* - write a marker to the stack. It is then possible to pop only those - messages following the marker off of the stack, leaving the previous - messages unaffected. - - The marker is ignored by the ffgmsg routine. -*/ -{ - char *dummy = 0; - - ffxmsg(PutMark, dummy); - return; -} -/*--------------------------------------------------------------------------*/ -int ffgmsg(char *err_message) -/* - get oldest message from error stack, ignoring markers -*/ -{ - ffxmsg(GetMesg, err_message); - return(*err_message); -} -/*--------------------------------------------------------------------------*/ -void ffcmsg(void) -/* - erase all messages in the error stack -*/ -{ - char *dummy = 0; - - ffxmsg(DelAll, dummy); - return; -} -/*--------------------------------------------------------------------------*/ -void ffcmrk(void) -/* - erase newest messages in the error stack, stopping if a marker is found. - The marker is also erased in this case. -*/ -{ - char *dummy = 0; - - ffxmsg(DelMark, dummy); - return; -} -/*--------------------------------------------------------------------------*/ -void ffxmsg( int action, - char *errmsg) -/* - general routine to get, put, or clear the error message stack. - Use a static array rather than allocating memory as needed for - the error messages because it is likely to be more efficient - and simpler to implement. - - Action Code: -DelAll 1 delete all messages on the error stack -DelMark 2 delete messages back to and including the 1st marker -DelNewest 3 delete the newest message from the stack -GetMesg 4 pop and return oldest message, ignoring marks -PutMesg 5 add a new message to the stack -PutMark 6 add a marker to the stack - -*/ -{ - int ii; - char markflag; - static char *txtbuff[errmsgsiz], *tmpbuff, *msgptr; - static char errbuff[errmsgsiz][81]; /* initialize all = \0 */ - static int nummsg = 0; - - FFLOCK; - - if (action == DelAll) /* clear the whole message stack */ - { - for (ii = 0; ii < nummsg; ii ++) - *txtbuff[ii] = '\0'; - - nummsg = 0; - } - else if (action == DelMark) /* clear up to and including first marker */ - { - while (nummsg > 0) { - nummsg--; - markflag = *txtbuff[nummsg]; /* store possible marker character */ - *txtbuff[nummsg] = '\0'; /* clear the buffer for this msg */ - - if (markflag == ESMARKER) - break; /* found a marker, so quit */ - } - } - else if (action == DelNewest) /* remove newest message from stack */ - { - if (nummsg > 0) - { - nummsg--; - *txtbuff[nummsg] = '\0'; /* clear the buffer for this msg */ - } - } - else if (action == GetMesg) /* pop and return oldest message from stack */ - { /* ignoring markers */ - while (nummsg > 0) - { - strcpy(errmsg, txtbuff[0]); /* copy oldest message to output */ - - *txtbuff[0] = '\0'; /* clear the buffer for this msg */ - - nummsg--; - for (ii = 0; ii < nummsg; ii++) - txtbuff[ii] = txtbuff[ii + 1]; /* shift remaining pointers */ - - if (errmsg[0] != ESMARKER) { /* quit if this is not a marker */ - FFUNLOCK; - return; - } - } - errmsg[0] = '\0'; /* no messages in the stack */ - } - else if (action == PutMesg) /* add new message to stack */ - { - msgptr = errmsg; - while (strlen(msgptr)) - { - if (nummsg == errmsgsiz) - { - tmpbuff = txtbuff[0]; /* buffers full; reuse oldest buffer */ - *txtbuff[0] = '\0'; /* clear the buffer for this msg */ - - nummsg--; - for (ii = 0; ii < nummsg; ii++) - txtbuff[ii] = txtbuff[ii + 1]; /* shift remaining pointers */ - - txtbuff[nummsg] = tmpbuff; /* set pointer for the new message */ - } - else - { - for (ii = 0; ii < errmsgsiz; ii++) - { - if (*errbuff[ii] == '\0') /* find first empty buffer */ - { - txtbuff[nummsg] = errbuff[ii]; - break; - } - } - } - - strncat(txtbuff[nummsg], msgptr, 80); - nummsg++; - - msgptr += minvalue(80, strlen(msgptr)); - } - } - else if (action == PutMark) /* put a marker on the stack */ - { - if (nummsg == errmsgsiz) - { - tmpbuff = txtbuff[0]; /* buffers full; reuse oldest buffer */ - *txtbuff[0] = '\0'; /* clear the buffer for this msg */ - - nummsg--; - for (ii = 0; ii < nummsg; ii++) - txtbuff[ii] = txtbuff[ii + 1]; /* shift remaining pointers */ - - txtbuff[nummsg] = tmpbuff; /* set pointer for the new message */ - } - else - { - for (ii = 0; ii < errmsgsiz; ii++) - { - if (*errbuff[ii] == '\0') /* find first empty buffer */ - { - txtbuff[nummsg] = errbuff[ii]; - break; - } - } - } - - *txtbuff[nummsg] = ESMARKER; /* write the marker */ - *(txtbuff[nummsg] + 1) = '\0'; - nummsg++; - - } - - FFUNLOCK; - return; -} -/*--------------------------------------------------------------------------*/ -int ffpxsz(int datatype) -/* - return the number of bytes per pixel associated with the datatype -*/ -{ - if (datatype == TBYTE) - return(sizeof(char)); - else if (datatype == TUSHORT) - return(sizeof(short)); - else if (datatype == TSHORT) - return(sizeof(short)); - else if (datatype == TULONG) - return(sizeof(long)); - else if (datatype == TLONG) - return(sizeof(long)); - else if (datatype == TINT) - return(sizeof(int)); - else if (datatype == TUINT) - return(sizeof(int)); - else if (datatype == TFLOAT) - return(sizeof(float)); - else if (datatype == TDOUBLE) - return(sizeof(double)); - else if (datatype == TLOGICAL) - return(sizeof(char)); - else - return(0); -} -/*--------------------------------------------------------------------------*/ -int fftkey(const char *keyword, /* I - keyword name */ - int *status) /* IO - error status */ -/* - Test that the keyword name conforms to the FITS standard. Must contain - only capital letters, digits, minus or underscore chars. Trailing spaces - are allowed. If the input status value is less than zero, then the test - is modified so that upper or lower case letters are allowed, and no - error messages are printed if the keyword is not legal. -*/ -{ - size_t maxchr, ii; - int spaces=0; - char msg[81], testchar; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - maxchr=strlen(keyword); - if (maxchr > 8) - maxchr = 8; - - for (ii = 0; ii < maxchr; ii++) - { - if (*status == 0) - testchar = keyword[ii]; - else - testchar = toupper(keyword[ii]); - - if ( (testchar >= 'A' && testchar <= 'Z') || - (testchar >= '0' && testchar <= '9') || - testchar == '-' || testchar == '_' ) - { - if (spaces) - { - if (*status == 0) - { - /* don't print error message if status < 0 */ - sprintf(msg, - "Keyword name contains embedded space(s): %.8s", - keyword); - ffpmsg(msg); - } - return(*status = BAD_KEYCHAR); - } - } - else if (keyword[ii] == ' ') - spaces = 1; - - else - { - if (*status == 0) - { - /* don't print error message if status < 0 */ - sprintf(msg, "Character %d in this keyword is illegal: %.8s", - (int) (ii+1), keyword); - ffpmsg(msg); - - /* explicitly flag the 2 most common cases */ - if (keyword[ii] == 0) - ffpmsg(" (This a NULL (0) character)."); - else if (keyword[ii] == 9) - ffpmsg(" (This an ASCII TAB (9) character)."); - } - - return(*status = BAD_KEYCHAR); - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fftrec(char *card, /* I - keyword card to test */ - int *status) /* IO - error status */ -/* - Test that the keyword card conforms to the FITS standard. Must contain - only printable ASCII characters; -*/ -{ - size_t ii, maxchr; - char msg[81]; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - maxchr = strlen(card); - - for (ii = 8; ii < maxchr; ii++) - { - if (card[ii] < 32 || card[ii] > 126) - { - sprintf(msg, - "Character %d in this keyword is illegal. Hex Value = %X", - (int) (ii+1), (int) card[ii] ); - - if (card[ii] == 0) - strcat(msg, " (NULL char.)"); - else if (card[ii] == 9) - strcat(msg, " (TAB char.)"); - else if (card[ii] == 10) - strcat(msg, " (Line Feed char.)"); - else if (card[ii] == 11) - strcat(msg, " (Vertical Tab)"); - else if (card[ii] == 12) - strcat(msg, " (Form Feed char.)"); - else if (card[ii] == 13) - strcat(msg, " (Carriage Return)"); - else if (card[ii] == 27) - strcat(msg, " (Escape char.)"); - else if (card[ii] == 127) - strcat(msg, " (Delete char.)"); - - ffpmsg(msg); - - strncpy(msg, card, 80); - msg[80] = '\0'; - ffpmsg(msg); - return(*status = BAD_KEYCHAR); - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -void ffupch(char *string) -/* - convert string to upper case, in place. -*/ -{ - size_t len, ii; - - len = strlen(string); - for (ii = 0; ii < len; ii++) - string[ii] = toupper(string[ii]); - return; -} -/*--------------------------------------------------------------------------*/ -int ffmkky(const char *keyname, /* I - keyword name */ - char *value, /* I - keyword value */ - const char *comm, /* I - keyword comment */ - char *card, /* O - constructed keyword card */ - int *status) /* IO - status value */ -/* - Make a complete FITS 80-byte keyword card from the input name, value and - comment strings. Output card is null terminated without any trailing blanks. -*/ -{ - size_t namelen, len, ii; - char tmpname[FLEN_KEYWORD], tmpname2[FLEN_KEYWORD],*cptr; - char *saveptr; - int tstatus = -1, nblank = 0, ntoken = 0, maxlen = 0, specialchar = 0; - - if (*status > 0) - return(*status); - - *tmpname = '\0'; - *tmpname2 = '\0'; - *card = '\0'; - - /* skip leading blanks in the name */ - while(*(keyname + nblank) == ' ') - nblank++; - - strncat(tmpname, keyname + nblank, FLEN_KEYWORD - 1); - - len = strlen(value); - namelen = strlen(tmpname); - - /* delete non-significant trailing blanks in the name */ - if (namelen) { - cptr = tmpname + namelen - 1; - - while(*cptr == ' ') { - *cptr = '\0'; - cptr--; - } - - namelen = cptr - tmpname + 1; - } - - /* check that the name does not contain an '=' (equals sign) */ - if (strchr(tmpname, '=') ) { - ffpmsg("Illegal keyword name; contains an equals sign (=)"); - ffpmsg(tmpname); - return(*status = BAD_KEYCHAR); - } - - if (namelen <= 8 && fftkey(tmpname, &tstatus) <= 0 ) { - - /* a normal 8-char (or less) FITS keyword. */ - strcat(card, tmpname); /* copy keyword name to buffer */ - - for (ii = namelen; ii < 8; ii++) - card[ii] = ' '; /* pad keyword name with spaces */ - - card[8] = '='; /* append '= ' in columns 9-10 */ - card[9] = ' '; - card[10] = '\0'; /* terminate the partial string */ - namelen = 10; - } else if ((FSTRNCMP(tmpname, "HIERARCH ", 9) == 0) || - (FSTRNCMP(tmpname, "hierarch ", 9) == 0) ) { - - /* this is an explicit ESO HIERARCH keyword */ - - strcat(card, tmpname); /* copy keyword name to buffer */ - - if (namelen + 3 + len > 80) { - /* save 1 char by not putting a space before the equals sign */ - strcat(card, "= "); - namelen += 2; - } else { - strcat(card, " = "); - namelen += 3; - } - } else { - - /* scan the keyword name to determine the number and max length of the tokens */ - /* and test if any of the tokens contain nonstandard characters */ - - strncat(tmpname2, tmpname, FLEN_KEYWORD - 1); - cptr = ffstrtok(tmpname2, " ",&saveptr); - while (cptr) { - if (strlen(cptr) > maxlen) maxlen = strlen(cptr); /* find longest token */ - - /* name contains special characters? */ - tstatus = -1; /* suppress any error message */ - if (fftkey(cptr, &tstatus) > 0) specialchar = 1; - - cptr = ffstrtok(NULL, " ",&saveptr); - ntoken++; - } - - tstatus = -1; /* suppress any error message */ - -/* if (ntoken > 1) { */ - if (ntoken > 0) { /* temporarily change so that this case should always be true */ - /* for now at least, treat all cases as an implicit ESO HIERARCH keyword. */ - /* This could change if FITS is ever expanded to directly support longer keywords. */ - - strcat(card, "HIERARCH "); - strcat(card, tmpname); - namelen += 9; - - if (namelen + 3 + len > 80) { - /* save 1 char by not putting a space before the equals sign */ - strcat(card, "= "); - namelen += 2; - } else { - strcat(card, " = "); - namelen += 3; - } - - } else if ((fftkey(tmpname, &tstatus) <= 0)) { - /* should never get here (at least for now) */ - /* allow keyword names longer than 8 characters */ - - strncat(card, tmpname, FLEN_KEYWORD - 1); - strcat(card, "= "); - namelen += 2; - } else { - /* should never get here (at least for now) */ - ffpmsg("Illegal keyword name:"); - ffpmsg(tmpname); - return(*status = BAD_KEYCHAR); - } - } - - if (len > 0) /* now process the value string */ - { - if (value[0] == '\'') /* is this a quoted string value? */ - { - if (namelen > 77) - { - ffpmsg( - "The following keyword + value is too long to fit on a card:"); - ffpmsg(keyname); - ffpmsg(value); - return(*status = BAD_KEYCHAR); - } - - strncat(card, value, 80 - namelen); /* append the value string */ - len = minvalue(80, namelen + len); - - /* restore the closing quote if it got truncated */ - if (len == 80) - { - card[79] = '\''; - } - - if (comm) - { - if (comm[0] != 0) - { - if (len < 30) - { - for (ii = len; ii < 30; ii++) - card[ii] = ' '; /* fill with spaces to col 30 */ - - card[30] = '\0'; - len = 30; - } - } - } - } - else - { - if (namelen + len > 80) - { - ffpmsg( - "The following keyword + value is too long to fit on a card:"); - ffpmsg(keyname); - ffpmsg(value); - return(*status = BAD_KEYCHAR); - } - else if (namelen + len < 30) - { - /* add spaces so field ends at least in col 30 */ - strncat(card, " ", 30 - (namelen + len)); - } - - strncat(card, value, 80 - namelen); /* append the value string */ - len = minvalue(80, namelen + len); - len = maxvalue(30, len); - } - - if (comm) - { - if ((len < 77) && ( strlen(comm) > 0) ) /* room for a comment? */ - { - strcat(card, " / "); /* append comment separator */ - strncat(card, comm, 77 - len); /* append comment (what fits) */ - } - } - } - else - { - if (namelen == 10) /* This case applies to normal keywords only */ - { - card[8] = ' '; /* keywords with no value have no '=' */ - if (comm) - { - strncat(card, comm, 80 - namelen); /* append comment (what fits) */ - } - } - } - - /* issue a warning if this keyword does not strictly conform to the standard - HIERARCH convention, which requires, - 1) at least 2 tokens in the name, - 2) no tokens longer than 8 characters, and - 3) no special characters in any of the tokens */ - - if (ntoken == 1 || specialchar == 1) { - ffpmsg("Warning: the following keyword does not conform to the HIERARCH convention"); - /* ffpmsg(" (e.g., name is not hierarchical or contains non-standard characters)."); */ - ffpmsg(card); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffmkey(fitsfile *fptr, /* I - FITS file pointer */ - const char *card, /* I - card string value */ - int *status) /* IO - error status */ -/* - replace the previously read card (i.e. starting 80 bytes before the - (fptr->Fptr)->nextkey position) with the contents of the input card. -*/ -{ - char tcard[81]; - size_t len, ii; - int keylength = 8; - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - strncpy(tcard,card,80); - tcard[80] = '\0'; - - len = strlen(tcard); - - /* silently replace any illegal characters with a space */ - for (ii=0; ii < len; ii++) - if (tcard[ii] < ' ' || tcard[ii] > 126) tcard[ii] = ' '; - - for (ii=len; ii < 80; ii++) /* fill card with spaces if necessary */ - tcard[ii] = ' '; - - keylength = strcspn(tcard, "="); - if (keylength == 80) keylength = 8; - - for (ii=0; ii < keylength; ii++) /* make sure keyword name is uppercase */ - tcard[ii] = toupper(tcard[ii]); - - fftkey(tcard, status); /* test keyword name contains legal chars */ - -/* no need to do this any more, since any illegal characters have been removed - fftrec(tcard, status); */ /* test rest of keyword for legal chars */ - - /* move position of keyword to be over written */ - ffmbyt(fptr, ((fptr->Fptr)->nextkey) - 80, REPORT_EOF, status); - ffpbyt(fptr, 80, tcard, status); /* write the 80 byte card */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffkeyn(const char *keyroot, /* I - root string for keyword name */ - int value, /* I - index number to be appended to root name */ - char *keyname, /* O - output root + index keyword name */ - int *status) /* IO - error status */ -/* - Construct a keyword name string by appending the index number to the root. - e.g., if root = "TTYPE" and value = 12 then keyname = "TTYPE12". - Note: this allows keyword names longer than 8 characters. -*/ -{ - char suffix[16]; - size_t rootlen; - - keyname[0] = '\0'; /* initialize output name to null */ - rootlen = strlen(keyroot); - - if (rootlen == 0 || value < 0 ) - return(*status = 206); - - sprintf(suffix, "%d", value); /* construct keyword suffix */ - - strcpy(keyname, keyroot); /* copy root string to name string */ - while (rootlen > 0 && keyname[rootlen - 1] == ' ') { - rootlen--; /* remove trailing spaces in root name */ - keyname[rootlen] = '\0'; - } - - strcat(keyname, suffix); /* append suffix to the root */ - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffnkey(int value, /* I - index number to be appended to root name */ - const char *keyroot, /* I - root string for keyword name */ - char *keyname, /* O - output root + index keyword name */ - int *status) /* IO - error status */ -/* - Construct a keyword name string by appending the root string to the index - number. e.g., if root = "TTYPE" and value = 12 then keyname = "12TTYPE". -*/ -{ - size_t rootlen; - - keyname[0] = '\0'; /* initialize output name to null */ - rootlen = strlen(keyroot); - - if (rootlen == 0 || rootlen > 7 || value < 0 ) - return(*status = 206); - - sprintf(keyname, "%d", value); /* construct keyword prefix */ - - if (rootlen + strlen(keyname) > 8) - return(*status = 206); - - strcat(keyname, keyroot); /* append root to the prefix */ - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffpsvc(char *card, /* I - FITS header card (nominally 80 bytes long) */ - char *value, /* O - value string parsed from the card */ - char *comm, /* O - comment string parsed from the card */ - int *status) /* IO - error status */ -/* - ParSe the Value and Comment strings from the input header card string. - If the card contains a quoted string value, the returned value string - includes the enclosing quote characters. If comm = NULL, don't return - the comment string. -*/ -{ - int jj; - size_t ii, cardlen, nblank, valpos; - - if (*status > 0) - return(*status); - - value[0] = '\0'; - if (comm) - comm[0] = '\0'; - - cardlen = strlen(card); - - /* support for ESO HIERARCH keywords; find the '=' */ - if (FSTRNCMP(card, "HIERARCH ", 9) == 0) - { - valpos = strcspn(card, "="); - - if (valpos == cardlen) /* no value indicator ??? */ - { - if (comm != NULL) - { - if (cardlen > 8) - { - strcpy(comm, &card[8]); - - jj=cardlen - 8; - for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ - { - if (comm[jj] == ' ') - comm[jj] = '\0'; - else - break; - } - } - } - return(*status); /* no value indicator */ - } - valpos++; /* point to the position after the '=' */ - } - else if (cardlen < 9 || - FSTRNCMP(card, "COMMENT ", 8) == 0 || /* keywords with no value */ - FSTRNCMP(card, "HISTORY ", 8) == 0 || - FSTRNCMP(card, "END ", 8) == 0 || - FSTRNCMP(card, "CONTINUE", 8) == 0 || - FSTRNCMP(card, " ", 8) == 0 ) - { - /* no value, so the comment extends from cols 9 - 80 */ - if (comm != NULL) - { - if (cardlen > 8) - { - strcpy(comm, &card[8]); - - jj=cardlen - 8; - for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ - { - if (comm[jj] == ' ') - comm[jj] = '\0'; - else - break; - } - } - } - return(*status); - } - else if (FSTRNCMP(&card[8], "= ", 2) == 0 ) - { - /* normal keyword with '= ' in cols 9-10 */ - valpos = 10; /* starting position of the value field */ - } - else - { - valpos = strcspn(card, "="); - - if (valpos == cardlen) /* no value indicator ??? */ - { - if (comm != NULL) - { - if (cardlen > 8) - { - strcpy(comm, &card[8]); - - jj=cardlen - 8; - for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ - { - if (comm[jj] == ' ') - comm[jj] = '\0'; - else - break; - } - } - } - return(*status); /* no value indicator */ - } - valpos++; /* point to the position after the '=' */ - } - - nblank = strspn(&card[valpos], " "); /* find number of leading blanks */ - - if (nblank + valpos == cardlen) - { - /* the absence of a value string is legal, and simply indicates - that the keyword value is undefined. Don't write an error - message in this case. - */ - return(*status); - } - - ii = valpos + nblank; - - if (card[ii] == '/' ) /* slash indicates start of the comment */ - { - ii++; - } - else if (card[ii] == '\'' ) /* is this a quoted string value? */ - { - value[0] = card[ii]; - for (jj=1, ii++; ii < cardlen; ii++, jj++) - { - if (card[ii] == '\'') /* is this the closing quote? */ - { - if (card[ii+1] == '\'') /* 2 successive quotes? */ - { - value[jj] = card[ii]; - ii++; - jj++; - } - else - { - value[jj] = card[ii]; - break; /* found the closing quote, so exit this loop */ - } - } - value[jj] = card[ii]; /* copy the next character to the output */ - } - - if (ii == cardlen) - { - jj = minvalue(jj, 69); /* don't exceed 70 char string length */ - value[jj] = '\''; /* close the bad value string */ - value[jj+1] = '\0'; /* terminate the bad value string */ - ffpmsg("This keyword string value has no closing quote:"); - ffpmsg(card); - /* May 2008 - modified to not fail on this minor error */ -/* return(*status = NO_QUOTE); */ - } - else - { - value[jj+1] = '\0'; /* terminate the good value string */ - ii++; /* point to the character following the value */ - } - } - else if (card[ii] == '(' ) /* is this a complex value? */ - { - nblank = strcspn(&card[ii], ")" ); /* find closing ) */ - if (nblank == strlen( &card[ii] ) ) - { - ffpmsg("This complex keyword value has no closing ')':"); - ffpmsg(card); - return(*status = NO_QUOTE); - } - - nblank++; - strncpy(value, &card[ii], nblank); - value[nblank] = '\0'; - ii = ii + nblank; - } - else /* an integer, floating point, or logical FITS value string */ - { - nblank = strcspn(&card[ii], " /"); /* find the end of the token */ - strncpy(value, &card[ii], nblank); - value[nblank] = '\0'; - ii = ii + nblank; - } - - /* now find the comment string, if any */ - if (comm) - { - nblank = strspn(&card[ii], " "); /* find next non-space character */ - ii = ii + nblank; - - if (ii < 80) - { - if (card[ii] == '/') /* ignore the slash separator */ - { - ii++; - if (card[ii] == ' ') /* also ignore the following space */ - ii++; - } - strcat(comm, &card[ii]); /* copy the remaining characters */ - - jj=strlen(comm); - for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ - { - if (comm[jj] == ' ') - comm[jj] = '\0'; - else - break; - } - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgthd(char *tmplt, /* I - input header template string */ - char *card, /* O - returned FITS header record */ - int *hdtype, /* O - how to interpreter the returned card string */ - /* - -2 = modify the name of a keyword; the old keyword name - is returned starting at address chars[0]; the new name - is returned starting at address char[40] (to be consistent - with the Fortran version). Both names are null terminated. - -1 = card contains the name of a keyword that is to be deleted - 0 = append this keyword if it doesn't already exist, or - modify the value if the keyword already exists. - 1 = append this comment keyword ('HISTORY', - 'COMMENT', or blank keyword name) - 2 = this is the END keyword; do not write it to the header - */ - int *status) /* IO - error status */ -/* - 'Get Template HeaDer' - parse a template header line and create a formated - character string which is suitable for appending to a FITS header -*/ -{ - char keyname[FLEN_KEYWORD], value[140], comment[140]; - char *tok, *suffix, *loc, tvalue[140]; - int len, vlen, more, tstatus; - double dval; - - if (*status > 0) - return(*status); - - card[0] = '\0'; - *hdtype = 0; - - if (!FSTRNCMP(tmplt, " ", 8) ) - { - /* if first 8 chars of template are blank, then this is a comment */ - strncat(card, tmplt, 80); - *hdtype = 1; - return(*status); - } - - tok = tmplt; /* point to start of template string */ - - keyname[0] = '\0'; - value[0] = '\0'; - comment[0] = '\0'; - - len = strspn(tok, " "); /* no. of spaces before keyword */ - tok += len; - - /* test for pecular case where token is a string of dashes */ - if (strncmp(tok, "--------------------", 20) == 0) - return(*status = BAD_KEYCHAR); - - if (tok[0] == '-') /* is there a leading minus sign? */ - { - /* first token is name of keyword to be deleted or renamed */ - *hdtype = -1; - tok++; - len = strspn(tok, " "); /* no. of spaces before keyword */ - tok += len; - if (len < 8) /* not a blank name? */ - { - len = strcspn(tok, " ="); /* length of name */ - if (len >= FLEN_KEYWORD) - return(*status = BAD_KEYCHAR); - - strncat(card, tok, len); - - /* - The HIERARCH convention supports non-standard characters - in the keyword name, so don't always convert to upper case or - abort if there are illegal characters in the name or if the - name is greater than 8 characters long. - */ - - if (len < 9) /* this is possibly a normal FITS keyword name */ - { - ffupch(card); - tstatus = 0; - if (fftkey(card, &tstatus) > 0) - { - /* name contained non-standard characters, so reset */ - card[0] = '\0'; - strncat(card, tok, len); - } - } - - tok += len; - } - - /* second token, if present, is the new name for the keyword */ - - len = strspn(tok, " "); /* no. of spaces before next token */ - tok += len; - - if (tok[0] == '\0' || tok[0] == '=') - return(*status); /* no second token */ - - *hdtype = -2; - len = strcspn(tok, " "); /* length of new name */ - if (len > 40) /* name has to fit on columns 41-80 of card */ - return(*status = BAD_KEYCHAR); - - /* copy the new name to card + 40; This is awkward, */ - /* but is consistent with the way the Fortran FITSIO works */ - strcat(card," "); - strncpy(&card[40], tok, len+1); /* copy len+1 to get terminator */ - - /* - The HIERARCH convention supports non-standard characters - in the keyword name, so don't always convert to upper case or - abort if there are illegal characters in the name or if the - name is greater than 8 characters long. - */ - - if (len < 9) /* this is possibly a normal FITS keyword name */ - { - ffupch(&card[40]); - tstatus = 0; - if (fftkey(&card[40], &tstatus) > 0) - { - /* name contained non-standard characters, so reset */ - strncpy(&card[40], tok, len); - } - } - } - else /* no negative sign at beginning of template */ - { - /* get the keyword name token */ - - len = strcspn(tok, " ="); /* length of keyword name */ - if (len >= FLEN_KEYWORD) - return(*status = BAD_KEYCHAR); - - strncat(keyname, tok, len); - - /* - The HIERARCH convention supports non-standard characters - in the keyword name, so don't always convert to upper case or - abort if there are illegal characters in the name or if the - name is greater than 8 characters long. - */ - - if (len < 9) /* this is possibly a normal FITS keyword name */ - { - ffupch(keyname); - tstatus = 0; - if (fftkey(keyname, &tstatus) > 0) - { - /* name contained non-standard characters, so reset */ - keyname[0] = '\0'; - strncat(keyname, tok, len); - } - } - - if (!FSTRCMP(keyname, "END") ) - { - strcpy(card, "END"); - *hdtype = 2; - return(*status); - } - - tok += len; /* move token pointer to end of the keyword */ - - if (!FSTRCMP(keyname, "COMMENT") || !FSTRCMP(keyname, "HISTORY") - || !FSTRCMP(keyname, "HIERARCH") ) - { - *hdtype = 1; /* simply append COMMENT and HISTORY keywords */ - strcpy(card, keyname); - strncat(card, tok, 73); - return(*status); - } - - /* look for the value token */ - len = strspn(tok, " ="); /* spaces or = between name and value */ - tok += len; - - if (*tok == '\'') /* is value enclosed in quotes? */ - { - more = TRUE; - while (more) - { - tok++; /* temporarily move past the quote char */ - len = strcspn(tok, "'"); /* length of quoted string */ - tok--; - strncat(value, tok, len + 2); - - tok += len + 1; - if (tok[0] != '\'') /* check there is a closing quote */ - return(*status = NO_QUOTE); - - tok++; - if (tok[0] != '\'') /* 2 quote chars = literal quote */ - more = FALSE; - } - } - else if (*tok == '/' || *tok == '\0') /* There is no value */ - { - strcat(value, " "); - } - else /* not a quoted string value */ - { - len = strcspn(tok, " /"); /* length of value string */ - - strncat(value, tok, len); - if (!( (tok[0] == 'T' || tok[0] == 'F') && - (tok[1] == ' ' || tok[1] == '/' || tok[1] == '\0') )) - { - /* not a logical value */ - - dval = strtod(value, &suffix); /* try to read value as number */ - - if (*suffix != '\0' && *suffix != ' ' && *suffix != '/') - { - /* value not recognized as a number; might be because it */ - /* contains a 'd' or 'D' exponent character */ - strcpy(tvalue, value); - if ((loc = strchr(tvalue, 'D'))) - { - *loc = 'E'; /* replace D's with E's. */ - dval = strtod(tvalue, &suffix); /* read value again */ - } - else if ((loc = strchr(tvalue, 'd'))) - { - *loc = 'E'; /* replace d's with E's. */ - dval = strtod(tvalue, &suffix); /* read value again */ - } - else if ((loc = strchr(tvalue, '.'))) - { - *loc = ','; /* replace period with a comma */ - dval = strtod(tvalue, &suffix); /* read value again */ - } - } - - if (*suffix != '\0' && *suffix != ' ' && *suffix != '/') - { - /* value is not a number; must enclose it in quotes */ - strcpy(value, "'"); - strncat(value, tok, len); - strcat(value, "'"); - - /* the following useless statement stops the compiler warning */ - /* that dval is not used anywhere */ - if (dval == 0.) - len += (int) dval; - } - else - { - /* value is a number; convert any 'e' to 'E', or 'd' to 'D' */ - loc = strchr(value, 'e'); - if (loc) - { - *loc = 'E'; - } - else - { - loc = strchr(value, 'd'); - if (loc) - { - *loc = 'D'; - } - } - } - } - tok += len; - } - - len = strspn(tok, " /"); /* no. of spaces between value and comment */ - tok += len; - - vlen = strlen(value); - if (vlen > 0 && vlen < 10 && value[0] == '\'') - { - /* pad quoted string with blanks so it is at least 8 chars long */ - value[vlen-1] = '\0'; - strncat(value, " ", 10 - vlen); - strcat(&value[9], "'"); - } - - /* get the comment string */ - strncat(comment, tok, 70); - - /* construct the complete FITS header card */ - ffmkky(keyname, value, comment, card, status); - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_translate_keyword( - char *inrec, /* I - input string */ - char *outrec, /* O - output converted string, or */ - /* a null string if input does not */ - /* match any of the patterns */ - char *patterns[][2],/* I - pointer to input / output string */ - /* templates */ - int npat, /* I - number of templates passed */ - int n_value, /* I - base 'n' template value of interest */ - int n_offset, /* I - offset to be applied to the 'n' */ - /* value in the output string */ - int n_range, /* I - controls range of 'n' template */ - /* values of interest (-1,0, or +1) */ - int *pat_num, /* O - matched pattern number (0 based) or -1 */ - int *i, /* O - value of i, if any, else 0 */ - int *j, /* O - value of j, if any, else 0 */ - int *m, /* O - value of m, if any, else 0 */ - int *n, /* O - value of n, if any, else 0 */ - - int *status) /* IO - error status */ - -/* - -Translate a keyword name to a new name, based on a set of patterns. -The user passes an array of patterns to be matched. Input pattern -number i is pattern[i][0], and output pattern number i is -pattern[i][1]. Keywords are matched against the input patterns. If a -match is found then the keyword is re-written according to the output -pattern. - -Order is important. The first match is accepted. The fastest match -will be made when templates with the same first character are grouped -together. - -Several characters have special meanings: - - i,j - single digits, preserved in output template - n - column number of one or more digits, preserved in output template - m - generic number of one or more digits, preserved in output template - a - coordinate designator, preserved in output template - # - number of one or more digits - ? - any character - * - only allowed in first character position, to match all - keywords; only useful as last pattern in the list - -i, j, n, and m are returned by the routine. - -For example, the input pattern "iCTYPn" will match "1CTYP5" (if n_value -is 5); the output pattern "CTYPEi" will be re-written as "CTYPE1". -Notice that "i" is preserved. - -The following output patterns are special - -Special output pattern characters: - - "-" - do not copy a keyword that matches the corresponding input pattern - - "+" - copy the input unchanged - -The inrec string could be just the 8-char keyword name, or the entire -80-char header record. Characters 9 = 80 in the input string simply get -appended to the translated keyword name. - -If n_range = 0, then only keywords with 'n' equal to n_value will be -considered as a pattern match. If n_range = +1, then all values of -'n' greater than or equal to n_value will be a match, and if -1, -then values of 'n' less than or equal to n_value will match. - - This routine was written by Craig Markwardt, GSFC -*/ - -{ - int i1 = 0, j1 = 0, n1 = 0, m1 = 0; - int fac; - char a = ' '; - char oldp; - char c, s; - int ip, ic, pat, pass = 0, firstfail; - char *spat; - - if (*status > 0) - return(*status); - if ((inrec == 0) || (outrec == 0)) - return (*status = NULL_INPUT_PTR); - - *outrec = '\0'; -/* - if (*inrec == '\0') return 0; -*/ - - if (*inrec == '\0') /* expand to full 8 char blank keyword name */ - strcpy(inrec, " "); - - oldp = '\0'; - firstfail = 0; - - /* ===== Pattern match stage */ - for (pat=0; pat < npat; pat++) { - spat = patterns[pat][0]; - - i1 = 0; j1 = 0; m1 = -1; n1 = -1; a = ' '; /* Initialize the place-holders */ - pass = 0; - - /* Pass the wildcard pattern */ - if (spat[0] == '*') { - pass = 1; - break; - } - - /* Optimization: if we have seen this initial pattern character before, - then it must have failed, and we can skip the pattern */ - if (firstfail && spat[0] == oldp) continue; - oldp = spat[0]; - - /* - ip = index of pattern character being matched - ic = index of keyname character being matched - firstfail = 1 if we fail on the first characteor (0=not) - */ - - for (ip=0, ic=0, firstfail=1; - (spat[ip]) && (ic < 8); - ip++, ic++, firstfail=0) { - c = inrec[ic]; - s = spat[ip]; - - if (s == 'i') { - /* Special pattern: 'i' placeholder */ - if (isdigit(c)) { i1 = c - '0'; pass = 1;} - } else if (s == 'j') { - /* Special pattern: 'j' placeholder */ - if (isdigit(c)) { j1 = c - '0'; pass = 1;} - } else if ((s == 'n')||(s == 'm')||(s == '#')) { - /* Special patterns: multi-digit number */ - int val = 0; - pass = 0; - if (isdigit(c)) { - pass = 1; /* NOTE, could fail below */ - - /* Parse decimal number */ - while (ic<8 && isdigit(c)) { - val = val*10 + (c - '0'); - ic++; c = inrec[ic]; - } - ic--; c = inrec[ic]; - - if (s == 'n') { - - /* Is it a column number? */ - if ( val >= 1 && val <= 999 && /* Row range check */ - (((n_range == 0) && (val == n_value)) || /* Strict equality */ - ((n_range == -1) && (val <= n_value)) || /* n <= n_value */ - ((n_range == +1) && (val >= n_value))) ) { /* n >= n_value */ - n1 = val; - } else { - pass = 0; - } - } else if (s == 'm') { - - /* Generic number */ - m1 = val; - } - } - } else if (s == 'a') { - /* Special pattern: coordinate designator */ - if (isupper(c) || c == ' ') { a = c; pass = 1;} - } else if (s == '?') { - /* Match any individual character */ - pass = 1; - } else if (c == s) { - /* Match a specific character */ - pass = 1; - } else { - /* FAIL */ - pass = 0; - } - if (!pass) break; - } - - /* Must pass to the end of the keyword. No partial matches allowed */ - if (pass && (ic >= 8 || inrec[ic] == ' ')) break; - } - - /* Transfer the pattern-matched numbers to the output parameters */ - if (i) { *i = i1; } - if (j) { *j = j1; } - if (n) { *n = n1; } - if (m) { *m = m1; } - if (pat_num) { *pat_num = pat; } - - /* ===== Keyword rewriting and output stage */ - spat = patterns[pat][1]; - - /* Return case: no match, or explicit deletion pattern */ - if (pass == 0 || spat[0] == '\0' || spat[0] == '-') return 0; - - /* A match: we start by copying the input record to the output */ - strcpy(outrec, inrec); - - /* Return case: return the input record unchanged */ - if (spat[0] == '+') return 0; - - - /* Final case: a new output pattern */ - for (ip=0, ic=0; spat[ip]; ip++, ic++) { - s = spat[ip]; - if (s == 'i') { - outrec[ic] = (i1+'0'); - } else if (s == 'j') { - outrec[ic] = (j1+'0'); - } else if (s == 'n') { - if (n1 == -1) { n1 = n_value; } - if (n1 > 0) { - n1 += n_offset; - for (fac = 1; (n1/fac) > 0; fac *= 10); - fac /= 10; - while(fac > 0) { - outrec[ic] = ((n1/fac) % 10) + '0'; - fac /= 10; - ic ++; - } - ic--; - } - } else if (s == 'm' && m1 >= 0) { - for (fac = 1; (m1/fac) > 0; fac *= 10); - fac /= 10; - while(fac > 0) { - outrec[ic] = ((m1/fac) % 10) + '0'; - fac /= 10; - ic ++; - } - ic --; - } else if (s == 'a') { - outrec[ic] = a; - } else { - outrec[ic] = s; - } - } - - /* Pad the keyword name with spaces */ - for ( ; ic<8; ic++) { outrec[ic] = ' '; } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_translate_keywords( - fitsfile *infptr, /* I - pointer to input HDU */ - fitsfile *outfptr, /* I - pointer to output HDU */ - int firstkey, /* I - first HDU record number to start with */ - char *patterns[][2],/* I - pointer to input / output keyword templates */ - int npat, /* I - number of templates passed */ - int n_value, /* I - base 'n' template value of interest */ - int n_offset, /* I - offset to be applied to the 'n' */ - /* value in the output string */ - int n_range, /* I - controls range of 'n' template */ - /* values of interest (-1,0, or +1) */ - int *status) /* IO - error status */ -/* - Copy relevant keywords from the table header into the newly - created primary array header. Convert names of keywords where - appropriate. See fits_translate_keyword() for the definitions. - - Translation begins at header record number 'firstkey', and - continues to the end of the header. - - This routine was written by Craig Markwardt, GSFC -*/ -{ - int nrec, nkeys, nmore; - char rec[FLEN_CARD]; - int i = 0, j = 0, n = 0, m = 0; - int pat_num = 0, maxchr, ii; - char outrec[FLEN_CARD]; - - if (*status > 0) - return(*status); - - ffghsp(infptr, &nkeys, &nmore, status); /* get number of keywords */ - - for (nrec = firstkey; nrec <= nkeys; nrec++) { - outrec[0] = '\0'; - - ffgrec(infptr, nrec, rec, status); - - /* silently overlook any illegal ASCII characters in the value or */ - /* comment fields of the record. It is usually not appropriate to */ - /* abort the process because of this minor transgression of the FITS rules. */ - /* Set the offending character to a blank */ - - maxchr = strlen(rec); - for (ii = 8; ii < maxchr; ii++) - { - if (rec[ii] < 32 || rec[ii] > 126) - rec[ii] = ' '; - } - - fits_translate_keyword(rec, outrec, patterns, npat, - n_value, n_offset, n_range, - &pat_num, &i, &j, &m, &n, status); - - if (outrec[0]) { - ffprec(outfptr, outrec, status); /* copy the keyword */ - rec[8] = 0; outrec[8] = 0; - } else { - rec[8] = 0; outrec[8] = 0; - } - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_copy_pixlist2image( - fitsfile *infptr, /* I - pointer to input HDU */ - fitsfile *outfptr, /* I - pointer to output HDU */ - int firstkey, /* I - first HDU record number to start with */ - int naxis, /* I - number of axes in the image */ - int *colnum, /* I - numbers of the columns to be binned */ - int *status) /* IO - error status */ -/* - Copy relevant keywords from the pixel list table header into a newly - created primary array header. Convert names of keywords where - appropriate. See fits_translate_pixkeyword() for the definitions. - - Translation begins at header record number 'firstkey', and - continues to the end of the header. -*/ -{ - int nrec, nkeys, nmore; - char rec[FLEN_CARD], outrec[FLEN_CARD]; - int pat_num = 0, npat; - int iret, jret, nret, mret, lret; - char *patterns[][2] = { - - {"TCTYPn", "CTYPEn" }, - {"TCTYna", "CTYPEna" }, - {"TCUNIn", "CUNITn" }, - {"TCUNna", "CUNITna" }, - {"TCRVLn", "CRVALn" }, - {"TCRVna", "CRVALna" }, - {"TCDLTn", "CDELTn" }, - {"TCDEna", "CDELTna" }, - {"TCRPXn", "CRPIXn" }, - {"TCRPna", "CRPIXna" }, - {"TCROTn", "CROTAn" }, - {"TPn_ma", "PCn_ma" }, - {"TPCn_m", "PCn_ma" }, - {"TCn_ma", "CDn_ma" }, - {"TCDn_m", "CDn_ma" }, - {"TVn_la", "PVn_la" }, - {"TPVn_l", "PVn_la" }, - {"TSn_la", "PSn_la" }, - {"TPSn_l", "PSn_la" }, - {"TWCSna", "WCSNAMEa" }, - {"TCNAna", "CNAMEna" }, - {"TCRDna", "CRDERna" }, - {"TCSYna", "CSYERna" }, - {"LONPna", "LONPOLEa" }, - {"LATPna", "LATPOLEa" }, - {"EQUIna", "EQUINOXa" }, - {"MJDOBn", "MJD-OBS" }, - {"MJDAn", "MJD-AVG" }, - {"DAVGn", "DATE-AVG" }, - {"RADEna", "RADESYSa" }, - {"RFRQna", "RESTFRQa" }, - {"RWAVna", "RESTWAVa" }, - {"SPECna", "SPECSYSa" }, - {"SOBSna", "SSYSOBSa" }, - {"SSRCna", "SSYSSRCa" }, - - /* preserve common keywords */ - {"LONPOLEa", "+" }, - {"LATPOLEa", "+" }, - {"EQUINOXa", "+" }, - {"EPOCH", "+" }, - {"MJD-????", "+" }, - {"DATE????", "+" }, - {"TIME????", "+" }, - {"RADESYSa", "+" }, - {"RADECSYS", "+" }, - {"TELESCOP", "+" }, - {"INSTRUME", "+" }, - {"OBSERVER", "+" }, - {"OBJECT", "+" }, - - /* Delete general table column keywords */ - {"XTENSION", "-" }, - {"BITPIX", "-" }, - {"NAXIS", "-" }, - {"NAXISi", "-" }, - {"PCOUNT", "-" }, - {"GCOUNT", "-" }, - {"TFIELDS", "-" }, - - {"TDIM#", "-" }, - {"THEAP", "-" }, - {"EXTNAME", "-" }, - {"EXTVER", "-" }, - {"EXTLEVEL","-" }, - {"CHECKSUM","-" }, - {"DATASUM", "-" }, - {"NAXLEN", "-" }, - {"AXLEN#", "-" }, - {"CPREF", "-" }, - - /* Delete table keywords related to other columns */ - {"T????#a", "-" }, - {"TC??#a", "-" }, - {"T??#_#", "-" }, - {"TWCS#a", "-" }, - - {"LONP#a", "-" }, - {"LATP#a", "-" }, - {"EQUI#a", "-" }, - {"MJDOB#", "-" }, - {"MJDA#", "-" }, - {"RADE#a", "-" }, - {"DAVG#", "-" }, - - {"iCTYP#", "-" }, - {"iCTY#a", "-" }, - {"iCUNI#", "-" }, - {"iCUN#a", "-" }, - {"iCRVL#", "-" }, - {"iCDLT#", "-" }, - {"iCRPX#", "-" }, - {"iCTY#a", "-" }, - {"iCUN#a", "-" }, - {"iCRV#a", "-" }, - {"iCDE#a", "-" }, - {"iCRP#a", "-" }, - {"ijPC#a", "-" }, - {"ijCD#a", "-" }, - {"iV#_#a", "-" }, - {"iS#_#a", "-" }, - {"iCRD#a", "-" }, - {"iCSY#a", "-" }, - {"iCROT#", "-" }, - {"WCAX#a", "-" }, - {"WCSN#a", "-" }, - {"iCNA#a", "-" }, - - {"*", "+" }}; /* copy all other keywords */ - - if (*status > 0) - return(*status); - - npat = sizeof(patterns)/sizeof(patterns[0][0])/2; - - ffghsp(infptr, &nkeys, &nmore, status); /* get number of keywords */ - - for (nrec = firstkey; nrec <= nkeys; nrec++) { - outrec[0] = '\0'; - - ffgrec(infptr, nrec, rec, status); - - fits_translate_pixkeyword(rec, outrec, patterns, npat, - naxis, colnum, - &pat_num, &iret, &jret, &nret, &mret, &lret, status); - - if (outrec[0]) { - ffprec(outfptr, outrec, status); /* copy the keyword */ - } - - rec[8] = 0; outrec[8] = 0; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_translate_pixkeyword( - char *inrec, /* I - input string */ - char *outrec, /* O - output converted string, or */ - /* a null string if input does not */ - /* match any of the patterns */ - char *patterns[][2],/* I - pointer to input / output string */ - /* templates */ - int npat, /* I - number of templates passed */ - int naxis, /* I - number of columns to be binned */ - int *colnum, /* I - numbers of the columns to be binned */ - int *pat_num, /* O - matched pattern number (0 based) or -1 */ - int *i, - int *j, - int *n, - int *m, - int *l, - int *status) /* IO - error status */ - -/* - -Translate a keyword name to a new name, based on a set of patterns. -The user passes an array of patterns to be matched. Input pattern -number i is pattern[i][0], and output pattern number i is -pattern[i][1]. Keywords are matched against the input patterns. If a -match is found then the keyword is re-written according to the output -pattern. - -Order is important. The first match is accepted. The fastest match -will be made when templates with the same first character are grouped -together. - -Several characters have special meanings: - - i,j - single digits, preserved in output template - n, m - column number of one or more digits, preserved in output template - k - generic number of one or more digits, preserved in output template - a - coordinate designator, preserved in output template - # - number of one or more digits - ? - any character - * - only allowed in first character position, to match all - keywords; only useful as last pattern in the list - -i, j, n, and m are returned by the routine. - -For example, the input pattern "iCTYPn" will match "1CTYP5" (if n_value -is 5); the output pattern "CTYPEi" will be re-written as "CTYPE1". -Notice that "i" is preserved. - -The following output patterns are special - -Special output pattern characters: - - "-" - do not copy a keyword that matches the corresponding input pattern - - "+" - copy the input unchanged - -The inrec string could be just the 8-char keyword name, or the entire -80-char header record. Characters 9 = 80 in the input string simply get -appended to the translated keyword name. - -If n_range = 0, then only keywords with 'n' equal to n_value will be -considered as a pattern match. If n_range = +1, then all values of -'n' greater than or equal to n_value will be a match, and if -1, -then values of 'n' less than or equal to n_value will match. - -*/ - -{ - int i1 = 0, j1 = 0, val; - int fac, nval = 0, mval = 0, lval = 0; - char a = ' '; - char oldp; - char c, s; - int ip, ic, pat, pass = 0, firstfail; - char *spat; - - if (*status > 0) - return(*status); - - if ((inrec == 0) || (outrec == 0)) - return (*status = NULL_INPUT_PTR); - - *outrec = '\0'; - if (*inrec == '\0') return 0; - - oldp = '\0'; - firstfail = 0; - - /* ===== Pattern match stage */ - for (pat=0; pat < npat; pat++) { - - spat = patterns[pat][0]; - - i1 = 0; j1 = 0; a = ' '; /* Initialize the place-holders */ - pass = 0; - - /* Pass the wildcard pattern */ - if (spat[0] == '*') { - pass = 1; - break; - } - - /* Optimization: if we have seen this initial pattern character before, - then it must have failed, and we can skip the pattern */ - if (firstfail && spat[0] == oldp) continue; - oldp = spat[0]; - - /* - ip = index of pattern character being matched - ic = index of keyname character being matched - firstfail = 1 if we fail on the first characteor (0=not) - */ - - for (ip=0, ic=0, firstfail=1; - (spat[ip]) && (ic < 8); - ip++, ic++, firstfail=0) { - c = inrec[ic]; - s = spat[ip]; - - if (s == 'i') { - /* Special pattern: 'i' placeholder */ - if (isdigit(c)) { i1 = c - '0'; pass = 1;} - } else if (s == 'j') { - /* Special pattern: 'j' placeholder */ - if (isdigit(c)) { j1 = c - '0'; pass = 1;} - } else if ((s == 'n')||(s == 'm')||(s == 'l')||(s == '#')) { - /* Special patterns: multi-digit number */ - val = 0; - pass = 0; - if (isdigit(c)) { - pass = 1; /* NOTE, could fail below */ - - /* Parse decimal number */ - while (ic<8 && isdigit(c)) { - val = val*10 + (c - '0'); - ic++; c = inrec[ic]; - } - ic--; c = inrec[ic]; - - if (s == 'n' || s == 'm') { - - /* Is it a column number? */ - if ( val >= 1 && val <= 999) { - - if (val == colnum[0]) - val = 1; - else if (val == colnum[1]) - val = 2; - else if (val == colnum[2]) - val = 3; - else if (val == colnum[3]) - val = 4; - else { - pass = 0; - val = 0; - } - - if (s == 'n') - nval = val; - else - mval = val; - - } else { - pass = 0; - } - } else if (s == 'l') { - /* Generic number */ - lval = val; - } - } - } else if (s == 'a') { - /* Special pattern: coordinate designator */ - if (isupper(c) || c == ' ') { a = c; pass = 1;} - } else if (s == '?') { - /* Match any individual character */ - pass = 1; - } else if (c == s) { - /* Match a specific character */ - pass = 1; - } else { - /* FAIL */ - pass = 0; - } - - if (!pass) break; - } - - - /* Must pass to the end of the keyword. No partial matches allowed */ - if (pass && (ic >= 8 || inrec[ic] == ' ')) break; - } - - - /* Transfer the pattern-matched numbers to the output parameters */ - if (i) { *i = i1; } - if (j) { *j = j1; } - if (n) { *n = nval; } - if (m) { *m = mval; } - if (l) { *l = lval; } - if (pat_num) { *pat_num = pat; } - - /* ===== Keyword rewriting and output stage */ - spat = patterns[pat][1]; - - /* Return case: no match, or explicit deletion pattern */ - if (pass == 0 || spat[0] == '\0' || spat[0] == '-') return 0; - - /* A match: we start by copying the input record to the output */ - strcpy(outrec, inrec); - - /* Return case: return the input record unchanged */ - if (spat[0] == '+') return 0; - - /* Final case: a new output pattern */ - for (ip=0, ic=0; spat[ip]; ip++, ic++) { - s = spat[ip]; - if (s == 'i') { - outrec[ic] = (i1+'0'); - } else if (s == 'j') { - outrec[ic] = (j1+'0'); - } else if (s == 'n' && nval > 0) { - for (fac = 1; (nval/fac) > 0; fac *= 10); - fac /= 10; - while(fac > 0) { - outrec[ic] = ((nval/fac) % 10) + '0'; - fac /= 10; - ic ++; - } - ic--; - } else if (s == 'm' && mval > 0) { - for (fac = 1; (mval/fac) > 0; fac *= 10); - fac /= 10; - while(fac > 0) { - outrec[ic] = ((mval/fac) % 10) + '0'; - fac /= 10; - ic ++; - } - ic--; - } else if (s == 'l' && lval >= 0) { - for (fac = 1; (lval/fac) > 0; fac *= 10); - fac /= 10; - while(fac > 0) { - outrec[ic] = ((lval/fac) % 10) + '0'; - fac /= 10; - ic ++; - } - ic --; - } else if (s == 'a') { - outrec[ic] = a; - } else { - outrec[ic] = s; - } - } - - /* Pad the keyword name with spaces */ - for ( ; ic<8; ic++) { outrec[ic] = ' '; } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffasfm(char *tform, /* I - format code from the TFORMn keyword */ - int *dtcode, /* O - numerical datatype code */ - long *twidth, /* O - width of the field, in chars */ - int *decimals, /* O - number of decimal places (F, E, D format) */ - int *status) /* IO - error status */ -{ -/* - parse the ASCII table TFORM column format to determine the data - type, the field width, and number of decimal places (if relevant) -*/ - int ii, datacode; - long longval, width; - float fwidth; - char *form, temp[FLEN_VALUE], message[FLEN_ERRMSG]; - - if (*status > 0) - return(*status); - - if (dtcode) - *dtcode = 0; - - if (twidth) - *twidth = 0; - - if (decimals) - *decimals = 0; - - ii = 0; - while (tform[ii] != 0 && tform[ii] == ' ') /* find first non-blank char */ - ii++; - - strcpy(temp, &tform[ii]); /* copy format string */ - ffupch(temp); /* make sure it is in upper case */ - form = temp; /* point to start of format string */ - - - if (form[0] == 0) - { - ffpmsg("Error: ASCII table TFORM code is blank"); - return(*status = BAD_TFORM); - } - - /*-----------------------------------------------*/ - /* determine default datatype code */ - /*-----------------------------------------------*/ - if (form[0] == 'A') - datacode = TSTRING; - else if (form[0] == 'I') - datacode = TLONG; - else if (form[0] == 'F') - datacode = TFLOAT; - else if (form[0] == 'E') - datacode = TFLOAT; - else if (form[0] == 'D') - datacode = TDOUBLE; - else - { - sprintf(message, - "Illegal ASCII table TFORMn datatype: \'%s\'", tform); - ffpmsg(message); - return(*status = BAD_TFORM_DTYPE); - } - - if (dtcode) - *dtcode = datacode; - - form++; /* point to the start of field width */ - - if (datacode == TSTRING || datacode == TLONG) - { - /*-----------------------------------------------*/ - /* A or I data formats: */ - /*-----------------------------------------------*/ - - if (ffc2ii(form, &width, status) <= 0) /* read the width field */ - { - if (width <= 0) - { - width = 0; - *status = BAD_TFORM; - } - else - { - /* set to shorter precision if I4 or less */ - if (width <= 4 && datacode == TLONG) - datacode = TSHORT; - } - } - } - else - { - /*-----------------------------------------------*/ - /* F, E or D data formats: */ - /*-----------------------------------------------*/ - - if (ffc2rr(form, &fwidth, status) <= 0) /* read ww.dd width field */ - { - if (fwidth <= 0.) - *status = BAD_TFORM; - else - { - width = (long) fwidth; /* convert from float to long */ - - if (width > 7 && *temp == 'F') - datacode = TDOUBLE; /* type double if >7 digits */ - - if (width < 10) - form = form + 1; /* skip 1 digit */ - else - form = form + 2; /* skip 2 digits */ - - if (form[0] == '.') /* should be a decimal point here */ - { - form++; /* point to start of decimals field */ - - if (ffc2ii(form, &longval, status) <= 0) /* read decimals */ - { - if (decimals) - *decimals = longval; /* long to short convertion */ - - if (longval >= width) /* width < no. of decimals */ - *status = BAD_TFORM; - - if (longval > 6 && *temp == 'E') - datacode = TDOUBLE; /* type double if >6 digits */ - } - } - - } - } - } - if (*status > 0) - { - *status = BAD_TFORM; - sprintf(message,"Illegal ASCII table TFORMn code: \'%s\'", tform); - ffpmsg(message); - } - - if (dtcode) - *dtcode = datacode; - - if (twidth) - *twidth = width; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffbnfm(char *tform, /* I - format code from the TFORMn keyword */ - int *dtcode, /* O - numerical datatype code */ - long *trepeat, /* O - repeat count of the field */ - long *twidth, /* O - width of the field, in chars */ - int *status) /* IO - error status */ -{ -/* - parse the binary table TFORM column format to determine the data - type, repeat count, and the field width (if it is an ASCII (A) field) -*/ - size_t ii, nchar; - int datacode, variable, iread; - long width, repeat; - char *form, temp[FLEN_VALUE], message[FLEN_ERRMSG]; - - if (*status > 0) - return(*status); - - if (dtcode) - *dtcode = 0; - - if (trepeat) - *trepeat = 0; - - if (twidth) - *twidth = 0; - - nchar = strlen(tform); - - for (ii = 0; ii < nchar; ii++) - { - if (tform[ii] != ' ') /* find first non-space char */ - break; - } - - if (ii == nchar) - { - ffpmsg("Error: binary table TFORM code is blank (ffbnfm)."); - return(*status = BAD_TFORM); - } - - strcpy(temp, &tform[ii]); /* copy format string */ - ffupch(temp); /* make sure it is in upper case */ - form = temp; /* point to start of format string */ - - /*-----------------------------------------------*/ - /* get the repeat count */ - /*-----------------------------------------------*/ - - ii = 0; - while(isdigit((int) form[ii])) - ii++; /* look for leading digits in the field */ - - if (ii == 0) - repeat = 1; /* no explicit repeat count */ - else - sscanf(form,"%ld", &repeat); /* read repeat count */ - - /*-----------------------------------------------*/ - /* determine datatype code */ - /*-----------------------------------------------*/ - - form = form + ii; /* skip over the repeat field */ - - if (form[0] == 'P' || form[0] == 'Q') - { - variable = 1; /* this is a variable length column */ -/* repeat = 1; */ /* disregard any other repeat value */ - form++; /* move to the next data type code char */ - } - else - variable = 0; - - if (form[0] == 'U') /* internal code to signify unsigned integer */ - { - datacode = TUSHORT; - width = 2; - } - else if (form[0] == 'I') - { - datacode = TSHORT; - width = 2; - } - else if (form[0] == 'V') /* internal code to signify unsigned integer */ - { - datacode = TULONG; - width = 4; - } - else if (form[0] == 'J') - { - datacode = TLONG; - width = 4; - } - else if (form[0] == 'K') - { - datacode = TLONGLONG; - width = 8; - } - else if (form[0] == 'E') - { - datacode = TFLOAT; - width = 4; - } - else if (form[0] == 'D') - { - datacode = TDOUBLE; - width = 8; - } - else if (form[0] == 'A') - { - datacode = TSTRING; - - /* - the following code is used to support the non-standard - datatype of the form rAw where r = total width of the field - and w = width of fixed-length substrings within the field. - */ - iread = 0; - if (form[1] != 0) - { - if (form[1] == '(' ) /* skip parenthesis around */ - form++; /* variable length column width */ - - iread = sscanf(&form[1],"%ld", &width); - } - - if (iread != 1 || (!variable && (width > repeat)) ) - width = repeat; - - } - else if (form[0] == 'L') - { - datacode = TLOGICAL; - width = 1; - } - else if (form[0] == 'X') - { - datacode = TBIT; - width = 1; - } - else if (form[0] == 'B') - { - datacode = TBYTE; - width = 1; - } - else if (form[0] == 'S') /* internal code to signify signed byte */ - { - datacode = TSBYTE; - width = 1; - } - else if (form[0] == 'C') - { - datacode = TCOMPLEX; - width = 8; - } - else if (form[0] == 'M') - { - datacode = TDBLCOMPLEX; - width = 16; - } - else - { - sprintf(message, - "Illegal binary table TFORMn datatype: \'%s\' ", tform); - ffpmsg(message); - return(*status = BAD_TFORM_DTYPE); - } - - if (variable) - datacode = datacode * (-1); /* flag variable cols w/ neg type code */ - - if (dtcode) - *dtcode = datacode; - - if (trepeat) - *trepeat = repeat; - - if (twidth) - *twidth = width; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffbnfmll(char *tform, /* I - format code from the TFORMn keyword */ - int *dtcode, /* O - numerical datatype code */ - LONGLONG *trepeat, /* O - repeat count of the field */ - long *twidth, /* O - width of the field, in chars */ - int *status) /* IO - error status */ -{ -/* - parse the binary table TFORM column format to determine the data - type, repeat count, and the field width (if it is an ASCII (A) field) -*/ - size_t ii, nchar; - int datacode, variable, iread; - long width; - LONGLONG repeat; - char *form, temp[FLEN_VALUE], message[FLEN_ERRMSG]; - double drepeat; - - if (*status > 0) - return(*status); - - if (dtcode) - *dtcode = 0; - - if (trepeat) - *trepeat = 0; - - if (twidth) - *twidth = 0; - - nchar = strlen(tform); - - for (ii = 0; ii < nchar; ii++) - { - if (tform[ii] != ' ') /* find first non-space char */ - break; - } - - if (ii == nchar) - { - ffpmsg("Error: binary table TFORM code is blank (ffbnfmll)."); - return(*status = BAD_TFORM); - } - - strcpy(temp, &tform[ii]); /* copy format string */ - ffupch(temp); /* make sure it is in upper case */ - form = temp; /* point to start of format string */ - - /*-----------------------------------------------*/ - /* get the repeat count */ - /*-----------------------------------------------*/ - - ii = 0; - while(isdigit((int) form[ii])) - ii++; /* look for leading digits in the field */ - - if (ii == 0) - repeat = 1; /* no explicit repeat count */ - else { - /* read repeat count */ - - /* print as double, because the string-to-64-bit int conversion */ - /* character is platform dependent (%lld, %ld, %I64d) */ - - sscanf(form,"%lf", &drepeat); - repeat = (LONGLONG) (drepeat + 0.1); - } - /*-----------------------------------------------*/ - /* determine datatype code */ - /*-----------------------------------------------*/ - - form = form + ii; /* skip over the repeat field */ - - if (form[0] == 'P' || form[0] == 'Q') - { - variable = 1; /* this is a variable length column */ -/* repeat = 1; */ /* disregard any other repeat value */ - form++; /* move to the next data type code char */ - } - else - variable = 0; - - if (form[0] == 'U') /* internal code to signify unsigned integer */ - { - datacode = TUSHORT; - width = 2; - } - else if (form[0] == 'I') - { - datacode = TSHORT; - width = 2; - } - else if (form[0] == 'V') /* internal code to signify unsigned integer */ - { - datacode = TULONG; - width = 4; - } - else if (form[0] == 'J') - { - datacode = TLONG; - width = 4; - } - else if (form[0] == 'K') - { - datacode = TLONGLONG; - width = 8; - } - else if (form[0] == 'E') - { - datacode = TFLOAT; - width = 4; - } - else if (form[0] == 'D') - { - datacode = TDOUBLE; - width = 8; - } - else if (form[0] == 'A') - { - datacode = TSTRING; - - /* - the following code is used to support the non-standard - datatype of the form rAw where r = total width of the field - and w = width of fixed-length substrings within the field. - */ - iread = 0; - if (form[1] != 0) - { - if (form[1] == '(' ) /* skip parenthesis around */ - form++; /* variable length column width */ - - iread = sscanf(&form[1],"%ld", &width); - } - - if (iread != 1 || (!variable && (width > repeat)) ) - width = (long) repeat; - - } - else if (form[0] == 'L') - { - datacode = TLOGICAL; - width = 1; - } - else if (form[0] == 'X') - { - datacode = TBIT; - width = 1; - } - else if (form[0] == 'B') - { - datacode = TBYTE; - width = 1; - } - else if (form[0] == 'S') /* internal code to signify signed byte */ - { - datacode = TSBYTE; - width = 1; - } - else if (form[0] == 'C') - { - datacode = TCOMPLEX; - width = 8; - } - else if (form[0] == 'M') - { - datacode = TDBLCOMPLEX; - width = 16; - } - else - { - sprintf(message, - "Illegal binary table TFORMn datatype: \'%s\' ", tform); - ffpmsg(message); - return(*status = BAD_TFORM_DTYPE); - } - - if (variable) - datacode = datacode * (-1); /* flag variable cols w/ neg type code */ - - if (dtcode) - *dtcode = datacode; - - if (trepeat) - *trepeat = repeat; - - if (twidth) - *twidth = width; - - return(*status); -} - -/*--------------------------------------------------------------------------*/ -void ffcfmt(char *tform, /* value of an ASCII table TFORMn keyword */ - char *cform) /* equivalent format code in C language syntax */ -/* - convert the FITS format string for an ASCII Table extension column into the - equivalent C format string that can be used in a printf statement, after - the values have been read as a double. -*/ -{ - int ii; - - cform[0] = '\0'; - ii = 0; - while (tform[ii] != 0 && tform[ii] == ' ') /* find first non-blank char */ - ii++; - - if (tform[ii] == 0) - return; /* input format string was blank */ - - cform[0] = '%'; /* start the format string */ - - strcpy(&cform[1], &tform[ii + 1]); /* append the width and decimal code */ - - - if (tform[ii] == 'A') - strcat(cform, "s"); - else if (tform[ii] == 'I') - strcat(cform, ".0f"); /* 0 precision to suppress decimal point */ - if (tform[ii] == 'F') - strcat(cform, "f"); - if (tform[ii] == 'E') - strcat(cform, "E"); - if (tform[ii] == 'D') - strcat(cform, "E"); - - return; -} -/*--------------------------------------------------------------------------*/ -void ffcdsp(char *tform, /* value of an ASCII table TFORMn keyword */ - char *cform) /* equivalent format code in C language syntax */ -/* - convert the FITS TDISPn display format into the equivalent C format - suitable for use in a printf statement. -*/ -{ - int ii; - - cform[0] = '\0'; - ii = 0; - while (tform[ii] != 0 && tform[ii] == ' ') /* find first non-blank char */ - ii++; - - if (tform[ii] == 0) - { - cform[0] = '\0'; - return; /* input format string was blank */ - } - - if (strchr(tform+ii, '%')) /* is there a % character in the string?? */ - { - cform[0] = '\0'; - return; /* illegal TFORM string (possibly even harmful) */ - } - - cform[0] = '%'; /* start the format string */ - - strcpy(&cform[1], &tform[ii + 1]); /* append the width and decimal code */ - - if (tform[ii] == 'A' || tform[ii] == 'a') - strcat(cform, "s"); - else if (tform[ii] == 'I' || tform[ii] == 'i') - strcat(cform, "d"); - else if (tform[ii] == 'O' || tform[ii] == 'o') - strcat(cform, "o"); - else if (tform[ii] == 'Z' || tform[ii] == 'z') - strcat(cform, "X"); - else if (tform[ii] == 'F' || tform[ii] == 'f') - strcat(cform, "f"); - else if (tform[ii] == 'E' || tform[ii] == 'e') - strcat(cform, "E"); - else if (tform[ii] == 'D' || tform[ii] == 'd') - strcat(cform, "E"); - else if (tform[ii] == 'G' || tform[ii] == 'g') - strcat(cform, "G"); - else - cform[0] = '\0'; /* unrecognized tform code */ - - return; -} -/*--------------------------------------------------------------------------*/ -int ffgcno( fitsfile *fptr, /* I - FITS file pionter */ - int casesen, /* I - case sensitive string comparison? 0=no */ - char *templt, /* I - input name of column (w/wildcards) */ - int *colnum, /* O - number of the named column; 1=first col */ - int *status) /* IO - error status */ -/* - Determine the column number corresponding to an input column name. - The first column of the table = column 1; - This supports the * and ? wild cards in the input template. -*/ -{ - char colname[FLEN_VALUE]; /* temporary string to hold column name */ - - ffgcnn(fptr, casesen, templt, colname, colnum, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgcnn( fitsfile *fptr, /* I - FITS file pointer */ - int casesen, /* I - case sensitive string comparison? 0=no */ - char *templt, /* I - input name of column (w/wildcards) */ - char *colname, /* O - full column name up to 68 + 1 chars long*/ - int *colnum, /* O - number of the named column; 1=first col */ - int *status) /* IO - error status */ -/* - Return the full column name and column number of the next column whose - TTYPEn keyword value matches the input template string. - The template may contain the * and ? wildcards. Status = 237 is - returned if the match is not unique. If so, one may call this routine - again with input status=237 to get the next match. A status value of - 219 is returned when there are no more matching columns. -*/ -{ - char errmsg[FLEN_ERRMSG]; - int tstatus, ii, founde, foundw, match, exact, unique; - long ivalue; - tcolumn *colptr; - - if (*status <= 0) - { - (fptr->Fptr)->startcol = 0; /* start search with first column */ - tstatus = 0; - } - else if (*status == COL_NOT_UNIQUE) /* start search from previous spot */ - { - tstatus = COL_NOT_UNIQUE; - *status = 0; - } - else - return(*status); /* bad input status value */ - - colname[0] = 0; /* initialize null return */ - *colnum = 0; - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header to get col struct */ - return(*status); - - colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ - colptr += ((fptr->Fptr)->startcol); /* offset to starting column */ - - founde = FALSE; /* initialize 'found exact match' flag */ - foundw = FALSE; /* initialize 'found wildcard match' flag */ - unique = FALSE; - - for (ii = (fptr->Fptr)->startcol; ii < (fptr->Fptr)->tfield; ii++, colptr++) - { - ffcmps(templt, colptr->ttype, casesen, &match, &exact); - if (match) - { - if (founde && exact) - { - /* warning: this is the second exact match we've found */ - /*reset pointer to first match so next search starts there */ - (fptr->Fptr)->startcol = *colnum; - return(*status = COL_NOT_UNIQUE); - } - else if (founde) /* a wildcard match */ - { - /* already found exact match so ignore this non-exact match */ - } - else if (exact) - { - /* this is the first exact match we have found, so save it. */ - strcpy(colname, colptr->ttype); - *colnum = ii + 1; - founde = TRUE; - } - else if (foundw) - { - /* we have already found a wild card match, so not unique */ - /* continue searching for other matches */ - unique = FALSE; - } - else - { - /* this is the first wild card match we've found. save it */ - strcpy(colname, colptr->ttype); - *colnum = ii + 1; - (fptr->Fptr)->startcol = *colnum; - foundw = TRUE; - unique = TRUE; - } - } - } - - /* OK, we've checked all the names now see if we got any matches */ - if (founde) - { - if (tstatus == COL_NOT_UNIQUE) /* we did find 1 exact match but */ - *status = COL_NOT_UNIQUE; /* there was a previous match too */ - } - else if (foundw) - { - /* found one or more wildcard matches; report error if not unique */ - if (!unique || tstatus == COL_NOT_UNIQUE) - *status = COL_NOT_UNIQUE; - } - else - { - /* didn't find a match; check if template is a positive integer */ - ffc2ii(templt, &ivalue, &tstatus); - if (tstatus == 0 && ivalue <= (fptr->Fptr)->tfield && ivalue > 0) - { - *colnum = ivalue; - - colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ - colptr += (ivalue - 1); /* offset to correct column */ - strcpy(colname, colptr->ttype); - } - else - { - *status = COL_NOT_FOUND; - if (tstatus != COL_NOT_UNIQUE) - { - sprintf(errmsg, "ffgcnn could not find column: %.45s", templt); - ffpmsg(errmsg); - } - } - } - - (fptr->Fptr)->startcol = *colnum; /* save pointer for next time */ - return(*status); -} -/*--------------------------------------------------------------------------*/ -void ffcmps(char *templt, /* I - input template (may have wildcards) */ - char *colname, /* I - full column name up to 68 + 1 chars long */ - int casesen, /* I - case sensitive string comparison? 1=yes */ - int *match, /* O - do template and colname match? 1=yes */ - int *exact) /* O - do strings exactly match, or wildcards */ -/* - compare the template to the string and test if they match. - The strings are limited to 68 characters or less (the max. length - of a FITS string keyword value. This routine reports whether - the two strings match and whether the match is exact or - involves wildcards. - - This algorithm is very similar to the way unix filename wildcards - work except that this first treats a wild card as a literal character - when looking for a match. If there is no literal match, then - it interpretes it as a wild card. So the template 'AB*DE' - is considered to be an exact rather than a wild card match to - the string 'AB*DE'. The '#' wild card in the template string will - match any consecutive string of decimal digits in the colname. - -*/ -{ - int ii, found, t1, s1, wildsearch = 0, tsave = 0, ssave = 0; - char temp[FLEN_VALUE], col[FLEN_VALUE]; - - *match = FALSE; - *exact = TRUE; - - strncpy(temp, templt, FLEN_VALUE); /* copy strings to work area */ - strncpy(col, colname, FLEN_VALUE); - temp[FLEN_VALUE - 1] = '\0'; /* make sure strings are terminated */ - col[FLEN_VALUE - 1] = '\0'; - - /* truncate trailing non-significant blanks */ - for (ii = strlen(temp) - 1; ii >= 0 && temp[ii] == ' '; ii--) - temp[ii] = '\0'; - - for (ii = strlen(col) - 1; ii >= 0 && col[ii] == ' '; ii--) - col[ii] = '\0'; - - if (!casesen) - { /* convert both strings to uppercase before comparison */ - ffupch(temp); - ffupch(col); - } - - if (!FSTRCMP(temp, col) ) - { - *match = TRUE; /* strings exactly match */ - return; - } - - *exact = FALSE; /* strings don't exactly match */ - - t1 = 0; /* start comparison with 1st char of each string */ - s1 = 0; - - while(1) /* compare corresponding chars in each string */ - { - if (temp[t1] == '\0' && col[s1] == '\0') - { - /* completely scanned both strings so they match */ - *match = TRUE; - return; - } - else if (temp[t1] == '\0') - { - if (wildsearch) - { - /* - the previous wildcard search may have been going down - a blind alley. Backtrack, and resume the wildcard - search with the next character in the string. - */ - t1 = tsave; - s1 = ssave + 1; - } - else - { - /* reached end of template string so they don't match */ - return; - } - } - else if (col[s1] == '\0') - { - /* reached end of other string; they match if the next */ - /* character in the template string is a '*' wild card */ - - if (temp[t1] == '*' && temp[t1 + 1] == '\0') - { - *match = TRUE; - } - - return; - } - - if (temp[t1] == col[s1] || (temp[t1] == '?') ) - { - s1++; /* corresponding chars in the 2 strings match */ - t1++; /* increment both pointers and loop back again */ - } - else if (temp[t1] == '#' && isdigit((int) col[s1]) ) - { - s1++; /* corresponding chars in the 2 strings match */ - t1++; /* increment both pointers */ - - /* find the end of the string of digits */ - while (isdigit((int) col[s1]) ) - s1++; - } - else if (temp[t1] == '*') - { - - /* save current string locations, in case we need to restart */ - wildsearch = 1; - tsave = t1; - ssave = s1; - - /* get next char from template and look for it in the col name */ - t1++; - if (temp[t1] == '\0' || temp[t1] == ' ') - { - /* reached end of template so strings match */ - *match = TRUE; - return; - } - - found = FALSE; - while (col[s1] && !found) - { - if (temp[t1] == col[s1]) - { - t1++; /* found matching characters; incre both pointers */ - s1++; /* and loop back to compare next chars */ - found = TRUE; - } - else - s1++; /* increment the column name pointer and try again */ - } - - if (!found) - { - return; /* hit end of column name and failed to find a match */ - } - } - else - { - if (wildsearch) - { - /* - the previous wildcard search may have been going down - a blind alley. Backtrack, and resume the wildcard - search with the next character in the string. - */ - t1 = tsave; - s1 = ssave + 1; - } - else - { - return; /* strings don't match */ - } - } - } -} -/*--------------------------------------------------------------------------*/ -int ffgtcl( fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number */ - int *typecode, /* O - datatype code (21 = short, etc) */ - long *repeat, /* O - repeat count of field */ - long *width, /* O - if ASCII, width of field or unit string */ - int *status) /* IO - error status */ -/* - Get Type of table column. - Returns the datatype code of the column, as well as the vector - repeat count and (if it is an ASCII character column) the - width of the field or a unit string within the field. This supports the - TFORMn = 'rAw' syntax for specifying arrays of substrings, so - if TFORMn = '60A12' then repeat = 60 and width = 12. -*/ -{ - LONGLONG trepeat, twidth; - - ffgtclll(fptr, colnum, typecode, &trepeat, &twidth, status); - - if (*status > 0) - return(*status); - - if (repeat) - *repeat= (long) trepeat; - - if (width) - *width = (long) twidth; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgtclll( fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number */ - int *typecode, /* O - datatype code (21 = short, etc) */ - LONGLONG *repeat, /* O - repeat count of field */ - LONGLONG *width, /* O - if ASCII, width of field or unit string */ - int *status) /* IO - error status */ -/* - Get Type of table column. - Returns the datatype code of the column, as well as the vector - repeat count and (if it is an ASCII character column) the - width of the field or a unit string within the field. This supports the - TFORMn = 'rAw' syntax for specifying arrays of substrings, so - if TFORMn = '60A12' then repeat = 60 and width = 12. -*/ -{ - tcolumn *colptr; - int hdutype, decims; - long tmpwidth; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - if (colnum < 1 || colnum > (fptr->Fptr)->tfield) - return(*status = BAD_COL_NUM); - - colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ - colptr += (colnum - 1); /* offset to correct column */ - - if (ffghdt(fptr, &hdutype, status) > 0) - return(*status); - - if (hdutype == ASCII_TBL) - { - ffasfm(colptr->tform, typecode, &tmpwidth, &decims, status); - *width = tmpwidth; - - if (repeat) - *repeat = 1; - } - else - { - if (typecode) - *typecode = colptr->tdatatype; - - if (width) - *width = colptr->twidth; - - if (repeat) - *repeat = colptr->trepeat; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffeqty( fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number */ - int *typecode, /* O - datatype code (21 = short, etc) */ - long *repeat, /* O - repeat count of field */ - long *width, /* O - if ASCII, width of field or unit string */ - int *status) /* IO - error status */ -/* - Get the 'equivalent' table column type. - - This routine is similar to the ffgtcl routine (which returns the physical - datatype of the column, as stored in the FITS file) except that if the - TSCALn and TZEROn keywords are defined for the column, then it returns - the 'equivalent' datatype. Thus, if the column is defined as '1I' (short - integer) this routine may return the type as 'TUSHORT' or as 'TFLOAT' - depending on the TSCALn and TZEROn values. - - Returns the datatype code of the column, as well as the vector - repeat count and (if it is an ASCII character column) the - width of the field or a unit string within the field. This supports the - TFORMn = 'rAw' syntax for specifying arrays of substrings, so - if TFORMn = '60A12' then repeat = 60 and width = 12. -*/ -{ - LONGLONG trepeat, twidth; - - ffeqtyll(fptr, colnum, typecode, &trepeat, &twidth, status); - - if (repeat) - *repeat= (long) trepeat; - - if (width) - *width = (long) twidth; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffeqtyll( fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number */ - int *typecode, /* O - datatype code (21 = short, etc) */ - LONGLONG *repeat, /* O - repeat count of field */ - LONGLONG *width, /* O - if ASCII, width of field or unit string */ - int *status) /* IO - error status */ -/* - Get the 'equivalent' table column type. - - This routine is similar to the ffgtcl routine (which returns the physical - datatype of the column, as stored in the FITS file) except that if the - TSCALn and TZEROn keywords are defined for the column, then it returns - the 'equivalent' datatype. Thus, if the column is defined as '1I' (short - integer) this routine may return the type as 'TUSHORT' or as 'TFLOAT' - depending on the TSCALn and TZEROn values. - - Returns the datatype code of the column, as well as the vector - repeat count and (if it is an ASCII character column) the - width of the field or a unit string within the field. This supports the - TFORMn = 'rAw' syntax for specifying arrays of substrings, so - if TFORMn = '60A12' then repeat = 60 and width = 12. -*/ -{ - tcolumn *colptr; - int hdutype, decims, tcode, effcode; - double tscale, tzero, min_val, max_val; - long lngscale, lngzero = 0, tmpwidth; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - if (colnum < 1 || colnum > (fptr->Fptr)->tfield) - return(*status = BAD_COL_NUM); - - colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ - colptr += (colnum - 1); /* offset to correct column */ - - if (ffghdt(fptr, &hdutype, status) > 0) - return(*status); - - if (hdutype == ASCII_TBL) - { - ffasfm(colptr->tform, typecode, &tmpwidth, &decims, status); - if (width) - *width = tmpwidth; - - if (repeat) - *repeat = 1; - } - else - { - if (typecode) - *typecode = colptr->tdatatype; - - if (width) - *width = colptr->twidth; - - if (repeat) - *repeat = colptr->trepeat; - } - - /* return if caller is not interested in the typecode value */ - if (!typecode) - return(*status); - - /* check if the tscale and tzero keywords are defined, which might - change the effective datatype of the column */ - - tscale = colptr->tscale; - tzero = colptr->tzero; - - if (tscale == 1.0 && tzero == 0.0) /* no scaling */ - return(*status); - - tcode = abs(*typecode); - - switch (tcode) - { - case TBYTE: /* binary table 'rB' column */ - min_val = 0.; - max_val = 255.0; - break; - - case TSHORT: - min_val = -32768.0; - max_val = 32767.0; - break; - - case TLONG: - - min_val = -2147483648.0; - max_val = 2147483647.0; - break; - - case TLONGLONG: - /* simply reuse the TLONG values */ - min_val = -2147483648.0; - max_val = 2147483647.0; - break; - - default: /* don't have to deal with other data types */ - return(*status); - } - - if (tscale >= 0.) { - min_val = tzero + tscale * min_val; - max_val = tzero + tscale * max_val; - } else { - max_val = tzero + tscale * min_val; - min_val = tzero + tscale * max_val; - } - if (tzero < 2147483648.) /* don't exceed range of 32-bit integer */ - lngzero = (long) tzero; - lngscale = (long) tscale; - - if ((tzero != 2147483648.) && /* special value that exceeds integer range */ - (lngzero != tzero || lngscale != tscale)) { /* not integers? */ - /* floating point scaled values; just decide on required precision */ - if (tcode == TBYTE || tcode == TSHORT) - effcode = TFLOAT; - else - effcode = TDOUBLE; - - /* - In all the remaining cases, TSCALn and TZEROn are integers, - and not equal to 1 and 0, respectively. - */ - - } else if ((min_val == -128.) && (max_val == 127.)) { - effcode = TSBYTE; - - } else if ((min_val >= -32768.0) && (max_val <= 32767.0)) { - effcode = TSHORT; - - } else if ((min_val >= 0.0) && (max_val <= 65535.0)) { - effcode = TUSHORT; - - } else if ((min_val >= -2147483648.0) && (max_val <= 2147483647.0)) { - effcode = TLONG; - - } else if ((min_val >= 0.0) && (max_val < 4294967296.0)) { - effcode = TULONG; - - } else { /* exceeds the range of a 32-bit integer */ - effcode = TDOUBLE; - } - - /* return the effective datatype code (negative if variable length col.) */ - if (*typecode < 0) /* variable length array column */ - *typecode = -effcode; - else - *typecode = effcode; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgncl( fitsfile *fptr, /* I - FITS file pointer */ - int *ncols, /* O - number of columns in the table */ - int *status) /* IO - error status */ -/* - Get the number of columns in the table (= TFIELDS keyword) -*/ -{ - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - return(*status = NOT_TABLE); - - *ncols = (fptr->Fptr)->tfield; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgnrw( fitsfile *fptr, /* I - FITS file pointer */ - long *nrows, /* O - number of rows in the table */ - int *status) /* IO - error status */ -/* - Get the number of rows in the table (= NAXIS2 keyword) -*/ -{ - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - return(*status = NOT_TABLE); - - /* the NAXIS2 keyword may not be up to date, so use the structure value */ - *nrows = (long) (fptr->Fptr)->numrows; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgnrwll( fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG *nrows, /* O - number of rows in the table */ - int *status) /* IO - error status */ -/* - Get the number of rows in the table (= NAXIS2 keyword) -*/ -{ - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - return(*status = NOT_TABLE); - - /* the NAXIS2 keyword may not be up to date, so use the structure value */ - *nrows = (fptr->Fptr)->numrows; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgacl( fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number */ - char *ttype, /* O - TTYPEn keyword value */ - long *tbcol, /* O - TBCOLn keyword value */ - char *tunit, /* O - TUNITn keyword value */ - char *tform, /* O - TFORMn keyword value */ - double *tscal, /* O - TSCALn keyword value */ - double *tzero, /* O - TZEROn keyword value */ - char *tnull, /* O - TNULLn keyword value */ - char *tdisp, /* O - TDISPn keyword value */ - int *status) /* IO - error status */ -/* - get ASCII column keyword values -*/ -{ - char name[FLEN_KEYWORD], comm[FLEN_COMMENT]; - tcolumn *colptr; - int tstatus; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - if (colnum < 1 || colnum > (fptr->Fptr)->tfield) - return(*status = BAD_COL_NUM); - - /* get what we can from the column structure */ - - colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ - colptr += (colnum -1); /* offset to correct column */ - - if (ttype) - strcpy(ttype, colptr->ttype); - - if (tbcol) - *tbcol = (long) ((colptr->tbcol) + 1); /* first col is 1, not 0 */ - - if (tform) - strcpy(tform, colptr->tform); - - if (tscal) - *tscal = colptr->tscale; - - if (tzero) - *tzero = colptr->tzero; - - if (tnull) - strcpy(tnull, colptr->strnull); - - /* read keywords to get additional parameters */ - - if (tunit) - { - ffkeyn("TUNIT", colnum, name, status); - tstatus = 0; - *tunit = '\0'; - ffgkys(fptr, name, tunit, comm, &tstatus); - } - - if (tdisp) - { - ffkeyn("TDISP", colnum, name, status); - tstatus = 0; - *tdisp = '\0'; - ffgkys(fptr, name, tdisp, comm, &tstatus); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgbcl( fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number */ - char *ttype, /* O - TTYPEn keyword value */ - char *tunit, /* O - TUNITn keyword value */ - char *dtype, /* O - datatype char: I, J, E, D, etc. */ - long *repeat, /* O - vector column repeat count */ - double *tscal, /* O - TSCALn keyword value */ - double *tzero, /* O - TZEROn keyword value */ - long *tnull, /* O - TNULLn keyword value integer cols only */ - char *tdisp, /* O - TDISPn keyword value */ - int *status) /* IO - error status */ -/* - get BINTABLE column keyword values -*/ -{ - LONGLONG trepeat, ttnull; - - if (*status > 0) - return(*status); - - ffgbclll(fptr, colnum, ttype, tunit, dtype, &trepeat, tscal, tzero, - &ttnull, tdisp, status); - - if (repeat) - *repeat = (long) trepeat; - - if (tnull) - *tnull = (long) ttnull; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgbclll( fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number */ - char *ttype, /* O - TTYPEn keyword value */ - char *tunit, /* O - TUNITn keyword value */ - char *dtype, /* O - datatype char: I, J, E, D, etc. */ - LONGLONG *repeat, /* O - vector column repeat count */ - double *tscal, /* O - TSCALn keyword value */ - double *tzero, /* O - TZEROn keyword value */ - LONGLONG *tnull, /* O - TNULLn keyword value integer cols only */ - char *tdisp, /* O - TDISPn keyword value */ - int *status) /* IO - error status */ -/* - get BINTABLE column keyword values -*/ -{ - char name[FLEN_KEYWORD], comm[FLEN_COMMENT]; - tcolumn *colptr; - int tstatus; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - if (colnum < 1 || colnum > (fptr->Fptr)->tfield) - return(*status = BAD_COL_NUM); - - /* get what we can from the column structure */ - - colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ - colptr += (colnum -1); /* offset to correct column */ - - if (ttype) - strcpy(ttype, colptr->ttype); - - if (dtype) - { - if (colptr->tdatatype < 0) /* add the "P" prefix for */ - strcpy(dtype, "P"); /* variable length columns */ - else - dtype[0] = 0; - - if (abs(colptr->tdatatype) == TBIT) - strcat(dtype, "X"); - else if (abs(colptr->tdatatype) == TBYTE) - strcat(dtype, "B"); - else if (abs(colptr->tdatatype) == TLOGICAL) - strcat(dtype, "L"); - else if (abs(colptr->tdatatype) == TSTRING) - strcat(dtype, "A"); - else if (abs(colptr->tdatatype) == TSHORT) - strcat(dtype, "I"); - else if (abs(colptr->tdatatype) == TLONG) - strcat(dtype, "J"); - else if (abs(colptr->tdatatype) == TLONGLONG) - strcat(dtype, "K"); - else if (abs(colptr->tdatatype) == TFLOAT) - strcat(dtype, "E"); - else if (abs(colptr->tdatatype) == TDOUBLE) - strcat(dtype, "D"); - else if (abs(colptr->tdatatype) == TCOMPLEX) - strcat(dtype, "C"); - else if (abs(colptr->tdatatype) == TDBLCOMPLEX) - strcat(dtype, "M"); - } - - if (repeat) - *repeat = colptr->trepeat; - - if (tscal) - *tscal = colptr->tscale; - - if (tzero) - *tzero = colptr->tzero; - - if (tnull) - *tnull = colptr->tnull; - - /* read keywords to get additional parameters */ - - if (tunit) - { - ffkeyn("TUNIT", colnum, name, status); - tstatus = 0; - *tunit = '\0'; - ffgkys(fptr, name, tunit, comm, &tstatus); - } - - if (tdisp) - { - ffkeyn("TDISP", colnum, name, status); - tstatus = 0; - *tdisp = '\0'; - ffgkys(fptr, name, tdisp, comm, &tstatus); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffghdn(fitsfile *fptr, /* I - FITS file pointer */ - int *chdunum) /* O - number of the CHDU; 1 = primary array */ -/* - Return the number of the Current HDU in the FITS file. The primary array - is HDU number 1. Note that this is one of the few cfitsio routines that - does not return the error status value as the value of the function. -*/ -{ - *chdunum = (fptr->HDUposition) + 1; - return(*chdunum); -} -/*--------------------------------------------------------------------------*/ -int ffghadll(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG *headstart, /* O - byte offset to beginning of CHDU */ - LONGLONG *datastart, /* O - byte offset to beginning of next HDU */ - LONGLONG *dataend, /* O - byte offset to beginning of next HDU */ - int *status) /* IO - error status */ -/* - Return the address (= byte offset) in the FITS file to the beginning of - the current HDU, the beginning of the data unit, and the end of the data unit. -*/ -{ - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - if (ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status) > 0) - return(*status); - } - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - { - if (ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - } - - if (headstart) - *headstart = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]; - - if (datastart) - *datastart = (fptr->Fptr)->datastart; - - if (dataend) - *dataend = (fptr->Fptr)->headstart[((fptr->Fptr)->curhdu) + 1]; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffghof(fitsfile *fptr, /* I - FITS file pointer */ - OFF_T *headstart, /* O - byte offset to beginning of CHDU */ - OFF_T *datastart, /* O - byte offset to beginning of next HDU */ - OFF_T *dataend, /* O - byte offset to beginning of next HDU */ - int *status) /* IO - error status */ -/* - Return the address (= byte offset) in the FITS file to the beginning of - the current HDU, the beginning of the data unit, and the end of the data unit. -*/ -{ - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - if (ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status) > 0) - return(*status); - } - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - { - if (ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - } - - if (headstart) - *headstart = (OFF_T) (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]; - - if (datastart) - *datastart = (OFF_T) (fptr->Fptr)->datastart; - - if (dataend) - *dataend = (OFF_T) (fptr->Fptr)->headstart[((fptr->Fptr)->curhdu) + 1]; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffghad(fitsfile *fptr, /* I - FITS file pointer */ - long *headstart, /* O - byte offset to beginning of CHDU */ - long *datastart, /* O - byte offset to beginning of next HDU */ - long *dataend, /* O - byte offset to beginning of next HDU */ - int *status) /* IO - error status */ -/* - Return the address (= byte offset) in the FITS file to the beginning of - the current HDU, the beginning of the data unit, and the end of the data unit. -*/ -{ - LONGLONG shead, sdata, edata; - - if (*status > 0) - return(*status); - - ffghadll(fptr, &shead, &sdata, &edata, status); - - if (headstart) - { - if (shead > LONG_MAX) - *status = NUM_OVERFLOW; - else - *headstart = (long) shead; - } - - if (datastart) - { - if (sdata > LONG_MAX) - *status = NUM_OVERFLOW; - else - *datastart = (long) sdata; - } - - if (dataend) - { - if (edata > LONG_MAX) - *status = NUM_OVERFLOW; - else - *dataend = (long) edata; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffrhdu(fitsfile *fptr, /* I - FITS file pointer */ - int *hdutype, /* O - type of HDU */ - int *status) /* IO - error status */ -/* - read the required keywords of the CHDU and initialize the corresponding - structure elements that describe the format of the HDU -*/ -{ - int ii, tstatus; - char card[FLEN_CARD]; - char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; - char xname[FLEN_VALUE], *xtension, urltype[20]; - - if (*status > 0) - return(*status); - - if (ffgrec(fptr, 1, card, status) > 0 ) /* get the 80-byte card */ - { - ffpmsg("Cannot read first keyword in header (ffrhdu)."); - return(*status); - } - strncpy(name,card,8); /* first 8 characters = the keyword name */ - name[8] = '\0'; - - for (ii=7; ii >= 0; ii--) /* replace trailing blanks with nulls */ - { - if (name[ii] == ' ') - name[ii] = '\0'; - else - break; - } - - if (ffpsvc(card, value, comm, status) > 0) /* parse value and comment */ - { - ffpmsg("Cannot read value of first keyword in header (ffrhdu):"); - ffpmsg(card); - return(*status); - } - - if (!strcmp(name, "SIMPLE")) /* this is the primary array */ - { - - ffpinit(fptr, status); /* initialize the primary array */ - - if (hdutype != NULL) - *hdutype = 0; - } - - else if (!strcmp(name, "XTENSION")) /* this is an XTENSION keyword */ - { - if (ffc2s(value, xname, status) > 0) /* get the value string */ - { - ffpmsg("Bad value string for XTENSION keyword:"); - ffpmsg(value); - return(*status); - } - - xtension = xname; - while (*xtension == ' ') /* ignore any leading spaces in name */ - xtension++; - - if (!strcmp(xtension, "TABLE")) - { - ffainit(fptr, status); /* initialize the ASCII table */ - if (hdutype != NULL) - *hdutype = 1; - } - - else if (!strcmp(xtension, "BINTABLE") || - !strcmp(xtension, "A3DTABLE") || - !strcmp(xtension, "3DTABLE") ) - { - ffbinit(fptr, status); /* initialize the binary table */ - if (hdutype != NULL) - *hdutype = 2; - } - - else - { - tstatus = 0; - ffpinit(fptr, &tstatus); /* probably an IMAGE extension */ - - if (tstatus == UNKNOWN_EXT && hdutype != NULL) - *hdutype = -1; /* don't recognize this extension type */ - else - { - *status = tstatus; - if (hdutype != NULL) - *hdutype = 0; - } - } - } - - else /* not the start of a new extension */ - { - if (card[0] == 0 || - card[0] == 10) /* some editors append this character to EOF */ - { - *status = END_OF_FILE; - } - else - { - *status = UNKNOWN_REC; /* found unknown type of record */ - ffpmsg - ("Extension doesn't start with SIMPLE or XTENSION keyword. (ffrhdu)"); - ffpmsg(card); - } - } - - /* compare the starting position of the next HDU (if any) with the size */ - /* of the whole file to see if this is the last HDU in the file */ - - if ((fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] < - (fptr->Fptr)->logfilesize ) - { - (fptr->Fptr)->lasthdu = 0; /* no, not the last HDU */ - } - else - { - (fptr->Fptr)->lasthdu = 1; /* yes, this is the last HDU */ - - /* special code for mem:// type files (FITS file in memory) */ - /* Allocate enough memory to hold the entire HDU. */ - /* Without this code, CFITSIO would repeatedly realloc memory */ - /* to incrementally increase the size of the file by 2880 bytes */ - /* at a time, until it reached the final size */ - - ffurlt(fptr, urltype, status); - if (!strcmp(urltype,"mem://") || !strcmp(urltype,"memkeep://")) - { - fftrun(fptr, (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1], - status); - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffpinit(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -/* - initialize the parameters defining the structure of the primary array - or an Image extension -*/ -{ - int groups, tstatus, simple, bitpix, naxis, extend, nspace; - int ttype = 0, bytlen = 0, ii, ntilebins; - long pcount, gcount; - LONGLONG naxes[999], npix, blank; - double bscale, bzero; - char comm[FLEN_COMMENT]; - tcolumn *colptr; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - (fptr->Fptr)->hdutype = IMAGE_HDU; /* primary array or IMAGE extension */ - (fptr->Fptr)->headend = (fptr->Fptr)->logfilesize; /* set max size */ - - groups = 0; - tstatus = *status; - - /* get all the descriptive info about this HDU */ - ffgphd(fptr, 999, &simple, &bitpix, &naxis, naxes, &pcount, &gcount, - &extend, &bscale, &bzero, &blank, &nspace, status); - - if (*status == NOT_IMAGE) - *status = tstatus; /* ignore 'unknown extension type' error */ - else if (*status > 0) - return(*status); - - /* - the logical end of the header is 80 bytes before the current position, - minus any trailing blank keywords just before the END keyword. - */ - (fptr->Fptr)->headend = (fptr->Fptr)->nextkey - (80 * (nspace + 1)); - - /* the data unit begins at the beginning of the next logical block */ - (fptr->Fptr)->datastart = (((fptr->Fptr)->nextkey - 80) / 2880 + 1) - * 2880; - - if (naxis > 0 && naxes[0] == 0) /* test for 'random groups' */ - { - tstatus = 0; - ffmaky(fptr, 2, status); /* reset to beginning of header */ - - if (ffgkyl(fptr, "GROUPS", &groups, comm, &tstatus)) - groups = 0; /* GROUPS keyword not found */ - } - - if (bitpix == BYTE_IMG) /* test bitpix and set the datatype code */ - { - ttype=TBYTE; - bytlen=1; - } - else if (bitpix == SHORT_IMG) - { - ttype=TSHORT; - bytlen=2; - } - else if (bitpix == LONG_IMG) - { - ttype=TLONG; - bytlen=4; - } - else if (bitpix == LONGLONG_IMG) - { - ttype=TLONGLONG; - bytlen=8; - } - else if (bitpix == FLOAT_IMG) - { - ttype=TFLOAT; - bytlen=4; - } - else if (bitpix == DOUBLE_IMG) - { - ttype=TDOUBLE; - bytlen=8; - } - - /* calculate the size of the primary array */ - (fptr->Fptr)->imgdim = naxis; - if (naxis == 0) - { - npix = 0; - } - else - { - if (groups) - { - npix = 1; /* NAXIS1 = 0 is a special flag for 'random groups' */ - } - else - { - npix = naxes[0]; - } - - (fptr->Fptr)->imgnaxis[0] = naxes[0]; - for (ii=1; ii < naxis; ii++) - { - npix = npix*naxes[ii]; /* calc number of pixels in the array */ - (fptr->Fptr)->imgnaxis[ii] = naxes[ii]; - } - } - - /* - now we know everything about the array; just fill in the parameters: - the next HDU begins in the next logical block after the data - */ - - (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] = - (fptr->Fptr)->datastart + - ( ((LONGLONG) pcount + npix) * bytlen * gcount + 2879) / 2880 * 2880; - - /* - initialize the fictitious heap starting address (immediately following - the array data) and a zero length heap. This is used to find the - end of the data when checking the fill values in the last block. - */ - (fptr->Fptr)->heapstart = (npix + pcount) * bytlen * gcount; - (fptr->Fptr)->heapsize = 0; - - (fptr->Fptr)->compressimg = 0; /* this is not a compressed image */ - - if (naxis == 0) - { - (fptr->Fptr)->rowlength = 0; /* rows have zero length */ - (fptr->Fptr)->tfield = 0; /* table has no fields */ - - /* free the tile-compressed image cache, if it exists */ - if ((fptr->Fptr)->tilerow) { - ntilebins = - (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; - - for (ii = 0; ii < ntilebins; ii++) { - if ((fptr->Fptr)->tiledata[ii]) { - free((fptr->Fptr)->tiledata[ii]); - } - - if ((fptr->Fptr)->tilenullarray[ii]) { - free((fptr->Fptr)->tilenullarray[ii]); - } - } - - free((fptr->Fptr)->tileanynull); - free((fptr->Fptr)->tiletype); - free((fptr->Fptr)->tiledatasize); - free((fptr->Fptr)->tilenullarray); - free((fptr->Fptr)->tiledata); - free((fptr->Fptr)->tilerow); - - (fptr->Fptr)->tileanynull = 0; - (fptr->Fptr)->tiletype = 0; - (fptr->Fptr)->tiledatasize = 0; - (fptr->Fptr)->tilenullarray = 0; - (fptr->Fptr)->tiledata = 0; - (fptr->Fptr)->tilerow = 0; - } - - if ((fptr->Fptr)->tableptr) - free((fptr->Fptr)->tableptr); /* free memory for the old CHDU */ - - (fptr->Fptr)->tableptr = 0; /* set a null table structure pointer */ - (fptr->Fptr)->numrows = 0; - (fptr->Fptr)->origrows = 0; - } - else - { - /* - The primary array is actually interpreted as a binary table. There - are two columns: the first column contains the group parameters if any. - The second column contains the primary array of data as a single vector - column element. In the case of 'random grouped' format, each group - is stored in a separate row of the table. - */ - /* the number of rows is equal to the number of groups */ - (fptr->Fptr)->numrows = gcount; - (fptr->Fptr)->origrows = gcount; - - (fptr->Fptr)->rowlength = (npix + pcount) * bytlen; /* total size */ - (fptr->Fptr)->tfield = 2; /* 2 fields: group params and the image */ - - /* free the tile-compressed image cache, if it exists */ - if ((fptr->Fptr)->tilerow) { - - ntilebins = - (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; - - for (ii = 0; ii < ntilebins; ii++) { - if ((fptr->Fptr)->tiledata[ii]) { - free((fptr->Fptr)->tiledata[ii]); - } - - if ((fptr->Fptr)->tilenullarray[ii]) { - free((fptr->Fptr)->tilenullarray[ii]); - } - } - - free((fptr->Fptr)->tileanynull); - free((fptr->Fptr)->tiletype); - free((fptr->Fptr)->tiledatasize); - free((fptr->Fptr)->tilenullarray); - free((fptr->Fptr)->tiledata); - free((fptr->Fptr)->tilerow); - - (fptr->Fptr)->tileanynull = 0; - (fptr->Fptr)->tiletype = 0; - (fptr->Fptr)->tiledatasize = 0; - (fptr->Fptr)->tilenullarray = 0; - (fptr->Fptr)->tiledata = 0; - (fptr->Fptr)->tilerow = 0; - } - - if ((fptr->Fptr)->tableptr) - free((fptr->Fptr)->tableptr); /* free memory for the old CHDU */ - - colptr = (tcolumn *) calloc(2, sizeof(tcolumn) ) ; - - if (!colptr) - { - ffpmsg - ("malloc failed to get memory for FITS array descriptors (ffpinit)"); - (fptr->Fptr)->tableptr = 0; /* set a null table structure pointer */ - return(*status = ARRAY_TOO_BIG); - } - - /* copy the table structure address to the fitsfile structure */ - (fptr->Fptr)->tableptr = colptr; - - /* the first column represents the group parameters, if any */ - colptr->tbcol = 0; - colptr->tdatatype = ttype; - colptr->twidth = bytlen; - colptr->trepeat = (LONGLONG) pcount; - colptr->tscale = 1.; - colptr->tzero = 0.; - colptr->tnull = blank; - - colptr++; /* increment pointer to the second column */ - - /* the second column represents the image array */ - colptr->tbcol = pcount * bytlen; /* col starts after the group parms */ - colptr->tdatatype = ttype; - colptr->twidth = bytlen; - colptr->trepeat = npix; - colptr->tscale = bscale; - colptr->tzero = bzero; - colptr->tnull = blank; - } - - /* reset next keyword pointer to the start of the header */ - (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu ]; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffainit(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -{ -/* - initialize the parameters defining the structure of an ASCII table -*/ - int ii, nspace, ntilebins; - long tfield; - LONGLONG pcount, rowlen, nrows, tbcoln; - tcolumn *colptr = 0; - char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; - char message[FLEN_ERRMSG], errmsg[81]; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - (fptr->Fptr)->hdutype = ASCII_TBL; /* set that this is an ASCII table */ - (fptr->Fptr)->headend = (fptr->Fptr)->logfilesize; /* set max size */ - - /* get table parameters and test that the header is a valid: */ - if (ffgttb(fptr, &rowlen, &nrows, &pcount, &tfield, status) > 0) - return(*status); - - if (pcount != 0) - { - ffpmsg("PCOUNT keyword not equal to 0 in ASCII table (ffainit)."); - sprintf(errmsg, " PCOUNT = %ld", (long) pcount); - ffpmsg(errmsg); - return(*status = BAD_PCOUNT); - } - - (fptr->Fptr)->rowlength = rowlen; /* store length of a row */ - (fptr->Fptr)->tfield = tfield; /* store number of table fields in row */ - - /* free the tile-compressed image cache, if it exists */ - if ((fptr->Fptr)->tilerow) { - - ntilebins = - (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; - - for (ii = 0; ii < ntilebins; ii++) { - if ((fptr->Fptr)->tiledata[ii]) { - free((fptr->Fptr)->tiledata[ii]); - } - - if ((fptr->Fptr)->tilenullarray[ii]) { - free((fptr->Fptr)->tilenullarray[ii]); - } - } - - free((fptr->Fptr)->tileanynull); - free((fptr->Fptr)->tiletype); - free((fptr->Fptr)->tiledatasize); - free((fptr->Fptr)->tilenullarray); - free((fptr->Fptr)->tiledata); - free((fptr->Fptr)->tilerow); - - (fptr->Fptr)->tileanynull = 0; - (fptr->Fptr)->tiletype = 0; - (fptr->Fptr)->tiledatasize = 0; - (fptr->Fptr)->tilenullarray = 0; - (fptr->Fptr)->tiledata = 0; - (fptr->Fptr)->tilerow = 0; - } - - if ((fptr->Fptr)->tableptr) - free((fptr->Fptr)->tableptr); /* free memory for the old CHDU */ - - /* mem for column structures ; space is initialized = 0 */ - if (tfield > 0) - { - colptr = (tcolumn *) calloc(tfield, sizeof(tcolumn) ); - if (!colptr) - { - ffpmsg - ("malloc failed to get memory for FITS table descriptors (ffainit)"); - (fptr->Fptr)->tableptr = 0; /* set a null table structure pointer */ - return(*status = ARRAY_TOO_BIG); - } - } - - /* copy the table structure address to the fitsfile structure */ - (fptr->Fptr)->tableptr = colptr; - - /* initialize the table field parameters */ - for (ii = 0; ii < tfield; ii++, colptr++) - { - colptr->ttype[0] = '\0'; /* null column name */ - colptr->tscale = 1.; - colptr->tzero = 0.; - colptr->strnull[0] = ASCII_NULL_UNDEFINED; /* null value undefined */ - colptr->tbcol = -1; /* initialize to illegal value */ - colptr->tdatatype = -9999; /* initialize to illegal value */ - } - - /* - Initialize the fictitious heap starting address (immediately following - the table data) and a zero length heap. This is used to find the - end of the table data when checking the fill values in the last block. - There is no special data following an ASCII table. - */ - (fptr->Fptr)->numrows = nrows; - (fptr->Fptr)->origrows = nrows; - (fptr->Fptr)->heapstart = rowlen * nrows; - (fptr->Fptr)->heapsize = 0; - - (fptr->Fptr)->compressimg = 0; /* this is not a compressed image */ - - /* now search for the table column keywords and the END keyword */ - - for (nspace = 0, ii = 8; 1; ii++) /* infinite loop */ - { - ffgkyn(fptr, ii, name, value, comm, status); - - /* try to ignore minor syntax errors */ - if (*status == NO_QUOTE) - { - strcat(value, "'"); - *status = 0; - } - else if (*status == BAD_KEYCHAR) - { - *status = 0; - } - - if (*status == END_OF_FILE) - { - ffpmsg("END keyword not found in ASCII table header (ffainit)."); - return(*status = NO_END); - } - else if (*status > 0) - return(*status); - - else if (name[0] == 'T') /* keyword starts with 'T' ? */ - ffgtbp(fptr, name, value, status); /* test if column keyword */ - - else if (!FSTRCMP(name, "END")) /* is this the END keyword? */ - break; - - if (!name[0] && !value[0] && !comm[0]) /* a blank keyword? */ - nspace++; - - else - nspace = 0; - } - - /* test that all required keywords were found and have legal values */ - colptr = (fptr->Fptr)->tableptr; - for (ii = 0; ii < tfield; ii++, colptr++) - { - tbcoln = colptr->tbcol; /* the starting column number (zero based) */ - - if (colptr->tdatatype == -9999) - { - ffkeyn("TFORM", ii+1, name, status); /* construct keyword name */ - sprintf(message,"Required %s keyword not found (ffainit).", name); - ffpmsg(message); - return(*status = NO_TFORM); - } - - else if (tbcoln == -1) - { - ffkeyn("TBCOL", ii+1, name, status); /* construct keyword name */ - sprintf(message,"Required %s keyword not found (ffainit).", name); - ffpmsg(message); - return(*status = NO_TBCOL); - } - - else if ((fptr->Fptr)->rowlength != 0 && - (tbcoln < 0 || tbcoln >= (fptr->Fptr)->rowlength ) ) - { - ffkeyn("TBCOL", ii+1, name, status); /* construct keyword name */ - sprintf(message,"Value of %s keyword out of range: %ld (ffainit).", - name, (long) tbcoln); - ffpmsg(message); - return(*status = BAD_TBCOL); - } - - else if ((fptr->Fptr)->rowlength != 0 && - tbcoln + colptr->twidth > (fptr->Fptr)->rowlength ) - { - sprintf(message,"Column %d is too wide to fit in table (ffainit)", - ii+1); - ffpmsg(message); - sprintf(message, " TFORM = %s and NAXIS1 = %ld", - colptr->tform, (long) (fptr->Fptr)->rowlength); - ffpmsg(message); - return(*status = COL_TOO_WIDE); - } - } - - /* - now we know everything about the table; just fill in the parameters: - the 'END' record is 80 bytes before the current position, minus - any trailing blank keywords just before the END keyword. - */ - (fptr->Fptr)->headend = (fptr->Fptr)->nextkey - (80 * (nspace + 1)); - - /* the data unit begins at the beginning of the next logical block */ - (fptr->Fptr)->datastart = (((fptr->Fptr)->nextkey - 80) / 2880 + 1) - * 2880; - - /* the next HDU begins in the next logical block after the data */ - (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] = - (fptr->Fptr)->datastart + - ( ((LONGLONG)rowlen * nrows + 2879) / 2880 * 2880 ); - - /* reset next keyword pointer to the start of the header */ - (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu ]; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffbinit(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -{ -/* - initialize the parameters defining the structure of a binary table -*/ - int ii, nspace, ntilebins; - long tfield; - LONGLONG pcount, rowlen, nrows, totalwidth; - tcolumn *colptr = 0; - char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; - char message[FLEN_ERRMSG]; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - (fptr->Fptr)->hdutype = BINARY_TBL; /* set that this is a binary table */ - (fptr->Fptr)->headend = (fptr->Fptr)->logfilesize; /* set max size */ - - /* get table parameters and test that the header is valid: */ - if (ffgttb(fptr, &rowlen, &nrows, &pcount, &tfield, status) > 0) - return(*status); - - (fptr->Fptr)->rowlength = rowlen; /* store length of a row */ - (fptr->Fptr)->tfield = tfield; /* store number of table fields in row */ - - /* free the tile-compressed image cache, if it exists */ - if ((fptr->Fptr)->tilerow) { - - ntilebins = - (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; - - for (ii = 0; ii < ntilebins; ii++) { - if ((fptr->Fptr)->tiledata[ii]) { - free((fptr->Fptr)->tiledata[ii]); - } - - if ((fptr->Fptr)->tilenullarray[ii]) { - free((fptr->Fptr)->tilenullarray[ii]); - } - } - - free((fptr->Fptr)->tileanynull); - free((fptr->Fptr)->tiletype); - free((fptr->Fptr)->tiledatasize); - free((fptr->Fptr)->tilenullarray); - free((fptr->Fptr)->tiledata); - free((fptr->Fptr)->tilerow); - - (fptr->Fptr)->tileanynull = 0; - (fptr->Fptr)->tiletype = 0; - (fptr->Fptr)->tiledatasize = 0; - (fptr->Fptr)->tilenullarray = 0; - (fptr->Fptr)->tiledata = 0; - (fptr->Fptr)->tilerow = 0; - } - - if ((fptr->Fptr)->tableptr) - free((fptr->Fptr)->tableptr); /* free memory for the old CHDU */ - - /* mem for column structures ; space is initialized = 0 */ - if (tfield > 0) - { - colptr = (tcolumn *) calloc(tfield, sizeof(tcolumn) ); - if (!colptr) - { - ffpmsg - ("malloc failed to get memory for FITS table descriptors (ffbinit)"); - (fptr->Fptr)->tableptr = 0; /* set a null table structure pointer */ - return(*status = ARRAY_TOO_BIG); - } - } - - /* copy the table structure address to the fitsfile structure */ - (fptr->Fptr)->tableptr = colptr; - - /* initialize the table field parameters */ - for (ii = 0; ii < tfield; ii++, colptr++) - { - colptr->ttype[0] = '\0'; /* null column name */ - colptr->tscale = 1.; - colptr->tzero = 0.; - colptr->tnull = NULL_UNDEFINED; /* (integer) null value undefined */ - colptr->tdatatype = -9999; /* initialize to illegal value */ - colptr->trepeat = 1; - colptr->strnull[0] = '\0'; /* for ASCII string columns (TFORM = rA) */ - } - - /* - Initialize the heap starting address (immediately following - the table data) and the size of the heap. This is used to find the - end of the table data when checking the fill values in the last block. - */ - (fptr->Fptr)->numrows = nrows; - (fptr->Fptr)->origrows = nrows; - (fptr->Fptr)->heapstart = rowlen * nrows; - (fptr->Fptr)->heapsize = pcount; - - (fptr->Fptr)->compressimg = 0; /* initialize as not a compressed image */ - - /* now search for the table column keywords and the END keyword */ - - for (nspace = 0, ii = 8; 1; ii++) /* infinite loop */ - { - ffgkyn(fptr, ii, name, value, comm, status); - - /* try to ignore minor syntax errors */ - if (*status == NO_QUOTE) - { - strcat(value, "'"); - *status = 0; - } - else if (*status == BAD_KEYCHAR) - { - *status = 0; - } - - if (*status == END_OF_FILE) - { - ffpmsg("END keyword not found in binary table header (ffbinit)."); - return(*status = NO_END); - } - else if (*status > 0) - return(*status); - - else if (name[0] == 'T') /* keyword starts with 'T' ? */ - ffgtbp(fptr, name, value, status); /* test if column keyword */ - - else if (!FSTRCMP(name, "ZIMAGE")) - { - if (value[0] == 'T') - (fptr->Fptr)->compressimg = 1; /* this is a compressed image */ - } - else if (!FSTRCMP(name, "END")) /* is this the END keyword? */ - break; - - - if (!name[0] && !value[0] && !comm[0]) /* a blank keyword? */ - nspace++; - - else - nspace = 0; /* reset number of consecutive spaces before END */ - } - - /* test that all the required keywords were found and have legal values */ - colptr = (fptr->Fptr)->tableptr; /* set pointer to first column */ - - for (ii = 0; ii < tfield; ii++, colptr++) - { - if (colptr->tdatatype == -9999) - { - ffkeyn("TFORM", ii+1, name, status); /* construct keyword name */ - sprintf(message,"Required %s keyword not found (ffbinit).", name); - ffpmsg(message); - return(*status = NO_TFORM); - } - } - - /* - now we know everything about the table; just fill in the parameters: - the 'END' record is 80 bytes before the current position, minus - any trailing blank keywords just before the END keyword. - */ - - (fptr->Fptr)->headend = (fptr->Fptr)->nextkey - (80 * (nspace + 1)); - - /* the data unit begins at the beginning of the next logical block */ - (fptr->Fptr)->datastart = (((fptr->Fptr)->nextkey - 80) / 2880 + 1) - * 2880; - - /* the next HDU begins in the next logical block after the data */ - (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] = - (fptr->Fptr)->datastart + - ( ((fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize + 2879) / 2880 * 2880 ); - - /* determine the byte offset to the beginning of each column */ - ffgtbc(fptr, &totalwidth, status); - - if (totalwidth != rowlen) - { - sprintf(message, - "NAXIS1 = %ld is not equal to the sum of column widths: %ld", - (long) rowlen, (long) totalwidth); - ffpmsg(message); - *status = BAD_ROW_WIDTH; - } - - /* reset next keyword pointer to the start of the header */ - (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu ]; - - if ( (fptr->Fptr)->compressimg == 1) /* Is this a compressed image */ - imcomp_get_compressed_image_par(fptr, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgabc(int tfields, /* I - number of columns in the table */ - char **tform, /* I - value of TFORMn keyword for each column */ - int space, /* I - number of spaces to leave between cols */ - long *rowlen, /* O - total width of a table row */ - long *tbcol, /* O - starting byte in row for each column */ - int *status) /* IO - error status */ -/* - calculate the starting byte offset of each column of an ASCII table - and the total length of a row, in bytes. The input space value determines - how many blank spaces to leave between each column (1 is recommended). -*/ -{ - int ii, datacode, decims; - long width; - - if (*status > 0) - return(*status); - - *rowlen=0; - - if (tfields <= 0) - return(*status); - - tbcol[0] = 1; - - for (ii = 0; ii < tfields; ii++) - { - tbcol[ii] = *rowlen + 1; /* starting byte in row of column */ - - ffasfm(tform[ii], &datacode, &width, &decims, status); - - *rowlen += (width + space); /* total length of row */ - } - - *rowlen -= space; /* don't add space after the last field */ - - return (*status); -} -/*--------------------------------------------------------------------------*/ -int ffgtbc(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG *totalwidth, /* O - total width of a table row */ - int *status) /* IO - error status */ -{ -/* - calculate the starting byte offset of each column of a binary table. - Use the values of the datatype code and repeat counts in the - column structure. Return the total length of a row, in bytes. -*/ - int tfields, ii; - LONGLONG nbytes; - tcolumn *colptr; - char message[FLEN_ERRMSG], *cptr; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - tfields = (fptr->Fptr)->tfield; - colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ - - *totalwidth = 0; - - for (ii = 0; ii < tfields; ii++, colptr++) - { - colptr->tbcol = *totalwidth; /* byte offset in row to this column */ - - if (colptr->tdatatype == TSTRING) - { - nbytes = colptr->trepeat; /* one byte per char */ - } - else if (colptr->tdatatype == TBIT) - { - nbytes = ( colptr->trepeat + 7) / 8; - } - else if (colptr->tdatatype > 0) - { - nbytes = colptr->trepeat * (colptr->tdatatype / 10); - } - else { - - cptr = colptr->tform; - while (isdigit(*cptr)) cptr++; - - if (*cptr == 'P') - /* this is a 'P' variable length descriptor (neg. tdatatype) */ - nbytes = colptr->trepeat * 8; - else if (*cptr == 'Q') - /* this is a 'Q' variable length descriptor (neg. tdatatype) */ - nbytes = colptr->trepeat * 16; - - else { - sprintf(message, - "unknown binary table column type: %s", colptr->tform); - ffpmsg(message); - *status = BAD_TFORM; - return(*status); - } - } - - *totalwidth = *totalwidth + nbytes; - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgtbp(fitsfile *fptr, /* I - FITS file pointer */ - char *name, /* I - name of the keyword */ - char *value, /* I - value string of the keyword */ - int *status) /* IO - error status */ -{ -/* - Get TaBle Parameter. The input keyword name begins with the letter T. - Test if the keyword is one of the table column definition keywords - of an ASCII or binary table. If so, decode it and update the value - in the structure. -*/ - int tstatus, datacode, decimals; - long width, repeat, nfield, ivalue; - LONGLONG jjvalue; - double dvalue; - char tvalue[FLEN_VALUE], *loc; - char message[FLEN_ERRMSG]; - tcolumn *colptr; - - if (*status > 0) - return(*status); - - tstatus = 0; - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - if(!FSTRNCMP(name + 1, "TYPE", 4) ) - { - /* get the index number */ - if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ - return(*status); /* must not be an indexed keyword */ - - if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ - return(*status); - - colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ - colptr = colptr + nfield - 1; /* point to the correct column */ - - if (ffc2s(value, tvalue, &tstatus) > 0) /* remove quotes */ - return(*status); - - strcpy(colptr->ttype, tvalue); /* copy col name to structure */ - } - else if(!FSTRNCMP(name + 1, "FORM", 4) ) - { - /* get the index number */ - if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ - return(*status); /* must not be an indexed keyword */ - - if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ - return(*status); - - colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ - colptr = colptr + nfield - 1; /* point to the correct column */ - - if (ffc2s(value, tvalue, &tstatus) > 0) /* remove quotes */ - return(*status); - - strncpy(colptr->tform, tvalue, 9); /* copy TFORM to structure */ - colptr->tform[9] = '\0'; /* make sure it is terminated */ - - if ((fptr->Fptr)->hdutype == ASCII_TBL) /* ASCII table */ - { - if (ffasfm(tvalue, &datacode, &width, &decimals, status) > 0) - return(*status); /* bad format code */ - - colptr->tdatatype = TSTRING; /* store datatype code */ - colptr->trepeat = 1; /* field repeat count == 1 */ - colptr->twidth = width; /* the width of the field, in bytes */ - } - else /* binary table */ - { - if (ffbnfm(tvalue, &datacode, &repeat, &width, status) > 0) - return(*status); /* bad format code */ - - colptr->tdatatype = datacode; /* store datatype code */ - colptr->trepeat = (LONGLONG) repeat; /* field repeat count */ - - /* Don't overwrite the unit string width if it was previously */ - /* set by a TDIMn keyword and has a legal value */ - if (datacode == TSTRING) { - if (colptr->twidth == 0 || colptr->twidth > repeat) - colptr->twidth = width; /* width of a unit string */ - - } else { - colptr->twidth = width; /* width of a unit value in chars */ - } - } - } - else if(!FSTRNCMP(name + 1, "BCOL", 4) ) - { - /* get the index number */ - if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ - return(*status); /* must not be an indexed keyword */ - - if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ - return(*status); - - colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ - colptr = colptr + nfield - 1; /* point to the correct column */ - - if ((fptr->Fptr)->hdutype == BINARY_TBL) - return(*status); /* binary tables don't have TBCOL keywords */ - - if (ffc2ii(value, &ivalue, status) > 0) - { - sprintf(message, - "Error reading value of %s as an integer: %s", name, value); - ffpmsg(message); - return(*status); - } - colptr->tbcol = ivalue - 1; /* convert to zero base */ - } - else if(!FSTRNCMP(name + 1, "SCAL", 4) ) - { - /* get the index number */ - if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ - return(*status); /* must not be an indexed keyword */ - - if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ - return(*status); - - colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ - colptr = colptr + nfield - 1; /* point to the correct column */ - - if (ffc2dd(value, &dvalue, &tstatus) > 0) - { - sprintf(message, - "Error reading value of %s as a double: %s", name, value); - ffpmsg(message); - - /* ignore this error, so don't return error status */ - return(*status); - } - colptr->tscale = dvalue; - } - else if(!FSTRNCMP(name + 1, "ZERO", 4) ) - { - /* get the index number */ - if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ - return(*status); /* must not be an indexed keyword */ - - if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ - return(*status); - - colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ - colptr = colptr + nfield - 1; /* point to the correct column */ - - if (ffc2dd(value, &dvalue, &tstatus) > 0) - { - sprintf(message, - "Error reading value of %s as a double: %s", name, value); - ffpmsg(message); - - /* ignore this error, so don't return error status */ - return(*status); - } - colptr->tzero = dvalue; - } - else if(!FSTRNCMP(name + 1, "NULL", 4) ) - { - /* get the index number */ - if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ - return(*status); /* must not be an indexed keyword */ - - if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ - return(*status); - - colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ - colptr = colptr + nfield - 1; /* point to the correct column */ - - if ((fptr->Fptr)->hdutype == ASCII_TBL) /* ASCII table */ - { - if (ffc2s(value, tvalue, &tstatus) > 0) /* remove quotes */ - return(*status); - - strncpy(colptr->strnull, tvalue, 17); /* copy TNULL string */ - colptr->strnull[17] = '\0'; /* terminate the strnull field */ - - } - else /* binary table */ - { - if (ffc2jj(value, &jjvalue, &tstatus) > 0) - { - sprintf(message, - "Error reading value of %s as an integer: %s", name, value); - ffpmsg(message); - - /* ignore this error, so don't return error status */ - return(*status); - } - colptr->tnull = jjvalue; /* null value for integer column */ - } - } - else if(!FSTRNCMP(name + 1, "DIM", 3) ) - { - if ((fptr->Fptr)->hdutype == ASCII_TBL) /* ASCII table */ - return(*status); /* ASCII tables don't support TDIMn keyword */ - - /* get the index number */ - if( ffc2ii(name + 4, &nfield, &tstatus) > 0) /* read index no. */ - return(*status); /* must not be an indexed keyword */ - - if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ - return(*status); - - colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ - colptr = colptr + nfield - 1; /* point to the correct column */ - - /* uninitialized columns have tdatatype set = -9999 */ - if (colptr->tdatatype != -9999 && colptr->tdatatype != TSTRING) - return(*status); /* this is not an ASCII string column */ - - loc = strchr(value, '(' ); /* find the opening parenthesis */ - if (!loc) - return(*status); /* not a proper TDIM keyword */ - - loc++; - width = strtol(loc, &loc, 10); /* read size of first dimension */ - if (colptr->trepeat != 1 && colptr->trepeat < width) - return(*status); /* string length is greater than column width */ - - colptr->twidth = width; /* set width of a unit string in chars */ - } - else if (!FSTRNCMP(name + 1, "HEAP", 4) ) - { - if ((fptr->Fptr)->hdutype == ASCII_TBL) /* ASCII table */ - return(*status); /* ASCII tables don't have a heap */ - - if (ffc2jj(value, &jjvalue, &tstatus) > 0) - { - sprintf(message, - "Error reading value of %s as an integer: %s", name, value); - ffpmsg(message); - - /* ignore this error, so don't return error status */ - return(*status); - } - (fptr->Fptr)->heapstart = jjvalue; /* starting byte of the heap */ - return(*status); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgcprll( fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number (1 = 1st column of table) */ - LONGLONG firstrow, /* I - first row (1 = 1st row of table) */ - LONGLONG firstelem, /* I - first element within vector (1 = 1st) */ - LONGLONG nelem, /* I - number of elements to read or write */ - int writemode, /* I - = 1 if writing data, = 0 if reading data */ - /* If = 2, then writing data, but don't modify */ - /* the returned values of repeat and incre. */ - /* If = -1, then reading data in reverse */ - /* direction. */ - double *scale, /* O - FITS scaling factor (TSCALn keyword value) */ - double *zero, /* O - FITS scaling zero pt (TZEROn keyword value) */ - char *tform, /* O - ASCII column format: value of TFORMn keyword */ - long *twidth, /* O - width of ASCII column (characters) */ - int *tcode, /* O - column datatype code: I*4=41, R*4=42, etc */ - int *maxelem, /* O - max number of elements that fit in buffer */ - LONGLONG *startpos,/* O - offset in file to starting row & column */ - LONGLONG *elemnum, /* O - starting element number ( 0 = 1st element) */ - long *incre, /* O - byte offset between elements within a row */ - LONGLONG *repeat, /* O - number of elements in a row (vector column) */ - LONGLONG *rowlen, /* O - length of a row, in bytes */ - int *hdutype, /* O - HDU type: 0, 1, 2 = primary, table, bintable */ - LONGLONG *tnull, /* O - null value for integer columns */ - char *snull, /* O - null value for ASCII table columns */ - int *status) /* IO - error status */ -/* - Get Column PaRameters, and test starting row and element numbers for - validity. This is a workhorse routine that is call by nearly every - other routine that reads or writes to FITS files. -*/ -{ - int nulpos, rangecheck = 1, tstatus = 0; - LONGLONG datastart, endpos; - long nblock; - LONGLONG heapoffset, lrepeat, endrow, nrows, tbcol; - char message[81]; - tcolumn *colptr; - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) { - /* reset position to the correct HDU if necessary */ - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { - /* rescan header if data structure is undefined */ - if ( ffrdef(fptr, status) > 0) - return(*status); - - } else if (writemode > 0) { - - /* Only terminate the header with the END card if */ - /* writing to the stdout stream (don't have random access). */ - - /* Initialize STREAM_DRIVER to be the device number for */ - /* writing FITS files directly out to the stdout stream. */ - /* This only needs to be done once and is thread safe. */ - if (STREAM_DRIVER <= 0 || STREAM_DRIVER > 40) { - urltype2driver("stream://", &STREAM_DRIVER); - } - - if ((fptr->Fptr)->driver == STREAM_DRIVER) { - if ((fptr->Fptr)->ENDpos != - maxvalue((fptr->Fptr)->headend , (fptr->Fptr)->datastart -2880)) { - ffwend(fptr, status); - } - } - } - - /* Do sanity check of input parameters */ - if (firstrow < 1) - { - if ((fptr->Fptr)->hdutype == IMAGE_HDU) /* Primary Array or IMAGE */ - { - sprintf(message, "Image group number is less than 1: %.0f", - (double) firstrow); - ffpmsg(message); - return(*status = BAD_ROW_NUM); - } - else - { - sprintf(message, "Starting row number is less than 1: %.0f", - (double) firstrow); - ffpmsg(message); - return(*status = BAD_ROW_NUM); - } - } - else if ((fptr->Fptr)->hdutype != ASCII_TBL && firstelem < 1) - { - sprintf(message, "Starting element number less than 1: %ld", - (long) firstelem); - ffpmsg(message); - return(*status = BAD_ELEM_NUM); - } - else if (nelem < 0) - { - sprintf(message, "Tried to read or write less than 0 elements: %.0f", - (double) nelem); - ffpmsg(message); - return(*status = NEG_BYTES); - } - else if (colnum < 1 || colnum > (fptr->Fptr)->tfield) - { - sprintf(message, "Specified column number is out of range: %d", - colnum); - ffpmsg(message); - sprintf(message, " There are %d columns in this table.", - (fptr->Fptr)->tfield ); - ffpmsg(message); - - return(*status = BAD_COL_NUM); - } - - /* copy relevant parameters from the structure */ - - *hdutype = (fptr->Fptr)->hdutype; /* image, ASCII table, or BINTABLE */ - *rowlen = (fptr->Fptr)->rowlength; /* width of the table, in bytes */ - datastart = (fptr->Fptr)->datastart; /* offset in file to start of table */ - - colptr = (fptr->Fptr)->tableptr; /* point to first column */ - colptr += (colnum - 1); /* offset to correct column structure */ - - *scale = colptr->tscale; /* value scaling factor; default = 1.0 */ - *zero = colptr->tzero; /* value scaling zeropoint; default = 0.0 */ - *tnull = colptr->tnull; /* null value for integer columns */ - tbcol = colptr->tbcol; /* offset to start of column within row */ - *twidth = colptr->twidth; /* width of a single datum, in bytes */ - *incre = colptr->twidth; /* increment between datums, in bytes */ - - *tcode = colptr->tdatatype; - *repeat = colptr->trepeat; - - strcpy(tform, colptr->tform); /* value of TFORMn keyword */ - strcpy(snull, colptr->strnull); /* null value for ASCII table columns */ - - if (*hdutype == ASCII_TBL && snull[0] == '\0') - { - /* In ASCII tables, a null value is equivalent to all spaces */ - - strcpy(snull, " "); /* maximum of 17 spaces */ - nulpos = minvalue(17, *twidth); /* truncate to width of column */ - snull[nulpos] = '\0'; - } - - /* Special case: interpret writemode = -1 as reading data, but */ - /* don't do error check for exceeding the range of pixels */ - if (writemode == -1) - { - writemode = 0; - rangecheck = 0; - } - - /* Special case: interprete 'X' column as 'B' */ - if (abs(*tcode) == TBIT) - { - *tcode = *tcode / TBIT * TBYTE; - *repeat = (*repeat + 7) / 8; - } - - /* Special case: support the 'rAw' format in BINTABLEs */ - if (*hdutype == BINARY_TBL && *tcode == TSTRING) { - *repeat = *repeat / *twidth; /* repeat = # of unit strings in field */ - } - else if (*hdutype == BINARY_TBL && *tcode == -TSTRING) { - /* variable length string */ - *incre = 1; - *twidth = (long) nelem; - } - - if (*hdutype == ASCII_TBL) - *elemnum = 0; /* ASCII tables don't have vector elements */ - else - *elemnum = firstelem - 1; - - /* interprete complex and double complex as pairs of floats or doubles */ - if (abs(*tcode) >= TCOMPLEX) - { - if (*tcode > 0) - *tcode = (*tcode + 1) / 2; - else - *tcode = (*tcode - 1) / 2; - - *repeat = *repeat * 2; - *twidth = *twidth / 2; - *incre = *incre / 2; - } - - /* calculate no. of pixels that fit in buffer */ - /* allow for case where floats are 8 bytes long */ - if (abs(*tcode) == TFLOAT) - *maxelem = DBUFFSIZE / sizeof(float); - else if (abs(*tcode) == TDOUBLE) - *maxelem = DBUFFSIZE / sizeof(double); - else if (abs(*tcode) == TSTRING) - { - *maxelem = (DBUFFSIZE - 1)/ *twidth; /* leave room for final \0 */ - if (*maxelem == 0) { - sprintf(message, - "ASCII string column is too wide: %ld; max supported width is %d", - *twidth, DBUFFSIZE - 1); - ffpmsg(message); - return(*status = COL_TOO_WIDE); - } - } - else - *maxelem = DBUFFSIZE / *twidth; - - /* calc starting byte position to 1st element of col */ - /* (this does not apply to variable length columns) */ - *startpos = datastart + ((LONGLONG)(firstrow - 1) * *rowlen) + tbcol; - - if (*hdutype == IMAGE_HDU && writemode) /* Primary Array or IMAGE */ - { /* - For primary arrays, set the repeat count greater than the total - number of pixels to be written. This prevents an out-of-range - error message in cases where the final image array size is not - yet known or defined. - */ - if (*repeat < *elemnum + nelem) - *repeat = *elemnum + nelem; - } - else if (*tcode > 0) /* Fixed length table column */ - { - if (*elemnum >= *repeat) - { - sprintf(message, - "First element to write is too large: %ld; max allowed value is %ld", - (long) ((*elemnum) + 1), (long) *repeat); - ffpmsg(message); - return(*status = BAD_ELEM_NUM); - } - - /* last row number to be read or written */ - endrow = ((*elemnum + nelem - 1) / *repeat) + firstrow; - - if (writemode) - { - /* check if we are writing beyond the current end of table */ - if ((endrow > (fptr->Fptr)->numrows) && (nelem > 0) ) - { - /* if there are more HDUs following the current one, or */ - /* if there is a data heap, then we must insert space */ - /* for the new rows. */ - if ( !((fptr->Fptr)->lasthdu) || (fptr->Fptr)->heapsize > 0) - { - nrows = endrow - ((fptr->Fptr)->numrows); - if (ffirow(fptr, (fptr->Fptr)->numrows, nrows, status) > 0) - { - sprintf(message, - "Failed to add space for %.0f new rows in table.", - (double) nrows); - ffpmsg(message); - return(*status); - } - } - else - { - /* update heap starting address */ - (fptr->Fptr)->heapstart += - ((LONGLONG)(endrow - (fptr->Fptr)->numrows) * - (fptr->Fptr)->rowlength ); - - (fptr->Fptr)->numrows = endrow; /* update number of rows */ - } - } - } - else /* reading from the file */ - { - if ( endrow > (fptr->Fptr)->numrows && rangecheck) - { - if (*hdutype == IMAGE_HDU) /* Primary Array or IMAGE */ - { - if (firstrow > (fptr->Fptr)->numrows) - { - sprintf(message, - "Attempted to read from group %ld of the HDU,", (long) firstrow); - ffpmsg(message); - - sprintf(message, - "however the HDU only contains %ld group(s).", - (long) ((fptr->Fptr)->numrows) ); - ffpmsg(message); - } - else - { - ffpmsg("Attempt to read past end of array:"); - sprintf(message, - " Image has %ld elements;", (long) *repeat); - ffpmsg(message); - - sprintf(message, - " Tried to read %ld elements starting at element %ld.", - (long) nelem, (long) firstelem); - ffpmsg(message); - } - } - else - { - ffpmsg("Attempt to read past end of table:"); - sprintf(message, - " Table has %.0f rows with %.0f elements per row;", - (double) ((fptr->Fptr)->numrows), (double) *repeat); - ffpmsg(message); - - sprintf(message, - " Tried to read %.0f elements starting at row %.0f, element %.0f.", - (double) nelem, (double) firstrow, (double) ((*elemnum) + 1)); - ffpmsg(message); - - } - return(*status = BAD_ROW_NUM); - } - } - - if (*repeat == 1 && nelem > 1 && writemode != 2) - { /* - When accessing a scalar column, fool the calling routine into - thinking that this is a vector column with very big elements. - This allows multiple values (up to the maxelem number of elements - that will fit in the buffer) to be read or written with a single - routine call, which increases the efficiency. - - If writemode == 2, then the calling program does not want to - have this efficiency trick applied. - */ - if (*rowlen <= LONG_MAX) { - *incre = (long) *rowlen; - *repeat = nelem; - } - } - } - else /* Variable length Binary Table column */ - { - *tcode *= (-1); - - if (writemode) /* return next empty heap address for writing */ - { - - *repeat = nelem + *elemnum; /* total no. of elements in the field */ - - /* first, check if we are overwriting an existing row, and */ - /* if so, if the existing space is big enough for the new vector */ - - if ( firstrow <= (fptr->Fptr)->numrows ) - { - ffgdesll(fptr, colnum, firstrow, &lrepeat, &heapoffset, &tstatus); - if (!tstatus) - { - if (colptr->tdatatype <= -TCOMPLEX) - lrepeat = lrepeat * 2; /* no. of float or double values */ - else if (colptr->tdatatype == -TBIT) - lrepeat = (lrepeat + 7) / 8; /* convert from bits to bytes */ - - if (lrepeat >= *repeat) /* enough existing space? */ - { - *startpos = datastart + heapoffset + (fptr->Fptr)->heapstart; - - /* write the descriptor into the fixed length part of table */ - if (colptr->tdatatype <= -TCOMPLEX) - { - /* divide repeat count by 2 to get no. of complex values */ - ffpdes(fptr, colnum, firstrow, *repeat / 2, - heapoffset, status); - } - else - { - ffpdes(fptr, colnum, firstrow, *repeat, - heapoffset, status); - } - return(*status); - } - } - } - - /* Add more rows to the table, if writing beyond the end. */ - /* It is necessary to shift the heap down in this case */ - if ( firstrow > (fptr->Fptr)->numrows) - { - nrows = firstrow - ((fptr->Fptr)->numrows); - if (ffirow(fptr, (fptr->Fptr)->numrows, nrows, status) > 0) - { - sprintf(message, - "Failed to add space for %.0f new rows in table.", - (double) nrows); - ffpmsg(message); - return(*status); - } - } - - /* calculate starting position (for writing new data) in the heap */ - *startpos = datastart + (fptr->Fptr)->heapstart + - (fptr->Fptr)->heapsize; - - /* write the descriptor into the fixed length part of table */ - if (colptr->tdatatype <= -TCOMPLEX) - { - /* divide repeat count by 2 to get no. of complex values */ - ffpdes(fptr, colnum, firstrow, *repeat / 2, - (fptr->Fptr)->heapsize, status); - } - else - { - ffpdes(fptr, colnum, firstrow, *repeat, (fptr->Fptr)->heapsize, - status); - } - - /* If this is not the last HDU in the file, then check if */ - /* extending the heap would overwrite the following header. */ - /* If so, then have to insert more blocks. */ - if ( !((fptr->Fptr)->lasthdu) ) - { - endpos = datastart + (fptr->Fptr)->heapstart + - (fptr->Fptr)->heapsize + ( *repeat * (*incre)); - - if (endpos > (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1]) - { - /* calc the number of blocks that need to be added */ - nblock = (long) (((endpos - 1 - - (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] ) - / 2880) + 1); - - if (ffiblk(fptr, nblock, 1, status) > 0) /* insert blocks */ - { - sprintf(message, - "Failed to extend the size of the variable length heap by %ld blocks.", - nblock); - ffpmsg(message); - return(*status); - } - } - } - - /* increment the address to the next empty heap position */ - (fptr->Fptr)->heapsize += ( *repeat * (*incre)); - } - else /* get the read start position in the heap */ - { - if ( firstrow > (fptr->Fptr)->numrows) - { - ffpmsg("Attempt to read past end of table"); - sprintf(message, - " Table has %.0f rows and tried to read row %.0f.", - (double) ((fptr->Fptr)->numrows), (double) firstrow); - ffpmsg(message); - return(*status = BAD_ROW_NUM); - } - - ffgdesll(fptr, colnum, firstrow, &lrepeat, &heapoffset, status); - *repeat = lrepeat; - - if (colptr->tdatatype <= -TCOMPLEX) - *repeat = *repeat * 2; /* no. of float or double values */ - else if (colptr->tdatatype == -TBIT) - *repeat = (*repeat + 7) / 8; /* convert from bits to bytes */ - - if (*elemnum >= *repeat) - { - sprintf(message, - "Starting element to read in variable length column is too large: %ld", - (long) firstelem); - ffpmsg(message); - sprintf(message, - " This row only contains %ld elements", (long) *repeat); - ffpmsg(message); - return(*status = BAD_ELEM_NUM); - } - - *startpos = datastart + heapoffset + (fptr->Fptr)->heapstart; - } - } - return(*status); -} -/*---------------------------------------------------------------------------*/ -int fftheap(fitsfile *fptr, /* I - FITS file pointer */ - LONGLONG *heapsz, /* O - current size of the heap */ - LONGLONG *unused, /* O - no. of unused bytes in the heap */ - LONGLONG *overlap, /* O - no. of bytes shared by > 1 descriptors */ - int *valid, /* O - are all the heap addresses valid? */ - int *status) /* IO - error status */ -/* - Tests the contents of the binary table variable length array heap. - Returns the number of bytes that are currently not pointed to by any - of the descriptors, and also the number of bytes that are pointed to - by more than one descriptor. It returns valid = FALSE if any of the - descriptors point to addresses that are out of the bounds of the - heap. -*/ -{ - int jj, typecode, pixsize; - long ii, kk, theapsz, nbytes; - LONGLONG repeat, offset, tunused = 0, toverlap = 0; - char *buffer, message[81]; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if ( fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - /* rescan header to make sure everything is up to date */ - else if ( ffrdef(fptr, status) > 0) - return(*status); - - if (valid) *valid = TRUE; - if (heapsz) *heapsz = (fptr->Fptr)->heapsize; - if (unused) *unused = 0; - if (overlap) *overlap = 0; - - /* return if this is not a binary table HDU or if the heap is empty */ - if ( (fptr->Fptr)->hdutype != BINARY_TBL || (fptr->Fptr)->heapsize == 0 ) - return(*status); - - if ((fptr->Fptr)->heapsize > LONG_MAX) { - ffpmsg("Heap is too big to test ( > 2**31 bytes). (fftheap)"); - return(*status = MEMORY_ALLOCATION); - } - - theapsz = (long) (fptr->Fptr)->heapsize; - buffer = calloc(1, theapsz); /* allocate temp space */ - if (!buffer ) - { - sprintf(message,"Failed to allocate buffer to test the heap"); - ffpmsg(message); - return(*status = MEMORY_ALLOCATION); - } - - /* loop over all cols */ - for (jj = 1; jj <= (fptr->Fptr)->tfield && *status <= 0; jj++) - { - ffgtcl(fptr, jj, &typecode, NULL, NULL, status); - if (typecode > 0) - continue; /* ignore fixed length columns */ - - pixsize = -typecode / 10; - - for (ii = 1; ii <= (fptr->Fptr)->numrows; ii++) - { - ffgdesll(fptr, jj, ii, &repeat, &offset, status); - if (typecode == -TBIT) - nbytes = (long) (repeat + 7) / 8; - else - nbytes = (long) repeat * pixsize; - - if (offset < 0 || offset + nbytes > theapsz) - { - if (valid) *valid = FALSE; /* address out of bounds */ - sprintf(message, - "Descriptor in row %ld, column %d has invalid heap address", - ii, jj); - ffpmsg(message); - } - else - { - for (kk = 0; kk < nbytes; kk++) - buffer[kk + offset]++; /* increment every used byte */ - } - } - } - - for (kk = 0; kk < theapsz; kk++) - { - if (buffer[kk] == 0) - tunused++; - else if (buffer[kk] > 1) - toverlap++; - } - - if (heapsz) *heapsz = theapsz; - if (unused) *unused = tunused; - if (overlap) *overlap = toverlap; - - free(buffer); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffcmph(fitsfile *fptr, /* I -FITS file pointer */ - int *status) /* IO - error status */ -/* - compress the binary table heap by reordering the contents heap and - recovering any unused space -*/ -{ - fitsfile *tptr; - int jj, typecode, pixsize, valid; - long ii, buffsize = 10000, nblock, nbytes; - LONGLONG unused, overlap; - LONGLONG repeat, offset; - char *buffer, *tbuff, comm[FLEN_COMMENT]; - char message[81]; - LONGLONG pcount; - LONGLONG readheapstart, writeheapstart, endpos, t1heapsize, t2heapsize; - - if (*status > 0) - return(*status); - - /* get information about the current heap */ - fftheap(fptr, NULL, &unused, &overlap, &valid, status); - - if (!valid) - return(*status = BAD_HEAP_PTR); /* bad heap pointers */ - - /* return if this is not a binary table HDU or if the heap is OK as is */ - if ( (fptr->Fptr)->hdutype != BINARY_TBL || (fptr->Fptr)->heapsize == 0 || - (unused == 0 && overlap == 0) || *status > 0 ) - return(*status); - - /* copy the current HDU to a temporary file in memory */ - if (ffinit( &tptr, "mem://tempheapfile", status) ) - { - sprintf(message,"Failed to create temporary file for the heap"); - ffpmsg(message); - return(*status); - } - if ( ffcopy(fptr, tptr, 0, status) ) - { - sprintf(message,"Failed to create copy of the heap"); - ffpmsg(message); - ffclos(tptr, status); - return(*status); - } - - buffer = (char *) malloc(buffsize); /* allocate initial buffer */ - if (!buffer) - { - sprintf(message,"Failed to allocate buffer to copy the heap"); - ffpmsg(message); - ffclos(tptr, status); - return(*status = MEMORY_ALLOCATION); - } - - readheapstart = (tptr->Fptr)->datastart + (tptr->Fptr)->heapstart; - writeheapstart = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; - - t1heapsize = (fptr->Fptr)->heapsize; /* save original heap size */ - (fptr->Fptr)->heapsize = 0; /* reset heap to zero */ - - /* loop over all cols */ - for (jj = 1; jj <= (fptr->Fptr)->tfield && *status <= 0; jj++) - { - ffgtcl(tptr, jj, &typecode, NULL, NULL, status); - if (typecode > 0) - continue; /* ignore fixed length columns */ - - pixsize = -typecode / 10; - - /* copy heap data, row by row */ - for (ii = 1; ii <= (fptr->Fptr)->numrows; ii++) - { - ffgdesll(tptr, jj, ii, &repeat, &offset, status); - if (typecode == -TBIT) - nbytes = (long) (repeat + 7) / 8; - else - nbytes = (long) repeat * pixsize; - - /* increase size of buffer if necessary to read whole array */ - if (nbytes > buffsize) - { - tbuff = realloc(buffer, nbytes); - - if (tbuff) - { - buffer = tbuff; - buffsize = nbytes; - } - else - *status = MEMORY_ALLOCATION; - } - - /* If this is not the last HDU in the file, then check if */ - /* extending the heap would overwrite the following header. */ - /* If so, then have to insert more blocks. */ - if ( !((fptr->Fptr)->lasthdu) ) - { - endpos = writeheapstart + (fptr->Fptr)->heapsize + nbytes; - - if (endpos > (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1]) - { - /* calc the number of blocks that need to be added */ - nblock = (long) (((endpos - 1 - - (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] ) - / 2880) + 1); - - if (ffiblk(fptr, nblock, 1, status) > 0) /* insert blocks */ - { - sprintf(message, - "Failed to extend the size of the variable length heap by %ld blocks.", - nblock); - ffpmsg(message); - } - } - } - - /* read arrray of bytes from temporary copy */ - ffmbyt(tptr, readheapstart + offset, REPORT_EOF, status); - ffgbyt(tptr, nbytes, buffer, status); - - /* write arrray of bytes back to original file */ - ffmbyt(fptr, writeheapstart + (fptr->Fptr)->heapsize, - IGNORE_EOF, status); - ffpbyt(fptr, nbytes, buffer, status); - - /* write descriptor */ - ffpdes(fptr, jj, ii, repeat, - (fptr->Fptr)->heapsize, status); - - (fptr->Fptr)->heapsize += nbytes; /* update heapsize */ - - if (*status > 0) - { - free(buffer); - ffclos(tptr, status); - return(*status); - } - } - } - - free(buffer); - ffclos(tptr, status); - - /* delete any empty blocks at the end of the HDU */ - nblock = (long) (( (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] - - (writeheapstart + (fptr->Fptr)->heapsize) ) / 2880); - - if (nblock > 0) - { - t2heapsize = (fptr->Fptr)->heapsize; /* save new heap size */ - (fptr->Fptr)->heapsize = t1heapsize; /* restore original heap size */ - - ffdblk(fptr, nblock, status); - (fptr->Fptr)->heapsize = t2heapsize; /* reset correct heap size */ - } - - /* update the PCOUNT value (size of heap) */ - ffmaky(fptr, 2, status); /* reset to beginning of header */ - - ffgkyjj(fptr, "PCOUNT", &pcount, comm, status); - if ((fptr->Fptr)->heapsize != pcount) - { - ffmkyj(fptr, "PCOUNT", (fptr->Fptr)->heapsize, comm, status); - } - ffrdef(fptr, status); /* rescan new HDU structure */ - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgdes(fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number (1 = 1st column of table) */ - LONGLONG rownum, /* I - row number (1 = 1st row of table) */ - long *length, /* O - number of elements in the row */ - long *heapaddr, /* O - heap pointer to the data */ - int *status) /* IO - error status */ -/* - get (read) the variable length vector descriptor from the table. -*/ -{ - LONGLONG lengthjj, heapaddrjj; - - if (ffgdesll(fptr, colnum, rownum, &lengthjj, &heapaddrjj, status) > 0) - return(*status); - - /* convert the temporary 8-byte values to 4-byte values */ - /* check for overflow */ - if (length) { - if (lengthjj > LONG_MAX) - *status = NUM_OVERFLOW; - else - *length = (long) lengthjj; - } - - if (heapaddr) { - if (heapaddrjj > LONG_MAX) - *status = NUM_OVERFLOW; - else - *heapaddr = (long) heapaddrjj; - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgdesll(fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number (1 = 1st column of table) */ - LONGLONG rownum, /* I - row number (1 = 1st row of table) */ - LONGLONG *length, /* O - number of elements in the row */ - LONGLONG *heapaddr, /* O - heap pointer to the data */ - int *status) /* IO - error status */ -/* - get (read) the variable length vector descriptor from the binary table. - This is similar to ffgdes, except it supports the full 8-byte range of the - length and offset values in 'Q' columns, as well as 'P' columns. -*/ -{ - LONGLONG bytepos; - unsigned int descript4[2] = {0,0}; - LONGLONG descript8[2] = {0,0}; - tcolumn *colptr; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ - colptr += (colnum - 1); /* offset to the correct column */ - - if (colptr->tdatatype >= 0) { - *status = NOT_VARI_LEN; - return(*status); - } - - bytepos = (fptr->Fptr)->datastart + - ((fptr->Fptr)->rowlength * (rownum - 1)) + - colptr->tbcol; - - if (colptr->tform[0] == 'P' || colptr->tform[1] == 'P') - { - /* read 4-byte descriptor */ - if (ffgi4b(fptr, bytepos, 2, 4, (INT32BIT *) descript4, status) <= 0) - { - if (length) - *length = (LONGLONG) descript4[0]; /* 1st word is the length */ - if (heapaddr) - *heapaddr = (LONGLONG) descript4[1]; /* 2nd word is the address */ - } - - } - else /* this is for 'Q' columns */ - { - /* read 8 byte descriptor */ - if (ffgi8b(fptr, bytepos, 2, 8, (long *) descript8, status) <= 0) - { - if (length) - *length = descript8[0]; /* 1st word is the length */ - if (heapaddr) - *heapaddr = descript8[1]; /* 2nd word is the address */ - } - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgdess(fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number (1 = 1st column of table) */ - LONGLONG firstrow, /* I - first row (1 = 1st row of table) */ - LONGLONG nrows, /* I - number or rows to read */ - long *length, /* O - number of elements in the row */ - long *heapaddr, /* O - heap pointer to the data */ - int *status) /* IO - error status */ -/* - get (read) a range of variable length vector descriptors from the table. -*/ -{ - LONGLONG rowsize, bytepos; - long ii; - INT32BIT descript4[2] = {0,0}; - LONGLONG descript8[2] = {0,0}; - tcolumn *colptr; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ - colptr += (colnum - 1); /* offset to the correct column */ - - if (colptr->tdatatype >= 0) { - *status = NOT_VARI_LEN; - return(*status); - } - - rowsize = (fptr->Fptr)->rowlength; - bytepos = (fptr->Fptr)->datastart + - (rowsize * (firstrow - 1)) + - colptr->tbcol; - - if (colptr->tform[0] == 'P' || colptr->tform[1] == 'P') - { - /* read 4-byte descriptors */ - for (ii = 0; ii < nrows; ii++) - { - /* read descriptors */ - if (ffgi4b(fptr, bytepos, 2, 4, descript4, status) <= 0) - { - if (length) { - *length = (long) descript4[0]; /* 1st word is the length */ - length++; - } - - if (heapaddr) { - *heapaddr = (long) descript4[1]; /* 2nd word is the address */ - heapaddr++; - } - bytepos += rowsize; - } - else - return(*status); - } - } - else /* this is for 'Q' columns */ - { - /* read 8-byte descriptors */ - for (ii = 0; ii < nrows; ii++) - { - /* read descriptors */ - if (ffgi8b(fptr, bytepos, 2, 8, (long *) descript8, status) <= 0) - { - if (length) { - if (descript8[0] > LONG_MAX)*status = NUM_OVERFLOW; - *length = (long) descript8[0]; /* 1st word is the length */ - length++; - } - if (heapaddr) { - if (descript8[1] > LONG_MAX)*status = NUM_OVERFLOW; - *heapaddr = (long) descript8[1]; /* 2nd word is the address */ - heapaddr++; - } - bytepos += rowsize; - } - else - return(*status); - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgdessll(fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number (1 = 1st column of table) */ - LONGLONG firstrow, /* I - first row (1 = 1st row of table) */ - LONGLONG nrows, /* I - number or rows to read */ - LONGLONG *length, /* O - number of elements in the row */ - LONGLONG *heapaddr, /* O - heap pointer to the data */ - int *status) /* IO - error status */ -/* - get (read) a range of variable length vector descriptors from the table. -*/ -{ - LONGLONG rowsize, bytepos; - long ii; - unsigned int descript4[2] = {0,0}; - LONGLONG descript8[2] = {0,0}; - tcolumn *colptr; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ - colptr += (colnum - 1); /* offset to the correct column */ - - if (colptr->tdatatype >= 0) { - *status = NOT_VARI_LEN; - return(*status); - } - - rowsize = (fptr->Fptr)->rowlength; - bytepos = (fptr->Fptr)->datastart + - (rowsize * (firstrow - 1)) + - colptr->tbcol; - - if (colptr->tform[0] == 'P' || colptr->tform[1] == 'P') - { - /* read 4-byte descriptors */ - for (ii = 0; ii < nrows; ii++) - { - /* read descriptors */ - if (ffgi4b(fptr, bytepos, 2, 4, (INT32BIT *) descript4, status) <= 0) - { - if (length) { - *length = (LONGLONG) descript4[0]; /* 1st word is the length */ - length++; - } - - if (heapaddr) { - *heapaddr = (LONGLONG) descript4[1]; /* 2nd word is the address */ - heapaddr++; - } - bytepos += rowsize; - } - else - return(*status); - } - } - else /* this is for 'Q' columns */ - { - /* read 8-byte descriptors */ - for (ii = 0; ii < nrows; ii++) - { - /* read descriptors */ - /* cast to type (long *) even though it is actually (LONGLONG *) */ - if (ffgi8b(fptr, bytepos, 2, 8, (long *) descript8, status) <= 0) - { - if (length) { - *length = descript8[0]; /* 1st word is the length */ - length++; - } - - if (heapaddr) { - *heapaddr = descript8[1]; /* 2nd word is the address */ - heapaddr++; - } - bytepos += rowsize; - } - else - return(*status); - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffpdes(fitsfile *fptr, /* I - FITS file pointer */ - int colnum, /* I - column number (1 = 1st column of table) */ - LONGLONG rownum, /* I - row number (1 = 1st row of table) */ - LONGLONG length, /* I - number of elements in the row */ - LONGLONG heapaddr, /* I - heap pointer to the data */ - int *status) /* IO - error status */ -/* - put (write) the variable length vector descriptor to the table. -*/ -{ - LONGLONG bytepos; - unsigned int descript4[2]; - LONGLONG descript8[2]; - tcolumn *colptr; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ - colptr += (colnum - 1); /* offset to the correct column */ - - if (colptr->tdatatype >= 0) - *status = NOT_VARI_LEN; - - bytepos = (fptr->Fptr)->datastart + - ((fptr->Fptr)->rowlength * (rownum - 1)) + - colptr->tbcol; - - ffmbyt(fptr, bytepos, IGNORE_EOF, status); /* move to element */ - - if (colptr->tform[0] == 'P' || colptr->tform[1] == 'P') - { - if (length > UINT_MAX || length < 0 || - heapaddr > UINT_MAX || heapaddr < 0) { - ffpmsg("P variable length column descriptor is out of range"); - *status = NUM_OVERFLOW; - return(*status); - } - - descript4[0] = (unsigned int) length; /* 1st word is the length */ - descript4[1] = (unsigned int) heapaddr; /* 2nd word is the address */ - - ffpi4b(fptr, 2, 4, (INT32BIT *) descript4, status); /* write the descriptor */ - } - else /* this is a 'Q' descriptor column */ - { - descript8[0] = length; /* 1st word is the length */ - descript8[1] = heapaddr; /* 2nd word is the address */ - - ffpi8b(fptr, 2, 8, (long *) descript8, status); /* write the descriptor */ - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffchdu(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -{ -/* - close the current HDU. If we have write access to the file, then: - - write the END keyword and pad header with blanks if necessary - - check the data fill values, and rewrite them if not correct -*/ - char message[FLEN_ERRMSG]; - int ii, stdriver, ntilebins; - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - /* no need to do any further updating of the HDU */ - } - else if ((fptr->Fptr)->writemode == 1) - { - urltype2driver("stream://", &stdriver); - - /* don't rescan header in special case of writing to stdout */ - if (((fptr->Fptr)->driver != stdriver)) - ffrdef(fptr, status); - - if ((fptr->Fptr)->heapsize > 0) { - ffuptf(fptr, status); /* update the variable length TFORM values */ - } - - ffpdfl(fptr, status); /* insure correct data fill values */ - } - - if ((fptr->Fptr)->open_count == 1) - { - - /* free memory for the CHDU structure only if no other files are using it */ - if ((fptr->Fptr)->tableptr) - { - free((fptr->Fptr)->tableptr); - (fptr->Fptr)->tableptr = NULL; - - /* free the tile-compressed image cache, if it exists */ - if ((fptr->Fptr)->tilerow) { - - ntilebins = - (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; - - for (ii = 0; ii < ntilebins; ii++) { - if ((fptr->Fptr)->tiledata[ii]) { - free((fptr->Fptr)->tiledata[ii]); - } - - if ((fptr->Fptr)->tilenullarray[ii]) { - free((fptr->Fptr)->tilenullarray[ii]); - } - } - - free((fptr->Fptr)->tileanynull); - free((fptr->Fptr)->tiletype); - free((fptr->Fptr)->tiledatasize); - free((fptr->Fptr)->tilenullarray); - free((fptr->Fptr)->tiledata); - free((fptr->Fptr)->tilerow); - - (fptr->Fptr)->tileanynull = 0; - (fptr->Fptr)->tiletype = 0; - (fptr->Fptr)->tiledatasize = 0; - (fptr->Fptr)->tilenullarray = 0; - (fptr->Fptr)->tiledata = 0; - (fptr->Fptr)->tilerow = 0; - } - } - } - - if (*status > 0 && *status != NO_CLOSE_ERROR) - { - sprintf(message, - "Error while closing HDU number %d (ffchdu).", (fptr->Fptr)->curhdu); - ffpmsg(message); - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffuptf(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -/* - Update the value of the TFORM keywords for the variable length array - columns to make sure they all have the form 1Px(len) or Px(len) where - 'len' is the maximum length of the vector in the table (e.g., '1PE(400)') -*/ -{ - int ii; - long tflds; - LONGLONG length, addr, maxlen, naxis2, jj; - char comment[FLEN_COMMENT], keyname[FLEN_KEYWORD]; - char tform[FLEN_VALUE], newform[FLEN_VALUE], lenval[40]; - char card[FLEN_CARD]; - char message[FLEN_ERRMSG]; - char *tmp; - - ffmaky(fptr, 2, status); /* reset to beginning of header */ - ffgkyjj(fptr, "NAXIS2", &naxis2, comment, status); - ffgkyj(fptr, "TFIELDS", &tflds, comment, status); - - for (ii = 1; ii <= tflds; ii++) /* loop over all the columns */ - { - ffkeyn("TFORM", ii, keyname, status); /* construct name */ - if (ffgkys(fptr, keyname, tform, comment, status) > 0) - { - sprintf(message, - "Error while updating variable length vector TFORMn values (ffuptf)."); - ffpmsg(message); - return(*status); - } - /* is this a variable array length column ? */ - if (tform[0] == 'P' || tform[1] == 'P' || tform[0] == 'Q' || tform[1] == 'Q') - { - /* get the max length */ - maxlen = 0; - for (jj=1; jj <= naxis2; jj++) - { - ffgdesll(fptr, ii, jj, &length, &addr, status); - - if (length > maxlen) - maxlen = length; - } - - /* construct the new keyword value */ - strcpy(newform, "'"); - tmp = strchr(tform, '('); /* truncate old length, if present */ - if (tmp) *tmp = 0; - strcat(newform, tform); - - /* print as double, because the string-to-64-bit */ - /* conversion is platform dependent (%lld, %ld, %I64d) */ - - sprintf(lenval, "(%.0f)", (double) maxlen); - - strcat(newform,lenval); - while(strlen(newform) < 9) - strcat(newform," "); /* append spaces 'till length = 8 */ - strcat(newform,"'" ); /* append closing parenthesis */ - /* would be simpler to just call ffmkyj here, but this */ - /* would force linking in all the modkey & putkey routines */ - ffmkky(keyname, newform, comment, card, status); /* make new card */ - ffmkey(fptr, card, status); /* replace last read keyword */ - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffrdef(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -/* - ReDEFine the structure of a data unit. This routine re-reads - the CHDU header keywords to determine the structure and length of the - current data unit. This redefines the start of the next HDU. -*/ -{ - int dummy, tstatus = 0; - LONGLONG naxis2; - LONGLONG pcount; - char card[FLEN_CARD], comm[FLEN_COMMENT], valstring[FLEN_VALUE]; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - } - else if ((fptr->Fptr)->writemode == 1) /* write access to the file? */ - { - /* don't need to check NAXIS2 and PCOUNT if data hasn't been written */ - if ((fptr->Fptr)->datastart != DATA_UNDEFINED) - { - /* update NAXIS2 keyword if more rows were written to the table */ - /* and if the user has not explicitly reset the NAXIS2 value */ - if ((fptr->Fptr)->hdutype != IMAGE_HDU) - { - ffmaky(fptr, 2, status); - if (ffgkyjj(fptr, "NAXIS2", &naxis2, comm, &tstatus) > 0) - { - /* Couldn't read NAXIS2 (odd!); in certain circumstances */ - /* this may be normal, so ignore the error. */ - naxis2 = (fptr->Fptr)->numrows; - } - - if ((fptr->Fptr)->numrows > naxis2 - && (fptr->Fptr)->origrows == naxis2) - /* if origrows is not equal to naxis2, then the user must */ - /* have manually modified the NAXIS2 keyword value, and */ - /* we will assume that the current value is correct. */ - { - /* would be simpler to just call ffmkyj here, but this */ - /* would force linking in all the modkey & putkey routines */ - - /* print as double because the 64-bit int conversion */ - /* is platform dependent (%lld, %ld, %I64 ) */ - - sprintf(valstring, "%.0f", (double) ((fptr->Fptr)->numrows)); - - ffmkky("NAXIS2", valstring, comm, card, status); - ffmkey(fptr, card, status); - } - } - - /* if data has been written to variable length columns in a */ - /* binary table, then we may need to update the PCOUNT value */ - if ((fptr->Fptr)->heapsize > 0) - { - ffmaky(fptr, 2, status); - ffgkyjj(fptr, "PCOUNT", &pcount, comm, status); - if ((fptr->Fptr)->heapsize != pcount) - { - ffmkyj(fptr, "PCOUNT", (fptr->Fptr)->heapsize, comm, status); - } - } - } - - if (ffwend(fptr, status) <= 0) /* rewrite END keyword and fill */ - { - ffrhdu(fptr, &dummy, status); /* re-scan the header keywords */ - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffhdef(fitsfile *fptr, /* I - FITS file pointer */ - int morekeys, /* I - reserve space for this many keywords */ - int *status) /* IO - error status */ -/* - based on the number of keywords which have already been written, - plus the number of keywords to reserve space for, we then can - define where the data unit should start (it must start at the - beginning of a 2880-byte logical block). - - This routine will only have any effect if the starting location of the - data unit following the header is not already defined. In any case, - it is always possible to add more keywords to the header even if the - data has already been written. It is just more efficient to reserve - the space in advance. -*/ -{ - LONGLONG delta; - - if (*status > 0 || morekeys < 1) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - } - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - { - ffrdef(fptr, status); - - /* ffrdef defines the offset to datastart and the start of */ - /* the next HDU based on the number of existing keywords. */ - /* We need to increment both of these values based on */ - /* the number of new keywords to be added. */ - - delta = (((fptr->Fptr)->headend + (morekeys * 80)) / 2880 + 1) - * 2880 - (fptr->Fptr)->datastart; - - (fptr->Fptr)->datastart += delta; - - (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] += delta; - - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffwend(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -/* - write the END card and following fill (space chars) in the current header -*/ -{ - int ii, tstatus; - LONGLONG endpos; - long nspace; - char blankkey[FLEN_CARD], endkey[FLEN_CARD], keyrec[FLEN_CARD] = ""; - - if (*status > 0) - return(*status); - - endpos = (fptr->Fptr)->headend; - - /* we assume that the HDUposition == curhdu in all cases */ - - /* calc the data starting position if not currently defined */ - if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - (fptr->Fptr)->datastart = ( endpos / 2880 + 1 ) * 2880; - - /* calculate the number of blank keyword slots in the header */ - nspace = (long) (( (fptr->Fptr)->datastart - endpos ) / 80); - - /* construct a blank and END keyword (80 spaces ) */ - strcpy(blankkey, " "); - strcat(blankkey, " "); - strcpy(endkey, "END "); - strcat(endkey, " "); - - /* check if header is already correctly terminated with END and fill */ - tstatus=0; - ffmbyt(fptr, endpos, REPORT_EOF, &tstatus); /* move to header end */ - for (ii=0; ii < nspace; ii++) - { - ffgbyt(fptr, 80, keyrec, &tstatus); /* get next keyword */ - if (tstatus) break; - if (strncmp(keyrec, blankkey, 80) && strncmp(keyrec, endkey, 80)) - break; - } - - if (ii == nspace && !tstatus) - { - /* check if the END keyword exists at the correct position */ - endpos=maxvalue( endpos, ( (fptr->Fptr)->datastart - 2880 ) ); - ffmbyt(fptr, endpos, REPORT_EOF, &tstatus); /* move to END position */ - ffgbyt(fptr, 80, keyrec, &tstatus); /* read the END keyword */ - if ( !strncmp(keyrec, endkey, 80) && !tstatus) { - - /* store this position, for later reference */ - (fptr->Fptr)->ENDpos = endpos; - - return(*status); /* END card was already correct */ - } - } - - /* header was not correctly terminated, so write the END and blank fill */ - endpos = (fptr->Fptr)->headend; - ffmbyt(fptr, endpos, IGNORE_EOF, status); /* move to header end */ - for (ii=0; ii < nspace; ii++) - ffpbyt(fptr, 80, blankkey, status); /* write the blank keywords */ - - /* - The END keyword must either be placed immediately after the last - keyword that was written (as indicated by the headend value), or - must be in the first 80 bytes of the 2880-byte FITS record immediately - preceeding the data unit, whichever is further in the file. The - latter will occur if space has been reserved for more header keywords - which have not yet been written. - */ - - endpos=maxvalue( endpos, ( (fptr->Fptr)->datastart - 2880 ) ); - ffmbyt(fptr, endpos, REPORT_EOF, status); /* move to END position */ - - ffpbyt(fptr, 80, endkey, status); /* write the END keyword to header */ - - /* store this position, for later reference */ - (fptr->Fptr)->ENDpos = endpos; - - if (*status > 0) - ffpmsg("Error while writing END card (ffwend)."); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffpdfl(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -/* - Write the Data Unit Fill values if they are not already correct. - The fill values are used to fill out the last 2880 byte block of the HDU. - Fill the data unit with zeros or blanks depending on the type of HDU - from the end of the data to the end of the current FITS 2880 byte block -*/ -{ - char chfill, fill[2880]; - LONGLONG fillstart; - int nfill, tstatus, ii; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - return(*status); /* fill has already been correctly written */ - - if ((fptr->Fptr)->heapstart == 0) - return(*status); /* null data unit, so there is no fill */ - - fillstart = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart + - (fptr->Fptr)->heapsize; - - nfill = (long) ((fillstart + 2879) / 2880 * 2880 - fillstart); - - if ((fptr->Fptr)->hdutype == ASCII_TBL) - chfill = 32; /* ASCII tables are filled with spaces */ - else - chfill = 0; /* all other extensions are filled with zeros */ - - tstatus = 0; - - if (!nfill) /* no fill bytes; just check that entire table exists */ - { - fillstart--; - nfill = 1; - ffmbyt(fptr, fillstart, REPORT_EOF, &tstatus); /* move to last byte */ - ffgbyt(fptr, nfill, fill, &tstatus); /* get the last byte */ - - if (tstatus == 0) - return(*status); /* no EOF error, so everything is OK */ - } - else - { - ffmbyt(fptr, fillstart, REPORT_EOF, &tstatus); /* move to fill area */ - ffgbyt(fptr, nfill, fill, &tstatus); /* get the fill bytes */ - - if (tstatus == 0) - { - for (ii = 0; ii < nfill; ii++) - { - if (fill[ii] != chfill) - break; - } - - if (ii == nfill) - return(*status); /* all the fill values were correct */ - } - } - - /* fill values are incorrect or have not been written, so write them */ - - memset(fill, chfill, nfill); /* fill the buffer with the fill value */ - - ffmbyt(fptr, fillstart, IGNORE_EOF, status); /* move to fill area */ - ffpbyt(fptr, nfill, fill, status); /* write the fill bytes */ - - if (*status > 0) - ffpmsg("Error writing Data Unit fill bytes (ffpdfl)."); - - return(*status); -} -/********************************************************************** - ffchfl : Check Header Fill values - - Check that the header unit is correctly filled with blanks from - the END card to the end of the current FITS 2880-byte block - - Function parameters: - fptr Fits file pointer - status output error status - - Translated ftchfl into C by Peter Wilson, Oct. 1997 -**********************************************************************/ -int ffchfl( fitsfile *fptr, int *status) -{ - int nblank,i,gotend; - LONGLONG endpos; - char rec[FLEN_CARD]; - char *blanks=" "; /* 80 spaces */ - - if( *status > 0 ) return (*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - /* calculate the number of blank keyword slots in the header */ - - endpos=(fptr->Fptr)->headend; - nblank=(long) (((fptr->Fptr)->datastart-endpos)/80); - - /* move the i/o pointer to the end of the header keywords */ - - ffmbyt(fptr,endpos,TRUE,status); - - /* find the END card (there may be blank keywords perceeding it) */ - - gotend=FALSE; - for(i=0;i 0 ) { - rec[FLEN_CARD - 1] = '\0'; /* make sure string is null terminated */ - ffpmsg(rec); - return( *status ); - } - } - return( *status ); -} - -/********************************************************************** - ffcdfl : Check Data Unit Fill values - - Check that the data unit is correctly filled with zeros or - blanks from the end of the data to the end of the current - FITS 2880 byte block - - Function parameters: - fptr Fits file pointer - status output error status - - Translated ftcdfl into C by Peter Wilson, Oct. 1997 -**********************************************************************/ -int ffcdfl( fitsfile *fptr, int *status) -{ - int nfill,i; - LONGLONG filpos; - char chfill,chbuff[2880]; - - if( *status > 0 ) return( *status ); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - /* check if the data unit is null */ - if( (fptr->Fptr)->heapstart==0 ) return( *status ); - - /* calculate starting position of the fill bytes, if any */ - filpos = (fptr->Fptr)->datastart - + (fptr->Fptr)->heapstart - + (fptr->Fptr)->heapsize; - - /* calculate the number of fill bytes */ - nfill = (long) ((filpos + 2879) / 2880 * 2880 - filpos); - if( nfill == 0 ) return( *status ); - - /* move to the beginning of the fill bytes */ - ffmbyt(fptr, filpos, FALSE, status); - - if( ffgbyt(fptr, nfill, chbuff, status) > 0) - { - ffpmsg("Error reading data unit fill bytes (ffcdfl)."); - return( *status ); - } - - if( (fptr->Fptr)->hdutype==ASCII_TBL ) - chfill = 32; /* ASCII tables are filled with spaces */ - else - chfill = 0; /* all other extensions are filled with zeros */ - - /* check for all zeros or blanks */ - - for(i=0;iFptr)->hdutype==ASCII_TBL ) - ffpmsg("Warning: remaining bytes following ASCII table data are not filled with blanks."); - else - ffpmsg("Warning: remaining bytes following data are not filled with zeros."); - return( *status ); - } - } - return( *status ); -} -/*--------------------------------------------------------------------------*/ -int ffcrhd(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -/* - CReate Header Data unit: Create, initialize, and move the i/o pointer - to a new extension appended to the end of the FITS file. -*/ -{ - int tstatus = 0; - LONGLONG bytepos, *ptr; - - if (*status > 0) - return(*status); - - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - - /* If the current header is empty, we don't have to do anything */ - if ((fptr->Fptr)->headend == (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) - return(*status); - - while (ffmrhd(fptr, 1, 0, &tstatus) == 0); /* move to end of file */ - - if ((fptr->Fptr)->maxhdu == (fptr->Fptr)->MAXHDU) - { - /* allocate more space for the headstart array */ - ptr = (LONGLONG*) realloc( (fptr->Fptr)->headstart, - ((fptr->Fptr)->MAXHDU + 1001) * sizeof(LONGLONG) ); - - if (ptr == NULL) - return (*status = MEMORY_ALLOCATION); - else { - (fptr->Fptr)->MAXHDU = (fptr->Fptr)->MAXHDU + 1000; - (fptr->Fptr)->headstart = ptr; - } - } - - if (ffchdu(fptr, status) <= 0) /* close the current HDU */ - { - bytepos = (fptr->Fptr)->headstart[(fptr->Fptr)->maxhdu + 1]; /* last */ - ffmbyt(fptr, bytepos, IGNORE_EOF, status); /* move file ptr to it */ - (fptr->Fptr)->maxhdu++; /* increment the known number of HDUs */ - (fptr->Fptr)->curhdu = (fptr->Fptr)->maxhdu; /* set current HDU loc */ - fptr->HDUposition = (fptr->Fptr)->maxhdu; /* set current HDU loc */ - (fptr->Fptr)->nextkey = bytepos; /* next keyword = start of header */ - (fptr->Fptr)->headend = bytepos; /* end of header */ - (fptr->Fptr)->datastart = DATA_UNDEFINED; /* start data unit undefined */ - - /* any other needed resets */ - - /* reset the dithering offset that may have been calculated for the */ - /* previous HDU back to the requested default value */ - (fptr->Fptr)->dither_seed = (fptr->Fptr)->request_dither_seed; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffdblk(fitsfile *fptr, /* I - FITS file pointer */ - long nblocks, /* I - number of 2880-byte blocks to delete */ - int *status) /* IO - error status */ -/* - Delete the specified number of 2880-byte blocks from the end - of the CHDU by shifting all following extensions up this - number of blocks. -*/ -{ - char buffer[2880]; - int tstatus, ii; - LONGLONG readpos, writepos; - - if (*status > 0 || nblocks <= 0) - return(*status); - - tstatus = 0; - /* pointers to the read and write positions */ - - readpos = (fptr->Fptr)->datastart + - (fptr->Fptr)->heapstart + - (fptr->Fptr)->heapsize; - readpos = ((readpos + 2879) / 2880) * 2880; /* start of block */ - -/* the following formula is wrong because the current data unit - may have been extended without updating the headstart value - of the following HDU. - - readpos = (fptr->Fptr)->headstart[((fptr->Fptr)->curhdu) + 1]; -*/ - writepos = readpos - ((LONGLONG)nblocks * 2880); - - while ( !ffmbyt(fptr, readpos, REPORT_EOF, &tstatus) && - !ffgbyt(fptr, 2880L, buffer, &tstatus) ) - { - ffmbyt(fptr, writepos, REPORT_EOF, status); - ffpbyt(fptr, 2880L, buffer, status); - - if (*status > 0) - { - ffpmsg("Error deleting FITS blocks (ffdblk)"); - return(*status); - } - readpos += 2880; /* increment to next block to transfer */ - writepos += 2880; - } - - /* now fill the last nblock blocks with zeros */ - memset(buffer, 0, 2880); - ffmbyt(fptr, writepos, REPORT_EOF, status); - - for (ii = 0; ii < nblocks; ii++) - ffpbyt(fptr, 2880L, buffer, status); - - /* move back before the deleted blocks, since they may be deleted */ - /* and we do not want to delete the current active buffer */ - ffmbyt(fptr, writepos - 1, REPORT_EOF, status); - - /* truncate the file to the new size, if supported on this device */ - fftrun(fptr, writepos, status); - - /* recalculate the starting location of all subsequent HDUs */ - for (ii = (fptr->Fptr)->curhdu; ii <= (fptr->Fptr)->maxhdu; ii++) - (fptr->Fptr)->headstart[ii + 1] -= ((LONGLONG)nblocks * 2880); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffghdt(fitsfile *fptr, /* I - FITS file pointer */ - int *exttype, /* O - type of extension, 0, 1, or 2 */ - /* for IMAGE_HDU, ASCII_TBL, or BINARY_TBL */ - int *status) /* IO - error status */ -/* - Return the type of the CHDU. This returns the 'logical' type of the HDU, - not necessarily the physical type, so in the case of a compressed image - stored in a binary table, this will return the type as an Image, not a - binary table. -*/ -{ - if (*status > 0) - return(*status); - - if (fptr->HDUposition == 0 && (fptr->Fptr)->headend == 0) { - /* empty primary array is alway an IMAGE_HDU */ - *exttype = IMAGE_HDU; - } - else { - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - } - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - { - /* rescan header if data structure is undefined */ - if ( ffrdef(fptr, status) > 0) - return(*status); - } - - *exttype = (fptr->Fptr)->hdutype; /* return the type of HDU */ - - /* check if this is a compressed image */ - if ((fptr->Fptr)->compressimg) - *exttype = IMAGE_HDU; - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fits_is_reentrant(void) -/* - Was CFITSIO compiled with the -D_REENTRANT flag? 1 = yes, 0 = no. - Note that specifying the -D_REENTRANT flag is required, but may not be - sufficient, to ensure that CFITSIO can be safely used in a multi-threaded - environoment. -*/ -{ -#ifdef _REENTRANT - return(1); -#else - return(0); -#endif -} -/*--------------------------------------------------------------------------*/ -int fits_is_compressed_image(fitsfile *fptr, /* I - FITS file pointer */ - int *status) /* IO - error status */ -/* - Returns TRUE if the CHDU is a compressed image, else returns zero. -*/ -{ - if (*status > 0) - return(0); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - { - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - } - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - { - /* rescan header if data structure is undefined */ - if ( ffrdef(fptr, status) > 0) - return(*status); - } - - /* check if this is a compressed image */ - if ((fptr->Fptr)->compressimg) - return(1); - - return(0); -} -/*--------------------------------------------------------------------------*/ -int ffgipr(fitsfile *infptr, /* I - FITS file pointer */ - int maxaxis, /* I - max number of axes to return */ - int *bitpix, /* O - image data type */ - int *naxis, /* O - image dimension (NAXIS value) */ - long *naxes, /* O - size of image dimensions */ - int *status) /* IO - error status */ - -/* - get the datatype and size of the input image -*/ -{ - - if (*status > 0) - return(*status); - - /* don't return the parameter if a null pointer was given */ - - if (bitpix) - fits_get_img_type(infptr, bitpix, status); /* get BITPIX value */ - - if (naxis) - fits_get_img_dim(infptr, naxis, status); /* get NAXIS value */ - - if (naxes) - fits_get_img_size(infptr, maxaxis, naxes, status); /* get NAXISn values */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgiprll(fitsfile *infptr, /* I - FITS file pointer */ - int maxaxis, /* I - max number of axes to return */ - int *bitpix, /* O - image data type */ - int *naxis, /* O - image dimension (NAXIS value) */ - LONGLONG *naxes, /* O - size of image dimensions */ - int *status) /* IO - error status */ - -/* - get the datatype and size of the input image -*/ -{ - - if (*status > 0) - return(*status); - - /* don't return the parameter if a null pointer was given */ - - if (bitpix) - fits_get_img_type(infptr, bitpix, status); /* get BITPIX value */ - - if (naxis) - fits_get_img_dim(infptr, naxis, status); /* get NAXIS value */ - - if (naxes) - fits_get_img_sizell(infptr, maxaxis, naxes, status); /* get NAXISn values */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgidt( fitsfile *fptr, /* I - FITS file pointer */ - int *imgtype, /* O - image data type */ - int *status) /* IO - error status */ -/* - Get the datatype of the image (= BITPIX keyword for normal image, or - ZBITPIX for a compressed image) -*/ -{ - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - /* reset to beginning of header */ - ffmaky(fptr, 1, status); /* simply move to beginning of header */ - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - { - ffgky(fptr, TINT, "BITPIX", imgtype, NULL, status); - } - else if ((fptr->Fptr)->compressimg) - { - /* this is a binary table containing a compressed image */ - ffgky(fptr, TINT, "ZBITPIX", imgtype, NULL, status); - } - else - { - *status = NOT_IMAGE; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgiet( fitsfile *fptr, /* I - FITS file pointer */ - int *imgtype, /* O - image data type */ - int *status) /* IO - error status */ -/* - Get the effective datatype of the image (= BITPIX keyword for normal image, - or ZBITPIX for a compressed image) -*/ -{ - int tstatus; - long lngscale, lngzero = 0; - double bscale, bzero, min_val, max_val; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - /* reset to beginning of header */ - ffmaky(fptr, 2, status); /* simply move to beginning of header */ - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - { - ffgky(fptr, TINT, "BITPIX", imgtype, NULL, status); - } - else if ((fptr->Fptr)->compressimg) - { - /* this is a binary table containing a compressed image */ - ffgky(fptr, TINT, "ZBITPIX", imgtype, NULL, status); - } - else - { - *status = NOT_IMAGE; - return(*status); - - } - - /* check if the BSCALE and BZERO keywords are defined, which might - change the effective datatype of the image */ - tstatus = 0; - ffgky(fptr, TDOUBLE, "BSCALE", &bscale, NULL, &tstatus); - if (tstatus) - bscale = 1.0; - - tstatus = 0; - ffgky(fptr, TDOUBLE, "BZERO", &bzero, NULL, &tstatus); - if (tstatus) - bzero = 0.0; - - if (bscale == 1.0 && bzero == 0.0) /* no scaling */ - return(*status); - - switch (*imgtype) - { - case BYTE_IMG: /* 8-bit image */ - min_val = 0.; - max_val = 255.0; - break; - - case SHORT_IMG: - min_val = -32768.0; - max_val = 32767.0; - break; - - case LONG_IMG: - - min_val = -2147483648.0; - max_val = 2147483647.0; - break; - - default: /* don't have to deal with other data types */ - return(*status); - } - - if (bscale >= 0.) { - min_val = bzero + bscale * min_val; - max_val = bzero + bscale * max_val; - } else { - max_val = bzero + bscale * min_val; - min_val = bzero + bscale * max_val; - } - if (bzero < 2147483648.) /* don't exceed range of 32-bit integer */ - lngzero = (long) bzero; - lngscale = (long) bscale; - - if ((bzero != 2147483648.) && /* special value that exceeds integer range */ - (lngzero != bzero || lngscale != bscale)) { /* not integers? */ - /* floating point scaled values; just decide on required precision */ - if (*imgtype == BYTE_IMG || *imgtype == SHORT_IMG) - *imgtype = FLOAT_IMG; - else - *imgtype = DOUBLE_IMG; - - /* - In all the remaining cases, BSCALE and BZERO are integers, - and not equal to 1 and 0, respectively. - */ - - } else if ((min_val == -128.) && (max_val == 127.)) { - *imgtype = SBYTE_IMG; - - } else if ((min_val >= -32768.0) && (max_val <= 32767.0)) { - *imgtype = SHORT_IMG; - - } else if ((min_val >= 0.0) && (max_val <= 65535.0)) { - *imgtype = USHORT_IMG; - - } else if ((min_val >= -2147483648.0) && (max_val <= 2147483647.0)) { - *imgtype = LONG_IMG; - - } else if ((min_val >= 0.0) && (max_val < 4294967296.0)) { - *imgtype = ULONG_IMG; - - } else { /* exceeds the range of a 32-bit integer */ - *imgtype = DOUBLE_IMG; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgidm( fitsfile *fptr, /* I - FITS file pointer */ - int *naxis , /* O - image dimension (NAXIS value) */ - int *status) /* IO - error status */ -/* - Get the dimension of the image (= NAXIS keyword for normal image, or - ZNAXIS for a compressed image) - These values are cached for faster access. -*/ -{ - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - { - *naxis = (fptr->Fptr)->imgdim; - } - else if ((fptr->Fptr)->compressimg) - { - *naxis = (fptr->Fptr)->zndim; - } - else - { - *status = NOT_IMAGE; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgisz( fitsfile *fptr, /* I - FITS file pointer */ - int nlen, /* I - number of axes to return */ - long *naxes, /* O - size of image dimensions */ - int *status) /* IO - error status */ -/* - Get the size of the image dimensions (= NAXISn keywords for normal image, or - ZNAXISn for a compressed image) - These values are cached for faster access. - -*/ -{ - int ii, naxis; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - { - naxis = minvalue((fptr->Fptr)->imgdim, nlen); - for (ii = 0; ii < naxis; ii++) - { - naxes[ii] = (long) (fptr->Fptr)->imgnaxis[ii]; - } - } - else if ((fptr->Fptr)->compressimg) - { - naxis = minvalue( (fptr->Fptr)->zndim, nlen); - for (ii = 0; ii < naxis; ii++) - { - naxes[ii] = (long) (fptr->Fptr)->znaxis[ii]; - } - } - else - { - *status = NOT_IMAGE; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgiszll( fitsfile *fptr, /* I - FITS file pointer */ - int nlen, /* I - number of axes to return */ - LONGLONG *naxes, /* O - size of image dimensions */ - int *status) /* IO - error status */ -/* - Get the size of the image dimensions (= NAXISn keywords for normal image, or - ZNAXISn for a compressed image) -*/ -{ - int ii, naxis; - - if (*status > 0) - return(*status); - - /* reset position to the correct HDU if necessary */ - if (fptr->HDUposition != (fptr->Fptr)->curhdu) - ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); - else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - if ( ffrdef(fptr, status) > 0) /* rescan header */ - return(*status); - - if ((fptr->Fptr)->hdutype == IMAGE_HDU) - { - naxis = minvalue((fptr->Fptr)->imgdim, nlen); - for (ii = 0; ii < naxis; ii++) - { - naxes[ii] = (fptr->Fptr)->imgnaxis[ii]; - } - } - else if ((fptr->Fptr)->compressimg) - { - naxis = minvalue( (fptr->Fptr)->zndim, nlen); - for (ii = 0; ii < naxis; ii++) - { - naxes[ii] = (fptr->Fptr)->znaxis[ii]; - } - } - else - { - *status = NOT_IMAGE; - } - - return(*status); -}/*--------------------------------------------------------------------------*/ -int ffmahd(fitsfile *fptr, /* I - FITS file pointer */ - int hdunum, /* I - number of the HDU to move to */ - int *exttype, /* O - type of extension, 0, 1, or 2 */ - int *status) /* IO - error status */ -/* - Move to Absolute Header Data unit. Move to the specified HDU - and read the header to initialize the table structure. Note that extnum - is one based, so the primary array is extnum = 1. -*/ -{ - int moveto, tstatus; - char message[FLEN_ERRMSG]; - LONGLONG *ptr; - - if (*status > 0) - return(*status); - else if (hdunum < 1 ) - return(*status = BAD_HDU_NUM); - else if (hdunum >= (fptr->Fptr)->MAXHDU ) - { - /* allocate more space for the headstart array */ - ptr = (LONGLONG*) realloc( (fptr->Fptr)->headstart, - (hdunum + 1001) * sizeof(LONGLONG) ); - - if (ptr == NULL) - return (*status = MEMORY_ALLOCATION); - else { - (fptr->Fptr)->MAXHDU = hdunum + 1000; - (fptr->Fptr)->headstart = ptr; - } - } - - /* set logical HDU position to the actual position, in case they differ */ - fptr->HDUposition = (fptr->Fptr)->curhdu; - - while( ((fptr->Fptr)->curhdu) + 1 != hdunum) /* at the correct HDU? */ - { - /* move directly to the extension if we know that it exists, - otherwise move to the highest known extension. */ - - moveto = minvalue(hdunum - 1, ((fptr->Fptr)->maxhdu) + 1); - - /* test if HDU exists */ - if ((fptr->Fptr)->headstart[moveto] < (fptr->Fptr)->logfilesize ) - { - if (ffchdu(fptr, status) <= 0) /* close out the current HDU */ - { - if (ffgext(fptr, moveto, exttype, status) > 0) - { /* failed to get the requested extension */ - - tstatus = 0; - ffrhdu(fptr, exttype, &tstatus); /* restore the CHDU */ - } - } - } - else - *status = END_OF_FILE; - - if (*status > 0) - { - if (*status != END_OF_FILE) - { - /* don't clutter up the message stack in the common case of */ - /* simply hitting the end of file (often an expected error) */ - - sprintf(message, - "Failed to move to HDU number %d (ffmahd).", hdunum); - ffpmsg(message); - } - return(*status); - } - } - - /* return the type of HDU; tile compressed images which are stored */ - /* in a binary table will return exttype = IMAGE_HDU, not BINARY_TBL */ - if (exttype != NULL) - ffghdt(fptr, exttype, status); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffmrhd(fitsfile *fptr, /* I - FITS file pointer */ - int hdumov, /* I - rel. no. of HDUs to move by (+ or -) */ - int *exttype, /* O - type of extension, 0, 1, or 2 */ - int *status) /* IO - error status */ -/* - Move a Relative number of Header Data units. Offset to the specified - extension and read the header to initialize the HDU structure. -*/ -{ - int extnum; - - if (*status > 0) - return(*status); - - extnum = fptr->HDUposition + 1 + hdumov; /* the absolute HDU number */ - ffmahd(fptr, extnum, exttype, status); /* move to the HDU */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffmnhd(fitsfile *fptr, /* I - FITS file pointer */ - int exttype, /* I - desired extension type */ - char *hduname, /* I - desired EXTNAME value for the HDU */ - int hduver, /* I - desired EXTVERS value for the HDU */ - int *status) /* IO - error status */ -/* - Move to the next HDU with a given extension type (IMAGE_HDU, ASCII_TBL, - BINARY_TBL, or ANY_HDU), extension name (EXTNAME or HDUNAME keyword), - and EXTVERS keyword values. If hduvers = 0, then move to the first HDU - with the given type and name regardless of EXTVERS value. If no matching - HDU is found in the file, then the current open HDU will remain unchanged. -*/ -{ - char extname[FLEN_VALUE]; - int ii, hdutype, alttype, extnum, tstatus, match, exact; - int slen, putback = 0, chopped = 0; - long extver; - - if (*status > 0) - return(*status); - - extnum = fptr->HDUposition + 1; /* save the current HDU number */ - - /* - This is a kludge to deal with a special case where the - user specified a hduname that ended with a # character, which - CFITSIO previously interpreted as a flag to mean "don't copy any - other HDUs in the file into the virtual file in memory. If the - remaining hduname does not end with a # character (meaning that - the user originally entered a hduname ending in 2 # characters) - then there is the possibility that the # character should be - treated literally, if the actual EXTNAME also ends with a #. - Setting putback = 1 means that we need to test for this case later on. - */ - - if ((fptr->Fptr)->only_one) { /* if true, name orignally ended with a # */ - slen = strlen(hduname); - if (hduname[slen - 1] != '#') /* This will fail if real EXTNAME value */ - putback = 1; /* ends with 2 # characters. */ - } - - for (ii=1; 1; ii++) /* loop over all HDUs until EOF */ - { - tstatus = 0; - if (ffmahd(fptr, ii, &hdutype, &tstatus)) /* move to next HDU */ - { - ffmahd(fptr, extnum, 0, status); /* restore original file position */ - return(*status = BAD_HDU_NUM); /* couldn't find desired HDU */ - } - - alttype = -1; - if (fits_is_compressed_image(fptr, status)) - alttype = BINARY_TBL; - - /* Does this HDU have a matching type? */ - if (exttype == ANY_HDU || hdutype == exttype || hdutype == alttype) - { - ffmaky(fptr, 2, status); /* reset to the 2nd keyword in the header */ - if (ffgkys(fptr, "EXTNAME", extname, 0, &tstatus) <= 0) /* get keyword */ - { - if (putback) { /* more of the kludge */ - /* test if the EXTNAME value ends with a #; if so, chop it */ - /* off before comparing the strings */ - chopped = 0; - slen = strlen(extname); - if (extname[slen - 1] == '#') { - extname[slen - 1] = '\0'; - chopped = 1; - } - } - - /* see if the strings are an exact match */ - ffcmps(extname, hduname, CASEINSEN, &match, &exact); - } - - /* if EXTNAME keyword doesn't exist, or it does not match, then try HDUNAME */ - if (tstatus || !exact) - { - tstatus = 0; - if (ffgkys(fptr, "HDUNAME", extname, 0, &tstatus) <= 0) - { - if (putback) { /* more of the kludge */ - chopped = 0; - slen = strlen(extname); - if (extname[slen - 1] == '#') { - extname[slen - 1] = '\0'; /* chop off the # */ - chopped = 1; - } - } - - /* see if the strings are an exact match */ - ffcmps(extname, hduname, CASEINSEN, &match, &exact); - } - } - - if (!tstatus && exact) /* found a matching name */ - { - if (hduver) /* need to check if version numbers match? */ - { - if (ffgkyj(fptr, "EXTVER", &extver, 0, &tstatus) > 0) - extver = 1; /* assume default EXTVER value */ - - if ( (int) extver == hduver) - { - if (chopped) { - /* The # was literally part of the name, not a flag */ - (fptr->Fptr)->only_one = 0; - } - return(*status); /* found matching name and vers */ - } - } - else - { - if (chopped) { - /* The # was literally part of the name, not a flag */ - (fptr->Fptr)->only_one = 0; - } - return(*status); /* found matching name */ - } - } /* end of !tstatus && exact */ - - } /* end of matching HDU type */ - } /* end of loop over HDUs */ -} -/*--------------------------------------------------------------------------*/ -int ffthdu(fitsfile *fptr, /* I - FITS file pointer */ - int *nhdu, /* O - number of HDUs in the file */ - int *status) /* IO - error status */ -/* - Return the number of HDUs that currently exist in the file. -*/ -{ - int ii, extnum, tstatus; - - if (*status > 0) - return(*status); - - extnum = fptr->HDUposition + 1; /* save the current HDU number */ - *nhdu = extnum - 1; - - /* if the CHDU is empty or not completely defined, just return */ - if ((fptr->Fptr)->datastart == DATA_UNDEFINED) - return(*status); - - tstatus = 0; - - /* loop until EOF */ - for (ii=extnum; ffmahd(fptr, ii, 0, &tstatus) <= 0; ii++) - { - *nhdu = ii; - } - - ffmahd(fptr, extnum, 0, status); /* restore orig file position */ - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgext(fitsfile *fptr, /* I - FITS file pointer */ - int hdunum, /* I - no. of HDU to move get (0 based) */ - int *exttype, /* O - type of extension, 0, 1, or 2 */ - int *status) /* IO - error status */ -/* - Get Extension. Move to the specified extension and initialize the - HDU structure. -*/ -{ - int xcurhdu, xmaxhdu; - LONGLONG xheadend; - - if (*status > 0) - return(*status); - - if (ffmbyt(fptr, (fptr->Fptr)->headstart[hdunum], REPORT_EOF, status) <= 0) - { - /* temporarily save current values, in case of error */ - xcurhdu = (fptr->Fptr)->curhdu; - xmaxhdu = (fptr->Fptr)->maxhdu; - xheadend = (fptr->Fptr)->headend; - - /* set new parameter values */ - (fptr->Fptr)->curhdu = hdunum; - fptr->HDUposition = hdunum; - (fptr->Fptr)->maxhdu = maxvalue((fptr->Fptr)->maxhdu, hdunum); - (fptr->Fptr)->headend = (fptr->Fptr)->logfilesize; /* set max size */ - - if (ffrhdu(fptr, exttype, status) > 0) - { /* failed to get the new HDU, so restore previous values */ - (fptr->Fptr)->curhdu = xcurhdu; - fptr->HDUposition = xcurhdu; - (fptr->Fptr)->maxhdu = xmaxhdu; - (fptr->Fptr)->headend = xheadend; - } - } - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffiblk(fitsfile *fptr, /* I - FITS file pointer */ - long nblock, /* I - no. of blocks to insert */ - int headdata, /* I - insert where? 0=header, 1=data */ - /* -1=beginning of file */ - int *status) /* IO - error status */ -/* - insert 2880-byte blocks at the end of the current header or data unit -*/ -{ - int tstatus, savehdu, typhdu; - LONGLONG insertpt, jpoint; - long ii, nshift; - char charfill; - char buff1[2880], buff2[2880]; - char *inbuff, *outbuff, *tmpbuff; - char card[FLEN_CARD]; - - if (*status > 0 || nblock <= 0) - return(*status); - - tstatus = *status; - - if (headdata == 0 || (fptr->Fptr)->hdutype == ASCII_TBL) - charfill = 32; /* headers and ASCII tables have space (32) fill */ - else - charfill = 0; /* images and binary tables have zero fill */ - - if (headdata == 0) - insertpt = (fptr->Fptr)->datastart; /* insert just before data, or */ - else if (headdata == -1) - { - insertpt = 0; - strcpy(card, "XTENSION= 'IMAGE ' / IMAGE extension"); - } - else /* at end of data, */ - { - insertpt = (fptr->Fptr)->datastart + - (fptr->Fptr)->heapstart + - (fptr->Fptr)->heapsize; - insertpt = ((insertpt + 2879) / 2880) * 2880; /* start of block */ - - /* the following formula is wrong because the current data unit - may have been extended without updating the headstart value - of the following HDU. - */ - /* insertpt = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu + 1]; */ - } - - inbuff = buff1; /* set pointers to input and output buffers */ - outbuff = buff2; - - memset(outbuff, charfill, 2880); /* initialize buffer with fill */ - - if (nblock == 1) /* insert one block */ - { - if (headdata == -1) - ffmrec(fptr, 1, card, status); /* change SIMPLE -> XTENSION */ - - ffmbyt(fptr, insertpt, REPORT_EOF, status); /* move to 1st point */ - ffgbyt(fptr, 2880, inbuff, status); /* read first block of bytes */ - - while (*status <= 0) - { - ffmbyt(fptr, insertpt, REPORT_EOF, status); /* insert point */ - ffpbyt(fptr, 2880, outbuff, status); /* write the output buffer */ - - if (*status > 0) - return(*status); - - tmpbuff = inbuff; /* swap input and output pointers */ - inbuff = outbuff; - outbuff = tmpbuff; - insertpt += 2880; /* increment insert point by 1 block */ - - ffmbyt(fptr, insertpt, REPORT_EOF, status); /* move to next block */ - ffgbyt(fptr, 2880, inbuff, status); /* read block of bytes */ - } - - *status = tstatus; /* reset status value */ - ffmbyt(fptr, insertpt, IGNORE_EOF, status); /* move back to insert pt */ - ffpbyt(fptr, 2880, outbuff, status); /* write the final block */ - } - - else /* inserting more than 1 block */ - - { - savehdu = (fptr->Fptr)->curhdu; /* save the current HDU number */ - tstatus = *status; - while(*status <= 0) /* find the last HDU in file */ - ffmrhd(fptr, 1, &typhdu, status); - - if (*status == END_OF_FILE) - { - *status = tstatus; - } - - ffmahd(fptr, savehdu + 1, &typhdu, status); /* move back to CHDU */ - if (headdata == -1) - ffmrec(fptr, 1, card, status); /* NOW change SIMPLE -> XTENSION */ - - /* number of 2880-byte blocks that have to be shifted down */ - nshift = (long) (((fptr->Fptr)->headstart[(fptr->Fptr)->maxhdu + 1] - insertpt) - / 2880); - /* position of last block in file to be shifted */ - jpoint = (fptr->Fptr)->headstart[(fptr->Fptr)->maxhdu + 1] - 2880; - - /* move all the blocks starting at end of file working backwards */ - for (ii = 0; ii < nshift; ii++) - { - /* move to the read start position */ - if (ffmbyt(fptr, jpoint, REPORT_EOF, status) > 0) - return(*status); - - ffgbyt(fptr, 2880, inbuff,status); /* read one record */ - - /* move forward to the write postion */ - ffmbyt(fptr, jpoint + ((LONGLONG) nblock * 2880), IGNORE_EOF, status); - - ffpbyt(fptr, 2880, inbuff, status); /* write the record */ - - jpoint -= 2880; - } - - /* move back to the write start postion (might be EOF) */ - ffmbyt(fptr, insertpt, IGNORE_EOF, status); - - for (ii = 0; ii < nblock; ii++) /* insert correct fill value */ - ffpbyt(fptr, 2880, outbuff, status); - } - - if (headdata == 0) /* update data start address */ - (fptr->Fptr)->datastart += ((LONGLONG) nblock * 2880); - - /* update following HDU addresses */ - for (ii = (fptr->Fptr)->curhdu; ii <= (fptr->Fptr)->maxhdu; ii++) - (fptr->Fptr)->headstart[ii + 1] += ((LONGLONG) nblock * 2880); - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffgkcl(char *tcard) - -/* - Return the type classification of the input header record - - TYP_STRUC_KEY: SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, - GROUPS, PCOUNT, GCOUNT, END - XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, - and the first 4 COMMENT keywords in the primary array - that define the FITS format. - - TYP_CMPRS_KEY: - The keywords used in the compressed image format - ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, ZTILEn, - ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK, - EXTNAME = 'COMPRESSED_IMAGE' - ZSIMPLE, ZTENSION, ZEXTEND, ZBLOCKED, ZPCOUNT, ZGCOUNT - ZQUANTIZ, ZDITHER0 - - TYP_SCAL_KEY: BSCALE, BZERO, TSCALn, TZEROn - - TYP_NULL_KEY: BLANK, TNULLn - - TYP_DIM_KEY: TDIMn - - TYP_RANG_KEY: TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX - - TYP_UNIT_KEY: BUNIT, TUNITn - - TYP_DISP_KEY: TDISPn - - TYP_HDUID_KEY: EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL - - TYP_CKSUM_KEY CHECKSUM, DATASUM - - TYP_WCS_KEY: - Primary array: - WCAXES, CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn - CDj_is, PVj_ms, LONPOLEs, LATPOLEs - - Pixel list: - TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, TCRPks, - TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn - - Bintable vector: - jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, iCRPns, - jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn - - TYP_REFSYS_KEY: - EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs - - TYP_COMM_KEY: COMMENT, HISTORY, (blank keyword) - - TYP_CONT_KEY: CONTINUE - - TYP_USER_KEY: all other keywords - -*/ -{ - char card[20], *card1, *card5; - - card[0] = '\0'; - strncat(card, tcard, 8); /* copy the keyword name */ - strcat(card, " "); /* append blanks to make at least 8 chars long */ - ffupch(card); /* make sure it is in upper case */ - - card1 = card + 1; /* pointer to 2nd character */ - card5 = card + 5; /* pointer to 6th character */ - - /* the strncmp function is slow, so try to be more efficient */ - if (*card == 'Z') - { - if (FSTRNCMP (card1, "IMAGE ", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "CMPTYPE", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "NAME", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_CMPRS_KEY); - } - else if (FSTRNCMP (card1, "VAL", 3) == 0) - { - if (*(card + 4) >= '0' && *(card + 4) <= '9') - return (TYP_CMPRS_KEY); - } - else if (FSTRNCMP (card1, "TILE", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_CMPRS_KEY); - } - else if (FSTRNCMP (card1, "BITPIX ", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "NAXIS", 5) == 0) - { - if ( ( *(card + 6) >= '0' && *(card + 6) <= '9' ) - || (*(card + 6) == ' ') ) - return (TYP_CMPRS_KEY); - } - else if (FSTRNCMP (card1, "SCALE ", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "ZERO ", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "BLANK ", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "SIMPLE ", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "TENSION", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "EXTEND ", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "BLOCKED", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "PCOUNT ", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "GCOUNT ", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "QUANTIZ", 7) == 0) - return (TYP_CMPRS_KEY); - else if (FSTRNCMP (card1, "DITHER0", 7) == 0) - return (TYP_CMPRS_KEY); - } - else if (*card == ' ') - { - return (TYP_COMM_KEY); - } - else if (*card == 'B') - { - if (FSTRNCMP (card1, "ITPIX ", 7) == 0) - return (TYP_STRUC_KEY); - if (FSTRNCMP (card1, "LOCKED ", 7) == 0) - return (TYP_STRUC_KEY); - - if (FSTRNCMP (card1, "LANK ", 7) == 0) - return (TYP_NULL_KEY); - - if (FSTRNCMP (card1, "SCALE ", 7) == 0) - return (TYP_SCAL_KEY); - if (FSTRNCMP (card1, "ZERO ", 7) == 0) - return (TYP_SCAL_KEY); - - if (FSTRNCMP (card1, "UNIT ", 7) == 0) - return (TYP_UNIT_KEY); - } - else if (*card == 'C') - { - if (FSTRNCMP (card1, "OMMENT",6) == 0) - { - /* new comment string starting Oct 2001 */ - if (FSTRNCMP (tcard, "COMMENT and Astrophysics', volume 376, page 3", - 47) == 0) - return (TYP_STRUC_KEY); - - /* original COMMENT strings from 1993 - 2001 */ - if (FSTRNCMP (tcard, "COMMENT FITS (Flexible Image Transport System", - 47) == 0) - return (TYP_STRUC_KEY); - if (FSTRNCMP (tcard, "COMMENT Astrophysics Supplement Series v44/p3", - 47) == 0) - return (TYP_STRUC_KEY); - if (FSTRNCMP (tcard, "COMMENT Contact the NASA Science Office of St", - 47) == 0) - return (TYP_STRUC_KEY); - if (FSTRNCMP (tcard, "COMMENT FITS Definition document #100 and oth", - 47) == 0) - return (TYP_STRUC_KEY); - - if (*(card + 7) == ' ') - return (TYP_COMM_KEY); - else - return (TYP_USER_KEY); - } - - if (FSTRNCMP (card1, "HECKSUM", 7) == 0) - return (TYP_CKSUM_KEY); - - if (FSTRNCMP (card1, "ONTINUE", 7) == 0) - return (TYP_CONT_KEY); - - if (FSTRNCMP (card1, "TYPE",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "UNIT",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "RVAL",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "RPIX",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "ROTA",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "RDER",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "SYER",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "DELT",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (*card1 == 'D') - { - if (*(card + 2) >= '0' && *(card + 2) <= '9') - return (TYP_WCS_KEY); - } - } - else if (*card == 'D') - { - if (FSTRNCMP (card1, "ATASUM ", 7) == 0) - return (TYP_CKSUM_KEY); - if (FSTRNCMP (card1, "ATAMIN ", 7) == 0) - return (TYP_RANG_KEY); - if (FSTRNCMP (card1, "ATAMAX ", 7) == 0) - return (TYP_RANG_KEY); - if (FSTRNCMP (card1, "ATE-OBS", 7) == 0) - return (TYP_REFSYS_KEY); } - else if (*card == 'E') - { - if (FSTRNCMP (card1, "XTEND ", 7) == 0) - return (TYP_STRUC_KEY); - if (FSTRNCMP (card1, "ND ", 7) == 0) - return (TYP_STRUC_KEY); - if (FSTRNCMP (card1, "XTNAME ", 7) == 0) - { - /* check for special compressed image value */ - if (FSTRNCMP(tcard, "EXTNAME = 'COMPRESSED_IMAGE'", 28) == 0) - return (TYP_CMPRS_KEY); - else - return (TYP_HDUID_KEY); - } - if (FSTRNCMP (card1, "XTVER ", 7) == 0) - return (TYP_HDUID_KEY); - if (FSTRNCMP (card1, "XTLEVEL", 7) == 0) - return (TYP_HDUID_KEY); - - if (FSTRNCMP (card1, "QUINOX", 6) == 0) - return (TYP_REFSYS_KEY); - if (FSTRNCMP (card1, "QUI",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_REFSYS_KEY); - } - if (FSTRNCMP (card1, "POCH ", 7) == 0) - return (TYP_REFSYS_KEY); - } - else if (*card == 'G') - { - if (FSTRNCMP (card1, "COUNT ", 7) == 0) - return (TYP_STRUC_KEY); - if (FSTRNCMP (card1, "ROUPS ", 7) == 0) - return (TYP_STRUC_KEY); - } - else if (*card == 'H') - { - if (FSTRNCMP (card1, "DUNAME ", 7) == 0) - return (TYP_HDUID_KEY); - if (FSTRNCMP (card1, "DUVER ", 7) == 0) - return (TYP_HDUID_KEY); - if (FSTRNCMP (card1, "DULEVEL", 7) == 0) - return (TYP_HDUID_KEY); - - if (FSTRNCMP (card1, "ISTORY",6) == 0) - { - if (*(card + 7) == ' ') - return (TYP_COMM_KEY); - else - return (TYP_USER_KEY); - } - } - else if (*card == 'L') - { - if (FSTRNCMP (card1, "ONPOLE",6) == 0) - return (TYP_WCS_KEY); - if (FSTRNCMP (card1, "ATPOLE",6) == 0) - return (TYP_WCS_KEY); - if (FSTRNCMP (card1, "ONP",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "ATP",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - } - else if (*card == 'M') - { - if (FSTRNCMP (card1, "JD-OBS ", 7) == 0) - return (TYP_REFSYS_KEY); - if (FSTRNCMP (card1, "JDOB",4) == 0) - { - if (*(card+5) >= '0' && *(card+5) <= '9') - return (TYP_REFSYS_KEY); - } - } - else if (*card == 'N') - { - if (FSTRNCMP (card1, "AXIS", 4) == 0) - { - if ((*card5 >= '0' && *card5 <= '9') - || (*card5 == ' ')) - return (TYP_STRUC_KEY); - } - } - else if (*card == 'P') - { - if (FSTRNCMP (card1, "COUNT ", 7) == 0) - return (TYP_STRUC_KEY); - if (*card1 == 'C') - { - if (*(card + 2) >= '0' && *(card + 2) <= '9') - return (TYP_WCS_KEY); - } - else if (*card1 == 'V') - { - if (*(card + 2) >= '0' && *(card + 2) <= '9') - return (TYP_WCS_KEY); - } - else if (*card1 == 'S') - { - if (*(card + 2) >= '0' && *(card + 2) <= '9') - return (TYP_WCS_KEY); - } - } - else if (*card == 'R') - { - if (FSTRNCMP (card1, "ADECSYS", 7) == 0) - return (TYP_REFSYS_KEY); - if (FSTRNCMP (card1, "ADESYS", 6) == 0) - return (TYP_REFSYS_KEY); - if (FSTRNCMP (card1, "ADE",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_REFSYS_KEY); - } - } - else if (*card == 'S') - { - if (FSTRNCMP (card1, "IMPLE ", 7) == 0) - return (TYP_STRUC_KEY); - } - else if (*card == 'T') - { - if (FSTRNCMP (card1, "TYPE", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_STRUC_KEY); - } - else if (FSTRNCMP (card1, "FORM", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_STRUC_KEY); - } - else if (FSTRNCMP (card1, "BCOL", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_STRUC_KEY); - } - else if (FSTRNCMP (card1, "FIELDS ", 7) == 0) - return (TYP_STRUC_KEY); - else if (FSTRNCMP (card1, "HEAP ", 7) == 0) - return (TYP_STRUC_KEY); - - else if (FSTRNCMP (card1, "NULL", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_NULL_KEY); - } - - else if (FSTRNCMP (card1, "DIM", 3) == 0) - { - if (*(card + 4) >= '0' && *(card + 4) <= '9') - return (TYP_DIM_KEY); - } - - else if (FSTRNCMP (card1, "UNIT", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_UNIT_KEY); - } - - else if (FSTRNCMP (card1, "DISP", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_DISP_KEY); - } - - else if (FSTRNCMP (card1, "SCAL", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_SCAL_KEY); - } - else if (FSTRNCMP (card1, "ZERO", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_SCAL_KEY); - } - - else if (FSTRNCMP (card1, "LMIN", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_RANG_KEY); - } - else if (FSTRNCMP (card1, "LMAX", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_RANG_KEY); - } - else if (FSTRNCMP (card1, "DMIN", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_RANG_KEY); - } - else if (FSTRNCMP (card1, "DMAX", 4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_RANG_KEY); - } - - else if (FSTRNCMP (card1, "CTYP",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CTY",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CUNI",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CUN",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CRVL",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CRV",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CRPX",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CRP",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CROT",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CDLT",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CDE",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CRD",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CSY",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "WCS",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "C",1) == 0) - { - if (*(card + 2) >= '0' && *(card + 2) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "P",1) == 0) - { - if (*(card + 2) >= '0' && *(card + 2) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "V",1) == 0) - { - if (*(card + 2) >= '0' && *(card + 2) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "S",1) == 0) - { - if (*(card + 2) >= '0' && *(card + 2) <= '9') - return (TYP_WCS_KEY); - } - } - else if (*card == 'X') - { - if (FSTRNCMP (card1, "TENSION", 7) == 0) - return (TYP_STRUC_KEY); - } - else if (*card == 'W') - { - if (FSTRNCMP (card1, "CSAXES", 6) == 0) - return (TYP_WCS_KEY); - if (FSTRNCMP (card1, "CSNAME", 6) == 0) - return (TYP_WCS_KEY); - if (FSTRNCMP (card1, "CAX", 3) == 0) - { - if (*(card + 4) >= '0' && *(card + 4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CSN", 3) == 0) - { - if (*(card + 4) >= '0' && *(card + 4) <= '9') - return (TYP_WCS_KEY); - } - } - - else if (*card >= '0' && *card <= '9') - { - if (*card1 == 'C') - { - if (FSTRNCMP (card1, "CTYP",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CTY",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CUNI",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CUN",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CRVL",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CRV",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CRPX",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CRP",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CROT",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CDLT",4) == 0) - { - if (*card5 >= '0' && *card5 <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CDE",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CRD",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "CSY",3) == 0) - { - if (*(card+4) >= '0' && *(card+4) <= '9') - return (TYP_WCS_KEY); - } - } - else if (FSTRNCMP (card1, "V",1) == 0) - { - if (*(card + 2) >= '0' && *(card + 2) <= '9') - return (TYP_WCS_KEY); - } - else if (FSTRNCMP (card1, "S",1) == 0) - { - if (*(card + 2) >= '0' && *(card + 2) <= '9') - return (TYP_WCS_KEY); - } - else if (*card1 >= '0' && *card1 <= '9') - { /* 2 digits at beginning of keyword */ - - if ( (*(card + 2) == 'P') && (*(card + 3) == 'C') ) - { - if (*(card + 4) >= '0' && *(card + 4) <= '9') - return (TYP_WCS_KEY); /* ijPCn keyword */ - } - else if ( (*(card + 2) == 'C') && (*(card + 3) == 'D') ) - { - if (*(card + 4) >= '0' && *(card + 4) <= '9') - return (TYP_WCS_KEY); /* ijCDn keyword */ - } - } - - } - - return (TYP_USER_KEY); /* by default all others are user keywords */ -} -/*--------------------------------------------------------------------------*/ -int ffdtyp(const char *cval, /* I - formatted string representation of the value */ - char *dtype, /* O - datatype code: C, L, F, I, or X */ - int *status) /* IO - error status */ -/* - determine implicit datatype of input string. - This assumes that the string conforms to the FITS standard - for keyword values, so may not detect all invalid formats. -*/ -{ - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - if (cval[0] == '\0') - return(*status = VALUE_UNDEFINED); - else if (cval[0] == '\'') - *dtype = 'C'; /* character string starts with a quote */ - else if (cval[0] == 'T' || cval[0] == 'F') - *dtype = 'L'; /* logical = T or F character */ - else if (cval[0] == '(') - *dtype = 'X'; /* complex datatype "(1.2, -3.4)" */ - else if (strchr(cval,'.')) - *dtype = 'F'; /* float usualy contains a decimal point */ - else if (strchr(cval,'E') || strchr(cval,'D') ) - *dtype = 'F'; /* exponential contains a E or D */ - else - *dtype = 'I'; /* if none of the above assume it is integer */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffinttyp(char *cval, /* I - formatted string representation of the integer */ - int *dtype, /* O - datatype code: TBYTE, TSHORT, TUSHORT, etc */ - int *negative, /* O - is cval negative? */ - int *status) /* IO - error status */ -/* - determine implicit datatype of input integer string. - This assumes that the string conforms to the FITS standard - for integer keyword value, so may not detect all invalid formats. -*/ -{ - int ii, len; - char *p; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - *dtype = 0; /* initialize to NULL */ - *negative = 0; - p = cval; - - if (*p == '+') { - p++; /* ignore leading + sign */ - } else if (*p == '-') { - p++; - *negative = 1; /* this is a negative number */ - } - - if (*p == '0') { - while (*p == '0') p++; /* skip leading zeros */ - - if (*p == 0) { /* the value is a string of 1 or more zeros */ - *dtype = TSBYTE; - return(*status); - } - } - - len = strlen(p); - for (ii = 0; ii < len; ii++) { - if (!isdigit(*(p+ii))) { - *status = BAD_INTKEY; - return(*status); - } - } - - /* check for unambiguous cases, based on length of the string */ - if (len == 0) { - *status = VALUE_UNDEFINED; - } else if (len < 3) { - *dtype = TSBYTE; - } else if (len == 4) { - *dtype = TSHORT; - } else if (len > 5 && len < 10) { - *dtype = TINT; - } else if (len > 10 && len < 19) { - *dtype = TLONGLONG; - } else if (len > 19) { - *status = BAD_INTKEY; - } else { - - if (!(*negative)) { /* positive integers */ - if (len == 3) { - if (strcmp(p,"127") <= 0 ) { - *dtype = TSBYTE; - } else if (strcmp(p,"255") <= 0 ) { - *dtype = TBYTE; - } else { - *dtype = TSHORT; - } - } else if (len == 5) { - if (strcmp(p,"32767") <= 0 ) { - *dtype = TSHORT; - } else if (strcmp(p,"65535") <= 0 ) { - *dtype = TUSHORT; - } else { - *dtype = TINT; - } - } else if (len == 10) { - if (strcmp(p,"2147483647") <= 0 ) { - *dtype = TINT; - } else if (strcmp(p,"4294967295") <= 0 ) { - *dtype = TUINT; - } else { - *dtype = TLONGLONG; - } - } else if (len == 19) { - if (strcmp(p,"9223372036854775807") <= 0 ) { - *dtype = TLONGLONG; - } else { - *status = BAD_INTKEY; - } - } - - } else { /* negative integers */ - if (len == 3) { - if (strcmp(p,"128") <= 0 ) { - *dtype = TSBYTE; - } else { - *dtype = TSHORT; - } - } else if (len == 5) { - if (strcmp(p,"32768") <= 0 ) { - *dtype = TSHORT; - } else { - *dtype = TINT; - } - } else if (len == 10) { - if (strcmp(p,"2147483648") <= 0 ) { - *dtype = TINT; - } else { - *dtype = TLONGLONG; - } - } else if (len == 19) { - if (strcmp(p,"9223372036854775808") <= 0 ) { - *dtype = TLONGLONG; - } else { - *status = BAD_INTKEY; - } - } - } - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2x(const char *cval, /* I - formatted string representation of the value */ - char *dtype, /* O - datatype code: C, L, F, I or X */ - - /* Only one of the following will be defined, depending on datatype */ - long *ival, /* O - integer value */ - int *lval, /* O - logical value */ - char *sval, /* O - string value */ - double *dval, /* O - double value */ - - int *status) /* IO - error status */ -/* - high level routine to convert formatted character string to its - intrinsic data type -*/ -{ - ffdtyp(cval, dtype, status); /* determine the datatype */ - - if (*dtype == 'I') - ffc2ii(cval, ival, status); - else if (*dtype == 'F') - ffc2dd(cval, dval, status); - else if (*dtype == 'L') - ffc2ll(cval, lval, status); - else - ffc2s(cval, sval, status); /* C and X formats */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2xx(const char *cval, /* I - formatted string representation of the value */ - char *dtype, /* O - datatype code: C, L, F, I or X */ - - /* Only one of the following will be defined, depending on datatype */ - LONGLONG *ival, /* O - integer value */ - int *lval, /* O - logical value */ - char *sval, /* O - string value */ - double *dval, /* O - double value */ - - int *status) /* IO - error status */ -/* - high level routine to convert formatted character string to its - intrinsic data type -*/ -{ - ffdtyp(cval, dtype, status); /* determine the datatype */ - - if (*dtype == 'I') - ffc2jj(cval, ival, status); - else if (*dtype == 'F') - ffc2dd(cval, dval, status); - else if (*dtype == 'L') - ffc2ll(cval, lval, status); - else - ffc2s(cval, sval, status); /* C and X formats */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2i(const char *cval, /* I - string representation of the value */ - long *ival, /* O - numerical value of the input string */ - int *status) /* IO - error status */ -/* - convert formatted string to an integer value, doing implicit - datatype conversion if necessary. -*/ -{ - char dtype, sval[81], msg[81]; - int lval; - double dval; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - if (cval[0] == '\0') - return(*status = VALUE_UNDEFINED); /* null value string */ - - /* convert the keyword to its native datatype */ - ffc2x(cval, &dtype, ival, &lval, sval, &dval, status); - - if (dtype == 'X' ) - { - *status = BAD_INTKEY; - } - else if (dtype == 'C') - { - /* try reading the string as a number */ - if (ffc2dd(sval, &dval, status) <= 0) - { - if (dval > (double) LONG_MAX || dval < (double) LONG_MIN) - *status = NUM_OVERFLOW; - else - *ival = (long) dval; - } - } - else if (dtype == 'F') - { - if (dval > (double) LONG_MAX || dval < (double) LONG_MIN) - *status = NUM_OVERFLOW; - else - *ival = (long) dval; - } - else if (dtype == 'L') - { - *ival = (long) lval; - } - - if (*status > 0) - { - *ival = 0; - strcpy(msg,"Error in ffc2i evaluating string as an integer: "); - strncat(msg,cval,30); - ffpmsg(msg); - return(*status); - } - - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2j(const char *cval, /* I - string representation of the value */ - LONGLONG *ival, /* O - numerical value of the input string */ - int *status) /* IO - error status */ -/* - convert formatted string to a LONGLONG integer value, doing implicit - datatype conversion if necessary. -*/ -{ - char dtype, sval[81], msg[81]; - int lval; - double dval; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - if (cval[0] == '\0') - return(*status = VALUE_UNDEFINED); /* null value string */ - - /* convert the keyword to its native datatype */ - ffc2xx(cval, &dtype, ival, &lval, sval, &dval, status); - - if (dtype == 'X' ) - { - *status = BAD_INTKEY; - } - else if (dtype == 'C') - { - /* try reading the string as a number */ - if (ffc2dd(sval, &dval, status) <= 0) - { - if (dval > (double) LONGLONG_MAX || dval < (double) LONGLONG_MIN) - *status = NUM_OVERFLOW; - else - *ival = (LONGLONG) dval; - } - } - else if (dtype == 'F') - { - if (dval > (double) LONGLONG_MAX || dval < (double) LONGLONG_MIN) - *status = NUM_OVERFLOW; - else - *ival = (LONGLONG) dval; - } - else if (dtype == 'L') - { - *ival = (LONGLONG) lval; - } - - if (*status > 0) - { - *ival = 0; - strcpy(msg,"Error in ffc2j evaluating string as a long integer: "); - strncat(msg,cval,30); - ffpmsg(msg); - return(*status); - } - - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2l(const char *cval, /* I - string representation of the value */ - int *lval, /* O - numerical value of the input string */ - int *status) /* IO - error status */ -/* - convert formatted string to a logical value, doing implicit - datatype conversion if necessary -*/ -{ - char dtype, sval[81], msg[81]; - long ival; - double dval; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - if (cval[0] == '\0') - return(*status = VALUE_UNDEFINED); /* null value string */ - - /* convert the keyword to its native datatype */ - ffc2x(cval, &dtype, &ival, lval, sval, &dval, status); - - if (dtype == 'C' || dtype == 'X' ) - *status = BAD_LOGICALKEY; - - if (*status > 0) - { - *lval = 0; - strcpy(msg,"Error in ffc2l evaluating string as a logical: "); - strncat(msg,cval,30); - ffpmsg(msg); - return(*status); - } - - if (dtype == 'I') - { - if (ival) - *lval = 1; - else - *lval = 0; - } - else if (dtype == 'F') - { - if (dval) - *lval = 1; - else - *lval = 0; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2r(const char *cval, /* I - string representation of the value */ - float *fval, /* O - numerical value of the input string */ - int *status) /* IO - error status */ -/* - convert formatted string to a real float value, doing implicit - datatype conversion if necessary -*/ -{ - char dtype, sval[81], msg[81]; - int lval; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - if (cval[0] == '\0') - return(*status = VALUE_UNDEFINED); /* null value string */ - - ffdtyp(cval, &dtype, status); /* determine the datatype */ - - if (dtype == 'I' || dtype == 'F') - ffc2rr(cval, fval, status); - else if (dtype == 'L') - { - ffc2ll(cval, &lval, status); - *fval = (float) lval; - } - else if (dtype == 'C') - { - /* try reading the string as a number */ - ffc2s(cval, sval, status); - ffc2rr(sval, fval, status); - } - else - *status = BAD_FLOATKEY; - - if (*status > 0) - { - *fval = 0.; - strcpy(msg,"Error in ffc2r evaluating string as a float: "); - strncat(msg,cval,30); - ffpmsg(msg); - return(*status); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2d(const char *cval, /* I - string representation of the value */ - double *dval, /* O - numerical value of the input string */ - int *status) /* IO - error status */ -/* - convert formatted string to a double value, doing implicit - datatype conversion if necessary -*/ -{ - char dtype, sval[81], msg[81]; - int lval; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - if (cval[0] == '\0') - return(*status = VALUE_UNDEFINED); /* null value string */ - - ffdtyp(cval, &dtype, status); /* determine the datatype */ - - if (dtype == 'I' || dtype == 'F') - ffc2dd(cval, dval, status); - else if (dtype == 'L') - { - ffc2ll(cval, &lval, status); - *dval = (double) lval; - } - else if (dtype == 'C') - { - /* try reading the string as a number */ - ffc2s(cval, sval, status); - ffc2dd(sval, dval, status); - } - else - *status = BAD_DOUBLEKEY; - - if (*status > 0) - { - *dval = 0.; - strcpy(msg,"Error in ffc2d evaluating string as a double: "); - strncat(msg,cval,30); - ffpmsg(msg); - return(*status); - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2ii(const char *cval, /* I - string representation of the value */ - long *ival, /* O - numerical value of the input string */ - int *status) /* IO - error status */ -/* - convert null-terminated formatted string to an integer value -*/ -{ - char *loc, msg[81]; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - errno = 0; - *ival = 0; - *ival = strtol(cval, &loc, 10); /* read the string as an integer */ - - /* check for read error, or junk following the integer */ - if (*loc != '\0' && *loc != ' ' ) - *status = BAD_C2I; - - if (errno == ERANGE) - { - strcpy(msg,"Range Error in ffc2ii converting string to long int: "); - strncat(msg,cval,25); - ffpmsg(msg); - - *status = NUM_OVERFLOW; - errno = 0; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2jj(const char *cval, /* I - string representation of the value */ - LONGLONG *ival, /* O - numerical value of the input string */ - int *status) /* IO - error status */ -/* - convert null-terminated formatted string to an long long integer value -*/ -{ - char *loc, msg[81]; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - errno = 0; - *ival = 0; - -#if defined(_MSC_VER) - - /* Microsoft Visual C++ 6.0 does not have the strtoll function */ - *ival = _atoi64(cval); - loc = (char *) cval; - while (*loc == ' ') loc++; /* skip spaces */ - if (*loc == '-') loc++; /* skip minus sign */ - if (*loc == '+') loc++; /* skip plus sign */ - while (isdigit(*loc)) loc++; /* skip digits */ - -#elif (USE_LL_SUFFIX == 1) - *ival = strtoll(cval, &loc, 10); /* read the string as an integer */ -#else - *ival = strtol(cval, &loc, 10); /* read the string as an integer */ -#endif - - /* check for read error, or junk following the integer */ - if (*loc != '\0' && *loc != ' ' ) - *status = BAD_C2I; - - if (errno == ERANGE) - { - strcpy(msg,"Range Error in ffc2jj converting string to longlong int: "); - strncat(msg,cval,25); - ffpmsg(msg); - - *status = NUM_OVERFLOW; - errno = 0; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2ll(const char *cval, /* I - string representation of the value: T or F */ - int *lval, /* O - numerical value of the input string: 1 or 0 */ - int *status) /* IO - error status */ -/* - convert null-terminated formatted string to a logical value -*/ -{ - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - if (cval[0] == 'T') - *lval = 1; - else - *lval = 0; /* any character besides T is considered false */ - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2s(const char *instr, /* I - null terminated quoted input string */ - char *outstr, /* O - null terminated output string without quotes */ - int *status) /* IO - error status */ -/* - convert an input quoted string to an unquoted string by removing - the leading and trailing quote character. Also, replace any - pairs of single quote characters with just a single quote - character (FITS used a pair of single quotes to represent - a literal quote character within the string). -*/ -{ - int jj; - size_t len, ii; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - if (instr[0] != '\'') - { - if (instr[0] == '\0') { - outstr[0] = '\0'; - return(*status = VALUE_UNDEFINED); /* null value string */ - } else { - strcpy(outstr, instr); /* no leading quote, so return input string */ - return(*status); - } - } - - len = strlen(instr); - - for (ii=1, jj=0; ii < len; ii++, jj++) - { - if (instr[ii] == '\'') /* is this the closing quote? */ - { - if (instr[ii+1] == '\'') /* 2 successive quotes? */ - ii++; /* copy only one of the quotes */ - else - break; /* found the closing quote, so exit this loop */ - } - outstr[jj] = instr[ii]; /* copy the next character to the output */ - } - - outstr[jj] = '\0'; /* terminate the output string */ - - if (ii == len) - { - ffpmsg("This string value has no closing quote (ffc2s):"); - ffpmsg(instr); - return(*status = 205); - } - - for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ - { - if (outstr[jj] == ' ') - outstr[jj] = 0; - else - break; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2rr(const char *cval, /* I - string representation of the value */ - float *fval, /* O - numerical value of the input string */ - int *status) /* IO - error status */ -/* - convert null-terminated formatted string to a float value -*/ -{ - char *loc, msg[81], tval[73]; - struct lconv *lcc = 0; - static char decimalpt = 0; - short *sptr, iret; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - if (!decimalpt) { /* only do this once for efficiency */ - lcc = localeconv(); /* set structure containing local decimal point symbol */ - decimalpt = *(lcc->decimal_point); - } - - errno = 0; - *fval = 0.; - - if (strchr(cval, 'D') || decimalpt == ',') { - /* strtod expects a comma, not a period, as the decimal point */ - strcpy(tval, cval); - - /* The C language does not support a 'D'; replace with 'E' */ - if ((loc = strchr(tval, 'D'))) *loc = 'E'; - - if (decimalpt == ',') { - /* strtod expects a comma, not a period, as the decimal point */ - if ((loc = strchr(tval, '.'))) *loc = ','; - } - - *fval = (float) strtod(tval, &loc); /* read the string as an float */ - } else { - *fval = (float) strtod(cval, &loc); - } - - /* check for read error, or junk following the value */ - if (*loc != '\0' && *loc != ' ' ) - { - strcpy(msg,"Error in ffc2rr converting string to float: "); - strncat(msg,cval,30); - ffpmsg(msg); - - *status = BAD_C2F; - } - - sptr = (short *) fval; -#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS - sptr++; /* point to MSBs */ -#endif - iret = fnan(*sptr); /* if iret == 1, then the float value is a NaN */ - - if (errno == ERANGE || (iret == 1) ) - { - strcpy(msg,"Error in ffc2rr converting string to float: "); - strncat(msg,cval,30); - ffpmsg(msg); - *fval = 0.; - - *status = NUM_OVERFLOW; - errno = 0; - } - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int ffc2dd(const char *cval, /* I - string representation of the value */ - double *dval, /* O - numerical value of the input string */ - int *status) /* IO - error status */ -/* - convert null-terminated formatted string to a double value -*/ -{ - char *loc, msg[81], tval[73]; - struct lconv *lcc = 0; - static char decimalpt = 0; - short *sptr, iret; - - if (*status > 0) /* inherit input status value if > 0 */ - return(*status); - - if (!decimalpt) { /* only do this once for efficiency */ - lcc = localeconv(); /* set structure containing local decimal point symbol */ - decimalpt = *(lcc->decimal_point); - } - - errno = 0; - *dval = 0.; - - if (strchr(cval, 'D') || decimalpt == ',') { - /* need to modify a temporary copy of the string before parsing it */ - strcpy(tval, cval); - /* The C language does not support a 'D'; replace with 'E' */ - if ((loc = strchr(tval, 'D'))) *loc = 'E'; - - if (decimalpt == ',') { - /* strtod expects a comma, not a period, as the decimal point */ - if ((loc = strchr(tval, '.'))) *loc = ','; - } - - *dval = strtod(tval, &loc); /* read the string as an double */ - } else { - *dval = strtod(cval, &loc); - } - - /* check for read error, or junk following the value */ - if (*loc != '\0' && *loc != ' ' ) - { - strcpy(msg,"Error in ffc2dd converting string to double: "); - strncat(msg,cval,30); - ffpmsg(msg); - - *status = BAD_C2D; - } - - sptr = (short *) dval; -#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS - sptr += 3; /* point to MSBs */ -#endif - iret = dnan(*sptr); /* if iret == 1, then the double value is a NaN */ - - if (errno == ERANGE || (iret == 1) ) - { - strcpy(msg,"Error in ffc2dd converting string to double: "); - strncat(msg,cval,30); - ffpmsg(msg); - *dval = 0.; - - *status = NUM_OVERFLOW; - errno = 0; - } - - return(*status); -} - -/* ================================================================== */ -/* A hack for nonunix machines, which lack strcasecmp and strncasecmp */ -/* ================================================================== */ - -int fits_strcasecmp(const char *s1, const char *s2) -{ - char c1, c2; - - for (;;) { - c1 = toupper( *s1 ); - c2 = toupper( *s2 ); - - if (c1 < c2) return(-1); - if (c1 > c2) return(1); - if (c1 == 0) return(0); - s1++; - s2++; - } -} - -int fits_strncasecmp(const char *s1, const char *s2, size_t n) -{ - char c1, c2; - - for (; n-- ;) { - c1 = toupper( *s1 ); - c2 = toupper( *s2 ); - - if (c1 < c2) return(-1); - if (c1 > c2) return(1); - if (c1 == 0) return(0); - s1++; - s2++; - } - return(0); -} diff --git a/src/external/OpenGR/3rdparty/cfitsio/fitsio.h b/src/external/OpenGR/3rdparty/cfitsio/fitsio.h deleted file mode 100644 index ec26d9dca..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/fitsio.h +++ /dev/null @@ -1,2001 +0,0 @@ -/* The FITSIO software was written by William Pence at the High Energy */ -/* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ -/* Goddard Space Flight Center. */ -/* - -Copyright (Unpublished--all rights reserved under the copyright laws of -the United States), U.S. Government as represented by the Administrator -of the National Aeronautics and Space Administration. No copyright is -claimed in the United States under Title 17, U.S. Code. - -Permission to freely use, copy, modify, and distribute this software -and its documentation without fee is hereby granted, provided that this -copyright notice and disclaimer of warranty appears in all copies. - -DISCLAIMER: - -THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, -EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, -ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY -IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE -DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE -SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY -DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR -CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY -CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, -CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY -PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED -FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR -SERVICES PROVIDED HEREUNDER." - -*/ - -#ifndef _FITSIO_H -#define _FITSIO_H - -#define CFITSIO_VERSION 3.41 -#define CFITSIO_MINOR 41 -#define CFITSIO_MAJOR 3 -#define CFITSIO_SONAME 5 - -/* the SONAME is incremented in a new release if the binary shared */ -/* library (on linux and Mac systems) is not backward compatible */ -/* with the previous release of CFITSIO */ - - -/* CFITS_API is defined below for use on Windows systems. */ -/* It is used to identify the public functions which should be exported. */ -/* This has no effect on non-windows platforms where "WIN32" is not defined */ - -#if defined (WIN32) - #if defined(cfitsio_EXPORTS) - #define CFITS_API __declspec(dllexport) - #else - #define CFITS_API /* __declspec(dllimport) */ - #endif /* CFITS_API */ -#else /* defined (WIN32) */ - #define CFITS_API -#endif - -#include - -/* the following was provided by Michael Greason (GSFC) to fix a */ -/* C/Fortran compatibility problem on an SGI Altix system running */ -/* SGI ProPack 4 [this is a Novell SuSE Enterprise 9 derivative] */ -/* and using the Intel C++ and Fortran compilers (version 9.1) */ -#if defined(__INTEL_COMPILER) && defined(__itanium__) -# define mipsFortran 1 -# define _MIPS_SZLONG 64 -#endif - -#if defined(linux) || defined(__APPLE__) || defined(__sgi) -# include /* apparently needed on debian linux systems */ -#endif /* to define off_t */ - -#include /* apparently needed to define size_t with gcc 2.8.1 */ -#include /* needed for LLONG_MAX and INT64_MAX definitions */ - -/* Define the datatype for variables which store file offset values. */ -/* The newer 'off_t' datatype should be used for this purpose, but some */ -/* older compilers do not recognize this type, in which case we use 'long' */ -/* instead. Note that _OFF_T is defined (or not) in stdio.h depending */ -/* on whether _LARGEFILE_SOURCE is defined in sys/feature_tests.h */ -/* (at least on Solaris platforms using cc) */ - -/* Debian systems require: "(defined(linux) && defined(__off_t_defined))" */ -/* the mingw-w64 compiler requires: "(defined(__MINGW32__) && defined(_OFF_T_DEFINED))" */ -#if defined(_OFF_T) \ - || (defined(linux) && defined(__off_t_defined)) \ - || (defined(__MINGW32__) && defined(_OFF_T_DEFINED)) \ - || defined(_MIPS_SZLONG) || defined(__APPLE__) || defined(_AIX) -# define OFF_T off_t -#elif defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER>= 1400)) -# define OFF_T long long -#else -# define OFF_T long -#endif - -/* this block determines if the the string function name is - strtol or strtoll, and whether to use %ld or %lld in printf statements */ - -/* - The following 2 cases for that Athon64 were removed on 4 Jan 2006; - they appear to be incorrect now that LONGLONG is always typedef'ed - to 'long long' - || defined(__ia64__) \ - || defined(__x86_64__) \ -*/ -#if (defined(__alpha) && ( defined(__unix__) || defined(__NetBSD__) )) \ - || defined(__sparcv9) || (defined(__sparc__) && defined(__arch64__)) \ - || defined(__powerpc64__) || defined(__64BIT__) \ - || (defined(_MIPS_SZLONG) && _MIPS_SZLONG == 64) \ - || defined( _MSC_VER)|| defined(__BORLANDC__) - -# define USE_LL_SUFFIX 0 -#else -# define USE_LL_SUFFIX 1 -#endif - -/* - Determine what 8-byte integer data type is available. - 'long long' is now supported by most compilers, but - older MS Visual C++ compilers before V7.0 use '__int64' instead. -*/ - -#ifndef LONGLONG_TYPE /* this may have been previously defined */ -#if defined(_MSC_VER) /* Microsoft Visual C++ */ - -#if (_MSC_VER < 1300) /* versions earlier than V7.0 do not have 'long long' */ - typedef __int64 LONGLONG; -#else /* newer versions do support 'long long' */ - typedef long long LONGLONG; -#endif - -#elif defined( __BORLANDC__) /* for the Borland 5.5 compiler, in particular */ - typedef __int64 LONGLONG; -#else - typedef long long LONGLONG; -#endif - -#define LONGLONG_TYPE -#endif - -#ifndef LONGLONG_MAX - -#ifdef LLONG_MAX -/* Linux and Solaris definition */ -#define LONGLONG_MAX LLONG_MAX -#define LONGLONG_MIN LLONG_MIN - -#elif defined(LONG_LONG_MAX) -#define LONGLONG_MAX LONG_LONG_MAX -#define LONGLONG_MIN LONG_LONG_MIN - -#elif defined(__LONG_LONG_MAX__) -/* Mac OS X & CYGWIN defintion */ -#define LONGLONG_MAX __LONG_LONG_MAX__ -#define LONGLONG_MIN (-LONGLONG_MAX -1LL) - -#elif defined(INT64_MAX) -/* windows definition */ -#define LONGLONG_MAX INT64_MAX -#define LONGLONG_MIN INT64_MIN - -#elif defined(_I64_MAX) -/* windows definition */ -#define LONGLONG_MAX _I64_MAX -#define LONGLONG_MIN _I64_MIN - -#elif (defined(__alpha) && ( defined(__unix__) || defined(__NetBSD__) )) \ - || defined(__sparcv9) \ - || defined(__ia64__) \ - || defined(__x86_64__) \ - || defined(_SX) \ - || defined(__powerpc64__) || defined(__64BIT__) \ - || (defined(_MIPS_SZLONG) && _MIPS_SZLONG == 64) -/* sizeof(long) = 64 */ -#define LONGLONG_MAX 9223372036854775807L /* max 64-bit integer */ -#define LONGLONG_MIN (-LONGLONG_MAX -1L) /* min 64-bit integer */ - -#else -/* define a default value, even if it is never used */ -#define LONGLONG_MAX 9223372036854775807LL /* max 64-bit integer */ -#define LONGLONG_MIN (-LONGLONG_MAX -1LL) /* min 64-bit integer */ - -#endif -#endif /* end of ndef LONGLONG_MAX section */ - - -/* ================================================================= */ - - -/* The following exclusion if __CINT__ is defined is needed for ROOT */ -#ifndef __CINT__ -#include "longnam.h" -#endif - -#define NIOBUF 40 /* number of IO buffers to create (default = 40) */ - /* !! Significantly increasing NIOBUF may degrade performance !! */ - -#define IOBUFLEN 2880 /* size in bytes of each IO buffer (DONT CHANGE!) */ - -/* global variables */ - -#define FLEN_FILENAME 1025 /* max length of a filename */ -#define FLEN_KEYWORD 75 /* max length of a keyword (HIERARCH convention) */ -#define FLEN_CARD 81 /* length of a FITS header card */ -#define FLEN_VALUE 71 /* max length of a keyword value string */ -#define FLEN_COMMENT 73 /* max length of a keyword comment string */ -#define FLEN_ERRMSG 81 /* max length of a FITSIO error message */ -#define FLEN_STATUS 31 /* max length of a FITSIO status text string */ - -#define TBIT 1 /* codes for FITS table data types */ -#define TBYTE 11 -#define TSBYTE 12 -#define TLOGICAL 14 -#define TSTRING 16 -#define TUSHORT 20 -#define TSHORT 21 -#define TUINT 30 -#define TINT 31 -#define TULONG 40 -#define TLONG 41 -#define TINT32BIT 41 /* used when returning datatype of a column */ -#define TFLOAT 42 -#define TLONGLONG 81 -#define TDOUBLE 82 -#define TCOMPLEX 83 -#define TDBLCOMPLEX 163 - -#define TYP_STRUC_KEY 10 -#define TYP_CMPRS_KEY 20 -#define TYP_SCAL_KEY 30 -#define TYP_NULL_KEY 40 -#define TYP_DIM_KEY 50 -#define TYP_RANG_KEY 60 -#define TYP_UNIT_KEY 70 -#define TYP_DISP_KEY 80 -#define TYP_HDUID_KEY 90 -#define TYP_CKSUM_KEY 100 -#define TYP_WCS_KEY 110 -#define TYP_REFSYS_KEY 120 -#define TYP_COMM_KEY 130 -#define TYP_CONT_KEY 140 -#define TYP_USER_KEY 150 - - -#define INT32BIT int /* 32-bit integer datatype. Currently this */ - /* datatype is an 'int' on all useful platforms */ - /* however, it is possible that that are cases */ - /* where 'int' is a 2-byte integer, in which case */ - /* INT32BIT would need to be defined as 'long'. */ - -#define BYTE_IMG 8 /* BITPIX code values for FITS image types */ -#define SHORT_IMG 16 -#define LONG_IMG 32 -#define LONGLONG_IMG 64 -#define FLOAT_IMG -32 -#define DOUBLE_IMG -64 - /* The following 2 codes are not true FITS */ - /* datatypes; these codes are only used internally */ - /* within cfitsio to make it easier for users */ - /* to deal with unsigned integers. */ -#define SBYTE_IMG 10 -#define USHORT_IMG 20 -#define ULONG_IMG 40 - -#define IMAGE_HDU 0 /* Primary Array or IMAGE HDU */ -#define ASCII_TBL 1 /* ASCII table HDU */ -#define BINARY_TBL 2 /* Binary table HDU */ -#define ANY_HDU -1 /* matches any HDU type */ - -#define READONLY 0 /* options when opening a file */ -#define READWRITE 1 - -/* adopt a hopefully obscure number to use as a null value flag */ -/* could be problems if the FITS files contain data with these values */ -#define FLOATNULLVALUE -9.11912E-36F -#define DOUBLENULLVALUE -9.1191291391491E-36 - -/* compression algorithm codes */ -#define NO_DITHER -1 -#define SUBTRACTIVE_DITHER_1 1 -#define SUBTRACTIVE_DITHER_2 2 -#define MAX_COMPRESS_DIM 6 -#define RICE_1 11 -#define GZIP_1 21 -#define GZIP_2 22 -#define PLIO_1 31 -#define HCOMPRESS_1 41 -#define BZIP2_1 51 /* not publicly supported; only for test purposes */ -#define NOCOMPRESS -1 - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#define CASESEN 1 /* do case-sensitive string match */ -#define CASEINSEN 0 /* do case-insensitive string match */ - -#define GT_ID_ALL_URI 0 /* hierarchical grouping parameters */ -#define GT_ID_REF 1 -#define GT_ID_POS 2 -#define GT_ID_ALL 3 -#define GT_ID_REF_URI 11 -#define GT_ID_POS_URI 12 - -#define OPT_RM_GPT 0 -#define OPT_RM_ENTRY 1 -#define OPT_RM_MBR 2 -#define OPT_RM_ALL 3 - -#define OPT_GCP_GPT 0 -#define OPT_GCP_MBR 1 -#define OPT_GCP_ALL 2 - -#define OPT_MCP_ADD 0 -#define OPT_MCP_NADD 1 -#define OPT_MCP_REPL 2 -#define OPT_MCP_MOV 3 - -#define OPT_MRG_COPY 0 -#define OPT_MRG_MOV 1 - -#define OPT_CMT_MBR 1 -#define OPT_CMT_MBR_DEL 11 - -typedef struct /* structure used to store table column information */ -{ - char ttype[70]; /* column name = FITS TTYPEn keyword; */ - LONGLONG tbcol; /* offset in row to first byte of each column */ - int tdatatype; /* datatype code of each column */ - LONGLONG trepeat; /* repeat count of column; number of elements */ - double tscale; /* FITS TSCALn linear scaling factor */ - double tzero; /* FITS TZEROn linear scaling zero point */ - LONGLONG tnull; /* FITS null value for int image or binary table cols */ - char strnull[20]; /* FITS null value string for ASCII table columns */ - char tform[10]; /* FITS tform keyword value */ - long twidth; /* width of each ASCII table column */ -}tcolumn; - -#define VALIDSTRUC 555 /* magic value used to identify if structure is valid */ - -typedef struct /* structure used to store basic FITS file information */ -{ - int filehandle; /* handle returned by the file open function */ - int driver; /* defines which set of I/O drivers should be used */ - int open_count; /* number of opened 'fitsfiles' using this structure */ - char *filename; /* file name */ - int validcode; /* magic value used to verify that structure is valid */ - int only_one; /* flag meaning only copy the specified extension */ - LONGLONG filesize; /* current size of the physical disk file in bytes */ - LONGLONG logfilesize; /* logical size of file, including unflushed buffers */ - int lasthdu; /* is this the last HDU in the file? 0 = no, else yes */ - LONGLONG bytepos; /* current logical I/O pointer position in file */ - LONGLONG io_pos; /* current I/O pointer position in the physical file */ - int curbuf; /* number of I/O buffer currently in use */ - int curhdu; /* current HDU number; 0 = primary array */ - int hdutype; /* 0 = primary array, 1 = ASCII table, 2 = binary table */ - int writemode; /* 0 = readonly, 1 = readwrite */ - int maxhdu; /* highest numbered HDU known to exist in the file */ - int MAXHDU; /* dynamically allocated dimension of headstart array */ - LONGLONG *headstart; /* byte offset in file to start of each HDU */ - LONGLONG headend; /* byte offest in file to end of the current HDU header */ - LONGLONG ENDpos; /* byte offest to where the END keyword was last written */ - LONGLONG nextkey; /* byte offset in file to beginning of next keyword */ - LONGLONG datastart; /* byte offset in file to start of the current data unit */ - int imgdim; /* dimension of image; cached for fast access */ - LONGLONG imgnaxis[99]; /* length of each axis; cached for fast access */ - int tfield; /* number of fields in the table (primary array has 2 */ - int startcol; /* used by ffgcnn to record starting column number */ - LONGLONG origrows; /* original number of rows (value of NAXIS2 keyword) */ - LONGLONG numrows; /* number of rows in the table (dynamically updated) */ - LONGLONG rowlength; /* length of a table row or image size (bytes) */ - tcolumn *tableptr; /* pointer to the table structure */ - LONGLONG heapstart; /* heap start byte relative to start of data unit */ - LONGLONG heapsize; /* size of the heap, in bytes */ - - /* the following elements are related to compressed images */ - - /* these record the 'requested' options to be used when the image is compressed */ - int request_compress_type; /* requested image compression algorithm */ - long request_tilesize[MAX_COMPRESS_DIM]; /* requested tiling size */ - float request_quantize_level; /* requested quantize level */ - int request_quantize_method ; /* requested quantizing method */ - int request_dither_seed; /* starting offset into the array of random dithering */ - int request_lossy_int_compress; /* lossy compress integer image as if float image? */ - int request_huge_hdu; /* use '1Q' rather then '1P' variable length arrays */ - float request_hcomp_scale; /* requested HCOMPRESS scale factor */ - int request_hcomp_smooth; /* requested HCOMPRESS smooth parameter */ - - /* these record the actual options that were used when the image was compressed */ - int compress_type; /* type of compression algorithm */ - long tilesize[MAX_COMPRESS_DIM]; /* size of compression tiles */ - float quantize_level; /* floating point quantization level */ - int quantize_method; /* floating point pixel quantization algorithm */ - int dither_seed; /* starting offset into the array of random dithering */ - - /* other compression parameters */ - int compressimg; /* 1 if HDU contains a compressed image, else 0 */ - char zcmptype[12]; /* compression type string */ - int zbitpix; /* FITS data type of image (BITPIX) */ - int zndim; /* dimension of image */ - long znaxis[MAX_COMPRESS_DIM]; /* length of each axis */ - long maxtilelen; /* max number of pixels in each image tile */ - long maxelem; /* maximum byte length of tile compressed arrays */ - - int cn_compressed; /* column number for COMPRESSED_DATA column */ - int cn_uncompressed; /* column number for UNCOMPRESSED_DATA column */ - int cn_gzip_data; /* column number for GZIP2 lossless compressed data */ - int cn_zscale; /* column number for ZSCALE column */ - int cn_zzero; /* column number for ZZERO column */ - int cn_zblank; /* column number for the ZBLANK column */ - - double zscale; /* scaling value, if same for all tiles */ - double zzero; /* zero pt, if same for all tiles */ - double cn_bscale; /* value of the BSCALE keyword in header */ - double cn_bzero; /* value of the BZERO keyword (may be reset) */ - double cn_actual_bzero; /* actual value of the BZERO keyword */ - int zblank; /* value for null pixels, if not a column */ - - int rice_blocksize; /* first compression parameter: Rice pixels/block */ - int rice_bytepix; /* 2nd compression parameter: Rice bytes/pixel */ - float hcomp_scale; /* 1st hcompress compression parameter */ - int hcomp_smooth; /* 2nd hcompress compression parameter */ - - int *tilerow; /* row number of the array of uncompressed tiledata */ - long *tiledatasize; /* length of the array of tile data in bytes */ - int *tiletype; /* datatype of the array of tile (TINT, TSHORT, etc) */ - void **tiledata; /* array of uncompressed tile of data, for row *tilerow */ - void **tilenullarray; /* array of optional array of null value flags */ - int *tileanynull; /* anynulls in the array of tile? */ - - char *iobuffer; /* pointer to FITS file I/O buffers */ - long bufrecnum[NIOBUF]; /* file record number of each of the buffers */ - int dirty[NIOBUF]; /* has the corresponding buffer been modified? */ - int ageindex[NIOBUF]; /* relative age of each buffer */ -} FITSfile; - -typedef struct /* structure used to store basic HDU information */ -{ - int HDUposition; /* HDU position in file; 0 = first HDU */ - FITSfile *Fptr; /* pointer to FITS file structure */ -}fitsfile; - -typedef struct /* structure for the iterator function column information */ -{ - /* elements required as input to fits_iterate_data: */ - - fitsfile *fptr; /* pointer to the HDU containing the column */ - int colnum; /* column number in the table (use name if < 1) */ - char colname[70]; /* name (= TTYPEn value) of the column (optional) */ - int datatype; /* output datatype (converted if necessary */ - int iotype; /* = InputCol, InputOutputCol, or OutputCol */ - - /* output elements that may be useful for the work function: */ - - void *array; /* pointer to the array (and the null value) */ - long repeat; /* binary table vector repeat value */ - long tlmin; /* legal minimum data value */ - long tlmax; /* legal maximum data value */ - char tunit[70]; /* physical unit string */ - char tdisp[70]; /* suggested display format */ - -} iteratorCol; - -#define InputCol 0 /* flag for input only iterator column */ -#define InputOutputCol 1 /* flag for input and output iterator column */ -#define OutputCol 2 /* flag for output only iterator column */ - -/*============================================================================= -* -* The following wtbarr typedef is used in the fits_read_wcstab() routine, -* which is intended for use with the WCSLIB library written by Mark -* Calabretta, http://www.atnf.csiro.au/~mcalabre/index.html -* -* In order to maintain WCSLIB and CFITSIO as independent libraries it -* was not permissible for any CFITSIO library code to include WCSLIB -* header files, or vice versa. However, the CFITSIO function -* fits_read_wcstab() accepts an array of structs defined by wcs.h within -* WCSLIB. The problem then was to define this struct within fitsio.h -* without including wcs.h, especially noting that wcs.h will often (but -* not always) be included together with fitsio.h in an applications -* program that uses fits_read_wcstab(). -* -* Of the various possibilities, the solution adopted was for WCSLIB to -* define "struct wtbarr" while fitsio.h defines "typedef wtbarr", a -* untagged struct with identical members. This allows both wcs.h and -* fitsio.h to define a wtbarr data type without conflict by virtue of -* the fact that structure tags and typedef names share different -* namespaces in C. Therefore, declarations within WCSLIB look like -* -* struct wtbarr *w; -* -* while within CFITSIO they are simply -* -* wtbarr *w; -* -* but as suggested by the commonality of the names, these are really the -* same aggregate data type. However, in passing a (struct wtbarr *) to -* fits_read_wcstab() a cast to (wtbarr *) is formally required. -*===========================================================================*/ - -#ifndef WCSLIB_GETWCSTAB -#define WCSLIB_GETWCSTAB - -typedef struct { - int i; /* Image axis number. */ - int m; /* Array axis number for index vectors. */ - int kind; /* Array type, 'c' (coord) or 'i' (index). */ - char extnam[72]; /* EXTNAME of binary table extension. */ - int extver; /* EXTVER of binary table extension. */ - int extlev; /* EXTLEV of binary table extension. */ - char ttype[72]; /* TTYPEn of column containing the array. */ - long row; /* Table row number. */ - int ndim; /* Expected array dimensionality. */ - int *dimlen; /* Where to write the array axis lengths. */ - double **arrayp; /* Where to write the address of the array */ - /* allocated to store the array. */ -} wtbarr; - -/* The following exclusion if __CINT__ is defined is needed for ROOT */ -#ifndef __CINT__ -/* the following 3 lines are needed to support C++ compilers */ -#ifdef __cplusplus -extern "C" { -#endif -#endif - -int CFITS_API fits_read_wcstab(fitsfile *fptr, int nwtb, wtbarr *wtb, int *status); - -/* The following exclusion if __CINT__ is defined is needed for ROOT */ -#ifndef __CINT__ -#ifdef __cplusplus -} -#endif -#endif - -#endif /* WCSLIB_GETWCSTAB */ - -/* error status codes */ - -#define CREATE_DISK_FILE -106 /* create disk file, without extended filename syntax */ -#define OPEN_DISK_FILE -105 /* open disk file, without extended filename syntax */ -#define SKIP_TABLE -104 /* move to 1st image when opening file */ -#define SKIP_IMAGE -103 /* move to 1st table when opening file */ -#define SKIP_NULL_PRIMARY -102 /* skip null primary array when opening file */ -#define USE_MEM_BUFF -101 /* use memory buffer when opening file */ -#define OVERFLOW_ERR -11 /* overflow during datatype conversion */ -#define PREPEND_PRIMARY -9 /* used in ffiimg to insert new primary array */ -#define SAME_FILE 101 /* input and output files are the same */ -#define TOO_MANY_FILES 103 /* tried to open too many FITS files */ -#define FILE_NOT_OPENED 104 /* could not open the named file */ -#define FILE_NOT_CREATED 105 /* could not create the named file */ -#define WRITE_ERROR 106 /* error writing to FITS file */ -#define END_OF_FILE 107 /* tried to move past end of file */ -#define READ_ERROR 108 /* error reading from FITS file */ -#define FILE_NOT_CLOSED 110 /* could not close the file */ -#define ARRAY_TOO_BIG 111 /* array dimensions exceed internal limit */ -#define READONLY_FILE 112 /* Cannot write to readonly file */ -#define MEMORY_ALLOCATION 113 /* Could not allocate memory */ -#define BAD_FILEPTR 114 /* invalid fitsfile pointer */ -#define NULL_INPUT_PTR 115 /* NULL input pointer to routine */ -#define SEEK_ERROR 116 /* error seeking position in file */ - -#define BAD_URL_PREFIX 121 /* invalid URL prefix on file name */ -#define TOO_MANY_DRIVERS 122 /* tried to register too many IO drivers */ -#define DRIVER_INIT_FAILED 123 /* driver initialization failed */ -#define NO_MATCHING_DRIVER 124 /* matching driver is not registered */ -#define URL_PARSE_ERROR 125 /* failed to parse input file URL */ -#define RANGE_PARSE_ERROR 126 /* failed to parse input file URL */ - -#define SHARED_ERRBASE (150) -#define SHARED_BADARG (SHARED_ERRBASE + 1) -#define SHARED_NULPTR (SHARED_ERRBASE + 2) -#define SHARED_TABFULL (SHARED_ERRBASE + 3) -#define SHARED_NOTINIT (SHARED_ERRBASE + 4) -#define SHARED_IPCERR (SHARED_ERRBASE + 5) -#define SHARED_NOMEM (SHARED_ERRBASE + 6) -#define SHARED_AGAIN (SHARED_ERRBASE + 7) -#define SHARED_NOFILE (SHARED_ERRBASE + 8) -#define SHARED_NORESIZE (SHARED_ERRBASE + 9) - -#define HEADER_NOT_EMPTY 201 /* header already contains keywords */ -#define KEY_NO_EXIST 202 /* keyword not found in header */ -#define KEY_OUT_BOUNDS 203 /* keyword record number is out of bounds */ -#define VALUE_UNDEFINED 204 /* keyword value field is blank */ -#define NO_QUOTE 205 /* string is missing the closing quote */ -#define BAD_INDEX_KEY 206 /* illegal indexed keyword name */ -#define BAD_KEYCHAR 207 /* illegal character in keyword name or card */ -#define BAD_ORDER 208 /* required keywords out of order */ -#define NOT_POS_INT 209 /* keyword value is not a positive integer */ -#define NO_END 210 /* couldn't find END keyword */ -#define BAD_BITPIX 211 /* illegal BITPIX keyword value*/ -#define BAD_NAXIS 212 /* illegal NAXIS keyword value */ -#define BAD_NAXES 213 /* illegal NAXISn keyword value */ -#define BAD_PCOUNT 214 /* illegal PCOUNT keyword value */ -#define BAD_GCOUNT 215 /* illegal GCOUNT keyword value */ -#define BAD_TFIELDS 216 /* illegal TFIELDS keyword value */ -#define NEG_WIDTH 217 /* negative table row size */ -#define NEG_ROWS 218 /* negative number of rows in table */ -#define COL_NOT_FOUND 219 /* column with this name not found in table */ -#define BAD_SIMPLE 220 /* illegal value of SIMPLE keyword */ -#define NO_SIMPLE 221 /* Primary array doesn't start with SIMPLE */ -#define NO_BITPIX 222 /* Second keyword not BITPIX */ -#define NO_NAXIS 223 /* Third keyword not NAXIS */ -#define NO_NAXES 224 /* Couldn't find all the NAXISn keywords */ -#define NO_XTENSION 225 /* HDU doesn't start with XTENSION keyword */ -#define NOT_ATABLE 226 /* the CHDU is not an ASCII table extension */ -#define NOT_BTABLE 227 /* the CHDU is not a binary table extension */ -#define NO_PCOUNT 228 /* couldn't find PCOUNT keyword */ -#define NO_GCOUNT 229 /* couldn't find GCOUNT keyword */ -#define NO_TFIELDS 230 /* couldn't find TFIELDS keyword */ -#define NO_TBCOL 231 /* couldn't find TBCOLn keyword */ -#define NO_TFORM 232 /* couldn't find TFORMn keyword */ -#define NOT_IMAGE 233 /* the CHDU is not an IMAGE extension */ -#define BAD_TBCOL 234 /* TBCOLn keyword value < 0 or > rowlength */ -#define NOT_TABLE 235 /* the CHDU is not a table */ -#define COL_TOO_WIDE 236 /* column is too wide to fit in table */ -#define COL_NOT_UNIQUE 237 /* more than 1 column name matches template */ -#define BAD_ROW_WIDTH 241 /* sum of column widths not = NAXIS1 */ -#define UNKNOWN_EXT 251 /* unrecognizable FITS extension type */ -#define UNKNOWN_REC 252 /* unrecognizable FITS record */ -#define END_JUNK 253 /* END keyword is not blank */ -#define BAD_HEADER_FILL 254 /* Header fill area not blank */ -#define BAD_DATA_FILL 255 /* Data fill area not blank or zero */ -#define BAD_TFORM 261 /* illegal TFORM format code */ -#define BAD_TFORM_DTYPE 262 /* unrecognizable TFORM datatype code */ -#define BAD_TDIM 263 /* illegal TDIMn keyword value */ -#define BAD_HEAP_PTR 264 /* invalid BINTABLE heap address */ - -#define BAD_HDU_NUM 301 /* HDU number < 1 or > MAXHDU */ -#define BAD_COL_NUM 302 /* column number < 1 or > tfields */ -#define NEG_FILE_POS 304 /* tried to move before beginning of file */ -#define NEG_BYTES 306 /* tried to read or write negative bytes */ -#define BAD_ROW_NUM 307 /* illegal starting row number in table */ -#define BAD_ELEM_NUM 308 /* illegal starting element number in vector */ -#define NOT_ASCII_COL 309 /* this is not an ASCII string column */ -#define NOT_LOGICAL_COL 310 /* this is not a logical datatype column */ -#define BAD_ATABLE_FORMAT 311 /* ASCII table column has wrong format */ -#define BAD_BTABLE_FORMAT 312 /* Binary table column has wrong format */ -#define NO_NULL 314 /* null value has not been defined */ -#define NOT_VARI_LEN 317 /* this is not a variable length column */ -#define BAD_DIMEN 320 /* illegal number of dimensions in array */ -#define BAD_PIX_NUM 321 /* first pixel number greater than last pixel */ -#define ZERO_SCALE 322 /* illegal BSCALE or TSCALn keyword = 0 */ -#define NEG_AXIS 323 /* illegal axis length < 1 */ - -#define NOT_GROUP_TABLE 340 -#define HDU_ALREADY_MEMBER 341 -#define MEMBER_NOT_FOUND 342 -#define GROUP_NOT_FOUND 343 -#define BAD_GROUP_ID 344 -#define TOO_MANY_HDUS_TRACKED 345 -#define HDU_ALREADY_TRACKED 346 -#define BAD_OPTION 347 -#define IDENTICAL_POINTERS 348 -#define BAD_GROUP_ATTACH 349 -#define BAD_GROUP_DETACH 350 - -#define BAD_I2C 401 /* bad int to formatted string conversion */ -#define BAD_F2C 402 /* bad float to formatted string conversion */ -#define BAD_INTKEY 403 /* can't interprete keyword value as integer */ -#define BAD_LOGICALKEY 404 /* can't interprete keyword value as logical */ -#define BAD_FLOATKEY 405 /* can't interprete keyword value as float */ -#define BAD_DOUBLEKEY 406 /* can't interprete keyword value as double */ -#define BAD_C2I 407 /* bad formatted string to int conversion */ -#define BAD_C2F 408 /* bad formatted string to float conversion */ -#define BAD_C2D 409 /* bad formatted string to double conversion */ -#define BAD_DATATYPE 410 /* bad keyword datatype code */ -#define BAD_DECIM 411 /* bad number of decimal places specified */ -#define NUM_OVERFLOW 412 /* overflow during datatype conversion */ - -# define DATA_COMPRESSION_ERR 413 /* error in imcompress routines */ -# define DATA_DECOMPRESSION_ERR 414 /* error in imcompress routines */ -# define NO_COMPRESSED_TILE 415 /* compressed tile doesn't exist */ - -#define BAD_DATE 420 /* error in date or time conversion */ - -#define PARSE_SYNTAX_ERR 431 /* syntax error in parser expression */ -#define PARSE_BAD_TYPE 432 /* expression did not evaluate to desired type */ -#define PARSE_LRG_VECTOR 433 /* vector result too large to return in array */ -#define PARSE_NO_OUTPUT 434 /* data parser failed not sent an out column */ -#define PARSE_BAD_COL 435 /* bad data encounter while parsing column */ -#define PARSE_BAD_OUTPUT 436 /* Output file not of proper type */ - -#define ANGLE_TOO_BIG 501 /* celestial angle too large for projection */ -#define BAD_WCS_VAL 502 /* bad celestial coordinate or pixel value */ -#define WCS_ERROR 503 /* error in celestial coordinate calculation */ -#define BAD_WCS_PROJ 504 /* unsupported type of celestial projection */ -#define NO_WCS_KEY 505 /* celestial coordinate keywords not found */ -#define APPROX_WCS_KEY 506 /* approximate WCS keywords were calculated */ - -#define NO_CLOSE_ERROR 999 /* special value used internally to switch off */ - /* the error message from ffclos and ffchdu */ - -/*------- following error codes are used in the grparser.c file -----------*/ -#define NGP_ERRBASE (360) /* base chosen so not to interfere with CFITSIO */ -#define NGP_OK (0) -#define NGP_NO_MEMORY (NGP_ERRBASE + 0) /* malloc failed */ -#define NGP_READ_ERR (NGP_ERRBASE + 1) /* read error from file */ -#define NGP_NUL_PTR (NGP_ERRBASE + 2) /* null pointer passed as argument */ -#define NGP_EMPTY_CURLINE (NGP_ERRBASE + 3) /* line read seems to be empty */ -#define NGP_UNREAD_QUEUE_FULL (NGP_ERRBASE + 4) /* cannot unread more then 1 line (or single line twice) */ -#define NGP_INC_NESTING (NGP_ERRBASE + 5) /* too deep include file nesting (inf. loop ?) */ -#define NGP_ERR_FOPEN (NGP_ERRBASE + 6) /* fopen() failed, cannot open file */ -#define NGP_EOF (NGP_ERRBASE + 7) /* end of file encountered */ -#define NGP_BAD_ARG (NGP_ERRBASE + 8) /* bad arguments passed */ -#define NGP_TOKEN_NOT_EXPECT (NGP_ERRBASE + 9) /* token not expected here */ - -/* The following exclusion if __CINT__ is defined is needed for ROOT */ -#ifndef __CINT__ -/* the following 3 lines are needed to support C++ compilers */ -#ifdef __cplusplus -extern "C" { -#endif -#endif - -int CFITS2Unit( fitsfile *fptr ); -CFITS_API fitsfile* CUnit2FITS(int unit); - -/*---------------- FITS file URL parsing routines -------------*/ -int CFITS_API fits_get_token (char **ptr, char *delimiter, char *token, int *isanumber); -int CFITS_API fits_get_token2(char **ptr, char *delimiter, char **token, int *isanumber, int *status); -char CFITS_API *fits_split_names(char *list); -int CFITS_API ffiurl( char *url, char *urltype, char *infile, - char *outfile, char *extspec, char *rowfilter, - char *binspec, char *colspec, int *status); -int CFITS_API ffifile (char *url, char *urltype, char *infile, - char *outfile, char *extspec, char *rowfilter, - char *binspec, char *colspec, char *pixfilter, int *status); -int CFITS_API ffifile2 (char *url, char *urltype, char *infile, - char *outfile, char *extspec, char *rowfilter, - char *binspec, char *colspec, char *pixfilter, char *compspec, int *status); -int CFITS_API ffrtnm(char *url, char *rootname, int *status); -int CFITS_API ffexist(const char *infile, int *exists, int *status); -int CFITS_API ffexts(char *extspec, int *extnum, char *extname, int *extvers, - int *hdutype, char *colname, char *rowexpress, int *status); -int CFITS_API ffextn(char *url, int *extension_num, int *status); -int CFITS_API ffurlt(fitsfile *fptr, char *urlType, int *status); -int CFITS_API ffbins(char *binspec, int *imagetype, int *haxis, - char colname[4][FLEN_VALUE], double *minin, - double *maxin, double *binsizein, - char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], - char binname[4][FLEN_VALUE], double *weight, char *wtname, - int *recip, int *status); -int CFITS_API ffbinr(char **binspec, char *colname, double *minin, - double *maxin, double *binsizein, char *minname, - char *maxname, char *binname, int *status); -int CFITS_API fits_copy_cell2image(fitsfile *fptr, fitsfile *newptr, char *colname, - long rownum, int *status); -int CFITS_API fits_copy_image2cell(fitsfile *fptr, fitsfile *newptr, char *colname, - long rownum, int copykeyflag, int *status); -int CFITS_API fits_copy_pixlist2image(fitsfile *infptr, fitsfile *outfptr, int firstkey, /* I - first HDU record number to start with */ - int naxis, int *colnum, int *status); -int CFITS_API ffimport_file( char *filename, char **contents, int *status ); -int CFITS_API ffrwrg( char *rowlist, LONGLONG maxrows, int maxranges, int *numranges, - long *minrow, long *maxrow, int *status); -int CFITS_API ffrwrgll( char *rowlist, LONGLONG maxrows, int maxranges, int *numranges, - LONGLONG *minrow, LONGLONG *maxrow, int *status); -/*---------------- FITS file I/O routines -------------*/ -int CFITS_API fits_init_cfitsio(void); -int CFITS_API ffomem(fitsfile **fptr, const char *name, int mode, void **buffptr, - size_t *buffsize, size_t deltasize, - void *(*mem_realloc)(void *p, size_t newsize), - int *status); -int CFITS_API ffopen(fitsfile **fptr, const char *filename, int iomode, int *status); -int CFITS_API ffopentest(int soname, fitsfile **fptr, const char *filename, int iomode, int *status); - -int CFITS_API ffdopn(fitsfile **fptr, const char *filename, int iomode, int *status); -int CFITS_API ffeopn(fitsfile **fptr, const char *filename, int iomode, - char *extlist, int *hdutype, int *status); -int CFITS_API fftopn(fitsfile **fptr, const char *filename, int iomode, int *status); -int CFITS_API ffiopn(fitsfile **fptr, const char *filename, int iomode, int *status); -int CFITS_API ffdkopn(fitsfile **fptr, const char *filename, int iomode, int *status); -int CFITS_API ffreopen(fitsfile *openfptr, fitsfile **newfptr, int *status); -int CFITS_API ffinit( fitsfile **fptr, const char *filename, int *status); -int CFITS_API ffdkinit(fitsfile **fptr, const char *filename, int *status); -int CFITS_API ffimem(fitsfile **fptr, void **buffptr, - size_t *buffsize, size_t deltasize, - void *(*mem_realloc)(void *p, size_t newsize), - int *status); -int CFITS_API fftplt(fitsfile **fptr, const char *filename, const char *tempname, - int *status); -int CFITS_API ffflus(fitsfile *fptr, int *status); -int CFITS_API ffflsh(fitsfile *fptr, int clearbuf, int *status); -int CFITS_API ffclos(fitsfile *fptr, int *status); -int CFITS_API ffdelt(fitsfile *fptr, int *status); -int CFITS_API ffflnm(fitsfile *fptr, char *filename, int *status); -int CFITS_API ffflmd(fitsfile *fptr, int *filemode, int *status); -int CFITS_API fits_delete_iraf_file(const char *filename, int *status); - -/*---------------- utility routines -------------*/ - -float CFITS_API ffvers(float *version); -void CFITS_API ffupch(char *string); -void CFITS_API ffgerr(int status, char *errtext); -void CFITS_API ffpmsg(const char *err_message); -void CFITS_API ffpmrk(void); -int CFITS_API ffgmsg(char *err_message); -void CFITS_API ffcmsg(void); -void CFITS_API ffcmrk(void); -void CFITS_API ffrprt(FILE *stream, int status); -void CFITS_API ffcmps(char *templt, char *colname, int casesen, int *match, - int *exact); -int CFITS_API fftkey(const char *keyword, int *status); -int CFITS_API fftrec(char *card, int *status); -int CFITS_API ffnchk(fitsfile *fptr, int *status); -int CFITS_API ffkeyn(const char *keyroot, int value, char *keyname, int *status); -int CFITS_API ffnkey(int value, const char *keyroot, char *keyname, int *status); -int CFITS_API ffgkcl(char *card); -int CFITS_API ffdtyp(const char *cval, char *dtype, int *status); -int CFITS_API ffinttyp(char *cval, int *datatype, int *negative, int *status); -int CFITS_API ffpsvc(char *card, char *value, char *comm, int *status); -int CFITS_API ffgknm(char *card, char *name, int *length, int *status); -int CFITS_API ffgthd(char *tmplt, char *card, int *hdtype, int *status); -int CFITS_API ffmkky(const char *keyname, char *keyval, const char *comm, char *card, int *status); -int CFITS_API fits_translate_keyword(char *inrec, char *outrec, char *patterns[][2], - int npat, int n_value, int n_offset, int n_range, int *pat_num, - int *i, int *j, int *m, int *n, int *status); -int CFITS_API fits_translate_keywords(fitsfile *infptr, fitsfile *outfptr, - int firstkey, char *patterns[][2], - int npat, int n_value, int n_offset, int n_range, int *status); -int CFITS_API ffasfm(char *tform, int *datacode, long *width, int *decim, int *status); -int CFITS_API ffbnfm(char *tform, int *datacode, long *repeat, long *width, int *status); -int CFITS_API ffbnfmll(char *tform, int *datacode, LONGLONG *repeat, long *width, int *status); -int CFITS_API ffgabc(int tfields, char **tform, int space, long *rowlen, long *tbcol, - int *status); -int CFITS_API fits_get_section_range(char **ptr,long *secmin,long *secmax,long *incre, - int *status); -/* ffmbyt should not normally be used in application programs, but it is - defined here as a publicly available routine because there are a few - rare cases where it is needed -*/ -int CFITS_API ffmbyt(fitsfile *fptr, LONGLONG bytpos, int ignore_err, int *status); -/*----------------- write single keywords --------------*/ -int CFITS_API ffpky(fitsfile *fptr, int datatype, const char *keyname, void *value, - const char *comm, int *status); -int CFITS_API ffprec(fitsfile *fptr, const char *card, int *status); -int CFITS_API ffpcom(fitsfile *fptr, const char *comm, int *status); -int CFITS_API ffpunt(fitsfile *fptr, const char *keyname, const char *unit, int *status); -int CFITS_API ffphis(fitsfile *fptr, const char *history, int *status); -int CFITS_API ffpdat(fitsfile *fptr, int *status); -int CFITS_API ffverifydate(int year, int month, int day, int *status); -int CFITS_API ffgstm(char *timestr, int *timeref, int *status); -int CFITS_API ffgsdt(int *day, int *month, int *year, int *status); -int CFITS_API ffdt2s(int year, int month, int day, char *datestr, int *status); -int CFITS_API fftm2s(int year, int month, int day, int hour, int minute, double second, - int decimals, char *datestr, int *status); -int CFITS_API ffs2dt(char *datestr, int *year, int *month, int *day, int *status); -int CFITS_API ffs2tm(char *datestr, int *year, int *month, int *day, int *hour, - int *minute, double *second, int *status); -int CFITS_API ffpkyu(fitsfile *fptr, const char *keyname, const char *comm, int *status); -int CFITS_API ffpkys(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); -int CFITS_API ffpkls(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); -int CFITS_API ffplsw(fitsfile *fptr, int *status); -int CFITS_API ffpkyl(fitsfile *fptr, const char *keyname, int value, const char *comm, int *status); -int CFITS_API ffpkyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status); -int CFITS_API ffpkyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, - int *status); -int CFITS_API ffpkye(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, - int *status); -int CFITS_API ffpkyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, - int *status); -int CFITS_API ffpkyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, - int *status); -int CFITS_API ffpkyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, - int *status); -int CFITS_API ffpkym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, - int *status); -int CFITS_API ffpkfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, - int *status); -int CFITS_API ffpkfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, - int *status); -int CFITS_API ffpkyt(fitsfile *fptr, const char *keyname, long intval, double frac, const char *comm, - int *status); -int CFITS_API ffptdm( fitsfile *fptr, int colnum, int naxis, long naxes[], int *status); -int CFITS_API ffptdmll( fitsfile *fptr, int colnum, int naxis, LONGLONG naxes[], int *status); - -/*----------------- write array of keywords --------------*/ -int CFITS_API ffpkns(fitsfile *fptr, const char *keyroot, int nstart, int nkey, char *value[], - char *comm[], int *status); -int CFITS_API ffpknl(fitsfile *fptr, const char *keyroot, int nstart, int nkey, int *value, - char *comm[], int *status); -int CFITS_API ffpknj(fitsfile *fptr, const char *keyroot, int nstart, int nkey, long *value, - char *comm[], int *status); -int CFITS_API ffpknjj(fitsfile *fptr, const char *keyroot, int nstart, int nkey, LONGLONG *value, - char *comm[], int *status); -int CFITS_API ffpknf(fitsfile *fptr, const char *keyroot, int nstart, int nkey, float *value, - int decim, char *comm[], int *status); -int CFITS_API ffpkne(fitsfile *fptr, const char *keyroot, int nstart, int nkey, float *value, - int decim, char *comm[], int *status); -int CFITS_API ffpkng(fitsfile *fptr, const char *keyroot, int nstart, int nkey, double *value, - int decim, char *comm[], int *status); -int CFITS_API ffpknd(fitsfile *fptr, const char *keyroot, int nstart, int nkey, double *value, - int decim, char *comm[], int *status); -int CFITS_API ffcpky(fitsfile *infptr,fitsfile *outfptr,int incol,int outcol, - char *rootname, int *status); - -/*----------------- write required header keywords --------------*/ -int CFITS_API ffphps( fitsfile *fptr, int bitpix, int naxis, long naxes[], int *status); -int CFITS_API ffphpsll( fitsfile *fptr, int bitpix, int naxis, LONGLONG naxes[], int *status); -int CFITS_API ffphpr( fitsfile *fptr, int simple, int bitpix, int naxis, long naxes[], - LONGLONG pcount, LONGLONG gcount, int extend, int *status); -int CFITS_API ffphprll( fitsfile *fptr, int simple, int bitpix, int naxis, LONGLONG naxes[], - LONGLONG pcount, LONGLONG gcount, int extend, int *status); -int CFITS_API ffphtb(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, int tfields, char **ttype, - long *tbcol, char **tform, char **tunit, const char *extname, int *status); -int CFITS_API ffphbn(fitsfile *fptr, LONGLONG naxis2, int tfields, char **ttype, - char **tform, char **tunit, const char *extname, LONGLONG pcount, int *status); -int CFITS_API ffphext( fitsfile *fptr, const char *xtension, int bitpix, int naxis, long naxes[], - LONGLONG pcount, LONGLONG gcount, int *status); -/*----------------- write template keywords --------------*/ -int CFITS_API ffpktp(fitsfile *fptr, const char *filename, int *status); - -/*------------------ get header information --------------*/ -int CFITS_API ffghsp(fitsfile *fptr, int *nexist, int *nmore, int *status); -int CFITS_API ffghps(fitsfile *fptr, int *nexist, int *position, int *status); - -/*------------------ move position in header -------------*/ -int CFITS_API ffmaky(fitsfile *fptr, int nrec, int *status); -int CFITS_API ffmrky(fitsfile *fptr, int nrec, int *status); - -/*------------------ read single keywords -----------------*/ -int CFITS_API ffgnxk(fitsfile *fptr, char **inclist, int ninc, char **exclist, - int nexc, char *card, int *status); -int CFITS_API ffgrec(fitsfile *fptr, int nrec, char *card, int *status); -int CFITS_API ffgcrd(fitsfile *fptr, const char *keyname, char *card, int *status); -int CFITS_API ffgstr(fitsfile *fptr, const char *string, char *card, int *status); -int CFITS_API ffgunt(fitsfile *fptr, const char *keyname, char *unit, int *status); -int CFITS_API ffgkyn(fitsfile *fptr, int nkey, char *keyname, char *keyval, char *comm, - int *status); -int CFITS_API ffgkey(fitsfile *fptr, const char *keyname, char *keyval, char *comm, - int *status); - -int CFITS_API ffgky( fitsfile *fptr, int datatype, const char *keyname, void *value, - char *comm, int *status); -int CFITS_API ffgkys(fitsfile *fptr, const char *keyname, char *value, char *comm, int *status); -int CFITS_API ffgksl(fitsfile *fptr, const char *keyname, int *length, int *status); -int CFITS_API ffgkls(fitsfile *fptr, const char *keyname, char **value, char *comm, int *status); -int CFITS_API ffgsky(fitsfile *fptr, const char *keyname, int firstchar, int maxchar, - char *value, int *valuelen, char *comm, int *status); -int CFITS_API fffree(void *value, int *status); -int CFITS_API fffkls(char *value, int *status); -int CFITS_API ffgkyl(fitsfile *fptr, const char *keyname, int *value, char *comm, int *status); -int CFITS_API ffgkyj(fitsfile *fptr, const char *keyname, long *value, char *comm, int *status); -int CFITS_API ffgkyjj(fitsfile *fptr, const char *keyname, LONGLONG *value, char *comm, int *status); -int CFITS_API ffgkye(fitsfile *fptr, const char *keyname, float *value, char *comm,int *status); -int CFITS_API ffgkyd(fitsfile *fptr, const char *keyname, double *value,char *comm,int *status); -int CFITS_API ffgkyc(fitsfile *fptr, const char *keyname, float *value, char *comm,int *status); -int CFITS_API ffgkym(fitsfile *fptr, const char *keyname, double *value,char *comm,int *status); -int CFITS_API ffgkyt(fitsfile *fptr, const char *keyname, long *ivalue, double *dvalue, - char *comm, int *status); -int CFITS_API ffgtdm(fitsfile *fptr, int colnum, int maxdim, int *naxis, long naxes[], - int *status); -int CFITS_API ffgtdmll(fitsfile *fptr, int colnum, int maxdim, int *naxis, LONGLONG naxes[], - int *status); -int CFITS_API ffdtdm(fitsfile *fptr, char *tdimstr, int colnum, int maxdim, - int *naxis, long naxes[], int *status); -int CFITS_API ffdtdmll(fitsfile *fptr, char *tdimstr, int colnum, int maxdim, - int *naxis, LONGLONG naxes[], int *status); - -/*------------------ read array of keywords -----------------*/ -int CFITS_API ffgkns(fitsfile *fptr, const char *keyname, int nstart, int nmax, char *value[], - int *nfound, int *status); -int CFITS_API ffgknl(fitsfile *fptr, const char *keyname, int nstart, int nmax, int *value, - int *nfound, int *status); -int CFITS_API ffgknj(fitsfile *fptr, const char *keyname, int nstart, int nmax, long *value, - int *nfound, int *status); -int CFITS_API ffgknjj(fitsfile *fptr, const char *keyname, int nstart, int nmax, LONGLONG *value, - int *nfound, int *status); -int CFITS_API ffgkne(fitsfile *fptr, const char *keyname, int nstart, int nmax, float *value, - int *nfound, int *status); -int CFITS_API ffgknd(fitsfile *fptr, const char *keyname, int nstart, int nmax, double *value, - int *nfound, int *status); -int CFITS_API ffh2st(fitsfile *fptr, char **header, int *status); -int CFITS_API ffhdr2str( fitsfile *fptr, int exclude_comm, char **exclist, - int nexc, char **header, int *nkeys, int *status); -int CFITS_API ffcnvthdr2str( fitsfile *fptr, int exclude_comm, char **exclist, - int nexc, char **header, int *nkeys, int *status); - -/*----------------- read required header keywords --------------*/ -int CFITS_API ffghpr(fitsfile *fptr, int maxdim, int *simple, int *bitpix, int *naxis, - long naxes[], long *pcount, long *gcount, int *extend, int *status); - -int CFITS_API ffghprll(fitsfile *fptr, int maxdim, int *simple, int *bitpix, int *naxis, - LONGLONG naxes[], long *pcount, long *gcount, int *extend, int *status); - -int CFITS_API ffghtb(fitsfile *fptr,int maxfield, long *naxis1, long *naxis2, - int *tfields, char **ttype, long *tbcol, char **tform, char **tunit, - char *extname, int *status); - -int CFITS_API ffghtbll(fitsfile *fptr,int maxfield, LONGLONG *naxis1, LONGLONG *naxis2, - int *tfields, char **ttype, LONGLONG *tbcol, char **tform, char **tunit, - char *extname, int *status); - - -int CFITS_API ffghbn(fitsfile *fptr, int maxfield, long *naxis2, int *tfields, - char **ttype, char **tform, char **tunit, char *extname, - long *pcount, int *status); - -int CFITS_API ffghbnll(fitsfile *fptr, int maxfield, LONGLONG *naxis2, int *tfields, - char **ttype, char **tform, char **tunit, char *extname, - LONGLONG *pcount, int *status); - -/*--------------------- update keywords ---------------*/ -int CFITS_API ffuky(fitsfile *fptr, int datatype, const char *keyname, void *value, - const char *comm, int *status); -int CFITS_API ffucrd(fitsfile *fptr, const char *keyname, const char *card, int *status); -int CFITS_API ffukyu(fitsfile *fptr, const char *keyname, const char *comm, int *status); -int CFITS_API ffukys(fitsfile *fptr, const char *keyname, const char *value, const char *comm, int *status); -int CFITS_API ffukls(fitsfile *fptr, const char *keyname, const char *value, const char *comm, int *status); -int CFITS_API ffukyl(fitsfile *fptr, const char *keyname, int value, const char *comm, int *status); -int CFITS_API ffukyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status); -int CFITS_API ffukyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, - int *status); -int CFITS_API ffukye(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, - int *status); -int CFITS_API ffukyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, - int *status); -int CFITS_API ffukyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, - int *status); -int CFITS_API ffukyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, - int *status); -int CFITS_API ffukym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, - int *status); -int CFITS_API ffukfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, - int *status); -int CFITS_API ffukfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, - int *status); - -/*--------------------- modify keywords ---------------*/ -int CFITS_API ffmrec(fitsfile *fptr, int nkey, const char *card, int *status); -int CFITS_API ffmcrd(fitsfile *fptr, const char *keyname, const char *card, int *status); -int CFITS_API ffmnam(fitsfile *fptr, const char *oldname, const char *newname, int *status); -int CFITS_API ffmcom(fitsfile *fptr, const char *keyname, const char *comm, int *status); -int CFITS_API ffmkyu(fitsfile *fptr, const char *keyname, const char *comm, int *status); -int CFITS_API ffmkys(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); -int CFITS_API ffmkls(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); -int CFITS_API ffmkyl(fitsfile *fptr, const char *keyname, int value, const char *comm, int *status); -int CFITS_API ffmkyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status); -int CFITS_API ffmkyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, - int *status); -int CFITS_API ffmkye(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, - int *status); -int CFITS_API ffmkyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, - int *status); -int CFITS_API ffmkyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, - int *status); -int CFITS_API ffmkyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, - int *status); -int CFITS_API ffmkym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, - int *status); -int CFITS_API ffmkfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, - int *status); -int CFITS_API ffmkfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, - int *status); - -/*--------------------- insert keywords ---------------*/ -int CFITS_API ffirec(fitsfile *fptr, int nkey, const char *card, int *status); -int CFITS_API ffikey(fitsfile *fptr, const char *card, int *status); -int CFITS_API ffikyu(fitsfile *fptr, const char *keyname, const char *comm, int *status); -int CFITS_API ffikys(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); -int CFITS_API ffikls(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); -int CFITS_API ffikyl(fitsfile *fptr, const char *keyname, int value, const char *comm, int *status); -int CFITS_API ffikyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status); -int CFITS_API ffikyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, - int *status); -int CFITS_API ffikye(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, - int *status); -int CFITS_API ffikyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, - int *status); -int CFITS_API ffikyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, - int *status); -int CFITS_API ffikyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, - int *status); -int CFITS_API ffikym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, - int *status); -int CFITS_API ffikfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, - int *status); -int CFITS_API ffikfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, - int *status); - -/*--------------------- delete keywords ---------------*/ -int CFITS_API ffdkey(fitsfile *fptr, const char *keyname, int *status); -int CFITS_API ffdstr(fitsfile *fptr, const char *string, int *status); -int CFITS_API ffdrec(fitsfile *fptr, int keypos, int *status); - -/*--------------------- get HDU information -------------*/ -int CFITS_API ffghdn(fitsfile *fptr, int *chdunum); -int CFITS_API ffghdt(fitsfile *fptr, int *exttype, int *status); -int CFITS_API ffghad(fitsfile *fptr, long *headstart, long *datastart, long *dataend, - int *status); -int CFITS_API ffghadll(fitsfile *fptr, LONGLONG *headstart, LONGLONG *datastart, - LONGLONG *dataend, int *status); -int CFITS_API ffghof(fitsfile *fptr, OFF_T *headstart, OFF_T *datastart, OFF_T *dataend, - int *status); -int CFITS_API ffgipr(fitsfile *fptr, int maxaxis, int *imgtype, int *naxis, - long *naxes, int *status); -int CFITS_API ffgiprll(fitsfile *fptr, int maxaxis, int *imgtype, int *naxis, - LONGLONG *naxes, int *status); -int CFITS_API ffgidt(fitsfile *fptr, int *imgtype, int *status); -int CFITS_API ffgiet(fitsfile *fptr, int *imgtype, int *status); -int CFITS_API ffgidm(fitsfile *fptr, int *naxis, int *status); -int CFITS_API ffgisz(fitsfile *fptr, int nlen, long *naxes, int *status); -int CFITS_API ffgiszll(fitsfile *fptr, int nlen, LONGLONG *naxes, int *status); - -/*--------------------- HDU operations -------------*/ -int CFITS_API ffmahd(fitsfile *fptr, int hdunum, int *exttype, int *status); -int CFITS_API ffmrhd(fitsfile *fptr, int hdumov, int *exttype, int *status); -int CFITS_API ffmnhd(fitsfile *fptr, int exttype, char *hduname, int hduvers, - int *status); -int CFITS_API ffthdu(fitsfile *fptr, int *nhdu, int *status); -int CFITS_API ffcrhd(fitsfile *fptr, int *status); -int CFITS_API ffcrim(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status); -int CFITS_API ffcrimll(fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, int *status); -int CFITS_API ffcrtb(fitsfile *fptr, int tbltype, LONGLONG naxis2, int tfields, char **ttype, - char **tform, char **tunit, const char *extname, int *status); -int CFITS_API ffiimg(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status); -int CFITS_API ffiimgll(fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, int *status); -int CFITS_API ffitab(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, int tfields, char **ttype, - long *tbcol, char **tform, char **tunit, const char *extname, int *status); -int CFITS_API ffibin(fitsfile *fptr, LONGLONG naxis2, int tfields, char **ttype, char **tform, - char **tunit, const char *extname, LONGLONG pcount, int *status); -int CFITS_API ffrsim(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status); -int CFITS_API ffrsimll(fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, int *status); -int CFITS_API ffdhdu(fitsfile *fptr, int *hdutype, int *status); -int CFITS_API ffcopy(fitsfile *infptr, fitsfile *outfptr, int morekeys, int *status); -int CFITS_API ffcpfl(fitsfile *infptr, fitsfile *outfptr, int prev, int cur, int follow, - int *status); -int CFITS_API ffcphd(fitsfile *infptr, fitsfile *outfptr, int *status); -int CFITS_API ffcpdt(fitsfile *infptr, fitsfile *outfptr, int *status); -int CFITS_API ffchfl(fitsfile *fptr, int *status); -int CFITS_API ffcdfl(fitsfile *fptr, int *status); -int CFITS_API ffwrhdu(fitsfile *fptr, FILE *outstream, int *status); - -int CFITS_API ffrdef(fitsfile *fptr, int *status); -int CFITS_API ffrhdu(fitsfile *fptr, int *hdutype, int *status); -int CFITS_API ffhdef(fitsfile *fptr, int morekeys, int *status); -int CFITS_API ffpthp(fitsfile *fptr, long theap, int *status); - -int CFITS_API ffcsum(fitsfile *fptr, long nrec, unsigned long *sum, int *status); -void CFITS_API ffesum(unsigned long sum, int complm, char *ascii); -unsigned long CFITS_API ffdsum(char *ascii, int complm, unsigned long *sum); -int CFITS_API ffpcks(fitsfile *fptr, int *status); -int CFITS_API ffupck(fitsfile *fptr, int *status); -int CFITS_API ffvcks(fitsfile *fptr, int *datastatus, int *hdustatus, int *status); -int CFITS_API ffgcks(fitsfile *fptr, unsigned long *datasum, unsigned long *hdusum, - int *status); - -/*--------------------- define scaling or null values -------------*/ -int CFITS_API ffpscl(fitsfile *fptr, double scale, double zeroval, int *status); -int CFITS_API ffpnul(fitsfile *fptr, LONGLONG nulvalue, int *status); -int CFITS_API fftscl(fitsfile *fptr, int colnum, double scale, double zeroval, int *status); -int CFITS_API fftnul(fitsfile *fptr, int colnum, LONGLONG nulvalue, int *status); -int CFITS_API ffsnul(fitsfile *fptr, int colnum, char *nulstring, int *status); - -/*--------------------- get column information -------------*/ -int CFITS_API ffgcno(fitsfile *fptr, int casesen, char *templt, int *colnum, - int *status); -int CFITS_API ffgcnn(fitsfile *fptr, int casesen, char *templt, char *colname, - int *colnum, int *status); - -int CFITS_API ffgtcl(fitsfile *fptr, int colnum, int *typecode, long *repeat, - long *width, int *status); -int CFITS_API ffgtclll(fitsfile *fptr, int colnum, int *typecode, LONGLONG *repeat, - LONGLONG *width, int *status); -int CFITS_API ffeqty(fitsfile *fptr, int colnum, int *typecode, long *repeat, - long *width, int *status); -int CFITS_API ffeqtyll(fitsfile *fptr, int colnum, int *typecode, LONGLONG *repeat, - LONGLONG *width, int *status); -int CFITS_API ffgncl(fitsfile *fptr, int *ncols, int *status); -int CFITS_API ffgnrw(fitsfile *fptr, long *nrows, int *status); -int CFITS_API ffgnrwll(fitsfile *fptr, LONGLONG *nrows, int *status); -int CFITS_API ffgacl(fitsfile *fptr, int colnum, char *ttype, long *tbcol, - char *tunit, char *tform, double *tscal, double *tzero, - char *tnull, char *tdisp, int *status); -int CFITS_API ffgbcl(fitsfile *fptr, int colnum, char *ttype, char *tunit, - char *dtype, long *repeat, double *tscal, double *tzero, - long *tnull, char *tdisp, int *status); -int CFITS_API ffgbclll(fitsfile *fptr, int colnum, char *ttype, char *tunit, - char *dtype, LONGLONG *repeat, double *tscal, double *tzero, - LONGLONG *tnull, char *tdisp, int *status); -int CFITS_API ffgrsz(fitsfile *fptr, long *nrows, int *status); -int CFITS_API ffgcdw(fitsfile *fptr, int colnum, int *width, int *status); - -/*--------------------- read primary array or image elements -------------*/ -int CFITS_API ffgpxv(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem, - void *nulval, void *array, int *anynul, int *status); -int CFITS_API ffgpxvll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem, - void *nulval, void *array, int *anynul, int *status); -int CFITS_API ffgpxf(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem, - void *array, char *nullarray, int *anynul, int *status); -int CFITS_API ffgpxfll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem, - void *array, char *nullarray, int *anynul, int *status); -int CFITS_API ffgsv(fitsfile *fptr, int datatype, long *blc, long *trc, long *inc, - void *nulval, void *array, int *anynul, int *status); - -int CFITS_API ffgpv(fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelem, - void *nulval, void *array, int *anynul, int *status); -int CFITS_API ffgpf(fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelem, - void *array, char *nullarray, int *anynul, int *status); -int CFITS_API ffgpvb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned - char nulval, unsigned char *array, int *anynul, int *status); -int CFITS_API ffgpvsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, signed - char nulval, signed char *array, int *anynul, int *status); -int CFITS_API ffgpvui(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - unsigned short nulval, unsigned short *array, int *anynul, - int *status); -int CFITS_API ffgpvi(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - short nulval, short *array, int *anynul, int *status); -int CFITS_API ffgpvuj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - unsigned long nulval, unsigned long *array, int *anynul, - int *status); -int CFITS_API ffgpvj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - long nulval, long *array, int *anynul, int *status); -int CFITS_API ffgpvjj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - LONGLONG nulval, LONGLONG *array, int *anynul, int *status); -int CFITS_API ffgpvuk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - unsigned int nulval, unsigned int *array, int *anynul, int *status); -int CFITS_API ffgpvk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - int nulval, int *array, int *anynul, int *status); -int CFITS_API ffgpve(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - float nulval, float *array, int *anynul, int *status); -int CFITS_API ffgpvd(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - double nulval, double *array, int *anynul, int *status); - -int CFITS_API ffgpfb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - unsigned char *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgpfsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - signed char *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgpfui(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - unsigned short *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgpfi(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - short *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgpfuj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - unsigned long *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgpfj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - long *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgpfjj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - LONGLONG *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgpfuk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - unsigned int *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgpfk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - int *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgpfe(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - float *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgpfd(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - double *array, char *nularray, int *anynul, int *status); - -int CFITS_API ffg2db(fitsfile *fptr, long group, unsigned char nulval, LONGLONG ncols, - LONGLONG naxis1, LONGLONG naxis2, unsigned char *array, - int *anynul, int *status); -int CFITS_API ffg2dsb(fitsfile *fptr, long group, signed char nulval, LONGLONG ncols, - LONGLONG naxis1, LONGLONG naxis2, signed char *array, - int *anynul, int *status); -int CFITS_API ffg2dui(fitsfile *fptr, long group, unsigned short nulval, LONGLONG ncols, - LONGLONG naxis1, LONGLONG naxis2, unsigned short *array, - int *anynul, int *status); -int CFITS_API ffg2di(fitsfile *fptr, long group, short nulval, LONGLONG ncols, - LONGLONG naxis1, LONGLONG naxis2, short *array, - int *anynul, int *status); -int CFITS_API ffg2duj(fitsfile *fptr, long group, unsigned long nulval, LONGLONG ncols, - LONGLONG naxis1, LONGLONG naxis2, unsigned long *array, - int *anynul, int *status); -int CFITS_API ffg2dj(fitsfile *fptr, long group, long nulval, LONGLONG ncols, - LONGLONG naxis1, LONGLONG naxis2, long *array, - int *anynul, int *status); -int CFITS_API ffg2djj(fitsfile *fptr, long group, LONGLONG nulval, LONGLONG ncols, - LONGLONG naxis1, LONGLONG naxis2, LONGLONG *array, - int *anynul, int *status); -int CFITS_API ffg2duk(fitsfile *fptr, long group, unsigned int nulval, LONGLONG ncols, - LONGLONG naxis1, LONGLONG naxis2, unsigned int *array, - int *anynul, int *status); -int CFITS_API ffg2dk(fitsfile *fptr, long group, int nulval, LONGLONG ncols, - LONGLONG naxis1, LONGLONG naxis2, int *array, - int *anynul, int *status); -int CFITS_API ffg2de(fitsfile *fptr, long group, float nulval, LONGLONG ncols, - LONGLONG naxis1, LONGLONG naxis2, float *array, - int *anynul, int *status); -int CFITS_API ffg2dd(fitsfile *fptr, long group, double nulval, LONGLONG ncols, - LONGLONG naxis1, LONGLONG naxis2, double *array, - int *anynul, int *status); - -int CFITS_API ffg3db(fitsfile *fptr, long group, unsigned char nulval, LONGLONG ncols, - LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - unsigned char *array, int *anynul, int *status); -int CFITS_API ffg3dsb(fitsfile *fptr, long group, signed char nulval, LONGLONG ncols, - LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - signed char *array, int *anynul, int *status); -int CFITS_API ffg3dui(fitsfile *fptr, long group, unsigned short nulval, LONGLONG ncols, - LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - unsigned short *array, int *anynul, int *status); -int CFITS_API ffg3di(fitsfile *fptr, long group, short nulval, LONGLONG ncols, - LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - short *array, int *anynul, int *status); -int CFITS_API ffg3duj(fitsfile *fptr, long group, unsigned long nulval, LONGLONG ncols, - LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - unsigned long *array, int *anynul, int *status); -int CFITS_API ffg3dj(fitsfile *fptr, long group, long nulval, LONGLONG ncols, - LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - long *array, int *anynul, int *status); -int CFITS_API ffg3djj(fitsfile *fptr, long group, LONGLONG nulval, LONGLONG ncols, - LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - LONGLONG *array, int *anynul, int *status); -int CFITS_API ffg3duk(fitsfile *fptr, long group, unsigned int nulval, LONGLONG ncols, - LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - unsigned int *array, int *anynul, int *status); -int CFITS_API ffg3dk(fitsfile *fptr, long group, int nulval, LONGLONG ncols, - LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - int *array, int *anynul, int *status); -int CFITS_API ffg3de(fitsfile *fptr, long group, float nulval, LONGLONG ncols, - LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - float *array, int *anynul, int *status); -int CFITS_API ffg3dd(fitsfile *fptr, long group, double nulval, LONGLONG ncols, - LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, - double *array, int *anynul, int *status); - -int CFITS_API ffgsvb(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, unsigned char nulval, unsigned char *array, - int *anynul, int *status); -int CFITS_API ffgsvsb(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, signed char nulval, signed char *array, - int *anynul, int *status); -int CFITS_API ffgsvui(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, unsigned short nulval, unsigned short *array, - int *anynul, int *status); -int CFITS_API ffgsvi(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, short nulval, short *array, int *anynul, int *status); -int CFITS_API ffgsvuj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, unsigned long nulval, unsigned long *array, - int *anynul, int *status); -int CFITS_API ffgsvj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, long nulval, long *array, int *anynul, int *status); -int CFITS_API ffgsvjj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, LONGLONG nulval, LONGLONG *array, int *anynul, - int *status); -int CFITS_API ffgsvuk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, unsigned int nulval, unsigned int *array, - int *anynul, int *status); -int CFITS_API ffgsvk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, int nulval, int *array, int *anynul, int *status); -int CFITS_API ffgsve(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, float nulval, float *array, int *anynul, int *status); -int CFITS_API ffgsvd(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, double nulval, double *array, int *anynul, - int *status); - -int CFITS_API ffgsfb(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, unsigned char *array, char *flagval, - int *anynul, int *status); -int CFITS_API ffgsfsb(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, signed char *array, char *flagval, - int *anynul, int *status); -int CFITS_API ffgsfui(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, unsigned short *array, char *flagval, int *anynul, - int *status); -int CFITS_API ffgsfi(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, short *array, char *flagval, int *anynul, int *status); -int CFITS_API ffgsfuj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, unsigned long *array, char *flagval, int *anynul, - int *status); -int CFITS_API ffgsfj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, long *array, char *flagval, int *anynul, int *status); -int CFITS_API ffgsfjj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, LONGLONG *array, char *flagval, int *anynul, - int *status); -int CFITS_API ffgsfuk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, unsigned int *array, char *flagval, int *anynul, - int *status); -int CFITS_API ffgsfk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, int *array, char *flagval, int *anynul, int *status); -int CFITS_API ffgsfe(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, float *array, char *flagval, int *anynul, int *status); -int CFITS_API ffgsfd(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, - long *trc, long *inc, double *array, char *flagval, int *anynul, - int *status); - -int CFITS_API ffggpb(fitsfile *fptr, long group, long firstelem, long nelem, - unsigned char *array, int *status); -int CFITS_API ffggpsb(fitsfile *fptr, long group, long firstelem, long nelem, - signed char *array, int *status); -int CFITS_API ffggpui(fitsfile *fptr, long group, long firstelem, long nelem, - unsigned short *array, int *status); -int CFITS_API ffggpi(fitsfile *fptr, long group, long firstelem, long nelem, - short *array, int *status); -int CFITS_API ffggpuj(fitsfile *fptr, long group, long firstelem, long nelem, - unsigned long *array, int *status); -int CFITS_API ffggpj(fitsfile *fptr, long group, long firstelem, long nelem, - long *array, int *status); -int CFITS_API ffggpjj(fitsfile *fptr, long group, long firstelem, long nelem, - LONGLONG *array, int *status); -int CFITS_API ffggpuk(fitsfile *fptr, long group, long firstelem, long nelem, - unsigned int *array, int *status); -int CFITS_API ffggpk(fitsfile *fptr, long group, long firstelem, long nelem, - int *array, int *status); -int CFITS_API ffggpe(fitsfile *fptr, long group, long firstelem, long nelem, - float *array, int *status); -int CFITS_API ffggpd(fitsfile *fptr, long group, long firstelem, long nelem, - double *array, int *status); - -/*--------------------- read column elements -------------*/ -int CFITS_API ffgcv( fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, - LONGLONG firstelem, LONGLONG nelem, void *nulval, void *array, int *anynul, - int *status); -int CFITS_API ffgcf( fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, - LONGLONG firstelem, LONGLONG nelem, void *array, char *nullarray, - int *anynul, int *status); -int CFITS_API ffgcvs(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, char *nulval, char **array, int *anynul, int *status); -int CFITS_API ffgcl (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, char *array, int *status); -int CFITS_API ffgcvl (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, char nulval, char *array, int *anynul, int *status); -int CFITS_API ffgcvb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned char nulval, unsigned char *array, - int *anynul, int *status); -int CFITS_API ffgcvsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, signed char nulval, signed char *array, - int *anynul, int *status); -int CFITS_API ffgcvui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned short nulval, unsigned short *array, - int *anynul, int *status); -int CFITS_API ffgcvi(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, short nulval, short *array, int *anynul, int *status); -int CFITS_API ffgcvuj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned long nulval, unsigned long *array, int *anynul, - int *status); -int CFITS_API ffgcvj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long nulval, long *array, int *anynul, int *status); -int CFITS_API ffgcvjj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, LONGLONG nulval, LONGLONG *array, int *anynul, - int *status); -int CFITS_API ffgcvuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned int nulval, unsigned int *array, int *anynul, - int *status); -int CFITS_API ffgcvk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, int nulval, int *array, int *anynul, int *status); -int CFITS_API ffgcve(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, float nulval, float *array, int *anynul, int *status); -int CFITS_API ffgcvd(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, double nulval, double *array, int *anynul, int *status); -int CFITS_API ffgcvc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, float nulval, float *array, int *anynul, int *status); -int CFITS_API ffgcvm(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, double nulval, double *array, int *anynul, int *status); - -int CFITS_API ffgcx(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstbit, - LONGLONG nbits, char *larray, int *status); -int CFITS_API ffgcxui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, - long firstbit, int nbits, unsigned short *array, int *status); -int CFITS_API ffgcxuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, - long firstbit, int nbits, unsigned int *array, int *status); - -int CFITS_API ffgcfs(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, char **array, char *nularray, int *anynul, int *status); -int CFITS_API ffgcfl(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, char *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgcfb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned char *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgcfsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, signed char *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgcfui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned short *array, char *nularray, int *anynul, - int *status); -int CFITS_API ffgcfi(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, short *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgcfuj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned long *array, char *nularray, int *anynul, - int *status); -int CFITS_API ffgcfj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgcfjj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, LONGLONG *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgcfuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned int *array, char *nularray, int *anynul, - int *status); -int CFITS_API ffgcfk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, int *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgcfe(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, float *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgcfd(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, double *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgcfc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, float *array, char *nularray, int *anynul, int *status); -int CFITS_API ffgcfm(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, double *array, char *nularray, int *anynul, int *status); - -int CFITS_API ffgdes(fitsfile *fptr, int colnum, LONGLONG rownum, long *length, - long *heapaddr, int *status); -int CFITS_API ffgdesll(fitsfile *fptr, int colnum, LONGLONG rownum, LONGLONG *length, - LONGLONG *heapaddr, int *status); -int CFITS_API ffgdess(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, long *length, - long *heapaddr, int *status); -int CFITS_API ffgdessll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, LONGLONG *length, - LONGLONG *heapaddr, int *status); -int CFITS_API ffpdes(fitsfile *fptr, int colnum, LONGLONG rownum, LONGLONG length, - LONGLONG heapaddr, int *status); -int CFITS_API fftheap(fitsfile *fptr, LONGLONG *heapsize, LONGLONG *unused, LONGLONG *overlap, - int *valid, int *status); -int CFITS_API ffcmph(fitsfile *fptr, int *status); - -int CFITS_API ffgtbb(fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, - unsigned char *values, int *status); - -int CFITS_API ffgextn(fitsfile *fptr, LONGLONG offset, LONGLONG nelem, void *array, int *status); -int CFITS_API ffpextn(fitsfile *fptr, LONGLONG offset, LONGLONG nelem, void *array, int *status); - -/*------------ write primary array or image elements -------------*/ -int CFITS_API ffppx(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem, - void *array, int *status); -int CFITS_API ffppxll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem, - void *array, int *status); -int CFITS_API ffppxn(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem, - void *array, void *nulval, int *status); -int CFITS_API ffppxnll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem, - void *array, void *nulval, int *status); -int CFITS_API ffppr(fitsfile *fptr, int datatype, LONGLONG firstelem, - LONGLONG nelem, void *array, int *status); -int CFITS_API ffpprb(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, unsigned char *array, int *status); -int CFITS_API ffpprsb(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, signed char *array, int *status); -int CFITS_API ffpprui(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, unsigned short *array, int *status); -int CFITS_API ffppri(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, short *array, int *status); -int CFITS_API ffppruj(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, unsigned long *array, int *status); -int CFITS_API ffpprj(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, long *array, int *status); -int CFITS_API ffppruk(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, unsigned int *array, int *status); -int CFITS_API ffpprk(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, int *array, int *status); -int CFITS_API ffppre(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, float *array, int *status); -int CFITS_API ffpprd(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, double *array, int *status); -int CFITS_API ffpprjj(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, LONGLONG *array, int *status); - -int CFITS_API ffppru(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - int *status); -int CFITS_API ffpprn(fitsfile *fptr, LONGLONG firstelem, LONGLONG nelem, int *status); - -int CFITS_API ffppn(fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelem, - void *array, void *nulval, int *status); -int CFITS_API ffppnb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - unsigned char *array, unsigned char nulval, int *status); -int CFITS_API ffppnsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - signed char *array, signed char nulval, int *status); -int CFITS_API ffppnui(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, unsigned short *array, unsigned short nulval, - int *status); -int CFITS_API ffppni(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, short *array, short nulval, int *status); -int CFITS_API ffppnj(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, long *array, long nulval, int *status); -int CFITS_API ffppnuj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - unsigned long *array, unsigned long nulval, int *status); -int CFITS_API ffppnuk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, - unsigned int *array, unsigned int nulval, int *status); -int CFITS_API ffppnk(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, int *array, int nulval, int *status); -int CFITS_API ffppne(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, float *array, float nulval, int *status); -int CFITS_API ffppnd(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, double *array, double nulval, int *status); -int CFITS_API ffppnjj(fitsfile *fptr, long group, LONGLONG firstelem, - LONGLONG nelem, LONGLONG *array, LONGLONG nulval, int *status); - -int CFITS_API ffp2db(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, - LONGLONG naxis2, unsigned char *array, int *status); -int CFITS_API ffp2dsb(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, - LONGLONG naxis2, signed char *array, int *status); -int CFITS_API ffp2dui(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, - LONGLONG naxis2, unsigned short *array, int *status); -int CFITS_API ffp2di(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, - LONGLONG naxis2, short *array, int *status); -int CFITS_API ffp2duj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, - LONGLONG naxis2, unsigned long *array, int *status); -int CFITS_API ffp2dj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, - LONGLONG naxis2, long *array, int *status); -int CFITS_API ffp2duk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, - LONGLONG naxis2, unsigned int *array, int *status); -int CFITS_API ffp2dk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, - LONGLONG naxis2, int *array, int *status); -int CFITS_API ffp2de(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, - LONGLONG naxis2, float *array, int *status); -int CFITS_API ffp2dd(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, - LONGLONG naxis2, double *array, int *status); -int CFITS_API ffp2djj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG *array, int *status); - -int CFITS_API ffp3db(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, unsigned char *array, int *status); -int CFITS_API ffp3dsb(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, signed char *array, int *status); -int CFITS_API ffp3dui(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, unsigned short *array, int *status); -int CFITS_API ffp3di(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, short *array, int *status); -int CFITS_API ffp3duj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, unsigned long *array, int *status); -int CFITS_API ffp3dj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, long *array, int *status); -int CFITS_API ffp3duk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, unsigned int *array, int *status); -int CFITS_API ffp3dk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, int *array, int *status); -int CFITS_API ffp3de(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, float *array, int *status); -int CFITS_API ffp3dd(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, double *array, int *status); -int CFITS_API ffp3djj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, - LONGLONG naxis2, LONGLONG naxis3, LONGLONG *array, int *status); - -int CFITS_API ffpss(fitsfile *fptr, int datatype, - long *fpixel, long *lpixel, void *array, int *status); -int CFITS_API ffpssb(fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, unsigned char *array, int *status); -int CFITS_API ffpsssb(fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, signed char *array, int *status); -int CFITS_API ffpssui(fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, unsigned short *array, int *status); -int CFITS_API ffpssi(fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, short *array, int *status); -int CFITS_API ffpssuj(fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, unsigned long *array, int *status); -int CFITS_API ffpssj(fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, long *array, int *status); -int CFITS_API ffpssuk(fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, unsigned int *array, int *status); -int CFITS_API ffpssk(fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, int *array, int *status); -int CFITS_API ffpsse(fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, float *array, int *status); -int CFITS_API ffpssd(fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, double *array, int *status); -int CFITS_API ffpssjj(fitsfile *fptr, long group, long naxis, long *naxes, - long *fpixel, long *lpixel, LONGLONG *array, int *status); - -int CFITS_API ffpgpb(fitsfile *fptr, long group, long firstelem, - long nelem, unsigned char *array, int *status); -int CFITS_API ffpgpsb(fitsfile *fptr, long group, long firstelem, - long nelem, signed char *array, int *status); -int CFITS_API ffpgpui(fitsfile *fptr, long group, long firstelem, - long nelem, unsigned short *array, int *status); -int CFITS_API ffpgpi(fitsfile *fptr, long group, long firstelem, - long nelem, short *array, int *status); -int CFITS_API ffpgpuj(fitsfile *fptr, long group, long firstelem, - long nelem, unsigned long *array, int *status); -int CFITS_API ffpgpj(fitsfile *fptr, long group, long firstelem, - long nelem, long *array, int *status); -int CFITS_API ffpgpuk(fitsfile *fptr, long group, long firstelem, - long nelem, unsigned int *array, int *status); -int CFITS_API ffpgpk(fitsfile *fptr, long group, long firstelem, - long nelem, int *array, int *status); -int CFITS_API ffpgpe(fitsfile *fptr, long group, long firstelem, - long nelem, float *array, int *status); -int CFITS_API ffpgpd(fitsfile *fptr, long group, long firstelem, - long nelem, double *array, int *status); -int CFITS_API ffpgpjj(fitsfile *fptr, long group, long firstelem, - long nelem, LONGLONG *array, int *status); - -/*--------------------- iterator functions -------------*/ -int CFITS_API fits_iter_set_by_name(iteratorCol *col, fitsfile *fptr, char *colname, - int datatype, int iotype); -int CFITS_API fits_iter_set_by_num(iteratorCol *col, fitsfile *fptr, int colnum, - int datatype, int iotype); -int CFITS_API fits_iter_set_file(iteratorCol *col, fitsfile *fptr); -int CFITS_API fits_iter_set_colname(iteratorCol *col, char *colname); -int CFITS_API fits_iter_set_colnum(iteratorCol *col, int colnum); -int CFITS_API fits_iter_set_datatype(iteratorCol *col, int datatype); -int CFITS_API fits_iter_set_iotype(iteratorCol *col, int iotype); - -CFITS_API fitsfile * fits_iter_get_file(iteratorCol *col); -char CFITS_API * fits_iter_get_colname(iteratorCol *col); -int CFITS_API fits_iter_get_colnum(iteratorCol *col); -int CFITS_API fits_iter_get_datatype(iteratorCol *col); -int CFITS_API fits_iter_get_iotype(iteratorCol *col); -void CFITS_API *fits_iter_get_array(iteratorCol *col); -long CFITS_API fits_iter_get_tlmin(iteratorCol *col); -long CFITS_API fits_iter_get_tlmax(iteratorCol *col); -long CFITS_API fits_iter_get_repeat(iteratorCol *col); -char CFITS_API *fits_iter_get_tunit(iteratorCol *col); -char CFITS_API *fits_iter_get_tdisp(iteratorCol *col); - -int CFITS_API ffiter(int ncols, iteratorCol *data, long offset, long nPerLoop, - int (*workFn)( long totaln, long offset, long firstn, - long nvalues, int narrays, iteratorCol *data, void *userPointer), - void *userPointer, int *status); - -/*--------------------- write column elements -------------*/ -int CFITS_API ffpcl(fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, - LONGLONG firstelem, LONGLONG nelem, void *array, int *status); -int CFITS_API ffpcls(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, char **array, int *status); -int CFITS_API ffpcll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, char *array, int *status); -int CFITS_API ffpclb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned char *array, int *status); -int CFITS_API ffpclsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, signed char *array, int *status); -int CFITS_API ffpclui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned short *array, int *status); -int CFITS_API ffpcli(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, short *array, int *status); -int CFITS_API ffpcluj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned long *array, int *status); -int CFITS_API ffpclj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long *array, int *status); -int CFITS_API ffpcluk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned int *array, int *status); -int CFITS_API ffpclk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, int *array, int *status); -int CFITS_API ffpcle(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, float *array, int *status); -int CFITS_API ffpcld(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, double *array, int *status); -int CFITS_API ffpclc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, float *array, int *status); -int CFITS_API ffpclm(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, double *array, int *status); -int CFITS_API ffpclu(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, int *status); -int CFITS_API ffprwu(fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, int *status); -int CFITS_API ffpcljj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, LONGLONG *array, int *status); -int CFITS_API ffpclx(fitsfile *fptr, int colnum, LONGLONG frow, long fbit, long nbit, - char *larray, int *status); - -int CFITS_API ffpcn(fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, void *array, void *nulval, int *status); -int CFITS_API ffpcns( fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, char **array, char *nulvalue, int *status); -int CFITS_API ffpcnl( fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, char *array, char nulvalue, int *status); -int CFITS_API ffpcnb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned char *array, unsigned char nulvalue, - int *status); -int CFITS_API ffpcnsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, signed char *array, signed char nulvalue, - int *status); -int CFITS_API ffpcnui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned short *array, unsigned short nulvalue, - int *status); -int CFITS_API ffpcni(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, short *array, short nulvalue, int *status); -int CFITS_API ffpcnuj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned long *array, unsigned long nulvalue, - int *status); -int CFITS_API ffpcnj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long *array, long nulvalue, int *status); -int CFITS_API ffpcnuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, unsigned int *array, unsigned int nulvalue, - int *status); -int CFITS_API ffpcnk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, int *array, int nulvalue, int *status); -int CFITS_API ffpcne(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, float *array, float nulvalue, int *status); -int CFITS_API ffpcnd(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, double *array, double nulvalue, int *status); -int CFITS_API ffpcnjj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, LONGLONG *array, LONGLONG nulvalue, int *status); -int CFITS_API ffptbb(fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, - unsigned char *values, int *status); - -int CFITS_API ffirow(fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, int *status); -int CFITS_API ffdrow(fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, int *status); -int CFITS_API ffdrrg(fitsfile *fptr, char *ranges, int *status); -int CFITS_API ffdrws(fitsfile *fptr, long *rownum, long nrows, int *status); -int CFITS_API ffdrwsll(fitsfile *fptr, LONGLONG *rownum, LONGLONG nrows, int *status); -int CFITS_API fficol(fitsfile *fptr, int numcol, char *ttype, char *tform, int *status); -int CFITS_API fficls(fitsfile *fptr, int firstcol, int ncols, char **ttype, - char **tform, int *status); -int CFITS_API ffmvec(fitsfile *fptr, int colnum, LONGLONG newveclen, int *status); -int CFITS_API ffdcol(fitsfile *fptr, int numcol, int *status); -int CFITS_API ffcpcl(fitsfile *infptr, fitsfile *outfptr, int incol, int outcol, - int create_col, int *status); -int CFITS_API ffcprw(fitsfile *infptr, fitsfile *outfptr, LONGLONG firstrow, - LONGLONG nrows, int *status); - -/*--------------------- WCS Utilities ------------------*/ -int CFITS_API ffgics(fitsfile *fptr, double *xrval, double *yrval, double *xrpix, - double *yrpix, double *xinc, double *yinc, double *rot, - char *type, int *status); -int CFITS_API ffgicsa(fitsfile *fptr, char version, double *xrval, double *yrval, double *xrpix, - double *yrpix, double *xinc, double *yinc, double *rot, - char *type, int *status); -int CFITS_API ffgtcs(fitsfile *fptr, int xcol, int ycol, double *xrval, - double *yrval, double *xrpix, double *yrpix, double *xinc, - double *yinc, double *rot, char *type, int *status); -int CFITS_API ffwldp(double xpix, double ypix, double xref, double yref, - double xrefpix, double yrefpix, double xinc, double yinc, - double rot, char *type, double *xpos, double *ypos, int *status); -int CFITS_API ffxypx(double xpos, double ypos, double xref, double yref, - double xrefpix, double yrefpix, double xinc, double yinc, - double rot, char *type, double *xpix, double *ypix, int *status); - -/* WCS support routines (provide interface to Doug Mink's WCS library */ -int CFITS_API ffgiwcs(fitsfile *fptr, char **header, int *status); -int CFITS_API ffgtwcs(fitsfile *fptr, int xcol, int ycol, char **header, int *status); - -/*--------------------- lexical parsing routines ------------------*/ -int CFITS_API fftexp( fitsfile *fptr, char *expr, int maxdim, - int *datatype, long *nelem, int *naxis, - long *naxes, int *status ); - -int CFITS_API fffrow( fitsfile *infptr, char *expr, - long firstrow, long nrows, - long *n_good_rows, char *row_status, int *status); - -int CFITS_API ffffrw( fitsfile *fptr, char *expr, long *rownum, int *status); - -int CFITS_API fffrwc( fitsfile *fptr, char *expr, char *timeCol, - char *parCol, char *valCol, long ntimes, - double *times, char *time_status, int *status ); - -int CFITS_API ffsrow( fitsfile *infptr, fitsfile *outfptr, char *expr, - int *status); - -int CFITS_API ffcrow( fitsfile *fptr, int datatype, char *expr, - long firstrow, long nelements, void *nulval, - void *array, int *anynul, int *status ); - -int CFITS_API ffcalc_rng( fitsfile *infptr, char *expr, fitsfile *outfptr, - char *parName, char *parInfo, int nRngs, - long *start, long *end, int *status ); - -int CFITS_API ffcalc( fitsfile *infptr, char *expr, fitsfile *outfptr, - char *parName, char *parInfo, int *status ); - - /* ffhist is not really intended as a user-callable routine */ - /* but it may be useful for some specialized applications */ - /* ffhist2 is a newer version which is strongly recommended instead of ffhist */ - -int CFITS_API ffhist(fitsfile **fptr, char *outfile, int imagetype, int naxis, - char colname[4][FLEN_VALUE], - double *minin, double *maxin, double *binsizein, - char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], - char binname[4][FLEN_VALUE], - double weightin, char wtcol[FLEN_VALUE], - int recip, char *rowselect, int *status); -int CFITS_API ffhist2(fitsfile **fptr, char *outfile, int imagetype, int naxis, - char colname[4][FLEN_VALUE], - double *minin, double *maxin, double *binsizein, - char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], - char binname[4][FLEN_VALUE], - double weightin, char wtcol[FLEN_VALUE], - int recip, char *rowselect, int *status); -CFITS_API fitsfile *ffhist3(fitsfile *fptr, - char *outfile, int imagetype, int naxis, - char colname[4][FLEN_VALUE], - double *minin, - double *maxin, - double *binsizein, - char minname[4][FLEN_VALUE], - char maxname[4][FLEN_VALUE], - char binname[4][FLEN_VALUE], - double weightin, - char wtcol[FLEN_VALUE], - int recip, - char *selectrow, - int *status); -int CFITS_API fits_select_image_section(fitsfile **fptr, char *outfile, - char *imagesection, int *status); -int CFITS_API fits_copy_image_section(fitsfile *infptr, fitsfile *outfile, - char *imagesection, int *status); - -int CFITS_API fits_calc_binning(fitsfile *fptr, int naxis, char colname[4][FLEN_VALUE], - double *minin, double *maxin, double *binsizein, - char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], - char binname[4][FLEN_VALUE], int *colnum, long *haxes, float *amin, - float *amax, float *binsize, int *status); - -int CFITS_API fits_write_keys_histo(fitsfile *fptr, fitsfile *histptr, - int naxis, int *colnum, int *status); -int CFITS_API fits_rebin_wcs( fitsfile *fptr, int naxis, float *amin, float *binsize, - int *status); -int CFITS_API fits_make_hist(fitsfile *fptr, fitsfile *histptr, int bitpix,int naxis, - long *naxes, int *colnum, float *amin, float *amax, float *binsize, - float weight, int wtcolnum, int recip, char *selectrow, int *status); - -typedef struct -{ - /* input(s) */ - int count; - char ** path; - char ** tag; - fitsfile ** ifptr; - - char * expression; - - /* output control */ - int bitpix; - long blank; - fitsfile * ofptr; - char keyword[FLEN_KEYWORD]; - char comment[FLEN_COMMENT]; -} PixelFilter; - - -int CFITS_API fits_pixel_filter (PixelFilter * filter, int * status); - - -/*--------------------- grouping routines ------------------*/ - -int CFITS_API ffgtcr(fitsfile *fptr, char *grpname, int grouptype, int *status); -int CFITS_API ffgtis(fitsfile *fptr, char *grpname, int grouptype, int *status); -int CFITS_API ffgtch(fitsfile *gfptr, int grouptype, int *status); -int CFITS_API ffgtrm(fitsfile *gfptr, int rmopt, int *status); -int CFITS_API ffgtcp(fitsfile *infptr, fitsfile *outfptr, int cpopt, int *status); -int CFITS_API ffgtmg(fitsfile *infptr, fitsfile *outfptr, int mgopt, int *status); -int CFITS_API ffgtcm(fitsfile *gfptr, int cmopt, int *status); -int CFITS_API ffgtvf(fitsfile *gfptr, long *firstfailed, int *status); -int CFITS_API ffgtop(fitsfile *mfptr,int group,fitsfile **gfptr,int *status); -int CFITS_API ffgtam(fitsfile *gfptr, fitsfile *mfptr, int hdupos, int *status); -int CFITS_API ffgtnm(fitsfile *gfptr, long *nmembers, int *status); -int CFITS_API ffgmng(fitsfile *mfptr, long *nmembers, int *status); -int CFITS_API ffgmop(fitsfile *gfptr, long member, fitsfile **mfptr, int *status); -int CFITS_API ffgmcp(fitsfile *gfptr, fitsfile *mfptr, long member, int cpopt, - int *status); -int CFITS_API ffgmtf(fitsfile *infptr, fitsfile *outfptr, long member, int tfopt, - int *status); -int CFITS_API ffgmrm(fitsfile *fptr, long member, int rmopt, int *status); - -/*--------------------- group template parser routines ------------------*/ - -int CFITS_API fits_execute_template(fitsfile *ff, char *ngp_template, int *status); - -int CFITS_API fits_img_stats_short(short *array,long nx, long ny, int nullcheck, - short nullvalue,long *ngoodpix, short *minvalue, short *maxvalue, double *mean, - double *sigma, double *noise1, double *noise2, double *noise3, double *noise5, int *status); -int CFITS_API fits_img_stats_int(int *array,long nx, long ny, int nullcheck, - int nullvalue,long *ngoodpix, int *minvalue, int *maxvalue, double *mean, - double *sigma, double *noise1, double *noise2, double *noise3, double *noise5, int *status); -int CFITS_API fits_img_stats_float(float *array, long nx, long ny, int nullcheck, - float nullvalue,long *ngoodpix, float *minvalue, float *maxvalue, double *mean, - double *sigma, double *noise1, double *noise2, double *noise3, double *noise5, int *status); - -/*--------------------- image compression routines ------------------*/ - -int CFITS_API fits_set_compression_type(fitsfile *fptr, int ctype, int *status); -int CFITS_API fits_set_tile_dim(fitsfile *fptr, int ndim, long *dims, int *status); -int CFITS_API fits_set_noise_bits(fitsfile *fptr, int noisebits, int *status); -int CFITS_API fits_set_quantize_level(fitsfile *fptr, float qlevel, int *status); -int CFITS_API fits_set_hcomp_scale(fitsfile *fptr, float scale, int *status); -int CFITS_API fits_set_hcomp_smooth(fitsfile *fptr, int smooth, int *status); -int CFITS_API fits_set_quantize_method(fitsfile *fptr, int method, int *status); -int CFITS_API fits_set_quantize_dither(fitsfile *fptr, int dither, int *status); -int CFITS_API fits_set_dither_seed(fitsfile *fptr, int seed, int *status); -int CFITS_API fits_set_dither_offset(fitsfile *fptr, int offset, int *status); -int CFITS_API fits_set_lossy_int(fitsfile *fptr, int lossy_int, int *status); -int CFITS_API fits_set_huge_hdu(fitsfile *fptr, int huge, int *status); -int CFITS_API fits_set_compression_pref(fitsfile *infptr, fitsfile *outfptr, int *status); - -int CFITS_API fits_get_compression_type(fitsfile *fptr, int *ctype, int *status); -int CFITS_API fits_get_tile_dim(fitsfile *fptr, int ndim, long *dims, int *status); -int CFITS_API fits_get_quantize_level(fitsfile *fptr, float *qlevel, int *status); -int CFITS_API fits_get_noise_bits(fitsfile *fptr, int *noisebits, int *status); -int CFITS_API fits_get_hcomp_scale(fitsfile *fptr, float *scale, int *status); -int CFITS_API fits_get_hcomp_smooth(fitsfile *fptr, int *smooth, int *status); -int CFITS_API fits_get_dither_seed(fitsfile *fptr, int *seed, int *status); - -int CFITS_API fits_img_compress(fitsfile *infptr, fitsfile *outfptr, int *status); -int CFITS_API fits_compress_img(fitsfile *infptr, fitsfile *outfptr, int compress_type, - long *tilesize, int parm1, int parm2, int *status); -int CFITS_API fits_is_compressed_image(fitsfile *fptr, int *status); -int CFITS_API fits_is_reentrant(void); -int CFITS_API fits_decompress_img (fitsfile *infptr, fitsfile *outfptr, int *status); -int CFITS_API fits_img_decompress_header(fitsfile *infptr, fitsfile *outfptr, int *status); -int CFITS_API fits_img_decompress (fitsfile *infptr, fitsfile *outfptr, int *status); - -/* H-compress routines */ -int CFITS_API fits_hcompress(int *a, int nx, int ny, int scale, char *output, - long *nbytes, int *status); -int CFITS_API fits_hcompress64(LONGLONG *a, int nx, int ny, int scale, char *output, - long *nbytes, int *status); -int CFITS_API fits_hdecompress(unsigned char *input, int smooth, int *a, int *nx, - int *ny, int *scale, int *status); -int CFITS_API fits_hdecompress64(unsigned char *input, int smooth, LONGLONG *a, int *nx, - int *ny, int *scale, int *status); - -int CFITS_API fits_compress_table (fitsfile *infptr, fitsfile *outfptr, int *status); -int CFITS_API fits_uncompress_table(fitsfile *infptr, fitsfile *outfptr, int *status); - -/* The following exclusion if __CINT__ is defined is needed for ROOT */ -#ifndef __CINT__ -#ifdef __cplusplus -} -#endif -#endif - -#endif - diff --git a/src/external/OpenGR/3rdparty/cfitsio/fitsio2.h b/src/external/OpenGR/3rdparty/cfitsio/fitsio2.h deleted file mode 100644 index 61c0bf34c..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/fitsio2.h +++ /dev/null @@ -1,1216 +0,0 @@ -#ifndef _FITSIO2_H -#define _FITSIO2_H - -#include "fitsio.h" - -/* - Threading support using POSIX threads programming interface - (supplied by Bruce O'Neel) - - All threaded programs MUST have the - - -D_REENTRANT - - on the compile line and must link with -lpthread. This means that - when one builds cfitsio for threads you must have -D_REENTRANT on the - gcc or cc command line. -*/ - -#ifdef _REENTRANT -#include -/* #include not needed any more */ -extern pthread_mutex_t Fitsio_Lock; -extern int Fitsio_Pthread_Status; - -#define FFLOCK1(lockname) (Fitsio_Pthread_Status = pthread_mutex_lock(&lockname)) -#define FFUNLOCK1(lockname) (Fitsio_Pthread_Status = pthread_mutex_unlock(&lockname)) -#define FFLOCK FFLOCK1(Fitsio_Lock) -#define FFUNLOCK FFUNLOCK1(Fitsio_Lock) -#define ffstrtok(str, tok, save) strtok_r(str, tok, save) - -#else -#define FFLOCK -#define FFUNLOCK -#define ffstrtok(str, tok, save) strtok(str, tok) -#endif - -/* - If REPLACE_LINKS is defined, then whenever CFITSIO fails to open - a file with write access because it is a soft link to a file that - only has read access, then CFITSIO will attempt to replace - the link with a local copy of the file, with write access. This - feature was originally added to support the ftools in the Hera - environment, where many of the user's data file are soft links. -*/ -#if defined(BUILD_HERA) -#define REPLACE_LINKS 1 -#endif - -#define USE_LARGE_VALUE -99 /* flag used when writing images */ - -#define DBUFFSIZE 28800 /* size of data buffer in bytes */ - -#define NMAXFILES 1000 /* maximum number of FITS files that can be opened */ - /* CFITSIO will allocate (NMAXFILES * 80) bytes of memory */ - /* plus each file that is opened will use NIOBUF * 2880 bytes of memeory */ - /* where NIOBUF is defined in fitio.h and has a default value of 40 */ - -#define MINDIRECT 8640 /* minimum size for direct reads and writes */ - /* MINDIRECT must have a value >= 8640 */ - -/* it is useful to identify certain specific types of machines */ -#define NATIVE 0 /* machine that uses non-byteswapped IEEE formats */ -#define OTHERTYPE 1 /* any other type of machine */ -#define VAXVMS 3 /* uses an odd floating point format */ -#define ALPHAVMS 4 /* uses an odd floating point format */ -#define IBMPC 5 /* used in drvrfile.c to work around a bug on PCs */ -#define CRAY 6 /* requires a special NaN test algorithm */ - -#define GFLOAT 1 /* used for VMS */ -#define IEEEFLOAT 2 /* used for VMS */ - -/* ======================================================================= */ -/* The following logic is used to determine the type machine, */ -/* whether the bytes are swapped, and the number of bits in a long value */ -/* ======================================================================= */ - -/* The following platforms have sizeof(long) == 8 */ -/* This block of code should match a similar block in fitsio.h */ -/* and the block of code at the beginning of f77_wrap.h */ - -#if defined(__alpha) && ( defined(__unix__) || defined(__NetBSD__) ) - /* old Dec Alpha platforms running OSF */ -#define BYTESWAPPED TRUE -#define LONGSIZE 64 - -#elif defined(__sparcv9) || (defined(__sparc__) && defined(__arch64__)) - /* SUN Solaris7 in 64-bit mode */ -#define BYTESWAPPED FALSE -#define MACHINE NATIVE -#define LONGSIZE 64 - - /* IBM System z mainframe support */ -#elif defined(__s390x__) -#define BYTESWAPPED FALSE -#define LONGSIZE 64 - -#elif defined(__s390__) -#define BYTESWAPPED FALSE -#define LONGSIZE 32 - -#elif defined(__ia64__) || defined(__x86_64__) || defined(__AARCH64EL__) - /* Intel itanium 64-bit PC, or AMD opteron 64-bit PC */ -#define BYTESWAPPED TRUE -#define LONGSIZE 64 - -#elif defined(_SX) /* Nec SuperUx */ - -#define BYTESWAPPED FALSE -#define MACHINE NATIVE -#define LONGSIZE 64 - -#elif defined(__powerpc64__) || defined(__64BIT__) || defined(__AARCH64EB__) /* IBM 64-bit AIX powerpc*/ - /* could also test for __ppc64__ or __PPC64 */ - -# if defined(__LITTLE_ENDIAN__) -# define BYTESWAPPED TRUE -# else -# define BYTESWAPPED FALSE -# define MACHINE NATIVE -# endif -# define LONGSIZE 64 - -#elif defined(_MIPS_SZLONG) - -# if defined(MIPSEL) -# define BYTESWAPPED TRUE -# else -# define BYTESWAPPED FALSE -# define MACHINE NATIVE -# endif - -# if _MIPS_SZLONG == 32 -# define LONGSIZE 32 -# elif _MIPS_SZLONG == 64 -# define LONGSIZE 64 -# else -# error "can't handle long size given by _MIPS_SZLONG" -# endif - -/* ============================================================== */ -/* the following are all 32-bit byteswapped platforms */ - -#elif defined(vax) && defined(VMS) - -#define MACHINE VAXVMS -#define BYTESWAPPED TRUE - -#elif defined(__alpha) && defined(__VMS) - -#if (__D_FLOAT == TRUE) - -/* this float option is the same as for VAX/VMS machines. */ -#define MACHINE VAXVMS -#define BYTESWAPPED TRUE - -#elif (__G_FLOAT == TRUE) - -/* G_FLOAT is the default for ALPHA VMS systems */ -#define MACHINE ALPHAVMS -#define BYTESWAPPED TRUE -#define FLOATTYPE GFLOAT - -#elif (__IEEE_FLOAT == TRUE) - -#define MACHINE ALPHAVMS -#define BYTESWAPPED TRUE -#define FLOATTYPE IEEEFLOAT - -#endif /* end of alpha VMS case */ - -#elif defined(ultrix) && defined(unix) - /* old Dec ultrix machines */ -#define BYTESWAPPED TRUE - -#elif defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) \ - || defined(_MSC_VER) || defined(__BORLANDC__) || defined(__TURBOC__) \ - || defined(_NI_mswin_) || defined(__EMX__) - -/* generic 32-bit IBM PC */ -#define MACHINE IBMPC -#define BYTESWAPPED TRUE - -#elif defined(__arm__) - -/* This assumes all ARM are little endian. In the future, it might be */ -/* necessary to use "if defined(__ARMEL__)" to distinguish little from big. */ -/* (__ARMEL__ would be defined on little-endian, but not on big-endian). */ - -#define BYTESWAPPED TRUE - -#elif defined(__tile__) - -/* 64-core 8x8-architecture Tile64 platform */ - -#define BYTESWAPPED TRUE - -#elif defined(__sh__) - -/* SuperH CPU can be used in both little and big endian modes */ - -#if defined(__LITTLE_ENDIAN__) -#define BYTESWAPPED TRUE -#else -#define BYTESWAPPED FALSE -#endif - -#else - -/* assume all other machine uses the same IEEE formats as used in FITS files */ -/* e.g., Macs fall into this category */ - -#define MACHINE NATIVE -#define BYTESWAPPED FALSE - -#endif - -#ifndef MACHINE -#define MACHINE OTHERTYPE -#endif - -/* assume longs are 4 bytes long, unless previously set otherwise */ -#ifndef LONGSIZE -#define LONGSIZE 32 -#endif - -/* end of block that determine long size and byte swapping */ -/* ==================================================================== */ - -#define IGNORE_EOF 1 -#define REPORT_EOF 0 -#define DATA_UNDEFINED -1 -#define NULL_UNDEFINED 1234554321 -#define ASCII_NULL_UNDEFINED 1 /* indicate no defined null value */ - -#define maxvalue(A,B) ((A) > (B) ? (A) : (B)) -#define minvalue(A,B) ((A) < (B) ? (A) : (B)) - -/* faster string comparison macros */ -#define FSTRCMP(a,b) ((a)[0]<(b)[0]? -1:(a)[0]>(b)[0]?1:strcmp((a),(b))) -#define FSTRNCMP(a,b,n) ((a)[0]<(b)[0]?-1:(a)[0]>(b)[0]?1:strncmp((a),(b),(n))) - -#if defined(__VMS) || defined(VMS) - -#define FNANMASK 0xFFFF /* mask all bits */ -#define DNANMASK 0xFFFF /* mask all bits */ - -#else - -#define FNANMASK 0x7F80 /* mask bits 1 - 8; all set on NaNs */ - /* all 0 on underflow or 0. */ - -#define DNANMASK 0x7FF0 /* mask bits 1 - 11; all set on NaNs */ - /* all 0 on underflow or 0. */ - -#endif - -#if MACHINE == CRAY - /* - Cray machines: the large negative integer corresponds - to the 3 most sig digits set to 1. If these - 3 bits are set in a floating point number (64 bits), then it represents - a reserved value (i.e., a NaN) - */ -#define fnan(L) ( (L) >= 0xE000000000000000 ? 1 : 0) ) - -#else - /* these functions work for both big and little endian machines */ - /* that use the IEEE floating point format for internal numbers */ - - /* These functions tests whether the float value is a reserved IEEE */ - /* value such as a Not-a-Number (NaN), or underflow, overflow, or */ - /* infinity. The functions returns 1 if the value is a NaN, overflow */ - /* or infinity; it returns 2 if the value is an denormalized underflow */ - /* value; otherwise it returns 0. fnan tests floats, dnan tests doubles */ - -#define fnan(L) \ - ( (L & FNANMASK) == FNANMASK ? 1 : (L & FNANMASK) == 0 ? 2 : 0) - -#define dnan(L) \ - ( (L & DNANMASK) == DNANMASK ? 1 : (L & DNANMASK) == 0 ? 2 : 0) - -#endif - -#define DSCHAR_MAX 127.49 /* max double value that fits in an signed char */ -#define DSCHAR_MIN -128.49 /* min double value that fits in an signed char */ -#define DUCHAR_MAX 255.49 /* max double value that fits in an unsigned char */ -#define DUCHAR_MIN -0.49 /* min double value that fits in an unsigned char */ -#define DUSHRT_MAX 65535.49 /* max double value that fits in a unsigned short*/ -#define DUSHRT_MIN -0.49 /* min double value that fits in an unsigned short */ -#define DSHRT_MAX 32767.49 /* max double value that fits in a short */ -#define DSHRT_MIN -32768.49 /* min double value that fits in a short */ - -#if LONGSIZE == 32 -# define DLONG_MAX 2147483647.49 /* max double value that fits in a long */ -# define DLONG_MIN -2147483648.49 /* min double value that fits in a long */ -# define DULONG_MAX 4294967295.49 /* max double that fits in a unsigned long */ -#else -# define DLONG_MAX 9.2233720368547752E18 /* max double value long */ -# define DLONG_MIN -9.2233720368547752E18 /* min double value long */ -# define DULONG_MAX 1.84467440737095504E19 /* max double value ulong */ -#endif - -#define DULONG_MIN -0.49 /* min double value that fits in an unsigned long */ -#define DLONGLONG_MAX 9.2233720368547755807E18 /* max double value longlong */ -#define DLONGLONG_MIN -9.2233720368547755808E18 /* min double value longlong */ -#define DUINT_MAX 4294967295.49 /* max dbl that fits in a unsigned 4-byte int */ -#define DUINT_MIN -0.49 /* min dbl that fits in an unsigned 4-byte int */ -#define DINT_MAX 2147483647.49 /* max double value that fits in a 4-byte int */ -#define DINT_MIN -2147483648.49 /* min double value that fits in a 4-byte int */ - -#ifndef UINT32_MAX -#define UINT32_MAX 4294967295U /* max unsigned 32-bit integer */ -#endif -#ifndef INT32_MAX -#define INT32_MAX 2147483647 /* max 32-bit integer */ -#endif -#ifndef INT32_MIN -#define INT32_MIN (-INT32_MAX -1) /* min 32-bit integer */ -#endif - - -#define COMPRESS_NULL_VALUE -2147483647 -#define N_RANDOM 10000 /* DO NOT CHANGE THIS; used when quantizing real numbers */ - -int ffgnky(fitsfile *fptr, char *card, int *status); -void ffcfmt(char *tform, char *cform); -void ffcdsp(char *tform, char *cform); -void ffswap2(short *values, long nvalues); -void ffswap4(INT32BIT *values, long nvalues); -void ffswap8(double *values, long nvalues); -int ffi2c(LONGLONG ival, char *cval, int *status); -int ffl2c(int lval, char *cval, int *status); -int ffs2c(const char *instr, char *outstr, int *status); -int ffr2f(float fval, int decim, char *cval, int *status); -int ffr2e(float fval, int decim, char *cval, int *status); -int ffd2f(double dval, int decim, char *cval, int *status); -int ffd2e(double dval, int decim, char *cval, int *status); -int ffc2ii(const char *cval, long *ival, int *status); -int ffc2jj(const char *cval, LONGLONG *ival, int *status); -int ffc2ll(const char *cval, int *lval, int *status); -int ffc2rr(const char *cval, float *fval, int *status); -int ffc2dd(const char *cval, double *dval, int *status); -int ffc2x(const char *cval, char *dtype, long *ival, int *lval, char *sval, - double *dval, int *status); -int ffc2xx(const char *cval, char *dtype, LONGLONG *ival, int *lval, char *sval, - double *dval, int *status); -int ffc2s(const char *instr, char *outstr, int *status); -int ffc2i(const char *cval, long *ival, int *status); -int ffc2j(const char *cval, LONGLONG *ival, int *status); -int ffc2r(const char *cval, float *fval, int *status); -int ffc2d(const char *cval, double *dval, int *status); -int ffc2l(const char *cval, int *lval, int *status); -void ffxmsg(int action, char *err_message); -int ffgcnt(fitsfile *fptr, char *value, char *comm, int *status); -int ffgtkn(fitsfile *fptr, int numkey, char *keyname, long *value, int *status); -int ffgtknjj(fitsfile *fptr, int numkey, char *keyname, LONGLONG *value, int *status); -int fftkyn(fitsfile *fptr, int numkey, char *keyname, char *value, int *status); -int ffgphd(fitsfile *fptr, int maxdim, int *simple, int *bitpix, int *naxis, - LONGLONG naxes[], long *pcount, long *gcount, int *extend, double *bscale, - double *bzero, LONGLONG *blank, int *nspace, int *status); -int ffgttb(fitsfile *fptr, LONGLONG *rowlen, LONGLONG *nrows, LONGLONG *pcount, - long *tfield, int *status); - -int ffmkey(fitsfile *fptr, const char *card, int *status); - -/* ffmbyt has been moved to fitsio.h */ -int ffgbyt(fitsfile *fptr, LONGLONG nbytes, void *buffer, int *status); -int ffpbyt(fitsfile *fptr, LONGLONG nbytes, void *buffer, int *status); -int ffgbytoff(fitsfile *fptr, long gsize, long ngroups, long offset, - void *buffer, int *status); -int ffpbytoff(fitsfile *fptr, long gsize, long ngroups, long offset, - void *buffer, int *status); -int ffldrc(fitsfile *fptr, long record, int err_mode, int *status); -int ffwhbf(fitsfile *fptr, int *nbuff); -int ffbfeof(fitsfile *fptr, int *status); -int ffbfwt(FITSfile *Fptr, int nbuff, int *status); -int ffpxsz(int datatype); - -int ffourl(char *url, char *urltype, char *outfile, char *tmplfile, - char *compspec, int *status); -int ffparsecompspec(fitsfile *fptr, char *compspec, int *status); -int ffoptplt(fitsfile *fptr, const char *tempname, int *status); -int fits_is_this_a_copy(char *urltype); -int fits_store_Fptr(FITSfile *Fptr, int *status); -int fits_clear_Fptr(FITSfile *Fptr, int *status); -int fits_already_open(fitsfile **fptr, char *url, - char *urltype, char *infile, char *extspec, char *rowfilter, - char *binspec, char *colspec, int mode,int *isopen, int *status); -int ffedit_columns(fitsfile **fptr, char *outfile, char *expr, int *status); -int fits_get_col_minmax(fitsfile *fptr, int colnum, float *datamin, - float *datamax, int *status); -int ffwritehisto(long totaln, long offset, long firstn, long nvalues, - int narrays, iteratorCol *imagepars, void *userPointer); -int ffcalchist(long totalrows, long offset, long firstrow, long nrows, - int ncols, iteratorCol *colpars, void *userPointer); -int ffpinit(fitsfile *fptr, int *status); -int ffainit(fitsfile *fptr, int *status); -int ffbinit(fitsfile *fptr, int *status); -int ffchdu(fitsfile *fptr, int *status); -int ffwend(fitsfile *fptr, int *status); -int ffpdfl(fitsfile *fptr, int *status); -int ffuptf(fitsfile *fptr, int *status); - -int ffdblk(fitsfile *fptr, long nblocks, int *status); -int ffgext(fitsfile *fptr, int moveto, int *exttype, int *status); -int ffgtbc(fitsfile *fptr, LONGLONG *totalwidth, int *status); -int ffgtbp(fitsfile *fptr, char *name, char *value, int *status); -int ffiblk(fitsfile *fptr, long nblock, int headdata, int *status); -int ffshft(fitsfile *fptr, LONGLONG firstbyte, LONGLONG nbytes, LONGLONG nshift, - int *status); - - int ffgcprll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, int writemode, double *scale, double *zero, char *tform, - long *twidth, int *tcode, int *maxelem, LONGLONG *startpos, - LONGLONG *elemnum, long *incre, LONGLONG *repeat, LONGLONG *rowlen, - int *hdutype, LONGLONG *tnull, char *snull, int *status); - -int ffflushx(FITSfile *fptr); -int ffseek(FITSfile *fptr, LONGLONG position); -int ffread(FITSfile *fptr, long nbytes, void *buffer, - int *status); -int ffwrite(FITSfile *fptr, long nbytes, void *buffer, - int *status); -int fftrun(fitsfile *fptr, LONGLONG filesize, int *status); - -int ffpcluc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, int *status); - -int ffgcll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, int nultyp, char nulval, char *array, char *nularray, - int *anynul, int *status); -int ffgcls(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, int nultyp, char *nulval, - char **array, char *nularray, int *anynul, int *status); -int ffgcls2(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, int nultyp, char *nulval, - char **array, char *nularray, int *anynul, int *status); -int ffgclb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long elemincre, int nultyp, unsigned char nulval, - unsigned char *array, char *nularray, int *anynul, int *status); -int ffgclsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long elemincre, int nultyp, signed char nulval, - signed char *array, char *nularray, int *anynul, int *status); -int ffgclui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long elemincre, int nultyp, unsigned short nulval, - unsigned short *array, char *nularray, int *anynul, int *status); -int ffgcli(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long elemincre, int nultyp, short nulval, - short *array, char *nularray, int *anynul, int *status); -int ffgcluj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long elemincre, int nultyp, unsigned long nulval, - unsigned long *array, char *nularray, int *anynul, int *status); -int ffgcljj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long elemincre, int nultyp, LONGLONG nulval, - LONGLONG *array, char *nularray, int *anynul, int *status); -int ffgclj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long elemincre, int nultyp, long nulval, long *array, - char *nularray, int *anynul, int *status); -int ffgcluk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long elemincre, int nultyp, unsigned int nulval, - unsigned int *array, char *nularray, int *anynul, int *status); -int ffgclk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long elemincre, int nultyp, int nulval, int *array, - char *nularray, int *anynul, int *status); -int ffgcle(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long elemincre, int nultyp, float nulval, float *array, - char *nularray, int *anynul, int *status); -int ffgcld(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, - LONGLONG nelem, long elemincre, int nultyp, double nulval, - double *array, char *nularray, int *anynul, int *status); - -int ffpi1b(fitsfile *fptr, long nelem, long incre, unsigned char *buffer, - int *status); -int ffpi2b(fitsfile *fptr, long nelem, long incre, short *buffer, int *status); -int ffpi4b(fitsfile *fptr, long nelem, long incre, INT32BIT *buffer, - int *status); -int ffpi8b(fitsfile *fptr, long nelem, long incre, long *buffer, int *status); -int ffpr4b(fitsfile *fptr, long nelem, long incre, float *buffer, int *status); -int ffpr8b(fitsfile *fptr, long nelem, long incre, double *buffer, int *status); - -int ffgi1b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, - unsigned char *buffer, int *status); -int ffgi2b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, short *buffer, - int *status); -int ffgi4b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, INT32BIT *buffer, - int *status); -int ffgi8b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, long *buffer, - int *status); -int ffgr4b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, float *buffer, - int *status); -int ffgr8b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, double *buffer, - int *status); - -int ffcins(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, LONGLONG nbytes, - LONGLONG bytepos, int *status); -int ffcdel(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, LONGLONG nbytes, - LONGLONG bytepos, int *status); -int ffkshf(fitsfile *fptr, int firstcol, int tfields, int nshift, int *status); - -int fffi1i1(unsigned char *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char tnull, unsigned char nullval, char - *nullarray, int *anynull, unsigned char *output, int *status); -int fffi2i1(short *input, long ntodo, double scale, double zero, - int nullcheck, short tnull, unsigned char nullval, char *nullarray, - int *anynull, unsigned char *output, int *status); -int fffi4i1(INT32BIT *input, long ntodo, double scale, double zero, - int nullcheck, INT32BIT tnull, unsigned char nullval, char *nullarray, - int *anynull, unsigned char *output, int *status); -int fffi8i1(LONGLONG *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG tnull, unsigned char nullval, char *nullarray, - int *anynull, unsigned char *output, int *status); -int fffr4i1(float *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char nullval, char *nullarray, - int *anynull, unsigned char *output, int *status); -int fffr8i1(double *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char nullval, char *nullarray, - int *anynull, unsigned char *output, int *status); -int fffstri1(char *input, long ntodo, double scale, double zero, - long twidth, double power, int nullcheck, char *snull, - unsigned char nullval, char *nullarray, int *anynull, - unsigned char *output, int *status); - -int fffi1s1(unsigned char *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char tnull, signed char nullval, char - *nullarray, int *anynull, signed char *output, int *status); -int fffi2s1(short *input, long ntodo, double scale, double zero, - int nullcheck, short tnull, signed char nullval, char *nullarray, - int *anynull, signed char *output, int *status); -int fffi4s1(INT32BIT *input, long ntodo, double scale, double zero, - int nullcheck, INT32BIT tnull, signed char nullval, char *nullarray, - int *anynull, signed char *output, int *status); -int fffi8s1(LONGLONG *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG tnull, signed char nullval, char *nullarray, - int *anynull, signed char *output, int *status); -int fffr4s1(float *input, long ntodo, double scale, double zero, - int nullcheck, signed char nullval, char *nullarray, - int *anynull, signed char *output, int *status); -int fffr8s1(double *input, long ntodo, double scale, double zero, - int nullcheck, signed char nullval, char *nullarray, - int *anynull, signed char *output, int *status); -int fffstrs1(char *input, long ntodo, double scale, double zero, - long twidth, double power, int nullcheck, char *snull, - signed char nullval, char *nullarray, int *anynull, - signed char *output, int *status); - -int fffi1u2(unsigned char *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char tnull, unsigned short nullval, - char *nullarray, - int *anynull, unsigned short *output, int *status); -int fffi2u2(short *input, long ntodo, double scale, double zero, - int nullcheck, short tnull, unsigned short nullval, char *nullarray, - int *anynull, unsigned short *output, int *status); -int fffi4u2(INT32BIT *input, long ntodo, double scale, double zero, - int nullcheck, INT32BIT tnull, unsigned short nullval, char *nullarray, - int *anynull, unsigned short *output, int *status); -int fffi8u2(LONGLONG *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG tnull, unsigned short nullval, char *nullarray, - int *anynull, unsigned short *output, int *status); -int fffr4u2(float *input, long ntodo, double scale, double zero, - int nullcheck, unsigned short nullval, char *nullarray, - int *anynull, unsigned short *output, int *status); -int fffr8u2(double *input, long ntodo, double scale, double zero, - int nullcheck, unsigned short nullval, char *nullarray, - int *anynull, unsigned short *output, int *status); -int fffstru2(char *input, long ntodo, double scale, double zero, - long twidth, double power, int nullcheck, char *snull, - unsigned short nullval, char *nullarray, int *anynull, - unsigned short *output, int *status); - -int fffi1i2(unsigned char *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char tnull, short nullval, char *nullarray, - int *anynull, short *output, int *status); -int fffi2i2(short *input, long ntodo, double scale, double zero, - int nullcheck, short tnull, short nullval, char *nullarray, - int *anynull, short *output, int *status); -int fffi4i2(INT32BIT *input, long ntodo, double scale, double zero, - int nullcheck, INT32BIT tnull, short nullval, char *nullarray, - int *anynull, short *output, int *status); -int fffi8i2(LONGLONG *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG tnull, short nullval, char *nullarray, - int *anynull, short *output, int *status); -int fffr4i2(float *input, long ntodo, double scale, double zero, - int nullcheck, short nullval, char *nullarray, - int *anynull, short *output, int *status); -int fffr8i2(double *input, long ntodo, double scale, double zero, - int nullcheck, short nullval, char *nullarray, - int *anynull, short *output, int *status); -int fffstri2(char *input, long ntodo, double scale, double zero, - long twidth, double power, int nullcheck, char *snull, - short nullval, char *nullarray, int *anynull, short *output, - int *status); - -int fffi1u4(unsigned char *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char tnull, unsigned long nullval, - char *nullarray, - int *anynull, unsigned long *output, int *status); -int fffi2u4(short *input, long ntodo, double scale, double zero, - int nullcheck, short tnull, unsigned long nullval, char *nullarray, - int *anynull, unsigned long *output, int *status); -int fffi4u4(INT32BIT *input, long ntodo, double scale, double zero, - int nullcheck, INT32BIT tnull, unsigned long nullval, char *nullarray, - int *anynull, unsigned long *output, int *status); -int fffi8u4(LONGLONG *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG tnull, unsigned long nullval, char *nullarray, - int *anynull, unsigned long *output, int *status); -int fffr4u4(float *input, long ntodo, double scale, double zero, - int nullcheck, unsigned long nullval, char *nullarray, - int *anynull, unsigned long *output, int *status); -int fffr8u4(double *input, long ntodo, double scale, double zero, - int nullcheck, unsigned long nullval, char *nullarray, - int *anynull, unsigned long *output, int *status); -int fffstru4(char *input, long ntodo, double scale, double zero, - long twidth, double power, int nullcheck, char *snull, - unsigned long nullval, char *nullarray, int *anynull, - unsigned long *output, int *status); - -int fffi1i4(unsigned char *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char tnull, long nullval, char *nullarray, - int *anynull, long *output, int *status); -int fffi2i4(short *input, long ntodo, double scale, double zero, - int nullcheck, short tnull, long nullval, char *nullarray, - int *anynull, long *output, int *status); -int fffi4i4(INT32BIT *input, long ntodo, double scale, double zero, - int nullcheck, INT32BIT tnull, long nullval, char *nullarray, - int *anynull, long *output, int *status); -int fffi8i4(LONGLONG *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG tnull, long nullval, char *nullarray, - int *anynull, long *output, int *status); -int fffr4i4(float *input, long ntodo, double scale, double zero, - int nullcheck, long nullval, char *nullarray, - int *anynull, long *output, int *status); -int fffr8i4(double *input, long ntodo, double scale, double zero, - int nullcheck, long nullval, char *nullarray, - int *anynull, long *output, int *status); -int fffstri4(char *input, long ntodo, double scale, double zero, - long twidth, double power, int nullcheck, char *snull, - long nullval, char *nullarray, int *anynull, long *output, - int *status); - -int fffi1int(unsigned char *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char tnull, int nullval, char *nullarray, - int *anynull, int *output, int *status); -int fffi2int(short *input, long ntodo, double scale, double zero, - int nullcheck, short tnull, int nullval, char *nullarray, - int *anynull, int *output, int *status); -int fffi4int(INT32BIT *input, long ntodo, double scale, double zero, - int nullcheck, INT32BIT tnull, int nullval, char *nullarray, - int *anynull, int *output, int *status); -int fffi8int(LONGLONG *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG tnull, int nullval, char *nullarray, - int *anynull, int *output, int *status); -int fffr4int(float *input, long ntodo, double scale, double zero, - int nullcheck, int nullval, char *nullarray, - int *anynull, int *output, int *status); -int fffr8int(double *input, long ntodo, double scale, double zero, - int nullcheck, int nullval, char *nullarray, - int *anynull, int *output, int *status); -int fffstrint(char *input, long ntodo, double scale, double zero, - long twidth, double power, int nullcheck, char *snull, - int nullval, char *nullarray, int *anynull, int *output, - int *status); - -int fffi1uint(unsigned char *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char tnull, unsigned int nullval, - char *nullarray, int *anynull, unsigned int *output, int *status); -int fffi2uint(short *input, long ntodo, double scale, double zero, - int nullcheck, short tnull, unsigned int nullval, char *nullarray, - int *anynull, unsigned int *output, int *status); -int fffi4uint(INT32BIT *input, long ntodo, double scale, double zero, - int nullcheck, INT32BIT tnull, unsigned int nullval, char *nullarray, - int *anynull, unsigned int *output, int *status); -int fffi8uint(LONGLONG *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG tnull, unsigned int nullval, char *nullarray, - int *anynull, unsigned int *output, int *status); -int fffr4uint(float *input, long ntodo, double scale, double zero, - int nullcheck, unsigned int nullval, char *nullarray, - int *anynull, unsigned int *output, int *status); -int fffr8uint(double *input, long ntodo, double scale, double zero, - int nullcheck, unsigned int nullval, char *nullarray, - int *anynull, unsigned int *output, int *status); -int fffstruint(char *input, long ntodo, double scale, double zero, - long twidth, double power, int nullcheck, char *snull, - unsigned int nullval, char *nullarray, int *anynull, - unsigned int *output, int *status); - -int fffi1i8(unsigned char *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char tnull, LONGLONG nullval, - char *nullarray, int *anynull, LONGLONG *output, int *status); -int fffi2i8(short *input, long ntodo, double scale, double zero, - int nullcheck, short tnull, LONGLONG nullval, char *nullarray, - int *anynull, LONGLONG *output, int *status); -int fffi4i8(INT32BIT *input, long ntodo, double scale, double zero, - int nullcheck, INT32BIT tnull, LONGLONG nullval, char *nullarray, - int *anynull, LONGLONG *output, int *status); -int fffi8i8(LONGLONG *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG tnull, LONGLONG nullval, char *nullarray, - int *anynull, LONGLONG *output, int *status); -int fffr4i8(float *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG nullval, char *nullarray, - int *anynull, LONGLONG *output, int *status); -int fffr8i8(double *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG nullval, char *nullarray, - int *anynull, LONGLONG *output, int *status); -int fffstri8(char *input, long ntodo, double scale, double zero, - long twidth, double power, int nullcheck, char *snull, - LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, - int *status); - -int fffi1r4(unsigned char *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char tnull, float nullval, char *nullarray, - int *anynull, float *output, int *status); -int fffi2r4(short *input, long ntodo, double scale, double zero, - int nullcheck, short tnull, float nullval, char *nullarray, - int *anynull, float *output, int *status); -int fffi4r4(INT32BIT *input, long ntodo, double scale, double zero, - int nullcheck, INT32BIT tnull, float nullval, char *nullarray, - int *anynull, float *output, int *status); -int fffi8r4(LONGLONG *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG tnull, float nullval, char *nullarray, - int *anynull, float *output, int *status); -int fffr4r4(float *input, long ntodo, double scale, double zero, - int nullcheck, float nullval, char *nullarray, - int *anynull, float *output, int *status); -int fffr8r4(double *input, long ntodo, double scale, double zero, - int nullcheck, float nullval, char *nullarray, - int *anynull, float *output, int *status); -int fffstrr4(char *input, long ntodo, double scale, double zero, - long twidth, double power, int nullcheck, char *snull, - float nullval, char *nullarray, int *anynull, float *output, - int *status); - -int fffi1r8(unsigned char *input, long ntodo, double scale, double zero, - int nullcheck, unsigned char tnull, double nullval, char *nullarray, - int *anynull, double *output, int *status); -int fffi2r8(short *input, long ntodo, double scale, double zero, - int nullcheck, short tnull, double nullval, char *nullarray, - int *anynull, double *output, int *status); -int fffi4r8(INT32BIT *input, long ntodo, double scale, double zero, - int nullcheck, INT32BIT tnull, double nullval, char *nullarray, - int *anynull, double *output, int *status); -int fffi8r8(LONGLONG *input, long ntodo, double scale, double zero, - int nullcheck, LONGLONG tnull, double nullval, char *nullarray, - int *anynull, double *output, int *status); -int fffr4r8(float *input, long ntodo, double scale, double zero, - int nullcheck, double nullval, char *nullarray, - int *anynull, double *output, int *status); -int fffr8r8(double *input, long ntodo, double scale, double zero, - int nullcheck, double nullval, char *nullarray, - int *anynull, double *output, int *status); -int fffstrr8(char *input, long ntodo, double scale, double zero, - long twidth, double power, int nullcheck, char *snull, - double nullval, char *nullarray, int *anynull, double *output, - int *status); - -int ffi1fi1(unsigned char *array, long ntodo, double scale, double zero, - unsigned char *buffer, int *status); -int ffs1fi1(signed char *array, long ntodo, double scale, double zero, - unsigned char *buffer, int *status); -int ffu2fi1(unsigned short *array, long ntodo, double scale, double zero, - unsigned char *buffer, int *status); -int ffi2fi1(short *array, long ntodo, double scale, double zero, - unsigned char *buffer, int *status); -int ffu4fi1(unsigned long *array, long ntodo, double scale, double zero, - unsigned char *buffer, int *status); -int ffi4fi1(long *array, long ntodo, double scale, double zero, - unsigned char *buffer, int *status); -int ffi8fi1(LONGLONG *array, long ntodo, double scale, double zero, - unsigned char *buffer, int *status); -int ffuintfi1(unsigned int *array, long ntodo, double scale, double zero, - unsigned char *buffer, int *status); -int ffintfi1(int *array, long ntodo, double scale, double zero, - unsigned char *buffer, int *status); -int ffr4fi1(float *array, long ntodo, double scale, double zero, - unsigned char *buffer, int *status); -int ffr8fi1(double *array, long ntodo, double scale, double zero, - unsigned char *buffer, int *status); - -int ffi1fi2(unsigned char *array, long ntodo, double scale, double zero, - short *buffer, int *status); -int ffs1fi2(signed char *array, long ntodo, double scale, double zero, - short *buffer, int *status); -int ffu2fi2(unsigned short *array, long ntodo, double scale, double zero, - short *buffer, int *status); -int ffi2fi2(short *array, long ntodo, double scale, double zero, - short *buffer, int *status); -int ffu4fi2(unsigned long *array, long ntodo, double scale, double zero, - short *buffer, int *status); -int ffi4fi2(long *array, long ntodo, double scale, double zero, - short *buffer, int *status); -int ffi8fi2(LONGLONG *array, long ntodo, double scale, double zero, - short *buffer, int *status); -int ffuintfi2(unsigned int *array, long ntodo, double scale, double zero, - short *buffer, int *status); -int ffintfi2(int *array, long ntodo, double scale, double zero, - short *buffer, int *status); -int ffr4fi2(float *array, long ntodo, double scale, double zero, - short *buffer, int *status); -int ffr8fi2(double *array, long ntodo, double scale, double zero, - short *buffer, int *status); - -int ffi1fi4(unsigned char *array, long ntodo, double scale, double zero, - INT32BIT *buffer, int *status); -int ffs1fi4(signed char *array, long ntodo, double scale, double zero, - INT32BIT *buffer, int *status); -int ffu2fi4(unsigned short *array, long ntodo, double scale, double zero, - INT32BIT *buffer, int *status); -int ffi2fi4(short *array, long ntodo, double scale, double zero, - INT32BIT *buffer, int *status); -int ffu4fi4(unsigned long *array, long ntodo, double scale, double zero, - INT32BIT *buffer, int *status); -int ffi4fi4(long *array, long ntodo, double scale, double zero, - INT32BIT *buffer, int *status); -int ffi8fi4(LONGLONG *array, long ntodo, double scale, double zero, - INT32BIT *buffer, int *status); -int ffuintfi4(unsigned int *array, long ntodo, double scale, double zero, - INT32BIT *buffer, int *status); -int ffintfi4(int *array, long ntodo, double scale, double zero, - INT32BIT *buffer, int *status); -int ffr4fi4(float *array, long ntodo, double scale, double zero, - INT32BIT *buffer, int *status); -int ffr8fi4(double *array, long ntodo, double scale, double zero, - INT32BIT *buffer, int *status); - -int fflongfi8(long *array, long ntodo, double scale, double zero, - LONGLONG *buffer, int *status); -int ffi8fi8(LONGLONG *array, long ntodo, double scale, double zero, - LONGLONG *buffer, int *status); -int ffi2fi8(short *array, long ntodo, double scale, double zero, - LONGLONG *buffer, int *status); -int ffi1fi8(unsigned char *array, long ntodo, double scale, double zero, - LONGLONG *buffer, int *status); -int ffs1fi8(signed char *array, long ntodo, double scale, double zero, - LONGLONG *buffer, int *status); -int ffr4fi8(float *array, long ntodo, double scale, double zero, - LONGLONG *buffer, int *status); -int ffr8fi8(double *array, long ntodo, double scale, double zero, - LONGLONG *buffer, int *status); -int ffintfi8(int *array, long ntodo, double scale, double zero, - LONGLONG *buffer, int *status); -int ffu2fi8(unsigned short *array, long ntodo, double scale, double zero, - LONGLONG *buffer, int *status); -int ffu4fi8(unsigned long *array, long ntodo, double scale, double zero, - LONGLONG *buffer, int *status); -int ffuintfi8(unsigned int *array, long ntodo, double scale, double zero, - LONGLONG *buffer, int *status); - -int ffi1fr4(unsigned char *array, long ntodo, double scale, double zero, - float *buffer, int *status); -int ffs1fr4(signed char *array, long ntodo, double scale, double zero, - float *buffer, int *status); -int ffu2fr4(unsigned short *array, long ntodo, double scale, double zero, - float *buffer, int *status); -int ffi2fr4(short *array, long ntodo, double scale, double zero, - float *buffer, int *status); -int ffu4fr4(unsigned long *array, long ntodo, double scale, double zero, - float *buffer, int *status); -int ffi4fr4(long *array, long ntodo, double scale, double zero, - float *buffer, int *status); -int ffi8fr4(LONGLONG *array, long ntodo, double scale, double zero, - float *buffer, int *status); -int ffuintfr4(unsigned int *array, long ntodo, double scale, double zero, - float *buffer, int *status); -int ffintfr4(int *array, long ntodo, double scale, double zero, - float *buffer, int *status); -int ffr4fr4(float *array, long ntodo, double scale, double zero, - float *buffer, int *status); -int ffr8fr4(double *array, long ntodo, double scale, double zero, - float *buffer, int *status); - -int ffi1fr8(unsigned char *array, long ntodo, double scale, double zero, - double *buffer, int *status); -int ffs1fr8(signed char *array, long ntodo, double scale, double zero, - double *buffer, int *status); -int ffu2fr8(unsigned short *array, long ntodo, double scale, double zero, - double *buffer, int *status); -int ffi2fr8(short *array, long ntodo, double scale, double zero, - double *buffer, int *status); -int ffu4fr8(unsigned long *array, long ntodo, double scale, double zero, - double *buffer, int *status); -int ffi4fr8(long *array, long ntodo, double scale, double zero, - double *buffer, int *status); -int ffi8fr8(LONGLONG *array, long ntodo, double scale, double zero, - double *buffer, int *status); -int ffuintfr8(unsigned int *array, long ntodo, double scale, double zero, - double *buffer, int *status); -int ffintfr8(int *array, long ntodo, double scale, double zero, - double *buffer, int *status); -int ffr4fr8(float *array, long ntodo, double scale, double zero, - double *buffer, int *status); -int ffr8fr8(double *array, long ntodo, double scale, double zero, - double *buffer, int *status); - -int ffi1fstr(unsigned char *input, long ntodo, double scale, double zero, - char *cform, long twidth, char *output, int *status); -int ffs1fstr(signed char *input, long ntodo, double scale, double zero, - char *cform, long twidth, char *output, int *status); -int ffu2fstr(unsigned short *input, long ntodo, double scale, double zero, - char *cform, long twidth, char *output, int *status); -int ffi2fstr(short *input, long ntodo, double scale, double zero, - char *cform, long twidth, char *output, int *status); -int ffu4fstr(unsigned long *input, long ntodo, double scale, double zero, - char *cform, long twidth, char *output, int *status); -int ffi4fstr(long *input, long ntodo, double scale, double zero, - char *cform, long twidth, char *output, int *status); -int ffi8fstr(LONGLONG *input, long ntodo, double scale, double zero, - char *cform, long twidth, char *output, int *status); -int ffintfstr(int *input, long ntodo, double scale, double zero, - char *cform, long twidth, char *output, int *status); -int ffuintfstr(unsigned int *input, long ntodo, double scale, double zero, - char *cform, long twidth, char *output, int *status); -int ffr4fstr(float *input, long ntodo, double scale, double zero, - char *cform, long twidth, char *output, int *status); -int ffr8fstr(double *input, long ntodo, double scale, double zero, - char *cform, long twidth, char *output, int *status); - -/* the following 4 routines are VMS macros used on VAX or Alpha VMS */ -void ieevpd(double *inarray, double *outarray, long *nvals); -void ieevud(double *inarray, double *outarray, long *nvals); -void ieevpr(float *inarray, float *outarray, long *nvals); -void ieevur(float *inarray, float *outarray, long *nvals); - -/* routines related to the lexical parser */ -int ffselect_table(fitsfile **fptr, char *outfile, char *expr, int *status); -int ffiprs( fitsfile *fptr, int compressed, char *expr, int maxdim, - int *datatype, long *nelem, int *naxis, long *naxes, - int *status ); -void ffcprs( void ); -int ffcvtn( int inputType, void *input, char *undef, long ntodo, - int outputType, void *nulval, void *output, - int *anynull, int *status ); -int parse_data( long totalrows, long offset, long firstrow, - long nrows, int nCols, iteratorCol *colData, - void *userPtr ); -int uncompress_hkdata( fitsfile *fptr, long ntimes, - double *times, int *status ); -int ffffrw_work( long totalrows, long offset, long firstrow, - long nrows, int nCols, iteratorCol *colData, - void *userPtr ); - -int fits_translate_pixkeyword(char *inrec, char *outrec,char *patterns[][2], - int npat, int naxis, int *colnum, int *pat_num, int *i, - int *j, int *n, int *m, int *l, int *status); - -/* image compression routines */ -int fits_write_compressed_img(fitsfile *fptr, - int datatype, long *fpixel, long *lpixel, - int nullcheck, void *array, void *nulval, - int *status); -int fits_write_compressed_pixels(fitsfile *fptr, - int datatype, LONGLONG fpixel, LONGLONG npixels, - int nullcheck, void *array, void *nulval, - int *status); -int fits_write_compressed_img_plane(fitsfile *fptr, int datatype, - int bytesperpixel, long nplane, long *firstcoord, long *lastcoord, - long *naxes, int nullcheck, - void *array, void *nullval, long *nread, int *status); - -int imcomp_init_table(fitsfile *outfptr, - int bitpix, int naxis,long *naxes, int writebitpix, int *status); -int imcomp_calc_max_elem (int comptype, int nx, int zbitpix, int blocksize); -int imcomp_copy_imheader(fitsfile *infptr, fitsfile *outfptr, - int *status); -int imcomp_copy_img2comp(fitsfile *infptr, fitsfile *outfptr, int *status); -int imcomp_copy_comp2img(fitsfile *infptr, fitsfile *outfptr, - int norec, int *status); -int imcomp_copy_prime2img(fitsfile *infptr, fitsfile *outfptr, int *status); -int imcomp_compress_image (fitsfile *infptr, fitsfile *outfptr, - int *status); -int imcomp_compress_tile (fitsfile *outfptr, long row, - int datatype, void *tiledata, long tilelen, long nx, long ny, - int nullcheck, void *nullval, int *status); -int imcomp_nullscale(int *idata, long tilelen, int nullflagval, int nullval, - double scale, double zero, int * status); -int imcomp_nullvalues(int *idata, long tilelen, int nullflagval, int nullval, - int * status); -int imcomp_scalevalues(int *idata, long tilelen, double scale, double zero, - int * status); -int imcomp_nullscalefloats(float *fdata, long tilelen, int *idata, - double scale, double zero, int nullcheck, float nullflagval, int nullval, - int *status); -int imcomp_nullfloats(float *fdata, long tilelen, int *idata, int nullcheck, - float nullflagval, int nullval, int *status); -int imcomp_nullscaledoubles(double *fdata, long tilelen, int *idata, - double scale, double zero, int nullcheck, double nullflagval, int nullval, - int *status); -int imcomp_nulldoubles(double *fdata, long tilelen, int *idata, int nullcheck, - double nullflagval, int nullval, int *status); - - -/* image decompression routines */ -int fits_read_compressed_img(fitsfile *fptr, - int datatype, LONGLONG *fpixel,LONGLONG *lpixel,long *inc, - int nullcheck, void *nulval, void *array, char *nullarray, - int *anynul, int *status); -int fits_read_compressed_pixels(fitsfile *fptr, - int datatype, LONGLONG fpixel, LONGLONG npixels, - int nullcheck, void *nulval, void *array, char *nullarray, - int *anynul, int *status); -int fits_read_compressed_img_plane(fitsfile *fptr, int datatype, - int bytesperpixel, long nplane, LONGLONG *firstcoord, LONGLONG *lastcoord, - long *inc, long *naxes, int nullcheck, void *nullval, - void *array, char *nullarray, int *anynul, long *nread, int *status); - -int imcomp_get_compressed_image_par(fitsfile *infptr, int *status); -int imcomp_decompress_tile (fitsfile *infptr, - int nrow, int tilesize, int datatype, int nullcheck, - void *nulval, void *buffer, char *bnullarray, int *anynul, - int *status); -int imcomp_copy_overlap (char *tile, int pixlen, int ndim, - long *tfpixel, long *tlpixel, char *bnullarray, char *image, - long *fpixel, long *lpixel, long *inc, int nullcheck, char *nullarray, - int *status); -int imcomp_test_overlap (int ndim, long *tfpixel, long *tlpixel, - long *fpixel, long *lpixel, long *inc, int *status); -int imcomp_merge_overlap (char *tile, int pixlen, int ndim, - long *tfpixel, long *tlpixel, char *bnullarray, char *image, - long *fpixel, long *lpixel, int nullcheck, int *status); -int imcomp_decompress_img(fitsfile *infptr, fitsfile *outfptr, int datatype, - int *status); -int fits_quantize_float (long row, float fdata[], long nx, long ny, int nullcheck, - float in_null_value, float quantize_level, - int dither_method, int idata[], double *bscale, double *bzero, - int *iminval, int *imaxval); -int fits_quantize_double (long row, double fdata[], long nx, long ny, int nullcheck, - double in_null_value, float quantize_level, - int dither_method, int idata[], double *bscale, double *bzero, - int *iminval, int *imaxval); -int fits_rcomp(int a[], int nx, unsigned char *c, int clen,int nblock); -int fits_rcomp_short(short a[], int nx, unsigned char *c, int clen,int nblock); -int fits_rcomp_byte(signed char a[], int nx, unsigned char *c, int clen,int nblock); -int fits_rdecomp (unsigned char *c, int clen, unsigned int array[], int nx, - int nblock); -int fits_rdecomp_short (unsigned char *c, int clen, unsigned short array[], int nx, - int nblock); -int fits_rdecomp_byte (unsigned char *c, int clen, unsigned char array[], int nx, - int nblock); -int pl_p2li (int *pxsrc, int xs, short *lldst, int npix); -int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix); -int fits_init_randoms(void); -int fits_unset_compression_param( fitsfile *fptr, int *status); -int fits_unset_compression_request( fitsfile *fptr, int *status); -int fitsio_init_lock(void); - -/* general driver routines */ - -int urltype2driver(char *urltype, int *driver); - -int fits_register_driver( char *prefix, - int (*init)(void), - int (*fitsshutdown)(void), - int (*setoptions)(int option), - int (*getoptions)(int *options), - int (*getversion)(int *version), - int (*checkfile) (char *urltype, char *infile, char *outfile), - int (*fitsopen)(char *filename, int rwmode, int *driverhandle), - int (*fitscreate)(char *filename, int *driverhandle), - int (*fitstruncate)(int driverhandle, LONGLONG filesize), - int (*fitsclose)(int driverhandle), - int (*fremove)(char *filename), - int (*size)(int driverhandle, LONGLONG *sizex), - int (*flush)(int driverhandle), - int (*seek)(int driverhandle, LONGLONG offset), - int (*fitsread) (int driverhandle, void *buffer, long nbytes), - int (*fitswrite)(int driverhandle, void *buffer, long nbytes)); - -/* file driver I/O routines */ - -int file_init(void); -int file_setoptions(int options); -int file_getoptions(int *options); -int file_getversion(int *version); -int file_shutdown(void); -int file_checkfile(char *urltype, char *infile, char *outfile); -int file_open(char *filename, int rwmode, int *driverhandle); -int file_compress_open(char *filename, int rwmode, int *hdl); -int file_openfile(char *filename, int rwmode, FILE **diskfile); -int file_create(char *filename, int *driverhandle); -int file_truncate(int driverhandle, LONGLONG filesize); -int file_size(int driverhandle, LONGLONG *filesize); -int file_close(int driverhandle); -int file_remove(char *filename); -int file_flush(int driverhandle); -int file_seek(int driverhandle, LONGLONG offset); -int file_read (int driverhandle, void *buffer, long nbytes); -int file_write(int driverhandle, void *buffer, long nbytes); -int file_is_compressed(char *filename); - -/* stream driver I/O routines */ - -int stream_open(char *filename, int rwmode, int *driverhandle); -int stream_create(char *filename, int *driverhandle); -int stream_size(int driverhandle, LONGLONG *filesize); -int stream_close(int driverhandle); -int stream_flush(int driverhandle); -int stream_seek(int driverhandle, LONGLONG offset); -int stream_read (int driverhandle, void *buffer, long nbytes); -int stream_write(int driverhandle, void *buffer, long nbytes); - -/* memory driver I/O routines */ - -int mem_init(void); -int mem_setoptions(int options); -int mem_getoptions(int *options); -int mem_getversion(int *version); -int mem_shutdown(void); -int mem_create(char *filename, int *handle); -int mem_create_comp(char *filename, int *handle); -int mem_openmem(void **buffptr, size_t *buffsize, size_t deltasize, - void *(*memrealloc)(void *p, size_t newsize), int *handle); -int mem_createmem(size_t memsize, int *handle); -int stdin_checkfile(char *urltype, char *infile, char *outfile); -int stdin_open(char *filename, int rwmode, int *handle); -int stdin2mem(int hd); -int stdin2file(int hd); -int stdout_close(int handle); -int mem_compress_openrw(char *filename, int rwmode, int *hdl); -int mem_compress_open(char *filename, int rwmode, int *hdl); -int mem_compress_stdin_open(char *filename, int rwmode, int *hdl); -int mem_iraf_open(char *filename, int rwmode, int *hdl); -int mem_rawfile_open(char *filename, int rwmode, int *hdl); -int mem_size(int handle, LONGLONG *filesize); -int mem_truncate(int handle, LONGLONG filesize); -int mem_close_free(int handle); -int mem_close_keep(int handle); -int mem_close_comp(int handle); -int mem_seek(int handle, LONGLONG offset); -int mem_read(int hdl, void *buffer, long nbytes); -int mem_write(int hdl, void *buffer, long nbytes); -int mem_uncompress2mem(char *filename, FILE *diskfile, int hdl); - -int iraf2mem(char *filename, char **buffptr, size_t *buffsize, - size_t *filesize, int *status); - -/* root driver I/O routines */ - -int root_init(void); -int root_setoptions(int options); -int root_getoptions(int *options); -int root_getversion(int *version); -int root_shutdown(void); -int root_open(char *filename, int rwmode, int *driverhandle); -int root_create(char *filename, int *driverhandle); -int root_close(int driverhandle); -int root_flush(int driverhandle); -int root_seek(int driverhandle, LONGLONG offset); -int root_read (int driverhandle, void *buffer, long nbytes); -int root_write(int driverhandle, void *buffer, long nbytes); -int root_size(int handle, LONGLONG *filesize); - -/* http driver I/O routines */ - -int http_checkfile(char *urltype, char *infile, char *outfile); -int http_open(char *filename, int rwmode, int *driverhandle); -int http_file_open(char *filename, int rwmode, int *driverhandle); -int http_compress_open(char *filename, int rwmode, int *driverhandle); - -/* ftp driver I/O routines */ - -int ftp_checkfile(char *urltype, char *infile, char *outfile); -int ftp_open(char *filename, int rwmode, int *driverhandle); -int ftp_file_open(char *filename, int rwmode, int *driverhandle); -int ftp_compress_open(char *filename, int rwmode, int *driverhandle); - -int uncompress2mem(char *filename, FILE *diskfile, - char **buffptr, size_t *buffsize, - void *(*mem_realloc)(void *p, size_t newsize), - size_t *filesize, int *status); - -int uncompress2mem_from_mem( - char *inmemptr, - size_t inmemsize, - char **buffptr, - size_t *buffsize, - void *(*mem_realloc)(void *p, size_t newsize), - size_t *filesize, - int *status); - -int uncompress2file(char *filename, - FILE *indiskfile, - FILE *outdiskfile, - int *status); - -int compress2mem_from_mem( - char *inmemptr, - size_t inmemsize, - char **buffptr, - size_t *buffsize, - void *(*mem_realloc)(void *p, size_t newsize), - size_t *filesize, - int *status); - -int compress2file_from_mem( - char *inmemptr, - size_t inmemsize, - FILE *outdiskfile, - size_t *filesize, /* O - size of file, in bytes */ - int *status); - - -#ifdef HAVE_GSIFTP -/* prototypes for gsiftp driver I/O routines */ -#include "drvrgsiftp.h" -#endif - -#ifdef HAVE_SHMEM_SERVICES -/* prototypes for shared memory driver I/O routines */ -#include "drvrsmem.h" -#endif - -/* A hack for nonunix machines, which lack strcasecmp and strncasecmp */ -/* these functions are in fitscore.c */ -int fits_strcasecmp (const char *s1, const char *s2 ); -int fits_strncasecmp(const char *s1, const char *s2, size_t n); - -/* end of the entire "ifndef _FITSIO2_H" block */ -#endif diff --git a/src/external/OpenGR/3rdparty/cfitsio/fpack.c b/src/external/OpenGR/3rdparty/cfitsio/fpack.c deleted file mode 100644 index 3b0b44804..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/fpack.c +++ /dev/null @@ -1,410 +0,0 @@ -/* FPACK - * R. Seaman, NOAO, with a few enhancements by W. Pence, HEASARC - * - * Calls fits_img_compress in the CFITSIO library by W. Pence, HEASARC - */ - -#include -/* #include */ -#include "fitsio.h" -#include "fpack.h" - -/* ================================================================== */ -int main(int argc, char *argv[]) -{ - fpstate fpvar; - - if (argc <= 1) { fp_usage (); fp_hint (); exit (-1); } - - fp_init (&fpvar); - fp_get_param (argc, argv, &fpvar); - - if (fpvar.listonly) { - fp_list (argc, argv, fpvar); - - } else { - fp_preflight (argc, argv, FPACK, &fpvar); - fp_loop (argc, argv, FPACK, fpvar); - } - - exit (0); -} -/* ================================================================== */ -int fp_get_param (int argc, char *argv[], fpstate *fpptr) -{ - int gottype=0, gottile=0, wholetile=0, iarg, len, ndim, ii, doffset; - char tmp[SZ_STR], tile[SZ_STR]; - - if (fpptr->initialized != FP_INIT_MAGIC) { - fp_msg ("Error: internal initialization error\n"); exit (-1); - } - - tile[0] = 0; - - /* flags must come first and be separately specified - */ - for (iarg = 1; iarg < argc; iarg++) { - if ((argv[iarg][0] == '-' && strlen (argv[iarg]) == 2) || - !strncmp(argv[iarg], "-q", 2) || !strncmp(argv[iarg], "-qz", 3) || - !strncmp(argv[iarg], "-g1", 3) || !strncmp(argv[iarg], "-g2", 3) || - !strncmp(argv[iarg], "-i2f", 4) || - !strncmp(argv[iarg], "-n3ratio", 8) || !strncmp(argv[iarg], "-n3min", 6) || - !strncmp(argv[iarg], "-tableonly", 10) || !strncmp(argv[iarg], "-table", 6) ) - { - - /* Rice is the default, so -r is superfluous */ - if ( argv[iarg][1] == 'r') { - fpptr->comptype = RICE_1; - if (gottype) { - fp_msg ("Error: multiple compression flags\n"); - fp_usage (); exit (-1); - } else - gottype++; - - } else if (argv[iarg][1] == 'p') { - fpptr->comptype = PLIO_1; - if (gottype) { - fp_msg ("Error: multiple compression flags\n"); - fp_usage (); exit (-1); - } else - gottype++; - - } else if (argv[iarg][1] == 'g') { - /* test for modifiers following the 'g' */ - if (argv[iarg][2] == '2') - fpptr->comptype = GZIP_2; - else - fpptr->comptype = GZIP_1; - - if (gottype) { - fp_msg ("Error: multiple compression flags\n"); - fp_usage (); exit (-1); - } else - gottype++; -/* - } else if (argv[iarg][1] == 'b') { - fpptr->comptype = BZIP2_1; - if (gottype) { - fp_msg ("Error: multiple compression flags\n"); - fp_usage (); exit (-1); - } else - gottype++; -*/ - } else if (argv[iarg][1] == 'h') { - fpptr->comptype = HCOMPRESS_1; - if (gottype) { - fp_msg ("Error: multiple compression flags\n"); - fp_usage (); exit (-1); - } else - gottype++; - - } else if (argv[iarg][1] == 'd') { - fpptr->comptype = NOCOMPRESS; - if (gottype) { - fp_msg ("Error: multiple compression flags\n"); - fp_usage (); exit (-1); - } else - gottype++; - - } else if (!strcmp(argv[iarg], "-i2f")) { - /* this means convert integer images to float, and then */ - /* quantize and compress the float image. This lossy */ - /* compression method may give higher compression than the */ - /* lossless compression method that is usually applied to */ - /* integer images. */ - - fpptr->int_to_float = 1; - - } else if (!strcmp(argv[iarg], "-n3ratio")) { - /* this is the minimum ratio between the MAD noise sigma */ - /* and the q parameter value in the case where the integer */ - /* image is quantized and compressed like a float image. */ - if (++iarg >= argc) { - fp_usage (); exit (-1); - } else { - fpptr->n3ratio = (float) atof (argv[iarg]); - } - } else if (!strcmp(argv[iarg], "-n3min")) { - /* this is the minimum MAD noise sigma in the case where the */ - /* integer image is quantized and compressed like a float image. */ - if (++iarg >= argc) { - fp_usage (); exit (-1); - } else { - fpptr->n3min = (float) atof (argv[iarg]); - } - } else if (argv[iarg][1] == 'q') { - /* test for modifiers following the 'q' */ - - if (argv[iarg][2] == 'z') { - fpptr->dither_method = 2; /* preserve zero pixels */ - - if (argv[iarg][3] == 't') { - fpptr->dither_offset = -1; /* dither based on tile checksum */ - - } else if (isdigit(argv[iarg][3])) { /* is a number appended to q? */ - doffset = atoi(argv[iarg]+3); - - if (doffset == 0) { - fpptr->no_dither = 1; /* don't dither the quantized values */ - } else if (doffset > 0 && doffset <= 10000) { - fpptr->dither_offset = doffset; - } else { - fp_msg ("Error: invalid q suffix\n"); - fp_usage (); exit (-1); - } - } - } else { - if (argv[iarg][2] == 't') { - fpptr->dither_offset = -1; /* dither based on tile checksum */ - - } else if (isdigit(argv[iarg][2])) { /* is a number appended to q? */ - doffset = atoi(argv[iarg]+2); - - if (doffset == 0) { - fpptr->no_dither = 1; /* don't dither the quantized values */ - } else if (doffset > 0 && doffset <= 10000) { - fpptr->dither_offset = doffset; - } else { - fp_msg ("Error: invalid q suffix\n"); - fp_usage (); exit (-1); - } - } - } - - if (++iarg >= argc) { - fp_usage (); exit (-1); - } else { - fpptr->quantize_level = (float) atof (argv[iarg]); - } - } else if (argv[iarg][1] == 'n') { - if (++iarg >= argc) { - fp_usage (); exit (-1); - } else { - fpptr->rescale_noise = (float) atof (argv[iarg]); - } - } else if (argv[iarg][1] == 's') { - if (++iarg >= argc) { - fp_usage (); exit (-1); - } else { - fpptr->scale = (float) atof (argv[iarg]); - } - } else if (!strcmp(argv[iarg], "-tableonly")) { - fpptr->do_tables = 1; - fpptr->do_images = 0; - fp_msg ("Note: -tableonly is intended for feasibility studies, not general use.\n"); - - } else if (!strcmp(argv[iarg], "-table")) { - fpptr->do_tables = 1; - fp_msg ("Note: -table is intended for feasibility studies, not general use.\n"); - - } else if (argv[iarg][1] == 't') { - if (gottile) { - fp_msg ("Error: multiple tile specifications\n"); - fp_usage (); exit (-1); - } else - gottile++; - - if (++iarg >= argc) { - fp_usage (); exit (-1); - } else - strncpy (tile, argv[iarg], SZ_STR); /* checked below */ - - } else if (argv[iarg][1] == 'v') { - fpptr->verbose = 1; - - } else if (argv[iarg][1] == 'w') { - wholetile++; - if (gottile) { - fp_msg ("Error: multiple tile specifications\n"); - fp_usage (); exit (-1); - } else - gottile++; - - } else if (argv[iarg][1] == 'F') { - fpptr->clobber++; /* overwrite existing file */ - - } else if (argv[iarg][1] == 'D') { - fpptr->delete_input++; - - } else if (argv[iarg][1] == 'Y') { - fpptr->do_not_prompt++; - - } else if (argv[iarg][1] == 'S') { - fpptr->to_stdout++; - - } else if (argv[iarg][1] == 'L') { - fpptr->listonly++; - - } else if (argv[iarg][1] == 'C') { - fpptr->do_checksums = 0; - - } else if (argv[iarg][1] == 'T') { - fpptr->test_all = 1; - - } else if (argv[iarg][1] == 'R') { - if (++iarg >= argc) { - fp_usage (); fp_hint (); exit (-1); - } else - strncpy (fpptr->outfile, argv[iarg], SZ_STR); - - } else if (argv[iarg][1] == 'H') { - fp_help (); exit (0); - - } else if (argv[iarg][1] == 'V') { - fp_version (); exit (0); - - } else { - fp_msg ("Error: unknown command line flag `"); - fp_msg (argv[iarg]); fp_msg ("'\n"); - fp_usage (); fp_hint (); exit (-1); - } - - } else - break; - } - - if (fpptr->scale != 0. && - fpptr->comptype != HCOMPRESS_1 && fpptr->test_all != 1) { - - fp_msg ("Error: `-s' requires `-h or -T'\n"); exit (-1); - } - - if (fpptr->quantize_level == 0) { - - if ((fpptr->comptype != GZIP_1) && (fpptr->comptype != GZIP_2)) { - fp_msg ("Error: `-q 0' only allowed with GZIP\n"); exit (-1); - } - - if (fpptr->int_to_float == 1) { - fp_msg ("Error: `-q 0' not allowed with -i2f\n"); exit (-1); - } - } - - if (wholetile) { - for (ndim=0; ndim < MAX_COMPRESS_DIM; ndim++) - fpptr->ntile[ndim] = (long) -1; - - } else if (gottile) { - len = strlen (tile); - for (ii=0, ndim=0; ii < len; ) { - if (! (isdigit (tile[ii]) || tile[ii] == ',')) { - fp_msg ("Error: `-t' requires comma separated tile dims, "); - fp_msg ("e.g., `-t 100,100'\n"); exit (-1); - } - - if (tile[ii] == ',') { ii++; continue; } - - fpptr->ntile[ndim] = atol (&tile[ii]); - for ( ; isdigit(tile[ii]); ii++); - - if (++ndim > MAX_COMPRESS_DIM) { - fp_msg ("Error: too many dimensions for `-t', max="); - sprintf (tmp, "%d\n", MAX_COMPRESS_DIM); fp_msg (tmp); - exit (-1); - } - } - } - - if (iarg >= argc) { - fp_msg ("Error: no FITS files to compress\n"); - fp_usage (); exit (-1); - } else - fpptr->firstfile = iarg; - - return(0); -} - -/* ================================================================== */ -int fp_usage (void) -{ -fp_msg ("usage: fpack "); -fp_msg ( -"[-r|-h|-g|-p] [-w|-t ] [-q ] [-s ] [-n ] -v \n"); -fp_msg ("more: [-T] [-R] [-F] [-D] [-Y] [-S] [-L] [-C] [-H] [-V] [-i2f]\n"); -return(0); -} - -/* ================================================================== */ -int fp_hint (void) -{ fp_msg (" `fpack -H' for help\n"); -return(0); -} - -/* ================================================================== */ -int fp_help (void) -{ -fp_msg ("fpack, a FITS image compression program. Version "); -fp_version (); -fp_usage (); -fp_msg ("\n"); -fp_msg ("NOTE: the compression parameters specified on the fpack command line may\n"); -fp_msg ("be over-ridden by compression directive keywords in the header of each HDU\n"); -fp_msg ("of the input file(s). See the fpack User's Guide for more details\n"); -fp_msg ("\n"); - -fp_msg ("Flags must be separate and appear before filenames:\n"); -fp_msg (" -r Rice compression [default], or\n"); -fp_msg (" -h Hcompress compression, or\n"); -fp_msg (" -g or -g1 GZIP_1 (per-tile) compression, or\n"); -fp_msg (" -g2 GZIP_2 (per-tile) compression (with byte shuffling), or\n"); -/* -fp_msg (" -b BZIP2 (per-tile) compression, or\n"); -*/ -fp_msg (" -p PLIO compression (only for positive 8 or 16-bit integer images).\n"); -fp_msg (" -d Tile the image without compression (debugging mode).\n"); - -fp_msg (" -w Compress the whole image as a single large tile.\n"); -fp_msg (" -t Comma separated list of tile dimensions [default is row by row].\n"); - -fp_msg (" -q Quantized level spacing when converting floating point images to\n"); -fp_msg (" scaled integers. (+value relative to sigma of background noise;\n"); -fp_msg (" -value is absolute). Default q value of 4 gives a compression ratio\n"); -fp_msg (" of about 6 with very high fidelity (only 0.26% increase in noise).\n"); -fp_msg (" Using q values of 2, or 1 will give compression ratios of\n"); -fp_msg (" about 8, or 10, respectively (with 1.0% or 4.1% noise increase).\n"); -fp_msg (" The scaled quantized values are randomly dithered using a seed \n"); -fp_msg (" value determined from the system clock at run time.\n"); -fp_msg (" Use -q0 instead of -q to suppress random dithering.\n"); -fp_msg (" Use -qz instead of -q to not dither zero-valued pixels.\n"); -fp_msg (" Use -qt or -qzt to compute random dithering seed from first tile checksum.\n"); -fp_msg (" Use -qN or -qzN, (N in range 1 to 10000) to use a specific dithering seed.\n"); -fp_msg (" Floating-point images can be losslessly compressed by selecting\n"); -fp_msg (" the GZIP algorithm and specifying -q 0, but this is slower and often\n"); -fp_msg (" produces much less compression than the default quantization method.\n"); -fp_msg (" -i2f Convert integer images to floating point, then quantize and compress\n"); -fp_msg (" using the specified q level. When used appropriately, this lossy\n"); -fp_msg (" compression method can give much better compression than the normal\n"); -fp_msg (" lossless compression methods without significant loss of information.\n"); -fp_msg (" The -n3ratio and -n3min flags control the minimum noise thresholds;\n"); -fp_msg (" Images below these thresholds will be losslessly compressed.\n"); -fp_msg (" -n3ratio Minimum ratio of background noise sigma divided by q. Default = 2.0.\n"); -fp_msg (" -n3min Minimum background noise sigma. Default = 6. The -i2f flag will be ignored\n"); -fp_msg (" if the noise level in the image does not exceed both thresholds.\n"); -fp_msg (" -s Scale factor for lossy Hcompress [default = 0 = lossless]\n"); -fp_msg (" (+values relative to RMS noise; -value is absolute)\n"); -fp_msg (" -n Rescale scaled-integer images to reduce noise and improve compression.\n"); -fp_msg (" -v Verbose mode; list each file as it is processed.\n"); -fp_msg (" -T Show compression algorithm comparison test statistics; files unchanged.\n"); -fp_msg (" -R Write the comparison test report (above) to a text file.\n"); -fp_msg (" -table Compress FITS binary tables as well as compress any image HDUs.\n"); -fp_msg (" -tableonly Compress only FITS binary tables; do not compress any image HDUs.\n"); -fp_msg (" \n"); - -fp_msg ("\nkeywords shared with funpack:\n"); - -fp_msg (" -F Overwrite input file by output file with same name.\n"); -fp_msg (" -D Delete input file after writing output.\n"); -fp_msg (" -Y Suppress prompts to confirm -F or -D options.\n"); - -fp_msg (" -S Output compressed FITS files to STDOUT.\n"); -fp_msg (" -L List contents; files unchanged.\n"); - -fp_msg (" -C Don't update FITS checksum keywords.\n"); - -fp_msg (" -H Show this message.\n"); -fp_msg (" -V Show version number.\n"); - -fp_msg ("\n FITS files to pack; enter '-' (a hyphen) to read input from stdin stream.\n"); -fp_msg (" Refer to the fpack User's Guide for more extensive help.\n"); -return(0); -} diff --git a/src/external/OpenGR/3rdparty/cfitsio/fpack.h b/src/external/OpenGR/3rdparty/cfitsio/fpack.h deleted file mode 100644 index a37f966b6..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/fpack.h +++ /dev/null @@ -1,189 +0,0 @@ -/* used by FPACK and FUNPACK - * R. Seaman, NOAO - * W. Pence, NASA/GSFC - */ - -#include -#include -#include - -/* not needed any more */ -/* #include */ -/* #include */ -/* #include */ - -#define FPACK_VERSION "1.7.0 (Dec 2013)" -/* -VERSION History - -1.7.0 (Dec 2013) - - extensive changes to the binary table compression method. All types - of binary table columns, including variable length array columns are - now supported. The command line table compression flag has been changed - to "-table" instead of "-BETAtable", and a new "-tableonly" flag has - been introduced to only compress the binary tables in the input files(s) - and not the image HDUs. -1.6.1 (Mar 2013) - - numerous changes to the BETAtable compression method used to compress - binary tables - - added support for compression 'steering' keywords that specify the - desired compression parameters that should be used when compressing - that particular HDU, thus overriding the fpack command line parameter - values. - -1.6.0 (June 2012) - - Fixed behavior of the "rename" function on Windows platforms so that - it will clobber/delete an existing file before renaming a file to - that name (the rename command behaves differently on POSIX and non-POSIX - environments). - -1.6.0 (February 2011) - - Added full support for compressing and uncompressing FITS binary tables - using a newly proposed format convention. This is intended only for - further feasibility studies, and is not recommended for use with publicly - distributed FITS files. - - Use the minimum of the MAD 2nd, 3rd, and 5th order values as a more - conservative extimate of the noise when quantizing floating point images. - - Enhanced the tile compression routines so that a tile that contains all - NaN pixel values will be compressed. - - When uncompressing an image that was originally in a FITS primary array, - funpack will also append any new keywords that were written into the - primary array of the compressed FITS file after the file was compressed. - - Added support for the GZIP_2 algorithm, which shuffles the bytes in the - pixel values prior to compressing them with gzip. -1.5.1 (December 2010) Added prototype, mainly hidden, support for compressing - binary tables. -1.5.0 (August 2010) Added the -i2f option to lossy compress integer images. -1.4.0 (Jan 2010) Reduced the default value for the q floating point image - quantization parameter from 16 to 4. This results in about 50% better - compression (from about 4.6x to 6.4) with no lost of significant information - (with the new subtractive dithering enhancement). Replaced the code for - generating temporary filenames to make the code more portable (to Windows). - Replaced calls to the unix 'access' and 'stat' functions with more portable - code. When unpacking a file, write it first to a temporary file, then - rename it when finished, so that other tasks cannot try to read the file - before it is complete. -1.3.0 (Oct 2009) added randomization to the dithering pattern so that - the same pattern is not used for every image; also added an option - for losslessly compressing floating point images with GZIP for test - purposes (not recommended for general use). Also added support for - reading the input FITS file from the stdin file streams. -1.2.0 (Sept 2009) added subtractive dithering feature (in CFITSIO) when - quantizing floating point images; When packing an IRAF .imh + .pix image, - the file name is changed to FILE.fits.fz, and if the original file is - deleted, then both the .imh and .pix files are deleted. -1.1.4 (May 2009) added -E option to funpack to unpack a list of HDUs -1.1.3 (March 2009) minor modifications to the content and format of the -T report -1.1.2 (September 2008) -*/ - -#define FP_INIT_MAGIC 42 -#define FPACK 0 -#define FUNPACK 1 - -/* changed from 16 in Jan. 2010 */ -#define DEF_QLEVEL 4. - -#define DEF_HCOMP_SCALE 0. -#define DEF_HCOMP_SMOOTH 0 -#define DEF_RESCALE_NOISE 0 - -#define SZ_STR 513 -#define SZ_CARD 81 - - -typedef struct -{ - int comptype; - float quantize_level; - int no_dither; - int dither_offset; - int dither_method; - float scale; - float rescale_noise; - int smooth; - int int_to_float; - float n3ratio; - float n3min; - long ntile[MAX_COMPRESS_DIM]; - - int to_stdout; - int listonly; - int clobber; - int delete_input; - int do_not_prompt; - int do_checksums; - int do_gzip_file; - int do_images; - int do_tables; - int test_all; - int verbose; - - char prefix[SZ_STR]; - char extname[SZ_STR]; - int delete_suffix; - char outfile[SZ_STR]; - int firstfile; - - int initialized; - int preflight_checked; -} fpstate; - -typedef struct -{ - int n_nulls; - double minval; - double maxval; - double mean; - double sigma; - double noise1; - double noise2; - double noise3; - double noise5; -} imgstats; - -int fp_get_param (int argc, char *argv[], fpstate *fpptr); -void abort_fpack(int sig); -void fp_abort_output (fitsfile *infptr, fitsfile *outfptr, int stat); -int fp_usage (void); -int fp_help (void); -int fp_hint (void); -int fp_init (fpstate *fpptr); -int fp_list (int argc, char *argv[], fpstate fpvar); -int fp_info (char *infits); -int fp_info_hdu (fitsfile *infptr); -int fp_preflight (int argc, char *argv[], int unpack, fpstate *fpptr); -int fp_loop (int argc, char *argv[], int unpack, fpstate fpvar); -int fp_pack (char *infits, char *outfits, fpstate fpvar, int *islossless); -int fp_unpack (char *infits, char *outfits, fpstate fpvar); -int fp_test (char *infits, char *outfits, char *outfits2, fpstate fpvar); -int fp_pack_hdu (fitsfile *infptr, fitsfile *outfptr, fpstate fpvar, - int *islossless, int *status); -int fp_unpack_hdu (fitsfile *infptr, fitsfile *outfptr, fpstate fpvar, int *status); -int fits_read_image_speed (fitsfile *infptr, float *whole_elapse, - float *whole_cpu, float *row_elapse, float *row_cpu, int *status); -int fp_test_hdu (fitsfile *infptr, fitsfile *outfptr, fitsfile *outfptr2, - fpstate fpvar, int *status); -int fp_test_table (fitsfile *infptr, fitsfile *outfptr, fitsfile *outfptr2, - fpstate fpvar, int *status); -int marktime(int *status); -int gettime(float *elapse, float *elapscpu, int *status); -int fits_read_image_speed (fitsfile *infptr, float *whole_elapse, - float *whole_cpu, float *row_elapse, float *row_cpu, int *status); - -int fp_i2stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status); -int fp_i4stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status); -int fp_r4stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status); -int fp_i2rescale(fitsfile *infptr, int naxis, long *naxes, double rescale, - fitsfile *outfptr, int *status); -int fp_i4rescale(fitsfile *infptr, int naxis, long *naxes, double rescale, - fitsfile *outfptr, int *status); - -int fp_msg (char *msg); -int fp_version (void); -int fp_noop (void); - -int fu_get_param (int argc, char *argv[], fpstate *fpptr); -int fu_usage (void); -int fu_hint (void); -int fu_help (void); diff --git a/src/external/OpenGR/3rdparty/cfitsio/fpackutil.c b/src/external/OpenGR/3rdparty/cfitsio/fpackutil.c deleted file mode 100644 index a4c0ccbf1..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/fpackutil.c +++ /dev/null @@ -1,2335 +0,0 @@ -/* FPACK utility routines - R. Seaman, NOAO & W. Pence, NASA/GSFC -*/ - -#include -#include -#include -#include - -/* #include "bzlib.h" only for experimental purposes */ - -#if defined(unix) || defined(__unix__) || defined(__unix) -#include -#endif - -#include -#include "fitsio.h" -#include "fpack.h" - -/* these filename buffer are used to delete temporary files */ -/* in case the program is aborted */ -char tempfilename[SZ_STR]; -char tempfilename2[SZ_STR]; -char tempfilename3[SZ_STR]; - -/* nearest integer function */ -# define NINT(x) ((x >= 0.) ? (int) (x + 0.5) : (int) (x - 0.5)) -# define NSHRT(x) ((x >= 0.) ? (short) (x + 0.5) : (short) (x - 0.5)) - -/* define variables for measuring elapsed time */ -clock_t scpu, ecpu; -long startsec; /* start of elapsed time interval */ -int startmilli; /* start of elapsed time interval */ - -/* CLOCKS_PER_SEC should be defined by most compilers */ -#if defined(CLOCKS_PER_SEC) -#define CLOCKTICKS CLOCKS_PER_SEC -#else -/* on SUN OS machine, CLOCKS_PER_SEC is not defined, so set its value */ -#define CLOCKTICKS 1000000 -#endif - -FILE *outreport; - -/* dimension of central image area to be sampled for test statistics */ -int XSAMPLE = 4100; -int YSAMPLE = 4100; - -int fp_msg (char *msg) -{ - printf ("%s", msg); - return(0); -} -/*--------------------------------------------------------------------------*/ -int fp_noop (void) -{ - fp_msg ("Input and output files are unchanged.\n"); - return(0); -} -/*--------------------------------------------------------------------------*/ -void fp_abort_output (fitsfile *infptr, fitsfile *outfptr, int stat) -{ - int status = 0, hdunum; - char msg[SZ_STR]; - - fits_file_name(infptr, tempfilename, &status); - fits_get_hdu_num(infptr, &hdunum); - - fits_close_file (infptr, &status); - - sprintf(msg, "Error processing file: %s\n", tempfilename); - fp_msg (msg); - sprintf(msg, " in HDU number %d\n", hdunum); - fp_msg (msg); - - fits_report_error (stderr, stat); - - if (outfptr) { - fits_delete_file(outfptr, &status); - fp_msg ("Input file is unchanged.\n"); - } - - exit (stat); -} -/*--------------------------------------------------------------------------*/ -int fp_version (void) -{ - float version; - char cfitsioversion[40]; - - fp_msg (FPACK_VERSION); - fits_get_version(&version); - sprintf(cfitsioversion, " CFITSIO version %5.3f", version); - fp_msg(cfitsioversion); - fp_msg ("\n"); - return(0); -} -/*--------------------------------------------------------------------------*/ -int fp_access (char *filename) -{ - /* test if a file exists */ - - FILE *diskfile; - - diskfile = fopen(filename, "r"); - - if (diskfile) { - fclose(diskfile); - return(0); - } else { - return(-1); - } -} -/*--------------------------------------------------------------------------*/ -int fp_tmpnam(char *suffix, char *rootname, char *tmpnam) -{ - /* create temporary file name */ - - int maxtry = 30, ii; - - if (strlen(suffix) + strlen(rootname) > SZ_STR-5) { - fp_msg ("Error: filename is too long to create tempory file\n"); exit (-1); - } - - strcpy (tmpnam, rootname); /* start with rootname */ - strcat(tmpnam, suffix); /* append the suffix */ - - maxtry = SZ_STR - strlen(tmpnam) - 1; - - for (ii = 0; ii < maxtry; ii++) { - if (fp_access(tmpnam)) break; /* good, the file does not exist */ - strcat(tmpnam, "x"); /* append an x to the name, and try again */ - } - - if (ii == maxtry) { - fp_msg ("\nCould not create temporary file name:\n"); - fp_msg (tmpnam); - fp_msg ("\n"); - exit (-1); - } - - return(0); -} -/*--------------------------------------------------------------------------*/ -int fp_init (fpstate *fpptr) -{ - int ii; - - fpptr->comptype = RICE_1; - fpptr->quantize_level = DEF_QLEVEL; - fpptr->no_dither = 0; - fpptr->dither_method = 1; - fpptr->dither_offset = 0; - fpptr->int_to_float = 0; - - /* thresholds when using the -i2f flag */ - fpptr->n3ratio = 2.0; /* minimum ratio of image noise sigma / q */ - fpptr->n3min = 6.; /* minimum noise sigma. */ - - fpptr->scale = DEF_HCOMP_SCALE; - fpptr->smooth = DEF_HCOMP_SMOOTH; - fpptr->rescale_noise = DEF_RESCALE_NOISE; - fpptr->ntile[0] = (long) -1; /* -1 means extent of axis */ - - for (ii=1; ii < MAX_COMPRESS_DIM; ii++) - fpptr->ntile[ii] = (long) 1; - - fpptr->to_stdout = 0; - fpptr->listonly = 0; - fpptr->clobber = 0; - fpptr->delete_input = 0; - fpptr->do_not_prompt = 0; - fpptr->do_checksums = 1; - fpptr->do_gzip_file = 0; - fpptr->do_tables = 0; /* this is intended for testing purposes */ - fpptr->do_images = 1; /* can be turned off with -tableonly switch */ - fpptr->test_all = 0; - fpptr->verbose = 0; - - fpptr->prefix[0] = 0; - fpptr->extname[0] = 0; - fpptr->delete_suffix = 0; - fpptr->outfile[0] = 0; - - fpptr->firstfile = 1; - - /* magic number for initialization check, boolean for preflight - */ - fpptr->initialized = FP_INIT_MAGIC; - fpptr->preflight_checked = 0; - return(0); -} -/*--------------------------------------------------------------------------*/ -int fp_list (int argc, char *argv[], fpstate fpvar) -{ - fitsfile *infptr; - char infits[SZ_STR], msg[SZ_STR]; - int hdunum, iarg, stat=0; - LONGLONG sizell; - - if (fpvar.initialized != FP_INIT_MAGIC) { - fp_msg ("Error: internal initialization error\n"); exit (-1); - } - - for (iarg=fpvar.firstfile; iarg < argc; iarg++) { - strncpy (infits, argv[iarg], SZ_STR); - - if (strchr (infits, '[') || strchr (infits, ']')) { - fp_msg ("Error: section/extension notation not supported: "); - fp_msg (infits); fp_msg ("\n"); exit (-1); - } - - if (fp_access (infits) != 0) { - fp_msg ("Error: can't find or read input file "); fp_msg (infits); - fp_msg ("\n"); fp_noop (); exit (-1); - } - - fits_open_file (&infptr, infits, READONLY, &stat); - if (stat) { fits_report_error (stderr, stat); exit (stat); } - - /* move to the end of file, to get the total size in bytes */ - fits_get_num_hdus (infptr, &hdunum, &stat); - fits_movabs_hdu (infptr, hdunum, NULL, &stat); - fits_get_hduaddrll(infptr, NULL, NULL, &sizell, &stat); - - - if (stat) { - fp_abort_output(infptr, NULL, stat); - } - - sprintf (msg, "# %s (", infits); fp_msg (msg); - -#if defined(_MSC_VER) - /* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */ - sprintf(msg, "%I64d bytes)\n", sizell); fp_msg (msg); -#elif (USE_LL_SUFFIX == 1) - sprintf(msg, "%lld bytes)\n", sizell); fp_msg (msg); -#else - sprintf(msg, "%ld bytes)\n", sizell); fp_msg (msg); -#endif - fp_info_hdu (infptr); - - fits_close_file (infptr, &stat); - if (stat) { fits_report_error (stderr, stat); exit (stat); } - } - return(0); -} -/*--------------------------------------------------------------------------*/ -int fp_info_hdu (fitsfile *infptr) -{ - long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; - char msg[SZ_STR], val[SZ_CARD], com[SZ_CARD]; - int naxis=0, hdutype, bitpix, hdupos, stat=0, ii; - unsigned long datasum, hdusum; - - fits_movabs_hdu (infptr, 1, NULL, &stat); - if (stat) { - fp_abort_output(infptr, NULL, stat); - } - - for (hdupos=1; ! stat; hdupos++) { - fits_get_hdu_type (infptr, &hdutype, &stat); - if (stat) { - fp_abort_output(infptr, NULL, stat); - } - - /* fits_get_hdu_type calls unknown extensions "IMAGE_HDU" - * so consult XTENSION keyword itself - */ - fits_read_keyword (infptr, "XTENSION", val, com, &stat); - if (stat == KEY_NO_EXIST) { - /* in primary HDU which by definition is an "image" */ - stat=0; /* clear for later error handling */ - - } else if (stat) { - fp_abort_output(infptr, NULL, stat); - - } else if (hdutype == IMAGE_HDU) { - /* that is, if XTENSION != "IMAGE" AND != "BINTABLE" */ - if (strncmp (val+1, "IMAGE", 5) && - strncmp (val+1, "BINTABLE", 5)) { - - /* assign something other than any of these */ - hdutype = IMAGE_HDU + ASCII_TBL + BINARY_TBL; - } - } - - fits_get_chksum(infptr, &datasum, &hdusum, &stat); - - if (hdutype == IMAGE_HDU) { - sprintf (msg, " %d IMAGE", hdupos); fp_msg (msg); - sprintf (msg, " SUMS=%lu/%lu", (unsigned long) (~((int) hdusum)), datasum); fp_msg (msg); - - fits_get_img_param (infptr, 9, &bitpix, &naxis, naxes, &stat); - - sprintf (msg, " BITPIX=%d", bitpix); fp_msg (msg); - - if (naxis == 0) { - sprintf (msg, " [no_pixels]"); fp_msg (msg); - } else if (naxis == 1) { - sprintf (msg, " [%ld]", naxes[1]); fp_msg (msg); - } else { - sprintf (msg, " [%ld", naxes[0]); fp_msg (msg); - for (ii=1; ii < naxis; ii++) { - sprintf (msg, "x%ld", naxes[ii]); fp_msg (msg); - } - fp_msg ("]"); - } - - if (fits_is_compressed_image (infptr, &stat)) { - fits_read_keyword (infptr, "ZCMPTYPE", val, com, &stat); - - /* allow for quote in keyword value */ - if (! strncmp (val+1, "RICE_1", 6)) - fp_msg (" tiled_rice\n"); - else if (! strncmp (val+1, "GZIP_1", 6)) - fp_msg (" tiled_gzip_1\n"); - else if (! strncmp (val+1, "GZIP_2", 6)) - fp_msg (" tiled_gzip_2\n"); - else if (! strncmp (val+1, "PLIO_1", 6)) - fp_msg (" tiled_plio\n"); - else if (! strncmp (val+1, "HCOMPRESS_1", 11)) - fp_msg (" tiled_hcompress\n"); - else - fp_msg (" unknown\n"); - - } else - fp_msg (" not_tiled\n"); - - } else if (hdutype == ASCII_TBL) { - sprintf (msg, " %d ASCII_TBL", hdupos); fp_msg (msg); - sprintf (msg, " SUMS=%lu/%lu\n", (unsigned long) (~((int) hdusum)), datasum); fp_msg (msg); - - } else if (hdutype == BINARY_TBL) { - sprintf (msg, " %d BINARY_TBL", hdupos); fp_msg (msg); - sprintf (msg, " SUMS=%lu/%lu\n", (unsigned long) (~((int) hdusum)), datasum); fp_msg (msg); - - } else { - sprintf (msg, " %d OTHER", hdupos); fp_msg (msg); - sprintf (msg, " SUMS=%lu/%lu", (unsigned long) (~((int) hdusum)), datasum); fp_msg (msg); - sprintf (msg, " %s\n", val); fp_msg (msg); - } - - fits_movrel_hdu (infptr, 1, NULL, &stat); - } - return(0); -} - -/*--------------------------------------------------------------------------*/ -int fp_preflight (int argc, char *argv[], int unpack, fpstate *fpptr) -{ - char infits[SZ_STR], outfits[SZ_STR]; - int iarg, namelen, nfiles = 0; - - if (fpptr->initialized != FP_INIT_MAGIC) { - fp_msg ("Error: internal initialization error\n"); exit (-1); - } - - for (iarg=fpptr->firstfile; iarg < argc; iarg++) { - - outfits[0] = '\0'; - - if (strlen(argv[iarg]) > SZ_STR - 4) { /* allow for .fz or .gz suffix */ - fp_msg ("Error: input file name\n "); fp_msg (argv[iarg]); - fp_msg ("\n is too long\n"); fp_noop (); exit (-1); - } - - strncpy (infits, argv[iarg], SZ_STR); - if (infits[0] == '-' && infits[1] != '\0') { - /* don't interpret this as intending to read input file from stdin */ - fp_msg ("Error: invalid input file name\n "); fp_msg (argv[iarg]); - fp_msg ("\n"); fp_noop (); exit (-1); - } - - if (strchr (infits, '[') || strchr (infits, ']')) { - fp_msg ("Error: section/extension notation not supported: "); - fp_msg (infits); fp_msg ("\n"); fp_noop (); exit (-1); - } - - if (unpack) { - /* ********** This section applies to funpack ************ */ - - /* check that input file exists */ - if (infits[0] != '-') { /* if not reading from stdin stream */ - if (fp_access (infits) != 0) { /* if not, then check if */ - strcat(infits, ".fz"); /* a .fz version exsits */ - if (fp_access (infits) != 0) { - namelen = strlen(infits); - infits[namelen - 3] = '\0'; /* remove the .fz suffix */ - fp_msg ("Error: can't find or read input file "); fp_msg (infits); - fp_msg ("\n"); fp_noop (); exit (-1); - } - } else { /* make sure a .fz version of the same file doesn't exist */ - namelen = strlen(infits); - strcat(infits, ".fz"); - if (fp_access (infits) == 0) { - infits[namelen] = '\0'; /* remove the .fz suffix */ - fp_msg ("Error: ambiguous input file name. Which file should be unpacked?:\n "); - fp_msg (infits); fp_msg ("\n "); - fp_msg (infits); fp_msg (".fz\n"); - fp_noop (); exit (-1); - } else { - infits[namelen] = '\0'; /* remove the .fz suffix */ - } - } - } - - /* if writing to stdout, then we are all done */ - if (fpptr->to_stdout) { - continue; - } - - if (fpptr->outfile[0]) { /* user specified output file name */ - nfiles++; - if (nfiles > 1) { - fp_msg ("Error: cannot use same output file name for multiple files:\n "); - fp_msg (fpptr->outfile); - fp_msg ("\n"); fp_noop (); exit (-1); - } - - /* check that output file doesn't exist */ - if (fp_access (fpptr->outfile) == 0) { - fp_msg ("Error: output file already exists:\n "); - fp_msg (fpptr->outfile); - fp_msg ("\n "); fp_noop (); exit (-1); - } - continue; - } - - /* construct output file name to test */ - if (fpptr->prefix[0]) { - if (strlen(fpptr->prefix) + strlen(infits) > SZ_STR - 1) { - fp_msg ("Error: output file name for\n "); fp_msg (infits); - fp_msg ("\n is too long with the prefix\n"); fp_noop (); exit (-1); - } - strcat(outfits,fpptr->prefix); - } - - /* construct output file name */ - if (infits[0] == '-') { - strcpy(outfits, "output.fits"); - } else { - strcpy(outfits, infits); - } - - /* remove .gz suffix, if present (output is not gzipped) */ - namelen = strlen(outfits); - if ( !strcmp(".gz", outfits + namelen - 3) ) { - outfits[namelen - 3] = '\0'; - } - - /* check for .fz suffix that is sometimes required */ - /* and remove it if present */ - if (infits[0] != '-') { /* if not reading from stdin stream */ - namelen = strlen(outfits); - if ( !strcmp(".fz", outfits + namelen - 3) ) { /* suffix is present */ - outfits[namelen - 3] = '\0'; - } else if (fpptr->delete_suffix) { /* required suffix is missing */ - fp_msg ("Error: input compressed file "); fp_msg (infits); - fp_msg ("\n does not have the default .fz suffix.\n"); - fp_noop (); exit (-1); - } - } - - /* if infits != outfits, make sure outfits doesn't already exist */ - if (strcmp(infits, outfits)) { - if (fp_access (outfits) == 0) { - fp_msg ("Error: output file already exists:\n "); fp_msg (outfits); - fp_msg ("\n "); fp_noop (); exit (-1); - } - } - - /* if gzipping the output, make sure .gz file doesn't exist */ - if (fpptr->do_gzip_file) { - strcat(outfits, ".gz"); - if (fp_access (outfits) == 0) { - fp_msg ("Error: output file already exists:\n "); fp_msg (outfits); - fp_msg ("\n "); fp_noop (); exit (-1); - } - namelen = strlen(outfits); - outfits[namelen - 3] = '\0'; /* remove the .gz suffix again */ - } - } else { - /* ********** This section applies to fpack ************ */ - - /* check that input file exists */ - if (infits[0] != '-') { /* if not reading from stdin stream */ - if (fp_access (infits) != 0) { /* if not, then check if */ - strcat(infits, ".gz"); /* a gzipped version exsits */ - if (fp_access (infits) != 0) { - namelen = strlen(infits); - infits[namelen - 3] = '\0'; /* remove the .gz suffix */ - fp_msg ("Error: can't find or read input file "); fp_msg (infits); - fp_msg ("\n"); fp_noop (); exit (-1); - } - } - } - - /* make sure the file to pack does not already have a .fz suffix */ - namelen = strlen(infits); - if ( !strcmp(".fz", infits + namelen - 3) ) { - fp_msg ("Error: fpack input file already has '.fz' suffix\n" ); fp_msg (infits); - fp_msg ("\n"); fp_noop (); exit (-1); - } - - /* if writing to stdout, or just testing the files, then we are all done */ - if (fpptr->to_stdout || fpptr->test_all) { - continue; - } - - /* construct output file name */ - if (infits[0] == '-') { - strcpy(outfits, "input.fits"); - } else { - strcpy(outfits, infits); - } - - /* remove .gz suffix, if present (output is not gzipped) */ - namelen = strlen(outfits); - if ( !strcmp(".gz", outfits + namelen - 3) ) { - outfits[namelen - 3] = '\0'; - } - - /* remove .imh suffix (IRAF format image), and replace with .fits */ - namelen = strlen(outfits); - if ( !strcmp(".imh", outfits + namelen - 4) ) { - outfits[namelen - 4] = '\0'; - strcat(outfits, ".fits"); - } - - /* If not clobbering the input file, add .fz suffix to output name */ - if (! fpptr->clobber) - strcat(outfits, ".fz"); - - /* if infits != outfits, make sure outfits doesn't already exist */ - if (strcmp(infits, outfits)) { - if (fp_access (outfits) == 0) { - fp_msg ("Error: output file already exists:\n "); fp_msg (outfits); - fp_msg ("\n "); fp_noop (); exit (-1); - } - } - } /* end of fpack section */ - } - - fpptr->preflight_checked++; - return(0); -} - -/*--------------------------------------------------------------------------*/ -/* must run fp_preflight() before fp_loop() - */ -int fp_loop (int argc, char *argv[], int unpack, fpstate fpvar) -{ - char infits[SZ_STR], outfits[SZ_STR]; - char temp[SZ_STR], answer[30]; - int iarg, islossless, namelen, iraf_infile = 0, status = 0, ifail; - - if (fpvar.initialized != FP_INIT_MAGIC) { - fp_msg ("Error: internal initialization error\n"); exit (-1); - } else if (! fpvar.preflight_checked) { - fp_msg ("Error: internal preflight error\n"); exit (-1); - } - - if (fpvar.test_all && fpvar.outfile[0]) { - outreport = fopen(fpvar.outfile, "w"); - fprintf(outreport," Filename Extension BITPIX NAXIS1 NAXIS2 Size N_nulls Minval Maxval Mean Sigm Noise1 Noise2 Noise3 Noise5 T_whole T_rowbyrow "); - fprintf(outreport,"[Comp_ratio, Pack_cpu, Unpack_cpu, Lossless readtimes] (repeated for Rice, Hcompress, and GZIP)\n"); - } - - - tempfilename[0] = '\0'; - tempfilename2[0] = '\0'; - tempfilename3[0] = '\0'; - -/* set up signal handler to delete temporary file on abort */ -#ifdef SIGINT - if (signal(SIGINT, SIG_IGN) != SIG_IGN) { - (void) signal(SIGINT, abort_fpack); - } -#endif - -#ifdef SIGTERM - if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { - (void) signal(SIGTERM, abort_fpack); - } -#endif - -#ifdef SIGHUP - if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { - (void) signal(SIGHUP, abort_fpack); - } -#endif - - for (iarg=fpvar.firstfile; iarg < argc; iarg++) { - - temp[0] = '\0'; - outfits[0] = '\0'; - islossless = 1; - - strncpy (infits, argv[iarg], SZ_STR - 1); - - if (unpack) { - /* ********** This section applies to funpack ************ */ - - /* find input file */ - if (infits[0] != '-') { /* if not reading from stdin stream */ - if (fp_access (infits) != 0) { /* if not, then */ - strcat(infits, ".fz"); /* a .fz version must exsit */ - } - } - - if (fpvar.to_stdout) { - strcpy(outfits, "-"); - - } else if (fpvar.outfile[0]) { /* user specified output file name */ - strcpy(outfits, fpvar.outfile); - - } else { - /* construct output file name */ - if (fpvar.prefix[0]) { - strcat(outfits,fpvar.prefix); - } - - /* construct output file name */ - if (infits[0] == '-') { - strcpy(outfits, "output.fits"); - } else { - strcpy(outfits, infits); - } - - /* remove .gz suffix, if present (output is not gzipped) */ - namelen = strlen(outfits); - if ( !strcmp(".gz", outfits + namelen - 3) ) { - outfits[namelen - 3] = '\0'; - } - - /* check for .fz suffix that is sometimes required */ - /* and remove it if present */ - namelen = strlen(outfits); - if ( !strcmp(".fz", outfits + namelen - 3) ) { /* suffix is present */ - outfits[namelen - 3] = '\0'; - } - } - - } else { - /* ********** This section applies to fpack ************ */ - - if (fpvar.to_stdout) { - strcpy(outfits, "-"); - } else if (! fpvar.test_all) { - - /* construct output file name */ - if (infits[0] == '-') { - strcpy(outfits, "input.fits"); - } else { - strcpy(outfits, infits); - } - - /* remove .gz suffix, if present (output is not gzipped) */ - namelen = strlen(outfits); - if ( !strcmp(".gz", outfits + namelen - 3) ) { - outfits[namelen - 3] = '\0'; - } - - /* remove .imh suffix (IRAF format image), and replace with .fits */ - namelen = strlen(outfits); - if ( !strcmp(".imh", outfits + namelen - 4) ) { - outfits[namelen - 4] = '\0'; - strcat(outfits, ".fits"); - iraf_infile = 1; /* this is an IRAF format input file */ - /* change the output name to "NAME.fits.fz" */ - } - - /* If not clobbering the input file, add .fz suffix to output name */ - if (! fpvar.clobber) - strcat(outfits, ".fz"); - } - } - - strncpy(temp, outfits, SZ_STR-1); - - if (infits[0] != '-') { /* if not reading from stdin stream */ - if (!strcmp(infits, outfits) ) { /* are input and output names the same? */ - - /* clobber the input file with the output file with the same name */ - if (! fpvar.clobber) { - fp_msg ("\nError: must use -F flag to clobber input file.\n"); - exit (-1); - } - - /* create temporary file name in the output directory (same as input directory)*/ - fp_tmpnam("Tmp1", infits, outfits); - - strcpy(tempfilename, outfits); /* store temp file name, in case of abort */ - } - } - - - /* *************** now do the real work ********************* */ - - if (fpvar.verbose && ! fpvar.to_stdout) - printf("%s ", infits); - - if (fpvar.test_all) { /* compare all the algorithms */ - - /* create 2 temporary file names, in the CWD */ - fp_tmpnam("Tmpfile1", "", tempfilename); - fp_tmpnam("Tmpfile2", "", tempfilename2); - - fp_test (infits, tempfilename, tempfilename2, fpvar); - - remove(tempfilename); - tempfilename[0] = '\0'; /* clear the temp file name */ - remove(tempfilename2); - tempfilename2[0] = '\0'; - continue; - - } else if (unpack) { - if (fpvar.to_stdout) { - /* unpack the input file to the stdout stream */ - fp_unpack (infits, outfits, fpvar); - } else { - /* unpack to temporary file, so other tasks can't open it until it is renamed */ - - /* create temporary file name, in the output directory */ - fp_tmpnam("Tmp2", outfits, tempfilename2); - - /* unpack the input file to the temporary file */ - fp_unpack (infits, tempfilename2, fpvar); - - /* rename the temporary file to it's real name */ - ifail = rename(tempfilename2, outfits); - if (ifail) { - fp_msg("Failed to rename temporary file name:\n "); - fp_msg(tempfilename2); - fp_msg(" -> "); - fp_msg(outfits); - fp_msg("\n"); - exit (-1); - } else { - tempfilename2[0] = '\0'; /* clear temporary file name */ - } - } - } else { - fp_pack (infits, outfits, fpvar, &islossless); - } - - if (fpvar.to_stdout) { - continue; - } - - /* ********** clobber and/or delete files, if needed ************** */ - - if (!strcmp(infits, temp) && fpvar.clobber ) { - - if (!islossless && ! fpvar.do_not_prompt) { - fp_msg ("\nFile "); - fp_msg (infits); - fp_msg ("\nwas compressed with a LOSSY method. Overwrite the\n"); - fp_msg ("original file with the compressed version? (Y/N) "); - fgets(answer, 29, stdin); - if (answer[0] != 'Y' && answer[0] != 'y') { - fp_msg ("\noriginal file NOT overwritten!\n"); - remove(outfits); - continue; - } - } - - if (iraf_infile) { /* special case of deleting an IRAF format header and pixel file */ - if (fits_delete_iraf_file(infits, &status)) { - fp_msg("\nError deleting IRAF .imh and .pix files.\n"); - fp_msg(infits); fp_msg ("\n"); exit (-1); - } - } - -#if defined(unix) || defined(__unix__) || defined(__unix) - /* rename clobbers input on Unix platforms */ - if (rename (outfits, temp) != 0) { - fp_msg ("\nError renaming tmp file to "); - fp_msg (temp); fp_msg ("\n"); exit (-1); - } -#else - /* rename DOES NOT clobber existing files on Windows platforms */ - /* so explicitly remove any existing file before renaming the file */ - remove(temp); - if (rename (outfits, temp) != 0) { - fp_msg ("\nError renaming tmp file to "); - fp_msg (temp); fp_msg ("\n"); exit (-1); - } -#endif - - tempfilename[0] = '\0'; /* clear temporary file name */ - strcpy(outfits, temp); - - } else if (fpvar.clobber || fpvar.delete_input) { /* delete the input file */ - if (!islossless && !fpvar.do_not_prompt) { /* user did not turn off delete prompt */ - fp_msg ("\nFile "); - fp_msg (infits); - fp_msg ("\nwas compressed with a LOSSY method. \n"); - fp_msg ("Delete the original file? (Y/N) "); - fgets(answer, 29, stdin); - if (answer[0] != 'Y' && answer[0] != 'y') { /* user abort */ - fp_msg ("\noriginal file NOT deleted!\n"); - } else { - if (iraf_infile) { /* special case of deleting an IRAF format header and pixel file */ - if (fits_delete_iraf_file(infits, &status)) { - fp_msg("\nError deleting IRAF .imh and .pix files.\n"); - fp_msg(infits); fp_msg ("\n"); exit (-1); - } - } else if (remove(infits) != 0) { /* normal case of deleting input FITS file */ - fp_msg ("\nError deleting input file "); - fp_msg (infits); fp_msg ("\n"); exit (-1); - } - } - } else { /* user said don't prompt, so just delete the input file */ - if (iraf_infile) { /* special case of deleting an IRAF format header and pixel file */ - if (fits_delete_iraf_file(infits, &status)) { - fp_msg("\nError deleting IRAF .imh and .pix files.\n"); - fp_msg(infits); fp_msg ("\n"); exit (-1); - } - } else if (remove(infits) != 0) { /* normal case of deleting input FITS file */ - fp_msg ("\nError deleting input file "); - fp_msg (infits); fp_msg ("\n"); exit (-1); - } - } - } - iraf_infile = 0; - - if (fpvar.do_gzip_file) { /* gzip the output file */ - strcpy(temp, "gzip -1 "); - strcat(temp,outfits); - system(temp); - strcat(outfits, ".gz"); /* only possibible with funpack */ - } - - if (fpvar.verbose && ! fpvar.to_stdout) - printf("-> %s\n", outfits); - - } - - if (fpvar.test_all && fpvar.outfile[0]) - fclose(outreport); - return(0); -} - -/*--------------------------------------------------------------------------*/ -/* fp_pack assumes the output file does not exist (checked by preflight) - */ -int fp_pack (char *infits, char *outfits, fpstate fpvar, int *islossless) -{ - fitsfile *infptr, *outfptr; - int stat=0; - - fits_open_file (&infptr, infits, READONLY, &stat); - if (stat) { fits_report_error (stderr, stat); exit (stat); } - - fits_create_file (&outfptr, outfits, &stat); - if (stat) { - fp_abort_output(infptr, NULL, stat); - } - - - if (stat) { - fp_abort_output(infptr, outfptr, stat); - } - - while (! stat) { - - /* LOOP OVER EACH HDU */ - - fits_set_lossy_int (outfptr, fpvar.int_to_float, &stat); - fits_set_compression_type (outfptr, fpvar.comptype, &stat); - fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); - - if (fpvar.no_dither) - fits_set_quantize_method(outfptr, -1, &stat); - else - fits_set_quantize_method(outfptr, fpvar.dither_method, &stat); - - fits_set_quantize_level (outfptr, fpvar.quantize_level, &stat); - fits_set_dither_offset(outfptr, fpvar.dither_offset, &stat); - fits_set_hcomp_scale (outfptr, fpvar.scale, &stat); - fits_set_hcomp_smooth (outfptr, fpvar.smooth, &stat); - - fp_pack_hdu (infptr, outfptr, fpvar, islossless, &stat); - - if (fpvar.do_checksums) { - fits_write_chksum (outfptr, &stat); - } - - fits_movrel_hdu (infptr, 1, NULL, &stat); - } - - if (stat == END_OF_FILE) stat = 0; - - /* set checksum for case of newly created primary HDU */ - - if (fpvar.do_checksums) { - fits_movabs_hdu (outfptr, 1, NULL, &stat); - fits_write_chksum (outfptr, &stat); - } - - if (stat) { - fp_abort_output(infptr, outfptr, stat); - } - - fits_close_file (outfptr, &stat); - fits_close_file (infptr, &stat); - - return(0); -} - -/*--------------------------------------------------------------------------*/ -/* fp_unpack assumes the output file does not exist - */ -int fp_unpack (char *infits, char *outfits, fpstate fpvar) -{ - fitsfile *infptr, *outfptr; - int stat=0, hdutype, extnum, single = 0; - char *loc, *hduloc, hduname[SZ_STR]; - - fits_open_file (&infptr, infits, READONLY, &stat); - fits_create_file (&outfptr, outfits, &stat); - - if (stat) { - fp_abort_output(infptr, outfptr, stat); - } - - if (fpvar.extname[0]) { /* unpack a list of HDUs? */ - - /* move to the first HDU in the list */ - hduloc = fpvar.extname; - loc = strchr(hduloc, ','); /* look for 'comma' delimiter between names */ - - if (loc) - *loc = '\0'; /* terminate the first name in the string */ - - strcpy(hduname, hduloc); /* copy the first name into temporary string */ - - if (loc) - hduloc = loc + 1; /* advance to the beginning of the next name, if any */ - else { - hduloc += strlen(hduname); /* end of the list */ - single = 1; /* only 1 HDU is being unpacked */ - } - - if (isdigit( (int) hduname[0]) ) { - extnum = strtol(hduname, &loc, 10); /* read the string as an integer */ - - /* check for junk following the integer */ - if (*loc == '\0' ) /* no junk, so move to this HDU number (+1) */ - { - fits_movabs_hdu(infptr, extnum + 1, &hdutype, &stat); /* move to HDU number */ - if (hdutype != IMAGE_HDU) - stat = NOT_IMAGE; - - } else { /* the string is not an integer, so must be the column name */ - hdutype = IMAGE_HDU; - fits_movnam_hdu(infptr, hdutype, hduname, 0, &stat); - } - } - else - { - /* move to the named image extension */ - hdutype = IMAGE_HDU; - fits_movnam_hdu(infptr, hdutype, hduname, 0, &stat); - } - } - - if (stat) { - fp_msg ("Unable to find and move to extension '"); - fp_msg(hduname); - fp_msg("'\n"); - fp_abort_output(infptr, outfptr, stat); - } - - while (! stat) { - - if (single) - stat = -1; /* special status flag to force output primary array */ - - fp_unpack_hdu (infptr, outfptr, fpvar, &stat); - - if (fpvar.do_checksums) { - fits_write_chksum (outfptr, &stat); - } - - /* move to the next HDU */ - if (fpvar.extname[0]) { /* unpack a list of HDUs? */ - - if (!(*hduloc)) { - stat = END_OF_FILE; /* we reached the end of the list */ - } else { - /* parse the next HDU name and move to it */ - loc = strchr(hduloc, ','); - - if (loc) /* look for 'comma' delimiter between names */ - *loc = '\0'; /* terminate the first name in the string */ - - strcpy(hduname, hduloc); /* copy the next name into temporary string */ - - if (loc) - hduloc = loc + 1; /* advance to the beginning of the next name, if any */ - else - *hduloc = '\0'; /* end of the list */ - - if (isdigit( (int) hduname[0]) ) { - extnum = strtol(hduname, &loc, 10); /* read the string as an integer */ - - /* check for junk following the integer */ - if (*loc == '\0' ) /* no junk, so move to this HDU number (+1) */ - { - fits_movabs_hdu(infptr, extnum + 1, &hdutype, &stat); /* move to HDU number */ - if (hdutype != IMAGE_HDU) - stat = NOT_IMAGE; - - } else { /* the string is not an integer, so must be the column name */ - hdutype = IMAGE_HDU; - fits_movnam_hdu(infptr, hdutype, hduname, 0, &stat); - } - - } else { - /* move to the named image extension */ - hdutype = IMAGE_HDU; - fits_movnam_hdu(infptr, hdutype, hduname, 0, &stat); - } - - if (stat) { - fp_msg ("Unable to find and move to extension '"); - fp_msg(hduname); - fp_msg("'\n"); - } - } - } else { - /* increment to the next HDU */ - fits_movrel_hdu (infptr, 1, NULL, &stat); - } - } - - if (stat == END_OF_FILE) stat = 0; - - /* set checksum for case of newly created primary HDU - */ - if (fpvar.do_checksums) { - fits_movabs_hdu (outfptr, 1, NULL, &stat); - fits_write_chksum (outfptr, &stat); - } - - - if (stat) { - fp_abort_output(infptr, outfptr, stat); - } - - fits_close_file (outfptr, &stat); - fits_close_file (infptr, &stat); - - return(0); -} - -/*--------------------------------------------------------------------------*/ -/* fp_test assumes the output files do not exist - */ -int fp_test (char *infits, char *outfits, char *outfits2, fpstate fpvar) -{ - fitsfile *inputfptr, *infptr, *outfptr, *outfptr2, *tempfile; - - long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; - int stat=0, totpix=0, naxis=0, ii, hdutype, bitpix = 0, extnum = 0, len; - int tstatus = 0, hdunum, rescale_flag, bpix, ncols; - char dtype[8], dimen[100]; - double bscale, rescale, noisemin; - long headstart, datastart, dataend; - float origdata = 0., whole_cpu, whole_elapse, row_elapse, row_cpu, xbits; - - LONGLONG nrows; - /* structure to hold image statistics (defined in fpack.h) */ - imgstats imagestats; - - fits_open_file (&inputfptr, infits, READONLY, &stat); - fits_create_file (&outfptr, outfits, &stat); - fits_create_file (&outfptr2, outfits2, &stat); - - if (stat) { fits_report_error (stderr, stat); exit (stat); } - - while (! stat) { - - /* LOOP OVER EACH HDU */ - rescale_flag = 0; - fits_get_hdu_type (inputfptr, &hdutype, &stat); - - if (hdutype == IMAGE_HDU) { - fits_get_img_param (inputfptr, 9, &bitpix, &naxis, naxes, &stat); - for (totpix=1, ii=0; ii < 9; ii++) totpix *= naxes[ii]; - } - - if (!fits_is_compressed_image (inputfptr, &stat) && hdutype == IMAGE_HDU && - naxis != 0 && totpix != 0 && fpvar.do_images) { - - /* rescale a scaled integer image to reduce noise? */ - if (fpvar.rescale_noise != 0. && bitpix > 0 && bitpix < LONGLONG_IMG) { - - tstatus = 0; - fits_read_key(inputfptr, TDOUBLE, "BSCALE", &bscale, 0, &tstatus); - - if (tstatus == 0 && bscale != 1.0) { /* image must be scaled */ - - if (bitpix == LONG_IMG) - fp_i4stat(inputfptr, naxis, naxes, &imagestats, &stat); - else - fp_i2stat(inputfptr, naxis, naxes, &imagestats, &stat); - - /* use the minimum of the MAD 2nd, 3rd, and 5th order noise estimates */ - noisemin = imagestats.noise3; - if (imagestats.noise2 != 0. && imagestats.noise2 < noisemin) noisemin = imagestats.noise2; - if (imagestats.noise5 != 0. && imagestats.noise5 < noisemin) noisemin = imagestats.noise5; - - rescale = noisemin / fpvar.rescale_noise; - if (rescale > 1.0) { - - /* all the criteria are met, so create a temporary file that */ - /* contains a rescaled version of the image, in CWD */ - - /* create temporary file name */ - fp_tmpnam("Tmpfile3", "", tempfilename3); - - fits_create_file(&tempfile, tempfilename3, &stat); - - fits_get_hdu_num(inputfptr, &hdunum); - if (hdunum != 1) { - - /* the input hdu is an image extension, so create dummy primary */ - fits_create_img(tempfile, 8, 0, naxes, &stat); - } - - fits_copy_header(inputfptr, tempfile, &stat); /* copy the header */ - - /* rescale the data, so that it will compress more efficiently */ - if (bitpix == LONG_IMG) - fp_i4rescale(inputfptr, naxis, naxes, rescale, tempfile, &stat); - else - fp_i2rescale(inputfptr, naxis, naxes, rescale, tempfile, &stat); - - /* scale the BSCALE keyword by the inverse factor */ - - bscale = bscale * rescale; - fits_update_key(tempfile, TDOUBLE, "BSCALE", &bscale, 0, &stat); - - /* rescan the header, to reset the actual scaling parameters */ - fits_set_hdustruc(tempfile, &stat); - - infptr = tempfile; - rescale_flag = 1; - } - } - } - - if (!rescale_flag) /* just compress the input file, without rescaling */ - infptr = inputfptr; - - /* compute basic statistics about the input image */ - if (bitpix == BYTE_IMG) { - bpix = 8; - strcpy(dtype, "8 "); - fp_i2stat(infptr, naxis, naxes, &imagestats, &stat); - } else if (bitpix == SHORT_IMG) { - bpix = 16; - strcpy(dtype, "16 "); - fp_i2stat(infptr, naxis, naxes, &imagestats, &stat); - } else if (bitpix == LONG_IMG) { - bpix = 32; - strcpy(dtype, "32 "); - fp_i4stat(infptr, naxis, naxes, &imagestats, &stat); - } else if (bitpix == LONGLONG_IMG) { - bpix = 64; - strcpy(dtype, "64 "); - } else if (bitpix == FLOAT_IMG) { - bpix = 32; - strcpy(dtype, "-32"); - fp_r4stat(infptr, naxis, naxes, &imagestats, &stat); - } else if (bitpix == DOUBLE_IMG) { - bpix = 64; - strcpy(dtype, "-64"); - fp_r4stat(infptr, naxis, naxes, &imagestats, &stat); - } - - /* use the minimum of the MAD 2nd, 3rd, and 5th order noise estimates */ - noisemin = imagestats.noise3; - if (imagestats.noise2 != 0. && imagestats.noise2 < noisemin) noisemin = imagestats.noise2; - if (imagestats.noise5 != 0. && imagestats.noise5 < noisemin) noisemin = imagestats.noise5; - - xbits = (float) (log10(noisemin)/.301 + 1.792); - - printf("\n File: %s\n", infits); - printf(" Ext BITPIX Dimens. Nulls Min Max Mean Sigma Noise2 Noise3 Noise5 Nbits MaxR\n"); - - printf(" %3d %s", extnum, dtype); - sprintf(dimen," (%ld", naxes[0]); - len =strlen(dimen); - for (ii = 1; ii < naxis; ii++) { - sprintf(dimen+len,",%ld", naxes[ii]); - len =strlen(dimen); - } - strcat(dimen, ")"); - printf("%-12s",dimen); - - fits_get_hduaddr(inputfptr, &headstart, &datastart, &dataend, &stat); - origdata = (float) ((dataend - datastart)/1000000.); - - /* get elapsed and cpu times need to read the uncompressed image */ - fits_read_image_speed (infptr, &whole_elapse, &whole_cpu, - &row_elapse, &row_cpu, &stat); - - printf(" %5d %6.0f %6.0f %8.1f %#8.2g %#7.3g %#7.3g %#7.3g %#5.1f %#6.2f\n", - imagestats.n_nulls, imagestats.minval, imagestats.maxval, - imagestats.mean, imagestats.sigma, - imagestats.noise2, imagestats.noise3, imagestats.noise5, xbits, bpix/xbits); - - printf("\n Type Ratio Size (MB) Pk (Sec) UnPk Exact ElpN CPUN Elp1 CPU1\n"); - - printf(" Native %5.3f %5.3f %5.3f %5.3f\n", - whole_elapse, whole_cpu, row_elapse, row_cpu); - - if (fpvar.outfile[0]) { - fprintf(outreport, - " %s %d %d %ld %ld %#10.4g %d %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g", - infits, extnum, bitpix, naxes[0], naxes[1], origdata, imagestats.n_nulls, imagestats.minval, - imagestats.maxval, imagestats.mean, imagestats.sigma, - imagestats.noise1, imagestats.noise2, imagestats.noise3, imagestats.noise5, whole_elapse, whole_cpu, row_elapse, row_cpu); - } - - fits_set_lossy_int (outfptr, fpvar.int_to_float, &stat); - if ( (bitpix > 0) && (fpvar.int_to_float != 0) ) { - - if ( (noisemin < (fpvar.n3ratio * fpvar.quantize_level) ) || - (noisemin < fpvar.n3min)) { - - /* image contains too little noise to quantize effectively */ - fits_set_lossy_int (outfptr, 0, &stat); - fits_get_hdu_num(infptr, &hdunum); - -printf(" HDU %d does not meet noise criteria to be quantized, so losslessly compressed.\n", hdunum); - } - } - - /* test compression ratio and speed for each algorithm */ - - if (fpvar.quantize_level != 0) { - - fits_set_compression_type (outfptr, RICE_1, &stat); - fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); - if (fpvar.no_dither) - fits_set_quantize_method(outfptr, -1, &stat); - else - fits_set_quantize_method(outfptr, fpvar.dither_method, &stat); - - fits_set_quantize_level (outfptr, fpvar.quantize_level, &stat); - fits_set_dither_offset(outfptr, fpvar.dither_offset, &stat); - fits_set_hcomp_scale (outfptr, fpvar.scale, &stat); - fits_set_hcomp_smooth (outfptr, fpvar.smooth, &stat); - - fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); - } - - if (fpvar.quantize_level != 0) { -\ - fits_set_compression_type (outfptr, HCOMPRESS_1, &stat); - fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); - - if (fpvar.no_dither) - fits_set_quantize_method(outfptr, -1, &stat); - else - fits_set_quantize_method(outfptr, fpvar.dither_method, &stat); - - fits_set_quantize_level (outfptr, fpvar.quantize_level, &stat); - fits_set_dither_offset(outfptr, fpvar.dither_offset, &stat); - fits_set_hcomp_scale (outfptr, fpvar.scale, &stat); - fits_set_hcomp_smooth (outfptr, fpvar.smooth, &stat); - - fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); - } - - if (fpvar.comptype == GZIP_2) { - fits_set_compression_type (outfptr, GZIP_2, &stat); - } else { - fits_set_compression_type (outfptr, GZIP_1, &stat); - } - - fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); - - if (fpvar.no_dither) - fits_set_quantize_method(outfptr, -1, &stat); - else - fits_set_quantize_method(outfptr, fpvar.dither_method, &stat); - - fits_set_quantize_level (outfptr, fpvar.quantize_level, &stat); - fits_set_dither_offset(outfptr, fpvar.dither_offset, &stat); - fits_set_hcomp_scale (outfptr, fpvar.scale, &stat); - fits_set_hcomp_smooth (outfptr, fpvar.smooth, &stat); - - fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); - -/* - fits_set_compression_type (outfptr, BZIP2_1, &stat); - fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); - fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); -*/ -/* - fits_set_compression_type (outfptr, PLIO_1, &stat); - fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); - fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); -*/ -/* - if (bitpix == SHORT_IMG || bitpix == LONG_IMG) { - fits_set_compression_type (outfptr, NOCOMPRESS, &stat); - fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); - fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); - } -*/ - if (fpvar.outfile[0]) - fprintf(outreport,"\n"); - - /* delete the temporary file */ - if (rescale_flag) { - fits_delete_file (infptr, &stat); - tempfilename3[0] = '\0'; /* clear the temp filename */ - } - } else if ( (hdutype == BINARY_TBL) && fpvar.do_tables) { - - fits_get_num_rowsll(inputfptr, &nrows, &stat); - fits_get_num_cols(inputfptr, &ncols, &stat); -#if defined(_MSC_VER) - /* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */ - printf("\n File: %s, HDU %d, %d cols X %I64d rows\n", infits, extnum, ncols, nrows); -#elif (USE_LL_SUFFIX == 1) - printf("\n File: %s, HDU %d, %d cols X %lld rows\n", infits, extnum, ncols, nrows); -#else - printf("\n File: %s, HDU %d, %d cols X %ld rows\n", infits, extnum, ncols, nrows); -#endif - fp_test_table(inputfptr, outfptr, outfptr2, fpvar, &stat); - - } else { - fits_copy_hdu (inputfptr, outfptr, 0, &stat); - fits_copy_hdu (inputfptr, outfptr2, 0, &stat); - } - - fits_movrel_hdu (inputfptr, 1, NULL, &stat); - extnum++; - } - - - if (stat == END_OF_FILE) stat = 0; - - fits_close_file (outfptr2, &stat); - fits_close_file (outfptr, &stat); - fits_close_file (inputfptr, &stat); - - if (stat) { - fits_report_error (stderr, stat); - } - return(0); -} -/*--------------------------------------------------------------------------*/ -int fp_pack_hdu (fitsfile *infptr, fitsfile *outfptr, fpstate fpvar, - int *islossless, int *status) -{ - fitsfile *tempfile; - long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; - int stat=0, totpix=0, naxis=0, ii, hdutype, bitpix; - int tstatus, hdunum; - double bscale, rescale; - - char outfits[SZ_STR], fzalgor[FLEN_VALUE]; - long headstart, datastart, dataend, datasize; - double noisemin; - /* structure to hold image statistics (defined in fpack.h) */ - imgstats imagestats; - - if (*status) return(0); - - fits_get_hdu_type (infptr, &hdutype, &stat); - - if (hdutype == IMAGE_HDU) { - fits_get_img_param (infptr, 9, &bitpix, &naxis, naxes, &stat); - for (totpix=1, ii=0; ii < 9; ii++) totpix *= naxes[ii]; - } - - /* check directive keyword to see if this HDU should not be compressed */ - tstatus = 0; - if (!fits_read_key(infptr, TSTRING, "FZALGOR", fzalgor, NULL, &tstatus) ) { - if (!strcmp(fzalgor, "NONE") || !strcmp(fzalgor, "none") ) { - fits_copy_hdu (infptr, outfptr, 0, &stat); - - *status = stat; - return(0); - } - } - - /* =============================================================== */ - /* This block is only for binary table compression */ - if (hdutype == BINARY_TBL && fpvar.do_tables) { - - fits_get_hduaddr(infptr, &headstart, &datastart, &dataend, status); - datasize = dataend - datastart; - - if (datasize <= 2880) { - /* data is less than 1 FITS block in size, so don't compress */ - fits_copy_hdu (infptr, outfptr, 0, &stat); - } else { - fits_compress_table (infptr, outfptr, &stat); - } - - *status = stat; - return(0); - } - /* =============================================================== */ - - /* If this is not a non-null image HDU, just copy it verbatim */ - if (fits_is_compressed_image (infptr, &stat) || hdutype != IMAGE_HDU || - naxis == 0 || totpix == 0 || !fpvar.do_images) { - fits_copy_hdu (infptr, outfptr, 0, &stat); - - } else { /* remaining code deals only with IMAGE HDUs */ - - /* special case: rescale a scaled integer image to reduce noise? */ - if (fpvar.rescale_noise != 0. && bitpix > 0 && bitpix < LONGLONG_IMG) { - - tstatus = 0; - fits_read_key(infptr, TDOUBLE, "BSCALE", &bscale, 0, &tstatus); - if (tstatus == 0 && bscale != 1.0) { /* image must be scaled */ - - if (bitpix == LONG_IMG) - fp_i4stat(infptr, naxis, naxes, &imagestats, &stat); - else - fp_i2stat(infptr, naxis, naxes, &imagestats, &stat); - - /* use the minimum of the MAD 2nd, 3rd, and 5th order noise estimates */ - noisemin = imagestats.noise3; - if (imagestats.noise2 != 0. && imagestats.noise2 < noisemin) noisemin = imagestats.noise2; - if (imagestats.noise5 != 0. && imagestats.noise5 < noisemin) noisemin = imagestats.noise5; - - rescale = noisemin / fpvar.rescale_noise; - if (rescale > 1.0) { - - /* all the criteria are met, so create a temporary file that */ - /* contains a rescaled version of the image, in output directory */ - - /* create temporary file name */ - fits_file_name(outfptr, outfits, &stat); /* get the output file name */ - fp_tmpnam("Tmp3", outfits, tempfilename3); - - fits_create_file(&tempfile, tempfilename3, &stat); - - fits_get_hdu_num(infptr, &hdunum); - if (hdunum != 1) { - - /* the input hdu is an image extension, so create dummy primary */ - fits_create_img(tempfile, 8, 0, naxes, &stat); - } - - fits_copy_header(infptr, tempfile, &stat); /* copy the header */ - - /* rescale the data, so that it will compress more efficiently */ - if (bitpix == LONG_IMG) - fp_i4rescale(infptr, naxis, naxes, rescale, tempfile, &stat); - else - fp_i2rescale(infptr, naxis, naxes, rescale, tempfile, &stat); - - - /* scale the BSCALE keyword by the inverse factor */ - - bscale = bscale * rescale; - fits_update_key(tempfile, TDOUBLE, "BSCALE", &bscale, 0, &stat); - - /* rescan the header, to reset the actual scaling parameters */ - fits_set_hdustruc(tempfile, &stat); - - fits_img_compress (tempfile, outfptr, &stat); - fits_delete_file (tempfile, &stat); - tempfilename3[0] = '\0'; /* clear the temp filename */ - *islossless = 0; /* used a lossy compression method */ - - *status = stat; - return(0); - } - } - } - - /* if requested to do lossy compression of integer images (by */ - /* converting to float), then check if this HDU qualifies */ - if ( (bitpix > 0) && (fpvar.int_to_float != 0) ) { - - if (bitpix >= LONG_IMG) - fp_i4stat(infptr, naxis, naxes, &imagestats, &stat); - else - fp_i2stat(infptr, naxis, naxes, &imagestats, &stat); - - /* rescan the image header to reset scaling values (changed by fp_iNstat) */ - ffrhdu(infptr, &hdutype, &stat); - - /* use the minimum of the MAD 2nd, 3rd, and 5th order noise estimates */ - noisemin = imagestats.noise3; - if (imagestats.noise2 != 0. && imagestats.noise2 < noisemin) noisemin = imagestats.noise2; - if (imagestats.noise5 != 0. && imagestats.noise5 < noisemin) noisemin = imagestats.noise5; - - if ( (noisemin < (fpvar.n3ratio * fpvar.quantize_level) ) || - (imagestats.noise3 < fpvar.n3min)) { - - /* image contains too little noise to quantize effectively */ - fits_set_lossy_int (outfptr, 0, &stat); - - fits_get_hdu_num(infptr, &hdunum); - -printf(" HDU %d does not meet noise criteria to be quantized, so losslessly compressed.\n", hdunum); - - } else { - /* compressed image is not identical to original */ - *islossless = 0; - } - } - - /* finally, do the actual image compression */ - fits_img_compress (infptr, outfptr, &stat); - - if (bitpix < 0 || - (fpvar.comptype == HCOMPRESS_1 && fpvar.scale != 0.)) { - - /* compressed image is not identical to original */ - *islossless = 0; - } - } - - *status = stat; - return(0); -} - -/*--------------------------------------------------------------------------*/ -int fp_unpack_hdu (fitsfile *infptr, fitsfile *outfptr, fpstate fpvar, int *status) -{ - int hdutype, lval; - - if (*status > 0) return(0); - - fits_get_hdu_type (infptr, &hdutype, status); - - /* =============================================================== */ - /* This block is only for beta testing of binary table compression */ - if (hdutype == BINARY_TBL) { - - fits_read_key(infptr, TLOGICAL, "ZTABLE", &lval, NULL, status); - - if (*status == 0 && lval != 0) { - /* uncompress the table */ - fits_uncompress_table (infptr, outfptr, status); - } else { - if (*status == KEY_NO_EXIST) /* table is not compressed */ - *status = 0; - fits_copy_hdu (infptr, outfptr, 0, status); - } - - return(0); - /* =============================================================== */ - - } else if (fits_is_compressed_image (infptr, status)) { - /* uncompress the compressed image HDU */ - fits_img_decompress (infptr, outfptr, status); - } else { - /* not a compressed image HDU, so just copy it to the output */ - fits_copy_hdu (infptr, outfptr, 0, status); - } - - return(0); -} -/*--------------------------------------------------------------------------*/ -int fits_read_image_speed (fitsfile *infptr, float *whole_elapse, - float *whole_cpu, float *row_elapse, float *row_cpu, int *status) -{ - unsigned char *carray, cnull = 0; - short *sarray, snull=0; - int bitpix, naxis, anynull, *iarray, inull = 0; - long ii, naxes[9], fpixel[9]={1,1,1,1,1,1,1,1,1}, lpixel[9]={1,1,1,1,1,1,1,1,1}; - long inc[9]={1,1,1,1,1,1,1,1,1} ; - float *earray, enull = 0, filesize; - double *darray, dnull = 0; - - if (*status) return(*status); - - fits_get_img_param (infptr, 9, &bitpix, &naxis, naxes, status); - - if (naxis != 2)return(*status); - - lpixel[0] = naxes[0]; - lpixel[1] = naxes[1]; - - /* filesize in MB */ - filesize = (float) (naxes[0] * abs(bitpix) / 8000000. * naxes[1]); - - /* measure time required to read the raw image */ - fits_set_bscale(infptr, 1.0, 0.0, status); - *whole_elapse = 0.; - *whole_cpu = 0; - - if (bitpix == BYTE_IMG) { - carray = calloc(naxes[1]*naxes[0], sizeof(char)); - - /* remove any cached uncompressed tile - (dangerous to directly modify the structure!) */ - /* (infptr->Fptr)->tilerow = 0; */ - - marktime(status); - fits_read_subset(infptr, TBYTE, fpixel, lpixel, inc, &cnull, - carray, &anynull, status); - - /* get elapsped times */ - gettime(whole_elapse, whole_cpu, status); - - /* now read the image again, row by row */ - if (row_elapse) { - - /* remove any cached uncompressed tile - (dangerous to directly modify the structure!) */ - /* (infptr->Fptr)->tilerow = 0; */ - - marktime(status); - for (ii = 0; ii < naxes[1]; ii++) { - fpixel[1] = ii+1; - fits_read_pix(infptr, TBYTE, fpixel, naxes[0], &cnull, - carray, &anynull, status); - } - /* get elapsped times */ - gettime(row_elapse, row_cpu, status); - } - free(carray); - - } else if (bitpix == SHORT_IMG) { - sarray = calloc(naxes[0]*naxes[1], sizeof(short)); - - marktime(status); - fits_read_subset(infptr, TSHORT, fpixel, lpixel, inc, &snull, - sarray, &anynull, status); - - gettime(whole_elapse, whole_cpu, status); /* get elapsped times */ - - /* now read the image again, row by row */ - if (row_elapse) { - marktime(status); - for (ii = 0; ii < naxes[1]; ii++) { - - fpixel[1] = ii+1; - fits_read_pix(infptr, TSHORT, fpixel, naxes[0], &snull, - sarray, &anynull, status); - } - /* get elapsped times */ - gettime(row_elapse, row_cpu, status); - } - - free(sarray); - - } else if (bitpix == LONG_IMG) { - iarray = calloc(naxes[0]*naxes[1], sizeof(int)); - - marktime(status); - - fits_read_subset(infptr, TINT, fpixel, lpixel, inc, &inull, - iarray, &anynull, status); - - /* get elapsped times */ - gettime(whole_elapse, whole_cpu, status); - - - /* now read the image again, row by row */ - if (row_elapse) { - marktime(status); - for (ii = 0; ii < naxes[1]; ii++) { - fpixel[1] = ii+1; - fits_read_pix(infptr, TINT, fpixel, naxes[0], &inull, - iarray, &anynull, status); - } - /* get elapsped times */ - gettime(row_elapse, row_cpu, status); - } - - - free(iarray); - - } else if (bitpix == FLOAT_IMG) { - earray = calloc(naxes[1]*naxes[0], sizeof(float)); - - marktime(status); - - fits_read_subset(infptr, TFLOAT, fpixel, lpixel, inc, &enull, - earray, &anynull, status); - - /* get elapsped times */ - gettime(whole_elapse, whole_cpu, status); - - /* now read the image again, row by row */ - if (row_elapse) { - marktime(status); - for (ii = 0; ii < naxes[1]; ii++) { - fpixel[1] = ii+1; - fits_read_pix(infptr, TFLOAT, fpixel, naxes[0], &enull, - earray, &anynull, status); - } - /* get elapsped times */ - gettime(row_elapse, row_cpu, status); - } - - free(earray); - - } else if (bitpix == DOUBLE_IMG) { - darray = calloc(naxes[1]*naxes[0], sizeof(double)); - - marktime(status); - - fits_read_subset(infptr, TDOUBLE, fpixel, lpixel, inc, &dnull, - darray, &anynull, status); - - /* get elapsped times */ - gettime(whole_elapse, whole_cpu, status); - - /* now read the image again, row by row */ - if (row_elapse) { - marktime(status); - for (ii = 0; ii < naxes[1]; ii++) { - fpixel[1] = ii+1; - fits_read_pix(infptr, TDOUBLE, fpixel, naxes[0], &dnull, - darray, &anynull, status); - } - /* get elapsped times */ - gettime(row_elapse, row_cpu, status); - } - - free(darray); - } - - if (whole_elapse) *whole_elapse = *whole_elapse / filesize; - if (row_elapse) *row_elapse = *row_elapse / filesize; - if (whole_cpu) *whole_cpu = *whole_cpu / filesize; - if (row_cpu) *row_cpu = *row_cpu / filesize; - - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fp_test_hdu (fitsfile *infptr, fitsfile *outfptr, fitsfile *outfptr2, - fpstate fpvar, int *status) -{ - /* This routine is only used for performance testing of image HDUs. */ - /* Use fp_test_table for testing binary table HDUs. */ - - int stat = 0, hdutype, comptype; - char ctype[20], lossless[4]; - long headstart, datastart, dataend; - float origdata = 0., compressdata = 0.; - float compratio = 0., packcpu = 0., unpackcpu = 0.; - float elapse, whole_elapse, row_elapse, whole_cpu, row_cpu; - unsigned long datasum1, datasum2, hdusum; - - if (*status) return(0); - - origdata = 0; - compressdata = 0; - compratio = 0.; - lossless[0] = '\0'; - - fits_get_compression_type(outfptr, &comptype, &stat); - if (comptype == RICE_1) - strcpy(ctype, "RICE"); - else if (comptype == GZIP_1) - strcpy(ctype, "GZIP1"); - else if (comptype == GZIP_2) - strcpy(ctype, "GZIP2");/* - else if (comptype == BZIP2_1) - strcpy(ctype, "BZIP2"); -*/ - else if (comptype == PLIO_1) - strcpy(ctype, "PLIO"); - else if (comptype == HCOMPRESS_1) - strcpy(ctype, "HCOMP"); - else if (comptype == NOCOMPRESS) - strcpy(ctype, "NONE"); - else { - fp_msg ("Error: unsupported image compression type "); - *status = DATA_COMPRESSION_ERR; - return(0); - } - - /* -------------- COMPRESS the image ------------------ */ - - marktime(&stat); - - fits_img_compress (infptr, outfptr, &stat); - - /* get elapsped times */ - gettime(&elapse, &packcpu, &stat); - - /* get elapsed and cpu times need to read the compressed image */ - fits_read_image_speed (outfptr, &whole_elapse, &whole_cpu, - &row_elapse, &row_cpu, &stat); - - if (!stat) { - - /* -------------- UNCOMPRESS the image ------------------ */ - - /* remove any cached uncompressed tile - (dangerous to directly modify the structure!) */ - /* (outfptr->Fptr)->tilerow = 0; */ - marktime(&stat); - - fits_img_decompress (outfptr, outfptr2, &stat); - - /* get elapsped times */ - gettime(&elapse, &unpackcpu, &stat); - - /* ----------------------------------------------------- */ - - - /* get sizes of original and compressed images */ - - fits_get_hduaddr(infptr, &headstart, &datastart, &dataend, &stat); - origdata = (float) ((dataend - datastart)/1000000.); - - fits_get_hduaddr(outfptr, &headstart, &datastart, &dataend, &stat); - compressdata = (float) ((dataend - datastart)/1000000.); - - if (compressdata != 0) - compratio = (float) origdata / (float) compressdata; - - /* is this uncompressed image identical to the original? */ - - fits_get_chksum(infptr, &datasum1, &hdusum, &stat); - fits_get_chksum(outfptr2, &datasum2, &hdusum, &stat); - - if ( datasum1 == datasum2) { - strcpy(lossless, "Yes"); - } else { - strcpy(lossless, "No"); - } - - printf(" %-5s %6.2f %7.2f ->%7.2f %7.2f %7.2f %s %5.3f %5.3f %5.3f %5.3f\n", - ctype, compratio, origdata, compressdata, - packcpu, unpackcpu, lossless, whole_elapse, whole_cpu, - row_elapse, row_cpu); - - - if (fpvar.outfile[0]) { - fprintf(outreport," %6.3f %5.2f %5.2f %s %7.3f %7.3f %7.3f %7.3f", - compratio, packcpu, unpackcpu, lossless, whole_elapse, whole_cpu, - row_elapse, row_cpu); - } - - /* delete the output HDUs to concerve disk space */ - - fits_delete_hdu(outfptr, &hdutype, &stat); - fits_delete_hdu(outfptr2, &hdutype, &stat); - - } else { - printf(" %-5s (unable to compress image)\n", ctype); - } - - /* try to recover from any compression errors */ - if (stat == DATA_COMPRESSION_ERR) stat = 0; - - *status = stat; - return(0); -} -/*--------------------------------------------------------------------------*/ -int fp_test_table (fitsfile *infptr, fitsfile *outfptr, fitsfile *outfptr2, - fpstate fpvar, int *status) -{ -/* this routine is for performance testing of the table compression methods */ - - int stat = 0, hdutype, tstatus = 0; - char fzalgor[FLEN_VALUE]; - LONGLONG headstart, datastart, dataend; - float elapse, cpu; - - if (*status) return(0); - - /* check directive keyword to see if this HDU should not be compressed */ - if (!fits_read_key(infptr, TSTRING, "FZALGOR", fzalgor, NULL, &tstatus) ) { - if (!strcmp(fzalgor, "NONE") || !strcmp(fzalgor, "none")) { - return(0); - } - } - - fits_get_hduaddrll(infptr, &headstart, &datastart, &dataend, status); - - /* can't compress small tables with less than 2880 bytes of data */ - if (dataend - datastart <= 2880) { - return(0); - } - - marktime(&stat); - stat= -999; /* set special flag value */ - fits_compress_table (infptr, outfptr, &stat); - - /* get elapsped times */ - gettime(&elapse, &cpu, &stat); - - fits_delete_hdu(outfptr, &hdutype, &stat); - - printf("\nElapsed time = %f, cpu = %f\n", elapse, cpu); - - fits_report_error (stderr, stat); - - return(0); -} -/*--------------------------------------------------------------------------*/ -int marktime(int *status) -{ -#if defined(unix) || defined(__unix__) || defined(__unix) - struct timeval tv; -/* struct timezone tz; */ - -/* gettimeofday (&tv, &tz); */ - gettimeofday (&tv, NULL); - - startsec = tv.tv_sec; - startmilli = tv.tv_usec/1000; - - scpu = clock(); -#else -/* don't support high timing precision on Windows machines */ - startsec = 0; - startmilli = 0; - - scpu = clock(); -#endif - return( *status ); -} -/*--------------------------------------------------------------------------*/ -int gettime(float *elapse, float *elapscpu, int *status) -{ -#if defined(unix) || defined(__unix__) || defined(__unix) - struct timeval tv; -/* struct timezone tz; */ - int stopmilli; - long stopsec; - -/* gettimeofday (&tv, &tz); */ - gettimeofday (&tv, NULL); - ecpu = clock(); - - stopmilli = tv.tv_usec/1000; - stopsec = tv.tv_sec; - - *elapse = (stopsec - startsec) + (stopmilli - startmilli)/1000.; - *elapscpu = (ecpu - scpu) * 1.0 / CLOCKTICKS; -/* -printf(" (start: %ld + %d), stop: (%ld + %d) elapse: %f\n ", -startsec,startmilli,stopsec, stopmilli, *elapse); -*/ -#else -/* set the elapsed time the same as the CPU time on Windows machines */ - *elapscpu = (float) ((ecpu - scpu) * 1.0 / CLOCKTICKS); - *elapse = *elapscpu; -#endif - return( *status ); -} -/*--------------------------------------------------------------------------*/ -int fp_i2stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status) -{ -/* - read the central XSAMPLE by YSAMPLE region of pixels in the int*2 image, - and then compute basic statistics: min, max, mean, sigma, mean diff, etc. -*/ - - long fpixel[9] = {1,1,1,1,1,1,1,1,1}; - long lpixel[9] = {1,1,1,1,1,1,1,1,1}; - long inc[9] = {1,1,1,1,1,1,1,1,1}; - long i1, i2, npix, ngood, nx, ny; - short *intarray, minvalue, maxvalue, nullvalue; - int anynul, tstatus, checknull = 1; - double mean, sigma, noise1, noise2, noise3, noise5; - - /* select the middle XSAMPLE by YSAMPLE area of the image */ - i1 = naxes[0]/2 - (XSAMPLE/2 - 1); - i2 = naxes[0]/2 + (XSAMPLE/2); - if (i1 < 1) i1 = 1; - if (i2 > naxes[0]) i2 = naxes[0]; - fpixel[0] = i1; - lpixel[0] = i2; - nx = i2 - i1 +1; - - if (naxis > 1) { - i1 = naxes[1]/2 - (YSAMPLE/2 - 1); - i2 = naxes[1]/2 + (YSAMPLE/2); - if (i1 < 1) i1 = 1; - if (i2 > naxes[1]) i2 = naxes[1]; - fpixel[1] = i1; - lpixel[1] = i2; - } - ny = i2 - i1 +1; - - npix = nx * ny; - - /* if there are higher dimensions, read the middle plane of the cube */ - if (naxis > 2) { - fpixel[2] = naxes[2]/2 + 1; - lpixel[2] = naxes[2]/2 + 1; - } - - intarray = calloc(npix, sizeof(short)); - if (!intarray) { - *status = MEMORY_ALLOCATION; - return(*status); - } - - /* turn off any scaling of the integer pixel values */ - fits_set_bscale(infptr, 1.0, 0.0, status); - - fits_read_subset_sht(infptr, 0, naxis, naxes, fpixel, lpixel, inc, - 0, intarray, &anynul, status); - - /* read the null value keyword (BLANK) if present */ - tstatus = 0; - fits_read_key(infptr, TSHORT, "BLANK", &nullvalue, 0, &tstatus); - if (tstatus) { - nullvalue = 0; - checknull = 0; - } - - /* compute statistics of the image */ - - fits_img_stats_short(intarray, nx, ny, checknull, nullvalue, - &ngood, &minvalue, &maxvalue, &mean, &sigma, &noise1, &noise2, &noise3, &noise5, status); - - imagestats->n_nulls = npix - ngood; - imagestats->minval = minvalue; - imagestats->maxval = maxvalue; - imagestats->mean = mean; - imagestats->sigma = sigma; - imagestats->noise1 = noise1; - imagestats->noise2 = noise2; - imagestats->noise3 = noise3; - imagestats->noise5 = noise5; - - free(intarray); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fp_i4stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status) -{ -/* - read the central XSAMPLE by YSAMPLE region of pixels in the int*2 image, - and then compute basic statistics: min, max, mean, sigma, mean diff, etc. -*/ - - long fpixel[9] = {1,1,1,1,1,1,1,1,1}; - long lpixel[9] = {1,1,1,1,1,1,1,1,1}; - long inc[9] = {1,1,1,1,1,1,1,1,1}; - long i1, i2, npix, ngood, nx, ny; - int *intarray, minvalue, maxvalue, nullvalue; - int anynul, tstatus, checknull = 1; - double mean, sigma, noise1, noise2, noise3, noise5; - - /* select the middle XSAMPLE by YSAMPLE area of the image */ - i1 = naxes[0]/2 - (XSAMPLE/2 - 1); - i2 = naxes[0]/2 + (XSAMPLE/2); - if (i1 < 1) i1 = 1; - if (i2 > naxes[0]) i2 = naxes[0]; - fpixel[0] = i1; - lpixel[0] = i2; - nx = i2 - i1 +1; - - if (naxis > 1) { - i1 = naxes[1]/2 - (YSAMPLE/2 - 1); - i2 = naxes[1]/2 + (YSAMPLE/2); - if (i1 < 1) i1 = 1; - if (i2 > naxes[1]) i2 = naxes[1]; - fpixel[1] = i1; - lpixel[1] = i2; - } - ny = i2 - i1 +1; - - npix = nx * ny; - - /* if there are higher dimensions, read the middle plane of the cube */ - if (naxis > 2) { - fpixel[2] = naxes[2]/2 + 1; - lpixel[2] = naxes[2]/2 + 1; - } - - intarray = calloc(npix, sizeof(int)); - if (!intarray) { - *status = MEMORY_ALLOCATION; - return(*status); - } - - /* turn off any scaling of the integer pixel values */ - fits_set_bscale(infptr, 1.0, 0.0, status); - - fits_read_subset_int(infptr, 0, naxis, naxes, fpixel, lpixel, inc, - 0, intarray, &anynul, status); - - /* read the null value keyword (BLANK) if present */ - tstatus = 0; - fits_read_key(infptr, TINT, "BLANK", &nullvalue, 0, &tstatus); - if (tstatus) { - nullvalue = 0; - checknull = 0; - } - - /* compute statistics of the image */ - - fits_img_stats_int(intarray, nx, ny, checknull, nullvalue, - &ngood, &minvalue, &maxvalue, &mean, &sigma, &noise1, &noise2, &noise3, &noise5, status); - - imagestats->n_nulls = npix - ngood; - imagestats->minval = minvalue; - imagestats->maxval = maxvalue; - imagestats->mean = mean; - imagestats->sigma = sigma; - imagestats->noise1 = noise1; - imagestats->noise2 = noise2; - imagestats->noise3 = noise3; - imagestats->noise5 = noise5; - - free(intarray); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fp_r4stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status) -{ -/* - read the central XSAMPLE by YSAMPLE region of pixels in the int*2 image, - and then compute basic statistics: min, max, mean, sigma, mean diff, etc. -*/ - - long fpixel[9] = {1,1,1,1,1,1,1,1,1}; - long lpixel[9] = {1,1,1,1,1,1,1,1,1}; - long inc[9] = {1,1,1,1,1,1,1,1,1}; - long i1, i2, npix, ngood, nx, ny; - float *array, minvalue, maxvalue, nullvalue = FLOATNULLVALUE; - int anynul,checknull = 1; - double mean, sigma, noise1, noise2, noise3, noise5; - - /* select the middle XSAMPLE by YSAMPLE area of the image */ - i1 = naxes[0]/2 - (XSAMPLE/2 - 1); - i2 = naxes[0]/2 + (XSAMPLE/2); - if (i1 < 1) i1 = 1; - if (i2 > naxes[0]) i2 = naxes[0]; - fpixel[0] = i1; - lpixel[0] = i2; - nx = i2 - i1 +1; - - if (naxis > 1) { - i1 = naxes[1]/2 - (YSAMPLE/2 - 1); - i2 = naxes[1]/2 + (YSAMPLE/2); - if (i1 < 1) i1 = 1; - if (i2 > naxes[1]) i2 = naxes[1]; - fpixel[1] = i1; - lpixel[1] = i2; - } - ny = i2 - i1 +1; - - npix = nx * ny; - - /* if there are higher dimensions, read the middle plane of the cube */ - if (naxis > 2) { - fpixel[2] = naxes[2]/2 + 1; - lpixel[2] = naxes[2]/2 + 1; - } - - array = calloc(npix, sizeof(float)); - if (!array) { - *status = MEMORY_ALLOCATION; - return(*status); - } - - fits_read_subset_flt(infptr, 0, naxis, naxes, fpixel, lpixel, inc, - nullvalue, array, &anynul, status); - - /* are there any null values in the array? */ - if (!anynul) { - nullvalue = 0.; - checknull = 0; - } - - /* compute statistics of the image */ - - fits_img_stats_float(array, nx, ny, checknull, nullvalue, - &ngood, &minvalue, &maxvalue, &mean, &sigma, &noise1, &noise2, &noise3, &noise5, status); - - imagestats->n_nulls = npix - ngood; - imagestats->minval = minvalue; - imagestats->maxval = maxvalue; - imagestats->mean = mean; - imagestats->sigma = sigma; - imagestats->noise1 = noise1; - imagestats->noise2 = noise2; - imagestats->noise3 = noise3; - imagestats->noise5 = noise5; - - free(array); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fp_i2rescale(fitsfile *infptr, int naxis, long *naxes, double rescale, - fitsfile *outfptr, int *status) -{ -/* - divide the integer pixel values in the input file by rescale, - and write back out to the output file.. -*/ - - long ii, jj, nelem = 1, nx, ny; - short *intarray, nullvalue; - int anynul, tstatus, checknull = 1; - - nx = naxes[0]; - ny = 1; - - for (ii = 1; ii < naxis; ii++) { - ny = ny * naxes[ii]; - } - - intarray = calloc(nx, sizeof(short)); - if (!intarray) { - *status = MEMORY_ALLOCATION; - return(*status); - } - - /* read the null value keyword (BLANK) if present */ - tstatus = 0; - fits_read_key(infptr, TSHORT, "BLANK", &nullvalue, 0, &tstatus); - if (tstatus) { - checknull = 0; - } - - /* turn off any scaling of the integer pixel values */ - fits_set_bscale(infptr, 1.0, 0.0, status); - fits_set_bscale(outfptr, 1.0, 0.0, status); - - for (ii = 0; ii < ny; ii++) { - - fits_read_img_sht(infptr, 1, nelem, nx, - 0, intarray, &anynul, status); - - if (checknull) { - for (jj = 0; jj < nx; jj++) { - if (intarray[jj] != nullvalue) - intarray[jj] = NSHRT( (intarray[jj] / rescale) ); - } - } else { - for (jj = 0; jj < nx; jj++) - intarray[jj] = NSHRT( (intarray[jj] / rescale) ); - } - - fits_write_img_sht(outfptr, 1, nelem, nx, intarray, status); - - nelem += nx; - } - - free(intarray); - return(*status); -} -/*--------------------------------------------------------------------------*/ -int fp_i4rescale(fitsfile *infptr, int naxis, long *naxes, double rescale, - fitsfile *outfptr, int *status) -{ -/* - divide the integer pixel values in the input file by rescale, - and write back out to the output file.. -*/ - - long ii, jj, nelem = 1, nx, ny; - int *intarray, nullvalue; - int anynul, tstatus, checknull = 1; - - nx = naxes[0]; - ny = 1; - - for (ii = 1; ii < naxis; ii++) { - ny = ny * naxes[ii]; - } - - intarray = calloc(nx, sizeof(int)); - if (!intarray) { - *status = MEMORY_ALLOCATION; - return(*status); - } - - /* read the null value keyword (BLANK) if present */ - tstatus = 0; - fits_read_key(infptr, TINT, "BLANK", &nullvalue, 0, &tstatus); - if (tstatus) { - checknull = 0; - } - - /* turn off any scaling of the integer pixel values */ - fits_set_bscale(infptr, 1.0, 0.0, status); - fits_set_bscale(outfptr, 1.0, 0.0, status); - - for (ii = 0; ii < ny; ii++) { - - fits_read_img_int(infptr, 1, nelem, nx, - 0, intarray, &anynul, status); - - if (checknull) { - for (jj = 0; jj < nx; jj++) { - if (intarray[jj] != nullvalue) - intarray[jj] = NINT( (intarray[jj] / rescale) ); - } - } else { - for (jj = 0; jj < nx; jj++) - intarray[jj] = NINT( (intarray[jj] / rescale) ); - } - - fits_write_img_int(outfptr, 1, nelem, nx, intarray, status); - - nelem += nx; - } - - free(intarray); - return(*status); -} -/* ======================================================================== - * Signal and error handler. - */ -void abort_fpack(int sig) -{ - /* clean up by deleting temporary files */ - - if (tempfilename[0]) { - remove(tempfilename); - } - if (tempfilename2[0]) { - remove(tempfilename2); - } - if (tempfilename3[0]) { - remove(tempfilename3); - } - exit(-1); -} diff --git a/src/external/OpenGR/3rdparty/cfitsio/funpack.c b/src/external/OpenGR/3rdparty/cfitsio/funpack.c deleted file mode 100644 index 8f8ad30ac..000000000 --- a/src/external/OpenGR/3rdparty/cfitsio/funpack.c +++ /dev/null @@ -1,168 +0,0 @@ -/* FUNPACK - * R. Seaman, NOAO - * uses fits_img_compress by W. Pence, HEASARC - */ - -#include "fitsio.h" -#include "fpack.h" - -int main (int argc, char *argv[]) -{ - fpstate fpvar; - - if (argc <= 1) { fu_usage (); fu_hint (); exit (-1); } - - fp_init (&fpvar); - fu_get_param (argc, argv, &fpvar); - - if (fpvar.listonly) { - fp_list (argc, argv, fpvar); - - } else { - fp_preflight (argc, argv, FUNPACK, &fpvar); - fp_loop (argc, argv, FUNPACK, fpvar); - } - - exit (0); -} - -int fu_get_param (int argc, char *argv[], fpstate *fpptr) -{ - int iarg; - char tile[SZ_STR]; - - if (fpptr->initialized != FP_INIT_MAGIC) { - fp_msg ("Error: internal initialization error\n"); exit (-1); - } - - tile[0] = 0; - - /* by default, .fz suffix characters to be deleted from compressed file */ - fpptr->delete_suffix = 1; - - /* flags must come first and be separately specified - */ - for (iarg = 1; iarg < argc; iarg++) { - if (argv[iarg][0] == '-' && strlen (argv[iarg]) == 2) { - - if (argv[iarg][1] == 'F') { - fpptr->clobber++; - fpptr->delete_suffix = 0; /* no suffix in this case */ - - } else if (argv[iarg][1] == 'D') { - fpptr->delete_input++; - - } else if (argv[iarg][1] == 'P') { - if (++iarg >= argc) { - fu_usage (); fu_hint (); exit (-1); - } else - strncpy (fpptr->prefix, argv[iarg], SZ_STR); - - } else if (argv[iarg][1] == 'E') { - if (++iarg >= argc) { - fu_usage (); fu_hint (); exit (-1); - } else - strncpy (fpptr->extname, argv[iarg], SZ_STR); - - } else if (argv[iarg][1] == 'S') { - fpptr->to_stdout++; - - } else if (argv[iarg][1] == 'L') { - fpptr->listonly++; - - } else if (argv[iarg][1] == 'C') { - fpptr->do_checksums = 0; - - } else if (argv[iarg][1] == 'H') { - fu_help (); exit (0); - - } else if (argv[iarg][1] == 'V') { - fp_version (); exit (0); - - } else if (argv[iarg][1] == 'Z') { - fpptr->do_gzip_file++; - - } else if (argv[iarg][1] == 'v') { - fpptr->verbose = 1; - - } else if (argv[iarg][1] == 'O') { - if (++iarg >= argc) { - fu_usage (); fu_hint (); exit (-1); - } else - strncpy (fpptr->outfile, argv[iarg], SZ_STR); - - } else { - fp_msg ("Error: unknown command line flag `"); - fp_msg (argv[iarg]); fp_msg ("'\n"); - fu_usage (); fu_hint (); exit (-1); - } - - } else - break; - } - - if (fpptr->extname[0] && (fpptr->clobber || fpptr->delete_input)) { - fp_msg ("Error: -E option may not be used with -F or -D\n"); - fu_usage (); exit (-1); - } - - if (fpptr->to_stdout && (fpptr->outfile[0] || fpptr->prefix[0]) ) { - - fp_msg ("Error: -S option may not be used with -P or -O\n"); - fu_usage (); exit (-1); - } - - if (fpptr->outfile[0] && fpptr->prefix[0] ) { - fp_msg ("Error: -P and -O options may not be used together\n"); - fu_usage (); exit (-1); - } - - if (iarg >= argc) { - fp_msg ("Error: no FITS files to uncompress\n"); - fu_usage (); exit (-1); - } else - fpptr->firstfile = iarg; - - return(0); -} - -int fu_usage (void) -{ - fp_msg ("usage: funpack [-E ] [-P

] [-O ] [-Z] -v \n");
-        fp_msg ("more:   [-F] [-D] [-S] [-L] [-C] [-H] [-V] \n");
-	return(0);
-}
-
-int fu_hint (void)
-{
-	fp_msg ("      `funpack -H' for help\n");
-	return(0);
-}
-
-int fu_help (void)
-{
-fp_msg ("funpack, decompress fpacked files.  Version ");
-fp_version ();
-fu_usage ();
-fp_msg ("\n");
-
-fp_msg ("Flags must be separate and appear before filenames:\n");
-fp_msg (" -E  Unpack only the list of HDU names or numbers in the file.\n");
-fp_msg (" -P 
    Prepend 
 to create new output filenames.\n");
-fp_msg (" -O    Specify full output file name.\n");
-fp_msg (" -Z          Recompress the output file with host GZIP program.\n");
-fp_msg (" -F          Overwrite input file by output file with same name.\n");
-fp_msg (" -D          Delete input file after writing output.\n");
-fp_msg (" -S          Output uncompressed file to STDOUT file stream.\n");
-fp_msg (" -L          List contents, files unchanged.\n");
-
-fp_msg (" -C          Don't update FITS checksum keywords.\n");
-
-fp_msg (" -v          Verbose mode; list each file as it is processed.\n");
-fp_msg (" -H          Show this message.\n");
-fp_msg (" -V          Show version number.\n");
-
-fp_msg (" \n       FITS files to unpack; enter '-' (a hyphen) to read from stdin.\n");
-fp_msg (" Refer to the fpack User's Guide for more extensive help.\n");
-	return(0);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcol.c b/src/external/OpenGR/3rdparty/cfitsio/getcol.c
deleted file mode 100644
index fbeed2054..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcol.c
+++ /dev/null
@@ -1,1053 +0,0 @@
-
-/*  This file, getcol.c, contains routines that read data elements from    */
-/*  a FITS image or table.  There are generic datatype routines.           */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffgpxv( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  datatype,    /* I - datatype of the value                   */
-            long *firstpix,   /* I - coord of first pixel to read (1s based) */
-            LONGLONG nelem,   /* I - number of values to read                */
-            void *nulval,     /* I - value for undefined pixels              */
-            void *array,      /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. The datatype of the
-  input array is defined by the 2nd argument.  Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    LONGLONG tfirstpix[99];
-    int naxis, ii;
-
-    if (*status > 0 || nelem == 0)   /* inherit input status value if > 0 */
-        return(*status);
-
-    /* get the size of the image */
-    ffgidm(fptr, &naxis, status);
-    
-    for (ii=0; ii < naxis; ii++)
-       tfirstpix[ii] = firstpix[ii];
-
-    ffgpxvll(fptr, datatype, tfirstpix, nelem, nulval, array, anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpxvll( fitsfile *fptr, /* I - FITS file pointer                       */
-            int  datatype,    /* I - datatype of the value                   */
-            LONGLONG *firstpix, /* I - coord of first pixel to read (1s based) */
-            LONGLONG nelem,   /* I - number of values to read                */
-            void *nulval,     /* I - value for undefined pixels              */
-            void *array,      /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. The datatype of the
-  input array is defined by the 2nd argument.  Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    int naxis, ii;
-    char cdummy;
-    int nullcheck = 1;
-    LONGLONG naxes[9], trc[9]= {1,1,1,1,1,1,1,1,1};
-    long inc[9]= {1,1,1,1,1,1,1,1,1};
-    LONGLONG dimsize = 1, firstelem;
-
-    if (*status > 0 || nelem == 0)   /* inherit input status value if > 0 */
-        return(*status);
-
-    /* get the size of the image */
-    ffgidm(fptr, &naxis, status);
-
-    ffgiszll(fptr, 9, naxes, status);
-
-    if (naxis == 0 || naxes[0] == 0) {
-       *status = BAD_DIMEN;
-       return(*status);
-    }
-
-    /* calculate the position of the first element in the array */
-    firstelem = 0;
-    for (ii=0; ii < naxis; ii++)
-    {
-        firstelem += ((firstpix[ii] - 1) * dimsize);
-        dimsize *= naxes[ii];
-        trc[ii] = firstpix[ii];
-    }
-    firstelem++;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        /* test for special case of reading an integral number of */
-        /* rows in a 2D or 3D image (which includes reading the whole image */
-
-	if (naxis > 1 && naxis < 4 && firstpix[0] == 1 &&
-            (nelem / naxes[0]) * naxes[0] == nelem) {
-
-                /* calculate coordinate of last pixel */
-		trc[0] = naxes[0];  /* reading whole rows */
-		trc[1] = firstpix[1] + (nelem / naxes[0] - 1);
-                while (trc[1] > naxes[1])  {
-		    trc[1] = trc[1] - naxes[1];
-		    trc[2] = trc[2] + 1;  /* increment to next plane of cube */
-                }
-
-                fits_read_compressed_img(fptr, datatype, firstpix, trc, inc,
-                   1, nulval, array, NULL, anynul, status);
-
-        } else {
-
-                fits_read_compressed_pixels(fptr, datatype, firstelem,
-                   nelem, nullcheck, nulval, array, NULL, anynul, status);
-        }
-
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (datatype == TBYTE)
-    {
-      if (nulval == 0)
-        ffgclb(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
-               (unsigned char *) array, &cdummy, anynul, status);
-      else
-        ffgclb(fptr, 2, 1, firstelem, nelem, 1, 1, *(unsigned char *) nulval,
-               (unsigned char *) array, &cdummy, anynul, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-      if (nulval == 0)
-        ffgclsb(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
-               (signed char *) array, &cdummy, anynul, status);
-      else
-        ffgclsb(fptr, 2, 1, firstelem, nelem, 1, 1, *(signed char *) nulval,
-               (signed char *) array, &cdummy, anynul, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-      if (nulval == 0)
-        ffgclui(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
-               (unsigned short *) array, &cdummy, anynul, status);
-      else
-        ffgclui(fptr, 2, 1, firstelem, nelem, 1, 1, *(unsigned short *) nulval,
-               (unsigned short *) array, &cdummy, anynul, status);
-    }
-    else if (datatype == TSHORT)
-    {
-      if (nulval == 0)
-        ffgcli(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
-               (short *) array, &cdummy, anynul, status);
-      else
-        ffgcli(fptr, 2, 1, firstelem, nelem, 1, 1, *(short *) nulval,
-               (short *) array, &cdummy, anynul, status);
-    }
-    else if (datatype == TUINT)
-    {
-      if (nulval == 0)
-        ffgcluk(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
-               (unsigned int *) array, &cdummy, anynul, status);
-      else
-        ffgcluk(fptr, 2, 1, firstelem, nelem, 1, 1, *(unsigned int *) nulval,
-               (unsigned int *) array, &cdummy, anynul, status);
-    }
-    else if (datatype == TINT)
-    {
-      if (nulval == 0)
-        ffgclk(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
-               (int *) array, &cdummy, anynul, status);
-      else
-        ffgclk(fptr, 2, 1, firstelem, nelem, 1, 1, *(int *) nulval,
-               (int *) array, &cdummy, anynul, status);
-    }
-    else if (datatype == TULONG)
-    {
-      if (nulval == 0)
-        ffgcluj(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
-               (unsigned long *) array, &cdummy, anynul, status);
-      else
-        ffgcluj(fptr, 2, 1, firstelem, nelem, 1, 1, *(unsigned long *) nulval,
-               (unsigned long *) array, &cdummy, anynul, status);
-    }
-    else if (datatype == TLONG)
-    {
-      if (nulval == 0)
-        ffgclj(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
-               (long *) array, &cdummy, anynul, status);
-      else
-        ffgclj(fptr, 2, 1, firstelem, nelem, 1, 1, *(long *) nulval,
-               (long *) array, &cdummy, anynul, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-      if (nulval == 0)
-        ffgcljj(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
-               (LONGLONG *) array, &cdummy, anynul, status);
-      else
-        ffgcljj(fptr, 2, 1, firstelem, nelem, 1, 1, *(LONGLONG *) nulval,
-               (LONGLONG *) array, &cdummy, anynul, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      if (nulval == 0)
-        ffgcle(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
-               (float *) array, &cdummy, anynul, status);
-      else
-        ffgcle(fptr, 2, 1, firstelem, nelem, 1, 1, *(float *) nulval,
-               (float *) array, &cdummy, anynul, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-      if (nulval == 0)
-        ffgcld(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
-               (double *) array, &cdummy, anynul, status);
-      else
-        ffgcld(fptr, 2, 1, firstelem, nelem, 1, 1, *(double *) nulval,
-               (double *) array, &cdummy, anynul, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpxf( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  datatype,    /* I - datatype of the value                   */
-            long *firstpix,   /* I - coord of first pixel to read (1s based) */
-            LONGLONG nelem,       /* I - number of values to read            */
-            void *array,      /* O - array of values that are returned       */
-            char *nullarray,  /* O - returned array of null value flags      */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. The datatype of the
-  input array is defined by the 2nd argument.  Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  The nullarray values will = 1 if the corresponding array value is null.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    LONGLONG tfirstpix[99];
-    int naxis, ii;
-
-    if (*status > 0 || nelem == 0)   /* inherit input status value if > 0 */
-        return(*status);
-
-    /* get the size of the image */
-    ffgidm(fptr, &naxis, status);
-
-    for (ii=0; ii < naxis; ii++)
-       tfirstpix[ii] = firstpix[ii];
-
-    ffgpxfll(fptr, datatype, tfirstpix, nelem, array, nullarray, anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpxfll( fitsfile *fptr, /* I - FITS file pointer                       */
-            int  datatype,    /* I - datatype of the value                   */
-            LONGLONG *firstpix, /* I - coord of first pixel to read (1s based) */
-            LONGLONG nelem,       /* I - number of values to read              */
-            void *array,      /* O - array of values that are returned       */
-            char *nullarray,  /* O - returned array of null value flags      */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. The datatype of the
-  input array is defined by the 2nd argument.  Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  The nullarray values will = 1 if the corresponding array value is null.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    int naxis, ii;
-    int nullcheck = 2;
-    LONGLONG naxes[9];
-    LONGLONG dimsize = 1, firstelem;
-
-    if (*status > 0 || nelem == 0)   /* inherit input status value if > 0 */
-        return(*status);
-
-    /* get the size of the image */
-    ffgidm(fptr, &naxis, status);
-    ffgiszll(fptr, 9, naxes, status);
-
-    /* calculate the position of the first element in the array */
-    firstelem = 0;
-    for (ii=0; ii < naxis; ii++)
-    {
-        firstelem += ((firstpix[ii] - 1) * dimsize);
-        dimsize *= naxes[ii];
-    }
-    firstelem++;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_read_compressed_pixels(fptr, datatype, firstelem, nelem,
-            nullcheck, NULL, array, nullarray, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (datatype == TBYTE)
-    {
-        ffgclb(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
-               (unsigned char *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-        ffgclsb(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
-               (signed char *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-        ffgclui(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
-               (unsigned short *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TSHORT)
-    {
-        ffgcli(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
-               (short *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TUINT)
-    {
-        ffgcluk(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
-               (unsigned int *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TINT)
-    {
-        ffgclk(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
-               (int *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TULONG)
-    {
-        ffgcluj(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
-               (unsigned long *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TLONG)
-    {
-        ffgclj(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
-               (long *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-        ffgcljj(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
-               (LONGLONG *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-        ffgcle(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
-               (float *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-        ffgcld(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
-               (double *) array, nullarray, anynul, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsv(  fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  datatype,    /* I - datatype of the value                   */
-            long *blc,        /* I - 'bottom left corner' of the subsection  */
-            long *trc ,       /* I - 'top right corner' of the subsection    */
-            long *inc,        /* I - increment to be applied in each dim.    */
-            void *nulval,     /* I - value for undefined pixels              */
-            void *array,      /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an section of values from the primary array. The datatype of the
-  input array is defined by the 2nd argument.  Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    int naxis, ii;
-    long naxes[9];
-    LONGLONG nelem = 1;
-
-    if (*status > 0)   /* inherit input status value if > 0 */
-        return(*status);
-
-    /* get the size of the image */
-    ffgidm(fptr, &naxis, status);
-    ffgisz(fptr, 9, naxes, status);
-
-    /* test for the important special case where we are reading the whole image */
-    /* this is only useful for images that are not tile-compressed */
-    if (!fits_is_compressed_image(fptr, status)) {
-        for (ii = 0; ii < naxis; ii++) {
-            if (inc[ii] != 1 || blc[ii] !=1 || trc[ii] != naxes[ii])
-                break;
-
-            nelem = nelem * naxes[ii];
-        }
-
-        if (ii == naxis) {
-            /* read the whole image more efficiently */
-            ffgpxv(fptr, datatype, blc, nelem, nulval, array, anynul, status);
-            return(*status);
-        }
-    }
-
-    if (datatype == TBYTE)
-    {
-      if (nulval == 0)
-        ffgsvb(fptr, 1, naxis, naxes, blc, trc, inc, 0,
-               (unsigned char *) array, anynul, status);
-      else
-        ffgsvb(fptr, 1, naxis, naxes, blc, trc, inc, *(unsigned char *) nulval,
-               (unsigned char *) array, anynul, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-      if (nulval == 0)
-        ffgsvsb(fptr, 1, naxis, naxes, blc, trc, inc, 0,
-               (signed char *) array, anynul, status);
-      else
-        ffgsvsb(fptr, 1, naxis, naxes, blc, trc, inc, *(signed char *) nulval,
-               (signed char *) array, anynul, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-      if (nulval == 0)
-        ffgsvui(fptr, 1, naxis, naxes, blc, trc, inc, 0,
-               (unsigned short *) array, anynul, status);
-      else
-        ffgsvui(fptr, 1, naxis, naxes,blc, trc, inc, *(unsigned short *) nulval,
-               (unsigned short *) array, anynul, status);
-    }
-    else if (datatype == TSHORT)
-    {
-      if (nulval == 0)
-        ffgsvi(fptr, 1, naxis, naxes, blc, trc, inc, 0,
-               (short *) array, anynul, status);
-      else
-        ffgsvi(fptr, 1, naxis, naxes, blc, trc, inc, *(short *) nulval,
-               (short *) array, anynul, status);
-    }
-    else if (datatype == TUINT)
-    {
-      if (nulval == 0)
-        ffgsvuk(fptr, 1, naxis, naxes, blc, trc, inc, 0,
-               (unsigned int *) array, anynul, status);
-      else
-        ffgsvuk(fptr, 1, naxis, naxes, blc, trc, inc, *(unsigned int *) nulval,
-               (unsigned int *) array, anynul, status);
-    }
-    else if (datatype == TINT)
-    {
-      if (nulval == 0)
-        ffgsvk(fptr, 1, naxis, naxes, blc, trc, inc, 0,
-               (int *) array, anynul, status);
-      else
-        ffgsvk(fptr, 1, naxis, naxes, blc, trc, inc, *(int *) nulval,
-               (int *) array, anynul, status);
-    }
-    else if (datatype == TULONG)
-    {
-      if (nulval == 0)
-        ffgsvuj(fptr, 1, naxis, naxes, blc, trc, inc, 0,
-               (unsigned long *) array, anynul, status);
-      else
-        ffgsvuj(fptr, 1, naxis, naxes, blc, trc, inc, *(unsigned long *) nulval,
-               (unsigned long *) array, anynul, status);
-    }
-    else if (datatype == TLONG)
-    {
-      if (nulval == 0)
-        ffgsvj(fptr, 1, naxis, naxes, blc, trc, inc, 0,
-               (long *) array, anynul, status);
-      else
-        ffgsvj(fptr, 1, naxis, naxes, blc, trc, inc, *(long *) nulval,
-               (long *) array, anynul, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-      if (nulval == 0)
-        ffgsvjj(fptr, 1, naxis, naxes, blc, trc, inc, 0,
-               (LONGLONG *) array, anynul, status);
-      else
-        ffgsvjj(fptr, 1, naxis, naxes, blc, trc, inc, *(LONGLONG *) nulval,
-               (LONGLONG *) array, anynul, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      if (nulval == 0)
-        ffgsve(fptr, 1, naxis, naxes, blc, trc, inc, 0,
-               (float *) array, anynul, status);
-      else
-        ffgsve(fptr, 1, naxis, naxes, blc, trc, inc, *(float *) nulval,
-               (float *) array, anynul, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-      if (nulval == 0)
-        ffgsvd(fptr, 1, naxis, naxes, blc, trc, inc, 0,
-               (double *) array, anynul, status);
-      else
-        ffgsvd(fptr, 1, naxis, naxes, blc, trc, inc, *(double *) nulval,
-               (double *) array, anynul, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpv(  fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  datatype,    /* I - datatype of the value                   */
-            LONGLONG firstelem,   /* I - first vector element to read (1 = 1st)  */
-            LONGLONG nelem,       /* I - number of values to read                */
-            void *nulval,     /* I - value for undefined pixels              */
-            void *array,      /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. The datatype of the
-  input array is defined by the 2nd argument.  Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-
-    if (*status > 0 || nelem == 0)   /* inherit input status value if > 0 */
-        return(*status);
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (datatype == TBYTE)
-    {
-      if (nulval == 0)
-        ffgpvb(fptr, 1, firstelem, nelem, 0,
-               (unsigned char *) array, anynul, status);
-      else
-        ffgpvb(fptr, 1, firstelem, nelem, *(unsigned char *) nulval,
-               (unsigned char *) array, anynul, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-      if (nulval == 0)
-        ffgpvsb(fptr, 1, firstelem, nelem, 0,
-               (signed char *) array, anynul, status);
-      else
-        ffgpvsb(fptr, 1, firstelem, nelem, *(signed char *) nulval,
-               (signed char *) array, anynul, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-      if (nulval == 0)
-        ffgpvui(fptr, 1, firstelem, nelem, 0,
-               (unsigned short *) array, anynul, status);
-      else
-        ffgpvui(fptr, 1, firstelem, nelem, *(unsigned short *) nulval,
-               (unsigned short *) array, anynul, status);
-    }
-    else if (datatype == TSHORT)
-    {
-      if (nulval == 0)
-        ffgpvi(fptr, 1, firstelem, nelem, 0,
-               (short *) array, anynul, status);
-      else
-        ffgpvi(fptr, 1, firstelem, nelem, *(short *) nulval,
-               (short *) array, anynul, status);
-    }
-    else if (datatype == TUINT)
-    {
-      if (nulval == 0)
-        ffgpvuk(fptr, 1, firstelem, nelem, 0,
-               (unsigned int *) array, anynul, status);
-      else
-        ffgpvuk(fptr, 1, firstelem, nelem, *(unsigned int *) nulval,
-               (unsigned int *) array, anynul, status);
-    }
-    else if (datatype == TINT)
-    {
-      if (nulval == 0)
-        ffgpvk(fptr, 1, firstelem, nelem, 0,
-               (int *) array, anynul, status);
-      else
-        ffgpvk(fptr, 1, firstelem, nelem, *(int *) nulval,
-               (int *) array, anynul, status);
-    }
-    else if (datatype == TULONG)
-    {
-      if (nulval == 0)
-        ffgpvuj(fptr, 1, firstelem, nelem, 0,
-               (unsigned long *) array, anynul, status);
-      else
-        ffgpvuj(fptr, 1, firstelem, nelem, *(unsigned long *) nulval,
-               (unsigned long *) array, anynul, status);
-    }
-    else if (datatype == TLONG)
-    {
-      if (nulval == 0)
-        ffgpvj(fptr, 1, firstelem, nelem, 0,
-               (long *) array, anynul, status);
-      else
-        ffgpvj(fptr, 1, firstelem, nelem, *(long *) nulval,
-               (long *) array, anynul, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-      if (nulval == 0)
-        ffgpvjj(fptr, 1, firstelem, nelem, 0,
-               (LONGLONG *) array, anynul, status);
-      else
-        ffgpvjj(fptr, 1, firstelem, nelem, *(LONGLONG *) nulval,
-               (LONGLONG *) array, anynul, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      if (nulval == 0)
-        ffgpve(fptr, 1, firstelem, nelem, 0,
-               (float *) array, anynul, status);
-      else
-        ffgpve(fptr, 1, firstelem, nelem, *(float *) nulval,
-               (float *) array, anynul, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-      if (nulval == 0)
-        ffgpvd(fptr, 1, firstelem, nelem, 0,
-               (double *) array, anynul, status);
-      else
-      {
-        ffgpvd(fptr, 1, firstelem, nelem, *(double *) nulval,
-               (double *) array, anynul, status);
-      }
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpf(  fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  datatype,    /* I - datatype of the value                   */
-            LONGLONG firstelem,   /* I - first vector element to read (1 = 1st)  */
-            LONGLONG nelem,       /* I - number of values to read                */
-            void *array,      /* O - array of values that are returned       */
-            char *nullarray,  /* O - array of null value flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. The datatype of the
-  input array is defined by the 2nd argument.  Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  The nullarray values will = 1 if the corresponding array value is null.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-
-    if (*status > 0 || nelem == 0)   /* inherit input status value if > 0 */
-        return(*status);
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (datatype == TBYTE)
-    {
-        ffgpfb(fptr, 1, firstelem, nelem, 
-               (unsigned char *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-        ffgpfsb(fptr, 1, firstelem, nelem, 
-               (signed char *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-        ffgpfui(fptr, 1, firstelem, nelem, 
-               (unsigned short *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TSHORT)
-    {
-        ffgpfi(fptr, 1, firstelem, nelem, 
-               (short *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TUINT)
-    {
-        ffgpfuk(fptr, 1, firstelem, nelem, 
-               (unsigned int *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TINT)
-    {
-        ffgpfk(fptr, 1, firstelem, nelem, 
-               (int *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TULONG)
-    {
-        ffgpfuj(fptr, 1, firstelem, nelem, 
-               (unsigned long *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TLONG)
-    {
-        ffgpfj(fptr, 1, firstelem, nelem,
-               (long *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-        ffgpfjj(fptr, 1, firstelem, nelem,
-               (LONGLONG *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-        ffgpfe(fptr, 1, firstelem, nelem, 
-               (float *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-        ffgpfd(fptr, 1, firstelem, nelem,
-               (double *) array, nullarray, anynul, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcv(  fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  datatype,    /* I - datatype of the value                   */
-            int  colnum,      /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,   /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG nelem,       /* I - number of values to read                */
-            void *nulval,     /* I - value for undefined pixels              */
-            void *array,      /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a table column. The datatype of the
-  input array is defined by the 2nd argument.  Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of true if any pixels are undefined.
-*/
-{
-    char cdummy[2];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (datatype == TBIT)
-    {
-      ffgcx(fptr, colnum, firstrow, firstelem, nelem, (char *) array, status);
-    }
-    else if (datatype == TBYTE)
-    {
-      if (nulval == 0)
-        ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
-              (unsigned char *) array, cdummy, anynul, status);
-      else
-       ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(unsigned char *)
-              nulval, (unsigned char *) array, cdummy, anynul, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-      if (nulval == 0)
-        ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
-              (signed char *) array, cdummy, anynul, status);
-      else
-       ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(signed char *)
-              nulval, (signed char *) array, cdummy, anynul, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-      if (nulval == 0)
-        ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
-               (unsigned short *) array, cdummy, anynul, status);
-      else
-        ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 1,
-               *(unsigned short *) nulval,
-               (unsigned short *) array, cdummy, anynul, status);
-    }
-    else if (datatype == TSHORT)
-    {
-      if (nulval == 0)
-        ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
-              (short *) array, cdummy, anynul, status);
-      else
-        ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(short *)
-              nulval, (short *) array, cdummy, anynul, status);
-    }
-    else if (datatype == TUINT)
-    {
-      if (nulval == 0)
-        ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
-              (unsigned int *) array, cdummy, anynul, status);
-      else
-        ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 1,
-         *(unsigned int *) nulval, (unsigned int *) array, cdummy, anynul,
-         status);
-    }
-    else if (datatype == TINT)
-    {
-      if (nulval == 0)
-        ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
-              (int *) array, cdummy, anynul, status);
-      else
-        ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(int *)
-            nulval, (int *) array, cdummy, anynul, status);
-    }
-    else if (datatype == TULONG)
-    {
-      if (nulval == 0)
-        ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
-               (unsigned long *) array, cdummy, anynul, status);
-      else
-        ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 1,
-               *(unsigned long *) nulval, 
-               (unsigned long *) array, cdummy, anynul, status);
-    }
-    else if (datatype == TLONG)
-    {
-      if (nulval == 0)
-        ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
-              (long *) array, cdummy, anynul, status);
-      else
-        ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(long *)
-              nulval, (long *) array, cdummy, anynul, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-      if (nulval == 0)
-        ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
-              (LONGLONG *) array, cdummy, anynul, status);
-      else
-        ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(LONGLONG *)
-              nulval, (LONGLONG *) array, cdummy, anynul, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      if (nulval == 0)
-        ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0.,
-              (float *) array, cdummy, anynul, status);
-      else
-      ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(float *)
-               nulval,(float *) array, cdummy, anynul, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-      if (nulval == 0)
-        ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0.,
-              (double *) array, cdummy, anynul, status);
-      else
-        ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(double *)
-              nulval, (double *) array, cdummy, anynul, status);
-    }
-    else if (datatype == TCOMPLEX)
-    {
-      if (nulval == 0)
-        ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
-           1, 1, 0., (float *) array, cdummy, anynul, status);
-      else
-        ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
-           1, 1, *(float *) nulval, (float *) array, cdummy, anynul, status);
-    }
-    else if (datatype == TDBLCOMPLEX)
-    {
-      if (nulval == 0)
-        ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, 
-         1, 1, 0., (double *) array, cdummy, anynul, status);
-      else
-        ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, 
-         1, 1, *(double *) nulval, (double *) array, cdummy, anynul, status);
-    }
-
-    else if (datatype == TLOGICAL)
-    {
-      if (nulval == 0)
-        ffgcll(fptr, colnum, firstrow, firstelem, nelem, 1, 0,
-          (char *) array, cdummy, anynul, status);
-      else
-        ffgcll(fptr, colnum, firstrow, firstelem, nelem, 1, *(char *) nulval,
-          (char *) array, cdummy, anynul, status);
-    }
-    else if (datatype == TSTRING)
-    {
-      if (nulval == 0)
-      {
-        cdummy[0] = '\0';
-        ffgcls(fptr, colnum, firstrow, firstelem, nelem, 1, 
-             cdummy, (char **) array, cdummy, anynul, status);
-      }
-      else
-        ffgcls(fptr, colnum, firstrow, firstelem, nelem, 1, (char *)
-             nulval, (char **) array, cdummy, anynul, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcf(  fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  datatype,    /* I - datatype of the value                   */
-            int  colnum,      /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,   /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG nelem,       /* I - number of values to read                */
-            void *array,      /* O - array of values that are returned       */
-            char *nullarray,  /* O - array of null value flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a table column. The datatype of the
-  input array is defined by the 2nd argument.  Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  ANYNUL is returned with a value of true if any pixels are undefined.
-*/
-{
-    double nulval = 0.;
-    char cnulval[2];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (datatype == TBIT)
-    {
-      ffgcx(fptr, colnum, firstrow, firstelem, nelem, (char *) array, status);
-    }
-    else if (datatype == TBYTE)
-    {
-       ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (unsigned char )
-              nulval, (unsigned char *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-       ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (signed char )
-              nulval, (signed char *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-        ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 2,
-               (unsigned short ) nulval,
-               (unsigned short *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TSHORT)
-    {
-        ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (short )
-              nulval, (short *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TUINT)
-    {
-        ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 2,
-         (unsigned int ) nulval, (unsigned int *) array, nullarray, anynul,
-         status);
-    }
-    else if (datatype == TINT)
-    {
-        ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (int )
-            nulval, (int *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TULONG)
-    {
-        ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 2,
-               (unsigned long ) nulval, 
-               (unsigned long *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TLONG)
-    {
-        ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (long )
-              nulval, (long *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-        ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (LONGLONG )
-              nulval, (LONGLONG *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (float )
-               nulval,(float *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-        ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 2, 
-              nulval, (double *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TCOMPLEX)
-    {
-        ffgcfc(fptr, colnum, firstrow, firstelem, nelem,
-           (float *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TDBLCOMPLEX)
-    {
-        ffgcfm(fptr, colnum, firstrow, firstelem, nelem, 
-           (double *) array, nullarray, anynul, status);
-    }
-
-    else if (datatype == TLOGICAL)
-    {
-        ffgcll(fptr, colnum, firstrow, firstelem, nelem, 2, (char ) nulval,
-          (char *) array, nullarray, anynul, status);
-    }
-    else if (datatype == TSTRING)
-    {
-        ffgcls(fptr, colnum, firstrow, firstelem, nelem, 2, 
-             cnulval, (char **) array, nullarray, anynul, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcolb.c b/src/external/OpenGR/3rdparty/cfitsio/getcolb.c
deleted file mode 100644
index b010870bd..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcolb.c
+++ /dev/null
@@ -1,2008 +0,0 @@
-/*  This file, getcolb.c, contains routines that read data elements from   */
-/*  a FITS image or table, with unsigned char (unsigned byte) data type.   */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffgpvb( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            unsigned char nulval, /* I - value for undefined pixels          */
-            unsigned char *array, /* O - array of values that are returned   */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    char cdummy;
-    int nullcheck = 1;
-    unsigned char nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-         nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_pixels(fptr, TBYTE, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclb(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpfb( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            unsigned char *array, /* O - array of values that are returned   */
-            char *nularray,   /* O - array of null pixel flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Any undefined pixels in the returned array will be set = 0 and the 
-  corresponding nularray value will be set = 1.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    int nullcheck = 2;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_read_compressed_pixels(fptr, TBYTE, firstelem, nelem,
-            nullcheck, NULL, array, nularray, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclb(fptr, 2, row, firstelem, nelem, 1, 2, 0,
-               array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg2db(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           unsigned char nulval, /* set undefined pixels equal to this     */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           unsigned char *array, /* O - array to be filled and returned    */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    /* call the 3D reading routine, with the 3rd dimension = 1 */
-
-    ffg3db(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
-           anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg3db(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           unsigned char nulval, /* set undefined pixels equal to this     */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
-           unsigned char *array, /* O - array to be filled and returned    */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 3-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    long tablerow, ii, jj;
-    LONGLONG narray, nfits;
-    char cdummy;
-    int  nullcheck = 1;
-    long inc[] = {1,1,1};
-    LONGLONG fpixel[] = {1,1,1};
-    LONGLONG lpixel[3];
-    unsigned char nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        lpixel[0] = ncols;
-        lpixel[1] = nrows;
-        lpixel[2] = naxis3;
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TBYTE, fpixel, lpixel, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-       /* all the image pixels are contiguous, so read all at once */
-       ffgclb(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-       return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to read */
-    narray = 0;  /* next pixel in output array to be filled */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* reading naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffgclb(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
-          &array[narray], &cdummy, anynul, status) > 0)
-          return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsvb(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           unsigned char nulval, /* I - value to set undefined pixels       */
-           unsigned char *array, /* O - array to be filled and returned     */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii, i0, i1, i2, i3, i4, i5, i6, i7, i8, row, rstr, rstp, rinc;
-    long str[9], stp[9], incr[9], dir[9];
-    long nelem, nultyp, ninc, numcol;
-    LONGLONG felem, dsize[10], blcll[9], trcll[9];
-    int hdutype, anyf;
-    char ldummy, msg[FLEN_ERRMSG];
-    int  nullcheck = 1;
-    unsigned char nullvalue;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvb is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TBYTE, blcll, trcll, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 1;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-        dir[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        if (hdutype == IMAGE_HDU)
-        {
-           dir[ii] = -1;
-        }
-        else
-        {
-          sprintf(msg, "ffgsvb: illegal range specified for axis %ld", ii + 1);
-          ffpmsg(msg);
-          return(*status = BAD_PIX_NUM);
-        }
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-      dsize[ii] = dsize[ii] * dir[ii];
-    }
-    dsize[naxis] = dsize[naxis] * dir[naxis];
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
-      ninc = incr[0] * dir[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
-            {
-
-              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
-                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
-                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
-                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];
-
-              if ( ffgclb(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsfb(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           unsigned char *array, /* O - array to be filled and returned     */
-           char *flagval,  /* O - set to 1 if corresponding value is null   */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dsize[10];
-    LONGLONG blcll[9], trcll[9];
-    long felem, nelem, nultyp, ninc, numcol;
-    int hdutype, anyf;
-    unsigned char nulval = 0;
-    char msg[FLEN_ERRMSG];
-    int  nullcheck = 2;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvb is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        fits_read_compressed_img(fptr, TBYTE, blcll, trcll, inc,
-            nullcheck, NULL, array, flagval, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 2;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvb: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgclb(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffggpb( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            long  nelem,      /* I - number of values to read                */
-            unsigned char *array, /* O - array of values that are returned   */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of group parameters from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-*/
-{
-    long row;
-    int idummy;
-    char cdummy;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclb(fptr, 1, row, firstelem, nelem, 1, 1, 0,
-               array, &cdummy, &idummy, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcvb(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           unsigned char nulval, /* I - value for null pixels               */
-           unsigned char *array, /* O - array of values that are read       */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy;
-
-    ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
-           array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfb(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           unsigned char *array, /* O - array of values that are read       */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-*/
-{
-    unsigned char dummy = 0;
-
-    ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
-           array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgclb( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-            unsigned char nulval, /* I - value for null pixels if nultyp = 1 */
-            unsigned char *array, /* O - array of values that are read       */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer be a virtual column in a 1 or more grouped FITS primary
-  array or image extension.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The output array of values will be converted from the datatype of the column 
-  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    double scale, zero, power = 1., dtemp;
-    int tcode, maxelem2, hdutype, xcode, decimals;
-    long twidth, incre, ntodo;
-    long ii, xwidth;
-    int convert, nulcheck, readcheck = 0;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull;
-    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
-    char tform[20];
-    char message[81];
-    char snull[20];   /*  the FITS null value if reading from ASCII table  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    union u_tag {
-       char charval;
-       unsigned char ucharval;
-    } u;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    if (anynul)
-        *anynul = 0;
-
-    if (nultyp == 2)      
-       memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (elemincre < 0)
-        readcheck = -1;  /* don't do range checking in this case */
-
-    ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
-         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
-         &repeat, &rowlen, &hdutype, &tnull, snull, status);
-    maxelem = maxelem2;
-
-    /* special case */
-    if (tcode == TLOGICAL && elemincre == 1)
-    {
-        u.ucharval = nulval;
-        ffgcll(fptr, colnum, firstrow, firstelem, nelem, nultyp,
-               u.charval, (char *) array, nularray, anynul, status);
-
-        return(*status);
-    }
-
-    if (strchr(tform,'A') != NULL) 
-    {
-        if (*status == BAD_ELEM_NUM)
-        {
-            /* ignore this error message */
-            *status = 0;
-            ffcmsg();   /* clear error stack */
-        }
-
-        /*  interpret a 'A' ASCII column as a 'B' byte column ('8A' == '8B') */
-        /*  This is an undocumented 'feature' in CFITSIO */
-
-        /*  we have to reset some of the values returned by ffgcpr */
-        
-        tcode = TBYTE;
-        incre = 1;         /* each element is 1 byte wide */
-        repeat = twidth;   /* total no. of chars in the col */
-        twidth = 1;        /* width of each element */
-        scale = 1.0;       /* no scaling */
-        zero  = 0.0;
-        tnull = NULL_UNDEFINED;  /* don't test for nulls */
-        maxelem = DBUFFSIZE;
-    }
-
-    if (*status > 0)
-        return(*status);
-        
-    incre *= elemincre;   /* multiply incre to just get every nth pixel */
-
-    if (tcode == TSTRING && hdutype == ASCII_TBL) /* setup for ASCII tables */
-    {
-      /* get the number of implied decimal places if no explicit decmal point */
-      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
-      for(ii = 0; ii < decimals; ii++)
-        power *= 10.;
-    }
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default, check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
-            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
-            nulcheck = 0;            /* then do not check for null values. */
-
-    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
-         nulcheck = 0;
-
-    /*----------------------------------------------------------------------*/
-    /*  If FITS column and output data array have same datatype, then we do */
-    /*  not need to use a temporary buffer to store intermediate datatype.  */
-    /*----------------------------------------------------------------------*/
-    convert = 1;
-    if (tcode == TBYTE) /* Special Case:                        */
-    {                             /* no type convertion required, so read */
-                                  /* data directly into output buffer.    */
-
-        if (nelem < (LONGLONG)INT32_MAX) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX;
-        }
-
-        if (nulcheck == 0 && scale == 1. && zero == 0.)
-            convert = 0;  /* no need to scale data or find nulls */
-    }
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the pixels from the FITS column. If the column does not   */
-    /*  have the same datatype as the output array, then we have to read   */
-    /*  the raw values into a temporary buffer (of limited size).  In      */
-    /*  the case of a vector colum read only 1 vector of values at a time  */
-    /*  then skip to the next row if more values need to be read.          */
-    /*  After reading the raw values, then call the fffXXYY routine to (1) */
-    /*  test for undefined values, (2) convert the datatype if necessary,  */
-    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
-    /*  scaling parameters.                                                */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to read */
-    next = 0;                 /* next element in array to be read   */
-    rownum = 0;               /* row number, relative to firstrow   */
-
-    while (remain)
-    {
-        /* limit the number of pixels to read at one time to the number that
-           will fit in the buffer or to the number of pixels that remain in
-           the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);
-        if (elemincre >= 0)
-        {
-          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
-        }
-        else
-        {
-          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
-        }
-
-        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
-
-        switch (tcode) 
-        {
-            case (TBYTE):
-                ffgi1b(fptr, readptr, ntodo, incre, &array[next], status);
-                if (convert)
-                    fffi1i1(&array[next], ntodo, scale, zero, nulcheck, 
-                    (unsigned char) tnull, nulval, &nularray[next], anynul, 
-                           &array[next], status);
-                break;
-            case (TSHORT):
-                ffgi2b(fptr, readptr, ntodo, incre, (short *) buffer, status);
-                fffi2i1((short  *) buffer, ntodo, scale, zero, nulcheck, 
-                       (short) tnull, nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TLONG):
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
-                       status);
-                fffi4i1((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
-                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TLONGLONG):
-                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
-                fffi8i1( (LONGLONG *) buffer, ntodo, scale, zero, 
-                           nulcheck, tnull, nulval, &nularray[next], 
-                            anynul, &array[next], status);
-                break;
-            case (TFLOAT):
-                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
-                fffr4i1((float  *) buffer, ntodo, scale, zero, nulcheck, 
-                       nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TDOUBLE):
-                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
-                fffr8i1((double *) buffer, ntodo, scale, zero, nulcheck, 
-                          nulval, &nularray[next], anynul, 
-                          &array[next], status);
-                break;
-            case (TSTRING):
-                ffmbyt(fptr, readptr, REPORT_EOF, status);
-       
-                if (incre == twidth)    /* contiguous bytes */
-                     ffgbyt(fptr, ntodo * twidth, buffer, status);
-                else
-                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                               status);
-
-                /* interpret the string as an ASCII formated number */
-                fffstri1((char *) buffer, ntodo, scale, zero, twidth, power,
-                      nulcheck, snull, nulval, &nularray[next], anynul,
-                      &array[next], status);
-                break;
-
-            default:  /*  error trap for invalid column format */
-                sprintf(message, 
-                   "Cannot read bytes from column %d which has format %s",
-                    colnum, tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous read operation */
-        {
-	  dtemp = (double) next;
-          if (hdutype > 0)
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from column %d (ffgclb).",
-              dtemp+1., dtemp+ntodo, colnum);
-          else
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from image (ffgclb).",
-              dtemp+1., dtemp+ntodo);
-
-         ffpmsg(message);
-         return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum = elemnum + (ntodo * elemincre);
-
-            if (elemnum >= repeat)  /* completed a row; start on later row */
-            {
-                rowincre = elemnum / repeat;
-                rownum += rowincre;
-                elemnum = elemnum - (rowincre * repeat);
-            }
-            else if (elemnum < 0)  /* completed a row; start on a previous row */
-            {
-                rowincre = (-elemnum - 1) / repeat + 1;
-                rownum -= rowincre;
-                elemnum = (rowincre * repeat) + elemnum;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while reading FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgextn( fitsfile *fptr,        /* I - FITS file pointer                        */
-            LONGLONG  offset,      /* I - byte offset from start of extension data */
-            LONGLONG  nelem,       /* I - number of elements to read               */
-            void *buffer,          /* I - stream of bytes to read                  */
-            int  *status)          /* IO - error status                            */
-/*
-  Read a stream of bytes from the current FITS HDU.  This primative routine is mainly
-  for reading non-standard "conforming" extensions and should not be used
-  for standard IMAGE, TABLE or BINTABLE extensions.
-*/
-{
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    /* rescan header if data structure is undefined */
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-        if ( ffrdef(fptr, status) > 0)               
-            return(*status);
-
-    /* move to write position */
-    ffmbyt(fptr, (fptr->Fptr)->datastart+ offset, IGNORE_EOF, status);
-    
-    /* read the buffer */
-    ffgbyt(fptr, nelem, buffer, status); 
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi1i1(unsigned char *input, /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-            unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            unsigned char *output,/* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {              /* this routine is normally not called in this case */
-           memmove(output, input, ntodo );
-        }
-        else             /* must scale the data */
-        {                
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UCHAR_MAX;
-                }
-                else
-                    output[ii] = (unsigned char) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi2i1(short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-            unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            unsigned char *output,/* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > UCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UCHAR_MAX;
-                }
-                else
-                    output[ii] = (unsigned char) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UCHAR_MAX;
-                }
-                else
-                    output[ii] = (unsigned char) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-
-                else
-                {
-                    if (input[ii] < 0)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > UCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi4i1(INT32BIT *input,          /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-            unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            unsigned char *output,/* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > UCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UCHAR_MAX;
-                }
-                else
-                    output[ii] = (unsigned char) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UCHAR_MAX;
-                }
-                else
-                    output[ii] = (unsigned char) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < 0)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > UCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi8i1(LONGLONG *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
-            unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            unsigned char *output,/* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > UCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UCHAR_MAX;
-                }
-                else
-                    output[ii] = (unsigned char) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UCHAR_MAX;
-                }
-                else
-                    output[ii] = (unsigned char) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < 0)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > UCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr4i1(float *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            unsigned char *output,/* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DUCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > DUCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UCHAR_MAX;
-                }
-                else
-                    output[ii] = (unsigned char) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UCHAR_MAX;
-                }
-                else
-                    output[ii] = (unsigned char) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr++;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              /* use redundant boolean logic in following statement */
-              /* to suppress irritating Borland compiler warning message */
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DUCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > DUCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  {
-                    if (zero < DUCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (zero > DUCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr8i1(double *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            unsigned char *output,/* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DUCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > DUCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UCHAR_MAX;
-                }
-                else
-                    output[ii] = (unsigned char) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UCHAR_MAX;
-                }
-                else
-                    output[ii] = (unsigned char) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr += 3;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DUCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > DUCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  {
-                    if (zero < DUCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (zero > DUCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UCHAR_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned char) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffstri1(char *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            long twidth,          /* I - width of each substring of chars    */
-            double implipower,    /* I - power of 10 of implied decimal      */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            char  *snull,         /* I - value of FITS null string, if any   */
-            unsigned char nullval, /* I - set null pixels, if nullcheck = 1  */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            unsigned char *output, /* O - array of converted pixels          */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file. Check
-  for null values and do scaling if required. The nullcheck code value
-  determines how any null values in the input array are treated. A null
-  value is an input pixel that is equal to snull.  If nullcheck= 0, then
-  no special checking for nulls is performed.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    int  nullen;
-    long ii;
-    double dvalue;
-    char *cstring, message[81];
-    char *cptr, *tpos;
-    char tempstore, chrzero = '0';
-    double val, power;
-    int exponent, sign, esign, decpt;
-
-    nullen = strlen(snull);
-    cptr = input;  /* pointer to start of input string */
-    for (ii = 0; ii < ntodo; ii++)
-    {
-      cstring = cptr;
-      /* temporarily insert a null terminator at end of the string */
-      tpos = cptr + twidth;
-      tempstore = *tpos;
-      *tpos = 0;
-
-      /* check if null value is defined, and if the    */
-      /* column string is identical to the null string */
-      if (snull[0] != ASCII_NULL_UNDEFINED && 
-         !strncmp(snull, cptr, nullen) )
-      {
-        if (nullcheck)  
-        {
-          *anynull = 1;    
-          if (nullcheck == 1)
-            output[ii] = nullval;
-          else
-            nullarray[ii] = 1;
-        }
-        cptr += twidth;
-      }
-      else
-      {
-        /* value is not the null value, so decode it */
-        /* remove any embedded blank characters from the string */
-
-        decpt = 0;
-        sign = 1;
-        val  = 0.;
-        power = 1.;
-        exponent = 0;
-        esign = 1;
-
-        while (*cptr == ' ')               /* skip leading blanks */
-           cptr++;
-
-        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
-        {
-          if (*cptr == '-')
-             sign = -1;
-
-          cptr++;
-
-          while (*cptr == ' ')         /* skip blanks between sign and value */
-            cptr++;
-        }
-
-        while (*cptr >= '0' && *cptr <= '9')
-        {
-          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-          cptr++;
-
-          while (*cptr == ' ')         /* skip embedded blanks in the value */
-            cptr++;
-        }
-
-        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
-        {
-          decpt = 1;
-          cptr++;
-          while (*cptr == ' ')         /* skip any blanks */
-            cptr++;
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-            power = power * 10.;
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks in the value */
-              cptr++;
-          }
-        }
-
-        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
-        {
-          cptr++;
-          while (*cptr == ' ')         /* skip blanks */
-              cptr++;
-  
-          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
-          {
-            if (*cptr == '-')
-               esign = -1;
-
-            cptr++;
-
-            while (*cptr == ' ')        /* skip blanks between sign and exp */
-              cptr++;
-          }
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks */
-              cptr++;
-          }
-        }
-
-        if (*cptr  != 0)  /* should end up at the null terminator */
-        {
-          sprintf(message, "Cannot read number from ASCII table");
-          ffpmsg(message);
-          sprintf(message, "Column field = %s.", cstring);
-          ffpmsg(message);
-          /* restore the char that was overwritten by the null */
-          *tpos = tempstore;
-          return(*status = BAD_C2D);
-        }
-
-        if (!decpt)  /* if no explicit decimal, use implied */
-           power = implipower;
-
-        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
-
-        dvalue = dvalue * scale + zero;   /* apply the scaling */
-
-        if (dvalue < DUCHAR_MIN)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = 0;
-        }
-        else if (dvalue > DUCHAR_MAX)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = UCHAR_MAX;
-        }
-        else
-            output[ii] = (unsigned char) dvalue;
-      }
-      /* restore the char that was overwritten by the null */
-      *tpos = tempstore;
-    }
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcold.c b/src/external/OpenGR/3rdparty/cfitsio/getcold.c
deleted file mode 100644
index de7d18527..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcold.c
+++ /dev/null
@@ -1,1683 +0,0 @@
-/*  This file, getcold.c, contains routines that read data elements from   */
-/*  a FITS image or table, with double datatype.                           */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffgpvd( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            double nulval,    /* I - value for undefined pixels              */
-            double *array,    /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    char cdummy;
-    int nullcheck = 1;
-    double nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-         nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_pixels(fptr, TDOUBLE, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcld(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpfd( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            double *array,    /* O - array of values that are returned       */
-            char *nularray,   /* O - array of null pixel flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Any undefined pixels in the returned array will be set = 0 and the 
-  corresponding nularray value will be set = 1.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    int nullcheck = 2;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_read_compressed_pixels(fptr, TDOUBLE, firstelem, nelem,
-            nullcheck, NULL, array, nularray, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcld(fptr, 2, row, firstelem, nelem, 1, 2, 0.,
-               array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg2dd(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           double nulval,   /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           double *array,   /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    /* call the 3D reading routine, with the 3rd dimension = 1 */
-
-    ffg3dd(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
-           anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg3dd(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           double nulval,   /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
-           double *array,   /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 3-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    LONGLONG nfits, narray;
-    long tablerow, ii, jj;
-    char cdummy;
-    int nullcheck = 1;
-    long inc[] = {1,1,1};
-    LONGLONG fpixel[] = {1,1,1};
-    LONGLONG lpixel[3];
-    double nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        lpixel[0] =  (long) ncols;
-        lpixel[1] = (long) nrows;
-        lpixel[2] = (long) naxis3;
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TDOUBLE, fpixel, lpixel, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-       /* all the image pixels are contiguous, so read all at once */
-       ffgcld(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-       return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to read */
-    narray = 0;  /* next pixel in output array to be filled */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* reading naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffgcld(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
-          &array[narray], &cdummy, anynul, status) > 0)
-          return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsvd(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           double nulval,  /* I - value to set undefined pixels             */
-           double *array,  /* O - array to be filled and returned           */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dir[9];
-    long nelem, nultyp, ninc, numcol;
-    LONGLONG felem, dsize[10], blcll[9], trcll[9];
-    int hdutype, anyf;
-    char ldummy, msg[FLEN_ERRMSG];
-    int nullcheck = 1;
-    double nullvalue;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvd is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TDOUBLE, blcll, trcll, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 1;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-        dir[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        if (hdutype == IMAGE_HDU)
-        {
-           dir[ii] = -1;
-        }
-        else
-        {
-          sprintf(msg, "ffgsvd: illegal range specified for axis %ld", ii + 1);
-          ffpmsg(msg);
-          return(*status = BAD_PIX_NUM);
-        }
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-      dsize[ii] = dsize[ii] * dir[ii];
-    }
-    dsize[naxis] = dsize[naxis] * dir[naxis];
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
-      ninc = incr[0] * dir[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
-            {
-
-              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
-                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
-                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
-                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];
-
-              if ( ffgcld(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsfd(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           double *array,  /* O - array to be filled and returned           */
-           char *flagval,  /* O - set to 1 if corresponding value is null   */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dsize[10];
-    LONGLONG blcll[9], trcll[9];
-    long felem, nelem, nultyp, ninc, numcol;
-    int hdutype, anyf;
-    double nulval = 0;
-    char msg[FLEN_ERRMSG];
-    int nullcheck = 2;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvd is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        fits_read_compressed_img(fptr, TDOUBLE, blcll, trcll, inc,
-            nullcheck, NULL, array, flagval, anynul, status);
-        return(*status);
-    }
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 2;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvd: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgcld(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffggpd( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            long  nelem,      /* I - number of values to read                */
-            double *array,    /* O - array of values that are returned       */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of group parameters from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-*/
-{
-    long row;
-    int idummy;
-    char cdummy;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcld(fptr, 1, row, firstelem, nelem, 1, 1, 0.,
-               array, &cdummy, &idummy, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcvd(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           double nulval,    /* I - value for null pixels                   */
-           double *array,    /* O - array of values that are read           */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy;
-
-    ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
-           array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcvm(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           double nulval,    /* I - value for null pixels                   */
-           double *array,    /* O - array of values that are read           */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-
-  TSCAL and ZERO should not be used with complex values. 
-*/
-{
-    char cdummy;
-
-    /* a complex double value is interpreted as a pair of double values,   */
-    /* thus need to multiply the first element and number of elements by 2 */
-
-    ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
-        1, 1, nulval, array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfd(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           double *array,    /* O - array of values that are read           */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-*/
-{
-    double dummy = 0;
-
-    ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
-           array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfm(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           double *array,    /* O - array of values that are read           */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-
-  TSCAL and ZERO should not be used with complex values. 
-*/
-{
-    LONGLONG ii, jj;
-    float dummy = 0;
-    char *carray;
-
-    /* a complex double value is interpreted as a pair of double values,   */
-    /* thus need to multiply the first element and number of elements by 2 */
-
-    /* allocate temporary array */
-    carray = (char *) calloc( (size_t) (nelem * 2), 1); 
-
-    ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
-     1, 2, dummy, array, carray, anynul, status);
-
-    for (ii = 0, jj = 0; jj < nelem; ii += 2, jj++)
-    {
-       if (carray[ii] || carray[ii + 1])
-          nularray[jj] = 1;
-       else
-          nularray[jj] = 0;
-    }
-
-    free(carray);    
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcld( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-            double nulval,    /* I - value for null pixels if nultyp = 1     */
-            double *array,    /* O - array of values that are read           */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer be a virtual column in a 1 or more grouped FITS primary
-  array or image extension.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The output array of values will be converted from the datatype of the column
-  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    double scale, zero, power = 1, dtemp;
-    int tcode, hdutype, xcode, decimals, maxelem2;
-    long twidth, incre;
-    long ii, xwidth, ntodo;
-    int convert, nulcheck, readcheck = 0;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull;
-    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
-    char tform[20];
-    char message[81];
-    char snull[20];   /*  the FITS null value if reading from ASCII table  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    if (anynul)
-        *anynul = 0;
-
-    if (nultyp == 2)
-        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (elemincre < 0)
-        readcheck = -1;  /* don't do range checking in this case */
-
-    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
-         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
-         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
-         return(*status);
-    maxelem = maxelem2;
-
-    incre *= elemincre;   /* multiply incre to just get every nth pixel */
-
-    if (tcode == TSTRING)    /* setup for ASCII tables */
-    {
-      /* get the number of implied decimal places if no explicit decmal point */
-      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
-      for(ii = 0; ii < decimals; ii++)
-        power *= 10.;
-    }
-
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
-            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
-            nulcheck = 0;            /* then do not check for null values. */
-
-    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
-         nulcheck = 0;
-
-    /*----------------------------------------------------------------------*/
-    /*  If FITS column and output data array have same datatype, then we do */
-    /*  not need to use a temporary buffer to store intermediate datatype.  */
-    /*----------------------------------------------------------------------*/
-    convert = 1;
-    if (tcode == TDOUBLE) /* Special Case:                        */
-    {                              /* no type convertion required, so read */
-                                  /* data directly into output buffer.    */
-
-        if (nelem < (LONGLONG)INT32_MAX/8) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/8;
-        }
-
-        if (nulcheck == 0 && scale == 1. && zero == 0.)
-            convert = 0;  /* no need to scale data or find nulls */
-    }
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the pixels from the FITS column. If the column does not   */
-    /*  have the same datatype as the output array, then we have to read   */
-    /*  the raw values into a temporary buffer (of limited size).  In      */
-    /*  the case of a vector colum read only 1 vector of values at a time  */
-    /*  then skip to the next row if more values need to be read.          */
-    /*  After reading the raw values, then call the fffXXYY routine to (1) */
-    /*  test for undefined values, (2) convert the datatype if necessary,  */
-    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
-    /*  scaling parameters.                                                */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to read */
-    next = 0;                 /* next element in array to be read   */
-    rownum = 0;               /* row number, relative to firstrow   */
-
-    while (remain)
-    {
-        /* limit the number of pixels to read at one time to the number that
-           will fit in the buffer or to the number of pixels that remain in
-           the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);
-        if (elemincre >= 0)
-        {
-          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
-        }
-        else
-        {
-          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
-        }
-
-        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
-
-        switch (tcode) 
-        {
-            case (TDOUBLE):
-                ffgr8b(fptr, readptr, ntodo, incre, &array[next], status);
-                if (convert)
-                    fffr8r8(&array[next], ntodo, scale, zero, nulcheck, 
-                           nulval, &nularray[next], anynul, 
-                           &array[next], status);
-                break;
-            case (TBYTE):
-                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
-                       status);
-                fffi1r8((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
-                   (unsigned char) tnull, nulval, &nularray[next], anynul, 
-                   &array[next], status);
-                break;
-            case (TSHORT):
-                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
-                fffi2r8((short  *) buffer, ntodo, scale, zero, nulcheck, 
-                    (short) tnull, nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TLONG):
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
-                       status);
-                fffi4r8((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
-                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TLONGLONG):
-                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
-                fffi8r8( (LONGLONG *) buffer, ntodo, scale, zero, 
-                           nulcheck, tnull, nulval, &nularray[next], 
-                            anynul, &array[next], status);
-                break;
-            case (TFLOAT):
-                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
-                fffr4r8((float  *) buffer, ntodo, scale, zero, nulcheck, 
-                          nulval, &nularray[next], anynul, 
-                          &array[next], status);
-                break;
-            case (TSTRING):
-                ffmbyt(fptr, readptr, REPORT_EOF, status);
-       
-                if (incre == twidth)    /* contiguous bytes */
-                     ffgbyt(fptr, ntodo * twidth, buffer, status);
-                else
-                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                               status);
-
-                fffstrr8((char *) buffer, ntodo, scale, zero, twidth, power,
-                     nulcheck, snull, nulval, &nularray[next], anynul,
-                     &array[next], status);
-                break;
-
-
-            default:  /*  error trap for invalid column format */
-                sprintf(message, 
-                   "Cannot read numbers from column %d which has format %s",
-                    colnum, tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous read operation */
-        {
-	  dtemp = (double) next;
-          if (hdutype > 0)
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from column %d (ffgcld).",
-              dtemp+1., dtemp+ntodo, colnum);
-          else
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from image (ffgcld).",
-              dtemp+1., dtemp+ntodo);
-
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum = elemnum + (ntodo * elemincre);
-
-            if (elemnum >= repeat)  /* completed a row; start on later row */
-            {
-                rowincre = (long) (elemnum / repeat);
-                rownum += rowincre;
-                elemnum = elemnum - (rowincre * repeat);
-            }
-            else if (elemnum < 0)  /* completed a row; start on a previous row */
-            {
-                rowincre = (long) ((-elemnum - 1) / repeat + 1);
-                rownum -= rowincre;
-                elemnum = (rowincre * repeat) + elemnum;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while reading FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi1r8(unsigned char *input, /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-            double nullval,       /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,       /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii]; /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                output[ii] = input[ii] * scale + zero;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (double) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    output[ii] = input[ii] * scale + zero;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi2r8(short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-            double nullval,       /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,       /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii]; /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                output[ii] = input[ii] * scale + zero;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (double) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    output[ii] = input[ii] * scale + zero;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi4r8(INT32BIT *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-            double nullval,       /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,       /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii]; /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                output[ii] = input[ii] * scale + zero;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (double) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    output[ii] = input[ii] * scale + zero;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi8r8(LONGLONG *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
-            double nullval,       /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,       /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii]; /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                output[ii] = input[ii] * scale + zero;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (double) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    output[ii] = input[ii] * scale + zero;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr4r8(float *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            double nullval,       /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,       /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii]; /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                output[ii] = input[ii] * scale + zero;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr++;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                output[ii] = (double) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = zero;
-              }
-              else
-                  output[ii] = input[ii] * scale + zero;
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr8r8(double *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            double nullval,       /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,       /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            memmove(output, input, ntodo * sizeof(double) );
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                output[ii] = input[ii] * scale + zero;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr += 3;       /* point to MSBs */
-#endif
-
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                    {
-                        nullarray[ii] = 1;
-                       /* explicitly set value in case output contains a NaN */
-                        output[ii] = DOUBLENULLVALUE;
-                    }
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                  output[ii] = input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                    {
-                        nullarray[ii] = 1;
-                       /* explicitly set value in case output contains a NaN */
-                        output[ii] = DOUBLENULLVALUE;
-                    }
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = zero;
-              }
-              else
-                  output[ii] = input[ii] * scale + zero;
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffstrr8(char *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            long twidth,          /* I - width of each substring of chars    */
-            double implipower,    /* I - power of 10 of implied decimal      */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            char  *snull,         /* I - value of FITS null string, if any   */
-            double nullval,       /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,       /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file. Check
-  for null values and do scaling if required. The nullcheck code value
-  determines how any null values in the input array are treated. A null
-  value is an input pixel that is equal to snull.  If nullcheck= 0, then
-  no special checking for nulls is performed.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    int nullen;
-    long ii;
-    double dvalue;
-    char *cstring, message[81];
-    char *cptr, *tpos;
-    char tempstore, chrzero = '0';
-    double val, power;
-    int exponent, sign, esign, decpt;
-
-    nullen = strlen(snull);
-    cptr = input;  /* pointer to start of input string */
-    for (ii = 0; ii < ntodo; ii++)
-    {
-      cstring = cptr;
-      /* temporarily insert a null terminator at end of the string */
-      tpos = cptr + twidth;
-      tempstore = *tpos;
-      *tpos = 0;
-
-      /* check if null value is defined, and if the    */
-      /* column string is identical to the null string */
-      if (snull[0] != ASCII_NULL_UNDEFINED && 
-         !strncmp(snull, cptr, nullen) )
-      {
-        if (nullcheck)  
-        {
-          *anynull = 1;    
-          if (nullcheck == 1)
-            output[ii] = nullval;
-          else
-            nullarray[ii] = 1;
-        }
-        cptr += twidth;
-      }
-      else
-      {
-        /* value is not the null value, so decode it */
-        /* remove any embedded blank characters from the string */
-
-        decpt = 0;
-        sign = 1;
-        val  = 0.;
-        power = 1.;
-        exponent = 0;
-        esign = 1;
-
-        while (*cptr == ' ')               /* skip leading blanks */
-           cptr++;
-
-        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
-        {
-          if (*cptr == '-')
-             sign = -1;
-
-          cptr++;
-
-          while (*cptr == ' ')         /* skip blanks between sign and value */
-            cptr++;
-        }
-
-        while (*cptr >= '0' && *cptr <= '9')
-        {
-          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-          cptr++;
-
-          while (*cptr == ' ')         /* skip embedded blanks in the value */
-            cptr++;
-        }
-
-        if (*cptr == '.' || *cptr == ',')              /* check for decimal point */
-        {
-          decpt = 1;       /* set flag to show there was a decimal point */
-          cptr++;
-          while (*cptr == ' ')         /* skip any blanks */
-            cptr++;
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-            power = power * 10.;
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks in the value */
-              cptr++;
-          }
-        }
-
-        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
-        {
-          cptr++;
-          while (*cptr == ' ')         /* skip blanks */
-              cptr++;
-  
-          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
-          {
-            if (*cptr == '-')
-               esign = -1;
-
-            cptr++;
-
-            while (*cptr == ' ')        /* skip blanks between sign and exp */
-              cptr++;
-          }
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks */
-              cptr++;
-          }
-        }
-
-        if (*cptr  != 0)  /* should end up at the null terminator */
-        {
-          sprintf(message, "Cannot read number from ASCII table");
-          ffpmsg(message);
-          sprintf(message, "Column field = %s.", cstring);
-          ffpmsg(message);
-          /* restore the char that was overwritten by the null */
-          *tpos = tempstore;
-          return(*status = BAD_C2D);
-        }
-
-        if (!decpt)  /* if no explicit decimal, use implied */
-           power = implipower;
-
-        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
-
-        output[ii] = (dvalue * scale + zero);   /* apply the scaling */
-      }
-      /* restore the char that was overwritten by the null */
-      *tpos = tempstore;
-    }
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcole.c b/src/external/OpenGR/3rdparty/cfitsio/getcole.c
deleted file mode 100644
index fa2b9c62a..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcole.c
+++ /dev/null
@@ -1,1686 +0,0 @@
-/*  This file, getcole.c, contains routines that read data elements from   */
-/*  a FITS image or table, with float datatype                             */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffgpve( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            float nulval,     /* I - value for undefined pixels              */
-            float *array,     /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    char cdummy;
-    int nullcheck = 1;
-    float nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-         nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_pixels(fptr, TFLOAT, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcle(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpfe( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            float *array,     /* O - array of values that are returned       */
-            char *nularray,   /* O - array of null pixel flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Any undefined pixels in the returned array will be set = 0 and the 
-  corresponding nularray value will be set = 1.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    int nullcheck = 2;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_read_compressed_pixels(fptr, TFLOAT, firstelem, nelem,
-            nullcheck, NULL, array, nularray, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcle(fptr, 2, row, firstelem, nelem, 1, 2, 0.F,
-               array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg2de(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           float nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           float *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    /* call the 3D reading routine, with the 3rd dimension = 1 */
-
-    ffg3de(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
-           anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg3de(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           float nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
-           float *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 3-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    long tablerow;
-    LONGLONG narray, nfits, ii, jj;
-    char cdummy;
-    int nullcheck = 1;
-    long inc[] = {1,1,1};
-    LONGLONG fpixel[] = {1,1,1};
-    LONGLONG lpixel[3];
-    float nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        lpixel[0] = ncols;
-        lpixel[1] = nrows;
-        lpixel[2] = naxis3;
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TFLOAT, fpixel, lpixel, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-       /* all the image pixels are contiguous, so read all at once */
-       ffgcle(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-       return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to read */
-    narray = 0;  /* next pixel in output array to be filled */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* reading naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffgcle(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
-          &array[narray], &cdummy, anynul, status) > 0)
-          return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsve(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           float nulval,   /* I - value to set undefined pixels             */
-           float *array,   /* O - array to be filled and returned           */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dir[9];
-    long nelem, nultyp, ninc, numcol;
-    LONGLONG felem, dsize[10], blcll[9], trcll[9];
-    int hdutype, anyf;
-    char ldummy, msg[FLEN_ERRMSG];
-    int nullcheck = 1;
-    float nullvalue;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsve is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TFLOAT, blcll, trcll, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 1;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-        dir[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        if (hdutype == IMAGE_HDU)
-        {
-           dir[ii] = -1;
-        }
-        else
-        {
-          sprintf(msg, "ffgsve: illegal range specified for axis %ld", ii + 1);
-          ffpmsg(msg);
-          return(*status = BAD_PIX_NUM);
-        }
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-      dsize[ii] = dsize[ii] * dir[ii];
-    }
-    dsize[naxis] = dsize[naxis] * dir[naxis];
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
-      ninc = incr[0] * dir[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
-            {
-
-              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
-                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
-                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
-                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];
-
-              if ( ffgcle(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsfe(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           float *array,   /* O - array to be filled and returned           */
-           char *flagval,  /* O - set to 1 if corresponding value is null   */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dsize[10];
-    LONGLONG blcll[9], trcll[9];
-    long felem, nelem, nultyp, ninc, numcol;
-    int hdutype, anyf;
-    float nulval = 0;
-    char msg[FLEN_ERRMSG];
-    int nullcheck = 2;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsve is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        fits_read_compressed_img(fptr, TFLOAT, blcll, trcll, inc,
-            nullcheck, NULL, array, flagval, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 2;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsve: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgcle(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffggpe( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            long  nelem,      /* I - number of values to read                */
-            float *array,     /* O - array of values that are returned       */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of group parameters from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-*/
-{
-    long row;
-    int idummy;
-    char cdummy;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcle(fptr, 1, row, firstelem, nelem, 1, 1, 0.F,
-               array, &cdummy, &idummy, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcve(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           float nulval,     /* I - value for null pixels                   */
-           float *array,     /* O - array of values that are read           */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy;
-
-    ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
-           array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcvc(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           float nulval,     /* I - value for null pixels                   */
-           float *array,     /* O - array of values that are read           */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-
-  TSCAL and ZERO should not be used with complex values. 
-*/
-{
-    char cdummy;
-
-    /* a complex value is interpreted as a pair of float values, thus */
-    /* need to multiply the first element and number of elements by 2 */
-
-    ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem *2,
-           1, 1, nulval, array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfe(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           float *array,     /* O - array of values that are read           */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-*/
-{
-    float dummy = 0;
-
-    ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
-           array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfc(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           float *array,     /* O - array of values that are read           */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-
-  TSCAL and ZERO should not be used with complex values. 
-*/
-{
-    LONGLONG ii, jj;
-    float dummy = 0;
-    char *carray;
-
-    /* a complex value is interpreted as a pair of float values, thus */
-    /* need to multiply the first element and number of elements by 2 */
-    
-    /* allocate temporary array */
-    carray = (char *) calloc( (size_t) (nelem * 2), 1); 
-
-    ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
-           1, 2, dummy, array, carray, anynul, status);
-
-    for (ii = 0, jj = 0; jj < nelem; ii += 2, jj++)
-    {
-       if (carray[ii] || carray[ii + 1])
-          nularray[jj] = 1;
-       else
-          nularray[jj] = 0;
-    }
-
-    free(carray);    
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcle( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-            float nulval,     /* I - value for null pixels if nultyp = 1     */
-            float *array,     /* O - array of values that are read           */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer be a virtual column in a 1 or more grouped FITS primary
-  array or image extension.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The output array of values will be converted from the datatype of the column 
-  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    double scale, zero, power = 1., dtemp;
-    int tcode, maxelem2, hdutype, xcode, decimals;
-    long twidth, incre;
-    long ii, xwidth, ntodo;
-    int convert, nulcheck, readcheck = 0;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull;
-    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
-    char tform[20];
-    char message[81];
-    char snull[20];   /*  the FITS null value if reading from ASCII table  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    if (anynul)
-       *anynul = 0;
-
-    if (nultyp == 2)
-        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (elemincre < 0)
-        readcheck = -1;  /* don't do range checking in this case */
-
-    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
-         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
-         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
-         return(*status);
-    maxelem = maxelem2;
-
-    incre *= elemincre;   /* multiply incre to just get every nth pixel */
-
-    if (tcode == TSTRING)    /* setup for ASCII tables */
-    {
-      /* get the number of implied decimal places if no explicit decmal point */
-      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
-      for(ii = 0; ii < decimals; ii++)
-        power *= 10.;
-    }
-
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
-            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
-            nulcheck = 0;            /* then do not check for null values. */
-
-    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
-         nulcheck = 0;
-
-    /*----------------------------------------------------------------------*/
-    /*  If FITS column and output data array have same datatype, then we do */
-    /*  not need to use a temporary buffer to store intermediate datatype.  */
-    /*----------------------------------------------------------------------*/
-    convert = 1;
-    if (tcode == TFLOAT) /* Special Case:                        */
-    {                             /* no type convertion required, so read */
-                                  /* data directly into output buffer.    */
-
-        if (nelem < (LONGLONG)INT32_MAX/4) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/4;
-        }
-
-        if (nulcheck == 0 && scale == 1. && zero == 0.)
-            convert = 0;  /* no need to scale data or find nulls */
-    }
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the pixels from the FITS column. If the column does not   */
-    /*  have the same datatype as the output array, then we have to read   */
-    /*  the raw values into a temporary buffer (of limited size).  In      */
-    /*  the case of a vector colum read only 1 vector of values at a time  */
-    /*  then skip to the next row if more values need to be read.          */
-    /*  After reading the raw values, then call the fffXXYY routine to (1) */
-    /*  test for undefined values, (2) convert the datatype if necessary,  */
-    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
-    /*  scaling parameters.                                                */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to read */
-    next = 0;                 /* next element in array to be read   */
-    rownum = 0;               /* row number, relative to firstrow   */
-
-    while (remain)
-    {
-        /* limit the number of pixels to read at one time to the number that
-           will fit in the buffer or to the number of pixels that remain in
-           the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);
-        if (elemincre >= 0)
-        {
-          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
-        }
-        else
-        {
-          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
-        }
-
-        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
-
-        switch (tcode) 
-        {
-            case (TFLOAT):
-                ffgr4b(fptr, readptr, ntodo, incre, &array[next], status);
-                if (convert)
-                    fffr4r4(&array[next], ntodo, scale, zero, nulcheck, 
-                           nulval, &nularray[next], anynul, 
-                           &array[next], status);
-                break;
-            case (TBYTE):
-                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
-                       status);
-                fffi1r4((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
-                    (unsigned char) tnull, nulval, &nularray[next], anynul, 
-                     &array[next], status);
-                break;
-            case (TSHORT):
-                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
-                fffi2r4((short  *) buffer, ntodo, scale, zero, nulcheck, 
-                       (short) tnull, nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TLONG):
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
-                       status);
-                fffi4r4((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
-                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-
-            case (TLONGLONG):
-                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
-                fffi8r4( (LONGLONG *) buffer, ntodo, scale, zero, 
-                           nulcheck, tnull, nulval, &nularray[next], 
-                            anynul, &array[next], status);
-                break;
-            case (TDOUBLE):
-                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
-                fffr8r4((double *) buffer, ntodo, scale, zero, nulcheck, 
-                          nulval, &nularray[next], anynul, 
-                          &array[next], status);
-                break;
-            case (TSTRING):
-                ffmbyt(fptr, readptr, REPORT_EOF, status);
-       
-                if (incre == twidth)    /* contiguous bytes */
-                     ffgbyt(fptr, ntodo * twidth, buffer, status);
-                else
-                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                               status);
-
-                fffstrr4((char *) buffer, ntodo, scale, zero, twidth, power,
-                     nulcheck, snull, nulval, &nularray[next], anynul,
-                     &array[next], status);
-                break;
-
-
-            default:  /*  error trap for invalid column format */
-                sprintf(message, 
-                   "Cannot read numbers from column %d which has format %s",
-                    colnum, tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous read operation */
-        {
-	  dtemp = (double) next;
-          if (hdutype > 0)
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from column %d (ffgcle).",
-              dtemp+1., dtemp+ntodo, colnum);
-          else
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from image (ffgcle).",
-              dtemp+1., dtemp+ntodo);
-
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum = elemnum + (ntodo * elemincre);
-
-            if (elemnum >= repeat)  /* completed a row; start on later row */
-            {
-                rowincre = elemnum / repeat;
-                rownum += rowincre;
-                elemnum = elemnum - (rowincre * repeat);
-            }
-            else if (elemnum < 0)  /* completed a row; start on a previous row */
-            {
-                rowincre = (-elemnum - 1) / repeat + 1;
-                rownum -= rowincre;
-                elemnum = (rowincre * repeat) + elemnum;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while reading FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi1r4(unsigned char *input, /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];  /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                output[ii] = (float) (( (double) input[ii] ) * scale + zero);
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (float) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    output[ii] = (float) (( (double) input[ii] ) * scale + zero);
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi2r4(short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];  /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                output[ii] = (float) (input[ii] * scale + zero);
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (float) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    output[ii] = (float) (input[ii] * scale + zero);
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi4r4(INT32BIT *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];  /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                output[ii] = (float) (input[ii] * scale + zero);
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (float) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    output[ii] = (float) (input[ii] * scale + zero);
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi8r4(LONGLONG *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];  /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                output[ii] = (float) (input[ii] * scale + zero);
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (float) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    output[ii] = (float) (input[ii] * scale + zero);
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr4r4(float *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            memmove(output, input, ntodo * sizeof(float) );
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                output[ii] = (float) (input[ii] * scale + zero);
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr++;       /* point to MSBs */
-#endif
-
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                    {
-                        nullarray[ii] = 1;
-                       /* explicitly set value in case output contains a NaN */
-                        output[ii] = FLOATNULLVALUE;
-                    }
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                output[ii] = input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                    {
-                        nullarray[ii] = 1;
-                       /* explicitly set value in case output contains a NaN */
-                        output[ii] = FLOATNULLVALUE;
-                    }
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = (float) zero;
-              }
-              else
-                  output[ii] = (float) (input[ii] * scale + zero);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr8r4(double *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii]; /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                output[ii] = (float) (input[ii] * scale + zero);
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr += 3;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                  output[ii] = (float) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = (float) zero;
-              }
-              else
-                  output[ii] = (float) (input[ii] * scale + zero);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffstrr4(char *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            long twidth,          /* I - width of each substring of chars    */
-            double implipower,    /* I - power of 10 of implied decimal      */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            char  *snull,         /* I - value of FITS null string, if any   */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file. Check
-  for null values and do scaling if required. The nullcheck code value
-  determines how any null values in the input array are treated. A null
-  value is an input pixel that is equal to snull.  If nullcheck= 0, then
-  no special checking for nulls is performed.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    int nullen;
-    long ii;
-    double dvalue;
-    char *cstring, message[81];
-    char *cptr, *tpos;
-    char tempstore, chrzero = '0';
-    double val, power;
-    int exponent, sign, esign, decpt;
-
-    nullen = strlen(snull);
-    cptr = input;  /* pointer to start of input string */
-    for (ii = 0; ii < ntodo; ii++)
-    {
-      cstring = cptr;
-      /* temporarily insert a null terminator at end of the string */
-      tpos = cptr + twidth;
-      tempstore = *tpos;
-      *tpos = 0;
-
-      /* check if null value is defined, and if the    */
-      /* column string is identical to the null string */
-      if (snull[0] != ASCII_NULL_UNDEFINED && 
-         !strncmp(snull, cptr, nullen) )
-      {
-        if (nullcheck)  
-        {
-          *anynull = 1;    
-          if (nullcheck == 1)
-            output[ii] = nullval;
-          else
-            nullarray[ii] = 1;
-        }
-        cptr += twidth;
-      }
-      else
-      {
-        /* value is not the null value, so decode it */
-        /* remove any embedded blank characters from the string */
-
-        decpt = 0;
-        sign = 1;
-        val  = 0.;
-        power = 1.;
-        exponent = 0;
-        esign = 1;
-
-        while (*cptr == ' ')               /* skip leading blanks */
-           cptr++;
-
-        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
-        {
-          if (*cptr == '-')
-             sign = -1;
-
-          cptr++;
-
-          while (*cptr == ' ')         /* skip blanks between sign and value */
-            cptr++;
-        }
-
-        while (*cptr >= '0' && *cptr <= '9')
-        {
-          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-          cptr++;
-
-          while (*cptr == ' ')         /* skip embedded blanks in the value */
-            cptr++;
-        }
-
-        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
-        {
-          decpt = 1;       /* set flag to show there was a decimal point */
-          cptr++;
-          while (*cptr == ' ')         /* skip any blanks */
-            cptr++;
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-            power = power * 10.;
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks in the value */
-              cptr++;
-          }
-        }
-
-        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
-        {
-          cptr++;
-          while (*cptr == ' ')         /* skip blanks */
-              cptr++;
-  
-          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
-          {
-            if (*cptr == '-')
-               esign = -1;
-
-            cptr++;
-
-            while (*cptr == ' ')        /* skip blanks between sign and exp */
-              cptr++;
-          }
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks */
-              cptr++;
-          }
-        }
-
-        if (*cptr  != 0)  /* should end up at the null terminator */
-        {
-          sprintf(message, "Cannot read number from ASCII table");
-          ffpmsg(message);
-          sprintf(message, "Column field = %s.", cstring);
-          ffpmsg(message);
-          /* restore the char that was overwritten by the null */
-          *tpos = tempstore;
-          return(*status = BAD_C2D);
-        }
-
-        if (!decpt)  /* if no explicit decimal, use implied */
-           power = implipower;
-
-        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
-
-        output[ii] = (float) (dvalue * scale + zero);   /* apply the scaling */
-
-      }
-      /* restore the char that was overwritten by the null */
-      *tpos = tempstore;
-    }
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcoli.c b/src/external/OpenGR/3rdparty/cfitsio/getcoli.c
deleted file mode 100644
index 03a0ca03b..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcoli.c
+++ /dev/null
@@ -1,1908 +0,0 @@
-/*  This file, getcoli.c, contains routines that read data elements from   */
-/*  a FITS image or table, with short datatype.                            */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffgpvi( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            short nulval,     /* I - value for undefined pixels              */
-            short *array,     /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    char cdummy;
-    int nullcheck = 1;
-    short nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-         nullvalue = nulval;  /* set local variable */
-        fits_read_compressed_pixels(fptr, TSHORT, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcli(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpfi( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            short *array,     /* O - array of values that are returned       */
-            char *nularray,   /* O - array of null pixel flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Any undefined pixels in the returned array will be set = 0 and the 
-  corresponding nularray value will be set = 1.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    int nullcheck = 2;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_read_compressed_pixels(fptr, TSHORT, firstelem, nelem,
-            nullcheck, NULL, array, nularray, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcli(fptr, 2, row, firstelem, nelem, 1, 2, 0,
-               array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg2di(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           short nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           short *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    /* call the 3D reading routine, with the 3rd dimension = 1 */
-
-    ffg3di(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
-           anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg3di(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           short nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
-           short *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 3-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    long tablerow, ii, jj;
-    LONGLONG nfits, narray;
-    char cdummy;
-    int nullcheck = 1;
-    long inc[] = {1,1,1};
-    LONGLONG fpixel[] = {1,1,1};
-    LONGLONG lpixel[3];
-    short nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        lpixel[0] = ncols;
-        lpixel[1] = nrows;
-        lpixel[2] = naxis3;
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TSHORT, fpixel, lpixel, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-       /* all the image pixels are contiguous, so read all at once */
-       ffgcli(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-       return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to read */
-    narray = 0;  /* next pixel in output array to be filled */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* reading naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffgcli(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
-          &array[narray], &cdummy, anynul, status) > 0)
-          return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsvi(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           short nulval,   /* I - value to set undefined pixels             */
-           short *array,   /* O - array to be filled and returned           */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dir[9];
-    long nelem, nultyp, ninc, numcol;
-    LONGLONG felem, dsize[10], blcll[9], trcll[9];
-    int hdutype, anyf;
-    char ldummy, msg[FLEN_ERRMSG];
-    int nullcheck = 1;
-    short nullvalue;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvi is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TSHORT, blcll, trcll, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 1;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-        dir[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        if (hdutype == IMAGE_HDU)
-        {
-           dir[ii] = -1;
-        }
-        else
-        {
-          sprintf(msg, "ffgsvi: illegal range specified for axis %ld", ii + 1);
-          ffpmsg(msg);
-          return(*status = BAD_PIX_NUM);
-        }
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-      dsize[ii] = dsize[ii] * dir[ii];
-    }
-    dsize[naxis] = dsize[naxis] * dir[naxis];
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
-      ninc = incr[0] * dir[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
-            {
-
-              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
-                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
-                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
-                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];
-
-              if ( ffgcli(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsfi(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           short *array,   /* O - array to be filled and returned           */
-           char *flagval,  /* O - set to 1 if corresponding value is null   */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dsize[10];
-    LONGLONG blcll[9], trcll[9];
-    long felem, nelem, nultyp, ninc, numcol;
-    int hdutype, anyf;
-    short nulval = 0;
-    char msg[FLEN_ERRMSG];
-    int nullcheck = 2;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvi is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        fits_read_compressed_img(fptr, TSHORT, blcll, trcll, inc,
-            nullcheck, NULL, array, flagval, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 2;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvi: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgcli(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffggpi( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            long  nelem,      /* I - number of values to read                */
-            short *array,     /* O - array of values that are returned       */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of group parameters from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-*/
-{
-    long row;
-    int idummy;
-    char cdummy;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcli(fptr, 1, row, firstelem, nelem, 1, 1, 0,
-               array, &cdummy, &idummy, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcvi(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           short nulval,     /* I - value for null pixels                   */
-           short *array,     /* O - array of values that are read           */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy;
-
-    ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
-           array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfi(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           short *array,     /* O - array of values that are read           */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-*/
-{
-    short dummy = 0;
-
-    ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
-           array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcli( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG  firstelem, /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-            short nulval,     /* I - value for null pixels if nultyp = 1     */
-            short *array,     /* O - array of values that are read           */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer be a virtual column in a 1 or more grouped FITS primary
-  array or image extension.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The output array of values will be converted from the datatype of the column 
-  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    double scale, zero, power = 1., dtemp;
-    int tcode, maxelem2, hdutype, xcode, decimals;
-    long twidth, incre;
-    long ii, xwidth, ntodo;
-    int convert, nulcheck, readcheck = 0;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull;
-    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
-    char tform[20];
-    char message[81];
-    char snull[20];   /*  the FITS null value if reading from ASCII table  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    if (anynul)
-        *anynul = 0;
-
-    if (nultyp == 2)
-        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (elemincre < 0)
-        readcheck = -1;  /* don't do range checking in this case */
-
-    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
-         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
-         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
-         return(*status);
-    maxelem = maxelem2;
-
-    incre *= elemincre;   /* multiply incre to just get every nth pixel */
-
-    if (tcode == TSTRING)    /* setup for ASCII tables */
-    {
-      /* get the number of implied decimal places if no explicit decmal point */
-      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
-      for(ii = 0; ii < decimals; ii++)
-        power *= 10.;
-    }
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
-            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
-            nulcheck = 0;            /* then do not check for null values. */
-
-    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
-         nulcheck = 0;
-
-    /*----------------------------------------------------------------------*/
-    /*  If FITS column and output data array have same datatype, then we do */
-    /*  not need to use a temporary buffer to store intermediate datatype.  */
-    /*----------------------------------------------------------------------*/
-    convert = 1;
-    if (tcode == TSHORT) /* Special Case:                        */
-    {                             /* no type convertion required, so read */
-                                  /* data directly into output buffer.    */
-
-        if (nelem < (LONGLONG)INT32_MAX/2) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/2;
-        }
-
-        if (nulcheck == 0 && scale == 1. && zero == 0.)
-            convert = 0;  /* no need to scale data or find nulls */
-    }
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the pixels from the FITS column. If the column does not   */
-    /*  have the same datatype as the output array, then we have to read   */
-    /*  the raw values into a temporary buffer (of limited size).  In      */
-    /*  the case of a vector colum read only 1 vector of values at a time  */
-    /*  then skip to the next row if more values need to be read.          */
-    /*  After reading the raw values, then call the fffXXYY routine to (1) */
-    /*  test for undefined values, (2) convert the datatype if necessary,  */
-    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
-    /*  scaling parameters.                                                */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to read */
-    next = 0;                 /* next element in array to be read   */
-    rownum = 0;               /* row number, relative to firstrow   */
-
-    while (remain)
-    {
-        /* limit the number of pixels to read at one time to the number that
-           will fit in the buffer or to the number of pixels that remain in
-           the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);
-        if (elemincre >= 0)
-        {
-          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
-        }
-        else
-        {
-          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
-        }
-
-        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
-
-        switch (tcode) 
-        {
-            case (TSHORT):
-                ffgi2b(fptr, readptr, ntodo, incre, &array[next], status);
-                if (convert)
-                    fffi2i2(&array[next], ntodo, scale, zero, nulcheck, 
-                           (short) tnull, nulval, &nularray[next], anynul, 
-                           &array[next], status);
-                break;
-            case (TLONGLONG):
-
-                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
-                fffi8i2( (LONGLONG *) buffer, ntodo, scale, zero, 
-                           nulcheck, tnull, nulval, &nularray[next], 
-                            anynul, &array[next], status);
-                break;
-            case (TBYTE):
-                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
-                      status);
-                fffi1i2((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
-                    (unsigned char) tnull, nulval, &nularray[next], anynul, 
-                    &array[next], status);
-                break;
-            case (TLONG):
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
-                       status);
-                fffi4i2((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
-                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TFLOAT):
-                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
-                fffr4i2((float  *) buffer, ntodo, scale, zero, nulcheck, 
-                       nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TDOUBLE):
-                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
-                fffr8i2((double *) buffer, ntodo, scale, zero, nulcheck, 
-                          nulval, &nularray[next], anynul, 
-                          &array[next], status);
-                break;
-            case (TSTRING):
-                ffmbyt(fptr, readptr, REPORT_EOF, status);
-       
-                if (incre == twidth)    /* contiguous bytes */
-                     ffgbyt(fptr, ntodo * twidth, buffer, status);
-                else
-                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                               status);
-
-                fffstri2((char *) buffer, ntodo, scale, zero, twidth, power,
-                     nulcheck, snull, nulval, &nularray[next], anynul,
-                     &array[next], status);
-                break;
-
-            default:  /*  error trap for invalid column format */
-                sprintf(message, 
-                   "Cannot read numbers from column %d which has format %s",
-                    colnum, tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous read operation */
-        {
-	  dtemp = (double) next;
-          if (hdutype > 0)
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from column %d (ffgcli).",
-              dtemp+1, dtemp+ntodo, colnum);
-          else
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from image (ffgcli).",
-              dtemp+1, dtemp+ntodo);
-
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum = elemnum + (ntodo * elemincre);
-
-            if (elemnum >= repeat)  /* completed a row; start on later row */
-            {
-                rowincre = elemnum / repeat;
-                rownum += rowincre;
-                elemnum = elemnum - (rowincre * repeat);
-            }
-            else if (elemnum < 0) /* completed a row; start on a previous row */
-            {
-                rowincre = (-elemnum - 1) / repeat + 1;
-                rownum -= rowincre;
-                elemnum = (rowincre * repeat) + elemnum;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while reading FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi1i2(unsigned char *input, /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-            short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (short) input[ii];  /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MIN;
-                }
-                else if (dvalue > DSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MAX;
-                }
-                else
-                    output[ii] = (short) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (short) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MIN;
-                    }
-                    else if (dvalue > DSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MAX;
-                    }
-                    else
-                        output[ii] = (short) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi2i2(short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-            short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            memmove(output, input, ntodo * sizeof(short) );
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MIN;
-                }
-                else if (dvalue > DSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MAX;
-                }
-                else
-                    output[ii] = (short) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MIN;
-                    }
-                    else if (dvalue > DSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MAX;
-                    }
-                    else
-                        output[ii] = (short) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi4i2(INT32BIT *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-            short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < SHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MIN;
-                }
-                else if (input[ii] > SHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MAX;
-                }
-                else
-                    output[ii] = (short) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MIN;
-                }
-                else if (dvalue > DSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MAX;
-                }
-                else
-                    output[ii] = (short) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < SHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MIN;
-                    }
-                    else if (input[ii] > SHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MAX;
-                    }
-                    else
-                        output[ii] = (short) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MIN;
-                    }
-                    else if (dvalue > DSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MAX;
-                    }
-                    else
-                        output[ii] = (short) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi8i2(LONGLONG *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
-            short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < SHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MIN;
-                }
-                else if (input[ii] > SHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MAX;
-                }
-                else
-                    output[ii] = (short) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MIN;
-                }
-                else if (dvalue > DSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MAX;
-                }
-                else
-                    output[ii] = (short) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < SHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MIN;
-                    }
-                    else if (input[ii] > SHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MAX;
-                    }
-                    else
-                        output[ii] = (short) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MIN;
-                    }
-                    else if (dvalue > DSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MAX;
-                    }
-                    else
-                        output[ii] = (short) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr4i2(float *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MIN;
-                }
-                else if (input[ii] > DSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MAX;
-                }
-                else
-                    output[ii] = (short) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MIN;
-                }
-                else if (dvalue > DSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MAX;
-                }
-                else
-                    output[ii] = (short) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr++;       /* point to MSBs */
-#endif
-
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MIN;
-                    }
-                    else if (input[ii] > DSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MAX;
-                    }
-                    else
-                        output[ii] = (short) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  {
-                    if (zero < DSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MIN;
-                    }
-                    else if (zero > DSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MAX;
-                    }
-                    else
-                        output[ii] = (short) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MIN;
-                    }
-                    else if (dvalue > DSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MAX;
-                    }
-                    else
-                        output[ii] = (short) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr8i2(double *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MIN;
-                }
-                else if (input[ii] > DSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MAX;
-                }
-                else
-                    output[ii] = (short) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MIN;
-                }
-                else if (dvalue > DSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = SHRT_MAX;
-                }
-                else
-                    output[ii] = (short) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr += 3;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MIN;
-                    }
-                    else if (input[ii] > DSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MAX;
-                    }
-                    else
-                        output[ii] = (short) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  {
-                    if (zero < DSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MIN;
-                    }
-                    else if (zero > DSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MAX;
-                    }
-                    else
-                        output[ii] = (short) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MIN;
-                    }
-                    else if (dvalue > DSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = SHRT_MAX;
-                    }
-                    else
-                        output[ii] = (short) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffstri2(char *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            long twidth,          /* I - width of each substring of chars    */
-            double implipower,    /* I - power of 10 of implied decimal      */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            char  *snull,         /* I - value of FITS null string, if any   */
-            short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file. Check
-  for null values and do scaling if required. The nullcheck code value
-  determines how any null values in the input array are treated. A null
-  value is an input pixel that is equal to snull.  If nullcheck= 0, then
-  no special checking for nulls is performed.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    int nullen;
-    long ii;
-    double dvalue;
-    char *cstring, message[81];
-    char *cptr, *tpos;
-    char tempstore, chrzero = '0';
-    double val, power;
-    int exponent, sign, esign, decpt;
-
-    nullen = strlen(snull);
-    cptr = input;  /* pointer to start of input string */
-    for (ii = 0; ii < ntodo; ii++)
-    {
-      cstring = cptr;
-      /* temporarily insert a null terminator at end of the string */
-      tpos = cptr + twidth;
-      tempstore = *tpos;
-      *tpos = 0;
-
-      /* check if null value is defined, and if the    */
-      /* column string is identical to the null string */
-      if (snull[0] != ASCII_NULL_UNDEFINED && 
-         !strncmp(snull, cptr, nullen) )
-      {
-        if (nullcheck)  
-        {
-          *anynull = 1;    
-          if (nullcheck == 1)
-            output[ii] = nullval;
-          else
-            nullarray[ii] = 1;
-        }
-        cptr += twidth;
-      }
-      else
-      {
-        /* value is not the null value, so decode it */
-        /* remove any embedded blank characters from the string */
-
-        decpt = 0;
-        sign = 1;
-        val  = 0.;
-        power = 1.;
-        exponent = 0;
-        esign = 1;
-
-        while (*cptr == ' ')               /* skip leading blanks */
-           cptr++;
-
-        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
-        {
-          if (*cptr == '-')
-             sign = -1;
-
-          cptr++;
-
-          while (*cptr == ' ')         /* skip blanks between sign and value */
-            cptr++;
-        }
-
-        while (*cptr >= '0' && *cptr <= '9')
-        {
-          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-          cptr++;
-
-          while (*cptr == ' ')         /* skip embedded blanks in the value */
-            cptr++;
-        }
-
-        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
-        {
-          decpt = 1;       /* set flag to show there was a decimal point */
-          cptr++;
-          while (*cptr == ' ')         /* skip any blanks */
-            cptr++;
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-            power = power * 10.;
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks in the value */
-              cptr++;
-          }
-        }
-
-        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
-        {
-          cptr++;
-          while (*cptr == ' ')         /* skip blanks */
-              cptr++;
-  
-          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
-          {
-            if (*cptr == '-')
-               esign = -1;
-
-            cptr++;
-
-            while (*cptr == ' ')        /* skip blanks between sign and exp */
-              cptr++;
-          }
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks */
-              cptr++;
-          }
-        }
-
-        if (*cptr  != 0)  /* should end up at the null terminator */
-        {
-          sprintf(message, "Cannot read number from ASCII table");
-          ffpmsg(message);
-          sprintf(message, "Column field = %s.", cstring);
-          ffpmsg(message);
-          /* restore the char that was overwritten by the null */
-          *tpos = tempstore;
-          return(*status = BAD_C2D);
-        }
-
-        if (!decpt)  /* if no explicit decimal, use implied */
-           power = implipower;
-
-        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
-
-        dvalue = dvalue * scale + zero;   /* apply the scaling */
-
-        if (dvalue < DSHRT_MIN)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = SHRT_MIN;
-        }
-        else if (dvalue > DSHRT_MAX)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = SHRT_MAX;
-        }
-        else
-            output[ii] = (short) dvalue;
-      }
-      /* restore the char that was overwritten by the null */
-      *tpos = tempstore;
-    }
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcolj.c b/src/external/OpenGR/3rdparty/cfitsio/getcolj.c
deleted file mode 100644
index 2017d6a5d..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcolj.c
+++ /dev/null
@@ -1,3746 +0,0 @@
-/*  This file, getcolj.c, contains routines that read data elements from   */
-/*  a FITS image or table, with long data type.                            */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffgpvj( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  nulval,     /* I - value for undefined pixels              */
-            long  *array,     /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    char cdummy;
-    int nullcheck = 1;
-    long nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-         nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_pixels(fptr, TLONG, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclj(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpfj( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  *array,     /* O - array of values that are returned       */
-            char *nularray,   /* O - array of null pixel flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Any undefined pixels in the returned array will be set = 0 and the 
-  corresponding nularray value will be set = 1.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    int nullcheck = 2;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_read_compressed_pixels(fptr, TLONG, firstelem, nelem,
-            nullcheck, NULL, array, nularray, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclj(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
-               array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg2dj(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           long  nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           long  *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    /* call the 3D reading routine, with the 3rd dimension = 1 */
-
-    ffg3dj(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
-           anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg3dj(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           long  nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
-           long  *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 3-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    long tablerow, ii, jj;
-    char cdummy;
-    int nullcheck = 1;
-    long inc[] = {1,1,1};
-    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
-    LONGLONG lpixel[3], nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        lpixel[0] = ncols;
-        lpixel[1] = nrows;
-        lpixel[2] = naxis3;
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TLONG, fpixel, lpixel, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-       /* all the image pixels are contiguous, so read all at once */
-       ffgclj(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-       return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to read */
-    narray = 0;  /* next pixel in output array to be filled */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* reading naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffgclj(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
-          &array[narray], &cdummy, anynul, status) > 0)
-          return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsvj(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           long nulval,    /* I - value to set undefined pixels             */
-           long *array,    /* O - array to be filled and returned           */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dir[9];
-    long nelem, nultyp, ninc, numcol;
-    LONGLONG felem, dsize[10], blcll[9], trcll[9];
-    int hdutype, anyf;
-    char ldummy, msg[FLEN_ERRMSG];
-    int nullcheck = 1;
-    long nullvalue;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvj is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TLONG, blcll, trcll, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 1;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-        dir[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        if (hdutype == IMAGE_HDU)
-        {
-           dir[ii] = -1;
-        }
-        else
-        {
-          sprintf(msg, "ffgsvj: illegal range specified for axis %ld", ii + 1);
-          ffpmsg(msg);
-          return(*status = BAD_PIX_NUM);
-        }
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-      dsize[ii] = dsize[ii] * dir[ii];
-    }
-    dsize[naxis] = dsize[naxis] * dir[naxis];
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
-      ninc = incr[0] * dir[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
-            {
-
-              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
-                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
-                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
-                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];
-
-              if ( ffgclj(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsfj(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           long *array,    /* O - array to be filled and returned           */
-           char *flagval,  /* O - set to 1 if corresponding value is null   */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dsize[10];
-    LONGLONG blcll[9], trcll[9];
-    long felem, nelem, nultyp, ninc, numcol;
-    long nulval = 0;
-    int hdutype, anyf;
-    char msg[FLEN_ERRMSG];
-    int nullcheck = 2;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvj is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        fits_read_compressed_img(fptr, TLONG, blcll, trcll, inc,
-            nullcheck, NULL, array, flagval, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 2;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvj: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgclj(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffggpj( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            long  nelem,      /* I - number of values to read                */
-            long  *array,     /* O - array of values that are returned       */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of group parameters from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-*/
-{
-    long row;
-    int idummy;
-    char cdummy;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclj(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
-               array, &cdummy, &idummy, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcvj(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           long  nulval,     /* I - value for null pixels                   */
-           long *array,      /* O - array of values that are read           */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy;
-
-    ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
-           array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfj(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           long  *array,     /* O - array of values that are read           */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-*/
-{
-    long dummy = 0;
-
-    ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
-           array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgclj( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-            long  nulval,     /* I - value for null pixels if nultyp = 1     */
-            long  *array,     /* O - array of values that are read           */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer be a virtual column in a 1 or more grouped FITS primary
-  array or image extension.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The output array of values will be converted from the datatype of the column 
-  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    double scale, zero, power = 1., dtemp;
-    int tcode, maxelem2, hdutype, xcode, decimals;
-    long twidth, incre;
-    long ii, xwidth, ntodo;
-    int convert, nulcheck, readcheck = 0;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull;
-    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
-    char tform[20];
-    char message[81];
-    char snull[20];   /*  the FITS null value if reading from ASCII table  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    if (anynul)
-        *anynul = 0;
-
-    if (nultyp == 2)
-        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (elemincre < 0)
-        readcheck = -1;  /* don't do range checking in this case */
-
-    if (ffgcprll(fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
-         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
-         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
-         return(*status);
-    maxelem = maxelem2;
-
-    incre *= elemincre;   /* multiply incre to just get every nth pixel */
-
-    if (tcode == TSTRING)    /* setup for ASCII tables */
-    {
-      /* get the number of implied decimal places if no explicit decmal point */
-      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
-      for(ii = 0; ii < decimals; ii++)
-        power *= 10.;
-    }
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
-            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
-            nulcheck = 0;            /* then do not check for null values. */
-
-    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
-         nulcheck = 0;
-
-    /*----------------------------------------------------------------------*/
-    /*  If FITS column and output data array have same datatype, then we do */
-    /*  not need to use a temporary buffer to store intermediate datatype.  */
-    /*----------------------------------------------------------------------*/
-    convert = 1;
-    if ((tcode == TLONG) && (LONGSIZE == 32))  /* Special Case:                        */
-    {                             /* no type convertion required, so read */
-                                  /* data directly into output buffer.    */
-
-        if (nelem < (LONGLONG)INT32_MAX/4) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/4;   
-        }
-
-        if (nulcheck == 0 && scale == 1. && zero == 0. )
-            convert = 0;  /* no need to scale data or find nulls */
-    }
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the pixels from the FITS column. If the column does not   */
-    /*  have the same datatype as the output array, then we have to read   */
-    /*  the raw values into a temporary buffer (of limited size).  In      */
-    /*  the case of a vector colum read only 1 vector of values at a time  */
-    /*  then skip to the next row if more values need to be read.          */
-    /*  After reading the raw values, then call the fffXXYY routine to (1) */
-    /*  test for undefined values, (2) convert the datatype if necessary,  */
-    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
-    /*  scaling parameters.                                                */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to read */
-    next = 0;                 /* next element in array to be read   */
-    rownum = 0;               /* row number, relative to firstrow   */
-
-    while (remain)
-    {
-        /* limit the number of pixels to read at one time to the number that
-           will fit in the buffer or to the number of pixels that remain in
-           the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);
-        if (elemincre >= 0)
-        {
-          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
-        }
-        else
-        {
-          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
-        }
-
-        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
-
-        switch (tcode) 
-        {
-            case (TLONG):
-	      if (LONGSIZE == 32) {
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
-                       status);
-                if (convert)
-                    fffi4i4((INT32BIT *) &array[next], ntodo, scale, zero, 
-                           nulcheck, (INT32BIT) tnull, nulval, &nularray[next], 
-                            anynul, &array[next], status);
-	      } else { /* case where sizeof(long) = 8 */
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
-                       status);
-                if (convert)
-                    fffi4i4((INT32BIT *) buffer, ntodo, scale, zero, 
-                           nulcheck, (INT32BIT) tnull, nulval, &nularray[next], 
-                            anynul, &array[next], status);
-	      }
-
-                break;
-            case (TLONGLONG):
-                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
-                fffi8i4((LONGLONG *) buffer, ntodo, scale, zero, 
-                           nulcheck, tnull, nulval, &nularray[next], 
-                            anynul, &array[next], status);
-                break;
-            case (TBYTE):
-                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
-                       status);
-                fffi1i4((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
-                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
-                     &array[next], status);
-                break;
-            case (TSHORT):
-                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
-                fffi2i4((short  *) buffer, ntodo, scale, zero, nulcheck, 
-                      (short) tnull, nulval, &nularray[next], anynul, 
-                      &array[next], status);
-                break;
-            case (TFLOAT):
-                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
-                fffr4i4((float  *) buffer, ntodo, scale, zero, nulcheck, 
-                       nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TDOUBLE):
-                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
-                fffr8i4((double *) buffer, ntodo, scale, zero, nulcheck, 
-                          nulval, &nularray[next], anynul, 
-                          &array[next], status);
-                break;
-            case (TSTRING):
-                ffmbyt(fptr, readptr, REPORT_EOF, status);
-       
-                if (incre == twidth)    /* contiguous bytes */
-                     ffgbyt(fptr, ntodo * twidth, buffer, status);
-                else
-                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                               status);
-
-                fffstri4((char *) buffer, ntodo, scale, zero, twidth, power,
-                     nulcheck, snull, nulval, &nularray[next], anynul,
-                     &array[next], status);
-                break;
-
-            default:  /*  error trap for invalid column format */
-                sprintf(message, 
-                   "Cannot read numbers from column %d which has format %s",
-                    colnum, tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous read operation */
-        {
-	  dtemp = (double) next;
-          if (hdutype > 0)
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from column %d (ffgclj).",
-              dtemp+1., dtemp+ntodo, colnum);
-          else
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from image (ffgclj).",
-              dtemp+1., dtemp+ntodo);
-
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum = elemnum + (ntodo * elemincre);
-
-            if (elemnum >= repeat)  /* completed a row; start on later row */
-            {
-                rowincre = elemnum / repeat;
-                rownum += rowincre;
-                elemnum = elemnum - (rowincre * repeat);
-            }
-            else if (elemnum < 0)  /* completed a row; start on a previous row */
-            {
-                rowincre = (-elemnum - 1) / repeat + 1;
-                rownum -= rowincre;
-                elemnum = (rowincre * repeat) + elemnum;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while reading FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi1i4(unsigned char *input, /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-            long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (long) input[ii];  /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MIN;
-                }
-                else if (dvalue > DLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MAX;
-                }
-                else
-                    output[ii] = (long) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (long) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MIN;
-                    }
-                    else if (dvalue > DLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MAX;
-                    }
-                    else
-                        output[ii] = (long) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi2i4(short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-            long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (long) input[ii];   /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MIN;
-                }
-                else if (dvalue > DLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MAX;
-                }
-                else
-                    output[ii] = (long) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (long) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MIN;
-                    }
-                    else if (dvalue > DLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MAX;
-                    }
-                    else
-                        output[ii] = (long) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi4i4(INT32BIT *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-            long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++) { 
-                 output[ii] = (long) input[ii];   /* copy input to output */
-	    }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MIN;
-                }
-                else if (dvalue > DLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MAX;
-                }
-                else
-                    output[ii] = (long) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MIN;
-                    }
-                    else if (dvalue > DLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MAX;
-                    }
-                    else
-                        output[ii] = (long) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi8i4(LONGLONG *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
-            long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < LONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MIN;
-                }
-                else if (input[ii] > LONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MAX;
-                }
-                else
-                    output[ii] = (long) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MIN;
-                }
-                else if (dvalue > DLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MAX;
-                }
-                else
-                    output[ii] = (long) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < LONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MIN;
-                    }
-                    else if (input[ii] > LONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MAX;
-                    }
-                    else
-                        output[ii] = (long) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MIN;
-                    }
-                    else if (dvalue > DLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MAX;
-                    }
-                    else
-                        output[ii] = (long) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr4i4(float *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MIN;
-                }
-                else if (input[ii] > DLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MAX;
-                }
-                else
-                    output[ii] = (long) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MIN;
-                }
-                else if (dvalue > DLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MAX;
-                }
-                else
-                    output[ii] = (long) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr++;       /* point to MSBs */
-#endif
-
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MIN;
-                    }
-                    else if (input[ii] > DLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MAX;
-                    }
-                    else
-                        output[ii] = (long) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  {
-                    if (zero < DLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MIN;
-                    }
-                    else if (zero > DLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MAX;
-                    }
-                    else
-                        output[ii] = (long) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MIN;
-                    }
-                    else if (dvalue > DLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MAX;
-                    }
-                    else
-                        output[ii] = (long) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr8i4(double *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MIN;
-                }
-                else if (input[ii] > DLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MAX;
-                }
-                else
-                    output[ii] = (long) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MIN;
-                }
-                else if (dvalue > DLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONG_MAX;
-                }
-                else
-                    output[ii] = (long) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr += 3;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MIN;
-                    }
-                    else if (input[ii] > DLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MAX;
-                    }
-                    else
-                        output[ii] = (long) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  {
-                    if (zero < DLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MIN;
-                    }
-                    else if (zero > DLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MAX;
-                    }
-                    else
-                        output[ii] = (long) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MIN;
-                    }
-                    else if (dvalue > DLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONG_MAX;
-                    }
-                    else
-                        output[ii] = (long) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffstri4(char *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            long twidth,          /* I - width of each substring of chars    */
-            double implipower,    /* I - power of 10 of implied decimal      */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            char  *snull,         /* I - value of FITS null string, if any   */
-            long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file. Check
-  for null values and do scaling if required. The nullcheck code value
-  determines how any null values in the input array are treated. A null
-  value is an input pixel that is equal to snull.  If nullcheck= 0, then
-  no special checking for nulls is performed.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    int nullen;
-    long ii;
-    double dvalue;
-    char *cstring, message[81];
-    char *cptr, *tpos;
-    char tempstore, chrzero = '0';
-    double val, power;
-    int exponent, sign, esign, decpt;
-
-    nullen = strlen(snull);
-    cptr = input;  /* pointer to start of input string */
-    for (ii = 0; ii < ntodo; ii++)
-    {
-      cstring = cptr;
-      /* temporarily insert a null terminator at end of the string */
-      tpos = cptr + twidth;
-      tempstore = *tpos;
-      *tpos = 0;
-
-      /* check if null value is defined, and if the    */
-      /* column string is identical to the null string */
-      if (snull[0] != ASCII_NULL_UNDEFINED && 
-         !strncmp(snull, cptr, nullen) )
-      {
-        if (nullcheck)  
-        {
-          *anynull = 1;    
-          if (nullcheck == 1)
-            output[ii] = nullval;
-          else
-            nullarray[ii] = 1;
-        }
-        cptr += twidth;
-      }
-      else
-      {
-        /* value is not the null value, so decode it */
-        /* remove any embedded blank characters from the string */
-
-        decpt = 0;
-        sign = 1;
-        val  = 0.;
-        power = 1.;
-        exponent = 0;
-        esign = 1;
-
-        while (*cptr == ' ')               /* skip leading blanks */
-           cptr++;
-
-        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
-        {
-          if (*cptr == '-')
-             sign = -1;
-
-          cptr++;
-
-          while (*cptr == ' ')         /* skip blanks between sign and value */
-            cptr++;
-        }
-
-        while (*cptr >= '0' && *cptr <= '9')
-        {
-          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-          cptr++;
-
-          while (*cptr == ' ')         /* skip embedded blanks in the value */
-            cptr++;
-        }
-
-        if (*cptr == '.' || *cptr == ',')    /* check for decimal point */
-        {
-          decpt = 1;       /* set flag to show there was a decimal point */
-          cptr++;
-          while (*cptr == ' ')         /* skip any blanks */
-            cptr++;
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-            power = power * 10.;
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks in the value */
-              cptr++;
-          }
-        }
-
-        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
-        {
-          cptr++;
-          while (*cptr == ' ')         /* skip blanks */
-              cptr++;
-  
-          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
-          {
-            if (*cptr == '-')
-               esign = -1;
-
-            cptr++;
-
-            while (*cptr == ' ')        /* skip blanks between sign and exp */
-              cptr++;
-          }
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks */
-              cptr++;
-          }
-        }
-
-        if (*cptr  != 0)  /* should end up at the null terminator */
-        {
-          sprintf(message, "Cannot read number from ASCII table");
-          ffpmsg(message);
-          sprintf(message, "Column field = %s.", cstring);
-          ffpmsg(message);
-          /* restore the char that was overwritten by the null */
-          *tpos = tempstore;
-          return(*status = BAD_C2D);
-        }
-
-        if (!decpt)  /* if no explicit decimal, use implied */
-           power = implipower;
-
-        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
-
-        dvalue = dvalue * scale + zero;   /* apply the scaling */
-
-        if (dvalue < DLONG_MIN)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = LONG_MIN;
-        }
-        else if (dvalue > DLONG_MAX)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = LONG_MAX;
-        }
-        else
-            output[ii] = (long) dvalue;
-      }
-      /* restore the char that was overwritten by the null */
-      *tpos = tempstore;
-    }
-    return(*status);
-}
-
-/* ======================================================================== */
-/*      the following routines support the 'long long' data type            */
-/* ======================================================================== */
-
-/*--------------------------------------------------------------------------*/
-int ffgpvjj(fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            LONGLONG  nulval, /* I - value for undefined pixels              */
-            LONGLONG  *array, /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    char cdummy;
-    int nullcheck = 1;
-    LONGLONG nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-         nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_pixels(fptr, TLONGLONG, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcljj(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpfjj(fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            LONGLONG  *array, /* O - array of values that are returned       */
-            char *nularray,   /* O - array of null pixel flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Any undefined pixels in the returned array will be set = 0 and the 
-  corresponding nularray value will be set = 1.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    int nullcheck = 2;
-    LONGLONG dummy = 0;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_read_compressed_pixels(fptr, TLONGLONG, firstelem, nelem,
-            nullcheck, NULL, array, nularray, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcljj(fptr, 2, row, firstelem, nelem, 1, 2, dummy,
-               array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg2djj(fitsfile *fptr, /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           LONGLONG nulval ,/* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           LONGLONG  *array,/* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    /* call the 3D reading routine, with the 3rd dimension = 1 */
-
-    ffg3djj(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
-           anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg3djj(fitsfile *fptr, /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           LONGLONG nulval, /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
-           LONGLONG  *array,/* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 3-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    long tablerow, ii, jj;
-    char cdummy;
-    int nullcheck = 1;
-    long inc[] = {1,1,1};
-    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
-    LONGLONG lpixel[3];
-    LONGLONG nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        lpixel[0] = ncols;
-        lpixel[1] = nrows;
-        lpixel[2] = naxis3;
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TLONGLONG, fpixel, lpixel, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-       /* all the image pixels are contiguous, so read all at once */
-       ffgcljj(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-       return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to read */
-    narray = 0;  /* next pixel in output array to be filled */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* reading naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffgcljj(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
-          &array[narray], &cdummy, anynul, status) > 0)
-          return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsvjj(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           LONGLONG nulval,/* I - value to set undefined pixels             */
-           LONGLONG *array,/* O - array to be filled and returned           */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dir[9];
-    long nelem, nultyp, ninc, numcol;
-    LONGLONG felem, dsize[10], blcll[9], trcll[9];
-    int hdutype, anyf;
-    char ldummy, msg[FLEN_ERRMSG];
-    int nullcheck = 1;
-    LONGLONG nullvalue;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvj is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TLONGLONG, blcll, trcll, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 1;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-        dir[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        if (hdutype == IMAGE_HDU)
-        {
-           dir[ii] = -1;
-        }
-        else
-        {
-          sprintf(msg, "ffgsvj: illegal range specified for axis %ld", ii + 1);
-          ffpmsg(msg);
-          return(*status = BAD_PIX_NUM);
-        }
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-      dsize[ii] = dsize[ii] * dir[ii];
-    }
-    dsize[naxis] = dsize[naxis] * dir[naxis];
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
-      ninc = incr[0] * dir[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
-            {
-
-              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
-                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
-                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
-                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];
-
-              if ( ffgcljj(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsfjj(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           LONGLONG *array,/* O - array to be filled and returned           */
-           char *flagval,  /* O - set to 1 if corresponding value is null   */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dsize[10];
-    LONGLONG blcll[9], trcll[9];
-    long felem, nelem, nultyp, ninc, numcol;
-    LONGLONG nulval = 0;
-    int hdutype, anyf;
-    char msg[FLEN_ERRMSG];
-    int nullcheck = 2;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvj is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-         fits_read_compressed_img(fptr, TLONGLONG, blcll, trcll, inc,
-            nullcheck, NULL, array, flagval, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 2;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvj: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgcljj(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffggpjj(fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            long  nelem,      /* I - number of values to read                */
-            LONGLONG  *array, /* O - array of values that are returned       */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of group parameters from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-*/
-{
-    long row;
-    int idummy;
-    char cdummy;
-    LONGLONG dummy = 0;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcljj(fptr, 1, row, firstelem, nelem, 1, 1, dummy,
-               array, &cdummy, &idummy, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcvjj(fitsfile *fptr,  /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           LONGLONG  nulval, /* I - value for null pixels                   */
-           LONGLONG *array,  /* O - array of values that are read           */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy;
-
-    ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
-           array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfjj(fitsfile *fptr,  /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           LONGLONG  *array, /* O - array of values that are read           */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-*/
-{
-    LONGLONG dummy = 0;
-
-    ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
-           array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcljj( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-            LONGLONG  nulval, /* I - value for null pixels if nultyp = 1     */
-            LONGLONG  *array, /* O - array of values that are read           */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer be a virtual column in a 1 or more grouped FITS primary
-  array or image extension.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The output array of values will be converted from the datatype of the column 
-  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    double scale, zero, power = 1., dtemp;
-    int tcode, maxelem2, hdutype, xcode, decimals;
-    long twidth, incre;
-    long ii, xwidth, ntodo;
-    int convert, nulcheck, readcheck = 0;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull;
-    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
-    char tform[20];
-    char message[81];
-    char snull[20];   /*  the FITS null value if reading from ASCII table  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    if (anynul)
-        *anynul = 0;
-
-    if (nultyp == 2)
-        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (elemincre < 0)
-        readcheck = -1;  /* don't do range checking in this case */
-
-    if (ffgcprll(fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
-         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
-         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
-         return(*status);
-    maxelem = maxelem2;
-
-    incre *= elemincre;   /* multiply incre to just get every nth pixel */
-
-    if (tcode == TSTRING)    /* setup for ASCII tables */
-    {
-      /* get the number of implied decimal places if no explicit decmal point */
-      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
-      for(ii = 0; ii < decimals; ii++)
-        power *= 10.;
-    }
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
-            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
-            nulcheck = 0;            /* then do not check for null values. */
-
-    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
-         nulcheck = 0;
-
-    /*----------------------------------------------------------------------*/
-    /*  If FITS column and output data array have same datatype, then we do */
-    /*  not need to use a temporary buffer to store intermediate datatype.  */
-    /*----------------------------------------------------------------------*/
-    convert = 1;
-    if (tcode == TLONGLONG)  /* Special Case:                        */
-    {                             /* no type convertion required, so read */
-                                  /* data directly into output buffer.    */
-
-        if (nelem < (LONGLONG)INT32_MAX/8) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/8;
-        }
-
-        if (nulcheck == 0 && scale == 1. && zero == 0.)
-            convert = 0;  /* no need to scale data or find nulls */
-    }
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the pixels from the FITS column. If the column does not   */
-    /*  have the same datatype as the output array, then we have to read   */
-    /*  the raw values into a temporary buffer (of limited size).  In      */
-    /*  the case of a vector colum read only 1 vector of values at a time  */
-    /*  then skip to the next row if more values need to be read.          */
-    /*  After reading the raw values, then call the fffXXYY routine to (1) */
-    /*  test for undefined values, (2) convert the datatype if necessary,  */
-    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
-    /*  scaling parameters.                                                */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to read */
-    next = 0;                 /* next element in array to be read   */
-    rownum = 0;               /* row number, relative to firstrow   */
-
-    while (remain)
-    {
-        /* limit the number of pixels to read at one time to the number that
-           will fit in the buffer or to the number of pixels that remain in
-           the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);
-        if (elemincre >= 0)
-        {
-          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
-        }
-        else
-        {
-          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
-        }
-
-        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
-
-        switch (tcode) 
-        {
-            case (TLONGLONG):
-                ffgi8b(fptr, readptr, ntodo, incre, (long *) &array[next],
-                       status);
-                if (convert)
-                    fffi8i8((LONGLONG *) &array[next], ntodo, scale, zero, 
-                           nulcheck, tnull, nulval, &nularray[next], 
-                           anynul, &array[next], status);
-                break;
-            case (TLONG):
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
-                       status);
-                fffi4i8((INT32BIT *) buffer, ntodo, scale, zero, 
-                        nulcheck, (INT32BIT) tnull, nulval, &nularray[next], 
-                        anynul, &array[next], status);
-                break;
-            case (TBYTE):
-                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
-                       status);
-                fffi1i8((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
-                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
-                     &array[next], status);
-                break;
-            case (TSHORT):
-                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
-                fffi2i8((short  *) buffer, ntodo, scale, zero, nulcheck, 
-                      (short) tnull, nulval, &nularray[next], anynul, 
-                      &array[next], status);
-                break;
-            case (TFLOAT):
-                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
-                fffr4i8((float  *) buffer, ntodo, scale, zero, nulcheck, 
-                       nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TDOUBLE):
-                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
-                fffr8i8((double *) buffer, ntodo, scale, zero, nulcheck, 
-                          nulval, &nularray[next], anynul, 
-                          &array[next], status);
-                break;
-            case (TSTRING):
-                ffmbyt(fptr, readptr, REPORT_EOF, status);
-       
-                if (incre == twidth)    /* contiguous bytes */
-                     ffgbyt(fptr, ntodo * twidth, buffer, status);
-                else
-                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                               status);
-
-                fffstri8((char *) buffer, ntodo, scale, zero, twidth, power,
-                     nulcheck, snull, nulval, &nularray[next], anynul,
-                     &array[next], status);
-                break;
-
-            default:  /*  error trap for invalid column format */
-                sprintf(message, 
-                   "Cannot read numbers from column %d which has format %s",
-                    colnum, tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous read operation */
-        {
-	  dtemp = (double) next;
-          if (hdutype > 0)
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from column %d (ffgclj).",
-              dtemp+1., dtemp+ntodo, colnum);
-          else
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from image (ffgclj).",
-              dtemp+1., dtemp+ntodo);
-
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum = elemnum + (ntodo * elemincre);
-
-            if (elemnum >= repeat)  /* completed a row; start on later row */
-            {
-                rowincre = elemnum / repeat;
-                rownum += rowincre;
-                elemnum = elemnum - (rowincre * repeat);
-            }
-            else if (elemnum < 0)  /* completed a row; start on a previous row */
-            {
-                rowincre = (-elemnum - 1) / repeat + 1;
-                rownum -= rowincre;
-                elemnum = (rowincre * repeat) + elemnum;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while reading FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi1i8(unsigned char *input, /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            LONGLONG *output,     /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (LONGLONG) input[ii];  /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DLONGLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MIN;
-                }
-                else if (dvalue > DLONGLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MAX;
-                }
-                else
-                    output[ii] = (LONGLONG) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (LONGLONG) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DLONGLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MIN;
-                    }
-                    else if (dvalue > DLONGLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MAX;
-                    }
-                    else
-                        output[ii] = (LONGLONG) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi2i8(short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            LONGLONG *output,     /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (LONGLONG) input[ii];   /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DLONGLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MIN;
-                }
-                else if (dvalue > DLONGLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MAX;
-                }
-                else
-                    output[ii] = (LONGLONG) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (LONGLONG) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DLONGLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MIN;
-                    }
-                    else if (dvalue > DLONGLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MAX;
-                    }
-                    else
-                        output[ii] = (LONGLONG) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi4i8(INT32BIT *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            LONGLONG *output,     /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (LONGLONG) input[ii];   /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DLONGLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MIN;
-                }
-                else if (dvalue > DLONGLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MAX;
-                }
-                else
-                    output[ii] = (LONGLONG) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (LONGLONG) input[ii];
-
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DLONGLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MIN;
-                    }
-                    else if (dvalue > DLONGLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MAX;
-                    }
-                    else
-                        output[ii] = (LONGLONG) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi8i8(LONGLONG *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
-            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            LONGLONG *output,     /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] =  input[ii];   /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DLONGLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MIN;
-                }
-                else if (dvalue > DLONGLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MAX;
-                }
-                else
-                    output[ii] = (LONGLONG) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = input[ii];
-
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DLONGLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MIN;
-                    }
-                    else if (dvalue > DLONGLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MAX;
-                    }
-                    else
-                        output[ii] = (LONGLONG) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr4i8(float *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            LONGLONG *output,     /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DLONGLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MIN;
-                }
-                else if (input[ii] > DLONGLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MAX;
-                }
-                else
-                    output[ii] = (LONGLONG) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DLONGLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MIN;
-                }
-                else if (dvalue > DLONGLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MAX;
-                }
-                else
-                    output[ii] = (LONGLONG) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr++;       /* point to MSBs */
-#endif
-
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DLONGLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MIN;
-                    }
-                    else if (input[ii] > DLONGLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MAX;
-                    }
-                    else
-                        output[ii] = (LONGLONG) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  {
-                    if (zero < DLONGLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MIN;
-                    }
-                    else if (zero > DLONGLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MAX;
-                    }
-                    else
-                        output[ii] = (LONGLONG) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DLONGLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MIN;
-                    }
-                    else if (dvalue > DLONGLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MAX;
-                    }
-                    else
-                        output[ii] = (LONGLONG) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr8i8(double *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            LONGLONG *output,     /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DLONGLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MIN;
-                }
-                else if (input[ii] > DLONGLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MAX;
-                }
-                else
-                    output[ii] = (LONGLONG) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DLONGLONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MIN;
-                }
-                else if (dvalue > DLONGLONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = LONGLONG_MAX;
-                }
-                else
-                    output[ii] = (LONGLONG) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr += 3;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DLONGLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MIN;
-                    }
-                    else if (input[ii] > DLONGLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MAX;
-                    }
-                    else
-                        output[ii] = (LONGLONG) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  {
-                    if (zero < DLONGLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MIN;
-                    }
-                    else if (zero > DLONGLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MAX;
-                    }
-                    else
-                        output[ii] = (LONGLONG) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DLONGLONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MIN;
-                    }
-                    else if (dvalue > DLONGLONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = LONGLONG_MAX;
-                    }
-                    else
-                        output[ii] = (LONGLONG) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffstri8(char *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            long twidth,          /* I - width of each substring of chars    */
-            double implipower,    /* I - power of 10 of implied decimal      */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            char  *snull,         /* I - value of FITS null string, if any   */
-            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            LONGLONG *output,     /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file. Check
-  for null values and do scaling if required. The nullcheck code value
-  determines how any null values in the input array are treated. A null
-  value is an input pixel that is equal to snull.  If nullcheck= 0, then
-  no special checking for nulls is performed.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    int nullen;
-    long ii;
-    double dvalue;
-    char *cstring, message[81];
-    char *cptr, *tpos;
-    char tempstore, chrzero = '0';
-    double val, power;
-    int exponent, sign, esign, decpt;
-
-    nullen = strlen(snull);
-    cptr = input;  /* pointer to start of input string */
-    for (ii = 0; ii < ntodo; ii++)
-    {
-      cstring = cptr;
-      /* temporarily insert a null terminator at end of the string */
-      tpos = cptr + twidth;
-      tempstore = *tpos;
-      *tpos = 0;
-
-      /* check if null value is defined, and if the    */
-      /* column string is identical to the null string */
-      if (snull[0] != ASCII_NULL_UNDEFINED && 
-         !strncmp(snull, cptr, nullen) )
-      {
-        if (nullcheck)  
-        {
-          *anynull = 1;    
-          if (nullcheck == 1)
-            output[ii] = nullval;
-          else
-            nullarray[ii] = 1;
-        }
-        cptr += twidth;
-      }
-      else
-      {
-        /* value is not the null value, so decode it */
-        /* remove any embedded blank characters from the string */
-
-        decpt = 0;
-        sign = 1;
-        val  = 0.;
-        power = 1.;
-        exponent = 0;
-        esign = 1;
-
-        while (*cptr == ' ')               /* skip leading blanks */
-           cptr++;
-
-        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
-        {
-          if (*cptr == '-')
-             sign = -1;
-
-          cptr++;
-
-          while (*cptr == ' ')         /* skip blanks between sign and value */
-            cptr++;
-        }
-
-        while (*cptr >= '0' && *cptr <= '9')
-        {
-          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-          cptr++;
-
-          while (*cptr == ' ')         /* skip embedded blanks in the value */
-            cptr++;
-        }
-
-        if (*cptr == '.' || *cptr == ',')    /* check for decimal point */
-        {
-          decpt = 1;       /* set flag to show there was a decimal point */
-          cptr++;
-          while (*cptr == ' ')         /* skip any blanks */
-            cptr++;
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-            power = power * 10.;
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks in the value */
-              cptr++;
-          }
-        }
-
-        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
-        {
-          cptr++;
-          while (*cptr == ' ')         /* skip blanks */
-              cptr++;
-  
-          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
-          {
-            if (*cptr == '-')
-               esign = -1;
-
-            cptr++;
-
-            while (*cptr == ' ')        /* skip blanks between sign and exp */
-              cptr++;
-          }
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks */
-              cptr++;
-          }
-        }
-
-        if (*cptr  != 0)  /* should end up at the null terminator */
-        {
-          sprintf(message, "Cannot read number from ASCII table");
-          ffpmsg(message);
-          sprintf(message, "Column field = %s.", cstring);
-          ffpmsg(message);
-          /* restore the char that was overwritten by the null */
-          *tpos = tempstore;
-          return(*status = BAD_C2D);
-        }
-
-        if (!decpt)  /* if no explicit decimal, use implied */
-           power = implipower;
-
-        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
-
-        dvalue = dvalue * scale + zero;   /* apply the scaling */
-
-        if (dvalue < DLONGLONG_MIN)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = LONGLONG_MIN;
-        }
-        else if (dvalue > DLONGLONG_MAX)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = LONGLONG_MAX;
-        }
-        else
-            output[ii] = (LONGLONG) dvalue;
-      }
-      /* restore the char that was overwritten by the null */
-      *tpos = tempstore;
-    }
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcolk.c b/src/external/OpenGR/3rdparty/cfitsio/getcolk.c
deleted file mode 100644
index 2fa45082d..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcolk.c
+++ /dev/null
@@ -1,1901 +0,0 @@
-/*  This file, getcolk.c, contains routines that read data elements from   */
-/*  a FITS image or table, with 'int' data type.                           */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffgpvk( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            int   nulval,     /* I - value for undefined pixels              */
-            int   *array,     /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    char cdummy;
-    int nullcheck = 1;
-    int nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-         nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_pixels(fptr, TINT, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclk(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpfk( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            int   *array,     /* O - array of values that are returned       */
-            char *nularray,   /* O - array of null pixel flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Any undefined pixels in the returned array will be set = 0 and the 
-  corresponding nularray value will be set = 1.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    int nullcheck = 2;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_read_compressed_pixels(fptr, TINT, firstelem, nelem,
-            nullcheck, NULL, array, nularray, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclk(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
-               array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg2dk(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           int  nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           int  *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    /* call the 3D reading routine, with the 3rd dimension = 1 */
-
-    ffg3dk(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
-           anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg3dk(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           int   nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
-           int   *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 3-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    long tablerow, ii, jj;
-    char cdummy;
-    int nullcheck = 1;
-    long inc[] = {1,1,1};
-    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
-    LONGLONG lpixel[3];
-    int nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        lpixel[0] = ncols;
-        lpixel[1] = nrows;
-        lpixel[2] = naxis3;
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TINT, fpixel, lpixel, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-       /* all the image pixels are contiguous, so read all at once */
-       ffgclk(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-       return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to read */
-    narray = 0;  /* next pixel in output array to be filled */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* reading naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffgclk(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
-          &array[narray], &cdummy, anynul, status) > 0)
-          return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsvk(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           int  nulval,    /* I - value to set undefined pixels             */
-           int  *array,    /* O - array to be filled and returned           */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dir[9];
-    long nelem, nultyp, ninc, numcol;
-    LONGLONG felem, dsize[10], blcll[9], trcll[9];
-    int hdutype, anyf;
-    char ldummy, msg[FLEN_ERRMSG];
-    int nullcheck = 1;
-    int nullvalue;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvj is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TINT, blcll, trcll, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 1;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-        dir[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        if (hdutype == IMAGE_HDU)
-        {
-           dir[ii] = -1;
-        }
-        else
-        {
-          sprintf(msg, "ffgsvk: illegal range specified for axis %ld", ii + 1);
-          ffpmsg(msg);
-          return(*status = BAD_PIX_NUM);
-        }
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-      dsize[ii] = dsize[ii] * dir[ii];
-    }
-    dsize[naxis] = dsize[naxis] * dir[naxis];
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
-      ninc = incr[0] * dir[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
-            {
-
-              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
-                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
-                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
-                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];
-
-              if ( ffgclk(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsfk(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           int  *array,    /* O - array to be filled and returned           */
-           char *flagval,  /* O - set to 1 if corresponding value is null   */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dsize[10];
-    LONGLONG blcll[9], trcll[9];
-    long felem, nelem, nultyp, ninc, numcol;
-    long nulval = 0;
-    int hdutype, anyf;
-    char msg[FLEN_ERRMSG];
-    int nullcheck = 2;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvj is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        fits_read_compressed_img(fptr, TINT, blcll, trcll, inc,
-            nullcheck, NULL, array, flagval, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 2;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvj: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgclk(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffggpk( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            long  nelem,      /* I - number of values to read                */
-            int  *array,     /* O - array of values that are returned       */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of group parameters from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-*/
-{
-    long row;
-    int idummy;
-    char cdummy;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclk(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
-               array, &cdummy, &idummy, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcvk(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           int   nulval,     /* I - value for null pixels                   */
-           int  *array,      /* O - array of values that are read           */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy;
-
-    ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
-           array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfk(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           int   *array,     /* O - array of values that are read           */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-*/
-{
-    int dummy = 0;
-
-    ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
-           array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgclk( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-            int   nulval,     /* I - value for null pixels if nultyp = 1     */
-            int  *array,      /* O - array of values that are read           */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer be a virtual column in a 1 or more grouped FITS primary
-  array or image extension.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The output array of values will be converted from the datatype of the column 
-  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    double scale, zero, power, dtemp;
-    int tcode, maxelem2, hdutype, xcode, decimals;
-    long twidth, incre;
-    long ii, xwidth, ntodo;
-    int convert, nulcheck, readcheck = 0;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull;
-    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
-    char tform[20];
-    char message[81];
-    char snull[20];   /*  the FITS null value if reading from ASCII table  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    /* call the 'short' or 'long' version of this routine, if possible */
-    if (sizeof(int) == sizeof(short))
-        ffgcli(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
-              (short) nulval, (short *) array, nularray, anynul, status);
-    else if (sizeof(int) == sizeof(long))
-        ffgclj(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
-              (long) nulval, (long *) array, nularray, anynul, status);
-    else
-    {
-    /*
-      This is a special case: sizeof(int) is not equal to sizeof(short) or
-      sizeof(long).  This occurs on Alpha OSF systems where short = 2 bytes,
-      int = 4 bytes, and long = 8 bytes.
-    */
-
-    buffer = cbuff;
-    power = 1.;
-
-    if (anynul)
-        *anynul = 0;
-
-    if (nultyp == 2)
-        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (elemincre < 0)
-        readcheck = -1;  /* don't do range checking in this case */
-
-    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
-         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
-         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
-         return(*status);
-    maxelem = maxelem2;
-
-    incre *= elemincre;   /* multiply incre to just get every nth pixel */
-
-    if (tcode == TSTRING)    /* setup for ASCII tables */
-    {
-      /* get the number of implied decimal places if no explicit decmal point */
-      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
-      for(ii = 0; ii < decimals; ii++)
-        power *= 10.;
-    }
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
-            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
-            nulcheck = 0;            /* then do not check for null values. */
-
-    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
-         nulcheck = 0;
-
-    /*----------------------------------------------------------------------*/
-    /*  If FITS column and output data array have same datatype, then we do */
-    /*  not need to use a temporary buffer to store intermediate datatype.  */
-    /*----------------------------------------------------------------------*/
-    convert = 1;
-    if (tcode == TLONG)           /* Special Case:                        */
-    {                             /* no type convertion required, so read */
-                                  /* data directly into output buffer.    */
-
-        if (nelem < (LONGLONG)INT32_MAX/4) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/4;
-        }
-
-        if (nulcheck == 0 && scale == 1. && zero == 0.)
-            convert = 0;  /* no need to scale data or find nulls */
-    }
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the pixels from the FITS column. If the column does not   */
-    /*  have the same datatype as the output array, then we have to read   */
-    /*  the raw values into a temporary buffer (of limited size).  In      */
-    /*  the case of a vector colum read only 1 vector of values at a time  */
-    /*  then skip to the next row if more values need to be read.          */
-    /*  After reading the raw values, then call the fffXXYY routine to (1) */
-    /*  test for undefined values, (2) convert the datatype if necessary,  */
-    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
-    /*  scaling parameters.                                                */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to read */
-    next = 0;                 /* next element in array to be read   */
-    rownum = 0;               /* row number, relative to firstrow   */
-
-    while (remain)
-    {
-        /* limit the number of pixels to read at one time to the number that
-           will fit in the buffer or to the number of pixels that remain in
-           the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);
-        if (elemincre >= 0)
-        {
-          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
-        }
-        else
-        {
-          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
-        }
-
-        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
-
-        switch (tcode) 
-        {
-            case (TLONG):
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
-                       status);
-                if (convert)
-                    fffi4int((INT32BIT *) &array[next], ntodo, scale, zero, 
-                             nulcheck, (INT32BIT) tnull, nulval,
-                             &nularray[next], anynul, &array[next], status);
-                break;
-            case (TLONGLONG):
-
-                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
-                fffi8int( (LONGLONG *) buffer, ntodo, scale, zero, 
-                           nulcheck, tnull, nulval, &nularray[next], 
-                            anynul, &array[next], status);
-                break;
-            case (TBYTE):
-                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
-                       status);
-                fffi1int((unsigned char *) buffer, ntodo, scale, zero, nulcheck,
-                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
-                     &array[next], status);
-                break;
-            case (TSHORT):
-                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
-                fffi2int((short  *) buffer, ntodo, scale, zero, nulcheck, 
-                      (short) tnull, nulval, &nularray[next], anynul, 
-                      &array[next], status);
-                break;
-            case (TFLOAT):
-                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
-                fffr4int((float  *) buffer, ntodo, scale, zero, nulcheck, 
-                       nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TDOUBLE):
-                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
-                fffr8int((double *) buffer, ntodo, scale, zero, nulcheck, 
-                          nulval, &nularray[next], anynul, 
-                          &array[next], status);
-                break;
-            case (TSTRING):
-                ffmbyt(fptr, readptr, REPORT_EOF, status);
-       
-                if (incre == twidth)    /* contiguous bytes */
-                     ffgbyt(fptr, ntodo * twidth, buffer, status);
-                else
-                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                               status);
-
-                fffstrint((char *) buffer, ntodo, scale, zero, twidth, power,
-                     nulcheck, snull, nulval, &nularray[next], anynul,
-                     &array[next], status);
-                break;
-
-            default:  /*  error trap for invalid column format */
-                sprintf(message, 
-                   "Cannot read numbers from column %d which has format %s",
-                    colnum, tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous read operation */
-        {
-	  dtemp = (double) next;
-          if (hdutype > 0)
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from column %d (ffgclk).",
-              dtemp+1., dtemp+ntodo, colnum);
-          else
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from image (ffgclk).",
-              dtemp+1., dtemp+ntodo);
-
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum = elemnum + (ntodo * elemincre);
-
-            if (elemnum >= repeat)  /* completed a row; start on later row */
-            {
-                rowincre = elemnum / repeat;
-                rownum += rowincre;
-                elemnum = elemnum - (rowincre * repeat);
-            }
-            else if (elemnum < 0)  /* completed a row; start on a previous row */
-            {
-                rowincre = (-elemnum - 1) / repeat + 1;
-                rownum -= rowincre;
-                elemnum = (rowincre * repeat) + elemnum;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while reading FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    }  /* end of DEC Alpha special case */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi1int(unsigned char *input,/* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-            int  nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            int  *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (int) input[ii];  /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MIN;
-                }
-                else if (dvalue > DINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MAX;
-                }
-                else
-                    output[ii] = (int) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (int) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MIN;
-                    }
-                    else if (dvalue > DINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MAX;
-                    }
-                    else
-                        output[ii] = (int) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi2int(short *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-            int  nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            int  *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (int) input[ii];   /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MIN;
-                }
-                else if (dvalue > DINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MAX;
-                }
-                else
-                    output[ii] = (int) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (int) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MIN;
-                    }
-                    else if (dvalue > DINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MAX;
-                    }
-                    else
-                        output[ii] = (int) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi4int(INT32BIT *input,     /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-            int  nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            int  *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (int) input[ii];   /* copy input to output */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MIN;
-                }
-                else if (dvalue > DINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MAX;
-                }
-                else
-                    output[ii] = (int) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (int) input[ii];
-
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MIN;
-                    }
-                    else if (dvalue > DINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MAX;
-                    }
-                    else
-                        output[ii] = (int) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi8int(LONGLONG *input,     /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
-            int  nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            int  *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < INT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MIN;
-                }
-                else if (input[ii] > INT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MAX;
-                }
-                else
-                    output[ii] = (int) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MIN;
-                }
-                else if (dvalue > DINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MAX;
-                }
-                else
-                    output[ii] = (int) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < INT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MIN;
-                    }
-                    else if (input[ii] > INT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MAX;
-                    }
-                    else
-                        output[ii] = (int) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MIN;
-                    }
-                    else if (dvalue > DINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MAX;
-                    }
-                    else
-                        output[ii] = (int) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr4int(float *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            int  nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            int  *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MIN;
-                }
-                else if (input[ii] > DINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MAX;
-                }
-                else
-                    output[ii] = (int) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MIN;
-                }
-                else if (dvalue > DINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MAX;
-                }
-                else
-                    output[ii] = (int) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr++;       /* point to MSBs */
-#endif
-
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MIN;
-                    }
-                    else if (input[ii] > DINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MAX;
-                    }
-                    else
-                        output[ii] = (int) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  { 
-                    if (zero < DINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MIN;
-                    }
-                    else if (zero > DINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MAX;
-                    }
-                    else
-                      output[ii] = (int) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MIN;
-                    }
-                    else if (dvalue > DINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MAX;
-                    }
-                    else
-                        output[ii] = (int) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr8int(double *input,       /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            int  nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            int  *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MIN;
-                }
-                else if (input[ii] > DINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MAX;
-                }
-                else
-                    output[ii] = (int) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MIN;
-                }
-                else if (dvalue > DINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = INT_MAX;
-                }
-                else
-                    output[ii] = (int) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr += 3;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MIN;
-                    }
-                    else if (input[ii] > DINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MAX;
-                    }
-                    else
-                        output[ii] = (int) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  { 
-                    if (zero < DINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MIN;
-                    }
-                    else if (zero > DINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MAX;
-                    }
-                    else
-                      output[ii] = (int) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MIN;
-                    }
-                    else if (dvalue > DINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = INT_MAX;
-                    }
-                    else
-                        output[ii] = (int) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffstrint(char *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            long twidth,          /* I - width of each substring of chars    */
-            double implipower,    /* I - power of 10 of implied decimal      */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            char  *snull,         /* I - value of FITS null string, if any   */
-            int nullval,          /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            int *output,          /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file. Check
-  for null values and do scaling if required. The nullcheck code value
-  determines how any null values in the input array are treated. A null
-  value is an input pixel that is equal to snull.  If nullcheck= 0, then
-  no special checking for nulls is performed.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    int nullen;
-    long ii;
-    double dvalue;
-    char *cstring, message[81];
-    char *cptr, *tpos;
-    char tempstore, chrzero = '0';
-    double val, power;
-    int exponent, sign, esign, decpt;
-
-    nullen = strlen(snull);
-    cptr = input;  /* pointer to start of input string */
-    for (ii = 0; ii < ntodo; ii++)
-    {
-      cstring = cptr;
-      /* temporarily insert a null terminator at end of the string */
-      tpos = cptr + twidth;
-      tempstore = *tpos;
-      *tpos = 0;
-
-      /* check if null value is defined, and if the    */
-      /* column string is identical to the null string */
-      if (snull[0] != ASCII_NULL_UNDEFINED && 
-         !strncmp(snull, cptr, nullen) )
-      {
-        if (nullcheck)  
-        {
-          *anynull = 1;    
-          if (nullcheck == 1)
-            output[ii] = nullval;
-          else
-            nullarray[ii] = 1;
-        }
-        cptr += twidth;
-      }
-      else
-      {
-        /* value is not the null value, so decode it */
-        /* remove any embedded blank characters from the string */
-
-        decpt = 0;
-        sign = 1;
-        val  = 0.;
-        power = 1.;
-        exponent = 0;
-        esign = 1;
-
-        while (*cptr == ' ')               /* skip leading blanks */
-           cptr++;
-
-        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
-        {
-          if (*cptr == '-')
-             sign = -1;
-
-          cptr++;
-
-          while (*cptr == ' ')         /* skip blanks between sign and value */
-            cptr++;
-        }
-
-        while (*cptr >= '0' && *cptr <= '9')
-        {
-          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-          cptr++;
-
-          while (*cptr == ' ')         /* skip embedded blanks in the value */
-            cptr++;
-        }
-
-        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
-        {
-          decpt = 1;       /* set flag to show there was a decimal point */
-          cptr++;
-          while (*cptr == ' ')         /* skip any blanks */
-            cptr++;
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-            power = power * 10.;
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks in the value */
-              cptr++;
-          }
-        }
-
-        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
-        {
-          cptr++;
-          while (*cptr == ' ')         /* skip blanks */
-              cptr++;
-  
-          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
-          {
-            if (*cptr == '-')
-               esign = -1;
-
-            cptr++;
-
-            while (*cptr == ' ')        /* skip blanks between sign and exp */
-              cptr++;
-          }
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks */
-              cptr++;
-          }
-        }
-
-        if (*cptr  != 0)  /* should end up at the null terminator */
-        {
-          sprintf(message, "Cannot read number from ASCII table");
-          ffpmsg(message);
-          sprintf(message, "Column field = %s.", cstring);
-          ffpmsg(message);
-          /* restore the char that was overwritten by the null */
-          *tpos = tempstore;
-          return(*status = BAD_C2D);
-        }
-
-        if (!decpt)  /* if no explicit decimal, use implied */
-           power = implipower;
-
-        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
-
-        dvalue = dvalue * scale + zero;   /* apply the scaling */
-
-        if (dvalue < DINT_MIN)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = INT_MIN;
-        }
-        else if (dvalue > DINT_MAX)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = INT_MAX;
-        }
-        else
-            output[ii] = (long) dvalue;
-      }
-      /* restore the char that was overwritten by the null */
-      *tpos = tempstore;
-    }
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcoll.c b/src/external/OpenGR/3rdparty/cfitsio/getcoll.c
deleted file mode 100644
index 7e1ab20ce..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcoll.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/*  This file, getcoll.c, contains routines that read data elements from   */
-/*  a FITS image or table, with logical datatype.                          */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include "fitsio2.h"
-/*--------------------------------------------------------------------------*/
-int ffgcvl( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            char  nulval,     /* I - value for null pixels                   */
-            char *array,      /* O - array of values                         */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of logical values from a column in the current FITS HDU.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy;
-
-    ffgcll( fptr, colnum, firstrow, firstelem, nelem, 1, nulval, array,
-            &cdummy, anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcl(  fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            char *array,      /* O - array of values                         */
-            int  *status)     /* IO - error status                           */
-/*
-  !!!! THIS ROUTINE IS DEPRECATED AND SHOULD NOT BE USED !!!!!!
-                  !!!! USE ffgcvl INSTEAD  !!!!!!
-  Read an array of logical values from a column in the current FITS HDU.
-  No checking for null values will be performed.
-*/
-{
-    char nulval = 0;
-    int anynul;
-
-    ffgcvl( fptr, colnum, firstrow, firstelem, nelem, nulval, array,
-            &anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfl( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            char *array,      /* O - array of values                         */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of logical values from a column in the current FITS HDU.
-*/
-{
-    char nulval = 0;
-
-    ffgcll( fptr, colnum, firstrow, firstelem, nelem, 2, nulval, array,
-            nularray, anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcll( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG  firstelem, /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-            char nulval,      /* I - value for null pixels if nultyp = 1     */
-            char *array,      /* O - array of values                         */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of logical values from a column in the current FITS HDU.
-*/
-{
-    double dtemp;
-    int tcode, maxelem, hdutype, ii, nulcheck;
-    long twidth, incre;
-    long ntodo;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull, rowlen, rownum, remain, next;
-    double scale, zero;
-    char tform[20];
-    char message[FLEN_ERRMSG];
-    char snull[20];   /*  the FITS null value  */
-    unsigned char buffer[DBUFFSIZE], *buffptr;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    if (anynul)
-       *anynul = 0;
-
-    if (nultyp == 2)      
-       memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-
-    if (tcode != TLOGICAL)   
-        return(*status = NOT_LOGICAL_COL);
- 
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default, check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the logical values from the FITS column.                  */
-    /*---------------------------------------------------------------------*/
-
-    remain = nelem;           /* remaining number of values to read */
-    next = 0;                 /* next element in array to be read   */
-    rownum = 0;               /* row number, relative to firstrow   */
-    ntodo = (long) remain;           /* max number of elements to read at one time */
-
-    while (ntodo)
-    {
-      /*
-         limit the number of pixels to read at one time to the number that
-         remain in the current vector.    
-      */
-      ntodo = (long) minvalue(ntodo, maxelem);      
-      ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-      readptr = startpos + (rowlen * rownum) + (elemnum * incre);
-
-      ffgi1b(fptr, readptr, ntodo, incre, buffer, status);
-
-      /* convert from T or F to 1 or 0 */
-      buffptr = buffer;
-      for (ii = 0; ii < ntodo; ii++, next++, buffptr++)
-      {
-        if (*buffptr == 'T')
-          array[next] = 1;
-        else if (*buffptr =='F') 
-          array[next] = 0;
-        else if (*buffptr == 0)
-        {
-          array[next] = nulval;  /* set null values to input nulval */
-          if (anynul)
-              *anynul = 1;
-
-          if (nulcheck == 2)
-          {
-            nularray[next] = 1;  /* set null flags */
-          }
-        }
-        else  /* some other illegal character; return the char value */
-        {
-          if (*buffptr == 1) {
-            /* this is an unfortunate case where the illegal value is the same
-               as what we set True values to, so set the value to the character '1'
-               instead, which has ASCII value 49.  */
-            array[next] = 49;
-          } else {
-            array[next] = (char) *buffptr;
-          }
-        }
-      }
-
-      if (*status > 0)  /* test for error during previous read operation */
-      {
-	dtemp = (double) next;
-        sprintf(message,
-          "Error reading elements %.0f thruough %.0f of logical array (ffgcl).",
-           dtemp+1., dtemp + ntodo);
-        ffpmsg(message);
-        return(*status);
-      }
-
-      /*--------------------------------------------*/
-      /*  increment the counters for the next loop  */
-      /*--------------------------------------------*/
-      remain -= ntodo;
-      if (remain)
-      {
-        elemnum += ntodo;
-
-        if (elemnum == repeat)  /* completed a row; start on later row */
-          {
-            elemnum = 0;
-            rownum++;
-          }
-      }
-      ntodo = (long) remain;  /* this is the maximum number to do in next loop */
-
-    }  /*  End of main while Loop  */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcx(  fitsfile *fptr,  /* I - FITS file pointer                       */
-            int   colnum,    /* I - number of column to write (1 = 1st col) */
-            LONGLONG  frow,      /* I - first row to write (1 = 1st row)        */
-            LONGLONG  fbit,      /* I - first bit to write (1 = 1st)            */
-            LONGLONG  nbit,      /* I - number of bits to write                 */
-            char *larray,    /* O - array of logicals corresponding to bits */
-            int  *status)    /* IO - error status                           */
-/*
-  read an array of logical values from a specified bit or byte
-  column of the binary table.    larray is set = TRUE, if the corresponding
-  bit = 1, otherwise it is set to FALSE.
-  The binary table column being read from must have datatype 'B' or 'X'. 
-*/
-{
-    LONGLONG bstart;
-    long offset, ndone, ii, repeat, bitloc, fbyte;
-    LONGLONG  rstart, estart;
-    int tcode, descrp;
-    unsigned char cbuff;
-    static unsigned char onbit[8] = {128,  64,  32,  16,   8,   4,   2,   1};
-    tcolumn *colptr;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /*  check input parameters */
-    if (nbit < 1)
-        return(*status);
-    else if (frow < 1)
-        return(*status = BAD_ROW_NUM);
-    else if (fbit < 1)
-        return(*status = BAD_ELEM_NUM);
-
-    /* position to the correct HDU */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    /* rescan header if data structure is undefined */
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-        if ( ffrdef(fptr, status) > 0)               
-            return(*status);
-
-    fbyte = (long) ((fbit + 7) / 8);
-    bitloc = (long) (fbit - 1 - ((fbit - 1) / 8 * 8));
-    ndone = 0;
-    rstart = frow - 1;
-    estart = fbyte - 1;
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode = colptr->tdatatype;
-
-    if (abs(tcode) > TBYTE)
-        return(*status = NOT_LOGICAL_COL); /* not correct datatype column */
-
-    if (tcode > 0)
-    {
-        descrp = FALSE;  /* not a variable length descriptor column */
-        /* N.B: REPEAT is the number of bytes, not number of bits */
-        repeat = (long) colptr->trepeat;
-
-        if (tcode == TBIT)
-            repeat = (repeat + 7) / 8;  /* convert from bits to bytes */
-
-        if (fbyte > repeat)
-            return(*status = BAD_ELEM_NUM);
-
-        /* calc the i/o pointer location to start of sequence of pixels */
-        bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) +
-               colptr->tbcol + estart;
-    }
-    else
-    {
-        descrp = TRUE;  /* a variable length descriptor column */
-        /* only bit arrays (tform = 'X') are supported for variable */
-        /* length arrays.  REPEAT is the number of BITS in the array. */
-
-        ffgdes(fptr, colnum, frow, &repeat, &offset, status);
-
-        if (tcode == -TBIT)
-            repeat = (repeat + 7) / 8;
-
-        if ((fbit + nbit + 6) / 8 > repeat)
-            return(*status = BAD_ELEM_NUM);
-
-        /* calc the i/o pointer location to start of sequence of pixels */
-        bstart = (fptr->Fptr)->datastart + offset + (fptr->Fptr)->heapstart + estart;
-    }
-
-    /* move the i/o pointer to the start of the pixel sequence */
-    if (ffmbyt(fptr, bstart, REPORT_EOF, status) > 0)
-        return(*status);
-
-    /* read the next byte */
-    while (1)
-    {
-      if (ffgbyt(fptr, 1, &cbuff, status) > 0)
-        return(*status);
-
-      for (ii = bitloc; (ii < 8) && (ndone < nbit); ii++, ndone++)
-      {
-        if(cbuff & onbit[ii])       /* test if bit is set */
-          larray[ndone] = TRUE;
-        else
-          larray[ndone] = FALSE;
-      }
-
-      if (ndone == nbit)   /* finished all the bits */
-        return(*status);
-
-      /* not done, so get the next byte */
-      if (!descrp)
-      {
-        estart++;
-        if (estart == repeat) 
-        {
-          /* move the i/o pointer to the next row of pixels */
-          estart = 0;
-          rstart = rstart + 1;
-          bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) +
-               colptr->tbcol;
-
-          ffmbyt(fptr, bstart, REPORT_EOF, status);
-        }
-      }
-      bitloc = 0;
-    }
-}
-/*--------------------------------------------------------------------------*/
-int ffgcxui(fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG  nrows,      /* I - no. of rows to read                     */
-            long  input_first_bit, /* I - first bit to read (1 = 1st)        */
-            int   input_nbits,     /* I - number of bits to read (<= 32)     */
-            unsigned short *array, /* O - array of integer values            */
-            int  *status)     /* IO - error status                           */
-/*
-  Read a consecutive string of bits from an 'X' or 'B' column and
-  interprete them as an unsigned integer.  The number of bits must be
-  less than or equal to 16 or the total number of bits in the column, 
-  which ever is less.
-*/
-{
-    int ii, firstbit, nbits, bytenum, startbit, numbits, endbit;
-    int firstbyte, lastbyte, nbytes, rshift, lshift;
-    unsigned short colbyte[5];
-    tcolumn *colptr;
-    char message[81];
-
-    if (*status > 0 || nrows == 0)
-        return(*status);
-
-    /*  check input parameters */
-    if (firstrow < 1)
-    {
-          sprintf(message, "Starting row number is less than 1: %ld (ffgcxui)",
-                (long) firstrow);
-          ffpmsg(message);
-          return(*status = BAD_ROW_NUM);
-    }
-    else if (input_first_bit < 1)
-    {
-          sprintf(message, "Starting bit number is less than 1: %ld (ffgcxui)",
-                input_first_bit);
-          ffpmsg(message);
-          return(*status = BAD_ELEM_NUM);
-    }
-    else if (input_nbits > 16)
-    {
-          sprintf(message, "Number of bits to read is > 16: %d (ffgcxui)",
-                input_nbits);
-          ffpmsg(message);
-          return(*status = BAD_ELEM_NUM);
-    }
-
-    /* position to the correct HDU */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    /* rescan header if data structure is undefined */
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-        if ( ffrdef(fptr, status) > 0)               
-            return(*status);
-
-    if ((fptr->Fptr)->hdutype != BINARY_TBL)
-    {
-        ffpmsg("This is not a binary table extension (ffgcxui)");
-        return(*status = NOT_BTABLE);
-    }
-
-    if (colnum > (fptr->Fptr)->tfield)
-    {
-      sprintf(message, "Specified column number is out of range: %d (ffgcxui)",
-                colnum);
-        ffpmsg(message);
-        sprintf(message, "  There are %d columns in this table.",
-                (fptr->Fptr)->tfield );
-        ffpmsg(message);
-
-        return(*status = BAD_COL_NUM);
-    }       
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    if (abs(colptr->tdatatype) > TBYTE)
-    {
-        ffpmsg("Can only read bits from X or B type columns. (ffgcxui)");
-        return(*status = NOT_LOGICAL_COL); /* not correct datatype column */
-    }
-
-    firstbyte = (input_first_bit - 1              ) / 8 + 1;
-    lastbyte  = (input_first_bit + input_nbits - 2) / 8 + 1;
-    nbytes = lastbyte - firstbyte + 1;
-
-    if (colptr->tdatatype == TBIT && 
-        input_first_bit + input_nbits - 1 > (long) colptr->trepeat)
-    {
-        ffpmsg("Too many bits. Tried to read past width of column (ffgcxui)");
-        return(*status = BAD_ELEM_NUM);
-    }
-    else if (colptr->tdatatype == TBYTE && lastbyte > (long) colptr->trepeat)
-    {
-        ffpmsg("Too many bits. Tried to read past width of column (ffgcxui)");
-        return(*status = BAD_ELEM_NUM);
-    }
-
-    for (ii = 0; ii < nrows; ii++)
-    {
-        /* read the relevant bytes from the row */
-        if (ffgcvui(fptr, colnum, firstrow+ii, firstbyte, nbytes, 0, 
-               colbyte, NULL, status) > 0)
-        {
-             ffpmsg("Error reading bytes from column (ffgcxui)");
-             return(*status);
-        }
-
-        firstbit = (input_first_bit - 1) % 8; /* modulus operator */
-        nbits = input_nbits;
-
-        array[ii] = 0;
-
-        /* select and shift the bits from each byte into the output word */
-        while(nbits)
-        {
-            bytenum = firstbit / 8;
-
-            startbit = firstbit % 8;  
-            numbits = minvalue(nbits, 8 - startbit);
-            endbit = startbit + numbits - 1;
-
-            rshift = 7 - endbit;
-            lshift = nbits - numbits;
-
-            array[ii] = ((colbyte[bytenum] >> rshift) << lshift) | array[ii];
-
-            nbits -= numbits;
-            firstbit += numbits;
-        }
-    }
-
-    return(*status);
-}
-
-/*--------------------------------------------------------------------------*/
-int ffgcxuk(fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG  nrows,      /* I - no. of rows to read                     */
-            long  input_first_bit, /* I - first bit to read (1 = 1st)        */
-            int   input_nbits,     /* I - number of bits to read (<= 32)     */
-            unsigned int *array,   /* O - array of integer values            */
-            int  *status)     /* IO - error status                           */
-/*
-  Read a consecutive string of bits from an 'X' or 'B' column and
-  interprete them as an unsigned integer.  The number of bits must be
-  less than or equal to 32 or the total number of bits in the column, 
-  which ever is less.
-*/
-{
-    int ii, firstbit, nbits, bytenum, startbit, numbits, endbit;
-    int firstbyte, lastbyte, nbytes, rshift, lshift;
-    unsigned int colbyte[5];
-    tcolumn *colptr;
-    char message[81];
-
-    if (*status > 0 || nrows == 0)
-        return(*status);
-
-    /*  check input parameters */
-    if (firstrow < 1)
-    {
-          sprintf(message, "Starting row number is less than 1: %ld (ffgcxuk)",
-                (long) firstrow);
-          ffpmsg(message);
-          return(*status = BAD_ROW_NUM);
-    }
-    else if (input_first_bit < 1)
-    {
-          sprintf(message, "Starting bit number is less than 1: %ld (ffgcxuk)",
-                input_first_bit);
-          ffpmsg(message);
-          return(*status = BAD_ELEM_NUM);
-    }
-    else if (input_nbits > 32)
-    {
-          sprintf(message, "Number of bits to read is > 32: %d (ffgcxuk)",
-                input_nbits);
-          ffpmsg(message);
-          return(*status = BAD_ELEM_NUM);
-    }
-
-    /* position to the correct HDU */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    /* rescan header if data structure is undefined */
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-        if ( ffrdef(fptr, status) > 0)               
-            return(*status);
-
-    if ((fptr->Fptr)->hdutype != BINARY_TBL)
-    {
-        ffpmsg("This is not a binary table extension (ffgcxuk)");
-        return(*status = NOT_BTABLE);
-    }
-
-    if (colnum > (fptr->Fptr)->tfield)
-    {
-      sprintf(message, "Specified column number is out of range: %d (ffgcxuk)",
-                colnum);
-        ffpmsg(message);
-        sprintf(message, "  There are %d columns in this table.",
-                (fptr->Fptr)->tfield );
-        ffpmsg(message);
-
-        return(*status = BAD_COL_NUM);
-    }       
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    if (abs(colptr->tdatatype) > TBYTE)
-    {
-        ffpmsg("Can only read bits from X or B type columns. (ffgcxuk)");
-        return(*status = NOT_LOGICAL_COL); /* not correct datatype column */
-    }
-
-    firstbyte = (input_first_bit - 1              ) / 8 + 1;
-    lastbyte  = (input_first_bit + input_nbits - 2) / 8 + 1;
-    nbytes = lastbyte - firstbyte + 1;
-
-    if (colptr->tdatatype == TBIT && 
-        input_first_bit + input_nbits - 1 > (long) colptr->trepeat)
-    {
-        ffpmsg("Too many bits. Tried to read past width of column (ffgcxuk)");
-        return(*status = BAD_ELEM_NUM);
-    }
-    else if (colptr->tdatatype == TBYTE && lastbyte > (long) colptr->trepeat)
-    {
-        ffpmsg("Too many bits. Tried to read past width of column (ffgcxuk)");
-        return(*status = BAD_ELEM_NUM);
-    }
-
-    for (ii = 0; ii < nrows; ii++)
-    {
-        /* read the relevant bytes from the row */
-        if (ffgcvuk(fptr, colnum, firstrow+ii, firstbyte, nbytes, 0, 
-               colbyte, NULL, status) > 0)
-        {
-             ffpmsg("Error reading bytes from column (ffgcxuk)");
-             return(*status);
-        }
-
-        firstbit = (input_first_bit - 1) % 8; /* modulus operator */
-        nbits = input_nbits;
-
-        array[ii] = 0;
-
-        /* select and shift the bits from each byte into the output word */
-        while(nbits)
-        {
-            bytenum = firstbit / 8;
-
-            startbit = firstbit % 8;  
-            numbits = minvalue(nbits, 8 - startbit);
-            endbit = startbit + numbits - 1;
-
-            rshift = 7 - endbit;
-            lshift = nbits - numbits;
-
-            array[ii] = ((colbyte[bytenum] >> rshift) << lshift) | array[ii];
-
-            nbits -= numbits;
-            firstbit += numbits;
-        }
-    }
-
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcols.c b/src/external/OpenGR/3rdparty/cfitsio/getcols.c
deleted file mode 100644
index 2620618f6..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcols.c
+++ /dev/null
@@ -1,852 +0,0 @@
-/*  This file, getcols.c, contains routines that read data elements from   */
-/*  a FITS image or table, with a character string datatype.               */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-/* stddef.h is apparently needed to define size_t */
-#include 
-#include 
-#include "fitsio2.h"
-/*--------------------------------------------------------------------------*/
-int ffgcvs( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of strings to read               */
-            char *nulval,     /* I - string for null pixels                  */
-            char **array,     /* O - array of values that are read           */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of string values from a column in the current FITS HDU.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = null in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy[2];
-
-    ffgcls(fptr, colnum, firstrow, firstelem, nelem, 1, nulval,
-           array, cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfs( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col) */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)        */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st) */
-            LONGLONG  nelem,      /* I - number of strings to read              */
-            char **array,     /* O - array of values that are read           */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of string values from a column in the current FITS HDU.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-*/
-{
-    char dummy[2];
-
-    ffgcls(fptr, colnum, firstrow, firstelem, nelem, 2, dummy,
-           array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcls( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col) */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)        */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st) */
-            LONGLONG  nelem,      /* I - number of strings to read              */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-            char  *nulval,    /* I - value for null pixels if nultyp = 1     */
-            char **array,     /* O - array of values that are read           */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of string values from a column in the current FITS HDU.
-  Returns a formated string value, regardless of the datatype of the column
-*/
-{
-    int tcode, hdutype, tstatus, scaled, intcol, dwidth, nulwidth, ll, dlen;
-    int equivtype;
-    long ii, jj;
-    tcolumn *colptr;
-    char message[FLEN_ERRMSG], *carray, keyname[FLEN_KEYWORD];
-    char cform[20], dispfmt[20], tmpstr[400], *flgarray, tmpnull[80];
-    unsigned char byteval;
-    float *earray;
-    double *darray, tscale = 1.0;
-    LONGLONG *llarray;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    /* rescan header if data structure is undefined */
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-        if ( ffrdef(fptr, status) > 0)               
-            return(*status);
-
-    if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
-    {
-        sprintf(message, "Specified column number is out of range: %d",
-                colnum);
-        ffpmsg(message);
-        return(*status = BAD_COL_NUM);
-    }
-
-    /* get equivalent dataype of column (only needed for TLONGLONG columns) */
-    ffeqtyll(fptr, colnum, &equivtype, NULL, NULL, status);
-    if (equivtype < 0) equivtype = abs(equivtype);
-    
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-    tcode = abs(colptr->tdatatype);
-
-    if (tcode == TSTRING)
-    {
-      /* simply call the string column reading routine */
-      ffgcls2(fptr, colnum, firstrow, firstelem, nelem, nultyp, nulval,
-           array, nularray, anynul, status);
-    }
-    else if (tcode == TLOGICAL)
-    {
-      /* allocate memory for the array of logical values */
-      carray = (char *) malloc((size_t) nelem);
-
-      /*  call the logical column reading routine */
-      ffgcll(fptr, colnum, firstrow, firstelem, nelem, nultyp, *nulval,
-           carray, nularray, anynul, status); 
-
-      if (*status <= 0)
-      {
-         /* convert logical values to "T", "F", or "N" (Null) */
-         for (ii = 0; ii < nelem; ii++)
-         {
-           if (carray[ii] == 1)
-              strcpy(array[ii], "T");
-           else if (carray[ii] == 0)
-              strcpy(array[ii], "F");
-           else  /* undefined values = 2 */
-              strcpy(array[ii],"N");
-         }
-      }
-
-      free(carray);  /* free the memory */
-    }
-    else if (tcode == TCOMPLEX)
-    {
-      /* allocate memory for the array of double values */
-      earray = (float *) calloc((size_t) (nelem * 2), sizeof(float) );
-      
-      ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
-        1, 1, FLOATNULLVALUE, earray, nularray, anynul, status);
-
-      if (*status <= 0)
-      {
-
-         /* determine the format for the output strings */
-
-         ffgcdw(fptr, colnum, &dwidth, status);
-         dwidth = (dwidth - 3) / 2;
- 
-         /* use the TDISPn keyword if it exists */
-         ffkeyn("TDISP", colnum, keyname, status);
-         tstatus = 0;
-         cform[0] = '\0';
-
-         if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
-         {
-             /* convert the Fortran style format to a C style format */
-             ffcdsp(dispfmt, cform);
-         }
-
-         if (!cform[0])
-             strcpy(cform, "%14.6E");
-
-         /* write the formated string for each value:  "(real,imag)" */
-         jj = 0;
-         for (ii = 0; ii < nelem; ii++)
-         {
-           strcpy(array[ii], "(");
-
-           /* test for null value */
-           if (earray[jj] == FLOATNULLVALUE)
-           {
-             strcpy(tmpstr, "NULL");
-             if (nultyp == 2)
-                nularray[ii] = 1;
-           }
-           else
-             sprintf(tmpstr, cform, earray[jj]);
-
-           strncat(array[ii], tmpstr, dwidth);
-           strcat(array[ii], ",");
-           jj++;
-
-           /* test for null value */
-           if (earray[jj] == FLOATNULLVALUE)
-           {
-             strcpy(tmpstr, "NULL");
-             if (nultyp == 2)
-                nularray[ii] = 1;
-           }
-           else
-             sprintf(tmpstr, cform, earray[jj]);
-
-           strncat(array[ii], tmpstr, dwidth);
-           strcat(array[ii], ")");
-           jj++;
-         }
-      }
-
-      free(earray);  /* free the memory */
-    }
-    else if (tcode == TDBLCOMPLEX)
-    {
-      /* allocate memory for the array of double values */
-      darray = (double *) calloc((size_t) (nelem * 2), sizeof(double) );
-      
-      ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
-        1, 1, DOUBLENULLVALUE, darray, nularray, anynul, status);
-
-      if (*status <= 0)
-      {
-         /* determine the format for the output strings */
-
-         ffgcdw(fptr, colnum, &dwidth, status);
-         dwidth = (dwidth - 3) / 2;
-
-         /* use the TDISPn keyword if it exists */
-         ffkeyn("TDISP", colnum, keyname, status);
-         tstatus = 0;
-         cform[0] = '\0';
- 
-         if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
-         {
-             /* convert the Fortran style format to a C style format */
-             ffcdsp(dispfmt, cform);
-         }
-
-         if (!cform[0])
-            strcpy(cform, "%23.15E");
-
-         /* write the formated string for each value:  "(real,imag)" */
-         jj = 0;
-         for (ii = 0; ii < nelem; ii++)
-         {
-           strcpy(array[ii], "(");
-
-           /* test for null value */
-           if (darray[jj] == DOUBLENULLVALUE)
-           {
-             strcpy(tmpstr, "NULL");
-             if (nultyp == 2)
-                nularray[ii] = 1;
-           }
-           else
-             sprintf(tmpstr, cform, darray[jj]);
-
-           strncat(array[ii], tmpstr, dwidth);
-           strcat(array[ii], ",");
-           jj++;
-
-           /* test for null value */
-           if (darray[jj] == DOUBLENULLVALUE)
-           {
-             strcpy(tmpstr, "NULL");
-             if (nultyp == 2)
-                nularray[ii] = 1;
-           }
-           else
-             sprintf(tmpstr, cform, darray[jj]);
-
-           strncat(array[ii], tmpstr, dwidth);
-           strcat(array[ii], ")");
-           jj++;
-         }
-      }
-
-      free(darray);  /* free the memory */
-    }
-    else if (tcode == TLONGLONG && equivtype == TLONGLONG)
-    {
-      /* allocate memory for the array of LONGLONG values */
-      llarray = (LONGLONG *) calloc((size_t) nelem, sizeof(LONGLONG) );
-      flgarray = (char *) calloc((size_t) nelem, sizeof(char) );
-      dwidth = 20;  /* max width of displayed long long integer value */
-
-      if (ffgcfjj(fptr, colnum, firstrow, firstelem, nelem,
-            llarray, flgarray, anynul, status) > 0)
-      {
-         free(flgarray);
-         free(llarray);
-         return(*status);
-      }
-
-      /* write the formated string for each value */
-      if (nulval) {
-          strcpy(tmpnull, nulval);
-          nulwidth = strlen(nulval);
-      } else {
-          strcpy(tmpnull, " ");
-          nulwidth = 1;
-      }
-
-      for (ii = 0; ii < nelem; ii++)
-      {
-           if ( flgarray[ii] )
-           {
-              *array[ii] = '\0';
-              if (dwidth < nulwidth)
-                  strncat(array[ii], tmpnull, dwidth);
-              else
-                  sprintf(array[ii],"%*s",dwidth,tmpnull);
-		  
-              if (nultyp == 2)
-	          nularray[ii] = 1;
-           }
-           else
-           {	   
-
-#if defined(_MSC_VER)
-    /* Microsoft Visual C++ 6.0 uses '%I64d' syntax  for 8-byte integers */
-        sprintf(tmpstr, "%20I64d", llarray[ii]);
-#elif (USE_LL_SUFFIX == 1)
-        sprintf(tmpstr, "%20lld", llarray[ii]);
-#else
-        sprintf(tmpstr, "%20ld", llarray[ii]);
-#endif
-              *array[ii] = '\0';
-              strncat(array[ii], tmpstr, 20);
-           }
-      }
-
-      free(flgarray);
-      free(llarray);  /* free the memory */
-
-    }
-    else
-    {
-      /* allocate memory for the array of double values */
-      darray = (double *) calloc((size_t) nelem, sizeof(double) );
-      
-      /* read all other numeric type columns as doubles */
-      if (ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, nultyp, 
-           DOUBLENULLVALUE, darray, nularray, anynul, status) > 0)
-      {
-         free(darray);
-         return(*status);
-      }
-
-      /* determine the format for the output strings */
-
-      ffgcdw(fptr, colnum, &dwidth, status);
-
-      /* check if  column is scaled */
-      ffkeyn("TSCAL", colnum, keyname, status);
-      tstatus = 0;
-      scaled = 0;
-      if (ffgkyd(fptr, keyname, &tscale, NULL, &tstatus) == 0)
-      {
-            if (tscale != 1.0)
-                scaled = 1;    /* yes, this is a scaled column */
-      }
-
-      intcol = 0;
-      if (tcode <= TLONG && !scaled)
-             intcol = 1;   /* this is an unscaled integer column */
-
-      /* use the TDISPn keyword if it exists */
-      ffkeyn("TDISP", colnum, keyname, status);
-      tstatus = 0;
-      cform[0] = '\0';
-
-      if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
-      {
-           /* convert the Fortran style TDISPn to a C style format */
-           ffcdsp(dispfmt, cform);
-      }
-
-      if (!cform[0])
-      {
-            /* no TDISPn keyword; use TFORMn instead */
-
-            ffkeyn("TFORM", colnum, keyname, status);
-            ffgkys(fptr, keyname, dispfmt, NULL, status);
-
-            if (scaled && tcode <= TSHORT)
-            {
-                  /* scaled short integer column == float */
-                  strcpy(cform, "%#14.6G");
-            }
-            else if (scaled && tcode == TLONG)
-            {
-                  /* scaled long integer column == double */
-                  strcpy(cform, "%#23.15G");
-            }
-            else if (scaled && tcode == TLONGLONG)
-            {
-                  /* scaled long long integer column == double */
-                  strcpy(cform, "%#23.15G");
-            }
-            else
-            {
-               ffghdt(fptr, &hdutype, status);
-               if (hdutype == ASCII_TBL)
-               {
-                  /* convert the Fortran style TFORMn to a C style format */
-                  ffcdsp(dispfmt, cform);
-               }
-               else
-               {
-                 /* this is a binary table, need to convert the format */
-                  if (tcode == TBIT) {            /* 'X' */
-                     strcpy(cform, "%4d");
-                  } else if (tcode == TBYTE) {    /* 'B' */
-                     strcpy(cform, "%4d");
-                  } else if (tcode == TSHORT) {   /* 'I' */
-                     strcpy(cform, "%6d");
-                  } else if (tcode == TLONG) {    /* 'J' */
-                     strcpy(cform, "%11.0f");
-                     intcol = 0;  /* needed to support unsigned int */
-                  } else if (tcode == TFLOAT) {   /* 'E' */
-                     strcpy(cform, "%#14.6G");
-                  } else if (tcode == TDOUBLE) {  /* 'D' */
-                     strcpy(cform, "%#23.15G");
-                  }
-               }
-            }
-      } 
-
-      if (nulval) {
-          strcpy(tmpnull, nulval);
-          nulwidth = strlen(nulval);
-      } else {
-          strcpy(tmpnull, " ");
-          nulwidth = 1;
-      }
-
-      /* write the formated string for each value */
-      for (ii = 0; ii < nelem; ii++)
-      {
-           if (tcode == TBIT)
-           {
-               byteval = (char) darray[ii];
-
-               for (ll=0; ll < 8; ll++)
-               {
-                   if ( ((unsigned char) (byteval << ll)) >> 7 )
-                       *(array[ii] + ll) = '1';
-                   else
-                       *(array[ii] + ll) = '0';
-               }
-               *(array[ii] + 8) = '\0';
-           }
-           /* test for null value */
-           else if ( (nultyp == 1 && darray[ii] == DOUBLENULLVALUE) ||
-                (nultyp == 2 && nularray[ii]) )
-           {
-              *array[ii] = '\0';
-              if (dwidth < nulwidth)
-                  strncat(array[ii], tmpnull, dwidth);
-              else
-                  sprintf(array[ii],"%*s",dwidth,tmpnull);
-           }
-           else
-           {	   
-              if (intcol) {
-                sprintf(tmpstr, cform, (int) darray[ii]);
-              } else {
-                sprintf(tmpstr, cform, darray[ii]);
-              }
-	      
-              /* fill field with '*' if number is too wide */
-              dlen = strlen(tmpstr);
-	      if (dlen > dwidth) {
-	         memset(tmpstr, '*', dwidth);
-              }
-
-              *array[ii] = '\0';
-              strncat(array[ii], tmpstr, dwidth);
-           }
-      }
-
-      free(darray);  /* free the memory */
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcdw( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column (1 = 1st col)      */
-            int  *width,      /* O - display width                       */
-            int  *status)     /* IO - error status                           */
-/*
-  Get Column Display Width.
-*/
-{
-    tcolumn *colptr;
-    char *cptr;
-    char message[FLEN_ERRMSG], keyname[FLEN_KEYWORD], dispfmt[20];
-    int tcode, hdutype, tstatus, scaled;
-    double tscale;
-
-    if (*status > 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
-    {
-        sprintf(message, "Specified column number is out of range: %d",
-                colnum);
-        ffpmsg(message);
-        return(*status = BAD_COL_NUM);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-    tcode = abs(colptr->tdatatype);
-
-    /* use the TDISPn keyword if it exists */
-    ffkeyn("TDISP", colnum, keyname, status);
-
-    *width = 0;
-    tstatus = 0;
-    if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
-    {
-          /* parse TDISPn get the display width */
-          cptr = dispfmt;
-          while(*cptr == ' ') /* skip leading blanks */
-              cptr++;
-
-          if (*cptr == 'A' || *cptr == 'a' ||
-              *cptr == 'I' || *cptr == 'i' ||
-              *cptr == 'O' || *cptr == 'o' ||
-              *cptr == 'Z' || *cptr == 'z' ||
-              *cptr == 'F' || *cptr == 'f' ||
-              *cptr == 'E' || *cptr == 'e' ||
-              *cptr == 'D' || *cptr == 'd' ||
-              *cptr == 'G' || *cptr == 'g')
-          {
-
-            while(!isdigit((int) *cptr) && *cptr != '\0') /* find 1st digit */
-              cptr++;
-
-            *width = atoi(cptr);
-            if (tcode >= TCOMPLEX)
-              *width = (2 * (*width)) + 3;
-          }
-    }
-
-    if (*width == 0)
-    {
-        /* no valid TDISPn keyword; use TFORMn instead */
-
-        ffkeyn("TFORM", colnum, keyname, status);
-        ffgkys(fptr, keyname, dispfmt, NULL, status);
-
-        /* check if  column is scaled */
-        ffkeyn("TSCAL", colnum, keyname, status);
-        tstatus = 0;
-        scaled = 0;
-
-        if (ffgkyd(fptr, keyname, &tscale, NULL, &tstatus) == 0)
-        {
-            if (tscale != 1.0)
-                scaled = 1;    /* yes, this is a scaled column */
-        }
-
-        if (scaled && tcode <= TSHORT)
-        {
-            /* scaled short integer col == float; default format is 14.6G */
-            *width = 14;
-        }
-        else if (scaled && tcode == TLONG)
-        {
-            /* scaled long integer col == double; default format is 23.15G */
-            *width = 23;
-        }
-        else if (scaled && tcode == TLONGLONG)
-        {
-            /* scaled long long integer col == double; default format is 23.15G */
-            *width = 23;
-        }
-
-        else
-        {
-           ffghdt(fptr, &hdutype, status);  /* get type of table */
-           if (hdutype == ASCII_TBL)
-           {
-              /* parse TFORMn get the display width */
-              cptr = dispfmt;
-              while(!isdigit((int) *cptr) && *cptr != '\0') /* find 1st digit */
-                 cptr++;
-
-              *width = atoi(cptr);
-           }
-           else
-           {
-                 /* this is a binary table */
-                  if (tcode == TBIT)           /* 'X' */
-                     *width = 8;
-                  else if (tcode == TBYTE)     /* 'B' */
-                     *width = 4;
-                  else if (tcode == TSHORT)    /* 'I' */
-                     *width = 6;
-                  else if (tcode == TLONG)     /* 'J' */
-                     *width = 11;
-                  else if (tcode == TLONGLONG) /* 'K' */
-                     *width = 20;
-                  else if (tcode == TFLOAT)    /* 'E' */
-                     *width = 14;
-                  else if (tcode == TDOUBLE)   /* 'D' */
-                     *width = 23;
-                  else if (tcode == TCOMPLEX)  /* 'C' */
-                     *width = 31;
-                  else if (tcode == TDBLCOMPLEX)  /* 'M' */
-                     *width = 49;
-                  else if (tcode == TLOGICAL)  /* 'L' */
-                     *width = 1;
-                  else if (tcode == TSTRING)   /* 'A' */
-                  {
-                     cptr = dispfmt;
-                     while(!isdigit((int) *cptr) && *cptr != '\0') 
-                         cptr++;
-
-                     *width = atoi(cptr);
-
-                     if (*width < 1)
-                         *width = 1;  /* default is at least 1 column */
-                  }
-            }
-        }
-    } 
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcls2 ( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col) */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)        */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st) */
-            LONGLONG  nelem,      /* I - number of strings to read              */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-            char  *nulval,    /* I - value for null pixels if nultyp = 1     */
-            char **array,     /* O - array of values that are read           */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of string values from a column in the current FITS HDU.
-*/
-{
-    double dtemp;
-    long nullen; 
-    int tcode, maxelem, hdutype, nulcheck;
-    long twidth, incre;
-    long ii, jj, ntodo;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull, rowlen, rownum, remain, next;
-    double scale, zero;
-    char tform[20];
-    char message[FLEN_ERRMSG];
-    char snull[20];   /*  the FITS null value  */
-    tcolumn *colptr;
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    char *buffer, *arrayptr;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if (anynul)
-        *anynul = 0;
-
-    if (nultyp == 2)
-        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
-    {
-        sprintf(message, "Specified column number is out of range: %d",
-                colnum);
-        ffpmsg(message);
-        return(*status = BAD_COL_NUM);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-    tcode = colptr->tdatatype;
-
-    if (tcode == -TSTRING) /* variable length column in a binary table? */
-    {
-      /* only read a single string; ignore value of firstelem */
-
-      if (ffgcprll( fptr, colnum, firstrow, 1, 1, 0, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-
-      remain = 1;
-      twidth = (long) repeat;  
-    }
-    else if (tcode == TSTRING)
-    {
-      if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-
-      /* if string length is greater than a FITS block (2880 char) then must */
-      /* only read 1 string at a time, to force reading by ffgbyt instead of */
-      /* ffgbytoff (ffgbytoff can't handle this case) */
-      if (twidth > IOBUFLEN) {
-        maxelem = 1;
-        incre = twidth;
-        repeat = 1;
-      }   
-
-      remain = nelem;
-    }
-    else
-        return(*status = NOT_ASCII_COL);
-
-    nullen = strlen(snull);   /* length of the undefined pixel string */
-    if (nullen == 0)
-        nullen = 1;
- 
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (nultyp == 1 && nulval && nulval[0] == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (snull[0] == ASCII_NULL_UNDEFINED)
-       nulcheck = 0;   /* null value string in ASCII table not defined */
-
-    else if (nullen > twidth)
-       nulcheck = 0;   /* null value string is longer than width of column  */
-                       /* thus impossible for any column elements to = null */
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the strings one at a time from the FITS column.           */
-    /*---------------------------------------------------------------------*/
-    next = 0;                 /* next element in array to be read  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-      /* limit the number of pixels to process at one time to the number that
-         will fit in the buffer space or to the number of pixels that remain
-         in the current vector, which ever is smaller.
-      */
-      ntodo = (long) minvalue(remain, maxelem);      
-      ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-      readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-      ffmbyt(fptr, readptr, REPORT_EOF, status);  /* move to read position */
-
-      /* read the array of strings from the FITS file into the buffer */
-
-      if (incre == twidth)
-         ffgbyt(fptr, ntodo * twidth, cbuff, status);
-      else
-         ffgbytoff(fptr, twidth, ntodo, incre - twidth, cbuff, status);
-
-      /* copy from the buffer into the user's array of strings */
-      /* work backwards from last char of last string to 1st char of 1st */
-
-      buffer = ((char *) cbuff) + (ntodo * twidth) - 1;
-
-      for (ii = (long) (next + ntodo - 1); ii >= next; ii--)
-      {
-         arrayptr = array[ii] + twidth - 1;
-
-         for (jj = twidth - 1; jj > 0; jj--)  /* ignore trailing blanks */
-         {
-            if (*buffer == ' ')
-            {
-              buffer--;
-              arrayptr--;
-            }
-            else
-              break;
-         }
-         *(arrayptr + 1) = 0;  /* write the string terminator */
-         
-         for (; jj >= 0; jj--)    /* copy the string itself */
-         {
-           *arrayptr = *buffer;
-           buffer--;
-           arrayptr--;
-         }
-
-         /* check if null value is defined, and if the   */
-         /* column string is identical to the null string */
-         if (nulcheck && !strncmp(snull, array[ii], nullen) )
-         {
-           *anynul = 1;   /* this is a null value */
-           if (nultyp == 1) {
-	   
-	     if (nulval)
-                strcpy(array[ii], nulval);
-	     else
-	        strcpy(array[ii], " ");
-	     
-           } else
-             nularray[ii] = 1;
-         }
-      }
-    
-      if (*status > 0)  /* test for error during previous read operation */
-      {
-         dtemp = (double) next;
-         sprintf(message,
-          "Error reading elements %.0f thru %.0f of data array (ffpcls).",
-             dtemp+1., dtemp+ntodo);
-
-         ffpmsg(message);
-         return(*status);
-      }
-
-      /*--------------------------------------------*/
-      /*  increment the counters for the next loop  */
-      /*--------------------------------------------*/
-      next += ntodo;
-      remain -= ntodo;
-      if (remain)
-      {
-          elemnum += ntodo;
-          if (elemnum == repeat)  /* completed a row; start on next row */
-          {
-              elemnum = 0;
-              rownum++;
-          }
-      }
-    }  /*  End of main while Loop  */
-
-    return(*status);
-}
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcolsb.c b/src/external/OpenGR/3rdparty/cfitsio/getcolsb.c
deleted file mode 100644
index f750681d6..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcolsb.c
+++ /dev/null
@@ -1,1991 +0,0 @@
-/*  This file, getcolsb.c, contains routines that read data elements from   */
-/*  a FITS image or table, with signed char (signed byte) data type.        */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffgpvsb(fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            signed char nulval, /* I - value for undefined pixels            */
-            signed char *array, /* O - array of values that are returned     */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    char cdummy;
-    int nullcheck = 1;
-    signed char nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-         nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_pixels(fptr, TSBYTE, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclsb(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpfsb(fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            signed char *array, /* O - array of values that are returned     */
-            char *nularray,   /* O - array of null pixel flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Any undefined pixels in the returned array will be set = 0 and the 
-  corresponding nularray value will be set = 1.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    int nullcheck = 2;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_read_compressed_pixels(fptr, TSBYTE, firstelem, nelem,
-            nullcheck, NULL, array, nularray, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclsb(fptr, 2, row, firstelem, nelem, 1, 2, 0,
-               array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg2dsb(fitsfile *fptr, /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           signed char nulval,   /* set undefined pixels equal to this     */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           signed char *array,   /* O - array to be filled and returned    */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    /* call the 3D reading routine, with the 3rd dimension = 1 */
-
-    ffg3dsb(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
-           anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg3dsb(fitsfile *fptr, /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-           signed char nulval,   /* set undefined pixels equal to this     */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
-           signed char *array,   /* O - array to be filled and returned    */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 3-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    long tablerow, ii, jj;
-    LONGLONG  nfits, narray;
-    char cdummy;
-    int  nullcheck = 1;
-    long inc[] = {1,1,1};
-    LONGLONG fpixel[] = {1,1,1};
-    LONGLONG lpixel[3];
-    signed char nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        lpixel[0] = ncols;
-        lpixel[1] = nrows;
-        lpixel[2] = naxis3;
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TSBYTE, fpixel, lpixel, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-       /* all the image pixels are contiguous, so read all at once */
-       ffgclsb(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-       return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to read */
-    narray = 0;  /* next pixel in output array to be filled */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* reading naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffgclsb(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
-          &array[narray], &cdummy, anynul, status) > 0)
-          return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsvsb(fitsfile *fptr, /* I - FITS file pointer                        */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           signed char nulval, /* I - value to set undefined pixels         */
-           signed char *array, /* O - array to be filled and returned       */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii, i0, i1, i2, i3, i4, i5, i6, i7, i8, row, rstr, rstp, rinc;
-    long str[9], stp[9], incr[9], dir[9];
-    long nelem, nultyp, ninc, numcol;
-    LONGLONG felem, dsize[10], blcll[9], trcll[9];
-    int hdutype, anyf;
-    char ldummy, msg[FLEN_ERRMSG];
-    int  nullcheck = 1;
-    signed char nullvalue;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvsb is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TSBYTE, blcll, trcll, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 1;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-        dir[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        if (hdutype == IMAGE_HDU)
-        {
-           dir[ii] = -1;
-        }
-        else
-        {
-          sprintf(msg, "ffgsvsb: illegal range specified for axis %ld", ii + 1);
-          ffpmsg(msg);
-          return(*status = BAD_PIX_NUM);
-        }
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-      dsize[ii] = dsize[ii] * dir[ii];
-    }
-    dsize[naxis] = dsize[naxis] * dir[naxis];
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
-      ninc = incr[0] * dir[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
-            {
-
-              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
-                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
-                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
-                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];
-
-              if ( ffgclsb(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsfsb(fitsfile *fptr, /* I - FITS file pointer                        */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-           signed char *array,   /* O - array to be filled and returned     */
-           char *flagval,  /* O - set to 1 if corresponding value is null   */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dsize[10];
-    LONGLONG blcll[9], trcll[9];
-    long felem, nelem, nultyp, ninc, numcol;
-    int hdutype, anyf;
-    signed char nulval = 0;
-    char msg[FLEN_ERRMSG];
-    int  nullcheck = 2;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvsb is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        fits_read_compressed_img(fptr, TSBYTE, blcll, trcll, inc,
-            nullcheck, NULL, array, flagval, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 2;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvsb: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgclsb(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffggpsb( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            long  nelem,      /* I - number of values to read                */
-            signed char *array,   /* O - array of values that are returned   */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of group parameters from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-*/
-{
-    long row;
-    int idummy;
-    char cdummy;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclsb(fptr, 1, row, firstelem, nelem, 1, 1, 0,
-               array, &cdummy, &idummy, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcvsb(fitsfile *fptr,  /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           signed char nulval,   /* I - value for null pixels               */
-           signed char *array,   /* O - array of values that are read       */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy;
-
-    ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
-           array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfsb(fitsfile *fptr,  /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-           signed char *array,   /* O - array of values that are read       */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-*/
-{
-    signed char dummy = 0;
-
-    ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
-           array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgclsb(fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-            signed char nulval,   /* I - value for null pixels if nultyp = 1 */
-            signed char *array,   /* O - array of values that are read       */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer be a virtual column in a 1 or more grouped FITS primary
-  array or image extension.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The output array of values will be converted from the datatype of the column 
-  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    double scale, zero, power = 1., dtemp;
-    int tcode, maxelem, hdutype, xcode, decimals;
-    long twidth, incre;
-    long ii, xwidth, ntodo;
-    int nulcheck, readcheck = 0;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull;
-    LONGLONG rowlen, rownum, remain, next, rowincre;
-    char tform[20];
-    char message[81];
-    char snull[20];   /*  the FITS null value if reading from ASCII table  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    union u_tag {
-       char charval;
-       signed char scharval;
-    } u;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    if (anynul)
-        *anynul = 0;
-
-    if (nultyp == 2)      
-       memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (elemincre < 0)
-        readcheck = -1;  /* don't do range checking in this case */
-
-    ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
-         tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre,
-         &repeat, &rowlen, &hdutype, &tnull, snull, status);
-
-    /* special case: read column of T/F logicals */
-    if (tcode == TLOGICAL && elemincre == 1)
-    {
-        u.scharval = nulval;
-        ffgcll(fptr, colnum, firstrow, firstelem, nelem, nultyp,
-               u.charval, (char *) array, nularray, anynul, status);
-
-        return(*status);
-    }
-
-    if (strchr(tform,'A') != NULL) 
-    {
-        if (*status == BAD_ELEM_NUM)
-        {
-            /* ignore this error message */
-            *status = 0;
-            ffcmsg();   /* clear error stack */
-        }
-
-        /*  interpret a 'A' ASCII column as a 'B' byte column ('8A' == '8B') */
-        /*  This is an undocumented 'feature' in CFITSIO */
-
-        /*  we have to reset some of the values returned by ffgcpr */
-        
-        tcode = TBYTE;
-        incre = 1;         /* each element is 1 byte wide */
-        repeat = twidth;   /* total no. of chars in the col */
-        twidth = 1;        /* width of each element */
-        scale = 1.0;       /* no scaling */
-        zero  = 0.0;
-        tnull = NULL_UNDEFINED;  /* don't test for nulls */
-        maxelem = DBUFFSIZE;
-    }
-
-    if (*status > 0)
-        return(*status);
-        
-    incre *= elemincre;   /* multiply incre to just get every nth pixel */
-
-    if (tcode == TSTRING && hdutype == ASCII_TBL) /* setup for ASCII tables */
-    {
-      /* get the number of implied decimal places if no explicit decmal point */
-      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
-      for(ii = 0; ii < decimals; ii++)
-        power *= 10.;
-    }
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default, check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
-            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
-            nulcheck = 0;            /* then do not check for null values. */
-
-    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
-         nulcheck = 0;
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the pixels from the FITS column. If the column does not   */
-    /*  have the same datatype as the output array, then we have to read   */
-    /*  the raw values into a temporary buffer (of limited size).  In      */
-    /*  the case of a vector colum read only 1 vector of values at a time  */
-    /*  then skip to the next row if more values need to be read.          */
-    /*  After reading the raw values, then call the fffXXYY routine to (1) */
-    /*  test for undefined values, (2) convert the datatype if necessary,  */
-    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
-    /*  scaling parameters.                                                */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to read */
-    next = 0;                 /* next element in array to be read   */
-    rownum = 0;               /* row number, relative to firstrow   */
-
-    while (remain)
-    {
-        /* limit the number of pixels to read at one time to the number that
-           will fit in the buffer or to the number of pixels that remain in
-           the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);
-        if (elemincre >= 0)
-        {
-          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
-        }
-        else
-        {
-          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
-        }
-
-        readptr = startpos + (rownum * rowlen) + (elemnum * (incre / elemincre));
-
-        switch (tcode) 
-        {
-            case (TBYTE):
-                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) &array[next], status);
-                fffi1s1((unsigned char *)&array[next], ntodo, scale, zero,
-                        nulcheck, (unsigned char) tnull, nulval, &nularray[next], 
-                        anynul, &array[next], status);
-                break;
-            case (TSHORT):
-                ffgi2b(fptr, readptr, ntodo, incre, (short *) buffer, status);
-                fffi2s1((short  *) buffer, ntodo, scale, zero, nulcheck, 
-                       (short) tnull, nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TLONG):
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
-                       status);
-                fffi4s1((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
-                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TLONGLONG):
-                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
-                fffi8s1( (LONGLONG *) buffer, ntodo, scale, zero, 
-                           nulcheck, tnull, nulval, &nularray[next], 
-                            anynul, &array[next], status);
-                break;
-            case (TFLOAT):
-                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
-                fffr4s1((float  *) buffer, ntodo, scale, zero, nulcheck, 
-                       nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TDOUBLE):
-                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
-                fffr8s1((double *) buffer, ntodo, scale, zero, nulcheck, 
-                          nulval, &nularray[next], anynul, 
-                          &array[next], status);
-                break;
-            case (TSTRING):
-                ffmbyt(fptr, readptr, REPORT_EOF, status);
-       
-                if (incre == twidth)    /* contiguous bytes */
-                     ffgbyt(fptr, ntodo * twidth, buffer, status);
-                else
-                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                               status);
-
-                /* interpret the string as an ASCII formated number */
-                fffstrs1((char *) buffer, ntodo, scale, zero, twidth, power,
-                      nulcheck, snull, nulval, &nularray[next], anynul,
-                      &array[next], status);
-                break;
-
-            default:  /*  error trap for invalid column format */
-                sprintf(message, 
-                   "Cannot read bytes from column %d which has format %s",
-                    colnum, tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous read operation */
-        {
-	  dtemp = (double) next;
-          if (hdutype > 0)
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from column %d (ffgclsb).",
-              dtemp+1., dtemp+ntodo, colnum);
-          else
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from image (ffgclsb).",
-              dtemp+1., dtemp+ntodo);
-
-         ffpmsg(message);
-         return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum = elemnum + (ntodo * elemincre);
-
-            if (elemnum >= repeat)  /* completed a row; start on later row */
-            {
-                rowincre = elemnum / repeat;
-                rownum += rowincre;
-                elemnum = elemnum - (rowincre * repeat);
-            }
-            else if (elemnum < 0)  /* completed a row; start on a previous row */
-            {
-                rowincre = (-elemnum - 1) / repeat + 1;
-                rownum -= rowincre;
-                elemnum = (rowincre * repeat) + elemnum;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while reading FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi1s1(unsigned char *input, /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            signed char *output,  /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == -128.)
-        {
-            /* Instead of subtracting 128, it is more efficient */
-            /* to just flip the sign bit with the XOR operator */
-
-            for (ii = 0; ii < ntodo; ii++)
-                 output[ii] =  ( *(signed char *) &input[ii] ) ^ 0x80;
-        }
-        else if (scale == 1. && zero == 0.)      /* no scaling */
-        { 
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] > 127)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 127;
-                }
-                else
-                    output[ii] = (signed char) input[ii]; /* copy input */
-            }
-        }
-        else             /* must scale the data */
-        {                
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DSCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = -128;
-                }
-                else if (dvalue > DSCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 127;
-                }
-                else
-                    output[ii] = (signed char) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == -128.)
-        {
-            /* Instead of subtracting 128, it is more efficient */
-            /* to just flip the sign bit with the XOR operator */
-
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] =  ( *(signed char *) &input[ii] ) ^ 0x80;
-            }
-        }
-        else if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (signed char) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DSCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (dvalue > DSCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi2s1(short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            signed char *output,  /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < -128)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = -128;
-                }
-                else if (input[ii] > 127)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 127;
-                }
-                else
-                    output[ii] = (signed char) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DSCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = -128;
-                }
-                else if (dvalue > DSCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 127;
-                }
-                else
-                    output[ii] = (signed char) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-
-                else
-                {
-                    if (input[ii] < -128)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (input[ii] > 127)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DSCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (dvalue > DSCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi4s1(INT32BIT *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            signed char *output,  /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < -128)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = -128;
-                }
-                else if (input[ii] > 127)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 127;
-                }
-                else
-                    output[ii] = (signed char) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DSCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = -128;
-                }
-                else if (dvalue > DSCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 127;
-                }
-                else
-                    output[ii] = (signed char) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < -128)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (input[ii] > 127)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DSCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (dvalue > DSCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi8s1(LONGLONG *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
-            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            signed char *output,  /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < -128)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = -128;
-                }
-                else if (input[ii] > 127)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 127;
-                }
-                else
-                    output[ii] = (signed char) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DSCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = -128;
-                }
-                else if (dvalue > DSCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 127;
-                }
-                else
-                    output[ii] = (signed char) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < -128)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (input[ii] > 127)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DSCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (dvalue > DSCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr4s1(float *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            signed char *output,  /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DSCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = -128;
-                }
-                else if (input[ii] > DSCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 127;
-                }
-                else
-                    output[ii] = (signed char) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DSCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = -128;
-                }
-                else if (dvalue > DSCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 127;
-                }
-                else
-                    output[ii] = (signed char) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr++;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              /* use redundant boolean logic in following statement */
-              /* to suppress irritating Borland compiler warning message */
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DSCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (input[ii] > DSCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  {
-                    if (zero < DSCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (zero > DSCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DSCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (dvalue > DSCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr8s1(double *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            signed char *output,  /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DSCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = -128;
-                }
-                else if (input[ii] > DSCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 127;
-                }
-                else
-                    output[ii] = (signed char) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DSCHAR_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = -128;
-                }
-                else if (dvalue > DSCHAR_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 127;
-                }
-                else
-                    output[ii] = (signed char) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr += 3;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DSCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (input[ii] > DSCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  {
-                    if (zero < DSCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (zero > DSCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DSCHAR_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = -128;
-                    }
-                    else if (dvalue > DSCHAR_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 127;
-                    }
-                    else
-                        output[ii] = (signed char) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffstrs1(char *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            long twidth,          /* I - width of each substring of chars    */
-            double implipower,    /* I - power of 10 of implied decimal      */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            char  *snull,         /* I - value of FITS null string, if any   */
-            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            signed char *output,  /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file. Check
-  for null values and do scaling if required. The nullcheck code value
-  determines how any null values in the input array are treated. A null
-  value is an input pixel that is equal to snull.  If nullcheck= 0, then
-  no special checking for nulls is performed.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    int  nullen;
-    long ii;
-    double dvalue;
-    char *cstring, message[81];
-    char *cptr, *tpos;
-    char tempstore, chrzero = '0';
-    double val, power;
-    int exponent, sign, esign, decpt;
-
-    nullen = strlen(snull);
-    cptr = input;  /* pointer to start of input string */
-    for (ii = 0; ii < ntodo; ii++)
-    {
-      cstring = cptr;
-      /* temporarily insert a null terminator at end of the string */
-      tpos = cptr + twidth;
-      tempstore = *tpos;
-      *tpos = 0;
-
-      /* check if null value is defined, and if the    */
-      /* column string is identical to the null string */
-      if (snull[0] != ASCII_NULL_UNDEFINED && 
-         !strncmp(snull, cptr, nullen) )
-      {
-        if (nullcheck)  
-        {
-          *anynull = 1;    
-          if (nullcheck == 1)
-            output[ii] = nullval;
-          else
-            nullarray[ii] = 1;
-        }
-        cptr += twidth;
-      }
-      else
-      {
-        /* value is not the null value, so decode it */
-        /* remove any embedded blank characters from the string */
-
-        decpt = 0;
-        sign = 1;
-        val  = 0.;
-        power = 1.;
-        exponent = 0;
-        esign = 1;
-
-        while (*cptr == ' ')               /* skip leading blanks */
-           cptr++;
-
-        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
-        {
-          if (*cptr == '-')
-             sign = -1;
-
-          cptr++;
-
-          while (*cptr == ' ')         /* skip blanks between sign and value */
-            cptr++;
-        }
-
-        while (*cptr >= '0' && *cptr <= '9')
-        {
-          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-          cptr++;
-
-          while (*cptr == ' ')         /* skip embedded blanks in the value */
-            cptr++;
-        }
-
-        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
-        {
-          decpt = 1;
-          cptr++;
-          while (*cptr == ' ')         /* skip any blanks */
-            cptr++;
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-            power = power * 10.;
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks in the value */
-              cptr++;
-          }
-        }
-
-        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
-        {
-          cptr++;
-          while (*cptr == ' ')         /* skip blanks */
-              cptr++;
-  
-          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
-          {
-            if (*cptr == '-')
-               esign = -1;
-
-            cptr++;
-
-            while (*cptr == ' ')        /* skip blanks between sign and exp */
-              cptr++;
-          }
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks */
-              cptr++;
-          }
-        }
-
-        if (*cptr  != 0)  /* should end up at the null terminator */
-        {
-          sprintf(message, "Cannot read number from ASCII table");
-          ffpmsg(message);
-          sprintf(message, "Column field = %s.", cstring);
-          ffpmsg(message);
-          /* restore the char that was overwritten by the null */
-          *tpos = tempstore;
-          return(*status = BAD_C2D);
-        }
-
-        if (!decpt)  /* if no explicit decimal, use implied */
-           power = implipower;
-
-        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
-
-        dvalue = dvalue * scale + zero;   /* apply the scaling */
-
-        if (dvalue < DSCHAR_MIN)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = -128;
-        }
-        else if (dvalue > DSCHAR_MAX)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = 127;
-        }
-        else
-            output[ii] = (signed char) dvalue;
-      }
-      /* restore the char that was overwritten by the null */
-      *tpos = tempstore;
-    }
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcolui.c b/src/external/OpenGR/3rdparty/cfitsio/getcolui.c
deleted file mode 100644
index e3a7e9a07..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcolui.c
+++ /dev/null
@@ -1,1914 +0,0 @@
-/*  This file, getcolui.c, contains routines that read data elements from   */
-/*  a FITS image or table, with unsigned short datatype.                    */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffgpvui( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-   unsigned short nulval,     /* I - value for undefined pixels              */
-   unsigned short *array,     /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    char cdummy;
-    int nullcheck = 1;
-    unsigned short nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-         nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_pixels(fptr, TUSHORT, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclui(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpfui( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-   unsigned short *array,     /* O - array of values that are returned       */
-            char *nularray,   /* O - array of null pixel flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Any undefined pixels in the returned array will be set = 0 and the 
-  corresponding nularray value will be set = 1.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    int nullcheck = 2;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_read_compressed_pixels(fptr, TUSHORT, firstelem, nelem,
-            nullcheck, NULL, array, nularray, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclui(fptr, 2, row, firstelem, nelem, 1, 2, 0,
-               array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg2dui(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-  unsigned short nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-  unsigned short *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    /* call the 3D reading routine, with the 3rd dimension = 1 */
-
-    ffg3dui(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
-           anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg3dui(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-  unsigned short nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
-  unsigned short *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 3-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    long tablerow, ii, jj;
-    char cdummy;
-    int nullcheck = 1;
-    long inc[] = {1,1,1};
-    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
-    LONGLONG lpixel[3];
-    unsigned short nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        lpixel[0] = ncols;
-        lpixel[1] = nrows;
-        lpixel[2] = naxis3;
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TUSHORT, fpixel, lpixel, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-       /* all the image pixels are contiguous, so read all at once */
-       ffgclui(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-       return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to read */
-    narray = 0;  /* next pixel in output array to be filled */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* reading naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffgclui(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
-          &array[narray], &cdummy, anynul, status) > 0)
-          return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsvui(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-  unsigned short nulval,   /* I - value to set undefined pixels             */
-  unsigned short *array,   /* O - array to be filled and returned           */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9];
-    long nelem, nultyp, ninc, numcol;
-    LONGLONG felem, dsize[10], blcll[9], trcll[9];
-    int hdutype, anyf;
-    char ldummy, msg[FLEN_ERRMSG];
-    int nullcheck = 1;
-    unsigned short nullvalue;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvui is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TUSHORT, blcll, trcll, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 1;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvui: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-              if ( ffgclui(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsfui(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-  unsigned short *array,   /* O - array to be filled and returned           */
-           char *flagval,  /* O - set to 1 if corresponding value is null   */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dsize[10];
-    LONGLONG blcll[9], trcll[9];
-    long felem, nelem, nultyp, ninc, numcol;
-    int hdutype, anyf;
-    unsigned short nulval = 0;
-    char msg[FLEN_ERRMSG];
-    int nullcheck = 2;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvi is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        fits_read_compressed_img(fptr, TUSHORT, blcll, trcll, inc,
-            nullcheck, NULL, array, flagval, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 2;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvi: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgclui(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffggpui( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            long  nelem,      /* I - number of values to read                */
-   unsigned short *array,     /* O - array of values that are returned       */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of group parameters from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-*/
-{
-    long row;
-    int idummy;
-    char cdummy;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgclui(fptr, 1, row, firstelem, nelem, 1, 1, 0,
-               array, &cdummy, &idummy, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcvui(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-  unsigned short nulval,     /* I - value for null pixels                   */
-  unsigned short *array,     /* O - array of values that are read           */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy;
-
-    ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
-           array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfui(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-  unsigned short *array,     /* O - array of values that are read           */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-*/
-{
-    unsigned short dummy = 0;
-
-    ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
-           array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgclui( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-   unsigned short nulval,     /* I - value for null pixels if nultyp = 1     */
-   unsigned short *array,     /* O - array of values that are read           */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer be a virtual column in a 1 or more grouped FITS primary
-  array or image extension.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The output array of values will be converted from the datatype of the column 
-  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    double scale, zero, power = 1., dtemp;
-    int tcode, maxelem2, hdutype, xcode, decimals;
-    long twidth, incre;
-    long ii, xwidth, ntodo;
-    int nulcheck;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull;
-    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
-    char tform[20];
-    char message[81];
-    char snull[20];   /*  the FITS null value if reading from ASCII table  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    if (anynul)
-        *anynul = 0;
-
-    if (nultyp == 2)
-        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
-         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
-         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
-         return(*status);
-    maxelem = maxelem2;
-
-    incre *= elemincre;   /* multiply incre to just get every nth pixel */
-
-    if (tcode == TSTRING)    /* setup for ASCII tables */
-    {
-      /* get the number of implied decimal places if no explicit decmal point */
-      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
-      for(ii = 0; ii < decimals; ii++)
-        power *= 10.;
-    }
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
-            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
-            nulcheck = 0;            /* then do not check for null values. */
-
-    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
-         nulcheck = 0;
-
-    /*----------------------------------------------------------------------*/
-    /*  If FITS column and output data array have same datatype, then we do */
-    /*  not need to use a temporary buffer to store intermediate datatype.  */
-    /*----------------------------------------------------------------------*/
-    if (tcode == TSHORT) /* Special Case:                        */
-    {                             /* no type convertion required, so read */
-                                  /* data directly into output buffer.    */
-
-        if (nelem < (LONGLONG)INT32_MAX/2) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/2;
-        }
-    }
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the pixels from the FITS column. If the column does not   */
-    /*  have the same datatype as the output array, then we have to read   */
-    /*  the raw values into a temporary buffer (of limited size).  In      */
-    /*  the case of a vector colum read only 1 vector of values at a time  */
-    /*  then skip to the next row if more values need to be read.          */
-    /*  After reading the raw values, then call the fffXXYY routine to (1) */
-    /*  test for undefined values, (2) convert the datatype if necessary,  */
-    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
-    /*  scaling parameters.                                                */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to read */
-    next = 0;                 /* next element in array to be read   */
-    rownum = 0;               /* row number, relative to firstrow   */
-
-    while (remain)
-    {
-        /* limit the number of pixels to read at one time to the number that
-           will fit in the buffer or to the number of pixels that remain in
-           the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
-
-        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
-
-        switch (tcode) 
-        {
-            case (TSHORT):
-                ffgi2b(fptr, readptr, ntodo, incre,
-                       (short *) &array[next], status);
-                fffi2u2((short *) &array[next], ntodo, scale,
-                       zero, nulcheck, (short) tnull, nulval, &nularray[next],
-                       anynul, &array[next], status);
-                break;
-            case (TLONGLONG):
-
-                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
-                fffi8u2( (LONGLONG *) buffer, ntodo, scale, zero, 
-                           nulcheck, tnull, nulval, &nularray[next], 
-                            anynul, &array[next], status);
-                break;
-            case (TBYTE):
-                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
-                      status);
-                fffi1u2((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
-                    (unsigned char) tnull, nulval, &nularray[next], anynul, 
-                    &array[next], status);
-                break;
-            case (TLONG):
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
-                       status);
-                fffi4u2((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
-                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TFLOAT):
-                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
-                fffr4u2((float  *) buffer, ntodo, scale, zero, nulcheck, 
-                       nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TDOUBLE):
-                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
-                fffr8u2((double *) buffer, ntodo, scale, zero, nulcheck, 
-                          nulval, &nularray[next], anynul, 
-                          &array[next], status);
-                break;
-            case (TSTRING):
-                ffmbyt(fptr, readptr, REPORT_EOF, status);
-       
-                if (incre == twidth)    /* contiguous bytes */
-                     ffgbyt(fptr, ntodo * twidth, buffer, status);
-                else
-                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                               status);
-
-                fffstru2((char *) buffer, ntodo, scale, zero, twidth, power,
-                     nulcheck, snull, nulval, &nularray[next], anynul,
-                     &array[next], status);
-                break;
-
-            default:  /*  error trap for invalid column format */
-                sprintf(message, 
-                   "Cannot read numbers from column %d which has format %s",
-                    colnum, tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous read operation */
-        {
-	  dtemp = (double) next;
-          if (hdutype > 0)
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from column %d (ffgclui).",
-              dtemp+1., dtemp+ntodo, colnum);
-          else
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from image (ffgclui).",
-              dtemp+1., dtemp+ntodo);
-
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum = elemnum + (ntodo * elemincre);
-
-            if (elemnum >= repeat)  /* completed a row; start on later row */
-            {
-                rowincre = elemnum / repeat;
-                rownum += rowincre;
-                elemnum = elemnum - (rowincre * repeat);
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while reading FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi1u2(unsigned char *input, /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (unsigned short) input[ii]; /* copy input */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = USHRT_MAX;
-                }
-                else
-                    output[ii] = (unsigned short) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (unsigned short) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = USHRT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned short) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi2u2(short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 32768.) 
-        {       
-           /* Instead of adding 32768, it is more efficient */
-           /* to just flip the sign bit with the XOR operator */
-
-           for (ii = 0; ii < ntodo; ii++)
-              output[ii] =  ( *(unsigned short *) &input[ii] ) ^ 0x8000;
-        }
-        else if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else
-                    output[ii] = (unsigned short) input[ii]; /* copy input */
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = USHRT_MAX;
-                }
-                else
-                    output[ii] = (unsigned short) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 32768.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] =  ( *(unsigned short *) &input[ii] ) ^ 0x8000;
-            }
-        }
-        else if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else
-                    output[ii] = (unsigned short) input[ii]; /* copy input */
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = USHRT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned short) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi4u2(INT32BIT *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > USHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = USHRT_MAX;
-                }
-                else
-                    output[ii] = (unsigned short) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = USHRT_MAX;
-                }
-                else
-                    output[ii] = (unsigned short) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < 0)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > USHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = USHRT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned short) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = USHRT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned short) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi8u2(LONGLONG *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
-   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > USHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = USHRT_MAX;
-                }
-                else
-                    output[ii] = (unsigned short) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = USHRT_MAX;
-                }
-                else
-                    output[ii] = (unsigned short) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < 0)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > USHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = USHRT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned short) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = USHRT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned short) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr4u2(float *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DUSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > DUSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = USHRT_MAX;
-                }
-                else
-                    output[ii] = (unsigned short) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = USHRT_MAX;
-                }
-                else
-                    output[ii] = (unsigned short) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr++;       /* point to MSBs */
-#endif
-
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )   /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DUSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > DUSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = USHRT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned short) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  { 
-                    if (zero < DUSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (zero > DUSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = USHRT_MAX;
-                    }
-                    else
-                      output[ii] = (unsigned short) zero;
-                  }
-              }
-              else
-              {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = USHRT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned short) dvalue;
-              }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr8u2(double *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DUSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > DUSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = USHRT_MAX;
-                }
-                else
-                    output[ii] = (unsigned short) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUSHRT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUSHRT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = USHRT_MAX;
-                }
-                else
-                    output[ii] = (unsigned short) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr += 3;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DUSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > DUSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = USHRT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned short) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  { 
-                    if (zero < DUSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (zero > DUSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = USHRT_MAX;
-                    }
-                    else
-                      output[ii] = (unsigned short) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUSHRT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUSHRT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = USHRT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned short) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffstru2(char *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            long twidth,          /* I - width of each substring of chars    */
-            double implipower,    /* I - power of 10 of implied decimal      */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            char  *snull,         /* I - value of FITS null string, if any   */
-   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned short *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file. Check
-  for null values and do scaling if required. The nullcheck code value
-  determines how any null values in the input array are treated. A null
-  value is an input pixel that is equal to snull.  If nullcheck= 0, then
-  no special checking for nulls is performed.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    int nullen;
-    long ii;
-    double dvalue;
-    char *cstring, message[81];
-    char *cptr, *tpos;
-    char tempstore, chrzero = '0';
-    double val, power;
-    int exponent, sign, esign, decpt;
-
-    nullen = strlen(snull);
-    cptr = input;  /* pointer to start of input string */
-    for (ii = 0; ii < ntodo; ii++)
-    {
-      cstring = cptr;
-      /* temporarily insert a null terminator at end of the string */
-      tpos = cptr + twidth;
-      tempstore = *tpos;
-      *tpos = 0;
-
-      /* check if null value is defined, and if the    */
-      /* column string is identical to the null string */
-      if (snull[0] != ASCII_NULL_UNDEFINED && 
-         !strncmp(snull, cptr, nullen) )
-      {
-        if (nullcheck)  
-        {
-          *anynull = 1;    
-          if (nullcheck == 1)
-            output[ii] = nullval;
-          else
-            nullarray[ii] = 1;
-        }
-        cptr += twidth;
-      }
-      else
-      {
-        /* value is not the null value, so decode it */
-        /* remove any embedded blank characters from the string */
-
-        decpt = 0;
-        sign = 1;
-        val  = 0.;
-        power = 1.;
-        exponent = 0;
-        esign = 1;
-
-        while (*cptr == ' ')               /* skip leading blanks */
-           cptr++;
-
-        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
-        {
-          if (*cptr == '-')
-             sign = -1;
-
-          cptr++;
-
-          while (*cptr == ' ')         /* skip blanks between sign and value */
-            cptr++;
-        }
-
-        while (*cptr >= '0' && *cptr <= '9')
-        {
-          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-          cptr++;
-
-          while (*cptr == ' ')         /* skip embedded blanks in the value */
-            cptr++;
-        }
-
-        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
-        {
-          decpt = 1;       /* set flag to show there was a decimal point */
-          cptr++;
-          while (*cptr == ' ')         /* skip any blanks */
-            cptr++;
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-            power = power * 10.;
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks in the value */
-              cptr++;
-          }
-        }
-
-        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
-        {
-          cptr++;
-          while (*cptr == ' ')         /* skip blanks */
-              cptr++;
-  
-          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
-          {
-            if (*cptr == '-')
-               esign = -1;
-
-            cptr++;
-
-            while (*cptr == ' ')        /* skip blanks between sign and exp */
-              cptr++;
-          }
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks */
-              cptr++;
-          }
-        }
-
-        if (*cptr  != 0)  /* should end up at the null terminator */
-        {
-          sprintf(message, "Cannot read number from ASCII table");
-          ffpmsg(message);
-          sprintf(message, "Column field = %s.", cstring);
-          ffpmsg(message);
-          /* restore the char that was overwritten by the null */
-          *tpos = tempstore;
-          return(*status = BAD_C2D);
-        }
-
-        if (!decpt)  /* if no explicit decimal, use implied */
-           power = implipower;
-
-        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
-
-        dvalue = dvalue * scale + zero;   /* apply the scaling */
-
-        if (dvalue < DUSHRT_MIN)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = 0;
-        }
-        else if (dvalue > DUSHRT_MAX)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = USHRT_MAX;
-        }
-        else
-            output[ii] = (unsigned short) dvalue;
-      }
-      /* restore the char that was overwritten by the null */
-      *tpos = tempstore;
-    }
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcoluj.c b/src/external/OpenGR/3rdparty/cfitsio/getcoluj.c
deleted file mode 100644
index d3b0e638b..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcoluj.c
+++ /dev/null
@@ -1,1915 +0,0 @@
-/*  This file, getcoluj.c, contains routines that read data elements from  */
-/*  a FITS image or table, with unsigned long data type.                   */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffgpvuj(fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-   unsigned long  nulval,     /* I - value for undefined pixels              */
-   unsigned long  *array,     /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    char cdummy;
-    int nullcheck = 1;
-    unsigned long nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_pixels(fptr, TULONG, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcluj(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpfuj(fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-   unsigned long  *array,     /* O - array of values that are returned       */
-            char *nularray,   /* O - array of null pixel flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Any undefined pixels in the returned array will be set = 0 and the 
-  corresponding nularray value will be set = 1.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    int nullcheck = 2;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_read_compressed_pixels(fptr, TULONG, firstelem, nelem,
-            nullcheck, NULL, array, nularray, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcluj(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
-               array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg2duj(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-  unsigned long  nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-  unsigned long  *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    /* call the 3D reading routine, with the 3rd dimension = 1 */
-
-    ffg3duj(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
-           anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg3duj(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-  unsigned long  nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
-  unsigned long  *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 3-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    long tablerow, ii, jj;
-    char cdummy;
-    int nullcheck = 1;
-    long inc[] = {1,1,1};
-    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
-    LONGLONG lpixel[3];
-    unsigned long nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        lpixel[0] = ncols;
-        lpixel[1] = nrows;
-        lpixel[2] = naxis3;
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TULONG, fpixel, lpixel, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-       /* all the image pixels are contiguous, so read all at once */
-       ffgcluj(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-       return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to read */
-    narray = 0;  /* next pixel in output array to be filled */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* reading naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffgcluj(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
-          &array[narray], &cdummy, anynul, status) > 0)
-          return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsvuj(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-  unsigned long nulval,    /* I - value to set undefined pixels             */
-  unsigned long *array,    /* O - array to be filled and returned           */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9];
-    long nelem, nultyp, ninc, numcol;
-    LONGLONG felem, dsize[10], blcll[9], trcll[9];
-    int hdutype, anyf;
-    char ldummy, msg[FLEN_ERRMSG];
-    int nullcheck = 1;
-    unsigned long nullvalue;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvuj is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TULONG, blcll, trcll, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 1;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvuj: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgcluj(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsfuj(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-  unsigned long *array,    /* O - array to be filled and returned           */
-           char *flagval,  /* O - set to 1 if corresponding value is null   */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dsize[10];
-    LONGLONG blcll[9], trcll[9];
-    long felem, nelem, nultyp, ninc, numcol;
-    unsigned long nulval = 0;
-    int hdutype, anyf;
-    char msg[FLEN_ERRMSG];
-    int nullcheck = 2;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvj is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        fits_read_compressed_img(fptr, TULONG, blcll, trcll, inc,
-            nullcheck, NULL, array, flagval, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 2;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvj: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgcluj(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffggpuj(fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            long  nelem,      /* I - number of values to read                */
-   unsigned long  *array,     /* O - array of values that are returned       */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of group parameters from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-*/
-{
-    long row;
-    int idummy;
-    char cdummy;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcluj(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
-               array, &cdummy, &idummy, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcvuj(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-  unsigned long  nulval,     /* I - value for null pixels                   */
-  unsigned long *array,      /* O - array of values that are read           */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy;
-
-    ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
-           array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfuj(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-  unsigned long  *array,     /* O - array of values that are read           */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-*/
-{
-    unsigned long dummy = 0;
-
-    ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
-           array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcluj(fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG  firstelem, /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-   unsigned long  nulval,     /* I - value for null pixels if nultyp = 1     */
-   unsigned long  *array,     /* O - array of values that are read           */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer be a virtual column in a 1 or more grouped FITS primary
-  array or image extension.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The output array of values will be converted from the datatype of the column 
-  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    double scale, zero, power = 1., dtemp;
-    int tcode, maxelem2, hdutype, xcode, decimals;
-    long twidth, incre;
-    long ii, xwidth, ntodo;
-    int nulcheck;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull;
-    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
-    char tform[20];
-    char message[81];
-    char snull[20];   /*  the FITS null value if reading from ASCII table  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    if (anynul)
-        *anynul = 0;
-
-    if (nultyp == 2)
-        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
-         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
-         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
-         return(*status);
-    maxelem = maxelem2;
-
-    incre *= elemincre;   /* multiply incre to just get every nth pixel */
-
-    if (tcode == TSTRING)    /* setup for ASCII tables */
-    {
-      /* get the number of implied decimal places if no explicit decmal point */
-      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
-      for(ii = 0; ii < decimals; ii++)
-        power *= 10.;
-    }
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
-            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
-            nulcheck = 0;            /* then do not check for null values. */
-
-    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
-         nulcheck = 0;
-
-    /*----------------------------------------------------------------------*/
-    /*  If FITS column and output data array have same datatype, then we do */
-    /*  not need to use a temporary buffer to store intermediate datatype.  */
-    /*----------------------------------------------------------------------*/
-    if ((tcode == TLONG) && (LONGSIZE == 32))  /* Special Case:                        */
-    {                             /* no type convertion required, so read */
-                                  /* data directly into output buffer.    */
-
-        if (nelem < (LONGLONG)INT32_MAX/4) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/4;
-        }
-    }
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the pixels from the FITS column. If the column does not   */
-    /*  have the same datatype as the output array, then we have to read   */
-    /*  the raw values into a temporary buffer (of limited size).  In      */
-    /*  the case of a vector colum read only 1 vector of values at a time  */
-    /*  then skip to the next row if more values need to be read.          */
-    /*  After reading the raw values, then call the fffXXYY routine to (1) */
-    /*  test for undefined values, (2) convert the datatype if necessary,  */
-    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
-    /*  scaling parameters.                                                */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to read */
-    next = 0;                 /* next element in array to be read   */
-    rownum = 0;               /* row number, relative to firstrow   */
-
-    while (remain)
-    {
-        /* limit the number of pixels to read at one time to the number that
-           will fit in the buffer or to the number of pixels that remain in
-           the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
-
-        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
-
-        switch (tcode) 
-        {
-            case (TLONG):
-	      if (LONGSIZE == 32) {
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
-                       status);
-                fffi4u4((INT32BIT *) &array[next], ntodo, scale, zero,
-                         nulcheck, (INT32BIT) tnull, nulval, &nularray[next],
-                         anynul, &array[next], status);
-	      } else { /* case where sizeof(long) = 8 */
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
-                       status);
-                fffi4u4((INT32BIT *) buffer, ntodo, scale, zero,
-                         nulcheck, (INT32BIT) tnull, nulval, &nularray[next],
-                         anynul, &array[next], status);
-	      }
-
-
-                break;
-            case (TLONGLONG):
-
-                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
-                fffi8u4( (LONGLONG *) buffer, ntodo, scale, zero, 
-                           nulcheck, tnull, nulval, &nularray[next], 
-                            anynul, &array[next], status);
-                break;
-            case (TBYTE):
-                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
-                       status);
-                fffi1u4((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
-                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
-                     &array[next], status);
-                break;
-            case (TSHORT):
-                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
-                fffi2u4((short  *) buffer, ntodo, scale, zero, nulcheck, 
-                      (short) tnull, nulval, &nularray[next], anynul, 
-                      &array[next], status);
-                break;
-            case (TFLOAT):
-                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
-                fffr4u4((float  *) buffer, ntodo, scale, zero, nulcheck, 
-                       nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TDOUBLE):
-                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
-                fffr8u4((double *) buffer, ntodo, scale, zero, nulcheck, 
-                          nulval, &nularray[next], anynul, 
-                          &array[next], status);
-                break;
-            case (TSTRING):
-                ffmbyt(fptr, readptr, REPORT_EOF, status);
-       
-                if (incre == twidth)    /* contiguous bytes */
-                     ffgbyt(fptr, ntodo * twidth, buffer, status);
-                else
-                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                               status);
-
-                fffstru4((char *) buffer, ntodo, scale, zero, twidth, power,
-                     nulcheck, snull, nulval, &nularray[next], anynul,
-                     &array[next], status);
-                break;
-
-            default:  /*  error trap for invalid column format */
-                sprintf(message, 
-                   "Cannot read numbers from column %d which has format %s",
-                    colnum, tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous read operation */
-        {
-	  dtemp = (double) next;
-          if (hdutype > 0)
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from column %d (ffgcluj).",
-              dtemp+1., dtemp+ntodo, colnum);
-          else
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from image (ffgcluj).",
-              dtemp+1., dtemp+ntodo);
-
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum = elemnum + (ntodo * elemincre);
-
-            if (elemnum >= repeat)  /* completed a row; start on later row */
-            {
-                rowincre = elemnum / repeat;
-                rownum += rowincre;
-                elemnum = elemnum - (rowincre * repeat);
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while reading FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi1u4(unsigned char *input, /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (unsigned long) input[ii];  /* copy input */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DULONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DULONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = ULONG_MAX;
-                }
-                else
-                    output[ii] = (unsigned long) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (unsigned long) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DULONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DULONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = ULONG_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned long) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi2u4(short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else
-                    output[ii] = (unsigned long) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DULONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DULONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = ULONG_MAX;
-                }
-                else
-                    output[ii] = (unsigned long) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < 0)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else
-                        output[ii] = (unsigned long) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DULONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DULONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = ULONG_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned long) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi4u4(INT32BIT *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 2147483648.)
-        {       
-           /* Instead of adding 2147483648, it is more efficient */
-           /* to just flip the sign bit with the XOR operator */
-
-            for (ii = 0; ii < ntodo; ii++) {
-               output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
-	    }
-        }
-        else if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else
-                    output[ii] = (unsigned long) input[ii]; /* copy input */
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DULONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DULONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = ULONG_MAX;
-                }
-                else
-                    output[ii] = (unsigned long) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 2147483648.) 
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                   output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
-            }
-        }
-        else if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else
-                    output[ii] = (unsigned long) input[ii]; /* copy input */
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DULONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DULONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = ULONG_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned long) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi8u4(LONGLONG *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
-   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > ULONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = ULONG_MAX;
-                }
-                else
-                    output[ii] = (unsigned long) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DULONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DULONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = ULONG_MAX;
-                }
-                else
-                    output[ii] = (unsigned long) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < 0)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > ULONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = ULONG_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned long) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DULONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DULONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = ULONG_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned long) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr4u4(float *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DULONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > DULONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = ULONG_MAX;
-                }
-                else
-                    output[ii] = (unsigned long) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DULONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DULONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = ULONG_MAX;
-                }
-                else
-                    output[ii] = (unsigned long) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr++;       /* point to MSBs */
-#endif
-
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DULONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > DULONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = ULONG_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned long) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  { 
-                    if (zero < DULONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (zero > DULONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = ULONG_MAX;
-                    }
-                    else
-                      output[ii] = (unsigned long) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DULONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DULONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = ULONG_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned long) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr8u4(double *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DULONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > DULONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = ULONG_MAX;
-                }
-                else
-                    output[ii] = (unsigned long) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DULONG_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DULONG_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = ULONG_MAX;
-                }
-                else
-                    output[ii] = (unsigned long) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr += 3;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DULONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > DULONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = ULONG_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned long) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  { 
-                    if (zero < DULONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (zero > DULONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = ULONG_MAX;
-                    }
-                    else
-                      output[ii] = (unsigned long) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DULONG_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DULONG_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = ULONG_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned long) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffstru4(char *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            long twidth,          /* I - width of each substring of chars    */
-            double implipower,    /* I - power of 10 of implied decimal      */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            char  *snull,         /* I - value of FITS null string, if any   */
-   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned long *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file. Check
-  for null values and do scaling if required. The nullcheck code value
-  determines how any null values in the input array are treated. A null
-  value is an input pixel that is equal to snull.  If nullcheck= 0, then
-  no special checking for nulls is performed.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    int nullen;
-    long ii;
-    double dvalue;
-    char *cstring, message[81];
-    char *cptr, *tpos;
-    char tempstore, chrzero = '0';
-    double val, power;
-    int exponent, sign, esign, decpt;
-
-    nullen = strlen(snull);
-    cptr = input;  /* pointer to start of input string */
-    for (ii = 0; ii < ntodo; ii++)
-    {
-      cstring = cptr;
-      /* temporarily insert a null terminator at end of the string */
-      tpos = cptr + twidth;
-      tempstore = *tpos;
-      *tpos = 0;
-
-      /* check if null value is defined, and if the    */
-      /* column string is identical to the null string */
-      if (snull[0] != ASCII_NULL_UNDEFINED && 
-         !strncmp(snull, cptr, nullen) )
-      {
-        if (nullcheck)  
-        {
-          *anynull = 1;    
-          if (nullcheck == 1)
-            output[ii] = nullval;
-          else
-            nullarray[ii] = 1;
-        }
-        cptr += twidth;
-      }
-      else
-      {
-        /* value is not the null value, so decode it */
-        /* remove any embedded blank characters from the string */
-
-        decpt = 0;
-        sign = 1;
-        val  = 0.;
-        power = 1.;
-        exponent = 0;
-        esign = 1;
-
-        while (*cptr == ' ')               /* skip leading blanks */
-           cptr++;
-
-        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
-        {
-          if (*cptr == '-')
-             sign = -1;
-
-          cptr++;
-
-          while (*cptr == ' ')         /* skip blanks between sign and value */
-            cptr++;
-        }
-
-        while (*cptr >= '0' && *cptr <= '9')
-        {
-          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-          cptr++;
-
-          while (*cptr == ' ')         /* skip embedded blanks in the value */
-            cptr++;
-        }
-
-        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
-        {
-          decpt = 1;       /* set flag to show there was a decimal point */
-          cptr++;
-          while (*cptr == ' ')         /* skip any blanks */
-            cptr++;
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-            power = power * 10.;
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks in the value */
-              cptr++;
-          }
-        }
-
-        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
-        {
-          cptr++;
-          while (*cptr == ' ')         /* skip blanks */
-              cptr++;
-  
-          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
-          {
-            if (*cptr == '-')
-               esign = -1;
-
-            cptr++;
-
-            while (*cptr == ' ')        /* skip blanks between sign and exp */
-              cptr++;
-          }
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks */
-              cptr++;
-          }
-        }
-
-        if (*cptr  != 0)  /* should end up at the null terminator */
-        {
-          sprintf(message, "Cannot read number from ASCII table");
-          ffpmsg(message);
-          sprintf(message, "Column field = %s.", cstring);
-          ffpmsg(message);
-          /* restore the char that was overwritten by the null */
-          *tpos = tempstore;
-          return(*status = BAD_C2D);
-        }
-
-        if (!decpt)  /* if no explicit decimal, use implied */
-           power = implipower;
-
-        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
-
-        dvalue = dvalue * scale + zero;   /* apply the scaling */
-
-        if (dvalue < DULONG_MIN)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = 0;
-        }
-        else if (dvalue > DULONG_MAX)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = ULONG_MAX;
-        }
-        else
-            output[ii] = (unsigned long) dvalue;
-      }
-      /* restore the char that was overwritten by the null */
-      *tpos = tempstore;
-    }
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getcoluk.c b/src/external/OpenGR/3rdparty/cfitsio/getcoluk.c
deleted file mode 100644
index 6c0dfb04b..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getcoluk.c
+++ /dev/null
@@ -1,1923 +0,0 @@
-/*  This file, getcolk.c, contains routines that read data elements from   */
-/*  a FITS image or table, with 'unsigned int' data type.                  */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffgpvuk( fitsfile *fptr,   /* I - FITS file pointer                      */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-   unsigned int   nulval,     /* I - value for undefined pixels              */
-   unsigned int   *array,     /* O - array of values that are returned       */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Undefined elements will be set equal to NULVAL, unless NULVAL=0
-  in which case no checking for undefined values will be performed.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    char cdummy;
-    int nullcheck = 1;
-    unsigned int nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-         nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_pixels(fptr, TUINT, firstelem, nelem,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcluk(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgpfuk(fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-   unsigned int   *array,     /* O - array of values that are returned       */
-            char *nularray,   /* O - array of null pixel flags               */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-  Any undefined pixels in the returned array will be set = 0 and the 
-  corresponding nularray value will be set = 1.
-  ANYNUL is returned with a value of .true. if any pixels are undefined.
-*/
-{
-    long row;
-    int nullcheck = 2;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_read_compressed_pixels(fptr, TUINT, firstelem, nelem,
-            nullcheck, NULL, array, nularray, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcluk(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
-               array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg2duk(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-  unsigned int  nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-  unsigned int  *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    /* call the 3D reading routine, with the 3rd dimension = 1 */
-
-    ffg3duk(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
-           anynul, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffg3duk(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,     /* I - group to read (1 = 1st group)           */
-  unsigned int   nulval,    /* set undefined pixels equal to this          */
-           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
-           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
-           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
-           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
-           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
-  unsigned int   *array,    /* O - array to be filled and returned         */
-           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
-           int  *status)    /* IO - error status                           */
-/*
-  Read an entire 3-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being read).  Any null
-  values in the array will be set equal to the value of nulval, unless
-  nulval = 0 in which case no null checking will be performed.
-*/
-{
-    long tablerow, ii, jj;
-    char cdummy;
-    int nullcheck = 1;
-    long inc[] = {1,1,1};
-    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
-    LONGLONG lpixel[3];
-    unsigned int nullvalue;
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        lpixel[0] = ncols;
-        lpixel[1] = nrows;
-        lpixel[2] = naxis3;
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TUINT, fpixel, lpixel, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-       /* all the image pixels are contiguous, so read all at once */
-       ffgcluk(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
-               array, &cdummy, anynul, status);
-       return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to read */
-    narray = 0;  /* next pixel in output array to be filled */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* reading naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffgcluk(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
-          &array[narray], &cdummy, anynul, status) > 0)
-          return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsvuk(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-  unsigned int  nulval,    /* I - value to set undefined pixels             */
-  unsigned int  *array,    /* O - array to be filled and returned           */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9];
-    long nelem, nultyp, ninc, numcol;
-    LONGLONG felem, dsize[10], blcll[9], trcll[9];
-    int hdutype, anyf;
-    char ldummy, msg[FLEN_ERRMSG];
-    int nullcheck = 1;
-    unsigned int nullvalue;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvuk is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        nullvalue = nulval;  /* set local variable */
-
-        fits_read_compressed_img(fptr, TUINT, blcll, trcll, inc,
-            nullcheck, &nullvalue, array, NULL, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 1;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvuk: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgcluk(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsfuk(fitsfile *fptr, /* I - FITS file pointer                         */
-           int  colnum,    /* I - number of the column to read (1 = 1st)    */
-           int naxis,      /* I - number of dimensions in the FITS array    */
-           long  *naxes,   /* I - size of each dimension                    */
-           long  *blc,     /* I - 'bottom left corner' of the subsection    */
-           long  *trc,     /* I - 'top right corner' of the subsection      */
-           long  *inc,     /* I - increment to be applied in each dimension */
-  unsigned int  *array,    /* O - array to be filled and returned           */
-           char *flagval,  /* O - set to 1 if corresponding value is null   */
-           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
-           int  *status)   /* IO - error status                             */
-/*
-  Read a subsection of data values from an image or a table column.
-  This routine is set up to handle a maximum of nine dimensions.
-*/
-{
-    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
-    long str[9],stp[9],incr[9],dsize[10];
-    LONGLONG blcll[9], trcll[9];
-    long felem, nelem, nultyp, ninc, numcol;
-    long nulval = 0;
-    int hdutype, anyf;
-    char msg[FLEN_ERRMSG];
-    int nullcheck = 2;
-
-    if (naxis < 1 || naxis > 9)
-    {
-        sprintf(msg, "NAXIS = %d in call to ffgsvj is out of range", naxis);
-        ffpmsg(msg);
-        return(*status = BAD_DIMEN);
-    }
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        for (ii=0; ii < naxis; ii++) {
-	    blcll[ii] = blc[ii];
-	    trcll[ii] = trc[ii];
-	}
-
-        fits_read_compressed_img(fptr, TUINT, blcll, trcll, inc,
-            nullcheck, NULL, array, flagval, anynul, status);
-        return(*status);
-    }
-
-/*
-    if this is a primary array, then the input COLNUM parameter should
-    be interpreted as the row number, and we will alway read the image
-    data from column 2 (any group parameters are in column 1).
-*/
-    if (ffghdt(fptr, &hdutype, status) > 0)
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-    {
-        /* this is a primary array, or image extension */
-        if (colnum == 0)
-        {
-            rstr = 1;
-            rstp = 1;
-        }
-        else
-        {
-            rstr = colnum;
-            rstp = colnum;
-        }
-        rinc = 1;
-        numcol = 2;
-    }
-    else
-    {
-        /* this is a table, so the row info is in the (naxis+1) elements */
-        rstr = blc[naxis];
-        rstp = trc[naxis];
-        rinc = inc[naxis];
-        numcol = colnum;
-    }
-
-    nultyp = 2;
-    if (anynul)
-        *anynul = FALSE;
-
-    i0 = 0;
-    for (ii = 0; ii < 9; ii++)
-    {
-        str[ii] = 1;
-        stp[ii] = 1;
-        incr[ii] = 1;
-        dsize[ii] = 1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      if (trc[ii] < blc[ii])
-      {
-        sprintf(msg, "ffgsvj: illegal range specified for axis %ld", ii + 1);
-        ffpmsg(msg);
-        return(*status = BAD_PIX_NUM);
-      }
-
-      str[ii] = blc[ii];
-      stp[ii] = trc[ii];
-      incr[ii] = inc[ii];
-      dsize[ii + 1] = dsize[ii] * naxes[ii];
-    }
-
-    if (naxis == 1 && naxes[0] == 1)
-    {
-      /* This is not a vector column, so read all the rows at once */
-      nelem = (rstp - rstr) / rinc + 1;
-      ninc = rinc;
-      rstp = rstr;
-    }
-    else
-    {
-      /* have to read each row individually, in all dimensions */
-      nelem = (stp[0] - str[0]) / inc[0] + 1;
-      ninc = incr[0];
-    }
-
-    for (row = rstr; row <= rstp; row += rinc)
-    {
-     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
-     {
-      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
-      {
-       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
-       {
-        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
-        {
-         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
-         {
-          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
-          {
-           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
-           {
-            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
-            {
-              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
-                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
-                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
-                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
-
-              if ( ffgcluk(fptr, numcol, row, felem, nelem, ninc, nultyp,
-                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
-                   return(*status);
-
-              if (anyf && anynul)
-                  *anynul = TRUE;
-
-              i0 += nelem;
-            }
-           }
-          }
-         }
-        }
-       }
-      }
-     }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffggpuk( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to read (1 = 1st group)           */
-            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
-            long  nelem,      /* I - number of values to read                */
-   unsigned int  *array,     /* O - array of values that are returned       */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of group parameters from the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being read).
-*/
-{
-    long row;
-    int idummy;
-    char cdummy;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffgcluk(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
-               array, &cdummy, &idummy, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcvuk(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-  unsigned int   nulval,     /* I - value for null pixels                   */
-  unsigned int  *array,      /* O - array of values that are read           */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Any undefined pixels will be set equal to the value of 'nulval' unless
-  nulval = 0 in which case no checks for undefined pixels will be made.
-*/
-{
-    char cdummy;
-
-    ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
-           array, &cdummy, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcfuk(fitsfile *fptr,   /* I - FITS file pointer                       */
-           int  colnum,      /* I - number of column to read (1 = 1st col)  */
-           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
-           LONGLONG  nelem,      /* I - number of values to read                */
-  unsigned int   *array,     /* O - array of values that are read           */
-           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
-           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-           int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU. Automatic
-  datatype conversion will be performed if the datatype of the column does not
-  match the datatype of the array parameter. The output values will be scaled 
-  by the FITS TSCALn and TZEROn values if these values have been defined.
-  Nularray will be set = 1 if the corresponding array pixel is undefined, 
-  otherwise nularray will = 0.
-*/
-{
-    int dummy = 0;
-
-    ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
-           array, nularray, anynul, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcluk( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to read (1 = 1st col)  */
-            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
-            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to read                */
-            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
-            int   nultyp,     /* I - null value handling code:               */
-                              /*     1: set undefined pixels = nulval        */
-                              /*     2: set nularray=1 for undefined pixels  */
-   unsigned int   nulval,     /* I - value for null pixels if nultyp = 1     */
-   unsigned int  *array,      /* O - array of values that are read           */
-            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-  Read an array of values from a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer be a virtual column in a 1 or more grouped FITS primary
-  array or image extension.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The output array of values will be converted from the datatype of the column 
-  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    double scale, zero, power = 1., dtemp;
-    int tcode, maxelem2, hdutype, xcode, decimals;
-    long twidth, incre;
-    long ii, xwidth, ntodo;
-    int nulcheck;
-    LONGLONG repeat, startpos, elemnum, readptr, tnull;
-    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
-    char tform[20];
-    char message[81];
-    char snull[20];   /*  the FITS null value if reading from ASCII table  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
-        return(*status);
-
-    /* call the 'short' or 'long' version of this routine, if possible */
-    if (sizeof(int) == sizeof(short))
-        ffgclui(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
-          (unsigned short) nulval, (unsigned short *) array, nularray, anynul,
-           status);
-    else if (sizeof(int) == sizeof(long))
-        ffgcluj(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
-          (unsigned long) nulval, (unsigned long *) array, nularray, anynul,
-          status);
-    else
-    {
-    /*
-      This is a special case: sizeof(int) is not equal to sizeof(short) or
-      sizeof(long).  This occurs on Alpha OSF systems where short = 2 bytes,
-      int = 4 bytes, and long = 8 bytes.
-    */
-
-    buffer = cbuff;
-
-    if (anynul)
-        *anynul = 0;
-
-    if (nultyp == 2)
-        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
-         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
-         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
-         return(*status);
-    maxelem = maxelem2;
-
-    incre *= elemincre;   /* multiply incre to just get every nth pixel */
-
-    if (tcode == TSTRING)    /* setup for ASCII tables */
-    {
-      /* get the number of implied decimal places if no explicit decmal point */
-      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
-      for(ii = 0; ii < decimals; ii++)
-        power *= 10.;
-    }
-    /*------------------------------------------------------------------*/
-    /*  Decide whether to check for null values in the input FITS file: */
-    /*------------------------------------------------------------------*/
-    nulcheck = nultyp; /* by default check for null values in the FITS file */
-
-    if (nultyp == 1 && nulval == 0)
-       nulcheck = 0;    /* calling routine does not want to check for nulls */
-
-    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
-            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
-            nulcheck = 0;            /* then do not check for null values. */
-
-    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
-            nulcheck = 0;            /* Impossible null value */
-
-    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
-         nulcheck = 0;
-
-    /*----------------------------------------------------------------------*/
-    /*  If FITS column and output data array have same datatype, then we do */
-    /*  not need to use a temporary buffer to store intermediate datatype.  */
-    /*----------------------------------------------------------------------*/
-    if (tcode == TLONG)  /* Special Case: */
-    {                             /* data are 4-bytes long, so read       */
-                                  /* data directly into output buffer.    */
-
-        if (nelem < (LONGLONG)INT32_MAX/4) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/4;
-        }
-    }
-
-    /*---------------------------------------------------------------------*/
-    /*  Now read the pixels from the FITS column. If the column does not   */
-    /*  have the same datatype as the output array, then we have to read   */
-    /*  the raw values into a temporary buffer (of limited size).  In      */
-    /*  the case of a vector colum read only 1 vector of values at a time  */
-    /*  then skip to the next row if more values need to be read.          */
-    /*  After reading the raw values, then call the fffXXYY routine to (1) */
-    /*  test for undefined values, (2) convert the datatype if necessary,  */
-    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
-    /*  scaling parameters.                                                */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to read */
-    next = 0;                 /* next element in array to be read   */
-    rownum = 0;               /* row number, relative to firstrow   */
-
-    while (remain)
-    {
-        /* limit the number of pixels to read at one time to the number that
-           will fit in the buffer or to the number of pixels that remain in
-           the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
-
-        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
-
-        switch (tcode) 
-        {
-            case (TLONG):
-                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
-                       status);
-                    fffi4uint((INT32BIT *) &array[next], ntodo, scale, zero, 
-                           nulcheck, (INT32BIT) tnull, nulval, &nularray[next],
-                           anynul, &array[next], status);
-                break;
-            case (TLONGLONG):
-
-                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
-                fffi8uint( (LONGLONG *) buffer, ntodo, scale, zero, 
-                           nulcheck, tnull, nulval, &nularray[next], 
-                            anynul, &array[next], status);
-                break;
-            case (TBYTE):
-                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
-                       status);
-                fffi1uint((unsigned char *) buffer, ntodo, scale, zero,nulcheck,
-                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
-                     &array[next], status);
-                break;
-            case (TSHORT):
-                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
-                fffi2uint((short  *) buffer, ntodo, scale, zero, nulcheck, 
-                      (short) tnull, nulval, &nularray[next], anynul, 
-                      &array[next], status);
-                break;
-            case (TFLOAT):
-                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
-                fffr4uint((float  *) buffer, ntodo, scale, zero, nulcheck, 
-                       nulval, &nularray[next], anynul, 
-                       &array[next], status);
-                break;
-            case (TDOUBLE):
-                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
-                fffr8uint((double *) buffer, ntodo, scale, zero, nulcheck, 
-                          nulval, &nularray[next], anynul, 
-                          &array[next], status);
-                break;
-            case (TSTRING):
-                ffmbyt(fptr, readptr, REPORT_EOF, status);
-       
-                if (incre == twidth)    /* contiguous bytes */
-                     ffgbyt(fptr, ntodo * twidth, buffer, status);
-                else
-                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                               status);
-
-                fffstruint((char *) buffer, ntodo, scale, zero, twidth, power,
-                     nulcheck, snull, nulval, &nularray[next], anynul,
-                     &array[next], status);
-                break;
-
-            default:  /*  error trap for invalid column format */
-                sprintf(message, 
-                   "Cannot read numbers from column %d which has format %s",
-                    colnum, tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous read operation */
-        {
-	  dtemp = (double) next;
-          if (hdutype > 0)
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from column %d (ffgcluk).",
-              dtemp+1., dtemp+ntodo, colnum);
-          else
-            sprintf(message,
-            "Error reading elements %.0f thru %.0f from image (ffgcluk).",
-              dtemp+1., dtemp+ntodo);
-
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum = elemnum + (ntodo * elemincre);
-
-            if (elemnum >= repeat)  /* completed a row; start on later row */
-            {
-                rowincre = elemnum / repeat;
-                rownum += rowincre;
-                elemnum = elemnum - (rowincre * repeat);
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while reading FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    }  /* end of DEC Alpha special case */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi1uint(unsigned char *input,/* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-   unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned int  *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (unsigned int) input[ii];  /* copy input */
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UINT_MAX;
-                }
-                else
-                    output[ii] = (unsigned int) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                    output[ii] = (unsigned int) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UINT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned int) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi2uint(short *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-   unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned int  *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else
-                    output[ii] = (unsigned int) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UINT_MAX;
-                }
-                else
-                    output[ii] = (unsigned int) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < 0)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else
-                        output[ii] = (unsigned int) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UINT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned int) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi4uint(INT32BIT *input,    /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-   unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned int  *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 2147483648.)
-        {       
-           /* Instead of adding 2147483648, it is more efficient */
-           /* to just flip the sign bit with the XOR operator */
-
-            for (ii = 0; ii < ntodo; ii++)
-               output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
-        }
-        else if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else
-                    output[ii] = (unsigned int) input[ii]; /* copy to output */
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UINT_MAX;
-                }
-                else
-                    output[ii] = (unsigned int) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 2147483648.) 
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                   output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
-            }
-        }
-        else if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else
-                    output[ii] = (unsigned int) input[ii];
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UINT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned int) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffi8uint(LONGLONG *input,    /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
-   unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned int  *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to tnull.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < 0)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > UINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UINT_MAX;
-                }
-                else
-                    output[ii] = (unsigned int) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UINT_MAX;
-                }
-                else
-                    output[ii] = (unsigned int) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (input[ii] < 0)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > UINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UINT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned int) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UINT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned int) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr4uint(float *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-   unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned int  *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DUINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > DUINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UINT_MAX;
-                }
-                else
-                    output[ii] = (unsigned int) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UINT_MAX;
-                }
-                else
-                    output[ii] = (unsigned int) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr++;       /* point to MSBs */
-#endif
-
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DUINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > DUINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UINT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned int) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 2)
-            {
-              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  { 
-                    if (zero < DUINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (zero > DUINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UINT_MAX;
-                    }
-                    else
-                      output[ii] = (unsigned int) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UINT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned int) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffr8uint(double *input,       /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-   unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned int  *output,         /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file.
-  Check for null values and do datatype conversion and scaling if required.
-  The nullcheck code value determines how any null values in the input array
-  are treated.  A null value is an input pixel that is equal to NaN.  If 
-  nullcheck = 0, then no checking for nulls is performed and any null values
-  will be transformed just like any other pixel.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    long ii;
-    double dvalue;
-    short *sptr, iret;
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-        if (scale == 1. && zero == 0.)      /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] < DUINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (input[ii] > DUINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UINT_MAX;
-                }
-                else
-                    output[ii] = (unsigned int) input[ii];
-            }
-        }
-        else             /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                dvalue = input[ii] * scale + zero;
-
-                if (dvalue < DUINT_MIN)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = 0;
-                }
-                else if (dvalue > DUINT_MAX)
-                {
-                    *status = OVERFLOW_ERR;
-                    output[ii] = UINT_MAX;
-                }
-                else
-                    output[ii] = (unsigned int) dvalue;
-            }
-        }
-    }
-    else        /* must check for null values */
-    {
-        sptr = (short *) input;
-
-#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
-        sptr += 3;       /* point to MSBs */
-#endif
-        if (scale == 1. && zero == 0.)  /* no scaling */
-        {       
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                     output[ii] = 0;
-              }
-              else
-                {
-                    if (input[ii] < DUINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (input[ii] > DUINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UINT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned int) input[ii];
-                }
-            }
-        }
-        else                  /* must scale the data */
-        {
-            for (ii = 0; ii < ntodo; ii++, sptr += 4)
-            {
-              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
-              {
-                  if (iret == 1)  /* is it a NaN? */
-                  {  
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                  }
-                  else            /* it's an underflow */
-                  { 
-                    if (zero < DUINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (zero > DUINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UINT_MAX;
-                    }
-                    else
-                      output[ii] = (unsigned int) zero;
-                  }
-              }
-              else
-                {
-                    dvalue = input[ii] * scale + zero;
-
-                    if (dvalue < DUINT_MIN)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = 0;
-                    }
-                    else if (dvalue > DUINT_MAX)
-                    {
-                        *status = OVERFLOW_ERR;
-                        output[ii] = UINT_MAX;
-                    }
-                    else
-                        output[ii] = (unsigned int) dvalue;
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffstruint(char *input,        /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            long twidth,          /* I - width of each substring of chars    */
-            double implipower,    /* I - power of 10 of implied decimal      */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            char  *snull,         /* I - value of FITS null string, if any   */
-   unsigned int nullval,          /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-   unsigned int *output,          /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-  Copy input to output following reading of the input from a FITS file. Check
-  for null values and do scaling if required. The nullcheck code value
-  determines how any null values in the input array are treated. A null
-  value is an input pixel that is equal to snull.  If nullcheck= 0, then
-  no special checking for nulls is performed.  If nullcheck = 1, then the
-  output pixel will be set = nullval if the corresponding input pixel is null.
-  If nullcheck = 2, then if the pixel is null then the corresponding value of
-  nullarray will be set to 1; the value of nullarray for non-null pixels 
-  will = 0.  The anynull parameter will be set = 1 if any of the returned
-  pixels are null, otherwise anynull will be returned with a value = 0;
-*/
-{
-    int nullen;
-    long ii;
-    double dvalue;
-    char *cstring, message[81];
-    char *cptr, *tpos;
-    char tempstore, chrzero = '0';
-    double val, power;
-    int exponent, sign, esign, decpt;
-
-    nullen = strlen(snull);
-    cptr = input;  /* pointer to start of input string */
-    for (ii = 0; ii < ntodo; ii++)
-    {
-      cstring = cptr;
-      /* temporarily insert a null terminator at end of the string */
-      tpos = cptr + twidth;
-      tempstore = *tpos;
-      *tpos = 0;
-
-      /* check if null value is defined, and if the    */
-      /* column string is identical to the null string */
-      if (snull[0] != ASCII_NULL_UNDEFINED && 
-         !strncmp(snull, cptr, nullen) )
-      {
-        if (nullcheck)  
-        {
-          *anynull = 1;    
-          if (nullcheck == 1)
-            output[ii] = nullval;
-          else
-            nullarray[ii] = 1;
-        }
-        cptr += twidth;
-      }
-      else
-      {
-        /* value is not the null value, so decode it */
-        /* remove any embedded blank characters from the string */
-
-        decpt = 0;
-        sign = 1;
-        val  = 0.;
-        power = 1.;
-        exponent = 0;
-        esign = 1;
-
-        while (*cptr == ' ')               /* skip leading blanks */
-           cptr++;
-
-        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
-        {
-          if (*cptr == '-')
-             sign = -1;
-
-          cptr++;
-
-          while (*cptr == ' ')         /* skip blanks between sign and value */
-            cptr++;
-        }
-
-        while (*cptr >= '0' && *cptr <= '9')
-        {
-          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-          cptr++;
-
-          while (*cptr == ' ')         /* skip embedded blanks in the value */
-            cptr++;
-        }
-
-        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
-        {
-          decpt = 1;       /* set flag to show there was a decimal point */
-          cptr++;
-          while (*cptr == ' ')         /* skip any blanks */
-            cptr++;
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
-            power = power * 10.;
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks in the value */
-              cptr++;
-          }
-        }
-
-        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
-        {
-          cptr++;
-          while (*cptr == ' ')         /* skip blanks */
-              cptr++;
-  
-          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
-          {
-            if (*cptr == '-')
-               esign = -1;
-
-            cptr++;
-
-            while (*cptr == ' ')        /* skip blanks between sign and exp */
-              cptr++;
-          }
-
-          while (*cptr >= '0' && *cptr <= '9')
-          {
-            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
-            cptr++;
-
-            while (*cptr == ' ')         /* skip embedded blanks */
-              cptr++;
-          }
-        }
-
-        if (*cptr  != 0)  /* should end up at the null terminator */
-        {
-          sprintf(message, "Cannot read number from ASCII table");
-          ffpmsg(message);
-          sprintf(message, "Column field = %s.", cstring);
-          ffpmsg(message);
-          /* restore the char that was overwritten by the null */
-          *tpos = tempstore;
-          return(*status = BAD_C2D);
-        }
-
-        if (!decpt)  /* if no explicit decimal, use implied */
-           power = implipower;
-
-        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
-
-        dvalue = dvalue * scale + zero;   /* apply the scaling */
-
-        if (dvalue < DUINT_MIN)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = 0;
-        }
-        else if (dvalue > DUINT_MAX)
-        {
-            *status = OVERFLOW_ERR;
-            output[ii] = UINT_MAX;
-        }
-        else
-            output[ii] = (long) dvalue;
-      }
-      /* restore the char that was overwritten by the null */
-      *tpos = tempstore;
-    }
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/getkey.c b/src/external/OpenGR/3rdparty/cfitsio/getkey.c
deleted file mode 100644
index 513dc7373..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/getkey.c
+++ /dev/null
@@ -1,3471 +0,0 @@
-/*  This file, getkey.c, contains routines that read keywords from         */
-/*  a FITS header.                                                         */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include 
-/* stddef.h is apparently needed to define size_t */
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffghsp(fitsfile *fptr,  /* I - FITS file pointer                     */
-           int *nexist,     /* O - number of existing keywords in header */
-           int *nmore,      /* O - how many more keywords will fit       */
-           int *status)     /* IO - error status                         */
-/*
-  returns the number of existing keywords (not counting the END keyword)
-  and the number of more keyword that will fit in the current header 
-  without having to insert more FITS blocks.
-*/
-{
-    if (*status > 0)
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if (nexist)
-        *nexist = (int) (( ((fptr->Fptr)->headend) - 
-                ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) ) / 80);
-
-    if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-      if (nmore)
-        *nmore = -1;   /* data not written yet, so room for any keywords */
-    }
-    else
-    {
-      /* calculate space available between the data and the END card */
-      if (nmore)
-        *nmore = (int) (((fptr->Fptr)->datastart - (fptr->Fptr)->headend) / 80 - 1);
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffghps(fitsfile *fptr, /* I - FITS file pointer                     */
-          int *nexist,     /* O - number of existing keywords in header */
-          int *position,   /* O - position of next keyword to be read   */
-          int *status)     /* IO - error status                         */
-/*
-  return the number of existing keywords and the position of the next
-  keyword that will be read.
-*/
-{
-    if (*status > 0)
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if (nexist)
-      *nexist = (int) (( ((fptr->Fptr)->headend) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) ) / 80);
-
-    if (position)
-      *position = (int) (( ((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) ) / 80 + 1);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffnchk(fitsfile *fptr,  /* I - FITS file pointer                     */
-           int *status)     /* IO - error status                         */
-/*
-  function returns the position of the first null character (ASCII 0), if
-  any, in the current header.  Null characters are illegal, but the other
-  CFITSIO routines that read the header will not detect this error, because
-  the null gets interpreted as a normal end of string character.
-*/
-{
-    long ii, nblock;
-    LONGLONG bytepos;
-    int length, nullpos;
-    char block[2881];
-    
-    if (*status > 0)
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        return(0);  /* Don't check a file that is just being created.  */
-                    /* It cannot contain nulls since CFITSIO wrote it. */
-    }
-    else
-    {
-        /* calculate number of blocks in the header */
-        nblock = (long) (( (fptr->Fptr)->datastart - 
-                   (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) / 2880);
-    }
-
-    bytepos = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu];
-    ffmbyt(fptr, bytepos, REPORT_EOF, status);  /* move to read pos. */
-
-    block[2880] = '\0';
-    for (ii = 0; ii < nblock; ii++)
-    {
-        if (ffgbyt(fptr, 2880, block, status) > 0)
-            return(0);   /* read error of some sort */
-
-        length = strlen(block);
-        if (length != 2880)
-        {
-            nullpos = (ii * 2880) + length + 1;
-            return(nullpos);
-        }
-    }
-
-    return(0);
-}
-/*--------------------------------------------------------------------------*/
-int ffmaky(fitsfile *fptr,    /* I - FITS file pointer                    */
-          int nrec,           /* I - one-based keyword number to move to  */
-          int *status)        /* IO - error status                        */
-{
-/*
-  move pointer to the specified absolute keyword position.  E.g. this keyword 
-  will then be read by the next call to ffgnky.
-*/
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] + ( (nrec - 1) * 80);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmrky(fitsfile *fptr,    /* I - FITS file pointer                   */
-          int nmove,          /* I - relative number of keywords to move */
-          int *status)        /* IO - error status                       */
-{
-/*
-  move pointer to the specified keyword position relative to the current
-  position.  E.g. this keyword  will then be read by the next call to ffgnky.
-*/
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    (fptr->Fptr)->nextkey += (nmove * 80);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgnky(fitsfile *fptr,  /* I - FITS file pointer     */
-           char *card,      /* O - card string           */
-           int *status)     /* IO - error status         */
-/*
-  read the next keyword from the header - used internally by cfitsio
-*/
-{
-    int jj, nrec;
-    LONGLONG bytepos, endhead;
-    char message[FLEN_ERRMSG];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    card[0] = '\0';  /* make sure card is terminated, even affer read error */
-
-/*
-  Check that nextkey points to a legal keyword position.  Note that headend
-  is the current end of the header, i.e., the position where a new keyword
-  would be appended, however, if there are more than 1 FITS block worth of
-  blank keywords at the end of the header (36 keywords per 2880 byte block)
-  then the actual physical END card must be located at a starting position
-  which is just 2880 bytes prior to the start of the data unit.
-*/
-
-    bytepos = (fptr->Fptr)->nextkey;
-    endhead = maxvalue( ((fptr->Fptr)->headend), ((fptr->Fptr)->datastart - 2880) );
-
-    /* nextkey must be < endhead and > than  headstart */
-    if (bytepos > endhead ||  
-        bytepos < (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) 
-    {
-        nrec= (int) ((bytepos - (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) / 80 + 1);
-        sprintf(message, "Cannot get keyword number %d.  It does not exist.",
-                nrec);
-        ffpmsg(message);
-        return(*status = KEY_OUT_BOUNDS);
-    }
-      
-    ffmbyt(fptr, bytepos, REPORT_EOF, status);  /* move to read pos. */
-
-    card[80] = '\0';  /* make sure card is terminate, even if ffgbyt fails */
-
-    if (ffgbyt(fptr, 80, card, status) <= 0) 
-    {
-        (fptr->Fptr)->nextkey += 80;   /* increment pointer to next keyword */
-
-        /* strip off trailing blanks with terminated string */
-        jj = 79;
-        while (jj >= 0 && card[jj] == ' ')
-               jj--;
-
-        card[jj + 1] = '\0';
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgnxk( fitsfile *fptr,     /* I - FITS file pointer              */
-            char **inclist,     /* I - list of included keyword names */
-            int ninc,           /* I - number of names in inclist     */
-            char **exclist,     /* I - list of excluded keyword names */
-            int nexc,           /* I - number of names in exclist     */
-            char *card,         /* O - first matching keyword         */
-            int  *status)       /* IO - error status                  */
-/*
-    Return the next keyword that matches one of the names in inclist
-    but does not match any of the names in exclist.  The search
-    goes from the current position to the end of the header, only.
-    Wild card characters may be used in the name lists ('*', '?' and '#').
-*/
-{
-    int casesn, match, exact, namelen;
-    long ii, jj;
-    char keybuf[FLEN_CARD], keyname[FLEN_KEYWORD];
-
-    card[0] = '\0';
-    if (*status > 0)
-        return(*status);
-
-    casesn = FALSE;
-
-    /* get next card, and return with an error if hit end of header */
-    while( ffgcrd(fptr, "*", keybuf, status) <= 0)
-    {
-        ffgknm(keybuf, keyname, &namelen, status); /* get the keyword name */
-        
-        /* does keyword match any names in the include list? */
-        for (ii = 0; ii < ninc; ii++)
-        {
-            ffcmps(inclist[ii], keyname, casesn, &match, &exact);
-            if (match)
-            {
-                /* does keyword match any names in the exclusion list? */
-                jj = -1;
-                while ( ++jj < nexc )
-                {
-                    ffcmps(exclist[jj], keyname, casesn, &match, &exact);
-                    if (match)
-                        break;
-                }
-
-                if (jj >= nexc)
-                {
-                    /* not in exclusion list, so return this keyword */
-                    strcat(card, keybuf);
-                    return(*status);
-                }
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgky( fitsfile *fptr,     /* I - FITS file pointer        */
-           int  datatype,      /* I - datatype of the value    */
-           const char *keyname,      /* I - name of keyword to read  */
-           void *value,        /* O - keyword value            */
-           char *comm,         /* O - keyword comment          */
-           int  *status)       /* IO - error status            */
-/*
-  Read (get) the keyword value and comment from the FITS header.
-  Reads a keyword value with the datatype specified by the 2nd argument.
-*/
-{
-    long longval;
-    double doubleval;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (datatype == TSTRING)
-    {
-        ffgkys(fptr, keyname, (char *) value, comm, status);
-    }
-    else if (datatype == TBYTE)
-    {
-        if (ffgkyj(fptr, keyname, &longval, comm, status) <= 0)
-        {
-            if (longval > UCHAR_MAX || longval < 0)
-                *status = NUM_OVERFLOW;
-            else
-                *(unsigned char *) value = (unsigned char) longval;
-        }
-    }
-    else if (datatype == TSBYTE)
-    {
-        if (ffgkyj(fptr, keyname, &longval, comm, status) <= 0)
-        {
-            if (longval > 127 || longval < -128)
-                *status = NUM_OVERFLOW;
-            else
-                *(signed char *) value = (signed char) longval;
-        }
-    }
-    else if (datatype == TUSHORT)
-    {
-        if (ffgkyj(fptr, keyname, &longval, comm, status) <= 0)
-        {
-            if (longval > (long) USHRT_MAX || longval < 0)
-                *status = NUM_OVERFLOW;
-            else
-                *(unsigned short *) value = (unsigned short) longval;
-        }
-    }
-    else if (datatype == TSHORT)
-    {
-        if (ffgkyj(fptr, keyname, &longval, comm, status) <= 0)
-        {
-            if (longval > SHRT_MAX || longval < SHRT_MIN)
-                *status = NUM_OVERFLOW;
-            else
-                *(short *) value = (short) longval;
-        }
-    }
-    else if (datatype == TUINT)
-    {
-        if (ffgkyj(fptr, keyname, &longval, comm, status) <= 0)
-        {
-            if (longval > (long) UINT_MAX || longval < 0)
-                *status = NUM_OVERFLOW;
-            else
-                *(unsigned int *) value = longval;
-        }
-    }
-    else if (datatype == TINT)
-    {
-        if (ffgkyj(fptr, keyname, &longval, comm, status) <= 0)
-        {
-            if (longval > INT_MAX || longval < INT_MIN)
-                *status = NUM_OVERFLOW;
-            else
-                *(int *) value = longval;
-        }
-    }
-    else if (datatype == TLOGICAL)
-    {
-        ffgkyl(fptr, keyname, (int *) value, comm, status);
-    }
-    else if (datatype == TULONG)
-    {
-        if (ffgkyd(fptr, keyname, &doubleval, comm, status) <= 0)
-        {
-            if (doubleval > (double) ULONG_MAX || doubleval < 0)
-                *status = NUM_OVERFLOW;
-            else
-                 *(unsigned long *) value = (unsigned long) doubleval;
-        }
-    }
-    else if (datatype == TLONG)
-    {
-        ffgkyj(fptr, keyname, (long *) value, comm, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-        ffgkyjj(fptr, keyname, (LONGLONG *) value, comm, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-        ffgkye(fptr, keyname, (float *) value, comm, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-        ffgkyd(fptr, keyname, (double *) value, comm, status);
-    }
-    else if (datatype == TCOMPLEX)
-    {
-        ffgkyc(fptr, keyname, (float *) value, comm, status);
-    }
-    else if (datatype == TDBLCOMPLEX)
-    {
-        ffgkym(fptr, keyname, (double *) value, comm, status);
-    }
-    else
-        *status = BAD_DATATYPE;
-
-    return(*status);
-} 
-/*--------------------------------------------------------------------------*/
-int ffgkey( fitsfile *fptr,     /* I - FITS file pointer        */
-            const char *keyname,      /* I - name of keyword to read  */
-            char *keyval,       /* O - keyword value            */
-            char *comm,         /* O - keyword comment          */
-            int  *status)       /* IO - error status            */
-/*
-  Read (get) the named keyword, returning the keyword value and comment.
-  The value is just the literal string of characters in the value field
-  of the keyword.  In the case of a string valued keyword, the returned
-  value includes the leading and closing quote characters.  The value may be
-  up to 70 characters long, and the comment may be up to 72 characters long.
-  If the keyword has no value (no equal sign in column 9) then a null value
-  is returned.
-*/
-{
-    char card[FLEN_CARD];
-
-    keyval[0] = '\0';
-    if (comm)
-       comm[0] = '\0';
-
-    if (*status > 0)
-        return(*status);
-
-    if (ffgcrd(fptr, keyname, card, status) > 0)    /* get the 80-byte card */
-        return(*status);
-
-    ffpsvc(card, keyval, comm, status);      /* parse the value and comment */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgrec( fitsfile *fptr,     /* I - FITS file pointer          */
-            int nrec,           /* I - number of keyword to read  */
-            char *card,         /* O - keyword card               */
-            int  *status)       /* IO - error status              */
-/*
-  Read (get) the nrec-th keyword, returning the entire keyword card up to
-  80 characters long.  The first keyword in the header has nrec = 1, not 0.
-  The returned card value is null terminated with any trailing blank 
-  characters removed.  If nrec = 0, then this routine simply moves the
-  current header pointer to the top of the header.
-*/
-{
-    if (*status > 0)
-        return(*status);
-
-    if (nrec == 0)
-    {
-        ffmaky(fptr, 1, status);  /* simply move to beginning of header */
-        if (card)
-            card[0] = '\0';           /* and return null card */
-    }
-    else if (nrec > 0)
-    {
-        ffmaky(fptr, nrec, status);
-        ffgnky(fptr, card, status);
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgcrd( fitsfile *fptr,     /* I - FITS file pointer        */
-            const char *name,         /* I - name of keyword to read  */
-            char *card,         /* O - keyword card             */
-            int  *status)       /* IO - error status            */
-/*
-  Read (get) the named keyword, returning the entire keyword card up to
-  80 characters long.  
-  The returned card value is null terminated with any trailing blank 
-  characters removed.
-
-  If the input name contains wild cards ('?' matches any single char
-  and '*' matches any sequence of chars, # matches any string of decimal
-  digits) then the search ends once the end of header is reached and does 
-  not automatically resume from the top of the header.
-*/
-{
-    int nkeys, nextkey, ntodo, namelen, namelen_limit, namelenminus1, cardlen;
-    int ii = 0, jj, kk, wild, match, exact, hier = 0;
-    char keyname[FLEN_KEYWORD], cardname[FLEN_KEYWORD];
-    char *ptr1, *ptr2, *gotstar;
-
-    if (*status > 0)
-        return(*status);
-
-    *keyname = '\0';
-    
-    while (name[ii] == ' ')  /* skip leading blanks in name */
-        ii++;
-
-    strncat(keyname, &name[ii], FLEN_KEYWORD - 1);
-
-    namelen = strlen(keyname);
-
-    while (namelen > 0 && keyname[namelen - 1] == ' ')
-         namelen--;            /* ignore trailing blanks in name */
-
-    keyname[namelen] = '\0';  /* terminate the name */
-
-    for (ii=0; ii < namelen; ii++)       
-        keyname[ii] = toupper(keyname[ii]);    /*  make upper case  */
-
-    if (FSTRNCMP("HIERARCH", keyname, 8) == 0)
-    {
-        if (namelen == 8)
-        {
-            /* special case: just looking for any HIERARCH keyword */
-            hier = 1;
-        }
-        else
-        {
-            /* ignore the leading HIERARCH and look for the 'real' name */
-            /* starting with first non-blank character following HIERARCH */
-            ptr1 = keyname;
-            ptr2 = &keyname[8];
-
-            while(*ptr2 == ' ')
-                ptr2++;
-
-            namelen = 0;
-            while(*ptr2)
-            {
-                *ptr1 = *ptr2;
-                 ptr1++;
-                 ptr2++;
-                 namelen++;
-            }
-            *ptr1 = '\0';
-        }
-    }
-
-    /* does input name contain wild card chars?  ('?',  '*', or '#') */
-    /* wild cards are currently not supported with HIERARCH keywords */
-
-    namelen_limit = namelen;
-    gotstar = 0;
-    if (namelen < 9 && 
-       (strchr(keyname,'?') || (gotstar = strchr(keyname,'*')) || 
-        strchr(keyname,'#')) )
-    {
-        wild = 1;
-
-        /* if we found a '*' wild card in the name, there might be */
-        /* more than one.  Support up to 2 '*' in the template. */
-        /* Thus we need to compare keywords whose names have at least */
-        /* namelen - 2 characters.                                   */
-        if (gotstar)
-           namelen_limit -= 2;           
-    }
-    else
-        wild = 0;
-
-    ffghps(fptr, &nkeys, &nextkey, status); /* get no. keywords and position */
-
-    namelenminus1 = maxvalue(namelen - 1, 1);
-    ntodo = nkeys - nextkey + 1;  /* first, read from next keyword to end */
-    for (jj=0; jj < 2; jj++)
-    {
-      for (kk = 0; kk < ntodo; kk++)
-      {
-        ffgnky(fptr, card, status);     /* get next keyword */
-
-        if (hier)
-        {
-           if (FSTRNCMP("HIERARCH", card, 8) == 0)
-                return(*status);  /* found a HIERARCH keyword */
-        }
-        else
-        {
-          ffgknm(card, cardname, &cardlen, status); /* get the keyword name */
-
-          if (cardlen >= namelen_limit)  /* can't match if card < name */
-          { 
-            /* if there are no wild cards, lengths must be the same */
-            if (!( !wild && cardlen != namelen) )
-            {
-              for (ii=0; ii < cardlen; ii++)
-              {    
-                /* make sure keyword is in uppercase */
-                if (cardname[ii] > 96)
-                {
-                  /* This assumes the ASCII character set in which */
-                  /* upper case characters start at ASCII(97)  */
-                  /* Timing tests showed that this is 20% faster */
-                  /* than calling the isupper function.          */
-
-                  cardname[ii] = toupper(cardname[ii]);  /* make upper case */
-                }
-              }
-
-              if (wild)
-              {
-                ffcmps(keyname, cardname, 1, &match, &exact);
-                if (match)
-                    return(*status); /* found a matching keyword */
-              }
-              else if (keyname[namelenminus1] == cardname[namelenminus1])
-              {
-                /* test the last character of the keyword name first, on */
-                /* the theory that it is less likely to match then the first */
-                /* character since many keywords begin with 'T', for example */
-
-                if (FSTRNCMP(keyname, cardname, namelenminus1) == 0)
-                {
-                  return(*status);   /* found the matching keyword */
-                }
-              }
-	      else if (namelen == 0 && cardlen == 0)
-	      {
-	         /* matched a blank keyword */
-		 return(*status);
-	      }
-            }
-          }
-        }
-      }
-
-      if (wild || jj == 1)
-            break;  /* stop at end of header if template contains wildcards */
-
-      ffmaky(fptr, 1, status);  /* reset pointer to beginning of header */
-      ntodo = nextkey - 1;      /* number of keyword to read */ 
-    }
-
-    return(*status = KEY_NO_EXIST);  /* couldn't find the keyword */
-}
-/*--------------------------------------------------------------------------*/
-int ffgstr( fitsfile *fptr,     /* I - FITS file pointer        */
-            const char *string, /* I - string to match  */
-            char *card,         /* O - keyword card             */
-            int  *status)       /* IO - error status            */
-/*
-  Read (get) the next keyword record that contains the input character string,
-  returning the entire keyword card up to 80 characters long.
-  The returned card value is null terminated with any trailing blank 
-  characters removed.
-*/
-{
-    int nkeys, nextkey, ntodo, stringlen;
-    int jj, kk;
-
-    if (*status > 0)
-        return(*status);
-
-    stringlen = strlen(string);
-    if (stringlen > 80) {
-        return(*status = KEY_NO_EXIST);  /* matching string is too long to exist */
-    }
-
-    ffghps(fptr, &nkeys, &nextkey, status); /* get no. keywords and position */
-    ntodo = nkeys - nextkey + 1;  /* first, read from next keyword to end */
-
-    for (jj=0; jj < 2; jj++)
-    {
-      for (kk = 0; kk < ntodo; kk++)
-      {
-        ffgnky(fptr, card, status);     /* get next keyword */
-        if (strstr(card, string) != 0) {
-            return(*status);   /* found the matching string */
-        }
-      }
-
-      ffmaky(fptr, 1, status);  /* reset pointer to beginning of header */
-      ntodo = nextkey - 1;      /* number of keyword to read */ 
-    }
-
-    return(*status = KEY_NO_EXIST);  /* couldn't find the keyword */
-}
-/*--------------------------------------------------------------------------*/
-int ffgknm( char *card,         /* I - keyword card                   */
-            char *name,         /* O - name of the keyword            */
-            int *length,        /* O - length of the keyword name     */
-            int  *status)       /* IO - error status                  */
-
-/*
-  Return the name of the keyword, and the name length.  This supports the
-  ESO HIERARCH convention where keyword names may be > 8 characters long.
-*/
-{
-    char *ptr1, *ptr2;
-    int ii, namelength;
-
-    namelength = FLEN_KEYWORD - 1;
-    *name = '\0';
-    *length = 0;
-
-    /* support for ESO HIERARCH keywords; find the '=' */
-    if (FSTRNCMP(card, "HIERARCH ", 9) == 0)
-    {
-        ptr2 = strchr(card, '=');
-
-        if (!ptr2)   /* no value indicator ??? */
-        {
-            /* this probably indicates an error, so just return FITS name */
-            strcat(name, "HIERARCH");
-            *length = 8;
-            return(*status);
-        }
-
-        /* find the start and end of the HIERARCH name */
-        ptr1 = &card[9];
-        while (*ptr1 == ' ')   /* skip spaces */
-            ptr1++;
-
-        strncat(name, ptr1, ptr2 - ptr1);
-        ii = ptr2 - ptr1;
-
-        while (ii > 0 && name[ii - 1] == ' ')  /* remove trailing spaces */
-            ii--;
-
-        name[ii] = '\0';
-        *length = ii;
-    }
-    else
-    {
-        for (ii = 0; ii < namelength; ii++)
-        {
-           /* look for string terminator, or a blank */
-           if (*(card+ii) != ' ' && *(card+ii) != '=' && *(card+ii) !='\0')
-           {
-               *(name+ii) = *(card+ii);
-           }
-           else
-           {
-               name[ii] = '\0';
-               *length = ii;
-               return(*status);
-           }
-        }
-
-        /* if we got here, keyword is namelength characters long */
-        name[namelength] = '\0';
-        *length = namelength;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgunt( fitsfile *fptr,     /* I - FITS file pointer         */
-            const char *keyname,      /* I - name of keyword to read   */
-            char *unit,         /* O - keyword units             */
-            int  *status)       /* IO - error status             */
-/*
-    Read (get) the units string from the comment field of the existing
-    keyword. This routine uses a local FITS convention (not defined in the
-    official FITS standard) in which the units are enclosed in 
-    square brackets following the '/' comment field delimiter, e.g.:
-
-    KEYWORD =                   12 / [kpc] comment string goes here
-*/
-{
-    char valstring[FLEN_VALUE];
-    char comm[FLEN_COMMENT];
-    char *loc;
-
-    if (*status > 0)
-        return(*status);
-
-    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
-
-    if (comm[0] == '[')
-    {
-        loc = strchr(comm, ']');   /*  find the closing bracket */
-        if (loc)
-            *loc = '\0';           /*  terminate the string */
-
-        strcpy(unit, &comm[1]);    /*  copy the string */
-     }
-     else
-        unit[0] = '\0';
- 
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkys( fitsfile *fptr,     /* I - FITS file pointer         */
-            const char *keyname,      /* I - name of keyword to read   */
-            char *value,        /* O - keyword value             */
-            char *comm,         /* O - keyword comment           */
-            int  *status)       /* IO - error status             */
-/*
-  Get KeYword with a String value:
-  Read (get) a simple string valued keyword.  The returned value may be up to 
-  68 chars long ( + 1 null terminator char).  The routine does not support the
-  HEASARC convention for continuing long string values over multiple keywords.
-  The ffgkls routine may be used to read long continued strings. The returned
-  comment string may be up to 69 characters long (including null terminator).
-*/
-{
-    char valstring[FLEN_VALUE];
-
-    if (*status > 0)
-        return(*status);
-
-    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
-    value[0] = '\0';
-    ffc2s(valstring, value, status);   /* remove quotes from string */
- 
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgksl( fitsfile *fptr,     /* I - FITS file pointer             */
-           const char *keyname, /* I - name of keyword to read       */
-           int *length,         /* O - length of the string value    */
-           int  *status)        /* IO - error status                 */
-/*
-  Get the length of the keyword value string.
-  This routine explicitly supports the CONTINUE convention for long string values.
-*/
-{
-    char valstring[FLEN_VALUE], value[FLEN_VALUE];
-    int position, contin, len;
-    
-    if (*status > 0)
-        return(*status);
-
-    ffgkey(fptr, keyname, valstring, NULL, status);  /* read the keyword */
-
-    if (*status > 0)
-        return(*status);
-
-    ffghps(fptr, NULL,  &position, status); /* save the current header position */
-    
-    if (!valstring[0])  { /* null value string? */
-        *length = 0;
-    } else {
-      ffc2s(valstring, value, status);  /* in case string contains "/" char  */
-      *length = strlen(value);
-
-      /* If last character is a & then value may be continued on next keyword */
-      contin = 1;
-      while (contin)  
-      {
-        len = strlen(value);
-
-        if (len && *(value+len-1) == '&')  /*  is last char an anpersand?  */
-        {
-            ffgcnt(fptr, value, NULL, status);
-            if (*value)    /* a null valstring indicates no continuation */
-            {
-               *length += strlen(value) - 1;
-            }
-            else
-	    {
-                contin = 0;
-            }
-        }
-        else
-	{
-            contin = 0;
-	}
-      }
-    }
-
-    ffmaky(fptr, position - 1, status); /* reset header pointer to the keyword */
-                                        /* since in many cases the program will read */
-					/* the string value after getting the length */
-    
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkls( fitsfile *fptr,     /* I - FITS file pointer             */
-           const char *keyname, /* I - name of keyword to read       */
-           char **value,        /* O - pointer to keyword value      */
-           char *comm,          /* O - keyword comment (may be NULL) */
-           int  *status)        /* IO - error status                 */
-/*
-  This is the original routine for reading long string keywords that use
-  the CONTINUE keyword convention.  In 2016 a new routine called
-  ffgsky / fits_read_string_key was added, which may provide a more 
-  convenient user interface  for most applications.
-
-  Get Keyword with possible Long String value:
-  Read (get) the named keyword, returning the value and comment.
-  The returned value string may be arbitrarily long (by using the HEASARC
-  convention for continuing long string values over multiple keywords) so
-  this routine allocates the required memory for the returned string value.
-  It is up to the calling routine to free the memory once it is finished
-  with the value string.  The returned comment string may be up to 69
-  characters long.
-*/
-{
-    char valstring[FLEN_VALUE], nextcomm[FLEN_COMMENT];
-    int contin, commspace = 0;
-    size_t len;
-
-    if (*status > 0)
-        return(*status);
-
-    *value = NULL;  /* initialize a null pointer in case of error */
-
-    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
-
-    if (*status > 0)
-        return(*status);
-
-    if (comm)
-    {
-        /* remaining space in comment string */
-        commspace = FLEN_COMMENT - strlen(comm) - 2;
-    }
-    
-    if (!valstring[0])   /* null value string? */
-    {
-      *value = (char *) malloc(1);  /* allocate and return a null string */
-      **value = '\0';
-    }
-    else
-    {
-      /* allocate space,  plus 1 for null */
-      *value = (char *) malloc(strlen(valstring) + 1);
-
-      ffc2s(valstring, *value, status);   /* convert string to value */
-      len = strlen(*value);
-
-      /* If last character is a & then value may be continued on next keyword */
-      contin = 1;
-      while (contin)  
-      {
-        if (len && *(*value+len-1) == '&')  /*  is last char an anpersand?  */
-        {
-            ffgcnt(fptr, valstring, nextcomm, status);
-            if (*valstring)    /* a null valstring indicates no continuation */
-            {
-               *(*value+len-1) = '\0';         /* erase the trailing & char */
-               len += strlen(valstring) - 1;
-               *value = (char *) realloc(*value, len + 1); /* increase size */
-               strcat(*value, valstring);     /* append the continued chars */
-            }
-            else
-	    {
-                contin = 0;
-            }
-
-            /* concantenate comment strings (if any) */
-	    if ((commspace > 0) && (*nextcomm != 0)) 
-	    {
-                strncat(comm, " ", 1);
-		strncat(comm, nextcomm, commspace);
-                commspace = FLEN_COMMENT - strlen(comm) - 2;
-            }
-        }
-        else
-	{
-            contin = 0;
-	}
-      }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsky( fitsfile *fptr,     /* I - FITS file pointer             */
-           const char *keyname, /* I - name of keyword to read       */
-           int firstchar,       /* I - first character of string to return */
-           int maxchar,         /* I - maximum length of string to return */
-	                        /*    (string will be null terminated)  */      
-           char *value,         /* O - pointer to keyword value      */
-           int *valuelen,       /* O - total length of the keyword value string */
-                                /*     The returned 'value' string may only */
-				/*     contain a piece of the total string, depending */
-				/*     on the value of firstchar and maxchar */
-           char *comm,          /* O - keyword comment (may be NULL) */
-           int  *status)        /* IO - error status                 */
-/*
-  Read and return the value of the specified string-valued keyword.
-  
-  This new routine was added in 2016 to provide a more convenient user
-  interface than the older ffgkls routine.
-
-  Read a string keyword, returning up to 'naxchars' characters of the value
-  starting with the 'firstchar' character.
-  The input 'value' string must be allocated at least 1 char bigger to
-  allow for the terminating null character.
-  
-  This routine may be used to read continued string keywords that use 
-  the CONTINUE keyword convention, as well as normal string keywords
-  that are contained within a single header record.
-  
-  This routine differs from the ffkls routine in that it does not
-  internally allocate memory for the returned value string, and consequently
-  the calling routine does not need to call fffree to free the memory.
-*/
-{
-    char valstring[FLEN_VALUE], nextcomm[FLEN_COMMENT];
-    char *tempstring;
-    int contin, commspace = 0;
-    size_t len;
-
-    if (*status > 0)
-        return(*status);
-
-    tempstring = NULL;  /* initialize in case of error */
-    *value = '\0';
-    if (valuelen) *valuelen = 0;
-    
-    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
-
-    if (*status > 0)
-        return(*status);
-
-    if (comm)
-    {
-        /* remaining space in comment string */
-        commspace = FLEN_COMMENT - strlen(comm) - 2;
-    }
-    
-    if (!valstring[0])   /* null value string? */
-    {
-      tempstring = (char *) malloc(1);  /* allocate and return a null string */
-      *tempstring = '\0';
-    }
-    else
-    {
-      /* allocate space,  plus 1 for null */
-      tempstring = (char *) malloc(strlen(valstring) + 1);
-
-      ffc2s(valstring, tempstring, status);   /* convert string to value */
-      len = strlen(tempstring);
-
-      /* If last character is a & then value may be continued on next keyword */
-      contin = 1;
-      while (contin && *status <= 0)  
-      {
-        if (len && *(tempstring+len-1) == '&')  /*  is last char an anpersand?  */
-        {
-            ffgcnt(fptr, valstring, nextcomm, status);
-            if (*valstring)    /* a null valstring indicates no continuation */
-            {
-               *(tempstring+len-1) = '\0';         /* erase the trailing & char */
-               len += strlen(valstring) - 1;
-               tempstring = (char *) realloc(tempstring, len + 1); /* increase size */
-               strcat(tempstring, valstring);     /* append the continued chars */
-            }
-            else
-	    {
-                contin = 0;
-            }
-
-            /* concantenate comment strings (if any) */
-	    if ((commspace > 0) && (*nextcomm != 0)) 
-	    {
-                strncat(comm, " ", 1);
-		strncat(comm, nextcomm, commspace);
-                commspace = FLEN_COMMENT - strlen(comm) - 2;
-            }
-        }
-        else
-	{
-            contin = 0;
-	}
-      }
-    }
-    
-    if (tempstring) 
-    {
-        len = strlen(tempstring);
-	if (firstchar <= len)
-            strncat(value, tempstring + (firstchar - 1), maxchar);
-        free(tempstring);
-	if (valuelen) *valuelen = len;  /* total length of the keyword value */
-    }
-    
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fffree( void *value,       /* I - pointer to keyword value  */
-            int  *status)      /* IO - error status             */
-/*
-  Free the memory that was previously allocated by CFITSIO, 
-  such as by ffgkls or fits_hdr2str
-*/
-{
-    if (*status > 0)
-        return(*status);
-
-    if (value)
-        free(value);
-
-    return(*status);
-}
- /*--------------------------------------------------------------------------*/
-int ffgcnt( fitsfile *fptr,     /* I - FITS file pointer         */
-            char *value,        /* O - continued string value    */
-            char *comm,         /* O - continued comment string  */
-            int  *status)       /* IO - error status             */
-/*
-  Attempt to read the next keyword, returning the string value
-  if it is a continuation of the previous string keyword value.
-  This uses the HEASARC convention for continuing long string values
-  over multiple keywords.  Each continued string is terminated with a
-  backslash character, and the continuation follows on the next keyword
-  which must have the name CONTINUE without an equal sign in column 9
-  of the card.  If the next card is not a continuation, then the returned
-  value string will be null.
-*/
-{
-    int tstatus;
-    char card[FLEN_CARD], strval[FLEN_VALUE];
-
-    if (*status > 0)
-        return(*status);
-
-    tstatus = 0;
-    value[0] = '\0';
-
-    if (ffgnky(fptr, card, &tstatus) > 0)  /*  read next keyword  */
-        return(*status);                   /*  hit end of header  */
-
-    if (strncmp(card, "CONTINUE  ", 10) == 0)  /* a continuation card? */
-    {
-        strncpy(card, "D2345678=  ", 10); /* overwrite a dummy keyword name */
-        ffpsvc(card, strval, comm, &tstatus);  /*  get the string value & comment */
-        ffc2s(strval, value, &tstatus);    /* remove the surrounding quotes */
-
-        if (tstatus)       /*  return null if error status was returned  */
-           value[0] = '\0';
-    }
-    else
-        ffmrky(fptr, -1, status);  /* reset the keyword pointer */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkyl( fitsfile *fptr,     /* I - FITS file pointer         */
-            const char *keyname,      /* I - name of keyword to read   */
-            int  *value,        /* O - keyword value             */
-            char *comm,         /* O - keyword comment           */
-            int  *status)       /* IO - error status             */
-/*
-  Read (get) the named keyword, returning the value and comment.
-  The returned value = 1 if the keyword is true, else = 0 if false.
-  The comment may be up to 69 characters long.
-*/
-{
-    char valstring[FLEN_VALUE];
-
-    if (*status > 0)
-        return(*status);
-
-    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
-    ffc2l(valstring, value, status);   /* convert string to value */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkyj( fitsfile *fptr,     /* I - FITS file pointer         */
-            const char *keyname,      /* I - name of keyword to read   */
-            long *value,        /* O - keyword value             */
-            char *comm,         /* O - keyword comment           */
-            int  *status)       /* IO - error status             */
-/*
-  Read (get) the named keyword, returning the value and comment.
-  The value will be implicitly converted to a (long) integer if it not
-  already of this datatype.  The comment may be up to 69 characters long.
-*/
-{
-    char valstring[FLEN_VALUE];
-
-    if (*status > 0)
-        return(*status);
-
-    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
-    ffc2i(valstring, value, status);   /* convert string to value */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkyjj( fitsfile *fptr,     /* I - FITS file pointer         */
-            const char *keyname,      /* I - name of keyword to read   */
-            LONGLONG *value,    /* O - keyword value             */
-            char *comm,         /* O - keyword comment           */
-            int  *status)       /* IO - error status             */
-/*
-  Read (get) the named keyword, returning the value and comment.
-  The value will be implicitly converted to a (long) integer if it not
-  already of this datatype.  The comment may be up to 69 characters long.
-*/
-{
-    char valstring[FLEN_VALUE];
-
-    if (*status > 0)
-        return(*status);
-
-    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
-    ffc2j(valstring, value, status);   /* convert string to value */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkye( fitsfile *fptr,     /* I - FITS file pointer         */
-            const char  *keyname,     /* I - name of keyword to read   */
-            float *value,       /* O - keyword value             */
-            char  *comm,        /* O - keyword comment           */
-            int   *status)      /* IO - error status             */
-/*
-  Read (get) the named keyword, returning the value and comment.
-  The value will be implicitly converted to a float if it not
-  already of this datatype.  The comment may be up to 69 characters long.
-*/
-{
-    char valstring[FLEN_VALUE];
-
-    if (*status > 0)
-        return(*status);
-
-    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
-    ffc2r(valstring, value, status);   /* convert string to value */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkyd( fitsfile *fptr,      /* I - FITS file pointer         */
-            const char   *keyname,     /* I - name of keyword to read   */
-            double *value,       /* O - keyword value             */
-            char   *comm,        /* O - keyword comment           */
-            int    *status)      /* IO - error status             */
-/*
-  Read (get) the named keyword, returning the value and comment.
-  The value will be implicitly converted to a double if it not
-  already of this datatype.  The comment may be up to 69 characters long.
-*/
-{
-    char valstring[FLEN_VALUE];
-
-    if (*status > 0)
-        return(*status);
-
-    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
-    ffc2d(valstring, value, status);   /* convert string to value */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkyc( fitsfile *fptr,     /* I - FITS file pointer         */
-            const char  *keyname,     /* I - name of keyword to read   */
-            float *value,       /* O - keyword value (real,imag) */
-            char  *comm,        /* O - keyword comment           */
-            int   *status)      /* IO - error status             */
-/*
-  Read (get) the named keyword, returning the value and comment.
-  The keyword must have a complex value. No implicit data conversion
-  will be performed.
-*/
-{
-    char valstring[FLEN_VALUE], message[81];
-    int len;
-
-    if (*status > 0)
-        return(*status);
-
-    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
-
-    if (valstring[0] != '(' )   /* test that this is a complex keyword */
-    {
-      sprintf(message, "keyword %s does not have a complex value (ffgkyc):",
-              keyname);
-      ffpmsg(message);
-      ffpmsg(valstring);
-      return(*status = BAD_C2F);
-    }
-
-    valstring[0] = ' ';            /* delete the opening parenthesis */
-    len = strcspn(valstring, ")" );  
-    valstring[len] = '\0';         /* delete the closing parenthesis */
-
-    len = strcspn(valstring, ",");
-    valstring[len] = '\0';
-
-    ffc2r(valstring, &value[0], status);       /* convert the real part */
-    ffc2r(&valstring[len + 1], &value[1], status); /* convert imag. part */
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkym( fitsfile *fptr,     /* I - FITS file pointer         */
-            const char  *keyname,     /* I - name of keyword to read   */
-            double *value,      /* O - keyword value (real,imag) */
-            char  *comm,        /* O - keyword comment           */
-            int   *status)      /* IO - error status             */
-/*
-  Read (get) the named keyword, returning the value and comment.
-  The keyword must have a complex value. No implicit data conversion
-  will be performed.
-*/
-{
-    char valstring[FLEN_VALUE], message[81];
-    int len;
-
-    if (*status > 0)
-        return(*status);
-
-    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
-
-    if (valstring[0] != '(' )   /* test that this is a complex keyword */
-    {
-      sprintf(message, "keyword %s does not have a complex value (ffgkym):",
-              keyname);
-      ffpmsg(message);
-      ffpmsg(valstring);
-      return(*status = BAD_C2D);
-    }
-
-    valstring[0] = ' ';            /* delete the opening parenthesis */
-    len = strcspn(valstring, ")" );  
-    valstring[len] = '\0';         /* delete the closing parenthesis */
-
-    len = strcspn(valstring, ",");
-    valstring[len] = '\0';
-
-    ffc2d(valstring, &value[0], status);        /* convert the real part */
-    ffc2d(&valstring[len + 1], &value[1], status);  /* convert the imag. part */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkyt( fitsfile *fptr,      /* I - FITS file pointer                 */
-            const char   *keyname,     /* I - name of keyword to read           */
-            long   *ivalue,      /* O - integer part of keyword value     */
-            double *fraction,    /* O - fractional part of keyword value  */
-            char   *comm,        /* O - keyword comment                   */
-            int    *status)      /* IO - error status                     */
-/*
-  Read (get) the named keyword, returning the value and comment.
-  The integer and fractional parts of the value are returned in separate
-  variables, to allow more numerical precision to be passed.  This
-  effectively passes a 'triple' precision value, with a 4-byte integer
-  and an 8-byte fraction.  The comment may be up to 69 characters long.
-*/
-{
-    char valstring[FLEN_VALUE];
-    char *loc;
-
-    if (*status > 0)
-        return(*status);
-
-    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
-
-    /*  read the entire value string as a double, to get the integer part */
-    ffc2d(valstring, fraction, status);
-
-    *ivalue = (long) *fraction;
-
-    *fraction = *fraction - *ivalue;
-
-    /* see if we need to read the fractional part again with more precision */
-    /* look for decimal point, without an exponential E or D character */
-
-    loc = strchr(valstring, '.');
-    if (loc)
-    {
-        if (!strchr(valstring, 'E') && !strchr(valstring, 'D'))
-            ffc2d(loc, fraction, status);
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkyn( fitsfile *fptr,      /* I - FITS file pointer             */
-            int    nkey,         /* I - number of the keyword to read */
-            char   *keyname,     /* O - name of the keyword           */
-            char   *value,       /* O - keyword value                 */
-            char   *comm,        /* O - keyword comment               */
-            int    *status)      /* IO - error status                 */
-/*
-  Read (get) the nkey-th keyword returning the keyword name, value and comment.
-  The value is just the literal string of characters in the value field
-  of the keyword.  In the case of a string valued keyword, the returned
-  value includes the leading and closing quote characters.  The value may be
-  up to 70 characters long, and the comment may be up to 72 characters long.
-  If the keyword has no value (no equal sign in column 9) then a null value
-  is returned.  If comm = NULL, then do not return the comment string.
-*/
-{
-    char card[FLEN_CARD], sbuff[FLEN_CARD];
-    int namelen;
-
-    keyname[0] = '\0';
-    value[0] = '\0';
-    if (comm)
-        comm[0] = '\0';
-
-    if (*status > 0)
-        return(*status);
-
-    if (ffgrec(fptr, nkey, card, status) > 0 )  /* get the 80-byte card */
-        return(*status);
-
-    ffgknm(card, keyname, &namelen, status); /* get the keyword name */
-
-    if (ffpsvc(card, value, comm, status) > 0)   /* parse value and comment */
-        return(*status);
-
-    if (fftrec(keyname, status) > 0)  /* test keyword name; catches no END */
-    {
-     sprintf(sbuff,"Name of keyword no. %d contains illegal character(s): %s",
-              nkey, keyname);
-     ffpmsg(sbuff);
-
-     if (nkey % 36 == 0)  /* test if at beginning of 36-card FITS record */
-            ffpmsg("  (This may indicate a missing END keyword).");
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkns( fitsfile *fptr,     /* I - FITS file pointer                    */
-            const char *keyname,      /* I - root name of keywords to read        */
-            int  nstart,        /* I - starting index number                */
-            int  nmax,          /* I - maximum number of keywords to return */
-            char *value[],      /* O - array of pointers to keyword values  */
-            int  *nfound,       /* O - number of values that were returned  */
-            int  *status)       /* IO - error status                        */
-/*
-  Read (get) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NMAX -1) inclusive.  
-  This routine does NOT support the HEASARC long string convention.
-*/
-{
-    int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval;
-    long ival;
-    char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD];
-    char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign;
-
-    if (*status > 0)
-        return(*status);
-
-    *nfound = 0;
-    nend = nstart + nmax - 1;
-
-    keyroot[0] = '\0';
-    strncat(keyroot, keyname, FLEN_KEYWORD - 1);
-     
-    lenroot = strlen(keyroot);
-    
-    if (lenroot == 0)     /*  root must be at least 1 char long  */
-        return(*status);
-
-    for (ii=0; ii < lenroot; ii++)           /*  make sure upper case  */
-        keyroot[ii] = toupper(keyroot[ii]);
-
-    ffghps(fptr, &nkeys, &mkeys, status);  /*  get the number of keywords  */
-
-    undefinedval = FALSE;
-    for (ii=3; ii <= nkeys; ii++)  
-    {
-       if (ffgrec(fptr, ii, card, status) > 0)     /*  get next keyword  */
-           return(*status);
-
-       if (strncmp(keyroot, card, lenroot) == 0)  /* see if keyword matches */
-       {
-          keyindex[0] = '\0';
-          equalssign = strchr(card, '=');
-	  if (equalssign == 0) continue;  /* keyword has no value */
-
-          strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
-          tstatus = 0;
-          if (ffc2ii(keyindex, &ival, &tstatus) <= 0)     /*  test suffix  */
-          {
-             if (ival <= nend && ival >= nstart)
-             {
-                ffpsvc(card, svalue, comm, status);  /*  parse the value */
-                ffc2s(svalue, value[ival-nstart], status); /* convert */
-                if (ival - nstart + 1 > *nfound)
-                      *nfound = ival - nstart + 1;  /*  max found */ 
-
-                if (*status == VALUE_UNDEFINED)
-                {
-                   undefinedval = TRUE;
-                   *status = 0;  /* reset status to read remaining values */
-                }
-             }
-          }
-       }
-    }
-    if (undefinedval && (*status <= 0) )
-        *status = VALUE_UNDEFINED;  /* report at least 1 value undefined */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgknl( fitsfile *fptr,     /* I - FITS file pointer                    */
-            const char *keyname,      /* I - root name of keywords to read        */
-            int  nstart,        /* I - starting index number                */
-            int  nmax,          /* I - maximum number of keywords to return */
-            int  *value,        /* O - array of keyword values              */
-            int  *nfound,       /* O - number of values that were returned  */
-            int  *status)       /* IO - error status                        */
-/*
-  Read (get) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NMAX -1) inclusive.  
-  The returned value = 1 if the keyword is true, else = 0 if false.
-*/
-{
-    int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval;
-    long ival;
-    char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD];
-    char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign;
-
-    if (*status > 0)
-        return(*status);
-
-    *nfound = 0;
-    nend = nstart + nmax - 1;
-
-    keyroot[0] = '\0';
-    strncat(keyroot, keyname, FLEN_KEYWORD - 1);
-
-    lenroot = strlen(keyroot);
-    
-    if (lenroot == 0)     /*  root must be at least 1 char long  */
-        return(*status);
- 
-    for (ii=0; ii < lenroot; ii++)           /*  make sure upper case  */
-        keyroot[ii] = toupper(keyroot[ii]);
-
-    ffghps(fptr, &nkeys, &mkeys, status);  /*  get the number of keywords  */
-
-    ffmaky(fptr, 3, status);  /* move to 3rd keyword (skip 1st 2 keywords) */
-
-    undefinedval = FALSE;
-    for (ii=3; ii <= nkeys; ii++)  
-    {
-       if (ffgnky(fptr, card, status) > 0)     /*  get next keyword  */
-           return(*status);
-
-       if (strncmp(keyroot, card, lenroot) == 0)  /* see if keyword matches */
-       {
-          keyindex[0] = '\0';
-          equalssign = strchr(card, '=');
-	  if (equalssign == 0) continue;  /* keyword has no value */
-
-          strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
-
-          tstatus = 0;
-          if (ffc2ii(keyindex, &ival, &tstatus) <= 0)    /*  test suffix  */
-          {
-             if (ival <= nend && ival >= nstart)
-             {
-                ffpsvc(card, svalue, comm, status);   /*  parse the value */
-                ffc2l(svalue, &value[ival-nstart], status); /* convert*/
-                if (ival - nstart + 1 > *nfound)
-                      *nfound = ival - nstart + 1;  /*  max found */ 
-
-                if (*status == VALUE_UNDEFINED)
-                {
-                    undefinedval = TRUE;
-                   *status = 0;  /* reset status to read remaining values */
-                }
-             }
-          }
-       }
-    }
-    if (undefinedval && (*status <= 0) )
-        *status = VALUE_UNDEFINED;  /* report at least 1 value undefined */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgknj( fitsfile *fptr,     /* I - FITS file pointer                    */
-            const char *keyname,      /* I - root name of keywords to read        */
-            int  nstart,        /* I - starting index number                */
-            int  nmax,          /* I - maximum number of keywords to return */
-            long *value,        /* O - array of keyword values              */
-            int  *nfound,       /* O - number of values that were returned  */
-            int  *status)       /* IO - error status                        */
-/*
-  Read (get) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NMAX -1) inclusive.  
-*/
-{
-    int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval;
-    long ival;
-    char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD];
-    char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign;
-
-    if (*status > 0)
-        return(*status);
-
-    *nfound = 0;
-    nend = nstart + nmax - 1;
-
-    keyroot[0] = '\0';
-    strncat(keyroot, keyname, FLEN_KEYWORD - 1);
-
-    lenroot = strlen(keyroot);
-    
-    if (lenroot == 0)     /*  root must be at least 1 char long  */
-        return(*status);
- 
-    for (ii=0; ii < lenroot; ii++)           /*  make sure upper case  */
-        keyroot[ii] = toupper(keyroot[ii]);
-
-    ffghps(fptr, &nkeys, &mkeys, status);  /*  get the number of keywords  */
-
-    ffmaky(fptr, 3, status);  /* move to 3rd keyword (skip 1st 2 keywords) */
-
-    undefinedval = FALSE;
-    for (ii=3; ii <= nkeys; ii++)  
-    {
-       if (ffgnky(fptr, card, status) > 0)     /*  get next keyword  */
-           return(*status);
-
-       if (strncmp(keyroot, card, lenroot) == 0)  /* see if keyword matches */
-       {
-          keyindex[0] = '\0';
-          equalssign = strchr(card, '=');
-	  if (equalssign == 0) continue;  /* keyword has no value */
-
-          strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
-
-          tstatus = 0;
-          if (ffc2ii(keyindex, &ival, &tstatus) <= 0)     /*  test suffix  */
-          {
-             if (ival <= nend && ival >= nstart)
-             {
-                ffpsvc(card, svalue, comm, status);   /*  parse the value */
-                ffc2i(svalue, &value[ival-nstart], status);  /* convert */
-                if (ival - nstart + 1 > *nfound)
-                      *nfound = ival - nstart + 1;  /*  max found */ 
-
-                if (*status == VALUE_UNDEFINED)
-                {
-                    undefinedval = TRUE;
-                   *status = 0;  /* reset status to read remaining values */
-                }
-             }
-          }
-       }
-    }
-    if (undefinedval && (*status <= 0) )
-        *status = VALUE_UNDEFINED;  /* report at least 1 value undefined */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgknjj( fitsfile *fptr,    /* I - FITS file pointer                    */
-            const char *keyname,      /* I - root name of keywords to read        */
-            int  nstart,        /* I - starting index number                */
-            int  nmax,          /* I - maximum number of keywords to return */
-            LONGLONG *value,    /* O - array of keyword values              */
-            int  *nfound,       /* O - number of values that were returned  */
-            int  *status)       /* IO - error status                        */
-/*
-  Read (get) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NMAX -1) inclusive.  
-*/
-{
-    int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval;
-    long ival;
-    char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD];
-    char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign;
-
-    if (*status > 0)
-        return(*status);
-
-    *nfound = 0;
-    nend = nstart + nmax - 1;
-
-    keyroot[0] = '\0';
-    strncat(keyroot, keyname, FLEN_KEYWORD - 1);
-
-    lenroot = strlen(keyroot);
-    
-    if (lenroot == 0)     /*  root must be at least 1 char long  */
-        return(*status);
-
-    for (ii=0; ii < lenroot; ii++)           /*  make sure upper case  */
-        keyroot[ii] = toupper(keyroot[ii]);
-
-    ffghps(fptr, &nkeys, &mkeys, status);  /*  get the number of keywords  */
-
-    ffmaky(fptr, 3, status);  /* move to 3rd keyword (skip 1st 2 keywords) */
-
-    undefinedval = FALSE;
-    for (ii=3; ii <= nkeys; ii++)  
-    {
-       if (ffgnky(fptr, card, status) > 0)     /*  get next keyword  */
-           return(*status);
-
-       if (strncmp(keyroot, card, lenroot) == 0)  /* see if keyword matches */
-       {
-          keyindex[0] = '\0';
-          equalssign = strchr(card, '=');
-	  if (equalssign == 0) continue;  /* keyword has no value */
-
-          strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
-
-          tstatus = 0;
-          if (ffc2ii(keyindex, &ival, &tstatus) <= 0)     /*  test suffix  */
-          {
-             if (ival <= nend && ival >= nstart)
-             {
-                ffpsvc(card, svalue, comm, status);   /*  parse the value */
-                ffc2j(svalue, &value[ival-nstart], status);  /* convert */
-                if (ival - nstart + 1 > *nfound)
-                      *nfound = ival - nstart + 1;  /*  max found */ 
-
-                if (*status == VALUE_UNDEFINED)
-                {
-                    undefinedval = TRUE;
-                   *status = 0;  /* reset status to read remaining values */
-                }
-             }
-          }
-       }
-    }
-    if (undefinedval && (*status <= 0) )
-        *status = VALUE_UNDEFINED;  /* report at least 1 value undefined */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgkne( fitsfile *fptr,     /* I - FITS file pointer                    */
-            const char *keyname,      /* I - root name of keywords to read        */
-            int  nstart,        /* I - starting index number                */
-            int  nmax,          /* I - maximum number of keywords to return */
-            float *value,       /* O - array of keyword values              */
-            int  *nfound,       /* O - number of values that were returned  */
-            int  *status)       /* IO - error status                        */
-/*
-  Read (get) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NMAX -1) inclusive.  
-*/
-{
-    int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval;
-    long ival;
-    char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD];
-    char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign;
-
-    if (*status > 0)
-        return(*status);
-
-    *nfound = 0;
-    nend = nstart + nmax - 1;
-
-    keyroot[0] = '\0';
-    strncat(keyroot, keyname, FLEN_KEYWORD - 1);
-
-    lenroot = strlen(keyroot);
-    
-    if (lenroot == 0)     /*  root must be at least 1 char long  */
-        return(*status);
-
-    for (ii=0; ii < lenroot; ii++)           /*  make sure upper case  */
-        keyroot[ii] = toupper(keyroot[ii]);
-
-    ffghps(fptr, &nkeys, &mkeys, status);  /*  get the number of keywords  */
-
-    ffmaky(fptr, 3, status);  /* move to 3rd keyword (skip 1st 2 keywords) */
-
-    undefinedval = FALSE;
-    for (ii=3; ii <= nkeys; ii++)  
-    {
-       if (ffgnky(fptr, card, status) > 0)     /*  get next keyword  */
-           return(*status);
-
-       if (strncmp(keyroot, card, lenroot) == 0)  /* see if keyword matches */
-       {
-          keyindex[0] = '\0';
-          equalssign = strchr(card, '=');
-	  if (equalssign == 0) continue;  /* keyword has no value */
-
-          strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
-
-          tstatus = 0;
-          if (ffc2ii(keyindex, &ival, &tstatus) <= 0)     /*  test suffix  */
-          {
-             if (ival <= nend && ival >= nstart)
-             {
-                ffpsvc(card, svalue, comm, status);   /*  parse the value */
-                ffc2r(svalue, &value[ival-nstart], status); /* convert */
-                if (ival - nstart + 1 > *nfound)
-                      *nfound = ival - nstart + 1;  /*  max found */ 
-
-                if (*status == VALUE_UNDEFINED)
-                {
-                    undefinedval = TRUE;
-                   *status = 0;  /* reset status to read remaining values */
-                }
-             }
-          }
-       }
-    }
-    if (undefinedval && (*status <= 0) )
-        *status = VALUE_UNDEFINED;  /* report at least 1 value undefined */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgknd( fitsfile *fptr,     /* I - FITS file pointer                    */
-            const char *keyname,      /* I - root name of keywords to read        */
-            int  nstart,        /* I - starting index number                */
-            int  nmax,          /* I - maximum number of keywords to return */
-            double *value,      /* O - array of keyword values              */
-            int  *nfound,       /* O - number of values that were returned  */
-            int  *status)       /* IO - error status                        */
-/*
-  Read (get) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NMAX -1) inclusive.  
-*/
-{
-    int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval;
-    long ival;
-    char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD];
-    char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign;
-
-    if (*status > 0)
-        return(*status);
-
-    *nfound = 0;
-    nend = nstart + nmax - 1;
-
-    keyroot[0] = '\0';
-    strncat(keyroot, keyname, FLEN_KEYWORD - 1);
-
-    lenroot = strlen(keyroot);
-
-    if (lenroot == 0)     /*  root must be at least 1 char long  */
-        return(*status);
-
-    for (ii=0; ii < lenroot; ii++)           /*  make sure upper case  */
-        keyroot[ii] = toupper(keyroot[ii]);
-
-    ffghps(fptr, &nkeys, &mkeys, status);  /*  get the number of keywords  */
-
-    ffmaky(fptr, 3, status);  /* move to 3rd keyword (skip 1st 2 keywords) */
-
-    undefinedval = FALSE;
-    for (ii=3; ii <= nkeys; ii++)  
-    {
-       if (ffgnky(fptr, card, status) > 0)     /*  get next keyword  */
-           return(*status);
-       if (strncmp(keyroot, card, lenroot) == 0)   /* see if keyword matches */
-       {
-          keyindex[0] = '\0';
-          equalssign = strchr(card, '=');
-	  if (equalssign == 0) continue;  /* keyword has no value */
-
-          strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
-          tstatus = 0;
-          if (ffc2ii(keyindex, &ival, &tstatus) <= 0)      /*  test suffix */
-          {
-             if (ival <= nend && ival >= nstart) /* is index within range? */
-             {
-                ffpsvc(card, svalue, comm, status);   /*  parse the value */
-                ffc2d(svalue, &value[ival-nstart], status); /* convert */
-                if (ival - nstart + 1 > *nfound)
-                      *nfound = ival - nstart + 1;  /*  max found */ 
-
-                if (*status == VALUE_UNDEFINED)
-                {
-                    undefinedval = TRUE;
-                   *status = 0;  /* reset status to read remaining values */
-                }
-             }
-          }
-       }
-    }
-    if (undefinedval && (*status <= 0) )
-        *status = VALUE_UNDEFINED;  /* report at least 1 value undefined */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgtdm(fitsfile *fptr,  /* I - FITS file pointer                        */
-           int colnum,      /* I - number of the column to read             */
-           int maxdim,      /* I - maximum no. of dimensions to read;       */
-           int *naxis,      /* O - number of axes in the data array         */
-           long naxes[],    /* O - length of each data axis                 */
-           int *status)     /* IO - error status                            */
-/*
-  read and parse the TDIMnnn keyword to get the dimensionality of a column
-*/
-{
-    int tstatus = 0;
-    char keyname[FLEN_KEYWORD], tdimstr[FLEN_VALUE];
-
-    if (*status > 0)
-        return(*status);
-
-    ffkeyn("TDIM", colnum, keyname, status);      /* construct keyword name */
-
-    ffgkys(fptr, keyname, tdimstr, NULL, &tstatus); /* try reading keyword */
-
-    ffdtdm(fptr, tdimstr, colnum, maxdim,naxis, naxes, status); /* decode it */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgtdmll(fitsfile *fptr,  /* I - FITS file pointer                      */
-           int colnum,      /* I - number of the column to read             */
-           int maxdim,      /* I - maximum no. of dimensions to read;       */
-           int *naxis,      /* O - number of axes in the data array         */
-           LONGLONG naxes[], /* O - length of each data axis                 */
-           int *status)     /* IO - error status                            */
-/*
-  read and parse the TDIMnnn keyword to get the dimensionality of a column
-*/
-{
-    int tstatus = 0;
-    char keyname[FLEN_KEYWORD], tdimstr[FLEN_VALUE];
-
-    if (*status > 0)
-        return(*status);
-
-    ffkeyn("TDIM", colnum, keyname, status);      /* construct keyword name */
-
-    ffgkys(fptr, keyname, tdimstr, NULL, &tstatus); /* try reading keyword */
-
-    ffdtdmll(fptr, tdimstr, colnum, maxdim,naxis, naxes, status); /* decode it */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffdtdm(fitsfile *fptr,  /* I - FITS file pointer                        */
-           char *tdimstr,   /* I - TDIMn keyword value string. e.g. (10,10) */
-           int colnum,      /* I - number of the column             */
-           int maxdim,      /* I - maximum no. of dimensions to read;       */
-           int *naxis,      /* O - number of axes in the data array         */
-           long naxes[],    /* O - length of each data axis                 */
-           int *status)     /* IO - error status                            */
-/*
-  decode the TDIMnnn keyword to get the dimensionality of a column.
-  Check that the value is legal and consistent with the TFORM value.
-  If colnum = 0, then the validity checking is disabled.
-*/
-{
-    long dimsize, totalpix = 1;
-    char *loc, *lastloc, message[81];
-    tcolumn *colptr = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    if (colnum != 0) {
-        if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-            ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-        if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
-            return(*status = BAD_COL_NUM);
-
-        colptr = (fptr->Fptr)->tableptr;   /* set pointer to the first column */
-        colptr += (colnum - 1);    /* increment to the correct column */
-
-        if (!tdimstr[0])   /* TDIMn keyword doesn't exist? */
-        {
-            *naxis = 1;                   /* default = 1 dimensional */
-            if (maxdim > 0)
-                naxes[0] = (long) colptr->trepeat; /* default length = repeat */
-
-            return(*status);
-        }
-    }
-
-    *naxis = 0;
-
-    loc = strchr(tdimstr, '(' );  /* find the opening quote */
-    if (!loc)
-    {
-            sprintf(message, "Illegal dimensions format: %s", tdimstr);
-            return(*status = BAD_TDIM);
-    }
-
-    while (loc)
-    {
-            loc++;
-            dimsize = strtol(loc, &loc, 10);  /* read size of next dimension */
-            if (*naxis < maxdim)
-                naxes[*naxis] = dimsize;
-
-            if (dimsize < 0)
-            {
-                ffpmsg("one or more dimension are less than 0 (ffdtdm)");
-                ffpmsg(tdimstr);
-                return(*status = BAD_TDIM);
-            }
-
-            totalpix *= dimsize;
-            (*naxis)++;
-            lastloc = loc;
-            loc = strchr(loc, ',');  /* look for comma before next dimension */
-    }
-
-    loc = strchr(lastloc, ')' );  /* check for the closing quote */
-    if (!loc)
-    {
-            sprintf(message, "Illegal dimensions format: %s", tdimstr);
-            return(*status = BAD_TDIM);
-    }
-
-    if (colnum != 0) {
-        if ((colptr->tdatatype > 0) && ((long) colptr->trepeat != totalpix))
-        {
-          sprintf(message,
-          "column vector length, %ld, does not equal TDIMn array size, %ld",
-          (long) colptr->trepeat, totalpix);
-          ffpmsg(message);
-          ffpmsg(tdimstr);
-          return(*status = BAD_TDIM);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffdtdmll(fitsfile *fptr,  /* I - FITS file pointer                        */
-           char *tdimstr,   /* I - TDIMn keyword value string. e.g. (10,10) */
-           int colnum,      /* I - number of the column             */
-           int maxdim,      /* I - maximum no. of dimensions to read;       */
-           int *naxis,      /* O - number of axes in the data array         */
-           LONGLONG naxes[],    /* O - length of each data axis                 */
-           int *status)     /* IO - error status                            */
-/*
-  decode the TDIMnnn keyword to get the dimensionality of a column.
-  Check that the value is legal and consistent with the TFORM value.
-*/
-{
-    LONGLONG dimsize;
-    LONGLONG totalpix = 1;
-    char *loc, *lastloc, message[81];
-    tcolumn *colptr;
-    double doublesize;
-
-    if (*status > 0)
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
-        return(*status = BAD_COL_NUM);
-
-    colptr = (fptr->Fptr)->tableptr;   /* set pointer to the first column */
-    colptr += (colnum - 1);    /* increment to the correct column */
-
-    if (!tdimstr[0])   /* TDIMn keyword doesn't exist? */
-    {
-        *naxis = 1;                   /* default = 1 dimensional */
-        if (maxdim > 0)
-            naxes[0] = colptr->trepeat; /* default length = repeat */
-    }
-    else
-    {
-        *naxis = 0;
-
-        loc = strchr(tdimstr, '(' );  /* find the opening quote */
-        if (!loc)
-        {
-            sprintf(message, "Illegal TDIM keyword value: %s", tdimstr);
-            return(*status = BAD_TDIM);
-        }
-
-        while (loc)
-        {
-            loc++;
-
-    /* Read value as a double because the string to 64-bit int function is  */
-    /* platform dependent (strtoll, strtol, _atoI64).  This still gives     */
-    /* about 48 bits of precision, which is plenty for this purpose.        */
-
-            doublesize = strtod(loc, &loc);
-            dimsize = (LONGLONG) (doublesize + 0.1);
-
-            if (*naxis < maxdim)
-                naxes[*naxis] = dimsize;
-
-            if (dimsize < 0)
-            {
-                ffpmsg("one or more TDIM values are less than 0 (ffdtdm)");
-                ffpmsg(tdimstr);
-                return(*status = BAD_TDIM);
-            }
-
-            totalpix *= dimsize;
-            (*naxis)++;
-            lastloc = loc;
-            loc = strchr(loc, ',');  /* look for comma before next dimension */
-        }
-
-        loc = strchr(lastloc, ')' );  /* check for the closing quote */
-        if (!loc)
-        {
-            sprintf(message, "Illegal TDIM keyword value: %s", tdimstr);
-            return(*status = BAD_TDIM);
-        }
-
-        if ((colptr->tdatatype > 0) && (colptr->trepeat != totalpix))
-        {
-          sprintf(message,
-          "column vector length, %.0f, does not equal TDIMn array size, %.0f",
-          (double) (colptr->trepeat), (double) totalpix);
-          ffpmsg(message);
-          ffpmsg(tdimstr);
-          return(*status = BAD_TDIM);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffghpr(fitsfile *fptr,  /* I - FITS file pointer                        */
-           int maxdim,      /* I - maximum no. of dimensions to read;       */
-           int *simple,     /* O - does file conform to FITS standard? 1/0  */
-           int *bitpix,     /* O - number of bits per data value pixel      */
-           int *naxis,      /* O - number of axes in the data array         */
-           long naxes[],    /* O - length of each data axis                 */
-           long *pcount,    /* O - number of group parameters (usually 0)   */
-           long *gcount,    /* O - number of random groups (usually 1 or 0) */
-           int *extend,     /* O - may FITS file haave extensions?          */
-           int *status)     /* IO - error status                            */
-/*
-  Get keywords from the Header of the PRimary array:
-  Check that the keywords conform to the FITS standard and return the
-  parameters which determine the size and structure of the primary array
-  or IMAGE extension.
-*/
-{
-    int idummy, ii;
-    LONGLONG lldummy;
-    double ddummy;
-    LONGLONG tnaxes[99];
-
-    ffgphd(fptr, maxdim, simple, bitpix, naxis, tnaxes, pcount, gcount, extend,
-          &ddummy, &ddummy, &lldummy, &idummy, status);
-	  
-    if (naxis && naxes) {
-         for (ii = 0; (ii < *naxis) && (ii < maxdim); ii++)
-	     naxes[ii] = (long) tnaxes[ii];
-    } else if (naxes) {
-         for (ii = 0; ii < maxdim; ii++)
-	     naxes[ii] = (long) tnaxes[ii];
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffghprll(fitsfile *fptr,  /* I - FITS file pointer                        */
-           int maxdim,      /* I - maximum no. of dimensions to read;       */
-           int *simple,     /* O - does file conform to FITS standard? 1/0  */
-           int *bitpix,     /* O - number of bits per data value pixel      */
-           int *naxis,      /* O - number of axes in the data array         */
-           LONGLONG naxes[],    /* O - length of each data axis                 */
-           long *pcount,    /* O - number of group parameters (usually 0)   */
-           long *gcount,    /* O - number of random groups (usually 1 or 0) */
-           int *extend,     /* O - may FITS file haave extensions?          */
-           int *status)     /* IO - error status                            */
-/*
-  Get keywords from the Header of the PRimary array:
-  Check that the keywords conform to the FITS standard and return the
-  parameters which determine the size and structure of the primary array
-  or IMAGE extension.
-*/
-{
-    int idummy;
-    LONGLONG lldummy;
-    double ddummy;
-
-    ffgphd(fptr, maxdim, simple, bitpix, naxis, naxes, pcount, gcount, extend,
-          &ddummy, &ddummy, &lldummy, &idummy, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffghtb(fitsfile *fptr,  /* I - FITS file pointer                        */
-           int maxfield,    /* I - maximum no. of columns to read;          */
-           long *naxis1,    /* O - length of table row in bytes             */
-           long *naxis2,    /* O - number of rows in the table              */
-           int *tfields,    /* O - number of columns in the table           */
-           char **ttype,    /* O - name of each column                      */
-           long *tbcol,     /* O - byte offset in row to each column        */
-           char **tform,    /* O - value of TFORMn keyword for each column  */
-           char **tunit,    /* O - value of TUNITn keyword for each column  */
-           char *extnm,   /* O - value of EXTNAME keyword, if any         */
-           int *status)     /* IO - error status                            */
-/*
-  Get keywords from the Header of the ASCII TaBle:
-  Check that the keywords conform to the FITS standard and return the
-  parameters which describe the table.
-*/
-{
-    int ii, maxf, nfound, tstatus;
-    long fields;
-    char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT];
-    char xtension[FLEN_VALUE], message[81];
-    LONGLONG llnaxis1, llnaxis2, pcount;
-
-    if (*status > 0)
-        return(*status);
-
-    /* read the first keyword of the extension */
-    ffgkyn(fptr, 1, name, value, comm, status);
-
-    if (!strcmp(name, "XTENSION"))
-    {
-            if (ffc2s(value, xtension, status) > 0)  /* get the value string */
-            {
-                ffpmsg("Bad value string for XTENSION keyword:");
-                ffpmsg(value);
-                return(*status);
-            }
-
-            /* allow the quoted string value to begin in any column and */
-            /* allow any number of trailing blanks before the closing quote */
-            if ( (value[0] != '\'')   ||  /* first char must be a quote */
-                 ( strcmp(xtension, "TABLE") ) )
-            {
-                sprintf(message,
-                "This is not a TABLE extension: %s", value);
-                ffpmsg(message);
-                return(*status = NOT_ATABLE);
-            }
-    }
-
-    else  /* error: 1st keyword of extension != XTENSION */
-    {
-        sprintf(message,
-        "First keyword of the extension is not XTENSION: %s", name);
-        ffpmsg(message);
-        return(*status = NO_XTENSION);
-    }
-
-    if (ffgttb(fptr, &llnaxis1, &llnaxis2, &pcount, &fields, status) > 0)
-        return(*status);
-
-    if (naxis1)
-       *naxis1 = (long) llnaxis1;
-
-    if (naxis2)
-       *naxis2 = (long) llnaxis2;
-
-    if (pcount != 0)
-    {
-       sprintf(message, "PCOUNT = %.0f is illegal in ASCII table; must = 0",
-               (double) pcount);
-       ffpmsg(message);
-       return(*status = BAD_PCOUNT);
-    }
-
-    if (tfields)
-       *tfields = fields;
-
-    if (maxfield < 0)
-        maxf = fields;
-    else
-        maxf = minvalue(maxfield, fields);
-
-    if (maxf > 0)
-    {
-        for (ii = 0; ii < maxf; ii++)
-        {   /* initialize optional keyword values */
-            if (ttype)
-                *ttype[ii] = '\0';   
-
-            if (tunit)
-                *tunit[ii] = '\0';
-        }
-
-   
-        if (ttype)
-            ffgkns(fptr, "TTYPE", 1, maxf, ttype, &nfound, status);
-
-        if (tunit)
-            ffgkns(fptr, "TUNIT", 1, maxf, tunit, &nfound, status);
-
-        if (*status > 0)
-            return(*status);
-
-        if (tbcol)
-        {
-            ffgknj(fptr, "TBCOL", 1, maxf, tbcol, &nfound, status);
-
-            if (*status > 0 || nfound != maxf)
-            {
-                ffpmsg(
-        "Required TBCOL keyword(s) not found in ASCII table header (ffghtb).");
-                return(*status = NO_TBCOL);
-            }
-        }
-
-        if (tform)
-        {
-            ffgkns(fptr, "TFORM", 1, maxf, tform, &nfound, status);
-
-            if (*status > 0 || nfound != maxf)
-            {
-                ffpmsg(
-        "Required TFORM keyword(s) not found in ASCII table header (ffghtb).");
-                return(*status = NO_TFORM);
-            }
-        }
-    }
-
-    if (extnm)
-    {
-        extnm[0] = '\0';
-
-        tstatus = *status;
-        ffgkys(fptr, "EXTNAME", extnm, comm, status);
-
-        if (*status == KEY_NO_EXIST)
-            *status = tstatus;  /* keyword not required, so ignore error */
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffghtbll(fitsfile *fptr, /* I - FITS file pointer                        */
-           int maxfield,    /* I - maximum no. of columns to read;          */
-           LONGLONG *naxis1, /* O - length of table row in bytes             */
-           LONGLONG *naxis2, /* O - number of rows in the table              */
-           int *tfields,    /* O - number of columns in the table           */
-           char **ttype,    /* O - name of each column                      */
-           LONGLONG *tbcol, /* O - byte offset in row to each column        */
-           char **tform,    /* O - value of TFORMn keyword for each column  */
-           char **tunit,    /* O - value of TUNITn keyword for each column  */
-           char *extnm,     /* O - value of EXTNAME keyword, if any         */
-           int *status)     /* IO - error status                            */
-/*
-  Get keywords from the Header of the ASCII TaBle:
-  Check that the keywords conform to the FITS standard and return the
-  parameters which describe the table.
-*/
-{
-    int ii, maxf, nfound, tstatus;
-    long fields;
-    char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT];
-    char xtension[FLEN_VALUE], message[81];
-    LONGLONG llnaxis1, llnaxis2, pcount;
-
-    if (*status > 0)
-        return(*status);
-
-    /* read the first keyword of the extension */
-    ffgkyn(fptr, 1, name, value, comm, status);
-
-    if (!strcmp(name, "XTENSION"))
-    {
-            if (ffc2s(value, xtension, status) > 0)  /* get the value string */
-            {
-                ffpmsg("Bad value string for XTENSION keyword:");
-                ffpmsg(value);
-                return(*status);
-            }
-
-            /* allow the quoted string value to begin in any column and */
-            /* allow any number of trailing blanks before the closing quote */
-            if ( (value[0] != '\'')   ||  /* first char must be a quote */
-                 ( strcmp(xtension, "TABLE") ) )
-            {
-                sprintf(message,
-                "This is not a TABLE extension: %s", value);
-                ffpmsg(message);
-                return(*status = NOT_ATABLE);
-            }
-    }
-
-    else  /* error: 1st keyword of extension != XTENSION */
-    {
-        sprintf(message,
-        "First keyword of the extension is not XTENSION: %s", name);
-        ffpmsg(message);
-        return(*status = NO_XTENSION);
-    }
-
-    if (ffgttb(fptr, &llnaxis1, &llnaxis2, &pcount, &fields, status) > 0)
-        return(*status);
-
-    if (naxis1)
-       *naxis1 = llnaxis1;
-
-    if (naxis2)
-       *naxis2 = llnaxis2;
-
-    if (pcount != 0)
-    {
-       sprintf(message, "PCOUNT = %.0f is illegal in ASCII table; must = 0",
-             (double) pcount);
-       ffpmsg(message);
-       return(*status = BAD_PCOUNT);
-    }
-
-    if (tfields)
-       *tfields = fields;
-
-    if (maxfield < 0)
-        maxf = fields;
-    else
-        maxf = minvalue(maxfield, fields);
-
-    if (maxf > 0)
-    {
-        for (ii = 0; ii < maxf; ii++)
-        {   /* initialize optional keyword values */
-            if (ttype)
-                *ttype[ii] = '\0';   
-
-            if (tunit)
-                *tunit[ii] = '\0';
-        }
-
-   
-        if (ttype)
-            ffgkns(fptr, "TTYPE", 1, maxf, ttype, &nfound, status);
-
-        if (tunit)
-            ffgkns(fptr, "TUNIT", 1, maxf, tunit, &nfound, status);
-
-        if (*status > 0)
-            return(*status);
-
-        if (tbcol)
-        {
-            ffgknjj(fptr, "TBCOL", 1, maxf, tbcol, &nfound, status);
-
-            if (*status > 0 || nfound != maxf)
-            {
-                ffpmsg(
-        "Required TBCOL keyword(s) not found in ASCII table header (ffghtbll).");
-                return(*status = NO_TBCOL);
-            }
-        }
-
-        if (tform)
-        {
-            ffgkns(fptr, "TFORM", 1, maxf, tform, &nfound, status);
-
-            if (*status > 0 || nfound != maxf)
-            {
-                ffpmsg(
-        "Required TFORM keyword(s) not found in ASCII table header (ffghtbll).");
-                return(*status = NO_TFORM);
-            }
-        }
-    }
-
-    if (extnm)
-    {
-        extnm[0] = '\0';
-
-        tstatus = *status;
-        ffgkys(fptr, "EXTNAME", extnm, comm, status);
-
-        if (*status == KEY_NO_EXIST)
-            *status = tstatus;  /* keyword not required, so ignore error */
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffghbn(fitsfile *fptr,  /* I - FITS file pointer                        */
-           int maxfield,    /* I - maximum no. of columns to read;          */
-           long *naxis2,    /* O - number of rows in the table              */
-           int *tfields,    /* O - number of columns in the table           */
-           char **ttype,    /* O - name of each column                      */
-           char **tform,    /* O - TFORMn value for each column             */
-           char **tunit,    /* O - TUNITn value for each column             */
-           char *extnm,     /* O - value of EXTNAME keyword, if any         */
-           long *pcount,    /* O - value of PCOUNT keyword                  */
-           int *status)     /* IO - error status                            */
-/*
-  Get keywords from the Header of the BiNary table:
-  Check that the keywords conform to the FITS standard and return the
-  parameters which describe the table.
-*/
-{
-    int ii, maxf, nfound, tstatus;
-    long  fields;
-    char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT];
-    char xtension[FLEN_VALUE], message[81];
-    LONGLONG naxis1ll, naxis2ll, pcountll;
-
-    if (*status > 0)
-        return(*status);
-
-    /* read the first keyword of the extension */
-    ffgkyn(fptr, 1, name, value, comm, status);
-
-    if (!strcmp(name, "XTENSION"))
-    {
-            if (ffc2s(value, xtension, status) > 0)  /* get the value string */
-            {
-                ffpmsg("Bad value string for XTENSION keyword:");
-                ffpmsg(value);
-                return(*status);
-            }
-
-            /* allow the quoted string value to begin in any column and */
-            /* allow any number of trailing blanks before the closing quote */
-            if ( (value[0] != '\'')   ||  /* first char must be a quote */
-                 ( strcmp(xtension, "BINTABLE") &&
-                   strcmp(xtension, "A3DTABLE") &&
-                   strcmp(xtension, "3DTABLE")
-                 ) )
-            {
-                sprintf(message,
-                "This is not a BINTABLE extension: %s", value);
-                ffpmsg(message);
-                return(*status = NOT_BTABLE);
-            }
-    }
-
-    else  /* error: 1st keyword of extension != XTENSION */
-    {
-        sprintf(message,
-        "First keyword of the extension is not XTENSION: %s", name);
-        ffpmsg(message);
-        return(*status = NO_XTENSION);
-    }
-
-    if (ffgttb(fptr, &naxis1ll, &naxis2ll, &pcountll, &fields, status) > 0)
-        return(*status);
-
-    if (naxis2)
-       *naxis2 = (long) naxis2ll;
-
-    if (pcount)
-       *pcount = (long) pcountll;
-
-    if (tfields)
-        *tfields = fields;
-
-    if (maxfield < 0)
-        maxf = fields;
-    else
-        maxf = minvalue(maxfield, fields);
-
-    if (maxf > 0)
-    {
-        for (ii = 0; ii < maxf; ii++)
-        {   /* initialize optional keyword values */
-            if (ttype)
-                *ttype[ii] = '\0';   
-
-            if (tunit)
-                *tunit[ii] = '\0';
-        }
-
-        if (ttype)
-            ffgkns(fptr, "TTYPE", 1, maxf, ttype, &nfound, status);
-
-        if (tunit)
-            ffgkns(fptr, "TUNIT", 1, maxf, tunit, &nfound, status);
-
-        if (*status > 0)
-            return(*status);
-
-        if (tform)
-        {
-            ffgkns(fptr, "TFORM", 1, maxf, tform, &nfound, status);
-
-            if (*status > 0 || nfound != maxf)
-            {
-                ffpmsg(
-        "Required TFORM keyword(s) not found in binary table header (ffghbn).");
-                return(*status = NO_TFORM);
-            }
-        }
-    }
-
-    if (extnm)
-    {
-        extnm[0] = '\0';
-
-        tstatus = *status;
-        ffgkys(fptr, "EXTNAME", extnm, comm, status);
-
-        if (*status == KEY_NO_EXIST)
-          *status = tstatus;  /* keyword not required, so ignore error */
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffghbnll(fitsfile *fptr,  /* I - FITS file pointer                        */
-           int maxfield,    /* I - maximum no. of columns to read;          */
-           LONGLONG *naxis2,    /* O - number of rows in the table              */
-           int *tfields,    /* O - number of columns in the table           */
-           char **ttype,    /* O - name of each column                      */
-           char **tform,    /* O - TFORMn value for each column             */
-           char **tunit,    /* O - TUNITn value for each column             */
-           char *extnm,     /* O - value of EXTNAME keyword, if any         */
-           LONGLONG *pcount,    /* O - value of PCOUNT keyword                  */
-           int *status)     /* IO - error status                            */
-/*
-  Get keywords from the Header of the BiNary table:
-  Check that the keywords conform to the FITS standard and return the
-  parameters which describe the table.
-*/
-{
-    int ii, maxf, nfound, tstatus;
-    long  fields;
-    char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT];
-    char xtension[FLEN_VALUE], message[81];
-    LONGLONG naxis1ll, naxis2ll, pcountll;
-
-    if (*status > 0)
-        return(*status);
-
-    /* read the first keyword of the extension */
-    ffgkyn(fptr, 1, name, value, comm, status);
-
-    if (!strcmp(name, "XTENSION"))
-    {
-            if (ffc2s(value, xtension, status) > 0)  /* get the value string */
-            {
-                ffpmsg("Bad value string for XTENSION keyword:");
-                ffpmsg(value);
-                return(*status);
-            }
-
-            /* allow the quoted string value to begin in any column and */
-            /* allow any number of trailing blanks before the closing quote */
-            if ( (value[0] != '\'')   ||  /* first char must be a quote */
-                 ( strcmp(xtension, "BINTABLE") &&
-                   strcmp(xtension, "A3DTABLE") &&
-                   strcmp(xtension, "3DTABLE")
-                 ) )
-            {
-                sprintf(message,
-                "This is not a BINTABLE extension: %s", value);
-                ffpmsg(message);
-                return(*status = NOT_BTABLE);
-            }
-    }
-
-    else  /* error: 1st keyword of extension != XTENSION */
-    {
-        sprintf(message,
-        "First keyword of the extension is not XTENSION: %s", name);
-        ffpmsg(message);
-        return(*status = NO_XTENSION);
-    }
-
-    if (ffgttb(fptr, &naxis1ll, &naxis2ll, &pcountll, &fields, status) > 0)
-        return(*status);
-
-    if (naxis2)
-       *naxis2 = naxis2ll;
-
-    if (pcount)
-       *pcount = pcountll;
-
-    if (tfields)
-        *tfields = fields;
-
-    if (maxfield < 0)
-        maxf = fields;
-    else
-        maxf = minvalue(maxfield, fields);
-
-    if (maxf > 0)
-    {
-        for (ii = 0; ii < maxf; ii++)
-        {   /* initialize optional keyword values */
-            if (ttype)
-                *ttype[ii] = '\0';   
-
-            if (tunit)
-                *tunit[ii] = '\0';
-        }
-
-        if (ttype)
-            ffgkns(fptr, "TTYPE", 1, maxf, ttype, &nfound, status);
-
-        if (tunit)
-            ffgkns(fptr, "TUNIT", 1, maxf, tunit, &nfound, status);
-
-        if (*status > 0)
-            return(*status);
-
-        if (tform)
-        {
-            ffgkns(fptr, "TFORM", 1, maxf, tform, &nfound, status);
-
-            if (*status > 0 || nfound != maxf)
-            {
-                ffpmsg(
-        "Required TFORM keyword(s) not found in binary table header (ffghbn).");
-                return(*status = NO_TFORM);
-            }
-        }
-    }
-
-    if (extnm)
-    {
-        extnm[0] = '\0';
-
-        tstatus = *status;
-        ffgkys(fptr, "EXTNAME", extnm, comm, status);
-
-        if (*status == KEY_NO_EXIST)
-          *status = tstatus;  /* keyword not required, so ignore error */
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgphd(fitsfile *fptr,  /* I - FITS file pointer                        */
-           int maxdim,      /* I - maximum no. of dimensions to read;       */
-           int *simple,     /* O - does file conform to FITS standard? 1/0  */
-           int *bitpix,     /* O - number of bits per data value pixel      */
-           int *naxis,      /* O - number of axes in the data array         */
-           LONGLONG naxes[],    /* O - length of each data axis                 */
-           long *pcount,    /* O - number of group parameters (usually 0)   */
-           long *gcount,    /* O - number of random groups (usually 1 or 0) */
-           int *extend,     /* O - may FITS file haave extensions?          */
-           double *bscale,  /* O - array pixel linear scaling factor        */
-           double *bzero,   /* O - array pixel linear scaling zero point    */
-           LONGLONG *blank, /* O - value used to represent undefined pixels */
-           int *nspace,     /* O - number of blank keywords prior to END    */
-           int *status)     /* IO - error status                            */
-{
-/*
-  Get the Primary HeaDer parameters.  Check that the keywords conform to
-  the FITS standard and return the parameters which determine the size and
-  structure of the primary array or IMAGE extension.
-*/
-    int unknown, found_end, tstatus, ii, nextkey, namelen;
-    long longbitpix, longnaxis;
-    LONGLONG axislen;
-    char message[FLEN_ERRMSG], keyword[FLEN_KEYWORD];
-    char card[FLEN_CARD];
-    char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT];
-    char xtension[FLEN_VALUE];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if (simple)
-       *simple = 1;
-
-    unknown = 0;
-
-    /*--------------------------------------------------------------------*/
-    /*  Get 1st keyword of HDU and test whether it is SIMPLE or XTENSION  */
-    /*--------------------------------------------------------------------*/
-    ffgkyn(fptr, 1, name, value, comm, status);
-
-    if ((fptr->Fptr)->curhdu == 0) /* Is this the beginning of the FITS file? */
-    {
-        if (!strcmp(name, "SIMPLE"))
-        {
-            if (value[0] == 'F')
-            {
-                if (simple)
-                    *simple=0;          /* not a simple FITS file */
-            }
-            else if (value[0] != 'T')
-                return(*status = BAD_SIMPLE);
-        }
-
-        else
-        {
-            sprintf(message,
-                   "First keyword of the file is not SIMPLE: %s", name);
-            ffpmsg(message);
-            return(*status = NO_SIMPLE);
-        }
-    }
-
-    else    /* not beginning of the file, so presumably an IMAGE extension */
-    {       /* or it could be a compressed image in a binary table */
-
-        if (!strcmp(name, "XTENSION"))
-        {
-            if (ffc2s(value, xtension, status) > 0)  /* get the value string */
-            {
-                ffpmsg("Bad value string for XTENSION keyword:");
-                ffpmsg(value);
-                return(*status);
-            }
-
-            /* allow the quoted string value to begin in any column and */
-            /* allow any number of trailing blanks before the closing quote */
-            if ( (value[0] != '\'')   ||  /* first char must be a quote */
-                  ( strcmp(xtension, "IMAGE")  &&
-                    strcmp(xtension, "IUEIMAGE") ) )
-            {
-                unknown = 1;  /* unknown type of extension; press on anyway */
-                sprintf(message,
-                   "This is not an IMAGE extension: %s", value);
-                ffpmsg(message);
-            }
-        }
-
-        else  /* error: 1st keyword of extension != XTENSION */
-        {
-            sprintf(message,
-            "First keyword of the extension is not XTENSION: %s", name);
-            ffpmsg(message);
-            return(*status = NO_XTENSION);
-        }
-    }
-
-    if (unknown && (fptr->Fptr)->compressimg)
-    {
-        /* this is a compressed image, so read ZBITPIX, ZNAXIS keywords */
-        unknown = 0;  /* reset flag */
-        ffxmsg(3, message); /* clear previous spurious error message */
-
-        if (bitpix)
-        {
-            ffgidt(fptr, bitpix, status); /* get bitpix value */
-
-            if (*status > 0)
-            {
-                ffpmsg("Error reading BITPIX value of compressed image");
-                return(*status);
-            }
-        }
-
-        if (naxis)
-        {
-            ffgidm(fptr, naxis, status); /* get NAXIS value */
-
-            if (*status > 0)
-            {
-                ffpmsg("Error reading NAXIS value of compressed image");
-                return(*status);
-            }
-        }
-
-        if (naxes)
-        {
-            ffgiszll(fptr, maxdim, naxes, status);  /* get NAXISn value */
-
-            if (*status > 0)
-            {
-                ffpmsg("Error reading NAXISn values of compressed image");
-                return(*status);
-            }
-        }
-
-        nextkey = 9; /* skip required table keywords in the following search */
-    }
-    else
-    {
-
-        /*----------------------------------------------------------------*/
-        /*  Get 2nd keyword;  test whether it is BITPIX with legal value  */
-        /*----------------------------------------------------------------*/
-        ffgkyn(fptr, 2, name, value, comm, status);  /* BITPIX = 2nd keyword */
-
-        if (strcmp(name, "BITPIX"))
-        {
-            sprintf(message,
-            "Second keyword of the extension is not BITPIX: %s", name);
-            ffpmsg(message);
-            return(*status = NO_BITPIX);
-        }
-
-        if (ffc2ii(value,  &longbitpix, status) > 0)
-        {
-            sprintf(message,
-            "Value of BITPIX keyword is not an integer: %s", value);
-            ffpmsg(message);
-            return(*status = BAD_BITPIX);
-        }
-        else if (longbitpix != BYTE_IMG && longbitpix != SHORT_IMG &&
-             longbitpix != LONG_IMG && longbitpix != LONGLONG_IMG &&
-             longbitpix != FLOAT_IMG && longbitpix != DOUBLE_IMG)
-        {
-            sprintf(message,
-            "Illegal value for BITPIX keyword: %s", value);
-            ffpmsg(message);
-            return(*status = BAD_BITPIX);
-        }
-        if (bitpix)
-            *bitpix = longbitpix;  /* do explicit type conversion */
-
-        /*---------------------------------------------------------------*/
-        /*  Get 3rd keyword;  test whether it is NAXIS with legal value  */
-        /*---------------------------------------------------------------*/
-        ffgtkn(fptr, 3, "NAXIS",  &longnaxis, status);
-
-        if (*status == BAD_ORDER)
-            return(*status = NO_NAXIS);
-        else if (*status == NOT_POS_INT || longnaxis > 999)
-        {
-            sprintf(message,"NAXIS = %ld is illegal", longnaxis);
-            ffpmsg(message);
-            return(*status = BAD_NAXIS);
-        }
-        else
-            if (naxis)
-                 *naxis = longnaxis;  /* do explicit type conversion */
-
-        /*---------------------------------------------------------*/
-        /*  Get the next NAXISn keywords and test for legal values */
-        /*---------------------------------------------------------*/
-        for (ii=0, nextkey=4; ii < longnaxis; ii++, nextkey++)
-        {
-            ffkeyn("NAXIS", ii+1, keyword, status);
-            ffgtknjj(fptr, 4+ii, keyword, &axislen, status);
-
-            if (*status == BAD_ORDER)
-                return(*status = NO_NAXES);
-            else if (*status == NOT_POS_INT)
-                return(*status = BAD_NAXES);
-            else if (ii < maxdim)
-                if (naxes)
-                    naxes[ii] = axislen;
-        }
-    }
-
-    /*---------------------------------------------------------*/
-    /*  now look for other keywords of interest:               */
-    /*  BSCALE, BZERO, BLANK, PCOUNT, GCOUNT, EXTEND, and END  */
-    /*---------------------------------------------------------*/
-
-    /*  initialize default values in case keyword is not present */
-    if (bscale)
-        *bscale = 1.0;
-    if (bzero)
-        *bzero  = 0.0;
-    if (pcount)
-        *pcount = 0;
-    if (gcount)
-        *gcount = 1;
-    if (extend)
-        *extend = 0;
-    if (blank)
-      *blank = NULL_UNDEFINED; /* no default null value for BITPIX=8,16,32 */
-
-    *nspace = 0;
-    found_end = 0;
-    tstatus = *status;
-
-    for (; !found_end; nextkey++)  
-    {
-      /* get next keyword */
-      /* don't use ffgkyn here because it trys to parse the card to read */
-      /* the value string, thus failing to read the file just because of */
-      /* minor syntax errors in optional keywords.                       */
-
-      if (ffgrec(fptr, nextkey, card, status) > 0 )  /* get the 80-byte card */
-      {
-        if (*status == KEY_OUT_BOUNDS)
-        {
-          found_end = 1;  /* simply hit the end of the header */
-          *status = tstatus;  /* reset error status */
-        }
-        else          
-        {
-          ffpmsg("Failed to find the END keyword in header (ffgphd).");
-        }
-      }
-      else /* got the next keyword without error */
-      {
-        ffgknm(card, name, &namelen, status); /* get the keyword name */
-
-        if (fftrec(name, status) > 0)  /* test keyword name; catches no END */
-        {
-          sprintf(message,
-              "Name of keyword no. %d contains illegal character(s): %s",
-              nextkey, name);
-          ffpmsg(message);
-
-          if (nextkey % 36 == 0) /* test if at beginning of 36-card record */
-            ffpmsg("  (This may indicate a missing END keyword).");
-        }
-
-        if (!strcmp(name, "BSCALE") && bscale)
-        {
-            *nspace = 0;  /* reset count of blank keywords */
-            ffpsvc(card, value, comm, status); /* parse value and comment */
-
-            if (ffc2dd(value, bscale, status) > 0) /* convert to double */
-            {
-                /* reset error status and continue, but still issue warning */
-                *status = tstatus;
-                *bscale = 1.0;
-
-                sprintf(message,
-                "Error reading BSCALE keyword value as a double: %s", value);
-                ffpmsg(message);
-            }
-        }
-
-        else if (!strcmp(name, "BZERO") && bzero)
-        {
-            *nspace = 0;  /* reset count of blank keywords */
-            ffpsvc(card, value, comm, status); /* parse value and comment */
-
-            if (ffc2dd(value, bzero, status) > 0) /* convert to double */
-            {
-                /* reset error status and continue, but still issue warning */
-                *status = tstatus;
-                *bzero = 0.0;
-
-                sprintf(message,
-                "Error reading BZERO keyword value as a double: %s", value);
-                ffpmsg(message);
-            }
-        }
-
-        else if (!strcmp(name, "BLANK") && blank)
-        {
-            *nspace = 0;  /* reset count of blank keywords */
-            ffpsvc(card, value, comm, status); /* parse value and comment */
-
-            if (ffc2jj(value, blank, status) > 0) /* convert to LONGLONG */
-            {
-                /* reset error status and continue, but still issue warning */
-                *status = tstatus;
-                *blank = NULL_UNDEFINED;
-
-                sprintf(message,
-                "Error reading BLANK keyword value as an integer: %s", value);
-                ffpmsg(message);
-            }
-        }
-
-        else if (!strcmp(name, "PCOUNT") && pcount)
-        {
-            *nspace = 0;  /* reset count of blank keywords */
-            ffpsvc(card, value, comm, status); /* parse value and comment */
-
-            if (ffc2ii(value, pcount, status) > 0) /* convert to long */
-            {
-                sprintf(message,
-                "Error reading PCOUNT keyword value as an integer: %s", value);
-                ffpmsg(message);
-            }
-        }
-
-        else if (!strcmp(name, "GCOUNT") && gcount)
-        {
-            *nspace = 0;  /* reset count of blank keywords */
-            ffpsvc(card, value, comm, status); /* parse value and comment */
-
-            if (ffc2ii(value, gcount, status) > 0) /* convert to long */
-            {
-                sprintf(message,
-                "Error reading GCOUNT keyword value as an integer: %s", value);
-                ffpmsg(message);
-            }
-        }
-
-        else if (!strcmp(name, "EXTEND") && extend)
-        {
-            *nspace = 0;  /* reset count of blank keywords */
-            ffpsvc(card, value, comm, status); /* parse value and comment */
-
-            if (ffc2ll(value, extend, status) > 0) /* convert to logical */
-            {
-                /* reset error status and continue, but still issue warning */
-                *status = tstatus;
-                *extend = 0;
-
-                sprintf(message,
-                "Error reading EXTEND keyword value as a logical: %s", value);
-                ffpmsg(message);
-            }
-        }
-
-        else if (!strcmp(name, "END"))
-            found_end = 1;
-
-        else if (!card[0] )
-            *nspace = *nspace + 1;  /* this is a blank card in the header */
-
-        else
-            *nspace = 0;  /* reset count of blank keywords immediately
-                            before the END keyword to zero   */
-      }
-
-      if (*status > 0)  /* exit on error after writing error message */
-      {
-        if ((fptr->Fptr)->curhdu == 0)
-            ffpmsg(
-            "Failed to read the required primary array header keywords.");
-        else
-            ffpmsg(
-            "Failed to read the required image extension header keywords.");
-
-        return(*status);
-      }
-    }
-
-    if (unknown)
-       *status = NOT_IMAGE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgttb(fitsfile *fptr,      /* I - FITS file pointer*/
-           LONGLONG *rowlen,        /* O - length of a table row, in bytes */
-           LONGLONG *nrows,         /* O - number of rows in the table */
-           LONGLONG *pcount,    /* O - value of PCOUNT keyword */
-           long *tfields,       /* O - number of fields in the table */
-           int *status)         /* IO - error status    */
-{
-/*
-  Get and Test TaBle;
-  Test that this is a legal ASCII or binary table and get some keyword values.
-  We assume that the calling routine has already tested the 1st keyword
-  of the extension to ensure that this is really a table extension.
-*/
-    if (*status > 0)
-        return(*status);
-
-    if (fftkyn(fptr, 2, "BITPIX", "8", status) == BAD_ORDER) /* 2nd keyword */
-        return(*status = NO_BITPIX);  /* keyword not BITPIX */
-    else if (*status == NOT_POS_INT)
-        return(*status = BAD_BITPIX); /* value != 8 */
-
-    if (fftkyn(fptr, 3, "NAXIS", "2", status) == BAD_ORDER) /* 3rd keyword */
-        return(*status = NO_NAXIS);  /* keyword not NAXIS */
-    else if (*status == NOT_POS_INT)
-        return(*status = BAD_NAXIS); /* value != 2 */
-
-    if (ffgtknjj(fptr, 4, "NAXIS1", rowlen, status) == BAD_ORDER) /* 4th key */
-        return(*status = NO_NAXES);  /* keyword not NAXIS1 */
-    else if (*status == NOT_POS_INT)
-        return(*status == BAD_NAXES); /* bad NAXIS1 value */
-
-    if (ffgtknjj(fptr, 5, "NAXIS2", nrows, status) == BAD_ORDER) /* 5th key */
-        return(*status = NO_NAXES);  /* keyword not NAXIS2 */
-    else if (*status == NOT_POS_INT)
-        return(*status == BAD_NAXES); /* bad NAXIS2 value */
-
-    if (ffgtknjj(fptr, 6, "PCOUNT", pcount, status) == BAD_ORDER) /* 6th key */
-        return(*status = NO_PCOUNT);  /* keyword not PCOUNT */
-    else if (*status == NOT_POS_INT)
-        return(*status = BAD_PCOUNT); /* bad PCOUNT value */
-
-    if (fftkyn(fptr, 7, "GCOUNT", "1", status) == BAD_ORDER) /* 7th keyword */
-        return(*status = NO_GCOUNT);  /* keyword not GCOUNT */
-    else if (*status == NOT_POS_INT)
-        return(*status = BAD_GCOUNT); /* value != 1 */
-
-    if (ffgtkn(fptr, 8, "TFIELDS", tfields, status) == BAD_ORDER) /* 8th key*/
-        return(*status = NO_TFIELDS);  /* keyword not TFIELDS */
-    else if (*status == NOT_POS_INT || *tfields > 999)
-        return(*status == BAD_TFIELDS); /* bad TFIELDS value */
-
-
-    if (*status > 0)
-       ffpmsg(
-       "Error reading required keywords in the table header (FTGTTB).");
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgtkn(fitsfile *fptr,  /* I - FITS file pointer              */
-           int numkey,      /* I - number of the keyword to read  */
-           char *name,      /* I - expected name of the keyword   */
-           long *value,     /* O - integer value of the keyword   */
-           int *status)     /* IO - error status                  */
-{
-/*
-  test that keyword number NUMKEY has the expected name and get the
-  integer value of the keyword.  Return an error if the keyword
-  name does not match the input name, or if the value of the
-  keyword is not a positive integer.
-*/
-    char keyname[FLEN_KEYWORD], valuestring[FLEN_VALUE];
-    char comm[FLEN_COMMENT], message[FLEN_ERRMSG];
-   
-    if (*status > 0)
-        return(*status);
-    
-    keyname[0] = '\0';
-    valuestring[0] = '\0';
-
-    if (ffgkyn(fptr, numkey, keyname, valuestring, comm, status) <= 0)
-    {
-        if (strcmp(keyname, name) )
-            *status = BAD_ORDER;  /* incorrect keyword name */
-
-        else
-        {
-            ffc2ii(valuestring, value, status);  /* convert to integer */
-
-            if (*status > 0 || *value < 0 )
-               *status = NOT_POS_INT;
-        }
-
-        if (*status > 0)
-        {
-            sprintf(message,
-              "ffgtkn found unexpected keyword or value for keyword no. %d.",
-              numkey);
-            ffpmsg(message);
-
-            sprintf(message,
-              " Expected positive integer keyword %s, but instead", name);
-            ffpmsg(message);
-
-            sprintf(message,
-              " found keyword %s with value %s", keyname, valuestring);
-            ffpmsg(message);
-        }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgtknjj(fitsfile *fptr,  /* I - FITS file pointer              */
-           int numkey,      /* I - number of the keyword to read  */
-           char *name,      /* I - expected name of the keyword   */
-           LONGLONG *value, /* O - integer value of the keyword   */
-           int *status)     /* IO - error status                  */
-{
-/*
-  test that keyword number NUMKEY has the expected name and get the
-  integer value of the keyword.  Return an error if the keyword
-  name does not match the input name, or if the value of the
-  keyword is not a positive integer.
-*/
-    char keyname[FLEN_KEYWORD], valuestring[FLEN_VALUE];
-    char comm[FLEN_COMMENT], message[FLEN_ERRMSG];
-   
-    if (*status > 0)
-        return(*status);
-    
-    keyname[0] = '\0';
-    valuestring[0] = '\0';
-
-    if (ffgkyn(fptr, numkey, keyname, valuestring, comm, status) <= 0)
-    {
-        if (strcmp(keyname, name) )
-            *status = BAD_ORDER;  /* incorrect keyword name */
-
-        else
-        {
-            ffc2jj(valuestring, value, status);  /* convert to integer */
-
-            if (*status > 0 || *value < 0 )
-               *status = NOT_POS_INT;
-        }
-
-        if (*status > 0)
-        {
-            sprintf(message,
-              "ffgtknjj found unexpected keyword or value for keyword no. %d.",
-              numkey);
-            ffpmsg(message);
-
-            sprintf(message,
-              " Expected positive integer keyword %s, but instead", name);
-            ffpmsg(message);
-
-            sprintf(message,
-              " found keyword %s with value %s", keyname, valuestring);
-            ffpmsg(message);
-        }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fftkyn(fitsfile *fptr,  /* I - FITS file pointer              */
-           int numkey,      /* I - number of the keyword to read  */
-           char *name,      /* I - expected name of the keyword   */
-           char *value,     /* I - expected value of the keyword  */
-           int *status)     /* IO - error status                  */
-{
-/*
-  test that keyword number NUMKEY has the expected name and the
-  expected value string.
-*/
-    char keyname[FLEN_KEYWORD], valuestring[FLEN_VALUE];
-    char comm[FLEN_COMMENT], message[FLEN_ERRMSG];
-   
-    if (*status > 0)
-        return(*status);
-    
-    keyname[0] = '\0';
-    valuestring[0] = '\0';
-
-    if (ffgkyn(fptr, numkey, keyname, valuestring, comm, status) <= 0)
-    {
-        if (strcmp(keyname, name) )
-            *status = BAD_ORDER;  /* incorrect keyword name */
-
-        if (strcmp(value, valuestring) )
-            *status = NOT_POS_INT;  /* incorrect keyword value */
-    }
-
-    if (*status > 0)
-    {
-        sprintf(message,
-          "fftkyn found unexpected keyword or value for keyword no. %d.",
-          numkey);
-        ffpmsg(message);
-
-        sprintf(message,
-          " Expected keyword %s with value %s, but", name, value);
-        ffpmsg(message);
-
-        sprintf(message,
-          " found keyword %s with value %s", keyname, valuestring);
-        ffpmsg(message);
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffh2st(fitsfile *fptr,   /* I - FITS file pointer           */
-           char **header,    /* O - returned header string      */
-           int  *status)     /* IO - error status               */
-
-/*
-  read header keywords into a long string of chars.  This routine allocates
-  memory for the string, so the calling routine must eventually free the
-  memory when it is not needed any more.
-*/
-{
-    int nkeys;
-    long nrec;
-    LONGLONG headstart;
-
-    if (*status > 0)
-        return(*status);
-
-    /* get number of keywords in the header (doesn't include END) */
-    if (ffghsp(fptr, &nkeys, NULL, status) > 0)
-        return(*status);
-
-    nrec = (nkeys / 36 + 1);
-
-    /* allocate memory for all the keywords (multiple of 2880 bytes) */
-    *header = (char *) calloc ( nrec * 2880 + 1, 1);
-    if (!(*header))
-    {
-         *status = MEMORY_ALLOCATION;
-         ffpmsg("failed to allocate memory to hold all the header keywords");
-         return(*status);
-    }
-
-    ffghadll(fptr, &headstart, NULL, NULL, status); /* get header address */
-    ffmbyt(fptr, headstart, REPORT_EOF, status);   /* move to header */
-    ffgbyt(fptr, nrec * 2880, *header, status);     /* copy header */
-    *(*header + (nrec * 2880)) = '\0';
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffhdr2str( fitsfile *fptr,  /* I - FITS file pointer                    */
-            int exclude_comm,   /* I - if TRUE, exclude commentary keywords */
-            char **exclist,     /* I - list of excluded keyword names       */
-            int nexc,           /* I - number of names in exclist           */
-            char **header,      /* O - returned header string               */
-            int *nkeys,         /* O - returned number of 80-char keywords  */
-            int  *status)       /* IO - error status                        */
-/*
-  read header keywords into a long string of chars.  This routine allocates
-  memory for the string, so the calling routine must eventually free the
-  memory when it is not needed any more.  If exclude_comm is TRUE, then all 
-  the COMMENT, HISTORY, and  keywords will be excluded from the output
-  string of keywords.  Any other list of keywords to be excluded may be
-  specified with the exclist parameter.
-*/
-{
-    int casesn, match, exact, totkeys;
-    long ii, jj;
-    char keybuf[162], keyname[FLEN_KEYWORD], *headptr;
-
-    *nkeys = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    /* get number of keywords in the header (doesn't include END) */
-    if (ffghsp(fptr, &totkeys, NULL, status) > 0)
-        return(*status);
-
-    /* allocate memory for all the keywords */
-    /* (will reallocate it later to minimize the memory size) */
-    
-    *header = (char *) calloc ( (totkeys + 1) * 80 + 1, 1);
-    if (!(*header))
-    {
-         *status = MEMORY_ALLOCATION;
-         ffpmsg("failed to allocate memory to hold all the header keywords");
-         return(*status);
-    }
-
-    headptr = *header;
-    casesn = FALSE;
-
-    /* read every keyword */
-    for (ii = 1; ii <= totkeys; ii++) 
-    {
-        ffgrec(fptr, ii, keybuf, status);
-        /* pad record with blanks so that it is at least 80 chars long */
-        strcat(keybuf,
-    "                                                                                ");
-
-        keyname[0] = '\0';
-        strncat(keyname, keybuf, 8); /* copy the keyword name */
-        
-        if (exclude_comm)
-        {
-            if (!FSTRCMP("COMMENT ", keyname) ||
-                !FSTRCMP("HISTORY ", keyname) ||
-                !FSTRCMP("        ", keyname) )
-              continue;  /* skip this commentary keyword */
-        }
-
-        /* does keyword match any names in the exclusion list? */
-        for (jj = 0; jj < nexc; jj++ )
-        {
-            ffcmps(exclist[jj], keyname, casesn, &match, &exact);
-                 if (match)
-                     break;
-        }
-
-        if (jj == nexc)
-        {
-            /* not in exclusion list, add this keyword to the string */
-            strcpy(headptr, keybuf);
-            headptr += 80;
-            (*nkeys)++;
-        }
-    }
-
-    /* add the END keyword */
-    strcpy(headptr,
-    "END                                                                             ");
-    headptr += 80;
-    (*nkeys)++;
-
-    *headptr = '\0';   /* terminate the header string */
-    /* minimize the allocated memory */
-    *header = (char *) realloc(*header, (*nkeys *80) + 1);  
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffcnvthdr2str( fitsfile *fptr,  /* I - FITS file pointer                    */
-            int exclude_comm,   /* I - if TRUE, exclude commentary keywords */
-            char **exclist,     /* I - list of excluded keyword names       */
-            int nexc,           /* I - number of names in exclist           */
-            char **header,      /* O - returned header string               */
-            int *nkeys,         /* O - returned number of 80-char keywords  */
-            int  *status)       /* IO - error status                        */
-/*
-  Same as ffhdr2str, except that if the input HDU is a tile compressed image
-  (stored in a binary table) then it will first convert that header back
-  to that of a normal uncompressed FITS image before concatenating the header
-  keyword records.
-*/
-{
-    fitsfile *tempfptr;
-    
-    if (*status > 0)
-        return(*status);
-
-    if (fits_is_compressed_image(fptr, status) )
-    {
-        /* this is a tile compressed image, so need to make an uncompressed */
-	/* copy of the image header in memory before concatenating the keywords */
-        if (fits_create_file(&tempfptr, "mem://", status) > 0) {
-	    return(*status);
-	}
-
-	if (fits_img_decompress_header(fptr, tempfptr, status) > 0) {
-	    fits_delete_file(tempfptr, status);
-	    return(*status);
-	}
-
-	ffhdr2str(tempfptr, exclude_comm, exclist, nexc, header, nkeys, status);
-	fits_close_file(tempfptr, status);
-
-    } else {
-        ffhdr2str(fptr, exclude_comm, exclist, nexc, header, nkeys, status);
-    }
-
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/group.c b/src/external/OpenGR/3rdparty/cfitsio/group.c
deleted file mode 100644
index 9326c5774..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/group.c
+++ /dev/null
@@ -1,6464 +0,0 @@
-/*  This file, group.c, contains the grouping convention suport routines.  */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-/*                                                                         */
-/*  The group.c module of CFITSIO was written by Donald G. Jennings of     */
-/*  the INTEGRAL Science Data Centre (ISDC) under NASA contract task       */
-/*  66002J6. The above copyright laws apply. Copyright guidelines of The   */
-/*  University of Geneva might also apply.                                 */
-
-/*  The following routines are designed to create, read, and manipulate    */
-/*  FITS Grouping Tables as defined in the FITS Grouping Convention paper  */
-/*  by Jennings, Pence, Folk and Schlesinger. The development of the       */
-/*  grouping structure was partially funded under the NASA AISRP Program.  */ 
-    
-#include "fitsio2.h"
-#include "group.h"
-#include 
-#include 
-#include 
-
-#if defined(WIN32) || defined(__WIN32__)
-#include    /* defines the getcwd function on Windows PCs */
-#endif
-
-#if defined(unix) || defined(__unix__)  || defined(__unix) || defined(HAVE_UNISTD_H)
-#include   /* needed for getcwd prototype on unix machines */
-#endif
-
-#define HEX_ESCAPE '%'
-
-/*---------------------------------------------------------------------------
- Change record:
-
-D. Jennings, 18/06/98, version 1.0 of group module delivered to B. Pence for
-                       integration into CFITSIO 2.005
-
-D. Jennings, 17/11/98, fixed bug in ffgtcpr(). Now use fits_find_nextkey()
-                       correctly and insert auxiliary keyword records 
-		       directly before the TTYPE1 keyword in the copied
-		       group table.
-
-D. Jennings, 22/01/99, ffgmop() now looks for relative file paths when 
-                       the MEMBER_LOCATION information is given in a 
-		       grouping table.
-
-D. Jennings, 01/02/99, ffgtop() now looks for relatve file paths when 
-                       the GRPLCn keyword value is supplied in the member
-		       HDU header.
-
-D. Jennings, 01/02/99, ffgtam() now trys to construct relative file paths
-                       from the member's file to the group table's file
-		       (and visa versa) when both the member's file and
-		       group table file are of access type FILE://.
-
-D. Jennings, 05/05/99, removed the ffgtcn() function; made obsolete by
-                       fits_get_url().
-
-D. Jennings, 05/05/99, updated entire module to handle partial URLs and
-                       absolute URLs more robustly. Host dependent directory
-		       paths are now converted to true URLs before being
-		       read from/written to grouping tables.
-
-D. Jennings, 05/05/99, added the following new functions (note, none of these
-                       are directly callable by the application)
-
-		       int fits_path2url()
-		       int fits_url2path()
-		       int fits_get_cwd()
-		       int fits_get_url()
-		       int fits_clean_url()
-		       int fits_relurl2url()
-		       int fits_encode_url()
-		       int fits_unencode_url()
-		       int fits_is_url_absolute()
-
------------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-int ffgtcr(fitsfile *fptr,      /* FITS file pointer                         */
-	   char    *grpname,    /* name of the grouping table                */
-	   int      grouptype,  /* code specifying the type of
-				   grouping table information:
-				   GT_ID_ALL_URI  0 ==> defualt (all columns)
-				   GT_ID_REF      1 ==> ID by reference
-				   GT_ID_POS      2 ==> ID by position
-				   GT_ID_ALL      3 ==> ID by ref. and position
-				   GT_ID_REF_URI 11 ==> (1) + URI info 
-				   GT_ID_POS_URI 12 ==> (2) + URI info       */
-	   int      *status    )/* return status code                        */
-
-/* 
-   create a grouping table at the end of the current FITS file. This
-   function makes the last HDU in the file the CHDU, then calls the
-   fits_insert_group() function to actually create the new grouping table.
-*/
-
-{
-  int hdutype;
-  int hdunum;
-
-
-  if(*status != 0) return(*status);
-
-
-  *status = fits_get_num_hdus(fptr,&hdunum,status);
-
-  /* If hdunum is 0 then we are at the beginning of the file and
-     we actually haven't closed the first header yet, so don't do
-     anything more */
-
-  if (0 != hdunum) {
-
-      *status = fits_movabs_hdu(fptr,hdunum,&hdutype,status);
-  }
-
-  /* Now, the whole point of the above two fits_ calls was to get to
-     the end of file.  Let's ignore errors at this point and keep
-     going since any error is likely to mean that we are already at the 
-     EOF, or the file is fatally corrupted.  If we are at the EOF then
-     the next fits_ call will be ok.  If it's corrupted then the
-     next call will fail, but that's not big deal at this point.
-  */
-
-  if (0 != *status ) *status = 0;
-
-  *status = fits_insert_group(fptr,grpname,grouptype,status);
-
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int ffgtis(fitsfile *fptr,      /* FITS file pointer                         */
-	   char    *grpname,    /* name of the grouping table                */
-	   int      grouptype,  /* code specifying the type of
-				   grouping table information:
-				   GT_ID_ALL_URI  0 ==> defualt (all columns)
-				   GT_ID_REF      1 ==> ID by reference
-				   GT_ID_POS      2 ==> ID by position
-				   GT_ID_ALL      3 ==> ID by ref. and position
-				   GT_ID_REF_URI 11 ==> (1) + URI info 
-				   GT_ID_POS_URI 12 ==> (2) + URI info       */
-	   int      *status)     /* return status code                       */
-	   
-/* 
-   insert a grouping table just after the current HDU of the current FITS file.
-   This is the same as fits_create_group() only it allows the user to select
-   the place within the FITS file to add the grouping table.
-*/
-
-{
-
-  int tfields  = 0;
-  int hdunum   = 0;
-  int hdutype  = 0;
-  int extver;
-  int i;
-  
-  long pcount  = 0;
-
-  char *ttype[6];
-  char *tform[6];
-
-  char ttypeBuff[102];  
-  char tformBuff[54];  
-
-  char  extname[] = "GROUPING";
-  char  keyword[FLEN_KEYWORD];
-  char  keyvalue[FLEN_VALUE];
-  char  comment[FLEN_COMMENT];
-    
-  do
-    {
-
-      /* set up the ttype and tform character buffers */
-
-      for(i = 0; i < 6; ++i)
-	{
-	  ttype[i] = ttypeBuff+(i*17);
-	  tform[i] = tformBuff+(i*9);
-	}
-
-      /* define the columns required according to the grouptype parameter */
-
-      *status = ffgtdc(grouptype,0,0,0,0,0,0,ttype,tform,&tfields,status);
-
-      /* create the grouping table using the columns defined above */
-
-      *status = fits_insert_btbl(fptr,0,tfields,ttype,tform,NULL,
-				 NULL,pcount,status);
-
-      if(*status != 0) continue;
-
-      /*
-	 retrieve the hdu position of the new grouping table for
-	 future use
-      */
-
-      fits_get_hdu_num(fptr,&hdunum);
-
-      /*
-	 add the EXTNAME and EXTVER keywords to the HDU just after the 
-	 TFIELDS keyword; for now the EXTVER value is set to 0, it will be 
-	 set to the correct value later on
-      */
-
-      fits_read_keyword(fptr,"TFIELDS",keyvalue,comment,status);
-
-      fits_insert_key_str(fptr,"EXTNAME",extname,
-			  "HDU contains a Grouping Table",status);
-      fits_insert_key_lng(fptr,"EXTVER",0,"Grouping Table vers. (this file)",
-			  status);
-
-      /* 
-	 if the grpname parameter value was defined (Non NULL and non zero
-	 length) then add the GRPNAME keyword and value
-      */
-
-      if(grpname != NULL && strlen(grpname) > 0)
-	fits_insert_key_str(fptr,"GRPNAME",grpname,"Grouping Table name",
-			    status);
-
-      /* 
-	 add the TNULL keywords and values for each integer column defined;
-	 integer null values are zero (0) for the MEMBER_POSITION and 
-	 MEMBER_VERSION columns.
-      */
-
-      for(i = 0; i < tfields && *status == 0; ++i)
-	{	  
-	  if(fits_strcasecmp(ttype[i],"MEMBER_POSITION") == 0 ||
-	     fits_strcasecmp(ttype[i],"MEMBER_VERSION")  == 0)
-	    {
-	      sprintf(keyword,"TFORM%d",i+1);
-	      *status = fits_read_key_str(fptr,keyword,keyvalue,comment,
-					  status);
-	 
-	      sprintf(keyword,"TNULL%d",i+1);
-
-	      *status = fits_insert_key_lng(fptr,keyword,0,"Column Null Value",
-					    status);
-	    }
-	}
-
-      /*
-	 determine the correct EXTVER value for the new grouping table
-	 by finding the highest numbered grouping table EXTVER value
-	 the currently exists
-      */
-
-      for(extver = 1;
-	  (fits_movnam_hdu(fptr,ANY_HDU,"GROUPING",extver,status)) == 0; 
-	  ++extver);
-
-      if(*status == BAD_HDU_NUM) *status = 0;
-
-      /*
-	 move back to the new grouping table HDU and update the EXTVER
-	 keyword value
-      */
-
-      fits_movabs_hdu(fptr,hdunum,&hdutype,status);
-
-      fits_modify_key_lng(fptr,"EXTVER",extver,"&",status);
-
-    }while(0);
-
-
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int ffgtch(fitsfile *gfptr,     /* FITS pointer to group                     */
-	   int       grouptype, /* code specifying the type of
-				   grouping table information:
-				   GT_ID_ALL_URI  0 ==> defualt (all columns)
-				   GT_ID_REF      1 ==> ID by reference
-				   GT_ID_POS      2 ==> ID by position
-				   GT_ID_ALL      3 ==> ID by ref. and position
-				   GT_ID_REF_URI 11 ==> (1) + URI info 
-				   GT_ID_POS_URI 12 ==> (2) + URI info       */
-	   int      *status)     /* return status code                       */
-
-
-/* 
-   Change the grouping table structure of the grouping table pointed to by
-   gfptr. The grouptype code specifies the new structure of the table. This
-   operation only adds or removes grouping table columns, it does not add
-   or delete group members (i.e., table rows). If the grouping table already
-   has the desired structure then no operations are performed and function   
-   simply returns with a (0) success status code. If the requested structure
-   change creates new grouping table columns, then the column values for all
-   existing members will be filled with the appropriate null values.
-*/
-
-{
-  int xtensionCol, extnameCol, extverCol, positionCol, locationCol, uriCol;
-  int ncols    = 0;
-  int colnum   = 0;
-  int nrows    = 0;
-  int grptype  = 0;
-  int i,j;
-
-  long intNull  = 0;
-  long tfields  = 0;
-  
-  char *tform[6];
-  char *ttype[6];
-
-  unsigned char  charNull[1] = {'\0'};
-
-  char ttypeBuff[102];  
-  char tformBuff[54];  
-
-  char  keyword[FLEN_KEYWORD];
-  char  keyvalue[FLEN_VALUE];
-  char  comment[FLEN_COMMENT];
-
-
-  if(*status != 0) return(*status);
-
-  do
-    {
-      /* set up the ttype and tform character buffers */
-
-      for(i = 0; i < 6; ++i)
-	{
-	  ttype[i] = ttypeBuff+(i*17);
-	  tform[i] = tformBuff+(i*9);
-	}
-
-      /* retrieve positions of all Grouping table reserved columns */
-
-      *status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol,
-		       &locationCol,&uriCol,&grptype,status);
-
-      if(*status != 0) continue;
-
-      /* determine the total number of grouping table columns */
-
-      *status = fits_read_key_lng(gfptr,"TFIELDS",&tfields,comment,status);
-
-      /* define grouping table columns to be added to the configuration */
-
-      *status = ffgtdc(grouptype,xtensionCol,extnameCol,extverCol,positionCol,
-		       locationCol,uriCol,ttype,tform,&ncols,status);
-
-      /*
-	delete any grouping tables columns that exist but do not belong to
-	new desired configuration; note that we delete before creating new
-	columns for (file size) efficiency reasons
-      */
-
-      switch(grouptype)
-	{
-
-	case GT_ID_ALL_URI:
-
-	  /* no columns to be deleted in this case */
-
-	  break;
-
-	case GT_ID_REF:
-
-	  if(positionCol != 0) 
-	    {
-	      *status = fits_delete_col(gfptr,positionCol,status);
-	      --tfields;
-	      if(uriCol      > positionCol)  --uriCol;
-	      if(locationCol > positionCol) --locationCol;
-	    }
-	  if(uriCol      != 0)
-	    { 
-	    *status = fits_delete_col(gfptr,uriCol,status);
-	      --tfields;
-	      if(locationCol > uriCol) --locationCol;
-	    }
-	  if(locationCol != 0) 
-	    *status = fits_delete_col(gfptr,locationCol,status);
-
-	  break;
-
-	case  GT_ID_POS:
-
-	  if(xtensionCol != 0) 
-	    {
-	      *status = fits_delete_col(gfptr,xtensionCol,status);
-	      --tfields;
-	      if(extnameCol  > xtensionCol)  --extnameCol;
-	      if(extverCol   > xtensionCol)  --extverCol;
-	      if(uriCol      > xtensionCol)  --uriCol;
-	      if(locationCol > xtensionCol)  --locationCol;
-	    }
-	  if(extnameCol  != 0) 
-	    {
-	      *status = fits_delete_col(gfptr,extnameCol,status);
-	      --tfields;
-	      if(extverCol   > extnameCol)  --extverCol;
-	      if(uriCol      > extnameCol)  --uriCol;
-	      if(locationCol > extnameCol)  --locationCol;
-	    }
-	  if(extverCol   != 0)
-	    { 
-	      *status = fits_delete_col(gfptr,extverCol,status);
-	      --tfields;
-	      if(uriCol      > extverCol)  --uriCol;
-	      if(locationCol > extverCol)  --locationCol;
-	    }
-	  if(uriCol      != 0)
-	    { 
-	      *status = fits_delete_col(gfptr,uriCol,status);
-	      --tfields;
-	      if(locationCol > uriCol)  --locationCol;
-	    }
-	  if(locationCol != 0)
-	    { 
-	      *status = fits_delete_col(gfptr,locationCol,status);
-	      --tfields;
-	    }
-	  
-	  break;
-
-	case  GT_ID_ALL:
-
-	  if(uriCol      != 0) 
-	    {
-	      *status = fits_delete_col(gfptr,uriCol,status);
-	      --tfields;
-	      if(locationCol > uriCol)  --locationCol;
-	    }
-	  if(locationCol != 0)
-	    { 
-	      *status = fits_delete_col(gfptr,locationCol,status);
-	      --tfields;
-	    }
-
-	  break;
-
-	case GT_ID_REF_URI:
-
-	  if(positionCol != 0)
-	    { 
-	      *status = fits_delete_col(gfptr,positionCol,status);
-	      --tfields;
-	    }
-
-	  break;
-
-	case  GT_ID_POS_URI:
-
-	  if(xtensionCol != 0) 
-	    {
-	      *status = fits_delete_col(gfptr,xtensionCol,status);
-	      --tfields;
-	      if(extnameCol > xtensionCol)  --extnameCol;
-	      if(extverCol  > xtensionCol)  --extverCol;
-	    }
-	  if(extnameCol  != 0)
-	    { 
-	      *status = fits_delete_col(gfptr,extnameCol,status);
-	      --tfields;
-	      if(extverCol > extnameCol)  --extverCol;
-	    }
-	  if(extverCol   != 0)
-	    { 
-	      *status = fits_delete_col(gfptr,extverCol,status);
-	      --tfields;
-	    }
-
-	  break;
-
-	default:
-
-	  *status = BAD_OPTION;
-	  ffpmsg("Invalid value for grouptype parameter specified (ffgtch)");
-	  break;
-
-	}
-
-      /*
-	add all the new grouping table columns that were not there
-	previously but are called for by the grouptype parameter
-      */
-
-      for(i = 0; i < ncols && *status == 0; ++i)
-	*status = fits_insert_col(gfptr,tfields+i+1,ttype[i],tform[i],status);
-
-      /* 
-	 add the TNULL keywords and values for each new integer column defined;
-	 integer null values are zero (0) for the MEMBER_POSITION and 
-	 MEMBER_VERSION columns. Insert a null ("/0") into each new string
-	 column defined: MEMBER_XTENSION, MEMBER_NAME, MEMBER_URI_TYPE and
-	 MEMBER_LOCATION. Note that by convention a null string is the
-	 TNULL value for character fields so no TNULL is required.
-      */
-
-      for(i = 0; i < ncols && *status == 0; ++i)
-	{	  
-	  if(fits_strcasecmp(ttype[i],"MEMBER_POSITION") == 0 ||
-	     fits_strcasecmp(ttype[i],"MEMBER_VERSION")  == 0)
-	    {
-	      /* col contains int data; set TNULL and insert 0 for each col */
-
-	      *status = fits_get_colnum(gfptr,CASESEN,ttype[i],&colnum,
-					status);
-	      
-	      sprintf(keyword,"TFORM%d",colnum);
-
-	      *status = fits_read_key_str(gfptr,keyword,keyvalue,comment,
-					  status);
-	 
-	      sprintf(keyword,"TNULL%d",colnum);
-
-	      *status = fits_insert_key_lng(gfptr,keyword,0,
-					    "Column Null Value",status);
-
-	      for(j = 1; j <= nrows && *status == 0; ++j)
-		*status = fits_write_col_lng(gfptr,colnum,j,1,1,&intNull,
-					     status);
-	    }
-	  else if(fits_strcasecmp(ttype[i],"MEMBER_XTENSION") == 0 ||
-		  fits_strcasecmp(ttype[i],"MEMBER_NAME")     == 0 ||
-		  fits_strcasecmp(ttype[i],"MEMBER_URI_TYPE") == 0 ||
-		  fits_strcasecmp(ttype[i],"MEMBER_LOCATION") == 0)
-	    {
-
-	      /* new col contains character data; insert NULLs into each col */
-
-	      *status = fits_get_colnum(gfptr,CASESEN,ttype[i],&colnum,
-					status);
-
-	      for(j = 1; j <= nrows && *status == 0; ++j)
-	    /* WILL THIS WORK FOR VAR LENTH CHAR COLS??????*/
-		*status = fits_write_col_byt(gfptr,colnum,j,1,1,charNull,
-					     status);
-	    }
-	}
-
-    }while(0);
-
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int ffgtrm(fitsfile *gfptr,  /* FITS file pointer to group                   */
-	   int       rmopt,  /* code specifying if member
-				elements are to be deleted:
-				OPT_RM_GPT ==> remove only group table
-				OPT_RM_ALL ==> recursively remove members
-				and their members (if groups)                */
-	   int      *status) /* return status code                           */
-	    
-/*
-  remove a grouping table, and optionally all its members. Any groups 
-  containing the grouping table are updated, and all members (if not 
-  deleted) have their GRPIDn and GRPLCn keywords updated accordingly. 
-  If the (deleted) members are members of another grouping table then those
-  tables are also updated. The CHDU of the FITS file pointed to by gfptr must 
-  be positioned to the grouping table to be deleted.
-*/
-
-{
-  int hdutype;
-
-  long i;
-  long nmembers = 0;
-
-  HDUtracker HDU;
-  
-
-  if(*status != 0) return(*status);
-
-  /*
-     remove the grouping table depending upon the rmopt parameter
-  */
-
-  switch(rmopt)
-    {
-
-    case OPT_RM_GPT:
-
-      /*
-	 for this option, the grouping table is deleted, but the member
-	 HDUs remain; in this case we only have to remove each member from
-	 the grouping table by calling fits_remove_member() with the
-	 OPT_RM_ENTRY option
-      */
-
-      /* get the number of members contained by this table */
-
-      *status = fits_get_num_members(gfptr,&nmembers,status);
-
-      /* loop over all grouping table members and remove them */
-
-      for(i = nmembers; i > 0 && *status == 0; --i)
-	*status = fits_remove_member(gfptr,i,OPT_RM_ENTRY,status);
-      
-	break;
-
-    case OPT_RM_ALL:
-
-      /*
-	for this option the entire Group is deleted -- this includes all
-	members and their members (if grouping tables themselves). Call 
-	the recursive form of this function to perform the removal.
-      */
-
-      /* add the current grouping table to the HDUtracker struct */
-
-      HDU.nHDU = 0;
-
-      *status = fftsad(gfptr,&HDU,NULL,NULL);
-
-      /* call the recursive group remove function */
-
-      *status = ffgtrmr(gfptr,&HDU,status);
-
-      /* free the memory allocated to the HDUtracker struct */
-
-      for(i = 0; i < HDU.nHDU; ++i)
-	{
-	  free(HDU.filename[i]);
-	  free(HDU.newFilename[i]);
-	}
-
-      break;
-
-    default:
-      
-      *status = BAD_OPTION;
-      ffpmsg("Invalid value for the rmopt parameter specified (ffgtrm)");
-      break;
-
-     }
-
-  /*
-     if all went well then unlink and delete the grouping table HDU
-  */
-
-  *status = ffgmul(gfptr,0,status);
-
-  *status = fits_delete_hdu(gfptr,&hdutype,status);
-      
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int ffgtcp(fitsfile *infptr,  /* input FITS file pointer                     */
-	   fitsfile *outfptr, /* output FITS file pointer                    */
-	   int        cpopt,  /* code specifying copy options:
-				OPT_GCP_GPT (0) ==> copy only grouping table
-				OPT_GCP_ALL (2) ==> recusrively copy members 
-				                    and their members (if 
-						    groups)                  */
-	   int      *status)  /* return status code                          */
-
-/*
-  copy a grouping table, and optionally all its members, to a new FITS file.
-  If the cpopt is set to OPT_GCP_GPT (copy grouping table only) then the 
-  existing members have their GRPIDn and GRPLCn keywords updated to reflect 
-  the existance of the new group, since they now belong to another group. If 
-  cpopt is set to OPT_GCP_ALL (copy grouping table and members recursively) 
-  then the original members are not updated; the new grouping table is 
-  modified to include only the copied member HDUs and not the original members.
-
-  Note that the recursive version of this function, ffgtcpr(), is called
-  to perform the group table copy. In the case of cpopt == OPT_GCP_GPT
-  ffgtcpr() does not actually use recursion.
-*/
-
-{
-  int i;
-
-  HDUtracker HDU;
-
-
-  if(*status != 0) return(*status);
-
-  /* make sure infptr and outfptr are not the same pointer */
-
-  if(infptr == outfptr) *status = IDENTICAL_POINTERS;
-  else
-    {
-
-      /* initialize the HDUtracker struct */
-      
-      HDU.nHDU = 0;
-      
-      *status = fftsad(infptr,&HDU,NULL,NULL);
-      
-      /* 
-	 call the recursive form of this function to copy the grouping table. 
-	 If the cpopt is OPT_GCP_GPT then there is actually no recursion
-	 performed
-      */
-
-      *status = ffgtcpr(infptr,outfptr,cpopt,&HDU,status);
-  
-      /* free memory allocated for the HDUtracker struct */
-
-      for(i = 0; i < HDU.nHDU; ++i) 
-	{
-	  free(HDU.filename[i]);
-	  free(HDU.newFilename[i]);
-	}
-    }
-
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int ffgtmg(fitsfile *infptr,  /* FITS file ptr to source grouping table      */
-	   fitsfile *outfptr, /* FITS file ptr to target grouping table      */
-	   int       mgopt,   /* code specifying merge options:
-				 OPT_MRG_COPY (0) ==> copy members to target
-				                      group, leaving source 
-						      group in place
-				 OPT_MRG_MOV  (1) ==> move members to target
-				                      group, source group is
-						      deleted after merge    */
-	   int      *status)   /* return status code                         */
-     
-
-/*
-  merge two grouping tables by combining their members into a single table. 
-  The source grouping table must be the CHDU of the fitsfile pointed to by 
-  infptr, and the target grouping table must be the CHDU of the fitsfile to by 
-  outfptr. All members of the source grouping table shall be copied to the
-  target grouping table. If the mgopt parameter is OPT_MRG_COPY then the source
-  grouping table continues to exist after the merge. If the mgopt parameter
-  is OPT_MRG_MOV then the source grouping table is deleted after the merge, 
-  and all member HDUs are updated accordingly.
-*/
-{
-  long i ;
-  long nmembers = 0;
-
-  fitsfile *tmpfptr = NULL;
-
-
-  if(*status != 0) return(*status);
-
-  do
-    {
-
-      *status = fits_get_num_members(infptr,&nmembers,status);
-
-      for(i = 1; i <= nmembers && *status == 0; ++i)
-	{
-	  *status = fits_open_member(infptr,i,&tmpfptr,status);
-	  *status = fits_add_group_member(outfptr,tmpfptr,0,status);
-
-	  if(*status == HDU_ALREADY_MEMBER) *status = 0;
-
-	  if(tmpfptr != NULL)
-	    {
-	      fits_close_file(tmpfptr,status);
-	      tmpfptr = NULL;
-	    }
-	}
-
-      if(*status != 0) continue;
-
-      if(mgopt == OPT_MRG_MOV) 
-	*status = fits_remove_group(infptr,OPT_RM_GPT,status);
-
-    }while(0);
-
-  if(tmpfptr != NULL)
-    {
-      fits_close_file(tmpfptr,status);
-    }
-
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int ffgtcm(fitsfile *gfptr,  /* FITS file pointer to grouping table          */
-	   int       cmopt,  /* code specifying compact options
-				OPT_CMT_MBR      (1) ==> compact only direct 
-			                                 members (if groups)
-				OPT_CMT_MBR_DEL (11) ==> (1) + delete all 
-				                         compacted groups    */
-	   int      *status) /* return status code                           */
-    
-/*
-  "Compact" a group pointed to by the FITS file pointer gfptr. This 
-  is achieved by flattening the tree structure of a group and its 
-  (grouping table) members. All members HDUs of a grouping table which is 
-  itself a member of the grouping table gfptr are added to gfptr. Optionally,
-  the grouping tables which are "compacted" are deleted. If the grouping 
-  table contains no members that are themselves grouping tables then this 
-  function performs a NOOP.
-*/
-
-{
-  long i;
-  long nmembers = 0;
-
-  char keyvalue[FLEN_VALUE];
-  char comment[FLEN_COMMENT];
-
-  fitsfile *mfptr = NULL;
-
-
-  if(*status != 0) return(*status);
-
-  do
-    {
-      if(cmopt != OPT_CMT_MBR && cmopt != OPT_CMT_MBR_DEL)
-	{
-	  *status = BAD_OPTION;
-	  ffpmsg("Invalid value for cmopt parameter specified (ffgtcm)");
-	  continue;
-	}
-
-      /* reteive the number of grouping table members */
-
-      *status = fits_get_num_members(gfptr,&nmembers,status);
-
-      /*
-	loop over all the grouping table members; if the member is a 
-	grouping table then merge its members with the parent grouping 
-	table 
-      */
-
-      for(i = 1; i <= nmembers && *status == 0; ++i)
-	{
-	  *status = fits_open_member(gfptr,i,&mfptr,status);
-
-	  if(*status != 0) continue;
-
-	  *status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,comment,status);
-
-	  /* if no EXTNAME keyword then cannot be a grouping table */
-
-	  if(*status == KEY_NO_EXIST) 
-	    {
-	      *status = 0;
-	      continue;
-	    }
-	  prepare_keyvalue(keyvalue);
-
-	  if(*status != 0) continue;
-
-	  /* if EXTNAME == "GROUPING" then process member as grouping table */
-
-	  if(fits_strcasecmp(keyvalue,"GROUPING") == 0)
-	    {
-	      /* merge the member (grouping table) into the grouping table */
-
-	      *status = fits_merge_groups(mfptr,gfptr,OPT_MRG_COPY,status);
-
-	      *status = fits_close_file(mfptr,status);
-	      mfptr = NULL;
-
-	      /* 
-		 remove the member from the grouping table now that all of
-		 its members have been transferred; if cmopt is set to
-		 OPT_CMT_MBR_DEL then remove and delete the member
-	      */
-
-	      if(cmopt == OPT_CMT_MBR)
-		*status = fits_remove_member(gfptr,i,OPT_RM_ENTRY,status);
-	      else
-		*status = fits_remove_member(gfptr,i,OPT_RM_MBR,status);
-	    }
-	  else
-	    {
-	      /* not a grouping table; just close the opened member */
-
-	      *status = fits_close_file(mfptr,status);
-	      mfptr = NULL;
-	    }
-	}
-
-    }while(0);
-
-  return(*status);
-}
-
-/*--------------------------------------------------------------------------*/
-int ffgtvf(fitsfile *gfptr,       /* FITS file pointer to group             */
-	   long     *firstfailed, /* Member ID (if positive) of first failed
-				     member HDU verify check or GRPID index
-				     (if negitive) of first failed group
-				     link verify check.                     */
-	   int      *status)      /* return status code                     */
-
-/*
- check the integrity of a grouping table to make sure that all group members 
- are accessible and all the links to other grouping tables are valid. The
- firstfailed parameter returns the member ID of the first member HDU to fail
- verification if positive or the first group link to fail if negative; 
- otherwise firstfailed contains a return value of 0.
-*/
-
-{
-  long i;
-  long nmembers = 0;
-  long ngroups  = 0;
-
-  char errstr[FLEN_VALUE];
-
-  fitsfile *fptr = NULL;
-
-
-  if(*status != 0) return(*status);
-
-  *firstfailed = 0;
-
-  do
-    {
-      /*
-	attempt to open all the members of the grouping table. We stop
-	at the first member which cannot be opened (which implies that it
-	cannot be located)
-      */
-
-      *status = fits_get_num_members(gfptr,&nmembers,status);
-
-      for(i = 1; i <= nmembers && *status == 0; ++i)
-	{
-	  *status = fits_open_member(gfptr,i,&fptr,status);
-	  fits_close_file(fptr,status);
-	}
-
-      /*
-	if the status is non-zero from the above loop then record the
-	member index that caused the error
-      */
-
-      if(*status != 0)
-	{
-	  *firstfailed = i;
-	  sprintf(errstr,"Group table verify failed for member %ld (ffgtvf)",
-		  i);
-	  ffpmsg(errstr);
-	  continue;
-	}
-
-      /*
-	attempt to open all the groups linked to this grouping table. We stop
-	at the first group which cannot be opened (which implies that it
-	cannot be located)
-      */
-
-      *status = fits_get_num_groups(gfptr,&ngroups,status);
-
-      for(i = 1; i <= ngroups && *status == 0; ++i)
-	{
-	  *status = fits_open_group(gfptr,i,&fptr,status);
-	  fits_close_file(fptr,status);
-	}
-
-      /*
-	if the status from the above loop is non-zero, then record the
-	GRPIDn index of the group that caused the failure
-      */
-
-      if(*status != 0)
-	{
-	  *firstfailed = -1*i;
-	  sprintf(errstr,
-		  "Group table verify failed for GRPID index %ld (ffgtvf)",i);
-	  ffpmsg(errstr);
-	  continue;
-	}
-
-    }while(0);
-
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int ffgtop(fitsfile *mfptr,  /* FITS file pointer to the member HDU          */
-	   int       grpid,  /* group ID (GRPIDn index) within member HDU    */
-	   fitsfile **gfptr, /* FITS file pointer to grouping table HDU      */
-	   int      *status) /* return status code                           */
-
-/*
-  open the grouping table that contains the member HDU. The member HDU must
-  be the CHDU of the FITS file pointed to by mfptr, and the grouping table
-  is identified by the Nth index number of the GRPIDn keywords specified in 
-  the member HDU's header. The fitsfile gfptr pointer is positioned with the
-  appropriate FITS file with the grouping table as the CHDU. If the group
-  grouping table resides in a file other than the member then an attempt
-  is first made to open the file readwrite, and failing that readonly.
- 
-  Note that it is possible for the GRPIDn/GRPLCn keywords in a member 
-  header to be non-continuous, e.g., GRPID1, GRPID2, GRPID5, GRPID6. In 
-  such cases, the grpid index value specified in the function call shall
-  identify the (grpid)th GRPID value. In the above example, if grpid == 3,
-  then the group specified by GRPID5 would be opened.
-*/
-{
-  int i;
-  int found;
-
-  long ngroups   = 0;
-  long grpExtver = 0;
-
-  char keyword[FLEN_KEYWORD];
-  char keyvalue[FLEN_FILENAME];
-  char *tkeyvalue;
-  char location[FLEN_FILENAME];
-  char location1[FLEN_FILENAME];
-  char location2[FLEN_FILENAME];
-  char comment[FLEN_COMMENT];
-
-  char *url[2];
-
-
-  if(*status != 0) return(*status);
-
-  do
-    {
-      /* set the grouping table pointer to NULL for error checking later */
-
-      *gfptr = NULL;
-
-      /*
-	make sure that the group ID requested is valid ==> cannot be
-	larger than the number of GRPIDn keywords in the member HDU header
-      */
-
-      *status = fits_get_num_groups(mfptr,&ngroups,status);
-
-      if(grpid > ngroups)
-	{
-	  *status = BAD_GROUP_ID;
-	  sprintf(comment,
-		  "GRPID index %d larger total GRPID keywords %ld (ffgtop)",
-		  grpid,ngroups);
-	  ffpmsg(comment);
-	  continue;
-	}
-
-      /*
-	find the (grpid)th group that the member HDU belongs to and read
-	the value of the GRPID(grpid) keyword; fits_get_num_groups()
-	automatically re-enumerates the GRPIDn/GRPLCn keywords to fill in
-	any gaps
-      */
-
-      sprintf(keyword,"GRPID%d",grpid);
-
-      *status = fits_read_key_lng(mfptr,keyword,&grpExtver,comment,status);
-
-      if(*status != 0) continue;
-
-      /*
-	if the value of the GRPIDn keyword is positive then the member is
-	in the same FITS file as the grouping table and we only have to
-	reopen the current FITS file. Else the member and grouping table
-	HDUs reside in different files and another FITS file must be opened
-	as specified by the corresponding GRPLCn keyword
-	
-	The DO WHILE loop only executes once and is used to control the
-	file opening logic.
-      */
-
-      do
-	{
-	  if(grpExtver > 0) 
-	    {
-	      /*
-		the member resides in the same file as the grouping
-		 table, so just reopen the grouping table file
-	      */
-
-	      *status = fits_reopen_file(mfptr,gfptr,status);
-	      continue;
-	    }
-
-	  else if(grpExtver == 0)
-	    {
-	      /* a GRPIDn value of zero (0) is undefined */
-
-	      *status = BAD_GROUP_ID;
-	      sprintf(comment,"Invalid value of %ld for GRPID%d (ffgtop)",
-		      grpExtver,grpid);
-	      ffpmsg(comment);
-	      continue;
-	    }
-
-	  /* 
-	     The GRPLCn keyword value is negative, which implies that
-	     the grouping table must reside in another FITS file;
-	     search for the corresponding GRPLCn keyword 
-	  */
-	  
-	  /* set the grpExtver value positive */
-  
-	  grpExtver = -1*grpExtver;
-
-	  /* read the GRPLCn keyword value */
-
-	  sprintf(keyword,"GRPLC%d",grpid);
-	  /* SPR 1738 */
-	  *status = fits_read_key_longstr(mfptr,keyword,&tkeyvalue,comment,
-				      status);
-	  if (0 == *status) {
-	    strcpy(keyvalue,tkeyvalue);
-	    free(tkeyvalue);
-	  }
-	  
-
-	  /* if the GRPLCn keyword was not found then there is a problem */
-
-	  if(*status == KEY_NO_EXIST)
-	    {
-	      *status = BAD_GROUP_ID;
-
-	      sprintf(comment,"Cannot find GRPLC%d keyword (ffgtop)",
-		      grpid);
-	      ffpmsg(comment);
-
-	      continue;
-	    }
-
-	  prepare_keyvalue(keyvalue);
-
-	  /*
-	    if the GRPLCn keyword value specifies an absolute URL then
-	    try to open the file; we cannot attempt any relative URL
-	    or host-dependent file path reconstruction
-	  */
-
-	  if(fits_is_url_absolute(keyvalue))
-	    {
-	      ffpmsg("Try to open group table file as absolute URL (ffgtop)");
-
-	      *status = fits_open_file(gfptr,keyvalue,READWRITE,status);
-
-	      /* if the open was successful then continue */
-
-	      if(*status == 0) continue;
-
-	      /* if READWRITE failed then try opening it READONLY */
-
-	      ffpmsg("OK, try open group table file as READONLY (ffgtop)");
-	      
-	      *status = 0;
-	      *status = fits_open_file(gfptr,keyvalue,READONLY,status);
-
-	      /* continue regardless of the outcome */
-
-	      continue;
-	    }
-
-	  /*
-	    see if the URL gives a file path that is absolute on the
-	    host machine 
-	  */
-
-	  *status = fits_url2path(keyvalue,location1,status);
-
-	  *status = fits_open_file(gfptr,location1,READWRITE,status);
-
-	  /* if the file opened then continue */
-
-	  if(*status == 0) continue;
-
-	  /* if READWRITE failed then try opening it READONLY */
-
-	  ffpmsg("OK, try open group table file as READONLY (ffgtop)");
-	  
-	  *status = 0;
-	  *status = fits_open_file(gfptr,location1,READONLY,status);
-
-	  /* if the file opened then continue */
-
-	  if(*status == 0) continue;
-
-	  /*
-	    the grouping table location given by GRPLCn must specify a 
-	    relative URL. We assume that this URL is relative to the 
-	    member HDU's FITS file. Try to construct a full URL location 
-	    for the grouping table's FITS file and then open it
-	  */
-
-	  *status = 0;
-		  
-	  /* retrieve the URL information for the member HDU's file */
-		  
-	  url[0] = location1; url[1] = location2;
-		  
-	  *status = fits_get_url(mfptr,url[0],url[1],NULL,NULL,NULL,status);
-
-	  /*
-	    It is possible that the member HDU file has an initial
-	    URL it was opened with and a real URL that the file actually
-	    exists at (e.g., an HTTP accessed file copied to a local
-	    file). For each possible URL try to construct a
-	  */
-		  
-	  for(i = 0, found = 0, *gfptr = NULL; i < 2 && !found; ++i)
-	    {
-	      
-	      /* the url string could be empty */
-	      
-	      if(*url[i] == 0) continue;
-	      
-	      /* 
-		 create a full URL from the partial and the member
-		 HDU file URL
-	      */
-	      
-	      *status = fits_relurl2url(url[i],keyvalue,location,status);
-	      
-	      /* if an error occured then contniue */
-	      
-	      if(*status != 0) 
-		{
-		  *status = 0;
-		  continue;
-		}
-	      
-	      /*
-		if the location does not specify an access method
-		then turn it into a host dependent path
-	      */
-
-	      if(! fits_is_url_absolute(location))
-		{
-		  *status = fits_url2path(location,url[i],status);
-		  strcpy(location,url[i]);
-		}
-	      
-	      /* try to open the grouping table file READWRITE */
-	      
-	      *status = fits_open_file(gfptr,location,READWRITE,status);
-	      
-	      if(*status != 0)
-		{    
-		  /* try to open the grouping table file READONLY */
-		  
-		  ffpmsg("opening file as READWRITE failed (ffgtop)");
-		  ffpmsg("OK, try to open file as READONLY (ffgtop)");
-		  *status = 0;
-		  *status = fits_open_file(gfptr,location,READONLY,status);
-		}
-	      
-	      /* either set the found flag or reset the status flag */
-	      
-	      if(*status == 0) 
-		found = 1;
-	      else
-		*status = 0;
-	    }
-
-	}while(0); /* end of file opening loop */
-
-      /* if an error occured with the file opening then exit */
-
-      if(*status != 0) continue;
-  
-      if(*gfptr == NULL)
-	{
-	  ffpmsg("Cannot open or find grouping table FITS file (ffgtop)");
-	  *status = GROUP_NOT_FOUND;
-	  continue;
-	}
-
-      /* search for the grouping table in its FITS file */
-
-      *status = fits_movnam_hdu(*gfptr,ANY_HDU,"GROUPING",(int)grpExtver,
-				status);
-
-      if(*status != 0) *status = GROUP_NOT_FOUND;
-
-    }while(0);
-
-  if(*status != 0 && *gfptr != NULL) 
-    {
-      fits_close_file(*gfptr,status);
-      *gfptr = NULL;
-    }
-
-  return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int ffgtam(fitsfile *gfptr,   /* FITS file pointer to grouping table HDU     */
-	   fitsfile *mfptr,   /* FITS file pointer to member HDU             */
-	   int       hdupos,  /* member HDU position IF in the same file as
-			         the grouping table AND mfptr == NULL        */
-	   int      *status)  /* return status code                          */
- 
-/*
-  add a member HDU to an existing grouping table. The fitsfile pointer gfptr
-  must be positioned with the grouping table as the CHDU. The member HDU
-  may either be identifed with the fitsfile *mfptr (which must be positioned
-  to the member HDU) or the hdupos parameter (the HDU number of the member 
-  HDU) if both reside in the same FITS file. The hdupos value is only used
-  if the mfptr parameter has a value of NULL (0). The new member HDU shall 
-  have the appropriate GRPIDn and GRPLCn keywords created in its header.
-
-  Note that if the member HDU to be added to the grouping table is already
-  a member of the group then it will not be added a sceond time.
-*/
-
-{
-  int xtensionCol,extnameCol,extverCol,positionCol,locationCol,uriCol;
-  int memberPosition = 0;
-  int grptype        = 0;
-  int hdutype        = 0;
-  int useLocation    = 0;
-  int nkeys          = 6;
-  int found;
-  int i;
-
-  int memberIOstate;
-  int groupIOstate;
-  int iomode;
-
-  long memberExtver = 0;
-  long groupExtver  = 0;
-  long memberID     = 0;
-  long nmembers     = 0;
-  long ngroups      = 0;
-  long grpid        = 0;
-
-  char memberAccess1[FLEN_VALUE];
-  char memberAccess2[FLEN_VALUE];
-  char memberFileName[FLEN_FILENAME];
-  char memberLocation[FLEN_FILENAME];
-  char grplc[FLEN_FILENAME];
-  char *tgrplc;
-  char memberHDUtype[FLEN_VALUE];
-  char memberExtname[FLEN_VALUE];
-  char memberURI[] = "URL";
-
-  char groupAccess1[FLEN_VALUE];
-  char groupAccess2[FLEN_VALUE];
-  char groupFileName[FLEN_FILENAME];
-  char groupLocation[FLEN_FILENAME];
-  char tmprootname[FLEN_FILENAME], grootname[FLEN_FILENAME];
-  char cwd[FLEN_FILENAME];
-
-  char *keys[] = {"GRPNAME","EXTVER","EXTNAME","TFIELDS","GCOUNT","EXTEND"};
-  char *tmpPtr[1];
-
-  char keyword[FLEN_KEYWORD];
-  char card[FLEN_CARD];
-
-  unsigned char charNull[]  = {'\0'};
-
-  fitsfile *tmpfptr = NULL;
-
-  int parentStatus = 0;
-
-  if(*status != 0) return(*status);
-
-  do
-    {
-      /*
-	make sure the grouping table can be modified before proceeding
-      */
-
-      fits_file_mode(gfptr,&iomode,status);
-
-      if(iomode != READWRITE)
-	{
-	  ffpmsg("cannot modify grouping table (ffgtam)");
-	  *status = BAD_GROUP_ATTACH;
-	  continue;
-	}
-
-      /*
-	 if the calling function supplied the HDU position of the member
-	 HDU instead of fitsfile pointer then get a fitsfile pointer
-      */
-
-      if(mfptr == NULL)
-	{
-	  *status = fits_reopen_file(gfptr,&tmpfptr,status);
-	  *status = fits_movabs_hdu(tmpfptr,hdupos,&hdutype,status);
-
-	  if(*status != 0) continue;
-	}
-      else
-	tmpfptr = mfptr;
-
-      /*
-	 determine all the information about the member HDU that will
-	 be needed later; note that we establish the default values for
-	 all information values that are not explicitly found
-      */
-
-      *status = fits_read_key_str(tmpfptr,"XTENSION",memberHDUtype,card,
-				  status);
-
-      if(*status == KEY_NO_EXIST) 
-	{
-	  strcpy(memberHDUtype,"PRIMARY");
-	  *status = 0;
-	}
-      prepare_keyvalue(memberHDUtype);
-
-      *status = fits_read_key_lng(tmpfptr,"EXTVER",&memberExtver,card,status);
-
-      if(*status == KEY_NO_EXIST) 
-	{
-	  memberExtver = 1;
-	  *status      = 0;
-	}
-
-      *status = fits_read_key_str(tmpfptr,"EXTNAME",memberExtname,card,
-				  status);
-
-      if(*status == KEY_NO_EXIST) 
-	{
-	  memberExtname[0] = 0;
-	  *status          = 0;
-	}
-      prepare_keyvalue(memberExtname);
-
-      fits_get_hdu_num(tmpfptr,&memberPosition);
-
-      /*
-	Determine if the member HDU's FITS file location needs to be
-	taken into account when building its grouping table reference
-
-	If the member location needs to be used (==> grouping table and member
-	HDU reside in different files) then create an appropriate URL for
-	the member HDU's file and grouping table's file. Note that the logic
-	for this is rather complicated
-      */
-
-      /* SPR 3463, don't do this 
-	 if(tmpfptr->Fptr == gfptr->Fptr)
-	 {  */
-	  /*
-	    member HDU and grouping table reside in the same file, no need
-	    to use the location information */
-	  
-      /* printf ("same file\n");
-	   
-	   useLocation     = 0;
-	   memberIOstate   = 1;
-	   *memberFileName = 0;
-	}
-      else
-      { */ 
-	  /*
-	     the member HDU and grouping table FITS file location information 
-	     must be used.
-
-	     First determine the correct driver and file name for the group
-	     table and member HDU files. If either are disk files then
-	     construct an absolute file path for them. Finally, if both are
-	     disk files construct relative file paths from the group(member)
-	     file to the member(group) file.
-
-	  */
-
-	  /* set the USELOCATION flag to true */
-
-	  useLocation = 1;
-
-	  /* 
-	     get the location, access type and iostate (RO, RW) of the
-	     member HDU file
-	  */
-
-	  *status = fits_get_url(tmpfptr,memberFileName,memberLocation,
-				 memberAccess1,memberAccess2,&memberIOstate,
-				 status);
-
-	  /*
-	     if the memberFileName string is empty then use the values of
-	     the memberLocation string. This corresponds to a file where
-	     the "real" file is a temporary memory file, and we must assume
-	     the the application really wants the original file to be the
-	     group member
-	   */
-
-	  if(strlen(memberFileName) == 0)
-	    {
-	      strcpy(memberFileName,memberLocation);
-	      strcpy(memberAccess1,memberAccess2);
-	    }
-
-	  /* 
-	     get the location, access type and iostate (RO, RW) of the
-	     grouping table file
-	  */
-
-	  *status = fits_get_url(gfptr,groupFileName,groupLocation,
-				 groupAccess1,groupAccess2,&groupIOstate,
-				 status);
-	  
-	  if(*status != 0) continue;
-
-	  /*
-	    the grouping table file must be writable to continue
-	  */
-
-	  if(groupIOstate == 0)
-	    {
-	      ffpmsg("cannot modify grouping table (ffgtam)");
-	      *status = BAD_GROUP_ATTACH;
-	      continue;
-	    }
-
-	  /*
-	    determine how to construct the resulting URLs for the member and
-	    group files
-	  */
-
-	  if(fits_strcasecmp(groupAccess1,"file://")  &&
-	                                   fits_strcasecmp(memberAccess1,"file://"))
-	    {
-              *cwd = 0;
-	      /* 
-		 nothing to do in this case; both the member and group files
-		 must be of an access type that already gives valid URLs;
-		 i.e., URLs that we can pass directly to the file drivers
-	      */
-	    }
-	  else
-	    {
-	      /*
-		 retrieve the Current Working Directory as a Unix-like
-		 URL standard string
-	      */
-
-	      *status = fits_get_cwd(cwd,status);
-
-	      /*
-		 create full file path for the member HDU FITS file URL
-		 if it is of access type file://
-	      */
-	      
-	      if(fits_strcasecmp(memberAccess1,"file://") == 0)
-		{
-		  if(*memberFileName == '/')
-		    {
-		      strcpy(memberLocation,memberFileName);
-		    }
-		  else
-		    {
-		      strcpy(memberLocation,cwd);
-		      strcat(memberLocation,"/");
-		      strcat(memberLocation,memberFileName);
-		    }
-		  
-		  *status = fits_clean_url(memberLocation,memberFileName,
-					   status);
-		}
-
-	      /*
-		 create full file path for the grouping table HDU FITS file URL
-		 if it is of access type file://
-	      */
-
-	      if(fits_strcasecmp(groupAccess1,"file://") == 0)
-		{
-		  if(*groupFileName == '/')
-		    {
-		      strcpy(groupLocation,groupFileName);
-		    }
-		  else
-		    {
-		      strcpy(groupLocation,cwd);
-		      strcat(groupLocation,"/");
-		      strcat(groupLocation,groupFileName);
-		    }
-		  
-		  *status = fits_clean_url(groupLocation,groupFileName,status);
-		}
-
-	      /*
-		if both the member and group files are disk files then 
-		create a relative path (relative URL) strings with 
-		respect to the grouping table's file and the grouping table's 
-		file with respect to the member HDU's file
-	      */
-	      
-	      if(fits_strcasecmp(groupAccess1,"file://") == 0 &&
-		                      fits_strcasecmp(memberAccess1,"file://") == 0)
-		{
-		  fits_url2relurl(memberFileName,groupFileName,
-				                  groupLocation,status);
-		  fits_url2relurl(groupFileName,memberFileName,
-				                  memberLocation,status);
-
-		  /*
-		     copy the resulting partial URL strings to the
-		     memberFileName and groupFileName variables for latter
-		     use in the function
-		   */
-		    
-		  strcpy(memberFileName,memberLocation);
-		  strcpy(groupFileName,groupLocation);		  
-		}
-	    }
-	  /* beo done */
-	  /* }  */
-      
-
-      /* retrieve the grouping table's EXTVER value */
-
-      *status = fits_read_key_lng(gfptr,"EXTVER",&groupExtver,card,status);
-
-      /* 
-	 if useLocation is true then make the group EXTVER value negative
-	 for the subsequent GRPIDn/GRPLCn matching
-      */
-      /* SPR 3463 change test;  WDP added test for same filename */
-      /* Now, if either the Fptr values are the same, or the root filenames
-         are the same, then assume these refer to the same file.
-      */
-      fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status);
-      fits_parse_rootname(gfptr->Fptr->filename, grootname, status);
-
-      if((tmpfptr->Fptr != gfptr->Fptr) && 
-          strncmp(tmprootname, grootname, FLEN_FILENAME))
-	   groupExtver = -1*groupExtver;
-
-      /* retrieve the number of group members */
-
-      *status = fits_get_num_members(gfptr,&nmembers,status);
-	      
-    do {
-
-      /*
-	 make sure the member HDU is not already an entry in the
-	 grouping table before adding it
-      */
-
-      *status = ffgmf(gfptr,memberHDUtype,memberExtname,memberExtver,
-		      memberPosition,memberFileName,&memberID,status);
-
-      if(*status == MEMBER_NOT_FOUND) *status = 0;
-      else if(*status == 0)
-	{  
-	  parentStatus = HDU_ALREADY_MEMBER;
-    ffpmsg("Specified HDU is already a member of the Grouping table (ffgtam)");
-	  continue;
-	}
-      else continue;
-
-      /*
-	 if the member HDU is not already recorded in the grouping table
-	 then add it 
-      */
-
-      /* add a new row to the grouping table */
-
-      *status = fits_insert_rows(gfptr,nmembers,1,status);
-      ++nmembers;
-
-      /* retrieve the grouping table column IDs and structure type */
-
-      *status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol,
-		       &locationCol,&uriCol,&grptype,status);
-
-      /* fill in the member HDU data in the new grouping table row */
-
-      *tmpPtr = memberHDUtype; 
-
-      if(xtensionCol != 0)
-	fits_write_col_str(gfptr,xtensionCol,nmembers,1,1,tmpPtr,status);
-
-      *tmpPtr = memberExtname; 
-
-      if(extnameCol  != 0)
-	{
-	  if(strlen(memberExtname) != 0)
-	    fits_write_col_str(gfptr,extnameCol,nmembers,1,1,tmpPtr,status);
-	  else
-	    /* WILL THIS WORK FOR VAR LENTH CHAR COLS??????*/
-	    fits_write_col_byt(gfptr,extnameCol,nmembers,1,1,charNull,status);
-	}
-
-      if(extverCol   != 0)
-	fits_write_col_lng(gfptr,extverCol,nmembers,1,1,&memberExtver,
-			   status);
-
-      if(positionCol != 0)
-	fits_write_col_int(gfptr,positionCol,nmembers,1,1,
-			   &memberPosition,status);
-
-      *tmpPtr = memberFileName; 
-
-      if(locationCol != 0)
-	{
-	  /* Change the test for SPR 3463 */
-	  /* Now, if either the Fptr values are the same, or the root filenames
-	     are the same, then assume these refer to the same file.
-	  */
-	  fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status);
-	  fits_parse_rootname(gfptr->Fptr->filename, grootname, status);
-
-	  if((tmpfptr->Fptr != gfptr->Fptr) && 
-	          strncmp(tmprootname, grootname, FLEN_FILENAME))
-	    fits_write_col_str(gfptr,locationCol,nmembers,1,1,tmpPtr,status);
-	  else
-	    /* WILL THIS WORK FOR VAR LENTH CHAR COLS??????*/
-	    fits_write_col_byt(gfptr,locationCol,nmembers,1,1,charNull,status);
-	}
-
-      *tmpPtr = memberURI;
-
-      if(uriCol      != 0)
-	{
-
-	  /* Change the test for SPR 3463 */
-	  /* Now, if either the Fptr values are the same, or the root filenames
-	     are the same, then assume these refer to the same file.
-	  */
-	  fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status);
-	  fits_parse_rootname(gfptr->Fptr->filename, grootname, status);
-
-	  if((tmpfptr->Fptr != gfptr->Fptr) && 
-	          strncmp(tmprootname, grootname, FLEN_FILENAME))
-	    fits_write_col_str(gfptr,uriCol,nmembers,1,1,tmpPtr,status);
-	  else
-	    /* WILL THIS WORK FOR VAR LENTH CHAR COLS??????*/
-	    fits_write_col_byt(gfptr,uriCol,nmembers,1,1,charNull,status);
-	}
-    } while(0);
-
-      if(0 != *status) continue;
-      /*
-	 add GRPIDn/GRPLCn keywords to the member HDU header to link
-	 it to the grouing table if the they do not already exist and
-	 the member file is RW
-      */
-
-      fits_file_mode(tmpfptr,&iomode,status);
- 
-     if(memberIOstate == 0 || iomode != READWRITE) 
-	{
-	  ffpmsg("cannot add GRPID/LC keywords to member HDU: (ffgtam)");
-	  ffpmsg(memberFileName);
-	  continue;
-	}
-
-      *status = fits_get_num_groups(tmpfptr,&ngroups,status);
-
-      /* 
-	 look for the GRPID/LC keywords in the member HDU; if the keywords
-	 for the back-link to the grouping table already exist then no
-	 need to add them again
-       */
-
-      for(i = 1, found = 0; i <= ngroups && !found && *status == 0; ++i)
-	{
-	  sprintf(keyword,"GRPID%d",(int)ngroups);
-	  *status = fits_read_key_lng(tmpfptr,keyword,&grpid,card,status);
-
-	  if(grpid == groupExtver)
-	    {
-	      if(grpid < 0)
-		{
-
-		  /* have to make sure the GRPLCn keyword matches too */
-
-		  sprintf(keyword,"GRPLC%d",(int)ngroups);
-		  /* SPR 1738 */
-		  *status = fits_read_key_longstr(mfptr,keyword,&tgrplc,card,
-						  status);
-		  if (0 == *status) {
-		    strcpy(grplc,tgrplc);
-		    free(tgrplc);
-		  }
-		  
-		  /*
-		     always compare files using absolute paths
-                     the presence of a non-empty cwd indicates
-                     that the file names may require conversion
-                     to absolute paths
-                  */
-
-                  if(0 < strlen(cwd)) {
-                    /* temp buffer for use in assembling abs. path(s) */
-                    char tmp[FLEN_FILENAME];
-
-                    /* make grplc absolute if necessary */
-                    if(!fits_is_url_absolute(grplc)) {
-		      fits_path2url(grplc,groupLocation,status);
-
-		      if(groupLocation[0] != '/')
-			{
-			  strcpy(tmp, cwd);
-			  strcat(tmp,"/");
-			  strcat(tmp,groupLocation);
-			  fits_clean_url(tmp,grplc,status);
-			}
-                    }
-
-                    /* make groupFileName absolute if necessary */
-                    if(!fits_is_url_absolute(groupFileName)) {
-		      fits_path2url(groupFileName,groupLocation,status);
-
-		      if(groupLocation[0] != '/')
-			{
-			  strcpy(tmp, cwd);
-			  strcat(tmp,"/");
-			  strcat(tmp,groupLocation);
-                          /*
-                             note: use groupLocation (which is not used
-                             below this block), to store the absolute
-                             file name instead of using groupFileName.
-                             The latter may be needed unaltered if the
-                             GRPLC is written below
-                          */
-
-			  fits_clean_url(tmp,groupLocation,status);
-			}
-                    }
-                  }
-		  /*
-		    see if the grplc value and the group file name match
-		  */
-
-		  if(strcmp(grplc,groupLocation) == 0) found = 1;
-		}
-	      else
-		{
-		  /* the match is found with GRPIDn alone */
-		  found = 1;
-		}
-	    }
-	}
-
-      /*
-	 if FOUND is true then no need to continue
-      */
-
-      if(found)
-	{
-	  ffpmsg("HDU already has GRPID/LC keywords for group table (ffgtam)");
-	  continue;
-	}
-
-      /*
-	 add the GRPID/LC keywords to the member header for this grouping
-	 table
-	 
-	 If NGROUPS == 0 then we must position the header pointer to the
-	 record where we want to insert the GRPID/LC keywords (the pointer
-	 is already correctly positioned if the above search loop activiated)
-      */
-
-      if(ngroups == 0)
-	{
-	  /* 
-	     no GRPIDn/GRPLCn keywords currently exist in header so try
-	     to position the header pointer to a desirable position
-	  */
-	  
-	  for(i = 0, *status = KEY_NO_EXIST; 
-	                       i < nkeys && *status == KEY_NO_EXIST; ++i)
-	    {
-	      *status = 0;
-	      *status = fits_read_card(tmpfptr,keys[i],card,status);
-	    }
-	      
-	  /* all else fails: move write pointer to end of header */
-	      
-	  if(*status == KEY_NO_EXIST)
-	    {
-	      *status = 0;
-	      fits_get_hdrspace(tmpfptr,&nkeys,&i,status);
-	      ffgrec(tmpfptr,nkeys,card,status);
-	    }
-	  
-	  /* any other error status then abort */
-	  
-	  if(*status != 0) continue;
-	}
-      
-      /* 
-	 now that the header pointer is positioned for the GRPID/LC 
-	 keyword insertion increment the number of group links counter for 
-	 the member HDU 
-      */
-
-      ++ngroups;
-
-      /*
-	 if the member HDU and grouping table reside in the same FITS file
-	 then there is no need to add a GRPLCn keyword
-      */
-      /* SPR 3463 change test */
-      /* Now, if either the Fptr values are the same, or the root filenames
-	 are the same, then assume these refer to the same file.
-      */
-      fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status);
-      fits_parse_rootname(gfptr->Fptr->filename, grootname, status);
-
-      if((tmpfptr->Fptr == gfptr->Fptr) || 
-	          strncmp(tmprootname, grootname, FLEN_FILENAME) == 0)
-	{
-	  /* add the GRPIDn keyword only */
-
-	  sprintf(keyword,"GRPID%d",(int)ngroups);
-	  fits_insert_key_lng(tmpfptr,keyword,groupExtver,
-			      "EXTVER of Group containing this HDU",status);
-	}
-      else 
-	{
-	  /* add the GRPIDn and GRPLCn keywords */
-
-	  sprintf(keyword,"GRPID%d",(int)ngroups);
-	  fits_insert_key_lng(tmpfptr,keyword,groupExtver,
-			      "EXTVER of Group containing this HDU",status);
-
-	  sprintf(keyword,"GRPLC%d",(int)ngroups);
-	  /* SPR 1738 */
-	  fits_insert_key_longstr(tmpfptr,keyword,groupFileName,
-			      "URL of file containing Group",status);
-	  fits_write_key_longwarn(tmpfptr,status);
-
-	}
-
-    }while(0);
-
-  /* close the tmpfptr pointer if it was opened in this function */
-
-  if(mfptr == NULL)
-    {
-      *status = fits_close_file(tmpfptr,status);
-    }
-
-  *status = 0 == *status ? parentStatus : *status;
-
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int ffgtnm(fitsfile *gfptr,    /* FITS file pointer to grouping table        */
-	   long     *nmembers, /* member count  of the groping table         */
-	   int      *status)   /* return status code                         */
-
-/*
-  return the number of member HDUs in a grouping table. The fitsfile pointer
-  gfptr must be positioned with the grouping table as the CHDU. The number
-  of grouping table member HDUs is just the NAXIS2 value of the grouping
-  table.
-*/
-
-{
-  char keyvalue[FLEN_VALUE];
-  char comment[FLEN_COMMENT];
-  
-
-  if(*status != 0) return(*status);
-
-  *status = fits_read_keyword(gfptr,"EXTNAME",keyvalue,comment,status);
-  
-  if(*status == KEY_NO_EXIST)
-    *status = NOT_GROUP_TABLE;
-  else
-    {
-      prepare_keyvalue(keyvalue);
-
-      if(fits_strcasecmp(keyvalue,"GROUPING") != 0)
-	{
-	  *status = NOT_GROUP_TABLE;
-	  ffpmsg("Specified HDU is not a Grouping table (ffgtnm)");
-	}
-
-      *status = fits_read_key_lng(gfptr,"NAXIS2",nmembers,comment,status);
-    }
-
-  return(*status);
-}
-
-/*--------------------------------------------------------------------------*/
-int ffgmng(fitsfile *mfptr,   /* FITS file pointer to member HDU            */
-	   long     *ngroups, /* total number of groups linked to HDU       */
-	   int      *status)  /* return status code                         */
-
-/*
-  return the number of groups to which a HDU belongs, as defined by the number
-  of GRPIDn/GRPLCn keyword records that appear in the HDU header. The 
-  fitsfile pointer mfptr must be positioned with the member HDU as the CHDU. 
-  Each time this function is called, the indicies of the GRPIDn/GRPLCn
-  keywords are checked to make sure they are continuous (ie no gaps) and
-  are re-enumerated to eliminate gaps if gaps are found to be present.
-*/
-
-{
-  int offset;
-  int index;
-  int newIndex;
-  int i;
-  
-  long grpid;
-
-  char *inclist[] = {"GRPID#"};
-  char keyword[FLEN_KEYWORD];
-  char newKeyword[FLEN_KEYWORD];
-  char card[FLEN_CARD];
-  char comment[FLEN_COMMENT];
-  char *tkeyvalue;
-
-  if(*status != 0) return(*status);
-
-  *ngroups = 0;
-
-  /* reset the member HDU keyword counter to the beginning */
-
-  *status = ffgrec(mfptr,0,card,status);
-  
-  /*
-    search for the number of GRPIDn keywords in the member HDU header
-    and count them with the ngroups variable
-  */
-  
-  while(*status == 0)
-    {
-      /* read the next GRPIDn keyword in the series */
-
-      *status = fits_find_nextkey(mfptr,inclist,1,NULL,0,card,status);
-      
-      if(*status != 0) continue;
-      
-      ++(*ngroups);
-    }
-
-  if(*status == KEY_NO_EXIST) *status = 0;
-      
-  /*
-     read each GRPIDn/GRPLCn keyword and adjust their index values so that
-     there are no gaps in the index count
-  */
-
-  for(index = 1, offset = 0, i = 1; i <= *ngroups && *status == 0; ++index)
-    {	  
-      sprintf(keyword,"GRPID%d",index);
-
-      /* try to read the next GRPIDn keyword in the series */
-
-      *status = fits_read_key_lng(mfptr,keyword,&grpid,card,status);
-
-      /* if not found then increment the offset counter and continue */
-
-      if(*status == KEY_NO_EXIST) 
-	{
-	  *status = 0;
-	  ++offset;
-	}
-      else
-	{
-	  /* 
-	     increment the number_keys_found counter and see if the index
-	     of the keyword needs to be updated
-	  */
-
-	  ++i;
-
-	  if(offset > 0)
-	    {
-	      /* compute the new index for the GRPIDn/GRPLCn keywords */
-	      newIndex = index - offset;
-
-	      /* update the GRPIDn keyword index */
-
-	      sprintf(newKeyword,"GRPID%d",newIndex);
-	      fits_modify_name(mfptr,keyword,newKeyword,status);
-
-	      /* If present, update the GRPLCn keyword index */
-
-	      sprintf(keyword,"GRPLC%d",index);
-	      sprintf(newKeyword,"GRPLC%d",newIndex);
-	      /* SPR 1738 */
-	      *status = fits_read_key_longstr(mfptr,keyword,&tkeyvalue,comment,
-					      status);
-	      if (0 == *status) {
-		fits_delete_key(mfptr,keyword,status);
-		fits_insert_key_longstr(mfptr,newKeyword,tkeyvalue,comment,status);
-		fits_write_key_longwarn(mfptr,status);
-		free(tkeyvalue);
-	      }
-	      
-
-	      if(*status == KEY_NO_EXIST) *status = 0;
-	    }
-	}
-    }
-
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int ffgmop(fitsfile *gfptr,  /* FITS file pointer to grouping table          */
-	   long      member, /* member ID (row num) within grouping table    */
-	   fitsfile **mfptr, /* FITS file pointer to member HDU              */
-	   int      *status) /* return status code                           */
-
-/*
-  open a grouping table member, returning a pointer to the member's FITS file
-  with the CHDU set to the member HDU. The grouping table must be the CHDU of
-  the FITS file pointed to by gfptr. The member to open is identified by its
-  row number within the grouping table (first row/member == 1).
-
-  If the member resides in a FITS file different from the grouping
-  table the member file is first opened readwrite and if this fails then
-  it is opened readonly. For access type of FILE:// the member file is
-  searched for assuming (1) an absolute path is given, (2) a path relative
-  to the CWD is given, and (3) a path relative to the grouping table file
-  but not relative to the CWD is given. If all of these fail then the
-  error FILE_NOT_FOUND is returned.
-*/
-
-{
-  int xtensionCol,extnameCol,extverCol,positionCol,locationCol,uriCol;
-  int grptype,hdutype;
-  int dummy;
-
-  long hdupos = 0;
-  long extver = 0;
-
-  char  xtension[FLEN_VALUE];
-  char  extname[FLEN_VALUE];
-  char  uri[FLEN_VALUE];
-  char  grpLocation1[FLEN_FILENAME];
-  char  grpLocation2[FLEN_FILENAME];
-  char  mbrLocation1[FLEN_FILENAME];
-  char  mbrLocation2[FLEN_FILENAME];
-  char  mbrLocation3[FLEN_FILENAME];
-  char  cwd[FLEN_FILENAME];
-  char  card[FLEN_CARD];
-  char  nstr[] = {'\0'};
-  char *tmpPtr[1];
-
-
-  if(*status != 0) return(*status);
-
-  do
-    {
-      /*
-	retrieve the Grouping Convention reserved column positions within
-	the grouping table
-      */
-
-      *status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol,
-		       &locationCol,&uriCol,&grptype,status);
-
-      if(*status != 0) continue;
-
-      /*
-	 extract the member information from grouping table
-      */
-
-      tmpPtr[0] = xtension;
-
-      if(xtensionCol != 0)
-	{
-
-	  *status = fits_read_col_str(gfptr,xtensionCol,member,1,1,nstr,
-				      tmpPtr,&dummy,status);
-
-	  /* convert the xtension string to a hdutype code */
-
-	  if(fits_strcasecmp(xtension,"PRIMARY")       == 0) hdutype = IMAGE_HDU; 
-	  else if(fits_strcasecmp(xtension,"IMAGE")    == 0) hdutype = IMAGE_HDU; 
-	  else if(fits_strcasecmp(xtension,"TABLE")    == 0) hdutype = ASCII_TBL; 
-	  else if(fits_strcasecmp(xtension,"BINTABLE") == 0) hdutype = BINARY_TBL; 
-	  else hdutype = ANY_HDU; 
-	}
-
-      tmpPtr[0] = extname;
-
-      if(extnameCol  != 0)
-	  *status = fits_read_col_str(gfptr,extnameCol,member,1,1,nstr,
-				      tmpPtr,&dummy,status);
-
-      if(extverCol   != 0)
-	  *status = fits_read_col_lng(gfptr,extverCol,member,1,1,0,
-				      (long*)&extver,&dummy,status);
-
-      if(positionCol != 0)
-	  *status = fits_read_col_lng(gfptr,positionCol,member,1,1,0,
-				      (long*)&hdupos,&dummy,status);
-
-      tmpPtr[0] = mbrLocation1;
-
-      if(locationCol != 0)
-	*status = fits_read_col_str(gfptr,locationCol,member,1,1,nstr,
-				    tmpPtr,&dummy,status);
-      tmpPtr[0] = uri;
-
-      if(uriCol != 0)
-	*status = fits_read_col_str(gfptr,uriCol,member,1,1,nstr,
-				    tmpPtr,&dummy,status);
-
-      if(*status != 0) continue;
-
-      /* 
-	 decide what FITS file the member HDU resides in and open the file
-	 using the fitsfile* pointer mfptr; note that this logic is rather
-	 complicated and is based primiarly upon if a URL specifier is given
-	 for the member file in the grouping table
-      */
-
-      switch(grptype)
-	{
-
-	case GT_ID_POS:
-	case GT_ID_REF:
-	case GT_ID_ALL:
-
-	  /*
-	     no location information is given so we must assume that the
-	     member HDU resides in the same FITS file as the grouping table;
-	     if the grouping table was incorrectly constructed then this
-	     assumption will be false, but there is nothing to be done about
-	     it at this point
-	  */
-
-	  *status = fits_reopen_file(gfptr,mfptr,status);
-	  
-	  break;
-
-	case GT_ID_REF_URI:
-	case GT_ID_POS_URI:
-	case GT_ID_ALL_URI:
-
-	  /*
-	    The member location column exists. Determine if the member 
-	    resides in the same file as the grouping table or in a
-	    separate file; open the member file in either case
-	  */
-
-	  if(strlen(mbrLocation1) == 0)
-	    {
-	      /*
-		 since no location information was given we must assume
-		 that the member is in the same FITS file as the grouping
-		 table
-	      */
-
-	      *status = fits_reopen_file(gfptr,mfptr,status);
-	    }
-	  else
-	    {
-	      /*
-		make sure the location specifiation is "URL"; we cannot
-		decode any other URI types at this time
-	      */
-
-	      if(fits_strcasecmp(uri,"URL") != 0)
-		{
-		  *status = FILE_NOT_OPENED;
-		  sprintf(card,
-		  "Cannot open member HDU file with URI type %s (ffgmop)",
-			  uri);
-		  ffpmsg(card);
-
-		  continue;
-		}
-
-	      /*
-		The location string for the member is not NULL, so it 
-		does not necessially reside in the same FITS file as the
-		grouping table. 
-
-		Three cases are attempted for opening the member's file
-		in the following order:
-
-		1. The URL given for the member's file is absolute (i.e.,
-		access method supplied); try to open the member
-
-		2. The URL given for the member's file is not absolute but
-		is an absolute file path; try to open the member as a file
-		after the file path is converted to a host-dependent form
-
-		3. The URL given for the member's file is not absolute
-	        and is given as a relative path to the location of the 
-		grouping table's file. Create an absolute URL using the 
-		grouping table's file URL and try to open the member.
-		
-		If all three cases fail then an error is returned. In each
-		case the file is first opened in read/write mode and failing
-		that readonly mode.
-		
-		The following DO loop is only used as a mechanism to break
-		(continue) when the proper file opening method is found
-	       */
-
-	      do
-		{
-		  /*
-		     CASE 1:
-
-		     See if the member URL is absolute (i.e., includes a
-		     access directive) and if so open the file
-		   */
-
-		  if(fits_is_url_absolute(mbrLocation1))
-		    {
-		      /*
-			 the URL must specify an access method, which 
-			 implies that its an absolute reference
-			 
-			 regardless of the access method, pass the whole
-			 URL to the open function for processing
-		       */
-		      
-		      ffpmsg("member URL is absolute, try open R/W (ffgmop)");
-
-		      *status = fits_open_file(mfptr,mbrLocation1,READWRITE,
-					       status);
-
-		      if(*status == 0) continue;
-
-		      *status = 0;
-
-		      /* 
-			 now try to open file using full URL specs in 
-			 readonly mode 
-		      */ 
-
-		      ffpmsg("OK, now try to open read-only (ffgmop)");
-
-		      *status = fits_open_file(mfptr,mbrLocation1,READONLY,
-					       status);
-
-		      /* break from DO loop regardless of status */
-
-		      continue;
-		    }
-
-		  /*
-		     CASE 2:
-
-		     If we got this far then the member URL location 
-		     has no access type ==> FILE:// Try to open the member 
-		     file using the URL as is, i.e., assume that it is given 
-		     as absolute, if it starts with a '/' character
-		   */
-
-		  ffpmsg("Member URL is of type FILE (ffgmop)");
-
-		  if(*mbrLocation1 == '/')
-		    {
-		      ffpmsg("Member URL specifies abs file path (ffgmop)");
-
-		      /* 
-			 convert the URL path to a host dependent path
-		      */
-
-		      *status = fits_url2path(mbrLocation1,mbrLocation2,
-					      status);
-
-		      ffpmsg("Try to open member URL in R/W mode (ffgmop)");
-
-		      *status = fits_open_file(mfptr,mbrLocation2,READWRITE,
-					       status);
-
-		      if(*status == 0) continue;
-
-		      *status = 0;
-
-		      /* 
-			 now try to open file using the URL as an absolute 
-			 path in readonly mode 
-		      */
- 
-		      ffpmsg("OK, now try to open read-only (ffgmop)");
-
-		      *status = fits_open_file(mfptr,mbrLocation2,READONLY,
-					       status);
-
-		      /* break from the Do loop regardless of the status */
-
-		      continue;
-		    }
-		  
-		  /* 
-		     CASE 3:
-
-		     If we got this far then the URL does not specify an
-		     absoulte file path or URL with access method. Since 
-		     the path to the group table's file is (obviously) valid 
-		     for the CWD, create a full location string for the
-		     member HDU using the grouping table URL as a basis
-
-		     The only problem is that the grouping table file might
-		     have two URLs, the original one used to open it and
-		     the one that points to the real file being accessed
-		     (i.e., a file accessed via HTTP but transferred to a
-		     local disk file). Have to attempt to build a URL to
-		     the member HDU file using both of these URLs if
-		     defined.
-		  */
-
-		  ffpmsg("Try to open member file as relative URL (ffgmop)");
-
-		  /* get the URL information for the grouping table file */
-
-		  *status = fits_get_url(gfptr,grpLocation1,grpLocation2,
-					 NULL,NULL,NULL,status);
-
-		  /* 
-		     if the "real" grouping table file URL is defined then
-		     build a full url for the member HDU file using it
-		     and try to open the member HDU file
-		  */
-
-		  if(*grpLocation1)
-		    {
-		      /* make sure the group location is absolute */
-
-		      if(! fits_is_url_absolute(grpLocation1) &&
-			                              *grpLocation1 != '/')
-			{
-			  fits_get_cwd(cwd,status);
-			  strcat(cwd,"/");
-			  strcat(cwd,grpLocation1);
-			  strcpy(grpLocation1,cwd);
-			}
-
-		      /* create a full URL for the member HDU file */
-
-		      *status = fits_relurl2url(grpLocation1,mbrLocation1,
-						mbrLocation2,status);
-
-		      if(*status != 0) continue;
-
-		      /*
-			if the URL does not have an access method given then
-			translate it into a host dependent file path
-		      */
-
-		      if(! fits_is_url_absolute(mbrLocation2))
-			{
-			  *status = fits_url2path(mbrLocation2,mbrLocation3,
-						  status);
-			  strcpy(mbrLocation2,mbrLocation3);
-			}
-
-		      /* try to open the member file READWRITE */
-
-		      *status = fits_open_file(mfptr,mbrLocation2,READWRITE,
-					       status);
-
-		      if(*status == 0) continue;
-
-		      *status = 0;
-		  
-		      /* now try to open in readonly mode */ 
-
-		      ffpmsg("now try to open file as READONLY (ffgmop)");
-
-		      *status = fits_open_file(mfptr,mbrLocation2,READONLY,
-					       status);
-
-		      if(*status == 0) continue;
-
-		      *status = 0;
-		    }
-
-		  /* 
-		     if we got this far then either the "real" grouping table
-		     file URL was not defined or all attempts to open the
-		     resulting member HDU file URL failed.
-
-		     if the "original" grouping table file URL is defined then
-		     build a full url for the member HDU file using it
-		     and try to open the member HDU file
-		  */
-
-		  if(*grpLocation2)
-		    {
-		      /* make sure the group location is absolute */
-
-		      if(! fits_is_url_absolute(grpLocation2) &&
-			                              *grpLocation2 != '/')
-			{
-			  fits_get_cwd(cwd,status);
-			  strcat(cwd,"/");
-			  strcat(cwd,grpLocation2);
-			  strcpy(grpLocation2,cwd);
-			}
-
-		      /* create an absolute URL for the member HDU file */
-
-		      *status = fits_relurl2url(grpLocation2,mbrLocation1,
-						mbrLocation2,status);
-		      if(*status != 0) continue;
-
-		      /*
-			if the URL does not have an access method given then
-			translate it into a host dependent file path
-		      */
-
-		      if(! fits_is_url_absolute(mbrLocation2))
-			{
-			  *status = fits_url2path(mbrLocation2,mbrLocation3,
-						  status);
-			  strcpy(mbrLocation2,mbrLocation3);
-			}
-
-		      /* try to open the member file READWRITE */
-
-		      *status = fits_open_file(mfptr,mbrLocation2,READWRITE,
-					       status);
-
-		      if(*status == 0) continue;
-
-		      *status = 0;
-		  
-		      /* now try to open in readonly mode */ 
-
-		      ffpmsg("now try to open file as READONLY (ffgmop)");
-
-		      *status = fits_open_file(mfptr,mbrLocation2,READONLY,
-					       status);
-
-		      if(*status == 0) continue;
-
-		      *status = 0;
-		    }
-
-		  /*
-		     if we got this far then the member HDU file could not
-		     be opened using any method. Log the error.
-		  */
-
-		  ffpmsg("Cannot open member HDU FITS file (ffgmop)");
-		  *status = MEMBER_NOT_FOUND;
-		  
-		}while(0);
-	    }
-
-	  break;
-
-	default:
-
-	  /* no default action */
-	  
-	  break;
-	}
-	  
-      if(*status != 0) continue;
-
-      /*
-	 attempt to locate the member HDU within its FITS file as determined
-	 and opened above
-      */
-
-      switch(grptype)
-	{
-
-	case GT_ID_POS:
-	case GT_ID_POS_URI:
-
-	  /*
-	    try to find the member hdu in the the FITS file pointed to
-	    by mfptr based upon its HDU posistion value. Note that is 
-	    impossible to verify if the HDU is actually the correct HDU due 
-	    to a lack of information.
-	  */
-	  
-	  *status = fits_movabs_hdu(*mfptr,(int)hdupos,&hdutype,status);
-
-	  break;
-
-	case GT_ID_REF:
-	case GT_ID_REF_URI:
-
-	  /*
-	     try to find the member hdu in the FITS file pointed to
-	     by mfptr based upon its XTENSION, EXTNAME and EXTVER keyword 
-	     values
-	  */
-
-	  *status = fits_movnam_hdu(*mfptr,hdutype,extname,extver,status);
-
-	  if(*status == BAD_HDU_NUM) 
-	    {
-	      *status = MEMBER_NOT_FOUND;
-	      ffpmsg("Cannot find specified member HDU (ffgmop)");
-	    }
-
-	  /*
-	     if the above function returned without error then the
-	     mfptr is pointed to the member HDU
-	  */
-
-	  break;
-
-	case GT_ID_ALL:
-	case GT_ID_ALL_URI:
-
-	  /*
-	     if the member entry has reference information then use it
-             (ID by reference is safer than ID by position) else use
-	     the position information
-	  */
-
-	  if(strlen(xtension) > 0 && strlen(extname) > 0 && extver > 0)
-	    {
-	      /* valid reference info exists so use it */
-	      
-	      /* try to find the member hdu in the grouping table's file */
-
-	      *status = fits_movnam_hdu(*mfptr,hdutype,extname,extver,status);
-
-	      if(*status == BAD_HDU_NUM) 
-		{
-		  *status = MEMBER_NOT_FOUND;
-		  ffpmsg("Cannot find specified member HDU (ffgmop)");
-		}
-	    }
-	  else
-	      {
-		  *status = fits_movabs_hdu(*mfptr,(int)hdupos,&hdutype,
-					    status);
-		  if(*status == END_OF_FILE) *status = MEMBER_NOT_FOUND;
-	      }
-
-	  /*
-	     if the above function returned without error then the
-	     mfptr is pointed to the member HDU
-	  */
-
-	  break;
-
-	default:
-
-	  /* no default action */
-
-	  break;
-	}
-      
-    }while(0);
-
-  if(*status != 0 && *mfptr != NULL) 
-    {
-      fits_close_file(*mfptr,status);
-    }
-
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int ffgmcp(fitsfile *gfptr,  /* FITS file pointer to group                   */
-	   fitsfile *mfptr,  /* FITS file pointer to new member
-				FITS file                                    */
-	   long      member, /* member ID (row num) within grouping table    */
-	   int       cpopt,  /* code specifying copy options:
-				OPT_MCP_ADD  (0) ==> add copied member to the
- 				                     grouping table
-				OPT_MCP_NADD (1) ==> do not add member copy to
-				                     the grouping table
-				OPT_MCP_REPL (2) ==> replace current member
-				                     entry with member copy  */
-	   int      *status) /* return status code                           */
-	   
-/*
-  copy a member HDU of a grouping table to a new FITS file. The grouping table
-  must be the CHDU of the FITS file pointed to by gfptr. The copy of the
-  group member shall be appended to the end of the FITS file pointed to by
-  mfptr. If the cpopt parameter is set to OPT_MCP_ADD then the copy of the 
-  member is added to the grouping table as a new member, if OPT_MCP_NADD 
-  then the copied member is not added to the grouping table, and if 
-  OPT_MCP_REPL then the copied member is used to replace the original member.
-  The copied member HDU also has its EXTVER value updated so that its
-  combination of XTENSION, EXTNAME and EXVTER is unique within its new
-  FITS file.
-*/
-
-{
-  int numkeys = 0;
-  int keypos  = 0;
-  int hdunum  = 0;
-  int hdutype = 0;
-  int i;
-  
-  char *incList[] = {"GRPID#","GRPLC#"};
-  char  extname[FLEN_VALUE];
-  char  card[FLEN_CARD];
-  char  comment[FLEN_COMMENT];
-  char  keyname[FLEN_CARD];
-  char  value[FLEN_CARD];
-
-  fitsfile *tmpfptr = NULL;
-
-
-  if(*status != 0) return(*status);
-
-  do
-    {
-      /* open the member HDU to be copied */
-
-      *status = fits_open_member(gfptr,member,&tmpfptr,status);
-
-      if(*status != 0) continue;
-
-      /*
-	if the member is a grouping table then copy it with a call to
-	fits_copy_group() using the "copy only the grouping table" option
-
-	if it is not a grouping table then copy the hdu with fits_copy_hdu()
-	remove all GRPIDn and GRPLCn keywords, and update the EXTVER keyword
-	value
-      */
-
-      /* get the member HDU's EXTNAME value */
-
-      *status = fits_read_key_str(tmpfptr,"EXTNAME",extname,comment,status);
-
-      /* if no EXTNAME value was found then set the extname to a null string */
-
-      if(*status == KEY_NO_EXIST) 
-	{
-	  extname[0] = 0;
-	  *status    = 0;
-	}
-      else if(*status != 0) continue;
-
-      prepare_keyvalue(extname);
-
-      /* if a grouping table then copy with fits_copy_group() */
-
-      if(fits_strcasecmp(extname,"GROUPING") == 0)
-	*status = fits_copy_group(tmpfptr,mfptr,OPT_GCP_GPT,status);
-      else
-	{
-	  /* copy the non-grouping table HDU the conventional way */
-
-	  *status = fits_copy_hdu(tmpfptr,mfptr,0,status);
-
-	  ffgrec(mfptr,0,card,status);
-
-	  /* delete all the GRPIDn and GRPLCn keywords in the copied HDU */
-
-	  while(*status == 0)
-	    {
-	      *status = fits_find_nextkey(mfptr,incList,2,NULL,0,card,status);
-	      *status = fits_get_hdrpos(mfptr,&numkeys,&keypos,status);  
-	      /* SPR 1738 */
-	      *status = fits_read_keyn(mfptr,keypos-1,keyname,value,
-				       comment,status);
-	      *status = fits_read_record(mfptr,keypos-1,card,status);
-	      *status = fits_delete_key(mfptr,keyname,status);
-	    }
-
-	  if(*status == KEY_NO_EXIST) *status = 0;
-	  if(*status != 0) continue;
-	}
-
-      /* 
-	 if the member HDU does not have an EXTNAME keyword then add one
-	 with a default value
-      */
-
-      if(strlen(extname) == 0)
-	{
-	  if(fits_get_hdu_num(tmpfptr,&hdunum) == 1)
-	    {
-	      strcpy(extname,"PRIMARY");
-	      *status = fits_write_key_str(mfptr,"EXTNAME",extname,
-					   "HDU was Formerly a Primary Array",
-					   status);
-	    }
-	  else
-	    {
-	      strcpy(extname,"DEFAULT");
-	      *status = fits_write_key_str(mfptr,"EXTNAME",extname,
-					   "default EXTNAME set by CFITSIO",
-					   status);
-	    }
-	}
-
-      /* 
-	 update the member HDU's EXTVER value (add it if not present)
-      */
-
-      fits_get_hdu_num(mfptr,&hdunum);
-      fits_get_hdu_type(mfptr,&hdutype,status);
-
-      /* set the EXTVER value to 0 for now */
-
-      *status = fits_modify_key_lng(mfptr,"EXTVER",0,NULL,status);
-
-      /* if the EXTVER keyword was not found then add it */
-
-      if(*status == KEY_NO_EXIST)
-	{
-	  *status = 0;
-	  *status = fits_read_key_str(mfptr,"EXTNAME",extname,comment,
-				      status);
-	  *status = fits_insert_key_lng(mfptr,"EXTVER",0,
-					"Extension version ID",status);
-	}
-
-      if(*status != 0) continue;
-
-      /* find the first available EXTVER value for the copied HDU */
- 
-      for(i = 1; fits_movnam_hdu(mfptr,hdutype,extname,i,status) == 0; ++i);
-
-      *status = 0;
-
-      fits_movabs_hdu(mfptr,hdunum,&hdutype,status);
-
-      /* reset the copied member HDUs EXTVER value */
-
-      *status = fits_modify_key_lng(mfptr,"EXTVER",(long)i,NULL,status);    
-
-      /*
-	perform member copy operations that are dependent upon the cpopt
-	parameter value
-      */
-
-      switch(cpopt)
-	{
-	case OPT_MCP_ADD:
-
-	  /*
-	    add the copied member to the grouping table, leaving the
-	    entry for the original member in place
-	  */
-
-	  *status = fits_add_group_member(gfptr,mfptr,0,status);
-
-	  break;
-
-	case OPT_MCP_NADD:
-
-	  /*
-	    nothing to do for this copy option
-	  */
-
-	  break;
-
-	case OPT_MCP_REPL:
-
-	  /*
-	    remove the original member from the grouping table and add the
-	    copied member in its place
-	  */
-
-	  *status = fits_remove_member(gfptr,member,OPT_RM_ENTRY,status);
-	  *status = fits_add_group_member(gfptr,mfptr,0,status);
-
-	  break;
-
-	default:
-
-	  *status = BAD_OPTION;
-	  ffpmsg("Invalid value specified for the cmopt parameter (ffgmcp)");
-
-	  break;
-	}
-
-    }while(0);
-      
-  if(tmpfptr != NULL) 
-    {
-      fits_close_file(tmpfptr,status);
-    }
-
-  return(*status);
-}		     
-
-/*---------------------------------------------------------------------------*/
-int ffgmtf(fitsfile *infptr,   /* FITS file pointer to source grouping table */
-	   fitsfile *outfptr,  /* FITS file pointer to target grouping table */
-	   long      member,   /* member ID within source grouping table     */
-	   int       tfopt,    /* code specifying transfer opts:
-				  OPT_MCP_ADD (0) ==> copy member to dest.
-				  OPT_MCP_MOV (3) ==> move member to dest.   */
-	   int      *status)   /* return status code                         */
-
-/*
-  transfer a group member from one grouping table to another. The source
-  grouping table must be the CHDU of the fitsfile pointed to by infptr, and 
-  the destination grouping table must be the CHDU of the fitsfile to by 
-  outfptr. If the tfopt parameter is OPT_MCP_ADD then the member is made a 
-  member of the target group and remains a member of the source group. If
-  the tfopt parameter is OPT_MCP_MOV then the member is deleted from the 
-  source group after the transfer to the destination group. The member to be
-  transfered is identified by its row number within the source grouping table.
-*/
-
-{
-  fitsfile *mfptr = NULL;
-
-
-  if(*status != 0) return(*status);
-
-  if(tfopt != OPT_MCP_MOV && tfopt != OPT_MCP_ADD)
-    {
-      *status = BAD_OPTION;
-      ffpmsg("Invalid value specified for the tfopt parameter (ffgmtf)");
-    }
-  else
-    {
-      /* open the member of infptr to be transfered */
-
-      *status = fits_open_member(infptr,member,&mfptr,status);
-      
-      /* add the member to the outfptr grouping table */
-      
-      *status = fits_add_group_member(outfptr,mfptr,0,status);
-      
-      /* close the member HDU */
-      
-      *status = fits_close_file(mfptr,status);
-      
-      /* 
-	 if the tfopt is "move member" then remove it from the infptr 
-	 grouping table
-      */
-
-      if(tfopt == OPT_MCP_MOV)
-	*status = fits_remove_member(infptr,member,OPT_RM_ENTRY,status);
-    }
-  
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int ffgmrm(fitsfile *gfptr,  /* FITS file pointer to group table             */
-	   long      member, /* member ID (row num) in the group             */
-	   int       rmopt,  /* code specifying the delete option:
-				OPT_RM_ENTRY ==> delete the member entry
-				OPT_RM_MBR   ==> delete entry and member HDU */
-	   int      *status)  /* return status code                          */
-
-/*
-  remove a member HDU from a grouping table. The fitsfile pointer gfptr must
-  be positioned with the grouping table as the CHDU, and the member to 
-  delete is identified by its row number in the table (first member == 1).
-  The rmopt parameter determines if the member entry is deleted from the
-  grouping table (in which case GRPIDn and GRPLCn keywords in the member 
-  HDU's header shall be updated accordingly) or if the member HDU shall 
-  itself be removed from its FITS file.
-*/
-
-{
-  int found;
-  int hdutype   = 0;
-  int index;
-  int iomode    = 0;
-
-  long i;
-  long ngroups      = 0;
-  long nmembers     = 0;
-  long groupExtver  = 0;
-  long grpid        = 0;
-
-  char grpLocation1[FLEN_FILENAME];
-  char grpLocation2[FLEN_FILENAME];
-  char grpLocation3[FLEN_FILENAME];
-  char cwd[FLEN_FILENAME];
-  char keyword[FLEN_KEYWORD];
-  /* SPR 1738 This can now be longer */
-  char grplc[FLEN_FILENAME];
-  char *tgrplc;
-  char keyvalue[FLEN_VALUE];
-  char card[FLEN_CARD];
-  char *editLocation;
-  char mrootname[FLEN_FILENAME], grootname[FLEN_FILENAME];
-
-  fitsfile *mfptr  = NULL;
-
-
-  if(*status != 0) return(*status);
-
-  do
-    {
-      /*
-	make sure the grouping table can be modified before proceeding
-      */
-
-      fits_file_mode(gfptr,&iomode,status);
-
-      if(iomode != READWRITE)
-	{
-	  ffpmsg("cannot modify grouping table (ffgtam)");
-	  *status = BAD_GROUP_DETACH;
-	  continue;
-	}
-
-      /* open the group member to be deleted and get its IOstatus*/
-
-      *status = fits_open_member(gfptr,member,&mfptr,status);
-      *status = fits_file_mode(mfptr,&iomode,status);
-
-      /*
-	 if the member HDU is to be deleted then call fits_unlink_member()
-	 to remove it from all groups to which it belongs (including
-	 this one) and then delete it. Note that if the member is a
-	 grouping table then we have to recursively call fits_remove_member()
-	 for each member of the member before we delete the member itself.
-      */
-
-      if(rmopt == OPT_RM_MBR)
-	{
-	    /* cannot delete a PHDU */
-	    if(fits_get_hdu_num(mfptr,&hdutype) == 1)
-		{
-		    *status = BAD_HDU_NUM;
-		    continue;
-		}
-
-	  /* determine if the member HDU is itself a grouping table */
-
-	  *status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,card,status);
-
-	  /* if no EXTNAME is found then the HDU cannot be a grouping table */ 
-
-	  if(*status == KEY_NO_EXIST) 
-	    {
-	      keyvalue[0] = 0;
-	      *status = 0;
-	    }
-	  prepare_keyvalue(keyvalue);
-
-	  /* Any other error is a reason to abort */
-
-	  if(*status != 0) continue;
-
-	  /* if the EXTNAME == GROUPING then the member is a grouping table */
-	  
-	  if(fits_strcasecmp(keyvalue,"GROUPING") == 0)
-	    {
-	      /* remove each of the grouping table members */
-	      
-	      *status = fits_get_num_members(mfptr,&nmembers,status);
-	      
-	      for(i = nmembers; i > 0 && *status == 0; --i)
-		*status = fits_remove_member(mfptr,i,OPT_RM_ENTRY,status);
-	      
-	      if(*status != 0) continue;
-	    }
-
-	  /* unlink the member HDU from all groups that contain it */
-
-	  *status = ffgmul(mfptr,0,status);
-
-	  if(*status != 0) continue;
- 
-	  /* reset the grouping table HDU struct */
-
-	  fits_set_hdustruc(gfptr,status);
-
-	  /* delete the member HDU */
-
-	  if(iomode != READONLY)
-	    *status = fits_delete_hdu(mfptr,&hdutype,status);
-	}
-      else if(rmopt == OPT_RM_ENTRY)
-	{
-	  /* 
-	     The member HDU is only to be removed as an entry from this
-	     grouping table. Actions are (1) find the GRPIDn/GRPLCn 
-	     keywords that link the member to the grouping table, (2)
-	     remove the GRPIDn/GRPLCn keyword from the member HDU header
-	     and (3) remove the member entry from the grouping table
-	  */
-
-	  /*
-	    there is no need to seach for and remove the GRPIDn/GRPLCn
-	    keywords from the member HDU if it has not been opened
-	    in READWRITE mode
-	  */
-
-	  if(iomode == READWRITE)
-	    {	  	      
-	      /* 
-		 determine the group EXTVER value of the grouping table; if
-		 the member HDU and grouping table HDU do not reside in the 
-		 same file then set the groupExtver value to its negative 
-	      */
-	      
-	      *status = fits_read_key_lng(gfptr,"EXTVER",&groupExtver,card,
-					  status);
-	      /* Now, if either the Fptr values are the same, or the root filenames
-	         are the same, then assume these refer to the same file.
-	      */
-	      fits_parse_rootname(mfptr->Fptr->filename, mrootname, status);
-	      fits_parse_rootname(gfptr->Fptr->filename, grootname, status);
-
-	      if((mfptr->Fptr != gfptr->Fptr) && 
-	          strncmp(mrootname, grootname, FLEN_FILENAME))
-                       groupExtver = -1*groupExtver;
-	      
-	      /*
-		retrieve the URLs for the grouping table; note that it is 
-		possible that the grouping table file has two URLs, the 
-		one used to open it and the "real" one pointing to the 
-		actual file being accessed
-	      */
-	      
-	      *status = fits_get_url(gfptr,grpLocation1,grpLocation2,NULL,
-				     NULL,NULL,status);
-	      
-	      if(*status != 0) continue;
-	      
-	      /*
-		if either of the group location strings specify a relative
-		file path then convert them into absolute file paths
-	      */
-
-	      *status = fits_get_cwd(cwd,status);
-	      
-	      if(*grpLocation1 != 0 && *grpLocation1 != '/' &&
-		 !fits_is_url_absolute(grpLocation1))
-		{
-		  strcpy(grpLocation3,cwd);
-		  strcat(grpLocation3,"/");
-		  strcat(grpLocation3,grpLocation1);
-		  fits_clean_url(grpLocation3,grpLocation1,status);
-		}
-	      
-	      if(*grpLocation2 != 0 && *grpLocation2 != '/' &&
-		 !fits_is_url_absolute(grpLocation2))
-		{
-		  strcpy(grpLocation3,cwd);
-		  strcat(grpLocation3,"/");
-		  strcat(grpLocation3,grpLocation2);
-		  fits_clean_url(grpLocation3,grpLocation2,status);
-		}
-	      
-	      /*
-		determine the number of groups to which the member HDU 
-		belongs
-	      */
-	      
-	      *status = fits_get_num_groups(mfptr,&ngroups,status);
-	      
-	      /* reset the HDU keyword position counter to the beginning */
-	      
-	      *status = ffgrec(mfptr,0,card,status);
-	      
-	      /*
-		loop over all the GRPIDn keywords in the member HDU header 
-		and find the appropriate GRPIDn and GRPLCn keywords that 
-		identify it as belonging to the group
-	      */
-	      
-	      for(index = 1, found = 0; index <= ngroups && *status == 0 && 
-		    !found; ++index)
-		{	  
-		  /* read the next GRPIDn keyword in the series */
-		  
-		  sprintf(keyword,"GRPID%d",index);
-		  
-		  *status = fits_read_key_lng(mfptr,keyword,&grpid,card,
-					      status);
-		  if(*status != 0) continue;
-		  
-		  /* 
-		     grpid value == group EXTVER value then we could have a 
-		     match
-		  */
-		  
-		  if(grpid == groupExtver && grpid > 0)
-		    {
-		      /*
-			if GRPID is positive then its a match because 
-			both the member HDU and grouping table HDU reside
-			in the same FITS file
-		      */
-		      
-		      found = index;
-		    }
-		  else if(grpid == groupExtver && grpid < 0)
-		    {
-		      /* 
-			 have to look at the GRPLCn value to determine a 
-			 match because the member HDU and grouping table 
-			 HDU reside in different FITS files
-		      */
-		      
-		      sprintf(keyword,"GRPLC%d",index);
-		      
-		      /* SPR 1738 */
-		      *status = fits_read_key_longstr(mfptr,keyword,&tgrplc,
-						      card, status);
-		      if (0 == *status) {
-			strcpy(grplc,tgrplc);
-			free(tgrplc);
-		      }
-		      		      
-		      if(*status == KEY_NO_EXIST)
-			{
-			  /* 
-			     no GRPLCn keyword value found ==> grouping
-			     convention not followed; nothing we can do 
-			     about it, so just continue
-			  */
-			  
-			  sprintf(card,"No GRPLC%d found for GRPID%d",
-				  index,index);
-			  ffpmsg(card);
-			  *status = 0;
-			  continue;
-			}
-		      else if (*status != 0) continue;
-		      
-		      /* construct the URL for the GRPLCn value */
-		      
-		      prepare_keyvalue(grplc);
-		      
-		      /*
-			if the grplc value specifies a relative path then
-			turn it into a absolute file path for comparison
-			purposes
-		      */
-		      
-		      if(*grplc != 0 && !fits_is_url_absolute(grplc) &&
-			 *grplc != '/')
-			{
-			    /* No, wrong, 
-			       strcpy(grpLocation3,cwd);
-			       should be */
-			    *status = fits_file_name(mfptr,grpLocation3,status);
-			    /* Remove everything after the last / */
-			    if (NULL != (editLocation = strrchr(grpLocation3,'/'))) {
-				*editLocation = '\0';
-			    }
-				
-			  strcat(grpLocation3,"/");
-			  strcat(grpLocation3,grplc);
-			  *status = fits_clean_url(grpLocation3,grplc,
-						   status);
-			}
-		      
-		      /*
-			if the absolute value of GRPIDn is equal to the
-			EXTVER value of the grouping table and (one of the 
-			possible two) grouping table file URL matches the
-			GRPLCn keyword value then we hava a match
-		      */
-		      
-		      if(strcmp(grplc,grpLocation1) == 0  || 
-			 strcmp(grplc,grpLocation2) == 0) 
-			found = index; 
-		    }
-		}
-
-	      /*
-		if found == 0 (false) after the above search then we assume 
-		that it is due to an inpromper updating of the GRPIDn and 
-		GRPLCn keywords in the member header ==> nothing to delete 
-		in the header. Else delete the GRPLCn and GRPIDn keywords 
-		that identify the member HDU with the group HDU and 
-		re-enumerate the remaining GRPIDn and GRPLCn keywords
-	      */
-
-	      if(found != 0)
-		{
-		  sprintf(keyword,"GRPID%d",found);
-		  *status = fits_delete_key(mfptr,keyword,status);
-		  
-		  sprintf(keyword,"GRPLC%d",found);
-		  *status = fits_delete_key(mfptr,keyword,status);
-		  
-		  *status = 0;
-		  
-		  /* call fits_get_num_groups() to re-enumerate the GRPIDn */
-		  
-		  *status = fits_get_num_groups(mfptr,&ngroups,status);
-		} 
-	    }
-
-	  /*
-	     finally, remove the member entry from the current grouping table
-	     pointed to by gfptr
-	  */
-
-	  *status = fits_delete_rows(gfptr,member,1,status);
-	}
-      else
-	{
-	  *status = BAD_OPTION;
-	  ffpmsg("Invalid value specified for the rmopt parameter (ffgmrm)");
-	}
-
-    }while(0);
-
-  if(mfptr != NULL) 
-    {
-      fits_close_file(mfptr,status);
-    }
-
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------
-                 Grouping Table support functions
-  ---------------------------------------------------------------------------*/
-int ffgtgc(fitsfile *gfptr,  /* pointer to the grouping table                */
-	   int *xtensionCol, /* column ID of the MEMBER_XTENSION column      */
-	   int *extnameCol,  /* column ID of the MEMBER_NAME column          */
-	   int *extverCol,   /* column ID of the MEMBER_VERSION column       */
-	   int *positionCol, /* column ID of the MEMBER_POSITION column      */
-	   int *locationCol, /* column ID of the MEMBER_LOCATION column      */
-	   int *uriCol,      /* column ID of the MEMBER_URI_TYPE column      */
-	   int *grptype,     /* group structure type code specifying the
-				grouping table columns that are defined:
-				GT_ID_ALL_URI  (0) ==> all columns defined   
-				GT_ID_REF      (1) ==> reference cols only   
-				GT_ID_POS      (2) ==> position col only     
-				GT_ID_ALL      (3) ==> ref & pos cols        
-				GT_ID_REF_URI (11) ==> ref & loc cols        
-				GT_ID_POS_URI (12) ==> pos & loc cols        */
-	   int *status)      /* return status code                           */
-/*
-   examine the grouping table pointed to by gfptr and determine the column
-   index ID of each possible grouping column. If a column is not found then
-   an index of 0 is returned. the grptype parameter returns the structure
-   of the grouping table ==> what columns are defined.
-*/
-
-{
-
-  char keyvalue[FLEN_VALUE];
-  char comment[FLEN_COMMENT];
-
-
-  if(*status != 0) return(*status);
-
-  do
-    {
-      /*
-	if the HDU does not have an extname of "GROUPING" then it is not
-	a grouping table
-      */
-
-      *status = fits_read_key_str(gfptr,"EXTNAME",keyvalue,comment,status);
-  
-      if(*status == KEY_NO_EXIST) 
-	{
-	  *status = NOT_GROUP_TABLE;
-	  ffpmsg("Specified HDU is not a Grouping Table (ffgtgc)");
-	}
-      if(*status != 0) continue;
-
-      prepare_keyvalue(keyvalue);
-
-      if(fits_strcasecmp(keyvalue,"GROUPING") != 0)
-	{
-	  *status = NOT_GROUP_TABLE;
-	  continue;
-	}
-
-      /*
-        search for the MEMBER_XTENSION, MEMBER_NAME, MEMBER_VERSION,
-	MEMBER_POSITION, MEMBER_LOCATION and MEMBER_URI_TYPE columns
-	and determine their column index ID
-      */
-
-      *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_XTENSION",xtensionCol,
-				status);
-
-      if(*status == COL_NOT_FOUND)
-	{
-	  *status      = 0;
- 	  *xtensionCol = 0;
-	}
-
-      if(*status != 0) continue;
-
-      *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_NAME",extnameCol,status);
-
-      if(*status == COL_NOT_FOUND)
-	{
-	  *status     = 0;
-	  *extnameCol = 0;
-	}
-
-      if(*status != 0) continue;
-
-      *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_VERSION",extverCol,
-				status);
-
-      if(*status == COL_NOT_FOUND)
-	{
-	  *status    = 0;
-	  *extverCol = 0;
-	}
-
-      if(*status != 0) continue;
-
-      *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_POSITION",positionCol,
-				status);
-
-      if(*status == COL_NOT_FOUND)
-	{
-	  *status      = 0;
-	  *positionCol = 0;
-	}
-
-      if(*status != 0) continue;
-
-      *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_LOCATION",locationCol,
-				status);
-
-      if(*status == COL_NOT_FOUND)
-	{
-	  *status      = 0;
-	  *locationCol = 0;
-	}
-
-      if(*status != 0) continue;
-
-      *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_URI_TYPE",uriCol,
-				status);
-
-      if(*status == COL_NOT_FOUND)
-	{
-	  *status = 0;
-	  *uriCol = 0;
-	}
-
-      if(*status != 0) continue;
-
-      /*
-	 determine the type of grouping table structure used by this
-	 grouping table and record it in the grptype parameter
-      */
-
-      if(*xtensionCol && *extnameCol && *extverCol && *positionCol &&
-	 *locationCol && *uriCol) 
-	*grptype = GT_ID_ALL_URI;
-      
-      else if(*xtensionCol && *extnameCol && *extverCol &&
-	      *locationCol && *uriCol) 
-	*grptype = GT_ID_REF_URI;
-
-      else if(*xtensionCol && *extnameCol && *extverCol && *positionCol)
-	*grptype = GT_ID_ALL;
-      
-      else if(*xtensionCol && *extnameCol && *extverCol)
-	*grptype = GT_ID_REF;
-      
-      else if(*positionCol && *locationCol && *uriCol) 
-	*grptype = GT_ID_POS_URI;
-      
-      else if(*positionCol)
-	*grptype = GT_ID_POS;
-      
-      else
-	*status = NOT_GROUP_TABLE;
-      
-    }while(0);
-
-  /*
-    if the table contained more than one column with a reserved name then
-    this cannot be considered a vailid grouping table
-  */
-
-  if(*status == COL_NOT_UNIQUE) 
-    {
-      *status = NOT_GROUP_TABLE;
-      ffpmsg("Specified HDU has multipule Group table cols defined (ffgtgc)");
-    }
-
-  return(*status);
-}
-
-/*****************************************************************************/
-int ffgtdc(int   grouptype,     /* code specifying the type of
-				   grouping table information:
-				   GT_ID_ALL_URI  0 ==> defualt (all columns)
-				   GT_ID_REF      1 ==> ID by reference
-				   GT_ID_POS      2 ==> ID by position
-				   GT_ID_ALL      3 ==> ID by ref. and position
-				   GT_ID_REF_URI 11 ==> (1) + URI info 
-				   GT_ID_POS_URI 12 ==> (2) + URI info       */
-	   int   xtensioncol, /* does MEMBER_XTENSION already exist?         */
-	   int   extnamecol,  /* does MEMBER_NAME aleady exist?              */
-	   int   extvercol,   /* does MEMBER_VERSION already exist?          */
-	   int   positioncol, /* does MEMBER_POSITION already exist?         */
-	   int   locationcol, /* does MEMBER_LOCATION already exist?         */
-	   int   uricol,      /* does MEMBER_URI_TYPE aleardy exist?         */
-	   char *ttype[],     /* array of grouping table column TTYPE names
-				 to define (if *col var false)               */
-	   char *tform[],     /* array of grouping table column TFORM values
-				 to define (if*col variable false)           */
-	   int  *ncols,       /* number of TTYPE and TFORM values returned   */
-	   int  *status)      /* return status code                          */
-
-/*
-  create the TTYPE and TFORM values for the grouping table according to the
-  value of the grouptype parameter and the values of the *col flags. The
-  resulting TTYPE and TFORM are returned in ttype[] and tform[] respectively.
-  The number of TTYPE and TFORMs returned is given by ncols. Both the TTYPE[]
-  and TTFORM[] arrays must contain enough pre-allocated strings to hold
-  the returned information.
-*/
-
-{
-
-  int i = 0;
-
-  char  xtension[]  = "MEMBER_XTENSION";
-  char  xtenTform[] = "8A";
-  
-  char  name[]      = "MEMBER_NAME";
-  char  nameTform[] = "32A";
-
-  char  version[]   = "MEMBER_VERSION";
-  char  verTform[]  = "1J";
-  
-  char  position[]  = "MEMBER_POSITION";
-  char  posTform[]  = "1J";
-
-  char  URI[]       = "MEMBER_URI_TYPE";
-  char  URITform[]  = "3A";
-
-  char  location[]  = "MEMBER_LOCATION";
-  /* SPR 01720, move from 160A to 256A */
-  char  locTform[]  = "256A";
-
-
-  if(*status != 0) return(*status);
-
-  switch(grouptype)
-    {
-      
-    case GT_ID_ALL_URI:
-
-      if(xtensioncol == 0)
-	{
-	  strcpy(ttype[i],xtension);
-	  strcpy(tform[i],xtenTform);
-	  ++i;
-	}
-      if(extnamecol == 0)
-	{
-	  strcpy(ttype[i],name);
-	  strcpy(tform[i],nameTform);
-	  ++i;
-	}
-      if(extvercol == 0)
-	{
-	  strcpy(ttype[i],version);
-	  strcpy(tform[i],verTform);
-	  ++i;
-	}
-      if(positioncol == 0)
-	{
-	  strcpy(ttype[i],position);
-	  strcpy(tform[i],posTform);
-	  ++i;
-	}
-      if(locationcol == 0)
-	{
-	  strcpy(ttype[i],location);
-	  strcpy(tform[i],locTform);
-	  ++i;
-	}
-      if(uricol == 0)
-	{
-	  strcpy(ttype[i],URI);
-	  strcpy(tform[i],URITform);
-	  ++i;
-	}
-      break;
-      
-    case GT_ID_REF:
-      
-      if(xtensioncol == 0)
-	{
-	  strcpy(ttype[i],xtension);
-	  strcpy(tform[i],xtenTform);
-	  ++i;
-	}
-      if(extnamecol == 0)
-	{
-	  strcpy(ttype[i],name);
-	  strcpy(tform[i],nameTform);
-	  ++i;
-	}
-      if(extvercol == 0)
-	{
-	  strcpy(ttype[i],version);
-	  strcpy(tform[i],verTform);
-	  ++i;
-	}
-      break;
-      
-    case GT_ID_POS:
-      
-      if(positioncol == 0)
-	{
-	  strcpy(ttype[i],position);
-	  strcpy(tform[i],posTform);
-	  ++i;
-	}	  
-      break;
-      
-    case GT_ID_ALL:
-      
-      if(xtensioncol == 0)
-	{
-	  strcpy(ttype[i],xtension);
-	  strcpy(tform[i],xtenTform);
-	  ++i;
-	}
-      if(extnamecol == 0)
-	{
-	  strcpy(ttype[i],name);
-	  strcpy(tform[i],nameTform);
-	  ++i;
-	}
-      if(extvercol == 0)
-	{
-	  strcpy(ttype[i],version);
-	  strcpy(tform[i],verTform);
-	  ++i;
-	}
-      if(positioncol == 0)
-	{
-	  strcpy(ttype[i],position);
-	  strcpy(tform[i], posTform);
-	  ++i;
-	}	  
-      
-      break;
-      
-    case GT_ID_REF_URI:
-      
-      if(xtensioncol == 0)
-	{
-	  strcpy(ttype[i],xtension);
-	  strcpy(tform[i],xtenTform);
-	  ++i;
-	}
-      if(extnamecol == 0)
-	{
-	  strcpy(ttype[i],name);
-	  strcpy(tform[i],nameTform);
-	  ++i;
-	}
-      if(extvercol == 0)
-	{
-	  strcpy(ttype[i],version);
-	  strcpy(tform[i],verTform);
-	  ++i;
-	}
-      if(locationcol == 0)
-	{
-	  strcpy(ttype[i],location);
-	  strcpy(tform[i],locTform);
-	  ++i;
-	}
-      if(uricol == 0)
-	{
-	  strcpy(ttype[i],URI);
-	  strcpy(tform[i],URITform);
-	  ++i;
-	}
-      break;
-      
-    case GT_ID_POS_URI:
-      
-      if(positioncol == 0)
-	{
-	  strcpy(ttype[i],position);
-	  strcpy(tform[i],posTform);
-	  ++i;
-	}
-      if(locationcol == 0)
-	{
-	  strcpy(ttype[i],location);
-	  strcpy(tform[i],locTform);
-	  ++i;
-	}
-      if(uricol == 0)
-	{
-	  strcpy(ttype[i],URI);
-	  strcpy(tform[i],URITform);
-	  ++i;
-	}
-      break;
-      
-    default:
-      
-      *status = BAD_OPTION;
-      ffpmsg("Invalid value specified for the grouptype parameter (ffgtdc)");
-
-      break;
-
-    }
-
-  *ncols = i;
-  
-  return(*status);
-}
-
-/*****************************************************************************/
-int ffgmul(fitsfile *mfptr,   /* pointer to the grouping table member HDU    */
-           int       rmopt,   /* 0 ==> leave GRPIDn/GRPLCn keywords,
-				 1 ==> remove GRPIDn/GRPLCn keywords         */
-	   int      *status) /* return status code                          */
-
-/*
-   examine all the GRPIDn and GRPLCn keywords in the member HDUs header
-   and remove the member from the grouping tables referenced; This
-   effectively "unlinks" the member from all of its groups. The rmopt 
-   specifies if the GRPIDn/GRPLCn keywords are to be removed from the
-   member HDUs header after the unlinking.
-*/
-
-{
-  int memberPosition = 0;
-  int iomode;
-
-  long index;
-  long ngroups      = 0;
-  long memberExtver = 0;
-  long memberID     = 0;
-
-  char mbrLocation1[FLEN_FILENAME];
-  char mbrLocation2[FLEN_FILENAME];
-  char memberHDUtype[FLEN_VALUE];
-  char memberExtname[FLEN_VALUE];
-  char keyword[FLEN_KEYWORD];
-  char card[FLEN_CARD];
-
-  fitsfile *gfptr = NULL;
-
-
-  if(*status != 0) return(*status);
-
-  do
-    {
-      /* 
-	 determine location parameters of the member HDU; note that
-	 default values are supplied if the expected keywords are not
-	 found
-      */
-
-      *status = fits_read_key_str(mfptr,"XTENSION",memberHDUtype,card,status);
-
-      if(*status == KEY_NO_EXIST) 
-	{
-	  strcpy(memberHDUtype,"PRIMARY");
-	  *status = 0;
-	}
-      prepare_keyvalue(memberHDUtype);
-
-      *status = fits_read_key_lng(mfptr,"EXTVER",&memberExtver,card,status);
-
-      if(*status == KEY_NO_EXIST) 
-	{
-	  memberExtver = 1;
-	  *status      = 0;
-	}
-
-      *status = fits_read_key_str(mfptr,"EXTNAME",memberExtname,card,status);
-
-      if(*status == KEY_NO_EXIST) 
-	{
-	  memberExtname[0] = 0;
-	  *status          = 0;
-	}
-      prepare_keyvalue(memberExtname);
-
-      fits_get_hdu_num(mfptr,&memberPosition);
-
-      *status = fits_get_url(mfptr,mbrLocation1,mbrLocation2,NULL,NULL,
-			     NULL,status);
-
-      if(*status != 0) continue;
-
-      /*
-	 open each grouping table linked to this HDU and remove the member 
-	 from the grouping tables
-      */
-
-      *status = fits_get_num_groups(mfptr,&ngroups,status);
-
-      /* loop over each group linked to the member HDU */
-
-      for(index = 1; index <= ngroups && *status == 0; ++index)
-	{
-	  /* open the (index)th group linked to the member HDU */ 
-
-	  *status = fits_open_group(mfptr,index,&gfptr,status);
-
-	  /* if the group could not be opened then just skip it */
-
-	  if(*status != 0)
-	    {
-	      *status = 0;
-	      sprintf(card,"Cannot open the %dth group table (ffgmul)",
-		      (int)index);
-	      ffpmsg(card);
-	      continue;
-	    }
-
-	  /*
-	    make sure the grouping table can be modified before proceeding
-	  */
-	  
-	  fits_file_mode(gfptr,&iomode,status);
-
-	  if(iomode != READWRITE)
-	    {
-	      sprintf(card,"The %dth group cannot be modified (ffgtam)",
-		      (int)index);
-	      ffpmsg(card);
-	      continue;
-	    }
-
-	  /* 
-	     try to find the member's row within the grouping table; first 
-	     try using the member HDU file's "real" URL string then try
-	     using its originally opened URL string if either string exist
-	   */
-	     
-	  memberID = 0;
- 
-	  if(strlen(mbrLocation1) != 0)
-	    {
-	      *status = ffgmf(gfptr,memberHDUtype,memberExtname,memberExtver,
-			      memberPosition,mbrLocation1,&memberID,status);
-	    }
-
-	  if(*status == MEMBER_NOT_FOUND && strlen(mbrLocation2) != 0)
-	    {
-	      *status = 0;
-	      *status = ffgmf(gfptr,memberHDUtype,memberExtname,memberExtver,
-			      memberPosition,mbrLocation2,&memberID,status);
-	    }
-
-	  /* if the member was found then delete it from the grouping table */
-
-	  if(*status == 0)
-	    *status = fits_delete_rows(gfptr,memberID,1,status);
-
-	  /*
-	     continue the loop over all member groups even if an error
-	     was generated
-	  */
-
-	  if(*status == MEMBER_NOT_FOUND)
-	    {
-	      ffpmsg("cannot locate member's entry in group table (ffgmul)");
-	    }
-	  *status = 0;
-
-	  /*
-	     close the file pointed to by gfptr if it is non NULL to
-	     prepare for the next loop iterration
-	  */
-
-	  if(gfptr != NULL)
-	    {
-	      fits_close_file(gfptr,status);
-	      gfptr = NULL;
-	    }
-	}
-
-      if(*status != 0) continue;
-
-      /*
-	 if rmopt is non-zero then find and delete the GRPIDn/GRPLCn 
-	 keywords from the member HDU header
-      */
-
-      if(rmopt != 0)
-	{
-	  fits_file_mode(mfptr,&iomode,status);
-
-	  if(iomode == READONLY)
-	    {
-	      ffpmsg("Cannot modify member HDU, opened READONLY (ffgmul)");
-	      continue;
-	    }
-
-	  /* delete all the GRPIDn/GRPLCn keywords */
-
-	  for(index = 1; index <= ngroups && *status == 0; ++index)
-	    {
-	      sprintf(keyword,"GRPID%d",(int)index);
-	      fits_delete_key(mfptr,keyword,status);
-	      
-	      sprintf(keyword,"GRPLC%d",(int)index);
-	      fits_delete_key(mfptr,keyword,status);
-
-	      if(*status == KEY_NO_EXIST) *status = 0;
-	    }
-	}
-    }while(0);
-
-  /* make sure the gfptr has been closed */
-
-  if(gfptr != NULL)
-    { 
-      fits_close_file(gfptr,status);
-    }
-
-return(*status);
-}
-
-/*--------------------------------------------------------------------------*/
-int ffgmf(fitsfile *gfptr, /* pointer to grouping table HDU to search       */
-	   char *xtension,  /* XTENSION value for member HDU                */
-	   char *extname,   /* EXTNAME value for member HDU                 */
-	   int   extver,    /* EXTVER value for member HDU                  */
-	   int   position,  /* HDU position value for member HDU            */
-	   char *location,  /* FITS file location value for member HDU      */
-	   long *member,    /* member HDU ID within group table (if found)  */
-	   int  *status)    /* return status code                           */
-
-/*
-   try to find the entry for the member HDU defined by the xtension, extname,
-   extver, position, and location parameters within the grouping table
-   pointed to by gfptr. If the member HDU is found then its ID (row number)
-   within the grouping table is returned in the member variable; if not
-   found then member is returned with a value of 0 and the status return
-   code will be set to MEMBER_NOT_FOUND.
-
-   Note that the member HDU postion information is used to obtain a member
-   match only if the grouping table type is GT_ID_POS_URI or GT_ID_POS. This
-   is because the position information can become invalid much more
-   easily then the reference information for a group member.
-*/
-
-{
-  int xtensionCol,extnameCol,extverCol,positionCol,locationCol,uriCol;
-  int mposition = 0;
-  int grptype;
-  int dummy;
-  int i;
-
-  long nmembers = 0;
-  long mextver  = 0;
- 
-  char  charBuff1[FLEN_FILENAME];
-  char  charBuff2[FLEN_FILENAME];
-  char  tmpLocation[FLEN_FILENAME];
-  char  mbrLocation1[FLEN_FILENAME];
-  char  mbrLocation2[FLEN_FILENAME];
-  char  mbrLocation3[FLEN_FILENAME];
-  char  grpLocation1[FLEN_FILENAME];
-  char  grpLocation2[FLEN_FILENAME];
-  char  cwd[FLEN_FILENAME];
-
-  char  nstr[] = {'\0'};
-  char *tmpPtr[2];
-
-  if(*status != 0) return(*status);
-
-  *member = 0;
-
-  tmpPtr[0] = charBuff1;
-  tmpPtr[1] = charBuff2;
-
-
-  if(*status != 0) return(*status);
-
-  /*
-    if the passed LOCATION value is not an absolute URL then turn it
-    into an absolute path
-  */
-
-  if(location == NULL)
-    {
-      *tmpLocation = 0;
-    }
-
-  else if(*location == 0)
-    {
-      *tmpLocation = 0;
-    }
-
-  else if(!fits_is_url_absolute(location))
-    {
-      fits_path2url(location,tmpLocation,status);
-
-      if(*tmpLocation != '/')
-	{
-	  fits_get_cwd(cwd,status);
-	  strcat(cwd,"/");
-	  strcat(cwd,tmpLocation);
-	  fits_clean_url(cwd,tmpLocation,status);
-	}
-    }
-
-  else
-    strcpy(tmpLocation,location);
-
-  /*
-     retrieve the Grouping Convention reserved column positions within
-     the grouping table
-  */
-
-  *status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol,
-		   &locationCol,&uriCol,&grptype,status);
-
-  /* retrieve the number of group members */
-
-  *status = fits_get_num_members(gfptr,&nmembers,status);
-	      
-  /* 
-     loop over all grouping table rows until the member HDU is found 
-  */
-
-  for(i = 1; i <= nmembers && *member == 0 && *status == 0; ++i)
-    {
-      if(xtensionCol != 0)
-	{
-	  fits_read_col_str(gfptr,xtensionCol,i,1,1,nstr,tmpPtr,&dummy,status);
-	  if(fits_strcasecmp(tmpPtr[0],xtension) != 0) continue;
-	}
-	  
-      if(extnameCol  != 0)
-	{
-	  fits_read_col_str(gfptr,extnameCol,i,1,1,nstr,tmpPtr,&dummy,status);
-	  if(fits_strcasecmp(tmpPtr[0],extname) != 0) continue;
-	}
-	  
-      if(extverCol   != 0)
-	{
-	  fits_read_col_lng(gfptr,extverCol,i,1,1,0,
-			    (long*)&mextver,&dummy,status);
-	  if(extver != mextver) continue;
-	}
-      
-      /* note we only use postionCol if we have to */
-
-      if(positionCol != 0 && 
-	            (grptype == GT_ID_POS || grptype == GT_ID_POS_URI))
-	{
-	  fits_read_col_int(gfptr,positionCol,i,1,1,0,
-			    &mposition,&dummy,status);
-	  if(position != mposition) continue;
-	}
-      
-      /*
-	if no location string was passed to the function then assume that
-	the calling application does not wish to use it as a comparision
-	critera ==> if we got this far then we have a match
-      */
-
-      if(location == NULL)
-	{
-	  ffpmsg("NULL Location string given ==> ingore location (ffgmf)");
-	  *member = i;
-	  continue;
-	}
-
-      /*
-	if the grouping table MEMBER_LOCATION column exists then read the
-	location URL for the member, else set the location string to
-	a zero-length string for subsequent comparisions
-      */
-
-      if(locationCol != 0)
-	{
-	  fits_read_col_str(gfptr,locationCol,i,1,1,nstr,tmpPtr,&dummy,status);
-	  strcpy(mbrLocation1,tmpPtr[0]);
-	  *mbrLocation2 = 0;
-	}
-      else
-	*mbrLocation1 = 0;
-
-      /* 
-	 if the member location string from the grouping table is zero 
-	 length (either implicitly or explicitly) then assume that the 
-	 member HDU is in the same file as the grouping table HDU; retrieve
-	 the possible URL values of the grouping table HDU file 
-       */
-
-      if(*mbrLocation1 == 0)
-	{
-	  /* retrieve the possible URLs of the grouping table file */
-	  *status = fits_get_url(gfptr,mbrLocation1,mbrLocation2,NULL,NULL,
-				 NULL,status);
-
-	  /* if non-NULL, make sure the first URL is absolute or a full path */
-	  if(*mbrLocation1 != 0 && !fits_is_url_absolute(mbrLocation1) &&
-	     *mbrLocation1 != '/')
-	    {
-	      fits_get_cwd(cwd,status);
-	      strcat(cwd,"/");
-	      strcat(cwd,mbrLocation1);
-	      fits_clean_url(cwd,mbrLocation1,status);
-	    }
-
-	  /* if non-NULL, make sure the first URL is absolute or a full path */
-	  if(*mbrLocation2 != 0 && !fits_is_url_absolute(mbrLocation2) &&
-	     *mbrLocation2 != '/')
-	    {
-	      fits_get_cwd(cwd,status);
-	      strcat(cwd,"/");
-	      strcat(cwd,mbrLocation2);
-	      fits_clean_url(cwd,mbrLocation2,status);
-	    }
-	}
-
-      /*
-	if the member location was specified, then make sure that it is
-	either an absolute URL or specifies a full path
-      */
-
-      else if(!fits_is_url_absolute(mbrLocation1) && *mbrLocation1 != '/')
-	{
-	  strcpy(mbrLocation2,mbrLocation1);
-
-	  /* get the possible URLs for the grouping table file */
-	  *status = fits_get_url(gfptr,grpLocation1,grpLocation2,NULL,NULL,
-				 NULL,status);
-	  
-	  if(*grpLocation1 != 0)
-	    {
-	      /* make sure the first grouping table URL is absolute */
-	      if(!fits_is_url_absolute(grpLocation1) && *grpLocation1 != '/')
-		{
-		  fits_get_cwd(cwd,status);
-		  strcat(cwd,"/");
-		  strcat(cwd,grpLocation1);
-		  fits_clean_url(cwd,grpLocation1,status);
-		}
-	      
-	      /* create an absoute URL for the member */
-
-	      fits_relurl2url(grpLocation1,mbrLocation1,mbrLocation3,status);
-	      
-	      /* 
-		 if URL construction succeeded then copy it to the
-		 first location string; else set the location string to 
-		 empty
-	      */
-
-	      if(*status == 0)
-		{
-		  strcpy(mbrLocation1,mbrLocation3);
-		}
-
-	      else if(*status == URL_PARSE_ERROR)
-		{
-		  *status       = 0;
-		  *mbrLocation1 = 0;
-		}
-	    }
-	  else
-	    *mbrLocation1 = 0;
-
-	  if(*grpLocation2 != 0)
-	    {
-	      /* make sure the second grouping table URL is absolute */
-	      if(!fits_is_url_absolute(grpLocation2) && *grpLocation2 != '/')
-		{
-		  fits_get_cwd(cwd,status);
-		  strcat(cwd,"/");
-		  strcat(cwd,grpLocation2);
-		  fits_clean_url(cwd,grpLocation2,status);
-		}
-	      
-	      /* create an absolute URL for the member */
-
-	      fits_relurl2url(grpLocation2,mbrLocation2,mbrLocation3,status);
-	      
-	      /* 
-		 if URL construction succeeded then copy it to the
-		 second location string; else set the location string to 
-		 empty
-	      */
-
-	      if(*status == 0)
-		{
-		  strcpy(mbrLocation2,mbrLocation3);
-		}
-
-	      else if(*status == URL_PARSE_ERROR)
-		{
-		  *status       = 0;
-		  *mbrLocation2 = 0;
-		}
-	    }
-	  else
-	    *mbrLocation2 = 0;
-	}
-
-      /*
-	compare the passed member HDU file location string with the
-	(possibly two) member location strings to see if there is a match
-       */
-
-      if(strcmp(mbrLocation1,tmpLocation) != 0 && 
-	 strcmp(mbrLocation2,tmpLocation) != 0   ) continue;
-  
-      /* if we made it this far then a match to the member HDU was found */
-      
-      *member = i;
-    }
-
-  /* if a match was not found then set the return status code */
-
-  if(*member == 0 && *status == 0) 
-    {
-      *status = MEMBER_NOT_FOUND;
-      ffpmsg("Cannot find specified member HDU (ffgmf)");
-    }
-
-  return(*status);
-}
-
-/*--------------------------------------------------------------------------
-                        Recursive Group Functions
-  --------------------------------------------------------------------------*/
-int ffgtrmr(fitsfile   *gfptr,  /* FITS file pointer to group               */
-	    HDUtracker *HDU,    /* list of processed HDUs                   */
-	    int        *status) /* return status code                       */
-	    
-/*
-  recursively remove a grouping table and all its members. Each member of
-  the grouping table pointed to by gfptr it processed. If the member is itself
-  a grouping table then ffgtrmr() is recursively called to process all
-  of its members. The HDUtracker struct *HDU is used to make sure a member
-  is not processed twice, thus avoiding an infinite loop (e.g., a grouping
-  table contains itself as a member).
-*/
-
-{
-  int i;
-  int hdutype;
-
-  long nmembers = 0;
-
-  char keyvalue[FLEN_VALUE];
-  char comment[FLEN_COMMENT];
-  
-  fitsfile *mfptr = NULL;
-
-
-  if(*status != 0) return(*status);
-
-  /* get the number of members contained by this grouping table */
-
-  *status = fits_get_num_members(gfptr,&nmembers,status);
-
-  /* loop over all group members and delete them */
-
-  for(i = nmembers; i > 0 && *status == 0; --i)
-    {
-      /* open the member HDU */
-
-      *status = fits_open_member(gfptr,i,&mfptr,status);
-
-      /* if the member cannot be opened then just skip it and continue */
-
-      if(*status == MEMBER_NOT_FOUND) 
-	{
-	  *status = 0;
-	  continue;
-	}
-
-      /* Any other error is a reason to abort */
-      
-      if(*status != 0) continue;
-
-      /* add the member HDU to the HDUtracker struct */
-
-      *status = fftsad(mfptr,HDU,NULL,NULL);
-
-      /* status == HDU_ALREADY_TRACKED ==> HDU has already been processed */
-
-      if(*status == HDU_ALREADY_TRACKED) 
-	{
-	  *status = 0;
-	  fits_close_file(mfptr,status);
-	  continue;
-	}
-      else if(*status != 0) continue;
-
-      /* determine if the member HDU is itself a grouping table */
-
-      *status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,comment,status);
-
-      /* if no EXTNAME is found then the HDU cannot be a grouping table */ 
-
-      if(*status == KEY_NO_EXIST) 
-	{
-	  *status     = 0;
-	  keyvalue[0] = 0;
-	}
-      prepare_keyvalue(keyvalue);
-
-      /* Any other error is a reason to abort */
-      
-      if(*status != 0) continue;
-
-      /* 
-	 if the EXTNAME == GROUPING then the member is a grouping table 
-	 and we must call ffgtrmr() to process its members
-      */
-
-      if(fits_strcasecmp(keyvalue,"GROUPING") == 0)
-	  *status = ffgtrmr(mfptr,HDU,status);  
-
-      /* 
-	 unlink all the grouping tables that contain this HDU as a member 
-	 and then delete the HDU (if not a PHDU)
-      */
-
-      if(fits_get_hdu_num(mfptr,&hdutype) == 1)
-	      *status = ffgmul(mfptr,1,status);
-      else
-	  {
-	      *status = ffgmul(mfptr,0,status);
-	      *status = fits_delete_hdu(mfptr,&hdutype,status);
-	  }
-
-      /* close the fitsfile pointer */
-
-      fits_close_file(mfptr,status);
-    }
-
-  return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgtcpr(fitsfile   *infptr,  /* input FITS file pointer                 */
-	    fitsfile   *outfptr, /* output FITS file pointer                */
-	    int         cpopt,   /* code specifying copy options:
-				    OPT_GCP_GPT (0) ==> cp only grouping table
-				    OPT_GCP_ALL (2) ==> recusrively copy 
-				    members and their members (if groups)   */
-	    HDUtracker *HDU,     /* list of already copied HDUs             */
-	    int        *status)  /* return status code                      */
-
-/*
-  copy a Group to a new FITS file. If the cpopt parameter is set to 
-  OPT_GCP_GPT (copy grouping table only) then the existing members have their 
-  GRPIDn and GRPLCn keywords updated to reflect the existance of the new group,
-  since they now belong to another group. If cpopt is set to OPT_GCP_ALL 
-  (copy grouping table and members recursively) then the original members are 
-  not updated; the new grouping table is modified to include only the copied 
-  member HDUs and not the original members.
-
-  Note that this function is recursive. When copt is OPT_GCP_ALL it will call
-  itself whenever a member HDU of the current grouping table is itself a
-  grouping table (i.e., EXTNAME = 'GROUPING').
-*/
-
-{
-
-  int i;
-  int nexclude     = 8;
-  int hdutype      = 0;
-  int groupHDUnum  = 0;
-  int numkeys      = 0;
-  int keypos       = 0;
-  int startSearch  = 0;
-  int newPosition  = 0;
-
-  long nmembers    = 0;
-  long tfields     = 0;
-  long newTfields  = 0;
-
-  char keyword[FLEN_KEYWORD];
-  char keyvalue[FLEN_VALUE];
-  char card[FLEN_CARD];
-  char comment[FLEN_CARD];
-  char *tkeyvalue;
-
-  char *includeList[] = {"*"};
-  char *excludeList[] = {"EXTNAME","EXTVER","GRPNAME","GRPID#","GRPLC#",
-			 "THEAP","TDIM#","T????#"};
-
-  fitsfile *mfptr = NULL;
-
-
-  if(*status != 0) return(*status);
-
-  do
-    {
-      /*
-	create a new grouping table in the FITS file pointed to by outptr
-      */
-
-      *status = fits_get_num_members(infptr,&nmembers,status);
-
-      *status = fits_read_key_str(infptr,"GRPNAME",keyvalue,card,status);
-
-      if(*status == KEY_NO_EXIST)
-	{
-	  keyvalue[0] = 0;
-	  *status     = 0;
-	}
-      prepare_keyvalue(keyvalue);
-
-      *status = fits_create_group(outfptr,keyvalue,GT_ID_ALL_URI,status);
-     
-      /* save the new grouping table's HDU position for future use */
-
-      fits_get_hdu_num(outfptr,&groupHDUnum);
-
-      /* update the HDUtracker struct with the grouping table's new position */
-      
-      *status = fftsud(infptr,HDU,groupHDUnum,NULL);
-
-      /*
-	Now populate the copied grouping table depending upon the 
-	copy option parameter value
-      */
-
-      switch(cpopt)
-	{
-
-	  /*
-	    for the "copy grouping table only" option we only have to
-	    add the members of the original grouping table to the new
-	    grouping table
-	  */
-
-	case OPT_GCP_GPT:
-
-	  for(i = 1; i <= nmembers && *status == 0; ++i)
-	    {
-	      *status = fits_open_member(infptr,i,&mfptr,status);
-	      *status = fits_add_group_member(outfptr,mfptr,0,status);
-
-	      fits_close_file(mfptr,status);
-	      mfptr = NULL;
-	    }
-
-	  break;
-
-	case OPT_GCP_ALL:
-      
-	  /*
-	    for the "copy the entire group" option
- 	  */
-
-	  /* loop over all the grouping table members */
-
-	  for(i = 1; i <= nmembers && *status == 0; ++i)
-	    {
-	      /* open the ith member */
-
-	      *status = fits_open_member(infptr,i,&mfptr,status);
-
-	      if(*status != 0) continue;
-
-	      /* add it to the HDUtracker struct */
-
-	      *status = fftsad(mfptr,HDU,&newPosition,NULL);
-
-	      /* if already copied then just add the member to the group */
-
-	      if(*status == HDU_ALREADY_TRACKED)
-		{
-		  *status = 0;
-		  *status = fits_add_group_member(outfptr,NULL,newPosition,
-						  status);
-		  fits_close_file(mfptr,status);
-                  mfptr = NULL;
-		  continue;
-		}
-	      else if(*status != 0) continue;
-
-	      /* see if the member is a grouping table */
-
-	      *status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,card,
-					  status);
-
-	      if(*status == KEY_NO_EXIST)
-		{
-		  keyvalue[0] = 0;
-		  *status     = 0;
-		}
-	      prepare_keyvalue(keyvalue);
-
-	      /*
-		if the member is a grouping table then copy it and all of
-		its members using ffgtcpr(), else copy it using
-		fits_copy_member(); the outptr will point to the newly
-		copied member upon return from both functions
-	      */
-
-	      if(fits_strcasecmp(keyvalue,"GROUPING") == 0)
-		*status = ffgtcpr(mfptr,outfptr,OPT_GCP_ALL,HDU,status);
-	      else
-		*status = fits_copy_member(infptr,outfptr,i,OPT_MCP_NADD,
-					   status);
-
-	      /* retrieve the position of the newly copied member */
-
-	      fits_get_hdu_num(outfptr,&newPosition);
-
-	      /* update the HDUtracker struct with member's new position */
-	      
-	      if(fits_strcasecmp(keyvalue,"GROUPING") != 0)
-		*status = fftsud(mfptr,HDU,newPosition,NULL);
-
-	      /* move the outfptr back to the copied grouping table HDU */
-
-	      *status = fits_movabs_hdu(outfptr,groupHDUnum,&hdutype,status);
-
-	      /* add the copied member HDU to the copied grouping table */
-
-	      *status = fits_add_group_member(outfptr,NULL,newPosition,status);
-
-	      /* close the mfptr pointer */
-
-	      fits_close_file(mfptr,status);
-	      mfptr = NULL;
-	    }
-
-	  break;
-
-	default:
-	  
-	  *status = BAD_OPTION;
-	  ffpmsg("Invalid value specified for cmopt parameter (ffgtcpr)");
-	  break;
-	}
-
-      if(*status != 0) continue; 
-
-      /* 
-	 reposition the outfptr to the grouping table so that the grouping
-	 table is the CHDU upon return to the calling function
-      */
-
-      fits_movabs_hdu(outfptr,groupHDUnum,&hdutype,status);
-
-      /*
-	 copy all auxiliary keyword records from the original grouping table
-	 to the new grouping table; they are copied in their original order
-	 and inserted just before the TTYPE1 keyword record
-      */
-
-      *status = fits_read_card(outfptr,"TTYPE1",card,status);
-      *status = fits_get_hdrpos(outfptr,&numkeys,&keypos,status);
-      --keypos;
-
-      startSearch = 8;
-
-      while(*status == 0)
-	{
-	  ffgrec(infptr,startSearch,card,status);
-
-	  *status = fits_find_nextkey(infptr,includeList,1,excludeList,
-				      nexclude,card,status);
-
-	  *status = fits_get_hdrpos(infptr,&numkeys,&startSearch,status);
-
-	  --startSearch;
-	  /* SPR 1738 */
-	  if (strncmp(card,"GRPLC",5)) {
-	    /* Not going to be a long string so we're ok */
-	    *status = fits_insert_record(outfptr,keypos,card,status);
-	  } else {
-	    /* We could have a long string */
-	    *status = fits_read_record(infptr,startSearch,card,status);
-	    card[9] = '\0';
-	    *status = fits_read_key_longstr(infptr,card,&tkeyvalue,comment,
-					    status);
-	    if (0 == *status) {
-	      fits_insert_key_longstr(outfptr,card,tkeyvalue,comment,status);
-	      fits_write_key_longwarn(outfptr,status);
-	      free(tkeyvalue);
-	    }
-	  }
-	  
-	  ++keypos;
-	}
-      
-	  
-      if(*status == KEY_NO_EXIST) 
-	*status = 0;
-      else if(*status != 0) continue;
-
-      /*
-	 search all the columns of the original grouping table and copy
-	 those to the new grouping table that were not part of the grouping
-	 convention. Note that is legal to have additional columns in a
-	 grouping table. Also note that the order of the columns may
-	 not be the same in the original and copied grouping table.
-      */
-
-      /* retrieve the number of columns in the original and new group tables */
-
-      *status = fits_read_key_lng(infptr,"TFIELDS",&tfields,card,status);
-      *status = fits_read_key_lng(outfptr,"TFIELDS",&newTfields,card,status);
-
-      for(i = 1; i <= tfields; ++i)
-	{
-	  sprintf(keyword,"TTYPE%d",i);
-	  *status = fits_read_key_str(infptr,keyword,keyvalue,card,status);
-	  
-	  if(*status == KEY_NO_EXIST)
-	    {
-	      *status = 0;
-              keyvalue[0] = 0;
-	    }
-	  prepare_keyvalue(keyvalue);
-
-	  if(fits_strcasecmp(keyvalue,"MEMBER_XTENSION") != 0 &&
-	     fits_strcasecmp(keyvalue,"MEMBER_NAME")     != 0 &&
-	     fits_strcasecmp(keyvalue,"MEMBER_VERSION")  != 0 &&
-	     fits_strcasecmp(keyvalue,"MEMBER_POSITION") != 0 &&
-	     fits_strcasecmp(keyvalue,"MEMBER_LOCATION") != 0 &&
-	     fits_strcasecmp(keyvalue,"MEMBER_URI_TYPE") != 0   )
-	    {
- 
-	      /* SPR 3956, add at the end of the table */
-	      *status = fits_copy_col(infptr,outfptr,i,newTfields+1,1,status);
-	      ++newTfields;
-	    }
-	}
-
-    }while(0);
-
-  if(mfptr != NULL) 
-    {
-      fits_close_file(mfptr,status);
-    }
-
-  return(*status);
-}
-
-/*--------------------------------------------------------------------------
-                HDUtracker struct manipulation functions
-  --------------------------------------------------------------------------*/
-int fftsad(fitsfile   *mfptr,       /* pointer to an member HDU             */
-	   HDUtracker *HDU,         /* pointer to an HDU tracker struct     */
-	   int        *newPosition, /* new HDU position of the member HDU   */
-	   char       *newFileName) /* file containing member HDU           */
-
-/*
-  add an HDU to the HDUtracker struct pointed to by HDU. The HDU is only 
-  added if it does not already reside in the HDUtracker. If it already
-  resides in the HDUtracker then the new HDU postion and file name are
-  returned in  newPosition and newFileName (if != NULL)
-*/
-
-{
-  int i;
-  int hdunum;
-  int status = 0;
-
-  char filename1[FLEN_FILENAME];
-  char filename2[FLEN_FILENAME];
-
-  do
-    {
-      /* retrieve the HDU's position within the FITS file */
-
-      fits_get_hdu_num(mfptr,&hdunum);
-      
-      /* retrieve the HDU's file name */
-      
-      status = fits_file_name(mfptr,filename1,&status);
-      
-      /* parse the file name and construct the "standard" URL for it */
-      
-      status = ffrtnm(filename1,filename2,&status);
-      
-      /* 
-	 examine all the existing HDUs in the HDUtracker an see if this HDU
-	 has already been registered
-      */
-
-      for(i = 0; 
-       i < HDU->nHDU &&  !(HDU->position[i] == hdunum 
-			   && strcmp(HDU->filename[i],filename2) == 0);
-	  ++i);
-
-      if(i != HDU->nHDU) 
-	{
-	  status = HDU_ALREADY_TRACKED;
-	  if(newPosition != NULL) *newPosition = HDU->newPosition[i];
-	  if(newFileName != NULL) strcpy(newFileName,HDU->newFilename[i]);
-	  continue;
-	}
-
-      if(HDU->nHDU == MAX_HDU_TRACKER) 
-	{
-	  status = TOO_MANY_HDUS_TRACKED;
-	  continue;
-	}
-
-      HDU->filename[i] = (char*) malloc(FLEN_FILENAME * sizeof(char));
-
-      if(HDU->filename[i] == NULL)
-	{
-	  status = MEMORY_ALLOCATION;
-	  continue;
-	}
-
-      HDU->newFilename[i] = (char*) malloc(FLEN_FILENAME * sizeof(char));
-
-      if(HDU->newFilename[i] == NULL)
-	{
-	  status = MEMORY_ALLOCATION;
-	  free(HDU->filename[i]);
-	  continue;
-	}
-
-      HDU->position[i]    = hdunum;
-      HDU->newPosition[i] = hdunum;
-
-      strcpy(HDU->filename[i],filename2);
-      strcpy(HDU->newFilename[i],filename2);
- 
-       ++(HDU->nHDU);
-
-    }while(0);
-
-  return(status);
-}
-/*--------------------------------------------------------------------------*/
-int fftsud(fitsfile   *mfptr,       /* pointer to an member HDU             */
-	   HDUtracker *HDU,         /* pointer to an HDU tracker struct     */
-	   int         newPosition, /* new HDU position of the member HDU   */
-	   char       *newFileName) /* file containing member HDU           */
-
-/*
-  update the HDU information in the HDUtracker struct pointed to by HDU. The 
-  HDU to update is pointed to by mfptr. If non-zero, the value of newPosition
-  is used to update the HDU->newPosition[] value for the mfptr, and if
-  non-NULL the newFileName value is used to update the HDU->newFilename[]
-  value for mfptr.
-*/
-
-{
-  int i;
-  int hdunum;
-  int status = 0;
-
-  char filename1[FLEN_FILENAME];
-  char filename2[FLEN_FILENAME];
-
-
-  /* retrieve the HDU's position within the FITS file */
-  
-  fits_get_hdu_num(mfptr,&hdunum);
-  
-  /* retrieve the HDU's file name */
-  
-  status = fits_file_name(mfptr,filename1,&status);
-  
-  /* parse the file name and construct the "standard" URL for it */
-      
-  status = ffrtnm(filename1,filename2,&status);
-
-  /* 
-     examine all the existing HDUs in the HDUtracker an see if this HDU
-     has already been registered
-  */
-
-  for(i = 0; i < HDU->nHDU && 
-      !(HDU->position[i] == hdunum && strcmp(HDU->filename[i],filename2) == 0);
-      ++i);
-
-  /* if previously registered then change newPosition and newFileName */
-
-  if(i != HDU->nHDU) 
-    {
-      if(newPosition  != 0) HDU->newPosition[i] = newPosition;
-      if(newFileName  != NULL) 
-	{
-	  strcpy(HDU->newFilename[i],newFileName);
-	}
-    }
-  else
-    status = MEMBER_NOT_FOUND;
- 
-  return(status);
-}
-
-/*---------------------------------------------------------------------------*/
-
-void prepare_keyvalue(char *keyvalue) /* string containing keyword value     */
-
-/*
-  strip off all single quote characters "'" and blank spaces from a keyword
-  value retrieved via fits_read_key*() routines
-
-  this is necessary so that a standard comparision of keyword values may
-  be made
-*/
-
-{
-
-  int i;
-  int length;
-
-  /*
-    strip off any leading or trailing single quotes (`) and (') from
-    the keyword value
-  */
-
-  length = strlen(keyvalue) - 1;
-
-  if(keyvalue[0] == '\'' && keyvalue[length] == '\'')
-    {
-      for(i = 0; i < length - 1; ++i) keyvalue[i] = keyvalue[i+1];
-      keyvalue[length-1] = 0;
-    }
-  
-  /*
-    strip off any trailing blanks from the keyword value; note that if the
-    keyvalue consists of nothing but blanks then no blanks are stripped
-  */
-
-  length = strlen(keyvalue) - 1;
-
-  for(i = 0; i < length && keyvalue[i] == ' '; ++i);
-
-  if(i != length)
-    {
-      for(i = length; i >= 0 && keyvalue[i] == ' '; --i) keyvalue[i] = '\0';
-    }
-}
-
-/*---------------------------------------------------------------------------
-        Host dependent directory path to/from URL functions
-  --------------------------------------------------------------------------*/
-int fits_path2url(char *inpath,  /* input file path string                  */
-		  char *outpath, /* output file path string                 */
-		  int  *status)
-  /*
-     convert a file path into its Unix-style equivelent for URL 
-     purposes. Note that this process is platform dependent. This
-     function supports Unix, MSDOS/WIN32, VMS and Macintosh platforms. 
-     The plaform dependant code is conditionally compiled depending upon
-     the setting of the appropriate C preprocessor macros.
-   */
-{
-  char buff[FLEN_FILENAME];
-
-#if defined(WINNT) || defined(__WINNT__)
-
-  /*
-    Microsoft Windows NT case. We assume input file paths of the form:
-
-    //disk/path/filename
-
-     All path segments may be null, so that a single file name is the
-     simplist case.
-
-     The leading "//" becomes a single "/" if present. If no "//" is present,
-     then make sure the resulting URL path is relative, i.e., does not
-     begin with a "/". In other words, the only way that an absolute URL
-     file path may be generated is if the drive specification is given.
-  */
-
-  if(*status > 0) return(*status);
-
-  if(inpath[0] == '/')
-    {
-      strcpy(buff,inpath+1);
-    }
-  else
-    {
-      strcpy(buff,inpath);
-    }
-
-#elif defined(MSDOS) || defined(__WIN32__) || defined(WIN32)
-
-  /*
-     MSDOS or Microsoft windows/NT case. The assumed form of the
-     input path is:
-
-     disk:\path\filename
-
-     All path segments may be null, so that a single file name is the
-     simplist case.
-
-     All back-slashes '\' become slashes '/'; if the path starts with a
-     string of the form "X:" then it is replaced with "/X/"
-  */
-
-  int i,j,k;
-  int size;
-  if(*status > 0) return(*status);
-
-  for(i = 0, j = 0, size = strlen(inpath), buff[0] = 0; 
-                                           i < size; j = strlen(buff))
-    {
-      switch(inpath[i])
-	{
-
-	case ':':
-
-	  /*
-	     must be a disk desiginator; add a slash '/' at the start of
-	     outpath to designate that the path is absolute, then change
-	     the colon ':' to a slash '/'
-	   */
-
-	  for(k = j; k >= 0; --k) buff[k+1] = buff[k];
-	  buff[0] = '/';
-	  strcat(buff,"/");
-	  ++i;
-	  
-	  break;
-
-	case '\\':
-
-	  /* just replace the '\' with a '/' IF its not the first character */
-
-	  if(i != 0 && buff[(j == 0 ? 0 : j-1)] != '/')
-	    {
-	      buff[j] = '/';
-	      buff[j+1] = 0;
-	    }
-
-	  ++i;
-
-	  break;
-
-	default:
-
-	  /* copy the character from inpath to buff as is */
-
-	  buff[j]   = inpath[i];
-	  buff[j+1] = 0;
-	  ++i;
-
-	  break;
-	}
-    }
-
-#elif defined(VMS) || defined(vms) || defined(__vms)
-
-  /*
-     VMS case. Assumed format of the input path is:
-
-     node::disk:[path]filename.ext;version
-
-     Any part of the file path may be missing, so that in the simplist
-     case a single file name/extension is given.
-
-     all brackets "[", "]" and dots "." become "/"; dashes "-" become "..", 
-     all single colons ":" become ":/", all double colons "::" become
-     "FILE://"
-   */
-
-  int i,j,k;
-  int done;
-  int size;
-
-  if(*status > 0) return(*status);
-     
-  /* see if inpath contains a directory specification */
-
-  if(strchr(inpath,']') == NULL) 
-    done = 1;
-  else
-    done = 0;
-
-  for(i = 0, j = 0, size = strlen(inpath), buff[0] = 0; 
-                           i < size && j < FLEN_FILENAME - 8; j = strlen(buff))
-    {
-      switch(inpath[i])
-	{
-
-	case ':':
-
-	  /*
-	     must be a logical/symbol separator or (in the case of a double
-	     colon "::") machine node separator
-	   */
-
-	  if(inpath[i+1] == ':')
-	    {
-	      /* insert a "FILE://" at the start of buff ==> machine given */
-
-	      for(k = j; k >= 0; --k) buff[k+7] = buff[k];
-	      strncpy(buff,"FILE://",7);
-	      i += 2;
-	    }
-	  else if(strstr(buff,"FILE://") == NULL)
-	    {
-	      /* insert a "/" at the start of buff ==> absolute path */
-
-	      for(k = j; k >= 0; --k) buff[k+1] = buff[k];
-	      buff[0] = '/';
-	      ++i;
-	    }
-	  else
-	    ++i;
-
-	  /* a colon always ==> path separator */
-
-	  strcat(buff,"/");
-
-	  break;
-  
-	case ']':
-
-	  /* end of directory spec, file name spec begins after this */
-
-	  done = 1;
-
-	  buff[j]   = '/';
-	  buff[j+1] = 0;
-	  ++i;
-
-	  break;
-
-	case '[':
-
-	  /* 
-	     begin directory specification; add a '/' only if the last char 
-	     is not '/' 
-	  */
-
-	  if(i != 0 && buff[(j == 0 ? 0 : j-1)] != '/')
-	    {
-	      buff[j]   = '/';
-	      buff[j+1] = 0;
-	    }
-
-	  ++i;
-
-	  break;
-
-	case '.':
-
-	  /* 
-	     directory segment separator or file name/extension separator;
-	     we decide which by looking at the value of done
-	  */
-
-	  if(!done)
-	    {
-	    /* must be a directory segment separator */
-	      if(inpath[i-1] == '[')
-		{
-		  strcat(buff,"./");
-		  ++j;
-		}
-	      else
-		buff[j] = '/';
-	    }
-	  else
-	    /* must be a filename/extension separator */
-	    buff[j] = '.';
-
-	  buff[j+1] = 0;
-
-	  ++i;
-
-	  break;
-
-	case '-':
-
-	  /* 
-	     a dash is the same as ".." in Unix speak, but lets make sure
-	     that its not part of the file name first!
-	   */
-
-	  if(!done)
-	    /* must be part of the directory path specification */
-	    strcat(buff,"..");
-	  else
-	    {
-	      /* the dash is part of the filename, so just copy it as is */
-	      buff[j] = '-';
-	      buff[j+1] = 0;
-	    }
-
-	  ++i;
-
-	  break;
-
-	default:
-
-	  /* nothing special, just copy the character as is */
-
-	  buff[j]   = inpath[i];
-	  buff[j+1] = 0;
-
-	  ++i;
-
-	  break;
-
-	}
-    }
-
-  if(j > FLEN_FILENAME - 8)
-    {
-      *status = URL_PARSE_ERROR;
-      ffpmsg("resulting path to URL conversion too big (fits_path2url)");
-    }
-
-#elif defined(macintosh)
-
-  /*
-     MacOS case. The assumed form of the input path is:
-
-     disk:path:filename
-
-     It is assumed that all paths are absolute with disk and path specified,
-     unless no colons ":" are supplied with the string ==> a single file name
-     only. All colons ":" become slashes "/", and if one or more colon is 
-     encountered then the path is specified as absolute.
-  */
-
-  int i,j,k;
-  int firstColon;
-  int size;
-
-  if(*status > 0) return(*status);
-
-  for(i = 0, j = 0, firstColon = 1, size = strlen(inpath), buff[0] = 0; 
-                                                   i < size; j = strlen(buff))
-    {
-      switch(inpath[i])
-	{
-
-	case ':':
-
-	  /*
-	     colons imply path separators. If its the first colon encountered
-	     then assume that its the disk designator and add a slash to the
-	     beginning of the buff string
-	   */
-	  
-	  if(firstColon)
-	    {
-	      firstColon = 0;
-
-	      for(k = j; k >= 0; --k) buff[k+1] = buff[k];
-	      buff[0] = '/';
-	    }
-
-	  /* all colons become slashes */
-
-	  strcat(buff,"/");
-
-	  ++i;
-	  
-	  break;
-
-	default:
-
-	  /* copy the character from inpath to buff as is */
-
-	  buff[j]   = inpath[i];
-	  buff[j+1] = 0;
-
-	  ++i;
-
-	  break;
-	}
-    }
-
-#else 
-
-  /*
-     Default Unix case.
-
-     Nothing special to do here except to remove the double or more // and 
-     replace them with single /
-   */
-
-  int ii = 0;
-  int jj = 0;
-
-  if(*status > 0) return(*status);
-
-  while (inpath[ii]) {
-      if (inpath[ii] == '/' && inpath[ii+1] == '/') {
-	  /* do nothing */
-      } else {
-	  buff[jj] = inpath[ii];
-	  jj++;
-      }
-      ii++;
-  }
-  buff[jj] = '\0';
-  /* printf("buff is %s\ninpath is %s\n",buff,inpath); */
-  /* strcpy(buff,inpath); */
-
-#endif
-
-  /*
-    encode all "unsafe" and "reserved" URL characters
-  */
-
-  *status = fits_encode_url(buff,outpath,status);
-
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int fits_url2path(char *inpath,  /* input file path string  */
-		  char *outpath, /* output file path string */
-		  int  *status)
-  /*
-     convert a Unix-style URL into a platform dependent directory path. 
-     Note that this process is platform dependent. This
-     function supports Unix, MSDOS/WIN32, VMS and Macintosh platforms. Each
-     platform dependent code segment is conditionally compiled depending 
-     upon the setting of the appropriate C preprocesser macros.
-   */
-{
-  char buff[FLEN_FILENAME];
-  int absolute;
-
-#if defined(MSDOS) || defined(__WIN32__) || defined(WIN32)
-  char *tmpStr, *saveptr;
-#elif defined(VMS) || defined(vms) || defined(__vms)
-  int i;
-  char *tmpStr, *saveptr;
-#elif defined(macintosh)
-  char *tmpStr, *saveptr;
-#endif
-
-  if(*status != 0) return(*status);
-
-  /*
-    make a copy of the inpath so that we can manipulate it
-  */
-
-  strcpy(buff,inpath);
-
-  /*
-    convert any encoded characters to their unencoded values
-  */
-
-  *status = fits_unencode_url(inpath,buff,status);
-
-  /*
-    see if the URL is given as absolute w.r.t. the "local" file system
-  */
-
-  if(buff[0] == '/') 
-    absolute = 1;
-  else
-    absolute = 0;
-
-#if defined(WINNT) || defined(__WINNT__)
-
-  /*
-    Microsoft Windows NT case. We create output paths of the form
-
-    //disk/path/filename
-
-     All path segments but the last may be null, so that a single file name 
-     is the simplist case.     
-  */
-
-  if(absolute)
-    {
-      strcpy(outpath,"/");
-      strcat(outpath,buff);
-    }
-  else
-    {
-      strcpy(outpath,buff);
-    }
-
-#elif defined(MSDOS) || defined(__WIN32__) || defined(WIN32)
-
-  /*
-     MSDOS or Microsoft windows/NT case. The output path will be of the
-     form
-
-     disk:\path\filename
-
-     All path segments but the last may be null, so that a single file name 
-     is the simplist case.
-  */
-
-  /*
-    separate the URL into tokens at each slash '/' and process until
-    all tokens have been examined
-  */
-
-  for(tmpStr = ffstrtok(buff,"/",&saveptr), outpath[0] = 0;
-                                 tmpStr != NULL; tmpStr = ffstrtok(NULL,"/",&saveptr))
-    {
-      strcat(outpath,tmpStr);
-
-      /* 
-	 if the absolute flag is set then process the token as a disk 
-	 specification; else just process it as a directory path or filename
-      */
-
-      if(absolute)
-	{
-	  strcat(outpath,":\\");
-	  absolute = 0;
-	}
-      else
-	strcat(outpath,"\\");
-    }
-
-  /* remove the last "\" from the outpath, it does not belong there */
-
-  outpath[strlen(outpath)-1] = 0;
-
-#elif defined(VMS) || defined(vms) || defined(__vms)
-
-  /*
-     VMS case. The output path will be of the form:
-
-     node::disk:[path]filename.ext;version
-
-     Any part of the file path may be missing execpt filename.ext, so that in 
-     the simplist case a single file name/extension is given.
-
-     if the path is specified as relative starting with "./" then the first
-     part of the VMS path is "[.". If the path is relative and does not start
-     with "./" (e.g., "a/b/c") then the VMS path is constructed as
-     "[a.b.c]"
-   */
-     
-  /*
-    separate the URL into tokens at each slash '/' and process until
-    all tokens have been examined
-  */
-
-  for(tmpStr = ffstrtok(buff,"/",&saveptr), outpath[0] = 0; 
-                                 tmpStr != NULL; tmpStr = ffstrtok(NULL,"/",&saveptr))
-    {
-
-      if(fits_strcasecmp(tmpStr,"FILE:") == 0)
-	{
-	  /* the next token should contain the DECnet machine name */
-
-	  tmpStr = ffstrtok(NULL,"/",&saveptr);
-	  if(tmpStr == NULL) continue;
-
-	  strcat(outpath,tmpStr);
-	  strcat(outpath,"::");
-
-	  /* set the absolute flag to true for the next token */
-	  absolute = 1;
-	}
-
-      else if(strcmp(tmpStr,"..") == 0)
-	{
-	  /* replace all Unix-like ".." with VMS "-" */
-
-	  if(strlen(outpath) == 0) strcat(outpath,"[");
-	  strcat(outpath,"-.");
-	}
-
-      else if(strcmp(tmpStr,".") == 0 && strlen(outpath) == 0)
-	{
-	  /*
-	    must indicate a relative path specifier
-	  */
-
-	  strcat(outpath,"[.");
-	}
-  
-      else if(strchr(tmpStr,'.') != NULL)
-	{
-	  /* 
-	     must be up to the file name; turn the last "." path separator
-	     into a "]" and then add the file name to the outpath
-	  */
-	  
-	  i = strlen(outpath);
-	  if(i > 0 && outpath[i-1] == '.') outpath[i-1] = ']';
-
-	  strcat(outpath,tmpStr);
-	}
-
-      else
-	{
-	  /*
-	    process the token as a a directory path segement
-	  */
-
-	  if(absolute)
-	    {
-	      /* treat the token as a disk specifier */
-	      absolute = 0;
-	      strcat(outpath,tmpStr);
-	      strcat(outpath,":[");
-	    }
-	  else if(strlen(outpath) == 0)
-	    {
-	      /* treat the token as the first directory path specifier */
-	      strcat(outpath,"[");
-	      strcat(outpath,tmpStr);
-	      strcat(outpath,".");
-	    }
-	  else
-	    {
-	      /* treat the token as an imtermediate path specifier */
-	      strcat(outpath,tmpStr);
-	      strcat(outpath,".");
-	    }
-	}
-    }
-
-#elif defined(macintosh)
-
-  /*
-     MacOS case. The output path will be of the form
-
-     disk:path:filename
-
-     All path segments but the last may be null, so that a single file name 
-     is the simplist case.
-  */
-
-  /*
-    separate the URL into tokens at each slash '/' and process until
-    all tokens have been examined
-  */
-
-  for(tmpStr = ffstrtok(buff,"/",&saveptr), outpath[0] = 0;
-                                 tmpStr != NULL; tmpStr = ffstrtok(NULL,"/",&saveptr))
-    {
-      strcat(outpath,tmpStr);
-      strcat(outpath,":");
-    }
-
-  /* remove the last ":" from the outpath, it does not belong there */
-
-  outpath[strlen(outpath)-1] = 0;
-
-#else
-
-  /*
-     Default Unix case.
-
-     Nothing special to do here
-   */
-
-  strcpy(outpath,buff);
-
-#endif
-
-  return(*status);
-}
-
-/****************************************************************************/
-int fits_get_cwd(char *cwd,  /* IO current working directory string */
-		 int  *status)
-  /*
-     retrieve the string containing the current working directory absolute
-     path in Unix-like URL standard notation. It is assumed that the CWD
-     string has a size of at least FLEN_FILENAME.
-
-     Note that this process is platform dependent. This
-     function supports Unix, MSDOS/WIN32, VMS and Macintosh platforms. Each
-     platform dependent code segment is conditionally compiled depending 
-     upon the setting of the appropriate C preprocesser macros.
-   */
-{
-
-  char buff[FLEN_FILENAME];
-
-
-  if(*status != 0) return(*status);
-
-#if defined(macintosh)
-
-  /*
-     MacOS case. Currently unknown !!!!
-  */
-
-  *buff = 0;
-
-#else
-  /*
-    Good old getcwd() seems to work with all other platforms
-  */
-
-  getcwd(buff,FLEN_FILENAME);
-
-#endif
-
-  /*
-    convert the cwd string to a URL standard path string
-  */
-
-  fits_path2url(buff,cwd,status);
-
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int  fits_get_url(fitsfile *fptr,       /* I ptr to FITS file to evaluate    */
-		  char     *realURL,    /* O URL of real FITS file           */
-		  char     *startURL,   /* O URL of starting FITS file       */
-		  char     *realAccess, /* O true access method of FITS file */
-		  char     *startAccess,/* O "official" access of FITS file  */
-		  int      *iostate,    /* O can this file be modified?      */
-		  int      *status)
-/*
-  For grouping convention purposes, determine the URL of the FITS file
-  associated with the fitsfile pointer fptr. The true access type (file://,
-  mem://, shmem://, root://), starting "official" access type, and iostate 
-  (0 ==> readonly, 1 ==> readwrite) are also returned.
-
-  It is assumed that the url string has enough room to hold the resulting
-  URL, and the the accessType string has enough room to hold the access type.
-*/
-{
-  int i;
-  int tmpIOstate = 0;
-
-  char infile[FLEN_FILENAME];
-  char outfile[FLEN_FILENAME];
-  char tmpStr1[FLEN_FILENAME];
-  char tmpStr2[FLEN_FILENAME];
-  char tmpStr3[FLEN_FILENAME];
-  char tmpStr4[FLEN_FILENAME];
-  char *tmpPtr;
-
-
-  if(*status != 0) return(*status);
-
-  do
-    {
-      /* 
-	 retrieve the member HDU's file name as opened by ffopen() 
-	 and parse it into its constitutent pieces; get the currently
-	 active driver token too
-       */
-	  
-      *tmpStr1 = *tmpStr2 = *tmpStr3 = *tmpStr4 = 0;
-
-      *status = fits_file_name(fptr,tmpStr1,status);
-
-      *status = ffiurl(tmpStr1,NULL,infile,outfile,NULL,tmpStr2,tmpStr3,
-		       tmpStr4,status);
-
-      if((*tmpStr2) || (*tmpStr3) || (*tmpStr4)) tmpIOstate = -1;
- 
-      *status = ffurlt(fptr,tmpStr3,status);
-
-      strcpy(tmpStr4,tmpStr3);
-
-      *status = ffrtnm(tmpStr1,tmpStr2,status);
-      strcpy(tmpStr1,tmpStr2);
-
-      /*
-	for grouping convention purposes (only) determine the URL of the
-	actual FITS file being used for the given fptr, its true access 
-	type (file://, mem://, shmem://, root://) and its iostate (0 ==>
-	read only, 1 ==> readwrite)
-      */
-
-      /*
-	The first set of access types are "simple" in that they do not
-	use any redirection to temporary memory or outfiles
-       */
-
-      /* standard disk file driver is in use */
-      
-      if(fits_strcasecmp(tmpStr3,"file://")              == 0)         
-	{
-	  tmpIOstate = 1;
-	  
-	  if(strlen(outfile)) strcpy(tmpStr1,outfile);
-	  else *tmpStr2 = 0;
-
-	  /*
-	    make sure no FILE:// specifier is given in the tmpStr1
-	    or tmpStr2 strings; the convention calls for local files
-	    to have no access specification
-	  */
-
-	  if((tmpPtr = strstr(tmpStr1,"://")) != NULL)
-	    {
-	      strcpy(infile,tmpPtr+3);
-	      strcpy(tmpStr1,infile);
-	    }
-
-	  if((tmpPtr = strstr(tmpStr2,"://")) != NULL)
-	    {
-	      strcpy(infile,tmpPtr+3);
-	      strcpy(tmpStr2,infile);
-	    }
-	}
-
-      /* file stored in conventional memory */
-	  
-      else if(fits_strcasecmp(tmpStr3,"mem://")          == 0)          
-	{
-	  if(tmpIOstate < 0)
-	    {
-	      /* file is a temp mem file only */
-	      ffpmsg("cannot make URL from temp MEM:// file (fits_get_url)");
-	      *status = URL_PARSE_ERROR;
-	    }
-	  else
-	    {
-	      /* file is a "perminate" mem file for this process */
-	      tmpIOstate = 1;
-	      *tmpStr2 = 0;
-	    }
-	}
-
-      /* file stored in conventional memory */
- 
-     else if(fits_strcasecmp(tmpStr3,"memkeep://")      == 0)      
-	{
-	  strcpy(tmpStr3,"mem://");
-	  *tmpStr4 = 0;
-	  *tmpStr2 = 0;
-	  tmpIOstate = 1;
-	}
-
-      /* file residing in shared memory */
-
-      else if(fits_strcasecmp(tmpStr3,"shmem://")        == 0)        
-	{
-	  *tmpStr4   = 0;
-	  *tmpStr2   = 0;
-	  tmpIOstate = 1;
-	}
-      
-      /* file accessed via the ROOT network protocol */
-
-      else if(fits_strcasecmp(tmpStr3,"root://")         == 0)         
-	{
-	  *tmpStr4   = 0;
-	  *tmpStr2   = 0;
-	  tmpIOstate = 1;
-	}
-  
-      /*
-	the next set of access types redirect the contents of the original
-	file to an special outfile because the original could not be
-	directly modified (i.e., resides on the network, was compressed).
-	In these cases the URL string takes on the value of the OUTFILE,
-	the access type becomes file://, and the iostate is set to 1 (can
-	read/write to the file).
-      */
-
-      /* compressed file uncompressed and written to disk */
-
-      else if(fits_strcasecmp(tmpStr3,"compressfile://") == 0) 
-	{
-	  strcpy(tmpStr1,outfile);
-	  strcpy(tmpStr2,infile);
-	  strcpy(tmpStr3,"file://");
-	  strcpy(tmpStr4,"file://");
-	  tmpIOstate = 1;
-	}
-
-      /* HTTP accessed file written locally to disk */
-
-      else if(fits_strcasecmp(tmpStr3,"httpfile://")     == 0)     
-	{
-	  strcpy(tmpStr1,outfile);
-	  strcpy(tmpStr3,"file://");
-	  strcpy(tmpStr4,"http://");
-	  tmpIOstate = 1;
-	}
-      
-      /* FTP accessd file written locally to disk */
-
-      else if(fits_strcasecmp(tmpStr3,"ftpfile://")      == 0)      
-	{
-	  strcpy(tmpStr1,outfile);
-	  strcpy(tmpStr3,"file://");
-	  strcpy(tmpStr4,"ftp://");
-	  tmpIOstate = 1;
-	}
-      
-      /* file from STDIN written to disk */
-
-      else if(fits_strcasecmp(tmpStr3,"stdinfile://")    == 0)    
-	{
-	  strcpy(tmpStr1,outfile);
-	  strcpy(tmpStr3,"file://");
-	  strcpy(tmpStr4,"stdin://");
-	  tmpIOstate = 1;
-	}
-
-      /* 
-	 the following access types use memory resident files as temporary
-	 storage; they cannot be modified or be made group members for 
-	 grouping conventions purposes, but their original files can be.
-	 Thus, their tmpStr3s are reset to mem://, their iostate
-	 values are set to 0 (for no-modification), and their URL string
-	 values remain set to their original values
-       */
-
-      /* compressed disk file uncompressed into memory */
-
-      else if(fits_strcasecmp(tmpStr3,"compress://")     == 0)     
-	{
-	  *tmpStr1 = 0;
-	  strcpy(tmpStr2,infile);
-	  strcpy(tmpStr3,"mem://");
-	  strcpy(tmpStr4,"file://");
-	  tmpIOstate = 0;
-	}
-      
-      /* HTTP accessed file transferred into memory */
-
-      else if(fits_strcasecmp(tmpStr3,"http://")         == 0)         
-	{
-	  *tmpStr1 = 0;
-	  strcpy(tmpStr3,"mem://");
-	  strcpy(tmpStr4,"http://");
-	  tmpIOstate = 0;
-	}
-      
-      /* HTTP accessed compressed file transferred into memory */
-
-      else if(fits_strcasecmp(tmpStr3,"httpcompress://") == 0) 
-	{
-	  *tmpStr1 = 0;
-	  strcpy(tmpStr3,"mem://");
-	  strcpy(tmpStr4,"http://");
-	  tmpIOstate = 0;
-	}
-      
-      /* FTP accessed file transferred into memory */
-      
-      else if(fits_strcasecmp(tmpStr3,"ftp://")          == 0)          
-	{
-	  *tmpStr1 = 0;
-	  strcpy(tmpStr3,"mem://");
-	  strcpy(tmpStr4,"ftp://");
-	  tmpIOstate = 0;
-	}
-      
-      /* FTP accessed compressed file transferred into memory */
-
-      else if(fits_strcasecmp(tmpStr3,"ftpcompress://")  == 0)  
-	{
-	  *tmpStr1 = 0;
-	  strcpy(tmpStr3,"mem://");
-	  strcpy(tmpStr4,"ftp://");
-	  tmpIOstate = 0;
-	}	
-      
-      /*
-	The last set of access types cannot be used to make a meaningful URL 
-	strings from; thus an error is generated
-       */
-
-      else if(fits_strcasecmp(tmpStr3,"stdin://")        == 0)        
-	{
-	  *status = URL_PARSE_ERROR;
-	  ffpmsg("cannot make vaild URL from stdin:// (fits_get_url)");
-	  *tmpStr1 = *tmpStr2 = 0;
-	}
-
-      else if(fits_strcasecmp(tmpStr3,"stdout://")       == 0)       
-	{
-	  *status = URL_PARSE_ERROR;
-	  ffpmsg("cannot make vaild URL from stdout:// (fits_get_url)");
-	  *tmpStr1 = *tmpStr2 = 0;
-	}
-
-      else if(fits_strcasecmp(tmpStr3,"irafmem://")      == 0)      
-	{
-	  *status = URL_PARSE_ERROR;
-	  ffpmsg("cannot make vaild URL from irafmem:// (fits_get_url)");
-	  *tmpStr1 = *tmpStr2 = 0;
-	}
-
-      if(*status != 0) continue;
-
-      /*
-	 assign values to the calling parameters if they are non-NULL
-      */
-
-      if(realURL != NULL)
-	{
-	  if(strlen(tmpStr1) == 0)
-	    *realURL = 0;
-	  else
-	    {
-	      if((tmpPtr = strstr(tmpStr1,"://")) != NULL)
-		{
-		  tmpPtr += 3;
-		  i = (long)tmpPtr - (long)tmpStr1;
-		  strncpy(realURL,tmpStr1,i);
-		}
-	      else
-		{
-		  tmpPtr = tmpStr1;
-		  i = 0;
-		}
-
-	      *status = fits_path2url(tmpPtr,realURL+i,status);
-	    }
-	}
-
-      if(startURL != NULL)
-	{
-	  if(strlen(tmpStr2) == 0)
-	    *startURL = 0;
-	  else
-	    {
-	      if((tmpPtr = strstr(tmpStr2,"://")) != NULL)
-		{
-		  tmpPtr += 3;
-		  i = (long)tmpPtr - (long)tmpStr2;
-		  strncpy(startURL,tmpStr2,i);
-		}
-	      else
-		{
-		  tmpPtr = tmpStr2;
-		  i = 0;
-		}
-
-	      *status = fits_path2url(tmpPtr,startURL+i,status);
-	    }
-	}
-
-      if(realAccess  != NULL)  strcpy(realAccess,tmpStr3);
-      if(startAccess != NULL)  strcpy(startAccess,tmpStr4);
-      if(iostate     != NULL) *iostate = tmpIOstate;
-
-    }while(0);
-
-  return(*status);
-}
-
-/*--------------------------------------------------------------------------
-                           URL parse support functions
-  --------------------------------------------------------------------------*/
-
-/* simple push/pop/shift/unshift string stack for use by fits_clean_url */
-typedef char* grp_stack_data; /* type of data held by grp_stack */
-
-typedef struct grp_stack_item_struct {
-  grp_stack_data data; /* value of this stack item */
-  struct grp_stack_item_struct* next; /* next stack item */
-  struct grp_stack_item_struct* prev; /* previous stack item */
-} grp_stack_item;
-
-typedef struct grp_stack_struct {
-  size_t stack_size; /* number of items on stack */
-  grp_stack_item* top; /* top item */
-} grp_stack;
-
-static char* grp_stack_default = NULL; /* initial value for new instances
-                                          of grp_stack_data */
-
-/* the following functions implement the group string stack grp_stack */
-static void delete_grp_stack(grp_stack** mystack);
-static grp_stack_item* grp_stack_append(
-  grp_stack_item* last, grp_stack_data data
-);
-static grp_stack_data grp_stack_remove(grp_stack_item* last);
-static grp_stack* new_grp_stack(void);
-static grp_stack_data pop_grp_stack(grp_stack* mystack);
-static void push_grp_stack(grp_stack* mystack, grp_stack_data data);
-static grp_stack_data shift_grp_stack(grp_stack* mystack);
-/* static void unshift_grp_stack(grp_stack* mystack, grp_stack_data data); */
-
-int fits_clean_url(char *inURL,  /* I input URL string                      */
-		   char *outURL, /* O output URL string                     */
-		   int  *status)
-/*
-  clean the URL by eliminating any ".." or "." specifiers in the inURL
-  string, and write the output to the outURL string.
-
-  Note that this function must have a valid Unix-style URL as input; platform
-  dependent path strings are not allowed.
- */
-{
-  grp_stack* mystack; /* stack to hold pieces of URL */
-  char* tmp;
-  char *saveptr;
-
-  if(*status) return *status;
-
-  mystack = new_grp_stack();
-  *outURL = 0;
-
-  do {
-    /* handle URL scheme and domain if they exist */
-    tmp = strstr(inURL, "://");
-    if(tmp) {
-      /* there is a URL scheme, so look for the end of the domain too */
-      tmp = strchr(tmp + 3, '/');
-      if(tmp) {
-        /* tmp is now the end of the domain, so
-         * copy URL scheme and domain as is, and terminate by hand */
-        size_t string_size = (size_t) (tmp - inURL);
-        strncpy(outURL, inURL, string_size);
-        outURL[string_size] = 0;
-
-        /* now advance the input pointer to just after the domain and go on */
-        inURL = tmp;
-      } else {
-        /* '/' was not found, which means there are no path-like
-         * portions, so copy whole inURL to outURL and we're done */
-        strcpy(outURL, inURL);
-        continue; /* while(0) */
-      }
-    }
-
-    /* explicitly copy a leading / (absolute path) */
-    if('/' == *inURL) strcat(outURL, "/");
-
-    /* now clean the remainder of the inURL. push URL segments onto
-     * stack, dealing with .. and . as we go */
-    tmp = ffstrtok(inURL, "/",&saveptr); /* finds first / */
-    while(tmp) {
-      if(!strcmp(tmp, "..")) {
-        /* discard previous URL segment, if there was one. if not,
-         * add the .. to the stack if this is *not* an absolute path
-         * (for absolute paths, leading .. has no effect, so skip it) */
-        if(0 < mystack->stack_size) pop_grp_stack(mystack);
-        else if('/' != *inURL) push_grp_stack(mystack, tmp);
-      } else {
-        /* always just skip ., but otherwise add segment to stack */
-        if(strcmp(tmp, ".")) push_grp_stack(mystack, tmp);
-      }
-      tmp = ffstrtok(NULL, "/",&saveptr); /* get the next segment */
-    }
-
-    /* stack now has pieces of cleaned URL, so just catenate them
-     * onto output string until stack is empty */
-    while(0 < mystack->stack_size) {
-      tmp = shift_grp_stack(mystack);
-      strcat(outURL, tmp);
-      strcat(outURL, "/");
-    }
-    outURL[strlen(outURL) - 1] = 0; /* blank out trailing / */
-  } while(0);
-  delete_grp_stack(&mystack);
-  return *status;
-}
-
-/* free all stack contents using pop_grp_stack before freeing the
- * grp_stack itself */
-static void delete_grp_stack(grp_stack** mystack) {
-  if(!mystack || !*mystack) return;
-  while((*mystack)->stack_size) pop_grp_stack(*mystack);
-  free(*mystack);
-  *mystack = NULL;
-}
-
-/* append an item to the stack, handling the special case of the first
- * item appended */
-static grp_stack_item* grp_stack_append(
-  grp_stack_item* last, grp_stack_data data
-) {
-  /* first create a new stack item, and copy data to it */
-  grp_stack_item* new_item = (grp_stack_item*) malloc(sizeof(grp_stack_item));
-  new_item->data = data;
-  if(last) {
-    /* attach this item between the "last" item and its "next" item */
-    new_item->next = last->next;
-    new_item->prev = last;
-    last->next->prev = new_item;
-    last->next = new_item;
-  } else {
-    /* stack is empty, so "next" and "previous" both point back to it */
-    new_item->next = new_item;
-    new_item->prev = new_item;
-  }
-  return new_item;
-}
-
-/* remove an item from the stack, handling the special case of the last
- * item removed */
-static grp_stack_data grp_stack_remove(grp_stack_item* last) {
-  grp_stack_data retval = last->data;
-  last->prev->next = last->next;
-  last->next->prev = last->prev;
-  free(last);
-  return retval;
-}
-
-/* create new stack dynamically, and give it valid initial values */
-static grp_stack* new_grp_stack(void) {
-  grp_stack* retval = (grp_stack*) malloc(sizeof(grp_stack));
-  if(retval) {
-    retval->stack_size = 0;
-    retval->top = NULL;
-  }
-  return retval;
-}
-
-/* return the value at the top of the stack and remove it, updating
- * stack_size. top->prev becomes the new "top" */
-static grp_stack_data pop_grp_stack(grp_stack* mystack) {
-  grp_stack_data retval = grp_stack_default;
-  if(mystack && mystack->top) {
-    grp_stack_item* newtop = mystack->top->prev;
-    retval = grp_stack_remove(mystack->top);
-    mystack->top = newtop;
-    if(0 == --mystack->stack_size) mystack->top = NULL;
-  }
-  return retval;
-}
-
-/* add to the stack after the top element. the added element becomes
- * the new "top" */
-static void push_grp_stack(grp_stack* mystack, grp_stack_data data) {
-  if(!mystack) return;
-  mystack->top = grp_stack_append(mystack->top, data);
-  ++mystack->stack_size;
-  return;
-}
-
-/* return the value at the bottom of the stack and remove it, updating
- * stack_size. "top" pointer is unaffected */
-static grp_stack_data shift_grp_stack(grp_stack* mystack) {
-  grp_stack_data retval = grp_stack_default;
-  if(mystack && mystack->top) {
-    retval = grp_stack_remove(mystack->top->next); /* top->next == bottom */
-    if(0 == --mystack->stack_size) mystack->top = NULL;
-  }
-  return retval;
-}
-
-/* add to the stack after the top element. "top" is unaffected, except
- * in the special case of an initially empty stack */
-/* static void unshift_grp_stack(grp_stack* mystack, grp_stack_data data) {
-   if(!mystack) return;
-   if(mystack->top) grp_stack_append(mystack->top, data);
-   else mystack->top = grp_stack_append(NULL, data);
-   ++mystack->stack_size;
-   return;
-   } */
-
-/*--------------------------------------------------------------------------*/
-int fits_url2relurl(char     *refURL, /* I reference URL string             */
-		    char     *absURL, /* I absoulute URL string to process  */
-		    char     *relURL, /* O resulting relative URL string    */
-		    int      *status)
-/*
-  create a relative URL to the file referenced by absURL with respect to the
-  reference URL refURL. The relative URL is returned in relURL.
-
-  Both refURL and absURL must be absolute URL strings; i.e. either begin
-  with an access method specification "XXX://" or with a '/' character
-  signifiying that they are absolute file paths.
-
-  Note that it is possible to make a relative URL from two input URLs
-  (absURL and refURL) that are not compatable. This function does not
-  check to see if the resulting relative URL makes any sence. For instance,
-  it is impossible to make a relative URL from the following two inputs:
-
-  absURL = ftp://a.b.c.com/x/y/z/foo.fits
-  refURL = /a/b/c/ttt.fits
-
-  The resulting relURL will be:
-
-  ../../../ftp://a.b.c.com/x/y/z/foo.fits 
-
-  Which is syntically correct but meaningless. The problem is that a file
-  with an access method of ftp:// cannot be expressed a a relative URL to
-  a local disk file.
-*/
-
-{
-  int i,j;
-  int refcount,abscount;
-  int refsize,abssize;
-  int done;
-
-
-  if(*status != 0) return(*status);
-
-  /* initialize the relative URL string */
-  relURL[0] = 0;
-
-  do
-    {
-      /*
-	refURL and absURL must be absolute to process
-      */
-
-      if(!(fits_is_url_absolute(refURL) || *refURL == '/') ||
-	 !(fits_is_url_absolute(absURL) || *absURL == '/'))
-	{
-	  *status = URL_PARSE_ERROR;
-	  ffpmsg("Cannot make rel. URL from non abs. URLs (fits_url2relurl)");
-	  continue;
-	}
-
-      /* determine the size of the refURL and absURL strings */
-
-      refsize = strlen(refURL);
-      abssize = strlen(absURL);
-
-      /* process the two URL strings and build the relative URL between them */
-		
-
-      for(done = 0, refcount = 0, abscount = 0; 
-	  !done && refcount < refsize && abscount < abssize; 
-	  ++refcount, ++abscount)
-	{
-	  for(; abscount < abssize && absURL[abscount] == '/'; ++abscount);
-	  for(; refcount < refsize && refURL[refcount] == '/'; ++refcount);
-
-	  /* find the next path segment in absURL */ 
-	  for(i = abscount; absURL[i] != '/' && i < abssize; ++i);
-	  
-	  /* find the next path segment in refURL */
-	  for(j = refcount; refURL[j] != '/' && j < refsize; ++j);
-	  
-	  /* do the two path segments match? */
-	  if(i == j && 
-	     strncmp(absURL+abscount, refURL+refcount,i-refcount) == 0)
-	    {
-	      /* they match, so ignore them and continue */
-	      abscount = i; refcount = j;
-	      continue;
-	    }
-	  
-	  /* We found a difference in the paths in refURL and absURL.
-	     For every path segment remaining in the refURL string, append
-	     a "../" path segment to the relataive URL relURL.
-	  */
-
-	  for(j = refcount; j < refsize; ++j)
-	    if(refURL[j] == '/') strcat(relURL,"../");
-	  
-	  /* copy all remaining characters of absURL to the output relURL */
-
-	  strcat(relURL,absURL+abscount);
-	  
-	  /* we are done building the relative URL */
-	  done = 1;
-	}
-
-    }while(0);
-
-  return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_relurl2url(char     *refURL, /* I reference URL string             */
-		    char     *relURL, /* I relative URL string to process   */
-		    char     *absURL, /* O absolute URL string              */
-		    int      *status)
-/*
-  create an absolute URL from a relative url and a reference URL. The 
-  reference URL is given by the FITS file pointed to by fptr.
-
-  The construction of the absolute URL from the partial and reference URl
-  is performed using the rules set forth in:
- 
-  http://www.w3.org/Addressing/URL/URL_TOC.html
-  and
-  http://www.w3.org/Addressing/URL/4_3_Partial.html
-
-  Note that the relative URL string relURL must conform to the Unix-like
-  URL syntax; host dependent partial URL strings are not allowed.
-*/
-{
-  int i;
-
-  char tmpStr[FLEN_FILENAME];
-
-  char *tmpStr1, *tmpStr2;
-
-
-  if(*status != 0) return(*status);
-  
-  do
-    {
-
-      /*
-	make a copy of the reference URL string refURL for parsing purposes
-      */
-
-      strcpy(tmpStr,refURL);
-
-      /*
-	if the reference file has an access method of mem:// or shmem://
-	then we cannot use it as the basis of an absolute URL construction
-	for a partial URL
-      */
-	  
-      if(fits_strncasecmp(tmpStr,"MEM:",4)   == 0 ||
-                	                fits_strncasecmp(tmpStr,"SHMEM:",6) == 0)
-	{
-	  ffpmsg("ref URL has access mem:// or shmem:// (fits_relurl2url)");
-	  ffpmsg("   cannot construct full URL from a partial URL and ");
-	  ffpmsg("   MEM/SHMEM base URL");
-	  *status = URL_PARSE_ERROR;
-	  continue;
-	}
-
-      if(relURL[0] != '/')
-	{
-	  /*
-	    just append the relative URL string to the reference URL
-	    string (minus the reference URL file name) to form the 
-	    absolute URL string
-	  */
-	      
-	  tmpStr1 = strrchr(tmpStr,'/');
-	  
-	  if(tmpStr1 != NULL) tmpStr1[1] = 0;
-	  else                tmpStr[0]  = 0;
-	  
-	  strcat(tmpStr,relURL);
-	}
-      else
-	{
-	  /*
-	    have to parse the refURL string for the first occurnace of the 
-	    same number of '/' characters as contained in the beginning of
-	    location that is not followed by a greater number of consective 
-	    '/' charaters (yes, that is a confusing statement); this is the 
-	    location in the refURL string where the relURL string is to
-	    be appended to form the new absolute URL string
-	   */
-	  
-	  /*
-	    first, build up a slash pattern string that has one more
-	    slash in it than the starting slash pattern of the
-	    relURL string
-	  */
-	  
-	  strcpy(absURL,"/");
-	  
-	  for(i = 0; relURL[i] == '/'; ++i) strcat(absURL,"/");
-	  
-	  /*
-	    loop over the refURL string until the slash pattern stored
-	    in absURL is no longer found
-	  */
-
-	  for(tmpStr1 = tmpStr, i = strlen(absURL); 
-	      (tmpStr2 = strstr(tmpStr1,absURL)) != NULL;
-	      tmpStr1 = tmpStr2 + i);
-	  
-	  /* reduce the slash pattern string by one slash */
-	  
-	  absURL[i-1] = 0;
-	  
-	  /* 
-	     search for the slash pattern in the remaining portion
-	     of the refURL string
-	  */
-
-	  tmpStr2 = strstr(tmpStr1,absURL);
-	  
-	  /* if no slash pattern match was found */
-	  
-	  if(tmpStr2 == NULL)
-	    {
-	      /* just strip off the file name from the refURL  */
-	      
-	      tmpStr2 = strrchr(tmpStr1,'/');
-	      
-	      if(tmpStr2 != NULL) tmpStr2[0] = 0;
-	      else                tmpStr[0]  = 0;
-	    }
-	  else
-	    {
-	      /* set a string terminator at the slash pattern match */
-	      
-	      *tmpStr2 = 0;
-	    }
-	  
-	  /* 
-	    conatenate the relURL string to the refURL string to form
-	    the absURL
-	   */
-
-	  strcat(tmpStr,relURL);
-	}
-
-      /*
-	normalize the absURL by removing any ".." or "." specifiers
-	in the string
-      */
-
-      *status = fits_clean_url(tmpStr,absURL,status);
-
-    }while(0);
-
-  return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_encode_url(char *inpath,  /* I URL  to be encoded                  */ 
-		    char *outpath, /* O output encoded URL                  */
-		    int *status)
-     /*
-       encode all URL "unsafe" and "reserved" characters using the "%XX"
-       convention, where XX stand for the two hexidecimal digits of the
-       encode character's ASCII code.
-
-       Note that the output path is at least as large as, if not larger than
-       the input path, so that OUTPATH should be passed to this function
-       with room for growth. If not a runtime error could result. It is
-       assumed that OUTPATH has been allocated with enough room to hold
-       the resulting encoded URL.
-
-       This function was adopted from code in the libwww.a library available
-       via the W3 consortium 
-     */
-{
-  unsigned char a;
-  
-  char *p;
-  char *q;
-  char *hex = "0123456789ABCDEF";
-  
-unsigned const char isAcceptable[96] =
-{/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF */
-  
-    0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xF,0xE,0x0,0xF,0xF,0xC, 
-                                           /* 2x  !"#$%&'()*+,-./   */
-    0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x8,0x0,0x0,0x0,0x0,0x0,
-                                           /* 3x 0123456789:;<=>?   */
-    0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF, 
-                                           /* 4x @ABCDEFGHIJKLMNO   */
-    0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x0,0x0,0x0,0x0,0xF,
-                                           /* 5X PQRSTUVWXYZ[\]^_   */
-    0x0,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,
-                                           /* 6x `abcdefghijklmno   */
-    0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x0,0x0,0x0,0x0,0x0  
-                                           /* 7X pqrstuvwxyz{\}~DEL */
-};
-
-  if(*status != 0) return(*status);
-  
-  /* loop over all characters in inpath until '\0' is encountered */
-
-  for(q = outpath, p = inpath; *p; p++)
-    {
-      a = (unsigned char)*p;
-
-      /* if the charcter requires encoding then process it */
-
-      if(!( a>=32 && a<128 && (isAcceptable[a-32])))
-	{
-	  /* add a '%' character to the outpath */
-	  *q++ = HEX_ESCAPE;
-	  /* add the most significant ASCII code hex value */
-	  *q++ = hex[a >> 4];
-	  /* add the least significant ASCII code hex value */
-	  *q++ = hex[a & 15];
-	}
-      /* else just copy the character as is */
-      else *q++ = *p;
-    }
-
-  /* null terminate the outpath string */
-
-  *q++ = 0; 
-  
-  return(*status);
-}
-
-/*---------------------------------------------------------------------------*/
-int fits_unencode_url(char *inpath,  /* I input URL with encoding            */
-		      char *outpath, /* O unencoded URL                      */
-		      int  *status)
-     /*
-       unencode all URL "unsafe" and "reserved" characters to their actual
-       ASCII representation. All tokens of the form "%XX" where XX is the
-       hexidecimal code for an ASCII character, are searched for and
-       translated into the actuall ASCII character (so three chars become
-       1 char).
-
-       It is assumed that OUTPATH has enough room to hold the unencoded
-       URL.
-
-       This function was adopted from code in the libwww.a library available
-       via the W3 consortium 
-     */
-
-{
-    char *p;
-    char *q;
-    char  c;
-
-    if(*status != 0) return(*status);
-
-    p = inpath;
-    q = outpath;
-
-    /* 
-       loop over all characters in the inpath looking for the '%' escape
-       character; if found the process the escape sequence
-    */
-
-    while(*p != 0) 
-      {
-	/* 
-	   if the character is '%' then unencode the sequence, else
-	   just copy the character from inpath to outpath
-        */
-
-        if (*p == HEX_ESCAPE)
-	  {
-            if((c = *(++p)) != 0)
-	      { 
-		*q = (
-		      (c >= '0' && c <= '9') ?
-		      (c - '0') : ((c >= 'A' && c <= 'F') ?
-				   (c - 'A' + 10) : (c - 'a' + 10))
-		      )*16;
-
-		if((c = *(++p)) != 0)
-		  {
-		    *q = *q + (
-			       (c >= '0' && c <= '9') ? 
-		               (c - '0') : ((c >= 'A' && c <= 'F') ? 
-					    (c - 'A' + 10) : (c - 'a' + 10))
-			       );
-		    p++, q++;
-		  }
-	      }
-	  } 
-	else
-	  *q++ = *p++; 
-      }
- 
-    /* terminate the outpath */
-    *q = 0;
-
-    return(*status);   
-}
-/*---------------------------------------------------------------------------*/
-
-int fits_is_url_absolute(char *url)
-/*
-  Return a True (1) or False (0) value indicating whether or not the passed
-  URL string contains an access method specifier or not. Note that this is
-  a boolean function and it neither reads nor returns the standard error
-  status parameter
-*/
-{
-  char *tmpStr1, *tmpStr2;
-
-  char reserved[] = {':',';','/','?','@','&','=','+','$',','};
-
-  /*
-    The rule for determing if an URL is relative or absolute is that it (1)
-    must have a colon ":" and (2) that the colon must appear before any other
-    reserved URL character in the URL string. We first see if a colon exists,
-    get its position in the string, and then check to see if any of the other
-    reserved characters exists and if their position in the string is greater
-    than that of the colons. 
-   */
-
-  if( (tmpStr1 = strchr(url,reserved[0])) != NULL                       &&
-     ((tmpStr2 = strchr(url,reserved[1])) == NULL || tmpStr2 > tmpStr1) &&
-     ((tmpStr2 = strchr(url,reserved[2])) == NULL || tmpStr2 > tmpStr1) &&
-     ((tmpStr2 = strchr(url,reserved[3])) == NULL || tmpStr2 > tmpStr1) &&
-     ((tmpStr2 = strchr(url,reserved[4])) == NULL || tmpStr2 > tmpStr1) &&
-     ((tmpStr2 = strchr(url,reserved[5])) == NULL || tmpStr2 > tmpStr1) &&
-     ((tmpStr2 = strchr(url,reserved[6])) == NULL || tmpStr2 > tmpStr1) &&
-     ((tmpStr2 = strchr(url,reserved[7])) == NULL || tmpStr2 > tmpStr1) &&
-     ((tmpStr2 = strchr(url,reserved[8])) == NULL || tmpStr2 > tmpStr1) &&
-     ((tmpStr2 = strchr(url,reserved[9])) == NULL || tmpStr2 > tmpStr1)   )
-    {
-      return(1);
-    }
-  else
-    {
-      return(0);
-    }
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/group.h b/src/external/OpenGR/3rdparty/cfitsio/group.h
deleted file mode 100644
index f7aae5b1d..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/group.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#define MAX_HDU_TRACKER 1000
-
-typedef struct _HDUtracker HDUtracker;
-
-struct _HDUtracker
-{
-  int nHDU;
-
-  char *filename[MAX_HDU_TRACKER];
-  int  position[MAX_HDU_TRACKER];
-
-  char *newFilename[MAX_HDU_TRACKER];
-  int  newPosition[MAX_HDU_TRACKER];
-};
-
-/* functions used internally in the grouping convention module */
-
-int ffgtdc(int grouptype, int xtensioncol, int extnamecol, int extvercol,
-	   int positioncol, int locationcol, int uricol, char *ttype[],
-	   char *tform[], int *ncols, int  *status);
-
-int ffgtgc(fitsfile *gfptr, int *xtensionCol, int *extnameCol, int *extverCol,
-	   int *positionCol, int *locationCol, int *uriCol, int *grptype,
-	   int *status);
-
-int ffgmul(fitsfile *mfptr, int rmopt, int *status);
-
-int ffgmf(fitsfile *gfptr, char *xtension, char *extname, int extver,	   
-	  int position,	char *location,	long *member, int *status);
-
-int ffgtrmr(fitsfile *gfptr, HDUtracker *HDU, int *status);
-
-int ffgtcpr(fitsfile *infptr, fitsfile *outfptr, int cpopt, HDUtracker *HDU,
-	    int *status);
-
-int fftsad(fitsfile *mfptr, HDUtracker *HDU, int *newPosition, 
-	   char *newFileName);
-
-int fftsud(fitsfile *mfptr, HDUtracker *HDU, int newPosition, 
-	   char *newFileName);
-
-void prepare_keyvalue(char *keyvalue);
-
-int fits_path2url(char *inpath, char *outpath, int  *status);
-
-int fits_url2path(char *inpath, char *outpath, int  *status);
-
-int fits_get_cwd(char *cwd, int *status);
-
-int fits_get_url(fitsfile *fptr, char *realURL, char *startURL, 
-		 char *realAccess, char *startAccess, int *iostate, 
-		 int *status);
-
-int fits_clean_url(char *inURL, char *outURL, int *status);
-
-int fits_relurl2url(char *refURL, char *relURL, char *absURL, int *status);
-
-int fits_url2relurl(char *refURL, char *absURL, char *relURL, int *status);
-
-int fits_encode_url(char *inpath, char *outpath, int *status);
-
-int fits_unencode_url(char *inpath, char *outpath, int *status);
-
-int fits_is_url_absolute(char *url);
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/grparser.c b/src/external/OpenGR/3rdparty/cfitsio/grparser.c
deleted file mode 100644
index 76b64569c..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/grparser.c
+++ /dev/null
@@ -1,1338 +0,0 @@
-/*		T E M P L A T E   P A R S E R
-		=============================
-
-		by Jerzy.Borkowski@obs.unige.ch
-
-		Integral Science Data Center
-		ch. d'Ecogia 16
-		1290 Versoix
-		Switzerland
-
-14-Oct-98: initial release
-16-Oct-98: code cleanup, #include  included, now gcc -Wall prints no
-		warnings during compilation. Bugfix: now one can specify additional
-		columns in group HDU. Autoindexing also works in this situation
-		(colunms are number from 7 however).
-17-Oct-98: bugfix: complex keywords were incorrectly written (was TCOMPLEX should
-		be TDBLCOMPLEX).
-20-Oct-98: bugfix: parser was writing EXTNAME twice, when first HDU in template is
-		defined with XTENSION IMAGE then parser creates now dummy PHDU,
-		SIMPLE T is now allowed only at most once and in first HDU only.
-		WARNING: one should not define EXTNAME keyword for GROUP HDUs, as
-		they have them already defined by parser (EXTNAME = GROUPING).
-		Parser accepts EXTNAME oin GROUP HDU definition, but in this
-		case multiple EXTNAME keywords will present in HDU header.
-23-Oct-98: bugfix: unnecessary space was written to FITS file for blank
-		keywords.
-24-Oct-98: syntax change: empty lines and lines with only whitespaces are 
-		written to FITS files as blank keywords (if inside group/hdu
-		definition). Previously lines had to have at least 8 spaces.
-		Please note, that due to pecularities of CFITSIO if the
-		last keyword(s) defined for given HDU are blank keywords
-		consisting of only 80 spaces, then (some of) those keywords
-		may be silently deleted by CFITSIO.
-13-Nov-98: bugfix: parser was writing GRPNAME twice. Parser still creates
-                GRPNAME keywords for GROUP HDU's which do not specify them.
-                However, values (of form DEFAULT_GROUP_XXX) are assigned
-                not necessarily in order HDUs appear in template file, but
-                rather in order parser completes their creation in FITS
-                file. Also, when including files, if fopen fails, parser
-                tries to open file with a name = directory_of_top_level
-                file + name of file to be included, as long as name
-                of file to be included does not specify absolute pathname.
-16-Nov-98: bugfix to bugfix from 13-Nov-98
-19-Nov-98: EXTVER keyword is now automatically assigned value by parser.
-17-Dev-98: 2 new things added: 1st: CFITSIO_INCLUDE_FILES environment
-		variable can contain a colon separated list of directories
-		to look for when looking for template include files (and master
-		template also). 2nd: it is now possible to append template
-		to nonempty FITS. file. fitsfile *ff no longer needs to point
-		to an empty FITS file with 0 HDUs in it. All data written by
-		parser will simple be appended at the end of file.
-22-Jan-99: changes to parser: when in append mode parser initially scans all
-		existing HDUs to built a list of already used EXTNAME/EXTVERs
-22-Jan-99: Bruce O'Neel, bugfix : TLONG should always reference long type
-		variable on OSF/Alpha and on 64-bit archs in general
-20-Jun-2002 Wm Pence, added support for the HIERARCH keyword convention in
-                which keyword names can effectively be longer than 8 characters.
-                Example:
-                HIERARCH  LongKeywordName = 'value' / comment
-30-Jan-2003 Wm Pence, bugfix: ngp_read_xtension was testing for "ASCIITABLE" 
-                instead of "TABLE" as the XTENSION value of an ASCII table,
-                and it did not allow for optional trailing spaces in the
-                "IMAGE" or "TABLE" string. 
-16-Dec-2003 James Peachey: ngp_keyword_all_write was modified to apply
-                comments from the template file to the output file in
-                the case of reserved keywords (e.g. tform#, ttype# etcetera).
-*/
-
-
-#include 
-#include 
-
-#ifdef sparc
-#include 
-#include 
-#endif
-
-#include 
-#include "fitsio2.h"
-#include "grparser.h"
-
-NGP_RAW_LINE	ngp_curline = { NULL, NULL, NULL, NGP_TTYPE_UNKNOWN, NULL, NGP_FORMAT_OK, 0 };
-NGP_RAW_LINE	ngp_prevline = { NULL, NULL, NULL, NGP_TTYPE_UNKNOWN, NULL, NGP_FORMAT_OK, 0 };
-
-int		ngp_inclevel = 0;		/* number of included files, 1 - means mean file */
-int		ngp_grplevel = 0;		/* group nesting level, 0 - means no grouping */
-
-FILE		*ngp_fp[NGP_MAX_INCLUDE];	/* stack of included file handles */
-int		ngp_keyidx = NGP_TOKEN_UNKNOWN;	/* index of token in current line */
-NGP_TOKEN	ngp_linkey;			/* keyword after line analyze */
-
-char            ngp_master_dir[NGP_MAX_FNAME];  /* directory of top level include file */
-
-NGP_TKDEF	ngp_tkdef[] = 			/* tokens recognized by parser */
-      { {	"\\INCLUDE",	NGP_TOKEN_INCLUDE },
-	{	"\\GROUP",	NGP_TOKEN_GROUP },
-	{	"\\END",	NGP_TOKEN_END },
-	{	"XTENSION",	NGP_TOKEN_XTENSION },
-	{	"SIMPLE",	NGP_TOKEN_SIMPLE },
-	{	NULL,		NGP_TOKEN_UNKNOWN }
-      };
-
-int	master_grp_idx = 1;			/* current unnamed group in object */
-
-int		ngp_extver_tab_size = 0;
-NGP_EXTVER_TAB	*ngp_extver_tab = NULL;
-
-
-int	ngp_get_extver(char *extname, int *version)
- { NGP_EXTVER_TAB *p;
-   char 	*p2;
-   int		i;
-
-   if ((NULL == extname) || (NULL == version)) return(NGP_BAD_ARG);
-   if ((NULL == ngp_extver_tab) && (ngp_extver_tab_size > 0)) return(NGP_BAD_ARG);
-   if ((NULL != ngp_extver_tab) && (ngp_extver_tab_size <= 0)) return(NGP_BAD_ARG);
-
-   for (i=0; i 0)) return(NGP_BAD_ARG);
-   if ((NULL != ngp_extver_tab) && (ngp_extver_tab_size <= 0)) return(NGP_BAD_ARG);
-
-   for (i=0; i ngp_extver_tab[i].version)  ngp_extver_tab[i].version = version;
-          return(NGP_OK);
-        }
-    }
-
-   if (NULL == ngp_extver_tab)
-     { p = (NGP_EXTVER_TAB *)ngp_alloc(sizeof(NGP_EXTVER_TAB)); }
-   else
-     { p = (NGP_EXTVER_TAB *)ngp_realloc(ngp_extver_tab, (ngp_extver_tab_size + 1) * sizeof(NGP_EXTVER_TAB)); }
-
-   if (NULL == p) return(NGP_NO_MEMORY);
-
-   p2 = ngp_alloc(strlen(extname) + 1);
-   if (NULL == p2)
-     { ngp_free(p);
-       return(NGP_NO_MEMORY);
-     }
-
-   strcpy(p2, extname);
-   ngp_extver_tab = p;
-   ngp_extver_tab[ngp_extver_tab_size].extname = p2;
-   ngp_extver_tab[ngp_extver_tab_size].version = version;
-
-   ngp_extver_tab_size++;
-
-   return(NGP_OK);
- }
-
-
-int	ngp_delete_extver_tab(void)
- { int i;
-
-   if ((NULL == ngp_extver_tab) && (ngp_extver_tab_size > 0)) return(NGP_BAD_ARG);
-   if ((NULL != ngp_extver_tab) && (ngp_extver_tab_size <= 0)) return(NGP_BAD_ARG);
-   if ((NULL == ngp_extver_tab) && (0 == ngp_extver_tab_size)) return(NGP_OK);
-
-   for (i=0; i allocsize)
-        { p2 = (char *)ngp_realloc(*p, alen);	/* realloc buffer, if there is need */
-          if (NULL == p2)
-            { r = NGP_NO_MEMORY;
-              break;
-            }
-	  *p = p2;
-          allocsize = alen;
-        }
-      (*p)[llen - 1] = c;			/* copy character to buffer */
-    }
-
-   llen++;					/* place for terminating \0 */
-   if (llen != allocsize)
-     { p2 = (char *)ngp_realloc(*p, llen);
-       if (NULL == p2) r = NGP_NO_MEMORY;
-       else
-         { *p = p2;
-           (*p)[llen - 1] = 0;			/* copy \0 to buffer */
-         }         
-     }
-   else
-     { (*p)[llen - 1] = 0;			/* necessary when line read was empty */
-     }
-
-   if ((NGP_EOF != r) && (NGP_OK != r))		/* in case of errors free resources */
-     { ngp_free(*p);
-       *p = NULL;
-     }
-   
-   return(r);					/* return  status code */
- }
-
-	/* free current line structure */
-
-int	ngp_free_line(void)
- {
-   if (NULL != ngp_curline.line)
-     { ngp_free(ngp_curline.line);
-       ngp_curline.line = NULL;
-       ngp_curline.name = NULL;
-       ngp_curline.value = NULL;
-       ngp_curline.comment = NULL;
-       ngp_curline.type = NGP_TTYPE_UNKNOWN;
-       ngp_curline.format = NGP_FORMAT_OK;
-       ngp_curline.flags = 0;
-     }
-   return(NGP_OK);
- }
-
-	/* free cached line structure */
-
-int	ngp_free_prevline(void)
- {
-   if (NULL != ngp_prevline.line)
-     { ngp_free(ngp_prevline.line);
-       ngp_prevline.line = NULL;
-       ngp_prevline.name = NULL;
-       ngp_prevline.value = NULL;
-       ngp_prevline.comment = NULL;
-       ngp_prevline.type = NGP_TTYPE_UNKNOWN;
-       ngp_prevline.format = NGP_FORMAT_OK;
-       ngp_prevline.flags = 0;
-     }
-   return(NGP_OK);
- }
-
-	/* read one line */
-
-int	ngp_read_line_buffered(FILE *fp)
- {
-   ngp_free_line();				/* first free current line (if any) */
-   
-   if (NULL != ngp_prevline.line)		/* if cached, return cached line */
-     { ngp_curline = ngp_prevline;
-       ngp_prevline.line = NULL;
-       ngp_prevline.name = NULL;
-       ngp_prevline.value = NULL;
-       ngp_prevline.comment = NULL;
-       ngp_prevline.type = NGP_TTYPE_UNKNOWN;
-       ngp_prevline.format = NGP_FORMAT_OK;
-       ngp_prevline.flags = 0;
-       ngp_curline.flags = NGP_LINE_REREAD;
-       return(NGP_OK);
-     }
-
-   ngp_curline.flags = 0;   			/* if not cached really read line from file */
-   return(ngp_line_from_file(fp, &(ngp_curline.line)));
- }
-
-	/* unread line */
-
-int	ngp_unread_line(void)
- {
-   if (NULL == ngp_curline.line)		/* nothing to unread */
-     return(NGP_EMPTY_CURLINE);
-
-   if (NULL != ngp_prevline.line)		/* we cannot unread line twice */
-     return(NGP_UNREAD_QUEUE_FULL);
-
-   ngp_prevline = ngp_curline;
-   ngp_curline.line = NULL;
-   return(NGP_OK);
- }
-
-	/* a first guess line decomposition */
-
-int	ngp_extract_tokens(NGP_RAW_LINE *cl)
- { char *p, *s;
-   int	cl_flags, i;
-
-   p = cl->line;				/* start from beginning of line */
-   if (NULL == p) return(NGP_NUL_PTR);
-
-   cl->name = cl->value = cl->comment = NULL;
-   cl->type = NGP_TTYPE_UNKNOWN;
-   cl->format = NGP_FORMAT_OK;
-
-   cl_flags = 0;
-
-   for (i=0;; i++)				/* if 8 spaces at beginning then line is comment */
-    { if ((0 == *p) || ('\n' == *p))
-        {					/* if line has only blanks -> write blank keyword */
-          cl->line[0] = 0;			/* create empty name (0 length string) */
-          cl->comment = cl->name = cl->line;
-	  cl->type = NGP_TTYPE_RAW;		/* signal write unformatted to FITS file */
-          return(NGP_OK);
-        }
-      if ((' ' != *p) && ('\t' != *p)) break;
-      if (i >= 7)
-        { 
-          cl->comment = p + 1;
-          for (s = cl->comment;; s++)		/* filter out any EOS characters in comment */
-           { if ('\n' == *s) *s = 0;
-	     if (0 == *s) break;
-           }
-          cl->line[0] = 0;			/* create empty name (0 length string) */
-          cl->name = cl->line;
-	  cl->type = NGP_TTYPE_RAW;
-          return(NGP_OK);
-        }
-      p++;
-    }
-
-   cl->name = p;
-
-   for (;;)					/* we need to find 1st whitespace */
-    { if ((0 == *p) || ('\n' == *p))
-        { *p = 0;
-          break;
-        }
-
-      /*
-        from Richard Mathar, 2002-05-03, add 10 lines:
-        if upper/lowercase HIERARCH followed also by an equal sign...
-      */
-      if( fits_strncasecmp("HIERARCH",p,strlen("HIERARCH")) == 0 )
-      {
-           char * const eqsi=strchr(p,'=') ;
-           if( eqsi )
-           {
-              cl_flags |= NGP_FOUND_EQUAL_SIGN ;
-              p=eqsi ;
-              break ;
-           }
-      }
-
-      if ((' ' == *p) || ('\t' == *p)) break;
-      if ('=' == *p)
-        { cl_flags |= NGP_FOUND_EQUAL_SIGN;
-          break;
-        }
-
-      p++;
-    }
-
-   if (*p) *(p++) = 0;				/* found end of keyname so terminate string with zero */
-
-   if ((!fits_strcasecmp("HISTORY", cl->name))
-    || (!fits_strcasecmp("COMMENT", cl->name))
-    || (!fits_strcasecmp("CONTINUE", cl->name)))
-     { cl->comment = p;
-       for (s = cl->comment;; s++)		/* filter out any EOS characters in comment */
-        { if ('\n' == *s) *s = 0;
-	  if (0 == *s) break;
-        }
-       cl->type = NGP_TTYPE_RAW;
-       return(NGP_OK);
-     }
-
-   if (!fits_strcasecmp("\\INCLUDE", cl->name))
-     {
-       for (;; p++)  if ((' ' != *p) && ('\t' != *p)) break; /* skip whitespace */
-
-       cl->value = p;
-       for (s = cl->value;; s++)		/* filter out any EOS characters */
-        { if ('\n' == *s) *s = 0;
-	  if (0 == *s) break;
-        }
-       cl->type = NGP_TTYPE_UNKNOWN;
-       return(NGP_OK);
-     }
-       
-   for (;; p++)
-    { if ((0 == *p) || ('\n' == *p))  return(NGP_OK);	/* test if at end of string */
-      if ((' ' == *p) || ('\t' == *p)) continue; /* skip whitespace */
-      if (cl_flags & NGP_FOUND_EQUAL_SIGN) break;
-      if ('=' != *p) break;			/* ignore initial equal sign */
-      cl_flags |= NGP_FOUND_EQUAL_SIGN;
-    }
-      
-   if ('/' == *p)				/* no value specified, comment only */
-     { p++;
-       if ((' ' == *p) || ('\t' == *p)) p++;
-       cl->comment = p;
-       for (s = cl->comment;; s++)		/* filter out any EOS characters in comment */
-        { if ('\n' == *s) *s = 0;
-	  if (0 == *s) break;
-        }
-       return(NGP_OK);
-     }
-
-   if ('\'' == *p)				/* we have found string within quotes */
-     { cl->value = s = ++p;			/* set pointer to beginning of that string */
-       cl->type = NGP_TTYPE_STRING;		/* signal that it is of string type */
-
-       for (;;)					/* analyze it */
-        { if ((0 == *p) || ('\n' == *p))	/* end of line -> end of string */
-            { *s = 0; return(NGP_OK); }
-
-          if ('\'' == *p)			/* we have found doublequote */
-            { if ((0 == p[1]) || ('\n' == p[1]))/* doublequote is the last character in line */
-                { *s = 0; return(NGP_OK); }
-              if (('\t' == p[1]) || (' ' == p[1])) /* duoblequote was string terminator */
-                { *s = 0; p++; break; }
-              if ('\'' == p[1]) p++;		/* doublequote is inside string, convert "" -> " */ 
-            }
-
-          *(s++) = *(p++);			/* compact string in place, necess. by "" -> " conversion */
-        }
-     }
-   else						/* regular token */
-     { 
-       cl->value = p;				/* set pointer to token */
-       cl->type = NGP_TTYPE_UNKNOWN;		/* we dont know type at the moment */
-       for (;; p++)				/* we need to find 1st whitespace */
-        { if ((0 == *p) || ('\n' == *p))
-            { *p = 0; return(NGP_OK); }
-          if ((' ' == *p) || ('\t' == *p)) break;
-        }
-       if (*p)  *(p++) = 0;			/* found so terminate string with zero */
-     }
-       
-   for (;; p++)
-    { if ((0 == *p) || ('\n' == *p))  return(NGP_OK);	/* test if at end of string */
-      if ((' ' != *p) && ('\t' != *p)) break;	/* skip whitespace */
-    }
-      
-   if ('/' == *p)				/* no value specified, comment only */
-     { p++;
-       if ((' ' == *p) || ('\t' == *p)) p++;
-       cl->comment = p;
-       for (s = cl->comment;; s++)		/* filter out any EOS characters in comment */
-        { if ('\n' == *s) *s = 0;
-	  if (0 == *s) break;
-        }
-       return(NGP_OK);
-     }
-
-   cl->format = NGP_FORMAT_ERROR;
-   return(NGP_OK);				/* too many tokens ... */
- }
-
-/*      try to open include file. If open fails and fname
-        does not specify absolute pathname, try to open fname
-        in any directory specified in CFITSIO_INCLUDE_FILES
-        environment variable. Finally try to open fname
-        relative to ngp_master_dir, which is directory of top
-        level include file
-*/
-
-int	ngp_include_file(char *fname)		/* try to open include file */
- { char *p, *p2, *cp, *envar, envfiles[NGP_MAX_ENVFILES];
-   char *saveptr;
-
-   if (NULL == fname) return(NGP_NUL_PTR);
-
-   if (ngp_inclevel >= NGP_MAX_INCLUDE)		/* too many include files */
-     return(NGP_INC_NESTING);
-
-   if (NULL == (ngp_fp[ngp_inclevel] = fopen(fname, "r")))
-     {                                          /* if simple open failed .. */
-       envar = getenv("CFITSIO_INCLUDE_FILES");	/* scan env. variable, and retry to open */
-
-       if (NULL != envar)			/* is env. variable defined ? */
-         { strncpy(envfiles, envar, NGP_MAX_ENVFILES - 1);
-           envfiles[NGP_MAX_ENVFILES - 1] = 0;	/* copy search path to local variable, env. is fragile */
-
-           for (p2 = ffstrtok(envfiles, ":",&saveptr); NULL != p2; p2 = ffstrtok(NULL, ":",&saveptr))
-            {
-	      cp = (char *)ngp_alloc(strlen(fname) + strlen(p2) + 2);
-	      if (NULL == cp) return(NGP_NO_MEMORY);
-
-	      strcpy(cp, p2);
-#ifdef  MSDOS
-              strcat(cp, "\\");			/* abs. pathname for MSDOS */
-               
-#else
-              strcat(cp, "/");			/* and for unix */
-#endif
-	      strcat(cp, fname);
-	  
-	      ngp_fp[ngp_inclevel] = fopen(cp, "r");
-	      ngp_free(cp);
-
-	      if (NULL != ngp_fp[ngp_inclevel]) break;
-	    }
-        }
-                                      
-       if (NULL == ngp_fp[ngp_inclevel])	/* finally try to open relative to top level */
-         {
-#ifdef  MSDOS
-           if ('\\' == fname[0]) return(NGP_ERR_FOPEN); /* abs. pathname for MSDOS, does not support C:\\PATH */
-#else
-           if ('/' == fname[0]) return(NGP_ERR_FOPEN); /* and for unix */
-#endif
-           if (0 == ngp_master_dir[0]) return(NGP_ERR_FOPEN);
-
-	   p = ngp_alloc(strlen(fname) + strlen(ngp_master_dir) + 1);
-           if (NULL == p) return(NGP_NO_MEMORY);
-
-           strcpy(p, ngp_master_dir);		/* construct composite pathname */
-           strcat(p, fname);			/* comp = master + fname */
-
-           ngp_fp[ngp_inclevel] = fopen(p, "r");/* try to open composite */
-           ngp_free(p);				/* we don't need buffer anymore */
-
-           if (NULL == ngp_fp[ngp_inclevel])
-             return(NGP_ERR_FOPEN);		/* fail if error */
-         }
-     }
-
-   ngp_inclevel++;
-   return(NGP_OK);
- }
-
-
-/* read line in the intelligent way. All \INCLUDE directives are handled,
-   empty and comment line skipped. If this function returns NGP_OK, than
-   decomposed line (name, type, value in proper type and comment) are
-   stored in ngp_linkey structure. ignore_blank_lines parameter is zero
-   when parser is inside GROUP or HDU definition. Nonzero otherwise.
-*/
-
-int	ngp_read_line(int ignore_blank_lines)
- { int r, nc, savec;
-   unsigned k;
-
-   if (ngp_inclevel <= 0)		/* do some sanity checking first */
-     { ngp_keyidx = NGP_TOKEN_EOF;	/* no parents, so report error */
-       return(NGP_OK);	
-     }
-   if (ngp_inclevel > NGP_MAX_INCLUDE)  return(NGP_INC_NESTING);
-   if (NULL == ngp_fp[ngp_inclevel - 1]) return(NGP_NUL_PTR);
-
-   for (;;)
-    { switch (r = ngp_read_line_buffered(ngp_fp[ngp_inclevel - 1]))
-       { case NGP_EOF:
-		ngp_inclevel--;			/* end of file, revert to parent */
-		if (ngp_fp[ngp_inclevel])	/* we can close old file */
-		  fclose(ngp_fp[ngp_inclevel]);
-
-		ngp_fp[ngp_inclevel] = NULL;
-		if (ngp_inclevel <= 0)
-		  { ngp_keyidx = NGP_TOKEN_EOF;	/* no parents, so report error */
-		    return(NGP_OK);	
-		  }
-		continue;
-
-	 case NGP_OK:
-		if (ngp_curline.flags & NGP_LINE_REREAD) return(r);
-		break;
-	 default:
-		return(r);
-       }
-      
-      switch (ngp_curline.line[0])
-       { case 0: if (0 == ignore_blank_lines) break; /* ignore empty lines if told so */
-         case '#': continue;			/* ignore comment lines */
-       }
-      
-      r = ngp_extract_tokens(&ngp_curline);	/* analyse line, extract tokens and comment */
-      if (NGP_OK != r) return(r);
-
-      if (NULL == ngp_curline.name)  continue;	/* skip lines consisting only of whitespaces */
-
-      for (k = 0; k < strlen(ngp_curline.name); k++)
-       { if ((ngp_curline.name[k] >= 'a') && (ngp_curline.name[k] <= 'z')) 
-           ngp_curline.name[k] += 'A' - 'a';	/* force keyword to be upper case */
-         if (k == 7) break;  /* only first 8 chars are required to be upper case */
-       }
-
-      for (k=0;; k++)				/* find index of keyword in keyword table */
-       { if (NGP_TOKEN_UNKNOWN == ngp_tkdef[k].code) break;
-         if (0 == strcmp(ngp_curline.name, ngp_tkdef[k].name)) break;
-       }
-
-      ngp_keyidx = ngp_tkdef[k].code;		/* save this index, grammar parser will need this */
-
-      if (NGP_TOKEN_INCLUDE == ngp_keyidx)	/* if this is \INCLUDE keyword, try to include file */
-        { if (NGP_OK != (r = ngp_include_file(ngp_curline.value))) return(r);
-	  continue;				/* and read next line */
-        }
-
-      ngp_linkey.type = NGP_TTYPE_UNKNOWN;	/* now, get the keyword type, it's a long story ... */
-
-      if (NULL != ngp_curline.value)		/* if no value given signal it */
-        { if (NGP_TTYPE_STRING == ngp_curline.type)  /* string type test */
-            { ngp_linkey.type = NGP_TTYPE_STRING;
-              ngp_linkey.value.s = ngp_curline.value;
-            }
-          if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* bool type test */
-            { if ((!fits_strcasecmp("T", ngp_curline.value)) || (!fits_strcasecmp("F", ngp_curline.value)))
-                { ngp_linkey.type = NGP_TTYPE_BOOL;
-                  ngp_linkey.value.b = (fits_strcasecmp("T", ngp_curline.value) ? 0 : 1);
-                }
-            }
-          if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* complex type test */
-            { if (2 == sscanf(ngp_curline.value, "(%lg,%lg)%n", &(ngp_linkey.value.c.re), &(ngp_linkey.value.c.im), &nc))
-                { if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc])
-                   || ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc]))
-                    { ngp_linkey.type = NGP_TTYPE_COMPLEX;
-                    }
-                }
-            }
-          if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* real type test */
-            { if (strchr(ngp_curline.value, '.') && (1 == sscanf(ngp_curline.value, "%lg%n", &(ngp_linkey.value.d), &nc)))
-                {
-		 if ('D' == ngp_curline.value[nc]) {
-		   /* test if template used a 'D' rather than an 'E' as the exponent character (added by WDP in 12/2010) */
-                   savec = nc;
-		   ngp_curline.value[nc] = 'E';
-		   sscanf(ngp_curline.value, "%lg%n", &(ngp_linkey.value.d), &nc);
-		   if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc])
-                    || ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc]))  {
-                       ngp_linkey.type = NGP_TTYPE_REAL;
-                     } else {  /* no, this is not a real value */
-		       ngp_curline.value[savec] = 'D';  /* restore the original D character */
- 		     }
-		 } else {
-		  if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc])
-                   || ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc]))
-                    { ngp_linkey.type = NGP_TTYPE_REAL;
-                    }
-                 } 
-                }
-            }
-          if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* integer type test */
-            { if (1 == sscanf(ngp_curline.value, "%d%n", &(ngp_linkey.value.i), &nc))
-                { if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc])
-                   || ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc]))
-                    { ngp_linkey.type = NGP_TTYPE_INT;
-                    }
-                }
-            }
-          if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* force string type */
-            { ngp_linkey.type = NGP_TTYPE_STRING;
-              ngp_linkey.value.s = ngp_curline.value;
-            }
-        }
-      else
-        { if (NGP_TTYPE_RAW == ngp_curline.type) ngp_linkey.type = NGP_TTYPE_RAW;
-	  else ngp_linkey.type = NGP_TTYPE_NULL;
-	}
-
-      if (NULL != ngp_curline.comment)
-        { strncpy(ngp_linkey.comment, ngp_curline.comment, NGP_MAX_COMMENT); /* store comment */
-	  ngp_linkey.comment[NGP_MAX_COMMENT - 1] = 0;
-	}
-      else
-        { ngp_linkey.comment[0] = 0;
-        }
-
-      strncpy(ngp_linkey.name, ngp_curline.name, NGP_MAX_NAME); /* and keyword's name */
-      ngp_linkey.name[NGP_MAX_NAME - 1] = 0;
-
-      if (strlen(ngp_linkey.name) > FLEN_KEYWORD)  /* WDP: 20-Jun-2002:  mod to support HIERARCH */
-        { 
-           return(NGP_BAD_ARG);		/* cfitsio does not allow names > 8 chars */
-        }
-      
-      return(NGP_OK);			/* we have valid non empty line, so return success */
-    }
- }
-
-	/* check whether keyword can be written as is */
-
-int	ngp_keyword_is_write(NGP_TOKEN *ngp_tok)
- { int i, j, l, spc;
-                        /* indexed variables not to write */
-
-   static char *nm[] = { "NAXIS", "TFORM", "TTYPE", NULL } ;
-
-                        /* non indexed variables not allowed to write */
-  
-   static char *nmni[] = { "SIMPLE", "XTENSION", "BITPIX", "NAXIS", "PCOUNT",
-                           "GCOUNT", "TFIELDS", "THEAP", "EXTEND", "EXTVER",
-                           NULL } ;
-
-   if (NULL == ngp_tok) return(NGP_NUL_PTR);
-
-   for (j = 0; ; j++)           /* first check non indexed */
-    { if (NULL == nmni[j]) break;
-      if (0 == strcmp(nmni[j], ngp_tok->name)) return(NGP_BAD_ARG);
-    } 
-
-   for (j = 0; ; j++)           /* now check indexed */
-    { if (NULL == nm[j]) return(NGP_OK);
-      l = strlen(nm[j]);
-      if ((l < 1) || (l > 5)) continue;
-      if (0 == strncmp(nm[j], ngp_tok->name, l)) break;
-    } 
-
-   if ((ngp_tok->name[l] < '1') || (ngp_tok->name[l] > '9')) return(NGP_OK);
-   spc = 0;
-   for (i = l + 1; i < 8; i++)
-    { if (spc) { if (' ' != ngp_tok->name[i]) return(NGP_OK); }
-      else
-       { if ((ngp_tok->name[i] >= '0') && (ngp_tok->name[i] <= '9')) continue;
-         if (' ' == ngp_tok->name[i]) { spc = 1; continue; }
-         if (0 == ngp_tok->name[i]) break;
-         return(NGP_OK);
-       }
-    }
-   return(NGP_BAD_ARG);
- }
-
-	/* write (almost) all keywords from given HDU to disk */
-
-int     ngp_keyword_all_write(NGP_HDU *ngph, fitsfile *ffp, int mode)
- { int		i, r, ib;
-   char		buf[200];
-   long		l;
-
-
-   if (NULL == ngph) return(NGP_NUL_PTR);
-   if (NULL == ffp) return(NGP_NUL_PTR);
-   r = NGP_OK;
-   
-   for (i=0; itokcnt; i++)
-    { r = ngp_keyword_is_write(&(ngph->tok[i]));
-      if ((NGP_REALLY_ALL & mode) || (NGP_OK == r))
-        { switch (ngph->tok[i].type)
-           { case NGP_TTYPE_BOOL:
-			ib = ngph->tok[i].value.b;
-			fits_write_key(ffp, TLOGICAL, ngph->tok[i].name, &ib, ngph->tok[i].comment, &r);
-			break;
-             case NGP_TTYPE_STRING:
-			fits_write_key_longstr(ffp, ngph->tok[i].name, ngph->tok[i].value.s, ngph->tok[i].comment, &r);
-			break;
-             case NGP_TTYPE_INT:
-			l = ngph->tok[i].value.i;	/* bugfix - 22-Jan-99, BO - nonalignment of OSF/Alpha */
-			fits_write_key(ffp, TLONG, ngph->tok[i].name, &l, ngph->tok[i].comment, &r);
-			break;
-             case NGP_TTYPE_REAL:
-			fits_write_key(ffp, TDOUBLE, ngph->tok[i].name, &(ngph->tok[i].value.d), ngph->tok[i].comment, &r);
-			break;
-             case NGP_TTYPE_COMPLEX:
-			fits_write_key(ffp, TDBLCOMPLEX, ngph->tok[i].name, &(ngph->tok[i].value.c), ngph->tok[i].comment, &r);
-			break;
-             case NGP_TTYPE_NULL:
-			fits_write_key_null(ffp, ngph->tok[i].name, ngph->tok[i].comment, &r);
-			break;
-             case NGP_TTYPE_RAW:
-			if (0 == strcmp("HISTORY", ngph->tok[i].name))
-			  { fits_write_history(ffp, ngph->tok[i].comment, &r);
-			    break;
-			  }
-			if (0 == strcmp("COMMENT", ngph->tok[i].name))
-			  { fits_write_comment(ffp, ngph->tok[i].comment, &r);
-			    break;
-			  }
-			sprintf(buf, "%-8.8s%s", ngph->tok[i].name, ngph->tok[i].comment);
-			fits_write_record(ffp, buf, &r);
-                        break;
-           }
-        }
-      else if (NGP_BAD_ARG == r) /* enhancement 10 dec 2003, James Peachey: template comments replace defaults */
-        { r = NGP_OK;						/* update comments of special keywords like TFORM */
-          if (ngph->tok[i].comment && *ngph->tok[i].comment)	/* do not update with a blank comment */
-            { fits_modify_comment(ffp, ngph->tok[i].name, ngph->tok[i].comment, &r);
-            }
-        }
-      else /* other problem, typically a blank token */
-        { r = NGP_OK;						/* skip this token, but continue */
-        }
-      if (r) return(r);
-    }
-     
-   fits_set_hdustruc(ffp, &r);				/* resync cfitsio */
-   return(r);
- }
-
-	/* init HDU structure */
-
-int	ngp_hdu_init(NGP_HDU *ngph)
- { if (NULL == ngph) return(NGP_NUL_PTR);
-   ngph->tok = NULL;
-   ngph->tokcnt = 0;
-   return(NGP_OK);
- }
-
-	/* clear HDU structure */
-
-int	ngp_hdu_clear(NGP_HDU *ngph)
- { int i;
-
-   if (NULL == ngph) return(NGP_NUL_PTR);
-
-   for (i=0; itokcnt; i++)
-    { if (NGP_TTYPE_STRING == ngph->tok[i].type)
-        if (NULL != ngph->tok[i].value.s)
-          { ngp_free(ngph->tok[i].value.s);
-            ngph->tok[i].value.s = NULL;
-          }
-    }
-
-   if (NULL != ngph->tok) ngp_free(ngph->tok);
-
-   ngph->tok = NULL;
-   ngph->tokcnt = 0;
-
-   return(NGP_OK);
- }
-
-	/* insert new token to HDU structure */
-
-int	ngp_hdu_insert_token(NGP_HDU *ngph, NGP_TOKEN *newtok)
- { NGP_TOKEN *tkp;
-   
-   if (NULL == ngph) return(NGP_NUL_PTR);
-   if (NULL == newtok) return(NGP_NUL_PTR);
-
-   if (0 == ngph->tokcnt)
-     tkp = (NGP_TOKEN *)ngp_alloc((ngph->tokcnt + 1) * sizeof(NGP_TOKEN));
-   else
-     tkp = (NGP_TOKEN *)ngp_realloc(ngph->tok, (ngph->tokcnt + 1) * sizeof(NGP_TOKEN));
-
-   if (NULL == tkp) return(NGP_NO_MEMORY);
-       
-   ngph->tok = tkp;
-   ngph->tok[ngph->tokcnt] = *newtok;
-
-   if (NGP_TTYPE_STRING == newtok->type)
-     { if (NULL != newtok->value.s)
-         { ngph->tok[ngph->tokcnt].value.s = (char *)ngp_alloc(1 + strlen(newtok->value.s));
-           if (NULL == ngph->tok[ngph->tokcnt].value.s) return(NGP_NO_MEMORY);
-           strcpy(ngph->tok[ngph->tokcnt].value.s, newtok->value.s);
-         }
-     }
-
-   ngph->tokcnt++;
-   return(NGP_OK);
- }
-
-
-int	ngp_append_columns(fitsfile *ff, NGP_HDU *ngph, int aftercol)
- { int		r, i, j, exitflg, ngph_i;
-   char 	*my_tform, *my_ttype;
-   char		ngph_ctmp;
-
-
-   if (NULL == ff) return(NGP_NUL_PTR);
-   if (NULL == ngph) return(NGP_NUL_PTR);
-   if (0 == ngph->tokcnt) return(NGP_OK);	/* nothing to do ! */
-
-   r = NGP_OK;
-   exitflg = 0;
-
-   for (j=aftercol; jtok[i].name, "TFORM%d%c", &ngph_i, &ngph_ctmp))
-           { if ((NGP_TTYPE_STRING == ngph->tok[i].type) && (ngph_i == (j + 1)))
-   	    { my_tform = ngph->tok[i].value.s;
-   	    }
-                }
-         else if (1 == sscanf(ngph->tok[i].name, "TTYPE%d%c", &ngph_i, &ngph_ctmp))
-           { if ((NGP_TTYPE_STRING == ngph->tok[i].type) && (ngph_i == (j + 1)))
-               { my_ttype = ngph->tok[i].value.s;
-               }
-           }
-         
-         if ((NULL != my_tform) && (my_ttype[0])) break;
-         
-         if (i < (ngph->tokcnt - 1)) continue;
-         exitflg = 1;
-         break;
-       }
-      if ((NGP_OK == r) && (NULL != my_tform))
-        fits_insert_col(ff, j + 1, my_ttype, my_tform, &r);
-
-      if ((NGP_OK != r) || exitflg) break;
-    }
-   return(r);
- }
-
-	/* read complete HDU */
-
-int	ngp_read_xtension(fitsfile *ff, int parent_hn, int simple_mode)
- { int		r, exflg, l, my_hn, tmp0, incrementor_index, i, j;
-   int		ngph_dim, ngph_bitpix, ngph_node_type, my_version;
-   char		incrementor_name[NGP_MAX_STRING], ngph_ctmp;
-   char 	*ngph_extname = 0;
-   long		ngph_size[NGP_MAX_ARRAY_DIM];
-   NGP_HDU	ngph;
-   long		lv;
-
-   incrementor_name[0] = 0;			/* signal no keyword+'#' found yet */
-   incrementor_index = 0;
-
-   if (NGP_OK != (r = ngp_hdu_init(&ngph))) return(r);
-
-   if (NGP_OK != (r = ngp_read_line(0))) return(r);	/* EOF always means error here */
-   switch (NGP_XTENSION_SIMPLE & simple_mode)
-     {
-       case 0:  if (NGP_TOKEN_XTENSION != ngp_keyidx) return(NGP_TOKEN_NOT_EXPECT);
-		break;
-       default:	if (NGP_TOKEN_SIMPLE != ngp_keyidx) return(NGP_TOKEN_NOT_EXPECT);
-		break;
-     }
-       	
-   if (NGP_OK != (r = ngp_hdu_insert_token(&ngph, &ngp_linkey))) return(r);
-
-   for (;;)
-    { if (NGP_OK != (r = ngp_read_line(0))) return(r);	/* EOF always means error here */
-      exflg = 0;
-      switch (ngp_keyidx)
-       { 
-	 case NGP_TOKEN_SIMPLE:
-	 		r = NGP_TOKEN_NOT_EXPECT;
-			break;
-	 		                        
-	 case NGP_TOKEN_END:
-         case NGP_TOKEN_XTENSION:
-         case NGP_TOKEN_GROUP:
-         		r = ngp_unread_line();	/* WARNING - not break here .... */
-         case NGP_TOKEN_EOF:
-			exflg = 1;
- 			break;
-
-         default:	l = strlen(ngp_linkey.name);
-			if ((l >= 2) && (l <= 6))
-			  { if ('#' == ngp_linkey.name[l - 1])
-			      { if (0 == incrementor_name[0])
-			          { memcpy(incrementor_name, ngp_linkey.name, l - 1);
-			            incrementor_name[l - 1] = 0;
-			          }
-			        if (((l - 1) == (int)strlen(incrementor_name)) && (0 == memcmp(incrementor_name, ngp_linkey.name, l - 1)))
-			          { incrementor_index++;
-			          }
-			        sprintf(ngp_linkey.name + l - 1, "%d", incrementor_index);
-			      }
-			  }
-			r = ngp_hdu_insert_token(&ngph, &ngp_linkey);
- 			break;
-       }
-      if ((NGP_OK != r) || exflg) break;
-    }
-
-   if (NGP_OK == r)
-     { 				/* we should scan keywords, and calculate HDU's */
-				/* structure ourselves .... */
-
-       ngph_node_type = NGP_NODE_INVALID;	/* init variables */
-       ngph_bitpix = 0;
-       ngph_extname = NULL;
-       for (i=0; i=1) && (j <= NGP_MAX_ARRAY_DIM))
-		  { ngph_size[j - 1] = ngph.tok[i].value.i;
-		  }
-            }
-        }
-
-       switch (ngph_node_type)
-        { case NGP_NODE_IMAGE:
-			if (NGP_XTENSION_FIRST == ((NGP_XTENSION_FIRST | NGP_XTENSION_SIMPLE) & simple_mode))
-			  { 		/* if caller signals that this is 1st HDU in file */
-					/* and it is IMAGE defined with XTENSION, then we */
-					/* need create dummy Primary HDU */			  
-			    fits_create_img(ff, 16, 0, NULL, &r);
-			  }
-					/* create image */
-			fits_create_img(ff, ngph_bitpix, ngph_dim, ngph_size, &r);
-
-					/* update keywords */
-			if (NGP_OK == r)  r = ngp_keyword_all_write(&ngph, ff, NGP_NON_SYSTEM_ONLY);
-			break;
-
-          case NGP_NODE_ATABLE:
-          case NGP_NODE_BTABLE:
-					/* create table, 0 rows and 0 columns for the moment */
-			fits_create_tbl(ff, ((NGP_NODE_ATABLE == ngph_node_type)
-					     ? ASCII_TBL : BINARY_TBL),
-					0, 0, NULL, NULL, NULL, NULL, &r);
-			if (NGP_OK != r) break;
-
-					/* add columns ... */
-			r = ngp_append_columns(ff, &ngph, 0);
-			if (NGP_OK != r) break;
-
-					/* add remaining keywords */
-			r = ngp_keyword_all_write(&ngph, ff, NGP_NON_SYSTEM_ONLY);
-			if (NGP_OK != r) break;
-
-					/* if requested add rows */
-			if (ngph_size[1] > 0) fits_insert_rows(ff, 0, ngph_size[1], &r);
-			break;
-
-	  default:	r = NGP_BAD_ARG;
-	  		break;
-	}
-
-     }
-
-   if ((NGP_OK == r) && (NULL != ngph_extname))
-     { r = ngp_get_extver(ngph_extname, &my_version);	/* write correct ext version number */
-       lv = my_version;		/* bugfix - 22-Jan-99, BO - nonalignment of OSF/Alpha */
-       fits_write_key(ff, TLONG, "EXTVER", &lv, "auto assigned by template parser", &r); 
-     }
-
-   if (NGP_OK == r)
-     { if (parent_hn > 0)
-         { fits_get_hdu_num(ff, &my_hn);
-           fits_movabs_hdu(ff, parent_hn, &tmp0, &r);	/* link us to parent */
-           fits_add_group_member(ff, NULL, my_hn, &r);
-           fits_movabs_hdu(ff, my_hn, &tmp0, &r);
-           if (NGP_OK != r) return(r);
-         }
-     }
-
-   if (NGP_OK != r)					/* in case of error - delete hdu */
-     { tmp0 = 0;
-       fits_delete_hdu(ff, NULL, &tmp0);
-     }
-
-   ngp_hdu_clear(&ngph);
-   return(r);
- }
-
-	/* read complete GROUP */
-
-int	ngp_read_group(fitsfile *ff, char *grpname, int parent_hn)
- { int		r, exitflg, l, my_hn, tmp0, incrementor_index;
-   char		grnm[NGP_MAX_STRING];			/* keyword holding group name */
-   char		incrementor_name[NGP_MAX_STRING];
-   NGP_HDU	ngph;
-
-   incrementor_name[0] = 0;			/* signal no keyword+'#' found yet */
-   incrementor_index = 6;			/* first 6 cols are used by group */
-
-   ngp_grplevel++;
-   if (NGP_OK != (r = ngp_hdu_init(&ngph))) return(r);
-
-   r = NGP_OK;
-   if (NGP_OK != (r = fits_create_group(ff, grpname, GT_ID_ALL_URI, &r))) return(r);
-   fits_get_hdu_num(ff, &my_hn);
-   if (parent_hn > 0)
-     { fits_movabs_hdu(ff, parent_hn, &tmp0, &r);	/* link us to parent */
-       fits_add_group_member(ff, NULL, my_hn, &r);
-       fits_movabs_hdu(ff, my_hn, &tmp0, &r);
-       if (NGP_OK != r) return(r);
-     }
-
-   for (exitflg = 0; 0 == exitflg;)
-    { if (NGP_OK != (r = ngp_read_line(0))) break;	/* EOF always means error here */
-      switch (ngp_keyidx)
-       {
-	 case NGP_TOKEN_SIMPLE:
-	 case NGP_TOKEN_EOF:
-			r = NGP_TOKEN_NOT_EXPECT;
-			break;
-
-         case NGP_TOKEN_END:
-         		ngp_grplevel--;
-			exitflg = 1;
-			break;
-
-         case NGP_TOKEN_GROUP:
-			if (NGP_TTYPE_STRING == ngp_linkey.type)
-			  { strncpy(grnm, ngp_linkey.value.s, NGP_MAX_STRING);
-			  }
-			else
-			  { sprintf(grnm, "DEFAULT_GROUP_%d", master_grp_idx++);
-			  }
-			grnm[NGP_MAX_STRING - 1] = 0;
-			r = ngp_read_group(ff, grnm, my_hn);
-			break;			/* we can have many subsequent GROUP defs */
-
-         case NGP_TOKEN_XTENSION:
-         		r = ngp_unread_line();
-         		if (NGP_OK != r) break;
-         		r = ngp_read_xtension(ff, my_hn, 0);
-			break;			/* we can have many subsequent HDU defs */
-
-         default:	l = strlen(ngp_linkey.name);
-			if ((l >= 2) && (l <= 6))
-			  { if ('#' == ngp_linkey.name[l - 1])
-			      { if (0 == incrementor_name[0])
-			          { memcpy(incrementor_name, ngp_linkey.name, l - 1);
-			            incrementor_name[l - 1] = 0;
-			          }
-			        if (((l - 1) == (int)strlen(incrementor_name)) && (0 == memcmp(incrementor_name, ngp_linkey.name, l - 1)))
-			          { incrementor_index++;
-			          }
-			        sprintf(ngp_linkey.name + l - 1, "%d", incrementor_index);
-			      }
-			  }
-         		r = ngp_hdu_insert_token(&ngph, &ngp_linkey); 
-			break;			/* here we can add keyword */
-       }
-      if (NGP_OK != r) break;
-    }
-
-   fits_movabs_hdu(ff, my_hn, &tmp0, &r);	/* back to our HDU */
-
-   if (NGP_OK == r)				/* create additional columns, if requested */
-     r = ngp_append_columns(ff, &ngph, 6);
-
-   if (NGP_OK == r)				/* and write keywords */
-     r = ngp_keyword_all_write(&ngph, ff, NGP_NON_SYSTEM_ONLY);
-
-   if (NGP_OK != r)			/* delete group in case of error */
-     { tmp0 = 0;
-       fits_remove_group(ff, OPT_RM_GPT, &tmp0);
-     }
-
-   ngp_hdu_clear(&ngph);		/* we are done with this HDU, so delete it */
-   return(r);
- }
-
-		/* top level API functions */
-
-/* read whole template. ff should point to the opened empty fits file. */
-
-int	fits_execute_template(fitsfile *ff, char *ngp_template, int *status)
- { int		r, exit_flg, first_extension, i, my_hn, tmp0, keys_exist, more_keys, used_ver;
-   char		grnm[NGP_MAX_STRING], used_name[NGP_MAX_STRING];
-   long		luv;
-
-   if (NULL == status) return(NGP_NUL_PTR);
-   if (NGP_OK != *status) return(*status);
-
-   if ((NULL == ff) || (NULL == ngp_template))
-     { *status = NGP_NUL_PTR;
-       return(*status);
-     }
-
-   ngp_inclevel = 0;				/* initialize things, not all should be zero */
-   ngp_grplevel = 0;
-   master_grp_idx = 1;
-   exit_flg = 0;
-   ngp_master_dir[0] = 0;			/* this should be before 1st call to ngp_include_file */
-   first_extension = 1;				/* we need to create PHDU */
-
-   if (NGP_OK != (r = ngp_delete_extver_tab()))
-     { *status = r;
-       return(r);
-     }
-
-   fits_get_hdu_num(ff, &my_hn);		/* our HDU position */
-   if (my_hn <= 1)				/* check whether we really need to create PHDU */
-     { fits_movabs_hdu(ff, 1, &tmp0, status);
-       fits_get_hdrspace(ff, &keys_exist, &more_keys, status);
-       fits_movabs_hdu(ff, my_hn, &tmp0, status);
-       if (NGP_OK != *status) return(*status);	/* error here means file is corrupted */
-       if (keys_exist > 0) first_extension = 0;	/* if keywords exist assume PHDU already exist */
-     }
-   else
-     { first_extension = 0;			/* PHDU (followed by 1+ extensions) exist */
-
-       for (i = 2; i<= my_hn; i++)
-        { *status = NGP_OK;
-          fits_movabs_hdu(ff, 1, &tmp0, status);
-          if (NGP_OK != *status) break;
-
-          fits_read_key(ff, TSTRING, "EXTNAME", used_name, NULL, status);
-          if (NGP_OK != *status)  continue;
-
-          fits_read_key(ff, TLONG, "EXTVER", &luv, NULL, status);
-          used_ver = luv;			/* bugfix - 22-Jan-99, BO - nonalignment of OSF/Alpha */
-          if (VALUE_UNDEFINED == *status)
-            { used_ver = 1;
-              *status = NGP_OK;
-            }
-
-          if (NGP_OK == *status) *status = ngp_set_extver(used_name, used_ver);
-        }
-
-       fits_movabs_hdu(ff, my_hn, &tmp0, status);
-     }
-   if (NGP_OK != *status) return(*status);
-                                                                          
-   if (NGP_OK != (*status = ngp_include_file(ngp_template))) return(*status);
-
-   for (i = strlen(ngp_template) - 1; i >= 0; i--) /* strlen is > 0, otherwise fopen failed */
-    { 
-#ifdef MSDOS
-      if ('\\' == ngp_template[i]) break;
-#else
-      if ('/' == ngp_template[i]) break;
-#endif
-    } 
-      
-   i++;
-   if (i > (NGP_MAX_FNAME - 1)) i = NGP_MAX_FNAME - 1;
-
-   if (i > 0)
-     { memcpy(ngp_master_dir, ngp_template, i);
-       ngp_master_dir[i] = 0;
-     }
-
-
-   for (;;)
-    { if (NGP_OK != (r = ngp_read_line(1))) break;	/* EOF always means error here */
-      switch (ngp_keyidx)
-       {
-         case NGP_TOKEN_SIMPLE:
-			if (0 == first_extension)	/* simple only allowed in first HDU */
-			  { r = NGP_TOKEN_NOT_EXPECT;
-			    break;
-			  }
-			if (NGP_OK != (r = ngp_unread_line())) break;
-			r = ngp_read_xtension(ff, 0, NGP_XTENSION_SIMPLE | NGP_XTENSION_FIRST);
-			first_extension = 0;
-			break;
-
-         case NGP_TOKEN_XTENSION:
-			if (NGP_OK != (r = ngp_unread_line())) break;
-			r = ngp_read_xtension(ff, 0, (first_extension ? NGP_XTENSION_FIRST : 0));
-			first_extension = 0;
-			break;
-
-         case NGP_TOKEN_GROUP:
-			if (NGP_TTYPE_STRING == ngp_linkey.type)
-			  { strncpy(grnm, ngp_linkey.value.s, NGP_MAX_STRING); }
-			else
-			  { sprintf(grnm, "DEFAULT_GROUP_%d", master_grp_idx++); }
-			grnm[NGP_MAX_STRING - 1] = 0;
-			r = ngp_read_group(ff, grnm, 0);
-			first_extension = 0;
-			break;
-
-	 case NGP_TOKEN_EOF:
-			exit_flg = 1;
-			break;
-
-         default:	r = NGP_TOKEN_NOT_EXPECT;
-			break;
-       }
-      if (exit_flg || (NGP_OK != r)) break;
-    }
-
-/* all top level HDUs up to faulty one are left intact in case of i/o error. It is up
-   to the caller to call fits_close_file or fits_delete_file when this function returns
-   error. */
-
-   ngp_free_line();		/* deallocate last line (if any) */
-   ngp_free_prevline();		/* deallocate cached line (if any) */
-   ngp_delete_extver_tab();	/* delete extver table (if present), error ignored */
-   
-   *status = r;
-   return(r);
- }
diff --git a/src/external/OpenGR/3rdparty/cfitsio/grparser.h b/src/external/OpenGR/3rdparty/cfitsio/grparser.h
deleted file mode 100644
index 2a924b6fb..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/grparser.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/*		T E M P L A T E   P A R S E R   H E A D E R   F I L E
-		=====================================================
-
-		by Jerzy.Borkowski@obs.unige.ch
-
-		Integral Science Data Center
-		ch. d'Ecogia 16
-		1290 Versoix
-		Switzerland
-
-14-Oct-98: initial release
-16-Oct-98: reference to fitsio.h removed, also removed strings after #endif
-		directives to make gcc -Wall not to complain
-20-Oct-98: added declarations NGP_XTENSION_SIMPLE and NGP_XTENSION_FIRST
-24-Oct-98: prototype of ngp_read_line() function updated.
-22-Jan-99: prototype for ngp_set_extver() function added.
-20-Jun-2002 Wm Pence, added support for the HIERARCH keyword convention
-            (changed NGP_MAX_NAME from (20) to FLEN_KEYWORD)
-*/
-
-#ifndef	GRPARSER_H_INCLUDED
-#define	GRPARSER_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-	/* error codes  - now defined in fitsio.h */
-
-	/* common constants definitions */
-
-#define	NGP_ALLOCCHUNK		(1000)
-#define	NGP_MAX_INCLUDE		(10)			/* include file nesting limit */
-#define	NGP_MAX_COMMENT		(80)			/* max size for comment */
-#define	NGP_MAX_NAME		FLEN_KEYWORD		/* max size for KEYWORD (FITS limits it to 8 chars) */
-                                                        /* except HIERARCH can have longer effective keyword names */
-#define	NGP_MAX_STRING		(80)			/* max size for various strings */
-#define	NGP_MAX_ARRAY_DIM	(999)			/* max. number of dimensions in array */
-#define NGP_MAX_FNAME           (1000)                  /* max size of combined path+fname */
-#define	NGP_MAX_ENVFILES	(10000)			/* max size of CFITSIO_INCLUDE_FILES env. variable */
-
-#define	NGP_TOKEN_UNKNOWN	(-1)			/* token type unknown */
-#define	NGP_TOKEN_INCLUDE	(0)			/* \INCLUDE token */
-#define	NGP_TOKEN_GROUP		(1)			/* \GROUP token */
-#define	NGP_TOKEN_END		(2)			/* \END token */
-#define	NGP_TOKEN_XTENSION	(3)			/* XTENSION token */
-#define	NGP_TOKEN_SIMPLE	(4)			/* SIMPLE token */
-#define	NGP_TOKEN_EOF		(5)			/* End Of File pseudo token */
-
-#define	NGP_TTYPE_UNKNOWN	(0)			/* undef (yet) token type - invalid to print/write to disk */
-#define	NGP_TTYPE_BOOL		(1)			/* boolean, it is 'T' or 'F' */
-#define	NGP_TTYPE_STRING	(2)			/* something withing "" or starting with letter */
-#define	NGP_TTYPE_INT		(3)			/* starting with digit and not with '.' */
-#define	NGP_TTYPE_REAL		(4)			/* digits + '.' */
-#define	NGP_TTYPE_COMPLEX	(5)			/* 2 reals, separated with ',' */
-#define	NGP_TTYPE_NULL		(6)			/* NULL token, format is : NAME = / comment */
-#define	NGP_TTYPE_RAW		(7)			/* HISTORY/COMMENT/8SPACES + comment string without / */
-
-#define	NGP_FOUND_EQUAL_SIGN	(1)			/* line contains '=' after keyword name */
-
-#define	NGP_FORMAT_OK		(0)			/* line format OK */
-#define	NGP_FORMAT_ERROR	(1)			/* line format error */
-
-#define	NGP_NODE_INVALID	(0)			/* default node type - invalid (to catch errors) */
-#define	NGP_NODE_IMAGE		(1)			/* IMAGE type */
-#define	NGP_NODE_ATABLE		(2)			/* ASCII table type */
-#define	NGP_NODE_BTABLE		(3)			/* BINARY table type */
-
-#define	NGP_NON_SYSTEM_ONLY	(0)			/* save all keywords except NAXIS,BITPIX,etc.. */
-#define	NGP_REALLY_ALL		(1)			/* save really all keywords */
-
-#define	NGP_XTENSION_SIMPLE	(1)			/* HDU defined with SIMPLE T */
-#define	NGP_XTENSION_FIRST	(2)			/* this is first extension in template */
-
-#define	NGP_LINE_REREAD		(1)			/* reread line */
-
-#define	NGP_BITPIX_INVALID	(-12345)		/* default BITPIX (to catch errors) */
-
-	/* common macro definitions */
-
-#ifdef	NGP_PARSER_DEBUG_MALLOC
-
-#define	ngp_alloc(x)		dal_malloc(x)
-#define	ngp_free(x)		dal_free(x)
-#define	ngp_realloc(x,y)	dal_realloc(x,y)
-
-#else
-
-#define	ngp_alloc(x)		malloc(x)
-#define	ngp_free(x)		free(x)
-#define	ngp_realloc(x,y)	realloc(x,y)
-
-#endif
-
-	/* type definitions */
-
-typedef struct NGP_RAW_LINE_STRUCT
-      {	char	*line;
-	char	*name;
-	char	*value;
-	int	type;
-	char	*comment;
-	int	format;
-	int	flags;
-      } NGP_RAW_LINE;
-
-
-typedef union NGP_TOKVAL_UNION
-      {	char	*s;		/* space allocated separately, be careful !!! */
-	char	b;
-	int	i;
-	double	d;
-	struct NGP_COMPLEX_STRUCT
-	 { double re;
-	   double im;
-	 } c;			/* complex value */
-      } NGP_TOKVAL;
-
-
-typedef struct NGP_TOKEN_STRUCT
-      { int		type;
-        char		name[NGP_MAX_NAME];
-        NGP_TOKVAL	value;
-        char		comment[NGP_MAX_COMMENT];
-      } NGP_TOKEN;
-
-
-typedef struct NGP_HDU_STRUCT
-      {	int		tokcnt;
-        NGP_TOKEN	*tok;
-      } NGP_HDU;
-
-
-typedef struct NGP_TKDEF_STRUCT
-      {	char	*name;
-	int	code;
-      } NGP_TKDEF;
-
-
-typedef struct NGP_EXTVER_TAB_STRUCT
-      {	char	*extname;
-	int	version;
-      } NGP_EXTVER_TAB;
-
-
-	/* globally visible variables declarations */
-
-extern	NGP_RAW_LINE	ngp_curline;
-extern	NGP_RAW_LINE	ngp_prevline;
-
-extern	int		ngp_extver_tab_size;
-extern	NGP_EXTVER_TAB	*ngp_extver_tab;
-
-
-	/* globally visible functions declarations */
-
-int	ngp_get_extver(char *extname, int *version);
-int	ngp_set_extver(char *extname, int version);
-int	ngp_delete_extver_tab(void);
-int	ngp_line_from_file(FILE *fp, char **p);
-int	ngp_free_line(void);
-int	ngp_free_prevline(void);
-int	ngp_read_line_buffered(FILE *fp);
-int	ngp_unread_line(void);
-int	ngp_extract_tokens(NGP_RAW_LINE *cl);
-int	ngp_include_file(char *fname);
-int	ngp_read_line(int ignore_blank_lines);
-int	ngp_keyword_is_write(NGP_TOKEN *ngp_tok);
-int     ngp_keyword_all_write(NGP_HDU *ngph, fitsfile *ffp, int mode);
-int	ngp_hdu_init(NGP_HDU *ngph);
-int	ngp_hdu_clear(NGP_HDU *ngph);
-int	ngp_hdu_insert_token(NGP_HDU *ngph, NGP_TOKEN *newtok);
-int	ngp_append_columns(fitsfile *ff, NGP_HDU *ngph, int aftercol);
-int	ngp_read_xtension(fitsfile *ff, int parent_hn, int simple_mode);
-int	ngp_read_group(fitsfile *ff, char *grpname, int parent_hn);
-
-		/* top level API function - now defined in fitsio.h */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/external/OpenGR/3rdparty/cfitsio/histo.c b/src/external/OpenGR/3rdparty/cfitsio/histo.c
deleted file mode 100644
index 77cbbc047..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/histo.c
+++ /dev/null
@@ -1,2364 +0,0 @@
-/*   Globally defined histogram parameters */
-#include 
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-typedef struct {  /*  Structure holding all the histogramming information   */
-   union {        /*  the iterator work functions (ffwritehist, ffcalchist) */
-      char   *b;  /*  need to do their job... passed via *userPointer.      */
-      short  *i;
-      int    *j;
-      float  *r;
-      double *d;
-   } hist;
-
-   fitsfile *tblptr;
-
-   int   haxis, hcolnum[4], himagetype;
-   long  haxis1, haxis2, haxis3, haxis4;
-   float amin1, amin2, amin3, amin4;
-   float maxbin1, maxbin2, maxbin3, maxbin4;
-   float binsize1, binsize2, binsize3, binsize4;
-   int   wtrecip, wtcolnum;
-   float weight;
-   char  *rowselector;
-
-} histType;
-
-/*--------------------------------------------------------------------------*/
-int ffbins(char *binspec,   /* I - binning specification */
-                   int *imagetype,      /* O - image type, TINT or TSHORT */
-                   int *histaxis,       /* O - no. of axes in the histogram */
-                   char colname[4][FLEN_VALUE],  /* column name for axis */
-                   double *minin,        /* minimum value for each axis */
-                   double *maxin,        /* maximum value for each axis */
-                   double *binsizein,    /* size of bins on each axis */
-                   char minname[4][FLEN_VALUE],  /* keyword name for min */
-                   char maxname[4][FLEN_VALUE],  /* keyword name for max */
-                   char binname[4][FLEN_VALUE],  /* keyword name for binsize */
-                   double *wt,          /* weighting factor          */
-                   char *wtname,        /* keyword or column name for weight */
-                   int *recip,          /* the reciprocal of the weight? */
-                   int *status)
-{
-/*
-   Parse the input binning specification string, returning the binning
-   parameters.  Supports up to 4 dimensions.  The binspec string has
-   one of these forms:
-
-   bin binsize                  - 2D histogram with binsize on each axis
-   bin xcol                     - 1D histogram on column xcol
-   bin (xcol, ycol) = binsize   - 2D histogram with binsize on each axis
-   bin x=min:max:size, y=min:max:size, z..., t... 
-   bin x=:max, y=::size
-   bin x=size, y=min::size
-
-   most other reasonable combinations are supported.        
-*/
-    int ii, slen, defaulttype;
-    char *ptr, tmpname[30], *file_expr = NULL;
-    double  dummy;
-
-    if (*status > 0)
-         return(*status);
-
-    /* set the default values */
-    *histaxis = 2;
-    *imagetype = TINT;
-    defaulttype = 1;
-    *wt = 1.;
-    *recip = 0;
-    *wtname = '\0';
-
-    /* set default values */
-    for (ii = 0; ii < 4; ii++)
-    {
-        *colname[ii] = '\0';
-        *minname[ii] = '\0';
-        *maxname[ii] = '\0';
-        *binname[ii] = '\0';
-        minin[ii] = DOUBLENULLVALUE;  /* undefined values */
-        maxin[ii] = DOUBLENULLVALUE;
-        binsizein[ii] = DOUBLENULLVALUE;
-    }
-
-    ptr = binspec + 3;  /* skip over 'bin' */
-
-    if (*ptr == 'i' )  /* bini */
-    {
-        *imagetype = TSHORT;
-        defaulttype = 0;
-        ptr++;
-    }
-    else if (*ptr == 'j' )  /* binj; same as default */
-    {
-        defaulttype = 0;
-        ptr ++;
-    }
-    else if (*ptr == 'r' )  /* binr */
-    {
-        *imagetype = TFLOAT;
-        defaulttype = 0;
-        ptr ++;
-    }
-    else if (*ptr == 'd' )  /* bind */
-    {
-        *imagetype = TDOUBLE;
-        defaulttype = 0;
-        ptr ++;
-    }
-    else if (*ptr == 'b' )  /* binb */
-    {
-        *imagetype = TBYTE;
-        defaulttype = 0;
-        ptr ++;
-    }
-
-    if (*ptr == '\0')  /* use all defaults for other parameters */
-        return(*status);
-    else if (*ptr != ' ')  /* must be at least one blank */
-    {
-        ffpmsg("binning specification syntax error:");
-        ffpmsg(binspec);
-        return(*status = URL_PARSE_ERROR);
-    }
-
-    while (*ptr == ' ')  /* skip over blanks */
-           ptr++;
-
-    if (*ptr == '\0')   /* no other parameters; use defaults */
-        return(*status);
-
-    /* Check if need to import expression from a file */
-
-    if( *ptr=='@' ) {
-       if( ffimport_file( ptr+1, &file_expr, status ) ) return(*status);
-       ptr = file_expr;
-       while (*ptr == ' ')
-               ptr++;       /* skip leading white space... again */
-    }
-
-    if (*ptr == '(' )
-    {
-        /* this must be the opening parenthesis around a list of column */
-        /* names, optionally followed by a '=' and the binning spec. */
-
-        for (ii = 0; ii < 4; ii++)
-        {
-            ptr++;               /* skip over the '(', ',', or ' ') */
-            while (*ptr == ' ')  /* skip over blanks */
-                ptr++;
-
-            slen = strcspn(ptr, " ,)");
-            strncat(colname[ii], ptr, slen); /* copy 1st column name */
-
-            ptr += slen;
-            while (*ptr == ' ')  /* skip over blanks */
-                ptr++;
-
-            if (*ptr == ')' )   /* end of the list of names */
-            {
-                *histaxis = ii + 1;
-                break;
-            }
-        }
-
-        if (ii == 4)   /* too many names in the list , or missing ')'  */
-        {
-            ffpmsg(
- "binning specification has too many column names or is missing closing ')':");
-            ffpmsg(binspec);
-	    if( file_expr ) free( file_expr );
-            return(*status = URL_PARSE_ERROR);
-        }
-
-        ptr++;  /* skip over the closing parenthesis */
-        while (*ptr == ' ')  /* skip over blanks */
-            ptr++;
-
-        if (*ptr == '\0') {
-	    if( file_expr ) free( file_expr );
-            return(*status);  /* parsed the entire string */
-	}
-
-        else if (*ptr != '=')  /* must be an equals sign now*/
-        {
-            ffpmsg("illegal binning specification in URL:");
-            ffpmsg(" an equals sign '=' must follow the column names");
-            ffpmsg(binspec);
-	    if( file_expr ) free( file_expr );
-            return(*status = URL_PARSE_ERROR);
-        }
-
-        ptr++;  /* skip over the equals sign */
-        while (*ptr == ' ')  /* skip over blanks */
-            ptr++;
-
-        /* get the single range specification for all the columns */
-        ffbinr(&ptr, tmpname, minin,
-                                     maxin, binsizein, minname[0],
-                                     maxname[0], binname[0], status);
-        if (*status > 0)
-        {
-            ffpmsg("illegal binning specification in URL:");
-            ffpmsg(binspec);
-	    if( file_expr ) free( file_expr );
-            return(*status);
-        }
-
-        for (ii = 1; ii < *histaxis; ii++)
-        {
-            minin[ii] = minin[0];
-            maxin[ii] = maxin[0];
-            binsizein[ii] = binsizein[0];
-            strcpy(minname[ii], minname[0]);
-            strcpy(maxname[ii], maxname[0]);
-            strcpy(binname[ii], binname[0]);
-        }
-
-        while (*ptr == ' ')  /* skip over blanks */
-            ptr++;
-
-        if (*ptr == ';')
-            goto getweight;   /* a weighting factor is specified */
-
-        if (*ptr != '\0')  /* must have reached end of string */
-        {
-            ffpmsg("illegal syntax after binning range specification in URL:");
-            ffpmsg(binspec);
-	    if( file_expr ) free( file_expr );
-            return(*status = URL_PARSE_ERROR);
-        }
-
-        return(*status);
-    }             /* end of case with list of column names in ( )  */
-
-    /* if we've reached this point, then the binning specification */
-    /* must be of the form: XCOL = min:max:binsize, YCOL = ...     */
-    /* where the column name followed by '=' are optional.         */
-    /* If the column name is not specified, then use the default name */
-
-    for (ii = 0; ii < 4; ii++) /* allow up to 4 histogram dimensions */
-    {
-        ffbinr(&ptr, colname[ii], &minin[ii],
-                                     &maxin[ii], &binsizein[ii], minname[ii],
-                                     maxname[ii], binname[ii], status);
-
-        if (*status > 0)
-        {
-            ffpmsg("illegal syntax in binning range specification in URL:");
-            ffpmsg(binspec);
-	    if( file_expr ) free( file_expr );
-            return(*status);
-        }
-
-        if (*ptr == '\0' || *ptr == ';')
-            break;        /* reached the end of the string */
-
-        if (*ptr == ' ')
-        {
-            while (*ptr == ' ')  /* skip over blanks */
-                ptr++;
-
-            if (*ptr == '\0' || *ptr == ';')
-                break;        /* reached the end of the string */
-
-            if (*ptr == ',')
-                ptr++;  /* comma separates the next column specification */
-        }
-        else if (*ptr == ',')
-        {          
-            ptr++;  /* comma separates the next column specification */
-        }
-        else
-        {
-            ffpmsg("illegal characters following binning specification in URL:");
-            ffpmsg(binspec);
-	    if( file_expr ) free( file_expr );
-            return(*status = URL_PARSE_ERROR);
-        }
-    }
-
-    if (ii == 4)
-    {
-        /* there are yet more characters in the string */
-        ffpmsg("illegal binning specification in URL:");
-        ffpmsg("apparently greater than 4 histogram dimensions");
-        ffpmsg(binspec);
-        return(*status = URL_PARSE_ERROR);
-    }
-    else
-        *histaxis = ii + 1;
-
-    /* special case: if a single number was entered it should be      */
-    /* interpreted as the binning factor for the default X and Y axes */
-
-    if (*histaxis == 1 && *colname[0] == '\0' && 
-         minin[0] == DOUBLENULLVALUE && maxin[0] == DOUBLENULLVALUE)
-    {
-        *histaxis = 2;
-        binsizein[1] = binsizein[0];
-    }
-
-getweight:
-    if (*ptr == ';')  /* looks like a weighting factor is given */
-    {
-        ptr++;
-       
-        while (*ptr == ' ')  /* skip over blanks */
-            ptr++;
-
-        recip = 0;
-        if (*ptr == '/')
-        {
-            *recip = 1;  /* the reciprocal of the weight is entered */
-            ptr++;
-
-            while (*ptr == ' ')  /* skip over blanks */
-                ptr++;
-        }
-
-        /* parse the weight as though it were a binrange. */
-        /* either a column name or a numerical value will be returned */
-
-        ffbinr(&ptr, wtname, &dummy, &dummy, wt, tmpname,
-                                     tmpname, tmpname, status);
-
-        if (*status > 0)
-        {
-            ffpmsg("illegal binning weight specification in URL:");
-            ffpmsg(binspec);
-	    if( file_expr ) free( file_expr );
-            return(*status);
-        }
-
-        /* creat a float datatype histogram by default, if weight */
-        /* factor is not = 1.0  */
-
-        if ( (defaulttype && *wt != 1.0) || (defaulttype && *wtname) )
-            *imagetype = TFLOAT;
-    }
-
-    while (*ptr == ' ')  /* skip over blanks */
-         ptr++;
-
-    if (*ptr != '\0')  /* should have reached the end of string */
-    {
-        ffpmsg("illegal syntax after binning weight specification in URL:");
-        ffpmsg(binspec);
-        *status = URL_PARSE_ERROR;
-    }
-
-    if( file_expr ) free( file_expr );
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffbinr(char **ptr, 
-                   char *colname, 
-                   double *minin,
-                   double *maxin, 
-                   double *binsizein,
-                   char *minname,
-                   char *maxname,
-                   char *binname,
-                   int *status)
-/*
-   Parse the input binning range specification string, returning 
-   the column name, histogram min and max values, and bin size.
-*/
-{
-    int slen, isanumber;
-    char token[FLEN_VALUE];
-
-    if (*status > 0)
-        return(*status);
-
-    slen = fits_get_token(ptr, " ,=:;", token, &isanumber); /* get 1st token */
-
-    if (slen == 0 && (**ptr == '\0' || **ptr == ',' || **ptr == ';') )
-        return(*status);   /* a null range string */
-
-    if (!isanumber && **ptr != ':')
-    {
-        /* this looks like the column name */
-
-        if (token[0] == '#' && isdigit((int) token[1]) )
-        {
-            /* omit the leading '#' in the column number */
-            strcpy(colname, token+1);
-        }
-        else
-            strcpy(colname, token);
-
-        while (**ptr == ' ')  /* skip over blanks */
-             (*ptr)++;
-
-        if (**ptr != '=')
-            return(*status);  /* reached the end */
-
-        (*ptr)++;   /* skip over the = sign */
-
-        while (**ptr == ' ')  /* skip over blanks */
-             (*ptr)++;
-
-        slen = fits_get_token(ptr, " ,:;", token, &isanumber); /* get token */
-    }
-
-    if (**ptr != ':')
-    {
-        /* this is the first token, and since it is not followed by */
-        /* a ':' this must be the binsize token */
-        if (!isanumber)
-            strcpy(binname, token);
-        else
-            *binsizein =  strtod(token, NULL);
-
-        return(*status);  /* reached the end */
-    }
-    else
-    {
-        /* the token contains the min value */
-        if (slen)
-        {
-            if (!isanumber)
-                strcpy(minname, token);
-            else
-                *minin = strtod(token, NULL);
-        }
-    }
-
-    (*ptr)++;  /* skip the colon between the min and max values */
-    slen = fits_get_token(ptr, " ,:;", token, &isanumber); /* get token */
-
-    /* the token contains the max value */
-    if (slen)
-    {
-        if (!isanumber)
-            strcpy(maxname, token);
-        else
-            *maxin = strtod(token, NULL);
-    }
-
-    if (**ptr != ':')
-        return(*status);  /* reached the end; no binsize token */
-
-    (*ptr)++;  /* skip the colon between the max and binsize values */
-    slen = fits_get_token(ptr, " ,:;", token, &isanumber); /* get token */
-
-    /* the token contains the binsize value */
-    if (slen)
-    {
-        if (!isanumber)
-            strcpy(binname, token);
-        else
-            *binsizein = strtod(token, NULL);
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffhist2(fitsfile **fptr,  /* IO - pointer to table with X and Y cols;    */
-                             /*     on output, points to histogram image    */
-           char *outfile,    /* I - name for the output histogram file      */
-           int imagetype,    /* I - datatype for image: TINT, TSHORT, etc   */
-           int naxis,        /* I - number of axes in the histogram image   */
-           char colname[4][FLEN_VALUE],   /* I - column names               */
-           double *minin,     /* I - minimum histogram value, for each axis */
-           double *maxin,     /* I - maximum histogram value, for each axis */
-           double *binsizein, /* I - bin size along each axis               */
-           char minname[4][FLEN_VALUE], /* I - optional keywords for min    */
-           char maxname[4][FLEN_VALUE], /* I - optional keywords for max    */
-           char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */
-           double weightin,        /* I - binning weighting factor          */
-           char wtcol[FLEN_VALUE], /* I - optional keyword or col for weight*/
-           int recip,              /* I - use reciprocal of the weight?     */
-           char *selectrow,        /* I - optional array (length = no. of   */
-                             /* rows in the table).  If the element is true */
-                             /* then the corresponding row of the table will*/
-                             /* be included in the histogram, otherwise the */
-                             /* row will be skipped.  Ingnored if *selectrow*/
-                             /* is equal to NULL.                           */
-           int *status)
-{
-    fitsfile *histptr;
-    int   bitpix, colnum[4], wtcolnum;
-    long haxes[4];
-    float amin[4], amax[4], binsize[4],  weight;
-
-    if (*status > 0)
-        return(*status);
-
-    if (naxis > 4)
-    {
-        ffpmsg("histogram has more than 4 dimensions");
-        return(*status = BAD_DIMEN);
-    }
-
-    /* reset position to the correct HDU if necessary */
-    if ((*fptr)->HDUposition != ((*fptr)->Fptr)->curhdu)
-        ffmahd(*fptr, ((*fptr)->HDUposition) + 1, NULL, status);
-
-    if (imagetype == TBYTE)
-        bitpix = BYTE_IMG;
-    else if (imagetype == TSHORT)
-        bitpix = SHORT_IMG;
-    else if (imagetype == TINT)
-        bitpix = LONG_IMG;
-    else if (imagetype == TFLOAT)
-        bitpix = FLOAT_IMG;
-    else if (imagetype == TDOUBLE)
-        bitpix = DOUBLE_IMG;
-    else
-        return(*status = BAD_DATATYPE);
-
-    
-    /*    Calculate the binning parameters:    */
-    /*   columm numbers, axes length, min values,  max values, and binsizes.  */
-
-    if (fits_calc_binning(
-      *fptr, naxis, colname, minin, maxin, binsizein, minname, maxname, binname,
-      colnum,  haxes, amin, amax, binsize, status) > 0)
-    {
-        ffpmsg("failed to determine binning parameters");
-        return(*status);
-    }
- 
-    /* get the histogramming weighting factor, if any */
-    if (*wtcol)
-    {
-        /* first, look for a keyword with the weight value */
-        if (ffgky(*fptr, TFLOAT, wtcol, &weight, NULL, status) )
-        {
-            /* not a keyword, so look for column with this name */
-            *status = 0;
-
-            /* get the column number in the table */
-            if (ffgcno(*fptr, CASEINSEN, wtcol, &wtcolnum, status) > 0)
-            {
-               ffpmsg(
-               "keyword or column for histogram weights doesn't exist: ");
-               ffpmsg(wtcol);
-               return(*status);
-            }
-
-            weight = FLOATNULLVALUE;
-        }
-    }
-    else
-        weight = (float) weightin;
-
-    if (weight <= 0. && weight != FLOATNULLVALUE)
-    {
-        ffpmsg("Illegal histogramming weighting factor <= 0.");
-        return(*status = URL_PARSE_ERROR);
-    }
-
-    if (recip && weight != FLOATNULLVALUE)
-       /* take reciprocal of weight */
-       weight = (float) (1.0 / weight);
-
-    /* size of histogram is now known, so create temp output file */
-    if (fits_create_file(&histptr, outfile, status) > 0)
-    {
-        ffpmsg("failed to create temp output file for histogram");
-        return(*status);
-    }
-
-    /* create output FITS image HDU */
-    if (ffcrim(histptr, bitpix, naxis, haxes, status) > 0)
-    {
-        ffpmsg("failed to create output histogram FITS image");
-        return(*status);
-    }
-
-    /* copy header keywords, converting pixel list WCS keywords to image WCS form */
-    if (fits_copy_pixlist2image(*fptr, histptr, 9, naxis, colnum, status) > 0)
-    {
-        ffpmsg("failed to copy pixel list keywords to new histogram header");
-        return(*status);
-    }
-
-    /* if the table columns have no WCS keywords, then write default keywords */
-    fits_write_keys_histo(*fptr, histptr, naxis, colnum, status);
-    
-    /* update the WCS keywords for the ref. pixel location, and pixel size */
-    fits_rebin_wcs(histptr, naxis, amin, binsize,  status);      
-    
-    /* now compute the output image by binning the column values */
-    if (fits_make_hist(*fptr, histptr, bitpix, naxis, haxes, colnum, amin, amax,
-        binsize, weight, wtcolnum, recip, selectrow, status) > 0)
-    {
-        ffpmsg("failed to calculate new histogram values");
-        return(*status);
-    }
-              
-    /* finally, close the original file and return ptr to the new image */
-    ffclos(*fptr, status);
-    *fptr = histptr;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-
-/* ffhist3: same as ffhist2, but does not close the original file */
-/*  and/or replace the original file pointer */
-fitsfile *ffhist3(fitsfile *fptr, /* I - ptr to table with X and Y cols*/
-           char *outfile,    /* I - name for the output histogram file      */
-           int imagetype,    /* I - datatype for image: TINT, TSHORT, etc   */
-           int naxis,        /* I - number of axes in the histogram image   */
-           char colname[4][FLEN_VALUE],   /* I - column names               */
-           double *minin,     /* I - minimum histogram value, for each axis */
-           double *maxin,     /* I - maximum histogram value, for each axis */
-           double *binsizein, /* I - bin size along each axis               */
-           char minname[4][FLEN_VALUE], /* I - optional keywords for min    */
-           char maxname[4][FLEN_VALUE], /* I - optional keywords for max    */
-           char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */
-           double weightin,        /* I - binning weighting factor          */
-           char wtcol[FLEN_VALUE], /* I - optional keyword or col for weight*/
-           int recip,              /* I - use reciprocal of the weight?     */
-           char *selectrow,        /* I - optional array (length = no. of   */
-                             /* rows in the table).  If the element is true */
-                             /* then the corresponding row of the table will*/
-                             /* be included in the histogram, otherwise the */
-                             /* row will be skipped.  Ingnored if *selectrow*/
-                             /* is equal to NULL.                           */
-           int *status)
-{
-    fitsfile *histptr;
-    int   bitpix, colnum[4], wtcolnum;
-    long haxes[4];
-    float amin[4], amax[4], binsize[4],  weight;
-
-    if (*status > 0)
-        return(NULL);
-
-    if (naxis > 4)
-    {
-        ffpmsg("histogram has more than 4 dimensions");
-	*status = BAD_DIMEN;
-        return(NULL);
-    }
-
-    /* reset position to the correct HDU if necessary */
-    if ((fptr)->HDUposition != ((fptr)->Fptr)->curhdu)
-        ffmahd(fptr, ((fptr)->HDUposition) + 1, NULL, status);
-
-    if (imagetype == TBYTE)
-        bitpix = BYTE_IMG;
-    else if (imagetype == TSHORT)
-        bitpix = SHORT_IMG;
-    else if (imagetype == TINT)
-        bitpix = LONG_IMG;
-    else if (imagetype == TFLOAT)
-        bitpix = FLOAT_IMG;
-    else if (imagetype == TDOUBLE)
-        bitpix = DOUBLE_IMG;
-    else{
-        *status = BAD_DATATYPE;
-        return(NULL);
-    }
-    
-    /*    Calculate the binning parameters:    */
-    /*   columm numbers, axes length, min values,  max values, and binsizes.  */
-
-    if (fits_calc_binning(
-      fptr, naxis, colname, minin, maxin, binsizein, minname, maxname, binname,
-      colnum, haxes, amin, amax, binsize, status) > 0)
-    {
-       ffpmsg("failed to determine binning parameters");
-        return(NULL);
-    }
- 
-    /* get the histogramming weighting factor, if any */
-    if (*wtcol)
-    {
-        /* first, look for a keyword with the weight value */
-        if (fits_read_key(fptr, TFLOAT, wtcol, &weight, NULL, status) )
-        {
-            /* not a keyword, so look for column with this name */
-            *status = 0;
-
-            /* get the column number in the table */
-            if (ffgcno(fptr, CASEINSEN, wtcol, &wtcolnum, status) > 0)
-            {
-               ffpmsg(
-               "keyword or column for histogram weights doesn't exist: ");
-               ffpmsg(wtcol);
-               return(NULL);
-            }
-
-            weight = FLOATNULLVALUE;
-        }
-    }
-    else
-        weight = (float) weightin;
-
-    if (weight <= 0. && weight != FLOATNULLVALUE)
-    {
-        ffpmsg("Illegal histogramming weighting factor <= 0.");
-	*status = URL_PARSE_ERROR;
-        return(NULL);
-    }
-
-    if (recip && weight != FLOATNULLVALUE)
-       /* take reciprocal of weight */
-       weight = (float) (1.0 / weight);
-
-    /* size of histogram is now known, so create temp output file */
-    if (fits_create_file(&histptr, outfile, status) > 0)
-    {
-        ffpmsg("failed to create temp output file for histogram");
-        return(NULL);
-    }
-
-    /* create output FITS image HDU */
-    if (ffcrim(histptr, bitpix, naxis, haxes, status) > 0)
-    {
-        ffpmsg("failed to create output histogram FITS image");
-        return(NULL);
-    }
-
-    /* copy header keywords, converting pixel list WCS keywords to image WCS */
-    if (fits_copy_pixlist2image(fptr, histptr, 9, naxis, colnum, status) > 0)
-    {
-        ffpmsg("failed to copy pixel list keywords to new histogram header");
-        return(NULL);
-    }
-
-    /* if the table columns have no WCS keywords, then write default keywords */
-    fits_write_keys_histo(fptr, histptr, naxis, colnum, status);
-    
-    /* update the WCS keywords for the ref. pixel location, and pixel size */
-    fits_rebin_wcs(histptr, naxis, amin, binsize,  status);      
-    
-    /* now compute the output image by binning the column values */
-    if (fits_make_hist(fptr, histptr, bitpix, naxis, haxes, colnum, amin, amax,
-        binsize, weight, wtcolnum, recip, selectrow, status) > 0)
-    {
-        ffpmsg("failed to calculate new histogram values");
-        return(NULL);
-    }
-              
-    return(histptr);
-}
-/*--------------------------------------------------------------------------*/
-int ffhist(fitsfile **fptr,  /* IO - pointer to table with X and Y cols;    */
-                             /*     on output, points to histogram image    */
-           char *outfile,    /* I - name for the output histogram file      */
-           int imagetype,    /* I - datatype for image: TINT, TSHORT, etc   */
-           int naxis,        /* I - number of axes in the histogram image   */
-           char colname[4][FLEN_VALUE],   /* I - column names               */
-           double *minin,     /* I - minimum histogram value, for each axis */
-           double *maxin,     /* I - maximum histogram value, for each axis */
-           double *binsizein, /* I - bin size along each axis               */
-           char minname[4][FLEN_VALUE], /* I - optional keywords for min    */
-           char maxname[4][FLEN_VALUE], /* I - optional keywords for max    */
-           char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */
-           double weightin,        /* I - binning weighting factor          */
-           char wtcol[FLEN_VALUE], /* I - optional keyword or col for weight*/
-           int recip,              /* I - use reciprocal of the weight?     */
-           char *selectrow,        /* I - optional array (length = no. of   */
-                             /* rows in the table).  If the element is true */
-                             /* then the corresponding row of the table will*/
-                             /* be included in the histogram, otherwise the */
-                             /* row will be skipped.  Ingnored if *selectrow*/
-                             /* is equal to NULL.                           */
-           int *status)
-{
-    int ii, datatype, repeat, imin, imax, ibin, bitpix, tstatus, use_datamax = 0;
-    long haxes[4];
-    fitsfile *histptr;
-    char errmsg[FLEN_ERRMSG], keyname[FLEN_KEYWORD], card[FLEN_CARD];
-    tcolumn *colptr;
-    iteratorCol imagepars[1];
-    int n_cols = 1, nkeys;
-    long  offset = 0;
-    long n_per_loop = -1;  /* force whole array to be passed at one time */
-    histType histData;    /* Structure holding histogram info for iterator */
-    
-    float amin[4], amax[4], binsize[4], maxbin[4];
-    float datamin = FLOATNULLVALUE, datamax = FLOATNULLVALUE;
-    char svalue[FLEN_VALUE];
-    double dvalue;
-    char cpref[4][FLEN_VALUE];
-    char *cptr;
-
-    if (*status > 0)
-        return(*status);
-
-    if (naxis > 4)
-    {
-        ffpmsg("histogram has more than 4 dimensions");
-        return(*status = BAD_DIMEN);
-    }
-
-    /* reset position to the correct HDU if necessary */
-    if ((*fptr)->HDUposition != ((*fptr)->Fptr)->curhdu)
-        ffmahd(*fptr, ((*fptr)->HDUposition) + 1, NULL, status);
-
-    histData.tblptr     = *fptr;
-    histData.himagetype = imagetype;
-    histData.haxis      = naxis;
-    histData.rowselector = selectrow;
-
-    if (imagetype == TBYTE)
-        bitpix = BYTE_IMG;
-    else if (imagetype == TSHORT)
-        bitpix = SHORT_IMG;
-    else if (imagetype == TINT)
-        bitpix = LONG_IMG;
-    else if (imagetype == TFLOAT)
-        bitpix = FLOAT_IMG;
-    else if (imagetype == TDOUBLE)
-        bitpix = DOUBLE_IMG;
-    else
-        return(*status = BAD_DATATYPE);
-
-    /* The CPREF keyword, if it exists, gives the preferred columns. */
-    /* Otherwise, assume "X", "Y", "Z", and "T"  */
-
-    tstatus = 0;
-    ffgky(*fptr, TSTRING, "CPREF", cpref[0], NULL, &tstatus);
-
-    if (!tstatus)
-    {
-        /* Preferred column names are given;  separate them */
-        cptr = cpref[0];
-
-        /* the first preferred axis... */
-        while (*cptr != ',' && *cptr != '\0')
-           cptr++;
-
-        if (*cptr != '\0')
-        {
-           *cptr = '\0';
-           cptr++;
-           while (*cptr == ' ')
-               cptr++;
-
-           strcpy(cpref[1], cptr);
-           cptr = cpref[1];
-
-          /* the second preferred axis... */
-          while (*cptr != ',' && *cptr != '\0')
-             cptr++;
-
-          if (*cptr != '\0')
-          {
-             *cptr = '\0';
-             cptr++;
-             while (*cptr == ' ')
-                 cptr++;
-
-             strcpy(cpref[2], cptr);
-             cptr = cpref[2];
-
-            /* the third preferred axis... */
-            while (*cptr != ',' && *cptr != '\0')
-               cptr++;
-
-            if (*cptr != '\0')
-            {
-               *cptr = '\0';
-               cptr++;
-               while (*cptr == ' ')
-                   cptr++;
-
-               strcpy(cpref[3], cptr);
-
-            }
-          }
-        }
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-
-      /* get the min, max, and binsize values from keywords, if specified */
-
-      if (*minname[ii])
-      {
-         if (ffgky(*fptr, TDOUBLE, minname[ii], &minin[ii], NULL, status) )
-         {
-             ffpmsg("error reading histogramming minimum keyword");
-             ffpmsg(minname[ii]);
-             return(*status);
-         }
-      }
-
-      if (*maxname[ii])
-      {
-         if (ffgky(*fptr, TDOUBLE, maxname[ii], &maxin[ii], NULL, status) )
-         {
-             ffpmsg("error reading histogramming maximum keyword");
-             ffpmsg(maxname[ii]);
-             return(*status);
-         }
-      }
-
-      if (*binname[ii])
-      {
-         if (ffgky(*fptr, TDOUBLE, binname[ii], &binsizein[ii], NULL, status) )
-         {
-             ffpmsg("error reading histogramming binsize keyword");
-             ffpmsg(binname[ii]);
-             return(*status);
-         }
-      }
-
-      if (binsizein[ii] == 0.)
-      {
-        ffpmsg("error: histogram binsize = 0");
-        return(*status = ZERO_SCALE);
-      }
-
-      if (*colname[ii] == '\0')
-      {
-         strcpy(colname[ii], cpref[ii]); /* try using the preferred column */
-         if (*colname[ii] == '\0')
-         {
-           if (ii == 0)
-              strcpy(colname[ii], "X");
-           else if (ii == 1)
-              strcpy(colname[ii], "Y");
-           else if (ii == 2)
-              strcpy(colname[ii], "Z");
-           else if (ii == 3)
-              strcpy(colname[ii], "T");
-         }
-      }
-
-      /* get the column number in the table */
-      if (ffgcno(*fptr, CASEINSEN, colname[ii], histData.hcolnum+ii, status)
-              > 0)
-      {
-        strcpy(errmsg, "column for histogram axis doesn't exist: ");
-        strcat(errmsg, colname[ii]);
-        ffpmsg(errmsg);
-        return(*status);
-      }
-
-      colptr = ((*fptr)->Fptr)->tableptr;
-      colptr += (histData.hcolnum[ii] - 1);
-
-      repeat = (int) colptr->trepeat;  /* vector repeat factor of the column */
-      if (repeat > 1)
-      {
-        strcpy(errmsg, "Can't bin a vector column: ");
-        strcat(errmsg, colname[ii]);
-        ffpmsg(errmsg);
-        return(*status = BAD_DATATYPE);
-      }
-
-      /* get the datatype of the column */
-      fits_get_coltype(*fptr, histData.hcolnum[ii], &datatype,
-         NULL, NULL, status);
-
-      if (datatype < 0 || datatype == TSTRING)
-      {
-        strcpy(errmsg, "Inappropriate datatype; can't bin this column: ");
-        strcat(errmsg, colname[ii]);
-        ffpmsg(errmsg);
-        return(*status = BAD_DATATYPE);
-      }
-
-      /* use TLMINn and TLMAXn keyword values if min and max were not given */
-      /* else use actual data min and max if TLMINn and TLMAXn don't exist */
- 
-      if (minin[ii] == DOUBLENULLVALUE)
-      {
-        ffkeyn("TLMIN", histData.hcolnum[ii], keyname, status);
-        if (ffgky(*fptr, TFLOAT, keyname, amin+ii, NULL, status) > 0)
-        {
-            /* use actual data minimum value for the histogram minimum */
-            *status = 0;
-            if (fits_get_col_minmax(*fptr, histData.hcolnum[ii], amin+ii, &datamax, status) > 0)
-            {
-                strcpy(errmsg, "Error calculating datamin and datamax for column: ");
-                strcat(errmsg, colname[ii]);
-                ffpmsg(errmsg);
-                return(*status);
-            }
-         }
-      }
-      else
-      {
-        amin[ii] = (float) minin[ii];
-      }
-
-      if (maxin[ii] == DOUBLENULLVALUE)
-      {
-        ffkeyn("TLMAX", histData.hcolnum[ii], keyname, status);
-        if (ffgky(*fptr, TFLOAT, keyname, &amax[ii], NULL, status) > 0)
-        {
-          *status = 0;
-          if(datamax != FLOATNULLVALUE)  /* already computed max value */
-          {
-             amax[ii] = datamax;
-          }
-          else
-          {
-             /* use actual data maximum value for the histogram maximum */
-             if (fits_get_col_minmax(*fptr, histData.hcolnum[ii], &datamin, &amax[ii], status) > 0)
-             {
-                 strcpy(errmsg, "Error calculating datamin and datamax for column: ");
-                 strcat(errmsg, colname[ii]);
-                 ffpmsg(errmsg);
-                 return(*status);
-             }
-          }
-        }
-        use_datamax = 1;  /* flag that the max was determined by the data values */
-                          /* and not specifically set by the calling program */
-      }
-      else
-      {
-        amax[ii] = (float) maxin[ii];
-      }
-
-      /* use TDBINn keyword or else 1 if bin size is not given */
-      if (binsizein[ii] == DOUBLENULLVALUE)
-      {
-         tstatus = 0;
-         ffkeyn("TDBIN", histData.hcolnum[ii], keyname, &tstatus);
-
-         if (ffgky(*fptr, TDOUBLE, keyname, binsizein + ii, NULL, &tstatus) > 0)
-         {
-	    /* make at least 10 bins */
-            binsizein[ii] = (amax[ii] - amin[ii]) / 10. ;
-            if (binsizein[ii] > 1.)
-                binsizein[ii] = 1.;  /* use default bin size */
-         }
-      }
-
-      if ( (amin[ii] > amax[ii] && binsizein[ii] > 0. ) ||
-           (amin[ii] < amax[ii] && binsizein[ii] < 0. ) )
-          binsize[ii] = (float) -binsizein[ii];  /* reverse the sign of binsize */
-      else
-          binsize[ii] =  (float) binsizein[ii];  /* binsize has the correct sign */
-
-      ibin = (int) binsize[ii];
-      imin = (int) amin[ii];
-      imax = (int) amax[ii];
-
-      /* Determine the range and number of bins in the histogram. This  */
-      /* depends on whether the input columns are integer or floats, so */
-      /* treat each case separately.                                    */
-
-      if (datatype <= TLONG && (float) imin == amin[ii] &&
-                               (float) imax == amax[ii] &&
-                               (float) ibin == binsize[ii] )
-      {
-        /* This is an integer column and integer limits were entered. */
-        /* Shift the lower and upper histogramming limits by 0.5, so that */
-        /* the values fall in the center of the bin, not on the edge. */
-
-        haxes[ii] = (imax - imin) / ibin + 1;  /* last bin may only */
-                                               /* be partially full */
-        maxbin[ii] = (float) (haxes[ii] + 1.);  /* add 1. instead of .5 to avoid roundoff */
-
-        if (amin[ii] < amax[ii])
-        {
-          amin[ii] = (float) (amin[ii] - 0.5);
-          amax[ii] = (float) (amax[ii] + 0.5);
-        }
-        else
-        {
-          amin[ii] = (float) (amin[ii] + 0.5);
-          amax[ii] = (float) (amax[ii] - 0.5);
-        }
-      }
-      else if (use_datamax)  
-      {
-        /* Either the column datatype and/or the limits are floating point, */
-        /* and the histogram limits are being defined by the min and max */
-        /* values of the array.  Add 1 to the number of histogram bins to */
-        /* make sure that pixels that are equal to the maximum or are */
-        /* in the last partial bin are included.  */
-
-        maxbin[ii] = (amax[ii] - amin[ii]) / binsize[ii]; 
-        haxes[ii] = (long) (maxbin[ii] + 1);
-      }
-      else  
-      {
-        /*  float datatype column and/or limits, and the maximum value to */
-        /*  include in the histogram is specified by the calling program. */
-        /*  The lower limit is inclusive, but upper limit is exclusive    */
-        maxbin[ii] = (amax[ii] - amin[ii]) / binsize[ii];
-        haxes[ii] = (long) maxbin[ii];
-
-        if (amin[ii] < amax[ii])
-        {
-          if (amin[ii] + (haxes[ii] * binsize[ii]) < amax[ii])
-            haxes[ii]++;   /* need to include another partial bin */
-        }
-        else
-        {
-          if (amin[ii] + (haxes[ii] * binsize[ii]) > amax[ii])
-            haxes[ii]++;   /* need to include another partial bin */
-        }
-      }
-    }
-
-       /* get the histogramming weighting factor */
-    if (*wtcol)
-    {
-        /* first, look for a keyword with the weight value */
-        if (ffgky(*fptr, TFLOAT, wtcol, &histData.weight, NULL, status) )
-        {
-            /* not a keyword, so look for column with this name */
-            *status = 0;
-
-            /* get the column number in the table */
-            if (ffgcno(*fptr, CASEINSEN, wtcol, &histData.wtcolnum, status) > 0)
-            {
-               ffpmsg(
-               "keyword or column for histogram weights doesn't exist: ");
-               ffpmsg(wtcol);
-               return(*status);
-            }
-
-            histData.weight = FLOATNULLVALUE;
-        }
-    }
-    else
-        histData.weight = (float) weightin;
-
-    if (histData.weight <= 0. && histData.weight != FLOATNULLVALUE)
-    {
-        ffpmsg("Illegal histogramming weighting factor <= 0.");
-        return(*status = URL_PARSE_ERROR);
-    }
-
-    if (recip && histData.weight != FLOATNULLVALUE)
-       /* take reciprocal of weight */
-       histData.weight = (float) (1.0 / histData.weight);
-
-    histData.wtrecip = recip;
-        
-    /* size of histogram is now known, so create temp output file */
-    if (ffinit(&histptr, outfile, status) > 0)
-    {
-        ffpmsg("failed to create temp output file for histogram");
-        return(*status);
-    }
-
-    if (ffcrim(histptr, bitpix, histData.haxis, haxes, status) > 0)
-    {
-        ffpmsg("failed to create primary array histogram in temp file");
-        ffclos(histptr, status);
-        return(*status);
-    }
-
-    /* copy all non-structural keywords from the table to the image */
-    fits_get_hdrspace(*fptr, &nkeys, NULL, status);
-    for (ii = 1; ii <= nkeys; ii++)
-    {
-       fits_read_record(*fptr, ii, card, status);
-       if (fits_get_keyclass(card) >= 120)
-           fits_write_record(histptr, card, status);
-    }           
-
-    /* Set global variables with histogram parameter values.    */
-    /* Use separate scalar variables rather than arrays because */
-    /* it is more efficient when computing the histogram.       */
-
-    histData.amin1 = amin[0];
-    histData.maxbin1 = maxbin[0];
-    histData.binsize1 = binsize[0];
-    histData.haxis1 = haxes[0];
-
-    if (histData.haxis > 1)
-    {
-      histData.amin2 = amin[1];
-      histData.maxbin2 = maxbin[1];
-      histData.binsize2 = binsize[1];
-      histData.haxis2 = haxes[1];
-
-      if (histData.haxis > 2)
-      {
-        histData.amin3 = amin[2];
-        histData.maxbin3 = maxbin[2];
-        histData.binsize3 = binsize[2];
-        histData.haxis3 = haxes[2];
-
-        if (histData.haxis > 3)
-        {
-          histData.amin4 = amin[3];
-          histData.maxbin4 = maxbin[3];
-          histData.binsize4 = binsize[3];
-          histData.haxis4 = haxes[3];
-        }
-      }
-    }
-
-    /* define parameters of image for the iterator function */
-    fits_iter_set_file(imagepars, histptr);        /* pointer to image */
-    fits_iter_set_datatype(imagepars, imagetype);  /* image datatype   */
-    fits_iter_set_iotype(imagepars, OutputCol);    /* image is output  */
-
-    /* call the iterator function to write out the histogram image */
-    if (fits_iterate_data(n_cols, imagepars, offset, n_per_loop,
-                          ffwritehisto, (void*)&histData, status) )
-         return(*status);
-
-    /* write the World Coordinate System (WCS) keywords */
-    /* create default values if WCS keywords are not present in the table */
-    for (ii = 0; ii < histData.haxis; ii++)
-    {
-     /*  CTYPEn  */
-       tstatus = 0;
-       ffkeyn("TCTYP", histData.hcolnum[ii], keyname, &tstatus);
-       ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus);
-       if (tstatus)
-       {               /* just use column name as the type */
-          tstatus = 0;
-          ffkeyn("TTYPE", histData.hcolnum[ii], keyname, &tstatus);
-          ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus);
-       }
-
-       if (!tstatus)
-       {
-        ffkeyn("CTYPE", ii + 1, keyname, &tstatus);
-        ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Type", &tstatus);
-       }
-       else
-          tstatus = 0;
-
-     /*  CUNITn  */
-       ffkeyn("TCUNI", histData.hcolnum[ii], keyname, &tstatus);
-       ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus);
-       if (tstatus)
-       {         /* use the column units */
-          tstatus = 0;
-          ffkeyn("TUNIT", histData.hcolnum[ii], keyname, &tstatus);
-          ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus);
-       }
-
-       if (!tstatus)
-       {
-        ffkeyn("CUNIT", ii + 1, keyname, &tstatus);
-        ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Units", &tstatus);
-       }
-       else
-         tstatus = 0;
-
-     /*  CRPIXn  - Reference Pixel  */
-       ffkeyn("TCRPX", histData.hcolnum[ii], keyname, &tstatus);
-       ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus);
-       if (tstatus)
-       {
-         dvalue = 1.0; /* choose first pixel in new image as ref. pix. */
-         tstatus = 0;
-       }
-       else
-       {
-           /* calculate locate of the ref. pix. in the new image */
-           dvalue = (dvalue - amin[ii]) / binsize[ii] + .5;
-       }
-
-       ffkeyn("CRPIX", ii + 1, keyname, &tstatus);
-       ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Pixel", &tstatus);
-
-     /*  CRVALn - Value at the location of the reference pixel */
-       ffkeyn("TCRVL", histData.hcolnum[ii], keyname, &tstatus);
-       ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus);
-       if (tstatus)
-       {
-         /* calculate value at ref. pix. location (at center of 1st pixel) */
-         dvalue = amin[ii] + binsize[ii]/2.;
-         tstatus = 0;
-       }
-
-       ffkeyn("CRVAL", ii + 1, keyname, &tstatus);
-       ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Value", &tstatus);
-
-     /*  CDELTn - unit size of pixels  */
-       ffkeyn("TCDLT", histData.hcolnum[ii], keyname, &tstatus);
-       ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus);
-       if (tstatus)
-       {
-         dvalue = 1.0;  /* use default pixel size */
-         tstatus = 0;
-       }
-
-       dvalue = dvalue * binsize[ii];
-       ffkeyn("CDELT", ii + 1, keyname, &tstatus);
-       ffpky(histptr, TDOUBLE, keyname, &dvalue, "Pixel size", &tstatus);
-
-     /*  CROTAn - Rotation angle (degrees CCW)  */
-     /*  There should only be a CROTA2 keyword, and only for 2+ D images */
-       if (ii == 1)
-       {
-         ffkeyn("TCROT", histData.hcolnum[ii], keyname, &tstatus);
-         ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus);
-         if (!tstatus && dvalue != 0.)  /* only write keyword if angle != 0 */
-         {
-           ffkeyn("CROTA", ii + 1, keyname, &tstatus);
-           ffpky(histptr, TDOUBLE, keyname, &dvalue,
-                 "Rotation angle", &tstatus);
-         }
-         else
-         {
-            /* didn't find CROTA for the 2nd axis, so look for one */
-            /* on the first axis */
-           tstatus = 0;
-           ffkeyn("TCROT", histData.hcolnum[0], keyname, &tstatus);
-           ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus);
-           if (!tstatus && dvalue != 0.)  /* only write keyword if angle != 0 */
-           {
-             dvalue *= -1.;   /* negate the value, because mirror image */
-             ffkeyn("CROTA", ii + 1, keyname, &tstatus);
-             ffpky(histptr, TDOUBLE, keyname, &dvalue,
-                   "Rotation angle", &tstatus);
-           }
-         }
-       }
-    }
-
-    /* convert any TPn_k keywords to PCi_j; the value remains unchanged */
-    /* also convert any TCn_k to CDi_j; the value is modified by n binning size */
-    /* This is a bit of a kludge, and only works for 2D WCS */
-
-    if (histData.haxis == 2) {
-
-      /* PC1_1 */
-      tstatus = 0;
-      ffkeyn("TP", histData.hcolnum[0], card, &tstatus);
-      strcat(card,"_");
-      ffkeyn(card, histData.hcolnum[0], keyname, &tstatus);
-      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
-      if (!tstatus) 
-         ffpky(histptr, TDOUBLE, "PC1_1", &dvalue, card, &tstatus);
-
-      tstatus = 0;
-      keyname[1] = 'C';
-      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
-      if (!tstatus) {
-         dvalue *=  binsize[0];
-         ffpky(histptr, TDOUBLE, "CD1_1", &dvalue, card, &tstatus);
-      }
-
-      /* PC1_2 */
-      tstatus = 0;
-      ffkeyn("TP", histData.hcolnum[0], card, &tstatus);
-      strcat(card,"_");
-      ffkeyn(card, histData.hcolnum[1], keyname, &tstatus);
-      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
-      if (!tstatus) 
-         ffpky(histptr, TDOUBLE, "PC1_2", &dvalue, card, &tstatus);
- 
-      tstatus = 0;
-      keyname[1] = 'C';
-      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
-      if (!tstatus) {
-        dvalue *=  binsize[0];
-        ffpky(histptr, TDOUBLE, "CD1_2", &dvalue, card, &tstatus);
-      }
-       
-      /* PC2_1 */
-      tstatus = 0;
-      ffkeyn("TP", histData.hcolnum[1], card, &tstatus);
-      strcat(card,"_");
-      ffkeyn(card, histData.hcolnum[0], keyname, &tstatus);
-      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
-      if (!tstatus) 
-         ffpky(histptr, TDOUBLE, "PC2_1", &dvalue, card, &tstatus);
- 
-      tstatus = 0;
-      keyname[1] = 'C';
-      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
-      if (!tstatus) {
-         dvalue *=  binsize[1];
-         ffpky(histptr, TDOUBLE, "CD2_1", &dvalue, card, &tstatus);
-      }
-       
-       /* PC2_2 */
-      tstatus = 0;
-      ffkeyn("TP", histData.hcolnum[1], card, &tstatus);
-      strcat(card,"_");
-      ffkeyn(card, histData.hcolnum[1], keyname, &tstatus);
-      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
-      if (!tstatus) 
-         ffpky(histptr, TDOUBLE, "PC2_2", &dvalue, card, &tstatus);
-        
-      tstatus = 0;
-      keyname[1] = 'C';
-      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
-      if (!tstatus) {
-         dvalue *=  binsize[1];
-         ffpky(histptr, TDOUBLE, "CD2_2", &dvalue, card, &tstatus);
-      }
-    }   
-       
-    /* finally, close the original file and return ptr to the new image */
-    ffclos(*fptr, status);
-    *fptr = histptr;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_calc_binning(
-      fitsfile *fptr,  /* IO - pointer to table to be binned      ;       */
-      int naxis,       /* I - number of axes/columns in the binned image  */
-      char colname[4][FLEN_VALUE],   /* I - optional column names         */
-      double *minin,     /* I - optional lower bound value for each axis  */
-      double *maxin,     /* I - optional upper bound value, for each axis */
-      double *binsizein, /* I - optional bin size along each axis         */
-      char minname[4][FLEN_VALUE], /* I - optional keywords for min       */
-      char maxname[4][FLEN_VALUE], /* I - optional keywords for max       */
-      char binname[4][FLEN_VALUE], /* I - optional keywords for binsize   */
-
-    /* The returned parameters for each axis of the n-dimensional histogram are */
-
-      int *colnum,     /* O - column numbers, to be binned */
-      long *haxes,     /* O - number of bins in each histogram axis */
-      float *amin,     /* O - lower bound of the histogram axes */
-      float *amax,     /* O - upper bound of the histogram axes */
-      float *binsize,  /* O - width of histogram bins/pixels on each axis */
-      int *status)
-/*_
-    Calculate the actual binning parameters, based on various user input
-    options.
-*/
-{
-    tcolumn *colptr;
-    char *cptr, cpref[4][FLEN_VALUE];
-    char errmsg[FLEN_ERRMSG], keyname[FLEN_KEYWORD];
-    int tstatus, ii;
-    int datatype, repeat, imin, imax, ibin,  use_datamax = 0;
-    float datamin, datamax;
-
-    /* check inputs */
-    
-    if (*status > 0)
-        return(*status);
-
-    if (naxis > 4)
-    {
-        ffpmsg("histograms with more than 4 dimensions are not supported");
-        return(*status = BAD_DIMEN);
-    }
-
-    /* reset position to the correct HDU if necessary */
-    if ((fptr)->HDUposition != ((fptr)->Fptr)->curhdu)
-        ffmahd(fptr, ((fptr)->HDUposition) + 1, NULL, status);
-    
-    /* ============================================================= */
-    /* The CPREF keyword, if it exists, gives the preferred columns. */
-    /* Otherwise, assume "X", "Y", "Z", and "T"  */
-
-    *cpref[0] = '\0';
-    *cpref[1] = '\0';
-    *cpref[2] = '\0';
-    *cpref[3] = '\0';
-
-    tstatus = 0;
-    ffgky(fptr, TSTRING, "CPREF", cpref[0], NULL, &tstatus);
-
-    if (!tstatus)
-    {
-        /* Preferred column names are given;  separate them */
-        cptr = cpref[0];
-
-        /* the first preferred axis... */
-        while (*cptr != ',' && *cptr != '\0')
-           cptr++;
-
-        if (*cptr != '\0')
-        {
-           *cptr = '\0';
-           cptr++;
-           while (*cptr == ' ')
-               cptr++;
-
-           strcpy(cpref[1], cptr);
-           cptr = cpref[1];
-
-          /* the second preferred axis... */
-          while (*cptr != ',' && *cptr != '\0')
-             cptr++;
-
-          if (*cptr != '\0')
-          {
-             *cptr = '\0';
-             cptr++;
-             while (*cptr == ' ')
-                 cptr++;
-
-             strcpy(cpref[2], cptr);
-             cptr = cpref[2];
-
-            /* the third preferred axis... */
-            while (*cptr != ',' && *cptr != '\0')
-               cptr++;
-
-            if (*cptr != '\0')
-            {
-               *cptr = '\0';
-               cptr++;
-               while (*cptr == ' ')
-                   cptr++;
-
-               strcpy(cpref[3], cptr);
-
-            }
-          }
-        }
-    }
-
-    /* ============================================================= */
-    /* Main Loop for calculating parameters for each column          */
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-
-      /* =========================================================== */
-      /* Determine column Number, based on, in order of priority,
-         1  input column name, or
-	 2  name given by CPREF keyword, or
-	 3  assume X, Y, Z and T for the name
-      */
-	  
-      if (*colname[ii] == '\0')
-      {
-         strcpy(colname[ii], cpref[ii]); /* try using the preferred column */
-         if (*colname[ii] == '\0')
-         {
-           if (ii == 0)
-              strcpy(colname[ii], "X");
-           else if (ii == 1)
-              strcpy(colname[ii], "Y");
-           else if (ii == 2)
-              strcpy(colname[ii], "Z");
-           else if (ii == 3)
-              strcpy(colname[ii], "T");
-         }
-      }
-
-      /* get the column number in the table */
-      if (ffgcno(fptr, CASEINSEN, colname[ii], colnum+ii, status)
-              > 0)
-      {
-          strcpy(errmsg, "column for histogram axis doesn't exist: ");
-          strcat(errmsg, colname[ii]);
-          ffpmsg(errmsg);
-          return(*status);
-      }
-
-      /* ================================================================ */
-      /* check tha column is not a vector or a string                     */
-
-      colptr = ((fptr)->Fptr)->tableptr;
-      colptr += (colnum[ii] - 1);
-
-      repeat = (int) colptr->trepeat;  /* vector repeat factor of the column */
-      if (repeat > 1)
-      {
-        strcpy(errmsg, "Can't bin a vector column: ");
-        strcat(errmsg, colname[ii]);
-        ffpmsg(errmsg);
-        return(*status = BAD_DATATYPE);
-      }
-
-      /* get the datatype of the column */
-      fits_get_coltype(fptr, colnum[ii], &datatype,
-         NULL, NULL, status);
-
-      if (datatype < 0 || datatype == TSTRING)
-      {
-        strcpy(errmsg, "Inappropriate datatype; can't bin this column: ");
-        strcat(errmsg, colname[ii]);
-        ffpmsg(errmsg);
-        return(*status = BAD_DATATYPE);
-      }
-
-      /* ================================================================ */
-      /* get the minimum value */
-
-      datamin = FLOATNULLVALUE;
-      datamax = FLOATNULLVALUE;
-      
-      if (*minname[ii])
-      {
-         if (ffgky(fptr, TDOUBLE, minname[ii], &minin[ii], NULL, status) )
-         {
-             ffpmsg("error reading histogramming minimum keyword");
-             ffpmsg(minname[ii]);
-             return(*status);
-         }
-      }
-
-      if (minin[ii] != DOUBLENULLVALUE)
-      {
-        amin[ii] = (float) minin[ii];
-      }
-      else
-      {
-        ffkeyn("TLMIN", colnum[ii], keyname, status);
-        if (ffgky(fptr, TFLOAT, keyname, amin+ii, NULL, status) > 0)
-        {
-            /* use actual data minimum value for the histogram minimum */
-            *status = 0;
-            if (fits_get_col_minmax(fptr, colnum[ii], amin+ii, &datamax, status) > 0)
-            {
-                strcpy(errmsg, "Error calculating datamin and datamax for column: ");
-                strcat(errmsg, colname[ii]);
-                ffpmsg(errmsg);
-                return(*status);
-            }
-         }
-      }
-
-      /* ================================================================ */
-      /* get the maximum value */
-
-      if (*maxname[ii])
-      {
-         if (ffgky(fptr, TDOUBLE, maxname[ii], &maxin[ii], NULL, status) )
-         {
-             ffpmsg("error reading histogramming maximum keyword");
-             ffpmsg(maxname[ii]);
-             return(*status);
-         }
-      }
-
-      if (maxin[ii] != DOUBLENULLVALUE)
-      {
-        amax[ii] = (float) maxin[ii];
-      }
-      else
-      {
-        ffkeyn("TLMAX", colnum[ii], keyname, status);
-        if (ffgky(fptr, TFLOAT, keyname, &amax[ii], NULL, status) > 0)
-        {
-          *status = 0;
-          if(datamax != FLOATNULLVALUE)  /* already computed max value */
-          {
-             amax[ii] = datamax;
-          }
-          else
-          {
-             /* use actual data maximum value for the histogram maximum */
-             if (fits_get_col_minmax(fptr, colnum[ii], &datamin, &amax[ii], status) > 0)
-             {
-                 strcpy(errmsg, "Error calculating datamin and datamax for column: ");
-                 strcat(errmsg, colname[ii]);
-                 ffpmsg(errmsg);
-                 return(*status);
-             }
-          }
-        }
-        use_datamax = 1;  /* flag that the max was determined by the data values */
-                          /* and not specifically set by the calling program */
-      }
-
-
-      /* ================================================================ */
-      /* determine binning size and range                                 */
-
-      if (*binname[ii])
-      {
-         if (ffgky(fptr, TDOUBLE, binname[ii], &binsizein[ii], NULL, status) )
-         {
-             ffpmsg("error reading histogramming binsize keyword");
-             ffpmsg(binname[ii]);
-             return(*status);
-         }
-      }
-
-      if (binsizein[ii] == 0.)
-      {
-        ffpmsg("error: histogram binsize = 0");
-        return(*status = ZERO_SCALE);
-      }
-
-      /* use TDBINn keyword or else 1 if bin size is not given */
-      if (binsizein[ii] != DOUBLENULLVALUE)
-      { 
-         binsize[ii] = (float) binsizein[ii];
-      }
-      else
-      {
-         tstatus = 0;
-         ffkeyn("TDBIN", colnum[ii], keyname, &tstatus);
-
-         if (ffgky(fptr, TDOUBLE, keyname, binsizein + ii, NULL, &tstatus) > 0)
-         {
-	    /* make at least 10 bins */
-            binsize[ii] = (amax[ii] - amin[ii]) / 10.F ;
-            if (binsize[ii] > 1.)
-                binsize[ii] = 1.;  /* use default bin size */
-         }
-      }
-
-      /* ================================================================ */
-      /* if the min is greater than the max, make the binsize negative */
-      if ( (amin[ii] > amax[ii] && binsize[ii] > 0. ) ||
-           (amin[ii] < amax[ii] && binsize[ii] < 0. ) )
-          binsize[ii] =  -binsize[ii];  /* reverse the sign of binsize */
-
-
-      ibin = (int) binsize[ii];
-      imin = (int) amin[ii];
-      imax = (int) amax[ii];
-
-      /* Determine the range and number of bins in the histogram. This  */
-      /* depends on whether the input columns are integer or floats, so */
-      /* treat each case separately.                                    */
-
-      if (datatype <= TLONG && (float) imin == amin[ii] &&
-                               (float) imax == amax[ii] &&
-                               (float) ibin == binsize[ii] )
-      {
-        /* This is an integer column and integer limits were entered. */
-        /* Shift the lower and upper histogramming limits by 0.5, so that */
-        /* the values fall in the center of the bin, not on the edge. */
-
-        haxes[ii] = (imax - imin) / ibin + 1;  /* last bin may only */
-                                               /* be partially full */
-        if (amin[ii] < amax[ii])
-        {
-          amin[ii] = (float) (amin[ii] - 0.5);
-          amax[ii] = (float) (amax[ii] + 0.5);
-        }
-        else
-        {
-          amin[ii] = (float) (amin[ii] + 0.5);
-          amax[ii] = (float) (amax[ii] - 0.5);
-        }
-      }
-      else if (use_datamax)  
-      {
-        /* Either the column datatype and/or the limits are floating point, */
-        /* and the histogram limits are being defined by the min and max */
-        /* values of the array.  Add 1 to the number of histogram bins to */
-        /* make sure that pixels that are equal to the maximum or are */
-        /* in the last partial bin are included.  */
-
-        haxes[ii] = (long) (((amax[ii] - amin[ii]) / binsize[ii]) + 1.); 
-      }
-      else  
-      {
-        /*  float datatype column and/or limits, and the maximum value to */
-        /*  include in the histogram is specified by the calling program. */
-        /*  The lower limit is inclusive, but upper limit is exclusive    */
-        haxes[ii] = (long) ((amax[ii] - amin[ii]) / binsize[ii]);
-
-        if (amin[ii] < amax[ii])
-        {
-          if (amin[ii] + (haxes[ii] * binsize[ii]) < amax[ii])
-            haxes[ii]++;   /* need to include another partial bin */
-        }
-        else
-        {
-          if (amin[ii] + (haxes[ii] * binsize[ii]) > amax[ii])
-            haxes[ii]++;   /* need to include another partial bin */
-        }
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_write_keys_histo(
-      fitsfile *fptr,   /* I - pointer to table to be binned              */
-      fitsfile *histptr,  /* I - pointer to output histogram image HDU      */
-      int naxis,        /* I - number of axes in the histogram image      */
-      int *colnum,      /* I - column numbers (array length = naxis)      */
-      int *status)     
-{      
-   /*  Write default WCS keywords in the output histogram image header */
-   /*  if the keywords do not already exist.   */
-
-    int ii, tstatus;
-    char keyname[FLEN_KEYWORD], svalue[FLEN_VALUE];
-    double dvalue;
-    
-    if (*status > 0)
-        return(*status);
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-     /*  CTYPEn  */
-       tstatus = 0;
-       ffkeyn("CTYPE", ii+1, keyname, &tstatus);
-       ffgky(histptr, TSTRING, keyname, svalue, NULL, &tstatus);
-       
-       if (!tstatus) continue;  /* keyword already exists, so skip to next axis */
-       
-       /* use column name as the axis name */
-       tstatus = 0;
-       ffkeyn("TTYPE", colnum[ii], keyname, &tstatus);
-       ffgky(fptr, TSTRING, keyname, svalue, NULL, &tstatus);
-
-       if (!tstatus)
-       {
-         ffkeyn("CTYPE", ii + 1, keyname, &tstatus);
-         ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Type", &tstatus);
-       }
-
-       /*  CUNITn,  use the column units */
-       tstatus = 0;
-       ffkeyn("TUNIT", colnum[ii], keyname, &tstatus);
-       ffgky(fptr, TSTRING, keyname, svalue, NULL, &tstatus);
-
-       if (!tstatus)
-       {
-         ffkeyn("CUNIT", ii + 1, keyname, &tstatus);
-         ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Units", &tstatus);
-       }
-
-       /*  CRPIXn  - Reference Pixel choose first pixel in new image as ref. pix. */
-       dvalue = 1.0;
-       tstatus = 0;
-       ffkeyn("CRPIX", ii + 1, keyname, &tstatus);
-       ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Pixel", &tstatus);
-
-       /*  CRVALn - Value at the location of the reference pixel */
-       dvalue = 1.0;
-       tstatus = 0;
-       ffkeyn("CRVAL", ii + 1, keyname, &tstatus);
-       ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Value", &tstatus);
-
-       /*  CDELTn - unit size of pixels  */
-       dvalue = 1.0;  
-       tstatus = 0;
-       dvalue = 1.;
-       ffkeyn("CDELT", ii + 1, keyname, &tstatus);
-       ffpky(histptr, TDOUBLE, keyname, &dvalue, "Pixel size", &tstatus);
-
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_rebin_wcs(
-      fitsfile *fptr,   /* I - pointer to table to be binned           */
-      int naxis,        /* I - number of axes in the histogram image   */
-      float *amin,        /* I - first pixel include in each axis        */
-      float *binsize,     /* I - binning factor for each axis            */
-      int *status)      
-{      
-   /*  Update the  WCS keywords that define the location of the reference */
-   /*  pixel, and the pixel size, along each axis.   */
-
-    int ii, jj, tstatus, reset ;
-    char keyname[FLEN_KEYWORD], svalue[FLEN_VALUE];
-    double dvalue;
-    
-    if (*status > 0)
-        return(*status);
-  
-    for (ii = 0; ii < naxis; ii++)
-    {
-       reset = 0;  /* flag to reset the reference pixel */
-       tstatus = 0;
-       ffkeyn("CRVAL", ii + 1, keyname, &tstatus);
-       /* get previous (pre-binning) value */
-       ffgky(fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); 
-       if (!tstatus && dvalue == 1.0)
-           reset = 1;
-
-       tstatus = 0;
-       /*  CRPIXn - update location of the ref. pix. in the binned image */
-       ffkeyn("CRPIX", ii + 1, keyname, &tstatus);
-
-       /* get previous (pre-binning) value */
-       ffgky(fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); 
-
-       if (!tstatus)
-       {
-           if (dvalue != 1.0)
-	      reset = 0;
-
-           /* updated value to give pixel location after binning */
-           dvalue = (dvalue - amin[ii]) / ((double) binsize[ii]) + .5;  
-
-           fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus);
-       } else {
-          reset = 0;
-       }
-
-       /*  CDELTn - update unit size of pixels  */
-       tstatus = 0;
-       ffkeyn("CDELT", ii + 1, keyname, &tstatus);
-
-       /* get previous (pre-binning) value */
-       ffgky(fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); 
-
-       if (!tstatus)
-       {
-           if (dvalue != 1.0)
-	      reset = 0;
-
-           /* updated to give post-binning value */
-           dvalue = dvalue * binsize[ii];  
-
-           fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus);
-       }
-       else
-       {   /* no CDELTn keyword, so look for a CDij keywords */
-          reset = 0;
-
-          for (jj = 0; jj < naxis; jj++)
-	  {
-             tstatus = 0;
-             ffkeyn("CD", jj + 1, svalue, &tstatus);
-	     strcat(svalue,"_");
-	     ffkeyn(svalue, ii + 1, keyname, &tstatus);
-
-             /* get previous (pre-binning) value */
-             ffgky(fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); 
-
-             if (!tstatus)
-             {
-                /* updated to give post-binning value */
-               dvalue = dvalue * binsize[ii];  
-
-               fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus);
-             }
-	  }
-       }
-
-       if (reset) {
-          /* the original CRPIX, CRVAL, and CDELT keywords were all = 1.0 */
-	  /* In this special case, reset the reference pixel to be the */
-	  /* first pixel in the array (instead of possibly far off the array) */
- 
-           dvalue = 1.0;
-           ffkeyn("CRPIX", ii + 1, keyname, &tstatus);
-           fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus);
-
-           ffkeyn("CRVAL", ii + 1, keyname, &tstatus);
-	   dvalue = amin[ii] + (binsize[ii] / 2.0);	  
-           fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus);
-	}
-
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-
-int fits_make_hist(fitsfile *fptr, /* IO - pointer to table with X and Y cols; */
-    fitsfile *histptr, /* I - pointer to output FITS image      */
-    int bitpix,       /* I - datatype for image: 16, 32, -32, etc    */
-    int naxis,        /* I - number of axes in the histogram image   */
-    long *naxes,      /* I - size of axes in the histogram image   */
-    int *colnum,    /* I - column numbers (array length = naxis)   */
-    float *amin,     /* I - minimum histogram value, for each axis */
-    float *amax,     /* I - maximum histogram value, for each axis */
-    float *binsize, /* I - bin size along each axis               */
-    float weight,        /* I - binning weighting factor          */
-    int wtcolnum, /* I - optional keyword or col for weight*/
-    int recip,              /* I - use reciprocal of the weight?     */
-    char *selectrow,        /* I - optional array (length = no. of   */
-                             /* rows in the table).  If the element is true */
-                             /* then the corresponding row of the table will*/
-                             /* be included in the histogram, otherwise the */
-                             /* row will be skipped.  Ingnored if *selectrow*/
-                             /* is equal to NULL.                           */
-    int *status)
-{		  
-    int ii, imagetype, datatype;
-    int n_cols = 1;
-    long imin, imax, ibin;
-    long  offset = 0;
-    long n_per_loop = -1;  /* force whole array to be passed at one time */
-    float taxes[4], tmin[4], tmax[4], tbin[4], maxbin[4];
-    histType histData;    /* Structure holding histogram info for iterator */
-    iteratorCol imagepars[1];
-
-    /* check inputs */
-    
-    if (*status > 0)
-        return(*status);
-
-    if (naxis > 4)
-    {
-        ffpmsg("histogram has more than 4 dimensions");
-        return(*status = BAD_DIMEN);
-    }
-
-    if   (bitpix == BYTE_IMG)
-         imagetype = TBYTE;
-    else if (bitpix == SHORT_IMG)
-         imagetype = TSHORT;
-    else if (bitpix == LONG_IMG)
-         imagetype = TINT;    
-    else if (bitpix == FLOAT_IMG)
-         imagetype = TFLOAT;    
-    else if (bitpix == DOUBLE_IMG)
-         imagetype = TDOUBLE;    
-    else
-        return(*status = BAD_DATATYPE);
-
-    /* reset position to the correct HDU if necessary */
-    if ((fptr)->HDUposition != ((fptr)->Fptr)->curhdu)
-        ffmahd(fptr, ((fptr)->HDUposition) + 1, NULL, status);
-
-    histData.weight     = weight;
-    histData.wtcolnum   = wtcolnum;
-    histData.wtrecip    = recip;
-    histData.tblptr     = fptr;
-    histData.himagetype = imagetype;
-    histData.haxis      = naxis;
-    histData.rowselector = selectrow;
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-      taxes[ii] = (float) naxes[ii];
-      tmin[ii] = amin[ii];
-      tmax[ii] = amax[ii];
-      if ( (amin[ii] > amax[ii] && binsize[ii] > 0. ) ||
-           (amin[ii] < amax[ii] && binsize[ii] < 0. ) )
-          tbin[ii] =  -binsize[ii];  /* reverse the sign of binsize */
-      else
-          tbin[ii] =   binsize[ii];  /* binsize has the correct sign */
-          
-      imin = (long) tmin[ii];
-      imax = (long) tmax[ii];
-      ibin = (long) tbin[ii];
-    
-      /* get the datatype of the column */
-      fits_get_coltype(fptr, colnum[ii], &datatype, NULL, NULL, status);
-
-      if (datatype <= TLONG && (float) imin == tmin[ii] &&
-                               (float) imax == tmax[ii] &&
-                               (float) ibin == tbin[ii] )
-      {
-        /* This is an integer column and integer limits were entered. */
-        /* Shift the lower and upper histogramming limits by 0.5, so that */
-        /* the values fall in the center of the bin, not on the edge. */
-
-        maxbin[ii] = (taxes[ii] + 1.F);  /* add 1. instead of .5 to avoid roundoff */
-
-        if (tmin[ii] < tmax[ii])
-        {
-          tmin[ii] = tmin[ii] - 0.5F;
-          tmax[ii] = tmax[ii] + 0.5F;
-        }
-        else
-        {
-          tmin[ii] = tmin[ii] + 0.5F;
-          tmax[ii] = tmax[ii] - 0.5F;
-        }
-      } else {  /* not an integer column with integer limits */
-          maxbin[ii] = (tmax[ii] - tmin[ii]) / tbin[ii]; 
-      }
-    }
-
-    /* Set global variables with histogram parameter values.    */
-    /* Use separate scalar variables rather than arrays because */
-    /* it is more efficient when computing the histogram.       */
-
-    histData.hcolnum[0]  = colnum[0];
-    histData.amin1 = tmin[0];
-    histData.maxbin1 = maxbin[0];
-    histData.binsize1 = tbin[0];
-    histData.haxis1 = (long) taxes[0];
-
-    if (histData.haxis > 1)
-    {
-      histData.hcolnum[1]  = colnum[1];
-      histData.amin2 = tmin[1];
-      histData.maxbin2 = maxbin[1];
-      histData.binsize2 = tbin[1];
-      histData.haxis2 = (long) taxes[1];
-
-      if (histData.haxis > 2)
-      {
-        histData.hcolnum[2]  = colnum[2];
-        histData.amin3 = tmin[2];
-        histData.maxbin3 = maxbin[2];
-        histData.binsize3 = tbin[2];
-        histData.haxis3 = (long) taxes[2];
-
-        if (histData.haxis > 3)
-        {
-          histData.hcolnum[3]  = colnum[3];
-          histData.amin4 = tmin[3];
-          histData.maxbin4 = maxbin[3];
-          histData.binsize4 = tbin[3];
-          histData.haxis4 = (long) taxes[3];
-        }
-      }
-    }
-
-    /* define parameters of image for the iterator function */
-    fits_iter_set_file(imagepars, histptr);        /* pointer to image */
-    fits_iter_set_datatype(imagepars, imagetype);  /* image datatype   */
-    fits_iter_set_iotype(imagepars, OutputCol);    /* image is output  */
-
-    /* call the iterator function to write out the histogram image */
-    fits_iterate_data(n_cols, imagepars, offset, n_per_loop,
-                          ffwritehisto, (void*)&histData, status);
-       
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_get_col_minmax(fitsfile *fptr, int colnum, float *datamin, 
-                     float *datamax, int *status)
-/* 
-   Simple utility routine to compute the min and max value in a column
-*/
-{
-    int anynul;
-    long nrows, ntodo, firstrow, ii;
-    float array[1000], nulval;
-
-    ffgky(fptr, TLONG, "NAXIS2", &nrows, NULL, status); /* no. of rows */
-
-    firstrow = 1;
-    nulval = FLOATNULLVALUE;
-    *datamin =  9.0E36F;
-    *datamax = -9.0E36F;
-
-    while(nrows)
-    {
-        ntodo = minvalue(nrows, 100);
-        ffgcv(fptr, TFLOAT, colnum, firstrow, 1, ntodo, &nulval, array,
-              &anynul, status);
-
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (array[ii] != nulval)
-            {
-                *datamin = minvalue(*datamin, array[ii]);
-                *datamax = maxvalue(*datamax, array[ii]);
-            }
-        }
-
-        nrows -= ntodo;
-        firstrow += ntodo;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffwritehisto(long totaln, long pixoffset, long firstn, long nvalues,
-             int narrays, iteratorCol *imagepars, void *userPointer)
-/*
-   Interator work function that writes out the histogram.
-   The histogram values are calculated by another work function, ffcalchisto.
-   This work function only gets called once, and totaln = nvalues.
-*/
-{
-    iteratorCol colpars[5];
-    int ii, status = 0, ncols;
-    long rows_per_loop = 0, offset = 0;
-    histType *histData;
-
-    histData = (histType *)userPointer;
-
-    /* store pointer to the histogram array, and initialize to zero */
-
-    switch( histData->himagetype ) {
-    case TBYTE:
-       histData->hist.b = (char *  ) fits_iter_get_array(imagepars);
-       break;
-    case TSHORT:
-       histData->hist.i = (short * ) fits_iter_get_array(imagepars);
-       break;
-    case TINT:
-       histData->hist.j = (int *   ) fits_iter_get_array(imagepars);
-       break;
-    case TFLOAT:
-       histData->hist.r = (float * ) fits_iter_get_array(imagepars);
-       break;
-    case TDOUBLE:
-       histData->hist.d = (double *) fits_iter_get_array(imagepars);
-       break;
-    }
-
-    /* set the column parameters for the iterator function */
-    for (ii = 0; ii < histData->haxis; ii++)
-    {
-      fits_iter_set_by_num(&colpars[ii], histData->tblptr,
-			   histData->hcolnum[ii], TFLOAT, InputCol);
-    }
-    ncols = histData->haxis;
-
-    if (histData->weight == FLOATNULLVALUE)
-    {
-      fits_iter_set_by_num(&colpars[histData->haxis], histData->tblptr,
-			   histData->wtcolnum, TFLOAT, InputCol);
-      ncols = histData->haxis + 1;
-    }
-
-    /* call iterator function to calc the histogram pixel values */
-
-    /* must lock this call in multithreaded environoments because */
-    /* the ffcalchist work routine uses static vaiables that would */
-    /* get clobbered if multiple threads were running at the same time */
-    FFLOCK;
-    fits_iterate_data(ncols, colpars, offset, rows_per_loop,
-                          ffcalchist, (void*)histData, &status);
-    FFUNLOCK;
-
-    return(status);
-}
-/*--------------------------------------------------------------------------*/
-int ffcalchist(long totalrows, long offset, long firstrow, long nrows,
-             int ncols, iteratorCol *colpars, void *userPointer)
-/*
-   Interator work function that calculates values for the 2D histogram.
-*/
-{
-    long ii, ipix, iaxisbin;
-    float pix, axisbin;
-    static float *col1, *col2, *col3, *col4; /* static to preserve values */
-    static float *wtcol;
-    static long incr2, incr3, incr4;
-    static histType histData;
-    static char *rowselect;
-
-    /*  Initialization procedures: execute on the first call  */
-    if (firstrow == 1)
-    {
-
-      /*  Copy input histogram data to static local variable so we */
-      /*  don't have to constantly dereference it.                 */
-
-      histData = *(histType*)userPointer;
-      rowselect = histData.rowselector;
-
-      /* assign the input array pointers to local pointers */
-      col1 = (float *) fits_iter_get_array(&colpars[0]);
-      if (histData.haxis > 1)
-      {
-        col2 = (float *) fits_iter_get_array(&colpars[1]);
-        incr2 = histData.haxis1;
-
-        if (histData.haxis > 2)
-        {
-          col3 = (float *) fits_iter_get_array(&colpars[2]);
-          incr3 = incr2 * histData.haxis2;
-
-          if (histData.haxis > 3)
-          {
-            col4 = (float *) fits_iter_get_array(&colpars[3]);
-            incr4 = incr3 * histData.haxis3;
-          }
-        }
-      }
-
-      if (ncols > histData.haxis)  /* then weights are give in a column */
-      {
-        wtcol = (float *) fits_iter_get_array(&colpars[histData.haxis]);
-      }
-    }   /* end of Initialization procedures */
-
-    /*  Main loop: increment the histogram at position of each event */
-    for (ii = 1; ii <= nrows; ii++) 
-    {
-        if (rowselect)     /* if a row selector array is supplied... */
-        {
-           if (*rowselect)
-           {
-               rowselect++;   /* this row is included in the histogram */
-           }
-           else
-           {
-               rowselect++;   /* this row is excluded from the histogram */
-               continue;
-           }
-        }
-
-        if (col1[ii] == FLOATNULLVALUE)  /* test for null value */
-            continue;
-
-        pix = (col1[ii] - histData.amin1) / histData.binsize1;
-        ipix = (long) (pix + 1.); /* add 1 because the 1st pixel is the null value */
-
-	/* test if bin is within range */
-        if (ipix < 1 || ipix > histData.haxis1 || pix > histData.maxbin1)
-            continue;
-
-        if (histData.haxis > 1)
-        {
-          if (col2[ii] == FLOATNULLVALUE)
-              continue;
-
-          axisbin = (col2[ii] - histData.amin2) / histData.binsize2;
-          iaxisbin = (long) axisbin;
-
-          if (axisbin < 0. || iaxisbin >= histData.haxis2 || axisbin > histData.maxbin2)
-              continue;
-
-          ipix += (iaxisbin * incr2);
-
-          if (histData.haxis > 2)
-          {
-            if (col3[ii] == FLOATNULLVALUE)
-                continue;
-
-            axisbin = (col3[ii] - histData.amin3) / histData.binsize3;
-            iaxisbin = (long) axisbin;
-            if (axisbin < 0. || iaxisbin >= histData.haxis3 || axisbin > histData.maxbin3)
-                continue;
-
-            ipix += (iaxisbin * incr3);
- 
-            if (histData.haxis > 3)
-            {
-              if (col4[ii] == FLOATNULLVALUE)
-                  continue;
-
-              axisbin = (col4[ii] - histData.amin4) / histData.binsize4;
-              iaxisbin = (long) axisbin;
-              if (axisbin < 0. || iaxisbin >= histData.haxis4 || axisbin > histData.maxbin4)
-                  continue;
-
-              ipix += (iaxisbin * incr4);
-
-            }  /* end of haxis > 3 case */
-          }    /* end of haxis > 2 case */
-        }      /* end of haxis > 1 case */
-
-        /* increment the histogram pixel */
-        if (histData.weight != FLOATNULLVALUE) /* constant weight factor */
-        {
-            if (histData.himagetype == TINT)
-              histData.hist.j[ipix] += (int) histData.weight;
-            else if (histData.himagetype == TSHORT)
-              histData.hist.i[ipix] += (short) histData.weight;
-            else if (histData.himagetype == TFLOAT)
-              histData.hist.r[ipix] += histData.weight;
-            else if (histData.himagetype == TDOUBLE)
-              histData.hist.d[ipix] += histData.weight;
-            else if (histData.himagetype == TBYTE)
-              histData.hist.b[ipix] += (char) histData.weight;
-        }
-        else if (histData.wtrecip) /* use reciprocal of the weight */
-        {
-            if (histData.himagetype == TINT)
-              histData.hist.j[ipix] += (int) (1./wtcol[ii]);
-            else if (histData.himagetype == TSHORT)
-              histData.hist.i[ipix] += (short) (1./wtcol[ii]);
-            else if (histData.himagetype == TFLOAT)
-              histData.hist.r[ipix] += (float) (1./wtcol[ii]);
-            else if (histData.himagetype == TDOUBLE)
-              histData.hist.d[ipix] += 1./wtcol[ii];
-            else if (histData.himagetype == TBYTE)
-              histData.hist.b[ipix] += (char) (1./wtcol[ii]);
-        }
-        else   /* no weights */
-        {
-            if (histData.himagetype == TINT)
-              histData.hist.j[ipix] += (int) wtcol[ii];
-            else if (histData.himagetype == TSHORT)
-              histData.hist.i[ipix] += (short) wtcol[ii];
-            else if (histData.himagetype == TFLOAT)
-              histData.hist.r[ipix] += wtcol[ii];
-            else if (histData.himagetype == TDOUBLE)
-              histData.hist.d[ipix] += wtcol[ii];
-            else if (histData.himagetype == TBYTE)
-              histData.hist.b[ipix] += (char) wtcol[ii];
-        }
-
-    }  /* end of main loop over all rows */
-
-    return(0);
-}
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/imcompress.c b/src/external/OpenGR/3rdparty/cfitsio/imcompress.c
deleted file mode 100644
index da5a6d66c..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/imcompress.c
+++ /dev/null
@@ -1,9754 +0,0 @@
-# include 
-# include 
-# include 
-# include 
-# include 
-# include 
-# include "fitsio2.h"
-
-#define NULL_VALUE -2147483647 /* value used to represent undefined pixels */
-#define ZERO_VALUE -2147483646 /* value used to represent zero-valued pixels */
-
-/* nearest integer function */
-# define NINT(x)  ((x >= 0.) ? (int) (x + 0.5) : (int) (x - 0.5))
-
-/* special quantize level value indicates that floating point image pixels */
-/* should not be quantized and instead losslessly compressed (with GZIP) */
-#define NO_QUANTIZE 9999
-
-/* string array for storing the individual column compression stats */
-char results[999][30];
-
-float *fits_rand_value = 0;
-
-int imcomp_write_nocompress_tile(fitsfile *outfptr, long row, int datatype, 
-    void *tiledata, long tilelen, int nullcheck, void *nullflagval, int *status);
-int imcomp_convert_tile_tshort(fitsfile *outfptr, void *tiledata, long tilelen,
-    int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale,
-    double zero, double actual_bzero, int *intlength, int *status);
-int imcomp_convert_tile_tushort(fitsfile *outfptr, void *tiledata, long tilelen,
-    int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale,
-    double zero, int *intlength, int *status);
-int imcomp_convert_tile_tint(fitsfile *outfptr, void *tiledata, long tilelen,
-    int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale,
-    double zero, int *intlength, int *status);
-int imcomp_convert_tile_tuint(fitsfile *outfptr, void *tiledata, long tilelen,
-    int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale,
-    double zero, int *intlength, int *status);
-int imcomp_convert_tile_tbyte(fitsfile *outfptr, void *tiledata, long tilelen,
-    int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale,
-    double zero, int *intlength, int *status);
-int imcomp_convert_tile_tsbyte(fitsfile *outfptr, void *tiledata, long tilelen,
-    int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale,
-    double zero, int *intlength, int *status);
-int imcomp_convert_tile_tfloat(fitsfile *outfptr, long row, void *tiledata, long tilelen,
-    long tilenx, long tileny, int nullcheck, void *nullflagval, int nullval, int zbitpix,
-    double scale, double zero, int *intlength, int *flag, double *bscale, double *bzero,int *status);
-int imcomp_convert_tile_tdouble(fitsfile *outfptr, long row, void *tiledata, long tilelen,
-    long tilenx, long tileny, int nullcheck, void *nullflagval, int nullval, int zbitpix, 
-    double scale, double zero, int *intlength, int *flag, double *bscale, double *bzero, int *status);
-
-static int unquantize_i1r4(long row,
-            unsigned char *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int dither_method,    /* I - which subtractive dither method to use */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,          /* I - value of FITS TNULLn keyword if any */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status);          /* IO - error status                       */
-static int unquantize_i2r4(long row,
-            short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int dither_method,    /* I - which subtractive dither method to use */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status);          /* IO - error status                       */
-static int unquantize_i4r4(long row,
-            INT32BIT *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int dither_method,    /* I - which subtractive dither method to use */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status);          /* IO - error status                       */
-static int unquantize_i1r8(long row,
-            unsigned char *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int dither_method,    /* I - which subtractive dither method to use */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,          /* I - value of FITS TNULLn keyword if any */
-            double nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,        /* O - array of converted pixels           */
-            int *status);          /* IO - error status                       */
-static int unquantize_i2r8(long row,
-            short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int dither_method,    /* I - which subtractive dither method to use */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-            double nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,        /* O - array of converted pixels           */
-            int *status);          /* IO - error status                       */
-static int unquantize_i4r8(long row,
-            INT32BIT *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int dither_method,    /* I - which subtractive dither method to use */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-            double nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,        /* O - array of converted pixels           */
-            int *status);          /* IO - error status                       */
-static int imcomp_float2nan(float *indata, long tilelen, int *outdata,
-    float nullflagval,  int *status);
-static int imcomp_double2nan(double *indata, long tilelen, LONGLONG *outdata,
-    double nullflagval,  int *status);    
-static int fits_read_write_compressed_img(fitsfile *fptr,   /* I - FITS file pointer */
-            int  datatype,  /* I - datatype of the array to be returned      */
-            LONGLONG  *infpixel, /* I - 'bottom left corner' of the subsection    */
-            LONGLONG  *inlpixel, /* I - 'top right corner' of the subsection      */
-            long  *ininc,    /* I - increment to be applied in each dimension */
-            int  nullcheck,  /* I - 0 for no null checking                   */
-                              /*     1: set undefined pixels = nullval       */
-            void *nullval,    /* I - value for undefined pixels              */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            fitsfile *outfptr,   /* I - FITS file pointer                    */
-            int  *status);
-
-static int fits_shuffle_8bytes(char *heap, LONGLONG length, int *status);
-static int fits_shuffle_4bytes(char *heap, LONGLONG length, int *status);
-static int fits_shuffle_2bytes(char *heap, LONGLONG length, int *status);
-static int fits_unshuffle_8bytes(char *heap, LONGLONG length, int *status);
-static int fits_unshuffle_4bytes(char *heap, LONGLONG length, int *status);
-static int fits_unshuffle_2bytes(char *heap, LONGLONG length, int *status);
-
-static int fits_int_to_longlong_inplace(int *intarray, long length, int *status);
-static int fits_short_to_int_inplace(short *intarray, long length, int *status);
-static int fits_ushort_to_int_inplace(unsigned short *intarray, long length, int *status);
-static int fits_sbyte_to_int_inplace(signed char *intarray, long length, int *status);
-static int fits_ubyte_to_int_inplace(unsigned char *intarray, long length, int *status);
-
-/* only used for diagnoitic purposes */
-/* int fits_get_case(int *c1, int*c2, int*c3); */ 
-/*---------------------------------------------------------------------------*/
-int fits_init_randoms(void) {
-
-/* initialize an array of random numbers */
-
-    int ii;
-    double a = 16807.0;
-    double m = 2147483647.0;
-    double temp, seed;
-
-    FFLOCK;
- 
-    if (fits_rand_value) {
-       FFUNLOCK;
-       return(0);  /* array is already initialized */
-    }
-
-    /* allocate array for the random number sequence */
-    /* THIS MEMORY IS NEVER FREED */
-    fits_rand_value = calloc(N_RANDOM, sizeof(float));
-
-    if (!fits_rand_value) {
-        FFUNLOCK;
-	return(MEMORY_ALLOCATION);
-    }
-		       
-    /*  We need a portable algorithm that anyone can use to generate this
-        exact same sequence of random number.  The C 'rand' function is not
-	suitable because it is not available to Fortran or Java programmers.
-	Instead, use a well known simple algorithm published here: 
-	"Random number generators: good ones are hard to find", Communications of the ACM,
-        Volume 31 ,  Issue 10  (October 1988) Pages: 1192 - 1201 
-    */  
-
-    /* initialize the random numbers */
-    seed = 1;
-    for (ii = 0; ii < N_RANDOM; ii++) {
-        temp = a * seed;
-	seed = temp -m * ((int) (temp / m) );
-	fits_rand_value[ii] = (float) (seed / m);
-    }
-
-    FFUNLOCK;
-
-    /* 
-    IMPORTANT NOTE: the 10000th seed value must have the value 1043618065 if the 
-       algorithm has been implemented correctly */
-    
-    if ( (int) seed != 1043618065) {
-        ffpmsg("fits_init_randoms generated incorrect random number sequence");
-	return(1);
-    } else {
-        return(0);
-    }
-}
-/*--------------------------------------------------------------------------*/
-void bz_internal_error(int errcode)
-{
-    /* external function declared by the bzip2 code in bzlib_private.h */
-    ffpmsg("bzip2 returned an internal error");
-    ffpmsg("This should never happen");
-    return;
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_compression_type(fitsfile *fptr,  /* I - FITS file pointer     */
-       int ctype,    /* image compression type code;                        */
-                     /* allowed values: RICE_1, GZIP_1, GZIP_2, PLIO_1,     */
-                     /*  HCOMPRESS_1, BZIP2_1, and NOCOMPRESS               */
-       int *status)  /* IO - error status                                   */
-{
-/*
-   This routine specifies the image compression algorithm that should be
-   used when writing a FITS image.  The image is divided into tiles, and
-   each tile is compressed and stored in a row of at variable length binary
-   table column.
-*/
-
-    if (ctype != RICE_1 && 
-        ctype != GZIP_1 && 
-        ctype != GZIP_2 && 
-        ctype != PLIO_1 && 
-        ctype != HCOMPRESS_1 && 
-        ctype != BZIP2_1 && 
-        ctype != NOCOMPRESS &&
-	ctype != 0)
-    {
-	ffpmsg("unknown compression algorithm (fits_set_compression_type)");
-	*status = DATA_COMPRESSION_ERR; 
-    } else {
-        (fptr->Fptr)->request_compress_type = ctype;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_tile_dim(fitsfile *fptr,  /* I - FITS file pointer             */
-           int ndim,   /* number of dimensions in the compressed image      */
-           long *dims, /* size of image compression tile in each dimension  */
-                      /* default tile size = (NAXIS1, 1, 1, ...)            */
-           int *status)         /* IO - error status                        */
-{
-/*
-   This routine specifies the size (dimension) of the image
-   compression  tiles that should be used when writing a FITS
-   image.  The image is divided into tiles, and each tile is compressed
-   and stored in a row of at variable length binary table column.
-*/
-    int ii;
-
-    if (ndim < 0 || ndim > MAX_COMPRESS_DIM)
-    {
-        *status = BAD_DIMEN;
-	ffpmsg("illegal number of tile dimensions (fits_set_tile_dim)");
-        return(*status);
-    }
-
-    for (ii = 0; ii < ndim; ii++)
-    {
-        (fptr->Fptr)->request_tilesize[ii] = dims[ii];
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_quantize_level(fitsfile *fptr,  /* I - FITS file pointer   */
-           float qlevel,        /* floating point quantization level      */
-           int *status)         /* IO - error status                */
-{
-/*
-   This routine specifies the value of the quantization level, q,  that
-   should be used when compressing floating point images.  The image is
-   divided into tiles, and each tile is compressed and stored in a row
-   of at variable length binary table column.
-*/
-    if (qlevel == 0.)
-    {
-        /* this means don't quantize the floating point values. Instead, */
-	/* the floating point values will be losslessly compressed */
-       (fptr->Fptr)->request_quantize_level = NO_QUANTIZE;
-    } else {
-
-        (fptr->Fptr)->request_quantize_level = qlevel;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_quantize_method(fitsfile *fptr,  /* I - FITS file pointer   */
-           int method,          /* quantization method       */
-           int *status)         /* IO - error status                */
-{
-/*
-   This routine specifies what type of dithering (randomization) should
-   be performed when quantizing floating point images to integer prior to
-   compression.   A value of -1 means do no dithering.  A value of 0 means
-   use the default SUBTRACTIVE_DITHER_1 (which is equivalent to dither = 1).
-   A value of 2 means use SUBTRACTIVE_DITHER_2.
-*/
-
-    if (method < -1 || method > 2)
-    {
-	ffpmsg("illegal dithering value (fits_set_quantize_method)");
-	*status = DATA_COMPRESSION_ERR; 
-    } else {
-       
-        if (method == 0) method = 1;
-        (fptr->Fptr)->request_quantize_method = method;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_quantize_dither(fitsfile *fptr,  /* I - FITS file pointer   */
-           int dither,        /* dither type      */
-           int *status)         /* IO - error status                */
-{
-/*
-   the name of this routine has changed.  This is kept here only for backwards
-   compatibility for any software that may be calling the old routine.
-*/
-
-    fits_set_quantize_method(fptr, dither, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_dither_seed(fitsfile *fptr,  /* I - FITS file pointer   */
-           int seed,        /* random dithering seed value (1 to 10000) */
-           int *status)         /* IO - error status                */
-{
-/*
-   This routine specifies the value of the offset that should be applied when
-   calculating the random dithering when quantizing floating point iamges.
-   A random offset should be applied to each image to avoid quantization 
-   effects when taking the difference of 2 images, or co-adding a set of
-   images.  Without this random offset, the corresponding pixel in every image
-   will have exactly the same dithering.
-   
-   offset = 0 means use the default random dithering based on system time
-   offset = negative means randomly chose dithering based on 1st tile checksum
-   offset = [1 - 10000] means use that particular dithering pattern
-
-*/
-    /* if positive, ensure that the value is in the range 1 to 10000 */
-    if (seed > 10000) {
-	ffpmsg("illegal dithering seed value (fits_set_dither_seed)");
-	*status = DATA_COMPRESSION_ERR;
-    } else {
-       (fptr->Fptr)->request_dither_seed = seed; 
-    }
-    
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_dither_offset(fitsfile *fptr,  /* I - FITS file pointer   */
-           int offset,        /* random dithering offset value (1 to 10000) */
-           int *status)         /* IO - error status                */
-{
-/*
-    The name of this routine has changed.  This is kept just for
-    backwards compatibility with any software that calls the old name
-*/
-
-    fits_set_dither_seed(fptr, offset, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_noise_bits(fitsfile *fptr,  /* I - FITS file pointer   */
-           int noisebits,       /* noise_bits parameter value       */
-                                /* (default = 4)                    */
-           int *status)         /* IO - error status                */
-{
-/*
-   ********************************************************************
-   ********************************************************************
-   THIS ROUTINE IS PROVIDED ONLY FOR BACKWARDS COMPATIBILITY;
-   ALL NEW SOFTWARE SHOULD CALL fits_set_quantize_level INSTEAD
-   ********************************************************************
-   ********************************************************************
-
-   This routine specifies the value of the noice_bits parameter that
-   should be used when compressing floating point images.  The image is
-   divided into tiles, and each tile is compressed and stored in a row
-   of at variable length binary table column.
-
-   Feb 2008:  the "noisebits" parameter has been replaced with the more
-   general "quantize level" parameter.
-*/
-    float qlevel;
-
-    if (noisebits < 1 || noisebits > 16)
-    {
-        *status = DATA_COMPRESSION_ERR;
-	ffpmsg("illegal number of noise bits (fits_set_noise_bits)");
-        return(*status);
-    }
-
-    qlevel = (float) pow (2., (double)noisebits);
-    fits_set_quantize_level(fptr, qlevel, status);
-    
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_hcomp_scale(fitsfile *fptr,  /* I - FITS file pointer   */
-           float scale,       /* hcompress scale parameter value       */
-                                /* (default = 0.)                    */
-           int *status)         /* IO - error status                */
-{
-/*
-   This routine specifies the value of the hcompress scale parameter.
-*/
-    (fptr->Fptr)->request_hcomp_scale = scale;
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_hcomp_smooth(fitsfile *fptr,  /* I - FITS file pointer   */
-           int smooth,       /* hcompress smooth parameter value       */
-                                /* if scale > 1 and smooth != 0, then */
-				/*  the image will be smoothed when it is */
-				/* decompressed to remove some of the */
-				/* 'blockiness' in the image produced */
-				/* by the lossy compression    */
-           int *status)         /* IO - error status                */
-{
-/*
-   This routine specifies the value of the hcompress scale parameter.
-*/
-
-    (fptr->Fptr)->request_hcomp_smooth = smooth;
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_lossy_int(fitsfile *fptr,  /* I - FITS file pointer   */
-           int lossy_int,       /* I - True (!= 0) or False (0) */
-           int *status)         /* IO - error status                */
-{
-/*
-   This routine specifies whether images with integer pixel values should
-   quantized and compressed the same way float images are compressed.
-   The default is to not do this, and instead apply a lossless compression
-   algorithm to integer images.
-*/
-
-    (fptr->Fptr)->request_lossy_int_compress = lossy_int;
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_huge_hdu(fitsfile *fptr,  /* I - FITS file pointer   */
-           int huge,       /* I - True (!= 0) or False (0) */
-           int *status)         /* IO - error status                */
-{
-/*
-   This routine specifies whether the HDU that is being compressed is so large
-   (i.e., > 4 GB) that the 'Q' type variable length array columns should be used
-   rather than the normal 'P' type.  The allows the heap pointers to be stored
-   as 64-bit quantities, rather than just 32-bits.
-*/
-
-    (fptr->Fptr)->request_huge_hdu = huge;
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_get_compression_type(fitsfile *fptr,  /* I - FITS file pointer     */
-       int *ctype,   /* image compression type code;                        */
-                     /* allowed values:                                     */
-		     /* RICE_1, GZIP_1, GZIP_2, PLIO_1, HCOMPRESS_1, BZIP2_1 */
-       int *status)  /* IO - error status                                   */
-{
-/*
-   This routine returns the image compression algorithm that should be
-   used when writing a FITS image.  The image is divided into tiles, and
-   each tile is compressed and stored in a row of at variable length binary
-   table column.
-*/
-    *ctype = (fptr->Fptr)->request_compress_type;
-
-    if (*ctype != RICE_1 && 
-        *ctype != GZIP_1 && 
-        *ctype != GZIP_2 && 
-        *ctype != PLIO_1 && 
-        *ctype != HCOMPRESS_1 && 
-        *ctype != BZIP2_1 && 
-        *ctype != NOCOMPRESS &&
-	*ctype != 0   ) 
-
-    {
-	ffpmsg("unknown compression algorithm (fits_get_compression_type)");
-	*status = DATA_COMPRESSION_ERR; 
-    }
- 
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_get_tile_dim(fitsfile *fptr,  /* I - FITS file pointer             */
-           int ndim,   /* number of dimensions in the compressed image      */
-           long *dims, /* size of image compression tile in each dimension  */
-                       /* default tile size = (NAXIS1, 1, 1, ...)           */
-           int *status)         /* IO - error status                        */
-{
-/*
-   This routine returns the size (dimension) of the image
-   compression  tiles that should be used when writing a FITS
-   image.  The image is divided into tiles, and each tile is compressed
-   and stored in a row of at variable length binary table column.
-*/
-    int ii;
-
-    if (ndim < 0 || ndim > MAX_COMPRESS_DIM)
-    {
-        *status = BAD_DIMEN;
-	ffpmsg("illegal number of tile dimensions (fits_get_tile_dim)");
-        return(*status);
-    }
-
-    for (ii = 0; ii < ndim; ii++)
-    {
-        dims[ii] = (fptr->Fptr)->request_tilesize[ii];
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_unset_compression_param(
-      fitsfile *fptr,
-      int *status) 
-{
-    int ii;
-
-    (fptr->Fptr)->compress_type = 0;
-    (fptr->Fptr)->quantize_level = 0;
-    (fptr->Fptr)->quantize_method = 0;
-    (fptr->Fptr)->dither_seed = 0; 
-    (fptr->Fptr)->hcomp_scale = 0;
-
-    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-    {
-        (fptr->Fptr)->tilesize[ii] = 0;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_unset_compression_request(
-      fitsfile *fptr,
-      int *status) 
-{
-    int ii;
-
-    (fptr->Fptr)->request_compress_type = 0;
-    (fptr->Fptr)->request_quantize_level = 0;
-    (fptr->Fptr)->request_quantize_method = 0;
-    (fptr->Fptr)->request_dither_seed = 0; 
-    (fptr->Fptr)->request_hcomp_scale = 0;
-    (fptr->Fptr)->request_lossy_int_compress = 0;
-    (fptr->Fptr)->request_huge_hdu = 0;
-
-    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-    {
-        (fptr->Fptr)->request_tilesize[ii] = 0;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_set_compression_pref(
-      fitsfile *infptr,
-      fitsfile *outfptr,
-      int *status) 
-{
-/*
-   Set the preference for various compression options, based
-   on keywords in the input file that
-   provide guidance about how the HDU should be compressed when written
-   to the output file.
-*/
-
-    int ii, naxis, nkeys, comptype;
-    int  ivalue;
-    long tiledim[6]= {1,1,1,1,1,1};
-    char card[FLEN_CARD], value[FLEN_VALUE];
-    double  qvalue;
-    float hscale;
-    LONGLONG datastart, dataend; 
-    if (*status > 0)
-        return(*status);
-
-    /* check the size of the HDU that is to be compressed */
-    fits_get_hduaddrll(infptr, NULL, &datastart, &dataend, status);
-    if ( (LONGLONG)(dataend - datastart) > UINT32_MAX) {
-       /* use 64-bit '1Q' variable length columns instead of '1P' columns */
-       /* for large files, in case the heap size becomes larger than 2**32 bytes*/
-       fits_set_huge_hdu(outfptr, 1, status);
-    }
-
-    fits_get_hdrspace(infptr, &nkeys, NULL, status);
- 
-   /* look for a image compression directive keywords (begin with 'FZ') */
-    for (ii = 2; ii <= nkeys; ii++) {
-        
-	fits_read_record(infptr, ii, card, status);
-
-	if (!strncmp(card, "FZ", 2) ){
-	
-            /* get the keyword value string */
-            fits_parse_value(card, value, NULL, status);
-	    
-	    if      (!strncmp(card+2, "ALGOR", 5) ) {
-
-	        /* set the desired compression algorithm */
-                /* allowed values: RICE_1, GZIP_1, GZIP_2, PLIO_1,     */
-                /*  HCOMPRESS_1, BZIP2_1, and NOCOMPRESS               */
-
-                if        (!fits_strncasecmp(value, "'RICE_1", 7) ) {
-		    comptype = RICE_1;
-                } else if (!fits_strncasecmp(value, "'GZIP_1", 7) ) {
-		    comptype = GZIP_1;
-                } else if (!fits_strncasecmp(value, "'GZIP_2", 7) ) {
-		    comptype = GZIP_2;
-                } else if (!fits_strncasecmp(value, "'PLIO_1", 7) ) {
-		    comptype = PLIO_1;
-                } else if (!fits_strncasecmp(value, "'HCOMPRESS_1", 12) ) {
-		    comptype = HCOMPRESS_1;
-                } else if (!fits_strncasecmp(value, "'NONE", 5) ) {
-		    comptype = NOCOMPRESS;
-		} else {
-			ffpmsg("Unknown FZALGOR keyword compression algorithm:");
-			ffpmsg(value);
-			return(*status = DATA_COMPRESSION_ERR);
-		}  
-
-	        fits_set_compression_type (outfptr, comptype, status);
-
-	    } else if (!strncmp(card+2, "TILE  ", 6) ) {
-
-                if (!fits_strncasecmp(value, "'row", 4) ) {
-                   tiledim[0] = -1;
-		} else if (!fits_strncasecmp(value, "'whole", 6) ) {
-                   tiledim[0] = -1;
-                   tiledim[1] = -1;
-                   tiledim[2] = -1;
-                } else {
-		   ffdtdm(infptr, value, 0,6, &naxis, tiledim, status);
-                }
-
-	        /* set the desired tile size */
-		fits_set_tile_dim (outfptr, 6, tiledim, status);
-
-	    } else if (!strncmp(card+2, "QVALUE", 6) ) {
-
-	        /* set the desired Q quantization value */
-		qvalue = atof(value);
-		fits_set_quantize_level (outfptr, (float) qvalue, status);
-
-	    } else if (!strncmp(card+2, "QMETHD", 6) ) {
-
-                    if (!fits_strncasecmp(value, "'no_dither", 10) ) {
-                        ivalue = -1; /* just quantize, with no dithering */
-		    } else if (!fits_strncasecmp(value, "'subtractive_dither_1", 21) ) {
-                        ivalue = SUBTRACTIVE_DITHER_1; /* use subtractive dithering */
-		    } else if (!fits_strncasecmp(value, "'subtractive_dither_2", 21) ) {
-                        ivalue = SUBTRACTIVE_DITHER_2; /* dither, except preserve zero-valued pixels */
-		    } else {
-		        ffpmsg("Unknown value for FZQUANT keyword: (set_compression_pref)");
-			ffpmsg(value);
-                        return(*status = DATA_COMPRESSION_ERR);
-		    }
-
-		    fits_set_quantize_method(outfptr, ivalue, status);
-		    
-	    } else if (!strncmp(card+2, "DTHRSD", 6) ) {
-
-                if (!fits_strncasecmp(value, "'checksum", 9) ) {
-                    ivalue = -1; /* use checksum of first tile */
-		} else if (!fits_strncasecmp(value, "'clock", 6) ) {
-                    ivalue = 0; /* set dithering seed based on system clock */
-		} else {  /* read integer value */
-		    if (*value == '\'')
-                        ivalue = (int) atol(value+1); /* allow for leading quote character */
-                    else 
-                        ivalue = (int) atol(value); 
-
-                    if (ivalue < 1 || ivalue > 10000) {
-		        ffpmsg("Invalid value for FZDTHRSD keyword: (set_compression_pref)");
-			ffpmsg(value);
-                        return(*status = DATA_COMPRESSION_ERR);
-                    }
-		}
-
-	        /* set the desired dithering */
-		fits_set_dither_seed(outfptr, ivalue, status);
-
-	    } else if (!strncmp(card+2, "I2F", 3) ) {
-
-	        /* set whether to convert integers to float then use lossy compression */
-                if (!fits_strcasecmp(value, "t") ) {
-		    fits_set_lossy_int (outfptr, 1, status);
-		} else if (!fits_strcasecmp(value, "f") ) {
-		    fits_set_lossy_int (outfptr, 0, status);
-		} else {
-		        ffpmsg("Unknown value for FZI2F keyword: (set_compression_pref)");
-			ffpmsg(value);
-                        return(*status = DATA_COMPRESSION_ERR);
-                }
-
-	    } else if (!strncmp(card+2, "HSCALE ", 6) ) {
-
-	        /* set the desired Hcompress scale value */
-		hscale = (float) atof(value);
-		fits_set_hcomp_scale (outfptr, hscale, status);
-            }
-	}    
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_get_noise_bits(fitsfile *fptr,  /* I - FITS file pointer   */
-           int *noisebits,       /* noise_bits parameter value       */
-                                /* (default = 4)                    */
-           int *status)         /* IO - error status                */
-{
-/*
-   ********************************************************************
-   ********************************************************************
-   THIS ROUTINE IS PROVIDED ONLY FOR BACKWARDS COMPATIBILITY;
-   ALL NEW SOFTWARE SHOULD CALL fits_set_quantize_level INSTEAD
-   ********************************************************************
-   ********************************************************************
-
-
-   This routine returns the value of the noice_bits parameter that
-   should be used when compressing floating point images.  The image is
-   divided into tiles, and each tile is compressed and stored in a row
-   of at variable length binary table column.
-
-   Feb 2008: code changed to use the more general "quantize level" parameter
-   rather than the "noise bits" parameter.  If quantize level is greater than
-   zero, then the previous noisebits parameter is approximately given by
-   
-   noise bits = natural logarithm (quantize level) / natural log (2)
-   
-   This result is rounded to the nearest integer.
-*/
-    double qlevel;
-
-    qlevel = (fptr->Fptr)->request_quantize_level;
-
-    if (qlevel > 0. && qlevel < 65537. )
-         *noisebits =  (int) ((log(qlevel) / log(2.0)) + 0.5);
-    else 
-        *noisebits = 0;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_get_quantize_level(fitsfile *fptr,  /* I - FITS file pointer   */
-           float *qlevel,       /* quantize level parameter value       */
-           int *status)         /* IO - error status                */
-{
-/*
-   This routine returns the value of the noice_bits parameter that
-   should be used when compressing floating point images.  The image is
-   divided into tiles, and each tile is compressed and stored in a row
-   of at variable length binary table column.
-*/
-
-    if ((fptr->Fptr)->request_quantize_level == NO_QUANTIZE) {
-      *qlevel = 0;
-    } else {
-      *qlevel = (fptr->Fptr)->request_quantize_level;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_get_dither_seed(fitsfile *fptr,  /* I - FITS file pointer   */
-           int *offset,       /* dithering offset parameter value       */
-           int *status)         /* IO - error status                */
-{
-/*
-   This routine returns the value of the dithering offset parameter that
-   is used when compressing floating point images.  The image is
-   divided into tiles, and each tile is compressed and stored in a row
-   of at variable length binary table column.
-*/
-
-    *offset = (fptr->Fptr)->request_dither_seed;
-    return(*status);
-}/*--------------------------------------------------------------------------*/
-int fits_get_hcomp_scale(fitsfile *fptr,  /* I - FITS file pointer   */
-           float *scale,          /* Hcompress scale parameter value       */
-           int *status)         /* IO - error status                */
-
-{
-/*
-   This routine returns the value of the noice_bits parameter that
-   should be used when compressing floating point images.  The image is
-   divided into tiles, and each tile is compressed and stored in a row
-   of at variable length binary table column.
-*/
-
-    *scale = (fptr->Fptr)->request_hcomp_scale;
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_get_hcomp_smooth(fitsfile *fptr,  /* I - FITS file pointer   */
-           int *smooth,          /* Hcompress smooth parameter value       */
-           int *status)         /* IO - error status                */
-
-{
-    *smooth = (fptr->Fptr)->request_hcomp_smooth;
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_img_compress(fitsfile *infptr, /* pointer to image to be compressed */
-                 fitsfile *outfptr, /* empty HDU for output compressed image */
-                 int *status)       /* IO - error status               */
-
-/*
-   This routine initializes the output table, copies all the keywords,
-   and  loops through the input image, compressing the data and
-   writing the compressed tiles to the output table.
-   
-   This is a high level routine that is called by the fpack and funpack
-   FITS compression utilities.
-*/
-{
-    int bitpix, naxis;
-    long naxes[MAX_COMPRESS_DIM];
-/*    int c1, c2, c3; */
-
-    if (*status > 0)
-        return(*status);
-
-
-    /* get datatype and size of input image */
-    if (fits_get_img_param(infptr, MAX_COMPRESS_DIM, &bitpix, 
-                       &naxis, naxes, status) > 0)
-        return(*status);
-
-    if (naxis < 1 || naxis > MAX_COMPRESS_DIM)
-    {
-        ffpmsg("Image cannot be compressed: NAXIS out of range");
-        return(*status = BAD_NAXIS);
-    }
-
-    /* create a new empty HDU in the output file now, before setting the */
-    /* compression preferences.  This HDU will become a binary table that */
-    /* contains the compressed image.  If necessary, create a dummy primary */
-    /* array, which much precede the binary table extension. */
-    
-    ffcrhd(outfptr, status);  /* this does nothing if the output file is empty */
-
-    if ((outfptr->Fptr)->curhdu == 0)  /* have to create dummy primary array */
-    {
-       ffcrim(outfptr, 16, 0, NULL, status);
-       ffcrhd(outfptr, status);
-    } else {
-        /* unset any compress parameter preferences that may have been
-           set when closing the previous HDU in the output file */
-        fits_unset_compression_param(outfptr, status);
-    }
-    
-    /* set any compress parameter preferences as given in the input file */
-    fits_set_compression_pref(infptr, outfptr, status);
-
-    /* special case: the quantization level is not given by a keyword in  */
-    /* the HDU header, so we have to explicitly copy the requested value */
-    /* to the actual value */
-/* do this in imcomp_get_compressed_image_par, instead
-    if ( (outfptr->Fptr)->request_quantize_level != 0.)
-        (outfptr->Fptr)->quantize_level = (outfptr->Fptr)->request_quantize_level;
-*/
-    /* if requested, treat integer images same as a float image. */
-    /* Then the pixels will be quantized (lossy algorithm) to achieve */
-    /* higher amounts of compression than with lossless algorithms */
-
-    if ( (outfptr->Fptr)->request_lossy_int_compress != 0  && bitpix > 0) 
-	bitpix = FLOAT_IMG;  /* compress integer images as if float */
-
-    /* initialize output table */
-    if (imcomp_init_table(outfptr, bitpix, naxis, naxes, 0, status) > 0)
-        return (*status);    
-
-    /* Copy the image header keywords to the table header. */
-    if (imcomp_copy_img2comp(infptr, outfptr, status) > 0)
-	    return (*status);
-
-    /* turn off any intensity scaling (defined by BSCALE and BZERO */
-    /* keywords) so that unscaled values will be read by CFITSIO */
-    /* (except if quantizing an int image, same as a float image) */
-    if ( (outfptr->Fptr)->request_lossy_int_compress == 0 && bitpix > 0) 
-        ffpscl(infptr, 1.0, 0.0, status);
-
-    /* force a rescan of the output file keywords, so that */
-    /* the compression parameters will be copied to the internal */
-    /* fitsfile structure used by CFITSIO */
-    ffrdef(outfptr, status);
-
-    /* turn off any intensity scaling (defined by BSCALE and BZERO */
-    /* keywords) so that unscaled values will be written by CFITSIO */
-    /* (except if quantizing an int image, same as a float image) */
-    if ( (outfptr->Fptr)->request_lossy_int_compress == 0 && bitpix > 0) 
-        ffpscl(outfptr, 1.0, 0.0, status);
-
-    /* Read each image tile, compress, and write to a table row. */
-    imcomp_compress_image (infptr, outfptr, status);
-
-    /* force another rescan of the output file keywords, to */
-    /* update PCOUNT and TFORMn = '1PB(iii)' keyword values. */
-    ffrdef(outfptr, status);
-
-    /* unset any previously set compress parameter preferences */
-    fits_unset_compression_request(outfptr, status);
-
-/*
-    fits_get_case(&c1, &c2, &c3);
-    printf("c1, c2, c3 = %d, %d, %d\n", c1, c2, c3); 
-*/
-
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_init_table(fitsfile *outfptr,
-        int inbitpix,
-        int naxis,
-        long *naxes,
-	int writebitpix,    /* write the ZBITPIX, ZNAXIS, and ZNAXES keyword? */
-        int *status)
-/* 
-  create a BINTABLE extension for the output compressed image.
-*/
-{
-    char keyname[FLEN_KEYWORD], zcmptype[12];
-    int ii,  remain,  ncols, bitpix;
-    long nrows;
-    char *ttype[] = {"COMPRESSED_DATA", "ZSCALE", "ZZERO"};
-    char *tform[3];
-    char tf0[4], tf1[4], tf2[4];
-    char *tunit[] = {"\0",            "\0",            "\0"  };
-    char comm[FLEN_COMMENT];
-    long actual_tilesize[MAX_COMPRESS_DIM]; /* Actual size to use for tiles */
-    
-    if (*status > 0)
-        return(*status);
-
-    /* check for special case of losslessly compressing floating point */
-    /* images.  Only compression algorithm that supports this is GZIP */
-    if ( (outfptr->Fptr)->request_quantize_level == NO_QUANTIZE) {
-       if (((outfptr->Fptr)->request_compress_type != GZIP_1) &&
-           ((outfptr->Fptr)->request_compress_type != GZIP_2)) {
-         ffpmsg("Lossless compression of floating point images must use GZIP (imcomp_init_table)");
-         return(*status = DATA_COMPRESSION_ERR);
-       }
-    }
- 
-     /* set default compression parameter values, if undefined */
-    
-    if ( (outfptr->Fptr)->request_compress_type == 0) {
-	/* use RICE_1 by default */
-	(outfptr->Fptr)->request_compress_type = RICE_1;
-    }
-
-    if (inbitpix < 0 && (outfptr->Fptr)->request_quantize_level != NO_QUANTIZE) {  
-	/* set defaults for quantizing floating point images */
-	if ( (outfptr->Fptr)->request_quantize_method == 0) {
-	      /* set default dithering method */
-              (outfptr->Fptr)->request_quantize_method = SUBTRACTIVE_DITHER_1;
-	}
-
-	if ( (outfptr->Fptr)->request_quantize_level == 0) {
-	    if ((outfptr->Fptr)->request_quantize_method == NO_DITHER) {
-	        /* must use finer quantization if no dithering is done */
-	        (outfptr->Fptr)->request_quantize_level = 16; 
-	    } else {
-	        (outfptr->Fptr)->request_quantize_level = 4; 
-	    }
-        }
-    }
-
-    /* special case: the quantization level is not given by a keyword in  */
-    /* the HDU header, so we have to explicitly copy the requested value */
-    /* to the actual value */
-/* do this in imcomp_get_compressed_image_par, instead
-    if ( (outfptr->Fptr)->request_quantize_level != 0.)
-        (outfptr->Fptr)->quantize_level = (outfptr->Fptr)->request_quantize_level;
-*/
-    /* test for the 2 special cases that represent unsigned integers */
-    if (inbitpix == USHORT_IMG)
-        bitpix = SHORT_IMG;
-    else if (inbitpix == ULONG_IMG)
-        bitpix = LONG_IMG;
-    else if (inbitpix == SBYTE_IMG)
-        bitpix = BYTE_IMG;
-    else 
-        bitpix = inbitpix;
-
-    /* reset default tile dimensions too if required */
-    memcpy(actual_tilesize, outfptr->Fptr->request_tilesize, MAX_COMPRESS_DIM * sizeof(long));
-
-    if ((outfptr->Fptr)->request_compress_type == HCOMPRESS_1) {
-
-         if (naxis < 2 ) {
-            ffpmsg("Hcompress cannot be used with 1-dimensional images (imcomp_init_table)");
-            return(*status = DATA_COMPRESSION_ERR);
-
-	 } else if  (naxes[0] < 4 || naxes[1] < 4) {
-            ffpmsg("Hcompress minimum image dimension is 4 pixels (imcomp_init_table)");
-            return(*status = DATA_COMPRESSION_ERR);
-         }
-
-         if ((actual_tilesize[0] <= 0) &&
-             (actual_tilesize[1] == -1) ){
-	     
-	    /* compress the whole image as a single tile */
-             actual_tilesize[0] = naxes[0];
-             actual_tilesize[1] = naxes[1];
-
-              for (ii = 2; ii < naxis; ii++) {
-	             /* set all higher tile dimensions = 1 */
-                     actual_tilesize[ii] = 1;
-	      }
-
-         } else if ((actual_tilesize[0] <= 0) &&
-             (actual_tilesize[1] == 0 || actual_tilesize[1] == 1) ){
-	     
-             /*
-              The Hcompress algorithm is inherently 2D in nature, so the row by row
-	      tiling that is used for other compression algorithms is not appropriate.
-	      If the image has less than 30 rows, then the entire image will be compressed
-	      as a single tile.  Otherwise the tiles will consist of 16 rows of the image. 
-	      This keeps the tiles to a reasonable size, and it also includes enough rows
-	      to allow good compression efficiency.  If the last tile of the image 
-	      happens to contain less than 4 rows, then find another tile size with
-	      between 14 and 30 rows (preferably even), so that the last tile has 
-	      at least 4 rows
-	     */ 
-	      
-             /* 1st tile dimension is the row length of the image */
-             actual_tilesize[0] = naxes[0];
-
-              if (naxes[1] <= 30) {  /* use whole image if it is small */
-                   actual_tilesize[1] = naxes[1];
-	      } else {
-                /* look for another good tile dimension */
-	          if        (naxes[1] % 16 == 0 || naxes[1] % 16 > 3) {
-                      actual_tilesize[1] = 16;
-		  } else if (naxes[1] % 24 == 0 || naxes[1] % 24 > 3) {
-                      actual_tilesize[1] = 24;
-		  } else if (naxes[1] % 20 == 0 || naxes[1] % 20 > 3) {
-                      actual_tilesize[1] = 20;
-		  } else if (naxes[1] % 30 == 0 || naxes[1] % 30 > 3) {
-                      actual_tilesize[1] = 30;
-		  } else if (naxes[1] % 28 == 0 || naxes[1] % 28 > 3) {
-                      actual_tilesize[1] = 28;
-		  } else if (naxes[1] % 26 == 0 || naxes[1] % 26 > 3) {
-                      actual_tilesize[1] = 26;
-		  } else if (naxes[1] % 22 == 0 || naxes[1] % 22 > 3) {
-                      actual_tilesize[1] = 22;
-		  } else if (naxes[1] % 18 == 0 || naxes[1] % 18 > 3) {
-                      actual_tilesize[1] = 18;
-		  } else if (naxes[1] % 14 == 0 || naxes[1] % 14 > 3) {
-                      actual_tilesize[1] = 14;
-		  } else  {
-                      actual_tilesize[1] = 17;
-		  }
-	      }
-        } else if (actual_tilesize[0] < 4 ||
-                   actual_tilesize[1] < 4) {
-
-            /* user-specified tile size is too small */
-            ffpmsg("Hcompress minimum tile dimension is 4 pixels (imcomp_init_table)");
-            return(*status = DATA_COMPRESSION_ERR);
-	}
-	
-        /* check if requested tile size causes the last tile to to have less than 4 pixels */
-        remain = naxes[0] % (actual_tilesize[0]);  /* 1st dimension */
-        if (remain > 0 && remain < 4) {
-            (actual_tilesize[0])++; /* try increasing tile size by 1 */
-	   
-            remain = naxes[0] % (actual_tilesize[0]);
-            if (remain > 0 && remain < 4) {
-                ffpmsg("Last tile along 1st dimension has less than 4 pixels (imcomp_init_table)");
-                return(*status = DATA_COMPRESSION_ERR);	
-            }        
-        }
-
-        remain = naxes[1] % (actual_tilesize[1]);  /* 2nd dimension */
-        if (remain > 0 && remain < 4) {
-            (actual_tilesize[1])++; /* try increasing tile size by 1 */
-	   
-            remain = naxes[1] % (actual_tilesize[1]);
-            if (remain > 0 && remain < 4) {
-                ffpmsg("Last tile along 2nd dimension has less than 4 pixels (imcomp_init_table)");
-                return(*status = DATA_COMPRESSION_ERR);	
-            }        
-        }
-
-    } /* end, if HCOMPRESS_1 */
-    
-    for (ii = 0; ii < naxis; ii++) {
-	if (ii == 0) { /* first axis is different */
-	    if (actual_tilesize[ii] <= 0) {
-                actual_tilesize[ii] = naxes[ii]; 
-	    }
-	} else {
-	    if (actual_tilesize[ii] < 0) {
-                actual_tilesize[ii] = naxes[ii];  /* negative value maean use whole length */
-	    } else if (actual_tilesize[ii] == 0) {
-                actual_tilesize[ii] = 1;  /* zero value means use default value = 1 */
-	    }
-	}
-    }
-
-    /* ---- set up array of TFORM strings -------------------------------*/
-    if ( (outfptr->Fptr)->request_huge_hdu != 0) {
-        strcpy(tf0, "1QB");
-    } else {
-        strcpy(tf0, "1PB");
-    }
-    strcpy(tf1, "1D");
-    strcpy(tf2, "1D");
-
-    tform[0] = tf0;
-    tform[1] = tf1;
-    tform[2] = tf2;
-
-    /* calculate number of rows in output table */
-    nrows = 1;
-    for (ii = 0; ii < naxis; ii++)
-    {
-        nrows = nrows * ((naxes[ii] - 1)/ (actual_tilesize[ii]) + 1);
-    }
-
-    /* determine the default  number of columns in the output table */
-    if (bitpix < 0 && (outfptr->Fptr)->request_quantize_level != NO_QUANTIZE)  
-        ncols = 3;  /* quantized and scaled floating point image */
-    else
-        ncols = 1; /* default table has just one 'COMPRESSED_DATA' column */
-
-    if ((outfptr->Fptr)->request_compress_type == RICE_1)
-    {
-        strcpy(zcmptype, "RICE_1");
-    }
-    else if ((outfptr->Fptr)->request_compress_type == GZIP_1)
-    {
-        strcpy(zcmptype, "GZIP_1");
-    }
-    else if ((outfptr->Fptr)->request_compress_type == GZIP_2)
-    {
-        strcpy(zcmptype, "GZIP_2");
-    }
-    else if ((outfptr->Fptr)->request_compress_type == BZIP2_1)
-    {
-        strcpy(zcmptype, "BZIP2_1");
-    }
-    else if ((outfptr->Fptr)->request_compress_type == PLIO_1)
-    {
-        strcpy(zcmptype, "PLIO_1");
-       /* the PLIO compression algorithm outputs short integers, not bytes */
-        if ( (outfptr->Fptr)->request_huge_hdu != 0) {
-            strcpy(tform[0], "1QI");
-        } else {
-            strcpy(tform[0], "1PI");
-        }
-    }
-    else if ((outfptr->Fptr)->request_compress_type == HCOMPRESS_1)
-    {
-        strcpy(zcmptype, "HCOMPRESS_1");
-    }
-    else if ((outfptr->Fptr)->request_compress_type == NOCOMPRESS)
-    {
-        strcpy(zcmptype, "NOCOMPRESS");
-    }    
-    else
-    {
-        ffpmsg("unknown compression type (imcomp_init_table)");
-        return(*status = DATA_COMPRESSION_ERR);
-    }
-
-    /* create the bintable extension to contain the compressed image */
-    ffcrtb(outfptr, BINARY_TBL, nrows, ncols, ttype, 
-                tform, tunit, 0, status);
-
-    /* Add standard header keywords. */
-    ffpkyl (outfptr, "ZIMAGE", 1, 
-           "extension contains compressed image", status);  
-
-    if (writebitpix) {
-        /*  write the keywords defining the datatype and dimensions of */
-	/*  the uncompressed image.  If not, these keywords will be */
-        /*  copied later from the input uncompressed image  */
-	   
-        ffpkyl (outfptr, "ZSIMPLE", 1,
-			"file does conform to FITS standard", status);
-        ffpkyj (outfptr, "ZBITPIX", bitpix,
-			"data type of original image", status);
-        ffpkyj (outfptr, "ZNAXIS", naxis,
-			"dimension of original image", status);
-
-        for (ii = 0;  ii < naxis;  ii++)
-        {
-            sprintf (keyname, "ZNAXIS%d", ii+1);
-            ffpkyj (outfptr, keyname, naxes[ii],
-			"length of original image axis", status);
-        }
-    }
-                      
-    for (ii = 0;  ii < naxis;  ii++)
-    {
-        sprintf (keyname, "ZTILE%d", ii+1);
-        ffpkyj (outfptr, keyname, actual_tilesize[ii],
-			"size of tiles to be compressed", status);
-    }
-
-    if (bitpix < 0) {
-       
-	if ((outfptr->Fptr)->request_quantize_level == NO_QUANTIZE) {
-	    ffpkys(outfptr, "ZQUANTIZ", "NONE", 
-	      "Lossless compression without quantization", status);
-	} else {
-	    
-	    /* Unless dithering has been specifically turned off by setting */
-	    /* request_quantize_method = -1, use dithering by default */
-	    /* when quantizing floating point images. */
-	
-	    if ( (outfptr->Fptr)->request_quantize_method == 0) 
-              (outfptr->Fptr)->request_quantize_method = SUBTRACTIVE_DITHER_1;
-       
-	    if ((outfptr->Fptr)->request_quantize_method == SUBTRACTIVE_DITHER_1) {
-	      ffpkys(outfptr, "ZQUANTIZ", "SUBTRACTIVE_DITHER_1", 
-	        "Pixel Quantization Algorithm", status);
-
-	      /* also write the associated ZDITHER0 keyword with a default value */
-	      /* which may get updated later. */
-              ffpky(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->request_dither_seed), 
-	       "dithering offset when quantizing floats", status);
- 
-            } else if ((outfptr->Fptr)->request_quantize_method == SUBTRACTIVE_DITHER_2) {
-	      ffpkys(outfptr, "ZQUANTIZ", "SUBTRACTIVE_DITHER_2", 
-	        "Pixel Quantization Algorithm", status);
-
-	      /* also write the associated ZDITHER0 keyword with a default value */
-	      /* which may get updated later. */
-              ffpky(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->request_dither_seed), 
-	       "dithering offset when quantizing floats", status);
-
-	      if (!strcmp(zcmptype, "RICE_1"))  {
-	        /* when using this new dithering method, change the compression type */
-		/* to an alias, so that old versions of funpack will not be able to */
-		/* created a corrupted uncompressed image. */
-		/* ******* can remove this cludge after about June 2015, after most old versions of fpack are gone */
-        	strcpy(zcmptype, "RICE_ONE");
-	      }
-
-            } else if ((outfptr->Fptr)->request_quantize_method == NO_DITHER) {
-	      ffpkys(outfptr, "ZQUANTIZ", "NO_DITHER", 
-	        "No dithering during quantization", status);
-	    }
-
-	}
-    }
-
-    ffpkys (outfptr, "ZCMPTYPE", zcmptype,
-	          "compression algorithm", status);
-
-    /* write any algorithm-specific keywords */
-    if ((outfptr->Fptr)->request_compress_type == RICE_1)
-    {
-        ffpkys (outfptr, "ZNAME1", "BLOCKSIZE",
-            "compression block size", status);
-
-        /* for now at least, the block size is always 32 */
-        ffpkyj (outfptr, "ZVAL1", 32,
-			"pixels per block", status);
-
-        ffpkys (outfptr, "ZNAME2", "BYTEPIX",
-            "bytes per pixel (1, 2, 4, or 8)", status);
-
-        if (bitpix == BYTE_IMG)
-            ffpkyj (outfptr, "ZVAL2", 1,
-			"bytes per pixel (1, 2, 4, or 8)", status);
-        else if (bitpix == SHORT_IMG)
-            ffpkyj (outfptr, "ZVAL2", 2,
-			"bytes per pixel (1, 2, 4, or 8)", status);
-        else 
-            ffpkyj (outfptr, "ZVAL2", 4,
-			"bytes per pixel (1, 2, 4, or 8)", status);
-
-    }
-    else if ((outfptr->Fptr)->request_compress_type == HCOMPRESS_1)
-    {
-        ffpkys (outfptr, "ZNAME1", "SCALE",
-            "HCOMPRESS scale factor", status);
-        ffpkye (outfptr, "ZVAL1", (outfptr->Fptr)->request_hcomp_scale,
-		7, "HCOMPRESS scale factor", status);
-
-        ffpkys (outfptr, "ZNAME2", "SMOOTH",
-            "HCOMPRESS smooth option", status);
-        ffpkyj (outfptr, "ZVAL2", (long) (outfptr->Fptr)->request_hcomp_smooth,
-			"HCOMPRESS smooth option", status);
-    }
-
-    /* Write the BSCALE and BZERO keywords, if an unsigned integer image */
-    if (inbitpix == USHORT_IMG)
-    {
-        strcpy(comm, "offset data range to that of unsigned short");
-        ffpkyg(outfptr, "BZERO", 32768., 0, comm, status);
-        strcpy(comm, "default scaling factor");
-        ffpkyg(outfptr, "BSCALE", 1.0, 0, comm, status);
-    }
-    else if (inbitpix == SBYTE_IMG)
-    {
-        strcpy(comm, "offset data range to that of signed byte");
-        ffpkyg(outfptr, "BZERO", -128., 0, comm, status);
-        strcpy(comm, "default scaling factor");
-        ffpkyg(outfptr, "BSCALE", 1.0, 0, comm, status);
-    }
-    else if (inbitpix == ULONG_IMG)
-    {
-        strcpy(comm, "offset data range to that of unsigned long");
-        ffpkyg(outfptr, "BZERO", 2147483648., 0, comm, status);
-        strcpy(comm, "default scaling factor");
-        ffpkyg(outfptr, "BSCALE", 1.0, 0, comm, status);
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_calc_max_elem (int comptype, int nx, int zbitpix, int blocksize)
-
-/* This function returns the maximum number of bytes in a compressed
-   image line.
-
-    nx = maximum number of pixels in a tile
-    blocksize is only relevant for RICE compression
-*/
-{    
-    if (comptype == RICE_1)
-    {
-        if (zbitpix == 16)
-            return (sizeof(short) * nx + nx / blocksize + 2 + 4);
-	else
-            return (sizeof(float) * nx + nx / blocksize + 2 + 4);
-    }
-    else if ((comptype == GZIP_1) || (comptype == GZIP_2))
-    {
-        /* gzip usually compressed by at least a factor of 2 for I*4 images */
-        /* and somewhat less for I*2 images */
-        /* If this size turns out to be too small, then the gzip */
-        /* compression routine will allocate more space as required */
-        /* to be on the safe size, allocate buffer same size as input */
-	
-        if (zbitpix == 16)
-            return(nx * 2);
-	else if (zbitpix == 8)
-            return(nx);
-	else
-            return(nx * 4);
-    }
-    else if (comptype == BZIP2_1)
-    {
-        /* To guarantee that the compressed data will fit, allocate an output
-	   buffer of size 1% larger than the uncompressed data, plus 600 bytes */
-
-            return((int) (nx * 1.01 * zbitpix / 8. + 601.));
-    }
-     else if (comptype == HCOMPRESS_1)
-    {
-        /* Imperical evidence suggests in the worst case, 
-	   the compressed stream could be up to 10% larger than the original
-	   image.  Add 26 byte overhead, only significant for very small tiles
-	   
-         Possible improvement: may need to allow a larger size for 32-bit images */
-
-        if (zbitpix == 16 || zbitpix == 8)
-	
-            return( (int) (nx * 2.2 + 26));   /* will be compressing 16-bit int array */
-        else
-            return( (int) (nx * 4.4 + 26));   /* will be compressing 32-bit int array */
-    }
-    else
-        return(nx * sizeof(int));
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_compress_image (fitsfile *infptr, fitsfile *outfptr, int *status)
-
-/* This routine does the following:
-        - reads an image one tile at a time
-        - if it is a float or double image, then it tries to quantize the pixels
-          into scaled integers.
-        - it then compressess the integer pixels, or if the it was not
-	  possible to quantize the floating point pixels, then it losslessly
-	  compresses them with gzip
-	- writes the compressed byte stream to the output FITS file
-*/
-{
-    double *tiledata;
-    int anynul, gotnulls = 0, datatype;
-    long ii, row;
-    int naxis;
-    double dummy = 0., dblnull = DOUBLENULLVALUE;
-    float fltnull = FLOATNULLVALUE;
-    long maxtilelen, tilelen, incre[] = {1, 1, 1, 1, 1, 1};
-    long naxes[MAX_COMPRESS_DIM], fpixel[MAX_COMPRESS_DIM];
-    long lpixel[MAX_COMPRESS_DIM], tile[MAX_COMPRESS_DIM];
-    long tilesize[MAX_COMPRESS_DIM];
-    long i0, i1, i2, i3, i4, i5;
-    char card[FLEN_CARD];
-
-    if (*status > 0)
-        return(*status);
-
-    maxtilelen = (outfptr->Fptr)->maxtilelen;
-
-    /* 
-     Allocate buffer to hold 1 tile of data; size depends on which compression 
-     algorithm is used:
-
-      Rice and GZIP will compress byte, short, or int arrays without conversion.
-      PLIO requires 4-byte int values, so byte and short arrays must be converted to int.
-      HCompress internally converts byte or short values to ints, and
-         converts int values to 8-byte longlong integers.
-    */
-    
-    if ((outfptr->Fptr)->zbitpix == FLOAT_IMG)
-    {
-        datatype = TFLOAT;
-
-        if ( (outfptr->Fptr)->compress_type == HCOMPRESS_1) {
-	    /* need twice as much scratch space (8 bytes per pixel) */
-            tiledata = (double*) malloc (maxtilelen * 2 *sizeof (float));	
-	} else {
-            tiledata = (double*) malloc (maxtilelen * sizeof (float));
-	}
-    }
-    else if ((outfptr->Fptr)->zbitpix == DOUBLE_IMG)
-    {
-        datatype = TDOUBLE;
-        tiledata = (double*) malloc (maxtilelen * sizeof (double));
-    }
-    else if ((outfptr->Fptr)->zbitpix == SHORT_IMG)
-    {
-        datatype = TSHORT;
-        if ( (outfptr->Fptr)->compress_type == RICE_1  ||
-	     (outfptr->Fptr)->compress_type == GZIP_1  ||
-	     (outfptr->Fptr)->compress_type == GZIP_2  ||
-	     (outfptr->Fptr)->compress_type == BZIP2_1 ||
-             (outfptr->Fptr)->compress_type == NOCOMPRESS) {
-	    /* only need  buffer of I*2 pixels for gzip, bzip2, and Rice */
-
-            tiledata = (double*) malloc (maxtilelen * sizeof (short));	
-	} else {
- 	    /*  need  buffer of I*4 pixels for Hcompress and PLIO */
-            tiledata = (double*) malloc (maxtilelen * sizeof (int));
-        }
-    }
-    else if ((outfptr->Fptr)->zbitpix == BYTE_IMG)
-    {
-
-        datatype = TBYTE;
-        if ( (outfptr->Fptr)->compress_type == RICE_1  ||
-	     (outfptr->Fptr)->compress_type == BZIP2_1 ||
-	     (outfptr->Fptr)->compress_type == GZIP_1  ||
-	     (outfptr->Fptr)->compress_type == GZIP_2) {
-	    /* only need  buffer of I*1 pixels for gzip, bzip2, and Rice */
-
-            tiledata = (double*) malloc (maxtilelen);	
-	} else {
- 	    /*  need  buffer of I*4 pixels for Hcompress and PLIO */
-            tiledata = (double*) malloc (maxtilelen * sizeof (int));
-        }
-    }
-    else if ((outfptr->Fptr)->zbitpix == LONG_IMG)
-    {
-        datatype = TINT;
-        if ( (outfptr->Fptr)->compress_type == HCOMPRESS_1) {
-	    /* need twice as much scratch space (8 bytes per pixel) */
-
-            tiledata = (double*) malloc (maxtilelen * 2 * sizeof (int));	
-	} else {
- 	    /* only need  buffer of I*4 pixels for gzip, bzip2,  Rice, and PLIO */
-
-            tiledata = (double*) malloc (maxtilelen * sizeof (int));
-        }
-    }
-    else
-    {
-	ffpmsg("Bad image datatype. (imcomp_compress_image)");
-	return (*status = MEMORY_ALLOCATION);
-    }
-    
-    if (tiledata == NULL)
-    {
-	ffpmsg("Out of memory. (imcomp_compress_image)");
-	return (*status = MEMORY_ALLOCATION);
-    }
-
-    /*  calculate size of tile in each dimension */
-    naxis = (outfptr->Fptr)->zndim;
-    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-    {
-        if (ii < naxis)
-        {
-             naxes[ii] = (outfptr->Fptr)->znaxis[ii];
-             tilesize[ii] = (outfptr->Fptr)->tilesize[ii];
-        }
-        else
-        {
-            naxes[ii] = 1;
-            tilesize[ii] = 1;
-        }
-    }
-    row = 1;
-
-    /* set up big loop over up to 6 dimensions */
-    for (i5 = 1; i5 <= naxes[5]; i5 += tilesize[5])
-    {
-     fpixel[5] = i5;
-     lpixel[5] = minvalue(i5 + tilesize[5] - 1, naxes[5]);
-     tile[5] = lpixel[5] - fpixel[5] + 1;
-     for (i4 = 1; i4 <= naxes[4]; i4 += tilesize[4])
-     {
-      fpixel[4] = i4;
-      lpixel[4] = minvalue(i4 + tilesize[4] - 1, naxes[4]);
-      tile[4] = lpixel[4] - fpixel[4] + 1;
-      for (i3 = 1; i3 <= naxes[3]; i3 += tilesize[3])
-      {
-       fpixel[3] = i3;
-       lpixel[3] = minvalue(i3 + tilesize[3] - 1, naxes[3]);
-       tile[3] = lpixel[3] - fpixel[3] + 1;
-       for (i2 = 1; i2 <= naxes[2]; i2 += tilesize[2])
-       {
-        fpixel[2] = i2;
-        lpixel[2] = minvalue(i2 + tilesize[2] - 1, naxes[2]);
-        tile[2] = lpixel[2] - fpixel[2] + 1;
-        for (i1 = 1; i1 <= naxes[1]; i1 += tilesize[1])
-        {
-         fpixel[1] = i1;
-         lpixel[1] = minvalue(i1 + tilesize[1] - 1, naxes[1]);
-         tile[1] = lpixel[1] - fpixel[1] + 1;
-         for (i0 = 1; i0 <= naxes[0]; i0 += tilesize[0])
-         {
-          fpixel[0] = i0;
-          lpixel[0] = minvalue(i0 + tilesize[0] - 1, naxes[0]);
-          tile[0] = lpixel[0] - fpixel[0] + 1;
-
-          /* number of pixels in this tile */
-          tilelen = tile[0];
-          for (ii = 1; ii < naxis; ii++)
-          {
-             tilelen *= tile[ii];
-          }
-
-          /* read next tile of data from image */
-	  anynul = 0;
-          if (datatype == TFLOAT)
-          {
-              ffgsve(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 
-                  FLOATNULLVALUE, (float *) tiledata,  &anynul, status);
-          }
-          else if (datatype == TDOUBLE)
-          {
-              ffgsvd(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 
-                  DOUBLENULLVALUE, tiledata, &anynul, status);
-          }
-          else if (datatype == TINT)
-          {
-              ffgsvk(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 
-                  0, (int *) tiledata,  &anynul, status);
-          }
-          else if (datatype == TSHORT)
-          {
-              ffgsvi(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 
-                  0, (short *) tiledata,  &anynul, status);
-          }
-          else if (datatype == TBYTE)
-          {
-              ffgsvb(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 
-                  0, (unsigned char *) tiledata,  &anynul, status);
-          }
-          else 
-          {
-              ffpmsg("Error bad datatype of image tile to compress");
-              free(tiledata);
-              return (*status);
-          }
-
-          /* now compress the tile, and write to row of binary table */
-          /*   NOTE: we don't have to worry about the presence of null values in the
-	       array if it is an integer array:  the null value is simply encoded
-	       in the compressed array just like any other pixel value.  
-	       
-	       If it is a floating point array, then we need to check for null
-	       only if the anynul parameter returned a true value when reading the tile
-	  */
-          if (anynul && datatype == TFLOAT) {
-              imcomp_compress_tile(outfptr, row, datatype, tiledata, tilelen,
-                               tile[0], tile[1], 1, &fltnull, status);
-          } else if (anynul && datatype == TDOUBLE) {
-              imcomp_compress_tile(outfptr, row, datatype, tiledata, tilelen,
-                               tile[0], tile[1], 1, &dblnull, status);
-          } else {
-              imcomp_compress_tile(outfptr, row, datatype, tiledata, tilelen,
-                               tile[0], tile[1], 0, &dummy, status);
-          }
-
-          /* set flag if we found any null values */
-          if (anynul)
-              gotnulls = 1;
-
-          /* check for any error in the previous operations */
-          if (*status > 0)
-          {
-              ffpmsg("Error writing compressed image to table");
-              free(tiledata);
-              return (*status);
-          }
-
-	  row++;
-         }
-        }
-       }
-      }
-     }
-    }
-
-    free (tiledata);  /* finished with this buffer */
-
-    /* insert ZBLANK keyword if necessary; only for TFLOAT or TDOUBLE images */
-    if (gotnulls)
-    {
-          ffgcrd(outfptr, "ZCMPTYPE", card, status);
-          ffikyj(outfptr, "ZBLANK", COMPRESS_NULL_VALUE, 
-             "null value in the compressed integer array", status);
-    }
-
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_compress_tile (fitsfile *outfptr,
-    long row,  /* tile number = row in the binary table that holds the compressed data */
-    int datatype, 
-    void *tiledata, 
-    long tilelen,
-    long tilenx,
-    long tileny,
-    int nullcheck,
-    void *nullflagval,
-    int *status)
-
-/*
-   This is the main compression routine.
-
-   This routine does the following to the input tile of pixels:
-        - if it is a float or double image, then it quantizes the pixels
-        - compresses the integer pixel values
-        - writes the compressed byte stream to the FITS file.
-
-   If the tile cannot be quantized than the raw float or double values
-   are losslessly compressed with gzip and then written to the output table.
-   
-   This input array may be modified by this routine.  If the array is of type TINT
-   or TFLOAT, and the compression type is HCOMPRESS, then it must have been 
-   allocated to be twice as large (8 bytes per pixel) to provide scratch space.
-
-  Note that this routine does not fully support the implicit datatype conversion that
-  is supported when writing to normal FITS images.  The datatype of the input array
-  must have the same datatype (either signed or unsigned) as the output (compressed)
-  FITS image in some cases.
-*/
-{
-    int *idata;		/* quantized integer data */
-    int cn_zblank, zbitpix, nullval;
-    int flag = 1;  /* true by default; only = 0 if float data couldn't be quantized */
-    int intlength;      /* size of integers to be compressed */
-    double scale, zero, actual_bzero;
-    long ii;
-    size_t clen;		/* size of cbuf */
-    short *cbuf;	/* compressed data */
-    int  nelem = 0;		/* number of bytes */
-    int tilecol;
-    size_t gzip_nelem = 0;
-    unsigned int bzlen;
-    int ihcompscale;
-    float hcompscale;
-    double noise2, noise3, noise5;
-    double bscale[1] = {1.}, bzero[1] = {0.};	/* scaling parameters */
-    long  hcomp_len;
-    LONGLONG *lldata;
-
-    if (*status > 0)
-        return(*status);
-
-    /* check for special case of losslessly compressing floating point */
-    /* images.  Only compression algorithm that supports this is GZIP */
-    if ( (outfptr->Fptr)->quantize_level == NO_QUANTIZE) {
-       if (((outfptr->Fptr)->compress_type != GZIP_1) &&
-           ((outfptr->Fptr)->compress_type != GZIP_2)) {
-         ffpmsg("Lossless compression of floating point images must use GZIP (imcomp_compress_tile)");
-         return(*status = DATA_COMPRESSION_ERR);
-       }
-    }
-
-    /* free the previously saved tile if the input tile is for the same row */
-    if ((outfptr->Fptr)->tilerow) {  /* has the tile cache been allocated? */
-
-      /* calculate the column bin of the compressed tile */
-      tilecol = (row - 1) % ((long)(((outfptr->Fptr)->znaxis[0] - 1) / ((outfptr->Fptr)->tilesize[0])) + 1);
-      
-      if ((outfptr->Fptr)->tilerow[tilecol] == row) {
-        if (((outfptr->Fptr)->tiledata)[tilecol]) {
-            free(((outfptr->Fptr)->tiledata)[tilecol]);
-        }
-	  
-        if (((outfptr->Fptr)->tilenullarray)[tilecol]) {
-            free(((outfptr->Fptr)->tilenullarray)[tilecol]);
-        }
-
-        ((outfptr->Fptr)->tiledata)[tilecol] = 0;
-        ((outfptr->Fptr)->tilenullarray)[tilecol] = 0;
-        (outfptr->Fptr)->tilerow[tilecol] = 0;
-        (outfptr->Fptr)->tiledatasize[tilecol] = 0;
-        (outfptr->Fptr)->tiletype[tilecol] = 0;
-        (outfptr->Fptr)->tileanynull[tilecol] = 0;
-      }
-    }
-
-    if ( (outfptr->Fptr)->compress_type == NOCOMPRESS) {
-         /* Special case when using NOCOMPRESS for diagnostic purposes in fpack */
-         if (imcomp_write_nocompress_tile(outfptr, row, datatype, tiledata, tilelen, 
-	     nullcheck, nullflagval, status) > 0) {
-             return(*status);
-         }
-         return(*status);
-    }
-
-    /* =========================================================================== */
-    /* initialize various parameters */
-    idata = (int *) tiledata;   /* may overwrite the input tiledata in place */
-
-    /* zbitpix is the BITPIX keyword value in the uncompressed FITS image */
-    zbitpix = (outfptr->Fptr)->zbitpix;
-
-    /* if the tile/image has an integer datatype, see if a null value has */
-    /* been defined (with the BLANK keyword in a normal FITS image).  */
-    /* If so, and if the input tile array also contains null pixels, */
-    /* (represented by pixels that have a value = nullflagval) then  */
-    /* any pixels whose value = nullflagval, must be set to the value = nullval */
-    /* before the pixel array is compressed.  These null pixel values must */
-    /* not be inverse scaled by the BSCALE/BZERO values, if present. */
-
-    cn_zblank = (outfptr->Fptr)->cn_zblank;
-    nullval = (outfptr->Fptr)->zblank;
-
-    if (zbitpix > 0 && cn_zblank != -1)  /* If the integer image has no defined null */
-        nullcheck = 0;    /* value, then don't bother checking input array for nulls. */
-
-    /* if the BSCALE and BZERO keywords exist, then the input values must */
-    /* be inverse scaled by this factor, before the values are compressed. */
-    /* (The program may have turned off scaling, which over rides the keywords) */
-    
-    scale = (outfptr->Fptr)->cn_bscale;
-    zero  = (outfptr->Fptr)->cn_bzero;
-    actual_bzero = (outfptr->Fptr)->cn_actual_bzero;
-
-    /* =========================================================================== */
-    /* prepare the tile of pixel values for compression */
-    if (datatype == TSHORT) {
-       imcomp_convert_tile_tshort(outfptr, tiledata, tilelen, nullcheck, nullflagval,
-           nullval, zbitpix, scale, zero, actual_bzero, &intlength, status);
-    } else if (datatype == TUSHORT) {
-       imcomp_convert_tile_tushort(outfptr, tiledata, tilelen, nullcheck, nullflagval,
-           nullval, zbitpix, scale, zero, &intlength, status);
-    } else if (datatype == TBYTE) {
-       imcomp_convert_tile_tbyte(outfptr, tiledata, tilelen, nullcheck, nullflagval,
-           nullval, zbitpix, scale, zero,  &intlength, status);
-    } else if (datatype == TSBYTE) {
-       imcomp_convert_tile_tsbyte(outfptr, tiledata, tilelen, nullcheck, nullflagval,
-           nullval, zbitpix, scale, zero,  &intlength, status);
-    } else if (datatype == TINT) {
-       imcomp_convert_tile_tint(outfptr, tiledata, tilelen, nullcheck, nullflagval,
-           nullval, zbitpix, scale, zero, &intlength, status);
-    } else if (datatype == TUINT) {
-       imcomp_convert_tile_tuint(outfptr, tiledata, tilelen, nullcheck, nullflagval,
-           nullval, zbitpix, scale, zero, &intlength, status);
-    } else if (datatype == TLONG && sizeof(long) == 8) {
-           ffpmsg("Integer*8 Long datatype is not supported when writing to compressed images");
-           return(*status = BAD_DATATYPE);
-    } else if (datatype == TULONG && sizeof(long) == 8) {
-           ffpmsg("Unsigned integer*8 datatype is not supported when writing to compressed images");
-           return(*status = BAD_DATATYPE);
-    } else if (datatype == TFLOAT) {
-        imcomp_convert_tile_tfloat(outfptr, row, tiledata, tilelen, tilenx, tileny, nullcheck,
-        nullflagval, nullval, zbitpix, scale, zero, &intlength, &flag, bscale, bzero, status);
-    } else if (datatype == TDOUBLE) {
-       imcomp_convert_tile_tdouble(outfptr, row, tiledata, tilelen, tilenx, tileny, nullcheck,
-       nullflagval, nullval, zbitpix, scale, zero, &intlength, &flag, bscale, bzero, status);
-    } else {
-          ffpmsg("unsupported image datatype (imcomp_compress_tile)");
-          return(*status = BAD_DATATYPE);
-    }
-
-    if (*status > 0)
-      return(*status);      /* return if error occurs */
-
-    /* =========================================================================== */
-    if (flag)   /* now compress the integer data array */
-    {
-        /* allocate buffer for the compressed tile bytes */
-        clen = (outfptr->Fptr)->maxelem;
-        cbuf = (short *) calloc (clen, sizeof (unsigned char));
-
-        if (cbuf == NULL) {
-            ffpmsg("Memory allocation failure. (imcomp_compress_tile)");
-	    return (*status = MEMORY_ALLOCATION);
-        }
-
-        /* =========================================================================== */
-        if ( (outfptr->Fptr)->compress_type == RICE_1)
-        {
-            if (intlength == 2) {
-  	        nelem = fits_rcomp_short ((short *)idata, tilelen, (unsigned char *) cbuf,
-                       clen, (outfptr->Fptr)->rice_blocksize);
-            } else if (intlength == 1) {
-  	        nelem = fits_rcomp_byte ((signed char *)idata, tilelen, (unsigned char *) cbuf,
-                       clen, (outfptr->Fptr)->rice_blocksize);
-            } else {
-  	        nelem = fits_rcomp (idata, tilelen, (unsigned char *) cbuf,
-                       clen, (outfptr->Fptr)->rice_blocksize);
-            }
-
-	    if (nelem < 0)  /* data compression error condition */
-            {
-	        free (cbuf);
-                ffpmsg("error Rice compressing image tile (imcomp_compress_tile)");
-                return (*status = DATA_COMPRESSION_ERR);
-            }
-
-	    /* Write the compressed byte stream. */
-            ffpclb(outfptr, (outfptr->Fptr)->cn_compressed, row, 1,
-                     nelem, (unsigned char *) cbuf, status);
-        }
-
-        /* =========================================================================== */
-        else if ( (outfptr->Fptr)->compress_type == PLIO_1)
-        {
-              for (ii = 0; ii < tilelen; ii++)  {
-                if (idata[ii] < 0 || idata[ii] > 16777215)
-                {
-                   /* plio algorithn only supports positive 24 bit ints */
-                   ffpmsg("data out of range for PLIO compression (0 - 2**24)");
-                   return(*status = DATA_COMPRESSION_ERR);
-                }
-              }
-
-  	      nelem = pl_p2li (idata, 1, cbuf, tilelen);
-
-	      if (nelem < 0)  /* data compression error condition */
-              {
-	        free (cbuf);
-                ffpmsg("error PLIO compressing image tile (imcomp_compress_tile)");
-                return (*status = DATA_COMPRESSION_ERR);
-              }
-
-	      /* Write the compressed byte stream. */
-              ffpcli(outfptr, (outfptr->Fptr)->cn_compressed, row, 1,
-                     nelem, cbuf, status);
-        }
-
-        /* =========================================================================== */
-        else if ( ((outfptr->Fptr)->compress_type == GZIP_1) ||
-                  ((outfptr->Fptr)->compress_type == GZIP_2) )   {
-
-	    if ((outfptr->Fptr)->quantize_level == NO_QUANTIZE && datatype == TFLOAT) {
-	      /* Special case of losslessly compressing floating point pixels with GZIP */
-	      /* In this case we compress the input tile array directly */
-
-#if BYTESWAPPED
-               ffswap4((int*) tiledata, tilelen); 
-#endif
-               if ( (outfptr->Fptr)->compress_type == GZIP_2 )
-		    fits_shuffle_4bytes((char *) tiledata, tilelen, status);
-
-                compress2mem_from_mem((char *) tiledata, tilelen * sizeof(float),
-                    (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);
-
-	    } else if ((outfptr->Fptr)->quantize_level == NO_QUANTIZE && datatype == TDOUBLE) {
-	      /* Special case of losslessly compressing double pixels with GZIP */
-	      /* In this case we compress the input tile array directly */
-
-#if BYTESWAPPED
-               ffswap8((double *) tiledata, tilelen); 
-#endif
-               if ( (outfptr->Fptr)->compress_type == GZIP_2 )
-		    fits_shuffle_8bytes((char *) tiledata, tilelen, status);
-
-                compress2mem_from_mem((char *) tiledata, tilelen * sizeof(double),
-                    (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);
-
-	    } else {
-
-	        /* compress the integer idata array */
-
-#if BYTESWAPPED
-	       if (intlength == 2)
-                 ffswap2((short *) idata, tilelen); 
-	       else if (intlength == 4)
-                 ffswap4(idata, tilelen); 
-#endif
-
-               if (intlength == 2) {
-
-                  if ( (outfptr->Fptr)->compress_type == GZIP_2 )
-		    fits_shuffle_2bytes((char *) tiledata, tilelen, status);
-
-                  compress2mem_from_mem((char *) idata, tilelen * sizeof(short),
-                   (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);
-
-               } else if (intlength == 1) {
-
-                  compress2mem_from_mem((char *) idata, tilelen * sizeof(unsigned char),
-                   (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);
-
-               } else {
-
-                  if ( (outfptr->Fptr)->compress_type == GZIP_2 )
-		    fits_shuffle_4bytes((char *) tiledata, tilelen, status);
-
-                  compress2mem_from_mem((char *) idata, tilelen * sizeof(int),
-                   (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);
-               }
-            }
-
-	    /* Write the compressed byte stream. */
-            ffpclb(outfptr, (outfptr->Fptr)->cn_compressed, row, 1,
-                     gzip_nelem, (unsigned char *) cbuf, status);
-
-        /* =========================================================================== */
-        } else if ( (outfptr->Fptr)->compress_type == BZIP2_1) {
-
-#if BYTESWAPPED
-	   if (intlength == 2)
-               ffswap2((short *) idata, tilelen); 
-	   else if (intlength == 4)
-               ffswap4(idata, tilelen); 
-#endif
-
-           bzlen = (unsigned int) clen;
-	   
-           /* call bzip2 with blocksize = 900K, verbosity = 0, and default workfactor */
-
-/*  bzip2 is not supported in the public release.  This is only for test purposes.
-           if (BZ2_bzBuffToBuffCompress( (char *) cbuf, &bzlen,
-	         (char *) idata, (unsigned int) (tilelen * intlength), 9, 0, 0) ) 
-*/
-	   {
-                   ffpmsg("bzip2 compression error");
-                   return(*status = DATA_COMPRESSION_ERR);
-           }
-
-	    /* Write the compressed byte stream. */
-            ffpclb(outfptr, (outfptr->Fptr)->cn_compressed, row, 1,
-                     bzlen, (unsigned char *) cbuf, status);
-
-        /* =========================================================================== */
-        }  else if ( (outfptr->Fptr)->compress_type == HCOMPRESS_1)     {
-	    /*
-	      if hcompscale is positive, then we have to multiply
-	      the value by the RMS background noise to get the 
-	      absolute scale value.  If negative, then it gives the
-	      absolute scale value directly.
-	    */
-            hcompscale = (outfptr->Fptr)->hcomp_scale;
-
-	    if (hcompscale > 0.) {
-	       fits_img_stats_int(idata, tilenx, tileny, nullcheck,
-	                nullval, 0,0,0,0,0,0,&noise2,&noise3,&noise5,status);
-
-		/* use the minimum of the 3 noise estimates */
-		if (noise2 != 0. && noise2 < noise3) noise3 = noise2;
-		if (noise5 != 0. && noise5 < noise3) noise3 = noise5;
-		
-		hcompscale = (float) (hcompscale * noise3);
-
-	    } else if (hcompscale < 0.) {
-
-		hcompscale = hcompscale * -1.0F;
-	    }
-
-	    ihcompscale = (int) (hcompscale + 0.5);
-
-            hcomp_len = clen;  /* allocated size of the buffer */
-	    
-            if (zbitpix == BYTE_IMG || zbitpix == SHORT_IMG) {
-                fits_hcompress(idata, tilenx, tileny, 
-		  ihcompscale, (char *) cbuf, &hcomp_len, status);
-
-            } else {
-                 /* have to convert idata to an I*8 array, in place */
-                 /* idata must have been allocated large enough to do this */
-
-                fits_int_to_longlong_inplace(idata, tilelen, status);
-                lldata = (LONGLONG *) idata;		
-
-                fits_hcompress64(lldata, tilenx, tileny, 
-		  ihcompscale, (char *) cbuf, &hcomp_len, status);
-            }
-
-	    /* Write the compressed byte stream. */
-            ffpclb(outfptr, (outfptr->Fptr)->cn_compressed, row, 1,
-                     hcomp_len, (unsigned char *) cbuf, status);
-        }
-
-        /* =========================================================================== */
-        if ((outfptr->Fptr)->cn_zscale > 0)
-        {
-              /* write the linear scaling parameters for this tile */
-	      ffpcld (outfptr, (outfptr->Fptr)->cn_zscale, row, 1, 1,
-                      bscale, status);
-	      ffpcld (outfptr, (outfptr->Fptr)->cn_zzero,  row, 1, 1,
-                      bzero,  status);
-        }
-
-        free(cbuf);  /* finished with this buffer */
-
-    /* =========================================================================== */
-    } else {    /* if flag == 0., floating point data couldn't be quantized */
-
-	 /* losslessly compress the data with gzip. */
-
-         /* if gzip2 compressed data column doesn't exist, create it */
-         if ((outfptr->Fptr)->cn_gzip_data < 1) {
-              if ( (outfptr->Fptr)->request_huge_hdu != 0) {
-                 fits_insert_col(outfptr, 999, "GZIP_COMPRESSED_DATA", "1QB", status);
-              } else {
-                 fits_insert_col(outfptr, 999, "GZIP_COMPRESSED_DATA", "1PB", status);
-              }
-
-                 if (*status <= 0)  /* save the number of this column */
-                       ffgcno(outfptr, CASEINSEN, "GZIP_COMPRESSED_DATA",
-                                &(outfptr->Fptr)->cn_gzip_data, status);
-         }
-
-         if (datatype == TFLOAT)  {
-               /* allocate buffer for the compressed tile bytes */
-	       /* make it 10% larger than the original uncompressed data */
-               clen = (size_t) (tilelen * sizeof(float) * 1.1);
-               cbuf = (short *) calloc (clen, sizeof (unsigned char));
-
-               if (cbuf == NULL)
-               {
-                   ffpmsg("Memory allocation error. (imcomp_compress_tile)");
-	           return (*status = MEMORY_ALLOCATION);
-               }
-
-	       /* convert null values to NaNs in place, if necessary */
-	       if (nullcheck == 1) {
-	           imcomp_float2nan((float *) tiledata, tilelen, (int *) tiledata,
-	               *(float *) (nullflagval), status);
-	       }
-
-#if BYTESWAPPED
-               ffswap4((int*) tiledata, tilelen); 
-#endif
-               compress2mem_from_mem((char *) tiledata, tilelen * sizeof(float),
-                    (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);
-
-         } else {  /* datatype == TDOUBLE */
-
-               /* allocate buffer for the compressed tile bytes */
-	       /* make it 10% larger than the original uncompressed data */
-               clen = (size_t) (tilelen * sizeof(double) * 1.1);
-               cbuf = (short *) calloc (clen, sizeof (unsigned char));
-
-               if (cbuf == NULL)
-               {
-                   ffpmsg("Memory allocation error. (imcomp_compress_tile)");
-	           return (*status = MEMORY_ALLOCATION);
-               }
-
-	       /* convert null values to NaNs in place, if necessary */
-	       if (nullcheck == 1) {
-	           imcomp_double2nan((double *) tiledata, tilelen, (LONGLONG *) tiledata,
-	               *(double *) (nullflagval), status);
-	       }
-
-#if BYTESWAPPED
-               ffswap8((double*) tiledata, tilelen); 
-#endif
-               compress2mem_from_mem((char *) tiledata, tilelen * sizeof(double),
-                    (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);
-        }
-
-	/* Write the compressed byte stream. */
-        ffpclb(outfptr, (outfptr->Fptr)->cn_gzip_data, row, 1,
-             gzip_nelem, (unsigned char *) cbuf, status);
-
-        free(cbuf);  /* finished with this buffer */
-    }
-
-    return(*status);
-}
-
-/*--------------------------------------------------------------------------*/
-int imcomp_write_nocompress_tile(fitsfile *outfptr,
-    long row,
-    int datatype, 
-    void *tiledata, 
-    long tilelen,
-    int nullcheck,
-    void *nullflagval,
-    int *status)
-{
-    char coltype[4];
-
-    /* Write the uncompressed image tile pixels to the tile-compressed image file. */
-    /* This is a special case when using NOCOMPRESS for diagnostic purposes in fpack. */ 
-    /* Currently, this only supports a limited number of data types and */
-    /* does not fully support null-valued pixels in the image. */
-
-    if ((outfptr->Fptr)->cn_uncompressed < 1) {
-        /* uncompressed data column doesn't exist, so append new column to table */
-        if (datatype == TSHORT) {
-	    strcpy(coltype, "1PI");
-	} else if (datatype == TINT) {
-	    strcpy(coltype, "1PJ");
-	} else if (datatype == TFLOAT) {
-	    strcpy(coltype, "1QE");
-        } else {
-	    ffpmsg("NOCOMPRESSION option only supported for int*2, int*4, and float*4 images");
-            return(*status = DATA_COMPRESSION_ERR);
-        }
-
-        fits_insert_col(outfptr, 999, "UNCOMPRESSED_DATA", coltype, status); /* create column */
-    }
-
-    fits_get_colnum(outfptr, CASEINSEN, "UNCOMPRESSED_DATA",
-                    &(outfptr->Fptr)->cn_uncompressed, status);  /* save col. num. */
-    
-    fits_write_col(outfptr, datatype, (outfptr->Fptr)->cn_uncompressed, row, 1,
-                      tilelen, tiledata, status);  /* write the tile data */
-    return (*status);
-}
- /*--------------------------------------------------------------------------*/
-int imcomp_convert_tile_tshort(
-    fitsfile *outfptr,
-    void *tiledata, 
-    long tilelen,
-    int nullcheck,
-    void *nullflagval,
-    int nullval,
-    int zbitpix,
-    double scale,
-    double zero,
-    double actual_bzero,
-    int *intlength,
-    int *status)
-{
-    /*  Prepare the input tile array of pixels for compression. */
-    /*  Convert input integer*2 tile array in place to 4 or 8-byte ints for compression, */
-    /*  If needed, convert 4 or 8-byte ints and do null value substitution. */
-    /*  Note that the calling routine must have allocated the input array big enough */
-    /* to be able to do this.  */
-
-    short *sbuff;
-    int flagval, *idata;
-    long ii;
-    
-       /* We only support writing this integer*2 tile data to a FITS image with 
-          BITPIX = 16 and with BZERO = 0 and BSCALE = 1.  */
-	  
-       if (zbitpix != SHORT_IMG || scale != 1.0 || zero != 0.0) {
-           ffpmsg("Datatype conversion/scaling is not supported when writing to compressed images");
-           return(*status = DATA_COMPRESSION_ERR);
-       } 
-
-       sbuff = (short *) tiledata;
-       idata = (int *) tiledata;
-       
-       if ( (outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1
-         || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1 ) 
-       {
-           /* don't have to convert to int if using gzip, bzip2 or Rice compression */
-           *intlength = 2;
-             
-           if (nullcheck == 1) {
-               /* reset pixels equal to flagval to the FITS null value, prior to compression */
-               flagval = *(short *) (nullflagval);
-               if (flagval != nullval) {
-                  for (ii = tilelen - 1; ii >= 0; ii--) {
-	            if (sbuff[ii] == (short) flagval)
-		       sbuff[ii] = (short) nullval;
-                  }
-               }
-           }
-       } else if ((outfptr->Fptr)->compress_type == HCOMPRESS_1) {
-           /* have to convert to int if using HCOMPRESS */
-           *intlength = 4;
-
-           if (nullcheck == 1) {
-               /* reset pixels equal to flagval to the FITS null value, prior to compression */
-               flagval = *(short *) (nullflagval);
-               for (ii = tilelen - 1; ii >= 0; ii--) {
-	            if (sbuff[ii] == (short) flagval)
-		       idata[ii] = nullval;
-                    else 
-                       idata[ii] = (int) sbuff[ii];
-               }
-           } else {  /* just do the data type conversion to int */
-                 /* have to convert sbuff to an I*4 array, in place */
-                 /* sbuff must have been allocated large enough to do this */
-                 fits_short_to_int_inplace(sbuff, tilelen, status);
-           }
-       } else {
-           /* have to convert to int if using PLIO */
-           *intlength = 4;
-           if (zero == 0. && actual_bzero == 32768.) {
-             /* Here we are compressing unsigned 16-bit integers that have */
-	     /* been offset by -32768 using the standard FITS convention. */
-	     /* Since PLIO cannot deal with negative values, we must apply */
-	     /* the shift of 32786 to the values to make them all positive. */
-	     /* The inverse negative shift will be applied in */
-	     /* imcomp_decompress_tile when reading the compressed tile. */
-             if (nullcheck == 1) {
-               /* reset pixels equal to flagval to the FITS null value, prior to compression */
-               flagval = *(short *) (nullflagval);
-               for (ii = tilelen - 1; ii >= 0; ii--) {
-	            if (sbuff[ii] == (short) flagval)
-		       idata[ii] = nullval;
-                    else
-                       idata[ii] = (int) sbuff[ii] + 32768;
-               }
-             } else {  /* just do the data type conversion to int */
-                 /* have to convert sbuff to an I*4 array, in place */
-                 /* sbuff must have been allocated large enough to do this */
-                 fits_short_to_int_inplace(sbuff, tilelen, status);
-             }
-           } else {
-	     /* This is not an unsigned 16-bit integer array, so process normally */
-             if (nullcheck == 1) {
-               /* reset pixels equal to flagval to the FITS null value, prior to compression */
-               flagval = *(short *) (nullflagval);
-               for (ii = tilelen - 1; ii >= 0; ii--) {
-	            if (sbuff[ii] == (short) flagval)
-		       idata[ii] = nullval;
-                    else
-                       idata[ii] = (int) sbuff[ii];
-               }
-             } else {  /* just do the data type conversion to int */
-                 /* have to convert sbuff to an I*4 array, in place */
-                 /* sbuff must have been allocated large enough to do this */
-                 fits_short_to_int_inplace(sbuff, tilelen, status);
-             }
-           }
-        }
-        return(*status);
-}
- /*--------------------------------------------------------------------------*/
-int imcomp_convert_tile_tushort(
-    fitsfile *outfptr,
-    void *tiledata, 
-    long tilelen,
-    int nullcheck,
-    void *nullflagval,
-    int nullval,
-    int zbitpix,
-    double scale,
-    double zero,
-    int *intlength,
-    int *status)
-{
-    /*  Prepare the input  tile array of pixels for compression. */
-    /*  Convert input unsigned integer*2 tile array in place to 4 or 8-byte ints for compression, */
-    /*  If needed, convert 4 or 8-byte ints and do null value substitution. */
-    /*  Note that the calling routine must have allocated the input array big enough */
-    /* to be able to do this.  */
-
-    unsigned short *usbuff;
-    short *sbuff;
-    int flagval, *idata;
-    long ii;
-    
-       /* datatype of input array is unsigned short.  We only support writing this datatype
-          to a FITS image with BITPIX = 16 and with BZERO = 0 and BSCALE = 32768.  */
-
-       if (zbitpix != SHORT_IMG || scale != 1.0 || zero != 32768.) {
-           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
-           return(*status = DATA_COMPRESSION_ERR);
-       } 
-
-       usbuff = (unsigned short *) tiledata;
-       sbuff = (short *) tiledata;
-       idata = (int *) tiledata;
-
-       if ((outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1
-        || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1) 
-       {
-           /* don't have to convert to int if using gzip, bzip2, or Rice compression */
-           *intlength = 2;
-
-          /* offset the unsigned value by -32768 to a signed short value. */
-	  /* It is more efficient to do this by just flipping the most significant of the 16 bits */
-
-           if (nullcheck == 1) {
-               /* reset pixels equal to flagval to the FITS null value, prior to compression  */
-               flagval = *(unsigned short *) (nullflagval);
-               for (ii = tilelen - 1; ii >= 0; ii--) {
-	            if (usbuff[ii] == (unsigned short) flagval)
-		       sbuff[ii] = (short) nullval;
-                    else
-		       usbuff[ii] =  (usbuff[ii]) ^ 0x8000;
-               }
-           } else {
-               /* just offset the pixel values by 32768 (by flipping the MSB */
-               for (ii = tilelen - 1; ii >= 0; ii--)
-		       usbuff[ii] =  (usbuff[ii]) ^ 0x8000;
-           }
-       } else {
-           /* have to convert to int if using HCOMPRESS or PLIO */
-           *intlength = 4;
-
-           if (nullcheck == 1) {
-               /* offset the pixel values by 32768, and */
-               /* reset pixels equal to flagval to nullval */
-               flagval = *(unsigned short *) (nullflagval);
-               for (ii = tilelen - 1; ii >= 0; ii--) {
-	            if (usbuff[ii] == (unsigned short) flagval)
-		       idata[ii] = nullval;
-                    else
-		       idata[ii] = ((int) usbuff[ii]) - 32768;
-               }
-           } else {  /* just do the data type conversion to int */
-                 /* have to convert usbuff to an I*4 array, in place */
-                 /* usbuff must have been allocated large enough to do this */
-                 fits_ushort_to_int_inplace(usbuff, tilelen, status);
-           }
-        }
-
-        return(*status);
-}
- /*--------------------------------------------------------------------------*/
-int imcomp_convert_tile_tint(
-    fitsfile *outfptr,
-    void *tiledata, 
-    long tilelen,
-    int nullcheck,
-    void *nullflagval,
-    int nullval,
-    int zbitpix,
-    double scale,
-    double zero,
-    int *intlength,
-    int *status)
-{
-    /*  Prepare the input tile array of pixels for compression. */
-    /*  Convert input integer tile array in place to 4 or 8-byte ints for compression, */
-    /*  If needed, do null value substitution. */
-   
-    int flagval, *idata;
-    long ii;
-    
- 
-        /* datatype of input array is int.  We only support writing this datatype
-           to a FITS image with BITPIX = 32 and with BZERO = 0 and BSCALE = 1.  */
-
-       if (zbitpix != LONG_IMG || scale != 1.0 || zero != 0.) {
-           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
-           return(*status = DATA_COMPRESSION_ERR);
-       } 
-
-       idata = (int *) tiledata;
-       *intlength = 4;
-
-       if (nullcheck == 1) {
-               /* no datatype conversion is required for any of the compression algorithms,
-	         except possibly for HCOMPRESS (to I*8), which is handled later.
-		 Just reset pixels equal to flagval to the FITS null value */
-               flagval = *(int *) (nullflagval);
-               if (flagval != nullval) {
-                  for (ii = tilelen - 1; ii >= 0; ii--) {
-	            if (idata[ii] == flagval)
-		       idata[ii] = nullval;
-                  }
-               }
-       }
-
-       return(*status);
-}
- /*--------------------------------------------------------------------------*/
-int imcomp_convert_tile_tuint(
-    fitsfile *outfptr,
-    void *tiledata, 
-    long tilelen,
-    int nullcheck,
-    void *nullflagval,
-    int nullval,
-    int zbitpix,
-    double scale,
-    double zero,
-    int *intlength,
-    int *status)
-{
-    /*  Prepare the input tile array of pixels for compression. */
-    /*  Convert input unsigned integer tile array in place to 4 or 8-byte ints for compression, */
-    /*  If needed, do null value substitution. */
-
-
-    int *idata;
-    unsigned int *uintbuff, uintflagval;
-    long ii;
- 
-       /* datatype of input array is unsigned int.  We only support writing this datatype
-          to a FITS image with BITPIX = 32 and with BZERO = 0 and BSCALE = 2147483648.  */
-
-       if (zbitpix != LONG_IMG || scale != 1.0 || zero != 2147483648.) {
-           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
-           return(*status = DATA_COMPRESSION_ERR);
-       } 
-
-       *intlength = 4;
-       idata = (int *) tiledata;
-       uintbuff = (unsigned int *) tiledata;
-
-       /* offset the unsigned value by -2147483648 to a signed int value. */
-       /* It is more efficient to do this by just flipping the most significant of the 32 bits */
-
-       if (nullcheck == 1) {
-               /* reset pixels equal to flagval to nullval and */
-               /* offset the other pixel values (by flipping the MSB) */
-               uintflagval = *(unsigned int *) (nullflagval);
-               for (ii = tilelen - 1; ii >= 0; ii--) {
-	            if (uintbuff[ii] == uintflagval)
-		       idata[ii] = nullval;
-                    else
-		       uintbuff[ii] = (uintbuff[ii]) ^ 0x80000000;
-               }
-       } else {
-               /* just offset the pixel values (by flipping the MSB) */
-               for (ii = tilelen - 1; ii >= 0; ii--)
-		       uintbuff[ii] = (uintbuff[ii]) ^ 0x80000000;
-       }
-
-       return(*status);
-}
- /*--------------------------------------------------------------------------*/
-int imcomp_convert_tile_tbyte(
-    fitsfile *outfptr,
-    void *tiledata, 
-    long tilelen,
-    int nullcheck,
-    void *nullflagval,
-    int nullval,
-    int zbitpix,
-    double scale,
-    double zero,
-    int *intlength,
-    int *status)
-{
-    /*  Prepare the input tile array of pixels for compression. */
-    /*  Convert input unsigned integer*1 tile array in place to 4 or 8-byte ints for compression, */
-    /*  If needed, convert 4 or 8-byte ints and do null value substitution. */
-    /*  Note that the calling routine must have allocated the input array big enough */
-    /* to be able to do this.  */
-
-    int flagval, *idata;
-    long ii;
-    unsigned char *usbbuff;
-        
-       /* datatype of input array is unsigned byte.  We only support writing this datatype
-          to a FITS image with BITPIX = 8 and with BZERO = 0 and BSCALE = 1.  */
-
-       if (zbitpix != BYTE_IMG || scale != 1.0 || zero != 0.) {
-           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
-           return(*status = DATA_COMPRESSION_ERR);
-       } 
-
-       idata = (int *) tiledata;
-       usbbuff = (unsigned char *) tiledata;
-
-       if ( (outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1
-         || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1 ) 
-       {
-           /* don't have to convert to int if using gzip, bzip2, or Rice compression */
-           *intlength = 1;
-             
-           if (nullcheck == 1) {
-               /* reset pixels equal to flagval to the FITS null value, prior to compression */
-               flagval = *(unsigned char *) (nullflagval);
-               if (flagval != nullval) {
-                  for (ii = tilelen - 1; ii >= 0; ii--) {
-	            if (usbbuff[ii] == (unsigned char) flagval)
-		       usbbuff[ii] = (unsigned char) nullval;
-                    }
-               }
-           }
-       } else {
-           /* have to convert to int if using HCOMPRESS or PLIO */
-           *intlength = 4;
-
-           if (nullcheck == 1) {
-               /* reset pixels equal to flagval to the FITS null value, prior to compression */
-               flagval = *(unsigned char *) (nullflagval);
-               for (ii = tilelen - 1; ii >= 0; ii--) {
-	            if (usbbuff[ii] == (unsigned char) flagval)
-		       idata[ii] = nullval;
-                    else
-                       idata[ii] = (int) usbbuff[ii];
-               }
-           } else {  /* just do the data type conversion to int */
-                 /* have to convert usbbuff to an I*4 array, in place */
-                 /* usbbuff must have been allocated large enough to do this */
-                 fits_ubyte_to_int_inplace(usbbuff, tilelen, status);
-           }
-       }
-
-       return(*status);
-}
- /*--------------------------------------------------------------------------*/
-int imcomp_convert_tile_tsbyte(
-    fitsfile *outfptr,
-    void *tiledata, 
-    long tilelen,
-    int nullcheck,
-    void *nullflagval,
-    int nullval,
-    int zbitpix,
-    double scale,
-    double zero,
-    int *intlength,
-    int *status)
-{
-    /*  Prepare the input tile array of pixels for compression. */
-    /*  Convert input integer*1 tile array in place to 4 or 8-byte ints for compression, */
-    /*  If needed, convert 4 or 8-byte ints and do null value substitution. */
-    /*  Note that the calling routine must have allocated the input array big enough */
-    /* to be able to do this.  */
-
-    int flagval, *idata;
-    long ii;
-    signed char *sbbuff;
-
-       /* datatype of input array is signed byte.  We only support writing this datatype
-          to a FITS image with BITPIX = 8 and with BZERO = 0 and BSCALE = -128.  */
-
-       if (zbitpix != BYTE_IMG|| scale != 1.0 || zero != -128.) {
-           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
-           return(*status = DATA_COMPRESSION_ERR);
-       }
-
-       idata = (int *) tiledata;
-       sbbuff = (signed char *) tiledata;
-
-       if ( (outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1
-         || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1 ) 
-       {
-           /* don't have to convert to int if using gzip, bzip2 or Rice compression */
-           *intlength = 1;
-             
-           if (nullcheck == 1) {
-               /* reset pixels equal to flagval to the FITS null value, prior to compression */
-               /* offset the other pixel values (by flipping the MSB) */
-
-               flagval = *(signed char *) (nullflagval);
-               for (ii = tilelen - 1; ii >= 0; ii--) {
-	            if (sbbuff[ii] == (signed char) flagval)
-		       sbbuff[ii] = (signed char) nullval;
-                    else
-		       sbbuff[ii] = (sbbuff[ii]) ^ 0x80;               }
-           } else {  /* just offset the pixel values (by flipping the MSB) */
-               for (ii = tilelen - 1; ii >= 0; ii--) 
-		       sbbuff[ii] = (sbbuff[ii]) ^ 0x80;
-           }
-
-       } else {
-           /* have to convert to int if using HCOMPRESS or PLIO */
-           *intlength = 4;
-
-           if (nullcheck == 1) {
-               /* reset pixels equal to flagval to the FITS null value, prior to compression */
-               flagval = *(signed char *) (nullflagval);
-               for (ii = tilelen - 1; ii >= 0; ii--) {
-	            if (sbbuff[ii] == (signed char) flagval)
-		       idata[ii] = nullval;
-                    else
-                       idata[ii] = ((int) sbbuff[ii]) + 128;
-               }
-           } else {  /* just do the data type conversion to int */
-                 /* have to convert sbbuff to an I*4 array, in place */
-                 /* sbbuff must have been allocated large enough to do this */
-                 fits_sbyte_to_int_inplace(sbbuff, tilelen, status);
-           }
-       }
- 
-       return(*status);
-}
- /*--------------------------------------------------------------------------*/
-int imcomp_convert_tile_tfloat(
-    fitsfile *outfptr,
-    long row,
-    void *tiledata, 
-    long tilelen,
-    long tilenx,
-    long tileny,
-    int nullcheck,
-    void *nullflagval,
-    int nullval,
-    int zbitpix,
-    double scale,
-    double zero,
-    int *intlength,
-    int *flag,
-    double *bscale,
-    double *bzero,
-    int *status)
-{
-    /*  Prepare the input tile array of pixels for compression. */
-    /*  Convert input float tile array in place to 4 or 8-byte ints for compression, */
-    /*  If needed, convert 4 or 8-byte ints and do null value substitution. */
-    /*  Note that the calling routine must have allocated the input array big enough */
-    /* to be able to do this.  */
-
-    int *idata;
-    long irow, ii;
-    float floatnull;
-    unsigned char *usbbuff;
-    unsigned long dithersum;
-    int iminval = 0, imaxval = 0;  /* min and max quantized integers */
-
-        /* datatype of input array is double.  We only support writing this datatype
-           to a FITS image with BITPIX = -64 or -32, except we also support the special case where
-	   BITPIX = 32 and BZERO = 0 and BSCALE = 1.  */
-
-       if ((zbitpix != LONG_IMG && zbitpix != DOUBLE_IMG && zbitpix != FLOAT_IMG) || scale != 1.0 || zero != 0.) {
-           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
-           return(*status = DATA_COMPRESSION_ERR);
-       } 
-
-           *intlength = 4;
-           idata = (int *) tiledata;
-
-          /* if the tile-compressed table contains zscale and zzero columns */
-          /* then scale and quantize the input floating point data.    */
-
-          if ((outfptr->Fptr)->cn_zscale > 0) {
-	    /* quantize the float values into integers */
-
-            if (nullcheck == 1)
-	      floatnull = *(float *) (nullflagval);
-	    else
-	      floatnull = FLOATNULLVALUE;  /* NaNs are represented by this, by default */
-
-            if ((outfptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_1  ||
-	        (outfptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_2) {
-	      
-	          /* see if the dithering offset value needs to be initialized */                  
-	          if ((outfptr->Fptr)->request_dither_seed == 0 && (outfptr->Fptr)->dither_seed == 0) {
-
-		     /* This means randomly choose the dithering offset based on the system time. */
-		     /* The offset will have a value between 1 and 10000, inclusive. */
-		     /* The time function returns an integer value that is incremented each second. */
-		     /* The clock function returns the elapsed CPU time, in integer CLOCKS_PER_SEC units. */
-		     /* The CPU time returned by clock is typically (on linux PC) only good to 0.01 sec */
-		     /* Summing the 2 quantities may help avoid cases where 2 executions of the program */
-		     /* (perhaps in a multithreaded environoment) end up with exactly the same dither seed */
-		     /* value.  The sum is incremented by the current HDU number in the file to provide */
-		     /* further randomization.  This randomization is desireable if multiple compressed */
-		     /* images will be summed (or differenced). In such cases, the benefits of dithering */
-		     /* may be lost if all the images use exactly the same sequence of random numbers when */
-		     /* calculating the dithering offsets. */	     
-		     
-		     (outfptr->Fptr)->dither_seed = 
-		       (( (int)time(NULL) + ( (int) clock() / (int) (CLOCKS_PER_SEC / 100)) + (outfptr->Fptr)->curhdu) % 10000) + 1;
-		     
-                     /* update the header keyword with this new value */
-		     fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_seed), 
-	                        NULL, status);
-
-	          } else if ((outfptr->Fptr)->request_dither_seed < 0 && (outfptr->Fptr)->dither_seed < 0) {
-
-		     /* this means randomly choose the dithering offset based on some hash function */
-		     /* of the first input tile of data to be quantized and compressed.  This ensures that */
-                     /* the same offset value is used for a given image every time it is compressed. */
-
-		     usbbuff = (unsigned char *) tiledata;
-		     dithersum = 0;
-		     for (ii = 0; ii < 4 * tilelen; ii++) {
-		         dithersum += usbbuff[ii];  /* doesn't matter if there is an integer overflow */
-	             }
-		     (outfptr->Fptr)->dither_seed = ((int) (dithersum % 10000)) + 1;
-		
-                     /* update the header keyword with this new value */
-		     fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_seed), 
-	                        NULL, status);
-		  }
-
-                  /* subtract 1 to convert from 1-based to 0-based element number */
-	          irow = row + (outfptr->Fptr)->dither_seed - 1; /* dither the quantized values */
-
-	      } else if ((outfptr->Fptr)->quantize_method == -1) {
-	          irow = 0;  /* do not dither the quantized values */
-              } else {
-                  ffpmsg("Unknown dithering method.");
-                  ffpmsg("May need to install a newer version of CFITSIO.");
-                  return(*status = DATA_COMPRESSION_ERR);
-              }
-
-              *flag = fits_quantize_float (irow, (float *) tiledata, tilenx, tileny,
-                   nullcheck, floatnull, (outfptr->Fptr)->quantize_level, 
-		   (outfptr->Fptr)->quantize_method, idata, bscale, bzero, &iminval, &imaxval);
-
-              if (*flag > 1)
-		   return(*status = *flag);
-          }
-          else if ((outfptr->Fptr)->quantize_level != NO_QUANTIZE)
-	  {
-	    /* if floating point pixels are not being losslessly compressed, then */
-	    /* input float data is implicitly converted (truncated) to integers */
-            if ((scale != 1. || zero != 0.))  /* must scale the values */
-	       imcomp_nullscalefloats((float *) tiledata, tilelen, idata, scale, zero,
-	           nullcheck, *(float *) (nullflagval), nullval, status);
-             else
-	       imcomp_nullfloats((float *) tiledata, tilelen, idata,
-	           nullcheck, *(float *) (nullflagval), nullval,  status);
-          }
-          else if ((outfptr->Fptr)->quantize_level == NO_QUANTIZE)
-	  {
-	      /* just convert null values to NaNs in place, if necessary, then do lossless gzip compression */
-		if (nullcheck == 1) {
-	            imcomp_float2nan((float *) tiledata, tilelen, (int *) tiledata,
-	                *(float *) (nullflagval), status);
-		}
-          }
-
-          return(*status);
-}
- /*--------------------------------------------------------------------------*/
-int imcomp_convert_tile_tdouble(
-    fitsfile *outfptr,
-    long row,
-    void *tiledata, 
-    long tilelen,
-    long tilenx,
-    long tileny,
-    int nullcheck,
-    void *nullflagval,
-    int nullval,
-    int zbitpix,
-    double scale,
-    double zero,
-    int *intlength,
-    int *flag,
-    double *bscale,
-    double *bzero,
-    int *status)
-{
-    /*  Prepare the input tile array of pixels for compression. */
-    /*  Convert input double tile array in place to 4-byte ints for compression, */
-    /*  If needed, convert 4 or 8-byte ints and do null value substitution. */
-    /*  Note that the calling routine must have allocated the input array big enough */
-    /* to be able to do this.  */
-
-    int *idata;
-    long irow, ii;
-    double doublenull;
-    unsigned char *usbbuff;
-    unsigned long dithersum;
-    int iminval = 0, imaxval = 0;  /* min and max quantized integers */
-
-        /* datatype of input array is double.  We only support writing this datatype
-           to a FITS image with BITPIX = -64 or -32, except we also support the special case where
-	   BITPIX = 32 and BZERO = 0 and BSCALE = 1.  */
-
-       if ((zbitpix != LONG_IMG && zbitpix != DOUBLE_IMG && zbitpix != FLOAT_IMG) || scale != 1.0 || zero != 0.) {
-           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
-           return(*status = DATA_COMPRESSION_ERR);
-       } 
-
-           *intlength = 4;
-           idata = (int *) tiledata;
-
-          /* if the tile-compressed table contains zscale and zzero columns */
-          /* then scale and quantize the input floating point data.    */
-          /* Otherwise, just truncate the floats to integers.          */
-
-          if ((outfptr->Fptr)->cn_zscale > 0)
-          {
-            if (nullcheck == 1)
-	      doublenull = *(double *) (nullflagval);
-	    else
-	      doublenull = DOUBLENULLVALUE;
-
-            /* quantize the double values into integers */
-              if ((outfptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_1 ||
-	          (outfptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_2) {
-
-	          /* see if the dithering offset value needs to be initialized (see above) */                  
-	          if ((outfptr->Fptr)->request_dither_seed == 0 && (outfptr->Fptr)->dither_seed == 0) {
-
-		     (outfptr->Fptr)->dither_seed = 
-		       (( (int)time(NULL) + ( (int) clock() / (int) (CLOCKS_PER_SEC / 100)) + (outfptr->Fptr)->curhdu) % 10000) + 1;
-		     
-                     /* update the header keyword with this new value */
-		     fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_seed), 
-	                        NULL, status);
-
-	          } else if ((outfptr->Fptr)->request_dither_seed < 0 && (outfptr->Fptr)->dither_seed < 0) {
-
-		     usbbuff = (unsigned char *) tiledata;
-		     dithersum = 0;
-		     for (ii = 0; ii < 8 * tilelen; ii++) {
-		         dithersum += usbbuff[ii];
-	             }
-		     (outfptr->Fptr)->dither_seed = ((int) (dithersum % 10000)) + 1;
-		
-                     /* update the header keyword with this new value */
-		     fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_seed), 
-	                        NULL, status);
-		  }
-
-	          irow = row + (outfptr->Fptr)->dither_seed - 1; /* dither the quantized values */
-
-	      } else if ((outfptr->Fptr)->quantize_method == -1) {
-	          irow = 0;  /* do not dither the quantized values */
-              } else {
-                  ffpmsg("Unknown subtractive dithering method.");
-                  ffpmsg("May need to install a newer version of CFITSIO.");
-                  return(*status = DATA_COMPRESSION_ERR);
-              }
-
-            *flag = fits_quantize_double (irow, (double *) tiledata, tilenx, tileny,
-               nullcheck, doublenull, (outfptr->Fptr)->quantize_level, 
-	       (outfptr->Fptr)->quantize_method, idata,
-               bscale, bzero, &iminval, &imaxval);
-
-            if (*flag > 1)
-		return(*status = *flag);
-          }
-          else if ((outfptr->Fptr)->quantize_level != NO_QUANTIZE)
-	  {
-	    /* if floating point pixels are not being losslessly compressed, then */
-	    /* input float data is implicitly converted (truncated) to integers */
-             if ((scale != 1. || zero != 0.))  /* must scale the values */
-	       imcomp_nullscaledoubles((double *) tiledata, tilelen, idata, scale, zero,
-	           nullcheck, *(double *) (nullflagval), nullval, status);
-             else
-	       imcomp_nulldoubles((double *) tiledata, tilelen, idata,
-	           nullcheck, *(double *) (nullflagval), nullval,  status);
-          }
-          else if ((outfptr->Fptr)->quantize_level == NO_QUANTIZE)
-	  {
-	      /* just convert null values to NaNs in place, if necessary, then do lossless gzip compression */
-		if (nullcheck == 1) {
-	            imcomp_double2nan((double *) tiledata, tilelen, (LONGLONG *) tiledata,
-	                *(double *) (nullflagval), status);
-		}
-          }
- 
-          return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int imcomp_nullscale(
-     int *idata, 
-     long tilelen,
-     int nullflagval,
-     int nullval,
-     double scale,
-     double zero,
-     int *status)
-/*
-   do null value substitution AND scaling of the integer array.
-   If array value = nullflagval, then set the value to nullval.
-   Otherwise, inverse scale the integer value.
-*/
-{
-    long ii;
-    double dvalue;
-    
-    for (ii=0; ii < tilelen; ii++)
-    {
-        if (idata[ii] == nullflagval)
-	    idata[ii] = nullval;
-	else 
-	{
-            dvalue = (idata[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    idata[ii] = (int) (dvalue + .5);
-                else
-                    idata[ii] = (int) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int imcomp_nullvalues(
-     int *idata, 
-     long tilelen,
-     int nullflagval,
-     int nullval,
-     int *status)
-/*
-   do null value substitution.
-   If array value = nullflagval, then set the value to nullval.
-*/
-{
-    long ii;
-    
-    for (ii=0; ii < tilelen; ii++)
-    {
-        if (idata[ii] == nullflagval)
-	    idata[ii] = nullval;
-    }
-    return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int imcomp_scalevalues(
-     int *idata, 
-     long tilelen,
-     double scale,
-     double zero,
-     int *status)
-/*
-   do inverse scaling the integer values.
-*/
-{
-    long ii;
-    double dvalue;
-    
-    for (ii=0; ii < tilelen; ii++)
-    {
-            dvalue = (idata[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    idata[ii] = (int) (dvalue + .5);
-                else
-                    idata[ii] = (int) (dvalue - .5);
-            }
-    }
-    return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int imcomp_nullscalei2(
-     short *idata, 
-     long tilelen,
-     short nullflagval,
-     short nullval,
-     double scale,
-     double zero,
-     int *status)
-/*
-   do null value substitution AND scaling of the integer array.
-   If array value = nullflagval, then set the value to nullval.
-   Otherwise, inverse scale the integer value.
-*/
-{
-    long ii;
-    double dvalue;
-    
-    for (ii=0; ii < tilelen; ii++)
-    {
-        if (idata[ii] == nullflagval)
-	    idata[ii] = nullval;
-	else 
-	{
-            dvalue = (idata[ii] - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    idata[ii] = (int) (dvalue + .5);
-                else
-                    idata[ii] = (int) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int imcomp_nullvaluesi2(
-     short *idata, 
-     long tilelen,
-     short nullflagval,
-     short nullval,
-     int *status)
-/*
-   do null value substitution.
-   If array value = nullflagval, then set the value to nullval.
-*/
-{
-    long ii;
-    
-    for (ii=0; ii < tilelen; ii++)
-    {
-        if (idata[ii] == nullflagval)
-	    idata[ii] = nullval;
-    }
-    return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int imcomp_scalevaluesi2(
-     short *idata, 
-     long tilelen,
-     double scale,
-     double zero,
-     int *status)
-/*
-   do inverse scaling the integer values.
-*/
-{
-    long ii;
-    double dvalue;
-    
-    for (ii=0; ii < tilelen; ii++)
-    {
-            dvalue = (idata[ii] - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    idata[ii] = (int) (dvalue + .5);
-                else
-                    idata[ii] = (int) (dvalue - .5);
-            }
-    }
-    return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int imcomp_nullfloats(
-     float *fdata,
-     long tilelen,
-     int *idata, 
-     int nullcheck,
-     float nullflagval,
-     int nullval,
-     int *status)
-/*
-   do null value substitution  of the float array.
-   If array value = nullflagval, then set the output value to FLOATNULLVALUE.
-*/
-{
-    long ii;
-    double dvalue;
-    
-    if (nullcheck == 1) /* must check for null values */
-    {
-      for (ii=0; ii < tilelen; ii++)
-      {
-        if (fdata[ii] == nullflagval)
-	    idata[ii] = nullval;
-	else 
-	{
-            dvalue = fdata[ii];
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    idata[ii] = (int) (dvalue + .5);
-                else
-                    idata[ii] = (int) (dvalue - .5);
-            }
-        }
-      }
-    }
-    else  /* don't have to worry about null values */
-    {
-      for (ii=0; ii < tilelen; ii++)
-      {
-            dvalue = fdata[ii];
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    idata[ii] = (int) (dvalue + .5);
-                else
-                    idata[ii] = (int) (dvalue - .5);
-            }
-      }
-    }
-    return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int imcomp_nullscalefloats(
-     float *fdata,
-     long tilelen,
-     int *idata, 
-     double scale,
-     double zero,
-     int nullcheck,
-     float nullflagval,
-     int nullval,
-     int *status)
-/*
-   do null value substitution  of the float array.
-   If array value = nullflagval, then set the output value to FLOATNULLVALUE.
-   Otherwise, inverse scale the integer value.
-*/
-{
-    long ii;
-    double dvalue;
-    
-    if (nullcheck == 1) /* must check for null values */
-    {
-      for (ii=0; ii < tilelen; ii++)
-      {
-        if (fdata[ii] == nullflagval)
-	    idata[ii] = nullval;
-	else 
-	{
-            dvalue = (fdata[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0.)
-                    idata[ii] = (int) (dvalue + .5);
-                else
-                    idata[ii] = (int) (dvalue - .5);
-            }
-        }
-      }
-    }
-    else  /* don't have to worry about null values */
-    {
-      for (ii=0; ii < tilelen; ii++)
-      {
-            dvalue = (fdata[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0.)
-                    idata[ii] = (int) (dvalue + .5);
-                else
-                    idata[ii] = (int) (dvalue - .5);
-            }
-      }
-    }
-    return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int imcomp_nulldoubles(
-     double *fdata,
-     long tilelen,
-     int *idata, 
-     int nullcheck,
-     double nullflagval,
-     int nullval,
-     int *status)
-/*
-   do null value substitution  of the float array.
-   If array value = nullflagval, then set the output value to FLOATNULLVALUE.
-   Otherwise, inverse scale the integer value.
-*/
-{
-    long ii;
-    double dvalue;
-    
-    if (nullcheck == 1) /* must check for null values */
-    {
-      for (ii=0; ii < tilelen; ii++)
-      {
-        if (fdata[ii] == nullflagval)
-	    idata[ii] = nullval;
-	else 
-	{
-            dvalue = fdata[ii];
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0.)
-                    idata[ii] = (int) (dvalue + .5);
-                else
-                    idata[ii] = (int) (dvalue - .5);
-            }
-        }
-      }
-    }
-    else  /* don't have to worry about null values */
-    {
-      for (ii=0; ii < tilelen; ii++)
-      {
-            dvalue = fdata[ii];
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0.)
-                    idata[ii] = (int) (dvalue + .5);
-                else
-                    idata[ii] = (int) (dvalue - .5);
-            }
-      }
-    }
-    return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int imcomp_nullscaledoubles(
-     double *fdata,
-     long tilelen,
-     int *idata, 
-     double scale,
-     double zero,
-     int nullcheck,
-     double nullflagval,
-     int nullval,
-     int *status)
-/*
-   do null value substitution  of the float array.
-   If array value = nullflagval, then set the output value to FLOATNULLVALUE.
-   Otherwise, inverse scale the integer value.
-*/
-{
-    long ii;
-    double dvalue;
-    
-    if (nullcheck == 1) /* must check for null values */
-    {
-      for (ii=0; ii < tilelen; ii++)
-      {
-        if (fdata[ii] == nullflagval)
-	    idata[ii] = nullval;
-	else 
-	{
-            dvalue = (fdata[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0.)
-                    idata[ii] = (int) (dvalue + .5);
-                else
-                    idata[ii] = (int) (dvalue - .5);
-            }
-        }
-      }
-    }
-    else  /* don't have to worry about null values */
-    {
-      for (ii=0; ii < tilelen; ii++)
-      {
-            dvalue = (fdata[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                idata[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0.)
-                    idata[ii] = (int) (dvalue + .5);
-                else
-                    idata[ii] = (int) (dvalue - .5);
-            }
-      }
-    }
-    return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int fits_write_compressed_img(fitsfile *fptr,   /* I - FITS file pointer     */
-            int  datatype,   /* I - datatype of the array to be written      */
-            long  *infpixel, /* I - 'bottom left corner' of the subsection   */
-            long  *inlpixel, /* I - 'top right corner' of the subsection     */
-            int  nullcheck,  /* I - 0 for no null checking                   */
-                             /*     1: pixels that are = nullval will be     */
-                             /*     written with the FITS null pixel value   */
-                             /*     (floating point arrays only)             */
-            void *array,     /* I - array of values to be written            */
-            void *nullval,   /* I - undefined pixel value                    */
-            int  *status)    /* IO - error status                            */
-/*
-   Write a section of a compressed image.
-*/
-{
-    int  tiledim[MAX_COMPRESS_DIM];
-    long naxis[MAX_COMPRESS_DIM];
-    long tilesize[MAX_COMPRESS_DIM], thistilesize[MAX_COMPRESS_DIM];
-    long ftile[MAX_COMPRESS_DIM], ltile[MAX_COMPRESS_DIM];
-    long tfpixel[MAX_COMPRESS_DIM], tlpixel[MAX_COMPRESS_DIM];
-    long rowdim[MAX_COMPRESS_DIM], offset[MAX_COMPRESS_DIM],ntemp;
-    long fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM];
-    long i5, i4, i3, i2, i1, i0, irow;
-    int ii, ndim, pixlen, tilenul;
-    int  tstatus, buffpixsiz;
-    void *buffer;
-    char *bnullarray = 0, card[FLEN_CARD];
-
-    if (*status > 0) 
-        return(*status);
-
-    if (!fits_is_compressed_image(fptr, status) )
-    {
-        ffpmsg("CHDU is not a compressed image (fits_write_compressed_img)");
-        return(*status = DATA_COMPRESSION_ERR);
-    }
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    /* rescan header if data structure is undefined */
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-        if ( ffrdef(fptr, status) > 0)               
-            return(*status);
-
-
-    /* ===================================================================== */
-
-
-    if (datatype == TSHORT || datatype == TUSHORT)
-    {
-       pixlen = sizeof(short);
-    }
-    else if (datatype == TINT || datatype == TUINT)
-    {
-       pixlen = sizeof(int);
-    }
-    else if (datatype == TBYTE || datatype == TSBYTE)
-    {
-       pixlen = 1;
-    }
-    else if (datatype == TLONG || datatype == TULONG)
-    {
-       pixlen = sizeof(long);
-    }
-    else if (datatype == TFLOAT)
-    {
-       pixlen = sizeof(float);
-    }
-    else if (datatype == TDOUBLE)
-    {
-       pixlen = sizeof(double);
-    }
-    else
-    {
-        ffpmsg("unsupported datatype for compressing image");
-        return(*status = BAD_DATATYPE);
-    }
-
-    /* ===================================================================== */
-
-    /* allocate scratch space for processing one tile of the image */
-    buffpixsiz = pixlen;  /* this is the minimum pixel size */
-    
-    if ( (fptr->Fptr)->compress_type == HCOMPRESS_1) { /* need 4 or 8 bytes per pixel */
-        if ((fptr->Fptr)->zbitpix == BYTE_IMG ||
-	    (fptr->Fptr)->zbitpix == SHORT_IMG )
-                buffpixsiz = maxvalue(buffpixsiz, 4);
-        else
-	        buffpixsiz = 8;
-    }
-    else if ( (fptr->Fptr)->compress_type == PLIO_1) { /* need 4 bytes per pixel */
-                buffpixsiz = maxvalue(buffpixsiz, 4);
-    }
-    else if ( (fptr->Fptr)->compress_type == RICE_1  ||
-              (fptr->Fptr)->compress_type == GZIP_1 ||
-              (fptr->Fptr)->compress_type == GZIP_2 ||
-              (fptr->Fptr)->compress_type == BZIP2_1) {  /* need 1, 2, or 4 bytes per pixel */
-        if ((fptr->Fptr)->zbitpix == BYTE_IMG)
-            buffpixsiz = maxvalue(buffpixsiz, 1);
-        else if ((fptr->Fptr)->zbitpix == SHORT_IMG)
-            buffpixsiz = maxvalue(buffpixsiz, 2);
-        else 
-            buffpixsiz = maxvalue(buffpixsiz, 4);
-    }
-    else
-    {
-        ffpmsg("unsupported image compression algorithm");
-        return(*status = BAD_DATATYPE);
-    }
-    
-    /* cast to double to force alignment on 8-byte addresses */
-    buffer = (double *) calloc ((fptr->Fptr)->maxtilelen, buffpixsiz);
-
-    if (buffer == NULL)
-    {
-	    ffpmsg("Out of memory (fits_write_compress_img)");
-	    return (*status = MEMORY_ALLOCATION);
-    }
-
-    /* ===================================================================== */
-
-    /* initialize all the arrays */
-    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-    {
-        naxis[ii] = 1;
-        tiledim[ii] = 1;
-        tilesize[ii] = 1;
-        ftile[ii] = 1;
-        ltile[ii] = 1;
-        rowdim[ii] = 1;
-    }
-
-    ndim = (fptr->Fptr)->zndim;
-    ntemp = 1;
-    for (ii = 0; ii < ndim; ii++)
-    {
-        fpixel[ii] = infpixel[ii];
-        lpixel[ii] = inlpixel[ii];
-
-        /* calc number of tiles in each dimension, and tile containing */
-        /* the first and last pixel we want to read in each dimension  */
-        naxis[ii] = (fptr->Fptr)->znaxis[ii];
-        if (fpixel[ii] < 1)
-        {
-            free(buffer);
-            return(*status = BAD_PIX_NUM);
-        }
-
-        tilesize[ii] = (fptr->Fptr)->tilesize[ii];
-        tiledim[ii] = (naxis[ii] - 1) / tilesize[ii] + 1;
-        ftile[ii]   = (fpixel[ii] - 1)   / tilesize[ii] + 1;
-        ltile[ii]   = minvalue((lpixel[ii] - 1) / tilesize[ii] + 1, 
-                                tiledim[ii]);
-        rowdim[ii]  = ntemp;  /* total tiles in each dimension */
-        ntemp *= tiledim[ii];
-    }
-
-    /* support up to 6 dimensions for now */
-    /* tfpixel and tlpixel are the first and last image pixels */
-    /* along each dimension of the compression tile */
-    for (i5 = ftile[5]; i5 <= ltile[5]; i5++)
-    {
-     tfpixel[5] = (i5 - 1) * tilesize[5] + 1;
-     tlpixel[5] = minvalue(tfpixel[5] + tilesize[5] - 1, 
-                            naxis[5]);
-     thistilesize[5] = tlpixel[5] - tfpixel[5] + 1;
-     offset[5] = (i5 - 1) * rowdim[5];
-     for (i4 = ftile[4]; i4 <= ltile[4]; i4++)
-     {
-      tfpixel[4] = (i4 - 1) * tilesize[4] + 1;
-      tlpixel[4] = minvalue(tfpixel[4] + tilesize[4] - 1, 
-                            naxis[4]);
-      thistilesize[4] = thistilesize[5] * (tlpixel[4] - tfpixel[4] + 1);
-      offset[4] = (i4 - 1) * rowdim[4] + offset[5];
-      for (i3 = ftile[3]; i3 <= ltile[3]; i3++)
-      {
-        tfpixel[3] = (i3 - 1) * tilesize[3] + 1;
-        tlpixel[3] = minvalue(tfpixel[3] + tilesize[3] - 1, 
-                              naxis[3]);
-        thistilesize[3] = thistilesize[4] * (tlpixel[3] - tfpixel[3] + 1);
-        offset[3] = (i3 - 1) * rowdim[3] + offset[4];
-        for (i2 = ftile[2]; i2 <= ltile[2]; i2++)
-        {
-          tfpixel[2] = (i2 - 1) * tilesize[2] + 1;
-          tlpixel[2] = minvalue(tfpixel[2] + tilesize[2] - 1, 
-                                naxis[2]);
-          thistilesize[2] = thistilesize[3] * (tlpixel[2] - tfpixel[2] + 1);
-          offset[2] = (i2 - 1) * rowdim[2] + offset[3];
-          for (i1 = ftile[1]; i1 <= ltile[1]; i1++)
-          {
-            tfpixel[1] = (i1 - 1) * tilesize[1] + 1;
-            tlpixel[1] = minvalue(tfpixel[1] + tilesize[1] - 1, 
-                                  naxis[1]);
-            thistilesize[1] = thistilesize[2] * (tlpixel[1] - tfpixel[1] + 1);
-            offset[1] = (i1 - 1) * rowdim[1] + offset[2];
-            for (i0 = ftile[0]; i0 <= ltile[0]; i0++)
-            {
-              tfpixel[0] = (i0 - 1) * tilesize[0] + 1;
-              tlpixel[0] = minvalue(tfpixel[0] + tilesize[0] - 1, 
-                                    naxis[0]);
-              thistilesize[0] = thistilesize[1] * (tlpixel[0] - tfpixel[0] + 1);
-              /* calculate row of table containing this tile */
-              irow = i0 + offset[1];
-
-              /* read and uncompress this row (tile) of the table */
-              /* also do type conversion and undefined pixel substitution */
-              /* at this point */
-              imcomp_decompress_tile(fptr, irow, thistilesize[0],
-                    datatype, nullcheck, nullval, buffer, bnullarray, &tilenul,
-                     status);
-
-              if (*status == NO_COMPRESSED_TILE)
-              {
-                   /* tile doesn't exist, so initialize to zero */
-                   memset(buffer, 0, pixlen * thistilesize[0]);
-                   *status = 0;
-              }
-
-              /* copy the intersecting pixels to this tile from the input */
-              imcomp_merge_overlap(buffer, pixlen, ndim, tfpixel, tlpixel, 
-                     bnullarray, array, fpixel, lpixel, nullcheck, status);
-
-              /* compress the tile again, and write it back to the FITS file */
-              imcomp_compress_tile (fptr, irow, datatype, buffer, 
-                                    thistilesize[0],
-				    tlpixel[0] - tfpixel[0] + 1,
-				    tlpixel[1] - tfpixel[1] + 1,
-				    nullcheck, nullval, 
-				    status);
-            }
-          }
-        }
-      }
-     }
-    }
-    free(buffer);
-    
-
-    if ((fptr->Fptr)->zbitpix < 0 && nullcheck != 0) { 
-/*
-     This is a floating point FITS image with possible null values.
-     It is too messy to test if any null values are actually written, so 
-     just assume so.  We need to make sure that the
-     ZBLANK keyword is present in the compressed image header.  If it is not
-     there then we need to insert the keyword. 
-*/   
-        tstatus = 0;
-        ffgcrd(fptr, "ZBLANK", card, &tstatus);
-
-	if (tstatus) {   /* have to insert the ZBLANK keyword */
-           ffgcrd(fptr, "ZCMPTYPE", card, status);
-           ffikyj(fptr, "ZBLANK", COMPRESS_NULL_VALUE, 
-                "null value in the compressed integer array", status);
-	
-           /* set this value into the internal structure; it is used if */
-	   /* the program reads back the values from the array */
-	 
-          (fptr->Fptr)->zblank = COMPRESS_NULL_VALUE;
-          (fptr->Fptr)->cn_zblank = -1;  /* flag for a constant ZBLANK */
-        }  
-    }  
-    
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_write_compressed_pixels(fitsfile *fptr, /* I - FITS file pointer   */
-            int  datatype,  /* I - datatype of the array to be written      */
-            LONGLONG   fpixel,  /* I - 'first pixel to write          */
-            LONGLONG   npixel,  /* I - number of pixels to write      */
-            int  nullcheck,  /* I - 0 for no null checking                   */
-                             /*     1: pixels that are = nullval will be     */
-                             /*     written with the FITS null pixel value   */
-                             /*     (floating point arrays only)             */
-            void *array,      /* I - array of values to write                */
-            void *nullval,    /* I - value used to represent undefined pixels*/
-            int  *status)     /* IO - error status                           */
-/*
-   Write a consecutive set of pixels to a compressed image.  This routine
-   interpretes the n-dimensional image as a long one-dimensional array. 
-   This is actually a rather inconvenient way to write compressed images in
-   general, and could be rather inefficient if the requested pixels to be
-   written are located in many different image compression tiles.    
-
-   The general strategy used here is to write the requested pixels in blocks
-   that correspond to rectangular image sections.  
-*/
-{
-    int naxis, ii, bytesperpixel;
-    long naxes[MAX_COMPRESS_DIM], nread;
-    LONGLONG tfirst, tlast, last0, last1, dimsize[MAX_COMPRESS_DIM];
-    long nplane, firstcoord[MAX_COMPRESS_DIM], lastcoord[MAX_COMPRESS_DIM];
-    char *arrayptr;
-
-    if (*status > 0)
-        return(*status);
-
-    arrayptr = (char *) array;
-
-    /* get size of array pixels, in bytes */
-    bytesperpixel = ffpxsz(datatype);
-
-    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-    {
-        naxes[ii] = 1;
-        firstcoord[ii] = 0;
-        lastcoord[ii] = 0;
-    }
-
-    /*  determine the dimensions of the image to be written */
-    ffgidm(fptr, &naxis, status);
-    ffgisz(fptr, MAX_COMPRESS_DIM, naxes, status);
-
-    /* calc the cumulative number of pixels in each successive dimension */
-    dimsize[0] = 1;
-    for (ii = 1; ii < MAX_COMPRESS_DIM; ii++)
-         dimsize[ii] = dimsize[ii - 1] * naxes[ii - 1];
-
-    /*  determine the coordinate of the first and last pixel in the image */
-    /*  Use zero based indexes here */
-    tfirst = fpixel - 1;
-    tlast = tfirst + npixel - 1;
-    for (ii = naxis - 1; ii >= 0; ii--)
-    {
-        firstcoord[ii] = (long) (tfirst / dimsize[ii]);
-        lastcoord[ii]  = (long) (tlast / dimsize[ii]);
-        tfirst = tfirst - firstcoord[ii] * dimsize[ii];
-        tlast = tlast - lastcoord[ii] * dimsize[ii];
-    }
-
-    /* to simplify things, treat 1-D, 2-D, and 3-D images as separate cases */
-
-    if (naxis == 1)
-    {
-        /* Simple: just write the requested range of pixels */
-
-        firstcoord[0] = firstcoord[0] + 1;
-        lastcoord[0] = lastcoord[0] + 1;
-        fits_write_compressed_img(fptr, datatype, firstcoord, lastcoord,
-            nullcheck, array, nullval, status);
-        return(*status);
-    }
-    else if (naxis == 2)
-    {
-        nplane = 0;  /* write 1st (and only) plane of the image */
-        fits_write_compressed_img_plane(fptr, datatype, bytesperpixel,
-          nplane, firstcoord, lastcoord, naxes, nullcheck,
-          array, nullval, &nread, status);
-    }
-    else if (naxis == 3)
-    {
-        /* test for special case: writing an integral number of planes */
-        if (firstcoord[0] == 0 && firstcoord[1] == 0 &&
-            lastcoord[0] == naxes[0] - 1 && lastcoord[1] == naxes[1] - 1)
-        {
-            for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-            {
-                /* convert from zero base to 1 base */
-                (firstcoord[ii])++;
-                (lastcoord[ii])++;
-            }
-
-            /* we can write the contiguous block of pixels in one go */
-            fits_write_compressed_img(fptr, datatype, firstcoord, lastcoord,
-                nullcheck, array, nullval, status);
-            return(*status);
-        }
-
-        /* save last coordinate in temporary variables */
-        last0 = lastcoord[0];
-        last1 = lastcoord[1];
-
-        if (firstcoord[2] < lastcoord[2])
-        {
-            /* we will write up to the last pixel in all but the last plane */
-            lastcoord[0] = naxes[0] - 1;
-            lastcoord[1] = naxes[1] - 1;
-        }
-
-        /* write one plane of the cube at a time, for simplicity */
-        for (nplane = firstcoord[2]; nplane <= lastcoord[2]; nplane++)
-        {
-            if (nplane == lastcoord[2])
-            {
-                lastcoord[0] = (long) last0;
-                lastcoord[1] = (long) last1;
-            }
-
-            fits_write_compressed_img_plane(fptr, datatype, bytesperpixel,
-              nplane, firstcoord, lastcoord, naxes, nullcheck,
-              arrayptr, nullval, &nread, status);
-
-            /* for all subsequent planes, we start with the first pixel */
-            firstcoord[0] = 0;
-            firstcoord[1] = 0;
-
-            /* increment pointers to next elements to be written */
-            arrayptr = arrayptr + nread * bytesperpixel;
-        }
-    }
-    else
-    {
-        ffpmsg("only 1D, 2D, or 3D images are currently supported");
-        return(*status = DATA_COMPRESSION_ERR);
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_write_compressed_img_plane(fitsfile *fptr, /* I - FITS file    */
-            int  datatype,  /* I - datatype of the array to be written    */
-            int  bytesperpixel, /* I - number of bytes per pixel in array */
-            long   nplane,  /* I - which plane of the cube to write      */
-            long *firstcoord, /* I coordinate of first pixel to write */
-            long *lastcoord,  /* I coordinate of last pixel to write */
-            long *naxes,     /* I size of each image dimension */
-            int  nullcheck,  /* I - 0 for no null checking                   */
-                             /*     1: pixels that are = nullval will be     */
-                             /*     written with the FITS null pixel value   */
-                             /*     (floating point arrays only)             */
-            void *array,      /* I - array of values that are written        */
-            void *nullval,    /* I - value for undefined pixels              */
-            long *nread,      /* O - total number of pixels written          */
-            int  *status)     /* IO - error status                           */
-
-   /*
-           in general we have to write the first partial row of the image,
-           followed by the middle complete rows, followed by the last
-           partial row of the image.  If the first or last rows are complete,
-           then write them at the same time as all the middle rows.
-    */
-{
-    /* bottom left coord. and top right coord. */
-    long blc[MAX_COMPRESS_DIM], trc[MAX_COMPRESS_DIM]; 
-    char *arrayptr;
-
-    *nread = 0;
-
-    arrayptr = (char *) array;
-
-    blc[2] = nplane + 1;
-    trc[2] = nplane + 1;
-
-    if (firstcoord[0] != 0)
-    { 
-            /* have to read a partial first row */
-            blc[0] = firstcoord[0] + 1;
-            blc[1] = firstcoord[1] + 1;
-            trc[1] = blc[1];  
-            if (lastcoord[1] == firstcoord[1])
-               trc[0] = lastcoord[0] + 1; /* 1st and last pixels in same row */
-            else
-               trc[0] = naxes[0];  /* read entire rest of the row */
-
-            fits_write_compressed_img(fptr, datatype, blc, trc,
-                nullcheck, arrayptr, nullval, status);
-
-            *nread = *nread + trc[0] - blc[0] + 1;
-
-            if (lastcoord[1] == firstcoord[1])
-            {
-               return(*status);  /* finished */
-            }
-
-            /* set starting coord to beginning of next line */
-            firstcoord[0] = 0;
-            firstcoord[1] += 1;
-            arrayptr = arrayptr + (trc[0] - blc[0] + 1) * bytesperpixel;
-    }
-
-    /* write contiguous complete rows of the image, if any */
-    blc[0] = 1;
-    blc[1] = firstcoord[1] + 1;
-    trc[0] = naxes[0];
-
-    if (lastcoord[0] + 1 == naxes[0])
-    {
-            /* can write the last complete row, too */
-            trc[1] = lastcoord[1] + 1;
-    }
-    else
-    {
-            /* last row is incomplete; have to read it separately */
-            trc[1] = lastcoord[1];
-    }
-
-    if (trc[1] >= blc[1])  /* must have at least one whole line to read */
-    {
-        fits_write_compressed_img(fptr, datatype, blc, trc,
-                nullcheck, arrayptr, nullval, status);
-
-        *nread = *nread + (trc[1] - blc[1] + 1) * naxes[0];
-
-        if (lastcoord[1] + 1 == trc[1])
-               return(*status);  /* finished */
-
-        /* increment pointers for the last partial row */
-        arrayptr = arrayptr + (trc[1] - blc[1] + 1) * naxes[0] * bytesperpixel;
-
-     }
-
-    if (trc[1] == lastcoord[1] + 1)
-        return(*status);           /* all done */
-
-    /* set starting and ending coord to last line */
-
-    trc[0] = lastcoord[0] + 1;
-    trc[1] = lastcoord[1] + 1;
-    blc[1] = trc[1];
-
-    fits_write_compressed_img(fptr, datatype, blc, trc,
-                nullcheck, arrayptr, nullval, status);
-
-    *nread = *nread + trc[0] - blc[0] + 1;
-
-    return(*status);
-}
-
-/* ######################################################################## */
-/* ###                 Image Decompression Routines                     ### */
-/* ######################################################################## */
-
-/*--------------------------------------------------------------------------*/
-int fits_img_decompress (fitsfile *infptr, /* image (bintable) to uncompress */
-              fitsfile *outfptr,   /* empty HDU for output uncompressed image */
-              int *status)         /* IO - error status               */
-
-/* 
-  This routine decompresses the whole image and writes it to the output file.
-*/
-
-{
-    int ii, datatype = 0;
-    int nullcheck, anynul;
-    LONGLONG fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM];
-    long inc[MAX_COMPRESS_DIM];
-    long imgsize;
-    float *nulladdr, fnulval;
-    double dnulval;
-
-    if (fits_img_decompress_header(infptr, outfptr, status) > 0)
-    {
-    	return (*status);
-    }
-
-    /* force a rescan of the output header keywords, then reset the scaling */
-    /* in case the BSCALE and BZERO keywords are present, so that the       */
-    /* decompressed values won't be scaled when written to the output image */
-    ffrdef(outfptr, status);
-    ffpscl(outfptr, 1.0, 0.0, status);
-    ffpscl(infptr, 1.0, 0.0, status);
-
-    /* initialize; no null checking is needed for integer images */
-    nullcheck = 0;
-    nulladdr =  &fnulval;
-
-    /* determine datatype for image */
-    if ((infptr->Fptr)->zbitpix == BYTE_IMG)
-    {
-        datatype = TBYTE;
-    }
-    else if ((infptr->Fptr)->zbitpix == SHORT_IMG)
-    {
-        datatype = TSHORT;
-    }
-    else if ((infptr->Fptr)->zbitpix == LONG_IMG)
-    {
-        datatype = TINT;
-    }
-    else if ((infptr->Fptr)->zbitpix == FLOAT_IMG)
-    {
-        /* In the case of float images we must check for NaNs  */
-        nullcheck = 1;
-        fnulval = FLOATNULLVALUE;
-        nulladdr =  &fnulval;
-        datatype = TFLOAT;
-    }
-    else if ((infptr->Fptr)->zbitpix == DOUBLE_IMG)
-    {
-        /* In the case of double images we must check for NaNs  */
-        nullcheck = 1;
-        dnulval = DOUBLENULLVALUE;
-        nulladdr = (float *) &dnulval;
-        datatype = TDOUBLE;
-    }
-
-    /* calculate size of the image (in pixels) */
-    imgsize = 1;
-    for (ii = 0; ii < (infptr->Fptr)->zndim; ii++)
-    {
-        imgsize *= (infptr->Fptr)->znaxis[ii];
-        fpixel[ii] = 1;              /* Set first and last pixel to */
-        lpixel[ii] = (infptr->Fptr)->znaxis[ii]; /* include the entire image. */
-        inc[ii] = 1;
-    }
-
-    /* uncompress the input image and write to output image, one tile at a time */
-
-    fits_read_write_compressed_img(infptr, datatype, fpixel, lpixel, inc,  
-            nullcheck, nulladdr, &anynul, outfptr, status);
-
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_decompress_img (fitsfile *infptr, /* image (bintable) to uncompress */
-              fitsfile *outfptr,   /* empty HDU for output uncompressed image */
-              int *status)         /* IO - error status               */
-
-/* 
-  THIS IS AN OBSOLETE ROUTINE.  USE fits_img_decompress instead!!!
-  
-  This routine decompresses the whole image and writes it to the output file.
-*/
-
-{
-    double *data;
-    int ii, datatype = 0, byte_per_pix = 0;
-    int nullcheck, anynul;
-    LONGLONG fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM];
-    long inc[MAX_COMPRESS_DIM];
-    long imgsize, memsize;
-    float *nulladdr, fnulval;
-    double dnulval;
-
-    if (*status > 0)
-        return(*status);
-
-    if (!fits_is_compressed_image(infptr, status) )
-    {
-        ffpmsg("CHDU is not a compressed image (fits_decompress_img)");
-        return(*status = DATA_DECOMPRESSION_ERR);
-    }
-
-    /* create an empty output image with the correct dimensions */
-    if (ffcrim(outfptr, (infptr->Fptr)->zbitpix, (infptr->Fptr)->zndim, 
-       (infptr->Fptr)->znaxis, status) > 0)
-    {
-        ffpmsg("error creating output decompressed image HDU");
-    	return (*status);
-    }
-    /* Copy the table header to the image header. */
-    if (imcomp_copy_imheader(infptr, outfptr, status) > 0)
-    {
-        ffpmsg("error copying header of compressed image");
-    	return (*status);
-    }
-
-    /* force a rescan of the output header keywords, then reset the scaling */
-    /* in case the BSCALE and BZERO keywords are present, so that the       */
-    /* decompressed values won't be scaled when written to the output image */
-    ffrdef(outfptr, status);
-    ffpscl(outfptr, 1.0, 0.0, status);
-    ffpscl(infptr, 1.0, 0.0, status);
-
-    /* initialize; no null checking is needed for integer images */
-    nullcheck = 0;
-    nulladdr =  &fnulval;
-
-    /* determine datatype for image */
-    if ((infptr->Fptr)->zbitpix == BYTE_IMG)
-    {
-        datatype = TBYTE;
-        byte_per_pix = 1;
-    }
-    else if ((infptr->Fptr)->zbitpix == SHORT_IMG)
-    {
-        datatype = TSHORT;
-        byte_per_pix = sizeof(short);
-    }
-    else if ((infptr->Fptr)->zbitpix == LONG_IMG)
-    {
-        datatype = TINT;
-        byte_per_pix = sizeof(int);
-    }
-    else if ((infptr->Fptr)->zbitpix == FLOAT_IMG)
-    {
-        /* In the case of float images we must check for NaNs  */
-        nullcheck = 1;
-        fnulval = FLOATNULLVALUE;
-        nulladdr =  &fnulval;
-        datatype = TFLOAT;
-        byte_per_pix = sizeof(float);
-    }
-    else if ((infptr->Fptr)->zbitpix == DOUBLE_IMG)
-    {
-        /* In the case of double images we must check for NaNs  */
-        nullcheck = 1;
-        dnulval = DOUBLENULLVALUE;
-        nulladdr = (float *) &dnulval;
-        datatype = TDOUBLE;
-        byte_per_pix = sizeof(double);
-    }
-
-    /* calculate size of the image (in pixels) */
-    imgsize = 1;
-    for (ii = 0; ii < (infptr->Fptr)->zndim; ii++)
-    {
-        imgsize *= (infptr->Fptr)->znaxis[ii];
-        fpixel[ii] = 1;              /* Set first and last pixel to */
-        lpixel[ii] = (infptr->Fptr)->znaxis[ii]; /* include the entire image. */
-        inc[ii] = 1;
-    }
-    /* Calc equivalent number of double pixels same size as whole the image. */
-    /* We use double datatype to force the memory to be aligned properly */
-    memsize = ((imgsize * byte_per_pix) - 1) / sizeof(double) + 1;
-
-    /* allocate memory for the image */
-    data = (double*) calloc (memsize, sizeof(double));
-    if (!data)
-    { 
-        ffpmsg("Couldn't allocate memory for the uncompressed image");
-        return(*status = MEMORY_ALLOCATION);
-    }
-
-    /* uncompress the entire image into memory */
-    /* This routine should be enhanced sometime to only need enough */
-    /* memory to uncompress one tile at a time.  */
-    fits_read_compressed_img(infptr, datatype, fpixel, lpixel, inc,  
-            nullcheck, nulladdr, data, NULL, &anynul, status);
-
-    /* write the image to the output file */
-    if (anynul)
-        fits_write_imgnull(outfptr, datatype, 1, imgsize, data, nulladdr, 
-                          status);
-    else
-        fits_write_img(outfptr, datatype, 1, imgsize, data, status);
-
-    free(data);
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_img_decompress_header(fitsfile *infptr, /* image (bintable) to uncompress */
-              fitsfile *outfptr,   /* empty HDU for output uncompressed image */
-              int *status)         /* IO - error status               */
-
-/* 
-  This routine reads the header of the input tile compressed image and 
-  converts it to that of a standard uncompress FITS image.
-*/
-
-{
-    int writeprime = 0;
-    int hdupos, inhdupos, numkeys;
-    int nullprime = 0, copyprime = 0, norec = 0, tstatus;
-    char card[FLEN_CARD];
-    int ii, naxis, bitpix;
-    long naxes[MAX_COMPRESS_DIM];
-
-    if (*status > 0)
-        return(*status);
-    else if (*status == -1) {
-        *status = 0;
-	writeprime = 1;
-    }
-
-    if (!fits_is_compressed_image(infptr, status) )
-    {
-        ffpmsg("CHDU is not a compressed image (fits_img_decompress)");
-        return(*status = DATA_DECOMPRESSION_ERR);
-    }
-
-    /* get information about the state of the output file; does it already */
-    /* contain any keywords and HDUs?  */
-    fits_get_hdu_num(infptr, &inhdupos);  /* Get the current output HDU position */
-    fits_get_hdu_num(outfptr, &hdupos);  /* Get the current output HDU position */
-    fits_get_hdrspace(outfptr, &numkeys, 0, status);
-
-    /* Was the input compressed HDU originally the primary array image? */
-    tstatus = 0;
-    if (!fits_read_card(infptr, "ZSIMPLE", card, &tstatus)) { 
-      /* yes, input HDU was a primary array (not an IMAGE extension) */
-      /* Now determine if we can uncompress it into the primary array of */
-      /* the output file.  This is only possible if the output file */
-      /* currently only contains a null primary array, with no addition */
-      /* header keywords and with no following extension in the FITS file. */
-      
-      if (hdupos == 1) {  /* are we positioned at the primary array? */
-            if (numkeys == 0) { /* primary HDU is completely empty */
-	        nullprime = 1;
-            } else {
-                fits_get_img_param(outfptr, MAX_COMPRESS_DIM, &bitpix, &naxis, naxes, status);
-	
-	        if (naxis == 0) { /* is this a null image? */
-                   nullprime = 1;
-
-		   if (inhdupos == 2)  /* must be at the first extension */
-		      copyprime = 1;
-		}
-           }
-      }
-    } 
-
-    if (nullprime) {  
-       /* We will delete the existing keywords in the null primary array
-          and uncompress the input image into the primary array of the output.
-	  Some of these keywords may be added back to the uncompressed image
-	  header later.
-       */
-
-       for (ii = numkeys; ii > 0; ii--)
-          fits_delete_record(outfptr, ii, status);
-
-    } else  {
-
-       /* if the ZTENSION keyword doesn't exist, then we have to 
-          write the required keywords manually */
-       tstatus = 0;
-       if (fits_read_card(infptr, "ZTENSION", card, &tstatus)) {
-
-          /* create an empty output image with the correct dimensions */
-          if (ffcrim(outfptr, (infptr->Fptr)->zbitpix, (infptr->Fptr)->zndim, 
-             (infptr->Fptr)->znaxis, status) > 0)
-          {
-             ffpmsg("error creating output decompressed image HDU");
-    	     return (*status);
-          }
-
-	  norec = 1;  /* the required keywords have already been written */
-
-       } else {  /* the input compressed image does have ZTENSION keyword */
-       
-          if (writeprime) {  /* convert the image extension to a primary array */
-	      /* have to write the required keywords manually */
-
-              /* create an empty output image with the correct dimensions */
-              if (ffcrim(outfptr, (infptr->Fptr)->zbitpix, (infptr->Fptr)->zndim, 
-                 (infptr->Fptr)->znaxis, status) > 0)
-              {
-                 ffpmsg("error creating output decompressed image HDU");
-    	         return (*status);
-              }
-
-	      norec = 1;  /* the required keywords have already been written */
-
-          } else {  /* write the input compressed image to an image extension */
-
-              if (numkeys == 0) {  /* the output file is currently completely empty */
-	  
-	         /* In this case, the input is a compressed IMAGE extension. */
-	         /* Since the uncompressed output file is currently completely empty, */
-	         /* we need to write a null primary array before uncompressing the */
-                 /* image extension */
-	     
-                 ffcrim(outfptr, 8, 0, naxes, status); /* naxes is not used */
-	     
-	         /* now create the empty extension to uncompress into */
-                 if (fits_create_hdu(outfptr, status) > 0)
-                 {
-                      ffpmsg("error creating output decompressed image HDU");
-    	              return (*status);
-                 }
-	  
-	      } else {
-                  /* just create a new empty extension, then copy all the required */
-	          /* keywords into it.  */
-                 fits_create_hdu(outfptr, status);
-	      }
-           }
-       }
-
-    }
-
-    if (*status > 0)  {
-        ffpmsg("error creating output decompressed image HDU");
-    	return (*status);
-    }
-
-    /* Copy the table header to the image header. */
-
-    if (imcomp_copy_comp2img(infptr, outfptr, norec, status) > 0)
-    {
-        ffpmsg("error copying header keywords from compressed image");
-    }
-
-    if (copyprime) {  
-	/* append any unexpected keywords from the primary array.
-	   This includes any keywords except SIMPLE, BITPIX, NAXIS,
-	   EXTEND, COMMENT, HISTORY, CHECKSUM, and DATASUM.
-	*/
-
-        fits_movabs_hdu(infptr, 1, NULL, status);  /* move to primary array */
-	
-        /* do this so that any new keywords get written before any blank
-	   keywords that may have been appended by imcomp_copy_comp2img  */
-        fits_set_hdustruc(outfptr, status);
-
-        if (imcomp_copy_prime2img(infptr, outfptr, status) > 0)
-        {
-            ffpmsg("error copying primary keywords from compressed file");
-        }
-
-        fits_movabs_hdu(infptr, 2, NULL, status); /* move back to where we were */
-    }
-
-    return (*status);
-}
-/*---------------------------------------------------------------------------*/
-int fits_read_compressed_img(fitsfile *fptr,   /* I - FITS file pointer      */
-            int  datatype,  /* I - datatype of the array to be returned      */
-            LONGLONG  *infpixel, /* I - 'bottom left corner' of the subsection    */
-            LONGLONG  *inlpixel, /* I - 'top right corner' of the subsection      */
-            long  *ininc,    /* I - increment to be applied in each dimension */
-            int  nullcheck,  /* I - 0 for no null checking                   */
-                              /*     1: set undefined pixels = nullval       */
-                              /*     2: set nullarray=1 for undefined pixels */
-            void *nullval,    /* I - value for undefined pixels              */
-            void *array,      /* O - array of values that are returned       */
-            char *nullarray,  /* O - array of flags = 1 if nullcheck = 2     */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-   Read a section of a compressed image;  Note: lpixel may be larger than the 
-   size of the uncompressed image.  Only the pixels within the image will be
-   returned.
-*/
-{
-    long naxis[MAX_COMPRESS_DIM], tiledim[MAX_COMPRESS_DIM];
-    long tilesize[MAX_COMPRESS_DIM], thistilesize[MAX_COMPRESS_DIM];
-    long ftile[MAX_COMPRESS_DIM], ltile[MAX_COMPRESS_DIM];
-    long tfpixel[MAX_COMPRESS_DIM], tlpixel[MAX_COMPRESS_DIM];
-    long rowdim[MAX_COMPRESS_DIM], offset[MAX_COMPRESS_DIM],ntemp;
-    long fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM];
-    long inc[MAX_COMPRESS_DIM];
-    long i5, i4, i3, i2, i1, i0, irow;
-    int ii, ndim, pixlen, tilenul;
-    void *buffer;
-    char *bnullarray = 0;
-    double testnullval = 0.;
-
-    if (*status > 0) 
-        return(*status);
-
-    if (!fits_is_compressed_image(fptr, status) )
-    {
-        ffpmsg("CHDU is not a compressed image (fits_read_compressed_img)");
-        return(*status = DATA_DECOMPRESSION_ERR);
-    }
-
-    /* get temporary space for uncompressing one image tile */
-    if (datatype == TSHORT)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (short)); 
-       pixlen = sizeof(short);
-       if (nullval)
-           testnullval = *(short *) nullval;
-    }
-    else if (datatype == TINT)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (int));
-       pixlen = sizeof(int);
-       if (nullval)
-           testnullval = *(int *) nullval;
-    }
-    else if (datatype == TLONG)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (long));
-       pixlen = sizeof(long);
-       if (nullval)
-           testnullval = *(long *) nullval;
-    }
-    else if (datatype == TFLOAT)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (float));
-       pixlen = sizeof(float);
-       if (nullval)
-           testnullval = *(float *) nullval;
-    }
-    else if (datatype == TDOUBLE)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (double));
-       pixlen = sizeof(double);
-       if (nullval)
-           testnullval = *(double *) nullval;
-    }
-    else if (datatype == TUSHORT)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned short));
-       pixlen = sizeof(short);
-       if (nullval)
-           testnullval = *(unsigned short *) nullval;
-    }
-    else if (datatype == TUINT)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned int));
-       pixlen = sizeof(int);
-       if (nullval)
-           testnullval = *(unsigned int *) nullval;
-    }
-    else if (datatype == TULONG)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned long));
-       pixlen = sizeof(long);
-       if (nullval)
-           testnullval = *(unsigned long *) nullval;
-    }
-    else if (datatype == TBYTE || datatype == TSBYTE)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (char));
-       pixlen = 1;
-       if (nullval)
-           testnullval = *(unsigned char *) nullval;
-    }
-    else
-    {
-        ffpmsg("unsupported datatype for uncompressing image");
-        return(*status = BAD_DATATYPE);
-    }
-
-    /* If nullcheck ==1 and nullval == 0, then this means that the */
-    /* calling routine does not want to check for null pixels in the array */
-    if (nullcheck == 1 && testnullval == 0.)
-        nullcheck = 0;
-
-    if (buffer == NULL)
-    {
-	    ffpmsg("Out of memory (fits_read_compress_img)");
-	    return (*status = MEMORY_ALLOCATION);
-    }
-	
-    /* allocate memory for a null flag array, if needed */
-    if (nullcheck == 2)
-    {
-        bnullarray = calloc ((fptr->Fptr)->maxtilelen, sizeof (char));
-
-        if (bnullarray == NULL)
-        {
-	    ffpmsg("Out of memory (fits_read_compress_img)");
-            free(buffer);
-	    return (*status = MEMORY_ALLOCATION);
-        }
-    }
-
-    /* initialize all the arrays */
-    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-    {
-        naxis[ii] = 1;
-        tiledim[ii] = 1;
-        tilesize[ii] = 1;
-        ftile[ii] = 1;
-        ltile[ii] = 1;
-        rowdim[ii] = 1;
-    }
-
-    ndim = (fptr->Fptr)->zndim;
-    ntemp = 1;
-    for (ii = 0; ii < ndim; ii++)
-    {
-        /* support for mirror-reversed image sections */
-        if (infpixel[ii] <= inlpixel[ii])
-        {
-           fpixel[ii] = (long) infpixel[ii];
-           lpixel[ii] = (long) inlpixel[ii];
-           inc[ii]    = ininc[ii];
-        }
-        else
-        {
-           fpixel[ii] = (long) inlpixel[ii];
-           lpixel[ii] = (long) infpixel[ii];
-           inc[ii]    = -ininc[ii];
-        }
-
-        /* calc number of tiles in each dimension, and tile containing */
-        /* the first and last pixel we want to read in each dimension  */
-        naxis[ii] = (fptr->Fptr)->znaxis[ii];
-        if (fpixel[ii] < 1)
-        {
-            if (nullcheck == 2)
-            {
-                free(bnullarray);
-            }
-            free(buffer);
-            return(*status = BAD_PIX_NUM);
-        }
-
-        tilesize[ii] = (fptr->Fptr)->tilesize[ii];
-        tiledim[ii] = (naxis[ii] - 1) / tilesize[ii] + 1;
-        ftile[ii]   = (fpixel[ii] - 1)   / tilesize[ii] + 1;
-        ltile[ii]   = minvalue((lpixel[ii] - 1) / tilesize[ii] + 1, 
-                                tiledim[ii]);
-        rowdim[ii]  = ntemp;  /* total tiles in each dimension */
-        ntemp *= tiledim[ii];
-    }
-
-    if (anynul)
-       *anynul = 0;  /* initialize */
-
-    /* support up to 6 dimensions for now */
-    /* tfpixel and tlpixel are the first and last image pixels */
-    /* along each dimension of the compression tile */
-    for (i5 = ftile[5]; i5 <= ltile[5]; i5++)
-    {
-     tfpixel[5] = (i5 - 1) * tilesize[5] + 1;
-     tlpixel[5] = minvalue(tfpixel[5] + tilesize[5] - 1, 
-                            naxis[5]);
-     thistilesize[5] = tlpixel[5] - tfpixel[5] + 1;
-     offset[5] = (i5 - 1) * rowdim[5];
-     for (i4 = ftile[4]; i4 <= ltile[4]; i4++)
-     {
-      tfpixel[4] = (i4 - 1) * tilesize[4] + 1;
-      tlpixel[4] = minvalue(tfpixel[4] + tilesize[4] - 1, 
-                            naxis[4]);
-      thistilesize[4] = thistilesize[5] * (tlpixel[4] - tfpixel[4] + 1);
-      offset[4] = (i4 - 1) * rowdim[4] + offset[5];
-      for (i3 = ftile[3]; i3 <= ltile[3]; i3++)
-      {
-        tfpixel[3] = (i3 - 1) * tilesize[3] + 1;
-        tlpixel[3] = minvalue(tfpixel[3] + tilesize[3] - 1, 
-                              naxis[3]);
-        thistilesize[3] = thistilesize[4] * (tlpixel[3] - tfpixel[3] + 1);
-        offset[3] = (i3 - 1) * rowdim[3] + offset[4];
-        for (i2 = ftile[2]; i2 <= ltile[2]; i2++)
-        {
-          tfpixel[2] = (i2 - 1) * tilesize[2] + 1;
-          tlpixel[2] = minvalue(tfpixel[2] + tilesize[2] - 1, 
-                                naxis[2]);
-          thistilesize[2] = thistilesize[3] * (tlpixel[2] - tfpixel[2] + 1);
-          offset[2] = (i2 - 1) * rowdim[2] + offset[3];
-          for (i1 = ftile[1]; i1 <= ltile[1]; i1++)
-          {
-            tfpixel[1] = (i1 - 1) * tilesize[1] + 1;
-            tlpixel[1] = minvalue(tfpixel[1] + tilesize[1] - 1, 
-                                  naxis[1]);
-            thistilesize[1] = thistilesize[2] * (tlpixel[1] - tfpixel[1] + 1);
-            offset[1] = (i1 - 1) * rowdim[1] + offset[2];
-            for (i0 = ftile[0]; i0 <= ltile[0]; i0++)
-            {
-             tfpixel[0] = (i0 - 1) * tilesize[0] + 1;
-             tlpixel[0] = minvalue(tfpixel[0] + tilesize[0] - 1, 
-                                    naxis[0]);
-              thistilesize[0] = thistilesize[1] * (tlpixel[0] - tfpixel[0] + 1);
-              /* calculate row of table containing this tile */
-              irow = i0 + offset[1];
-
-/*
-printf("row %d, %d %d, %d %d, %d %d; %d\n",
-              irow, tfpixel[0],tlpixel[0],tfpixel[1],tlpixel[1],tfpixel[2],tlpixel[2],
-	      thistilesize[0]);
-*/   
-              /* test if there are any intersecting pixels in this tile and the output image */
-              if (imcomp_test_overlap(ndim, tfpixel, tlpixel, 
-                      fpixel, lpixel, inc, status)) {
-                  /* read and uncompress this row (tile) of the table */
-                  /* also do type conversion and undefined pixel substitution */
-                  /* at this point */
-
-                  imcomp_decompress_tile(fptr, irow, thistilesize[0],
-                    datatype, nullcheck, nullval, buffer, bnullarray, &tilenul,
-                     status);
-
-                  if (tilenul && anynul)
-                      *anynul = 1;  /* there are null pixels */
-/*
-printf(" pixlen=%d, ndim=%d, %d %d %d, %d %d %d, %d %d %d\n",
-     pixlen, ndim, fpixel[0],lpixel[0],inc[0],fpixel[1],lpixel[1],inc[1],
-     fpixel[2],lpixel[2],inc[2]);
-*/
-                  /* copy the intersecting pixels from this tile to the output */
-                  imcomp_copy_overlap(buffer, pixlen, ndim, tfpixel, tlpixel, 
-                     bnullarray, array, fpixel, lpixel, inc, nullcheck, 
-                     nullarray, status);
-               }
-            }
-          }
-        }
-      }
-     }
-    }
-    if (nullcheck == 2)
-    {
-        free(bnullarray);
-    }
-    free(buffer);
-
-    return(*status);
-}
-/*---------------------------------------------------------------------------*/
-int fits_read_write_compressed_img(fitsfile *fptr,   /* I - FITS file pointer      */
-            int  datatype,  /* I - datatype of the array to be returned      */
-            LONGLONG  *infpixel, /* I - 'bottom left corner' of the subsection    */
-            LONGLONG  *inlpixel, /* I - 'top right corner' of the subsection      */
-            long  *ininc,    /* I - increment to be applied in each dimension */
-            int  nullcheck,  /* I - 0 for no null checking                   */
-                              /*     1: set undefined pixels = nullval       */
-            void *nullval,    /* I - value for undefined pixels              */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            fitsfile *outfptr,   /* I - FITS file pointer                    */
-            int  *status)     /* IO - error status                           */
-/*
-   This is similar to fits_read_compressed_img, except that it writes
-   the pixels to the output image, on a tile by tile basis instead of returning
-   the array.
-*/
-{
-    long naxis[MAX_COMPRESS_DIM], tiledim[MAX_COMPRESS_DIM];
-    long tilesize[MAX_COMPRESS_DIM], thistilesize[MAX_COMPRESS_DIM];
-    long ftile[MAX_COMPRESS_DIM], ltile[MAX_COMPRESS_DIM];
-    long tfpixel[MAX_COMPRESS_DIM], tlpixel[MAX_COMPRESS_DIM];
-    long rowdim[MAX_COMPRESS_DIM], offset[MAX_COMPRESS_DIM],ntemp;
-    long fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM];
-    long inc[MAX_COMPRESS_DIM];
-    long i5, i4, i3, i2, i1, i0, irow;
-    int ii, ndim, tilenul;
-    void *buffer;
-    char *bnullarray = 0, *cnull;
-    LONGLONG firstelem;
-
-    if (*status > 0) 
-        return(*status);
-
-    if (!fits_is_compressed_image(fptr, status) )
-    {
-        ffpmsg("CHDU is not a compressed image (fits_read_compressed_img)");
-        return(*status = DATA_DECOMPRESSION_ERR);
-    }
-
-    cnull = (char *) nullval;  /* used to test if the nullval = 0 */
-    
-    /* get temporary space for uncompressing one image tile */
-    /* If nullval == 0, then this means that the */
-    /* calling routine does not want to check for null pixels in the array */
-    if (datatype == TSHORT)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (short)); 
-       if (cnull) {
-         if (cnull[0] == 0 && cnull[1] == 0 ) {
-           nullcheck = 0;
-	 }
-       }
-    }
-    else if (datatype == TINT)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (int));
-       if (cnull) {
-         if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ) {
-           nullcheck = 0;
-	 }
-       }
-    }
-    else if (datatype == TLONG)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (long));
-       if (cnull) {
-         if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ) {
-           nullcheck = 0;
-	 }
-       }
-    }
-    else if (datatype == TFLOAT)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (float));
-       if (cnull) {
-         if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0  ) {
-           nullcheck = 0;
-	 }
-       }
-    }
-    else if (datatype == TDOUBLE)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (double));
-       if (cnull) {
-         if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 &&
-	     cnull[4] == 0 && cnull[5] == 0 && cnull[6] == 0 && cnull[7] == 0 ) {
-           nullcheck = 0;
-	 }
-       }
-    }
-    else if (datatype == TUSHORT)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned short));
-       if (cnull) {
-         if (cnull[0] == 0 && cnull[1] == 0 ){
-           nullcheck = 0;
-	 }
-       }
-    }
-    else if (datatype == TUINT)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned int));
-       if (cnull) {
-         if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ){
-           nullcheck = 0;
-	 }
-       }
-    }
-    else if (datatype == TULONG)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned long));
-       if (cnull) {
-         if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ){
-           nullcheck = 0;
-	 }
-       }
-    }
-    else if (datatype == TBYTE || datatype == TSBYTE)
-    {
-       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (char));
-       if (cnull) {
-         if (cnull[0] == 0){
-           nullcheck = 0;
-	 }
-       }
-    }
-    else
-    {
-        ffpmsg("unsupported datatype for uncompressing image");
-        return(*status = BAD_DATATYPE);
-    }
-
-    if (buffer == NULL)
-    {
-	    ffpmsg("Out of memory (fits_read_compress_img)");
-	    return (*status = MEMORY_ALLOCATION);
-    }
-
-    /* initialize all the arrays */
-    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-    {
-        naxis[ii] = 1;
-        tiledim[ii] = 1;
-        tilesize[ii] = 1;
-        ftile[ii] = 1;
-        ltile[ii] = 1;
-        rowdim[ii] = 1;
-    }
-
-    ndim = (fptr->Fptr)->zndim;
-    ntemp = 1;
-    for (ii = 0; ii < ndim; ii++)
-    {
-        /* support for mirror-reversed image sections */
-        if (infpixel[ii] <= inlpixel[ii])
-        {
-           fpixel[ii] = (long) infpixel[ii];
-           lpixel[ii] = (long) inlpixel[ii];
-           inc[ii]    = ininc[ii];
-        }
-        else
-        {
-           fpixel[ii] = (long) inlpixel[ii];
-           lpixel[ii] = (long) infpixel[ii];
-           inc[ii]    = -ininc[ii];
-        }
-
-        /* calc number of tiles in each dimension, and tile containing */
-        /* the first and last pixel we want to read in each dimension  */
-        naxis[ii] = (fptr->Fptr)->znaxis[ii];
-        if (fpixel[ii] < 1)
-        {
-            free(buffer);
-            return(*status = BAD_PIX_NUM);
-        }
-
-        tilesize[ii] = (fptr->Fptr)->tilesize[ii];
-        tiledim[ii] = (naxis[ii] - 1) / tilesize[ii] + 1;
-        ftile[ii]   = (fpixel[ii] - 1)   / tilesize[ii] + 1;
-        ltile[ii]   = minvalue((lpixel[ii] - 1) / tilesize[ii] + 1, 
-                                tiledim[ii]);
-        rowdim[ii]  = ntemp;  /* total tiles in each dimension */
-        ntemp *= tiledim[ii];
-    }
-
-    if (anynul)
-       *anynul = 0;  /* initialize */
-
-    firstelem = 1;
-
-    /* support up to 6 dimensions for now */
-    /* tfpixel and tlpixel are the first and last image pixels */
-    /* along each dimension of the compression tile */
-    for (i5 = ftile[5]; i5 <= ltile[5]; i5++)
-    {
-     tfpixel[5] = (i5 - 1) * tilesize[5] + 1;
-     tlpixel[5] = minvalue(tfpixel[5] + tilesize[5] - 1, 
-                            naxis[5]);
-     thistilesize[5] = tlpixel[5] - tfpixel[5] + 1;
-     offset[5] = (i5 - 1) * rowdim[5];
-     for (i4 = ftile[4]; i4 <= ltile[4]; i4++)
-     {
-      tfpixel[4] = (i4 - 1) * tilesize[4] + 1;
-      tlpixel[4] = minvalue(tfpixel[4] + tilesize[4] - 1, 
-                            naxis[4]);
-      thistilesize[4] = thistilesize[5] * (tlpixel[4] - tfpixel[4] + 1);
-      offset[4] = (i4 - 1) * rowdim[4] + offset[5];
-      for (i3 = ftile[3]; i3 <= ltile[3]; i3++)
-      {
-        tfpixel[3] = (i3 - 1) * tilesize[3] + 1;
-        tlpixel[3] = minvalue(tfpixel[3] + tilesize[3] - 1, 
-                              naxis[3]);
-        thistilesize[3] = thistilesize[4] * (tlpixel[3] - tfpixel[3] + 1);
-        offset[3] = (i3 - 1) * rowdim[3] + offset[4];
-        for (i2 = ftile[2]; i2 <= ltile[2]; i2++)
-        {
-          tfpixel[2] = (i2 - 1) * tilesize[2] + 1;
-          tlpixel[2] = minvalue(tfpixel[2] + tilesize[2] - 1, 
-                                naxis[2]);
-          thistilesize[2] = thistilesize[3] * (tlpixel[2] - tfpixel[2] + 1);
-          offset[2] = (i2 - 1) * rowdim[2] + offset[3];
-          for (i1 = ftile[1]; i1 <= ltile[1]; i1++)
-          {
-            tfpixel[1] = (i1 - 1) * tilesize[1] + 1;
-            tlpixel[1] = minvalue(tfpixel[1] + tilesize[1] - 1, 
-                                  naxis[1]);
-            thistilesize[1] = thistilesize[2] * (tlpixel[1] - tfpixel[1] + 1);
-            offset[1] = (i1 - 1) * rowdim[1] + offset[2];
-            for (i0 = ftile[0]; i0 <= ltile[0]; i0++)
-            {
-              tfpixel[0] = (i0 - 1) * tilesize[0] + 1;
-              tlpixel[0] = minvalue(tfpixel[0] + tilesize[0] - 1, 
-                                    naxis[0]);
-              thistilesize[0] = thistilesize[1] * (tlpixel[0] - tfpixel[0] + 1);
-              /* calculate row of table containing this tile */
-              irow = i0 + offset[1];
- 
-              /* read and uncompress this row (tile) of the table */
-              /* also do type conversion and undefined pixel substitution */
-              /* at this point */
-
-              imcomp_decompress_tile(fptr, irow, thistilesize[0],
-                    datatype, nullcheck, nullval, buffer, bnullarray, &tilenul,
-                     status);
-
-               /* write the image to the output file */
-
-              if (tilenul && anynul) {     
-                   /* this assumes that the tiled pixels are in the same order
-		      as in the uncompressed FITS image.  This is not necessarily
-		      the case, but it almost alway is in practice.  
-		      Note that null checking is not performed for integer images,
-		      so this could only be a problem for tile compressed floating
-		      point images that use an unconventional tiling pattern.
-		   */
-                   fits_write_imgnull(outfptr, datatype, firstelem, thistilesize[0],
-		      buffer, nullval, status);
-              } else {
-                  fits_write_subset(outfptr, datatype, tfpixel, tlpixel, 
-		      buffer, status);
-              }
-
-              firstelem += thistilesize[0];
-
-            }
-          }
-        }
-      }
-     }
-    }
-
-    free(buffer);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_read_compressed_pixels(fitsfile *fptr, /* I - FITS file pointer    */
-            int  datatype,  /* I - datatype of the array to be returned     */
-            LONGLONG   fpixel, /* I - 'first pixel to read          */
-            LONGLONG   npixel,  /* I - number of pixels to read      */
-            int  nullcheck,  /* I - 0 for no null checking                   */
-                              /*     1: set undefined pixels = nullval       */
-                              /*     2: set nullarray=1 for undefined pixels */
-            void *nullval,    /* I - value for undefined pixels              */
-            void *array,      /* O - array of values that are returned       */
-            char *nullarray,  /* O - array of flags = 1 if nullcheck = 2     */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            int  *status)     /* IO - error status                           */
-/*
-   Read a consecutive set of pixels from a compressed image.  This routine
-   interpretes the n-dimensional image as a long one-dimensional array. 
-   This is actually a rather inconvenient way to read compressed images in
-   general, and could be rather inefficient if the requested pixels to be
-   read are located in many different image compression tiles.    
-
-   The general strategy used here is to read the requested pixels in blocks
-   that correspond to rectangular image sections.  
-*/
-{
-    int naxis, ii, bytesperpixel, planenul;
-    long naxes[MAX_COMPRESS_DIM], nread;
-    long nplane, inc[MAX_COMPRESS_DIM];
-    LONGLONG tfirst, tlast, last0, last1, dimsize[MAX_COMPRESS_DIM];
-    LONGLONG firstcoord[MAX_COMPRESS_DIM], lastcoord[MAX_COMPRESS_DIM];
-    char *arrayptr, *nullarrayptr;
-
-    if (*status > 0)
-        return(*status);
-
-    arrayptr = (char *) array;
-    nullarrayptr = nullarray;
-
-    /* get size of array pixels, in bytes */
-    bytesperpixel = ffpxsz(datatype);
-
-    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-    {
-        naxes[ii] = 1;
-        firstcoord[ii] = 0;
-        lastcoord[ii] = 0;
-        inc[ii] = 1;
-    }
-
-    /*  determine the dimensions of the image to be read */
-    ffgidm(fptr, &naxis, status);
-    ffgisz(fptr, MAX_COMPRESS_DIM, naxes, status);
-
-    /* calc the cumulative number of pixels in each successive dimension */
-    dimsize[0] = 1;
-    for (ii = 1; ii < MAX_COMPRESS_DIM; ii++)
-         dimsize[ii] = dimsize[ii - 1] * naxes[ii - 1];
-
-    /*  determine the coordinate of the first and last pixel in the image */
-    /*  Use zero based indexes here */
-    tfirst = fpixel - 1;
-    tlast = tfirst + npixel - 1;
-    for (ii = naxis - 1; ii >= 0; ii--)
-    {
-        firstcoord[ii] = tfirst / dimsize[ii];
-        lastcoord[ii] =  tlast / dimsize[ii];
-        tfirst = tfirst - firstcoord[ii] * dimsize[ii];
-        tlast = tlast - lastcoord[ii] * dimsize[ii];
-    }
-
-    /* to simplify things, treat 1-D, 2-D, and 3-D images as separate cases */
-
-    if (naxis == 1)
-    {
-        /* Simple: just read the requested range of pixels */
-
-        firstcoord[0] = firstcoord[0] + 1;
-        lastcoord[0] = lastcoord[0] + 1;
-        fits_read_compressed_img(fptr, datatype, firstcoord, lastcoord, inc,
-            nullcheck, nullval, array, nullarray, anynul, status);
-        return(*status);
-    }
-    else if (naxis == 2)
-    {
-        nplane = 0;  /* read 1st (and only) plane of the image */
-
-        fits_read_compressed_img_plane(fptr, datatype, bytesperpixel,
-          nplane, firstcoord, lastcoord, inc, naxes, nullcheck, nullval,
-          array, nullarray, anynul, &nread, status);
-    }
-    else if (naxis == 3)
-    {
-        /* test for special case: reading an integral number of planes */
-        if (firstcoord[0] == 0 && firstcoord[1] == 0 &&
-            lastcoord[0] == naxes[0] - 1 && lastcoord[1] == naxes[1] - 1)
-        {
-            for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-            {
-                /* convert from zero base to 1 base */
-                (firstcoord[ii])++;
-                (lastcoord[ii])++;
-            }
-
-            /* we can read the contiguous block of pixels in one go */
-            fits_read_compressed_img(fptr, datatype, firstcoord, lastcoord, inc,
-                nullcheck, nullval, array, nullarray, anynul, status);
-
-            return(*status);
-        }
-
-        if (anynul)
-            *anynul = 0;  /* initialize */
-
-        /* save last coordinate in temporary variables */
-        last0 = lastcoord[0];
-        last1 = lastcoord[1];
-
-        if (firstcoord[2] < lastcoord[2])
-        {
-            /* we will read up to the last pixel in all but the last plane */
-            lastcoord[0] = naxes[0] - 1;
-            lastcoord[1] = naxes[1] - 1;
-        }
-
-        /* read one plane of the cube at a time, for simplicity */
-        for (nplane = (long) firstcoord[2]; nplane <= lastcoord[2]; nplane++)
-        {
-            if (nplane == lastcoord[2])
-            {
-                lastcoord[0] = last0;
-                lastcoord[1] = last1;
-            }
-
-            fits_read_compressed_img_plane(fptr, datatype, bytesperpixel,
-              nplane, firstcoord, lastcoord, inc, naxes, nullcheck, nullval,
-              arrayptr, nullarrayptr, &planenul, &nread, status);
-
-            if (planenul && anynul)
-               *anynul = 1;  /* there are null pixels */
-
-            /* for all subsequent planes, we start with the first pixel */
-            firstcoord[0] = 0;
-            firstcoord[1] = 0;
-
-            /* increment pointers to next elements to be read */
-            arrayptr = arrayptr + nread * bytesperpixel;
-            if (nullarrayptr && (nullcheck == 2) )
-                nullarrayptr = nullarrayptr + nread;
-        }
-    }
-    else
-    {
-        ffpmsg("only 1D, 2D, or 3D images are currently supported");
-        return(*status = DATA_DECOMPRESSION_ERR);
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_read_compressed_img_plane(fitsfile *fptr, /* I - FITS file   */
-            int  datatype,  /* I - datatype of the array to be returned      */
-            int  bytesperpixel, /* I - number of bytes per pixel in array */
-            long   nplane,  /* I - which plane of the cube to read      */
-            LONGLONG *firstcoord,  /* coordinate of first pixel to read */
-            LONGLONG *lastcoord,   /* coordinate of last pixel to read */
-            long *inc,         /* increment of pixels to read */
-            long *naxes,      /* size of each image dimension */
-            int  nullcheck,  /* I - 0 for no null checking                   */
-                              /*     1: set undefined pixels = nullval       */
-                              /*     2: set nullarray=1 for undefined pixels */
-            void *nullval,    /* I - value for undefined pixels              */
-            void *array,      /* O - array of values that are returned       */
-            char *nullarray,  /* O - array of flags = 1 if nullcheck = 2     */
-            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
-            long *nread,      /* O - total number of pixels read and returned*/
-            int  *status)     /* IO - error status                           */
-
-   /*
-           in general we have to read the first partial row of the image,
-           followed by the middle complete rows, followed by the last
-           partial row of the image.  If the first or last rows are complete,
-           then read them at the same time as all the middle rows.
-    */
-{
-     /* bottom left coord. and top right coord. */
-    LONGLONG blc[MAX_COMPRESS_DIM], trc[MAX_COMPRESS_DIM]; 
-    char *arrayptr, *nullarrayptr;
-    int tnull;
-
-    if (anynul)
-        *anynul = 0;
-
-    *nread = 0;
-
-    arrayptr = (char *) array;
-    nullarrayptr = nullarray;
-
-    blc[2] = nplane + 1;
-    trc[2] = nplane + 1;
-
-    if (firstcoord[0] != 0)
-    { 
-            /* have to read a partial first row */
-            blc[0] = firstcoord[0] + 1;
-            blc[1] = firstcoord[1] + 1;
-            trc[1] = blc[1];  
-            if (lastcoord[1] == firstcoord[1])
-               trc[0] = lastcoord[0] + 1; /* 1st and last pixels in same row */
-            else
-               trc[0] = naxes[0];  /* read entire rest of the row */
-
-            fits_read_compressed_img(fptr, datatype, blc, trc, inc,
-                nullcheck, nullval, arrayptr, nullarrayptr, &tnull, status);
-
-            *nread = *nread + (long) (trc[0] - blc[0] + 1);
-
-            if (tnull && anynul)
-               *anynul = 1;  /* there are null pixels */
-
-            if (lastcoord[1] == firstcoord[1])
-            {
-               return(*status);  /* finished */
-            }
-
-            /* set starting coord to beginning of next line */
-            firstcoord[0] = 0;
-            firstcoord[1] += 1;
-            arrayptr = arrayptr + (trc[0] - blc[0] + 1) * bytesperpixel;
-            if (nullarrayptr && (nullcheck == 2) )
-                nullarrayptr = nullarrayptr + (trc[0] - blc[0] + 1);
-
-    }
-
-    /* read contiguous complete rows of the image, if any */
-    blc[0] = 1;
-    blc[1] = firstcoord[1] + 1;
-    trc[0] = naxes[0];
-
-    if (lastcoord[0] + 1 == naxes[0])
-    {
-            /* can read the last complete row, too */
-            trc[1] = lastcoord[1] + 1;
-    }
-    else
-    {
-            /* last row is incomplete; have to read it separately */
-            trc[1] = lastcoord[1];
-    }
-
-    if (trc[1] >= blc[1])  /* must have at least one whole line to read */
-    {
-        fits_read_compressed_img(fptr, datatype, blc, trc, inc,
-                nullcheck, nullval, arrayptr, nullarrayptr, &tnull, status);
-
-        *nread = *nread + (long) ((trc[1] - blc[1] + 1) * naxes[0]);
-
-        if (tnull && anynul)
-           *anynul = 1;
-
-        if (lastcoord[1] + 1 == trc[1])
-               return(*status);  /* finished */
-
-        /* increment pointers for the last partial row */
-        arrayptr = arrayptr + (trc[1] - blc[1] + 1) * naxes[0] * bytesperpixel;
-        if (nullarrayptr && (nullcheck == 2) )
-                nullarrayptr = nullarrayptr + (trc[1] - blc[1] + 1) * naxes[0];
-     }
-
-    if (trc[1] == lastcoord[1] + 1)
-        return(*status);           /* all done */
-
-    /* set starting and ending coord to last line */
-
-    trc[0] = lastcoord[0] + 1;
-    trc[1] = lastcoord[1] + 1;
-    blc[1] = trc[1];
-
-    fits_read_compressed_img(fptr, datatype, blc, trc, inc,
-                nullcheck, nullval, arrayptr, nullarrayptr, &tnull, status);
-
-    if (tnull && anynul)
-       *anynul = 1;
-
-    *nread = *nread + (long) (trc[0] - blc[0] + 1);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_get_compressed_image_par(fitsfile *infptr, int *status)
- 
-/* 
-    This routine reads keywords from a BINTABLE extension containing a
-    compressed image.
-*/
-{
-    char keyword[FLEN_KEYWORD];
-    char value[FLEN_VALUE];
-    int ii, tstatus, doffset;
-    long expect_nrows, maxtilelen;
-
-    if (*status > 0)
-        return(*status);
-
-    /* Copy relevant header keyword values to structure */
-    if (ffgky (infptr, TSTRING, "ZCMPTYPE", value, NULL, status) > 0)
-    {
-        ffpmsg("required ZCMPTYPE compression keyword not found in");
-        ffpmsg(" imcomp_get_compressed_image_par");
-        return(*status);
-    }
-
-    (infptr->Fptr)->zcmptype[0] = '\0';
-    strncat((infptr->Fptr)->zcmptype, value, 11);
-
-    if (!FSTRCMP(value, "RICE_1") || !FSTRCMP(value, "RICE_ONE") )
-        (infptr->Fptr)->compress_type = RICE_1;
-    else if (!FSTRCMP(value, "HCOMPRESS_1") )
-        (infptr->Fptr)->compress_type = HCOMPRESS_1;
-    else if (!FSTRCMP(value, "GZIP_1") )
-        (infptr->Fptr)->compress_type = GZIP_1;
-    else if (!FSTRCMP(value, "GZIP_2") )
-        (infptr->Fptr)->compress_type = GZIP_2;
-    else if (!FSTRCMP(value, "BZIP2_1") )
-        (infptr->Fptr)->compress_type = BZIP2_1;
-    else if (!FSTRCMP(value, "PLIO_1") )
-        (infptr->Fptr)->compress_type = PLIO_1;
-    else if (!FSTRCMP(value, "NOCOMPRESS") )
-        (infptr->Fptr)->compress_type = NOCOMPRESS;
-    else
-    {
-        ffpmsg("Unknown image compression type:");
-        ffpmsg(value);
-	return (*status = DATA_DECOMPRESSION_ERR);
-    }
-
-    /* get the floating point to integer quantization type, if present. */
-    /* FITS files produced before 2009 will not have this keyword */
-    tstatus = 0;
-    if (ffgky(infptr, TSTRING, "ZQUANTIZ", value, NULL, &tstatus) > 0)
-    {
-        (infptr->Fptr)->quantize_method = 0;
-    } else {
-
-        if (!FSTRCMP(value, "NONE") ) {
-            (infptr->Fptr)->quantize_level = NO_QUANTIZE;
-       } else if (!FSTRCMP(value, "SUBTRACTIVE_DITHER_1") )
-            (infptr->Fptr)->quantize_method = SUBTRACTIVE_DITHER_1;
-        else if (!FSTRCMP(value, "SUBTRACTIVE_DITHER_2") )
-            (infptr->Fptr)->quantize_method = SUBTRACTIVE_DITHER_2;
-        else if (!FSTRCMP(value, "NO_DITHER") )
-            (infptr->Fptr)->quantize_method = NO_DITHER;
-        else
-            (infptr->Fptr)->quantize_method = 0;
-    }
-
-    /* get the floating point quantization dithering offset, if present. */
-    /* FITS files produced before October 2009 will not have this keyword */
-    tstatus = 0;
-    if (ffgky(infptr, TINT, "ZDITHER0", &doffset, NULL, &tstatus) > 0)
-    {
-	/* by default start with 1st element of random sequence */
-        (infptr->Fptr)->dither_seed = 1;  
-    } else {
-        (infptr->Fptr)->dither_seed = doffset;
-    }
-
-    if (ffgky (infptr, TINT,  "ZBITPIX",  &(infptr->Fptr)->zbitpix,  
-               NULL, status) > 0)
-    {
-        ffpmsg("required ZBITPIX compression keyword not found");
-        return(*status);
-    }
-
-    if (ffgky (infptr,TINT, "ZNAXIS", &(infptr->Fptr)->zndim, NULL, status) > 0)
-    {
-        ffpmsg("required ZNAXIS compression keyword not found");
-        return(*status);
-    }
-
-    if ((infptr->Fptr)->zndim < 1)
-    {
-        ffpmsg("Compressed image has no data (ZNAXIS < 1)");
-	return (*status = BAD_NAXIS);
-    }
-
-    if ((infptr->Fptr)->zndim > MAX_COMPRESS_DIM)
-    {
-        ffpmsg("Compressed image has too many dimensions");
-        return(*status = BAD_NAXIS);
-    }
-
-    expect_nrows = 1;
-    maxtilelen = 1;
-    for (ii = 0;  ii < (infptr->Fptr)->zndim;  ii++)
-    {
-        /* get image size */
-        sprintf (keyword, "ZNAXIS%d", ii+1);
-	ffgky (infptr, TLONG,keyword, &(infptr->Fptr)->znaxis[ii],NULL,status);
-
-        if (*status > 0)
-        {
-            ffpmsg("required ZNAXISn compression keyword not found");
-            return(*status);
-        }
-
-        /* get compression tile size */
-	sprintf (keyword, "ZTILE%d", ii+1);
-
-        /* set default tile size in case keywords are not present */
-        if (ii == 0)
-            (infptr->Fptr)->tilesize[0] = (infptr->Fptr)->znaxis[0];
-        else
-            (infptr->Fptr)->tilesize[ii] = 1;
-
-        tstatus = 0;
-	ffgky (infptr, TLONG, keyword, &(infptr->Fptr)->tilesize[ii], NULL, 
-               &tstatus);
-
-        expect_nrows *= (((infptr->Fptr)->znaxis[ii] - 1) / 
-                  (infptr->Fptr)->tilesize[ii]+ 1);
-        maxtilelen *= (infptr->Fptr)->tilesize[ii];
-    }
-
-    /* check number of rows */
-    if (expect_nrows != (infptr->Fptr)->numrows)
-    {
-        ffpmsg(
-        "number of table rows != the number of tiles in compressed image");
-        return (*status = DATA_DECOMPRESSION_ERR);
-    }
-
-    /* read any algorithm specific parameters */
-    if ((infptr->Fptr)->compress_type == RICE_1 )
-    {
-        if (ffgky(infptr, TINT,"ZVAL1", &(infptr->Fptr)->rice_blocksize,
-                  NULL, status) > 0)
-        {
-            ffpmsg("required ZVAL1 compression keyword not found");
-            return(*status);
-        }
-
-        tstatus = 0;
-        if (ffgky(infptr, TINT,"ZVAL2", &(infptr->Fptr)->rice_bytepix,
-                  NULL, &tstatus) > 0)
-        {
-            (infptr->Fptr)->rice_bytepix = 4;  /* default value */
-        }
-
-        if ((infptr->Fptr)->rice_blocksize < 16 &&
-	    (infptr->Fptr)->rice_bytepix > 8) {
-	     /* values are reversed */
-	     tstatus = (infptr->Fptr)->rice_bytepix;
-	     (infptr->Fptr)->rice_bytepix = (infptr->Fptr)->rice_blocksize;
-	     (infptr->Fptr)->rice_blocksize = tstatus;
-        }
-    } else if ((infptr->Fptr)->compress_type == HCOMPRESS_1 ) {
-
-        if (ffgky(infptr, TFLOAT,"ZVAL1", &(infptr->Fptr)->hcomp_scale,
-                  NULL, status) > 0)
-        {
-            ffpmsg("required ZVAL1 compression keyword not found");
-            return(*status);
-        }
-
-        tstatus = 0;
-        ffgky(infptr, TINT,"ZVAL2", &(infptr->Fptr)->hcomp_smooth,
-                  NULL, &tstatus);
-    }    
-
-    /* store number of pixels in each compression tile, */
-    /* and max size of the compressed tile buffer */
-    (infptr->Fptr)->maxtilelen = maxtilelen;
-
-    (infptr->Fptr)->maxelem = 
-           imcomp_calc_max_elem ((infptr->Fptr)->compress_type, maxtilelen, 
-               (infptr->Fptr)->zbitpix, (infptr->Fptr)->rice_blocksize);
-
-    /* Get Column numbers. */
-    if (ffgcno(infptr, CASEINSEN, "COMPRESSED_DATA",
-         &(infptr->Fptr)->cn_compressed, status) > 0)
-    {
-        ffpmsg("couldn't find COMPRESSED_DATA column (fits_get_compressed_img_par)");
-        return(*status = DATA_DECOMPRESSION_ERR);
-    }
-
-    ffpmrk(); /* put mark on message stack; erase any messages after this */
-
-    tstatus = 0;
-    ffgcno(infptr,CASEINSEN, "UNCOMPRESSED_DATA",
-          &(infptr->Fptr)->cn_uncompressed, &tstatus);
-
-    tstatus = 0;
-    ffgcno(infptr,CASEINSEN, "GZIP_COMPRESSED_DATA",
-          &(infptr->Fptr)->cn_gzip_data, &tstatus);
-
-    tstatus = 0;
-    if (ffgcno(infptr, CASEINSEN, "ZSCALE", &(infptr->Fptr)->cn_zscale,
-              &tstatus) > 0)
-    {
-        /* CMPSCALE column doesn't exist; see if there is a keyword */
-        tstatus = 0;
-        if (ffgky(infptr, TDOUBLE, "ZSCALE", &(infptr->Fptr)->zscale, NULL, 
-                 &tstatus) <= 0)
-            (infptr->Fptr)->cn_zscale = -1;  /* flag for a constant ZSCALE */
-    }
-
-    tstatus = 0;
-    if (ffgcno(infptr, CASEINSEN, "ZZERO", &(infptr->Fptr)->cn_zzero,
-               &tstatus) > 0)
-    {
-        /* CMPZERO column doesn't exist; see if there is a keyword */
-        tstatus = 0;
-        if (ffgky(infptr, TDOUBLE, "ZZERO", &(infptr->Fptr)->zzero, NULL, 
-                  &tstatus) <= 0)
-            (infptr->Fptr)->cn_zzero = -1;  /* flag for a constant ZZERO */
-    }
-
-    tstatus = 0;
-    if (ffgcno(infptr, CASEINSEN, "ZBLANK", &(infptr->Fptr)->cn_zblank,
-               &tstatus) > 0)
-    {
-        /* ZBLANK column doesn't exist; see if there is a keyword */
-        tstatus = 0;
-        if (ffgky(infptr, TINT, "ZBLANK", &(infptr->Fptr)->zblank, NULL,
-                  &tstatus) <= 0)  {
-            (infptr->Fptr)->cn_zblank = -1;  /* flag for a constant ZBLANK */
-
-        } else {
-           /* ZBLANK keyword doesn't exist; see if there is a BLANK keyword */
-           tstatus = 0;
-           if (ffgky(infptr, TINT, "BLANK", &(infptr->Fptr)->zblank, NULL,
-                  &tstatus) <= 0)  
-              (infptr->Fptr)->cn_zblank = -1;  /* flag for a constant ZBLANK */
-        }
-    }
-
-    /* read the conventional BSCALE and BZERO scaling keywords, if present */
-    tstatus = 0;
-    if (ffgky (infptr, TDOUBLE, "BSCALE", &(infptr->Fptr)->cn_bscale, 
-        NULL, &tstatus) > 0)
-    {
-        (infptr->Fptr)->cn_bscale = 1.0;
-    }
-
-    tstatus = 0;
-    if (ffgky (infptr, TDOUBLE, "BZERO", &(infptr->Fptr)->cn_bzero, 
-        NULL, &tstatus) > 0)
-    {
-        (infptr->Fptr)->cn_bzero = 0.0;
-        (infptr->Fptr)->cn_actual_bzero = 0.0;
-    } else {
-        (infptr->Fptr)->cn_actual_bzero = (infptr->Fptr)->cn_bzero;
-    }
-
-    /* special case: the quantization level is not given by a keyword in  */
-    /* the HDU header, so we have to explicitly copy the requested value */
-    /* to the actual value */
-    if ( (infptr->Fptr)->request_quantize_level != 0.)
-        (infptr->Fptr)->quantize_level = (infptr->Fptr)->request_quantize_level;
-
-    ffcmrk();  /* clear any spurious error messages, back to the mark */
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_copy_imheader(fitsfile *infptr, fitsfile *outfptr, int *status)
-/*
-    This routine reads the header keywords from the input image and
-    copies them to the output image;  the manditory structural keywords
-    and the checksum keywords are not copied. If the DATE keyword is copied,
-    then it is updated with the current date and time.
-*/
-{
-    int nkeys, ii, keyclass;
-    char card[FLEN_CARD];	/* a header record */
-
-    if (*status > 0)
-        return(*status);
-
-    ffghsp(infptr, &nkeys, NULL, status); /* get number of keywords in image */
-
-    for (ii = 5; ii <= nkeys; ii++)  /* skip the first 4 keywords */
-    {
-        ffgrec(infptr, ii, card, status);
-
-	keyclass = ffgkcl(card);  /* Get the type/class of keyword */
-
-        /* don't copy structural keywords or checksum keywords */
-        if ((keyclass <= TYP_CMPRS_KEY) || (keyclass == TYP_CKSUM_KEY))
-	    continue;
-
-        if (FSTRNCMP(card, "DATE ", 5) == 0) /* write current date */
-        {
-            ffpdat(outfptr, status);
-        }
-        else if (FSTRNCMP(card, "EXTNAME ", 8) == 0) 
-        {
-            /* don't copy default EXTNAME keyword from a compressed image */
-            if (FSTRNCMP(card, "EXTNAME = 'COMPRESSED_IMAGE'", 28))
-            {
-                /* if EXTNAME keyword already exists, overwrite it */
-                /* otherwise append a new EXTNAME keyword */
-                ffucrd(outfptr, "EXTNAME", card, status);
-            }
-        }
-        else
-        {
-            /* just copy the keyword to the output header */
-	    ffprec (outfptr, card, status);
-        }
-
-        if (*status > 0)
-           return (*status);
-    }
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_copy_img2comp(fitsfile *infptr, fitsfile *outfptr, int *status)
-/*
-    This routine copies the header keywords from the uncompressed input image 
-    and to the compressed image (in a binary table) 
-*/
-{
-    char card[FLEN_CARD], card2[FLEN_CARD];	/* a header record */
-    int nkeys, nmore, ii, jj, tstatus, bitpix;
-
-    /* tile compressed image keyword translation table  */
-    /*                        INPUT      OUTPUT  */
-    /*                       01234567   01234567 */
-    char *patterns[][2] = {{"SIMPLE",  "ZSIMPLE" },  
-			   {"XTENSION", "ZTENSION" },
-			   {"BITPIX",  "ZBITPIX" },
-			   {"NAXIS",   "ZNAXIS"  },
-			   {"NAXISm",  "ZNAXISm" },
-			   {"EXTEND",  "ZEXTEND" },
-			   {"BLOCKED", "ZBLOCKED"},
-			   {"PCOUNT",  "ZPCOUNT" },  
-			   {"GCOUNT",  "ZGCOUNT" },
-
-			   {"CHECKSUM","ZHECKSUM"},  /* save original checksums */
-			   {"DATASUM", "ZDATASUM"},
-			   
-			   {"*",       "+"       }}; /* copy all other keywords */
-    int npat;
-
-    if (*status > 0)
-        return(*status);
-
-    /* write a default EXTNAME keyword if it doesn't exist in input file*/
-    fits_read_card(infptr, "EXTNAME", card, status);
-    
-    if (*status) {
-       *status = 0;
-       strcpy(card, "EXTNAME = 'COMPRESSED_IMAGE'");
-       fits_write_record(outfptr, card, status);
-    }
-
-    /* copy all the keywords from the input file to the output */
-    npat = sizeof(patterns)/sizeof(patterns[0][0])/2;
-    fits_translate_keywords(infptr, outfptr, 1, patterns, npat,
-			    0, 0, 0, status);
-
-
-    if ( (outfptr->Fptr)->request_lossy_int_compress != 0) { 
-
-	/* request was made to compress integer images as if they had float pixels. */
-	/* If input image has positive bitpix value, then reset the output ZBITPIX */
-	/* value to -32. */
-
-	fits_read_key(infptr, TINT, "BITPIX", &bitpix, NULL, status);
-
-	if (*status <= 0 && bitpix > 0) {
-	    fits_modify_key_lng(outfptr, "ZBITPIX", -32, NULL, status);
-
-	    /* also delete the BSCALE, BZERO, and BLANK keywords */
-	    tstatus = 0;
-	    fits_delete_key(outfptr, "BSCALE", &tstatus);
-	    tstatus = 0;
-	    fits_delete_key(outfptr, "BZERO", &tstatus);
-	    tstatus = 0;
-	    fits_delete_key(outfptr, "BLANK", &tstatus);
-	}
-    }
-
-   /*
-     For compatibility with software that uses an older version of CFITSIO,
-     we must make certain that the new ZQUANTIZ keyword, if it exists, must
-     occur after the other peudo-required keywords (e.g., ZSIMPLE, ZBITPIX,
-     etc.).  Do this by trying to delete the keyword.  If that succeeds (and
-     thus the keyword did exist) then rewrite the keyword at the end of header.
-     In principle this should not be necessary once all software has upgraded
-     to a newer version of CFITSIO (version number greater than 3.181, newer
-     than August 2009).
-     
-     Do the same for the new ZDITHER0 keyword.
-   */
-
-   tstatus = 0;
-   if (fits_read_card(outfptr, "ZQUANTIZ", card, &tstatus) == 0)
-   {
-        fits_delete_key(outfptr, "ZQUANTIZ", status);
-
-        /* rewrite the deleted keyword at the end of the header */
-        fits_write_record(outfptr, card, status);
-
-	/* write some associated HISTORY keywords */
-        fits_parse_value(card, card2, NULL, status);
-	if (fits_strncasecmp(card2, "'NONE", 5) ) {
-	    /* the value is not 'NONE' */	
-	    fits_write_history(outfptr, 
-	        "Image was compressed by CFITSIO using scaled integer quantization:", status);
-	    sprintf(card2, "  q = %f / quantized level scaling parameter", 
-	        (outfptr->Fptr)->request_quantize_level);
-	    fits_write_history(outfptr, card2, status); 
-	    fits_write_history(outfptr, card+10, status); 
-	}
-   }
-
-   tstatus = 0;
-   if (fits_read_card(outfptr, "ZDITHER0", card, &tstatus) == 0)
-   {
-        fits_delete_key(outfptr, "ZDITHER0", status);
-
-        /* rewrite the deleted keyword at the end of the header */
-        fits_write_record(outfptr, card, status);
-   }
-
-
-    ffghsp(infptr, &nkeys, &nmore, status); /* get number of keywords in image */
-
-    nmore = nmore / 36;  /* how many completely empty header blocks are there? */
-     
-     /* preserve the same number of spare header blocks in the output header */
-     
-    for (jj = 0; jj < nmore; jj++)
-       for (ii = 0; ii < 36; ii++)
-          fits_write_record(outfptr, "    ", status);
-
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_copy_comp2img(fitsfile *infptr, fitsfile *outfptr, 
-                          int norec, int *status)
-/*
-    This routine copies the header keywords from the compressed input image 
-    and to the uncompressed image (in a binary table) 
-*/
-{
-    char card[FLEN_CARD];	/* a header record */
-    char *patterns[40][2];
-    char negative[] = "-";
-    int ii,jj, npat, nreq, nsp, tstatus = 0;
-    int nkeys, nmore;
-    
-    /* tile compressed image keyword translation table  */
-    /*                        INPUT      OUTPUT  */
-    /*                       01234567   01234567 */
-
-    /*  only translate these if required keywords not already written */
-    char *reqkeys[][2] = {  
-			   {"ZSIMPLE",   "SIMPLE" },  
-			   {"ZTENSION", "XTENSION"},
-			   {"ZBITPIX",   "BITPIX" },
-			   {"ZNAXIS",    "NAXIS"  },
-			   {"ZNAXISm",   "NAXISm" },
-			   {"ZEXTEND",   "EXTEND" },
-			   {"ZBLOCKED",  "BLOCKED"},
-			   {"ZPCOUNT",   "PCOUNT" },  
-			   {"ZGCOUNT",   "GCOUNT" },
-			   {"ZHECKSUM",  "CHECKSUM"},  /* restore original checksums */
-			   {"ZDATASUM",  "DATASUM"}}; 
-
-    /* other special keywords */
-    char *spkeys[][2] = {
-			   {"XTENSION", "-"      },
-			   {"BITPIX",  "-"       },
-			   {"NAXIS",   "-"       },
-			   {"NAXISm",  "-"       },
-			   {"PCOUNT",  "-"       },
-			   {"GCOUNT",  "-"       },
-			   {"TFIELDS", "-"       },
-			   {"TTYPEm",  "-"       },
-			   {"TFORMm",  "-"       },
-			   {"THEAP",   "-"       },
-			   {"ZIMAGE",  "-"       },
-			   {"ZQUANTIZ", "-"      },
-			   {"ZDITHER0", "-"      },
-			   {"ZTILEm",  "-"       },
-			   {"ZCMPTYPE", "-"      },
-			   {"ZBLANK",  "-"       },
-			   {"ZNAMEm",  "-"       },
-			   {"ZVALm",   "-"       },
-
-			   {"CHECKSUM","-"       },  /* delete checksums */
-			   {"DATASUM", "-"       },
-			   {"EXTNAME", "+"       },  /* we may change this, below */
-			   {"*",       "+"      }};  
-
-
-    if (*status > 0)
-        return(*status);
-	
-    nreq = sizeof(reqkeys)/sizeof(reqkeys[0][0])/2;
-    nsp = sizeof(spkeys)/sizeof(spkeys[0][0])/2;
-
-    /* construct translation patterns */
-
-    for (ii = 0; ii < nreq; ii++) {
-        patterns[ii][0] = reqkeys[ii][0];
-	
-        if (norec) 
-            patterns[ii][1] = negative;
-        else
-            patterns[ii][1] = reqkeys[ii][1];
-    }
-    
-    for (ii = 0; ii < nsp; ii++) {
-        patterns[ii+nreq][0] = spkeys[ii][0];
-        patterns[ii+nreq][1] = spkeys[ii][1];
-    }
-
-    npat = nreq + nsp;
-    
-    /* see if the EXTNAME keyword should be copied or not */
-    fits_read_card(infptr, "EXTNAME", card, &tstatus);
-
-    if (tstatus == 0) {
-      if (!strncmp(card, "EXTNAME = 'COMPRESSED_IMAGE'", 28)) 
-        patterns[npat-2][1] = negative;
-    }
-    
-    /* translate and copy the keywords from the input file to the output */
-    fits_translate_keywords(infptr, outfptr, 1, patterns, npat,
-			    0, 0, 0, status);
-
-    ffghsp(infptr, &nkeys, &nmore, status); /* get number of keywords in image */
-
-    nmore = nmore / 36;  /* how many completely empty header blocks are there? */
-     
-    /* preserve the same number of spare header blocks in the output header */
-     
-    for (jj = 0; jj < nmore; jj++)
-       for (ii = 0; ii < 36; ii++)
-          fits_write_record(outfptr, "    ", status);
-
-
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_copy_prime2img(fitsfile *infptr, fitsfile *outfptr, int *status)
-/*
-    This routine copies any unexpected keywords from the primary array
-    of the compressed input image into the header of the uncompressed image
-    (which is the primary array of the output file). 
-*/
-{
-    int  nsp;
-
-    /* keywords that will not be copied */
-    char *spkeys[][2] = {
-			   {"SIMPLE", "-"      },
-			   {"BITPIX",  "-"       },
-			   {"NAXIS",   "-"       },
-			   {"NAXISm",  "-"       },
-			   {"PCOUNT",  "-"       },
-			   {"EXTEND",  "-"       },
-			   {"GCOUNT",  "-"       },
-			   {"CHECKSUM","-"       }, 
-			   {"DATASUM", "-"       },
-			   {"EXTNAME", "-"       },
-			   {"HISTORY", "-"       },
-			   {"COMMENT", "-"       },
-			   {"*",       "+"      }};  
-
-    if (*status > 0)
-        return(*status);
-	
-    nsp = sizeof(spkeys)/sizeof(spkeys[0][0])/2;
-
-    /* translate and copy the keywords from the input file to the output */
-    fits_translate_keywords(infptr, outfptr, 1, spkeys, nsp,
-			    0, 0, 0, status);
-
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_decompress_tile (fitsfile *infptr,
-          int nrow,            /* I - row of table to read and uncompress */
-          int tilelen,         /* I - number of pixels in the tile        */
-          int datatype,        /* I - datatype to be returned in 'buffer' */
-          int nullcheck,       /* I - 0 for no null checking */
-          void *nulval,        /* I - value to be used for undefined pixels */
-          void *buffer,        /* O - buffer for returned decompressed values */
-          char *bnullarray,    /* O - buffer for returned null flags */
-          int *anynul,         /* O - any null values returned?  */
-          int *status)
-
-/* This routine decompresses one tile of the image */
-{
-    int *idata = 0;
-    int tiledatatype, pixlen = 0;          /* uncompressed integer data */
-    size_t idatalen, tilebytesize;
-    int ii, tnull;        /* value in the data which represents nulls */
-    unsigned char *cbuf; /* compressed data */
-    unsigned char charnull = 0;
-    short snull = 0;
-    int blocksize, ntilebins, tilecol = 0;
-    float fnulval=0;
-    float *tempfloat = 0;
-    double dnulval=0;
-    double bscale, bzero, actual_bzero, dummy = 0;    /* scaling parameters */
-    long tilesize;      /* number of bytes */
-    int smooth, nx, ny, scale;  /* hcompress parameters */
-    LONGLONG nelemll = 0, offset = 0;
-
-    if (*status > 0)
-       return(*status);
-
-
-    /* **************************************************************** */
-    /* allocate pointers to array of cached uncompressed tiles, if not already done */
-    if ((infptr->Fptr)->tilerow == 0)  {
-
-      /* calculate number of column bins of compressed tile */
-      ntilebins =  (((infptr->Fptr)->znaxis[0] - 1) / ((infptr->Fptr)->tilesize[0])) + 1;
-
-     if ((infptr->Fptr)->znaxis[0]   != (infptr->Fptr)->tilesize[0] ||
-        (infptr->Fptr)->tilesize[1] != 1 ) {   /* don't cache the tile if only single row of the image */
-
-        (infptr->Fptr)->tilerow = (int *) calloc (ntilebins, sizeof(int));
-        (infptr->Fptr)->tiledata = (void**) calloc (ntilebins, sizeof(void*));
-        (infptr->Fptr)->tilenullarray = (void **) calloc (ntilebins, sizeof(char*));
-        (infptr->Fptr)->tiledatasize = (long *) calloc (ntilebins, sizeof(long));
-        (infptr->Fptr)->tiletype = (int *) calloc (ntilebins, sizeof(int));
-        (infptr->Fptr)->tileanynull = (int *) calloc (ntilebins, sizeof(int));
-      }
-    }
- 
-    /* **************************************************************** */
-    /* check if this tile was cached; if so, just copy it out */
-    if ((infptr->Fptr)->tilerow)  {
-      /* calculate the column bin of the compressed tile */
-      tilecol = (nrow - 1) % ((long)(((infptr->Fptr)->znaxis[0] - 1) / ((infptr->Fptr)->tilesize[0])) + 1);
-
-      if (nrow == (infptr->Fptr)->tilerow[tilecol] && datatype == (infptr->Fptr)->tiletype[tilecol] ) {
-
-         memcpy(buffer, ((infptr->Fptr)->tiledata)[tilecol], (infptr->Fptr)->tiledatasize[tilecol]);
-	 
-	 if (nullcheck == 2)
-             memcpy(bnullarray, (infptr->Fptr)->tilenullarray[tilecol], tilelen);
-
-         *anynul = (infptr->Fptr)->tileanynull[tilecol];
-
-         return(*status);
-       }
-    }
-
-    /* **************************************************************** */
-    /* get length of the compressed byte stream */
-    ffgdesll (infptr, (infptr->Fptr)->cn_compressed, nrow, &nelemll, &offset, 
-            status);
-
-    /* EOF error here indicates that this tile has not yet been written */
-    if (*status == END_OF_FILE)
-           return(*status = NO_COMPRESSED_TILE);
-      
-    /* **************************************************************** */
-    if (nelemll == 0)  /* special case: tile was not compressed normally */
-    {
-        if ((infptr->Fptr)->cn_uncompressed >= 1 ) {
-
-	    /* This option of writing the uncompressed floating point data */
-	    /* to the tile compressed file was used until about May 2011. */
-	    /* This was replaced by the more efficient option of gzipping the */
-	    /* floating point data before writing it to the tile-compressed file */
-	    
-            /* no compressed data, so simply read the uncompressed data */
-            /* directly from the UNCOMPRESSED_DATA column */   
-            ffgdesll (infptr, (infptr->Fptr)->cn_uncompressed, nrow, &nelemll,
-               &offset, status);
-
-            if (nelemll == 0 && offset == 0)  /* this should never happen */
-	        return (*status = NO_COMPRESSED_TILE);
-
-            if (nullcheck <= 1) { /* set any null values in the array = nulval */
-                fits_read_col(infptr, datatype, (infptr->Fptr)->cn_uncompressed,
-                  nrow, 1, (long) nelemll, nulval, buffer, anynul, status);
-            } else  { /* set the bnullarray = 1 for any null values in the array */
-                fits_read_colnull(infptr, datatype, (infptr->Fptr)->cn_uncompressed,
-                  nrow, 1, (long) nelemll, buffer, bnullarray, anynul, status);
-            }
-        } else if ((infptr->Fptr)->cn_gzip_data >= 1) {
-
-            /* This is the newer option, that was introduced in May 2011 */
-            /* floating point data was not quantized,  so read the losslessly */
-	    /* compressed data from the GZIP_COMPRESSED_DATA column */   
-
-            ffgdesll (infptr, (infptr->Fptr)->cn_gzip_data, nrow, &nelemll,
-               &offset, status);
-
-            if (nelemll == 0 && offset == 0) /* this should never happen */
-	        return (*status = NO_COMPRESSED_TILE);
-
-	    /* allocate memory for the compressed tile of data */
-            cbuf = (unsigned char *) malloc ((long) nelemll);  
-            if (cbuf == NULL) {
-	        ffpmsg("error allocating memory for gzipped tile (imcomp_decompress_tile)");
-	        return (*status = MEMORY_ALLOCATION);
-            }
-
-            /* read array of compressed bytes */
-            if (fits_read_col(infptr, TBYTE, (infptr->Fptr)->cn_gzip_data, nrow,
-                 1, (long) nelemll, &charnull, cbuf, NULL, status) > 0) {
-                ffpmsg("error reading compressed byte stream from binary table");
-	        free (cbuf);
-                return (*status);
-            }
-
-            /* size of the returned (uncompressed) data buffer, in bytes */
-            if ((infptr->Fptr)->zbitpix == FLOAT_IMG) {
-	         idatalen = tilelen * sizeof(float);
-            } else if ((infptr->Fptr)->zbitpix == DOUBLE_IMG) {
-	         idatalen = tilelen * sizeof(double);
-            } else {
-                /* this should never happen! */
-                ffpmsg("incompatible data type in gzipped floating-point tile-compressed image");
-                free (cbuf);
-                return (*status = DATA_DECOMPRESSION_ERR);
-            }
-
-            if (datatype == TDOUBLE && (infptr->Fptr)->zbitpix == FLOAT_IMG) {  
-                /*  have to allocat a temporary buffer for the uncompressed data in the */
-                /*  case where a gzipped "float" tile is returned as a "double" array   */
-                tempfloat = (float*) malloc (idatalen); 
-
-                if (tempfloat == NULL) {
-	            ffpmsg("Memory allocation failure for tempfloat. (imcomp_decompress_tile)");
-                    free (cbuf);
-	            return (*status = MEMORY_ALLOCATION);
-                }
-
-                /* uncompress the data into temp buffer */
-                if (uncompress2mem_from_mem ((char *)cbuf, (long) nelemll,
-                     (char **) &tempfloat, &idatalen, NULL, &tilebytesize, status)) {
-                    ffpmsg("failed to gunzip the image tile");
-                    free (tempfloat);
-                    free (cbuf);
-                    return (*status);
-                }
-            } else {
-
-                /* uncompress the data directly into the output buffer in all other cases */
-                if (uncompress2mem_from_mem ((char *)cbuf, (long) nelemll,
-                  (char **) &buffer, &idatalen, NULL, &tilebytesize, status)) {
-                    ffpmsg("failed to gunzip the image tile");
-                    free (cbuf);
-                    return (*status);
-                }
-            }
-
-            free(cbuf);
-
-            /* do byte swapping and null value substitution for the tile of pixels */
-            if (tilebytesize == 4 * tilelen) {  /* float pixels */
-
-#if BYTESWAPPED
-                if (tempfloat)
-                    ffswap4((int *) tempfloat, tilelen);
-                else
-                    ffswap4((int *) buffer, tilelen);
-#endif
-               if (datatype == TFLOAT) {
-                  if (nulval) {
-		    fnulval = *(float *) nulval;
-  		  }
-
-                  fffr4r4((float *) buffer, (long) tilelen, 1., 0., nullcheck,   
-                        fnulval, bnullarray, anynul,
-                        (float *) buffer, status);
-                } else if (datatype == TDOUBLE) {
-                  if (nulval) {
-		    dnulval = *(double *) nulval;
-		  }
-
-                  /* note that the R*4 data are in the tempfloat array in this case */
-                  fffr4r8((float *) tempfloat, (long) tilelen, 1., 0., nullcheck,   
-                   dnulval, bnullarray, anynul,
-                    (double *) buffer, status);            
-                  free(tempfloat);
-
-                } else {
-                  ffpmsg("implicit data type conversion is not supported for gzipped image tiles");
-                  return (*status = DATA_DECOMPRESSION_ERR);
-                }
-            } else if (tilebytesize == 8 * tilelen) { /* double pixels */
-
-#if BYTESWAPPED
-                ffswap8((double *) buffer, tilelen);
-#endif
-                if (datatype == TFLOAT) {
-                  if (nulval) {
-		    fnulval = *(float *) nulval;
-  		  }
-
-                  fffr8r4((double *) buffer, (long) tilelen, 1., 0., nullcheck,   
-                        fnulval, bnullarray, anynul,
-                        (float *) buffer, status);
-                } else if (datatype == TDOUBLE) {
-                  if (nulval) {
-		    dnulval = *(double *) nulval;
-		  }
-
-                  fffr8r8((double *) buffer, (long) tilelen, 1., 0., nullcheck,   
-                   dnulval, bnullarray, anynul,
-                    (double *) buffer, status);            
-                } else {
-                  ffpmsg("implicit data type conversion is not supported in tile-compressed images");
-                  return (*status = DATA_DECOMPRESSION_ERR);
-                }
-	    } else {
-                ffpmsg("error: uncompressed tile has wrong size");
-                return (*status = DATA_DECOMPRESSION_ERR);
-            }
-
-          /* end of special case of losslessly gzipping a floating-point image tile */
-        } else {  /* this should never happen */
-	   *status = NO_COMPRESSED_TILE;
-        }
-
-        return(*status);
-    }
-
-    /* **************************************************************** */
-    /* deal with the normal case of a compressed tile of pixels */
-    if (nullcheck == 2)  {
-        for (ii = 0; ii < tilelen; ii++)  /* initialize the null flage array */
-            bnullarray[ii] = 0;
-    }
-
-    if (anynul)
-       *anynul = 0;
-
-    /* get linear scaling and offset values, if they exist */
-    actual_bzero = (infptr->Fptr)->cn_actual_bzero;
-    if ((infptr->Fptr)->cn_zscale == 0) {
-         /* set default scaling, if scaling is not defined */
-         bscale = 1.;
-         bzero = 0.;
-    } else if ((infptr->Fptr)->cn_zscale == -1) {
-        bscale = (infptr->Fptr)->zscale;
-        bzero  = (infptr->Fptr)->zzero;
-    } else {
-        /* read the linear scale and offset values for this row */
-	ffgcvd (infptr, (infptr->Fptr)->cn_zscale, nrow, 1, 1, 0.,
-				&bscale, NULL, status);
-	ffgcvd (infptr, (infptr->Fptr)->cn_zzero, nrow, 1, 1, 0.,
-				&bzero, NULL, status);
-        if (*status > 0)
-        {
-          ffpmsg("error reading scaling factor and offset for compressed tile");
-          return (*status);
-        }
-
-        /* test if floating-point FITS image also has non-default BSCALE and  */
-	/* BZERO keywords.  If so, we have to combine the 2 linear scaling factors. */
-	
-	if ( ((infptr->Fptr)->zbitpix == FLOAT_IMG || 
-	      (infptr->Fptr)->zbitpix == DOUBLE_IMG )
-	    &&  
-	      ((infptr->Fptr)->cn_bscale != 1.0 ||
-	       (infptr->Fptr)->cn_bzero  != 0.0 )    ) 
-	    {
-	       bscale = bscale * (infptr->Fptr)->cn_bscale;
-	       bzero  = bzero  * (infptr->Fptr)->cn_bscale + (infptr->Fptr)->cn_bzero;
-	    }
-    }
-
-    if (bscale == 1.0 && bzero == 0.0 ) {
-      /* if no other scaling has been specified, try using the values
-         given by the BSCALE and BZERO keywords, if any */
-
-        bscale = (infptr->Fptr)->cn_bscale;
-        bzero  = (infptr->Fptr)->cn_bzero;
-    }
-
-    /* ************************************************************* */
-    /* get the value used to represent nulls in the int array */
-    if ((infptr->Fptr)->cn_zblank == 0) {
-        nullcheck = 0;  /* no null value; don't check for nulls */
-    } else if ((infptr->Fptr)->cn_zblank == -1) {
-        tnull = (infptr->Fptr)->zblank;  /* use the the ZBLANK keyword */
-    } else {
-        /* read the null value for this row */
-	ffgcvk (infptr, (infptr->Fptr)->cn_zblank, nrow, 1, 1, 0,
-				&tnull, NULL, status);
-        if (*status > 0) {
-            ffpmsg("error reading null value for compressed tile");
-            return (*status);
-        }
-    }
-
-    /* ************************************************************* */
-    /* allocate memory for the uncompressed array of tile integers */
-    /* The size depends on the datatype and the compression type. */
-    
-    if ((infptr->Fptr)->compress_type == HCOMPRESS_1 &&
-          ((infptr->Fptr)->zbitpix != BYTE_IMG &&
-	   (infptr->Fptr)->zbitpix != SHORT_IMG) ) {
-
-           idatalen = tilelen * sizeof(LONGLONG);  /* 8 bytes per pixel */
-
-    } else if ( (infptr->Fptr)->compress_type == RICE_1 &&
-               (infptr->Fptr)->zbitpix == BYTE_IMG && 
-	       (infptr->Fptr)->rice_bytepix == 1) {
-
-           idatalen = tilelen * sizeof(char); /* 1 byte per pixel */
-    } else if ( ( (infptr->Fptr)->compress_type == GZIP_1  ||
-                  (infptr->Fptr)->compress_type == GZIP_2  ||
-                  (infptr->Fptr)->compress_type == BZIP2_1 ) &&
-               (infptr->Fptr)->zbitpix == BYTE_IMG ) {
-
-           idatalen = tilelen * sizeof(char); /* 1 byte per pixel */
-    } else if ( (infptr->Fptr)->compress_type == RICE_1 &&
-               (infptr->Fptr)->zbitpix == SHORT_IMG && 
-	       (infptr->Fptr)->rice_bytepix == 2) {
-
-           idatalen = tilelen * sizeof(short); /* 2 bytes per pixel */
-    } else if ( ( (infptr->Fptr)->compress_type == GZIP_1  ||
-                  (infptr->Fptr)->compress_type == GZIP_2  ||
-                  (infptr->Fptr)->compress_type == BZIP2_1 )  &&
-               (infptr->Fptr)->zbitpix == SHORT_IMG ) {
-
-           idatalen = tilelen * sizeof(short); /* 2 bytes per pixel */
-    } else if ( ( (infptr->Fptr)->compress_type == GZIP_1  ||
-                  (infptr->Fptr)->compress_type == GZIP_2  ||
-                  (infptr->Fptr)->compress_type == BZIP2_1 ) &&
-               (infptr->Fptr)->zbitpix == DOUBLE_IMG ) {
-
-           idatalen = tilelen * sizeof(double); /* 8 bytes per pixel  */
-    } else {
-           idatalen = tilelen * sizeof(int);  /* all other cases have int pixels */
-    }
-
-    idata = (int*) malloc (idatalen); 
-    if (idata == NULL) {
-	    ffpmsg("Memory allocation failure for idata. (imcomp_decompress_tile)");
-	    return (*status = MEMORY_ALLOCATION);
-    }
-
-    /* ************************************************************* */
-    /* allocate memory for the compressed bytes */
-
-    if ((infptr->Fptr)->compress_type == PLIO_1) {
-        cbuf = (unsigned char *) malloc ((long) nelemll * sizeof (short));
-    } else {
-        cbuf = (unsigned char *) malloc ((long) nelemll);
-    }
-    if (cbuf == NULL) {
-	ffpmsg("Out of memory for cbuf. (imcomp_decompress_tile)");
-        free(idata);
-	return (*status = MEMORY_ALLOCATION);
-    }
-    
-    /* ************************************************************* */
-    /* read the compressed bytes from the FITS file */
-
-    if ((infptr->Fptr)->compress_type == PLIO_1) {
-        fits_read_col(infptr, TSHORT, (infptr->Fptr)->cn_compressed, nrow,
-             1, (long) nelemll, &snull, (short *) cbuf, NULL, status);
-    } else {
-       fits_read_col(infptr, TBYTE, (infptr->Fptr)->cn_compressed, nrow,
-             1, (long) nelemll, &charnull, cbuf, NULL, status);
-    }
-
-    if (*status > 0) {
-        ffpmsg("error reading compressed byte stream from binary table");
-	free (cbuf);
-        free(idata);
-        return (*status);
-    }
-
-    /* ************************************************************* */
-    /*  call the algorithm-specific code to uncompress the tile */
-
-    if ((infptr->Fptr)->compress_type == RICE_1) {
-
-        blocksize = (infptr->Fptr)->rice_blocksize;
-
-        if ((infptr->Fptr)->rice_bytepix == 1 ) {
-            *status = fits_rdecomp_byte (cbuf, (long) nelemll, (unsigned char *)idata,
-                        tilelen, blocksize);
-            tiledatatype = TBYTE;
-        } else if ((infptr->Fptr)->rice_bytepix == 2 ) {
-            *status = fits_rdecomp_short (cbuf, (long) nelemll, (unsigned short *)idata,
-                        tilelen, blocksize);
-            tiledatatype = TSHORT;
-        } else {
-            *status = fits_rdecomp (cbuf, (long) nelemll, (unsigned int *)idata,
-                         tilelen, blocksize);
-            tiledatatype = TINT;
-        }
-
-    /* ************************************************************* */
-    } else if ((infptr->Fptr)->compress_type == HCOMPRESS_1)  {
-
-        smooth = (infptr->Fptr)->hcomp_smooth;
-
-        if ( ((infptr->Fptr)->zbitpix == BYTE_IMG || (infptr->Fptr)->zbitpix == SHORT_IMG)) {
-            *status = fits_hdecompress(cbuf, smooth, idata, &nx, &ny,
-	        &scale, status);
-        } else {  /* zbitpix = LONG_IMG (32) */
-            /* idata must have been allocated twice as large for this to work */
-            *status = fits_hdecompress64(cbuf, smooth, (LONGLONG *) idata, &nx, &ny,
-	        &scale, status);
-        }       
-
-        tiledatatype = TINT;
-
-    /* ************************************************************* */
-    } else if ((infptr->Fptr)->compress_type == PLIO_1) {
-
-        pl_l2pi ((short *) cbuf, 1, idata, tilelen);  /* uncompress the data */
-        tiledatatype = TINT;
-
-    /* ************************************************************* */
-    } else if ( ((infptr->Fptr)->compress_type == GZIP_1) ||
-                ((infptr->Fptr)->compress_type == GZIP_2) ) {
-
-        uncompress2mem_from_mem ((char *)cbuf, (long) nelemll,
-             (char **) &idata, &idatalen, realloc, &tilebytesize, status);
-
-        /* determine the data type of the uncompressed array, and */
-	/*  do byte unshuffling and unswapping if needed */
-	if (tilebytesize == (size_t) (tilelen * 2)) {
-	    /* this is a short I*2 array */
-            tiledatatype = TSHORT;
-
-            if ( (infptr->Fptr)->compress_type == GZIP_2 )
-		    fits_unshuffle_2bytes((char *) idata, tilelen, status);
-
-#if BYTESWAPPED
-            ffswap2((short *) idata, tilelen);
-#endif
-
-	} else if (tilebytesize == (size_t) (tilelen * 4)) {
-	    /* this is a int I*4 array (or maybe R*4) */
-            tiledatatype = TINT;
-
-            if ( (infptr->Fptr)->compress_type == GZIP_2 )
-		    fits_unshuffle_4bytes((char *) idata, tilelen, status);
-
-#if BYTESWAPPED
-            ffswap4(idata, tilelen);
-#endif
-
-	} else if (tilebytesize == (size_t) (tilelen * 8)) {
-	    /* this is a R*8 double array */
-            tiledatatype = TDOUBLE;
-
-            if ( (infptr->Fptr)->compress_type == GZIP_2 )
-		    fits_unshuffle_8bytes((char *) idata, tilelen, status);
-#if BYTESWAPPED
-            ffswap8((double *) idata, tilelen);
-#endif
-
-        } else if (tilebytesize == (size_t) tilelen) {
-	    
-	    /* this is an unsigned char I*1 array */
-            tiledatatype = TBYTE;
-
-        } else {
-            ffpmsg("error: uncompressed tile has wrong size");
-            free(idata);
-            return (*status = DATA_DECOMPRESSION_ERR);
-        }
-
-    /* ************************************************************* */
-    } else if ((infptr->Fptr)->compress_type == BZIP2_1) {
-
-/*  BZIP2 is not supported in the public release; this is only for test purposes 
-
-        if (BZ2_bzBuffToBuffDecompress ((char *) idata, &idatalen, 
-		(char *)cbuf, (unsigned int) nelemll, 0, 0) )
-*/
-        {
-            ffpmsg("bzip2 decompression error");
-            free(idata);
-            free (cbuf);
-            return (*status = DATA_DECOMPRESSION_ERR);
-        }
-
-        if ((infptr->Fptr)->zbitpix == BYTE_IMG) {
-	     tiledatatype = TBYTE;
-        } else if ((infptr->Fptr)->zbitpix == SHORT_IMG) {
-  	     tiledatatype = TSHORT;
-#if BYTESWAPPED
-            ffswap2((short *) idata, tilelen);
-#endif
-	} else {
-  	     tiledatatype = TINT;
-#if BYTESWAPPED
-            ffswap4(idata, tilelen);
-#endif
-	}
-
-    /* ************************************************************* */
-    } else {
-        ffpmsg("unknown compression algorithm");
-        free(idata);
-        return (*status = DATA_DECOMPRESSION_ERR);
-    }
-
-    free(cbuf);
-    if (*status)  {  /* error uncompressing the tile */
-            free(idata);
-            return (*status);
-    }
-
-    /* ************************************************************* */
-    /* copy the uncompressed tile data to the output buffer, doing */
-    /* null checking, datatype conversion and linear scaling, if necessary */
-
-    if (nulval == 0)
-         nulval = &dummy;  /* set address to dummy value */
-
-    if (datatype == TSHORT)
-    {
-        pixlen = sizeof(short);
-
-	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
-	 /* the floating point pixels were losselessly compressed with GZIP */
-	 /* Just have to copy the values to the output array */
-	 
-          if (tiledatatype == TINT) {
-              fffr4i2((float *) idata, tilelen, bscale, bzero, nullcheck,   
-                *(short *) nulval, bnullarray, anynul,
-                (short *) buffer, status);
-          } else {
-              fffr8i2((double *) idata, tilelen, bscale, bzero, nullcheck,   
-                *(short *) nulval, bnullarray, anynul,
-                (short *) buffer, status);
-          }
-        } else if (tiledatatype == TINT) {
-          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
-	    /* special case where unsigned 16-bit integers have been */
-	    /* offset by +32768 when using PLIO */
-            fffi4i2(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
-             *(short *) nulval, bnullarray, anynul,
-            (short *) buffer, status);
-          } else {
-            fffi4i2(idata, tilelen, bscale, bzero, nullcheck, tnull,
-             *(short *) nulval, bnullarray, anynul,
-            (short *) buffer, status);
-
-            /*
-	       Hcompress is a special case:  ignore any numerical overflow
-	       errors that may have occurred during the integer*4 to integer*2
-	       convertion.  Overflows can happen when a lossy Hcompress algorithm
-	       is invoked (with a non-zero scale factor).  The fffi4i2 routine
-	       clips the returned values to be within the legal I*2 range, so
-	       all we need to is to reset the error status to zero.
-	    */
-	       
-            if ((infptr->Fptr)->compress_type == HCOMPRESS_1) {
-	        if (*status == NUM_OVERFLOW) *status = 0;
-	    }
-          }
-        } else if (tiledatatype == TSHORT) {
-          fffi2i2((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
-           *(short *) nulval, bnullarray, anynul,
-          (short *) buffer, status);
-        } else if (tiledatatype == TBYTE) {
-          fffi1i2((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
-           *(short *) nulval, bnullarray, anynul,
-          (short *) buffer, status);
-        }
-    }
-    else if (datatype == TINT)
-    {
-        pixlen = sizeof(int);
-
-	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
-	 /* the floating point pixels were losselessly compressed with GZIP */
-	 /* Just have to copy the values to the output array */
-	 
-          if (tiledatatype == TINT) {
-              fffr4int((float *) idata, tilelen, bscale, bzero, nullcheck,   
-                *(int *) nulval, bnullarray, anynul,
-                (int *) buffer, status);
-          } else {
-              fffr8int((double *) idata, tilelen, bscale, bzero, nullcheck,   
-                *(int *) nulval, bnullarray, anynul,
-                (int *) buffer, status);
-          }
-        } else if (tiledatatype == TINT)
-          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
-	    /* special case where unsigned 16-bit integers have been */
-	    /* offset by +32768 when using PLIO */
-            fffi4int(idata, (long) tilelen, bscale, bzero - 32768., nullcheck, tnull,
-             *(int *) nulval, bnullarray, anynul,
-            (int *) buffer, status);
-          } else {
-            fffi4int(idata, (long) tilelen, bscale, bzero, nullcheck, tnull,
-             *(int *) nulval, bnullarray, anynul,
-            (int *) buffer, status);
-          } 
-        else if (tiledatatype == TSHORT)
-          fffi2int((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
-           *(int *) nulval, bnullarray, anynul,
-           (int *) buffer, status);
-        else if (tiledatatype == TBYTE)
-          fffi1int((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
-           *(int *) nulval, bnullarray, anynul,
-           (int *) buffer, status);
-    }
-    else if (datatype == TLONG)
-    {
-        pixlen = sizeof(long);
-
-	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
-	 /* the floating point pixels were losselessly compressed with GZIP */
-	 /* Just have to copy the values to the output array */
-	 
-          if (tiledatatype == TINT) {
-              fffr4i4((float *) idata, tilelen, bscale, bzero, nullcheck,   
-                *(long *) nulval, bnullarray, anynul,
-                (long *) buffer, status);
-          } else {
-              fffr8i4((double *) idata, tilelen, bscale, bzero, nullcheck,   
-                *(long *) nulval, bnullarray, anynul,
-                (long *) buffer, status);
-          }
-        } else if (tiledatatype == TINT)
-          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
-	    /* special case where unsigned 16-bit integers have been */
-	    /* offset by +32768 when using PLIO */
-            fffi4i4(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
-             *(long *) nulval, bnullarray, anynul,
-             (long *) buffer, status);
-          } else {
-            fffi4i4(idata, tilelen, bscale, bzero, nullcheck, tnull,
-             *(long *) nulval, bnullarray, anynul,
-              (long *) buffer, status);
-          }
-        else if (tiledatatype == TSHORT)
-          fffi2i4((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
-           *(long *) nulval, bnullarray, anynul,
-            (long *) buffer, status);
-        else if (tiledatatype == TBYTE)
-          fffi1i4((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
-           *(long *) nulval, bnullarray, anynul,
-            (long *) buffer, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-        pixlen = sizeof(float);
-        if (nulval) {
-	      fnulval = *(float *) nulval;
-	}
- 
-	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
-	 /* the floating point pixels were losselessly compressed with GZIP */
-	 /* Just have to copy the values to the output array */
-	 
-          if (tiledatatype == TINT) {
-              fffr4r4((float *) idata, tilelen, bscale, bzero, nullcheck,   
-                fnulval, bnullarray, anynul,
-                (float *) buffer, status);
-          } else {
-              fffr8r4((double *) idata, tilelen, bscale, bzero, nullcheck,   
-                fnulval, bnullarray, anynul,
-                (float *) buffer, status);
-          }
-	
-        } else if ((infptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_1 ||
-	           (infptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_2) {
-
-         /* use the new dithering algorithm (introduced in July 2009) */
-
-         if (tiledatatype == TINT)
-          unquantize_i4r4(nrow + (infptr->Fptr)->dither_seed - 1, idata, 
-	   tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, tnull,
-           fnulval, bnullarray, anynul,
-            (float *) buffer, status);
-         else if (tiledatatype == TSHORT)
-          unquantize_i2r4(nrow + (infptr->Fptr)->dither_seed - 1, (short *)idata, 
-	   tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, (short) tnull,
-           fnulval, bnullarray, anynul,
-            (float *) buffer, status);
-         else if (tiledatatype == TBYTE)
-          unquantize_i1r4(nrow + (infptr->Fptr)->dither_seed - 1, (unsigned char *)idata, 
-	   tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, (unsigned char) tnull,
-           fnulval, bnullarray, anynul,
-            (float *) buffer, status);
-
-        } else {  /* use the old "round to nearest level" quantization algorithm */
-
-         if (tiledatatype == TINT)
-          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
-	    /* special case where unsigned 16-bit integers have been */
-	    /* offset by +32768 when using PLIO */
-            fffi4r4(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
-             fnulval, bnullarray, anynul,
-             (float *) buffer, status);
-          } else {
-            fffi4r4(idata, tilelen, bscale, bzero, nullcheck, tnull,  
-             fnulval, bnullarray, anynul,
-              (float *) buffer, status);
-          }
-         else if (tiledatatype == TSHORT)
-          fffi2r4((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,  
-           fnulval, bnullarray, anynul,
-            (float *) buffer, status);
-         else if (tiledatatype == TBYTE)
-          fffi1r4((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
-           fnulval, bnullarray, anynul,
-            (float *) buffer, status);
-	}
-    }
-    else if (datatype == TDOUBLE)
-    {
-        pixlen = sizeof(double);
-        if (nulval) {
-	     dnulval = *(double *) nulval;
-	}
-
-	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
-	 /* the floating point pixels were losselessly compressed with GZIP */
-	 /* Just have to copy the values to the output array */
-
-          if (tiledatatype == TINT) {
-              fffr4r8((float *) idata, tilelen, bscale, bzero, nullcheck,   
-                dnulval, bnullarray, anynul,
-                (double *) buffer, status);
-          } else {
-              fffr8r8((double *) idata, tilelen, bscale, bzero, nullcheck,   
-                dnulval, bnullarray, anynul,
-                (double *) buffer, status);
-          }
-	
-	} else if ((infptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_1 ||
-	           (infptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_2) {
-
-         /* use the new dithering algorithm (introduced in July 2009) */
-         if (tiledatatype == TINT)
-          unquantize_i4r8(nrow + (infptr->Fptr)->dither_seed - 1, idata,
-	   tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, tnull,
-           dnulval, bnullarray, anynul,
-            (double *) buffer, status);
-         else if (tiledatatype == TSHORT)
-          unquantize_i2r8(nrow + (infptr->Fptr)->dither_seed - 1, (short *)idata,
-	   tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, (short) tnull,
-           dnulval, bnullarray, anynul,
-            (double *) buffer, status);
-         else if (tiledatatype == TBYTE)
-          unquantize_i1r8(nrow + (infptr->Fptr)->dither_seed - 1, (unsigned char *)idata,
-	   tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, (unsigned char) tnull,
-           dnulval, bnullarray, anynul,
-            (double *) buffer, status);
-
-        } else {  /* use the old "round to nearest level" quantization algorithm */
-
-         if (tiledatatype == TINT) {
-          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
-	    /* special case where unsigned 16-bit integers have been */
-	    /* offset by +32768 when using PLIO */
-            fffi4r8(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
-             dnulval, bnullarray, anynul,
-             (double *) buffer, status);
-          } else {
-            fffi4r8(idata, tilelen, bscale, bzero, nullcheck, tnull,
-             dnulval, bnullarray, anynul,
-              (double *) buffer, status);
-          }
-         } else if (tiledatatype == TSHORT) {
-          fffi2r8((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
-           dnulval, bnullarray, anynul,
-            (double *) buffer, status);
-         } else if (tiledatatype == TBYTE)
-          fffi1r8((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
-           dnulval, bnullarray, anynul,
-            (double *) buffer, status);
-	}
-    }
-    else if (datatype == TBYTE)
-    {
-        pixlen = sizeof(char);
-        if (tiledatatype == TINT)
-          fffi4i1(idata, tilelen, bscale, bzero, nullcheck, tnull,
-           *(unsigned char *) nulval, bnullarray, anynul,
-            (unsigned char *) buffer, status);
-        else if (tiledatatype == TSHORT)
-          fffi2i1((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
-           *(unsigned char *) nulval, bnullarray, anynul,
-            (unsigned char *) buffer, status);
-        else if (tiledatatype == TBYTE)
-          fffi1i1((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
-           *(unsigned char *) nulval, bnullarray, anynul,
-            (unsigned char *) buffer, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-        pixlen = sizeof(char);
-        if (tiledatatype == TINT)
-          fffi4s1(idata, tilelen, bscale, bzero, nullcheck, tnull,
-           *(signed char *) nulval, bnullarray, anynul,
-            (signed char *) buffer, status);
-        else if (tiledatatype == TSHORT)
-          fffi2s1((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
-           *(signed char *) nulval, bnullarray, anynul,
-            (signed char *) buffer, status);
-        else if (tiledatatype == TBYTE)
-          fffi1s1((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
-           *(signed char *) nulval, bnullarray, anynul,
-            (signed char *) buffer, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-        pixlen = sizeof(short);
-
-	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
-	 /* the floating point pixels were losselessly compressed with GZIP */
-	 /* Just have to copy the values to the output array */
-	 
-          if (tiledatatype == TINT) {
-              fffr4u2((float *) idata, tilelen, bscale, bzero, nullcheck,   
-                *(unsigned short *) nulval, bnullarray, anynul,
-                (unsigned short *) buffer, status);
-          } else {
-              fffr8u2((double *) idata, tilelen, bscale, bzero, nullcheck,   
-                *(unsigned short *) nulval, bnullarray, anynul,
-                (unsigned short *) buffer, status);
-          }
-        } else if (tiledatatype == TINT)
-          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
-	    /* special case where unsigned 16-bit integers have been */
-	    /* offset by +32768 when using PLIO */
-            fffi4u2(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
-             *(unsigned short *) nulval, bnullarray, anynul,
-            (unsigned short *) buffer, status);
-          } else {
-            fffi4u2(idata, tilelen, bscale, bzero, nullcheck, tnull,
-             *(unsigned short *) nulval, bnullarray, anynul,
-              (unsigned short *) buffer, status);
-          }
-        else if (tiledatatype == TSHORT)
-          fffi2u2((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
-           *(unsigned short *) nulval, bnullarray, anynul,
-            (unsigned short *) buffer, status);
-        else if (tiledatatype == TBYTE)
-          fffi1u2((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
-           *(unsigned short *) nulval, bnullarray, anynul,
-            (unsigned short *) buffer, status);
-    }
-    else if (datatype == TUINT)
-    {
-        pixlen = sizeof(int);
-
-	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
-	 /* the floating point pixels were losselessly compressed with GZIP */
-	 /* Just have to copy the values to the output array */
-	 
-          if (tiledatatype == TINT) {
-              fffr4uint((float *) idata, tilelen, bscale, bzero, nullcheck,   
-                *(unsigned int *) nulval, bnullarray, anynul,
-                (unsigned int *) buffer, status);
-          } else {
-              fffr8uint((double *) idata, tilelen, bscale, bzero, nullcheck,   
-                *(unsigned int *) nulval, bnullarray, anynul,
-                (unsigned int *) buffer, status);
-          }
-        } else
-         if (tiledatatype == TINT)
-          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
-	    /* special case where unsigned 16-bit integers have been */
-	    /* offset by +32768 when using PLIO */
-            fffi4uint(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
-             *(unsigned int *) nulval, bnullarray, anynul,
-              (unsigned int *) buffer, status);
-          } else {
-            fffi4uint(idata, tilelen, bscale, bzero, nullcheck, tnull,
-             *(unsigned int *) nulval, bnullarray, anynul,
-              (unsigned int *) buffer, status);
-          }
-        else if (tiledatatype == TSHORT)
-          fffi2uint((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
-           *(unsigned int *) nulval, bnullarray, anynul,
-            (unsigned int *) buffer, status);
-        else if (tiledatatype == TBYTE)
-          fffi1uint((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
-           *(unsigned int *) nulval, bnullarray, anynul,
-            (unsigned int *) buffer, status);
-    }
-    else if (datatype == TULONG)
-    {
-        pixlen = sizeof(long);
-
-	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
-	 /* the floating point pixels were losselessly compressed with GZIP */
-	 /* Just have to copy the values to the output array */
-	 
-          if (tiledatatype == TINT) {
-              fffr4u4((float *) idata, tilelen, bscale, bzero, nullcheck,   
-                *(unsigned long *) nulval, bnullarray, anynul,
-                (unsigned long *) buffer, status);
-          } else {
-              fffr8u4((double *) idata, tilelen, bscale, bzero, nullcheck,   
-                *(unsigned long *) nulval, bnullarray, anynul,
-                (unsigned long *) buffer, status);
-          }
-        } else if (tiledatatype == TINT)
-          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
-	    /* special case where unsigned 16-bit integers have been */
-	    /* offset by +32768 when using PLIO */
-            fffi4u4(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
-             *(unsigned long *) nulval, bnullarray, anynul,
-              (unsigned long *) buffer, status);
-          } else {
-            fffi4u4(idata, tilelen, bscale, bzero, nullcheck, tnull,
-             *(unsigned long *) nulval, bnullarray, anynul, 
-              (unsigned long *) buffer, status);
-          }
-        else if (tiledatatype == TSHORT)
-          fffi2u4((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
-           *(unsigned long *) nulval, bnullarray, anynul, 
-            (unsigned long *) buffer, status);
-        else if (tiledatatype == TBYTE)
-          fffi1u4((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
-           *(unsigned long *) nulval, bnullarray, anynul, 
-            (unsigned long *) buffer, status);
-    }
-    else
-         *status = BAD_DATATYPE;
-
-    free(idata);  /* don't need the uncompressed tile any more */
-
-    /* **************************************************************** */
-    /* cache the tile, in case the application wants it again  */
-
-    /*   Don't cache the tile if tile is a single row of the image; 
-         it is less likely that the cache will be used in this cases,
-	 so it is not worth the time and the memory overheads.
-    */
-    
-    if ((infptr->Fptr)->tilerow)  {  /* make sure cache has been allocated */
-     if ((infptr->Fptr)->znaxis[0]   != (infptr->Fptr)->tilesize[0] ||
-        (infptr->Fptr)->tilesize[1] != 1 )
-     {
-      tilesize = pixlen * tilelen;
-
-      /* check that tile size/type has not changed */
-      if (tilesize != (infptr->Fptr)->tiledatasize[tilecol] ||
-        datatype != (infptr->Fptr)->tiletype[tilecol] )  {
-
-        if (((infptr->Fptr)->tiledata)[tilecol]) {
-            free(((infptr->Fptr)->tiledata)[tilecol]);	    
-        }
-	
-        if (((infptr->Fptr)->tilenullarray)[tilecol]) {
-            free(((infptr->Fptr)->tilenullarray)[tilecol]);
-        }
-	
-        ((infptr->Fptr)->tilenullarray)[tilecol] = 0;
-        ((infptr->Fptr)->tilerow)[tilecol] = 0;
-        ((infptr->Fptr)->tiledatasize)[tilecol] = 0;
-        ((infptr->Fptr)->tiletype)[tilecol] = 0;
-
-        /* allocate new array(s) */
-	((infptr->Fptr)->tiledata)[tilecol] = malloc(tilesize);
-
-	if (((infptr->Fptr)->tiledata)[tilecol] == 0)
-	   return (*status);
-
-        if (nullcheck == 2) {  /* also need array of null pixel flags */
-	    (infptr->Fptr)->tilenullarray[tilecol] = malloc(tilelen);
-	    if ((infptr->Fptr)->tilenullarray[tilecol] == 0)
-	        return (*status);
-        }
-
-        (infptr->Fptr)->tiledatasize[tilecol] = tilesize;
-        (infptr->Fptr)->tiletype[tilecol] = datatype;
-      }
-
-      /* copy the tile array(s) into cache buffer */
-      memcpy((infptr->Fptr)->tiledata[tilecol], buffer, tilesize);
-
-      if (nullcheck == 2) {
-	    if ((infptr->Fptr)->tilenullarray == 0)  {
-       	      (infptr->Fptr)->tilenullarray[tilecol] = malloc(tilelen);
-            }
-            memcpy((infptr->Fptr)->tilenullarray[tilecol], bnullarray, tilelen);
-      }
-
-      (infptr->Fptr)->tilerow[tilecol] = nrow;
-      (infptr->Fptr)->tileanynull[tilecol] = *anynul;
-     }
-    }
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_test_overlap (
-    int ndim,           /* I - number of dimension in the tile and image */
-    long *tfpixel,      /* I - first pixel number in each dim. of the tile */
-    long *tlpixel,      /* I - last pixel number in each dim. of the tile */
-    long *fpixel,       /* I - first pixel number in each dim. of the image */
-    long *lpixel,       /* I - last pixel number in each dim. of the image */
-    long *ininc,        /* I - increment to be applied in each image dimen. */
-    int *status)
-
-/* 
-  test if there are any intersecting pixels between this tile and the section
-  of the image defined by fixel, lpixel, ininc. 
-*/
-{
-    long imgdim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */
-                                   /* output image, allowing for inc factor */
-    long tiledim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */
-                                 /* tile, array;  inc factor is not relevant */
-    long imgfpix[MAX_COMPRESS_DIM]; /* 1st img pix overlapping tile: 0 base, */
-                                    /*  allowing for inc factor */
-    long imglpix[MAX_COMPRESS_DIM]; /* last img pix overlapping tile 0 base, */
-                                    /*  allowing for inc factor */
-    long tilefpix[MAX_COMPRESS_DIM]; /* 1st tile pix overlapping img 0 base, */
-                                    /*  allowing for inc factor */
-    long inc[MAX_COMPRESS_DIM]; /* local copy of input ininc */
-    int ii;
-    long tf, tl;
-
-    if (*status > 0)
-        return(*status);
-
-
-    /* ------------------------------------------------------------ */
-    /* calc amount of overlap in each dimension; if there is zero   */
-    /* overlap in any dimension then just return  */
-    /* ------------------------------------------------------------ */
-    
-    for (ii = 0; ii < ndim; ii++)
-    {
-        if (tlpixel[ii] < fpixel[ii] || tfpixel[ii] > lpixel[ii])
-            return(0);  /* there are no overlapping pixels */
-
-        inc[ii] = ininc[ii];
-
-        /* calc dimensions of the output image section */
-        imgdim[ii] = (lpixel[ii] - fpixel[ii]) / labs(inc[ii]) + 1;
-        if (imgdim[ii] < 1) {
-            *status = NEG_AXIS;
-            return(0);
-        }
-
-        /* calc dimensions of the tile */
-        tiledim[ii] = tlpixel[ii] - tfpixel[ii] + 1;
-        if (tiledim[ii] < 1) {
-            *status = NEG_AXIS;
-            return(0);
-        }
-
-        if (ii > 0)
-           tiledim[ii] *= tiledim[ii - 1];  /* product of dimensions */
-
-        /* first and last pixels in image that overlap with the tile, 0 base */
-        tf = tfpixel[ii] - 1;
-        tl = tlpixel[ii] - 1;
-
-        /* skip this plane if it falls in the cracks of the subsampled image */
-        while ((tf-(fpixel[ii] - 1)) % labs(inc[ii]))
-        {
-           tf++;
-           if (tf > tl)
-             return(0);  /* no overlapping pixels */
-        }
-
-        while ((tl-(fpixel[ii] - 1)) % labs(inc[ii]))
-        {
-           tl--;
-           if (tf > tl)
-             return(0);  /* no overlapping pixels */
-        }
-        imgfpix[ii] = maxvalue((tf - fpixel[ii] +1) / labs(inc[ii]) , 0);
-        imglpix[ii] = minvalue((tl - fpixel[ii] +1) / labs(inc[ii]) ,
-                               imgdim[ii] - 1);
-
-        /* first pixel in the tile that overlaps with the image (0 base) */
-        tilefpix[ii] = maxvalue(fpixel[ii] - tfpixel[ii], 0);
-
-        while ((tfpixel[ii] + tilefpix[ii] - fpixel[ii]) % labs(inc[ii]))
-        {
-           (tilefpix[ii])++;
-           if (tilefpix[ii] >= tiledim[ii])
-              return(0);  /* no overlapping pixels */
-        }
-
-        if (ii > 0)
-           imgdim[ii] *= imgdim[ii - 1];  /* product of dimensions */
-    }
-
-    return(1);  /* there appears to be  intersecting pixels */
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_copy_overlap (
-    char *tile,         /* I - multi dimensional array of tile pixels */
-    int pixlen,         /* I - number of bytes in each tile or image pixel */
-    int ndim,           /* I - number of dimension in the tile and image */
-    long *tfpixel,      /* I - first pixel number in each dim. of the tile */
-    long *tlpixel,      /* I - last pixel number in each dim. of the tile */
-    char *bnullarray,   /* I - array of null flags; used if nullcheck = 2 */
-    char *image,        /* O - multi dimensional output image */
-    long *fpixel,       /* I - first pixel number in each dim. of the image */
-    long *lpixel,       /* I - last pixel number in each dim. of the image */
-    long *ininc,        /* I - increment to be applied in each image dimen. */
-    int nullcheck,      /* I - 0, 1: do nothing; 2: set nullarray for nulls */
-    char *nullarray, 
-    int *status)
-
-/* 
-  copy the intersecting pixels from a decompressed tile to the output image. 
-  Both the tile and the image must have the same number of dimensions. 
-*/
-{
-    long imgdim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */
-                                   /* output image, allowing for inc factor */
-    long tiledim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */
-                                 /* tile, array;  inc factor is not relevant */
-    long imgfpix[MAX_COMPRESS_DIM]; /* 1st img pix overlapping tile: 0 base, */
-                                    /*  allowing for inc factor */
-    long imglpix[MAX_COMPRESS_DIM]; /* last img pix overlapping tile 0 base, */
-                                    /*  allowing for inc factor */
-    long tilefpix[MAX_COMPRESS_DIM]; /* 1st tile pix overlapping img 0 base, */
-                                    /*  allowing for inc factor */
-    long inc[MAX_COMPRESS_DIM]; /* local copy of input ininc */
-    long i1, i2, i3, i4;   /* offset along each axis of the image */
-    long it1, it2, it3, it4;
-    long im1, im2, im3, im4;  /* offset to image pixel, allowing for inc */
-    long ipos, tf, tl;
-    long t2, t3, t4;   /* offset along each axis of the tile */
-    long tilepix, imgpix, tilepixbyte, imgpixbyte;
-    int ii, overlap_bytes, overlap_flags;
-
-    if (*status > 0)
-        return(*status);
-
-    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-    {
-        /* set default values for higher dimensions */
-        inc[ii] = 1;
-        imgdim[ii] = 1;
-        tiledim[ii] = 1;
-        imgfpix[ii] = 0;
-        imglpix[ii] = 0;
-        tilefpix[ii] = 0;
-    }
-
-    /* ------------------------------------------------------------ */
-    /* calc amount of overlap in each dimension; if there is zero   */
-    /* overlap in any dimension then just return  */
-    /* ------------------------------------------------------------ */
-    
-    for (ii = 0; ii < ndim; ii++)
-    {
-        if (tlpixel[ii] < fpixel[ii] || tfpixel[ii] > lpixel[ii])
-            return(*status);  /* there are no overlapping pixels */
-
-        inc[ii] = ininc[ii];
-
-        /* calc dimensions of the output image section */
-        imgdim[ii] = (lpixel[ii] - fpixel[ii]) / labs(inc[ii]) + 1;
-        if (imgdim[ii] < 1)
-            return(*status = NEG_AXIS);
-
-        /* calc dimensions of the tile */
-        tiledim[ii] = tlpixel[ii] - tfpixel[ii] + 1;
-        if (tiledim[ii] < 1)
-            return(*status = NEG_AXIS);
-
-        if (ii > 0)
-           tiledim[ii] *= tiledim[ii - 1];  /* product of dimensions */
-
-        /* first and last pixels in image that overlap with the tile, 0 base */
-        tf = tfpixel[ii] - 1;
-        tl = tlpixel[ii] - 1;
-
-        /* skip this plane if it falls in the cracks of the subsampled image */
-        while ((tf-(fpixel[ii] - 1)) % labs(inc[ii]))
-        {
-           tf++;
-           if (tf > tl)
-             return(*status);  /* no overlapping pixels */
-        }
-
-        while ((tl-(fpixel[ii] - 1)) % labs(inc[ii]))
-        {
-           tl--;
-           if (tf > tl)
-             return(*status);  /* no overlapping pixels */
-        }
-        imgfpix[ii] = maxvalue((tf - fpixel[ii] +1) / labs(inc[ii]) , 0);
-        imglpix[ii] = minvalue((tl - fpixel[ii] +1) / labs(inc[ii]) ,
-                               imgdim[ii] - 1);
-
-        /* first pixel in the tile that overlaps with the image (0 base) */
-        tilefpix[ii] = maxvalue(fpixel[ii] - tfpixel[ii], 0);
-
-        while ((tfpixel[ii] + tilefpix[ii] - fpixel[ii]) % labs(inc[ii]))
-        {
-           (tilefpix[ii])++;
-           if (tilefpix[ii] >= tiledim[ii])
-              return(*status);  /* no overlapping pixels */
-        }
-/*
-printf("ii tfpixel, tlpixel %d %d %d \n",ii, tfpixel[ii], tlpixel[ii]);
-printf("ii, tf, tl, imgfpix,imglpix, tilefpix %d %d %d %d %d %d\n",ii,
- tf,tl,imgfpix[ii], imglpix[ii],tilefpix[ii]);
-*/
-        if (ii > 0)
-           imgdim[ii] *= imgdim[ii - 1];  /* product of dimensions */
-    }
-
-    /* ---------------------------------------------------------------- */
-    /* calc number of pixels in each row (first dimension) that overlap */
-    /* multiply by pixlen to get number of bytes to copy in each loop   */
-    /* ---------------------------------------------------------------- */
-
-    if (inc[0] != 1)
-       overlap_flags = 1;  /* can only copy 1 pixel at a time */
-    else
-       overlap_flags = imglpix[0] - imgfpix[0] + 1;  /* can copy whole row */
-
-    overlap_bytes = overlap_flags * pixlen;
-
-    /* support up to 5 dimensions for now */
-    for (i4 = 0, it4=0; i4 <= imglpix[4] - imgfpix[4]; i4++, it4++)
-    {
-     /* increment plane if it falls in the cracks of the subsampled image */
-     while (ndim > 4 &&  (tfpixel[4] + tilefpix[4] - fpixel[4] + it4)
-                          % labs(inc[4]) != 0)
-        it4++;
-
-       /* offset to start of hypercube */
-       if (inc[4] > 0)
-          im4 = (i4 + imgfpix[4]) * imgdim[3];
-       else
-          im4 = imgdim[4] - (i4 + 1 + imgfpix[4]) * imgdim[3];
-
-      t4 = (tilefpix[4] + it4) * tiledim[3];
-      for (i3 = 0, it3=0; i3 <= imglpix[3] - imgfpix[3]; i3++, it3++)
-      {
-       /* increment plane if it falls in the cracks of the subsampled image */
-       while (ndim > 3 &&  (tfpixel[3] + tilefpix[3] - fpixel[3] + it3)
-                            % labs(inc[3]) != 0)
-          it3++;
-
-       /* offset to start of cube */
-       if (inc[3] > 0)
-          im3 = (i3 + imgfpix[3]) * imgdim[2] + im4;
-       else
-          im3 = imgdim[3] - (i3 + 1 + imgfpix[3]) * imgdim[2] + im4;
-
-       t3 = (tilefpix[3] + it3) * tiledim[2] + t4;
-
-       /* loop through planes of the image */
-       for (i2 = 0, it2=0; i2 <= imglpix[2] - imgfpix[2]; i2++, it2++)
-       {
-          /* incre plane if it falls in the cracks of the subsampled image */
-          while (ndim > 2 &&  (tfpixel[2] + tilefpix[2] - fpixel[2] + it2)
-                               % labs(inc[2]) != 0)
-             it2++;
-
-          /* offset to start of plane */
-          if (inc[2] > 0)
-             im2 = (i2 + imgfpix[2]) * imgdim[1] + im3;
-          else
-             im2 = imgdim[2] - (i2 + 1 + imgfpix[2]) * imgdim[1] + im3;
-
-          t2 = (tilefpix[2] + it2) * tiledim[1] + t3;
-
-          /* loop through rows of the image */
-          for (i1 = 0, it1=0; i1 <= imglpix[1] - imgfpix[1]; i1++, it1++)
-          {
-             /* incre row if it falls in the cracks of the subsampled image */
-             while (ndim > 1 &&  (tfpixel[1] + tilefpix[1] - fpixel[1] + it1)
-                                  % labs(inc[1]) != 0)
-                it1++;
-
-             /* calc position of first pixel in tile to be copied */
-             tilepix = tilefpix[0] + (tilefpix[1] + it1) * tiledim[0] + t2;
-
-             /* offset to start of row */
-             if (inc[1] > 0)
-                im1 = (i1 + imgfpix[1]) * imgdim[0] + im2;
-             else
-                im1 = imgdim[1] - (i1 + 1 + imgfpix[1]) * imgdim[0] + im2;
-/*
-printf("inc = %d %d %d %d\n",inc[0],inc[1],inc[2],inc[3]);
-printf("im1,im2,im3,im4 = %d %d %d %d\n",im1,im2,im3,im4);
-*/
-             /* offset to byte within the row */
-             if (inc[0] > 0)
-                imgpix = imgfpix[0] + im1;
-             else
-                imgpix = imgdim[0] - 1 - imgfpix[0] + im1;
-/*
-printf("tilefpix0,1, imgfpix1, it1, inc1, t2= %d %d %d %d %d %d\n",
-       tilefpix[0],tilefpix[1],imgfpix[1],it1,inc[1], t2);
-printf("i1, it1, tilepix, imgpix %d %d %d %d \n", i1, it1, tilepix, imgpix);
-*/
-             /* loop over pixels along one row of the image */
-             for (ipos = imgfpix[0]; ipos <= imglpix[0]; ipos += overlap_flags)
-             {
-               if (nullcheck == 2)
-               {
-                   /* copy overlapping null flags from tile to image */
-                   memcpy(nullarray + imgpix, bnullarray + tilepix,
-                          overlap_flags);
-               }
-
-               /* convert from image pixel to byte offset */
-               tilepixbyte = tilepix * pixlen;
-               imgpixbyte  = imgpix  * pixlen;
-/*
-printf("  tilepix, tilepixbyte, imgpix, imgpixbyte= %d %d %d %d\n",
-          tilepix, tilepixbyte, imgpix, imgpixbyte);
-*/
-               /* copy overlapping row of pixels from tile to image */
-               memcpy(image + imgpixbyte, tile + tilepixbyte, overlap_bytes);
-
-               tilepix += (overlap_flags * labs(inc[0]));
-               if (inc[0] > 0)
-                 imgpix += overlap_flags;
-               else
-                 imgpix -= overlap_flags;
-            }
-          }
-        }
-      }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int imcomp_merge_overlap (
-    char *tile,         /* O - multi dimensional array of tile pixels */
-    int pixlen,         /* I - number of bytes in each tile or image pixel */
-    int ndim,           /* I - number of dimension in the tile and image */
-    long *tfpixel,      /* I - first pixel number in each dim. of the tile */
-    long *tlpixel,      /* I - last pixel number in each dim. of the tile */
-    char *bnullarray,   /* I - array of null flags; used if nullcheck = 2 */
-    char *image,        /* I - multi dimensional output image */
-    long *fpixel,       /* I - first pixel number in each dim. of the image */
-    long *lpixel,       /* I - last pixel number in each dim. of the image */
-    int nullcheck,      /* I - 0, 1: do nothing; 2: set nullarray for nulls */
-    int *status)
-
-/* 
-  Similar to imcomp_copy_overlap, except it copies the overlapping pixels from
-  the 'image' to the 'tile'.
-*/
-{
-    long imgdim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */
-                                   /* output image, allowing for inc factor */
-    long tiledim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */
-                                 /* tile, array;  inc factor is not relevant */
-    long imgfpix[MAX_COMPRESS_DIM]; /* 1st img pix overlapping tile: 0 base, */
-                                    /*  allowing for inc factor */
-    long imglpix[MAX_COMPRESS_DIM]; /* last img pix overlapping tile 0 base, */
-                                    /*  allowing for inc factor */
-    long tilefpix[MAX_COMPRESS_DIM]; /* 1st tile pix overlapping img 0 base, */
-                                    /*  allowing for inc factor */
-    long inc[MAX_COMPRESS_DIM]; /* local copy of input ininc */
-    long i1, i2, i3, i4;   /* offset along each axis of the image */
-    long it1, it2, it3, it4;
-    long im1, im2, im3, im4;  /* offset to image pixel, allowing for inc */
-    long ipos, tf, tl;
-    long t2, t3, t4;   /* offset along each axis of the tile */
-    long tilepix, imgpix, tilepixbyte, imgpixbyte;
-    int ii, overlap_bytes, overlap_flags;
-
-    if (*status > 0)
-        return(*status);
-
-    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
-    {
-        /* set default values for higher dimensions */
-        inc[ii] = 1;
-        imgdim[ii] = 1;
-        tiledim[ii] = 1;
-        imgfpix[ii] = 0;
-        imglpix[ii] = 0;
-        tilefpix[ii] = 0;
-    }
-
-    /* ------------------------------------------------------------ */
-    /* calc amount of overlap in each dimension; if there is zero   */
-    /* overlap in any dimension then just return  */
-    /* ------------------------------------------------------------ */
-    
-    for (ii = 0; ii < ndim; ii++)
-    {
-        if (tlpixel[ii] < fpixel[ii] || tfpixel[ii] > lpixel[ii])
-            return(*status);  /* there are no overlapping pixels */
-
-        /* calc dimensions of the output image section */
-        imgdim[ii] = (lpixel[ii] - fpixel[ii]) / labs(inc[ii]) + 1;
-        if (imgdim[ii] < 1)
-            return(*status = NEG_AXIS);
-
-        /* calc dimensions of the tile */
-        tiledim[ii] = tlpixel[ii] - tfpixel[ii] + 1;
-        if (tiledim[ii] < 1)
-            return(*status = NEG_AXIS);
-
-        if (ii > 0)
-           tiledim[ii] *= tiledim[ii - 1];  /* product of dimensions */
-
-        /* first and last pixels in image that overlap with the tile, 0 base */
-        tf = tfpixel[ii] - 1;
-        tl = tlpixel[ii] - 1;
-
-        /* skip this plane if it falls in the cracks of the subsampled image */
-        while ((tf-(fpixel[ii] - 1)) % labs(inc[ii]))
-        {
-           tf++;
-           if (tf > tl)
-             return(*status);  /* no overlapping pixels */
-        }
-
-        while ((tl-(fpixel[ii] - 1)) % labs(inc[ii]))
-        {
-           tl--;
-           if (tf > tl)
-             return(*status);  /* no overlapping pixels */
-        }
-        imgfpix[ii] = maxvalue((tf - fpixel[ii] +1) / labs(inc[ii]) , 0);
-        imglpix[ii] = minvalue((tl - fpixel[ii] +1) / labs(inc[ii]) ,
-                               imgdim[ii] - 1);
-
-        /* first pixel in the tile that overlaps with the image (0 base) */
-        tilefpix[ii] = maxvalue(fpixel[ii] - tfpixel[ii], 0);
-
-        while ((tfpixel[ii] + tilefpix[ii] - fpixel[ii]) % labs(inc[ii]))
-        {
-           (tilefpix[ii])++;
-           if (tilefpix[ii] >= tiledim[ii])
-              return(*status);  /* no overlapping pixels */
-        }
-/*
-printf("ii tfpixel, tlpixel %d %d %d \n",ii, tfpixel[ii], tlpixel[ii]);
-printf("ii, tf, tl, imgfpix,imglpix, tilefpix %d %d %d %d %d %d\n",ii,
- tf,tl,imgfpix[ii], imglpix[ii],tilefpix[ii]);
-*/
-        if (ii > 0)
-           imgdim[ii] *= imgdim[ii - 1];  /* product of dimensions */
-    }
-
-    /* ---------------------------------------------------------------- */
-    /* calc number of pixels in each row (first dimension) that overlap */
-    /* multiply by pixlen to get number of bytes to copy in each loop   */
-    /* ---------------------------------------------------------------- */
-
-    if (inc[0] != 1)
-       overlap_flags = 1;  /* can only copy 1 pixel at a time */
-    else
-       overlap_flags = imglpix[0] - imgfpix[0] + 1;  /* can copy whole row */
-
-    overlap_bytes = overlap_flags * pixlen;
-
-    /* support up to 5 dimensions for now */
-    for (i4 = 0, it4=0; i4 <= imglpix[4] - imgfpix[4]; i4++, it4++)
-    {
-     /* increment plane if it falls in the cracks of the subsampled image */
-     while (ndim > 4 &&  (tfpixel[4] + tilefpix[4] - fpixel[4] + it4)
-                          % labs(inc[4]) != 0)
-        it4++;
-
-       /* offset to start of hypercube */
-       if (inc[4] > 0)
-          im4 = (i4 + imgfpix[4]) * imgdim[3];
-       else
-          im4 = imgdim[4] - (i4 + 1 + imgfpix[4]) * imgdim[3];
-
-      t4 = (tilefpix[4] + it4) * tiledim[3];
-      for (i3 = 0, it3=0; i3 <= imglpix[3] - imgfpix[3]; i3++, it3++)
-      {
-       /* increment plane if it falls in the cracks of the subsampled image */
-       while (ndim > 3 &&  (tfpixel[3] + tilefpix[3] - fpixel[3] + it3)
-                            % labs(inc[3]) != 0)
-          it3++;
-
-       /* offset to start of cube */
-       if (inc[3] > 0)
-          im3 = (i3 + imgfpix[3]) * imgdim[2] + im4;
-       else
-          im3 = imgdim[3] - (i3 + 1 + imgfpix[3]) * imgdim[2] + im4;
-
-       t3 = (tilefpix[3] + it3) * tiledim[2] + t4;
-
-       /* loop through planes of the image */
-       for (i2 = 0, it2=0; i2 <= imglpix[2] - imgfpix[2]; i2++, it2++)
-       {
-          /* incre plane if it falls in the cracks of the subsampled image */
-          while (ndim > 2 &&  (tfpixel[2] + tilefpix[2] - fpixel[2] + it2)
-                               % labs(inc[2]) != 0)
-             it2++;
-
-          /* offset to start of plane */
-          if (inc[2] > 0)
-             im2 = (i2 + imgfpix[2]) * imgdim[1] + im3;
-          else
-             im2 = imgdim[2] - (i2 + 1 + imgfpix[2]) * imgdim[1] + im3;
-
-          t2 = (tilefpix[2] + it2) * tiledim[1] + t3;
-
-          /* loop through rows of the image */
-          for (i1 = 0, it1=0; i1 <= imglpix[1] - imgfpix[1]; i1++, it1++)
-          {
-             /* incre row if it falls in the cracks of the subsampled image */
-             while (ndim > 1 &&  (tfpixel[1] + tilefpix[1] - fpixel[1] + it1)
-                                  % labs(inc[1]) != 0)
-                it1++;
-
-             /* calc position of first pixel in tile to be copied */
-             tilepix = tilefpix[0] + (tilefpix[1] + it1) * tiledim[0] + t2;
-
-             /* offset to start of row */
-             if (inc[1] > 0)
-                im1 = (i1 + imgfpix[1]) * imgdim[0] + im2;
-             else
-                im1 = imgdim[1] - (i1 + 1 + imgfpix[1]) * imgdim[0] + im2;
-/*
-printf("inc = %d %d %d %d\n",inc[0],inc[1],inc[2],inc[3]);
-printf("im1,im2,im3,im4 = %d %d %d %d\n",im1,im2,im3,im4);
-*/
-             /* offset to byte within the row */
-             if (inc[0] > 0)
-                imgpix = imgfpix[0] + im1;
-             else
-                imgpix = imgdim[0] - 1 - imgfpix[0] + im1;
-/*
-printf("tilefpix0,1, imgfpix1, it1, inc1, t2= %d %d %d %d %d %d\n",
-       tilefpix[0],tilefpix[1],imgfpix[1],it1,inc[1], t2);
-printf("i1, it1, tilepix, imgpix %d %d %d %d \n", i1, it1, tilepix, imgpix);
-*/
-             /* loop over pixels along one row of the image */
-             for (ipos = imgfpix[0]; ipos <= imglpix[0]; ipos += overlap_flags)
-             {
-               /* convert from image pixel to byte offset */
-               tilepixbyte = tilepix * pixlen;
-               imgpixbyte  = imgpix  * pixlen;
-/*
-printf("  tilepix, tilepixbyte, imgpix, imgpixbyte= %d %d %d %d\n",
-          tilepix, tilepixbyte, imgpix, imgpixbyte);
-*/
-               /* copy overlapping row of pixels from image to tile */
-               memcpy(tile + tilepixbyte, image + imgpixbyte,  overlap_bytes);
-
-               tilepix += (overlap_flags * labs(inc[0]));
-               if (inc[0] > 0)
-                 imgpix += overlap_flags;
-               else
-                 imgpix -= overlap_flags;
-            }
-          }
-        }
-      }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int unquantize_i1r4(long row, /* tile number = row number in table  */
-            unsigned char *input, /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int dither_method,    /* I - dithering method to use             */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-    Unquantize byte values into the scaled floating point values
-*/
-{
-    long ii;
-    int nextrand, iseed;
-
-    if (!fits_rand_value) 
-       if (fits_init_randoms()) return(MEMORY_ALLOCATION);
-
-    /* initialize the index to the next random number in the list */
-    iseed = (int) ((row - 1) % N_RANDOM);
-    nextrand = (int) (fits_rand_value[iseed] * 500);
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-             for (ii = 0; ii < ntodo; ii++)
-            {
-/*
-		if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
-		    output[ii] = 0.0;
-		else
-*/
-                    output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
-
-	        nextrand++;
-	        if (nextrand == N_RANDOM) {
-	            iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-		    nextrand = (int) (fits_rand_value[iseed] * 500);
-	        }
-            }
-    }
-    else        /* must check for null values */
-    {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-/*
-		    if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
-		        output[ii] = 0.0;
-		    else
-*/
-                        output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
-                } 
-
-	        nextrand++;
-	        if (nextrand == N_RANDOM) {
-	            iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-	            nextrand = (int) (fits_rand_value[iseed] * 500);
-                }
-            }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int unquantize_i2r4(long row, /* seed for random values  */
-            short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int dither_method,    /* I - dithering method to use             */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-    Unquantize short integer values into the scaled floating point values
-*/
-{
-    long ii;
-    int nextrand, iseed;
-
-    if (!fits_rand_value) 
-       if (fits_init_randoms()) return(MEMORY_ALLOCATION);
-
-    /* initialize the index to the next random number in the list */
-    iseed = (int) ((row - 1) % N_RANDOM);
-    nextrand = (int) (fits_rand_value[iseed] * 500);
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-           for (ii = 0; ii < ntodo; ii++)
-            {
-/*
-		if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
-		    output[ii] = 0.0;
-		else
-*/
-                    output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
-
-	        nextrand++;
-	        if (nextrand == N_RANDOM) {
-	            iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-		    nextrand = (int) (fits_rand_value[iseed] * 500);
-	        }
-            }
-    }
-    else        /* must check for null values */
-    {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-/*
-                    if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
-		        output[ii] = 0.0;
-		    else
-*/
-                        output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
-                }
-
-	        nextrand++;
-	        if (nextrand == N_RANDOM) {
-	            iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-		    nextrand = (int) (fits_rand_value[iseed] * 500);
-	        }
-             }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int unquantize_i4r4(long row, /* tile number = row number in table    */
-            INT32BIT *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int dither_method,    /* I - dithering method to use             */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-            float nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            float *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-    Unquantize int integer values into the scaled floating point values
-*/
-{
-    long ii;
-    int nextrand, iseed;
-
-    if (fits_rand_value == 0) 
-       if (fits_init_randoms()) return(MEMORY_ALLOCATION);
-
-    /* initialize the index to the next random number in the list */
-    iseed = (int) ((row - 1) % N_RANDOM);
-    nextrand = (int) (fits_rand_value[iseed] * 500);
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
-		    output[ii] = 0.0;
-		else
-                    output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
-
-	        nextrand++;
-	        if (nextrand == N_RANDOM) {
-	            iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-		    nextrand = (int) (fits_rand_value[iseed] * 500);
-	        }
-            }
-    }
-    else        /* must check for null values */
-    {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
-		        output[ii] = 0.0;
-		    else
-                        output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
-                }
-
-	        nextrand++;
-	        if (nextrand == N_RANDOM) {
-	            iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-		    nextrand = (int) (fits_rand_value[iseed] * 500);
-	        }
-            }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int unquantize_i1r8(long row, /* tile number = row number in table  */
-            unsigned char *input, /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int dither_method,    /* I - dithering method to use             */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
-            double nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-    Unquantize byte values into the scaled floating point values
-*/
-{
-    long ii;
-    int nextrand, iseed;
-
-    if (!fits_rand_value) 
-       if (fits_init_randoms()) return(MEMORY_ALLOCATION);
-
-    /* initialize the index to the next random number in the list */
-    iseed = (int) ((row - 1) % N_RANDOM);
-    nextrand = (int) (fits_rand_value[iseed] * 500);
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-/*
-                if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
-		    output[ii] = 0.0;
-		else
-*/
-                    output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
-
-	        nextrand++;
-	        if (nextrand == N_RANDOM) {
-	            iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-		    nextrand = (int) (fits_rand_value[iseed] * 500);
-	        }
-            }
-    }
-    else        /* must check for null values */
-    {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-/*
-                    if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
-		        output[ii] = 0.0;
-		    else
-*/
-                        output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
-                }
-
-	        nextrand++;
-	        if (nextrand == N_RANDOM) {
-	            iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-		    nextrand = (int) (fits_rand_value[iseed] * 500);
-	        }
-            }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int unquantize_i2r8(long row, /* tile number = row number in table  */
-            short *input,         /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int dither_method,    /* I - dithering method to use             */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            short tnull,          /* I - value of FITS TNULLn keyword if any */
-            double nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-    Unquantize short integer values into the scaled floating point values
-*/
-{
-    long ii;
-    int nextrand, iseed;
-
-    if (!fits_rand_value) 
-       if (fits_init_randoms()) return(MEMORY_ALLOCATION);
-
-    /* initialize the index to the next random number in the list */
-    iseed = (int) ((row - 1) % N_RANDOM);
-    nextrand = (int) (fits_rand_value[iseed] * 500);
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-           for (ii = 0; ii < ntodo; ii++)
-            {
-/*
-                if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
-		    output[ii] = 0.0;
-		else
-*/
-                    output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
-
-	        nextrand++;
-	        if (nextrand == N_RANDOM) {
-	            iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-		    nextrand = (int) (fits_rand_value[iseed] * 500);
-	        }
-            }
-    }
-    else        /* must check for null values */
-    {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-/*                    if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
-		        output[ii] = 0.0;
-		    else
-*/
-                        output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
-                }
-
-	        nextrand++;
-	        if (nextrand == N_RANDOM) {
-	            iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-		    nextrand = (int) (fits_rand_value[iseed] * 500);
-	        }
-            }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int unquantize_i4r8(long row, /* tile number = row number in table    */
-            INT32BIT *input,      /* I - array of values to be converted     */
-            long ntodo,           /* I - number of elements in the array     */
-            double scale,         /* I - FITS TSCALn or BSCALE value         */
-            double zero,          /* I - FITS TZEROn or BZERO  value         */
-            int dither_method,    /* I - dithering method to use             */
-            int nullcheck,        /* I - null checking code; 0 = don't check */
-                                  /*     1:set null pixels = nullval         */
-                                  /*     2: if null pixel, set nullarray = 1 */
-            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
-            double nullval,        /* I - set null pixels, if nullcheck = 1   */
-            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
-            int  *anynull,        /* O - set to 1 if any pixels are null     */
-            double *output,        /* O - array of converted pixels           */
-            int *status)          /* IO - error status                       */
-/*
-    Unquantize int integer values into the scaled floating point values
-*/
-{
-    long ii;
-    int nextrand, iseed;
-
-    if (fits_rand_value == 0) 
-       if (fits_init_randoms()) return(MEMORY_ALLOCATION);
-
-    /* initialize the index to the next random number in the list */
-    iseed = (int) ((row - 1) % N_RANDOM);
-    nextrand = (int) (fits_rand_value[iseed] * 500);
-
-    if (nullcheck == 0)     /* no null checking required */
-    {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
-		    output[ii] = 0.0;
-		else
-                    output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
-
-	        nextrand++;
-	        if (nextrand == N_RANDOM) {
-	            iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-		    nextrand = (int) (fits_rand_value[iseed] * 500);
-	        }
-            }
-    }
-    else        /* must check for null values */
-    {
-            for (ii = 0; ii < ntodo; ii++)
-            {
-                if (input[ii] == tnull)
-                {
-                    *anynull = 1;
-                    if (nullcheck == 1)
-                        output[ii] = nullval;
-                    else
-                        nullarray[ii] = 1;
-                }
-                else
-                {
-                    if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
-		        output[ii] = 0.0;
-		    else
-                        output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
-                }
-
-	        nextrand++;
-	        if (nextrand == N_RANDOM) {
-	            iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-		    nextrand = (int) (fits_rand_value[iseed] * 500);
-	        }
-            }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int imcomp_float2nan(float *indata, 
-    long tilelen,
-    int *outdata,
-    float nullflagval, 
-    int *status)
-/*
-  convert pixels that are equal to nullflag to NaNs.
-  Note that indata and outdata point to the same location.
-*/
-{
-    int ii;
-    
-    for (ii = 0; ii < tilelen; ii++) {
-
-      if (indata[ii] == nullflagval)
-        outdata[ii] = -1;  /* integer -1 has the same bit pattern as a real*4 NaN */
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int imcomp_double2nan(double *indata, 
-    long tilelen,
-    LONGLONG *outdata,
-    double nullflagval, 
-    int *status)
-/*
-  convert pixels that are equal to nullflag to NaNs.
-  Note that indata and outdata point to the same location.
-*/
-{
-    int ii;
-    
-    for (ii = 0; ii < tilelen; ii++) {
-
-      if (indata[ii] == nullflagval)
-        outdata[ii] = -1;  /* integer -1 has the same bit pattern as a real*8 NaN */
-    }
-
-    return(*status);
-}
-
-/* ======================================================================= */
-/*    TABLE COMPRESSION ROUTINES                                           */
-/* =-====================================================================== */
-
-/*--------------------------------------------------------------------------*/
-int fits_compress_table(fitsfile *infptr, fitsfile *outfptr, int *status)
-
-/*
-  Compress the input FITS Binary Table.
-  
-  First divide the table into equal sized chunks (analogous to image tiles) where all
-  the contain the same number of rows (except perhaps for the last chunk
-  which may contain fewer rows).   The chunks should not be too large to copy into memory
-  (currently, about 100 MB max seems a reasonable size).
-  
-  Then, on a chunk by piece basis, do the following:
-  
-  1. Transpose the table from its original row-major order, into column-major order.
-  All the bytes for each column are then continuous.  In addition, the bytes within
-  each table element may be shuffled so that the most significant
-  byte of every element occurs first in the array, followed by the next most
-  significant byte, and so on to the least significant byte.  Byte shuffling often
-  improves the gzip compression of floating-point arrays.
-   
-  2. Compress the contiguous array of bytes in each column using the specified
-  compression method.  If no method is specifed, then a default method for that
-  data type is chosen. 
-  
-  3. Store the compressed stream of bytes into a column that has the same name
-  as in the input table, but which has a variable-length array data type (1QB).
-  The output table will contain one row for each piece of the original table.
-  
-  4. If the input table contain variable-length arrays, then each VLA
-  is compressed individually, and written to the heap in the output table.
-  Note that the output table will contain 2 sets of pointers for each VLA column.  
-  The first set contains the pointers to the uncompressed VLAs from the input table
-  and the second is the set of pointers to the compressed VLAs in the output table.
-  The latter set of pointers is used to reconstruct table when it is uncompressed,
-  so that the heap has exactly the same structure as in the original file.  The 2
-  sets of pointers are concatinated together, compressed with gzip, and written to
-  the output table.  When reading the compressed table, the only VLA that is directly
-  visible is this compressed array of descriptors.  One has to uncompress this array
-  to be able to to read all the descriptors to the individual VLAs in the column.  
-*/
-{ 
-    long maxchunksize = 10000000; /* default value for the size of each chunk of the table */
-
-    char *cm_buffer;  /* memory buffer for the transposed, Column-Major, chunk of the table */ 
-    LONGLONG cm_colstart[1000];  /* starting offset of each column in the cm_buffer */
-    LONGLONG rm_repeat[1000];    /* repeat count of each column in the input row-major table */
-    LONGLONG rm_colwidth[999];   /* width in bytes of each column in the input row-major table */
-    LONGLONG cm_repeat[999];  /* total number of elements in each column of the transposed column-major table */
-
-    int coltype[999];         /* data type code for each column */
-    int compalgor[999], default_algor = 0;       /* compression algorithm to be applied to each column */
-    float cratio[999];        /* compression ratio for each column (for diagnostic purposes) */
-
-    float compressed_size, uncompressed_size, tot_compressed_size, tot_uncompressed_size;
-    LONGLONG nrows, firstrow;
-    LONGLONG headstart, datastart, dataend, startbyte, jj, kk, naxis1;
-    LONGLONG vlalen, vlamemlen, vlastart, bytepos;
-    long repeat, width, nchunks, rowspertile, lastrows;
-    int ii, ll, ncols, hdutype, ltrue = 1, print_report = 0, tstatus;
-    char *cptr, keyname[9], tform[40], *cdescript;
-    char comm[FLEN_COMMENT], keyvalue[FLEN_VALUE], *cvlamem, tempstring[FLEN_VALUE], card[FLEN_CARD];
-
-    LONGLONG *descriptors, *outdescript, *vlamem;
-    int *pdescriptors;
-    size_t dlen, datasize, compmemlen;
-
-    /* ================================================================================== */
-    /* perform initial sanity checks */
-    /* ================================================================================== */
-    
-    /* special input flag value that means print out diagnostics */
-    if (*status == -999) {
-       print_report = 1;
-       *status = 0;
-    }
-
-    if (*status > 0)
-        return(*status);
-    
-    fits_get_hdu_type(infptr, &hdutype, status);
-    if (hdutype != BINARY_TBL) {
-        *status = NOT_BTABLE;
-        return(*status);
-    }
-
-    if (infptr == outfptr) {
-        ffpmsg("Cannot compress table 'in place' (fits_compress_table)");
-        ffpmsg(" outfptr cannot be the same as infptr.");
-        *status = DATA_COMPRESSION_ERR;
-        return(*status);
-    }
-
-    /* get dimensions of the table */
-    fits_get_num_rowsll(infptr, &nrows, status);
-    fits_get_num_cols(infptr, &ncols, status);
-    fits_read_key(infptr, TLONGLONG, "NAXIS1", &naxis1, NULL, status);
-    /* get offset to the start of the data and total size of the table (including the heap) */
-    fits_get_hduaddrll(infptr, &headstart, &datastart, &dataend, status);
-
-    if (*status > 0)
-        return(*status);
-
-    tstatus = 0;
-    if (!fits_read_key(infptr, TSTRING, "FZALGOR", tempstring, NULL, &tstatus)) {
-
-	    if (!fits_strcasecmp(tempstring, "NONE")) {
-	            default_algor = NOCOMPRESS;
-	    } else if (!fits_strcasecmp(tempstring, "GZIP") || !fits_strcasecmp(tempstring, "GZIP_1")) {
-	            default_algor = GZIP_1;
-	    } else if (!fits_strcasecmp(tempstring, "GZIP_2")) {
-	            default_algor = GZIP_2;
- 	    } else if (!fits_strcasecmp(tempstring, "RICE_1")) {
-	            default_algor = RICE_1;
- 	    } else {
- 	        ffpmsg("FZALGOR specifies unsupported table compression algorithm:");
-		ffpmsg(tempstring);
-	        *status = DATA_COMPRESSION_ERR;
-	        return(*status);
-	    }
-    }
-
-     /* just copy the HDU verbatim if the table has 0 columns or rows or if the table */
-    /* is less than 5760 bytes (2 blocks) in size, or compression directive keyword = "NONE" */
-    if (nrows < 1  || ncols < 1 || (dataend - datastart) < 5760  || default_algor == NOCOMPRESS) {
-	fits_copy_hdu (infptr, outfptr, 0, status);
-	return(*status);
-    }
-   
-    /* Check if the chunk size has been specified with the FZTILELN keyword. */
-    /* If not, calculate a default number of rows per chunck, */
-
-    tstatus = 0;
-    if (fits_read_key(infptr, TLONG, "FZTILELN", &rowspertile, NULL, &tstatus)) {
-	rowspertile = (long) (maxchunksize / naxis1);
-    }
-
-    if (rowspertile < 1) rowspertile = 1;  
-    if (rowspertile > nrows) rowspertile = (long) nrows;
-    
-    nchunks = (long) ((nrows - 1) / rowspertile + 1);  /* total number of chunks */
-    lastrows = (long) (nrows - ((nchunks - 1) * rowspertile)); /* number of rows in last chunk */
-
-    /* allocate space for the transposed, column-major chunk of the table */
-    cm_buffer = calloc((size_t) naxis1, (size_t) rowspertile);
-    if (!cm_buffer) {
-        ffpmsg("Could not allocate cm_buffer for transposed table");
-        *status = MEMORY_ALLOCATION;
-        return(*status);
-    }
-
-    /* ================================================================================== */
-    /*  Construct the header of the output compressed table  */
-    /* ================================================================================== */
-    fits_copy_header(infptr, outfptr, status);  /* start with verbatim copy of the input header */
-
-    fits_write_key(outfptr, TLOGICAL, "ZTABLE", <rue, "this is a compressed table", status);
-    fits_write_key(outfptr, TLONG, "ZTILELEN", &rowspertile, "number of rows in each tile", status);
-
-    fits_read_card(outfptr, "NAXIS1", card, status); /* copy NAXIS1 to ZNAXIS1 */
-    strncpy(card, "ZNAXIS1", 7);
-    fits_write_record(outfptr, card, status);
-    
-    fits_read_card(outfptr, "NAXIS2", card, status); /* copy NAXIS2 to ZNAXIS2 */
-    strncpy(card, "ZNAXIS2", 7);
-    fits_write_record(outfptr, card, status);
-
-    fits_read_card(outfptr, "PCOUNT", card, status); /* copy PCOUNT to ZPCOUNT */
-    strncpy(card, "ZPCOUNT", 7);
-    fits_write_record(outfptr, card, status);
-
-    fits_modify_key_lng(outfptr, "NAXIS2", nchunks, "&", status);  /* 1 row per chunk */
-    fits_modify_key_lng(outfptr, "NAXIS1", ncols * 16, "&", status); /* 16 bytes for each 1QB column */
-    fits_modify_key_lng(outfptr, "PCOUNT", 0L, "&", status); /* reset PCOUNT to 0 */
-    
-    /* rename the Checksum keywords, if they exist */
-    tstatus = 0;
-    fits_modify_name(outfptr, "CHECKSUM", "ZHECKSUM", &tstatus);
-    tstatus = 0;
-    fits_modify_name(outfptr, "DATASUM", "ZDATASUM", &tstatus);
-
-    /* ================================================================================== */
-    /*  Now loop over each column of the input table: write the column-specific keywords */
-    /*  and determine which compression algorithm to use.     */
-    /*  Also calculate various offsets to the start of the column data in both the */
-    /*  original row-major table and in the transposed column-major form of the table.  */
-    /* ================================================================================== */
-
-    cm_colstart[0] = 0;
-    for (ii = 0; ii < ncols; ii++) {  
-
- 	/* get the structural parameters of the original uncompressed column */
-	fits_make_keyn("TFORM", ii+1, keyname, status);
-	fits_read_key(outfptr, TSTRING, keyname, tform, comm, status);
-        fits_binary_tform(tform, coltype+ii, &repeat, &width, status); /* get the repeat count and the width */
-
-	/* preserve the original TFORM value and comment string in a ZFORMn keyword */
-	fits_read_card(outfptr, keyname, card, status); 
-	card[0] = 'Z';
-	fits_write_record(outfptr, card, status);
- 
-        /* All columns in the compressed table will have a variable-length array type. */
-	fits_modify_key_str(outfptr, keyname, "1QB", "&", status);  /* Use 'Q' pointers (64-bit) */ 
-
-	/* deal with special cases: bit, string, and variable length array columns */
-	if (coltype[ii] == TBIT) {
-	    repeat = (repeat + 7) / 8;  /* convert from bits to equivalent number of bytes */
-	} else if (coltype[ii] == TSTRING) {
-	    width = 1;  /* ignore the optional 'w' in 'rAw' format */
-	} else if (coltype[ii] < 0) {  /* pointer to variable length array */
-	    if (strchr(tform,'Q') ) {
-	        width = 16;  /* 'Q' descriptor has 64-bit pointers */
-	    } else {
-	        width = 8;  /* 'P' descriptor has 32-bit pointers */
- 	    }
-	    repeat = 1;
-	}
-
-	rm_repeat[ii] = repeat;   
-	rm_colwidth[ii] = repeat * width; /* column width (in bytes)in the input table */
-	
-	/* starting offset of each field in the OUTPUT transposed column-major table */
-	cm_colstart[ii + 1] = cm_colstart[ii] + rm_colwidth[ii] * rowspertile;
-	/* total number of elements in each column of the transposed column-major table */
-	cm_repeat[ii] = rm_repeat[ii] * rowspertile;
-
-	compalgor[ii] = default_algor;  /* initialize the column compression algorithm to the default */
-	
-	/*  check if a compression method has been specified for this column */
-	fits_make_keyn("FZALG", ii+1, keyname, status);
-	tstatus = 0;
-	if (!fits_read_key(outfptr, TSTRING, keyname, tempstring, NULL, &tstatus)) {
-
-	    if (!fits_strcasecmp(tempstring, "GZIP") || !fits_strcasecmp(tempstring, "GZIP_1")) {
-	            compalgor[ii] = GZIP_1;
-	    } else if (!fits_strcasecmp(tempstring, "GZIP_2")) {
-	            compalgor[ii] = GZIP_2;
-	    } else if (!fits_strcasecmp(tempstring, "RICE_1")) {
-	            compalgor[ii] = RICE_1;
-	    } else {
-	        ffpmsg("Unsupported table compression algorithm specification.");
-		ffpmsg(keyname);
-		ffpmsg(tempstring);
-	        *status = DATA_COMPRESSION_ERR;
-		free(cm_buffer);
-	        return(*status);
-	    }
-	}
-
-	/* do sanity check of the requested algorithm and override if necessary */
-	if ( abs(coltype[ii]) == TLOGICAL || abs(coltype[ii]) == TBIT || abs(coltype[ii]) == TSTRING) {
-	        if (compalgor[ii] != GZIP_1) {
-			compalgor[ii] = GZIP_1;
-		}
-	} else if ( abs(coltype[ii]) == TCOMPLEX || abs(coltype[ii]) == TDBLCOMPLEX ||
-	                abs(coltype[ii]) == TFLOAT   || abs(coltype[ii]) == TDOUBLE ||
-			abs(coltype[ii]) == TLONGLONG ) {
-	        if (compalgor[ii] != GZIP_1 && compalgor[ii] != GZIP_2) {
-			compalgor[ii] = GZIP_2;  /* gzip_2 usually works better gzip_1 */
-		}
-	} else if ( abs(coltype[ii]) == TSHORT ) {
-	        if (compalgor[ii] != GZIP_1 && compalgor[ii] != GZIP_2 && compalgor[ii] != RICE_1) {
-			compalgor[ii] = GZIP_2;  /* gzip_2 usually works better rice_1 */
-		 }
-	} else if (  abs(coltype[ii]) == TLONG	) {
-	        if (compalgor[ii] != GZIP_1 && compalgor[ii] != GZIP_2 && compalgor[ii] != RICE_1) {
-			compalgor[ii] = RICE_1;
-		}
-	} else if ( abs(coltype[ii]) == TBYTE ) {
-	        if (compalgor[ii] != GZIP_1 && compalgor[ii] != RICE_1 ) {
-			compalgor[ii] = GZIP_1;
-		}
-	}
-    }  /* end of loop over columns */
-
-    /* ================================================================================== */
-    /*    now process each chunk of the table, in turn          */
-    /* ================================================================================== */
-
-    tot_uncompressed_size = 0.;
-    tot_compressed_size = 0;
-    firstrow = 1;
-    for (ll = 0; ll < nchunks; ll++) {
-
-        if (ll == nchunks - 1) {  /* the last chunk may have fewer rows */
-	    rowspertile = lastrows; 
-            for (ii = 0; ii < ncols; ii++) { 
-		cm_colstart[ii + 1] = cm_colstart[ii] + (rm_colwidth[ii] * rowspertile);
-		cm_repeat[ii] = rm_repeat[ii] * rowspertile;
-	    }
-	}
-
-        /* move to the start of the chunk in the input table */
-        ffmbyt(infptr, datastart, 0, status);
-
-        /* ================================================================================*/
-        /*  First, transpose this chunck from row-major order to column-major order  */
-	/*  At the same time, shuffle the bytes in each datum, if doing GZIP_2 compression */
-        /* ================================================================================*/
-
-        for (jj = 0; jj < rowspertile; jj++)   {    /* loop over rows */
-          for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
-      
-           if (rm_repeat[ii] > 0) {  /*  skip virtual columns that have 0 elements */
-
-	    kk = 0;	
-
-	     /* if the  GZIP_2 compression algorithm is used, shuffle the bytes */
-	    if (coltype[ii] == TSHORT && compalgor[ii] == GZIP_2) {
-	      while(kk < rm_colwidth[ii]) {
-	        cptr = cm_buffer + (cm_colstart[ii] + (jj * rm_repeat[ii]) + kk/2);  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 1st byte */
-	        cptr += cm_repeat[ii];  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 2nd byte */
-	        kk += 2;
-	      }
-	    } else if ((coltype[ii] == TFLOAT || coltype[ii] == TLONG) && compalgor[ii] == GZIP_2) {
-	      while(kk < rm_colwidth[ii]) {
-	        cptr = cm_buffer + (cm_colstart[ii] + (jj * rm_repeat[ii]) + kk/4);  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 1st byte */
-	        cptr += cm_repeat[ii];  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 2nd byte */
-	        cptr += cm_repeat[ii];  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 3rd byte */
-	        cptr += cm_repeat[ii];  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 4th byte */
-	        kk += 4;
-	      }
-	    } else if ( (coltype[ii] == TDOUBLE || coltype[ii] == TLONGLONG) && compalgor[ii] == GZIP_2) {
-	      while(kk < rm_colwidth[ii]) {
-	        cptr = cm_buffer + (cm_colstart[ii] + (jj * rm_repeat[ii]) + kk/8);  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 1st byte */
-	        cptr += cm_repeat[ii];  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 2nd byte */
-	        cptr += cm_repeat[ii];  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 3rd byte */
-	        cptr += cm_repeat[ii];  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 4th byte */
-	        cptr += cm_repeat[ii];  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 5th byte */
-	        cptr += cm_repeat[ii];  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 6th byte */
-	        cptr += cm_repeat[ii];  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 7th byte */
-	        cptr += cm_repeat[ii];  
-	        ffgbyt(infptr, 1, cptr, status);  /* get 8th byte */
-	        kk += 8;
-	      }
-	    } else  { /* all other cases: don't shuffle the bytes; simply transpose the column */
-	        cptr = cm_buffer + (cm_colstart[ii] + (jj * rm_colwidth[ii]));   /* addr to copy to */
-	        startbyte = (infptr->Fptr)->bytepos;  /* save the starting byte location */
-	        ffgbyt(infptr, rm_colwidth[ii], cptr, status);  /* copy all the bytes */
-
-	        if (rm_colwidth[ii] >= MINDIRECT) { /* have to explicitly move to next byte */
-	  	    ffmbyt(infptr, startbyte + rm_colwidth[ii], 0, status);
-	        }
-	    }  /* end of test of coltypee */
-
-           }  /* end of not virtual column */
-          }  /* end of loop over columns */
-        }  /* end of loop over rows */
-
-        /* ================================================================================*/
-        /*  now compress each column in the transposed chunk of the table    */
-        /* ================================================================================*/
-
-        fits_set_hdustruc(outfptr, status);  /* initialize structures in the output table */
-    
-        for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
-	  /* initialize the diagnostic compression results string */
-	  sprintf(results[ii],"%3d %3d %3d ", ii+1, coltype[ii], compalgor[ii]);  
-          cratio[ii] = 0;
-	  
-          if (rm_repeat[ii] > 0) {  /* skip virtual columns with zero width */
-
-	    if (coltype[ii] < 0)  {  /* this is a variable length array (VLA) column */
-
-		/*=========================================================================*/	    
-	        /* variable-length array columns are a complicated special case  */
-		/*=========================================================================*/
-
-		/* allocate memory to hold all the VLA descriptors from the input table, plus */
-		/* room to hold the descriptors to the compressed VLAs in the output table */
-		/* In total, there will be 2 descriptors for each row in this chunk */
-
-		uncompressed_size = 0.;
-		compressed_size = 0;
-		
-		datasize = (size_t) (cm_colstart[ii + 1] - cm_colstart[ii]); /* size of input descriptors */
-
-		cdescript =  calloc(datasize + (rowspertile * 16), 1); /* room for both descriptors */
-		if (!cdescript) {
-                    ffpmsg("Could not allocate buffer for descriptors");
-                    *status = MEMORY_ALLOCATION;
-		    free(cm_buffer);
-	            return(*status);
-		}
-
-		/* copy the input descriptors to this array */
-		memcpy(cdescript, &cm_buffer[cm_colstart[ii]], datasize);
-#if BYTESWAPPED
-		/* byte-swap the integer values into the native machine representation */
-		if (rm_colwidth[ii] == 16) {
-		    ffswap8((double *) cdescript,  rowspertile * 2);
-		} else {
-		    ffswap4((int *) cdescript,  rowspertile * 2);
-		}
-#endif
-		descriptors = (LONGLONG *) cdescript;  /* use this for Q type descriptors */
-		pdescriptors = (int *) cdescript;     /* use this instead for or P type descriptors */
-		/* pointer to the 2nd set of descriptors */
-		outdescript = (LONGLONG *) (cdescript + datasize);  /* this is a LONGLONG pointer */
-		
-		for (jj = 0; jj < rowspertile; jj++)   {    /* loop to compress each VLA in turn */
-
-		  if (rm_colwidth[ii] == 16) { /* if Q pointers */
-			vlalen = descriptors[jj * 2];
-			vlastart = descriptors[(jj * 2) + 1];
-		  } else {  /* if P pointers */
-			vlalen = (LONGLONG) pdescriptors[jj * 2];
-			vlastart = (LONGLONG) pdescriptors[(jj * 2) + 1];
-		  }
-
-		  if (vlalen > 0) {  /* skip zero-length VLAs */
-
-		    vlamemlen = vlalen * (int) (-coltype[ii] / 10);
-		    vlamem = (LONGLONG *) malloc((size_t) vlamemlen); /* memory for the input uncompressed VLA */
-		    if (!vlamem) {
-			ffpmsg("Could not allocate buffer for VLA");
-			*status = MEMORY_ALLOCATION;
-			free(cdescript); free(cm_buffer);
-			return(*status);
-		    }
-
-		    compmemlen = (size_t) (vlalen * ((LONGLONG) (-coltype[ii] / 10)) * 1.5);
-		    if (compmemlen < 100) compmemlen = 100;
-		    cvlamem = malloc(compmemlen);  /* memory for the output compressed VLA */
-		    if (!cvlamem) {
-			ffpmsg("Could not allocate buffer for compressed data");
-			*status = MEMORY_ALLOCATION;
-			free(vlamem); free(cdescript); free(cm_buffer);
-			return(*status);
-		    }
-
-		    /* read the raw bytes directly from the heap, without any byte-swapping or null value detection */
-		    bytepos = (infptr->Fptr)->datastart + (infptr->Fptr)->heapstart + vlastart;
-		    ffmbyt(infptr, bytepos, REPORT_EOF, status);
-		    ffgbyt(infptr, vlamemlen, vlamem, status);  /* read the bytes */
-		    uncompressed_size += vlamemlen;  /* total size of the uncompressed VLAs */
-		    tot_uncompressed_size += vlamemlen;  /* total size of the uncompressed file */
-
-		    /* compress the VLA with the appropriate algorithm */
-	    	    if (compalgor[ii] == RICE_1) {
-
-		        if (-coltype[ii] == TSHORT) {
-#if BYTESWAPPED
-			  ffswap2((short *) (vlamem),  (long) vlalen); 
-#endif
-			  dlen = fits_rcomp_short ((short *)(vlamem), (int) vlalen, (unsigned char *) cvlamem,
-			   (int) compmemlen, 32);
-		        } else if (-coltype[ii] == TLONG) {
-#if BYTESWAPPED
-			  ffswap4((int *) (vlamem),  (long) vlalen); 
-#endif
-			  dlen = fits_rcomp ((int *)(vlamem), (int) vlalen, (unsigned char *) cvlamem,
-                           (int) compmemlen, 32);
-		        } else if (-coltype[ii] == TBYTE) {
-			  dlen = fits_rcomp_byte ((signed char *)(vlamem), (int) vlalen, (unsigned char *) cvlamem,
-                           (int) compmemlen, 32);
-		        } else {
-			  /* this should not happen */
-			  ffpmsg(" Error: cannot compress this column type with the RICE algorthm");
-			  free(vlamem); free(cdescript); free(cm_buffer); free(cvlamem);
-			  *status = DATA_COMPRESSION_ERR;
-			  return(*status);
-		        }  
-		    } else if (compalgor[ii] == GZIP_1 || compalgor[ii] == GZIP_2){  
-		       if (compalgor[ii] == GZIP_2 ) {  /* shuffle the bytes before gzipping them */
-			   if ( (int) (-coltype[ii] / 10) == 2) {
-			       fits_shuffle_2bytes((char *) vlamem, vlalen, status);
-			   } else if ( (int) (-coltype[ii] / 10) == 4) {
-			       fits_shuffle_4bytes((char *) vlamem, vlalen, status);
-			   } else if ( (int) (-coltype[ii] / 10) == 8) {
-			       fits_shuffle_8bytes((char *) vlamem, vlalen, status);
-			   }
-		        }
-		        /*: gzip compress the array of bytes */
-		        compress2mem_from_mem( (char *) vlamem, (size_t) vlamemlen,
-	    		    &cvlamem,  &compmemlen, realloc, &dlen, status);        
-		    } else {
-			  /* this should not happen */
-			  ffpmsg(" Error: unknown compression algorthm");
-			  free(vlamem); free(cdescript); free(cm_buffer); free(cvlamem);
-			  *status = DATA_COMPRESSION_ERR;
-			  return(*status);
-		    }  
-
-		    /* write the compressed array to the output table, but... */
-		    /* We use a trick of always writing the array to the same row of the output table */
-		    /* and then copy the descriptor into the array of descriptors that we allocated. */
-		     
-		    /* First, reset the descriptor */
-		    fits_write_descript(outfptr, ii+1, ll+1, 0, 0, status);
-
-		    /* write the compressed VLA if it is smaller than the original, else write */
-		    /* the uncompressed array */
-		    fits_set_tscale(outfptr, ii + 1, 1.0, 0.0, status);  /* turn off any data scaling, first */
-		    if (dlen < vlamemlen) {
-		        fits_write_col(outfptr, TBYTE, ii + 1, ll+1, 1, dlen, cvlamem, status);
-		        compressed_size += dlen;  /* total size of the compressed VLAs */
-		        tot_compressed_size += dlen;  /* total size of the compressed file */
-		    } else {
-			if ( -coltype[ii] != TBYTE && compalgor[ii] != GZIP_1) {
-			    /* it is probably faster to reread the raw bytes, rather than unshuffle or unswap them */
-			    bytepos = (infptr->Fptr)->datastart + (infptr->Fptr)->heapstart + vlastart;
-			    ffmbyt(infptr, bytepos, REPORT_EOF, status);
-			    ffgbyt(infptr, vlamemlen, vlamem, status);  /* read the bytes */
-			}
-		        fits_write_col(outfptr, TBYTE, ii + 1, ll+1, 1, vlamemlen, vlamem, status);
-		        compressed_size += vlamemlen;  /* total size of the compressed VLAs */
-		        tot_compressed_size += vlamemlen;  /* total size of the compressed file */
-		    }
-
-		    /* read back the descriptor and save it in the array of descriptors */
-		    fits_read_descriptll(outfptr, ii + 1, ll + 1, outdescript+(jj*2), outdescript+(jj*2)+1, status);
-		    free(cvlamem);  free(vlamem);
-
-		  } /* end of vlalen > 0 */
-		}  /* end of loop over rows */
-
-		if (compressed_size != 0)
-		    cratio[ii] = uncompressed_size / compressed_size;
-
-		sprintf(tempstring," r=%6.2f",cratio[ii]);
-		strcat(results[ii],tempstring);
-
-		/* now we just have to compress the array of descriptors (both input and output) */
-		/* and write them to the output table. */
-
-		/* allocate memory for the compressed descriptors */
-		cvlamem = malloc(datasize + (rowspertile * 16) );
-		if (!cvlamem) {
-		    ffpmsg("Could not allocate buffer for compressed data");
-		    *status = MEMORY_ALLOCATION;
-		    free(cdescript); free(cm_buffer);
-		    return(*status);
-		}
-
-#if BYTESWAPPED
-		/* byte swap the input and output descriptors */
-		if (rm_colwidth[ii] == 16) {
-		    ffswap8((double *) cdescript,  rowspertile * 2);
-		} else {
-		    ffswap4((int *) cdescript,  rowspertile * 2);
-		}
-		ffswap8((double *) outdescript,  rowspertile * 2);
-#endif
-		/* compress the array contain both sets of descriptors */
-		compress2mem_from_mem((char *) cdescript, datasize + (rowspertile * 16),
-	    		&cvlamem,  &datasize, realloc, &dlen, status);        
-
-		free(cdescript);
-
-		/* write the compressed descriptors to the output column */
-		fits_set_tscale(outfptr, ii + 1, 1.0, 0.0, status);  /* turn off any data scaling, first */
-		fits_write_descript(outfptr, ii+1, ll+1, 0, 0, status); /* First, reset the descriptor */
-		fits_write_col(outfptr, TBYTE, ii + 1, ll+1, 1, dlen, cvlamem, status);
-		free(cvlamem); 
-
-		if (ll == 0) {  /* only write the ZCTYPn keyword once, while processing the first column */
-			fits_make_keyn("ZCTYP", ii+1, keyname, status);
-
-			if (compalgor[ii] == RICE_1) {
-			     strcpy(keyvalue, "RICE_1");
-			} else if (compalgor[ii] == GZIP_2) {
-			     strcpy(keyvalue, "GZIP_2");
-			} else {
-			     strcpy(keyvalue, "GZIP_1");
-			}
-
-			fits_write_key(outfptr, TSTRING, keyname, keyvalue,
-			"compression algorithm for column", status);
-		}
-
-	        continue;  /* jump to end of loop, to go to next column */
-	    }  /* end of VLA case */
-
-	    /* ================================================================================*/
-	    /* deal with all the normal fixed-length columns here */
-	    /* ================================================================================*/
-
-	    /* allocate memory for the compressed data */
-	    datasize = (size_t) (cm_colstart[ii + 1] - cm_colstart[ii]);
-	    cvlamem = malloc(datasize*2);
-	    tot_uncompressed_size += datasize;
-	    
-	    if (!cvlamem) {
-                ffpmsg("Could not allocate buffer for compressed data");
-                *status = MEMORY_ALLOCATION;
-		free(cm_buffer);
-	        return(*status);
-	    }
-
-	    if (compalgor[ii] == RICE_1) {
-	        if (coltype[ii] == TSHORT) {
-#if BYTESWAPPED
-                    ffswap2((short *) (cm_buffer + cm_colstart[ii]),  datasize / 2); 
-#endif
-  	            dlen = fits_rcomp_short ((short *)(cm_buffer + cm_colstart[ii]), datasize / 2, (unsigned char *) cvlamem,
-                       datasize * 2, 32);
-
-	        } else if (coltype[ii] == TLONG) {
-#if BYTESWAPPED
-                    ffswap4((int *) (cm_buffer + cm_colstart[ii]),  datasize / 4); 
-#endif
-   	            dlen = fits_rcomp ((int *)(cm_buffer + cm_colstart[ii]), datasize / 4, (unsigned char *) cvlamem,
-                       datasize * 2, 32);
-
-	        } else if (coltype[ii] == TBYTE) {
-
-  	            dlen = fits_rcomp_byte ((signed char *)(cm_buffer + cm_colstart[ii]), datasize, (unsigned char *) cvlamem,
-                       datasize * 2, 32);
-	        } else {  /* this should not happen */
-                    ffpmsg(" Error: cannot compress this column type with the RICE algorthm");
-		    free(cvlamem);  free(cm_buffer);
-	            *status = DATA_COMPRESSION_ERR;
-	            return(*status);
-	        }
-	    } else {
-	    	/* all other cases: gzip compress the column (bytes may have been shuffled previously) */
-		compress2mem_from_mem(cm_buffer + cm_colstart[ii], datasize,
-	    		&cvlamem,  &datasize, realloc, &dlen, status);        
-	    }
-
-	    if (ll == 0) {  /* only write the ZCTYPn keyword once, while processing the first column */
-		fits_make_keyn("ZCTYP", ii+1, keyname, status);
-
-		if (compalgor[ii] == RICE_1) {
-		     strcpy(keyvalue, "RICE_1");
-		} else if (compalgor[ii] == GZIP_2) {
-		     strcpy(keyvalue, "GZIP_2");
-		} else {
-		     strcpy(keyvalue, "GZIP_1");
-		}
-
-		fits_write_key(outfptr, TSTRING, keyname, keyvalue,
-		"compression algorithm for column", status);
-	    }
-
-	    /* write the compressed data to the output column */
-	    fits_set_tscale(outfptr, ii + 1, 1.0, 0.0, status);  /* turn off any data scaling, first */
-	    fits_write_col(outfptr, TBYTE, ii + 1, ll+1, 1, dlen, cvlamem, status);
-	    tot_compressed_size += dlen;
-
-	    free(cvlamem);   /* don't need the compressed data any more */
-
-            /* create diagnostic messages */
-	    if (dlen != 0)
-	       cratio[ii] = (float) datasize / (float) dlen;  /* compression ratio of the column */
-
-	    sprintf(tempstring," r=%6.2f",cratio[ii]);
-	    strcat(results[ii],tempstring);
- 
-          }  /* end of not a virtual column */
-        }  /* end of loop over columns */
-
-        datastart += (rowspertile * naxis1);   /* increment to start of next chunk */
-        firstrow += rowspertile;  /* increment first row in next chunk */
-
-       if (print_report) {
-	  printf("\nChunk = %d\n",ll+1);
-	  for (ii = 0; ii < ncols; ii++) {  
-		printf("%s\n", results[ii]);
-	  }
-	}
-	
-    }  /* end of loop over chunks of the table */
-
-    /* =================================================================================*/
-    /*  all done; just clean up and return  */
-    /* ================================================================================*/
-
-    free(cm_buffer);
-    fits_set_hdustruc(outfptr, status);  /* reset internal structures */
-       	
-    if (print_report) {
-
-       if (tot_compressed_size != 0)
-           printf("\nTotal data size (MB) %.3f -> %.3f, ratio = %.3f\n", tot_uncompressed_size/1000000., 
-	     tot_compressed_size/1000000., tot_uncompressed_size/tot_compressed_size);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_uncompress_table(fitsfile *infptr, fitsfile *outfptr, int *status)
-
-/*
-  Uncompress the table that was compressed with fits_compress_table
-*/
-{ 
-    char colcode[999];  /* column data type code character */
-    char coltype[999];  /* column data type numeric code value */
-    char *cm_buffer;   /* memory buffer for the transposed, Column-Major, chunk of the table */ 
-    char *rm_buffer;   /* memory buffer for the original, Row-Major, chunk of the table */ 
-    LONGLONG nrows, rmajor_colwidth[999], rmajor_colstart[1000], cmajor_colstart[1000];
-    LONGLONG cmajor_repeat[999], rmajor_repeat[999], cmajor_bytespan[999], kk;
-    LONGLONG headstart, datastart = 0, dataend, rowsremain, *descript, *qdescript = 0;
-    LONGLONG rowstart, cvlalen, cvlastart, vlalen, vlastart;
-    long repeat, width, vla_repeat, vla_address, rowspertile, ntile;
-    int  ncols, hdutype, inttype, anynull, tstatus, zctype[999], addspace = 0, *pdescript = 0;
-    char *cptr, keyname[9], tform[40];
-    long  pcount, zheapptr, naxis1, naxis2, ii, jj;
-    char *ptr, comm[FLEN_COMMENT], zvalue[FLEN_VALUE], *uncompressed_vla = 0, *compressed_vla;
-    char card[FLEN_CARD];
-    size_t dlen, fullsize, cm_size, bytepos, vlamemlen;
-
-    /* ================================================================================== */
-    /* perform initial sanity checks */
-    /* ================================================================================== */
-    if (*status > 0)
-        return(*status);
-     
-    fits_get_hdu_type(infptr, &hdutype, status);
-    if (hdutype != BINARY_TBL) {
-        ffpmsg("This is not a binary table, so cannot uncompress it!");
-        *status = NOT_BTABLE;
-        return(*status);
-    }
-
-    if (fits_read_key(infptr, TLOGICAL, "ZTABLE", &tstatus, NULL, status)) {
-	/* just copy the HDU if the table is not compressed */
-	if (infptr != outfptr) { 
-		fits_copy_hdu (infptr, outfptr, 0, status);
-	}
-	return(*status);
-    }
- 
-    fits_get_num_rowsll(infptr, &nrows, status);
-    fits_get_num_cols(infptr, &ncols, status);
-
-    if ((ncols < 1)) {
-	/* just copy the HDU if the table does not have  more than 0 columns */
-	if (infptr != outfptr) { 
-		fits_copy_hdu (infptr, outfptr, 0, status);
-	}
-	return(*status);
-    }
-
-    fits_read_key(infptr, TLONG, "ZTILELEN", &rowspertile, comm, status);
-    if (*status > 0) {
-        ffpmsg("Could not find the required ZTILELEN keyword");
-        *status = DATA_DECOMPRESSION_ERR;
-        return(*status);
-    }
-
-    /**** get size of the uncompressed table */
-    fits_read_key(infptr, TLONG, "ZNAXIS1", &naxis1, comm, status);
-    if (*status > 0) {
-        ffpmsg("Could not find the required ZNAXIS1 keyword");
-        *status = DATA_DECOMPRESSION_ERR;
-        return(*status);
-    }
-
-    fits_read_key(infptr, TLONG, "ZNAXIS2", &naxis2, comm, status);
-    if (*status > 0) {
-        ffpmsg("Could not find the required ZNAXIS2 keyword");
-        *status = DATA_DECOMPRESSION_ERR;
-        return(*status);
-    }
-
-    /* silently ignore illegal ZTILELEN value if too large */
-    if (rowspertile > naxis2) rowspertile = naxis2;
-
-    fits_read_key(infptr, TLONG, "ZPCOUNT", &pcount, comm, status);
-    if (*status > 0) {
-        ffpmsg("Could not find the required ZPCOUNT keyword");
-        *status = DATA_DECOMPRESSION_ERR;
-        return(*status);
-    }
-
-    tstatus = 0;
-    fits_read_key(infptr, TLONG, "ZHEAPPTR", &zheapptr, comm, &tstatus);
-    if (tstatus > 0) {
-        zheapptr = 0;  /* uncompressed table has no heap */
-    }
-
-    /* ================================================================================== */
-    /* copy of the input header, then recreate the uncompressed table keywords */
-    /* ================================================================================== */
-    fits_copy_header(infptr, outfptr, status);
-
-    /* reset the NAXIS1, NAXIS2. and PCOUNT keywords to the original */
-    fits_read_card(outfptr, "ZNAXIS1", card, status);
-    strncpy(card, "NAXIS1 ", 7);
-    fits_update_card(outfptr, "NAXIS1", card, status);
-    
-    fits_read_card(outfptr, "ZNAXIS2", card, status);
-    strncpy(card, "NAXIS2 ", 7);
-    fits_update_card(outfptr, "NAXIS2", card, status);
-    
-    fits_read_card(outfptr, "ZPCOUNT", card, status);
-    strncpy(card, "PCOUNT ", 7);
-    fits_update_card(outfptr, "PCOUNT", card, status);
-
-    fits_delete_key(outfptr, "ZTABLE", status);
-    fits_delete_key(outfptr, "ZTILELEN", status);
-    fits_delete_key(outfptr, "ZNAXIS1", status);
-    fits_delete_key(outfptr, "ZNAXIS2", status);
-    fits_delete_key(outfptr, "ZPCOUNT", status);
-    tstatus = 0;
-    fits_delete_key(outfptr, "CHECKSUM", &tstatus); 
-    tstatus = 0;
-    fits_delete_key(outfptr, "DATASUM", &tstatus); 
-    /* restore the Checksum keywords, if they exist */
-    tstatus = 0;
-    fits_modify_name(outfptr, "ZHECKSUM", "CHECKSUM", &tstatus);
-    tstatus = 0;
-    fits_modify_name(outfptr, "ZDATASUM", "DATASUM", &tstatus);
-
-    /* ================================================================================== */
-    /* determine compression paramters for each column and write column-specific keywords */
-    /* ================================================================================== */
-    for (ii = 0; ii < ncols; ii++) {
-
-	/* get the original column type, repeat count, and unit width */
-	fits_make_keyn("ZFORM", ii+1, keyname, status);
-	fits_read_key(infptr, TSTRING, keyname, tform, comm, status);
-
-	/* restore the original TFORM value and comment */
-	fits_read_card(outfptr, keyname, card, status);
-	card[0] = 'T';
-	keyname[0] = 'T';
-	fits_update_card(outfptr, keyname, card, status);
-
-	/* now delete the ZFORM keyword */
-        keyname[0] = 'Z';
-	fits_delete_key(outfptr, keyname, status);
-
-	cptr = tform;
-	while(isdigit(*cptr)) cptr++;
-	colcode[ii] = *cptr; /* save the column type code */
-
-        fits_binary_tform(tform, &inttype, &repeat, &width, status);
-        coltype[ii] = inttype;
-
-	/* deal with special cases */
-	if (abs(coltype[ii]) == TBIT) { 
-	        repeat = (repeat + 7) / 8 ;   /* convert from bits to bytes */
-	} else if (abs(coltype[ii]) == TSTRING) {
-	        width = 1;
-	} else if (coltype[ii] < 0) {  /* pointer to variable length array */
-	        if (colcode[ii] == 'P')
-	           width = 8;  /* this is a 'P' column */
-	        else
-	           width = 16;  /* this is a 'Q' not a 'P' column */
-
-                addspace += 16; /* need space for a second set of Q pointers for this column */
-	}
-
-	rmajor_repeat[ii] = repeat;
-
-	/* width (in bytes) of each field in the row-major table */
-	rmajor_colwidth[ii] = rmajor_repeat[ii] * width;
-
-	/* construct the ZCTYPn keyword name then read the keyword */
-	fits_make_keyn("ZCTYP", ii+1, keyname, status);
-	tstatus = 0;
-        fits_read_key(infptr, TSTRING, keyname, zvalue, NULL, &tstatus);
-	if (tstatus) {
-           zctype[ii] = GZIP_2;
-	} else {
-	   if (!strcmp(zvalue, "GZIP_2")) {
-               zctype[ii] = GZIP_2;
-	   } else if (!strcmp(zvalue, "GZIP_1")) {
-               zctype[ii] = GZIP_1;
-	   } else if (!strcmp(zvalue, "RICE_1")) {
-               zctype[ii] = RICE_1;
-	   } else {
-	       ffpmsg("Unrecognized ZCTYPn keyword compression code:");
-	       ffpmsg(zvalue);
-	       *status = DATA_DECOMPRESSION_ERR;
-	       return(*status);
-	   }
-	   
-	   /* delete this keyword from the uncompressed header */
-	   fits_delete_key(outfptr, keyname, status);
-	}
-    }
-
-    /* rescan header keywords to reset internal table structure parameters */
-    fits_set_hdustruc(outfptr, status);
-
-    /* ================================================================================== */
-    /* allocate memory for the transposed and untransposed tile of the table */
-    /* ================================================================================== */
-
-    fullsize = naxis1 * rowspertile;
-    cm_size = fullsize + (addspace * rowspertile);
-
-    cm_buffer = malloc(cm_size);
-    if (!cm_buffer) {
-        ffpmsg("Could not allocate buffer for transformed column-major table");
-        *status = MEMORY_ALLOCATION;
-        return(*status);
-    }
-
-    rm_buffer = malloc(fullsize);
-    if (!rm_buffer) {
-        ffpmsg("Could not allocate buffer for untransformed row-major table");
-        *status = MEMORY_ALLOCATION;
-        free(cm_buffer);
-        return(*status);
-    }
-
-    /* ================================================================================== */
-    /* Main loop over all the tiles */
-    /* ================================================================================== */
-
-    rowsremain = naxis2;
-    rowstart = 1;
-    ntile = 0;
-
-    while(rowsremain) {
-
-        /* ================================================================================== */
-        /* loop over each column: read and uncompress the bytes */
-        /* ================================================================================== */
-        ntile++;
-        rmajor_colstart[0] = 0;
-        cmajor_colstart[0] = 0;
-        for (ii = 0; ii < ncols; ii++) {
-
-	    cmajor_repeat[ii] = rmajor_repeat[ii] * rowspertile;
-
-	    /* starting offset of each field in the column-major table */
-            if (coltype[ii] > 0) {  /* normal fixed length column */
-	          cmajor_colstart[ii + 1] = cmajor_colstart[ii] + rmajor_colwidth[ii] * rowspertile;
-	    } else { /* VLA column: reserve space for the 2nd set of Q pointers */
-	          cmajor_colstart[ii + 1] = cmajor_colstart[ii] + (rmajor_colwidth[ii] + 16) * rowspertile;
-	    }
-	    /* length of each sequence of bytes, after sorting them in signicant order */
-	    cmajor_bytespan[ii] = (rmajor_repeat[ii] * rowspertile);
-
-	    /* starting offset of each field in the  row-major table */
-	    rmajor_colstart[ii + 1] = rmajor_colstart[ii] + rmajor_colwidth[ii];
-
-            if (rmajor_repeat[ii] > 0) { /* ignore columns with 0 elements */
-	
-	        /* read compressed bytes from input table */
-	        fits_read_descript(infptr, ii + 1, ntile, &vla_repeat, &vla_address, status);
-	
-	        /* allocate memory and read in the compressed bytes */
-	        ptr = malloc(vla_repeat);
-	        if (!ptr) {
-                   ffpmsg("Could not allocate buffer for uncompressed bytes");
-                   *status = MEMORY_ALLOCATION;
-                   free(rm_buffer);  free(cm_buffer);
-                   return(*status);
-	        }
-
-	        fits_set_tscale(infptr, ii + 1, 1.0, 0.0, status);  /* turn off any data scaling, first */
-	        fits_read_col_byt(infptr, ii + 1, ntile, 1, vla_repeat, 0, (unsigned char *) ptr, &anynull, status);
-                cptr = cm_buffer + cmajor_colstart[ii];
-	
-		/* size in bytes of the uncompressed column of bytes */
-	        fullsize = (size_t) (cmajor_colstart[ii+1] - cmajor_colstart[ii]);
-
-	        switch (colcode[ii]) {
-
-	        case 'I':
-
-	          if (zctype[ii] == RICE_1) {
-   	             dlen = fits_rdecomp_short((unsigned char *)ptr, vla_repeat, (unsigned short *)cptr, 
-		       fullsize / 2, 32);
-#if BYTESWAPPED
-                     ffswap2((short *) cptr, fullsize / 2); 
-#endif
-	          } else { /* gunzip the data into the correct location */
-	             uncompress2mem_from_mem(ptr, vla_repeat, &cptr, &fullsize, realloc, &dlen, status);        
-	          }
-	          break;
-
-	        case 'J':
-
-	          if (zctype[ii] == RICE_1) {
-   	              dlen = fits_rdecomp ((unsigned char *) ptr, vla_repeat, (unsigned int *)cptr, 
-		        fullsize / 4, 32);
-#if BYTESWAPPED
-                      ffswap4((int *) cptr,  fullsize / 4); 
-#endif
-	          } else { /* gunzip the data into the correct location */
-	             uncompress2mem_from_mem(ptr, vla_repeat, &cptr, &fullsize, realloc, &dlen, status);        
-	          }
-	          break;
-
-	        case 'B':
-
-	          if (zctype[ii] == RICE_1) {
-   	              dlen = fits_rdecomp_byte ((unsigned char *) ptr, vla_repeat, (unsigned char *)cptr, 
-		        fullsize, 32);
-	          } else { /* gunzip the data into the correct location */
-	             uncompress2mem_from_mem(ptr, vla_repeat, &cptr, &fullsize, realloc, &dlen, status);        
-	          }
-	          break;
-
-	        default: 
-		  /* all variable length array columns are included in this case */
-	          /* gunzip the data into the correct location in the full table buffer */
-	          uncompress2mem_from_mem(ptr, vla_repeat,
-	              &cptr,  &fullsize, realloc, &dlen, status);              
-
-	        } /* end of switch block */
-
-	        free(ptr);
-	  }  /* end of rmajor_repeat > 0 */
-      }  /* end of loop over columns */
-      
-      /* now transpose the rows and columns (from cm_buffer to rm_buffer) */
-      /* move each byte, in turn, from the cm_buffer to the appropriate place in the rm_buffer */
-      for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
-	 ptr = (char *) (cm_buffer + cmajor_colstart[ii]);  /* initialize ptr to start of the column in the cm_buffer */
-         if (rmajor_repeat[ii] > 0) {  /* skip columns with zero elements */
-             if (coltype[ii] > 0) {  /* normal fixed length array columns */
-                 if (zctype[ii] == GZIP_2) {  /*  need to unshuffle the bytes */
-
-	             /* recombine the byte planes for the 2-byte, 4-byte, and 8-byte numeric columns */
-	             switch (colcode[ii]) {
-	
-		     case 'I':
-		         /* get the 1st byte of each I*2 value */
-	                 for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		             cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]));  
-		             for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		                 *cptr = *ptr;  /* copy 1 byte */
-		                 ptr++;
-		                 cptr += 2;  
-			     }
-			 }
-		         /* get the 2nd byte of each I*2 value */
-	                 for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		            cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 1);  
-		            for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		                *cptr = *ptr;  /* copy 1 byte */
-		                ptr++;
-		                cptr += 2;  
-		            }
-		         }
-		         break;
-
-		   case 'J':
-		   case 'E':
-		       /* get the 1st byte of each 4-byte value */
-	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]));  
-		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		           *cptr = *ptr;  /* copy 1 byte */
-		           ptr++;
-		           cptr += 4;  
-		         }
-		       }
-		       /* get the 2nd byte  */
-	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 1);  
-		          for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		            *cptr = *ptr;  /* copy 1 byte */
-		            ptr++;
-		            cptr += 4;  
-		          }
-		       }
-		       /* get the 3rd byte  */
-	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 2);  
-		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		           *cptr = *ptr;  /* copy 1 byte */
-		           ptr++;
-		           cptr += 4;  
-		         }
-		       }
-		       /* get the 4th byte  */
-	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 3);  
-		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		           *cptr = *ptr;  /* copy 1 byte */
-		           ptr++;
-		           cptr += 4;  
-		         }
-		       }
-		       break;
-
-		 case 'D':
-		 case 'K':
-		       /* get the 1st byte of each 8-byte value */
- 	              for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]));  
-		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		           *cptr = *ptr;  /* copy 1 byte */
-		           ptr++;
-		           cptr += 8;  
-		         }
-		       }
-		       /* get the 2nd byte  */
-	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 1);  
-		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		           *cptr = *ptr;  /* copy 1 byte */
-		           ptr++;
-		           cptr += 8;  
-		         }
-		       }
-		       /* get the 3rd byte  */
-	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 2);  
-		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		           *cptr = *ptr;  /* copy 1 byte */
-		           ptr++;
-		           cptr += 8;  
-		         }
-		       }
-		       /* get the 4th byte  */
-	  	       for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 3);  
-		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		           *cptr = *ptr;  /* copy 1 byte */
-		           ptr++;
-		           cptr += 8;  
-		         }
-		       }
-		       /* get the 5th byte */
-	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 4);  
-		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		           *cptr = *ptr;  /* copy 1 byte */
-		           ptr++;
-		           cptr += 8;  
-		         }
-		       }
-		       /* get the 6th byte  */
-	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 5);  
-		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		           *cptr = *ptr;  /* copy 1 byte */
-		           ptr++;
-		           cptr += 8;  
-		         }
-		       }
-		       /* get the 7th byte  */
-	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 6);  
-		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		           *cptr = *ptr;  /* copy 1 byte */
-		           ptr++;
-		           cptr += 8;  
-		         }
-		       }
-		       /* get the 8th byte  */
-	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 7);  
-		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
-		           *cptr = *ptr;  /* copy 1 byte */
-		           ptr++;
-		           cptr += 8;  
-		         }
-		       }
-		       break;
-
-		default: /*  should never get here */
-	            ffpmsg("Error: unexpected attempt to use GZIP_2 to compress a column unsuitable data type");
-		    *status = DATA_DECOMPRESSION_ERR;
-                    free(rm_buffer);  free(cm_buffer);
-	            return(*status);
-
-	        }  /* end of switch  for shuffling the bytes*/
-
-            } else {  /* not GZIP_2, don't have to shuffle bytes, so just transpose the rows and columns */
-
-	         for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
-		     cptr = rm_buffer + (rmajor_colstart[ii] + jj * rmajor_colstart[ncols]);   /* addr to copy to */
-		     memcpy(cptr, ptr, (size_t) rmajor_colwidth[ii]);
-	 
-		     ptr += (rmajor_colwidth[ii]);
-		 }
-	    }
-        } else {  /* transpose the variable length array pointers */
-
-              for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output uncompressed table */
-	        cptr = rm_buffer + (rmajor_colstart[ii] + jj * rmajor_colstart[ncols]);   /* addr to copy to */
-	        memcpy(cptr, ptr, (size_t) rmajor_colwidth[ii]);
-	 
-	        ptr += (rmajor_colwidth[ii]);
-	      }
-
-	      if (rmajor_colwidth[ii] == 8 ) {  /* these are P-type descriptors */
-	           pdescript = (int *) (cm_buffer + cmajor_colstart[ii]);
-#if BYTESWAPPED
-	           ffswap4((int *) pdescript,  rowspertile * 2);  /* byte-swap the descriptor */
-#endif
-	      } else if (rmajor_colwidth[ii] == 16 ) {  /* these are Q-type descriptors */
-	           qdescript = (LONGLONG *) (cm_buffer + cmajor_colstart[ii]);
-#if BYTESWAPPED
-	           ffswap8((double *) qdescript,  rowspertile * 2); /* byte-swap the descriptor */
-#endif
-	      } else { /* this should never happen */
-	            ffpmsg("Error: Descriptor column is neither 8 nor 16 bytes wide");
-                    free(rm_buffer);  free(cm_buffer);
-		    *status = DATA_DECOMPRESSION_ERR;
-	            return(*status);
-	      }	
-	      	
-	      /* First, set pointer to the Q descriptors, and byte-swap them, if needed */
-	      descript = (LONGLONG*) (cm_buffer + cmajor_colstart[ii] + (rmajor_colwidth[ii] * rowspertile));
-#if BYTESWAPPED
-	      /* byte-swap the descriptor */
-	      ffswap8((double *) descript,  rowspertile * 2);
-#endif
-
-	      /* now uncompress all the individual VLAs, and */
-	      /* write them to their original location in the uncompressed file */
-
-	      for (jj = 0; jj < rowspertile; jj++)   {    /* loop over rows */
-                    /* get the size and location of the compressed VLA in the compressed table */
-		    cvlalen = descript[jj * 2];
-		    cvlastart = descript[(jj * 2) + 1]; 
-		    if (cvlalen > 0 ) {
-
-			/* get the size and location to write the uncompressed VLA in the uncompressed table */
-			if (rmajor_colwidth[ii] == 8 ) { 
-			    vlalen = pdescript[jj * 2];
-			    vlastart = pdescript[(jj * 2) + 1];
-			} else  {
-			    vlalen = qdescript[jj * 2];
-			    vlastart = qdescript[(jj * 2) + 1];
-			}			
-			vlamemlen = (size_t) (vlalen * (-coltype[ii] / 10));  /* size of the uncompressed VLA, in bytes */
-
-			/* allocate memory for the compressed vla */
-			compressed_vla = malloc( (size_t) cvlalen);
-			if (!compressed_vla) {
-			    ffpmsg("Could not allocate buffer for compressed VLA");
-			    free(rm_buffer);  free(cm_buffer);
-			    *status = MEMORY_ALLOCATION;
-			    return(*status);
-			}
-
-			/* read the compressed VLA from the heap in the input compressed table */
-			bytepos = (size_t) ((infptr->Fptr)->datastart + (infptr->Fptr)->heapstart + cvlastart);
-			ffmbyt(infptr, bytepos, REPORT_EOF, status);
-			ffgbyt(infptr, cvlalen, compressed_vla, status);  /* read the bytes */
-			/* if the VLA couldn't be compressed, just copy it directly to the output uncompressed table */
-			if (cvlalen   == vlamemlen ) {
-			    bytepos = (size_t) ((outfptr->Fptr)->datastart + (outfptr->Fptr)->heapstart + vlastart);
-			    ffmbyt(outfptr, bytepos, IGNORE_EOF, status);
-			    ffpbyt(outfptr, cvlalen, compressed_vla, status);  /* write the bytes */
-			} else {  /* uncompress the VLA  */
-		  
-			    /* allocate memory for the uncompressed VLA */
-			    uncompressed_vla =  malloc(vlamemlen);
-			    if (!uncompressed_vla) {
-				ffpmsg("Could not allocate buffer for uncompressed VLA");
-				*status = MEMORY_ALLOCATION;
-			        free(compressed_vla); free(rm_buffer);  free(cm_buffer);
-				return(*status);
-			    }
-			    /* uncompress the VLA with the appropriate algorithm */
-			    if (zctype[ii] == RICE_1) {
-
-				if (-coltype[ii] == TSHORT) {
-				    dlen = fits_rdecomp_short((unsigned char *) compressed_vla, (int) cvlalen, (unsigned short *)uncompressed_vla, 
-					(int) vlalen, 32);
-#if BYTESWAPPED
-				   ffswap2((short *) uncompressed_vla, (long) vlalen); 
-#endif
-				} else if (-coltype[ii] == TLONG) {
-				    dlen = fits_rdecomp((unsigned char *) compressed_vla, (int) cvlalen, (unsigned int *)uncompressed_vla, 
-					(int) vlalen, 32);
-#if BYTESWAPPED
-				   ffswap4((int *) uncompressed_vla, (long) vlalen); 
-#endif
- 				} else if (-coltype[ii] == TBYTE) {
-				    dlen = fits_rdecomp_byte((unsigned char *) compressed_vla, (int) cvlalen, (unsigned char *) uncompressed_vla, 
-					(int) vlalen, 32);
-				} else {
-				    /* this should not happen */
-				    ffpmsg(" Error: cannot uncompress this column type with the RICE algorthm");
-
-				    *status = DATA_DECOMPRESSION_ERR;
-			            free(uncompressed_vla); free(compressed_vla); free(rm_buffer);  free(cm_buffer);
-				    return(*status);
-				}  
-
-			    } else if (zctype[ii] == GZIP_1 || zctype[ii] == GZIP_2){  
-
-			       /*: gzip uncompress the array of bytes */
-			       uncompress2mem_from_mem( compressed_vla, (size_t) cvlalen, &uncompressed_vla, &vlamemlen, realloc, &vlamemlen, status);
-
-			       if (zctype[ii] == GZIP_2 ) {
-				  /* unshuffle the bytes after ungzipping them */
-				  if ( (int) (-coltype[ii] / 10) == 2) {
-				    fits_unshuffle_2bytes((char *) uncompressed_vla, vlalen, status);
-				  } else if ( (int) (-coltype[ii] / 10) == 4) {
-				    fits_unshuffle_4bytes((char *) uncompressed_vla, vlalen, status);
-				  } else if ( (int) (-coltype[ii] / 10) == 8) {
-				    fits_unshuffle_8bytes((char *) uncompressed_vla, vlalen, status);
-				  }
-			       }
-
-			    } else {
-				/* this should not happen */
-				ffpmsg(" Error: unknown compression algorthm");
-			        free(uncompressed_vla); free(compressed_vla); free(rm_buffer);  free(cm_buffer);
-				*status = DATA_COMPRESSION_ERR;
-				return(*status);
-			    }  		     
-
-			    bytepos = (size_t) ((outfptr->Fptr)->datastart + (outfptr->Fptr)->heapstart + vlastart);
-			    ffmbyt(outfptr, bytepos, IGNORE_EOF, status);
-			    ffpbyt(outfptr, vlamemlen, uncompressed_vla, status);  /* write the bytes */
-			    
-			     free(uncompressed_vla);
-			}  /* end of uncompress VLA */
-
-		        free(compressed_vla);
-
-		  } /* end of vlalen > 0 */
-		} /* end of loop over rowspertile */
-
-              } /* end of variable length array section*/
-           }  /* end of if column repeat > 0 */
-        }  /* end of ncols loop */
-
-        /* copy the buffer of data to the output data unit */
-
-        if (datastart == 0) fits_get_hduaddrll(outfptr, &headstart, &datastart, &dataend, status);        
-
-        ffmbyt(outfptr, datastart, 1, status);
-        ffpbyt(outfptr, naxis1 * rowspertile, rm_buffer, status);
-
-	/* increment pointers for next tile */
-	rowstart += rowspertile;
-        rowsremain -= rowspertile;
-	datastart += (naxis1 * rowspertile);
-	if (rowspertile > rowsremain) rowspertile = (long) rowsremain;
-
-    }  /* end of while rows still remain */
-
-    free(rm_buffer);
-    free(cm_buffer);
-	
-    /* reset internal table structure parameters */
-    fits_set_hdustruc(outfptr, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int fits_shuffle_2bytes(char *heap, LONGLONG length, int *status)
-
-/* shuffle the bytes in an array of 2-byte integers in the heap */
-
-{
-    LONGLONG ii;
-    char *ptr, *cptr, *heapptr;
-    
-    ptr = malloc((size_t) (length * 2));
-    heapptr = heap;
-    cptr = ptr;
-    
-    for (ii = 0; ii < length; ii++) {
-       *cptr = *heapptr;
-       heapptr++;
-       *(cptr + length) = *heapptr;
-       heapptr++;
-       cptr++;
-    }
-         
-    memcpy(heap, ptr, (size_t) (length * 2));
-    free(ptr);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int fits_shuffle_4bytes(char *heap, LONGLONG length, int *status)
-
-/* shuffle the bytes in an array of 4-byte integers or floats  */
-
-{
-    LONGLONG ii;
-    char *ptr, *cptr, *heapptr;
-    
-    ptr = malloc((size_t) (length * 4));
-    if (!ptr) {
-      ffpmsg("malloc failed\n");
-      return(*status);
-    }
-
-    heapptr = heap;
-    cptr = ptr;
- 
-    for (ii = 0; ii < length; ii++) {
-       *cptr = *heapptr;
-       heapptr++;
-       *(cptr + length) = *heapptr;
-       heapptr++;
-       *(cptr + (length * 2)) = *heapptr;
-       heapptr++;
-       *(cptr + (length * 3)) = *heapptr;
-       heapptr++;
-       cptr++;
-    }
-        
-    memcpy(heap, ptr, (size_t) (length * 4));
-    free(ptr);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int fits_shuffle_8bytes(char *heap, LONGLONG length, int *status)
-
-/* shuffle the bytes in an array of 8-byte integers or doubles in the heap */
-
-{
-    LONGLONG ii;
-    char *ptr, *cptr, *heapptr;
-    
-    ptr = calloc(1, (size_t) (length * 8));
-    heapptr = heap;
-    
-/* for some bizarre reason this loop fails to compile under OpenSolaris using
-   the proprietary SunStudioExpress C compiler;  use the following equivalent
-   loop instead.
-   
-    cptr = ptr;
-
-    for (ii = 0; ii < length; ii++) {
-       *cptr = *heapptr;
-       heapptr++;
-       *(cptr + length) = *heapptr;
-       heapptr++;
-       *(cptr + (length * 2)) = *heapptr;
-       heapptr++;
-       *(cptr + (length * 3)) = *heapptr;
-       heapptr++;
-       *(cptr + (length * 4)) = *heapptr;
-       heapptr++;
-       *(cptr + (length * 5)) = *heapptr;
-       heapptr++;
-       *(cptr + (length * 6)) = *heapptr;
-       heapptr++;
-       *(cptr + (length * 7)) = *heapptr;
-       heapptr++;
-       cptr++;
-     }
-*/
-     for (ii = 0; ii < length; ii++) {
-        cptr = ptr + ii;
-
-        *cptr = *heapptr;
-
-        heapptr++;
-        cptr += length;
-        *cptr = *heapptr;
-
-        heapptr++;
-        cptr += length;
-        *cptr = *heapptr;
-
-        heapptr++;
-        cptr += length;
-        *cptr = *heapptr;
-
-        heapptr++;
-        cptr += length;
-        *cptr = *heapptr;
-
-        heapptr++;
-        cptr += length;
-        *cptr = *heapptr;
-
-        heapptr++;
-        cptr += length;
-        *cptr = *heapptr;
-
-        heapptr++;
-        cptr += length;
-        *cptr = *heapptr;
-
-        heapptr++;
-     }
-        
-    memcpy(heap, ptr, (size_t) (length * 8));
-    free(ptr);
- 
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int fits_unshuffle_2bytes(char *heap, LONGLONG length, int *status)
-
-/* unshuffle the bytes in an array of 2-byte integers */
-
-{
-    LONGLONG ii;
-    char *ptr, *cptr, *heapptr;
-    
-    ptr = malloc((size_t) (length * 2));
-    heapptr = heap + (2 * length) - 1;
-    cptr = ptr + (2 * length) - 1;
-    
-    for (ii = 0; ii < length; ii++) {
-       *cptr = *heapptr;
-       cptr--;
-       *cptr = *(heapptr - length);
-       cptr--;
-       heapptr--;
-    }
-         
-    memcpy(heap, ptr, (size_t) (length * 2));
-    free(ptr);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int fits_unshuffle_4bytes(char *heap, LONGLONG length, int *status)
-
-/* unshuffle the bytes in an array of 4-byte integers or floats */
-
-{
-    LONGLONG ii;
-    char *ptr, *cptr, *heapptr;
-    
-    ptr = malloc((size_t) (length * 4));
-    heapptr = heap + (4 * length) -1;
-    cptr = ptr + (4 * length) -1;
- 
-    for (ii = 0; ii < length; ii++) {
-       *cptr = *heapptr;
-       cptr--;
-       *cptr = *(heapptr - length);
-       cptr--;
-       *cptr = *(heapptr - (2 * length));
-       cptr--;
-       *cptr = *(heapptr - (3 * length));
-       cptr--;
-       heapptr--;
-    }
-        
-    memcpy(heap, ptr, (size_t) (length * 4));
-    free(ptr);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int fits_unshuffle_8bytes(char *heap, LONGLONG length, int *status)
-
-/* unshuffle the bytes in an array of 8-byte integers or doubles */
-
-{
-    LONGLONG ii;
-    char *ptr, *cptr, *heapptr;
-    
-    ptr = malloc((size_t) (length * 8));
-    heapptr = heap + (8 * length) - 1;
-    cptr = ptr + (8 * length)  -1;
-    
-    for (ii = 0; ii < length; ii++) {
-       *cptr = *heapptr;
-       cptr--;
-       *cptr = *(heapptr - length);
-       cptr--;
-       *cptr = *(heapptr - (2 * length));
-       cptr--;
-       *cptr = *(heapptr - (3 * length));
-       cptr--;
-       *cptr = *(heapptr - (4 * length));
-       cptr--;
-       *cptr = *(heapptr - (5 * length));
-       cptr--;
-       *cptr = *(heapptr - (6 * length));
-       cptr--;
-       *cptr = *(heapptr - (7 * length));
-       cptr--;
-       heapptr--;
-    }
-       
-    memcpy(heap, ptr, (size_t) (length * 8));
-    free(ptr);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int fits_int_to_longlong_inplace(int *intarray, long length, int *status)
-
-/* convert the input array of 32-bit integers into an array of 64-bit integers,
-in place. This will overwrite the input array with the new longer array starting
-at the same memory location.  
-
-Note that aliasing the same memory location with pointers of different datatypes is
-not allowed in strict ANSI C99, however it is  used here for efficency. In principle,
-one could simply copy the input array in reverse order to the output array,
-but this only works if the compiler performs the operation in strict order.  Certain
-compiler optimization techniques may vioate this assumption.  Therefore, we first
-copy a section of the input array to a temporary intermediate array, before copying
-the longer datatype values back to the original array.
-*/
-
-{
-    LONGLONG *longlongarray, *aliasarray;
-    long ii, ntodo, firstelem, nmax = 10000;
-    
-    if (*status > 0) 
-        return(*status);
-
-    ntodo = nmax;
-    if (length < nmax) ntodo = length;
-    
-    firstelem = length - ntodo;  /* first element to be converted */
-    
-    longlongarray = (LONGLONG *) malloc(ntodo * sizeof(LONGLONG));
-    
-    if (longlongarray == NULL)
-    {
-	ffpmsg("Out of memory. (fits_int_to_longlong_inplace)");
-	return (*status = MEMORY_ALLOCATION);
-    }
-
-    aliasarray = (LONGLONG *) intarray; /* alias pointer to the input array */
-
-    while (ntodo > 0) {
-    
-	/* do datatype conversion into temp array */
-        for (ii = 0; ii < ntodo; ii++) { 
-	    longlongarray[ii] = intarray[ii + firstelem];
-        }
-
-        /* copy temp array back to alias */
-        memcpy(&(aliasarray[firstelem]), longlongarray, ntodo * 8);
-	
-        if (firstelem == 0) {  /* we are all done */
-	    ntodo = 0;   
-	} else {  /* recalculate ntodo and firstelem for next loop */
-	    if (firstelem > nmax) {
-	        firstelem -= nmax;
-	    } else {
-	        ntodo = firstelem;
-	        firstelem = 0;
-	    }
-	}
-    }
-
-    free(longlongarray);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int fits_short_to_int_inplace(short *shortarray, long length, int *status)
-
-/* convert the input array of 16-bit integers into an array of 32-bit integers,
-in place. This will overwrite the input array with the new longer array starting
-at the same memory location.  
-
-Note that aliasing the same memory location with pointers of different datatypes is
-not allowed in strict ANSI C99, however it is  used here for efficency. In principle,
-one could simply copy the input array in reverse order to the output array,
-but this only works if the compiler performs the operation in strict order.  Certain
-compiler optimization techniques may vioate this assumption.  Therefore, we first
-copy a section of the input array to a temporary intermediate array, before copying
-the longer datatype values back to the original array.
-*/
-
-{
-    int *intarray, *aliasarray;
-    long ii, ntodo, firstelem, nmax = 10000;
-    
-    if (*status > 0) 
-        return(*status);
-
-    ntodo = nmax;
-    if (length < nmax) ntodo = length;
-    
-    firstelem = length - ntodo;  /* first element to be converted */
-    
-    intarray = (int *) malloc(ntodo * sizeof(int));
-    
-    if (intarray == NULL)
-    {
-	ffpmsg("Out of memory. (fits_short_to_int_inplace)");
-	return (*status = MEMORY_ALLOCATION);
-    }
-
-    aliasarray = (int *) shortarray; /* alias pointer to the input array */
-
-    while (ntodo > 0) {
-    
-	/* do datatype conversion into temp array */
-        for (ii = 0; ii < ntodo; ii++) { 
-	    intarray[ii] = shortarray[ii + firstelem];
-        }
-
-        /* copy temp array back to alias */
-        memcpy(&(aliasarray[firstelem]), intarray, ntodo * 4);
-	
-        if (firstelem == 0) {  /* we are all done */
-	    ntodo = 0;   
-	} else {  /* recalculate ntodo and firstelem for next loop */
-	    if (firstelem > nmax) {
-	        firstelem -= nmax;
-	    } else {
-	        ntodo = firstelem;
-	        firstelem = 0;
-	    }
-	}
-    }
-
-    free(intarray);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int fits_ushort_to_int_inplace(unsigned short *ushortarray, long length, 
-                                      int *status)
-
-/* convert the input array of 16-bit unsigned integers into an array of 32-bit integers,
-in place. This will overwrite the input array with the new longer array starting
-at the same memory location.  
-
-Note that aliasing the same memory location with pointers of different datatypes is
-not allowed in strict ANSI C99, however it is  used here for efficency. In principle,
-one could simply copy the input array in reverse order to the output array,
-but this only works if the compiler performs the operation in strict order.  Certain
-compiler optimization techniques may vioate this assumption.  Therefore, we first
-copy a section of the input array to a temporary intermediate array, before copying
-the longer datatype values back to the original array.
-*/
-
-{
-    int *intarray, *aliasarray;
-    long ii, ntodo, firstelem, nmax = 10000;
-    
-    if (*status > 0) 
-        return(*status);
-
-    ntodo = nmax;
-    if (length < nmax) ntodo = length;
-    
-    firstelem = length - ntodo;  /* first element to be converted */
-    
-    intarray = (int *) malloc(ntodo * sizeof(int));
-    
-    if (intarray == NULL)
-    {
-	ffpmsg("Out of memory. (fits_ushort_to_int_inplace)");
-	return (*status = MEMORY_ALLOCATION);
-    }
-
-    aliasarray = (int *) ushortarray; /* alias pointer to the input array */
-
-    while (ntodo > 0) {
-    
-	/* do datatype conversion into temp array */
-        for (ii = 0; ii < ntodo; ii++) { 
-	    intarray[ii] = ushortarray[ii + firstelem];
-        }
-
-        /* copy temp array back to alias */
-        memcpy(&(aliasarray[firstelem]), intarray, ntodo * 4);
-	
-        if (firstelem == 0) {  /* we are all done */
-	    ntodo = 0;   
-	} else {  /* recalculate ntodo and firstelem for next loop */
-	    if (firstelem > nmax) {
-	        firstelem -= nmax;
-	    } else {
-	        ntodo = firstelem;
-	        firstelem = 0;
-	    }
-	}
-    }
-
-    free(intarray);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int fits_ubyte_to_int_inplace(unsigned char *ubytearray, long length, 
-                                      int *status)
-
-/* convert the input array of 8-bit unsigned integers into an array of 32-bit integers,
-in place. This will overwrite the input array with the new longer array starting
-at the same memory location.  
-
-Note that aliasing the same memory location with pointers of different datatypes is
-not allowed in strict ANSI C99, however it is  used here for efficency. In principle,
-one could simply copy the input array in reverse order to the output array,
-but this only works if the compiler performs the operation in strict order.  Certain
-compiler optimization techniques may vioate this assumption.  Therefore, we first
-copy a section of the input array to a temporary intermediate array, before copying
-the longer datatype values back to the original array.
-*/
-
-{
-    int *intarray, *aliasarray;
-    long ii, ntodo, firstelem, nmax = 10000;
-    
-    if (*status > 0) 
-        return(*status);
-
-    ntodo = nmax;
-    if (length < nmax) ntodo = length;
-    
-    firstelem = length - ntodo;  /* first element to be converted */
-    
-    intarray = (int *) malloc(ntodo * sizeof(int));
-    
-    if (intarray == NULL)
-    {
-	ffpmsg("Out of memory. (fits_ubyte_to_int_inplace)");
-	return (*status = MEMORY_ALLOCATION);
-    }
-
-    aliasarray = (int *) ubytearray; /* alias pointer to the input array */
-
-    while (ntodo > 0) {
-    
-	/* do datatype conversion into temp array */
-        for (ii = 0; ii < ntodo; ii++) { 
-	    intarray[ii] = ubytearray[ii + firstelem];
-        }
-
-        /* copy temp array back to alias */
-        memcpy(&(aliasarray[firstelem]), intarray, ntodo * 4);
-	
-        if (firstelem == 0) {  /* we are all done */
-	    ntodo = 0;   
-	} else {  /* recalculate ntodo and firstelem for next loop */
-	    if (firstelem > nmax) {
-	        firstelem -= nmax;
-	    } else {
-	        ntodo = firstelem;
-	        firstelem = 0;
-	    }
-	}
-    }
-
-    free(intarray);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int fits_sbyte_to_int_inplace(signed char *sbytearray, long length, 
-                                      int *status)
-
-/* convert the input array of 8-bit signed integers into an array of 32-bit integers,
-in place. This will overwrite the input array with the new longer array starting
-at the same memory location.  
-
-Note that aliasing the same memory location with pointers of different datatypes is
-not allowed in strict ANSI C99, however it is  used here for efficency. In principle,
-one could simply copy the input array in reverse order to the output array,
-but this only works if the compiler performs the operation in strict order.  Certain
-compiler optimization techniques may vioate this assumption.  Therefore, we first
-copy a section of the input array to a temporary intermediate array, before copying
-the longer datatype values back to the original array.
-*/
-
-/*
-!!!!!!!!!!!!!!!!!
-NOTE THAT THIS IS A SPECIALIZED ROUTINE THAT ADDS AN OFFSET OF 128 TO THE ARRAY VALUES
-!!!!!!!!!!!!!!!!!
-*/
-
-{
-    int *intarray, *aliasarray;
-    long ii, ntodo, firstelem, nmax = 10000;
-    
-    if (*status > 0) 
-        return(*status);
-
-    ntodo = nmax;
-    if (length < nmax) ntodo = length;
-    
-    firstelem = length - ntodo;  /* first element to be converted */
-    
-    intarray = (int *) malloc(ntodo * sizeof(int));
-    
-    if (intarray == NULL)
-    {
-	ffpmsg("Out of memory. (fits_sbyte_to_int_inplace)");
-	return (*status = MEMORY_ALLOCATION);
-    }
-
-    aliasarray = (int *) sbytearray; /* alias pointer to the input array */
-
-    while (ntodo > 0) {
-    
-	/* do datatype conversion into temp array */
-        for (ii = 0; ii < ntodo; ii++) { 
-	    intarray[ii] = sbytearray[ii + firstelem] + 128;  /* !! Note the offset !! */
-        }
-
-        /* copy temp array back to alias */
-        memcpy(&(aliasarray[firstelem]), intarray, ntodo * 4);
-	
-        if (firstelem == 0) {  /* we are all done */
-	    ntodo = 0;   
-	} else {  /* recalculate ntodo and firstelem for next loop */
-	    if (firstelem > nmax) {
-	        firstelem -= nmax;
-	    } else {
-	        ntodo = firstelem;
-	        firstelem = 0;
-	    }
-	}
-    }
-
-    free(intarray);
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/imcopy.c b/src/external/OpenGR/3rdparty/cfitsio/imcopy.c
deleted file mode 100644
index 253205d97..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/imcopy.c
+++ /dev/null
@@ -1,233 +0,0 @@
-#include 
-#include 
-#include 
-#include "fitsio.h"
-
-int main(int argc, char *argv[])
-{
-    fitsfile *infptr, *outfptr;   /* FITS file pointers defined in fitsio.h */
-    int status = 0, tstatus, ii = 1, iteration = 0, single = 0, hdupos;
-    int hdutype, bitpix, bytepix, naxis = 0, nkeys, datatype = 0, anynul;
-    long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
-    long first, totpix = 0, npix;
-    double *array, bscale = 1.0, bzero = 0.0, nulval = 0.;
-    char card[81];
-
-    if (argc != 3)
-    {
- printf("\n");
- printf("Usage:  imcopy inputImage outputImage[compress]\n");
- printf("\n");
- printf("Copy an input image to an output image, optionally compressing\n");
- printf("or uncompressing the image in the process.  If the [compress]\n");
- printf("qualifier is appended to the output file name then the input image\n");
- printf("will be compressed using the tile-compressed format.  In this format,\n");
- printf("the image is divided into rectangular tiles and each tile of pixels\n");
- printf("is compressed and stored in a variable-length row of a binary table.\n");
- printf("If the [compress] qualifier is omitted, and the input image is\n");
- printf("in tile-compressed format, then the output image will be uncompressed.\n");
- printf("\n");
- printf("If an extension name or number is appended to the input file name, \n");
- printf("enclosed in square brackets, then only that single extension will be\n");
- printf("copied to the output file.  Otherwise, every extension in the input file\n");
- printf("will be processed in turn and copied to the output file.\n");
- printf("\n");
- printf("Examples:\n");
- printf("\n");
- printf("1)  imcopy image.fit 'cimage.fit[compress]'\n");
- printf("\n");
- printf("    This compresses the input image using the default parameters, i.e.,\n");
- printf("    using the Rice compression algorithm and using row by row tiles.\n");
- printf("\n");
- printf("2)  imcopy cimage.fit image2.fit\n");
- printf("\n");
- printf("    This uncompresses the image created in the first example.\n");
- printf("    image2.fit should be identical to image.fit if the image\n");
- printf("    has an integer datatype.  There will be small differences\n");
- printf("    in the pixel values if it is a floating point image.\n");
- printf("\n");
- printf("3)  imcopy image.fit 'cimage.fit[compress GZIP 100,100;q 16]'\n");
- printf("\n");
- printf("    This compresses the input image using the following parameters:\n");
- printf("         GZIP compression algorithm;\n");
- printf("         100 X 100 pixel compression tiles;\n");
- printf("         quantization level = 16 (only used with floating point images)\n");
- printf("\n");
- printf("The full syntax of the compression qualifier is:\n");
- printf("    [compress ALGORITHM TDIM1,TDIM2,...; q QLEVEL s SCALE]\n");
- printf("where the allowed ALGORITHM values are:\n");
- printf("      Rice, HCOMPRESS, HSCOMPRESS, GZIP, or PLIO. \n");
- printf("       (HSCOMPRESS is a variant of HCOMPRESS in which a small\n");
- printf("        amount of smoothing is applied to the uncompressed image\n");
- printf("        to help suppress blocky compression artifacts in the image\n");
- printf("        when using large values for the 'scale' parameter).\n");
- printf("TDIMn is the size of the compression tile in each dimension,\n");
- printf("\n");
- printf("QLEVEL specifies the quantization level when converting a floating\n");
- printf("point image into integers, prior to compressing the image.  The\n");
- printf("default value = 16, which means the image will be quantized into\n");
- printf("integer levels that are spaced at intervals of sigma/16., where \n");
- printf("sigma is the estimated noise level in background areas of the image.\n");
- printf("If QLEVEL is negative, this means use the absolute value for the\n");
- printf("quantization spacing (e.g. 'q -0.005' means quantize the floating\n");
- printf("point image such that the scaled integers represent steps of 0.005\n");
- printf("in the original image).\n");
- printf("\n");
- printf("SCALE is the integer scale factor that only applies to the HCOMPRESS\n");
- printf("algorithm.  The default value SCALE = 0 forces the image to be\n");
- printf("losslessly compressed; Greater amounts of lossy compression (resulting\n");
- printf("in smaller compressed files) can be specified with larger SCALE values.\n");
- printf("\n");
- printf("\n");
- printf("Note that it may be necessary to enclose the file names\n");
- printf("in single quote characters on the Unix command line.\n");
-      return(0);
-    }
-
-    /* Open the input file and create output file */
-    fits_open_file(&infptr, argv[1], READONLY, &status);
-    fits_create_file(&outfptr, argv[2], &status);
-
-    if (status != 0) {    
-        fits_report_error(stderr, status);
-        return(status);
-    }
-
-    fits_get_hdu_num(infptr, &hdupos);  /* Get the current HDU position */
-
-    /* Copy only a single HDU if a specific extension was given */ 
-    if (hdupos != 1 || strchr(argv[1], '[')) single = 1;
-
-    for (; !status; hdupos++)  /* Main loop through each extension */
-    {
-
-      fits_get_hdu_type(infptr, &hdutype, &status);
-
-      if (hdutype == IMAGE_HDU) {
-
-          /* get image dimensions and total number of pixels in image */
-          for (ii = 0; ii < 9; ii++)
-              naxes[ii] = 1;
-
-          fits_get_img_param(infptr, 9, &bitpix, &naxis, naxes, &status);
-
-          totpix = naxes[0] * naxes[1] * naxes[2] * naxes[3] * naxes[4]
-             * naxes[5] * naxes[6] * naxes[7] * naxes[8];
-      }
-
-      if (hdutype != IMAGE_HDU || naxis == 0 || totpix == 0) { 
-
-          /* just copy tables and null images */
-          fits_copy_hdu(infptr, outfptr, 0, &status);
-
-      } else {
-
-          /* Explicitly create new image, to support compression */
-          fits_create_img(outfptr, bitpix, naxis, naxes, &status);
-          if (status) {
-                 fits_report_error(stderr, status);
-                 return(status);
-          }
-
-          if (fits_is_compressed_image(outfptr, &status)) {
-              /* write default EXTNAME keyword if it doesn't already exist */
-	      tstatus = 0;
-              fits_read_card(infptr, "EXTNAME", card, &tstatus);
-	      if (tstatus) {
-	         strcpy(card, "EXTNAME = 'COMPRESSED_IMAGE'   / name of this binary table extension");
-	         fits_write_record(outfptr, card, &status);
-	      }
-          }
-	  	    
-          /* copy all the user keywords (not the structural keywords) */
-          fits_get_hdrspace(infptr, &nkeys, NULL, &status); 
-
-          for (ii = 1; ii <= nkeys; ii++) {
-              fits_read_record(infptr, ii, card, &status);
-              if (fits_get_keyclass(card) > TYP_CMPRS_KEY)
-                  fits_write_record(outfptr, card, &status);
-          }
-
-              /* delete default EXTNAME keyword if it exists */
-/*
-          if (!fits_is_compressed_image(outfptr, &status)) {
-	      tstatus = 0;
-              fits_read_key(outfptr, TSTRING, "EXTNAME", card, NULL, &tstatus);
-	      if (!tstatus) {
-	         if (strcmp(card, "COMPRESSED_IMAGE") == 0)
-	            fits_delete_key(outfptr, "EXTNAME", &status);
-	      }
-          }
-*/
-	  
-          switch(bitpix) {
-              case BYTE_IMG:
-                  datatype = TBYTE;
-                  break;
-              case SHORT_IMG:
-                  datatype = TSHORT;
-                  break;
-              case LONG_IMG:
-                  datatype = TINT;
-                  break;
-              case FLOAT_IMG:
-                  datatype = TFLOAT;
-                  break;
-              case DOUBLE_IMG:
-                  datatype = TDOUBLE;
-                  break;
-          }
-
-          bytepix = abs(bitpix) / 8;
-
-          npix = totpix;
-          iteration = 0;
-
-          /* try to allocate memory for the entire image */
-          /* use double type to force memory alignment */
-          array = (double *) calloc(npix, bytepix);
-
-          /* if allocation failed, divide size by 2 and try again */
-          while (!array && iteration < 10)  {
-              iteration++;
-              npix = npix / 2;
-              array = (double *) calloc(npix, bytepix);
-          }
-
-          if (!array)  {
-              printf("Memory allocation error\n");
-              return(0);
-          }
-
-          /* turn off any scaling so that we copy the raw pixel values */
-          fits_set_bscale(infptr,  bscale, bzero, &status);
-          fits_set_bscale(outfptr, bscale, bzero, &status);
-
-          first = 1;
-          while (totpix > 0 && !status)
-          {
-             /* read all or part of image then write it back to the output file */
-             fits_read_img(infptr, datatype, first, npix, 
-                     &nulval, array, &anynul, &status);
-
-             fits_write_img(outfptr, datatype, first, npix, array, &status);
-             totpix = totpix - npix;
-             first  = first  + npix;
-          }
-          free(array);
-      }
-
-      if (single) break;  /* quit if only copying a single HDU */
-      fits_movrel_hdu(infptr, 1, NULL, &status);  /* try to move to next HDU */
-    }
-
-    if (status == END_OF_FILE)  status = 0; /* Reset after normal error */
-
-    fits_close_file(outfptr,  &status);
-    fits_close_file(infptr, &status);
-
-    /* if error occurred, print out error message */
-    if (status)
-       fits_report_error(stderr, status);
-    return(status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/install-sh b/src/external/OpenGR/3rdparty/cfitsio/install-sh
deleted file mode 100644
index ebc66913e..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/install-sh
+++ /dev/null
@@ -1,250 +0,0 @@
-#! /bin/sh
-#
-# install - install a program, script, or datafile
-# This comes from X11R5 (mit/util/scripts/install.sh).
-#
-# Copyright 1991 by the Massachusetts Institute of Technology
-#
-# Permission to use, copy, modify, distribute, and sell this software and its
-# documentation for any purpose is hereby granted without fee, provided that
-# the above copyright notice appear in all copies and that both that
-# copyright notice and this permission notice appear in supporting
-# documentation, and that the name of M.I.T. not be used in advertising or
-# publicity pertaining to distribution of the software without specific,
-# written prior permission.  M.I.T. makes no representations about the
-# suitability of this software for any purpose.  It is provided "as is"
-# without express or implied warranty.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch.  It can only install one file at a time, a restriction
-# shared with many OS's install programs.
-
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
-
-transformbasename=""
-transform_arg=""
-instcmd="$mvprog"
-chmodcmd="$chmodprog 0755"
-chowncmd=""
-chgrpcmd=""
-stripcmd=""
-rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=""
-dst=""
-dir_arg=""
-
-while [ x"$1" != x ]; do
-    case $1 in
-	-c) instcmd="$cpprog"
-	    shift
-	    continue;;
-
-	-d) dir_arg=true
-	    shift
-	    continue;;
-
-	-m) chmodcmd="$chmodprog $2"
-	    shift
-	    shift
-	    continue;;
-
-	-o) chowncmd="$chownprog $2"
-	    shift
-	    shift
-	    continue;;
-
-	-g) chgrpcmd="$chgrpprog $2"
-	    shift
-	    shift
-	    continue;;
-
-	-s) stripcmd="$stripprog"
-	    shift
-	    continue;;
-
-	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
-	    shift
-	    continue;;
-
-	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
-	    shift
-	    continue;;
-
-	*)  if [ x"$src" = x ]
-	    then
-		src=$1
-	    else
-		# this colon is to work around a 386BSD /bin/sh bug
-		:
-		dst=$1
-	    fi
-	    shift
-	    continue;;
-    esac
-done
-
-if [ x"$src" = x ]
-then
-	echo "install:	no input file specified"
-	exit 1
-else
-	true
-fi
-
-if [ x"$dir_arg" != x ]; then
-	dst=$src
-	src=""
-	
-	if [ -d $dst ]; then
-		instcmd=:
-	else
-		instcmd=mkdir
-	fi
-else
-
-# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad 
-# if $src (and thus $dsttmp) contains '*'.
-
-	if [ -f $src -o -d $src ]
-	then
-		true
-	else
-		echo "install:  $src does not exist"
-		exit 1
-	fi
-	
-	if [ x"$dst" = x ]
-	then
-		echo "install:	no destination specified"
-		exit 1
-	else
-		true
-	fi
-
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
-
-	if [ -d $dst ]
-	then
-		dst="$dst"/`basename $src`
-	else
-		true
-	fi
-fi
-
-## this sed command emulates the dirname command
-dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
-
-# Make sure that the destination directory exists.
-#  this part is taken from Noah Friedman's mkinstalldirs script
-
-# Skip lots of stat calls in the usual case.
-if [ ! -d "$dstdir" ]; then
-defaultIFS='	
-'
-IFS="${IFS-${defaultIFS}}"
-
-oIFS="${IFS}"
-# Some sh's can't handle IFS=/ for some reason.
-IFS='%'
-set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
-IFS="${oIFS}"
-
-pathcomp=''
-
-while [ $# -ne 0 ] ; do
-	pathcomp="${pathcomp}${1}"
-	shift
-
-	if [ ! -d "${pathcomp}" ] ;
-        then
-		$mkdirprog "${pathcomp}"
-	else
-		true
-	fi
-
-	pathcomp="${pathcomp}/"
-done
-fi
-
-if [ x"$dir_arg" != x ]
-then
-	$doit $instcmd $dst &&
-
-	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
-	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
-	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
-	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
-else
-
-# If we're going to rename the final executable, determine the name now.
-
-	if [ x"$transformarg" = x ] 
-	then
-		dstfile=`basename $dst`
-	else
-		dstfile=`basename $dst $transformbasename | 
-			sed $transformarg`$transformbasename
-	fi
-
-# don't allow the sed command to completely eliminate the filename
-
-	if [ x"$dstfile" = x ] 
-	then
-		dstfile=`basename $dst`
-	else
-		true
-	fi
-
-# Make a temp file name in the proper directory.
-
-	dsttmp=$dstdir/#inst.$$#
-
-# Move or copy the file name to the temp name
-
-	$doit $instcmd $src $dsttmp &&
-
-	trap "rm -f ${dsttmp}" 0 &&
-
-# and set any options; do chmod last to preserve setuid bits
-
-# If any of these fail, we abort the whole thing.  If we want to
-# ignore errors from any of these, just make sure not to ignore
-# errors from the above "$doit $instcmd $src $dsttmp" command.
-
-	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
-	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
-	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
-	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
-
-# Now rename the file to the real destination.
-
-	$doit $rmcmd -f $dstdir/$dstfile &&
-	$doit $mvcmd $dsttmp $dstdir/$dstfile 
-
-fi &&
-
-
-exit 0
diff --git a/src/external/OpenGR/3rdparty/cfitsio/iraffits.c b/src/external/OpenGR/3rdparty/cfitsio/iraffits.c
deleted file mode 100644
index ebced9b0c..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/iraffits.c
+++ /dev/null
@@ -1,2095 +0,0 @@
-/*------------------------------------------------------------------------*/
-/*                                                                        */
-/*  These routines have been modified by William Pence for use by CFITSIO */
-/*        The original files were provided by Doug Mink                   */
-/*------------------------------------------------------------------------*/
-
-/* File imhfile.c
- * August 6, 1998
- * By Doug Mink, based on Mike VanHilst's readiraf.c
-
- * Module:      imhfile.c (IRAF .imh image file reading and writing)
- * Purpose:     Read and write IRAF image files (and translate headers)
- * Subroutine:  irafrhead (filename, lfhead, fitsheader, lihead)
- *              Read IRAF image header
- * Subroutine:  irafrimage (fitsheader)
- *              Read IRAF image pixels (call after irafrhead)
- * Subroutine:	same_path (pixname, hdrname)
- *		Put filename and header path together
- * Subroutine:	iraf2fits (hdrname, irafheader, nbiraf, nbfits)
- *		Convert IRAF image header to FITS image header
- * Subroutine:  irafgeti4 (irafheader, offset)
- *		Get 4-byte integer from arbitrary part of IRAF header
- * Subroutine:  irafgetc2 (irafheader, offset)
- *		Get character string from arbitrary part of IRAF v.1 header
- * Subroutine:  irafgetc (irafheader, offset)
- *		Get character string from arbitrary part of IRAF header
- * Subroutine:  iraf2str (irafstring, nchar)
- * 		Convert 2-byte/char IRAF string to 1-byte/char string
- * Subroutine:	irafswap (bitpix,string,nbytes)
- *		Swap bytes in string in place, with FITS bits/pixel code
- * Subroutine:	irafswap2 (string,nbytes)
- *		Swap bytes in string in place
- * Subroutine	irafswap4 (string,nbytes)
- *		Reverse bytes of Integer*4 or Real*4 vector in place
- * Subroutine	irafswap8 (string,nbytes)
- *		Reverse bytes of Real*8 vector in place
-
-
- * Copyright:   2000 Smithsonian Astrophysical Observatory
- *              You may do anything you like with this file except remove
- *              this copyright.  The Smithsonian Astrophysical Observatory
- *              makes no representations about the suitability of this
- *              software for any purpose.  It is provided "as is" without
- *              express or implied warranty.
- */
-
-#include "fitsio2.h"
-#include 		/* define stderr, FD, and NULL */
-#include 
-#include   /* stddef.h is apparently needed to define size_t */
-#include 
-
-#define FILE_NOT_OPENED 104
-
-/* Parameters from iraf/lib/imhdr.h for IRAF version 1 images */
-#define SZ_IMPIXFILE	 79		/* name of pixel storage file */
-#define SZ_IMHDRFILE	 79   		/* length of header storage file */
-#define SZ_IMTITLE	 79		/* image title string */
-#define LEN_IMHDR	2052		/* length of std header */
-
-/* Parameters from iraf/lib/imhdr.h for IRAF version 2 images */
-#define	SZ_IM2PIXFILE	255		/* name of pixel storage file */
-#define	SZ_IM2HDRFILE	255		/* name of header storage file */
-#define	SZ_IM2TITLE	383		/* image title string */
-#define LEN_IM2HDR	2046		/* length of std header */
-
-/* Offsets into header in bytes for parameters in IRAF version 1 images */
-#define IM_HDRLEN	 12		/* Length of header in 4-byte ints */
-#define IM_PIXTYPE       16             /* Datatype of the pixels */
-#define IM_NDIM          20             /* Number of dimensions */
-#define IM_LEN           24             /* Length (as stored) */
-#define IM_PHYSLEN       52             /* Physical length (as stored) */
-#define IM_PIXOFF        88             /* Offset of the pixels */
-#define IM_CTIME        108             /* Time of image creation */
-#define IM_MTIME        112             /* Time of last modification */
-#define IM_LIMTIME      116             /* Time of min,max computation */
-#define IM_MAX          120             /* Maximum pixel value */
-#define IM_MIN          124             /* Maximum pixel value */
-#define IM_PIXFILE      412             /* Name of pixel storage file */
-#define IM_HDRFILE      572             /* Name of header storage file */
-#define IM_TITLE        732             /* Image name string */
-
-/* Offsets into header in bytes for parameters in IRAF version 2 images */
-#define IM2_HDRLEN	  6		/* Length of header in 4-byte ints */
-#define IM2_PIXTYPE      10             /* Datatype of the pixels */
-#define IM2_SWAPPED      14             /* Pixels are byte swapped */
-#define IM2_NDIM         18             /* Number of dimensions */
-#define IM2_LEN          22             /* Length (as stored) */
-#define IM2_PHYSLEN      50             /* Physical length (as stored) */
-#define IM2_PIXOFF       86             /* Offset of the pixels */
-#define IM2_CTIME       106             /* Time of image creation */
-#define IM2_MTIME       110             /* Time of last modification */
-#define IM2_LIMTIME     114             /* Time of min,max computation */
-#define IM2_MAX         118             /* Maximum pixel value */
-#define IM2_MIN         122             /* Maximum pixel value */
-#define IM2_PIXFILE     126             /* Name of pixel storage file */
-#define IM2_HDRFILE     382             /* Name of header storage file */
-#define IM2_TITLE       638             /* Image name string */
-
-/* Codes from iraf/unix/hlib/iraf.h */
-#define	TY_CHAR		2
-#define	TY_SHORT	3
-#define	TY_INT		4
-#define	TY_LONG		5
-#define	TY_REAL		6
-#define	TY_DOUBLE	7
-#define	TY_COMPLEX	8
-#define TY_POINTER      9
-#define TY_STRUCT       10
-#define TY_USHORT       11
-#define TY_UBYTE        12
-
-#define LEN_PIXHDR	1024
-#define MAXINT  2147483647 /* Biggest number that can fit in long */
-
-static int isirafswapped(char *irafheader, int offset);
-static int irafgeti4(char *irafheader, int offset);
-static char *irafgetc2(char *irafheader, int offset, int nc);
-static char *irafgetc(char *irafheader,	int offset, int	nc);
-static char *iraf2str(char *irafstring, int nchar);
-static char *irafrdhead(const char *filename, int *lihead);
-static int irafrdimage (char **buffptr, size_t *buffsize,
-    size_t *filesize, int *status);
-static int iraftofits (char *hdrname, char *irafheader, int nbiraf,
-    char **buffptr, size_t *nbfits, size_t *fitssize, int *status);
-static char *same_path(char *pixname, const char *hdrname);
-
-static int swaphead=0;	/* =1 to swap data bytes of IRAF header values */
-static int swapdata=0;  /* =1 to swap bytes in IRAF data pixels */
-
-static void irafswap(int bitpix, char *string, int nbytes);
-static void irafswap2(char *string, int nbytes);
-static void irafswap4(char *string, int nbytes);
-static void irafswap8(char *string, int nbytes);
-static int pix_version (char *irafheader);
-static int irafncmp (char *irafheader, char *teststring, int nc);
-static int machswap(void);
-static int head_version (char *irafheader);
-static int hgeti4(char* hstring, char* keyword, int* val);
-static int hgets(char* hstring, char* keyword, int lstr, char* string);
-static char* hgetc(char* hstring, char* keyword);
-static char* ksearch(char* hstring, char* keyword);
-static char *blsearch (char* hstring, char* keyword);	
-static char *strsrch (char* s1,	char* s2);
-static char *strnsrch (	char* s1,char* s2,int ls1);
-static void hputi4(char* hstring,char* keyword,	int ival);
-static void hputs(char* hstring,char* keyword,char* cval);
-static void hputcom(char* hstring,char* keyword,char* comment);
-static void hputl(char* hstring,char* keyword,int lval);
-static void hputc(char* hstring,char* keyword,char* cval);
-static int getirafpixname (const char *hdrname, char *irafheader, char *pixfilename, int *status);
-int iraf2mem(char *filename, char **buffptr, size_t *buffsize, 
-      size_t *filesize, int *status);
-
-void ffpmsg(const char *err_message);
-
-/* CFITS_API is defined below for use on Windows systems.  */
-/* It is used to identify the public functions which should be exported. */
-/* This has no effect on non-windows platforms where "WIN32" is not defined */
-
-/* this is only needed to export the "fits_delete_iraf_file" symbol, which */
-/* is called in fpackutil.c (and perhaps in other applications programs) */
-
-#if defined (WIN32)
-  #if defined(cfitsio_EXPORTS)
-    #define CFITS_API __declspec(dllexport)
-  #else
-    #define CFITS_API //__declspec(dllimport)
-  #endif /* CFITS_API */
-#else /* defined (WIN32) */
- #define CFITS_API
-#endif
-
-int CFITS_API fits_delete_iraf_file(const char *filename, int *status);
-
-
-/*--------------------------------------------------------------------------*/
-int fits_delete_iraf_file(const char *filename,  /* name of input file      */
-             int *status)                        /* IO - error status       */
-
-/*
-   Delete the iraf .imh header file and the associated .pix data file
-*/
-{
-    char *irafheader;
-    int lenirafhead;
-
-    char pixfilename[SZ_IM2PIXFILE+1];
-
-    /* read IRAF header into dynamically created char array (free it later!) */
-    irafheader = irafrdhead(filename, &lenirafhead);
-
-    if (!irafheader)
-    {
-	return(*status = FILE_NOT_OPENED);
-    }
-
-    getirafpixname (filename, irafheader, pixfilename, status);
-
-    /* don't need the IRAF header any more */
-    free(irafheader);
-
-    if (*status > 0)
-       return(*status);
-
-    remove(filename);
-    remove(pixfilename);
-    
-    return(*status);
-}
-
-/*--------------------------------------------------------------------------*/
-int iraf2mem(char *filename,     /* name of input file                 */
-             char **buffptr,     /* O - memory pointer (initially NULL)    */
-             size_t *buffsize,   /* O - size of mem buffer, in bytes        */
-             size_t *filesize,   /* O - size of FITS file, in bytes         */
-             int *status)        /* IO - error status                       */
-
-/*
-   Driver routine that reads an IRAF image into memory, also converting
-   it into FITS format.
-*/
-{
-    char *irafheader;
-    int lenirafhead;
-
-    *buffptr = NULL;
-    *buffsize = 0;
-    *filesize = 0;
-
-    /* read IRAF header into dynamically created char array (free it later!) */
-    irafheader = irafrdhead(filename, &lenirafhead);
-
-    if (!irafheader)
-    {
-	return(*status = FILE_NOT_OPENED);
-    }
-
-    /* convert IRAF header to FITS header in memory */
-    iraftofits(filename, irafheader, lenirafhead, buffptr, buffsize, filesize,
-               status);
-
-    /* don't need the IRAF header any more */
-    free(irafheader);
-
-    if (*status > 0)
-       return(*status);
-
-    *filesize = (((*filesize - 1) / 2880 ) + 1 ) * 2880; /* multiple of 2880 */
-
-    /* append the image data onto the FITS header */
-    irafrdimage(buffptr, buffsize, filesize, status);
-
-    return(*status);
-}
-
-/*--------------------------------------------------------------------------*/
-/* Subroutine:	irafrdhead  (was irafrhead in D. Mink's original code)
- * Purpose:	Open and read the iraf .imh file.
- * Returns:	NULL if failure, else pointer to IRAF .imh image header
- * Notes:	The imhdr format is defined in iraf/lib/imhdr.h, some of
- *		which defines or mimicked, above.
- */
-
-static char *irafrdhead (
-    const char *filename,  /* Name of IRAF header file */
-    int *lihead)           /* Length of IRAF image header in bytes (returned) */
-{
-    FILE *fd;
-    int nbr;
-    char *irafheader;
-    char errmsg[81];
-    long nbhead;
-    int nihead;
-
-    *lihead = 0;
-
-    /* open the image header file */
-    fd = fopen (filename, "rb");
-    if (fd == NULL) {
-        ffpmsg("unable to open IRAF header file:");
-        ffpmsg(filename);
-	return (NULL);
-	}
-
-    /* Find size of image header file */
-    if (fseek(fd, 0, 2) != 0)  /* move to end of the file */
-    {
-        ffpmsg("IRAFRHEAD: cannot seek in file:");
-        ffpmsg(filename);
-        return(NULL);
-    }
-
-    nbhead = ftell(fd);     /* position = size of file */
-    if (nbhead < 0)
-    {
-        ffpmsg("IRAFRHEAD: cannot get pos. in file:");
-        ffpmsg(filename);
-        return(NULL);
-    }
-
-    if (fseek(fd, 0, 0) != 0) /* move back to beginning */
-    {
-        ffpmsg("IRAFRHEAD: cannot seek to beginning of file:");
-        ffpmsg(filename);
-        return(NULL);
-    }
-
-    /* allocate initial sized buffer */
-    nihead = nbhead + 5000;
-    irafheader = (char *) calloc (1, nihead);
-    if (irafheader == NULL) {
-	sprintf(errmsg, "IRAFRHEAD Cannot allocate %d-byte header",
-		      nihead);
-        ffpmsg(errmsg);
-        ffpmsg(filename);
-	return (NULL);
-	}
-    *lihead = nihead;
-
-    /* Read IRAF header */
-    nbr = fread (irafheader, 1, nbhead, fd);
-    fclose (fd);
-
-    /* Reject if header less than minimum length */
-    if (nbr < LEN_PIXHDR) {
-	sprintf(errmsg, "IRAFRHEAD header file: %d / %d bytes read.",
-		      nbr,LEN_PIXHDR);
-        ffpmsg(errmsg);
-        ffpmsg(filename);
-	free (irafheader);
-	return (NULL);
-	}
-
-    return (irafheader);
-}
-/*--------------------------------------------------------------------------*/
-static int irafrdimage (
-    char **buffptr,	/* FITS image header (filled) */
-    size_t *buffsize,      /* allocated size of the buffer */
-    size_t *filesize,      /* actual size of the FITS file */
-    int *status)
-{
-    FILE *fd;
-    char *bang;
-    int nax = 1, naxis1 = 1, naxis2 = 1, naxis3 = 1, naxis4 = 1, npaxis1 = 1, npaxis2;
-    int bitpix, bytepix, i;
-    char *fitsheader, *image;
-    int nbr, nbimage, nbaxis, nbl, nbdiff;
-    char *pixheader;
-    char *linebuff;
-    int imhver, lpixhead = 0;
-    char pixname[SZ_IM2PIXFILE+1];
-    char errmsg[81];
-    size_t newfilesize;
- 
-    fitsheader = *buffptr;           /* pointer to start of header */
-
-    /* Convert pixel file name to character string */
-    hgets (fitsheader, "PIXFILE", SZ_IM2PIXFILE, pixname);
-    hgeti4 (fitsheader, "PIXOFF", &lpixhead);
-
-    /* Open pixel file, ignoring machine name if present */
-    if ((bang = strchr (pixname, '!')) != NULL )
-	fd = fopen (bang + 1, "rb");
-    else
-	fd = fopen (pixname, "rb");
-
-    /* Print error message and exit if pixel file is not found */
-    if (!fd) {
-        ffpmsg("IRAFRIMAGE: Cannot open IRAF pixel file:");
-        ffpmsg(pixname);
-	return (*status = FILE_NOT_OPENED);
-	}
-
-    /* Read pixel header */
-    pixheader = (char *) calloc (lpixhead, 1);
-    if (pixheader == NULL) {
-            ffpmsg("IRAFRIMAGE: Cannot alloc memory for pixel header");
-            ffpmsg(pixname);
-            fclose (fd);
-	    return (*status = FILE_NOT_OPENED);
-	}
-    nbr = fread (pixheader, 1, lpixhead, fd);
-
-    /* Check size of pixel header */
-    if (nbr < lpixhead) {
-	sprintf(errmsg, "IRAF pixel file: %d / %d bytes read.",
-		      nbr,LEN_PIXHDR);
-        ffpmsg(errmsg);
-	free (pixheader);
-	fclose (fd);
-	return (*status = FILE_NOT_OPENED);
-	}
-
-    /* check pixel header magic word */
-    imhver = pix_version (pixheader);
-    if (imhver < 1) {
-        ffpmsg("File not valid IRAF pixel file:");
-        ffpmsg(pixname);
-	free (pixheader);
-	fclose (fd);
-	return (*status = FILE_NOT_OPENED);
-	}
-    free (pixheader);
-
-    /* Find number of bytes to read */
-    hgeti4 (fitsheader,"NAXIS",&nax);
-    hgeti4 (fitsheader,"NAXIS1",&naxis1);
-    hgeti4 (fitsheader,"NPAXIS1",&npaxis1);
-    if (nax > 1) {
-        hgeti4 (fitsheader,"NAXIS2",&naxis2);
-        hgeti4 (fitsheader,"NPAXIS2",&npaxis2);
-	}
-    if (nax > 2)
-        hgeti4 (fitsheader,"NAXIS3",&naxis3);
-    if (nax > 3)
-        hgeti4 (fitsheader,"NAXIS4",&naxis4);
-
-    hgeti4 (fitsheader,"BITPIX",&bitpix);
-    if (bitpix < 0)
-	bytepix = -bitpix / 8;
-    else
-	bytepix = bitpix / 8;
-
-    nbimage = naxis1 * naxis2 * naxis3 * naxis4 * bytepix;
-    
-    newfilesize = *filesize + nbimage;  /* header + data */
-    newfilesize = (((newfilesize - 1) / 2880 ) + 1 ) * 2880;
-
-    if (newfilesize > *buffsize)   /* need to allocate more memory? */
-    {
-      fitsheader =  (char *) realloc (*buffptr, newfilesize);
-      if (fitsheader == NULL) {
-	sprintf(errmsg, "IRAFRIMAGE Cannot allocate %d-byte image buffer",
-		(int) (*filesize));
-        ffpmsg(errmsg);
-        ffpmsg(pixname);
-	fclose (fd);
-	return (*status = FILE_NOT_OPENED);
-	}
-    }
-
-    *buffptr = fitsheader;
-    *buffsize = newfilesize;
-
-    image = fitsheader + *filesize;
-    *filesize = newfilesize;
-
-    /* Read IRAF image all at once if physical and image dimensions are the same */
-    if (npaxis1 == naxis1)
-	nbr = fread (image, 1, nbimage, fd);
-
-    /* Read IRAF image one line at a time if physical and image dimensions differ */
-    else {
-	nbdiff = (npaxis1 - naxis1) * bytepix;
-	nbaxis = naxis1 * bytepix;
-	linebuff = image;
-	nbr = 0;
-	if (naxis2 == 1 && naxis3 > 1)
-	    naxis2 = naxis3;
-	for (i = 0; i < naxis2; i++) {
-	    nbl = fread (linebuff, 1, nbaxis, fd);
-	    nbr = nbr + nbl;
-	    fseek (fd, nbdiff, 1);
-	    linebuff = linebuff + nbaxis;
-	    }
-	}
-    fclose (fd);
-
-    /* Check size of image */
-    if (nbr < nbimage) {
-	sprintf(errmsg, "IRAF pixel file: %d / %d bytes read.",
-		      nbr,nbimage);
-        ffpmsg(errmsg);
-        ffpmsg(pixname);
-	return (*status = FILE_NOT_OPENED);
-	}
-
-    /* Byte-reverse image, if necessary */
-    if (swapdata)
-	irafswap (bitpix, image, nbimage);
-
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-/* Return IRAF image format version number from magic word in IRAF header*/
-
-static int head_version (
-    char *irafheader)	/* IRAF image header from file */
-
-{
-
-    /* Check header file magic word */
-    if (irafncmp (irafheader, "imhdr", 5) != 0 ) {
-	if (strncmp (irafheader, "imhv2", 5) != 0)
-	    return (0);
-	else
-	    return (2);
-	}
-    else
-	return (1);
-}
-
-/*--------------------------------------------------------------------------*/
-/* Return IRAF image format version number from magic word in IRAF pixel file */
-
-static int pix_version (
-    char *irafheader)   /* IRAF image header from file */
-{
-
-    /* Check pixel file header magic word */
-    if (irafncmp (irafheader, "impix", 5) != 0) {
-	if (strncmp (irafheader, "impv2", 5) != 0)
-	    return (0);
-	else
-	    return (2);
-	}
-    else
-	return (1);
-}
-
-/*--------------------------------------------------------------------------*/
-/* Verify that file is valid IRAF imhdr or impix by checking first 5 chars
- * Returns:	0 on success, 1 on failure */
-
-static int irafncmp (
-
-char	*irafheader,	/* IRAF image header from file */
-char	*teststring,	/* C character string to compare */
-int	nc)		/* Number of characters to compate */
-
-{
-    char *line;
-
-    if ((line = iraf2str (irafheader, nc)) == NULL)
-	return (1);
-    if (strncmp (line, teststring, nc) == 0) {
-	free (line);
-	return (0);
-	}
-    else {
-	free (line);
-	return (1);
-	}
-}
-/*--------------------------------------------------------------------------*/
-
-/* Convert IRAF image header to FITS image header, returning FITS header */
-
-static int iraftofits (
-    char    *hdrname,  /* IRAF header file name (may be path) */
-    char    *irafheader,  /* IRAF image header */
-    int	    nbiraf,	  /* Number of bytes in IRAF header */
-    char    **buffptr,    /* pointer to the FITS header  */
-    size_t  *nbfits,      /* allocated size of the FITS header buffer */
-    size_t  *fitssize,  /* Number of bytes in FITS header (returned) */
-                        /*  = number of bytes to the end of the END keyword */
-    int     *status)
-{
-    char *objname;	/* object name from FITS file */
-    int lstr, i, j, k, ib, nax, nbits;
-    char *pixname, *newpixname, *bang, *chead;
-    char *fitsheader;
-    int nblock, nlines;
-    char *fhead, *fhead1, *fp, endline[81];
-    char irafchar;
-    char fitsline[81];
-    int pixtype;
-    int imhver, n, imu, pixoff, impixoff;
-/*    int immax, immin, imtime;  */
-    int imndim, imlen, imphyslen, impixtype;
-    char errmsg[81];
-
-    /* Set up last line of FITS header */
-    (void)strncpy (endline,"END", 3);
-    for (i = 3; i < 80; i++)
-	endline[i] = ' ';
-    endline[80] = 0;
-
-    /* Check header magic word */
-    imhver = head_version (irafheader);
-    if (imhver < 1) {
-	ffpmsg("File not valid IRAF image header");
-        ffpmsg(hdrname);
-	return(*status = FILE_NOT_OPENED);
-	}
-    if (imhver == 2) {
-	nlines = 24 + ((nbiraf - LEN_IM2HDR) / 81);
-	imndim = IM2_NDIM;
-	imlen = IM2_LEN;
-	imphyslen = IM2_PHYSLEN;
-	impixtype = IM2_PIXTYPE;
-	impixoff = IM2_PIXOFF;
-/*	imtime = IM2_MTIME; */
-/*	immax = IM2_MAX;  */
-/*	immin = IM2_MIN; */
-	}
-    else {
-	nlines = 24 + ((nbiraf - LEN_IMHDR) / 162);
-	imndim = IM_NDIM;
-	imlen = IM_LEN;
-	imphyslen = IM_PHYSLEN;
-	impixtype = IM_PIXTYPE;
-	impixoff = IM_PIXOFF;
-/*	imtime = IM_MTIME; */
-/*	immax = IM_MAX; */
-/*	immin = IM_MIN; */
-	}
-
-    /*  Initialize FITS header */
-    nblock = (nlines * 80) / 2880;
-    *nbfits = (nblock + 5) * 2880 + 4;
-    fitsheader = (char *) calloc (*nbfits, 1);
-    if (fitsheader == NULL) {
-	sprintf(errmsg, "IRAF2FITS Cannot allocate %d-byte FITS header",
-		(int) (*nbfits));
-        ffpmsg(hdrname);
-	return (*status = FILE_NOT_OPENED);
-	}
-
-    fhead = fitsheader;
-    *buffptr = fitsheader;
-    (void)strncpy (fitsheader, endline, 80);
-    hputl (fitsheader, "SIMPLE", 1);
-    fhead = fhead + 80;
-
-    /*  check if the IRAF file is in big endian (sun) format (= 0) or not. */
-    /*  This is done by checking the 4 byte integer in the header that     */
-    /*  represents the iraf pixel type.  This 4-byte word is guaranteed to */
-    /*  have the least sig byte != 0 and the most sig byte = 0,  so if the */
-    /*  first byte of the word != 0, then the file in little endian format */
-    /*  like on an Alpha machine.                                          */
-
-    swaphead = isirafswapped(irafheader, impixtype);
-    if (imhver == 1)
-        swapdata = swaphead; /* vers 1 data has same swapness as header */
-    else
-        swapdata = irafgeti4 (irafheader, IM2_SWAPPED); 
-
-    /*  Set pixel size in FITS header */
-    pixtype = irafgeti4 (irafheader, impixtype);
-    switch (pixtype) {
-	case TY_CHAR:
-	    nbits = 8;
-	    break;
-	case TY_UBYTE:
-	    nbits = 8;
-	    break;
-	case TY_SHORT:
-	    nbits = 16;
-	    break;
-	case TY_USHORT:
-	    nbits = -16;
-	    break;
-	case TY_INT:
-	case TY_LONG:
-	    nbits = 32;
-	    break;
-	case TY_REAL:
-	    nbits = -32;
-	    break;
-	case TY_DOUBLE:
-	    nbits = -64;
-	    break;
-	default:
-	    sprintf(errmsg,"Unsupported IRAF data type: %d", pixtype);
-            ffpmsg(errmsg);
-            ffpmsg(hdrname);
-	    return (*status = FILE_NOT_OPENED);
-	}
-    hputi4 (fitsheader,"BITPIX",nbits);
-    hputcom (fitsheader,"BITPIX", "IRAF .imh pixel type");
-    fhead = fhead + 80;
-
-    /*  Set image dimensions in FITS header */
-    nax = irafgeti4 (irafheader, imndim);
-    hputi4 (fitsheader,"NAXIS",nax);
-    hputcom (fitsheader,"NAXIS", "IRAF .imh naxis");
-    fhead = fhead + 80;
-
-    n = irafgeti4 (irafheader, imlen);
-    hputi4 (fitsheader, "NAXIS1", n);
-    hputcom (fitsheader,"NAXIS1", "IRAF .imh image naxis[1]");
-    fhead = fhead + 80;
-
-    if (nax > 1) {
-	n = irafgeti4 (irafheader, imlen+4);
-	hputi4 (fitsheader, "NAXIS2", n);
-	hputcom (fitsheader,"NAXIS2", "IRAF .imh image naxis[2]");
-        fhead = fhead + 80;
-	}
-    if (nax > 2) {
-	n = irafgeti4 (irafheader, imlen+8);
-	hputi4 (fitsheader, "NAXIS3", n);
-	hputcom (fitsheader,"NAXIS3", "IRAF .imh image naxis[3]");
-	fhead = fhead + 80;
-	}
-    if (nax > 3) {
-	n = irafgeti4 (irafheader, imlen+12);
-	hputi4 (fitsheader, "NAXIS4", n);
-	hputcom (fitsheader,"NAXIS4", "IRAF .imh image naxis[4]");
-	fhead = fhead + 80;
-	}
-
-    /* Set object name in FITS header */
-    if (imhver == 2)
-	objname = irafgetc (irafheader, IM2_TITLE, SZ_IM2TITLE);
-    else
-	objname = irafgetc2 (irafheader, IM_TITLE, SZ_IMTITLE);
-    if ((lstr = strlen (objname)) < 8) {
-	for (i = lstr; i < 8; i++)
-	    objname[i] = ' ';
-	objname[8] = 0;
-	}
-    hputs (fitsheader,"OBJECT",objname);
-    hputcom (fitsheader,"OBJECT", "IRAF .imh title");
-    free (objname);
-    fhead = fhead + 80;
-
-    /* Save physical axis lengths so image file can be read */
-    n = irafgeti4 (irafheader, imphyslen);
-    hputi4 (fitsheader, "NPAXIS1", n);
-    hputcom (fitsheader,"NPAXIS1", "IRAF .imh physical naxis[1]");
-    fhead = fhead + 80;
-    if (nax > 1) {
-	n = irafgeti4 (irafheader, imphyslen+4);
-	hputi4 (fitsheader, "NPAXIS2", n);
-	hputcom (fitsheader,"NPAXIS2", "IRAF .imh physical naxis[2]");
-	fhead = fhead + 80;
-	}
-    if (nax > 2) {
-	n = irafgeti4 (irafheader, imphyslen+8);
-	hputi4 (fitsheader, "NPAXIS3", n);
-	hputcom (fitsheader,"NPAXIS3", "IRAF .imh physical naxis[3]");
-	fhead = fhead + 80;
-	}
-    if (nax > 3) {
-	n = irafgeti4 (irafheader, imphyslen+12);
-	hputi4 (fitsheader, "NPAXIS4", n);
-	hputcom (fitsheader,"NPAXIS4", "IRAF .imh physical naxis[4]");
-	fhead = fhead + 80;
-	}
-
-    /* Save image header filename in header */
-    hputs (fitsheader,"IMHFILE",hdrname);
-    hputcom (fitsheader,"IMHFILE", "IRAF header file name");
-    fhead = fhead + 80;
-
-    /* Save image pixel file pathname in header */
-    if (imhver == 2)
-	pixname = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE);
-    else
-	pixname = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE);
-    if (strncmp(pixname, "HDR", 3) == 0 ) {
-	newpixname = same_path (pixname, hdrname);
-        if (newpixname) {
-          free (pixname);
-          pixname = newpixname;
-	  }
-	}
-    if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) {
-	newpixname = same_path (pixname, hdrname);
-        if (newpixname) {
-          free (pixname);
-          pixname = newpixname;
-	  }
-	}
-	
-    if ((bang = strchr (pixname, '!')) != NULL )
-	hputs (fitsheader,"PIXFILE",bang+1);
-    else
-	hputs (fitsheader,"PIXFILE",pixname);
-    free (pixname);
-    hputcom (fitsheader,"PIXFILE", "IRAF .pix pixel file");
-    fhead = fhead + 80;
-
-    /* Save image offset from star of pixel file */
-    pixoff = irafgeti4 (irafheader, impixoff);
-    pixoff = (pixoff - 1) * 2;
-    hputi4 (fitsheader, "PIXOFF", pixoff);
-    hputcom (fitsheader,"PIXOFF", "IRAF .pix pixel offset (Do not change!)");
-    fhead = fhead + 80;
-
-    /* Save IRAF file format version in header */
-    hputi4 (fitsheader,"IMHVER",imhver);
-    hputcom (fitsheader,"IMHVER", "IRAF .imh format version (1 or 2)");
-    fhead = fhead + 80;
-
-    /* Save flag as to whether to swap IRAF data for this file and machine */
-    if (swapdata)
-	hputl (fitsheader, "PIXSWAP", 1);
-    else
-	hputl (fitsheader, "PIXSWAP", 0);
-    hputcom (fitsheader,"PIXSWAP", "IRAF pixels, FITS byte orders differ if T");
-    fhead = fhead + 80;
-
-    /* Add user portion of IRAF header to FITS header */
-    fitsline[80] = 0;
-    if (imhver == 2) {
-	imu = LEN_IM2HDR;
-	chead = irafheader;
-	j = 0;
-	for (k = 0; k < 80; k++)
-	    fitsline[k] = ' ';
-	for (i = imu; i < nbiraf; i++) {
-	    irafchar = chead[i];
-	    if (irafchar == 0)
-		break;
-	    else if (irafchar == 10) {
-		(void)strncpy (fhead, fitsline, 80);
-		/* fprintf (stderr,"%80s\n",fitsline); */
-		if (strncmp (fitsline, "OBJECT ", 7) != 0) {
-		    fhead = fhead + 80;
-		    }
-		for (k = 0; k < 80; k++)
-		    fitsline[k] = ' ';
-		j = 0;
-		}
-	    else {
-		if (j > 80) {
-		    if (strncmp (fitsline, "OBJECT ", 7) != 0) {
-			(void)strncpy (fhead, fitsline, 80);
-			/* fprintf (stderr,"%80s\n",fitsline); */
-			j = 9;
-			fhead = fhead + 80;
-			}
-		    for (k = 0; k < 80; k++)
-			fitsline[k] = ' ';
-		    }
-		if (irafchar > 32 && irafchar < 127)
-		    fitsline[j] = irafchar;
-		j++;
-		}
-	    }
-	}
-    else {
-	imu = LEN_IMHDR;
-	chead = irafheader;
-	if (swaphead == 1)
-	    ib = 0;
-	else
-	    ib = 1;
-	for (k = 0; k < 80; k++)
-	    fitsline[k] = ' ';
-	j = 0;
-	for (i = imu; i < nbiraf; i=i+2) {
-	    irafchar = chead[i+ib];
-	    if (irafchar == 0)
-		break;
-	    else if (irafchar == 10) {
-		if (strncmp (fitsline, "OBJECT ", 7) != 0) {
-		    (void)strncpy (fhead, fitsline, 80);
-		    fhead = fhead + 80;
-		    }
-		/* fprintf (stderr,"%80s\n",fitsline); */
-		j = 0;
-		for (k = 0; k < 80; k++)
-		    fitsline[k] = ' ';
-		}
-	    else {
-		if (j > 80) {
-		    if (strncmp (fitsline, "OBJECT ", 7) != 0) {
-			(void)strncpy (fhead, fitsline, 80);
-			j = 9;
-			fhead = fhead + 80;
-			}
-		    /* fprintf (stderr,"%80s\n",fitsline); */
-		    for (k = 0; k < 80; k++)
-			fitsline[k] = ' ';
-		    }
-		if (irafchar > 32 && irafchar < 127)
-		    fitsline[j] = irafchar;
-		j++;
-		}
-	    }
-	}
-
-    /* Add END to last line */
-    (void)strncpy (fhead, endline, 80);
-
-    /* Find end of last 2880-byte block of header */
-    fhead = ksearch (fitsheader, "END") + 80;
-    nblock = *nbfits / 2880;
-    fhead1 = fitsheader + (nblock * 2880);
-    *fitssize = fhead - fitsheader;  /* no. of bytes to end of END keyword */
-
-    /* Pad rest of header with spaces */
-    strncpy (endline,"   ",3);
-    for (fp = fhead; fp < fhead1; fp = fp + 80) {
-	(void)strncpy (fp, endline,80);
-	}
-
-    return (*status);
-}
-/*--------------------------------------------------------------------------*/
-
-/* get the IRAF pixel file name */
-
-static int getirafpixname (
-    const char *hdrname,  /* IRAF header file name (may be path) */
-    char    *irafheader,  /* IRAF image header */
-    char    *pixfilename,     /* IRAF pixel file name */
-    int     *status)
-{
-    int imhver;
-    char *pixname, *newpixname, *bang;
-
-    /* Check header magic word */
-    imhver = head_version (irafheader);
-    if (imhver < 1) {
-	ffpmsg("File not valid IRAF image header");
-        ffpmsg(hdrname);
-	return(*status = FILE_NOT_OPENED);
-	}
-
-    /* get image pixel file pathname in header */
-    if (imhver == 2)
-	pixname = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE);
-    else
-	pixname = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE);
-
-    if (strncmp(pixname, "HDR", 3) == 0 ) {
-	newpixname = same_path (pixname, hdrname);
-        if (newpixname) {
-          free (pixname);
-          pixname = newpixname;
-	  }
-	}
-
-    if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) {
-	newpixname = same_path (pixname, hdrname);
-        if (newpixname) {
-          free (pixname);
-          pixname = newpixname;
-	  }
-	}
-	
-    if ((bang = strchr (pixname, '!')) != NULL )
-	strcpy(pixfilename,bang+1);
-    else
-	strcpy(pixfilename,pixname);
-
-    free (pixname);
-
-    return (*status);
-}
-
-/*--------------------------------------------------------------------------*/
-/* Put filename and header path together */
-
-static char *same_path (
-
-char	*pixname,	/* IRAF pixel file pathname */
-const char	*hdrname)	/* IRAF image header file pathname */
-
-{
-    int len;
-    char *newpixname;
-
-/*  WDP - 10/16/2007 - increased allocation to avoid possible overflow */
-/*    newpixname = (char *) calloc (SZ_IM2PIXFILE, sizeof (char)); */
-
-    newpixname = (char *) calloc (2*SZ_IM2PIXFILE+1, sizeof (char));
-    if (newpixname == NULL) {
-            ffpmsg("iraffits same_path: Cannot alloc memory for newpixname");
-	    return (NULL);
-	}
-
-    /* Pixel file is in same directory as header */
-    if (strncmp(pixname, "HDR$", 4) == 0 ) {
-	(void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE);
-
-	/* find the end of the pathname */
-	len = strlen (newpixname);
-#ifndef VMS
-	while( (len > 0) && (newpixname[len-1] != '/') )
-#else
-	while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') )
-#endif
-	    len--;
-
-	/* add name */
-	newpixname[len] = '\0';
-	(void)strncat (newpixname, &pixname[4], SZ_IM2PIXFILE);
-	}
-
-    /* Bare pixel file with no path is assumed to be same as HDR$filename */
-    else if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) {
-	(void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE);
-
-	/* find the end of the pathname */
-	len = strlen (newpixname);
-#ifndef VMS
-	while( (len > 0) && (newpixname[len-1] != '/') )
-#else
-	while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') )
-#endif
-	    len--;
-
-	/* add name */
-	newpixname[len] = '\0';
-	(void)strncat (newpixname, pixname, SZ_IM2PIXFILE);
-	}
-
-    /* Pixel file has same name as header file, but with .pix extension */
-    else if (strncmp (pixname, "HDR", 3) == 0) {
-
-	/* load entire header name string into name buffer */
-	(void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE);
-	len = strlen (newpixname);
-	newpixname[len-3] = 'p';
-	newpixname[len-2] = 'i';
-	newpixname[len-1] = 'x';
-	}
-
-    return (newpixname);
-}
-
-/*--------------------------------------------------------------------------*/
-static int isirafswapped (
-
-char	*irafheader,	/* IRAF image header */
-int	offset)		/* Number of bytes to skip before number */
-
-    /*  check if the IRAF file is in big endian (sun) format (= 0) or not */
-    /*  This is done by checking the 4 byte integer in the header that */
-    /*  represents the iraf pixel type.  This 4-byte word is guaranteed to */
-    /*  have the least sig byte != 0 and the most sig byte = 0,  so if the */
-    /*  first byte of the word != 0, then the file in little endian format */
-    /*  like on an Alpha machine.                                          */
-
-{
-    int  swapped;
-
-    if (irafheader[offset] != 0)
-	swapped = 1;
-    else
-	swapped = 0;
-
-    return (swapped);
-}
-/*--------------------------------------------------------------------------*/
-static int irafgeti4 (
-
-char	*irafheader,	/* IRAF image header */
-int	offset)		/* Number of bytes to skip before number */
-
-{
-    char *ctemp, *cheader;
-    int  temp;
-
-    cheader = irafheader;
-    ctemp = (char *) &temp;
-
-    if (machswap() != swaphead) {
-	ctemp[3] = cheader[offset];
-	ctemp[2] = cheader[offset+1];
-	ctemp[1] = cheader[offset+2];
-	ctemp[0] = cheader[offset+3];
-	}
-    else {
-	ctemp[0] = cheader[offset];
-	ctemp[1] = cheader[offset+1];
-	ctemp[2] = cheader[offset+2];
-	ctemp[3] = cheader[offset+3];
-	}
-    return (temp);
-}
-
-/*--------------------------------------------------------------------------*/
-/* IRAFGETC2 -- Get character string from arbitrary part of v.1 IRAF header */
-
-static char *irafgetc2 (
-
-char	*irafheader,	/* IRAF image header */
-int	offset,		/* Number of bytes to skip before string */
-int	nc)		/* Maximum number of characters in string */
-
-{
-    char *irafstring, *string;
-
-    irafstring = irafgetc (irafheader, offset, 2*(nc+1));
-    string = iraf2str (irafstring, nc);
-    free (irafstring);
-
-    return (string);
-}
-
-/*--------------------------------------------------------------------------*/
-/* IRAFGETC -- Get character string from arbitrary part of IRAF header */
-
-static char *irafgetc (
-
-char	*irafheader,	/* IRAF image header */
-int	offset,		/* Number of bytes to skip before string */
-int	nc)		/* Maximum number of characters in string */
-
-{
-    char *ctemp, *cheader;
-    int i;
-
-    cheader = irafheader;
-    ctemp = (char *) calloc (nc+1, 1);
-    if (ctemp == NULL) {
-	ffpmsg("IRAFGETC Cannot allocate memory for string variable");
-	return (NULL);
-	}
-    for (i = 0; i < nc; i++) {
-	ctemp[i] = cheader[offset+i];
-	if (ctemp[i] > 0 && ctemp[i] < 32)
-	    ctemp[i] = ' ';
-	}
-
-    return (ctemp);
-}
-
-/*--------------------------------------------------------------------------*/
-/* Convert IRAF 2-byte/char string to 1-byte/char string */
-
-static char *iraf2str (
-
-char	*irafstring,	/* IRAF 2-byte/character string */
-int	nchar)		/* Number of characters in string */
-{
-    char *string;
-    int i, j;
-
-    string = (char *) calloc (nchar+1, 1);
-    if (string == NULL) {
-	ffpmsg("IRAF2STR Cannot allocate memory for string variable");
-	return (NULL);
-	}
-
-    /* the chars are in bytes 1, 3, 5, ... if bigendian format (SUN) */
-    /* else in bytes 0, 2, 4, ... if little endian format (Alpha)    */
-
-    if (irafstring[0] != 0)
-	j = 0;
-    else
-	j = 1;
-
-    /* Convert appropriate byte of input to output character */
-    for (i = 0; i < nchar; i++) {
-	string[i] = irafstring[j];
-	j = j + 2;
-	}
-
-    return (string);
-}
-
-/*--------------------------------------------------------------------------*/
-/* IRAFSWAP -- Reverse bytes of any type of vector in place */
-
-static void irafswap (
-
-int	bitpix,		/* Number of bits per pixel */
-			/*  16 = short, -16 = unsigned short, 32 = int */
-			/* -32 = float, -64 = double */
-char	*string,	/* Address of starting point of bytes to swap */
-int	nbytes)		/* Number of bytes to swap */
-
-{
-    switch (bitpix) {
-
-	case 16:
-	    if (nbytes < 2) return;
-	    irafswap2 (string,nbytes);
-	    break;
-
-	case 32:
-	    if (nbytes < 4) return;
-	    irafswap4 (string,nbytes);
-	    break;
-
-	case -16:
-	    if (nbytes < 2) return;
-	    irafswap2 (string,nbytes);
-	    break;
-
-	case -32:
-	    if (nbytes < 4) return;
-	    irafswap4 (string,nbytes);
-	    break;
-
-	case -64:
-	    if (nbytes < 8) return;
-	    irafswap8 (string,nbytes);
-	    break;
-
-	}
-    return;
-}
-
-/*--------------------------------------------------------------------------*/
-/* IRAFSWAP2 -- Swap bytes in string in place */
-
-static void irafswap2 (
-
-char *string,	/* Address of starting point of bytes to swap */
-int nbytes)	/* Number of bytes to swap */
-
-{
-    char *sbyte, temp, *slast;
-
-    slast = string + nbytes;
-    sbyte = string;
-    while (sbyte < slast) {
-	temp = sbyte[0];
-	sbyte[0] = sbyte[1];
-	sbyte[1] = temp;
-	sbyte= sbyte + 2;
-	}
-    return;
-}
-
-/*--------------------------------------------------------------------------*/
-/* IRAFSWAP4 -- Reverse bytes of Integer*4 or Real*4 vector in place */
-
-static void irafswap4 (
-
-char *string,	/* Address of Integer*4 or Real*4 vector */
-int nbytes)	/* Number of bytes to reverse */
-
-{
-    char *sbyte, *slast;
-    char temp0, temp1, temp2, temp3;
-
-    slast = string + nbytes;
-    sbyte = string;
-    while (sbyte < slast) {
-	temp3 = sbyte[0];
-	temp2 = sbyte[1];
-	temp1 = sbyte[2];
-	temp0 = sbyte[3];
-	sbyte[0] = temp0;
-	sbyte[1] = temp1;
-	sbyte[2] = temp2;
-	sbyte[3] = temp3;
-	sbyte = sbyte + 4;
-	}
-
-    return;
-}
-
-/*--------------------------------------------------------------------------*/
-/* IRAFSWAP8 -- Reverse bytes of Real*8 vector in place */
-
-static void irafswap8 (
-
-char *string,	/* Address of Real*8 vector */
-int nbytes)	/* Number of bytes to reverse */
-
-{
-    char *sbyte, *slast;
-    char temp[8];
-
-    slast = string + nbytes;
-    sbyte = string;
-    while (sbyte < slast) {
-	temp[7] = sbyte[0];
-	temp[6] = sbyte[1];
-	temp[5] = sbyte[2];
-	temp[4] = sbyte[3];
-	temp[3] = sbyte[4];
-	temp[2] = sbyte[5];
-	temp[1] = sbyte[6];
-	temp[0] = sbyte[7];
-	sbyte[0] = temp[0];
-	sbyte[1] = temp[1];
-	sbyte[2] = temp[2];
-	sbyte[3] = temp[3];
-	sbyte[4] = temp[4];
-	sbyte[5] = temp[5];
-	sbyte[6] = temp[6];
-	sbyte[7] = temp[7];
-	sbyte = sbyte + 8;
-	}
-    return;
-}
-
-/*--------------------------------------------------------------------------*/
-static int
-machswap (void)
-
-{
-    char *ctest;
-    int itest;
-
-    itest = 1;
-    ctest = (char *)&itest;
-    if (*ctest)
-	return (1);
-    else
-	return (0);
-}
-
-/*--------------------------------------------------------------------------*/
-/*             the following routines were originally in hget.c             */
-/*--------------------------------------------------------------------------*/
-
-
-static int lhead0 = 0;
-
-/*--------------------------------------------------------------------------*/
-
-/* Extract long value for variable from FITS header string */
-
-static int
-hgeti4 (hstring,keyword,ival)
-
-char *hstring;	/* character string containing FITS header information
-		   in the format =  {/ } */
-char *keyword;	/* character string containing the name of the keyword
-		   the value of which is returned.  hget searches for a
-		   line beginning with this string.  if "[n]" is present,
-		   the n'th token in the value is returned.
-		   (the first 8 characters must be unique) */
-int *ival;
-{
-char *value;
-double dval;
-int minint;
-char val[30]; 
-
-/* Get value and comment from header string */
-	value = hgetc (hstring,keyword);
-
-/* Translate value from ASCII to binary */
-	if (value != NULL) {
-	    minint = -MAXINT - 1;
-	    strcpy (val, value);
-	    dval = atof (val);
-	    if (dval+0.001 > MAXINT)
-		*ival = MAXINT;
-	    else if (dval >= 0)
-		*ival = (int) (dval + 0.001);
-	    else if (dval-0.001 < minint)
-		*ival = minint;
-	    else
-		*ival = (int) (dval - 0.001);
-	    return (1);
-	    }
-	else {
-	    return (0);
-	    }
-}
-
-/*-------------------------------------------------------------------*/
-/* Extract string value for variable from FITS header string */
-
-static int
-hgets (hstring, keyword, lstr, str)
-
-char *hstring;	/* character string containing FITS header information
-		   in the format =  {/ } */
-char *keyword;	/* character string containing the name of the keyword
-		   the value of which is returned.  hget searches for a
-		   line beginning with this string.  if "[n]" is present,
-		   the n'th token in the value is returned.
-		   (the first 8 characters must be unique) */
-int lstr;	/* Size of str in characters */
-char *str;	/* String (returned) */
-{
-	char *value;
-	int lval;
-
-/* Get value and comment from header string */
-	value = hgetc (hstring,keyword);
-
-	if (value != NULL) {
-	    lval = strlen (value);
-	    if (lval < lstr)
-		strcpy (str, value);
-	    else if (lstr > 1)
-		strncpy (str, value, lstr-1);
-	    else
-		str[0] = value[0];
-	    return (1);
-	    }
-	else
-	    return (0);
-}
-
-/*-------------------------------------------------------------------*/
-/* Extract character value for variable from FITS header string */
-
-static char *
-hgetc (hstring,keyword0)
-
-char *hstring;	/* character string containing FITS header information
-		   in the format =  {/ } */
-char *keyword0;	/* character string containing the name of the keyword
-		   the value of which is returned.  hget searches for a
-		   line beginning with this string.  if "[n]" is present,
-		   the n'th token in the value is returned.
-		   (the first 8 characters must be unique) */
-{
-	static char cval[80];
-	char *value;
-	char cwhite[2];
-	char squot[2], dquot[2], lbracket[2], rbracket[2], slash[2], comma[2];
-	char keyword[81]; /* large for ESO hierarchical keywords */
-	char line[100];
-	char *vpos, *cpar = NULL;
-	char *q1, *q2 = NULL, *v1, *v2, *c1, *brack1, *brack2;
-        char *saveptr;
-	int ipar, i;
-
-	squot[0] = 39;
-	squot[1] = 0;
-	dquot[0] = 34;
-	dquot[1] = 0;
-	lbracket[0] = 91;
-	lbracket[1] = 0;
-	comma[0] = 44;
-	comma[1] = 0;
-	rbracket[0] = 93;
-	rbracket[1] = 0;
-	slash[0] = 47;
-	slash[1] = 0;
-
-/* Find length of variable name */
-	strncpy (keyword,keyword0, sizeof(keyword)-1);
-	brack1 = strsrch (keyword,lbracket);
-	if (brack1 == NULL)
-	    brack1 = strsrch (keyword,comma);
-	if (brack1 != NULL) {
-	    *brack1 = '\0';
-	    brack1++;
-	    }
-
-/* Search header string for variable name */
-	vpos = ksearch (hstring,keyword);
-
-/* Exit if not found */
-	if (vpos == NULL) {
-	    return (NULL);
-	    }
-
-/* Initialize line to nulls */
-	 for (i = 0; i < 100; i++)
-	    line[i] = 0;
-
-/* In standard FITS, data lasts until 80th character */
-
-/* Extract entry for this variable from the header */
-	strncpy (line,vpos,80);
-
-/* check for quoted value */
-	q1 = strsrch (line,squot);
-	c1 = strsrch (line,slash);
-	if (q1 != NULL) {
-	    if (c1 != NULL && q1 < c1)
-		q2 = strsrch (q1+1,squot);
-	    else if (c1 == NULL)
-		q2 = strsrch (q1+1,squot);
-	    else
-		q1 = NULL;
-	    }
-	else {
-	    q1 = strsrch (line,dquot);
-	    if (q1 != NULL) {
-		if (c1 != NULL && q1 < c1)
-		    q2 = strsrch (q1+1,dquot);
-		else if (c1 == NULL)
-		    q2 = strsrch (q1+1,dquot);
-		else
-		    q1 = NULL;
-		}
-	    else {
-		q1 = NULL;
-		q2 = line + 10;
-		}
-	    }
-
-/* Extract value and remove excess spaces */
-	if (q1 != NULL) {
-	    v1 = q1 + 1;
-	    v2 = q2;
-	    c1 = strsrch (q2,"/");
-	    }
-	else {
-	    v1 = strsrch (line,"=") + 1;
-	    c1 = strsrch (line,"/");
-	    if (c1 != NULL)
-		v2 = c1;
-	    else
-		v2 = line + 79;
-	    }
-
-/* Ignore leading spaces */
-	while (*v1 == ' ' && v1 < v2) {
-	    v1++;
-	    }
-
-/* Drop trailing spaces */
-	*v2 = '\0';
-	v2--;
-	while (*v2 == ' ' && v2 > v1) {
-	    *v2 = '\0';
-	    v2--;
-	    }
-
-	if (!strcmp (v1, "-0"))
-	    v1++;
-	strcpy (cval,v1);
-	value = cval;
-
-/* If keyword has brackets, extract appropriate token from value */
-	if (brack1 != NULL) {
-	    brack2 = strsrch (brack1,rbracket);
-	    if (brack2 != NULL)
-		*brack2 = '\0';
-	    ipar = atoi (brack1);
-	    if (ipar > 0) {
-		cwhite[0] = ' ';
-		cwhite[1] = '\0';
-		for (i = 1; i <= ipar; i++) {
-		    cpar = ffstrtok (v1,cwhite,&saveptr);
-		    v1 = NULL;
-		    }
-		if (cpar != NULL) {
-		    strcpy (cval,cpar);
-		    }
-		else
-		    value = NULL;
-		}
-	    }
-
-	return (value);
-}
-
-
-/*-------------------------------------------------------------------*/
-/* Find beginning of fillable blank line before FITS header keyword line */
-
-static char *
-blsearch (hstring,keyword)
-
-/* Find entry for keyword keyword in FITS header string hstring.
-   (the keyword may have a maximum of eight letters)
-   NULL is returned if the keyword is not found */
-
-char *hstring;	/* character string containing fits-style header
-		information in the format =  {/ }
-		the default is that each entry is 80 characters long;
-		however, lines may be of arbitrary length terminated by
-		nulls, carriage returns or linefeeds, if packed is true.  */
-char *keyword;	/* character string containing the name of the variable
-		to be returned.  ksearch searches for a line beginning
-		with this string.  The string may be a character
-		literal or a character variable terminated by a null
-		or '$'.  it is truncated to 8 characters. */
-{
-    char *loc, *headnext, *headlast, *pval, *lc, *line;
-    char *bval;
-    int icol, nextchar, lkey, nleft, lhstr;
-
-    pval = 0;
-
-    /* Search header string for variable name */
-    if (lhead0)
-	lhstr = lhead0;
-    else {
-	lhstr = 0;
-	while (lhstr < 57600 && hstring[lhstr] != 0)
-	    lhstr++;
-	}
-    headlast = hstring + lhstr;
-    headnext = hstring;
-    pval = NULL;
-    while (headnext < headlast) {
-	nleft = headlast - headnext;
-	loc = strnsrch (headnext, keyword, nleft);
-
-	/* Exit if keyword is not found */
-	if (loc == NULL) {
-	    break;
-	    }
-
-	icol = (loc - hstring) % 80;
-	lkey = strlen (keyword);
-	nextchar = (int) *(loc + lkey);
-
-	/* If this is not in the first 8 characters of a line, keep searching */
-	if (icol > 7)
-	    headnext = loc + 1;
-
-	/* If parameter name in header is longer, keep searching */
-	else if (nextchar != 61 && nextchar > 32 && nextchar < 127)
-	    headnext = loc + 1;
-
-	/* If preceeding characters in line are not blanks, keep searching */
-	else {
-	    line = loc - icol;
-	    for (lc = line; lc < loc; lc++) {
-		if (*lc != ' ')
-		    headnext = loc + 1;
-		}
-
-	/* Return pointer to start of line if match */
-	    if (loc >= headnext) {
-		pval = line;
-		break;
-		}
-	    }
-	}
-
-    /* Return NULL if keyword is found at start of FITS header string */
-    if (pval == NULL)
-	return (pval);
-
-    /* Return NULL if  found the first keyword in the header */
-    if (pval == hstring)
-        return (NULL);
-
-    /* Find last nonblank line before requested keyword */
-    bval = pval - 80;
-    while (!strncmp (bval,"        ",8))
-	bval = bval - 80;
-    bval = bval + 80;
-
-    /* Return pointer to calling program if blank lines found */
-    if (bval < pval)
-	return (bval);
-    else
-	return (NULL);
-}
-
-
-/*-------------------------------------------------------------------*/
-/* Find FITS header line containing specified keyword */
-
-static char *ksearch (hstring,keyword)
-
-/* Find entry for keyword keyword in FITS header string hstring.
-   (the keyword may have a maximum of eight letters)
-   NULL is returned if the keyword is not found */
-
-char *hstring;	/* character string containing fits-style header
-		information in the format =  {/ }
-		the default is that each entry is 80 characters long;
-		however, lines may be of arbitrary length terminated by
-		nulls, carriage returns or linefeeds, if packed is true.  */
-char *keyword;	/* character string containing the name of the variable
-		to be returned.  ksearch searches for a line beginning
-		with this string.  The string may be a character
-		literal or a character variable terminated by a null
-		or '$'.  it is truncated to 8 characters. */
-{
-    char *loc, *headnext, *headlast, *pval, *lc, *line;
-    int icol, nextchar, lkey, nleft, lhstr;
-
-    pval = 0;
-
-/* Search header string for variable name */
-    if (lhead0)
-	lhstr = lhead0;
-    else {
-	lhstr = 0;
-	while (lhstr < 57600 && hstring[lhstr] != 0)
-	    lhstr++;
-	}
-    headlast = hstring + lhstr;
-    headnext = hstring;
-    pval = NULL;
-    while (headnext < headlast) {
-	nleft = headlast - headnext;
-	loc = strnsrch (headnext, keyword, nleft);
-
-	/* Exit if keyword is not found */
-	if (loc == NULL) {
-	    break;
-	    }
-
-	icol = (loc - hstring) % 80;
-	lkey = strlen (keyword);
-	nextchar = (int) *(loc + lkey);
-
-	/* If this is not in the first 8 characters of a line, keep searching */
-	if (icol > 7)
-	    headnext = loc + 1;
-
-	/* If parameter name in header is longer, keep searching */
-	else if (nextchar != 61 && nextchar > 32 && nextchar < 127)
-	    headnext = loc + 1;
-
-	/* If preceeding characters in line are not blanks, keep searching */
-	else {
-	    line = loc - icol;
-	    for (lc = line; lc < loc; lc++) {
-		if (*lc != ' ')
-		    headnext = loc + 1;
-		}
-
-	/* Return pointer to start of line if match */
-	    if (loc >= headnext) {
-		pval = line;
-		break;
-		}
-	    }
-	}
-
-/* Return pointer to calling program */
-	return (pval);
-
-}
-
-/*-------------------------------------------------------------------*/
-/* Find string s2 within null-terminated string s1 */
-
-static char *
-strsrch (s1, s2)
-
-char *s1;	/* String to search */
-char *s2;	/* String to look for */
-
-{
-    int ls1;
-    ls1 = strlen (s1);
-    return (strnsrch (s1, s2, ls1));
-}
-
-/*-------------------------------------------------------------------*/
-/* Find string s2 within string s1 */
-
-static char *
-strnsrch (s1, s2, ls1)
-
-char	*s1;	/* String to search */
-char	*s2;	/* String to look for */
-int	ls1;	/* Length of string being searched */
-
-{
-    char *s,*s1e;
-    char cfirst,clast;
-    int i,ls2;
-
-    /* Return null string if either pointer is NULL */
-    if (s1 == NULL || s2 == NULL)
-	return (NULL);
-
-    /* A zero-length pattern is found in any string */
-    ls2 = strlen (s2);
-    if (ls2 ==0)
-	return (s1);
-
-    /* Only a zero-length string can be found in a zero-length string */
-    if (ls1 ==0)
-	return (NULL);
-
-    cfirst = s2[0];
-    clast = s2[ls2-1];
-    s1e = s1 + ls1 - ls2 + 1;
-    s = s1;
-    while (s < s1e) { 
-
-	/* Search for first character in pattern string */
-	if (*s == cfirst) {
-
-	    /* If single character search, return */
-	    if (ls2 == 1)
-		return (s);
-
-	    /* Search for last character in pattern string if first found */
-	    if (s[ls2-1] == clast) {
-
-		/* If two-character search, return */
-		if (ls2 == 2)
-		    return (s);
-
-		/* If 3 or more characters, check for rest of search string */
-		i = 1;
-		while (i < ls2 && s[i] == s2[i])
-		    i++;
-
-		/* If entire string matches, return */
-		if (i >= ls2)
-		    return (s);
-		}
-	    }
-	s++;
-	}
-    return (NULL);
-}
-
-/*-------------------------------------------------------------------*/
-/*             the following routines were originally in hget.c      */
-/*-------------------------------------------------------------------*/
-/*  HPUTI4 - Set int keyword = ival in FITS header string */
-
-static void
-hputi4 (hstring,keyword,ival)
-
-  char *hstring;	/* character string containing FITS-style header
-			   information in the format
-			   =  {/ }
-			   each entry is padded with spaces to 80 characters */
-
-  char *keyword;		/* character string containing the name of the variable
-			   to be returned.  hput searches for a line beginning
-			   with this string, and if there isn't one, creates one.
-		   	   The first 8 characters of keyword must be unique. */
-  int ival;		/* int number */
-{
-    char value[30];
-
-    /* Translate value from binary to ASCII */
-    sprintf (value,"%d",ival);
-
-    /* Put value into header string */
-    hputc (hstring,keyword,value);
-
-    /* Return to calling program */
-    return;
-}
-
-/*-------------------------------------------------------------------*/
-
-/*  HPUTL - Set keyword = F if lval=0, else T, in FITS header string */
-
-static void
-hputl (hstring, keyword,lval)
-
-char *hstring;		/* FITS header */
-char *keyword;		/* Keyword name */
-int lval;		/* logical variable (0=false, else true) */
-{
-    char value[8];
-
-    /* Translate value from binary to ASCII */
-    if (lval)
-	strcpy (value, "T");
-    else
-	strcpy (value, "F");
-
-    /* Put value into header string */
-    hputc (hstring,keyword,value);
-
-    /* Return to calling program */
-    return;
-}
-
-/*-------------------------------------------------------------------*/
-
-/*  HPUTS - Set character string keyword = 'cval' in FITS header string */
-
-static void
-hputs (hstring,keyword,cval)
-
-char *hstring;	/* FITS header */
-char *keyword;	/* Keyword name */
-char *cval;	/* character string containing the value for variable
-		   keyword.  trailing and leading blanks are removed.  */
-{
-    char squot = 39;
-    char value[70];
-    int lcval;
-
-    /*  find length of variable string */
-
-    lcval = strlen (cval);
-    if (lcval > 67)
-	lcval = 67;
-
-    /* Put quotes around string */
-    value[0] = squot;
-    strncpy (&value[1],cval,lcval);
-    value[lcval+1] = squot;
-    value[lcval+2] = 0;
-
-    /* Put value into header string */
-    hputc (hstring,keyword,value);
-
-    /* Return to calling program */
-    return;
-}
-
-/*---------------------------------------------------------------------*/
-/*  HPUTC - Set character string keyword = value in FITS header string */
-
-static void
-hputc (hstring,keyword,value)
-
-char *hstring;
-char *keyword;
-char *value;	/* character string containing the value for variable
-		   keyword.  trailing and leading blanks are removed.  */
-{
-    char squot = 39;
-    char line[100];
-    char newcom[50];
-    char blank[80];
-    char *v, *vp, *v1, *v2, *q1, *q2, *c1, *ve;
-    int lkeyword, lcom, lval, lc, i;
-
-    for (i = 0; i < 80; i++)
-	blank[i] = ' ';
-
-    /*  find length of keyword and value */
-    lkeyword = strlen (keyword);
-    lval = strlen (value);
-
-    /*  If COMMENT or HISTORY, always add it just before the END */
-    if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 ||
-	strncmp (keyword,"HISTORY",7) == 0)) {
-
-	/* Find end of header */
-	v1 = ksearch (hstring,"END");
-	v2 = v1 + 80;
-
-	/* Move END down one line */
-	strncpy (v2, v1, 80);
-
-	/* Insert keyword */
-	strncpy (v1,keyword,7);
-
-	/* Pad with spaces */
-	for (vp = v1+lkeyword; vp < v2; vp++)
-	    *vp = ' ';
-
-	/* Insert comment */
-	strncpy (v1+9,value,lval);
-	return;
-	}
-
-    /* Otherwise search for keyword */
-    else
-	v1 = ksearch (hstring,keyword);
-
-    /*  If parameter is not found, find a place to put it */
-    if (v1 == NULL) {
-	
-	/* First look for blank lines before END */
-        v1 = blsearch (hstring, "END");
-    
-	/*  Otherwise, create a space for it at the end of the header */
-	if (v1 == NULL) {
-	    ve = ksearch (hstring,"END");
-	    v1 = ve;
-	    v2 = v1 + 80;
-	    strncpy (v2, ve, 80);
-	    }
-	else
-	    v2 = v1 + 80;
-	lcom = 0;
-	newcom[0] = 0;
-	}
-
-    /*  Otherwise, extract the entry for this keyword from the header */
-    else {
-	strncpy (line, v1, 80);
-	line[80] = 0;
-	v2 = v1 + 80;
-
-	/*  check for quoted value */
-	q1 = strchr (line, squot);
-	if (q1 != NULL)
-	    q2 = strchr (q1+1,squot);
-	else
-	    q2 = line;
-
-	/*  extract comment and remove trailing spaces */
-
-	c1 = strchr (q2,'/');
-	if (c1 != NULL) {
-	    lcom = 80 - (c1 - line);
-	    strncpy (newcom, c1+1, lcom);
-	    vp = newcom + lcom - 1;
-	    while (vp-- > newcom && *vp == ' ')
-		*vp = 0;
-	    lcom = strlen (newcom);
-	    }
-	else {
-	    newcom[0] = 0;
-	    lcom = 0;
-	    }
-	}
-
-    /* Fill new entry with spaces */
-    for (vp = v1; vp < v2; vp++)
-	*vp = ' ';
-
-    /*  Copy keyword to new entry */
-    strncpy (v1, keyword, lkeyword);
-
-    /*  Add parameter value in the appropriate place */
-    vp = v1 + 8;
-    *vp = '=';
-    vp = v1 + 9;
-    *vp = ' ';
-    vp = vp + 1;
-    if (*value == squot) {
-	strncpy (vp, value, lval);
-	if (lval+12 > 31)
-	    lc = lval + 12;
-	else
-	    lc = 30;
-	}
-    else {
-	vp = v1 + 30 - lval;
-	strncpy (vp, value, lval);
-	lc = 30;
-	}
-
-    /* Add comment in the appropriate place */
-	if (lcom > 0) {
-	    if (lc+2+lcom > 80)
-		lcom = 78 - lc;
-	    vp = v1 + lc + 2;     /* Jul 16 1997: was vp = v1 + lc * 2 */
-	    *vp = '/';
-	    vp = vp + 1;
-	    strncpy (vp, newcom, lcom);
-	    for (v = vp + lcom; v < v2; v++)
-		*v = ' ';
-	    }
-
-	return;
-}
-
-/*-------------------------------------------------------------------*/
-/*  HPUTCOM - Set comment for keyword or on line in FITS header string */
-
-static void
-hputcom (hstring,keyword,comment)
-
-  char *hstring;
-  char *keyword;
-  char *comment;
-{
-	char squot;
-	char line[100];
-	int lkeyword, lcom;
-	char *vp, *v1, *v2, *c0 = NULL, *c1, *q1, *q2;
-
-	squot = 39;
-
-/*  Find length of variable name */
-	lkeyword = strlen (keyword);
-
-/*  If COMMENT or HISTORY, always add it just before the END */
-	if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 ||
-	    strncmp (keyword,"HISTORY",7) == 0)) {
-
-	/* Find end of header */
-	    v1 = ksearch (hstring,"END");
-	    v2 = v1 + 80;
-	    strncpy (v2, v1, 80);
-
-	/*  blank out new line and insert keyword */
-	    for (vp = v1; vp < v2; vp++)
-		*vp = ' ';
-	    strncpy (v1, keyword, lkeyword);
-	    }
-
-/* search header string for variable name */
-	else {
-	    v1 = ksearch (hstring,keyword);
-	    v2 = v1 + 80;
-
-	/* if parameter is not found, return without doing anything */
-	    if (v1 == NULL) {
-		return;
-		}
-
-	/* otherwise, extract entry for this variable from the header */
-	    strncpy (line, v1, 80);
-
-	/* check for quoted value */
-	    q1 = strchr (line,squot);
-	    if (q1 != NULL)
-		q2 = strchr (q1+1,squot);
-	    else
-		q2 = NULL;
-
-	    if (q2 == NULL || q2-line < 31)
-		c0 = v1 + 31;
-	    else
-		c0 = v1 + (q2-line) + 2; /* allan: 1997-09-30, was c0=q2+2 */
-
-	    strncpy (c0, "/ ",2);
-	    }
-
-/* create new entry */
-	lcom = strlen (comment);
-
-	if (lcom > 0) {
-	    c1 = c0 + 2;
-	    if (c1+lcom > v2)
-		lcom = v2 - c1;
-	    strncpy (c1, comment, lcom);
-	    }
-
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/iter_a.c b/src/external/OpenGR/3rdparty/cfitsio/iter_a.c
deleted file mode 100644
index 19ea1d1c3..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/iter_a.c
+++ /dev/null
@@ -1,147 +0,0 @@
-#include 
-#include 
-#include 
-#include "fitsio.h"
-
-/*
-  This program illustrates how to use the CFITSIO iterator function.
-  It reads and modifies the input 'iter_a.fit' file by computing a
-  value for the 'rate' column as a function of the values in the other
-  'counts' and 'time' columns.
-*/
-main()
-{
-    extern flux_rate(); /* external work function is passed to the iterator */
-    fitsfile *fptr;
-    iteratorCol cols[3];  /* structure used by the iterator function */
-    int n_cols;
-    long rows_per_loop, offset;
-
-    int status, nkeys, keypos, hdutype, ii, jj;
-    char filename[]  = "iter_a.fit";     /* name of rate FITS file */
-
-    status = 0; 
-
-    fits_open_file(&fptr, filename, READWRITE, &status); /* open file */
-
-    /* move to the desired binary table extension */
-    if (fits_movnam_hdu(fptr, BINARY_TBL, "RATE", 0, &status) )
-        fits_report_error(stderr, status);    /* print out error messages */
-
-    n_cols  = 3;   /* number of columns */
-
-    /* define input column structure members for the iterator function */
-    fits_iter_set_by_name(&cols[0], fptr, "COUNTS", TLONG,  InputCol);
-    fits_iter_set_by_name(&cols[1], fptr, "TIME",   TFLOAT, InputCol);
-    fits_iter_set_by_name(&cols[2], fptr, "RATE",   TFLOAT, OutputCol);
-
-    rows_per_loop = 0;  /* use default optimum number of rows */
-    offset = 0;         /* process all the rows */
-
-    /* apply the rate function to each row of the table */
-    printf("Calling iterator function...%d\n", status);
-
-    fits_iterate_data(n_cols, cols, offset, rows_per_loop,
-                      flux_rate, 0L, &status);
-
-    fits_close_file(fptr, &status);      /* all done */
-
-    if (status)
-        fits_report_error(stderr, status);  /* print out error messages */
-
-    return(status);
-}
-/*--------------------------------------------------------------------------*/
-int flux_rate(long totalrows, long offset, long firstrow, long nrows,
-             int ncols, iteratorCol *cols, void *user_strct ) 
-
-/*
-   Sample iterator function that calculates the output flux 'rate' column
-   by dividing the input 'counts' by the 'time' column.
-   It also applies a constant deadtime correction factor if the 'deadtime'
-   keyword exists.  Finally, this creates or updates the 'LIVETIME'
-   keyword with the sum of all the individual integration times.
-*/
-{
-    int ii, status = 0;
-
-    /* declare variables static to preserve their values between calls */
-    static long *counts;
-    static float *interval;
-    static float *rate;
-    static float deadtime, livetime; /* must preserve values between calls */
-
-    /*--------------------------------------------------------*/
-    /*  Initialization procedures: execute on the first call  */
-    /*--------------------------------------------------------*/
-    if (firstrow == 1)
-    {
-       if (ncols != 3)
-           return(-1);  /* number of columns incorrect */
-
-       if (fits_iter_get_datatype(&cols[0]) != TLONG  ||
-           fits_iter_get_datatype(&cols[1]) != TFLOAT ||
-           fits_iter_get_datatype(&cols[2]) != TFLOAT )
-           return(-2);  /* bad data type */
-
-       /* assign the input pointers to the appropriate arrays and null ptrs*/
-       counts       = (long *)  fits_iter_get_array(&cols[0]);
-       interval     = (float *) fits_iter_get_array(&cols[1]);
-       rate         = (float *) fits_iter_get_array(&cols[2]);
-
-       livetime = 0;  /* initialize the total integration time */
-
-       /* try to get the deadtime keyword value */
-       fits_read_key(cols[0].fptr, TFLOAT, "DEADTIME", &deadtime, '\0',
-                     &status);
-       if (status)
-       {
-           deadtime = 1.0;  /* default deadtime if keyword doesn't exist */
-       }
-       else if (deadtime < 0. || deadtime > 1.0)
-       {
-           return(-1);    /* bad deadtime value */
-       }
-
-       printf("deadtime = %f\n", deadtime);
-    }
-
-    /*--------------------------------------------*/
-    /*  Main loop: process all the rows of data */
-    /*--------------------------------------------*/
-
-    /*  NOTE: 1st element of array is the null pixel value!  */
-    /*  Loop from 1 to nrows, not 0 to nrows - 1.  */
-
-    /* this version tests for null values */
-    rate[0] = DOUBLENULLVALUE;   /* define the value that represents null */
-
-    for (ii = 1; ii <= nrows; ii++)
-    {
-       if (counts[ii] == counts[0])   /*  undefined counts value? */
-       {
-           rate[ii] = DOUBLENULLVALUE;
-       }
-       else if (interval[ii] > 0.)
-       {
-           rate[ii] = counts[ii] / interval[ii] / deadtime;
-           livetime += interval[ii];  /* accumulate total integration time */
-       }
-       else
-           return(-2);  /* bad integration time */
-    }
-
-    /*-------------------------------------------------------*/
-    /*  Clean up procedures:  after processing all the rows  */
-    /*-------------------------------------------------------*/
-
-    if (firstrow + nrows - 1 == totalrows)
-    {
-        /*  update the LIVETIME keyword value */
-
-        fits_update_key(cols[0].fptr, TFLOAT, "LIVETIME", &livetime, 
-                 "total integration time", &status);
-        printf("livetime = %f\n", livetime);
-   }
-    return(0);  /* return successful status */
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/iter_a.f b/src/external/OpenGR/3rdparty/cfitsio/iter_a.f
deleted file mode 100644
index e62218973..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/iter_a.f
+++ /dev/null
@@ -1,224 +0,0 @@
-      program f77iterate_a
-
-      external flux_rate
-      integer ncols
-      parameter (ncols=3)
-      integer units(ncols), colnum(ncols), datatype(ncols)
-      integer iotype(ncols), offset, rows_per_loop, status
-      character*70 colname(ncols)
-      integer iunit, blocksize
-      character*80 fname
-
-C     include f77.inc -------------------------------------
-C     Codes for FITS extension types
-      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
-      parameter (
-     &     IMAGE_HDU  = 0,
-     &     ASCII_TBL  = 1,
-     &     BINARY_TBL = 2  )
-
-C     Codes for FITS table data types
-
-      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
-      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
-      parameter (
-     &     TBIT        =   1,
-     &     TBYTE       =  11,
-     &     TLOGICAL    =  14,
-     &     TSTRING     =  16,
-     &     TSHORT      =  21,
-     &     TINT        =  31,
-     &     TFLOAT      =  42,
-     &     TDOUBLE     =  82,
-     &     TCOMPLEX    =  83,
-     &     TDBLCOMPLEX = 163  )
-
-C     Codes for iterator column types
-
-      integer InputCol, InputOutputCol, OutputCol
-      parameter (
-     &     InputCol       = 0,
-     &     InputOutputCol = 1,
-     &     OutputCol      = 2  )
-C     End of f77.inc -------------------------------------
-
-
-      iunit = 15
-
-      units(1) = iunit
-      units(2) = iunit
-      units(3) = iunit
-
-C open the file
-      fname = 'iter_a.fit'
-      call ftopen(iunit,fname,1,blocksize,status)
-
-C move to the HDU containing the rate table
-      call ftmnhd(iunit, BINARY_TBL, 'RATE', 0, status)
-
-C Select iotypes for column data
-      iotype(1) = InputCol
-      iotype(2) = InputCol
-      iotype(3) = OutputCol
-
-C Select desired datatypes for column data
-      datatype(1) = TINT
-      datatype(2) = TFLOAT
-      datatype(3) = TFLOAT
-
-C find the column number corresponding to each column
-      call ftgcno( iunit, 0, 'counts', colnum(1), status )
-      call ftgcno( iunit, 0, 'time', colnum(2), status )
-      call ftgcno( iunit, 0, 'rate', colnum(3), status )
-
-C use default optimum number of rows
-      rows_per_loop = 0
-      offset = 0
-
-C apply the rate function to each row of the table
-      print *, 'Calling iterator function...', status
-
-C although colname is not being used, still need to send a string
-C array in the function
-      call ftiter( ncols, units, colnum, colname, datatype, iotype,
-     &      offset, rows_per_loop, flux_rate, 3, status )
-
-      call ftclos(iunit, status)
-      stop
-      end
-
-C***************************************************************************
-C   Sample iterator function that calculates the output flux 'rate' column
-C   by dividing the input 'counts' by the 'time' column.
-C   It also applies a constant deadtime correction factor if the 'deadtime'
-C   keyword exists.  Finally, this creates or updates the 'LIVETIME'
-C   keyword with the sum of all the individual integration times.
-C***************************************************************************
-      subroutine flux_rate(totalrows, offset, firstrow, nrows, ncols,
-     &     units, colnum, datatype, iotype, repeat, status, userData,
-     &     counts, interval, rate )
-
-      integer totalrows, offset, firstrow, nrows, ncols
-      integer units(ncols), colnum(ncols), datatype(ncols)
-      integer iotype(ncols), repeat(ncols)
-      integer userData
-
-C     include f77.inc -------------------------------------
-C     Codes for FITS extension types
-      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
-      parameter (
-     &     IMAGE_HDU  = 0,
-     &     ASCII_TBL  = 1,
-     &     BINARY_TBL = 2  )
-
-C     Codes for FITS table data types
-
-      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
-      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
-      parameter (
-     &     TBIT        =   1,
-     &     TBYTE       =  11,
-     &     TLOGICAL    =  14,
-     &     TSTRING     =  16,
-     &     TSHORT      =  21,
-     &     TINT        =  31,
-     &     TFLOAT      =  42,
-     &     TDOUBLE     =  82,
-     &     TCOMPLEX    =  83,
-     &     TDBLCOMPLEX = 163  )
-
-C     Codes for iterator column types
-
-      integer InputCol, InputOutputCol, OutputCol
-      parameter (
-     &     InputCol       = 0,
-     &     InputOutputCol = 1,
-     &     OutputCol      = 2  )
-C     End of f77.inc -------------------------------------
-
-      integer counts(*)
-      real interval(*),rate(*)
-
-      integer ii, status
-      character*80 comment
-
-C**********************************************************************
-C  must preserve these values between calls
-      real deadtime, livetime
-      common /fluxblock/ deadtime, livetime
-C**********************************************************************
-
-      if (status .ne. 0) return
-
-C    --------------------------------------------------------
-C      Initialization procedures: execute on the first call  
-C    --------------------------------------------------------
-      if (firstrow .eq. 1) then
-         if (ncols .ne. 3) then
-C     wrong number of columns
-            status = -1
-            return
-         endif
-
-         if (datatype(1).ne.TINT .or. datatype(2).ne.TFLOAT .or.
-     &        datatype(3).ne.TFLOAT ) then
-C     bad data type
-            status = -2
-            return
-         endif
-
-C     try to get the deadtime keyword value
-         call ftgkye( units(1), 'DEADTIME', deadtime, comment, status )
-
-         if (status.ne.0) then
-C     default deadtime if keyword doesn't exist
-            deadtime = 1.0
-            status = 0
-         elseif (deadtime .lt. 0.0 .or. deadtime .gt. 1.0) then
-C     bad deadtime value
-            status = -3
-            return
-         endif
-
-         print *, 'deadtime = ', deadtime
-
-         livetime = 0.0
-      endif
-
-C    --------------------------------------------
-C      Main loop: process all the rows of data
-C    --------------------------------------------
-      
-C     NOTE: 1st element of array is the null pixel value!
-C     Loop over elements 2 to nrows+1, not 1 to nrows.
-      
-C     this version ignores null values
-
-C     set the output null value to zero to ignore nulls */
-      rate(1) = 0.0
-      do 10 ii = 2,nrows+1
-         if ( interval(ii) .gt. 0.0) then
-           rate(ii) = counts(ii) / interval(ii) / deadtime
-           livetime = livetime + interval(ii)
-        else
-C     Nonsensical negative time interval
-           status = -3
-           return
-        endif
- 10   continue
-
-C    -------------------------------------------------------
-C      Clean up procedures:  after processing all the rows  
-C    -------------------------------------------------------
-
-      if (firstrow + nrows - 1 .eq. totalrows) then
-C     update the LIVETIME keyword value
-
-         call ftukye( units(1),'LIVETIME', livetime, 3,
-     &        'total integration time', status )
-         print *,'livetime = ', livetime
-
-      endif
- 
-      return
-      end
diff --git a/src/external/OpenGR/3rdparty/cfitsio/iter_a.fit b/src/external/OpenGR/3rdparty/cfitsio/iter_a.fit
deleted file mode 100644
index 0f951cfdc..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/iter_a.fit
+++ /dev/null
@@ -1,1111 +0,0 @@
-SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    0 / number of data axes                            EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format defined in Astronomy andCOMMENT   Astrophysics Supplement Series v44/p363, v44/p371, v73/p359, v73/p365.COMMENT   Contact the NASA Science Office of Standards and Technology for the   COMMENT   FITS Definition document #100 and other FITS information.             HISTORY    TASK:FMERGE on file ratefile.fits                                    HISTORY   fmerge3.1c at 29/12/97 16:1:37.                                       HISTORY    TASK:FMERGE on file m1.fits                                          HISTORY   fmerge3.1c at 29/12/97 16:2:30.                                       HISTORY    TASK:FMERGE on file m3.fits                                          HISTORY   fmerge3.1c at 29/12/97 16:3:38.                                       HISTORY    TASK:FMERGE on file m5.fits                                          HISTORY   fmerge3.1c at 29/12/97 16:4:15.                                       HISTORY    TASK:FMERGE on file m7.fits                                          HISTORY   fmerge3.1c at 29/12/97 16:5:1.0                                       HISTORY    TASK:FMERGE on file m9.fits                                          HISTORY   fmerge3.1c at 29/12/97 16:6:48.                                       END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'BINTABLE'           / binary table extension                         BITPIX  =                    8 / 8-bit bytes                                    NAXIS   =                    2 / 2-dimensional binary table                     NAXIS1  =                   12 / width of table in bytes                        NAXIS2  =                10000 / number of rows in table                        PCOUNT  =                    0 / size of special data area                      GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                    3 / number of fields in each row                   TTYPE1  = 'Counts  '           / label for field   1                            TFORM1  = 'J       '           / data format of field: 4-byte INTEGER           TTYPE2  = 'Time    '           / label for field   2                            TFORM2  = 'E       '           / data format of field: 4-byte REAL              TTYPE3  = 'Rate    '           / label for field   3                            TFORM3  = 'E       '           / data format of field: 4-byte REAL              EXTNAME = 'rate    '           / name of this binary table extension            DEADTIME=                  1.0                                                  HISTORY   This FITS file was created by the FCREATE task.                       HISTORY   fcreate3.1 at 29/12/97                                                HISTORY   File modified by user 'pence' with fv  on 97-12-29T15:45:06           HISTORY   File modified by user 'pence' with fv  on 97-12-29T15:54:30           LIVETIME=              30554.5 / total integration time                         HISTORY    TASK:FMERGE copied   26924 rows from file ratefile.fits              HISTORY    TASK:FMERGE appended   26924 rows from file r2.fits                  HISTORY    TASK:FMERGE copied   53848 rows from file m1.fits                    HISTORY    TASK:FMERGE appended   53848 rows from file m2.fits                  HISTORY    TASK:FMERGE copied  107696 rows from file m3.fits                    HISTORY    TASK:FMERGE appended  107696 rows from file m4.fits                  HISTORY    TASK:FMERGE copied  215392 rows from file m5.fits                    HISTORY    TASK:FMERGE appended  215392 rows from file m6.fits                  HISTORY    TASK:FMERGE copied  430784 rows from file m7.fits                    HISTORY    TASK:FMERGE appended  430784 rows from file m8.fits                  HISTORY    TASK:FMERGE copied  861568 rows from file m9.fits                    HISTORY    TASK:FMERGE appended  861568 rows from file m10.fits                 HISTORY   File modified by user 'pence' with fv  on 97-12-30T10:44:37           HISTORY   File modified by user 'pence' with fv  on 97-12-30T10:51:44           HISTORY   ftabcopy V4.0a copied columns from ratefile.fits                      HISTORY   ftabcopy V4.0a at 5/1/98 23:10:24                                     END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@@@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@@@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@?@dA A ?@?@@@AUU-@@
-?A @@?@
\ No newline at end of file
diff --git a/src/external/OpenGR/3rdparty/cfitsio/iter_b.c b/src/external/OpenGR/3rdparty/cfitsio/iter_b.c
deleted file mode 100644
index 296f4e16d..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/iter_b.c
+++ /dev/null
@@ -1,114 +0,0 @@
-#include 
-#include 
-#include 
-#include "fitsio.h"
-
-/*
-  This program illustrates how to use the CFITSIO iterator function.
-  It simply prints out the values in a character string and a logical
-  type column in a table, and toggles the value in the logical column
-  so that T -> F and F -> T.
-*/
-main()
-{
-    extern str_iter(); /* external work function is passed to the iterator */
-    fitsfile *fptr;
-    iteratorCol cols[2];
-    int n_cols;
-    long rows_per_loop, offset;
-    int status = 0;
-    char filename[]  = "iter_b.fit";     /* name of rate FITS file */
-
-    /* open the file and move to the correct extension */
-    fits_open_file(&fptr, filename, READWRITE, &status);
-    fits_movnam_hdu(fptr, BINARY_TBL, "iter_test", 0, &status);
-
-    /* define input column structure members for the iterator function */
-    n_cols  = 2;   /* number of columns */
-
-    /* define input column structure members for the iterator function */
-    fits_iter_set_by_name(&cols[0], fptr, "Avalue", TSTRING,  InputOutputCol);
-    fits_iter_set_by_name(&cols[1], fptr, "Lvalue", TLOGICAL, InputOutputCol);
-
-    rows_per_loop = 0;  /* use default optimum number of rows */
-    offset = 0;         /* process all the rows */
-
-    /* apply the  function to each row of the table */
-    printf("Calling iterator function...%d\n", status);
-
-    fits_iterate_data(n_cols, cols, offset, rows_per_loop,
-                      str_iter, 0L, &status);
-
-    fits_close_file(fptr, &status);      /* all done */
-
-    if (status)
-       fits_report_error(stderr, status); /* print out error messages */
-
-    return(status);
-}
-/*--------------------------------------------------------------------------*/
-int str_iter(long totalrows, long offset, long firstrow, long nrows,
-             int ncols, iteratorCol *cols, void *user_strct )
-
-/*
-   Sample iterator function.
-*/
-{
-    int ii;
-
-    /* declare variables static to preserve their values between calls */
-    static char **stringvals;
-    static char *logicalvals;
-
-    /*--------------------------------------------------------*/
-    /*  Initialization procedures: execute on the first call  */
-    /*--------------------------------------------------------*/
-    if (firstrow == 1)
-    {
-       if (ncols != 2)
-           return(-1);  /* number of columns incorrect */
-
-       if (fits_iter_get_datatype(&cols[0]) != TSTRING ||
-           fits_iter_get_datatype(&cols[1]) != TLOGICAL )
-           return(-2);  /* bad data type */
-
-       /* assign the input pointers to the appropriate arrays */
-       stringvals       = (char **) fits_iter_get_array(&cols[0]);
-       logicalvals      = (char *)  fits_iter_get_array(&cols[1]);
-
-       printf("Total rows, No. rows = %d %d\n",totalrows, nrows);
-    }
-
-    /*------------------------------------------*/
-    /*  Main loop: process all the rows of data */
-    /*------------------------------------------*/
-
-    /*  NOTE: 1st element of array is the null pixel value!  */
-    /*  Loop from 1 to nrows, not 0 to nrows - 1.  */
-   
-    for (ii = 1; ii <= nrows; ii++)
-    {
-      printf("%s %d\n", stringvals[ii], logicalvals[ii]);
-      if (logicalvals[ii])
-      {
-         logicalvals[ii] = FALSE;
-         strcpy(stringvals[ii], "changed to false");
-      }
-      else
-      {
-         logicalvals[ii] = TRUE;
-         strcpy(stringvals[ii], "changed to true");
-      }
-    }
-
-    /*-------------------------------------------------------*/
-    /*  Clean up procedures:  after processing all the rows  */
-    /*-------------------------------------------------------*/
-
-    if (firstrow + nrows - 1 == totalrows)
-    {
-      /* no action required in this case */
-    }
- 
-    return(0);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/iter_b.f b/src/external/OpenGR/3rdparty/cfitsio/iter_b.f
deleted file mode 100644
index 7a2a6e7df..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/iter_b.f
+++ /dev/null
@@ -1,193 +0,0 @@
-      program f77iterate_b
-
-C     external work function is passed to the iterator
-      external str_iter
-
-      integer ncols
-      parameter (ncols=2)
-      integer units(ncols), colnum(ncols), datatype(ncols)
-      integer iotype(ncols), offset, rows_per_loop, status
-      character*70 colname(ncols)
-
-      integer iunit, blocksize
-      character*80 fname
-
-C     include f77.inc -------------------------------------
-C     Codes for FITS extension types
-      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
-      parameter (
-     &     IMAGE_HDU  = 0,
-     &     ASCII_TBL  = 1,
-     &     BINARY_TBL = 2  )
-
-C     Codes for FITS table data types
-
-      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
-      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
-      parameter (
-     &     TBIT        =   1,
-     &     TBYTE       =  11,
-     &     TLOGICAL    =  14,
-     &     TSTRING     =  16,
-     &     TSHORT      =  21,
-     &     TINT        =  31,
-     &     TFLOAT      =  42,
-     &     TDOUBLE     =  82,
-     &     TCOMPLEX    =  83,
-     &     TDBLCOMPLEX = 163  )
-
-C     Codes for iterator column types
-
-      integer InputCol, InputOutputCol, OutputCol
-      parameter (
-     &     InputCol       = 0,
-     &     InputOutputCol = 1,
-     &     OutputCol      = 2  )
-C     End of f77.inc -------------------------------------
-
-      status = 0
-
-      fname = 'iter_b.fit'
-      iunit = 15
-
-C     both columns are in the same FITS file
-      units(1) = iunit
-      units(2) = iunit
-
-C     open the file and move to the correct extension
-      call ftopen(iunit,fname,1,blocksize,status)
-      call ftmnhd(iunit, BINARY_TBL, 'iter_test', 0, status)
-
-C     define the desired columns by name
-      colname(1) = 'Avalue'
-      colname(2) = 'Lvalue'
-
-C     leave column numbers undefined
-      colnum(1) = 0
-      colnum(2) = 0  
-
-C     define the desired datatype for each column: TSTRING & TLOGICAL
-      datatype(1) = TSTRING
-      datatype(2) = TLOGICAL
-
-C     define whether columns are input, input/output, or output only
-C     Both in/out
-      iotype(1) = InputOutputCol
-      iotype(2) = InputOutputCol
- 
-C     use default optimum number of rows and process all the rows
-      rows_per_loop = 0
-      offset = 0
-
-C     apply the  function to each row of the table
-      print *,'Calling iterator function...', status
-
-      call ftiter( ncols, units, colnum, colname, datatype, iotype,
-     &      offset, rows_per_loop, str_iter, 0, status )
-
-      call ftclos(iunit, status)
-
-C     print out error messages if problem
-      if (status.ne.0) call ftrprt('STDERR', status)
-      stop
-      end
-
-C--------------------------------------------------------------------------
-C
-C   Sample iterator function.
-C
-C--------------------------------------------------------------------------
-      subroutine str_iter(totalrows, offset, firstrow, nrows, ncols,
-     &     units, colnum, datatype, iotype, repeat, status, 
-     &     userData, stringCol, logicalCol )
-
-      integer totalrows,offset,firstrow,nrows,ncols,status
-      integer units(*),colnum(*),datatype(*),iotype(*),repeat(*)
-      integer userData
-      character*(*) stringCol(*)
-      logical logicalCol(*)
-
-      integer ii
-
-C     include f77.inc -------------------------------------
-C     Codes for FITS extension types
-      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
-      parameter (
-     &     IMAGE_HDU  = 0,
-     &     ASCII_TBL  = 1,
-     &     BINARY_TBL = 2  )
-
-C     Codes for FITS table data types
-
-      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
-      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
-      parameter (
-     &     TBIT        =   1,
-     &     TBYTE       =  11,
-     &     TLOGICAL    =  14,
-     &     TSTRING     =  16,
-     &     TSHORT      =  21,
-     &     TINT        =  31,
-     &     TFLOAT      =  42,
-     &     TDOUBLE     =  82,
-     &     TCOMPLEX    =  83,
-     &     TDBLCOMPLEX = 163  )
-
-C     Codes for iterator column types
-
-      integer InputCol, InputOutputCol, OutputCol
-      parameter (
-     &     InputCol       = 0,
-     &     InputOutputCol = 1,
-     &     OutputCol      = 2  )
-C     End of f77.inc -------------------------------------
-
-      if (status .ne. 0) return
-
-C    --------------------------------------------------------
-C      Initialization procedures: execute on the first call  
-C    --------------------------------------------------------
-      if (firstrow .eq. 1) then
-         if (ncols .ne. 2) then
-            status = -1
-            return
-         endif
-         
-         if (datatype(1).ne.TSTRING .or. datatype(2).ne.TLOGICAL) then
-            status = -2
-            return
-         endif
-         
-         print *,'Total rows, No. rows = ',totalrows, nrows
-         
-      endif
-      
-C     -------------------------------------------
-C       Main loop: process all the rows of data 
-C     -------------------------------------------
-      
-C     NOTE: 1st element of array is the null pixel value!
-C     Loop over elements 2 to nrows+1, not 1 to nrows.
-      
-      do 10 ii=2,nrows+1
-         print *, stringCol(ii), logicalCol(ii)
-         if( logicalCol(ii) ) then
-            logicalCol(ii) = .false.
-            stringCol(ii) = 'changed to false'
-         else
-            logicalCol(ii) = .true.
-            stringCol(ii) = 'changed to true'
-         endif
- 10   continue
-      
-C     -------------------------------------------------------
-C     Clean up procedures:  after processing all the rows  
-C     -------------------------------------------------------
-      
-      if (firstrow + nrows - 1 .eq. totalrows) then
-C     no action required in this case
-      endif
-      
-      return
-      end
-      
diff --git a/src/external/OpenGR/3rdparty/cfitsio/iter_b.fit b/src/external/OpenGR/3rdparty/cfitsio/iter_b.fit
deleted file mode 100644
index 74dcd9d62..000000000
Binary files a/src/external/OpenGR/3rdparty/cfitsio/iter_b.fit and /dev/null differ
diff --git a/src/external/OpenGR/3rdparty/cfitsio/iter_c.c b/src/external/OpenGR/3rdparty/cfitsio/iter_c.c
deleted file mode 100644
index bbf977423..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/iter_c.c
+++ /dev/null
@@ -1,171 +0,0 @@
-#include 
-#include 
-#include 
-#include "fitsio.h"
-
-/*
-    This example program illustrates how to use the CFITSIO iterator function.
-
-    This program creates a 2D histogram of the X and Y columns of an event
-    list.  The 'main' routine just creates the empty new image, then executes
-    the 'writehisto' work function by calling the CFITSIO iterator function.
-
-    'writehisto' opens the FITS event list that contains the X and Y columns.
-    It then calls a second work function, calchisto, (by recursively calling
-    the CFITSIO iterator function) which actually computes the 2D histogram.
-*/
-
-/*   Globally defined parameters */
-
-long xsize = 480; /* size of the histogram image */
-long ysize = 480;
-long xbinsize = 32;
-long ybinsize = 32;
-
-main()
-{
-    extern writehisto();  /* external work function passed to the iterator */
-    extern long xsize, ysize;  /* size of image */
-
-    fitsfile *fptr;
-    iteratorCol cols[1];
-    int n_cols, status = 0;
-    long n_per_loop, offset, naxes[2];
-    char filename[]  = "histoimg.fit";     /* name of FITS image */
-
-    remove(filename);   /* delete previous version of the file if it exists */
-    fits_create_file(&fptr, filename, &status);  /* create new output image */
-
-    naxes[0] = xsize;
-    naxes[1] = ysize;
-    fits_create_img(fptr, LONG_IMG, 2, naxes, &status); /* create primary HDU */
-
-    n_cols  = 1;   /* number of columns */
-
-    /* define input column structure members for the iterator function */
-    fits_iter_set_by_name(&cols[0], fptr, " ", TLONG, OutputCol);
-
-    n_per_loop = -1;  /* force whole array to be passed at one time */
-    offset = 0;       /* don't skip over any pixels */
-
-    /* execute the function to create and write the 2D histogram */
-    printf("Calling writehisto iterator work function... %d\n", status);
-
-    fits_iterate_data(n_cols, cols, offset, n_per_loop,
-                      writehisto, 0L, &status);
-
-    fits_close_file(fptr, &status);      /* all done; close the file */
-
-    if (status)
-        fits_report_error(stderr, status);  /* print out error messages */
-    else
-        printf("Program completed successfully.\n");
-
-    return(status);
-}
-/*--------------------------------------------------------------------------*/
-int writehisto(long totaln, long offset, long firstn, long nvalues,
-             int narrays, iteratorCol *histo, void *userPointer)
-/*
-   Iterator work function that writes out the 2D histogram.
-   The histogram values are calculated by another work function, calchisto.
-
-   This routine is executed only once since nvalues was forced to = totaln.
-*/
-{
-    extern calchisto();  /* external function called by the iterator */
-    long *histogram;
-    fitsfile *tblptr;
-    iteratorCol cols[2];
-    int n_cols, status = 0;
-    long rows_per_loop, rowoffset;
-    char filename[]  = "iter_c.fit";     /* name of FITS table */
-
-    /* do sanity checking of input values */
-    if (totaln != nvalues)
-        return(-1);  /* whole image must be passed at one time */
-
-    if (narrays != 1)
-        return(-2);  /* number of images is incorrect */
-
-    if (fits_iter_get_datatype(&histo[0]) != TLONG)
-        return(-3);  /* input array has wrong data type */
-
-    /* assign the FITS array pointer to the global histogram pointer */
-    histogram = (long *) fits_iter_get_array(&histo[0]);
-
-    /* open the file and move to the table containing the X and Y columns */
-    fits_open_file(&tblptr, filename, READONLY, &status);
-    fits_movnam_hdu(tblptr, BINARY_TBL, "EVENTS", 0, &status);
-    if (status)
-       return(status);
-   
-    n_cols = 2; /* number of columns */
-
-    /* define input column structure members for the iterator function */
-    fits_iter_set_by_name(&cols[0], tblptr, "X", TLONG,  InputCol);
-    fits_iter_set_by_name(&cols[1], tblptr, "Y", TLONG, InputCol);
-
-    rows_per_loop = 0;  /* take default number of rows per interation */
-    rowoffset = 0;     
-
-    /* calculate the histogram */
-    printf("Calling calchisto iterator work function... %d\n", status);
-
-    fits_iterate_data(n_cols, cols, rowoffset, rows_per_loop,
-                      calchisto, histogram, &status);
-
-    fits_close_file(tblptr, &status);      /* all done */
-    return(status);
-}
-/*--------------------------------------------------------------------------*/
-int calchisto(long totalrows, long offset, long firstrow, long nrows,
-             int ncols, iteratorCol *cols, void *userPointer)
-
-/*
-   Interator work function that calculates values for the 2D histogram.
-*/
-{
-    extern long xsize, ysize, xbinsize, ybinsize;
-    long ii, ihisto, xbin, ybin;
-    static long *xcol, *ycol, *histogram;  /* static to preserve values */
-
-    /*--------------------------------------------------------*/
-    /*  Initialization procedures: execute on the first call  */
-    /*--------------------------------------------------------*/
-    if (firstrow == 1)
-    {
-        /* do sanity checking of input values */
-       if (ncols != 2)
-         return(-3);  /* number of arrays is incorrect */
-
-       if (fits_iter_get_datatype(&cols[0]) != TLONG ||
-           fits_iter_get_datatype(&cols[1]) != TLONG)
-         return(-4);  /* wrong datatypes */
-
-       /* assign the input array points to the X and Y arrays */
-       xcol = (long *) fits_iter_get_array(&cols[0]);
-       ycol = (long *) fits_iter_get_array(&cols[1]);
-       histogram = (long *) userPointer;
-
-       /* initialize the histogram image pixels = 0 */
-       for (ii = 0; ii <= xsize * ysize; ii++)
-           histogram[ii] = 0L;
-    }
-
-    /*------------------------------------------------------------------*/
-    /*  Main loop: increment the 2D histogram at position of each event */
-    /*------------------------------------------------------------------*/
-
-    for (ii = 1; ii <= nrows; ii++) 
-    {
-        xbin = xcol[ii] / xbinsize;
-        ybin = ycol[ii] / ybinsize;
-
-        ihisto = ( ybin * xsize ) + xbin + 1;
-        histogram[ihisto]++;
-    }
-
-    return(0);
-}
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/iter_c.f b/src/external/OpenGR/3rdparty/cfitsio/iter_c.f
deleted file mode 100644
index f9abeaa80..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/iter_c.f
+++ /dev/null
@@ -1,347 +0,0 @@
-      program f77iterate_c
-C
-C    This example program illustrates how to use the CFITSIO iterator function.
-C
-C    This program creates a 2D histogram of the X and Y columns of an event
-C    list.  The 'main' routine just creates the empty new image, then executes
-C    the 'writehisto' work function by calling the CFITSIO iterator function.
-C
-C    'writehisto' opens the FITS event list that contains the X and Y columns.
-C    It then calls a second work function, calchisto, (by recursively calling
-C    the CFITSIO iterator function) which actually computes the 2D histogram.
-
-C     external work function to be passed to the iterator
-      external writehisto
-
-      integer ncols
-      parameter (ncols=1)
-      integer units(ncols), colnum(ncols), datatype(ncols)
-      integer iotype(ncols), offset, n_per_loop, status
-      character*70 colname(ncols)
-
-      integer naxes(2), ounit, blocksize
-      character*80 fname
-      logical exists
-
-C     include f77.inc -------------------------------------
-C     Codes for FITS extension types
-      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
-      parameter (
-     &     IMAGE_HDU  = 0,
-     &     ASCII_TBL  = 1,
-     &     BINARY_TBL = 2  )
-
-C     Codes for FITS table data types
-
-      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
-      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
-      parameter (
-     &     TBIT        =   1,
-     &     TBYTE       =  11,
-     &     TLOGICAL    =  14,
-     &     TSTRING     =  16,
-     &     TSHORT      =  21,
-     &     TINT        =  31,
-     &     TFLOAT      =  42,
-     &     TDOUBLE     =  82,
-     &     TCOMPLEX    =  83,
-     &     TDBLCOMPLEX = 163  )
-
-C     Codes for iterator column types
-
-      integer InputCol, InputOutputCol, OutputCol
-      parameter (
-     &     InputCol       = 0,
-     &     InputOutputCol = 1,
-     &     OutputCol      = 2  )
-C     End of f77.inc -------------------------------------
-
-C**********************************************************************
-C     Need to make these variables available to the 2 work functions
-      integer xsize,ysize,xbinsize,ybinsize
-      common /histcomm/ xsize,ysize,xbinsize,ybinsize
-C**********************************************************************
-
-      status = 0
-
-      xsize = 480
-      ysize = 480
-      xbinsize = 32
-      ybinsize = 32
-
-      fname = 'histoimg.fit'
-      ounit = 15
-
-C     delete previous version of the file if it exists
-      inquire(file=fname,exist=exists)
-      if( exists ) then
-         open(ounit,file=fname,status='old')
-         close(ounit,status='delete')
-      endif
- 99   blocksize = 2880
-
-C     create new output image
-      call ftinit(ounit,fname,blocksize,status)
-
-      naxes(1) = xsize
-      naxes(2) = ysize
-
-C     create primary HDU
-      call ftiimg(ounit,32,2,naxes,status)
-
-      units(1) = ounit
-
-C     Define column as TINT and Output
-      datatype(1) = TINT
-      iotype(1) = OutputCol
-
-C     force whole array to be passed at one time
-      n_per_loop = -1
-      offset = 0
-
-C     execute the function to create and write the 2D histogram
-      print *,'Calling writehisto iterator work function... ',status
-
-      call ftiter( ncols, units, colnum, colname, datatype, iotype,
-     &      offset, n_per_loop, writehisto, 0, status )
-
-      call ftclos(ounit, status)
-
-C     print out error messages if problem
-      if (status.ne.0) then
-         call ftrprt('STDERR', status)
-      else
-        print *,'Program completed successfully.'
-      endif
-
-      stop
-      end
-
-C--------------------------------------------------------------------------
-C
-C   Sample iterator function.
-C
-C   Iterator work function that writes out the 2D histogram.
-C   The histogram values are calculated by another work function, calchisto.
-C
-C--------------------------------------------------------------------------
-      subroutine writehisto(totaln, offset, firstn, nvalues, narrays,
-     &     units_out, colnum_out, datatype_out, iotype_out, repeat,
-     &     status, userData, histogram )
-
-      integer totaln,offset,firstn,nvalues,narrays,status
-      integer units_out(narrays),colnum_out(narrays)
-      integer datatype_out(narrays),iotype_out(narrays)
-      integer repeat(narrays)
-      integer histogram(*), userData
-
-      external calchisto
-      integer ncols
-      parameter (ncols=2)
-      integer units(ncols), colnum(ncols), datatype(ncols)
-      integer iotype(ncols), rowoffset, rows_per_loop
-      character*70 colname(ncols)
-
-      integer iunit, blocksize
-      character*80 fname
-
-C     include f77.inc -------------------------------------
-C     Codes for FITS extension types
-      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
-      parameter (
-     &     IMAGE_HDU  = 0,
-     &     ASCII_TBL  = 1,
-     &     BINARY_TBL = 2  )
-
-C     Codes for FITS table data types
-
-      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
-      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
-      parameter (
-     &     TBIT        =   1,
-     &     TBYTE       =  11,
-     &     TLOGICAL    =  14,
-     &     TSTRING     =  16,
-     &     TSHORT      =  21,
-     &     TINT        =  31,
-     &     TFLOAT      =  42,
-     &     TDOUBLE     =  82,
-     &     TCOMPLEX    =  83,
-     &     TDBLCOMPLEX = 163  )
-
-C     Codes for iterator column types
-
-      integer InputCol, InputOutputCol, OutputCol
-      parameter (
-     &     InputCol       = 0,
-     &     InputOutputCol = 1,
-     &     OutputCol      = 2  )
-C     End of f77.inc -------------------------------------
-
-C**********************************************************************
-C     Need to make these variables available to the 2 work functions
-      integer xsize,ysize,xbinsize,ybinsize
-      common /histcomm/ xsize,ysize,xbinsize,ybinsize
-C**********************************************************************
-
-      if (status .ne. 0) return
-
-C     name of FITS table
-      fname = 'iter_c.fit'
-      iunit = 16
-
-C     do sanity checking of input values
-      if (totaln .ne. nvalues) then
-C     whole image must be passed at one time
-         status = -1
-         return
-      endif
-
-      if (narrays .ne. 1) then
-C     number of images is incorrect
-         status = -2
-         return
-      endif
-
-      if (datatype_out(1) .ne. TINT) then
-C     input array has wrong data type
-         status = -3
-         return
-      endif
-
-C     open the file and move to the table containing the X and Y columns
-      call ftopen(iunit,fname,0,blocksize,status)
-      call ftmnhd(iunit, BINARY_TBL, 'EVENTS', 0, status)
-      if (status) return
-   
-C     both the columns are in the same FITS file
-      units(1) = iunit
-      units(2) = iunit
-
-C     desired datatype for each column: TINT
-      datatype(1) = TINT
-      datatype(2) = TINT
-
-C     names of the columns
-      colname(1) = 'X'
-      colname(2) = 'Y'
-
-C     leave column numbers undefined
-      colnum(1) = 0
-      colnum(2) = 0
-
-C     define whether columns are input, input/output, or output only
-C     Both input
-      iotype(1) = InputCol
-      iotype(1) = InputCol
- 
-C     take default number of rows per iteration
-      rows_per_loop = 0
-      rowoffset = 0
-
-C     calculate the histogram
-      print *,'Calling calchisto iterator work function... ', status
-
-      call ftiter( ncols, units, colnum, colname, datatype, iotype,
-     &      rowoffset, rows_per_loop, calchisto, histogram, status )
-
-      call ftclos(iunit,status)
-      return
-      end
-
-C--------------------------------------------------------------------------
-C
-C   Iterator work function that calculates values for the 2D histogram.
-C
-C--------------------------------------------------------------------------
-      subroutine calchisto(totalrows, offset, firstrow, nrows, ncols,
-     &     units, colnum, datatype, iotype, repeat, status, 
-     &     histogram, xcol, ycol )
-
-      integer totalrows,offset,firstrow,nrows,ncols,status
-      integer units(ncols),colnum(ncols),datatype(ncols)
-      integer iotype(ncols),repeat(ncols)
-      integer histogram(*),xcol(*),ycol(*)
-C     include f77.inc -------------------------------------
-C     Codes for FITS extension types
-      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
-      parameter (
-     &     IMAGE_HDU  = 0,
-     &     ASCII_TBL  = 1,
-     &     BINARY_TBL = 2  )
-
-C     Codes for FITS table data types
-
-      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
-      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
-      parameter (
-     &     TBIT        =   1,
-     &     TBYTE       =  11,
-     &     TLOGICAL    =  14,
-     &     TSTRING     =  16,
-     &     TSHORT      =  21,
-     &     TINT        =  31,
-     &     TFLOAT      =  42,
-     &     TDOUBLE     =  82,
-     &     TCOMPLEX    =  83,
-     &     TDBLCOMPLEX = 163  )
-
-C     Codes for iterator column types
-
-      integer InputCol, InputOutputCol, OutputCol
-      parameter (
-     &     InputCol       = 0,
-     &     InputOutputCol = 1,
-     &     OutputCol      = 2  )
-C     End of f77.inc -------------------------------------
-
-      integer ii, ihisto, xbin, ybin
-
-C**********************************************************************
-C     Need to make these variables available to the 2 work functions
-      integer xsize,ysize,xbinsize,ybinsize
-      common /histcomm/ xsize,ysize,xbinsize,ybinsize
-C**********************************************************************
-
-      if (status .ne. 0) return
-
-C    --------------------------------------------------------
-C      Initialization procedures: execute on the first call  
-C    --------------------------------------------------------
-      if (firstrow .eq. 1) then
-C     do sanity checking of input values
-
-         if (ncols .ne. 2) then
-C     number of arrays is incorrect
-            status = -4
-            return
-         endif
-
-         if (datatype(1).ne.TINT .or. datatype(2).ne.TINT) then
-C     wrong datatypes
-            status = -5
-            return
-         endif
-
-C     initialize the histogram image pixels = 0, including null value
-         do 10 ii = 1, xsize * ysize + 1
-            histogram(ii) = 0
- 10     continue
-
-      endif
-
-C     ------------------------------------------------------------------
-C       Main loop: increment the 2D histogram at position of each event 
-C     ------------------------------------------------------------------
-
-      do 20 ii=2,nrows+1
-        xbin = xcol(ii) / xbinsize
-        ybin = ycol(ii) / ybinsize
-
-        ihisto = ( ybin * xsize ) + xbin + 2
-        histogram(ihisto) = histogram(ihisto) + 1
- 20   continue
-
-      return
-      end
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/iter_c.fit b/src/external/OpenGR/3rdparty/cfitsio/iter_c.fit
deleted file mode 100644
index f85767415..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/iter_c.fit
+++ /dev/null
@@ -1,701 +0,0 @@
-SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   32 / number of bits per data pixel                  NAXIS   =                    0 / number of data axes                            EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format defined in Astronomy andCOMMENT   Astrophysics Supplement Series v44/p363, v44/p371, v73/p359, v73/p365.COMMENT   Contact the NASA Science Office of Standards and Technology for the   COMMENT   FITS Definition document #100 and other FITS information.             END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'BINTABLE'  /  FITS 3D BINARY TABLE                                   BITPIX  =                    8  /  Binary data                                  NAXIS   =                    2  /  Table is a matrix                            NAXIS1  =                   16 /  Width of table in bytes                       NAXIS2  =                 5000 /  Number of entries in table                    PCOUNT  =                    0  /  Random parameter count                       GCOUNT  =                    1  /  Group count                                  TFIELDS =                    5 /  Number of fields in each row                  EXTNAME = 'EVENTS  '  /  Table name                                             EXTVER  =                    1  /  Version number of table                      TFORM1  = '1I      '  /  Data type for field                                    TTYPE1  = 'X       '  /  Label for field                                        TUNIT1  = '        '  /  Physical units for field                               TFORM2  = '1I      '  /  Data type for field                                    TTYPE2  = 'Y       '  /  Label for field                                        TUNIT2  = '        '  /  Physical units for field                               TFORM3  = '1I      '  /  Data type for field                                    TTYPE3  = 'PHA     '  /  Label for field                                        TUNIT3  = '        '  /  Physical units for field                               TFORM4  = '1D      '  /  Data type for field                                    TTYPE4  = 'TIME    '  /  Label for field                                        TUNIT4  = '        '  /  Physical units for field                               TFORM5  = '1I      '  /  Data type for field                                    TTYPE5  = 'DY      '  /  Label for field                                        TUNIT5  = '        '  /  Physical units for field                               TLMIN1  =                    1                                                  TLMAX1  =                15360                                                  TLMIN2  =                    1                                                  TLMAX2  =                15360                                                  NAXLEN  =                    2  /  Number of QPOE axes                          AXLEN1  =                15360  /  Dim. of qpoe axis 1                          AXLEN2  =                15360  /  Dim. of qpoe axis 2                          TELESCOP= 'ROSAT   '  /  telescope (mission) name                               INSTRUME= 'PSPC    '  /  instrument (detector) name                             RADECSYS= 'FK5     '  /  WCS for this file (e.g. Fk4)                           EQUINOX =           2.000000E3  /  equinox (epoch) for WCS                      CTYPE1  = 'RA---TAN'  /  axis type for dim. 1 (e.g. RA---TAN)                   CTYPE2  = 'DEC--TAN'  /  axis type for dim. 2 (e.g. DEC--TAN)                   CRVAL1  =           8.588000E1  /  sky coord of 1st axis (deg.)                 CRVAL2  =           6.926986E1  /  sky coord of 2nd axis (deg.)                 CDELT1  =         -1.388889E-4  /  x degrees per pixel                          CDELT2  =          1.388889E-4  /  y degrees per pixel                          CRPIX1  =           7.680000E3  /  x pixel of tangent plane direction           CRPIX2  =           7.680000E3  /  y pixel of tangent plane direction           CROTA2  =           0.000000E0  /  rotation angle (degrees)                     MJD-OBS =           4.905444E4  /  MJD of start of obs.                         DATE-OBS= '08/03/93'  /  date of observation start                              TIME-OBS= '10:30:32'  /  time of observation start                              DATE-END= '11/03/93'  /  date of observation end                                TIME-END= '05:02:18'  /  time of observation end                                XS-OBSID= 'US800282P.N1    '  /  observation ID                                 XS-SEQPI= 'ROTS, DR., ARNOLD,H.                                           '  /  XS-SUBIN=                    2  /  subinstrument id                             XS-OBSV =               800282  /  observer id                                  XS-CNTRY= 'USA     '  /  country where data was processed                       XS-FILTR=                    0  /  filter id: 0=none, 1=PSPC boron              XS-MODE =                    1  /  pointing mode: 1=point,2=slew,3=scan         XS-DANG =           0.000000E0  /  detector roll angle (degrees)                XS-MJDRD=                48043  /  integer portion of mjd for SC clock start    XS-MJDRF= 8.797453703700740E-1  /  fractional portion of mjd for SC clock start XS-EVREF=                    0  /  day offset from mjdrday to evenr start times XS-TBASE=  0.000000000000000E0  /  seconds from s/c clock start to obs start    XS-ONTI =  1.476600000000000E4  /  on time (seconds)                            XS-LIVTI=  1.476600000000000E4  /  live time (seconds)                          XS-DTCOR=           1.000000E0  /  dead time correction                         XS-BKDEN=           0.000000E0  /  bkgd density cts/arcmin**2                   XS-MINLT=           0.000000E0  /  min live time factor                         XS-MAXLT=           0.000000E0  /  max live time factor                         XS-XAOPT=           0.000000E0  /  avg. opt. axis x in degrees from tangent planXS-YAOPT=           0.000000E0  /  avg. opt. axis y in degrees from tangent planXS-XAOFF=           0.000000E0  /  avg x aspect offset (degrees)                XS-YAOFF=           0.000000E0  /  avg y aspect offset (degrees)                XS-RAROT=           0.000000E0  /  avg aspect rotation (degrees)                XS-XARMS=           0.000000E0  /  avg x aspect RMS (arcsec)                    XS-YARMS=           0.000000E0  /  avg y aspect RMS (arcsec)                    XS-RARMS=           0.000000E0  /  avg aspect rotation RMS (degrees)            XS-RAPT =           8.588000E1  /  nominal right ascension (degrees)            XS-DECPT=           6.926986E1  /  nominal declination (degrees)                XS-XPT  =                 4096  /  target pointing direction (pixels)           XS-YPT  =                 4096  /  target pointing direction (pixels)           XS-XDET =                 8192  /  x dimen. of detector                         XS-YDET =                 8192  /  y dimen. of detector                         XS-FOV  =                    0  /  field of view (degrees)                      XS-INPXX=          2.595021E-4  /  original degrees per pixel                   XS-INPXY=          2.595021E-4  /  original degrees per pixel                   XS-XDOPT=           4.119000E3  /  detector opt. axis x in detector pixels      XS-YDOPT=           3.929000E3  /  detector opt. axis y in detector pixels      XS-CHANS=                  256  /  pha channels                                 TDISP4  = 'I12     '                                                            HISTORY   modified by pence on Thu Apr 24 15:04:08 EDT 1997                     HISTORY   modified by pence on Thu Apr 24 15:07:24 EDT 1997                     TDISP5  = 'I4      '                                                            HISTORY   modified by pence on Thu Apr 24 16:06:08 EDT 1997                     HISTORY   File modified by user 'pence' with fv  on 97-11-25T14:34:58           HISTORY   File modified by user 'pence' with fv  on 98-01-12T14:03:09           HISTORY   File modified by user 'pence' with fv  on 98-02-06T15:18:24           END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             AU=q1&AUA	=#t6AVo(RAX/@)P#FAX@Y[	AX
,~AY@ S?AZW^AZĀ},aAZ@LzA[":$A^NrA_MuA_@'nA`g@
 	NA`$Aa@*	Aa+912Aa%	Ab tB( AbD@	*vhAb I X,4Ab@OAc7e$.+Ac] 3	OAdW2+
Ad*2IAdC	 )Ad`[#Af$&^AfM
AgoxAg !%AjS-`hAk\
Ak|"0$SAl@
-?-aTAl@ f)
-Am~s1\#Am`
- Am`-V%An
Aq`5	Ar{-Ar#*)
-Ar Ps	Asg' 
AtyAu@ PwXAv`#cAy@3+KA{/ ! \/A{Q@
u,D
bA{`
:
-A{@g"'*%A|	M*SA} 	'2^Q
A}sf A~0`"0YA~
-eA%DIA`!v3A}T"-A*	A X,AN
A`($_A
-OA`i:AϠv*-DA
 0A y	A	AL$)oA)-bA@
-A(
Z(A&@+ A	#kA/91
Ah 4Ao'ASA,/B%vA	3Aji!?A{+Af."D:A l3AP'	A`
-1
-Ak DzA&=Avy#
-A@
Q3&A	h'3&0AÀ
-(AA/A! ~A: 
A@SA&	V2Ay*&8A@ZAv`#
YALSAa@A1,PAn /3xwA7 PA*E	A<3ApA=`?&A@zA\h0A 
#?Aɠ
(U+DAb*:BA$$A-3DAL*[3'
A}zAl`
-$s
-Aŵ.^A
-$_'AmF1Aʒ+A`O&A֠s
7A"AJ@/ P4EAͻ`

-A+
A`'
A
-/
AЛAh#
-A+"SEAҁ Aҫ / 35A	)7A	4A4 ln	A:@2%
-AZ 
?aFAi.]FA*
-
- JAn`-
A`+XAU`v AW A,4`!A@"dA C(jA%,&A	>%L
Ao@
-AA"!!#A
3$
A`H/&XA 	h(-3A- -A[,Ac`+%$A4SA-z3
-A 0(%A
-J	]{A y!7A \'
A`	}&&|A 	&,	A	`e9A
-`d%x.A"*WAp}A5`(AO+9AX|"rAAy\'A7@	%
A
-^

8Ae)0A31AWA
"
-A
-RA<s-A`A cA`L2A@
,'B@A?,	A`u(-A@
-;AIwAC !%Amq%,d+Aq
A ,1{
A`xv-tAk@k'*A4`Pc-sA m!ISA!h!`
-A!`CA!$A"%,
-+A#Pk;1A$."6A$l!H
A&- g%A'@
-4`PA(Z@_A(Ƞ)-(%A)P		A)w,)A)`
>A*AA,*@f
A-I#{]A-@_t
A.֠yn;A/O b6	A/.'A/4vA4S`/A5%;A5
-4A5./A5 %{A6`!A6`
R3A7_0r
A7r!mA8@
>iA9`/WA:f WfA;"y "A;:

A;S.b!"A;c` )eA>@
)"t{A>-A?=`	N&D5A?gxb0A? @E	A? PA@'$TA@V.VOA@
A@`AAW`s!AB֠e,s*ACXw1
-ACi$Z$AC D
-_(UAD
-QJAE& wAF(%'AF b
1)2AG
-	^
-^nAG;-+AHAJGAJ#$AJ@h1"%
AJ@	0"sAMo 
3ANq AO/jAPcD#;(e
AQ@-AQ\4d
-AQ |eAR)`G
-AR- 8,dAR3$x3AT&&AV
-*
BAAWd AW@3jAY81m AY?!
-A\ (4	A]ΠFPTA^+4	A^@)1*	A_`)*>A`F.{OA`#JAa*7Ab*4^Ab,`,4Ab@WAeZ'&Ae
-fAe1}!'jAe	

Ae1+AfA'~AfI!w	AfrAg(mAh@	u	-EAhD.6Ai
	Ajj~Aj #lPAj("jHAk*~JAk!1`Ak@J#\8Al
\1AlH@.%An܀y//
Ao@%C#Ao3`eA$rApSXAq0nAq5)I	Aq@2Ar26:Ar[At%+VAtN3At
-Au@G 
-Au'!{Avg 7Av-!7Av%tAx'4 Ay@1-Azl`&) Az
t#AzǠ(3Azm"*A{>&BA{l6	A}("iA~%_	A~@)i%QA~
-Y4pA~ :&A@!:	A)A	1!AL?3A 
.	ABA$1f7A`2'AIU>A$!A{
LA A4JLAsANdK?A
-,|LA5A2(A&.!,A1gA*@!6AU 
-<A 3AQ--f
-A &E
-AI2V(A2%A	$C5
AAD M-!WA 
6~ Ay	AI!=9A1A 

m
Aa
+A |mA~`
'A<HjAo 4AA(! A 
&2"vA!)$A
--AT
-ACAYAmAdY.A
- }]A
5tA@A@,A A-&f	A	'0	A@YAʀt#A 
T!A
4!	A1!Y	A$L#AC
s'y#UA{@,
-NA|`s

-A&A
- 6ASR":A
+#3AmyA )A 6v"%A
4"#2AAt}("A	AdbB
A <.ISAl|A)Ajn
A6@m.Aj

-A`BA`|hA#a&A A !5A&'3QA%.x
A`{(VAp5%A`		{ A%y-AO)bAS0*f'
-PA:	,6VAD@(Aß&A`!2!r	A'`-^/5Ak
-''-A	
-s	A_$K[Aɞ	Aɷ`%5 A`
B5A3!Ae
4-AʁA
-%LAϧBMA`&A]k)AրY, Ai
9-A19A ;)A@	x Aָ 	A`6!AT :A\ 7t(AX!	Aؕ`A$
-1)VAِ`
-&bpA@z0z+A\##AS@",6HA~#;.#Aڠ73m%Aݞ`Tj$A@@) 
AX
e |
Aރ
Aި`4!-A`! oAp.A @m#Ai@
X"*A !9!OA9
J-~1FAg`
-D.Au1jA?)!'A
AK	A*(&A`	6%AJF!$
AP3AJA(Q5*2AA]A 6A@0
-,Aπ<4A݀
-A (%oAiu!E5+Ap`3L		A5@!A|@
-A`T^AL.[)A	AW< *
A [A'
-
A;!5A
5e:AI`A #@#V+uA @*A Ϡ"PA !	=A  ""VRA 4@
S
-#A 	
.6A 
-sIA  %7|=A  C/

A `.8
A ڠ
caA ,.A 
uM&A 
 &	*8A 	
A XA &DA  | A LA M[("5A S A ,CA  
"~A 
3B5A `DA ŀU!
-A   0.A 3@s!A `@
#&A kS
A  ?QA 
1A >0	A h$[A `'(A C5A U )
-[A ,$A !A O(2A !A #u("A #`
]A %`5	A & A 't=!A 'A (	*eAA (:`(E A (`
7*A ('UA )
-+!EA + 
vjA +j#}$A +op6A +  6
-A ,*`',@A ,@Q$1A -`?'a1KA -Yh1A .b`A~A .`!
-=A .A /#	A /*'A 0 %A 1;MKA 2:@>']A 3S	%&VA 3@
-? NA 3~:A 4@%(uFA 4 	:+A 4 YA 8z6C6A 8}X@&
-A :
-]AA <`0h,oA >? A ?r.A A7 +uGA A Z$&w
-A BG 
-_9
PA Cv@A C@aA D&A E1#>A H*

-#A HeA J{xA J@*%jZA K`%-^*A M`W4A M ][A N`jA N? 5A NX@|
*A P`	r&`A Q .ZJA R=
R7A S@\.A S`e$?SA T 6W>A TK
-A TLA U2_A V2 [.{SA Wb qA X EA X /TA Y€ A Z
-`g,A ZSZ A \c6JA ]`H}A ]	A _%`%
-A _@`?EA `F0)f	A `(A b,@2$m*A c
-0A da 
Z1A eS?
-!A e
KA e ?-0A e$CpA g4$A g
+A h p:A h'/!A i]5)A i4
A jJ o"j4A kӠ!zA kq]KA l  #0NA mH)PY
A n*A p`I-ZJA q@&I/A r+@s!o2(A rÀ,5A u
	&.A u '	A v8uA v f
-A v"dA w
h+eA w  $?A y(A {
-
-3f?A { 
$
-A |6A `a&'*A >@
-(J a*A .`
-)wA `i
*A >	|%$A H
2I#A 
A k!T4A l@"A A 
-HA - Y3KA I *(|.`"A A TO
-g(CA ֠.`A "4-A @UA @A !%A Z`0q	,A _8A *`H2+
-A (SA  	'f$A vR"A 
&V6iA v-A  j	A `+)5A 
-H"	+A `I>#A 0 ]"sA |"$A `JA ;`+
A A0/
A lF%*vA *7A @r/v
-A GA Π!OA &4 A  s"Y1A @

#
-A !Oe
A m
-@
-QA  '@+gA +&*DA  	A @}2I	A e"A 
-A !A 9-	A 5d#A ('.A Z%A jt" _A 
5PA @
}E
A ThA X@
!'A =)!#)A v
&&(%A 	0%7A UR
!A {f!TA  
&0A </A ``3A k0$D A s
,2x	A FA %f	/A +'A Fr(	A 
-&yA 6FA L*
A ?Y
RA 0A #hA n
 bA `N0";A 2%5E$A 5A 1)A Q= 
?CA `G.!vA ņ  !Z4A ź@
,A$A P`%%
-A W@Y"A 
IP=A p  o9A qU/MA ˩`,'%A @lA @#-,.
-A ̄`"t	{A ̀-v9A  D*p:A /9A @`!A F
1(A @DA qN!fXA ӊ@`"rA ӪN&u*lA Գ u,)U	A `	#=hA 'l)A 4A ٹ@*A ڀ$hA /
A  C]A `!;A (@#.*tA ݸ2"A @I
A t` -A ޞj2"
A ޯ:	5A 4A V 1!!
-A 
O
-@A '	'A Რ3: A `4+l
A ~%0J A ?
"`A 
)A 0!A _nA 5!	A 4P!WA KO8A 5 
A @#'HA 쵀w
1
-A *	vA n $o4A t3?A `rgA G(A O
-6A ;4->?A @y02QA (A `	(=
-A @
-	'yA  6#A L #A 
,1A $A 
)-A 5
-91/A `1$@A }
-)?/A  p&*A ] S(XA s]CA H`!(%A ڀ
-:1A [ ")A s*5A @JH1TA y@%A6}KA (A @A @v	3~
A T1/A!c*A! ~
-A! 565A!jT19
-A!`/i=A!
@s1A!F 0t*A!`	$\
-A!	T'A!	/()A!mA!@%=A!	4 A! A!(;A!@
-)	A! 
-A!?A!%,
-A!Y@L,~A!7(_A!-:+A!> $A!V 0DA!
A!
@Y
E
-
A!NF!	A!ŀ5(A!-@&)A!6@	^*4A!UU!
A!m-	A!m
4A!IA! `6N%A!!+3A!!R`mG)\A!"SIr2vA!"ǀc A!"`5:	A!#3}lA!'	.8A!'-jNA!'58A!(cY
#$A!)=
%&A!)F
-0
SA!*,.d
-A!-+~+A!-|"
-A!-`-o)	A!..A!.)/	A!/0#A!0z"A!1.@!1
-A!1=s*A!1"?RA!2<VA!2ˠT#~A!3
.%A!3 3A!4N@	)A!4l1%-
A!4
-$$!cA!4
A!5`E.%QA!5׀s2&GA!6\(kA!6
-l],A!6@)(
-A!7R8F
-A!8@7&	A!8m&6A!8`*$A!8 1zA!9@!,kA!:u@/F33A!:~2.4A!: '0
A!;$@#ZA!< )gA!<&d7]A!=e.jV	A!=
-*5A!=#"L	A!?
-"
-A!@M
5A!@-
A!@ 0A!AG));A!D ]!J	A!D\A!D`/!@A!F`V"2A!FF#+#0OA!G( Z\A!GE`K((RA!HEA!H .7	A!I /HRA!J
@4E1A!J9]	,/A!Ld$,QA!LSQ!7A!Ld%b!A!L}
qTA!M@.*A!M J%(-wA!Nf%
A!NK1A!OvR1VA!Q!2A!Qh #I'
-A!Sz
-[:	A!V# L3 A!V,
:A!Wz1!(A!W	 )5A!W@7 A!W MA!X43A!Y)#!'A!Ze4--
A!Zu`!
A![FA![2A!\)-	A!]aP0erA!]r(A!^a,W,dA!^q@X"	A!^`'@A!a.
-&2A!a8@OfaA!a@
zA!ar]	A!c8h5A!cO- zA!cd-A!d$A!d
'5A!e4%A!f!
-%+sA!f@'
`#|	A!g|`
*A!gf)$;A!gɠ%MA!g5-/A!h zPA!hv6]A!i66A!iE !EA!j
--A!j7 R1"A!j:()
-A!ji@	!Z,?A!j
! !A!kr	A!k[V=A!m-FA!m@
-
A!mg!EA!mZA!o`BA!o#3 DA!o`
mLA!rb,A!r@)PA!r%6A!sB3A!sTS!!/3A!s 
6A!t
	h$A!u`
b='&(A!v@gS,%
-A!wh#c/A!y`	A!y='%a8
-A!y`(A!z,dj#A!zr 
)43A!{.
-
-aA!~
 LKA!~ 0\
A!^	A!1`,A!n@yP
A!y5-'A!2NA!
- 
*A%BA!#l1
-A!3A7$6A!A 
-1SA!@  FA!
-A!U+,A!#XA!C`
	(MA!
-"A!xA!J{3]A!C0A!70^A!_$A!1@.h A!J #7
-A!ks`A! 3.R%}A!
-*@(A!y`@2"	A!@(#8]	A!z013A!(1A!
-XS
A!x@mA!v"A!:k'sA!a/bCA!%8^A!@!"A! 3-A!S@K
-A!@,]A!`3A!!A!#
J7A!@G#/,A! 6!wA!M7A!8uf*-A!@	4A! 9"5A!b-L#A!T
-	A!V@"qA!z@0F
-A!xA!e &66A!Q"O2A!D*B!A! 
UA!`lBA!@A!xA!
&IA!/($A!X
-
-A!W,,9A! *FA!`
-#%0fA!@A!?F2*yA!Z
$"A!@@bA!jA!lA!Ú'A!?`jA!d"lA!
/sA!`6+ &(A!V
1-HA!>!sA!+~)]-A!_ 
-R-,A!ܛg IA! G8A! ?#CJA!^@+2A!@X AA! A!>1
A!>@4y 	A!P%.THA!#-qA!쩠+
qZA!b2A!+/.1A!]@"A!4$A!؀$&A!Y h8A!s`%	A!g
-9A!O@,A!`?*iA!	,X+	A!A@Q+
-A!Π*p
A!"	%o|A!s,A!`	%,	A!t@E5A!׀Q,@A!
	& 8A!`
-o7A!6aBA!
*q
-A!	n
-A!<@2A!@0 A!@
+`!A!ՠ
v$A"i
	A"7.	A"'!=-A"W

/A"jA"u4bA"Z& 2A"F'A"
-*NA"	/`	[
VA"	 (/	A"
-C@1
-'(A"
8_:"A"
w@-(~A"
Ƞ	,
-A"b1+A"M&*A"+ .(cA"	6$kA"|8.A"`.&
A"ۀt
GNA" q!YA"@&$F7
A" RA"t
*wA"@/f(vA"h	LA"3A"%f(&A"&	!A"j |1A"{`A"@(c
-A"@	%8
A"f kA"? 8A"6A"W}A"v.50A") )Y
A"`(\ A"ʠ'A" {)i&hA"#*wMA"$=;5^A"$O<k	A"$&
-A"%4$K93A"%`+A"%	>
$~	A"&R

-A"&r`+L	A"& q4)A"' 73EA"'"sA"'f+JA"(	3g"]A"(->(4EYA"(j&A"( %7
-A"(@	*$[*`$)DA"> ({q
A">A"?%>-A"@o
+OA"Bk*#3A"BY**H0A"C)^"A"C`"bA"D@ $5'5A"D"DA"D@J'eA"F@T
-A/(A"G`&A"H#:A"Inf!?!CA"Ia`!A"K7)A"K 
-/A"LW& A"M4 R KA"Mr+,+qA"NC-t2GA"N ,v2'A"P14A"QV/=]A"Q"3^A"R}!8fA"T 1+GA"U@	3"A"V&*A"Vl)AA"V
-LJA"Wq_^0	A"X<)7A"X 
0$EA"Y[_3+A"Z",{5mA"Z@6
A"[@*)3A"]	sl\A"^@#gA"_
zq'_A"`%!$r^A"`z'a_3A"`)5F:
A"` k!>F$A"a3!iA"a@R"A"b4 M)A"bs`/A"c&@U7A"c4`Ux6A"d[$R
-A"e@) A"e*}'lcA"e/d
A"fX`c0
A"gQ@QcA"h
-iO0A"h%0Q#A"h!!!_A"h ~jA"hΠ'\y	A"hQ(	A"jC0A"n\n
 A"o~%
A"ob 2-A"o`&2IA"o`

!A"pu"7A"q	^A"r (eA"rA6
-A"u{N+H A"vd 
MA"v@7A"w!@n:6A"yr35A"z` S
A"~X|3jA"pA">$FA"-=A"4A"A"	A"&*eA"`'.3({A"@A" .
A" 2>A" 'A".
-BqA"F0`&H
A"K@
-{ bA"K5%/gA"V
BA"& 6A"T47A"l w0$9
A"8SA"A@G%A"('',A"
A"*`t3)>A"
-'A"d`<.1A"ߠ/"+A"I+aA"(O,	A" a+oJA"	I BCA"	a0NA"`9!$A"	6z A"@U'A" p	A"-7"A"
CA"΀
-if
A"`"])B	A"L@	1RA"@}0|(9
-A"	c+S	ZA"K`9A"HjA" P-7TA"g`j!TA"x`$
.QA"@3<
A"`h A"A"5|mA"2
 A"`4{!I
A"܀.,TA"ś 3"A"+o )A"r &A"`
-%7{LA"(\
-A"E&|	A"&/*A"' )2(A"@`n(A"t[%	A"~  A"ʄ%t:A"ʢB&1A"ʹ`:
-A"#ZA"K4VWA"@-
-A"?) A" 
-}RA"<#A" 
DA"|0i
A"ѭPA"9$S*A"4H)A"Ӝji@A"A"1
-TA"֐@
JA"
GA"@$A"+v8A"ذ`.+A" i(mA"ق(A"

-%)DA"!A"۷%A"o"<A"`OP)A"m 	;6A"ܖtRCA")A"@iaA" (427A"@YVA"@/V'A"	!
-A"2,+A"5	A"V e"j
PA"bqA"&( A"
.A"(
W	A"t5A"< *"!1A"
p
-A"@_!
h
A"@_$EA"#Z-A"/6A"} /A"v7A"(
A"i!CA"103A"`%A"<AA"$0/
-A"%3&FA"=)A"O0H1WA"A,(;A"
-"
-;A"L`A"j 1/B>A"k@9-&46A"
-z)/#jA" 5+?A#/A#c@"
-A#]
25+A#@##5A#|@Y=A#@
-A#+A#Ā	A#	O@s4bA#	o@w_A#	%A#
-kGA#`a)NA#9`
-`"3A#NA#50A#@#2ZA#>`pA#P %A#|*A#à9 @ 	A#.DsA#
"(A#j@
-))A#`(
-A#ŠL2/	A#y;
-A#i)A#@	,0A#1#'IA#t
-b^7A#V"A#/2^A#H<(A#)`	#qA#0#A#n %5A#@
-A#B&'A#o`
-U4A#@V\:A#6A#
 ,A#  1P)A# 6+S2LA#!
-.A#!~@
05A#"N-/XVA#"`,q0A#">
.A##
R$X#$AA## $i
-A#$67A#$5+WA#$Q%A#'@1k%
A#(@
-$A#*z 01
A#,e(O
-A#-B-(^A#.À	8%=#A#/F`A#/p`1$A#0`
-#1
-A#10#:A#1'4'-
-A#>0
AA#?r#7	A#@_ g2A#@b #5"A#B
-A#B A#C&A#D 
-i. A#Fg.3PA#F,,A#F e![0A#F1$A#G?MA#G`*A#HM-@$=
A#J`d!J wA#Jm@0pA#K@3)%A#Kc	2A#L+*A#Mr26A#MxA#M2A#N׀6A#O%`A#O#quA#O@.2A#P 3A#Qh 
F H'A#Q`
-?+
-A#R@E#A	A#T
A#T7`&#cA#TEQ/*A#T`05"A#T`+'	A#Uh	*>)A#U@( A#U
- 
A#V  M3A#VF	A#W`S(
1A#X3 z/A#Xv/y
-A#X,)&A#YV
-U
-A#]ik.A#_2%A#_
-1#o'A#_ 
-%A#`q0N++A#` |xA#a%oA#b $+	A#c T#AA#c"}A#d8	(JA#f(&">
-A#huA#hb!c!eA#iT
'"A#k	%vA#lA#lm$BRA#m%rKA#m8 A#nA#oM, A#o`
2%
A#pR$2A#pYA#q!`)-A#s`nA#sz@H7d
-A#tp jmA#u1"A#u>}$xA#u-*[7A#uۀ!
A#v
-4+A#x?@d"8 aA#xv7m#vGA#x'"6
A#y! ;A#y-(*A#y`	\,7A#y#
#A#z
-1^A#|P`"*A#)mWA# /!MA#y$30A#%:.A#.
A#d*	A#`	5A#f@0E"^A#lA#A@>.H(2A#`%1OA#`r0(~A#
-8/A#@	7;`
A#	_
A#["(A#	n+8A#CG.#
-A#P@/A#@C!2A#e'2A#ɀ(A#	.8+A#6
-A#3!6A#E/
-A#m (~A#H`\A#.A#@
A#F5ZA#`OG"A#o
n!@&R
A#@
-'&fA#/`
-f	9A#@"*A#R	xA#@A#@rA#^A#V.A#a ;1A# /!:A# n!A#]`$0.A#&A#@W|A#@3*SA#	(
-)qA#2*
-A#Hp-[A#@
-[+A#@	.R/
A#|A/*6A#5 !0A#S/
A#	w
-A# @A#!@D+%
A#٠
-^A#N7eA#d 0AA#n -A#3
-A#@0A#, A#1oi	A#j)+A#/A#%7A#\5:A#, IA# `V4A# anA#If	-A#m
-A#Ƞ3(A#.
-A#DY"(A#ɀ	&;.A# 
-!,
A#3h"A# 
]"7A#`6%heA#2daA#,)feA#W1A#^U0	A#`A#ǽX6A#
-)A.A#- *W%%
A#ʘ
-2#}A#J0pXA#Wp
A#ˣb
A#~)A#x	A#,-A#%b	,
-A#נ#Y+mA#2 #;(A#qA# F)PA#p
-+++
-A#ϐE3A#Q-daA#N@QA#`1
-A## 1A#ҡ!xA#Ҥ
A#ӎ*3V	A#<@y+A#Զ %2A#."}A#ms
'A#؜7
A# -9A#di{A#D*
-A#ۦ1-~'A#,'(:A#I@	Q A#S.A#-`$A#r5$|A#`
-	(xA#
-(:$A#;%|$A#+A#j*'PA# 	%A#kxA#@%A#5	+A#`	)A#
) -A#7
;5A#[XA#@]A#@	
A#Ok0A#`&		!
A#+@a&
-XA#E &[A#q`c* A#D
8$1?
-A# "7
A# $XA#
-6tA#S@)0A#Y2eAA#zx!A#@'!A#.[A#8GA#"A#*qA# 	+$A#ހ
-$HA#`S,&{*A# 	(

-A#q ]A$  y+@A$ 
-A$XV2A$6DA$f
!6PXA$~0"A$@GA$`.-!
-A$n4A$&AAAS` 
-
-OAS/ X ASh <%P7-AS@4%%AS'
-*! AS8 YAS -
-AS@&3AS PAS@,4	AS_T+?QASSQ!uAS`72ASe:'?ASo 
-AS@&{"AS@"vASJ`>AASy&k
-AS`r-AS	.AS !0AS#ASÊ'4jASá@7
-
AS@$
-AS@7AS/1GAS	AS>AtOASǕ`'
-%
-AS 8AS1
iASB7pAS3')AS̮	Zq
-ASʹ -D#b
AS (#AS@ASo`
+H&WASе`
-AS@w19"ASіGASN@V3"TASd`f!lASo':AS D NASC"AS=
m"-ASՊ 
 HAT.!U{	"
AT.I#"{AT/
PTAT1/$`AT1F |AT2rk
AT37@`",
-AT3`w|AT3@Rv/AT5.+2AT5ݠ
-@$AT6@
"%AT6)f AT71XlAT7 AT9(	?AT9c]	AT9| #%TAT:
/9
AT:{@A(|/bAT:3?+$AT:"lAT=`
AT=#AT=.@1	AT>@&
AT> F"ZAT?
~]AT?i$*AT?!AT@@1ATC@
ATD]H(ATE( *eATEL2(
-ATF$ ATG&;4zATG6f&RATG@	-kATG*ATH+ATH_$X
ATI@%ATI`j-%	ATJ
-S7LATJV21 ATJ ATK: c	ATKU  "ATK^
-ATK 	>ATK@".4ATMj7C0MATN? 60ATQ\*!
ATRq#	ATR`2%ATSY
-%5ZATS~(
ATTO@
-5a	ATT`1ATU@;..1ATVG"ATW.
-ATW?d]ATWo I4]ATW`V4<ATWܠ%5wATX 'ATX@%59ATX۠/!]ATYJ`4.6ATYP  rATYu@&[ATYx`U*ATZ`WQAT[7.|%	AT[2AT\nT%AT\`+5AT]N`/AT]K/AT^ ,AT^1'AT^G!AT_kM1AT_4-AATb$#ATbk`5GATb@3\
ATc#.-)ATcj*1ATcЀ	'(;ATc`
-IATd@ATe.`ATe<@(
--ATe@$iATe
&&
ATf0#ATfa2|CATgVATh!ATiF&8g
-ATi`(#:
ATj+'mATjѠ+$1	ATj`	,t.ATkGu'hOATk3&FATlV&)|	ATm@	~$ATm!Q3$) 2ATm5@sATn4 $ATn =ATo	P
ATpu
|.fATqR@J1ATqU4ATr@.&		ATr#ATs%%	ATsv6W!5ATt
.1 ATt 
	!&OATt`~%ATvv*ATv	/
-ATy 7:ATy b&ATz<'xATz-xAT~+E5&iAT~р
-La1
ATa AT+AT	%ATATU(aNAT_	
-ATo 
/55AT)#AT^ 
v14$ATb]w zAT0W
-AT@D#ATՀ
+s[AT
e4-]'ATy[zATY	/AT6+ATÀ	X!8'XAT*`
-5SdAT2 +zAT	0%,AT4*lAT@19
AT!"2AT`
hg2lATd'ATe,!	AT
/qAT9=i
AT=b.FKATK@JmAT@1gATK;,p&ATu YFAT$AT5AT'.-	AT[/!AT
gATD!-AT(gAT/.,!AT\@al)AT4
-#(/s
-AT`%(x7AT !*$AT
C+RAT`!@ATj
%
-cAT`'-AT5!$ATw#ATd
tCiATҀ2ATӠvNAT2|6AT`N4%HAT@
-9%.AT
("6AT+AT&'AT8Io
ATU~#$E
-ATX]P	ATo!=AT E#3ATڀ
;4AT'?/bATC,XxEAT
8i&&AT)	.EAT+HAT		.ATp)AToAT|"7AT 
-"DGAT"AT 2JPAT /AT` %AT%TAT`!&ATUh0*
AT`1-BAT@!AT#r#lAT8
AT)ATX`	"vHAT{ LAT9`}*AT|K'8FATHATBAT~`s0AT
$CATȀ,"	
AT~0`AT5)Y?ATCE*0
-AT`*cAT`,&ATŎ%6~AT6 #5qAT #AT'`
	ATȨf+KNAT@	1H,AT `z#*
-AT!
k&ATK@1AT@FATϠ10AT{@&
X!ATЀT!ATҪFATɀ.#"W
ATJ(0MATl}&	AT,`+-2#:ATԠ 8!7AT`.s,ATys]6QATՀ`5-7ATe#	ATִ
3ATigAT/ 23AT/@r*PAT*AT@46AT\.1-,hAT6#ATw
5` ATۙ
}$AT`
ATܱ )AT0ATD $OL5ATݖ +ATަ4#AT`
(bATE
-+ATX	/3AT0EAT15;AT9'ATh
-w5AT؀9o;AT.AT䭀:!-ATS)(AT	3AT*, AT QIATH)(
AT		(h!
-AT
x5+PAT@	6,AT/"
-ATS-KAT@w#9-
-AT <|"IATL`\a%OAT`84#H#AT*!
-AT@
8	0"AT %'	AT
-j.ZVAT|)	AT2	{78,AT-0
-ATG@.z
-ATc@=9AT AT`

OAToTjN	ATp`%*ATw5{AT}+?!/AT
&$ATV
-*AUA@-,AU$CAU& +
-AUp #,\AU #q7.PAUt( $
-AU:AUb`XAUiu
-AUOVAU sAU&AU	;(AU	|
-\_AU
-.
-AU
-:`E$N'AU
- 	`'AU#
-AUS
#)<%AUyRAULG!1	AU&*AU
4AU
. %"#5AU
w g!9NAU
@+AU
`5
-AU@`1/
AU	
-AUՀ6l
AU	ScAUG,
-AU0AU,/SBAUj/FAU{+AU؀A%d#efAU.AU'(JAU 	AU= jAUg`+2$AUŠW,AU(AU>$AU`5.;AU@7,4AU$G(AU`8"lAU
-2
AU,`6~	AU	@m%V.AUr`
76d
-AU`.'=AU:(qrAUj3&" sAU@
"#AU8)/AU+ZAU	AU!<)AU!*)!AU"U
*)WAU#	
-V(AU#`
-a 18AU#g4B
-AU#v2!AU#v!0AU%vR*AU%H8AU%`".R*OAU%`S!T/8AU&nl)S
-AU(6	.	AU(#O"AU*'
/AU*Ҁ?.+5AU+AU,.J!AU,6G6s7AU,O
&AU,}
@AU- ,AU-= @7@AU-;AU.! B-AU05S)VAU0
-$	fAU0@H&dAU2>*)W
-AU2U7'
AU2 o	AU3] x*16NAU4	%BAU5KB"AU5V
"AU5πa% AU6:@)dAU7`
-p*>AU7,)0AU8:+2AU8l)AU9`J$)AU:	8AU;%1L
-AU<x$&AU=`
--AU>T*AU?) 
~AU?C'?
AU? D
-QAU? %) AU?	-$AU?ǀ/%AU?!32 8AU@,(aAUA4	#,1TAUBI`#AUBeAUC-/mGAUC('
-AUCԀ	:.
AUC )	mAUGZ:"AUG>80AUH@
-,AUH {%.AUI$[8-,AUI2(uAUI>[AUIZ[
-AUI[ S
AUJ, 0*P	AUJ 3 !'AUJ +tAUKy`-xAUL#=AUM 
 pWRAUM 2UAUM-ZlAUM@4)AUN+ !{AUO]#7}&AUO`n3|	AUPk`D/AUQ
-EAAUQ9
$'AUQ3b!AUQ`%*AUR`5y(AUR`$#8AUSC , _qAUSJ$AUT"w&AUT
-P{0AUU &
AUU W5#AUU/DsAUV 
-AUVFl4AUW1!"<	AUXV
=+'AUXy	!2S*AUX (4$AUX "2AUYրm e2
-AU[l.AU[`"AU\H.AU\`$|1
-AU\`	I%}fAU\@&
/#|AU^
Q,;AU^		AU_452
-AU_@5
-SAU_71[AUat
-&Q8AUa"j
-AUc8,\AUc3($
AUdS
-0AUds
-UAUdր!30!AUe ,AUe!!$)AUe-
AAUfTy4)AUfms

6AUgWD
AUh(`KV*AUho	7 
AUix )%	/AUjK`!&J
-AUjߠ'2pbAUlZ%@AUlo'NAUlu
-3
-AUm48NOAUA	&(AU
HAU,2
AUA/@AUJ(AU@	TMAAU7&AU2+)AU@S
.AU@u%8AU4m@5AU-*KAUÀ	IAUlYAU.AUkAU`y&d AUa
3,f	AUF $AU`
AUz@
"AU?F/`	AUL`C-C"
AUy !{;AU[ORAUV"b8AUS`
)AU 
-AU`i 0AUO L5AU@o
AU 
-1?AU`7
s^AU ( (	AU
-
0?AU]*o
AU5AUZ*=	AUJ@	q2AU 
AUn`!AUæ#A5AU1aMAUī 
2%AU/-D3AUH`$PAUI;(+mAUǼ@!	AUq!,	AUqS6_&N	AU`	*(AUp`}#AU

AU@9=!^YAU6j p*AUs'6FAU< 
-.(pAU˯	AUܠ$UAUy!$3AU p%AUH5kjAU$AU·@B
AU΢&AUq0AU--"VAUY G)AU
-w/O7AU`2r+JAU7
|AUs*kAUх j,/tAUьZ+%_AUa')=AUҒ
-y0=AU	 AU~`{%8AUӡ`
p 'AU-3:;6AU2C0AUH.2AUo@
-AUױ7AUWB?AUٷ5
-AUN`96qfAUڈ 
-AUCZ&AU80SAUr@p!1AU 3AU$P#AU`AUРG<UAU*
`
AU{!"AU`2AU`$/AU
AU`Y%l	AU#4`	AU@,(AAU
-(RGAUAU'	[AUG	AU> 2"
AUEYAU`
)AAU
-Q#M0"AU q!AU '1AUV`f4fWAU@!RAUx`CAUZMAUxB`1AU؀m+;
AUOs.AU9 -	
-AU:"iAUk$AUB
HHAU0HAUڀV
AU݀RAVg 6AV *H	AV'@(,_AV(.B	AV

AV@c$dAV@,+
4AVn 1AV`mAV c2AV 
)
AV	 AV	
t/7bAV	*l/AV
- &"I6AV
-`
1*O"	AV@-QAV'AV-I	AV
q`I
AV
`0I)!AV@0(
AVh
-m (WAVl	+1AV`? AVC %3,N1AVXXAV`iAlAV&AV 
-
-$AV
-#AV
*7AV@w
AV)`'7	AV - 6AV 
#BAV])2'cAVd@	4!M-AVЀ$MAVZ~!7;AV%e	*AV	>4AVeX/AAV'2,.AV[1AV3`!&#b@AV(1AV'0{AVSAV J5gAV8(jAVF`XAVa`/ AV`$%_AV /AAV @w#2AV |AV!:`|KAV"I^%[(AV"	H"'?AV$*
'AV$ 
-F$
-AV%Do$^	AV%t;"JAV%
'$
AV%1	AV&e'AV'O`
-`3P]AV(5AV)P@Q,AV)e 4AV)+eAV*y(1wAV*aP{AV+J#$AV+%AV,-@3AV,tAV,@J&"AV-C
;4
-AV.U;-AV/ 
-AV0][-*AV0 AV1`
-AV2:":AV2? 
-z$	AV2d?AV3P.AV31AV3'Y
AV4vO_AV5`
#AV5	g	AV6,NAV811&AV9	
-AV93*AV:.	n$K2	AV:2"	AV: $&
-AV; ;0"6AV;!L%AV;
--+AV<$*AV>@)DAV>	 B
-AV?#!AV?`,AV?%x-N0	AV?kYAV?
-$
-AV?`
AV@&@d)3AV@eQ	PAV@@!fwUAV@n-	AVA@@p#$AVB@:-wAVB-`x
-LAVB@t?m+AVCE("AVC@(Q+KAVD +1LAVEBHAVErq3LAVE"
-AVF`f.AVGĀ+
-AVG'2"lAVH`*?AVJĠ#>=AVK@
#
-AVL!@%
AVLk <c-AVMZ&,AVO=`I&L3A-AVO n*.U
AVO&AVP~@,p
-AVQ	@["k0AVQ2`J>.AVQQ@*2AVQ	5%!AVST`*{AVUQ 	"s)AVV 	"I	AVW0AVWr@AVW "(AVW  AVX2
EJ.AVX@0%AVY ^,AVZaNAVZˠ)$AV[=`
-6&AV[	.@AV\@[*;NAV\!WAV]; 
t**'AV]>@_AV^&&*@AV^k	bbAV^{ ECAV^.AV^e0/	AV_ 3AV`Vh=AV`X\7AVaKM+,eTAVa $jAVa
"iAVbR
.AVbs`-!K 4AVc
h?:AVc} )u2/
AVc;l
-AVe
-(",gAVe0 &AVfq^AVf'AVf[*'AVftq&AVf@6	AVh[		AVh6##1A
-AVh 
rAVi`%AVjg2AVj1-,AVj@:2D u;AVk,0AVkc`AVk`3AVlC')&AVl 	"&lAVnK@
-QAVn@AVo%z
-AVp7"D AVp
i;)?"AVp	B 1+AVqL.pAVr1@
U/AVr 1m*	AVuU`
(ZAVu
-lA
AVu 2vAVv~d*"AVwm	!).
AVx 	2:%5AVz
-"I,[AVz`G11AVz{#5	AV{V

'AV{ 
6AV|4 j%W	UAV|Fu.kAV~	.7yAV~o aAV~ !
-AV.49AVd#d+[AV`S(	AV5!
-?
AV J4tIMAVIM$9$0AV؀"s*AVT@V)AVt	 /dAVm31AV!JAV

AV!FAVZ
*AV&)v
AV	eDAV`@0AV@/d AVt#'AV 
P!RAVd*dAV`3GAV
BzAVq*a1	AV`IAV!P:AVAVX2AV'JAV2'
AV,j&o%
-AVS
-W)[jAVw1:AV#	AVN("0qAVl@mAV@
AVtkAV^$4c":AVg^	,AVìCAVĴ+AVŘ` mAVť4$PAV
-EAVƆ@>)l1
-AV`
-dAV'
2AVXsDAVȡ@.F$AV`
-05AAV4F-0AV,`(,,AVݎMAVL
5$eAVt	%AV`^0AV߹%0%2AV	5)AV AVcVAV`,,
-AV@{6yAV
 
-)AVh4AV, +h0AVN$#AV`"AV۠tAVv)+AV -AV|RAV3~JAVrAV(!a$AV
'AV甀C"
-AV`/#A\AV!XAV,B	AWm`!31*AWB"91
-AWY@E
-V"m?AW
}%DAW"
-AW "B	AW:)I+nAWf0)%AW@4qAW`f13AW
C2AW@@R&AWB
-!AW 2AW)H8AW5B1AWn ]Z!?AW 
'	AWj 7
AWj@U.+OAWm*;7AW 	j'AWg$H
-AW@Q"=,lAW	}AWzc
-AW@(LAW`$	AW)AW #"!AW!L+%AW#`R3
-AW& $!%0?AW&-5AW&D
-F
-AW'@^4
AW'-uAW).+
-AW*H)3AW+/!NAW,i&AW--DI6AW-;$9AW/D!%AW0
-B,kK(AW1 f4i}AW2- AW2(19AW3`AW3,oAW3%j.?AW4f "9AW4@b3(AW5@3	AW5!"AW6@/	AW6 3LAW7;/$AAW7	;AW8`!T;=AW8à
:YAW;`0"gAW< 
54wAW=AAW>q0-	AW>N@E AW>Y)q3AW@a)PAW@@	08AW@@U~AWA8 G2AWA<o&$'	AWAe
-$BAWAo $kAWA<%,AWB 1 c B	AWB`
R6AWCo'/
-AWDy	LAWDȠ
&|(AWD0u,gAWE*WAWEwAWE	KAWE`"4QAWF`"!e&AWF@&	*AWG@/;AWH4I=AWH`
*#>AWH@()?AWI%>AWJ3`+A%JAWJ>l+($AWJ54AWJ sAWLt`+>+AWM#5AWN`~3 JIAWNˀ6P!4AWN
wXAWOj@4Q}AWPd$9~9AWQ0FAWQr+0
b.AWQw@#AWR&,qAWR@
"aAWSA 
-)AWTC	+BAWU|`3AWW 4"+AWX&iZAWX=@zkAWX
-AWX )YAWY!B"vAWZ9
~)9AW[ H'EvAW[!@	'(r
AW\"9	AW\ $$AW\
-!AW]s&ZAW^`D,*AW^` oHAW`L`Y&##AWag3%.AWa@2AWe*AWfƀS=AWg`"7AWgX,-AWg`s%!	AWh
-$
-AWh,rGAWi*vAWi`(AWjc&,	$UAWjx`)&]AWk("*"AWk	TwAWl v}!CAWp 
4z%1AWp
#AWq
 ?8AWrK
G$MAWs@)-AWt@1fAWt( $RTwAWtM!#AWt@LB*AWu C	@AWu Z}AWv@ TQAWw|*AWw`a5AWy i'3AWyAWyE
-AWy€~4-7AWy$!]AW{L@
;AW{
AW{1V%^$AW|@	$sAW}x 
-
AW~Q"GAW
~1'	AW.
AGAWo cAW[	)EAW 	&{AWF
	k+AW@Y,0n%AW, "2&n;AWY	-&AWPV08AW!'=iAW	m,
-AW `+$AW@.5
-AWvAW-XAWa'tE$AW@+'AW+1/
-AW
-"AWG P$e2.	AW@nYAW ~
AW2rAW@/"fAWG@{*3AW*-
-[AẀ&l
AWe9AW0|AWӀ+(tAW@+
-AWi FAW4WAW`)
-FAW1hFAWa5AW44S$AW`1AWqcMAWVfAW`AWeAWAW@$.MAWlAWb`T,
-AW`#h! AW AWaZ-&AW}-f'4AWw1lAW1AW 9bAW)@@^AW`
-AW]AWk*s#AW'@I
-+
AWI@G6AWc@e#\AWe@""AW
q0*kAWY` ,6AWF"HAW
}fAW!@x)eAWE+RAW`	AWM F%>FAWѠ
-
-].w	AW/"2	AW5^21,AWqh!X0AW!0zrAWq(EAW	-D.AWe 3
AW9`
!.AWԀ
^
-AW2AWAIZAW@(^
AW:`	'5AWև C3QAWD2
$AW\	'H2"AWzdDAW@%	
AW
-5-AWط`
03
'AW
)+kAW1`/%
-AWU	"1AWٔ}/B	AW )

AW.AWr
W
AWr#
6DAWNAWn@ 64AW`V/,0AW /
AW305AW1J,>AW@.\AW
DAWMAWU*.r
AW22dAWp@*1<AWs*WqAW"@s%+"qAWK`AW92AW+>AW
AW`*;$2AW+Z
-AW9
AW@V<	AW%bAW$D'	AW
-	kAW$AW5`(3U	AWV'-E
AWu (2'	AW퓠T*AW ':AW
sAW@"-mAW7$RAWw
83AW@~pAWr-
-AWSpAW`i*?AW*"e40AWId'%AW#JAW`5	"AW 
+!3AWJ.AW -/AW`%FAW
-\AW V%VAW`[**AW
/AXJ)AX+`
7AXl583AX`&{AX /X9AX 2w"*AX\AXl`P AX eAX 1AX	E,B1
-AX	 1(yAX
- 
-AXp#	SAX
- (P+AX
&gAX &AX@&AXH 
-YJAXzv{+AX *.AX@1%;AX@>"	AX5w
AXbAXl<*	AX'"#EAX@&&AX"	q
C\AXK"$AXi`R0dAX	)AXmAX*"AX3EAX@	
oAXx#AX h
YWAXl%S
-AXc
- 7AXg !gh*AX2sAX\4@
AXn@#v('AXx	5wAX 2AX))^AX+"'Q
AX`	#
AX'`~z7UAX~J(PAX@N	AXL+?AX`5BAX `u$AX  'E_AX!
-#s	AX"@R.AX# 
h
AX#`0%AX%W1AX%@1$#AX&x
-4%-AX&!K}AX&(GAX&`	k+S	AX(v	$R!AX( -UAX(AX) 0O'2AX+
-I.nAX,}',1AX,!
AX-@ 
-BAX-xAX.@$( AX0L
V	AX0V%yAX0u#^AX2M
-+AX2S &
--AX3s,!-
-AX3`b#AX3
AX4I@$AX4@#4:AX4.-yAX5AX5A.AX5~fp1AX5`7AX7@3AX8^	,jAX8W@"B$AX8Z3 5AX93@,AX9ƀ%"AX:g %AX=z@ 
	AX=sfAX>c DAX?&AXA(j
-'AXAV-AXAg`>AXDG)
AXEwU'yAXF'O4?AXG6
-AXG$`0LAXGm 
-+
AXG*\Y
-AXI
-*_5*AXI #QAXJ
l1^NAXKHV!AXKJ`
<EAXKz(hAXL\
n(dAXL@
-Z)3IAXL /!AXM6l&!AXMՠw#>&AXN`
-!(
AXN
-7AXOj1:AXQ`
RAXQ5
	AXQLA
-AXR/"AXRD-#AXRv#&,AXR`
-.AXTy ;AXT@E3rAXU  7nAXU`!.AXVl/1'
-AXXdAXZP"4#AX[w%.AX["0AX\(1!9UAX\{@8*1AX]5`2?AX] n+oAX^4b#AX^
-3
2AX^`2%AX_h@	&	LAX_@t5AX`~@
AX`)!AX`@e{*
-AXbA2)SAXb`v)1&>#u$AXoAXp)AXtY	z!!:AXu6@
$vAXuq_AXv1AXw= 	ZAXw 'Y$v
-AXx=.kAXyl5-AXy@|YAXz`/q$,AXz 
-*
AXz	u%dAXz͠5 oAXzT^AX|c EAX|f2AX}`$3	AX~
 k"#<
AX~a,@ZAX~@,AX~ȠfyAX~Nd2pAX"@~ AX=@AXAXd&AX
-*!AX	hAAXǠ=xbjAXt .AX*%{4AX J#H(AX@	*P-AXf@)
-AX`AX%$"FAX`AX 9+~AX2"AX@4 [AXo`z2
-AXlAX@S&vAX)fAX 	B}AX+` AXlb?70AX N4'LAXl`3PTAX`*+{AX%^AX
-"AX@4^"AX~AX$*AX-@!7AX,AX #/AX
?	`'bAX82AX`<.dAX{BF)BAX`	a+"AX'FAX
-"HAX)K>AX)
-
-"	AX *	FAX `O
&AX$x,#AX@eOAX}r+!|AXS,tO	AX?3

-AXπ-VAAX3IKAX(]"}.CAXX;7{	AXrc05,AXX`</
-AX`
>BAX 6u-AXA-e
-AX[_KAX!Hn1AX`j
AX-@/!tXAXI,3AXV@~AXcOAX%%5AX
-R4AXD*7AX@\1AX,AXa-YAXi=-
AXǠ2zAX#"AX`+AX";b		AXHT~AX1>"3*AXJn)$AX
-AXĠ
-
-AX,=4AX@
AX AX /$AX`*:	AX1AX3..WsAXb1 AX-u c	AX[AXg"&
-AX	.AX@
AX'+AXŹ ==CAX`AX&)AX&: 73AXTt*HAXʪ	uNAX Q*"nAX`C
-AX8+
-AAXD@`+"AX̨`\0$"+AX )AX͏&WAX`"!AXG $q4'AX/`0.n	AXЪD,AX`A(AX
-	b
AXԇ
'/AX:*qAXh _5z%?>AXw	h"AX)`
"#'NAX	#..AX77j	AX_@'-KAX`q'<AX)AX-!@AXA@O%-AXLfAXa&lAXq(|<AX(&+AXۋ`j6AX۱	AXܨ ->,AX@'L$NAX6,.?AXP`i.
AXݵ1AX1%lAXn`YAXަ)!#AXߞ%>AX߰ AXӀ2AX!_AXC@rAXf 61AX w"AX*`:&AXV 
'jAX㩀#_r
AX;2&#AX#2m	AX6 
-AX:s
-AXZ@z#AX@%AX###9AXa6AX`3AX 7=1|AX@:$AXv3"AXɀ(-/AXo"CcAX#&,3AX'2e
AXRy;AXna';AX할AX_3AX*  =AXf ,JAXр+]AXAAX$AX4@QAX> &AX`
-*	AX	
AX"7AXN HAXi`/6JZAX`
8?AXa (!AX2#!7AX)%AX
-*"	AX N%AX 
-&AX6 0;'AXPp
-AX@30	AYB	#^)AY!DAY OAY@}
AYנ,{AY<
-c0AYL"XAY	D`Q H
-AY	z2}RAY
-=k1%6AY
-Ӏ
-M\FAYG]eAY`T(H
-AY
n`9AY
 
,/AY`+()1AY
-.&AYp%$'AY$7AY@z
 'pTAY!#1QAY9@+AY@iAY`$=AY AY
)'3eAY@7$*AAY{2+i&bAY@
-%%AY=w)
-AY $!8AY3AY[@:
-?AY+)AYG@BEPAY)`8AYF+AY`|
0 0QAY,)1AYR 
-4
,
-AY@0'AYŠ]4	)AY@AY"3W
-AY"`S%AY#`mAY$:u*EAY$	$2AY$͠9!AY% %	AY%75AY%`)zMAY&=!/'AY& 	2&AY&c)45qAY'+s
-AY' $ 
-AY'f
t-AY(2'AY)`	H%*!wAY)!
	W&#AY)n]AY*=aAY,11-oAY-Q@!V+AY-@!(
AY/
+,1AY1fmAY1	[AY1`AY2@24
AY3
-2 AY3' ~*AY3	
" 	AY4.@AY4
7^
-AY6@
I!AY7~ 
x6cAY7wAY7`
-,
AY8AY9 .+JAY:@O![,AY;`<'#AY;xgRAY;
AY;s#AY<@!SAY<r$6PAY=y)#rAY=8,DAY= 0v+QAY>7-)@AY?B 	##AY?t)AY?l!AY@@
h&8AYAZ@-AYC0h+rAYC@8AYC`AYD C!f-AYD`,%FAYEJ(1
-AYF(tAYFYt`AYF QAYF!IAYGI)AYHh#
-,AYHۀB1(AYI~4AYI`s#AYI #,AYJ`W	AYK]	2AYLs`N	yAYM ,AYP`Z%)AYQP:"1,AYQ 7'AYR@(/?"-AYR/)AYS`!LAYS &n=
-AYT@e;5lAYO'7AY AY AYQi+OAY%yAY@Y'-vAY``/dAYP`XB/AY^4-AYr.AY//-AYIAY6#
-AYDAYA)3	AYz$66AY t
-AYaGAYK&AY$QAY #AYAY)AY;/!AY`
ziwAYy..3
-AY@.A.AYT$v-AY@
s%
AY
!c
AY
-j(}
-AY9&/
AYd+4+AY AY1`(",AY+AY;@R&5OAYi%HAYd2	g
AYQ+AY`
%HAYP\ E
-AY`+AY!EAYAY}]AY`
--(AY~B(AYu /AY
- ps(SAY, 
-@->AY@3MAY^AYX3)9AY%!AY:$	AY`3?AYS/	-RAY %.5QAY6K(AY v$AY`%A5AY"H AY=%!	AY
3#D(AY  	#AY
k*AY 
,(AY5IAY@r AY 
AY)!0RAYV Z	'AY@-2)AY`t1rAY .|AYǹ
7:AYȳ +!
--AY
/4AY`QaAY.@AYVa6cAYJ2*	AY'AY˵ AY y*:AY̱
-!
-/
AY?
/.AY 5*:AYm~)!kAY̓'rAŸ́dAYͻ'HiAYK@a)LAY#`	q d^AYe")lAYω5 AYϓ e.'AY϶_$AYs ,AYd 
,KAY%mAYa

Q!AYPB&AY`f$AYC@LcAYղ4AY[`AYe<
-AYހ+$
AY}Z8/AY@3;0AY%).\"AY{	AY 
-AYM2AY5)jAY<`	;"AYQ
u,mlAY&5AYBUB6AY߸@"AY@%$AY+AY\"!AY: Y%AYt)AY#F/AY
>*AAY#`o.=qAY- )AYz 	HAYM&@-AY}-	AY#&&]AY %AY
-AY!)	AY	0,AY,AY
-/0AY)$ `*g%AY8"oAY 
w/&:AYs 3!x)AY3*
YAY`",2AY@
-gAY		AYb
4AYl $&H
AY!AYʠhAYh &
-AY
-x"AY@A"
-=AY-AY@AY16
,]UAYS$r(AYH	)DAY`1 HuAY^%*NAY	8KAY	AY@AYz_u$AY	s	AYg$AYKX"AYT
V	AYX/)AYg/AY0)#
AYɀ'AY
-6*%AZS
^AZJ*AZg
-SdAZ`*JW
AZ@`xAZoAZUU5w!),AZ3AZ ?e2
AZ-AZ	W` BAZ	!$UAZ		C)IAZ
-
-VAZ
-@9#4AZ`@O4
AZi
4AZ@$c2
AZl&v+AZ
@#VRAZ
"6AZ ,@AZ"t
u4AZb`n*dAZ@	7+AZ`!hAZc5 J AZ!AZ0
##AZv` L%3DAZ
-@49
-AZ )NAZ,!vAZ"9AZY3%SAZ"`E AZ[*
-AZ##AZHG&AZ; i!)0	AZ\	AZgK7AZx(AZ}$:.c!AZ(}AZ1J.	AZ/2-AZ7	AZ:/N
AZ.	AZ "AZO3AZ+
4V AZ`$O!AZn0AZIaAZ 
-Ss1AZ SD$9'I9AZ"
-y,h+AZ").JiAZ"@q%B2AZ"'L	AZ#C HAZ#`!#FAZ$
m5AZ&ԠC	AZ(q39AZ)y*	-AZ)@3lAZ*RC
-f!AZ*C
#p7AZ+` 
-[AZ+{"l\AZ+ 1ZtAZ, AZ-@*AZ-g#e
AZ.
	1)AZ/Z 
-HAZ1Qs  7AZ5| Z*1	AZ5&AZ6Lg
|AZ6I)AZ6
-d0DAZ7 
-1AZ7`&!AZ8! 89eAZ8O9AZ8 *1AZ8@1	9%AZ9`c+l8AZ9V@0AZ9(~AZ:c$+AZ;V 2#>FAZ;!AZ.+VAZA	2K!LAZAk`*%AZA#
AZB+(.AZC@1#AZD!H)AZG/`\AZG@)^|AZH.`)/aAZH	'AZH<2+AZHG)66{AZI,:"1AZI AZK E-,AZK`+8#
AZLF 'AZLNAZN! &O#AZN[@nAZN  }7AZQF$+AZR`	4AZR-$3AZS_`"5UAZS8/.2AZTl*/~AZU
-3~ AZV:@u7/sfAZVF1OAZVX&A	AZWU7AZW@	E#AZW$
AZW $fAZX `
AZX3 +9BAZXՀ&AZYr#1/AZY_	XAZYŀL2[AZZ*j.2&AZ[b-8AZ[k/4AZ[ -
-UAZ\#d
AZ\
=#^
AZ\j
%j
-AZ]M 2$LAZ]xz
->AZ]ʀ(&AZ]
-&;AZ] !+ AZ^ F'(xfAZ_ހ	/
-AZ`iY3z*[AZaf`1/AZa RAZb#@zrAZb@DKWAZco4L'AZc	M8:AZd'`SAZde@]AZdh)AZd@
(RAZd {$'
-AZd
#
-AZeQ*F*
-AZf),v}AZfI*
AZh%S"AZhR S'AZi4&	AZiǠb!idAZjtB*P#AZjC	y#AZjZ$8AZjŀ$C6;+AZkAZk* (
AZkH+#	AZk;AZl<"AZme%>AZo 53AZo01
AZou,AZpH&	AZp`5'fGAZq9@PHAZqu*m4S
-AZr3&AZsd`
-/J	AZtDAZuxV$Q$6AZv?)VAZvKTAZv_#AZv 

-AZw7@/`AZxD@+;AZy%  T,cAZy`B//CAZy0+AZz-@!Q*AZ{F 	5A4AZ|I4
-1AZ|\c+oAZ|`	8!AZ}R )N!AZ}l
YICAZ}v`.sAZ~ 	O, AZ7`	$`,znAZ$AZQAZ!dAZS3AZs	AZhAZk5"W?AZ A%,AZ*/mAZf' AZ`0
-AZ@$"AZE
-
-%'$AZn
[AwAZ##5AZq
+'AZ
-wAZAZ@'04AZ AZ@'~AZ@^#L
AZa
p8AZ*$AZ`J#(&AZNAZ;3$+AZ\S1AZ`Z9?gAZZ/%AZ{AZ]((AZ@	)
-AZDAZ>"0AZ@_AZ_	+OAZ/+	AZ
-)sAZ "(	AZ%
ZAZ/>AZ*2AZLVAZˀn-AZ )#AZph&&AZi	)9AZ'AZUA-AZ%y	AZ`bOAZU3PAZ&$AZ-
5UAZ $
-AZ@,@
AZF@'*
-AZH`E4N,.AZ@fs&AZ&AZ] 5#
-AZj,%0<
-AZ# 
-p.b1AZE)AZ	"/AZ@%0QAZ !!9}AZu@G#|
-AZ
y)b%AZ@lAZ!7iAZZS/&)AZ0=2&AZ+@"Mg#AZV'AZ
AZ_
-AZzI7AZ'*L	AZ9@	( _AZ?^1EAZ 6h!AZ`-,=AZ#'yAZ_ 
-7eAZ"JAZ 
'7?AZc>
$AZˀ
0(AZ`t8AZ)
AZ@- 	AZsAZVhAZtiAZ`+vAZ7 	% AZ=9;~	AZ +$AZ!AZ odAZ‚!\
AZ…@'y,AZ¬GaAZ*r
-AZn	'!
	AZ1uAZנ0Y
AZ*` 3EAZƪ`	F
AZE
\ No newline at end of file
diff --git a/src/external/OpenGR/3rdparty/cfitsio/iter_image.c b/src/external/OpenGR/3rdparty/cfitsio/iter_image.c
deleted file mode 100644
index 43f263cb5..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/iter_image.c
+++ /dev/null
@@ -1,93 +0,0 @@
-#include 
-#include 
-#include 
-#include "fitsio.h"
-
-/*
-  This program illustrates how to use the CFITSIO iterator function.
-  It reads and modifies the input 'iter_image.fit' image file by setting
-  all the pixel values to zero (DESTROYING THE ORIGINAL IMAGE!!!)
-*/
-main()
-{
-    extern zero_image(); /* external work function is passed to the iterator */
-    fitsfile *fptr;
-    iteratorCol cols[3];  /* structure used by the iterator function */
-    int n_cols;
-    long rows_per_loop, offset;
-
-    int status, nkeys, keypos, hdutype, ii, jj;
-    char filename[]  = "iter_image.fit";     /* name of rate FITS file */
-
-    status = 0; 
-
-    fits_open_file(&fptr, filename, READWRITE, &status); /* open file */
-
-
-    n_cols = 1;
-
-    /* define input column structure members for the iterator function */
-    fits_iter_set_file(&cols[0], fptr);
-    fits_iter_set_iotype(&cols[0], InputOutputCol);
-    fits_iter_set_datatype(&cols[0], 0);
-
-    rows_per_loop = 0;  /* use default optimum number of rows */
-    offset = 0;         /* process all the rows */
-
-    /* apply the rate function to each row of the table */
-    printf("Calling iterator function...%d\n", status);
-
-    fits_iterate_data(n_cols, cols, offset, rows_per_loop,
-                      zero_image, 0L, &status);
-
-    fits_close_file(fptr, &status);      /* all done */
-
-    if (status)
-        fits_report_error(stderr, status);  /* print out error messages */
-
-    return(status);
-}
-/*--------------------------------------------------------------------------*/
-int zero_image(long totalrows, long offset, long firstrow, long nrows,
-             int ncols, iteratorCol *cols, void *user_strct ) 
-
-/*
-   Sample iterator function that calculates the output flux 'rate' column
-   by dividing the input 'counts' by the 'time' column.
-   It also applies a constant deadtime correction factor if the 'deadtime'
-   keyword exists.  Finally, this creates or updates the 'LIVETIME'
-   keyword with the sum of all the individual integration times.
-*/
-{
-    int ii, status = 0;
-
-    /* declare variables static to preserve their values between calls */
-    static int *counts;
-
-    /*--------------------------------------------------------*/
-    /*  Initialization procedures: execute on the first call  */
-    /*--------------------------------------------------------*/
-    if (firstrow == 1)
-    {
-       if (ncols != 1)
-           return(-1);  /* number of columns incorrect */
-
-       /* assign the input pointers to the appropriate arrays and null ptrs*/
-       counts       = (int *)  fits_iter_get_array(&cols[0]);
-    }
-
-    /*--------------------------------------------*/
-    /*  Main loop: process all the rows of data */
-    /*--------------------------------------------*/
-
-    /*  NOTE: 1st element of array is the null pixel value!  */
-    /*  Loop from 1 to nrows, not 0 to nrows - 1.  */
-
-    for (ii = 1; ii <= nrows; ii++)
-    {
-       counts[ii] = 1.;
-    }
-    printf("firstrows, nrows = %d %d\n", firstrow, nrows);
-    
-    return(0);  /* return successful status */
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/iter_var.c b/src/external/OpenGR/3rdparty/cfitsio/iter_var.c
deleted file mode 100644
index 50d013205..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/iter_var.c
+++ /dev/null
@@ -1,100 +0,0 @@
-#include 
-#include 
-#include 
-#include "fitsio.h"
-
-/*
-  This program illustrates how to use the CFITSIO iterator function.
-  It reads and modifies the input 'iter_a.fit' file by computing a
-  value for the 'rate' column as a function of the values in the other
-  'counts' and 'time' columns.
-*/
-main()
-{
-    extern flux_rate(); /* external work function is passed to the iterator */
-    fitsfile *fptr;
-    iteratorCol cols[3];  /* structure used by the iterator function */
-    int n_cols;
-    long rows_per_loop, offset;
-
-    int status, nkeys, keypos, hdutype, ii, jj;
-    char filename[]  = "vari.fits";     /* name of rate FITS file */
-
-    status = 0; 
-
-    fits_open_file(&fptr, filename, READWRITE, &status); /* open file */
-
-    /* move to the desired binary table extension */
-    if (fits_movnam_hdu(fptr, BINARY_TBL, "COMPRESSED_IMAGE", 0, &status) )
-        fits_report_error(stderr, status);    /* print out error messages */
-
-    n_cols  = 1;   /* number of columns */
-
-    /* define input column structure members for the iterator function */
-    fits_iter_set_by_name(&cols[0], fptr, "COMPRESSED_DATA", 0,  InputCol);
-
-    rows_per_loop = 0;  /* use default optimum number of rows */
-    offset = 0;         /* process all the rows */
-
-    /* apply the rate function to each row of the table */
-    printf("Calling iterator function...%d\n", status);
-
-    fits_iterate_data(n_cols, cols, offset, rows_per_loop,
-                      flux_rate, 0L, &status);
-
-    fits_close_file(fptr, &status);      /* all done */
-
-    if (status)
-        fits_report_error(stderr, status);  /* print out error messages */
-
-    return(status);
-}
-/*--------------------------------------------------------------------------*/
-int flux_rate(long totalrows, long offset, long firstrow, long nrows,
-             int ncols, iteratorCol *cols, void *user_strct ) 
-
-/*
-   Sample iterator function that calculates the output flux 'rate' column
-   by dividing the input 'counts' by the 'time' column.
-   It also applies a constant deadtime correction factor if the 'deadtime'
-   keyword exists.  Finally, this creates or updates the 'LIVETIME'
-   keyword with the sum of all the individual integration times.
-*/
-{
-    int ii, status = 0;
-    long repeat;
-
-    /* declare variables static to preserve their values between calls */
-    static unsigned char *counts;
-
-    /*--------------------------------------------------------*/
-    /*  Initialization procedures: execute on the first call  */
-    /*--------------------------------------------------------*/
-    if (firstrow == 1)
-    {
-
-printf("Datatype of column = %d\n",fits_iter_get_datatype(&cols[0]));
-
-       /* assign the input pointers to the appropriate arrays and null ptrs*/
-       counts       = (long *)  fits_iter_get_array(&cols[0]);
-
-    }
-
-    /*--------------------------------------------*/
-    /*  Main loop: process all the rows of data */
-    /*--------------------------------------------*/
-
-    /*  NOTE: 1st element of array is the null pixel value!  */
-    /*  Loop from 1 to nrows, not 0 to nrows - 1.  */
-
-
-    for (ii = 1; ii <= nrows; ii++)
-    {
-       repeat = fits_iter_get_repeat(&cols[0]);
-       printf ("repeat = %d, %d\n",repeat, counts[1]);
-       
-    }
-
-
-    return(0);  /* return successful status */
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/longnam.h b/src/external/OpenGR/3rdparty/cfitsio/longnam.h
deleted file mode 100644
index fbd7caf68..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/longnam.h
+++ /dev/null
@@ -1,596 +0,0 @@
-#ifndef _LONGNAME_H
-#define _LONGNAME_H
-
-#define fits_parse_input_url ffiurl
-#define fits_parse_input_filename ffifile
-#define fits_parse_rootname ffrtnm
-#define fits_file_exists    ffexist
-#define fits_parse_output_url ffourl
-#define fits_parse_extspec  ffexts
-#define fits_parse_extnum   ffextn
-#define fits_parse_binspec  ffbins
-#define fits_parse_binrange ffbinr
-#define fits_parse_range    ffrwrg
-#define fits_parse_rangell    ffrwrgll
-#define fits_open_memfile   ffomem
-
-/* 
-   use the following special macro to test that the fitsio.h include file
-   that was used to build the CFITSIO library is compatible with the version
-   as included when compiling the application program
-*/
-#define fits_open_file(A, B, C, D)  ffopentest( CFITSIO_SONAME, A, B, C, D)
-
-#define fits_open_data      ffdopn
-#define fits_open_extlist   ffeopn
-#define fits_open_table     fftopn
-#define fits_open_image     ffiopn
-#define fits_open_diskfile  ffdkopn
-#define fits_reopen_file    ffreopen
-#define fits_create_file    ffinit
-#define fits_create_diskfile ffdkinit
-#define fits_create_memfile ffimem
-#define fits_create_template fftplt
-#define fits_flush_file     ffflus
-#define fits_flush_buffer   ffflsh
-#define fits_close_file     ffclos
-#define fits_delete_file    ffdelt
-#define fits_file_name      ffflnm
-#define fits_file_mode      ffflmd
-#define fits_url_type       ffurlt
-
-#define fits_get_version    ffvers
-#define fits_uppercase      ffupch
-#define fits_get_errstatus  ffgerr
-#define fits_write_errmsg   ffpmsg
-#define fits_write_errmark  ffpmrk
-#define fits_read_errmsg    ffgmsg
-#define fits_clear_errmsg   ffcmsg
-#define fits_clear_errmark  ffcmrk
-#define fits_report_error   ffrprt
-#define fits_compare_str    ffcmps
-#define fits_test_keyword   fftkey
-#define fits_test_record    fftrec
-#define fits_null_check     ffnchk
-#define fits_make_keyn      ffkeyn
-#define fits_make_nkey      ffnkey
-#define fits_make_key       ffmkky
-#define fits_get_keyclass   ffgkcl
-#define fits_get_keytype    ffdtyp
-#define fits_get_inttype    ffinttyp
-#define fits_parse_value    ffpsvc
-#define fits_get_keyname    ffgknm
-#define fits_parse_template ffgthd
-#define fits_ascii_tform    ffasfm
-#define fits_binary_tform   ffbnfm
-#define fits_binary_tformll   ffbnfmll
-#define fits_get_tbcol      ffgabc
-#define fits_get_rowsize    ffgrsz
-#define fits_get_col_display_width    ffgcdw
-
-#define fits_write_record       ffprec
-#define fits_write_key          ffpky
-#define fits_write_key_unit     ffpunt
-#define fits_write_comment      ffpcom
-#define fits_write_history      ffphis 
-#define fits_write_date         ffpdat
-#define fits_get_system_time    ffgstm
-#define fits_get_system_date    ffgsdt
-#define fits_date2str           ffdt2s
-#define fits_time2str           fftm2s
-#define fits_str2date           ffs2dt
-#define fits_str2time           ffs2tm
-#define fits_write_key_longstr  ffpkls
-#define fits_write_key_longwarn ffplsw
-#define fits_write_key_null     ffpkyu
-#define fits_write_key_str      ffpkys
-#define fits_write_key_log      ffpkyl
-#define fits_write_key_lng      ffpkyj
-#define fits_write_key_fixflt   ffpkyf
-#define fits_write_key_flt      ffpkye
-#define fits_write_key_fixdbl   ffpkyg
-#define fits_write_key_dbl      ffpkyd
-#define fits_write_key_fixcmp   ffpkfc
-#define fits_write_key_cmp      ffpkyc
-#define fits_write_key_fixdblcmp ffpkfm
-#define fits_write_key_dblcmp   ffpkym
-#define fits_write_key_triple   ffpkyt
-#define fits_write_tdim         ffptdm
-#define fits_write_tdimll       ffptdmll
-#define fits_write_keys_str     ffpkns
-#define fits_write_keys_log     ffpknl
-#define fits_write_keys_lng     ffpknj
-#define fits_write_keys_fixflt  ffpknf
-#define fits_write_keys_flt     ffpkne
-#define fits_write_keys_fixdbl  ffpkng
-#define fits_write_keys_dbl     ffpknd
-#define fits_copy_key           ffcpky
-#define fits_write_imghdr       ffphps
-#define fits_write_imghdrll     ffphpsll
-#define fits_write_grphdr       ffphpr
-#define fits_write_grphdrll     ffphprll
-#define fits_write_atblhdr      ffphtb
-#define fits_write_btblhdr      ffphbn
-#define fits_write_exthdr       ffphext
-#define fits_write_key_template ffpktp
-
-#define fits_get_hdrspace      ffghsp
-#define fits_get_hdrpos        ffghps
-#define fits_movabs_key        ffmaky
-#define fits_movrel_key        ffmrky
-#define fits_find_nextkey      ffgnxk
-
-#define fits_read_record       ffgrec
-#define fits_read_card         ffgcrd
-#define fits_read_str          ffgstr
-#define fits_read_key_unit     ffgunt
-#define fits_read_keyn         ffgkyn
-#define fits_read_key          ffgky
-#define fits_read_keyword      ffgkey
-#define fits_read_key_str      ffgkys
-#define fits_read_key_log      ffgkyl
-#define fits_read_key_lng      ffgkyj
-#define fits_read_key_lnglng   ffgkyjj
-#define fits_read_key_flt      ffgkye
-#define fits_read_key_dbl      ffgkyd
-#define fits_read_key_cmp      ffgkyc
-#define fits_read_key_dblcmp   ffgkym
-#define fits_read_key_triple   ffgkyt
-#define fits_get_key_strlen    ffgksl
-#define fits_read_key_longstr  ffgkls
-#define fits_read_string_key   ffgsky
-#define fits_free_memory       fffree
-#define fits_read_tdim         ffgtdm
-#define fits_read_tdimll       ffgtdmll
-#define fits_decode_tdim       ffdtdm
-#define fits_decode_tdimll     ffdtdmll
-#define fits_read_keys_str     ffgkns
-#define fits_read_keys_log     ffgknl
-#define fits_read_keys_lng     ffgknj
-#define fits_read_keys_lnglng  ffgknjj
-#define fits_read_keys_flt     ffgkne
-#define fits_read_keys_dbl     ffgknd
-#define fits_read_imghdr       ffghpr
-#define fits_read_imghdrll     ffghprll
-#define fits_read_atblhdr      ffghtb
-#define fits_read_btblhdr      ffghbn
-#define fits_read_atblhdrll    ffghtbll
-#define fits_read_btblhdrll    ffghbnll
-#define fits_hdr2str           ffhdr2str
-#define fits_convert_hdr2str   ffcnvthdr2str
-
-#define fits_update_card       ffucrd
-#define fits_update_key        ffuky
-#define fits_update_key_null   ffukyu
-#define fits_update_key_str    ffukys
-#define fits_update_key_longstr    ffukls
-#define fits_update_key_log    ffukyl
-#define fits_update_key_lng    ffukyj
-#define fits_update_key_fixflt ffukyf
-#define fits_update_key_flt    ffukye
-#define fits_update_key_fixdbl ffukyg
-#define fits_update_key_dbl    ffukyd
-#define fits_update_key_fixcmp ffukfc
-#define fits_update_key_cmp    ffukyc
-#define fits_update_key_fixdblcmp ffukfm
-#define fits_update_key_dblcmp ffukym
-
-#define fits_modify_record     ffmrec
-#define fits_modify_card       ffmcrd
-#define fits_modify_name       ffmnam
-#define fits_modify_comment    ffmcom
-#define fits_modify_key_null   ffmkyu
-#define fits_modify_key_str    ffmkys
-#define fits_modify_key_longstr    ffmkls
-#define fits_modify_key_log    ffmkyl
-#define fits_modify_key_lng    ffmkyj
-#define fits_modify_key_fixflt ffmkyf
-#define fits_modify_key_flt    ffmkye
-#define fits_modify_key_fixdbl ffmkyg
-#define fits_modify_key_dbl    ffmkyd
-#define fits_modify_key_fixcmp ffmkfc
-#define fits_modify_key_cmp    ffmkyc
-#define fits_modify_key_fixdblcmp ffmkfm
-#define fits_modify_key_dblcmp ffmkym
-
-#define fits_insert_record     ffirec
-#define fits_insert_card       ffikey
-#define fits_insert_key_null   ffikyu
-#define fits_insert_key_str    ffikys
-#define fits_insert_key_longstr    ffikls
-#define fits_insert_key_log    ffikyl
-#define fits_insert_key_lng    ffikyj
-#define fits_insert_key_fixflt ffikyf
-#define fits_insert_key_flt    ffikye
-#define fits_insert_key_fixdbl ffikyg
-#define fits_insert_key_dbl    ffikyd
-#define fits_insert_key_fixcmp ffikfc
-#define fits_insert_key_cmp    ffikyc
-#define fits_insert_key_fixdblcmp ffikfm
-#define fits_insert_key_dblcmp ffikym
-
-#define fits_delete_key     ffdkey
-#define fits_delete_str     ffdstr
-#define fits_delete_record  ffdrec
-#define fits_get_hdu_num    ffghdn
-#define fits_get_hdu_type   ffghdt
-#define fits_get_hduaddr    ffghad
-#define fits_get_hduaddrll    ffghadll
-#define fits_get_hduoff     ffghof
-
-#define fits_get_img_param  ffgipr
-#define fits_get_img_paramll  ffgiprll
-
-#define fits_get_img_type   ffgidt
-#define fits_get_img_equivtype   ffgiet
-#define fits_get_img_dim    ffgidm
-#define fits_get_img_size   ffgisz
-#define fits_get_img_sizell   ffgiszll
-
-#define fits_movabs_hdu     ffmahd
-#define fits_movrel_hdu     ffmrhd
-#define fits_movnam_hdu     ffmnhd
-#define fits_get_num_hdus   ffthdu
-#define fits_create_img     ffcrim
-#define fits_create_imgll   ffcrimll
-#define fits_create_tbl     ffcrtb
-#define fits_create_hdu     ffcrhd
-#define fits_insert_img     ffiimg
-#define fits_insert_imgll   ffiimgll
-#define fits_insert_atbl    ffitab
-#define fits_insert_btbl    ffibin
-#define fits_resize_img     ffrsim
-#define fits_resize_imgll   ffrsimll
-
-#define fits_delete_hdu     ffdhdu
-#define fits_copy_hdu       ffcopy
-#define fits_copy_file      ffcpfl
-#define fits_copy_header    ffcphd
-#define fits_copy_data      ffcpdt
-#define fits_write_hdu      ffwrhdu
-
-#define fits_set_hdustruc   ffrdef
-#define fits_set_hdrsize    ffhdef
-#define fits_write_theap    ffpthp
-
-#define fits_encode_chksum  ffesum
-#define fits_decode_chksum  ffdsum
-#define fits_write_chksum   ffpcks
-#define fits_update_chksum  ffupck
-#define fits_verify_chksum  ffvcks
-#define fits_get_chksum     ffgcks
-
-#define fits_set_bscale     ffpscl
-#define fits_set_tscale     fftscl
-#define fits_set_imgnull    ffpnul
-#define fits_set_btblnull   fftnul
-#define fits_set_atblnull   ffsnul
-
-#define fits_get_colnum     ffgcno
-#define fits_get_colname    ffgcnn
-#define fits_get_coltype    ffgtcl
-#define fits_get_coltypell  ffgtclll
-#define fits_get_eqcoltype  ffeqty
-#define fits_get_eqcoltypell ffeqtyll
-#define fits_get_num_rows   ffgnrw
-#define fits_get_num_rowsll   ffgnrwll
-#define fits_get_num_cols   ffgncl
-#define fits_get_acolparms  ffgacl
-#define fits_get_bcolparms  ffgbcl
-#define fits_get_bcolparmsll  ffgbclll
-
-#define fits_iterate_data   ffiter
-
-#define fits_read_grppar_byt  ffggpb
-#define fits_read_grppar_sbyt  ffggpsb
-#define fits_read_grppar_usht  ffggpui
-#define fits_read_grppar_ulng  ffggpuj
-#define fits_read_grppar_sht  ffggpi
-#define fits_read_grppar_lng  ffggpj
-#define fits_read_grppar_lnglng  ffggpjj
-#define fits_read_grppar_int  ffggpk
-#define fits_read_grppar_uint  ffggpuk
-#define fits_read_grppar_flt  ffggpe
-#define fits_read_grppar_dbl  ffggpd
-
-#define fits_read_pix         ffgpxv
-#define fits_read_pixll       ffgpxvll
-#define fits_read_pixnull     ffgpxf
-#define fits_read_pixnullll   ffgpxfll
-#define fits_read_img         ffgpv
-#define fits_read_imgnull     ffgpf
-#define fits_read_img_byt     ffgpvb
-#define fits_read_img_sbyt     ffgpvsb
-#define fits_read_img_usht     ffgpvui
-#define fits_read_img_ulng     ffgpvuj
-#define fits_read_img_sht     ffgpvi
-#define fits_read_img_lng     ffgpvj
-#define fits_read_img_lnglng     ffgpvjj
-#define fits_read_img_uint     ffgpvuk
-#define fits_read_img_int     ffgpvk
-#define fits_read_img_flt     ffgpve
-#define fits_read_img_dbl     ffgpvd
-
-#define fits_read_imgnull_byt ffgpfb
-#define fits_read_imgnull_sbyt ffgpfsb
-#define fits_read_imgnull_usht ffgpfui
-#define fits_read_imgnull_ulng ffgpfuj
-#define fits_read_imgnull_sht ffgpfi
-#define fits_read_imgnull_lng ffgpfj
-#define fits_read_imgnull_lnglng ffgpfjj
-#define fits_read_imgnull_uint ffgpfuk
-#define fits_read_imgnull_int ffgpfk
-#define fits_read_imgnull_flt ffgpfe
-#define fits_read_imgnull_dbl ffgpfd
-
-#define fits_read_2d_byt      ffg2db
-#define fits_read_2d_sbyt     ffg2dsb
-#define fits_read_2d_usht      ffg2dui
-#define fits_read_2d_ulng      ffg2duj
-#define fits_read_2d_sht      ffg2di
-#define fits_read_2d_lng      ffg2dj
-#define fits_read_2d_lnglng      ffg2djj
-#define fits_read_2d_uint      ffg2duk
-#define fits_read_2d_int      ffg2dk
-#define fits_read_2d_flt      ffg2de
-#define fits_read_2d_dbl      ffg2dd
-
-#define fits_read_3d_byt      ffg3db
-#define fits_read_3d_sbyt      ffg3dsb
-#define fits_read_3d_usht      ffg3dui
-#define fits_read_3d_ulng      ffg3duj
-#define fits_read_3d_sht      ffg3di
-#define fits_read_3d_lng      ffg3dj
-#define fits_read_3d_lnglng      ffg3djj
-#define fits_read_3d_uint      ffg3duk
-#define fits_read_3d_int      ffg3dk
-#define fits_read_3d_flt      ffg3de
-#define fits_read_3d_dbl      ffg3dd
-
-#define fits_read_subset      ffgsv
-#define fits_read_subset_byt  ffgsvb
-#define fits_read_subset_sbyt  ffgsvsb
-#define fits_read_subset_usht  ffgsvui
-#define fits_read_subset_ulng  ffgsvuj
-#define fits_read_subset_sht  ffgsvi
-#define fits_read_subset_lng  ffgsvj
-#define fits_read_subset_lnglng  ffgsvjj
-#define fits_read_subset_uint  ffgsvuk
-#define fits_read_subset_int  ffgsvk
-#define fits_read_subset_flt  ffgsve
-#define fits_read_subset_dbl  ffgsvd
-
-#define fits_read_subsetnull_byt ffgsfb
-#define fits_read_subsetnull_sbyt ffgsfsb
-#define fits_read_subsetnull_usht ffgsfui
-#define fits_read_subsetnull_ulng ffgsfuj
-#define fits_read_subsetnull_sht ffgsfi
-#define fits_read_subsetnull_lng ffgsfj
-#define fits_read_subsetnull_lnglng ffgsfjj
-#define fits_read_subsetnull_uint ffgsfuk
-#define fits_read_subsetnull_int ffgsfk
-#define fits_read_subsetnull_flt ffgsfe
-#define fits_read_subsetnull_dbl ffgsfd
-
-#define ffcpimg fits_copy_image_section
-#define fits_compress_img fits_comp_img
-#define fits_decompress_img fits_decomp_img
-
-#define fits_read_col        ffgcv
-#define fits_read_colnull    ffgcf
-#define fits_read_col_str    ffgcvs
-#define fits_read_col_log    ffgcvl
-#define fits_read_col_byt    ffgcvb
-#define fits_read_col_sbyt    ffgcvsb
-#define fits_read_col_usht    ffgcvui
-#define fits_read_col_ulng    ffgcvuj
-#define fits_read_col_sht    ffgcvi
-#define fits_read_col_lng    ffgcvj
-#define fits_read_col_lnglng    ffgcvjj
-#define fits_read_col_uint    ffgcvuk
-#define fits_read_col_int    ffgcvk
-#define fits_read_col_flt    ffgcve
-#define fits_read_col_dbl    ffgcvd
-#define fits_read_col_cmp    ffgcvc
-#define fits_read_col_dblcmp ffgcvm
-#define fits_read_col_bit    ffgcx
-#define fits_read_col_bit_usht ffgcxui
-#define fits_read_col_bit_uint ffgcxuk
-
-#define fits_read_colnull_str    ffgcfs
-#define fits_read_colnull_log    ffgcfl
-#define fits_read_colnull_byt    ffgcfb
-#define fits_read_colnull_sbyt    ffgcfsb
-#define fits_read_colnull_usht    ffgcfui
-#define fits_read_colnull_ulng    ffgcfuj
-#define fits_read_colnull_sht    ffgcfi
-#define fits_read_colnull_lng    ffgcfj
-#define fits_read_colnull_lnglng    ffgcfjj
-#define fits_read_colnull_uint    ffgcfuk
-#define fits_read_colnull_int    ffgcfk
-#define fits_read_colnull_flt    ffgcfe
-#define fits_read_colnull_dbl    ffgcfd
-#define fits_read_colnull_cmp    ffgcfc
-#define fits_read_colnull_dblcmp ffgcfm
-
-#define fits_read_descript ffgdes
-#define fits_read_descriptll ffgdesll
-#define fits_read_descripts ffgdess
-#define fits_read_descriptsll ffgdessll
-#define fits_read_tblbytes    ffgtbb
-
-#define fits_write_grppar_byt ffpgpb
-#define fits_write_grppar_sbyt ffpgpsb
-#define fits_write_grppar_usht ffpgpui
-#define fits_write_grppar_ulng ffpgpuj
-#define fits_write_grppar_sht ffpgpi
-#define fits_write_grppar_lng ffpgpj
-#define fits_write_grppar_lnglng ffpgpjj
-#define fits_write_grppar_uint ffpgpuk
-#define fits_write_grppar_int ffpgpk
-#define fits_write_grppar_flt ffpgpe
-#define fits_write_grppar_dbl ffpgpd
-
-#define fits_write_pix        ffppx
-#define fits_write_pixll      ffppxll
-#define fits_write_pixnull    ffppxn
-#define fits_write_pixnullll  ffppxnll
-#define fits_write_img        ffppr
-#define fits_write_img_byt    ffpprb
-#define fits_write_img_sbyt    ffpprsb
-#define fits_write_img_usht    ffpprui
-#define fits_write_img_ulng    ffppruj
-#define fits_write_img_sht    ffppri
-#define fits_write_img_lng    ffpprj
-#define fits_write_img_lnglng    ffpprjj
-#define fits_write_img_uint    ffppruk
-#define fits_write_img_int    ffpprk
-#define fits_write_img_flt    ffppre
-#define fits_write_img_dbl    ffpprd
-
-#define fits_write_imgnull     ffppn
-#define fits_write_imgnull_byt ffppnb
-#define fits_write_imgnull_sbyt ffppnsb
-#define fits_write_imgnull_usht ffppnui
-#define fits_write_imgnull_ulng ffppnuj
-#define fits_write_imgnull_sht ffppni
-#define fits_write_imgnull_lng ffppnj
-#define fits_write_imgnull_lnglng ffppnjj
-#define fits_write_imgnull_uint ffppnuk
-#define fits_write_imgnull_int ffppnk
-#define fits_write_imgnull_flt ffppne
-#define fits_write_imgnull_dbl ffppnd
-
-#define fits_write_img_null ffppru
-#define fits_write_null_img ffpprn
-
-#define fits_write_2d_byt   ffp2db
-#define fits_write_2d_sbyt   ffp2dsb
-#define fits_write_2d_usht   ffp2dui
-#define fits_write_2d_ulng   ffp2duj
-#define fits_write_2d_sht   ffp2di
-#define fits_write_2d_lng   ffp2dj
-#define fits_write_2d_lnglng   ffp2djj
-#define fits_write_2d_uint   ffp2duk
-#define fits_write_2d_int   ffp2dk
-#define fits_write_2d_flt   ffp2de
-#define fits_write_2d_dbl   ffp2dd
-
-#define fits_write_3d_byt   ffp3db
-#define fits_write_3d_sbyt   ffp3dsb
-#define fits_write_3d_usht   ffp3dui
-#define fits_write_3d_ulng   ffp3duj
-#define fits_write_3d_sht   ffp3di
-#define fits_write_3d_lng   ffp3dj
-#define fits_write_3d_lnglng   ffp3djj
-#define fits_write_3d_uint   ffp3duk
-#define fits_write_3d_int   ffp3dk
-#define fits_write_3d_flt   ffp3de
-#define fits_write_3d_dbl   ffp3dd
-
-#define fits_write_subset  ffpss
-#define fits_write_subset_byt  ffpssb
-#define fits_write_subset_sbyt  ffpsssb
-#define fits_write_subset_usht  ffpssui
-#define fits_write_subset_ulng  ffpssuj
-#define fits_write_subset_sht  ffpssi
-#define fits_write_subset_lng  ffpssj
-#define fits_write_subset_lnglng  ffpssjj
-#define fits_write_subset_uint  ffpssuk
-#define fits_write_subset_int  ffpssk
-#define fits_write_subset_flt  ffpsse
-#define fits_write_subset_dbl  ffpssd
-
-#define fits_write_col         ffpcl
-#define fits_write_col_str     ffpcls
-#define fits_write_col_log     ffpcll
-#define fits_write_col_byt     ffpclb
-#define fits_write_col_sbyt     ffpclsb
-#define fits_write_col_usht     ffpclui
-#define fits_write_col_ulng     ffpcluj
-#define fits_write_col_sht     ffpcli
-#define fits_write_col_lng     ffpclj
-#define fits_write_col_lnglng     ffpcljj
-#define fits_write_col_uint     ffpcluk
-#define fits_write_col_int     ffpclk
-#define fits_write_col_flt     ffpcle
-#define fits_write_col_dbl     ffpcld
-#define fits_write_col_cmp     ffpclc
-#define fits_write_col_dblcmp  ffpclm
-#define fits_write_col_null    ffpclu
-#define fits_write_col_bit     ffpclx
-#define fits_write_nulrows     ffprwu
-#define fits_write_nullrows    ffprwu
-
-#define fits_write_colnull ffpcn
-#define fits_write_colnull_str ffpcns
-#define fits_write_colnull_log ffpcnl
-#define fits_write_colnull_byt ffpcnb
-#define fits_write_colnull_sbyt ffpcnsb
-#define fits_write_colnull_usht ffpcnui
-#define fits_write_colnull_ulng ffpcnuj
-#define fits_write_colnull_sht ffpcni
-#define fits_write_colnull_lng ffpcnj
-#define fits_write_colnull_lnglng ffpcnjj
-#define fits_write_colnull_uint ffpcnuk
-#define fits_write_colnull_int ffpcnk
-#define fits_write_colnull_flt ffpcne
-#define fits_write_colnull_dbl ffpcnd
-
-#define fits_write_ext ffpextn
-#define fits_read_ext  ffgextn
-
-#define fits_write_descript  ffpdes
-#define fits_compress_heap   ffcmph
-#define fits_test_heap   fftheap
-
-#define fits_write_tblbytes  ffptbb
-#define fits_insert_rows  ffirow
-#define fits_delete_rows  ffdrow
-#define fits_delete_rowrange ffdrrg
-#define fits_delete_rowlist ffdrws
-#define fits_delete_rowlistll ffdrwsll
-#define fits_insert_col   fficol
-#define fits_insert_cols  fficls
-#define fits_delete_col   ffdcol
-#define fits_copy_col     ffcpcl
-#define fits_copy_rows    ffcprw
-#define fits_modify_vector_len  ffmvec
-
-#define fits_read_img_coord ffgics
-#define fits_read_img_coord_version ffgicsa
-#define fits_read_tbl_coord ffgtcs
-#define fits_pix_to_world ffwldp
-#define fits_world_to_pix ffxypx
-
-#define fits_get_image_wcs_keys ffgiwcs
-#define fits_get_table_wcs_keys ffgtwcs
-
-#define fits_find_rows          fffrow
-#define fits_find_first_row     ffffrw
-#define fits_find_rows_cmp      fffrwc
-#define fits_select_rows        ffsrow
-#define fits_calc_rows          ffcrow
-#define fits_calculator         ffcalc
-#define fits_calculator_rng     ffcalc_rng
-#define fits_test_expr          fftexp
-
-#define fits_create_group       ffgtcr 
-#define fits_insert_group       ffgtis 
-#define fits_change_group       ffgtch 
-#define fits_remove_group       ffgtrm 
-#define fits_copy_group         ffgtcp 
-#define fits_merge_groups       ffgtmg 
-#define fits_compact_group      ffgtcm 
-#define fits_verify_group       ffgtvf 
-#define fits_open_group         ffgtop 
-#define fits_add_group_member   ffgtam 
-#define fits_get_num_members    ffgtnm 
-
-#define fits_get_num_groups     ffgmng 
-#define fits_open_member        ffgmop 
-#define fits_copy_member        ffgmcp 
-#define fits_transfer_member    ffgmtf 
-#define fits_remove_member      ffgmrm
-
-#endif
diff --git a/src/external/OpenGR/3rdparty/cfitsio/makefile.bc b/src/external/OpenGR/3rdparty/cfitsio/makefile.bc
deleted file mode 100644
index 8e8526eaa..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/makefile.bc
+++ /dev/null
@@ -1,588 +0,0 @@
-#
-# Borland C++ IDE generated makefile
-# Generated 10/12/99 at 1:24:11 PM 
-#
-.AUTODEPEND
-
-
-#
-# Borland C++ tools
-#
-IMPLIB  = Implib
-BCC32   = Bcc32 +BccW32.cfg 
-BCC32I  = Bcc32i +BccW32.cfg 
-TLINK32 = TLink32
-ILINK32 = Ilink32
-TLIB    = TLib
-BRC32   = Brc32
-TASM32  = Tasm32
-#
-# IDE macros
-#
-
-
-#
-# Options
-#
-IDE_LinkFLAGS32 =  -LD:\BC5\LIB
-LinkerLocalOptsAtC32_cfitsiodlib =  -Tpd -ap -c
-ResLocalOptsAtC32_cfitsiodlib = 
-BLocalOptsAtC32_cfitsiodlib = 
-CompInheritOptsAt_cfitsiodlib = -ID:\BC5\INCLUDE -D_RTLDLL -DWIN32;
-LinkerInheritOptsAt_cfitsiodlib = -x
-LinkerOptsAt_cfitsiodlib = $(LinkerLocalOptsAtC32_cfitsiodlib)
-ResOptsAt_cfitsiodlib = $(ResLocalOptsAtC32_cfitsiodlib)
-BOptsAt_cfitsiodlib = $(BLocalOptsAtC32_cfitsiodlib)
-
-#
-# Dependency List
-#
-Dep_cfitsio = \
-   cfitsio.lib
-
-cfitsio : BccW32.cfg $(Dep_cfitsio)
-  echo MakeNode
-
-cfitsio.lib : cfitsio.dll
-  $(IMPLIB) $@ cfitsio.dll
-
-
-Dep_cfitsioddll = \
-   listhead.obj\
-   imcompress.obj\
-   quantize.obj\
-   ricecomp.obj\
-   pliocomp.obj\
-   iraffits.obj\
-   wcsutil.obj\
-   histo.obj\
-   scalnull.obj\
-   region.obj\
-   putkey.obj\
-   putcoluk.obj\
-   putcoluj.obj\
-   putcolui.obj\
-   putcolu.obj\
-   putcols.obj\
-   putcoll.obj\
-   putcolk.obj\
-   putcolj.obj\
-   putcoli.obj\
-   putcole.obj\
-   putcold.obj\
-   putcolb.obj\
-   putcolsb.obj\
-   putcol.obj\
-   modkey.obj\
-   swapproc.obj\
-   getcol.obj\
-   group.obj\
-   getkey.obj\
-   getcoluk.obj\
-   getcoluj.obj\
-   getcolui.obj\
-   getcols.obj\
-   getcoll.obj\
-   getcolk.obj\
-   getcolj.obj\
-   getcoli.obj\
-   getcole.obj\
-   getcold.obj\
-   getcolb.obj\
-   getcolsb.obj\
-   grparser.obj\
-   fitscore.obj\
-   f77_wrap1.obj\
-   f77_wrap2.obj\
-   f77_wrap3.obj\
-   f77_wrap4.obj\
-   eval_y.obj\
-   eval_l.obj\
-   eval_f.obj\
-   edithdu.obj\
-   editcol.obj\
-   drvrmem.obj\
-   drvrfile.obj\
-   checksum.obj\
-   cfileio.obj\
-   buffers.obj\
-   fits_hcompress.obj\
-   fits_hdecompress.obj\
-   zuncompress.obj\
-   zcompress.obj\
-   adler32.obj\
-   crc32.obj\
-   inffast.obj\
-   inftrees.obj\
-   trees.obj\
-   zutil.obj\
-   deflate.obj\
-   infback.obj\
-   inflate.obj\
-   uncompr.obj
-
-cfitsio.dll : $(Dep_cfitsioddll) cfitsio.def
-  $(ILINK32) @&&|
- /v $(IDE_LinkFLAGS32) $(LinkerOptsAt_cfitsiodlib) $(LinkerInheritOptsAt_cfitsiodlib) +
-D:\BC5\LIB\c0d32.obj+
-listhead.obj+
-imcompress.obj+
-quantize.obj+
-ricecomp.obj+
-pliocomp.obj+
-iraffits.obj+
-wcsutil.obj+
-histo.obj+
-iraffits.obj+
-scalnull.obj+
-region.obj+
-putkey.obj+
-putcoluk.obj+
-putcoluj.obj+
-putcolui.obj+
-putcolu.obj+
-putcols.obj+
-putcoll.obj+
-putcolk.obj+
-putcolj.obj+
-putcoli.obj+
-putcole.obj+
-putcold.obj+
-putcolb.obj+
-putcolsb.obj+
-putcol.obj+
-modkey.obj+
-swapproc.obj+
-getcol.obj+
-group.obj+
-getkey.obj+
-getcoluk.obj+
-getcoluj.obj+
-getcolui.obj+
-getcols.obj+
-getcoll.obj+
-getcolk.obj+
-getcolj.obj+
-getcoli.obj+
-getcole.obj+
-getcold.obj+
-getcolb.obj+
-getcolsb.obj+
-grparser.obj+
-fitscore.obj+
-f77_wrap1.obj+
-f77_wrap2.obj+
-f77_wrap3.obj+
-f77_wrap4.obj+
-eval_y.obj+
-eval_l.obj+
-eval_f.obj+
-edithdu.obj+
-editcol.obj+
-drvrmem.obj+
-drvrfile.obj+
-checksum.obj+
-cfileio.obj+
-buffers.obj+
-fits_hcompress.obj+
-fits_hdecompress.obj+
-zuncompress.obj+
-zcompress.obj+
-adler32.obj+
-crc32.obj+
-inffast.obj+
-inftrees.obj+
-trees.obj+
-zutil.obj+
-deflate.obj+
-infback.obj+
-inflate.obj+
-uncompr.obj
-$<,$*
-D:\BC5\LIB\import32.lib+
-D:\BC5\LIB\cw32i.lib
-cfitsio.def
-
-
-|
-wcsutil.obj :  wcsutil.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ wcsutil.c
-|
-iraffits.obj :  iraffits.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ iraffits.c
-|
-histo.obj :  histo.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ histo.c
-|
-
-scalnull.obj :  scalnull.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ scalnull.c
-|
-
-region.obj :  region.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ region.c
-|
-
-putkey.obj :  putkey.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putkey.c
-|
-
-putcoluk.obj :  putcoluk.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcoluk.c
-|
-
-putcoluj.obj :  putcoluj.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcoluj.c
-|
-
-putcolui.obj :  putcolui.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcolui.c
-|
-
-putcolu.obj :  putcolu.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcolu.c
-|
-
-putcols.obj :  putcols.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcols.c
-|
-
-putcoll.obj :  putcoll.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcoll.c
-|
-
-putcolk.obj :  putcolk.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcolk.c
-|
-
-putcolj.obj :  putcolj.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcolj.c
-|
-
-putcoli.obj :  putcoli.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcoli.c
-|
-
-putcole.obj :  putcole.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcole.c
-|
-
-putcold.obj :  putcold.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcold.c
-|
-
-putcolb.obj :  putcolb.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcolb.c
-|
-
-putcolsb.obj :  putcolsb.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcolsb.c
-|
-
-putcol.obj :  putcol.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcol.c
-|
-
-modkey.obj :  modkey.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ modkey.c
-|
-
-swapproc.obj :  swapproc.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ swapproc.c
-|
-
-getcol.obj :  getcol.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcol.c
-|
-
-group.obj :  group.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ group.c
-|
-
-getkey.obj :  getkey.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getkey.c
-|
-
-getcoluk.obj :  getcoluk.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcoluk.c
-|
-
-getcoluj.obj :  getcoluj.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcoluj.c
-|
-
-getcolui.obj :  getcolui.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcolui.c
-|
-
-getcols.obj :  getcols.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcols.c
-|
-
-getcoll.obj :  getcoll.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcoll.c
-|
-
-getcolk.obj :  getcolk.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcolk.c
-|
-
-getcolj.obj :  getcolj.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcolj.c
-|
-
-getcoli.obj :  getcoli.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcoli.c
-|
-
-getcole.obj :  getcole.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcole.c
-|
-
-getcold.obj :  getcold.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcold.c
-|
-
-getcolb.obj :  getcolb.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcolb.c
-|
-getcolsb.obj :  getcolsb.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcolsb.c
-|
-
-grparser.obj :  grparser.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ grparser.c
-|
-
-fitscore.obj :  fitscore.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ fitscore.c
-|
-
-f77_wrap1.obj :  f77_wrap1.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ f77_wrap1.c
-|
-
-f77_wrap2.obj :  f77_wrap2.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ f77_wrap2.c
-|
-
-f77_wrap3.obj :  f77_wrap3.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ f77_wrap3.c
-|
-
-f77_wrap4.obj :  f77_wrap4.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ f77_wrap4.c
-|
-
-eval_y.obj :  eval_y.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ eval_y.c
-|
-
-eval_l.obj :  eval_l.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ eval_l.c
-|
-
-eval_f.obj :  eval_f.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ eval_f.c
-|
-
-edithdu.obj :  edithdu.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ edithdu.c
-|
-
-editcol.obj :  editcol.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ editcol.c
-|
-
-drvrmem.obj :  drvrmem.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ drvrmem.c
-|
-
-drvrfile.obj :  drvrfile.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ drvrfile.c
-|
-
-checksum.obj :  checksum.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ checksum.c
-|
-
-cfileio.obj :  cfileio.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ cfileio.c
-|
-
-listhead.obj :  listhead.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ listhead.c
-|
-
-imcompress.obj :  imcompress.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ imcompress.c
-|
-
-quantize.obj :  quantize.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ quantize.c
-|
-
-ricecomp.obj :  ricecomp.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ ricecomp.c
-|
-
-pliocomp.obj :  pliocomp.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ pliocomp.c
-|
-
-buffers.obj :  buffers.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ buffers.c
-|
-
-fits_hcompress.obj :  fits_hcompress.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ fits_hcompress.c
-|
-
-fits_hdecompress.obj :  fits_hdecompress.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ fits_hdecompress.c
-|
-
-zuncompress.obj :  zuncompress.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ zuncompress.c
-|
-
-zcompress.obj :  zcompress.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ zcompress.c
-|
-
-adler32.obj :  adler32.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ adler32.c
-|
-
-crc32.obj :  crc32.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ crc32.c
-|
-
-inffast.obj :  inffast.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ inffast.c
-|
-
-inftrees.obj :  inftrees.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ inftrees.c
-|
-
-trees.obj :  trees.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ trees.c
-|
-
-zutil.obj :  zutil.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ zutil.c
-|
-
-deflate.obj :  deflate.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ deflate.c
-|
-
-infback.obj :  infback.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ infback.c
-|
-
-inflate.obj :  inflate.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ inflate.c
-|
-
-uncompr.obj :  uncompr.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ uncompr.c
-|
-
-
-windumpexts.exe :  windumpexts.c
-  bcc32 windumpexts.c
-
-
-cfitsio.def: windumpexts.exe
-	windumpexts -o cfitsio.def cfitsio.dll @&&|
-		$(Dep_cfitsioddll)
-|
-
-# Compiler configuration file
-BccW32.cfg : 
-   Copy &&|
--w
--R
--v
--WM-
--vi
--H
--H=cfitsio.csm
--WCD
-| $@
-
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/makefile.vcc b/src/external/OpenGR/3rdparty/cfitsio/makefile.vcc
deleted file mode 100644
index e0e28b8bb..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/makefile.vcc
+++ /dev/null
@@ -1,793 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on cfitsio.dsp
-!IF "$(CFG)" == ""
-CFG=Win32 Release
-!MESSAGE No configuration specified. Defaulting to Win32 Release.
-!ENDIF 
-
-!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "cfitsio.mak" CFG="Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE 
-!ERROR An invalid configuration is specified.
-!ENDIF 
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE 
-NULL=nul
-!ENDIF 
-
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "Win32 Release"
-
-OUTDIR=.
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.
-# End Custom Macros
-
-ALL : "$(OUTDIR)\cfitsio.dll"
-
-
-CLEAN :
-	-@erase "$(INTDIR)\buffers.obj"
-	-@erase "$(INTDIR)\cfileio.obj"
-	-@erase "$(INTDIR)\checksum.obj"
-	-@erase "$(INTDIR)\drvrfile.obj"
-	-@erase "$(INTDIR)\drvrmem.obj"
-	-@erase "$(INTDIR)\editcol.obj"
-	-@erase "$(INTDIR)\edithdu.obj"
-	-@erase "$(INTDIR)\eval_f.obj"
-	-@erase "$(INTDIR)\eval_l.obj"
-	-@erase "$(INTDIR)\eval_y.obj"
-	-@erase "$(INTDIR)\fitscore.obj"
-	-@erase "$(INTDIR)\f77_wrap1.obj"
-	-@erase "$(INTDIR)\f77_wrap2.obj"
-	-@erase "$(INTDIR)\f77_wrap3.obj"
-	-@erase "$(INTDIR)\f77_wrap4.obj"
-	-@erase "$(INTDIR)\getcol.obj"
-	-@erase "$(INTDIR)\getcolb.obj"
-	-@erase "$(INTDIR)\getcolsb.obj"
-	-@erase "$(INTDIR)\getcold.obj"
-	-@erase "$(INTDIR)\getcole.obj"
-	-@erase "$(INTDIR)\getcoli.obj"
-	-@erase "$(INTDIR)\getcolj.obj"
-	-@erase "$(INTDIR)\getcolk.obj"
-	-@erase "$(INTDIR)\getcoll.obj"
-	-@erase "$(INTDIR)\getcols.obj"
-	-@erase "$(INTDIR)\getcolui.obj"
-	-@erase "$(INTDIR)\getcoluj.obj"
-	-@erase "$(INTDIR)\getcoluk.obj"
-	-@erase "$(INTDIR)\getkey.obj"
-	-@erase "$(INTDIR)\group.obj"
-	-@erase "$(INTDIR)\grparser.obj"
-	-@erase "$(INTDIR)\histo.obj"
-	-@erase "$(INTDIR)\iraffits.obj"
-	-@erase "$(INTDIR)\modkey.obj"
-	-@erase "$(INTDIR)\putcol.obj"
-	-@erase "$(INTDIR)\putcolb.obj"
-	-@erase "$(INTDIR)\putcolsb.obj"
-	-@erase "$(INTDIR)\putcold.obj"
-	-@erase "$(INTDIR)\putcole.obj"
-	-@erase "$(INTDIR)\putcoli.obj"
-	-@erase "$(INTDIR)\putcolj.obj"
-	-@erase "$(INTDIR)\putcolk.obj"
-	-@erase "$(INTDIR)\putcoll.obj"
-	-@erase "$(INTDIR)\putcols.obj"
-	-@erase "$(INTDIR)\putcolu.obj"
-	-@erase "$(INTDIR)\putcolui.obj"
-	-@erase "$(INTDIR)\putcoluj.obj"
-	-@erase "$(INTDIR)\putcoluk.obj"
-	-@erase "$(INTDIR)\putkey.obj"
-	-@erase "$(INTDIR)\region.obj"
-	-@erase "$(INTDIR)\scalnull.obj"
-	-@erase "$(INTDIR)\swapproc.obj"
-	-@erase "$(INTDIR)\wcssub.obj"
-	-@erase "$(INTDIR)\wcsutil.obj"
-	-@erase "$(INTDIR)\imcompress.obj"
-	-@erase "$(INTDIR)\ricecomp.obj"
-	-@erase "$(INTDIR)\quantize.obj"
-	-@erase "$(INTDIR)\pliocomp.obj"
-	-@erase "$(INTDIR)\fits_hcompress.obj"
-	-@erase "$(INTDIR)\fits_hdecompress.obj"
-	-@erase "$(INTDIR)\zuncompress.obj"
-	-@erase "$(INTDIR)\zcompress.obj"
-	-@erase "$(INTDIR)\adler32.obj"
-	-@erase "$(INTDIR)\crc32.obj"
-	-@erase "$(INTDIR)\inffast.obj"
-	-@erase "$(INTDIR)\inftrees.obj"
-	-@erase "$(INTDIR)\trees.obj"
-	-@erase "$(INTDIR)\zutil.obj"
-	-@erase "$(INTDIR)\deflate.obj"
-	-@erase "$(INTDIR)\infback.obj"
-	-@erase "$(INTDIR)\inflate.obj"
-	-@erase "$(INTDIR)\uncompr.obj"
-	-@erase "$(INTDIR)\vc60.idb"
-	-@erase "$(OUTDIR)\cfitsio.dll"
-	-@erase "$(OUTDIR)\cfitsio.exp"
-	-@erase "$(OUTDIR)\cfitsio.lib"
-
-"$(OUTDIR)" :
-    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-"$(INTDIR)" :
-    if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
-
-CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CFITSIO_EXPORTS" /D "_CRT_SECURE_NO_DEPRECATE" /Fp"$(INTDIR)\cfitsio.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\cfitsio.bsc" 
-BSC32_SBRS= \
-	
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\cfitsio.pdb" /machine:I386 /def:".\cfitsio.def" /out:"$(OUTDIR)\cfitsio.dll" /implib:"$(OUTDIR)\cfitsio.lib" 
-DEF_FILE= ".\cfitsio.def"
-LINK32_OBJS= \
-	"$(INTDIR)\buffers.obj" \
-	"$(INTDIR)\cfileio.obj" \
-	"$(INTDIR)\checksum.obj" \
-	"$(INTDIR)\drvrfile.obj" \
-	"$(INTDIR)\drvrmem.obj" \
-	"$(INTDIR)\editcol.obj" \
-	"$(INTDIR)\edithdu.obj" \
-	"$(INTDIR)\eval_f.obj" \
-	"$(INTDIR)\eval_l.obj" \
-	"$(INTDIR)\eval_y.obj" \
-	"$(INTDIR)\fitscore.obj" \
-	"$(INTDIR)\f77_wrap1.obj" \
-	"$(INTDIR)\f77_wrap2.obj" \
-	"$(INTDIR)\f77_wrap3.obj" \
-	"$(INTDIR)\f77_wrap4.obj" \
-	"$(INTDIR)\getcol.obj" \
-	"$(INTDIR)\getcolb.obj" \
-	"$(INTDIR)\getcolsb.obj" \
-	"$(INTDIR)\getcold.obj" \
-	"$(INTDIR)\getcole.obj" \
-	"$(INTDIR)\getcoli.obj" \
-	"$(INTDIR)\getcolj.obj" \
-	"$(INTDIR)\getcolk.obj" \
-	"$(INTDIR)\getcoll.obj" \
-	"$(INTDIR)\getcols.obj" \
-	"$(INTDIR)\getcolui.obj" \
-	"$(INTDIR)\getcoluj.obj" \
-	"$(INTDIR)\getcoluk.obj" \
-	"$(INTDIR)\getkey.obj" \
-	"$(INTDIR)\group.obj" \
-	"$(INTDIR)\grparser.obj" \
-	"$(INTDIR)\histo.obj" \
-	"$(INTDIR)\iraffits.obj" \
-	"$(INTDIR)\modkey.obj" \
-	"$(INTDIR)\putcol.obj" \
-	"$(INTDIR)\putcolb.obj" \
-	"$(INTDIR)\putcolsb.obj" \
-	"$(INTDIR)\putcold.obj" \
-	"$(INTDIR)\putcole.obj" \
-	"$(INTDIR)\putcoli.obj" \
-	"$(INTDIR)\putcolj.obj" \
-	"$(INTDIR)\putcolk.obj" \
-	"$(INTDIR)\putcoll.obj" \
-	"$(INTDIR)\putcols.obj" \
-	"$(INTDIR)\putcolu.obj" \
-	"$(INTDIR)\putcolui.obj" \
-	"$(INTDIR)\putcoluj.obj" \
-	"$(INTDIR)\putcoluk.obj" \
-	"$(INTDIR)\putkey.obj" \
-	"$(INTDIR)\region.obj" \
-	"$(INTDIR)\scalnull.obj" \
-	"$(INTDIR)\swapproc.obj" \
-	"$(INTDIR)\wcssub.obj"  \
-	"$(INTDIR)\wcsutil.obj" \
-	"$(INTDIR)\imcompress.obj" \
-	"$(INTDIR)\ricecomp.obj" \
-	"$(INTDIR)\quantize.obj" \
-	"$(INTDIR)\pliocomp.obj" \
-	"$(INTDIR)\fits_hcompress.obj" \
-	"$(INTDIR)\fits_hdecompress.obj" \
-	"$(INTDIR)\zuncompress.obj" \
-	"$(INTDIR)\zcompress.obj" \
-	"$(INTDIR)\adler32.obj" \
-	"$(INTDIR)\crc32.obj" \
-	"$(INTDIR)\inffast.obj" \
-	"$(INTDIR)\inftrees.obj" \
-	"$(INTDIR)\trees.obj" \
-	"$(INTDIR)\zutil.obj" \
-	"$(INTDIR)\deflate.obj" \
-	"$(INTDIR)\infback.obj" \
-	"$(INTDIR)\inflate.obj" \
-	"$(INTDIR)\uncompr.obj" 
-
-"$(OUTDIR)\cfitsio.dll" : $(LINK32_OBJS) WINDUMP
-	windumpexts -o $(DEF_FILE) cfitsio.dll $(LINK32_OBJS)
-	$(LINK32) @<<
-  $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF  "$(CFG)" == "Win32 Debug"
-
-OUTDIR=.
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.
-# End Custom Macros
-
-ALL : "$(OUTDIR)\cfitsio.dll"
-
-
-CLEAN :
-	-@erase "$(INTDIR)\buffers.obj"
-	-@erase "$(INTDIR)\cfileio.obj"
-	-@erase "$(INTDIR)\checksum.obj"
-	-@erase "$(INTDIR)\drvrfile.obj"
-	-@erase "$(INTDIR)\drvrmem.obj"
-	-@erase "$(INTDIR)\editcol.obj"
-	-@erase "$(INTDIR)\edithdu.obj"
-	-@erase "$(INTDIR)\eval_f.obj"
-	-@erase "$(INTDIR)\eval_l.obj"
-	-@erase "$(INTDIR)\eval_y.obj"
-	-@erase "$(INTDIR)\fitscore.obj"
-	-@erase "$(INTDIR)\f77_wrap1.obj"
-	-@erase "$(INTDIR)\f77_wrap2.obj"
-	-@erase "$(INTDIR)\f77_wrap3.obj"
-	-@erase "$(INTDIR)\f77_wrap4.obj"
-	-@erase "$(INTDIR)\getcol.obj"
-	-@erase "$(INTDIR)\getcolb.obj"
-	-@erase "$(INTDIR)\getcolsb.obj"
-	-@erase "$(INTDIR)\getcold.obj"
-	-@erase "$(INTDIR)\getcole.obj"
-	-@erase "$(INTDIR)\getcoli.obj"
-	-@erase "$(INTDIR)\getcolj.obj"
-	-@erase "$(INTDIR)\getcolk.obj"
-	-@erase "$(INTDIR)\getcoll.obj"
-	-@erase "$(INTDIR)\getcols.obj"
-	-@erase "$(INTDIR)\getcolui.obj"
-	-@erase "$(INTDIR)\getcoluj.obj"
-	-@erase "$(INTDIR)\getcoluk.obj"
-	-@erase "$(INTDIR)\getkey.obj"
-	-@erase "$(INTDIR)\group.obj"
-	-@erase "$(INTDIR)\grparser.obj"
-	-@erase "$(INTDIR)\histo.obj"
-	-@erase "$(INTDIR)\iraffits.obj"
-	-@erase "$(INTDIR)\modkey.obj"
-	-@erase "$(INTDIR)\putcol.obj"
-	-@erase "$(INTDIR)\putcolb.obj"
-	-@erase "$(INTDIR)\putcolsb.obj"
-	-@erase "$(INTDIR)\putcold.obj"
-	-@erase "$(INTDIR)\putcole.obj"
-	-@erase "$(INTDIR)\putcoli.obj"
-	-@erase "$(INTDIR)\putcolj.obj"
-	-@erase "$(INTDIR)\putcolk.obj"
-	-@erase "$(INTDIR)\putcoll.obj"
-	-@erase "$(INTDIR)\putcols.obj"
-	-@erase "$(INTDIR)\putcolu.obj"
-	-@erase "$(INTDIR)\putcolui.obj"
-	-@erase "$(INTDIR)\putcoluj.obj"
-	-@erase "$(INTDIR)\putcoluk.obj"
-	-@erase "$(INTDIR)\putkey.obj"
-	-@erase "$(INTDIR)\region.obj"
-	-@erase "$(INTDIR)\scalnull.obj"
-	-@erase "$(INTDIR)\swapproc.obj"
-	-@erase "$(INTDIR)\vc60.idb"
-	-@erase "$(INTDIR)\vc60.pdb"
-	-@erase "$(INTDIR)\wcssub.obj"
-	-@erase "$(INTDIR)\wcsutil.obj"
-	-@erase "$(INTDIR)\imcompress.obj"
-	-@erase "$(INTDIR)\ricecomp.obj"
-	-@erase "$(INTDIR)\quantize.obj"
-	-@erase "$(INTDIR)\pliocomp.obj"
-	-@erase "$(INTDIR)\fits_hcompress.obj"
-	-@erase "$(INTDIR)\fits_hdecompress.obj"
-	-@erase "$(INTDIR)\zuncompress.obj"
-	-@erase "$(INTDIR)\zcompress.obj"
-	-@erase "$(INTDIR)\adler32.obj"
-	-@erase "$(INTDIR)\crc32.obj"
-	-@erase "$(INTDIR)\inffast.obj"
-	-@erase "$(INTDIR)\inftrees.obj"
-	-@erase "$(INTDIR)\trees.obj"
-	-@erase "$(INTDIR)\zutil.obj"
-	-@erase "$(INTDIR)\deflate.obj"
-	-@erase "$(INTDIR)\infback.obj"
-	-@erase "$(INTDIR)\inflate.obj"
-	-@erase "$(INTDIR)\uncompr.obj"
-	-@erase "$(OUTDIR)\cfitsio.dll"
-	-@erase "$(OUTDIR)\cfitsio.exp"
-	-@erase "$(OUTDIR)\cfitsio.ilk"
-	-@erase "$(OUTDIR)\cfitsio.lib"
-	-@erase "$(OUTDIR)\cfitsio.pdb"
-
-"$(OUTDIR)" :
-    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-"$(INTDIR)" :
-    if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
-
-CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /D "__WIN32__" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CFITSIO_EXPORTS" /D "_CRT_SECURE_NO_DEPRECATE" /Fp"$(INTDIR)\cfitsio.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\cfitsio.bsc" 
-BSC32_SBRS= \
-	
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\cfitsio.pdb" /debug /machine:I386 /def:".\cfitsio.def" /out:"$(OUTDIR)\cfitsio.dll" /implib:"$(OUTDIR)\cfitsio.lib" /pdbtype:sept 
-DEF_FILE= ".\cfitsio.def"
-LINK32_OBJS= \
-	"$(INTDIR)\buffers.obj" \
-	"$(INTDIR)\cfileio.obj" \
-	"$(INTDIR)\checksum.obj" \
-	"$(INTDIR)\drvrfile.obj" \
-	"$(INTDIR)\drvrmem.obj" \
-	"$(INTDIR)\editcol.obj" \
-	"$(INTDIR)\edithdu.obj" \
-	"$(INTDIR)\eval_f.obj" \
-	"$(INTDIR)\eval_l.obj" \
-	"$(INTDIR)\eval_y.obj" \
-	"$(INTDIR)\fitscore.obj" \
-	"$(INTDIR)\f77_wrap1.obj" \
-	"$(INTDIR)\f77_wrap2.obj" \
-	"$(INTDIR)\f77_wrap3.obj" \
-	"$(INTDIR)\f77_wrap4.obj" \
-	"$(INTDIR)\getcol.obj" \
-	"$(INTDIR)\getcolb.obj" \
-	"$(INTDIR)\getcolsb.obj" \
-	"$(INTDIR)\getcold.obj" \
-	"$(INTDIR)\getcole.obj" \
-	"$(INTDIR)\getcoli.obj" \
-	"$(INTDIR)\getcolj.obj" \
-	"$(INTDIR)\getcolk.obj" \
-	"$(INTDIR)\getcoll.obj" \
-	"$(INTDIR)\getcols.obj" \
-	"$(INTDIR)\getcolui.obj" \
-	"$(INTDIR)\getcoluj.obj" \
-	"$(INTDIR)\getcoluk.obj" \
-	"$(INTDIR)\getkey.obj" \
-	"$(INTDIR)\group.obj" \
-	"$(INTDIR)\grparser.obj" \
-	"$(INTDIR)\histo.obj" \
-	"$(INTDIR)\iraffits.obj" \
-	"$(INTDIR)\modkey.obj" \
-	"$(INTDIR)\putcol.obj" \
-	"$(INTDIR)\putcolb.obj" \
-	"$(INTDIR)\putcolsb.obj" \
-	"$(INTDIR)\putcold.obj" \
-	"$(INTDIR)\putcole.obj" \
-	"$(INTDIR)\putcoli.obj" \
-	"$(INTDIR)\putcolj.obj" \
-	"$(INTDIR)\putcolk.obj" \
-	"$(INTDIR)\putcoll.obj" \
-	"$(INTDIR)\putcols.obj" \
-	"$(INTDIR)\putcolu.obj" \
-	"$(INTDIR)\putcolui.obj" \
-	"$(INTDIR)\putcoluj.obj" \
-	"$(INTDIR)\putcoluk.obj" \
-	"$(INTDIR)\putkey.obj" \
-	"$(INTDIR)\region.obj" \
-	"$(INTDIR)\scalnull.obj" \
-	"$(INTDIR)\swapproc.obj" \
-	"$(INTDIR)\wcssub.obj" \
-	"$(INTDIR)\wcsutil.obj" \
-	"$(INTDIR)\imcompress.obj" \
-	"$(INTDIR)\ricecomp.obj" \
-	"$(INTDIR)\quantize.obj" \
-	"$(INTDIR)\pliocomp.obj" \
-	"$(INTDIR)\fits_hcompress.obj" \
-	"$(INTDIR)\fits_hdecompress.obj" \
-	"$(INTDIR)\zuncompress.obj" \
-	"$(INTDIR)\zcompress.obj" \
-	"$(INTDIR)\adler32.obj" \
-	"$(INTDIR)\crc32.obj" \
-	"$(INTDIR)\inffast.obj" \
-	"$(INTDIR)\inftrees.obj" \
-	"$(INTDIR)\trees.obj" \
-	"$(INTDIR)\zutil.obj" \
-	"$(INTDIR)\deflate.obj" \
-	"$(INTDIR)\infback.obj" \
-	"$(INTDIR)\inflate.obj" \
-	"$(INTDIR)\uncompr.obj" 
-
-"$(OUTDIR)\cfitsio.dll" : $(LINK32_OBJS) WINDUMP
-	windumpexts -o $(DEF_FILE) cfitsio.dll $(LINK32_OBJS)    
-	$(LINK32) @<<
-	$(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF 
-
-.c{$(INTDIR)}.obj::
-   $(CPP) @<<
-   $(CPP_PROJ) $< 
-<<
-
-.cpp{$(INTDIR)}.obj::
-   $(CPP) @<<
-   $(CPP_PROJ) $< 
-<<
-
-.cxx{$(INTDIR)}.obj::
-   $(CPP) @<<
-   $(CPP_PROJ) $< 
-<<
-
-.c{$(INTDIR)}.sbr::
-   $(CPP) @<<
-   $(CPP_PROJ) $< 
-<<
-
-.cpp{$(INTDIR)}.sbr::
-   $(CPP) @<<
-   $(CPP_PROJ) $< 
-<<
-
-.cxx{$(INTDIR)}.sbr::
-   $(CPP) @<<
-   $(CPP_PROJ) $< 
-<<
-
-
-!IF "$(NO_EXTERNAL_DEPS)" != "1"
-!IF EXISTS("cfitsio.dep")
-!INCLUDE "cfitsio.dep"
-!ELSE 
-!MESSAGE Warning: cannot find "cfitsio.dep"
-!ENDIF 
-!ENDIF 
-
-
-!IF "$(CFG)" == "Win32 Release" || "$(CFG)" == "Win32 Debug"
-SOURCE=.\buffers.c
-
-"$(INTDIR)\buffers.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\cfileio.c
-
-"$(INTDIR)\cfileio.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\checksum.c
-
-"$(INTDIR)\checksum.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\drvrfile.c
-
-"$(INTDIR)\drvrfile.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\drvrmem.c
-
-"$(INTDIR)\drvrmem.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\editcol.c
-
-"$(INTDIR)\editcol.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\edithdu.c
-
-"$(INTDIR)\edithdu.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\eval_f.c
-
-"$(INTDIR)\eval_f.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\eval_l.c
-
-"$(INTDIR)\eval_l.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\eval_y.c
-
-"$(INTDIR)\eval_y.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\fitscore.c
-
-"$(INTDIR)\fitscore.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\f77_wrap1.c
-
-"$(INTDIR)\f77_wrap1.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\f77_wrap2.c
-
-"$(INTDIR)\f77_wrap2.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\f77_wrap3.c
-
-"$(INTDIR)\f77_wrap3.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\f77_wrap4.c
-
-"$(INTDIR)\f77_wrap4.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcol.c
-
-"$(INTDIR)\getcol.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcolb.c
-
-"$(INTDIR)\getcolb.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcolsb.c
-
-"$(INTDIR)\getcolsb.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcold.c
-
-"$(INTDIR)\getcold.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcole.c
-
-"$(INTDIR)\getcole.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcoli.c
-
-"$(INTDIR)\getcoli.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcolj.c
-
-"$(INTDIR)\getcolj.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcolk.c
-
-"$(INTDIR)\getcolk.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcoll.c
-
-"$(INTDIR)\getcoll.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcols.c
-
-"$(INTDIR)\getcols.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcolui.c
-
-"$(INTDIR)\getcolui.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcoluj.c
-
-"$(INTDIR)\getcoluj.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getcoluk.c
-
-"$(INTDIR)\getcoluk.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\getkey.c
-
-"$(INTDIR)\getkey.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\group.c
-
-"$(INTDIR)\group.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\grparser.c
-
-"$(INTDIR)\grparser.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\histo.c
-
-"$(INTDIR)\histo.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\iraffits.c
-
-"$(INTDIR)\iraffits.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\modkey.c
-
-"$(INTDIR)\modkey.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcol.c
-
-"$(INTDIR)\putcol.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcolb.c
-
-"$(INTDIR)\putcolb.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcolsb.c
-
-"$(INTDIR)\putcolsb.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcold.c
-
-"$(INTDIR)\putcold.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcole.c
-
-"$(INTDIR)\putcole.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcoli.c
-
-"$(INTDIR)\putcoli.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcolj.c
-
-"$(INTDIR)\putcolj.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcolk.c
-
-"$(INTDIR)\putcolk.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcoll.c
-
-"$(INTDIR)\putcoll.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcols.c
-
-"$(INTDIR)\putcols.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcolu.c
-
-"$(INTDIR)\putcolu.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcolui.c
-
-"$(INTDIR)\putcolui.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcoluj.c
-
-"$(INTDIR)\putcoluj.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putcoluk.c
-
-"$(INTDIR)\putcoluk.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\putkey.c
-
-"$(INTDIR)\putkey.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\region.c
-
-"$(INTDIR)\region.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\scalnull.c
-
-"$(INTDIR)\scalnull.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\swapproc.c
-
-"$(INTDIR)\swapproc.obj" : $(SOURCE) "$(INTDIR)"
-
-
-SOURCE=.\wcssub.c
-
-"$(INTDIR)\wcssub.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=.\wcsutil.c
-
-"$(INTDIR)\wcsutil.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=imcompress.c
-
-"$(INTDIR)\imcompress.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=ricecomp.c
-
-"$(INTDIR)\ricecomp.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=quantize.c
-
-"$(INTDIR)\quantize.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=pliocomp.c
-
-"$(INTDIR)\pliocomp.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=fits_hcompress.c
-
-"$(INTDIR)\fits_hcompress.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=fits_hdecompress.c
-
-"$(INTDIR)\fits_hdecompress.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=zuncompress.c
-
-"$(INTDIR)\zuncompress.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=zcompress.c
-
-"$(INTDIR)\zcompress.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=adler32.c
-
-"$(INTDIR)\adler32.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=crc32.c
-
-"$(INTDIR)\crc32.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=inffast.c
-
-"$(INTDIR)\inffast.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=inftrees.c
-
-"$(INTDIR)\inftrees.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=trees.c
-
-"$(INTDIR)\trees.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=zutil.c
-
-"$(INTDIR)\zutil.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=deflate.c
-
-"$(INTDIR)\deflate.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=infback.c
-
-"$(INTDIR)\infback.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=inflate.c
-
-"$(INTDIR)\inflate.obj" : $(SOURCE) "$(INTDIR)"
-
-SOURCE=uncompr.c
-
-"$(INTDIR)\uncompr.obj" : $(SOURCE) "$(INTDIR)"
-
-!ENDIF 
-
-$(DEF_FILE):  
-
-
-
-WINDUMP:
-	nmake -f winDumpExts.mak
diff --git a/src/external/OpenGR/3rdparty/cfitsio/makepc.bat b/src/external/OpenGR/3rdparty/cfitsio/makepc.bat
deleted file mode 100644
index 3079a296a..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/makepc.bat
+++ /dev/null
@@ -1,87 +0,0 @@
-rem:  this batch file builds the cfitsio library 
-rem:  using the Borland C++ v4.5 or new free v5.5 compiler
-rem:
-bcc32 -c buffers.c
-bcc32 -c cfileio.c
-bcc32 -c checksum.c
-bcc32 -c drvrfile.c
-bcc32 -c drvrmem.c
-bcc32 -c editcol.c
-bcc32 -c edithdu.c
-bcc32 -c eval_l.c
-bcc32 -c eval_y.c
-bcc32 -c eval_f.c
-bcc32 -c fitscore.c
-bcc32 -c getcol.c
-bcc32 -c getcolb.c
-bcc32 -c getcolsb.c
-bcc32 -c getcoli.c
-bcc32 -c getcolj.c
-bcc32 -c getcolui.c
-bcc32 -c getcoluj.c
-bcc32 -c getcoluk.c
-bcc32 -c getcolk.c
-bcc32 -c getcole.c
-bcc32 -c getcold.c
-bcc32 -c getcoll.c
-bcc32 -c getcols.c
-bcc32 -c getkey.c
-bcc32 -c group.c
-bcc32 -c grparser.c
-bcc32 -c histo.c
-bcc32 -c iraffits.c
-bcc32 -c modkey.c
-bcc32 -c putcol.c
-bcc32 -c putcolb.c
-bcc32 -c putcolsb.c
-bcc32 -c putcoli.c
-bcc32 -c putcolj.c
-bcc32 -c putcolui.c
-bcc32 -c putcoluj.c
-bcc32 -c putcoluk.c
-bcc32 -c putcolk.c
-bcc32 -c putcole.c
-bcc32 -c putcold.c
-bcc32 -c putcols.c
-bcc32 -c putcoll.c
-bcc32 -c putcolu.c
-bcc32 -c putkey.c
-bcc32 -c region.c
-bcc32 -c scalnull.c
-bcc32 -c swapproc.c
-bcc32 -c wcsutil.c
-bcc32 -c wcssub.c
-bcc32 -c imcompress.c
-bcc32 -c quantize.c
-bcc32 -c ricecomp.c
-bcc32 -c pliocomp.c
-bcc32 -c fits_hcompress.c
-bcc32 -c fits_hdecompress.c
-bcc32 -c zuncompress.c
-bcc32 -c zcompress.c
-bcc32 -c adler32.c
-bcc32 -c crc32.c
-bcc32 -c inffast.c
-bcc32 -c inftrees.c
-bcc32 -c trees.c
-bcc32 -c zutil.c
-bcc32 -c deflate.c
-bcc32 -c infback.c
-bcc32 -c inflate.c
-bcc32 -c uncompr.c
-del cfitsio.lib
-tlib cfitsio +buffers +cfileio +checksum +drvrfile +drvrmem 
-tlib cfitsio +editcol +edithdu +eval_l +eval_y +eval_f +fitscore
-tlib cfitsio +getcol +getcolb +getcolsb +getcoli +getcolj +getcolk +getcoluk 
-tlib cfitsio +getcolui +getcoluj +getcole +getcold +getcoll +getcols
-tlib cfitsio +getkey +group +grparser +histo +iraffits +modkey +putkey 
-tlib cfitsio +putcol  +putcolb +putcoli +putcolj +putcolk +putcole +putcold
-tlib cfitsio +putcoll +putcols +putcolu +putcolui +putcoluj +putcoluk
-tlib cfitsio +region +scalnull +swapproc +wcsutil +wcssub +putcolsb
-tlib cfitsio +imcompress +quantize +ricecomp +pliocomp
-tlib cfitsio +fits_hcompress +fits_hdecompress
-tlib cfitsio +zuncompress +zcompress +adler32 +crc32 +inffast
-tlib cfitsio +inftrees +trees +zutil +deflate +infback +inflate +uncompr
-bcc32 -f testprog.c cfitsio.lib
-bcc32 -f cookbook.c cfitsio.lib
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/modkey.c b/src/external/OpenGR/3rdparty/cfitsio/modkey.c
deleted file mode 100644
index e12b585f6..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/modkey.c
+++ /dev/null
@@ -1,1747 +0,0 @@
-/*  This file, modkey.c, contains routines that modify, insert, or update  */
-/*  keywords in a FITS header.                                             */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-/* stddef.h is apparently needed to define size_t */
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-/*--------------------------------------------------------------------------*/
-int ffuky( fitsfile *fptr,     /* I - FITS file pointer        */
-           int  datatype,      /* I - datatype of the value    */
-           const char *keyname,/* I - name of keyword to write */
-           void *value,        /* I - keyword value            */
-           const char *comm,   /* I - keyword comment          */
-           int  *status)       /* IO - error status            */
-/*
-  Update the keyword, value and comment in the FITS header.
-  The datatype is specified by the 2nd argument.
-*/
-{
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (datatype == TSTRING)
-    {
-        ffukys(fptr, keyname, (char *) value, comm, status);
-    }
-    else if (datatype == TBYTE)
-    {
-        ffukyj(fptr, keyname, (LONGLONG) *(unsigned char *) value, comm, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-        ffukyj(fptr, keyname, (LONGLONG) *(signed char *) value, comm, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-        ffukyj(fptr, keyname, (LONGLONG) *(unsigned short *) value, comm, status);
-    }
-    else if (datatype == TSHORT)
-    {
-        ffukyj(fptr, keyname, (LONGLONG) *(short *) value, comm, status);
-    }
-    else if (datatype == TINT)
-    {
-        ffukyj(fptr, keyname, (LONGLONG) *(int *) value, comm, status);
-    }
-    else if (datatype == TUINT)
-    {
-        ffukyg(fptr, keyname, (double) *(unsigned int *) value, 0,
-               comm, status);
-    }
-    else if (datatype == TLOGICAL)
-    {
-        ffukyl(fptr, keyname, *(int *) value, comm, status);
-    }
-    else if (datatype == TULONG)
-    {
-        ffukyg(fptr, keyname, (double) *(unsigned long *) value, 0,
-               comm, status);
-    }
-    else if (datatype == TLONG)
-    {
-        ffukyj(fptr, keyname, (LONGLONG) *(long *) value, comm, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-        ffukyj(fptr, keyname, *(LONGLONG *) value, comm, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-        ffukye(fptr, keyname, *(float *) value, -7, comm, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-        ffukyd(fptr, keyname, *(double *) value, -15, comm, status);
-    }
-    else if (datatype == TCOMPLEX)
-    {
-        ffukyc(fptr, keyname, (float *) value, -7, comm, status);
-    }
-    else if (datatype == TDBLCOMPLEX)
-    {
-        ffukym(fptr, keyname, (double *) value, -15, comm, status);
-    }
-    else
-        *status = BAD_DATATYPE;
-
-    return(*status);
-} 
-/*--------------------------------------------------------------------------*/
-int ffukyu(fitsfile *fptr,      /* I - FITS file pointer  */
-           const char *keyname, /* I - keyword name       */
-           const char *comm,    /* I - keyword comment    */
-           int *status)         /* IO - error status      */
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkyu(fptr, keyname, comm, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffpkyu(fptr, keyname, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffukys(fitsfile *fptr,       /* I - FITS file pointer  */
-           const char *keyname,  /* I - keyword name       */
-           const char *value,    /* I - keyword value      */
-           const char *comm,     /* I - keyword comment    */
-           int *status)          /* IO - error status      */ 
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkys(fptr, keyname, value, comm, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffpkys(fptr, keyname, value, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffukls(fitsfile *fptr,      /* I - FITS file pointer  */
-           const char *keyname, /* I - keyword name       */
-           const char *value,   /* I - keyword value      */
-           const char *comm,    /* I - keyword comment    */
-           int *status)         /* IO - error status      */ 
-{
-    /* update a long string keyword */
-
-    int tstatus;
-    char junk[FLEN_ERRMSG];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkls(fptr, keyname, value, comm, status) == KEY_NO_EXIST)
-    {
-        /* since the ffmkls call failed, it wrote a bogus error message */
-        fits_read_errmsg(junk);  /* clear the error message */
-	
-        *status = tstatus;
-        ffpkls(fptr, keyname, value, comm, status);
-    }
-    return(*status);
-}/*--------------------------------------------------------------------------*/
-int ffukyl(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           int value,          /* I - keyword value      */
-           const char *comm,   /* I - keyword comment    */
-           int *status)        /* IO - error status      */
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkyl(fptr, keyname, value, comm, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffpkyl(fptr, keyname, value, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffukyj(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           LONGLONG value,     /* I - keyword value      */
-           const char *comm,   /* I - keyword comment    */
-           int *status)        /* IO - error status      */
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkyj(fptr, keyname, value, comm, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffpkyj(fptr, keyname, value, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffukyf(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           float value,        /* I - keyword value      */
-           int decim,          /* I - no of decimals     */         
-           const char *comm,   /* I - keyword comment    */
-           int *status)        /* IO - error status      */
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkyf(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffpkyf(fptr, keyname, value, decim, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffukye(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           float value,        /* I - keyword value      */
-           int decim,          /* I - no of decimals     */
-           const char *comm,   /* I - keyword comment    */
-           int *status)        /* IO - error status      */
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkye(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffpkye(fptr, keyname, value, decim, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffukyg(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           double value,       /* I - keyword value      */
-           int decim,          /* I - no of decimals     */
-           const char *comm,   /* I - keyword comment    */
-           int *status)        /* IO - error status      */
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkyg(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffpkyg(fptr, keyname, value, decim, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffukyd(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           double value,       /* I - keyword value      */
-           int decim,          /* I - no of decimals     */
-           const char *comm,   /* I - keyword comment    */
-           int *status)        /* IO - error status      */
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkyd(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffpkyd(fptr, keyname, value, decim, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffukfc(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           float *value,       /* I - keyword value      */
-           int decim,          /* I - no of decimals     */         
-           const char *comm,   /* I - keyword comment    */
-           int *status)        /* IO - error status      */
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkfc(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffpkfc(fptr, keyname, value, decim, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffukyc(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           float *value,       /* I - keyword value      */
-           int decim,          /* I - no of decimals     */
-           const char *comm,   /* I - keyword comment    */
-           int *status)        /* IO - error status      */
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkyc(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffpkyc(fptr, keyname, value, decim, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffukfm(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           double *value,      /* I - keyword value      */
-           int decim,          /* I - no of decimals     */
-           const char *comm,   /* I - keyword comment    */
-           int *status)        /* IO - error status      */
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkfm(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffpkfm(fptr, keyname, value, decim, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffukym(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           double *value,      /* I - keyword value      */
-           int decim,          /* I - no of decimals     */
-           const char *comm,   /* I - keyword comment    */
-           int *status)        /* IO - error status      */
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmkym(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffpkym(fptr, keyname, value, decim, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffucrd(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           const char *card,   /* I - card string value  */
-           int *status)        /* IO - error status      */
-{
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = *status;
-
-    if (ffmcrd(fptr, keyname, card, status) == KEY_NO_EXIST)
-    {
-        *status = tstatus;
-        ffprec(fptr, card, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmrec(fitsfile *fptr,    /* I - FITS file pointer               */
-           int nkey,          /* I - number of the keyword to modify */
-           const char *card,  /* I - card string value               */
-           int *status)       /* IO - error status                   */
-{
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffmaky(fptr, nkey+1, status);
-    ffmkey(fptr, card, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmcrd(fitsfile *fptr,      /* I - FITS file pointer  */
-           const char *keyname, /* I - keyword name       */
-           const char *card,    /* I - card string value  */
-           int *status)         /* IO - error status      */
-{
-    char tcard[FLEN_CARD], valstring[FLEN_CARD], comm[FLEN_CARD], value[FLEN_CARD];
-    char nextcomm[FLEN_COMMENT];
-    int keypos, len;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgcrd(fptr, keyname, tcard, status) > 0)
-        return(*status);
-
-    ffmkey(fptr, card, status);
-
-    /* calc position of keyword in header */
-    keypos = (int) ((((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu])) / 80) + 1;
-
-    ffpsvc(tcard, valstring, comm, status);
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* check for string value which may be continued over multiple keywords */
-    ffpmrk(); /* put mark on message stack; erase any messages after this */
-    ffc2s(valstring, value, status);   /* remove quotes and trailing spaces */
-
-    if (*status == VALUE_UNDEFINED) {
-       ffcmrk();  /* clear any spurious error messages, back to the mark */
-       *status = 0;
-    } else {
- 
-      len = strlen(value);
-
-      while (len && value[len - 1] == '&')  /* ampersand used as continuation char */
-      {
-        ffgcnt(fptr, value, nextcomm, status);
-        if (*value)
-        {
-            ffdrec(fptr, keypos, status);  /* delete the keyword */
-            len = strlen(value);
-        }
-        else   /* a null valstring indicates no continuation */
-            len = 0;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmnam(fitsfile *fptr,     /* I - FITS file pointer     */
-           const char *oldname,/* I - existing keyword name */
-           const char *newname,/* I - new name for keyword  */
-           int *status)        /* IO - error status         */
-{
-    char comm[FLEN_COMMENT];
-    char value[FLEN_VALUE];
-    char card[FLEN_CARD];
- 
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, oldname, value, comm, status) > 0)
-        return(*status);
-
-    ffmkky(newname, value, comm, card, status);  /* construct the card */
-    ffmkey(fptr, card, status);  /* rewrite with new name */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmcom(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           const char *comm,   /* I - keyword comment    */
-           int *status)        /* IO - error status      */
-{
-    char oldcomm[FLEN_COMMENT];
-    char value[FLEN_VALUE];
-    char card[FLEN_CARD];
- 
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, value, oldcomm, status) > 0)
-        return(*status);
-
-    ffmkky(keyname, value, comm, card, status);  /* construct the card */
-    ffmkey(fptr, card, status);  /* rewrite with new comment */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpunt(fitsfile *fptr,     /* I - FITS file pointer   */
-           const char *keyname,/* I - keyword name        */
-           const char *unit,   /* I - keyword unit string */
-           int *status)        /* IO - error status       */
-/*
-    Write (put) the units string into the comment field of the existing keyword.
-    This routine uses a  FITS convention  in which the units are enclosed in 
-    square brackets following the '/' comment field delimiter, e.g.:
-
-    KEYWORD =                   12 / [kpc] comment string goes here
-*/
-{
-    char oldcomm[FLEN_COMMENT];
-    char newcomm[FLEN_COMMENT];
-    char value[FLEN_VALUE];
-    char card[FLEN_CARD];
-    char *loc;
-    size_t len;
- 
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, value, oldcomm, status) > 0)
-        return(*status);
-
-    /* copy the units string to the new comment string if not null */
-    if (*unit)
-    {
-        strcpy(newcomm, "[");
-        strncat(newcomm, unit, 45);  /* max allowed length is about 45 chars */
-        strcat(newcomm, "] ");
-        len = strlen(newcomm);  
-        len = FLEN_COMMENT - len - 1;  /* amount of space left in the field */
-    }
-    else
-    {
-        newcomm[0] = '\0';
-        len = FLEN_COMMENT - 1;
-    }
-
-    if (oldcomm[0] == '[')  /* check for existing units field */
-    {
-        loc = strchr(oldcomm, ']');  /* look for the closing bracket */
-        if (loc)
-        {
-            loc++;
-            while (*loc == ' ')   /* skip any blank spaces */
-               loc++;
-
-            strncat(newcomm, loc, len);  /* concat remainder of comment */
-        }
-        else
-        {
-            strncat(newcomm, oldcomm, len);  /* append old comment onto new */
-        }
-    }
-    else
-    {
-        strncat(newcomm, oldcomm, len);
-    }
-
-    ffmkky(keyname, value, newcomm, card, status);  /* construct the card */
-    ffmkey(fptr, card, status);  /* rewrite with new units string */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkyu(fitsfile *fptr,     /* I - FITS file pointer  */
-           const char *keyname,/* I - keyword name       */
-           const char *comm,   /* I - keyword comment    */
-           int *status)        /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char oldcomm[FLEN_COMMENT];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
-        return(*status);                               /* get old comment */
-
-    strcpy(valstring," ");  /* create a dummy value string */
-
-    if (!comm || comm[0] == '&')  /* preserve the current comment string */
-        ffmkky(keyname, valstring, oldcomm, card, status);
-    else
-        ffmkky(keyname, valstring, comm, card, status);
-
-    ffmkey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkys(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           const char *value,       /* I - keyword value      */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-  /* NOTE: This routine does not support long continued strings */
-  /*  It will correctly overwrite an existing long continued string, */
-  /*  but it will not write a new long string.  */
-
-    char oldval[FLEN_VALUE], valstring[FLEN_VALUE];
-    char oldcomm[FLEN_COMMENT];
-    char card[FLEN_CARD], nextcomm[FLEN_COMMENT];
-    int len, keypos;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, oldval, oldcomm, status) > 0)
-        return(*status);                               /* get old comment */
-
-    ffs2c(value, valstring, status);   /* convert value to a string */
-
-    if (!comm || comm[0] == '&')  /* preserve the current comment string */
-        ffmkky(keyname, valstring, oldcomm, card, status);
-    else
-        ffmkky(keyname, valstring, comm, card, status);
-
-    ffmkey(fptr, card, status); /* overwrite the previous keyword */
-
-    keypos = (int) (((((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu])) / 80) + 1);
-
-    if (*status > 0)           
-        return(*status);
-
-    /* check if old string value was continued over multiple keywords */
-    ffpmrk(); /* put mark on message stack; erase any messages after this */
-    ffc2s(oldval, valstring, status); /* remove quotes and trailing spaces */
-
-    if (*status == VALUE_UNDEFINED) {
-       ffcmrk();  /* clear any spurious error messages, back to the mark */
-       *status = 0;
-    } else {
-        
-      len = strlen(valstring);
-
-      while (len && valstring[len - 1] == '&')  /* ampersand is continuation char */
-      {
-        ffgcnt(fptr, valstring, nextcomm, status);
-        if (*valstring)
-        {
-            ffdrec(fptr, keypos, status);  /* delete the continuation */
-            len = strlen(valstring);
-        }
-        else   /* a null valstring indicates no continuation */
-            len = 0;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkls( fitsfile *fptr,           /* I - FITS file pointer        */
-            const char *keyname,      /* I - name of keyword to write */
-            const char *value,        /* I - keyword value            */
-            const char *incomm,       /* I - keyword comment          */
-            int  *status)             /* IO - error status            */
-/*
-  Modify the value and optionally the comment of a long string keyword.
-  This routine supports the
-  HEASARC long string convention and can modify arbitrarily long string
-  keyword values.  The value is continued over multiple keywords that
-  have the name COMTINUE without an equal sign in column 9 of the card.
-  This routine also supports simple string keywords which are less than
-  69 characters in length.
-
-  This routine is not very efficient, so it should be used sparingly.
-*/
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD], tmpkeyname[FLEN_CARD];
-    char comm[FLEN_COMMENT];
-    char tstring[FLEN_VALUE], *cptr;
-    char *longval;
-    int next, remain, vlen, nquote, nchar, namelen, contin, tstatus = -1;
-    int nkeys, keypos;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (!incomm || incomm[0] == '&')  /* preserve the old comment string */
-    {
-        ffghps(fptr, &nkeys, &keypos, status); /* save current position */
-
-        if (ffgkls(fptr, keyname, &longval, comm, status) > 0)
-            return(*status);            /* keyword doesn't exist */
-
-        free(longval);  /* don't need the old value */
-
-        /* move back to previous position to ensure that we delete */
-        /* the right keyword in case there are more than one keyword */
-        /* with this same name. */
-        ffgrec(fptr, keypos - 1, card, status); 
-    } else {
-        /* copy the input comment string */
-        strncpy(comm, incomm, FLEN_COMMENT-1);
-        comm[FLEN_COMMENT-1] = '\0';
-    }
-
-    /* delete the old keyword */
-    if (ffdkey(fptr, keyname, status) > 0)
-        return(*status);            /* keyword doesn't exist */
-
-    ffghps(fptr, &nkeys, &keypos, status); /* save current position */
-
-    /* now construct the new keyword, and insert into header */
-    remain = strlen(value);    /* number of characters to write out */
-    next = 0;                  /* pointer to next character to write */
-    
-    /* count the number of single quote characters in the string */
-    nquote = 0;
-    cptr = strchr(value, '\'');   /* search for quote character */
-
-    while (cptr)  /* search for quote character */
-    {
-        nquote++;            /*  increment no. of quote characters  */
-        cptr++;              /*  increment pointer to next character */
-        cptr = strchr(cptr, '\'');  /* search for another quote char */
-    }
-
-    strncpy(tmpkeyname, keyname, 80);
-    tmpkeyname[80] = '\0';
-    
-    cptr = tmpkeyname;
-    while(*cptr == ' ')   /* skip over leading spaces in name */
-        cptr++;
-
-    /* determine the number of characters that will fit on the line */
-    /* Note: each quote character is expanded to 2 quotes */
-
-    namelen = strlen(cptr);
-    if (namelen <= 8 && (fftkey(cptr, &tstatus) <= 0) )
-    {
-        /* This a normal 8-character FITS keyword */
-        nchar = 68 - nquote; /*  max of 68 chars fit in a FITS string value */
-    }
-    else
-    {
-	nchar = 80 - nquote - namelen - 5;
-    }
-
-    contin = 0;
-    while (remain > 0)
-    {
-        strncpy(tstring, &value[next], nchar); /* copy string to temp buff */
-        tstring[nchar] = '\0';
-        ffs2c(tstring, valstring, status);  /* put quotes around the string */
-
-        if (remain > nchar)   /* if string is continued, put & as last char */
-        {
-            vlen = strlen(valstring);
-            nchar -= 1;        /* outputting one less character now */
-
-            if (valstring[vlen-2] != '\'')
-                valstring[vlen-2] = '&';  /*  over write last char with &  */
-            else
-            { /* last char was a pair of single quotes, so over write both */
-                valstring[vlen-3] = '&';
-                valstring[vlen-1] = '\0';
-            }
-        }
-
-        if (contin)           /* This is a CONTINUEd keyword */
-        {
-           ffmkky("CONTINUE", valstring, comm, card, status); /* make keyword */
-           strncpy(&card[8], "   ",  2);  /* overwrite the '=' */
-        }
-        else
-        {
-           ffmkky(keyname, valstring, comm, card, status);  /* make keyword */
-        }
-
-        ffirec(fptr, keypos, card, status);  /* insert the keyword */
-       
-        keypos++;        /* next insert position */
-        contin = 1;
-        remain -= nchar;
-        next  += nchar;
-        nchar = 68 - nquote;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkyl(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           int value,               /* I - keyword value      */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char oldcomm[FLEN_COMMENT];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
-        return(*status);                               /* get old comment */
-
-    ffl2c(value, valstring, status);   /* convert value to a string */
-
-    if (!comm || comm[0] == '&')  /* preserve the current comment string */
-        ffmkky(keyname, valstring, oldcomm, card, status);
-    else
-        ffmkky(keyname, valstring, comm, card, status);
-
-    ffmkey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkyj(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           LONGLONG value,          /* I - keyword value      */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char oldcomm[FLEN_COMMENT];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
-        return(*status);                               /* get old comment */
-
-    ffi2c(value, valstring, status);   /* convert value to a string */
-
-    if (!comm || comm[0] == '&')  /* preserve the current comment string */
-        ffmkky(keyname, valstring, oldcomm, card, status);
-    else
-        ffmkky(keyname, valstring, comm, card, status);
-
-    ffmkey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkyf(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           float value,             /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char oldcomm[FLEN_COMMENT];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
-        return(*status);                               /* get old comment */
-
-    ffr2f(value, decim, valstring, status);   /* convert value to a string */
-
-    if (!comm || comm[0] == '&')  /* preserve the current comment string */
-        ffmkky(keyname, valstring, oldcomm, card, status);
-    else
-        ffmkky(keyname, valstring, comm, card, status);
-
-    ffmkey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkye(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           float value,             /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char oldcomm[FLEN_COMMENT];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
-        return(*status);                               /* get old comment */
-
-    ffr2e(value, decim, valstring, status);   /* convert value to a string */
-
-    if (!comm || comm[0] == '&')  /* preserve the current comment string */
-        ffmkky(keyname, valstring, oldcomm, card, status);
-    else
-        ffmkky(keyname, valstring, comm, card, status);
-
-    ffmkey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkyg(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           double value,            /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char oldcomm[FLEN_COMMENT];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
-        return(*status);                               /* get old comment */
-
-    ffd2f(value, decim, valstring, status);   /* convert value to a string */
-
-    if (!comm || comm[0] == '&')  /* preserve the current comment string */
-        ffmkky(keyname, valstring, oldcomm, card, status);
-    else
-        ffmkky(keyname, valstring, comm, card, status);
-
-    ffmkey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkyd(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           double value,            /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char oldcomm[FLEN_COMMENT];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
-        return(*status);                               /* get old comment */
-
-    ffd2e(value, decim, valstring, status);   /* convert value to a string */
-
-    if (!comm || comm[0] == '&')  /* preserve the current comment string */
-        ffmkky(keyname, valstring, oldcomm, card, status);
-    else
-        ffmkky(keyname, valstring, comm, card, status);
-
-    ffmkey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkfc(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           float *value,            /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
-    char oldcomm[FLEN_COMMENT];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
-        return(*status);                               /* get old comment */
-
-    strcpy(valstring, "(" );
-    ffr2f(value[0], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ", ");
-    ffr2f(value[1], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ")");
-
-    if (!comm || comm[0] == '&')  /* preserve the current comment string */
-        ffmkky(keyname, valstring, oldcomm, card, status);
-    else
-        ffmkky(keyname, valstring, comm, card, status);
-
-    ffmkey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkyc(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           float *value,            /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
-    char oldcomm[FLEN_COMMENT];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
-        return(*status);                               /* get old comment */
-
-    strcpy(valstring, "(" );
-    ffr2e(value[0], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ", ");
-    ffr2e(value[1], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ")");
-
-    if (!comm || comm[0] == '&')  /* preserve the current comment string */
-        ffmkky(keyname, valstring, oldcomm, card, status);
-    else
-        ffmkky(keyname, valstring, comm, card, status);
-
-    ffmkey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkfm(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           double *value,           /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
-    char oldcomm[FLEN_COMMENT];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
-        return(*status);                               /* get old comment */
-
-    strcpy(valstring, "(" );
-    ffd2f(value[0], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ", ");
-    ffd2f(value[1], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ")");
-
-    if (!comm || comm[0] == '&')  /* preserve the current comment string */
-        ffmkky(keyname, valstring, oldcomm, card, status);
-    else
-        ffmkky(keyname, valstring, comm, card, status);
-
-    ffmkey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffmkym(fitsfile *fptr,    /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           double *value,     /* I - keyword value      */
-           int decim,         /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */
-           int *status)       /* IO - error status      */
-{
-    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
-    char oldcomm[FLEN_COMMENT];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
-        return(*status);                               /* get old comment */
-
-    strcpy(valstring, "(" );
-    ffd2e(value[0], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ", ");
-    ffd2e(value[1], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ")");
-
-    if (!comm || comm[0] == '&')  /* preserve the current comment string */
-        ffmkky(keyname, valstring, oldcomm, card, status);
-    else
-        ffmkky(keyname, valstring, comm, card, status);
-
-    ffmkey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikyu(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-/*
-  Insert a null-valued keyword and comment into the FITS header.  
-*/
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    strcpy(valstring," ");  /* create a dummy value string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffikey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikys(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           const char *value,       /* I - keyword value      */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffs2c(value, valstring, status);   /* put quotes around the string */
-
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffikey(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikls( fitsfile *fptr,           /* I - FITS file pointer        */
-            const char *keyname,      /* I - name of keyword to write */
-            const char *value,        /* I - keyword value            */
-            const char *comm,         /* I - keyword comment          */
-            int  *status)             /* IO - error status            */
-/*
-  Insert a long string keyword.  This routine supports the
-  HEASARC long string convention and can insert arbitrarily long string
-  keyword values.  The value is continued over multiple keywords that
-  have the name COMTINUE without an equal sign in column 9 of the card.
-  This routine also supports simple string keywords which are less than
-  69 characters in length.
-*/
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD], tmpkeyname[FLEN_CARD];
-    char tstring[FLEN_VALUE], *cptr;
-    int next, remain, vlen, nquote, nchar, namelen, contin, tstatus = -1;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /*  construct the new keyword, and insert into header */
-    remain = strlen(value);    /* number of characters to write out */
-    next = 0;                  /* pointer to next character to write */
-    
-    /* count the number of single quote characters in the string */
-    nquote = 0;
-    cptr = strchr(value, '\'');   /* search for quote character */
-
-    while (cptr)  /* search for quote character */
-    {
-        nquote++;            /*  increment no. of quote characters  */
-        cptr++;              /*  increment pointer to next character */
-        cptr = strchr(cptr, '\'');  /* search for another quote char */
-    }
-
-
-    strncpy(tmpkeyname, keyname, 80);
-    tmpkeyname[80] = '\0';
-    
-    cptr = tmpkeyname;
-    while(*cptr == ' ')   /* skip over leading spaces in name */
-        cptr++;
-
-    /* determine the number of characters that will fit on the line */
-    /* Note: each quote character is expanded to 2 quotes */
-
-    namelen = strlen(cptr);
-    if (namelen <= 8 && (fftkey(cptr, &tstatus) <= 0) )
-    {
-        /* This a normal 8-character FITS keyword */
-        nchar = 68 - nquote; /*  max of 68 chars fit in a FITS string value */
-    }
-    else
-    {
-	nchar = 80 - nquote - namelen - 5;
-    }
-
-    contin = 0;
-    while (remain > 0)
-    {
-        strncpy(tstring, &value[next], nchar); /* copy string to temp buff */
-        tstring[nchar] = '\0';
-        ffs2c(tstring, valstring, status);  /* put quotes around the string */
-
-        if (remain > nchar)   /* if string is continued, put & as last char */
-        {
-            vlen = strlen(valstring);
-            nchar -= 1;        /* outputting one less character now */
-
-            if (valstring[vlen-2] != '\'')
-                valstring[vlen-2] = '&';  /*  over write last char with &  */
-            else
-            { /* last char was a pair of single quotes, so over write both */
-                valstring[vlen-3] = '&';
-                valstring[vlen-1] = '\0';
-            }
-        }
-
-        if (contin)           /* This is a CONTINUEd keyword */
-        {
-           ffmkky("CONTINUE", valstring, comm, card, status); /* make keyword */
-           strncpy(&card[8], "   ",  2);  /* overwrite the '=' */
-        }
-        else
-        {
-           ffmkky(keyname, valstring, comm, card, status);  /* make keyword */
-        }
-
-        ffikey(fptr, card, status);  /* insert the keyword */
-       
-        contin = 1;
-        remain -= nchar;
-        next  += nchar;
-        nchar = 68 - nquote;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikyl(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           int value,               /* I - keyword value      */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffl2c(value, valstring, status);   /* convert logical to 'T' or 'F' */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffikey(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikyj(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           LONGLONG value,          /* I - keyword value      */
-           const char *comm,        /* I - keyword comment    */
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffi2c(value, valstring, status);   /* convert to formatted string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffikey(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikyf(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           float value,             /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */ 
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffr2f(value, decim, valstring, status);   /* convert to formatted string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffikey(fptr, card, status);  /* write the keyword*/
-
-    return(*status); 
-}
-/*--------------------------------------------------------------------------*/
-int ffikye(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           float value,             /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */ 
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffr2e(value, decim, valstring, status);   /* convert to formatted string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffikey(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikyg(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           double value,            /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */ 
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffd2f(value, decim, valstring, status);   /* convert to formatted string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffikey(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikyd(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           double value,            /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */ 
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffd2e(value, decim, valstring, status);   /* convert to formatted string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffikey(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikfc(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           float *value,            /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */ 
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    strcpy(valstring, "(" );
-    ffr2f(value[0], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ", ");
-    ffr2f(value[1], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ")");
-
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffikey(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikyc(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           float *value,            /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */ 
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    strcpy(valstring, "(" );
-    ffr2e(value[0], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ", ");
-    ffr2e(value[1], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ")");
-
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffikey(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikfm(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           double *value,           /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */ 
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-
-    strcpy(valstring, "(" );
-    ffd2f(value[0], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ", ");
-    ffd2f(value[1], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ")");
-
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffikey(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikym(fitsfile *fptr,          /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           double *value,           /* I - keyword value      */
-           int decim,               /* I - no of decimals     */
-           const char *comm,        /* I - keyword comment    */ 
-           int *status)             /* IO - error status      */
-{
-    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    strcpy(valstring, "(" );
-    ffd2e(value[0], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ", ");
-    ffd2e(value[1], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ")");
-
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffikey(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffirec(fitsfile *fptr,    /* I - FITS file pointer              */
-           int nkey,          /* I - position to insert new keyword */
-           const char *card,  /* I - card string value              */
-           int *status)       /* IO - error status                  */
-{
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffmaky(fptr, nkey, status);  /* move to insert position */
-    ffikey(fptr, card, status);  /* insert the keyword card */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffikey(fitsfile *fptr,    /* I - FITS file pointer  */
-           const char *card,  /* I - card string value  */
-           int *status)       /* IO - error status      */
-/*
-  insert a keyword at the position of (fptr->Fptr)->nextkey
-*/
-{
-    int ii, len, nshift, keylength;
-    long nblocks;
-    LONGLONG bytepos;
-    char *inbuff, *outbuff, *tmpbuff, buff1[FLEN_CARD], buff2[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if ( ((fptr->Fptr)->datastart - (fptr->Fptr)->headend) == 80) /* only room for END card */
-    {
-        nblocks = 1;
-        if (ffiblk(fptr, nblocks, 0, status) > 0) /* add new 2880-byte block*/
-            return(*status);  
-    }
-
-    /* no. keywords to shift */
-    nshift= (int) (( (fptr->Fptr)->headend - (fptr->Fptr)->nextkey ) / 80); 
-
-    strncpy(buff2, card, 80);     /* copy card to output buffer */
-    buff2[80] = '\0';
-
-    len = strlen(buff2);
-
-    /* silently replace any illegal characters with a space */
-    for (ii=0; ii < len; ii++)   
-        if (buff2[ii] < ' ' || buff2[ii] > 126) buff2[ii] = ' ';
-
-    for (ii=len; ii < 80; ii++)   /* fill buffer with spaces if necessary */
-        buff2[ii] = ' ';
-
-    keylength = strcspn(buff2, "=");
-    if (keylength == 80) keylength = 8;
-    
-    for (ii=0; ii < keylength; ii++)       /* make sure keyword name is uppercase */
-        buff2[ii] = toupper(buff2[ii]);
-
-    fftkey(buff2, status);        /* test keyword name contains legal chars */
-
-/*  no need to do this any more, since any illegal characters have been removed
-    fftrec(buff2, status);  */      /* test rest of keyword for legal chars   */
-
-    inbuff = buff1;
-    outbuff = buff2;
-
-    bytepos = (fptr->Fptr)->nextkey;           /* pointer to next keyword in header */
-    ffmbyt(fptr, bytepos, REPORT_EOF, status);
-
-    for (ii = 0; ii < nshift; ii++) /* shift each keyword down one position */
-    {
-        ffgbyt(fptr, 80, inbuff, status);   /* read the current keyword */
-
-        ffmbyt(fptr, bytepos, REPORT_EOF, status); /* move back */
-        ffpbyt(fptr, 80, outbuff, status);  /* overwrite with other buffer */
-
-        tmpbuff = inbuff;   /* swap input and output buffers */
-        inbuff = outbuff;
-        outbuff = tmpbuff;
-
-        bytepos += 80;
-    }
-
-    ffpbyt(fptr, 80, outbuff, status);  /* write the final keyword */
-
-    (fptr->Fptr)->headend += 80; /* increment the position of the END keyword */
-    (fptr->Fptr)->nextkey += 80; /* increment the pointer to next keyword */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffdkey(fitsfile *fptr,    /* I - FITS file pointer  */
-           const char *keyname,     /* I - keyword name       */
-           int *status)       /* IO - error status      */
-/*
-  delete a specified header keyword
-*/
-{
-    int keypos, len;
-    char valstring[FLEN_VALUE], comm[FLEN_COMMENT], value[FLEN_VALUE];
-    char message[FLEN_ERRMSG], nextcomm[FLEN_COMMENT];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgkey(fptr, keyname, valstring, comm, status) > 0) /* read keyword */
-    {
-        sprintf(message, "Could not find the %s keyword to delete (ffdkey)",
-                keyname);
-        ffpmsg(message);
-        return(*status);
-    }
-
-    /* calc position of keyword in header */
-    keypos = (int) ((((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu])) / 80);
-
-    ffdrec(fptr, keypos, status);  /* delete the keyword */
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* check for string value which may be continued over multiple keywords */
-    ffpmrk(); /* put mark on message stack; erase any messages after this */
-    ffc2s(valstring, value, status);   /* remove quotes and trailing spaces */
-
-    if (*status == VALUE_UNDEFINED) {
-       ffcmrk();  /* clear any spurious error messages, back to the mark */
-       *status = 0;
-    } else {
- 
-      len = strlen(value);
-
-      while (len && value[len - 1] == '&')  /* ampersand used as continuation char */
-      {
-        ffgcnt(fptr, value, nextcomm, status);
-        if (*value)
-        {
-            ffdrec(fptr, keypos, status);  /* delete the keyword */
-            len = strlen(value);
-        }
-        else   /* a null valstring indicates no continuation */
-            len = 0;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffdstr(fitsfile *fptr,    /* I - FITS file pointer  */
-           const char *string,     /* I - keyword name       */
-           int *status)       /* IO - error status      */
-/*
-  delete a specified header keyword containing the input string
-*/
-{
-    int keypos, len;
-    char valstring[FLEN_VALUE], comm[FLEN_COMMENT], value[FLEN_VALUE];
-    char card[FLEN_CARD], message[FLEN_ERRMSG], nextcomm[FLEN_COMMENT];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (ffgstr(fptr, string, card, status) > 0) /* read keyword */
-    {
-        sprintf(message, "Could not find the %s keyword to delete (ffdkey)",
-                string);
-        ffpmsg(message);
-        return(*status);
-    }
-
-    /* calc position of keyword in header */
-    keypos = (int) ((((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu])) / 80);
-
-    ffdrec(fptr, keypos, status);  /* delete the keyword */
-
-    /* check for string value which may be continued over multiple keywords */
-    ffpsvc(card, valstring, comm, status);
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* check for string value which may be continued over multiple keywords */
-    ffpmrk(); /* put mark on message stack; erase any messages after this */
-    ffc2s(valstring, value, status);   /* remove quotes and trailing spaces */
-
-    if (*status == VALUE_UNDEFINED) {
-       ffcmrk();  /* clear any spurious error messages, back to the mark */
-       *status = 0;
-    } else {
- 
-      len = strlen(value);
-
-      while (len && value[len - 1] == '&')  /* ampersand used as continuation char */
-      {
-        ffgcnt(fptr, value, nextcomm, status);
-        if (*value)
-        {
-            ffdrec(fptr, keypos, status);  /* delete the keyword */
-            len = strlen(value);
-        }
-        else   /* a null valstring indicates no continuation */
-            len = 0;
-      }
-    }
-
-    return(*status);
-}/*--------------------------------------------------------------------------*/
-int ffdrec(fitsfile *fptr,   /* I - FITS file pointer  */
-           int keypos,       /* I - position in header of keyword to delete */
-           int *status)      /* IO - error status      */
-/*
-  Delete a header keyword at position keypos. The 1st keyword is at keypos=1.
-*/
-{
-    int ii, nshift;
-    LONGLONG bytepos;
-    char *inbuff, *outbuff, *tmpbuff, buff1[81], buff2[81];
-    char message[FLEN_ERRMSG];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if (keypos < 1 ||
-        keypos > (fptr->Fptr)->headend - (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] / 80 )
-        return(*status = KEY_OUT_BOUNDS);
-
-    (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] + (keypos - 1) * 80;
-
-    nshift=(int) (( (fptr->Fptr)->headend - (fptr->Fptr)->nextkey ) / 80); /* no. keywords to shift */
-
-    if (nshift <= 0)
-    {
-        sprintf(message, "Cannot delete keyword number %d.  It does not exist.",
-                keypos);
-        ffpmsg(message);
-        return(*status = KEY_OUT_BOUNDS);
-    }
-
-    bytepos = (fptr->Fptr)->headend - 80;  /* last keyword in header */  
-
-    /* construct a blank keyword */
-    strcpy(buff2, "                                        ");
-    strcat(buff2, "                                        ");
-    inbuff  = buff1;
-    outbuff = buff2;
-    for (ii = 0; ii < nshift; ii++) /* shift each keyword up one position */
-    {
-
-        ffmbyt(fptr, bytepos, REPORT_EOF, status);
-        ffgbyt(fptr, 80, inbuff, status);   /* read the current keyword */
-
-        ffmbyt(fptr, bytepos, REPORT_EOF, status);
-        ffpbyt(fptr, 80, outbuff, status);  /* overwrite with next keyword */
-
-        tmpbuff = inbuff;   /* swap input and output buffers */
-        inbuff = outbuff;
-        outbuff = tmpbuff;
-
-        bytepos -= 80;
-    }
-
-    (fptr->Fptr)->headend -= 80; /* decrement the position of the END keyword */
-    return(*status);
-}
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/pliocomp.c b/src/external/OpenGR/3rdparty/cfitsio/pliocomp.c
deleted file mode 100644
index 47a636918..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/pliocomp.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/* stdlib is needed for the abs function */
-#include 
-/*
-   The following prototype code was provided by Doug Tody, NRAO, for
-   performing conversion between pixel arrays and line lists.  The
-   compression technique is used in IRAF.
-*/
-int pl_p2li (int *pxsrc, int xs, short *lldst, int npix);
-int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix);
-
-
-/*
- * PL_P2L -- Convert a pixel array to a line list.  The length of the list is
- * returned as the function value.
- *
- * Translated from the SPP version using xc -f, f2c.  8Sep99 DCT.
- */
-
-#ifndef min
-#define min(a,b)        (((a)<(b))?(a):(b))
-#endif
-#ifndef max
-#define max(a,b)        (((a)>(b))?(a):(b))
-#endif
-
-int pl_p2li (int *pxsrc, int xs, short *lldst, int npix)
-/* int *pxsrc;                      input pixel array */
-/* int xs;                          starting index in pxsrc (?) */
-/* short *lldst;                    encoded line list */
-/* int npix;                        number of pixels to convert */
-{
-    /* System generated locals */
-    int ret_val, i__1, i__2, i__3;
-
-    /* Local variables */
-    int zero, v, x1, hi, ip, dv, xe, np, op, iz, nv = 0, pv, nz;
-
-    /* Parameter adjustments */
-    --lldst;
-    --pxsrc;
-
-    /* Function Body */
-    if (! (npix <= 0)) {
-        goto L110;
-    }
-    ret_val = 0;
-    goto L100;
-L110:
-    lldst[3] = -100;
-    lldst[2] = 7;
-    lldst[1] = 0;
-    lldst[6] = 0;
-    lldst[7] = 0;
-    xe = xs + npix - 1;
-    op = 8;
-    zero = 0;
-/* Computing MAX */
-    i__1 = zero, i__2 = pxsrc[xs];
-    pv = max(i__1,i__2);
-    x1 = xs;
-    iz = xs;
-    hi = 1;
-    i__1 = xe;
-    for (ip = xs; ip <= i__1; ++ip) {
-        if (! (ip < xe)) {
-            goto L130;
-        }
-/* Computing MAX */
-        i__2 = zero, i__3 = pxsrc[ip + 1];
-        nv = max(i__2,i__3);
-        if (! (nv == pv)) {
-            goto L140;
-        }
-        goto L120;
-L140:
-        if (! (pv == 0)) {
-            goto L150;
-        }
-        pv = nv;
-        x1 = ip + 1;
-        goto L120;
-L150:
-        goto L131;
-L130:
-        if (! (pv == 0)) {
-            goto L160;
-        }
-        x1 = xe + 1;
-L160:
-L131:
-        np = ip - x1 + 1;
-        nz = x1 - iz;
-        if (! (pv > 0)) {
-            goto L170;
-        }
-        dv = pv - hi;
-        if (! (dv != 0)) {
-            goto L180;
-        }
-        hi = pv;
-        if (! (abs(dv) > 4095)) {
-            goto L190;
-        }
-        lldst[op] = (short) ((pv & 4095) + 4096);
-        ++op;
-        lldst[op] = (short) (pv / 4096);
-        ++op;
-        goto L191;
-L190:
-        if (! (dv < 0)) {
-            goto L200;
-        }
-        lldst[op] = (short) (-dv + 12288);
-        goto L201;
-L200:
-        lldst[op] = (short) (dv + 8192);
-L201:
-        ++op;
-        if (! (np == 1 && nz == 0)) {
-            goto L210;
-        }
-        v = lldst[op - 1];
-        lldst[op - 1] = (short) (v | 16384);
-        goto L91;
-L210:
-L191:
-L180:
-L170:
-        if (! (nz > 0)) {
-            goto L220;
-        }
-L230:
-        if (! (nz > 0)) {
-            goto L232;
-        }
-        lldst[op] = (short) min(4095,nz);
-        ++op;
-/* L231: */
-        nz += -4095;
-        goto L230;
-L232:
-        if (! (np == 1 && pv > 0)) {
-            goto L240;
-        }
-        lldst[op - 1] = (short) (lldst[op - 1] + 20481);
-        goto L91;
-L240:
-L220:
-L250:
-        if (! (np > 0)) {
-            goto L252;
-        }
-        lldst[op] = (short) (min(4095,np) + 16384);
-        ++op;
-/* L251: */
-        np += -4095;
-        goto L250;
-L252:
-L91:
-        x1 = ip + 1;
-        iz = x1;
-        pv = nv;
-L120:
-        ;
-    }
-/* L121: */
-    lldst[4] = (short) ((op - 1) % 32768);
-    lldst[5] = (short) ((op - 1) / 32768);
-    ret_val = op - 1;
-    goto L100;
-L100:
-    return ret_val;
-} /* plp2li_ */
-
-/*
- * PL_L2PI -- Translate a PLIO line list into an integer pixel array.
- * The number of pixels output (always npix) is returned as the function
- * value.
- *
- * Translated from the SPP version using xc -f, f2c.  8Sep99 DCT.
- */
-
-int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix)
-/* short *ll_src;                   encoded line list */
-/* int xs;                          starting index in ll_src */
-/* int *px_dst;                    output pixel array */
-/* int npix;                       number of pixels to convert */
-{
-    /* System generated locals */
-    int ret_val, i__1, i__2;
-
-    /* Local variables */
-    int data, sw0001, otop, i__, lllen, i1, i2, x1, x2, ip, xe, np,
-             op, pv, opcode, llfirt;
-    int skipwd;
-
-    /* Parameter adjustments */
-    --px_dst;
-    --ll_src;
-
-    /* Function Body */
-    if (! (ll_src[3] > 0)) {
-        goto L110;
-    }
-    lllen = ll_src[3];
-    llfirt = 4;
-    goto L111;
-L110:
-    lllen = (ll_src[5] << 15) + ll_src[4];
-    llfirt = ll_src[2] + 1;
-L111:
-    if (! (npix <= 0 || lllen <= 0)) {
-        goto L120;
-    }
-    ret_val = 0;
-    goto L100;
-L120:
-    xe = xs + npix - 1;
-    skipwd = 0;
-    op = 1;
-    x1 = 1;
-    pv = 1;
-    i__1 = lllen;
-    for (ip = llfirt; ip <= i__1; ++ip) {
-        if (! skipwd) {
-            goto L140;
-        }
-        skipwd = 0;
-        goto L130;
-L140:
-        opcode = ll_src[ip] / 4096;
-        data = ll_src[ip] & 4095;
-        sw0001 = opcode;
-        goto L150;
-L160:
-        x2 = x1 + data - 1;
-        i1 = max(x1,xs);
-        i2 = min(x2,xe);
-        np = i2 - i1 + 1;
-        if (! (np > 0)) {
-            goto L170;
-        }
-        otop = op + np - 1;
-        if (! (opcode == 4)) {
-            goto L180;
-        }
-        i__2 = otop;
-        for (i__ = op; i__ <= i__2; ++i__) {
-            px_dst[i__] = pv;
-/* L190: */
-        }
-/* L191: */
-        goto L181;
-L180:
-        i__2 = otop;
-        for (i__ = op; i__ <= i__2; ++i__) {
-            px_dst[i__] = 0;
-/* L200: */
-        }
-/* L201: */
-        if (! (opcode == 5 && i2 == x2)) {
-            goto L210;
-        }
-        px_dst[otop] = pv;
-L210:
-L181:
-        op = otop + 1;
-L170:
-        x1 = x2 + 1;
-        goto L151;
-L220:
-        pv = (ll_src[ip + 1] << 12) + data;
-        skipwd = 1;
-        goto L151;
-L230:
-        pv += data;
-        goto L151;
-L240:
-        pv -= data;
-        goto L151;
-L250:
-        pv += data;
-        goto L91;
-L260:
-        pv -= data;
-L91:
-        if (! (x1 >= xs && x1 <= xe)) {
-            goto L270;
-        }
-        px_dst[op] = pv;
-        ++op;
-L270:
-        ++x1;
-        goto L151;
-L150:
-        ++sw0001;
-        if (sw0001 < 1 || sw0001 > 8) {
-            goto L151;
-        }
-        switch ((int)sw0001) {
-            case 1:  goto L160;
-            case 2:  goto L220;
-            case 3:  goto L230;
-            case 4:  goto L240;
-            case 5:  goto L160;
-            case 6:  goto L160;
-            case 7:  goto L250;
-            case 8:  goto L260;
-        }
-L151:
-        if (! (x1 > xe)) {
-            goto L280;
-        }
-        goto L131;
-L280:
-L130:
-        ;
-    }
-L131:
-    i__1 = npix;
-    for (i__ = op; i__ <= i__1; ++i__) {
-        px_dst[i__] = 0;
-/* L290: */
-    }
-/* L291: */
-    ret_val = npix;
-    goto L100;
-L100:
-    return ret_val;
-} /* pll2pi_ */
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcol.c b/src/external/OpenGR/3rdparty/cfitsio/putcol.c
deleted file mode 100644
index 676cfd9db..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcol.c
+++ /dev/null
@@ -1,1941 +0,0 @@
-/*  This file, putcol.c, contains routines that write data elements to     */
-/*  a FITS image or table. These are the generic routines.                 */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffppx(  fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  datatype,   /* I - datatype of the value                   */
-            long  *firstpix, /* I - coord of  first pixel to write(1 based) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            void  *array,    /* I - array of values that are written        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of pixels to the primary array.  The datatype of the
-  input array is defined by the 2nd argument. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written). 
-  
-  This routine is simillar to ffppr, except it supports writing to 
-  large images with more than 2**31 pixels.
-*/
-{
-    int naxis, ii;
-    long group = 1;
-    LONGLONG firstelem, dimsize = 1, naxes[9];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* get the size of the image */
-    ffgidm(fptr, &naxis, status);
-    ffgiszll(fptr, 9, naxes, status);
-
-    firstelem = 0;
-    for (ii=0; ii < naxis; ii++)
-    {
-        firstelem += ((firstpix[ii] - 1) * dimsize);
-        dimsize *= naxes[ii];
-    }
-    firstelem++;
-
-    if (datatype == TBYTE)
-    {
-      ffpprb(fptr, group, firstelem, nelem, (unsigned char *) array, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-      ffpprsb(fptr, group, firstelem, nelem, (signed char *) array, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-      ffpprui(fptr, group, firstelem, nelem, (unsigned short *) array,
-              status);
-    }
-    else if (datatype == TSHORT)
-    {
-      ffppri(fptr, group, firstelem, nelem, (short *) array, status);
-    }
-    else if (datatype == TUINT)
-    {
-      ffppruk(fptr, group, firstelem, nelem, (unsigned int *) array, status);
-    }
-    else if (datatype == TINT)
-    {
-      ffpprk(fptr, group, firstelem, nelem, (int *) array, status);
-    }
-    else if (datatype == TULONG)
-    {
-      ffppruj(fptr, group, firstelem, nelem, (unsigned long *) array, status);
-    }
-    else if (datatype == TLONG)
-    {
-      ffpprj(fptr, group, firstelem, nelem, (long *) array, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-      ffpprjj(fptr, group, firstelem, nelem, (LONGLONG *) array, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      ffppre(fptr, group, firstelem, nelem, (float *) array, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-      ffpprd(fptr, group, firstelem, nelem, (double *) array, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppxll(  fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  datatype,   /* I - datatype of the value                   */
-            LONGLONG  *firstpix, /* I - coord of  first pixel to write(1 based) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            void  *array,    /* I - array of values that are written        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of pixels to the primary array.  The datatype of the
-  input array is defined by the 2nd argument. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written). 
-  
-  This routine is simillar to ffppr, except it supports writing to 
-  large images with more than 2**31 pixels.
-*/
-{
-    int naxis, ii;
-    long group = 1;
-    LONGLONG firstelem, dimsize = 1, naxes[9];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* get the size of the image */
-    ffgidm(fptr, &naxis, status);
-    ffgiszll(fptr, 9, naxes, status);
-
-    firstelem = 0;
-    for (ii=0; ii < naxis; ii++)
-    {
-        firstelem += ((firstpix[ii] - 1) * dimsize);
-        dimsize *= naxes[ii];
-    }
-    firstelem++;
-
-    if (datatype == TBYTE)
-    {
-      ffpprb(fptr, group, firstelem, nelem, (unsigned char *) array, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-      ffpprsb(fptr, group, firstelem, nelem, (signed char *) array, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-      ffpprui(fptr, group, firstelem, nelem, (unsigned short *) array,
-              status);
-    }
-    else if (datatype == TSHORT)
-    {
-      ffppri(fptr, group, firstelem, nelem, (short *) array, status);
-    }
-    else if (datatype == TUINT)
-    {
-      ffppruk(fptr, group, firstelem, nelem, (unsigned int *) array, status);
-    }
-    else if (datatype == TINT)
-    {
-      ffpprk(fptr, group, firstelem, nelem, (int *) array, status);
-    }
-    else if (datatype == TULONG)
-    {
-      ffppruj(fptr, group, firstelem, nelem, (unsigned long *) array, status);
-    }
-    else if (datatype == TLONG)
-    {
-      ffpprj(fptr, group, firstelem, nelem, (long *) array, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-      ffpprjj(fptr, group, firstelem, nelem, (LONGLONG *) array, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      ffppre(fptr, group, firstelem, nelem, (float *) array, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-      ffpprd(fptr, group, firstelem, nelem, (double *) array, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppxn(  fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  datatype,   /* I - datatype of the value                   */
-            long  *firstpix, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            void  *array,    /* I - array of values that are written        */
-            void  *nulval,   /* I - pointer to the null value               */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array.  The datatype of the
-  input array is defined by the 2nd argument. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-
-  This routine supports writing to large images with
-  more than 2**31 pixels.
-*/
-{
-    int naxis, ii;
-    long group = 1;
-    LONGLONG firstelem, dimsize = 1, naxes[9];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (nulval == NULL)  /* null value not defined? */
-    {
-        ffppx(fptr, datatype, firstpix, nelem, array, status);
-        return(*status);
-    }
-
-    /* get the size of the image */
-    ffgidm(fptr, &naxis, status);
-    ffgiszll(fptr, 9, naxes, status);
-
-    firstelem = 0;
-    for (ii=0; ii < naxis; ii++)
-    {
-        firstelem += ((firstpix[ii] - 1) * dimsize);
-        dimsize *= naxes[ii];
-    }
-    firstelem++;
-
-    if (datatype == TBYTE)
-    {
-      ffppnb(fptr, group, firstelem, nelem, (unsigned char *) array, 
-             *(unsigned char *) nulval, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-      ffppnsb(fptr, group, firstelem, nelem, (signed char *) array, 
-             *(signed char *) nulval, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-      ffppnui(fptr, group, firstelem, nelem, (unsigned short *) array,
-              *(unsigned short *) nulval,status);
-    }
-    else if (datatype == TSHORT)
-    {
-      ffppni(fptr, group, firstelem, nelem, (short *) array,
-             *(short *) nulval, status);
-    }
-    else if (datatype == TUINT)
-    {
-      ffppnuk(fptr, group, firstelem, nelem, (unsigned int *) array,
-             *(unsigned int *) nulval, status);
-    }
-    else if (datatype == TINT)
-    {
-      ffppnk(fptr, group, firstelem, nelem, (int *) array,
-             *(int *) nulval, status);
-    }
-    else if (datatype == TULONG)
-    {
-      ffppnuj(fptr, group, firstelem, nelem, (unsigned long *) array,
-              *(unsigned long *) nulval,status);
-    }
-    else if (datatype == TLONG)
-    {
-      ffppnj(fptr, group, firstelem, nelem, (long *) array,
-             *(long *) nulval, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-      ffppnjj(fptr, group, firstelem, nelem, (LONGLONG *) array,
-             *(LONGLONG *) nulval, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      ffppne(fptr, group, firstelem, nelem, (float *) array,
-             *(float *) nulval, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-      ffppnd(fptr, group, firstelem, nelem, (double *) array,
-             *(double *) nulval, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppxnll(  fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  datatype,   /* I - datatype of the value                   */
-            LONGLONG  *firstpix, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            void  *array,    /* I - array of values that are written        */
-            void  *nulval,   /* I - pointer to the null value               */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array.  The datatype of the
-  input array is defined by the 2nd argument. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-
-  This routine supports writing to large images with
-  more than 2**31 pixels.
-*/
-{
-    int naxis, ii;
-    long  group = 1;
-    LONGLONG firstelem, dimsize = 1, naxes[9];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (nulval == NULL)  /* null value not defined? */
-    {
-        ffppxll(fptr, datatype, firstpix, nelem, array, status);
-        return(*status);
-    }
-
-    /* get the size of the image */
-    ffgidm(fptr, &naxis, status);
-    ffgiszll(fptr, 9, naxes, status);
-
-    firstelem = 0;
-    for (ii=0; ii < naxis; ii++)
-    {
-        firstelem += ((firstpix[ii] - 1) * dimsize);
-        dimsize *= naxes[ii];
-    }
-    firstelem++;
-
-    if (datatype == TBYTE)
-    {
-      ffppnb(fptr, group, firstelem, nelem, (unsigned char *) array, 
-             *(unsigned char *) nulval, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-      ffppnsb(fptr, group, firstelem, nelem, (signed char *) array, 
-             *(signed char *) nulval, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-      ffppnui(fptr, group, firstelem, nelem, (unsigned short *) array,
-              *(unsigned short *) nulval,status);
-    }
-    else if (datatype == TSHORT)
-    {
-      ffppni(fptr, group, firstelem, nelem, (short *) array,
-             *(short *) nulval, status);
-    }
-    else if (datatype == TUINT)
-    {
-      ffppnuk(fptr, group, firstelem, nelem, (unsigned int *) array,
-             *(unsigned int *) nulval, status);
-    }
-    else if (datatype == TINT)
-    {
-      ffppnk(fptr, group, firstelem, nelem, (int *) array,
-             *(int *) nulval, status);
-    }
-    else if (datatype == TULONG)
-    {
-      ffppnuj(fptr, group, firstelem, nelem, (unsigned long *) array,
-              *(unsigned long *) nulval,status);
-    }
-    else if (datatype == TLONG)
-    {
-      ffppnj(fptr, group, firstelem, nelem, (long *) array,
-             *(long *) nulval, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-      ffppnjj(fptr, group, firstelem, nelem, (LONGLONG *) array,
-             *(LONGLONG *) nulval, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      ffppne(fptr, group, firstelem, nelem, (float *) array,
-             *(float *) nulval, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-      ffppnd(fptr, group, firstelem, nelem, (double *) array,
-             *(double *) nulval, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppr(  fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  datatype,   /* I - datatype of the value                   */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            void  *array,    /* I - array of values that are written        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array.  The datatype of the
-  input array is defined by the 2nd argument. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-
-*/
-{
-    long group = 1;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (datatype == TBYTE)
-    {
-      ffpprb(fptr, group, firstelem, nelem, (unsigned char *) array, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-      ffpprsb(fptr, group, firstelem, nelem, (signed char *) array, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-      ffpprui(fptr, group, firstelem, nelem, (unsigned short *) array,
-              status);
-    }
-    else if (datatype == TSHORT)
-    {
-      ffppri(fptr, group, firstelem, nelem, (short *) array, status);
-    }
-    else if (datatype == TUINT)
-    {
-      ffppruk(fptr, group, firstelem, nelem, (unsigned int *) array, status);
-    }
-    else if (datatype == TINT)
-    {
-      ffpprk(fptr, group, firstelem, nelem, (int *) array, status);
-    }
-    else if (datatype == TULONG)
-    {
-      ffppruj(fptr, group, firstelem, nelem, (unsigned long *) array, status);
-    }
-    else if (datatype == TLONG)
-    {
-      ffpprj(fptr, group, firstelem, nelem, (long *) array, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-      ffpprjj(fptr, group, firstelem, nelem, (LONGLONG *) array, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      ffppre(fptr, group, firstelem, nelem, (float *) array, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-      ffpprd(fptr, group, firstelem, nelem, (double *) array, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppn(  fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  datatype,   /* I - datatype of the value                   */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            void  *array,    /* I - array of values that are written        */
-            void  *nulval,   /* I - pointer to the null value               */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array.  The datatype of the
-  input array is defined by the 2nd argument. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-
-*/
-{
-    long group = 1;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (nulval == NULL)  /* null value not defined? */
-    {
-        ffppr(fptr, datatype, firstelem, nelem, array, status);
-        return(*status);
-    }
-
-    if (datatype == TBYTE)
-    {
-      ffppnb(fptr, group, firstelem, nelem, (unsigned char *) array, 
-             *(unsigned char *) nulval, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-      ffppnsb(fptr, group, firstelem, nelem, (signed char *) array, 
-             *(signed char *) nulval, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-      ffppnui(fptr, group, firstelem, nelem, (unsigned short *) array,
-              *(unsigned short *) nulval,status);
-    }
-    else if (datatype == TSHORT)
-    {
-      ffppni(fptr, group, firstelem, nelem, (short *) array,
-             *(short *) nulval, status);
-    }
-    else if (datatype == TUINT)
-    {
-      ffppnuk(fptr, group, firstelem, nelem, (unsigned int *) array,
-             *(unsigned int *) nulval, status);
-    }
-    else if (datatype == TINT)
-    {
-      ffppnk(fptr, group, firstelem, nelem, (int *) array,
-             *(int *) nulval, status);
-    }
-    else if (datatype == TULONG)
-    {
-      ffppnuj(fptr, group, firstelem, nelem, (unsigned long *) array,
-              *(unsigned long *) nulval,status);
-    }
-    else if (datatype == TLONG)
-    {
-      ffppnj(fptr, group, firstelem, nelem, (long *) array,
-             *(long *) nulval, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-      ffppnjj(fptr, group, firstelem, nelem, (LONGLONG *) array,
-             *(LONGLONG *) nulval, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      ffppne(fptr, group, firstelem, nelem, (float *) array,
-             *(float *) nulval, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-      ffppnd(fptr, group, firstelem, nelem, (double *) array,
-             *(double *) nulval, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpss(  fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  datatype,    /* I - datatype of the value                   */
-            long *blc,        /* I - 'bottom left corner' of the subsection  */
-            long *trc ,       /* I - 'top right corner' of the subsection    */
-            void *array,      /* I - array of values that are written        */
-            int  *status)     /* IO - error status                           */
-/*
-  Write a section of values to the primary array. The datatype of the
-  input array is defined by the 2nd argument.  Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-
-  This routine supports writing to large images with
-  more than 2**31 pixels.
-*/
-{
-    int naxis;
-    long naxes[9];
-
-    if (*status > 0)   /* inherit input status value if > 0 */
-        return(*status);
-
-    /* get the size of the image */
-    ffgidm(fptr, &naxis, status);
-    ffgisz(fptr, 9, naxes, status);
-
-    if (datatype == TBYTE)
-    {
-        ffpssb(fptr, 1, naxis, naxes, blc, trc,
-               (unsigned char *) array, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-        ffpsssb(fptr, 1, naxis, naxes, blc, trc,
-               (signed char *) array, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-        ffpssui(fptr, 1, naxis, naxes, blc, trc,
-               (unsigned short *) array, status);
-    }
-    else if (datatype == TSHORT)
-    {
-        ffpssi(fptr, 1, naxis, naxes, blc, trc,
-               (short *) array, status);
-    }
-    else if (datatype == TUINT)
-    {
-        ffpssuk(fptr, 1, naxis, naxes, blc, trc,
-               (unsigned int *) array, status);
-    }
-    else if (datatype == TINT)
-    {
-        ffpssk(fptr, 1, naxis, naxes, blc, trc,
-               (int *) array, status);
-    }
-    else if (datatype == TULONG)
-    {
-        ffpssuj(fptr, 1, naxis, naxes, blc, trc,
-               (unsigned long *) array, status);
-    }
-    else if (datatype == TLONG)
-    {
-        ffpssj(fptr, 1, naxis, naxes, blc, trc,
-               (long *) array, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-        ffpssjj(fptr, 1, naxis, naxes, blc, trc,
-               (LONGLONG *) array, status);
-    }    else if (datatype == TFLOAT)
-    {
-        ffpsse(fptr, 1, naxis, naxes, blc, trc,
-               (float *) array, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-        ffpssd(fptr, 1, naxis, naxes, blc, trc,
-               (double *) array, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcl(  fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  datatype,   /* I - datatype of the value                   */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of elements to write             */
-            void  *array,    /* I - array of values that are written        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a table column.  The datatype of the
-  input array is defined by the 2nd argument. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS column is not the same as the array being written).
-
-*/
-{
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (datatype == TBIT)
-    {
-      ffpclx(fptr, colnum, firstrow, (long) firstelem, (long) nelem, (char *) array, 
-             status);
-    }
-    else if (datatype == TBYTE)
-    {
-      ffpclb(fptr, colnum, firstrow, firstelem, nelem, (unsigned char *) array,
-             status);
-    }
-    else if (datatype == TSBYTE)
-    {
-      ffpclsb(fptr, colnum, firstrow, firstelem, nelem, (signed char *) array,
-             status);
-    }
-    else if (datatype == TUSHORT)
-    {
-      ffpclui(fptr, colnum, firstrow, firstelem, nelem, 
-             (unsigned short *) array, status);
-    }
-    else if (datatype == TSHORT)
-    {
-      ffpcli(fptr, colnum, firstrow, firstelem, nelem, (short *) array,
-             status);
-    }
-    else if (datatype == TUINT)
-    {
-      ffpcluk(fptr, colnum, firstrow, firstelem, nelem, (unsigned int *) array,
-               status);
-    }
-    else if (datatype == TINT)
-    {
-      ffpclk(fptr, colnum, firstrow, firstelem, nelem, (int *) array,
-               status);
-    }
-    else if (datatype == TULONG)
-    {
-      ffpcluj(fptr, colnum, firstrow, firstelem, nelem, (unsigned long *) array,
-              status);
-    }
-    else if (datatype == TLONG)
-    {
-      ffpclj(fptr, colnum, firstrow, firstelem, nelem, (long *) array,
-             status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-      ffpcljj(fptr, colnum, firstrow, firstelem, nelem, (LONGLONG *) array,
-             status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      ffpcle(fptr, colnum, firstrow, firstelem, nelem, (float *) array,
-             status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-      ffpcld(fptr, colnum, firstrow, firstelem, nelem, (double *) array,
-             status);
-    }
-    else if (datatype == TCOMPLEX)
-    {
-      ffpcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
-             (float *) array, status);
-    }
-    else if (datatype == TDBLCOMPLEX)
-    {
-      ffpcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
-             (double *) array, status);
-    }
-    else if (datatype == TLOGICAL)
-    {
-      ffpcll(fptr, colnum, firstrow, firstelem, nelem, (char *) array,
-             status);
-    }
-    else if (datatype == TSTRING)
-    {
-      ffpcls(fptr, colnum, firstrow, firstelem, nelem, (char **) array,
-             status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcn(  fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  datatype,   /* I - datatype of the value                   */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of elements to write             */
-            void  *array,    /* I - array of values that are written        */
-            void  *nulval,   /* I - pointer to the null value               */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a table column.  The datatype of the
-  input array is defined by the 2nd argument. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS column is not the same as the array being written).
-
-*/
-{
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (nulval == NULL)  /* null value not defined? */
-    {
-        ffpcl(fptr, datatype, colnum, firstrow, firstelem, nelem, array,
-              status);
-        return(*status);
-    }
-
-    if (datatype == TBYTE)
-    {
-      ffpcnb(fptr, colnum, firstrow, firstelem, nelem, (unsigned char *) array,
-            *(unsigned char *) nulval, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-      ffpcnsb(fptr, colnum, firstrow, firstelem, nelem, (signed char *) array,
-            *(signed char *) nulval, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-     ffpcnui(fptr, colnum, firstrow, firstelem, nelem, (unsigned short *) array,
-             *(unsigned short *) nulval, status);
-    }
-    else if (datatype == TSHORT)
-    {
-      ffpcni(fptr, colnum, firstrow, firstelem, nelem, (short *) array,
-             *(unsigned short *) nulval, status);
-    }
-    else if (datatype == TUINT)
-    {
-      ffpcnuk(fptr, colnum, firstrow, firstelem, nelem, (unsigned int *) array,
-             *(unsigned int *) nulval, status);
-    }
-    else if (datatype == TINT)
-    {
-      ffpcnk(fptr, colnum, firstrow, firstelem, nelem, (int *) array,
-             *(int *) nulval, status);
-    }
-    else if (datatype == TULONG)
-    {
-      ffpcnuj(fptr, colnum, firstrow, firstelem, nelem, (unsigned long *) array,
-              *(unsigned long *) nulval, status);
-    }
-    else if (datatype == TLONG)
-    {
-      ffpcnj(fptr, colnum, firstrow, firstelem, nelem, (long *) array,
-             *(long *) nulval, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-      ffpcnjj(fptr, colnum, firstrow, firstelem, nelem, (LONGLONG *) array,
-             *(LONGLONG *) nulval, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-      ffpcne(fptr, colnum, firstrow, firstelem, nelem, (float *) array,
-             *(float *) nulval, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-      ffpcnd(fptr, colnum, firstrow, firstelem, nelem, (double *) array,
-             *(double *) nulval, status);
-    }
-    else if (datatype == TCOMPLEX)
-    {
-      ffpcne(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
-             (float *) array, *(float *) nulval, status);
-    }
-    else if (datatype == TDBLCOMPLEX)
-    {
-      ffpcnd(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
-             (double *) array, *(double *) nulval, status);
-    }
-    else if (datatype == TLOGICAL)
-    {
-      ffpcnl(fptr, colnum, firstrow, firstelem, nelem, (char *) array,
-             *(char *) nulval, status);
-    }
-    else if (datatype == TSTRING)
-    {
-      ffpcns(fptr, colnum, firstrow, firstelem, nelem, (char **) array,
-             (char *) nulval, status);
-    }
-    else
-      *status = BAD_DATATYPE;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_iter_set_by_name(iteratorCol *col, /* I - iterator col structure */
-           fitsfile *fptr,  /* I - FITS file pointer                      */
-           char *colname,   /* I - column name                            */
-           int datatype,    /* I - column datatype                        */
-           int iotype)      /* I - InputCol, InputOutputCol, or OutputCol */
-/*
-  set all the parameters for an iterator column, by column name
-*/
-{
-    col->fptr = fptr;
-    strcpy(col->colname, colname);
-    col->colnum = 0;  /* set column number undefined since name is given */
-    col->datatype = datatype;
-    col->iotype = iotype;
-    return(0);
-}
-/*--------------------------------------------------------------------------*/
-int fits_iter_set_by_num(iteratorCol *col, /* I - iterator column structure */
-           fitsfile *fptr,  /* I - FITS file pointer                      */
-           int colnum,      /* I - column number                          */
-           int datatype,    /* I - column datatype                        */
-           int iotype)      /* I - InputCol, InputOutputCol, or OutputCol */
-/*
-  set all the parameters for an iterator column, by column number
-*/
-{
-    col->fptr = fptr;
-    col->colnum = colnum; 
-    col->datatype = datatype;
-    col->iotype = iotype;
-    return(0);
-}
-/*--------------------------------------------------------------------------*/
-int fits_iter_set_file(iteratorCol *col, /* I - iterator column structure   */
-           fitsfile *fptr)   /* I - FITS file pointer                      */
-/*
-  set iterator column parameter
-*/
-{
-    col->fptr = fptr;
-    return(0);
-}
-/*--------------------------------------------------------------------------*/
-int fits_iter_set_colname(iteratorCol *col, /* I - iterator col structure  */
-           char *colname)    /* I - column name                            */
-/*
-  set iterator column parameter
-*/
-{
-    strcpy(col->colname, colname);
-    col->colnum = 0;  /* set column number undefined since name is given */
-    return(0);
-}
-/*--------------------------------------------------------------------------*/
-int fits_iter_set_colnum(iteratorCol *col, /* I - iterator column structure */
-           int colnum)       /* I - column number                          */
-/*
-  set iterator column parameter
-*/
-{
-    col->colnum = colnum; 
-    return(0);
-}
-/*--------------------------------------------------------------------------*/
-int fits_iter_set_datatype(iteratorCol *col, /* I - iterator col structure */
-           int datatype)    /* I - column datatype                        */
-/*
-  set iterator column parameter
-*/
-{
-    col->datatype = datatype;
-    return(0);
-}
-/*--------------------------------------------------------------------------*/
-int fits_iter_set_iotype(iteratorCol *col, /* I - iterator column structure */
-           int iotype)       /* I - InputCol, InputOutputCol, or OutputCol */
-/*
-  set iterator column parameter
-*/
-{
-    col->iotype = iotype;
-    return(0);
-}
-/*--------------------------------------------------------------------------*/
-fitsfile * fits_iter_get_file(iteratorCol *col) /* I -iterator col structure */
-/*
-  get iterator column parameter
-*/
-{
-     return(col->fptr);
-}
-/*--------------------------------------------------------------------------*/
-char * fits_iter_get_colname(iteratorCol *col) /* I -iterator col structure */
-/*
-  get iterator column parameter
-*/
-{
-    return(col->colname);
-}
-/*--------------------------------------------------------------------------*/
-int fits_iter_get_colnum(iteratorCol *col) /* I - iterator column structure */
-/*
-  get iterator column parameter
-*/
-{
-    return(col->colnum);
-}
-/*--------------------------------------------------------------------------*/
-int fits_iter_get_datatype(iteratorCol *col) /* I - iterator col structure */
-/*
-  get iterator column parameter
-*/
-{
-    return(col->datatype);
-}
-/*--------------------------------------------------------------------------*/
-int fits_iter_get_iotype(iteratorCol *col) /* I - iterator column structure */
-/*
-  get iterator column parameter
-*/
-{
-     return(col->iotype);
-}
-/*--------------------------------------------------------------------------*/
-void * fits_iter_get_array(iteratorCol *col) /* I - iterator col structure */
-/*
-  get iterator column parameter
-*/
-{
-     return(col->array);
-}
-/*--------------------------------------------------------------------------*/
-long fits_iter_get_tlmin(iteratorCol *col) /* I - iterator column structure */
-/*
-  get iterator column parameter
-*/
-{
-     return(col->tlmin);
-}
-/*--------------------------------------------------------------------------*/
-long fits_iter_get_tlmax(iteratorCol *col) /* I - iterator column structure */
-/*
-  get iterator column parameter
-*/
-{
-     return(col->tlmax);
-}
-/*--------------------------------------------------------------------------*/
-long fits_iter_get_repeat(iteratorCol *col) /* I - iterator col structure */
-/*
-  get iterator column parameter
-*/
-{
-     return(col->repeat);
-}
-/*--------------------------------------------------------------------------*/
-char * fits_iter_get_tunit(iteratorCol *col) /* I - iterator col structure */
-/*
-  get iterator column parameter
-*/
-{
-    return(col->tunit);
-}
-/*--------------------------------------------------------------------------*/
-char * fits_iter_get_tdisp(iteratorCol *col) /* I -iterator col structure   */
-/*
-  get iterator column parameter
-*/
-{
-    return(col->tdisp);
-}
-/*--------------------------------------------------------------------------*/
-int ffiter(int n_cols,
-           iteratorCol *cols,
-           long offset,
-           long n_per_loop,
-           int (*work_fn)(long total_n,
-                          long offset,
-                          long first_n,
-                          long n_values,
-                          int n_cols,
-                          iteratorCol *cols,
-                          void *userPointer),
-           void *userPointer,
-           int *status)
-/*
-   The iterator function.  This function will pass the specified
-   columns from a FITS table or pixels from a FITS image to the 
-   user-supplied function.  Depending on the size of the table
-   or image, only a subset of the rows or pixels may be passed to the
-   function on each call, in which case the function will be called
-   multiple times until all the rows or pixels have been processed.
-*/
-{
-    typedef struct  /* structure to store the column null value */
-    {  
-        int      nullsize;    /* length of the null value, in bytes */
-        union {   /*  default null value for the column */
-            char   *stringnull;
-            unsigned char   charnull;
-            signed char scharnull;
-            int    intnull;
-            short  shortnull;
-            long   longnull;
-            unsigned int   uintnull;
-            unsigned short ushortnull;
-            unsigned long  ulongnull;
-            float  floatnull;
-            double doublenull;
-	    LONGLONG longlongnull;
-        } null;
-    } colNulls;
-
-    void *dataptr, *defaultnull;
-    colNulls *col;
-    int ii, jj, tstatus, naxis, bitpix;
-    int typecode, hdutype, jtype, type, anynul, nfiles, nbytes;
-    long totaln, nleft, frow, felement, n_optimum, i_optimum, ntodo;
-    long rept, rowrept, width, tnull, naxes[9] = {1,1,1,1,1,1,1,1,1}, groups;
-    double zeros = 0.;
-    char message[FLEN_ERRMSG], keyname[FLEN_KEYWORD], nullstr[FLEN_VALUE];
-    char **stringptr, *nullptr, *cptr;
-
-    if (*status > 0)
-        return(*status);
-
-    if (n_cols  < 0 || n_cols > 999 )
-    {
-        ffpmsg("Illegal number of columms (ffiter)");
-        return(*status = BAD_COL_NUM);  /* negative number of columns */
-    }
-
-    /*------------------------------------------------------------*/
-    /* Make sure column numbers and datatypes are in legal range  */
-    /* and column numbers and datatypes are legal.                */ 
-    /* Also fill in other parameters in the column structure.     */
-    /*------------------------------------------------------------*/
-
-    ffghdt(cols[0].fptr, &hdutype, status);  /* type of first HDU */
-
-    for (jj = 0; jj < n_cols; jj++)
-    {
-        /* check that output datatype code value is legal */
-        type = cols[jj].datatype;  
-
-        /* Allow variable length arrays for InputCol and InputOutputCol columns,
-	   but not for OutputCol columns.  Variable length arrays have a
-	   negative type code value. */
-
-        if ((cols[jj].iotype != OutputCol) && (type<0)) {
-            type*=-1;
-        }
-
-        if (type != 0      && type != TBYTE  &&
-            type != TSBYTE && type != TLOGICAL && type != TSTRING &&
-            type != TSHORT && type != TINT     && type != TLONG && 
-            type != TFLOAT && type != TDOUBLE  && type != TCOMPLEX &&
-            type != TULONG && type != TUSHORT  && type != TDBLCOMPLEX &&
-	    type != TLONGLONG )
-        {
-	    if (type < 0) {
-	      sprintf(message,
-              "Variable length array not allowed for output column number %d (ffiter)",
-                    jj + 1);
-	    } else {
-            sprintf(message,
-                   "Illegal datatype for column number %d: %d  (ffiter)",
-                    jj + 1, cols[jj].datatype);
-	    }
-	    
-            ffpmsg(message);
-            return(*status = BAD_DATATYPE);
-        }
-
-        /* initialize TLMINn, TLMAXn, column name, and display format */
-        cols[jj].tlmin = 0;
-        cols[jj].tlmax = 0;
-        cols[jj].tunit[0] = '\0';
-        cols[jj].tdisp[0] = '\0';
-
-        ffghdt(cols[jj].fptr, &jtype, status);  /* get HDU type */
-
-        if (hdutype == IMAGE_HDU) /* operating on FITS images */
-        {
-            if (jtype != IMAGE_HDU)
-            {
-                sprintf(message,
-                "File %d not positioned to an image extension (ffiter)",
-                    jj + 1);
-                return(*status = NOT_IMAGE);
-            }
-
-            /* since this is an image, set a dummy column number = 0 */
-            cols[jj].colnum = 0;
-            strcpy(cols[jj].colname, "IMAGE");  /* dummy name for images */
-
-            tstatus = 0;
-            ffgkys(cols[jj].fptr, "BUNIT", cols[jj].tunit, 0, &tstatus);
-        }
-        else  /* operating on FITS tables */
-        {
-            if (jtype == IMAGE_HDU)
-            {
-                sprintf(message,
-                "File %d not positioned to a table extension (ffiter)",
-                    jj + 1);
-                return(*status = NOT_TABLE);
-            }
-
-            if (cols[jj].colnum < 1)
-            {
-                /* find the column number for the named column */
-                if (ffgcno(cols[jj].fptr, CASEINSEN, cols[jj].colname,
-                           &cols[jj].colnum, status) )
-                {
-                    sprintf(message,
-                      "Column '%s' not found for column number %d  (ffiter)",
-                       cols[jj].colname, jj + 1);
-                    ffpmsg(message);
-                    return(*status);
-                }
-            }
-
-            /* check that the column number is valid */
-            if (cols[jj].colnum < 1 || 
-                cols[jj].colnum > ((cols[jj].fptr)->Fptr)->tfield)
-            {
-                sprintf(message,
-                  "Column %d has illegal table position number: %d  (ffiter)",
-                    jj + 1, cols[jj].colnum);
-                ffpmsg(message);
-                return(*status = BAD_COL_NUM);
-            }
-
-            /* look for column description keywords and update structure */
-            tstatus = 0;
-            ffkeyn("TLMIN", cols[jj].colnum, keyname, &tstatus);
-            ffgkyj(cols[jj].fptr, keyname, &cols[jj].tlmin, 0, &tstatus);
-
-            tstatus = 0;
-            ffkeyn("TLMAX", cols[jj].colnum, keyname, &tstatus);
-            ffgkyj(cols[jj].fptr, keyname, &cols[jj].tlmax, 0, &tstatus);
-
-            tstatus = 0;
-            ffkeyn("TTYPE", cols[jj].colnum, keyname, &tstatus);
-            ffgkys(cols[jj].fptr, keyname, cols[jj].colname, 0, &tstatus);
-            if (tstatus)
-                cols[jj].colname[0] = '\0';
-
-            tstatus = 0;
-            ffkeyn("TUNIT", cols[jj].colnum, keyname, &tstatus);
-            ffgkys(cols[jj].fptr, keyname, cols[jj].tunit, 0, &tstatus);
-
-            tstatus = 0;
-            ffkeyn("TDISP", cols[jj].colnum, keyname, &tstatus);
-            ffgkys(cols[jj].fptr, keyname, cols[jj].tdisp, 0, &tstatus);
-        }
-    }  /* end of loop over all columns */
-
-    /*-----------------------------------------------------------------*/
-    /* use the first file to set the total number of values to process */
-    /*-----------------------------------------------------------------*/
-
-    offset = maxvalue(offset, 0L);  /* make sure offset is legal */
-
-    if (hdutype == IMAGE_HDU)   /* get total number of pixels in the image */
-    {
-      fits_get_img_dim(cols[0].fptr, &naxis, status);
-      fits_get_img_size(cols[0].fptr, 9, naxes, status);
-
-      tstatus = 0;
-      ffgkyj(cols[0].fptr, "GROUPS", &groups, NULL, &tstatus);
-      if (!tstatus && groups && (naxis > 1) && (naxes[0] == 0) )
-      {
-         /* this is a random groups file, with NAXIS1 = 0 */
-         /* Use GCOUNT, the number of groups, as the first multiplier  */
-         /* to calculate the total number of pixels in all the groups. */
-         ffgkyj(cols[0].fptr, "GCOUNT", &totaln, NULL, status);
-
-      }  else {
-         totaln = naxes[0];
-      }
-
-      for (ii = 1; ii < naxis; ii++)
-          totaln *= naxes[ii];
-
-      frow = 1;
-      felement = 1 + offset;
-    }
-    else   /* get total number or rows in the table */
-    {
-      ffgkyj(cols[0].fptr, "NAXIS2", &totaln, 0, status);
-      frow = 1 + offset;
-      felement = 1;
-    }
-
-    /*  adjust total by the input starting offset value */
-    totaln -= offset;
-    totaln = maxvalue(totaln, 0L);   /* don't allow negative number */
-
-    /*------------------------------------------------------------------*/
-    /* Determine number of values to pass to work function on each loop */
-    /*------------------------------------------------------------------*/
-
-    if (n_per_loop == 0)
-    {
-        /* Determine optimum number of values for each iteration.    */
-        /* Look at all the fitsfile pointers to determine the number */
-        /* of unique files.                                          */
-
-        nfiles = 1;
-        ffgrsz(cols[0].fptr, &n_optimum, status);
-
-        for (jj = 1; jj < n_cols; jj++)
-        {
-            for (ii = 0; ii < jj; ii++)
-            {
-                if (cols[ii].fptr == cols[jj].fptr)
-                   break;
-            }
-
-            if (ii == jj)  /* this is a new file */
-            {
-                nfiles++;
-                ffgrsz(cols[jj].fptr, &i_optimum, status);
-                n_optimum = minvalue(n_optimum, i_optimum);
-            }
-        }
-
-        /* divid n_optimum by the number of files that will be processed */
-        n_optimum = n_optimum / nfiles;
-        n_optimum = maxvalue(n_optimum, 1);
-    }
-    else if (n_per_loop < 0)  /* must pass all the values at one time */
-    {
-        n_optimum = totaln;
-    }
-    else /* calling routine specified how many values to pass at a time */
-    {
-        n_optimum = minvalue(n_per_loop, totaln);
-    }
-
-    /*--------------------------------------*/
-    /* allocate work arrays for each column */
-    /* and determine the null pixel value   */
-    /*--------------------------------------*/
-
-    col = calloc(n_cols, sizeof(colNulls) ); /* memory for the null values */
-    if (!col)
-    {
-        ffpmsg("ffiter failed to allocate memory for null values");
-        *status = MEMORY_ALLOCATION;  /* memory allocation failed */
-        return(*status);
-    }
-
-    for (jj = 0; jj < n_cols; jj++)
-    {
-        /* get image or column datatype and vector length */
-        if (hdutype == IMAGE_HDU)   /* get total number of pixels in the image */
-        {
-           fits_get_img_type(cols[jj].fptr, &bitpix, status);
-           switch(bitpix) {
-             case BYTE_IMG:
-                 typecode = TBYTE;
-                 break;
-             case SHORT_IMG:
-                 typecode = TSHORT;
-                 break;
-             case LONG_IMG:
-                 typecode = TLONG;
-                 break;
-             case FLOAT_IMG:
-                 typecode = TFLOAT;
-                 break;
-             case DOUBLE_IMG:
-                 typecode = TDOUBLE;
-                 break;
-             case LONGLONG_IMG:
-                 typecode = TLONGLONG;
-                 break;
-            }
-        }
-        else
-        {
-            if (ffgtcl(cols[jj].fptr, cols[jj].colnum, &typecode, &rept,
-                  &width, status) > 0)
-                goto cleanup;
-		
-	    if (typecode < 0) {  /* if any variable length arrays, then the */ 
-	        n_optimum = 1;   /* must process the table 1 row at a time */
-		
-              /* Allow variable length arrays for InputCol and InputOutputCol columns,
-	       but not for OutputCol columns.  Variable length arrays have a
-	       negative type code value. */
-
-              if (cols[jj].iotype == OutputCol) {
- 	        sprintf(message,
-                "Variable length array not allowed for output column number %d (ffiter)",
-                    jj + 1);
-                ffpmsg(message);
-                return(*status = BAD_DATATYPE);
-              }
-	   }
-        }
-
-        /* special case where sizeof(long) = 8: use TINT instead of TLONG */
-        if (abs(typecode) == TLONG && sizeof(long) == 8 && sizeof(int) == 4) {
-		if(typecode<0) {
-			typecode = -TINT;
-		} else {
-			typecode = TINT;
-		}
-        }
-
-        /* Special case: interprete 'X' column as 'B' */
-        if (abs(typecode) == TBIT)
-        {
-            typecode  = typecode / TBIT * TBYTE;
-            rept = (rept + 7) / 8;
-        }
-
-        if (cols[jj].datatype == 0)    /* output datatype not specified? */
-        {
-            /* special case if sizeof(long) = 8: use TINT instead of TLONG */
-            if (abs(typecode) == TLONG && sizeof(long) == 8 && sizeof(int) == 4)
-                cols[jj].datatype = TINT;
-            else
-                cols[jj].datatype = abs(typecode);
-        }
-
-        /* calc total number of elements to do on each iteration */
-        if (hdutype == IMAGE_HDU || cols[jj].datatype == TSTRING)
-        {
-            ntodo = n_optimum; 
-            cols[jj].repeat = 1;
-
-            /* get the BLANK keyword value, if it exists */
-            if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
-                || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
-            {
-                tstatus = 0;
-                ffgkyj(cols[jj].fptr, "BLANK", &tnull, 0, &tstatus);
-                if (tstatus)
-                {
-                    tnull = 0L;  /* no null values */
-                }
-            }
-        }
-        else
-        {
-	    if (typecode < 0) 
-	    {
-              /* get max size of the variable length vector; dont't trust the value
-	         given by the TFORM keyword  */
-	      rept = 1;
-	      for (ii = 0; ii < totaln; ii++) {
-		ffgdes(cols[jj].fptr, cols[jj].colnum, frow + ii, &rowrept, NULL, status);
-		
-		rept = maxvalue(rept, rowrept);
-	      }
-            }
-	    
-            ntodo = n_optimum * rept;   /* vector columns */
-            cols[jj].repeat = rept;
-
-            /* get the TNULL keyword value, if it exists */
-            if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
-                || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
-            {
-                tstatus = 0;
-                if (hdutype == ASCII_TBL) /* TNULLn value is a string */
-                {
-                    ffkeyn("TNULL", cols[jj].colnum, keyname, &tstatus);
-                    ffgkys(cols[jj].fptr, keyname, nullstr, 0, &tstatus);
-                    if (tstatus)
-                    {
-                        tnull = 0L; /* keyword doesn't exist; no null values */
-                    }
-                    else
-                    {
-                        cptr = nullstr;
-                        while (*cptr == ' ')  /* skip over leading blanks */
-                           cptr++;
-
-                        if (*cptr == '\0')  /* TNULLn is all blanks? */
-                            tnull = LONG_MIN;
-                        else
-                        {                                                
-                            /* attempt to read TNULLn string as an integer */
-                            ffc2ii(nullstr, &tnull, &tstatus);
-
-                            if (tstatus)
-                                tnull = LONG_MIN;  /* choose smallest value */
-                        }                          /* to represent nulls */
-                    }
-                }
-                else  /* Binary table; TNULLn value is an integer */
-                {
-                    ffkeyn("TNULL", cols[jj].colnum, keyname, &tstatus);
-                    ffgkyj(cols[jj].fptr, keyname, &tnull, 0, &tstatus);
-                    if (tstatus)
-                    {
-                        tnull = 0L; /* keyword doesn't exist; no null values */
-                    }
-                    else if (tnull == 0)
-                    {
-                        /* worst possible case: a value of 0 is used to   */
-                        /* represent nulls in the FITS file.  We have to  */
-                        /* use a non-zero null value here (zero is used to */
-                        /* mean there are no null values in the array) so we */
-                        /* will use the smallest possible integer instead. */
-
-                        tnull = LONG_MIN;  /* choose smallest possible value */
-                    }
-                }
-            }
-        }
-
-        /* Note that the data array starts with 2nd element;  */
-        /* 1st element of the array gives the null data value */
-
-        switch (cols[jj].datatype)
-        {
-         case TBYTE:
-          cols[jj].array = calloc(ntodo + 1, sizeof(char));
-          col[jj].nullsize  = sizeof(char);  /* number of bytes per value */
-
-          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
-              || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
-          {
-              tnull = minvalue(tnull, 255);
-              tnull = maxvalue(tnull, 0);
-              col[jj].null.charnull = (unsigned char) tnull;
-          }
-          else
-          {
-              col[jj].null.charnull = (unsigned char) 255; /* use 255 as null */
-          }
-          break;
-
-         case TSBYTE:
-          cols[jj].array = calloc(ntodo + 1, sizeof(char));
-          col[jj].nullsize  = sizeof(char);  /* number of bytes per value */
-
-          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
-              || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
-          {
-              tnull = minvalue(tnull, 127);
-              tnull = maxvalue(tnull, -128);
-              col[jj].null.scharnull = (signed char) tnull;
-          }
-          else
-          {
-              col[jj].null.scharnull = (signed char) -128; /* use -128  null */
-          }
-          break;
-
-         case TSHORT:
-          cols[jj].array = calloc(ntodo + 1, sizeof(short));
-          col[jj].nullsize  = sizeof(short);  /* number of bytes per value */
-
-          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
-              || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
-          {
-              tnull = minvalue(tnull, SHRT_MAX);
-              tnull = maxvalue(tnull, SHRT_MIN);
-              col[jj].null.shortnull = (short) tnull;
-          }
-          else
-          {
-              col[jj].null.shortnull = SHRT_MIN;  /* use minimum as null */
-          }
-          break;
-
-         case TUSHORT:
-          cols[jj].array = calloc(ntodo + 1, sizeof(unsigned short));
-          col[jj].nullsize  = sizeof(unsigned short);  /* bytes per value */
-
-          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
-               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
-          {
-              tnull = minvalue(tnull, (long) USHRT_MAX);
-              tnull = maxvalue(tnull, 0);  /* don't allow negative value */
-              col[jj].null.ushortnull = (unsigned short) tnull;
-          }
-          else
-          {
-              col[jj].null.ushortnull = USHRT_MAX;   /* use maximum null */
-          }
-          break;
-
-         case TINT:
-          cols[jj].array = calloc(sizeof(int), ntodo + 1);
-          col[jj].nullsize  = sizeof(int);  /* number of bytes per value */
-
-          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
-               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
-          {
-              tnull = minvalue(tnull, INT_MAX);
-              tnull = maxvalue(tnull, INT_MIN);
-              col[jj].null.intnull = (int) tnull;
-          }
-          else
-          {
-              col[jj].null.intnull = INT_MIN;  /* use minimum as null */
-          }
-          break;
-
-         case TUINT:
-          cols[jj].array = calloc(ntodo + 1, sizeof(unsigned int));
-          col[jj].nullsize  = sizeof(unsigned int);  /* bytes per value */
-
-          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
-               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
-          {
-              tnull = minvalue(tnull, INT32_MAX);
-              tnull = maxvalue(tnull, 0);
-              col[jj].null.uintnull = (unsigned int) tnull;
-          }
-          else
-          {
-              col[jj].null.uintnull = UINT_MAX;  /* use maximum as null */
-          }
-          break;
-
-         case TLONG:
-          cols[jj].array = calloc(ntodo + 1, sizeof(long));
-          col[jj].nullsize  = sizeof(long);  /* number of bytes per value */
-
-          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
-               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
-          {
-              col[jj].null.longnull = tnull;
-          }
-          else
-          {
-              col[jj].null.longnull = LONG_MIN;   /* use minimum as null */
-          }
-          break;
-
-         case TULONG:
-          cols[jj].array = calloc(ntodo + 1, sizeof(unsigned long));
-          col[jj].nullsize  = sizeof(unsigned long);  /* bytes per value */
-
-          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
-               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
-          {
-              if (tnull < 0)  /* can't use a negative null value */
-                  col[jj].null.ulongnull = LONG_MAX;
-              else
-                  col[jj].null.ulongnull = (unsigned long) tnull;
-          }
-          else
-          {
-              col[jj].null.ulongnull = LONG_MAX;   /* use maximum as null */
-          }
-          break;
-
-         case TFLOAT:
-          cols[jj].array = calloc(ntodo + 1, sizeof(float));
-          col[jj].nullsize  = sizeof(float);  /* number of bytes per value */
-
-          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
-               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
-          {
-              col[jj].null.floatnull = (float) tnull;
-          }
-          else
-          {
-              col[jj].null.floatnull = FLOATNULLVALUE;  /* special value */
-          }
-          break;
-
-         case TCOMPLEX:
-          cols[jj].array = calloc((ntodo * 2) + 1, sizeof(float));
-          col[jj].nullsize  = sizeof(float);  /* number of bytes per value */
-          col[jj].null.floatnull = FLOATNULLVALUE;  /* special value */
-          break;
-
-         case TDOUBLE:
-          cols[jj].array = calloc(ntodo + 1, sizeof(double));
-          col[jj].nullsize  = sizeof(double);  /* number of bytes per value */
-
-          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
-               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
-          {
-              col[jj].null.doublenull = (double) tnull;
-          }
-          else
-          {
-              col[jj].null.doublenull = DOUBLENULLVALUE;  /* special value */
-          }
-          break;
-
-         case TDBLCOMPLEX:
-          cols[jj].array = calloc((ntodo * 2) + 1, sizeof(double));
-          col[jj].nullsize  = sizeof(double);  /* number of bytes per value */
-          col[jj].null.doublenull = DOUBLENULLVALUE;  /* special value */
-          break;
-
-         case TSTRING:
-          /* allocate array of pointers to all the strings  */
-	  if( hdutype==ASCII_TBL ) rept = width;
-          stringptr = calloc((ntodo + 1) , sizeof(stringptr));
-          cols[jj].array = stringptr;
-          col[jj].nullsize  = rept + 1;  /* number of bytes per value */
-
-          if (stringptr)
-          {
-            /* allocate string to store the null string value */
-            col[jj].null.stringnull = calloc(rept + 1, sizeof(char) );
-            col[jj].null.stringnull[1] = 1; /* to make sure string != 0 */
-
-            /* allocate big block for the array of table column strings */
-            stringptr[0] = calloc((ntodo + 1) * (rept + 1), sizeof(char) );
-
-            if (stringptr[0])
-            {
-              for (ii = 1; ii <= ntodo; ii++)
-              {   /* pointer to each string */
-                stringptr[ii] = stringptr[ii - 1] + (rept + 1);
-              }
-
-              /* get the TNULL keyword value, if it exists */
-              tstatus = 0;
-              ffkeyn("TNULL", cols[jj].colnum, keyname, &tstatus);
-              ffgkys(cols[jj].fptr, keyname, nullstr, 0, &tstatus);
-              if (!tstatus)
-                  strncat(col[jj].null.stringnull, nullstr, rept);
-            }
-            else
-            {
-              ffpmsg("ffiter failed to allocate memory arrays");
-              *status = MEMORY_ALLOCATION;  /* memory allocation failed */
-              goto cleanup;
-            }
-          }
-          break;
-
-         case TLOGICAL:
-
-          cols[jj].array = calloc(ntodo + 1, sizeof(char));
-          col[jj].nullsize  = sizeof(char);  /* number of bytes per value */
-
-          /* use value = 2 to flag null values in logical columns */
-          col[jj].null.charnull = 2;
-          break;
-
-         case TLONGLONG:
-          cols[jj].array = calloc(ntodo + 1, sizeof(LONGLONG));
-          col[jj].nullsize  = sizeof(LONGLONG);  /* number of bytes per value */
-
-          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG ||
-	      abs(typecode) == TLONGLONG || abs(typecode) == TINT)
-          {
-              col[jj].null.longlongnull = tnull;
-          }
-          else
-          {
-              col[jj].null.longlongnull = LONGLONG_MIN;   /* use minimum as null */
-          }
-          break;
-
-         default:
-          sprintf(message,
-                  "Column %d datatype currently not supported: %d:  (ffiter)",
-                   jj + 1, cols[jj].datatype);
-          ffpmsg(message);
-          *status = BAD_DATATYPE;
-          goto cleanup;
-
-        }   /* end of switch block */
-
-        /* check that all the arrays were allocated successfully */
-        if (!cols[jj].array)
-        {
-            ffpmsg("ffiter failed to allocate memory arrays");
-            *status = MEMORY_ALLOCATION;  /* memory allocation failed */
-            goto cleanup;
-        }
-    }
-
-    /*--------------------------------------------------*/
-    /* main loop while there are values left to process */
-    /*--------------------------------------------------*/
-
-    nleft = totaln;
-
-    while (nleft)
-    {
-      ntodo = minvalue(nleft, n_optimum); /* no. of values for this loop */
-
-      /*  read input columns from FITS file(s)  */
-      for (jj = 0; jj < n_cols; jj++)
-      {
-        if (cols[jj].iotype != OutputCol)
-        {
-          if (cols[jj].datatype == TSTRING)
-          {
-            stringptr = cols[jj].array;
-            dataptr = stringptr + 1;
-            defaultnull = col[jj].null.stringnull; /* ptr to the null value */
-          }
-          else
-          {
-            dataptr = (char *) cols[jj].array + col[jj].nullsize;
-            defaultnull = &col[jj].null.charnull; /* ptr to the null value */
-          }
-
-          if (hdutype == IMAGE_HDU)   
-          {
-              if (ffgpv(cols[jj].fptr, cols[jj].datatype,
-                    felement, cols[jj].repeat * ntodo, defaultnull,
-                    dataptr,  &anynul, status) > 0)
-              {
-                 break;
-              }
-          }
-          else
-          {
-	      if (ffgtcl(cols[jj].fptr, cols[jj].colnum, &typecode, &rept,&width, status) > 0)
-	          goto cleanup;
-		  
-	      if (typecode<0)
-	      {
-	        /* get size of the variable length vector */
-		ffgdes(cols[jj].fptr, cols[jj].colnum, frow,&cols[jj].repeat, NULL,status);
-	      }
-		
-              if (ffgcv(cols[jj].fptr, cols[jj].datatype, cols[jj].colnum,
-                    frow, felement, cols[jj].repeat * ntodo, defaultnull,
-                    dataptr,  &anynul, status) > 0)
-              {
-                 break;
-              }
-          }
-
-          /* copy the appropriate null value into first array element */
-
-          if (anynul)   /* are there any nulls in the data? */
-          {   
-            if (cols[jj].datatype == TSTRING)
-            {
-              stringptr = cols[jj].array;
-              memcpy(*stringptr, col[jj].null.stringnull, col[jj].nullsize);
-            }
-            else
-            {
-              memcpy(cols[jj].array, defaultnull, col[jj].nullsize);
-            }
-          }
-          else /* no null values so copy zero into first element */
-          {
-            if (cols[jj].datatype == TSTRING)
-            {
-              stringptr = cols[jj].array;
-              memset(*stringptr, 0, col[jj].nullsize);  
-            }
-            else
-            {
-              memset(cols[jj].array, 0, col[jj].nullsize);  
-            }
-          }
-        }
-      }
-
-      if (*status > 0) 
-         break;   /* looks like an error occurred; quit immediately */
-
-      /* call work function */
-
-      if (hdutype == IMAGE_HDU) 
-          *status = work_fn(totaln, offset, felement, ntodo, n_cols, cols,
-                    userPointer);
-      else
-          *status = work_fn(totaln, offset, frow, ntodo, n_cols, cols,
-                    userPointer);
-
-      if (*status > 0 || *status < -1 ) 
-         break;   /* looks like an error occurred; quit immediately */
-
-      /*  write output columns  before quiting if status = -1 */
-      tstatus = 0;
-      for (jj = 0; jj < n_cols; jj++)
-      {
-        if (cols[jj].iotype != InputCol)
-        {
-          if (cols[jj].datatype == TSTRING)
-          {
-            stringptr = cols[jj].array;
-            dataptr = stringptr + 1;
-            nullptr = *stringptr;
-            nbytes = 2;
-          }
-          else
-          {
-            dataptr = (char *) cols[jj].array + col[jj].nullsize;
-            nullptr = (char *) cols[jj].array;
-            nbytes = col[jj].nullsize;
-          }
-
-          if (memcmp(nullptr, &zeros, nbytes) ) 
-          {
-            /* null value flag not zero; must check for and write nulls */
-            if (hdutype == IMAGE_HDU)   
-            {
-                if (ffppn(cols[jj].fptr, cols[jj].datatype, 
-                      felement, cols[jj].repeat * ntodo, dataptr,
-                      nullptr, &tstatus) > 0)
-                break;
-            }
-            else
-            {
-	    	if (ffgtcl(cols[jj].fptr, cols[jj].colnum, &typecode, &rept,&width, status) > 0)
-		    goto cleanup;
-		    
-		if (typecode<0)  /* variable length array colum */
-		{
-		   ffgdes(cols[jj].fptr, cols[jj].colnum, frow,&cols[jj].repeat, NULL,status);
-		}
-
-                if (ffpcn(cols[jj].fptr, cols[jj].datatype, cols[jj].colnum, frow,
-                      felement, cols[jj].repeat * ntodo, dataptr,
-                      nullptr, &tstatus) > 0)
-                break;
-            }
-          }
-          else
-          { 
-            /* no null values; just write the array */
-            if (hdutype == IMAGE_HDU)   
-            {
-                if (ffppr(cols[jj].fptr, cols[jj].datatype,
-                      felement, cols[jj].repeat * ntodo, dataptr,
-                      &tstatus) > 0)
-                break;
-            }
-            else
-            {
-	    	if (ffgtcl(cols[jj].fptr, cols[jj].colnum, &typecode, &rept,&width, status) > 0)
-		    goto cleanup;
-		    
-		if (typecode<0)  /* variable length array column */
-		{
-		   ffgdes(cols[jj].fptr, cols[jj].colnum, frow,&cols[jj].repeat, NULL,status);
-		}
-
-                 if (ffpcl(cols[jj].fptr, cols[jj].datatype, cols[jj].colnum, frow,
-                      felement, cols[jj].repeat * ntodo, dataptr,
-                      &tstatus) > 0)
-                break;
-            }
-          }
-        }
-      }
-
-      if (*status == 0)
-         *status = tstatus;   /* propagate any error status from the writes */
-
-      if (*status) 
-         break;   /* exit on any error */
-
-      nleft -= ntodo;
-
-      if (hdutype == IMAGE_HDU)
-          felement += ntodo;
-      else
-          frow  += ntodo;
-    }
-
-cleanup:
-
-    /*----------------------------------*/
-    /* free work arrays for the columns */
-    /*----------------------------------*/
-
-    for (jj = 0; jj < n_cols; jj++)
-    {
-        if (cols[jj].datatype == TSTRING)
-        {
-            if (cols[jj].array)
-            {
-                stringptr = cols[jj].array;
-                free(*stringptr);     /* free the block of strings */
-                free(col[jj].null.stringnull); /* free the null string */
-            }
-        }
-        if (cols[jj].array)
-            free(cols[jj].array); /* memory for the array of values from the col */
-    }
-    free(col);   /* the structure containing the null values */
-    return(*status);
-}
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcolb.c b/src/external/OpenGR/3rdparty/cfitsio/putcolb.c
deleted file mode 100644
index 278f37814..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcolb.c
+++ /dev/null
@@ -1,1017 +0,0 @@
-/*  This file, putcolb.c, contains routines that write data elements to    */
-/*  a FITS image or table with char (byte) datatype.                       */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffpprb( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            unsigned char *array, /* I - array of values that are written   */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-    unsigned char nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_pixels(fptr, TBYTE, firstelem, nelem,
-            0, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpclb(fptr, 2, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppnb( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            unsigned char *array, /* I - array of values that are written   */
-            unsigned char nulval, /* I - undefined pixel value              */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).  Any array values
-  that are equal to the value of nulval will be replaced with the null
-  pixel value that is appropriate for this column.
-*/
-{
-    long row;
-    unsigned char nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-
-        nullvalue = nulval;  /* set local variable */
-        fits_write_compressed_pixels(fptr, TBYTE, firstelem, nelem,
-            1, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcnb(fptr, 2, row, firstelem, nelem, array, nulval, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp2db(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           unsigned char *array, /* I - array to be written               */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    /* call the 3D writing routine, with the 3rd dimension = 1 */
-
-    ffp3db(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp3db(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  nrows,      /* I - number of rows in each plane of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
-           unsigned char *array, /* I - array to be written               */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 3-D cube of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    long tablerow, ii, jj;
-    LONGLONG nfits, narray;
-    long fpixel[3]= {1,1,1}, lpixel[3];
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-           
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-        lpixel[0] = (long) ncols;
-        lpixel[1] = (long) nrows;
-        lpixel[2] = (long) naxis3;
-       
-        fits_write_compressed_img(fptr, TBYTE, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-      /* all the image pixels are contiguous, so write all at once */
-      ffpclb(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
-      return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to write to */
-    narray = 0;  /* next pixel in input array to be written */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* writing naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffpclb(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
-         return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpssb(fitsfile *fptr,   /* I - FITS file pointer                       */
-           long  group,      /* I - group to write(1 = 1st group)           */
-           long  naxis,      /* I - number of data axes in array            */
-           long  *naxes,     /* I - size of each FITS axis                  */
-           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
-           long  *lpixel,    /* I - last pixel in each axis to write        */
-           unsigned char *array, /* I - array to be written                 */
-           int  *status)     /* IO - error status                           */
-/*
-  Write a subsection of pixels to the primary array or image.
-  A subsection is defined to be any contiguous rectangular
-  array of pixels within the n-dimensional FITS data file.
-  Data conversion and scaling will be performed if necessary 
-  (e.g, if the datatype of the FITS array is not the same as
-  the array being written).
-*/
-{
-    long tablerow;
-    LONGLONG fpix[7], dimen[7], astart, pstart;
-    LONGLONG off2, off3, off4, off5, off6, off7;
-    LONGLONG st10, st20, st30, st40, st50, st60, st70;
-    LONGLONG st1, st2, st3, st4, st5, st6, st7;
-    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_img(fptr, TBYTE, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    if (naxis < 1 || naxis > 7)
-      return(*status = BAD_DIMEN);
-
-    tablerow=maxvalue(1,group);
-
-     /* calculate the size and number of loops to perform in each dimension */
-    for (ii = 0; ii < 7; ii++)
-    {
-      fpix[ii]=1;
-      irange[ii]=1;
-      dimen[ii]=1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {    
-      fpix[ii]=fpixel[ii];
-      irange[ii]=lpixel[ii]-fpixel[ii]+1;
-      dimen[ii]=naxes[ii];
-    }
-
-    i1=irange[0];
-
-    /* compute the pixel offset between each dimension */
-    off2 =     dimen[0];
-    off3 = off2 * dimen[1];
-    off4 = off3 * dimen[2];
-    off5 = off4 * dimen[3];
-    off6 = off5 * dimen[4];
-    off7 = off6 * dimen[5];
-
-    st10 = fpix[0];
-    st20 = (fpix[1] - 1) * off2;
-    st30 = (fpix[2] - 1) * off3;
-    st40 = (fpix[3] - 1) * off4;
-    st50 = (fpix[4] - 1) * off5;
-    st60 = (fpix[5] - 1) * off6;
-    st70 = (fpix[6] - 1) * off7;
-
-    /* store the initial offset in each dimension */
-    st1 = st10;
-    st2 = st20;
-    st3 = st30;
-    st4 = st40;
-    st5 = st50;
-    st6 = st60;
-    st7 = st70;
-
-    astart = 0;
-
-    for (i7 = 0; i7 < irange[6]; i7++)
-    {
-     for (i6 = 0; i6 < irange[5]; i6++)
-     {
-      for (i5 = 0; i5 < irange[4]; i5++)
-      {
-       for (i4 = 0; i4 < irange[3]; i4++)
-       {
-        for (i3 = 0; i3 < irange[2]; i3++)
-        {
-         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
-
-         for (i2 = 0; i2 < irange[1]; i2++)
-         {
-           if (ffpclb(fptr, 2, tablerow, pstart, i1, &array[astart],
-              status) > 0)
-              return(*status);
-
-           astart += i1;
-           pstart += off2;
-         }
-         st2 = st20;
-         st3 = st3+off3;    
-        }
-        st3 = st30;
-        st4 = st4+off4;
-       }
-       st4 = st40;
-       st5 = st5+off5;
-      }
-      st5 = st50;
-      st6 = st6+off6;
-     }
-     st6 = st60;
-     st7 = st7+off7;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpgpb( fitsfile *fptr,   /* I - FITS file pointer                      */
-            long  group,      /* I - group to write(1 = 1st group)          */
-            long  firstelem,  /* I - first vector element to write(1 = 1st) */
-            long  nelem,      /* I - number of values to write              */
-            unsigned char *array, /* I - array of values that are written   */
-            int  *status)     /* IO - error status                          */
-/*
-  Write an array of group parameters to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffpclb(fptr, 1L, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpclb( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            unsigned char *array, /* I - array of values to write           */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table with
-  2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    int tcode, maxelem2, hdutype, writeraw;
-    long twidth, incre;
-    long  ntodo;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
-    double scale, zero;
-    char tform[20], cform[20];
-    char message[FLEN_ERRMSG];
-
-    char snull[20];   /*  the FITS null value  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-    maxelem = maxelem2;
-
-    if (tcode == TSTRING)   
-         ffcfmt(tform, cform);     /* derive C format for writing strings */
-
-    /*
-      if there is no scaling 
-      then we can simply write the raw data bytes into the FITS file if the
-      datatype of the FITS column is the same as the input values.  Otherwise,
-      we must convert the raw values into the scaled and/or machine dependent
-      format in a temporary buffer that has been allocated for this purpose.
-    */
-    if (scale == 1. && zero == 0. && tcode == TBYTE)
-    {
-        writeraw = 1;
-        if (nelem < (LONGLONG)INT32_MAX) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX;
-        }
-     }
-    else
-        writeraw = 0;
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
-    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
-    /*  TZEROn linear scaling parameters into a temporary buffer.          */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-        /* limit the number of pixels to process a one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TBYTE):
-              if (writeraw)
-              {
-                /* write raw input bytes without conversion */
-                ffpi1b(fptr, ntodo, incre, &array[next], status);
-              }
-              else
-              {
-                /* convert the raw data before writing to FITS file */
-                ffi1fi1(&array[next], ntodo, scale, zero,
-                        (unsigned char *) buffer, status);
-                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
-              }
-
-              break;
-
-            case (TLONGLONG):
-
-                ffi1fi8(&array[next], ntodo, scale, zero,
-                        (LONGLONG *) buffer, status);
-                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
-                break;
-
-            case (TSHORT):
- 
-                ffi1fi2(&array[next], ntodo, scale, zero,
-                        (short *) buffer, status);
-                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
-                break;
-
-            case (TLONG):
-
-                ffi1fi4(&array[next], ntodo, scale, zero,
-                        (INT32BIT *) buffer, status);
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
-                break;
-
-            case (TFLOAT):
-
-                ffi1fr4(&array[next], ntodo, scale, zero,
-                        (float *)  buffer, status);
-                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
-                break;
-
-            case (TDOUBLE):
-                ffi1fr8(&array[next], ntodo, scale, zero,
-                        (double *) buffer, status);
-                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
-                break;
-
-            case (TSTRING):  /* numerical column in an ASCII table */
-
-                if (strchr(tform,'A'))
-                {
-                    /* write raw input bytes without conversion        */
-                    /* This case is a hack to let users write a stream */
-                    /* of bytes directly to the 'A' format column      */
-
-                    if (incre == twidth)
-                        ffpbyt(fptr, ntodo, &array[next], status);
-                    else
-                        ffpbytoff(fptr, twidth, ntodo/twidth, incre - twidth, 
-                                &array[next], status);
-                    break;
-                }
-                else if (cform[1] != 's')  /*  "%s" format is a string */
-                {
-                  ffi1fstr(&array[next], ntodo, scale, zero, cform,
-                          twidth, (char *) buffer, status);
-
-                  if (incre == twidth)    /* contiguous bytes */
-                     ffpbyt(fptr, ntodo * twidth, buffer, status);
-                  else
-                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                            status);
-                  break;
-                }
-                /* can't write to string column, so fall thru to default: */
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                       "Cannot write numbers to column %d which has format %s",
-                        colnum,tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-          sprintf(message,
-          "Error writing elements %.0f thru %.0f of input data array (ffpclb).",
-              (double) (next+1), (double) (next+ntodo));
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-      ffpmsg(
-      "Numerical overflow during type conversion while writing FITS data.");
-      *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcnb( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            unsigned char *array,   /* I - array of values to write         */
-            unsigned char nulvalue, /* I - flag for undefined pixels        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels equal to the value of nulvalue will be replaced by the appropriate
-  null value in the output FITS file. 
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
-*/
-{
-    tcolumn *colptr;
-    LONGLONG  ngood = 0, nbad = 0, ii;
-    LONGLONG repeat, first, fstelm, fstrow;
-    int tcode, overflow = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode  = colptr->tdatatype;
-
-    if (tcode > 0)
-       repeat = colptr->trepeat;  /* repeat count for this column */
-    else
-       repeat = firstelem -1 + nelem;  /* variable length arrays */
-
-    /* if variable length array, first write the whole input vector, 
-       then go back and fill in the nulls */
-    if (tcode < 0) {
-      if (ffpclb(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
-        if (*status == NUM_OVERFLOW) 
-	{
-	  /* ignore overflows, which are possibly the null pixel values */
-	  /*  overflow = 1;   */
-	  *status = 0;
-	} else { 
-          return(*status);
-	}
-      }
-    }
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (array[ii] != nulvalue)  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-
-            nbad=0;
-         }
-
-         ngood = ngood + 1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (tcode > 0) {  /* variable length arrays have already been written */
-              if (ffpclb(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0) {
-		if (*status == NUM_OVERFLOW) 
-		{
-		  overflow = 1;
-		  *status = 0;
-		} else { 
-                  return(*status);
-		}
-	      }
-	    }
-            ngood=0;
-         }
-
-         nbad = nbad + 1;  /* the consecutive number of bad pixels */
-      }
-    }
-    
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      if (tcode > 0) {  /* variable length arrays have already been written */
-        ffpclb(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-      }
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-
-    if (*status <= 0) {
-      if (overflow) {
-        *status = NUM_OVERFLOW;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpextn( fitsfile *fptr,        /* I - FITS file pointer                        */
-            LONGLONG  offset,      /* I - byte offset from start of extension data */
-            LONGLONG  nelem,       /* I - number of elements to write              */
-            void *buffer,          /* I - stream of bytes to write                 */
-            int  *status)          /* IO - error status                            */
-/*
-  Write a stream of bytes to the current FITS HDU.  This primative routine is mainly
-  for writing non-standard "conforming" extensions and should not be used
-  for standard IMAGE, TABLE or BINTABLE extensions.
-*/
-{
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    /* rescan header if data structure is undefined */
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-        if ( ffrdef(fptr, status) > 0)               
-            return(*status);
-
-    /* move to write position */
-    ffmbyt(fptr, (fptr->Fptr)->datastart+ offset, IGNORE_EOF, status);
-    
-    /* write the buffer */
-    ffpbyt(fptr, nelem, buffer, status); 
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi1fi1(unsigned char *input,  /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            unsigned char *output, /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        memcpy(output, input, ntodo); /* just copy input to output */
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = ( ((double) input[ii]) - zero) / scale;
-
-            if (dvalue < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (dvalue > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) (dvalue + .5);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi1fi2(unsigned char *input,  /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            short *output,         /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = input[ii];   /* just copy input to output */
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (((double) input[ii]) - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (short) (dvalue + .5);
-                else
-                    output[ii] = (short) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi1fi4(unsigned char *input,  /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            INT32BIT *output,      /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (INT32BIT) input[ii];   /* copy input to output */
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (((double) input[ii]) - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (INT32BIT) (dvalue + .5);
-                else
-                    output[ii] = (INT32BIT) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi1fi8(unsigned char *input, /* I - array of values to be converted  */
-            long ntodo,           /* I - number of elements in the array  */
-            double scale,         /* I - FITS TSCALn or BSCALE value      */
-            double zero,          /* I - FITS TZEROn or BZERO  value      */
-            LONGLONG *output,     /* O - output array of converted values */
-            int *status)          /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (dvalue > DLONGLONG_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (LONGLONG) (dvalue + .5);
-                else
-                    output[ii] = (LONGLONG) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi1fr4(unsigned char *input,  /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            float *output,         /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (float) (( ( (double) input[ii] ) - zero) / scale);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi1fr8(unsigned char *input,  /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            double *output,        /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = ( ( (double) input[ii] ) - zero) / scale;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi1fstr(unsigned char *input, /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            char *cform,       /* I - format for output string values  */
-            long twidth,       /* I - width of each field, in chars    */
-            char *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-    char *cptr;
-
-    cptr = output;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-           sprintf(output, cform, (double) input[ii]);
-           output += twidth;
-
-           if (*output)  /* if this char != \0, then overflow occurred */
-              *status = OVERFLOW_ERR;
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-          dvalue = ((double) input[ii] - zero) / scale;
-          sprintf(output, cform, dvalue);
-          output += twidth;
-
-          if (*output)  /* if this char != \0, then overflow occurred */
-            *status = OVERFLOW_ERR;
-        }
-    }
-
-    /* replace any commas with periods (e.g., in French locale) */
-    while ((cptr = strchr(cptr, ','))) *cptr = '.';
-    
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcold.c b/src/external/OpenGR/3rdparty/cfitsio/putcold.c
deleted file mode 100644
index 9244d09c6..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcold.c
+++ /dev/null
@@ -1,1064 +0,0 @@
-/*  This file, putcold.c, contains routines that write data elements to    */
-/*  a FITS image or table, with double datatype.                           */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffpprd( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            double *array,   /* I - array of values that are written        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-    double nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_pixels(fptr, TDOUBLE, firstelem, nelem,
-            0, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcld(fptr, 2, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppnd( fitsfile *fptr,   /* I - FITS file pointer                       */
-            long  group,      /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem,  /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,      /* I - number of values to write               */
-            double *array,    /* I - array of values that are written        */
-            double nulval,    /* I - undefined pixel value                   */
-            int  *status)     /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).  Any array values
-  that are equal to the value of nulval will be replaced with the null
-  pixel value that is appropriate for this column.
-*/
-{
-    long row;
-    double nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        nullvalue = nulval;  /* set local variable */
-        fits_write_compressed_pixels(fptr, TDOUBLE, firstelem, nelem,
-            1, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcnd(fptr, 2, row, firstelem, nelem, array, nulval, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp2dd(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           double *array,    /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    /* call the 3D writing routine, with the 3rd dimension = 1 */
-
-    ffp3dd(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp3dd(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  nrows,      /* I - number of rows in each plane of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
-           double *array,    /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 3-D cube of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    long tablerow, ii, jj;
-    long fpixel[3]= {1,1,1}, lpixel[3];
-    LONGLONG nfits, narray;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-        lpixel[0] = (long) ncols;
-        lpixel[1] = (long) nrows;
-        lpixel[2] = (long) naxis3;
-
-        fits_write_compressed_img(fptr, TDOUBLE, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-      /* all the image pixels are contiguous, so write all at once */
-      ffpcld(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
-      return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to write to */
-    narray = 0;  /* next pixel in input array to be written */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* writing naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffpcld(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
-         return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpssd(fitsfile *fptr,   /* I - FITS file pointer                       */
-           long  group,      /* I - group to write(1 = 1st group)           */
-           long  naxis,      /* I - number of data axes in array            */
-           long  *naxes,     /* I - size of each FITS axis                  */
-           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
-           long  *lpixel,    /* I - last pixel in each axis to write        */
-           double *array,    /* I - array to be written                     */
-           int  *status)     /* IO - error status                           */
-/*
-  Write a subsection of pixels to the primary array or image.
-  A subsection is defined to be any contiguous rectangular
-  array of pixels within the n-dimensional FITS data file.
-  Data conversion and scaling will be performed if necessary 
-  (e.g, if the datatype of the FITS array is not the same as
-  the array being written).
-*/
-{
-    long tablerow;
-    LONGLONG fpix[7], dimen[7], astart, pstart;
-    LONGLONG off2, off3, off4, off5, off6, off7;
-    LONGLONG st10, st20, st30, st40, st50, st60, st70;
-    LONGLONG st1, st2, st3, st4, st5, st6, st7;
-    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_img(fptr, TDOUBLE, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    if (naxis < 1 || naxis > 7)
-      return(*status = BAD_DIMEN);
-
-    tablerow=maxvalue(1,group);
-
-     /* calculate the size and number of loops to perform in each dimension */
-    for (ii = 0; ii < 7; ii++)
-    {
-      fpix[ii]=1;
-      irange[ii]=1;
-      dimen[ii]=1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {    
-      fpix[ii]=fpixel[ii];
-      irange[ii]=lpixel[ii]-fpixel[ii]+1;
-      dimen[ii]=naxes[ii];
-    }
-
-    i1=irange[0];
-
-    /* compute the pixel offset between each dimension */
-    off2 =     dimen[0];
-    off3 = off2 * dimen[1];
-    off4 = off3 * dimen[2];
-    off5 = off4 * dimen[3];
-    off6 = off5 * dimen[4];
-    off7 = off6 * dimen[5];
-
-    st10 = fpix[0];
-    st20 = (fpix[1] - 1) * off2;
-    st30 = (fpix[2] - 1) * off3;
-    st40 = (fpix[3] - 1) * off4;
-    st50 = (fpix[4] - 1) * off5;
-    st60 = (fpix[5] - 1) * off6;
-    st70 = (fpix[6] - 1) * off7;
-
-    /* store the initial offset in each dimension */
-    st1 = st10;
-    st2 = st20;
-    st3 = st30;
-    st4 = st40;
-    st5 = st50;
-    st6 = st60;
-    st7 = st70;
-
-    astart = 0;
-
-    for (i7 = 0; i7 < irange[6]; i7++)
-    {
-     for (i6 = 0; i6 < irange[5]; i6++)
-     {
-      for (i5 = 0; i5 < irange[4]; i5++)
-      {
-       for (i4 = 0; i4 < irange[3]; i4++)
-       {
-        for (i3 = 0; i3 < irange[2]; i3++)
-        {
-         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
-
-         for (i2 = 0; i2 < irange[1]; i2++)
-         {
-           if (ffpcld(fptr, 2, tablerow, pstart, i1, &array[astart],
-              status) > 0)
-              return(*status);
-
-           astart += i1;
-           pstart += off2;
-         }
-         st2 = st20;
-         st3 = st3+off3;    
-        }
-        st3 = st30;
-        st4 = st4+off4;
-       }
-       st4 = st40;
-       st5 = st5+off5;
-      }
-      st5 = st50;
-      st6 = st6+off6;
-     }
-     st6 = st60;
-     st7 = st7+off7;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpgpd( fitsfile *fptr,   /* I - FITS file pointer                      */
-            long  group,      /* I - group to write(1 = 1st group)          */
-            long  firstelem,  /* I - first vector element to write(1 = 1st) */
-            long  nelem,      /* I - number of values to write              */
-            double *array,    /* I - array of values that are written       */
-            int  *status)     /* IO - error status                          */
-/*
-  Write an array of group parameters to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffpcld(fptr, 1L, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcld( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            double *array,   /* I - array of values to write                */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    int tcode, maxelem2, hdutype, writeraw;
-    long twidth, incre;
-    long ntodo;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
-    double scale, zero;
-    char tform[20], cform[20];
-    char message[FLEN_ERRMSG];
-
-    char snull[20];   /*  the FITS null value  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-    maxelem = maxelem2;
-
-    if (tcode == TSTRING)   
-         ffcfmt(tform, cform);     /* derive C format for writing strings */
-
-    /*
-      if there is no scaling and the native machine format is not byteswapped,
-      then we can simply write the raw data bytes into the FITS file if the
-      datatype of the FITS column is the same as the input values.  Otherwise,
-      we must convert the raw values into the scaled and/or machine dependent
-      format in a temporary buffer that has been allocated for this purpose.
-    */
-    if (scale == 1. && zero == 0. && 
-       MACHINE == NATIVE && tcode == TDOUBLE)
-    {
-        writeraw = 1;
-        if (nelem < (LONGLONG)INT32_MAX) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/8;
-        }
-     }
-    else
-        writeraw = 0;
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
-    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
-    /*  TZEROn linear scaling parameters into a temporary buffer.          */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-        /* limit the number of pixels to process a one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TDOUBLE):
-              if (writeraw)
-              {
-                /* write raw input bytes without conversion */
-                ffpr8b(fptr, ntodo, incre, &array[next], status);
-              }
-              else
-              {
-                /* convert the raw data before writing to FITS file */
-                ffr8fr8(&array[next], ntodo, scale, zero,
-                        (double *) buffer, status);
-                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
-              }
-
-              break;
-
-            case (TLONGLONG):
-
-                ffr8fi8(&array[next], ntodo, scale, zero,
-                        (LONGLONG *) buffer, status);
-                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
-                break;
-
-            case (TBYTE):
- 
-                ffr8fi1(&array[next], ntodo, scale, zero, 
-                        (unsigned char *) buffer, status);
-                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
-                break;
-
-            case (TSHORT):
-
-                ffr8fi2(&array[next], ntodo, scale, zero, 
-                       (short *) buffer, status);
-                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
-                break;
-
-            case (TLONG):
-
-                ffr8fi4(&array[next], ntodo, scale, zero,
-                        (INT32BIT *) buffer, status);
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
-                break;
-
-            case (TFLOAT):
-                ffr8fr4(&array[next], ntodo, scale, zero,
-                        (float *) buffer, status);
-                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
-                break;
-
-            case (TSTRING):  /* numerical column in an ASCII table */
-
-                if (cform[1] != 's')  /*  "%s" format is a string */
-                {
-                  ffr8fstr(&array[next], ntodo, scale, zero, cform,
-                          twidth, (char *) buffer, status);
-
-                  if (incre == twidth)    /* contiguous bytes */
-                     ffpbyt(fptr, ntodo * twidth, buffer, status);
-                  else
-                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                            status);
-
-                  break;
-                }
-                /* can't write to string column, so fall thru to default: */
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                      "Cannot write numbers to column %d which has format %s",
-                       colnum,tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-          sprintf(message,
-          "Error writing elements %.0f thru %.0f of input data array (ffpcld).",
-              (double) (next+1), (double) (next+ntodo));
-         ffpmsg(message);
-         return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while writing FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpclm( fitsfile *fptr,   /* I - FITS file pointer                       */
-            int  colnum,      /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,   /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem,  /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,      /* I - number of values to write               */
-            double *array,    /* I - array of values to write                */
-            int  *status)     /* IO - error status                           */
-/*
-  Write an array of double complex values to a column in the current FITS HDU.
-  Each complex number if interpreted as a pair of float values.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column
-  if necessary, but normally complex values should only be written to a binary
-  table with TFORMn = 'rM' where r is an optional repeat count. The TSCALn and
-  TZERO keywords should not be used with complex numbers because mathmatically
-  the scaling should only be applied to the real (first) component of the
-  complex value.
-*/
-{
-    /* simply multiply the number of elements by 2, and call ffpcld */
-
-    ffpcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, 
-            nelem * 2, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcnd( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            double *array,   /* I - array of values to write                */
-            double nulvalue, /* I - value used to flag undefined pixels     */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels equal to the value of nulvalue will be replaced by the appropriate
-  null value in the output FITS file. 
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
-*/
-{
-    tcolumn *colptr;
-    LONGLONG  ngood = 0, nbad = 0, ii;
-    LONGLONG repeat, first, fstelm, fstrow;
-    int tcode, overflow = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode  = colptr->tdatatype;
-
-    if (tcode > 0)
-       repeat = colptr->trepeat;  /* repeat count for this column */
-    else
-       repeat = firstelem -1 + nelem;  /* variable length arrays */
-
-    if (abs(tcode) >= TCOMPLEX)
-    { /* treat complex columns as pairs of numbers */
-        repeat *= 2;
-    }
-
-    /* if variable length array, first write the whole input vector, 
-       then go back and fill in the nulls */
-    if (tcode < 0) {
-      if (ffpcld(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
-	if (*status == NUM_OVERFLOW) 
-	{
-	  /* ignore overflows, which are possibly the null pixel values */
-	  /*  overflow = 1;   */
-	  *status = 0;
-	} else { 
-          return(*status);
-	}
-      }
-    }
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (array[ii] != nulvalue)  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            /* call ffpcluc, not ffpclu, in case we are writing to a
-	       complex ('C') binary table column */
-            if (ffpcluc(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-
-            nbad=0;
-         }
-
-         ngood = ngood +1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (tcode > 0) {  /* variable length arrays have already been written */
-              if (ffpcld(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0) {
-		if (*status == NUM_OVERFLOW) 
-		{
-		  overflow = 1;
-		  *status = 0;
-		} else {
-                  return(*status);
-		}
-	      }
-            }
-            ngood=0;
-         }
-
-         nbad = nbad +1;  /* the consecutive number of bad pixels */
-      }
-    }
-
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      if (tcode > 0) {  /* variable length arrays have already been written */
-        ffpcld(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-      }
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-      ffpcluc(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-
-    if (*status <= 0) {
-      if (overflow) {
-        *status = NUM_OVERFLOW;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr8fi1(double *input,         /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            unsigned char *output, /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (input[ii] > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (dvalue > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) (dvalue + .5);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr8fi2(double *input,     /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            short *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (input[ii] > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-                output[ii] = (short) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (short) (dvalue + .5);
-                else
-                    output[ii] = (short) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr8fi4(double *input,     /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            INT32BIT *output,  /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (input[ii] > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-                output[ii] = (INT32BIT) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (INT32BIT) (dvalue + .5);
-                else
-                    output[ii] = (INT32BIT) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr8fi8(double *input,     /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            LONGLONG *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (input[ii] > DLONGLONG_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-                output[ii] = (LONGLONG) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (dvalue > DLONGLONG_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (LONGLONG) (dvalue + .5);
-                else
-                    output[ii] = (LONGLONG) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr8fr4(double *input,     /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            float *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (float) ((input[ii] - zero) / scale);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr8fr8(double *input,     /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            double *output,    /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-      memcpy(output, input, ntodo * sizeof(double) ); /* copy input to output */
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (input[ii] - zero) / scale;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr8fstr(double *input,     /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            char *cform,       /* I - format for output string values  */
-            long twidth,       /* I - width of each field, in chars    */
-            char *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-    char *cptr;
-    
-    cptr = output;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-           sprintf(output, cform, input[ii]);
-           output += twidth;
-
-           if (*output)  /* if this char != \0, then overflow occurred */
-              *status = OVERFLOW_ERR;
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-          dvalue = (input[ii] - zero) / scale;
-          sprintf(output, cform, dvalue);
-          output += twidth;
-
-          if (*output)  /* if this char != \0, then overflow occurred */
-            *status = OVERFLOW_ERR;
-        }
-    }
-
-    /* replace any commas with periods (e.g., in French locale) */
-    while ((cptr = strchr(cptr, ','))) *cptr = '.';
-    
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcole.c b/src/external/OpenGR/3rdparty/cfitsio/putcole.c
deleted file mode 100644
index fa84fab43..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcole.c
+++ /dev/null
@@ -1,1078 +0,0 @@
-/*  This file, putcole.c, contains routines that write data elements to    */
-/*  a FITS image or table, with float datatype.                            */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffppre( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG nelem,     /* I - number of values to write               */
-            float *array,    /* I - array of values that are written        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-
-  This routine cannot be called directly by users to write to large
-  arrays with > 2**31 pixels (although CFITSIO can do so by passing
-  the firstelem thru a LONGLONG sized global variable)
-*/
-{
-    long row;
-    float nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_pixels(fptr, TFLOAT, firstelem, nelem,
-            0, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcle(fptr, 2, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppne( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG nelem,     /* I - number of values to write               */
-            float *array,    /* I - array of values that are written        */
-            float nulval,    /* I - undefined pixel value                   */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).  Any array values
-  that are equal to the value of nulval will be replaced with the null
-  pixel value that is appropriate for this column.
-
-  This routine cannot be called directly by users to write to large
-  arrays with > 2**31 pixels (although CFITSIO can do so by passing
-  the firstelem thru a LONGLONG sized global variable)
-*/
-{
-    long row;
-    float nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        nullvalue = nulval;  /* set local variable */
-        fits_write_compressed_pixels(fptr, TFLOAT, firstelem, nelem,
-            1, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcne(fptr, 2, row, firstelem, nelem, array, nulval, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp2de(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           float *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-
-  This routine does not support writing to large images with
-  more than 2**31 pixels.
-*/
-{
-    /* call the 3D writing routine, with the 3rd dimension = 1 */
-
-    ffp3de(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp3de(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  nrows,      /* I - number of rows in each plane of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
-           float *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 3-D cube of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-
-  This routine does not support writing to large images with
-  more than 2**31 pixels.
-*/
-{
-    long tablerow, ii, jj;
-    long fpixel[3]= {1,1,1}, lpixel[3];
-    LONGLONG nfits, narray;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-           
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-        lpixel[0] = (long) ncols;
-        lpixel[1] = (long) nrows;
-        lpixel[2] = (long) naxis3;
-       
-        fits_write_compressed_img(fptr, TFLOAT, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-      /* all the image pixels are contiguous, so write all at once */
-      ffpcle(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
-      return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to write to */
-    narray = 0;  /* next pixel in input array to be written */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* writing naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffpcle(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
-         return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpsse(fitsfile *fptr,   /* I - FITS file pointer                       */
-           long  group,      /* I - group to write(1 = 1st group)           */
-           long  naxis,      /* I - number of data axes in array            */
-           long  *naxes,     /* I - size of each FITS axis                  */
-           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
-           long  *lpixel,    /* I - last pixel in each axis to write        */
-           float *array,     /* I - array to be written                     */
-           int  *status)     /* IO - error status                           */
-/*
-  Write a subsection of pixels to the primary array or image.
-  A subsection is defined to be any contiguous rectangular
-  array of pixels within the n-dimensional FITS data file.
-  Data conversion and scaling will be performed if necessary 
-  (e.g, if the datatype of the FITS array is not the same as
-  the array being written).
-*/
-{
-    long tablerow;
-    LONGLONG fpix[7], dimen[7], astart, pstart;
-    LONGLONG off2, off3, off4, off5, off6, off7;
-    LONGLONG st10, st20, st30, st40, st50, st60, st70;
-    LONGLONG st1, st2, st3, st4, st5, st6, st7;
-    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_img(fptr, TFLOAT, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    if (naxis < 1 || naxis > 7)
-      return(*status = BAD_DIMEN);
-
-    tablerow=maxvalue(1,group);
-
-     /* calculate the size and number of loops to perform in each dimension */
-    for (ii = 0; ii < 7; ii++)
-    {
-      fpix[ii]=1;
-      irange[ii]=1;
-      dimen[ii]=1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {    
-      fpix[ii]=fpixel[ii];
-      irange[ii]=lpixel[ii]-fpixel[ii]+1;
-      dimen[ii]=naxes[ii];
-    }
-
-    i1=irange[0];
-
-    /* compute the pixel offset between each dimension */
-    off2 =     dimen[0];
-    off3 = off2 * dimen[1];
-    off4 = off3 * dimen[2];
-    off5 = off4 * dimen[3];
-    off6 = off5 * dimen[4];
-    off7 = off6 * dimen[5];
-
-    st10 = fpix[0];
-    st20 = (fpix[1] - 1) * off2;
-    st30 = (fpix[2] - 1) * off3;
-    st40 = (fpix[3] - 1) * off4;
-    st50 = (fpix[4] - 1) * off5;
-    st60 = (fpix[5] - 1) * off6;
-    st70 = (fpix[6] - 1) * off7;
-
-    /* store the initial offset in each dimension */
-    st1 = st10;
-    st2 = st20;
-    st3 = st30;
-    st4 = st40;
-    st5 = st50;
-    st6 = st60;
-    st7 = st70;
-
-    astart = 0;
-
-    for (i7 = 0; i7 < irange[6]; i7++)
-    {
-     for (i6 = 0; i6 < irange[5]; i6++)
-     {
-      for (i5 = 0; i5 < irange[4]; i5++)
-      {
-       for (i4 = 0; i4 < irange[3]; i4++)
-       {
-        for (i3 = 0; i3 < irange[2]; i3++)
-        {
-         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
-
-         for (i2 = 0; i2 < irange[1]; i2++)
-         {
-           if (ffpcle(fptr, 2, tablerow, pstart, i1, &array[astart],
-              status) > 0)
-              return(*status);
-
-           astart += i1;
-           pstart += off2;
-         }
-         st2 = st20;
-         st3 = st3+off3;    
-        }
-        st3 = st30;
-        st4 = st4+off4;
-       }
-       st4 = st40;
-       st5 = st5+off5;
-      }
-      st5 = st50;
-      st6 = st6+off6;
-     }
-     st6 = st60;
-     st7 = st7+off7;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpgpe( fitsfile *fptr,   /* I - FITS file pointer                      */
-            long  group,      /* I - group to write(1 = 1st group)          */
-            long  firstelem,  /* I - first vector element to write(1 = 1st) */
-            long  nelem,      /* I - number of values to write              */
-            float *array,     /* I - array of values that are written       */
-            int  *status)     /* IO - error status                          */
-/*
-  Write an array of group parameters to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffpcle(fptr, 1L, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcle( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            float *array,    /* I - array of values to write                */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    int tcode, maxelem2, hdutype, writeraw;
-    long twidth, incre;
-    long ntodo;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
-    double scale, zero;
-    char tform[20], cform[20];
-    char message[FLEN_ERRMSG];
-
-    char snull[20];   /*  the FITS null value  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-    maxelem = maxelem2;
-
-    if (tcode == TSTRING)   
-         ffcfmt(tform, cform);     /* derive C format for writing strings */
-
-    /*
-       if there is no scaling and the native machine format is not byteswapped
-       then we can simply write the raw data bytes into the FITS file if the
-       datatype of the FITS column is the same as the input values.  Otherwise,
-       we must convert the raw values into the scaled and/or machine dependent
-       format in a temporary buffer that has been allocated for this purpose.
-    */
-    if (scale == 1. && zero == 0. && 
-       MACHINE == NATIVE && tcode == TFLOAT)
-    {
-        writeraw = 1;
-        if (nelem < (LONGLONG)INT32_MAX) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/4;
-        }
-     }
-    else
-        writeraw = 0;
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
-    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
-    /*  TZEROn linear scaling parameters into a temporary buffer.          */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-        /* limit the number of pixels to process a one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TFLOAT):
-              if (writeraw)
-              {
-                /* write raw input bytes without conversion */
-                ffpr4b(fptr, ntodo, incre, &array[next], status);
-              }
-              else
-              {
-                /* convert the raw data before writing to FITS file */
-                ffr4fr4(&array[next], ntodo, scale, zero,
-                        (float *) buffer, status);
-                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
-              }
-
-              break;
-
-            case (TLONGLONG):
-
-                ffr4fi8(&array[next], ntodo, scale, zero,
-                        (LONGLONG *) buffer, status);
-                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
-                break;
-
-            case (TBYTE):
- 
-                ffr4fi1(&array[next], ntodo, scale, zero, 
-                        (unsigned char *) buffer, status);
-                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
-                break;
-
-            case (TSHORT):
-
-                ffr4fi2(&array[next], ntodo, scale, zero,
-                        (short *) buffer, status);
-                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
-                break;
-
-            case (TLONG):
-
-                ffr4fi4(&array[next], ntodo, scale, zero,
-                        (INT32BIT *) buffer, status);
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
-                break;
-
-            case (TDOUBLE):
-                ffr4fr8(&array[next], ntodo, scale, zero,
-                       (double *) buffer, status);
-                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
-                break;
-
-            case (TSTRING):  /* numerical column in an ASCII table */
-
-                if (cform[1] != 's')  /*  "%s" format is a string */
-                {
-                  ffr4fstr(&array[next], ntodo, scale, zero, cform,
-                          twidth, (char *) buffer, status);
-
-                  if (incre == twidth)    /* contiguous bytes */
-                     ffpbyt(fptr, ntodo * twidth, buffer, status);
-                  else
-                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                            status);
-
-                  break;
-                }
-                /* can't write to string column, so fall thru to default: */
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                       "Cannot write numbers to column %d which has format %s",
-                        colnum,tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-          sprintf(message,
-          "Error writing elements %.0f thru %.0f of input data array (ffpcle).",
-             (double) (next+1), (double) (next+ntodo));
-         ffpmsg(message);
-         return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while writing FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpclc( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            float *array,    /* I - array of values to write                */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of complex values to a column in the current FITS HDU.
-  Each complex number if interpreted as a pair of float values.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column
-  if necessary, but normally complex values should only be written to a binary
-  table with TFORMn = 'rC' where r is an optional repeat count. The TSCALn and
-  TZERO keywords should not be used with complex numbers because mathmatically
-  the scaling should only be applied to the real (first) component of the
-  complex value.
-*/
-{
-    /* simply multiply the number of elements by 2, and call ffpcle */
-
-    ffpcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1,
-            nelem * 2, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcne( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            float *array,    /* I - array of values to write                */
-            float  nulvalue, /* I - value used to flag undefined pixels     */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels equal to the value of nulvalue will be replaced by the appropriate
-  null value in the output FITS file. 
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
-*/
-{
-    tcolumn *colptr;
-    LONGLONG  ngood = 0, nbad = 0, ii;
-    LONGLONG repeat, first, fstelm, fstrow;
-    int tcode, overflow = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode  = colptr->tdatatype;
-
-    if (tcode > 0)
-       repeat = colptr->trepeat;  /* repeat count for this column */
-    else
-       repeat = firstelem -1 + nelem;  /* variable length arrays */
-
-    if (abs(tcode) >= TCOMPLEX)
-    { /* treat complex columns as pairs of numbers */
-        repeat *= 2;
-    }
-    
-    /* if variable length array, first write the whole input vector, 
-       then go back and fill in the nulls */
-    if (tcode < 0) {
-      if (ffpcle(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
-        if (*status == NUM_OVERFLOW) 
-	{
-	  /* ignore overflows, which are possibly the null pixel values */
-	  /*  overflow = 1;   */
-	  *status = 0;
-	} else { 
-          return(*status);
-	}
-      }
-    }
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (array[ii] != nulvalue)  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            /* call ffpcluc, not ffpclu, in case we are writing to a
-	       complex ('C') binary table column */
-            if (ffpcluc(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-
-            nbad=0;
-         }
-
-         ngood = ngood +1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (tcode > 0) {  /* variable length arrays have already been written */
-              if (ffpcle(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0) {
-		if (*status == NUM_OVERFLOW) 
-		{
-		  overflow = 1;
-		  *status = 0;
-		} else { 
-                  return(*status);
-		}
-              }
-	    }
-            ngood=0;
-         }
-
-         nbad = nbad +1;  /* the consecutive number of bad pixels */
-      }
-    }
-
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      if (tcode > 0) {  /* variable length arrays have already been written */
-        ffpcle(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-      }
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-      ffpcluc(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-    
-    if (*status <= 0) {
-      if (overflow) {
-        *status = NUM_OVERFLOW;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr4fi1(float *input,          /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            unsigned char *output, /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (input[ii] > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (dvalue > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) (dvalue + .5);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr4fi2(float *input,      /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            short *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {           
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (input[ii] > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-                output[ii] = (short) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (short) (dvalue + .5);
-                else
-                    output[ii] = (short) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr4fi4(float *input,      /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            INT32BIT *output,  /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (input[ii] > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-                output[ii] = (INT32BIT) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (INT32BIT) (dvalue + .5);
-                else
-                    output[ii] = (INT32BIT) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr4fi8(float *input,      /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            LONGLONG *output,  /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (input[ii] > DLONGLONG_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-                output[ii] = (long) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (LONGLONG) (dvalue + .5);
-                else
-                    output[ii] = (LONGLONG) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr4fr4(float *input,      /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            float *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-      memcpy(output, input, ntodo * sizeof(float) ); /* copy input to output */
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (float) ((input[ii] - zero) / scale);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr4fr8(float *input,      /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            double *output,    /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (input[ii] - zero) / scale;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr4fstr(float *input,     /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            char *cform,       /* I - format for output string values  */
-            long twidth,       /* I - width of each field, in chars    */
-            char *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-    char *cptr;
-    
-    cptr = output;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-           sprintf(output, cform, (double) input[ii]);
-           output += twidth;
-
-           if (*output)  /* if this char != \0, then overflow occurred */
-              *status = OVERFLOW_ERR;
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-          dvalue = (input[ii] - zero) / scale;
-          sprintf(output, cform, dvalue);
-          output += twidth;
-
-          if (*output)  /* if this char != \0, then overflow occurred */
-            *status = OVERFLOW_ERR;
-        }
-    }
-
-    /* replace any commas with periods (e.g., in French locale) */
-    while ((cptr = strchr(cptr, ','))) *cptr = '.';
-    
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcoli.c b/src/external/OpenGR/3rdparty/cfitsio/putcoli.c
deleted file mode 100644
index ca5e92f1d..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcoli.c
+++ /dev/null
@@ -1,988 +0,0 @@
-/*  This file, putcoli.c, contains routines that write data elements to    */
-/*  a FITS image or table, with short datatype.                            */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffppri( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write (1 = 1st group)          */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            short *array,    /* I - array of values that are written        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-    short nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-
-        fits_write_compressed_pixels(fptr, TSHORT, firstelem, nelem,
-            0, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcli(fptr, 2, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppni( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            short *array,    /* I - array of values that are written        */
-            short nulval,    /* I - undefined pixel value                   */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).  Any array values
-  that are equal to the value of nulval will be replaced with the null
-  pixel value that is appropriate for this column.
-*/
-{
-    long row;
-    short nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        nullvalue = nulval;  /* set local variable */
-        fits_write_compressed_pixels(fptr, TSHORT, firstelem, nelem,
-            1, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcni(fptr, 2, row, firstelem, nelem, array, nulval, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp2di(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           short *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    /* call the 3D writing routine, with the 3rd dimension = 1 */
-
-    ffp3di(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp3di(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  nrows,      /* I - number of rows in each plane of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
-           short *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 3-D cube of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    long tablerow, ii, jj;
-    long fpixel[3]= {1,1,1}, lpixel[3];
-    LONGLONG nfits, narray;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-           
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-        lpixel[0] = (long) ncols;
-        lpixel[1] = (long) nrows;
-        lpixel[2] = (long) naxis3;
-       
-        fits_write_compressed_img(fptr, TSHORT, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-      /* all the image pixels are contiguous, so write all at once */
-      ffpcli(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
-      return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to write to */
-    narray = 0;  /* next pixel in input array to be written */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* writing naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffpcli(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
-         return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpssi(fitsfile *fptr,   /* I - FITS file pointer                       */
-           long  group,      /* I - group to write(1 = 1st group)           */
-           long  naxis,      /* I - number of data axes in array            */
-           long  *naxes,     /* I - size of each FITS axis                  */
-           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
-           long  *lpixel,    /* I - last pixel in each axis to write        */
-           short *array,     /* I - array to be written                     */
-           int  *status)     /* IO - error status                           */
-/*
-  Write a subsection of pixels to the primary array or image.
-  A subsection is defined to be any contiguous rectangular
-  array of pixels within the n-dimensional FITS data file.
-  Data conversion and scaling will be performed if necessary 
-  (e.g, if the datatype of the FITS array is not the same as
-  the array being written).
-*/
-{
-    long tablerow;
-    LONGLONG fpix[7], dimen[7], astart, pstart;
-    LONGLONG off2, off3, off4, off5, off6, off7;
-    LONGLONG st10, st20, st30, st40, st50, st60, st70;
-    LONGLONG st1, st2, st3, st4, st5, st6, st7;
-    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_img(fptr, TSHORT, fpixel, lpixel,
-            0,  array, NULL, status);
-
-        return(*status);
-    }
-
-    if (naxis < 1 || naxis > 7)
-      return(*status = BAD_DIMEN);
-
-    tablerow=maxvalue(1,group);
-
-     /* calculate the size and number of loops to perform in each dimension */
-    for (ii = 0; ii < 7; ii++)
-    {
-      fpix[ii]=1;
-      irange[ii]=1;
-      dimen[ii]=1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {    
-      fpix[ii]=fpixel[ii];
-      irange[ii]=lpixel[ii]-fpixel[ii]+1;
-      dimen[ii]=naxes[ii];
-    }
-
-    i1=irange[0];
-
-    /* compute the pixel offset between each dimension */
-    off2 =     dimen[0];
-    off3 = off2 * dimen[1];
-    off4 = off3 * dimen[2];
-    off5 = off4 * dimen[3];
-    off6 = off5 * dimen[4];
-    off7 = off6 * dimen[5];
-
-    st10 = fpix[0];
-    st20 = (fpix[1] - 1) * off2;
-    st30 = (fpix[2] - 1) * off3;
-    st40 = (fpix[3] - 1) * off4;
-    st50 = (fpix[4] - 1) * off5;
-    st60 = (fpix[5] - 1) * off6;
-    st70 = (fpix[6] - 1) * off7;
-
-    /* store the initial offset in each dimension */
-    st1 = st10;
-    st2 = st20;
-    st3 = st30;
-    st4 = st40;
-    st5 = st50;
-    st6 = st60;
-    st7 = st70;
-
-    astart = 0;
-
-    for (i7 = 0; i7 < irange[6]; i7++)
-    {
-     for (i6 = 0; i6 < irange[5]; i6++)
-     {
-      for (i5 = 0; i5 < irange[4]; i5++)
-      {
-       for (i4 = 0; i4 < irange[3]; i4++)
-       {
-        for (i3 = 0; i3 < irange[2]; i3++)
-        {
-         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
-
-         for (i2 = 0; i2 < irange[1]; i2++)
-         {
-           if (ffpcli(fptr, 2, tablerow, pstart, i1, &array[astart],
-              status) > 0)
-              return(*status);
-
-           astart += i1;
-           pstart += off2;
-         }
-         st2 = st20;
-         st3 = st3+off3;    
-        }
-        st3 = st30;
-        st4 = st4+off4;
-       }
-       st4 = st40;
-       st5 = st5+off5;
-      }
-      st5 = st50;
-      st6 = st6+off6;
-     }
-     st6 = st60;
-     st7 = st7+off7;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpgpi( fitsfile *fptr,   /* I - FITS file pointer                      */
-            long  group,      /* I - group to write(1 = 1st group)          */
-            long  firstelem,  /* I - first vector element to write(1 = 1st) */
-            long  nelem,      /* I - number of values to write              */
-            short *array,     /* I - array of values that are written       */
-            int  *status)     /* IO - error status                          */
-/*
-  Write an array of group parameters to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffpcli(fptr, 1L, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcli( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            short *array,    /* I - array of values to write                */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table with
-  2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    int tcode, maxelem2, hdutype, writeraw;
-    long twidth, incre;
-    long ntodo;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
-    double scale, zero;
-    char tform[20], cform[20];
-    char message[FLEN_ERRMSG];
-
-    char snull[20];   /*  the FITS null value  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-    maxelem = maxelem2;
-
-    if (tcode == TSTRING)   
-         ffcfmt(tform, cform);     /* derive C format for writing strings */
-
-    /*
-      if there is no scaling and the native machine format is not byteswapped,
-      then we can simply write the raw data bytes into the FITS file if the
-      datatype of the FITS column is the same as the input values.  Otherwise,
-      we must convert the raw values into the scaled and/or machine dependent
-      format in a temporary buffer that has been allocated for this purpose.
-    */
-    if (scale == 1. && zero == 0. &&
-       MACHINE == NATIVE && tcode == TSHORT)
-    {
-        writeraw = 1;
-        if (nelem < (LONGLONG)INT32_MAX) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/2;
-        }
-    }
-    else
-        writeraw = 0;
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
-    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
-    /*  TZEROn linear scaling parameters into a temporary buffer.          */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-        /* limit the number of pixels to process a one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TSHORT):
-              if (writeraw)
-              {
-                /* write raw input bytes without conversion */
-                ffpi2b(fptr, ntodo, incre, &array[next], status);
-              }
-              else
-              {
-                /* convert the raw data before writing to FITS file */
-                ffi2fi2(&array[next], ntodo, scale, zero,
-                        (short *) buffer, status);
-                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
-              }
-
-              break;
-
-            case (TLONGLONG):
-
-                ffi2fi8(&array[next], ntodo, scale, zero,
-                        (LONGLONG *) buffer, status);
-                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
-                break;
-
-             case (TBYTE):
-
-                ffi2fi1(&array[next], ntodo, scale, zero,
-                        (unsigned char *) buffer, status);
-                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
-                break;
-
-            case (TLONG):
-
-                ffi2fi4(&array[next], ntodo, scale, zero,
-                        (INT32BIT *) buffer, status);
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
-                break;
-
-            case (TFLOAT):
-
-                ffi2fr4(&array[next], ntodo, scale, zero,
-                        (float *) buffer, status);
-                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
-                break;
-
-            case (TDOUBLE):
-                ffi2fr8(&array[next], ntodo, scale, zero,
-                        (double *) buffer, status);
-                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
-                break;
-
-            case (TSTRING):  /* numerical column in an ASCII table */
-
-                if (cform[1] != 's')  /*  "%s" format is a string */
-                {
-                  ffi2fstr(&array[next], ntodo, scale, zero, cform,
-                          twidth, (char *) buffer, status);
-
-
-                  if (incre == twidth)    /* contiguous bytes */
-                     ffpbyt(fptr, ntodo * twidth, buffer, status);
-                  else
-                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                            status);
-
-                  break;
-                }
-                /* can't write to string column, so fall thru to default: */
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                    "Cannot write numbers to column %d which has format %s",
-                      colnum,tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-         sprintf(message,
-          "Error writing elements %.0f thru %.0f of input data array (ffpcli).",
-             (double) (next+1), (double) (next+ntodo));
-         ffpmsg(message);
-         return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-       ffpmsg(
-       "Numerical overflow during type conversion while writing FITS data.");
-       *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcni( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            short *array,    /* I - array of values to write                */
-            short  nulvalue, /* I - value used to flag undefined pixels     */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels equal to the value of nulvalue will be replaced by the appropriate
-  null value in the output FITS file. 
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
-*/
-{
-    tcolumn *colptr;
-    LONGLONG  ngood = 0, nbad = 0, ii;
-    LONGLONG repeat, first, fstelm, fstrow;
-    int tcode, overflow = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode  = colptr->tdatatype;
-
-    if (tcode > 0)
-       repeat = colptr->trepeat;  /* repeat count for this column */
-    else
-       repeat = firstelem -1 + nelem;  /* variable length arrays */
-
-    /* if variable length array, first write the whole input vector, 
-       then go back and fill in the nulls */
-    if (tcode < 0) {
-      if (ffpcli(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
-        if (*status == NUM_OVERFLOW) 
-	{
-	  /* ignore overflows, which are possibly the null pixel values */
-	  /*  overflow = 1;   */
-	  *status = 0;
-	} else { 
-          return(*status);
-	}
-      }
-    }
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (array[ii] != nulvalue)  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-
-            nbad=0;
-         }
-
-         ngood = ngood +1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (tcode > 0) {  /* variable length arrays have already been written */
-              if (ffpcli(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0) {
-		if (*status == NUM_OVERFLOW) 
-		{
-		  overflow = 1;
-		  *status = 0;
-		} else { 
-                  return(*status);
-		}
-	      }
-	    }
-            ngood=0;
-         }
-
-         nbad = nbad +1;  /* the consecutive number of bad pixels */
-      }
-    }
-
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      if (tcode > 0) {  /* variable length arrays have already been written */
-        ffpcli(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-      }
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-
-    if (*status <= 0) {
-      if (overflow) {
-        *status = NUM_OVERFLOW;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi2fi1(short *input,          /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            unsigned char *output, /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < 0)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (input[ii] > UCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (dvalue > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) (dvalue + .5);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi2fi2(short *input,       /* I - array of values to be converted  */
-            long ntodo,         /* I - number of elements in the array  */
-            double scale,       /* I - FITS TSCALn or BSCALE value      */
-            double zero,        /* I - FITS TZEROn or BZERO  value      */
-            short *output,      /* O - output array of converted values */
-            int *status)        /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        memcpy(output, input, ntodo * sizeof(short) );
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (short) (dvalue + .5);
-                else
-                    output[ii] = (short) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi2fi4(short *input,      /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            INT32BIT *output,  /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (INT32BIT) input[ii];   /* just copy input to output */
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (INT32BIT) (dvalue + .5);
-                else
-                    output[ii] = (INT32BIT) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi2fi8(short *input,      /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            LONGLONG *output,  /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (dvalue > DLONGLONG_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (LONGLONG) (dvalue + .5);
-                else
-                    output[ii] = (LONGLONG) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi2fr4(short *input,      /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            float *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (float) ((input[ii] - zero) / scale);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi2fr8(short *input,      /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            double *output,    /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (input[ii] - zero) / scale;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi2fstr(short *input,     /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            char *cform,       /* I - format for output string values  */
-            long twidth,       /* I - width of each field, in chars    */
-            char *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-    char *cptr;
-    
-    cptr = output;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-           sprintf(output, cform, (double) input[ii]);
-           output += twidth;
-
-           if (*output)  /* if this char != \0, then overflow occurred */
-              *status = OVERFLOW_ERR;
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-          dvalue = (input[ii] - zero) / scale;
-          sprintf(output, cform, dvalue);
-          output += twidth;
-
-          if (*output)  /* if this char != \0, then overflow occurred */
-            *status = OVERFLOW_ERR;
-        }
-    }
-
-    /* replace any commas with periods (e.g., in French locale) */
-    while ((cptr = strchr(cptr, ','))) *cptr = '.';
-
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcolj.c b/src/external/OpenGR/3rdparty/cfitsio/putcolj.c
deleted file mode 100644
index d3125afa2..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcolj.c
+++ /dev/null
@@ -1,2000 +0,0 @@
-/*  This file, putcolj.c, contains routines that write data elements to    */
-/*  a FITS image or table, with long datatype.                             */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffpprj( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            long  *array,    /* I - array of values that are written        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-    long nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_pixels(fptr, TLONG, firstelem, nelem,
-            0, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpclj(fptr, 2, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppnj( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            long  *array,    /* I - array of values that are written        */
-            long  nulval,    /* I - undefined pixel value                   */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).  Any array values
-  that are equal to the value of nulval will be replaced with the null
-  pixel value that is appropriate for this column.
-*/
-{
-    long row;
-    long nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        nullvalue = nulval;  /* set local variable */
-        fits_write_compressed_pixels(fptr, TLONG, firstelem, nelem,
-            1, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcnj(fptr, 2, row, firstelem, nelem, array, nulval, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp2dj(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           long  *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-
-    /* call the 3D writing routine, with the 3rd dimension = 1 */
-
-    ffp3dj(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp3dj(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  nrows,      /* I - number of rows in each plane of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
-           long  *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 3-D cube of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    long tablerow, ii, jj;
-    long fpixel[3]= {1,1,1}, lpixel[3];
-    LONGLONG nfits, narray;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-           
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-        lpixel[0] = (long) ncols;
-        lpixel[1] = (long) nrows;
-        lpixel[2] = (long) naxis3;
-       
-        fits_write_compressed_img(fptr, TLONG, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-      /* all the image pixels are contiguous, so write all at once */
-      ffpclj(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
-      return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to write to */
-    narray = 0;  /* next pixel in input array to be written */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* writing naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffpclj(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
-         return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpssj(fitsfile *fptr,   /* I - FITS file pointer                       */
-           long  group,      /* I - group to write(1 = 1st group)           */
-           long  naxis,      /* I - number of data axes in array            */
-           long  *naxes,     /* I - size of each FITS axis                  */
-           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
-           long  *lpixel,    /* I - last pixel in each axis to write        */
-           long *array,      /* I - array to be written                     */
-           int  *status)     /* IO - error status                           */
-/*
-  Write a subsection of pixels to the primary array or image.
-  A subsection is defined to be any contiguous rectangular
-  array of pixels within the n-dimensional FITS data file.
-  Data conversion and scaling will be performed if necessary 
-  (e.g, if the datatype of the FITS array is not the same as
-  the array being written).
-*/
-{
-    long tablerow;
-    LONGLONG fpix[7], dimen[7], astart, pstart;
-    LONGLONG off2, off3, off4, off5, off6, off7;
-    LONGLONG st10, st20, st30, st40, st50, st60, st70;
-    LONGLONG st1, st2, st3, st4, st5, st6, st7;
-    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_img(fptr, TLONG, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    if (naxis < 1 || naxis > 7)
-      return(*status = BAD_DIMEN);
-
-    tablerow=maxvalue(1,group);
-
-     /* calculate the size and number of loops to perform in each dimension */
-    for (ii = 0; ii < 7; ii++)
-    {
-      fpix[ii]=1;
-      irange[ii]=1;
-      dimen[ii]=1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {    
-      fpix[ii]=fpixel[ii];
-      irange[ii]=lpixel[ii]-fpixel[ii]+1;
-      dimen[ii]=naxes[ii];
-    }
-
-    i1=irange[0];
-
-    /* compute the pixel offset between each dimension */
-    off2 =     dimen[0];
-    off3 = off2 * dimen[1];
-    off4 = off3 * dimen[2];
-    off5 = off4 * dimen[3];
-    off6 = off5 * dimen[4];
-    off7 = off6 * dimen[5];
-
-    st10 = fpix[0];
-    st20 = (fpix[1] - 1) * off2;
-    st30 = (fpix[2] - 1) * off3;
-    st40 = (fpix[3] - 1) * off4;
-    st50 = (fpix[4] - 1) * off5;
-    st60 = (fpix[5] - 1) * off6;
-    st70 = (fpix[6] - 1) * off7;
-
-    /* store the initial offset in each dimension */
-    st1 = st10;
-    st2 = st20;
-    st3 = st30;
-    st4 = st40;
-    st5 = st50;
-    st6 = st60;
-    st7 = st70;
-
-    astart = 0;
-
-    for (i7 = 0; i7 < irange[6]; i7++)
-    {
-     for (i6 = 0; i6 < irange[5]; i6++)
-     {
-      for (i5 = 0; i5 < irange[4]; i5++)
-      {
-       for (i4 = 0; i4 < irange[3]; i4++)
-       {
-        for (i3 = 0; i3 < irange[2]; i3++)
-        {
-         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
-
-         for (i2 = 0; i2 < irange[1]; i2++)
-         {
-           if (ffpclj(fptr, 2, tablerow, pstart, i1, &array[astart],
-              status) > 0)
-              return(*status);
-
-           astart += i1;
-           pstart += off2;
-         }
-         st2 = st20;
-         st3 = st3+off3;    
-        }
-        st3 = st30;
-        st4 = st4+off4;
-       }
-       st4 = st40;
-       st5 = st5+off5;
-      }
-      st5 = st50;
-      st6 = st6+off6;
-     }
-     st6 = st60;
-     st7 = st7+off7;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpgpj( fitsfile *fptr,   /* I - FITS file pointer                      */
-            long  group,      /* I - group to write(1 = 1st group)          */
-            long  firstelem,  /* I - first vector element to write(1 = 1st) */
-            long  nelem,      /* I - number of values to write              */
-            long  *array,     /* I - array of values that are written       */
-            int  *status)     /* IO - error status                          */
-/*
-  Write an array of group parameters to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffpclj(fptr, 1L, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpclj( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            long  *array,    /* I - array of values to write                */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    int tcode, maxelem2, hdutype, writeraw;
-    long twidth, incre;
-    long ntodo;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
-    double scale, zero;
-    char tform[20], cform[20];
-    char message[FLEN_ERRMSG];
-
-    char snull[20];   /*  the FITS null value  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-    maxelem = maxelem2;
-
-    if (tcode == TSTRING)   
-         ffcfmt(tform, cform);     /* derive C format for writing strings */
-
-    /*
-       if there is no scaling and the native machine format is not byteswapped
-       then we can simply write the raw data bytes into the FITS file if the
-       datatype of the FITS column is the same as the input values.  Otherwise
-       we must convert the raw values into the scaled and/or machine dependent
-       format in a temporary buffer that has been allocated for this purpose.
-    */
-    if (scale == 1. && zero == 0. && 
-       MACHINE == NATIVE && tcode == TLONG && LONGSIZE == 32)
-    {
-        writeraw = 1;
-        if (nelem < (LONGLONG)INT32_MAX) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/8;
-        }
-    }
-    else
-        writeraw = 0;
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
-    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
-    /*  TZEROn linear scaling parameters into a temporary buffer.          */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-        /* limit the number of pixels to process a one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TLONG):
-              if (writeraw)
-              {
-                /* write raw input bytes without conversion */
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) &array[next], status);
-              }
-              else
-              {
-                /* convert the raw data before writing to FITS file */
-                ffi4fi4(&array[next], ntodo, scale, zero,
-                        (INT32BIT *) buffer, status);
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
-              }
-
-              break;
-
-            case (TLONGLONG):
-
-                fflongfi8(&array[next], ntodo, scale, zero,
-                        (LONGLONG *) buffer, status);
-                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
-                break;
-
-            case (TBYTE):
- 
-                ffi4fi1(&array[next], ntodo, scale, zero,
-                        (unsigned char *) buffer, status);
-                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
-                break;
-
-            case (TSHORT):
-
-                ffi4fi2(&array[next], ntodo, scale, zero,
-                        (short *) buffer, status);
-                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
-                break;
-
-            case (TFLOAT):
-
-                ffi4fr4(&array[next], ntodo, scale, zero,
-                        (float *) buffer, status);
-                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
-                break;
-
-            case (TDOUBLE):
-                ffi4fr8(&array[next], ntodo, scale, zero,
-                       (double *) buffer, status);
-                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
-                break;
-
-            case (TSTRING):  /* numerical column in an ASCII table */
-
-                if (cform[1] != 's')  /*  "%s" format is a string */
-                {
-                  ffi4fstr(&array[next], ntodo, scale, zero, cform,
-                          twidth, (char *) buffer, status);
-
-                  if (incre == twidth)    /* contiguous bytes */
-                     ffpbyt(fptr, ntodo * twidth, buffer, status);
-                  else
-                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                            status);
-
-                  break;
-                }
-                /* can't write to string column, so fall thru to default: */
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                     "Cannot write numbers to column %d which has format %s",
-                      colnum,tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-          sprintf(message,
-          "Error writing elements %.0f thru %.0f of input data array (ffpclj).",
-              (double) (next+1), (double) (next+ntodo));
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while writing FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcnj( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            long  *array,    /* I - array of values to write                */
-            long   nulvalue, /* I - value used to flag undefined pixels     */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels equal to the value of nulvalue will be replaced by the appropriate
-  null value in the output FITS file. 
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
-*/
-{
-    tcolumn *colptr;
-    LONGLONG  ngood = 0, nbad = 0, ii;
-    LONGLONG repeat, first, fstelm, fstrow;
-    int tcode, overflow = 0;
- 
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode  = colptr->tdatatype;
-
-    if (tcode > 0)
-       repeat = colptr->trepeat;  /* repeat count for this column */
-    else
-       repeat = firstelem -1 + nelem;  /* variable length arrays */
-
-    /* if variable length array, first write the whole input vector, 
-       then go back and fill in the nulls */
-    if (tcode < 0) {
-      if (ffpclj(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
-        if (*status == NUM_OVERFLOW) 
-	{
-	  /* ignore overflows, which are possibly the null pixel values */
-	  /*  overflow = 1;   */
-	  *status = 0;
-	} else { 
-          return(*status);
-	}
-      }
-    }
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (array[ii] != nulvalue)  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-	  
-            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-
-            nbad=0;
-         }
-
-         ngood = ngood + 1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (tcode > 0) {  /* variable length arrays have already been written */
-              if (ffpclj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0) {
-		if (*status == NUM_OVERFLOW) 
-		{
-		  overflow = 1;
-		  *status = 0;
-		} else { 
-                  return(*status);
-		}
-	      }
-	    }
-            ngood=0;
-         }
-
-         nbad = nbad +1;  /* the consecutive number of bad pixels */
-      }
-    }
-
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      if (tcode > 0) {  /* variable length arrays have already been written */
-        ffpclj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-      }
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-
-    if (*status <= 0) {
-      if (overflow) {
-        *status = NUM_OVERFLOW;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi4fi1(long *input,           /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            unsigned char *output, /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < 0)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (input[ii] > UCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (dvalue > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) (dvalue + .5);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi4fi2(long *input,       /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            short *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < SHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (input[ii] > SHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-                output[ii] = (short) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (short) (dvalue + .5);
-                else
-                    output[ii] = (short) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi4fi4(long *input,       /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            INT32BIT *output,  /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (INT32BIT) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (INT32BIT) (dvalue + .5);
-                else
-                    output[ii] = (INT32BIT) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fflongfi8(long *input,       /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            LONGLONG *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (dvalue > DLONGLONG_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (LONGLONG) (dvalue + .5);
-                else
-                    output[ii] = (LONGLONG) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi4fr4(long *input,       /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            float *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (float) ((input[ii] - zero) / scale);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi4fr8(long *input,       /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            double *output,    /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (input[ii] - zero) / scale;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi4fstr(long *input,      /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            char *cform,       /* I - format for output string values  */
-            long twidth,       /* I - width of each field, in chars    */
-            char *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-    char *cptr;
-
-    cptr = output;
-    
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-           sprintf(output, cform, (double) input[ii]);
-           output += twidth;
-
-           if (*output)  /* if this char != \0, then overflow occurred */
-              *status = OVERFLOW_ERR;
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-          dvalue = (input[ii] - zero) / scale;
-          sprintf(output, cform, dvalue);
-          output += twidth;
-
-          if (*output)  /* if this char != \0, then overflow occurred */
-            *status = OVERFLOW_ERR;
-        }
-    }
-
-    /* replace any commas with periods (e.g., in French locale) */
-    while ((cptr = strchr(cptr, ','))) *cptr = '.';
-
-    return(*status);
-}
-
-/* ======================================================================== */
-/*      the following routines support the 'long long' data type            */
-/* ======================================================================== */
-
-/*--------------------------------------------------------------------------*/
-int ffpprjj(fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            LONGLONG  *array, /* I - array of values that are written       */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        ffpmsg("writing to compressed image is not supported");
-
-        return(*status = DATA_COMPRESSION_ERR);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcljj(fptr, 2, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppnjj(fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            LONGLONG  *array, /* I - array of values that are written       */
-            LONGLONG  nulval,    /* I - undefined pixel value                   */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).  Any array values
-  that are equal to the value of nulval will be replaced with the null
-  pixel value that is appropriate for this column.
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        ffpmsg("writing to compressed image is not supported");
-
-        return(*status = DATA_COMPRESSION_ERR);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcnjj(fptr, 2, row, firstelem, nelem, array, nulval, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp2djj(fitsfile *fptr,  /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           LONGLONG  *array, /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-
-    /* call the 3D writing routine, with the 3rd dimension = 1 */
-
-    ffp3djj(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp3djj(fitsfile *fptr,  /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  nrows,      /* I - number of rows in each plane of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
-           LONGLONG  *array, /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 3-D cube of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    long tablerow, ii, jj;
-    LONGLONG nfits, narray;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        ffpmsg("writing to compressed image is not supported");
-
-        return(*status = DATA_COMPRESSION_ERR);
-    }
-
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-      /* all the image pixels are contiguous, so write all at once */
-      ffpcljj(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
-      return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to write to */
-    narray = 0;  /* next pixel in input array to be written */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* writing naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffpcljj(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
-         return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpssjj(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,      /* I - group to write(1 = 1st group)           */
-           long  naxis,      /* I - number of data axes in array            */
-           long  *naxes,     /* I - size of each FITS axis                  */
-           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
-           long  *lpixel,    /* I - last pixel in each axis to write        */
-           LONGLONG *array,  /* I - array to be written                     */
-           int  *status)     /* IO - error status                           */
-/*
-  Write a subsection of pixels to the primary array or image.
-  A subsection is defined to be any contiguous rectangular
-  array of pixels within the n-dimensional FITS data file.
-  Data conversion and scaling will be performed if necessary 
-  (e.g, if the datatype of the FITS array is not the same as
-  the array being written).
-*/
-{
-    long tablerow;
-    LONGLONG fpix[7], dimen[7], astart, pstart;
-    LONGLONG off2, off3, off4, off5, off6, off7;
-    LONGLONG st10, st20, st30, st40, st50, st60, st70;
-    LONGLONG st1, st2, st3, st4, st5, st6, st7;
-    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        ffpmsg("writing to compressed image is not supported");
-
-
-        return(*status = DATA_COMPRESSION_ERR);
-    }
-
-    if (naxis < 1 || naxis > 7)
-      return(*status = BAD_DIMEN);
-
-    tablerow=maxvalue(1,group);
-
-     /* calculate the size and number of loops to perform in each dimension */
-    for (ii = 0; ii < 7; ii++)
-    {
-      fpix[ii]=1;
-      irange[ii]=1;
-      dimen[ii]=1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {    
-      fpix[ii]=fpixel[ii];
-      irange[ii]=lpixel[ii]-fpixel[ii]+1;
-      dimen[ii]=naxes[ii];
-    }
-
-    i1=irange[0];
-
-    /* compute the pixel offset between each dimension */
-    off2 =     dimen[0];
-    off3 = off2 * dimen[1];
-    off4 = off3 * dimen[2];
-    off5 = off4 * dimen[3];
-    off6 = off5 * dimen[4];
-    off7 = off6 * dimen[5];
-
-    st10 = fpix[0];
-    st20 = (fpix[1] - 1) * off2;
-    st30 = (fpix[2] - 1) * off3;
-    st40 = (fpix[3] - 1) * off4;
-    st50 = (fpix[4] - 1) * off5;
-    st60 = (fpix[5] - 1) * off6;
-    st70 = (fpix[6] - 1) * off7;
-
-    /* store the initial offset in each dimension */
-    st1 = st10;
-    st2 = st20;
-    st3 = st30;
-    st4 = st40;
-    st5 = st50;
-    st6 = st60;
-    st7 = st70;
-
-    astart = 0;
-
-    for (i7 = 0; i7 < irange[6]; i7++)
-    {
-     for (i6 = 0; i6 < irange[5]; i6++)
-     {
-      for (i5 = 0; i5 < irange[4]; i5++)
-      {
-       for (i4 = 0; i4 < irange[3]; i4++)
-       {
-        for (i3 = 0; i3 < irange[2]; i3++)
-        {
-         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
-
-         for (i2 = 0; i2 < irange[1]; i2++)
-         {
-           if (ffpcljj(fptr, 2, tablerow, pstart, i1, &array[astart],
-              status) > 0)
-              return(*status);
-
-           astart += i1;
-           pstart += off2;
-         }
-         st2 = st20;
-         st3 = st3+off3;    
-        }
-        st3 = st30;
-        st4 = st4+off4;
-       }
-       st4 = st40;
-       st5 = st5+off5;
-      }
-      st5 = st50;
-      st6 = st6+off6;
-     }
-     st6 = st60;
-     st7 = st7+off7;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpgpjj(fitsfile *fptr,   /* I - FITS file pointer                      */
-            long  group,      /* I - group to write(1 = 1st group)          */
-            long  firstelem,  /* I - first vector element to write(1 = 1st) */
-            long  nelem,      /* I - number of values to write              */
-            LONGLONG  *array, /* I - array of values that are written       */
-            int  *status)     /* IO - error status                          */
-/*
-  Write an array of group parameters to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffpcljj(fptr, 1L, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcljj(fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            LONGLONG  *array, /* I - array of values to write               */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    int tcode, maxelem2, hdutype, writeraw;
-    long twidth, incre;
-    long  ntodo;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
-    double scale, zero;
-    char tform[20], cform[20];
-    char message[FLEN_ERRMSG];
-
-    char snull[20];   /*  the FITS null value  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-    maxelem = maxelem2;
-
-    if (tcode == TSTRING)   
-         ffcfmt(tform, cform);     /* derive C format for writing strings */
-
-    /*
-       if there is no scaling and the native machine format is not byteswapped
-       then we can simply write the raw data bytes into the FITS file if the
-       datatype of the FITS column is the same as the input values.  Otherwise
-       we must convert the raw values into the scaled and/or machine dependent
-       format in a temporary buffer that has been allocated for this purpose.
-    */
-    if (scale == 1. && zero == 0. && 
-       MACHINE == NATIVE && tcode == TLONGLONG)
-    {
-        writeraw = 1;
-        if (nelem < (LONGLONG)INT32_MAX/8) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/8;
-        }
-    }
-    else
-        writeraw = 0;
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
-    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
-    /*  TZEROn linear scaling parameters into a temporary buffer.          */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-        /* limit the number of pixels to process a one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TLONGLONG):
-              if (writeraw)
-              {
-                /* write raw input bytes without conversion */
-                ffpi8b(fptr, ntodo, incre, (long *) &array[next], status);
-              }
-              else
-              {
-                /* convert the raw data before writing to FITS file */
-                ffi8fi8(&array[next], ntodo, scale, zero,
-                        (LONGLONG *) buffer, status);
-                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
-              }
-
-              break;
-
-            case (TLONG):
-
-                ffi8fi4(&array[next], ntodo, scale, zero,
-                        (INT32BIT *) buffer, status);
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
-                break;
-
-            case (TBYTE):
- 
-                ffi8fi1(&array[next], ntodo, scale, zero,
-                        (unsigned char *) buffer, status);
-                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
-                break;
-
-            case (TSHORT):
-
-                ffi8fi2(&array[next], ntodo, scale, zero,
-                        (short *) buffer, status);
-                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
-                break;
-
-            case (TFLOAT):
-
-                ffi8fr4(&array[next], ntodo, scale, zero,
-                        (float *) buffer, status);
-                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
-                break;
-
-            case (TDOUBLE):
-                ffi8fr8(&array[next], ntodo, scale, zero,
-                       (double *) buffer, status);
-                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
-                break;
-
-            case (TSTRING):  /* numerical column in an ASCII table */
-
-                if (cform[1] != 's')  /*  "%s" format is a string */
-                {
-                  ffi8fstr(&array[next], ntodo, scale, zero, cform,
-                          twidth, (char *) buffer, status);
-
-                  if (incre == twidth)    /* contiguous bytes */
-                     ffpbyt(fptr, ntodo * twidth, buffer, status);
-                  else
-                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                            status);
-
-                  break;
-                }
-                /* can't write to string column, so fall thru to default: */
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                     "Cannot write numbers to column %d which has format %s",
-                      colnum,tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-          sprintf(message,
-          "Error writing elements %.0f thru %.0f of input data array (ffpclj).",
-              (double) (next+1), (double) (next+ntodo));
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while writing FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcnjj(fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            LONGLONG *array, /* I - array of values to write                */
-            LONGLONG nulvalue, /* I - value used to flag undefined pixels   */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels equal to the value of nulvalue will be replaced by the appropriate
-  null value in the output FITS file. 
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
-*/
-{
-    tcolumn *colptr;
-    LONGLONG  ngood = 0, nbad = 0, ii;
-    LONGLONG repeat, first, fstelm, fstrow;
-    int tcode, overflow = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode  = colptr->tdatatype;
-
-    if (tcode > 0)
-       repeat = colptr->trepeat;  /* repeat count for this column */
-    else
-       repeat = firstelem -1 + nelem;  /* variable length arrays */
-
-    /* if variable length array, first write the whole input vector, 
-       then go back and fill in the nulls */
-    if (tcode < 0) {
-      if (ffpcljj(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
-        if (*status == NUM_OVERFLOW) 
-	{
-	  /* ignore overflows, which are possibly the null pixel values */
-	  /*  overflow = 1;   */
-	  *status = 0;
-	} else { 
-          return(*status);
-	}
-      }
-    }
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (array[ii] != nulvalue)  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-
-            nbad=0;
-         }
-
-         ngood = ngood +1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (tcode > 0) {  /* variable length arrays have already been written */
-              if (ffpcljj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0) {
-		if (*status == NUM_OVERFLOW) 
-		{
-		  overflow = 1;
-		  *status = 0;
-		} else { 
-                  return(*status);
-		}
-	      }
-	    }
-            ngood=0;
-         }
-
-         nbad = nbad +1;  /* the consecutive number of bad pixels */
-      }
-    }
-
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      if (tcode > 0) {  /* variable length arrays have already been written */
-        ffpcljj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-      }
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-
-    if (*status <= 0) {
-      if (overflow) {
-        *status = NUM_OVERFLOW;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi8fi1(LONGLONG *input,       /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            unsigned char *output, /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < 0)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (input[ii] > UCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (dvalue > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) (dvalue + .5);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi8fi2(LONGLONG *input,   /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            short *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < SHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (input[ii] > SHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-                output[ii] = (short) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (short) (dvalue + .5);
-                else
-                    output[ii] = (short) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi8fi4(LONGLONG *input,   /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            INT32BIT *output,  /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < INT32_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (input[ii] > INT32_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-                output[ii] = (INT32BIT) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (INT32BIT) (dvalue + .5);
-                else
-                    output[ii] = (INT32BIT) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi8fi8(LONGLONG *input,   /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            LONGLONG *output,  /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (dvalue > DLONGLONG_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (LONGLONG) (dvalue + .5);
-                else
-                    output[ii] = (LONGLONG) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi8fr4(LONGLONG *input,   /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            float *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (float) ((input[ii] - zero) / scale);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi8fr8(LONGLONG *input,       /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            double *output,    /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (input[ii] - zero) / scale;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi8fstr(LONGLONG *input,  /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            char *cform,       /* I - format for output string values  */
-            long twidth,       /* I - width of each field, in chars    */
-            char *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-    char *cptr;
-    
-    cptr = output;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-           sprintf(output, cform, (double) input[ii]);
-           output += twidth;
-
-           if (*output)  /* if this char != \0, then overflow occurred */
-              *status = OVERFLOW_ERR;
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-          dvalue = (input[ii] - zero) / scale;
-          sprintf(output, cform, dvalue);
-          output += twidth;
-
-          if (*output)  /* if this char != \0, then overflow occurred */
-            *status = OVERFLOW_ERR;
-        }
-    }
-
-    /* replace any commas with periods (e.g., in French locale) */
-    while ((cptr = strchr(cptr, ','))) *cptr = '.';
-    
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcolk.c b/src/external/OpenGR/3rdparty/cfitsio/putcolk.c
deleted file mode 100644
index 1bab91f45..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcolk.c
+++ /dev/null
@@ -1,1017 +0,0 @@
-/*  This file, putcolk.c, contains routines that write data elements to    */
-/*  a FITS image or table, with 'int' datatype.                            */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffpprk( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            int   *array,    /* I - array of values that are written        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-    int nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_pixels(fptr, TINT, firstelem, nelem,
-            0, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpclk(fptr, 2, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppnk( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            int   *array,    /* I - array of values that are written        */
-            int   nulval,    /* I - undefined pixel value                   */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).  Any array values
-  that are equal to the value of nulval will be replaced with the null
-  pixel value that is appropriate for this column.
-*/
-{
-    long row;
-    int nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        nullvalue = nulval;  /* set local variable */
-        fits_write_compressed_pixels(fptr, TINT, firstelem, nelem,
-            1, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcnk(fptr, 2, row, firstelem, nelem, array, nulval, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp2dk(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           int   *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    /* call the 3D writing routine, with the 3rd dimension = 1 */
-
-    ffp3dk(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp3dk(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  nrows,      /* I - number of rows in each plane of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
-           int   *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 3-D cube of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    long tablerow, ii, jj;
-    long fpixel[3]= {1,1,1}, lpixel[3];
-    LONGLONG nfits, narray;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-           
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-        lpixel[0] = (long) ncols;
-        lpixel[1] = (long) nrows;
-        lpixel[2] = (long) naxis3;
-       
-        fits_write_compressed_img(fptr, TINT, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-      /* all the image pixels are contiguous, so write all at once */
-      ffpclk(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
-      return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to write to */
-    narray = 0;  /* next pixel in input array to be written */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* writing naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffpclk(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
-         return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpssk(fitsfile *fptr,   /* I - FITS file pointer                       */
-           long  group,      /* I - group to write(1 = 1st group)           */
-           long  naxis,      /* I - number of data axes in array            */
-           long  *naxes,     /* I - size of each FITS axis                  */
-           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
-           long  *lpixel,    /* I - last pixel in each axis to write        */
-           int *array,      /* I - array to be written                     */
-           int  *status)     /* IO - error status                           */
-/*
-  Write a subsection of pixels to the primary array or image.
-  A subsection is defined to be any contiguous rectangular
-  array of pixels within the n-dimensional FITS data file.
-  Data conversion and scaling will be performed if necessary 
-  (e.g, if the datatype of the FITS array is not the same as
-  the array being written).
-*/
-{
-    long tablerow;
-    LONGLONG fpix[7], dimen[7], astart, pstart;
-    LONGLONG off2, off3, off4, off5, off6, off7;
-    LONGLONG st10, st20, st30, st40, st50, st60, st70;
-    LONGLONG st1, st2, st3, st4, st5, st6, st7;
-    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_img(fptr, TINT, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    if (naxis < 1 || naxis > 7)
-      return(*status = BAD_DIMEN);
-
-    tablerow=maxvalue(1,group);
-
-     /* calculate the size and number of loops to perform in each dimension */
-    for (ii = 0; ii < 7; ii++)
-    {
-      fpix[ii]=1;
-      irange[ii]=1;
-      dimen[ii]=1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {    
-      fpix[ii]=fpixel[ii];
-      irange[ii]=lpixel[ii]-fpixel[ii]+1;
-      dimen[ii]=naxes[ii];
-    }
-
-    i1=irange[0];
-
-    /* compute the pixel offset between each dimension */
-    off2 =     dimen[0];
-    off3 = off2 * dimen[1];
-    off4 = off3 * dimen[2];
-    off5 = off4 * dimen[3];
-    off6 = off5 * dimen[4];
-    off7 = off6 * dimen[5];
-
-    st10 = fpix[0];
-    st20 = (fpix[1] - 1) * off2;
-    st30 = (fpix[2] - 1) * off3;
-    st40 = (fpix[3] - 1) * off4;
-    st50 = (fpix[4] - 1) * off5;
-    st60 = (fpix[5] - 1) * off6;
-    st70 = (fpix[6] - 1) * off7;
-
-    /* store the initial offset in each dimension */
-    st1 = st10;
-    st2 = st20;
-    st3 = st30;
-    st4 = st40;
-    st5 = st50;
-    st6 = st60;
-    st7 = st70;
-
-    astart = 0;
-
-    for (i7 = 0; i7 < irange[6]; i7++)
-    {
-     for (i6 = 0; i6 < irange[5]; i6++)
-     {
-      for (i5 = 0; i5 < irange[4]; i5++)
-      {
-       for (i4 = 0; i4 < irange[3]; i4++)
-       {
-        for (i3 = 0; i3 < irange[2]; i3++)
-        {
-         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
-
-         for (i2 = 0; i2 < irange[1]; i2++)
-         {
-           if (ffpclk(fptr, 2, tablerow, pstart, i1, &array[astart],
-              status) > 0)
-              return(*status);
-
-           astart += i1;
-           pstart += off2;
-         }
-         st2 = st20;
-         st3 = st3+off3;    
-        }
-        st3 = st30;
-        st4 = st4+off4;
-       }
-       st4 = st40;
-       st5 = st5+off5;
-      }
-      st5 = st50;
-      st6 = st6+off6;
-     }
-     st6 = st60;
-     st7 = st7+off7;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpgpk( fitsfile *fptr,   /* I - FITS file pointer                      */
-            long  group,      /* I - group to write(1 = 1st group)          */
-            long  firstelem,  /* I - first vector element to write(1 = 1st) */
-            long  nelem,      /* I - number of values to write              */
-            int   *array,     /* I - array of values that are written       */
-            int  *status)     /* IO - error status                          */
-/*
-  Write an array of group parameters to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffpclk(fptr, 1L, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpclk( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            int   *array,    /* I - array of values to write                */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    int tcode, maxelem2, hdutype, writeraw;
-    long twidth, incre;
-    long ntodo;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
-    double scale, zero;
-    char tform[20], cform[20];
-    char message[FLEN_ERRMSG];
-
-    char snull[20];   /*  the FITS null value  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* call the 'short' or 'long' version of this routine, if possible */
-    if (sizeof(int) == sizeof(short))
-        ffpcli(fptr, colnum, firstrow, firstelem, nelem, 
-              (short *) array, status);
-    else if (sizeof(int) == sizeof(long))
-        ffpclj(fptr, colnum, firstrow, firstelem, nelem, 
-              (long *) array, status);
-    else
-    {
-    /*
-      This is a special case: sizeof(int) is not equal to sizeof(short) or
-      sizeof(long).  This occurs on Alpha OSF systems where short = 2 bytes,
-      int = 4 bytes, and long = 8 bytes.
-    */
-
-    buffer = cbuff;
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-    maxelem = maxelem2;
-
-    if (tcode == TSTRING)   
-         ffcfmt(tform, cform);     /* derive C format for writing strings */
-
-    /*
-       if there is no scaling and the native machine format is not byteswapped
-       then we can simply write the raw data bytes into the FITS file if the
-       datatype of the FITS column is the same as the input values.  Otherwise
-       we must convert the raw values into the scaled and/or machine dependent
-       format in a temporary buffer that has been allocated for this purpose.
-    */
-    if (scale == 1. && zero == 0. && 
-       MACHINE == NATIVE && tcode == TLONG)
-    {
-        writeraw = 1;
-        if (nelem < (LONGLONG)INT32_MAX) {
-            maxelem = nelem;
-        } else {
-            maxelem = INT32_MAX/4;
-        }
-    }
-    else
-        writeraw = 0;
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
-    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
-    /*  TZEROn linear scaling parameters into a temporary buffer.          */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-        /* limit the number of pixels to process a one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TLONG):
-              if (writeraw)
-              {
-                /* write raw input bytes without conversion */
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) &array[next], status);
-              }
-              else
-              {
-                /* convert the raw data before writing to FITS file */
-                ffintfi4(&array[next], ntodo, scale, zero,
-                        (INT32BIT *) buffer, status);
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
-              }
-
-                break;
-
-            case (TLONGLONG):
-
-                ffintfi8(&array[next], ntodo, scale, zero,
-                        (LONGLONG *) buffer, status);
-                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
-                break;
-
-            case (TBYTE):
- 
-                ffintfi1(&array[next], ntodo, scale, zero,
-                        (unsigned char *) buffer, status);
-                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
-                break;
-
-            case (TSHORT):
-
-                ffintfi2(&array[next], ntodo, scale, zero,
-                        (short *) buffer, status);
-                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
-                break;
-
-            case (TFLOAT):
-
-                ffintfr4(&array[next], ntodo, scale, zero,
-                        (float *) buffer, status);
-                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
-                break;
-
-            case (TDOUBLE):
-                ffintfr8(&array[next], ntodo, scale, zero,
-                       (double *) buffer, status);
-                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
-                break;
-
-            case (TSTRING):  /* numerical column in an ASCII table */
-
-                if (cform[1] != 's')  /*  "%s" format is a string */
-                {
-                  ffintfstr(&array[next], ntodo, scale, zero, cform,
-                          twidth, (char *) buffer, status);
-
-                  if (incre == twidth)    /* contiguous bytes */
-                     ffpbyt(fptr, ntodo * twidth, buffer, status);
-                  else
-                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                            status);
-
-                  break;
-                }
-                /* can't write to string column, so fall thru to default: */
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                     "Cannot write numbers to column %d which has format %s",
-                      colnum,tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-          sprintf(message,
-          "Error writing elements %.0f thru %.0f of input data array (ffpclk).",
-              (double) (next+1), (double) (next+ntodo));
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while writing FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    }   /* end of Dec ALPHA special case */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcnk( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            int   *array,    /* I - array of values to write                */
-            int    nulvalue, /* I - value used to flag undefined pixels     */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels equal to the value of nulvalue will be replaced by the appropriate
-  null value in the output FITS file. 
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
-*/
-{
-    tcolumn *colptr;
-    LONGLONG  ngood = 0, nbad = 0, ii;
-    LONGLONG repeat, first, fstelm, fstrow;
-    int tcode, overflow = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode  = colptr->tdatatype;
-
-    if (tcode > 0)
-       repeat = colptr->trepeat;  /* repeat count for this column */
-    else
-       repeat = firstelem -1 + nelem;  /* variable length arrays */
-
-    /* if variable length array, first write the whole input vector, 
-       then go back and fill in the nulls */
-    if (tcode < 0) {
-      if (ffpclk(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
-        if (*status == NUM_OVERFLOW) 
-	{
-	  /* ignore overflows, which are possibly the null pixel values */
-	  /*  overflow = 1;   */
-	  *status = 0;
-	} else { 
-          return(*status);
-	}
-      }
-    }
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (array[ii] != nulvalue)  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-
-            nbad=0;
-         }
-
-         ngood = ngood +1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (tcode > 0) {  /* variable length arrays have already been written */
-              if (ffpclk(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0)  {
-		if (*status == NUM_OVERFLOW) 
-		{
-		  overflow = 1;
-		  *status = 0;
-		} else { 
-                  return(*status);
-		}
-	      }
-	    }
-            ngood=0;
-         }
-
-         nbad = nbad +1;  /* the consecutive number of bad pixels */
-      }
-    }
-
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      if (tcode > 0) {  /* variable length arrays have already been written */
-        ffpclk(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-      }
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-
-    if (*status <= 0) {
-      if (overflow) {
-        *status = NUM_OVERFLOW;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffintfi1(int *input,           /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            unsigned char *output, /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < 0)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (input[ii] > UCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (dvalue > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) (dvalue + .5);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffintfi2(int *input,       /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            short *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < SHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (input[ii] > SHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-                output[ii] = input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (short) (dvalue + .5);
-                else
-                    output[ii] = (short) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffintfi4(int *input,       /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            INT32BIT *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)  
-    {       
-        memcpy(output, input, ntodo * sizeof(int) );
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (INT32BIT) (dvalue + .5);
-                else
-                    output[ii] = (INT32BIT) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffintfi8(int *input,  /* I - array of values to be converted  */
-            long ntodo,             /* I - number of elements in the array  */
-            double scale,           /* I - FITS TSCALn or BSCALE value      */
-            double zero,            /* I - FITS TZEROn or BZERO  value      */
-            LONGLONG *output,       /* O - output array of converted values */
-            int *status)            /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (dvalue > DLONGLONG_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (LONGLONG) (dvalue + .5);
-                else
-                    output[ii] = (LONGLONG) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffintfr4(int *input,       /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            float *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (float) ((input[ii] - zero) / scale);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffintfr8(int *input,       /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            double *output,    /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (input[ii] - zero) / scale;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffintfstr(int *input,      /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            char *cform,       /* I - format for output string values  */
-            long twidth,       /* I - width of each field, in chars    */
-            char *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-    char *cptr;
-    
-    cptr = output;
-
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-           sprintf(output, cform, (double) input[ii]);
-           output += twidth;
-
-           if (*output)  /* if this char != \0, then overflow occurred */
-              *status = OVERFLOW_ERR;
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-          dvalue = (input[ii] - zero) / scale;
-          sprintf(output, cform, dvalue);
-          output += twidth;
-
-          if (*output)  /* if this char != \0, then overflow occurred */
-            *status = OVERFLOW_ERR;
-        }
-    }
-
-    /* replace any commas with periods (e.g., in French locale) */
-    while ((cptr = strchr(cptr, ','))) *cptr = '.';
-    
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcoll.c b/src/external/OpenGR/3rdparty/cfitsio/putcoll.c
deleted file mode 100644
index f593755b2..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcoll.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/*  This file, putcoll.c, contains routines that write data elements to    */
-/*  a FITS image or table, with logical datatype.                          */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffpcll( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            char *array,     /* I - array of values to write                */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of logical values to a column in the current FITS HDU.
-*/
-{
-    int tcode, maxelem, hdutype;
-    long twidth, incre;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
-    double scale, zero;
-    char tform[20], ctrue = 'T', cfalse = 'F';
-    char message[FLEN_ERRMSG];
-    char snull[20];   /*  the FITS null value  */
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-
-    if (tcode != TLOGICAL)   
-        return(*status = NOT_LOGICAL_COL);
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the logical values one at a time to the FITS column.     */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-      wrtptr = startpos + (rowlen * rownum) + (elemnum * incre);
-
-      ffmbyt(fptr, wrtptr, IGNORE_EOF, status);  /* move to write position */
-
-      if (array[next])
-         ffpbyt(fptr, 1, &ctrue, status);
-      else
-         ffpbyt(fptr, 1, &cfalse, status);
-
-      if (*status > 0)  /* test for error during previous write operation */
-      {
-        sprintf(message,
-           "Error writing element %.0f of input array of logicals (ffpcll).",
-            (double) (next+1));
-        ffpmsg(message);
-        return(*status);
-      }
-
-      /*--------------------------------------------*/
-      /*  increment the counters for the next loop  */
-      /*--------------------------------------------*/
-      remain--;
-      if (remain)
-      {
-        next++;
-        elemnum++;
-        if (elemnum == repeat)  /* completed a row; start on next row */
-        {
-           elemnum = 0;
-           rownum++;
-        }
-      }
-
-    }  /*  End of main while Loop  */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcnl( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            char  *array,    /* I - array of values to write                */
-            char  nulvalue,  /* I - array flagging undefined pixels if true */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels flagged as null will be replaced by the appropriate
-  null value in the output FITS file. 
-*/
-{
-    tcolumn *colptr;
-    LONGLONG  ngood = 0, nbad = 0, ii;
-    LONGLONG repeat, first, fstelm, fstrow;
-    int tcode;
-
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode  = colptr->tdatatype;
-
-    if (tcode > 0)
-       repeat = colptr->trepeat;  /* repeat count for this column */
-    else
-       repeat = firstelem -1 + nelem;  /* variable length arrays */
-
-    /* first write the whole input vector, then go back and fill in the nulls */
-    if (ffpcll(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0)
-          return(*status);
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (array[ii] != nulvalue)  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-
-            nbad=0;
-         }
-
-         ngood = ngood +1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-/*  good values have already been written
-            if (ffpcll(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0)
-                return(*status);
-*/
-            ngood=0;
-         }
-
-         nbad = nbad +1;  /* the consecutive number of bad pixels */
-      }
-    }
-
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-/*  these have already been written
-      ffpcll(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-*/
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpclx( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  frow,      /* I - first row to write (1 = 1st row)        */
-            long  fbit,      /* I - first bit to write (1 = 1st)            */
-            long  nbit,      /* I - number of bits to write                 */
-            char *larray,    /* I - array of logicals corresponding to bits */
-            int  *status)    /* IO - error status                           */
-/*
-  write an array of logical values to a specified bit or byte
-  column of the binary table.   If larray is TRUE, then the corresponding
-  bit is set to 1, otherwise it is set to 0.
-  The binary table column being written to must have datatype 'B' or 'X'. 
-*/
-{
-    LONGLONG offset, bstart, repeat, rowlen, elemnum, rstart, estart, tnull;
-    long fbyte, lbyte, nbyte, bitloc, ndone;
-    long ii, twidth, incre;
-    int tcode, descrp, maxelem, hdutype;
-    double dummyd;
-    char tform[12], snull[12];
-    unsigned char cbuff;
-    static unsigned char onbit[8] = {128,  64,  32,  16,   8,   4,   2,   1};
-    static unsigned char offbit[8] = {127, 191, 223, 239, 247, 251, 253, 254};
-    LONGLONG heapoffset, lrepeat;
-    tcolumn *colptr;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /*  check input parameters */
-    if (nbit < 1)
-        return(*status);
-    else if (frow < 1)
-        return(*status = BAD_ROW_NUM);
-    else if (fbit < 1)
-        return(*status = BAD_ELEM_NUM);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    /* rescan header if data structure is undefined */
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-        if ( ffrdef(fptr, status) > 0)               
-            return(*status);
-
-    fbyte = (fbit + 7) / 8;
-    lbyte = (fbit + nbit + 6) / 8;
-    nbyte = lbyte - fbyte +1;
-
-    /* Save the current heapsize; ffgcprll will increment the value if */
-    /* we are writing to a variable length column. */
-    offset = (fptr->Fptr)->heapsize;
-
-    /* call ffgcprll in case we are writing beyond the current end of   */
-    /* the table; it will allocate more space and shift any following */
-    /* HDU's.  Otherwise, we have little use for most of the returned */
-    /* parameters, therefore just use dummy parameters.               */
-
-    if (ffgcprll( fptr, colnum, frow, fbyte, nbyte, 1, &dummyd, &dummyd,
-        tform, &twidth, &tcode, &maxelem, &bstart, &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-
-    bitloc = fbit - 1 - ((fbit - 1) / 8 * 8);
-    ndone = 0;
-    rstart = frow - 1;
-    estart = fbyte - 1;
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode = colptr->tdatatype;
-
-    if (abs(tcode) > TBYTE)
-        return(*status = NOT_LOGICAL_COL); /* not correct datatype column */
-
-    if (tcode > 0)
-    {
-        descrp = FALSE;  /* not a variable length descriptor column */
-        repeat = colptr->trepeat;
-
-        if (tcode == TBIT)
-            repeat = (repeat + 7) / 8; /* convert from bits to bytes */
-
-        if (fbyte > repeat)
-            return(*status = BAD_ELEM_NUM);
-
-        /* calc the i/o pointer location to start of sequence of pixels */
-        bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) +
-               colptr->tbcol + estart;
-    }
-    else
-    {
-        descrp = TRUE;  /* a variable length descriptor column */
-        /* only bit arrays (tform = 'X') are supported for variable */
-        /* length arrays.  REPEAT is the number of BITS in the array. */
-
-        repeat = fbit + nbit -1;
-
-        /* write the number of elements and the starting offset.    */
-        /* Note: ffgcprll previous wrote the descripter, but with the */
-        /* wrong repeat value  (gave bytes instead of bits).        */
-        /* Make sure to not change the current heap offset value!  */
-
-        if (tcode == -TBIT) {
-            ffgdesll(fptr, colnum, frow, &lrepeat, &heapoffset, status);
-            ffpdes(  fptr, colnum, frow, (long) repeat, heapoffset, status);
-	}
-
-        /* Calc the i/o pointer location to start of sequence of pixels.   */
-        /* ffgcprll has already calculated a value for bstart that         */
-        /* points to the first element of the vector; we just have to      */
-        /* increment it to point to the first element we want to write to. */
-        /* Note: ffgcprll also already updated the size of the heap, so we */
-        /* don't have to do that again here.                               */
-
-        bstart += estart;
-    }
-
-    /* move the i/o pointer to the start of the pixel sequence */
-    ffmbyt(fptr, bstart, IGNORE_EOF, status);
-
-    /* read the next byte (we may only be modifying some of the bits) */
-    while (1)
-    {
-      if (ffgbyt(fptr, 1, &cbuff, status) == END_OF_FILE)
-      {
-        /* hit end of file trying to read the byte, so just set byte = 0 */
-        *status = 0;
-        cbuff = 0;
-      }
-
-      /* move back, to be able to overwrite the byte */
-      ffmbyt(fptr, bstart, IGNORE_EOF, status);
- 
-      for (ii = bitloc; (ii < 8) && (ndone < nbit); ii++, ndone++)
-      {
-        if(larray[ndone])
-          cbuff = cbuff | onbit[ii];
-        else
-          cbuff = cbuff & offbit[ii];
-      }
-
-      ffpbyt(fptr, 1, &cbuff, status); /* write the modified byte */
-      if (ndone == nbit)  /* finished all the bits */
-        return(*status);
-
-      /* not done, so get the next byte */
-      bstart++;
-      if (!descrp)
-      {
-        estart++;
-        if (estart == repeat)
-        {
-          /* move the i/o pointer to the next row of pixels */
-          estart = 0;
-          rstart = rstart + 1;
-          bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) +
-               colptr->tbcol;
-
-          ffmbyt(fptr, bstart, IGNORE_EOF, status);
-        }
-      }
-      bitloc = 0;
-    }
-}
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcols.c b/src/external/OpenGR/3rdparty/cfitsio/putcols.c
deleted file mode 100644
index 67393c8c1..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcols.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*  This file, putcols.c, contains routines that write data elements to    */
-/*  a FITS image or table, of type character string.                       */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include "fitsio2.h"
-/*--------------------------------------------------------------------------*/
-int ffpcls( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of strings to write              */
-            char  **array,   /* I - array of pointers to strings            */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of string values to a column in the current FITS HDU.
-*/
-{
-    int tcode, maxelem, hdutype, nchar;
-    long twidth, incre;
-    long ii, jj, ntodo;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
-    double scale, zero;
-    char tform[20], *blanks;
-    char message[FLEN_ERRMSG];
-    char snull[20];   /*  the FITS null value  */
-    tcolumn *colptr;
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    char *buffer, *arrayptr;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
-    {
-        sprintf(message, "Specified column number is out of range: %d",
-                colnum);
-        ffpmsg(message);
-        return(*status = BAD_COL_NUM);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-    tcode = colptr->tdatatype;
-
-    if (tcode == -TSTRING) /* variable length column in a binary table? */
-    {
-      /* only write a single string; ignore value of firstelem */
-      nchar = maxvalue(1,strlen(array[0])); /* will write at least 1 char */
-                                          /* even if input string is null */
-
-      if (ffgcprll( fptr, colnum, firstrow, 1, nchar, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-	
-      /* simply move to write position, then write the string */
-      ffmbyt(fptr, startpos, IGNORE_EOF, status); 
-      ffpbyt(fptr, nchar, array[0], status);
-
-      if (*status > 0)  /* test for error during previous write operation */
-      {
-         sprintf(message,
-          "Error writing to variable length string column (ffpcls).");
-         ffpmsg(message);
-      }
-
-      return(*status);
-    }
-    else if (tcode == TSTRING)
-    {
-      if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-
-      /* if string length is greater than a FITS block (2880 char) then must */
-      /* only write 1 string at a time, to force writein by ffpbyt instead of */
-      /* ffpbytoff (ffpbytoff can't handle this case) */
-      if (twidth > IOBUFLEN) {
-        maxelem = 1;
-        incre = twidth;
-        repeat = 1;
-      }   
-
-      blanks = (char *) malloc(twidth); /* string for blank fill values */
-      if (!blanks)
-      {
-        ffpmsg("Could not allocate memory for string (ffpcls)");
-        return(*status = ARRAY_TOO_BIG);
-      }
-
-      for (ii = 0; ii < twidth; ii++)
-          blanks[ii] = ' ';          /* fill string with blanks */
-
-      remain = nelem;           /* remaining number of values to write  */
-    }
-    else 
-      return(*status = NOT_ASCII_COL);
- 
-    /*-------------------------------------------------------*/
-    /*  Now write the strings to the FITS column.            */
-    /*-------------------------------------------------------*/
-
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-      /* limit the number of pixels to process at one time to the number that
-         will fit in the buffer space or to the number of pixels that remain
-         in the current vector, which ever is smaller.
-      */
-      ntodo = (long) minvalue(remain, maxelem);      
-      ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-      wrtptr = startpos + (rownum * rowlen) + (elemnum * incre);
-      ffmbyt(fptr, wrtptr, IGNORE_EOF, status);  /* move to write position */
-
-      buffer = (char *) cbuff;
-
-      /* copy the user's strings into the buffer */
-      for (ii = 0; ii < ntodo; ii++)
-      {
-         arrayptr = array[next];
-
-         for (jj = 0; jj < twidth; jj++)  /*  copy the string, char by char */
-         {
-            if (*arrayptr)
-            {
-              *buffer = *arrayptr;
-              buffer++;
-              arrayptr++;
-            }
-            else
-              break;
-         }
-
-         for (;jj < twidth; jj++)    /* fill field with blanks, if needed */
-         {
-           *buffer = ' ';
-           buffer++;
-         }
-
-         next++;
-      }
-
-      /* write the buffer full of strings to the FITS file */
-      if (incre == twidth)
-         ffpbyt(fptr, ntodo * twidth, cbuff, status);
-      else
-         ffpbytoff(fptr, twidth, ntodo, incre - twidth, cbuff, status);
-
-      if (*status > 0)  /* test for error during previous write operation */
-      {
-         sprintf(message,
-          "Error writing elements %.0f thru %.0f of input data array (ffpcls).",
-             (double) (next+1), (double) (next+ntodo));
-         ffpmsg(message);
-
-         if (blanks)
-           free(blanks);
-
-         return(*status);
-      }
-
-      /*--------------------------------------------*/
-      /*  increment the counters for the next loop  */
-      /*--------------------------------------------*/
-      remain -= ntodo;
-      if (remain)
-      {
-          elemnum += ntodo;
-          if (elemnum == repeat)  /* completed a row; start on next row */
-          {
-              elemnum = 0;
-              rownum++;
-          }
-       }
-    }  /*  End of main while Loop  */
-
-    if (blanks)
-      free(blanks);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcns( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            char  **array,   /* I - array of values to write                */
-            char  *nulvalue, /* I - string representing a null value        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels flagged as null will be replaced by the appropriate
-  null value in the output FITS file. 
-*/
-{
-    long repeat, width;
-    LONGLONG ngood = 0, nbad = 0, ii;
-    LONGLONG first, fstelm, fstrow;
-
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    /* get the vector repeat length of the column */
-    ffgtcl(fptr, colnum, NULL, &repeat, &width, status);
-
-    if ((fptr->Fptr)->hdutype == BINARY_TBL)
-        repeat = repeat / width;    /* convert from chars to unit strings */
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (strcmp(nulvalue, array[ii]))  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-            nbad=0;
-         }
-
-         ngood = ngood +1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (ffpcls(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0)
-                return(*status);
-
-            ngood=0;
-         }
-
-         nbad = nbad +1;  /* the consecutive number of bad pixels */
-      }
-    }
-
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      ffpcls(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcolsb.c b/src/external/OpenGR/3rdparty/cfitsio/putcolsb.c
deleted file mode 100644
index b877dc483..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcolsb.c
+++ /dev/null
@@ -1,974 +0,0 @@
-/*  This file, putcolsb.c, contains routines that write data elements to   */
-/*  a FITS image or table with signed char (signed byte) datatype.         */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffpprsb( fitsfile *fptr,  /* I - FITS file pointer                      */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            signed char *array, /* I - array of values that are written     */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-    signed char nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_pixels(fptr, TSBYTE, firstelem, nelem,
-            0, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpclsb(fptr, 2, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppnsb( fitsfile *fptr,  /* I - FITS file pointer                      */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            signed char *array, /* I - array of values that are written     */
-            signed char nulval, /* I - undefined pixel value                */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).  Any array values
-  that are equal to the value of nulval will be replaced with the null
-  pixel value that is appropriate for this column.
-*/
-{
-    long row;
-    signed char nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        nullvalue = nulval;  /* set local variable */
-        fits_write_compressed_pixels(fptr, TSBYTE, firstelem, nelem,
-            1, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcnsb(fptr, 2, row, firstelem, nelem, array, nulval, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp2dsb(fitsfile *fptr,   /* I - FITS file pointer                    */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           signed char *array, /* I - array to be written                 */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    /* call the 3D writing routine, with the 3rd dimension = 1 */
-
-    ffp3dsb(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp3dsb(fitsfile *fptr,   /* I - FITS file pointer                    */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  nrows,      /* I - number of rows in each plane of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
-           signed char *array, /* I - array to be written                 */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 3-D cube of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    long tablerow, ii, jj;
-    long fpixel[3]= {1,1,1}, lpixel[3];
-    LONGLONG nfits, narray;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-           
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-        lpixel[0] = (long) ncols;
-        lpixel[1] = (long) nrows;
-        lpixel[2] = (long) naxis3;
-       
-        fits_write_compressed_img(fptr, TSBYTE, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-      /* all the image pixels are contiguous, so write all at once */
-      ffpclsb(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
-      return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to write to */
-    narray = 0;  /* next pixel in input array to be written */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* writing naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffpclsb(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
-         return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpsssb(fitsfile *fptr,   /* I - FITS file pointer                      */
-           long  group,      /* I - group to write(1 = 1st group)           */
-           long  naxis,      /* I - number of data axes in array            */
-           long  *naxes,     /* I - size of each FITS axis                  */
-           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
-           long  *lpixel,    /* I - last pixel in each axis to write        */
-           signed char *array, /* I - array to be written                   */
-           int  *status)     /* IO - error status                           */
-/*
-  Write a subsection of pixels to the primary array or image.
-  A subsection is defined to be any contiguous rectangular
-  array of pixels within the n-dimensional FITS data file.
-  Data conversion and scaling will be performed if necessary 
-  (e.g, if the datatype of the FITS array is not the same as
-  the array being written).
-*/
-{
-    long tablerow;
-    LONGLONG fpix[7], dimen[7], astart, pstart;
-    LONGLONG off2, off3, off4, off5, off6, off7;
-    LONGLONG st10, st20, st30, st40, st50, st60, st70;
-    LONGLONG st1, st2, st3, st4, st5, st6, st7;
-    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_img(fptr, TSBYTE, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    if (naxis < 1 || naxis > 7)
-      return(*status = BAD_DIMEN);
-
-    tablerow=maxvalue(1,group);
-
-     /* calculate the size and number of loops to perform in each dimension */
-    for (ii = 0; ii < 7; ii++)
-    {
-      fpix[ii]=1;
-      irange[ii]=1;
-      dimen[ii]=1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {    
-      fpix[ii]=fpixel[ii];
-      irange[ii]=lpixel[ii]-fpixel[ii]+1;
-      dimen[ii]=naxes[ii];
-    }
-
-    i1=irange[0];
-
-    /* compute the pixel offset between each dimension */
-    off2 =     dimen[0];
-    off3 = off2 * dimen[1];
-    off4 = off3 * dimen[2];
-    off5 = off4 * dimen[3];
-    off6 = off5 * dimen[4];
-    off7 = off6 * dimen[5];
-
-    st10 = fpix[0];
-    st20 = (fpix[1] - 1) * off2;
-    st30 = (fpix[2] - 1) * off3;
-    st40 = (fpix[3] - 1) * off4;
-    st50 = (fpix[4] - 1) * off5;
-    st60 = (fpix[5] - 1) * off6;
-    st70 = (fpix[6] - 1) * off7;
-
-    /* store the initial offset in each dimension */
-    st1 = st10;
-    st2 = st20;
-    st3 = st30;
-    st4 = st40;
-    st5 = st50;
-    st6 = st60;
-    st7 = st70;
-
-    astart = 0;
-
-    for (i7 = 0; i7 < irange[6]; i7++)
-    {
-     for (i6 = 0; i6 < irange[5]; i6++)
-     {
-      for (i5 = 0; i5 < irange[4]; i5++)
-      {
-       for (i4 = 0; i4 < irange[3]; i4++)
-       {
-        for (i3 = 0; i3 < irange[2]; i3++)
-        {
-         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
-
-         for (i2 = 0; i2 < irange[1]; i2++)
-         {
-           if (ffpclsb(fptr, 2, tablerow, pstart, i1, &array[astart],
-              status) > 0)
-              return(*status);
-
-           astart += i1;
-           pstart += off2;
-         }
-         st2 = st20;
-         st3 = st3+off3;    
-        }
-        st3 = st30;
-        st4 = st4+off4;
-       }
-       st4 = st40;
-       st5 = st5+off5;
-      }
-      st5 = st50;
-      st6 = st6+off6;
-     }
-     st6 = st60;
-     st7 = st7+off7;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpgpsb( fitsfile *fptr,   /* I - FITS file pointer                     */
-            long  group,      /* I - group to write(1 = 1st group)          */
-            long  firstelem,  /* I - first vector element to write(1 = 1st) */
-            long  nelem,      /* I - number of values to write              */
-            signed char *array, /* I - array of values that are written     */
-            int  *status)     /* IO - error status                          */
-/*
-  Write an array of group parameters to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffpclsb(fptr, 1L, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpclsb( fitsfile *fptr,  /* I - FITS file pointer                      */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            signed char *array, /* I - array of values to write             */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table with
-  2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    int tcode, maxelem, hdutype;
-    long twidth, incre;
-    long ntodo;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
-    double scale, zero;
-    char tform[20], cform[20];
-    char message[FLEN_ERRMSG];
-
-    char snull[20];   /*  the FITS null value  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-
-    if (tcode == TSTRING)   
-         ffcfmt(tform, cform);     /* derive C format for writing strings */
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
-    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
-    /*  TZEROn linear scaling parameters into a temporary buffer.          */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-        /* limit the number of pixels to process a one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TBYTE):
-
-                /* convert the raw data before writing to FITS file */
-                ffs1fi1(&array[next], ntodo, scale, zero,
-                        (unsigned char *) buffer, status);
-                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
-
-              break;
-
-            case (TLONGLONG):
-
-                ffs1fi8(&array[next], ntodo, scale, zero,
-                        (LONGLONG *) buffer, status);
-                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
-                break;
-
-            case (TSHORT):
- 
-                ffs1fi2(&array[next], ntodo, scale, zero,
-                        (short *) buffer, status);
-                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
-                break;
-
-            case (TLONG):
-
-                ffs1fi4(&array[next], ntodo, scale, zero,
-                        (INT32BIT *) buffer, status);
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
-                break;
-
-            case (TFLOAT):
-
-                ffs1fr4(&array[next], ntodo, scale, zero,
-                        (float *)  buffer, status);
-                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
-                break;
-
-            case (TDOUBLE):
-                ffs1fr8(&array[next], ntodo, scale, zero,
-                        (double *) buffer, status);
-                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
-                break;
-
-            case (TSTRING):  /* numerical column in an ASCII table */
-
-                if (strchr(tform,'A'))
-                {
-                    /* write raw input bytes without conversion        */
-                    /* This case is a hack to let users write a stream */
-                    /* of bytes directly to the 'A' format column      */
-
-                    if (incre == twidth)
-                        ffpbyt(fptr, ntodo, &array[next], status);
-                    else
-                        ffpbytoff(fptr, twidth, ntodo/twidth, incre - twidth, 
-                                &array[next], status);
-                    break;
-                }
-                else if (cform[1] != 's')  /*  "%s" format is a string */
-                {
-                  ffs1fstr(&array[next], ntodo, scale, zero, cform,
-                          twidth, (char *) buffer, status);
-
-                  if (incre == twidth)    /* contiguous bytes */
-                     ffpbyt(fptr, ntodo * twidth, buffer, status);
-                  else
-                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                            status);
-                  break;
-                }
-                /* can't write to string column, so fall thru to default: */
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                       "Cannot write numbers to column %d which has format %s",
-                        colnum,tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-          sprintf(message,
-          "Error writing elements %.0f thru %.0f of input data array (ffpclsb).",
-              (double) (next+1), (double) (next+ntodo));
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-      ffpmsg(
-      "Numerical overflow during type conversion while writing FITS data.");
-      *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcnsb( fitsfile *fptr,  /* I - FITS file pointer                      */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            signed char *array,   /* I - array of values to write           */
-            signed char nulvalue, /* I - flag for undefined pixels          */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels equal to the value of nulvalue will be replaced by the appropriate
-  null value in the output FITS file. 
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
-*/
-{
-    tcolumn *colptr;
-    LONGLONG  ngood = 0, nbad = 0, ii;
-    LONGLONG repeat, first, fstelm, fstrow;
-    int tcode, overflow = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode  = colptr->tdatatype;
-
-    if (tcode > 0)
-       repeat = colptr->trepeat;  /* repeat count for this column */
-    else
-       repeat = firstelem -1 + nelem;  /* variable length arrays */
-
-    /* if variable length array, first write the whole input vector, 
-       then go back and fill in the nulls */
-    if (tcode < 0) {
-      if (ffpclsb(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
-        if (*status == NUM_OVERFLOW) 
-	{
-	  /* ignore overflows, which are possibly the null pixel values */
-	  /*  overflow = 1;   */
-	  *status = 0;
-	} else { 
-          return(*status);
-	}
-      }
-    }
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (array[ii] != nulvalue)  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-
-            nbad=0;
-         }
-
-         ngood = ngood + 1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (tcode > 0) {  /* variable length arrays have already been written */
-              if (ffpclsb(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0) {
-		if (*status == NUM_OVERFLOW) 
-		{
-		  overflow = 1;
-		  *status = 0;
-		} else { 
-                  return(*status);
-		}
-	      }
-	    }
-            ngood=0;
-         }
-
-         nbad = nbad + 1;  /* the consecutive number of bad pixels */
-      }
-    }
-
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      if (tcode > 0) {  /* variable length arrays have already been written */
-        ffpclsb(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-      }
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-
-    if (*status <= 0) {
-      if (overflow) {
-        *status = NUM_OVERFLOW;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffs1fi1(signed char *input,    /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            unsigned char *output, /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == -128.)
-    {
-        /* Instead of adding 128, it is more efficient */
-        /* to just flip the sign bit with the XOR operator */
-
-        for (ii = 0; ii < ntodo; ii++)
-             output[ii] =  ( *(unsigned char *) &input[ii] ) ^ 0x80;
-    }
-    else if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] < 0)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else
-                output[ii] = (unsigned char) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = ( ((double) input[ii]) - zero) / scale;
-
-            if (dvalue < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (dvalue > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) (dvalue + .5);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffs1fi2(signed char *input,    /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            short *output,         /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = input[ii];   /* just copy input to output */
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (((double) input[ii]) - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (short) (dvalue + .5);
-                else
-                    output[ii] = (short) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffs1fi4(signed char *input,    /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            INT32BIT *output,      /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (INT32BIT) input[ii];   /* copy input to output */
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (((double) input[ii]) - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (INT32BIT) (dvalue + .5);
-                else
-                    output[ii] = (INT32BIT) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffs1fi8(signed char *input,   /* I - array of values to be converted  */
-            long ntodo,           /* I - number of elements in the array  */
-            double scale,         /* I - FITS TSCALn or BSCALE value      */
-            double zero,          /* I - FITS TZEROn or BZERO  value      */
-            LONGLONG *output,     /* O - output array of converted values */
-            int *status)          /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (dvalue > DLONGLONG_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (LONGLONG) (dvalue + .5);
-                else
-                    output[ii] = (LONGLONG) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffs1fr4(signed char *input,    /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            float *output,         /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (float) (( ( (double) input[ii] ) - zero) / scale);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffs1fr8(signed char *input,    /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            double *output,        /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = ( ( (double) input[ii] ) - zero) / scale;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffs1fstr(signed char *input, /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            char *cform,       /* I - format for output string values  */
-            long twidth,       /* I - width of each field, in chars    */
-            char *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-    char *cptr;
-    
-    cptr = output;
-
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-           sprintf(output, cform, (double) input[ii]);
-           output += twidth;
-
-           if (*output)  /* if this char != \0, then overflow occurred */
-              *status = OVERFLOW_ERR;
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-          dvalue = ((double) input[ii] - zero) / scale;
-          sprintf(output, cform, dvalue);
-          output += twidth;
-
-          if (*output)  /* if this char != \0, then overflow occurred */
-            *status = OVERFLOW_ERR;
-        }
-    }
-
-    /* replace any commas with periods (e.g., in French locale) */
-    while ((cptr = strchr(cptr, ','))) *cptr = '.';
-    
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcolu.c b/src/external/OpenGR/3rdparty/cfitsio/putcolu.c
deleted file mode 100644
index 8c57afd8e..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcolu.c
+++ /dev/null
@@ -1,629 +0,0 @@
-/*  This file, putcolu.c, contains routines that write data elements to    */
-/*  a FITS image or table.  Writes null values.                            */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffppru( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,      /* I - group to write(1 = 1st group)          */
-            LONGLONG  firstelem,  /* I - first vector element to write(1 = 1st) */
-            LONGLONG  nelem,      /* I - number of values to write              */
-            int  *status)     /* IO - error status                          */
-/*
-  Write null values to the primary array.
-
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        ffpmsg("writing to compressed image is not supported");
-
-        return(*status = DATA_COMPRESSION_ERR);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpclu(fptr, 2, row, firstelem, nelem, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpprn( fitsfile *fptr,  /* I - FITS file pointer                       */
-            LONGLONG  firstelem,  /* I - first vector element to write(1 = 1st) */
-            LONGLONG  nelem,      /* I - number of values to write              */
-            int  *status)     /* IO - error status                          */
-/*
-  Write null values to the primary array. (Doesn't support groups).
-
-*/
-{
-    long row = 1;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        ffpmsg("writing to compressed image is not supported");
-
-        return(*status = DATA_COMPRESSION_ERR);
-    }
-
-    ffpclu(fptr, 2, row, firstelem, nelem, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpclu( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelempar,     /* I - number of values to write               */
-            int  *status)    /* IO - error status                           */
-/*
-  Set elements of a table column to the appropriate null value for the column
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-  
-  This routine support COMPLEX and DOUBLE COMPLEX binary table columns, and
-  sets both the real and imaginary components of the element to a NaN.
-*/
-{
-    int tcode, maxelem, hdutype, writemode = 2, leng;
-    short i2null;
-    INT32BIT i4null;
-    long twidth, incre;
-    LONGLONG ii;
-    LONGLONG largeelem, nelem, tnull, i8null;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, ntodo;
-    double scale, zero;
-    unsigned char i1null, lognul = 0;
-    char tform[20], *cstring = 0;
-    char message[FLEN_ERRMSG];
-    char snull[20];   /*  the FITS null value  */
-    long   jbuff[2] = { -1, -1};  /* all bits set is equivalent to a NaN */
-    size_t buffsize;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    nelem = nelempar;
-    
-    largeelem = firstelem;
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-
-    /* note that writemode = 2 by default (not 1), so that the returned */
-    /* repeat and incre values will be the actual values for this column. */
-
-    /* If writing nulls to a variable length column then dummy data values  */
-    /* must have already been written to the heap. */
-    /* We just have to overwrite the previous values with null values. */
-    /* Set writemode = 0 in this case, to test that values have been written */
-
-    fits_get_coltype(fptr, colnum, &tcode, NULL, NULL, status);
-    if (tcode < 0)
-         writemode = 0;  /* this is a variable length column */
-
-    if (abs(tcode) >= TCOMPLEX)
-    { /* treat complex columns as pairs of numbers */
-      largeelem = (largeelem - 1) * 2 + 1;
-      nelem *= 2;
-    }
-
-    if (ffgcprll( fptr, colnum, firstrow, largeelem, nelem, writemode, &scale,
-       &zero, tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-
-    if (tcode == TSTRING)
-    {
-      if (snull[0] == ASCII_NULL_UNDEFINED)
-      {
-        ffpmsg(
-        "Null value string for ASCII table column is not defined (FTPCLU).");
-        return(*status = NO_NULL);
-      }
-
-      /* allocate buffer to hold the null string.  Must write the entire */
-      /* width of the column (twidth bytes) to avoid possible problems */
-      /* with uninitialized FITS blocks, in case the field spans blocks */
-
-      buffsize = maxvalue(20, twidth);
-      cstring = (char *) malloc(buffsize);
-      if (!cstring)
-         return(*status = MEMORY_ALLOCATION);
-
-      memset(cstring, ' ', buffsize);  /* initialize  with blanks */
-
-      leng = strlen(snull);
-      if (hdutype == BINARY_TBL)
-         leng++;        /* copy the terminator too in binary tables */
-
-      strncpy(cstring, snull, leng);  /* copy null string to temp buffer */
-    }
-    else if ( tcode == TBYTE  ||
-              tcode == TSHORT ||
-              tcode == TLONG  ||
-              tcode == TLONGLONG) 
-    {
-      if (tnull == NULL_UNDEFINED)
-      {
-        ffpmsg(
-        "Null value for integer table column is not defined (FTPCLU).");
-        return(*status = NO_NULL);
-      }
-
-      if (tcode == TBYTE)
-         i1null = (unsigned char) tnull;
-      else if (tcode == TSHORT)
-      {
-         i2null = (short) tnull;
-#if BYTESWAPPED
-         ffswap2(&i2null, 1); /* reverse order of bytes */
-#endif
-      }
-      else if (tcode == TLONG)
-      {
-         i4null = (INT32BIT) tnull;
-#if BYTESWAPPED
-         ffswap4(&i4null, 1); /* reverse order of bytes */
-#endif
-      }
-      else
-      {
-         i8null = tnull;
-#if BYTESWAPPED
-         ffswap8((double *)(&i8null), 1);  /* reverse order of bytes */
-#endif
-      }
-    }
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-    ntodo = remain;           /* number of elements to write at one time */
-
-    while (ntodo)
-    {
-        /* limit the number of pixels to process at one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = minvalue(ntodo, (repeat - elemnum));
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TBYTE):
- 
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 1,  &i1null, status);
-                break;
-
-            case (TSHORT):
-
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 2, &i2null, status);
-                break;
-
-            case (TLONG):
-
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 4, &i4null, status);
-                break;
-
-            case (TLONGLONG):
-
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 8, &i8null, status);
-                break;
-
-            case (TFLOAT):
-
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 4, jbuff, status);
-                break;
-
-            case (TDOUBLE):
-
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 8, jbuff, status);
-                break;
-
-            case (TLOGICAL):
- 
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 1, &lognul, status);
-                break;
-
-            case (TSTRING):  /* an ASCII table column */
-                /* repeat always = 1, so ntodo is also guaranteed to = 1 */
-                ffpbyt(fptr, twidth, cstring, status);
-                break;
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                   "Cannot write null value to column %d which has format %s",
-                     colnum,tform);
-                ffpmsg(message);
-                return(*status);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-           sprintf(message,
-             "Error writing %.0f thru %.0f of null values (ffpclu).",
-              (double) (next+1), (double) (next+ntodo));
-           ffpmsg(message);
-
-           if (cstring)
-              free(cstring);
-
-           return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-        ntodo = remain;  /* this is the maximum number to do in next loop */
-
-    }  /*  End of main while Loop  */
-
-    if (cstring)
-       free(cstring);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcluc( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-            int  *status)    /* IO - error status                           */
-/*
-  Set elements of a table column to the appropriate null value for the column
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-  
-  This routine does not do anything special in the case of COMPLEX table columns
-  (unlike the similar ffpclu routine).  This routine is mainly for use by
-  ffpcne which already compensates for the effective doubling of the number of 
-  elements in a complex column.
-*/
-{
-    int tcode, maxelem, hdutype, writemode = 2, leng;
-    short i2null;
-    INT32BIT i4null;
-    long twidth, incre;
-    LONGLONG ii;
-    LONGLONG tnull, i8null;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, ntodo;
-    double scale, zero;
-    unsigned char i1null, lognul = 0;
-    char tform[20], *cstring = 0;
-    char message[FLEN_ERRMSG];
-    char snull[20];   /*  the FITS null value  */
-    long   jbuff[2] = { -1, -1};  /* all bits set is equivalent to a NaN */
-    size_t buffsize;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-
-    /* note that writemode = 2 by default (not 1), so that the returned */
-    /* repeat and incre values will be the actual values for this column. */
-
-    /* If writing nulls to a variable length column then dummy data values  */
-    /* must have already been written to the heap. */
-    /* We just have to overwrite the previous values with null values. */
-    /* Set writemode = 0 in this case, to test that values have been written */
-
-    fits_get_coltype(fptr, colnum, &tcode, NULL, NULL, status);
-    if (tcode < 0)
-         writemode = 0;  /* this is a variable length column */
-    
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, writemode, &scale,
-       &zero, tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-
-    if (tcode == TSTRING)
-    {
-      if (snull[0] == ASCII_NULL_UNDEFINED)
-      {
-        ffpmsg(
-        "Null value string for ASCII table column is not defined (FTPCLU).");
-        return(*status = NO_NULL);
-      }
-
-      /* allocate buffer to hold the null string.  Must write the entire */
-      /* width of the column (twidth bytes) to avoid possible problems */
-      /* with uninitialized FITS blocks, in case the field spans blocks */
-
-      buffsize = maxvalue(20, twidth);
-      cstring = (char *) malloc(buffsize);
-      if (!cstring)
-         return(*status = MEMORY_ALLOCATION);
-
-      memset(cstring, ' ', buffsize);  /* initialize  with blanks */
-
-      leng = strlen(snull);
-      if (hdutype == BINARY_TBL)
-         leng++;        /* copy the terminator too in binary tables */
-
-      strncpy(cstring, snull, leng);  /* copy null string to temp buffer */
-
-    }
-    else if ( tcode == TBYTE  ||
-              tcode == TSHORT ||
-              tcode == TLONG  ||
-              tcode == TLONGLONG) 
-    {
-      if (tnull == NULL_UNDEFINED)
-      {
-        ffpmsg(
-        "Null value for integer table column is not defined (FTPCLU).");
-        return(*status = NO_NULL);
-      }
-
-      if (tcode == TBYTE)
-         i1null = (unsigned char) tnull;
-      else if (tcode == TSHORT)
-      {
-         i2null = (short) tnull;
-#if BYTESWAPPED
-         ffswap2(&i2null, 1); /* reverse order of bytes */
-#endif
-      }
-      else if (tcode == TLONG)
-      {
-         i4null = (INT32BIT) tnull;
-#if BYTESWAPPED
-         ffswap4(&i4null, 1); /* reverse order of bytes */
-#endif
-      }
-      else
-      {
-         i8null = tnull;
-#if BYTESWAPPED
-         ffswap4( (INT32BIT*) &i8null, 2); /* reverse order of bytes */
-#endif
-      }
-    }
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-    ntodo = remain;           /* number of elements to write at one time */
-
-    while (ntodo)
-    {
-        /* limit the number of pixels to process at one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = minvalue(ntodo, (repeat - elemnum));
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TBYTE):
- 
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 1,  &i1null, status);
-                break;
-
-            case (TSHORT):
-
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 2, &i2null, status);
-                break;
-
-            case (TLONG):
-
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 4, &i4null, status);
-                break;
-
-            case (TLONGLONG):
-
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 8, &i8null, status);
-                break;
-
-            case (TFLOAT):
-
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 4, jbuff, status);
-                break;
-
-            case (TDOUBLE):
-
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 8, jbuff, status);
-                break;
-
-            case (TLOGICAL):
- 
-                for (ii = 0; ii < ntodo; ii++)
-                  ffpbyt(fptr, 1, &lognul, status);
-                break;
-
-            case (TSTRING):  /* an ASCII table column */
-                /* repeat always = 1, so ntodo is also guaranteed to = 1 */
-                ffpbyt(fptr, twidth, cstring, status);
-                break;
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                   "Cannot write null value to column %d which has format %s",
-                     colnum,tform);
-                ffpmsg(message);
-                return(*status);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-           sprintf(message,
-             "Error writing %.0f thru %.0f of null values (ffpclu).",
-              (double) (next+1), (double) (next+ntodo));
-           ffpmsg(message);
-
-           if (cstring)
-              free(cstring);
-
-           return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-        ntodo = remain;  /* this is the maximum number to do in next loop */
-
-    }  /*  End of main while Loop  */
-
-    if (cstring)
-       free(cstring);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffprwu(fitsfile *fptr,
-           LONGLONG firstrow,
-           LONGLONG nrows, 
-           int *status)
-
-/* 
- * fits_write_nullrows / ffprwu - write TNULLs to all columns in one or more rows
- *
- * fitsfile *fptr - pointer to FITS HDU opened for read/write
- * long int firstrow - first table row to set to null. (firstrow >= 1)
- * long int nrows - total number or rows to set to null. (nrows >= 1)
- * int *status - upon return, *status contains CFITSIO status code
- *
- * RETURNS: CFITSIO status code
- *
- * written by Craig Markwardt, GSFC 
- */
-{
-  LONGLONG ntotrows;
-  int ncols, i;
-  int typecode = 0;
-  LONGLONG repeat = 0, width = 0;
-  int nullstatus;
-
-  if (*status > 0) return *status;
-
-  if ((firstrow <= 0) || (nrows <= 0)) return (*status = BAD_ROW_NUM);
-
-  fits_get_num_rowsll(fptr, &ntotrows, status);
-
-  if (firstrow + nrows - 1 > ntotrows) return (*status = BAD_ROW_NUM);
-  
-  fits_get_num_cols(fptr, &ncols, status);
-  if (*status) return *status;
-
-
-  /* Loop through each column and write nulls */
-  for (i=1; i <= ncols; i++) {
-    repeat = 0;  typecode = 0;  width = 0;
-    fits_get_coltypell(fptr, i, &typecode, &repeat, &width, status);
-    if (*status) break;
-
-    /* NOTE: data of TSTRING type must not write the total repeat
-       count, since the repeat count is the *character* count, not the
-       nstring count.  Divide by string width to get number of
-       strings. */
-    
-    if (typecode == TSTRING) repeat /= width;
-
-    /* Write NULLs */
-    nullstatus = 0;
-    fits_write_col_null(fptr, i, firstrow, 1, repeat*nrows, &nullstatus);
-
-    /* ignore error if no null value is defined for the column */
-    if (nullstatus && nullstatus != NO_NULL) return (*status = nullstatus);
-    
-  }
-    
-  return *status;
-}
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcolui.c b/src/external/OpenGR/3rdparty/cfitsio/putcolui.c
deleted file mode 100644
index 750164462..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcolui.c
+++ /dev/null
@@ -1,969 +0,0 @@
-/*  This file, putcolui.c, contains routines that write data elements to    */
-/*  a FITS image or table, with unsigned short datatype.                            */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffpprui(fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write (1 = 1st group)          */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-   unsigned short *array,    /* I - array of values that are written        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-    unsigned short nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_pixels(fptr, TUSHORT, firstelem, nelem,
-            0, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpclui(fptr, 2, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppnui(fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-   unsigned short *array,    /* I - array of values that are written        */
-   unsigned short nulval,    /* I - undefined pixel value                   */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).  Any array values
-  that are equal to the value of nulval will be replaced with the null
-  pixel value that is appropriate for this column.
-*/
-{
-    long row;
-    unsigned short nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        nullvalue = nulval;  /* set local variable */
-        fits_write_compressed_pixels(fptr, TUSHORT, firstelem, nelem,
-            1, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcnui(fptr, 2, row, firstelem, nelem, array, nulval, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp2dui(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-  unsigned short *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    /* call the 3D writing routine, with the 3rd dimension = 1 */
-
-    ffp3dui(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp3dui(fitsfile *fptr,   /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  nrows,      /* I - number of rows in each plane of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
-  unsigned short *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 3-D cube of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    long tablerow, ii, jj;
-    long fpixel[3]= {1,1,1}, lpixel[3];
-    LONGLONG nfits, narray;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-           
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-        lpixel[0] = (long) ncols;
-        lpixel[1] = (long) nrows;
-        lpixel[2] = (long) naxis3;
-       
-        fits_write_compressed_img(fptr, TUSHORT, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-      /* all the image pixels are contiguous, so write all at once */
-      ffpclui(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
-      return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to write to */
-    narray = 0;  /* next pixel in input array to be written */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* writing naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffpclui(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
-         return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpssui(fitsfile *fptr,   /* I - FITS file pointer                       */
-           long  group,      /* I - group to write(1 = 1st group)           */
-           long  naxis,      /* I - number of data axes in array            */
-           long  *naxes,     /* I - size of each FITS axis                  */
-           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
-           long  *lpixel,    /* I - last pixel in each axis to write        */
-  unsigned short *array,     /* I - array to be written                     */
-           int  *status)     /* IO - error status                           */
-/*
-  Write a subsection of pixels to the primary array or image.
-  A subsection is defined to be any contiguous rectangular
-  array of pixels within the n-dimensional FITS data file.
-  Data conversion and scaling will be performed if necessary 
-  (e.g, if the datatype of the FITS array is not the same as
-  the array being written).
-*/
-{
-    long tablerow;
-    LONGLONG fpix[7], dimen[7], astart, pstart;
-    LONGLONG off2, off3, off4, off5, off6, off7;
-    LONGLONG st10, st20, st30, st40, st50, st60, st70;
-    LONGLONG st1, st2, st3, st4, st5, st6, st7;
-    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_img(fptr, TUSHORT, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    if (naxis < 1 || naxis > 7)
-      return(*status = BAD_DIMEN);
-
-    tablerow=maxvalue(1,group);
-
-     /* calculate the size and number of loops to perform in each dimension */
-    for (ii = 0; ii < 7; ii++)
-    {
-      fpix[ii]=1;
-      irange[ii]=1;
-      dimen[ii]=1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {    
-      fpix[ii]=fpixel[ii];
-      irange[ii]=lpixel[ii]-fpixel[ii]+1;
-      dimen[ii]=naxes[ii];
-    }
-
-    i1=irange[0];
-
-    /* compute the pixel offset between each dimension */
-    off2 =     dimen[0];
-    off3 = off2 * dimen[1];
-    off4 = off3 * dimen[2];
-    off5 = off4 * dimen[3];
-    off6 = off5 * dimen[4];
-    off7 = off6 * dimen[5];
-
-    st10 = fpix[0];
-    st20 = (fpix[1] - 1) * off2;
-    st30 = (fpix[2] - 1) * off3;
-    st40 = (fpix[3] - 1) * off4;
-    st50 = (fpix[4] - 1) * off5;
-    st60 = (fpix[5] - 1) * off6;
-    st70 = (fpix[6] - 1) * off7;
-
-    /* store the initial offset in each dimension */
-    st1 = st10;
-    st2 = st20;
-    st3 = st30;
-    st4 = st40;
-    st5 = st50;
-    st6 = st60;
-    st7 = st70;
-
-    astart = 0;
-
-    for (i7 = 0; i7 < irange[6]; i7++)
-    {
-     for (i6 = 0; i6 < irange[5]; i6++)
-     {
-      for (i5 = 0; i5 < irange[4]; i5++)
-      {
-       for (i4 = 0; i4 < irange[3]; i4++)
-       {
-        for (i3 = 0; i3 < irange[2]; i3++)
-        {
-         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
-
-         for (i2 = 0; i2 < irange[1]; i2++)
-         {
-           if (ffpclui(fptr, 2, tablerow, pstart, i1, &array[astart],
-              status) > 0)
-              return(*status);
-
-           astart += i1;
-           pstart += off2;
-         }
-         st2 = st20;
-         st3 = st3+off3;    
-        }
-        st3 = st30;
-        st4 = st4+off4;
-       }
-       st4 = st40;
-       st5 = st5+off5;
-      }
-      st5 = st50;
-      st6 = st6+off6;
-     }
-     st6 = st60;
-     st7 = st7+off7;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpgpui( fitsfile *fptr,   /* I - FITS file pointer                      */
-            long  group,      /* I - group to write(1 = 1st group)          */
-            long  firstelem,  /* I - first vector element to write(1 = 1st) */
-            long  nelem,      /* I - number of values to write              */
-   unsigned short *array,     /* I - array of values that are written       */
-            int  *status)     /* IO - error status                          */
-/*
-  Write an array of group parameters to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffpclui(fptr, 1L, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpclui( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-   unsigned short *array,    /* I - array of values to write                */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table with
-  2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    int tcode, maxelem, hdutype;
-    long twidth, incre;
-    long ntodo;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
-    double scale, zero;
-    char tform[20], cform[20];
-    char message[FLEN_ERRMSG];
-
-    char snull[20];   /*  the FITS null value  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-
-    if (tcode == TSTRING)   
-         ffcfmt(tform, cform);     /* derive C format for writing strings */
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
-    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
-    /*  TZEROn linear scaling parameters into a temporary buffer.          */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-        /* limit the number of pixels to process a one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TSHORT):
-
-              ffu2fi2(&array[next], ntodo, scale, zero,
-                      (short *) buffer, status);
-              ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
-              break;
-
-            case (TLONGLONG):
-
-                ffu2fi8(&array[next], ntodo, scale, zero,
-                        (LONGLONG *) buffer, status);
-                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
-                break;
-
-            case (TBYTE):
- 
-                ffu2fi1(&array[next], ntodo, scale, zero,
-                        (unsigned char *) buffer, status);
-                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
-                break;
-
-            case (TLONG):
-
-                ffu2fi4(&array[next], ntodo, scale, zero,
-                        (INT32BIT *) buffer, status);
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
-                break;
-
-            case (TFLOAT):
-
-                ffu2fr4(&array[next], ntodo, scale, zero,
-                        (float *) buffer, status);
-                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
-                break;
-
-            case (TDOUBLE):
-                ffu2fr8(&array[next], ntodo, scale, zero,
-                        (double *) buffer, status);
-                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
-                break;
-
-            case (TSTRING):  /* numerical column in an ASCII table */
-
-                if (cform[1] != 's')  /*  "%s" format is a string */
-                {
-                  ffu2fstr(&array[next], ntodo, scale, zero, cform,
-                          twidth, (char *) buffer, status);
-
-
-                  if (incre == twidth)    /* contiguous bytes */
-                     ffpbyt(fptr, ntodo * twidth, buffer, status);
-                  else
-                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                            status);
-
-                  break;
-                }
-                /* can't write to string column, so fall thru to default: */
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                    "Cannot write numbers to column %d which has format %s",
-                      colnum,tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-         sprintf(message,
-          "Error writing elements %.0f thru %.0f of input data array (ffpclui).",
-             (double) (next+1), (double) (next+ntodo));
-         ffpmsg(message);
-         return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-       ffpmsg(
-       "Numerical overflow during type conversion while writing FITS data.");
-       *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcnui(fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-   unsigned short *array,    /* I - array of values to write                */
-   unsigned short  nulvalue, /* I - value used to flag undefined pixels     */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels equal to the value of nulvalue will be replaced by the appropriate
-  null value in the output FITS file. 
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
-*/
-{
-    tcolumn *colptr;
-    LONGLONG  ngood = 0, nbad = 0, ii;
-    LONGLONG repeat, first, fstelm, fstrow;
-    int tcode, overflow = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode  = colptr->tdatatype;
-
-    if (tcode > 0)
-       repeat = colptr->trepeat;  /* repeat count for this column */
-    else
-       repeat = firstelem -1 + nelem;  /* variable length arrays */
-
-    /* if variable length array, first write the whole input vector, 
-       then go back and fill in the nulls */
-    if (tcode < 0) {
-      if (ffpclui(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
-        if (*status == NUM_OVERFLOW) 
-	{
-	  /* ignore overflows, which are possibly the null pixel values */
-	  /*  overflow = 1;   */
-	  *status = 0;
-	} else { 
-          return(*status);
-	}
-      }
-    }
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (array[ii] != nulvalue)  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-
-            nbad=0;
-         }
-
-         ngood = ngood +1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (tcode > 0) {  /* variable length arrays have already been written */
-              if (ffpclui(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0) {
-		if (*status == NUM_OVERFLOW) 
-		{
-		  overflow = 1;
-		  *status = 0;
-		} else { 
-                  return(*status);
-		}
-	      }
-	    }
-            ngood=0;
-         }
-
-         nbad = nbad +1;  /* the consecutive number of bad pixels */
-      }
-    }
-
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      if (tcode > 0) {  /* variable length arrays have already been written */
-        ffpclui(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-      }
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-
-    if (*status <= 0) {
-      if (overflow) {
-        *status = NUM_OVERFLOW;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu2fi1(unsigned short *input, /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            unsigned char *output, /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] > UCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = ((double) input[ii] - zero) / scale;
-
-            if (dvalue < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (dvalue > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) (dvalue + .5);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu2fi2(unsigned short *input, /* I - array of values to be converted */
-            long ntodo,         /* I - number of elements in the array  */
-            double scale,       /* I - FITS TSCALn or BSCALE value      */
-            double zero,        /* I - FITS TZEROn or BZERO  value      */
-            short *output,      /* O - output array of converted values */
-            int *status)        /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 32768.)
-    {
-        /* Instead of subtracting 32768, it is more efficient */
-        /* to just flip the sign bit with the XOR operator */
-
-        for (ii = 0; ii < ntodo; ii++)
-             output[ii] =  ( *(short *) &input[ii] ) ^ 0x8000;
-    }
-    else if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] > SHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-                output[ii] = input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = ((double) input[ii] - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (short) (dvalue + .5);
-                else
-                    output[ii] = (short) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu2fi4(unsigned short *input, /* I - array of values to be converted */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            INT32BIT *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (INT32BIT) input[ii];   /* copy input to output */
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = ((double) input[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (INT32BIT) (dvalue + .5);
-                else
-                    output[ii] = (INT32BIT) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu2fi8(unsigned short *input,  /* I - array of values to be converted  */
-            long ntodo,             /* I - number of elements in the array  */
-            double scale,           /* I - FITS TSCALn or BSCALE value      */
-            double zero,            /* I - FITS TZEROn or BZERO  value      */
-            LONGLONG *output,       /* O - output array of converted values */
-            int *status)            /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (dvalue > DLONGLONG_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (LONGLONG) (dvalue + .5);
-                else
-                    output[ii] = (LONGLONG) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu2fr4(unsigned short *input, /* I - array of values to be converted */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            float *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (float) (((double) input[ii] - zero) / scale);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu2fr8(unsigned short *input, /* I - array of values to be converted */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            double *output,    /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = ((double) input[ii] - zero) / scale;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu2fstr(unsigned short *input, /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            char *cform,       /* I - format for output string values  */
-            long twidth,       /* I - width of each field, in chars    */
-            char *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-    char *cptr;
-    
-    cptr = output;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-           sprintf(output, cform, (double) input[ii]);
-           output += twidth;
-
-           if (*output)  /* if this char != \0, then overflow occurred */
-              *status = OVERFLOW_ERR;
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-          dvalue = ((double) input[ii] - zero) / scale;
-          sprintf(output, cform, dvalue);
-          output += twidth;
-
-          if (*output)  /* if this char != \0, then overflow occurred */
-            *status = OVERFLOW_ERR;
-        }
-    }
-
-    /* replace any commas with periods (e.g., in French locale) */
-    while ((cptr = strchr(cptr, ','))) *cptr = '.';
-    
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcoluj.c b/src/external/OpenGR/3rdparty/cfitsio/putcoluj.c
deleted file mode 100644
index 9fdbbcd0e..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcoluj.c
+++ /dev/null
@@ -1,977 +0,0 @@
-/*  This file, putcoluj.c, contains routines that write data elements to   */
-/*  a FITS image or table, with unsigned long datatype.                             */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffppruj( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-   unsigned long  *array,    /* I - array of values that are written        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-    unsigned long nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_pixels(fptr, TULONG, firstelem, nelem,
-            0, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcluj(fptr, 2, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppnuj( fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-   unsigned long  *array,    /* I - array of values that are written        */
-   unsigned long  nulval,    /* I - undefined pixel value                   */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).  Any array values
-  that are equal to the value of nulval will be replaced with the null
-  pixel value that is appropriate for this column.
-*/
-{
-    long row;
-    unsigned long nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        nullvalue = nulval;  /* set local variable */
-        fits_write_compressed_pixels(fptr, TULONG, firstelem, nelem,
-            1, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcnuj(fptr, 2, row, firstelem, nelem, array, nulval, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp2duj(fitsfile *fptr,   /* I - FITS file pointer                    */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-  unsigned long  *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    /* call the 3D writing routine, with the 3rd dimension = 1 */
-
-    ffp3duj(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp3duj(fitsfile *fptr,   /* I - FITS file pointer                    */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  nrows,      /* I - number of rows in each plane of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
-  unsigned long  *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 3-D cube of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    long tablerow, ii, jj;
-    long fpixel[3]= {1,1,1}, lpixel[3];
-    LONGLONG nfits, narray;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-           
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-        lpixel[0] = (long) ncols;
-        lpixel[1] = (long) nrows;
-        lpixel[2] = (long) naxis3;
-       
-        fits_write_compressed_img(fptr, TULONG, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-      /* all the image pixels are contiguous, so write all at once */
-      ffpcluj(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
-      return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to write to */
-    narray = 0;  /* next pixel in input array to be written */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* writing naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffpcluj(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
-         return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpssuj(fitsfile *fptr,   /* I - FITS file pointer                       */
-           long  group,      /* I - group to write(1 = 1st group)           */
-           long  naxis,      /* I - number of data axes in array            */
-           long  *naxes,     /* I - size of each FITS axis                  */
-           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
-           long  *lpixel,    /* I - last pixel in each axis to write        */
-  unsigned long *array,      /* I - array to be written                     */
-           int  *status)     /* IO - error status                           */
-/*
-  Write a subsection of pixels to the primary array or image.
-  A subsection is defined to be any contiguous rectangular
-  array of pixels within the n-dimensional FITS data file.
-  Data conversion and scaling will be performed if necessary 
-  (e.g, if the datatype of the FITS array is not the same as
-  the array being written).
-*/
-{
-    long tablerow;
-    LONGLONG fpix[7], dimen[7], astart, pstart;
-    LONGLONG off2, off3, off4, off5, off6, off7;
-    LONGLONG st10, st20, st30, st40, st50, st60, st70;
-    LONGLONG st1, st2, st3, st4, st5, st6, st7;
-    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_img(fptr, TULONG, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    if (naxis < 1 || naxis > 7)
-      return(*status = BAD_DIMEN);
-
-    tablerow=maxvalue(1,group);
-
-     /* calculate the size and number of loops to perform in each dimension */
-    for (ii = 0; ii < 7; ii++)
-    {
-      fpix[ii]=1;
-      irange[ii]=1;
-      dimen[ii]=1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {    
-      fpix[ii]=fpixel[ii];
-      irange[ii]=lpixel[ii]-fpixel[ii]+1;
-      dimen[ii]=naxes[ii];
-    }
-
-    i1=irange[0];
-
-    /* compute the pixel offset between each dimension */
-    off2 =     dimen[0];
-    off3 = off2 * dimen[1];
-    off4 = off3 * dimen[2];
-    off5 = off4 * dimen[3];
-    off6 = off5 * dimen[4];
-    off7 = off6 * dimen[5];
-
-    st10 = fpix[0];
-    st20 = (fpix[1] - 1) * off2;
-    st30 = (fpix[2] - 1) * off3;
-    st40 = (fpix[3] - 1) * off4;
-    st50 = (fpix[4] - 1) * off5;
-    st60 = (fpix[5] - 1) * off6;
-    st70 = (fpix[6] - 1) * off7;
-
-    /* store the initial offset in each dimension */
-    st1 = st10;
-    st2 = st20;
-    st3 = st30;
-    st4 = st40;
-    st5 = st50;
-    st6 = st60;
-    st7 = st70;
-
-    astart = 0;
-
-    for (i7 = 0; i7 < irange[6]; i7++)
-    {
-     for (i6 = 0; i6 < irange[5]; i6++)
-     {
-      for (i5 = 0; i5 < irange[4]; i5++)
-      {
-       for (i4 = 0; i4 < irange[3]; i4++)
-       {
-        for (i3 = 0; i3 < irange[2]; i3++)
-        {
-         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
-
-         for (i2 = 0; i2 < irange[1]; i2++)
-         {
-           if (ffpcluj(fptr, 2, tablerow, pstart, i1, &array[astart],
-              status) > 0)
-              return(*status);
-
-           astart += i1;
-           pstart += off2;
-         }
-         st2 = st20;
-         st3 = st3+off3;    
-        }
-        st3 = st30;
-        st4 = st4+off4;
-       }
-       st4 = st40;
-       st5 = st5+off5;
-      }
-      st5 = st50;
-      st6 = st6+off6;
-     }
-     st6 = st60;
-     st7 = st7+off7;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpgpuj( fitsfile *fptr,   /* I - FITS file pointer                      */
-            long  group,      /* I - group to write(1 = 1st group)          */
-            long  firstelem,  /* I - first vector element to write(1 = 1st) */
-            long  nelem,      /* I - number of values to write              */
-   unsigned long  *array,     /* I - array of values that are written       */
-            int  *status)     /* IO - error status                          */
-/*
-  Write an array of group parameters to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffpcluj(fptr, 1L, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcluj( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-   unsigned long  *array,    /* I - array of values to write                */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    int tcode, maxelem, hdutype;
-    long twidth, incre;
-    long ntodo;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
-    double scale, zero;
-    char tform[20], cform[20];
-    char message[FLEN_ERRMSG];
-
-    char snull[20];   /*  the FITS null value  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    buffer = cbuff;
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-
-    if (tcode == TSTRING)   
-         ffcfmt(tform, cform);     /* derive C format for writing strings */
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
-    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
-    /*  TZEROn linear scaling parameters into a temporary buffer.          */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-        /* limit the number of pixels to process a one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TLONG):
-
-                ffu4fi4(&array[next], ntodo, scale, zero,
-                      (INT32BIT *) buffer, status);
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
-                break;
-
-            case (TLONGLONG):
-
-                ffu4fi8(&array[next], ntodo, scale, zero,
-                        (LONGLONG *) buffer, status);
-                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
-                break;
-
-            case (TBYTE):
- 
-                ffu4fi1(&array[next], ntodo, scale, zero,
-                        (unsigned char *) buffer, status);
-                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
-                break;
-
-            case (TSHORT):
-
-                ffu4fi2(&array[next], ntodo, scale, zero,
-                        (short *) buffer, status);
-                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
-                break;
-
-            case (TFLOAT):
-
-                ffu4fr4(&array[next], ntodo, scale, zero,
-                        (float *) buffer, status);
-                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
-                break;
-
-            case (TDOUBLE):
-                ffu4fr8(&array[next], ntodo, scale, zero,
-                       (double *) buffer, status);
-                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
-                break;
-
-            case (TSTRING):  /* numerical column in an ASCII table */
-
-                if (cform[1] != 's')  /*  "%s" format is a string */
-                {
-                  ffu4fstr(&array[next], ntodo, scale, zero, cform,
-                          twidth, (char *) buffer, status);
-
-                  if (incre == twidth)    /* contiguous bytes */
-                     ffpbyt(fptr, ntodo * twidth, buffer, status);
-                  else
-                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                            status);
-
-                  break;
-                }
-                /* can't write to string column, so fall thru to default: */
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                     "Cannot write numbers to column %d which has format %s",
-                      colnum,tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-          sprintf(message,
-          "Error writing elements %.0f thru %.0f of input data array (ffpcluj).",
-              (double) (next+1), (double) (next+ntodo));
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while writing FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcnuj( fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-   unsigned long  *array,    /* I - array of values to write                */
-   unsigned long   nulvalue, /* I - value used to flag undefined pixels     */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels equal to the value of nulvalue will be replaced by the appropriate
-  null value in the output FITS file. 
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
-*/
-{
-    tcolumn *colptr;
-    LONGLONG  ngood = 0, nbad = 0, ii;
-    LONGLONG repeat, first, fstelm, fstrow;
-    int tcode, overflow = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode  = colptr->tdatatype;
-
-    if (tcode > 0)
-       repeat = colptr->trepeat;  /* repeat count for this column */
-    else
-       repeat = firstelem -1 + nelem;  /* variable length arrays */
-
-    /* if variable length array, first write the whole input vector, 
-       then go back and fill in the nulls */
-    if (tcode < 0) {
-      if (ffpcluj(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
-        if (*status == NUM_OVERFLOW) 
-	{
-	  /* ignore overflows, which are possibly the null pixel values */
-	  /*  overflow = 1;   */
-	  *status = 0;
-	} else { 
-          return(*status);
-	}
-      }
-    }
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (array[ii] != nulvalue)  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-
-            nbad=0;
-         }
-
-         ngood = ngood +1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (tcode > 0) {  /* variable length arrays have already been written */
-              if (ffpcluj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0) {
-		if (*status == NUM_OVERFLOW) 
-		{
-		  overflow = 1;
-		  *status = 0;
-		} else { 
-                  return(*status);
-		}
-	      }
-	    }
-            ngood=0;
-         }
-
-         nbad = nbad +1;  /* the consecutive number of bad pixels */
-      }
-    }
-
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      if (tcode > 0) {  /* variable length arrays have already been written */
-        ffpcluj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-      }
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-
-    if (*status <= 0) {
-      if (overflow) {
-        *status = NUM_OVERFLOW;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu4fi1(unsigned long *input,  /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            unsigned char *output, /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] > UCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (dvalue > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) (dvalue + .5);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu4fi2(unsigned long *input, /* I - array of values to be converted */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            short *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] > SHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-                output[ii] = (short) input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (short) (dvalue + .5);
-                else
-                    output[ii] = (short) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu4fi4(unsigned long *input, /* I - array of values to be converted */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            INT32BIT *output,  /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 2147483648. && sizeof(long) == 4)
-    {       
-        /* Instead of subtracting 2147483648, it is more efficient */
-        /* to just flip the sign bit with the XOR operator */
-
-        for (ii = 0; ii < ntodo; ii++)
-             output[ii] =  ( *(long *) &input[ii] ) ^ 0x80000000;
-    }
-    else if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] > INT32_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-                output[ii] = input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (INT32BIT) (dvalue + .5);
-                else
-                    output[ii] = (INT32BIT) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu4fi8(unsigned long *input,  /* I - array of values to be converted  */
-            long ntodo,             /* I - number of elements in the array  */
-            double scale,           /* I - FITS TSCALn or BSCALE value      */
-            double zero,            /* I - FITS TZEROn or BZERO  value      */
-            LONGLONG *output,       /* O - output array of converted values */
-            int *status)            /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (dvalue > DLONGLONG_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (LONGLONG) (dvalue + .5);
-                else
-                    output[ii] = (LONGLONG) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu4fr4(unsigned long *input, /* I - array of values to be converted */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            float *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (float) ((input[ii] - zero) / scale);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu4fr8(unsigned long *input, /* I - array of values to be converted */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            double *output,    /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (input[ii] - zero) / scale;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffu4fstr(unsigned long *input, /* I - array of values to be converted */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            char *cform,       /* I - format for output string values  */
-            long twidth,       /* I - width of each field, in chars    */
-            char *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-    char *cptr;
-    
-    cptr = output;
-
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-           sprintf(output, cform, (double) input[ii]);
-           output += twidth;
-
-           if (*output)  /* if this char != \0, then overflow occurred */
-              *status = OVERFLOW_ERR;
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-          dvalue = (input[ii] - zero) / scale;
-          sprintf(output, cform, dvalue);
-          output += twidth;
-
-          if (*output)  /* if this char != \0, then overflow occurred */
-            *status = OVERFLOW_ERR;
-        }
-    }
-
-    /* replace any commas with periods (e.g., in French locale) */
-    while ((cptr = strchr(cptr, ','))) *cptr = '.';
-    
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putcoluk.c b/src/external/OpenGR/3rdparty/cfitsio/putcoluk.c
deleted file mode 100644
index 74d0a0581..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putcoluk.c
+++ /dev/null
@@ -1,993 +0,0 @@
-/*  This file, putcolk.c, contains routines that write data elements to    */
-/*  a FITS image or table, with 'unsigned int' datatype.                   */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffppruk(fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-   unsigned int   *array,    /* I - array of values that are written        */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-    unsigned int nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_pixels(fptr, TUINT, firstelem, nelem,
-            0, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcluk(fptr, 2, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffppnuk(fitsfile *fptr,  /* I - FITS file pointer                       */
-            long  group,     /* I - group to write(1 = 1st group)           */
-            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
-            LONGLONG  nelem,     /* I - number of values to write               */
-   unsigned int   *array,    /* I - array of values that are written        */
-   unsigned int   nulval,    /* I - undefined pixel value                   */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).  Any array values
-  that are equal to the value of nulval will be replaced with the null
-  pixel value that is appropriate for this column.
-*/
-{
-    long row;
-    unsigned int nullvalue;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        nullvalue = nulval;  /* set local variable */
-        fits_write_compressed_pixels(fptr, TUINT, firstelem, nelem,
-            1, array, &nullvalue, status);
-        return(*status);
-    }
-
-    row=maxvalue(1,group);
-
-    ffpcnuk(fptr, 2, row, firstelem, nelem, array, nulval, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp2duk(fitsfile *fptr,  /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-  unsigned int   *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 2-D array of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    /* call the 3D writing routine, with the 3rd dimension = 1 */
-
-    ffp3duk(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffp3duk(fitsfile *fptr,  /* I - FITS file pointer                     */
-           long  group,      /* I - group to write(1 = 1st group)         */
-           LONGLONG  ncols,      /* I - number of pixels in each row of array */
-           LONGLONG  nrows,      /* I - number of rows in each plane of array */
-           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
-           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
-           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
-  unsigned int   *array,     /* I - array to be written                   */
-           int  *status)     /* IO - error status                         */
-/*
-  Write an entire 3-D cube of values to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of the
-  FITS array is not the same as the array being written).
-*/
-{
-    long tablerow, ii, jj;
-    long fpixel[3]= {1,1,1}, lpixel[3];
-    LONGLONG nfits, narray;
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-           
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-        lpixel[0] = (long) ncols;
-        lpixel[1] = (long) nrows;
-        lpixel[2] = (long) naxis3;
-       
-        fits_write_compressed_img(fptr, TUINT, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    tablerow=maxvalue(1,group);
-
-    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
-    {
-      /* all the image pixels are contiguous, so write all at once */
-      ffpcluk(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
-      return(*status);
-    }
-
-    if (ncols < naxis1 || nrows < naxis2)
-       return(*status = BAD_DIMEN);
-
-    nfits = 1;   /* next pixel in FITS image to write to */
-    narray = 0;  /* next pixel in input array to be written */
-
-    /* loop over naxis3 planes in the data cube */
-    for (jj = 0; jj < naxis3; jj++)
-    {
-      /* loop over the naxis2 rows in the FITS image, */
-      /* writing naxis1 pixels to each row            */
-
-      for (ii = 0; ii < naxis2; ii++)
-      {
-       if (ffpcluk(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
-         return(*status);
-
-       nfits += naxis1;
-       narray += ncols;
-      }
-      narray += (nrows - naxis2) * ncols;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpssuk(fitsfile *fptr,  /* I - FITS file pointer                       */
-           long  group,      /* I - group to write(1 = 1st group)           */
-           long  naxis,      /* I - number of data axes in array            */
-           long  *naxes,     /* I - size of each FITS axis                  */
-           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
-           long  *lpixel,    /* I - last pixel in each axis to write        */
-  unsigned int  *array,      /* I - array to be written                     */
-           int  *status)     /* IO - error status                           */
-/*
-  Write a subsection of pixels to the primary array or image.
-  A subsection is defined to be any contiguous rectangular
-  array of pixels within the n-dimensional FITS data file.
-  Data conversion and scaling will be performed if necessary 
-  (e.g, if the datatype of the FITS array is not the same as
-  the array being written).
-*/
-{
-    long tablerow;
-    LONGLONG fpix[7], dimen[7], astart, pstart;
-    LONGLONG off2, off3, off4, off5, off6, off7;
-    LONGLONG st10, st20, st30, st40, st50, st60, st70;
-    LONGLONG st1, st2, st3, st4, st5, st6, st7;
-    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fits_is_compressed_image(fptr, status))
-    {
-        /* this is a compressed image in a binary table */
-
-        fits_write_compressed_img(fptr, TUINT, fpixel, lpixel,
-            0,  array, NULL, status);
-    
-        return(*status);
-    }
-
-    if (naxis < 1 || naxis > 7)
-      return(*status = BAD_DIMEN);
-
-    tablerow=maxvalue(1,group);
-
-     /* calculate the size and number of loops to perform in each dimension */
-    for (ii = 0; ii < 7; ii++)
-    {
-      fpix[ii]=1;
-      irange[ii]=1;
-      dimen[ii]=1;
-    }
-
-    for (ii = 0; ii < naxis; ii++)
-    {    
-      fpix[ii]=fpixel[ii];
-      irange[ii]=lpixel[ii]-fpixel[ii]+1;
-      dimen[ii]=naxes[ii];
-    }
-
-    i1=irange[0];
-
-    /* compute the pixel offset between each dimension */
-    off2 =     dimen[0];
-    off3 = off2 * dimen[1];
-    off4 = off3 * dimen[2];
-    off5 = off4 * dimen[3];
-    off6 = off5 * dimen[4];
-    off7 = off6 * dimen[5];
-
-    st10 = fpix[0];
-    st20 = (fpix[1] - 1) * off2;
-    st30 = (fpix[2] - 1) * off3;
-    st40 = (fpix[3] - 1) * off4;
-    st50 = (fpix[4] - 1) * off5;
-    st60 = (fpix[5] - 1) * off6;
-    st70 = (fpix[6] - 1) * off7;
-
-    /* store the initial offset in each dimension */
-    st1 = st10;
-    st2 = st20;
-    st3 = st30;
-    st4 = st40;
-    st5 = st50;
-    st6 = st60;
-    st7 = st70;
-
-    astart = 0;
-
-    for (i7 = 0; i7 < irange[6]; i7++)
-    {
-     for (i6 = 0; i6 < irange[5]; i6++)
-     {
-      for (i5 = 0; i5 < irange[4]; i5++)
-      {
-       for (i4 = 0; i4 < irange[3]; i4++)
-       {
-        for (i3 = 0; i3 < irange[2]; i3++)
-        {
-         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
-
-         for (i2 = 0; i2 < irange[1]; i2++)
-         {
-           if (ffpcluk(fptr, 2, tablerow, pstart, i1, &array[astart],
-              status) > 0)
-              return(*status);
-
-           astart += i1;
-           pstart += off2;
-         }
-         st2 = st20;
-         st3 = st3+off3;    
-        }
-        st3 = st30;
-        st4 = st4+off4;
-       }
-       st4 = st40;
-       st5 = st5+off5;
-      }
-      st5 = st50;
-      st6 = st6+off6;
-     }
-     st6 = st60;
-     st7 = st7+off7;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpgpuk(fitsfile *fptr,   /* I - FITS file pointer                      */
-            long  group,      /* I - group to write(1 = 1st group)          */
-            long  firstelem,  /* I - first vector element to write(1 = 1st) */
-            long  nelem,      /* I - number of values to write              */
-   unsigned int   *array,     /* I - array of values that are written       */
-            int  *status)     /* IO - error status                          */
-/*
-  Write an array of group parameters to the primary array. Data conversion
-  and scaling will be performed if necessary (e.g, if the datatype of
-  the FITS array is not the same as the array being written).
-*/
-{
-    long row;
-
-    /*
-      the primary array is represented as a binary table:
-      each group of the primary array is a row in the table,
-      where the first column contains the group parameters
-      and the second column contains the image itself.
-    */
-
-    row=maxvalue(1,group);
-
-    ffpcluk(fptr, 1L, row, firstelem, nelem, array, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcluk(fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-   unsigned int   *array,    /* I - array of values to write                */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of values to a column in the current FITS HDU.
-  The column number may refer to a real column in an ASCII or binary table, 
-  or it may refer to a virtual column in a 1 or more grouped FITS primary
-  array.  FITSIO treats a primary array as a binary table
-  with 2 vector columns: the first column contains the group parameters (often
-  with length = 0) and the second column contains the array of image pixels.
-  Each row of the table represents a group in the case of multigroup FITS
-  images.
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
-*/
-{
-    int tcode, maxelem, hdutype;
-    long twidth, incre;
-    long ntodo;
-    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
-    double scale, zero;
-    char tform[20], cform[20];
-    char message[FLEN_ERRMSG];
-
-    char snull[20];   /*  the FITS null value  */
-
-    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
-    void *buffer;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* call the 'short' or 'long' version of this routine, if possible */
-    if (sizeof(int) == sizeof(short))
-        ffpclui(fptr, colnum, firstrow, firstelem, nelem, 
-              (unsigned short *) array, status);
-    else if (sizeof(int) == sizeof(long))
-        ffpcluj(fptr, colnum, firstrow, firstelem, nelem, 
-              (unsigned long *) array, status);
-    else
-    {
-    /*
-      This is a special case: sizeof(int) is not equal to sizeof(short) or
-      sizeof(long).  This occurs on Alpha OSF systems where short = 2 bytes,
-      int = 4 bytes, and long = 8 bytes.
-    */
-
-    buffer = cbuff;
-
-    /*---------------------------------------------------*/
-    /*  Check input and get parameters about the column: */
-    /*---------------------------------------------------*/
-    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
-        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
-        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
-        return(*status);
-
-    if (tcode == TSTRING)   
-         ffcfmt(tform, cform);     /* derive C format for writing strings */
-
-    /*---------------------------------------------------------------------*/
-    /*  Now write the pixels to the FITS column.                           */
-    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
-    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
-    /*  TZEROn linear scaling parameters into a temporary buffer.          */
-    /*---------------------------------------------------------------------*/
-    remain = nelem;           /* remaining number of values to write  */
-    next = 0;                 /* next element in array to be written  */
-    rownum = 0;               /* row number, relative to firstrow     */
-
-    while (remain)
-    {
-        /* limit the number of pixels to process a one time to the number that
-           will fit in the buffer space or to the number of pixels that remain
-           in the current vector, which ever is smaller.
-        */
-        ntodo = (long) minvalue(remain, maxelem);      
-        ntodo = (long) minvalue(ntodo, (repeat - elemnum));
-
-        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
-
-        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
-
-        switch (tcode) 
-        {
-            case (TLONG):
-                /* convert the raw data before writing to FITS file */
-                ffuintfi4(&array[next], ntodo, scale, zero,
-                        (INT32BIT *) buffer, status);
-                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
-                break;
-
-            case (TLONGLONG):
-
-                ffuintfi8(&array[next], ntodo, scale, zero,
-                        (LONGLONG *) buffer, status);
-                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
-                break;
-
-            case (TBYTE):
- 
-                ffuintfi1(&array[next], ntodo, scale, zero,
-                        (unsigned char *) buffer, status);
-                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
-                break;
-
-            case (TSHORT):
-
-                ffuintfi2(&array[next], ntodo, scale, zero,
-                        (short *) buffer, status);
-                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
-                break;
-
-            case (TFLOAT):
-
-                ffuintfr4(&array[next], ntodo, scale, zero,
-                        (float *) buffer, status);
-                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
-                break;
-
-            case (TDOUBLE):
-                ffuintfr8(&array[next], ntodo, scale, zero,
-                       (double *) buffer, status);
-                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
-                break;
-
-            case (TSTRING):  /* numerical column in an ASCII table */
-
-                if (cform[1] != 's')  /*  "%s" format is a string */
-                {
-                  ffuintfstr(&array[next], ntodo, scale, zero, cform,
-                          twidth, (char *) buffer, status);
-
-                  if (incre == twidth)    /* contiguous bytes */
-                     ffpbyt(fptr, ntodo * twidth, buffer, status);
-                  else
-                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
-                            status);
-
-                  break;
-                }
-                /* can't write to string column, so fall thru to default: */
-
-            default:  /*  error trap  */
-                sprintf(message, 
-                     "Cannot write numbers to column %d which has format %s",
-                      colnum,tform);
-                ffpmsg(message);
-                if (hdutype == ASCII_TBL)
-                    return(*status = BAD_ATABLE_FORMAT);
-                else
-                    return(*status = BAD_BTABLE_FORMAT);
-
-        } /* End of switch block */
-
-        /*-------------------------*/
-        /*  Check for fatal error  */
-        /*-------------------------*/
-        if (*status > 0)  /* test for error during previous write operation */
-        {
-          sprintf(message,
-          "Error writing elements %.0f thru %.0f of input data array (ffpcluk).",
-              (double) (next+1), (double) (next+ntodo));
-          ffpmsg(message);
-          return(*status);
-        }
-
-        /*--------------------------------------------*/
-        /*  increment the counters for the next loop  */
-        /*--------------------------------------------*/
-        remain -= ntodo;
-        if (remain)
-        {
-            next += ntodo;
-            elemnum += ntodo;
-            if (elemnum == repeat)  /* completed a row; start on next row */
-            {
-                elemnum = 0;
-                rownum++;
-            }
-        }
-    }  /*  End of main while Loop  */
-
-
-    /*--------------------------------*/
-    /*  check for numerical overflow  */
-    /*--------------------------------*/
-    if (*status == OVERFLOW_ERR)
-    {
-        ffpmsg(
-        "Numerical overflow during type conversion while writing FITS data.");
-        *status = NUM_OVERFLOW;
-    }
-
-    }   /* end of Dec ALPHA special case */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpcnuk(fitsfile *fptr,  /* I - FITS file pointer                       */
-            int  colnum,     /* I - number of column to write (1 = 1st col) */
-            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
-            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
-            LONGLONG  nelem,     /* I - number of values to write               */
-   unsigned int   *array,    /* I - array of values to write                */
-   unsigned int    nulvalue, /* I - value used to flag undefined pixels     */
-            int  *status)    /* IO - error status                           */
-/*
-  Write an array of elements to the specified column of a table.  Any input
-  pixels equal to the value of nulvalue will be replaced by the appropriate
-  null value in the output FITS file. 
-
-  The input array of values will be converted to the datatype of the column 
-  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
-*/
-{
-    tcolumn *colptr;
-    LONGLONG  ngood = 0, nbad = 0, ii;
-    LONGLONG repeat, first, fstelm, fstrow;
-    int tcode, overflow = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-    {
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    }
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-    {
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-    }
-
-    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
-    colptr += (colnum - 1);     /* offset to correct column structure */
-
-    tcode  = colptr->tdatatype;
-
-    if (tcode > 0)
-       repeat = colptr->trepeat;  /* repeat count for this column */
-    else
-       repeat = firstelem -1 + nelem;  /* variable length arrays */
-
-    /* if variable length array, first write the whole input vector, 
-       then go back and fill in the nulls */
-    if (tcode < 0) {
-      if (ffpcluk(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
-        if (*status == NUM_OVERFLOW) 
-	{
-	  /* ignore overflows, which are possibly the null pixel values */
-	  /*  overflow = 1;   */
-	  *status = 0;
-	} else { 
-          return(*status);
-	}
-      }
-    }
-
-    /* absolute element number in the column */
-    first = (firstrow - 1) * repeat + firstelem;
-
-    for (ii = 0; ii < nelem; ii++)
-    {
-      if (array[ii] != nulvalue)  /* is this a good pixel? */
-      {
-         if (nbad)  /* write previous string of bad pixels */
-         {
-            fstelm = ii - nbad + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
-                return(*status);
-
-            nbad=0;
-         }
-
-         ngood = ngood +1;  /* the consecutive number of good pixels */
-      }
-      else
-      {
-         if (ngood)  /* write previous string of good pixels */
-         {
-            fstelm = ii - ngood + first;  /* absolute element number */
-            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-            if (tcode > 0) {  /* variable length arrays have already been written */
-              if (ffpcluk(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
-                status) > 0) {
-		if (*status == NUM_OVERFLOW) 
-		{
-		  overflow = 1;
-		  *status = 0;
-		} else { 
-                  return(*status);
-		}
-	      }
-	    }
-            ngood=0;
-         }
-
-         nbad = nbad +1;  /* the consecutive number of bad pixels */
-      }
-    }
-
-    /* finished loop;  now just write the last set of pixels */
-
-    if (ngood)  /* write last string of good pixels */
-    {
-      fstelm = ii - ngood + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      if (tcode > 0) {  /* variable length arrays have already been written */
-        ffpcluk(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
-      }
-    }
-    else if (nbad) /* write last string of bad pixels */
-    {
-      fstelm = ii - nbad + first;  /* absolute element number */
-      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
-      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
-
-      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
-    }
-
-    if (*status <= 0) {
-      if (overflow) {
-        *status = NUM_OVERFLOW;
-      }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffuintfi1(unsigned int *input, /* I - array of values to be converted  */
-            long ntodo,            /* I - number of elements in the array  */
-            double scale,          /* I - FITS TSCALn or BSCALE value      */
-            double zero,           /* I - FITS TZEROn or BZERO  value      */
-            unsigned char *output, /* O - output array of converted values */
-            int *status)           /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] > UCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DUCHAR_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = 0;
-            }
-            else if (dvalue > DUCHAR_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = UCHAR_MAX;
-            }
-            else
-                output[ii] = (unsigned char) (dvalue + .5);
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffuintfi2(unsigned int *input,  /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            short *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] > SHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-                output[ii] = input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DSHRT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MIN;
-            }
-            else if (dvalue > DSHRT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = SHRT_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (short) (dvalue + .5);
-                else
-                    output[ii] = (short) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffuintfi4(unsigned int *input,  /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            INT32BIT *output,  /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 2147483648.)
-    {       
-        /* Instead of subtracting 2147483648, it is more efficient */
-        /* to just flip the sign bit with the XOR operator */
-
-        for (ii = 0; ii < ntodo; ii++)
-             output[ii] =  ( *(int *) &input[ii] ) ^ 0x80000000;
-    }
-    else if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            if (input[ii] > INT32_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-                output[ii] = input[ii];
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DINT_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MIN;
-            }
-            else if (dvalue > DINT_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = INT32_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (INT32BIT) (dvalue + .5);
-                else
-                    output[ii] = (INT32BIT) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffuintfi8(unsigned int *input,  /* I - array of values to be converted  */
-            long ntodo,             /* I - number of elements in the array  */
-            double scale,           /* I - FITS TSCALn or BSCALE value      */
-            double zero,            /* I - FITS TZEROn or BZERO  value      */
-            LONGLONG *output,       /* O - output array of converted values */
-            int *status)            /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required
-*/
-{
-    long ii;
-    double dvalue;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-            dvalue = (input[ii] - zero) / scale;
-
-            if (dvalue < DLONGLONG_MIN)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MIN;
-            }
-            else if (dvalue > DLONGLONG_MAX)
-            {
-                *status = OVERFLOW_ERR;
-                output[ii] = LONGLONG_MAX;
-            }
-            else
-            {
-                if (dvalue >= 0)
-                    output[ii] = (LONGLONG) (dvalue + .5);
-                else
-                    output[ii] = (LONGLONG) (dvalue - .5);
-            }
-        }
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffuintfr4(unsigned int *input,  /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            float *output,     /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (float) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (float) ((input[ii] - zero) / scale);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffuintfr8(unsigned int *input,  /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            double *output,    /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do datatype conversion and scaling if required.
-*/
-{
-    long ii;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-                output[ii] = (double) input[ii];
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-            output[ii] = (input[ii] - zero) / scale;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffuintfstr(unsigned int *input, /* I - array of values to be converted  */
-            long ntodo,        /* I - number of elements in the array  */
-            double scale,      /* I - FITS TSCALn or BSCALE value      */
-            double zero,       /* I - FITS TZEROn or BZERO  value      */
-            char *cform,       /* I - format for output string values  */
-            long twidth,       /* I - width of each field, in chars    */
-            char *output,      /* O - output array of converted values */
-            int *status)       /* IO - error status                    */
-/*
-  Copy input to output prior to writing output to a FITS file.
-  Do scaling if required.
-*/
-{
-    long ii;
-    double dvalue;
-    char *cptr;
-    
-    cptr = output;
-
-    if (scale == 1. && zero == 0.)
-    {       
-        for (ii = 0; ii < ntodo; ii++)
-        {
-           sprintf(output, cform, (double) input[ii]);
-           output += twidth;
-
-           if (*output)  /* if this char != \0, then overflow occurred */
-              *status = OVERFLOW_ERR;
-        }
-    }
-    else
-    {
-        for (ii = 0; ii < ntodo; ii++)
-        {
-          dvalue = (input[ii] - zero) / scale;
-          sprintf(output, cform, dvalue);
-          output += twidth;
-
-          if (*output)  /* if this char != \0, then overflow occurred */
-            *status = OVERFLOW_ERR;
-        }
-    }
-
-    /* replace any commas with periods (e.g., in French locale) */
-    while ((cptr = strchr(cptr, ','))) *cptr = '.';
-    
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/putkey.c b/src/external/OpenGR/3rdparty/cfitsio/putkey.c
deleted file mode 100644
index f09534431..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/putkey.c
+++ /dev/null
@@ -1,3112 +0,0 @@
-/*  This file, putkey.c, contains routines that write keywords to          */
-/*  a FITS header.                                                         */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include 
-#include 
-#include 
-/* stddef.h is apparently needed to define size_t */
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int ffcrim(fitsfile *fptr,      /* I - FITS file pointer           */
-           int bitpix,          /* I - bits per pixel              */
-           int naxis,           /* I - number of axes in the array */
-           long *naxes,         /* I - size of each axis           */
-           int *status)         /* IO - error status               */
-/*
-  create an IMAGE extension following the current HDU. If the
-  current HDU is empty (contains no header keywords), then simply
-  write the required image (or primary array) keywords to the current
-  HDU. 
-*/
-{
-    if (*status > 0)
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    /* create new extension if current header is not empty */
-    if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
-        ffcrhd(fptr, status);
-
-    /* write the required header keywords */
-    ffphpr(fptr, TRUE, bitpix, naxis, naxes, 0, 1, TRUE, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffcrimll(fitsfile *fptr,    /* I - FITS file pointer           */
-           int bitpix,          /* I - bits per pixel              */
-           int naxis,           /* I - number of axes in the array */
-           LONGLONG *naxes,     /* I - size of each axis           */
-           int *status)         /* IO - error status               */
-/*
-  create an IMAGE extension following the current HDU. If the
-  current HDU is empty (contains no header keywords), then simply
-  write the required image (or primary array) keywords to the current
-  HDU. 
-*/
-{
-    if (*status > 0)
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    /* create new extension if current header is not empty */
-    if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
-        ffcrhd(fptr, status);
-
-    /* write the required header keywords */
-    ffphprll(fptr, TRUE, bitpix, naxis, naxes, 0, 1, TRUE, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffcrtb(fitsfile *fptr,  /* I - FITS file pointer                        */
-           int tbltype,     /* I - type of table to create                  */
-           LONGLONG naxis2, /* I - number of rows in the table              */
-           int tfields,     /* I - number of columns in the table           */
-           char **ttype,    /* I - name of each column                      */
-           char **tform,    /* I - value of TFORMn keyword for each column  */
-           char **tunit,    /* I - value of TUNITn keyword for each column  */
-           const char *extnm, /* I - value of EXTNAME keyword, if any         */
-           int *status)     /* IO - error status                            */
-/*
-  Create a table extension in a FITS file. 
-*/
-{
-    LONGLONG naxis1 = 0;
-    long *tbcol = 0;
-
-    if (*status > 0)
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    /* create new extension if current header is not empty */
-    if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
-        ffcrhd(fptr, status);
-
-    if ((fptr->Fptr)->curhdu == 0)  /* have to create dummy primary array */
-    {
-       ffcrim(fptr, 16, 0, tbcol, status);
-       ffcrhd(fptr, status);
-    }
-    
-    if (tbltype == BINARY_TBL)
-    {
-      /* write the required header keywords. This will write PCOUNT = 0 */
-      ffphbn(fptr, naxis2, tfields, ttype, tform, tunit, extnm, 0, status);
-    }
-    else if (tbltype == ASCII_TBL)
-    {
-      /* write the required header keywords */
-      /* default values for naxis1 and tbcol will be calculated */
-      ffphtb(fptr, naxis1, naxis2, tfields, ttype, tbcol, tform, tunit,
-             extnm, status);
-    }
-    else
-      *status = NOT_TABLE;
-
-    return(*status);
-}
-/*-------------------------------------------------------------------------*/
-int ffpktp(fitsfile *fptr,       /* I - FITS file pointer       */
-           const char *filename, /* I - name of template file   */
-           int *status)          /* IO - error status           */
-/*
-  read keywords from template file and append to the FITS file
-*/
-{
-    FILE *diskfile;
-    char card[FLEN_CARD], template[161];
-    char keyname[FLEN_KEYWORD], newname[FLEN_KEYWORD];
-    int keytype;
-    size_t slen;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    diskfile = fopen(filename,"r"); 
-    if (!diskfile)          /* couldn't open file */
-    {
-            ffpmsg("ffpktp could not open the following template file:");
-            ffpmsg(filename);
-            return(*status = FILE_NOT_OPENED); 
-    }
-
-    while (fgets(template, 160, diskfile) )  /* get next template line */
-    {
-      template[160] = '\0';      /* make sure string is terminated */
-      slen = strlen(template);   /* get string length */
-      template[slen - 1] = '\0';  /* over write the 'newline' char */
-
-      if (ffgthd(template, card, &keytype, status) > 0) /* parse template */
-         break;
-
-      strncpy(keyname, card, 8);
-      keyname[8] = '\0';
-
-      if (keytype == -2)            /* rename the card */
-      {
-         strncpy(newname, &card[40], 8);
-         newname[8] = '\0';
-
-         ffmnam(fptr, keyname, newname, status); 
-      }
-      else if (keytype == -1)      /* delete the card */
-      {
-         ffdkey(fptr, keyname, status);
-      }
-      else if (keytype == 0)       /* update the card */
-      {
-         ffucrd(fptr, keyname, card, status);
-      }
-      else if (keytype == 1)      /* append the card */
-      {
-         ffprec(fptr, card, status);
-      }
-      else    /* END card; stop here */
-      {
-         break; 
-      }
-    }
-
-    fclose(diskfile);   /* close the template file */
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpky( fitsfile *fptr,     /* I - FITS file pointer        */
-           int  datatype,      /* I - datatype of the value    */
-           const char *keyname,/* I - name of keyword to write */
-           void *value,        /* I - keyword value            */
-           const char *comm,   /* I - keyword comment          */
-           int  *status)       /* IO - error status            */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  Writes a keyword value with the datatype specified by the 2nd argument.
-*/
-{
-    char errmsg[81];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (datatype == TSTRING)
-    {
-        ffpkys(fptr, keyname, (char *) value, comm, status);
-    }
-    else if (datatype == TBYTE)
-    {
-        ffpkyj(fptr, keyname, (LONGLONG) *(unsigned char *) value, comm, status);
-    }
-    else if (datatype == TSBYTE)
-    {
-        ffpkyj(fptr, keyname, (LONGLONG) *(signed char *) value, comm, status);
-    }
-    else if (datatype == TUSHORT)
-    {
-        ffpkyj(fptr, keyname, (LONGLONG) *(unsigned short *) value, comm, status);
-    }
-    else if (datatype == TSHORT)
-    {
-        ffpkyj(fptr, keyname, (LONGLONG) *(short *) value, comm, status);
-    }
-    else if (datatype == TUINT)
-    {
-        ffpkyg(fptr, keyname, (double) *(unsigned int *) value, 0,
-               comm, status);
-    }
-    else if (datatype == TINT)
-    {
-        ffpkyj(fptr, keyname, (LONGLONG) *(int *) value, comm, status);
-    }
-    else if (datatype == TLOGICAL)
-    {
-        ffpkyl(fptr, keyname, *(int *) value, comm, status);
-    }
-    else if (datatype == TULONG)
-    {
-        ffpkyg(fptr, keyname, (double) *(unsigned long *) value, 0,
-               comm, status);
-    }
-    else if (datatype == TLONG)
-    {
-        ffpkyj(fptr, keyname, (LONGLONG) *(long *) value, comm, status);
-    }
-    else if (datatype == TLONGLONG)
-    {
-        ffpkyj(fptr, keyname, *(LONGLONG *) value, comm, status);
-    }
-    else if (datatype == TFLOAT)
-    {
-        ffpkye(fptr, keyname, *(float *) value, -7, comm, status);
-    }
-    else if (datatype == TDOUBLE)
-    {
-        ffpkyd(fptr, keyname, *(double *) value, -15, comm, status);
-    }
-    else if (datatype == TCOMPLEX)
-    {
-        ffpkyc(fptr, keyname, (float *) value, -7, comm, status);
-    }
-    else if (datatype == TDBLCOMPLEX)
-    {
-        ffpkym(fptr, keyname, (double *) value, -15, comm, status);
-    }
-    else
-    {
-        sprintf(errmsg, "Bad keyword datatype code: %d (ffpky)", datatype);
-        ffpmsg(errmsg);
-        *status = BAD_DATATYPE;
-    }
-
-    return(*status);
-} 
-/*-------------------------------------------------------------------------*/
-int ffprec(fitsfile *fptr,     /* I - FITS file pointer        */
-           const char *card,   /* I - string to be written     */
-           int *status)        /* IO - error status            */
-/*
-  write a keyword record (80 bytes long) to the end of the header
-*/
-{
-    char tcard[FLEN_CARD];
-    size_t len, ii;
-    long nblocks;
-    int keylength;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if ( ((fptr->Fptr)->datastart - (fptr->Fptr)->headend) == 80) /* no room */
-    {
-        nblocks = 1;
-        if (ffiblk(fptr, nblocks, 0, status) > 0) /* insert 2880-byte block */
-            return(*status);  
-    }
-
-    strncpy(tcard,card,80);
-    tcard[80] = '\0';
-
-    len = strlen(tcard);
-
-    /* silently replace any illegal characters with a space */
-    for (ii=0; ii < len; ii++)   
-        if (tcard[ii] < ' ' || tcard[ii] > 126) tcard[ii] = ' ';
-
-    for (ii=len; ii < 80; ii++)    /* fill card with spaces if necessary */
-        tcard[ii] = ' ';
-
-    keylength = strcspn(tcard, "=");   /* support for free-format keywords */
-    if (keylength == 80) keylength = 8;
-    
-    /* test for the common commentary keywords which by definition have 8-char names */
-    if ( !fits_strncasecmp( "COMMENT ", tcard, 8) || !fits_strncasecmp( "HISTORY ", tcard, 8) ||
-         !fits_strncasecmp( "        ", tcard, 8) || !fits_strncasecmp( "CONTINUE", tcard, 8) )
-	 keylength = 8;
-
-    for (ii=0; ii < keylength; ii++)       /* make sure keyword name is uppercase */
-        tcard[ii] = toupper(tcard[ii]);
-
-    fftkey(tcard, status);        /* test keyword name contains legal chars */
-
-/*  no need to do this any more, since any illegal characters have been removed
-    fftrec(tcard, status);  */        /* test rest of keyword for legal chars */
-
-    ffmbyt(fptr, (fptr->Fptr)->headend, IGNORE_EOF, status); /* move to end */
-
-    ffpbyt(fptr, 80, tcard, status);   /* write the 80 byte card */
-
-    if (*status <= 0)
-       (fptr->Fptr)->headend += 80;    /* update end-of-header position */
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkyu( fitsfile *fptr,     /* I - FITS file pointer        */
-            const char *keyname,/* I - name of keyword to write */
-            const char *comm,   /* I - keyword comment          */
-            int  *status)       /* IO - error status            */
-/*
-  Write (put) a null-valued keyword and comment into the FITS header.  
-*/
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    strcpy(valstring," ");  /* create a dummy value string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword */
-    ffprec(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkys( fitsfile *fptr,     /* I - FITS file pointer        */
-            const char *keyname,/* I - name of keyword to write */
-            const char *value,  /* I - keyword value            */
-            const char *comm,   /* I - keyword comment          */
-            int  *status)       /* IO - error status            */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  The value string will be truncated at 68 characters which is the
-  maximum length that will fit on a single FITS keyword.
-*/
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffs2c(value, valstring, status);   /* put quotes around the string */
-
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword */
-    ffprec(fptr, card, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkls( fitsfile *fptr,     /* I - FITS file pointer        */
-            const char *keyname,/* I - name of keyword to write */
-            const char *value,  /* I - keyword value            */
-            const char *comm,   /* I - keyword comment          */
-            int  *status)       /* IO - error status            */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  This routine is a modified version of ffpkys which supports the
-  HEASARC long string convention and can write arbitrarily long string
-  keyword values.  The value is continued over multiple keywords that
-  have the name COMTINUE without an equal sign in column 9 of the card.
-  This routine also supports simple string keywords which are less than
-  69 characters in length.
-*/
-{
-    char valstring[FLEN_CARD];
-    char card[FLEN_CARD], tmpkeyname[FLEN_CARD];
-    char tstring[FLEN_CARD], *cptr;
-    int next, remain, vlen, nquote, nchar, namelen, contin, tstatus = -1;
-    int commlen=0, nocomment = 0;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    remain = maxvalue(strlen(value), 1); /* no. of chars to write (at least 1) */  
-    if (comm) { 
-       commlen = strlen(comm);
-       if (commlen > 47) commlen = 47;  /* only guarantee preserving the first 47 characters */
-    }
-
-    /* count the number of single quote characters are in the string */
-    tstring[0] = '\0';
-    strncat(tstring, value, 68); /* copy 1st part of string to temp buff */
-    nquote = 0;
-    cptr = strchr(tstring, '\'');   /* search for quote character */
-    while (cptr)  /* search for quote character */
-    {
-        nquote++;            /*  increment no. of quote characters  */
-        cptr++;              /*  increment pointer to next character */
-        cptr = strchr(cptr, '\'');  /* search for another quote char */
-    }
-
-    strncpy(tmpkeyname, keyname, 80);
-    tmpkeyname[80] = '\0';
-    
-    cptr = tmpkeyname;
-    while(*cptr == ' ')   /* skip over leading spaces in name */
-        cptr++;
-
-    /* determine the number of characters that will fit on the line */
-    /* Note: each quote character is expanded to 2 quotes */
-
-    namelen = strlen(cptr);
-    if (namelen <= 8 && (fftkey(cptr, &tstatus) <= 0) )
-    {
-        /* This a normal 8-character FITS keyword */
-        nchar = 68 - nquote; /*  max of 68 chars fit in a FITS string value */
-    }
-    else
-    {
-	   nchar = 80 - nquote - namelen - 5;
-    }
-
-    contin = 0;
-    next = 0;                  /* pointer to next character to write */
-
-    while (remain > 0)
-    {
-        tstring[0] = '\0';
-        strncat(tstring, &value[next], nchar); /* copy string to temp buff */
-        ffs2c(tstring, valstring, status);  /* expand quotes, and put quotes around the string */
-
-        if (remain > nchar)   /* if string is continued, put & as last char */
-        {
-            vlen = strlen(valstring);
-            nchar -= 1;        /* outputting one less character now */
-
-            if (valstring[vlen-2] != '\'')
-                valstring[vlen-2] = '&';  /*  over write last char with &  */
-            else
-            { /* last char was a pair of single quotes, so over write both */
-                valstring[vlen-3] = '&';
-                valstring[vlen-1] = '\0';
-            }
-        }
-
-        if (contin)           /* This is a CONTINUEd keyword */
-        {
-           if (nocomment) {
-               ffmkky("CONTINUE", valstring, NULL, card, status); /* make keyword w/o comment */
-           } else {
-               ffmkky("CONTINUE", valstring, comm, card, status); /* make keyword */
-	   }
-           strncpy(&card[8], "   ",  2);  /* overwrite the '=' */
-        }
-        else
-        {
-           ffmkky(keyname, valstring, comm, card, status);  /* make keyword */
-        }
-
-        ffprec(fptr, card, status);  /* write the keyword */
-
-        contin = 1;
-        remain -= nchar;
-        next  += nchar;
-        nocomment = 0;
-
-        if (remain > 0) 
-        {
-           /* count the number of single quote characters in next section */
-           tstring[0] = '\0';
-           strncat(tstring, &value[next], 68); /* copy next part of string */
-           nquote = 0;
-           cptr = strchr(tstring, '\'');   /* search for quote character */
-           while (cptr)  /* search for quote character */
-           {
-               nquote++;            /*  increment no. of quote characters  */
-               cptr++;              /*  increment pointer to next character */
-               cptr = strchr(cptr, '\'');  /* search for another quote char */
-           }
-           nchar = 68 - nquote;  /* max number of chars to write this time */
-        }
-
-        /* make adjustment if necessary to allow reasonable room for a comment on last CONTINUE card 
-	   only need to do this if 
-	     a) there is a comment string, and
-	     b) the remaining value string characters could all fit on the next CONTINUE card, and
-	     c) there is not enough room on the next CONTINUE card for both the remaining value
-	        characters, and at least 47 characters of the comment string.
-	*/
-	
-        if (commlen > 0 && remain + nquote < 69 && remain + nquote + commlen > 65) 
-	{
-            if (nchar > 18) { /* only false if there are a rediculous number of quotes in the string */
-	        nchar = remain - 15;  /* force continuation onto another card, so that */
-		                      /* there is room for a comment up to 47 chara long */
-                nocomment = 1;  /* don't write the comment string this time */
-            }
-	}
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffplsw( fitsfile *fptr,     /* I - FITS file pointer  */
-            int  *status)       /* IO - error status       */
-/*
-  Write the LONGSTRN keyword and a series of related COMMENT keywords
-  which document that this FITS header may contain long string keyword
-  values which are continued over multiple keywords using the HEASARC
-  long string keyword convention.  If the LONGSTRN keyword already exists
-  then this routine simple returns without doing anything.
-*/
-{
-    char valstring[FLEN_VALUE], comm[FLEN_COMMENT];
-    int tstatus;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    tstatus = 0;
-    if (ffgkys(fptr, "LONGSTRN", valstring, comm, &tstatus) == 0)
-        return(*status);     /* keyword already exists, so just return */
-
-    ffpkys(fptr, "LONGSTRN", "OGIP 1.0", 
-       "The HEASARC Long String Convention may be used.", status);
-
-    ffpcom(fptr,
-    "  This FITS file may contain long string keyword values that are", status);
-
-    ffpcom(fptr,
-    "  continued over multiple keywords.  The HEASARC convention uses the &",
-    status);
-
-    ffpcom(fptr,
-    "  character at the end of each substring which is then continued", status);
-
-    ffpcom(fptr,
-    "  on the next keyword which has the name CONTINUE.", status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkyl( fitsfile *fptr,     /* I - FITS file pointer        */
-            const char *keyname,/* I - name of keyword to write */
-            int  value,         /* I - keyword value            */
-            const char *comm,   /* I - keyword comment          */
-            int  *status)       /* IO - error status            */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  Values equal to 0 will result in a False FITS keyword; any other
-  non-zero value will result in a True FITS keyword.
-*/
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffl2c(value, valstring, status);   /* convert to formatted string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffprec(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkyj( fitsfile *fptr,     /* I - FITS file pointer        */
-            const char *keyname,/* I - name of keyword to write */
-            LONGLONG value,     /* I - keyword value            */
-            const char *comm,   /* I - keyword comment          */
-            int  *status)       /* IO - error status            */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  Writes an integer keyword value.
-*/
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffi2c(value, valstring, status);   /* convert to formatted string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffprec(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkyf( fitsfile *fptr,      /* I - FITS file pointer                   */
-            const char  *keyname,/* I - name of keyword to write            */
-            float value,         /* I - keyword value                       */
-            int   decim,         /* I - number of decimal places to display */
-            const char  *comm,   /* I - keyword comment                     */
-            int   *status)       /* IO - error status                       */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  Writes a fixed float keyword value.
-*/
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffr2f(value, decim, valstring, status);   /* convert to formatted string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffprec(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkye( fitsfile *fptr,      /* I - FITS file pointer                   */
-            const char  *keyname,/* I - name of keyword to write            */
-            float value,         /* I - keyword value                       */
-            int   decim,         /* I - number of decimal places to display */
-            const char  *comm,   /* I - keyword comment                     */
-            int   *status)       /* IO - error status                       */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  Writes an exponential float keyword value.
-*/
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffr2e(value, decim, valstring, status);   /* convert to formatted string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffprec(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkyg( fitsfile *fptr,      /* I - FITS file pointer                   */
-            const char  *keyname,/* I - name of keyword to write            */
-            double value,        /* I - keyword value                       */
-            int   decim,         /* I - number of decimal places to display */
-            const char  *comm,   /* I - keyword comment                     */
-            int   *status)       /* IO - error status                       */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  Writes a fixed double keyword value.*/
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffd2f(value, decim, valstring, status);  /* convert to formatted string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffprec(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkyd( fitsfile *fptr,      /* I - FITS file pointer                   */
-            const char  *keyname,/* I - name of keyword to write            */
-            double value,        /* I - keyword value                       */
-            int   decim,         /* I - number of decimal places to display */
-            const char  *comm,   /* I - keyword comment                     */
-            int   *status)       /* IO - error status                       */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  Writes an exponential double keyword value.*/
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffd2e(value, decim, valstring, status);  /* convert to formatted string */
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffprec(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkyc( fitsfile *fptr,      /* I - FITS file pointer                   */
-            const char  *keyname,/* I - name of keyword to write            */
-            float *value,        /* I - keyword value (real, imaginary)     */
-            int   decim,         /* I - number of decimal places to display */
-            const char  *comm,   /* I - keyword comment                     */
-            int   *status)       /* IO - error status                       */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  Writes an complex float keyword value. Format = (realvalue, imagvalue)
-*/
-{
-    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    strcpy(valstring, "(" );
-    ffr2e(value[0], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ", ");
-    ffr2e(value[1], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ")");
-
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffprec(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkym( fitsfile *fptr,      /* I - FITS file pointer                   */
-            const char  *keyname,/* I - name of keyword to write            */
-            double *value,       /* I - keyword value (real, imaginary)     */
-            int   decim,         /* I - number of decimal places to display */
-            const char  *comm,   /* I - keyword comment                     */
-            int   *status)       /* IO - error status                       */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  Writes an complex double keyword value. Format = (realvalue, imagvalue)
-*/
-{
-    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    strcpy(valstring, "(" );
-    ffd2e(value[0], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ", ");
-    ffd2e(value[1], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ")");
-
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffprec(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkfc( fitsfile *fptr,      /* I - FITS file pointer                   */
-            const char  *keyname,/* I - name of keyword to write            */
-            float *value,        /* I - keyword value (real, imaginary)     */
-            int   decim,         /* I - number of decimal places to display */
-            const char  *comm,   /* I - keyword comment                     */
-            int   *status)       /* IO - error status                       */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  Writes an complex float keyword value. Format = (realvalue, imagvalue)
-*/
-{
-    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    strcpy(valstring, "(" );
-    ffr2f(value[0], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ", ");
-    ffr2f(value[1], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ")");
-
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffprec(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkfm( fitsfile *fptr,      /* I - FITS file pointer                   */
-            const char  *keyname,/* I - name of keyword to write            */
-            double *value,       /* I - keyword value (real, imaginary)     */
-            int   decim,         /* I - number of decimal places to display */
-            const char  *comm,   /* I - keyword comment                     */
-            int   *status)       /* IO - error status                       */
-/*
-  Write (put) the keyword, value and comment into the FITS header.
-  Writes an complex double keyword value. Format = (realvalue, imagvalue)
-*/
-{
-    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    strcpy(valstring, "(" );
-    ffd2f(value[0], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ", ");
-    ffd2f(value[1], decim, tmpstring, status); /* convert to string */
-    strcat(valstring, tmpstring);
-    strcat(valstring, ")");
-
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffprec(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkyt( fitsfile *fptr,      /* I - FITS file pointer        */
-            const char  *keyname,/* I - name of keyword to write */
-            long  intval,        /* I - integer part of value    */
-            double fraction,     /* I - fractional part of value */
-            const char  *comm,   /* I - keyword comment          */
-            int   *status)       /* IO - error status            */
-/*
-  Write (put) a 'triple' precision keyword where the integer and
-  fractional parts of the value are passed in separate parameters to
-  increase the total amount of numerical precision.
-*/
-{
-    char valstring[FLEN_VALUE];
-    char card[FLEN_CARD];
-    char fstring[20], *cptr;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (fraction > 1. || fraction < 0.)
-    {
-        ffpmsg("fraction must be between 0. and 1. (ffpkyt)");
-        return(*status = BAD_F2C);
-    }
-
-    ffi2c(intval, valstring, status);  /* convert integer to string */
-    ffd2f(fraction, 16, fstring, status);  /* convert to 16 decimal string */
-
-    cptr = strchr(fstring, '.');    /* find the decimal point */
-    strcat(valstring, cptr);    /* append the fraction to the integer */
-
-    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
-    ffprec(fptr, card, status);  /* write the keyword*/
-
-    return(*status);
-}
-/*-----------------------------------------------------------------*/
-int ffpcom( fitsfile *fptr,      /* I - FITS file pointer   */
-            const char  *comm,   /* I - comment string      */
-            int   *status)       /* IO - error status       */
-/*
-  Write 1 or more COMMENT keywords.  If the comment string is too
-  long to fit on a single keyword (72 chars) then it will automatically
-  be continued on multiple CONTINUE keywords.
-*/
-{
-    char card[FLEN_CARD];
-    int len, ii;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    len = strlen(comm);
-    ii = 0;
-
-    for (; len > 0; len -= 72)
-    {
-        strcpy(card, "COMMENT ");
-        strncat(card, &comm[ii], 72);
-        ffprec(fptr, card, status);
-        ii += 72;
-    }
-
-    return(*status);
-}
-/*-----------------------------------------------------------------*/
-int ffphis( fitsfile *fptr,      /* I - FITS file pointer  */
-            const char *history, /* I - history string     */
-            int   *status)       /* IO - error status      */
-/*
-  Write 1 or more HISTORY keywords.  If the history string is too
-  long to fit on a single keyword (72 chars) then it will automatically
-  be continued on multiple HISTORY keywords.
-*/
-{
-    char card[FLEN_CARD];
-    int len, ii;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    len = strlen(history);
-    ii = 0;
-
-    for (; len > 0; len -= 72)
-    {
-        strcpy(card, "HISTORY ");
-        strncat(card, &history[ii], 72);
-        ffprec(fptr, card, status);
-        ii += 72;
-    }
-
-    return(*status);
-}
-/*-----------------------------------------------------------------*/
-int ffpdat( fitsfile *fptr,      /* I - FITS file pointer  */
-            int   *status)       /* IO - error status      */
-/*
-  Write the DATE keyword into the FITS header.  If the keyword already
-  exists then the date will simply be updated in the existing keyword.
-*/
-{
-    int timeref;
-    char date[30], tmzone[10], card[FLEN_CARD];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    ffgstm(date, &timeref, status);
-
-    if (timeref)           /* GMT not available on this machine */
-        strcpy(tmzone, " Local");    
-    else
-        strcpy(tmzone, " UT");    
-
-    strcpy(card, "DATE    = '");
-    strcat(card, date);
-    strcat(card, "' / file creation date (YYYY-MM-DDThh:mm:ss");
-    strcat(card, tmzone);
-    strcat(card, ")");
-
-    ffucrd(fptr, "DATE", card, status);
-
-    return(*status);
-}
-/*-------------------------------------------------------------------*/
-int ffverifydate(int year,          /* I - year (0 - 9999)           */
-                 int month,         /* I - month (1 - 12)            */
-                 int day,           /* I - day (1 - 31)              */
-                 int   *status)     /* IO - error status             */
-/*
-  Verify that the date is valid
-*/
-{
-    int ndays[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
-    char errmsg[81];
-    
-
-    if (year < 0 || year > 9999)
-    {
-       sprintf(errmsg, 
-       "input year value = %d is out of range 0 - 9999", year);
-       ffpmsg(errmsg);
-       return(*status = BAD_DATE);
-    }
-    else if (month < 1 || month > 12)
-    {
-       sprintf(errmsg, 
-       "input month value = %d is out of range 1 - 12", month);
-       ffpmsg(errmsg);
-       return(*status = BAD_DATE);
-    }
-    
-    if (ndays[month] == 31) {
-        if (day < 1 || day > 31)
-        {
-           sprintf(errmsg, 
-           "input day value = %d is out of range 1 - 31 for month %d", day, month);
-           ffpmsg(errmsg);
-           return(*status = BAD_DATE);
-        }
-    } else if (ndays[month] == 30) {
-        if (day < 1 || day > 30)
-        {
-           sprintf(errmsg, 
-           "input day value = %d is out of range 1 - 30 for month %d", day, month);
-           ffpmsg(errmsg);
-           return(*status = BAD_DATE);
-        }
-    } else {
-        if (day < 1 || day > 28)
-        {
-            if (day == 29)
-            {
-	      /* year is a leap year if it is divisible by 4 but not by 100,
-	         except years divisible by 400 are leap years
-	      */
-	        if ((year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0)
-		   return (*status);
-		   
- 	        sprintf(errmsg, 
-           "input day value = %d is out of range 1 - 28 for February %d (not leap year)", day, year);
-                ffpmsg(errmsg);
-	    } else {
-                sprintf(errmsg, 
-                "input day value = %d is out of range 1 - 28 (or 29) for February", day);
-                ffpmsg(errmsg);
-	    }
-	    
-            return(*status = BAD_DATE);
-        }
-    }
-    return(*status);
-}
-/*-----------------------------------------------------------------*/
-int ffgstm( char *timestr,   /* O  - returned system date and time string  */
-            int  *timeref,   /* O - GMT = 0, Local time = 1  */
-            int   *status)   /* IO - error status      */
-/*
-  Returns the current date and time in format 'yyyy-mm-ddThh:mm:ss'.
-*/
-{
-    time_t tp;
-    struct tm *ptr;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    time(&tp);
-    ptr = gmtime(&tp);         /* get GMT (= UTC) time */
-
-    if (timeref)
-    {
-        if (ptr)
-            *timeref = 0;   /* returning GMT */
-        else
-            *timeref = 1;   /* returning local time */
-    }
-
-    if (!ptr)                  /* GMT not available on this machine */
-        ptr = localtime(&tp); 
-
-    strftime(timestr, 25, "%Y-%m-%dT%H:%M:%S", ptr);
-
-    return(*status);
-}
-/*-----------------------------------------------------------------*/
-int ffdt2s(int year,          /* I - year (0 - 9999)           */
-           int month,         /* I - month (1 - 12)            */
-           int day,           /* I - day (1 - 31)              */
-           char *datestr,     /* O - date string: "YYYY-MM-DD" */
-           int   *status)     /* IO - error status             */
-/*
-  Construct a date character string
-*/
-{
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    *datestr = '\0';
-    
-    if (ffverifydate(year, month, day, status) > 0)
-    {
-        ffpmsg("invalid date (ffdt2s)");
-        return(*status);
-    }
-
-    if (year >= 1900 && year <= 1998)  /* use old 'dd/mm/yy' format */
-        sprintf(datestr, "%.2d/%.2d/%.2d", day, month, year - 1900);
-
-    else  /* use the new 'YYYY-MM-DD' format */
-        sprintf(datestr, "%.4d-%.2d-%.2d", year, month, day);
-
-    return(*status);
-}
-/*-----------------------------------------------------------------*/
-int ffs2dt(char *datestr,   /* I - date string: "YYYY-MM-DD" or "dd/mm/yy" */
-           int *year,       /* O - year (0 - 9999)                         */
-           int *month,      /* O - month (1 - 12)                          */
-           int *day,        /* O - day (1 - 31)                            */
-           int   *status)   /* IO - error status                           */
-/*
-  Parse a date character string into year, month, and day values
-*/
-{
-    int slen, lyear, lmonth, lday;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (year)
-        *year = 0;
-    if (month)
-        *month = 0;
-    if (day)
-        *day   = 0;
-
-    if (!datestr)
-    {
-        ffpmsg("error: null input date string (ffs2dt)");
-        return(*status = BAD_DATE);   /* Null datestr pointer ??? */
-    }
-
-    slen = strlen(datestr);
-
-    if (slen == 8 && datestr[2] == '/' && datestr[5] == '/')
-    {
-        if (isdigit((int) datestr[0]) && isdigit((int) datestr[1])
-         && isdigit((int) datestr[3]) && isdigit((int) datestr[4])
-         && isdigit((int) datestr[6]) && isdigit((int) datestr[7]) )
-        {
-            /* this is an old format string: "dd/mm/yy" */
-            lyear  = atoi(&datestr[6]) + 1900;
-            lmonth = atoi(&datestr[3]);
-	    lday   = atoi(datestr);
-	    
-            if (year)
-                *year = lyear;
-            if (month)
-                *month = lmonth;
-            if (day)
-                *day   = lday;
-        }
-        else
-        {
-            ffpmsg("input date string has illegal format (ffs2dt):");
-            ffpmsg(datestr);
-            return(*status = BAD_DATE);
-        }
-    }
-    else if (slen >= 10 && datestr[4] == '-' && datestr[7] == '-')
-        {
-        if (isdigit((int) datestr[0]) && isdigit((int) datestr[1])
-         && isdigit((int) datestr[2]) && isdigit((int) datestr[3])
-         && isdigit((int) datestr[5]) && isdigit((int) datestr[6])
-         && isdigit((int) datestr[8]) && isdigit((int) datestr[9]) )
-        {
-            if (slen > 10 && datestr[10] != 'T')
-            {
-                ffpmsg("input date string has illegal format (ffs2dt):");
-                ffpmsg(datestr);
-                return(*status = BAD_DATE);
-            }
-
-            /* this is a new format string: "yyyy-mm-dd" */
-            lyear  = atoi(datestr);
-            lmonth = atoi(&datestr[5]);
-            lday   = atoi(&datestr[8]);
-
-            if (year)
-               *year  = lyear;
-            if (month)
-               *month = lmonth;
-            if (day)
-               *day   = lday;
-        }
-        else
-        {
-                ffpmsg("input date string has illegal format (ffs2dt):");
-                ffpmsg(datestr);
-                return(*status = BAD_DATE);
-        }
-    }
-    else
-    {
-                ffpmsg("input date string has illegal format (ffs2dt):");
-                ffpmsg(datestr);
-                return(*status = BAD_DATE);
-    }
-
-
-    if (ffverifydate(lyear, lmonth, lday, status) > 0)
-    {
-        ffpmsg("invalid date (ffs2dt)");
-    }
-
-    return(*status);
-}
-/*-----------------------------------------------------------------*/
-int fftm2s(int year,          /* I - year (0 - 9999)           */
-           int month,         /* I - month (1 - 12)            */
-           int day,           /* I - day (1 - 31)              */
-           int hour,          /* I - hour (0 - 23)             */
-           int minute,        /* I - minute (0 - 59)           */
-           double second,     /* I - second (0. - 60.9999999)  */
-           int decimals,      /* I - number of decimal points to write      */
-           char *datestr,     /* O - date string: "YYYY-MM-DDThh:mm:ss.ddd" */
-                              /*   or "hh:mm:ss.ddd" if year, month day = 0 */
-           int   *status)     /* IO - error status             */
-/*
-  Construct a date and time character string
-*/
-{
-    int width;
-    char errmsg[81];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    *datestr='\0';
-
-    if (year != 0 || month != 0 || day !=0)
-    { 
-        if (ffverifydate(year, month, day, status) > 0)
-	{
-            ffpmsg("invalid date (fftm2s)");
-            return(*status);
-        }
-    }
-
-    if (hour < 0 || hour > 23)
-    {
-       sprintf(errmsg, 
-       "input hour value is out of range 0 - 23: %d (fftm2s)", hour);
-       ffpmsg(errmsg);
-       return(*status = BAD_DATE);
-    }
-    else if (minute < 0 || minute > 59)
-    {
-       sprintf(errmsg, 
-       "input minute value is out of range 0 - 59: %d (fftm2s)", minute);
-       ffpmsg(errmsg);
-       return(*status = BAD_DATE);
-    }
-    else if (second < 0. || second >= 61)
-    {
-       sprintf(errmsg, 
-       "input second value is out of range 0 - 60.999: %f (fftm2s)", second);
-       ffpmsg(errmsg);
-       return(*status = BAD_DATE);
-    }
-    else if (decimals > 25)
-    {
-       sprintf(errmsg, 
-       "input decimals value is out of range 0 - 25: %d (fftm2s)", decimals);
-       ffpmsg(errmsg);
-       return(*status = BAD_DATE);
-    }
-
-    if (decimals == 0)
-       width = 2;
-    else
-       width = decimals + 3;
-
-    if (decimals < 0)
-    {
-        /* a negative decimals value means return only the date, not time */
-        sprintf(datestr, "%.4d-%.2d-%.2d", year, month, day);
-    }
-    else if (year == 0 && month == 0 && day == 0)
-    {
-        /* return only the time, not the date */
-        sprintf(datestr, "%.2d:%.2d:%0*.*f",
-            hour, minute, width, decimals, second);
-    }
-    else
-    {
-        /* return both the time and date */
-        sprintf(datestr, "%.4d-%.2d-%.2dT%.2d:%.2d:%0*.*f",
-            year, month, day, hour, minute, width, decimals, second);
-    }
-    return(*status);
-}
-/*-----------------------------------------------------------------*/
-int ffs2tm(char *datestr,     /* I - date string: "YYYY-MM-DD"    */
-                              /*     or "YYYY-MM-DDThh:mm:ss.ddd" */
-                              /*     or "dd/mm/yy"                */
-           int *year,         /* O - year (0 - 9999)              */
-           int *month,        /* O - month (1 - 12)               */
-           int *day,          /* O - day (1 - 31)                 */
-           int *hour,          /* I - hour (0 - 23)                */
-           int *minute,        /* I - minute (0 - 59)              */
-           double *second,     /* I - second (0. - 60.9999999)     */
-           int   *status)     /* IO - error status                */
-/*
-  Parse a date character string into date and time values
-*/
-{
-    int slen;
-    char errmsg[81];
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (year)
-       *year   = 0;
-    if (month)
-       *month  = 0;
-    if (day)
-       *day    = 0;
-    if (hour)
-       *hour   = 0;
-    if (minute)
-       *minute = 0;
-    if (second)
-       *second = 0.;
-
-    if (!datestr)
-    {
-        ffpmsg("error: null input date string (ffs2tm)");
-        return(*status = BAD_DATE);   /* Null datestr pointer ??? */
-    }
-
-    if (datestr[2] == '/' || datestr[4] == '-')
-    {
-        /*  Parse the year, month, and date */
-        if (ffs2dt(datestr, year, month, day, status) > 0)
-            return(*status);
-
-        slen = strlen(datestr);
-        if (slen == 8 || slen == 10)
-            return(*status);               /* OK, no time fields */
-        else if (slen < 19) 
-        {
-            ffpmsg("input date string has illegal format:");
-            ffpmsg(datestr);
-            return(*status = BAD_DATE);
-        }
-
-        else if (datestr[10] == 'T' && datestr[13] == ':' && datestr[16] == ':')
-        {
-          if (isdigit((int) datestr[11]) && isdigit((int) datestr[12])
-           && isdigit((int) datestr[14]) && isdigit((int) datestr[15])
-           && isdigit((int) datestr[17]) && isdigit((int) datestr[18]) )
-            {
-                if (slen > 19 && datestr[19] != '.')
-                {
-                  ffpmsg("input date string has illegal format:");
-                  ffpmsg(datestr);
-                  return(*status = BAD_DATE);
-                }
-
-                /* this is a new format string: "yyyy-mm-ddThh:mm:ss.dddd" */
-                if (hour)
-                    *hour   = atoi(&datestr[11]);
-
-                if (minute)
-                    *minute = atoi(&datestr[14]);
-
-                if (second)
-                    *second = atof(&datestr[17]);
-            }
-            else
-            {
-                  ffpmsg("input date string has illegal format:");
-                  ffpmsg(datestr);
-                  return(*status = BAD_DATE);
-            }
-
-        }
-    }
-    else   /* no date fields */
-    {
-        if (datestr[2] == ':' && datestr[5] == ':')   /* time string */
-        {
-            if (isdigit((int) datestr[0]) && isdigit((int) datestr[1])
-             && isdigit((int) datestr[3]) && isdigit((int) datestr[4])
-             && isdigit((int) datestr[6]) && isdigit((int) datestr[7]) )
-            {
-                 /* this is a time string: "hh:mm:ss.dddd" */
-                 if (hour)
-                    *hour   = atoi(&datestr[0]);
-
-                 if (minute)
-                    *minute = atoi(&datestr[3]);
-
-                if (second)
-                    *second = atof(&datestr[6]);
-            }
-            else
-            {
-                  ffpmsg("input date string has illegal format:");
-                  ffpmsg(datestr);
-                  return(*status = BAD_DATE);
-            }
-
-        }
-        else
-        {
-                  ffpmsg("input date string has illegal format:");
-                  ffpmsg(datestr);
-                  return(*status = BAD_DATE);
-        }
-
-    }
-
-    if (hour)
-       if (*hour < 0 || *hour > 23)
-       {
-          sprintf(errmsg, 
-          "hour value is out of range 0 - 23: %d (ffs2tm)", *hour);
-          ffpmsg(errmsg);
-          return(*status = BAD_DATE);
-       }
-
-    if (minute)
-       if (*minute < 0 || *minute > 59)
-       {
-          sprintf(errmsg, 
-          "minute value is out of range 0 - 59: %d (ffs2tm)", *minute);
-          ffpmsg(errmsg);
-          return(*status = BAD_DATE);
-       }
-
-    if (second)
-       if (*second < 0 || *second >= 61.)
-       {
-          sprintf(errmsg, 
-          "second value is out of range 0 - 60.9999: %f (ffs2tm)", *second);
-          ffpmsg(errmsg);
-          return(*status = BAD_DATE);
-       }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgsdt( int *day, int *month, int *year, int *status )
-{  
-/*
-      This routine is included for backward compatibility
-            with the Fortran FITSIO library.
-
-   ffgsdt : Get current System DaTe (GMT if available)
-
-      Return integer values of the day, month, and year
-
-         Function parameters:
-            day      Day of the month
-            month    Numerical month (1=Jan, etc.)
-            year     Year (1999, 2000, etc.)
-            status   output error status
-
-*/
-   time_t now;
-   struct tm *date;
-
-   now = time( NULL );
-   date = gmtime(&now);         /* get GMT (= UTC) time */
-
-   if (!date)                  /* GMT not available on this machine */
-   {
-       date = localtime(&now); 
-   }
-
-   *day = date->tm_mday;
-   *month = date->tm_mon + 1;
-   *year = date->tm_year + 1900;  /* tm_year is defined as years since 1900 */
-   return( *status );
-}
-/*--------------------------------------------------------------------------*/
-int ffpkns( fitsfile *fptr,     /* I - FITS file pointer                    */
-            const char *keyroot,      /* I - root name of keywords to write       */
-            int  nstart,        /* I - starting index number                */
-            int  nkey,          /* I - number of keywords to write          */
-            char *value[],      /* I - array of pointers to keyword values  */
-            char *comm[],       /* I - array of pointers to keyword comment */
-            int  *status)       /* IO - error status                        */
-/*
-  Write (put) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NKEY -1) inclusive.  Writes string keywords.
-  The value strings will be truncated at 68 characters, and the HEASARC
-  long string keyword convention is not supported by this routine.
-*/
-{
-    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
-    int ii, jj, repeat, len;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* check if first comment string is to be repeated for all the keywords */
-    /* by looking to see if the last non-blank character is a '&' char      */
-
-    repeat = 0;
-
-    if (comm)
-    {
-      len = strlen(comm[0]);
-
-      while (len > 0  && comm[0][len - 1] == ' ')
-        len--;                               /* ignore trailing blanks */
-
-      if (comm[0][len - 1] == '&')
-      {
-        len = minvalue(len, FLEN_COMMENT);
-        tcomment[0] = '\0';
-        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
-        repeat = 1;
-      }
-    }
-    else
-    {
-      repeat = 1;
-      tcomment[0] = '\0';
-    }
-
-    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
-    {
-        ffkeyn(keyroot, jj, keyname, status);
-        if (repeat)
-            ffpkys(fptr, keyname, value[ii], tcomment, status);
-        else
-            ffpkys(fptr, keyname, value[ii], comm[ii], status);
-
-        if (*status > 0)
-            return(*status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpknl( fitsfile *fptr,     /* I - FITS file pointer                    */
-            const char *keyroot,      /* I - root name of keywords to write       */
-            int  nstart,        /* I - starting index number                */
-            int  nkey,          /* I - number of keywords to write          */
-            int  *value,        /* I - array of keyword values              */
-            char *comm[],       /* I - array of pointers to keyword comment */
-            int  *status)       /* IO - error status                        */
-/*
-  Write (put) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NKEY -1) inclusive.  Writes logical keywords
-  Values equal to zero will be written as a False FITS keyword value; any
-  other non-zero value will result in a True FITS keyword.
-*/
-{
-    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
-    int ii, jj, repeat, len;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* check if first comment string is to be repeated for all the keywords */
-    /* by looking to see if the last non-blank character is a '&' char      */
-
-    repeat = 0;
-    if (comm)
-    {
-      len = strlen(comm[0]);
-
-      while (len > 0  && comm[0][len - 1] == ' ')
-        len--;                               /* ignore trailing blanks */
-
-      if (comm[0][len - 1] == '&')
-      {
-        len = minvalue(len, FLEN_COMMENT);
-        tcomment[0] = '\0';
-        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
-        repeat = 1;
-      }
-    }
-    else
-    {
-      repeat = 1;
-      tcomment[0] = '\0';
-    }
-
-
-    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
-    {
-        ffkeyn(keyroot, jj, keyname, status);
-
-        if (repeat)
-            ffpkyl(fptr, keyname, value[ii], tcomment, status);
-        else
-            ffpkyl(fptr, keyname, value[ii], comm[ii], status);
-
-        if (*status > 0)
-            return(*status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpknj( fitsfile *fptr,     /* I - FITS file pointer                    */
-            const char *keyroot,      /* I - root name of keywords to write       */
-            int  nstart,        /* I - starting index number                */
-            int  nkey,          /* I - number of keywords to write          */
-            long *value,        /* I - array of keyword values              */
-            char *comm[],       /* I - array of pointers to keyword comment */
-            int  *status)       /* IO - error status                        */
-/*
-  Write (put) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NKEY -1) inclusive.  Write integer keywords
-*/
-{
-    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
-    int ii, jj, repeat, len;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* check if first comment string is to be repeated for all the keywords */
-    /* by looking to see if the last non-blank character is a '&' char      */
-
-    repeat = 0;
-
-    if (comm)
-    {
-      len = strlen(comm[0]);
-
-      while (len > 0  && comm[0][len - 1] == ' ')
-        len--;                               /* ignore trailing blanks */
-
-      if (comm[0][len - 1] == '&')
-      {
-        len = minvalue(len, FLEN_COMMENT);
-        tcomment[0] = '\0';
-        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
-        repeat = 1;
-      }
-    }
-    else
-    {
-      repeat = 1;
-      tcomment[0] = '\0';
-    }
-
-    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
-    {
-        ffkeyn(keyroot, jj, keyname, status);
-        if (repeat)
-            ffpkyj(fptr, keyname, value[ii], tcomment, status);
-        else
-            ffpkyj(fptr, keyname, value[ii], comm[ii], status);
-
-        if (*status > 0)
-            return(*status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpknjj( fitsfile *fptr,    /* I - FITS file pointer                    */
-            const char *keyroot,      /* I - root name of keywords to write       */
-            int  nstart,        /* I - starting index number                */
-            int  nkey,          /* I - number of keywords to write          */
-            LONGLONG *value,    /* I - array of keyword values              */
-            char *comm[],       /* I - array of pointers to keyword comment */
-            int  *status)       /* IO - error status                        */
-/*
-  Write (put) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NKEY -1) inclusive.  Write integer keywords
-*/
-{
-    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
-    int ii, jj, repeat, len;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* check if first comment string is to be repeated for all the keywords */
-    /* by looking to see if the last non-blank character is a '&' char      */
-
-    repeat = 0;
-
-    if (comm)
-    {
-      len = strlen(comm[0]);
-
-      while (len > 0  && comm[0][len - 1] == ' ')
-        len--;                               /* ignore trailing blanks */
-
-      if (comm[0][len - 1] == '&')
-      {
-        len = minvalue(len, FLEN_COMMENT);
-        tcomment[0] = '\0';
-        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
-        repeat = 1;
-      }
-    }
-    else
-    {
-      repeat = 1;
-      tcomment[0] = '\0';
-    }
-
-    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
-    {
-        ffkeyn(keyroot, jj, keyname, status);
-        if (repeat)
-            ffpkyj(fptr, keyname, value[ii], tcomment, status);
-        else
-            ffpkyj(fptr, keyname, value[ii], comm[ii], status);
-
-        if (*status > 0)
-            return(*status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpknf( fitsfile *fptr,     /* I - FITS file pointer                    */
-            const char *keyroot,      /* I - root name of keywords to write       */
-            int  nstart,        /* I - starting index number                */
-            int  nkey,          /* I - number of keywords to write          */
-            float *value,       /* I - array of keyword values              */
-            int decim,          /* I - number of decimals to display        */
-            char *comm[],       /* I - array of pointers to keyword comment */
-            int  *status)       /* IO - error status                        */
-/*
-  Write (put) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NKEY -1) inclusive.  Writes fixed float values.
-*/
-{
-    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
-    int ii, jj, repeat, len;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* check if first comment string is to be repeated for all the keywords */
-    /* by looking to see if the last non-blank character is a '&' char      */
-
-    repeat = 0;
-
-    if (comm)
-    {
-      len = strlen(comm[0]);
-
-      while (len > 0  && comm[0][len - 1] == ' ')
-        len--;                               /* ignore trailing blanks */
-
-      if (comm[0][len - 1] == '&')
-      {
-        len = minvalue(len, FLEN_COMMENT);
-        tcomment[0] = '\0';
-        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
-        repeat = 1;
-      }
-    }
-    else
-    {
-      repeat = 1;
-      tcomment[0] = '\0';
-    }
-
-    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
-    {
-        ffkeyn(keyroot, jj, keyname, status);
-        if (repeat)
-            ffpkyf(fptr, keyname, value[ii], decim, tcomment, status);
-        else
-            ffpkyf(fptr, keyname, value[ii], decim, comm[ii], status);
-
-        if (*status > 0)
-            return(*status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkne( fitsfile *fptr,     /* I - FITS file pointer                    */
-            const char *keyroot,      /* I - root name of keywords to write       */
-            int  nstart,        /* I - starting index number                */
-            int  nkey,          /* I - number of keywords to write          */
-            float *value,       /* I - array of keyword values              */
-            int decim,          /* I - number of decimals to display        */
-            char *comm[],       /* I - array of pointers to keyword comment */
-            int  *status)       /* IO - error status                        */
-/*
-  Write (put) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NKEY -1) inclusive.  Writes exponential float values.
-*/
-{
-    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
-    int ii, jj, repeat, len;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* check if first comment string is to be repeated for all the keywords */
-    /* by looking to see if the last non-blank character is a '&' char      */
-
-    repeat = 0;
-
-    if (comm)
-    {
-      len = strlen(comm[0]);
-
-      while (len > 0  && comm[0][len - 1] == ' ')
-        len--;                               /* ignore trailing blanks */
-
-      if (comm[0][len - 1] == '&')
-      {
-        len = minvalue(len, FLEN_COMMENT);
-        tcomment[0] = '\0';
-        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
-        repeat = 1;
-      }
-    }
-    else
-    {
-      repeat = 1;
-      tcomment[0] = '\0';
-    }
-
-    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
-    {
-        ffkeyn(keyroot, jj, keyname, status);
-        if (repeat)
-            ffpkye(fptr, keyname, value[ii], decim, tcomment, status);
-        else
-            ffpkye(fptr, keyname, value[ii], decim, comm[ii], status);
-
-        if (*status > 0)
-            return(*status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpkng( fitsfile *fptr,     /* I - FITS file pointer                    */
-            const char *keyroot,      /* I - root name of keywords to write       */
-            int  nstart,        /* I - starting index number                */
-            int  nkey,          /* I - number of keywords to write          */
-            double *value,      /* I - array of keyword values              */
-            int decim,          /* I - number of decimals to display        */
-            char *comm[],       /* I - array of pointers to keyword comment */
-            int  *status)       /* IO - error status                        */
-/*
-  Write (put) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NKEY -1) inclusive.  Writes fixed double values.
-*/
-{
-    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
-    int ii, jj, repeat, len;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* check if first comment string is to be repeated for all the keywords */
-    /* by looking to see if the last non-blank character is a '&' char      */
-
-    repeat = 0;
-
-    if (comm)
-    {
-      len = strlen(comm[0]);
-
-      while (len > 0  && comm[0][len - 1] == ' ')
-        len--;                               /* ignore trailing blanks */
-
-      if (comm[0][len - 1] == '&')
-      {
-        len = minvalue(len, FLEN_COMMENT);
-        tcomment[0] = '\0';
-        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
-        repeat = 1;
-      }
-    }
-    else
-    {
-      repeat = 1;
-      tcomment[0] = '\0';
-    }
-
-    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
-    {
-        ffkeyn(keyroot, jj, keyname, status);
-        if (repeat)
-            ffpkyg(fptr, keyname, value[ii], decim, tcomment, status);
-        else
-            ffpkyg(fptr, keyname, value[ii], decim, comm[ii], status);
-
-        if (*status > 0)
-            return(*status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpknd( fitsfile *fptr,     /* I - FITS file pointer                    */
-            const char *keyroot,      /* I - root name of keywords to write       */
-            int  nstart,        /* I - starting index number                */
-            int  nkey,          /* I - number of keywords to write          */
-            double *value,      /* I - array of keyword values              */
-            int decim,          /* I - number of decimals to display        */
-            char *comm[],       /* I - array of pointers to keyword comment */
-            int  *status)       /* IO - error status                        */
-/*
-  Write (put) an indexed array of keywords with index numbers between
-  NSTART and (NSTART + NKEY -1) inclusive.  Writes exponential double values.
-*/
-{
-    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
-    int ii, jj, repeat, len;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    /* check if first comment string is to be repeated for all the keywords */
-    /* by looking to see if the last non-blank character is a '&' char      */
-
-    repeat = 0;
-
-    if (comm)
-    {
-      len = strlen(comm[0]);
-
-      while (len > 0  && comm[0][len - 1] == ' ')
-        len--;                               /* ignore trailing blanks */
-
-      if (comm[0][len - 1] == '&')
-      {
-        len = minvalue(len, FLEN_COMMENT);
-        tcomment[0] = '\0';
-        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
-        repeat = 1;
-      }
-    }
-    else
-    {
-      repeat = 1;
-      tcomment[0] = '\0';
-    }
-
-    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
-    {
-        ffkeyn(keyroot, jj, keyname, status);
-        if (repeat)
-            ffpkyd(fptr, keyname, value[ii], decim, tcomment, status);
-        else
-            ffpkyd(fptr, keyname, value[ii], decim, comm[ii], status);
-
-        if (*status > 0)
-            return(*status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffptdm( fitsfile *fptr, /* I - FITS file pointer                        */
-            int colnum,     /* I - column number                            */
-            int naxis,      /* I - number of axes in the data array         */
-            long naxes[],   /* I - length of each data axis                 */
-            int *status)    /* IO - error status                            */
-/*
-  write the TDIMnnn keyword describing the dimensionality of a column
-*/
-{
-    char keyname[FLEN_KEYWORD], tdimstr[FLEN_VALUE], comm[FLEN_COMMENT];
-    char value[80], message[81];
-    int ii;
-    long totalpix = 1, repeat;
-    tcolumn *colptr;
-
-    if (*status > 0)
-        return(*status);
-
-    if (colnum < 1 || colnum > 999)
-    {
-        ffpmsg("column number is out of range 1 - 999 (ffptdm)");
-        return(*status = BAD_COL_NUM);
-    }
-
-    if (naxis < 1)
-    {
-        ffpmsg("naxis is less than 1 (ffptdm)");
-        return(*status = BAD_DIMEN);
-    }
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-
-    if ( (fptr->Fptr)->hdutype != BINARY_TBL)
-    {
-       ffpmsg(
-    "Error: The TDIMn keyword is only allowed in BINTABLE extensions (ffptdm)");
-       return(*status = NOT_BTABLE);
-    }
-
-    strcpy(tdimstr, "(");            /* start constructing the TDIM value */   
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-        if (ii > 0)
-            strcat(tdimstr, ",");   /* append the comma separator */
-
-        if (naxes[ii] < 0)
-        {
-            ffpmsg("one or more TDIM values are less than 0 (ffptdm)");
-            return(*status = BAD_TDIM);
-        }
-
-        sprintf(value, "%ld", naxes[ii]);
-        strcat(tdimstr, value);     /* append the axis size */
-
-        totalpix *= naxes[ii];
-    }
-
-    colptr = (fptr->Fptr)->tableptr;  /* point to first column structure */
-    colptr += (colnum - 1);      /* point to the specified column number */
-
-    if ((long) colptr->trepeat != totalpix)
-    {
-      /* There is an apparent inconsistency between TDIMn and TFORMn. */
-      /* The colptr->trepeat value may be out of date, so re-read     */
-      /* the TFORMn keyword to be sure.                               */
-
-      ffkeyn("TFORM", colnum, keyname, status);   /* construct TFORMn name  */
-      ffgkys(fptr, keyname, value, NULL, status); /* read TFORMn keyword    */
-      ffbnfm(value, NULL, &repeat, NULL, status); /* parse the repeat count */
-
-      if (*status > 0 || repeat != totalpix)
-      {
-        sprintf(message,
-        "column vector length, %ld, does not equal TDIMn array size, %ld",
-        (long) colptr->trepeat, totalpix);
-        ffpmsg(message);
-        return(*status = BAD_TDIM);
-      }
-    }
-
-    strcat(tdimstr, ")" );            /* append the closing parenthesis */
-
-    strcpy(comm, "size of the multidimensional array");
-    ffkeyn("TDIM", colnum, keyname, status);      /* construct TDIMn name */
-    ffpkys(fptr, keyname, tdimstr, comm, status);  /* write the keyword */
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffptdmll( fitsfile *fptr, /* I - FITS file pointer                      */
-            int colnum,     /* I - column number                            */
-            int naxis,      /* I - number of axes in the data array         */
-            LONGLONG naxes[], /* I - length of each data axis               */
-            int *status)    /* IO - error status                            */
-/*
-  write the TDIMnnn keyword describing the dimensionality of a column
-*/
-{
-    char keyname[FLEN_KEYWORD], tdimstr[FLEN_VALUE], comm[FLEN_COMMENT];
-    char value[80], message[81];
-    int ii;
-    LONGLONG totalpix = 1, repeat;
-    tcolumn *colptr;
-
-    if (*status > 0)
-        return(*status);
-
-    if (colnum < 1 || colnum > 999)
-    {
-        ffpmsg("column number is out of range 1 - 999 (ffptdm)");
-        return(*status = BAD_COL_NUM);
-    }
-
-    if (naxis < 1)
-    {
-        ffpmsg("naxis is less than 1 (ffptdm)");
-        return(*status = BAD_DIMEN);
-    }
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
-        if ( ffrdef(fptr, status) > 0)               /* rescan header */
-            return(*status);
-
-    if ( (fptr->Fptr)->hdutype != BINARY_TBL)
-    {
-       ffpmsg(
-    "Error: The TDIMn keyword is only allowed in BINTABLE extensions (ffptdm)");
-       return(*status = NOT_BTABLE);
-    }
-
-    strcpy(tdimstr, "(");            /* start constructing the TDIM value */   
-
-    for (ii = 0; ii < naxis; ii++)
-    {
-        if (ii > 0)
-            strcat(tdimstr, ",");   /* append the comma separator */
-
-        if (naxes[ii] < 0)
-        {
-            ffpmsg("one or more TDIM values are less than 0 (ffptdm)");
-            return(*status = BAD_TDIM);
-        }
-
-        /* cast to double because the 64-bit int conversion character in */
-        /* sprintf is platform dependent ( %lld, %ld, %I64d )            */
-
-        sprintf(value, "%.0f", (double) naxes[ii]);
-
-        strcat(tdimstr, value);     /* append the axis size */
-
-        totalpix *= naxes[ii];
-    }
-
-    colptr = (fptr->Fptr)->tableptr;  /* point to first column structure */
-    colptr += (colnum - 1);      /* point to the specified column number */
-
-    if ( colptr->trepeat != totalpix)
-    {
-      /* There is an apparent inconsistency between TDIMn and TFORMn. */
-      /* The colptr->trepeat value may be out of date, so re-read     */
-      /* the TFORMn keyword to be sure.                               */
-
-      ffkeyn("TFORM", colnum, keyname, status);   /* construct TFORMn name  */
-      ffgkys(fptr, keyname, value, NULL, status); /* read TFORMn keyword    */
-      ffbnfmll(value, NULL, &repeat, NULL, status); /* parse the repeat count */
-
-      if (*status > 0 || repeat != totalpix)
-      {
-        sprintf(message,
-        "column vector length, %.0f, does not equal TDIMn array size, %.0f",
-        (double) (colptr->trepeat), (double) totalpix);
-        ffpmsg(message);
-        return(*status = BAD_TDIM);
-      }
-    }
-
-    strcat(tdimstr, ")" );            /* append the closing parenthesis */
-
-    strcpy(comm, "size of the multidimensional array");
-    ffkeyn("TDIM", colnum, keyname, status);      /* construct TDIMn name */
-    ffpkys(fptr, keyname, tdimstr, comm, status);  /* write the keyword */
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffphps( fitsfile *fptr, /* I - FITS file pointer                        */
-            int bitpix,     /* I - number of bits per data value pixel      */
-            int naxis,      /* I - number of axes in the data array         */
-            long naxes[],   /* I - length of each data axis                 */
-            int *status)    /* IO - error status                            */
-/*
-  write STANDARD set of required primary header keywords
-*/
-{
-    int simple = 1;     /* does file conform to FITS standard? 1/0  */
-    long pcount = 0;    /* number of group parameters (usually 0)   */
-    long gcount = 1;    /* number of random groups (usually 1 or 0) */
-    int extend = 1;     /* may FITS file have extensions?           */
-
-    ffphpr(fptr, simple, bitpix, naxis, naxes, pcount, gcount, extend, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffphpsll( fitsfile *fptr, /* I - FITS file pointer                        */
-            int bitpix,     /* I - number of bits per data value pixel      */
-            int naxis,      /* I - number of axes in the data array         */
-            LONGLONG naxes[],   /* I - length of each data axis                 */
-            int *status)    /* IO - error status                            */
-/*
-  write STANDARD set of required primary header keywords
-*/
-{
-    int simple = 1;     /* does file conform to FITS standard? 1/0  */
-    LONGLONG pcount = 0;    /* number of group parameters (usually 0)   */
-    LONGLONG gcount = 1;    /* number of random groups (usually 1 or 0) */
-    int extend = 1;     /* may FITS file have extensions?           */
-
-    ffphprll(fptr, simple, bitpix, naxis, naxes, pcount, gcount, extend, status);
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffphpr( fitsfile *fptr, /* I - FITS file pointer                        */
-            int simple,     /* I - does file conform to FITS standard? 1/0  */
-            int bitpix,     /* I - number of bits per data value pixel      */
-            int naxis,      /* I - number of axes in the data array         */
-            long naxes[],   /* I - length of each data axis                 */
-            LONGLONG pcount, /* I - number of group parameters (usually 0)   */
-            LONGLONG gcount, /* I - number of random groups (usually 1 or 0) */
-            int extend,     /* I - may FITS file have extensions?           */
-            int *status)    /* IO - error status                            */
-/*
-  write required primary header keywords
-*/
-{
-    int ii;
-    LONGLONG naxesll[20];
-   
-    for (ii = 0; (ii < naxis) && (ii < 20); ii++)
-       naxesll[ii] = naxes[ii];
-
-    ffphprll(fptr, simple, bitpix, naxis, naxesll, pcount, gcount,
-             extend, status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffphprll( fitsfile *fptr, /* I - FITS file pointer                        */
-            int simple,     /* I - does file conform to FITS standard? 1/0  */
-            int bitpix,     /* I - number of bits per data value pixel      */
-            int naxis,      /* I - number of axes in the data array         */
-            LONGLONG naxes[], /* I - length of each data axis                 */
-            LONGLONG pcount,  /* I - number of group parameters (usually 0)   */
-            LONGLONG gcount,  /* I - number of random groups (usually 1 or 0) */
-            int extend,     /* I - may FITS file have extensions?           */
-            int *status)    /* IO - error status                            */
-/*
-  write required primary header keywords
-*/
-{
-    int ii;
-    long longbitpix, tnaxes[20];
-    char name[FLEN_KEYWORD], comm[FLEN_COMMENT], message[FLEN_ERRMSG];
-
-    if (*status > 0)
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
-        return(*status = HEADER_NOT_EMPTY);
-
-    if (naxis != 0)   /* never try to compress a null image */
-    {
-      if ( (fptr->Fptr)->request_compress_type )
-      {
-      
-       for (ii = 0; ii < naxis; ii++)
-           tnaxes[ii] = (long) naxes[ii];
-	   
-        /* write header for a compressed image */
-        imcomp_init_table(fptr, bitpix, naxis, tnaxes, 1, status);
-        return(*status);
-      }
-    }  
-
-    if ((fptr->Fptr)->curhdu == 0)
-    {                /* write primary array header */
-        if (simple)
-            strcpy(comm, "file does conform to FITS standard");
-        else
-            strcpy(comm, "file does not conform to FITS standard");
-
-        ffpkyl(fptr, "SIMPLE", simple, comm, status);
-    }
-    else
-    {               /* write IMAGE extension header */
-        strcpy(comm, "IMAGE extension");
-        ffpkys(fptr, "XTENSION", "IMAGE", comm, status);
-    }
-
-    longbitpix = bitpix;
-
-    /* test for the 3 special cases that represent unsigned integers */
-    if (longbitpix == USHORT_IMG)
-        longbitpix = SHORT_IMG;
-    else if (longbitpix == ULONG_IMG)
-        longbitpix = LONG_IMG;
-    else if (longbitpix == SBYTE_IMG)
-        longbitpix = BYTE_IMG;
-
-    if (longbitpix != BYTE_IMG && longbitpix != SHORT_IMG && 
-        longbitpix != LONG_IMG && longbitpix != LONGLONG_IMG &&
-        longbitpix != FLOAT_IMG && longbitpix != DOUBLE_IMG)
-    {
-        sprintf(message,
-        "Illegal value for BITPIX keyword: %d", bitpix);
-        ffpmsg(message);
-        return(*status = BAD_BITPIX);
-    }
-
-    strcpy(comm, "number of bits per data pixel");
-    if (ffpkyj(fptr, "BITPIX", longbitpix, comm, status) > 0)
-        return(*status);
-
-    if (naxis < 0 || naxis > 999)
-    {
-        sprintf(message,
-        "Illegal value for NAXIS keyword: %d", naxis);
-        ffpmsg(message);
-        return(*status = BAD_NAXIS);
-    }
-
-    strcpy(comm, "number of data axes");
-    ffpkyj(fptr, "NAXIS", naxis, comm, status);
-
-    strcpy(comm, "length of data axis ");
-    for (ii = 0; ii < naxis; ii++)
-    {
-        if (naxes[ii] < 0)
-        {
-            sprintf(message,
-            "Illegal negative value for NAXIS%d keyword: %.0f", ii + 1, (double) (naxes[ii]));
-            ffpmsg(message);
-            return(*status = BAD_NAXES);
-        }
-
-        sprintf(&comm[20], "%d", ii + 1);
-        ffkeyn("NAXIS", ii + 1, name, status);
-        ffpkyj(fptr, name, naxes[ii], comm, status);
-    }
-
-    if ((fptr->Fptr)->curhdu == 0)  /* the primary array */
-    {
-        if (extend)
-        {
-            /* only write EXTEND keyword if value = true */
-            strcpy(comm, "FITS dataset may contain extensions");
-            ffpkyl(fptr, "EXTEND", extend, comm, status);
-        }
-
-        if (pcount < 0)
-        {
-            ffpmsg("pcount value is less than 0");
-            return(*status = BAD_PCOUNT);
-        }
-
-        else if (gcount < 1)
-        {
-            ffpmsg("gcount value is less than 1");
-            return(*status = BAD_GCOUNT);
-        }
-
-        else if (pcount > 0 || gcount > 1)
-        {
-            /* only write these keyword if non-standard values */
-            strcpy(comm, "random group records are present");
-            ffpkyl(fptr, "GROUPS", 1, comm, status);
-
-            strcpy(comm, "number of random group parameters");
-            ffpkyj(fptr, "PCOUNT", pcount, comm, status);
-  
-            strcpy(comm, "number of random groups");
-            ffpkyj(fptr, "GCOUNT", gcount, comm, status);
-        }
-
-      /* write standard block of self-documentating comments */
-      ffprec(fptr,
-      "COMMENT   FITS (Flexible Image Transport System) format is defined in 'Astronomy",
-      status);
-      ffprec(fptr,
-      "COMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H",
-      status);
-    }
-
-    else  /* an IMAGE extension */
-
-    {   /* image extension; cannot have random groups */
-        if (pcount != 0)
-        {
-            ffpmsg("image extensions must have pcount = 0");
-            *status = BAD_PCOUNT;
-        }
-
-        else if (gcount != 1)
-        {
-            ffpmsg("image extensions must have gcount = 1");
-            *status = BAD_GCOUNT;
-        }
-
-        else
-        {
-            strcpy(comm, "required keyword; must = 0");
-            ffpkyj(fptr, "PCOUNT", 0, comm, status);
-  
-            strcpy(comm, "required keyword; must = 1");
-            ffpkyj(fptr, "GCOUNT", 1, comm, status);
-        }
-    }
-
-    /* Write the BSCALE and BZERO keywords, if an unsigned integer image */
-    if (bitpix == USHORT_IMG)
-    {
-        strcpy(comm, "offset data range to that of unsigned short");
-        ffpkyg(fptr, "BZERO", 32768., 0, comm, status);
-        strcpy(comm, "default scaling factor");
-        ffpkyg(fptr, "BSCALE", 1.0, 0, comm, status);
-    }
-    else if (bitpix == ULONG_IMG)
-    {
-        strcpy(comm, "offset data range to that of unsigned long");
-        ffpkyg(fptr, "BZERO", 2147483648., 0, comm, status);
-        strcpy(comm, "default scaling factor");
-        ffpkyg(fptr, "BSCALE", 1.0, 0, comm, status);
-    }
-    else if (bitpix == SBYTE_IMG)
-    {
-        strcpy(comm, "offset data range to that of signed byte");
-        ffpkyg(fptr, "BZERO", -128., 0, comm, status);
-        strcpy(comm, "default scaling factor");
-        ffpkyg(fptr, "BSCALE", 1.0, 0, comm, status);
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffphtb(fitsfile *fptr,  /* I - FITS file pointer                        */
-           LONGLONG naxis1,     /* I - width of row in the table                */
-           LONGLONG naxis2,     /* I - number of rows in the table              */
-           int tfields,     /* I - number of columns in the table           */
-           char **ttype,    /* I - name of each column                      */
-           long *tbcol,     /* I - byte offset in row to each column        */
-           char **tform,    /* I - value of TFORMn keyword for each column  */
-           char **tunit,    /* I - value of TUNITn keyword for each column  */
-           const char *extnmx,   /* I - value of EXTNAME keyword, if any         */
-           int *status)     /* IO - error status                            */
-/*
-  Put required Header keywords into the ASCII TaBle:
-*/
-{
-    int ii, ncols, gotmem = 0;
-    long rowlen; /* must be 'long' because it is passed to ffgabc */
-    char tfmt[30], name[FLEN_KEYWORD], comm[FLEN_COMMENT], extnm[FLEN_VALUE];
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if (*status > 0)
-        return(*status);
-    else if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
-        return(*status = HEADER_NOT_EMPTY);
-    else if (naxis1 < 0)
-        return(*status = NEG_WIDTH);
-    else if (naxis2 < 0)
-        return(*status = NEG_ROWS);
-    else if (tfields < 0 || tfields > 999)
-        return(*status = BAD_TFIELDS);
-    
-    extnm[0] = '\0';
-    if (extnmx)
-        strncat(extnm, extnmx, FLEN_VALUE-1);
-
-    rowlen = (long) naxis1;
-
-    if (!tbcol || !tbcol[0] || (!naxis1 && tfields)) /* spacing not defined? */
-    {
-      /* allocate mem for tbcol; malloc can have problems allocating small */
-      /* arrays, so allocate at least 20 bytes */
-
-      ncols = maxvalue(5, tfields);
-      tbcol = (long *) calloc(ncols, sizeof(long));
-
-      if (tbcol)
-      {
-        gotmem = 1;
-
-        /* calculate width of a row and starting position of each column. */
-        /* Each column will be separated by 1 blank space */
-        ffgabc(tfields, tform, 1, &rowlen, tbcol, status);
-      }
-    }
-    ffpkys(fptr, "XTENSION", "TABLE", "ASCII table extension", status);
-    ffpkyj(fptr, "BITPIX", 8, "8-bit ASCII characters", status);
-    ffpkyj(fptr, "NAXIS", 2, "2-dimensional ASCII table", status);
-    ffpkyj(fptr, "NAXIS1", rowlen, "width of table in characters", status);
-    ffpkyj(fptr, "NAXIS2", naxis2, "number of rows in table", status);
-    ffpkyj(fptr, "PCOUNT", 0, "no group parameters (required keyword)", status);
-    ffpkyj(fptr, "GCOUNT", 1, "one data group (required keyword)", status);
-    ffpkyj(fptr, "TFIELDS", tfields, "number of fields in each row", status);
-
-    for (ii = 0; ii < tfields; ii++) /* loop over every column */
-    {
-        if ( *(ttype[ii]) )  /* optional TTYPEn keyword */
-        {
-          sprintf(comm, "label for field %3d", ii + 1);
-          ffkeyn("TTYPE", ii + 1, name, status);
-          ffpkys(fptr, name, ttype[ii], comm, status);
-        }
-
-        if (tbcol[ii] < 1 || tbcol[ii] > rowlen)
-           *status = BAD_TBCOL;
-
-        sprintf(comm, "beginning column of field %3d", ii + 1);
-        ffkeyn("TBCOL", ii + 1, name, status);
-        ffpkyj(fptr, name, tbcol[ii], comm, status);
-
-        strcpy(tfmt, tform[ii]);  /* required TFORMn keyword */
-        ffupch(tfmt);
-        ffkeyn("TFORM", ii + 1, name, status);
-        ffpkys(fptr, name, tfmt, "Fortran-77 format of field", status);
-
-        if (tunit)
-        {
-         if (tunit[ii] && *(tunit[ii]) )  /* optional TUNITn keyword */
-         {
-          ffkeyn("TUNIT", ii + 1, name, status);
-          ffpkys(fptr, name, tunit[ii], "physical unit of field", status) ;
-         }
-        }
-
-        if (*status > 0)
-            break;       /* abort loop on error */
-    }
-
-    if (extnm[0])       /* optional EXTNAME keyword */
-        ffpkys(fptr, "EXTNAME", extnm,
-               "name of this ASCII table extension", status);
-
-    if (*status > 0)
-        ffpmsg("Failed to write ASCII table header keywords (ffphtb)");
-
-    if (gotmem)
-        free(tbcol); 
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffphbn(fitsfile *fptr,  /* I - FITS file pointer                        */
-           LONGLONG naxis2,     /* I - number of rows in the table              */
-           int tfields,     /* I - number of columns in the table           */
-           char **ttype,    /* I - name of each column                      */
-           char **tform,    /* I - value of TFORMn keyword for each column  */
-           char **tunit,    /* I - value of TUNITn keyword for each column  */
-           const char *extnmx,   /* I - value of EXTNAME keyword, if any         */
-           LONGLONG pcount,     /* I - size of the variable length heap area    */
-           int *status)     /* IO - error status                            */
-/*
-  Put required Header keywords into the Binary Table:
-*/
-{
-    int ii, datatype, iread = 0;
-    long repeat, width;
-    LONGLONG naxis1;
-
-    char tfmt[30], name[FLEN_KEYWORD], comm[FLEN_COMMENT], extnm[FLEN_VALUE];
-    char *cptr;
-
-    if (*status > 0)
-        return(*status);
-
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
-        return(*status = HEADER_NOT_EMPTY);
-    else if (naxis2 < 0)
-        return(*status = NEG_ROWS);
-    else if (pcount < 0)
-        return(*status = BAD_PCOUNT);
-    else if (tfields < 0 || tfields > 999)
-        return(*status = BAD_TFIELDS);
-
-    extnm[0] = '\0';
-    if (extnmx)
-        strncat(extnm, extnmx, FLEN_VALUE-1);
-
-    ffpkys(fptr, "XTENSION", "BINTABLE", "binary table extension", status);
-    ffpkyj(fptr, "BITPIX", 8, "8-bit bytes", status);
-    ffpkyj(fptr, "NAXIS", 2, "2-dimensional binary table", status);
-
-    naxis1 = 0;
-    for (ii = 0; ii < tfields; ii++)  /* sum the width of each field */
-    {
-        ffbnfm(tform[ii], &datatype, &repeat, &width, status);
-
-        if (datatype == TSTRING)
-            naxis1 += repeat;   /* one byte per char */
-        else if (datatype == TBIT)
-            naxis1 += (repeat + 7) / 8;
-        else if (datatype > 0)
-            naxis1 += repeat * (datatype / 10);
-        else if (tform[ii][0] == 'P' || tform[ii][1] == 'P'||
-                 tform[ii][0] == 'p' || tform[ii][1] == 'p')
-           /* this is a 'P' variable length descriptor (neg. datatype) */
-            naxis1 += 8;
-        else
-           /* this is a 'Q' variable length descriptor (neg. datatype) */
-            naxis1 += 16;
-
-        if (*status > 0)
-            break;       /* abort loop on error */
-    }
-
-    ffpkyj(fptr, "NAXIS1", naxis1, "width of table in bytes", status);
-    ffpkyj(fptr, "NAXIS2", naxis2, "number of rows in table", status);
-
-    /*
-      the initial value of PCOUNT (= size of the variable length array heap)
-      should always be zero.  If any variable length data is written, then
-      the value of PCOUNT will be updated when the HDU is closed
-    */
-    ffpkyj(fptr, "PCOUNT", 0, "size of special data area", status);
-    ffpkyj(fptr, "GCOUNT", 1, "one data group (required keyword)", status);
-    ffpkyj(fptr, "TFIELDS", tfields, "number of fields in each row", status);
-
-    for (ii = 0; ii < tfields; ii++) /* loop over every column */
-    {
-        if ( *(ttype[ii]) )  /* optional TTYPEn keyword */
-        {
-          sprintf(comm, "label for field %3d", ii + 1);
-          ffkeyn("TTYPE", ii + 1, name, status);
-          ffpkys(fptr, name, ttype[ii], comm, status);
-        }
-
-        strcpy(tfmt, tform[ii]);  /* required TFORMn keyword */
-        ffupch(tfmt);
-
-        ffkeyn("TFORM", ii + 1, name, status);
-        strcpy(comm, "data format of field");
-
-        ffbnfm(tfmt, &datatype, &repeat, &width, status);
-
-        if (datatype == TSTRING)
-        {
-            strcat(comm, ": ASCII Character");
-
-            /* Do sanity check to see if an ASCII table format was used,  */
-            /* e.g., 'A8' instead of '8A', or a bad unit width eg '8A9'.  */
-            /* Don't want to return an error status, so write error into  */
-            /* the keyword comment.  */
-
-            cptr = strchr(tfmt,'A');
-            cptr++;
-
-            if (cptr)
-               iread = sscanf(cptr,"%ld", &width);
-
-            if (iread == 1 && (width > repeat)) 
-            {
-              if (repeat == 1)
-                strcpy(comm, "ERROR??  USING ASCII TABLE SYNTAX BY MISTAKE??");
-              else
-                strcpy(comm, "rAw FORMAT ERROR! UNIT WIDTH w > COLUMN WIDTH r");
-            }
-        }
-        else if (datatype == TBIT)
-           strcat(comm, ": BIT");
-        else if (datatype == TBYTE)
-           strcat(comm, ": BYTE");
-        else if (datatype == TLOGICAL)
-           strcat(comm, ": 1-byte LOGICAL");
-        else if (datatype == TSHORT)
-           strcat(comm, ": 2-byte INTEGER");
-        else if (datatype == TUSHORT)
-           strcat(comm, ": 2-byte INTEGER");
-        else if (datatype == TLONG)
-           strcat(comm, ": 4-byte INTEGER");
-        else if (datatype == TLONGLONG)
-           strcat(comm, ": 8-byte INTEGER");
-        else if (datatype == TULONG)
-           strcat(comm, ": 4-byte INTEGER");
-        else if (datatype == TFLOAT)
-           strcat(comm, ": 4-byte REAL");
-        else if (datatype == TDOUBLE)
-           strcat(comm, ": 8-byte DOUBLE");
-        else if (datatype == TCOMPLEX)
-           strcat(comm, ": COMPLEX");
-        else if (datatype == TDBLCOMPLEX)
-           strcat(comm, ": DOUBLE COMPLEX");
-        else if (datatype < 0)
-           strcat(comm, ": variable length array");
-
-        if (abs(datatype) == TSBYTE) /* signed bytes */
-        {
-           /* Replace the 'S' with an 'B' in the TFORMn code */
-           cptr = tfmt;
-           while (*cptr != 'S') 
-              cptr++;
-
-           *cptr = 'B';
-           ffpkys(fptr, name, tfmt, comm, status);
-
-           /* write the TZEROn and TSCALn keywords */
-           ffkeyn("TZERO", ii + 1, name, status);
-           strcpy(comm, "offset for signed bytes");
-
-           ffpkyg(fptr, name, -128., 0, comm, status);
-
-           ffkeyn("TSCAL", ii + 1, name, status);
-           strcpy(comm, "data are not scaled");
-           ffpkyg(fptr, name, 1., 0, comm, status);
-        }
-        else if (abs(datatype) == TUSHORT) 
-        {
-           /* Replace the 'U' with an 'I' in the TFORMn code */
-           cptr = tfmt;
-           while (*cptr != 'U') 
-              cptr++;
-
-           *cptr = 'I';
-           ffpkys(fptr, name, tfmt, comm, status);
-
-           /* write the TZEROn and TSCALn keywords */
-           ffkeyn("TZERO", ii + 1, name, status);
-           strcpy(comm, "offset for unsigned integers");
-
-           ffpkyg(fptr, name, 32768., 0, comm, status);
-
-           ffkeyn("TSCAL", ii + 1, name, status);
-           strcpy(comm, "data are not scaled");
-           ffpkyg(fptr, name, 1., 0, comm, status);
-        }
-        else if (abs(datatype) == TULONG) 
-        {
-           /* Replace the 'V' with an 'J' in the TFORMn code */
-           cptr = tfmt;
-           while (*cptr != 'V') 
-              cptr++;
-
-           *cptr = 'J';
-           ffpkys(fptr, name, tfmt, comm, status);
-
-           /* write the TZEROn and TSCALn keywords */
-           ffkeyn("TZERO", ii + 1, name, status);
-           strcpy(comm, "offset for unsigned integers");
-
-           ffpkyg(fptr, name, 2147483648., 0, comm, status);
-
-           ffkeyn("TSCAL", ii + 1, name, status);
-           strcpy(comm, "data are not scaled");
-           ffpkyg(fptr, name, 1., 0, comm, status);
-        }
-        else
-        {
-           ffpkys(fptr, name, tfmt, comm, status);
-        }
-
-        if (tunit)
-        {
-         if (tunit[ii] && *(tunit[ii]) ) /* optional TUNITn keyword */
-         {
-          ffkeyn("TUNIT", ii + 1, name, status);
-          ffpkys(fptr, name, tunit[ii],
-             "physical unit of field", status);
-         }
-        }
-
-        if (*status > 0)
-            break;       /* abort loop on error */
-    }
-
-    if (extnm[0])       /* optional EXTNAME keyword */
-        ffpkys(fptr, "EXTNAME", extnm,
-               "name of this binary table extension", status);
-
-    if (*status > 0)
-        ffpmsg("Failed to write binary table header keywords (ffphbn)");
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffphext(fitsfile *fptr,  /* I - FITS file pointer                       */
-           const char *xtensionx,   /* I - value for the XTENSION keyword          */
-           int bitpix,       /* I - value for the BIXPIX keyword            */
-           int naxis,        /* I - value for the NAXIS keyword             */
-           long naxes[],     /* I - value for the NAXISn keywords           */
-           LONGLONG pcount,  /* I - value for the PCOUNT keyword            */
-           LONGLONG gcount,  /* I - value for the GCOUNT keyword            */
-           int *status)      /* IO - error status                           */
-/*
-  Put required Header keywords into a conforming extension:
-*/
-{
-    char message[FLEN_ERRMSG],comm[81], name[20], xtension[FLEN_VALUE];
-    int ii;
- 
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    if (*status > 0)
-        return(*status);
-    else if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
-        return(*status = HEADER_NOT_EMPTY);
-
-    if (naxis < 0 || naxis > 999)
-    {
-        sprintf(message,
-        "Illegal value for NAXIS keyword: %d", naxis);
-        ffpmsg(message);
-        return(*status = BAD_NAXIS);
-    }
-
-    xtension[0] = '\0';
-    strncat(xtension, xtensionx, FLEN_VALUE-1);
-
-    ffpkys(fptr, "XTENSION", xtension, "extension type", status);
-    ffpkyj(fptr, "BITPIX",   bitpix,   "number of bits per data pixel", status);
-    ffpkyj(fptr, "NAXIS",    naxis,    "number of data axes", status);
-
-    strcpy(comm, "length of data axis ");
-    for (ii = 0; ii < naxis; ii++)
-    {
-        if (naxes[ii] < 0)
-        {
-            sprintf(message,
-            "Illegal negative value for NAXIS%d keyword: %.0f", ii + 1, (double) (naxes[ii]));
-            ffpmsg(message);
-            return(*status = BAD_NAXES);
-        }
-
-        sprintf(&comm[20], "%d", ii + 1);
-        ffkeyn("NAXIS", ii + 1, name, status);
-        ffpkyj(fptr, name, naxes[ii], comm, status);
-    }
-
-
-    ffpkyj(fptr, "PCOUNT", pcount, " ", status);
-    ffpkyj(fptr, "GCOUNT", gcount, " ", status);
-
-    if (*status > 0)
-        ffpmsg("Failed to write extension header keywords (ffphext)");
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffi2c(LONGLONG ival,  /* I - value to be converted to a string */
-          char *cval,     /* O - character string representation of the value */
-          int *status)    /* IO - error status */
-/*
-  convert  value to a null-terminated formatted string.
-*/
-{
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    cval[0] = '\0';
-
-#if defined(_MSC_VER)
-    /* Microsoft Visual C++ 6.0 uses '%I64d' syntax  for 8-byte integers */
-    if (sprintf(cval, "%I64d", ival) < 0)
-
-#elif (USE_LL_SUFFIX == 1)
-    if (sprintf(cval, "%lld", ival) < 0)
-#else
-    if (sprintf(cval, "%ld", ival) < 0)
-#endif
-    {
-        ffpmsg("Error in ffi2c converting integer to string");
-        *status = BAD_I2C;
-    }
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffl2c(int lval,    /* I - value to be converted to a string */
-          char *cval,  /* O - character string representation of the value */
-          int *status) /* IO - error status ) */
-/*
-  convert logical value to a null-terminated formatted string.  If the
-  input value == 0, then the output character is the letter F, else
-  the output character is the letter T.  The output string is null terminated.
-*/
-{
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (lval)
-        strcpy(cval,"T");
-    else
-        strcpy(cval,"F");
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffs2c(const char *instr, /* I - null terminated input string  */
-          char *outstr,      /* O - null terminated quoted output string */
-          int *status)       /* IO - error status */
-/*
-  convert an input string to a quoted string. Leading spaces 
-  are significant.  FITS string keyword values must be at least 
-  8 chars long so pad out string with spaces if necessary.
-      Example:   km/s ==> 'km/s    '
-  Single quote characters in the input string will be replace by
-  two single quote characters. e.g., o'brian ==> 'o''brian'
-*/
-{
-    size_t len, ii, jj;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    if (!instr)            /* a null input pointer?? */
-    {
-       strcpy(outstr, "''");   /* a null FITS string */
-       return(*status);
-    }
-
-    outstr[0] = '\'';      /* start output string with a quote */
-
-    len = strlen(instr);
-    if (len > 68)
-        len = 68;    /* limit input string to 68 chars */
-
-    for (ii=0, jj=1; ii < len && jj < 69; ii++, jj++)
-    {
-        outstr[jj] = instr[ii];  /* copy each char from input to output */
-        if (instr[ii] == '\'')
-        {
-            jj++;
-            outstr[jj]='\'';   /* duplicate any apostrophies in the input */
-        }
-    }
-
-    for (; jj < 9; jj++)       /* pad string so it is at least 8 chars long */
-        outstr[jj] = ' ';
-
-    if (jj == 70)   /* only occurs if the last char of string was a quote */
-        outstr[69] = '\0';
-    else
-    {
-        outstr[jj] = '\'';         /* append closing quote character */
-        outstr[jj+1] = '\0';          /* terminate the string */
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr2f(float fval,   /* I - value to be converted to a string */
-          int  decim,   /* I - number of decimal places to display */
-          char *cval,   /* O - character string representation of the value */
-          int  *status) /* IO - error status */
-/*
-  convert float value to a null-terminated F format string
-*/
-{
-    char *cptr;
-        
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    cval[0] = '\0';
-
-    if (decim < 0)
-    {
-        ffpmsg("Error in ffr2f:  no. of decimal places < 0");
-        return(*status = BAD_DECIM);
-    }
-
-    if (sprintf(cval, "%.*f", decim, fval) < 0)
-    {
-        ffpmsg("Error in ffr2f converting float to string");
-        *status = BAD_F2C;
-    }
-
-    /* replace comma with a period (e.g. in French locale) */
-    if ( (cptr = strchr(cval, ','))) *cptr = '.';
-
-    /* test if output string is 'NaN', 'INDEF', or 'INF' */
-    if (strchr(cval, 'N'))
-    {
-        ffpmsg("Error in ffr2f: float value is a NaN or INDEF");
-        *status = BAD_F2C;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffr2e(float fval,  /* I - value to be converted to a string */
-         int decim,    /* I - number of decimal places to display */
-         char *cval,   /* O - character string representation of the value */
-         int *status)  /* IO - error status */
-/*
-  convert float value to a null-terminated exponential format string
-*/
-{
-    char *cptr;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    cval[0] = '\0';
-
-    if (decim < 0)
-    {   /* use G format if decim is negative */
-        if ( sprintf(cval, "%.*G", -decim, fval) < 0)
-        {
-            ffpmsg("Error in ffr2e converting float to string");
-            *status = BAD_F2C;
-        }
-        else
-        {
-            /* test if E format was used, and there is no displayed decimal */
-            if ( !strchr(cval, '.') && strchr(cval,'E') )
-            {
-                /* reformat value with a decimal point and single zero */
-                if ( sprintf(cval, "%.1E", fval) < 0)
-                {
-                    ffpmsg("Error in ffr2e converting float to string");
-                    *status = BAD_F2C;
-                }
-
-                return(*status);  
-            }
-        }
-    }
-    else
-    {
-        if ( sprintf(cval, "%.*E", decim, fval) < 0)
-        {
-            ffpmsg("Error in ffr2e converting float to string");
-            *status = BAD_F2C;
-        }
-    }
-
-    if (*status <= 0)
-    {
-        /* replace comma with a period (e.g. in French locale) */
-        if ( (cptr = strchr(cval, ','))) *cptr = '.';
-
-        /* test if output string is 'NaN', 'INDEF', or 'INF' */
-        if (strchr(cval, 'N'))
-        {
-            ffpmsg("Error in ffr2e: float value is a NaN or INDEF");
-            *status = BAD_F2C;
-        }
-        else if ( !strchr(cval, '.') && !strchr(cval,'E') )
-        {
-            /* add decimal point if necessary to distinquish from integer */
-            strcat(cval, ".");
-        }
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffd2f(double dval,  /* I - value to be converted to a string */
-          int decim,    /* I - number of decimal places to display */
-          char *cval,   /* O - character string representation of the value */
-          int *status)  /* IO - error status */
-/*
-  convert double value to a null-terminated F format string
-*/
-{
-    char *cptr;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    cval[0] = '\0';
-
-    if (decim < 0)
-    {
-        ffpmsg("Error in ffd2f:  no. of decimal places < 0");
-        return(*status = BAD_DECIM);
-    }
-
-    if (sprintf(cval, "%.*f", decim, dval) < 0)
-    {
-        ffpmsg("Error in ffd2f converting double to string");
-        *status = BAD_F2C;
-    }
-
-    /* replace comma with a period (e.g. in French locale) */
-    if ( (cptr = strchr(cval, ','))) *cptr = '.';
-
-    /* test if output string is 'NaN', 'INDEF', or 'INF' */
-    if (strchr(cval, 'N'))
-    {
-        ffpmsg("Error in ffd2f: double value is a NaN or INDEF");
-        *status = BAD_F2C;
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffd2e(double dval,  /* I - value to be converted to a string */
-          int decim,    /* I - number of decimal places to display */
-          char *cval,   /* O - character string representation of the value */
-          int *status)  /* IO - error status */
-/*
-  convert double value to a null-terminated exponential format string.
-*/
-{
-    char *cptr;
-
-    if (*status > 0)           /* inherit input status value if > 0 */
-        return(*status);
-
-    cval[0] = '\0';
-
-    if (decim < 0)
-    {   /* use G format if decim is negative */
-        if ( sprintf(cval, "%.*G", -decim, dval) < 0)
-        {
-            ffpmsg("Error in ffd2e converting float to string");
-            *status = BAD_F2C;
-        }
-        else
-        {
-            /* test if E format was used, and there is no displayed decimal */
-            if ( !strchr(cval, '.') && strchr(cval,'E') )
-            {
-                /* reformat value with a decimal point and single zero */
-                if ( sprintf(cval, "%.1E", dval) < 0)
-                {
-                    ffpmsg("Error in ffd2e converting float to string");
-                    *status = BAD_F2C;
-                }
-
-                return(*status);  
-            }
-        }
-    }
-    else
-    {
-        if ( sprintf(cval, "%.*E", decim, dval) < 0)
-        {
-            ffpmsg("Error in ffd2e converting float to string");
-            *status = BAD_F2C;
-        }
-    }
-
-    if (*status <= 0)
-    {
-        /* replace comma with a period (e.g. in French locale) */
-        if ( (cptr = strchr(cval, ','))) *cptr = '.';
-
-        /* test if output string is 'NaN', 'INDEF', or 'INF' */
-        if (strchr(cval, 'N'))
-        {
-            ffpmsg("Error in ffd2e: double value is a NaN or INDEF");
-            *status = BAD_F2C;
-        }
-        else if ( !strchr(cval, '.') && !strchr(cval,'E') )
-        {
-            /* add decimal point if necessary to distinquish from integer */
-            strcat(cval, ".");
-        }
-    }
-
-    return(*status);
-}
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/quantize.c b/src/external/OpenGR/3rdparty/cfitsio/quantize.c
deleted file mode 100644
index 0bf73faa6..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/quantize.c
+++ /dev/null
@@ -1,3955 +0,0 @@
-/*
-  The following code is based on algorithms written by Richard White at STScI and made
-  available for use in CFITSIO in July 1999 and updated in January 2008. 
-*/
-
-# include 
-# include 
-# include 
-# include 
-# include 
-
-#include "fitsio2.h"
-
-/* nearest integer function */
-# define NINT(x)  ((x >= 0.) ? (int) (x + 0.5) : (int) (x - 0.5))
-
-#define NULL_VALUE -2147483647 /* value used to represent undefined pixels */
-#define ZERO_VALUE -2147483646 /* value used to represent zero-valued pixels */
-#define N_RESERVED_VALUES 10   /* number of reserved values, starting with */
-                               /* and including NULL_VALUE.  These values */
-                               /* may not be used to represent the quantized */
-                               /* and scaled floating point pixel values */
-			       /* If lossy Hcompression is used, and the */
-			       /* array contains null values, then it is also */
-			       /* possible for the compressed values to slightly */
-			       /* exceed the range of the actual (lossless) values */
-			       /* so we must reserve a little more space */
-			       
-/* more than this many standard deviations from the mean is an outlier */
-# define SIGMA_CLIP     5.
-# define NITER          3	/* number of sigma-clipping iterations */
-
-static int FnMeanSigma_short(short *array, long npix, int nullcheck, 
-  short nullvalue, long *ngoodpix, double *mean, double *sigma, int *status);       
-static int FnMeanSigma_int(int *array, long npix, int nullcheck,
-  int nullvalue, long *ngoodpix, double *mean, double *sigma, int *status);       
-static int FnMeanSigma_float(float *array, long npix, int nullcheck,
-  float nullvalue, long *ngoodpix, double *mean, double *sigma, int *status);       
-static int FnMeanSigma_double(double *array, long npix, int nullcheck,
-  double nullvalue, long *ngoodpix, double *mean, double *sigma, int *status);       
-
-static int FnNoise5_short(short *array, long nx, long ny, int nullcheck, 
-   short nullvalue, long *ngood, short *minval, short *maxval, 
-   double *n2, double *n3, double *n5, int *status);   
-static int FnNoise5_int(int *array, long nx, long ny, int nullcheck, 
-   int nullvalue, long *ngood, int *minval, int *maxval, 
-   double *n2, double *n3, double *n5, int *status);   
-static int FnNoise5_float(float *array, long nx, long ny, int nullcheck, 
-   float nullvalue, long *ngood, float *minval, float *maxval, 
-   double *n2, double *n3, double *n5, int *status);   
-static int FnNoise5_double(double *array, long nx, long ny, int nullcheck, 
-   double nullvalue, long *ngood, double *minval, double *maxval, 
-   double *n2, double *n3, double *n5, int *status);   
-
-static int FnNoise3_short(short *array, long nx, long ny, int nullcheck, 
-   short nullvalue, long *ngood, short *minval, short *maxval, double *noise, int *status);       
-static int FnNoise3_int(int *array, long nx, long ny, int nullcheck, 
-   int nullvalue, long *ngood, int *minval, int *maxval, double *noise, int *status);          
-static int FnNoise3_float(float *array, long nx, long ny, int nullcheck, 
-   float nullvalue, long *ngood, float *minval, float *maxval, double *noise, int *status);        
-static int FnNoise3_double(double *array, long nx, long ny, int nullcheck, 
-   double nullvalue, long *ngood, double *minval, double *maxval, double *noise, int *status);        
-
-static int FnNoise1_short(short *array, long nx, long ny, 
-   int nullcheck, short nullvalue, double *noise, int *status);       
-static int FnNoise1_int(int *array, long nx, long ny, 
-   int nullcheck, int nullvalue, double *noise, int *status);       
-static int FnNoise1_float(float *array, long nx, long ny, 
-   int nullcheck, float nullvalue, double *noise, int *status);       
-static int FnNoise1_double(double *array, long nx, long ny, 
-   int nullcheck, double nullvalue, double *noise, int *status);       
-
-static int FnCompare_short (const void *, const void *);
-static int FnCompare_int (const void *, const void *);
-static int FnCompare_float (const void *, const void *);
-static int FnCompare_double (const void *, const void *);
-static float quick_select_float(float arr[], int n);
-static short quick_select_short(short arr[], int n);
-static int quick_select_int(int arr[], int n);
-static LONGLONG quick_select_longlong(LONGLONG arr[], int n);
-static double quick_select_double(double arr[], int n);
-
-/*---------------------------------------------------------------------------*/
-int fits_quantize_float (long row, float fdata[], long nxpix, long nypix, int nullcheck, 
-	float in_null_value, float qlevel, int dither_method, int idata[], double *bscale,
-	double *bzero, int *iminval, int *imaxval) {
-
-/* arguments:
-long row            i: if positive, used to calculate random dithering seed value
-                       (this is only used when dithering the quantized values)
-float fdata[]       i: array of image pixels to be compressed
-long nxpix          i: number of pixels in each row of fdata
-long nypix          i: number of rows in fdata
-nullcheck           i: check for nullvalues in fdata?
-float in_null_value i: value used to represent undefined pixels in fdata
-float qlevel        i: quantization level
-int dither_method   i; which dithering method to use
-int idata[]         o: values of fdata after applying bzero and bscale
-double bscale       o: scale factor
-double bzero        o: zero offset
-int iminval         o: minimum quantized value that is returned
-int imaxval         o: maximum quantized value that is returned
-
-The function value will be one if the input fdata were copied to idata;
-in this case the parameters bscale and bzero can be used to convert back to
-nearly the original floating point values:  fdata ~= idata * bscale + bzero.
-If the function value is zero, the data were not copied to idata.
-*/
-
-	int status, iseed = 0;
-	long i, nx, ngood = 0;
-	double stdev, noise2, noise3, noise5;	/* MAD 2nd, 3rd, and 5th order noise values */
-	float minval = 0., maxval = 0.;  /* min & max of fdata */
-	double delta;		/* bscale, 1 in idata = delta in fdata */
-	double zeropt;	        /* bzero */
-	double temp;
-        int nextrand = 0;
-	extern float *fits_rand_value; /* this is defined in imcompress.c */
-	LONGLONG iqfactor;
-
-	nx = nxpix * nypix;
-	if (nx <= 1) {
-	    *bscale = 1.;
-	    *bzero  = 0.;
-	    return (0);
-	}
-
-        if (qlevel >= 0.) {
-
-	    /* estimate background noise using MAD pixel differences */
-	    FnNoise5_float(fdata, nxpix, nypix, nullcheck, in_null_value, &ngood,
-	        &minval, &maxval, &noise2, &noise3, &noise5, &status);      
-
-	    if (nullcheck && ngood == 0) {   /* special case of an image filled with Nulls */
-	        /* set parameters to dummy values, which are not used */
-		minval = 0.;
-		maxval = 1.;
-		stdev = 1;
-	    } else {
-
-	        /* use the minimum of noise2, noise3, and noise5 as the best noise value */
-	        stdev = noise3;
-	        if (noise2 != 0. && noise2 < stdev) stdev = noise2;
-	        if (noise5 != 0. && noise5 < stdev) stdev = noise5;
-            }
-
-	    if (qlevel == 0.)
-	        delta = stdev / 4.;  /* default quantization */
-	    else
-	        delta = stdev / qlevel;
-
-	    if (delta == 0.) 
-	        return (0);			/* don't quantize */
-
-	} else {
-	    /* negative value represents the absolute quantization level */
-	    delta = -qlevel;
-
-	    /* only nned to calculate the min and max values */
-	    FnNoise3_float(fdata, nxpix, nypix, nullcheck, in_null_value, &ngood,
-	        &minval, &maxval, 0, &status);      
- 	}
-
-        /* check that the range of quantized levels is not > range of int */
-	if ((maxval - minval) / delta > 2. * 2147483647. - N_RESERVED_VALUES )
-	    return (0);			/* don't quantize */
-
-        if (row > 0) { /* we need to dither the quantized values */
-            if (!fits_rand_value) 
-	        if (fits_init_randoms()) return(MEMORY_ALLOCATION);
-
-	    /* initialize the index to the next random number in the list */
-            iseed = (int) ((row - 1) % N_RANDOM);
-	    nextrand = (int) (fits_rand_value[iseed] * 500.);
-	}
-
-        if (ngood == nx) {   /* don't have to check for nulls */
-            /* return all positive values, if possible since some */
-            /* compression algorithms either only work for positive integers, */
-            /* or are more efficient.  */
-
-            if (dither_method == SUBTRACTIVE_DITHER_2)
-	    {
-                /* shift the range to be close to the value used to represent zeros */
-                zeropt = minval - delta * (NULL_VALUE + N_RESERVED_VALUES);
-            }
-	    else if ((maxval - minval) / delta < 2147483647. - N_RESERVED_VALUES )
-            {
-                zeropt = minval;
-		/* fudge the zero point so it is an integer multiple of delta */
-		/* This helps to ensure the same scaling will be performed if the */
-		/* file undergoes multiple fpack/funpack cycles */
-		iqfactor = (LONGLONG) (zeropt/delta  + 0.5);
-		zeropt = iqfactor * delta;               
-            }
-            else
-            {
-                /* center the quantized levels around zero */
-                zeropt = (minval + maxval) / 2.;
-            }
-
-            if (row > 0) {  /* dither the values when quantizing */
-              for (i = 0;  i < nx;  i++) {
-	    
-		if (dither_method == SUBTRACTIVE_DITHER_2 && fdata[i] == 0.0) {
-		   idata[i] = ZERO_VALUE;
-		} else {
-		   idata[i] =  NINT((((double) fdata[i] - zeropt) / delta) + fits_rand_value[nextrand] - 0.5);
-		}
-
-                nextrand++;
-		if (nextrand == N_RANDOM) {
-		    iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-	            nextrand = (int) (fits_rand_value[iseed] * 500);
-                }
-              }
-            } else {  /* do not dither the values */
-
-       	        for (i = 0;  i < nx;  i++) {
-	            idata[i] = NINT ((fdata[i] - zeropt) / delta);
-                }
-            } 
-        }
-        else {
-            /* data contains null values; shift the range to be */
-            /* close to the value used to represent null values */
-            zeropt = minval - delta * (NULL_VALUE + N_RESERVED_VALUES);
-
-            if (row > 0) {  /* dither the values */
-	      for (i = 0;  i < nx;  i++) {
-                if (fdata[i] != in_null_value) {
-		    if (dither_method == SUBTRACTIVE_DITHER_2 && fdata[i] == 0.0) {
-		       idata[i] = ZERO_VALUE;
-		    } else {
-		       idata[i] =  NINT((((double) fdata[i] - zeropt) / delta) + fits_rand_value[nextrand] - 0.5);
-		    }
-                } else {
-                    idata[i] = NULL_VALUE;
-                }
-
-                /* increment the random number index, regardless */
-                nextrand++;
-		if (nextrand == N_RANDOM) {
-		    iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-	            nextrand = (int) (fits_rand_value[iseed] * 500);
-                }
-              }
-            } else {  /* do not dither the values */
-	       for (i = 0;  i < nx;  i++) {
- 
-                 if (fdata[i] != in_null_value) {
-		    idata[i] =  NINT((fdata[i] - zeropt) / delta);
-                 } else { 
-                    idata[i] = NULL_VALUE;
-                 }
-               }
-            }
-	}
-
-        /* calc min and max values */
-        temp = (minval - zeropt) / delta;
-        *iminval =  NINT (temp);
-        temp = (maxval - zeropt) / delta;
-        *imaxval =  NINT (temp);
-
-	*bscale = delta;
-	*bzero = zeropt;
-	return (1);			/* yes, data have been quantized */
-}
-/*---------------------------------------------------------------------------*/
-int fits_quantize_double (long row, double fdata[], long nxpix, long nypix, int nullcheck, 
-	double in_null_value, float qlevel, int dither_method, int idata[], double *bscale,
-	double *bzero, int *iminval, int *imaxval) {
-
-/* arguments:
-long row            i: tile number = row number in the binary table
-                       (this is only used when dithering the quantized values)
-double fdata[]      i: array of image pixels to be compressed
-long nxpix          i: number of pixels in each row of fdata
-long nypix          i: number of rows in fdata
-nullcheck           i: check for nullvalues in fdata?
-double in_null_value i: value used to represent undefined pixels in fdata
-float qlevel        i: quantization level
-int dither_method   i; which dithering method to use
-int idata[]         o: values of fdata after applying bzero and bscale
-double bscale       o: scale factor
-double bzero        o: zero offset
-int iminval         o: minimum quantized value that is returned
-int imaxval         o: maximum quantized value that is returned
-
-The function value will be one if the input fdata were copied to idata;
-in this case the parameters bscale and bzero can be used to convert back to
-nearly the original floating point values:  fdata ~= idata * bscale + bzero.
-If the function value is zero, the data were not copied to idata.
-*/
-
-	int status, iseed = 0;
-	long i, nx, ngood = 0;
-	double stdev, noise2 = 0., noise3 = 0., noise5 = 0.;	/* MAD 2nd, 3rd, and 5th order noise values */
-	double minval = 0., maxval = 0.;  /* min & max of fdata */
-	double delta;		/* bscale, 1 in idata = delta in fdata */
-	double zeropt;	        /* bzero */
-	double temp;
-        int nextrand = 0;
-	extern float *fits_rand_value;
-	LONGLONG iqfactor;
-
-	nx = nxpix * nypix;
-	if (nx <= 1) {
-	    *bscale = 1.;
-	    *bzero  = 0.;
-	    return (0);
-	}
-
-        if (qlevel >= 0.) {
-
-	    /* estimate background noise using MAD pixel differences */
-	    FnNoise5_double(fdata, nxpix, nypix, nullcheck, in_null_value, &ngood,
-	        &minval, &maxval, &noise2, &noise3, &noise5, &status);      
-
-	    if (nullcheck && ngood == 0) {   /* special case of an image filled with Nulls */
-	        /* set parameters to dummy values, which are not used */
-		minval = 0.;
-		maxval = 1.;
-		stdev = 1;
-	    } else {
-
-	        /* use the minimum of noise2, noise3, and noise5 as the best noise value */
-	        stdev = noise3;
-	        if (noise2 != 0. && noise2 < stdev) stdev = noise2;
-	        if (noise5 != 0. && noise5 < stdev) stdev = noise5;
-            }
-
-	    if (qlevel == 0.)
-	        delta = stdev / 4.;  /* default quantization */
-	    else
-	        delta = stdev / qlevel;
-
-	    if (delta == 0.) 
-	        return (0);			/* don't quantize */
-
-	} else {
-	    /* negative value represents the absolute quantization level */
-	    delta = -qlevel;
-
-	    /* only nned to calculate the min and max values */
-	    FnNoise3_double(fdata, nxpix, nypix, nullcheck, in_null_value, &ngood,
-	        &minval, &maxval, 0, &status);      
- 	}
-
-        /* check that the range of quantized levels is not > range of int */
-	if ((maxval - minval) / delta > 2. * 2147483647. - N_RESERVED_VALUES )
-	    return (0);			/* don't quantize */
-
-        if (row > 0) { /* we need to dither the quantized values */
-            if (!fits_rand_value) 
-	       if (fits_init_randoms()) return(MEMORY_ALLOCATION);
-
-	    /* initialize the index to the next random number in the list */
-            iseed = (int) ((row - 1) % N_RANDOM);
-	    nextrand = (int) (fits_rand_value[iseed] * 500);
-	}
-
-        if (ngood == nx) {   /* don't have to check for nulls */
-            /* return all positive values, if possible since some */
-            /* compression algorithms either only work for positive integers, */
-            /* or are more efficient.  */
-
-            if (dither_method == SUBTRACTIVE_DITHER_2)
-	    {
-                /* shift the range to be close to the value used to represent zeros */
-                zeropt = minval - delta * (NULL_VALUE + N_RESERVED_VALUES);
-            }
-	    else if ((maxval - minval) / delta < 2147483647. - N_RESERVED_VALUES )
-            {
-                zeropt = minval;
-		/* fudge the zero point so it is an integer multiple of delta */
-		/* This helps to ensure the same scaling will be performed if the */
-		/* file undergoes multiple fpack/funpack cycles */
-		iqfactor = (LONGLONG) (zeropt/delta  + 0.5);
-		zeropt = iqfactor * delta;               
-            }
-            else
-            {
-                /* center the quantized levels around zero */
-                zeropt = (minval + maxval) / 2.;
-            }
-
-            if (row > 0) {  /* dither the values when quantizing */
-       	      for (i = 0;  i < nx;  i++) {
-
-		if (dither_method == SUBTRACTIVE_DITHER_2 && fdata[i] == 0.0) {
-		   idata[i] = ZERO_VALUE;
-		} else {
-		   idata[i] =  NINT((((double) fdata[i] - zeropt) / delta) + fits_rand_value[nextrand] - 0.5);
-		}
-
-                nextrand++;
-		if (nextrand == N_RANDOM) {
-                    iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-	            nextrand = (int) (fits_rand_value[iseed] * 500);
-                }
-              }
-            } else {  /* do not dither the values */
-
-       	        for (i = 0;  i < nx;  i++) {
-	            idata[i] = NINT ((fdata[i] - zeropt) / delta);
-                }
-            } 
-        }
-        else {
-            /* data contains null values; shift the range to be */
-            /* close to the value used to represent null values */
-            zeropt = minval - delta * (NULL_VALUE + N_RESERVED_VALUES);
-
-            if (row > 0) {  /* dither the values */
-	      for (i = 0;  i < nx;  i++) {
-                if (fdata[i] != in_null_value) {
-		    if (dither_method == SUBTRACTIVE_DITHER_2 && fdata[i] == 0.0) {
-		       idata[i] = ZERO_VALUE;
-		    } else {
-		       idata[i] =  NINT((((double) fdata[i] - zeropt) / delta) + fits_rand_value[nextrand] - 0.5);
-		    }
-                } else {
-                    idata[i] = NULL_VALUE;
-                }
-
-                /* increment the random number index, regardless */
-                nextrand++;
-		if (nextrand == N_RANDOM) {
-		    iseed++;
-		    if (iseed == N_RANDOM) iseed = 0;
-	            nextrand = (int) (fits_rand_value[iseed] * 500);
-                }
-              }
-            } else {  /* do not dither the values */
-	       for (i = 0;  i < nx;  i++) {
-                 if (fdata[i] != in_null_value)
-		    idata[i] =  NINT((fdata[i] - zeropt) / delta);
-                 else 
-                    idata[i] = NULL_VALUE;
-               }
-            }
-	}
-
-        /* calc min and max values */
-        temp = (minval - zeropt) / delta;
-        *iminval =  NINT (temp);
-        temp = (maxval - zeropt) / delta;
-        *imaxval =  NINT (temp);
-
-	*bscale = delta;
-	*bzero = zeropt;
-
-	return (1);			/* yes, data have been quantized */
-}
-/*--------------------------------------------------------------------------*/
-int fits_img_stats_short(short *array, /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-	long ny,            /* number of rows in the image */
-	                    /* (if this is a 3D image, then ny should be the */
-			    /* product of the no. of rows times the no. of planes) */
-	int nullcheck,      /* check for null values, if true */
-	short nullvalue,    /* value of null pixels, if nullcheck is true */
-
-   /* returned parameters (if the pointer is not null)  */
-	long *ngoodpix,     /* number of non-null pixels in the image */
-	short *minvalue,    /* returned minimum non-null value in the array */
-	short *maxvalue,    /* returned maximum non-null value in the array */
-	double *mean,       /* returned mean value of all non-null pixels */
-	double *sigma,      /* returned R.M.S. value of all non-null pixels */
-	double *noise1,     /* 1st order estimate of noise in image background level */
-	double *noise2,     /* 2nd order estimate of noise in image background level */
-	double *noise3,     /* 3rd order estimate of noise in image background level */
-	double *noise5,     /* 5th order estimate of noise in image background level */
-	int *status)        /* error status */
-
-/*
-    Compute statistics of the input short integer image.
-*/
-{
-	long ngood;
-	short minval = 0, maxval = 0;
-	double xmean = 0., xsigma = 0., xnoise = 0., xnoise2 = 0., xnoise3 = 0., xnoise5 = 0.;
-
-	/* need to calculate mean and/or sigma and/or limits? */
-	if (mean || sigma ) {
-		FnMeanSigma_short(array, nx * ny, nullcheck, nullvalue, 
-			&ngood, &xmean, &xsigma, status);
-
-	    if (ngoodpix) *ngoodpix = ngood;
-	    if (mean)     *mean = xmean;
-	    if (sigma)    *sigma = xsigma;
-	}
-
-	if (noise1) {
-		FnNoise1_short(array, nx, ny, nullcheck, nullvalue, 
-		  &xnoise, status);
-
-		*noise1  = xnoise;
-	}
-
-	if (minvalue || maxvalue || noise3) {
-		FnNoise5_short(array, nx, ny, nullcheck, nullvalue, 
-			&ngood, &minval, &maxval, &xnoise2, &xnoise3, &xnoise5, status);
-
-		if (ngoodpix) *ngoodpix = ngood;
-		if (minvalue) *minvalue= minval;
-		if (maxvalue) *maxvalue = maxval;
-		if (noise2) *noise2  = xnoise2;
-		if (noise3) *noise3  = xnoise3;
-		if (noise5) *noise5  = xnoise5;
-	}
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_img_stats_int(int *array, /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-	long ny,            /* number of rows in the image */
-	                    /* (if this is a 3D image, then ny should be the */
-			    /* product of the no. of rows times the no. of planes) */
-	int nullcheck,      /* check for null values, if true */
-	int nullvalue,    /* value of null pixels, if nullcheck is true */
-
-   /* returned parameters (if the pointer is not null)  */
-	long *ngoodpix,     /* number of non-null pixels in the image */
-	int *minvalue,    /* returned minimum non-null value in the array */
-	int *maxvalue,    /* returned maximum non-null value in the array */
-	double *mean,       /* returned mean value of all non-null pixels */
-	double *sigma,      /* returned R.M.S. value of all non-null pixels */
-	double *noise1,     /* 1st order estimate of noise in image background level */
-	double *noise2,     /* 2nd order estimate of noise in image background level */
-	double *noise3,     /* 3rd order estimate of noise in image background level */
-	double *noise5,     /* 5th order estimate of noise in image background level */
-	int *status)        /* error status */
-
-/*
-    Compute statistics of the input integer image.
-*/
-{
-	long ngood;
-	int minval = 0, maxval = 0;
-	double xmean = 0., xsigma = 0., xnoise = 0., xnoise2 = 0., xnoise3 = 0., xnoise5 = 0.;
-
-	/* need to calculate mean and/or sigma and/or limits? */
-	if (mean || sigma ) {
-		FnMeanSigma_int(array, nx * ny, nullcheck, nullvalue, 
-			&ngood, &xmean, &xsigma, status);
-
-	    if (ngoodpix) *ngoodpix = ngood;
-	    if (mean)     *mean = xmean;
-	    if (sigma)    *sigma = xsigma;
-	}
-
-	if (noise1) {
-		FnNoise1_int(array, nx, ny, nullcheck, nullvalue, 
-		  &xnoise, status);
-
-		*noise1  = xnoise;
-	}
-
-	if (minvalue || maxvalue || noise3) {
-		FnNoise5_int(array, nx, ny, nullcheck, nullvalue, 
-			&ngood, &minval, &maxval, &xnoise2, &xnoise3, &xnoise5, status);
-
-		if (ngoodpix) *ngoodpix = ngood;
-		if (minvalue) *minvalue= minval;
-		if (maxvalue) *maxvalue = maxval;
-		if (noise2) *noise2  = xnoise2;
-		if (noise3) *noise3  = xnoise3;
-		if (noise5) *noise5  = xnoise5;
-	}
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fits_img_stats_float(float *array, /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-	long ny,            /* number of rows in the image */
-	                    /* (if this is a 3D image, then ny should be the */
-			    /* product of the no. of rows times the no. of planes) */
-	int nullcheck,      /* check for null values, if true */
-	float nullvalue,    /* value of null pixels, if nullcheck is true */
-
-   /* returned parameters (if the pointer is not null)  */
-	long *ngoodpix,     /* number of non-null pixels in the image */
-	float *minvalue,    /* returned minimum non-null value in the array */
-	float *maxvalue,    /* returned maximum non-null value in the array */
-	double *mean,       /* returned mean value of all non-null pixels */
-	double *sigma,      /* returned R.M.S. value of all non-null pixels */
-	double *noise1,     /* 1st order estimate of noise in image background level */
-	double *noise2,     /* 2nd order estimate of noise in image background level */
-	double *noise3,     /* 3rd order estimate of noise in image background level */
-	double *noise5,     /* 5th order estimate of noise in image background level */
-	int *status)        /* error status */
-
-/*
-    Compute statistics of the input float image.
-*/
-{
-	long ngood;
-	float minval, maxval;
-	double xmean = 0., xsigma = 0., xnoise = 0., xnoise2 = 0., xnoise3 = 0., xnoise5 = 0.;
-
-	/* need to calculate mean and/or sigma and/or limits? */
-	if (mean || sigma ) {
-		FnMeanSigma_float(array, nx * ny, nullcheck, nullvalue, 
-			&ngood, &xmean, &xsigma, status);
-
-	    if (ngoodpix) *ngoodpix = ngood;
-	    if (mean)     *mean = xmean;
-	    if (sigma)    *sigma = xsigma;
-	}
-
-	if (noise1) {
-		FnNoise1_float(array, nx, ny, nullcheck, nullvalue, 
-		  &xnoise, status);
-
-		*noise1  = xnoise;
-	}
-
-	if (minvalue || maxvalue || noise3) {
-		FnNoise5_float(array, nx, ny, nullcheck, nullvalue, 
-			&ngood, &minval, &maxval, &xnoise2, &xnoise3, &xnoise5, status);
-
-		if (ngoodpix) *ngoodpix = ngood;
-		if (minvalue) *minvalue= minval;
-		if (maxvalue) *maxvalue = maxval;
-		if (noise2) *noise2  = xnoise2;
-		if (noise3) *noise3  = xnoise3;
-		if (noise5) *noise5  = xnoise5;
-	}
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnMeanSigma_short
-       (short *array,       /*  2 dimensional array of image pixels */
-        long npix,          /* number of pixels in the image */
-	int nullcheck,      /* check for null values, if true */
-	short nullvalue,    /* value of null pixels, if nullcheck is true */
-
-   /* returned parameters */
-   
-	long *ngoodpix,     /* number of non-null pixels in the image */
-	double *mean,       /* returned mean value of all non-null pixels */
-	double *sigma,      /* returned R.M.S. value of all non-null pixels */
-	int *status)        /* error status */
-
-/*
-Compute mean and RMS sigma of the non-null pixels in the input array.
-*/
-{
-	long ii, ngood = 0;
-	short *value;
-	double sum = 0., sum2 = 0., xtemp;
-
-	value = array;
-	    
-	if (nullcheck) {
-	        for (ii = 0; ii < npix; ii++, value++) {
-		    if (*value != nullvalue) {
-		        ngood++;
-		        xtemp = (double) *value;
-		        sum += xtemp;
-		        sum2 += (xtemp * xtemp);
-		    }
-		}
-	} else {
-	        ngood = npix;
-	        for (ii = 0; ii < npix; ii++, value++) {
-		        xtemp = (double) *value;
-		        sum += xtemp;
-		        sum2 += (xtemp * xtemp);
-		}
-	}
-
-	if (ngood > 1) {
-		if (ngoodpix) *ngoodpix = ngood;
-		xtemp = sum / ngood;
-		if (mean)     *mean = xtemp;
-		if (sigma)    *sigma = sqrt((sum2 / ngood) - (xtemp * xtemp));
-	} else if (ngood == 1){
-		if (ngoodpix) *ngoodpix = 1;
-		if (mean)     *mean = sum;
-		if (sigma)    *sigma = 0.0;
-	} else {
-		if (ngoodpix) *ngoodpix = 0;
-	        if (mean)     *mean = 0.;
-		if (sigma)    *sigma = 0.;
-	}	    
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnMeanSigma_int
-       (int *array,       /*  2 dimensional array of image pixels */
-        long npix,          /* number of pixels in the image */
-	int nullcheck,      /* check for null values, if true */
-	int nullvalue,    /* value of null pixels, if nullcheck is true */
-
-   /* returned parameters */
-   
-	long *ngoodpix,     /* number of non-null pixels in the image */
-	double *mean,       /* returned mean value of all non-null pixels */
-	double *sigma,      /* returned R.M.S. value of all non-null pixels */
-	int *status)        /* error status */
-
-/*
-Compute mean and RMS sigma of the non-null pixels in the input array.
-*/
-{
-	long ii, ngood = 0;
-	int *value;
-	double sum = 0., sum2 = 0., xtemp;
-
-	value = array;
-	    
-	if (nullcheck) {
-	        for (ii = 0; ii < npix; ii++, value++) {
-		    if (*value != nullvalue) {
-		        ngood++;
-		        xtemp = (double) *value;
-		        sum += xtemp;
-		        sum2 += (xtemp * xtemp);
-		    }
-		}
-	} else {
-	        ngood = npix;
-	        for (ii = 0; ii < npix; ii++, value++) {
-		        xtemp = (double) *value;
-		        sum += xtemp;
-		        sum2 += (xtemp * xtemp);
-		}
-	}
-
-	if (ngood > 1) {
-		if (ngoodpix) *ngoodpix = ngood;
-		xtemp = sum / ngood;
-		if (mean)     *mean = xtemp;
-		if (sigma)    *sigma = sqrt((sum2 / ngood) - (xtemp * xtemp));
-	} else if (ngood == 1){
-		if (ngoodpix) *ngoodpix = 1;
-		if (mean)     *mean = sum;
-		if (sigma)    *sigma = 0.0;
-	} else {
-		if (ngoodpix) *ngoodpix = 0;
-	        if (mean)     *mean = 0.;
-		if (sigma)    *sigma = 0.;
-	}	    
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnMeanSigma_float
-       (float *array,       /*  2 dimensional array of image pixels */
-        long npix,          /* number of pixels in the image */
-	int nullcheck,      /* check for null values, if true */
-	float nullvalue,    /* value of null pixels, if nullcheck is true */
-
-   /* returned parameters */
-   
-	long *ngoodpix,     /* number of non-null pixels in the image */
-	double *mean,       /* returned mean value of all non-null pixels */
-	double *sigma,      /* returned R.M.S. value of all non-null pixels */
-	int *status)        /* error status */
-
-/*
-Compute mean and RMS sigma of the non-null pixels in the input array.
-*/
-{
-	long ii, ngood = 0;
-	float *value;
-	double sum = 0., sum2 = 0., xtemp;
-
-	value = array;
-	    
-	if (nullcheck) {
-	        for (ii = 0; ii < npix; ii++, value++) {
-		    if (*value != nullvalue) {
-		        ngood++;
-		        xtemp = (double) *value;
-		        sum += xtemp;
-		        sum2 += (xtemp * xtemp);
-		    }
-		}
-	} else {
-	        ngood = npix;
-	        for (ii = 0; ii < npix; ii++, value++) {
-		        xtemp = (double) *value;
-		        sum += xtemp;
-		        sum2 += (xtemp * xtemp);
-		}
-	}
-
-	if (ngood > 1) {
-		if (ngoodpix) *ngoodpix = ngood;
-		xtemp = sum / ngood;
-		if (mean)     *mean = xtemp;
-		if (sigma)    *sigma = sqrt((sum2 / ngood) - (xtemp * xtemp));
-	} else if (ngood == 1){
-		if (ngoodpix) *ngoodpix = 1;
-		if (mean)     *mean = sum;
-		if (sigma)    *sigma = 0.0;
-	} else {
-		if (ngoodpix) *ngoodpix = 0;
-	        if (mean)     *mean = 0.;
-		if (sigma)    *sigma = 0.;
-	}	    
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnMeanSigma_double
-       (double *array,       /*  2 dimensional array of image pixels */
-        long npix,          /* number of pixels in the image */
-	int nullcheck,      /* check for null values, if true */
-	double nullvalue,    /* value of null pixels, if nullcheck is true */
-
-   /* returned parameters */
-   
-	long *ngoodpix,     /* number of non-null pixels in the image */
-	double *mean,       /* returned mean value of all non-null pixels */
-	double *sigma,      /* returned R.M.S. value of all non-null pixels */
-	int *status)        /* error status */
-
-/*
-Compute mean and RMS sigma of the non-null pixels in the input array.
-*/
-{
-	long ii, ngood = 0;
-	double *value;
-	double sum = 0., sum2 = 0., xtemp;
-
-	value = array;
-	    
-	if (nullcheck) {
-	        for (ii = 0; ii < npix; ii++, value++) {
-		    if (*value != nullvalue) {
-		        ngood++;
-		        xtemp = *value;
-		        sum += xtemp;
-		        sum2 += (xtemp * xtemp);
-		    }
-		}
-	} else {
-	        ngood = npix;
-	        for (ii = 0; ii < npix; ii++, value++) {
-		        xtemp = *value;
-		        sum += xtemp;
-		        sum2 += (xtemp * xtemp);
-		}
-	}
-
-	if (ngood > 1) {
-		if (ngoodpix) *ngoodpix = ngood;
-		xtemp = sum / ngood;
-		if (mean)     *mean = xtemp;
-		if (sigma)    *sigma = sqrt((sum2 / ngood) - (xtemp * xtemp));
-	} else if (ngood == 1){
-		if (ngoodpix) *ngoodpix = 1;
-		if (mean)     *mean = sum;
-		if (sigma)    *sigma = 0.0;
-	} else {
-		if (ngoodpix) *ngoodpix = 0;
-	        if (mean)     *mean = 0.;
-		if (sigma)    *sigma = 0.;
-	}	    
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnNoise5_short
-       (short *array,       /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-        long ny,            /* number of rows in the image */
-	int nullcheck,      /* check for null values, if true */
-	short nullvalue,    /* value of null pixels, if nullcheck is true */
-   /* returned parameters */   
-	long *ngood,        /* number of good, non-null pixels? */
-	short *minval,    /* minimum non-null value */
-	short *maxval,    /* maximum non-null value */
-	double *noise2,      /* returned 2nd order MAD of all non-null pixels */
-	double *noise3,      /* returned 3rd order MAD of all non-null pixels */
-	double *noise5,      /* returned 5th order MAD of all non-null pixels */
-	int *status)        /* error status */
-
-/*
-Estimate the median and background noise in the input image using 2nd, 3rd and 5th
-order Median Absolute Differences.
-
-The noise in the background of the image is calculated using the MAD algorithms 
-developed for deriving the signal to noise ratio in spectra
-(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)
-
-3rd order:  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))
-
-The returned estimates are the median of the values that are computed for each 
-row of the image.
-*/
-{
-	long ii, jj, nrows = 0, nrows2 = 0, nvals, nvals2, ngoodpix = 0;
-	int *differences2, *differences3, *differences5;
-	short *rowpix, v1, v2, v3, v4, v5, v6, v7, v8, v9;
-	short xminval = SHRT_MAX, xmaxval = SHRT_MIN;
-	int do_range = 0;
-	double *diffs2, *diffs3, *diffs5; 
-	double xnoise2 = 0, xnoise3 = 0, xnoise5 = 0;
-	
-	if (nx < 9) {
-		/* treat entire array as an image with a single row */
-		nx = nx * ny;
-		ny = 1;
-	}
-
-	/* rows must have at least 9 pixels */
-	if (nx < 9) {
-
-		for (ii = 0; ii < nx; ii++) {
-		    if (nullcheck && array[ii] == nullvalue)
-		        continue;
-		    else {
-			if (array[ii] < xminval) xminval = array[ii];
-			if (array[ii] > xmaxval) xmaxval = array[ii];
-			ngoodpix++;
-		    }
-		}
-		if (minval) *minval = xminval;
-		if (maxval) *maxval = xmaxval;
-		if (ngood) *ngood = ngoodpix;
-		if (noise2) *noise2 = 0.;
-		if (noise3) *noise3 = 0.;
-		if (noise5) *noise5 = 0.;
-		return(*status);
-	}
-
-	/* do we need to compute the min and max value? */
-	if (minval || maxval) do_range = 1;
-	
-        /* allocate arrays used to compute the median and noise estimates */
-	differences2 = calloc(nx, sizeof(int));
-	if (!differences2) {
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-	differences3 = calloc(nx, sizeof(int));
-	if (!differences3) {
-		free(differences2);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-	differences5 = calloc(nx, sizeof(int));
-	if (!differences5) {
-		free(differences2);
-		free(differences3);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs2 = calloc(ny, sizeof(double));
-	if (!diffs2) {
-		free(differences2);
-		free(differences3);
-		free(differences5);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs3 = calloc(ny, sizeof(double));
-	if (!diffs3) {
-		free(differences2);
-		free(differences3);
-		free(differences5);
-		free(diffs2);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs5 = calloc(ny, sizeof(double));
-	if (!diffs5) {
-		free(differences2);
-		free(differences3);
-		free(differences5);
-		free(diffs2);
-		free(diffs3);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	/* loop over each row of the image */
-	for (jj=0; jj < ny; jj++) {
-
-                rowpix = array + (jj * nx); /* point to first pixel in the row */
-
-		/***** find the first valid pixel in row */
-		ii = 0;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v1 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v1 < xminval) xminval = v1;
-			if (v1 > xmaxval) xmaxval = v1;
-		}
-
-		/***** find the 2nd valid pixel in row (which we will skip over) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v2 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-		
-		if (do_range) {
-			if (v2 < xminval) xminval = v2;
-			if (v2 > xmaxval) xmaxval = v2;
-		}
-
-		/***** find the 3rd valid pixel in row */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v3 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v3 < xminval) xminval = v3;
-			if (v3 > xmaxval) xmaxval = v3;
-		}
-				
-		/* find the 4nd valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v4 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v4 < xminval) xminval = v4;
-			if (v4 > xmaxval) xmaxval = v4;
-		}
-			
-		/* find the 5th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v5 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v5 < xminval) xminval = v5;
-			if (v5 > xmaxval) xmaxval = v5;
-		}
-				
-		/* find the 6th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v6 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v6 < xminval) xminval = v6;
-			if (v6 > xmaxval) xmaxval = v6;
-		}
-				
-		/* find the 7th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v7 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v7 < xminval) xminval = v7;
-			if (v7 > xmaxval) xmaxval = v7;
-		}
-				
-		/* find the 8th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v8 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v8 < xminval) xminval = v8;
-			if (v8 > xmaxval) xmaxval = v8;
-		}
-		/* now populate the differences arrays */
-		/* for the remaining pixels in the row */
-		nvals = 0;
-		nvals2 = 0;
-		for (ii++; ii < nx; ii++) {
-
-		    /* find the next valid pixel in row */
-                    if (nullcheck)
-		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
-		     
-		    if (ii == nx) break;  /* hit end of row */
-		    v9 = rowpix[ii];  /* store the good pixel value */
-
-		    if (do_range) {
-			if (v9 < xminval) xminval = v9;
-			if (v9 > xmaxval) xmaxval = v9;
-		    }
-
-		    /* construct array of absolute differences */
-
-		    if (!(v5 == v6 && v6 == v7) ) {
-		        differences2[nvals2] =  abs((int) v5 - (int) v7);
-			nvals2++;
-		    }
-
-		    if (!(v3 == v4 && v4 == v5 && v5 == v6 && v6 == v7) ) {
-		        differences3[nvals] =  abs((2 * (int) v5) - (int) v3 - (int) v7);
-		        differences5[nvals] =  abs((6 * (int) v5) - (4 * (int) v3) - (4 * (int) v7) + (int) v1 + (int) v9);
-		        nvals++;  
-		    } else {
-		        /* ignore constant background regions */
-			ngoodpix++;
-		    }
-
-		    /* shift over 1 pixel */
-		    v1 = v2;
-		    v2 = v3;
-		    v3 = v4;
-		    v4 = v5;
-		    v5 = v6;
-		    v6 = v7;
-		    v7 = v8;
-		    v8 = v9;
-	        }  /* end of loop over pixels in the row */
-
-		/* compute the median diffs */
-		/* Note that there are 8 more pixel values than there are diffs values. */
-		ngoodpix += nvals;
-
-		if (nvals == 0) {
-		    continue;  /* cannot compute medians on this row */
-		} else if (nvals == 1) {
-		    if (nvals2 == 1) {
-		        diffs2[nrows2] = differences2[0];
-			nrows2++;
-		    }
-		        
-		    diffs3[nrows] = differences3[0];
-		    diffs5[nrows] = differences5[0];
-		} else {
-                    /* quick_select returns the median MUCH faster than using qsort */
-		    if (nvals2 > 1) {
-                        diffs2[nrows2] = quick_select_int(differences2, nvals);
-			nrows2++;
-		    }
-
-                    diffs3[nrows] = quick_select_int(differences3, nvals);
-                    diffs5[nrows] = quick_select_int(differences5, nvals);
-		}
-
-		nrows++;
-	}  /* end of loop over rows */
-
-	    /* compute median of the values for each row */
-	if (nrows == 0) { 
-	       xnoise3 = 0;
-	       xnoise5 = 0;
-	} else if (nrows == 1) {
-	       xnoise3 = diffs3[0];
-	       xnoise5 = diffs5[0];
-	} else {	    
-	       qsort(diffs3, nrows, sizeof(double), FnCompare_double);
-	       qsort(diffs5, nrows, sizeof(double), FnCompare_double);
-	       xnoise3 =  (diffs3[(nrows - 1)/2] + diffs3[nrows/2]) / 2.;
-	       xnoise5 =  (diffs5[(nrows - 1)/2] + diffs5[nrows/2]) / 2.;
-	}
-
-	if (nrows2 == 0) { 
-	       xnoise2 = 0;
-	} else if (nrows2 == 1) {
-	       xnoise2 = diffs2[0];
-	} else {	    
-	       qsort(diffs2, nrows2, sizeof(double), FnCompare_double);
-	       xnoise2 =  (diffs2[(nrows2 - 1)/2] + diffs2[nrows2/2]) / 2.;
-	}
-
-	if (ngood)  *ngood  = ngoodpix;
-	if (minval) *minval = xminval;
-	if (maxval) *maxval = xmaxval;
-	if (noise2)  *noise2  = 1.0483579 * xnoise2;
-	if (noise3)  *noise3  = 0.6052697 * xnoise3;
-	if (noise5)  *noise5  = 0.1772048 * xnoise5;
-
-	free(diffs5);
-	free(diffs3);
-	free(diffs2);
-	free(differences5);
-	free(differences3);
-	free(differences2);
-
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnNoise5_int
-       (int *array,       /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-        long ny,            /* number of rows in the image */
-	int nullcheck,      /* check for null values, if true */
-	int nullvalue,    /* value of null pixels, if nullcheck is true */
-   /* returned parameters */   
-	long *ngood,        /* number of good, non-null pixels? */
-	int *minval,    /* minimum non-null value */
-	int *maxval,    /* maximum non-null value */
-	double *noise2,      /* returned 2nd order MAD of all non-null pixels */
-	double *noise3,      /* returned 3rd order MAD of all non-null pixels */
-	double *noise5,      /* returned 5th order MAD of all non-null pixels */
-	int *status)        /* error status */
-
-/*
-Estimate the median and background noise in the input image using 2nd, 3rd and 5th
-order Median Absolute Differences.
-
-The noise in the background of the image is calculated using the MAD algorithms 
-developed for deriving the signal to noise ratio in spectra
-(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)
-
-3rd order:  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))
-
-The returned estimates are the median of the values that are computed for each 
-row of the image.
-*/
-{
-	long ii, jj, nrows = 0, nrows2 = 0, nvals, nvals2, ngoodpix = 0;
-	LONGLONG *differences2, *differences3, *differences5, tdiff;
-	int *rowpix, v1, v2, v3, v4, v5, v6, v7, v8, v9;
-	int xminval = INT_MAX, xmaxval = INT_MIN;
-	int do_range = 0;
-	double *diffs2, *diffs3, *diffs5; 
-	double xnoise2 = 0, xnoise3 = 0, xnoise5 = 0;
-	
-	if (nx < 9) {
-		/* treat entire array as an image with a single row */
-		nx = nx * ny;
-		ny = 1;
-	}
-
-	/* rows must have at least 9 pixels */
-	if (nx < 9) {
-
-		for (ii = 0; ii < nx; ii++) {
-		    if (nullcheck && array[ii] == nullvalue)
-		        continue;
-		    else {
-			if (array[ii] < xminval) xminval = array[ii];
-			if (array[ii] > xmaxval) xmaxval = array[ii];
-			ngoodpix++;
-		    }
-		}
-		if (minval) *minval = xminval;
-		if (maxval) *maxval = xmaxval;
-		if (ngood) *ngood = ngoodpix;
-		if (noise2) *noise2 = 0.;
-		if (noise3) *noise3 = 0.;
-		if (noise5) *noise5 = 0.;
-		return(*status);
-	}
-
-	/* do we need to compute the min and max value? */
-	if (minval || maxval) do_range = 1;
-	
-        /* allocate arrays used to compute the median and noise estimates */
-	differences2 = calloc(nx, sizeof(LONGLONG));
-	if (!differences2) {
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-	differences3 = calloc(nx, sizeof(LONGLONG));
-	if (!differences3) {
-		free(differences2);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-	differences5 = calloc(nx, sizeof(LONGLONG));
-	if (!differences5) {
-		free(differences2);
-		free(differences3);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs2 = calloc(ny, sizeof(double));
-	if (!diffs2) {
-		free(differences2);
-		free(differences3);
-		free(differences5);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs3 = calloc(ny, sizeof(double));
-	if (!diffs3) {
-		free(differences2);
-		free(differences3);
-		free(differences5);
-		free(diffs2);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs5 = calloc(ny, sizeof(double));
-	if (!diffs5) {
-		free(differences2);
-		free(differences3);
-		free(differences5);
-		free(diffs2);
-		free(diffs3);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	/* loop over each row of the image */
-	for (jj=0; jj < ny; jj++) {
-
-                rowpix = array + (jj * nx); /* point to first pixel in the row */
-
-		/***** find the first valid pixel in row */
-		ii = 0;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v1 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v1 < xminval) xminval = v1;
-			if (v1 > xmaxval) xmaxval = v1;
-		}
-
-		/***** find the 2nd valid pixel in row (which we will skip over) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v2 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-		
-		if (do_range) {
-			if (v2 < xminval) xminval = v2;
-			if (v2 > xmaxval) xmaxval = v2;
-		}
-
-		/***** find the 3rd valid pixel in row */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v3 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v3 < xminval) xminval = v3;
-			if (v3 > xmaxval) xmaxval = v3;
-		}
-				
-		/* find the 4nd valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v4 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v4 < xminval) xminval = v4;
-			if (v4 > xmaxval) xmaxval = v4;
-		}
-			
-		/* find the 5th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v5 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v5 < xminval) xminval = v5;
-			if (v5 > xmaxval) xmaxval = v5;
-		}
-				
-		/* find the 6th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v6 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v6 < xminval) xminval = v6;
-			if (v6 > xmaxval) xmaxval = v6;
-		}
-				
-		/* find the 7th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v7 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v7 < xminval) xminval = v7;
-			if (v7 > xmaxval) xmaxval = v7;
-		}
-				
-		/* find the 8th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v8 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v8 < xminval) xminval = v8;
-			if (v8 > xmaxval) xmaxval = v8;
-		}
-		/* now populate the differences arrays */
-		/* for the remaining pixels in the row */
-		nvals = 0;
-		nvals2 = 0;
-		for (ii++; ii < nx; ii++) {
-
-		    /* find the next valid pixel in row */
-                    if (nullcheck)
-		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
-		     
-		    if (ii == nx) break;  /* hit end of row */
-		    v9 = rowpix[ii];  /* store the good pixel value */
-
-		    if (do_range) {
-			if (v9 < xminval) xminval = v9;
-			if (v9 > xmaxval) xmaxval = v9;
-		    }
-
-		    /* construct array of absolute differences */
-
-		    if (!(v5 == v6 && v6 == v7) ) {
-		        tdiff =  (LONGLONG) v5 - (LONGLONG) v7;
-			if (tdiff < 0)
-		            differences2[nvals2] =  -1 * tdiff;
-			else
-		            differences2[nvals2] =  tdiff;
-
-			nvals2++;
-		    }
-
-		    if (!(v3 == v4 && v4 == v5 && v5 == v6 && v6 == v7) ) {
-		        tdiff =  (2 * (LONGLONG) v5) - (LONGLONG) v3 - (LONGLONG) v7;
-			if (tdiff < 0)
-		            differences3[nvals] =  -1 * tdiff;
-			else
-		            differences3[nvals] =  tdiff;
-
-		        tdiff =  (6 * (LONGLONG) v5) - (4 * (LONGLONG) v3) - (4 * (LONGLONG) v7) + (LONGLONG) v1 + (LONGLONG) v9;
-			if (tdiff < 0)
-		            differences5[nvals] =  -1 * tdiff;
-			else
-		            differences5[nvals] =  tdiff;
-
-		        nvals++;  
-		    } else {
-		        /* ignore constant background regions */
-			ngoodpix++;
-		    }
-
-		    /* shift over 1 pixel */
-		    v1 = v2;
-		    v2 = v3;
-		    v3 = v4;
-		    v4 = v5;
-		    v5 = v6;
-		    v6 = v7;
-		    v7 = v8;
-		    v8 = v9;
-	        }  /* end of loop over pixels in the row */
-
-		/* compute the median diffs */
-		/* Note that there are 8 more pixel values than there are diffs values. */
-		ngoodpix += nvals;
-
-		if (nvals == 0) {
-		    continue;  /* cannot compute medians on this row */
-		} else if (nvals == 1) {
-		    if (nvals2 == 1) {
-		        diffs2[nrows2] = (double) differences2[0];
-			nrows2++;
-		    }
-		        
-		    diffs3[nrows] = (double) differences3[0];
-		    diffs5[nrows] = (double) differences5[0];
-		} else {
-                    /* quick_select returns the median MUCH faster than using qsort */
-		    if (nvals2 > 1) {
-                        diffs2[nrows2] = (double) quick_select_longlong(differences2, nvals);
-			nrows2++;
-		    }
-
-                    diffs3[nrows] = (double) quick_select_longlong(differences3, nvals);
-                    diffs5[nrows] = (double) quick_select_longlong(differences5, nvals);
-		}
-
-		nrows++;
-	}  /* end of loop over rows */
-
-	    /* compute median of the values for each row */
-	if (nrows == 0) { 
-	       xnoise3 = 0;
-	       xnoise5 = 0;
-	} else if (nrows == 1) {
-	       xnoise3 = diffs3[0];
-	       xnoise5 = diffs5[0];
-	} else {	    
-	       qsort(diffs3, nrows, sizeof(double), FnCompare_double);
-	       qsort(diffs5, nrows, sizeof(double), FnCompare_double);
-	       xnoise3 =  (diffs3[(nrows - 1)/2] + diffs3[nrows/2]) / 2.;
-	       xnoise5 =  (diffs5[(nrows - 1)/2] + diffs5[nrows/2]) / 2.;
-	}
-
-	if (nrows2 == 0) { 
-	       xnoise2 = 0;
-	} else if (nrows2 == 1) {
-	       xnoise2 = diffs2[0];
-	} else {	    
-	       qsort(diffs2, nrows2, sizeof(double), FnCompare_double);
-	       xnoise2 =  (diffs2[(nrows2 - 1)/2] + diffs2[nrows2/2]) / 2.;
-	}
-
-	if (ngood)  *ngood  = ngoodpix;
-	if (minval) *minval = xminval;
-	if (maxval) *maxval = xmaxval;
-	if (noise2)  *noise2  = 1.0483579 * xnoise2;
-	if (noise3)  *noise3  = 0.6052697 * xnoise3;
-	if (noise5)  *noise5  = 0.1772048 * xnoise5;
-
-	free(diffs5);
-	free(diffs3);
-	free(diffs2);
-	free(differences5);
-	free(differences3);
-	free(differences2);
-
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnNoise5_float
-       (float *array,       /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-        long ny,            /* number of rows in the image */
-	int nullcheck,      /* check for null values, if true */
-	float nullvalue,    /* value of null pixels, if nullcheck is true */
-   /* returned parameters */   
-	long *ngood,        /* number of good, non-null pixels? */
-	float *minval,    /* minimum non-null value */
-	float *maxval,    /* maximum non-null value */
-	double *noise2,      /* returned 2nd order MAD of all non-null pixels */
-	double *noise3,      /* returned 3rd order MAD of all non-null pixels */
-	double *noise5,      /* returned 5th order MAD of all non-null pixels */
-	int *status)        /* error status */
-
-/*
-Estimate the median and background noise in the input image using 2nd, 3rd and 5th
-order Median Absolute Differences.
-
-The noise in the background of the image is calculated using the MAD algorithms 
-developed for deriving the signal to noise ratio in spectra
-(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)
-
-3rd order:  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))
-
-The returned estimates are the median of the values that are computed for each 
-row of the image.
-*/
-{
-	long ii, jj, nrows = 0, nrows2 = 0, nvals, nvals2, ngoodpix = 0;
-	float *differences2, *differences3, *differences5;
-	float *rowpix, v1, v2, v3, v4, v5, v6, v7, v8, v9;
-	float xminval = FLT_MAX, xmaxval = -FLT_MAX;
-	int do_range = 0;
-	double *diffs2, *diffs3, *diffs5; 
-	double xnoise2 = 0, xnoise3 = 0, xnoise5 = 0;
-	
-	if (nx < 9) {
-		/* treat entire array as an image with a single row */
-		nx = nx * ny;
-		ny = 1;
-	}
-
-	/* rows must have at least 9 pixels */
-	if (nx < 9) {
-
-		for (ii = 0; ii < nx; ii++) {
-		    if (nullcheck && array[ii] == nullvalue)
-		        continue;
-		    else {
-			if (array[ii] < xminval) xminval = array[ii];
-			if (array[ii] > xmaxval) xmaxval = array[ii];
-			ngoodpix++;
-		    }
-		}
-		if (minval) *minval = xminval;
-		if (maxval) *maxval = xmaxval;
-		if (ngood) *ngood = ngoodpix;
-		if (noise2) *noise2 = 0.;
-		if (noise3) *noise3 = 0.;
-		if (noise5) *noise5 = 0.;
-		return(*status);
-	}
-
-	/* do we need to compute the min and max value? */
-	if (minval || maxval) do_range = 1;
-	
-        /* allocate arrays used to compute the median and noise estimates */
-	differences2 = calloc(nx, sizeof(float));
-	if (!differences2) {
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-	differences3 = calloc(nx, sizeof(float));
-	if (!differences3) {
-		free(differences2);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-	differences5 = calloc(nx, sizeof(float));
-	if (!differences5) {
-		free(differences2);
-		free(differences3);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs2 = calloc(ny, sizeof(double));
-	if (!diffs2) {
-		free(differences2);
-		free(differences3);
-		free(differences5);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs3 = calloc(ny, sizeof(double));
-	if (!diffs3) {
-		free(differences2);
-		free(differences3);
-		free(differences5);
-		free(diffs2);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs5 = calloc(ny, sizeof(double));
-	if (!diffs5) {
-		free(differences2);
-		free(differences3);
-		free(differences5);
-		free(diffs2);
-		free(diffs3);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	/* loop over each row of the image */
-	for (jj=0; jj < ny; jj++) {
-
-                rowpix = array + (jj * nx); /* point to first pixel in the row */
-
-		/***** find the first valid pixel in row */
-		ii = 0;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v1 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v1 < xminval) xminval = v1;
-			if (v1 > xmaxval) xmaxval = v1;
-		}
-
-		/***** find the 2nd valid pixel in row (which we will skip over) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v2 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-		
-		if (do_range) {
-			if (v2 < xminval) xminval = v2;
-			if (v2 > xmaxval) xmaxval = v2;
-		}
-
-		/***** find the 3rd valid pixel in row */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v3 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v3 < xminval) xminval = v3;
-			if (v3 > xmaxval) xmaxval = v3;
-		}
-				
-		/* find the 4nd valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v4 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v4 < xminval) xminval = v4;
-			if (v4 > xmaxval) xmaxval = v4;
-		}
-			
-		/* find the 5th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v5 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v5 < xminval) xminval = v5;
-			if (v5 > xmaxval) xmaxval = v5;
-		}
-				
-		/* find the 6th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v6 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v6 < xminval) xminval = v6;
-			if (v6 > xmaxval) xmaxval = v6;
-		}
-				
-		/* find the 7th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v7 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v7 < xminval) xminval = v7;
-			if (v7 > xmaxval) xmaxval = v7;
-		}
-				
-		/* find the 8th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v8 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v8 < xminval) xminval = v8;
-			if (v8 > xmaxval) xmaxval = v8;
-		}
-		/* now populate the differences arrays */
-		/* for the remaining pixels in the row */
-		nvals = 0;
-		nvals2 = 0;
-		for (ii++; ii < nx; ii++) {
-
-		    /* find the next valid pixel in row */
-                    if (nullcheck)
-		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
-		     
-		    if (ii == nx) break;  /* hit end of row */
-		    v9 = rowpix[ii];  /* store the good pixel value */
-
-		    if (do_range) {
-			if (v9 < xminval) xminval = v9;
-			if (v9 > xmaxval) xmaxval = v9;
-		    }
-
-		    /* construct array of absolute differences */
-
-		    if (!(v5 == v6 && v6 == v7) ) {
-		        differences2[nvals2] = (float) fabs(v5 - v7);
-			nvals2++;
-		    }
-
-		    if (!(v3 == v4 && v4 == v5 && v5 == v6 && v6 == v7) ) {
-		        differences3[nvals] = (float) fabs((2 * v5) - v3 - v7);
-		        differences5[nvals] = (float) fabs((6 * v5) - (4 * v3) - (4 * v7) + v1 + v9);
-		        nvals++;  
-		    } else {
-		        /* ignore constant background regions */
-			ngoodpix++;
-		    }
-
-		    /* shift over 1 pixel */
-		    v1 = v2;
-		    v2 = v3;
-		    v3 = v4;
-		    v4 = v5;
-		    v5 = v6;
-		    v6 = v7;
-		    v7 = v8;
-		    v8 = v9;
-	        }  /* end of loop over pixels in the row */
-
-		/* compute the median diffs */
-		/* Note that there are 8 more pixel values than there are diffs values. */
-		ngoodpix += nvals;
-
-		if (nvals == 0) {
-		    continue;  /* cannot compute medians on this row */
-		} else if (nvals == 1) {
-		    if (nvals2 == 1) {
-		        diffs2[nrows2] = differences2[0];
-			nrows2++;
-		    }
-		        
-		    diffs3[nrows] = differences3[0];
-		    diffs5[nrows] = differences5[0];
-		} else {
-                    /* quick_select returns the median MUCH faster than using qsort */
-		    if (nvals2 > 1) {
-                        diffs2[nrows2] = quick_select_float(differences2, nvals);
-			nrows2++;
-		    }
-
-                    diffs3[nrows] = quick_select_float(differences3, nvals);
-                    diffs5[nrows] = quick_select_float(differences5, nvals);
-		}
-
-		nrows++;
-	}  /* end of loop over rows */
-
-	    /* compute median of the values for each row */
-	if (nrows == 0) { 
-	       xnoise3 = 0;
-	       xnoise5 = 0;
-	} else if (nrows == 1) {
-	       xnoise3 = diffs3[0];
-	       xnoise5 = diffs5[0];
-	} else {	    
-	       qsort(diffs3, nrows, sizeof(double), FnCompare_double);
-	       qsort(diffs5, nrows, sizeof(double), FnCompare_double);
-	       xnoise3 =  (diffs3[(nrows - 1)/2] + diffs3[nrows/2]) / 2.;
-	       xnoise5 =  (diffs5[(nrows - 1)/2] + diffs5[nrows/2]) / 2.;
-	}
-
-	if (nrows2 == 0) { 
-	       xnoise2 = 0;
-	} else if (nrows2 == 1) {
-	       xnoise2 = diffs2[0];
-	} else {	    
-	       qsort(diffs2, nrows2, sizeof(double), FnCompare_double);
-	       xnoise2 =  (diffs2[(nrows2 - 1)/2] + diffs2[nrows2/2]) / 2.;
-	}
-
-	if (ngood)  *ngood  = ngoodpix;
-	if (minval) *minval = xminval;
-	if (maxval) *maxval = xmaxval;
-	if (noise2)  *noise2  = 1.0483579 * xnoise2;
-	if (noise3)  *noise3  = 0.6052697 * xnoise3;
-	if (noise5)  *noise5  = 0.1772048 * xnoise5;
-
-	free(diffs5);
-	free(diffs3);
-	free(diffs2);
-	free(differences5);
-	free(differences3);
-	free(differences2);
-
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnNoise5_double
-       (double *array,       /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-        long ny,            /* number of rows in the image */
-	int nullcheck,      /* check for null values, if true */
-	double nullvalue,    /* value of null pixels, if nullcheck is true */
-   /* returned parameters */   
-	long *ngood,        /* number of good, non-null pixels? */
-	double *minval,    /* minimum non-null value */
-	double *maxval,    /* maximum non-null value */
-	double *noise2,      /* returned 2nd order MAD of all non-null pixels */
-	double *noise3,      /* returned 3rd order MAD of all non-null pixels */
-	double *noise5,      /* returned 5th order MAD of all non-null pixels */
-	int *status)        /* error status */
-
-/*
-Estimate the median and background noise in the input image using 2nd, 3rd and 5th
-order Median Absolute Differences.
-
-The noise in the background of the image is calculated using the MAD algorithms 
-developed for deriving the signal to noise ratio in spectra
-(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)
-
-3rd order:  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))
-
-The returned estimates are the median of the values that are computed for each 
-row of the image.
-*/
-{
-	long ii, jj, nrows = 0, nrows2 = 0, nvals, nvals2, ngoodpix = 0;
-	double *differences2, *differences3, *differences5;
-	double *rowpix, v1, v2, v3, v4, v5, v6, v7, v8, v9;
-	double xminval = DBL_MAX, xmaxval = -DBL_MAX;
-	int do_range = 0;
-	double *diffs2, *diffs3, *diffs5; 
-	double xnoise2 = 0, xnoise3 = 0, xnoise5 = 0;
-	
-	if (nx < 9) {
-		/* treat entire array as an image with a single row */
-		nx = nx * ny;
-		ny = 1;
-	}
-
-	/* rows must have at least 9 pixels */
-	if (nx < 9) {
-
-		for (ii = 0; ii < nx; ii++) {
-		    if (nullcheck && array[ii] == nullvalue)
-		        continue;
-		    else {
-			if (array[ii] < xminval) xminval = array[ii];
-			if (array[ii] > xmaxval) xmaxval = array[ii];
-			ngoodpix++;
-		    }
-		}
-		if (minval) *minval = xminval;
-		if (maxval) *maxval = xmaxval;
-		if (ngood) *ngood = ngoodpix;
-		if (noise2) *noise2 = 0.;
-		if (noise3) *noise3 = 0.;
-		if (noise5) *noise5 = 0.;
-		return(*status);
-	}
-
-	/* do we need to compute the min and max value? */
-	if (minval || maxval) do_range = 1;
-	
-        /* allocate arrays used to compute the median and noise estimates */
-	differences2 = calloc(nx, sizeof(double));
-	if (!differences2) {
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-	differences3 = calloc(nx, sizeof(double));
-	if (!differences3) {
-		free(differences2);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-	differences5 = calloc(nx, sizeof(double));
-	if (!differences5) {
-		free(differences2);
-		free(differences3);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs2 = calloc(ny, sizeof(double));
-	if (!diffs2) {
-		free(differences2);
-		free(differences3);
-		free(differences5);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs3 = calloc(ny, sizeof(double));
-	if (!diffs3) {
-		free(differences2);
-		free(differences3);
-		free(differences5);
-		free(diffs2);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs5 = calloc(ny, sizeof(double));
-	if (!diffs5) {
-		free(differences2);
-		free(differences3);
-		free(differences5);
-		free(diffs2);
-		free(diffs3);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	/* loop over each row of the image */
-	for (jj=0; jj < ny; jj++) {
-
-                rowpix = array + (jj * nx); /* point to first pixel in the row */
-
-		/***** find the first valid pixel in row */
-		ii = 0;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v1 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v1 < xminval) xminval = v1;
-			if (v1 > xmaxval) xmaxval = v1;
-		}
-
-		/***** find the 2nd valid pixel in row (which we will skip over) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v2 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-		
-		if (do_range) {
-			if (v2 < xminval) xminval = v2;
-			if (v2 > xmaxval) xmaxval = v2;
-		}
-
-		/***** find the 3rd valid pixel in row */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v3 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v3 < xminval) xminval = v3;
-			if (v3 > xmaxval) xmaxval = v3;
-		}
-				
-		/* find the 4nd valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v4 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v4 < xminval) xminval = v4;
-			if (v4 > xmaxval) xmaxval = v4;
-		}
-			
-		/* find the 5th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v5 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v5 < xminval) xminval = v5;
-			if (v5 > xmaxval) xmaxval = v5;
-		}
-				
-		/* find the 6th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v6 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v6 < xminval) xminval = v6;
-			if (v6 > xmaxval) xmaxval = v6;
-		}
-				
-		/* find the 7th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v7 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v7 < xminval) xminval = v7;
-			if (v7 > xmaxval) xmaxval = v7;
-		}
-				
-		/* find the 8th valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v8 = rowpix[ii];  /* store the good pixel value */
-		ngoodpix++;
-
-		if (do_range) {
-			if (v8 < xminval) xminval = v8;
-			if (v8 > xmaxval) xmaxval = v8;
-		}
-		/* now populate the differences arrays */
-		/* for the remaining pixels in the row */
-		nvals = 0;
-		nvals2 = 0;
-		for (ii++; ii < nx; ii++) {
-
-		    /* find the next valid pixel in row */
-                    if (nullcheck)
-		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
-		     
-		    if (ii == nx) break;  /* hit end of row */
-		    v9 = rowpix[ii];  /* store the good pixel value */
-
-		    if (do_range) {
-			if (v9 < xminval) xminval = v9;
-			if (v9 > xmaxval) xmaxval = v9;
-		    }
-
-		    /* construct array of absolute differences */
-
-		    if (!(v5 == v6 && v6 == v7) ) {
-		        differences2[nvals2] =  fabs(v5 - v7);
-			nvals2++;
-		    }
-
-		    if (!(v3 == v4 && v4 == v5 && v5 == v6 && v6 == v7) ) {
-		        differences3[nvals] =  fabs((2 * v5) - v3 - v7);
-		        differences5[nvals] =  fabs((6 * v5) - (4 * v3) - (4 * v7) + v1 + v9);
-		        nvals++;  
-		    } else {
-		        /* ignore constant background regions */
-			ngoodpix++;
-		    }
-
-		    /* shift over 1 pixel */
-		    v1 = v2;
-		    v2 = v3;
-		    v3 = v4;
-		    v4 = v5;
-		    v5 = v6;
-		    v6 = v7;
-		    v7 = v8;
-		    v8 = v9;
-	        }  /* end of loop over pixels in the row */
-
-		/* compute the median diffs */
-		/* Note that there are 8 more pixel values than there are diffs values. */
-		ngoodpix += nvals;
-
-		if (nvals == 0) {
-		    continue;  /* cannot compute medians on this row */
-		} else if (nvals == 1) {
-		    if (nvals2 == 1) {
-		        diffs2[nrows2] = differences2[0];
-			nrows2++;
-		    }
-		        
-		    diffs3[nrows] = differences3[0];
-		    diffs5[nrows] = differences5[0];
-		} else {
-                    /* quick_select returns the median MUCH faster than using qsort */
-		    if (nvals2 > 1) {
-                        diffs2[nrows2] = quick_select_double(differences2, nvals);
-			nrows2++;
-		    }
-
-                    diffs3[nrows] = quick_select_double(differences3, nvals);
-                    diffs5[nrows] = quick_select_double(differences5, nvals);
-		}
-
-		nrows++;
-	}  /* end of loop over rows */
-
-	    /* compute median of the values for each row */
-	if (nrows == 0) { 
-	       xnoise3 = 0;
-	       xnoise5 = 0;
-	} else if (nrows == 1) {
-	       xnoise3 = diffs3[0];
-	       xnoise5 = diffs5[0];
-	} else {	    
-	       qsort(diffs3, nrows, sizeof(double), FnCompare_double);
-	       qsort(diffs5, nrows, sizeof(double), FnCompare_double);
-	       xnoise3 =  (diffs3[(nrows - 1)/2] + diffs3[nrows/2]) / 2.;
-	       xnoise5 =  (diffs5[(nrows - 1)/2] + diffs5[nrows/2]) / 2.;
-	}
-
-	if (nrows2 == 0) { 
-	       xnoise2 = 0;
-	} else if (nrows2 == 1) {
-	       xnoise2 = diffs2[0];
-	} else {	    
-	       qsort(diffs2, nrows2, sizeof(double), FnCompare_double);
-	       xnoise2 =  (diffs2[(nrows2 - 1)/2] + diffs2[nrows2/2]) / 2.;
-	}
-
-	if (ngood)  *ngood  = ngoodpix;
-	if (minval) *minval = xminval;
-	if (maxval) *maxval = xmaxval;
-	if (noise2)  *noise2  = 1.0483579 * xnoise2;
-	if (noise3)  *noise3  = 0.6052697 * xnoise3;
-	if (noise5)  *noise5  = 0.1772048 * xnoise5;
-
-	free(diffs5);
-	free(diffs3);
-	free(diffs2);
-	free(differences5);
-	free(differences3);
-	free(differences2);
-
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnNoise3_short
-       (short *array,       /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-        long ny,            /* number of rows in the image */
-	int nullcheck,      /* check for null values, if true */
-	short nullvalue,    /* value of null pixels, if nullcheck is true */
-   /* returned parameters */   
-	long *ngood,        /* number of good, non-null pixels? */
-	short *minval,    /* minimum non-null value */
-	short *maxval,    /* maximum non-null value */
-	double *noise,      /* returned R.M.S. value of all non-null pixels */
-	int *status)        /* error status */
-
-/*
-Estimate the median and background noise in the input image using 3rd order differences.
-
-The noise in the background of the image is calculated using the 3rd order algorithm 
-developed for deriving the signal to noise ratio in spectra
-(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)
-
-  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))
-
-The returned estimates are the median of the values that are computed for each 
-row of the image.
-*/
-{
-	long ii, jj, nrows = 0, nvals, ngoodpix = 0;
-	short *differences, *rowpix, v1, v2, v3, v4, v5;
-	short xminval = SHRT_MAX, xmaxval = SHRT_MIN, do_range = 0;
-	double *diffs, xnoise = 0, sigma;
-
-	if (nx < 5) {
-		/* treat entire array as an image with a single row */
-		nx = nx * ny;
-		ny = 1;
-	}
-
-	/* rows must have at least 5 pixels */
-	if (nx < 5) {
-
-		for (ii = 0; ii < nx; ii++) {
-		    if (nullcheck && array[ii] == nullvalue)
-		        continue;
-		    else {
-			if (array[ii] < xminval) xminval = array[ii];
-			if (array[ii] > xmaxval) xmaxval = array[ii];
-			ngoodpix++;
-		    }
-		}
-		if (minval) *minval = xminval;
-		if (maxval) *maxval = xmaxval;
-		if (ngood) *ngood = ngoodpix;
-		if (noise) *noise = 0.;
-		return(*status);
-	}
-
-	/* do we need to compute the min and max value? */
-	if (minval || maxval) do_range = 1;
-	
-        /* allocate arrays used to compute the median and noise estimates */
-	differences = calloc(nx, sizeof(short));
-	if (!differences) {
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs = calloc(ny, sizeof(double));
-	if (!diffs) {
-		free(differences);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	/* loop over each row of the image */
-	for (jj=0; jj < ny; jj++) {
-
-                rowpix = array + (jj * nx); /* point to first pixel in the row */
-
-		/***** find the first valid pixel in row */
-		ii = 0;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v1 = rowpix[ii];  /* store the good pixel value */
-
-		if (do_range) {
-			if (v1 < xminval) xminval = v1;
-			if (v1 > xmaxval) xmaxval = v1;
-		}
-
-		/***** find the 2nd valid pixel in row (which we will skip over) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v2 = rowpix[ii];  /* store the good pixel value */
-		
-		if (do_range) {
-			if (v2 < xminval) xminval = v2;
-			if (v2 > xmaxval) xmaxval = v2;
-		}
-
-		/***** find the 3rd valid pixel in row */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v3 = rowpix[ii];  /* store the good pixel value */
-
-		if (do_range) {
-			if (v3 < xminval) xminval = v3;
-			if (v3 > xmaxval) xmaxval = v3;
-		}
-				
-		/* find the 4nd valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v4 = rowpix[ii];  /* store the good pixel value */
-
-		if (do_range) {
-			if (v4 < xminval) xminval = v4;
-			if (v4 > xmaxval) xmaxval = v4;
-		}
-		
-		/* now populate the differences arrays */
-		/* for the remaining pixels in the row */
-		nvals = 0;
-		for (ii++; ii < nx; ii++) {
-
-		    /* find the next valid pixel in row */
-                    if (nullcheck)
-		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
-		     
-		    if (ii == nx) break;  /* hit end of row */
-		    v5 = rowpix[ii];  /* store the good pixel value */
-
-		    if (do_range) {
-			if (v5 < xminval) xminval = v5;
-			if (v5 > xmaxval) xmaxval = v5;
-		    }
-
-		    /* construct array of 3rd order absolute differences */
-		    if (!(v1 == v2 && v2 == v3 && v3 == v4 && v4 == v5)) {
-		        differences[nvals] = abs((2 * v3) - v1 - v5);
-		        nvals++;  
-		    } else {
-		        /* ignore constant background regions */
-			ngoodpix++;
-		    }
-
-
-		    /* shift over 1 pixel */
-		    v1 = v2;
-		    v2 = v3;
-		    v3 = v4;
-		    v4 = v5;
-	        }  /* end of loop over pixels in the row */
-
-		/* compute the 3rd order diffs */
-		/* Note that there are 4 more pixel values than there are diffs values. */
-		ngoodpix += (nvals + 4);
-
-		if (nvals == 0) {
-		    continue;  /* cannot compute medians on this row */
-		} else if (nvals == 1) {
-		    diffs[nrows] = differences[0];
-		} else {
-                    /* quick_select returns the median MUCH faster than using qsort */
-                    diffs[nrows] = quick_select_short(differences, nvals);
-		}
-
-		nrows++;
-	}  /* end of loop over rows */
-
-	    /* compute median of the values for each row */
-	if (nrows == 0) { 
-	       xnoise = 0;
-	} else if (nrows == 1) {
-	       xnoise = diffs[0];
-	} else {	    
-
-
-	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
-	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
-
-              FnMeanSigma_double(diffs, nrows, 0, 0.0, 0, &xnoise, &sigma, status); 
-
-	      /* do a 4.5 sigma rejection of outliers */
-	      jj = 0;
-	      sigma = 4.5 * sigma;
-	      for (ii = 0; ii < nrows; ii++) {
-		if ( fabs(diffs[ii] - xnoise) <= sigma)	 {
-		   if (jj != ii)
-		       diffs[jj] = diffs[ii];
-		   jj++;
-	        } 
-	      }
-	      if (ii != jj)
-                FnMeanSigma_double(diffs, jj, 0, 0.0, 0, &xnoise, &sigma, status); 
-	}
-
-	if (ngood)  *ngood  = ngoodpix;
-	if (minval) *minval = xminval;
-	if (maxval) *maxval = xmaxval;
-	if (noise)  *noise  = 0.6052697 * xnoise;
-
-	free(diffs);
-	free(differences);
-
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnNoise3_int
-       (int *array,       /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-        long ny,            /* number of rows in the image */
-	int nullcheck,      /* check for null values, if true */
-	int nullvalue,    /* value of null pixels, if nullcheck is true */
-   /* returned parameters */   
-	long *ngood,        /* number of good, non-null pixels? */
-	int *minval,    /* minimum non-null value */
-	int *maxval,    /* maximum non-null value */
-	double *noise,      /* returned R.M.S. value of all non-null pixels */
-	int *status)        /* error status */
-
-/*
-Estimate the background noise in the input image using 3rd order differences.
-
-The noise in the background of the image is calculated using the 3rd order algorithm 
-developed for deriving the signal to noise ratio in spectra
-(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)
-
-  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))
-
-The returned estimates are the median of the values that are computed for each 
-row of the image.
-*/
-{
-	long ii, jj, nrows = 0, nvals, ngoodpix = 0;
-	int *differences, *rowpix, v1, v2, v3, v4, v5;
-	int xminval = INT_MAX, xmaxval = INT_MIN, do_range = 0;
-	double *diffs, xnoise = 0, sigma;
-	
-	if (nx < 5) {
-		/* treat entire array as an image with a single row */
-		nx = nx * ny;
-		ny = 1;
-	}
-
-	/* rows must have at least 5 pixels */
-	if (nx < 5) {
-
-		for (ii = 0; ii < nx; ii++) {
-		    if (nullcheck && array[ii] == nullvalue)
-		        continue;
-		    else {
-			if (array[ii] < xminval) xminval = array[ii];
-			if (array[ii] > xmaxval) xmaxval = array[ii];
-			ngoodpix++;
-		    }
-		}
-		if (minval) *minval = xminval;
-		if (maxval) *maxval = xmaxval;
-		if (ngood) *ngood = ngoodpix;
-		if (noise) *noise = 0.;
-		return(*status);
-	}
-
-	/* do we need to compute the min and max value? */
-	if (minval || maxval) do_range = 1;
-	
-        /* allocate arrays used to compute the median and noise estimates */
-	differences = calloc(nx, sizeof(int));
-	if (!differences) {
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs = calloc(ny, sizeof(double));
-	if (!diffs) {
-		free(differences);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	/* loop over each row of the image */
-	for (jj=0; jj < ny; jj++) {
-
-                rowpix = array + (jj * nx); /* point to first pixel in the row */
-
-		/***** find the first valid pixel in row */
-		ii = 0;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v1 = rowpix[ii];  /* store the good pixel value */
-
-		if (do_range) {
-			if (v1 < xminval) xminval = v1;
-			if (v1 > xmaxval) xmaxval = v1;
-		}
-
-		/***** find the 2nd valid pixel in row (which we will skip over) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v2 = rowpix[ii];  /* store the good pixel value */
-		
-		if (do_range) {
-			if (v2 < xminval) xminval = v2;
-			if (v2 > xmaxval) xmaxval = v2;
-		}
-
-		/***** find the 3rd valid pixel in row */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v3 = rowpix[ii];  /* store the good pixel value */
-
-		if (do_range) {
-			if (v3 < xminval) xminval = v3;
-			if (v3 > xmaxval) xmaxval = v3;
-		}
-				
-		/* find the 4nd valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v4 = rowpix[ii];  /* store the good pixel value */
-
-		if (do_range) {
-			if (v4 < xminval) xminval = v4;
-			if (v4 > xmaxval) xmaxval = v4;
-		}
-		
-		/* now populate the differences arrays */
-		/* for the remaining pixels in the row */
-		nvals = 0;
-		for (ii++; ii < nx; ii++) {
-
-		    /* find the next valid pixel in row */
-                    if (nullcheck)
-		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
-		     
-		    if (ii == nx) break;  /* hit end of row */
-		    v5 = rowpix[ii];  /* store the good pixel value */
-
-		    if (do_range) {
-			if (v5 < xminval) xminval = v5;
-			if (v5 > xmaxval) xmaxval = v5;
-		    }
-
-		    /* construct array of 3rd order absolute differences */
-		    if (!(v1 == v2 && v2 == v3 && v3 == v4 && v4 == v5)) {
-		        differences[nvals] = abs((2 * v3) - v1 - v5);
-		        nvals++;  
-		    } else {
-		        /* ignore constant background regions */
-			ngoodpix++;
-		    }
-
-		    /* shift over 1 pixel */
-		    v1 = v2;
-		    v2 = v3;
-		    v3 = v4;
-		    v4 = v5;
-	        }  /* end of loop over pixels in the row */
-
-		/* compute the 3rd order diffs */
-		/* Note that there are 4 more pixel values than there are diffs values. */
-		ngoodpix += (nvals + 4);
-
-		if (nvals == 0) {
-		    continue;  /* cannot compute medians on this row */
-		} else if (nvals == 1) {
-		    diffs[nrows] = differences[0];
-		} else {
-                    /* quick_select returns the median MUCH faster than using qsort */
-                    diffs[nrows] = quick_select_int(differences, nvals);
-		}
-
-		nrows++;
-	}  /* end of loop over rows */
-
-	    /* compute median of the values for each row */
-	if (nrows == 0) { 
-	       xnoise = 0;
-	} else if (nrows == 1) {
-	       xnoise = diffs[0];
-	} else {	    
-
-	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
-	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
-
-              FnMeanSigma_double(diffs, nrows, 0, 0.0, 0, &xnoise, &sigma, status); 
-
-	      /* do a 4.5 sigma rejection of outliers */
-	      jj = 0;
-	      sigma = 4.5 * sigma;
-	      for (ii = 0; ii < nrows; ii++) {
-		if ( fabs(diffs[ii] - xnoise) <= sigma)	 {
-		   if (jj != ii)
-		       diffs[jj] = diffs[ii];
-		   jj++;
-	        }
-	      }
-	      if (ii != jj)
-                FnMeanSigma_double(diffs, jj, 0, 0.0, 0, &xnoise, &sigma, status); 
-	}
-
-	if (ngood)  *ngood  = ngoodpix;
-	if (minval) *minval = xminval;
-	if (maxval) *maxval = xmaxval;
-	if (noise)  *noise  = 0.6052697 * xnoise;
-
-	free(diffs);
-	free(differences);
-
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnNoise3_float
-       (float *array,       /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-        long ny,            /* number of rows in the image */
-	int nullcheck,      /* check for null values, if true */
-	float nullvalue,    /* value of null pixels, if nullcheck is true */
-   /* returned parameters */   
-	long *ngood,        /* number of good, non-null pixels? */
-	float *minval,    /* minimum non-null value */
-	float *maxval,    /* maximum non-null value */
-	double *noise,      /* returned R.M.S. value of all non-null pixels */
-	int *status)        /* error status */
-
-/*
-Estimate the median and background noise in the input image using 3rd order differences.
-
-The noise in the background of the image is calculated using the 3rd order algorithm 
-developed for deriving the signal to noise ratio in spectra
-(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)
-
-  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))
-
-The returned estimates are the median of the values that are computed for each 
-row of the image.
-*/
-{
-	long ii, jj, nrows = 0, nvals, ngoodpix = 0;
-	float *differences, *rowpix, v1, v2, v3, v4, v5;
-	float xminval = FLT_MAX, xmaxval = -FLT_MAX;
-	int do_range = 0;
-	double *diffs, xnoise = 0;
-
-	if (nx < 5) {
-		/* treat entire array as an image with a single row */
-		nx = nx * ny;
-		ny = 1;
-	}
-
-	/* rows must have at least 5 pixels to calc noise, so just calc min, max, ngood */
-	if (nx < 5) {
-
-		for (ii = 0; ii < nx; ii++) {
-		    if (nullcheck && array[ii] == nullvalue)
-		        continue;
-		    else {
-			if (array[ii] < xminval) xminval = array[ii];
-			if (array[ii] > xmaxval) xmaxval = array[ii];
-			ngoodpix++;
-		    }
-		}
-		if (minval) *minval = xminval;
-		if (maxval) *maxval = xmaxval;
-		if (ngood) *ngood = ngoodpix;
-		if (noise) *noise = 0.;
-		return(*status);
-	}
-
-	/* do we need to compute the min and max value? */
-	if (minval || maxval) do_range = 1;
-	
-        /* allocate arrays used to compute the median and noise estimates */
-	if (noise) {
-	    differences = calloc(nx, sizeof(float));
-	    if (!differences) {
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	    }
-
-	    diffs = calloc(ny, sizeof(double));
-	    if (!diffs) {
-		free(differences);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	    }
-	}
-
-	/* loop over each row of the image */
-	for (jj=0; jj < ny; jj++) {
-
-                rowpix = array + (jj * nx); /* point to first pixel in the row */
-
-		/***** find the first valid pixel in row */
-		ii = 0;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v1 = rowpix[ii];  /* store the good pixel value */
-
-		if (do_range) {
-			if (v1 < xminval) xminval = v1;
-			if (v1 > xmaxval) xmaxval = v1;
-		}
-
-		/***** find the 2nd valid pixel in row (which we will skip over) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v2 = rowpix[ii];  /* store the good pixel value */
-		
-		if (do_range) {
-			if (v2 < xminval) xminval = v2;
-			if (v2 > xmaxval) xmaxval = v2;
-		}
-
-		/***** find the 3rd valid pixel in row */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v3 = rowpix[ii];  /* store the good pixel value */
-
-		if (do_range) {
-			if (v3 < xminval) xminval = v3;
-			if (v3 > xmaxval) xmaxval = v3;
-		}
-				
-		/* find the 4nd valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v4 = rowpix[ii];  /* store the good pixel value */
-
-		if (do_range) {
-			if (v4 < xminval) xminval = v4;
-			if (v4 > xmaxval) xmaxval = v4;
-		}
-		
-		/* now populate the differences arrays */
-		/* for the remaining pixels in the row */
-		nvals = 0;
-		for (ii++; ii < nx; ii++) {
-
-		    /* find the next valid pixel in row */
-                    if (nullcheck)
-		        while (ii < nx && rowpix[ii] == nullvalue) {
-			  ii++;
-		        }
-			
-		    if (ii == nx) break;  /* hit end of row */
-		    v5 = rowpix[ii];  /* store the good pixel value */
-
-		    if (do_range) {
-			if (v5 < xminval) xminval = v5;
-			if (v5 > xmaxval) xmaxval = v5;
-		    }
-
-		    /* construct array of 3rd order absolute differences */
-		    if (noise) {
-		        if (!(v1 == v2 && v2 == v3 && v3 == v4 && v4 == v5)) {
-
-		            differences[nvals] = (float) fabs((2. * v3) - v1 - v5);
-		            nvals++;  
-		       } else {
-		            /* ignore constant background regions */
-			    ngoodpix++;
-		       }
-		    } else {
-		       /* just increment the number of non-null pixels */
-		       ngoodpix++;
-		    }
-
-		    /* shift over 1 pixel */
-		    v1 = v2;
-		    v2 = v3;
-		    v3 = v4;
-		    v4 = v5;
-	        }  /* end of loop over pixels in the row */
-
-		/* compute the 3rd order diffs */
-		/* Note that there are 4 more pixel values than there are diffs values. */
-		ngoodpix += (nvals + 4);
-
-		if (noise) {
-		    if (nvals == 0) {
-		        continue;  /* cannot compute medians on this row */
-		    } else if (nvals == 1) {
-		        diffs[nrows] = differences[0];
-		    } else {
-                        /* quick_select returns the median MUCH faster than using qsort */
-                        diffs[nrows] = quick_select_float(differences, nvals);
-		    }
-		}
-		nrows++;
-	}  /* end of loop over rows */
-
-	    /* compute median of the values for each row */
-	if (noise) {
-	    if (nrows == 0) { 
-	       xnoise = 0;
-	    } else if (nrows == 1) {
-	       xnoise = diffs[0];
-	    } else {	    
-	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
-	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
-	    }
-	}
-
-	if (ngood)  *ngood  = ngoodpix;
-	if (minval) *minval = xminval;
-	if (maxval) *maxval = xmaxval;
-	if (noise) {
-		*noise  = 0.6052697 * xnoise;
-		free(diffs);
-		free(differences);
-	}
-
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnNoise3_double
-       (double *array,       /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-        long ny,            /* number of rows in the image */
-	int nullcheck,      /* check for null values, if true */
-	double nullvalue,    /* value of null pixels, if nullcheck is true */
-   /* returned parameters */   
-	long *ngood,        /* number of good, non-null pixels? */
-	double *minval,    /* minimum non-null value */
-	double *maxval,    /* maximum non-null value */
-	double *noise,      /* returned R.M.S. value of all non-null pixels */
-	int *status)        /* error status */
-
-/*
-Estimate the median and background noise in the input image using 3rd order differences.
-
-The noise in the background of the image is calculated using the 3rd order algorithm 
-developed for deriving the signal to noise ratio in spectra
-(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)
-
-  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))
-
-The returned estimates are the median of the values that are computed for each 
-row of the image.
-*/
-{
-	long ii, jj, nrows = 0, nvals, ngoodpix = 0;
-	double *differences, *rowpix, v1, v2, v3, v4, v5;
-	double xminval = DBL_MAX, xmaxval = -DBL_MAX;
-	int do_range = 0;
-	double *diffs, xnoise = 0;
-	
-	if (nx < 5) {
-		/* treat entire array as an image with a single row */
-		nx = nx * ny;
-		ny = 1;
-	}
-
-	/* rows must have at least 5 pixels */
-	if (nx < 5) {
-
-		for (ii = 0; ii < nx; ii++) {
-		    if (nullcheck && array[ii] == nullvalue)
-		        continue;
-		    else {
-			if (array[ii] < xminval) xminval = array[ii];
-			if (array[ii] > xmaxval) xmaxval = array[ii];
-			ngoodpix++;
-		    }
-		}
-		if (minval) *minval = xminval;
-		if (maxval) *maxval = xmaxval;
-		if (ngood) *ngood = ngoodpix;
-		if (noise) *noise = 0.;
-		return(*status);
-	}
-
-	/* do we need to compute the min and max value? */
-	if (minval || maxval) do_range = 1;
-	
-        /* allocate arrays used to compute the median and noise estimates */
-	if (noise) {
-	    differences = calloc(nx, sizeof(double));
-	    if (!differences) {
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	    }
-
-	    diffs = calloc(ny, sizeof(double));
-	    if (!diffs) {
-		free(differences);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	    }
-	}
-
-	/* loop over each row of the image */
-	for (jj=0; jj < ny; jj++) {
-
-                rowpix = array + (jj * nx); /* point to first pixel in the row */
-
-		/***** find the first valid pixel in row */
-		ii = 0;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v1 = rowpix[ii];  /* store the good pixel value */
-
-		if (do_range) {
-			if (v1 < xminval) xminval = v1;
-			if (v1 > xmaxval) xmaxval = v1;
-		}
-
-		/***** find the 2nd valid pixel in row (which we will skip over) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v2 = rowpix[ii];  /* store the good pixel value */
-		
-		if (do_range) {
-			if (v2 < xminval) xminval = v2;
-			if (v2 > xmaxval) xmaxval = v2;
-		}
-
-		/***** find the 3rd valid pixel in row */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v3 = rowpix[ii];  /* store the good pixel value */
-
-		if (do_range) {
-			if (v3 < xminval) xminval = v3;
-			if (v3 > xmaxval) xmaxval = v3;
-		}
-				
-		/* find the 4nd valid pixel in row (to be skipped) */
-		ii++;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v4 = rowpix[ii];  /* store the good pixel value */
-
-		if (do_range) {
-			if (v4 < xminval) xminval = v4;
-			if (v4 > xmaxval) xmaxval = v4;
-		}
-		
-		/* now populate the differences arrays */
-		/* for the remaining pixels in the row */
-		nvals = 0;
-		for (ii++; ii < nx; ii++) {
-
-		    /* find the next valid pixel in row */
-                    if (nullcheck)
-		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
-		     
-		    if (ii == nx) break;  /* hit end of row */
-		    v5 = rowpix[ii];  /* store the good pixel value */
-
-		    if (do_range) {
-			if (v5 < xminval) xminval = v5;
-			if (v5 > xmaxval) xmaxval = v5;
-		    }
-
-		    /* construct array of 3rd order absolute differences */
-		    if (noise) {
-		        if (!(v1 == v2 && v2 == v3 && v3 == v4 && v4 == v5)) {
-
-		            differences[nvals] = fabs((2. * v3) - v1 - v5);
-		            nvals++;  
-		        } else {
-		            /* ignore constant background regions */
-			    ngoodpix++;
-		        }
-		    } else {
-		       /* just increment the number of non-null pixels */
-		       ngoodpix++;
-		    }
-
-		    /* shift over 1 pixel */
-		    v1 = v2;
-		    v2 = v3;
-		    v3 = v4;
-		    v4 = v5;
-	        }  /* end of loop over pixels in the row */
-
-		/* compute the 3rd order diffs */
-		/* Note that there are 4 more pixel values than there are diffs values. */
-		ngoodpix += (nvals + 4);
-
-		if (noise) {
-		    if (nvals == 0) {
-		        continue;  /* cannot compute medians on this row */
-		    } else if (nvals == 1) {
-		        diffs[nrows] = differences[0];
-		    } else {
-                        /* quick_select returns the median MUCH faster than using qsort */
-                        diffs[nrows] = quick_select_double(differences, nvals);
-		    }
-		}
-		nrows++;
-	}  /* end of loop over rows */
-
-	    /* compute median of the values for each row */
-	if (noise) {
-	    if (nrows == 0) { 
-	       xnoise = 0;
-	    } else if (nrows == 1) {
-	       xnoise = diffs[0];
-	    } else {	    
-	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
-	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
-	    }
-	}
-
-	if (ngood)  *ngood  = ngoodpix;
-	if (minval) *minval = xminval;
-	if (maxval) *maxval = xmaxval;
-	if (noise) {
-		*noise  = 0.6052697 * xnoise;
-		free(diffs);
-		free(differences);
-	}
-
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnNoise1_short
-       (short *array,       /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-        long ny,            /* number of rows in the image */
-	int nullcheck,      /* check for null values, if true */
-	short nullvalue,    /* value of null pixels, if nullcheck is true */
-   /* returned parameters */   
-	double *noise,      /* returned R.M.S. value of all non-null pixels */
-	int *status)        /* error status */
-/*
-Estimate the background noise in the input image using sigma of 1st order differences.
-
-  noise = 1.0 / sqrt(2) * rms of (flux[i] - flux[i-1])
-
-The returned estimate is the median of the values that are computed for each 
-row of the image.
-*/
-{
-	int iter;
-	long ii, jj, kk, nrows = 0, nvals;
-	short *differences, *rowpix, v1;
-	double  *diffs, xnoise, mean, stdev;
-
-	/* rows must have at least 3 pixels to estimate noise */
-	if (nx < 3) {
-		*noise = 0;
-		return(*status);
-	}
-	
-        /* allocate arrays used to compute the median and noise estimates */
-	differences = calloc(nx, sizeof(short));
-	if (!differences) {
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs = calloc(ny, sizeof(double));
-	if (!diffs) {
-		free(differences);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	/* loop over each row of the image */
-	for (jj=0; jj < ny; jj++) {
-
-                rowpix = array + (jj * nx); /* point to first pixel in the row */
-
-		/***** find the first valid pixel in row */
-		ii = 0;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v1 = rowpix[ii];  /* store the good pixel value */
-
-		/* now continue populating the differences arrays */
-		/* for the remaining pixels in the row */
-		nvals = 0;
-		for (ii++; ii < nx; ii++) {
-
-		    /* find the next valid pixel in row */
-                    if (nullcheck)
-		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
-		     
-		    if (ii == nx) break;  /* hit end of row */
-		
-		    /* construct array of 1st order differences */
-		    differences[nvals] = v1 - rowpix[ii];
-
-		    nvals++;  
-		    /* shift over 1 pixel */
-		    v1 = rowpix[ii];
-	        }  /* end of loop over pixels in the row */
-
-		if (nvals < 2)
-		   continue;
-		else {
-
-		    FnMeanSigma_short(differences, nvals, 0, 0, 0, &mean, &stdev, status);
-
-		    if (stdev > 0.) {
-		        for (iter = 0;  iter < NITER;  iter++) {
-		            kk = 0;
-		            for (ii = 0;  ii < nvals;  ii++) {
-		                if (fabs (differences[ii] - mean) < SIGMA_CLIP * stdev) {
-			            if (kk < ii)
-			                differences[kk] = differences[ii];
-			            kk++;
-		                }
-		            }
-		            if (kk == nvals) break;
-
-		            nvals = kk;
-		            FnMeanSigma_short(differences, nvals, 0, 0, 0, &mean, &stdev, status);
-	              }
-		   }
-
-		   diffs[nrows] = stdev;
-		   nrows++;
-		}
-	}  /* end of loop over rows */
-
-	/* compute median of the values for each row */
-	if (nrows == 0) { 
-	       xnoise = 0;
-	} else if (nrows == 1) {
-	       xnoise = diffs[0];
-	} else {
-	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
-	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
-	}
-
-	*noise = .70710678 * xnoise;
-
-	free(diffs);
-	free(differences);
-
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnNoise1_int
-       (int *array,       /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-        long ny,            /* number of rows in the image */
-	int nullcheck,      /* check for null values, if true */
-	int nullvalue,    /* value of null pixels, if nullcheck is true */
-   /* returned parameters */   
-	double *noise,      /* returned R.M.S. value of all non-null pixels */
-	int *status)        /* error status */
-/*
-Estimate the background noise in the input image using sigma of 1st order differences.
-
-  noise = 1.0 / sqrt(2) * rms of (flux[i] - flux[i-1])
-
-The returned estimate is the median of the values that are computed for each 
-row of the image.
-*/
-{
-	int iter;
-	long ii, jj, kk, nrows = 0, nvals;
-	int *differences, *rowpix, v1;
-	double  *diffs, xnoise, mean, stdev;
-
-	/* rows must have at least 3 pixels to estimate noise */
-	if (nx < 3) {
-		*noise = 0;
-		return(*status);
-	}
-	
-        /* allocate arrays used to compute the median and noise estimates */
-	differences = calloc(nx, sizeof(int));
-	if (!differences) {
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs = calloc(ny, sizeof(double));
-	if (!diffs) {
-		free(differences);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	/* loop over each row of the image */
-	for (jj=0; jj < ny; jj++) {
-
-                rowpix = array + (jj * nx); /* point to first pixel in the row */
-
-		/***** find the first valid pixel in row */
-		ii = 0;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v1 = rowpix[ii];  /* store the good pixel value */
-
-		/* now continue populating the differences arrays */
-		/* for the remaining pixels in the row */
-		nvals = 0;
-		for (ii++; ii < nx; ii++) {
-
-		    /* find the next valid pixel in row */
-                    if (nullcheck)
-		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
-		     
-		    if (ii == nx) break;  /* hit end of row */
-		
-		    /* construct array of 1st order differences */
-		    differences[nvals] = v1 - rowpix[ii];
-
-		    nvals++;  
-		    /* shift over 1 pixel */
-		    v1 = rowpix[ii];
-	        }  /* end of loop over pixels in the row */
-
-		if (nvals < 2)
-		   continue;
-		else {
-
-		    FnMeanSigma_int(differences, nvals, 0, 0, 0, &mean, &stdev, status);
-
-		    if (stdev > 0.) {
-		        for (iter = 0;  iter < NITER;  iter++) {
-		            kk = 0;
-		            for (ii = 0;  ii < nvals;  ii++) {
-		                if (fabs (differences[ii] - mean) < SIGMA_CLIP * stdev) {
-			            if (kk < ii)
-			                differences[kk] = differences[ii];
-			            kk++;
-		                }
-		            }
-		            if (kk == nvals) break;
-
-		            nvals = kk;
-		            FnMeanSigma_int(differences, nvals, 0, 0, 0, &mean, &stdev, status);
-	              }
-		   }
-
-		   diffs[nrows] = stdev;
-		   nrows++;
-		}
-	}  /* end of loop over rows */
-
-	/* compute median of the values for each row */
-	if (nrows == 0) { 
-	       xnoise = 0;
-	} else if (nrows == 1) {
-	       xnoise = diffs[0];
-	} else {
-	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
-	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
-	}
-
-	*noise = .70710678 * xnoise;
-
-	free(diffs);
-	free(differences);
-
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnNoise1_float
-       (float *array,       /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-        long ny,            /* number of rows in the image */
-	int nullcheck,      /* check for null values, if true */
-	float nullvalue,    /* value of null pixels, if nullcheck is true */
-   /* returned parameters */   
-	double *noise,      /* returned R.M.S. value of all non-null pixels */
-	int *status)        /* error status */
-/*
-Estimate the background noise in the input image using sigma of 1st order differences.
-
-  noise = 1.0 / sqrt(2) * rms of (flux[i] - flux[i-1])
-
-The returned estimate is the median of the values that are computed for each 
-row of the image.
-*/
-{
-	int iter;
-	long ii, jj, kk, nrows = 0, nvals;
-	float *differences, *rowpix, v1;
-	double  *diffs, xnoise, mean, stdev;
-
-	/* rows must have at least 3 pixels to estimate noise */
-	if (nx < 3) {
-		*noise = 0;
-		return(*status);
-	}
-	
-        /* allocate arrays used to compute the median and noise estimates */
-	differences = calloc(nx, sizeof(float));
-	if (!differences) {
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs = calloc(ny, sizeof(double));
-	if (!diffs) {
-		free(differences);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	/* loop over each row of the image */
-	for (jj=0; jj < ny; jj++) {
-
-                rowpix = array + (jj * nx); /* point to first pixel in the row */
-
-		/***** find the first valid pixel in row */
-		ii = 0;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v1 = rowpix[ii];  /* store the good pixel value */
-
-		/* now continue populating the differences arrays */
-		/* for the remaining pixels in the row */
-		nvals = 0;
-		for (ii++; ii < nx; ii++) {
-
-		    /* find the next valid pixel in row */
-                    if (nullcheck)
-		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
-		     
-		    if (ii == nx) break;  /* hit end of row */
-		
-		    /* construct array of 1st order differences */
-		    differences[nvals] = v1 - rowpix[ii];
-
-		    nvals++;  
-		    /* shift over 1 pixel */
-		    v1 = rowpix[ii];
-	        }  /* end of loop over pixels in the row */
-
-		if (nvals < 2)
-		   continue;
-		else {
-
-		    FnMeanSigma_float(differences, nvals, 0, 0, 0, &mean, &stdev, status);
-
-		    if (stdev > 0.) {
-		        for (iter = 0;  iter < NITER;  iter++) {
-		            kk = 0;
-		            for (ii = 0;  ii < nvals;  ii++) {
-		                if (fabs (differences[ii] - mean) < SIGMA_CLIP * stdev) {
-			            if (kk < ii)
-			                differences[kk] = differences[ii];
-			            kk++;
-		                }
-		            }
-		            if (kk == nvals) break;
-
-		            nvals = kk;
-		            FnMeanSigma_float(differences, nvals, 0, 0, 0, &mean, &stdev, status);
-	              }
-		   }
-
-		   diffs[nrows] = stdev;
-		   nrows++;
-		}
-	}  /* end of loop over rows */
-
-	/* compute median of the values for each row */
-	if (nrows == 0) { 
-	       xnoise = 0;
-	} else if (nrows == 1) {
-	       xnoise = diffs[0];
-	} else {
-	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
-	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
-	}
-
-	*noise = .70710678 * xnoise;
-
-	free(diffs);
-	free(differences);
-
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnNoise1_double
-       (double *array,       /*  2 dimensional array of image pixels */
-        long nx,            /* number of pixels in each row of the image */
-        long ny,            /* number of rows in the image */
-	int nullcheck,      /* check for null values, if true */
-	double nullvalue,    /* value of null pixels, if nullcheck is true */
-   /* returned parameters */   
-	double *noise,      /* returned R.M.S. value of all non-null pixels */
-	int *status)        /* error status */
-/*
-Estimate the background noise in the input image using sigma of 1st order differences.
-
-  noise = 1.0 / sqrt(2) * rms of (flux[i] - flux[i-1])
-
-The returned estimate is the median of the values that are computed for each 
-row of the image.
-*/
-{
-	int iter;
-	long ii, jj, kk, nrows = 0, nvals;
-	double *differences, *rowpix, v1;
-	double  *diffs, xnoise, mean, stdev;
-
-	/* rows must have at least 3 pixels to estimate noise */
-	if (nx < 3) {
-		*noise = 0;
-		return(*status);
-	}
-	
-        /* allocate arrays used to compute the median and noise estimates */
-	differences = calloc(nx, sizeof(double));
-	if (!differences) {
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	diffs = calloc(ny, sizeof(double));
-	if (!diffs) {
-		free(differences);
-        	*status = MEMORY_ALLOCATION;
-		return(*status);
-	}
-
-	/* loop over each row of the image */
-	for (jj=0; jj < ny; jj++) {
-
-                rowpix = array + (jj * nx); /* point to first pixel in the row */
-
-		/***** find the first valid pixel in row */
-		ii = 0;
-		if (nullcheck)
-		    while (ii < nx && rowpix[ii] == nullvalue) ii++;
-
-		if (ii == nx) continue;  /* hit end of row */
-		v1 = rowpix[ii];  /* store the good pixel value */
-
-		/* now continue populating the differences arrays */
-		/* for the remaining pixels in the row */
-		nvals = 0;
-		for (ii++; ii < nx; ii++) {
-
-		    /* find the next valid pixel in row */
-                    if (nullcheck)
-		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
-		     
-		    if (ii == nx) break;  /* hit end of row */
-		
-		    /* construct array of 1st order differences */
-		    differences[nvals] = v1 - rowpix[ii];
-
-		    nvals++;  
-		    /* shift over 1 pixel */
-		    v1 = rowpix[ii];
-	        }  /* end of loop over pixels in the row */
-
-		if (nvals < 2)
-		   continue;
-		else {
-
-		    FnMeanSigma_double(differences, nvals, 0, 0, 0, &mean, &stdev, status);
-
-		    if (stdev > 0.) {
-		        for (iter = 0;  iter < NITER;  iter++) {
-		            kk = 0;
-		            for (ii = 0;  ii < nvals;  ii++) {
-		                if (fabs (differences[ii] - mean) < SIGMA_CLIP * stdev) {
-			            if (kk < ii)
-			                differences[kk] = differences[ii];
-			            kk++;
-		                }
-		            }
-		            if (kk == nvals) break;
-
-		            nvals = kk;
-		            FnMeanSigma_double(differences, nvals, 0, 0, 0, &mean, &stdev, status);
-	              }
-		   }
-
-		   diffs[nrows] = stdev;
-		   nrows++;
-		}
-	}  /* end of loop over rows */
-
-	/* compute median of the values for each row */
-	if (nrows == 0) { 
-	       xnoise = 0;
-	} else if (nrows == 1) {
-	       xnoise = diffs[0];
-	} else {
-	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
-	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
-	}
-
-	*noise = .70710678 * xnoise;
-
-	free(diffs);
-	free(differences);
-
-	return(*status);
-}
-/*--------------------------------------------------------------------------*/
-static int FnCompare_short(const void *v1, const void *v2)
-{
-   const short *i1 = v1;
-   const short *i2 = v2;
-   
-   if (*i1 < *i2)
-     return(-1);
-   else if (*i1 > *i2)
-     return(1);
-   else
-     return(0);
-}
-/*--------------------------------------------------------------------------*/
-static int FnCompare_int(const void *v1, const void *v2)
-{
-   const int *i1 = v1;
-   const int *i2 = v2;
-   
-   if (*i1 < *i2)
-     return(-1);
-   else if (*i1 > *i2)
-     return(1);
-   else
-     return(0);
-}
-/*--------------------------------------------------------------------------*/
-static int FnCompare_float(const void *v1, const void *v2)
-{
-   const float *i1 = v1;
-   const float *i2 = v2;
-   
-   if (*i1 < *i2)
-     return(-1);
-   else if (*i1 > *i2)
-     return(1);
-   else
-     return(0);
-}
-/*--------------------------------------------------------------------------*/
-static int FnCompare_double(const void *v1, const void *v2)
-{
-   const double *i1 = v1;
-   const double *i2 = v2;
-   
-   if (*i1 < *i2)
-     return(-1);
-   else if (*i1 > *i2)
-     return(1);
-   else
-     return(0);
-}
-/*--------------------------------------------------------------------------*/
-
-/*
- *  These Quickselect routines are based on the algorithm described in
- *  "Numerical recipes in C", Second Edition,
- *  Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5
- *  This code by Nicolas Devillard - 1998. Public domain.
- */
-
-/*--------------------------------------------------------------------------*/
-
-#define ELEM_SWAP(a,b) { register float t=(a);(a)=(b);(b)=t; }
-
-static float quick_select_float(float arr[], int n) 
-{
-    int low, high ;
-    int median;
-    int middle, ll, hh;
-
-    low = 0 ; high = n-1 ; median = (low + high) / 2;
-    for (;;) {
-        if (high <= low) /* One element only */
-            return arr[median] ;
-
-        if (high == low + 1) {  /* Two elements only */
-            if (arr[low] > arr[high])
-                ELEM_SWAP(arr[low], arr[high]) ;
-            return arr[median] ;
-        }
-
-    /* Find median of low, middle and high items; swap into position low */
-    middle = (low + high) / 2;
-    if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]) ;
-    if (arr[low] > arr[high])       ELEM_SWAP(arr[low], arr[high]) ;
-    if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;
-
-    /* Swap low item (now in position middle) into position (low+1) */
-    ELEM_SWAP(arr[middle], arr[low+1]) ;
-
-    /* Nibble from each end towards middle, swapping items when stuck */
-    ll = low + 1;
-    hh = high;
-    for (;;) {
-        do ll++; while (arr[low] > arr[ll]) ;
-        do hh--; while (arr[hh]  > arr[low]) ;
-
-        if (hh < ll)
-        break;
-
-        ELEM_SWAP(arr[ll], arr[hh]) ;
-    }
-
-    /* Swap middle item (in position low) back into correct position */
-    ELEM_SWAP(arr[low], arr[hh]) ;
-
-    /* Re-set active partition */
-    if (hh <= median)
-        low = ll;
-        if (hh >= median)
-        high = hh - 1;
-    }
-}
-
-#undef ELEM_SWAP
-
-/*--------------------------------------------------------------------------*/
-
-#define ELEM_SWAP(a,b) { register short t=(a);(a)=(b);(b)=t; }
-
-static short quick_select_short(short arr[], int n) 
-{
-    int low, high ;
-    int median;
-    int middle, ll, hh;
-
-    low = 0 ; high = n-1 ; median = (low + high) / 2;
-    for (;;) {
-        if (high <= low) /* One element only */
-            return arr[median] ;
-
-        if (high == low + 1) {  /* Two elements only */
-            if (arr[low] > arr[high])
-                ELEM_SWAP(arr[low], arr[high]) ;
-            return arr[median] ;
-        }
-
-    /* Find median of low, middle and high items; swap into position low */
-    middle = (low + high) / 2;
-    if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]) ;
-    if (arr[low] > arr[high])       ELEM_SWAP(arr[low], arr[high]) ;
-    if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;
-
-    /* Swap low item (now in position middle) into position (low+1) */
-    ELEM_SWAP(arr[middle], arr[low+1]) ;
-
-    /* Nibble from each end towards middle, swapping items when stuck */
-    ll = low + 1;
-    hh = high;
-    for (;;) {
-        do ll++; while (arr[low] > arr[ll]) ;
-        do hh--; while (arr[hh]  > arr[low]) ;
-
-        if (hh < ll)
-        break;
-
-        ELEM_SWAP(arr[ll], arr[hh]) ;
-    }
-
-    /* Swap middle item (in position low) back into correct position */
-    ELEM_SWAP(arr[low], arr[hh]) ;
-
-    /* Re-set active partition */
-    if (hh <= median)
-        low = ll;
-        if (hh >= median)
-        high = hh - 1;
-    }
-}
-
-#undef ELEM_SWAP
-
-/*--------------------------------------------------------------------------*/
-
-#define ELEM_SWAP(a,b) { register int t=(a);(a)=(b);(b)=t; }
-
-static int quick_select_int(int arr[], int n) 
-{
-    int low, high ;
-    int median;
-    int middle, ll, hh;
-
-    low = 0 ; high = n-1 ; median = (low + high) / 2;
-    for (;;) {
-        if (high <= low) /* One element only */
-            return arr[median] ;
-
-        if (high == low + 1) {  /* Two elements only */
-            if (arr[low] > arr[high])
-                ELEM_SWAP(arr[low], arr[high]) ;
-            return arr[median] ;
-        }
-
-    /* Find median of low, middle and high items; swap into position low */
-    middle = (low + high) / 2;
-    if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]) ;
-    if (arr[low] > arr[high])       ELEM_SWAP(arr[low], arr[high]) ;
-    if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;
-
-    /* Swap low item (now in position middle) into position (low+1) */
-    ELEM_SWAP(arr[middle], arr[low+1]) ;
-
-    /* Nibble from each end towards middle, swapping items when stuck */
-    ll = low + 1;
-    hh = high;
-    for (;;) {
-        do ll++; while (arr[low] > arr[ll]) ;
-        do hh--; while (arr[hh]  > arr[low]) ;
-
-        if (hh < ll)
-        break;
-
-        ELEM_SWAP(arr[ll], arr[hh]) ;
-    }
-
-    /* Swap middle item (in position low) back into correct position */
-    ELEM_SWAP(arr[low], arr[hh]) ;
-
-    /* Re-set active partition */
-    if (hh <= median)
-        low = ll;
-        if (hh >= median)
-        high = hh - 1;
-    }
-}
-
-#undef ELEM_SWAP
-
-/*--------------------------------------------------------------------------*/
-
-#define ELEM_SWAP(a,b) { register LONGLONG  t=(a);(a)=(b);(b)=t; }
-
-static LONGLONG quick_select_longlong(LONGLONG arr[], int n) 
-{
-    int low, high ;
-    int median;
-    int middle, ll, hh;
-
-    low = 0 ; high = n-1 ; median = (low + high) / 2;
-    for (;;) {
-        if (high <= low) /* One element only */
-            return arr[median] ;
-
-        if (high == low + 1) {  /* Two elements only */
-            if (arr[low] > arr[high])
-                ELEM_SWAP(arr[low], arr[high]) ;
-            return arr[median] ;
-        }
-
-    /* Find median of low, middle and high items; swap into position low */
-    middle = (low + high) / 2;
-    if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]) ;
-    if (arr[low] > arr[high])       ELEM_SWAP(arr[low], arr[high]) ;
-    if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;
-
-    /* Swap low item (now in position middle) into position (low+1) */
-    ELEM_SWAP(arr[middle], arr[low+1]) ;
-
-    /* Nibble from each end towards middle, swapping items when stuck */
-    ll = low + 1;
-    hh = high;
-    for (;;) {
-        do ll++; while (arr[low] > arr[ll]) ;
-        do hh--; while (arr[hh]  > arr[low]) ;
-
-        if (hh < ll)
-        break;
-
-        ELEM_SWAP(arr[ll], arr[hh]) ;
-    }
-
-    /* Swap middle item (in position low) back into correct position */
-    ELEM_SWAP(arr[low], arr[hh]) ;
-
-    /* Re-set active partition */
-    if (hh <= median)
-        low = ll;
-        if (hh >= median)
-        high = hh - 1;
-    }
-}
-
-#undef ELEM_SWAP
-
-/*--------------------------------------------------------------------------*/
-
-#define ELEM_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; }
-
-static double quick_select_double(double arr[], int n) 
-{
-    int low, high ;
-    int median;
-    int middle, ll, hh;
-
-    low = 0 ; high = n-1 ; median = (low + high) / 2;
-    for (;;) {
-        if (high <= low) /* One element only */
-            return arr[median] ;
-
-        if (high == low + 1) {  /* Two elements only */
-            if (arr[low] > arr[high])
-                ELEM_SWAP(arr[low], arr[high]) ;
-            return arr[median] ;
-        }
-
-    /* Find median of low, middle and high items; swap into position low */
-    middle = (low + high) / 2;
-    if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]) ;
-    if (arr[low] > arr[high])       ELEM_SWAP(arr[low], arr[high]) ;
-    if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;
-
-    /* Swap low item (now in position middle) into position (low+1) */
-    ELEM_SWAP(arr[middle], arr[low+1]) ;
-
-    /* Nibble from each end towards middle, swapping items when stuck */
-    ll = low + 1;
-    hh = high;
-    for (;;) {
-        do ll++; while (arr[low] > arr[ll]) ;
-        do hh--; while (arr[hh]  > arr[low]) ;
-
-        if (hh < ll)
-        break;
-
-        ELEM_SWAP(arr[ll], arr[hh]) ;
-    }
-
-    /* Swap middle item (in position low) back into correct position */
-    ELEM_SWAP(arr[low], arr[hh]) ;
-
-    /* Re-set active partition */
-    if (hh <= median)
-        low = ll;
-        if (hh >= median)
-        high = hh - 1;
-    }
-}
-
-#undef ELEM_SWAP
-
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/region.c b/src/external/OpenGR/3rdparty/cfitsio/region.c
deleted file mode 100644
index 5b71dc4c2..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/region.c
+++ /dev/null
@@ -1,1764 +0,0 @@
-#include 
-#include 
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-#include "region.h"
-static int Pt_in_Poly( double x, double y, int nPts, double *Pts );
-
-/*---------------------------------------------------------------------------*/
-int fits_read_rgnfile( const char *filename,
-            WCSdata    *wcs,
-            SAORegion  **Rgn,
-            int        *status )
-/*  Read regions from either a FITS or ASCII region file and return the information     */
-/*  in the "SAORegion" structure.  If it is nonNULL, use wcs to convert the  */
-/*  region coordinates to pixels.  Return an error if region is in degrees   */
-/*  but no WCS data is provided.                                             */
-/*---------------------------------------------------------------------------*/
-{
-  fitsfile *fptr;
-  int tstatus = 0;
-
-  if( *status ) return( *status );
-
-  /* try to open as a FITS file - if that doesn't work treat as an ASCII file */
-
-  fits_write_errmark();
-  if ( ffopen(&fptr, filename, READONLY, &tstatus) ) {
-    fits_clear_errmark();
-    fits_read_ascii_region(filename, wcs, Rgn, status);
-  } else {
-    fits_read_fits_region(fptr, wcs, Rgn, status);
-  }
-
-  return(*status);
-
-}
-/*---------------------------------------------------------------------------*/
-int fits_read_ascii_region( const char *filename,
-			    WCSdata    *wcs,
-			    SAORegion  **Rgn,
-			    int        *status )
-/*  Read regions from a SAO-style region file and return the information     */
-/*  in the "SAORegion" structure.  If it is nonNULL, use wcs to convert the  */
-/*  region coordinates to pixels.  Return an error if region is in degrees   */
-/*  but no WCS data is provided.                                             */
-/*---------------------------------------------------------------------------*/
-{
-   char     *currLine;
-   char     *namePtr, *paramPtr, *currLoc;
-   char     *pX, *pY, *endp;
-   long     allocLen, lineLen, hh, mm, dd;
-   double   *coords, X, Y, x, y, ss, div, xsave= 0., ysave= 0.;
-   int      nParams, nCoords, negdec;
-   int      i, done;
-   FILE     *rgnFile;
-   coordFmt cFmt;
-   SAORegion *aRgn;
-   RgnShape *newShape, *tmpShape;
-
-   if( *status ) return( *status );
-
-   aRgn = (SAORegion *)malloc( sizeof(SAORegion) );
-   if( ! aRgn ) {
-      ffpmsg("Couldn't allocate memory to hold Region file contents.");
-      return(*status = MEMORY_ALLOCATION );
-   }
-   aRgn->nShapes    =    0;
-   aRgn->Shapes     = NULL;
-   if( wcs && wcs->exists )
-      aRgn->wcs = *wcs;
-   else
-      aRgn->wcs.exists = 0;
-
-   cFmt = pixel_fmt; /* set default format */
-
-   /*  Allocate Line Buffer  */
-
-   allocLen = 512;
-   currLine = (char *)malloc( allocLen * sizeof(char) );
-   if( !currLine ) {
-      free( aRgn );
-      ffpmsg("Couldn't allocate memory to hold Region file contents.");
-      return(*status = MEMORY_ALLOCATION );
-   }
-
-   /*  Open Region File  */
-
-   if( (rgnFile = fopen( filename, "r" ))==NULL ) {
-      sprintf(currLine,"Could not open Region file %s.",filename);
-      ffpmsg( currLine );
-      free( currLine );
-      free( aRgn );
-      return( *status = FILE_NOT_OPENED );
-   }
-   
-   /*  Read in file, line by line  */
-   /*  First, set error status in case file is empty */ 
-   *status = FILE_NOT_OPENED;
-
-   while( fgets(currLine,allocLen,rgnFile) != NULL ) {
-
-      /* reset status if we got here */
-      *status = 0;
-
-      /*  Make sure we have a full line of text  */
-
-      lineLen = strlen(currLine);
-      while( lineLen==allocLen-1 && currLine[lineLen-1]!='\n' ) {
-         currLoc = (char *)realloc( currLine, 2 * allocLen * sizeof(char) );
-         if( !currLoc ) {
-            ffpmsg("Couldn't allocate memory to hold Region file contents.");
-            *status = MEMORY_ALLOCATION;
-            goto error;
-         } else {
-            currLine = currLoc;
-         }
-         fgets( currLine+lineLen, allocLen+1, rgnFile );
-         allocLen += allocLen;
-         lineLen  += strlen(currLine+lineLen);
-      }
-
-      currLoc = currLine;
-      if( *currLoc == '#' ) {
-
-         /*  Look to see if it is followed by a format statement...  */
-         /*  if not skip line                                        */
-
-         currLoc++;
-         while( isspace(*currLoc) ) currLoc++;
-         if( !fits_strncasecmp( currLoc, "format:", 7 ) ) {
-            if( aRgn->nShapes ) {
-               ffpmsg("Format code encountered after reading 1 or more shapes.");
-               *status = PARSE_SYNTAX_ERR;
-               goto error;
-            }
-            currLoc += 7;
-            while( isspace(*currLoc) ) currLoc++;
-            if( !fits_strncasecmp( currLoc, "pixel", 5 ) ) {
-               cFmt = pixel_fmt;
-            } else if( !fits_strncasecmp( currLoc, "degree", 6 ) ) {
-               cFmt = degree_fmt;
-            } else if( !fits_strncasecmp( currLoc, "hhmmss", 6 ) ) {
-               cFmt = hhmmss_fmt;
-            } else if( !fits_strncasecmp( currLoc, "hms", 3 ) ) {
-               cFmt = hhmmss_fmt;
-            } else {
-               ffpmsg("Unknown format code encountered in region file.");
-               *status = PARSE_SYNTAX_ERR;
-               goto error;
-            }
-         }
-
-      } else if( !fits_strncasecmp( currLoc, "glob", 4 ) ) {
-		  /* skip lines that begin with the word 'global' */
-
-      } else {
-
-         while( *currLoc != '\0' ) {
-
-            namePtr  = currLoc;
-            paramPtr = NULL;
-            nParams  = 1;
-
-            /*  Search for closing parenthesis  */
-
-            done = 0;
-            while( !done && !*status && *currLoc ) {
-               switch (*currLoc) {
-               case '(':
-                  *currLoc = '\0';
-                  currLoc++;
-                  if( paramPtr )   /* Can't have two '(' in a region! */
-                     *status = 1;
-                  else
-                     paramPtr = currLoc;
-                  break;
-               case ')':
-                  *currLoc = '\0';
-                  currLoc++;
-                  if( !paramPtr )  /* Can't have a ')' without a '(' first */
-                     *status = 1;
-                  else
-                     done = 1;
-                  break;
-               case '#':
-               case '\n':
-                  *currLoc = '\0';
-                  if( !paramPtr )  /* Allow for a blank line */
-                     done = 1;
-                  break;
-               case ':':  
-                  currLoc++;
-                  if ( paramPtr ) cFmt = hhmmss_fmt; /* set format if parameter has : */
-                  break;
-               case 'd':
-                  currLoc++;
-                  if ( paramPtr ) cFmt = degree_fmt; /* set format if parameter has d */  
-                  break;
-               case ',':
-                  nParams++;  /* Fall through to default */
-               default:
-                  currLoc++;
-                  break;
-               }
-            }
-            if( *status || !done ) {
-               ffpmsg( "Error reading Region file" );
-               *status = PARSE_SYNTAX_ERR;
-               goto error;
-            }
-
-            /*  Skip white space in region name  */
-
-            while( isspace(*namePtr) ) namePtr++;
-
-            /*  Was this a blank line? Or the end of the current one  */
-
-            if( ! *namePtr && ! paramPtr ) continue;
-
-            /*  Check for format code at beginning of the line */
-
-            if( !fits_strncasecmp( namePtr, "image;", 6 ) ) {
-				namePtr += 6;
-				cFmt = pixel_fmt;
-            } else if( !fits_strncasecmp( namePtr, "physical;", 9 ) ) {
-                                namePtr += 9;
-                                cFmt = pixel_fmt;
-            } else if( !fits_strncasecmp( namePtr, "linear;", 7 ) ) {
-                                namePtr += 7;
-                                cFmt = pixel_fmt;
-            } else if( !fits_strncasecmp( namePtr, "fk4;", 4 ) ) {
-				namePtr += 4;
-				cFmt = degree_fmt;
-            } else if( !fits_strncasecmp( namePtr, "fk5;", 4 ) ) {
-				namePtr += 4;
-				cFmt = degree_fmt;
-            } else if( !fits_strncasecmp( namePtr, "icrs;", 5 ) ) {
-				namePtr += 5;
-				cFmt = degree_fmt;
-
-            /* the following 5 cases support region files created by POW 
-	       (or ds9 Version 4.x) which
-               may have lines containing  only a format code, not followed
-               by a ';' (and with no region specifier on the line).  We use
-               the 'continue' statement to jump to the end of the loop and
-               then continue reading the next line of the region file. */
-
-            } else if( !fits_strncasecmp( namePtr, "fk5", 3 ) ) {
-				cFmt = degree_fmt;
-                                continue;  /* supports POW region file format */
-            } else if( !fits_strncasecmp( namePtr, "fk4", 3 ) ) {
-				cFmt = degree_fmt;
-                                continue;  /* supports POW region file format */
-            } else if( !fits_strncasecmp( namePtr, "icrs", 4 ) ) {
-				cFmt = degree_fmt;
-                                continue;  /* supports POW region file format */
-            } else if( !fits_strncasecmp( namePtr, "image", 5 ) ) {
-				cFmt = pixel_fmt;
-                                continue;  /* supports POW region file format */
-            } else if( !fits_strncasecmp( namePtr, "physical", 8 ) ) {
-				cFmt = pixel_fmt;
-                                continue;  /* supports POW region file format */
-
-
-            } else if( !fits_strncasecmp( namePtr, "galactic;", 9 ) ) {
-               ffpmsg( "Galactic region coordinates not supported" );
-               ffpmsg( namePtr );
-               *status = PARSE_SYNTAX_ERR;
-               goto error;
-            } else if( !fits_strncasecmp( namePtr, "ecliptic;", 9 ) ) {
-               ffpmsg( "ecliptic region coordinates not supported" );
-               ffpmsg( namePtr );
-               *status = PARSE_SYNTAX_ERR;
-               goto error;
-            }
-
-            /**************************************************/
-            /*  We've apparently found a region... Set it up  */
-            /**************************************************/
-
-            if( !(aRgn->nShapes % 10) ) {
-               if( aRgn->Shapes )
-                  tmpShape = (RgnShape *)realloc( aRgn->Shapes,
-                                                  (10+aRgn->nShapes)
-                                                  * sizeof(RgnShape) );
-               else
-                  tmpShape = (RgnShape *) malloc( 10 * sizeof(RgnShape) );
-               if( tmpShape ) {
-                  aRgn->Shapes = tmpShape;
-               } else {
-                  ffpmsg( "Failed to allocate memory for Region data");
-                  *status = MEMORY_ALLOCATION;
-                  goto error;
-               }
-
-            }
-            newShape        = &aRgn->Shapes[aRgn->nShapes++];
-            newShape->sign  = 1;
-            newShape->shape = point_rgn;
-	    for (i=0; i<8; i++) newShape->param.gen.p[i] = 0.0;
-	    newShape->param.gen.a = 0.0;
-	    newShape->param.gen.b = 0.0;
-	    newShape->param.gen.sinT = 0.0;
-	    newShape->param.gen.cosT = 0.0;
-
-            while( isspace(*namePtr) ) namePtr++;
-            
-			/*  Check for the shape's sign  */
-
-            if( *namePtr=='+' ) {
-               namePtr++;
-            } else if( *namePtr=='-' ) {
-               namePtr++;
-               newShape->sign = 0;
-            }
-
-            /* Skip white space in region name */
-
-            while( isspace(*namePtr) ) namePtr++;
-            if( *namePtr=='\0' ) {
-               ffpmsg( "Error reading Region file" );
-               *status = PARSE_SYNTAX_ERR;
-               goto error;
-            }
-            lineLen = strlen( namePtr ) - 1;
-            while( isspace(namePtr[lineLen]) ) namePtr[lineLen--] = '\0';
-
-            /*  Now identify the region  */
-
-            if(        !fits_strcasecmp( namePtr, "circle"  ) ) {
-               newShape->shape = circle_rgn;
-               if( nParams != 3 )
-                  *status = PARSE_SYNTAX_ERR;
-               nCoords = 2;
-            } else if( !fits_strcasecmp( namePtr, "annulus" ) ) {
-               newShape->shape = annulus_rgn;
-               if( nParams != 4 )
-                  *status = PARSE_SYNTAX_ERR;
-               nCoords = 2;
-            } else if( !fits_strcasecmp( namePtr, "ellipse" ) ) {
-               if( nParams < 4 || nParams > 8 ) {
-                  *status = PARSE_SYNTAX_ERR;
-	       } else if ( nParams < 6 ) {
-		 newShape->shape = ellipse_rgn;
-		 newShape->param.gen.p[4] = 0.0;
-	       } else {
-		 newShape->shape = elliptannulus_rgn;
-		 newShape->param.gen.p[6] = 0.0;
-		 newShape->param.gen.p[7] = 0.0;
-	       }
-               nCoords = 2;
-            } else if( !fits_strcasecmp( namePtr, "elliptannulus" ) ) {
-               newShape->shape = elliptannulus_rgn;
-               if( !( nParams==8 || nParams==6 ) )
-                  *status = PARSE_SYNTAX_ERR;
-               newShape->param.gen.p[6] = 0.0;
-               newShape->param.gen.p[7] = 0.0;
-               nCoords = 2;
-            } else if( !fits_strcasecmp( namePtr, "box"    ) 
-                    || !fits_strcasecmp( namePtr, "rotbox" ) ) {
-	       if( nParams < 4 || nParams > 8 ) {
-		 *status = PARSE_SYNTAX_ERR;
-	       } else if ( nParams < 6 ) {
-		 newShape->shape = box_rgn;
-		 newShape->param.gen.p[4] = 0.0;
-	       } else {
-		  newShape->shape = boxannulus_rgn;
-		  newShape->param.gen.p[6] = 0.0;
-		  newShape->param.gen.p[7] = 0.0;
-	       }
-	       nCoords = 2;
-            } else if( !fits_strcasecmp( namePtr, "rectangle"    )
-                    || !fits_strcasecmp( namePtr, "rotrectangle" ) ) {
-               newShape->shape = rectangle_rgn;
-               if( nParams < 4 || nParams > 5 )
-                  *status = PARSE_SYNTAX_ERR;
-               newShape->param.gen.p[4] = 0.0;
-               nCoords = 4;
-            } else if( !fits_strcasecmp( namePtr, "diamond"    )
-                    || !fits_strcasecmp( namePtr, "rotdiamond" )
-                    || !fits_strcasecmp( namePtr, "rhombus"    )
-                    || !fits_strcasecmp( namePtr, "rotrhombus" ) ) {
-               newShape->shape = diamond_rgn;
-               if( nParams < 4 || nParams > 5 )
-                  *status = PARSE_SYNTAX_ERR;
-               newShape->param.gen.p[4] = 0.0;
-               nCoords = 2;
-            } else if( !fits_strcasecmp( namePtr, "sector"  )
-                    || !fits_strcasecmp( namePtr, "pie"     ) ) {
-               newShape->shape = sector_rgn;
-               if( nParams != 4 )
-                  *status = PARSE_SYNTAX_ERR;
-               nCoords = 2;
-            } else if( !fits_strcasecmp( namePtr, "point"   ) ) {
-               newShape->shape = point_rgn;
-               if( nParams != 2 )
-                  *status = PARSE_SYNTAX_ERR;
-               nCoords = 2;
-            } else if( !fits_strcasecmp( namePtr, "line"    ) ) {
-               newShape->shape = line_rgn;
-               if( nParams != 4 )
-                  *status = PARSE_SYNTAX_ERR;
-               nCoords = 4;
-            } else if( !fits_strcasecmp( namePtr, "polygon" ) ) {
-               newShape->shape = poly_rgn;
-               if( nParams < 6 || (nParams&1) )
-                  *status = PARSE_SYNTAX_ERR;
-               nCoords = nParams;
-            } else if( !fits_strcasecmp( namePtr, "panda" ) ) {
-               newShape->shape = panda_rgn;
-               if( nParams != 8 )
-                  *status = PARSE_SYNTAX_ERR;
-               nCoords = 2;
-            } else if( !fits_strcasecmp( namePtr, "epanda" ) ) {
-               newShape->shape = epanda_rgn;
-               if( nParams < 10 || nParams > 11 )
-                  *status = PARSE_SYNTAX_ERR;
-               newShape->param.gen.p[10] = 0.0;
-               nCoords = 2;
-            } else if( !fits_strcasecmp( namePtr, "bpanda" ) ) {
-               newShape->shape = bpanda_rgn;
-               if( nParams < 10 || nParams > 11 )
-                  *status = PARSE_SYNTAX_ERR;
-               newShape->param.gen.p[10] = 0.0;
-               nCoords = 2;
-            } else {
-               ffpmsg( "Unrecognized region found in region file:" );
-               ffpmsg( namePtr );
-               *status = PARSE_SYNTAX_ERR;
-               goto error;
-            }
-            if( *status ) {
-               ffpmsg( "Wrong number of parameters found for region" );
-               ffpmsg( namePtr );
-               goto error;
-            }
-
-            /*  Parse Parameter string... convert to pixels if necessary  */
-
-            if( newShape->shape==poly_rgn ) {
-               newShape->param.poly.Pts = (double *)malloc( nParams
-                                                            * sizeof(double) );
-               if( !newShape->param.poly.Pts ) {
-                  ffpmsg(
-                      "Could not allocate memory to hold polygon parameters" );
-                  *status = MEMORY_ALLOCATION;
-                  goto error;
-               }
-               newShape->param.poly.nPts = nParams;
-               coords = newShape->param.poly.Pts;
-            } else
-               coords = newShape->param.gen.p;
-
-            /*  Parse the initial "WCS?" coordinates  */
-            for( i=0; iexists ) {
-                     ffpmsg("WCS information needed to convert region coordinates.");
-                     *status = NO_WCS_KEY;
-                     goto error;
-                  }
-                  
-                  if( ffxypx(  X,  Y, wcs->xrefval, wcs->yrefval,
-                                      wcs->xrefpix, wcs->yrefpix,
-                                      wcs->xinc,    wcs->yinc,
-                                      wcs->rot,     wcs->type,
-                              &x, &y, status ) ) {
-                     ffpmsg("Error converting region to pixel coordinates.");
-                     goto error;
-                  }
-                  X = x; Y = y;
-               }
-               coords[i]   = X;
-               coords[i+1] = Y;
-
-            }
-
-            /*  Read in remaining parameters...  */
-
-            for( ; ixrefval, wcs->yrefval,
-			       wcs->xrefpix, wcs->yrefpix,
-			       wcs->xinc,    wcs->yinc,
-			       wcs->rot,     wcs->type,
-                               &x, &y, status ) ) {
-		     ffpmsg("Error converting region to pixel coordinates.");
-		     goto error;
-		  }
-		 
-		  coords[i] = sqrt( pow(x-coords[0],2) + pow(y-coords[1],2) );
-
-               }
-            }
-
-	    /* special case for elliptannulus and boxannulus if only one angle
-	       was given */
-
-	    if ( (newShape->shape == elliptannulus_rgn || 
-		  newShape->shape == boxannulus_rgn ) && nParams == 7 ) {
-	      coords[7] = coords[6];
-	    }
-
-            /* Also, correct the position angle for any WCS rotation:  */
-            /*    If regions are specified in WCS coordintes, then the angles */
-            /*    are relative to the WCS system, not the pixel X,Y system */
-
-	    if( cFmt!=pixel_fmt ) {	    
-	      switch( newShape->shape ) {
-	      case sector_rgn:
-	      case panda_rgn:
-		coords[2] += (wcs->rot);
-		coords[3] += (wcs->rot);
-		break;
-	      case box_rgn:
-	      case rectangle_rgn:
-	      case diamond_rgn:
-	      case ellipse_rgn:
-		coords[4] += (wcs->rot);
-		break;
-	      case boxannulus_rgn:
-	      case elliptannulus_rgn:
-		coords[6] += (wcs->rot);
-		coords[7] += (wcs->rot);
-		break;
-	      case epanda_rgn:
-	      case bpanda_rgn:
-		coords[2] += (wcs->rot);
-		coords[3] += (wcs->rot);
-		coords[10] += (wcs->rot);
-              default:
-                break;
-	      }
-	    }
-
-	    /* do some precalculations to speed up tests */
-
-	    fits_setup_shape(newShape);
-
-         }  /* End of while( *currLoc ) */
-/*
-  if (coords)printf("%.8f %.8f %.8f %.8f %.8f\n",
-   coords[0],coords[1],coords[2],coords[3],coords[4]); 
-*/
-      }  /* End of if...else parse line */
-   }   /* End of while( fgets(rgnFile) ) */
-
-   /* set up component numbers */
-
-   fits_set_region_components( aRgn );
-
-error:
-
-   if( *status ) {
-      fits_free_region( aRgn );
-   } else {
-      *Rgn = aRgn;
-   }
-
-   fclose( rgnFile );
-   free( currLine );
-
-   return( *status );
-}
-
-/*---------------------------------------------------------------------------*/
-int fits_in_region( double    X,
-            double    Y,
-            SAORegion *Rgn )
-/*  Test if the given point is within the region described by Rgn.  X and    */
-/*  Y are in pixel coordinates.                                              */
-/*---------------------------------------------------------------------------*/
-{
-   double x, y, dx, dy, xprime, yprime, r, th;
-   RgnShape *Shapes;
-   int i, cur_comp;
-   int result, comp_result;
-
-   Shapes = Rgn->Shapes;
-
-   result = 0;
-   comp_result = 0;
-   cur_comp = Rgn->Shapes[0].comp;
-
-   for( i=0; inShapes; i++, Shapes++ ) {
-
-     /* if this region has a different component number to the last one  */
-     /*	then replace the accumulated selection logical with the union of */
-     /*	the current logical and the total logical. Reinitialize the      */
-     /* temporary logical.                                               */
-
-     if ( i==0 || Shapes->comp != cur_comp ) {
-       result = result || comp_result;
-       cur_comp = Shapes->comp;
-       /* if an excluded region is given first, then implicitly   */
-       /* assume a previous shape that includes the entire image. */
-       comp_result = !Shapes->sign;
-     }
-
-    /* only need to test if  */
-    /*   the point is not already included and this is an include region, */
-    /* or the point is included and this is an excluded region */
-
-    if ( (!comp_result && Shapes->sign) || (comp_result && !Shapes->sign) ) { 
-
-      comp_result = 1;
-
-      switch( Shapes->shape ) {
-
-      case box_rgn:
-         /*  Shift origin to center of region  */
-         xprime = X - Shapes->param.gen.p[0];
-         yprime = Y - Shapes->param.gen.p[1];
-
-         /*  Rotate point to region's orientation  */
-         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
-         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;
-
-         dx = 0.5 * Shapes->param.gen.p[2];
-         dy = 0.5 * Shapes->param.gen.p[3];
-         if( (x < -dx) || (x > dx) || (y < -dy) || (y > dy) )
-            comp_result = 0;
-         break;
-
-      case boxannulus_rgn:
-         /*  Shift origin to center of region  */
-         xprime = X - Shapes->param.gen.p[0];
-         yprime = Y - Shapes->param.gen.p[1];
-
-         /*  Rotate point to region's orientation  */
-         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
-         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;
-
-         dx = 0.5 * Shapes->param.gen.p[4];
-         dy = 0.5 * Shapes->param.gen.p[5];
-         if( (x < -dx) || (x > dx) || (y < -dy) || (y > dy) ) {
-	   comp_result = 0;
-	 } else {
-	   /* Repeat test for inner box */
-	   x =  xprime * Shapes->param.gen.b + yprime * Shapes->param.gen.a;
-	   y = -xprime * Shapes->param.gen.a + yprime * Shapes->param.gen.b;
-	   
-	   dx = 0.5 * Shapes->param.gen.p[2];
-	   dy = 0.5 * Shapes->param.gen.p[3];
-	   if( (x >= -dx) && (x <= dx) && (y >= -dy) && (y <= dy) )
-	     comp_result = 0;
-	 }
-         break;
-
-      case rectangle_rgn:
-         /*  Shift origin to center of region  */
-         xprime = X - Shapes->param.gen.p[5];
-         yprime = Y - Shapes->param.gen.p[6];
-
-         /*  Rotate point to region's orientation  */
-         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
-         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;
-
-         dx = Shapes->param.gen.a;
-         dy = Shapes->param.gen.b;
-         if( (x < -dx) || (x > dx) || (y < -dy) || (y > dy) )
-            comp_result = 0;
-         break;
-
-      case diamond_rgn:
-         /*  Shift origin to center of region  */
-         xprime = X - Shapes->param.gen.p[0];
-         yprime = Y - Shapes->param.gen.p[1];
-
-         /*  Rotate point to region's orientation  */
-         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
-         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;
-
-         dx = 0.5 * Shapes->param.gen.p[2];
-         dy = 0.5 * Shapes->param.gen.p[3];
-         r  = fabs(x/dx) + fabs(y/dy);
-         if( r > 1 )
-            comp_result = 0;
-         break;
-
-      case circle_rgn:
-         /*  Shift origin to center of region  */
-         x = X - Shapes->param.gen.p[0];
-         y = Y - Shapes->param.gen.p[1];
-
-         r  = x*x + y*y;
-         if ( r > Shapes->param.gen.a )
-            comp_result = 0;
-         break;
-
-      case annulus_rgn:
-         /*  Shift origin to center of region  */
-         x = X - Shapes->param.gen.p[0];
-         y = Y - Shapes->param.gen.p[1];
-
-         r = x*x + y*y;
-         if ( r < Shapes->param.gen.a || r > Shapes->param.gen.b )
-            comp_result = 0;
-         break;
-
-      case sector_rgn:
-         /*  Shift origin to center of region  */
-         x = X - Shapes->param.gen.p[0];
-         y = Y - Shapes->param.gen.p[1];
-
-         if( x || y ) {
-            r = atan2( y, x ) * RadToDeg;
-            if( Shapes->param.gen.p[2] <= Shapes->param.gen.p[3] ) {
-               if( r < Shapes->param.gen.p[2] || r > Shapes->param.gen.p[3] )
-                  comp_result = 0;
-            } else {
-               if( r < Shapes->param.gen.p[2] && r > Shapes->param.gen.p[3] )
-                  comp_result = 0;
-            }
-         }
-         break;
-
-      case ellipse_rgn:
-         /*  Shift origin to center of region  */
-         xprime = X - Shapes->param.gen.p[0];
-         yprime = Y - Shapes->param.gen.p[1];
-
-         /*  Rotate point to region's orientation  */
-         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
-         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;
-
-         x /= Shapes->param.gen.p[2];
-         y /= Shapes->param.gen.p[3];
-         r = x*x + y*y;
-         if( r>1.0 )
-            comp_result = 0;
-         break;
-
-      case elliptannulus_rgn:
-         /*  Shift origin to center of region  */
-         xprime = X - Shapes->param.gen.p[0];
-         yprime = Y - Shapes->param.gen.p[1];
-
-         /*  Rotate point to outer ellipse's orientation  */
-         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
-         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;
-
-         x /= Shapes->param.gen.p[4];
-         y /= Shapes->param.gen.p[5];
-         r = x*x + y*y;
-         if( r>1.0 )
-            comp_result = 0;
-         else {
-            /*  Repeat test for inner ellipse  */
-            x =  xprime * Shapes->param.gen.b + yprime * Shapes->param.gen.a;
-            y = -xprime * Shapes->param.gen.a + yprime * Shapes->param.gen.b;
-
-            x /= Shapes->param.gen.p[2];
-            y /= Shapes->param.gen.p[3];
-            r = x*x + y*y;
-            if( r<1.0 )
-               comp_result = 0;
-         }
-         break;
-
-      case line_rgn:
-         /*  Shift origin to first point of line  */
-         xprime = X - Shapes->param.gen.p[0];
-         yprime = Y - Shapes->param.gen.p[1];
-
-         /*  Rotate point to line's orientation  */
-         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
-         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;
-
-         if( (y < -0.5) || (y >= 0.5) || (x < -0.5)
-             || (x >= Shapes->param.gen.a) )
-            comp_result = 0;
-         break;
-
-      case point_rgn:
-         /*  Shift origin to center of region  */
-         x = X - Shapes->param.gen.p[0];
-         y = Y - Shapes->param.gen.p[1];
-
-         if ( (x<-0.5) || (x>=0.5) || (y<-0.5) || (y>=0.5) )
-            comp_result = 0;
-         break;
-
-      case poly_rgn:
-         if( Xxmin || X>Shapes->xmax
-             || Yymin || Y>Shapes->ymax )
-            comp_result = 0;
-         else
-            comp_result = Pt_in_Poly( X, Y, Shapes->param.poly.nPts,
-                                       Shapes->param.poly.Pts );
-         break;
-
-      case panda_rgn:
-         /*  Shift origin to center of region  */
-         x = X - Shapes->param.gen.p[0];
-         y = Y - Shapes->param.gen.p[1];
-
-         r = x*x + y*y;
-         if ( r < Shapes->param.gen.a || r > Shapes->param.gen.b ) {
-	   comp_result = 0;
-	 } else {
-	   if( x || y ) {
-	     th = atan2( y, x ) * RadToDeg;
-	     if( Shapes->param.gen.p[2] <= Shapes->param.gen.p[3] ) {
-               if( th < Shapes->param.gen.p[2] || th > Shapes->param.gen.p[3] )
-		 comp_result = 0;
-	     } else {
-               if( th < Shapes->param.gen.p[2] && th > Shapes->param.gen.p[3] )
-		 comp_result = 0;
-	     }
-	   }
-         }
-         break;
-
-      case epanda_rgn:
-         /*  Shift origin to center of region  */
-         xprime = X - Shapes->param.gen.p[0];
-         yprime = Y - Shapes->param.gen.p[1];
-
-         /*  Rotate point to region's orientation  */
-         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
-         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;
-	 xprime = x;
-	 yprime = y;
-
-	 /* outer region test */
-         x = xprime/Shapes->param.gen.p[7];
-         y = yprime/Shapes->param.gen.p[8];
-         r = x*x + y*y;
-	 if ( r>1.0 )
-	   comp_result = 0;
-	 else {
-	   /* inner region test */
-	   x = xprime/Shapes->param.gen.p[5];
-	   y = yprime/Shapes->param.gen.p[6];
-	   r = x*x + y*y;
-	   if ( r<1.0 )
-	     comp_result = 0;
-	   else {
-	     /* angle test */
-	     if( xprime || yprime ) {
-	       th = atan2( yprime, xprime ) * RadToDeg;
-	       if( Shapes->param.gen.p[2] <= Shapes->param.gen.p[3] ) {
-		 if( th < Shapes->param.gen.p[2] || th > Shapes->param.gen.p[3] )
-		   comp_result = 0;
-	       } else {
-		 if( th < Shapes->param.gen.p[2] && th > Shapes->param.gen.p[3] )
-		   comp_result = 0;
-	       }
-	     }
-	   }
-	 }
-         break;
-
-      case bpanda_rgn:
-         /*  Shift origin to center of region  */
-         xprime = X - Shapes->param.gen.p[0];
-         yprime = Y - Shapes->param.gen.p[1];
-
-         /*  Rotate point to region's orientation  */
-         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
-         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;
-
-	 /* outer box test */
-         dx = 0.5 * Shapes->param.gen.p[7];
-         dy = 0.5 * Shapes->param.gen.p[8];
-         if( (x < -dx) || (x > dx) || (y < -dy) || (y > dy) )
-	   comp_result = 0;
-	 else {
-	   /* inner box test */
-	   dx = 0.5 * Shapes->param.gen.p[5];
-	   dy = 0.5 * Shapes->param.gen.p[6];
-	   if( (x >= -dx) && (x <= dx) && (y >= -dy) && (y <= dy) )
-	     comp_result = 0;
-	   else {
-	     /* angle test */
-	     if( x || y ) {
-	       th = atan2( y, x ) * RadToDeg;
-	       if( Shapes->param.gen.p[2] <= Shapes->param.gen.p[3] ) {
-		 if( th < Shapes->param.gen.p[2] || th > Shapes->param.gen.p[3] )
-		   comp_result = 0;
-	       } else {
-		 if( th < Shapes->param.gen.p[2] && th > Shapes->param.gen.p[3] )
-		   comp_result = 0;
-	       }
-	     }
-	   }
-	 }
-         break;
-      }
-
-      if( !Shapes->sign ) comp_result = !comp_result;
-
-     } 
-
-   }
-
-   result = result || comp_result;
-   
-   return( result );
-}
-
-/*---------------------------------------------------------------------------*/
-void fits_free_region( SAORegion *Rgn )
-/*   Free up memory allocated to hold the region data.                       */
-/*---------------------------------------------------------------------------*/
-{
-   int i;
-
-   for( i=0; inShapes; i++ )
-      if( Rgn->Shapes[i].shape == poly_rgn )
-         free( Rgn->Shapes[i].param.poly.Pts );
-   if( Rgn->Shapes )
-      free( Rgn->Shapes );
-   free( Rgn );
-}
-
-/*---------------------------------------------------------------------------*/
-static int Pt_in_Poly( double x,
-                       double y,
-                       int nPts,
-                       double *Pts )
-/*  Internal routine for testing whether the coordinate x,y is within the    */
-/*  polygon region traced out by the array Pts.                              */
-/*---------------------------------------------------------------------------*/
-{
-   int i, j, flag=0;
-   double prevX, prevY;
-   double nextX, nextY;
-   double dx, dy, Dy;
-
-   nextX = Pts[nPts-2];
-   nextY = Pts[nPts-1];
-
-   for( i=0; iprevY && y>=nextY) || (yprevX && x>=nextX) )
-         continue;
-      
-      /* Check to see if x,y lies right on the segment */
-
-      if( x>=prevX || x>nextX ) {
-         dy = y - prevY;
-         Dy = nextY - prevY;
-
-         if( fabs(Dy)<1e-10 ) {
-            if( fabs(dy)<1e-10 )
-               return( 1 );
-            else
-               continue;
-         }
-
-         dx = prevX + ( (nextX-prevX)/(Dy) ) * dy - x;
-         if( dx < -1e-10 )
-            continue;
-         if( dx <  1e-10 )
-            return( 1 );
-      }
-
-      /* There is an intersection! Make sure it isn't a V point.  */
-
-      if( y != prevY ) {
-         flag = 1 - flag;
-      } else {
-         j = i+1;  /* Point to Y component */
-         do {
-            if( j>1 )
-               j -= 2;
-            else
-               j = nPts-1;
-         } while( y == Pts[j] );
-
-         if( (nextY-y)*(y-Pts[j]) > 0 )
-            flag = 1-flag;
-      }
-
-   }
-   return( flag );
-}
-/*---------------------------------------------------------------------------*/
-void fits_set_region_components ( SAORegion *aRgn )
-{
-/* 
-   Internal routine to turn a collection of regions read from an ascii file into
-   the more complex structure that is allowed by the FITS REGION extension with
-   multiple components. Regions are anded within components and ored between them
-   ie for a pixel to be selected it must be selected by at least one component
-   and to be selected by a component it must be selected by all that component's
-   shapes.
-
-   The algorithm is to replicate every exclude region after every include
-   region before it in the list. eg reg1, reg2, -reg3, reg4, -reg5 becomes
-   (reg1, -reg3, -reg5), (reg2, -reg5, -reg3), (reg4, -reg5) where the
-   parentheses designate components.
-*/
-
-  int i, j, k, icomp;
-
-/* loop round shapes */
-
-  i = 0;
-  while ( inShapes ) {
-
-    /* first do the case of an exclude region */
-
-    if ( !aRgn->Shapes[i].sign ) {
-
-      /* we need to run back through the list copying the current shape as
-	 required. start by findin the first include shape before this exclude */
-
-      j = i-1;
-      while ( j > 0 && !aRgn->Shapes[j].sign ) j--;
-
-      /* then go back one more shape */
-
-      j--;
-
-      /* and loop back through the regions */
-
-      while ( j >= 0 ) {
-
-	/* if this is an include region then insert a copy of the exclude
-	   region immediately after it */
-
-	if ( aRgn->Shapes[j].sign ) {
-
-	  aRgn->Shapes = (RgnShape *) realloc (aRgn->Shapes,(1+aRgn->nShapes)*sizeof(RgnShape));
-	  aRgn->nShapes++;
-	  for (k=aRgn->nShapes-1; k>j+1; k--) aRgn->Shapes[k] = aRgn->Shapes[k-1];
-
-	  i++;
-	  aRgn->Shapes[j+1] = aRgn->Shapes[i];
-
-	}
-
-	j--;
-
-      }
-
-    }
-
-    i++;
-
-  }
-
-  /* now set the component numbers */
-
-  icomp = 0;
-  for ( i=0; inShapes; i++ ) {
-    if ( aRgn->Shapes[i].sign ) icomp++;
-    aRgn->Shapes[i].comp = icomp;
-
-    /*
-    printf("i = %d, shape = %d, sign = %d, comp = %d\n", i, aRgn->Shapes[i].shape, aRgn->Shapes[i].sign, aRgn->Shapes[i].comp);
-    */
-
-  }
-
-  return;
-
-}
-
-/*---------------------------------------------------------------------------*/
-void fits_setup_shape ( RgnShape *newShape)
-{
-/* Perform some useful calculations now to speed up filter later             */
-
-  double X, Y, R;
-  double *coords;
-  int i;
-
-  if ( newShape->shape == poly_rgn ) {
-    coords = newShape->param.poly.Pts;
-  } else {
-    coords = newShape->param.gen.p;
-  }
-
-  switch( newShape->shape ) {
-  case circle_rgn:
-    newShape->param.gen.a = coords[2] * coords[2];
-    break;
-  case annulus_rgn:
-    newShape->param.gen.a = coords[2] * coords[2];
-    newShape->param.gen.b = coords[3] * coords[3];
-    break;
-  case sector_rgn:
-    while( coords[2]> 180.0 ) coords[2] -= 360.0;
-    while( coords[2]<=-180.0 ) coords[2] += 360.0;
-    while( coords[3]> 180.0 ) coords[3] -= 360.0;
-    while( coords[3]<=-180.0 ) coords[3] += 360.0;
-    break;
-  case ellipse_rgn:
-    newShape->param.gen.sinT = sin( myPI * (coords[4] / 180.0) );
-    newShape->param.gen.cosT = cos( myPI * (coords[4] / 180.0) );
-    break;
-  case elliptannulus_rgn:
-    newShape->param.gen.a    = sin( myPI * (coords[6] / 180.0) );
-    newShape->param.gen.b    = cos( myPI * (coords[6] / 180.0) );
-    newShape->param.gen.sinT = sin( myPI * (coords[7] / 180.0) );
-    newShape->param.gen.cosT = cos( myPI * (coords[7] / 180.0) );
-    break;
-  case box_rgn:
-    newShape->param.gen.sinT = sin( myPI * (coords[4] / 180.0) );
-    newShape->param.gen.cosT = cos( myPI * (coords[4] / 180.0) );
-    break;
-  case boxannulus_rgn:
-    newShape->param.gen.a    = sin( myPI * (coords[6] / 180.0) );
-    newShape->param.gen.b    = cos( myPI * (coords[6] / 180.0) );
-    newShape->param.gen.sinT = sin( myPI * (coords[7] / 180.0) );
-    newShape->param.gen.cosT = cos( myPI * (coords[7] / 180.0) );
-    break;
-  case rectangle_rgn:
-    newShape->param.gen.sinT = sin( myPI * (coords[4] / 180.0) );
-    newShape->param.gen.cosT = cos( myPI * (coords[4] / 180.0) );
-    X = 0.5 * ( coords[2]-coords[0] );
-    Y = 0.5 * ( coords[3]-coords[1] );
-    newShape->param.gen.a = fabs( X * newShape->param.gen.cosT
-				  + Y * newShape->param.gen.sinT );
-    newShape->param.gen.b = fabs( Y * newShape->param.gen.cosT
-				  - X * newShape->param.gen.sinT );
-    newShape->param.gen.p[5] = 0.5 * ( coords[2]+coords[0] );
-    newShape->param.gen.p[6] = 0.5 * ( coords[3]+coords[1] );
-    break;
-  case diamond_rgn:
-    newShape->param.gen.sinT = sin( myPI * (coords[4] / 180.0) );
-    newShape->param.gen.cosT = cos( myPI * (coords[4] / 180.0) );
-    break;
-  case line_rgn:
-    X = coords[2] - coords[0];
-    Y = coords[3] - coords[1];
-    R = sqrt( X*X + Y*Y );
-    newShape->param.gen.sinT = ( R ? Y/R : 0.0 );
-    newShape->param.gen.cosT = ( R ? X/R : 1.0 );
-    newShape->param.gen.a    = R + 0.5;
-    break;
-  case panda_rgn:
-    while( coords[2]> 180.0 ) coords[2] -= 360.0;
-    while( coords[2]<=-180.0 ) coords[2] += 360.0;
-    while( coords[3]> 180.0 ) coords[3] -= 360.0;
-    while( coords[3]<=-180.0 ) coords[3] += 360.0;
-    newShape->param.gen.a = newShape->param.gen.p[5]*newShape->param.gen.p[5];
-    newShape->param.gen.b = newShape->param.gen.p[6]*newShape->param.gen.p[6];
-    break;
-  case epanda_rgn:
-  case bpanda_rgn:
-    while( coords[2]> 180.0 ) coords[2] -= 360.0;
-    while( coords[2]<=-180.0 ) coords[2] += 360.0;
-    while( coords[3]> 180.0 ) coords[3] -= 360.0;
-    while( coords[3]<=-180.0 ) coords[3] += 360.0;
-    newShape->param.gen.sinT = sin( myPI * (coords[10] / 180.0) );
-    newShape->param.gen.cosT = cos( myPI * (coords[10] / 180.0) );
-    break;
-  default:
-    break;
-  }
-
-  /*  Set the xmin, xmax, ymin, ymax elements of the RgnShape structure */
-
-  /* For everything which has first two parameters as center position just */
-  /* find a circle that encompasses the region and use it to set the       */
-  /* bounding box                                                          */
-
-  R = -1.0;
-
-  switch ( newShape->shape ) {
-
-  case circle_rgn:
-    R = coords[2];
-    break;
-
-  case annulus_rgn:
-    R = coords[3];
-    break;
-
-  case ellipse_rgn:
-    if ( coords[2] > coords[3] ) {
-      R = coords[2];
-    } else {
-      R = coords[3];
-    }
-    break;
-
-  case elliptannulus_rgn:
-    if ( coords[4] > coords[5] ) {
-      R = coords[4];
-    } else {
-      R = coords[5];
-    }
-    break;
-
-  case box_rgn:
-    R = sqrt(coords[2]*coords[2]+
-	     coords[3]*coords[3])/2.0;
-    break;
-
-  case boxannulus_rgn:
-    R = sqrt(coords[4]*coords[5]+
-	     coords[4]*coords[5])/2.0;
-    break;
-
-  case diamond_rgn:
-    if ( coords[2] > coords[3] ) {
-      R = coords[2]/2.0;
-    } else {
-      R = coords[3]/2.0;
-    }
-    break;
-    
-  case point_rgn:
-    R = 1.0;
-    break;
-
-  case panda_rgn:
-    R = coords[6];
-    break;
-
-  case epanda_rgn:
-    if ( coords[7] > coords[8] ) {
-      R = coords[7];
-    } else {
-      R = coords[8];
-    }
-    break;
-
-  case bpanda_rgn:
-    R = sqrt(coords[7]*coords[8]+
-	     coords[7]*coords[8])/2.0;
-    break;
-
-  default:
-    break;
-  }
-
-  if ( R > 0.0 ) {
-
-    newShape->xmin = coords[0] - R;
-    newShape->xmax = coords[0] + R;
-    newShape->ymin = coords[1] - R;
-    newShape->ymax = coords[1] + R;
-
-    return;
-
-  }
-
-  /* Now do the rest of the shapes that require individual methods */
-
-  switch ( newShape->shape ) {
-
-  case rectangle_rgn:
-    R = sqrt((coords[5]-coords[0])*(coords[5]-coords[0])+
-	     (coords[6]-coords[1])*(coords[6]-coords[1]));
-    newShape->xmin = coords[5] - R;
-    newShape->xmax = coords[5] + R;
-    newShape->ymin = coords[6] - R;
-    newShape->ymax = coords[6] + R;
-    break;
-
-  case poly_rgn:
-    newShape->xmin = coords[0];
-    newShape->xmax = coords[0];
-    newShape->ymin = coords[1];
-    newShape->ymax = coords[1];
-    for( i=2; i < newShape->param.poly.nPts; ) {
-      if( newShape->xmin > coords[i] ) /* Min X */
-	newShape->xmin = coords[i];
-      if( newShape->xmax < coords[i] ) /* Max X */
-	newShape->xmax = coords[i];
-      i++;
-      if( newShape->ymin > coords[i] ) /* Min Y */
-	newShape->ymin = coords[i];
-      if( newShape->ymax < coords[i] ) /* Max Y */
-	newShape->ymax = coords[i];
-      i++;
-    }
-    break;
-
-  case line_rgn:
-    if ( coords[0] > coords[2] ) {
-      newShape->xmin = coords[2];
-      newShape->xmax = coords[0];
-    } else {
-      newShape->xmin = coords[0];
-      newShape->xmax = coords[2];
-    }
-    if ( coords[1] > coords[3] ) {
-      newShape->ymin = coords[3];
-      newShape->ymax = coords[1];
-    } else {
-      newShape->ymin = coords[1];
-      newShape->ymax = coords[3];
-    }
-
-    break;
-
-    /* sector doesn't have min and max so indicate by setting max < min */
-
-  case sector_rgn:
-    newShape->xmin = 1.0;
-    newShape->xmax = -1.0;
-    newShape->ymin = 1.0;
-    newShape->ymax = -1.0;
-    break;
-
-  default:
-    break;
-  }
-
-  return;
-
-}
-
-/*---------------------------------------------------------------------------*/
-int fits_read_fits_region ( fitsfile *fptr, 
-			    WCSdata *wcs, 
-			    SAORegion **Rgn, 
-			    int *status)
-/*  Read regions from a FITS region extension and return the information     */
-/*  in the "SAORegion" structure.  If it is nonNULL, use wcs to convert the  */
-/*  region coordinates to pixels.  Return an error if region is in degrees   */
-/*  but no WCS data is provided.                                             */
-/*---------------------------------------------------------------------------*/
-{
-
-  int i, j, icol[6], idum, anynul, npos;
-  int dotransform, got_component = 1, tstatus;
-  long icsize[6];
-  double X, Y, Theta, Xsave = 0, Ysave = 0, Xpos, Ypos;
-  double *coords;
-  char *cvalue, *cvalue2;
-  char comment[FLEN_COMMENT];
-  char colname[6][FLEN_VALUE] = {"X", "Y", "SHAPE", "R", "ROTANG", "COMPONENT"};
-  char shapename[17][FLEN_VALUE] = {"POINT","CIRCLE","ELLIPSE","ANNULUS",
-				    "ELLIPTANNULUS","BOX","ROTBOX","BOXANNULUS",
-				    "RECTANGLE","ROTRECTANGLE","POLYGON","PIE",
-				    "SECTOR","DIAMOND","RHOMBUS","ROTDIAMOND",
-				    "ROTRHOMBUS"};
-  int shapetype[17] = {point_rgn, circle_rgn, ellipse_rgn, annulus_rgn, 
-		       elliptannulus_rgn, box_rgn, box_rgn, boxannulus_rgn, 
-		       rectangle_rgn, rectangle_rgn, poly_rgn, sector_rgn, 
-		       sector_rgn, diamond_rgn, diamond_rgn, diamond_rgn, 
-		       diamond_rgn};
-  SAORegion *aRgn;
-  RgnShape *newShape;
-  WCSdata *regwcs = 0;
-
-  if ( *status ) return( *status );
-
-  aRgn = (SAORegion *)malloc( sizeof(SAORegion) );
-  if( ! aRgn ) {
-    ffpmsg("Couldn't allocate memory to hold Region file contents.");
-    return(*status = MEMORY_ALLOCATION );
-  }
-  aRgn->nShapes    =    0;
-  aRgn->Shapes     = NULL;
-  if( wcs && wcs->exists )
-    aRgn->wcs = *wcs;
-  else
-    aRgn->wcs.exists = 0;
-
-  /* See if we are already positioned to a region extension, else */
-  /* move to the REGION extension (file is already open). */
-
-  tstatus = 0;
-  for (i=0; i<5; i++) {
-    ffgcno(fptr, CASEINSEN, colname[i], &icol[i], &tstatus);
-  }
-
-  if (tstatus) {
-    /* couldn't find the required columns, so search for "REGION" extension */
-    if ( ffmnhd(fptr, BINARY_TBL, "REGION", 1, status) ) {
-      ffpmsg("Could not move to REGION extension.");
-      goto error;
-    }
-  }
-
-  /* get the number of shapes and allocate memory */
-
-  if ( ffgky(fptr, TINT, "NAXIS2", &aRgn->nShapes, comment, status) ) {
-    ffpmsg("Could not read NAXIS2 keyword.");
-    goto error;
-  }
-
-  aRgn->Shapes = (RgnShape *) malloc(aRgn->nShapes * sizeof(RgnShape));
-  if ( !aRgn->Shapes ) {
-    ffpmsg( "Failed to allocate memory for Region data");
-    *status = MEMORY_ALLOCATION;
-    goto error;
-  }
-
-  /* get the required column numbers */
-
-  for (i=0; i<5; i++) {
-    if ( ffgcno(fptr, CASEINSEN, colname[i], &icol[i], status) ) {
-      ffpmsg("Could not find column.");
-      goto error;
-    }
-  }
-
-  /* try to get the optional column numbers */
-
-  if ( ffgcno(fptr, CASEINSEN, colname[5], &icol[5], status) ) {
-       got_component = 0;
-  }
-
-  /* if there was input WCS then read the WCS info for the region in case they */
-  /* are different and we have to transform */
-
-  dotransform = 0;
-  if ( aRgn->wcs.exists ) {
-    regwcs = (WCSdata *) malloc ( sizeof(WCSdata) );
-    if ( !regwcs ) {
-      ffpmsg( "Failed to allocate memory for Region WCS data");
-      *status = MEMORY_ALLOCATION;
-      goto error;
-    }
-
-    regwcs->exists = 1;
-    if ( ffgtcs(fptr, icol[0], icol[1], ®wcs->xrefval,  ®wcs->yrefval,
-		®wcs->xrefpix, ®wcs->yrefpix, ®wcs->xinc, ®wcs->yinc,
-		®wcs->rot, regwcs->type, status) ) {
-      regwcs->exists = 0;
-      *status = 0;
-    }
-
-    if ( regwcs->exists && wcs->exists ) {
-      if ( fabs(regwcs->xrefval-wcs->xrefval) > 1.0e-6 ||
-	   fabs(regwcs->yrefval-wcs->yrefval) > 1.0e-6 ||
-	   fabs(regwcs->xrefpix-wcs->xrefpix) > 1.0e-6 ||
-	   fabs(regwcs->yrefpix-wcs->yrefpix) > 1.0e-6 ||
-	   fabs(regwcs->xinc-wcs->xinc) > 1.0e-6 ||
-	   fabs(regwcs->yinc-wcs->yinc) > 1.0e-6 ||
-	   fabs(regwcs->rot-wcs->rot) > 1.0e-6 ||
-	   !strcmp(regwcs->type,wcs->type) ) dotransform = 1;
-    }
-  }
-
-  /* get the sizes of the X, Y, R, and ROTANG vectors */
-
-  for (i=0; i<6; i++) {
-    if ( ffgtdm(fptr, icol[i], 1, &idum, &icsize[i], status) ) {
-      ffpmsg("Could not find vector size of column.");
-      goto error;
-    }
-  }
-
-  cvalue = (char *) malloc ((FLEN_VALUE+1)*sizeof(char));
-
-  /* loop over the shapes - note 1-based counting for rows in FITS files */
-
-  for (i=1; i<=aRgn->nShapes; i++) {
-
-    newShape = &aRgn->Shapes[i-1];
-    for (j=0; j<8; j++) newShape->param.gen.p[j] = 0.0;
-    newShape->param.gen.a = 0.0;
-    newShape->param.gen.b = 0.0;
-    newShape->param.gen.sinT = 0.0;
-    newShape->param.gen.cosT = 0.0;
-
-    /* get the shape */
-
-    if ( ffgcvs(fptr, icol[2], i, 1, 1, " ", &cvalue, &anynul, status) ) {
-      ffpmsg("Could not read shape.");
-      goto error;
-    }
-
-    /* set include or exclude */
-
-    newShape->sign = 1;
-    cvalue2 = cvalue;
-    if ( !strncmp(cvalue,"!",1) ) {
-      newShape->sign = 0;
-      cvalue2++;
-    }
-
-    /* set the shape type */
-
-    for (j=0; j<9; j++) {
-      if ( !strcmp(cvalue2, shapename[j]) ) newShape->shape = shapetype[j];
-    }
-
-    /* allocate memory for polygon case and set coords pointer */
-
-    if ( newShape->shape == poly_rgn ) {
-      newShape->param.poly.Pts = (double *) calloc (2*icsize[0], sizeof(double));
-      if ( !newShape->param.poly.Pts ) {
-	ffpmsg("Could not allocate memory to hold polygon parameters" );
-	*status = MEMORY_ALLOCATION;
-	goto error;
-      }
-      newShape->param.poly.nPts = 2*icsize[0];
-      coords = newShape->param.poly.Pts;
-    } else {
-      coords = newShape->param.gen.p;
-    }
-
-
-  /* read X and Y. Polygon and Rectangle require special cases */
-
-    npos = 1;
-    if ( newShape->shape == poly_rgn ) npos = newShape->param.poly.nPts/2;
-    if ( newShape->shape == rectangle_rgn ) npos = 2;
-
-    for (j=0; jparam.poly.nPts = npos * 2;
-	break;
-      }
-      coords++;
-      
-      if ( ffgcvd(fptr, icol[1], i, j+1, 1, DOUBLENULLVALUE, coords, &anynul, status) ) {
-	ffpmsg("Failed to read Y column for polygon region");
-	goto error;
-      }
-      if (*coords == DOUBLENULLVALUE) { /* check for null value end of array marker */
-        npos = j;
-	newShape->param.poly.nPts = npos * 2;
-        coords--;
-	break;
-      }
-      coords++;
- 
-      if (j == 0) {  /* save the first X and Y coordinate */
-        Xsave = *(coords - 2);
-	Ysave = *(coords - 1);
-      } else if ((Xsave == *(coords - 2)) && (Ysave == *(coords - 1)) ) {
-        /* if point has same coordinate as first point, this marks the end of the array */
-        npos = j + 1;
-	newShape->param.poly.nPts = npos * 2;
-	break;
-      }
-    }
-
-    /* transform positions if the region and input wcs differ */
-
-    if ( dotransform ) {
-
-      coords -= npos*2;
-      Xsave = coords[0];
-      Ysave = coords[1];
-      for (j=0; jxrefval, regwcs->yrefval, regwcs->xrefpix,
-	       regwcs->yrefpix, regwcs->xinc, regwcs->yinc, regwcs->rot,
-	       regwcs->type, &Xpos, &Ypos, status);
-	ffxypx(Xpos, Ypos, wcs->xrefval, wcs->yrefval, wcs->xrefpix,
-	       wcs->yrefpix, wcs->xinc, wcs->yinc, wcs->rot,
-	       wcs->type, &coords[2*j], &coords[2*j+1], status);
-	if ( *status ) {
-	  ffpmsg("Failed to transform coordinates");
-	  goto error;
-	}
-      }
-      coords += npos*2;
-    }
-
-  /* read R. Circle requires one number; Box, Diamond, Ellipse, Annulus, Sector 
-     and Panda two; Boxannulus and Elliptannulus four; Point, Rectangle and 
-     Polygon none. */
-
-    npos = 0;
-    switch ( newShape->shape ) {
-    case circle_rgn: 
-      npos = 1;
-      break;
-    case box_rgn:
-    case diamond_rgn:
-    case ellipse_rgn:
-    case annulus_rgn:
-    case sector_rgn:
-      npos = 2;
-      break;
-    case boxannulus_rgn:
-    case elliptannulus_rgn:
-      npos = 4;
-      break;
-    default:
-      break;
-    }
-
-    if ( npos > 0 ) {
-      if ( ffgcvd(fptr, icol[3], i, 1, npos, 0.0, coords, &anynul, status) ) {
-	ffpmsg("Failed to read R column for region");
-	goto error;
-      }
-
-    /* transform lengths if the region and input wcs differ */
-
-      if ( dotransform ) {
-	for (j=0; jxrefval, regwcs->yrefval, regwcs->xrefpix,
-		 regwcs->yrefpix, regwcs->xinc, regwcs->yinc, regwcs->rot,
-		 regwcs->type, &Xpos, &Ypos, status);
-	  ffxypx(Xpos, Ypos, wcs->xrefval, wcs->yrefval, wcs->xrefpix,
-		 wcs->yrefpix, wcs->xinc, wcs->yinc, wcs->rot,
-		 wcs->type, &X, &Y, status);
-	  if ( *status ) {
-	    ffpmsg("Failed to transform coordinates");
-	    goto error;
-	  }
-	  *(coords++) = sqrt(pow(X-newShape->param.gen.p[0],2)+pow(Y-newShape->param.gen.p[1],2));
-	}
-      } else {
-	coords += npos;
-      }
-    }
-
-  /* read ROTANG. Requires two values for Boxannulus, Elliptannulus, Sector, 
-     Panda; one for Box, Diamond, Ellipse; and none for Circle, Point, Annulus, 
-     Rectangle, Polygon */
-
-    npos = 0;
-    switch ( newShape->shape ) {
-    case box_rgn:
-    case diamond_rgn:
-    case ellipse_rgn:
-      npos = 1;
-      break;
-    case boxannulus_rgn:
-    case elliptannulus_rgn:
-    case sector_rgn:
-      npos = 2;
-      break;
-    default:
-     break;
-    }
-
-    if ( npos > 0 ) {
-      if ( ffgcvd(fptr, icol[4], i, 1, npos, 0.0, coords, &anynul, status) ) {
-	ffpmsg("Failed to read ROTANG column for region");
-	goto error;
-      }
-
-    /* transform angles if the region and input wcs differ */
-
-      if ( dotransform ) {
-	Theta = (wcs->rot) - (regwcs->rot);
-	for (j=0; jcomp, &anynul, status) ) {
-        ffpmsg("Failed to read COMPONENT column for region");
-        goto error;
-      }
-    } else {
-      newShape->comp = 1;
-    }
-
-
-    /* do some precalculations to speed up tests */
-
-    fits_setup_shape(newShape);
-
-    /* end loop over shapes */
-
-  }
-
-error:
-
-   if( *status )
-      fits_free_region( aRgn );
-   else
-      *Rgn = aRgn;
-
-   ffclos(fptr, status);
-
-   return( *status );
-}
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/region.h b/src/external/OpenGR/3rdparty/cfitsio/region.h
deleted file mode 100644
index 516c4fdb1..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/region.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/***************************************************************/
-/*                   REGION STUFF                              */
-/***************************************************************/
-
-#include "fitsio.h"
-#define myPI  3.1415926535897932385
-#define RadToDeg 180.0/myPI
-
-typedef struct {
-   int    exists;
-   double xrefval, yrefval;
-   double xrefpix, yrefpix;
-   double xinc,    yinc;
-   double rot;
-   char   type[6];
-} WCSdata;
-
-typedef enum {
-   point_rgn,
-   line_rgn,
-   circle_rgn,
-   annulus_rgn,
-   ellipse_rgn,
-   elliptannulus_rgn,
-   box_rgn,
-   boxannulus_rgn,
-   rectangle_rgn,
-   diamond_rgn,
-   sector_rgn,
-   poly_rgn,
-   panda_rgn,
-   epanda_rgn,
-   bpanda_rgn
-} shapeType;
-
-typedef enum { pixel_fmt, degree_fmt, hhmmss_fmt } coordFmt;
-   
-typedef struct {
-   char      sign;        /*  Include or exclude?        */
-   shapeType shape;       /*  Shape of this region       */
-   int       comp;        /*  Component number for this region */
-
-   double xmin,xmax;       /*  bounding box    */
-   double ymin,ymax;
-
-   union {                /*  Parameters - In pixels     */
-
-      /****   Generic Shape Data   ****/
-
-      struct {
-	 double p[11];       /*  Region parameters       */
-	 double sinT, cosT;  /*  For rotated shapes      */
-	 double a, b;        /*  Extra scratch area      */
-      } gen;
-
-      /****      Polygon Data      ****/
-
-      struct {
-         int    nPts;        /*  Number of Polygon pts   */
-         double *Pts;        /*  Polygon points          */
-      } poly;
-
-   } param;
-
-} RgnShape;
-
-typedef struct {
-   int       nShapes;
-   RgnShape  *Shapes;
-   WCSdata   wcs;
-} SAORegion;
-
-/*  SAO region file routines */
-int  fits_read_rgnfile( const char *filename, WCSdata *wcs, SAORegion **Rgn, int *status );
-int  fits_in_region( double X, double Y, SAORegion *Rgn );
-void fits_free_region( SAORegion *Rgn );
-void fits_set_region_components ( SAORegion *Rgn );
-void fits_setup_shape ( RgnShape *shape);
-int fits_read_fits_region ( fitsfile *fptr, WCSdata * wcs, SAORegion **Rgn, int *status);
-int fits_read_ascii_region ( const char *filename, WCSdata * wcs, SAORegion **Rgn, int *status);
-
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/ricecomp.c b/src/external/OpenGR/3rdparty/cfitsio/ricecomp.c
deleted file mode 100644
index a474c010e..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/ricecomp.c
+++ /dev/null
@@ -1,1353 +0,0 @@
-/*
-  The following code was written by Richard White at STScI and made
-  available for use in CFITSIO in July 1999.  These routines were
-  originally contained in 2 source files: rcomp.c and rdecomp.c,
-  and the 'include' file now called ricecomp.h was originally called buffer.h.
-*/
-
-/*----------------------------------------------------------*/
-/*                                                          */
-/*    START OF SOURCE FILE ORIGINALLY CALLED rcomp.c        */
-/*                                                          */
-/*----------------------------------------------------------*/
-/* @(#) rcomp.c 1.5 99/03/01 12:40:27 */
-/* rcomp.c	Compress image line using
- *		(1) Difference of adjacent pixels
- *		(2) Rice algorithm coding
- *
- * Returns number of bytes written to code buffer or
- * -1 on failure
- */
-
-#include 
-#include 
-#include 
-
-/*
- * nonzero_count is lookup table giving number of bits in 8-bit values not including
- * leading zeros used in fits_rdecomp, fits_rdecomp_short and fits_rdecomp_byte
- */
-static const int nonzero_count[256] = {
-0, 
-1, 
-2, 2, 
-3, 3, 3, 3, 
-4, 4, 4, 4, 4, 4, 4, 4, 
-5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
-6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 
-6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 
-7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
-7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
-7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
-7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
-8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
-8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
-8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
-8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
-8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
-8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
-8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
-8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
-
-typedef unsigned char Buffer_t;
-
-typedef struct {
-	int bitbuffer;		/* bit buffer			*/
-	int bits_to_go;		/* bits to go in buffer		*/
-	Buffer_t *start;	/* start of buffer		*/
-	Buffer_t *current;	/* current position in buffer	*/
-	Buffer_t *end;		/* end of buffer		*/
-} Buffer;
-
-#define putcbuf(c,mf) 	((*(mf->current)++ = c), 0)
-
-#include "fitsio2.h"
-
-static void start_outputing_bits(Buffer *buffer);
-static int done_outputing_bits(Buffer *buffer);
-static int output_nbits(Buffer *buffer, int bits, int n);
-
-/*  only used for diagnoistics
-static int case1, case2, case3;
-int fits_get_case(int *c1, int*c2, int*c3) {
-
-  *c1 = case1;
-  *c2 = case2;
-  *c3 = case3;
-  return(0);
-}
-*/
-
-/* this routine used to be called 'rcomp'  (WDP)  */
-/*---------------------------------------------------------------------------*/
-
-int fits_rcomp(int a[],		/* input array			*/
-	  int nx,		/* number of input pixels	*/
-	  unsigned char *c,	/* output buffer		*/
-	  int clen,		/* max length of output		*/
-	  int nblock)		/* coding block size		*/
-{
-Buffer bufmem, *buffer = &bufmem;
-/* int bsize;  */
-int i, j, thisblock;
-int lastpix, nextpix, pdiff;
-int v, fs, fsmask, top, fsmax, fsbits, bbits;
-int lbitbuffer, lbits_to_go;
-unsigned int psum;
-double pixelsum, dpsum;
-unsigned int *diff;
-
-    /*
-     * Original size of each pixel (bsize, bytes) and coding block
-     * size (nblock, pixels)
-     * Could make bsize a parameter to allow more efficient
-     * compression of short & byte images.
-     */
-/*    bsize = 4;   */
-
-/*    nblock = 32; now an input parameter*/
-    /*
-     * From bsize derive:
-     * FSBITS = # bits required to store FS
-     * FSMAX = maximum value for FS
-     * BBITS = bits/pixel for direct coding
-     */
-
-/*
-    switch (bsize) {
-    case 1:
-	fsbits = 3;
-	fsmax = 6;
-	break;
-    case 2:
-	fsbits = 4;
-	fsmax = 14;
-	break;
-    case 4:
-	fsbits = 5;
-	fsmax = 25;
-	break;
-    default:
-        ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes");
-	return(-1);
-    }
-*/
-
-    /* move out of switch block, to tweak performance */
-    fsbits = 5;
-    fsmax = 25;
-
-    bbits = 1<start = c;
-    buffer->current = c;
-    buffer->end = c+clen;
-    buffer->bits_to_go = 8;
-    /*
-     * array for differences mapped to non-negative values
-     */
-    diff = (unsigned int *) malloc(nblock*sizeof(unsigned int));
-    if (diff == (unsigned int *) NULL) {
-        ffpmsg("fits_rcomp: insufficient memory");
-	return(-1);
-    }
-    /*
-     * Code in blocks of nblock pixels
-     */
-    start_outputing_bits(buffer);
-
-    /* write out first int value to the first 4 bytes of the buffer */
-    if (output_nbits(buffer, a[0], 32) == EOF) {
-        ffpmsg("rice_encode: end of buffer");
-        free(diff);
-        return(-1);
-    }
-
-    lastpix = a[0];  /* the first difference will always be zero */
-
-    thisblock = nblock;
-    for (i=0; i> 1;
-	for (fs = 0; psum>0; fs++) psum >>= 1;
-
-	/*
-	 * write the codes
-	 * fsbits ID bits used to indicate split level
-	 */
-	if (fs >= fsmax) {
-	    /* Special high entropy case when FS >= fsmax
-	     * Just write pixel difference values directly, no Rice coding at all.
-	     */
-	    if (output_nbits(buffer, fsmax+1, fsbits) == EOF) {
-                ffpmsg("rice_encode: end of buffer");
-                free(diff);
-		return(-1);
-	    }
-	    for (j=0; jbitbuffer;
-	    lbits_to_go = buffer->bits_to_go;
-	    for (j=0; j> fs;
-		/*
-		 * top is coded by top zeros + 1
-		 */
-		if (lbits_to_go >= top+1) {
-		    lbitbuffer <<= top+1;
-		    lbitbuffer |= 1;
-		    lbits_to_go -= top+1;
-		} else {
-		    lbitbuffer <<= lbits_to_go;
-		    putcbuf(lbitbuffer & 0xff,buffer);
-
-		    for (top -= lbits_to_go; top>=8; top -= 8) {
-			putcbuf(0, buffer);
-		    }
-		    lbitbuffer = 1;
-		    lbits_to_go = 7-top;
-		}
-		/*
-		 * bottom FS bits are written without coding
-		 * code is output_nbits, moved into this routine to reduce overheads
-		 * This code potentially breaks if FS>24, so I am limiting
-		 * FS to 24 by choice of FSMAX above.
-		 */
-		if (fs > 0) {
-		    lbitbuffer <<= fs;
-		    lbitbuffer |= v & fsmask;
-		    lbits_to_go -= fs;
-		    while (lbits_to_go <= 0) {
-			putcbuf((lbitbuffer>>(-lbits_to_go)) & 0xff,buffer);
-			lbits_to_go += 8;
-		    }
-		}
-	    }
-
-	    /* check if overflowed output buffer */
-	    if (buffer->current > buffer->end) {
-                 ffpmsg("rice_encode: end of buffer");
-                 free(diff);
-		 return(-1);
-	    }
-	    buffer->bitbuffer = lbitbuffer;
-	    buffer->bits_to_go = lbits_to_go;
-	}
-    }
-    done_outputing_bits(buffer);
-    free(diff);
-    /*
-     * return number of bytes used
-     */
-    return(buffer->current - buffer->start);
-}
-/*---------------------------------------------------------------------------*/
-
-int fits_rcomp_short(
-	  short a[],		/* input array			*/
-	  int nx,		/* number of input pixels	*/
-	  unsigned char *c,	/* output buffer		*/
-	  int clen,		/* max length of output		*/
-	  int nblock)		/* coding block size		*/
-{
-Buffer bufmem, *buffer = &bufmem;
-/* int bsize;  */
-int i, j, thisblock;
-
-/* 
-NOTE: in principle, the following 2 variable could be declared as 'short'
-but in fact the code runs faster (on 32-bit Linux at least) as 'int'
-*/
-int lastpix, nextpix;
-/* int pdiff; */
-short pdiff; 
-int v, fs, fsmask, top, fsmax, fsbits, bbits;
-int lbitbuffer, lbits_to_go;
-/* unsigned int psum; */
-unsigned short psum;
-double pixelsum, dpsum;
-unsigned int *diff;
-
-    /*
-     * Original size of each pixel (bsize, bytes) and coding block
-     * size (nblock, pixels)
-     * Could make bsize a parameter to allow more efficient
-     * compression of short & byte images.
-     */
-/*    bsize = 2; */
-
-/*    nblock = 32; now an input parameter */
-    /*
-     * From bsize derive:
-     * FSBITS = # bits required to store FS
-     * FSMAX = maximum value for FS
-     * BBITS = bits/pixel for direct coding
-     */
-
-/*
-    switch (bsize) {
-    case 1:
-	fsbits = 3;
-	fsmax = 6;
-	break;
-    case 2:
-	fsbits = 4;
-	fsmax = 14;
-	break;
-    case 4:
-	fsbits = 5;
-	fsmax = 25;
-	break;
-    default:
-        ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes");
-	return(-1);
-    }
-*/
-
-    /* move these out of switch block to further tweak performance */
-    fsbits = 4;
-    fsmax = 14;
-    
-    bbits = 1<start = c;
-    buffer->current = c;
-    buffer->end = c+clen;
-    buffer->bits_to_go = 8;
-    /*
-     * array for differences mapped to non-negative values
-     */
-    diff = (unsigned int *) malloc(nblock*sizeof(unsigned int));
-    if (diff == (unsigned int *) NULL) {
-        ffpmsg("fits_rcomp: insufficient memory");
-	return(-1);
-    }
-    /*
-     * Code in blocks of nblock pixels
-     */
-    start_outputing_bits(buffer);
-
-    /* write out first short value to the first 2 bytes of the buffer */
-    if (output_nbits(buffer, a[0], 16) == EOF) {
-        ffpmsg("rice_encode: end of buffer");
-        free(diff);
-        return(-1);
-    }
-
-    lastpix = a[0];  /* the first difference will always be zero */
-
-    thisblock = nblock;
-    for (i=0; i> 1; */
-	psum = ((unsigned short) dpsum ) >> 1;
-	for (fs = 0; psum>0; fs++) psum >>= 1;
-
-	/*
-	 * write the codes
-	 * fsbits ID bits used to indicate split level
-	 */
-	if (fs >= fsmax) {
-/* case3++; */
-	    /* Special high entropy case when FS >= fsmax
-	     * Just write pixel difference values directly, no Rice coding at all.
-	     */
-	    if (output_nbits(buffer, fsmax+1, fsbits) == EOF) {
-                ffpmsg("rice_encode: end of buffer");
-                free(diff);
-		return(-1);
-	    }
-	    for (j=0; jbitbuffer;
-	    lbits_to_go = buffer->bits_to_go;
-	    for (j=0; j> fs;
-		/*
-		 * top is coded by top zeros + 1
-		 */
-		if (lbits_to_go >= top+1) {
-		    lbitbuffer <<= top+1;
-		    lbitbuffer |= 1;
-		    lbits_to_go -= top+1;
-		} else {
-		    lbitbuffer <<= lbits_to_go;
-		    putcbuf(lbitbuffer & 0xff,buffer);
-		    for (top -= lbits_to_go; top>=8; top -= 8) {
-			putcbuf(0, buffer);
-		    }
-		    lbitbuffer = 1;
-		    lbits_to_go = 7-top;
-		}
-		/*
-		 * bottom FS bits are written without coding
-		 * code is output_nbits, moved into this routine to reduce overheads
-		 * This code potentially breaks if FS>24, so I am limiting
-		 * FS to 24 by choice of FSMAX above.
-		 */
-		if (fs > 0) {
-		    lbitbuffer <<= fs;
-		    lbitbuffer |= v & fsmask;
-		    lbits_to_go -= fs;
-		    while (lbits_to_go <= 0) {
-			putcbuf((lbitbuffer>>(-lbits_to_go)) & 0xff,buffer);
-			lbits_to_go += 8;
-		    }
-		}
-	    }
-	    /* check if overflowed output buffer */
-	    if (buffer->current > buffer->end) {
-                 ffpmsg("rice_encode: end of buffer");
-                 free(diff);
-		 return(-1);
-	    }
-	    buffer->bitbuffer = lbitbuffer;
-	    buffer->bits_to_go = lbits_to_go;
-	}
-    }
-    done_outputing_bits(buffer);
-    free(diff);
-    /*
-     * return number of bytes used
-     */
-    return(buffer->current - buffer->start);
-}
-/*---------------------------------------------------------------------------*/
-
-int fits_rcomp_byte(
-	  signed char a[],		/* input array			*/
-	  int nx,		/* number of input pixels	*/
-	  unsigned char *c,	/* output buffer		*/
-	  int clen,		/* max length of output		*/
-	  int nblock)		/* coding block size		*/
-{
-Buffer bufmem, *buffer = &bufmem;
-/* int bsize; */
-int i, j, thisblock;
-
-/* 
-NOTE: in principle, the following 2 variable could be declared as 'short'
-but in fact the code runs faster (on 32-bit Linux at least) as 'int'
-*/
-int lastpix, nextpix;
-/* int pdiff; */
-signed char pdiff; 
-int v, fs, fsmask, top, fsmax, fsbits, bbits;
-int lbitbuffer, lbits_to_go;
-/* unsigned int psum; */
-unsigned char psum;
-double pixelsum, dpsum;
-unsigned int *diff;
-
-    /*
-     * Original size of each pixel (bsize, bytes) and coding block
-     * size (nblock, pixels)
-     * Could make bsize a parameter to allow more efficient
-     * compression of short & byte images.
-     */
-/*    bsize = 1;  */
-
-/*    nblock = 32; now an input parameter */
-    /*
-     * From bsize derive:
-     * FSBITS = # bits required to store FS
-     * FSMAX = maximum value for FS
-     * BBITS = bits/pixel for direct coding
-     */
-
-/*
-    switch (bsize) {
-    case 1:
-	fsbits = 3;
-	fsmax = 6;
-	break;
-    case 2:
-	fsbits = 4;
-	fsmax = 14;
-	break;
-    case 4:
-	fsbits = 5;
-	fsmax = 25;
-	break;
-    default:
-        ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes");
-	return(-1);
-    }
-*/
-
-    /* move these out of switch block to further tweak performance */
-    fsbits = 3;
-    fsmax = 6;
-    bbits = 1<start = c;
-    buffer->current = c;
-    buffer->end = c+clen;
-    buffer->bits_to_go = 8;
-    /*
-     * array for differences mapped to non-negative values
-     */
-    diff = (unsigned int *) malloc(nblock*sizeof(unsigned int));
-    if (diff == (unsigned int *) NULL) {
-        ffpmsg("fits_rcomp: insufficient memory");
-	return(-1);
-    }
-    /*
-     * Code in blocks of nblock pixels
-     */
-    start_outputing_bits(buffer);
-
-    /* write out first byte value to the first  byte of the buffer */
-    if (output_nbits(buffer, a[0], 8) == EOF) {
-        ffpmsg("rice_encode: end of buffer");
-        free(diff);
-        return(-1);
-    }
-
-    lastpix = a[0];  /* the first difference will always be zero */
-
-    thisblock = nblock;
-    for (i=0; i> 1; */
-	psum = ((unsigned char) dpsum ) >> 1;
-	for (fs = 0; psum>0; fs++) psum >>= 1;
-
-	/*
-	 * write the codes
-	 * fsbits ID bits used to indicate split level
-	 */
-	if (fs >= fsmax) {
-	    /* Special high entropy case when FS >= fsmax
-	     * Just write pixel difference values directly, no Rice coding at all.
-	     */
-	    if (output_nbits(buffer, fsmax+1, fsbits) == EOF) {
-                ffpmsg("rice_encode: end of buffer");
-                free(diff);
-		return(-1);
-	    }
-	    for (j=0; jbitbuffer;
-	    lbits_to_go = buffer->bits_to_go;
-	    for (j=0; j> fs;
-		/*
-		 * top is coded by top zeros + 1
-		 */
-		if (lbits_to_go >= top+1) {
-		    lbitbuffer <<= top+1;
-		    lbitbuffer |= 1;
-		    lbits_to_go -= top+1;
-		} else {
-		    lbitbuffer <<= lbits_to_go;
-		    putcbuf(lbitbuffer & 0xff,buffer);
-		    for (top -= lbits_to_go; top>=8; top -= 8) {
-			putcbuf(0, buffer);
-		    }
-		    lbitbuffer = 1;
-		    lbits_to_go = 7-top;
-		}
-		/*
-		 * bottom FS bits are written without coding
-		 * code is output_nbits, moved into this routine to reduce overheads
-		 * This code potentially breaks if FS>24, so I am limiting
-		 * FS to 24 by choice of FSMAX above.
-		 */
-		if (fs > 0) {
-		    lbitbuffer <<= fs;
-		    lbitbuffer |= v & fsmask;
-		    lbits_to_go -= fs;
-		    while (lbits_to_go <= 0) {
-			putcbuf((lbitbuffer>>(-lbits_to_go)) & 0xff,buffer);
-			lbits_to_go += 8;
-		    }
-		}
-	    }
-	    /* check if overflowed output buffer */
-	    if (buffer->current > buffer->end) {
-                 ffpmsg("rice_encode: end of buffer");
-                 free(diff);
-		 return(-1);
-	    }
-	    buffer->bitbuffer = lbitbuffer;
-	    buffer->bits_to_go = lbits_to_go;
-	}
-    }
-    done_outputing_bits(buffer);
-    free(diff);
-    /*
-     * return number of bytes used
-     */
-    return(buffer->current - buffer->start);
-}
-/*---------------------------------------------------------------------------*/
-/* bit_output.c
- *
- * Bit output routines
- * Procedures return zero on success, EOF on end-of-buffer
- *
- * Programmer: R. White     Date: 20 July 1998
- */
-
-/* Initialize for bit output */
-
-static void start_outputing_bits(Buffer *buffer)
-{
-    /*
-     * Buffer is empty to start with
-     */
-    buffer->bitbuffer = 0;
-    buffer->bits_to_go = 8;
-}
-
-/*---------------------------------------------------------------------------*/
-/* Output N bits (N must be <= 32) */
-
-static int output_nbits(Buffer *buffer, int bits, int n)
-{
-/* local copies */
-int lbitbuffer;
-int lbits_to_go;
-    /* AND mask for the right-most n bits */
-    static unsigned int mask[33] = 
-         {0,
-	  0x1,       0x3,       0x7,       0xf,       0x1f,       0x3f,       0x7f,       0xff,
-	  0x1ff,     0x3ff,     0x7ff,     0xfff,     0x1fff,     0x3fff,     0x7fff,     0xffff,
-	  0x1ffff,   0x3ffff,   0x7ffff,   0xfffff,   0x1fffff,   0x3fffff,   0x7fffff,   0xffffff,
-	  0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};
-
-    /*
-     * insert bits at end of bitbuffer
-     */
-    lbitbuffer = buffer->bitbuffer;
-    lbits_to_go = buffer->bits_to_go;
-    if (lbits_to_go+n > 32) {
-	/*
-	 * special case for large n: put out the top lbits_to_go bits first
-	 * note that 0 < lbits_to_go <= 8
-	 */
-	lbitbuffer <<= lbits_to_go;
-/*	lbitbuffer |= (bits>>(n-lbits_to_go)) & ((1<>(n-lbits_to_go)) & *(mask+lbits_to_go);
-	putcbuf(lbitbuffer & 0xff,buffer);
-	n -= lbits_to_go;
-	lbits_to_go = 8;
-    }
-    lbitbuffer <<= n;
-/*    lbitbuffer |= ( bits & ((1<>(-lbits_to_go)) & 0xff,buffer);
-	lbits_to_go += 8;
-    }
-    buffer->bitbuffer = lbitbuffer;
-    buffer->bits_to_go = lbits_to_go;
-    return(0);
-}
-/*---------------------------------------------------------------------------*/
-/* Flush out the last bits */
-
-static int done_outputing_bits(Buffer *buffer)
-{
-    if(buffer->bits_to_go < 8) {
-	putcbuf(buffer->bitbuffer<bits_to_go,buffer);
-	
-/*	if (putcbuf(buffer->bitbuffer<bits_to_go,buffer) == EOF)
-	    return(EOF);
-*/
-    }
-    return(0);
-}
-/*---------------------------------------------------------------------------*/
-/*----------------------------------------------------------*/
-/*                                                          */
-/*    START OF SOURCE FILE ORIGINALLY CALLED rdecomp.c      */
-/*                                                          */
-/*----------------------------------------------------------*/
-
-/* @(#) rdecomp.c 1.4 99/03/01 12:38:41 */
-/* rdecomp.c	Decompress image line using
- *		(1) Difference of adjacent pixels
- *		(2) Rice algorithm coding
- *
- * Returns 0 on success or 1 on failure
- */
-
-/*    moved these 'includes' to the beginning of the file (WDP)
-#include 
-#include 
-*/
-
-/*---------------------------------------------------------------------------*/
-/* this routine used to be called 'rdecomp'  (WDP)  */
-
-int fits_rdecomp (unsigned char *c,		/* input buffer			*/
-	     int clen,			/* length of input		*/
-	     unsigned int array[],	/* output array			*/
-	     int nx,			/* number of output pixels	*/
-	     int nblock)		/* coding block size		*/
-{
-/* int bsize;  */
-int i, k, imax;
-int nbits, nzero, fs;
-unsigned char *cend, bytevalue;
-unsigned int b, diff, lastpix;
-int fsmax, fsbits, bbits;
-extern const int nonzero_count[];
-
-   /*
-     * Original size of each pixel (bsize, bytes) and coding block
-     * size (nblock, pixels)
-     * Could make bsize a parameter to allow more efficient
-     * compression of short & byte images.
-     */
-/*    bsize = 4; */
-
-/*    nblock = 32; now an input parameter */
-    /*
-     * From bsize derive:
-     * FSBITS = # bits required to store FS
-     * FSMAX = maximum value for FS
-     * BBITS = bits/pixel for direct coding
-     */
-
-/*
-    switch (bsize) {
-    case 1:
-	fsbits = 3;
-	fsmax = 6;
-	break;
-    case 2:
-	fsbits = 4;
-	fsmax = 14;
-	break;
-    case 4:
-	fsbits = 5;
-	fsmax = 25;
-	break;
-    default:
-        ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes");
-	return 1;
-    }
-*/
-
-    /* move out of switch block, to tweak performance */
-    fsbits = 5;
-    fsmax = 25;
-
-    bbits = 1<> nbits) - 1;
-
-	b &= (1< nx) imax = nx;
-	if (fs<0) {
-	    /* low-entropy case, all zero differences */
-	    for ( ; i= 0; k -= 8) {
-		    b = *c++;
-		    diff |= b<0) {
-		    b = *c++;
-		    diff |= b>>(-k);
-		    b &= (1<>1;
-		} else {
-		    diff = ~(diff>>1);
-		}
-		array[i] = diff+lastpix;
-		lastpix = array[i];
-	    }
-	} else {
-	    /* normal case, Rice coding */
-	    for ( ; i>nbits);
-		b &= (1<>1;
-		} else {
-		    diff = ~(diff>>1);
-		}
-		array[i] = diff+lastpix;
-		lastpix = array[i];
-	    }
-	}
-	if (c > cend) {
-            ffpmsg("decompression error: hit end of compressed byte stream");
-	    return 1;
-	}
-    }
-    if (c < cend) {
-        ffpmsg("decompression warning: unused bytes at end of compressed buffer");
-    }
-    return 0;
-}
-/*---------------------------------------------------------------------------*/
-/* this routine used to be called 'rdecomp'  (WDP)  */
-
-int fits_rdecomp_short (unsigned char *c,		/* input buffer			*/
-	     int clen,			/* length of input		*/
-	     unsigned short array[],  	/* output array			*/
-	     int nx,			/* number of output pixels	*/
-	     int nblock)		/* coding block size		*/
-{
-int i, imax;
-/* int bsize; */
-int k;
-int nbits, nzero, fs;
-unsigned char *cend, bytevalue;
-unsigned int b, diff, lastpix;
-int fsmax, fsbits, bbits;
-extern const int nonzero_count[];
-
-   /*
-     * Original size of each pixel (bsize, bytes) and coding block
-     * size (nblock, pixels)
-     * Could make bsize a parameter to allow more efficient
-     * compression of short & byte images.
-     */
-
-/*    bsize = 2; */
-    
-/*    nblock = 32; now an input parameter */
-    /*
-     * From bsize derive:
-     * FSBITS = # bits required to store FS
-     * FSMAX = maximum value for FS
-     * BBITS = bits/pixel for direct coding
-     */
-
-/*
-    switch (bsize) {
-    case 1:
-	fsbits = 3;
-	fsmax = 6;
-	break;
-    case 2:
-	fsbits = 4;
-	fsmax = 14;
-	break;
-    case 4:
-	fsbits = 5;
-	fsmax = 25;
-	break;
-    default:
-        ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes");
-	return 1;
-    }
-*/
-
-    /* move out of switch block, to tweak performance */
-    fsbits = 4;
-    fsmax = 14;
-
-    bbits = 1<> nbits) - 1;
-
-	b &= (1< nx) imax = nx;
-	if (fs<0) {
-	    /* low-entropy case, all zero differences */
-	    for ( ; i= 0; k -= 8) {
-		    b = *c++;
-		    diff |= b<0) {
-		    b = *c++;
-		    diff |= b>>(-k);
-		    b &= (1<>1;
-		} else {
-		    diff = ~(diff>>1);
-		}
-		array[i] = diff+lastpix;
-		lastpix = array[i];
-	    }
-	} else {
-	    /* normal case, Rice coding */
-	    for ( ; i>nbits);
-		b &= (1<>1;
-		} else {
-		    diff = ~(diff>>1);
-		}
-		array[i] = diff+lastpix;
-		lastpix = array[i];
-	    }
-	}
-	if (c > cend) {
-            ffpmsg("decompression error: hit end of compressed byte stream");
-	    return 1;
-	}
-    }
-    if (c < cend) {
-        ffpmsg("decompression warning: unused bytes at end of compressed buffer");
-    }
-    return 0;
-}
-/*---------------------------------------------------------------------------*/
-/* this routine used to be called 'rdecomp'  (WDP)  */
-
-int fits_rdecomp_byte (unsigned char *c,		/* input buffer			*/
-	     int clen,			/* length of input		*/
-	     unsigned char array[],  	/* output array			*/
-	     int nx,			/* number of output pixels	*/
-	     int nblock)		/* coding block size		*/
-{
-int i, imax;
-/* int bsize; */
-int k;
-int nbits, nzero, fs;
-unsigned char *cend;
-unsigned int b, diff, lastpix;
-int fsmax, fsbits, bbits;
-extern const int nonzero_count[];
-
-   /*
-     * Original size of each pixel (bsize, bytes) and coding block
-     * size (nblock, pixels)
-     * Could make bsize a parameter to allow more efficient
-     * compression of short & byte images.
-     */
-
-/*    bsize = 1; */
-    
-/*    nblock = 32; now an input parameter */
-    /*
-     * From bsize derive:
-     * FSBITS = # bits required to store FS
-     * FSMAX = maximum value for FS
-     * BBITS = bits/pixel for direct coding
-     */
-
-/*
-    switch (bsize) {
-    case 1:
-	fsbits = 3;
-	fsmax = 6;
-	break;
-    case 2:
-	fsbits = 4;
-	fsmax = 14;
-	break;
-    case 4:
-	fsbits = 5;
-	fsmax = 25;
-	break;
-    default:
-        ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes");
-	return 1;
-    }
-*/
-
-    /* move out of switch block, to tweak performance */
-    fsbits = 3;
-    fsmax = 6;
-
-    bbits = 1<> nbits) - 1;
-
-	b &= (1< nx) imax = nx;
-	if (fs<0) {
-	    /* low-entropy case, all zero differences */
-	    for ( ; i= 0; k -= 8) {
-		    b = *c++;
-		    diff |= b<0) {
-		    b = *c++;
-		    diff |= b>>(-k);
-		    b &= (1<>1;
-		} else {
-		    diff = ~(diff>>1);
-		}
-		array[i] = diff+lastpix;
-		lastpix = array[i];
-	    }
-	} else {
-	    /* normal case, Rice coding */
-	    for ( ; i>nbits);
-		b &= (1<>1;
-		} else {
-		    diff = ~(diff>>1);
-		}
-		array[i] = diff+lastpix;
-		lastpix = array[i];
-	    }
-	}
-	if (c > cend) {
-            ffpmsg("decompression error: hit end of compressed byte stream");
-	    return 1;
-	}
-    }
-    if (c < cend) {
-        ffpmsg("decompression warning: unused bytes at end of compressed buffer");
-    }
-    return 0;
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/sample.tpl b/src/external/OpenGR/3rdparty/cfitsio/sample.tpl
deleted file mode 100644
index 8cfca14e7..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/sample.tpl
+++ /dev/null
@@ -1,121 +0,0 @@
-# sample template - create 9 HDUs in one FITS file
-
-# syntax :
-
-# everything which starts with a hashmark is ignored
-# the same for empty lines
-
-# one can use \include filename to include other files
-# equal sign after keyword name is optional
-# \group must be terminated by \end
-# xtension is terminated by \group, xtension or EOF
-# First HDU of type image may be defined using "SIMPLE T"
-# group may contain other groups and xtensions
-# keywords may be indented, but indentation is limited to max 7chars.
-
-# template parser processes all keywords, makes substitutions
-# when necessary (hashmarks -> index), converts keyword names
-# to uppercase and writes keywords to file.
-# For string keywords, parser uses CFITSIO long string routines
-# to store string values longer than 72 characters. Parser can
-# read/process lines of any length, as long as there is enough memory.
-# For a very limited set of keywords (like NAXIS1 for binary tables)
-# template parser ignores values specified in template file
-# (one should not specify NAXIS1 for binary tables) and computes and
-# writes values respective to table structure.
-# number of rows in binary/ascii tables can be specified with NAXIS2
-
-# if the 1st HDU is not defined with "SIMPLE T" and is defined with
-# xtension image/asciitable/bintable then dummy primary HDU is
-# created by parser.
-
-simple	t
- bitpix		16
- naxis		1
- naxis1		10
-COMMENT
- comment  
- sdsdf / keyword without value (null type)
-        if line begins with 8+ spaces everything is a comment
-
-xtension image
- bitpix		16
- naxis		1
- naxis1		10
- QWERW		F / dfg dfgsd fg - boolean keyword
- FFFSDS45	3454345 /integer_or_real keyword
- SSSDFS34	32345.453   / real keyword
- adsfd34	(234234.34,2342342.3) / complex keyword - no space between ()
- SDFDF#		adfasdfasdfdfcvxccvzxcvcvcxv / autoindexed keyword, here idx=1
- SDFD#		'asf dfa dfad df dfad f ad fadfdaf dfdfa df loooooong keyyywoooord - reaaalllly verrrrrrrrrryy loooooooooong' / comment is max 80 chars
- history        history record, spaces (all but 1st) after keyname are copied
- SDFDF#		strg_value_without_spaces / autoindexed keyword, here idx=2
- comment        comment record, spaces (all but 1st) after keyname are copied
- strg45		'sdfasdfadfffdfasdfasdfasdf &'
- continue   'sdfsdfsdfsd fsdf' / 3 spaces must follow CONTINUE keyword
-
-
-xtension image
- bitpix		16
- naxis		1
- naxis1		10
-
-\group
- 
- xtension image
-  bitpix	16
-  naxis		1
-  naxis1	10
-
-# create group inside group
-
- \group
-
-# one can specify additional columns in group HDU. The first column
-# specified will have index 7 however, since the first 6 columns are occupied
-# by grouping table itself.
-# Please note, that it is not allowed to specify EXTNAME keyword as an
-# additional keyword for group HDU, since parser automatically writes
-# EXTNAME = GROUPING keyword.
-
-  TFORM#	13A
-  TTYPE#	ADDIT_COL_IN_GRP_HDU
-  TFORM#	1E
-  TTYPE#	REAL_COLUMN
-  COMMENT sure, there is always place for comments
-
-# the following specifies empty ascii table (0 cols / 0 rows)
-
-  xtension asciitable
-
- \end
- 
-\end
-
-# one do not have to specify all NAXISn keywords. If not specified
-# NAXISn equals zero.
-
-xtension image
- bitpix	16
- naxis	1
-# naxis1	10
-
-# the following tells how to set number of rows in binary table
-# note also that the last line in template file does not have to
-# have LineFeed character as the last one.
-
-xtension bintable
-naxis2	 10
-EXTNAME	asdjfhsdkf
-TTYPE#   MEMBER_XTENSION
-TFORM#   8A
-TTYPE#   MEMBER_2
-TFORM#   8U
-TTYPE#   MEMBER_3
-TFORM#   8V
-TTYPE#   MEMBER_NAME
-TFORM#   32A
-TDIM#	 '(8,4)'
-TTYPE#   MEMBER_VERSION
-TFORM#   1J
-TNULL#   0
\ No newline at end of file
diff --git a/src/external/OpenGR/3rdparty/cfitsio/scalnull.c b/src/external/OpenGR/3rdparty/cfitsio/scalnull.c
deleted file mode 100644
index d2f2924ef..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/scalnull.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*  This file, scalnull.c, contains the FITSIO routines used to define     */
-/*  the starting heap address, the value scaling and the null values.      */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-#include 
-#include "fitsio2.h"
-/*--------------------------------------------------------------------------*/
-int ffpthp(fitsfile *fptr,      /* I - FITS file pointer */
-           long theap,          /* I - starting addrss for the heap */
-           int *status)         /* IO - error status     */
-/*
-  Define the starting address for the heap for a binary table.
-  The default address is NAXIS1 * NAXIS2.  It is in units of
-  bytes relative to the beginning of the regular binary table data.
-  This routine also writes the appropriate THEAP keyword to the
-  FITS header.
-*/
-{
-    if (*status > 0 || theap < 1)
-        return(*status);
-
-    /* reset position to the correct HDU if necessary */
-    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
-        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
-
-    (fptr->Fptr)->heapstart = theap;
-
-    ffukyj(fptr, "THEAP", theap, "byte offset to heap area", status);
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpscl(fitsfile *fptr,      /* I - FITS file pointer               */
-           double scale,        /* I - scaling factor: value of BSCALE */
-           double zero,         /* I - zero point: value of BZERO      */
-           int *status)         /* IO - error status                   */
-/*
-  Define the linear scaling factor for the primary array or image extension
-  pixel values. This routine overrides the scaling values given by the
-  BSCALE and BZERO keywords if present.  Note that this routine does not
-  write or modify the BSCALE and BZERO keywords, but instead only modifies
-  the values temporarily in the internal buffer.  Thus, a subsequent call to
-  the ffrdef routine will reset the scaling back to the BSCALE and BZERO
-  keyword values (or 1. and 0. respectively if the keywords are not present).
-*/
-{
-    tcolumn *colptr;
-    int hdutype;
-
-    if (*status > 0)
-        return(*status);
-
-    if (scale == 0)
-        return(*status = ZERO_SCALE);  /* zero scale value is illegal */
-
-    if (ffghdt(fptr, &hdutype, status) > 0)  /* get HDU type */
-        return(*status);
-
-    if (hdutype != IMAGE_HDU)
-        return(*status = NOT_IMAGE);         /* not proper HDU type */
-
-    if (fits_is_compressed_image(fptr, status)) /* compressed images */
-    {
-        (fptr->Fptr)->cn_bscale = scale;
-        (fptr->Fptr)->cn_bzero  = zero;
-        return(*status);
-    }
-
-    /* set pointer to the first 'column' (contains group parameters if any) */
-    colptr = (fptr->Fptr)->tableptr; 
-
-    colptr++;   /* increment to the 2nd 'column' pointer  (the image itself) */
-
-    colptr->tscale = scale;
-    colptr->tzero = zero;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffpnul(fitsfile *fptr,      /* I - FITS file pointer                */
-           LONGLONG nulvalue,   /* I - null pixel value: value of BLANK */
-           int *status)         /* IO - error status                    */
-/*
-  Define the value used to represent undefined pixels in the primary array or
-  image extension. This only applies to integer image pixel (i.e. BITPIX > 0).
-  This routine overrides the null pixel value given by the BLANK keyword
-  if present.  Note that this routine does not write or modify the BLANK
-  keyword, but instead only modifies the value temporarily in the internal
-  buffer. Thus, a subsequent call to the ffrdef routine will reset the null
-  value back to the BLANK  keyword value (or not defined if the keyword is not
-  present).
-*/
-{
-    tcolumn *colptr;
-    int hdutype;
-
-    if (*status > 0)
-        return(*status);
-
-    if (ffghdt(fptr, &hdutype, status) > 0)  /* get HDU type */
-        return(*status);
-
-    if (hdutype != IMAGE_HDU)
-        return(*status = NOT_IMAGE);         /* not proper HDU type */
-
-    if (fits_is_compressed_image(fptr, status)) /* ignore compressed images */
-        return(*status);
-
-    /* set pointer to the first 'column' (contains group parameters if any) */
-    colptr = (fptr->Fptr)->tableptr; 
-
-    colptr++;   /* increment to the 2nd 'column' pointer  (the image itself) */
-
-    colptr->tnull = nulvalue;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fftscl(fitsfile *fptr,      /* I - FITS file pointer */
-           int colnum,          /* I - column number to apply scaling to */
-           double scale,        /* I - scaling factor: value of TSCALn   */
-           double zero,         /* I - zero point: value of TZEROn       */
-           int *status)         /* IO - error status     */
-/*
-  Define the linear scaling factor for the TABLE or BINTABLE extension
-  column values. This routine overrides the scaling values given by the
-  TSCALn and TZEROn keywords if present.  Note that this routine does not
-  write or modify the TSCALn and TZEROn keywords, but instead only modifies
-  the values temporarily in the internal buffer.  Thus, a subsequent call to
-  the ffrdef routine will reset the scaling back to the TSCALn and TZEROn
-  keyword values (or 1. and 0. respectively if the keywords are not present).
-*/
-{
-    tcolumn *colptr;
-    int hdutype;
-
-    if (*status > 0)
-        return(*status);
-
-    if (scale == 0)
-        return(*status = ZERO_SCALE);  /* zero scale value is illegal */
-
-    if (ffghdt(fptr, &hdutype, status) > 0)  /* get HDU type */
-        return(*status);
-
-    if (hdutype == IMAGE_HDU)
-        return(*status = NOT_TABLE);         /* not proper HDU type */
-
-    colptr = (fptr->Fptr)->tableptr;   /* set pointer to the first column */
-    colptr += (colnum - 1);     /* increment to the correct column */
-
-    colptr->tscale = scale;
-    colptr->tzero = zero;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int fftnul(fitsfile *fptr,      /* I - FITS file pointer                  */
-           int colnum,          /* I - column number to apply nulvalue to */
-           LONGLONG nulvalue,   /* I - null pixel value: value of TNULLn  */
-           int *status)         /* IO - error status                      */
-/*
-  Define the value used to represent undefined pixels in the BINTABLE column.
-  This only applies to integer datatype columns (TFORM = B, I, or J).
-  This routine overrides the null pixel value given by the TNULLn keyword
-  if present.  Note that this routine does not write or modify the TNULLn
-  keyword, but instead only modifies the value temporarily in the internal
-  buffer. Thus, a subsequent call to the ffrdef routine will reset the null
-  value back to the TNULLn  keyword value (or not defined if the keyword is not
-  present).
-*/
-{
-    tcolumn *colptr;
-    int hdutype;
-
-    if (*status > 0)
-        return(*status);
-
-    if (ffghdt(fptr, &hdutype, status) > 0)  /* get HDU type */
-        return(*status);
-
-    if (hdutype != BINARY_TBL)
-        return(*status = NOT_BTABLE);        /* not proper HDU type */
- 
-    colptr = (fptr->Fptr)->tableptr;   /* set pointer to the first column */
-    colptr += (colnum - 1);    /* increment to the correct column */
-
-    colptr->tnull = nulvalue;
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffsnul(fitsfile *fptr,      /* I - FITS file pointer                  */
-           int colnum,          /* I - column number to apply nulvalue to */
-           char *nulstring,     /* I - null pixel value: value of TNULLn  */
-           int *status)         /* IO - error status                      */
-/*
-  Define the string used to represent undefined pixels in the ASCII TABLE
-  column. This routine overrides the null  value given by the TNULLn keyword
-  if present.  Note that this routine does not write or modify the TNULLn
-  keyword, but instead only modifies the value temporarily in the internal
-  buffer. Thus, a subsequent call to the ffrdef routine will reset the null
-  value back to the TNULLn keyword value (or not defined if the keyword is not
-  present).
-*/
-{
-    tcolumn *colptr;
-    int hdutype;
-
-    if (*status > 0)
-        return(*status);
-
-    if (ffghdt(fptr, &hdutype, status) > 0)  /* get HDU type */
-        return(*status);
-
-    if (hdutype != ASCII_TBL)
-        return(*status = NOT_ATABLE);        /* not proper HDU type */
- 
-    colptr = (fptr->Fptr)->tableptr;   /* set pointer to the first column */
-    colptr += (colnum - 1);    /* increment to the correct column */
-
-    colptr->strnull[0] = '\0';
-    strncat(colptr->strnull, nulstring, 19);  /* limit string to 19 chars */
-
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/simplerng.c b/src/external/OpenGR/3rdparty/cfitsio/simplerng.c
deleted file mode 100644
index 91ef6f88e..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/simplerng.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/* 
-   Simple Random Number Generators
-       - getuniform - uniform deviate [0,1]
-       - getnorm    - gaussian (normal) deviate (mean=0, stddev=1)
-       - getpoisson - poisson deviate for given expected mean lambda
-
-   This code is adapted from SimpleRNG by John D Cook, which is
-   provided in the public domain.
-
-   The original C++ code is found here:
-   http://www.johndcook.com/cpp_random_number_generation.html
-
-   This code has been modified in the following ways compared to the
-   original.
-     1. convert to C from C++
-     2. keep only uniform, gaussian and poisson deviates
-     3. state variables are module static instead of class variables
-     4. provide an srand() equivalent to initialize the state
-*/
-#include 
-#include 
-
-#define PI 3.1415926535897932384626433832795
-
-/* Use the standard system rand() library routine if it provides
-   enough bits of information, since it probably has better randomness
-   than the toy algorithm in this module. */
-#if defined(RAND_MAX) && RAND_MAX > 1000000000
-#define USE_SYSTEM_RAND
-#endif
-
-int simplerng_poisson_small(double lambda);
-int simplerng_poisson_large(double lambda);
-double simplerng_getuniform_pr(unsigned int *u, unsigned int *v);
-unsigned int simplerng_getuint_pr(unsigned int *u, unsigned int *v);
-double simplerng_logfactorial(int n);
-
-/*
-  These values are not magical, just the default values Marsaglia used.
-  Any unit should work.
-*/
-static unsigned int m_u = 521288629, m_v = 362436069;
-
-/* Set u and v state variables */
-void simplerng_setstate(unsigned int u, unsigned int v)
-{
-    m_u = u;
-    m_v = v;
-}
-
-/* Retrieve u and v state variables */
-void simplerng_getstate(unsigned int *u, unsigned int *v)
-{
-    *u = m_u;
-    *v = m_v;
-}
-
-/* srand() equivalent to seed the two state variables */
-void simplerng_srand(unsigned int seed)
-{
-#ifdef USE_SYSTEM_RAND
-  srand(seed);
-#else
-  simplerng_setstate(seed ^ 521288629, seed ^ 362436069);
-#endif
-}
-
-/* Private routine to get uniform deviate */
-double simplerng_getuniform_pr(unsigned int *u, unsigned int *v)
-{
-  /* 0 <= u <= 2^32 */
-  unsigned int z = simplerng_getuint_pr(u, v);
-  /* The magic number is 1/(2^32) and so result is positive and less than 1. */
-  return z*2.328306435996595e-10;
-}
-
-/* Private routine to get unsigned integer */
-/* Marsaglia multiply-with-carry algorithm (MWC) */
-unsigned int simplerng_getuint_pr(unsigned int *u, unsigned int *v)
-{
-  *v = 36969*((*v) & 65535) + ((*v) >> 16);
-  *u = 18000*((*u) & 65535) + ((*u) >> 16);
-  return ((*v) << 16) + (*u);
-}
-
-/* Get uniform deviate [0,1] */
-double simplerng_getuniform(void)
-{
-#ifdef USE_SYSTEM_RAND
-  return rand()*(1.0 / ((double)RAND_MAX + 1));
-#else
-  return simplerng_getuniform_pr(&m_u, &m_v);
-#endif
-}
-
-/* Get unsigned integer [0, UINT_MAX] */
-unsigned int simplerng_getuint()
-{
-  /* WARNING: no option for calling rand() here.  Will need to provide
-     a scalar to make the uint in the [0,UINT_MAX] range */
-  return simplerng_getuint_pr(&m_u, &m_v);
-}
-    
-/* Get normal (Gaussian) random sample with mean=0, stddev=1 */
-double simplerng_getnorm()
-{
-  double u1, u2, r, theta;
-  static int saved = 0;
-  static double y;
-
-  /* Since you get two deviates for "free" with each calculation, save
-     one of them for later */
-
-  if (saved == 0) {
-    /* Use Box-Muller algorithm */
-    u1 = simplerng_getuniform();
-    u2 = simplerng_getuniform();
-    r = sqrt( -2.0*log(u1) );
-    theta = 2.0*PI*u2;
-    /* save second value for next call */
-    y = r*cos(theta);
-    saved = 1;
-    return r*sin(theta);
-
-  } else {
-    /* We already saved a value from the last call so use it */
-    saved = 0;
-    return y;
-  }
-}
-
-/* Poisson deviate for expected mean value lambda.
-   lambda should be in the range [0, infinity]
-   
-   For small lambda, a simple rejection method is used
-   For large lambda, an approximation is used
-*/
-int simplerng_getpoisson(double lambda)
-{
-  if (lambda < 0) lambda = 0;
-  return ((lambda < 15.0) 
-	  ? simplerng_poisson_small(lambda) 
-	  : simplerng_poisson_large(lambda));
-}
-
-int simplerng_poisson_small(double lambda)
-{
-  /* Algorithm due to Donald Knuth, 1969. */
-  double p = 1.0, L = exp(-lambda);
-  int k = 0;
-  do {
-    k++;
-    p *= simplerng_getuniform();
-  }
-  while (p > L);
-  return k - 1;
-}
-
-int simplerng_poisson_large(double lambda)
-{
-  /* "Rejection method PA" from "The Computer Generation of Poisson Random Variables" by A. C. Atkinson
-     Journal of the Royal Statistical Society Series C (Applied Statistics) Vol. 28, No. 1. (1979)
-     The article is on pages 29-35. The algorithm given here is on page 32. */
-  static double beta, alpha, k;
-  static double old_lambda = -999999.;
-
-  if (lambda != old_lambda) {
-    double c = 0.767 - 3.36/lambda;
-    beta = PI/sqrt(3.0*lambda);
-    alpha = beta*lambda;
-    k = log(c) - lambda - log(beta);
-    old_lambda = lambda;
-  }
-
-  for(;;) { /* forever */
-    double u, x, v, y, temp, lhs, rhs;
-    int n;
-
-    u = simplerng_getuniform();
-    x = (alpha - log((1.0 - u)/u))/beta;
-    n = (int) floor(x + 0.5);
-    if (n < 0) continue;
-
-    v = simplerng_getuniform();
-    y = alpha - beta*x;
-    temp = 1.0 + exp(y);
-    lhs = y + log(v/(temp*temp));
-    rhs = k + n*log(lambda) - simplerng_logfactorial(n);
-    if (lhs <= rhs) return n;
-  }
-
-}
-
-/* Lookup table for log-gamma function */
-static double lf[] = {
-            0.000000000000000,
-            0.000000000000000,
-            0.693147180559945,
-            1.791759469228055,
-            3.178053830347946,
-            4.787491742782046,
-            6.579251212010101,
-            8.525161361065415,
-            10.604602902745251,
-            12.801827480081469,
-            15.104412573075516,
-            17.502307845873887,
-            19.987214495661885,
-            22.552163853123421,
-            25.191221182738683,
-            27.899271383840894,
-            30.671860106080675,
-            33.505073450136891,
-            36.395445208033053,
-            39.339884187199495,
-            42.335616460753485,
-            45.380138898476908,
-            48.471181351835227,
-            51.606675567764377,
-            54.784729398112319,
-            58.003605222980518,
-            61.261701761002001,
-            64.557538627006323,
-            67.889743137181526,
-            71.257038967168000,
-            74.658236348830158,
-            78.092223553315307,
-            81.557959456115029,
-            85.054467017581516,
-            88.580827542197682,
-            92.136175603687079,
-            95.719694542143202,
-            99.330612454787428,
-            102.968198614513810,
-            106.631760260643450,
-            110.320639714757390,
-            114.034211781461690,
-            117.771881399745060,
-            121.533081515438640,
-            125.317271149356880,
-            129.123933639127240,
-            132.952575035616290,
-            136.802722637326350,
-            140.673923648234250,
-            144.565743946344900,
-            148.477766951773020,
-            152.409592584497350,
-            156.360836303078800,
-            160.331128216630930,
-            164.320112263195170,
-            168.327445448427650,
-            172.352797139162820,
-            176.395848406997370,
-            180.456291417543780,
-            184.533828861449510,
-            188.628173423671600,
-            192.739047287844900,
-            196.866181672889980,
-            201.009316399281570,
-            205.168199482641200,
-            209.342586752536820,
-            213.532241494563270,
-            217.736934113954250,
-            221.956441819130360,
-            226.190548323727570,
-            230.439043565776930,
-            234.701723442818260,
-            238.978389561834350,
-            243.268849002982730,
-            247.572914096186910,
-            251.890402209723190,
-            256.221135550009480,
-            260.564940971863220,
-            264.921649798552780,
-            269.291097651019810,
-            273.673124285693690,
-            278.067573440366120,
-            282.474292687630400,
-            286.893133295426990,
-            291.323950094270290,
-            295.766601350760600,
-            300.220948647014100,
-            304.686856765668720,
-            309.164193580146900,
-            313.652829949878990,
-            318.152639620209300,
-            322.663499126726210,
-            327.185287703775200,
-            331.717887196928470,
-            336.261181979198450,
-            340.815058870798960,
-            345.379407062266860,
-            349.954118040770250,
-            354.539085519440790,
-            359.134205369575340,
-            363.739375555563470,
-            368.354496072404690,
-            372.979468885689020,
-            377.614197873918670,
-            382.258588773060010,
-            386.912549123217560,
-            391.575988217329610,
-            396.248817051791490,
-            400.930948278915760,
-            405.622296161144900,
-            410.322776526937280,
-            415.032306728249580,
-            419.750805599544780,
-            424.478193418257090,
-            429.214391866651570,
-            433.959323995014870,
-            438.712914186121170,
-            443.475088120918940,
-            448.245772745384610,
-            453.024896238496130,
-            457.812387981278110,
-            462.608178526874890,
-            467.412199571608080,
-            472.224383926980520,
-            477.044665492585580,
-            481.872979229887900,
-            486.709261136839360,
-            491.553448223298010,
-            496.405478487217580,
-            501.265290891579240,
-            506.132825342034830,
-            511.008022665236070,
-            515.890824587822520,
-            520.781173716044240,
-            525.679013515995050,
-            530.584288294433580,
-            535.496943180169520,
-            540.416924105997740,
-            545.344177791154950,
-            550.278651724285620,
-            555.220294146894960,
-            560.169054037273100,
-            565.124881094874350,
-            570.087725725134190,
-            575.057539024710200,
-            580.034272767130800,
-            585.017879388839220,
-            590.008311975617860,
-            595.005524249382010,
-            600.009470555327430,
-            605.020105849423770,
-            610.037385686238740,
-            615.061266207084940,
-            620.091704128477430,
-            625.128656730891070,
-            630.172081847810200,
-            635.221937855059760,
-            640.278183660408100,
-            645.340778693435030,
-            650.409682895655240,
-            655.484856710889060,
-            660.566261075873510,
-            665.653857411105950,
-            670.747607611912710,
-            675.847474039736880,
-            680.953419513637530,
-            686.065407301994010,
-            691.183401114410800,
-            696.307365093814040,
-            701.437263808737160,
-            706.573062245787470,
-            711.714725802289990,
-            716.862220279103440,
-            722.015511873601330,
-            727.174567172815840,
-            732.339353146739310,
-            737.509837141777440,
-            742.685986874351220,
-            747.867770424643370,
-            753.055156230484160,
-            758.248113081374300,
-            763.446610112640200,
-            768.650616799717000,
-            773.860102952558460,
-            779.075038710167410,
-            784.295394535245690,
-            789.521141208958970,
-            794.752249825813460,
-            799.988691788643450,
-            805.230438803703120,
-            810.477462875863580,
-            815.729736303910160,
-            820.987231675937890,
-            826.249921864842800,
-            831.517780023906310,
-            836.790779582469900,
-            842.068894241700490,
-            847.352097970438420,
-            852.640365001133090,
-            857.933669825857460,
-            863.231987192405430,
-            868.535292100464630,
-            873.843559797865740,
-            879.156765776907600,
-            884.474885770751830,
-            889.797895749890240,
-            895.125771918679900,
-            900.458490711945270,
-            905.796028791646340,
-            911.138363043611210,
-            916.485470574328820,
-            921.837328707804890,
-            927.193914982476710,
-            932.555207148186240,
-            937.921183163208070,
-            943.291821191335660,
-            948.667099599019820,
-            954.046996952560450,
-            959.431492015349480,
-            964.820563745165940,
-            970.214191291518320,
-            975.612353993036210,
-            981.015031374908400,
-            986.422203146368590,
-            991.833849198223450,
-            997.249949600427840,
-            1002.670484599700300,
-            1008.095434617181700,
-            1013.524780246136200,
-            1018.958502249690200,
-            1024.396581558613400,
-            1029.838999269135500,
-            1035.285736640801600,
-            1040.736775094367400,
-            1046.192096209724900,
-            1051.651681723869200,
-            1057.115513528895000,
-            1062.583573670030100,
-            1068.055844343701400,
-            1073.532307895632800,
-            1079.012946818975000,
-            1084.497743752465600,
-            1089.986681478622400,
-            1095.479742921962700,
-            1100.976911147256000,
-            1106.478169357800900,
-            1111.983500893733000,
-            1117.492889230361000,
-            1123.006317976526100,
-            1128.523770872990800,
-            1134.045231790853000,
-            1139.570684729984800,
-            1145.100113817496100,
-            1150.633503306223700,
-            1156.170837573242400,
-};
-
-double simplerng_logfactorial(int n)
-{
-  if (n < 0) return 0;
-  if (n > 254) {
-    double x = n + 1;
-    return (x - 0.5)*log(x) - x + 0.5*log(2*PI) + 1.0/(12.0*x);
-  }
-  return lf[n];
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/simplerng.h b/src/external/OpenGR/3rdparty/cfitsio/simplerng.h
deleted file mode 100644
index ef4e74ee3..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/simplerng.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* 
-   Simple Random Number Generators
-       - getuniform - uniform deviate [0,1]
-       - getnorm    - gaussian (normal) deviate (mean=0, stddev=1)
-       - getpoisson - poisson deviate for given expected mean lambda
-
-   This code is adapted from SimpleRNG by John D Cook, which is
-   provided in the public domain.
-
-   The original C++ code is found here:
-   http://www.johndcook.com/cpp_random_number_generation.html
-
-   This code has been modified in the following ways compared to the
-   original.
-     1. convert to C from C++
-     2. keep only uniform, gaussian and poisson deviates
-     3. state variables are module static instead of class variables
-     4. provide an srand() equivalent to initialize the state
-*/
-
-extern void simplerng_setstate(unsigned int u, unsigned int v);
-extern void simplerng_getstate(unsigned int *u, unsigned int *v);
-extern void simplerng_srand(unsigned int seed);
-extern double simplerng_getuniform(void);
-extern double simplerng_getnorm(void);
-extern int simplerng_getpoisson(double lambda);
-extern double simplerng_logfactorial(int n);
diff --git a/src/external/OpenGR/3rdparty/cfitsio/smem.c b/src/external/OpenGR/3rdparty/cfitsio/smem.c
deleted file mode 100644
index bf8237018..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/smem.c
+++ /dev/null
@@ -1,77 +0,0 @@
-#include 
-#include 
-#include 
-#ifdef __APPLE__
-#include 
-#else
-#include 
-#endif
-#include "fitsio.h"     /* needed to define LONGLONG */
-#include "drvrsmem.h"   /* uses LONGLONG */
-
-int	main(int argc, char **argv)
-{ int cmdok, listmode, longlistmode, recovermode, deletemode, id;
-int status;
-char *address;
-
-listmode = longlistmode = recovermode = deletemode = 0;
-id = -1;
-cmdok = 1;
-
-switch (argc)
- { case 1:	listmode = 1;
-		break;
-   case 2:
-		if (0 == strcmp("-l", argv[1])) longlistmode = 1;
-		else if (0 == strcmp("-r", argv[1])) recovermode = 1;
-		else if (0 == strcmp("-d", argv[1])) deletemode = 1;
-		else cmdok = 0;
-		break;
-   case 3:
-		if (0 == strcmp("-r", argv[1])) recovermode = 1;
-		else if (0 == strcmp("-d", argv[1])) deletemode = 1;
-		else
-		 { cmdok = 0;		/* signal invalid cmd line syntax */
-		   break;
-		 }
-		if (1 != sscanf(argv[2], "%d", &id)) cmdok = 0;
-		break;
-   default:
-		cmdok = 0;
-		break;
- }
-
-if (0 == cmdok)
-  { printf("usage :\n\n");
-    printf("smem            - list all shared memory segments\n");
-    printf("\t!\tcouldn't obtain RDONLY lock - info unreliable\n");
-    printf("\tIdx\thandle of shared memory segment (visible by application)\n");
-    printf("\tKey\tcurrent system key of shared memory segment. Key\n");
-    printf("\t\tchanges whenever shmem segment is reallocated. Use\n");
-    printf("\t\tipcs (or ipcs -a) to view all shmem segments\n");
-    printf("\tNproc\tnumber of processes attached to segment\n");
-    printf("\tSize\tsize of shmem segment in bytes\n");
-    printf("\tFlags\tRESIZABLE - realloc allowed, PERSIST - segment is not\n");
-    printf("\t\tdeleted after shared_free called by last process attached\n");
-    printf("\t\tto it.\n");
-    printf("smem -d         - delete all shared memory segments (may block)\n");
-    printf("smem -d id      - delete specific shared memory segment (may block)\n");
-    printf("smem -r         - unconditionally reset all shared memory segments\n\t\t(does not block, recovers zombie handles left by kill -9)\n");
-    printf("smem -r id      - unconditionally reset specific shared memory segment\n");
-  }
-
-if (shared_init(0))
-  { printf("couldn't initialize shared memory, aborting ...\n");
-    return(10);
-  }
-
-if (listmode) shared_list(id);
-else if (recovermode) shared_recover(id);
-else if (deletemode) shared_uncond_delete(id);
-
-for (id = 0; id <16; id++) {
-  status = shared_getaddr(id, &address);
-  if (!status)printf("id, status, address %d %d %ld %.30s\n", id, status, address, address);
-}
-return(0);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/speed.c b/src/external/OpenGR/3rdparty/cfitsio/speed.c
deleted file mode 100644
index 3062d3d72..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/speed.c
+++ /dev/null
@@ -1,509 +0,0 @@
-#include 
-#include 
-#include 
-#include 
-#include 
-
-/*
-  Every program which uses the CFITSIO interface must include the
-  the fitsio.h header file.  This contains the prototypes for all
-  the routines and defines the error status values and other symbolic
-  constants used in the interface.  
-*/
-#include "fitsio.h"
-
-#define minvalue(A,B) ((A) < (B) ? (A) : (B))
-
-/* size of the image */
-#define XSIZE 3000
-#define YSIZE 3000
-
-/* size of data buffer */
-#define SHTSIZE 20000
-static long sarray[ SHTSIZE ] = {SHTSIZE * 0};
-
-/* no. of rows in binary table */
-#define BROWS 2500000
-
-/* no. of rows in ASCII table */
-#define AROWS 400000
-
-/*  CLOCKS_PER_SEC should be defined by most compilers */
-#if defined(CLOCKS_PER_SEC)
-#define CLOCKTICKS CLOCKS_PER_SEC
-#else
-/* on SUN OS machine, CLOCKS_PER_SEC is not defined, so set its value */
-#define CLOCKTICKS 1000000
-#define difftime(A,B) ((double) A - (double) B)
-#endif
-
-/* define variables for measuring elapsed time */
-clock_t scpu, ecpu;
-time_t start, finish;
-long startsec;   /* start of elapsed time interval */
-int startmilli;  /* start of elapsed time interval */
-
-int writeimage(fitsfile *fptr, int *status);
-int writebintable(fitsfile *fptr, int *status);
-int writeasctable(fitsfile *fptr, int *status);
-int readimage(fitsfile *fptr, int *status);
-int readatable(fitsfile *fptr, int *status);
-int readbtable(fitsfile *fptr, int *status);
-void printerror( int status);
-int marktime(int *status);
-int gettime(double *elapse, float *elapscpu, int *status);
-int main(void);
-
-int main()
-{
-/*************************************************************************
-    This program tests the speed of writing/reading FITS files with cfitsio
-**************************************************************************/
-
-    FILE *diskfile;
-    fitsfile *fptr;        /* pointer to the FITS file, defined in fitsio.h */
-    int status, ii;
-    long rawloop;
-    char filename[] = "speedcc.fit";           /* name for new FITS file */
-    char buffer[2880] = {2880 * 0};
-    time_t tbegin, tend;
-    float rate, size, elapcpu, cpufrac;
-    double elapse;
-
-    tbegin = time(0);
-
-    remove(filename);               /* Delete old file if it already exists */
-
-    diskfile =  fopen(filename,"w+b");
-    rawloop = XSIZE * YSIZE / 720;
-
-    printf("                                                ");
-    printf(" SIZE / ELAPSE(%%CPU) = RATE\n");
-    printf("RAW fwrite (2880 bytes/loop)...                 ");
-    marktime(&status);
-
-    for (ii = 0; ii < rawloop; ii++)
-      if (fwrite(buffer, 1, 2880, diskfile) != 2880)
-        printf("write error \n");
-
-    gettime(&elapse, &elapcpu, &status);
-
-    cpufrac = elapcpu / elapse * 100.;
-    size = 2880. * rawloop / 1000000.;
-    rate = size / elapse;
-    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);
-
-    /* read back the binary records */
-    fseek(diskfile, 0, 0);
-
-    printf("RAW fread  (2880 bytes/loop)...                 ");
-    marktime(&status);
-
-    for (ii = 0; ii < rawloop; ii++)
-      if (fread(buffer, 1, 2880, diskfile) != 2880)
-        printf("read error \n");
-
-    gettime(&elapse, &elapcpu, &status);
-
-    cpufrac = elapcpu / elapse * 100.;
-    size = 2880. * rawloop / 1000000.;
-    rate = size / elapse;
-    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);
-
-    fclose(diskfile);
-    remove(filename);
-
-    status = 0;     
-    fptr = 0;
-
-    if (fits_create_file(&fptr, filename, &status)) /* create new FITS file */
-       printerror( status);          
-   
-    if (writeimage(fptr, &status))
-       printerror( status);     
-
-    if (writebintable(fptr, &status))
-       printerror( status);     
-
-    if (writeasctable(fptr, &status))
-       printerror( status);     
-
-    if (readimage(fptr, &status))
-       printerror( status);     
-
-    if (readbtable(fptr, &status))
-       printerror( status);     
-
-    if (readatable(fptr, &status))
-       printerror( status);     
-
-    if (fits_close_file(fptr, &status))     
-         printerror( status );
-
-    tend = time(0);
-    elapse = difftime(tend, tbegin) + 0.5;
-    printf("Total elapsed time = %.3fs, status = %d\n",elapse, status);
-    return(0);
-}
-/*--------------------------------------------------------------------------*/
-int writeimage(fitsfile *fptr, int *status)
-
-    /**************************************************/
-    /* write the primary array containing a 2-D image */
-    /**************************************************/
-{
-    long  nremain, ii;
-    float rate, size, elapcpu, cpufrac;
-    double elapse;
-
-    /* initialize FITS image parameters */
-    int bitpix   =  32;   /* 32-bit  signed integer pixel values       */
-    long naxis    =   2;  /* 2-dimensional image                            */    
-    long naxes[2] = {XSIZE, YSIZE }; /* image size */
-
-    /* write the required keywords for the primary array image */
-    if ( fits_create_img(fptr, bitpix, naxis, naxes, status) )
-         printerror( *status );          
-
-    printf("\nWrite %dx%d I*4 image, %d pixels/loop:   ",XSIZE,YSIZE,SHTSIZE);
-    marktime(status);
-
-    nremain = XSIZE * YSIZE;
-    for (ii = 1; ii <= nremain; ii += SHTSIZE)
-    {
-      ffpprj(fptr, 0, ii, SHTSIZE, sarray, status);
-    }
-
-    ffflus(fptr, status);  /* flush all buffers to disk */
-
-    gettime(&elapse, &elapcpu, status);
-
-    cpufrac = elapcpu / elapse * 100.;
-    size = XSIZE * 4. * YSIZE / 1000000.;
-    rate = size / elapse;
-    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);
-
-    return( *status );
-}
-/*--------------------------------------------------------------------------*/
-int writebintable (fitsfile *fptr, int *status)
-
-    /*********************************************************/
-    /* Create a binary table extension containing 3 columns  */
-    /*********************************************************/
-{
-    int tfields = 2;
-    long nremain, ntodo, firstrow = 1, firstelem = 1, nrows;
-    float rate, size, elapcpu, cpufrac;
-    double elapse;
-
-    char extname[] = "Speed_Test";           /* extension name */
-
-    /* define the name, datatype, and physical units for the columns */
-    char *ttype[] = { "first", "second" };
-    char *tform[] = {"1J",       "1J"   };
-    char *tunit[] = { " ",       " "    };
-
-    /* append a new empty binary table onto the FITS file */
-
-    if ( fits_create_tbl( fptr, BINARY_TBL, BROWS, tfields, ttype, tform,
-                tunit, extname, status) )
-         printerror( *status );
-
-    /* get table row size and optimum number of rows to write per loop */
-    fits_get_rowsize(fptr, &nrows, status);
-    nrows = minvalue(nrows, SHTSIZE);
-    nremain = BROWS;
-
-    printf("Write %7drow x %dcol bintable %4ld rows/loop:", BROWS, tfields,
-       nrows);
-    marktime(status);
-
-    while(nremain)
-    {
-      ntodo = minvalue(nrows, nremain);
-      ffpclj(fptr, 1, firstrow, firstelem, ntodo, sarray, status);
-      ffpclj(fptr, 2, firstrow, firstelem, ntodo, sarray, status);
-      firstrow += ntodo;
-      nremain -= ntodo;
-    }
-
-    ffflus(fptr, status);  /* flush all buffers to disk */
-
-    gettime(&elapse, &elapcpu, status);
-
-    cpufrac = elapcpu / elapse * 100.;
-    size = BROWS * 8. / 1000000.;
-    rate = size / elapse;
-    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);
-
-    return( *status );
-}
-/*--------------------------------------------------------------------------*/
-int writeasctable (fitsfile *fptr, int *status)
-
-    /*********************************************************/
-    /* Create an ASCII table extension containing 2 columns  */
-    /*********************************************************/
-{
-    int tfields = 2;
-    long nremain, ntodo, firstrow = 1, firstelem = 1;
-    long nrows;
-    float rate, size, elapcpu, cpufrac;
-    double elapse;
-
-    char extname[] = "Speed_Test";           /* extension name */
-
-    /* define the name, datatype, and physical units for the columns */
-    char *ttype[] = { "first", "second" };
-    char *tform[] = {"I6",       "I6"   };
-    char *tunit[] = { " ",      " "     };
-
-    /* append a new empty ASCII table onto the FITS file */
-    if ( fits_create_tbl( fptr, ASCII_TBL, AROWS, tfields, ttype, tform,
-                tunit, extname, status) )
-         printerror( *status );
-
-    /* get table row size and optimum number of rows to write per loop */
-    fits_get_rowsize(fptr, &nrows, status);
-    nrows = minvalue(nrows, SHTSIZE);
-    nremain = AROWS;
-
-    printf("Write %7drow x %dcol asctable %4ld rows/loop:", AROWS, tfields,
-           nrows);
-    marktime(status);
-
-    while(nremain)
-    {
-      ntodo = minvalue(nrows, nremain);
-      ffpclj(fptr, 1, firstrow, firstelem, ntodo, sarray, status);
-      ffpclj(fptr, 2, firstrow, firstelem, ntodo, sarray, status);
-      firstrow += ntodo;
-      nremain -= ntodo;
-    }
-
-    ffflus(fptr, status);  /* flush all buffers to disk */
-
-    gettime(&elapse, &elapcpu, status);
-
-    cpufrac = elapcpu / elapse * 100.;
-    size = AROWS * 13. / 1000000.;
-    rate = size / elapse;
-    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);
-
-    return( *status );
-}
-/*--------------------------------------------------------------------------*/
-int readimage( fitsfile *fptr, int *status )
-
-    /*********************/
-    /* Read a FITS image */
-    /*********************/
-{
-    int anynull, hdutype;
-    long nremain, ii;
-    long longnull = 0;
-    float rate, size, elapcpu, cpufrac;
-    double elapse;
-
-    /* move to the primary array */
-    if ( fits_movabs_hdu(fptr, 1, &hdutype, status) ) 
-         printerror( *status );
-
-    printf("\nRead back image                                 ");
-    marktime(status);
-
-    nremain = XSIZE * YSIZE;
-    for (ii=1; ii <= nremain; ii += SHTSIZE)
-    {
-      ffgpvj(fptr, 0, ii, SHTSIZE, longnull, sarray, &anynull, status);
-    }
-
-    gettime(&elapse, &elapcpu, status);
-
-    cpufrac = elapcpu / elapse * 100.;
-    size = XSIZE * 4. * YSIZE / 1000000.;
-    rate = size / elapse;
-    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);
-
-    return( *status );
-}
-/*--------------------------------------------------------------------------*/
-int readbtable( fitsfile *fptr, int *status )
-
-    /************************************************************/
-    /* read and print data values from the binary table */
-    /************************************************************/
-{
-    int hdutype, anynull;
-    long nremain, ntodo, firstrow = 1, firstelem = 1;
-    long nrows;
-    long lnull = 0;
-    float rate, size, elapcpu, cpufrac;
-    double elapse;
-
-    /* move to the table */
-    if ( fits_movrel_hdu(fptr, 1, &hdutype, status) ) 
-           printerror( *status );
-
-    /* get table row size and optimum number of rows to read per loop */
-    fits_get_rowsize(fptr, &nrows, status);
-    nrows = minvalue(nrows, SHTSIZE);
-    
-    /*  read the columns */  
-    nremain = BROWS;
-
-    printf("Read back BINTABLE                              ");
-    marktime(status);
-
-    while(nremain)
-    {
-      ntodo = minvalue(nrows, nremain);
-      ffgcvj(fptr, 1, firstrow, firstelem, ntodo,
-                     lnull, sarray, &anynull, status);
-      ffgcvj(fptr, 2, firstrow, firstelem, ntodo,
-                     lnull, sarray, &anynull, status);
-      firstrow += ntodo; 
-      nremain  -= ntodo;
-    }
-
-    gettime(&elapse, &elapcpu, status);
-
-    cpufrac = elapcpu / elapse * 100.;
-    size = BROWS * 8. / 1000000.;
-    rate = size / elapse;
-    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);
-
-    return( *status );
-}
-/*--------------------------------------------------------------------------*/
-int readatable( fitsfile *fptr, int *status )
-
-    /************************************************************/
-    /* read and print data values from an ASCII or binary table */
-    /************************************************************/
-{
-    int hdutype, anynull;
-    long nremain, ntodo, firstrow = 1, firstelem = 1;
-    long nrows;
-    long lnull = 0;
-    float rate, size, elapcpu, cpufrac;
-    double elapse;
-
-    /* move to the table */
-    if ( fits_movrel_hdu(fptr, 1, &hdutype, status) ) 
-           printerror( *status );
-
-    /* get table row size and optimum number of rows to read per loop */
-    fits_get_rowsize(fptr, &nrows, status);
-    nrows = minvalue(nrows, SHTSIZE);
- 
-    /*  read the columns */  
-    nremain = AROWS;
-
-    printf("Read back ASCII Table                           ");
-    marktime(status);
-
-    while(nremain)
-    {
-      ntodo = minvalue(nrows, nremain);
-      ffgcvj(fptr, 1, firstrow, firstelem, ntodo,
-                     lnull, sarray, &anynull, status);
-      ffgcvj(fptr, 2, firstrow, firstelem, ntodo,
-                     lnull, sarray, &anynull, status);
-      firstrow += ntodo;
-      nremain  -= ntodo;
-    }
-
-    gettime(&elapse, &elapcpu, status);
-
-    cpufrac = elapcpu / elapse * 100.;
-    size = AROWS * 13. / 1000000.;
-    rate = size / elapse;
-    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);
-
-    return( *status );
-}
-/*--------------------------------------------------------------------------*/
-void printerror( int status)
-{
-    /*****************************************************/
-    /* Print out cfitsio error messages and exit program */
-    /*****************************************************/
-
-    char status_str[FLEN_STATUS], errmsg[FLEN_ERRMSG];
-  
-    if (status)
-      fprintf(stderr, "\n*** Error occurred during program execution ***\n");
-
-    fits_get_errstatus(status, status_str);   /* get the error description */
-    fprintf(stderr, "\nstatus = %d: %s\n", status, status_str);
-
-    /* get first message; null if stack is empty */
-    if ( fits_read_errmsg(errmsg) ) 
-    {
-         fprintf(stderr, "\nError message stack:\n");
-         fprintf(stderr, " %s\n", errmsg);
-
-         while ( fits_read_errmsg(errmsg) )  /* get remaining messages */
-             fprintf(stderr, " %s\n", errmsg);
-    }
-
-    exit( status );       /* terminate the program, returning error status */
-}
-/*--------------------------------------------------------------------------*/
-int marktime( int *status)
-{
-    double telapse;
-    time_t temp;
-    struct  timeval tv;
-
-    temp = time(0);
-
-    /* Since elapsed time is only measured to the nearest second */
-    /* keep getting the time until the seconds tick just changes. */
-    /* This provides more consistent timing measurements since the */
-    /* intervals all start on an integer seconds. */
-
-    telapse = 0.;
-
-        scpu = clock();
-        start = time(0);
-/*
-    while (telapse == 0.)
-    {
-        scpu = clock();
-        start = time(0);
-        telapse = difftime( start, temp );
-    }
-*/
-        gettimeofday (&tv, NULL);
-
-	startsec = tv.tv_sec;
-        startmilli = tv.tv_usec/1000;
-
-    return( *status );
-}
-/*--------------------------------------------------------------------------*/
-int gettime(double *elapse, float *elapscpu, int *status)
-{
-        struct  timeval tv;
-	int stopmilli;
-	long stopsec;
-
-
-        gettimeofday (&tv, NULL);
-    ecpu = clock();
-    finish = time(0);
-
-        stopmilli = tv.tv_usec/1000;
-	stopsec = tv.tv_sec;
-	
-
-	*elapse = (stopsec - startsec) + (stopmilli - startmilli)/1000.;
-
-/*    *elapse = difftime(finish, start) + 0.5; */
-    *elapscpu = (ecpu - scpu) * 1.0 / CLOCKTICKS;
-
-    return( *status );
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/swapproc.c b/src/external/OpenGR/3rdparty/cfitsio/swapproc.c
deleted file mode 100644
index cc69d6e69..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/swapproc.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*  This file, swapproc.c, contains general utility routines that are      */
-/*  used by other FITSIO routines to swap bytes.                           */
-
-/*  The FITSIO software was written by William Pence at the High Energy    */
-/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
-/*  Goddard Space Flight Center.                                           */
-
-/* The fast SSE2 and SSSE3 functions were provided by Julian Taylor, ESO */
-
-#include 
-#include 
-#include "fitsio2.h"
-
-/* bswap builtin is available since GCC 4.3 */
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
-#define HAVE_BSWAP
-#endif
-
-#ifdef __SSSE3__
-#include 
-/* swap 16 bytes according to mask, values must be 16 byte aligned */
-static inline void swap_ssse3(char * values, __m128i mask)
-{
-    __m128i v = _mm_load_si128((__m128i *)values);
-    __m128i s = _mm_shuffle_epi8(v, mask);
-    _mm_store_si128((__m128i*)values, s);
-}
-#endif
-#ifdef __SSE2__
-#include 
-/* swap 8 shorts, values must be 16 byte aligned
- * faster than ssse3 variant for shorts */
-static inline void swap2_sse2(char * values)
-{
-    __m128i r1 = _mm_load_si128((__m128i *)values);
-    __m128i r2 = r1;
-    r1 = _mm_srli_epi16(r1, 8);
-    r2 = _mm_slli_epi16(r2, 8);
-    r1 = _mm_or_si128(r1, r2);
-    _mm_store_si128((__m128i*)values, r1);
-}
-/* the three shuffles required for 4 and 8 byte variants make
- * SSE2 slower than bswap */
-
-
-/* get number of elements to peel to reach alignment */
-static inline size_t get_peel(void * addr, size_t esize, size_t nvals,
-                              size_t alignment)
-{
-    const size_t offset = (size_t)addr % alignment;
-    size_t peel = offset ? (alignment - offset) / esize : 0;
-    peel = nvals < peel ? nvals : peel;
-    return peel;
-}
-#endif
-
-/*--------------------------------------------------------------------------*/
-static void ffswap2_slow(short *svalues, long nvals)
-{
-    register long ii;
-    unsigned short * usvalues;
-
-    usvalues = (unsigned short *) svalues;
-
-    for (ii = 0; ii < nvals; ii++)
-    {
-        usvalues[ii] = (usvalues[ii]>>8) | (usvalues[ii]<<8);
-    }
-}
-/*--------------------------------------------------------------------------*/
-#if __SSE2__
-void ffswap2(short *svalues,  /* IO - pointer to shorts to be swapped    */
-             long nvals)     /* I  - number of shorts to be swapped     */
-/*
-  swap the bytes in the input short integers: ( 0 1 -> 1 0 )
-*/
-{
-    if ((long)svalues % 2 != 0) { /* should not happen */
-        ffswap2_slow(svalues, nvals);
-        return;
-    }
-
-    long ii;
-    size_t peel = get_peel((void*)&svalues[0], sizeof(svalues[0]), nvals, 16);
-
-    ffswap2_slow(svalues, peel);
-    for (ii = peel; ii < (nvals - peel - (nvals - peel) % 8); ii+=8) {
-        swap2_sse2((char*)&svalues[ii]);
-    }
-    ffswap2_slow(&svalues[ii], nvals - ii);
-}
-#else
-void ffswap2(short *svalues,  /* IO - pointer to shorts to be swapped    */
-             long nvals)     /* I  - number of shorts to be swapped     */
-/*
-  swap the bytes in the input 4-byte integer: ( 0 1 2 3 -> 3 2 1 0 )
-*/
-{
-    ffswap2_slow(svalues, nvals);
-}
-#endif
-/*--------------------------------------------------------------------------*/
-static void ffswap4_slow(INT32BIT *ivalues, long nvals)
-{
-    register long ii;
-
-#if defined(HAVE_BSWAP)
-    for (ii = 0; ii < nvals; ii++)
-    {
-        ivalues[ii] = __builtin_bswap32(ivalues[ii]);
-    }
-#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
-    /* intrinsic byte swapping function in Microsoft Visual C++ 8.0 and later */
-    unsigned int* uivalues = (unsigned int *) ivalues;
-
-    /* intrinsic byte swapping function in Microsoft Visual C++ */
-    for (ii = 0; ii < nvals; ii++)
-    {
-        uivalues[ii] = _byteswap_ulong(uivalues[ii]);
-    }
-#else
-    char *cvalues, tmp;
-
-    for (ii = 0; ii < nvals; ii++)
-    {
-        cvalues = (char *)&ivalues[ii];
-        tmp = cvalues[0];
-        cvalues[0] = cvalues[3];
-        cvalues[3] = tmp;
-        tmp = cvalues[1];
-        cvalues[1] = cvalues[2];
-        cvalues[2] = tmp;
-    }
-#endif
-}
-/*--------------------------------------------------------------------------*/
-#ifdef __SSSE3__
-void ffswap4(INT32BIT *ivalues,  /* IO - pointer to INT*4 to be swapped    */
-                 long nvals)     /* I  - number of floats to be swapped     */
-/*
-  swap the bytes in the input 4-byte integer: ( 0 1 2 3 -> 3 2 1 0 )
-*/
-{
-    if ((long)ivalues % 4 != 0) { /* should not happen */
-        ffswap4_slow(ivalues, nvals);
-        return;
-    }
-
-    long ii;
-    const __m128i cmask4 = _mm_set_epi8(12, 13, 14, 15,
-                                        8, 9, 10, 11,
-                                        4, 5, 6, 7,
-                                        0, 1, 2 ,3);
-    size_t peel = get_peel((void*)&ivalues[0], sizeof(ivalues[0]), nvals, 16);
-    ffswap4_slow(ivalues, peel);
-    for (ii = peel; ii < (nvals - peel - (nvals - peel) % 4); ii+=4) {
-        swap_ssse3((char*)&ivalues[ii], cmask4);
-    }
-    ffswap4_slow(&ivalues[ii], nvals - ii);
-}
-#else
-void ffswap4(INT32BIT *ivalues,  /* IO - pointer to INT*4 to be swapped    */
-                 long nvals)     /* I  - number of floats to be swapped     */
-/*
-  swap the bytes in the input 4-byte integer: ( 0 1 2 3 -> 3 2 1 0 )
-*/
-{
-    ffswap4_slow(ivalues, nvals);
-}
-#endif
-/*--------------------------------------------------------------------------*/
-static void ffswap8_slow(double *dvalues, long nvals)
-{
-    register long ii;
-#ifdef HAVE_BSWAP
-    LONGLONG * llvalues = (LONGLONG*)dvalues;
-
-    for (ii = 0; ii < nvals; ii++) {
-        llvalues[ii] = __builtin_bswap64(llvalues[ii]);
-    }
-#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
-    /* intrinsic byte swapping function in Microsoft Visual C++ 8.0 and later */
-    unsigned __int64 * llvalues = (unsigned __int64 *) dvalues;
-
-    for (ii = 0; ii < nvals; ii++)
-    {
-        llvalues[ii] = _byteswap_uint64(llvalues[ii]);
-    }
-#else
-    register char *cvalues;
-    register char temp;
-
-    cvalues = (char *) dvalues;      /* copy the pointer value */
-
-    for (ii = 0; ii < nvals*8; ii += 8)
-    {
-        temp = cvalues[ii];
-        cvalues[ii] = cvalues[ii+7];
-        cvalues[ii+7] = temp;
-
-        temp = cvalues[ii+1];
-        cvalues[ii+1] = cvalues[ii+6];
-        cvalues[ii+6] = temp;
-
-        temp = cvalues[ii+2];
-        cvalues[ii+2] = cvalues[ii+5];
-        cvalues[ii+5] = temp;
-
-        temp = cvalues[ii+3];
-        cvalues[ii+3] = cvalues[ii+4];
-        cvalues[ii+4] = temp;
-    }
-#endif
-}
-/*--------------------------------------------------------------------------*/
-#ifdef __SSSE3__
-void ffswap8(double *dvalues,  /* IO - pointer to doubles to be swapped     */
-             long nvals)       /* I  - number of doubles to be swapped      */
-/*
-  swap the bytes in the input doubles: ( 01234567  -> 76543210 )
-*/
-{
-    if ((long)dvalues % 8 != 0) { /* should not happen on amd64 */
-        ffswap8_slow(dvalues, nvals);
-        return;
-    }
-
-    long ii;
-    const __m128i cmask8 = _mm_set_epi8(8, 9, 10, 11, 12, 13, 14, 15,
-                                        0, 1, 2 ,3, 4, 5, 6, 7);
-    size_t peel = get_peel((void*)&dvalues[0], sizeof(dvalues[0]), nvals, 16);
-    ffswap8_slow(dvalues, peel);
-    for (ii = peel; ii < (nvals - peel - (nvals - peel) % 2); ii+=2) {
-        swap_ssse3((char*)&dvalues[ii], cmask8);
-    }
-    ffswap8_slow(&dvalues[ii], nvals - ii);
-}
-#else
-void ffswap8(double *dvalues,  /* IO - pointer to doubles to be swapped     */
-             long nvals)       /* I  - number of doubles to be swapped      */
-/*
-  swap the bytes in the input doubles: ( 01234567  -> 76543210 )
-*/
-{
-    ffswap8_slow(dvalues, nvals);
-}
-#endif
diff --git a/src/external/OpenGR/3rdparty/cfitsio/testf77.f b/src/external/OpenGR/3rdparty/cfitsio/testf77.f
deleted file mode 100644
index 993991db5..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/testf77.f
+++ /dev/null
@@ -1,2488 +0,0 @@
-C     This is a big and complicated program that tests most of
-C     the fitsio routines.  This code does not represent
-C     the most efficient method of reading or writing FITS files 
-C     because this code is primarily designed to stress the fitsio
-C     library routines.
-
-      character asciisum*17
-      character*3 cval
-      character*1 xinarray(21), binarray(21), boutarray(21), bnul
-      character colname*70, tdisp*40, nulstr*40
-      character oskey*15
-      character iskey*21
-      character lstr*200   
-      character  comm*73
-      character*30 inskey(21)
-      character*30 onskey(3)
-      character filename*40, card*78, card2*78
-      character keyword*8
-      character value*68, comment*72
-      character uchars*78
-      character*15 ttype(10), tform(10), tunit(10)
-      character*15 tblname
-      character*15 binname
-      character errmsg*75
-      character*8  inclist(2),exclist(2)
-      character*8 xctype,yctype,ctype
-      character*18 kunit
-
-      logical simple,extend,larray(42), larray2(42)
-      logical olkey, ilkey, onlkey(3), inlkey(3), anynull
-
-      integer*2 imgarray(19,30), imgarray2(10,20)
-      integer*2         iinarray(21), ioutarray(21), inul
-
-      integer naxes(3), pcount, gcount, npixels, nrows, rowlen
-      integer existkeys, morekeys, keynum
-      integer datastatus, hdustatus
-      integer status, bitpix, naxis, block
-      integer ii, jj, jjj, hdutype, hdunum, tfields
-      integer nkeys, nfound, colnum, typecode, signval,nmsg
-      integer repeat, offset, width, jnulval
-      integer kinarray(21), koutarray(21), knul
-      integer jinarray(21), joutarray(21), jnul
-      integer ojkey, ijkey, otint
-      integer onjkey(3), injkey(3)
-      integer tbcol(5)
-      integer iunit, tmpunit
-      integer fpixels(2), lpixels(2), inc(2)
-
-      real estatus, vers
-      real einarray(21), eoutarray(21), enul, cinarray(42)
-      real ofkey, oekey, iekey, onfkey(3),onekey(3), inekey(3)
-
-      double precision dinarray(21),doutarray(21),dnul, minarray(42)
-      double precision scale, zero
-      double precision ogkey, odkey, idkey, otfrac, ongkey(3)
-      double precision ondkey(3), indkey(3)
-      double precision checksum, datsum
-      double precision xrval,yrval,xrpix,yrpix,xinc,yinc,rot
-      double precision xpos,ypos,xpix,ypix
-
-      tblname = 'Test-ASCII'
-      binname = 'Test-BINTABLE'
-      onskey(1) = 'first string'
-      onskey(2) = 'second string'
-      onskey(3) = '        '
-      oskey = 'value_string'
-      inclist(1)='key*'
-      inclist(2)='newikys'
-      exclist(1)='key_pr*'
-      exclist(2)='key_pkls'
-      xctype='RA---TAN'
-      yctype='DEC--TAN'
-
-      olkey = .true.
-      ojkey = 11
-      otint = 12345678
-      ofkey = 12.121212
-      oekey = 13.131313
-      ogkey = 14.1414141414141414D+00
-      odkey = 15.1515151515151515D+00
-      otfrac = .1234567890123456D+00
-      onlkey(1) = .true.
-      onlkey(2) = .false.
-      onlkey(3) = .true.
-      onjkey(1) = 11
-      onjkey(2) = 12
-      onjkey(3) = 13
-      onfkey(1) = 12.121212
-      onfkey(2) = 13.131313
-      onfkey(3) = 14.141414
-      onekey(1) = 13.131313
-      onekey(2) = 14.141414
-      onekey(3) = 15.151515
-      ongkey(1) = 14.1414141414141414D+00
-      ongkey(2) = 15.1515151515151515D+00
-      ongkey(3) = 16.1616161616161616D+00
-      ondkey(1) = 15.1515151515151515D+00
-      ondkey(2) = 16.1616161616161616D+00
-      ondkey(3) = 17.1717171717171717D+00
-
-      tbcol(1) = 1
-      tbcol(2) =  17
-      tbcol(3) =  28
-      tbcol(4) =  43
-      tbcol(5) =  56
-      status = 0
-
-      call ftvers(vers)
-      write(*,'(1x,A)') 'FITSIO TESTPROG'
-      write(*, '(1x,A)')' '
-
-      iunit = 15
-      tmpunit = 16
-
-      write(*,'(1x,A)') 'Try opening then closing a nonexistent file: '
-      call ftopen(iunit, 'tq123x.kjl', 1, block, status)
-      write(*,'(1x,A,2i4)')'  ftopen iunit, status (expect an error) ='
-     & ,iunit, status
-      call ftclos(iunit, status)
-      write(*,'(1x,A,i4)')'  ftclos status = ', status
-      write(*,'(1x,A)')' '
-
-      call ftcmsg
-      status = 0
-
-      filename = 'testf77.fit'
-
-C delete previous version of the file, if it exists 
-
-      call ftopen(iunit, filename, 1, block, status)
-      if (status .eq. 0)then
-         call ftdelt(iunit, status)
-      else
-C        clear the error message stack
-         call ftcmsg
-      end if
-
-      status = 0
-
-C
-C        #####################
-C        #  create FITS file #
-C        #####################
-      
-
-      call ftinit(iunit, filename, 1, status)
-      write(*,'(1x,A,i4)')'ftinit create new file status = ', status
-      write(*,'(1x,A)')' '
-
-      if (status .ne. 0)go to 999
-
-      simple = .true.
-      bitpix = 32
-      naxis = 2
-      naxes(1) = 10
-      naxes(2) = 2
-      npixels = 20
-      pcount = 0
-      gcount = 1
-      extend = .true.
-      
-C        ############################
-C        #  write single keywords   #
-C        ############################
-      
-      call ftphpr(iunit,simple, bitpix, naxis, naxes, 
-     & 0,1,extend,status)
-
-      call ftprec(iunit, 
-     &'key_prec= ''This keyword was written by fxprec'' / '//
-     & 'comment goes here',  status)
-
-      write(*,'(1x,A)') 'test writing of long string keywords: '
-      card = '1234567890123456789012345678901234567890'//
-     & '12345678901234567890123456789012345'
-      call ftpkys(iunit, 'card1', card, ' ', status)
-      call ftgkey(iunit, 'card1', card2, comment, status)
-
-      write(*,'(1x,A)') card
-      write(*,'(1x,A)') card2
-      
-      card = '1234567890123456789012345678901234567890'//
-     &  '123456789012345678901234''6789012345'
-      call ftpkys(iunit, 'card2', card, ' ', status)
-      call ftgkey(iunit, 'card2', card2, comment, status)
-      write(*,'(1x,A)') card
-      write(*,'(1x,A)') card2
-      
-      card = '1234567890123456789012345678901234567890'//
-     &  '123456789012345678901234''''789012345'
-      call ftpkys(iunit, 'card3', card, ' ', status)
-      call ftgkey(iunit, 'card3', card2, comment, status)
-      write(*,'(1x,A)') card
-      write(*,'(1x,A)') card2
-      
-      card = '1234567890123456789012345678901234567890'//
-     & '123456789012345678901234567''9012345'
-      call ftpkys(iunit, 'card4', card, ' ', status)
-      call ftgkey(iunit, 'card4', card2, comment, status)
-      write(*,'(1x,A)') card
-      write(*,'(1x,A)') card2
-
-      call ftpkys(iunit, 'key_pkys', oskey, 'fxpkys comment', status)
-      call ftpkyl(iunit, 'key_pkyl', olkey, 'fxpkyl comment', status)
-      call ftpkyj(iunit, 'key_pkyj', ojkey, 'fxpkyj comment', status)
-      call ftpkyf(iunit,'key_pkyf',ofkey,5, 'fxpkyf comment', status)
-      call ftpkye(iunit,'key_pkye',oekey,6, 'fxpkye comment', status)
-      call ftpkyg(iunit,'key_pkyg',ogkey,14, 'fxpkyg comment',status)
-      call ftpkyd(iunit,'key_pkyd',odkey,14, 'fxpkyd comment',status)
-
-      lstr='This is a very long string '//
-     &   'value that is continued over more than one keyword.'
-
-      call ftpkls(iunit,'key_pkls',lstr,'fxpkls comment',status)
-
-      call ftplsw(iunit, status)
-      call ftpkyt(iunit,'key_pkyt',otint,otfrac,'fxpkyt comment',
-     & status)
-      call ftpcom(iunit, 'This keyword was written by fxpcom.',
-     &  status)
-      call ftphis(iunit, 
-     &'  This keyword written by fxphis (w/ 2 leading spaces).',
-     &    status)
-
-      call ftpdat(iunit, status)
-      
-      if (status .gt. 0)go to 999   
-
-C
-C        ###############################
-C        #  write arrays of keywords   #
-C        ###############################
-      
-      nkeys = 3
-
-      comm = 'fxpkns comment&'
-      call ftpkns(iunit, 'ky_pkns', 1, nkeys, onskey, comm, status)
-      comm = 'fxpknl comment&'
-      call ftpknl(iunit, 'ky_pknl', 1, nkeys, onlkey, comm, status)
-
-      comm = 'fxpknj comment&'
-      call ftpknj(iunit, 'ky_pknj', 1, nkeys, onjkey, comm, status)
-
-      comm = 'fxpknf comment&'
-      call ftpknf(iunit, 'ky_pknf', 1, nkeys, onfkey,5,comm,status)
-
-      comm = 'fxpkne comment&'
-      call ftpkne(iunit, 'ky_pkne', 1, nkeys, onekey,6,comm,status)
-
-      comm = 'fxpkng comment&'
-      call ftpkng(iunit, 'ky_pkng', 1, nkeys, ongkey,13,comm,status)
-
-      comm = 'fxpknd comment&'
-      call ftpknd(iunit, 'ky_pknd', 1, nkeys, ondkey,14,comm,status)
-      
-      if (status .gt. 0)go to 999
-      
-C        ############################
-C        #  write generic keywords  #
-C        ############################
-      
-
-      oskey = '1'
-      call ftpkys(iunit, 'tstring', oskey, 'tstring comment',status)
-
-      olkey = .true.
-      call ftpkyl(iunit, 'tlogical', olkey, 'tlogical comment',
-     &    status)
-
-      ojkey = 11
-      call ftpkyj(iunit, 'tbyte', ojkey, 'tbyte comment', status)
-
-      ojkey = 21
-      call ftpkyj(iunit, 'tshort', ojkey, 'tshort comment', status)
-
-      ojkey = 31
-      call ftpkyj(iunit, 'tint', ojkey, 'tint comment', status)
-
-      ojkey = 41
-      call ftpkyj(iunit, 'tlong', ojkey, 'tlong comment', status)
-
-      oekey = 42
-      call ftpkye(iunit, 'tfloat', oekey, 6,'tfloat comment', status)
-
-      odkey = 82.D+00
-      call ftpkyd(iunit, 'tdouble', odkey, 14, 'tdouble comment',
-     &          status)
-
-      if (status .gt. 0)go to 999
-      write(*,'(1x,A)') 'Wrote all Keywords successfully '
-
-
-C        ############################
-C        #  write data              #
-C        ############################
-      
-      
-C define the null value (must do this before writing any data) 
-      call ftpkyj(iunit,'BLANK',-99,
-     & 'value to use for undefined pixels',   status)
-      
-C initialize arrays of values to write to primary array 
-      do ii = 1, npixels
-          boutarray(ii) = char(ii)
-          ioutarray(ii) = ii
-          joutarray(ii) = ii
-          eoutarray(ii) = ii
-          doutarray(ii) = ii
-      end do      
-
-C write a few pixels with each datatype 
-C set the last value in each group of 4 as undefined 
-      call ftpprb(iunit, 1,  1, 2, boutarray(1),  status)
-      call ftppri(iunit, 1,  5, 2, ioutarray(5),  status)
-      call ftpprj(iunit, 1,  9, 2, joutarray(9),  status)
-      call ftppre(iunit, 1, 13, 2, eoutarray(13), status)
-      call ftpprd(iunit, 1, 17, 2, doutarray(17), status)
-      bnul = char(4)
-      call ftppnb(iunit, 1,  3, 2, boutarray(3),   bnul, status)
-      inul = 8
-      call ftppni(iunit, 1,  7, 2, ioutarray(7),  inul, status)
-      call ftppnj(iunit, 1, 11, 2, joutarray(11),  12, status)
-      call ftppne(iunit, 1, 15, 2, eoutarray(15), 16., status)
-      dnul = 20.
-      call ftppnd(iunit, 1, 19, 2, doutarray(19), dnul, status)
-      call ftppru(iunit, 1, 1, 1, status)
-
-      if (status .gt. 0)then
-          write(*,'(1x,A,I4)')'ftppnx status = ', status
-          goto 999
-      end if
-
-      call ftflus(iunit, status)   
-C flush all data to the disk file  
-      write(*,'(1x,A,I4)')'ftflus status = ', status
-      write(*,'(1x,A)')' '
-
-      call ftghdn(iunit, hdunum)
-      write(*,'(1x,A,I4)')'HDU number = ', hdunum
-
-C        ############################
-C        #  read data               #
-C        ############################
-      
-     
-C read back the data, setting null values = 99 
-      write(*,'(1x,A)')
-     &   'Values read back from primary array (99 = null pixel)'
-      write(*,'(1x,A)') 
-     &  'The 1st, and every 4th pixel should be undefined: '
-
-      anynull = .false.
-      bnul = char(99)
-      call ftgpvb(iunit, 1,  1, 10, bnul, binarray, anynull, status)
-      call ftgpvb(iunit, 1, 11, 10, bnul, binarray(11),anynull,status)
-
-      do ii = 1,npixels
-           iinarray(ii) = ichar(binarray(ii))
-      end do
-
-      write(*,1101) (iinarray(ii), ii = 1, npixels), anynull,
-     &  ' (ftgpvb) '
-1101  format(1x,20i3,l3,a)
-
-      inul = 99
-      call ftgpvi(iunit, 1, 1, npixels, inul, iinarray,anynull,status)
-
-      write(*,1101) (iinarray(ii), ii = 1, npixels), anynull,
-     &  ' (ftgpvi) '
-
-      call ftgpvj(iunit, 1, 1, npixels, 99,  jinarray,anynull,status)
-
-      write(*,1101) (jinarray(ii), ii = 1, npixels), anynull,
-     &  ' (ftgpvj) '
-
-      call ftgpve(iunit, 1, 1, npixels, 99., einarray,anynull,status)
-
-      write(*,1102) (einarray(ii), ii = 1, npixels), anynull,
-     &  ' (ftgpve) '
-
-1102  format(2x,20f3.0,l2,a)
-
-      dnul = 99.
-      call ftgpvd(iunit, 1,  1, 10, dnul,  dinarray, anynull, status)
-      call ftgpvd(iunit, 1, 11, 10, dnul,dinarray(11),anynull,status)
-
-      write(*,1102) (dinarray(ii), ii = 1, npixels), anynull,
-     &  ' (ftgpvd) '
-
-      if (status .gt. 0)then
-          write(*,'(1x,A,I4)')'ERROR: ftgpv_ status = ', status
-          goto 999
-      end if
-      
-      if (.not. anynull)then
-         write(*,'(1x,A)') 'ERROR: ftgpv_ did not detect null values '
-         go to 999
-      end if
-      
-C reset the output null value to the expected input value 
-
-      do ii = 4, npixels, 4      
-          boutarray(ii) = char(99)
-          ioutarray(ii) = 99
-          joutarray(ii) = 99
-          eoutarray(ii) = 99.
-          doutarray(ii) = 99.
-      end do
-
-          ii = 1
-          boutarray(ii) = char(99)
-          ioutarray(ii) = 99
-          joutarray(ii) = 99
-          eoutarray(ii) = 99.
-          doutarray(ii) = 99.
-
-      
-C compare the output with the input flag any differences 
-      do ii = 1, npixels
-     
-         if (boutarray(ii) .ne. binarray(ii))then
-             write(*,'(1x,A,2A2)') 'bout != bin ', boutarray(ii), 
-     &      binarray(ii)
-         end if
-
-         if (ioutarray(ii) .ne. iinarray(ii))then
-             write(*,'(1x,A,2I8)') 'bout != bin ', ioutarray(ii), 
-     &      iinarray(ii)
-         end if
-
-         if (joutarray(ii) .ne. jinarray(ii))then
-             write(*,'(1x,A,2I12)') 'bout != bin ', joutarray(ii), 
-     &       jinarray(ii)
-         end if
-
-         if (eoutarray(ii) .ne. einarray(ii))then
-             write(*,'(1x,A,2E15.3)') 'bout != bin ', eoutarray(ii),
-     &       einarray(ii)
-         end if
-    
-         if (doutarray(ii) .ne. dinarray(ii))then
-             write(*,'(1x,A,2D20.6)') 'bout != bin ', doutarray(ii), 
-     &       dinarray(ii)
-         end if
-      end do
-
-      do ii = 1, npixels
-        binarray(ii) = char(0)
-        iinarray(ii) = 0
-        jinarray(ii) = 0
-        einarray(ii) = 0.
-        dinarray(ii) = 0.
-      end do      
-
-      anynull = .false.
-      call ftgpfb(iunit, 1,  1, 10, binarray, larray, anynull,status)
-      call ftgpfb(iunit, 1, 11, 10, binarray(11), larray(11),
-     & anynull, status)
-
-      do ii = 1, npixels
-        if (larray(ii))binarray(ii) = char(0)
-      end do
-
-      do ii = 1,npixels
-           iinarray(ii) = ichar(binarray(ii))
-      end do
-
-      write(*,1101)(iinarray(ii),ii = 1,npixels),anynull,' (ftgpfb)'
-
-      call ftgpfi(iunit, 1, 1, npixels, iinarray, larray, anynull,
-     & status)
-
-      do ii = 1, npixels
-        if (larray(ii))iinarray(ii) = 0
-      end do
-
-      write(*,1101)(iinarray(ii),ii = 1,npixels),anynull,' (ftgpfi)'
-
-      call ftgpfj(iunit, 1, 1, npixels, jinarray, larray, anynull,
-     & status)
-
-      do ii = 1, npixels
-        if (larray(ii))jinarray(ii) = 0
-      end do
-
-      write(*,1101)(jinarray(ii),ii = 1,npixels),anynull,' (ftgpfj)'
-
-      call ftgpfe(iunit, 1, 1, npixels, einarray, larray, anynull,
-     & status)
-
-      do ii = 1, npixels
-        if (larray(ii))einarray(ii) = 0.
-      end do
-
-      write(*,1102)(einarray(ii),ii = 1,npixels),anynull,' (ftgpfe)'
-
-      call ftgpfd(iunit, 1,  1, 10, dinarray, larray, anynull,status)
-      call ftgpfd(iunit, 1, 11, 10, dinarray(11), larray(11),
-     & anynull, status)
-
-      do ii = 1, npixels
-        if (larray(ii))dinarray(ii) = 0.
-      end do
-
-      write(*,1102)(dinarray(ii),ii = 1,npixels),anynull,' (ftgpfd)'
-
-      if (status .gt. 0)then
-          write(*,'(1x,A,I4)')'ERROR: ftgpf_ status = ', status
-          go to 999
-      end if
-
-      if (.not. anynull)then
-         write(*,'(1x,A)') 'ERROR: ftgpf_ did not detect null values'
-         go to 999
-      end if
-
-
-C        ##########################################
-C        #  close and reopen file multiple times  #
-C        ##########################################
-      
-
-      do ii = 1, 10
-         call ftclos(iunit, status)
-        
-         if (status .gt. 0)then
-            write(*,'(1x,A,I4)')'ERROR in ftclos (1) = ', status
-            go to 999
-         end if
-
-         call ftopen(iunit, filename, 1, block, status)
-
-         if (status .gt. 0)then
-            write(*,'(1x,A,I4)')'ERROR: ftopen open file status = ',
-     &      status
-            go to 999
-         end if
-      end do
-      
-      write(*,'(1x,A)') ' '
-      write(*,'(1x,A)') 'Closed then reopened the FITS file 10 times.'
-      write(*,'(1x,A)')' '
-
-      call ftghdn(iunit, hdunum)
-      write(*,'(1x,A,I4)')'HDU number = ', hdunum
-
-
-C        ############################
-C        #  read single keywords    #
-C        ############################
-      
-
-      simple = .false.
-      bitpix = 0
-      naxis = 0
-      naxes(1) = 0
-      naxes(2) = 0
-      pcount = -99
-      gcount =  -99
-      extend = .false.
-      write(*,'(1x,A)') 'Read back keywords: '
-      call ftghpr(iunit, 3, simple, bitpix, naxis, naxes, pcount,
-     &       gcount, extend, status)
-      write(*,'(1x,A,L4,4I4)')'simple, bitpix, naxis, naxes = ',
-     &       simple, bitpix, naxis, naxes(1), naxes(2)
-      write(*,'(1x,A,2I4,L4)')'  pcount, gcount, extend = ',
-     &           pcount, gcount, extend
-
-      call ftgrec(iunit, 9, card, status)
-      write(*,'(1x,A)') card
-      if (card(1:15) .ne. 'KEY_PREC= ''This')
-     &    write(*,'(1x,A)') 'ERROR in ftgrec '
-
-      call ftgkyn(iunit, 9, keyword, value, comment, status)
-      write(*,'(1x,5A)') keyword,' ', value(1:35),' ', comment(1:20)
-
-      if (keyword(1:8) .ne. 'KEY_PREC' )
-     &    write(*,'(1x,2A)') 'ERROR in ftgkyn: ', keyword
-
-      call ftgcrd(iunit, keyword, card, status)
-      write(*,'(1x,A)') card
-
-      if (keyword(1:8) .ne.  card(1:8) )
-     &    write(*,'(1x,2A)') 'ERROR in ftgcrd: ', keyword
-
-      call ftgkey(iunit, 'KY_PKNS1', value, comment, status)
-      write(*,'(1x,5A)') 'KY_PKNS1 ',':', value(1:15),':', comment(1:16)
-
-      if (value(1:14) .ne. '''first string''')
-     &  write(*,'(1x,2A)') 'ERROR in ftgkey: ', value
-
-      call ftgkys(iunit, 'key_pkys', iskey, comment, status)
-      write(*,'(1x,5A,I4)')'KEY_PKYS ',':',iskey,':',comment(1:16),
-     & status
-
-      call ftgkyl(iunit, 'key_pkyl', ilkey, comment, status)
-      write(*,'(1x,2A,L4,2A,I4)') 'KEY_PKYL ',':', ilkey,':', 
-     &comment(1:16), status
-
-      call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status)
-      write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', 
-     &  comment(1:16), status
-
-      call ftgkye(iunit, 'KEY_PKYJ', iekey, comment, status)
-      write(*,'(1x,2A,f12.5,2A,I4)') 'KEY_PKYE ',':',iekey,':',
-     & comment(1:16), status
-
-      call ftgkyd(iunit, 'KEY_PKYJ', idkey, comment, status)
-      write(*,'(1x,2A,F12.5,2A,I4)') 'KEY_PKYD ',':',idkey,':', 
-     & comment(1:16), status
-
-      if (ijkey .ne. 11 .or. iekey .ne. 11. .or. idkey .ne. 11.)
-     &   write(*,'(1x,A,I4,2F5.1)') 'ERROR in ftgky(jed): ',
-     & ijkey, iekey, idkey
-
-      iskey= ' '
-      call ftgkys(iunit, 'key_pkys', iskey, comment, status)
-      write(*,'(1x,5A,I4)') 'KEY_PKYS ',':', iskey,':', comment(1:16),
-     &  status
-
-      ilkey = .false.
-      call ftgkyl(iunit, 'key_pkyl', ilkey, comment, status)
-      write(*,'(1x,2A,L4,2A,I4)') 'KEY_PKYL ',':', ilkey,':',
-     &  comment(1:16), status
-
-      ijkey = 0
-      call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status)
-      write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', 
-     & comment(1:16), status
-
-      iekey = 0
-      call ftgkye(iunit, 'KEY_PKYE', iekey, comment, status)
-      write(*,'(1x,2A,f12.5,2A,I4)') 'KEY_PKYE ',':',iekey,':', 
-     & comment(1:16), status
-
-      idkey = 0
-      call ftgkyd(iunit, 'KEY_PKYD', idkey, comment, status)
-      write(*,'(1x,2A,F12.5,2A,I4)') 'KEY_PKYD ',':',idkey,':',
-     & comment(1:16), status
-
-      iekey = 0
-      call ftgkye(iunit, 'KEY_PKYF', iekey, comment, status)
-      write(*,'(1x,2A,f12.5,2A,I4)') 'KEY_PKYF ',':',iekey,':',
-     & comment(1:16), status
-
-      iekey = 0
-      call ftgkye(iunit, 'KEY_PKYE', iekey, comment, status)
-      write(*,'(1x,2A,f12.5,2A,I4)') 'KEY_PKYE ',':',iekey,':', 
-     & comment(1:16), status
-
-      idkey = 0
-      call ftgkyd(iunit, 'KEY_PKYG', idkey, comment, status)
-      write(*,'(1x,2A,f16.12,2A,I4)') 'KEY_PKYG ',':',idkey,':',
-     & comment(1:16), status
-
-      idkey = 0
-      call ftgkyd(iunit, 'KEY_PKYD', idkey, comment, status)
-      write(*,'(1x,2A,f16.12,2A,I4)') 'KEY_PKYD ',':',idkey,':', 
-     & comment(1:16), status
-
-      call ftgkyt(iunit, 'KEY_PKYT', ijkey, idkey, comment, status)
-      write(*,'(1x,2A,i10,A,f16.14,A,I4)') 'KEY_PKYT  ',':',
-     & ijkey,':', idkey, comment(1:16), status
-
-      call ftpunt(iunit, 'KEY_PKYJ', 'km/s/Mpc', status)
-      ijkey = 0
-      call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status)
-      write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', 
-     & comment(1:38), status
-      call ftgunt(iunit,'KEY_PKYJ',kunit,status)
-      write(*,'(1x,2A)') 'keyword unit=', kunit
-
-      call ftpunt(iunit, 'KEY_PKYJ', ' ', status)
-      ijkey = 0
-      call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status)
-      write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', 
-     & comment(1:38), status
-      call ftgunt(iunit,'KEY_PKYJ',kunit,status)
-      write(*,'(1x,2A)') 'keyword unit=', kunit
-
-      call ftpunt(iunit, 'KEY_PKYJ', 'feet/second/second', status)
-      ijkey = 0
-      call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status)
-      write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', 
-     & comment(1:38), status
-      call ftgunt(iunit,'KEY_PKYJ',kunit,status)
-      write(*,'(1x,2A)') 'keyword unit=', kunit
-
-      call ftgkys(iunit, 'key_pkls', lstr, comment, status)
-      write(*,'(1x,2A)') 'KEY_PKLS long string value = ', lstr(1:50)
-      write(*,'(1x,A)')lstr(51:120)
-
-C get size and position in header 
-      call ftghps(iunit, existkeys, keynum, status)
-      write(*,'(1x,A,I4,A,I4)') 'header contains ', existkeys,
-     & ' keywords; located at keyword ', keynum
-
-C        ############################
-C        #  read array keywords     #
-C        ############################
-      
-      call ftgkns(iunit, 'ky_pkns', 1, 3, inskey, nfound, status)
-      write(*,'(1x,4A)') 'ftgkns: ', inskey(1)(1:14), inskey(2)(1:14),
-     &  inskey(3)(1:14)
-      if (nfound .ne. 3 .or. status .gt. 0)
-     &   write(*,'(1x,A,2I4)') ' ERROR in ftgkns ', nfound, status
-
-      call ftgknl(iunit, 'ky_pknl', 1, 3, inlkey, nfound, status)
-      write(*,'(1x,A,3L4)') 'ftgknl: ', inlkey(1), inlkey(2), inlkey(3)
-      if (nfound .ne. 3 .or. status .gt. 0)
-     &   write(*,'(1x,A,2I4)') ' ERROR in ftgknl ', nfound, status
-
-      call ftgknj(iunit, 'ky_pknj', 1, 3, injkey, nfound, status)
-      write(*,'(1x,A,3I4)') 'ftgknj: ', injkey(1), injkey(2), injkey(3)
-      if (nfound .ne. 3 .or. status .gt. 0)
-     &   write(*,'(1x,A,2I4)') ' ERROR in ftgknj ', nfound, status
-
-      call ftgkne(iunit, 'ky_pkne', 1, 3, inekey, nfound, status)
-      write(*,'(1x,A,3F10.5)') 'ftgkne: ',inekey(1),inekey(2),inekey(3)
-      if (nfound .ne. 3 .or. status .gt. 0)
-     &   write(*,'(1x,A,2I4)') ' ERROR in ftgkne ', nfound, status
-
-      call ftgknd(iunit, 'ky_pknd', 1, 3, indkey, nfound, status)
-      write(*,'(1x,A,3F10.5)') 'ftgknd: ',indkey(1),indkey(2),indkey(3)
-      if (nfound .ne. 3 .or. status .gt. 0)
-     &   write(*,'(1x,A,2I4)') ' ERROR in ftgknd ', nfound, status
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)')
-     & 'Before deleting the HISTORY and DATE keywords...'
-      do ii = 29, 32     
-          call ftgrec(iunit, ii, card, status)
-          write(*,'(1x,A)') card(1:8)
-      end do
-
-C don't print date value, so that 
-C the output will always be the same 
-      
-
-C        ############################
-C        #  delete keywords         #
-C        ############################
-      
-
-      call ftdrec(iunit, 30, status)
-      call ftdkey(iunit, 'DATE', status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'After deleting the keywords... '
-      do ii = 29, 30            
-          call ftgrec(iunit, ii, card, status)
-          write(*,'(1x,A)') card
-      end do      
-
-      if (status .gt. 0)
-     &   write(*,'(1x,A)') ' ERROR deleting keywords '
-      
-
-C        ############################
-C        #  insert keywords         #
-C        ############################
-      
-      call ftirec(iunit,26,
-     & 'KY_IREC = ''This keyword inserted by fxirec''',
-     &   status)
-      call ftikys(iunit, 'KY_IKYS', 'insert_value_string',
-     &  'ikys comment', status)
-      call ftikyj(iunit, 'KY_IKYJ', 49, 'ikyj comment', status)
-      call ftikyl(iunit, 'KY_IKYL', .true., 'ikyl comment', status)
-      call ftikye(iunit, 'KY_IKYE',12.3456,4,'ikye comment',status)
-      odkey = 12.345678901234567D+00
-      call ftikyd(iunit, 'KY_IKYD', odkey, 14,
-     &  'ikyd comment', status)
-      call ftikyf(iunit, 'KY_IKYF', 12.3456, 4, 'ikyf comment',
-     & status)
-      call ftikyg(iunit, 'KY_IKYG', odkey, 13,
-     & 'ikyg comment', status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'After inserting the keywords... '
-      do ii = 25, 34
-          call ftgrec(iunit, ii, card, status)
-          write(*,'(1x,A)') card
-      end do
-
-      if (status .gt. 0)
-     &   write(*,'(1x,A)') ' ERROR inserting keywords '
-      
-
-C        ############################
-C        #  modify keywords         #
-C        ############################
-      
-      call ftmrec(iunit, 25,
-     & 'COMMENT   This keyword was modified by fxmrec', status)
-      call ftmcrd(iunit, 'KY_IREC', 
-     & 'KY_MREC = ''This keyword was modified by fxmcrd''', status)
-      call ftmnam(iunit, 'KY_IKYS', 'NEWIKYS', status)
-
-      call ftmcom(iunit,'KY_IKYJ','This is a modified comment',
-     & status)
-      call ftmkyj(iunit, 'KY_IKYJ', 50, '&', status)
-      call ftmkyl(iunit, 'KY_IKYL', .false., '&', status)
-      call ftmkys(iunit, 'NEWIKYS', 'modified_string', '&', status)
-      call ftmkye(iunit, 'KY_IKYE', -12.3456, 4, '&', status)
-      odkey = -12.345678901234567D+00
-
-      call ftmkyd(iunit, 'KY_IKYD', odkey, 14, 
-     & 'modified comment', status)
-      call ftmkyf(iunit, 'KY_IKYF', -12.3456, 4, '&', status)
-      call ftmkyg(iunit,'KY_IKYG', odkey,13,'&',status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'After modifying the keywords... '
-      do ii = 25, 34
-          call ftgrec(iunit, ii, card, status)
-          write(*,'(1x,A)') card
-      end do
-      
-      if (status .gt. 0)then
-         write(*,'(1x,A)') ' ERROR modifying keywords '
-         go to 999
-      end if
-      
-C        ############################
-C        #  update keywords         #
-C        ############################
-      
-      call ftucrd(iunit, 'KY_MREC', 
-     & 'KY_UCRD = ''This keyword was updated by fxucrd''',
-     &         status)
-
-      call ftukyj(iunit, 'KY_IKYJ', 51, '&', status)
-      call ftukyl(iunit, 'KY_IKYL', .true., '&', status)
-      call ftukys(iunit, 'NEWIKYS', 'updated_string', '&', status)
-      call ftukye(iunit, 'KY_IKYE', -13.3456, 4, '&', status)
-      odkey = -13.345678901234567D+00
-
-      call ftukyd(iunit, 'KY_IKYD',odkey , 14, 
-     & 'modified comment', status)
-      call ftukyf(iunit, 'KY_IKYF', -13.3456, 4, '&', status)
-      call ftukyg(iunit, 'KY_IKYG', odkey, 13, '&', status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'After updating the keywords... '
-      do ii = 25, 34
-          call ftgrec(iunit, ii, card, status)
-          write(*,'(1x,A)') card
-      end do
-
-      if (status .gt. 0)then
-         write(*,'(1x,A)') ' ERROR modifying keywords '
-         go to 999
-      end if
-
-C     move to top of header and find keywords using wild cards 
-      call ftgrec(iunit, 0, card, status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)')
-     &  'Keywords found using wildcard search (should be 9)...'
-      nfound = -1
-91    nfound = nfound +1
-      call ftgnxk(iunit, inclist, 2, exclist, 2, card, status)
-      if (status .eq. 0)then
-          write(*,'(1x,A)') card
-          go to 91
-      end if
-
-      if (nfound .ne. 9)then
-          write(*,'(1x,A)')
-     &    'ERROR reading keywords using wildcards (ftgnxk)'
-         go to 999
-      end if
-      status = 0
-
-C        ############################
-C        #  create binary table     #
-C        ############################
-      
-      tform(1) = '15A'
-      tform(2) = '1L'
-      tform(3) = '16X'
-      tform(4) = '1B'
-      tform(5) = '1I'
-      tform(6) = '1J'
-      tform(7) = '1E'
-      tform(8) = '1D'
-      tform(9) = '1C'
-      tform(10)= '1M'
-
-      ttype(1) = 'Avalue'
-      ttype(2) = 'Lvalue'
-      ttype(3) = 'Xvalue'
-      ttype(4) = 'Bvalue'
-      ttype(5) = 'Ivalue'
-      ttype(6) = 'Jvalue'
-      ttype(7) = 'Evalue'
-      ttype(8) = 'Dvalue'
-      ttype(9) = 'Cvalue'
-      ttype(10)= 'Mvalue'
-
-      tunit(1) = ' '
-      tunit(2) = 'm**2'
-      tunit(3) = 'cm'
-      tunit(4) = 'erg/s'
-      tunit(5) = 'km/s'
-      tunit(6) = ' '
-      tunit(7) = ' '
-      tunit(8) = ' '
-      tunit(9) = ' '
-      tunit(10)= ' '
-
-      nrows = 21
-      tfields = 10
-      pcount = 0
-
-      call ftibin(iunit, nrows, tfields, ttype, tform, tunit, 
-     & binname, pcount, status)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A,I4)') 'ftibin status = ', status
-      call ftghdn(iunit, hdunum)
-      write(*,'(1x,A,I4)') 'HDU number = ', hdunum
-
-C get size and position in header, and reserve space for more keywords 
-      call ftghps(iunit, existkeys, keynum, status)
-      write(*,'(1x,A,I4,A,I4)') 'header contains ',existkeys,
-     & ' keywords located at keyword ', keynum
-
-      morekeys = 40
-      call fthdef(iunit, morekeys, status)
-      call ftghsp(iunit, existkeys, morekeys, status)
-      write(*,'(1x,A,I4,A,I4,A)') 'header contains ', existkeys,
-     &' keywords with room for ', morekeys,' more'
-
-C define null value for int cols 
-      call fttnul(iunit, 4, 99, status)   
-      call fttnul(iunit, 5, 99, status)
-      call fttnul(iunit, 6, 99, status)
-
-      call ftpkyj(iunit, 'TNULL4', 99, 'value for undefined pixels',
-     &  status)
-      call ftpkyj(iunit, 'TNULL5', 99, 'value for undefined pixels',
-     &  status)
-      call ftpkyj(iunit, 'TNULL6', 99, 'value for undefined pixels',
-     & status)
-
-      naxis = 3
-      naxes(1) = 1
-      naxes(2) = 2
-      naxes(3) = 8
-      call ftptdm(iunit, 3, naxis, naxes, status)
-
-      naxis = 0
-      naxes(1) = 0
-      naxes(2) = 0
-      naxes(3) = 0
-      call ftgtdm(iunit, 3, 3, naxis, naxes, status)
-      call ftgkys(iunit, 'TDIM3', iskey, comment, status)
-      write(*,'(1x,2A,4I4)') 'TDIM3 = ', iskey, naxis, naxes(1),
-     &      naxes(2), naxes(3)
-
-C force header to be scanned (not required) 
-      call ftrdef(iunit, status)  
-    
-C        ############################
-C        #  write data to columns   #
-C        ############################
-         
-C initialize arrays of values to write to table 
-      signval = -1
-      do ii = 1, 21
-          signval = signval * (-1)
-          boutarray(ii) = char(ii)
-          ioutarray(ii) = (ii) * signval
-          joutarray(ii) = (ii) * signval
-          koutarray(ii) = (ii) * signval
-          eoutarray(ii) = (ii) * signval
-          doutarray(ii) = (ii) * signval
-      end do
-
-      call ftpcls(iunit, 1, 1, 1, 3, onskey, status)  
-C write string values 
-      call ftpclu(iunit, 1, 4, 1, 1, status)  
-C write null value 
-
-      larray(1) = .false.
-      larray(2) =.true.
-      larray(3) = .false.
-      larray(4) = .false.
-      larray(5) =.true.
-      larray(6) =.true.
-      larray(7) = .false.
-      larray(8) = .false.
-      larray(9) = .false.
-      larray(10) =.true.
-      larray(11) =.true.
-      larray(12) = .true.
-      larray(13) = .false.
-      larray(14) = .false.
-      larray(15) =.false.
-      larray(16) =.false.
-      larray(17) = .true.
-      larray(18) = .true.
-      larray(19) = .true.
-      larray(20) = .true.
-      larray(21) =.false.
-      larray(22) =.false.
-      larray(23) =.false.
-      larray(24) =.false.
-      larray(25) =.false.
-      larray(26) = .true.
-      larray(27) = .true.
-      larray(28) = .true.
-      larray(29) = .true.
-      larray(30) = .true.
-      larray(31) =.false.
-      larray(32) =.false.
-      larray(33) =.false.
-      larray(34) =.false.
-      larray(35) =.false.
-      larray(36) =.false.
-
-C write bits
-      call ftpclx(iunit, 3, 1, 1, 36, larray, status) 
-
-C loop over cols 4 - 8 
-      do ii = 4, 8   
-          call ftpclb(iunit, ii, 1, 1, 2, boutarray, status)
-          if (status .eq. 412) status = 0
-
-          call ftpcli(iunit, ii, 3, 1, 2, ioutarray(3), status) 
-          if (status .eq. 412) status = 0
-
-          call ftpclj(iunit, ii, 5, 1, 2, koutarray(5), status) 
-          if (status .eq. 412) status = 0
-
-          call ftpcle(iunit, ii, 7, 1, 2, eoutarray(7), status)
-          if (status .eq. 412)status = 0
-
-          call ftpcld(iunit, ii, 9, 1, 2, doutarray(9), status)
-          if (status .eq. 412)status = 0
-
-C write null value 
-          call ftpclu(iunit, ii, 11, 1, 1, status)  
-      end do
-
-      call ftpclc(iunit,  9, 1, 1, 10, eoutarray, status)
-      call ftpclm(iunit, 10, 1, 1, 10, doutarray, status)
-
-C loop over cols 4 - 8 
-      do ii = 4, 8
-          bnul = char(13)
-          call ftpcnb(iunit, ii, 12, 1, 2, boutarray(12),bnul,status)
-          if (status .eq. 412) status = 0
-          inul=15
-          call ftpcni(iunit, ii, 14, 1, 2, ioutarray(14),inul,status) 
-          if (status .eq. 412) status = 0
-          call ftpcnj(iunit, ii, 16, 1, 2, koutarray(16), 17, status) 
-          if (status .eq. 412) status = 0
-          call ftpcne(iunit, ii, 18, 1, 2, eoutarray(18), 19.,status)
-          if (status .eq. 412) status = 0
-          dnul = 21.
-          call ftpcnd(iunit, ii, 20, 1, 2, doutarray(20),dnul,status)
-          if (status .eq. 412) status = 0
-      end do
-      
-C write logicals
-      call ftpcll(iunit, 2, 1, 1, 21, larray, status) 
-C write null value 
-      call ftpclu(iunit, 2, 11, 1, 1, status)  
-      write(*,'(1x,A,I4)') 'ftpcl_ status = ', status
-      if (status .gt. 0)go to 999
-      
-C        #########################################
-C        #  get information about the columns    #
-C        #########################################
-      
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)')
-     & 'Find the column numbers a returned status value'//
-     & ' of 237 is'
-      write(*,'(1x,A)') 
-     & 'expected and indicates that more than one column'//
-     & ' name matches'
-      write(*,'(1x,A)')'the input column name template.'//
-     & '  Status = 219 indicates that'
-      write(*,'(1x,A)') 'there was no matching column name.'
-
-      call ftgcno(iunit, 0, 'Xvalue', colnum, status)
-      write(*,'(1x,A,I4,A,I4)') 'Column Xvalue is number', colnum,
-     &' status =',status
-
-219   continue
-      if (status .ne. 219)then
-        call ftgcnn(iunit, 1, '*ue', colname, colnum, status)
-        write(*,'(1x,3A,I4,A,I4)') 'Column ',colname(1:6),' is number', 
-     &   colnum,' status = ',  status
-        go to 219
-      end if
-
-      status = 0
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'Information about each column: '
-
-      do ii = 1, tfields
-        call ftgtcl(iunit, ii, typecode, repeat, width, status)
-        call ftgbcl(iunit,ii,ttype,tunit,cval,repeat,scale,
-     &        zero, jnulval, tdisp, status)
-
-        write(*,'(1x,A,3I4,5A,2F8.2,I12,A)')
-     &  tform(ii)(1:3), typecode, repeat, width,' ',
-     &  ttype(1)(1:6),' ',tunit(1)(1:6), cval, scale, zero, jnulval,
-     &  tdisp(1:8)
-      end do
-
-      write(*,'(1x,A)') ' '
-
-C        ###############################################
-C        #  insert ASCII table before the binary table #
-C        ###############################################
-
-      call ftmrhd(iunit, -1, hdutype, status)
-      if (status .gt. 0)goto 999
-
-      tform(1) = 'A15'
-      tform(2) = 'I10'
-      tform(3) = 'F14.6'
-      tform(4) = 'E12.5'
-      tform(5) = 'D21.14'
-
-      ttype(1) = 'Name'
-      ttype(2) = 'Ivalue'
-      ttype(3) = 'Fvalue'
-      ttype(4) = 'Evalue'
-      ttype(5) = 'Dvalue'
-
-      tunit(1) = ' '
-      tunit(2) = 'm**2'
-      tunit(3) = 'cm'
-      tunit(4) = 'erg/s'
-      tunit(5) = 'km/s'
-
-      rowlen = 76
-      nrows = 11
-      tfields = 5
-
-      call ftitab(iunit, rowlen, nrows, tfields, ttype, tbcol, 
-     & tform, tunit, tblname, status)
-      write(*,'(1x,A,I4)') 'ftitab status = ', status
-      call ftghdn(iunit, hdunum)
-      write(*,'(1x,A,I4)') 'HDU number = ', hdunum
-
-C define null value for int cols 
-      call ftsnul(iunit, 1, 'null1', status)   
-      call ftsnul(iunit, 2, 'null2', status)
-      call ftsnul(iunit, 3, 'null3', status)
-      call ftsnul(iunit, 4, 'null4', status)
-      call ftsnul(iunit, 5, 'null5', status)
- 
-      call ftpkys(iunit, 'TNULL1', 'null1',
-     & 'value for undefined pixels', status)
-      call ftpkys(iunit, 'TNULL2', 'null2',
-     & 'value for undefined pixels', status)
-      call ftpkys(iunit, 'TNULL3', 'null3',
-     & 'value for undefined pixels', status)
-      call ftpkys(iunit, 'TNULL4', 'null4',
-     & 'value for undefined pixels', status)
-      call ftpkys(iunit, 'TNULL5', 'null5',
-     & 'value for undefined pixels', status)
-
-      if (status .gt. 0) goto 999
-      
-C        ############################
-C        #  write data to columns   #
-C        ############################
-           
-C initialize arrays of values to write to table 
-      do ii = 1,21     
-          boutarray(ii) = char(ii)
-          ioutarray(ii) = ii
-          joutarray(ii) = ii
-          eoutarray(ii) = ii
-          doutarray(ii) = ii
-      end do      
-
-C write string values 
-      call ftpcls(iunit, 1, 1, 1, 3, onskey, status)  
-C write null value 
-      call ftpclu(iunit, 1, 4, 1, 1, status)  
-
-      do ii = 2,5 
-C loop over cols 2 - 5       
-          call ftpclb(iunit, ii, 1, 1, 2, boutarray, status)  
-C char array 
-          if (status .eq. 412) status = 0
-             
-          call ftpcli(iunit, ii, 3, 1, 2, ioutarray(3), status)  
-C short array 
-          if (status .eq. 412) status = 0
-             
-          call ftpclj(iunit, ii, 5, 1, 2, joutarray(5), status)  
-C long array 
-          if (status .eq. 412)status = 0
-              
-          call ftpcle(iunit, ii, 7, 1, 2, eoutarray(7), status)  
-C float array 
-          if (status .eq. 412) status = 0
-             
-          call ftpcld(iunit, ii, 9, 1, 2, doutarray(9), status)  
-C double array 
-          if (status .eq. 412) status = 0
-
-          call ftpclu(iunit, ii, 11, 1, 1, status)  
-C write null value 
-      end do
-      write(*,'(1x,A,I4)') 'ftpcl_ status = ', status
-      write(*,'(1x,A)')' '
-
-C        ################################
-C        #  read data from ASCII table  #
-C        ################################
-      
-      call ftghtb(iunit, 99, rowlen, nrows, tfields, ttype, tbcol, 
-     &       tform, tunit, tblname, status)
-
-      write(*,'(1x,A,3I3,2A)')
-     & 'ASCII table: rowlen, nrows, tfields, extname:',
-     & rowlen, nrows, tfields,' ',tblname
-
-      do ii = 1,tfields
-        write(*,'(1x,A,I4,3A)') 
-     & ttype(ii)(1:7), tbcol(ii),' ',tform(ii)(1:7), tunit(ii)(1:7)
-      end do
-
-      nrows = 11
-      call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', inskey,
-     &   anynull, status)
-      bnul = char(99)
-      call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray,
-     & anynull, status)
-      inul = 99
-      call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray,
-     & anynull, status)
-      call ftgcvj(iunit, 3, 1, 1, nrows, 99, jinarray,
-     & anynull, status)
-      call ftgcve(iunit, 4, 1, 1, nrows, 99., einarray,
-     & anynull, status)
-      dnul = 99.
-      call ftgcvd(iunit, 5, 1, 1, nrows, dnul, dinarray,
-     & anynull, status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'Data values read from ASCII table: '
-      do ii = 1, nrows
-        jj = ichar(binarray(ii))
-        write(*,1011) inskey(ii), jj,
-     &   iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii)
-1011    format(1x,a15,3i3,1x,2f3.0)
-      end do
-
-      call ftgtbs(iunit, 1, 20, 78, uchars, status)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') uchars
-      call ftptbs(iunit, 1, 20, 78, uchars, status)
-      
-C        #########################################
-C        #  get information about the columns    #
-C        #########################################
-
-      call ftgcno(iunit, 0, 'name', colnum, status)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A,I4,A,I4)')
-     &  'Column name is number',colnum,' status = ', status
-
-2190  continue
-      if (status .ne. 219)then
-        if (status .gt. 0 .and. status .ne. 237)go to 999
-
-        call ftgcnn(iunit, 1, '*ue', colname, colnum, status)
-        write(*,'(1x,3A,I4,A,I4)')
-     & 'Column ',colname(1:6),' is number',colnum,' status = ',status
-        go to 2190
-      end if
-   
-      status = 0
-
-      do ii = 1, tfields       
-        call ftgtcl(iunit, ii, typecode, repeat, width, status)
-        call ftgacl(iunit, ii, ttype, tbcol,tunit,tform, 
-     &   scale,zero, nulstr, tdisp, status)
-
-        write(*,'(1x,A,3I4,2A,I4,2A,2F10.2,3A)')
-     & tform(ii)(1:7), typecode, repeat, width,' ',
-     &  ttype(1)(1:6), tbcol(1), ' ',tunit(1)(1:5),
-     &  scale, zero, ' ', nulstr(1:6), tdisp(1:2)
-
-      end do
-
-      write(*,'(1x,A)') ' '
-
-C        ###############################################
-C        #  test the insert/delete row/column routines #
-C        ###############################################
-      
-      call ftirow(iunit, 2, 3, status)
-      if (status .gt. 0) goto 999
-
-      nrows = 14
-      call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED',
-     & inskey,   anynull, status)
-      call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray,
-     & anynull, status)
-      call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray,
-     & anynull, status)
-      call ftgcvj(iunit, 3, 1, 1, nrows, 99, jinarray,
-     & anynull, status)
-      call ftgcve(iunit, 4, 1, 1, nrows, 99., einarray,
-     & anynull, status)
-      call ftgcvd(iunit, 5, 1, 1, nrows, dnul, dinarray,
-     & anynull, status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)')'Data values after inserting 3 rows after row 2:'
-      do ii = 1, nrows     
-        jj = ichar(binarray(ii))
-        write(*,1011) inskey(ii), jj,
-     &   iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii)
-      end do
-
-      call ftdrow(iunit, 10, 2, status)
-
-      nrows = 12
-      call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', inskey,  
-     & anynull, status)
-      call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray, anynull,
-     & status)
-      call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray, anynull,
-     & status)
-      call ftgcvj(iunit, 3, 1, 1, nrows, 99, jinarray, anynull,
-     & status)
-      call ftgcve(iunit, 4, 1, 1, nrows, 99., einarray, anynull,
-     & status)
-      call ftgcvd(iunit, 5, 1, 1, nrows, dnul, dinarray, anynull,
-     & status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'Data values after deleting 2 rows at row 10: '
-      do ii = 1, nrows    
-        jj = ichar(binarray(ii))
-        write(*,1011)  inskey(ii), jj,
-     &       iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii)
-      end do
-      call ftdcol(iunit, 3, status)
-
-      call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', inskey, 
-     &  anynull, status)
-      call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray, anynull,
-     & status)
-      call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray, anynull,
-     & status)
-      call ftgcve(iunit, 3, 1, 1, nrows, 99., einarray, anynull,
-     & status)
-      call ftgcvd(iunit, 4, 1, 1, nrows, dnul, dinarray, anynull,
-     & status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'Data values after deleting column 3: '
-      do ii = 1,nrows
-        jj = ichar(binarray(ii))
-        write(*,1012) inskey(ii), jj,
-     &       iinarray(ii), einarray(ii), dinarray(ii)
-1012    format(1x,a15,2i3,1x,2f3.0)
-
-      end do
-
-      call fticol(iunit, 5, 'INSERT_COL', 'F14.6', status)
-
-      call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', inskey,
-     &   anynull, status)
-      call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray, anynull,
-     & status)
-      call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray, anynull,
-     & status)
-      call ftgcve(iunit, 3, 1, 1, nrows, 99., einarray, anynull,
-     & status)
-      call ftgcvd(iunit, 4, 1, 1, nrows, dnul, dinarray, anynull,
-     & status)
-      call ftgcvj(iunit, 5, 1, 1, nrows, 99, jinarray, anynull,
-     & status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') ' Data values after inserting column 5: '
-      do ii = 1, nrows
-        jj = ichar(binarray(ii))
-        write(*,1013) inskey(ii), jj,
-     &       iinarray(ii), einarray(ii), dinarray(ii) , jinarray(ii)
-1013    format(1x,a15,2i3,1x,2f3.0,i2)
-
-      end do
-
-C        ################################
-C        #  read data from binary table #
-C        ################################
-      
-
-      call ftmrhd(iunit, 1, hdutype, status)
-      if (status .gt. 0)go to 999
-      call ftghdn(iunit, hdunum)
-      write(*,'(1x,A,I4)') 'HDU number = ', hdunum
-
-      call ftghsp(iunit, existkeys, morekeys, status)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)')'Moved to binary table'
-      write(*,'(1x,A,I4,A,I4,A)') 'header contains ',existkeys,
-     & ' keywords with room for ',morekeys,' more '
-
-      call ftghbn(iunit, 99, nrows, tfields, ttype, 
-     &        tform, tunit, binname, pcount, status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A,2I4,A,I4)') 
-     & 'Binary table: nrows, tfields, extname, pcount:',
-     &        nrows, tfields, binname, pcount
-
-      do ii = 1,tfields
-        write(*,'(1x,3A)') ttype(ii), tform(ii), tunit(ii)
-      end do
-
-      do ii = 1, 40
-          larray(ii) = .false.
-      end do
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'Data values read from binary table: '
-      write(*,'(1x,A)') ' Bit column (X) data values:   '
-
-      call ftgcx(iunit, 3, 1, 1, 36, larray, status)
-      write(*,1014) (larray(ii), ii = 1,40)
-1014  format(1x,8l1,' ',8l1,' ',8l1,' ',8l1,' ',8l1)
-
-      nrows = 21
-      do ii = 1, nrows
-        larray(ii) = .false.
-        xinarray(ii) = ' '
-        binarray(ii) = ' '
-        iinarray(ii) = 0 
-        kinarray(ii) = 0
-        einarray(ii) = 0. 
-        dinarray(ii) = 0.
-        cinarray(ii * 2 -1) = 0. 
-        minarray(ii * 2 -1) = 0.
-        cinarray(ii * 2 ) = 0. 
-        minarray(ii * 2 ) = 0.
-      end do      
-
-      write(*,'(1x,A)') '  '
-      call ftgcvs(iunit, 1, 4, 1, 1, ' ',  inskey,   anynull,status)
-      if (ichar(inskey(1)(1:1)) .eq. 0)inskey(1)=' '
-      write(*,'(1x,2A)') 'null string column value (should be blank):',
-     &        inskey(1)
-
-      call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED',  inskey,
-     &   anynull, status)
-      call ftgcl( iunit, 2, 1, 1, nrows, larray, status)
-      bnul = char(98)
-      call ftgcvb(iunit, 3, 1, 1,nrows,bnul, xinarray,anynull,status)
-      call ftgcvb(iunit, 4, 1, 1,nrows,bnul, binarray,anynull,status)
-      inul = 98
-      call ftgcvi(iunit, 5, 1, 1,nrows,inul, iinarray,anynull,status)
-      call ftgcvj(iunit, 6, 1, 1, nrows, 98, kinarray,anynull,status)
-      call ftgcve(iunit, 7, 1, 1, nrows, 98.,einarray,anynull,status)
-      dnul = 98.
-      call ftgcvd(iunit, 8, 1, 1, nrows,dnul,dinarray,anynull,status)
-      call ftgcvc(iunit, 9, 1, 1, nrows, 98.,cinarray,anynull,status)
-      call ftgcvm(iunit,10, 1, 1, nrows,dnul,minarray,anynull,status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'Read columns with ftgcv_: '
-      do ii = 1,nrows
-        jj = ichar(xinarray(ii))
-        jjj = ichar(binarray(ii))
-      write(*,1201)inskey(ii),larray(ii),jj,jjj,iinarray(ii),
-     & kinarray(ii), einarray(ii), dinarray(ii), cinarray(ii * 2 -1), 
-     &cinarray(ii * 2 ), minarray(ii * 2 -1), minarray(ii * 2 )
-      end do
-1201  format(1x,a14,l4,4i4,6f5.0)
-
-      do ii = 1, nrows
-        larray(ii) = .false.
-        xinarray(ii) = ' '
-        binarray(ii) = ' '
-        iinarray(ii) = 0 
-        kinarray(ii) = 0
-        einarray(ii) = 0. 
-        dinarray(ii) = 0.
-        cinarray(ii * 2 -1) = 0. 
-        minarray(ii * 2 -1) = 0.
-        cinarray(ii * 2 ) = 0. 
-        minarray(ii * 2 ) = 0.
-      end do      
-
-      call ftgcfs(iunit, 1, 1, 1, nrows, inskey,   larray2, anynull,
-     & status)
-C     put blanks in strings if they are undefined.  (contain nulls)
-      do ii = 1, nrows
-         if (larray2(ii))inskey(ii) = ' '
-      end do
-
-      call ftgcfl(iunit, 2, 1, 1, nrows, larray,   larray2, anynull,
-     & status)
-      call ftgcfb(iunit, 3, 1, 1, nrows, xinarray, larray2, anynull,
-     & status)
-      call ftgcfb(iunit, 4, 1, 1, nrows, binarray, larray2, anynull,
-     & status)
-      call ftgcfi(iunit, 5, 1, 1, nrows, iinarray, larray2, anynull,
-     & status)
-      call ftgcfj(iunit, 6, 1, 1, nrows, kinarray, larray2, anynull,
-     & status)
-      call ftgcfe(iunit, 7, 1, 1, nrows, einarray, larray2, anynull,
-     & status)
-      call ftgcfd(iunit, 8, 1, 1, nrows, dinarray, larray2, anynull,
-     & status)
-      call ftgcfc(iunit, 9, 1, 1, nrows, cinarray, larray2, anynull,
-     & status)
-      call ftgcfm(iunit, 10,1, 1, nrows, minarray, larray2, anynull,
-     & status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') ' Read columns with ftgcf_: '
-      do ii = 1, 10
-        jj = ichar(xinarray(ii))
-        jjj = ichar(binarray(ii))
-      write(*,1201)
-     & inskey(ii),larray(ii),jj,jjj,iinarray(ii),
-     & kinarray(ii), einarray(ii), dinarray(ii), cinarray(ii * 2 -1), 
-     & cinarray(ii * 2 ), minarray(ii * 2 -1), minarray(ii * 2)
-      end do
-
-      do ii = 11, 21
-C don't try to print the NaN values 
-        jj = ichar(xinarray(ii))
-        jjj = ichar(binarray(ii))
-        write(*,1201) inskey(ii), larray(ii), jj,
-     &    jjj, iinarray(ii)
-      end do
-      
-      call ftprec(iunit,'key_prec= '// 
-     &'''This keyword was written by f_prec'' / comment here',
-     & status)
-
-C        ###############################################
-C        #  test the insert/delete row/column routines #
-C        ###############################################
-      
-      call ftirow(iunit, 2, 3, status)
-         if (status .gt. 0) go to 999
-
-      nrows = 14
-      call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED',  inskey,
-     & anynull, status)
-      call ftgcvb(iunit, 4, 1, 1, nrows,bnul,binarray,anynull,status)
-      call ftgcvi(iunit, 5, 1, 1, nrows,inul,iinarray,anynull,status)
-      call ftgcvj(iunit, 6, 1, 1, nrows, 98, jinarray,anynull,status)
-      call ftgcve(iunit, 7, 1, 1, nrows, 98.,einarray,anynull,status)
-      call ftgcvd(iunit, 8, 1, 1, nrows,dnul,dinarray,anynull,status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)')'Data values after inserting 3 rows after row 2:'
-      do ii = 1, nrows
-        jj = ichar(binarray(ii))
-        write(*,1202)  inskey(ii), jj,
-     &      iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii)
-      end do      
-1202  format(1x,a14,3i4,2f5.0)
-
-      call ftdrow(iunit, 10, 2, status)
-          if (status .gt. 0)goto 999
-
-      nrows = 12
-      call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED',  inskey,
-     &   anynull, status)
-      call ftgcvb(iunit, 4, 1, 1, nrows,bnul,binarray,anynull,status)
-      call ftgcvi(iunit, 5, 1, 1, nrows,inul,iinarray,anynull,status)
-      call ftgcvj(iunit, 6, 1, 1, nrows, 98,jinarray,anynull,status)
-      call ftgcve(iunit, 7, 1, 1, nrows, 98.,einarray,anynull,status)
-      call ftgcvd(iunit, 8, 1, 1, nrows,dnul,dinarray,anynull,status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'Data values after deleting 2 rows at row 10: '
-      do ii = 1, nrows
-        jj = ichar(binarray(ii))
-        write(*,1202) inskey(ii), jj,
-     &       iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii)
-      end do
-
-      call ftdcol(iunit, 6, status)
-
-      call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED',  inskey,
-     &   anynull, status)
-      call ftgcvb(iunit, 4, 1, 1, nrows,bnul,binarray,anynull,status)
-      call ftgcvi(iunit, 5, 1, 1, nrows,inul,iinarray,anynull,status)
-      call ftgcve(iunit, 6, 1, 1, nrows, 98.,einarray,anynull,status)
-      call ftgcvd(iunit, 7, 1, 1, nrows,dnul,dinarray,anynull,status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'Data values after deleting column 6: '
-      do ii = 1, nrows
-        jj = ichar(binarray(ii))      
-        write(*,1203) inskey(ii), jj,
-     &       iinarray(ii), einarray(ii), dinarray(ii)
-1203  format(1x,a14,2i4,2f5.0)
-
-      end do
-      call fticol(iunit, 8, 'INSERT_COL', '1E', status)
-
-      call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED',  inskey,
-     &   anynull, status)
-      call ftgcvb(iunit, 4, 1, 1, nrows,bnul,binarray,anynull,status)
-      call ftgcvi(iunit, 5, 1, 1, nrows,inul,iinarray,anynull,status)
-      call ftgcve(iunit, 6, 1, 1, nrows, 98.,einarray,anynull,status)
-      call ftgcvd(iunit, 7, 1, 1, nrows,dnul,dinarray,anynull,status)
-      call ftgcvj(iunit, 8, 1, 1, nrows, 98,jinarray,anynull,status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 'Data values after inserting column 8: '
-      do ii = 1, nrows
-        jj = ichar(binarray(ii))
-        write(*,1204) inskey(ii), jj,
-     &    iinarray(ii), einarray(ii), dinarray(ii) , jinarray(ii)
-1204  format(1x,a14,2i4,2f5.0,i3)
-      end do
-      call ftpclu(iunit, 8, 1, 1, 10, status)
-
-      call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED',  inskey,
-     &   anynull, status)
-      call ftgcvb(iunit, 4,1,1,nrows,bnul,binarray,anynull,status)
-      call ftgcvi(iunit, 5,1,1,nrows,inul,iinarray,anynull,status)
-      call ftgcve(iunit, 6,1,1,nrows,98., einarray,anynull,status)
-      call ftgcvd(iunit, 7,1,1,nrows,dnul, dinarray,anynull,status)
-      call ftgcvj(iunit, 8,1,1,nrows,98, jinarray,anynull, status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)') 
-     &  'Values after setting 1st 10 elements in column 8 = null: '
-      do ii = 1, nrows
-        jj = ichar(binarray(ii))
-        write(*,1204) inskey(ii), jj,
-     &      iinarray(ii), einarray(ii), dinarray(ii) , jinarray(ii)
-      end do      
-
-C        ####################################################
-C        #  insert binary table following the primary array #
-C        ####################################################
-   
-      call ftmahd(iunit,  1, hdutype, status)
-
-      tform(1) = '15A'
-      tform(2) = '1L'
-      tform(3) = '16X'
-      tform(4) = '1B'
-      tform(5) = '1I'
-      tform(6) = '1J'
-      tform(7) = '1E'
-      tform(8) = '1D'
-      tform(9) = '1C'
-      tform(10)= '1M'
-
-      ttype(1) = 'Avalue'
-      ttype(2) = 'Lvalue'
-      ttype(3) = 'Xvalue'
-      ttype(4) = 'Bvalue'
-      ttype(5) = 'Ivalue'
-      ttype(6) = 'Jvalue'
-      ttype(7) = 'Evalue'
-      ttype(8) = 'Dvalue'
-      ttype(9) = 'Cvalue'
-      ttype(10)= 'Mvalue'
-
-      tunit(1)= ' '
-      tunit(2)= 'm**2'
-      tunit(3)= 'cm'
-      tunit(4)= 'erg/s'
-      tunit(5)= 'km/s'
-      tunit(6)= ' '
-      tunit(7)= ' '
-      tunit(8)= ' '
-      tunit(9)= ' '
-      tunit(10)= ' '
-
-      nrows = 20
-      tfields = 10
-      pcount = 0
-
-      call ftibin(iunit, nrows, tfields, ttype, tform, tunit, 
-     & binname, pcount, status)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A,I4)') 'ftibin status = ', status
-      call ftghdn(iunit, hdunum)
-      write(*,'(1x,A,I4)') 'HDU number = ', hdunum
-
-      call ftpkyj(iunit, 'TNULL4', 77, 
-     & 'value for undefined pixels', status)
-      call ftpkyj(iunit, 'TNULL5', 77, 
-     & 'value for undefined pixels', status)
-      call ftpkyj(iunit, 'TNULL6', 77, 
-     & 'value for undefined pixels', status)
-
-      call ftpkyj(iunit, 'TSCAL4', 1000, 'scaling factor', status)
-      call ftpkyj(iunit, 'TSCAL5', 1, 'scaling factor', status)
-      call ftpkyj(iunit, 'TSCAL6', 100, 'scaling factor', status)
-
-      call ftpkyj(iunit, 'TZERO4', 0, 'scaling offset', status)
-      call ftpkyj(iunit, 'TZERO5', 32768, 'scaling offset', status)
-      call ftpkyj(iunit, 'TZERO6', 100, 'scaling offset', status)
-
-      call fttnul(iunit, 4, 77, status)   
-C define null value for int cols 
-      call fttnul(iunit, 5, 77, status)
-      call fttnul(iunit, 6, 77, status)
-      
-C set scaling 
-      scale=1000.
-      zero = 0.
-      call fttscl(iunit, 4, scale, zero, status)   
-      scale=1.
-      zero = 32768.
-      call fttscl(iunit, 5, scale, zero, status)
-      scale=100.
-      zero = 100.
-      call fttscl(iunit, 6, scale, zero, status)
-
-C  for some reason, it is still necessary to call ftrdef at this point
-      call ftrdef(iunit,status)
-
-C        ############################
-C        #  write data to columns   #
-C        ############################
-           
-C initialize arrays of values to write to table 
- 
-      joutarray(1) = 0
-      joutarray(2) = 1000
-      joutarray(3) = 10000
-      joutarray(4) = 32768
-      joutarray(5) = 65535
-
-
-      do ii = 4,6
-      
-          call ftpclj(iunit, ii, 1, 1, 5, joutarray, status) 
-          if (status .eq. 412)then
-              write(*,'(1x,A,I4)') 'Overflow writing to column  ', ii
-              status = 0
-          end if
-
-          call ftpclu(iunit, ii, 6, 1, 1, status)  
-C write null value 
-      end do
-
-      do jj = 4,6  
-        call ftgcvj(iunit, jj, 1,1,6, -999,jinarray,anynull,status)
-        write(*,'(1x,6I6)') (jinarray(ii), ii=1,6)
-      end do
-
-      write(*,'(1x,A)') ' '
-      
-C turn off scaling, and read the unscaled values 
-      scale = 1.
-      zero = 0.
-      call fttscl(iunit, 4, scale, zero, status)   
-      call fttscl(iunit, 5, scale, zero, status)
-      call fttscl(iunit, 6, scale, zero, status)
-
-      do jj = 4,6
-        call ftgcvj(iunit, jj,1,1,6,-999,jinarray,anynull,status)       
-            write(*,'(1x,6I6)') (jinarray(ii), ii = 1,6)
-      end do
-
-      if (status .gt. 0)go to 999
-
-C        ######################################################
-C        #  insert image extension following the binary table #
-C        ######################################################
-      
-      bitpix = -32
-      naxis = 2
-      naxes(1) = 15
-      naxes(2) = 25
-      call ftiimg(iunit, bitpix, naxis, naxes, status)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A,I4)') 
-     & ' Create image extension: ftiimg status = ', status
-      call ftghdn(iunit, hdunum)
-      write(*,'(1x,A,I4)') 'HDU number = ', hdunum
-
-      do jj = 0,29
-        do ii = 0,18
-          imgarray(ii+1,jj+1) = (jj * 10) + ii
-        end do
-      end do
-
-      call ftp2di(iunit, 1, 19, naxes(1),naxes(2),imgarray,status)
-      write(*,'(1x,A)') ' '
-      write(*,'(1x,A,I4)')'Wrote whole 2D array: ftp2di status =',
-     &      status
-
-      do jj =1, 30
-        do ii = 1, 19
-          imgarray(ii,jj) = 0
-        end do        
-      end do
-      
-      call ftg2di(iunit,1,0,19,naxes(1),naxes(2),imgarray,anynull,
-     &       status)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A,I4)')'Read whole 2D array: ftg2di status =',status
-
-      do jj =1, 30
-        write (*,1301)(imgarray(ii,jj),ii=1,19)
-1301    format(1x,19I4)
-      end do
-
-        write(*,'(1x,A)') ' '
-      
-
-      do jj =1, 30
-        do ii = 1, 19
-          imgarray(ii,jj) = 0
-        end do        
-      end do
-      
-      do jj =0, 19
-        do ii = 0, 9
-          imgarray2(ii+1,jj+1) = (jj * (-10)) - ii
-        end do        
-      end do
-
-      fpixels(1) = 5
-      fpixels(2) = 5
-      lpixels(1) = 14
-      lpixels(2) = 14
-      call ftpssi(iunit, 1, naxis, naxes, fpixels, lpixels, 
-     &     imgarray2, status)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A,I4)')'Wrote subset 2D array: ftpssi status =',
-     & status
-
-      call ftg2di(iunit,1,0,19,naxes(1), naxes(2),imgarray,anynull,
-     &        status)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A,I4)')'Read whole 2D array: ftg2di status =',status
-
-      do jj =1, 30
-        write (*,1301)(imgarray(ii,jj),ii=1,19)
-      end do
-      write(*,'(1x,A)') ' '
-
-
-      fpixels(1) = 2
-      fpixels(2) = 5
-      lpixels(1) = 10
-      lpixels(2) = 8
-      inc(1) = 2
-      inc(2) = 3
-
-      do jj = 1,30    
-        do ii = 1, 19
-          imgarray(ii,jj) = 0
-        end do
-      end do
-      
-      call ftgsvi(iunit, 1, naxis, naxes, fpixels, lpixels, inc, 0,
-     &       imgarray, anynull, status)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A,I4)')
-     & 'Read subset of 2D array: ftgsvi status = ',status
-
-      write(*,'(1x,10I5)')(imgarray(ii,1),ii = 1,10)
-
-      
-C        ###########################################################
-C        #  insert another image extension                         #
-C        #  copy the image extension to primary array of tmp file. #
-C        #  then delete the tmp file, and the image extension      #
-C        ###########################################################
-      
-      bitpix = 16
-      naxis = 2
-      naxes(1) = 15
-      naxes(2) = 25
-      call ftiimg(iunit, bitpix, naxis, naxes, status)
-      write(*,'(1x,A)') ' '
-      write(*,'(1x,A,I4)')'Create image extension: ftiimg status =',
-     &   status
-      call ftrdef(iunit, status)
-      call ftghdn(iunit, hdunum)
-      write(*,'(1x,A,I4)') 'HDU number = ', hdunum
-
-
-      filename = 't1q2s3v4.tmp'
-      call ftinit(tmpunit, filename, 1, status)
-      write(*,'(1x,A,I4)')'Create temporary file: ftinit status = ',
-     & status
-
-      call ftcopy(iunit, tmpunit, 0, status)
-      write(*,'(1x,A)') 
-     &  'Copy image extension to primary array of tmp file.'
-      write(*,'(1x,A,I4)')'ftcopy status = ',status
-
-
-      call ftgrec(tmpunit, 1, card, status)
-      write(*,'(1x,A)')  card
-      call ftgrec(tmpunit, 2, card, status)
-      write(*,'(1x,A)')  card
-      call ftgrec(tmpunit, 3, card, status)
-      write(*,'(1x,A)')  card
-      call ftgrec(tmpunit, 4, card, status)
-      write(*,'(1x,A)')  card
-      call ftgrec(tmpunit, 5, card, status)
-      write(*,'(1x,A)')  card
-      call ftgrec(tmpunit, 6, card, status)
-      write(*,'(1x,A)')  card
-
-      call ftdelt(tmpunit, status)
-      write(*,'(1x,A,I4)')'Delete the tmp file: ftdelt status =',status
-      call ftdhdu(iunit, hdutype, status)
-      write(*,'(1x,A,2I4)')
-     &  'Delete the image extension hdutype, status =',
-     &         hdutype, status
-      call ftghdn(iunit, hdunum)
-      write(*,'(1x,A,I4)') 'HDU number = ', hdunum
-
-      
-C        ###########################################################
-C        #  append bintable extension with variable length columns #
-C        ###########################################################
-      
-      call ftcrhd(iunit, status)
-      write(*,'(1x,A,I4)') 'ftcrhd status = ', status
-
-      tform(1)= '1PA'
-      tform(2)= '1PL'
-      tform(3)= '1PB' 
-C Fortran FITSIO doesn't support  1PX 
-      tform(4)= '1PB'
-      tform(5)= '1PI'
-      tform(6)= '1PJ'
-      tform(7)= '1PE'
-      tform(8)= '1PD'
-      tform(9)= '1PC'
-      tform(10)= '1PM'
-
-      ttype(1)= 'Avalue'
-      ttype(2)= 'Lvalue'
-      ttype(3)= 'Xvalue'
-      ttype(4)= 'Bvalue'
-      ttype(5)= 'Ivalue'
-      ttype(6)= 'Jvalue'
-      ttype(7)= 'Evalue'
-      ttype(8)= 'Dvalue'
-      ttype(9)= 'Cvalue'
-      ttype(10)= 'Mvalue'
-
-      tunit(1)= ' '
-      tunit(2)= 'm**2'
-      tunit(3)= 'cm'
-      tunit(4)= 'erg/s'
-      tunit(5)= 'km/s'
-      tunit(6)= ' '
-      tunit(7)= ' '
-      tunit(8)= ' '
-      tunit(9)= ' '
-      tunit(10)= ' '
-
-      nrows = 20
-      tfields = 10
-      pcount = 0
-
-      call ftphbn(iunit, nrows, tfields, ttype, tform, 
-     & tunit, binname, pcount, status)
-      write(*,'(1x,A,I4)')'Variable length arrays: ftphbn status =',
-     & status
-      call ftpkyj(iunit, 'TNULL4', 88, 'value for undefined pixels',
-     & status)
-      call ftpkyj(iunit, 'TNULL5', 88, 'value for undefined pixels',
-     & status)
-      call ftpkyj(iunit, 'TNULL6', 88, 'value for undefined pixels',
-     & status)
-
-C        ############################
-C        #  write data to columns   #
-C        ############################
-            
-C initialize arrays of values to write to table 
-      iskey='abcdefghijklmnopqrst'
-
-      do ii = 1, 20
-      
-          boutarray(ii) = char(ii)
-          ioutarray(ii) = ii
-          joutarray(ii) = ii
-          eoutarray(ii) = ii
-          doutarray(ii) = ii
-      end do
-
-      larray(1) = .false.
-      larray(2) = .true.
-      larray(3) = .false.
-      larray(4) = .false.
-      larray(5) = .true.
-      larray(6) = .true.
-      larray(7) = .false.
-      larray(8) = .false.
-      larray(9) = .false.
-      larray(10) = .true.
-      larray(11) = .true.
-      larray(12) = .true.
-      larray(13) = .false.
-      larray(14) = .false.
-      larray(15) = .false.
-      larray(16) = .false.
-      larray(17) = .true.
-      larray(18) = .true.
-      larray(19) = .true.
-      larray(20) = .true.
-
-C      inskey(1) = iskey(1:1)
-      inskey(1) = ' '
-
-        call ftpcls(iunit, 1, 1, 1, 1, inskey, status)  
-C write string values 
-        call ftpcll(iunit, 2, 1, 1, 1, larray, status)  
-C write logicals 
-        call ftpclx(iunit, 3, 1, 1, 1, larray, status)  
-C write bits 
-        call ftpclb(iunit, 4, 1, 1, 1, boutarray, status)
-        call ftpcli(iunit, 5, 1, 1, 1, ioutarray, status) 
-        call ftpclj(iunit, 6, 1, 1, 1, joutarray, status) 
-        call ftpcle(iunit, 7, 1, 1, 1, eoutarray, status)
-        call ftpcld(iunit, 8, 1, 1, 1, doutarray, status)
-
-      do ii = 2, 20   
-C loop over rows 1 - 20 
-      
-        inskey(1) =  iskey(1:ii)
-        call ftpcls(iunit, 1, ii, 1, ii, inskey, status)  
-C write string values 
-
-        call ftpcll(iunit, 2, ii, 1, ii, larray, status)  
-C write logicals 
-        call ftpclu(iunit, 2, ii, ii-1, 1, status)
-
-        call ftpclx(iunit, 3, ii, 1, ii, larray, status)  
-C write bits 
-
-        call ftpclb(iunit, 4, ii, 1, ii, boutarray, status)
-        call ftpclu(iunit, 4, ii, ii-1, 1, status)
-
-        call ftpcli(iunit, 5, ii, 1, ii, ioutarray, status) 
-        call ftpclu(iunit, 5, ii, ii-1, 1, status)
-
-        call ftpclj(iunit, 6, ii, 1, ii, joutarray, status) 
-        call ftpclu(iunit, 6, ii, ii-1, 1, status)
-
-        call ftpcle(iunit, 7, ii, 1, ii, eoutarray, status)
-        call ftpclu(iunit, 7, ii, ii-1, 1, status)
-
-        call ftpcld(iunit, 8, ii, 1, ii, doutarray, status)
-        call ftpclu(iunit, 8, ii, ii-1, 1, status)
-      end do
-
-C     it is no longer necessary to update the PCOUNT keyword;
-C     FITSIO now does this automatically when the HDU is closed.
-C     call ftmkyj(iunit,'PCOUNT',4446, '&',status)
-      write(*,'(1x,A,I4)') 'ftpcl_ status = ', status
-
-C        #################################
-C        #  close then reopen this HDU   #
-C        #################################
-
-       call ftmrhd(iunit, -1, hdutype, status)
-       call ftmrhd(iunit,  1, hdutype, status)
-
-C        #############################
-C        #  read data from columns   #
-C        #############################
-      
-
-      call ftgkyj(iunit, 'PCOUNT', pcount, comm, status)
-      write(*,'(1x,A,I4)') 'PCOUNT = ', pcount
-      
-C initialize the variables to be read 
-      inskey(1) =' '
-      iskey = ' '
-
-      do jj = 1, ii
-          larray(jj) = .false.
-          boutarray(jj) = char(0)
-          ioutarray(jj) = 0
-          joutarray(jj) = 0
-          eoutarray(jj) = 0
-          doutarray(jj) = 0
-      end do      
-
-      call ftghdn(iunit, hdunum)
-      write(*,'(1x,A,I4)') 'HDU number = ', hdunum
-
-      do ii = 1, 20   
-C loop over rows 1 - 20 
-      
-        do jj = 1, ii
-          larray(jj) = .false.
-          boutarray(jj) = char(0)
-          ioutarray(jj) = 0
-          joutarray(jj) = 0
-          eoutarray(jj) = 0
-          doutarray(jj) = 0
-        end do      
-
-        call ftgcvs(iunit, 1, ii, 1,1,iskey,inskey,anynull,status)
-        write(*,'(1x,2A,I4)') 'A  ', inskey(1), status
-
-        call ftgcl( iunit, 2, ii, 1, ii, larray, status) 
-        write(*,1400)'L',status,(larray(jj),jj=1,ii)
-1400    format(1x,a1,i3,20l3)
-1401    format(1x,a1,21i3)
-
-        call ftgcx(iunit, 3, ii, 1, ii, larray, status)
-        write(*,1400)'X',status,(larray(jj),jj=1,ii)
-
-        bnul = char(99)
-        call ftgcvb(iunit, 4, ii, 1,ii,bnul,boutarray,anynull,status)
-        do jj = 1,ii
-          jinarray(jj) = ichar(boutarray(jj))
-        end do
-        write(*,1401)'B',(jinarray(jj),jj=1,ii),status
-
-        inul = 99
-        call ftgcvi(iunit, 5, ii, 1,ii,inul,ioutarray,anynull,status)
-        write(*,1401)'I',(ioutarray(jj),jj=1,ii),status
-
-        call ftgcvj(iunit, 6, ii, 1, ii,99,joutarray,anynull,status)
-        write(*,1401)'J',(joutarray(jj),jj=1,ii),status
-
-        call ftgcve(iunit, 7, ii, 1,ii,99.,eoutarray,anynull,status)
-        estatus=status
-        write(*,1402)'E',(eoutarray(jj),jj=1,ii),estatus
-1402    format(1x,a1,1x,21f3.0)
-
-        dnul = 99.
-        call ftgcvd(iunit, 8, ii,1,ii,dnul,doutarray,anynull,status)
-        estatus=status
-        write(*,1402)'D',(doutarray(jj),jj=1,ii),estatus
-
-        call ftgdes(iunit, 8, ii, repeat, offset, status)
-        write(*,'(1x,A,2I5)')'Column 8 repeat and offset =',
-     &       repeat,offset
-      end do
-
-C        #####################################
-C        #  create another image extension   #
-C        #####################################
-      
-
-      bitpix = 32
-      naxis = 2
-      naxes(1) = 10
-      naxes(2) = 2
-      npixels = 20
- 
-      call ftiimg(iunit, bitpix, naxis, naxes, status)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A,I4)')'Create image extension: ftiimg status =',
-     &       status
-      
-C initialize arrays of values to write to primary array 
-      do ii = 1, npixels
-          boutarray(ii) = char(ii * 2 -2)
-          ioutarray(ii) = ii * 2 -2
-          joutarray(ii) = ii * 2 -2
-          koutarray(ii) = ii * 2 -2
-          eoutarray(ii) = ii * 2 -2
-          doutarray(ii) = ii * 2 -2
-      end do      
-
-C write a few pixels with each datatype 
-      call ftpprb(iunit, 1, 1,  2, boutarray(1),  status)
-      call ftppri(iunit, 1, 3,  2, ioutarray(3),  status)
-      call ftpprj(iunit, 1, 5,  2, koutarray(5),  status)
-      call ftppri(iunit, 1, 7,  2, ioutarray(7),  status)
-      call ftpprj(iunit, 1, 9,  2, joutarray(9),  status)
-      call ftppre(iunit, 1, 11, 2, eoutarray(11), status)
-      call ftpprd(iunit, 1, 13, 2, doutarray(13), status)
-      write(*,'(1x,A,I4)') 'ftppr status = ', status
-
-      
-C read back the pixels with each datatype 
-      bnul = char(0)
-      inul = 0
-      knul = 0
-      jnul = 0
-      enul = 0.
-      dnul = 0.
-
-      call ftgpvb(iunit, 1,  1,  14, bnul, binarray, anynull, status)
-      call ftgpvi(iunit, 1,  1,  14, inul, iinarray, anynull, status)
-      call ftgpvj(iunit, 1,  1,  14, knul, kinarray, anynull, status)
-      call ftgpvj(iunit, 1,  1,  14, jnul, jinarray, anynull, status)
-      call ftgpve(iunit, 1,  1,  14, enul, einarray, anynull, status)
-      call ftgpvd(iunit, 1,  1,  14, dnul, dinarray, anynull, status)
-
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)')
-     &   'Image values written with ftppr and read with ftgpv:'
-      npixels = 14
-      do jj = 1,ii
-          joutarray(jj) = ichar(binarray(jj))
-      end do
-
-      write(*,1501)(joutarray(ii),ii=1,npixels),anynull,'(byte)'
-1501  format(1x,14i3,l3,1x,a)
-      write(*,1501)(iinarray(ii),ii=1,npixels),anynull,'(short)'
-      write(*,1501)(kinarray(ii),ii=1,npixels),anynull,'(int)'
-      write(*,1501)(jinarray(ii),ii=1,npixels),anynull,'(long)'
-      write(*,1502)(einarray(ii),ii=1,npixels),anynull,'(float)'
-      write(*,1502)(dinarray(ii),ii=1,npixels),anynull,'(double)'
-1502  format(2x,14f3.0,l2,1x,a)
-
-C      ##########################################
-C      #  test world coordinate system routines #
-C      ##########################################
-
-      xrval = 45.83D+00
-      yrval =  63.57D+00
-      xrpix =  256.D+00
-      yrpix =  257.D+00
-      xinc =   -.00277777D+00
-      yinc =   .00277777D+00
-
-C     write the WCS keywords 
-C     use example values from the latest WCS document 
-      call ftpkyd(iunit, 'CRVAL1', xrval, 10, 'comment', status)
-      call ftpkyd(iunit, 'CRVAL2', yrval, 10, 'comment', status)
-      call ftpkyd(iunit, 'CRPIX1', xrpix, 10, 'comment', status)
-      call ftpkyd(iunit, 'CRPIX2', yrpix, 10, 'comment', status)
-      call ftpkyd(iunit, 'CDELT1', xinc, 10, 'comment', status)
-      call ftpkyd(iunit, 'CDELT2', yinc, 10, 'comment', status)
-C     call ftpkyd(iunit, 'CROTA2', rot, 10, 'comment', status) 
-      call ftpkys(iunit, 'CTYPE1', xctype, 'comment', status)
-      call ftpkys(iunit, 'CTYPE2', yctype, 'comment', status)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A,I4)')'Wrote WCS keywords status =', status
-
-C     reset value, to make sure they are reread correctly
-      xrval =  0.D+00
-      yrval =  0.D+00
-      xrpix =  0.D+00
-      yrpix =  0.D+00
-      xinc =   0.D+00
-      yinc =   0.D+00
-      rot =    67.D+00
-
-      call ftgics(iunit, xrval, yrval, xrpix,
-     &      yrpix, xinc, yinc, rot, ctype, status)
-      write(*,'(1x,A,I4)')'Read WCS keywords with ftgics status =',
-     &  status
-
-      xpix = 0.5D+00
-      ypix = 0.5D+00
-
-      call ftwldp(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,
-     &     rot,ctype, xpos, ypos,status)
-
-      write(*,'(1x,A,2f8.3)')'  CRVAL1, CRVAL2 =', xrval,yrval
-      write(*,'(1x,A,2f8.3)')'  CRPIX1, CRPIX2 =', xrpix,yrpix
-      write(*,'(1x,A,2f12.8)')'  CDELT1, CDELT2 =', xinc,yinc
-      write(*,'(1x,A,f8.3,2A)')'  Rotation =',rot,' CTYPE =',ctype
-      write(*,'(1x,A,I4)')'Calculated sky coord. with ftwldp status =',
-     &   status
-      write(*,6501)xpix,ypix,xpos,ypos
-6501  format('  Pixels (',f10.6,f10.6,') --> (',f10.6,f10.6,') Sky')
-
-      call ftxypx(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,
-     &     rot,ctype, xpix, ypix,status)
-      write(*,'(1x,A,I4)')
-     & 'Calculated pixel coord. with ftxypx status =', status
-      write(*,6502)xpos,ypos,xpix,ypix
-6502  format('  Sky (',f10.6,f10.6,') --> (',f10.6,f10.6,') Pixels')
-
-     
-C        ######################################
-C        #  append another ASCII table        #
-C        ######################################
-      
-
-      tform(1)= 'A15'
-      tform(2)= 'I11'
-      tform(3)= 'F15.6'
-      tform(4)= 'E13.5'
-      tform(5)= 'D22.14'
-
-      tbcol(1)= 1
-      tbcol(2)= 17
-      tbcol(3)= 29
-      tbcol(4)= 45
-      tbcol(5)= 59
-      rowlen = 80
-
-      ttype(1)= 'Name'
-      ttype(2)= 'Ivalue'
-      ttype(3)= 'Fvalue'
-      ttype(4)= 'Evalue'
-      ttype(5)= 'Dvalue'
-
-      tunit(1)= ' '
-      tunit(2)= 'm**2'
-      tunit(3)= 'cm'
-      tunit(4)= 'erg/s'
-      tunit(5)= 'km/s'
-
-      nrows = 11
-      tfields = 5
-      tblname = 'new_table'
-
-      call ftitab(iunit, rowlen, nrows, tfields, ttype, tbcol, 
-     & tform, tunit, tblname, status)
-      write(*,'(1x,A)') ' '
-      write(*,'(1x,A,I4)') 'ftitab status = ', status
-
-      call ftpcls(iunit, 1, 1, 1, 3, onskey, status)  
-C write string values 
-
-C initialize arrays of values to write to primary array 
-      
-      do ii = 1,npixels
-          boutarray(ii) = char(ii * 3 -3)
-          ioutarray(ii) = ii * 3 -3
-          joutarray(ii) = ii * 3 -3
-          koutarray(ii) = ii * 3 -3
-          eoutarray(ii) = ii * 3 -3
-          doutarray(ii) = ii * 3 -3
-      end do
-
-      do ii = 2,5 
-C loop over cols 2 - 5 
-      
-          call ftpclb(iunit,  ii, 1, 1, 2, boutarray,  status) 
-          call ftpcli(iunit,  ii, 3, 1, 2,ioutarray(3),status)
-          call ftpclj(iunit,  ii, 5, 1, 2,joutarray(5),status)
-          call ftpcle(iunit,  ii, 7, 1, 2,eoutarray(7),status)
-          call ftpcld(iunit,  ii, 9, 1, 2,doutarray(9),status)
-      end do
-      write(*,'(1x,A,I4)') 'ftpcl status = ', status
-      
-C read back the pixels with each datatype 
-      call ftgcvb(iunit,   2, 1, 1, 10, bnul, binarray,anynull,
-     & status)
-      call ftgcvi(iunit,  2, 1, 1, 10, inul, iinarray,anynull,
-     & status)
-      call ftgcvj(iunit,    3, 1, 1, 10, knul, kinarray,anynull,
-     & status)
-      call ftgcvj(iunit,    3, 1, 1, 10, jnul, jinarray,anynull,
-     & status)
-      call ftgcve(iunit,   4, 1, 1, 10, enul, einarray,anynull,
-     & status)
-      call ftgcvd(iunit, 5, 1, 1, 10, dnul, dinarray,anynull,
-     & status)
-
-      write(*,'(1x,A)') 
-     &'Column values written with ftpcl and read with ftgcl: '
-      npixels = 10
-      do ii = 1,npixels
-         joutarray(ii) = ichar(binarray(ii))
-      end do
-      write(*,1601)(joutarray(ii),ii = 1, npixels),anynull,'(byte) '
-      write(*,1601)(iinarray(ii),ii = 1, npixels),anynull,'(short) '
-      write(*,1601)(kinarray(ii),ii = 1, npixels),anynull,'(int) '
-      write(*,1601)(jinarray(ii),ii = 1, npixels),anynull,'(long) '
-      write(*,1602)(einarray(ii),ii = 1, npixels),anynull,'(float) '
-      write(*,1602)(dinarray(ii),ii = 1, npixels),anynull,'(double) '
-1601  format(1x,10i3,l3,1x,a)
-1602  format(2x,10f3.0,l2,1x,a)
-      
-C        ###########################################################
-C        #  perform stress test by cycling thru all the extensions #
-C        ###########################################################
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A)')'Repeatedly move to the 1st 4 HDUs of the file: '
-
-      do ii = 1,10
-        call ftmahd(iunit,  1, hdutype, status)
-        call ftghdn(iunit, hdunum)
-        call ftmrhd(iunit,  1, hdutype, status)
-        call ftghdn(iunit, hdunum)
-        call ftmrhd(iunit,  1, hdutype, status)
-        call ftghdn(iunit, hdunum)
-        call ftmrhd(iunit,  1, hdutype, status)
-        call ftghdn(iunit, hdunum)
-        call ftmrhd(iunit, -1, hdutype, status)
-        call ftghdn(iunit, hdunum)
-        if (status .gt. 0) go to 999
-      end do
-      
-      write(*,'(1x,A)') ' '
-
-      checksum = 1234567890.D+00
-      call ftesum(checksum, .false., asciisum)
-      write(*,'(1x,A,F13.1,2A)')'Encode checksum: ',checksum,' -> ',
-     &  asciisum
-      checksum = 0
-      call ftdsum(asciisum, 0, checksum)
-      write(*,'(1x,3A,F13.1)') 'Decode checksum: ',asciisum,' -> ',
-     & checksum
-
-      call ftpcks(iunit, status)
-
-C         don't print the CHECKSUM value because it is different every day
-C         because the current date is in the comment field.
-
-         call ftgcrd(iunit, 'CHECKSUM', card, status)
-C         write(*,'(1x,A)') card
-
-      call ftgcrd(iunit, 'DATASUM', card, status)
-      write(*,'(1x,A)') card(1:22)
-
-      call ftgcks(iunit, datsum, checksum, status)
-      write(*,'(1x,A,F13.1,I4)') 'ftgcks data checksum, status = ',
-     &         datsum, status
-
-      call ftvcks(iunit, datastatus, hdustatus, status) 
-      write(*,'(1x,A,3I4)')'ftvcks datastatus, hdustatus, status =  ',
-     &          datastatus, hdustatus, status
- 
-      call ftprec(iunit,
-     & 'new_key = ''written by fxprec'' / to change checksum',status)
-      call ftucks(iunit, status)
-      write(*,'(1x,A,I4)') 'ftupck status = ', status
-
-      call ftgcrd(iunit, 'DATASUM', card, status)
-      write(*,'(1x,A)') card(1:22)
-      call ftvcks(iunit, datastatus, hdustatus, status) 
-      write(*,'(1x,A,3I4)') 'ftvcks datastatus, hdustatus, status =  ',
-     &          datastatus, hdustatus, status
- 
-C        delete the checksum keywords, so that the FITS file is always
-C        the same, regardless of the date of when testprog is run.
-      
-      call ftdkey(iunit, 'CHECKSUM', status)
-      call ftdkey(iunit, 'DATASUM',  status)
-
-
-C        ############################
-C        #  close file and quit     #
-C        ############################
-      
-
-999   continue  
-C jump here on error 
-
-      call ftclos(iunit, status) 
-      write(*,'(1x,A,I4)') 'ftclos status = ', status
-      write(*,'(1x,A)')' '
-
-      write(*,'(1x,A)')
-     &  'Normally, there should be 8 error messages on the'
-      write(*,'(1x,A)') 'stack all regarding ''numerical overflows'':'
-
-      call ftgmsg(errmsg)
-      nmsg = 0
-
-998   continue
-      if (errmsg .ne. ' ')then      
-          write(*,'(1x,A)') errmsg
-          nmsg = nmsg + 1
-          call ftgmsg(errmsg)
-          go to 998
-      end if
-
-      if (nmsg .ne. 8)write(*,'(1x,A)')
-     & ' WARNING: Did not find the expected 8 error messages!'
-
-      call ftgerr(status, errmsg)
-      write(*,'(1x,A)')' '
-      write(*,'(1x,A,I4,2A)') 'Status =', status,': ', errmsg(1:50)
-      end
diff --git a/src/external/OpenGR/3rdparty/cfitsio/testf77.out b/src/external/OpenGR/3rdparty/cfitsio/testf77.out
deleted file mode 100644
index 323ad59c2..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/testf77.out
+++ /dev/null
@@ -1,746 +0,0 @@
- FITSIO TESTPROG
-  
- Try opening then closing a nonexistent file: 
-   ftopen iunit, status (expect an error) =  15 104
-   ftclos status =  104
-  
- ftinit create new file status =    0
-  
- test writing of long string keywords: 
- 123456789012345678901234567890123456789012345678901234567890123456789012345   
- '12345678901234567890123456789012345678901234567890123456789012345678'        
- 1234567890123456789012345678901234567890123456789012345678901234'6789012345   
- '1234567890123456789012345678901234567890123456789012345678901234''67'        
- 1234567890123456789012345678901234567890123456789012345678901234''789012345   
- '1234567890123456789012345678901234567890123456789012345678901234'''''        
- 1234567890123456789012345678901234567890123456789012345678901234567'9012345   
- '1234567890123456789012345678901234567890123456789012345678901234567'         
- Wrote all Keywords successfully 
- ftflus status =    0
-  
- HDU number =    1
- Values read back from primary array (99 = null pixel)
- The 1st, and every 4th pixel should be undefined: 
-  99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  T (ftgpvb) 
-  99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  T (ftgpvi) 
-  99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  T (ftgpvj) 
-  99. 2. 3.99. 5. 6. 7.99. 9.10.11.99.13.14.15.99.17.18.19.99. T (ftgpve) 
-  99. 2. 3.99. 5. 6. 7.99. 9.10.11.99.13.14.15.99.17.18.19.99. T (ftgpvd) 
-   0  2  3  0  5  6  7  0  9 10 11  0 13 14 15  0 17 18 19  0  T (ftgpfb)
-   0  2  3  0  5  6  7  0  9 10 11  0 13 14 15  0 17 18 19  0  T (ftgpfi)
-   0  2  3  0  5  6  7  0  9 10 11  0 13 14 15  0 17 18 19  0  T (ftgpfj)
-   0. 2. 3. 0. 5. 6. 7. 0. 9.10.11. 0.13.14.15. 0.17.18.19. 0. T (ftgpfe)
-   0. 2. 3. 0. 5. 6. 7. 0. 9.10.11. 0.13.14.15. 0.17.18.19. 0. T (ftgpfd)
-  
- Closed then reopened the FITS file 10 times.
-  
- HDU number =    1
- Read back keywords: 
- simple, bitpix, naxis, naxes =    T  32   2  10   2
-   pcount, gcount, extend =    0   1   T
- KEY_PREC= 'This keyword was written by fxprec' / comment goes here            
- KEY_PREC 'This keyword was written by fxprec comment goes here   
- KEY_PREC= 'This keyword was written by fxprec' / comment goes here            
- KY_PKNS1 :'first string' :fxpkns comment  
- KEY_PKYS :value_string         :fxpkys comment     0
- KEY_PKYL :   T:fxpkyl comment     0
- KEY_PKYJ :  11:fxpkyj comment     0
- KEY_PKYE :    11.00000:fxpkyj comment     0
- KEY_PKYD :    11.00000:fxpkyj comment     0
- KEY_PKYS :value_string         :fxpkys comment     0
- KEY_PKYL :   T:fxpkyl comment     0
- KEY_PKYJ :  11:fxpkyj comment     0
- KEY_PKYE :    13.13131:fxpkye comment     0
- KEY_PKYD :    15.15152:fxpkyd comment     0
- KEY_PKYF :    12.12121:fxpkyf comment     0
- KEY_PKYE :    13.13131:fxpkye comment     0
- KEY_PKYG : 14.141414141414:fxpkyg comment     0
- KEY_PKYD : 15.151515151515:fxpkyd comment     0
- KEY_PKYT  :  12345678:0.12345678901235fxpkyt comment     0
- KEY_PKYJ :  11:[km/s/Mpc] fxpkyj comment                0
- keyword unit=km/s/Mpc          
- KEY_PKYJ :  11:fxpkyj comment                           0
- keyword unit=                  
- KEY_PKYJ :  11:[feet/second/second] fxpkyj comment      0
- keyword unit=feet/second/second
- KEY_PKLS long string value = This is a very long string value that is continued
-  over more than one keyword.                                          
- header contains   61 keywords; located at keyword   23
- ftgkns: first string  second string               
- ftgknl:    T   F   T
- ftgknj:   11  12  13
- ftgkne:   13.13131  14.14141  15.15152
- ftgknd:   15.15152  16.16162  17.17172
-  
- Before deleting the HISTORY and DATE keywords...
- COMMENT 
- HISTORY 
- DATE    
- KY_PKNS1
-  
- After deleting the keywords... 
- COMMENT This keyword was written by fxpcom.                                   
- KY_PKNS1= 'first string'       / fxpkns comment                               
-  
- After inserting the keywords... 
- COMMENT   continued over multiple keywords.  The HEASARC convention uses the &
- KY_IREC = 'This keyword inserted by fxirec'                                   
- KY_IKYS = 'insert_value_string' / ikys comment                                
- KY_IKYJ =                   49 / ikyj comment                                 
- KY_IKYL =                    T / ikyl comment                                 
- KY_IKYE =           1.2346E+01 / ikye comment                                 
- KY_IKYD = 1.23456789012346E+01 / ikyd comment                                 
- KY_IKYF =              12.3456 / ikyf comment                                 
- KY_IKYG =     12.3456789012346 / ikyg comment                                 
- COMMENT   character at the end of each substring which is then continued      
-  
- After modifying the keywords... 
- COMMENT   This keyword was modified by fxmrec                                 
- KY_MREC = 'This keyword was modified by fxmcrd'                               
- NEWIKYS = 'modified_string'    / ikys comment                                 
- KY_IKYJ =                   50 / This is a modified comment                   
- KY_IKYL =                    F / ikyl comment                                 
- KY_IKYE =          -1.2346E+01 / ikye comment                                 
- KY_IKYD = -1.23456789012346E+01 / modified comment                            
- KY_IKYF =             -12.3456 / ikyf comment                                 
- KY_IKYG =    -12.3456789012346 / ikyg comment                                 
- COMMENT   character at the end of each substring which is then continued      
-  
- After updating the keywords... 
- COMMENT   This keyword was modified by fxmrec                                 
- KY_UCRD = 'This keyword was updated by fxucrd'                                
- NEWIKYS = 'updated_string'     / ikys comment                                 
- KY_IKYJ =                   51 / This is a modified comment                   
- KY_IKYL =                    T / ikyl comment                                 
- KY_IKYE =          -1.3346E+01 / ikye comment                                 
- KY_IKYD = -1.33456789012346E+01 / modified comment                            
- KY_IKYF =             -13.3456 / ikyf comment                                 
- KY_IKYG =    -13.3456789012346 / ikyg comment                                 
- COMMENT   character at the end of each substring which is then continued      
-  
- Keywords found using wildcard search (should be 9)...
- KEY_PKYS= 'value_string'       / fxpkys comment                               
- KEY_PKYL=                    T / fxpkyl comment                               
- KEY_PKYJ=                   11 / [feet/second/second] fxpkyj comment          
- KEY_PKYF=             12.12121 / fxpkyf comment                               
- KEY_PKYE=         1.313131E+01 / fxpkye comment                               
- KEY_PKYG=    14.14141414141414 / fxpkyg comment                               
- KEY_PKYD= 1.51515151515152E+01 / fxpkyd comment                               
- NEWIKYS = 'updated_string'     / ikys comment                                 
- KEY_PKYT= 12345678.1234567890123456 / fxpkyt comment                          
-  
- ftibin status =    0
- HDU number =    2
- header contains   33 keywords located at keyword    1
- header contains   33 keywords with room for   74 more
- TDIM3 = (1,2,8)                 3   1   2   8
- ftpcl_ status =    0
-  
- Find the column numbers a returned status value of 237 is
- expected and indicates that more than one column name matches
- the input column name template.  Status = 219 indicates that
- there was no matching column name.
- Column Xvalue is number   3 status =   0
- Column Avalue is number   1 status =  237
- Column Lvalue is number   2 status =  237
- Column Xvalue is number   3 status =  237
- Column Bvalue is number   4 status =  237
- Column Ivalue is number   5 status =  237
- Column Jvalue is number   6 status =  237
- Column Evalue is number   7 status =  237
- Column Dvalue is number   8 status =  237
- Column Cvalue is number   9 status =  237
- Column Mvalue is number  10 status =  237
- Column        is number   0 status =  219
-  
- Information about each column: 
- 15A  16  15  15 Avalue       A      1.00    0.00  1234554321        
- 1L   14   1   1 Lvalue m**2  L      1.00    0.00  1234554321        
- 16X   1  16   1 Xvalue cm    X      1.00    0.00  1234554321        
- 1B   11   1   1 Bvalue erg/s B      1.00    0.00          99        
- 1I   21   1   2 Ivalue km/s  I      1.00    0.00          99        
- 1J   41   1   4 Jvalue       J      1.00    0.00          99        
- 1E   42   1   4 Evalue       E      1.00    0.00  1234554321        
- 1D   82   1   8 Dvalue       D      1.00    0.00  1234554321        
- 1C   83   1   8 Cvalue       C      1.00    0.00  1234554321        
- 1M  163   1  16 Mvalue       M      1.00    0.00  1234554321        
-  
- ftitab status =    0
- HDU number =    2
- ftpcl_ status =    0
-  
- ASCII table: rowlen, nrows, tfields, extname: 76 11  5 Test-ASCII     
- Name      1 A15           
- Ivalue   17 I10    m**2   
- Fvalue   28 F14.6  cm     
- Evalue   43 E12.5  erg/s  
- Dvalue   56 D21.14 km/s   
-  
- Data values read from ASCII table: 
- first string     1  1  1  1. 1.
- second string    2  2  2  2. 2.
-                  3  3  3  3. 3.
- UNDEFINED        4  4  4  4. 4.
-                  5  5  5  5. 5.
-                  6  6  6  6. 6.
-                  7  7  7  7. 7.
-                  8  8  8  8. 8.
-                  9  9  9  9. 9.
-                 10 10 10 10.10.
-                 99 99 99 99.99.
-  
-       1       1.000000  1.00000E+00  1.00000000000000E+00second string        
-  
- Column name is number   1 status =    0
- Column Ivalue is number   2 status =  237
- Column Fvalue is number   3 status =  237
- Column Evalue is number   4 status =  237
- Column Dvalue is number   5 status =  237
- Column        is number   0 status =  219
- A15      16   1  15 Name     1            1.00      0.00 null1   
- I10      41   1  10 Ivalue  17 m**2       1.00      0.00 null2   
- F14.6    82   1  14 Fvalue  28 cm         1.00      0.00 null3   
- E12.5    42   1  12 Evalue  43 erg/s      1.00      0.00 null4   
- D21.14   82   1  21 Dvalue  56 km/s       1.00      0.00 null5   
-  
-  
- Data values after inserting 3 rows after row 2:
- first string     1  1  1  1. 1.
- second string    2  2  2  2. 2.
-                  0  0  0  0. 0.
-                  0  0  0  0. 0.
-                  0  0  0  0. 0.
-                  3  3  3  3. 3.
- UNDEFINED        4  4  4  4. 4.
-                  5  5  5  5. 5.
-                  6  6  6  6. 6.
-                  7  7  7  7. 7.
-                  8  8  8  8. 8.
-                  9  9  9  9. 9.
-                 10 10 10 10.10.
-                 99 99 99 99.99.
-  
- Data values after deleting 2 rows at row 10: 
- first string     1  1  1  1. 1.
- second string    2  2  2  2. 2.
-                  0  0  0  0. 0.
-                  0  0  0  0. 0.
-                  0  0  0  0. 0.
-                  3  3  3  3. 3.
- UNDEFINED        4  4  4  4. 4.
-                  5  5  5  5. 5.
-                  6  6  6  6. 6.
-                  9  9  9  9. 9.
-                 10 10 10 10.10.
-                 99 99 99 99.99.
-  
- Data values after deleting column 3: 
- first string     1  1  1. 1.
- second string    2  2  2. 2.
-                  0  0  0. 0.
-                  0  0  0. 0.
-                  0  0  0. 0.
-                  3  3  3. 3.
- UNDEFINED        4  4  4. 4.
-                  5  5  5. 5.
-                  6  6  6. 6.
-                  9  9  9. 9.
-                 10 10 10.10.
-                 99 99 99.99.
-  
-  Data values after inserting column 5: 
- first string     1  1  1. 1. 0
- second string    2  2  2. 2. 0
-                  0  0  0. 0. 0
-                  0  0  0. 0. 0
-                  0  0  0. 0. 0
-                  3  3  3. 3. 0
- UNDEFINED        4  4  4. 4. 0
-                  5  5  5. 5. 0
-                  6  6  6. 6. 0
-                  9  9  9. 9. 0
-                 10 10 10.10. 0
-                 99 99 99.99. 0
- HDU number =    3
-  
- Moved to binary table
- header contains   37 keywords with room for   70 more 
-  
- Binary table: nrows, tfields, extname, pcount:  21  10Test-BINTABLE     0
- Avalue         15A                           
- Lvalue         1L             m**2           
- Xvalue         16X            cm             
- Bvalue         1B             erg/s          
- Ivalue         1I             km/s           
- Jvalue         1J                            
- Evalue         1E                            
- Dvalue         1D                            
- Cvalue         1C                            
- Mvalue         1M                            
-  
- Data values read from binary table: 
-  Bit column (X) data values:   
- FTFFTTFF FTTTFFFF TTTTFFFF FTTTTTFF FFFFFFFF
-   
- null string column value (should be blank):                              
-  
- Read columns with ftgcv_: 
- first string     F  76   1   1   1   1.   1.   1.  -2.   1.  -2.
- second string    T 112   2   2   2   2.   2.   3.  -4.   3.  -4.
-                  F 240   3   3   3   3.   3.   5.  -6.   5.  -6.
- NOT DEFINED      F 124   0  -4  -4  -4.  -4.   7.  -8.   7.  -8.
- NOT DEFINED      T   0   5   5   5   5.   5.   9. -10.   9. -10.
- NOT DEFINED      T   0   0  -6  -6  -6.  -6.  11. -12.  11. -12.
- NOT DEFINED      F   0   7   7   7   7.   7.  13. -14.  13. -14.
- NOT DEFINED      F   0   0  -8  -8  -8.  -8.  15. -16.  15. -16.
- NOT DEFINED      F   0   9   9   9   9.   9.  17. -18.  17. -18.
- NOT DEFINED      T   0   0 -10 -10 -10. -10.  19. -20.  19. -20.
- NOT DEFINED      F   0  98  98  98  98.  98.   0.   0.   0.   0.
- NOT DEFINED      T   0  12  12  12  12.  12.   0.   0.   0.   0.
- NOT DEFINED      F   0  98  98  98  98.  98.   0.   0.   0.   0.
- NOT DEFINED      F   0   0 -14 -14 -14. -14.   0.   0.   0.   0.
- NOT DEFINED      F   0  98  98  98  98.  98.   0.   0.   0.   0.
- NOT DEFINED      F   0   0 -16 -16 -16. -16.   0.   0.   0.   0.
- NOT DEFINED      T   0  98  98  98  98.  98.   0.   0.   0.   0.
- NOT DEFINED      T   0   0 -18 -18 -18. -18.   0.   0.   0.   0.
- NOT DEFINED      T   0  98  98  98  98.  98.   0.   0.   0.   0.
- NOT DEFINED      T   0   0 -20 -20 -20. -20.   0.   0.   0.   0.
- NOT DEFINED      F   0  98  98  98  98.  98.   0.   0.   0.   0.
-  
-  Read columns with ftgcf_: 
- first string     F  76   1   1   1   1.   1.   1.  -2.   1.  -2.
- second string    T 112   2   2   2   2.   2.   3.  -4.   3.  -4.
-                  F 240   3   3   3   3.   3.   5.  -6.   5.  -6.
-                  F 124   0  -4  -4  -4.  -4.   7.  -8.   7.  -8.
-                  T   0   5   5   5   5.   5.   9. -10.   9. -10.
-                  T   0   0  -6  -6  -6.  -6.  11. -12.  11. -12.
-                  F   0   7   7   7   7.   7.  13. -14.  13. -14.
-                  F   0   0  -8  -8  -8.  -8.  15. -16.  15. -16.
-                  F   0   9   9   9   9.   9.  17. -18.  17. -18.
-                  T   0   0 -10 -10 -10. -10.  19. -20.  19. -20.
-                  F   0  99  99
-                  T   0  12  12
-                  F   0  99  99
-                  F   0   0 -14
-                  F   0  99  99
-                  F   0   0 -16
-                  T   0  99  99
-                  T   0   0 -18
-                  T   0  99  99
-                  T   0   0 -20
-                  F   0  99  99
-  
- Data values after inserting 3 rows after row 2:
- first string     1   1   1   1.   1.
- second string    2   2   2   2.   2.
- NOT DEFINED      0   0   0   0.   0.
- NOT DEFINED      0   0   0   0.   0.
- NOT DEFINED      0   0   0   0.   0.
-                  3   3   3   3.   3.
- NOT DEFINED      0  -4  -4  -4.  -4.
- NOT DEFINED      5   5   5   5.   5.
- NOT DEFINED      0  -6  -6  -6.  -6.
- NOT DEFINED      7   7   7   7.   7.
- NOT DEFINED      0  -8  -8  -8.  -8.
- NOT DEFINED      9   9   9   9.   9.
- NOT DEFINED      0 -10 -10 -10. -10.
- NOT DEFINED     98  98  98  98.  98.
-  
- Data values after deleting 2 rows at row 10: 
- first string     1   1   1   1.   1.
- second string    2   2   2   2.   2.
- NOT DEFINED      0   0   0   0.   0.
- NOT DEFINED      0   0   0   0.   0.
- NOT DEFINED      0   0   0   0.   0.
-                  3   3   3   3.   3.
- NOT DEFINED      0  -4  -4  -4.  -4.
- NOT DEFINED      5   5   5   5.   5.
- NOT DEFINED      0  -6  -6  -6.  -6.
- NOT DEFINED      9   9   9   9.   9.
- NOT DEFINED      0 -10 -10 -10. -10.
- NOT DEFINED     98  98  98  98.  98.
-  
- Data values after deleting column 6: 
- first string     1   1   1.   1.
- second string    2   2   2.   2.
- NOT DEFINED      0   0   0.   0.
- NOT DEFINED      0   0   0.   0.
- NOT DEFINED      0   0   0.   0.
-                  3   3   3.   3.
- NOT DEFINED      0  -4  -4.  -4.
- NOT DEFINED      5   5   5.   5.
- NOT DEFINED      0  -6  -6.  -6.
- NOT DEFINED      9   9   9.   9.
- NOT DEFINED      0 -10 -10. -10.
- NOT DEFINED     98  98  98.  98.
-  
- Data values after inserting column 8: 
- first string     1   1   1.   1.  0
- second string    2   2   2.   2.  0
- NOT DEFINED      0   0   0.   0.  0
- NOT DEFINED      0   0   0.   0.  0
- NOT DEFINED      0   0   0.   0.  0
-                  3   3   3.   3.  0
- NOT DEFINED      0  -4  -4.  -4.  0
- NOT DEFINED      5   5   5.   5.  0
- NOT DEFINED      0  -6  -6.  -6.  0
- NOT DEFINED      9   9   9.   9.  0
- NOT DEFINED      0 -10 -10. -10.  0
- NOT DEFINED     98  98  98.  98.  0
-  
- Values after setting 1st 10 elements in column 8 = null: 
- first string     1   1   1.   1. 98
- second string    2   2   2.   2. 98
- NOT DEFINED      0   0   0.   0. 98
- NOT DEFINED      0   0   0.   0. 98
- NOT DEFINED      0   0   0.   0. 98
-                  3   3   3.   3. 98
- NOT DEFINED      0  -4  -4.  -4. 98
- NOT DEFINED      5   5   5.   5. 98
- NOT DEFINED      0  -6  -6.  -6. 98
- NOT DEFINED      9   9   9.   9. 98
- NOT DEFINED      0 -10 -10. -10.  0
- NOT DEFINED     98  98  98.  98.  0
-  
- ftibin status =    0
- HDU number =    2
-      0  1000 10000 33000 66000  -999
-      0  1000 10000 32768 65535  -999
-      0  1000 10000 32800 65500  -999
-  
-      0     1    10    33    66  -999
- -32768-31768-22768     0 32767  -999
-     -1     9    99   327   654  -999
-  
-  Create image extension: ftiimg status =    0
- HDU number =    3
-  
- Wrote whole 2D array: ftp2di status =   0
-  
- Read whole 2D array: ftg2di status =   0
-    0   1   2   3   4   5   6   7   8   9  10  11  12  13  14   0   0   0   0
-   10  11  12  13  14  15  16  17  18  19  20  21  22  23  24   0   0   0   0
-   20  21  22  23  24  25  26  27  28  29  30  31  32  33  34   0   0   0   0
-   30  31  32  33  34  35  36  37  38  39  40  41  42  43  44   0   0   0   0
-   40  41  42  43  44  45  46  47  48  49  50  51  52  53  54   0   0   0   0
-   50  51  52  53  54  55  56  57  58  59  60  61  62  63  64   0   0   0   0
-   60  61  62  63  64  65  66  67  68  69  70  71  72  73  74   0   0   0   0
-   70  71  72  73  74  75  76  77  78  79  80  81  82  83  84   0   0   0   0
-   80  81  82  83  84  85  86  87  88  89  90  91  92  93  94   0   0   0   0
-   90  91  92  93  94  95  96  97  98  99 100 101 102 103 104   0   0   0   0
-  100 101 102 103 104 105 106 107 108 109 110 111 112 113 114   0   0   0   0
-  110 111 112 113 114 115 116 117 118 119 120 121 122 123 124   0   0   0   0
-  120 121 122 123 124 125 126 127 128 129 130 131 132 133 134   0   0   0   0
-  130 131 132 133 134 135 136 137 138 139 140 141 142 143 144   0   0   0   0
-  140 141 142 143 144 145 146 147 148 149 150 151 152 153 154   0   0   0   0
-  150 151 152 153 154 155 156 157 158 159 160 161 162 163 164   0   0   0   0
-  160 161 162 163 164 165 166 167 168 169 170 171 172 173 174   0   0   0   0
-  170 171 172 173 174 175 176 177 178 179 180 181 182 183 184   0   0   0   0
-  180 181 182 183 184 185 186 187 188 189 190 191 192 193 194   0   0   0   0
-  190 191 192 193 194 195 196 197 198 199 200 201 202 203 204   0   0   0   0
-  200 201 202 203 204 205 206 207 208 209 210 211 212 213 214   0   0   0   0
-  210 211 212 213 214 215 216 217 218 219 220 221 222 223 224   0   0   0   0
-  220 221 222 223 224 225 226 227 228 229 230 231 232 233 234   0   0   0   0
-  230 231 232 233 234 235 236 237 238 239 240 241 242 243 244   0   0   0   0
-  240 241 242 243 244 245 246 247 248 249 250 251 252 253 254   0   0   0   0
-    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-  
-  
- Wrote subset 2D array: ftpssi status =   0
-  
- Read whole 2D array: ftg2di status =   0
-    0   1   2   3   4   5   6   7   8   9  10  11  12  13  14   0   0   0   0
-   10  11  12  13  14  15  16  17  18  19  20  21  22  23  24   0   0   0   0
-   20  21  22  23  24  25  26  27  28  29  30  31  32  33  34   0   0   0   0
-   30  31  32  33  34  35  36  37  38  39  40  41  42  43  44   0   0   0   0
-   40  41  42  43   0  -1  -2  -3  -4  -5  -6  -7  -8  -9  54   0   0   0   0
-   50  51  52  53 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19  64   0   0   0   0
-   60  61  62  63 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29  74   0   0   0   0
-   70  71  72  73 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39  84   0   0   0   0
-   80  81  82  83 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49  94   0   0   0   0
-   90  91  92  93 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 104   0   0   0   0
-  100 101 102 103 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 114   0   0   0   0
-  110 111 112 113 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 124   0   0   0   0
-  120 121 122 123 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 134   0   0   0   0
-  130 131 132 133 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 144   0   0   0   0
-  140 141 142 143 144 145 146 147 148 149 150 151 152 153 154   0   0   0   0
-  150 151 152 153 154 155 156 157 158 159 160 161 162 163 164   0   0   0   0
-  160 161 162 163 164 165 166 167 168 169 170 171 172 173 174   0   0   0   0
-  170 171 172 173 174 175 176 177 178 179 180 181 182 183 184   0   0   0   0
-  180 181 182 183 184 185 186 187 188 189 190 191 192 193 194   0   0   0   0
-  190 191 192 193 194 195 196 197 198 199 200 201 202 203 204   0   0   0   0
-  200 201 202 203 204 205 206 207 208 209 210 211 212 213 214   0   0   0   0
-  210 211 212 213 214 215 216 217 218 219 220 221 222 223 224   0   0   0   0
-  220 221 222 223 224 225 226 227 228 229 230 231 232 233 234   0   0   0   0
-  230 231 232 233 234 235 236 237 238 239 240 241 242 243 244   0   0   0   0
-  240 241 242 243 244 245 246 247 248 249 250 251 252 253 254   0   0   0   0
-    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-  
-  
- Read subset of 2D array: ftgsvi status =    0
-    41   43   -1   -3   -5   71   73  -31  -33  -35
-  
- Create image extension: ftiimg status =   0
- HDU number =    4
- Create temporary file: ftinit status =    0
- Copy image extension to primary array of tmp file.
- ftcopy status =    0
- SIMPLE  =                    T / file does conform to FITS standard           
- BITPIX  =                   16 / number of bits per data pixel                
- NAXIS   =                    2 / number of data axes                          
- NAXIS1  =                   15 / length of data axis 1                        
- NAXIS2  =                   25 / length of data axis 2                        
- EXTEND  =                    T / FITS dataset may contain extensions          
- Delete the tmp file: ftdelt status =   0
- Delete the image extension hdutype, status =   1   0
- HDU number =    4
- ftcrhd status =    0
- Variable length arrays: ftphbn status =   0
- ftpcl_ status =    0
- PCOUNT = 4446
- HDU number =    6
- A                                   0
- L  0  F
- X  0  F
- B  1  0
- I  1  0
- J  1  0
- E  1. 0.
- D  1. 0.
- Column 8 repeat and offset =    1   14
- A  ab                               0
- L  0  F  T
- X  0  F  T
- B 99  2  0
- I 99  2  0
- J 99  2  0
- E 99. 2. 0.
- D 99. 2. 0.
- Column 8 repeat and offset =    2   49
- A  abc                              0
- L  0  F  F  F
- X  0  F  T  F
- B  1 99  3  0
- I  1 99  3  0
- J  1 99  3  0
- E  1.99. 3. 0.
- D  1.99. 3. 0.
- Column 8 repeat and offset =    3  105
- A  abcd                             0
- L  0  F  T  F  F
- X  0  F  T  F  F
- B  1  2 99  4  0
- I  1  2 99  4  0
- J  1  2 99  4  0
- E  1. 2.99. 4. 0.
- D  1. 2.99. 4. 0.
- Column 8 repeat and offset =    4  182
- A  abcde                            0
- L  0  F  T  F  F  T
- X  0  F  T  F  F  T
- B  1  2  3 99  5  0
- I  1  2  3 99  5  0
- J  1  2  3 99  5  0
- E  1. 2. 3.99. 5. 0.
- D  1. 2. 3.99. 5. 0.
- Column 8 repeat and offset =    5  280
- A  abcdef                           0
- L  0  F  T  F  F  F  T
- X  0  F  T  F  F  T  T
- B  1  2  3  4 99  6  0
- I  1  2  3  4 99  6  0
- J  1  2  3  4 99  6  0
- E  1. 2. 3. 4.99. 6. 0.
- D  1. 2. 3. 4.99. 6. 0.
- Column 8 repeat and offset =    6  399
- A  abcdefg                          0
- L  0  F  T  F  F  T  F  F
- X  0  F  T  F  F  T  T  F
- B  1  2  3  4  5 99  7  0
- I  1  2  3  4  5 99  7  0
- J  1  2  3  4  5 99  7  0
- E  1. 2. 3. 4. 5.99. 7. 0.
- D  1. 2. 3. 4. 5.99. 7. 0.
- Column 8 repeat and offset =    7  539
- A  abcdefgh                         0
- L  0  F  T  F  F  T  T  F  F
- X  0  F  T  F  F  T  T  F  F
- B  1  2  3  4  5  6 99  8  0
- I  1  2  3  4  5  6 99  8  0
- J  1  2  3  4  5  6 99  8  0
- E  1. 2. 3. 4. 5. 6.99. 8. 0.
- D  1. 2. 3. 4. 5. 6.99. 8. 0.
- Column 8 repeat and offset =    8  700
- A  abcdefghi                        0
- L  0  F  T  F  F  T  T  F  F  F
- X  0  F  T  F  F  T  T  F  F  F
- B  1  2  3  4  5  6  7 99  9  0
- I  1  2  3  4  5  6  7 99  9  0
- J  1  2  3  4  5  6  7 99  9  0
- E  1. 2. 3. 4. 5. 6. 7.99. 9. 0.
- D  1. 2. 3. 4. 5. 6. 7.99. 9. 0.
- Column 8 repeat and offset =    9  883
- A  abcdefghij                       0
- L  0  F  T  F  F  T  T  F  F  F  T
- X  0  F  T  F  F  T  T  F  F  F  T
- B  1  2  3  4  5  6  7  8 99 10  0
- I  1  2  3  4  5  6  7  8 99 10  0
- J  1  2  3  4  5  6  7  8 99 10  0
- E  1. 2. 3. 4. 5. 6. 7. 8.99.10. 0.
- D  1. 2. 3. 4. 5. 6. 7. 8.99.10. 0.
- Column 8 repeat and offset =   10 1087
- A  abcdefghijk                      0
- L  0  F  T  F  F  T  T  F  F  F  F  T
- X  0  F  T  F  F  T  T  F  F  F  T  T
- B  1  2  3  4  5  6  7  8  9 99 11  0
- I  1  2  3  4  5  6  7  8  9 99 11  0
- J  1  2  3  4  5  6  7  8  9 99 11  0
- E  1. 2. 3. 4. 5. 6. 7. 8. 9.99.11. 0.
- D  1. 2. 3. 4. 5. 6. 7. 8. 9.99.11. 0.
- Column 8 repeat and offset =   11 1312
- A  abcdefghijkl                     0
- L  0  F  T  F  F  T  T  F  F  F  T  F  T
- X  0  F  T  F  F  T  T  F  F  F  T  T  T
- B  1  2  3  4  5  6  7  8  9 10 99 12  0
- I  1  2  3  4  5  6  7  8  9 10 99 12  0
- J  1  2  3  4  5  6  7  8  9 10 99 12  0
- E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.99.12. 0.
- D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.99.12. 0.
- Column 8 repeat and offset =   12 1558
- A  abcdefghijklm                    0
- L  0  F  T  F  F  T  T  F  F  F  T  T  F  F
- X  0  F  T  F  F  T  T  F  F  F  T  T  T  F
- B  1  2  3  4  5  6  7  8  9 10 11 99 13  0
- I  1  2  3  4  5  6  7  8  9 10 11 99 13  0
- J  1  2  3  4  5  6  7  8  9 10 11 99 13  0
- E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.99.13. 0.
- D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.99.13. 0.
- Column 8 repeat and offset =   13 1825
- A  abcdefghijklmn                   0
- L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F
- X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F
- B  1  2  3  4  5  6  7  8  9 10 11 12 99 14  0
- I  1  2  3  4  5  6  7  8  9 10 11 12 99 14  0
- J  1  2  3  4  5  6  7  8  9 10 11 12 99 14  0
- E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.99.14. 0.
- D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.99.14. 0.
- Column 8 repeat and offset =   14 2113
- A  abcdefghijklmno                  0
- L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F
- X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F
- B  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15  0
- I  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15  0
- J  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15  0
- E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.99.15. 0.
- D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.99.15. 0.
- Column 8 repeat and offset =   15 2422
- A  abcdefghijklmnop                 0
- L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F
- X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F
- B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16  0
- I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16  0
- J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16  0
- E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.99.16. 0.
- D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.99.16. 0.
- Column 8 repeat and offset =   16 2752
- A  abcdefghijklmnopq                0
- L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T
- X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T
- B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17  0
- I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17  0
- J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17  0
- E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.99.17. 0.
- D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.99.17. 0.
- Column 8 repeat and offset =   17 3104
- A  abcdefghijklmnopqr               0
- L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  F  T
- X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T  T
- B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18  0
- I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18  0
- J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18  0
- E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.99.18. 0.
- D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.99.18. 0.
- Column 8 repeat and offset =   18 3477
- A  abcdefghijklmnopqrs              0
- L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T  F  T
- X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T  T  T
- B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19  0
- I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19  0
- J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19  0
- E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.17.99.19. 0.
- D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.17.99.19. 0.
- Column 8 repeat and offset =   19 3871
- A  abcdefghijklmnopqrst             0
- L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T  T  F  T
- X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T  T  T  T
- B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20  0
- I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20  0
- J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20  0
- E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.17.18.99.20. 0.
- D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.17.18.99.20. 0.
- Column 8 repeat and offset =   20 4286
-  
- Create image extension: ftiimg status =   0
- ftppr status =    0
-  
- Image values written with ftppr and read with ftgpv:
-   0  2  4  6  8 10 12 14 16 18 20 22 24 26  F (byte)
-   0  2  4  6  8 10 12 14 16 18 20 22 24 26  F (short)
-   0  2  4  6  8 10 12 14 16 18 20 22 24 26  F (int)
-   0  2  4  6  8 10 12 14 16 18 20 22 24 26  F (long)
-   0. 2. 4. 6. 8.10.12.14.16.18.20.22.24.26. F (float)
-   0. 2. 4. 6. 8.10.12.14.16.18.20.22.24.26. F (double)
-  
- Wrote WCS keywords status =   0
- Read WCS keywords with ftgics status =   0
-   CRVAL1, CRVAL2 =  45.830  63.570
-   CRPIX1, CRPIX2 = 256.000 257.000
-   CDELT1, CDELT2 = -0.00277777  0.00277777
-   Rotation =   0.000 CTYPE =-TAN    
- Calculated sky coord. with ftwldp status =   0
-  Pixels (  0.500000  0.500000) --> ( 47.385204 62.848968) Sky
- Calculated pixel coord. with ftxypx status =   0
-  Sky ( 47.385204 62.848968) --> (  0.500000  0.500000) Pixels
-  
- ftitab status =    0
- ftpcl status =    0
- Column values written with ftpcl and read with ftgcl: 
-   0  3  6  9 12 15 18 21 24 27  F (byte) 
-   0  3  6  9 12 15 18 21 24 27  F (short) 
-   0  3  6  9 12 15 18 21 24 27  F (int) 
-   0  3  6  9 12 15 18 21 24 27  F (long) 
-   0. 3. 6. 9.12.15.18.21.24.27. F (float) 
-   0. 3. 6. 9.12.15.18.21.24.27. F (double) 
-  
- Repeatedly move to the 1st 4 HDUs of the file: 
-  
- Encode checksum:  1234567890.0 -> dCW2fBU0dBU0dBU0 
- Decode checksum: dCW2fBU0dBU0dBU0  ->  1234567890.0
- DATASUM = '2338390162'
- ftgcks data checksum, status =  2338390162.0   0
- ftvcks datastatus, hdustatus, status =     1   1   0
- ftupck status =    0
- DATASUM = '2338390162'
- ftvcks datastatus, hdustatus, status =     1   1   0
- ftclos status =    0
-  
- Normally, there should be 8 error messages on the
- stack all regarding 'numerical overflows':
- Numerical overflow during type conversion while writing FITS data.         
- Numerical overflow during type conversion while writing FITS data.         
- Numerical overflow during type conversion while writing FITS data.         
- Numerical overflow during type conversion while writing FITS data.         
- Numerical overflow during type conversion while writing FITS data.         
- Numerical overflow during type conversion while writing FITS data.         
- Numerical overflow during type conversion while writing FITS data.         
- Numerical overflow during type conversion while writing FITS data.         
-  
- Status =   0: OK - no error                                     
diff --git a/src/external/OpenGR/3rdparty/cfitsio/testf77.std b/src/external/OpenGR/3rdparty/cfitsio/testf77.std
deleted file mode 100644
index 24975a43a..000000000
Binary files a/src/external/OpenGR/3rdparty/cfitsio/testf77.std and /dev/null differ
diff --git a/src/external/OpenGR/3rdparty/cfitsio/testprog.c b/src/external/OpenGR/3rdparty/cfitsio/testprog.c
deleted file mode 100644
index b684b7ee1..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/testprog.c
+++ /dev/null
@@ -1,2589 +0,0 @@
-#include 
-#include 
-#include "fitsio.h"
-int main(void);
-
-int main()
-{
-/*  
-    This is a big and complicated program that tests most of
-    the cfitsio routines.  This code does not represent
-    the most efficient method of reading or writing FITS files 
-    because this code is primarily designed to stress the cfitsio
-    library routines.
-*/
-    char asciisum[17];
-    unsigned long checksum, datsum;
-    int datastatus, hdustatus, filemode;
-    int status, simple, bitpix, naxis, extend, hdutype, hdunum, tfields;
-    long ii, jj, extvers;
-    int nkeys, nfound, colnum, typecode, signval,nmsg;
-    char cval, cvalstr[2];
-    long repeat, offset, width, jnulval;
-    int anynull;
-/*    float vers;   */
-    unsigned char xinarray[21], binarray[21], boutarray[21], bnul;
-    short         iinarray[21], ioutarray[21], inul;
-    int           kinarray[21], koutarray[21], knul;
-    long          jinarray[21], joutarray[21], jnul;
-    float         einarray[21], eoutarray[21], enul, cinarray[42];
-    double        dinarray[21], doutarray[21], dnul, minarray[42];
-    double scale, zero;
-    long naxes[3], pcount, gcount, npixels, nrows, rowlen, firstpix[3];
-    int existkeys, morekeys, keynum;
-
-    char larray[42], larray2[42], colname[70], tdisp[40], nulstr[40];
-    char oskey[] = "value_string";
-    char iskey[21];
-    int olkey = 1;
-    int ilkey;
-    short oshtkey, ishtkey;
-    long ojkey = 11, ijkey;
-    long otint = 12345678;
-    float ofkey = 12.121212f;
-    float oekey = 13.131313f, iekey;
-    double ogkey = 14.1414141414141414;
-    double odkey = 15.1515151515151515, idkey;
-    double otfrac = .1234567890123456;
-
-    double xrval,yrval,xrpix,yrpix,xinc,yinc,rot,xpos,ypos,xpix,ypix;
-    char xcoordtype[] = "RA---TAN";
-    char ycoordtype[] = "DEC--TAN";
-    char ctype[5];
-
-    char *lsptr;    /* pointer to long string value */
-    char  comm[73];
-    char *comms[3];
-    char *inskey[21];
-    char *onskey[3] = {"first string", "second string", "        "};
-    char *inclist[2] = {"key*", "newikys"};
-    char *exclist[2] = {"key_pr*", "key_pkls"};
-
-    int   onlkey[3] = {1, 0, 1}, inlkey[3];
-    long  onjkey[3] = {11, 12, 13}, injkey[3];
-    float onfkey[3] = {12.121212f, 13.131313f, 14.141414f};
-    float onekey[3] = {13.131313f, 14.141414f, 15.151515f}, inekey[3];
-    double ongkey[3] = {14.1414141414141414, 15.1515151515151515,
-           16.1616161616161616};
-    double ondkey[3] = {15.1515151515151515, 16.1616161616161616,
-           17.1717171717171717}, indkey[3];
-
-    long tbcol[5] = {1, 17, 28, 43, 56};
-
-    char filename[40], card[FLEN_CARD], card2[FLEN_CARD];
-    char keyword[FLEN_KEYWORD];
-    char value[FLEN_VALUE], comment[FLEN_COMMENT];
-    unsigned char uchars[80];
-
-    fitsfile *fptr, *tmpfptr;
-    char *ttype[10], *tform[10], *tunit[10];
-    char tblname[40];
-    char binname[] = "Test-BINTABLE";
-    char templt[] = "testprog.tpt";
-    char errmsg[FLEN_ERRMSG];
-    short imgarray[30][19], imgarray2[20][10];
-    long fpixels[2], lpixels[2], inc[2];
-
-    status = 0;
-    strcpy(tblname, "Test-ASCII");
-
-/*    ffvers(&vers); 
-    printf("CFITSIO TESTPROG, v%.3f\n\n",vers);
-*/
-    printf("CFITSIO TESTPROG\n\n");
-    printf("Try opening then closing a nonexistent file:\n");
-    fits_open_file(&fptr, "tq123x.kjl", READWRITE, &status);
-    printf("  ffopen fptr, status  = %lu %d (expect an error)\n", 
-           (unsigned long) fptr, status);
-    ffclos(fptr, &status);
-    printf("  ffclos status = %d\n\n", status);
-    ffcmsg();
-    status = 0;
-
-    for (ii = 0; ii < 21; ii++)  /* allocate space for string column value */
-        inskey[ii] = (char *) malloc(21);   
-
-    for (ii = 0; ii < 10; ii++)
-    {
-      ttype[ii] = (char *) malloc(20);
-      tform[ii] = (char *) malloc(20);
-      tunit[ii] = (char *) malloc(20);
-    }
-
-    comms[0] = comm;
-
-    /* delete previous version of the file, if it exists (with ! prefix) */
-    strcpy(filename, "!testprog.fit");
-
-    status = 0;
-
-    /*
-      #####################
-      #  create FITS file #
-      #####################
-    */
-
-    ffinit(&fptr, filename, &status);
-    printf("ffinit create new file status = %d\n", status);
-    if (status)
-        goto errstatus;
-
-    filename[0] = '\0';
-    ffflnm(fptr, filename, &status);
-
-    ffflmd(fptr, &filemode, &status);
-    printf("Name of file = %s, I/O mode = %d\n", filename, filemode);
-    simple = 1;
-    bitpix = 32;
-    naxis = 2;
-    naxes[0] = 10;
-    naxes[1] = 2;
-    npixels = 20;
-    pcount = 0;
-    gcount = 1;
-    extend = 1;
-    /*
-      ############################
-      #  write single keywords   #
-      ############################
-    */
-
-    if (ffphps(fptr, bitpix, naxis, naxes, &status) > 0)
-        printf("ffphps status = %d\n", status);
-
-    if (ffprec(fptr, 
-    "key_prec= 'This keyword was written by fxprec' / comment goes here", 
-     &status) > 0 )
-        printf("ffprec status = %d\n", status);
-
-    printf("\ntest writing of long string keywords:\n");
-    strcpy(card, "1234567890123456789012345678901234567890");
-    strcat(card, "12345678901234567890123456789012345");
-    ffpkys(fptr, "card1", card, "", &status);
-    ffgkey(fptr, "card1", card2, comment, &status);
-    printf(" %s\n%s\n", card, card2);
-    
-    strcpy(card, "1234567890123456789012345678901234567890");
-    strcat(card, "123456789012345678901234'6789012345");
-    ffpkys(fptr, "card2", card, "", &status);
-    ffgkey(fptr, "card2", card2, comment, &status);
-    printf(" %s\n%s\n", card, card2);
-    
-    strcpy(card, "1234567890123456789012345678901234567890");
-    strcat(card, "123456789012345678901234''789012345");
-    ffpkys(fptr, "card3", card, "", &status);
-    ffgkey(fptr, "card3", card2, comment, &status);
-    printf(" %s\n%s\n", card, card2);
-    
-    strcpy(card, "1234567890123456789012345678901234567890");
-    strcat(card, "123456789012345678901234567'9012345");
-    ffpkys(fptr, "card4", card, "", &status);
-    ffgkey(fptr, "card4", card2, comment, &status);
-    printf(" %s\n%s\n", card, card2);
-    
-    if (ffpkys(fptr, "key_pkys", oskey, "fxpkys comment", &status) > 0)
-        printf("ffpkys status = %d\n", status);
-
-    if (ffpkyl(fptr, "key_pkyl", olkey, "fxpkyl comment", &status) > 0)
-        printf("ffpkyl status = %d\n", status);
-
-    if (ffpkyj(fptr, "key_pkyj", ojkey, "fxpkyj comment", &status) > 0)
-        printf("ffpkyj status = %d\n", status);
-
-    if (ffpkyf(fptr, "key_pkyf", ofkey, 5, "fxpkyf comment", &status) > 0)
-        printf("ffpkyf status = %d\n", status);
-
-    if (ffpkye(fptr, "key_pkye", oekey, 6, "fxpkye comment", &status) > 0)
-        printf("ffpkye status = %d\n", status);
-
-    if (ffpkyg(fptr, "key_pkyg", ogkey, 14, "fxpkyg comment", &status) > 0)
-        printf("ffpkyg status = %d\n", status);
-
-    if (ffpkyd(fptr, "key_pkyd", odkey, 14, "fxpkyd comment", &status) > 0)
-        printf("ffpkyd status = %d\n", status);
-
-    if (ffpkyc(fptr, "key_pkyc", onekey, 6, "fxpkyc comment", &status) > 0)
-        printf("ffpkyc status = %d\n", status);
-
-    if (ffpkym(fptr, "key_pkym", ondkey, 14, "fxpkym comment", &status) > 0)
-        printf("ffpkym status = %d\n", status);
-
-    if (ffpkfc(fptr, "key_pkfc", onekey, 6, "fxpkfc comment", &status) > 0)
-        printf("ffpkfc status = %d\n", status);
-
-    if (ffpkfm(fptr, "key_pkfm", ondkey, 14, "fxpkfm comment", &status) > 0)
-        printf("ffpkfm status = %d\n", status);
-
-    if (ffpkls(fptr, "key_pkls", 
-"This is a very long string value that is continued over more than one keyword.",
-     "fxpkls comment", &status) > 0)
-        printf("ffpkls status = %d\n", status);
-
-    if (ffplsw(fptr, &status) > 0 )
-        printf("ffplsw status = %d\n", status);
-
-    if (ffpkyt(fptr, "key_pkyt", otint, otfrac, "fxpkyt comment", &status) > 0)
-        printf("ffpkyt status = %d\n", status);
-
-    if (ffpcom(fptr, "  This keyword was written by fxpcom.", &status) > 0)
-        printf("ffpcom status = %d\n", status);
-
-    if (ffphis(fptr, "    This keyword written by fxphis (w/ 2 leading spaces).",
-        &status) > 0)
-        printf("ffphis status = %d\n", status);
-
-    if (ffpdat(fptr, &status) > 0)
-    {
-        printf("ffpdat status = %d\n", status);
-        goto errstatus;
-    }
-
-    /*
-      ###############################
-      #  write arrays of keywords   #
-      ###############################
-    */
-    nkeys = 3;
-
-    comms[0] = comm;  /* use the inskey array of pointers for the comments */
-
-    strcpy(comm, "fxpkns comment&");
-    if (ffpkns(fptr, "ky_pkns", 1, nkeys, onskey, comms, &status) > 0)
-        printf("ffpkns status = %d\n", status);
-
-    strcpy(comm, "fxpknl comment&");
-    if (ffpknl(fptr, "ky_pknl", 1, nkeys, onlkey, comms, &status) > 0)
-        printf("ffpknl status = %d\n", status);
-
-    strcpy(comm, "fxpknj comment&");
-    if (ffpknj(fptr, "ky_pknj", 1, nkeys, onjkey, comms, &status) > 0)
-        printf("ffpknj status = %d\n", status);
-
-    strcpy(comm, "fxpknf comment&");
-    if (ffpknf(fptr, "ky_pknf", 1, nkeys, onfkey, 5, comms, &status) > 0)
-        printf("ffpknf status = %d\n", status);
-
-    strcpy(comm, "fxpkne comment&");
-    if (ffpkne(fptr, "ky_pkne", 1, nkeys, onekey, 6, comms, &status) > 0)
-        printf("ffpkne status = %d\n", status);
-
-    strcpy(comm, "fxpkng comment&");
-    if (ffpkng(fptr, "ky_pkng", 1, nkeys, ongkey, 13, comms, &status) > 0)
-        printf("ffpkng status = %d\n", status);
-
-    strcpy(comm, "fxpknd comment&");
-    if (ffpknd(fptr, "ky_pknd", 1, nkeys, ondkey, 14, comms, &status) > 0)
-    {
-        printf("ffpknd status = %d\n", status);
-        goto errstatus;
-    }
-    /*
-      ############################
-      #  write generic keywords  #
-      ############################
-    */
-
-    strcpy(oskey, "1");
-    if (ffpky(fptr, TSTRING, "tstring", oskey, "tstring comment", &status) > 0)
-        printf("ffpky status = %d\n", status);
-
-    olkey = TLOGICAL;
-    if (ffpky(fptr, TLOGICAL, "tlogical", &olkey, "tlogical comment",
-        &status) > 0)
-        printf("ffpky status = %d\n", status);
-
-    cval = TBYTE;
-    if (ffpky(fptr, TBYTE, "tbyte", &cval, "tbyte comment", &status) > 0)
-        printf("ffpky status = %d\n", status);
-
-    oshtkey = TSHORT;
-    if (ffpky(fptr, TSHORT, "tshort", &oshtkey, "tshort comment", &status) > 0)
-        printf("ffpky status = %d\n", status);
-
-    olkey = TINT;
-    if (ffpky(fptr, TINT, "tint", &olkey, "tint comment", &status) > 0)
-        printf("ffpky status = %d\n", status);
-
-    ojkey = TLONG;
-    if (ffpky(fptr, TLONG, "tlong", &ojkey, "tlong comment", &status) > 0)
-        printf("ffpky status = %d\n", status);
-
-    oekey = TFLOAT;
-    if (ffpky(fptr, TFLOAT, "tfloat", &oekey, "tfloat comment", &status) > 0)
-        printf("ffpky status = %d\n", status);
-
-    odkey = TDOUBLE;
-    if (ffpky(fptr, TDOUBLE, "tdouble", &odkey, "tdouble comment",
-              &status) > 0)
-        printf("ffpky status = %d\n", status);
-
-    /*
-      ############################
-      #  write data              #
-      ############################
-    */
-    /* define the null value (must do this before writing any data) */
-    if (ffpkyj(fptr, "BLANK", -99, "value to use for undefined pixels",
-       &status) > 0)
-        printf("BLANK keyword status = %d\n", status);
-
-    /* initialize arrays of values to write to primary array */
-    for (ii = 0; ii < npixels; ii++)
-    {
-        boutarray[ii] = (unsigned char) (ii + 1);
-        ioutarray[ii] = (short) (ii + 1);
-        joutarray[ii] = ii + 1;
-        eoutarray[ii] = (float) (ii + 1);
-        doutarray[ii] = ii + 1;
-    }
-
-    /* write a few pixels with each datatype */
-    /* set the last value in each group of 4 as undefined */
-
-/*
-    ffpprb(fptr, 1,  1, 2, &boutarray[0],  &status);
-    ffppri(fptr, 1,  5, 2, &ioutarray[4],  &status);
-    ffpprj(fptr, 1,  9, 2, &joutarray[8],  &status);
-    ffppre(fptr, 1, 13, 2, &eoutarray[12], &status);
-    ffpprd(fptr, 1, 17, 2, &doutarray[16], &status);
-*/
-
-/*  test the newer ffpx routine, instead of the older ffppr_ routines */
-    firstpix[0]=1;
-    firstpix[1]=1;
-    ffppx(fptr, TBYTE, firstpix, 2, &boutarray[0],  &status);
-    firstpix[0]=5;
-    ffppx(fptr, TSHORT, firstpix, 2, &ioutarray[4],  &status);
-    firstpix[0]=9;
-    ffppx(fptr, TLONG, firstpix, 2, &joutarray[8],  &status);
-    firstpix[0]=3;
-    firstpix[1]=2;
-    ffppx(fptr, TFLOAT, firstpix, 2, &eoutarray[12],  &status);
-    firstpix[0]=7;
-    ffppx(fptr, TDOUBLE, firstpix, 2, &doutarray[16],  &status);
-
-/*
-    ffppnb(fptr, 1,  3, 2, &boutarray[2],   4, &status);
-    ffppni(fptr, 1,  7, 2, &ioutarray[6],   8, &status);
-    ffppnj(fptr, 1, 11, 2, &joutarray[10],  12, &status);
-    ffppne(fptr, 1, 15, 2, &eoutarray[14], 16., &status);
-    ffppnd(fptr, 1, 19, 2, &doutarray[18], 20., &status);
-*/
-    firstpix[0]=3;
-    firstpix[1]=1;
-    bnul = 4;
-    ffppxn(fptr, TBYTE, firstpix, 2, &boutarray[2], &bnul,  &status);
-    firstpix[0]=7;
-    inul = 8;
-    ffppxn(fptr, TSHORT, firstpix, 2, &ioutarray[6], &inul, &status);
-    firstpix[0]=1;
-    firstpix[1]=2;
-    jnul = 12;
-    ffppxn(fptr, TLONG, firstpix, 2, &joutarray[10], &jnul, &status);
-    firstpix[0]=5;
-    enul = 16.;
-    ffppxn(fptr, TFLOAT, firstpix, 2, &eoutarray[14], &enul,  &status);
-    firstpix[0]=9;
-    dnul = 20.;
-    ffppxn(fptr, TDOUBLE, firstpix, 2, &doutarray[18], &dnul, &status);
-
-    ffppru(fptr, 1, 1, 1, &status);
-
-
-    if (status > 0)
-    {
-        printf("ffppnx status = %d\n", status);
-        goto errstatus;
-    }
-
-    ffflus(fptr, &status);   /* flush all data to the disk file */ 
-    printf("ffflus status = %d\n", status);
-    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));
-
-    /*
-      ############################
-      #  read data               #
-      ############################
-    */
-    /* read back the data, setting null values = 99 */
-    printf("\nValues read back from primary array (99 = null pixel)\n");
-    printf("The 1st, and every 4th pixel should be undefined:\n");
-
-    anynull = 0;
-    ffgpvb(fptr, 1,  1, 10, 99, binarray, &anynull, &status); 
-
-    ffgpvb(fptr, 1, 11, 10, 99, &binarray[10], &anynull, &status);
-
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2d", binarray[ii]);
-    printf("  %d (ffgpvb)\n", anynull);  
-
-    ffgpvi(fptr, 1, 1, npixels, 99,   iinarray, &anynull, &status);
-
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2d", iinarray[ii]);
-    printf("  %d (ffgpvi)\n", anynull);  
-
-    ffgpvj(fptr, 1, 1, npixels, 99,  jinarray, &anynull, &status);
-
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2ld", jinarray[ii]);
-    printf("  %d (ffgpvj)\n", anynull);  
-
-    ffgpve(fptr, 1, 1, npixels, 99., einarray, &anynull, &status);
-
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2.0f", einarray[ii]);
-    printf("  %d (ffgpve)\n", anynull);  
-
-    ffgpvd(fptr, 1,  1, 10, 99.,  dinarray, &anynull, &status);
-    ffgpvd(fptr, 1, 11, 10, 99.,  &dinarray[10], &anynull, &status);
-
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2.0f", dinarray[ii]);
-    printf("  %d (ffgpvd)\n", anynull);  
-
-    if (status > 0)
-    {
-        printf("ERROR: ffgpv_ status = %d\n", status);
-        goto errstatus;
-    }
-    if (anynull == 0)
-       printf("ERROR: ffgpv_ did not detect null values\n");
-
-    /* reset the output null value to the expected input value */
-    for (ii = 3; ii < npixels; ii += 4)
-    {
-        boutarray[ii] = 99;
-        ioutarray[ii] = 99;
-        joutarray[ii] = 99;
-        eoutarray[ii] = 99.;
-        doutarray[ii] = 99.;
-    }
-        ii = 0;
-        boutarray[ii] = 99;
-        ioutarray[ii] = 99;
-        joutarray[ii] = 99;
-        eoutarray[ii] = 99.;
-        doutarray[ii] = 99.;
-
-    /* compare the output with the input; flag any differences */
-    for (ii = 0; ii < npixels; ii++)
-    {
-       if (boutarray[ii] != binarray[ii])
-           printf("bout != bin = %u %u \n", boutarray[ii], binarray[ii]);
-
-       if (ioutarray[ii] != iinarray[ii])
-           printf("iout != iin = %d %d \n", ioutarray[ii], iinarray[ii]);
-
-       if (joutarray[ii] != jinarray[ii])
-           printf("jout != jin = %ld %ld \n", joutarray[ii], jinarray[ii]);
-
-       if (eoutarray[ii] != einarray[ii])
-           printf("eout != ein = %f %f \n", eoutarray[ii], einarray[ii]);
-
-       if (doutarray[ii] != dinarray[ii])
-           printf("dout != din = %f %f \n", doutarray[ii], dinarray[ii]);
-    }
-
-    for (ii = 0; ii < npixels; ii++)
-    {
-      binarray[ii] = 0;
-      iinarray[ii] = 0;
-      jinarray[ii] = 0;
-      einarray[ii] = 0.;
-      dinarray[ii] = 0.;
-    }
-
-    anynull = 0;
-    ffgpfb(fptr, 1,  1, 10, binarray, larray, &anynull, &status);
-    ffgpfb(fptr, 1, 11, 10, &binarray[10], &larray[10], &anynull, &status);
-
-    for (ii = 0; ii < npixels; ii++)
-      if (larray[ii])
-        printf("  *");
-      else
-        printf(" %2d", binarray[ii]);
-    printf("  %d (ffgpfb)\n", anynull);  
-
-    ffgpfi(fptr, 1, 1, npixels, iinarray, larray, &anynull, &status);
-
-    for (ii = 0; ii < npixels; ii++)
-      if (larray[ii])
-        printf("  *");
-      else
-        printf(" %2d", iinarray[ii]);
-    printf("  %d (ffgpfi)\n", anynull);  
-
-    ffgpfj(fptr, 1, 1, npixels, jinarray, larray, &anynull, &status);
-
-    for (ii = 0; ii < npixels; ii++)
-      if (larray[ii])
-        printf("  *");
-      else
-        printf(" %2ld", jinarray[ii]);
-    printf("  %d (ffgpfj)\n", anynull);  
-
-    ffgpfe(fptr, 1, 1, npixels, einarray, larray, &anynull, &status);
-
-    for (ii = 0; ii < npixels; ii++)
-      if (larray[ii])
-        printf("  *");
-      else
-        printf(" %2.0f", einarray[ii]);
-    printf("  %d (ffgpfe)\n", anynull);  
-
-    ffgpfd(fptr, 1,  1, 10, dinarray, larray, &anynull, &status);
-    ffgpfd(fptr, 1, 11, 10, &dinarray[10], &larray[10], &anynull, &status);
-
-    for (ii = 0; ii < npixels; ii++)
-      if (larray[ii])
-        printf("  *");
-      else
-        printf(" %2.0f", dinarray[ii]);
-    printf("  %d (ffgpfd)\n", anynull);  
-
-    if (status > 0)
-    {
-        printf("ERROR: ffgpf_ status = %d\n", status);
-        goto errstatus;
-    }
-    if (anynull == 0)
-       printf("ERROR: ffgpf_ did not detect null values\n");
-
-
-    /*
-      ##########################################
-      #  close and reopen file multiple times  #
-      ##########################################
-    */
-
-    for (ii = 0; ii < 10; ii++)
-    {
-      if (ffclos(fptr, &status) > 0)
-      {
-        printf("ERROR in ftclos (1) = %d", status);
-        goto errstatus;
-      }
-
-      if (fits_open_file(&fptr, filename, READWRITE, &status) > 0)
-      {
-        printf("ERROR: ffopen open file status = %d\n", status);
-        goto errstatus;
-      }
-    }
-    printf("\nClosed then reopened the FITS file 10 times.\n");
-    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));
-
-    filename[0] = '\0';
-    ffflnm(fptr, filename, &status);
-
-    ffflmd(fptr, &filemode, &status);
-    printf("Name of file = %s, I/O mode = %d\n", filename, filemode);
-
-    /*
-      ############################
-      #  read single keywords    #
-      ############################
-    */
-
-    simple = 0;
-    bitpix = 0;
-    naxis = 0;
-    naxes[0] = 0;
-    naxes[1] = 0;
-    pcount = -99;
-    gcount =  -99;
-    extend = -99;
-    printf("\nRead back keywords:\n");
-    ffghpr(fptr, 99, &simple, &bitpix, &naxis, naxes, &pcount,
-           &gcount, &extend, &status);
-    printf("simple = %d, bitpix = %d, naxis = %d, naxes = (%ld, %ld)\n",
-           simple, bitpix, naxis, naxes[0], naxes[1]);
-    printf("  pcount = %ld, gcount = %ld, extend = %d\n",
-               pcount, gcount, extend);
-
-    ffgrec(fptr, 9, card, &status);
-    printf("%s\n", card);
-    if (strncmp(card, "KEY_PREC= 'This", 15) )
-       printf("ERROR in ffgrec\n");
-
-    ffgkyn(fptr, 9, keyword, value, comment, &status);
-    printf("%s : %s : %s :\n",keyword, value, comment);
-    if (strncmp(keyword, "KEY_PREC", 8) )
-       printf("ERROR in ffgkyn: %s\n", keyword);
-
-    ffgcrd(fptr, keyword, card, &status);
-    printf("%s\n", card);
-
-    if (strncmp(keyword, card, 8) )
-       printf("ERROR in ffgcrd: %s\n", keyword);
-
-    ffgkey(fptr, "KY_PKNS1", value, comment, &status);
-    printf("KY_PKNS1 : %s : %s :\n", value, comment);
-
-    if (strncmp(value, "'first string'", 14) )
-       printf("ERROR in ffgkey: %s\n", value);
-
-    ffgkys(fptr, "key_pkys", iskey, comment, &status);
-    printf("KEY_PKYS %s %s %d\n", iskey, comment, status);
-
-    ffgkyl(fptr, "key_pkyl", &ilkey, comment, &status);
-    printf("KEY_PKYL %d %s %d\n", ilkey, comment, status);
-
-    ffgkyj(fptr, "KEY_PKYJ", &ijkey, comment, &status);
-    printf("KEY_PKYJ %ld %s %d\n",ijkey, comment, status);
-
-    ffgkye(fptr, "KEY_PKYJ", &iekey, comment, &status);
-    printf("KEY_PKYJ %f %s %d\n",iekey, comment, status);
-
-    ffgkyd(fptr, "KEY_PKYJ", &idkey, comment, &status);
-    printf("KEY_PKYJ %f %s %d\n",idkey, comment, status);
-
-    if (ijkey != 11 || iekey != 11. || idkey != 11.)
-       printf("ERROR in ffgky[jed]: %ld, %f, %f\n",ijkey, iekey, idkey);
-
-    iskey[0] = '\0';
-    ffgky(fptr, TSTRING, "key_pkys", iskey, comment, &status);
-    printf("KEY_PKY S %s %s %d\n", iskey, comment, status);
-
-    ilkey = 0;
-    ffgky(fptr, TLOGICAL, "key_pkyl", &ilkey, comment, &status);
-    printf("KEY_PKY L %d %s %d\n", ilkey, comment, status);
-
-    ffgky(fptr, TBYTE, "KEY_PKYJ", &cval, comment, &status);
-    printf("KEY_PKY BYTE %d %s %d\n",cval, comment, status);
-
-    ffgky(fptr, TSHORT, "KEY_PKYJ", &ishtkey, comment, &status);
-    printf("KEY_PKY SHORT %d %s %d\n",ishtkey, comment, status);
-
-    ffgky(fptr, TINT, "KEY_PKYJ", &ilkey, comment, &status);
-    printf("KEY_PKY INT %d %s %d\n",ilkey, comment, status);
-
-    ijkey = 0;
-    ffgky(fptr, TLONG, "KEY_PKYJ", &ijkey, comment, &status);
-    printf("KEY_PKY J %ld %s %d\n",ijkey, comment, status);
-
-    iekey = 0;
-    ffgky(fptr, TFLOAT, "KEY_PKYE", &iekey, comment, &status);
-    printf("KEY_PKY E %f %s %d\n",iekey, comment, status);
-
-    idkey = 0;
-    ffgky(fptr, TDOUBLE, "KEY_PKYD", &idkey, comment, &status);
-    printf("KEY_PKY D %f %s %d\n",idkey, comment, status);
-
-    ffgkyd(fptr, "KEY_PKYF", &idkey, comment, &status);
-    printf("KEY_PKYF %f %s %d\n",idkey, comment, status);
-
-    ffgkyd(fptr, "KEY_PKYE", &idkey, comment, &status);
-    printf("KEY_PKYE %f %s %d\n",idkey, comment, status);
-
-    ffgkyd(fptr, "KEY_PKYG", &idkey, comment, &status);
-    printf("KEY_PKYG %.14f %s %d\n",idkey, comment, status);
-
-    ffgkyd(fptr, "KEY_PKYD", &idkey, comment, &status);
-    printf("KEY_PKYD %.14f %s %d\n",idkey, comment, status);
-
-    ffgkyc(fptr, "KEY_PKYC", inekey, comment, &status);
-    printf("KEY_PKYC %f %f %s %d\n",inekey[0], inekey[1], comment, status);
-
-    ffgkyc(fptr, "KEY_PKFC", inekey, comment, &status);
-    printf("KEY_PKFC %f %f %s %d\n",inekey[0], inekey[1], comment, status);
-
-    ffgkym(fptr, "KEY_PKYM", indkey, comment, &status);
-    printf("KEY_PKYM %f %f %s %d\n",indkey[0], indkey[1], comment, status);
-
-    ffgkym(fptr, "KEY_PKFM", indkey, comment, &status);
-    printf("KEY_PKFM %f %f %s %d\n",indkey[0], indkey[1], comment, status);
-
-    ffgkyt(fptr, "KEY_PKYT", &ijkey, &idkey, comment, &status);
-    printf("KEY_PKYT %ld %.14f %s %d\n",ijkey, idkey, comment, status);
-
-    ffpunt(fptr, "KEY_PKYJ", "km/s/Mpc", &status);
-    ijkey = 0;
-    ffgky(fptr, TLONG, "KEY_PKYJ", &ijkey, comment, &status);
-    printf("KEY_PKY J %ld %s %d\n",ijkey, comment, status);
-    ffgunt(fptr,"KEY_PKYJ", comment, &status);
-    printf("KEY_PKY units = %s\n",comment);
-
-    ffpunt(fptr, "KEY_PKYJ", "", &status);
-    ijkey = 0;
-    ffgky(fptr, TLONG, "KEY_PKYJ", &ijkey, comment, &status);
-    printf("KEY_PKY J %ld %s %d\n",ijkey, comment, status);
-    ffgunt(fptr,"KEY_PKYJ", comment, &status);
-    printf("KEY_PKY units = %s\n",comment);
-
-    ffpunt(fptr, "KEY_PKYJ", "feet/second/second", &status);
-    ijkey = 0;
-    ffgky(fptr, TLONG, "KEY_PKYJ", &ijkey, comment, &status);
-    printf("KEY_PKY J %ld %s %d\n",ijkey, comment, status);
-    ffgunt(fptr,"KEY_PKYJ", comment, &status);
-    printf("KEY_PKY units = %s\n",comment);
-
-    ffgkls(fptr, "key_pkls", &lsptr, comment, &status);
-    printf("KEY_PKLS long string value = \n%s\n", lsptr);
-
-    /* free the memory for the long string value */
-    fits_free_memory(lsptr, &status);
-
-    /* get size and position in header */
-    ffghps(fptr, &existkeys, &keynum, &status);
-    printf("header contains %d keywords; located at keyword %d \n",existkeys,
-            keynum);
-
-    /*
-      ############################
-      #  read array keywords     #
-      ############################
-    */
-    ffgkns(fptr, "ky_pkns", 1, 3, inskey, &nfound, &status);
-    printf("ffgkns:  %s, %s, %s\n", inskey[0], inskey[1], inskey[2]);
-    if (nfound != 3 || status > 0)
-       printf("\nERROR in ffgkns %d, %d\n", nfound, status);
-
-    ffgknl(fptr, "ky_pknl", 1, 3, inlkey, &nfound, &status);
-    printf("ffgknl:  %d, %d, %d\n", inlkey[0], inlkey[1], inlkey[2]);
-    if (nfound != 3 || status > 0)
-       printf("\nERROR in ffgknl %d, %d\n", nfound, status);
-
-    ffgknj(fptr, "ky_pknj", 1, 3, injkey, &nfound, &status);
-    printf("ffgknj:  %ld, %ld, %ld\n", injkey[0], injkey[1], injkey[2]);
-    if (nfound != 3 || status > 0)
-       printf("\nERROR in ffgknj %d, %d\n", nfound, status);
-
-    ffgkne(fptr, "ky_pkne", 1, 3, inekey, &nfound, &status);
-    printf("ffgkne:  %f, %f, %f\n", inekey[0], inekey[1], inekey[2]);
-    if (nfound != 3 || status > 0)
-       printf("\nERROR in ffgkne %d, %d\n", nfound, status);
-
-    ffgknd(fptr, "ky_pknd", 1, 3, indkey, &nfound, &status);
-    printf("ffgknd:  %f, %f, %f\n", indkey[0], indkey[1], indkey[2]);
-    if (nfound != 3 || status > 0)
-       printf("\nERROR in ffgknd %d, %d\n", nfound, status);
-
-    /* get position of HISTORY keyword for subsequent deletes and inserts */
-    ffgcrd(fptr, "HISTORY", card, &status);
-    ffghps(fptr, &existkeys, &keynum, &status);
-    keynum -= 2;
-
-    printf("\nBefore deleting the HISTORY and DATE keywords...\n");
-    for (ii = keynum; ii <= keynum + 3; ii++)
-    {
-        ffgrec(fptr, ii, card, &status);
-        printf("%.8s\n", card);  /* don't print date value, so that */
-    }                            /* the output will always be the same */
-    /*
-      ############################
-      #  delete keywords         #
-      ############################
-    */
-
-    ffdrec(fptr, keynum + 1, &status);
-    ffdkey(fptr, "DATE", &status);
-
-    printf("\nAfter deleting the keywords...\n");
-    for (ii = keynum; ii <= keynum + 1; ii++)
-    {
-        ffgrec(fptr, ii, card, &status);
-        printf("%s\n", card);
-    }
-
-    if (status > 0)
-       printf("\nERROR deleting keywords\n");
-    /*
-      ############################
-      #  insert keywords         #
-      ############################
-    */
-    keynum += 4;
-    ffirec(fptr, keynum - 3, "KY_IREC = 'This keyword inserted by fxirec'",
-           &status);
-    ffikys(fptr, "KY_IKYS", "insert_value_string", "ikys comment", &status);
-    ffikyj(fptr, "KY_IKYJ", 49, "ikyj comment", &status);
-    ffikyl(fptr, "KY_IKYL", 1, "ikyl comment", &status);
-    ffikye(fptr, "KY_IKYE", 12.3456f, 4, "ikye comment", &status);
-    ffikyd(fptr, "KY_IKYD", 12.345678901234567, 14, "ikyd comment", &status);
-    ffikyf(fptr, "KY_IKYF", 12.3456f, 4, "ikyf comment", &status);
-    ffikyg(fptr, "KY_IKYG", 12.345678901234567, 13, "ikyg comment", &status);
-
-    printf("\nAfter inserting the keywords...\n");
-    for (ii = keynum - 4; ii <= keynum + 5; ii++)
-    {
-        ffgrec(fptr, ii, card, &status);
-        printf("%s\n", card);
-    }
-
-    if (status > 0)
-       printf("\nERROR inserting keywords\n");
-    /*
-      ############################
-      #  modify keywords         #
-      ############################
-    */
-    ffmrec(fptr, keynum - 4, "COMMENT   This keyword was modified by fxmrec", &status);
-    ffmcrd(fptr, "KY_IREC", "KY_MREC = 'This keyword was modified by fxmcrd'",
-            &status);
-    ffmnam(fptr, "KY_IKYS", "NEWIKYS", &status);
-
-    ffmcom(fptr, "KY_IKYJ","This is a modified comment", &status);
-    ffmkyj(fptr, "KY_IKYJ", 50, "&", &status);
-    ffmkyl(fptr, "KY_IKYL", 0, "&", &status);
-    ffmkys(fptr, "NEWIKYS", "modified_string", "&", &status);
-    ffmkye(fptr, "KY_IKYE", -12.3456f, 4, "&", &status);
-    ffmkyd(fptr, "KY_IKYD", -12.345678901234567, 14, "modified comment",
-            &status);
-    ffmkyf(fptr, "KY_IKYF", -12.3456f, 4, "&", &status);
-    ffmkyg(fptr, "KY_IKYG", -12.345678901234567, 13, "&", &status);
-
-    printf("\nAfter modifying the keywords...\n");
-    for (ii = keynum - 4; ii <= keynum + 5; ii++)
-    {
-        ffgrec(fptr, ii, card, &status);
-        printf("%s\n", card);
-    }
-    if (status > 0)
-       printf("\nERROR modifying keywords\n");
-
-    /*
-      ############################
-      #  update keywords         #
-      ############################
-    */
-    ffucrd(fptr, "KY_MREC", "KY_UCRD = 'This keyword was updated by fxucrd'",
-            &status);
-
-    ffukyj(fptr, "KY_IKYJ", 51, "&", &status);
-    ffukyl(fptr, "KY_IKYL", 1, "&", &status);
-    ffukys(fptr, "NEWIKYS", "updated_string", "&", &status);
-    ffukye(fptr, "KY_IKYE", -13.3456f, 4, "&", &status);
-    ffukyd(fptr, "KY_IKYD", -13.345678901234567, 14, "modified comment",
-            &status);
-    ffukyf(fptr, "KY_IKYF", -13.3456f, 4, "&", &status);
-    ffukyg(fptr, "KY_IKYG", -13.345678901234567, 13, "&", &status);
-
-    printf("\nAfter updating the keywords...\n");
-    for (ii = keynum - 4; ii <= keynum + 5; ii++)
-    {
-        ffgrec(fptr, ii, card, &status);
-        printf("%s\n", card);
-    }
-    if (status > 0)
-       printf("\nERROR modifying keywords\n");
-
-    /* move to top of header and find keywords using wild cards */
-    ffgrec(fptr, 0, card, &status);
-
-    printf("\nKeywords found using wildcard search (should be 13)...\n");
-    nfound = 0;
-    while (!ffgnxk(fptr,inclist, 2, exclist, 2, card, &status))
-    {
-        nfound++;
-        printf("%s\n", card);
-    }
-    if (nfound != 13)
-    {
-       printf("\nERROR reading keywords using wildcards (ffgnxk)\n");
-       goto errstatus;
-    }
-    status = 0;
-
-    /*
-      ############################
-      #  copy index keyword      #
-      ############################
-    */
-    ffcpky(fptr, fptr, 1, 4, "KY_PKNE", &status);
-    ffgkne(fptr, "ky_pkne", 2, 4, inekey, &nfound, &status);
-    printf("\nCopied keyword: ffgkne:  %f, %f, %f\n", inekey[0], inekey[1],
-           inekey[2]);
-
-    if (status > 0)
-    {
-       printf("\nERROR in ffgkne %d, %d\n", nfound, status);
-       goto errstatus;
-    }
-
-    /*
-      ######################################
-      #  modify header using template file #
-      ######################################
-    */
-    if (ffpktp(fptr, templt, &status))
-    {
-       printf("\nERROR returned by ffpktp:\n");
-       printf("Could not open or process the file 'testprog.tpt'.\n");
-       printf("  This file is included with the CFITSIO distribution\n");
-       printf("  and should be copied into the current directory\n");
-       printf("  before running the testprog program.\n");
-       status = 0;
-    }
-    printf("Updated header using template file (ffpktp)\n");
-    /*
-      ############################
-      #  create binary table     #
-      ############################
-    */
-
-    strcpy(tform[0], "15A");
-    strcpy(tform[1], "1L");
-    strcpy(tform[2], "16X");
-    strcpy(tform[3], "1B");
-    strcpy(tform[4], "1I");
-    strcpy(tform[5], "1J");
-    strcpy(tform[6], "1E");
-    strcpy(tform[7], "1D");
-    strcpy(tform[8], "1C");
-    strcpy(tform[9], "1M");
-
-    strcpy(ttype[0], "Avalue");
-    strcpy(ttype[1], "Lvalue");
-    strcpy(ttype[2], "Xvalue");
-    strcpy(ttype[3], "Bvalue");
-    strcpy(ttype[4], "Ivalue");
-    strcpy(ttype[5], "Jvalue");
-    strcpy(ttype[6], "Evalue");
-    strcpy(ttype[7], "Dvalue");
-    strcpy(ttype[8], "Cvalue");
-    strcpy(ttype[9], "Mvalue");
-
-    strcpy(tunit[0], "");
-    strcpy(tunit[1], "m**2");
-    strcpy(tunit[2], "cm");
-    strcpy(tunit[3], "erg/s");
-    strcpy(tunit[4], "km/s");
-    strcpy(tunit[5], "");
-    strcpy(tunit[6], "");
-    strcpy(tunit[7], "");
-    strcpy(tunit[8], "");
-    strcpy(tunit[9], "");
-
-    nrows = 21;
-    tfields = 10;
-    pcount = 0;
-
-/*
-    ffcrtb(fptr, BINARY_TBL, nrows, tfields, ttype, tform, tunit, binname,
-            &status);
-*/
-    ffibin(fptr, nrows, tfields, ttype, tform, tunit, binname, 0L,
-            &status);
-
-    printf("\nffibin status = %d\n", status);
-    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));
-
-    /* get size and position in header, and reserve space for more keywords */
-    ffghps(fptr, &existkeys, &keynum, &status);
-    printf("header contains %d keywords; located at keyword %d \n",existkeys,
-            keynum);
-
-    morekeys = 40;
-    ffhdef(fptr, morekeys, &status);
-    ffghsp(fptr, &existkeys, &morekeys, &status);
-    printf("header contains %d keywords with room for %d more\n",existkeys,
-            morekeys);
-
-    fftnul(fptr, 4, 99, &status);   /* define null value for int cols */
-    fftnul(fptr, 5, 99, &status);
-    fftnul(fptr, 6, 99, &status);
-
-    extvers = 1;
-    ffpkyj(fptr, "EXTVER", extvers, "extension version number", &status);
-    ffpkyj(fptr, "TNULL4", 99, "value for undefined pixels", &status);
-    ffpkyj(fptr, "TNULL5", 99, "value for undefined pixels", &status);
-    ffpkyj(fptr, "TNULL6", 99, "value for undefined pixels", &status);
-
-    naxis = 3;
-    naxes[0] = 1;
-    naxes[1] = 2;
-    naxes[2] = 8;
-    ffptdm(fptr, 3, naxis, naxes, &status);
-
-    naxis = 0;
-    naxes[0] = 0;
-    naxes[1] = 0;
-    naxes[2] = 0;
-    ffgtdm(fptr, 3, 3, &naxis, naxes, &status);
-    ffgkys(fptr, "TDIM3", iskey, comment, &status);
-    printf("TDIM3 = %s, %d, %ld, %ld, %ld\n", iskey, naxis, naxes[0],
-         naxes[1], naxes[2]);
-
-    ffrdef(fptr, &status);  /* force header to be scanned (not required) */
-
-    /*
-      ############################
-      #  write data to columns   #
-      ############################
-    */
-
-    /* initialize arrays of values to write to table */
-    signval = -1;
-    for (ii = 0; ii < 21; ii++)
-    {
-        signval *= -1;
-        boutarray[ii] = (unsigned char) (ii + 1);
-        ioutarray[ii] = (short) ((ii + 1) * signval);
-        joutarray[ii] = (ii + 1) * signval;
-        koutarray[ii] = (ii + 1) * signval;
-        eoutarray[ii] = (float) ((ii + 1) * signval);
-        doutarray[ii] = (ii + 1) * signval;
-    }
-
-    ffpcls(fptr, 1, 1, 1, 3, onskey, &status);  /* write string values */
-    ffpclu(fptr, 1, 4, 1, 1, &status);  /* write null value */
-
-    larray[0] = 0;
-    larray[1] = 1;
-    larray[2] = 0;
-    larray[3] = 0;
-    larray[4] = 1;
-    larray[5] = 1;
-    larray[6] = 0;
-    larray[7] = 0;
-    larray[8] = 0;
-    larray[9] = 1;
-    larray[10] = 1;
-    larray[11] = 1;
-    larray[12] = 0;
-    larray[13] = 0;
-    larray[14] = 0;
-    larray[15] = 0;
-    larray[16] = 1;
-    larray[17] = 1;
-    larray[18] = 1;
-    larray[19] = 1;
-    larray[20] = 0;
-    larray[21] = 0;
-    larray[22] = 0;
-    larray[23] = 0;
-    larray[24] = 0;
-    larray[25] = 1;
-    larray[26] = 1;
-    larray[27] = 1;
-    larray[28] = 1;
-    larray[29] = 1;
-    larray[30] = 0;
-    larray[31] = 0;
-    larray[32] = 0;
-    larray[33] = 0;
-    larray[34] = 0;
-    larray[35] = 0;
-
-
-    ffpclx(fptr, 3, 1, 1, 36, larray, &status); /*write bits*/
-
-    for (ii = 4; ii < 9; ii++)   /* loop over cols 4 - 8 */
-    {
-        ffpclb(fptr, ii, 1, 1, 2, boutarray, &status);
-        if (status == NUM_OVERFLOW)
-            status = 0;
-        ffpcli(fptr, ii, 3, 1, 2, &ioutarray[2], &status); 
-        if (status == NUM_OVERFLOW)
-            status = 0;
-        ffpclk(fptr, ii, 5, 1, 2, &koutarray[4], &status); 
-        if (status == NUM_OVERFLOW)
-            status = 0;
-        ffpcle(fptr, ii, 7, 1, 2, &eoutarray[6], &status);
-        if (status == NUM_OVERFLOW)
-            status = 0;
-        ffpcld(fptr, ii, 9, 1, 2, &doutarray[8], &status);
-        if (status == NUM_OVERFLOW)
-            status = 0;
-
-        ffpclu(fptr, ii, 11, 1, 1, &status);  /* write null value */
-    }
-
-    ffpclc(fptr, 9, 1, 1, 10, eoutarray, &status);
-    ffpclm(fptr, 10, 1, 1, 10, doutarray, &status);
-
-    for (ii = 4; ii < 9; ii++)   /* loop over cols 4 - 8 */
-    {
-        ffpcnb(fptr, ii, 12, 1, 2, &boutarray[11], 13, &status);
-        if (status == NUM_OVERFLOW)
-            status = 0;
-        ffpcni(fptr, ii, 14, 1, 2, &ioutarray[13], 15, &status); 
-        if (status == NUM_OVERFLOW)
-            status = 0;
-        ffpcnk(fptr, ii, 16, 1, 2, &koutarray[15], 17, &status); 
-        if (status == NUM_OVERFLOW)
-            status = 0;
-        ffpcne(fptr, ii, 18, 1, 2, &eoutarray[17], 19., &status);
-        if (status == NUM_OVERFLOW)
-            status = 0;
-        ffpcnd(fptr, ii, 20, 1, 2, &doutarray[19], 21., &status);
-        if (status == NUM_OVERFLOW)
-            status = 0;
-
-    }
-    ffpcll(fptr, 2, 1, 1, 21, larray, &status); /*write logicals*/
-    ffpclu(fptr, 2, 11, 1, 1, &status);  /* write null value */
-    printf("ffpcl_ status = %d\n", status);
-
-    /*
-      #########################################
-      #  get information about the columns    #
-      #########################################
-    */
-
-    printf("\nFind the column numbers; a returned status value of 237 is");
-    printf("\nexpected and indicates that more than one column name matches");
-    printf("\nthe input column name template.  Status = 219 indicates that");
-    printf("\nthere was no matching column name.");
-
-    ffgcno(fptr, 0, "Xvalue", &colnum, &status);
-    printf("\nColumn Xvalue is number %d; status = %d.\n", colnum, status);
-
-    while (status != COL_NOT_FOUND)
-    {
-      ffgcnn(fptr, 1, "*ue", colname, &colnum, &status);
-      printf("Column %s is number %d; status = %d.\n", 
-           colname, colnum, status);
-    }
-    status = 0;
-
-    printf("\nInformation about each column:\n");
-
-    for (ii = 0; ii < tfields; ii++)
-    {
-      ffgtcl(fptr, ii + 1, &typecode, &repeat, &width, &status);
-      printf("%4s %3d %2ld %2ld", tform[ii], typecode, repeat, width);
-      ffgbcl(fptr, ii + 1, ttype[0], tunit[0], cvalstr, &repeat, &scale,
-           &zero, &jnulval, tdisp, &status);
-      printf(" %s, %s, %c, %ld, %f, %f, %ld, %s.\n",
-         ttype[0], tunit[0], cvalstr[0], repeat, scale, zero, jnulval, tdisp);
-    }
-
-    printf("\n");
-
-    /*
-      ###############################################
-      #  insert ASCII table before the binary table #
-      ###############################################
-    */
-
-    if (ffmrhd(fptr, -1, &hdutype, &status) > 0)
-        goto errstatus;
-
-    strcpy(tform[0], "A15");
-    strcpy(tform[1], "I10");
-    strcpy(tform[2], "F14.6");
-    strcpy(tform[3], "E12.5");
-    strcpy(tform[4], "D21.14");
-
-    strcpy(ttype[0], "Name");
-    strcpy(ttype[1], "Ivalue");
-    strcpy(ttype[2], "Fvalue");
-    strcpy(ttype[3], "Evalue");
-    strcpy(ttype[4], "Dvalue");
-
-    strcpy(tunit[0], "");
-    strcpy(tunit[1], "m**2");
-    strcpy(tunit[2], "cm");
-    strcpy(tunit[3], "erg/s");
-    strcpy(tunit[4], "km/s");
-
-    rowlen = 76;
-    nrows = 11;
-    tfields = 5;
-
-    ffitab(fptr, rowlen, nrows, tfields, ttype, tbcol, tform, tunit, tblname,
-            &status);
-    printf("ffitab status = %d\n", status);
-    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));
-
-    ffsnul(fptr, 1, "null1", &status);   /* define null value for int cols */
-    ffsnul(fptr, 2, "null2", &status);
-    ffsnul(fptr, 3, "null3", &status);
-    ffsnul(fptr, 4, "null4", &status);
-    ffsnul(fptr, 5, "null5", &status);
- 
-    extvers = 2;
-    ffpkyj(fptr, "EXTVER", extvers, "extension version number", &status);
-
-    ffpkys(fptr, "TNULL1", "null1", "value for undefined pixels", &status);
-    ffpkys(fptr, "TNULL2", "null2", "value for undefined pixels", &status);
-    ffpkys(fptr, "TNULL3", "null3", "value for undefined pixels", &status);
-    ffpkys(fptr, "TNULL4", "null4", "value for undefined pixels", &status);
-    ffpkys(fptr, "TNULL5", "null5", "value for undefined pixels", &status);
-
-    if (status > 0)
-        goto errstatus;
-
-    /*
-      ############################
-      #  write data to columns   #
-      ############################
-    */
-
-    /* initialize arrays of values to write to table */
-    for (ii = 0; ii < 21; ii++)
-    {
-        boutarray[ii] = (unsigned char) (ii + 1);
-        ioutarray[ii] = (short) (ii + 1);
-        joutarray[ii] = ii + 1;
-        eoutarray[ii] = (float) (ii + 1);
-        doutarray[ii] = ii + 1;
-    }
-
-    ffpcls(fptr, 1, 1, 1, 3, onskey, &status);  /* write string values */
-    ffpclu(fptr, 1, 4, 1, 1, &status);  /* write null value */
-
-    for (ii = 2; ii < 6; ii++)   /* loop over cols 2 - 5 */
-    {
-        ffpclb(fptr, ii, 1, 1, 2, boutarray, &status);  /* char array */
-        if (status == NUM_OVERFLOW)
-            status = 0;
-        ffpcli(fptr, ii, 3, 1, 2, &ioutarray[2], &status);  /* short array */
-        if (status == NUM_OVERFLOW)
-            status = 0;
-        ffpclj(fptr, ii, 5, 1, 2, &joutarray[4], &status);  /* long array */
-        if (status == NUM_OVERFLOW)
-            status = 0;
-        ffpcle(fptr, ii, 7, 1, 2, &eoutarray[6], &status);  /* float array */
-        if (status == NUM_OVERFLOW)
-            status = 0;
-        ffpcld(fptr, ii, 9, 1, 2, &doutarray[8], &status);  /* double array */
-        if (status == NUM_OVERFLOW)
-            status = 0;
-
-        ffpclu(fptr, ii, 11, 1, 1, &status);  /* write null value */
-    }
-    printf("ffpcl_ status = %d\n", status);
-
-    /*
-      ################################
-      #  read data from ASCII table  #
-      ################################
-    */
-    ffghtb(fptr, 99, &rowlen, &nrows, &tfields, ttype, tbcol, 
-           tform, tunit, tblname, &status);
-
-    printf("\nASCII table: rowlen, nrows, tfields, extname: %ld %ld %d %s\n",
-           rowlen, nrows, tfields, tblname);
-
-    for (ii = 0; ii < tfields; ii++)
-      printf("%8s %3ld %8s %8s \n", ttype[ii], tbcol[ii], 
-                                   tform[ii], tunit[ii]);
-
-    nrows = 11;
-    ffgcvs(fptr, 1, 1, 1, nrows, "UNDEFINED", inskey,   &anynull, &status);
-    ffgcvb(fptr, 2, 1, 1, nrows, 99, binarray, &anynull, &status);
-    ffgcvi(fptr, 2, 1, 1, nrows, 99, iinarray, &anynull, &status);
-    ffgcvj(fptr, 3, 1, 1, nrows, 99, jinarray, &anynull, &status);
-    ffgcve(fptr, 4, 1, 1, nrows, 99., einarray, &anynull, &status);
-    ffgcvd(fptr, 5, 1, 1, nrows, 99., dinarray, &anynull, &status);
-
-    printf("\nData values read from ASCII table:\n");
-    for (ii = 0; ii < nrows; ii++)
-    {
-      printf("%15s %2d %2d %2ld %4.1f %4.1f\n", inskey[ii], binarray[ii],
-           iinarray[ii], jinarray[ii], einarray[ii], dinarray[ii]); 
-    }
-
-    ffgtbb(fptr, 1, 20, 78, uchars, &status);
-    uchars[78] = '\0';
-    printf("\n%s\n", uchars);
-    ffptbb(fptr, 1, 20, 78, uchars, &status);
-
-    /*
-      #########################################
-      #  get information about the columns    #
-      #########################################
-    */
-
-    ffgcno(fptr, 0, "name", &colnum, &status);
-    printf("\nColumn name is number %d; status = %d.\n", colnum, status);
-
-    while (status != COL_NOT_FOUND)
-    {
-      ffgcnn(fptr, 1, "*ue", colname, &colnum, &status);
-      printf("Column %s is number %d; status = %d.\n", 
-           colname, colnum, status);
-    }
-    status = 0;
-
-    for (ii = 0; ii < tfields; ii++)
-    {
-      ffgtcl(fptr, ii + 1, &typecode, &repeat, &width, &status);
-      printf("%4s %3d %2ld %2ld", tform[ii], typecode, repeat, width);
-      ffgacl(fptr, ii + 1, ttype[0], tbcol, tunit[0], tform[0], &scale,
-           &zero, nulstr, tdisp, &status);
-      printf(" %s, %ld, %s, %s, %f, %f, %s, %s.\n",
-         ttype[0], tbcol[0], tunit[0], tform[0], scale, zero,
-         nulstr, tdisp);
-    }
-
-    printf("\n");
-
-    /*
-      ###############################################
-      #  test the insert/delete row/column routines #
-      ###############################################
-    */
-
-    if (ffirow(fptr, 2, 3, &status) > 0)
-        goto errstatus;
-
-    nrows = 14;
-    ffgcvs(fptr, 1, 1, 1, nrows, "UNDEFINED", inskey,   &anynull, &status);
-    ffgcvb(fptr, 2, 1, 1, nrows, 99, binarray, &anynull, &status);
-    ffgcvi(fptr, 2, 1, 1, nrows, 99, iinarray, &anynull, &status);
-    ffgcvj(fptr, 3, 1, 1, nrows, 99, jinarray, &anynull, &status);
-    ffgcve(fptr, 4, 1, 1, nrows, 99., einarray, &anynull, &status);
-    ffgcvd(fptr, 5, 1, 1, nrows, 99., dinarray, &anynull, &status);
-
-
-    printf("\nData values after inserting 3 rows after row 2:\n");
-    for (ii = 0; ii < nrows; ii++)
-    {
-      printf("%15s %2d %2d %2ld %4.1f %4.1f\n",  inskey[ii], binarray[ii],
-          iinarray[ii], jinarray[ii], einarray[ii], dinarray[ii]);
-    }
-
-    if (ffdrow(fptr, 10, 2, &status) > 0)
-        goto errstatus;
-
-    nrows = 12;
-    ffgcvs(fptr, 1, 1, 1, nrows, "UNDEFINED", inskey,   &anynull, &status);
-    ffgcvb(fptr, 2, 1, 1, nrows, 99, binarray, &anynull, &status);
-    ffgcvi(fptr, 2, 1, 1, nrows, 99, iinarray, &anynull, &status);
-    ffgcvj(fptr, 3, 1, 1, nrows, 99, jinarray, &anynull, &status);
-    ffgcve(fptr, 4, 1, 1, nrows, 99., einarray, &anynull, &status);
-    ffgcvd(fptr, 5, 1, 1, nrows, 99., dinarray, &anynull, &status);
-
-    printf("\nData values after deleting 2 rows at row 10:\n");
-    for (ii = 0; ii < nrows; ii++)
-    {
-      printf("%15s %2d %2d %2ld %4.1f %4.1f\n",  inskey[ii], binarray[ii],
-          iinarray[ii], jinarray[ii], einarray[ii], dinarray[ii]);
-    }
-    if (ffdcol(fptr, 3, &status) > 0)
-        goto errstatus;
-
-    ffgcvs(fptr, 1, 1, 1, nrows, "UNDEFINED", inskey,   &anynull, &status);
-    ffgcvb(fptr, 2, 1, 1, nrows, 99, binarray, &anynull, &status);
-    ffgcvi(fptr, 2, 1, 1, nrows, 99, iinarray, &anynull, &status);
-    ffgcve(fptr, 3, 1, 1, nrows, 99., einarray, &anynull, &status);
-    ffgcvd(fptr, 4, 1, 1, nrows, 99., dinarray, &anynull, &status);
-
-    printf("\nData values after deleting column 3:\n");
-    for (ii = 0; ii < nrows; ii++)
-    {
-      printf("%15s %2d %2d %4.1f %4.1f\n", inskey[ii], binarray[ii],
-          iinarray[ii], einarray[ii], dinarray[ii]);
-    }
-
-    if (fficol(fptr, 5, "INSERT_COL", "F14.6", &status) > 0)
-        goto errstatus;
-
-    ffgcvs(fptr, 1, 1, 1, nrows, "UNDEFINED", inskey,   &anynull, &status);
-    ffgcvb(fptr, 2, 1, 1, nrows, 99, binarray, &anynull, &status);
-    ffgcvi(fptr, 2, 1, 1, nrows, 99, iinarray, &anynull, &status);
-    ffgcve(fptr, 3, 1, 1, nrows, 99., einarray, &anynull, &status);
-    ffgcvd(fptr, 4, 1, 1, nrows, 99., dinarray, &anynull, &status);
-    ffgcvj(fptr, 5, 1, 1, nrows, 99, jinarray, &anynull, &status);
-
-    printf("\nData values after inserting column 5:\n");
-    for (ii = 0; ii < nrows; ii++)
-    {
-      printf("%15s %2d %2d %4.1f %4.1f %ld\n", inskey[ii], binarray[ii],
-          iinarray[ii], einarray[ii], dinarray[ii] , jinarray[ii]);
-    }
-
-    /*
-      ############################################################
-      #  create a temporary file and copy the ASCII table to it, #
-      #  column by column.                                       #
-      ############################################################
-    */
-    bitpix = 16;
-    naxis = 0;
-
-    strcpy(filename, "!t1q2s3v6.tmp");
-    ffinit(&tmpfptr, filename, &status);
-    printf("Create temporary file: ffinit status = %d\n", status);
-
-    ffiimg(tmpfptr, bitpix, naxis, naxes, &status);
-    printf("\nCreate null primary array: ffiimg status = %d\n", status);
-
-    /* create an empty table with 12 rows and 0 columns */
-    nrows = 12;
-    tfields = 0;
-    rowlen = 0;
-    ffitab(tmpfptr, rowlen, nrows, tfields, ttype, tbcol, tform, tunit,
-           tblname, &status);
-    printf("\nCreate ASCII table with 0 columns: ffitab status = %d\n",
-           status);
-
-    /* copy columns from one table to the other */
-    ffcpcl(fptr, tmpfptr, 4, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-    ffcpcl(fptr, tmpfptr, 3, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-    ffcpcl(fptr, tmpfptr, 2, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-    ffcpcl(fptr, tmpfptr, 1, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-
-    /* now repeat by copying ASCII input to Binary output table */
-    ffibin(tmpfptr, nrows, tfields, ttype, tform, tunit,
-           tblname,  0L, &status);
-    printf("\nCreate Binary table with 0 columns: ffibin status = %d\n",
-           status);
-
-    /* copy columns from one table to the other */
-    ffcpcl(fptr, tmpfptr, 4, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-    ffcpcl(fptr, tmpfptr, 3, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-    ffcpcl(fptr, tmpfptr, 2, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-    ffcpcl(fptr, tmpfptr, 1, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-
-
-/*
-    ffclos(tmpfptr, &status);
-    printf("Close the tmp file: ffclos status = %d\n", status);
-*/
-
-    ffdelt(tmpfptr, &status);  
-    printf("Delete the tmp file: ffdelt status = %d\n", status);
-
-    if (status > 0)
-    {
-        goto errstatus;
-    }
-
-    /*
-      ################################
-      #  read data from binary table #
-      ################################
-    */
-
-    if (ffmrhd(fptr, 1, &hdutype, &status) > 0)
-        goto errstatus;
-
-    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));
-
-    ffghsp(fptr, &existkeys, &morekeys, &status);
-    printf("header contains %d keywords with room for %d more\n",existkeys,
-            morekeys);
-
-    ffghbn(fptr, 99, &nrows, &tfields, ttype, 
-           tform, tunit, binname, &pcount, &status);
-
-    printf("\nBinary table: nrows, tfields, extname, pcount: %ld %d %s %ld\n",
-           nrows, tfields, binname, pcount);
-
-    for (ii = 0; ii < tfields; ii++)
-      printf("%8s %8s %8s \n", ttype[ii], tform[ii], tunit[ii]);
-
-    for (ii = 0; ii < 40; ii++)
-        larray[ii] = 0;
-
-    printf("\nData values read from binary table:\n");
-    printf("  Bit column (X) data values: \n\n");
-
-    ffgcx(fptr, 3, 1, 1, 36, larray, &status);
-    for (jj = 0; jj < 5; jj++)
-    {
-      for (ii = 0; ii < 8; ii++)
-        printf("%1d",larray[jj * 8 + ii]);
-      printf(" ");
-    }
-
-    for (ii = 0; ii < nrows; ii++)
-    {
-      larray[ii] = 0;
-      xinarray[ii] = 0;
-      binarray[ii] = 0;
-      iinarray[ii] = 0; 
-      kinarray[ii] = 0;
-      einarray[ii] = 0.; 
-      dinarray[ii] = 0.;
-      cinarray[ii * 2] = 0.; 
-      minarray[ii * 2] = 0.;
-      cinarray[ii * 2 + 1] = 0.; 
-      minarray[ii * 2 + 1] = 0.;
-    }
-
-    printf("\n\n");
-    ffgcvs(fptr, 1, 4, 1, 1, "",  inskey,   &anynull, &status);
-    printf("null string column value = -%s- (should be --)\n",inskey[0]);
-
-    nrows = 21;
-    ffgcvs(fptr, 1, 1, 1, nrows, "NOT DEFINED",  inskey,   &anynull, &status);
-    ffgcl( fptr, 2, 1, 1, nrows, larray, &status);
-    ffgcvb(fptr, 3, 1, 1, nrows, 98, xinarray, &anynull, &status);
-    ffgcvb(fptr, 4, 1, 1, nrows, 98, binarray, &anynull, &status);
-    ffgcvi(fptr, 5, 1, 1, nrows, 98, iinarray, &anynull, &status);
-    ffgcvk(fptr, 6, 1, 1, nrows, 98, kinarray, &anynull, &status);
-    ffgcve(fptr, 7, 1, 1, nrows, 98., einarray, &anynull, &status);
-    ffgcvd(fptr, 8, 1, 1, nrows, 98., dinarray, &anynull, &status);
-    ffgcvc(fptr, 9, 1, 1, nrows, 98., cinarray, &anynull, &status);
-    ffgcvm(fptr, 10, 1, 1, nrows, 98., minarray, &anynull, &status);
-
-    printf("\nRead columns with ffgcv_:\n");
-    for (ii = 0; ii < nrows; ii++)
-    {
-  printf("%15s %d %3d %2d %3d %3d %5.1f %5.1f (%5.1f,%5.1f) (%5.1f,%5.1f) \n",
-        inskey[ii], larray[ii], xinarray[ii], binarray[ii], iinarray[ii], 
-        kinarray[ii], einarray[ii], dinarray[ii], cinarray[ii * 2], 
-        cinarray[ii * 2 + 1], minarray[ii * 2], minarray[ii * 2 + 1]);
-    }
-
-    for (ii = 0; ii < nrows; ii++)
-    {
-      larray[ii] = 0;
-      xinarray[ii] = 0;
-      binarray[ii] = 0;
-      iinarray[ii] = 0; 
-      kinarray[ii] = 0;
-      einarray[ii] = 0.; 
-      dinarray[ii] = 0.;
-      cinarray[ii * 2] = 0.; 
-      minarray[ii * 2] = 0.;
-      cinarray[ii * 2 + 1] = 0.; 
-      minarray[ii * 2 + 1] = 0.;
-    }
-
-    ffgcfs(fptr, 1, 1, 1, nrows, inskey,   larray2, &anynull, &status);
-    ffgcfl(fptr, 2, 1, 1, nrows, larray,   larray2, &anynull, &status);
-    ffgcfb(fptr, 3, 1, 1, nrows, xinarray, larray2, &anynull, &status);
-    ffgcfb(fptr, 4, 1, 1, nrows, binarray, larray2, &anynull, &status);
-    ffgcfi(fptr, 5, 1, 1, nrows, iinarray, larray2, &anynull, &status);
-    ffgcfk(fptr, 6, 1, 1, nrows, kinarray, larray2, &anynull, &status);
-    ffgcfe(fptr, 7, 1, 1, nrows, einarray, larray2, &anynull, &status);
-    ffgcfd(fptr, 8, 1, 1, nrows, dinarray, larray2, &anynull, &status);
-    ffgcfc(fptr, 9, 1, 1, nrows, cinarray, larray2, &anynull, &status);
-    ffgcfm(fptr, 10, 1, 1, nrows, minarray, larray2, &anynull, &status);
-
-    printf("\nRead columns with ffgcf_:\n");
-    for (ii = 0; ii < 10; ii++)
-    {
-    
-    printf("%15s %d %3d %2d %3d %3d %5.1f %5.1f (%5.1f,%5.1f) (%5.1f,%5.1f)\n",
-        inskey[ii], larray[ii], xinarray[ii], binarray[ii], iinarray[ii], 
-        kinarray[ii], einarray[ii], dinarray[ii], cinarray[ii * 2], 
-        cinarray[ii * 2 + 1], minarray[ii * 2], minarray[ii * 2 + 1]);
-    }
-    for (ii = 10; ii < nrows; ii++)
-    {
-      /* don't try to print the NaN values */
-      printf("%15s %d %3d %2d %3d \n",
-        inskey[ii], larray[ii], xinarray[ii], binarray[ii], iinarray[ii]);
-    }
-    ffprec(fptr, 
-    "key_prec= 'This keyword was written by f_prec' / comment here", &status);
-
-    /*
-      ###############################################
-      #  test the insert/delete row/column routines #
-      ###############################################
-    */
-    if (ffirow(fptr, 2, 3, &status) > 0)
-        goto errstatus;
-
-    nrows = 14;
-    ffgcvs(fptr, 1, 1, 1, nrows, "NOT DEFINED",  inskey,   &anynull, &status);
-    ffgcvb(fptr, 4, 1, 1, nrows, 98, binarray, &anynull, &status);
-    ffgcvi(fptr, 5, 1, 1, nrows, 98, iinarray, &anynull, &status);
-    ffgcvj(fptr, 6, 1, 1, nrows, 98, jinarray, &anynull, &status);
-    ffgcve(fptr, 7, 1, 1, nrows, 98., einarray, &anynull, &status);
-    ffgcvd(fptr, 8, 1, 1, nrows, 98., dinarray, &anynull, &status);
-
-    printf("\nData values after inserting 3 rows after row 2:\n");
-    for (ii = 0; ii < nrows; ii++)
-    {
-      printf("%15s %2d %3d %3ld %5.1f %5.1f\n",  inskey[ii], binarray[ii],
-          iinarray[ii], jinarray[ii], einarray[ii], dinarray[ii]);
-    }
-
-    if (ffdrow(fptr, 10, 2, &status) > 0)
-        goto errstatus;
-
-    nrows = 12;
-    ffgcvs(fptr, 1, 1, 1, nrows, "NOT DEFINED",  inskey,   &anynull, &status);
-    ffgcvb(fptr, 4, 1, 1, nrows, 98, binarray, &anynull, &status);
-    ffgcvi(fptr, 5, 1, 1, nrows, 98, iinarray, &anynull, &status);
-    ffgcvj(fptr, 6, 1, 1, nrows, 98, jinarray, &anynull, &status);
-    ffgcve(fptr, 7, 1, 1, nrows, 98., einarray, &anynull, &status);
-    ffgcvd(fptr, 8, 1, 1, nrows, 98., dinarray, &anynull, &status);
-
-    printf("\nData values after deleting 2 rows at row 10:\n");
-    for (ii = 0; ii < nrows; ii++)
-    {
-      printf("%15s %2d %3d %3ld %5.1f %5.1f\n",  inskey[ii], binarray[ii],
-          iinarray[ii], jinarray[ii], einarray[ii], dinarray[ii]);
-    }
-
-    if (ffdcol(fptr, 6, &status) > 0)
-        goto errstatus;
-
-    ffgcvs(fptr, 1, 1, 1, nrows, "NOT DEFINED",  inskey,   &anynull, &status);
-    ffgcvb(fptr, 4, 1, 1, nrows, 98, binarray, &anynull, &status);
-    ffgcvi(fptr, 5, 1, 1, nrows, 98, iinarray, &anynull, &status);
-    ffgcve(fptr, 6, 1, 1, nrows, 98., einarray, &anynull, &status);
-    ffgcvd(fptr, 7, 1, 1, nrows, 98., dinarray, &anynull, &status);
-
-    printf("\nData values after deleting column 6:\n");
-    for (ii = 0; ii < nrows; ii++)
-    {
-      printf("%15s %2d %3d %5.1f %5.1f\n", inskey[ii], binarray[ii],
-          iinarray[ii], einarray[ii], dinarray[ii]);
-    }
-
-    if (fficol(fptr, 8, "INSERT_COL", "1E", &status) > 0)
-        goto errstatus;
-
-    ffgcvs(fptr, 1, 1, 1, nrows, "NOT DEFINED",  inskey,   &anynull, &status);
-    ffgcvb(fptr, 4, 1, 1, nrows, 98, binarray, &anynull, &status);
-    ffgcvi(fptr, 5, 1, 1, nrows, 98, iinarray, &anynull, &status);
-    ffgcve(fptr, 6, 1, 1, nrows, 98., einarray, &anynull, &status);
-    ffgcvd(fptr, 7, 1, 1, nrows, 98., dinarray, &anynull, &status);
-    ffgcvj(fptr, 8, 1, 1, nrows, 98, jinarray, &anynull, &status);
-
-    printf("\nData values after inserting column 8:\n");
-    for (ii = 0; ii < nrows; ii++)
-    {
-      printf("%15s %2d %3d %5.1f %5.1f %ld\n", inskey[ii], binarray[ii],
-          iinarray[ii], einarray[ii], dinarray[ii] , jinarray[ii]);
-    }
-
-    ffpclu(fptr, 8, 1, 1, 10, &status);
-
-    ffgcvs(fptr, 1, 1, 1, nrows, "NOT DEFINED",  inskey,   &anynull, &status);
-    ffgcvb(fptr, 4, 1, 1, nrows, 98, binarray, &anynull, &status);
-    ffgcvi(fptr, 5, 1, 1, nrows, 98, iinarray, &anynull, &status);
-    ffgcve(fptr, 6, 1, 1, nrows, 98., einarray, &anynull, &status);
-    ffgcvd(fptr, 7, 1, 1, nrows, 98., dinarray, &anynull, &status);
-    ffgcvj(fptr, 8, 1, 1, nrows, 98, jinarray, &anynull, &status);
-
-    printf("\nValues after setting 1st 10 elements in column 8 = null:\n");
-    for (ii = 0; ii < nrows; ii++)
-    {
-      printf("%15s %2d %3d %5.1f %5.1f %ld\n", inskey[ii], binarray[ii],
-          iinarray[ii], einarray[ii], dinarray[ii] , jinarray[ii]);
-    }
-
-    /*
-      ############################################################
-      #  create a temporary file and copy the binary table to it,#
-      #  column by column.                                       #
-      ############################################################
-    */
-    bitpix = 16;
-    naxis = 0;
-
-    strcpy(filename, "!t1q2s3v5.tmp");
-    ffinit(&tmpfptr, filename, &status);
-    printf("Create temporary file: ffinit status = %d\n", status);
-
-    ffiimg(tmpfptr, bitpix, naxis, naxes, &status);
-    printf("\nCreate null primary array: ffiimg status = %d\n", status);
-
-    /* create an empty table with 22 rows and 0 columns */
-    nrows = 22;
-    tfields = 0;
-    ffibin(tmpfptr, nrows, tfields, ttype, tform, tunit, binname, 0L,
-            &status);
-    printf("\nCreate binary table with 0 columns: ffibin status = %d\n",
-           status);
-
-    /* copy columns from one table to the other */
-    ffcpcl(fptr, tmpfptr, 7, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-    ffcpcl(fptr, tmpfptr, 6, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-    ffcpcl(fptr, tmpfptr, 5, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-    ffcpcl(fptr, tmpfptr, 4, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-    ffcpcl(fptr, tmpfptr, 3, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-    ffcpcl(fptr, tmpfptr, 2, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-    ffcpcl(fptr, tmpfptr, 1, 1, TRUE, &status);
-    printf("copy column, ffcpcl status = %d\n", status);
-
-/*
-    ffclos(tmpfptr, &status);
-    printf("Close the tmp file: ffclos status = %d\n", status);
-*/
-
-    ffdelt(tmpfptr, &status);
-    printf("Delete the tmp file: ffdelt status = %d\n", status);
-    if (status > 0)
-    {
-        goto errstatus;
-    }
-    /*
-      ####################################################
-      #  insert binary table following the primary array #
-      ####################################################
-    */
-
-    ffmahd(fptr,  1, &hdutype, &status);
-
-    strcpy(tform[0], "15A");
-    strcpy(tform[1], "1L");
-    strcpy(tform[2], "16X");
-    strcpy(tform[3], "1B");
-    strcpy(tform[4], "1I");
-    strcpy(tform[5], "1J");
-    strcpy(tform[6], "1E");
-    strcpy(tform[7], "1D");
-    strcpy(tform[8], "1C");
-    strcpy(tform[9], "1M");
-
-    strcpy(ttype[0], "Avalue");
-    strcpy(ttype[1], "Lvalue");
-    strcpy(ttype[2], "Xvalue");
-    strcpy(ttype[3], "Bvalue");
-    strcpy(ttype[4], "Ivalue");
-    strcpy(ttype[5], "Jvalue");
-    strcpy(ttype[6], "Evalue");
-    strcpy(ttype[7], "Dvalue");
-    strcpy(ttype[8], "Cvalue");
-    strcpy(ttype[9], "Mvalue");
-
-    strcpy(tunit[0], "");
-    strcpy(tunit[1], "m**2");
-    strcpy(tunit[2], "cm");
-    strcpy(tunit[3], "erg/s");
-    strcpy(tunit[4], "km/s");
-    strcpy(tunit[5], "");
-    strcpy(tunit[6], "");
-    strcpy(tunit[7], "");
-    strcpy(tunit[8], "");
-    strcpy(tunit[9], "");
-
-    nrows = 20;
-    tfields = 10;
-    pcount = 0;
-
-    ffibin(fptr, nrows, tfields, ttype, tform, tunit, binname, pcount,
-            &status);
-    printf("ffibin status = %d\n", status);
-    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));
-
-    extvers = 3;
-    ffpkyj(fptr, "EXTVER", extvers, "extension version number", &status);
-
-
-    ffpkyj(fptr, "TNULL4", 77, "value for undefined pixels", &status);
-    ffpkyj(fptr, "TNULL5", 77, "value for undefined pixels", &status);
-    ffpkyj(fptr, "TNULL6", 77, "value for undefined pixels", &status);
-
-    ffpkyj(fptr, "TSCAL4", 1000, "scaling factor", &status);
-    ffpkyj(fptr, "TSCAL5", 1, "scaling factor", &status);
-    ffpkyj(fptr, "TSCAL6", 100, "scaling factor", &status);
-
-    ffpkyj(fptr, "TZERO4", 0, "scaling offset", &status);
-    ffpkyj(fptr, "TZERO5", 32768, "scaling offset", &status);
-    ffpkyj(fptr, "TZERO6", 100, "scaling offset", &status);
-
-    fftnul(fptr, 4, 77, &status);   /* define null value for int cols */
-    fftnul(fptr, 5, 77, &status);
-    fftnul(fptr, 6, 77, &status);
-    /* set scaling */
-    fftscl(fptr, 4, 1000., 0., &status);   
-    fftscl(fptr, 5, 1., 32768., &status);
-    fftscl(fptr, 6, 100., 100., &status);
-
-    /*
-      ############################
-      #  write data to columns   #
-      ############################
-    */
-
-    /* initialize arrays of values to write to table */
- 
-    joutarray[0] = 0;
-    joutarray[1] = 1000;
-    joutarray[2] = 10000;
-    joutarray[3] = 32768;
-    joutarray[4] = 65535;
-
-
-    for (ii = 4; ii < 7; ii++)
-    {
-        ffpclj(fptr, ii, 1, 1, 5, joutarray, &status); 
-        if (status == NUM_OVERFLOW)
-        {
-            printf("Overflow writing to column %ld\n", ii);
-            status = 0;
-        }
-
-        ffpclu(fptr, ii, 6, 1, 1, &status);  /* write null value */
-    }
-
-    for (jj = 4; jj < 7; jj++)
-    {
-      ffgcvj(fptr, jj, 1, 1, 6, -999, jinarray, &anynull, &status);
-      for (ii = 0; ii < 6; ii++)
-      {
-        printf(" %6ld", jinarray[ii]);
-      }
-      printf("\n");
-    }
-
-    printf("\n");
-    /* turn off scaling, and read the unscaled values */
-    fftscl(fptr, 4, 1., 0., &status);   
-    fftscl(fptr, 5, 1., 0., &status);
-    fftscl(fptr, 6, 1., 0., &status);
-
-    for (jj = 4; jj < 7; jj++)
-    {
-      ffgcvj(fptr, jj, 1, 1, 6, -999, jinarray, &anynull, &status);
-      for (ii = 0; ii < 6; ii++)
-      {
-        printf(" %6ld", jinarray[ii]);
-      }
-      printf("\n");
-    }
-    /*
-      ######################################################
-      #  insert image extension following the binary table #
-      ######################################################
-    */
-
-    bitpix = -32;
-    naxis = 2;
-    naxes[0] = 15;
-    naxes[1] = 25;
-    ffiimg(fptr, bitpix, naxis, naxes, &status);
-    printf("\nCreate image extension: ffiimg status = %d\n", status);
-    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));
-
-    for (jj = 0; jj < 30; jj++)
-    {
-      for (ii = 0; ii < 19; ii++)
-      {
-        imgarray[jj][ii] = (short) ((jj * 10) + ii);
-      }
-    }
-
-    ffp2di(fptr, 1, 19, naxes[0], naxes[1], imgarray[0], &status);
-    printf("\nWrote whole 2D array: ffp2di status = %d\n", status);
-
-    for (jj = 0; jj < 30; jj++)
-    {
-      for (ii = 0; ii < 19; ii++)
-      {
-        imgarray[jj][ii] = 0;
-      }
-    }
-    
-    ffg2di(fptr, 1, 0, 19, naxes[0], naxes[1], imgarray[0], &anynull,
-           &status);
-    printf("\nRead whole 2D array: ffg2di status = %d\n", status);
-
-    for (jj = 0; jj < 30; jj++)
-    {
-      for (ii = 0; ii < 19; ii++)
-      {
-        printf(" %3d", imgarray[jj][ii]);
-      }
-      printf("\n");
-    }
-
-    for (jj = 0; jj < 30; jj++)
-    {
-      for (ii = 0; ii < 19; ii++)
-      {
-        imgarray[jj][ii] = 0;
-      }
-    }
-    
-    for (jj = 0; jj < 20; jj++)
-    {
-      for (ii = 0; ii < 10; ii++)
-      {
-        imgarray2[jj][ii] = (short) ((jj * -10) - ii);
-      }
-    }
-
-    fpixels[0] = 5;
-    fpixels[1] = 5;
-    lpixels[0] = 14;
-    lpixels[1] = 14;
-    ffpssi(fptr, 1, naxis, naxes, fpixels, lpixels, 
-         imgarray2[0], &status);
-    printf("\nWrote subset 2D array: ffpssi status = %d\n", status);
-
-    ffg2di(fptr, 1, 0, 19, naxes[0], naxes[1], imgarray[0], &anynull,
-           &status);
-    printf("\nRead whole 2D array: ffg2di status = %d\n", status);
-
-    for (jj = 0; jj < 30; jj++)
-    {
-      for (ii = 0; ii < 19; ii++)
-      {
-        printf(" %3d", imgarray[jj][ii]);
-      }
-      printf("\n");
-    }
-
-    fpixels[0] = 2;
-    fpixels[1] = 5;
-    lpixels[0] = 10;
-    lpixels[1] = 8;
-    inc[0] = 2;
-    inc[1] = 3;
-
-    for (jj = 0; jj < 30; jj++)
-    {
-      for (ii = 0; ii < 19; ii++)
-      {
-        imgarray[jj][ii] = 0;
-      }
-    }
-    
-    ffgsvi(fptr, 1, naxis, naxes, fpixels, lpixels, inc, 0,
-          imgarray[0], &anynull, &status);
-    printf("\nRead subset of 2D array: ffgsvi status = %d\n", status);
-
-    for (ii = 0; ii < 10; ii++)
-    {
-        printf(" %3d", imgarray[0][ii]);
-    }
-    printf("\n");
-
-    /*
-      ###########################################################
-      #  insert another image extension                         #
-      #  copy the image extension to primary array of tmp file. #
-      #  then delete the tmp file, and the image extension      #
-      ###########################################################
-    */
-    bitpix = 16;
-    naxis = 2;
-    naxes[0] = 15;
-    naxes[1] = 25;
-    ffiimg(fptr, bitpix, naxis, naxes, &status);
-    printf("\nCreate image extension: ffiimg status = %d\n", status);
-    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));
-
-    strcpy(filename, "t1q2s3v4.tmp");
-    ffinit(&tmpfptr, filename, &status);
-    printf("Create temporary file: ffinit status = %d\n", status);
-
-    ffcopy(fptr, tmpfptr, 0, &status);
-    printf("Copy image extension to primary array of tmp file.\n");
-    printf("ffcopy status = %d\n", status);
-
-    ffgrec(tmpfptr, 1, card, &status);
-    printf("%s\n", card);
-    ffgrec(tmpfptr, 2, card, &status);
-    printf("%s\n", card);
-    ffgrec(tmpfptr, 3, card, &status);
-    printf("%s\n", card);
-    ffgrec(tmpfptr, 4, card, &status);
-    printf("%s\n", card);
-    ffgrec(tmpfptr, 5, card, &status);
-    printf("%s\n", card);
-    ffgrec(tmpfptr, 6, card, &status);
-    printf("%s\n", card);
-
-    ffdelt(tmpfptr, &status);
-    printf("Delete the tmp file: ffdelt status = %d\n", status);
-
-    ffdhdu(fptr, &hdutype, &status);
-    printf("Delete the image extension; hdutype, status = %d %d\n",
-             hdutype, status);
-    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));
-
-    /*
-      ###########################################################
-      #  append bintable extension with variable length columns #
-      ###########################################################
-    */
-
-    ffcrhd(fptr, &status);
-    printf("ffcrhd status = %d\n", status);
-
-    strcpy(tform[0], "1PA");
-    strcpy(tform[1], "1PL");
-    strcpy(tform[2], "1PB"); /* Fortran FITSIO doesn't support  1PX */
-    strcpy(tform[3], "1PB");
-    strcpy(tform[4], "1PI");
-    strcpy(tform[5], "1PJ");
-    strcpy(tform[6], "1PE");
-    strcpy(tform[7], "1PD");
-    strcpy(tform[8], "1PC");
-    strcpy(tform[9], "1PM");
-
-    strcpy(ttype[0], "Avalue");
-    strcpy(ttype[1], "Lvalue");
-    strcpy(ttype[2], "Xvalue");
-    strcpy(ttype[3], "Bvalue");
-    strcpy(ttype[4], "Ivalue");
-    strcpy(ttype[5], "Jvalue");
-    strcpy(ttype[6], "Evalue");
-    strcpy(ttype[7], "Dvalue");
-    strcpy(ttype[8], "Cvalue");
-    strcpy(ttype[9], "Mvalue");
-
-    strcpy(tunit[0], "");
-    strcpy(tunit[1], "m**2");
-    strcpy(tunit[2], "cm");
-    strcpy(tunit[3], "erg/s");
-    strcpy(tunit[4], "km/s");
-    strcpy(tunit[5], "");
-    strcpy(tunit[6], "");
-    strcpy(tunit[7], "");
-    strcpy(tunit[8], "");
-    strcpy(tunit[9], "");
-
-    nrows = 20;
-    tfields = 10;
-    pcount = 0;
-
-    ffphbn(fptr, nrows, tfields, ttype, tform, tunit, binname, pcount,
-            &status);
-    printf("Variable length arrays: ffphbn status = %d\n", status);
-
-
-    extvers = 4;
-    ffpkyj(fptr, "EXTVER", extvers, "extension version number", &status);
-
-    ffpkyj(fptr, "TNULL4", 88, "value for undefined pixels", &status);
-    ffpkyj(fptr, "TNULL5", 88, "value for undefined pixels", &status);
-    ffpkyj(fptr, "TNULL6", 88, "value for undefined pixels", &status);
-
-    /*
-      ############################
-      #  write data to columns   #
-      ############################
-    */
-
-    /* initialize arrays of values to write to table */
-    strcpy(iskey,"abcdefghijklmnopqrst");
-
-    for (ii = 0; ii < 20; ii++)
-    {
-        boutarray[ii] = (unsigned char) (ii + 1);
-        ioutarray[ii] = (short) (ii + 1);
-        joutarray[ii] = ii + 1;
-        eoutarray[ii] = (float) (ii + 1);
-        doutarray[ii] = ii + 1;
-    }
-
-    larray[0] = 0;
-    larray[1] = 1;
-    larray[2] = 0;
-    larray[3] = 0;
-    larray[4] = 1;
-    larray[5] = 1;
-    larray[6] = 0;
-    larray[7] = 0;
-    larray[8] = 0;
-    larray[9] = 1;
-    larray[10] = 1;
-    larray[11] = 1;
-    larray[12] = 0;
-    larray[13] = 0;
-    larray[14] = 0;
-    larray[15] = 0;
-    larray[16] = 1;
-    larray[17] = 1;
-    larray[18] = 1;
-    larray[19] = 1;
-
-    /* write values in 1st row */
-    /*  strncpy(inskey[0], iskey, 1); */
-      inskey[0][0] = '\0';  /* write a null string (i.e., a blank) */
-      ffpcls(fptr, 1, 1, 1, 1, inskey, &status);  /* write string values */
-      ffpcll(fptr, 2, 1, 1, 1, larray, &status);  /* write logicals */
-      ffpclx(fptr, 3, 1, 1, 1, larray, &status);  /* write bits */
-      ffpclb(fptr, 4, 1, 1, 1, boutarray, &status);
-      ffpcli(fptr, 5, 1, 1, 1, ioutarray, &status); 
-      ffpclj(fptr, 6, 1, 1, 1, joutarray, &status); 
-      ffpcle(fptr, 7, 1, 1, 1, eoutarray, &status);
-      ffpcld(fptr, 8, 1, 1, 1, doutarray, &status);
-
-    for (ii = 2; ii <= 20; ii++)   /* loop over rows 1 - 20 */
-    {
-      strncpy(inskey[0], iskey, ii);
-      inskey[0][ii] = '\0';
-      ffpcls(fptr, 1, ii, 1, 1, inskey, &status);  /* write string values */
-
-      ffpcll(fptr, 2, ii, 1, ii, larray, &status);  /* write logicals */
-      ffpclu(fptr, 2, ii, ii-1, 1, &status);
-
-      ffpclx(fptr, 3, ii, 1, ii, larray, &status);  /* write bits */
-
-      ffpclb(fptr, 4, ii, 1, ii, boutarray, &status);
-      ffpclu(fptr, 4, ii, ii-1, 1, &status);
-
-      ffpcli(fptr, 5, ii, 1, ii, ioutarray, &status); 
-      ffpclu(fptr, 5, ii, ii-1, 1, &status);
-
-      ffpclj(fptr, 6, ii, 1, ii, joutarray, &status); 
-      ffpclu(fptr, 6, ii, ii-1, 1, &status);
-
-      ffpcle(fptr, 7, ii, 1, ii, eoutarray, &status);
-      ffpclu(fptr, 7, ii, ii-1, 1, &status);
-
-      ffpcld(fptr, 8, ii, 1, ii, doutarray, &status);
-      ffpclu(fptr, 8, ii, ii-1, 1, &status);
-    }
-    printf("ffpcl_ status = %d\n", status);
-
-    /*
-      #################################
-      #  close then reopen this HDU   #
-      #################################
-    */
-
-
-     ffmrhd(fptr, -1, &hdutype, &status);
-     ffmrhd(fptr,  1, &hdutype, &status);
-
-    /*
-      #############################
-      #  read data from columns   #
-      #############################
-    */
-
-    ffgkyj(fptr, "PCOUNT", &pcount, comm, &status);
-    printf("PCOUNT = %ld\n", pcount);
-
-    /* initialize the variables to be read */
-    strcpy(inskey[0]," ");
-    strcpy(iskey," ");
-
-
-    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));
-    for (ii = 1; ii <= 20; ii++)   /* loop over rows 1 - 20 */
-    {
-      for (jj = 0; jj < ii; jj++)
-      {
-        larray[jj] = 0;
-        boutarray[jj] = 0;
-        ioutarray[jj] = 0;
-        joutarray[jj] = 0;
-        eoutarray[jj] = 0;
-        doutarray[jj] = 0;
-      }
-
-      ffgcvs(fptr, 1, ii, 1, 1, iskey, inskey, &anynull, &status);  
-      printf("A %s %d\nL", inskey[0], status);
-
-      ffgcl( fptr, 2, ii, 1, ii, larray, &status); 
-      for (jj = 0; jj < ii; jj++)
-        printf(" %2d", larray[jj]);
-      printf(" %d\nX", status);
-
-      ffgcx(fptr, 3, ii, 1, ii, larray, &status);
-      for (jj = 0; jj < ii; jj++)
-        printf(" %2d", larray[jj]);
-      printf(" %d\nB", status);
-
-      ffgcvb(fptr, 4, ii, 1, ii, 99, boutarray, &anynull, &status);
-      for (jj = 0; jj < ii; jj++)
-        printf(" %2d", boutarray[jj]);
-      printf(" %d\nI", status);
-
-      ffgcvi(fptr, 5, ii, 1, ii, 99, ioutarray, &anynull, &status); 
-      for (jj = 0; jj < ii; jj++)
-        printf(" %2d", ioutarray[jj]);
-      printf(" %d\nJ", status);
-
-      ffgcvj(fptr, 6, ii, 1, ii, 99, joutarray, &anynull, &status); 
-      for (jj = 0; jj < ii; jj++)
-        printf(" %2ld", joutarray[jj]);
-      printf(" %d\nE", status);
-
-      ffgcve(fptr, 7, ii, 1, ii, 99., eoutarray, &anynull, &status);
-      for (jj = 0; jj < ii; jj++)
-        printf(" %2.0f", eoutarray[jj]);
-      printf(" %d\nD", status);
-
-      ffgcvd(fptr, 8, ii, 1, ii, 99., doutarray, &anynull, &status);
-      for (jj = 0; jj < ii; jj++)
-        printf(" %2.0f", doutarray[jj]);
-      printf(" %d\n", status);
-
-      ffgdes(fptr, 8, ii, &repeat, &offset, &status);
-      printf("Column 8 repeat and offset = %ld %ld\n", repeat, offset);
-    }
-
-    /*
-      #####################################
-      #  create another image extension   #
-      #####################################
-    */
-
-    bitpix = 32;
-    naxis = 2;
-    naxes[0] = 10;
-    naxes[1] = 2;
-    npixels = 20;
- 
-/*    ffcrim(fptr, bitpix, naxis, naxes, &status); */
-    ffiimg(fptr, bitpix, naxis, naxes, &status);
-    printf("\nffcrim status = %d\n", status);
-
-    /* initialize arrays of values to write to primary array */
-    for (ii = 0; ii < npixels; ii++)
-    {
-        boutarray[ii] = (unsigned char) (ii * 2);
-        ioutarray[ii] = (short) (ii * 2);
-        joutarray[ii] = ii * 2;
-        koutarray[ii] = ii * 2;
-        eoutarray[ii] = (float) (ii * 2);
-        doutarray[ii] = ii * 2;
-    }
-
-    /* write a few pixels with each datatype */
-    ffppr(fptr, TBYTE,   1,  2, &boutarray[0],  &status);
-    ffppr(fptr, TSHORT,  3,  2, &ioutarray[2],  &status);
-    ffppr(fptr, TINT,    5,  2, &koutarray[4],  &status);
-    ffppr(fptr, TSHORT,  7,  2, &ioutarray[6],  &status);
-    ffppr(fptr, TLONG,   9,  2, &joutarray[8],  &status);
-    ffppr(fptr, TFLOAT,  11, 2, &eoutarray[10], &status);
-    ffppr(fptr, TDOUBLE, 13, 2, &doutarray[12], &status);
-    printf("ffppr status = %d\n", status);
-
-    /* read back the pixels with each datatype */
-    bnul = 0;
-    inul = 0;
-    knul = 0;
-    jnul = 0;
-    enul = 0.;
-    dnul = 0.;
-
-    ffgpv(fptr, TBYTE,   1,  14, &bnul, binarray, &anynull, &status);
-    ffgpv(fptr, TSHORT,  1,  14, &inul, iinarray, &anynull, &status);
-    ffgpv(fptr, TINT,    1,  14, &knul, kinarray, &anynull, &status);
-    ffgpv(fptr, TLONG,   1,  14, &jnul, jinarray, &anynull, &status);
-    ffgpv(fptr, TFLOAT,  1,  14, &enul, einarray, &anynull, &status);
-    ffgpv(fptr, TDOUBLE, 1,  14, &dnul, dinarray, &anynull, &status);
-
-    printf("\nImage values written with ffppr and read with ffgpv:\n");
-    npixels = 14;
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2d", binarray[ii]);
-    printf("  %d (byte)\n", anynull);  
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2d", iinarray[ii]);
-    printf("  %d (short)\n", anynull);  
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2d", kinarray[ii]);
-    printf("  %d (int)\n", anynull); 
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2ld", jinarray[ii]);
-    printf("  %d (long)\n", anynull); 
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2.0f", einarray[ii]);
-    printf("  %d (float)\n", anynull);
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2.0f", dinarray[ii]);
-    printf("  %d (double)\n", anynull);
-
-    /*
-      ##########################################
-      #  test world coordinate system routines #
-      ##########################################
-    */
-
-    xrval = 45.83;
-    yrval =  63.57;
-    xrpix =  256.;
-    yrpix =  257.;
-    xinc =   -.00277777;
-    yinc =   .00277777;
-
-    /* write the WCS keywords */
-    /* use example values from the latest WCS document */
-    ffpkyd(fptr, "CRVAL1", xrval, 10, "comment", &status);
-    ffpkyd(fptr, "CRVAL2", yrval, 10, "comment", &status);
-    ffpkyd(fptr, "CRPIX1", xrpix, 10, "comment", &status);
-    ffpkyd(fptr, "CRPIX2", yrpix, 10, "comment", &status);
-    ffpkyd(fptr, "CDELT1", xinc, 10, "comment", &status);
-    ffpkyd(fptr, "CDELT2", yinc, 10, "comment", &status);
- /*   ffpkyd(fptr, "CROTA2", rot, 10, "comment", &status); */
-    ffpkys(fptr, "CTYPE1", xcoordtype, "comment", &status);
-    ffpkys(fptr, "CTYPE2", ycoordtype, "comment", &status);
-    printf("\nWrote WCS keywords status = %d\n",status);
-
-    xrval =  0.;
-    yrval =  0.;
-    xrpix =  0.;
-    yrpix =  0.;
-    xinc =   0.;
-    yinc =   0.;
-    rot =    0.;
-
-    ffgics(fptr, &xrval, &yrval, &xrpix,
-           &yrpix, &xinc, &yinc, &rot, ctype, &status);
-    printf("Read WCS keywords with ffgics status = %d\n",status);
-
-    xpix = 0.5;
-    ypix = 0.5;
-
-    ffwldp(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot,ctype,
-           &xpos, &ypos,&status);
-
-    printf("  CRVAL1, CRVAL2 = %16.12f, %16.12f\n", xrval,yrval);
-    printf("  CRPIX1, CRPIX2 = %16.12f, %16.12f\n", xrpix,yrpix);
-    printf("  CDELT1, CDELT2 = %16.12f, %16.12f\n", xinc,yinc);
-    printf("  Rotation = %10.3f, CTYPE = %s\n", rot, ctype);
-    printf("Calculated sky coordinate with ffwldp status = %d\n",status);
-    printf("  Pixels (%8.4f,%8.4f) --> (%11.6f, %11.6f) Sky\n",
-            xpix,ypix,xpos,ypos);
-    ffxypx(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot,ctype,
-           &xpix, &ypix,&status);
-    printf("Calculated pixel coordinate with ffxypx status = %d\n",status);
-    printf("  Sky (%11.6f, %11.6f) --> (%8.4f,%8.4f) Pixels\n",
-            xpos,ypos,xpix,ypix);
-    /*
-      ######################################
-      #  append another ASCII table        #
-      ######################################
-    */
-
-    strcpy(tform[0], "A15");
-    strcpy(tform[1], "I11");
-    strcpy(tform[2], "F15.6");
-    strcpy(tform[3], "E13.5");
-    strcpy(tform[4], "D22.14");
-
-    strcpy(ttype[0], "Name");
-    strcpy(ttype[1], "Ivalue");
-    strcpy(ttype[2], "Fvalue");
-    strcpy(ttype[3], "Evalue");
-    strcpy(ttype[4], "Dvalue");
-
-    strcpy(tunit[0], "");
-    strcpy(tunit[1], "m**2");
-    strcpy(tunit[2], "cm");
-    strcpy(tunit[3], "erg/s");
-    strcpy(tunit[4], "km/s");
-
-    nrows = 11;
-    tfields = 5;
-    strcpy(tblname, "new_table");
-
-    ffcrtb(fptr, ASCII_TBL, nrows, tfields, ttype, tform, tunit, tblname,
-            &status);
-    printf("\nffcrtb status = %d\n", status);
-
-    extvers = 5;
-    ffpkyj(fptr, "EXTVER", extvers, "extension version number", &status);
-
-    ffpcl(fptr, TSTRING, 1, 1, 1, 3, onskey, &status);  /* write string values */
-
-    /* initialize arrays of values to write */
-    
-    for (ii = 0; ii < npixels; ii++)
-    {
-        boutarray[ii] = (unsigned char) (ii * 3);
-        ioutarray[ii] = (short) (ii * 3);
-        joutarray[ii] = ii * 3;
-        koutarray[ii] = ii * 3;
-        eoutarray[ii] = (float) (ii * 3);
-        doutarray[ii] = ii * 3;
-    }
-
-    for (ii = 2; ii < 6; ii++)   /* loop over cols 2 - 5 */
-    {
-        ffpcl(fptr, TBYTE,   ii, 1, 1, 2, boutarray,     &status); 
-        ffpcl(fptr, TSHORT,  ii, 3, 1, 2, &ioutarray[2], &status);  
-        ffpcl(fptr, TLONG,   ii, 5, 1, 2, &joutarray[4], &status);  
-        ffpcl(fptr, TFLOAT,  ii, 7, 1, 2, &eoutarray[6], &status);
-        ffpcl(fptr, TDOUBLE, ii, 9, 1, 2, &doutarray[8], &status); 
-    }
-    printf("ffpcl status = %d\n", status);
-
-    /* read back the pixels with each datatype */
-    ffgcv(fptr, TBYTE,   2, 1, 1, 10, &bnul, binarray, &anynull, &status);
-    ffgcv(fptr, TSHORT,  2, 1, 1, 10, &inul, iinarray, &anynull, &status);
-    ffgcv(fptr, TINT,    3, 1, 1, 10, &knul, kinarray, &anynull, &status);
-    ffgcv(fptr, TLONG,   3, 1, 1, 10, &jnul, jinarray, &anynull, &status);
-    ffgcv(fptr, TFLOAT,  4, 1, 1, 10, &enul, einarray, &anynull, &status);
-    ffgcv(fptr, TDOUBLE, 5, 1, 1, 10, &dnul, dinarray, &anynull, &status);
-
-    printf("\nColumn values written with ffpcl and read with ffgcl:\n");
-    npixels = 10;
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2d", binarray[ii]);
-    printf("  %d (byte)\n", anynull);  
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2d", iinarray[ii]);
-    printf("  %d (short)\n", anynull);
-
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2d", kinarray[ii]);
-    printf("  %d (int)\n", anynull); 
-
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2ld", jinarray[ii]);
-    printf("  %d (long)\n", anynull); 
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2.0f", einarray[ii]);
-    printf("  %d (float)\n", anynull);
-    for (ii = 0; ii < npixels; ii++)
-        printf(" %2.0f", dinarray[ii]);
-    printf("  %d (double)\n", anynull);
-
-    /*
-      ###########################################################
-      #  perform stress test by cycling thru all the extensions #
-      ###########################################################
-    */
-    printf("\nRepeatedly move to the 1st 4 HDUs of the file:\n");
-    for (ii = 0; ii < 10; ii++)
-    {
-      ffmahd(fptr,  1, &hdutype, &status);
-      printf("%d", ffghdn(fptr, &hdunum));
-      ffmrhd(fptr,  1, &hdutype, &status);
-      printf("%d", ffghdn(fptr, &hdunum));
-      ffmrhd(fptr,  1, &hdutype, &status);
-      printf("%d", ffghdn(fptr, &hdunum));
-      ffmrhd(fptr,  1, &hdutype, &status);
-      printf("%d", ffghdn(fptr, &hdunum));
-      ffmrhd(fptr, -1, &hdutype, &status);
-      printf("%d", ffghdn(fptr, &hdunum));
-      if (status > 0)
-         break;
-    }
-    printf("\n");
-
-    printf("Move to extensions by name and version number: (ffmnhd)\n");
-    extvers = 1;
-    ffmnhd(fptr, ANY_HDU, binname, (int) extvers, &status);
-    ffghdn(fptr, &hdunum);
-    printf(" %s, %ld = hdu %d, %d\n", binname, extvers, hdunum, status);
-    extvers = 3;
-    ffmnhd(fptr, ANY_HDU, binname, (int) extvers, &status);
-    ffghdn(fptr, &hdunum);
-    printf(" %s, %ld = hdu %d, %d\n", binname, extvers, hdunum, status);
-    extvers = 4;
-    ffmnhd(fptr, ANY_HDU, binname, (int) extvers, &status);
-    ffghdn(fptr, &hdunum);
-    printf(" %s, %ld = hdu %d, %d\n", binname, extvers, hdunum, status);
-
-
-    strcpy(tblname, "Test-ASCII");
-    extvers = 2;
-    ffmnhd(fptr, ANY_HDU, tblname, (int) extvers, &status);
-    ffghdn(fptr, &hdunum);
-    printf(" %s, %ld = hdu %d, %d\n", tblname, extvers, hdunum, status);
-
-    strcpy(tblname, "new_table");
-    extvers = 5;
-    ffmnhd(fptr, ANY_HDU, tblname, (int) extvers, &status);
-    ffghdn(fptr, &hdunum);
-    printf(" %s, %ld = hdu %d, %d\n", tblname, extvers, hdunum, status);
-    extvers = 0;
-    ffmnhd(fptr, ANY_HDU, binname, (int) extvers, &status);
-    ffghdn(fptr, &hdunum);
-    printf(" %s, %ld = hdu %d, %d\n", binname, extvers, hdunum, status);
-    extvers = 17;
-    ffmnhd(fptr, ANY_HDU, binname, (int) extvers, &status);
-    ffghdn(fptr, &hdunum);
-    printf(" %s, %ld = hdu %d, %d", binname, extvers, hdunum, status);
-    printf (" (expect a 301 error status here)\n");
-    status = 0;
-
-    ffthdu(fptr, &hdunum, &status);
-    printf("Total number of HDUs in the file = %d\n", hdunum);
-    /*
-      ########################
-      #  checksum tests      #
-      ########################
-    */
-    checksum = 1234567890;
-    ffesum(checksum, 0, asciisum);
-    printf("\nEncode checksum: %lu -> %s\n", checksum, asciisum);
-    checksum = 0;
-    ffdsum(asciisum, 0, &checksum);
-    printf("Decode checksum: %s -> %lu\n", asciisum, checksum);
-
-    ffpcks(fptr, &status);
-
-    /*
-       don't print the CHECKSUM value because it is different every day
-       because the current date is in the comment field.
-
-       ffgcrd(fptr, "CHECKSUM", card, &status);
-       printf("%s\n", card);
-    */
-
-    ffgcrd(fptr, "DATASUM", card, &status);
-    printf("%.30s\n", card);
-
-    ffgcks(fptr, &datsum, &checksum, &status);
-    printf("ffgcks data checksum, status = %lu, %d\n",
-            datsum, status);
-
-    ffvcks(fptr, &datastatus, &hdustatus, &status); 
-    printf("ffvcks datastatus, hdustatus, status = %d %d %d\n",
-              datastatus, hdustatus, status);
- 
-    ffprec(fptr,
-    "new_key = 'written by fxprec' / to change checksum", &status);
-    ffupck(fptr, &status);
-    printf("ffupck status = %d\n", status);
-
-    ffgcrd(fptr, "DATASUM", card, &status);
-    printf("%.30s\n", card);
-    ffvcks(fptr, &datastatus, &hdustatus, &status); 
-    printf("ffvcks datastatus, hdustatus, status = %d %d %d\n",
-              datastatus, hdustatus, status);
- 
-    /*
-      delete the checksum keywords, so that the FITS file is always
-      the same, regardless of the date of when testprog is run.
-    */
-
-    ffdkey(fptr, "CHECKSUM", &status);
-    ffdkey(fptr, "DATASUM",  &status);
-
-    /*
-      ############################
-      #  close file and quit     #
-      ############################
-    */
-
- errstatus:  /* jump here on error */
-
-    ffclos(fptr, &status); 
-    printf("ffclos status = %d\n", status);
-
-    printf("\nNormally, there should be 8 error messages on the stack\n");
-    printf("all regarding 'numerical overflows':\n");
-
-    ffgmsg(errmsg);
-    nmsg = 0;
-
-    while (errmsg[0])
-    {
-        printf(" %s\n", errmsg);
-        nmsg++;
-        ffgmsg(errmsg);
-    }
-
-    if (nmsg != 8)
-        printf("\nWARNING: Did not find the expected 8 error messages!\n");
-
-    ffgerr(status, errmsg);
-    printf("\nStatus = %d: %s\n", status, errmsg);
-
-    /* free the allocated memory */
-    for (ii = 0; ii < 21; ii++) 
-        free(inskey[ii]);   
-    for (ii = 0; ii < 10; ii++)
-    {
-      free(ttype[ii]);
-      free(tform[ii]);
-      free(tunit[ii]);
-    }
-
-    return(status);
-}
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/testprog.out b/src/external/OpenGR/3rdparty/cfitsio/testprog.out
deleted file mode 100644
index 6abc0e00e..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/testprog.out
+++ /dev/null
@@ -1,797 +0,0 @@
-CFITSIO TESTPROG
-
-Try opening then closing a nonexistent file:
-  ffopen fptr, status  = 0 104 (expect an error)
-  ffclos status = 115
-
-ffinit create new file status = 0
-Name of file = testprog.fit, I/O mode = 1
-
-test writing of long string keywords:
- 123456789012345678901234567890123456789012345678901234567890123456789012345
-'12345678901234567890123456789012345678901234567890123456789012345678'
- 1234567890123456789012345678901234567890123456789012345678901234'6789012345
-'1234567890123456789012345678901234567890123456789012345678901234''67'
- 1234567890123456789012345678901234567890123456789012345678901234''789012345
-'1234567890123456789012345678901234567890123456789012345678901234'''''
- 1234567890123456789012345678901234567890123456789012345678901234567'9012345
-'1234567890123456789012345678901234567890123456789012345678901234567'
-ffflus status = 0
-HDU number = 1
-
-Values read back from primary array (99 = null pixel)
-The 1st, and every 4th pixel should be undefined:
- 99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  1 (ffgpvb)
- 99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  1 (ffgpvi)
- 99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  1 (ffgpvj)
- 99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  1 (ffgpve)
- 99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  1 (ffgpvd)
-  *  2  3  *  5  6  7  *  9 10 11  * 13 14 15  * 17 18 19  *  1 (ffgpfb)
-  *  2  3  *  5  6  7  *  9 10 11  * 13 14 15  * 17 18 19  *  1 (ffgpfi)
-  *  2  3  *  5  6  7  *  9 10 11  * 13 14 15  * 17 18 19  *  1 (ffgpfj)
-  *  2  3  *  5  6  7  *  9 10 11  * 13 14 15  * 17 18 19  *  1 (ffgpfe)
-  *  2  3  *  5  6  7  *  9 10 11  * 13 14 15  * 17 18 19  *  1 (ffgpfd)
-
-Closed then reopened the FITS file 10 times.
-HDU number = 1
-Name of file = testprog.fit, I/O mode = 1
-
-Read back keywords:
-simple = 1, bitpix = 32, naxis = 2, naxes = (10, 2)
-  pcount = 0, gcount = 1, extend = 1
-KEY_PREC= 'This keyword was written by fxprec' / comment goes here
-KEY_PREC : 'This keyword was written by fxprec' : comment goes here :
-KEY_PREC= 'This keyword was written by fxprec' / comment goes here
-KY_PKNS1 : 'first string' : fxpkns comment :
-KEY_PKYS value_string fxpkys comment 0
-KEY_PKYL 1 fxpkyl comment 0
-KEY_PKYJ 11 fxpkyj comment 0
-KEY_PKYJ 11.000000 fxpkyj comment 0
-KEY_PKYJ 11.000000 fxpkyj comment 0
-KEY_PKY S value_string fxpkys comment 0
-KEY_PKY L 1 fxpkyl comment 0
-KEY_PKY BYTE 11 fxpkyj comment 0
-KEY_PKY SHORT 11 fxpkyj comment 0
-KEY_PKY INT 11 fxpkyj comment 0
-KEY_PKY J 11 fxpkyj comment 0
-KEY_PKY E 13.131310 fxpkye comment 0
-KEY_PKY D 15.151515 fxpkyd comment 0
-KEY_PKYF 12.121210 fxpkyf comment 0
-KEY_PKYE 13.131310 fxpkye comment 0
-KEY_PKYG 14.14141414141414 fxpkyg comment 0
-KEY_PKYD 15.15151515151520 fxpkyd comment 0
-KEY_PKYC 13.131310 14.141410 fxpkyc comment 0
-KEY_PKFC 13.131313 14.141414 fxpkfc comment 0
-KEY_PKYM 15.151515 16.161616 fxpkym comment 0
-KEY_PKFM 15.151515 16.161616 fxpkfm comment 0
-KEY_PKYT 12345678 0.12345678901235 fxpkyt comment 0
-KEY_PKY J 11 [km/s/Mpc] fxpkyj comment 0
-KEY_PKY units = km/s/Mpc
-KEY_PKY J 11 fxpkyj comment 0
-KEY_PKY units = 
-KEY_PKY J 11 [feet/second/second] fxpkyj comment 0
-KEY_PKY units = feet/second/second
-KEY_PKLS long string value = 
-This is a very long string value that is continued over more than one keyword.
-header contains 65 keywords; located at keyword 27 
-ffgkns:  first string, second string, 
-ffgknl:  1, 0, 1
-ffgknj:  11, 12, 13
-ffgkne:  13.131310, 14.141410, 15.151520
-ffgknd:  15.151515, 16.161616, 17.171717
-
-Before deleting the HISTORY and DATE keywords...
-COMMENT 
-HISTORY 
-DATE    
-KY_PKNS1
-
-After deleting the keywords...
-COMMENT   This keyword was written by fxpcom.
-KY_PKNS1= 'first string'       / fxpkns comment
-
-After inserting the keywords...
-COMMENT   This keyword was written by fxpcom.
-KY_IREC = 'This keyword inserted by fxirec'
-KY_IKYS = 'insert_value_string' / ikys comment
-KY_IKYJ =                   49 / ikyj comment
-KY_IKYL =                    T / ikyl comment
-KY_IKYE =           1.2346E+01 / ikye comment
-KY_IKYD = 1.23456789012346E+01 / ikyd comment
-KY_IKYF =              12.3456 / ikyf comment
-KY_IKYG =     12.3456789012346 / ikyg comment
-KY_PKNS1= 'first string'       / fxpkns comment
-
-After modifying the keywords...
-COMMENT   This keyword was modified by fxmrec
-KY_MREC = 'This keyword was modified by fxmcrd'
-NEWIKYS = 'modified_string'    / ikys comment
-KY_IKYJ =                   50 / This is a modified comment
-KY_IKYL =                    F / ikyl comment
-KY_IKYE =          -1.2346E+01 / ikye comment
-KY_IKYD = -1.23456789012346E+01 / modified comment
-KY_IKYF =             -12.3456 / ikyf comment
-KY_IKYG =    -12.3456789012346 / ikyg comment
-KY_PKNS1= 'first string'       / fxpkns comment
-
-After updating the keywords...
-COMMENT   This keyword was modified by fxmrec
-KY_UCRD = 'This keyword was updated by fxucrd'
-NEWIKYS = 'updated_string'     / ikys comment
-KY_IKYJ =                   51 / This is a modified comment
-KY_IKYL =                    T / ikyl comment
-KY_IKYE =          -1.3346E+01 / ikye comment
-KY_IKYD = -1.33456789012346E+01 / modified comment
-KY_IKYF =             -13.3456 / ikyf comment
-KY_IKYG =    -13.3456789012346 / ikyg comment
-KY_PKNS1= 'first string'       / fxpkns comment
-
-Keywords found using wildcard search (should be 13)...
-KEY_PKYS= 'value_string'       / fxpkys comment
-KEY_PKYL=                    T / fxpkyl comment
-KEY_PKYJ=                   11 / [feet/second/second] fxpkyj comment
-KEY_PKYF=             12.12121 / fxpkyf comment
-KEY_PKYE=         1.313131E+01 / fxpkye comment
-KEY_PKYG=    14.14141414141414 / fxpkyg comment
-KEY_PKYD= 1.51515151515152E+01 / fxpkyd comment
-KEY_PKYC= (1.313131E+01, 1.414141E+01) / fxpkyc comment
-KEY_PKYM= (1.51515151515152E+01, 1.61616161616162E+01) / fxpkym comment
-KEY_PKFC= (13.131313, 14.141414) / fxpkfc comment
-KEY_PKFM= (15.15151515151515, 16.16161616161616) / fxpkfm comment
-KEY_PKYT= 12345678.1234567890123456 / fxpkyt comment
-NEWIKYS = 'updated_string'     / ikys comment
-
-Copied keyword: ffgkne:  14.141410, 15.151520, 13.131310
-Updated header using template file (ffpktp)
-
-ffibin status = 0
-HDU number = 2
-header contains 33 keywords; located at keyword 1 
-header contains 33 keywords with room for 74 more
-TDIM3 = (1,2,8), 3, 1, 2, 8
-ffpcl_ status = 0
-
-Find the column numbers; a returned status value of 237 is
-expected and indicates that more than one column name matches
-the input column name template.  Status = 219 indicates that
-there was no matching column name.
-Column Xvalue is number 3; status = 0.
-Column Avalue is number 1; status = 237.
-Column Lvalue is number 2; status = 237.
-Column Xvalue is number 3; status = 237.
-Column Bvalue is number 4; status = 237.
-Column Ivalue is number 5; status = 237.
-Column Jvalue is number 6; status = 237.
-Column Evalue is number 7; status = 237.
-Column Dvalue is number 8; status = 237.
-Column Cvalue is number 9; status = 237.
-Column Mvalue is number 10; status = 237.
-Column  is number 0; status = 219.
-
-Information about each column:
- 15A  16 15 15 Avalue, , A, 15, 1.000000, 0.000000, 1234554321, .
-  1L  14  1  1 Lvalue, m**2, L, 1, 1.000000, 0.000000, 1234554321, .
- 16X   1 16  1 Xvalue, cm, X, 16, 1.000000, 0.000000, 1234554321, .
-  1B  11  1  1 Bvalue, erg/s, B, 1, 1.000000, 0.000000, 99, .
-  1I  21  1  2 Ivalue, km/s, I, 1, 1.000000, 0.000000, 99, .
-  1J  41  1  4 Jvalue, , J, 1, 1.000000, 0.000000, 99, .
-  1E  42  1  4 Evalue, , E, 1, 1.000000, 0.000000, 1234554321, .
-  1D  82  1  8 Dvalue, , D, 1, 1.000000, 0.000000, 1234554321, .
-  1C  83  1  8 Cvalue, , C, 1, 1.000000, 0.000000, 1234554321, .
-  1M 163  1 16 Mvalue, , M, 1, 1.000000, 0.000000, 1234554321, .
-
-ffitab status = 0
-HDU number = 2
-ffpcl_ status = 0
-
-ASCII table: rowlen, nrows, tfields, extname: 76 11 5 Test-ASCII
-    Name   1      A15          
-  Ivalue  17      I10     m**2 
-  Fvalue  28    F14.6       cm 
-  Evalue  43    E12.5    erg/s 
-  Dvalue  56   D21.14     km/s 
-
-Data values read from ASCII table:
-   first string  1  1  1  1.0  1.0
-  second string  2  2  2  2.0  2.0
-                 3  3  3  3.0  3.0
-      UNDEFINED  4  4  4  4.0  4.0
-                 5  5  5  5.0  5.0
-                 6  6  6  6.0  6.0
-                 7  7  7  7.0  7.0
-                 8  8  8  8.0  8.0
-                 9  9  9  9.0  9.0
-                10 10 10 10.0 10.0
-                99 99 99 99.0 99.0
-
-      1       1.000000  1.00000E+00  1.00000000000000E+00second string        
-
-Column name is number 1; status = 0.
-Column Ivalue is number 2; status = 237.
-Column Fvalue is number 3; status = 237.
-Column Evalue is number 4; status = 237.
-Column Dvalue is number 5; status = 237.
-Column  is number 0; status = 219.
- A15  16  1 15 Name, 1, , A15, 1.000000, 0.000000, null1, .
- I10  41  1 10 Ivalue, 17, m**2, I10, 1.000000, 0.000000, null2, .
-F14.6  82  1 14 Fvalue, 28, cm, F14.6, 1.000000, 0.000000, null3, .
-E12.5  42  1 12 Evalue, 43, erg/s, E12.5, 1.000000, 0.000000, null4, .
-D21.14  82  1 21 Dvalue, 56, km/s, D21.14, 1.000000, 0.000000, null5, .
-
-
-Data values after inserting 3 rows after row 2:
-   first string  1  1  1  1.0  1.0
-  second string  2  2  2  2.0  2.0
-                 0  0  0  0.0  0.0
-                 0  0  0  0.0  0.0
-                 0  0  0  0.0  0.0
-                 3  3  3  3.0  3.0
-      UNDEFINED  4  4  4  4.0  4.0
-                 5  5  5  5.0  5.0
-                 6  6  6  6.0  6.0
-                 7  7  7  7.0  7.0
-                 8  8  8  8.0  8.0
-                 9  9  9  9.0  9.0
-                10 10 10 10.0 10.0
-                99 99 99 99.0 99.0
-
-Data values after deleting 2 rows at row 10:
-   first string  1  1  1  1.0  1.0
-  second string  2  2  2  2.0  2.0
-                 0  0  0  0.0  0.0
-                 0  0  0  0.0  0.0
-                 0  0  0  0.0  0.0
-                 3  3  3  3.0  3.0
-      UNDEFINED  4  4  4  4.0  4.0
-                 5  5  5  5.0  5.0
-                 6  6  6  6.0  6.0
-                 9  9  9  9.0  9.0
-                10 10 10 10.0 10.0
-                99 99 99 99.0 99.0
-
-Data values after deleting column 3:
-   first string  1  1  1.0  1.0
-  second string  2  2  2.0  2.0
-                 0  0  0.0  0.0
-                 0  0  0.0  0.0
-                 0  0  0.0  0.0
-                 3  3  3.0  3.0
-      UNDEFINED  4  4  4.0  4.0
-                 5  5  5.0  5.0
-                 6  6  6.0  6.0
-                 9  9  9.0  9.0
-                10 10 10.0 10.0
-                99 99 99.0 99.0
-
-Data values after inserting column 5:
-   first string  1  1  1.0  1.0 0
-  second string  2  2  2.0  2.0 0
-                 0  0  0.0  0.0 0
-                 0  0  0.0  0.0 0
-                 0  0  0.0  0.0 0
-                 3  3  3.0  3.0 0
-      UNDEFINED  4  4  4.0  4.0 0
-                 5  5  5.0  5.0 0
-                 6  6  6.0  6.0 0
-                 9  9  9.0  9.0 0
-                10 10 10.0 10.0 0
-                99 99 99.0 99.0 0
-Create temporary file: ffinit status = 0
-
-Create null primary array: ffiimg status = 0
-
-Create ASCII table with 0 columns: ffitab status = 0
-copy column, ffcpcl status = 0
-copy column, ffcpcl status = 0
-copy column, ffcpcl status = 0
-copy column, ffcpcl status = 0
-
-Create Binary table with 0 columns: ffibin status = 0
-copy column, ffcpcl status = 0
-copy column, ffcpcl status = 0
-copy column, ffcpcl status = 0
-copy column, ffcpcl status = 0
-Delete the tmp file: ffdelt status = 0
-HDU number = 3
-header contains 38 keywords with room for 69 more
-
-Binary table: nrows, tfields, extname, pcount: 21 10 Test-BINTABLE 0
-  Avalue      15A          
-  Lvalue       1L     m**2 
-  Xvalue      16X       cm 
-  Bvalue       1B    erg/s 
-  Ivalue       1I     km/s 
-  Jvalue       1J          
-  Evalue       1E          
-  Dvalue       1D          
-  Cvalue       1C          
-  Mvalue       1M          
-
-Data values read from binary table:
-  Bit column (X) data values: 
-
-01001100 01110000 11110000 01111100 00000000 
-
-null string column value = -- (should be --)
-
-Read columns with ffgcv_:
-   first string 0  76  1   1   1   1.0   1.0 (  1.0, -2.0) (  1.0, -2.0) 
-  second string 1 112  2   2   2   2.0   2.0 (  3.0, -4.0) (  3.0, -4.0) 
-                0 240  3   3   3   3.0   3.0 (  5.0, -6.0) (  5.0, -6.0) 
-    NOT DEFINED 0 124  0  -4  -4  -4.0  -4.0 (  7.0, -8.0) (  7.0, -8.0) 
-    NOT DEFINED 1   0  5   5   5   5.0   5.0 (  9.0,-10.0) (  9.0,-10.0) 
-    NOT DEFINED 1   0  0  -6  -6  -6.0  -6.0 ( 11.0,-12.0) ( 11.0,-12.0) 
-    NOT DEFINED 0   0  7   7   7   7.0   7.0 ( 13.0,-14.0) ( 13.0,-14.0) 
-    NOT DEFINED 0   0  0  -8  -8  -8.0  -8.0 ( 15.0,-16.0) ( 15.0,-16.0) 
-    NOT DEFINED 0   0  9   9   9   9.0   9.0 ( 17.0,-18.0) ( 17.0,-18.0) 
-    NOT DEFINED 1   0  0 -10 -10 -10.0 -10.0 ( 19.0,-20.0) ( 19.0,-20.0) 
-    NOT DEFINED 0   0 98  98  98  98.0  98.0 (  0.0,  0.0) (  0.0,  0.0) 
-    NOT DEFINED 1   0 12  12  12  12.0  12.0 (  0.0,  0.0) (  0.0,  0.0) 
-    NOT DEFINED 0   0 98  98  98  98.0  98.0 (  0.0,  0.0) (  0.0,  0.0) 
-    NOT DEFINED 0   0  0 -14 -14 -14.0 -14.0 (  0.0,  0.0) (  0.0,  0.0) 
-    NOT DEFINED 0   0 98  98  98  98.0  98.0 (  0.0,  0.0) (  0.0,  0.0) 
-    NOT DEFINED 0   0  0 -16 -16 -16.0 -16.0 (  0.0,  0.0) (  0.0,  0.0) 
-    NOT DEFINED 1   0 98  98  98  98.0  98.0 (  0.0,  0.0) (  0.0,  0.0) 
-    NOT DEFINED 1   0  0 -18 -18 -18.0 -18.0 (  0.0,  0.0) (  0.0,  0.0) 
-    NOT DEFINED 1   0 98  98  98  98.0  98.0 (  0.0,  0.0) (  0.0,  0.0) 
-    NOT DEFINED 1   0  0 -20 -20 -20.0 -20.0 (  0.0,  0.0) (  0.0,  0.0) 
-    NOT DEFINED 0   0 98  98  98  98.0  98.0 (  0.0,  0.0) (  0.0,  0.0) 
-
-Read columns with ffgcf_:
-   first string 0  76  1   1   1   1.0   1.0 (  1.0, -2.0) (  1.0, -2.0)
-  second string 1 112  2   2   2   2.0   2.0 (  3.0, -4.0) (  3.0, -4.0)
-                0 240  3   3   3   3.0   3.0 (  5.0, -6.0) (  5.0, -6.0)
-                0 124  0  -4  -4  -4.0  -4.0 (  7.0, -8.0) (  7.0, -8.0)
-                1   0  5   5   5   5.0   5.0 (  9.0,-10.0) (  9.0,-10.0)
-                1   0  0  -6  -6  -6.0  -6.0 ( 11.0,-12.0) ( 11.0,-12.0)
-                0   0  7   7   7   7.0   7.0 ( 13.0,-14.0) ( 13.0,-14.0)
-                0   0  0  -8  -8  -8.0  -8.0 ( 15.0,-16.0) ( 15.0,-16.0)
-                0   0  9   9   9   9.0   9.0 ( 17.0,-18.0) ( 17.0,-18.0)
-                1   0  0 -10 -10 -10.0 -10.0 ( 19.0,-20.0) ( 19.0,-20.0)
-                0   0 99  99 
-                1   0 12  12 
-                0   0 99  99 
-                0   0  0 -14 
-                0   0 99  99 
-                0   0  0 -16 
-                1   0 99  99 
-                1   0  0 -18 
-                1   0 99  99 
-                1   0  0 -20 
-                0   0 99  99 
-
-Data values after inserting 3 rows after row 2:
-   first string  1   1   1   1.0   1.0
-  second string  2   2   2   2.0   2.0
-    NOT DEFINED  0   0   0   0.0   0.0
-    NOT DEFINED  0   0   0   0.0   0.0
-    NOT DEFINED  0   0   0   0.0   0.0
-                 3   3   3   3.0   3.0
-    NOT DEFINED  0  -4  -4  -4.0  -4.0
-    NOT DEFINED  5   5   5   5.0   5.0
-    NOT DEFINED  0  -6  -6  -6.0  -6.0
-    NOT DEFINED  7   7   7   7.0   7.0
-    NOT DEFINED  0  -8  -8  -8.0  -8.0
-    NOT DEFINED  9   9   9   9.0   9.0
-    NOT DEFINED  0 -10 -10 -10.0 -10.0
-    NOT DEFINED 98  98  98  98.0  98.0
-
-Data values after deleting 2 rows at row 10:
-   first string  1   1   1   1.0   1.0
-  second string  2   2   2   2.0   2.0
-    NOT DEFINED  0   0   0   0.0   0.0
-    NOT DEFINED  0   0   0   0.0   0.0
-    NOT DEFINED  0   0   0   0.0   0.0
-                 3   3   3   3.0   3.0
-    NOT DEFINED  0  -4  -4  -4.0  -4.0
-    NOT DEFINED  5   5   5   5.0   5.0
-    NOT DEFINED  0  -6  -6  -6.0  -6.0
-    NOT DEFINED  9   9   9   9.0   9.0
-    NOT DEFINED  0 -10 -10 -10.0 -10.0
-    NOT DEFINED 98  98  98  98.0  98.0
-
-Data values after deleting column 6:
-   first string  1   1   1.0   1.0
-  second string  2   2   2.0   2.0
-    NOT DEFINED  0   0   0.0   0.0
-    NOT DEFINED  0   0   0.0   0.0
-    NOT DEFINED  0   0   0.0   0.0
-                 3   3   3.0   3.0
-    NOT DEFINED  0  -4  -4.0  -4.0
-    NOT DEFINED  5   5   5.0   5.0
-    NOT DEFINED  0  -6  -6.0  -6.0
-    NOT DEFINED  9   9   9.0   9.0
-    NOT DEFINED  0 -10 -10.0 -10.0
-    NOT DEFINED 98  98  98.0  98.0
-
-Data values after inserting column 8:
-   first string  1   1   1.0   1.0 0
-  second string  2   2   2.0   2.0 0
-    NOT DEFINED  0   0   0.0   0.0 0
-    NOT DEFINED  0   0   0.0   0.0 0
-    NOT DEFINED  0   0   0.0   0.0 0
-                 3   3   3.0   3.0 0
-    NOT DEFINED  0  -4  -4.0  -4.0 0
-    NOT DEFINED  5   5   5.0   5.0 0
-    NOT DEFINED  0  -6  -6.0  -6.0 0
-    NOT DEFINED  9   9   9.0   9.0 0
-    NOT DEFINED  0 -10 -10.0 -10.0 0
-    NOT DEFINED 98  98  98.0  98.0 0
-
-Values after setting 1st 10 elements in column 8 = null:
-   first string  1   1   1.0   1.0 98
-  second string  2   2   2.0   2.0 98
-    NOT DEFINED  0   0   0.0   0.0 98
-    NOT DEFINED  0   0   0.0   0.0 98
-    NOT DEFINED  0   0   0.0   0.0 98
-                 3   3   3.0   3.0 98
-    NOT DEFINED  0  -4  -4.0  -4.0 98
-    NOT DEFINED  5   5   5.0   5.0 98
-    NOT DEFINED  0  -6  -6.0  -6.0 98
-    NOT DEFINED  9   9   9.0   9.0 98
-    NOT DEFINED  0 -10 -10.0 -10.0 0
-    NOT DEFINED 98  98  98.0  98.0 0
-Create temporary file: ffinit status = 0
-
-Create null primary array: ffiimg status = 0
-
-Create binary table with 0 columns: ffibin status = 0
-copy column, ffcpcl status = 0
-copy column, ffcpcl status = 0
-copy column, ffcpcl status = 0
-copy column, ffcpcl status = 0
-copy column, ffcpcl status = 0
-copy column, ffcpcl status = 0
-copy column, ffcpcl status = 0
-Delete the tmp file: ffdelt status = 0
-ffibin status = 0
-HDU number = 2
-      0   1000  10000  33000  66000   -999
-      0   1000  10000  32768  65535   -999
-      0   1000  10000  32800  65500   -999
-
-      0      1     10     33     66   -999
- -32768 -31768 -22768      0  32767   -999
-     -1      9     99    327    654   -999
-
-Create image extension: ffiimg status = 0
-HDU number = 3
-
-Wrote whole 2D array: ffp2di status = 0
-
-Read whole 2D array: ffg2di status = 0
-   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14   0   0   0   0
-  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24   0   0   0   0
-  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34   0   0   0   0
-  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44   0   0   0   0
-  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54   0   0   0   0
-  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64   0   0   0   0
-  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74   0   0   0   0
-  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84   0   0   0   0
-  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94   0   0   0   0
-  90  91  92  93  94  95  96  97  98  99 100 101 102 103 104   0   0   0   0
- 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114   0   0   0   0
- 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124   0   0   0   0
- 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134   0   0   0   0
- 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144   0   0   0   0
- 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154   0   0   0   0
- 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164   0   0   0   0
- 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174   0   0   0   0
- 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184   0   0   0   0
- 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194   0   0   0   0
- 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204   0   0   0   0
- 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214   0   0   0   0
- 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224   0   0   0   0
- 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234   0   0   0   0
- 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244   0   0   0   0
- 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254   0   0   0   0
-   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-
-Wrote subset 2D array: ffpssi status = 0
-
-Read whole 2D array: ffg2di status = 0
-   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14   0   0   0   0
-  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24   0   0   0   0
-  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34   0   0   0   0
-  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44   0   0   0   0
-  40  41  42  43   0  -1  -2  -3  -4  -5  -6  -7  -8  -9  54   0   0   0   0
-  50  51  52  53 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19  64   0   0   0   0
-  60  61  62  63 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29  74   0   0   0   0
-  70  71  72  73 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39  84   0   0   0   0
-  80  81  82  83 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49  94   0   0   0   0
-  90  91  92  93 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 104   0   0   0   0
- 100 101 102 103 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 114   0   0   0   0
- 110 111 112 113 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 124   0   0   0   0
- 120 121 122 123 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 134   0   0   0   0
- 130 131 132 133 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 144   0   0   0   0
- 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154   0   0   0   0
- 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164   0   0   0   0
- 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174   0   0   0   0
- 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184   0   0   0   0
- 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194   0   0   0   0
- 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204   0   0   0   0
- 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214   0   0   0   0
- 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224   0   0   0   0
- 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234   0   0   0   0
- 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244   0   0   0   0
- 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254   0   0   0   0
-   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
-
-Read subset of 2D array: ffgsvi status = 0
-  41  43  -1  -3  -5  71  73 -31 -33 -35
-
-Create image extension: ffiimg status = 0
-HDU number = 4
-Create temporary file: ffinit status = 0
-Copy image extension to primary array of tmp file.
-ffcopy status = 0
-SIMPLE  =                    T / file does conform to FITS standard
-BITPIX  =                   16 / number of bits per data pixel
-NAXIS   =                    2 / number of data axes
-NAXIS1  =                   15 / length of data axis 1
-NAXIS2  =                   25 / length of data axis 2
-EXTEND  =                    T / FITS dataset may contain extensions
-Delete the tmp file: ffdelt status = 0
-Delete the image extension; hdutype, status = 1 0
-HDU number = 4
-ffcrhd status = 0
-Variable length arrays: ffphbn status = 0
-ffpcl_ status = 0
-PCOUNT = 4446
-HDU number = 6
-A   0
-L  0 0
-X  0 0
-B  1 0
-I  1 0
-J  1 0
-E  1 0
-D  1 0
-Column 8 repeat and offset = 1 14
-A ab 0
-L  0  1 0
-X  0  1 0
-B 99  2 0
-I 99  2 0
-J 99  2 0
-E 99  2 0
-D 99  2 0
-Column 8 repeat and offset = 2 49
-A abc 0
-L  0  0  0 0
-X  0  1  0 0
-B  1 99  3 0
-I  1 99  3 0
-J  1 99  3 0
-E  1 99  3 0
-D  1 99  3 0
-Column 8 repeat and offset = 3 105
-A abcd 0
-L  0  1  0  0 0
-X  0  1  0  0 0
-B  1  2 99  4 0
-I  1  2 99  4 0
-J  1  2 99  4 0
-E  1  2 99  4 0
-D  1  2 99  4 0
-Column 8 repeat and offset = 4 182
-A abcde 0
-L  0  1  0  0  1 0
-X  0  1  0  0  1 0
-B  1  2  3 99  5 0
-I  1  2  3 99  5 0
-J  1  2  3 99  5 0
-E  1  2  3 99  5 0
-D  1  2  3 99  5 0
-Column 8 repeat and offset = 5 280
-A abcdef 0
-L  0  1  0  0  0  1 0
-X  0  1  0  0  1  1 0
-B  1  2  3  4 99  6 0
-I  1  2  3  4 99  6 0
-J  1  2  3  4 99  6 0
-E  1  2  3  4 99  6 0
-D  1  2  3  4 99  6 0
-Column 8 repeat and offset = 6 399
-A abcdefg 0
-L  0  1  0  0  1  0  0 0
-X  0  1  0  0  1  1  0 0
-B  1  2  3  4  5 99  7 0
-I  1  2  3  4  5 99  7 0
-J  1  2  3  4  5 99  7 0
-E  1  2  3  4  5 99  7 0
-D  1  2  3  4  5 99  7 0
-Column 8 repeat and offset = 7 539
-A abcdefgh 0
-L  0  1  0  0  1  1  0  0 0
-X  0  1  0  0  1  1  0  0 0
-B  1  2  3  4  5  6 99  8 0
-I  1  2  3  4  5  6 99  8 0
-J  1  2  3  4  5  6 99  8 0
-E  1  2  3  4  5  6 99  8 0
-D  1  2  3  4  5  6 99  8 0
-Column 8 repeat and offset = 8 700
-A abcdefghi 0
-L  0  1  0  0  1  1  0  0  0 0
-X  0  1  0  0  1  1  0  0  0 0
-B  1  2  3  4  5  6  7 99  9 0
-I  1  2  3  4  5  6  7 99  9 0
-J  1  2  3  4  5  6  7 99  9 0
-E  1  2  3  4  5  6  7 99  9 0
-D  1  2  3  4  5  6  7 99  9 0
-Column 8 repeat and offset = 9 883
-A abcdefghij 0
-L  0  1  0  0  1  1  0  0  0  1 0
-X  0  1  0  0  1  1  0  0  0  1 0
-B  1  2  3  4  5  6  7  8 99 10 0
-I  1  2  3  4  5  6  7  8 99 10 0
-J  1  2  3  4  5  6  7  8 99 10 0
-E  1  2  3  4  5  6  7  8 99 10 0
-D  1  2  3  4  5  6  7  8 99 10 0
-Column 8 repeat and offset = 10 1087
-A abcdefghijk 0
-L  0  1  0  0  1  1  0  0  0  0  1 0
-X  0  1  0  0  1  1  0  0  0  1  1 0
-B  1  2  3  4  5  6  7  8  9 99 11 0
-I  1  2  3  4  5  6  7  8  9 99 11 0
-J  1  2  3  4  5  6  7  8  9 99 11 0
-E  1  2  3  4  5  6  7  8  9 99 11 0
-D  1  2  3  4  5  6  7  8  9 99 11 0
-Column 8 repeat and offset = 11 1312
-A abcdefghijkl 0
-L  0  1  0  0  1  1  0  0  0  1  0  1 0
-X  0  1  0  0  1  1  0  0  0  1  1  1 0
-B  1  2  3  4  5  6  7  8  9 10 99 12 0
-I  1  2  3  4  5  6  7  8  9 10 99 12 0
-J  1  2  3  4  5  6  7  8  9 10 99 12 0
-E  1  2  3  4  5  6  7  8  9 10 99 12 0
-D  1  2  3  4  5  6  7  8  9 10 99 12 0
-Column 8 repeat and offset = 12 1558
-A abcdefghijklm 0
-L  0  1  0  0  1  1  0  0  0  1  1  0  0 0
-X  0  1  0  0  1  1  0  0  0  1  1  1  0 0
-B  1  2  3  4  5  6  7  8  9 10 11 99 13 0
-I  1  2  3  4  5  6  7  8  9 10 11 99 13 0
-J  1  2  3  4  5  6  7  8  9 10 11 99 13 0
-E  1  2  3  4  5  6  7  8  9 10 11 99 13 0
-D  1  2  3  4  5  6  7  8  9 10 11 99 13 0
-Column 8 repeat and offset = 13 1825
-A abcdefghijklmn 0
-L  0  1  0  0  1  1  0  0  0  1  1  1  0  0 0
-X  0  1  0  0  1  1  0  0  0  1  1  1  0  0 0
-B  1  2  3  4  5  6  7  8  9 10 11 12 99 14 0
-I  1  2  3  4  5  6  7  8  9 10 11 12 99 14 0
-J  1  2  3  4  5  6  7  8  9 10 11 12 99 14 0
-E  1  2  3  4  5  6  7  8  9 10 11 12 99 14 0
-D  1  2  3  4  5  6  7  8  9 10 11 12 99 14 0
-Column 8 repeat and offset = 14 2113
-A abcdefghijklmno 0
-L  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0 0
-X  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0 0
-B  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15 0
-I  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15 0
-J  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15 0
-E  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15 0
-D  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15 0
-Column 8 repeat and offset = 15 2422
-A abcdefghijklmnop 0
-L  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0 0
-X  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0 0
-B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16 0
-I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16 0
-J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16 0
-E  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16 0
-D  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16 0
-Column 8 repeat and offset = 16 2752
-A abcdefghijklmnopq 0
-L  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1 0
-X  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1 0
-B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17 0
-I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17 0
-J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17 0
-E  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17 0
-D  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17 0
-Column 8 repeat and offset = 17 3104
-A abcdefghijklmnopqr 0
-L  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  0  1 0
-X  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1  1 0
-B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18 0
-I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18 0
-J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18 0
-E  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18 0
-D  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18 0
-Column 8 repeat and offset = 18 3477
-A abcdefghijklmnopqrs 0
-L  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1  0  1 0
-X  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1  1  1 0
-B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19 0
-I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19 0
-J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19 0
-E  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19 0
-D  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19 0
-Column 8 repeat and offset = 19 3871
-A abcdefghijklmnopqrst 0
-L  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1  1  0  1 0
-X  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1  1  1  1 0
-B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20 0
-I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20 0
-J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20 0
-E  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20 0
-D  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20 0
-Column 8 repeat and offset = 20 4286
-
-ffcrim status = 0
-ffppr status = 0
-
-Image values written with ffppr and read with ffgpv:
-  0  2  4  6  8 10 12 14 16 18 20 22 24 26  0 (byte)
-  0  2  4  6  8 10 12 14 16 18 20 22 24 26  0 (short)
-  0  2  4  6  8 10 12 14 16 18 20 22 24 26  0 (int)
-  0  2  4  6  8 10 12 14 16 18 20 22 24 26  0 (long)
-  0  2  4  6  8 10 12 14 16 18 20 22 24 26  0 (float)
-  0  2  4  6  8 10 12 14 16 18 20 22 24 26  0 (double)
-
-Wrote WCS keywords status = 0
-Read WCS keywords with ffgics status = 0
-  CRVAL1, CRVAL2 =  45.830000000000,  63.570000000000
-  CRPIX1, CRPIX2 = 256.000000000000, 257.000000000000
-  CDELT1, CDELT2 =  -0.002777770000,   0.002777770000
-  Rotation =      0.000, CTYPE = -TAN
-Calculated sky coordinate with ffwldp status = 0
-  Pixels (  0.5000,  0.5000) --> (  47.385204,   62.848968) Sky
-Calculated pixel coordinate with ffxypx status = 0
-  Sky (  47.385204,   62.848968) --> (  0.5000,  0.5000) Pixels
-
-ffcrtb status = 0
-ffpcl status = 0
-
-Column values written with ffpcl and read with ffgcl:
-  0  3  6  9 12 15 18 21 24 27  0 (byte)
-  0  3  6  9 12 15 18 21 24 27  0 (short)
-  0  3  6  9 12 15 18 21 24 27  0 (int)
-  0  3  6  9 12 15 18 21 24 27  0 (long)
-  0  3  6  9 12 15 18 21 24 27  0 (float)
-  0  3  6  9 12 15 18 21 24 27  0 (double)
-
-Repeatedly move to the 1st 4 HDUs of the file:
-12343123431234312343123431234312343123431234312343
-Move to extensions by name and version number: (ffmnhd)
- Test-BINTABLE, 1 = hdu 5, 0
- Test-BINTABLE, 3 = hdu 2, 0
- Test-BINTABLE, 4 = hdu 6, 0
- Test-ASCII, 2 = hdu 4, 0
- new_table, 5 = hdu 8, 0
- Test-BINTABLE, 0 = hdu 2, 0
- Test-BINTABLE, 17 = hdu 2, 301 (expect a 301 error status here)
-Total number of HDUs in the file = 8
-
-Encode checksum: 1234567890 -> dCW2fBU0dBU0dBU0
-Decode checksum: dCW2fBU0dBU0dBU0 -> 1234567890
-DATASUM = '475248536'         
-ffgcks data checksum, status = 475248536, 0
-ffvcks datastatus, hdustatus, status = 1 1 0
-ffupck status = 0
-DATASUM = '475248536'         
-ffvcks datastatus, hdustatus, status = 1 1 0
-ffclos status = 0
-
-Normally, there should be 8 error messages on the stack
-all regarding 'numerical overflows':
- Numerical overflow during type conversion while writing FITS data.
- Numerical overflow during type conversion while writing FITS data.
- Numerical overflow during type conversion while writing FITS data.
- Numerical overflow during type conversion while writing FITS data.
- Numerical overflow during type conversion while writing FITS data.
- Numerical overflow during type conversion while writing FITS data.
- Numerical overflow during type conversion while writing FITS data.
- Numerical overflow during type conversion while writing FITS data.
-
-Status = 0: OK - no error
diff --git a/src/external/OpenGR/3rdparty/cfitsio/testprog.std b/src/external/OpenGR/3rdparty/cfitsio/testprog.std
deleted file mode 100644
index c1a2db5fc..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/testprog.std
+++ /dev/null
@@ -1,48 +0,0 @@
-SIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   10 / length of data axis 1                          NAXIS2  =                    2 / length of data axis 2                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H KEY_PREC= 'This keyword was written by fxprec' / comment goes here              CARD1   = '12345678901234567890123456789012345678901234567890123456789012345678'CARD2   = '1234567890123456789012345678901234567890123456789012345678901234''67'CARD3   = '1234567890123456789012345678901234567890123456789012345678901234'''''CARD4   = '1234567890123456789012345678901234567890123456789012345678901234567' KEY_PKYS= 'value_string'       / fxpkys comment                                 KEY_PKYL=                    T / fxpkyl comment                                 KEY_PKYJ=                   11 / [feet/second/second] fxpkyj comment            KEY_PKYF=             12.12121 / fxpkyf comment                                 KEY_PKYE=         1.313131E+01 / fxpkye comment                                 KEY_PKYG=    14.14141414141414 / fxpkyg comment                                 KEY_PKYD= 1.51515151515152E+01 / fxpkyd comment                                 KEY_PKYC= (1.313131E+01, 1.414141E+01) / fxpkyc comment                         KEY_PKYM= (1.51515151515152E+01, 1.61616161616162E+01) / fxpkym comment         KEY_PKFC= (13.131313, 14.141414) / fxpkfc comment                               KEY_PKFM= (15.15151515151515, 16.16161616161616) / fxpkfm comment               KEY_PKLS= 'This is a very long string value that is continued over more than o&'CONTINUE  'ne keyword.'        / fxpkls comment                                 LONGSTRN= 'OGIP 1.0'           / The HEASARC Long String Convention may be used.COMMENT   This FITS file may contain long string keyword values that are        COMMENT   continued over multiple keywords.  The HEASARC convention uses the &  COMMENT   character at the end of each substring which is then continued        COMMENT   on the next keyword which has the name CONTINUE.                      KEY_PKYT= 12345678.1234567890123456 / fxpkyt comment                            COMMENT   This keyword was modified by fxmrec                                   KY_UCRD = 'This keyword was updated by fxucrd'                                  NEWIKYS = 'updated_string'     / ikys comment                                   KY_IKYJ =                   51 / This is a modified comment                     KY_IKYL =                    T / ikyl comment                                   KY_IKYE =          -1.3346E+01 / ikye comment                                   KY_IKYD = -1.33456789012346E+01 / modified comment                              KY_IKYF =             -13.3456 / ikyf comment                                   KY_IKYG =    -13.3456789012346 / ikyg comment                                   KY_PKNS1= 'first string'       / fxpkns comment                                 KY_PKNS2= 'second string'      / fxpkns comment                                 KY_PKNS3= '        '           / fxpkns comment                                 KY_PKNL1=                    T / fxpknl comment                                 KY_PKNL2=                    F / fxpknl comment                                 KY_PKNL3=                    T / fxpknl comment                                 KY_PKNJ1=                   11 / fxpknj comment                                 KY_PKNJ2=                   12 / fxpknj comment                                 KY_PKNJ3=                   13 / fxpknj comment                                 KY_PKNF1=             12.12121 / fxpknf comment                                 KY_PKNF2=             13.13131 / fxpknf comment                                 KY_PKNF3=             14.14141 / fxpknf comment                                 KY_PKNE1=         1.313131E+01 / fxpkne comment                                 KY_PKNE2=         1.414141E+01 / fxpkne comment                                 KY_PKNE3=         1.515152E+01 / fxpkne comment                                 KY_PKNG1=     14.1414141414141 / fxpkng comment                                 KY_PKNG2=     15.1515151515152 / fxpkng comment                                 KY_PKNG3=     16.1616161616162 / fxpkng comment                                 KY_PKND1= 1.51515151515152E+01 / fxpknd comment                                 KY_PKND2= 1.61616161616162E+01 / fxpknd comment                                 KY_PKND3= 1.71717171717172E+01 / fxpknd comment                                 TSTRING = '1       '           / tstring comment                                TLOGICAL=                    T / tlogical comment                               TBYTE   =                   11 / tbyte comment                                  TSHORT  =                   21 / tshort comment                                 TINT    =                   31 / tint comment                                   TLONG   =                   41 / tlong comment                                  TFLOAT  =                  42. / tfloat comment                                 TDOUBLE =                  82. / tdouble comment                                BLANK   =                  -99 / value to use for undefined pixels              KY_PKNE4=         1.313131E+01 / fxpkne comment                                 TMPCARDA=                 1001 / this is the 1st template card                  TMPCARD2= 'ABCD    '           / this is the 2nd template card                  TMPCARD3=              1001.23 / this is the 3rd template card                  COMMENT this is the 5th template card                                           HISTORY this is the 6th template card                                           TMPCARD7=                      / comment for null keyword                       END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             	
-
XTENSION= 'BINTABLE'           / binary table extension                         BITPIX  =                    8 / 8-bit bytes                                    NAXIS   =                    2 / 2-dimensional binary table                     NAXIS1  =                   61 / width of table in bytes                        NAXIS2  =                   20 / number of rows in table                        PCOUNT  =                    0 / size of special data area                      GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                   10 / number of fields in each row                   TTYPE1  = 'Avalue  '           / label for field   1                            TFORM1  = '15A     '           / data format of field: ASCII Character          TTYPE2  = 'Lvalue  '           / label for field   2                            TFORM2  = '1L      '           / data format of field: 1-byte LOGICAL           TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Xvalue  '           / label for field   3                            TFORM3  = '16X     '           / data format of field: BIT                      TUNIT3  = 'cm      '           / physical unit of field                         TTYPE4  = 'Bvalue  '           / label for field   4                            TFORM4  = '1B      '           / data format of field: BYTE                     TUNIT4  = 'erg/s   '           / physical unit of field                         TTYPE5  = 'Ivalue  '           / label for field   5                            TFORM5  = '1I      '           / data format of field: 2-byte INTEGER           TUNIT5  = 'km/s    '           / physical unit of field                         TTYPE6  = 'Jvalue  '           / label for field   6                            TFORM6  = '1J      '           / data format of field: 4-byte INTEGER           TTYPE7  = 'Evalue  '           / label for field   7                            TFORM7  = '1E      '           / data format of field: 4-byte REAL              TTYPE8  = 'Dvalue  '           / label for field   8                            TFORM8  = '1D      '           / data format of field: 8-byte DOUBLE            TTYPE9  = 'Cvalue  '           / label for field   9                            TFORM9  = '1C      '           / data format of field: COMPLEX                  TTYPE10 = 'Mvalue  '           / label for field  10                            TFORM10 = '1M      '           / data format of field: DOUBLE COMPLEX           EXTNAME = 'Test-BINTABLE'      / name of this binary table extension            EXTVER  =                    3 / extension version number                       TNULL4  =                   77 / value for undefined pixels                     TNULL5  =                   77 / value for undefined pixels                     TNULL6  =                   77 / value for undefined pixels                     TSCAL4  =                 1000 / scaling factor                                 TSCAL5  =                    1 / scaling factor                                 TSCAL6  =                  100 / scaling factor                                 TZERO4  =                    0 / scaling offset                                 TZERO5  =                32768 / scaling offset                                 TZERO6  =                  100 / scaling offset                                 NEW_KEY = 'written by fxprec' / to change checksum                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             	
-c!GBMMMXTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   15 / length of data axis 1                          NAXIS2  =                   25 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ?@@@@@@@AAA A0A@APA`A A0A@APA`ApAAAAAAAAAAAAAAAAAAAAABBBAABBBBBBBBB B$B(B,B0B B$B(B,@BXBHBLBPBT 0@P`pBBpBtBxB|BBBBBBBBBB $(,048<@DBBBBBHLPTX\`dhlBBBBBptx|€‚„†ˆŠBBBBBŒŽ’”–˜šœžBBBBB ¢¤¦¨ª¬®°²CCCCC´¶¸º¼¾CCC
CCCCCCCCCCCCCCCCCCCCCCCC C!C"C#C$C C!C"C#C$C%C&C'C(C)C*C+C,C-C.C*C+C,C-C.C/C0C1C2C3C4C5C6C7C8C4C5C6C7C8C9C:C;C<C=C>C?C@CACBC>C?C@CACBCCCDCECFCGCHCICJCKCLCHCICJCKCLCMCNCOCPCQCRCSCTCUCVCRCSCTCUCVCWCXCYCZC[C\C]C^C_C`C\C]C^C_C`CaCbCcCdCeCfCgChCiCjCfCgChCiCjCkClCmCnCoCpCqCrCsCtCpCqCrCsCtCuCvCwCxCyCzC{C|C}C~XTENSION= 'TABLE   '           / ASCII table extension                          BITPIX  =                    8 / 8-bit ASCII characters                         NAXIS   =                    2 / 2-dimensional ASCII table                      NAXIS1  =                   76 / width of table in characters                   NAXIS2  =                   12 / number of rows in table                        PCOUNT  =                    0 / no group parameters (required keyword)         GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                    5 / number of fields in each row                   TTYPE1  = 'Name    '           / label for field   1                            TBCOL1  =                    1 / beginning column of field   1                  TFORM1  = 'A15     '           / Fortran-77 format of field                     TTYPE2  = 'Ivalue  '           / label for field   2                            TBCOL2  =                   17 / beginning column of field   2                  TFORM2  = 'I10     '           / Fortran-77 format of field                     TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Evalue  '           / label for field   4                            TBCOL3  =                   28 / beginning column of field   4                  TFORM3  = 'E12.5   '           / Fortran-77 format of field                     TUNIT3  = 'erg/s   '           / physical unit of field                         TTYPE4  = 'Dvalue  '           / label for field   5                            TBCOL4  =                   41 / beginning column of field   5                  TFORM4  = 'D21.14  '           / Fortran-77 format of field                     TUNIT4  = 'km/s    '           / physical unit of field                         EXTNAME = 'Test-ASCII'         / name of this ASCII table extension             EXTVER  =                    2 / extension version number                       TNULL1  = 'null1   '           / value for undefined pixels                     TNULL2  = 'null2   '           / value for undefined pixels                     TNULL3  = 'null4   '           / value for undefined pixels                     TNULL4  = 'null5   '           / value for undefined pixels                     TTYPE5  = 'INSERT_COL'         / label for field                                TFORM5  = 'F14.6   '           / format of field                                TBCOL5  =                   63 / beginning column of field                      END                                                                                                                                                                                                                                                                                                                             first string             1  1.00000E+00  1.00000000000000E+00               second string            2  2.00000E+00  2.00000000000000E+00                                                                                                                                                                                                                                                                            3  3.00000E+00  3.00000000000000E+00               null1                    4  4.00000E+00  4.00000000000000E+00                                        5  5.00000E+00  5.00000000000000E+00                                        6  6.00000E+00  6.00000000000000E+00                                        9  9.00000E+00  9.00000000000000E+00                                       10  1.00000E+01  1.00000000000000E+01                               null2      null4        null5                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               XTENSION= 'BINTABLE'           / binary table extension                         BITPIX  =                    8 / 8-bit bytes                                    NAXIS   =                    2 / 2-dimensional binary table                     NAXIS1  =                   61 / width of table in bytes                        NAXIS2  =                   22 / number of rows in table                        PCOUNT  =                    0 / size of special data area                      GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                   10 / number of fields in each row                   TTYPE1  = 'Avalue  '           / label for field   1                            TFORM1  = '15A     '           / data format of field: ASCII Character          TTYPE2  = 'Lvalue  '           / label for field   2                            TFORM2  = '1L      '           / data format of field: 1-byte LOGICAL           TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Xvalue  '           / label for field   3                            TFORM3  = '16X     '           / data format of field: BIT                      TUNIT3  = 'cm      '           / physical unit of field                         TTYPE4  = 'Bvalue  '           / label for field   4                            TFORM4  = '1B      '           / data format of field: BYTE                     TUNIT4  = 'erg/s   '           / physical unit of field                         TTYPE5  = 'Ivalue  '           / label for field   5                            TFORM5  = '1I      '           / data format of field: 2-byte INTEGER           TUNIT5  = 'km/s    '           / physical unit of field                         TTYPE6  = 'Evalue  '           / label for field   7                            TFORM6  = '1E      '           / data format of field: 4-byte REAL              TTYPE7  = 'Dvalue  '           / label for field   8                            TFORM7  = '1D      '           / data format of field: 8-byte DOUBLE            TTYPE9  = 'Cvalue  '           / label for field   9                            TFORM9  = '1C      '           / data format of field: COMPLEX                  TTYPE10 = 'Mvalue  '           / label for field  10                            TFORM10 = '1M      '           / data format of field: DOUBLE COMPLEX           EXTNAME = 'Test-BINTABLE'      / name of this binary table extension            EXTVER  =                    1 / extension version number                       TNULL4  =                   99 / value for undefined pixels                     TNULL5  =                   99 / value for undefined pixels                     TDIM3   = '(1,2,8) '           / size of the multidimensional array             KEY_PREC= 'This keyword was written by f_prec' / comment here                   TTYPE8  = 'INSERT_COL'         / label for field                                TFORM8  = '1E      '           / format of field                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             first string   FLp????second string  T|@@@@@               F@@@@@              F@@ T@@A @"$TA0@@&(F		A@"A@12T $A@34ccTA@@(FccF`,FccF0TccT2TccT4FccXTENSION= 'BINTABLE'           / binary table extension                         BITPIX  =                    8 / 8-bit bytes                                    NAXIS   =                    2 / 2-dimensional binary table                     NAXIS1  =                   80 / width of table in bytes                        NAXIS2  =                   20 / number of rows in table                        PCOUNT  =                 4446 / size of special data area                      GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                   10 / number of fields in each row                   TTYPE1  = 'Avalue  '           / label for field   1                            TFORM1  = '1PA(20) '           / data format of field: variable length array    TTYPE2  = 'Lvalue  '           / label for field   2                            TFORM2  = '1PL(20) '           / data format of field: variable length array    TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Xvalue  '           / label for field   3                            TFORM3  = '1PB(3)  '           / data format of field: variable length array    TUNIT3  = 'cm      '           / physical unit of field                         TTYPE4  = 'Bvalue  '           / label for field   4                            TFORM4  = '1PB(20) '           / data format of field: variable length array    TUNIT4  = 'erg/s   '           / physical unit of field                         TTYPE5  = 'Ivalue  '           / label for field   5                            TFORM5  = '1PI(20) '           / data format of field: variable length array    TUNIT5  = 'km/s    '           / physical unit of field                         TTYPE6  = 'Jvalue  '           / label for field   6                            TFORM6  = '1PJ(20) '           / data format of field: variable length array    TTYPE7  = 'Evalue  '           / label for field   7                            TFORM7  = '1PE(20) '           / data format of field: variable length array    TTYPE8  = 'Dvalue  '           / label for field   8                            TFORM8  = '1PD(20) '           / data format of field: variable length array    TTYPE9  = 'Cvalue  '           / label for field   9                            TFORM9  = '1PC(0)  '           / data format of field: variable length array    TTYPE10 = 'Mvalue  '           / label for field  10                            TFORM10 = '1PM(0)  '           / data format of field: variable length array    EXTNAME = 'Test-BINTABLE'      / name of this binary table extension            EXTVER  =                    4 / extension version number                       TNULL4  =                   88 / value for undefined pixels                     TNULL5  =                   88 / value for undefined pixels                     TNULL6  =                   88 / value for undefined pixels                     END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
-!)1ADGHKQ]i@FLMS_wS[cdl|					+	O	s
-
-
-
-
-
-
-? x
v





!	A	:	v		
-
-
- 
-@
-
-@Qbev 

M
%8KNanF??abT@XXX@@abcFF@XXX?@@?@abcdFTF@XXX?@@?@@abcdeFTFTHXXX?@@@@?@@@abcdefFTFFTLXXX?@@@@@?@@@@abcdefgFTFFTFLXXX?@@@@@@?@@@@@abcdefghFTFFTTFLXXX?@@@@@@A?@@@@@@ abcdefghiFTFFTTFFLX	X	X	?@@@@@@@A?@@@@@@@"abcdefghijFTFFTTFFTL@X
-X
-X
-?@@@@@@@AA ?@@@@@@@ @$abcdefghijkFTFFTTFFFTL`	X	X	X?@@@@@@@AAA0?@@@@@@@ @"@&abcdefghijklFTFFTTFFFTTLp	
-X	
-X	
-X?@@@@@@@AAA A@?@@@@@@@ @"@$@(abcdefghijklmFTFFTTFFFTTFLp	
-X
	
-X
	
-X
?@@@@@@@AAA A0AP?@@@@@@@ @"@$@&@*abcdefghijklmnFTFFTTFFFTTTFLp	
-X	
-X	
-X?@@@@@@@AAA A0A@A`?@@@@@@@ @"@$@&@(@,abcdefghijklmnoFTFFTTFFFTTTFFLp	
-
X	
-
X	
-
X?@@@@@@@AAA A0A@APAp?@@@@@@@ @"@$@&@(@*@.abcdefghijklmnopFTFFTTFFFTTTFFFLp	
-
X	
-
X	
-
X?@@@@@@@AAA A0A@APA`A?@@@@@@@ @"@$@&@(@*@,@0abcdefghijklmnopqFTFFTTFFFTTTFFFTLp	
-
X	
-
X	
-
X?@@@@@@@AAA A0A@APA`ApA?@@@@@@@ @"@$@&@(@*@,@.@1abcdefghijklmnopqrFTFFTTFFFTTTFFFFTLp	
-
X	
-
X	
-
X?@@@@@@@AAA A0A@APA`ApAA?@@@@@@@ @"@$@&@(@*@,@.@0@2abcdefghijklmnopqrsFTFFTTFFFTTTFFFFTTLp	
-
X	
-
X	
-
X?@@@@@@@AAA A0A@APA`ApAAA?@@@@@@@ @"@$@&@(@*@,@.@0@1@3abcdefghijklmnopqrstFTFFTTFFFTTTFFFFTTTLp	
-
X	
-
X	
-
X?@@@@@@@AAA A0A@APA`ApAAAA?@@@@@@@ @"@$@&@(@*@,@.@0@1@2@4XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   10 / length of data axis 1                          NAXIS2  =                    2 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     CRVAL1  =     4.5830000000E+01 / comment                                        CRVAL2  =     6.3570000000E+01 / comment                                        CRPIX1  =     2.5600000000E+02 / comment                                        CRPIX2  =     2.5700000000E+02 / comment                                        CDELT1  =    -2.7777700000E-03 / comment                                        CDELT2  =     2.7777700000E-03 / comment                                        CTYPE1  = 'RA---TAN'           / comment                                        CTYPE2  = 'DEC--TAN'           / comment                                        END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
-XTENSION= 'TABLE   '           / ASCII table extension                          BITPIX  =                    8 / 8-bit ASCII characters                         NAXIS   =                    2 / 2-dimensional ASCII table                      NAXIS1  =                   80 / width of table in characters                   NAXIS2  =                   11 / number of rows in table                        PCOUNT  =                    0 / no group parameters (required keyword)         GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                    5 / number of fields in each row                   TTYPE1  = 'Name    '           / label for field   1                            TBCOL1  =                    1 / beginning column of field   1                  TFORM1  = 'A15     '           / Fortran-77 format of field                     TTYPE2  = 'Ivalue  '           / label for field   2                            TBCOL2  =                   17 / beginning column of field   2                  TFORM2  = 'I11     '           / Fortran-77 format of field                     TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Fvalue  '           / label for field   3                            TBCOL3  =                   29 / beginning column of field   3                  TFORM3  = 'F15.6   '           / Fortran-77 format of field                     TUNIT3  = 'cm      '           / physical unit of field                         TTYPE4  = 'Evalue  '           / label for field   4                            TBCOL4  =                   45 / beginning column of field   4                  TFORM4  = 'E13.5   '           / Fortran-77 format of field                     TUNIT4  = 'erg/s   '           / physical unit of field                         TTYPE5  = 'Dvalue  '           / label for field   5                            TBCOL5  =                   59 / beginning column of field   5                  TFORM5  = 'D22.14  '           / Fortran-77 format of field                     TUNIT5  = 'km/s    '           / physical unit of field                         EXTNAME = 'new_table'          / name of this ASCII table extension             EXTVER  =                    5 / extension version number                       END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             first string              0        0.000000   0.00000E+00   0.00000000000000E+00second string             3        3.000000   3.00000E+00   3.00000000000000E+00                          6        6.000000   6.00000E+00   6.00000000000000E+00                          9        9.000000   9.00000E+00   9.00000000000000E+00                         12       12.000000   1.20000E+01   1.20000000000000E+01                         15       15.000000   1.50000E+01   1.50000000000000E+01                         18       18.000000   1.80000E+01   1.80000000000000E+01                         21       21.000000   2.10000E+01   2.10000000000000E+01                         24       24.000000   2.40000E+01   2.40000000000000E+01                         27       27.000000   2.70000E+01   2.70000000000000E+01                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
\ No newline at end of file
diff --git a/src/external/OpenGR/3rdparty/cfitsio/testprog.tpt b/src/external/OpenGR/3rdparty/cfitsio/testprog.tpt
deleted file mode 100644
index def9dcb28..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/testprog.tpt
+++ /dev/null
@@ -1,12 +0,0 @@
-tmpcard1  1001 this is the 1st template card 
-tmpcard2  ABCD this is the 2nd template card
-tmpcard3  1001.23 this is the 3rd template card
-tmpcard4  1001.45 this is the 4rd template card
-comment this is the 5th template card
-history this is the 6th template card
-tmpcard7 =            / comment for null keyword
--tmpcard1 tmpcarda  change the name of tmpcard1
--tmpcard4
-end
-
-junk will be ignored
diff --git a/src/external/OpenGR/3rdparty/cfitsio/vmsieee.c b/src/external/OpenGR/3rdparty/cfitsio/vmsieee.c
deleted file mode 100644
index 5ddc74865..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/vmsieee.c
+++ /dev/null
@@ -1,130 +0,0 @@
-#include 
-#include 
-
-unsigned long CVT$CONVERT_FLOAT();
-
-/* IEEVPAKR -- Pack a native floating point vector into an IEEE one.
-*/
-void ieevpr (unsigned int *native, unsigned int *ieee, int *nelem)
-{
-        unsigned long status;
-        unsigned long options;
-        unsigned int *unanval;
-        int nanval = -1;
-        int     i,n;
-
-        unanval = (unsigned int *) &nanval;
-        options = CVT$M_BIG_ENDIAN;
-        
-        n = *nelem;
-        status = CVT$_NORMAL;
-
-        for (i = 0; i < n ; i++) {
-
-            status = CVT$CONVERT_FLOAT (&native[i], CVT$K_VAX_F,
-                                        &ieee[i], CVT$K_IEEE_S, 
-                                        options);
-           if (status != CVT$_NORMAL) {
-                 ieee[i] = *unanval;
-           }
-        }       
-
-}
-/* IEEVPAKD -- Pack a native double floating point vector into an IEEE one.
-*/
-void ieevpd (unsigned long *native, unsigned long *ieee, int *nelem)
-{
-        unsigned long status;
-        unsigned long options;
-        unsigned long *unanval;
-        long nanval = -1;
-        int     i,n;
-
-        unanval = (unsigned long *) &nanval;
-        options = CVT$M_BIG_ENDIAN;
-        
-        n = *nelem * 2;
-        status = CVT$_NORMAL;
-
-        for (i = 0; i < n ; i=i+2) {
-
-            status = CVT$CONVERT_FLOAT (&native[i], CVT$K_VAX_D,
-                                        &ieee[i], CVT$K_IEEE_T, 
-                                        options);
-           if (status != CVT$_NORMAL) {
-                 ieee[i]   = *unanval;
-                 ieee[i+1] = *unanval;
-           }
-        }       
-
-}
-/* IEEVUPKR -- Unpack an ieee vector into native single floating point vector.
-*/
-void ieevur (unsigned int *ieee, unsigned int *native, int *nelem)
-{
-        unsigned long status;
-        unsigned long options;
-        unsigned int *unanval;
-        int nanval = -1;
-        int     j,n;
-
-        unanval = (unsigned int *) &nanval;
-        options = CVT$M_ERR_UNDERFLOW+CVT$M_BIG_ENDIAN;
-        
-        n = *nelem;
-
-        status = CVT$_NORMAL;
-
-        for (j = 0; j < n ; j++) {
-           status = CVT$CONVERT_FLOAT (&ieee[j], CVT$K_IEEE_S,
-                                        &native[j], CVT$K_VAX_F, 
-                                        options);
-           if (status != CVT$_NORMAL)
-              switch(status) {
-              case CVT$_INVVAL:
-              case CVT$_NEGINF:
-              case CVT$_OVERFLOW:
-              case CVT$_POSINF:
-                 native[j]   = *unanval;
-                 break;
-              default:
-                 native[j] = 0;             
-              }
-        }
-}
-/* IEEVUPKD -- Unpack an ieee vector into native double floating point vector.
-*/
-void ieevud (unsigned long *ieee, unsigned long *native, int *nelem)
-{
-        unsigned long status;
-        unsigned long options;
-        unsigned long *unanval;
-        long nanval = -1;
-        int     j,n;
-
-        unanval = (unsigned long *) &nanval;
-        options = CVT$M_BIG_ENDIAN + CVT$M_ERR_UNDERFLOW; 
-        
-        n = *nelem * 2;
-
-        status = CVT$_NORMAL;
-
-        for (j = 0; j < n ; j=j+2) {
-           status = CVT$CONVERT_FLOAT (&ieee[j], CVT$K_IEEE_T,
-                                        &native[j], CVT$K_VAX_D, 
-                                        options);
-           if (status != CVT$_NORMAL)
-              switch(status) {
-              case CVT$_INVVAL:
-              case CVT$_NEGINF:
-              case CVT$_OVERFLOW:
-              case CVT$_POSINF:
-                 native[j]   = *unanval;
-                 native[j+1] = *unanval;
-                 break;
-              default:
-                 native[j]   = 0;             
-                 native[j+1] = 0;             
-              }
-        }
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/wcssub.c b/src/external/OpenGR/3rdparty/cfitsio/wcssub.c
deleted file mode 100644
index 1c1a5b701..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/wcssub.c
+++ /dev/null
@@ -1,1043 +0,0 @@
-#include 
-#include 
-#include 
-#include "fitsio2.h"
-
-/*--------------------------------------------------------------------------*/
-int fits_read_wcstab(
-   fitsfile   *fptr, /* I - FITS file pointer           */
-   int  nwtb,        /* Number of arrays to be read from the binary table(s) */
-   wtbarr *wtb,      /* Address of the first element of an array of wtbarr
-                         typedefs.  This wtbarr typedef is defined below to
-                         match the wtbarr struct defined in WCSLIB.  An array
-                         of such structs returned by the WCSLIB function
-                         wcstab(). */
-   int  *status)
-
-/*
-*   Author: Mark Calabretta, Australia Telescope National Facility
-*   http://www.atnf.csiro.au/~mcalabre/index.html
-*
-*   fits_read_wcstab() extracts arrays from a binary table required in
-*   constructing -TAB coordinates.  This helper routine is intended for
-*   use by routines in the WCSLIB library when dealing with the -TAB table
-*   look up WCS convention.
-*/
-
-{
-   int  anynul, colnum, hdunum, iwtb, m, naxis, nostat;
-   long *naxes = 0, nelem;
-   wtbarr *wtbp;
-
-
-   if (*status) return *status;
-
-   if (fptr == 0) {
-      return (*status = NULL_INPUT_PTR);
-   }
-
-   if (nwtb == 0) return 0;
-
-   /* Zero the array pointers. */
-   wtbp = wtb;
-   for (iwtb = 0; iwtb < nwtb; iwtb++, wtbp++) {
-     *wtbp->arrayp = 0x0;
-   }
-
-   /* Save HDU number so that we can move back to it later. */
-   fits_get_hdu_num(fptr, &hdunum);
-
-   wtbp = wtb;
-   for (iwtb = 0; iwtb < nwtb; iwtb++, wtbp++) {
-      /* Move to the required binary table extension. */
-      if (fits_movnam_hdu(fptr, BINARY_TBL, (char *)(wtbp->extnam),
-          wtbp->extver, status)) {
-         goto cleanup;
-      }
-
-      /* Locate the table column. */
-      if (fits_get_colnum(fptr, CASEINSEN, (char *)(wtbp->ttype), &colnum,
-          status)) {
-         goto cleanup;
-      }
-
-      /* Get the array dimensions and check for consistency. */
-      if (wtbp->ndim < 1) {
-         *status = NEG_AXIS;
-         goto cleanup;
-      }
-
-      if (!(naxes = calloc(wtbp->ndim, sizeof(long)))) {
-         *status = MEMORY_ALLOCATION;
-         goto cleanup;
-      }
-
-      if (fits_read_tdim(fptr, colnum, wtbp->ndim, &naxis, naxes, status)) {
-         goto cleanup;
-      }
-
-      if (naxis != wtbp->ndim) {
-         if (wtbp->kind == 'c' && wtbp->ndim == 2) {
-            /* Allow TDIMn to be omitted for degenerate coordinate arrays. */
-            naxis = 2;
-            naxes[1] = naxes[0];
-            naxes[0] = 1;
-         } else {
-            *status = BAD_TDIM;
-            goto cleanup;
-         }
-      }
-
-      if (wtbp->kind == 'c') {
-         /* Coordinate array; calculate the array size. */
-         nelem = naxes[0];
-         for (m = 0; m < naxis-1; m++) {
-            *(wtbp->dimlen + m) = naxes[m+1];
-            nelem *= naxes[m+1];
-         }
-      } else {
-         /* Index vector; check length. */
-         if ((nelem = naxes[0]) != *(wtbp->dimlen)) {
-            /* N.B. coordinate array precedes the index vectors. */
-            *status = BAD_TDIM;
-            goto cleanup;
-         }
-      }
-
-      free(naxes);
-      naxes = 0;
-
-      /* Allocate memory for the array. */
-      if (!(*wtbp->arrayp = calloc((size_t)nelem, sizeof(double)))) {
-         *status = MEMORY_ALLOCATION;
-         goto cleanup;
-      }
-
-      /* Read the array from the table. */
-      if (fits_read_col_dbl(fptr, colnum, wtbp->row, 1L, nelem, 0.0,
-          *wtbp->arrayp, &anynul, status)) {
-         goto cleanup;
-      }
-   }
-
-cleanup:
-   /* Move back to the starting HDU. */
-   nostat = 0;
-   fits_movabs_hdu(fptr, hdunum, 0, &nostat);
-
-   /* Release allocated memory. */
-   if (naxes) free(naxes);
-   if (*status) {
-      wtbp = wtb;
-      for (iwtb = 0; iwtb < nwtb; iwtb++, wtbp++) {
-         if (*wtbp->arrayp) free(*wtbp->arrayp);
-      }
-   }
-
-   return *status;
-}
-/*--------------------------------------------------------------------------*/
-int ffgiwcs(fitsfile *fptr,  /* I - FITS file pointer                    */
-           char **header,   /* O - pointer to the WCS related keywords  */
-           int *status)     /* IO - error status                        */
-/*
-  int fits_get_image_wcs_keys 
-  return a string containing all the image WCS header keywords.
-  This string is then used as input to the wcsinit WCSlib routine.
-  
-  THIS ROUTINE IS DEPRECATED. USE fits_hdr2str INSTEAD
-*/
-{
-    int hdutype;
-
-    if (*status > 0)
-        return(*status);
-
-    fits_get_hdu_type(fptr, &hdutype, status);
-    if (hdutype != IMAGE_HDU)
-    {
-      ffpmsg(
-     "Error in ffgiwcs. This HDU is not an image. Can't read WCS keywords");
-      return(*status = NOT_IMAGE);
-    }
-
-    /* read header keywords into a long string of chars */
-    if (ffh2st(fptr, header, status) > 0)
-    {
-        ffpmsg("error creating string of image WCS keywords (ffgiwcs)");
-        return(*status);
-    }
-
-    return(*status);
-}
-
-/*--------------------------------------------------------------------------*/
-int ffgics(fitsfile *fptr,    /* I - FITS file pointer           */
-           double *xrval,     /* O - X reference value           */
-           double *yrval,     /* O - Y reference value           */
-           double *xrpix,     /* O - X reference pixel           */
-           double *yrpix,     /* O - Y reference pixel           */
-           double *xinc,      /* O - X increment per pixel       */
-           double *yinc,      /* O - Y increment per pixel       */
-           double *rot,       /* O - rotation angle (degrees)    */
-           char *type,        /* O - type of projection ('-tan') */
-           int *status)       /* IO - error status               */
-/*
-       read the values of the celestial coordinate system keywords.
-       These values may be used as input to the subroutines that
-       calculate celestial coordinates. (ffxypx, ffwldp)
-
-       Modified in Nov 1999 to convert the CD matrix keywords back
-       to the old CDELTn form, and to swap the axes if the dec-like
-       axis is given first, and to assume default values if any of the
-       keywords are not present.
-*/
-{
-    int tstat = 0, cd_exists = 0, pc_exists = 0;
-    char ctype[FLEN_VALUE];
-    double cd11 = 0.0, cd21 = 0.0, cd22 = 0.0, cd12 = 0.0;
-    double pc11 = 1.0, pc21 = 0.0, pc22 = 1.0, pc12 = 0.0;
-    double pi =  3.1415926535897932;
-    double phia, phib, temp;
-    double toler = .0002;  /* tolerance for angles to agree (radians) */
-                           /*   (= approximately 0.01 degrees) */
-
-    if (*status > 0)
-       return(*status);
-
-    tstat = 0;
-    if (ffgkyd(fptr, "CRVAL1", xrval, NULL, &tstat))
-       *xrval = 0.;
-
-    tstat = 0;
-    if (ffgkyd(fptr, "CRVAL2", yrval, NULL, &tstat))
-       *yrval = 0.;
-
-    tstat = 0;
-    if (ffgkyd(fptr, "CRPIX1", xrpix, NULL, &tstat))
-        *xrpix = 0.;
-
-    tstat = 0;
-    if (ffgkyd(fptr, "CRPIX2", yrpix, NULL, &tstat))
-        *yrpix = 0.;
-
-    /* look for CDELTn first, then CDi_j keywords */
-    tstat = 0;
-    if (ffgkyd(fptr, "CDELT1", xinc, NULL, &tstat))
-    {
-        /* CASE 1: no CDELTn keyword, so look for the CD matrix */
-        tstat = 0;
-        if (ffgkyd(fptr, "CD1_1", &cd11, NULL, &tstat))
-            tstat = 0;  /* reset keyword not found error */
-        else
-            cd_exists = 1;  /* found at least 1 CD_ keyword */
-
-        if (ffgkyd(fptr, "CD2_1", &cd21, NULL, &tstat))
-            tstat = 0;  /* reset keyword not found error */
-        else
-            cd_exists = 1;  /* found at least 1 CD_ keyword */
-
-        if (ffgkyd(fptr, "CD1_2", &cd12, NULL, &tstat))
-            tstat = 0;  /* reset keyword not found error */
-        else
-            cd_exists = 1;  /* found at least 1 CD_ keyword */
-
-        if (ffgkyd(fptr, "CD2_2", &cd22, NULL, &tstat))
-            tstat = 0;  /* reset keyword not found error */
-        else
-            cd_exists = 1;  /* found at least 1 CD_ keyword */
-
-        if (cd_exists)  /* convert CDi_j back to CDELTn */
-        {
-            /* there are 2 ways to compute the angle: */
-            phia = atan2( cd21, cd11);
-            phib = atan2(-cd12, cd22);
-
-            /* ensure that phia <= phib */
-            temp = minvalue(phia, phib);
-            phib = maxvalue(phia, phib);
-            phia = temp;
-
-            /* there is a possible 180 degree ambiguity in the angles */
-            /* so add 180 degress to the smaller value if the values  */
-            /* differ by more than 90 degrees = pi/2 radians.         */
-            /* (Later, we may decide to take the other solution by    */
-            /* subtracting 180 degrees from the larger value).        */
-
-            if ((phib - phia) > (pi / 2.))
-               phia += pi;
-
-            if (fabs(phia - phib) > toler) 
-            {
-               /* angles don't agree, so looks like there is some skewness */
-               /* between the axes.  Return with an error to be safe. */
-               *status = APPROX_WCS_KEY;
-            }
-      
-            phia = (phia + phib) /2.;  /* use the average of the 2 values */
-            *xinc = cd11 / cos(phia);
-            *yinc = cd22 / cos(phia);
-            *rot = phia * 180. / pi;
-
-            /* common usage is to have a positive yinc value.  If it is */
-            /* negative, then subtract 180 degrees from rot and negate  */
-            /* both xinc and yinc.  */
-
-            if (*yinc < 0)
-            {
-                *xinc = -(*xinc);
-                *yinc = -(*yinc);
-                *rot = *rot - 180.;
-            }
-        }
-        else   /* no CD matrix keywords either */
-        {
-            *xinc = 1.;
-
-            /* there was no CDELT1 keyword, but check for CDELT2 just in case */
-            tstat = 0;
-            if (ffgkyd(fptr, "CDELT2", yinc, NULL, &tstat))
-                *yinc = 1.;
-
-            tstat = 0;
-            if (ffgkyd(fptr, "CROTA2", rot, NULL, &tstat))
-                *rot=0.;
-        }
-    }
-    else  /* Case 2: CDELTn + optional PC matrix */
-    {
-        if (ffgkyd(fptr, "CDELT2", yinc, NULL, &tstat))
-            *yinc = 1.;
-
-        tstat = 0;
-        if (ffgkyd(fptr, "CROTA2", rot, NULL, &tstat))
-        {
-            *rot=0.;
-
-            /* no CROTA2 keyword, so look for the PC matrix */
-            tstat = 0;
-            if (ffgkyd(fptr, "PC1_1", &pc11, NULL, &tstat))
-                tstat = 0;  /* reset keyword not found error */
-            else
-                pc_exists = 1;  /* found at least 1 PC_ keyword */
-
-            if (ffgkyd(fptr, "PC2_1", &pc21, NULL, &tstat))
-                tstat = 0;  /* reset keyword not found error */
-            else
-                pc_exists = 1;  /* found at least 1 PC_ keyword */
-
-            if (ffgkyd(fptr, "PC1_2", &pc12, NULL, &tstat))
-                tstat = 0;  /* reset keyword not found error */
-            else
-                pc_exists = 1;  /* found at least 1 PC_ keyword */
-
-            if (ffgkyd(fptr, "PC2_2", &pc22, NULL, &tstat))
-                tstat = 0;  /* reset keyword not found error */
-            else
-                pc_exists = 1;  /* found at least 1 PC_ keyword */
-
-            if (pc_exists)  /* convert PCi_j back to CDELTn */
-            {
-                /* there are 2 ways to compute the angle: */
-                phia = atan2( pc21, pc11);
-                phib = atan2(-pc12, pc22);
-
-                /* ensure that phia <= phib */
-                temp = minvalue(phia, phib);
-                phib = maxvalue(phia, phib);
-                phia = temp;
-
-                /* there is a possible 180 degree ambiguity in the angles */
-                /* so add 180 degress to the smaller value if the values  */
-                /* differ by more than 90 degrees = pi/2 radians.         */
-                /* (Later, we may decide to take the other solution by    */
-                /* subtracting 180 degrees from the larger value).        */
-
-                if ((phib - phia) > (pi / 2.))
-                   phia += pi;
-
-                if (fabs(phia - phib) > toler) 
-                {
-                  /* angles don't agree, so looks like there is some skewness */
-                  /* between the axes.  Return with an error to be safe. */
-                  *status = APPROX_WCS_KEY;
-                }
-      
-                phia = (phia + phib) /2.;  /* use the average of the 2 values */
-                *rot = phia * 180. / pi;
-            }
-        }
-    }
-
-    /* get the type of projection, if any */
-    tstat = 0;
-    if (ffgkys(fptr, "CTYPE1", ctype, NULL, &tstat))
-         type[0] = '\0';
-    else
-    {
-        /* copy the projection type string */
-        strncpy(type, &ctype[4], 4);
-        type[4] = '\0';
-
-        /* check if RA and DEC are inverted */
-        if (!strncmp(ctype, "DEC-", 4) || !strncmp(ctype+1, "LAT", 3))
-        {
-            /* the latitudinal axis is given first, so swap them */
-
-/*
- this case was removed on 12/9.  Apparently not correct.
-
-            if ((*xinc / *yinc) < 0. )  
-                *rot = -90. - (*rot);
-            else
-*/
-            *rot = 90. - (*rot);
-
-            /* Empirical tests with ds9 show the y-axis sign must be negated */
-            /* and the xinc and yinc values must NOT be swapped. */
-            *yinc = -(*yinc);
-
-            temp = *xrval;
-            *xrval = *yrval;
-            *yrval = temp;
-        }   
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgicsa(fitsfile *fptr,    /* I - FITS file pointer           */
-           char version,      /* I - character code of desired version */
-	                      /*     A - Z or blank */
-           double *xrval,     /* O - X reference value           */
-           double *yrval,     /* O - Y reference value           */
-           double *xrpix,     /* O - X reference pixel           */
-           double *yrpix,     /* O - Y reference pixel           */
-           double *xinc,      /* O - X increment per pixel       */
-           double *yinc,      /* O - Y increment per pixel       */
-           double *rot,       /* O - rotation angle (degrees)    */
-           char *type,        /* O - type of projection ('-tan') */
-           int *status)       /* IO - error status               */
-/*
-       read the values of the celestial coordinate system keywords.
-       These values may be used as input to the subroutines that
-       calculate celestial coordinates. (ffxypx, ffwldp)
-
-       Modified in Nov 1999 to convert the CD matrix keywords back
-       to the old CDELTn form, and to swap the axes if the dec-like
-       axis is given first, and to assume default values if any of the
-       keywords are not present.
-*/
-{
-    int tstat = 0, cd_exists = 0, pc_exists = 0;
-    char ctype[FLEN_VALUE], keyname[FLEN_VALUE], alt[2];
-    double cd11 = 0.0, cd21 = 0.0, cd22 = 0.0, cd12 = 0.0;
-    double pc11 = 1.0, pc21 = 0.0, pc22 = 1.0, pc12 = 0.0;
-    double pi =  3.1415926535897932;
-    double phia, phib, temp;
-    double toler = .0002;  /* tolerance for angles to agree (radians) */
-                           /*   (= approximately 0.01 degrees) */
-
-    if (*status > 0)
-       return(*status);
-
-    if (version == ' ') {
-      ffgics(fptr, xrval, yrval, xrpix, yrpix, xinc, yinc, rot, type, status);
-      return (*status);
-    }
-
-    if (version > 'Z' || version < 'A') {
-      ffpmsg("ffgicsa: illegal WCS version code (must be A - Z or blank)");
-      return(*status = WCS_ERROR);
-    }
-
-    alt[0] = version;
-    alt[1] = '\0';
-    
-    tstat = 0;
-    strcpy(keyname, "CRVAL1");
-    strcat(keyname, alt);
-    if (ffgkyd(fptr, keyname, xrval, NULL, &tstat))
-       *xrval = 0.;
-
-    tstat = 0;
-    strcpy(keyname, "CRVAL2");
-    strcat(keyname, alt);
-    if (ffgkyd(fptr, keyname, yrval, NULL, &tstat))
-       *yrval = 0.;
-
-    tstat = 0;
-    strcpy(keyname, "CRPIX1");
-    strcat(keyname, alt);
-    if (ffgkyd(fptr, keyname, xrpix, NULL, &tstat))
-        *xrpix = 0.;
-
-    tstat = 0;
-    strcpy(keyname, "CRPIX2");
-    strcat(keyname, alt);
-     if (ffgkyd(fptr, keyname, yrpix, NULL, &tstat))
-        *yrpix = 0.;
-
-    /* look for CDELTn first, then CDi_j keywords */
-    tstat = 0;
-    strcpy(keyname, "CDELT1");
-    strcat(keyname, alt);
-    if (ffgkyd(fptr, keyname, xinc, NULL, &tstat))
-    {
-        /* CASE 1: no CDELTn keyword, so look for the CD matrix */
-        tstat = 0;
-        strcpy(keyname, "CD1_1");
-        strcat(keyname, alt);
-        if (ffgkyd(fptr, keyname, &cd11, NULL, &tstat))
-            tstat = 0;  /* reset keyword not found error */
-        else
-            cd_exists = 1;  /* found at least 1 CD_ keyword */
-
-        strcpy(keyname, "CD2_1");
-        strcat(keyname, alt);
-        if (ffgkyd(fptr, keyname, &cd21, NULL, &tstat))
-            tstat = 0;  /* reset keyword not found error */
-        else
-            cd_exists = 1;  /* found at least 1 CD_ keyword */
-
-        strcpy(keyname, "CD1_2");
-        strcat(keyname, alt);
-        if (ffgkyd(fptr, keyname, &cd12, NULL, &tstat))
-            tstat = 0;  /* reset keyword not found error */
-        else
-            cd_exists = 1;  /* found at least 1 CD_ keyword */
-
-        strcpy(keyname, "CD2_2");
-        strcat(keyname, alt);
-        if (ffgkyd(fptr, keyname, &cd22, NULL, &tstat))
-            tstat = 0;  /* reset keyword not found error */
-        else
-            cd_exists = 1;  /* found at least 1 CD_ keyword */
-
-        if (cd_exists)  /* convert CDi_j back to CDELTn */
-        {
-            /* there are 2 ways to compute the angle: */
-            phia = atan2( cd21, cd11);
-            phib = atan2(-cd12, cd22);
-
-            /* ensure that phia <= phib */
-            temp = minvalue(phia, phib);
-            phib = maxvalue(phia, phib);
-            phia = temp;
-
-            /* there is a possible 180 degree ambiguity in the angles */
-            /* so add 180 degress to the smaller value if the values  */
-            /* differ by more than 90 degrees = pi/2 radians.         */
-            /* (Later, we may decide to take the other solution by    */
-            /* subtracting 180 degrees from the larger value).        */
-
-            if ((phib - phia) > (pi / 2.))
-               phia += pi;
-
-            if (fabs(phia - phib) > toler) 
-            {
-               /* angles don't agree, so looks like there is some skewness */
-               /* between the axes.  Return with an error to be safe. */
-               *status = APPROX_WCS_KEY;
-            }
-      
-            phia = (phia + phib) /2.;  /* use the average of the 2 values */
-            *xinc = cd11 / cos(phia);
-            *yinc = cd22 / cos(phia);
-            *rot = phia * 180. / pi;
-
-            /* common usage is to have a positive yinc value.  If it is */
-            /* negative, then subtract 180 degrees from rot and negate  */
-            /* both xinc and yinc.  */
-
-            if (*yinc < 0)
-            {
-                *xinc = -(*xinc);
-                *yinc = -(*yinc);
-                *rot = *rot - 180.;
-            }
-        }
-        else   /* no CD matrix keywords either */
-        {
-            *xinc = 1.;
-
-            /* there was no CDELT1 keyword, but check for CDELT2 just in case */
-            tstat = 0;
-            strcpy(keyname, "CDELT2");
-            strcat(keyname, alt);
-            if (ffgkyd(fptr, keyname, yinc, NULL, &tstat))
-                *yinc = 1.;
-
-            tstat = 0;
-            strcpy(keyname, "CROTA2");
-            strcat(keyname, alt);
-            if (ffgkyd(fptr, keyname, rot, NULL, &tstat))
-                *rot=0.;
-        }
-    }
-    else  /* Case 2: CDELTn + optional PC matrix */
-    {
-        strcpy(keyname, "CDELT2");
-        strcat(keyname, alt);
-        if (ffgkyd(fptr, keyname, yinc, NULL, &tstat))
-            *yinc = 1.;
-
-        tstat = 0;
-        strcpy(keyname, "CROTA2");
-        strcat(keyname, alt);
-        if (ffgkyd(fptr, keyname, rot, NULL, &tstat))
-        {
-            *rot=0.;
-
-            /* no CROTA2 keyword, so look for the PC matrix */
-            tstat = 0;
-            strcpy(keyname, "PC1_1");
-            strcat(keyname, alt);
-            if (ffgkyd(fptr, keyname, &pc11, NULL, &tstat))
-                tstat = 0;  /* reset keyword not found error */
-            else
-                pc_exists = 1;  /* found at least 1 PC_ keyword */
-
-            strcpy(keyname, "PC2_1");
-            strcat(keyname, alt);
-            if (ffgkyd(fptr, keyname, &pc21, NULL, &tstat))
-                tstat = 0;  /* reset keyword not found error */
-            else
-                pc_exists = 1;  /* found at least 1 PC_ keyword */
-
-            strcpy(keyname, "PC1_2");
-            strcat(keyname, alt);
-            if (ffgkyd(fptr, keyname, &pc12, NULL, &tstat))
-                tstat = 0;  /* reset keyword not found error */
-            else
-                pc_exists = 1;  /* found at least 1 PC_ keyword */
-
-            strcpy(keyname, "PC2_2");
-            strcat(keyname, alt);
-            if (ffgkyd(fptr, keyname, &pc22, NULL, &tstat))
-                tstat = 0;  /* reset keyword not found error */
-            else
-                pc_exists = 1;  /* found at least 1 PC_ keyword */
-
-            if (pc_exists)  /* convert PCi_j back to CDELTn */
-            {
-                /* there are 2 ways to compute the angle: */
-                phia = atan2( pc21, pc11);
-                phib = atan2(-pc12, pc22);
-
-                /* ensure that phia <= phib */
-                temp = minvalue(phia, phib);
-                phib = maxvalue(phia, phib);
-                phia = temp;
-
-                /* there is a possible 180 degree ambiguity in the angles */
-                /* so add 180 degress to the smaller value if the values  */
-                /* differ by more than 90 degrees = pi/2 radians.         */
-                /* (Later, we may decide to take the other solution by    */
-                /* subtracting 180 degrees from the larger value).        */
-
-                if ((phib - phia) > (pi / 2.))
-                   phia += pi;
-
-                if (fabs(phia - phib) > toler) 
-                {
-                  /* angles don't agree, so looks like there is some skewness */
-                  /* between the axes.  Return with an error to be safe. */
-                  *status = APPROX_WCS_KEY;
-                }
-      
-                phia = (phia + phib) /2.;  /* use the average of the 2 values */
-                *rot = phia * 180. / pi;
-            }
-        }
-    }
-
-    /* get the type of projection, if any */
-    tstat = 0;
-    strcpy(keyname, "CTYPE1");
-    strcat(keyname, alt);
-    if (ffgkys(fptr, keyname, ctype, NULL, &tstat))
-         type[0] = '\0';
-    else
-    {
-        /* copy the projection type string */
-        strncpy(type, &ctype[4], 4);
-        type[4] = '\0';
-
-        /* check if RA and DEC are inverted */
-        if (!strncmp(ctype, "DEC-", 4) || !strncmp(ctype+1, "LAT", 3))
-        {
-            /* the latitudinal axis is given first, so swap them */
-
-            *rot = 90. - (*rot);
-
-            /* Empirical tests with ds9 show the y-axis sign must be negated */
-            /* and the xinc and yinc values must NOT be swapped. */
-            *yinc = -(*yinc);
-
-            temp = *xrval;
-            *xrval = *yrval;
-            *yrval = temp;
-        }   
-    }
-
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgtcs(fitsfile *fptr,    /* I - FITS file pointer           */
-           int xcol,          /* I - column containing the RA coordinate  */
-           int ycol,          /* I - column containing the DEC coordinate */
-           double *xrval,     /* O - X reference value           */
-           double *yrval,     /* O - Y reference value           */
-           double *xrpix,     /* O - X reference pixel           */
-           double *yrpix,     /* O - Y reference pixel           */
-           double *xinc,      /* O - X increment per pixel       */
-           double *yinc,      /* O - Y increment per pixel       */
-           double *rot,       /* O - rotation angle (degrees)    */
-           char *type,        /* O - type of projection ('-sin') */
-           int *status)       /* IO - error status               */
-/*
-       read the values of the celestial coordinate system keywords
-       from a FITS table where the X and Y or RA and DEC coordinates
-       are stored in separate column.  Do this by converting the
-       table to a temporary FITS image, then reading the keywords
-       from the image file.
-       These values may be used as input to the subroutines that
-       calculate celestial coordinates. (ffxypx, ffwldp)
-*/
-{
-    int colnum[2];
-    long naxes[2];
-    fitsfile *tptr;
-
-    if (*status > 0)
-       return(*status);
-
-    colnum[0] = xcol;
-    colnum[1] = ycol;
-    naxes[0] = 10;
-    naxes[1] = 10;
-
-    /* create temporary  FITS file, in memory */
-    ffinit(&tptr, "mem://", status);
-    
-    /* create a temporary image; the datatype and size are not important */
-    ffcrim(tptr, 32, 2, naxes, status);
-    
-    /* now copy the relevant keywords from the table to the image */
-    fits_copy_pixlist2image(fptr, tptr, 9, 2, colnum, status);
-
-    /* write default WCS keywords, if they are not present */
-    fits_write_keys_histo(fptr, tptr, 2, colnum, status);
-
-    if (*status > 0)
-       return(*status);
-         
-    /* read the WCS keyword values from the temporary image */
-    ffgics(tptr, xrval, yrval, xrpix, yrpix, xinc, yinc, rot, type, status); 
-
-    if (*status > 0)
-    {
-      ffpmsg
-      ("ffgtcs could not find all the celestial coordinate keywords");
-      return(*status = NO_WCS_KEY); 
-    }
-
-    /* delete the temporary file */
-    fits_delete_file(tptr, status);
-    
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int ffgtwcs(fitsfile *fptr,  /* I - FITS file pointer              */
-           int xcol,        /* I - column number for the X column  */
-           int ycol,        /* I - column number for the Y column  */
-           char **header,   /* O - string of all the WCS keywords  */
-           int *status)     /* IO - error status                   */
-/*
-  int fits_get_table_wcs_keys
-  Return string containing all the WCS keywords appropriate for the 
-  pair of X and Y columns containing the coordinate
-  of each event in an event list table.  This string may then be passed
-  to Doug Mink's WCS library wcsinit routine, to create and initialize the
-  WCS structure.  The calling routine must free the header character string
-  when it is no longer needed. 
-
-  THIS ROUTINE IS DEPRECATED. USE fits_hdr2str INSTEAD
-*/
-{
-    int hdutype, ncols, tstatus, length;
-    int naxis1 = 1, naxis2 = 1;
-    long tlmin, tlmax;
-    char keyname[FLEN_KEYWORD];
-    char valstring[FLEN_VALUE];
-    char comm[2];
-    char *cptr;
-    /*  construct a string of 80 blanks, for adding fill to the keywords */
-                 /*  12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
-    char blanks[] = "                                                                                ";
-
-    if (*status > 0)
-        return(*status);
-
-    fits_get_hdu_type(fptr, &hdutype, status);
-    if (hdutype == IMAGE_HDU)
-    {
-        ffpmsg("Can't read table WSC keywords. This HDU is not a table");
-        return(*status = NOT_TABLE);
-    }
-
-    fits_get_num_cols(fptr, &ncols, status);
-    
-    if (xcol < 1 || xcol > ncols)
-    {
-        ffpmsg("illegal X axis column number in fftwcs");
-        return(*status = BAD_COL_NUM);
-    }
-
-    if (ycol < 1 || ycol > ncols)
-    {
-        ffpmsg("illegal Y axis column number in fftwcs");
-        return(*status = BAD_COL_NUM);
-    }
-
-    /* allocate character string for all the WCS keywords */
-    *header = calloc(1, 2401);  /* room for up to 30 keywords */
-    if (*header == 0)
-    {
-        ffpmsg("error allocating memory for WCS header keywords (fftwcs)");
-        return(*status = MEMORY_ALLOCATION);
-    }
-
-    cptr = *header;
-    comm[0] = '\0';
-    
-    tstatus = 0;
-    ffkeyn("TLMIN",xcol,keyname,status);
-    ffgkyj(fptr,keyname, &tlmin,NULL,&tstatus);
-
-    if (!tstatus)
-    {
-        ffkeyn("TLMAX",xcol,keyname,status);
-        ffgkyj(fptr,keyname, &tlmax,NULL,&tstatus);
-    }
-
-    if (!tstatus)
-    {
-        naxis1 = tlmax - tlmin + 1;
-    }
-
-    tstatus = 0;
-    ffkeyn("TLMIN",ycol,keyname,status);
-    ffgkyj(fptr,keyname, &tlmin,NULL,&tstatus);
-
-    if (!tstatus)
-    {
-        ffkeyn("TLMAX",ycol,keyname,status);
-        ffgkyj(fptr,keyname, &tlmax,NULL,&tstatus);
-    }
-
-    if (!tstatus)
-    {
-        naxis2 = tlmax - tlmin + 1;
-    }
-
-    /*            123456789012345678901234567890    */
-    strcat(cptr, "NAXIS   =                    2");
-    strncat(cptr, blanks, 50);
-    cptr += 80;
-
-    ffi2c(naxis1, valstring, status);   /* convert to formatted string */
-    ffmkky("NAXIS1", valstring, comm, cptr, status);  /* construct the keyword*/
-    strncat(cptr, blanks, 50);  /* pad with blanks */
-    cptr += 80;
-
-    strcpy(keyname, "NAXIS2");
-    ffi2c(naxis2, valstring, status);   /* convert to formatted string */
-    ffmkky(keyname, valstring, comm, cptr, status);  /* construct the keyword*/
-    strncat(cptr, blanks, 50);  /* pad with blanks */
-    cptr += 80;
-
-    /* read the required header keywords (use defaults if not found) */
-
-    /*  CTYPE1 keyword */
-    tstatus = 0;
-    ffkeyn("TCTYP",xcol,keyname,status);
-    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
-       valstring[0] =  '\0';
-    ffmkky("CTYPE1", valstring, comm, cptr, status);  /* construct the keyword*/
-    length = strlen(cptr);
-    strncat(cptr, blanks, 80 - length);  /* pad with blanks */
-    cptr += 80;
-
-    /*  CTYPE2 keyword */
-    tstatus = 0;
-    ffkeyn("TCTYP",ycol,keyname,status);
-    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
-       valstring[0] =  '\0';
-    ffmkky("CTYPE2", valstring, comm, cptr, status);  /* construct the keyword*/
-    length = strlen(cptr);
-    strncat(cptr, blanks, 80 - length);  /* pad with blanks */
-    cptr += 80;
-
-    /*  CRPIX1 keyword */
-    tstatus = 0;
-    ffkeyn("TCRPX",xcol,keyname,status);
-    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
-       strcpy(valstring, "1");
-    ffmkky("CRPIX1", valstring, comm, cptr, status);  /* construct the keyword*/
-    strncat(cptr, blanks, 50);  /* pad with blanks */
-    cptr += 80;
-
-    /*  CRPIX2 keyword */
-    tstatus = 0;
-    ffkeyn("TCRPX",ycol,keyname,status);
-    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
-       strcpy(valstring, "1");
-    ffmkky("CRPIX2", valstring, comm, cptr, status);  /* construct the keyword*/
-    strncat(cptr, blanks, 50);  /* pad with blanks */
-    cptr += 80;
-
-    /*  CRVAL1 keyword */
-    tstatus = 0;
-    ffkeyn("TCRVL",xcol,keyname,status);
-    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
-       strcpy(valstring, "1");
-    ffmkky("CRVAL1", valstring, comm, cptr, status);  /* construct the keyword*/
-    strncat(cptr, blanks, 50);  /* pad with blanks */
-    cptr += 80;
-
-    /*  CRVAL2 keyword */
-    tstatus = 0;
-    ffkeyn("TCRVL",ycol,keyname,status);
-    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
-       strcpy(valstring, "1");
-    ffmkky("CRVAL2", valstring, comm, cptr, status);  /* construct the keyword*/
-    strncat(cptr, blanks, 50);  /* pad with blanks */
-    cptr += 80;
-
-    /*  CDELT1 keyword */
-    tstatus = 0;
-    ffkeyn("TCDLT",xcol,keyname,status);
-    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
-       strcpy(valstring, "1");
-    ffmkky("CDELT1", valstring, comm, cptr, status);  /* construct the keyword*/
-    strncat(cptr, blanks, 50);  /* pad with blanks */
-    cptr += 80;
-
-    /*  CDELT2 keyword */
-    tstatus = 0;
-    ffkeyn("TCDLT",ycol,keyname,status);
-    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
-       strcpy(valstring, "1");
-    ffmkky("CDELT2", valstring, comm, cptr, status);  /* construct the keyword*/
-    strncat(cptr, blanks, 50);  /* pad with blanks */
-    cptr += 80;
-
-    /* the following keywords may not exist */
-
-    /*  CROTA2 keyword */
-    tstatus = 0;
-    ffkeyn("TCROT",ycol,keyname,status);
-    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) == 0 )
-    {
-        ffmkky("CROTA2", valstring, comm, cptr, status);  /* construct keyword*/
-        strncat(cptr, blanks, 50);  /* pad with blanks */
-        cptr += 80;
-    }
-
-    /*  EPOCH keyword */
-    tstatus = 0;
-    if (ffgkey(fptr, "EPOCH", valstring, NULL, &tstatus) == 0 )
-    {
-        ffmkky("EPOCH", valstring, comm, cptr, status);  /* construct keyword*/
-        length = strlen(cptr);
-        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
-        cptr += 80;
-    }
-
-    /*  EQUINOX keyword */
-    tstatus = 0;
-    if (ffgkey(fptr, "EQUINOX", valstring, NULL, &tstatus) == 0 )
-    {
-        ffmkky("EQUINOX", valstring, comm, cptr, status); /* construct keyword*/
-        length = strlen(cptr);
-        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
-        cptr += 80;
-    }
-
-    /*  RADECSYS keyword */
-    tstatus = 0;
-    if (ffgkey(fptr, "RADECSYS", valstring, NULL, &tstatus) == 0 )
-    {
-        ffmkky("RADECSYS", valstring, comm, cptr, status); /*construct keyword*/
-        length = strlen(cptr);
-        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
-        cptr += 80;
-    }
-
-    /*  TELESCOPE keyword */
-    tstatus = 0;
-    if (ffgkey(fptr, "TELESCOP", valstring, NULL, &tstatus) == 0 )
-    {
-        ffmkky("TELESCOP", valstring, comm, cptr, status); 
-        length = strlen(cptr);
-        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
-        cptr += 80;
-    }
-
-    /*  INSTRUME keyword */
-    tstatus = 0;
-    if (ffgkey(fptr, "INSTRUME", valstring, NULL, &tstatus) == 0 )
-    {
-        ffmkky("INSTRUME", valstring, comm, cptr, status);  
-        length = strlen(cptr);
-        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
-        cptr += 80;
-    }
-
-    /*  DETECTOR keyword */
-    tstatus = 0;
-    if (ffgkey(fptr, "DETECTOR", valstring, NULL, &tstatus) == 0 )
-    {
-        ffmkky("DETECTOR", valstring, comm, cptr, status);  
-        length = strlen(cptr);
-        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
-        cptr += 80;
-    }
-
-    /*  MJD-OBS keyword */
-    tstatus = 0;
-    if (ffgkey(fptr, "MJD-OBS", valstring, NULL, &tstatus) == 0 )
-    {
-        ffmkky("MJD-OBS", valstring, comm, cptr, status);  
-        length = strlen(cptr);
-        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
-        cptr += 80;
-    }
-
-    /*  DATE-OBS keyword */
-    tstatus = 0;
-    if (ffgkey(fptr, "DATE-OBS", valstring, NULL, &tstatus) == 0 )
-    {
-        ffmkky("DATE-OBS", valstring, comm, cptr, status);  
-        length = strlen(cptr);
-        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
-        cptr += 80;
-    }
-
-    /*  DATE keyword */
-    tstatus = 0;
-    if (ffgkey(fptr, "DATE", valstring, NULL, &tstatus) == 0 )
-    {
-        ffmkky("DATE", valstring, comm, cptr, status);  
-        length = strlen(cptr);
-        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
-        cptr += 80;
-    }
-
-    strcat(cptr, "END");
-    strncat(cptr, blanks, 77);
-
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/wcsutil.c b/src/external/OpenGR/3rdparty/cfitsio/wcsutil.c
deleted file mode 100644
index 01d80f9c5..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/wcsutil.c
+++ /dev/null
@@ -1,502 +0,0 @@
-#include 
-#include "fitsio2.h"
-#define D2R 0.01745329252
-#define TWOPI 6.28318530717959
-
-/*--------------------------------------------------------------------------*/
-int ffwldp(double xpix, double ypix, double xref, double yref,
-      double xrefpix, double yrefpix, double xinc, double yinc, double rot,
-      char *type, double *xpos, double *ypos, int *status)
-
-/* This routine is based on the classic AIPS WCS routine. 
-
-   It converts from pixel location to RA,Dec for 9 projective geometries:
-   "-CAR", "-SIN", "-TAN", "-ARC", "-NCP", "-GLS", "-MER", "-AIT" and "-STG".
-*/
-
-/*-----------------------------------------------------------------------*/
-/* routine to determine accurate position for pixel coordinates          */
-/* returns 0 if successful otherwise:                                    */
-/* 501 = angle too large for projection;                                 */
-/* does: -CAR, -SIN, -TAN, -ARC, -NCP, -GLS, -MER, -AIT  -STG projections*/
-/* Input:                                                                */
-/*   f   xpix    x pixel number  (RA or long without rotation)           */
-/*   f   ypiy    y pixel number  (dec or lat without rotation)           */
-/*   d   xref    x reference coordinate value (deg)                      */
-/*   d   yref    y reference coordinate value (deg)                      */
-/*   f   xrefpix x reference pixel                                       */
-/*   f   yrefpix y reference pixel                                       */
-/*   f   xinc    x coordinate increment (deg)                            */
-/*   f   yinc    y coordinate increment (deg)                            */
-/*   f   rot     rotation (deg)  (from N through E)                      */
-/*   c  *type    projection type code e.g. "-SIN";                       */
-/* Output:                                                               */
-/*   d   *xpos   x (RA) coordinate (deg)                                 */
-/*   d   *ypos   y (dec) coordinate (deg)                                */
-/*-----------------------------------------------------------------------*/
- {double cosr, sinr, dx, dy, dz, temp, x, y, z;
-  double sins, coss, dect, rat, dt, l, m, mg, da, dd, cos0, sin0;
-  double dec0, ra0;
-  double geo1, geo2, geo3;
-  double deps = 1.0e-5;
-  char *cptr;
-  
-  if (*status > 0)
-     return(*status);
-
-/*   Offset from ref pixel  */
-  dx = (xpix-xrefpix) * xinc;
-  dy = (ypix-yrefpix) * yinc;
-
-/*   Take out rotation  */
-  cosr = cos(rot * D2R);
-  sinr = sin(rot * D2R);
-  if (rot != 0.0) {
-     temp = dx * cosr - dy * sinr;
-     dy = dy * cosr + dx * sinr;
-     dx = temp;
-  }
-
-/* convert to radians  */
-  ra0 = xref * D2R;
-  dec0 = yref * D2R;
-
-  l = dx * D2R;
-  m = dy * D2R;
-  sins = l*l + m*m;
-  cos0 = cos(dec0);
-  sin0 = sin(dec0);
-
-  if (*type != '-') {  /* unrecognized projection code */
-     return(*status = 504);
-  }
-
-    cptr = type + 1;
-
-    if (*cptr == 'C') { /* linear -CAR */
-      if (*(cptr + 1) != 'A' ||  *(cptr + 2) != 'R') {
-         return(*status = 504);
-      }
-      rat =  ra0 + l;
-      dect = dec0 + m;
-
-    } else if (*cptr == 'T') {  /* -TAN */
-      if (*(cptr + 1) != 'A' ||  *(cptr + 2) != 'N') {
-         return(*status = 504);
-      }
-      x = cos0*cos(ra0) - l*sin(ra0) - m*cos(ra0)*sin0;
-      y = cos0*sin(ra0) + l*cos(ra0) - m*sin(ra0)*sin0;
-      z = sin0                       + m*         cos0;
-      rat  = atan2( y, x );
-      dect = atan ( z / sqrt(x*x+y*y) );
-
-    } else if (*cptr == 'S') {
-
-      if (*(cptr + 1) == 'I' &&  *(cptr + 2) == 'N') { /* -SIN */
-          if (sins>1.0)
-	    return(*status = 501);
-          coss = sqrt (1.0 - sins);
-          dt = sin0 * coss + cos0 * m;
-          if ((dt>1.0) || (dt<-1.0))
-	    return(*status = 501);
-          dect = asin (dt);
-          rat = cos0 * coss - sin0 * m;
-          if ((rat==0.0) && (l==0.0))
-	    return(*status = 501);
-          rat = atan2 (l, rat) + ra0;
-
-       } else if (*(cptr + 1) == 'T' &&  *(cptr + 2) == 'G') {  /* -STG Sterographic*/
-          dz = (4.0 - sins) / (4.0 + sins);
-          if (fabs(dz)>1.0)
-	    return(*status = 501);
-          dect = dz * sin0 + m * cos0 * (1.0+dz) / 2.0;
-          if (fabs(dect)>1.0)
-	    return(*status = 501);
-          dect = asin (dect);
-          rat = cos(dect);
-          if (fabs(rat)1.0)
-	    return(*status = 501);
-          rat = asin (rat);
-          mg = 1.0 + sin(dect) * sin0 + cos(dect) * cos0 * cos(rat);
-          if (fabs(mg)deps)
-	    rat = TWOPI /2.0 - rat;
-          rat = ra0 + rat;
-        } else  {
-          return(*status = 504);
-        }
- 
-    } else if (*cptr == 'A') {
-
-      if (*(cptr + 1) == 'R' &&  *(cptr + 2) == 'C') { /* ARC */
-          if (sins>=TWOPI*TWOPI/4.0)
-	    return(*status = 501);
-          sins = sqrt(sins);
-          coss = cos (sins);
-          if (sins!=0.0)
-	    sins = sin (sins) / sins;
-          else
-	    sins = 1.0;
-          dt = m * cos0 * sins + sin0 * coss;
-          if ((dt>1.0) || (dt<-1.0))
-	    return(*status = 501);
-          dect = asin (dt);
-          da = coss - dt * sin0;
-          dt = l * sins * cos0;
-          if ((da==0.0) && (dt==0.0))
-	    return(*status = 501);
-          rat = ra0 + atan2 (dt, da);
-
-      } else if (*(cptr + 1) == 'I' &&  *(cptr + 2) == 'T') {  /* -AIT Aitoff */
-          dt = yinc*cosr + xinc*sinr;
-          if (dt==0.0)
-	    dt = 1.0;
-          dt = dt * D2R;
-          dy = yref * D2R;
-          dx = sin(dy+dt)/sqrt((1.0+cos(dy+dt))/2.0) -
-	      sin(dy)/sqrt((1.0+cos(dy))/2.0);
-          if (dx==0.0)
-	    dx = 1.0;
-          geo2 = dt / dx;
-          dt = xinc*cosr - yinc* sinr;
-          if (dt==0.0)
-	    dt = 1.0;
-          dt = dt * D2R;
-          dx = 2.0 * cos(dy) * sin(dt/2.0);
-          if (dx==0.0) dx = 1.0;
-          geo1 = dt * sqrt((1.0+cos(dy)*cos(dt/2.0))/2.0) / dx;
-          geo3 = geo2 * sin(dy) / sqrt((1.0+cos(dy))/2.0);
-          rat = ra0;
-          dect = dec0;
-          if ((l != 0.0) || (m != 0.0)) {
-            dz = 4.0 - l*l/(4.0*geo1*geo1) - ((m+geo3)/geo2)*((m+geo3)/geo2) ;
-            if ((dz>4.0) || (dz<2.0)) return(*status = 501);
-            dz = 0.5 * sqrt (dz);
-            dd = (m+geo3) * dz / geo2;
-            if (fabs(dd)>1.0) return(*status = 501);
-            dd = asin (dd);
-            if (fabs(cos(dd))1.0) return(*status = 501);
-            da = asin (da);
-            rat = ra0 + 2.0 * da;
-            dect = dd;
-          }
-        } else  {
-          return(*status = 504);
-        }
- 
-    } else if (*cptr == 'N') { /* -NCP North celestial pole*/
-      if (*(cptr + 1) != 'C' ||  *(cptr + 2) != 'P') {
-         return(*status = 504);
-      }
-      dect = cos0 - m * sin0;
-      if (dect==0.0)
-        return(*status = 501);
-      rat = ra0 + atan2 (l, dect);
-      dt = cos (rat-ra0);
-      if (dt==0.0)
-        return(*status = 501);
-      dect = dect / dt;
-      if ((dect>1.0) || (dect<-1.0))
-        return(*status = 501);
-      dect = acos (dect);
-      if (dec0<0.0) dect = -dect;
-
-    } else if (*cptr == 'G') {   /* -GLS global sinusoid */
-      if (*(cptr + 1) != 'L' ||  *(cptr + 2) != 'S') {
-         return(*status = 504);
-      }
-      dect = dec0 + m;
-      if (fabs(dect)>TWOPI/4.0)
-        return(*status = 501);
-      coss = cos (dect);
-      if (fabs(l)>TWOPI*coss/2.0)
-        return(*status = 501);
-      rat = ra0;
-      if (coss>deps) rat = rat + l / coss;
-
-    } else if (*cptr == 'M') {  /* -MER mercator*/
-      if (*(cptr + 1) != 'E' ||  *(cptr + 2) != 'R') {
-         return(*status = 504);
-      }
-      dt = yinc * cosr + xinc * sinr;
-      if (dt==0.0) dt = 1.0;
-      dy = (yref/2.0 + 45.0) * D2R;
-      dx = dy + dt / 2.0 * D2R;
-      dy = log (tan (dy));
-      dx = log (tan (dx));
-      geo2 = dt * D2R / (dx - dy);
-      geo3 = geo2 * dy;
-      geo1 = cos (yref*D2R);
-      if (geo1<=0.0) geo1 = 1.0;
-      rat = l / geo1 + ra0;
-      if (fabs(rat - ra0) > TWOPI)
-        return(*status = 501);
-      dt = 0.0;
-      if (geo2!=0.0) dt = (m + geo3) / geo2;
-      dt = exp (dt);
-      dect = 2.0 * atan (dt) - TWOPI / 4.0;
-
-    } else  {
-      return(*status = 504);
-    }
-
-  /*  correct for RA rollover  */
-  if (rat-ra0>TWOPI/2.0) rat = rat - TWOPI;
-  if (rat-ra0<-TWOPI/2.0) rat = rat + TWOPI;
-  if (rat < 0.0) rat += TWOPI;
-
-  /*  convert to degrees  */
-  *xpos  = rat  / D2R;
-  *ypos  = dect  / D2R;
-  return(*status);
-} 
-/*--------------------------------------------------------------------------*/
-int ffxypx(double xpos, double ypos, double xref, double yref, 
-      double xrefpix, double yrefpix, double xinc, double yinc, double rot,
-      char *type, double *xpix, double *ypix, int *status)
-
-/* This routine is based on the classic AIPS WCS routine. 
-
-   It converts from RA,Dec to pixel location to for 9 projective geometries:
-   "-CAR", "-SIN", "-TAN", "-ARC", "-NCP", "-GLS", "-MER", "-AIT" and "-STG".
-*/
-/*-----------------------------------------------------------------------*/
-/* routine to determine accurate pixel coordinates for an RA and Dec     */
-/* returns 0 if successful otherwise:                                    */
-/* 501 = angle too large for projection;                                 */
-/* 502 = bad values                                                      */
-/* does: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, -AIT projections            */
-/* anything else is linear                                               */
-/* Input:                                                                */
-/*   d   xpos    x (RA) coordinate (deg)                                 */
-/*   d   ypos    y (dec) coordinate (deg)                                */
-/*   d   xref    x reference coordinate value (deg)                      */
-/*   d   yref    y reference coordinate value (deg)                      */
-/*   f   xrefpix x reference pixel                                       */
-/*   f   yrefpix y reference pixel                                       */
-/*   f   xinc    x coordinate increment (deg)                            */
-/*   f   yinc    y coordinate increment (deg)                            */
-/*   f   rot     rotation (deg)  (from N through E)                      */
-/*   c  *type    projection type code e.g. "-SIN";                       */
-/* Output:                                                               */
-/*   f  *xpix    x pixel number  (RA or long without rotation)           */
-/*   f  *ypiy    y pixel number  (dec or lat without rotation)           */
-/*-----------------------------------------------------------------------*/
- {
-  double dx, dy, dz, r, ra0, dec0, ra, dec, coss, sins, dt, da, dd, sint;
-  double l, m, geo1, geo2, geo3, sinr, cosr, cos0, sin0;
-  double deps=1.0e-5;
-  char *cptr;
-
-  if (*type != '-') {  /* unrecognized projection code */
-     return(*status = 504);
-  }
-
-  cptr = type + 1;
-
-  dt = (xpos - xref);
-  if (dt >  180) xpos -= 360;
-  if (dt < -180) xpos += 360;
-  /* NOTE: changing input argument xpos is OK (call-by-value in C!) */
-
-  /* default values - linear */
-  dx = xpos - xref;
-  dy = ypos - yref;
-
-  /*  Correct for rotation */
-  r = rot * D2R;
-  cosr = cos (r);
-  sinr = sin (r);
-  dz = dx*cosr + dy*sinr;
-  dy = dy*cosr - dx*sinr;
-  dx = dz;
-
-  /*     check axis increments - bail out if either 0 */
-  if ((xinc==0.0) || (yinc==0.0)) {*xpix=0.0; *ypix=0.0;
-    return(*status = 502);}
-
-  /*     convert to pixels  */
-  *xpix = dx / xinc + xrefpix;
-  *ypix = dy / yinc + yrefpix;
-
-  if (*cptr == 'C') { /* linear -CAR */
-      if (*(cptr + 1) != 'A' ||  *(cptr + 2) != 'R') {
-         return(*status = 504);
-      }
-
-      return(*status);  /* done if linear */
-  }
-
-  /* Non linear position */
-  ra0 = xref * D2R;
-  dec0 = yref * D2R;
-  ra = xpos * D2R;
-  dec = ypos * D2R;
-
-  /* compute direction cosine */
-  coss = cos (dec);
-  sins = sin (dec);
-  cos0 = cos (dec0);
-  sin0 = sin (dec0);
-  l = sin(ra-ra0) * coss;
-  sint = sins * sin0 + coss * cos0 * cos(ra-ra0);
-
-    /* process by case  */
-    if (*cptr == 'T') {  /* -TAN tan */
-         if (*(cptr + 1) != 'A' ||  *(cptr + 2) != 'N') {
-           return(*status = 504);
-         }
-
-         if (sint<=0.0)
-	   return(*status = 501);
-         if( cos0<0.001 ) {
-            /* Do a first order expansion around pole */
-            m = (coss * cos(ra-ra0)) / (sins * sin0);
-            m = (-m + cos0 * (1.0 + m*m)) / sin0;
-         } else {
-            m = ( sins/sint - sin0 ) / cos0;
-         }
-	 if( fabs(sin(ra0)) < 0.3 ) {
-	    l  = coss*sin(ra)/sint - cos0*sin(ra0) + m*sin(ra0)*sin0;
-	    l /= cos(ra0);
-	 } else {
-	    l  = coss*cos(ra)/sint - cos0*cos(ra0) + m*cos(ra0)*sin0;
-	    l /= -sin(ra0);
-	 }
-
-    } else if (*cptr == 'S') {
-
-      if (*(cptr + 1) == 'I' &&  *(cptr + 2) == 'N') { /* -SIN */
-         if (sint<0.0)
-	   return(*status = 501);
-         m = sins * cos(dec0) - coss * sin(dec0) * cos(ra-ra0);
-
-      } else if (*(cptr + 1) == 'T' &&  *(cptr + 2) == 'G') {  /* -STG Sterographic*/
-         da = ra - ra0;
-         if (fabs(dec)>TWOPI/4.0)
-	   return(*status = 501);
-         dd = 1.0 + sins * sin(dec0) + coss * cos(dec0) * cos(da);
-         if (fabs(dd)1.0) m = 1.0;
-         m = acos (m);
-         if (m!=0) 
-            m = m / sin(m);
-         else
-            m = 1.0;
-         l = l * m;
-         m = (sins * cos(dec0) - coss * sin(dec0) * cos(ra-ra0)) * m;
-
-      } else if (*(cptr + 1) == 'I' &&  *(cptr + 2) == 'T') {  /* -AIT Aitoff */
-         da = (ra - ra0) / 2.0;
-         if (fabs(da)>TWOPI/4.0)
-	     return(*status = 501);
-         dt = yinc*cosr + xinc*sinr;
-         if (dt==0.0) dt = 1.0;
-         dt = dt * D2R;
-         dy = yref * D2R;
-         dx = sin(dy+dt)/sqrt((1.0+cos(dy+dt))/2.0) -
-             sin(dy)/sqrt((1.0+cos(dy))/2.0);
-         if (dx==0.0) dx = 1.0;
-         geo2 = dt / dx;
-         dt = xinc*cosr - yinc* sinr;
-         if (dt==0.0) dt = 1.0;
-         dt = dt * D2R;
-         dx = 2.0 * cos(dy) * sin(dt/2.0);
-         if (dx==0.0) dx = 1.0;
-         geo1 = dt * sqrt((1.0+cos(dy)*cos(dt/2.0))/2.0) / dx;
-         geo3 = geo2 * sin(dy) / sqrt((1.0+cos(dy))/2.0);
-         dt = sqrt ((1.0 + cos(dec) * cos(da))/2.0);
-         if (fabs(dt)TWOPI/4.0)
-	   return(*status = 501);
-         if (fabs(dec0)>TWOPI/4.0)
-	   return(*status = 501);
-         m = dec - dec0;
-         l = dt * coss;
-
-    } else if (*cptr == 'M') {  /* -MER mercator*/
-         if (*(cptr + 1) != 'E' ||  *(cptr + 2) != 'R') {
-             return(*status = 504);
-         }
-
-         dt = yinc * cosr + xinc * sinr;
-         if (dt==0.0) dt = 1.0;
-         dy = (yref/2.0 + 45.0) * D2R;
-         dx = dy + dt / 2.0 * D2R;
-         dy = log (tan (dy));
-         dx = log (tan (dx));
-         geo2 = dt * D2R / (dx - dy);
-         geo3 = geo2 * dy;
-         geo1 = cos (yref*D2R);
-         if (geo1<=0.0) geo1 = 1.0;
-         dt = ra - ra0;
-         l = geo1 * dt;
-         dt = dec / 2.0 + TWOPI / 8.0;
-         dt = tan (dt);
-         if (dt
-#include 
-#include 
-#include 
-
-#ifdef _ALPHA_
-#define e_magic_number IMAGE_FILE_MACHINE_ALPHA
-#else
-#define e_magic_number IMAGE_FILE_MACHINE_I386
-#endif
-
-/*
- *----------------------------------------------------------------------
- * GetArgcArgv --
- * 
- *	Break up a line into argc argv
- *----------------------------------------------------------------------
- */
-int
-GetArgcArgv(char *s, char **argv)
-{
-    int quote = 0;
-    int argc = 0;
-    char *bp;
-
-    bp = s;
-    while (1) {
-	while (isspace(*bp)) {
-	    bp++;
-	}
-	if (*bp == '\n' || *bp == '\0') {
-	    *bp = '\0';
-	    return argc;
-	}
-	if (*bp == '\"') {
-	    quote = 1;
-	    bp++;
-	}
-	argv[argc++] = bp;
-
-	while (*bp != '\0') {
-	    if (quote) {
-		if (*bp == '\"') {
-		    quote = 0;
-		    *bp = '\0';
-		    bp++;
-		    break;
-		}
-		bp++;
-		continue;
-	    }
-	    if (isspace(*bp)) {
-		*bp = '\0';
-		bp++;
-		break;
-	    }
-	    bp++;
-	}
-    }
-}
-
-/*
- *  The names of the first group of possible symbol table storage classes
- */
-char * SzStorageClass1[] = {
-    "NULL","AUTOMATIC","EXTERNAL","STATIC","REGISTER","EXTERNAL_DEF","LABEL",
-    "UNDEFINED_LABEL","MEMBER_OF_STRUCT","ARGUMENT","STRUCT_TAG",
-    "MEMBER_OF_UNION","UNION_TAG","TYPE_DEFINITION","UNDEFINED_STATIC",
-    "ENUM_TAG","MEMBER_OF_ENUM","REGISTER_PARAM","BIT_FIELD"
-};
-
-/*
- * The names of the second group of possible symbol table storage classes
- */
-char * SzStorageClass2[] = {
-    "BLOCK","FUNCTION","END_OF_STRUCT","FILE","SECTION","WEAK_EXTERNAL"
-};
-
-/*
- *----------------------------------------------------------------------
- * GetSZStorageClass --
- *
- *	Given a symbol storage class value, return a descriptive
- *	ASCII string
- *----------------------------------------------------------------------
- */
-PSTR
-GetSZStorageClass(BYTE storageClass)
-{
-	if ( storageClass <= IMAGE_SYM_CLASS_BIT_FIELD )
-		return SzStorageClass1[storageClass];
-	else if ( (storageClass >= IMAGE_SYM_CLASS_BLOCK)
-		      && (storageClass <= IMAGE_SYM_CLASS_WEAK_EXTERNAL) )
-		return SzStorageClass2[storageClass-IMAGE_SYM_CLASS_BLOCK];
-	else
-		return "???";
-}
-
-/*
- *----------------------------------------------------------------------
- * GetSectionName --
- *
- *	Used by DumpSymbolTable, it gives meaningful names to
- *	the non-normal section number.
- *
- * Results:
- *	A name is returned in buffer
- *----------------------------------------------------------------------
- */
-void
-GetSectionName(WORD section, PSTR buffer, unsigned cbBuffer)
-{
-    char tempbuffer[10];
-	
-    switch ( (SHORT)section )
-    {
-      case IMAGE_SYM_UNDEFINED: strcpy(tempbuffer, "UNDEF"); break;
-      case IMAGE_SYM_ABSOLUTE:  strcpy(tempbuffer, "ABS  "); break;
-      case IMAGE_SYM_DEBUG:	  strcpy(tempbuffer, "DEBUG"); break;
-      default: wsprintf(tempbuffer, "%-5X", section);
-    }
-	
-    strncpy(buffer, tempbuffer, cbBuffer-1);
-}
-
-/*
- *----------------------------------------------------------------------
- * DumpSymbolTable --
- *
- *	Dumps a COFF symbol table from an EXE or OBJ.  We only use
- *	it to dump tables from OBJs.
- *----------------------------------------------------------------------
- */
-void
-DumpSymbolTable(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols)
-{
-    unsigned i;
-    PSTR stringTable;
-    char sectionName[10];
-	
-    fprintf(fout, "Symbol Table - %X entries  (* = auxillary symbol)\n",
-	    cSymbols);
-
-    fprintf(fout, 
-     "Indx Name                 Value    Section    cAux  Type    Storage\n"
-     "---- -------------------- -------- ---------- ----- ------- --------\n");
-
-    /*
-     * The string table apparently starts right after the symbol table
-     */
-    stringTable = (PSTR)&pSymbolTable[cSymbols]; 
-		
-    for ( i=0; i < cSymbols; i++ ) {
-	fprintf(fout, "%04X ", i);
-	if ( pSymbolTable->N.Name.Short != 0 )
-	    fprintf(fout, "%-20.8s", pSymbolTable->N.ShortName);
-	else
-	    fprintf(fout, "%-20s", stringTable + pSymbolTable->N.Name.Long);
-
-	fprintf(fout, " %08X", pSymbolTable->Value);
-
-	GetSectionName(pSymbolTable->SectionNumber, sectionName,
-		       sizeof(sectionName));
-	fprintf(fout, " sect:%s aux:%X type:%02X st:%s\n",
-	       sectionName,
-	       pSymbolTable->NumberOfAuxSymbols,
-	       pSymbolTable->Type,
-	       GetSZStorageClass(pSymbolTable->StorageClass) );
-#if 0
-	if ( pSymbolTable->NumberOfAuxSymbols )
-	    DumpAuxSymbols(pSymbolTable);
-#endif
-
-	/*
-	 * Take into account any aux symbols
-	 */
-	i += pSymbolTable->NumberOfAuxSymbols;
-	pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
-	pSymbolTable++;
-    }
-}
-
-/*
- *----------------------------------------------------------------------
- * DumpExternals --
- *
- *	Dumps a COFF symbol table from an EXE or OBJ.  We only use
- *	it to dump tables from OBJs.
- *----------------------------------------------------------------------
- */
-void
-DumpExternals(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols)
-{
-    unsigned i;
-    PSTR stringTable;
-    char *s, *f;
-    char symbol[1024];
-	
-    /*
-     * The string table apparently starts right after the symbol table
-     */
-    stringTable = (PSTR)&pSymbolTable[cSymbols]; 
-		
-    for ( i=0; i < cSymbols; i++ ) {
-	if (pSymbolTable->SectionNumber > 0 && pSymbolTable->Type == 0x20) {
-	    if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
-		if (pSymbolTable->N.Name.Short != 0) {
-		    strncpy(symbol, pSymbolTable->N.ShortName, 8);
-		    symbol[8] = 0;
-		} else {
-		    s = stringTable + pSymbolTable->N.Name.Long;
-		    strcpy(symbol, s);
-		}
-		s = symbol;
-		f = strchr(s, '@');
-		if (f) {
-		    *f = 0;
-		}
-#if defined(_MSC_VER) && defined(_X86_)
-		if (symbol[0] == '_') {
-		    s = &symbol[1];
-		}
-#endif
-		if ((stricmp(s, "DllEntryPoint") != 0) 
-			&& (stricmp(s, "DllMain") != 0)) {
-		    fprintf(fout, "\t%s\n", s);
-		}
-	    }
-	}
-
-	/*
-	 * Take into account any aux symbols
-	 */
-	i += pSymbolTable->NumberOfAuxSymbols;
-	pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
-	pSymbolTable++;
-    }
-}
-
-/*
- *----------------------------------------------------------------------
- * DumpObjFile --
- *
- *	Dump an object file--either a full listing or just the exported
- *	symbols.
- *----------------------------------------------------------------------
- */
-void
-DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout, int full)
-{
-    PIMAGE_SYMBOL PCOFFSymbolTable;
-    DWORD COFFSymbolCount;
-    
-    PCOFFSymbolTable = (PIMAGE_SYMBOL)
-	((DWORD)pImageFileHeader + pImageFileHeader->PointerToSymbolTable);
-    COFFSymbolCount = pImageFileHeader->NumberOfSymbols;
-
-    if (full) {
-	DumpSymbolTable(PCOFFSymbolTable, fout, COFFSymbolCount);
-    } else {
-	DumpExternals(PCOFFSymbolTable, fout, COFFSymbolCount);
-    }
-}
-
-/*
- *----------------------------------------------------------------------
- * SkipToNextRecord --
- *
- *	Skip over the current ROMF record and return the type of the
- *	next record.
- *----------------------------------------------------------------------
- */
-
-BYTE
-SkipToNextRecord(BYTE **ppBuffer)
-{
-    int length;
-    (*ppBuffer)++;		/* Skip over the type.*/
-    length = *((WORD*)(*ppBuffer))++; /* Retrieve the length. */
-    *ppBuffer += length;	/* Skip over the rest. */
-    return **ppBuffer;		/* Return the type. */
-}
-
-/*
- *----------------------------------------------------------------------
- * DumpROMFObjFile --
- *
- *	Dump a Relocatable Object Module Format file, displaying only
- *	the exported symbols.
- *----------------------------------------------------------------------
- */
-void
-DumpROMFObjFile(LPVOID pBuffer, FILE *fout)
-{
-    BYTE type, length;
-    char symbol[1024], *s;
-
-    while (1) {
-	type = SkipToNextRecord(&(BYTE*)pBuffer);
-	if (type == 0x90) {	/* PUBDEF */
-	    if (((BYTE*)pBuffer)[4] != 0) {
-		length = ((BYTE*)pBuffer)[5];
-		strncpy(symbol, ((char*)pBuffer) + 6, length);
-		symbol[length] = '\0';
-		s = symbol;
-		if ((stricmp(s, "DllEntryPoint") != 0) 
-			&& (stricmp(s, "DllMain") != 0)) {
-		    if (s[0] == '_') {
-			s++;
-			fprintf(fout, "\t_%s\n\t%s=_%s\n", s, s, s);
-		    } else {
-			fprintf(fout, "\t%s\n", s);
-		    }
-		}
-	    }
-	} else if (type == 0x8B || type == 0x8A) { /* MODEND */
-	    break;
-	}
-    }
-}
-
-/*
- *----------------------------------------------------------------------
- * DumpFile --
- *
- *	Open up a file, memory map it, and call the appropriate
- *	dumping routine
- *----------------------------------------------------------------------
- */
-void
-DumpFile(LPSTR filename, FILE *fout, int full)
-{
-    HANDLE hFile;
-    HANDLE hFileMapping;
-    LPVOID lpFileBase;
-    PIMAGE_DOS_HEADER dosHeader;
-	
-    hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
-		       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
-					
-    if (hFile == INVALID_HANDLE_VALUE) {
-	fprintf(stderr, "Couldn't open file with CreateFile()\n");
-	return;
-    }
-
-    hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
-    if (hFileMapping == 0) {
-	CloseHandle(hFile);
-	fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n");
-	return;
-    }
-
-    lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
-    if (lpFileBase == 0) {
-	CloseHandle(hFileMapping);
-	CloseHandle(hFile);
-	fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n");
-	return;
-    }
-
-    dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
-    if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
-#if 0
-	DumpExeFile( dosHeader );
-#else
-	fprintf(stderr, "File is an executable.  I don't dump those.\n");
-	return;
-#endif
-    }
-    /* Does it look like a i386 COFF OBJ file??? */
-    else if ((dosHeader->e_magic == e_magic_number)
-	    && (dosHeader->e_sp == 0)) {
-	/*
-	 * The two tests above aren't what they look like.  They're
-	 * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C)
-	 * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
-	 */
-	DumpObjFile((PIMAGE_FILE_HEADER) lpFileBase, fout, full);
-    } else if (*((BYTE *)lpFileBase) == 0x80) {
-	/*
-	 * This file looks like it might be a ROMF file.
-	 */
-	DumpROMFObjFile(lpFileBase, fout);
-    } else {
-	printf("unrecognized file format\n");
-    }
-    UnmapViewOfFile(lpFileBase);
-    CloseHandle(hFileMapping);
-    CloseHandle(hFile);
-}
-
-void
-main(int argc, char **argv)
-{
-    char *fargv[1000];
-    char cmdline[10000];
-    int i, arg;
-    FILE *fout;
-    int pos;
-    int full = 0;
-    char *outfile = NULL;
-
-    if (argc < 3) {
-      Usage:
-	fprintf(stderr, "Usage: %s ?-o outfile? ?-f(ull)?   ..\n", argv[0]);
-	exit(1);
-    }
-
-    arg = 1;
-    while (argv[arg][0] == '-') {
-	if (strcmp(argv[arg], "--") == 0) {
-	    arg++;
-	    break;
-	} else if (strcmp(argv[arg], "-f") == 0) {
-	    full = 1;
-	} else if (strcmp(argv[arg], "-o") == 0) {
-	    arg++;
-	    if (arg == argc) {
-		goto Usage;
-	    }
-	    outfile = argv[arg];
-	}
-	arg++;
-    }
-    if (arg == argc) {
-	goto Usage;
-    }
-
-    if (outfile) {
-	fout = fopen(outfile, "w+");
-	if (fout == NULL) {
-	    fprintf(stderr, "Unable to open \'%s\' for writing:\n",
-		    argv[arg]);
-	    perror("");
-	    exit(1);
-	}
-    } else {
-	fout = stdout;
-    }
-    
-    if (! full) {
-	char *dllname = argv[arg];
-	arg++;
-	if (arg == argc) {
-	    goto Usage;
-	}
-	fprintf(fout, "LIBRARY    %s\n", dllname);
-	fprintf(fout, "EXETYPE WINDOWS\n");
-	fprintf(fout, "CODE PRELOAD MOVEABLE DISCARDABLE\n");
-	fprintf(fout, "DATA PRELOAD MOVEABLE MULTIPLE\n\n");
-	fprintf(fout, "EXPORTS\n");
-    }
-
-    for (; arg < argc; arg++) {
-	if (argv[arg][0] == '@') {
-	    FILE *fargs = fopen(&argv[arg][1], "r");
-	    if (fargs == NULL) {
-		fprintf(stderr, "Unable to open \'%s\' for reading:\n",
-			argv[arg]);
-		perror("");
-		exit(1);
-	    }
-	    pos = 0;
-	    for (i = 0; i < arg; i++) {
-		strcpy(&cmdline[pos], argv[i]);
-		pos += strlen(&cmdline[pos]) + 1;
-		fargv[i] = argv[i];
-	    }
-	    fgets(&cmdline[pos], sizeof(cmdline), fargs);
-	    fprintf(stderr, "%s\n", &cmdline[pos]);
-	    fclose(fargs);
-	    i += GetArgcArgv(&cmdline[pos], &fargv[i]);
-	    argc = i;
-	    argv = fargv;
-	}
-	DumpFile(argv[arg], fout, full);
-    }
-    exit(0);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/adler32.c b/src/external/OpenGR/3rdparty/cfitsio/zlib/adler32.c
deleted file mode 100644
index 172de6032..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/adler32.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995-2007 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include "zutil.h"
-
-#define local static
-
-local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
-
-#define BASE 65521UL    /* largest prime smaller than 65536 */
-#define NMAX 5552
-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-
-#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
-#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
-#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
-#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
-#define DO16(buf)   DO8(buf,0); DO8(buf,8);
-
-/* use NO_DIVIDE if your processor does not do division in hardware */
-#ifdef NO_DIVIDE
-#  define MOD(a) \
-    do { \
-        if (a >= (BASE << 16)) a -= (BASE << 16); \
-        if (a >= (BASE << 15)) a -= (BASE << 15); \
-        if (a >= (BASE << 14)) a -= (BASE << 14); \
-        if (a >= (BASE << 13)) a -= (BASE << 13); \
-        if (a >= (BASE << 12)) a -= (BASE << 12); \
-        if (a >= (BASE << 11)) a -= (BASE << 11); \
-        if (a >= (BASE << 10)) a -= (BASE << 10); \
-        if (a >= (BASE << 9)) a -= (BASE << 9); \
-        if (a >= (BASE << 8)) a -= (BASE << 8); \
-        if (a >= (BASE << 7)) a -= (BASE << 7); \
-        if (a >= (BASE << 6)) a -= (BASE << 6); \
-        if (a >= (BASE << 5)) a -= (BASE << 5); \
-        if (a >= (BASE << 4)) a -= (BASE << 4); \
-        if (a >= (BASE << 3)) a -= (BASE << 3); \
-        if (a >= (BASE << 2)) a -= (BASE << 2); \
-        if (a >= (BASE << 1)) a -= (BASE << 1); \
-        if (a >= BASE) a -= BASE; \
-    } while (0)
-#  define MOD4(a) \
-    do { \
-        if (a >= (BASE << 4)) a -= (BASE << 4); \
-        if (a >= (BASE << 3)) a -= (BASE << 3); \
-        if (a >= (BASE << 2)) a -= (BASE << 2); \
-        if (a >= (BASE << 1)) a -= (BASE << 1); \
-        if (a >= BASE) a -= BASE; \
-    } while (0)
-#else
-#  define MOD(a) a %= BASE
-#  define MOD4(a) a %= BASE
-#endif
-
-/* ========================================================================= */
-uLong ZEXPORT adler32(adler, buf, len)
-    uLong adler;
-    const Bytef *buf;
-    uInt len;
-{
-    unsigned long sum2;
-    unsigned n;
-
-    /* split Adler-32 into component sums */
-    sum2 = (adler >> 16) & 0xffff;
-    adler &= 0xffff;
-
-    /* in case user likes doing a byte at a time, keep it fast */
-    if (len == 1) {
-        adler += buf[0];
-        if (adler >= BASE)
-            adler -= BASE;
-        sum2 += adler;
-        if (sum2 >= BASE)
-            sum2 -= BASE;
-        return adler | (sum2 << 16);
-    }
-
-    /* initial Adler-32 value (deferred check for len == 1 speed) */
-    if (buf == Z_NULL)
-        return 1L;
-
-    /* in case short lengths are provided, keep it somewhat fast */
-    if (len < 16) {
-        while (len--) {
-            adler += *buf++;
-            sum2 += adler;
-        }
-        if (adler >= BASE)
-            adler -= BASE;
-        MOD4(sum2);             /* only added so many BASE's */
-        return adler | (sum2 << 16);
-    }
-
-    /* do length NMAX blocks -- requires just one modulo operation */
-    while (len >= NMAX) {
-        len -= NMAX;
-        n = NMAX / 16;          /* NMAX is divisible by 16 */
-        do {
-            DO16(buf);          /* 16 sums unrolled */
-            buf += 16;
-        } while (--n);
-        MOD(adler);
-        MOD(sum2);
-    }
-
-    /* do remaining bytes (less than NMAX, still just one modulo) */
-    if (len) {                  /* avoid modulos if none remaining */
-        while (len >= 16) {
-            len -= 16;
-            DO16(buf);
-            buf += 16;
-        }
-        while (len--) {
-            adler += *buf++;
-            sum2 += adler;
-        }
-        MOD(adler);
-        MOD(sum2);
-    }
-
-    /* return recombined sums */
-    return adler | (sum2 << 16);
-}
-
-/* ========================================================================= */
-local uLong adler32_combine_(adler1, adler2, len2)
-    uLong adler1;
-    uLong adler2;
-    z_off64_t len2;
-{
-    unsigned long sum1;
-    unsigned long sum2;
-    unsigned rem;
-
-    /* the derivation of this formula is left as an exercise for the reader */
-    rem = (unsigned)(len2 % BASE);
-    sum1 = adler1 & 0xffff;
-    sum2 = rem * sum1;
-    MOD(sum2);
-    sum1 += (adler2 & 0xffff) + BASE - 1;
-    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
-    if (sum1 >= BASE) sum1 -= BASE;
-    if (sum1 >= BASE) sum1 -= BASE;
-    if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
-    if (sum2 >= BASE) sum2 -= BASE;
-    return sum1 | (sum2 << 16);
-}
-
-/* ========================================================================= */
-uLong ZEXPORT adler32_combine(adler1, adler2, len2)
-    uLong adler1;
-    uLong adler2;
-    z_off_t len2;
-{
-    return adler32_combine_(adler1, adler2, len2);
-}
-
-uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
-    uLong adler1;
-    uLong adler2;
-    z_off64_t len2;
-{
-    return adler32_combine_(adler1, adler2, len2);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/crc32.c b/src/external/OpenGR/3rdparty/cfitsio/zlib/crc32.c
deleted file mode 100644
index 08843ff73..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/crc32.c
+++ /dev/null
@@ -1,440 +0,0 @@
-/* crc32.c -- compute the CRC-32 of a data stream
- * Copyright (C) 1995-2006, 2010 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- *
- * Thanks to Rodney Brown  for his contribution of faster
- * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
- * tables for updating the shift register in one step with three exclusive-ors
- * instead of four steps with four exclusive-ors.  This results in about a
- * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
- */
-
-/*
-  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
-  protection on the static variables used to control the first-use generation
-  of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
-  first call get_crc_table() to initialize the tables before allowing more than
-  one thread to use crc32().
- */
-
-#ifdef MAKECRCH
-#  include 
-#  ifndef DYNAMIC_CRC_TABLE
-#    define DYNAMIC_CRC_TABLE
-#  endif /* !DYNAMIC_CRC_TABLE */
-#endif /* MAKECRCH */
-
-#include "zutil.h"      /* for STDC and FAR definitions */
-
-#define local static
-
-/* Find a four-byte integer type for crc32_little() and crc32_big(). */
-#ifndef NOBYFOUR
-#  ifdef STDC           /* need ANSI C limits.h to determine sizes */
-#    include 
-#    define BYFOUR
-#    if (UINT_MAX == 0xffffffffUL)
-       typedef unsigned int u4;
-#    else
-#      if (ULONG_MAX == 0xffffffffUL)
-         typedef unsigned long u4;
-#      else
-#        if (USHRT_MAX == 0xffffffffUL)
-           typedef unsigned short u4;
-#        else
-#          undef BYFOUR     /* can't find a four-byte integer type! */
-#        endif
-#      endif
-#    endif
-#  endif /* STDC */
-#endif /* !NOBYFOUR */
-
-/* Definitions for doing the crc four data bytes at a time. */
-#ifdef BYFOUR
-#  define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \
-                (((w)&0xff00)<<8)+(((w)&0xff)<<24))
-   local unsigned long crc32_little OF((unsigned long,
-                        const unsigned char FAR *, unsigned));
-   local unsigned long crc32_big OF((unsigned long,
-                        const unsigned char FAR *, unsigned));
-#  define TBLS 8
-#else
-#  define TBLS 1
-#endif /* BYFOUR */
-
-/* Local functions for crc concatenation */
-local unsigned long gf2_matrix_times OF((unsigned long *mat,
-                                         unsigned long vec));
-local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
-local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2);
-
-
-#ifdef DYNAMIC_CRC_TABLE
-
-local volatile int crc_table_empty = 1;
-local unsigned long FAR crc_table[TBLS][256];
-local void make_crc_table OF((void));
-#ifdef MAKECRCH
-   local void write_table OF((FILE *, const unsigned long FAR *));
-#endif /* MAKECRCH */
-/*
-  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
-  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
-
-  Polynomials over GF(2) are represented in binary, one bit per coefficient,
-  with the lowest powers in the most significant bit.  Then adding polynomials
-  is just exclusive-or, and multiplying a polynomial by x is a right shift by
-  one.  If we call the above polynomial p, and represent a byte as the
-  polynomial q, also with the lowest power in the most significant bit (so the
-  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
-  where a mod b means the remainder after dividing a by b.
-
-  This calculation is done using the shift-register method of multiplying and
-  taking the remainder.  The register is initialized to zero, and for each
-  incoming bit, x^32 is added mod p to the register if the bit is a one (where
-  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
-  x (which is shifting right by one and adding x^32 mod p if the bit shifted
-  out is a one).  We start with the highest power (least significant bit) of
-  q and repeat for all eight bits of q.
-
-  The first table is simply the CRC of all possible eight bit values.  This is
-  all the information needed to generate CRCs on data a byte at a time for all
-  combinations of CRC register values and incoming bytes.  The remaining tables
-  allow for word-at-a-time CRC calculation for both big-endian and little-
-  endian machines, where a word is four bytes.
-*/
-local void make_crc_table()
-{
-    unsigned long c;
-    int n, k;
-    unsigned long poly;                 /* polynomial exclusive-or pattern */
-    /* terms of polynomial defining this crc (except x^32): */
-    static volatile int first = 1;      /* flag to limit concurrent making */
-    static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
-
-    /* See if another task is already doing this (not thread-safe, but better
-       than nothing -- significantly reduces duration of vulnerability in
-       case the advice about DYNAMIC_CRC_TABLE is ignored) */
-    if (first) {
-        first = 0;
-
-        /* make exclusive-or pattern from polynomial (0xedb88320UL) */
-        poly = 0UL;
-        for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
-            poly |= 1UL << (31 - p[n]);
-
-        /* generate a crc for every 8-bit value */
-        for (n = 0; n < 256; n++) {
-            c = (unsigned long)n;
-            for (k = 0; k < 8; k++)
-                c = c & 1 ? poly ^ (c >> 1) : c >> 1;
-            crc_table[0][n] = c;
-        }
-
-#ifdef BYFOUR
-        /* generate crc for each value followed by one, two, and three zeros,
-           and then the byte reversal of those as well as the first table */
-        for (n = 0; n < 256; n++) {
-            c = crc_table[0][n];
-            crc_table[4][n] = REV(c);
-            for (k = 1; k < 4; k++) {
-                c = crc_table[0][c & 0xff] ^ (c >> 8);
-                crc_table[k][n] = c;
-                crc_table[k + 4][n] = REV(c);
-            }
-        }
-#endif /* BYFOUR */
-
-        crc_table_empty = 0;
-    }
-    else {      /* not first */
-        /* wait for the other guy to finish (not efficient, but rare) */
-        while (crc_table_empty)
-            ;
-    }
-
-#ifdef MAKECRCH
-    /* write out CRC tables to crc32.h */
-    {
-        FILE *out;
-
-        out = fopen("crc32.h", "w");
-        if (out == NULL) return;
-        fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
-        fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
-        fprintf(out, "local const unsigned long FAR ");
-        fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
-        write_table(out, crc_table[0]);
-#  ifdef BYFOUR
-        fprintf(out, "#ifdef BYFOUR\n");
-        for (k = 1; k < 8; k++) {
-            fprintf(out, "  },\n  {\n");
-            write_table(out, crc_table[k]);
-        }
-        fprintf(out, "#endif\n");
-#  endif /* BYFOUR */
-        fprintf(out, "  }\n};\n");
-        fclose(out);
-    }
-#endif /* MAKECRCH */
-}
-
-#ifdef MAKECRCH
-local void write_table(out, table)
-    FILE *out;
-    const unsigned long FAR *table;
-{
-    int n;
-
-    for (n = 0; n < 256; n++)
-        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ", table[n],
-                n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
-}
-#endif /* MAKECRCH */
-
-#else /* !DYNAMIC_CRC_TABLE */
-/* ========================================================================
- * Tables of CRC-32s of all single-byte values, made by make_crc_table().
- */
-#include "crc32.h"
-#endif /* DYNAMIC_CRC_TABLE */
-
-/* =========================================================================
- * This function can be used by asm versions of crc32()
- */
-const unsigned long FAR * ZEXPORT get_crc_table()
-{
-#ifdef DYNAMIC_CRC_TABLE
-    if (crc_table_empty)
-        make_crc_table();
-#endif /* DYNAMIC_CRC_TABLE */
-    return (const unsigned long FAR *)crc_table;
-}
-
-/* ========================================================================= */
-#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
-#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
-
-/* ========================================================================= */
-unsigned long ZEXPORT crc32(crc, buf, len)
-    unsigned long crc;
-    const unsigned char FAR *buf;
-    uInt len;
-{
-    if (buf == Z_NULL) return 0UL;
-
-#ifdef DYNAMIC_CRC_TABLE
-    if (crc_table_empty)
-        make_crc_table();
-#endif /* DYNAMIC_CRC_TABLE */
-
-#ifdef BYFOUR
-    if (sizeof(void *) == sizeof(ptrdiff_t)) {
-        u4 endian;
-
-        endian = 1;
-        if (*((unsigned char *)(&endian)))
-            return crc32_little(crc, buf, len);
-        else
-            return crc32_big(crc, buf, len);
-    }
-#endif /* BYFOUR */
-    crc = crc ^ 0xffffffffUL;
-    while (len >= 8) {
-        DO8;
-        len -= 8;
-    }
-    if (len) do {
-        DO1;
-    } while (--len);
-    return crc ^ 0xffffffffUL;
-}
-
-#ifdef BYFOUR
-
-/* ========================================================================= */
-#define DOLIT4 c ^= *buf4++; \
-        c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
-            crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
-#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
-
-/* ========================================================================= */
-local unsigned long crc32_little(crc, buf, len)
-    unsigned long crc;
-    const unsigned char FAR *buf;
-    unsigned len;
-{
-    register u4 c;
-    register const u4 FAR *buf4;
-
-    c = (u4)crc;
-    c = ~c;
-    while (len && ((ptrdiff_t)buf & 3)) {
-        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
-        len--;
-    }
-
-    buf4 = (const u4 FAR *)(const void FAR *)buf;
-    while (len >= 32) {
-        DOLIT32;
-        len -= 32;
-    }
-    while (len >= 4) {
-        DOLIT4;
-        len -= 4;
-    }
-    buf = (const unsigned char FAR *)buf4;
-
-    if (len) do {
-        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
-    } while (--len);
-    c = ~c;
-    return (unsigned long)c;
-}
-
-/* ========================================================================= */
-#define DOBIG4 c ^= *++buf4; \
-        c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
-            crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
-#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
-
-/* ========================================================================= */
-local unsigned long crc32_big(crc, buf, len)
-    unsigned long crc;
-    const unsigned char FAR *buf;
-    unsigned len;
-{
-    register u4 c;
-    register const u4 FAR *buf4;
-
-    c = REV((u4)crc);
-    c = ~c;
-    while (len && ((ptrdiff_t)buf & 3)) {
-        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
-        len--;
-    }
-
-    buf4 = (const u4 FAR *)(const void FAR *)buf;
-    buf4--;
-    while (len >= 32) {
-        DOBIG32;
-        len -= 32;
-    }
-    while (len >= 4) {
-        DOBIG4;
-        len -= 4;
-    }
-    buf4++;
-    buf = (const unsigned char FAR *)buf4;
-
-    if (len) do {
-        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
-    } while (--len);
-    c = ~c;
-    return (unsigned long)(REV(c));
-}
-
-#endif /* BYFOUR */
-
-#define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */
-
-/* ========================================================================= */
-local unsigned long gf2_matrix_times(mat, vec)
-    unsigned long *mat;
-    unsigned long vec;
-{
-    unsigned long sum;
-
-    sum = 0;
-    while (vec) {
-        if (vec & 1)
-            sum ^= *mat;
-        vec >>= 1;
-        mat++;
-    }
-    return sum;
-}
-
-/* ========================================================================= */
-local void gf2_matrix_square(square, mat)
-    unsigned long *square;
-    unsigned long *mat;
-{
-    int n;
-
-    for (n = 0; n < GF2_DIM; n++)
-        square[n] = gf2_matrix_times(mat, mat[n]);
-}
-
-/* ========================================================================= */
-local uLong crc32_combine_(crc1, crc2, len2)
-    uLong crc1;
-    uLong crc2;
-    z_off64_t len2;
-{
-    int n;
-    unsigned long row;
-    unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
-    unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
-
-    /* degenerate case (also disallow negative lengths) */
-    if (len2 <= 0)
-        return crc1;
-
-    /* put operator for one zero bit in odd */
-    odd[0] = 0xedb88320UL;          /* CRC-32 polynomial */
-    row = 1;
-    for (n = 1; n < GF2_DIM; n++) {
-        odd[n] = row;
-        row <<= 1;
-    }
-
-    /* put operator for two zero bits in even */
-    gf2_matrix_square(even, odd);
-
-    /* put operator for four zero bits in odd */
-    gf2_matrix_square(odd, even);
-
-    /* apply len2 zeros to crc1 (first square will put the operator for one
-       zero byte, eight zero bits, in even) */
-    do {
-        /* apply zeros operator for this bit of len2 */
-        gf2_matrix_square(even, odd);
-        if (len2 & 1)
-            crc1 = gf2_matrix_times(even, crc1);
-        len2 >>= 1;
-
-        /* if no more bits set, then done */
-        if (len2 == 0)
-            break;
-
-        /* another iteration of the loop with odd and even swapped */
-        gf2_matrix_square(odd, even);
-        if (len2 & 1)
-            crc1 = gf2_matrix_times(odd, crc1);
-        len2 >>= 1;
-
-        /* if no more bits set, then done */
-    } while (len2 != 0);
-
-    /* return combined crc */
-    crc1 ^= crc2;
-    return crc1;
-}
-
-/* ========================================================================= */
-uLong ZEXPORT crc32_combine(crc1, crc2, len2)
-    uLong crc1;
-    uLong crc2;
-    z_off_t len2;
-{
-    return crc32_combine_(crc1, crc2, len2);
-}
-
-uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
-    uLong crc1;
-    uLong crc2;
-    z_off64_t len2;
-{
-    return crc32_combine_(crc1, crc2, len2);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/crc32.h b/src/external/OpenGR/3rdparty/cfitsio/zlib/crc32.h
deleted file mode 100644
index 8053b6117..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/crc32.h
+++ /dev/null
@@ -1,441 +0,0 @@
-/* crc32.h -- tables for rapid CRC calculation
- * Generated automatically by crc32.c
- */
-
-local const unsigned long FAR crc_table[TBLS][256] =
-{
-  {
-    0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
-    0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
-    0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
-    0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
-    0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
-    0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
-    0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
-    0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
-    0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
-    0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
-    0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
-    0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
-    0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
-    0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
-    0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
-    0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
-    0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
-    0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
-    0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
-    0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
-    0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
-    0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
-    0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
-    0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
-    0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
-    0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
-    0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
-    0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
-    0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
-    0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
-    0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
-    0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
-    0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
-    0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
-    0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
-    0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
-    0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
-    0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
-    0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
-    0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
-    0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
-    0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
-    0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
-    0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
-    0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
-    0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
-    0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
-    0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
-    0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
-    0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
-    0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
-    0x2d02ef8dUL
-#ifdef BYFOUR
-  },
-  {
-    0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
-    0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
-    0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
-    0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
-    0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
-    0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
-    0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
-    0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
-    0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
-    0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
-    0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
-    0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
-    0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
-    0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
-    0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
-    0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
-    0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
-    0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
-    0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
-    0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
-    0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
-    0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
-    0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
-    0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
-    0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
-    0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
-    0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
-    0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
-    0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
-    0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
-    0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
-    0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
-    0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
-    0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
-    0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
-    0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
-    0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
-    0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
-    0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
-    0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
-    0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
-    0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
-    0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
-    0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
-    0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
-    0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
-    0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
-    0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
-    0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
-    0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
-    0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
-    0x9324fd72UL
-  },
-  {
-    0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
-    0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
-    0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
-    0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
-    0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
-    0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
-    0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
-    0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
-    0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
-    0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
-    0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
-    0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
-    0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
-    0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
-    0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
-    0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
-    0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
-    0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
-    0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
-    0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
-    0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
-    0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
-    0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
-    0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
-    0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
-    0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
-    0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
-    0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
-    0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
-    0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
-    0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
-    0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
-    0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
-    0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
-    0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
-    0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
-    0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
-    0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
-    0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
-    0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
-    0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
-    0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
-    0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
-    0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
-    0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
-    0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
-    0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
-    0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
-    0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
-    0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
-    0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
-    0xbe9834edUL
-  },
-  {
-    0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
-    0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
-    0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
-    0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
-    0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
-    0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
-    0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
-    0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
-    0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
-    0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
-    0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
-    0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
-    0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
-    0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
-    0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
-    0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
-    0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
-    0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
-    0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
-    0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
-    0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
-    0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
-    0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
-    0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
-    0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
-    0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
-    0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
-    0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
-    0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
-    0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
-    0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
-    0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
-    0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
-    0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
-    0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
-    0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
-    0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
-    0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
-    0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
-    0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
-    0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
-    0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
-    0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
-    0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
-    0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
-    0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
-    0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
-    0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
-    0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
-    0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
-    0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
-    0xde0506f1UL
-  },
-  {
-    0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
-    0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
-    0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
-    0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
-    0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
-    0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
-    0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
-    0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
-    0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
-    0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
-    0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
-    0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
-    0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
-    0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
-    0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
-    0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
-    0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
-    0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
-    0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
-    0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
-    0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
-    0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
-    0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
-    0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
-    0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
-    0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
-    0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
-    0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
-    0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
-    0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
-    0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
-    0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
-    0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
-    0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
-    0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
-    0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
-    0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
-    0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
-    0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
-    0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
-    0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
-    0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
-    0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
-    0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
-    0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
-    0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
-    0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
-    0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
-    0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
-    0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
-    0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
-    0x8def022dUL
-  },
-  {
-    0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
-    0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
-    0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
-    0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
-    0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
-    0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
-    0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
-    0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
-    0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
-    0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
-    0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
-    0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
-    0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
-    0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
-    0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
-    0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
-    0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
-    0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
-    0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
-    0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
-    0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
-    0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
-    0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
-    0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
-    0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
-    0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
-    0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
-    0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
-    0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
-    0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
-    0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
-    0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
-    0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
-    0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
-    0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
-    0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
-    0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
-    0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
-    0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
-    0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
-    0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
-    0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
-    0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
-    0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
-    0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
-    0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
-    0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
-    0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
-    0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
-    0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
-    0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
-    0x72fd2493UL
-  },
-  {
-    0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
-    0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
-    0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
-    0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
-    0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
-    0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
-    0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
-    0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
-    0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
-    0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
-    0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
-    0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
-    0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
-    0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
-    0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
-    0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
-    0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
-    0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
-    0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
-    0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
-    0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
-    0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
-    0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
-    0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
-    0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
-    0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
-    0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
-    0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
-    0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
-    0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
-    0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
-    0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
-    0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
-    0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
-    0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
-    0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
-    0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
-    0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
-    0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
-    0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
-    0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
-    0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
-    0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
-    0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
-    0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
-    0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
-    0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
-    0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
-    0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
-    0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
-    0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
-    0xed3498beUL
-  },
-  {
-    0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
-    0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
-    0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
-    0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
-    0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
-    0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
-    0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
-    0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
-    0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
-    0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
-    0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
-    0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
-    0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
-    0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
-    0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
-    0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
-    0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
-    0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
-    0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
-    0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
-    0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
-    0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
-    0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
-    0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
-    0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
-    0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
-    0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
-    0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
-    0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
-    0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
-    0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
-    0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
-    0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
-    0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
-    0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
-    0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
-    0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
-    0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
-    0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
-    0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
-    0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
-    0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
-    0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
-    0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
-    0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
-    0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
-    0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
-    0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
-    0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
-    0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
-    0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
-    0xf10605deUL
-#endif
-  }
-};
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/deflate.c b/src/external/OpenGR/3rdparty/cfitsio/zlib/deflate.c
deleted file mode 100644
index 1c6a00c18..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/deflate.c
+++ /dev/null
@@ -1,1832 +0,0 @@
-/* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- *  ALGORITHM
- *
- *      The "deflation" process depends on being able to identify portions
- *      of the input text which are identical to earlier input (within a
- *      sliding window trailing behind the input currently being processed).
- *
- *      The most straightforward technique turns out to be the fastest for
- *      most input files: try all possible matches and select the longest.
- *      The key feature of this algorithm is that insertions into the string
- *      dictionary are very simple and thus fast, and deletions are avoided
- *      completely. Insertions are performed at each input character, whereas
- *      string matches are performed only when the previous match ends. So it
- *      is preferable to spend more time in matches to allow very fast string
- *      insertions and avoid deletions. The matching algorithm for small
- *      strings is inspired from that of Rabin & Karp. A brute force approach
- *      is used to find longer strings when a small match has been found.
- *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
- *      (by Leonid Broukhis).
- *         A previous version of this file used a more sophisticated algorithm
- *      (by Fiala and Greene) which is guaranteed to run in linear amortized
- *      time, but has a larger average cost, uses more memory and is patented.
- *      However the F&G algorithm may be faster for some highly redundant
- *      files if the parameter max_chain_length (described below) is too large.
- *
- *  ACKNOWLEDGEMENTS
- *
- *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
- *      I found it in 'freeze' written by Leonid Broukhis.
- *      Thanks to many people for bug reports and testing.
- *
- *  REFERENCES
- *
- *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
- *      Available in http://www.ietf.org/rfc/rfc1951.txt
- *
- *      A description of the Rabin and Karp algorithm is given in the book
- *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
- *
- *      Fiala,E.R., and Greene,D.H.
- *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
- *
- */
-
-#include "deflate.h"
-
-const char deflate_copyright[] =
-   " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler ";
-/*
-  If you use the zlib library in a product, an acknowledgment is welcome
-  in the documentation of your product. If for some reason you cannot
-  include such an acknowledgment, I would appreciate that you keep this
-  copyright string in the executable of your product.
- */
-
-/* ===========================================================================
- *  Function prototypes.
- */
-typedef enum {
-    need_more,      /* block not completed, need more input or more output */
-    block_done,     /* block flush performed */
-    finish_started, /* finish started, need only more output at next deflate */
-    finish_done     /* finish done, accept no more input or output */
-} block_state;
-
-typedef block_state (*compress_func) OF((deflate_state *s, int flush));
-/* Compression function. Returns the block state after the call. */
-
-local void fill_window    OF((deflate_state *s));
-local block_state deflate_stored OF((deflate_state *s, int flush));
-local block_state deflate_fast   OF((deflate_state *s, int flush));
-#ifndef FASTEST
-local block_state deflate_slow   OF((deflate_state *s, int flush));
-#endif
-local block_state deflate_rle    OF((deflate_state *s, int flush));
-local block_state deflate_huff   OF((deflate_state *s, int flush));
-local void lm_init        OF((deflate_state *s));
-local void putShortMSB    OF((deflate_state *s, uInt b));
-local void flush_pending  OF((z_streamp strm));
-local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
-#ifdef ASMV
-      void match_init OF((void)); /* asm code initialization */
-      uInt longest_match  OF((deflate_state *s, IPos cur_match));
-#else
-local uInt longest_match  OF((deflate_state *s, IPos cur_match));
-#endif
-
-#ifdef DEBUG
-local  void check_match OF((deflate_state *s, IPos start, IPos match,
-                            int length));
-#endif
-
-/* ===========================================================================
- * Local data
- */
-
-#define NIL 0
-/* Tail of hash chains */
-
-#ifndef TOO_FAR
-#  define TOO_FAR 4096
-#endif
-/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
-
-/* Values for max_lazy_match, good_match and max_chain_length, depending on
- * the desired pack level (0..9). The values given below have been tuned to
- * exclude worst case performance for pathological files. Better values may be
- * found for specific files.
- */
-typedef struct config_s {
-   ush good_length; /* reduce lazy search above this match length */
-   ush max_lazy;    /* do not perform lazy search above this match length */
-   ush nice_length; /* quit search above this match length */
-   ush max_chain;
-   compress_func func;
-} config;
-
-#ifdef FASTEST
-local const config configuration_table[2] = {
-/*      good lazy nice chain */
-/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
-/* 1 */ {4,    4,  8,    4, deflate_fast}}; /* max speed, no lazy matches */
-#else
-local const config configuration_table[10] = {
-/*      good lazy nice chain */
-/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
-/* 1 */ {4,    4,  8,    4, deflate_fast}, /* max speed, no lazy matches */
-/* 2 */ {4,    5, 16,    8, deflate_fast},
-/* 3 */ {4,    6, 32,   32, deflate_fast},
-
-/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
-/* 5 */ {8,   16, 32,   32, deflate_slow},
-/* 6 */ {8,   16, 128, 128, deflate_slow},
-/* 7 */ {8,   32, 128, 256, deflate_slow},
-/* 8 */ {32, 128, 258, 1024, deflate_slow},
-/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
-#endif
-
-/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
- * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
- * meaning.
- */
-
-#define EQUAL 0
-/* result of memcmp for equal strings */
-
-#ifndef NO_DUMMY_DECL
-struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
-#endif
-
-/* ===========================================================================
- * Update a hash value with the given input byte
- * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
- *    input characters, so that a running hash key can be computed from the
- *    previous key instead of complete recalculation each time.
- */
-#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask)
-
-
-/* ===========================================================================
- * Insert string str in the dictionary and set match_head to the previous head
- * of the hash chain (the most recent string with same hash key). Return
- * the previous length of the hash chain.
- * If this file is compiled with -DFASTEST, the compression level is forced
- * to 1, and no hash chains are maintained.
- * IN  assertion: all calls to to INSERT_STRING are made with consecutive
- *    input characters and the first MIN_MATCH bytes of str are valid
- *    (except for the last MIN_MATCH-1 bytes of the input file).
- */
-#ifdef FASTEST
-#define INSERT_STRING(s, str, match_head) \
-   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
-    match_head = s->head[s->ins_h], \
-    s->head[s->ins_h] = (Pos)(str))
-#else
-#define INSERT_STRING(s, str, match_head) \
-   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
-    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
-    s->head[s->ins_h] = (Pos)(str))
-#endif
-
-/* ===========================================================================
- * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
- * prev[] will be initialized on the fly.
- */
-#define CLEAR_HASH(s) \
-    s->head[s->hash_size-1] = NIL; \
-    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
-
-/* ========================================================================= */
-int ZEXPORT deflateInit_(strm, level, version, stream_size)
-    z_streamp strm;
-    int level;
-    const char *version;
-    int stream_size;
-{
-    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
-                         Z_DEFAULT_STRATEGY, version, stream_size);
-    /* To do: ignore strm->next_in if we use it as window */
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
-                  version, stream_size)
-    z_streamp strm;
-    int  level;
-    int  method;
-    int  windowBits;
-    int  memLevel;
-    int  strategy;
-    const char *version;
-    int stream_size;
-{
-    deflate_state *s;
-    int wrap = 1;
-    static const char my_version[] = ZLIB_VERSION;
-
-    ushf *overlay;
-    /* We overlay pending_buf and d_buf+l_buf. This works since the average
-     * output size for (length,distance) codes is <= 24 bits.
-     */
-
-    if (version == Z_NULL || version[0] != my_version[0] ||
-        stream_size != sizeof(z_stream)) {
-        return Z_VERSION_ERROR;
-    }
-    if (strm == Z_NULL) return Z_STREAM_ERROR;
-
-    strm->msg = Z_NULL;
-    if (strm->zalloc == (alloc_func)0) {
-        strm->zalloc = zcalloc;
-        strm->opaque = (voidpf)0;
-    }
-    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
-
-#ifdef FASTEST
-    if (level != 0) level = 1;
-#else
-    if (level == Z_DEFAULT_COMPRESSION) level = 6;
-#endif
-
-    if (windowBits < 0) { /* suppress zlib wrapper */
-        wrap = 0;
-        windowBits = -windowBits;
-    }
-#ifdef GZIP
-    else if (windowBits > 15) {
-        wrap = 2;       /* write gzip wrapper instead */
-        windowBits -= 16;
-    }
-#endif
-    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
-        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
-        strategy < 0 || strategy > Z_FIXED) {
-        return Z_STREAM_ERROR;
-    }
-    if (windowBits == 8) windowBits = 9;  /* until 256-byte window bug fixed */
-    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
-    if (s == Z_NULL) return Z_MEM_ERROR;
-    strm->state = (struct internal_state FAR *)s;
-    s->strm = strm;
-
-    s->wrap = wrap;
-    s->gzhead = Z_NULL;
-    s->w_bits = windowBits;
-    s->w_size = 1 << s->w_bits;
-    s->w_mask = s->w_size - 1;
-
-    s->hash_bits = memLevel + 7;
-    s->hash_size = 1 << s->hash_bits;
-    s->hash_mask = s->hash_size - 1;
-    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
-
-    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
-    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
-    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
-
-    s->high_water = 0;      /* nothing written to s->window yet */
-
-    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
-
-    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
-    s->pending_buf = (uchf *) overlay;
-    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
-
-    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
-        s->pending_buf == Z_NULL) {
-        s->status = FINISH_STATE;
-        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
-        deflateEnd (strm);
-        return Z_MEM_ERROR;
-    }
-    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
-    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
-
-    s->level = level;
-    s->strategy = strategy;
-    s->method = (Byte)method;
-
-    return deflateReset(strm);
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
-    z_streamp strm;
-    const Bytef *dictionary;
-    uInt  dictLength;
-{
-    deflate_state *s;
-    uInt length = dictLength;
-    uInt n;
-    IPos hash_head = 0;
-
-    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
-        strm->state->wrap == 2 ||
-        (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
-        return Z_STREAM_ERROR;
-
-    s = strm->state;
-    if (s->wrap)
-        strm->adler = adler32(strm->adler, dictionary, dictLength);
-
-    if (length < MIN_MATCH) return Z_OK;
-    if (length > s->w_size) {
-        length = s->w_size;
-        dictionary += dictLength - length; /* use the tail of the dictionary */
-    }
-    zmemcpy(s->window, dictionary, length);
-    s->strstart = length;
-    s->block_start = (long)length;
-
-    /* Insert all strings in the hash table (except for the last two bytes).
-     * s->lookahead stays null, so s->ins_h will be recomputed at the next
-     * call of fill_window.
-     */
-    s->ins_h = s->window[0];
-    UPDATE_HASH(s, s->ins_h, s->window[1]);
-    for (n = 0; n <= length - MIN_MATCH; n++) {
-        INSERT_STRING(s, n, hash_head);
-    }
-    if (hash_head) hash_head = 0;  /* to make compiler happy */
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateReset (strm)
-    z_streamp strm;
-{
-    deflate_state *s;
-
-    if (strm == Z_NULL || strm->state == Z_NULL ||
-        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
-        return Z_STREAM_ERROR;
-    }
-
-    strm->total_in = strm->total_out = 0;
-    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
-    strm->data_type = Z_UNKNOWN;
-
-    s = (deflate_state *)strm->state;
-    s->pending = 0;
-    s->pending_out = s->pending_buf;
-
-    if (s->wrap < 0) {
-        s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
-    }
-    s->status = s->wrap ? INIT_STATE : BUSY_STATE;
-    strm->adler =
-#ifdef GZIP
-        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
-#endif
-        adler32(0L, Z_NULL, 0);
-    s->last_flush = Z_NO_FLUSH;
-
-    _tr_init(s);
-    lm_init(s);
-
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateSetHeader (strm, head)
-    z_streamp strm;
-    gz_headerp head;
-{
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    if (strm->state->wrap != 2) return Z_STREAM_ERROR;
-    strm->state->gzhead = head;
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflatePrime (strm, bits, value)
-    z_streamp strm;
-    int bits;
-    int value;
-{
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    strm->state->bi_valid = bits;
-    strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
-    return Z_OK;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateParams(strm, level, strategy)
-    z_streamp strm;
-    int level;
-    int strategy;
-{
-    deflate_state *s;
-    compress_func func;
-    int err = Z_OK;
-
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    s = strm->state;
-
-#ifdef FASTEST
-    if (level != 0) level = 1;
-#else
-    if (level == Z_DEFAULT_COMPRESSION) level = 6;
-#endif
-    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
-        return Z_STREAM_ERROR;
-    }
-    func = configuration_table[s->level].func;
-
-    if ((strategy != s->strategy || func != configuration_table[level].func) &&
-        strm->total_in != 0) {
-        /* Flush the last buffer: */
-        err = deflate(strm, Z_BLOCK);
-    }
-    if (s->level != level) {
-        s->level = level;
-        s->max_lazy_match   = configuration_table[level].max_lazy;
-        s->good_match       = configuration_table[level].good_length;
-        s->nice_match       = configuration_table[level].nice_length;
-        s->max_chain_length = configuration_table[level].max_chain;
-    }
-    s->strategy = strategy;
-    return err;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
-    z_streamp strm;
-    int good_length;
-    int max_lazy;
-    int nice_length;
-    int max_chain;
-{
-    deflate_state *s;
-
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    s = strm->state;
-    s->good_match = good_length;
-    s->max_lazy_match = max_lazy;
-    s->nice_match = nice_length;
-    s->max_chain_length = max_chain;
-    return Z_OK;
-}
-
-/* =========================================================================
- * For the default windowBits of 15 and memLevel of 8, this function returns
- * a close to exact, as well as small, upper bound on the compressed size.
- * They are coded as constants here for a reason--if the #define's are
- * changed, then this function needs to be changed as well.  The return
- * value for 15 and 8 only works for those exact settings.
- *
- * For any setting other than those defaults for windowBits and memLevel,
- * the value returned is a conservative worst case for the maximum expansion
- * resulting from using fixed blocks instead of stored blocks, which deflate
- * can emit on compressed data for some combinations of the parameters.
- *
- * This function could be more sophisticated to provide closer upper bounds for
- * every combination of windowBits and memLevel.  But even the conservative
- * upper bound of about 14% expansion does not seem onerous for output buffer
- * allocation.
- */
-uLong ZEXPORT deflateBound(strm, sourceLen)
-    z_streamp strm;
-    uLong sourceLen;
-{
-    deflate_state *s;
-    uLong complen, wraplen;
-    Bytef *str;
-
-    /* conservative upper bound for compressed data */
-    complen = sourceLen +
-              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
-
-    /* if can't get parameters, return conservative bound plus zlib wrapper */
-    if (strm == Z_NULL || strm->state == Z_NULL)
-        return complen + 6;
-
-    /* compute wrapper length */
-    s = strm->state;
-    switch (s->wrap) {
-    case 0:                                 /* raw deflate */
-        wraplen = 0;
-        break;
-    case 1:                                 /* zlib wrapper */
-        wraplen = 6 + (s->strstart ? 4 : 0);
-        break;
-    case 2:                                 /* gzip wrapper */
-        wraplen = 18;
-        if (s->gzhead != Z_NULL) {          /* user-supplied gzip header */
-            if (s->gzhead->extra != Z_NULL)
-                wraplen += 2 + s->gzhead->extra_len;
-            str = s->gzhead->name;
-            if (str != Z_NULL)
-                do {
-                    wraplen++;
-                } while (*str++);
-            str = s->gzhead->comment;
-            if (str != Z_NULL)
-                do {
-                    wraplen++;
-                } while (*str++);
-            if (s->gzhead->hcrc)
-                wraplen += 2;
-        }
-        break;
-    default:                                /* for compiler happiness */
-        wraplen = 6;
-    }
-
-    /* if not default parameters, return conservative bound */
-    if (s->w_bits != 15 || s->hash_bits != 8 + 7)
-        return complen + wraplen;
-
-    /* default settings: return tight bound for that case */
-    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
-           (sourceLen >> 25) + 13 - 6 + wraplen;
-}
-
-/* =========================================================================
- * Put a short in the pending buffer. The 16-bit value is put in MSB order.
- * IN assertion: the stream state is correct and there is enough room in
- * pending_buf.
- */
-local void putShortMSB (s, b)
-    deflate_state *s;
-    uInt b;
-{
-    put_byte(s, (Byte)(b >> 8));
-    put_byte(s, (Byte)(b & 0xff));
-}
-
-/* =========================================================================
- * Flush as much pending output as possible. All deflate() output goes
- * through this function so some applications may wish to modify it
- * to avoid allocating a large strm->next_out buffer and copying into it.
- * (See also read_buf()).
- */
-local void flush_pending(strm)
-    z_streamp strm;
-{
-    unsigned len = strm->state->pending;
-
-    if (len > strm->avail_out) len = strm->avail_out;
-    if (len == 0) return;
-
-    zmemcpy(strm->next_out, strm->state->pending_out, len);
-    strm->next_out  += len;
-    strm->state->pending_out  += len;
-    strm->total_out += len;
-    strm->avail_out  -= len;
-    strm->state->pending -= len;
-    if (strm->state->pending == 0) {
-        strm->state->pending_out = strm->state->pending_buf;
-    }
-}
-
-/* ========================================================================= */
-int ZEXPORT deflate (strm, flush)
-    z_streamp strm;
-    int flush;
-{
-    int old_flush; /* value of flush param for previous deflate call */
-    deflate_state *s;
-
-    if (strm == Z_NULL || strm->state == Z_NULL ||
-        flush > Z_BLOCK || flush < 0) {
-        return Z_STREAM_ERROR;
-    }
-    s = strm->state;
-
-    if (strm->next_out == Z_NULL ||
-        (strm->next_in == Z_NULL && strm->avail_in != 0) ||
-        (s->status == FINISH_STATE && flush != Z_FINISH)) {
-        ERR_RETURN(strm, Z_STREAM_ERROR);
-    }
-    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
-
-    s->strm = strm; /* just in case */
-    old_flush = s->last_flush;
-    s->last_flush = flush;
-
-    /* Write the header */
-    if (s->status == INIT_STATE) {
-#ifdef GZIP
-        if (s->wrap == 2) {
-            strm->adler = crc32(0L, Z_NULL, 0);
-            put_byte(s, 31);
-            put_byte(s, 139);
-            put_byte(s, 8);
-            if (s->gzhead == Z_NULL) {
-                put_byte(s, 0);
-                put_byte(s, 0);
-                put_byte(s, 0);
-                put_byte(s, 0);
-                put_byte(s, 0);
-                put_byte(s, s->level == 9 ? 2 :
-                            (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
-                             4 : 0));
-                put_byte(s, OS_CODE);
-                s->status = BUSY_STATE;
-            }
-            else {
-                put_byte(s, (s->gzhead->text ? 1 : 0) +
-                            (s->gzhead->hcrc ? 2 : 0) +
-                            (s->gzhead->extra == Z_NULL ? 0 : 4) +
-                            (s->gzhead->name == Z_NULL ? 0 : 8) +
-                            (s->gzhead->comment == Z_NULL ? 0 : 16)
-                        );
-                put_byte(s, (Byte)(s->gzhead->time & 0xff));
-                put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
-                put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
-                put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
-                put_byte(s, s->level == 9 ? 2 :
-                            (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
-                             4 : 0));
-                put_byte(s, s->gzhead->os & 0xff);
-                if (s->gzhead->extra != Z_NULL) {
-                    put_byte(s, s->gzhead->extra_len & 0xff);
-                    put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
-                }
-                if (s->gzhead->hcrc)
-                    strm->adler = crc32(strm->adler, s->pending_buf,
-                                        s->pending);
-                s->gzindex = 0;
-                s->status = EXTRA_STATE;
-            }
-        }
-        else
-#endif
-        {
-            uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
-            uInt level_flags;
-
-            if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
-                level_flags = 0;
-            else if (s->level < 6)
-                level_flags = 1;
-            else if (s->level == 6)
-                level_flags = 2;
-            else
-                level_flags = 3;
-            header |= (level_flags << 6);
-            if (s->strstart != 0) header |= PRESET_DICT;
-            header += 31 - (header % 31);
-
-            s->status = BUSY_STATE;
-            putShortMSB(s, header);
-
-            /* Save the adler32 of the preset dictionary: */
-            if (s->strstart != 0) {
-                putShortMSB(s, (uInt)(strm->adler >> 16));
-                putShortMSB(s, (uInt)(strm->adler & 0xffff));
-            }
-            strm->adler = adler32(0L, Z_NULL, 0);
-        }
-    }
-#ifdef GZIP
-    if (s->status == EXTRA_STATE) {
-        if (s->gzhead->extra != Z_NULL) {
-            uInt beg = s->pending;  /* start of bytes to update crc */
-
-            while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
-                if (s->pending == s->pending_buf_size) {
-                    if (s->gzhead->hcrc && s->pending > beg)
-                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
-                                            s->pending - beg);
-                    flush_pending(strm);
-                    beg = s->pending;
-                    if (s->pending == s->pending_buf_size)
-                        break;
-                }
-                put_byte(s, s->gzhead->extra[s->gzindex]);
-                s->gzindex++;
-            }
-            if (s->gzhead->hcrc && s->pending > beg)
-                strm->adler = crc32(strm->adler, s->pending_buf + beg,
-                                    s->pending - beg);
-            if (s->gzindex == s->gzhead->extra_len) {
-                s->gzindex = 0;
-                s->status = NAME_STATE;
-            }
-        }
-        else
-            s->status = NAME_STATE;
-    }
-    if (s->status == NAME_STATE) {
-        if (s->gzhead->name != Z_NULL) {
-            uInt beg = s->pending;  /* start of bytes to update crc */
-            int val;
-
-            do {
-                if (s->pending == s->pending_buf_size) {
-                    if (s->gzhead->hcrc && s->pending > beg)
-                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
-                                            s->pending - beg);
-                    flush_pending(strm);
-                    beg = s->pending;
-                    if (s->pending == s->pending_buf_size) {
-                        val = 1;
-                        break;
-                    }
-                }
-                val = s->gzhead->name[s->gzindex++];
-                put_byte(s, val);
-            } while (val != 0);
-            if (s->gzhead->hcrc && s->pending > beg)
-                strm->adler = crc32(strm->adler, s->pending_buf + beg,
-                                    s->pending - beg);
-            if (val == 0) {
-                s->gzindex = 0;
-                s->status = COMMENT_STATE;
-            }
-        }
-        else
-            s->status = COMMENT_STATE;
-    }
-    if (s->status == COMMENT_STATE) {
-        if (s->gzhead->comment != Z_NULL) {
-            uInt beg = s->pending;  /* start of bytes to update crc */
-            int val;
-
-            do {
-                if (s->pending == s->pending_buf_size) {
-                    if (s->gzhead->hcrc && s->pending > beg)
-                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
-                                            s->pending - beg);
-                    flush_pending(strm);
-                    beg = s->pending;
-                    if (s->pending == s->pending_buf_size) {
-                        val = 1;
-                        break;
-                    }
-                }
-                val = s->gzhead->comment[s->gzindex++];
-                put_byte(s, val);
-            } while (val != 0);
-            if (s->gzhead->hcrc && s->pending > beg)
-                strm->adler = crc32(strm->adler, s->pending_buf + beg,
-                                    s->pending - beg);
-            if (val == 0)
-                s->status = HCRC_STATE;
-        }
-        else
-            s->status = HCRC_STATE;
-    }
-    if (s->status == HCRC_STATE) {
-        if (s->gzhead->hcrc) {
-            if (s->pending + 2 > s->pending_buf_size)
-                flush_pending(strm);
-            if (s->pending + 2 <= s->pending_buf_size) {
-                put_byte(s, (Byte)(strm->adler & 0xff));
-                put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
-                strm->adler = crc32(0L, Z_NULL, 0);
-                s->status = BUSY_STATE;
-            }
-        }
-        else
-            s->status = BUSY_STATE;
-    }
-#endif
-
-    /* Flush as much pending output as possible */
-    if (s->pending != 0) {
-        flush_pending(strm);
-        if (strm->avail_out == 0) {
-            /* Since avail_out is 0, deflate will be called again with
-             * more output space, but possibly with both pending and
-             * avail_in equal to zero. There won't be anything to do,
-             * but this is not an error situation so make sure we
-             * return OK instead of BUF_ERROR at next call of deflate:
-             */
-            s->last_flush = -1;
-            return Z_OK;
-        }
-
-    /* Make sure there is something to do and avoid duplicate consecutive
-     * flushes. For repeated and useless calls with Z_FINISH, we keep
-     * returning Z_STREAM_END instead of Z_BUF_ERROR.
-     */
-    } else if (strm->avail_in == 0 && flush <= old_flush &&
-               flush != Z_FINISH) {
-        ERR_RETURN(strm, Z_BUF_ERROR);
-    }
-
-    /* User must not provide more input after the first FINISH: */
-    if (s->status == FINISH_STATE && strm->avail_in != 0) {
-        ERR_RETURN(strm, Z_BUF_ERROR);
-    }
-
-    /* Start a new block or continue the current one.
-     */
-    if (strm->avail_in != 0 || s->lookahead != 0 ||
-        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
-        block_state bstate;
-
-        bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
-                    (s->strategy == Z_RLE ? deflate_rle(s, flush) :
-                        (*(configuration_table[s->level].func))(s, flush));
-
-        if (bstate == finish_started || bstate == finish_done) {
-            s->status = FINISH_STATE;
-        }
-        if (bstate == need_more || bstate == finish_started) {
-            if (strm->avail_out == 0) {
-                s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
-            }
-            return Z_OK;
-            /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
-             * of deflate should use the same flush parameter to make sure
-             * that the flush is complete. So we don't have to output an
-             * empty block here, this will be done at next call. This also
-             * ensures that for a very small output buffer, we emit at most
-             * one empty block.
-             */
-        }
-        if (bstate == block_done) {
-            if (flush == Z_PARTIAL_FLUSH) {
-                _tr_align(s);
-            } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
-                _tr_stored_block(s, (char*)0, 0L, 0);
-                /* For a full flush, this empty block will be recognized
-                 * as a special marker by inflate_sync().
-                 */
-                if (flush == Z_FULL_FLUSH) {
-                    CLEAR_HASH(s);             /* forget history */
-                    if (s->lookahead == 0) {
-                        s->strstart = 0;
-                        s->block_start = 0L;
-                    }
-                }
-            }
-            flush_pending(strm);
-            if (strm->avail_out == 0) {
-              s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
-              return Z_OK;
-            }
-        }
-    }
-    Assert(strm->avail_out > 0, "bug2");
-
-    if (flush != Z_FINISH) return Z_OK;
-    if (s->wrap <= 0) return Z_STREAM_END;
-
-    /* Write the trailer */
-#ifdef GZIP
-    if (s->wrap == 2) {
-        put_byte(s, (Byte)(strm->adler & 0xff));
-        put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
-        put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
-        put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
-        put_byte(s, (Byte)(strm->total_in & 0xff));
-        put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
-        put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
-        put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
-    }
-    else
-#endif
-    {
-        putShortMSB(s, (uInt)(strm->adler >> 16));
-        putShortMSB(s, (uInt)(strm->adler & 0xffff));
-    }
-    flush_pending(strm);
-    /* If avail_out is zero, the application will call deflate again
-     * to flush the rest.
-     */
-    if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
-    return s->pending != 0 ? Z_OK : Z_STREAM_END;
-}
-
-/* ========================================================================= */
-int ZEXPORT deflateEnd (strm)
-    z_streamp strm;
-{
-    int status;
-
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-
-    status = strm->state->status;
-    if (status != INIT_STATE &&
-        status != EXTRA_STATE &&
-        status != NAME_STATE &&
-        status != COMMENT_STATE &&
-        status != HCRC_STATE &&
-        status != BUSY_STATE &&
-        status != FINISH_STATE) {
-      return Z_STREAM_ERROR;
-    }
-
-    /* Deallocate in reverse order of allocations: */
-    TRY_FREE(strm, strm->state->pending_buf);
-    TRY_FREE(strm, strm->state->head);
-    TRY_FREE(strm, strm->state->prev);
-    TRY_FREE(strm, strm->state->window);
-
-    ZFREE(strm, strm->state);
-    strm->state = Z_NULL;
-
-    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
-}
-
-/* =========================================================================
- * Copy the source state to the destination state.
- * To simplify the source, this is not supported for 16-bit MSDOS (which
- * doesn't have enough memory anyway to duplicate compression states).
- */
-int ZEXPORT deflateCopy (dest, source)
-    z_streamp dest;
-    z_streamp source;
-{
-#ifdef MAXSEG_64K
-    return Z_STREAM_ERROR;
-#else
-    deflate_state *ds;
-    deflate_state *ss;
-    ushf *overlay;
-
-
-    if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
-        return Z_STREAM_ERROR;
-    }
-
-    ss = source->state;
-
-    zmemcpy(dest, source, sizeof(z_stream));
-
-    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
-    if (ds == Z_NULL) return Z_MEM_ERROR;
-    dest->state = (struct internal_state FAR *) ds;
-    zmemcpy(ds, ss, sizeof(deflate_state));
-    ds->strm = dest;
-
-    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
-    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
-    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
-    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
-    ds->pending_buf = (uchf *) overlay;
-
-    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
-        ds->pending_buf == Z_NULL) {
-        deflateEnd (dest);
-        return Z_MEM_ERROR;
-    }
-    /* following zmemcpy do not work for 16-bit MSDOS */
-    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
-    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
-    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
-    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
-
-    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
-    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
-    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
-
-    ds->l_desc.dyn_tree = ds->dyn_ltree;
-    ds->d_desc.dyn_tree = ds->dyn_dtree;
-    ds->bl_desc.dyn_tree = ds->bl_tree;
-
-    return Z_OK;
-#endif /* MAXSEG_64K */
-}
-
-/* ===========================================================================
- * Read a new buffer from the current input stream, update the adler32
- * and total number of bytes read.  All deflate() input goes through
- * this function so some applications may wish to modify it to avoid
- * allocating a large strm->next_in buffer and copying from it.
- * (See also flush_pending()).
- */
-local int read_buf(strm, buf, size)
-    z_streamp strm;
-    Bytef *buf;
-    unsigned size;
-{
-    unsigned len = strm->avail_in;
-
-    if (len > size) len = size;
-    if (len == 0) return 0;
-
-    strm->avail_in  -= len;
-
-    if (strm->state->wrap == 1) {
-        strm->adler = adler32(strm->adler, strm->next_in, len);
-    }
-#ifdef GZIP
-    else if (strm->state->wrap == 2) {
-        strm->adler = crc32(strm->adler, strm->next_in, len);
-    }
-#endif
-    zmemcpy(buf, strm->next_in, len);
-    strm->next_in  += len;
-    strm->total_in += len;
-
-    return (int)len;
-}
-
-/* ===========================================================================
- * Initialize the "longest match" routines for a new zlib stream
- */
-local void lm_init (s)
-    deflate_state *s;
-{
-    s->window_size = (ulg)2L*s->w_size;
-
-    CLEAR_HASH(s);
-
-    /* Set the default configuration parameters:
-     */
-    s->max_lazy_match   = configuration_table[s->level].max_lazy;
-    s->good_match       = configuration_table[s->level].good_length;
-    s->nice_match       = configuration_table[s->level].nice_length;
-    s->max_chain_length = configuration_table[s->level].max_chain;
-
-    s->strstart = 0;
-    s->block_start = 0L;
-    s->lookahead = 0;
-    s->match_length = s->prev_length = MIN_MATCH-1;
-    s->match_available = 0;
-    s->ins_h = 0;
-#ifndef FASTEST
-#ifdef ASMV
-    match_init(); /* initialize the asm code */
-#endif
-#endif
-}
-
-#ifndef FASTEST
-/* ===========================================================================
- * Set match_start to the longest match starting at the given string and
- * return its length. Matches shorter or equal to prev_length are discarded,
- * in which case the result is equal to prev_length and match_start is
- * garbage.
- * IN assertions: cur_match is the head of the hash chain for the current
- *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
- * OUT assertion: the match length is not greater than s->lookahead.
- */
-#ifndef ASMV
-/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
- * match.S. The code will be functionally equivalent.
- */
-local uInt longest_match(s, cur_match)
-    deflate_state *s;
-    IPos cur_match;                             /* current match */
-{
-    unsigned chain_length = s->max_chain_length;/* max hash chain length */
-    register Bytef *scan = s->window + s->strstart; /* current string */
-    register Bytef *match;                       /* matched string */
-    register int len;                           /* length of current match */
-    int best_len = s->prev_length;              /* best match length so far */
-    int nice_match = s->nice_match;             /* stop if match long enough */
-    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
-        s->strstart - (IPos)MAX_DIST(s) : NIL;
-    /* Stop when cur_match becomes <= limit. To simplify the code,
-     * we prevent matches with the string of window index 0.
-     */
-    Posf *prev = s->prev;
-    uInt wmask = s->w_mask;
-
-#ifdef UNALIGNED_OK
-    /* Compare two bytes at a time. Note: this is not always beneficial.
-     * Try with and without -DUNALIGNED_OK to check.
-     */
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
-    register ush scan_start = *(ushf*)scan;
-    register ush scan_end   = *(ushf*)(scan+best_len-1);
-#else
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
-    register Byte scan_end1  = scan[best_len-1];
-    register Byte scan_end   = scan[best_len];
-#endif
-
-    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
-     * It is easy to get rid of this optimization if necessary.
-     */
-    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
-
-    /* Do not waste too much time if we already have a good match: */
-    if (s->prev_length >= s->good_match) {
-        chain_length >>= 2;
-    }
-    /* Do not look for matches beyond the end of the input. This is necessary
-     * to make deflate deterministic.
-     */
-    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-
-    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
-
-    do {
-        Assert(cur_match < s->strstart, "no future");
-        match = s->window + cur_match;
-
-        /* Skip to next match if the match length cannot increase
-         * or if the match length is less than 2.  Note that the checks below
-         * for insufficient lookahead only occur occasionally for performance
-         * reasons.  Therefore uninitialized memory will be accessed, and
-         * conditional jumps will be made that depend on those values.
-         * However the length of the match is limited to the lookahead, so
-         * the output of deflate is not affected by the uninitialized values.
-         */
-#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
-        /* This code assumes sizeof(unsigned short) == 2. Do not use
-         * UNALIGNED_OK if your compiler uses a different size.
-         */
-        if (*(ushf*)(match+best_len-1) != scan_end ||
-            *(ushf*)match != scan_start) continue;
-
-        /* It is not necessary to compare scan[2] and match[2] since they are
-         * always equal when the other bytes match, given that the hash keys
-         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
-         * strstart+3, +5, ... up to strstart+257. We check for insufficient
-         * lookahead only every 4th comparison; the 128th check will be made
-         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
-         * necessary to put more guard bytes at the end of the window, or
-         * to check more often for insufficient lookahead.
-         */
-        Assert(scan[2] == match[2], "scan[2]?");
-        scan++, match++;
-        do {
-        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 scan < strend);
-        /* The funny "do {}" generates better code on most compilers */
-
-        /* Here, scan <= window+strstart+257 */
-        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-        if (*scan == *match) scan++;
-
-        len = (MAX_MATCH - 1) - (int)(strend-scan);
-        scan = strend - (MAX_MATCH-1);
-
-#else /* UNALIGNED_OK */
-
-        if (match[best_len]   != scan_end  ||
-            match[best_len-1] != scan_end1 ||
-            *match            != *scan     ||
-            *++match          != scan[1])      continue;
-
-        /* The check at best_len-1 can be removed because it will be made
-         * again later. (This heuristic is not always a win.)
-         * It is not necessary to compare scan[2] and match[2] since they
-         * are always equal when the other bytes match, given that
-         * the hash keys are equal and that HASH_BITS >= 8.
-         */
-        scan += 2, match++;
-        Assert(*scan == *match, "match[2]?");
-
-        /* We check for insufficient lookahead only every 8th comparison;
-         * the 256th check will be made at strstart+258.
-         */
-        do {
-        } while (*++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 scan < strend);
-
-        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-
-        len = MAX_MATCH - (int)(strend - scan);
-        scan = strend - MAX_MATCH;
-
-#endif /* UNALIGNED_OK */
-
-        if (len > best_len) {
-            s->match_start = cur_match;
-            best_len = len;
-            if (len >= nice_match) break;
-#ifdef UNALIGNED_OK
-            scan_end = *(ushf*)(scan+best_len-1);
-#else
-            scan_end1  = scan[best_len-1];
-            scan_end   = scan[best_len];
-#endif
-        }
-    } while ((cur_match = prev[cur_match & wmask]) > limit
-             && --chain_length != 0);
-
-    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
-    return s->lookahead;
-}
-#endif /* ASMV */
-
-#else /* FASTEST */
-
-/* ---------------------------------------------------------------------------
- * Optimized version for FASTEST only
- */
-local uInt longest_match(s, cur_match)
-    deflate_state *s;
-    IPos cur_match;                             /* current match */
-{
-    register Bytef *scan = s->window + s->strstart; /* current string */
-    register Bytef *match;                       /* matched string */
-    register int len;                           /* length of current match */
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
-
-    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
-     * It is easy to get rid of this optimization if necessary.
-     */
-    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
-
-    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
-
-    Assert(cur_match < s->strstart, "no future");
-
-    match = s->window + cur_match;
-
-    /* Return failure if the match length is less than 2:
-     */
-    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
-
-    /* The check at best_len-1 can be removed because it will be made
-     * again later. (This heuristic is not always a win.)
-     * It is not necessary to compare scan[2] and match[2] since they
-     * are always equal when the other bytes match, given that
-     * the hash keys are equal and that HASH_BITS >= 8.
-     */
-    scan += 2, match += 2;
-    Assert(*scan == *match, "match[2]?");
-
-    /* We check for insufficient lookahead only every 8th comparison;
-     * the 256th check will be made at strstart+258.
-     */
-    do {
-    } while (*++scan == *++match && *++scan == *++match &&
-             *++scan == *++match && *++scan == *++match &&
-             *++scan == *++match && *++scan == *++match &&
-             *++scan == *++match && *++scan == *++match &&
-             scan < strend);
-
-    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-
-    len = MAX_MATCH - (int)(strend - scan);
-
-    if (len < MIN_MATCH) return MIN_MATCH - 1;
-
-    s->match_start = cur_match;
-    return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
-}
-
-#endif /* FASTEST */
-
-#ifdef DEBUG
-/* ===========================================================================
- * Check that the match at match_start is indeed a match.
- */
-local void check_match(s, start, match, length)
-    deflate_state *s;
-    IPos start, match;
-    int length;
-{
-    /* check that the match is indeed a match */
-    if (zmemcmp(s->window + match,
-                s->window + start, length) != EQUAL) {
-        fprintf(stderr, " start %u, match %u, length %d\n",
-                start, match, length);
-        do {
-            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
-        } while (--length != 0);
-        z_error("invalid match");
-    }
-    if (z_verbose > 1) {
-        fprintf(stderr,"\\[%d,%d]", start-match, length);
-        do { putc(s->window[start++], stderr); } while (--length != 0);
-    }
-}
-#else
-#  define check_match(s, start, match, length)
-#endif /* DEBUG */
-
-/* ===========================================================================
- * Fill the window when the lookahead becomes insufficient.
- * Updates strstart and lookahead.
- *
- * IN assertion: lookahead < MIN_LOOKAHEAD
- * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
- *    At least one byte has been read, or avail_in == 0; reads are
- *    performed for at least two bytes (required for the zip translate_eol
- *    option -- not supported here).
- */
-local void fill_window(s)
-    deflate_state *s;
-{
-    register unsigned n, m;
-    register Posf *p;
-    unsigned more;    /* Amount of free space at the end of the window. */
-    uInt wsize = s->w_size;
-
-    do {
-        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
-
-        /* Deal with !@#$% 64K limit: */
-        if (sizeof(int) <= 2) {
-            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
-                more = wsize;
-
-            } else if (more == (unsigned)(-1)) {
-                /* Very unlikely, but possible on 16 bit machine if
-                 * strstart == 0 && lookahead == 1 (input done a byte at time)
-                 */
-                more--;
-            }
-        }
-
-        /* If the window is almost full and there is insufficient lookahead,
-         * move the upper half to the lower one to make room in the upper half.
-         */
-        if (s->strstart >= wsize+MAX_DIST(s)) {
-
-            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
-            s->match_start -= wsize;
-            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
-            s->block_start -= (long) wsize;
-
-            /* Slide the hash table (could be avoided with 32 bit values
-               at the expense of memory usage). We slide even when level == 0
-               to keep the hash table consistent if we switch back to level > 0
-               later. (Using level 0 permanently is not an optimal usage of
-               zlib, so we don't care about this pathological case.)
-             */
-            n = s->hash_size;
-            p = &s->head[n];
-            do {
-                m = *--p;
-                *p = (Pos)(m >= wsize ? m-wsize : NIL);
-            } while (--n);
-
-            n = wsize;
-#ifndef FASTEST
-            p = &s->prev[n];
-            do {
-                m = *--p;
-                *p = (Pos)(m >= wsize ? m-wsize : NIL);
-                /* If n is not on any hash chain, prev[n] is garbage but
-                 * its value will never be used.
-                 */
-            } while (--n);
-#endif
-            more += wsize;
-        }
-        if (s->strm->avail_in == 0) return;
-
-        /* If there was no sliding:
-         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
-         *    more == window_size - lookahead - strstart
-         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
-         * => more >= window_size - 2*WSIZE + 2
-         * In the BIG_MEM or MMAP case (not yet supported),
-         *   window_size == input_size + MIN_LOOKAHEAD  &&
-         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
-         * Otherwise, window_size == 2*WSIZE so more >= 2.
-         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
-         */
-        Assert(more >= 2, "more < 2");
-
-        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
-        s->lookahead += n;
-
-        /* Initialize the hash value now that we have some input: */
-        if (s->lookahead >= MIN_MATCH) {
-            s->ins_h = s->window[s->strstart];
-            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
-#if MIN_MATCH != 3
-            Call UPDATE_HASH() MIN_MATCH-3 more times
-#endif
-        }
-        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
-         * but this is not important since only literal bytes will be emitted.
-         */
-
-    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
-
-    /* If the WIN_INIT bytes after the end of the current data have never been
-     * written, then zero those bytes in order to avoid memory check reports of
-     * the use of uninitialized (or uninitialised as Julian writes) bytes by
-     * the longest match routines.  Update the high water mark for the next
-     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
-     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
-     */
-    if (s->high_water < s->window_size) {
-        ulg curr = s->strstart + (ulg)(s->lookahead);
-        ulg init;
-
-        if (s->high_water < curr) {
-            /* Previous high water mark below current data -- zero WIN_INIT
-             * bytes or up to end of window, whichever is less.
-             */
-            init = s->window_size - curr;
-            if (init > WIN_INIT)
-                init = WIN_INIT;
-            zmemzero(s->window + curr, (unsigned)init);
-            s->high_water = curr + init;
-        }
-        else if (s->high_water < (ulg)curr + WIN_INIT) {
-            /* High water mark at or above current data, but below current data
-             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
-             * to end of window, whichever is less.
-             */
-            init = (ulg)curr + WIN_INIT - s->high_water;
-            if (init > s->window_size - s->high_water)
-                init = s->window_size - s->high_water;
-            zmemzero(s->window + s->high_water, (unsigned)init);
-            s->high_water += init;
-        }
-    }
-}
-
-/* ===========================================================================
- * Flush the current block, with given end-of-file flag.
- * IN assertion: strstart is set to the end of the current match.
- */
-#define FLUSH_BLOCK_ONLY(s, last) { \
-   _tr_flush_block(s, (s->block_start >= 0L ? \
-                   (charf *)&s->window[(unsigned)s->block_start] : \
-                   (charf *)Z_NULL), \
-                (ulg)((long)s->strstart - s->block_start), \
-                (last)); \
-   s->block_start = s->strstart; \
-   flush_pending(s->strm); \
-   Tracev((stderr,"[FLUSH]")); \
-}
-
-/* Same but force premature exit if necessary. */
-#define FLUSH_BLOCK(s, last) { \
-   FLUSH_BLOCK_ONLY(s, last); \
-   if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
-}
-
-/* ===========================================================================
- * Copy without compression as much as possible from the input stream, return
- * the current block state.
- * This function does not insert new strings in the dictionary since
- * uncompressible data is probably not useful. This function is used
- * only for the level=0 compression option.
- * NOTE: this function should be optimized to avoid extra copying from
- * window to pending_buf.
- */
-local block_state deflate_stored(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
-     * to pending_buf_size, and each stored block has a 5 byte header:
-     */
-    ulg max_block_size = 0xffff;
-    ulg max_start;
-
-    if (max_block_size > s->pending_buf_size - 5) {
-        max_block_size = s->pending_buf_size - 5;
-    }
-
-    /* Copy as much as possible from input to output: */
-    for (;;) {
-        /* Fill the window as much as possible: */
-        if (s->lookahead <= 1) {
-
-            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
-                   s->block_start >= (long)s->w_size, "slide too late");
-
-            fill_window(s);
-            if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
-
-            if (s->lookahead == 0) break; /* flush the current block */
-        }
-        Assert(s->block_start >= 0L, "block gone");
-
-        s->strstart += s->lookahead;
-        s->lookahead = 0;
-
-        /* Emit a stored block if pending_buf will be full: */
-        max_start = s->block_start + max_block_size;
-        if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
-            /* strstart == 0 is possible when wraparound on 16-bit machine */
-            s->lookahead = (uInt)(s->strstart - max_start);
-            s->strstart = (uInt)max_start;
-            FLUSH_BLOCK(s, 0);
-        }
-        /* Flush if we may have to slide, otherwise block_start may become
-         * negative and the data will be gone:
-         */
-        if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
-            FLUSH_BLOCK(s, 0);
-        }
-    }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
-}
-
-/* ===========================================================================
- * Compress as much as possible from the input stream, return the current
- * block state.
- * This function does not perform lazy evaluation of matches and inserts
- * new strings in the dictionary only for unmatched strings or for short
- * matches. It is used only for the fast compression options.
- */
-local block_state deflate_fast(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    IPos hash_head;       /* head of the hash chain */
-    int bflush;           /* set if current block must be flushed */
-
-    for (;;) {
-        /* Make sure that we always have enough lookahead, except
-         * at the end of the input file. We need MAX_MATCH bytes
-         * for the next match, plus MIN_MATCH bytes to insert the
-         * string following the next match.
-         */
-        if (s->lookahead < MIN_LOOKAHEAD) {
-            fill_window(s);
-            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
-                return need_more;
-            }
-            if (s->lookahead == 0) break; /* flush the current block */
-        }
-
-        /* Insert the string window[strstart .. strstart+2] in the
-         * dictionary, and set hash_head to the head of the hash chain:
-         */
-        hash_head = NIL;
-        if (s->lookahead >= MIN_MATCH) {
-            INSERT_STRING(s, s->strstart, hash_head);
-        }
-
-        /* Find the longest match, discarding those <= prev_length.
-         * At this point we have always match_length < MIN_MATCH
-         */
-        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
-            /* To simplify the code, we prevent matches with the string
-             * of window index 0 (in particular we have to avoid a match
-             * of the string with itself at the start of the input file).
-             */
-            s->match_length = longest_match (s, hash_head);
-            /* longest_match() sets match_start */
-        }
-        if (s->match_length >= MIN_MATCH) {
-            check_match(s, s->strstart, s->match_start, s->match_length);
-
-            _tr_tally_dist(s, s->strstart - s->match_start,
-                           s->match_length - MIN_MATCH, bflush);
-
-            s->lookahead -= s->match_length;
-
-            /* Insert new strings in the hash table only if the match length
-             * is not too large. This saves time but degrades compression.
-             */
-#ifndef FASTEST
-            if (s->match_length <= s->max_insert_length &&
-                s->lookahead >= MIN_MATCH) {
-                s->match_length--; /* string at strstart already in table */
-                do {
-                    s->strstart++;
-                    INSERT_STRING(s, s->strstart, hash_head);
-                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
-                     * always MIN_MATCH bytes ahead.
-                     */
-                } while (--s->match_length != 0);
-                s->strstart++;
-            } else
-#endif
-            {
-                s->strstart += s->match_length;
-                s->match_length = 0;
-                s->ins_h = s->window[s->strstart];
-                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
-#if MIN_MATCH != 3
-                Call UPDATE_HASH() MIN_MATCH-3 more times
-#endif
-                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
-                 * matter since it will be recomputed at next deflate call.
-                 */
-            }
-        } else {
-            /* No match, output a literal byte */
-            Tracevv((stderr,"%c", s->window[s->strstart]));
-            _tr_tally_lit (s, s->window[s->strstart], bflush);
-            s->lookahead--;
-            s->strstart++;
-        }
-        if (bflush) FLUSH_BLOCK(s, 0);
-    }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
-}
-
-#ifndef FASTEST
-/* ===========================================================================
- * Same as above, but achieves better compression. We use a lazy
- * evaluation for matches: a match is finally adopted only if there is
- * no better match at the next window position.
- */
-local block_state deflate_slow(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    IPos hash_head;          /* head of hash chain */
-    int bflush;              /* set if current block must be flushed */
-
-    /* Process the input block. */
-    for (;;) {
-        /* Make sure that we always have enough lookahead, except
-         * at the end of the input file. We need MAX_MATCH bytes
-         * for the next match, plus MIN_MATCH bytes to insert the
-         * string following the next match.
-         */
-        if (s->lookahead < MIN_LOOKAHEAD) {
-            fill_window(s);
-            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
-                return need_more;
-            }
-            if (s->lookahead == 0) break; /* flush the current block */
-        }
-
-        /* Insert the string window[strstart .. strstart+2] in the
-         * dictionary, and set hash_head to the head of the hash chain:
-         */
-        hash_head = NIL;
-        if (s->lookahead >= MIN_MATCH) {
-            INSERT_STRING(s, s->strstart, hash_head);
-        }
-
-        /* Find the longest match, discarding those <= prev_length.
-         */
-        s->prev_length = s->match_length, s->prev_match = s->match_start;
-        s->match_length = MIN_MATCH-1;
-
-        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
-            s->strstart - hash_head <= MAX_DIST(s)) {
-            /* To simplify the code, we prevent matches with the string
-             * of window index 0 (in particular we have to avoid a match
-             * of the string with itself at the start of the input file).
-             */
-            s->match_length = longest_match (s, hash_head);
-            /* longest_match() sets match_start */
-
-            if (s->match_length <= 5 && (s->strategy == Z_FILTERED
-#if TOO_FAR <= 32767
-                || (s->match_length == MIN_MATCH &&
-                    s->strstart - s->match_start > TOO_FAR)
-#endif
-                )) {
-
-                /* If prev_match is also MIN_MATCH, match_start is garbage
-                 * but we will ignore the current match anyway.
-                 */
-                s->match_length = MIN_MATCH-1;
-            }
-        }
-        /* If there was a match at the previous step and the current
-         * match is not better, output the previous match:
-         */
-        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
-            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
-            /* Do not insert strings in hash table beyond this. */
-
-            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
-
-            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
-                           s->prev_length - MIN_MATCH, bflush);
-
-            /* Insert in hash table all strings up to the end of the match.
-             * strstart-1 and strstart are already inserted. If there is not
-             * enough lookahead, the last two strings are not inserted in
-             * the hash table.
-             */
-            s->lookahead -= s->prev_length-1;
-            s->prev_length -= 2;
-            do {
-                if (++s->strstart <= max_insert) {
-                    INSERT_STRING(s, s->strstart, hash_head);
-                }
-            } while (--s->prev_length != 0);
-            s->match_available = 0;
-            s->match_length = MIN_MATCH-1;
-            s->strstart++;
-
-            if (bflush) FLUSH_BLOCK(s, 0);
-
-        } else if (s->match_available) {
-            /* If there was no match at the previous position, output a
-             * single literal. If there was a match but the current match
-             * is longer, truncate the previous match to a single literal.
-             */
-            Tracevv((stderr,"%c", s->window[s->strstart-1]));
-            _tr_tally_lit(s, s->window[s->strstart-1], bflush);
-            if (bflush) {
-                FLUSH_BLOCK_ONLY(s, 0);
-            }
-            s->strstart++;
-            s->lookahead--;
-            if (s->strm->avail_out == 0) return need_more;
-        } else {
-            /* There is no previous match to compare with, wait for
-             * the next step to decide.
-             */
-            s->match_available = 1;
-            s->strstart++;
-            s->lookahead--;
-        }
-    }
-    Assert (flush != Z_NO_FLUSH, "no flush?");
-    if (s->match_available) {
-        Tracevv((stderr,"%c", s->window[s->strstart-1]));
-        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
-        s->match_available = 0;
-    }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
-}
-#endif /* FASTEST */
-
-/* ===========================================================================
- * For Z_RLE, simply look for runs of bytes, generate matches only of distance
- * one.  Do not maintain a hash table.  (It will be regenerated if this run of
- * deflate switches away from Z_RLE.)
- */
-local block_state deflate_rle(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    int bflush;             /* set if current block must be flushed */
-    uInt prev;              /* byte at distance one to match */
-    Bytef *scan, *strend;   /* scan goes up to strend for length of run */
-
-    for (;;) {
-        /* Make sure that we always have enough lookahead, except
-         * at the end of the input file. We need MAX_MATCH bytes
-         * for the longest encodable run.
-         */
-        if (s->lookahead < MAX_MATCH) {
-            fill_window(s);
-            if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
-                return need_more;
-            }
-            if (s->lookahead == 0) break; /* flush the current block */
-        }
-
-        /* See how many times the previous byte repeats */
-        s->match_length = 0;
-        if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
-            scan = s->window + s->strstart - 1;
-            prev = *scan;
-            if (prev == *++scan && prev == *++scan && prev == *++scan) {
-                strend = s->window + s->strstart + MAX_MATCH;
-                do {
-                } while (prev == *++scan && prev == *++scan &&
-                         prev == *++scan && prev == *++scan &&
-                         prev == *++scan && prev == *++scan &&
-                         prev == *++scan && prev == *++scan &&
-                         scan < strend);
-                s->match_length = MAX_MATCH - (int)(strend - scan);
-                if (s->match_length > s->lookahead)
-                    s->match_length = s->lookahead;
-            }
-        }
-
-        /* Emit match if have run of MIN_MATCH or longer, else emit literal */
-        if (s->match_length >= MIN_MATCH) {
-            check_match(s, s->strstart, s->strstart - 1, s->match_length);
-
-            _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
-
-            s->lookahead -= s->match_length;
-            s->strstart += s->match_length;
-            s->match_length = 0;
-        } else {
-            /* No match, output a literal byte */
-            Tracevv((stderr,"%c", s->window[s->strstart]));
-            _tr_tally_lit (s, s->window[s->strstart], bflush);
-            s->lookahead--;
-            s->strstart++;
-        }
-        if (bflush) FLUSH_BLOCK(s, 0);
-    }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
-}
-
-/* ===========================================================================
- * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
- * (It will be regenerated if this run of deflate switches away from Huffman.)
- */
-local block_state deflate_huff(s, flush)
-    deflate_state *s;
-    int flush;
-{
-    int bflush;             /* set if current block must be flushed */
-
-    for (;;) {
-        /* Make sure that we have a literal to write. */
-        if (s->lookahead == 0) {
-            fill_window(s);
-            if (s->lookahead == 0) {
-                if (flush == Z_NO_FLUSH)
-                    return need_more;
-                break;      /* flush the current block */
-            }
-        }
-
-        /* Output a literal byte */
-        s->match_length = 0;
-        Tracevv((stderr,"%c", s->window[s->strstart]));
-        _tr_tally_lit (s, s->window[s->strstart], bflush);
-        s->lookahead--;
-        s->strstart++;
-        if (bflush) FLUSH_BLOCK(s, 0);
-    }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/deflate.h b/src/external/OpenGR/3rdparty/cfitsio/zlib/deflate.h
deleted file mode 100644
index 6ac0a1eb1..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/deflate.h
+++ /dev/null
@@ -1,340 +0,0 @@
-/* deflate.h -- internal compression state
- * Copyright (C) 1995-2010 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-#ifndef DEFLATE_H
-#define DEFLATE_H
-
-#include "zutil.h"
-
-/* define NO_GZIP when compiling if you want to disable gzip header and
-   trailer creation by deflate().  NO_GZIP would be used to avoid linking in
-   the crc code when it is not needed.  For shared libraries, gzip encoding
-   should be left enabled. */
-#ifndef NO_GZIP
-#  define GZIP
-#endif
-
-/* ===========================================================================
- * Internal compression state.
- */
-
-#define LENGTH_CODES 29
-/* number of length codes, not counting the special END_BLOCK code */
-
-#define LITERALS  256
-/* number of literal bytes 0..255 */
-
-#define L_CODES (LITERALS+1+LENGTH_CODES)
-/* number of Literal or Length codes, including the END_BLOCK code */
-
-#define D_CODES   30
-/* number of distance codes */
-
-#define BL_CODES  19
-/* number of codes used to transfer the bit lengths */
-
-#define HEAP_SIZE (2*L_CODES+1)
-/* maximum heap size */
-
-#define MAX_BITS 15
-/* All codes must not exceed MAX_BITS bits */
-
-#define INIT_STATE    42
-#define EXTRA_STATE   69
-#define NAME_STATE    73
-#define COMMENT_STATE 91
-#define HCRC_STATE   103
-#define BUSY_STATE   113
-#define FINISH_STATE 666
-/* Stream status */
-
-
-/* Data structure describing a single value and its code string. */
-typedef struct ct_data_s {
-    union {
-        ush  freq;       /* frequency count */
-        ush  code;       /* bit string */
-    } fc;
-    union {
-        ush  dad;        /* father node in Huffman tree */
-        ush  len;        /* length of bit string */
-    } dl;
-} FAR ct_data;
-
-#define Freq fc.freq
-#define Code fc.code
-#define Dad  dl.dad
-#define Len  dl.len
-
-typedef struct static_tree_desc_s  static_tree_desc;
-
-typedef struct tree_desc_s {
-    ct_data *dyn_tree;           /* the dynamic tree */
-    int     max_code;            /* largest code with non zero frequency */
-    static_tree_desc *stat_desc; /* the corresponding static tree */
-} FAR tree_desc;
-
-typedef ush Pos;
-typedef Pos FAR Posf;
-typedef unsigned IPos;
-
-/* A Pos is an index in the character window. We use short instead of int to
- * save space in the various tables. IPos is used only for parameter passing.
- */
-
-typedef struct internal_state {
-    z_streamp strm;      /* pointer back to this zlib stream */
-    int   status;        /* as the name implies */
-    Bytef *pending_buf;  /* output still pending */
-    ulg   pending_buf_size; /* size of pending_buf */
-    Bytef *pending_out;  /* next pending byte to output to the stream */
-    uInt   pending;      /* nb of bytes in the pending buffer */
-    int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
-    gz_headerp  gzhead;  /* gzip header information to write */
-    uInt   gzindex;      /* where in extra, name, or comment */
-    Byte  method;        /* STORED (for zip only) or DEFLATED */
-    int   last_flush;    /* value of flush param for previous deflate call */
-
-                /* used by deflate.c: */
-
-    uInt  w_size;        /* LZ77 window size (32K by default) */
-    uInt  w_bits;        /* log2(w_size)  (8..16) */
-    uInt  w_mask;        /* w_size - 1 */
-
-    Bytef *window;
-    /* Sliding window. Input bytes are read into the second half of the window,
-     * and move to the first half later to keep a dictionary of at least wSize
-     * bytes. With this organization, matches are limited to a distance of
-     * wSize-MAX_MATCH bytes, but this ensures that IO is always
-     * performed with a length multiple of the block size. Also, it limits
-     * the window size to 64K, which is quite useful on MSDOS.
-     * To do: use the user input buffer as sliding window.
-     */
-
-    ulg window_size;
-    /* Actual size of window: 2*wSize, except when the user input buffer
-     * is directly used as sliding window.
-     */
-
-    Posf *prev;
-    /* Link to older string with same hash index. To limit the size of this
-     * array to 64K, this link is maintained only for the last 32K strings.
-     * An index in this array is thus a window index modulo 32K.
-     */
-
-    Posf *head; /* Heads of the hash chains or NIL. */
-
-    uInt  ins_h;          /* hash index of string to be inserted */
-    uInt  hash_size;      /* number of elements in hash table */
-    uInt  hash_bits;      /* log2(hash_size) */
-    uInt  hash_mask;      /* hash_size-1 */
-
-    uInt  hash_shift;
-    /* Number of bits by which ins_h must be shifted at each input
-     * step. It must be such that after MIN_MATCH steps, the oldest
-     * byte no longer takes part in the hash key, that is:
-     *   hash_shift * MIN_MATCH >= hash_bits
-     */
-
-    long block_start;
-    /* Window position at the beginning of the current output block. Gets
-     * negative when the window is moved backwards.
-     */
-
-    uInt match_length;           /* length of best match */
-    IPos prev_match;             /* previous match */
-    int match_available;         /* set if previous match exists */
-    uInt strstart;               /* start of string to insert */
-    uInt match_start;            /* start of matching string */
-    uInt lookahead;              /* number of valid bytes ahead in window */
-
-    uInt prev_length;
-    /* Length of the best match at previous step. Matches not greater than this
-     * are discarded. This is used in the lazy match evaluation.
-     */
-
-    uInt max_chain_length;
-    /* To speed up deflation, hash chains are never searched beyond this
-     * length.  A higher limit improves compression ratio but degrades the
-     * speed.
-     */
-
-    uInt max_lazy_match;
-    /* Attempt to find a better match only when the current match is strictly
-     * smaller than this value. This mechanism is used only for compression
-     * levels >= 4.
-     */
-#   define max_insert_length  max_lazy_match
-    /* Insert new strings in the hash table only if the match length is not
-     * greater than this length. This saves time but degrades compression.
-     * max_insert_length is used only for compression levels <= 3.
-     */
-
-    int level;    /* compression level (1..9) */
-    int strategy; /* favor or force Huffman coding*/
-
-    uInt good_match;
-    /* Use a faster search when the previous match is longer than this */
-
-    int nice_match; /* Stop searching when current match exceeds this */
-
-                /* used by trees.c: */
-    /* Didn't use ct_data typedef below to supress compiler warning */
-    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
-    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
-    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
-
-    struct tree_desc_s l_desc;               /* desc. for literal tree */
-    struct tree_desc_s d_desc;               /* desc. for distance tree */
-    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
-
-    ush bl_count[MAX_BITS+1];
-    /* number of codes at each bit length for an optimal tree */
-
-    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
-    int heap_len;               /* number of elements in the heap */
-    int heap_max;               /* element of largest frequency */
-    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
-     * The same heap array is used to build all trees.
-     */
-
-    uch depth[2*L_CODES+1];
-    /* Depth of each subtree used as tie breaker for trees of equal frequency
-     */
-
-    uchf *l_buf;          /* buffer for literals or lengths */
-
-    uInt  lit_bufsize;
-    /* Size of match buffer for literals/lengths.  There are 4 reasons for
-     * limiting lit_bufsize to 64K:
-     *   - frequencies can be kept in 16 bit counters
-     *   - if compression is not successful for the first block, all input
-     *     data is still in the window so we can still emit a stored block even
-     *     when input comes from standard input.  (This can also be done for
-     *     all blocks if lit_bufsize is not greater than 32K.)
-     *   - if compression is not successful for a file smaller than 64K, we can
-     *     even emit a stored file instead of a stored block (saving 5 bytes).
-     *     This is applicable only for zip (not gzip or zlib).
-     *   - creating new Huffman trees less frequently may not provide fast
-     *     adaptation to changes in the input data statistics. (Take for
-     *     example a binary file with poorly compressible code followed by
-     *     a highly compressible string table.) Smaller buffer sizes give
-     *     fast adaptation but have of course the overhead of transmitting
-     *     trees more frequently.
-     *   - I can't count above 4
-     */
-
-    uInt last_lit;      /* running index in l_buf */
-
-    ushf *d_buf;
-    /* Buffer for distances. To simplify the code, d_buf and l_buf have
-     * the same number of elements. To use different lengths, an extra flag
-     * array would be necessary.
-     */
-
-    ulg opt_len;        /* bit length of current block with optimal trees */
-    ulg static_len;     /* bit length of current block with static trees */
-    uInt matches;       /* number of string matches in current block */
-    int last_eob_len;   /* bit length of EOB code for last block */
-
-#ifdef DEBUG
-    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
-    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
-#endif
-
-    ush bi_buf;
-    /* Output buffer. bits are inserted starting at the bottom (least
-     * significant bits).
-     */
-    int bi_valid;
-    /* Number of valid bits in bi_buf.  All bits above the last valid bit
-     * are always zero.
-     */
-
-    ulg high_water;
-    /* High water mark offset in window for initialized bytes -- bytes above
-     * this are set to zero in order to avoid memory check warnings when
-     * longest match routines access bytes past the input.  This is then
-     * updated to the new high water mark.
-     */
-
-} FAR deflate_state;
-
-/* Output a byte on the stream.
- * IN assertion: there is enough room in pending_buf.
- */
-#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
-
-
-#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
-/* Minimum amount of lookahead, except at the end of the input file.
- * See deflate.c for comments about the MIN_MATCH+1.
- */
-
-#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
-/* In order to simplify the code, particularly on 16 bit machines, match
- * distances are limited to MAX_DIST instead of WSIZE.
- */
-
-#define WIN_INIT MAX_MATCH
-/* Number of bytes after end of data in window to initialize in order to avoid
-   memory checker errors from longest match routines */
-
-        /* in trees.c */
-void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
-int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
-void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
-                        ulg stored_len, int last));
-void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
-void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
-                        ulg stored_len, int last));
-
-#define d_code(dist) \
-   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
-/* Mapping from a distance to a distance code. dist is the distance - 1 and
- * must not have side effects. _dist_code[256] and _dist_code[257] are never
- * used.
- */
-
-#ifndef DEBUG
-/* Inline versions of _tr_tally for speed: */
-
-#if defined(GEN_TREES_H) || !defined(STDC)
-  extern uch ZLIB_INTERNAL _length_code[];
-  extern uch ZLIB_INTERNAL _dist_code[];
-#else
-  extern const uch ZLIB_INTERNAL _length_code[];
-  extern const uch ZLIB_INTERNAL _dist_code[];
-#endif
-
-# define _tr_tally_lit(s, c, flush) \
-  { uch cc = (c); \
-    s->d_buf[s->last_lit] = 0; \
-    s->l_buf[s->last_lit++] = cc; \
-    s->dyn_ltree[cc].Freq++; \
-    flush = (s->last_lit == s->lit_bufsize-1); \
-   }
-# define _tr_tally_dist(s, distance, length, flush) \
-  { uch len = (length); \
-    ush dist = (distance); \
-    s->d_buf[s->last_lit] = dist; \
-    s->l_buf[s->last_lit++] = len; \
-    dist--; \
-    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
-    s->dyn_dtree[d_code(dist)].Freq++; \
-    flush = (s->last_lit == s->lit_bufsize-1); \
-  }
-#else
-# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
-# define _tr_tally_dist(s, distance, length, flush) \
-              flush = _tr_tally(s, distance, length)
-#endif
-
-#endif /* DEFLATE_H */
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/infback.c b/src/external/OpenGR/3rdparty/cfitsio/zlib/infback.c
deleted file mode 100644
index af3a8c965..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/infback.c
+++ /dev/null
@@ -1,632 +0,0 @@
-/* infback.c -- inflate using a call-back interface
- * Copyright (C) 1995-2009 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
-   This code is largely copied from inflate.c.  Normally either infback.o or
-   inflate.o would be linked into an application--not both.  The interface
-   with inffast.c is retained so that optimized assembler-coded versions of
-   inflate_fast() can be used with either inflate.c or infback.c.
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-#include "inflate.h"
-#include "inffast.h"
-
-/* function prototypes */
-local void fixedtables OF((struct inflate_state FAR *state));
-
-/*
-   strm provides memory allocation functions in zalloc and zfree, or
-   Z_NULL to use the library memory allocation functions.
-
-   windowBits is in the range 8..15, and window is a user-supplied
-   window and output buffer that is 2**windowBits bytes.
- */
-int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
-z_streamp strm;
-int windowBits;
-unsigned char FAR *window;
-const char *version;
-int stream_size;
-{
-    struct inflate_state FAR *state;
-
-    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
-        stream_size != (int)(sizeof(z_stream)))
-        return Z_VERSION_ERROR;
-    if (strm == Z_NULL || window == Z_NULL ||
-        windowBits < 8 || windowBits > 15)
-        return Z_STREAM_ERROR;
-    strm->msg = Z_NULL;                 /* in case we return an error */
-    if (strm->zalloc == (alloc_func)0) {
-        strm->zalloc = zcalloc;
-        strm->opaque = (voidpf)0;
-    }
-    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
-    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
-                                               sizeof(struct inflate_state));
-    if (state == Z_NULL) return Z_MEM_ERROR;
-    Tracev((stderr, "inflate: allocated\n"));
-    strm->state = (struct internal_state FAR *)state;
-    state->dmax = 32768U;
-    state->wbits = windowBits;
-    state->wsize = 1U << windowBits;
-    state->window = window;
-    state->wnext = 0;
-    state->whave = 0;
-    return Z_OK;
-}
-
-/*
-   Return state with length and distance decoding tables and index sizes set to
-   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
-   If BUILDFIXED is defined, then instead this routine builds the tables the
-   first time it's called, and returns those tables the first time and
-   thereafter.  This reduces the size of the code by about 2K bytes, in
-   exchange for a little execution time.  However, BUILDFIXED should not be
-   used for threaded applications, since the rewriting of the tables and virgin
-   may not be thread-safe.
- */
-local void fixedtables(state)
-struct inflate_state FAR *state;
-{
-#ifdef BUILDFIXED
-    static int virgin = 1;
-    static code *lenfix, *distfix;
-    static code fixed[544];
-
-    /* build fixed huffman tables if first call (may not be thread safe) */
-    if (virgin) {
-        unsigned sym, bits;
-        static code *next;
-
-        /* literal/length table */
-        sym = 0;
-        while (sym < 144) state->lens[sym++] = 8;
-        while (sym < 256) state->lens[sym++] = 9;
-        while (sym < 280) state->lens[sym++] = 7;
-        while (sym < 288) state->lens[sym++] = 8;
-        next = fixed;
-        lenfix = next;
-        bits = 9;
-        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
-
-        /* distance table */
-        sym = 0;
-        while (sym < 32) state->lens[sym++] = 5;
-        distfix = next;
-        bits = 5;
-        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
-
-        /* do this just once */
-        virgin = 0;
-    }
-#else /* !BUILDFIXED */
-#   include "inffixed.h"
-#endif /* BUILDFIXED */
-    state->lencode = lenfix;
-    state->lenbits = 9;
-    state->distcode = distfix;
-    state->distbits = 5;
-}
-
-/* Macros for inflateBack(): */
-
-/* Load returned state from inflate_fast() */
-#define LOAD() \
-    do { \
-        put = strm->next_out; \
-        left = strm->avail_out; \
-        next = strm->next_in; \
-        have = strm->avail_in; \
-        hold = state->hold; \
-        bits = state->bits; \
-    } while (0)
-
-/* Set state from registers for inflate_fast() */
-#define RESTORE() \
-    do { \
-        strm->next_out = put; \
-        strm->avail_out = left; \
-        strm->next_in = next; \
-        strm->avail_in = have; \
-        state->hold = hold; \
-        state->bits = bits; \
-    } while (0)
-
-/* Clear the input bit accumulator */
-#define INITBITS() \
-    do { \
-        hold = 0; \
-        bits = 0; \
-    } while (0)
-
-/* Assure that some input is available.  If input is requested, but denied,
-   then return a Z_BUF_ERROR from inflateBack(). */
-#define PULL() \
-    do { \
-        if (have == 0) { \
-            have = in(in_desc, &next); \
-            if (have == 0) { \
-                next = Z_NULL; \
-                ret = Z_BUF_ERROR; \
-                goto inf_leave; \
-            } \
-        } \
-    } while (0)
-
-/* Get a byte of input into the bit accumulator, or return from inflateBack()
-   with an error if there is no input available. */
-#define PULLBYTE() \
-    do { \
-        PULL(); \
-        have--; \
-        hold += (unsigned long)(*next++) << bits; \
-        bits += 8; \
-    } while (0)
-
-/* Assure that there are at least n bits in the bit accumulator.  If there is
-   not enough available input to do that, then return from inflateBack() with
-   an error. */
-#define NEEDBITS(n) \
-    do { \
-        while (bits < (unsigned)(n)) \
-            PULLBYTE(); \
-    } while (0)
-
-/* Return the low n bits of the bit accumulator (n < 16) */
-#define BITS(n) \
-    ((unsigned)hold & ((1U << (n)) - 1))
-
-/* Remove n bits from the bit accumulator */
-#define DROPBITS(n) \
-    do { \
-        hold >>= (n); \
-        bits -= (unsigned)(n); \
-    } while (0)
-
-/* Remove zero to seven bits as needed to go to a byte boundary */
-#define BYTEBITS() \
-    do { \
-        hold >>= bits & 7; \
-        bits -= bits & 7; \
-    } while (0)
-
-/* Assure that some output space is available, by writing out the window
-   if it's full.  If the write fails, return from inflateBack() with a
-   Z_BUF_ERROR. */
-#define ROOM() \
-    do { \
-        if (left == 0) { \
-            put = state->window; \
-            left = state->wsize; \
-            state->whave = left; \
-            if (out(out_desc, put, left)) { \
-                ret = Z_BUF_ERROR; \
-                goto inf_leave; \
-            } \
-        } \
-    } while (0)
-
-/*
-   strm provides the memory allocation functions and window buffer on input,
-   and provides information on the unused input on return.  For Z_DATA_ERROR
-   returns, strm will also provide an error message.
-
-   in() and out() are the call-back input and output functions.  When
-   inflateBack() needs more input, it calls in().  When inflateBack() has
-   filled the window with output, or when it completes with data in the
-   window, it calls out() to write out the data.  The application must not
-   change the provided input until in() is called again or inflateBack()
-   returns.  The application must not change the window/output buffer until
-   inflateBack() returns.
-
-   in() and out() are called with a descriptor parameter provided in the
-   inflateBack() call.  This parameter can be a structure that provides the
-   information required to do the read or write, as well as accumulated
-   information on the input and output such as totals and check values.
-
-   in() should return zero on failure.  out() should return non-zero on
-   failure.  If either in() or out() fails, than inflateBack() returns a
-   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
-   was in() or out() that caused in the error.  Otherwise,  inflateBack()
-   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
-   error, or Z_MEM_ERROR if it could not allocate memory for the state.
-   inflateBack() can also return Z_STREAM_ERROR if the input parameters
-   are not correct, i.e. strm is Z_NULL or the state was not initialized.
- */
-int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
-z_streamp strm;
-in_func in;
-void FAR *in_desc;
-out_func out;
-void FAR *out_desc;
-{
-    struct inflate_state FAR *state;
-    unsigned char FAR *next;    /* next input */
-    unsigned char FAR *put;     /* next output */
-    unsigned have, left;        /* available input and output */
-    unsigned long hold;         /* bit buffer */
-    unsigned bits;              /* bits in bit buffer */
-    unsigned copy;              /* number of stored or match bytes to copy */
-    unsigned char FAR *from;    /* where to copy match bytes from */
-    code here;                  /* current decoding table entry */
-    code last;                  /* parent table entry */
-    unsigned len;               /* length to copy for repeats, bits to drop */
-    int ret;                    /* return code */
-    static const unsigned short order[19] = /* permutation of code lengths */
-        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-    /* Check that the strm exists and that the state was initialized */
-    if (strm == Z_NULL || strm->state == Z_NULL)
-        return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-
-    /* Reset the state */
-    strm->msg = Z_NULL;
-    state->mode = TYPE;
-    state->last = 0;
-    state->whave = 0;
-    next = strm->next_in;
-    have = next != Z_NULL ? strm->avail_in : 0;
-    hold = 0;
-    bits = 0;
-    put = state->window;
-    left = state->wsize;
-
-    /* Inflate until end of block marked as last */
-    for (;;)
-        switch (state->mode) {
-        case TYPE:
-            /* determine and dispatch block type */
-            if (state->last) {
-                BYTEBITS();
-                state->mode = DONE;
-                break;
-            }
-            NEEDBITS(3);
-            state->last = BITS(1);
-            DROPBITS(1);
-            switch (BITS(2)) {
-            case 0:                             /* stored block */
-                Tracev((stderr, "inflate:     stored block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = STORED;
-                break;
-            case 1:                             /* fixed block */
-                fixedtables(state);
-                Tracev((stderr, "inflate:     fixed codes block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = LEN;              /* decode codes */
-                break;
-            case 2:                             /* dynamic block */
-                Tracev((stderr, "inflate:     dynamic codes block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = TABLE;
-                break;
-            case 3:
-                strm->msg = (char *)"invalid block type";
-                state->mode = BAD;
-            }
-            DROPBITS(2);
-            break;
-
-        case STORED:
-            /* get and verify stored block length */
-            BYTEBITS();                         /* go to byte boundary */
-            NEEDBITS(32);
-            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
-                strm->msg = (char *)"invalid stored block lengths";
-                state->mode = BAD;
-                break;
-            }
-            state->length = (unsigned)hold & 0xffff;
-            Tracev((stderr, "inflate:       stored length %u\n",
-                    state->length));
-            INITBITS();
-
-            /* copy stored block from input to output */
-            while (state->length != 0) {
-                copy = state->length;
-                PULL();
-                ROOM();
-                if (copy > have) copy = have;
-                if (copy > left) copy = left;
-                zmemcpy(put, next, copy);
-                have -= copy;
-                next += copy;
-                left -= copy;
-                put += copy;
-                state->length -= copy;
-            }
-            Tracev((stderr, "inflate:       stored end\n"));
-            state->mode = TYPE;
-            break;
-
-        case TABLE:
-            /* get dynamic table entries descriptor */
-            NEEDBITS(14);
-            state->nlen = BITS(5) + 257;
-            DROPBITS(5);
-            state->ndist = BITS(5) + 1;
-            DROPBITS(5);
-            state->ncode = BITS(4) + 4;
-            DROPBITS(4);
-#ifndef PKZIP_BUG_WORKAROUND
-            if (state->nlen > 286 || state->ndist > 30) {
-                strm->msg = (char *)"too many length or distance symbols";
-                state->mode = BAD;
-                break;
-            }
-#endif
-            Tracev((stderr, "inflate:       table sizes ok\n"));
-
-            /* get code length code lengths (not a typo) */
-            state->have = 0;
-            while (state->have < state->ncode) {
-                NEEDBITS(3);
-                state->lens[order[state->have++]] = (unsigned short)BITS(3);
-                DROPBITS(3);
-            }
-            while (state->have < 19)
-                state->lens[order[state->have++]] = 0;
-            state->next = state->codes;
-            state->lencode = (code const FAR *)(state->next);
-            state->lenbits = 7;
-            ret = inflate_table(CODES, state->lens, 19, &(state->next),
-                                &(state->lenbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid code lengths set";
-                state->mode = BAD;
-                break;
-            }
-            Tracev((stderr, "inflate:       code lengths ok\n"));
-
-            /* get length and distance code code lengths */
-            state->have = 0;
-            while (state->have < state->nlen + state->ndist) {
-                for (;;) {
-                    here = state->lencode[BITS(state->lenbits)];
-                    if ((unsigned)(here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                if (here.val < 16) {
-                    NEEDBITS(here.bits);
-                    DROPBITS(here.bits);
-                    state->lens[state->have++] = here.val;
-                }
-                else {
-                    if (here.val == 16) {
-                        NEEDBITS(here.bits + 2);
-                        DROPBITS(here.bits);
-                        if (state->have == 0) {
-                            strm->msg = (char *)"invalid bit length repeat";
-                            state->mode = BAD;
-                            break;
-                        }
-                        len = (unsigned)(state->lens[state->have - 1]);
-                        copy = 3 + BITS(2);
-                        DROPBITS(2);
-                    }
-                    else if (here.val == 17) {
-                        NEEDBITS(here.bits + 3);
-                        DROPBITS(here.bits);
-                        len = 0;
-                        copy = 3 + BITS(3);
-                        DROPBITS(3);
-                    }
-                    else {
-                        NEEDBITS(here.bits + 7);
-                        DROPBITS(here.bits);
-                        len = 0;
-                        copy = 11 + BITS(7);
-                        DROPBITS(7);
-                    }
-                    if (state->have + copy > state->nlen + state->ndist) {
-                        strm->msg = (char *)"invalid bit length repeat";
-                        state->mode = BAD;
-                        break;
-                    }
-                    while (copy--)
-                        state->lens[state->have++] = (unsigned short)len;
-                }
-            }
-
-            /* handle error breaks in while */
-            if (state->mode == BAD) break;
-
-            /* check for end-of-block code (better have one) */
-            if (state->lens[256] == 0) {
-                strm->msg = (char *)"invalid code -- missing end-of-block";
-                state->mode = BAD;
-                break;
-            }
-
-            /* build code tables -- note: do not change the lenbits or distbits
-               values here (9 and 6) without reading the comments in inftrees.h
-               concerning the ENOUGH constants, which depend on those values */
-            state->next = state->codes;
-            state->lencode = (code const FAR *)(state->next);
-            state->lenbits = 9;
-            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
-                                &(state->lenbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid literal/lengths set";
-                state->mode = BAD;
-                break;
-            }
-            state->distcode = (code const FAR *)(state->next);
-            state->distbits = 6;
-            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
-                            &(state->next), &(state->distbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid distances set";
-                state->mode = BAD;
-                break;
-            }
-            Tracev((stderr, "inflate:       codes ok\n"));
-            state->mode = LEN;
-
-        case LEN:
-            /* use inflate_fast() if we have enough input and output */
-            if (have >= 6 && left >= 258) {
-                RESTORE();
-                if (state->whave < state->wsize)
-                    state->whave = state->wsize - left;
-                inflate_fast(strm, state->wsize);
-                LOAD();
-                break;
-            }
-
-            /* get a literal, length, or end-of-block code */
-            for (;;) {
-                here = state->lencode[BITS(state->lenbits)];
-                if ((unsigned)(here.bits) <= bits) break;
-                PULLBYTE();
-            }
-            if (here.op && (here.op & 0xf0) == 0) {
-                last = here;
-                for (;;) {
-                    here = state->lencode[last.val +
-                            (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                DROPBITS(last.bits);
-            }
-            DROPBITS(here.bits);
-            state->length = (unsigned)here.val;
-
-            /* process literal */
-            if (here.op == 0) {
-                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
-                        "inflate:         literal '%c'\n" :
-                        "inflate:         literal 0x%02x\n", here.val));
-                ROOM();
-                *put++ = (unsigned char)(state->length);
-                left--;
-                state->mode = LEN;
-                break;
-            }
-
-            /* process end of block */
-            if (here.op & 32) {
-                Tracevv((stderr, "inflate:         end of block\n"));
-                state->mode = TYPE;
-                break;
-            }
-
-            /* invalid code */
-            if (here.op & 64) {
-                strm->msg = (char *)"invalid literal/length code";
-                state->mode = BAD;
-                break;
-            }
-
-            /* length code -- get extra bits, if any */
-            state->extra = (unsigned)(here.op) & 15;
-            if (state->extra != 0) {
-                NEEDBITS(state->extra);
-                state->length += BITS(state->extra);
-                DROPBITS(state->extra);
-            }
-            Tracevv((stderr, "inflate:         length %u\n", state->length));
-
-            /* get distance code */
-            for (;;) {
-                here = state->distcode[BITS(state->distbits)];
-                if ((unsigned)(here.bits) <= bits) break;
-                PULLBYTE();
-            }
-            if ((here.op & 0xf0) == 0) {
-                last = here;
-                for (;;) {
-                    here = state->distcode[last.val +
-                            (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                DROPBITS(last.bits);
-            }
-            DROPBITS(here.bits);
-            if (here.op & 64) {
-                strm->msg = (char *)"invalid distance code";
-                state->mode = BAD;
-                break;
-            }
-            state->offset = (unsigned)here.val;
-
-            /* get distance extra bits, if any */
-            state->extra = (unsigned)(here.op) & 15;
-            if (state->extra != 0) {
-                NEEDBITS(state->extra);
-                state->offset += BITS(state->extra);
-                DROPBITS(state->extra);
-            }
-            if (state->offset > state->wsize - (state->whave < state->wsize ?
-                                                left : 0)) {
-                strm->msg = (char *)"invalid distance too far back";
-                state->mode = BAD;
-                break;
-            }
-            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
-
-            /* copy match from window to output */
-            do {
-                ROOM();
-                copy = state->wsize - state->offset;
-                if (copy < left) {
-                    from = put + copy;
-                    copy = left - copy;
-                }
-                else {
-                    from = put - state->offset;
-                    copy = left;
-                }
-                if (copy > state->length) copy = state->length;
-                state->length -= copy;
-                left -= copy;
-                do {
-                    *put++ = *from++;
-                } while (--copy);
-            } while (state->length != 0);
-            break;
-
-        case DONE:
-            /* inflate stream terminated properly -- write leftover output */
-            ret = Z_STREAM_END;
-            if (left < state->wsize) {
-                if (out(out_desc, state->window, state->wsize - left))
-                    ret = Z_BUF_ERROR;
-            }
-            goto inf_leave;
-
-        case BAD:
-            ret = Z_DATA_ERROR;
-            goto inf_leave;
-
-        default:                /* can't happen, but makes compilers happy */
-            ret = Z_STREAM_ERROR;
-            goto inf_leave;
-        }
-
-    /* Return unused input */
-  inf_leave:
-    strm->next_in = next;
-    strm->avail_in = have;
-    return ret;
-}
-
-int ZEXPORT inflateBackEnd(strm)
-z_streamp strm;
-{
-    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
-        return Z_STREAM_ERROR;
-    ZFREE(strm, strm->state);
-    strm->state = Z_NULL;
-    Tracev((stderr, "inflate: end\n"));
-    return Z_OK;
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/inffast.c b/src/external/OpenGR/3rdparty/cfitsio/zlib/inffast.c
deleted file mode 100644
index 2f1d60b43..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/inffast.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/* inffast.c -- fast decoding
- * Copyright (C) 1995-2008, 2010 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-#include "inflate.h"
-#include "inffast.h"
-
-#ifndef ASMINF
-
-/* Allow machine dependent optimization for post-increment or pre-increment.
-   Based on testing to date,
-   Pre-increment preferred for:
-   - PowerPC G3 (Adler)
-   - MIPS R5000 (Randers-Pehrson)
-   Post-increment preferred for:
-   - none
-   No measurable difference:
-   - Pentium III (Anderson)
-   - M68060 (Nikl)
- */
-#ifdef POSTINC
-#  define OFF 0
-#  define PUP(a) *(a)++
-#else
-#  define OFF 1
-#  define PUP(a) *++(a)
-#endif
-
-/*
-   Decode literal, length, and distance codes and write out the resulting
-   literal and match bytes until either not enough input or output is
-   available, an end-of-block is encountered, or a data error is encountered.
-   When large enough input and output buffers are supplied to inflate(), for
-   example, a 16K input buffer and a 64K output buffer, more than 95% of the
-   inflate execution time is spent in this routine.
-
-   Entry assumptions:
-
-        state->mode == LEN
-        strm->avail_in >= 6
-        strm->avail_out >= 258
-        start >= strm->avail_out
-        state->bits < 8
-
-   On return, state->mode is one of:
-
-        LEN -- ran out of enough output space or enough available input
-        TYPE -- reached end of block code, inflate() to interpret next block
-        BAD -- error in block data
-
-   Notes:
-
-    - The maximum input bits used by a length/distance pair is 15 bits for the
-      length code, 5 bits for the length extra, 15 bits for the distance code,
-      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
-      Therefore if strm->avail_in >= 6, then there is enough input to avoid
-      checking for available input while decoding.
-
-    - The maximum bytes that a single length/distance pair can output is 258
-      bytes, which is the maximum length that can be coded.  inflate_fast()
-      requires strm->avail_out >= 258 for each loop to avoid checking for
-      output space.
- */
-void ZLIB_INTERNAL inflate_fast(strm, start)
-z_streamp strm;
-unsigned start;         /* inflate()'s starting value for strm->avail_out */
-{
-    struct inflate_state FAR *state;
-    unsigned char FAR *in;      /* local strm->next_in */
-    unsigned char FAR *last;    /* while in < last, enough input available */
-    unsigned char FAR *out;     /* local strm->next_out */
-    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
-    unsigned char FAR *end;     /* while out < end, enough space available */
-#ifdef INFLATE_STRICT
-    unsigned dmax;              /* maximum distance from zlib header */
-#endif
-    unsigned wsize;             /* window size or zero if not using window */
-    unsigned whave;             /* valid bytes in the window */
-    unsigned wnext;             /* window write index */
-    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
-    unsigned long hold;         /* local strm->hold */
-    unsigned bits;              /* local strm->bits */
-    code const FAR *lcode;      /* local strm->lencode */
-    code const FAR *dcode;      /* local strm->distcode */
-    unsigned lmask;             /* mask for first level of length codes */
-    unsigned dmask;             /* mask for first level of distance codes */
-    code here;                  /* retrieved table entry */
-    unsigned op;                /* code bits, operation, extra bits, or */
-                                /*  window position, window bytes to copy */
-    unsigned len;               /* match length, unused bytes */
-    unsigned dist;              /* match distance */
-    unsigned char FAR *from;    /* where to copy match from */
-
-    /* copy state to local variables */
-    state = (struct inflate_state FAR *)strm->state;
-    in = strm->next_in - OFF;
-    last = in + (strm->avail_in - 5);
-    out = strm->next_out - OFF;
-    beg = out - (start - strm->avail_out);
-    end = out + (strm->avail_out - 257);
-#ifdef INFLATE_STRICT
-    dmax = state->dmax;
-#endif
-    wsize = state->wsize;
-    whave = state->whave;
-    wnext = state->wnext;
-    window = state->window;
-    hold = state->hold;
-    bits = state->bits;
-    lcode = state->lencode;
-    dcode = state->distcode;
-    lmask = (1U << state->lenbits) - 1;
-    dmask = (1U << state->distbits) - 1;
-
-    /* decode literals and length/distances until end-of-block or not enough
-       input data or output space */
-    do {
-        if (bits < 15) {
-            hold += (unsigned long)(PUP(in)) << bits;
-            bits += 8;
-            hold += (unsigned long)(PUP(in)) << bits;
-            bits += 8;
-        }
-        here = lcode[hold & lmask];
-      dolen:
-        op = (unsigned)(here.bits);
-        hold >>= op;
-        bits -= op;
-        op = (unsigned)(here.op);
-        if (op == 0) {                          /* literal */
-            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
-                    "inflate:         literal '%c'\n" :
-                    "inflate:         literal 0x%02x\n", here.val));
-            PUP(out) = (unsigned char)(here.val);
-        }
-        else if (op & 16) {                     /* length base */
-            len = (unsigned)(here.val);
-            op &= 15;                           /* number of extra bits */
-            if (op) {
-                if (bits < op) {
-                    hold += (unsigned long)(PUP(in)) << bits;
-                    bits += 8;
-                }
-                len += (unsigned)hold & ((1U << op) - 1);
-                hold >>= op;
-                bits -= op;
-            }
-            Tracevv((stderr, "inflate:         length %u\n", len));
-            if (bits < 15) {
-                hold += (unsigned long)(PUP(in)) << bits;
-                bits += 8;
-                hold += (unsigned long)(PUP(in)) << bits;
-                bits += 8;
-            }
-            here = dcode[hold & dmask];
-          dodist:
-            op = (unsigned)(here.bits);
-            hold >>= op;
-            bits -= op;
-            op = (unsigned)(here.op);
-            if (op & 16) {                      /* distance base */
-                dist = (unsigned)(here.val);
-                op &= 15;                       /* number of extra bits */
-                if (bits < op) {
-                    hold += (unsigned long)(PUP(in)) << bits;
-                    bits += 8;
-                    if (bits < op) {
-                        hold += (unsigned long)(PUP(in)) << bits;
-                        bits += 8;
-                    }
-                }
-                dist += (unsigned)hold & ((1U << op) - 1);
-#ifdef INFLATE_STRICT
-                if (dist > dmax) {
-                    strm->msg = (char *)"invalid distance too far back";
-                    state->mode = BAD;
-                    break;
-                }
-#endif
-                hold >>= op;
-                bits -= op;
-                Tracevv((stderr, "inflate:         distance %u\n", dist));
-                op = (unsigned)(out - beg);     /* max distance in output */
-                if (dist > op) {                /* see if copy from window */
-                    op = dist - op;             /* distance back in window */
-                    if (op > whave) {
-                        if (state->sane) {
-                            strm->msg =
-                                (char *)"invalid distance too far back";
-                            state->mode = BAD;
-                            break;
-                        }
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
-                        if (len <= op - whave) {
-                            do {
-                                PUP(out) = 0;
-                            } while (--len);
-                            continue;
-                        }
-                        len -= op - whave;
-                        do {
-                            PUP(out) = 0;
-                        } while (--op > whave);
-                        if (op == 0) {
-                            from = out - dist;
-                            do {
-                                PUP(out) = PUP(from);
-                            } while (--len);
-                            continue;
-                        }
-#endif
-                    }
-                    from = window - OFF;
-                    if (wnext == 0) {           /* very common case */
-                        from += wsize - op;
-                        if (op < len) {         /* some from window */
-                            len -= op;
-                            do {
-                                PUP(out) = PUP(from);
-                            } while (--op);
-                            from = out - dist;  /* rest from output */
-                        }
-                    }
-                    else if (wnext < op) {      /* wrap around window */
-                        from += wsize + wnext - op;
-                        op -= wnext;
-                        if (op < len) {         /* some from end of window */
-                            len -= op;
-                            do {
-                                PUP(out) = PUP(from);
-                            } while (--op);
-                            from = window - OFF;
-                            if (wnext < len) {  /* some from start of window */
-                                op = wnext;
-                                len -= op;
-                                do {
-                                    PUP(out) = PUP(from);
-                                } while (--op);
-                                from = out - dist;      /* rest from output */
-                            }
-                        }
-                    }
-                    else {                      /* contiguous in window */
-                        from += wnext - op;
-                        if (op < len) {         /* some from window */
-                            len -= op;
-                            do {
-                                PUP(out) = PUP(from);
-                            } while (--op);
-                            from = out - dist;  /* rest from output */
-                        }
-                    }
-                    while (len > 2) {
-                        PUP(out) = PUP(from);
-                        PUP(out) = PUP(from);
-                        PUP(out) = PUP(from);
-                        len -= 3;
-                    }
-                    if (len) {
-                        PUP(out) = PUP(from);
-                        if (len > 1)
-                            PUP(out) = PUP(from);
-                    }
-                }
-                else {
-                    from = out - dist;          /* copy direct from output */
-                    do {                        /* minimum length is three */
-                        PUP(out) = PUP(from);
-                        PUP(out) = PUP(from);
-                        PUP(out) = PUP(from);
-                        len -= 3;
-                    } while (len > 2);
-                    if (len) {
-                        PUP(out) = PUP(from);
-                        if (len > 1)
-                            PUP(out) = PUP(from);
-                    }
-                }
-            }
-            else if ((op & 64) == 0) {          /* 2nd level distance code */
-                here = dcode[here.val + (hold & ((1U << op) - 1))];
-                goto dodist;
-            }
-            else {
-                strm->msg = (char *)"invalid distance code";
-                state->mode = BAD;
-                break;
-            }
-        }
-        else if ((op & 64) == 0) {              /* 2nd level length code */
-            here = lcode[here.val + (hold & ((1U << op) - 1))];
-            goto dolen;
-        }
-        else if (op & 32) {                     /* end-of-block */
-            Tracevv((stderr, "inflate:         end of block\n"));
-            state->mode = TYPE;
-            break;
-        }
-        else {
-            strm->msg = (char *)"invalid literal/length code";
-            state->mode = BAD;
-            break;
-        }
-    } while (in < last && out < end);
-
-    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
-    len = bits >> 3;
-    in -= len;
-    bits -= len << 3;
-    hold &= (1U << bits) - 1;
-
-    /* update state and return */
-    strm->next_in = in + OFF;
-    strm->next_out = out + OFF;
-    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
-    strm->avail_out = (unsigned)(out < end ?
-                                 257 + (end - out) : 257 - (out - end));
-    state->hold = hold;
-    state->bits = bits;
-    return;
-}
-
-/*
-   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
-   - Using bit fields for code structure
-   - Different op definition to avoid & for extra bits (do & for table bits)
-   - Three separate decoding do-loops for direct, window, and wnext == 0
-   - Special case for distance > 1 copies to do overlapped load and store copy
-   - Explicit branch predictions (based on measured branch probabilities)
-   - Deferring match copy and interspersed it with decoding subsequent codes
-   - Swapping literal/length else
-   - Swapping window/direct else
-   - Larger unrolled copy loops (three is about right)
-   - Moving len -= 3 statement into middle of loop
- */
-
-#endif /* !ASMINF */
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/inffast.h b/src/external/OpenGR/3rdparty/cfitsio/zlib/inffast.h
deleted file mode 100644
index e5c1aa4ca..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/inffast.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* inffast.h -- header to use inffast.c
- * Copyright (C) 1995-2003, 2010 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/inffixed.h b/src/external/OpenGR/3rdparty/cfitsio/zlib/inffixed.h
deleted file mode 100644
index 75ed4b597..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/inffixed.h
+++ /dev/null
@@ -1,94 +0,0 @@
-    /* inffixed.h -- table for decoding fixed codes
-     * Generated automatically by makefixed().
-     */
-
-    /* WARNING: this file should *not* be used by applications. It
-       is part of the implementation of the compression library and
-       is subject to change. Applications should only use zlib.h.
-     */
-
-    static const code lenfix[512] = {
-        {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
-        {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
-        {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
-        {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
-        {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
-        {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
-        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
-        {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
-        {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
-        {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
-        {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
-        {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
-        {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
-        {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
-        {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
-        {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
-        {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
-        {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
-        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
-        {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
-        {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
-        {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
-        {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
-        {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
-        {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
-        {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
-        {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
-        {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
-        {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
-        {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
-        {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
-        {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
-        {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
-        {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
-        {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
-        {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
-        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
-        {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
-        {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
-        {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
-        {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
-        {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
-        {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
-        {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
-        {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
-        {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
-        {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
-        {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
-        {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
-        {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
-        {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
-        {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
-        {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
-        {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
-        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
-        {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
-        {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
-        {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
-        {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
-        {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
-        {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
-        {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
-        {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
-        {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
-        {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
-        {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
-        {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
-        {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
-        {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
-        {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
-        {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
-        {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
-        {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
-        {0,9,255}
-    };
-
-    static const code distfix[32] = {
-        {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
-        {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
-        {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
-        {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
-        {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
-        {22,5,193},{64,5,0}
-    };
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/inflate.c b/src/external/OpenGR/3rdparty/cfitsio/zlib/inflate.c
deleted file mode 100644
index a8431abea..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/inflate.c
+++ /dev/null
@@ -1,1480 +0,0 @@
-/* inflate.c -- zlib decompression
- * Copyright (C) 1995-2010 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- * Change history:
- *
- * 1.2.beta0    24 Nov 2002
- * - First version -- complete rewrite of inflate to simplify code, avoid
- *   creation of window when not needed, minimize use of window when it is
- *   needed, make inffast.c even faster, implement gzip decoding, and to
- *   improve code readability and style over the previous zlib inflate code
- *
- * 1.2.beta1    25 Nov 2002
- * - Use pointers for available input and output checking in inffast.c
- * - Remove input and output counters in inffast.c
- * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
- * - Remove unnecessary second byte pull from length extra in inffast.c
- * - Unroll direct copy to three copies per loop in inffast.c
- *
- * 1.2.beta2    4 Dec 2002
- * - Change external routine names to reduce potential conflicts
- * - Correct filename to inffixed.h for fixed tables in inflate.c
- * - Make hbuf[] unsigned char to match parameter type in inflate.c
- * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
- *   to avoid negation problem on Alphas (64 bit) in inflate.c
- *
- * 1.2.beta3    22 Dec 2002
- * - Add comments on state->bits assertion in inffast.c
- * - Add comments on op field in inftrees.h
- * - Fix bug in reuse of allocated window after inflateReset()
- * - Remove bit fields--back to byte structure for speed
- * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
- * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
- * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
- * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
- * - Use local copies of stream next and avail values, as well as local bit
- *   buffer and bit count in inflate()--for speed when inflate_fast() not used
- *
- * 1.2.beta4    1 Jan 2003
- * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
- * - Move a comment on output buffer sizes from inffast.c to inflate.c
- * - Add comments in inffast.c to introduce the inflate_fast() routine
- * - Rearrange window copies in inflate_fast() for speed and simplification
- * - Unroll last copy for window match in inflate_fast()
- * - Use local copies of window variables in inflate_fast() for speed
- * - Pull out common wnext == 0 case for speed in inflate_fast()
- * - Make op and len in inflate_fast() unsigned for consistency
- * - Add FAR to lcode and dcode declarations in inflate_fast()
- * - Simplified bad distance check in inflate_fast()
- * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
- *   source file infback.c to provide a call-back interface to inflate for
- *   programs like gzip and unzip -- uses window as output buffer to avoid
- *   window copying
- *
- * 1.2.beta5    1 Jan 2003
- * - Improved inflateBack() interface to allow the caller to provide initial
- *   input in strm.
- * - Fixed stored blocks bug in inflateBack()
- *
- * 1.2.beta6    4 Jan 2003
- * - Added comments in inffast.c on effectiveness of POSTINC
- * - Typecasting all around to reduce compiler warnings
- * - Changed loops from while (1) or do {} while (1) to for (;;), again to
- *   make compilers happy
- * - Changed type of window in inflateBackInit() to unsigned char *
- *
- * 1.2.beta7    27 Jan 2003
- * - Changed many types to unsigned or unsigned short to avoid warnings
- * - Added inflateCopy() function
- *
- * 1.2.0        9 Mar 2003
- * - Changed inflateBack() interface to provide separate opaque descriptors
- *   for the in() and out() functions
- * - Changed inflateBack() argument and in_func typedef to swap the length
- *   and buffer address return values for the input function
- * - Check next_in and next_out for Z_NULL on entry to inflate()
- *
- * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-#include "inflate.h"
-#include "inffast.h"
-
-#ifdef MAKEFIXED
-#  ifndef BUILDFIXED
-#    define BUILDFIXED
-#  endif
-#endif
-
-/* function prototypes */
-local void fixedtables OF((struct inflate_state FAR *state));
-local int updatewindow OF((z_streamp strm, unsigned out));
-#ifdef BUILDFIXED
-   void makefixed OF((void));
-#endif
-local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
-                              unsigned len));
-
-int ZEXPORT inflateReset(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    strm->total_in = strm->total_out = state->total = 0;
-    strm->msg = Z_NULL;
-    strm->adler = 1;        /* to support ill-conceived Java test suite */
-    state->mode = HEAD;
-    state->last = 0;
-    state->havedict = 0;
-    state->dmax = 32768U;
-    state->head = Z_NULL;
-    state->wsize = 0;
-    state->whave = 0;
-    state->wnext = 0;
-    state->hold = 0;
-    state->bits = 0;
-    state->lencode = state->distcode = state->next = state->codes;
-    state->sane = 1;
-    state->back = -1;
-    Tracev((stderr, "inflate: reset\n"));
-    return Z_OK;
-}
-
-int ZEXPORT inflateReset2(strm, windowBits)
-z_streamp strm;
-int windowBits;
-{
-    int wrap;
-    struct inflate_state FAR *state;
-
-    /* get the state */
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-
-    /* extract wrap request from windowBits parameter */
-    if (windowBits < 0) {
-        wrap = 0;
-        windowBits = -windowBits;
-    }
-    else {
-        wrap = (windowBits >> 4) + 1;
-#ifdef GUNZIP
-        if (windowBits < 48)
-            windowBits &= 15;
-#endif
-    }
-
-    /* set number of window bits, free window if different */
-    if (windowBits && (windowBits < 8 || windowBits > 15))
-        return Z_STREAM_ERROR;
-    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
-        ZFREE(strm, state->window);
-        state->window = Z_NULL;
-    }
-
-    /* update state and reset the rest of it */
-    state->wrap = wrap;
-    state->wbits = (unsigned)windowBits;
-    return inflateReset(strm);
-}
-
-int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
-z_streamp strm;
-int windowBits;
-const char *version;
-int stream_size;
-{
-    int ret;
-    struct inflate_state FAR *state;
-
-    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
-        stream_size != (int)(sizeof(z_stream)))
-        return Z_VERSION_ERROR;
-    if (strm == Z_NULL) return Z_STREAM_ERROR;
-    strm->msg = Z_NULL;                 /* in case we return an error */
-    if (strm->zalloc == (alloc_func)0) {
-        strm->zalloc = zcalloc;
-        strm->opaque = (voidpf)0;
-    }
-    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
-    state = (struct inflate_state FAR *)
-            ZALLOC(strm, 1, sizeof(struct inflate_state));
-    if (state == Z_NULL) return Z_MEM_ERROR;
-    Tracev((stderr, "inflate: allocated\n"));
-    strm->state = (struct internal_state FAR *)state;
-    state->window = Z_NULL;
-    ret = inflateReset2(strm, windowBits);
-    if (ret != Z_OK) {
-        ZFREE(strm, state);
-        strm->state = Z_NULL;
-    }
-    return ret;
-}
-
-int ZEXPORT inflateInit_(strm, version, stream_size)
-z_streamp strm;
-const char *version;
-int stream_size;
-{
-    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
-}
-
-int ZEXPORT inflatePrime(strm, bits, value)
-z_streamp strm;
-int bits;
-int value;
-{
-    struct inflate_state FAR *state;
-
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (bits < 0) {
-        state->hold = 0;
-        state->bits = 0;
-        return Z_OK;
-    }
-    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
-    value &= (1L << bits) - 1;
-    state->hold += value << state->bits;
-    state->bits += bits;
-    return Z_OK;
-}
-
-/*
-   Return state with length and distance decoding tables and index sizes set to
-   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
-   If BUILDFIXED is defined, then instead this routine builds the tables the
-   first time it's called, and returns those tables the first time and
-   thereafter.  This reduces the size of the code by about 2K bytes, in
-   exchange for a little execution time.  However, BUILDFIXED should not be
-   used for threaded applications, since the rewriting of the tables and virgin
-   may not be thread-safe.
- */
-local void fixedtables(state)
-struct inflate_state FAR *state;
-{
-#ifdef BUILDFIXED
-    static int virgin = 1;
-    static code *lenfix, *distfix;
-    static code fixed[544];
-
-    /* build fixed huffman tables if first call (may not be thread safe) */
-    if (virgin) {
-        unsigned sym, bits;
-        static code *next;
-
-        /* literal/length table */
-        sym = 0;
-        while (sym < 144) state->lens[sym++] = 8;
-        while (sym < 256) state->lens[sym++] = 9;
-        while (sym < 280) state->lens[sym++] = 7;
-        while (sym < 288) state->lens[sym++] = 8;
-        next = fixed;
-        lenfix = next;
-        bits = 9;
-        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
-
-        /* distance table */
-        sym = 0;
-        while (sym < 32) state->lens[sym++] = 5;
-        distfix = next;
-        bits = 5;
-        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
-
-        /* do this just once */
-        virgin = 0;
-    }
-#else /* !BUILDFIXED */
-#   include "inffixed.h"
-#endif /* BUILDFIXED */
-    state->lencode = lenfix;
-    state->lenbits = 9;
-    state->distcode = distfix;
-    state->distbits = 5;
-}
-
-#ifdef MAKEFIXED
-#include 
-
-/*
-   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
-   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
-   those tables to stdout, which would be piped to inffixed.h.  A small program
-   can simply call makefixed to do this:
-
-    void makefixed(void);
-
-    int main(void)
-    {
-        makefixed();
-        return 0;
-    }
-
-   Then that can be linked with zlib built with MAKEFIXED defined and run:
-
-    a.out > inffixed.h
- */
-void makefixed()
-{
-    unsigned low, size;
-    struct inflate_state state;
-
-    fixedtables(&state);
-    puts("    /* inffixed.h -- table for decoding fixed codes");
-    puts("     * Generated automatically by makefixed().");
-    puts("     */");
-    puts("");
-    puts("    /* WARNING: this file should *not* be used by applications.");
-    puts("       It is part of the implementation of this library and is");
-    puts("       subject to change. Applications should only use zlib.h.");
-    puts("     */");
-    puts("");
-    size = 1U << 9;
-    printf("    static const code lenfix[%u] = {", size);
-    low = 0;
-    for (;;) {
-        if ((low % 7) == 0) printf("\n        ");
-        printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
-               state.lencode[low].val);
-        if (++low == size) break;
-        putchar(',');
-    }
-    puts("\n    };");
-    size = 1U << 5;
-    printf("\n    static const code distfix[%u] = {", size);
-    low = 0;
-    for (;;) {
-        if ((low % 6) == 0) printf("\n        ");
-        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
-               state.distcode[low].val);
-        if (++low == size) break;
-        putchar(',');
-    }
-    puts("\n    };");
-}
-#endif /* MAKEFIXED */
-
-/*
-   Update the window with the last wsize (normally 32K) bytes written before
-   returning.  If window does not exist yet, create it.  This is only called
-   when a window is already in use, or when output has been written during this
-   inflate call, but the end of the deflate stream has not been reached yet.
-   It is also called to create a window for dictionary data when a dictionary
-   is loaded.
-
-   Providing output buffers larger than 32K to inflate() should provide a speed
-   advantage, since only the last 32K of output is copied to the sliding window
-   upon return from inflate(), and since all distances after the first 32K of
-   output will fall in the output data, making match copies simpler and faster.
-   The advantage may be dependent on the size of the processor's data caches.
- */
-local int updatewindow(strm, out)
-z_streamp strm;
-unsigned out;
-{
-    struct inflate_state FAR *state;
-    unsigned copy, dist;
-
-    state = (struct inflate_state FAR *)strm->state;
-
-    /* if it hasn't been done already, allocate space for the window */
-    if (state->window == Z_NULL) {
-        state->window = (unsigned char FAR *)
-                        ZALLOC(strm, 1U << state->wbits,
-                               sizeof(unsigned char));
-        if (state->window == Z_NULL) return 1;
-    }
-
-    /* if window not in use yet, initialize */
-    if (state->wsize == 0) {
-        state->wsize = 1U << state->wbits;
-        state->wnext = 0;
-        state->whave = 0;
-    }
-
-    /* copy state->wsize or less output bytes into the circular window */
-    copy = out - strm->avail_out;
-    if (copy >= state->wsize) {
-        zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
-        state->wnext = 0;
-        state->whave = state->wsize;
-    }
-    else {
-        dist = state->wsize - state->wnext;
-        if (dist > copy) dist = copy;
-        zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
-        copy -= dist;
-        if (copy) {
-            zmemcpy(state->window, strm->next_out - copy, copy);
-            state->wnext = copy;
-            state->whave = state->wsize;
-        }
-        else {
-            state->wnext += dist;
-            if (state->wnext == state->wsize) state->wnext = 0;
-            if (state->whave < state->wsize) state->whave += dist;
-        }
-    }
-    return 0;
-}
-
-/* Macros for inflate(): */
-
-/* check function to use adler32() for zlib or crc32() for gzip */
-#ifdef GUNZIP
-#  define UPDATE(check, buf, len) \
-    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
-#else
-#  define UPDATE(check, buf, len) adler32(check, buf, len)
-#endif
-
-/* check macros for header crc */
-#ifdef GUNZIP
-#  define CRC2(check, word) \
-    do { \
-        hbuf[0] = (unsigned char)(word); \
-        hbuf[1] = (unsigned char)((word) >> 8); \
-        check = crc32(check, hbuf, 2); \
-    } while (0)
-
-#  define CRC4(check, word) \
-    do { \
-        hbuf[0] = (unsigned char)(word); \
-        hbuf[1] = (unsigned char)((word) >> 8); \
-        hbuf[2] = (unsigned char)((word) >> 16); \
-        hbuf[3] = (unsigned char)((word) >> 24); \
-        check = crc32(check, hbuf, 4); \
-    } while (0)
-#endif
-
-/* Load registers with state in inflate() for speed */
-#define LOAD() \
-    do { \
-        put = strm->next_out; \
-        left = strm->avail_out; \
-        next = strm->next_in; \
-        have = strm->avail_in; \
-        hold = state->hold; \
-        bits = state->bits; \
-    } while (0)
-
-/* Restore state from registers in inflate() */
-#define RESTORE() \
-    do { \
-        strm->next_out = put; \
-        strm->avail_out = left; \
-        strm->next_in = next; \
-        strm->avail_in = have; \
-        state->hold = hold; \
-        state->bits = bits; \
-    } while (0)
-
-/* Clear the input bit accumulator */
-#define INITBITS() \
-    do { \
-        hold = 0; \
-        bits = 0; \
-    } while (0)
-
-/* Get a byte of input into the bit accumulator, or return from inflate()
-   if there is no input available. */
-#define PULLBYTE() \
-    do { \
-        if (have == 0) goto inf_leave; \
-        have--; \
-        hold += (unsigned long)(*next++) << bits; \
-        bits += 8; \
-    } while (0)
-
-/* Assure that there are at least n bits in the bit accumulator.  If there is
-   not enough available input to do that, then return from inflate(). */
-#define NEEDBITS(n) \
-    do { \
-        while (bits < (unsigned)(n)) \
-            PULLBYTE(); \
-    } while (0)
-
-/* Return the low n bits of the bit accumulator (n < 16) */
-#define BITS(n) \
-    ((unsigned)hold & ((1U << (n)) - 1))
-
-/* Remove n bits from the bit accumulator */
-#define DROPBITS(n) \
-    do { \
-        hold >>= (n); \
-        bits -= (unsigned)(n); \
-    } while (0)
-
-/* Remove zero to seven bits as needed to go to a byte boundary */
-#define BYTEBITS() \
-    do { \
-        hold >>= bits & 7; \
-        bits -= bits & 7; \
-    } while (0)
-
-/* Reverse the bytes in a 32-bit value */
-#define REVERSE(q) \
-    ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
-     (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
-
-/*
-   inflate() uses a state machine to process as much input data and generate as
-   much output data as possible before returning.  The state machine is
-   structured roughly as follows:
-
-    for (;;) switch (state) {
-    ...
-    case STATEn:
-        if (not enough input data or output space to make progress)
-            return;
-        ... make progress ...
-        state = STATEm;
-        break;
-    ...
-    }
-
-   so when inflate() is called again, the same case is attempted again, and
-   if the appropriate resources are provided, the machine proceeds to the
-   next state.  The NEEDBITS() macro is usually the way the state evaluates
-   whether it can proceed or should return.  NEEDBITS() does the return if
-   the requested bits are not available.  The typical use of the BITS macros
-   is:
-
-        NEEDBITS(n);
-        ... do something with BITS(n) ...
-        DROPBITS(n);
-
-   where NEEDBITS(n) either returns from inflate() if there isn't enough
-   input left to load n bits into the accumulator, or it continues.  BITS(n)
-   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
-   the low n bits off the accumulator.  INITBITS() clears the accumulator
-   and sets the number of available bits to zero.  BYTEBITS() discards just
-   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
-   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
-
-   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
-   if there is no input available.  The decoding of variable length codes uses
-   PULLBYTE() directly in order to pull just enough bytes to decode the next
-   code, and no more.
-
-   Some states loop until they get enough input, making sure that enough
-   state information is maintained to continue the loop where it left off
-   if NEEDBITS() returns in the loop.  For example, want, need, and keep
-   would all have to actually be part of the saved state in case NEEDBITS()
-   returns:
-
-    case STATEw:
-        while (want < need) {
-            NEEDBITS(n);
-            keep[want++] = BITS(n);
-            DROPBITS(n);
-        }
-        state = STATEx;
-    case STATEx:
-
-   As shown above, if the next state is also the next case, then the break
-   is omitted.
-
-   A state may also return if there is not enough output space available to
-   complete that state.  Those states are copying stored data, writing a
-   literal byte, and copying a matching string.
-
-   When returning, a "goto inf_leave" is used to update the total counters,
-   update the check value, and determine whether any progress has been made
-   during that inflate() call in order to return the proper return code.
-   Progress is defined as a change in either strm->avail_in or strm->avail_out.
-   When there is a window, goto inf_leave will update the window with the last
-   output written.  If a goto inf_leave occurs in the middle of decompression
-   and there is no window currently, goto inf_leave will create one and copy
-   output to the window for the next call of inflate().
-
-   In this implementation, the flush parameter of inflate() only affects the
-   return code (per zlib.h).  inflate() always writes as much as possible to
-   strm->next_out, given the space available and the provided input--the effect
-   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
-   the allocation of and copying into a sliding window until necessary, which
-   provides the effect documented in zlib.h for Z_FINISH when the entire input
-   stream available.  So the only thing the flush parameter actually does is:
-   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
-   will return Z_BUF_ERROR if it has not reached the end of the stream.
- */
-
-int ZEXPORT inflate(strm, flush)
-z_streamp strm;
-int flush;
-{
-    struct inflate_state FAR *state;
-    unsigned char FAR *next;    /* next input */
-    unsigned char FAR *put;     /* next output */
-    unsigned have, left;        /* available input and output */
-    unsigned long hold;         /* bit buffer */
-    unsigned bits;              /* bits in bit buffer */
-    unsigned in, out;           /* save starting available input and output */
-    unsigned copy;              /* number of stored or match bytes to copy */
-    unsigned char FAR *from;    /* where to copy match bytes from */
-    code here;                  /* current decoding table entry */
-    code last;                  /* parent table entry */
-    unsigned len;               /* length to copy for repeats, bits to drop */
-    int ret;                    /* return code */
-#ifdef GUNZIP
-    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
-#endif
-    static const unsigned short order[19] = /* permutation of code lengths */
-        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-    if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
-        (strm->next_in == Z_NULL && strm->avail_in != 0))
-        return Z_STREAM_ERROR;
-
-    state = (struct inflate_state FAR *)strm->state;
-    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
-    LOAD();
-    in = have;
-    out = left;
-    ret = Z_OK;
-    for (;;)
-        switch (state->mode) {
-        case HEAD:
-            if (state->wrap == 0) {
-                state->mode = TYPEDO;
-                break;
-            }
-            NEEDBITS(16);
-#ifdef GUNZIP
-            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
-                state->check = crc32(0L, Z_NULL, 0);
-                CRC2(state->check, hold);
-                INITBITS();
-                state->mode = FLAGS;
-                break;
-            }
-            state->flags = 0;           /* expect zlib header */
-            if (state->head != Z_NULL)
-                state->head->done = -1;
-            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
-#else
-            if (
-#endif
-                ((BITS(8) << 8) + (hold >> 8)) % 31) {
-                strm->msg = (char *)"incorrect header check";
-                state->mode = BAD;
-                break;
-            }
-            if (BITS(4) != Z_DEFLATED) {
-                strm->msg = (char *)"unknown compression method";
-                state->mode = BAD;
-                break;
-            }
-            DROPBITS(4);
-            len = BITS(4) + 8;
-            if (state->wbits == 0)
-                state->wbits = len;
-            else if (len > state->wbits) {
-                strm->msg = (char *)"invalid window size";
-                state->mode = BAD;
-                break;
-            }
-            state->dmax = 1U << len;
-            Tracev((stderr, "inflate:   zlib header ok\n"));
-            strm->adler = state->check = adler32(0L, Z_NULL, 0);
-            state->mode = hold & 0x200 ? DICTID : TYPE;
-            INITBITS();
-            break;
-#ifdef GUNZIP
-        case FLAGS:
-            NEEDBITS(16);
-            state->flags = (int)(hold);
-            if ((state->flags & 0xff) != Z_DEFLATED) {
-                strm->msg = (char *)"unknown compression method";
-                state->mode = BAD;
-                break;
-            }
-            if (state->flags & 0xe000) {
-                strm->msg = (char *)"unknown header flags set";
-                state->mode = BAD;
-                break;
-            }
-            if (state->head != Z_NULL)
-                state->head->text = (int)((hold >> 8) & 1);
-            if (state->flags & 0x0200) CRC2(state->check, hold);
-            INITBITS();
-            state->mode = TIME;
-        case TIME:
-            NEEDBITS(32);
-            if (state->head != Z_NULL)
-                state->head->time = hold;
-            if (state->flags & 0x0200) CRC4(state->check, hold);
-            INITBITS();
-            state->mode = OS;
-        case OS:
-            NEEDBITS(16);
-            if (state->head != Z_NULL) {
-                state->head->xflags = (int)(hold & 0xff);
-                state->head->os = (int)(hold >> 8);
-            }
-            if (state->flags & 0x0200) CRC2(state->check, hold);
-            INITBITS();
-            state->mode = EXLEN;
-        case EXLEN:
-            if (state->flags & 0x0400) {
-                NEEDBITS(16);
-                state->length = (unsigned)(hold);
-                if (state->head != Z_NULL)
-                    state->head->extra_len = (unsigned)hold;
-                if (state->flags & 0x0200) CRC2(state->check, hold);
-                INITBITS();
-            }
-            else if (state->head != Z_NULL)
-                state->head->extra = Z_NULL;
-            state->mode = EXTRA;
-        case EXTRA:
-            if (state->flags & 0x0400) {
-                copy = state->length;
-                if (copy > have) copy = have;
-                if (copy) {
-                    if (state->head != Z_NULL &&
-                        state->head->extra != Z_NULL) {
-                        len = state->head->extra_len - state->length;
-                        zmemcpy(state->head->extra + len, next,
-                                len + copy > state->head->extra_max ?
-                                state->head->extra_max - len : copy);
-                    }
-                    if (state->flags & 0x0200)
-                        state->check = crc32(state->check, next, copy);
-                    have -= copy;
-                    next += copy;
-                    state->length -= copy;
-                }
-                if (state->length) goto inf_leave;
-            }
-            state->length = 0;
-            state->mode = NAME;
-        case NAME:
-            if (state->flags & 0x0800) {
-                if (have == 0) goto inf_leave;
-                copy = 0;
-                do {
-                    len = (unsigned)(next[copy++]);
-                    if (state->head != Z_NULL &&
-                            state->head->name != Z_NULL &&
-                            state->length < state->head->name_max)
-                        state->head->name[state->length++] = len;
-                } while (len && copy < have);
-                if (state->flags & 0x0200)
-                    state->check = crc32(state->check, next, copy);
-                have -= copy;
-                next += copy;
-                if (len) goto inf_leave;
-            }
-            else if (state->head != Z_NULL)
-                state->head->name = Z_NULL;
-            state->length = 0;
-            state->mode = COMMENT;
-        case COMMENT:
-            if (state->flags & 0x1000) {
-                if (have == 0) goto inf_leave;
-                copy = 0;
-                do {
-                    len = (unsigned)(next[copy++]);
-                    if (state->head != Z_NULL &&
-                            state->head->comment != Z_NULL &&
-                            state->length < state->head->comm_max)
-                        state->head->comment[state->length++] = len;
-                } while (len && copy < have);
-                if (state->flags & 0x0200)
-                    state->check = crc32(state->check, next, copy);
-                have -= copy;
-                next += copy;
-                if (len) goto inf_leave;
-            }
-            else if (state->head != Z_NULL)
-                state->head->comment = Z_NULL;
-            state->mode = HCRC;
-        case HCRC:
-            if (state->flags & 0x0200) {
-                NEEDBITS(16);
-                if (hold != (state->check & 0xffff)) {
-                    strm->msg = (char *)"header crc mismatch";
-                    state->mode = BAD;
-                    break;
-                }
-                INITBITS();
-            }
-            if (state->head != Z_NULL) {
-                state->head->hcrc = (int)((state->flags >> 9) & 1);
-                state->head->done = 1;
-            }
-            strm->adler = state->check = crc32(0L, Z_NULL, 0);
-            state->mode = TYPE;
-            break;
-#endif
-        case DICTID:
-            NEEDBITS(32);
-            strm->adler = state->check = REVERSE(hold);
-            INITBITS();
-            state->mode = DICT;
-        case DICT:
-            if (state->havedict == 0) {
-                RESTORE();
-                return Z_NEED_DICT;
-            }
-            strm->adler = state->check = adler32(0L, Z_NULL, 0);
-            state->mode = TYPE;
-        case TYPE:
-            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
-        case TYPEDO:
-            if (state->last) {
-                BYTEBITS();
-                state->mode = CHECK;
-                break;
-            }
-            NEEDBITS(3);
-            state->last = BITS(1);
-            DROPBITS(1);
-            switch (BITS(2)) {
-            case 0:                             /* stored block */
-                Tracev((stderr, "inflate:     stored block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = STORED;
-                break;
-            case 1:                             /* fixed block */
-                fixedtables(state);
-                Tracev((stderr, "inflate:     fixed codes block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = LEN_;             /* decode codes */
-                if (flush == Z_TREES) {
-                    DROPBITS(2);
-                    goto inf_leave;
-                }
-                break;
-            case 2:                             /* dynamic block */
-                Tracev((stderr, "inflate:     dynamic codes block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = TABLE;
-                break;
-            case 3:
-                strm->msg = (char *)"invalid block type";
-                state->mode = BAD;
-            }
-            DROPBITS(2);
-            break;
-        case STORED:
-            BYTEBITS();                         /* go to byte boundary */
-            NEEDBITS(32);
-            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
-                strm->msg = (char *)"invalid stored block lengths";
-                state->mode = BAD;
-                break;
-            }
-            state->length = (unsigned)hold & 0xffff;
-            Tracev((stderr, "inflate:       stored length %u\n",
-                    state->length));
-            INITBITS();
-            state->mode = COPY_;
-            if (flush == Z_TREES) goto inf_leave;
-        case COPY_:
-            state->mode = COPY;
-        case COPY:
-            copy = state->length;
-            if (copy) {
-                if (copy > have) copy = have;
-                if (copy > left) copy = left;
-                if (copy == 0) goto inf_leave;
-                zmemcpy(put, next, copy);
-                have -= copy;
-                next += copy;
-                left -= copy;
-                put += copy;
-                state->length -= copy;
-                break;
-            }
-            Tracev((stderr, "inflate:       stored end\n"));
-            state->mode = TYPE;
-            break;
-        case TABLE:
-            NEEDBITS(14);
-            state->nlen = BITS(5) + 257;
-            DROPBITS(5);
-            state->ndist = BITS(5) + 1;
-            DROPBITS(5);
-            state->ncode = BITS(4) + 4;
-            DROPBITS(4);
-#ifndef PKZIP_BUG_WORKAROUND
-            if (state->nlen > 286 || state->ndist > 30) {
-                strm->msg = (char *)"too many length or distance symbols";
-                state->mode = BAD;
-                break;
-            }
-#endif
-            Tracev((stderr, "inflate:       table sizes ok\n"));
-            state->have = 0;
-            state->mode = LENLENS;
-        case LENLENS:
-            while (state->have < state->ncode) {
-                NEEDBITS(3);
-                state->lens[order[state->have++]] = (unsigned short)BITS(3);
-                DROPBITS(3);
-            }
-            while (state->have < 19)
-                state->lens[order[state->have++]] = 0;
-            state->next = state->codes;
-            state->lencode = (code const FAR *)(state->next);
-            state->lenbits = 7;
-            ret = inflate_table(CODES, state->lens, 19, &(state->next),
-                                &(state->lenbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid code lengths set";
-                state->mode = BAD;
-                break;
-            }
-            Tracev((stderr, "inflate:       code lengths ok\n"));
-            state->have = 0;
-            state->mode = CODELENS;
-        case CODELENS:
-            while (state->have < state->nlen + state->ndist) {
-                for (;;) {
-                    here = state->lencode[BITS(state->lenbits)];
-                    if ((unsigned)(here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                if (here.val < 16) {
-                    NEEDBITS(here.bits);
-                    DROPBITS(here.bits);
-                    state->lens[state->have++] = here.val;
-                }
-                else {
-                    if (here.val == 16) {
-                        NEEDBITS(here.bits + 2);
-                        DROPBITS(here.bits);
-                        if (state->have == 0) {
-                            strm->msg = (char *)"invalid bit length repeat";
-                            state->mode = BAD;
-                            break;
-                        }
-                        len = state->lens[state->have - 1];
-                        copy = 3 + BITS(2);
-                        DROPBITS(2);
-                    }
-                    else if (here.val == 17) {
-                        NEEDBITS(here.bits + 3);
-                        DROPBITS(here.bits);
-                        len = 0;
-                        copy = 3 + BITS(3);
-                        DROPBITS(3);
-                    }
-                    else {
-                        NEEDBITS(here.bits + 7);
-                        DROPBITS(here.bits);
-                        len = 0;
-                        copy = 11 + BITS(7);
-                        DROPBITS(7);
-                    }
-                    if (state->have + copy > state->nlen + state->ndist) {
-                        strm->msg = (char *)"invalid bit length repeat";
-                        state->mode = BAD;
-                        break;
-                    }
-                    while (copy--)
-                        state->lens[state->have++] = (unsigned short)len;
-                }
-            }
-
-            /* handle error breaks in while */
-            if (state->mode == BAD) break;
-
-            /* check for end-of-block code (better have one) */
-            if (state->lens[256] == 0) {
-                strm->msg = (char *)"invalid code -- missing end-of-block";
-                state->mode = BAD;
-                break;
-            }
-
-            /* build code tables -- note: do not change the lenbits or distbits
-               values here (9 and 6) without reading the comments in inftrees.h
-               concerning the ENOUGH constants, which depend on those values */
-            state->next = state->codes;
-            state->lencode = (code const FAR *)(state->next);
-            state->lenbits = 9;
-            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
-                                &(state->lenbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid literal/lengths set";
-                state->mode = BAD;
-                break;
-            }
-            state->distcode = (code const FAR *)(state->next);
-            state->distbits = 6;
-            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
-                            &(state->next), &(state->distbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid distances set";
-                state->mode = BAD;
-                break;
-            }
-            Tracev((stderr, "inflate:       codes ok\n"));
-            state->mode = LEN_;
-            if (flush == Z_TREES) goto inf_leave;
-        case LEN_:
-            state->mode = LEN;
-        case LEN:
-            if (have >= 6 && left >= 258) {
-                RESTORE();
-                inflate_fast(strm, out);
-                LOAD();
-                if (state->mode == TYPE)
-                    state->back = -1;
-                break;
-            }
-            state->back = 0;
-            for (;;) {
-                here = state->lencode[BITS(state->lenbits)];
-                if ((unsigned)(here.bits) <= bits) break;
-                PULLBYTE();
-            }
-            if (here.op && (here.op & 0xf0) == 0) {
-                last = here;
-                for (;;) {
-                    here = state->lencode[last.val +
-                            (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                DROPBITS(last.bits);
-                state->back += last.bits;
-            }
-            DROPBITS(here.bits);
-            state->back += here.bits;
-            state->length = (unsigned)here.val;
-            if ((int)(here.op) == 0) {
-                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
-                        "inflate:         literal '%c'\n" :
-                        "inflate:         literal 0x%02x\n", here.val));
-                state->mode = LIT;
-                break;
-            }
-            if (here.op & 32) {
-                Tracevv((stderr, "inflate:         end of block\n"));
-                state->back = -1;
-                state->mode = TYPE;
-                break;
-            }
-            if (here.op & 64) {
-                strm->msg = (char *)"invalid literal/length code";
-                state->mode = BAD;
-                break;
-            }
-            state->extra = (unsigned)(here.op) & 15;
-            state->mode = LENEXT;
-        case LENEXT:
-            if (state->extra) {
-                NEEDBITS(state->extra);
-                state->length += BITS(state->extra);
-                DROPBITS(state->extra);
-                state->back += state->extra;
-            }
-            Tracevv((stderr, "inflate:         length %u\n", state->length));
-            state->was = state->length;
-            state->mode = DIST;
-        case DIST:
-            for (;;) {
-                here = state->distcode[BITS(state->distbits)];
-                if ((unsigned)(here.bits) <= bits) break;
-                PULLBYTE();
-            }
-            if ((here.op & 0xf0) == 0) {
-                last = here;
-                for (;;) {
-                    here = state->distcode[last.val +
-                            (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                DROPBITS(last.bits);
-                state->back += last.bits;
-            }
-            DROPBITS(here.bits);
-            state->back += here.bits;
-            if (here.op & 64) {
-                strm->msg = (char *)"invalid distance code";
-                state->mode = BAD;
-                break;
-            }
-            state->offset = (unsigned)here.val;
-            state->extra = (unsigned)(here.op) & 15;
-            state->mode = DISTEXT;
-        case DISTEXT:
-            if (state->extra) {
-                NEEDBITS(state->extra);
-                state->offset += BITS(state->extra);
-                DROPBITS(state->extra);
-                state->back += state->extra;
-            }
-#ifdef INFLATE_STRICT
-            if (state->offset > state->dmax) {
-                strm->msg = (char *)"invalid distance too far back";
-                state->mode = BAD;
-                break;
-            }
-#endif
-            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
-            state->mode = MATCH;
-        case MATCH:
-            if (left == 0) goto inf_leave;
-            copy = out - left;
-            if (state->offset > copy) {         /* copy from window */
-                copy = state->offset - copy;
-                if (copy > state->whave) {
-                    if (state->sane) {
-                        strm->msg = (char *)"invalid distance too far back";
-                        state->mode = BAD;
-                        break;
-                    }
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
-                    Trace((stderr, "inflate.c too far\n"));
-                    copy -= state->whave;
-                    if (copy > state->length) copy = state->length;
-                    if (copy > left) copy = left;
-                    left -= copy;
-                    state->length -= copy;
-                    do {
-                        *put++ = 0;
-                    } while (--copy);
-                    if (state->length == 0) state->mode = LEN;
-                    break;
-#endif
-                }
-                if (copy > state->wnext) {
-                    copy -= state->wnext;
-                    from = state->window + (state->wsize - copy);
-                }
-                else
-                    from = state->window + (state->wnext - copy);
-                if (copy > state->length) copy = state->length;
-            }
-            else {                              /* copy from output */
-                from = put - state->offset;
-                copy = state->length;
-            }
-            if (copy > left) copy = left;
-            left -= copy;
-            state->length -= copy;
-            do {
-                *put++ = *from++;
-            } while (--copy);
-            if (state->length == 0) state->mode = LEN;
-            break;
-        case LIT:
-            if (left == 0) goto inf_leave;
-            *put++ = (unsigned char)(state->length);
-            left--;
-            state->mode = LEN;
-            break;
-        case CHECK:
-            if (state->wrap) {
-                NEEDBITS(32);
-                out -= left;
-                strm->total_out += out;
-                state->total += out;
-                if (out)
-                    strm->adler = state->check =
-                        UPDATE(state->check, put - out, out);
-                out = left;
-                if ((
-#ifdef GUNZIP
-                     state->flags ? hold :
-#endif
-                     REVERSE(hold)) != state->check) {
-                    strm->msg = (char *)"incorrect data check";
-                    state->mode = BAD;
-                    break;
-                }
-                INITBITS();
-                Tracev((stderr, "inflate:   check matches trailer\n"));
-            }
-#ifdef GUNZIP
-            state->mode = LENGTH;
-        case LENGTH:
-            if (state->wrap && state->flags) {
-                NEEDBITS(32);
-                if (hold != (state->total & 0xffffffffUL)) {
-                    strm->msg = (char *)"incorrect length check";
-                    state->mode = BAD;
-                    break;
-                }
-                INITBITS();
-                Tracev((stderr, "inflate:   length matches trailer\n"));
-            }
-#endif
-            state->mode = DONE;
-        case DONE:
-            ret = Z_STREAM_END;
-            goto inf_leave;
-        case BAD:
-            ret = Z_DATA_ERROR;
-            goto inf_leave;
-        case MEM:
-            return Z_MEM_ERROR;
-        case SYNC:
-        default:
-            return Z_STREAM_ERROR;
-        }
-
-    /*
-       Return from inflate(), updating the total counts and the check value.
-       If there was no progress during the inflate() call, return a buffer
-       error.  Call updatewindow() to create and/or update the window state.
-       Note: a memory error from inflate() is non-recoverable.
-     */
-  inf_leave:
-    RESTORE();
-    if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
-        if (updatewindow(strm, out)) {
-            state->mode = MEM;
-            return Z_MEM_ERROR;
-        }
-    in -= strm->avail_in;
-    out -= strm->avail_out;
-    strm->total_in += in;
-    strm->total_out += out;
-    state->total += out;
-    if (state->wrap && out)
-        strm->adler = state->check =
-            UPDATE(state->check, strm->next_out - out, out);
-    strm->data_type = state->bits + (state->last ? 64 : 0) +
-                      (state->mode == TYPE ? 128 : 0) +
-                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
-    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
-        ret = Z_BUF_ERROR;
-    return ret;
-}
-
-int ZEXPORT inflateEnd(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
-        return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (state->window != Z_NULL) ZFREE(strm, state->window);
-    ZFREE(strm, strm->state);
-    strm->state = Z_NULL;
-    Tracev((stderr, "inflate: end\n"));
-    return Z_OK;
-}
-
-int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
-z_streamp strm;
-const Bytef *dictionary;
-uInt dictLength;
-{
-    struct inflate_state FAR *state;
-    unsigned long id;
-
-    /* check state */
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (state->wrap != 0 && state->mode != DICT)
-        return Z_STREAM_ERROR;
-
-    /* check for correct dictionary id */
-    if (state->mode == DICT) {
-        id = adler32(0L, Z_NULL, 0);
-        id = adler32(id, dictionary, dictLength);
-        if (id != state->check)
-            return Z_DATA_ERROR;
-    }
-
-    /* copy dictionary to window */
-    if (updatewindow(strm, strm->avail_out)) {
-        state->mode = MEM;
-        return Z_MEM_ERROR;
-    }
-    if (dictLength > state->wsize) {
-        zmemcpy(state->window, dictionary + dictLength - state->wsize,
-                state->wsize);
-        state->whave = state->wsize;
-    }
-    else {
-        zmemcpy(state->window + state->wsize - dictLength, dictionary,
-                dictLength);
-        state->whave = dictLength;
-    }
-    state->havedict = 1;
-    Tracev((stderr, "inflate:   dictionary set\n"));
-    return Z_OK;
-}
-
-int ZEXPORT inflateGetHeader(strm, head)
-z_streamp strm;
-gz_headerp head;
-{
-    struct inflate_state FAR *state;
-
-    /* check state */
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
-
-    /* save header structure */
-    state->head = head;
-    head->done = 0;
-    return Z_OK;
-}
-
-/*
-   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
-   or when out of input.  When called, *have is the number of pattern bytes
-   found in order so far, in 0..3.  On return *have is updated to the new
-   state.  If on return *have equals four, then the pattern was found and the
-   return value is how many bytes were read including the last byte of the
-   pattern.  If *have is less than four, then the pattern has not been found
-   yet and the return value is len.  In the latter case, syncsearch() can be
-   called again with more data and the *have state.  *have is initialized to
-   zero for the first call.
- */
-local unsigned syncsearch(have, buf, len)
-unsigned FAR *have;
-unsigned char FAR *buf;
-unsigned len;
-{
-    unsigned got;
-    unsigned next;
-
-    got = *have;
-    next = 0;
-    while (next < len && got < 4) {
-        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
-            got++;
-        else if (buf[next])
-            got = 0;
-        else
-            got = 4 - got;
-        next++;
-    }
-    *have = got;
-    return next;
-}
-
-int ZEXPORT inflateSync(strm)
-z_streamp strm;
-{
-    unsigned len;               /* number of bytes to look at or looked at */
-    unsigned long in, out;      /* temporary to save total_in and total_out */
-    unsigned char buf[4];       /* to restore bit buffer to byte string */
-    struct inflate_state FAR *state;
-
-    /* check parameters */
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
-
-    /* if first time, start search in bit buffer */
-    if (state->mode != SYNC) {
-        state->mode = SYNC;
-        state->hold <<= state->bits & 7;
-        state->bits -= state->bits & 7;
-        len = 0;
-        while (state->bits >= 8) {
-            buf[len++] = (unsigned char)(state->hold);
-            state->hold >>= 8;
-            state->bits -= 8;
-        }
-        state->have = 0;
-        syncsearch(&(state->have), buf, len);
-    }
-
-    /* search available input */
-    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
-    strm->avail_in -= len;
-    strm->next_in += len;
-    strm->total_in += len;
-
-    /* return no joy or set up to restart inflate() on a new block */
-    if (state->have != 4) return Z_DATA_ERROR;
-    in = strm->total_in;  out = strm->total_out;
-    inflateReset(strm);
-    strm->total_in = in;  strm->total_out = out;
-    state->mode = TYPE;
-    return Z_OK;
-}
-
-/*
-   Returns true if inflate is currently at the end of a block generated by
-   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
-   implementation to provide an additional safety check. PPP uses
-   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
-   block. When decompressing, PPP checks that at the end of input packet,
-   inflate is waiting for these length bytes.
- */
-int ZEXPORT inflateSyncPoint(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    return state->mode == STORED && state->bits == 0;
-}
-
-int ZEXPORT inflateCopy(dest, source)
-z_streamp dest;
-z_streamp source;
-{
-    struct inflate_state FAR *state;
-    struct inflate_state FAR *copy;
-    unsigned char FAR *window;
-    unsigned wsize;
-
-    /* check input */
-    if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
-        source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
-        return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)source->state;
-
-    /* allocate space */
-    copy = (struct inflate_state FAR *)
-           ZALLOC(source, 1, sizeof(struct inflate_state));
-    if (copy == Z_NULL) return Z_MEM_ERROR;
-    window = Z_NULL;
-    if (state->window != Z_NULL) {
-        window = (unsigned char FAR *)
-                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
-        if (window == Z_NULL) {
-            ZFREE(source, copy);
-            return Z_MEM_ERROR;
-        }
-    }
-
-    /* copy state */
-    zmemcpy(dest, source, sizeof(z_stream));
-    zmemcpy(copy, state, sizeof(struct inflate_state));
-    if (state->lencode >= state->codes &&
-        state->lencode <= state->codes + ENOUGH - 1) {
-        copy->lencode = copy->codes + (state->lencode - state->codes);
-        copy->distcode = copy->codes + (state->distcode - state->codes);
-    }
-    copy->next = copy->codes + (state->next - state->codes);
-    if (window != Z_NULL) {
-        wsize = 1U << state->wbits;
-        zmemcpy(window, state->window, wsize);
-    }
-    copy->window = window;
-    dest->state = (struct internal_state FAR *)copy;
-    return Z_OK;
-}
-
-int ZEXPORT inflateUndermine(strm, subvert)
-z_streamp strm;
-int subvert;
-{
-    struct inflate_state FAR *state;
-
-    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    state->sane = !subvert;
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
-    return Z_OK;
-#else
-    state->sane = 1;
-    return Z_DATA_ERROR;
-#endif
-}
-
-long ZEXPORT inflateMark(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-
-    if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
-    state = (struct inflate_state FAR *)strm->state;
-    return ((long)(state->back) << 16) +
-        (state->mode == COPY ? state->length :
-            (state->mode == MATCH ? state->was - state->length : 0));
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/inflate.h b/src/external/OpenGR/3rdparty/cfitsio/zlib/inflate.h
deleted file mode 100644
index 95f4986d4..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/inflate.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* inflate.h -- internal inflate state definition
- * Copyright (C) 1995-2009 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* define NO_GZIP when compiling if you want to disable gzip header and
-   trailer decoding by inflate().  NO_GZIP would be used to avoid linking in
-   the crc code when it is not needed.  For shared libraries, gzip decoding
-   should be left enabled. */
-#ifndef NO_GZIP
-#  define GUNZIP
-#endif
-
-/* Possible inflate modes between inflate() calls */
-typedef enum {
-    HEAD,       /* i: waiting for magic header */
-    FLAGS,      /* i: waiting for method and flags (gzip) */
-    TIME,       /* i: waiting for modification time (gzip) */
-    OS,         /* i: waiting for extra flags and operating system (gzip) */
-    EXLEN,      /* i: waiting for extra length (gzip) */
-    EXTRA,      /* i: waiting for extra bytes (gzip) */
-    NAME,       /* i: waiting for end of file name (gzip) */
-    COMMENT,    /* i: waiting for end of comment (gzip) */
-    HCRC,       /* i: waiting for header crc (gzip) */
-    DICTID,     /* i: waiting for dictionary check value */
-    DICT,       /* waiting for inflateSetDictionary() call */
-        TYPE,       /* i: waiting for type bits, including last-flag bit */
-        TYPEDO,     /* i: same, but skip check to exit inflate on new block */
-        STORED,     /* i: waiting for stored size (length and complement) */
-        COPY_,      /* i/o: same as COPY below, but only first time in */
-        COPY,       /* i/o: waiting for input or output to copy stored block */
-        TABLE,      /* i: waiting for dynamic block table lengths */
-        LENLENS,    /* i: waiting for code length code lengths */
-        CODELENS,   /* i: waiting for length/lit and distance code lengths */
-            LEN_,       /* i: same as LEN below, but only first time in */
-            LEN,        /* i: waiting for length/lit/eob code */
-            LENEXT,     /* i: waiting for length extra bits */
-            DIST,       /* i: waiting for distance code */
-            DISTEXT,    /* i: waiting for distance extra bits */
-            MATCH,      /* o: waiting for output space to copy string */
-            LIT,        /* o: waiting for output space to write literal */
-    CHECK,      /* i: waiting for 32-bit check value */
-    LENGTH,     /* i: waiting for 32-bit length (gzip) */
-    DONE,       /* finished check, done -- remain here until reset */
-    BAD,        /* got a data error -- remain here until reset */
-    MEM,        /* got an inflate() memory error -- remain here until reset */
-    SYNC        /* looking for synchronization bytes to restart inflate() */
-} inflate_mode;
-
-/*
-    State transitions between above modes -
-
-    (most modes can go to BAD or MEM on error -- not shown for clarity)
-
-    Process header:
-        HEAD -> (gzip) or (zlib) or (raw)
-        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
-                  HCRC -> TYPE
-        (zlib) -> DICTID or TYPE
-        DICTID -> DICT -> TYPE
-        (raw) -> TYPEDO
-    Read deflate blocks:
-            TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
-            STORED -> COPY_ -> COPY -> TYPE
-            TABLE -> LENLENS -> CODELENS -> LEN_
-            LEN_ -> LEN
-    Read deflate codes in fixed or dynamic block:
-                LEN -> LENEXT or LIT or TYPE
-                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
-                LIT -> LEN
-    Process trailer:
-        CHECK -> LENGTH -> DONE
- */
-
-/* state maintained between inflate() calls.  Approximately 10K bytes. */
-struct inflate_state {
-    inflate_mode mode;          /* current inflate mode */
-    int last;                   /* true if processing last block */
-    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip */
-    int havedict;               /* true if dictionary provided */
-    int flags;                  /* gzip header method and flags (0 if zlib) */
-    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */
-    unsigned long check;        /* protected copy of check value */
-    unsigned long total;        /* protected copy of output count */
-    gz_headerp head;            /* where to save gzip header information */
-        /* sliding window */
-    unsigned wbits;             /* log base 2 of requested window size */
-    unsigned wsize;             /* window size or zero if not using window */
-    unsigned whave;             /* valid bytes in the window */
-    unsigned wnext;             /* window write index */
-    unsigned char FAR *window;  /* allocated sliding window, if needed */
-        /* bit accumulator */
-    unsigned long hold;         /* input bit accumulator */
-    unsigned bits;              /* number of bits in "in" */
-        /* for string and stored block copying */
-    unsigned length;            /* literal or length of data to copy */
-    unsigned offset;            /* distance back to copy string from */
-        /* for table and code decoding */
-    unsigned extra;             /* extra bits needed */
-        /* fixed and dynamic code tables */
-    code const FAR *lencode;    /* starting table for length/literal codes */
-    code const FAR *distcode;   /* starting table for distance codes */
-    unsigned lenbits;           /* index bits for lencode */
-    unsigned distbits;          /* index bits for distcode */
-        /* dynamic table building */
-    unsigned ncode;             /* number of code length code lengths */
-    unsigned nlen;              /* number of length code lengths */
-    unsigned ndist;             /* number of distance code lengths */
-    unsigned have;              /* number of code lengths in lens[] */
-    code FAR *next;             /* next available space in codes[] */
-    unsigned short lens[320];   /* temporary storage for code lengths */
-    unsigned short work[288];   /* work area for code table building */
-    code codes[ENOUGH];         /* space for code tables */
-    int sane;                   /* if false, allow invalid distance too far */
-    int back;                   /* bits back of last unprocessed length/lit */
-    unsigned was;               /* initial length of match */
-};
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/inftrees.c b/src/external/OpenGR/3rdparty/cfitsio/zlib/inftrees.c
deleted file mode 100644
index 11e9c52ac..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/inftrees.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2010 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-
-#define MAXBITS 15
-
-const char inflate_copyright[] =
-   " inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
-/*
-  If you use the zlib library in a product, an acknowledgment is welcome
-  in the documentation of your product. If for some reason you cannot
-  include such an acknowledgment, I would appreciate that you keep this
-  copyright string in the executable of your product.
- */
-
-/*
-   Build a set of tables to decode the provided canonical Huffman code.
-   The code lengths are lens[0..codes-1].  The result starts at *table,
-   whose indices are 0..2^bits-1.  work is a writable array of at least
-   lens shorts, which is used as a work area.  type is the type of code
-   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
-   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
-   on return points to the next available entry's address.  bits is the
-   requested root table index bits, and on return it is the actual root
-   table index bits.  It will differ if the request is greater than the
-   longest code or if it is less than the shortest code.
- */
-int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
-codetype type;
-unsigned short FAR *lens;
-unsigned codes;
-code FAR * FAR *table;
-unsigned FAR *bits;
-unsigned short FAR *work;
-{
-    unsigned len;               /* a code's length in bits */
-    unsigned sym;               /* index of code symbols */
-    unsigned min, max;          /* minimum and maximum code lengths */
-    unsigned root;              /* number of index bits for root table */
-    unsigned curr;              /* number of index bits for current table */
-    unsigned drop;              /* code bits to drop for sub-table */
-    int left;                   /* number of prefix codes available */
-    unsigned used;              /* code entries in table used */
-    unsigned huff;              /* Huffman code */
-    unsigned incr;              /* for incrementing code, index */
-    unsigned fill;              /* index for replicating entries */
-    unsigned low;               /* low bits for current root entry */
-    unsigned mask;              /* mask for low root bits */
-    code here;                  /* table entry for duplication */
-    code FAR *next;             /* next available space in table */
-    const unsigned short FAR *base;     /* base value table to use */
-    const unsigned short FAR *extra;    /* extra bits table to use */
-    int end;                    /* use base and extra for symbol > end */
-    unsigned short count[MAXBITS+1];    /* number of codes of each length */
-    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */
-    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
-        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
-        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
-    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
-        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
-        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
-    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
-        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
-        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
-        8193, 12289, 16385, 24577, 0, 0};
-    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
-        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
-        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
-        28, 28, 29, 29, 64, 64};
-
-    /*
-       Process a set of code lengths to create a canonical Huffman code.  The
-       code lengths are lens[0..codes-1].  Each length corresponds to the
-       symbols 0..codes-1.  The Huffman code is generated by first sorting the
-       symbols by length from short to long, and retaining the symbol order
-       for codes with equal lengths.  Then the code starts with all zero bits
-       for the first code of the shortest length, and the codes are integer
-       increments for the same length, and zeros are appended as the length
-       increases.  For the deflate format, these bits are stored backwards
-       from their more natural integer increment ordering, and so when the
-       decoding tables are built in the large loop below, the integer codes
-       are incremented backwards.
-
-       This routine assumes, but does not check, that all of the entries in
-       lens[] are in the range 0..MAXBITS.  The caller must assure this.
-       1..MAXBITS is interpreted as that code length.  zero means that that
-       symbol does not occur in this code.
-
-       The codes are sorted by computing a count of codes for each length,
-       creating from that a table of starting indices for each length in the
-       sorted table, and then entering the symbols in order in the sorted
-       table.  The sorted table is work[], with that space being provided by
-       the caller.
-
-       The length counts are used for other purposes as well, i.e. finding
-       the minimum and maximum length codes, determining if there are any
-       codes at all, checking for a valid set of lengths, and looking ahead
-       at length counts to determine sub-table sizes when building the
-       decoding tables.
-     */
-
-    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
-    for (len = 0; len <= MAXBITS; len++)
-        count[len] = 0;
-    for (sym = 0; sym < codes; sym++)
-        count[lens[sym]]++;
-
-    /* bound code lengths, force root to be within code lengths */
-    root = *bits;
-    for (max = MAXBITS; max >= 1; max--)
-        if (count[max] != 0) break;
-    if (root > max) root = max;
-    if (max == 0) {                     /* no symbols to code at all */
-        here.op = (unsigned char)64;    /* invalid code marker */
-        here.bits = (unsigned char)1;
-        here.val = (unsigned short)0;
-        *(*table)++ = here;             /* make a table to force an error */
-        *(*table)++ = here;
-        *bits = 1;
-        return 0;     /* no symbols, but wait for decoding to report error */
-    }
-    for (min = 1; min < max; min++)
-        if (count[min] != 0) break;
-    if (root < min) root = min;
-
-    /* check for an over-subscribed or incomplete set of lengths */
-    left = 1;
-    for (len = 1; len <= MAXBITS; len++) {
-        left <<= 1;
-        left -= count[len];
-        if (left < 0) return -1;        /* over-subscribed */
-    }
-    if (left > 0 && (type == CODES || max != 1))
-        return -1;                      /* incomplete set */
-
-    /* generate offsets into symbol table for each length for sorting */
-    offs[1] = 0;
-    for (len = 1; len < MAXBITS; len++)
-        offs[len + 1] = offs[len] + count[len];
-
-    /* sort symbols by length, by symbol order within each length */
-    for (sym = 0; sym < codes; sym++)
-        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
-
-    /*
-       Create and fill in decoding tables.  In this loop, the table being
-       filled is at next and has curr index bits.  The code being used is huff
-       with length len.  That code is converted to an index by dropping drop
-       bits off of the bottom.  For codes where len is less than drop + curr,
-       those top drop + curr - len bits are incremented through all values to
-       fill the table with replicated entries.
-
-       root is the number of index bits for the root table.  When len exceeds
-       root, sub-tables are created pointed to by the root entry with an index
-       of the low root bits of huff.  This is saved in low to check for when a
-       new sub-table should be started.  drop is zero when the root table is
-       being filled, and drop is root when sub-tables are being filled.
-
-       When a new sub-table is needed, it is necessary to look ahead in the
-       code lengths to determine what size sub-table is needed.  The length
-       counts are used for this, and so count[] is decremented as codes are
-       entered in the tables.
-
-       used keeps track of how many table entries have been allocated from the
-       provided *table space.  It is checked for LENS and DIST tables against
-       the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
-       the initial root table size constants.  See the comments in inftrees.h
-       for more information.
-
-       sym increments through all symbols, and the loop terminates when
-       all codes of length max, i.e. all codes, have been processed.  This
-       routine permits incomplete codes, so another loop after this one fills
-       in the rest of the decoding tables with invalid code markers.
-     */
-
-    /* set up for code type */
-    switch (type) {
-    case CODES:
-        base = extra = work;    /* dummy value--not used */
-        end = 19;
-        break;
-    case LENS:
-        base = lbase;
-        base -= 257;
-        extra = lext;
-        extra -= 257;
-        end = 256;
-        break;
-    default:            /* DISTS */
-        base = dbase;
-        extra = dext;
-        end = -1;
-    }
-
-    /* initialize state for loop */
-    huff = 0;                   /* starting code */
-    sym = 0;                    /* starting code symbol */
-    len = min;                  /* starting code length */
-    next = *table;              /* current table to fill in */
-    curr = root;                /* current table index bits */
-    drop = 0;                   /* current bits to drop from code for index */
-    low = (unsigned)(-1);       /* trigger new sub-table when len > root */
-    used = 1U << root;          /* use root table entries */
-    mask = used - 1;            /* mask for comparing low */
-
-    /* check available table space */
-    if ((type == LENS && used >= ENOUGH_LENS) ||
-        (type == DISTS && used >= ENOUGH_DISTS))
-        return 1;
-
-    /* process all codes and make table entries */
-    for (;;) {
-        /* create table entry */
-        here.bits = (unsigned char)(len - drop);
-        if ((int)(work[sym]) < end) {
-            here.op = (unsigned char)0;
-            here.val = work[sym];
-        }
-        else if ((int)(work[sym]) > end) {
-            here.op = (unsigned char)(extra[work[sym]]);
-            here.val = base[work[sym]];
-        }
-        else {
-            here.op = (unsigned char)(32 + 64);         /* end of block */
-            here.val = 0;
-        }
-
-        /* replicate for those indices with low len bits equal to huff */
-        incr = 1U << (len - drop);
-        fill = 1U << curr;
-        min = fill;                 /* save offset to next table */
-        do {
-            fill -= incr;
-            next[(huff >> drop) + fill] = here;
-        } while (fill != 0);
-
-        /* backwards increment the len-bit code huff */
-        incr = 1U << (len - 1);
-        while (huff & incr)
-            incr >>= 1;
-        if (incr != 0) {
-            huff &= incr - 1;
-            huff += incr;
-        }
-        else
-            huff = 0;
-
-        /* go to next symbol, update count, len */
-        sym++;
-        if (--(count[len]) == 0) {
-            if (len == max) break;
-            len = lens[work[sym]];
-        }
-
-        /* create new sub-table if needed */
-        if (len > root && (huff & mask) != low) {
-            /* if first time, transition to sub-tables */
-            if (drop == 0)
-                drop = root;
-
-            /* increment past last table */
-            next += min;            /* here min is 1 << curr */
-
-            /* determine length of next table */
-            curr = len - drop;
-            left = (int)(1 << curr);
-            while (curr + drop < max) {
-                left -= count[curr + drop];
-                if (left <= 0) break;
-                curr++;
-                left <<= 1;
-            }
-
-            /* check for enough space */
-            used += 1U << curr;
-            if ((type == LENS && used >= ENOUGH_LENS) ||
-                (type == DISTS && used >= ENOUGH_DISTS))
-                return 1;
-
-            /* point entry in root table to sub-table */
-            low = huff & mask;
-            (*table)[low].op = (unsigned char)curr;
-            (*table)[low].bits = (unsigned char)root;
-            (*table)[low].val = (unsigned short)(next - *table);
-        }
-    }
-
-    /*
-       Fill in rest of table for incomplete codes.  This loop is similar to the
-       loop above in incrementing huff for table indices.  It is assumed that
-       len is equal to curr + drop, so there is no loop needed to increment
-       through high index bits.  When the current sub-table is filled, the loop
-       drops back to the root table to fill in any remaining entries there.
-     */
-    here.op = (unsigned char)64;                /* invalid code marker */
-    here.bits = (unsigned char)(len - drop);
-    here.val = (unsigned short)0;
-    while (huff != 0) {
-        /* when done with sub-table, drop back to root table */
-        if (drop != 0 && (huff & mask) != low) {
-            drop = 0;
-            len = root;
-            next = *table;
-            here.bits = (unsigned char)len;
-        }
-
-        /* put invalid code marker in table */
-        next[huff >> drop] = here;
-
-        /* backwards increment the len-bit code huff */
-        incr = 1U << (len - 1);
-        while (huff & incr)
-            incr >>= 1;
-        if (incr != 0) {
-            huff &= incr - 1;
-            huff += incr;
-        }
-        else
-            huff = 0;
-    }
-
-    /* set return parameters */
-    *table += used;
-    *bits = root;
-    return 0;
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/inftrees.h b/src/external/OpenGR/3rdparty/cfitsio/zlib/inftrees.h
deleted file mode 100644
index baa53a0b1..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/inftrees.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995-2005, 2010 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* Structure for decoding tables.  Each entry provides either the
-   information needed to do the operation requested by the code that
-   indexed that table entry, or it provides a pointer to another
-   table that indexes more bits of the code.  op indicates whether
-   the entry is a pointer to another table, a literal, a length or
-   distance, an end-of-block, or an invalid code.  For a table
-   pointer, the low four bits of op is the number of index bits of
-   that table.  For a length or distance, the low four bits of op
-   is the number of extra bits to get after the code.  bits is
-   the number of bits in this code or part of the code to drop off
-   of the bit buffer.  val is the actual byte to output in the case
-   of a literal, the base length or distance, or the offset from
-   the current table to the next table.  Each entry is four bytes. */
-typedef struct {
-    unsigned char op;           /* operation, extra bits, table bits */
-    unsigned char bits;         /* bits in this part of the code */
-    unsigned short val;         /* offset in table or code value */
-} code;
-
-/* op values as set by inflate_table():
-    00000000 - literal
-    0000tttt - table link, tttt != 0 is the number of table index bits
-    0001eeee - length or distance, eeee is the number of extra bits
-    01100000 - end of block
-    01000000 - invalid code
- */
-
-/* Maximum size of the dynamic table.  The maximum number of code structures is
-   1444, which is the sum of 852 for literal/length codes and 592 for distance
-   codes.  These values were found by exhaustive searches using the program
-   examples/enough.c found in the zlib distribtution.  The arguments to that
-   program are the number of symbols, the initial root table size, and the
-   maximum bit length of a code.  "enough 286 9 15" for literal/length codes
-   returns returns 852, and "enough 30 6 15" for distance codes returns 592.
-   The initial root table size (9 or 6) is found in the fifth argument of the
-   inflate_table() calls in inflate.c and infback.c.  If the root table size is
-   changed, then these maximum sizes would be need to be recalculated and
-   updated. */
-#define ENOUGH_LENS 852
-#define ENOUGH_DISTS 592
-#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
-
-/* Type of code to build for inflate_table() */
-typedef enum {
-    CODES,
-    LENS,
-    DISTS
-} codetype;
-
-int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
-                             unsigned codes, code FAR * FAR *table,
-                             unsigned FAR *bits, unsigned short FAR *work));
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/trees.c b/src/external/OpenGR/3rdparty/cfitsio/zlib/trees.c
deleted file mode 100644
index 843612689..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/trees.c
+++ /dev/null
@@ -1,1242 +0,0 @@
-/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2010 Jean-loup Gailly
- * detect_data_type() function provided freely by Cosmin Truta, 2006
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- *  ALGORITHM
- *
- *      The "deflation" process uses several Huffman trees. The more
- *      common source values are represented by shorter bit sequences.
- *
- *      Each code tree is stored in a compressed form which is itself
- * a Huffman encoding of the lengths of all the code strings (in
- * ascending order by source values).  The actual code strings are
- * reconstructed from the lengths in the inflate process, as described
- * in the deflate specification.
- *
- *  REFERENCES
- *
- *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
- *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
- *
- *      Storer, James A.
- *          Data Compression:  Methods and Theory, pp. 49-50.
- *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
- *
- *      Sedgewick, R.
- *          Algorithms, p290.
- *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
- */
-
-/* #define GEN_TREES_H */
-
-#include "deflate.h"
-
-#ifdef DEBUG
-#  include 
-#endif
-
-/* ===========================================================================
- * Constants
- */
-
-#define MAX_BL_BITS 7
-/* Bit length codes must not exceed MAX_BL_BITS bits */
-
-#define END_BLOCK 256
-/* end of block literal code */
-
-#define REP_3_6      16
-/* repeat previous bit length 3-6 times (2 bits of repeat count) */
-
-#define REPZ_3_10    17
-/* repeat a zero length 3-10 times  (3 bits of repeat count) */
-
-#define REPZ_11_138  18
-/* repeat a zero length 11-138 times  (7 bits of repeat count) */
-
-local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
-   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
-
-local const int extra_dbits[D_CODES] /* extra bits for each distance code */
-   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
-
-local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
-   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
-
-local const uch bl_order[BL_CODES]
-   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
-/* The lengths of the bit length codes are sent in order of decreasing
- * probability, to avoid transmitting the lengths for unused bit length codes.
- */
-
-#define Buf_size (8 * 2*sizeof(char))
-/* Number of bits used within bi_buf. (bi_buf might be implemented on
- * more than 16 bits on some systems.)
- */
-
-/* ===========================================================================
- * Local data. These are initialized only once.
- */
-
-#define DIST_CODE_LEN  512 /* see definition of array dist_code below */
-
-#if defined(GEN_TREES_H) || !defined(STDC)
-/* non ANSI compilers may not accept trees.h */
-
-local ct_data static_ltree[L_CODES+2];
-/* The static literal tree. Since the bit lengths are imposed, there is no
- * need for the L_CODES extra codes used during heap construction. However
- * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
- * below).
- */
-
-local ct_data static_dtree[D_CODES];
-/* The static distance tree. (Actually a trivial tree since all codes use
- * 5 bits.)
- */
-
-uch _dist_code[DIST_CODE_LEN];
-/* Distance codes. The first 256 values correspond to the distances
- * 3 .. 258, the last 256 values correspond to the top 8 bits of
- * the 15 bit distances.
- */
-
-uch _length_code[MAX_MATCH-MIN_MATCH+1];
-/* length code for each normalized match length (0 == MIN_MATCH) */
-
-local int base_length[LENGTH_CODES];
-/* First normalized length for each code (0 = MIN_MATCH) */
-
-local int base_dist[D_CODES];
-/* First normalized distance for each code (0 = distance of 1) */
-
-#else
-#  include "trees.h"
-#endif /* GEN_TREES_H */
-
-struct static_tree_desc_s {
-    const ct_data *static_tree;  /* static tree or NULL */
-    const intf *extra_bits;      /* extra bits for each code or NULL */
-    int     extra_base;          /* base index for extra_bits */
-    int     elems;               /* max number of elements in the tree */
-    int     max_length;          /* max bit length for the codes */
-};
-
-local static_tree_desc  static_l_desc =
-{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
-
-local static_tree_desc  static_d_desc =
-{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};
-
-local static_tree_desc  static_bl_desc =
-{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};
-
-/* ===========================================================================
- * Local (static) routines in this file.
- */
-
-local void tr_static_init OF((void));
-local void init_block     OF((deflate_state *s));
-local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
-local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
-local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
-local void build_tree     OF((deflate_state *s, tree_desc *desc));
-local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
-local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
-local int  build_bl_tree  OF((deflate_state *s));
-local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
-                              int blcodes));
-local void compress_block OF((deflate_state *s, ct_data *ltree,
-                              ct_data *dtree));
-local int  detect_data_type OF((deflate_state *s));
-local unsigned bi_reverse OF((unsigned value, int length));
-local void bi_windup      OF((deflate_state *s));
-local void bi_flush       OF((deflate_state *s));
-local void copy_block     OF((deflate_state *s, charf *buf, unsigned len,
-                              int header));
-
-#ifdef GEN_TREES_H
-local void gen_trees_header OF((void));
-#endif
-
-#ifndef DEBUG
-#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
-   /* Send a code of the given tree. c and tree must not have side effects */
-
-#else /* DEBUG */
-#  define send_code(s, c, tree) \
-     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
-       send_bits(s, tree[c].Code, tree[c].Len); }
-#endif
-
-/* ===========================================================================
- * Output a short LSB first on the stream.
- * IN assertion: there is enough room in pendingBuf.
- */
-#define put_short(s, w) { \
-    put_byte(s, (uch)((w) & 0xff)); \
-    put_byte(s, (uch)((ush)(w) >> 8)); \
-}
-
-/* ===========================================================================
- * Send a value on a given number of bits.
- * IN assertion: length <= 16 and value fits in length bits.
- */
-#ifdef DEBUG
-local void send_bits      OF((deflate_state *s, int value, int length));
-
-local void send_bits(s, value, length)
-    deflate_state *s;
-    int value;  /* value to send */
-    int length; /* number of bits */
-{
-    Tracevv((stderr," l %2d v %4x ", length, value));
-    Assert(length > 0 && length <= 15, "invalid length");
-    s->bits_sent += (ulg)length;
-
-    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
-     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
-     * unused bits in value.
-     */
-    if (s->bi_valid > (int)Buf_size - length) {
-        s->bi_buf |= (ush)value << s->bi_valid;
-        put_short(s, s->bi_buf);
-        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
-        s->bi_valid += length - Buf_size;
-    } else {
-        s->bi_buf |= (ush)value << s->bi_valid;
-        s->bi_valid += length;
-    }
-}
-#else /* !DEBUG */
-
-#define send_bits(s, value, length) \
-{ int len = length;\
-  if (s->bi_valid > (int)Buf_size - len) {\
-    int val = value;\
-    s->bi_buf |= (ush)val << s->bi_valid;\
-    put_short(s, s->bi_buf);\
-    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
-    s->bi_valid += len - Buf_size;\
-  } else {\
-    s->bi_buf |= (ush)(value) << s->bi_valid;\
-    s->bi_valid += len;\
-  }\
-}
-#endif /* DEBUG */
-
-
-/* the arguments must not have side effects */
-
-/* ===========================================================================
- * Initialize the various 'constant' tables.
- */
-local void tr_static_init()
-{
-#if defined(GEN_TREES_H) || !defined(STDC)
-    static int static_init_done = 0;
-    int n;        /* iterates over tree elements */
-    int bits;     /* bit counter */
-    int length;   /* length value */
-    int code;     /* code value */
-    int dist;     /* distance index */
-    ush bl_count[MAX_BITS+1];
-    /* number of codes at each bit length for an optimal tree */
-
-    if (static_init_done) return;
-
-    /* For some embedded targets, global variables are not initialized: */
-#ifdef NO_INIT_GLOBAL_POINTERS
-    static_l_desc.static_tree = static_ltree;
-    static_l_desc.extra_bits = extra_lbits;
-    static_d_desc.static_tree = static_dtree;
-    static_d_desc.extra_bits = extra_dbits;
-    static_bl_desc.extra_bits = extra_blbits;
-#endif
-
-    /* Initialize the mapping length (0..255) -> length code (0..28) */
-    length = 0;
-    for (code = 0; code < LENGTH_CODES-1; code++) {
-        base_length[code] = length;
-        for (n = 0; n < (1< dist code (0..29) */
-    dist = 0;
-    for (code = 0 ; code < 16; code++) {
-        base_dist[code] = dist;
-        for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */
-    for ( ; code < D_CODES; code++) {
-        base_dist[code] = dist << 7;
-        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
-            _dist_code[256 + dist++] = (uch)code;
-        }
-    }
-    Assert (dist == 256, "tr_static_init: 256+dist != 512");
-
-    /* Construct the codes of the static literal tree */
-    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
-    n = 0;
-    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
-    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
-    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
-    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
-    /* Codes 286 and 287 do not exist, but we must include them in the
-     * tree construction to get a canonical Huffman tree (longest code
-     * all ones)
-     */
-    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
-
-    /* The static distance tree is trivial: */
-    for (n = 0; n < D_CODES; n++) {
-        static_dtree[n].Len = 5;
-        static_dtree[n].Code = bi_reverse((unsigned)n, 5);
-    }
-    static_init_done = 1;
-
-#  ifdef GEN_TREES_H
-    gen_trees_header();
-#  endif
-#endif /* defined(GEN_TREES_H) || !defined(STDC) */
-}
-
-/* ===========================================================================
- * Genererate the file trees.h describing the static trees.
- */
-#ifdef GEN_TREES_H
-#  ifndef DEBUG
-#    include 
-#  endif
-
-#  define SEPARATOR(i, last, width) \
-      ((i) == (last)? "\n};\n\n" :    \
-       ((i) % (width) == (width)-1 ? ",\n" : ", "))
-
-void gen_trees_header()
-{
-    FILE *header = fopen("trees.h", "w");
-    int i;
-
-    Assert (header != NULL, "Can't open trees.h");
-    fprintf(header,
-            "/* header created automatically with -DGEN_TREES_H */\n\n");
-
-    fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
-    for (i = 0; i < L_CODES+2; i++) {
-        fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
-                static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
-    }
-
-    fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
-    for (i = 0; i < D_CODES; i++) {
-        fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
-                static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
-    }
-
-    fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
-    for (i = 0; i < DIST_CODE_LEN; i++) {
-        fprintf(header, "%2u%s", _dist_code[i],
-                SEPARATOR(i, DIST_CODE_LEN-1, 20));
-    }
-
-    fprintf(header,
-        "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
-    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
-        fprintf(header, "%2u%s", _length_code[i],
-                SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
-    }
-
-    fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
-    for (i = 0; i < LENGTH_CODES; i++) {
-        fprintf(header, "%1u%s", base_length[i],
-                SEPARATOR(i, LENGTH_CODES-1, 20));
-    }
-
-    fprintf(header, "local const int base_dist[D_CODES] = {\n");
-    for (i = 0; i < D_CODES; i++) {
-        fprintf(header, "%5u%s", base_dist[i],
-                SEPARATOR(i, D_CODES-1, 10));
-    }
-
-    fclose(header);
-}
-#endif /* GEN_TREES_H */
-
-/* ===========================================================================
- * Initialize the tree data structures for a new zlib stream.
- */
-void ZLIB_INTERNAL _tr_init(s)
-    deflate_state *s;
-{
-    tr_static_init();
-
-    s->l_desc.dyn_tree = s->dyn_ltree;
-    s->l_desc.stat_desc = &static_l_desc;
-
-    s->d_desc.dyn_tree = s->dyn_dtree;
-    s->d_desc.stat_desc = &static_d_desc;
-
-    s->bl_desc.dyn_tree = s->bl_tree;
-    s->bl_desc.stat_desc = &static_bl_desc;
-
-    s->bi_buf = 0;
-    s->bi_valid = 0;
-    s->last_eob_len = 8; /* enough lookahead for inflate */
-#ifdef DEBUG
-    s->compressed_len = 0L;
-    s->bits_sent = 0L;
-#endif
-
-    /* Initialize the first block of the first file: */
-    init_block(s);
-}
-
-/* ===========================================================================
- * Initialize a new block.
- */
-local void init_block(s)
-    deflate_state *s;
-{
-    int n; /* iterates over tree elements */
-
-    /* Initialize the trees. */
-    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
-    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
-    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
-
-    s->dyn_ltree[END_BLOCK].Freq = 1;
-    s->opt_len = s->static_len = 0L;
-    s->last_lit = s->matches = 0;
-}
-
-#define SMALLEST 1
-/* Index within the heap array of least frequent node in the Huffman tree */
-
-
-/* ===========================================================================
- * Remove the smallest element from the heap and recreate the heap with
- * one less element. Updates heap and heap_len.
- */
-#define pqremove(s, tree, top) \
-{\
-    top = s->heap[SMALLEST]; \
-    s->heap[SMALLEST] = s->heap[s->heap_len--]; \
-    pqdownheap(s, tree, SMALLEST); \
-}
-
-/* ===========================================================================
- * Compares to subtrees, using the tree depth as tie breaker when
- * the subtrees have equal frequency. This minimizes the worst case length.
- */
-#define smaller(tree, n, m, depth) \
-   (tree[n].Freq < tree[m].Freq || \
-   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
-
-/* ===========================================================================
- * Restore the heap property by moving down the tree starting at node k,
- * exchanging a node with the smallest of its two sons if necessary, stopping
- * when the heap property is re-established (each father smaller than its
- * two sons).
- */
-local void pqdownheap(s, tree, k)
-    deflate_state *s;
-    ct_data *tree;  /* the tree to restore */
-    int k;               /* node to move down */
-{
-    int v = s->heap[k];
-    int j = k << 1;  /* left son of k */
-    while (j <= s->heap_len) {
-        /* Set j to the smallest of the two sons: */
-        if (j < s->heap_len &&
-            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
-            j++;
-        }
-        /* Exit if v is smaller than both sons */
-        if (smaller(tree, v, s->heap[j], s->depth)) break;
-
-        /* Exchange v with the smallest son */
-        s->heap[k] = s->heap[j];  k = j;
-
-        /* And continue down the tree, setting j to the left son of k */
-        j <<= 1;
-    }
-    s->heap[k] = v;
-}
-
-/* ===========================================================================
- * Compute the optimal bit lengths for a tree and update the total bit length
- * for the current block.
- * IN assertion: the fields freq and dad are set, heap[heap_max] and
- *    above are the tree nodes sorted by increasing frequency.
- * OUT assertions: the field len is set to the optimal bit length, the
- *     array bl_count contains the frequencies for each bit length.
- *     The length opt_len is updated; static_len is also updated if stree is
- *     not null.
- */
-local void gen_bitlen(s, desc)
-    deflate_state *s;
-    tree_desc *desc;    /* the tree descriptor */
-{
-    ct_data *tree        = desc->dyn_tree;
-    int max_code         = desc->max_code;
-    const ct_data *stree = desc->stat_desc->static_tree;
-    const intf *extra    = desc->stat_desc->extra_bits;
-    int base             = desc->stat_desc->extra_base;
-    int max_length       = desc->stat_desc->max_length;
-    int h;              /* heap index */
-    int n, m;           /* iterate over the tree elements */
-    int bits;           /* bit length */
-    int xbits;          /* extra bits */
-    ush f;              /* frequency */
-    int overflow = 0;   /* number of elements with bit length too large */
-
-    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
-
-    /* In a first pass, compute the optimal bit lengths (which may
-     * overflow in the case of the bit length tree).
-     */
-    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
-
-    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
-        n = s->heap[h];
-        bits = tree[tree[n].Dad].Len + 1;
-        if (bits > max_length) bits = max_length, overflow++;
-        tree[n].Len = (ush)bits;
-        /* We overwrite tree[n].Dad which is no longer needed */
-
-        if (n > max_code) continue; /* not a leaf node */
-
-        s->bl_count[bits]++;
-        xbits = 0;
-        if (n >= base) xbits = extra[n-base];
-        f = tree[n].Freq;
-        s->opt_len += (ulg)f * (bits + xbits);
-        if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
-    }
-    if (overflow == 0) return;
-
-    Trace((stderr,"\nbit length overflow\n"));
-    /* This happens for example on obj2 and pic of the Calgary corpus */
-
-    /* Find the first bit length which could increase: */
-    do {
-        bits = max_length-1;
-        while (s->bl_count[bits] == 0) bits--;
-        s->bl_count[bits]--;      /* move one leaf down the tree */
-        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
-        s->bl_count[max_length]--;
-        /* The brother of the overflow item also moves one step up,
-         * but this does not affect bl_count[max_length]
-         */
-        overflow -= 2;
-    } while (overflow > 0);
-
-    /* Now recompute all bit lengths, scanning in increasing frequency.
-     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
-     * lengths instead of fixing only the wrong ones. This idea is taken
-     * from 'ar' written by Haruhiko Okumura.)
-     */
-    for (bits = max_length; bits != 0; bits--) {
-        n = s->bl_count[bits];
-        while (n != 0) {
-            m = s->heap[--h];
-            if (m > max_code) continue;
-            if ((unsigned) tree[m].Len != (unsigned) bits) {
-                Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
-                s->opt_len += ((long)bits - (long)tree[m].Len)
-                              *(long)tree[m].Freq;
-                tree[m].Len = (ush)bits;
-            }
-            n--;
-        }
-    }
-}
-
-/* ===========================================================================
- * Generate the codes for a given tree and bit counts (which need not be
- * optimal).
- * IN assertion: the array bl_count contains the bit length statistics for
- * the given tree and the field len is set for all tree elements.
- * OUT assertion: the field code is set for all tree elements of non
- *     zero code length.
- */
-local void gen_codes (tree, max_code, bl_count)
-    ct_data *tree;             /* the tree to decorate */
-    int max_code;              /* largest code with non zero frequency */
-    ushf *bl_count;            /* number of codes at each bit length */
-{
-    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
-    ush code = 0;              /* running code value */
-    int bits;                  /* bit index */
-    int n;                     /* code index */
-
-    /* The distribution counts are first used to generate the code values
-     * without bit reversal.
-     */
-    for (bits = 1; bits <= MAX_BITS; bits++) {
-        next_code[bits] = code = (code + bl_count[bits-1]) << 1;
-    }
-    /* Check that the bit counts in bl_count are consistent. The last code
-     * must be all ones.
-     */
-    Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree;
-    const ct_data *stree  = desc->stat_desc->static_tree;
-    int elems             = desc->stat_desc->elems;
-    int n, m;          /* iterate over heap elements */
-    int max_code = -1; /* largest code with non zero frequency */
-    int node;          /* new node being created */
-
-    /* Construct the initial heap, with least frequent element in
-     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
-     * heap[0] is not used.
-     */
-    s->heap_len = 0, s->heap_max = HEAP_SIZE;
-
-    for (n = 0; n < elems; n++) {
-        if (tree[n].Freq != 0) {
-            s->heap[++(s->heap_len)] = max_code = n;
-            s->depth[n] = 0;
-        } else {
-            tree[n].Len = 0;
-        }
-    }
-
-    /* The pkzip format requires that at least one distance code exists,
-     * and that at least one bit should be sent even if there is only one
-     * possible code. So to avoid special checks later on we force at least
-     * two codes of non zero frequency.
-     */
-    while (s->heap_len < 2) {
-        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
-        tree[node].Freq = 1;
-        s->depth[node] = 0;
-        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
-        /* node is 0 or 1 so it does not have extra bits */
-    }
-    desc->max_code = max_code;
-
-    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
-     * establish sub-heaps of increasing lengths:
-     */
-    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
-
-    /* Construct the Huffman tree by repeatedly combining the least two
-     * frequent nodes.
-     */
-    node = elems;              /* next internal node of the tree */
-    do {
-        pqremove(s, tree, n);  /* n = node of least frequency */
-        m = s->heap[SMALLEST]; /* m = node of next least frequency */
-
-        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
-        s->heap[--(s->heap_max)] = m;
-
-        /* Create a new node father of n and m */
-        tree[node].Freq = tree[n].Freq + tree[m].Freq;
-        s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
-                                s->depth[n] : s->depth[m]) + 1);
-        tree[n].Dad = tree[m].Dad = (ush)node;
-#ifdef DUMP_BL_TREE
-        if (tree == s->bl_tree) {
-            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
-                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
-        }
-#endif
-        /* and insert the new node in the heap */
-        s->heap[SMALLEST] = node++;
-        pqdownheap(s, tree, SMALLEST);
-
-    } while (s->heap_len >= 2);
-
-    s->heap[--(s->heap_max)] = s->heap[SMALLEST];
-
-    /* At this point, the fields freq and dad are set. We can now
-     * generate the bit lengths.
-     */
-    gen_bitlen(s, (tree_desc *)desc);
-
-    /* The field len is now set, we can generate the bit codes */
-    gen_codes ((ct_data *)tree, max_code, s->bl_count);
-}
-
-/* ===========================================================================
- * Scan a literal or distance tree to determine the frequencies of the codes
- * in the bit length tree.
- */
-local void scan_tree (s, tree, max_code)
-    deflate_state *s;
-    ct_data *tree;   /* the tree to be scanned */
-    int max_code;    /* and its largest code of non zero frequency */
-{
-    int n;                     /* iterates over all tree elements */
-    int prevlen = -1;          /* last emitted length */
-    int curlen;                /* length of current code */
-    int nextlen = tree[0].Len; /* length of next code */
-    int count = 0;             /* repeat count of the current code */
-    int max_count = 7;         /* max repeat count */
-    int min_count = 4;         /* min repeat count */
-
-    if (nextlen == 0) max_count = 138, min_count = 3;
-    tree[max_code+1].Len = (ush)0xffff; /* guard */
-
-    for (n = 0; n <= max_code; n++) {
-        curlen = nextlen; nextlen = tree[n+1].Len;
-        if (++count < max_count && curlen == nextlen) {
-            continue;
-        } else if (count < min_count) {
-            s->bl_tree[curlen].Freq += count;
-        } else if (curlen != 0) {
-            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
-            s->bl_tree[REP_3_6].Freq++;
-        } else if (count <= 10) {
-            s->bl_tree[REPZ_3_10].Freq++;
-        } else {
-            s->bl_tree[REPZ_11_138].Freq++;
-        }
-        count = 0; prevlen = curlen;
-        if (nextlen == 0) {
-            max_count = 138, min_count = 3;
-        } else if (curlen == nextlen) {
-            max_count = 6, min_count = 3;
-        } else {
-            max_count = 7, min_count = 4;
-        }
-    }
-}
-
-/* ===========================================================================
- * Send a literal or distance tree in compressed form, using the codes in
- * bl_tree.
- */
-local void send_tree (s, tree, max_code)
-    deflate_state *s;
-    ct_data *tree; /* the tree to be scanned */
-    int max_code;       /* and its largest code of non zero frequency */
-{
-    int n;                     /* iterates over all tree elements */
-    int prevlen = -1;          /* last emitted length */
-    int curlen;                /* length of current code */
-    int nextlen = tree[0].Len; /* length of next code */
-    int count = 0;             /* repeat count of the current code */
-    int max_count = 7;         /* max repeat count */
-    int min_count = 4;         /* min repeat count */
-
-    /* tree[max_code+1].Len = -1; */  /* guard already set */
-    if (nextlen == 0) max_count = 138, min_count = 3;
-
-    for (n = 0; n <= max_code; n++) {
-        curlen = nextlen; nextlen = tree[n+1].Len;
-        if (++count < max_count && curlen == nextlen) {
-            continue;
-        } else if (count < min_count) {
-            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
-
-        } else if (curlen != 0) {
-            if (curlen != prevlen) {
-                send_code(s, curlen, s->bl_tree); count--;
-            }
-            Assert(count >= 3 && count <= 6, " 3_6?");
-            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
-
-        } else if (count <= 10) {
-            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
-
-        } else {
-            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
-        }
-        count = 0; prevlen = curlen;
-        if (nextlen == 0) {
-            max_count = 138, min_count = 3;
-        } else if (curlen == nextlen) {
-            max_count = 6, min_count = 3;
-        } else {
-            max_count = 7, min_count = 4;
-        }
-    }
-}
-
-/* ===========================================================================
- * Construct the Huffman tree for the bit lengths and return the index in
- * bl_order of the last bit length code to send.
- */
-local int build_bl_tree(s)
-    deflate_state *s;
-{
-    int max_blindex;  /* index of last bit length code of non zero freq */
-
-    /* Determine the bit length frequencies for literal and distance trees */
-    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
-    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
-
-    /* Build the bit length tree: */
-    build_tree(s, (tree_desc *)(&(s->bl_desc)));
-    /* opt_len now includes the length of the tree representations, except
-     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
-     */
-
-    /* Determine the number of bit length codes to send. The pkzip format
-     * requires that at least 4 bit length codes be sent. (appnote.txt says
-     * 3 but the actual value used is 4.)
-     */
-    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
-        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
-    }
-    /* Update opt_len to include the bit length tree and counts */
-    s->opt_len += 3*(max_blindex+1) + 5+5+4;
-    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
-            s->opt_len, s->static_len));
-
-    return max_blindex;
-}
-
-/* ===========================================================================
- * Send the header for a block using dynamic Huffman trees: the counts, the
- * lengths of the bit length codes, the literal tree and the distance tree.
- * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
- */
-local void send_all_trees(s, lcodes, dcodes, blcodes)
-    deflate_state *s;
-    int lcodes, dcodes, blcodes; /* number of codes for each tree */
-{
-    int rank;                    /* index in bl_order */
-
-    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
-    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
-            "too many codes");
-    Tracev((stderr, "\nbl counts: "));
-    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
-    send_bits(s, dcodes-1,   5);
-    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
-    for (rank = 0; rank < blcodes; rank++) {
-        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
-        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
-    }
-    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
-
-    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
-    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
-
-    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
-    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
-}
-
-/* ===========================================================================
- * Send a stored block
- */
-void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
-    deflate_state *s;
-    charf *buf;       /* input block */
-    ulg stored_len;   /* length of input block */
-    int last;         /* one if this is the last block for a file */
-{
-    send_bits(s, (STORED_BLOCK<<1)+last, 3);    /* send block type */
-#ifdef DEBUG
-    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
-    s->compressed_len += (stored_len + 4) << 3;
-#endif
-    copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
-}
-
-/* ===========================================================================
- * Send one empty static block to give enough lookahead for inflate.
- * This takes 10 bits, of which 7 may remain in the bit buffer.
- * The current inflate code requires 9 bits of lookahead. If the
- * last two codes for the previous block (real code plus EOB) were coded
- * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
- * the last real code. In this case we send two empty static blocks instead
- * of one. (There are no problems if the previous block is stored or fixed.)
- * To simplify the code, we assume the worst case of last real code encoded
- * on one bit only.
- */
-void ZLIB_INTERNAL _tr_align(s)
-    deflate_state *s;
-{
-    send_bits(s, STATIC_TREES<<1, 3);
-    send_code(s, END_BLOCK, static_ltree);
-#ifdef DEBUG
-    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
-#endif
-    bi_flush(s);
-    /* Of the 10 bits for the empty block, we have already sent
-     * (10 - bi_valid) bits. The lookahead for the last real code (before
-     * the EOB of the previous block) was thus at least one plus the length
-     * of the EOB plus what we have just sent of the empty static block.
-     */
-    if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
-        send_bits(s, STATIC_TREES<<1, 3);
-        send_code(s, END_BLOCK, static_ltree);
-#ifdef DEBUG
-        s->compressed_len += 10L;
-#endif
-        bi_flush(s);
-    }
-    s->last_eob_len = 7;
-}
-
-/* ===========================================================================
- * Determine the best encoding for the current block: dynamic trees, static
- * trees or store, and output the encoded block to the zip file.
- */
-void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
-    deflate_state *s;
-    charf *buf;       /* input block, or NULL if too old */
-    ulg stored_len;   /* length of input block */
-    int last;         /* one if this is the last block for a file */
-{
-    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
-    int max_blindex = 0;  /* index of last bit length code of non zero freq */
-
-    /* Build the Huffman trees unless a stored block is forced */
-    if (s->level > 0) {
-
-        /* Check if the file is binary or text */
-        if (s->strm->data_type == Z_UNKNOWN)
-            s->strm->data_type = detect_data_type(s);
-
-        /* Construct the literal and distance trees */
-        build_tree(s, (tree_desc *)(&(s->l_desc)));
-        Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
-                s->static_len));
-
-        build_tree(s, (tree_desc *)(&(s->d_desc)));
-        Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
-                s->static_len));
-        /* At this point, opt_len and static_len are the total bit lengths of
-         * the compressed block data, excluding the tree representations.
-         */
-
-        /* Build the bit length tree for the above two trees, and get the index
-         * in bl_order of the last bit length code to send.
-         */
-        max_blindex = build_bl_tree(s);
-
-        /* Determine the best encoding. Compute the block lengths in bytes. */
-        opt_lenb = (s->opt_len+3+7)>>3;
-        static_lenb = (s->static_len+3+7)>>3;
-
-        Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
-                opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
-                s->last_lit));
-
-        if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
-
-    } else {
-        Assert(buf != (char*)0, "lost buf");
-        opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
-    }
-
-#ifdef FORCE_STORED
-    if (buf != (char*)0) { /* force stored block */
-#else
-    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
-                       /* 4: two words for the lengths */
-#endif
-        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
-         * Otherwise we can't have processed more than WSIZE input bytes since
-         * the last block flush, because compression would have been
-         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
-         * transform a block into a stored block.
-         */
-        _tr_stored_block(s, buf, stored_len, last);
-
-#ifdef FORCE_STATIC
-    } else if (static_lenb >= 0) { /* force static trees */
-#else
-    } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
-#endif
-        send_bits(s, (STATIC_TREES<<1)+last, 3);
-        compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
-#ifdef DEBUG
-        s->compressed_len += 3 + s->static_len;
-#endif
-    } else {
-        send_bits(s, (DYN_TREES<<1)+last, 3);
-        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
-                       max_blindex+1);
-        compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
-#ifdef DEBUG
-        s->compressed_len += 3 + s->opt_len;
-#endif
-    }
-    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
-    /* The above check is made mod 2^32, for files larger than 512 MB
-     * and uLong implemented on 32 bits.
-     */
-    init_block(s);
-
-    if (last) {
-        bi_windup(s);
-#ifdef DEBUG
-        s->compressed_len += 7;  /* align on byte boundary */
-#endif
-    }
-    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
-           s->compressed_len-7*last));
-}
-
-/* ===========================================================================
- * Save the match info and tally the frequency counts. Return true if
- * the current block must be flushed.
- */
-int ZLIB_INTERNAL _tr_tally (s, dist, lc)
-    deflate_state *s;
-    unsigned dist;  /* distance of matched string */
-    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
-{
-    s->d_buf[s->last_lit] = (ush)dist;
-    s->l_buf[s->last_lit++] = (uch)lc;
-    if (dist == 0) {
-        /* lc is the unmatched char */
-        s->dyn_ltree[lc].Freq++;
-    } else {
-        s->matches++;
-        /* Here, lc is the match length - MIN_MATCH */
-        dist--;             /* dist = match distance - 1 */
-        Assert((ush)dist < (ush)MAX_DIST(s) &&
-               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
-               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
-
-        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
-        s->dyn_dtree[d_code(dist)].Freq++;
-    }
-
-#ifdef TRUNCATE_BLOCK
-    /* Try to guess if it is profitable to stop the current block here */
-    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
-        /* Compute an upper bound for the compressed length */
-        ulg out_length = (ulg)s->last_lit*8L;
-        ulg in_length = (ulg)((long)s->strstart - s->block_start);
-        int dcode;
-        for (dcode = 0; dcode < D_CODES; dcode++) {
-            out_length += (ulg)s->dyn_dtree[dcode].Freq *
-                (5L+extra_dbits[dcode]);
-        }
-        out_length >>= 3;
-        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
-               s->last_lit, in_length, out_length,
-               100L - out_length*100L/in_length));
-        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
-    }
-#endif
-    return (s->last_lit == s->lit_bufsize-1);
-    /* We avoid equality with lit_bufsize because of wraparound at 64K
-     * on 16 bit machines and because stored blocks are restricted to
-     * 64K-1 bytes.
-     */
-}
-
-/* ===========================================================================
- * Send the block data compressed using the given Huffman trees
- */
-local void compress_block(s, ltree, dtree)
-    deflate_state *s;
-    ct_data *ltree; /* literal tree */
-    ct_data *dtree; /* distance tree */
-{
-    unsigned dist;      /* distance of matched string */
-    int lc;             /* match length or unmatched char (if dist == 0) */
-    unsigned lx = 0;    /* running index in l_buf */
-    unsigned code;      /* the code to send */
-    int extra;          /* number of extra bits to send */
-
-    if (s->last_lit != 0) do {
-        dist = s->d_buf[lx];
-        lc = s->l_buf[lx++];
-        if (dist == 0) {
-            send_code(s, lc, ltree); /* send a literal byte */
-            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
-        } else {
-            /* Here, lc is the match length - MIN_MATCH */
-            code = _length_code[lc];
-            send_code(s, code+LITERALS+1, ltree); /* send the length code */
-            extra = extra_lbits[code];
-            if (extra != 0) {
-                lc -= base_length[code];
-                send_bits(s, lc, extra);       /* send the extra length bits */
-            }
-            dist--; /* dist is now the match distance - 1 */
-            code = d_code(dist);
-            Assert (code < D_CODES, "bad d_code");
-
-            send_code(s, code, dtree);       /* send the distance code */
-            extra = extra_dbits[code];
-            if (extra != 0) {
-                dist -= base_dist[code];
-                send_bits(s, dist, extra);   /* send the extra distance bits */
-            }
-        } /* literal or match pair ? */
-
-        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
-        Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
-               "pendingBuf overflow");
-
-    } while (lx < s->last_lit);
-
-    send_code(s, END_BLOCK, ltree);
-    s->last_eob_len = ltree[END_BLOCK].Len;
-}
-
-/* ===========================================================================
- * Check if the data type is TEXT or BINARY, using the following algorithm:
- * - TEXT if the two conditions below are satisfied:
- *    a) There are no non-portable control characters belonging to the
- *       "black list" (0..6, 14..25, 28..31).
- *    b) There is at least one printable character belonging to the
- *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
- * - BINARY otherwise.
- * - The following partially-portable control characters form a
- *   "gray list" that is ignored in this detection algorithm:
- *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
- * IN assertion: the fields Freq of dyn_ltree are set.
- */
-local int detect_data_type(s)
-    deflate_state *s;
-{
-    /* black_mask is the bit mask of black-listed bytes
-     * set bits 0..6, 14..25, and 28..31
-     * 0xf3ffc07f = binary 11110011111111111100000001111111
-     */
-    unsigned long black_mask = 0xf3ffc07fUL;
-    int n;
-
-    /* Check for non-textual ("black-listed") bytes. */
-    for (n = 0; n <= 31; n++, black_mask >>= 1)
-        if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
-            return Z_BINARY;
-
-    /* Check for textual ("white-listed") bytes. */
-    if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
-            || s->dyn_ltree[13].Freq != 0)
-        return Z_TEXT;
-    for (n = 32; n < LITERALS; n++)
-        if (s->dyn_ltree[n].Freq != 0)
-            return Z_TEXT;
-
-    /* There are no "black-listed" or "white-listed" bytes:
-     * this stream either is empty or has tolerated ("gray-listed") bytes only.
-     */
-    return Z_BINARY;
-}
-
-/* ===========================================================================
- * Reverse the first len bits of a code, using straightforward code (a faster
- * method would use a table)
- * IN assertion: 1 <= len <= 15
- */
-local unsigned bi_reverse(code, len)
-    unsigned code; /* the value to invert */
-    int len;       /* its bit length */
-{
-    register unsigned res = 0;
-    do {
-        res |= code & 1;
-        code >>= 1, res <<= 1;
-    } while (--len > 0);
-    return res >> 1;
-}
-
-/* ===========================================================================
- * Flush the bit buffer, keeping at most 7 bits in it.
- */
-local void bi_flush(s)
-    deflate_state *s;
-{
-    if (s->bi_valid == 16) {
-        put_short(s, s->bi_buf);
-        s->bi_buf = 0;
-        s->bi_valid = 0;
-    } else if (s->bi_valid >= 8) {
-        put_byte(s, (Byte)s->bi_buf);
-        s->bi_buf >>= 8;
-        s->bi_valid -= 8;
-    }
-}
-
-/* ===========================================================================
- * Flush the bit buffer and align the output on a byte boundary
- */
-local void bi_windup(s)
-    deflate_state *s;
-{
-    if (s->bi_valid > 8) {
-        put_short(s, s->bi_buf);
-    } else if (s->bi_valid > 0) {
-        put_byte(s, (Byte)s->bi_buf);
-    }
-    s->bi_buf = 0;
-    s->bi_valid = 0;
-#ifdef DEBUG
-    s->bits_sent = (s->bits_sent+7) & ~7;
-#endif
-}
-
-/* ===========================================================================
- * Copy a stored block, storing first the length and its
- * one's complement if requested.
- */
-local void copy_block(s, buf, len, header)
-    deflate_state *s;
-    charf    *buf;    /* the input data */
-    unsigned len;     /* its length */
-    int      header;  /* true if block header must be written */
-{
-    bi_windup(s);        /* align on byte boundary */
-    s->last_eob_len = 8; /* enough lookahead for inflate */
-
-    if (header) {
-        put_short(s, (ush)len);
-        put_short(s, (ush)~len);
-#ifdef DEBUG
-        s->bits_sent += 2*16;
-#endif
-    }
-#ifdef DEBUG
-    s->bits_sent += (ulg)len<<3;
-#endif
-    while (len--) {
-        put_byte(s, *buf++);
-    }
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/trees.h b/src/external/OpenGR/3rdparty/cfitsio/zlib/trees.h
deleted file mode 100644
index d35639d82..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/trees.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* header created automatically with -DGEN_TREES_H */
-
-local const ct_data static_ltree[L_CODES+2] = {
-{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},
-{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},
-{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},
-{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},
-{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},
-{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},
-{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},
-{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},
-{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},
-{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},
-{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},
-{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},
-{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},
-{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},
-{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},
-{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},
-{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},
-{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},
-{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},
-{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},
-{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},
-{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},
-{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},
-{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},
-{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},
-{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},
-{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},
-{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},
-{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},
-{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},
-{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},
-{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},
-{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},
-{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},
-{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},
-{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},
-{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},
-{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},
-{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},
-{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},
-{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},
-{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},
-{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},
-{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},
-{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},
-{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},
-{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},
-{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},
-{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},
-{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},
-{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},
-{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},
-{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},
-{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},
-{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},
-{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},
-{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},
-{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}
-};
-
-local const ct_data static_dtree[D_CODES] = {
-{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
-{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
-{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
-{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
-{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
-{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
-};
-
-const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
- 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
- 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
-10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
-11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
-13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
-15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
-18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
-23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
-27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
-28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
-28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
-28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
-};
-
-const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
- 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
-13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
-17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
-19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
-21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
-22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
-23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
-26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
-};
-
-local const int base_length[LENGTH_CODES] = {
-0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
-64, 80, 96, 112, 128, 160, 192, 224, 0
-};
-
-local const int base_dist[D_CODES] = {
-    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,
-   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,
- 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
-};
-
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/uncompr.c b/src/external/OpenGR/3rdparty/cfitsio/zlib/uncompr.c
deleted file mode 100644
index 769f83ee0..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/uncompr.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* uncompr.c -- decompress a memory buffer
- * Copyright (C) 1995-2003, 2010 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#define ZLIB_INTERNAL
-#include "zlib.h"
-
-/* ===========================================================================
-     Decompresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer. Upon entry, destLen is the total
-   size of the destination buffer, which must be large enough to hold the
-   entire uncompressed data. (The size of the uncompressed data must have
-   been saved previously by the compressor and transmitted to the decompressor
-   by some mechanism outside the scope of this compression library.)
-   Upon exit, destLen is the actual size of the compressed buffer.
-
-     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_BUF_ERROR if there was not enough room in the output
-   buffer, or Z_DATA_ERROR if the input data was corrupted.
-*/
-int ZEXPORT uncompress (dest, destLen, source, sourceLen)
-    Bytef *dest;
-    uLongf *destLen;
-    const Bytef *source;
-    uLong sourceLen;
-{
-    z_stream stream;
-    int err;
-
-    stream.next_in = (Bytef*)source;
-    stream.avail_in = (uInt)sourceLen;
-    /* Check for source > 64K on 16-bit machine: */
-    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
-
-    stream.next_out = dest;
-    stream.avail_out = (uInt)*destLen;
-    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
-
-    stream.zalloc = (alloc_func)0;
-    stream.zfree = (free_func)0;
-
-    err = inflateInit(&stream);
-    if (err != Z_OK) return err;
-
-    err = inflate(&stream, Z_FINISH);
-    if (err != Z_STREAM_END) {
-        inflateEnd(&stream);
-        if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
-            return Z_DATA_ERROR;
-        return err;
-    }
-    *destLen = stream.total_out;
-
-    err = inflateEnd(&stream);
-    return err;
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/zcompress.c b/src/external/OpenGR/3rdparty/cfitsio/zlib/zcompress.c
deleted file mode 100644
index d425aec4f..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/zcompress.c
+++ /dev/null
@@ -1,531 +0,0 @@
-#include 
-#include 
-#include 
-#include 
-#include 
-#include "zlib.h"  
-
-#define GZBUFSIZE 115200    /* 40 FITS blocks */
-#define BUFFINCR   28800    /* 10 FITS blocks */
-
-/* prototype for the following functions */
-int uncompress2mem(char *filename, 
-             FILE *diskfile, 
-             char **buffptr, 
-             size_t *buffsize, 
-             void *(*mem_realloc)(void *p, size_t newsize),
-             size_t *filesize,
-             int *status);
-
-int uncompress2mem_from_mem(                                                
-             char *inmemptr,     
-             size_t inmemsize, 
-             char **buffptr,  
-             size_t *buffsize,  
-             void *(*mem_realloc)(void *p, size_t newsize), 
-             size_t *filesize,  
-             int *status);
-
-int uncompress2file(char *filename, 
-             FILE *indiskfile, 
-             FILE *outdiskfile, 
-             int *status);
-
-
-int compress2mem_from_mem(                                                
-             char *inmemptr,     
-             size_t inmemsize, 
-             char **buffptr,  
-             size_t *buffsize,  
-             void *(*mem_realloc)(void *p, size_t newsize), 
-             size_t *filesize,  
-             int *status);
-
-int compress2file_from_mem(                                                
-             char *inmemptr,     
-             size_t inmemsize, 
-             FILE *outdiskfile, 
-             size_t *filesize,   /* O - size of file, in bytes              */
-             int *status);
-
-
-/*--------------------------------------------------------------------------*/
-int uncompress2mem(char *filename,  /* name of input file                 */
-             FILE *diskfile,     /* I - file pointer                        */
-             char **buffptr,   /* IO - memory pointer                     */
-             size_t *buffsize,   /* IO - size of buffer, in bytes           */
-             void *(*mem_realloc)(void *p, size_t newsize), /* function     */
-             size_t *filesize,   /* O - size of file, in bytes              */
-             int *status)        /* IO - error status                       */
-
-/*
-  Uncompress the disk file into memory.  Fill whatever amount of memory has
-  already been allocated, then realloc more memory, using the supplied
-  input function, if necessary.
-*/
-{
-    int err, len;
-    char *filebuff;
-    z_stream d_stream;   /* decompression stream */
-    /* Input args buffptr and buffsize may refer to a block of memory
-        larger than the 2^32 4 byte limit.  If so, must be broken
-        up into "pages" when assigned to d_stream.  
-        (d_stream.avail_out is a uInt type, which might be smaller
-        than buffsize's size_t type.)
-    */
-    const uLong nPages = (uLong)(*buffsize)/(uLong)UINT_MAX;
-    uLong iPage=0;
-    uInt outbuffsize = (nPages > 0) ? UINT_MAX : (uInt)(*buffsize);
-    
-
-    if (*status > 0) 
-        return(*status); 
-
-    /* Allocate memory to hold compressed bytes read from the file. */
-    filebuff = (char*)malloc(GZBUFSIZE);
-    if (!filebuff) return(*status = 113); /* memory error */
-
-    d_stream.zalloc = (alloc_func)0;
-    d_stream.zfree = (free_func)0;
-    d_stream.opaque = (voidpf)0;
-    d_stream.next_out = (unsigned char*) *buffptr;
-    d_stream.avail_out = outbuffsize;
-
-    /* Initialize the decompression.  The argument (15+16) tells the
-       decompressor that we are to use the gzip algorithm */
-
-    err = inflateInit2(&d_stream, (15+16));
-    if (err != Z_OK) return(*status = 414);
-
-    /* loop through the file, reading a buffer and uncompressing it */
-    for (;;)
-    {
-        len = fread(filebuff, 1, GZBUFSIZE, diskfile);
-	if (ferror(diskfile)) {
-              inflateEnd(&d_stream);
-              free(filebuff);
-              return(*status = 414);
-	}
-
-        if (len == 0) break;  /* no more data */
-
-        d_stream.next_in = (unsigned char*)filebuff;
-        d_stream.avail_in = len;
-
-        for (;;) {
-            /* uncompress as much of the input as will fit in the output */
-            err = inflate(&d_stream, Z_NO_FLUSH);
-
-            if (err == Z_STREAM_END ) { /* We reached the end of the input */
-	        break; 
-            } else if (err == Z_OK ) { 
-
-                if (!d_stream.avail_in) break; /* need more input */
-		
-                /* need more space in output buffer */
-                /* First check if more memory is available above the
-                    4Gb limit in the originally input buffptr array */
-                if (iPage < nPages)
-                {
-                   ++iPage;
-                   d_stream.next_out = (unsigned char*)(*buffptr + iPage*(uLong)UINT_MAX);
-                   if (iPage < nPages)
-                      d_stream.avail_out = UINT_MAX;
-                   else
-                      d_stream.avail_out = (uInt)((uLong)(*buffsize) % (uLong)UINT_MAX);
-                }
-                else if (mem_realloc) {   
-                    *buffptr = mem_realloc(*buffptr,*buffsize + BUFFINCR);
-                    if (*buffptr == NULL){
-                        inflateEnd(&d_stream);
-                        free(filebuff);
-                        return(*status = 414);  /* memory allocation failed */
-                    }
-
-                    d_stream.avail_out = BUFFINCR;
-                    d_stream.next_out = (unsigned char*) (*buffptr + *buffsize);
-                    *buffsize = *buffsize + BUFFINCR;
-                } else  { /* error: no realloc function available */
-                    inflateEnd(&d_stream);
-                    free(filebuff);
-                    return(*status = 414);
-                }
-            } else {  /* some other error */
-                inflateEnd(&d_stream);
-                free(filebuff);
-                return(*status = 414);
-            }
-        }
-	
-	if (feof(diskfile))  break;
-/*     
-        These settings for next_out and avail_out appear to be redundant,
-        as the inflate() function should already be re-setting these.
-        For case where *buffsize < 4Gb this did not matter, but for
-        > 4Gb it would produce the wrong value in the avail_out assignment.
-        (C. Gordon Jul 2016)
-        d_stream.next_out = (unsigned char*) (*buffptr + d_stream.total_out);
-        d_stream.avail_out = *buffsize - d_stream.total_out;
-*/    }
-
-    /* Set the output file size to be the total output data */
-    *filesize = d_stream.total_out;
-    
-    free(filebuff); /* free temporary output data buffer */
-    
-    err = inflateEnd(&d_stream); /* End the decompression */
-    if (err != Z_OK) return(*status = 414);
-  
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int uncompress2mem_from_mem(                                                
-             char *inmemptr,     /* I - memory pointer to compressed bytes */
-             size_t inmemsize,   /* I - size of input compressed file      */
-             char **buffptr,   /* IO - memory pointer                      */
-             size_t *buffsize,   /* IO - size of buffer, in bytes           */
-             void *(*mem_realloc)(void *p, size_t newsize), /* function     */
-             size_t *filesize,   /* O - size of file, in bytes              */
-             int *status)        /* IO - error status                       */
-
-/*
-  Uncompress the file in memory into memory.  Fill whatever amount of memory has
-  already been allocated, then realloc more memory, using the supplied
-  input function, if necessary.
-*/
-{
-    int err; 
-    z_stream d_stream;   /* decompression stream */
-
-    if (*status > 0) 
-        return(*status); 
-
-    d_stream.zalloc = (alloc_func)0;
-    d_stream.zfree = (free_func)0;
-    d_stream.opaque = (voidpf)0;
-
-    /* Initialize the decompression.  The argument (15+16) tells the
-       decompressor that we are to use the gzip algorithm */
-    err = inflateInit2(&d_stream, (15+16));
-    if (err != Z_OK) return(*status = 414);
-
-    d_stream.next_in = (unsigned char*)inmemptr;
-    d_stream.avail_in = inmemsize;
-
-    d_stream.next_out = (unsigned char*) *buffptr;
-    d_stream.avail_out = *buffsize;
-
-    for (;;) {
-        /* uncompress as much of the input as will fit in the output */
-        err = inflate(&d_stream, Z_NO_FLUSH);
-
-        if (err == Z_STREAM_END) { /* We reached the end of the input */
-	    break; 
-        } else if (err == Z_OK ) { /* need more space in output buffer */
-
-            if (mem_realloc) {   
-                *buffptr = mem_realloc(*buffptr,*buffsize + BUFFINCR);
-                if (*buffptr == NULL){
-                    inflateEnd(&d_stream);
-                    return(*status = 414);  /* memory allocation failed */
-                }
-
-                d_stream.avail_out = BUFFINCR;
-                d_stream.next_out = (unsigned char*) (*buffptr + *buffsize);
-                *buffsize = *buffsize + BUFFINCR;
-
-            } else  { /* error: no realloc function available */
-                inflateEnd(&d_stream);
-                return(*status = 414);
-            }
-        } else {  /* some other error */
-            inflateEnd(&d_stream);
-            return(*status = 414);
-        }
-    }
-
-    /* Set the output file size to be the total output data */
-    if (filesize) *filesize = d_stream.total_out;
-
-    /* End the decompression */
-    err = inflateEnd(&d_stream);
-
-    if (err != Z_OK) return(*status = 414);
-    
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int uncompress2file(char *filename,  /* name of input file                  */
-             FILE *indiskfile,     /* I - input file pointer                */
-             FILE *outdiskfile,    /* I - output file pointer               */
-             int *status)        /* IO - error status                       */
-/*
-  Uncompress the file into another file. 
-*/
-{
-    int err, len;
-    unsigned long bytes_out = 0;
-    char *infilebuff, *outfilebuff;
-    z_stream d_stream;   /* decompression stream */
-
-    if (*status > 0) 
-        return(*status); 
-
-    /* Allocate buffers to hold compressed and uncompressed */
-    infilebuff = (char*)malloc(GZBUFSIZE);
-    if (!infilebuff) return(*status = 113); /* memory error */
-
-    outfilebuff = (char*)malloc(GZBUFSIZE);
-    if (!outfilebuff) return(*status = 113); /* memory error */
-
-    d_stream.zalloc = (alloc_func)0;
-    d_stream.zfree = (free_func)0;
-    d_stream.opaque = (voidpf)0;
-
-    d_stream.next_out = (unsigned char*) outfilebuff;
-    d_stream.avail_out = GZBUFSIZE;
-
-    /* Initialize the decompression.  The argument (15+16) tells the
-       decompressor that we are to use the gzip algorithm */
-
-    err = inflateInit2(&d_stream, (15+16));
-    if (err != Z_OK) return(*status = 414);
-
-    /* loop through the file, reading a buffer and uncompressing it */
-    for (;;)
-    {
-        len = fread(infilebuff, 1, GZBUFSIZE, indiskfile);
-	if (ferror(indiskfile)) {
-              inflateEnd(&d_stream);
-              free(infilebuff);
-              free(outfilebuff);
-              return(*status = 414);
-	}
-
-        if (len == 0) break;  /* no more data */
-
-        d_stream.next_in = (unsigned char*)infilebuff;
-        d_stream.avail_in = len;
-
-        for (;;) {
-            /* uncompress as much of the input as will fit in the output */
-            err = inflate(&d_stream, Z_NO_FLUSH);
-
-            if (err == Z_STREAM_END ) { /* We reached the end of the input */
-	        break; 
-            } else if (err == Z_OK ) { 
-
-                if (!d_stream.avail_in) break; /* need more input */
-		
-                /* flush out the full output buffer */
-                if ((int)fwrite(outfilebuff, 1, GZBUFSIZE, outdiskfile) != GZBUFSIZE) {
-                    inflateEnd(&d_stream);
-                    free(infilebuff);
-                    free(outfilebuff);
-                    return(*status = 414);
-                }
-                bytes_out += GZBUFSIZE;
-                d_stream.next_out = (unsigned char*) outfilebuff;
-                d_stream.avail_out = GZBUFSIZE;
-
-            } else {  /* some other error */
-                inflateEnd(&d_stream);
-                free(infilebuff);
-                free(outfilebuff);
-                return(*status = 414);
-            }
-        }
-	
-	if (feof(indiskfile))  break;
-    }
-
-    /* write out any remaining bytes in the buffer */
-    if (d_stream.total_out > bytes_out) {
-        if ((int)fwrite(outfilebuff, 1, (d_stream.total_out - bytes_out), outdiskfile) 
-	    != (d_stream.total_out - bytes_out)) {
-            inflateEnd(&d_stream);
-            free(infilebuff);
-            free(outfilebuff);
-            return(*status = 414);
-        }
-    }
-
-    free(infilebuff); /* free temporary output data buffer */
-    free(outfilebuff); /* free temporary output data buffer */
-
-    err = inflateEnd(&d_stream); /* End the decompression */
-    if (err != Z_OK) return(*status = 414);
-  
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int compress2mem_from_mem(                                                
-             char *inmemptr,     /* I - memory pointer to uncompressed bytes */
-             size_t inmemsize,   /* I - size of input uncompressed file      */
-             char **buffptr,   /* IO - memory pointer for compressed file    */
-             size_t *buffsize,   /* IO - size of buffer, in bytes           */
-             void *(*mem_realloc)(void *p, size_t newsize), /* function     */
-             size_t *filesize,   /* O - size of file, in bytes              */
-             int *status)        /* IO - error status                       */
-
-/*
-  Compress the file into memory.  Fill whatever amount of memory has
-  already been allocated, then realloc more memory, using the supplied
-  input function, if necessary.
-*/
-{
-    int err;
-    z_stream c_stream;  /* compression stream */
-
-    if (*status > 0)
-        return(*status);
-
-    c_stream.zalloc = (alloc_func)0;
-    c_stream.zfree = (free_func)0;
-    c_stream.opaque = (voidpf)0;
-
-    /* Initialize the compression.  The argument (15+16) tells the 
-       compressor that we are to use the gzip algorythm.
-       Also use Z_BEST_SPEED for maximum speed with very minor loss
-       in compression factor. */
-    err = deflateInit2(&c_stream, Z_BEST_SPEED, Z_DEFLATED,
-                       (15+16), 8, Z_DEFAULT_STRATEGY);
-
-    if (err != Z_OK) return(*status = 413);
-
-    c_stream.next_in = (unsigned char*)inmemptr;
-    c_stream.avail_in = inmemsize;
-
-    c_stream.next_out = (unsigned char*) *buffptr;
-    c_stream.avail_out = *buffsize;
-
-    for (;;) {
-        /* compress as much of the input as will fit in the output */
-        err = deflate(&c_stream, Z_FINISH);
-
-        if (err == Z_STREAM_END) {  /* We reached the end of the input */
-	   break;
-        } else if (err == Z_OK ) { /* need more space in output buffer */
-
-            if (mem_realloc) {   
-                *buffptr = mem_realloc(*buffptr,*buffsize + BUFFINCR);
-                if (*buffptr == NULL){
-                    deflateEnd(&c_stream);
-                    return(*status = 413);  /* memory allocation failed */
-                }
-
-                c_stream.avail_out = BUFFINCR;
-                c_stream.next_out = (unsigned char*) (*buffptr + *buffsize);
-                *buffsize = *buffsize + BUFFINCR;
-
-            } else  { /* error: no realloc function available */
-                deflateEnd(&c_stream);
-                return(*status = 413);
-            }
-        } else {  /* some other error */
-            deflateEnd(&c_stream);
-            return(*status = 413);
-        }
-    }
-
-    /* Set the output file size to be the total output data */
-    if (filesize) *filesize = c_stream.total_out;
-
-    /* End the compression */
-    err = deflateEnd(&c_stream);
-
-    if (err != Z_OK) return(*status = 413);
-     
-    return(*status);
-}
-/*--------------------------------------------------------------------------*/
-int compress2file_from_mem(                                                
-             char *inmemptr,     /* I - memory pointer to uncompressed bytes */
-             size_t inmemsize,   /* I - size of input uncompressed file      */
-             FILE *outdiskfile, 
-             size_t *filesize,   /* O - size of file, in bytes              */
-             int *status)
-
-/*
-  Compress the memory file into disk file. 
-*/
-{
-    int err;
-    unsigned long bytes_out = 0;
-    char  *outfilebuff;
-    z_stream c_stream;  /* compression stream */
-
-    if (*status > 0)
-        return(*status);
-
-    /* Allocate buffer to hold compressed bytes */
-    outfilebuff = (char*)malloc(GZBUFSIZE);
-    if (!outfilebuff) return(*status = 113); /* memory error */
-
-    c_stream.zalloc = (alloc_func)0;
-    c_stream.zfree = (free_func)0;
-    c_stream.opaque = (voidpf)0;
-
-    /* Initialize the compression.  The argument (15+16) tells the 
-       compressor that we are to use the gzip algorythm.
-       Also use Z_BEST_SPEED for maximum speed with very minor loss
-       in compression factor. */
-    err = deflateInit2(&c_stream, Z_BEST_SPEED, Z_DEFLATED,
-                       (15+16), 8, Z_DEFAULT_STRATEGY);
-
-    if (err != Z_OK) return(*status = 413);
-
-    c_stream.next_in = (unsigned char*)inmemptr;
-    c_stream.avail_in = inmemsize;
-
-    c_stream.next_out = (unsigned char*) outfilebuff;
-    c_stream.avail_out = GZBUFSIZE;
-
-    for (;;) {
-        /* compress as much of the input as will fit in the output */
-        err = deflate(&c_stream, Z_FINISH);
-
-        if (err == Z_STREAM_END) {  /* We reached the end of the input */
-	   break;
-        } else if (err == Z_OK ) { /* need more space in output buffer */
-
-            /* flush out the full output buffer */
-            if ((int)fwrite(outfilebuff, 1, GZBUFSIZE, outdiskfile) != GZBUFSIZE) {
-                deflateEnd(&c_stream);
-                free(outfilebuff);
-                return(*status = 413);
-            }
-            bytes_out += GZBUFSIZE;
-            c_stream.next_out = (unsigned char*) outfilebuff;
-            c_stream.avail_out = GZBUFSIZE;
-
-
-        } else {  /* some other error */
-            deflateEnd(&c_stream);
-            free(outfilebuff);
-            return(*status = 413);
-        }
-    }
-
-    /* write out any remaining bytes in the buffer */
-    if (c_stream.total_out > bytes_out) {
-        if ((int)fwrite(outfilebuff, 1, (c_stream.total_out - bytes_out), outdiskfile) 
-	    != (c_stream.total_out - bytes_out)) {
-            deflateEnd(&c_stream);
-            free(outfilebuff);
-            return(*status = 413);
-        }
-    }
-
-    free(outfilebuff); /* free temporary output data buffer */
-
-    /* Set the output file size to be the total output data */
-    if (filesize) *filesize = c_stream.total_out;
-
-    /* End the compression */
-    err = deflateEnd(&c_stream);
-
-    if (err != Z_OK) return(*status = 413);
-     
-    return(*status);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/zconf.h b/src/external/OpenGR/3rdparty/cfitsio/zlib/zconf.h
deleted file mode 100644
index 142c33052..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/zconf.h
+++ /dev/null
@@ -1,426 +0,0 @@
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2010 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#ifndef ZCONF_H
-#define ZCONF_H
-
-/*
- * If you *really* need a unique prefix for all types and library functions,
- * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
- * Even better than compiling with -DZ_PREFIX would be to use configure to set
- * this permanently in zconf.h using "./configure --zprefix".
- */
-#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
-
-/* all linked symbols */
-#  define _dist_code            z__dist_code
-#  define _length_code          z__length_code
-#  define _tr_align             z__tr_align
-#  define _tr_flush_block       z__tr_flush_block
-#  define _tr_init              z__tr_init
-#  define _tr_stored_block      z__tr_stored_block
-#  define _tr_tally             z__tr_tally
-#  define adler32               z_adler32
-#  define adler32_combine       z_adler32_combine
-#  define adler32_combine64     z_adler32_combine64
-#  define compress              z_compress
-#  define compress2             z_compress2
-#  define compressBound         z_compressBound
-#  define crc32                 z_crc32
-#  define crc32_combine         z_crc32_combine
-#  define crc32_combine64       z_crc32_combine64
-#  define deflate               z_deflate
-#  define deflateBound          z_deflateBound
-#  define deflateCopy           z_deflateCopy
-#  define deflateEnd            z_deflateEnd
-#  define deflateInit2_         z_deflateInit2_
-#  define deflateInit_          z_deflateInit_
-#  define deflateParams         z_deflateParams
-#  define deflatePrime          z_deflatePrime
-#  define deflateReset          z_deflateReset
-#  define deflateSetDictionary  z_deflateSetDictionary
-#  define deflateSetHeader      z_deflateSetHeader
-#  define deflateTune           z_deflateTune
-#  define deflate_copyright     z_deflate_copyright
-#  define get_crc_table         z_get_crc_table
-#  define gz_error              z_gz_error
-#  define gz_intmax             z_gz_intmax
-#  define gz_strwinerror        z_gz_strwinerror
-#  define gzbuffer              z_gzbuffer
-#  define gzclearerr            z_gzclearerr
-#  define gzclose               z_gzclose
-#  define gzclose_r             z_gzclose_r
-#  define gzclose_w             z_gzclose_w
-#  define gzdirect              z_gzdirect
-#  define gzdopen               z_gzdopen
-#  define gzeof                 z_gzeof
-#  define gzerror               z_gzerror
-#  define gzflush               z_gzflush
-#  define gzgetc                z_gzgetc
-#  define gzgets                z_gzgets
-#  define gzoffset              z_gzoffset
-#  define gzoffset64            z_gzoffset64
-#  define gzopen                z_gzopen
-#  define gzopen64              z_gzopen64
-#  define gzprintf              z_gzprintf
-#  define gzputc                z_gzputc
-#  define gzputs                z_gzputs
-#  define gzread                z_gzread
-#  define gzrewind              z_gzrewind
-#  define gzseek                z_gzseek
-#  define gzseek64              z_gzseek64
-#  define gzsetparams           z_gzsetparams
-#  define gztell                z_gztell
-#  define gztell64              z_gztell64
-#  define gzungetc              z_gzungetc
-#  define gzwrite               z_gzwrite
-#  define inflate               z_inflate
-#  define inflateBack           z_inflateBack
-#  define inflateBackEnd        z_inflateBackEnd
-#  define inflateBackInit_      z_inflateBackInit_
-#  define inflateCopy           z_inflateCopy
-#  define inflateEnd            z_inflateEnd
-#  define inflateGetHeader      z_inflateGetHeader
-#  define inflateInit2_         z_inflateInit2_
-#  define inflateInit_          z_inflateInit_
-#  define inflateMark           z_inflateMark
-#  define inflatePrime          z_inflatePrime
-#  define inflateReset          z_inflateReset
-#  define inflateReset2         z_inflateReset2
-#  define inflateSetDictionary  z_inflateSetDictionary
-#  define inflateSync           z_inflateSync
-#  define inflateSyncPoint      z_inflateSyncPoint
-#  define inflateUndermine      z_inflateUndermine
-#  define inflate_copyright     z_inflate_copyright
-#  define inflate_fast          z_inflate_fast
-#  define inflate_table         z_inflate_table
-#  define uncompress            z_uncompress
-#  define zError                z_zError
-#  define zcalloc               z_zcalloc
-#  define zcfree                z_zcfree
-#  define zlibCompileFlags      z_zlibCompileFlags
-#  define zlibVersion           z_zlibVersion
-
-/* all zlib typedefs in zlib.h and zconf.h */
-#  define Byte                  z_Byte
-#  define Bytef                 z_Bytef
-#  define alloc_func            z_alloc_func
-#  define charf                 z_charf
-#  define free_func             z_free_func
-#  define gzFile                z_gzFile
-#  define gz_header             z_gz_header
-#  define gz_headerp            z_gz_headerp
-#  define in_func               z_in_func
-#  define intf                  z_intf
-#  define out_func              z_out_func
-#  define uInt                  z_uInt
-#  define uIntf                 z_uIntf
-#  define uLong                 z_uLong
-#  define uLongf                z_uLongf
-#  define voidp                 z_voidp
-#  define voidpc                z_voidpc
-#  define voidpf                z_voidpf
-
-/* all zlib structs in zlib.h and zconf.h */
-#  define gz_header_s           z_gz_header_s
-#  define internal_state        z_internal_state
-
-#endif
-
-#if defined(__MSDOS__) && !defined(MSDOS)
-#  define MSDOS
-#endif
-#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
-#  define OS2
-#endif
-#if defined(_WINDOWS) && !defined(WINDOWS)
-#  define WINDOWS
-#endif
-#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
-#  ifndef WIN32
-#    define WIN32
-#  endif
-#endif
-#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
-#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
-#    ifndef SYS16BIT
-#      define SYS16BIT
-#    endif
-#  endif
-#endif
-
-/*
- * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
- * than 64k bytes at a time (needed on systems with 16-bit int).
- */
-#ifdef SYS16BIT
-#  define MAXSEG_64K
-#endif
-#ifdef MSDOS
-#  define UNALIGNED_OK
-#endif
-
-#ifdef __STDC_VERSION__
-#  ifndef STDC
-#    define STDC
-#  endif
-#  if __STDC_VERSION__ >= 199901L
-#    ifndef STDC99
-#      define STDC99
-#    endif
-#  endif
-#endif
-#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
-#  define STDC
-#endif
-#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
-#  define STDC
-#endif
-#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
-#  define STDC
-#endif
-#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
-#  define STDC
-#endif
-
-#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
-#  define STDC
-#endif
-
-#ifndef STDC
-#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
-#    define const       /* note: need a more gentle solution here */
-#  endif
-#endif
-
-/* Some Mac compilers merge all .h files incorrectly: */
-#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
-#  define NO_DUMMY_DECL
-#endif
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-#  ifdef MAXSEG_64K
-#    define MAX_MEM_LEVEL 8
-#  else
-#    define MAX_MEM_LEVEL 9
-#  endif
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2.
- * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
- * created by gzip. (Files created by minigzip can still be extracted by
- * gzip.)
- */
-#ifndef MAX_WBITS
-#  define MAX_WBITS   15 /* 32K LZ77 window */
-#endif
-
-/* The memory requirements for deflate are (in bytes):
-            (1 << (windowBits+2)) +  (1 << (memLevel+9))
- that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
-     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
-   The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects.
-*/
-
-                        /* Type declarations */
-
-#ifndef OF /* function prototypes */
-#  ifdef STDC
-#    define OF(args)  args
-#  else
-#    define OF(args)  ()
-#  endif
-#endif
-
-/* The following definitions for FAR are needed only for MSDOS mixed
- * model programming (small or medium model with some far allocations).
- * This was tested only with MSC; for other MSDOS compilers you may have
- * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
- * just define FAR to be empty.
- */
-#ifdef SYS16BIT
-#  if defined(M_I86SM) || defined(M_I86MM)
-     /* MSC small or medium model */
-#    define SMALL_MEDIUM
-#    ifdef _MSC_VER
-#      define FAR _far
-#    else
-#      define FAR far
-#    endif
-#  endif
-#  if (defined(__SMALL__) || defined(__MEDIUM__))
-     /* Turbo C small or medium model */
-#    define SMALL_MEDIUM
-#    ifdef __BORLANDC__
-#      define FAR _far
-#    else
-#      define FAR far
-#    endif
-#  endif
-#endif
-
-#if defined(WINDOWS) || defined(WIN32)
-   /* If building or using zlib as a DLL, define ZLIB_DLL.
-    * This is not mandatory, but it offers a little performance increase.
-    */
-#  ifdef ZLIB_DLL
-#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
-#      ifdef ZLIB_INTERNAL
-#        define ZEXTERN extern __declspec(dllexport)
-#      else
-#        define ZEXTERN extern __declspec(dllimport)
-#      endif
-#    endif
-#  endif  /* ZLIB_DLL */
-   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
-    * define ZLIB_WINAPI.
-    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
-    */
-#  ifdef ZLIB_WINAPI
-#    ifdef FAR
-#      undef FAR
-#    endif
-#    include 
-     /* No need for _export, use ZLIB.DEF instead. */
-     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
-#    define ZEXPORT WINAPI
-#    ifdef WIN32
-#      define ZEXPORTVA WINAPIV
-#    else
-#      define ZEXPORTVA FAR CDECL
-#    endif
-#  endif
-#endif
-
-#if defined (__BEOS__)
-#  ifdef ZLIB_DLL
-#    ifdef ZLIB_INTERNAL
-#      define ZEXPORT   __declspec(dllexport)
-#      define ZEXPORTVA __declspec(dllexport)
-#    else
-#      define ZEXPORT   __declspec(dllimport)
-#      define ZEXPORTVA __declspec(dllimport)
-#    endif
-#  endif
-#endif
-
-#ifndef ZEXTERN
-#  define ZEXTERN extern
-#endif
-#ifndef ZEXPORT
-#  define ZEXPORT
-#endif
-#ifndef ZEXPORTVA
-#  define ZEXPORTVA
-#endif
-
-#ifndef FAR
-#  define FAR
-#endif
-
-#if !defined(__MACTYPES__)
-typedef unsigned char  Byte;  /* 8 bits */
-#endif
-typedef unsigned int   uInt;  /* 16 bits or more */
-typedef unsigned long  uLong; /* 32 bits or more */
-
-#ifdef SMALL_MEDIUM
-   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
-#  define Bytef Byte FAR
-#else
-   typedef Byte  FAR Bytef;
-#endif
-typedef char  FAR charf;
-typedef int   FAR intf;
-typedef uInt  FAR uIntf;
-typedef uLong FAR uLongf;
-
-#ifdef STDC
-   typedef void const *voidpc;
-   typedef void FAR   *voidpf;
-   typedef void       *voidp;
-#else
-   typedef Byte const *voidpc;
-   typedef Byte FAR   *voidpf;
-   typedef Byte       *voidp;
-#endif
-
-#if !defined(MSDOS) && !defined(WINDOWS) && !defined(WIN32)
-#  define Z_HAVE_UNISTD_H
-#endif
-
-#ifdef STDC
-#  include     /* for off_t */
-#endif
-
-/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
- * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
- * though the former does not conform to the LFS document), but considering
- * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
- * equivalently requesting no 64-bit operations
- */
-#if -_LARGEFILE64_SOURCE - -1 == 1
-#  undef _LARGEFILE64_SOURCE
-#endif
-
-#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
-#  include        /* for SEEK_* and off_t */
-#  ifdef VMS
-#    include      /* for off_t */
-#  endif
-#  ifndef z_off_t
-#    define z_off_t off_t
-#  endif
-#endif
-
-#ifndef SEEK_SET
-#  define SEEK_SET        0       /* Seek from beginning of file.  */
-#  define SEEK_CUR        1       /* Seek from current position.  */
-#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
-#endif
-
-#ifndef z_off_t
-#  define z_off_t long
-#endif
-
-#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
-#  define z_off64_t off64_t
-#else
-#  define z_off64_t z_off_t
-#endif
-
-#if defined(__OS400__)
-#  define NO_vsnprintf
-#endif
-
-#if defined(__MVS__)
-#  define NO_vsnprintf
-#endif
-
-/* MVS linker does not support external names larger than 8 bytes */
-#if defined(__MVS__)
-  #pragma map(deflateInit_,"DEIN")
-  #pragma map(deflateInit2_,"DEIN2")
-  #pragma map(deflateEnd,"DEEND")
-  #pragma map(deflateBound,"DEBND")
-  #pragma map(inflateInit_,"ININ")
-  #pragma map(inflateInit2_,"ININ2")
-  #pragma map(inflateEnd,"INEND")
-  #pragma map(inflateSync,"INSY")
-  #pragma map(inflateSetDictionary,"INSEDI")
-  #pragma map(compressBound,"CMBND")
-  #pragma map(inflate_table,"INTABL")
-  #pragma map(inflate_fast,"INFA")
-  #pragma map(inflate_copyright,"INCOPY")
-#endif
-
-#endif /* ZCONF_H */
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/zlib.h b/src/external/OpenGR/3rdparty/cfitsio/zlib/zlib.h
deleted file mode 100644
index bfbba83e8..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/zlib.h
+++ /dev/null
@@ -1,1613 +0,0 @@
-/* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 1.2.5, April 19th, 2010
-
-  Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  Jean-loup Gailly        Mark Adler
-  jloup@gzip.org          madler@alumni.caltech.edu
-
-
-  The data format used by the zlib library is described by RFCs (Request for
-  Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
-  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
-*/
-
-#ifndef ZLIB_H
-#define ZLIB_H
-
-#include "zconf.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define ZLIB_VERSION "1.2.5"
-#define ZLIB_VERNUM 0x1250
-#define ZLIB_VER_MAJOR 1
-#define ZLIB_VER_MINOR 2
-#define ZLIB_VER_REVISION 5
-#define ZLIB_VER_SUBREVISION 0
-
-/*
-    The 'zlib' compression library provides in-memory compression and
-  decompression functions, including integrity checks of the uncompressed data.
-  This version of the library supports only one compression method (deflation)
-  but other algorithms will be added later and will have the same stream
-  interface.
-
-    Compression can be done in a single step if the buffers are large enough,
-  or can be done by repeated calls of the compression function.  In the latter
-  case, the application must provide more input and/or consume the output
-  (providing more output space) before each call.
-
-    The compressed data format used by default by the in-memory functions is
-  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
-  around a deflate stream, which is itself documented in RFC 1951.
-
-    The library also supports reading and writing files in gzip (.gz) format
-  with an interface similar to that of stdio using the functions that start
-  with "gz".  The gzip format is different from the zlib format.  gzip is a
-  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
-
-    This library can optionally read and write gzip streams in memory as well.
-
-    The zlib format was designed to be compact and fast for use in memory
-  and on communications channels.  The gzip format was designed for single-
-  file compression on file systems, has a larger header than zlib to maintain
-  directory information, and uses a different, slower check method than zlib.
-
-    The library does not install any signal handler.  The decoder checks
-  the consistency of the compressed data, so the library should never crash
-  even in case of corrupted input.
-*/
-
-typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
-typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
-
-struct internal_state;
-
-typedef struct z_stream_s {
-    Bytef    *next_in;  /* next input byte */
-    uInt     avail_in;  /* number of bytes available at next_in */
-    uLong    total_in;  /* total nb of input bytes read so far */
-
-    Bytef    *next_out; /* next output byte should be put there */
-    uInt     avail_out; /* remaining free space at next_out */
-    uLong    total_out; /* total nb of bytes output so far */
-
-    char     *msg;      /* last error message, NULL if no error */
-    struct internal_state FAR *state; /* not visible by applications */
-
-    alloc_func zalloc;  /* used to allocate the internal state */
-    free_func  zfree;   /* used to free the internal state */
-    voidpf     opaque;  /* private data object passed to zalloc and zfree */
-
-    int     data_type;  /* best guess about the data type: binary or text */
-    uLong   adler;      /* adler32 value of the uncompressed data */
-    uLong   reserved;   /* reserved for future use */
-} z_stream;
-
-typedef z_stream FAR *z_streamp;
-
-/*
-     gzip header information passed to and from zlib routines.  See RFC 1952
-  for more details on the meanings of these fields.
-*/
-typedef struct gz_header_s {
-    int     text;       /* true if compressed data believed to be text */
-    uLong   time;       /* modification time */
-    int     xflags;     /* extra flags (not used when writing a gzip file) */
-    int     os;         /* operating system */
-    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
-    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
-    uInt    extra_max;  /* space at extra (only when reading header) */
-    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
-    uInt    name_max;   /* space at name (only when reading header) */
-    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
-    uInt    comm_max;   /* space at comment (only when reading header) */
-    int     hcrc;       /* true if there was or will be a header crc */
-    int     done;       /* true when done reading gzip header (not used
-                           when writing a gzip file) */
-} gz_header;
-
-typedef gz_header FAR *gz_headerp;
-
-/*
-     The application must update next_in and avail_in when avail_in has dropped
-   to zero.  It must update next_out and avail_out when avail_out has dropped
-   to zero.  The application must initialize zalloc, zfree and opaque before
-   calling the init function.  All other fields are set by the compression
-   library and must not be updated by the application.
-
-     The opaque value provided by the application will be passed as the first
-   parameter for calls of zalloc and zfree.  This can be useful for custom
-   memory management.  The compression library attaches no meaning to the
-   opaque value.
-
-     zalloc must return Z_NULL if there is not enough memory for the object.
-   If zlib is used in a multi-threaded application, zalloc and zfree must be
-   thread safe.
-
-     On 16-bit systems, the functions zalloc and zfree must be able to allocate
-   exactly 65536 bytes, but will not be required to allocate more than this if
-   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers
-   returned by zalloc for objects of exactly 65536 bytes *must* have their
-   offset normalized to zero.  The default allocation function provided by this
-   library ensures this (see zutil.c).  To reduce memory requirements and avoid
-   any allocation of 64K objects, at the expense of compression ratio, compile
-   the library with -DMAX_WBITS=14 (see zconf.h).
-
-     The fields total_in and total_out can be used for statistics or progress
-   reports.  After compression, total_in holds the total size of the
-   uncompressed data and may be saved for use in the decompressor (particularly
-   if the decompressor wants to decompress everything in a single step).
-*/
-
-                        /* constants */
-
-#define Z_NO_FLUSH      0
-#define Z_PARTIAL_FLUSH 1
-#define Z_SYNC_FLUSH    2
-#define Z_FULL_FLUSH    3
-#define Z_FINISH        4
-#define Z_BLOCK         5
-#define Z_TREES         6
-/* Allowed flush values; see deflate() and inflate() below for details */
-
-#define Z_OK            0
-#define Z_STREAM_END    1
-#define Z_NEED_DICT     2
-#define Z_ERRNO        (-1)
-#define Z_STREAM_ERROR (-2)
-#define Z_DATA_ERROR   (-3)
-#define Z_MEM_ERROR    (-4)
-#define Z_BUF_ERROR    (-5)
-#define Z_VERSION_ERROR (-6)
-/* Return codes for the compression/decompression functions. Negative values
- * are errors, positive values are used for special but normal events.
- */
-
-#define Z_NO_COMPRESSION         0
-#define Z_BEST_SPEED             1
-#define Z_BEST_COMPRESSION       9
-#define Z_DEFAULT_COMPRESSION  (-1)
-/* compression levels */
-
-#define Z_FILTERED            1
-#define Z_HUFFMAN_ONLY        2
-#define Z_RLE                 3
-#define Z_FIXED               4
-#define Z_DEFAULT_STRATEGY    0
-/* compression strategy; see deflateInit2() below for details */
-
-#define Z_BINARY   0
-#define Z_TEXT     1
-#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
-#define Z_UNKNOWN  2
-/* Possible values of the data_type field (though see inflate()) */
-
-#define Z_DEFLATED   8
-/* The deflate compression method (the only one supported in this version) */
-
-#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
-
-#define zlib_version zlibVersion()
-/* for compatibility with versions < 1.0.2 */
-
-
-                        /* basic functions */
-
-ZEXTERN const char * ZEXPORT zlibVersion OF((void));
-/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
-   If the first character differs, the library code actually used is not
-   compatible with the zlib.h header file used by the application.  This check
-   is automatically made by deflateInit and inflateInit.
- */
-
-/*
-ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
-
-     Initializes the internal stream state for compression.  The fields
-   zalloc, zfree and opaque must be initialized before by the caller.  If
-   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
-   allocation functions.
-
-     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
-   1 gives best speed, 9 gives best compression, 0 gives no compression at all
-   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION
-   requests a default compromise between speed and compression (currently
-   equivalent to level 6).
-
-     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_STREAM_ERROR if level is not a valid compression level, or
-   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
-   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null
-   if there is no error message.  deflateInit does not perform any compression:
-   this will be done by deflate().
-*/
-
-
-ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
-/*
-    deflate compresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full.  It may introduce
-  some output latency (reading input without producing any output) except when
-  forced to flush.
-
-    The detailed semantics are as follows.  deflate performs one or both of the
-  following actions:
-
-  - Compress more input starting at next_in and update next_in and avail_in
-    accordingly.  If not all input can be processed (because there is not
-    enough room in the output buffer), next_in and avail_in are updated and
-    processing will resume at this point for the next call of deflate().
-
-  - Provide more output starting at next_out and update next_out and avail_out
-    accordingly.  This action is forced if the parameter flush is non zero.
-    Forcing flush frequently degrades the compression ratio, so this parameter
-    should be set only when necessary (in interactive applications).  Some
-    output may be provided even if flush is not set.
-
-    Before the call of deflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming more
-  output, and updating avail_in or avail_out accordingly; avail_out should
-  never be zero before the call.  The application can consume the compressed
-  output when it wants, for example when the output buffer is full (avail_out
-  == 0), or after each call of deflate().  If deflate returns Z_OK and with
-  zero avail_out, it must be called again after making room in the output
-  buffer because there might be more output pending.
-
-    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
-  decide how much data to accumulate before producing output, in order to
-  maximize compression.
-
-    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
-  flushed to the output buffer and the output is aligned on a byte boundary, so
-  that the decompressor can get all input data available so far.  (In
-  particular avail_in is zero after the call if enough output space has been
-  provided before the call.) Flushing may degrade compression for some
-  compression algorithms and so it should be used only when necessary.  This
-  completes the current deflate block and follows it with an empty stored block
-  that is three bits plus filler bits to the next byte, followed by four bytes
-  (00 00 ff ff).
-
-    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
-  output buffer, but the output is not aligned to a byte boundary.  All of the
-  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
-  This completes the current deflate block and follows it with an empty fixed
-  codes block that is 10 bits long.  This assures that enough bytes are output
-  in order for the decompressor to finish the block before the empty fixed code
-  block.
-
-    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
-  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
-  seven bits of the current block are held to be written as the next byte after
-  the next deflate block is completed.  In this case, the decompressor may not
-  be provided enough bits at this point in order to complete decompression of
-  the data provided so far to the compressor.  It may need to wait for the next
-  block to be emitted.  This is for advanced applications that need to control
-  the emission of deflate blocks.
-
-    If flush is set to Z_FULL_FLUSH, all output is flushed as with
-  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
-  restart from this point if previous compressed data has been damaged or if
-  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade
-  compression.
-
-    If deflate returns with avail_out == 0, this function must be called again
-  with the same value of the flush parameter and more output space (updated
-  avail_out), until the flush is complete (deflate returns with non-zero
-  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
-  avail_out is greater than six to avoid repeated flush markers due to
-  avail_out == 0 on return.
-
-    If the parameter flush is set to Z_FINISH, pending input is processed,
-  pending output is flushed and deflate returns with Z_STREAM_END if there was
-  enough output space; if deflate returns with Z_OK, this function must be
-  called again with Z_FINISH and more output space (updated avail_out) but no
-  more input data, until it returns with Z_STREAM_END or an error.  After
-  deflate has returned Z_STREAM_END, the only possible operations on the stream
-  are deflateReset or deflateEnd.
-
-    Z_FINISH can be used immediately after deflateInit if all the compression
-  is to be done in a single step.  In this case, avail_out must be at least the
-  value returned by deflateBound (see below).  If deflate does not return
-  Z_STREAM_END, then it must be called again as described above.
-
-    deflate() sets strm->adler to the adler32 checksum of all input read
-  so far (that is, total_in bytes).
-
-    deflate() may update strm->data_type if it can make a good guess about
-  the input data type (Z_BINARY or Z_TEXT).  In doubt, the data is considered
-  binary.  This field is only for information purposes and does not affect the
-  compression algorithm in any manner.
-
-    deflate() returns Z_OK if some progress has been made (more input
-  processed or more output produced), Z_STREAM_END if all input has been
-  consumed and all output has been produced (only when flush is set to
-  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
-  if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible
-  (for example avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not
-  fatal, and deflate() can be called again with more input and more output
-  space to continue compressing.
-*/
-
-
-ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
-/*
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any pending
-   output.
-
-     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
-   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
-   prematurely (some input or output was discarded).  In the error case, msg
-   may be set but then points to a static string (which must not be
-   deallocated).
-*/
-
-
-/*
-ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
-
-     Initializes the internal stream state for decompression.  The fields
-   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
-   the caller.  If next_in is not Z_NULL and avail_in is large enough (the
-   exact value depends on the compression method), inflateInit determines the
-   compression method from the zlib header and allocates all data structures
-   accordingly; otherwise the allocation will be deferred to the first call of
-   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
-   use default allocation functions.
-
-     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
-   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
-   invalid, such as a null pointer to the structure.  msg is set to null if
-   there is no error message.  inflateInit does not perform any decompression
-   apart from possibly reading the zlib header if present: actual decompression
-   will be done by inflate().  (So next_in and avail_in may be modified, but
-   next_out and avail_out are unused and unchanged.) The current implementation
-   of inflateInit() does not process any header information -- that is deferred
-   until inflate() is called.
-*/
-
-
-ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
-/*
-    inflate decompresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full.  It may introduce
-  some output latency (reading input without producing any output) except when
-  forced to flush.
-
-  The detailed semantics are as follows.  inflate performs one or both of the
-  following actions:
-
-  - Decompress more input starting at next_in and update next_in and avail_in
-    accordingly.  If not all input can be processed (because there is not
-    enough room in the output buffer), next_in is updated and processing will
-    resume at this point for the next call of inflate().
-
-  - Provide more output starting at next_out and update next_out and avail_out
-    accordingly.  inflate() provides as much output as possible, until there is
-    no more input data or no more space in the output buffer (see below about
-    the flush parameter).
-
-    Before the call of inflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming more
-  output, and updating the next_* and avail_* values accordingly.  The
-  application can consume the uncompressed output when it wants, for example
-  when the output buffer is full (avail_out == 0), or after each call of
-  inflate().  If inflate returns Z_OK and with zero avail_out, it must be
-  called again after making room in the output buffer because there might be
-  more output pending.
-
-    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
-  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much
-  output as possible to the output buffer.  Z_BLOCK requests that inflate()
-  stop if and when it gets to the next deflate block boundary.  When decoding
-  the zlib or gzip format, this will cause inflate() to return immediately
-  after the header and before the first block.  When doing a raw inflate,
-  inflate() will go ahead and process the first block, and will return when it
-  gets to the end of that block, or when it runs out of data.
-
-    The Z_BLOCK option assists in appending to or combining deflate streams.
-  Also to assist in this, on return inflate() will set strm->data_type to the
-  number of unused bits in the last byte taken from strm->next_in, plus 64 if
-  inflate() is currently decoding the last block in the deflate stream, plus
-  128 if inflate() returned immediately after decoding an end-of-block code or
-  decoding the complete header up to just before the first byte of the deflate
-  stream.  The end-of-block will not be indicated until all of the uncompressed
-  data from that block has been written to strm->next_out.  The number of
-  unused bits may in general be greater than seven, except when bit 7 of
-  data_type is set, in which case the number of unused bits will be less than
-  eight.  data_type is set as noted here every time inflate() returns for all
-  flush options, and so can be used to determine the amount of currently
-  consumed input in bits.
-
-    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
-  end of each deflate block header is reached, before any actual data in that
-  block is decoded.  This allows the caller to determine the length of the
-  deflate block header for later use in random access within a deflate block.
-  256 is added to the value of strm->data_type when inflate() returns
-  immediately after reaching the end of the deflate block header.
-
-    inflate() should normally be called until it returns Z_STREAM_END or an
-  error.  However if all decompression is to be performed in a single step (a
-  single call of inflate), the parameter flush should be set to Z_FINISH.  In
-  this case all pending input is processed and all pending output is flushed;
-  avail_out must be large enough to hold all the uncompressed data.  (The size
-  of the uncompressed data may have been saved by the compressor for this
-  purpose.) The next operation on this stream must be inflateEnd to deallocate
-  the decompression state.  The use of Z_FINISH is never required, but can be
-  used to inform inflate that a faster approach may be used for the single
-  inflate() call.
-
-     In this implementation, inflate() always flushes as much output as
-  possible to the output buffer, and always uses the faster approach on the
-  first call.  So the only effect of the flush parameter in this implementation
-  is on the return value of inflate(), as noted below, or when it returns early
-  because Z_BLOCK or Z_TREES is used.
-
-     If a preset dictionary is needed after this call (see inflateSetDictionary
-  below), inflate sets strm->adler to the adler32 checksum of the dictionary
-  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
-  strm->adler to the adler32 checksum of all output produced so far (that is,
-  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
-  below.  At the end of the stream, inflate() checks that its computed adler32
-  checksum is equal to that saved by the compressor and returns Z_STREAM_END
-  only if the checksum is correct.
-
-    inflate() can decompress and check either zlib-wrapped or gzip-wrapped
-  deflate data.  The header type is detected automatically, if requested when
-  initializing with inflateInit2().  Any information contained in the gzip
-  header is not retained, so applications that need that information should
-  instead use raw inflate, see inflateInit2() below, or inflateBack() and
-  perform their own processing of the gzip header and trailer.
-
-    inflate() returns Z_OK if some progress has been made (more input processed
-  or more output produced), Z_STREAM_END if the end of the compressed data has
-  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
-  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
-  corrupted (input stream not conforming to the zlib format or incorrect check
-  value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
-  next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory,
-  Z_BUF_ERROR if no progress is possible or if there was not enough room in the
-  output buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and
-  inflate() can be called again with more input and more output space to
-  continue decompressing.  If Z_DATA_ERROR is returned, the application may
-  then call inflateSync() to look for a good compression block if a partial
-  recovery of the data is desired.
-*/
-
-
-ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
-/*
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any pending
-   output.
-
-     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
-   was inconsistent.  In the error case, msg may be set but then points to a
-   static string (which must not be deallocated).
-*/
-
-
-                        /* Advanced functions */
-
-/*
-    The following functions are needed only in some special applications.
-*/
-
-/*
-ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
-                                     int  level,
-                                     int  method,
-                                     int  windowBits,
-                                     int  memLevel,
-                                     int  strategy));
-
-     This is another version of deflateInit with more compression options.  The
-   fields next_in, zalloc, zfree and opaque must be initialized before by the
-   caller.
-
-     The method parameter is the compression method.  It must be Z_DEFLATED in
-   this version of the library.
-
-     The windowBits parameter is the base two logarithm of the window size
-   (the size of the history buffer).  It should be in the range 8..15 for this
-   version of the library.  Larger values of this parameter result in better
-   compression at the expense of memory usage.  The default value is 15 if
-   deflateInit is used instead.
-
-     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits
-   determines the window size.  deflate() will then generate raw deflate data
-   with no zlib header or trailer, and will not compute an adler32 check value.
-
-     windowBits can also be greater than 15 for optional gzip encoding.  Add
-   16 to windowBits to write a simple gzip header and trailer around the
-   compressed data instead of a zlib wrapper.  The gzip header will have no
-   file name, no extra data, no comment, no modification time (set to zero), no
-   header crc, and the operating system will be set to 255 (unknown).  If a
-   gzip stream is being written, strm->adler is a crc32 instead of an adler32.
-
-     The memLevel parameter specifies how much memory should be allocated
-   for the internal compression state.  memLevel=1 uses minimum memory but is
-   slow and reduces compression ratio; memLevel=9 uses maximum memory for
-   optimal speed.  The default value is 8.  See zconf.h for total memory usage
-   as a function of windowBits and memLevel.
-
-     The strategy parameter is used to tune the compression algorithm.  Use the
-   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
-   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
-   string match), or Z_RLE to limit match distances to one (run-length
-   encoding).  Filtered data consists mostly of small values with a somewhat
-   random distribution.  In this case, the compression algorithm is tuned to
-   compress them better.  The effect of Z_FILTERED is to force more Huffman
-   coding and less string matching; it is somewhat intermediate between
-   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as
-   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The
-   strategy parameter only affects the compression ratio but not the
-   correctness of the compressed output even if it is not set appropriately.
-   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
-   decoder for special applications.
-
-     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
-   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
-   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is
-   set to null if there is no error message.  deflateInit2 does not perform any
-   compression: this will be done by deflate().
-*/
-
-ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
-                                             const Bytef *dictionary,
-                                             uInt  dictLength));
-/*
-     Initializes the compression dictionary from the given byte sequence
-   without producing any compressed output.  This function must be called
-   immediately after deflateInit, deflateInit2 or deflateReset, before any call
-   of deflate.  The compressor and decompressor must use exactly the same
-   dictionary (see inflateSetDictionary).
-
-     The dictionary should consist of strings (byte sequences) that are likely
-   to be encountered later in the data to be compressed, with the most commonly
-   used strings preferably put towards the end of the dictionary.  Using a
-   dictionary is most useful when the data to be compressed is short and can be
-   predicted with good accuracy; the data can then be compressed better than
-   with the default empty dictionary.
-
-     Depending on the size of the compression data structures selected by
-   deflateInit or deflateInit2, a part of the dictionary may in effect be
-   discarded, for example if the dictionary is larger than the window size
-   provided in deflateInit or deflateInit2.  Thus the strings most likely to be
-   useful should be put at the end of the dictionary, not at the front.  In
-   addition, the current implementation of deflate will use at most the window
-   size minus 262 bytes of the provided dictionary.
-
-     Upon return of this function, strm->adler is set to the adler32 value
-   of the dictionary; the decompressor may later use this value to determine
-   which dictionary has been used by the compressor.  (The adler32 value
-   applies to the whole dictionary even if only a subset of the dictionary is
-   actually used by the compressor.) If a raw deflate was requested, then the
-   adler32 value is not computed and strm->adler is not set.
-
-     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
-   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
-   inconsistent (for example if deflate has already been called for this stream
-   or if the compression method is bsort).  deflateSetDictionary does not
-   perform any compression: this will be done by deflate().
-*/
-
-ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
-                                    z_streamp source));
-/*
-     Sets the destination stream as a complete copy of the source stream.
-
-     This function can be useful when several compression strategies will be
-   tried, for example when there are several ways of pre-processing the input
-   data with a filter.  The streams that will be discarded should then be freed
-   by calling deflateEnd.  Note that deflateCopy duplicates the internal
-   compression state which can be quite large, so this strategy is slow and can
-   consume lots of memory.
-
-     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
-   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
-   destination.
-*/
-
-ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
-/*
-     This function is equivalent to deflateEnd followed by deflateInit,
-   but does not free and reallocate all the internal compression state.  The
-   stream will keep the same compression level and any other attributes that
-   may have been set by deflateInit2.
-
-     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being Z_NULL).
-*/
-
-ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
-                                      int level,
-                                      int strategy));
-/*
-     Dynamically update the compression level and compression strategy.  The
-   interpretation of level and strategy is as in deflateInit2.  This can be
-   used to switch between compression and straight copy of the input data, or
-   to switch to a different kind of input data requiring a different strategy.
-   If the compression level is changed, the input available so far is
-   compressed with the old level (and may be flushed); the new level will take
-   effect only at the next call of deflate().
-
-     Before the call of deflateParams, the stream state must be set as for
-   a call of deflate(), since the currently available input may have to be
-   compressed and flushed.  In particular, strm->avail_out must be non-zero.
-
-     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
-   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if
-   strm->avail_out was zero.
-*/
-
-ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
-                                    int good_length,
-                                    int max_lazy,
-                                    int nice_length,
-                                    int max_chain));
-/*
-     Fine tune deflate's internal compression parameters.  This should only be
-   used by someone who understands the algorithm used by zlib's deflate for
-   searching for the best matching string, and even then only by the most
-   fanatic optimizer trying to squeeze out the last compressed bit for their
-   specific input data.  Read the deflate.c source code for the meaning of the
-   max_lazy, good_length, nice_length, and max_chain parameters.
-
-     deflateTune() can be called after deflateInit() or deflateInit2(), and
-   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
- */
-
-ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
-                                       uLong sourceLen));
-/*
-     deflateBound() returns an upper bound on the compressed size after
-   deflation of sourceLen bytes.  It must be called after deflateInit() or
-   deflateInit2(), and after deflateSetHeader(), if used.  This would be used
-   to allocate an output buffer for deflation in a single pass, and so would be
-   called before deflate().
-*/
-
-ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
-                                     int bits,
-                                     int value));
-/*
-     deflatePrime() inserts bits in the deflate output stream.  The intent
-   is that this function is used to start off the deflate output with the bits
-   leftover from a previous deflate stream when appending to it.  As such, this
-   function can only be used for raw deflate, and must be used before the first
-   deflate() call after a deflateInit2() or deflateReset().  bits must be less
-   than or equal to 16, and that many of the least significant bits of value
-   will be inserted in the output.
-
-     deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent.
-*/
-
-ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
-                                         gz_headerp head));
-/*
-     deflateSetHeader() provides gzip header information for when a gzip
-   stream is requested by deflateInit2().  deflateSetHeader() may be called
-   after deflateInit2() or deflateReset() and before the first call of
-   deflate().  The text, time, os, extra field, name, and comment information
-   in the provided gz_header structure are written to the gzip header (xflag is
-   ignored -- the extra flags are set according to the compression level).  The
-   caller must assure that, if not Z_NULL, name and comment are terminated with
-   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
-   available there.  If hcrc is true, a gzip header crc is included.  Note that
-   the current versions of the command-line version of gzip (up through version
-   1.3.x) do not support header crc's, and will report that it is a "multi-part
-   gzip file" and give up.
-
-     If deflateSetHeader is not used, the default gzip header has text false,
-   the time set to zero, and os set to 255, with no extra, name, or comment
-   fields.  The gzip header is returned to the default state by deflateReset().
-
-     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent.
-*/
-
-/*
-ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
-                                     int  windowBits));
-
-     This is another version of inflateInit with an extra parameter.  The
-   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
-   before by the caller.
-
-     The windowBits parameter is the base two logarithm of the maximum window
-   size (the size of the history buffer).  It should be in the range 8..15 for
-   this version of the library.  The default value is 15 if inflateInit is used
-   instead.  windowBits must be greater than or equal to the windowBits value
-   provided to deflateInit2() while compressing, or it must be equal to 15 if
-   deflateInit2() was not used.  If a compressed stream with a larger window
-   size is given as input, inflate() will return with the error code
-   Z_DATA_ERROR instead of trying to allocate a larger window.
-
-     windowBits can also be zero to request that inflate use the window size in
-   the zlib header of the compressed stream.
-
-     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits
-   determines the window size.  inflate() will then process raw deflate data,
-   not looking for a zlib or gzip header, not generating a check value, and not
-   looking for any check values for comparison at the end of the stream.  This
-   is for use with other formats that use the deflate compressed data format
-   such as zip.  Those formats provide their own check values.  If a custom
-   format is developed using the raw deflate format for compressed data, it is
-   recommended that a check value such as an adler32 or a crc32 be applied to
-   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
-   most applications, the zlib format should be used as is.  Note that comments
-   above on the use in deflateInit2() applies to the magnitude of windowBits.
-
-     windowBits can also be greater than 15 for optional gzip decoding.  Add
-   32 to windowBits to enable zlib and gzip decoding with automatic header
-   detection, or add 16 to decode only the gzip format (the zlib format will
-   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a
-   crc32 instead of an adler32.
-
-     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
-   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
-   invalid, such as a null pointer to the structure.  msg is set to null if
-   there is no error message.  inflateInit2 does not perform any decompression
-   apart from possibly reading the zlib header if present: actual decompression
-   will be done by inflate().  (So next_in and avail_in may be modified, but
-   next_out and avail_out are unused and unchanged.) The current implementation
-   of inflateInit2() does not process any header information -- that is
-   deferred until inflate() is called.
-*/
-
-ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
-                                             const Bytef *dictionary,
-                                             uInt  dictLength));
-/*
-     Initializes the decompression dictionary from the given uncompressed byte
-   sequence.  This function must be called immediately after a call of inflate,
-   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
-   can be determined from the adler32 value returned by that call of inflate.
-   The compressor and decompressor must use exactly the same dictionary (see
-   deflateSetDictionary).  For raw inflate, this function can be called
-   immediately after inflateInit2() or inflateReset() and before any call of
-   inflate() to set the dictionary.  The application must insure that the
-   dictionary that was used for compression is provided.
-
-     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
-   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
-   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
-   expected one (incorrect adler32 value).  inflateSetDictionary does not
-   perform any decompression: this will be done by subsequent calls of
-   inflate().
-*/
-
-ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
-/*
-     Skips invalid compressed data until a full flush point (see above the
-   description of deflate with Z_FULL_FLUSH) can be found, or until all
-   available input is skipped.  No output is provided.
-
-     inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
-   if no more input was provided, Z_DATA_ERROR if no flush point has been
-   found, or Z_STREAM_ERROR if the stream structure was inconsistent.  In the
-   success case, the application may save the current current value of total_in
-   which indicates where valid compressed data was found.  In the error case,
-   the application may repeatedly call inflateSync, providing more input each
-   time, until success or end of the input data.
-*/
-
-ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
-                                    z_streamp source));
-/*
-     Sets the destination stream as a complete copy of the source stream.
-
-     This function can be useful when randomly accessing a large stream.  The
-   first pass through the stream can periodically record the inflate state,
-   allowing restarting inflate at those points when randomly accessing the
-   stream.
-
-     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
-   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
-   destination.
-*/
-
-ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
-/*
-     This function is equivalent to inflateEnd followed by inflateInit,
-   but does not free and reallocate all the internal decompression state.  The
-   stream will keep attributes that may have been set by inflateInit2.
-
-     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being Z_NULL).
-*/
-
-ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
-                                      int windowBits));
-/*
-     This function is the same as inflateReset, but it also permits changing
-   the wrap and window size requests.  The windowBits parameter is interpreted
-   the same as it is for inflateInit2.
-
-     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being Z_NULL), or if
-   the windowBits parameter is invalid.
-*/
-
-ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
-                                     int bits,
-                                     int value));
-/*
-     This function inserts bits in the inflate input stream.  The intent is
-   that this function is used to start inflating at a bit position in the
-   middle of a byte.  The provided bits will be used before any bytes are used
-   from next_in.  This function should only be used with raw inflate, and
-   should be used before the first inflate() call after inflateInit2() or
-   inflateReset().  bits must be less than or equal to 16, and that many of the
-   least significant bits of value will be inserted in the input.
-
-     If bits is negative, then the input stream bit buffer is emptied.  Then
-   inflatePrime() can be called again to put bits in the buffer.  This is used
-   to clear out bits leftover after feeding inflate a block description prior
-   to feeding inflate codes.
-
-     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent.
-*/
-
-ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
-/*
-     This function returns two values, one in the lower 16 bits of the return
-   value, and the other in the remaining upper bits, obtained by shifting the
-   return value down 16 bits.  If the upper value is -1 and the lower value is
-   zero, then inflate() is currently decoding information outside of a block.
-   If the upper value is -1 and the lower value is non-zero, then inflate is in
-   the middle of a stored block, with the lower value equaling the number of
-   bytes from the input remaining to copy.  If the upper value is not -1, then
-   it is the number of bits back from the current bit position in the input of
-   the code (literal or length/distance pair) currently being processed.  In
-   that case the lower value is the number of bytes already emitted for that
-   code.
-
-     A code is being processed if inflate is waiting for more input to complete
-   decoding of the code, or if it has completed decoding but is waiting for
-   more output space to write the literal or match data.
-
-     inflateMark() is used to mark locations in the input data for random
-   access, which may be at bit positions, and to note those cases where the
-   output of a code may span boundaries of random access blocks.  The current
-   location in the input stream can be determined from avail_in and data_type
-   as noted in the description for the Z_BLOCK flush parameter for inflate.
-
-     inflateMark returns the value noted above or -1 << 16 if the provided
-   source stream state was inconsistent.
-*/
-
-ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
-                                         gz_headerp head));
-/*
-     inflateGetHeader() requests that gzip header information be stored in the
-   provided gz_header structure.  inflateGetHeader() may be called after
-   inflateInit2() or inflateReset(), and before the first call of inflate().
-   As inflate() processes the gzip stream, head->done is zero until the header
-   is completed, at which time head->done is set to one.  If a zlib stream is
-   being decoded, then head->done is set to -1 to indicate that there will be
-   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be
-   used to force inflate() to return immediately after header processing is
-   complete and before any actual data is decompressed.
-
-     The text, time, xflags, and os fields are filled in with the gzip header
-   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
-   was valid if done is set to one.) If extra is not Z_NULL, then extra_max
-   contains the maximum number of bytes to write to extra.  Once done is true,
-   extra_len contains the actual extra field length, and extra contains the
-   extra field, or that field truncated if extra_max is less than extra_len.
-   If name is not Z_NULL, then up to name_max characters are written there,
-   terminated with a zero unless the length is greater than name_max.  If
-   comment is not Z_NULL, then up to comm_max characters are written there,
-   terminated with a zero unless the length is greater than comm_max.  When any
-   of extra, name, or comment are not Z_NULL and the respective field is not
-   present in the header, then that field is set to Z_NULL to signal its
-   absence.  This allows the use of deflateSetHeader() with the returned
-   structure to duplicate the header.  However if those fields are set to
-   allocated memory, then the application will need to save those pointers
-   elsewhere so that they can be eventually freed.
-
-     If inflateGetHeader is not used, then the header information is simply
-   discarded.  The header is always checked for validity, including the header
-   CRC if present.  inflateReset() will reset the process to discard the header
-   information.  The application would need to call inflateGetHeader() again to
-   retrieve the header from the next gzip stream.
-
-     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent.
-*/
-
-/*
-ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
-                                        unsigned char FAR *window));
-
-     Initialize the internal stream state for decompression using inflateBack()
-   calls.  The fields zalloc, zfree and opaque in strm must be initialized
-   before the call.  If zalloc and zfree are Z_NULL, then the default library-
-   derived memory allocation routines are used.  windowBits is the base two
-   logarithm of the window size, in the range 8..15.  window is a caller
-   supplied buffer of that size.  Except for special applications where it is
-   assured that deflate was used with small window sizes, windowBits must be 15
-   and a 32K byte window must be supplied to be able to decompress general
-   deflate streams.
-
-     See inflateBack() for the usage of these routines.
-
-     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
-   the paramaters are invalid, Z_MEM_ERROR if the internal state could not be
-   allocated, or Z_VERSION_ERROR if the version of the library does not match
-   the version of the header file.
-*/
-
-typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
-typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
-
-ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
-                                    in_func in, void FAR *in_desc,
-                                    out_func out, void FAR *out_desc));
-/*
-     inflateBack() does a raw inflate with a single call using a call-back
-   interface for input and output.  This is more efficient than inflate() for
-   file i/o applications in that it avoids copying between the output and the
-   sliding window by simply making the window itself the output buffer.  This
-   function trusts the application to not change the output buffer passed by
-   the output function, at least until inflateBack() returns.
-
-     inflateBackInit() must be called first to allocate the internal state
-   and to initialize the state with the user-provided window buffer.
-   inflateBack() may then be used multiple times to inflate a complete, raw
-   deflate stream with each call.  inflateBackEnd() is then called to free the
-   allocated state.
-
-     A raw deflate stream is one with no zlib or gzip header or trailer.
-   This routine would normally be used in a utility that reads zip or gzip
-   files and writes out uncompressed files.  The utility would decode the
-   header and process the trailer on its own, hence this routine expects only
-   the raw deflate stream to decompress.  This is different from the normal
-   behavior of inflate(), which expects either a zlib or gzip header and
-   trailer around the deflate stream.
-
-     inflateBack() uses two subroutines supplied by the caller that are then
-   called by inflateBack() for input and output.  inflateBack() calls those
-   routines until it reads a complete deflate stream and writes out all of the
-   uncompressed data, or until it encounters an error.  The function's
-   parameters and return types are defined above in the in_func and out_func
-   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
-   number of bytes of provided input, and a pointer to that input in buf.  If
-   there is no input available, in() must return zero--buf is ignored in that
-   case--and inflateBack() will return a buffer error.  inflateBack() will call
-   out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].  out()
-   should return zero on success, or non-zero on failure.  If out() returns
-   non-zero, inflateBack() will return with an error.  Neither in() nor out()
-   are permitted to change the contents of the window provided to
-   inflateBackInit(), which is also the buffer that out() uses to write from.
-   The length written by out() will be at most the window size.  Any non-zero
-   amount of input may be provided by in().
-
-     For convenience, inflateBack() can be provided input on the first call by
-   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
-   in() will be called.  Therefore strm->next_in must be initialized before
-   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
-   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
-   must also be initialized, and then if strm->avail_in is not zero, input will
-   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].
-
-     The in_desc and out_desc parameters of inflateBack() is passed as the
-   first parameter of in() and out() respectively when they are called.  These
-   descriptors can be optionally used to pass any information that the caller-
-   supplied in() and out() functions need to do their job.
-
-     On return, inflateBack() will set strm->next_in and strm->avail_in to
-   pass back any unused input that was provided by the last in() call.  The
-   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
-   if in() or out() returned an error, Z_DATA_ERROR if there was a format error
-   in the deflate stream (in which case strm->msg is set to indicate the nature
-   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
-   In the case of Z_BUF_ERROR, an input or output error can be distinguished
-   using strm->next_in which will be Z_NULL only if in() returned an error.  If
-   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
-   non-zero.  (in() will always be called before out(), so strm->next_in is
-   assured to be defined if out() returns non-zero.) Note that inflateBack()
-   cannot return Z_OK.
-*/
-
-ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
-/*
-     All memory allocated by inflateBackInit() is freed.
-
-     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
-   state was inconsistent.
-*/
-
-ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
-/* Return flags indicating compile-time options.
-
-    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
-     1.0: size of uInt
-     3.2: size of uLong
-     5.4: size of voidpf (pointer)
-     7.6: size of z_off_t
-
-    Compiler, assembler, and debug options:
-     8: DEBUG
-     9: ASMV or ASMINF -- use ASM code
-     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
-     11: 0 (reserved)
-
-    One-time table building (smaller code, but not thread-safe if true):
-     12: BUILDFIXED -- build static block decoding tables when needed
-     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
-     14,15: 0 (reserved)
-
-    Library content (indicates missing functionality):
-     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
-                          deflate code when not needed)
-     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
-                    and decode gzip streams (to avoid linking crc code)
-     18-19: 0 (reserved)
-
-    Operation variations (changes in library functionality):
-     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
-     21: FASTEST -- deflate algorithm with only one, lowest compression level
-     22,23: 0 (reserved)
-
-    The sprintf variant used by gzprintf (zero is best):
-     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
-     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
-     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
-
-    Remainder:
-     27-31: 0 (reserved)
- */
-
-
-                        /* utility functions */
-
-/*
-     The following utility functions are implemented on top of the basic
-   stream-oriented functions.  To simplify the interface, some default options
-   are assumed (compression level and memory usage, standard memory allocation
-   functions).  The source code of these utility functions can be modified if
-   you need special options.
-*/
-
-ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
-                                 const Bytef *source, uLong sourceLen));
-/*
-     Compresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer.  Upon entry, destLen is the total size
-   of the destination buffer, which must be at least the value returned by
-   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
-   compressed buffer.
-
-     compress returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_BUF_ERROR if there was not enough room in the output
-   buffer.
-*/
-
-ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
-                                  const Bytef *source, uLong sourceLen,
-                                  int level));
-/*
-     Compresses the source buffer into the destination buffer.  The level
-   parameter has the same meaning as in deflateInit.  sourceLen is the byte
-   length of the source buffer.  Upon entry, destLen is the total size of the
-   destination buffer, which must be at least the value returned by
-   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
-   compressed buffer.
-
-     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
-   Z_STREAM_ERROR if the level parameter is invalid.
-*/
-
-ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
-/*
-     compressBound() returns an upper bound on the compressed size after
-   compress() or compress2() on sourceLen bytes.  It would be used before a
-   compress() or compress2() call to allocate the destination buffer.
-*/
-
-ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
-                                   const Bytef *source, uLong sourceLen));
-/*
-     Decompresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer.  Upon entry, destLen is the total size
-   of the destination buffer, which must be large enough to hold the entire
-   uncompressed data.  (The size of the uncompressed data must have been saved
-   previously by the compressor and transmitted to the decompressor by some
-   mechanism outside the scope of this compression library.) Upon exit, destLen
-   is the actual size of the uncompressed buffer.
-
-     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_BUF_ERROR if there was not enough room in the output
-   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
-*/
-
-
-                        /* gzip file access functions */
-
-/*
-     This library supports reading and writing files in gzip (.gz) format with
-   an interface similar to that of stdio, using the functions that start with
-   "gz".  The gzip format is different from the zlib format.  gzip is a gzip
-   wrapper, documented in RFC 1952, wrapped around a deflate stream.
-*/
-
-typedef voidp gzFile;       /* opaque gzip file descriptor */
-
-/*
-ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
-
-     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as
-   in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
-   a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
-   compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
-   for fixed code compression as in "wb9F".  (See the description of
-   deflateInit2 for more information about the strategy parameter.) Also "a"
-   can be used instead of "w" to request that the gzip stream that will be
-   written be appended to the file.  "+" will result in an error, since reading
-   and writing to the same gzip file is not supported.
-
-     gzopen can be used to read a file which is not in gzip format; in this
-   case gzread will directly read from the file without decompression.
-
-     gzopen returns NULL if the file could not be opened, if there was
-   insufficient memory to allocate the gzFile state, or if an invalid mode was
-   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
-   errno can be checked to determine if the reason gzopen failed was that the
-   file could not be opened.
-*/
-
-ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
-/*
-     gzdopen associates a gzFile with the file descriptor fd.  File descriptors
-   are obtained from calls like open, dup, creat, pipe or fileno (if the file
-   has been previously opened with fopen).  The mode parameter is as in gzopen.
-
-     The next call of gzclose on the returned gzFile will also close the file
-   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
-   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
-   mode);.  The duplicated descriptor should be saved to avoid a leak, since
-   gzdopen does not close fd if it fails.
-
-     gzdopen returns NULL if there was insufficient memory to allocate the
-   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
-   provided, or '+' was provided), or if fd is -1.  The file descriptor is not
-   used until the next gz* read, write, seek, or close operation, so gzdopen
-   will not detect if fd is invalid (unless fd is -1).
-*/
-
-ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
-/*
-     Set the internal buffer size used by this library's functions.  The
-   default buffer size is 8192 bytes.  This function must be called after
-   gzopen() or gzdopen(), and before any other calls that read or write the
-   file.  The buffer memory allocation is always deferred to the first read or
-   write.  Two buffers are allocated, either both of the specified size when
-   writing, or one of the specified size and the other twice that size when
-   reading.  A larger buffer size of, for example, 64K or 128K bytes will
-   noticeably increase the speed of decompression (reading).
-
-     The new buffer size also affects the maximum length for gzprintf().
-
-     gzbuffer() returns 0 on success, or -1 on failure, such as being called
-   too late.
-*/
-
-ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
-/*
-     Dynamically update the compression level or strategy.  See the description
-   of deflateInit2 for the meaning of these parameters.
-
-     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
-   opened for writing.
-*/
-
-ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
-/*
-     Reads the given number of uncompressed bytes from the compressed file.  If
-   the input file was not in gzip format, gzread copies the given number of
-   bytes into the buffer.
-
-     After reaching the end of a gzip stream in the input, gzread will continue
-   to read, looking for another gzip stream, or failing that, reading the rest
-   of the input file directly without decompression.  The entire input file
-   will be read if gzread is called until it returns less than the requested
-   len.
-
-     gzread returns the number of uncompressed bytes actually read, less than
-   len for end of file, or -1 for error.
-*/
-
-ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
-                                voidpc buf, unsigned len));
-/*
-     Writes the given number of uncompressed bytes into the compressed file.
-   gzwrite returns the number of uncompressed bytes written or 0 in case of
-   error.
-*/
-
-ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
-/*
-     Converts, formats, and writes the arguments to the compressed file under
-   control of the format string, as in fprintf.  gzprintf returns the number of
-   uncompressed bytes actually written, or 0 in case of error.  The number of
-   uncompressed bytes written is limited to 8191, or one less than the buffer
-   size given to gzbuffer().  The caller should assure that this limit is not
-   exceeded.  If it is exceeded, then gzprintf() will return an error (0) with
-   nothing written.  In this case, there may also be a buffer overflow with
-   unpredictable consequences, which is possible only if zlib was compiled with
-   the insecure functions sprintf() or vsprintf() because the secure snprintf()
-   or vsnprintf() functions were not available.  This can be determined using
-   zlibCompileFlags().
-*/
-
-ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
-/*
-     Writes the given null-terminated string to the compressed file, excluding
-   the terminating null character.
-
-     gzputs returns the number of characters written, or -1 in case of error.
-*/
-
-ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
-/*
-     Reads bytes from the compressed file until len-1 characters are read, or a
-   newline character is read and transferred to buf, or an end-of-file
-   condition is encountered.  If any characters are read or if len == 1, the
-   string is terminated with a null character.  If no characters are read due
-   to an end-of-file or len < 1, then the buffer is left untouched.
-
-     gzgets returns buf which is a null-terminated string, or it returns NULL
-   for end-of-file or in case of error.  If there was an error, the contents at
-   buf are indeterminate.
-*/
-
-ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
-/*
-     Writes c, converted to an unsigned char, into the compressed file.  gzputc
-   returns the value that was written, or -1 in case of error.
-*/
-
-ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
-/*
-     Reads one byte from the compressed file.  gzgetc returns this byte or -1
-   in case of end of file or error.
-*/
-
-ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
-/*
-     Push one character back onto the stream to be read as the first character
-   on the next read.  At least one character of push-back is allowed.
-   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will
-   fail if c is -1, and may fail if a character has been pushed but not read
-   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the
-   output buffer size of pushed characters is allowed.  (See gzbuffer above.)
-   The pushed character will be discarded if the stream is repositioned with
-   gzseek() or gzrewind().
-*/
-
-ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
-/*
-     Flushes all pending output into the compressed file.  The parameter flush
-   is as in the deflate() function.  The return value is the zlib error number
-   (see function gzerror below).  gzflush is only permitted when writing.
-
-     If the flush parameter is Z_FINISH, the remaining data is written and the
-   gzip stream is completed in the output.  If gzwrite() is called again, a new
-   gzip stream will be started in the output.  gzread() is able to read such
-   concatented gzip streams.
-
-     gzflush should be called only when strictly necessary because it will
-   degrade compression if called too often.
-*/
-
-/*
-ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
-                                   z_off_t offset, int whence));
-
-     Sets the starting position for the next gzread or gzwrite on the given
-   compressed file.  The offset represents a number of bytes in the
-   uncompressed data stream.  The whence parameter is defined as in lseek(2);
-   the value SEEK_END is not supported.
-
-     If the file is opened for reading, this function is emulated but can be
-   extremely slow.  If the file is opened for writing, only forward seeks are
-   supported; gzseek then compresses a sequence of zeroes up to the new
-   starting position.
-
-     gzseek returns the resulting offset location as measured in bytes from
-   the beginning of the uncompressed stream, or -1 in case of error, in
-   particular if the file is opened for writing and the new starting position
-   would be before the current position.
-*/
-
-ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
-/*
-     Rewinds the given file. This function is supported only for reading.
-
-     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
-*/
-
-/*
-ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
-
-     Returns the starting position for the next gzread or gzwrite on the given
-   compressed file.  This position represents a number of bytes in the
-   uncompressed data stream, and is zero when starting, even if appending or
-   reading a gzip stream from the middle of a file using gzdopen().
-
-     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
-*/
-
-/*
-ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
-
-     Returns the current offset in the file being read or written.  This offset
-   includes the count of bytes that precede the gzip stream, for example when
-   appending or when using gzdopen() for reading.  When reading, the offset
-   does not include as yet unused buffered input.  This information can be used
-   for a progress indicator.  On error, gzoffset() returns -1.
-*/
-
-ZEXTERN int ZEXPORT gzeof OF((gzFile file));
-/*
-     Returns true (1) if the end-of-file indicator has been set while reading,
-   false (0) otherwise.  Note that the end-of-file indicator is set only if the
-   read tried to go past the end of the input, but came up short.  Therefore,
-   just like feof(), gzeof() may return false even if there is no more data to
-   read, in the event that the last read request was for the exact number of
-   bytes remaining in the input file.  This will happen if the input file size
-   is an exact multiple of the buffer size.
-
-     If gzeof() returns true, then the read functions will return no more data,
-   unless the end-of-file indicator is reset by gzclearerr() and the input file
-   has grown since the previous end of file was detected.
-*/
-
-ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
-/*
-     Returns true (1) if file is being copied directly while reading, or false
-   (0) if file is a gzip stream being decompressed.  This state can change from
-   false to true while reading the input file if the end of a gzip stream is
-   reached, but is followed by data that is not another gzip stream.
-
-     If the input file is empty, gzdirect() will return true, since the input
-   does not contain a gzip stream.
-
-     If gzdirect() is used immediately after gzopen() or gzdopen() it will
-   cause buffers to be allocated to allow reading the file to determine if it
-   is a gzip file.  Therefore if gzbuffer() is used, it should be called before
-   gzdirect().
-*/
-
-ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
-/*
-     Flushes all pending output if necessary, closes the compressed file and
-   deallocates the (de)compression state.  Note that once file is closed, you
-   cannot call gzerror with file, since its structures have been deallocated.
-   gzclose must not be called more than once on the same file, just as free
-   must not be called more than once on the same allocation.
-
-     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
-   file operation error, or Z_OK on success.
-*/
-
-ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
-ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
-/*
-     Same as gzclose(), but gzclose_r() is only for use when reading, and
-   gzclose_w() is only for use when writing or appending.  The advantage to
-   using these instead of gzclose() is that they avoid linking in zlib
-   compression or decompression code that is not used when only reading or only
-   writing respectively.  If gzclose() is used, then both compression and
-   decompression code will be included the application when linking to a static
-   zlib library.
-*/
-
-ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
-/*
-     Returns the error message for the last error which occurred on the given
-   compressed file.  errnum is set to zlib error number.  If an error occurred
-   in the file system and not in the compression library, errnum is set to
-   Z_ERRNO and the application may consult errno to get the exact error code.
-
-     The application must not modify the returned string.  Future calls to
-   this function may invalidate the previously returned string.  If file is
-   closed, then the string previously returned by gzerror will no longer be
-   available.
-
-     gzerror() should be used to distinguish errors from end-of-file for those
-   functions above that do not distinguish those cases in their return values.
-*/
-
-ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
-/*
-     Clears the error and end-of-file flags for file.  This is analogous to the
-   clearerr() function in stdio.  This is useful for continuing to read a gzip
-   file that is being written concurrently.
-*/
-
-
-                        /* checksum functions */
-
-/*
-     These functions are not related to compression but are exported
-   anyway because they might be useful in applications using the compression
-   library.
-*/
-
-ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
-/*
-     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
-   return the updated checksum.  If buf is Z_NULL, this function returns the
-   required initial value for the checksum.
-
-     An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
-   much faster.
-
-   Usage example:
-
-     uLong adler = adler32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       adler = adler32(adler, buffer, length);
-     }
-     if (adler != original_adler) error();
-*/
-
-/*
-ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
-                                          z_off_t len2));
-
-     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
-   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
-   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
-   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
-*/
-
-ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
-/*
-     Update a running CRC-32 with the bytes buf[0..len-1] and return the
-   updated CRC-32.  If buf is Z_NULL, this function returns the required
-   initial value for the for the crc.  Pre- and post-conditioning (one's
-   complement) is performed within this function so it shouldn't be done by the
-   application.
-
-   Usage example:
-
-     uLong crc = crc32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       crc = crc32(crc, buffer, length);
-     }
-     if (crc != original_crc) error();
-*/
-
-/*
-ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
-
-     Combine two CRC-32 check values into one.  For two sequences of bytes,
-   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
-   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
-   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
-   len2.
-*/
-
-
-                        /* various hacks, don't look :) */
-
-/* deflateInit and inflateInit are macros to allow checking the zlib version
- * and the compiler's view of z_stream:
- */
-ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
-                                     const char *version, int stream_size));
-ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
-                                     const char *version, int stream_size));
-ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
-                                      int windowBits, int memLevel,
-                                      int strategy, const char *version,
-                                      int stream_size));
-ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
-                                      const char *version, int stream_size));
-ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
-                                         unsigned char FAR *window,
-                                         const char *version,
-                                         int stream_size));
-#define deflateInit(strm, level) \
-        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
-#define inflateInit(strm) \
-        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
-#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
-        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
-                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
-#define inflateInit2(strm, windowBits) \
-        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
-#define inflateBackInit(strm, windowBits, window) \
-        inflateBackInit_((strm), (windowBits), (window), \
-                                            ZLIB_VERSION, sizeof(z_stream))
-
-/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
- * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
- * both are true, the application gets the *64 functions, and the regular
- * functions are changed to 64 bits) -- in case these are set on systems
- * without large file support, _LFS64_LARGEFILE must also be true
- */
-#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
-   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
-   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
-   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
-   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
-   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
-   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
-#endif
-
-#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0
-#  define gzopen gzopen64
-#  define gzseek gzseek64
-#  define gztell gztell64
-#  define gzoffset gzoffset64
-#  define adler32_combine adler32_combine64
-#  define crc32_combine crc32_combine64
-#  ifdef _LARGEFILE64_SOURCE
-     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
-     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
-     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
-     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
-     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
-     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
-#  endif
-#else
-   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
-   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
-   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
-   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
-   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
-   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
-#endif
-
-/* hack for buggy compilers */
-#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
-    struct internal_state {int dummy;};
-#endif
-
-/* undocumented functions */
-ZEXTERN const char   * ZEXPORT zError           OF((int));
-ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
-ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
-ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ZLIB_H */
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/zuncompress.c b/src/external/OpenGR/3rdparty/cfitsio/zlib/zuncompress.c
deleted file mode 100644
index c73ee6deb..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/zuncompress.c
+++ /dev/null
@@ -1,603 +0,0 @@
-/* gzcompress.h -- definitions for the .Z decompression routine used in CFITSIO */
-
-#include 
-#include 
-#include 
-#include 
-
-#define get_char() get_byte()
-
-/* gzip.h -- common declarations for all gzip modules  */
-
-#define OF(args)  args
-typedef void *voidp;
-
-#define memzero(s, n)     memset ((voidp)(s), 0, (n))
-
-typedef unsigned char  uch;
-typedef unsigned short ush;
-typedef unsigned long  ulg;
-
-/* private version of MIN function */
-#define MINZIP(a,b) ((a) <= (b) ? (a) : (b))
-
-/* Return codes from gzip */
-#define OK      0
-#define ERROR   1
-#define COMPRESSED  1
-#define DEFLATED    8
-#define INBUFSIZ  0x8000    /* input buffer size */
-#define INBUF_EXTRA  64     /* required by unlzw() */
-#define OUTBUFSIZ  16384    /* output buffer size */
-#define OUTBUF_EXTRA 2048   /* required by unlzw() */
-#define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
-#define WSIZE 0x8000        /* window size--must be a power of two, and */
-#define DECLARE(type, array, size)  type array[size]
-#define tab_suffix window
-#define tab_prefix prev    /* hash link (see deflate.c) */
-#define head (prev+WSIZE)  /* hash head (see deflate.c) */
-#define	LZW_MAGIC      "\037\235" /* Magic header for lzw files, 1F 9D */
-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf(0))
-
-/* Diagnostic functions */
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-
-/* lzw.h -- define the lzw functions. */
-
-#ifndef BITS
-#  define BITS 16
-#endif
-#define INIT_BITS 9              /* Initial number of bits per code */
-#define BIT_MASK    0x1f /* Mask for 'number of compression bits' */
-#define BLOCK_MODE  0x80
-#define LZW_RESERVED 0x60 /* reserved bits */
-#define	CLEAR  256       /* flush the dictionary */
-#define FIRST  (CLEAR+1) /* first free entry */
-
-/* prototypes */
-
-#define local static
-void ffpmsg(const char *err_message);
-
-local int  fill_inbuf    OF((int eof_ok));
-local void write_buf     OF((voidp buf, unsigned cnt));
-local void error         OF((char *m));
-local int unlzw  OF((FILE *in, FILE *out));
-
-typedef int file_t;     /* Do not use stdio */
-
-int (*work) OF((FILE *infile, FILE *outfile)) = unlzw; /* function to call */
-
-local void error         OF((char *m));
-
-		/* global buffers */
-
-static DECLARE(uch, inbuf,  INBUFSIZ +INBUF_EXTRA);
-static DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
-static DECLARE(ush, d_buf,  DIST_BUFSIZE);
-static DECLARE(uch, window, 2L*WSIZE);
-
-#ifndef MAXSEG_64K
-    static DECLARE(ush, tab_prefix, 1L< 0)
-        return(*status);
-
-    /*  save input parameters into global variables */
-    ifname[0] = '\0';
-    strncat(ifname, filename, 127);
-    ifd = indiskfile;
-    memptr = (void **) buffptr;
-    memsize = buffsize;
-    realloc_fn = mem_realloc;
-
-    /* clear input and output buffers */
-
-    insize = inptr = 0;
-    bytes_in = bytes_out = 0L;
-
-    magic[0] = (char)get_byte();
-    magic[1] = (char)get_byte();
-
-    if (memcmp(magic, LZW_MAGIC, 2) != 0) {
-      error("ERROR: input .Z file is in unrecognized compression format.\n");
-      return(-1);
-    }
-
-    work = unlzw;
-    method = COMPRESSED;
-    last_member = 1;
-
-    /* do the uncompression */
-    if ((*work)(ifd, ofd) != OK) {
-        method = -1; /* force cleanup */
-        *status = 414;    /* report some sort of decompression error */
-    }
-
-    if (filesize)  *filesize = bytes_out;
-
-    return(*status);
-}
-/*=========================================================================*/
-/*=========================================================================*/
-/* this marks the begining of the original file 'unlzw.c'                  */
-/*=========================================================================*/
-/*=========================================================================*/
-
-/* unlzw.c -- decompress files in LZW format.
- * The code in this file is directly derived from the public domain 'compress'
- * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
- * Ken Turkowski, Dave Mack and Peter Jannesen.
- */
-
-typedef	unsigned char	char_type;
-typedef          long   code_int;
-typedef unsigned long 	count_int;
-typedef unsigned short	count_short;
-typedef unsigned long 	cmp_code_int;
-
-#define MAXCODE(n)	(1L << (n))
-    
-#ifndef	REGISTERS
-#	define	REGISTERS	2
-#endif
-#define	REG1	
-#define	REG2	
-#define	REG3	
-#define	REG4	
-#define	REG5	
-#define	REG6	
-#define	REG7	
-#define	REG8	
-#define	REG9	
-#define	REG10
-#define	REG11	
-#define	REG12	
-#define	REG13
-#define	REG14
-#define	REG15
-#define	REG16
-#if REGISTERS >= 1
-#	undef	REG1
-#	define	REG1	register
-#endif
-#if REGISTERS >= 2
-#	undef	REG2
-#	define	REG2	register
-#endif
-#if REGISTERS >= 3
-#	undef	REG3
-#	define	REG3	register
-#endif
-#if REGISTERS >= 4
-#	undef	REG4
-#	define	REG4	register
-#endif
-#if REGISTERS >= 5
-#	undef	REG5
-#	define	REG5	register
-#endif
-#if REGISTERS >= 6
-#	undef	REG6
-#	define	REG6	register
-#endif
-#if REGISTERS >= 7
-#	undef	REG7
-#	define	REG7	register
-#endif
-#if REGISTERS >= 8
-#	undef	REG8
-#	define	REG8	register
-#endif
-#if REGISTERS >= 9
-#	undef	REG9
-#	define	REG9	register
-#endif
-#if REGISTERS >= 10
-#	undef	REG10
-#	define	REG10	register
-#endif
-#if REGISTERS >= 11
-#	undef	REG11
-#	define	REG11	register
-#endif
-#if REGISTERS >= 12
-#	undef	REG12
-#	define	REG12	register
-#endif
-#if REGISTERS >= 13
-#	undef	REG13
-#	define	REG13	register
-#endif
-#if REGISTERS >= 14
-#	undef	REG14
-#	define	REG14	register
-#endif
-#if REGISTERS >= 15
-#	undef	REG15
-#	define	REG15	register
-#endif
-#if REGISTERS >= 16
-#	undef	REG16
-#	define	REG16	register
-#endif
-    
-#ifndef	BYTEORDER
-#	define	BYTEORDER	0000
-#endif
-	
-#ifndef	NOALLIGN
-#	define	NOALLIGN	0
-#endif
-
-
-union	bytes {
-    long  word;
-    struct {
-#if BYTEORDER == 4321
-	char_type	b1;
-	char_type	b2;
-	char_type	b3;
-	char_type	b4;
-#else
-#if BYTEORDER == 1234
-	char_type	b4;
-	char_type	b3;
-	char_type	b2;
-	char_type	b1;
-#else
-#	undef	BYTEORDER
-	int  dummy;
-#endif
-#endif
-    } bytes;
-};
-
-#if BYTEORDER == 4321 && NOALLIGN == 1
-#  define input(b,o,c,n,m){ \
-     (c) = (*(long *)(&(b)[(o)>>3])>>((o)&0x7))&(m); \
-     (o) += (n); \
-   }
-#else
-#  define input(b,o,c,n,m){ \
-     REG1 char_type *p = &(b)[(o)>>3]; \
-     (c) = ((((long)(p[0]))|((long)(p[1])<<8)| \
-     ((long)(p[2])<<16))>>((o)&0x7))&(m); \
-     (o) += (n); \
-   }
-#endif
-
-#ifndef MAXSEG_64K
-   /* DECLARE(ush, tab_prefix, (1<>1]
-#  define clear_tab_prefixof()	\
-      memzero(tab_prefix0, 128), \
-      memzero(tab_prefix1, 128);
-#endif
-#define de_stack        ((char_type *)(&d_buf[DIST_BUFSIZE-1]))
-#define tab_suffixof(i) tab_suffix[i]
-
-int block_mode = BLOCK_MODE; /* block compress mode -C compatible with 2.0 */
-
-/* ============================================================================
- * Decompress in to out.  This routine adapts to the codes in the
- * file building the "string" table on-the-fly; requiring no table to
- * be stored in the compressed file.
- * IN assertions: the buffer inbuf contains already the beginning of
- *   the compressed data, from offsets iptr to insize-1 included.
- *   The magic header has already been checked and skipped.
- *   bytes_in and bytes_out have been initialized.
- */
-local int unlzw(FILE *in, FILE *out) 
-    /* input and output file descriptors */
-{
-    REG2   char_type  *stackp;
-    REG3   code_int   code;
-    REG4   int        finchar;
-    REG5   code_int   oldcode;
-    REG6   code_int   incode;
-    REG7   long       inbits;
-    REG8   long       posbits;
-    REG9   int        outpos;
-/*  REG10  int        insize; (global) */
-    REG11  unsigned   bitmask;
-    REG12  code_int   free_ent;
-    REG13  code_int   maxcode;
-    REG14  code_int   maxmaxcode;
-    REG15  int        n_bits;
-    REG16  int        rsize;
-    
-    ofd = out;
-
-#ifdef MAXSEG_64K
-    tab_prefix[0] = tab_prefix0;
-    tab_prefix[1] = tab_prefix1;
-#endif
-    maxbits = get_byte();
-    block_mode = maxbits & BLOCK_MODE;
-    if ((maxbits & LZW_RESERVED) != 0) {
-	error( "warning, unknown flags in unlzw decompression");
-    }
-    maxbits &= BIT_MASK;
-    maxmaxcode = MAXCODE(maxbits);
-    
-    if (maxbits > BITS) {
-	error("compressed with too many bits; cannot handle file");
-	exit_code = ERROR;
-	return ERROR;
-    }
-    rsize = insize;
-    maxcode = MAXCODE(n_bits = INIT_BITS)-1;
-    bitmask = (1<= 0 ; --code) {
-	tab_suffixof(code) = (char_type)code;
-    }
-    do {
-	REG1 int i;
-	int  e;
-	int  o;
-	
-    resetbuf:
-	e = insize-(o = (posbits>>3));
-	
-	for (i = 0 ; i < e ; ++i) {
-	    inbuf[i] = inbuf[i+o];
-	}
-	insize = e;
-	posbits = 0;
-	
-	if (insize < INBUF_EXTRA) {
-/*  modified to use fread instead of read - WDP 10/22/97  */
-/*	    if ((rsize = read(in, (char*)inbuf+insize, INBUFSIZ)) == EOF) { */
-
-	    if ((rsize = fread((char*)inbuf+insize, 1, INBUFSIZ, in)) == EOF) {
-		error("unexpected end of file");
-	        exit_code = ERROR;
-                return ERROR;
-	    }
-	    insize += rsize;
-	    bytes_in += (ulg)rsize;
-	}
-	inbits = ((rsize != 0) ? ((long)insize - insize%n_bits)<<3 : 
-		  ((long)insize<<3)-(n_bits-1));
-	
-	while (inbits > posbits) {
-	    if (free_ent > maxcode) {
-		posbits = ((posbits-1) +
-			   ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
-		++n_bits;
-		if (n_bits == maxbits) {
-		    maxcode = maxmaxcode;
-		} else {
-		    maxcode = MAXCODE(n_bits)-1;
-		}
-		bitmask = (1<= 256) {
-                    error("corrupt input.");
-	            exit_code = ERROR;
-                    return ERROR;
-                }
-
-		outbuf[outpos++] = (char_type)(finchar = (int)(oldcode=code));
-		continue;
-	    }
-	    if (code == CLEAR && block_mode) {
-		clear_tab_prefixof();
-		free_ent = FIRST - 1;
-		posbits = ((posbits-1) +
-			   ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
-		maxcode = MAXCODE(n_bits = INIT_BITS)-1;
-		bitmask = (1<= free_ent) { /* Special case for KwKwK string. */
-		if (code > free_ent) {
-		    if (outpos > 0) {
-			write_buf((char*)outbuf, outpos);
-			bytes_out += (ulg)outpos;
-		    }
-		    error("corrupt input.");
-	            exit_code = ERROR;
-                    return ERROR;
-
-		}
-		*--stackp = (char_type)finchar;
-		code = oldcode;
-	    }
-
-	    while ((cmp_code_int)code >= (cmp_code_int)256) {
-		/* Generate output characters in reverse order */
-		*--stackp = tab_suffixof(code);
-		code = tab_prefixof(code);
-	    }
-	    *--stackp =	(char_type)(finchar = tab_suffixof(code));
-	    
-	    /* And put them out in forward order */
-	    {
-	/*	REG1 int	i;   already defined above (WDP) */
-	    
-		if (outpos+(i = (de_stack-stackp)) >= OUTBUFSIZ) {
-		    do {
-			if (i > OUTBUFSIZ-outpos) i = OUTBUFSIZ-outpos;
-
-			if (i > 0) {
-			    memcpy(outbuf+outpos, stackp, i);
-			    outpos += i;
-			}
-			if (outpos >= OUTBUFSIZ) {
-			    write_buf((char*)outbuf, outpos);
-			    bytes_out += (ulg)outpos;
-			    outpos = 0;
-			}
-			stackp+= i;
-		    } while ((i = (de_stack-stackp)) > 0);
-		} else {
-		    memcpy(outbuf+outpos, stackp, i);
-		    outpos += i;
-		}
-	    }
-
-	    if ((code = free_ent) < maxmaxcode) { /* Generate the new entry. */
-
-		tab_prefixof(code) = (unsigned short)oldcode;
-		tab_suffixof(code) = (char_type)finchar;
-		free_ent = code+1;
-	    } 
-	    oldcode = incode;	/* Remember previous code.	*/
-	}
-    } while (rsize != 0);
-    
-    if (outpos > 0) {
-	write_buf((char*)outbuf, outpos);
-	bytes_out += (ulg)outpos;
-    }
-    return OK;
-}
-/* ========================================================================*/
-/* this marks the start of the code from 'util.c'  */
-
-local int fill_inbuf(int eof_ok)
-         /* set if EOF acceptable as a result */
-{
-    int len;
-
-      /* Read as much as possible from file */
-      insize = 0;
-      do {
-        len = fread((char*)inbuf+insize, 1, INBUFSIZ-insize, ifd);
-        if (len == 0 || len == EOF) break;
-	insize += len;
-      } while (insize < INBUFSIZ);
-
-    if (insize == 0) {
-	if (eof_ok) return EOF;
-	error("unexpected end of file");
-        exit_code = ERROR;
-        return ERROR;
-    }
-
-    bytes_in += (ulg)insize;
-    inptr = 1;
-    return inbuf[0];
-}
-/* =========================================================================== */
-local void write_buf(voidp buf, unsigned cnt)
-/*              copy buffer into memory; allocate more memory if required*/
-{
-    if (!realloc_fn)
-    {
-      /* append buffer to file */
-      /* added 'unsigned' to get rid of compiler warning (WDP 1/1/99) */
-      if ((unsigned long) fwrite(buf, 1, cnt, ofd) != cnt)
-      {
-          error
-          ("failed to write buffer to uncompressed output file (write_buf)");
-          exit_code = ERROR;
-          return;
-      }
-    }
-    else
-    {
-      /* get more memory if current buffer is too small */
-      if (bytes_out + cnt > *memsize)
-      {
-        *memptr = realloc_fn(*memptr, bytes_out + cnt);
-        *memsize = bytes_out + cnt;  /* new memory buffer size */
-
-        if (!(*memptr))
-        {
-            error("malloc failed while uncompressing (write_buf)");
-            exit_code = ERROR;
-            return;
-        }  
-      }
-      /* copy  into memory buffer */
-      memcpy((char *) *memptr + bytes_out, (char *) buf, cnt);
-    }
-}
-/* ======================================================================== */
-local void error(char *m)
-/*                Error handler */
-{
-    ffpmsg(ifname);
-    ffpmsg(m);
-}
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/zutil.c b/src/external/OpenGR/3rdparty/cfitsio/zlib/zutil.c
deleted file mode 100644
index 15645c5e7..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/zutil.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995-2005, 2010 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include "zutil.h"
-
-#ifndef NO_DUMMY_DECL
-struct internal_state      {int dummy;}; /* for buggy compilers */
-#endif
-
-const char * const z_errmsg[10] = {
-"need dictionary",     /* Z_NEED_DICT       2  */
-"stream end",          /* Z_STREAM_END      1  */
-"",                    /* Z_OK              0  */
-"file error",          /* Z_ERRNO         (-1) */
-"stream error",        /* Z_STREAM_ERROR  (-2) */
-"data error",          /* Z_DATA_ERROR    (-3) */
-"insufficient memory", /* Z_MEM_ERROR     (-4) */
-"buffer error",        /* Z_BUF_ERROR     (-5) */
-"incompatible version",/* Z_VERSION_ERROR (-6) */
-""};
-
-
-const char * ZEXPORT zlibVersion()
-{
-    return ZLIB_VERSION;
-}
-
-uLong ZEXPORT zlibCompileFlags()
-{
-    uLong flags;
-
-    flags = 0;
-    switch ((int)(sizeof(uInt))) {
-    case 2:     break;
-    case 4:     flags += 1;     break;
-    case 8:     flags += 2;     break;
-    default:    flags += 3;
-    }
-    switch ((int)(sizeof(uLong))) {
-    case 2:     break;
-    case 4:     flags += 1 << 2;        break;
-    case 8:     flags += 2 << 2;        break;
-    default:    flags += 3 << 2;
-    }
-    switch ((int)(sizeof(voidpf))) {
-    case 2:     break;
-    case 4:     flags += 1 << 4;        break;
-    case 8:     flags += 2 << 4;        break;
-    default:    flags += 3 << 4;
-    }
-    switch ((int)(sizeof(z_off_t))) {
-    case 2:     break;
-    case 4:     flags += 1 << 6;        break;
-    case 8:     flags += 2 << 6;        break;
-    default:    flags += 3 << 6;
-    }
-#ifdef DEBUG
-    flags += 1 << 8;
-#endif
-#if defined(ASMV) || defined(ASMINF)
-    flags += 1 << 9;
-#endif
-#ifdef ZLIB_WINAPI
-    flags += 1 << 10;
-#endif
-#ifdef BUILDFIXED
-    flags += 1 << 12;
-#endif
-#ifdef DYNAMIC_CRC_TABLE
-    flags += 1 << 13;
-#endif
-#ifdef NO_GZCOMPRESS
-    flags += 1L << 16;
-#endif
-#ifdef NO_GZIP
-    flags += 1L << 17;
-#endif
-#ifdef PKZIP_BUG_WORKAROUND
-    flags += 1L << 20;
-#endif
-#ifdef FASTEST
-    flags += 1L << 21;
-#endif
-#ifdef STDC
-#  ifdef NO_vsnprintf
-        flags += 1L << 25;
-#    ifdef HAS_vsprintf_void
-        flags += 1L << 26;
-#    endif
-#  else
-#    ifdef HAS_vsnprintf_void
-        flags += 1L << 26;
-#    endif
-#  endif
-#else
-        flags += 1L << 24;
-#  ifdef NO_snprintf
-        flags += 1L << 25;
-#    ifdef HAS_sprintf_void
-        flags += 1L << 26;
-#    endif
-#  else
-#    ifdef HAS_snprintf_void
-        flags += 1L << 26;
-#    endif
-#  endif
-#endif
-    return flags;
-}
-
-#ifdef DEBUG
-
-#  ifndef verbose
-#    define verbose 0
-#  endif
-int ZLIB_INTERNAL z_verbose = verbose;
-
-void ZLIB_INTERNAL z_error (m)
-    char *m;
-{
-    fprintf(stderr, "%s\n", m);
-    exit(1);
-}
-#endif
-
-/* exported to allow conversion of error code to string for compress() and
- * uncompress()
- */
-const char * ZEXPORT zError(err)
-    int err;
-{
-    return ERR_MSG(err);
-}
-
-#if defined(_WIN32_WCE)
-    /* The Microsoft C Run-Time Library for Windows CE doesn't have
-     * errno.  We define it as a global variable to simplify porting.
-     * Its value is always 0 and should not be used.
-     */
-    int errno = 0;
-#endif
-
-#ifndef HAVE_MEMCPY
-
-void ZLIB_INTERNAL zmemcpy(dest, source, len)
-    Bytef* dest;
-    const Bytef* source;
-    uInt  len;
-{
-    if (len == 0) return;
-    do {
-        *dest++ = *source++; /* ??? to be unrolled */
-    } while (--len != 0);
-}
-
-int ZLIB_INTERNAL zmemcmp(s1, s2, len)
-    const Bytef* s1;
-    const Bytef* s2;
-    uInt  len;
-{
-    uInt j;
-
-    for (j = 0; j < len; j++) {
-        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
-    }
-    return 0;
-}
-
-void ZLIB_INTERNAL zmemzero(dest, len)
-    Bytef* dest;
-    uInt  len;
-{
-    if (len == 0) return;
-    do {
-        *dest++ = 0;  /* ??? to be unrolled */
-    } while (--len != 0);
-}
-#endif
-
-
-#ifdef SYS16BIT
-
-#ifdef __TURBOC__
-/* Turbo C in 16-bit mode */
-
-#  define MY_ZCALLOC
-
-/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
- * and farmalloc(64K) returns a pointer with an offset of 8, so we
- * must fix the pointer. Warning: the pointer must be put back to its
- * original form in order to free it, use zcfree().
- */
-
-#define MAX_PTR 10
-/* 10*64K = 640K */
-
-local int next_ptr = 0;
-
-typedef struct ptr_table_s {
-    voidpf org_ptr;
-    voidpf new_ptr;
-} ptr_table;
-
-local ptr_table table[MAX_PTR];
-/* This table is used to remember the original form of pointers
- * to large buffers (64K). Such pointers are normalized with a zero offset.
- * Since MSDOS is not a preemptive multitasking OS, this table is not
- * protected from concurrent access. This hack doesn't work anyway on
- * a protected system like OS/2. Use Microsoft C instead.
- */
-
-voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
-{
-    voidpf buf = opaque; /* just to make some compilers happy */
-    ulg bsize = (ulg)items*size;
-
-    /* If we allocate less than 65520 bytes, we assume that farmalloc
-     * will return a usable pointer which doesn't have to be normalized.
-     */
-    if (bsize < 65520L) {
-        buf = farmalloc(bsize);
-        if (*(ush*)&buf != 0) return buf;
-    } else {
-        buf = farmalloc(bsize + 16L);
-    }
-    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
-    table[next_ptr].org_ptr = buf;
-
-    /* Normalize the pointer to seg:0 */
-    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
-    *(ush*)&buf = 0;
-    table[next_ptr++].new_ptr = buf;
-    return buf;
-}
-
-void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
-{
-    int n;
-    if (*(ush*)&ptr != 0) { /* object < 64K */
-        farfree(ptr);
-        return;
-    }
-    /* Find the original pointer */
-    for (n = 0; n < next_ptr; n++) {
-        if (ptr != table[n].new_ptr) continue;
-
-        farfree(table[n].org_ptr);
-        while (++n < next_ptr) {
-            table[n-1] = table[n];
-        }
-        next_ptr--;
-        return;
-    }
-    ptr = opaque; /* just to make some compilers happy */
-    Assert(0, "zcfree: ptr not found");
-}
-
-#endif /* __TURBOC__ */
-
-
-#ifdef M_I86
-/* Microsoft C in 16-bit mode */
-
-#  define MY_ZCALLOC
-
-#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
-#  define _halloc  halloc
-#  define _hfree   hfree
-#endif
-
-voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
-{
-    if (opaque) opaque = 0; /* to make compiler happy */
-    return _halloc((long)items, size);
-}
-
-void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
-{
-    if (opaque) opaque = 0; /* to make compiler happy */
-    _hfree(ptr);
-}
-
-#endif /* M_I86 */
-
-#endif /* SYS16BIT */
-
-
-#ifndef MY_ZCALLOC /* Any system without a special alloc function */
-
-#ifndef STDC
-extern voidp  malloc OF((uInt size));
-extern voidp  calloc OF((uInt items, uInt size));
-extern void   free   OF((voidpf ptr));
-#endif
-
-voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
-    voidpf opaque;
-    unsigned items;
-    unsigned size;
-{
-    if (opaque) items += size - size; /* make compiler happy */
-    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
-                              (voidpf)calloc(items, size);
-}
-
-void ZLIB_INTERNAL zcfree (opaque, ptr)
-    voidpf opaque;
-    voidpf ptr;
-{
-    free(ptr);
-    if (opaque) return; /* make compiler happy */
-}
-
-#endif /* MY_ZCALLOC */
diff --git a/src/external/OpenGR/3rdparty/cfitsio/zlib/zutil.h b/src/external/OpenGR/3rdparty/cfitsio/zlib/zutil.h
deleted file mode 100644
index 1f5a6c0ef..000000000
--- a/src/external/OpenGR/3rdparty/cfitsio/zlib/zutil.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2010 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-#ifndef ZUTIL_H
-#define ZUTIL_H
-
-#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
-#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
-#else
-#  define ZLIB_INTERNAL
-#endif
-
-#include "zlib.h"
-
-#ifdef STDC
-#  if !(defined(_WIN32_WCE) && defined(_MSC_VER))
-#    include 
-#  endif
-#  include 
-#  include 
-#endif
-
-#ifndef local
-#  define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
-typedef unsigned char  uch;
-typedef uch FAR uchf;
-typedef unsigned short ush;
-typedef ush FAR ushf;
-typedef unsigned long  ulg;
-
-extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
-/* (size given to avoid silly warnings with Visual C++) */
-
-#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
-
-#define ERR_RETURN(strm,err) \
-  return (strm->msg = (char*)ERR_MSG(err), (err))
-/* To be used only when the state is known to be valid */
-
-        /* common constants */
-
-#ifndef DEF_WBITS
-#  define DEF_WBITS MAX_WBITS
-#endif
-/* default windowBits for decompression. MAX_WBITS is for compression only */
-
-#if MAX_MEM_LEVEL >= 8
-#  define DEF_MEM_LEVEL 8
-#else
-#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#endif
-/* default memLevel */
-
-#define STORED_BLOCK 0
-#define STATIC_TREES 1
-#define DYN_TREES    2
-/* The three kinds of block type */
-
-#define MIN_MATCH  3
-#define MAX_MATCH  258
-/* The minimum and maximum match lengths */
-
-#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
-
-        /* target dependencies */
-
-#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
-#  define OS_CODE  0x00
-#  if defined(__TURBOC__) || defined(__BORLANDC__)
-#    if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
-       /* Allow compilation with ANSI keywords only enabled */
-       void _Cdecl farfree( void *block );
-       void *_Cdecl farmalloc( unsigned long nbytes );
-#    else
-#      include 
-#    endif
-#  else /* MSC or DJGPP */
-#    include 
-#  endif
-#endif
-
-#ifdef AMIGA
-#  define OS_CODE  0x01
-#endif
-
-#if defined(VAXC) || defined(VMS)
-#  define OS_CODE  0x02
-#  define F_OPEN(name, mode) \
-     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
-#endif
-
-#if defined(ATARI) || defined(atarist)
-#  define OS_CODE  0x05
-#endif
-
-#ifdef OS2
-#  define OS_CODE  0x06
-#  ifdef M_I86
-#    include 
-#  endif
-#endif
-
-#if defined(MACOS) || defined(TARGET_OS_MAC)
-#  define OS_CODE  0x07
-#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
-#    include  /* for fdopen */
-#  else
-#    ifndef fdopen
-#      define fdopen(fd,mode) NULL /* No fdopen() */
-#    endif
-#  endif
-#endif
-
-#ifdef TOPS20
-#  define OS_CODE  0x0a
-#endif
-
-#ifdef WIN32
-#  ifndef __CYGWIN__  /* Cygwin is Unix, not Win32 */
-#    define OS_CODE  0x0b
-#  endif
-#endif
-
-#ifdef __50SERIES /* Prime/PRIMOS */
-#  define OS_CODE  0x0f
-#endif
-
-#if defined(_BEOS_) || defined(RISCOS)
-#  define fdopen(fd,mode) NULL /* No fdopen() */
-#endif
-
-#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
-#  if defined(_WIN32_WCE)
-#    define fdopen(fd,mode) NULL /* No fdopen() */
-#    ifndef _PTRDIFF_T_DEFINED
-       typedef int ptrdiff_t;
-#      define _PTRDIFF_T_DEFINED
-#    endif
-#  else
-#    define fdopen(fd,type)  _fdopen(fd,type)
-#  endif
-#endif
-
-#if defined(__BORLANDC__)
-  #pragma warn -8004
-  #pragma warn -8008
-  #pragma warn -8066
-#endif
-
-/* provide prototypes for these when building zlib without LFS */
-#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
-    ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
-    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
-#endif
-
-        /* common defaults */
-
-#ifndef OS_CODE
-#  define OS_CODE  0x03  /* assume Unix */
-#endif
-
-#ifndef F_OPEN
-#  define F_OPEN(name, mode) fopen((name), (mode))
-#endif
-
-         /* functions */
-
-#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
-#  ifndef HAVE_VSNPRINTF
-#    define HAVE_VSNPRINTF
-#  endif
-#endif
-#if defined(__CYGWIN__)
-#  ifndef HAVE_VSNPRINTF
-#    define HAVE_VSNPRINTF
-#  endif
-#endif
-#ifndef HAVE_VSNPRINTF
-#  ifdef MSDOS
-     /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
-        but for now we just assume it doesn't. */
-#    define NO_vsnprintf
-#  endif
-#  ifdef __TURBOC__
-#    define NO_vsnprintf
-#  endif
-#  ifdef WIN32
-     /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
-#    if !defined(vsnprintf) && !defined(NO_vsnprintf)
-#      if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
-#         define vsnprintf _vsnprintf
-#      endif
-#    endif
-#  endif
-#  ifdef __SASC
-#    define NO_vsnprintf
-#  endif
-#endif
-#ifdef VMS
-#  define NO_vsnprintf
-#endif
-
-#if defined(pyr)
-#  define NO_MEMCPY
-#endif
-#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
- /* Use our own functions for small and medium model with MSC <= 5.0.
-  * You may have to use the same strategy for Borland C (untested).
-  * The __SC__ check is for Symantec.
-  */
-#  define NO_MEMCPY
-#endif
-#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
-#  define HAVE_MEMCPY
-#endif
-#ifdef HAVE_MEMCPY
-#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
-#    define zmemcpy _fmemcpy
-#    define zmemcmp _fmemcmp
-#    define zmemzero(dest, len) _fmemset(dest, 0, len)
-#  else
-#    define zmemcpy memcpy
-#    define zmemcmp memcmp
-#    define zmemzero(dest, len) memset(dest, 0, len)
-#  endif
-#else
-   void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
-   int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
-   void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
-#endif
-
-/* Diagnostic functions */
-#ifdef DEBUG
-#  include 
-   extern int ZLIB_INTERNAL z_verbose;
-   extern void ZLIB_INTERNAL z_error OF((char *m));
-#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
-#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
-#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
-#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-
-voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
-                        unsigned size));
-void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));
-
-#define ZALLOC(strm, items, size) \
-           (*((strm)->zalloc))((strm)->opaque, (items), (size))
-#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
-#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
-
-#endif /* ZUTIL_H */
diff --git a/src/external/OpenGR/3rdparty/chealpix/CHANGES b/src/external/OpenGR/3rdparty/chealpix/CHANGES
deleted file mode 100644
index b82f662ad..000000000
--- a/src/external/OpenGR/3rdparty/chealpix/CHANGES
+++ /dev/null
@@ -1,11 +0,0 @@
-Changes since v2.20a (incomplete):
-
-- The Healpix C library has been rewritten almost completely. Algorithms are now
-  as similar as possible to the ones in the C++ library, simplifying code
-  maintenance. Many functions have become much faster and shorter.
-  The interface is unaffected by this change, so existing codes using the
-  Healpix C library should not need to be changed.
-- An additional set of functions was added to support Nside values up to 2^29.
-- Nside values which are not powers of 2 are supported in RING scheme.
-- optional compilation without libcfitsio (the cfitsio-related functions are
-  skipped in this mode); contributed by Yu Feng
diff --git a/src/external/OpenGR/3rdparty/chealpix/CMakeLists.txt b/src/external/OpenGR/3rdparty/chealpix/CMakeLists.txt
deleted file mode 100644
index dd2374197..000000000
--- a/src/external/OpenGR/3rdparty/chealpix/CMakeLists.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-cmake_minimum_required(VERSION 2.6)
-project(chealpix)
-
-include_directories(${CFITSIO_INCLUDE_DIRS})
-
-# Set variables
-set(Chealpix_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/include" CACHE INTERNAL "Chealpix include dir" FORCE)
-set(Chealpix_LIB_DIR "${PROJECT_BINARY_DIR}")
-set(Chealpix_LIBS ${PROJECT_NAME} CACHE INTERNAL "Chealpix lib dir" FORCE)
-
-# create the c-based healpix library.
-include_directories(${Chealpix_INCLUDE_DIR})
-
-add_library(${PROJECT_NAME} SHARED ${PROJECT_SOURCE_DIR}/src/chealpix.c)
-target_link_libraries(${PROJECT_NAME} ${CFITSIO_LIBRARIES})
-add_dependencies(${PROJECT_NAME}  cfitsio)
-
-set(targets_export_name "${PROJECT_NAME}Targets")
-install( TARGETS ${PROJECT_NAME}
-    EXPORT "${targets_export_name}"
-    RUNTIME DESTINATION bin
-    LIBRARY DESTINATION lib
-    ARCHIVE DESTINATION lib
-    INCLUDES DESTINATION include )
diff --git a/src/external/OpenGR/3rdparty/chealpix/COPYING b/src/external/OpenGR/3rdparty/chealpix/COPYING
deleted file mode 100644
index 3912109b5..000000000
--- a/src/external/OpenGR/3rdparty/chealpix/COPYING
+++ /dev/null
@@ -1,340 +0,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    
-    Copyright (C)   
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  , 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/src/external/OpenGR/3rdparty/chealpix/README b/src/external/OpenGR/3rdparty/chealpix/README
deleted file mode 100644
index c0e77e7e8..000000000
--- a/src/external/OpenGR/3rdparty/chealpix/README
+++ /dev/null
@@ -1,44 +0,0 @@
-README
-======
-
-Compilation and Installation
-----------------------------
-
-See the header in the 'subs/Makefile'.
-
-You can alternatively try to run the script 'doinstall'
-
-Usage
------
-
-To use in your 'c' code, include the line
-
-#include "chealpix.h"
-
-in your code and link with something like 
-
-gcc -o myprog myprog.c -I -L -lchealpix
-
-where  is where you've installed the '.h' files and 
- is where you've installed the libraries (See the header of 
-the 'Makefile').
-
-You will also need the 'cfitsio' library. See 
-http://heasarc.gsfc.nasa.gov/docs/software/fitsio/fitsio.html
-
-Disclaimer and Acknowledgements:
---------------------------------
-
-The original HEALPix Fortran90 software was written by Gorski, Hivon, Hansen,
-Stompor, Banday and Bartelmann. The 'C' routines are an adaptation of parts of
-the Healpix C++ library, done by Martin Reinecke.
-
-Description of Individual Files:
---------------------------------
-
-Makefile             : A UNIX makefile to build and install the library
-README               : This file
-chealpix.h           : Header file to be included to define the functions
-chealpix.c           : implementation of the C Healpix routines
-
-test_chealpix.c      : Self-test for pixel operations and FITS I/O
diff --git a/src/external/OpenGR/3rdparty/chealpix/READ_Copyrights_Licenses.txt b/src/external/OpenGR/3rdparty/chealpix/READ_Copyrights_Licenses.txt
deleted file mode 100644
index 36aafd1d6..000000000
--- a/src/external/OpenGR/3rdparty/chealpix/READ_Copyrights_Licenses.txt
+++ /dev/null
@@ -1,170 +0,0 @@
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-  Copyright (C) 1997-2013  HEALPix collaboration
-
-
-  HEALPix is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  HEALPix is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with HEALPix; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-  For more information about HEALPix see http://healpix.sourceforge.net
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-HISTORY
- 
- This is a software package for HEALPix, the Hierarchical, Equal Area, and 
- iso-Latitude Pixelation of the sphere, which was  originally devised 
- in early 1997 by Krzysztof M. Gorski at the Theoretical Astrophysics 
- Center in Copenhagen. Early development of the HEALPix concept and initial 
- implementation was made in the spring of 1997 in  collaborative work 
- of KMG, currently at JPL with Eric Hivon, currently at IAP. Benjamin D. Wandelt,
- currently at IAP, has contributed critically to the 
- further development of HEALPix and related mathematical methods.
-
- The  HEALPix-based  methods  contained  in  the  present  package,  their 
- implementation in Fortran90, IDL, C, C++ and java routines and codes, and documentation 
- were developed jointly by: 
- Anthony J. Banday (banday@mpa-garching.mpg.de),
- Matthias Bartelmann (mbartelmann@ita.uni-heidelberg.de),
- Hans Kristian Eriksen (h.k.k.eriksen@astro.uio.no),
- Krzysztof M. Gorski (krzysztof.m.gorski@jpl.nasa.gov),
- Frode K. Hansen (fhansen@mpa-garching.mpg.de), 
- Eric Hivon (hivon@iap.fr),
- William O'Mullane (womullan@skysrv.pha.jhu.edu),
- Martin Reinecke (martin@mpa-garching.mpg.de), and
- Benjamin D. Wandelt (bwandelt@iap.fr).
-
- The HEALPix package is available at this address: 
- http://healpix.sourceforge.net
-
-COPYRIGHTS
-
- Copyright 1997 by Krzysztof M. Gorski
- for the HEALPix design and logo.
-  All rights reserved.
-
- Copyright 1997 by Eric Hivon and Krzysztof M. Gorski
- for the HEALPix package version 0.80
-  All rights reserved.
-
- Copyright 1998 by Benjamin Wandelt, Eric Hivon, and Krzysztof M. Gorski
- for the HotSpot package
-  All rights reserved.
-
- Copyright 1998 by K.M. Gorski, Eric Hivon, and B.D. Wandelt
- for the HEALPix package version 0.90
-  All rights reserved.
-
- Copyright 1998 by A.J. Banday and M.S. Bartelmann
- for the healgif package
-  All rights reserved.
-
- Copyright 1999 by K.M. Gorski, B.D. Wandelt, E. Hivon, F. Hansen, A.J. Banday,
- and M. Bartelmann
- for the HEALPix package version 1.00
-  All rights reserved.
-
- Copyright 2000 by K.M. Gorski, B.D. Wandelt, E. Hivon, F. Hansen, A.J. Banday,
- and M. Bartelmann
- for the HEALPix package version 1.10
-  All rights reserved.
-
- Copyright 2003 by K.M. Gorski, E. Hivon, M. Reinecke, A.J. Banday,
- B.D. Wandelt, and M. Bartelmann
- for the HEALPix package version 1.20
-  All rights reserved.
-
- Copyright 2003 by E. Hivon, Kenneth M. Ganga (ganga@cdf.in2p3.fr), Reza Ansari (ansari@lal.in2p3.fr)
- for the HEALPix C package
-  All rights reserved.
-
- Copyright 2005 by E. Hivon, M. Reinecke, W. O'Mullane, H.K. Eriksen, K.M. Gorski, A.J. Banday
- for the HEALPix package version 2.00
-  All rights reserved.
-
- Copyright 2005 by  H.K. Eriksen, Snorre Boasson (snorre.boasson@ntnu.no), M. Reinecke, E. Hivon
- for the MPI implementation of HEALPix F90 alm routines
-  All rights reserved.
-
- Copyright 2008 by E. Hivon, M. Reinecke, W. O'Mullane, H.K. Eriksen, K.M. Gorski, A.J. Banday, E. Joliet
- for the HEALPix package version 2.10
-  All rights reserved.
-
- Copyright 2008 by G. Rocha
- for the ngsims package
-  All rights reserved.
-
- Copyright 2008 by J. P. Leahy
- for the ximview package
-  All rights reserved.
-
- Copyright 2008 by D. Larson
- for the alice package
-  All rights reserved.
-
- Copyright 2010 by E. Hivon, M. Reinecke, W. O'Mullane, E. Joliet, K.M. Gorski, A.J. Banday
- for the HEALPix package version 2.20
-  All rights reserved.
-
- Copyright 2012 by E. Hivon, M. Reinecke, W. O'Mullane, E. Joliet, K.M. Gorski, A.J. Banday
- for the HEALPix package version 3.00
-  All rights reserved.
-
- Copyright 2013 by E. Hivon, M. Reinecke, W. O'Mullane, E. Joliet, K.M. Gorski, A.J. Banday
- for the HEALPix package version 3.10
-  All rights reserved.
-
- Copyright 2013 by A. Zonca, C. Rosset
- for the healpy package version 1.5.0
-  All rights reserved.
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-ACKNOWLEDGMENTS
-
-We thank the following people for their contributions and/or suggestions, which
-significantly helped us to improve HEALPix throughout its several releases
-
- Reza Ansari,
- Marc Ashdown,
- Carlo Baccigalupi,
- Tristan Beau,
- Snorre Boasson,
- Michela Botti,
- Stephane Colombi,
- Giancarlo de Gasperis,
- Herve Dole,
- Olivier Dore,
- Hans Kristian Eriksen,
- Ken Ganga,
- Giovanna Giardino,
- Jean-Christophe Hamilton,
- Andrew Jaffe
- Alex Kim,
- Ted Kisner,
- Guy Le Meur,
- Anthony Lewis,
- Davide Maino,
- Serge Monkewitz,
- Paolo Natoli,
- Clive Page,
- William Pence,
- Nicolas Ponthieu,
- Torsti Poutanen,
- Simon Prunet,
- Benoit Revenu,
- Rosa Ruiloba,
- David N. Spergel,
- Radek Stompor,
- Giovanna Tinetti.
diff --git a/src/external/OpenGR/3rdparty/chealpix/include/chealpix.h b/src/external/OpenGR/3rdparty/chealpix/include/chealpix.h
deleted file mode 100644
index 3aefb07ca..000000000
--- a/src/external/OpenGR/3rdparty/chealpix/include/chealpix.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- *  Copyright (C) 1997-2012 Krzysztof M. Gorski, Eric Hivon, Martin Reinecke,
- *                          Benjamin D. Wandelt, Anthony J. Banday,
- *                          Matthias Bartelmann,
- *                          Reza Ansari & Kenneth M. Ganga
- *
- *
- *  This file is part of HEALPix.
- *
- *  HEALPix is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  HEALPix is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with HEALPix; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *  For more information about HEALPix see http://healpix.sourceforge.net
- *
- *----------------------------------------------------------------------------*/
-/*
- * chealpix.h
- */
-
-#ifndef CHEALPIX_H
-#define CHEALPIX_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*! \defgroup chealpix HEALPix C interface
-    All angles are in radian, all \a theta values are colatitudes, i.e. counted
-    downwards from the North Pole. \a Nside can be any positive number for
-    pixelisations in RING scheme; in NEST scheme, they must be powers of 2.
-    The maximum \a Nside for the traditional interface is 8192; for the
-    64bit interface it is 2^29.
- */
-/*! \{ */
-
-/* -------------------- */
-/* Constant Definitions */
-/* -------------------- */
-
-#ifndef HEALPIX_NULLVAL
-#define HEALPIX_NULLVAL (-1.6375e30)
-#endif /* HEALPIX_NULLVAL */
-
-/* pixel operations */
-/* ---------------- */
-/*! Sets \a *ipix to the pixel number in NEST scheme at resolution \a nside,
-    which contains the position \a theta, \a phi. */
-void ang2pix_nest(long nside, double theta, double phi, long *ipix);
-/*! Sets \a *ipix to the pixel number in RING scheme at resolution \a nside,
-    which contains the position \a theta, \a phi. */
-void ang2pix_ring(long nside, double theta, double phi, long *ipix);
-
-/*! Sets \a theta and \a phi to the angular position of the center of pixel
-    \a ipix in NEST scheme at resolution \a nside. */
-void pix2ang_nest(long nside, long ipix, double *theta, double *phi);
-/*! Sets \a theta and \a phi to the angular position of the center of pixel
-    \a ipix in NEST scheme at resolution \a nside. */
-void pix2ang_ring(long nside, long ipix, double *theta, double *phi);
-
-/*! Computes the RING pixel index of pixel \a ipnest at resolution \a nside
-    and returns it in \a *ipring. On error, \a *ipring is set to -1. */
-void nest2ring(long nside, long ipnest, long *ipring);
-/*! Computes the NEST pixel index of pixel \a ipring at resolution \a nside
-    and returns it in \a *ipring. On error, \a *ipnest is set to -1. */
-void ring2nest(long nside, long ipring, long *ipnest);
-
-/*! Returns \a 12*nside*nside. */
-long nside2npix(long nside);
-/*! Returns \a sqrt(npix/12) if this is an integer number, otherwise \a -1. */
-long npix2nside(long npix);
-
-/*! Computes a normalized Cartesian vector pointing in the same direction as
-    \a theta, \a phi, and stores it in \a vec. \a vec must point to storage
-    sufficient for at least three doubles. */
-void ang2vec(double theta, double phi, double *vec);
-/*! Computes the angles \a *theta and \a *phi describing the same directions
-    as the Cartesian vector \a vec. \a vec need not be normalized. */
-void vec2ang(const double *vec, double *theta, double *phi);
-
-/*! Sets \a *ipix to the pixel number in NEST scheme at resolution \a nside,
-    which contains the direction described the Cartesian vector \a vec. */
-void vec2pix_nest(long nside, const double *vec, long *ipix);
-/*! Sets \a *ipix to the pixel number in RING scheme at resolution \a nside,
-    which contains the direction described the Cartesian vector \a vec. */
-void vec2pix_ring(long nside, const double *vec, long *ipix);
-
-/*! Sets \a vec to the Cartesian vector pointing in the direction of the center
-    of pixel \a ipix in NEST scheme at resolution \a nside. */
-void pix2vec_nest(long nside, long ipix, double *vec);
-/*! Sets \a vec to the Cartesian vector pointing in the direction of the center
-    of pixel \a ipix in RING scheme at resolution \a nside. */
-void pix2vec_ring(long nside, long ipix, double *vec);
-
-/* operations on Nside values up to 2^29 */
-
-/*! 64bit integer type
-    \note We are not using \c int64_t, since this type is not part of the C++
-    standard, and we want the header to be usable from C++. */
-typedef long long hpint64;
-
-/*! Sets \a *ipix to the pixel number in NEST scheme at resolution \a nside,
-    which contains the position \a theta, \a phi. */
-void ang2pix_nest64(hpint64 nside, double theta, double phi, hpint64 *ipix);
-/*! Sets \a *ipix to the pixel number in RING scheme at resolution \a nside,
-    which contains the position \a theta, \a phi. */
-void ang2pix_ring64(hpint64 nside, double theta, double phi, hpint64 *ipix);
-
-/*! Sets \a theta and \a phi to the angular position of the center of pixel
-    \a ipix in NEST scheme at resolution \a nside. */
-void pix2ang_nest64(hpint64 nside, hpint64 ipix, double *theta, double *phi);
-/*! Sets \a theta and \a phi to the angular position of the center of pixel
-    \a ipix in RING scheme at resolution \a nside. */
-void pix2ang_ring64(hpint64 nside, hpint64 ipix, double *theta, double *phi);
-
-/*! Computes the RING pixel index of pixel \a ipnest at resolution \a nside
-    and returns it in \a *ipring. On error, \a *ipring is set to -1. */
-void nest2ring64(hpint64 nside, hpint64 ipnest, hpint64 *ipring);
-/*! Computes the NEST pixel index of pixel \a ipring at resolution \a nside
-    and returns it in \a *ipring. On error, \a *ipnest is set to -1. */
-void ring2nest64(hpint64 nside, hpint64 ipring, hpint64 *ipnest);
-
-/*! Returns \a 12*nside*nside. */
-hpint64 nside2npix64(hpint64 nside);
-/*! Returns \a sqrt(npix/12) if this is an integer number, otherwise \a -1. */
-long npix2nside64(hpint64 npix);
-
-/*! Sets \a *ipix to the pixel number in NEST scheme at resolution \a nside,
-    which contains the direction described the Cartesian vector \a vec. */
-void vec2pix_nest64(hpint64 nside, const double *vec, hpint64 *ipix);
-/*! Sets \a *ipix to the pixel number in RING scheme at resolution \a nside,
-    which contains the direction described the Cartesian vector \a vec. */
-void vec2pix_ring64(hpint64 nside, const double *vec, hpint64 *ipix);
-
-/*! Sets \a vec to the Cartesian vector pointing in the direction of the center
-    of pixel \a ipix in NEST scheme at resolution \a nside. */
-void pix2vec_nest64(hpint64 nside, hpint64 ipix, double *vec);
-/*! Sets \a vec to the Cartesian vector pointing in the direction of the center
-    of pixel \a ipix in RING scheme at resolution \a nside. */
-void pix2vec_ring64(hpint64 nside, hpint64 ipix, double *vec);
-
-/* FITS operations */
-/* --------------- */
-
-float *read_healpix_map (const char *infile, long *nside, char *coordsys,
-  char *ordering);
-
-void write_healpix_map (const float *signal, long nside, const char *filename,
-  char nest, const char *coordsys);
-
-long get_fits_size(const char *filename, long *nside, char *ordering);
-
-/*! \} */
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* CHEALPIX_H */
diff --git a/src/external/OpenGR/3rdparty/chealpix/src/chealpix.c b/src/external/OpenGR/3rdparty/chealpix/src/chealpix.c
deleted file mode 100644
index 223895f19..000000000
--- a/src/external/OpenGR/3rdparty/chealpix/src/chealpix.c
+++ /dev/null
@@ -1,1077 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- *  Copyright (C) 1997-2012 Krzysztof M. Gorski, Eric Hivon, Martin Reinecke,
- *                          Benjamin D. Wandelt, Anthony J. Banday,
- *                          Matthias Bartelmann,
- *                          Reza Ansari & Kenneth M. Ganga
- *
- *
- *  This file is part of HEALPix.
- *
- *  HEALPix is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  HEALPix is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with HEALPix; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *  For more information about HEALPix see http://healpix.sourceforge.net
- *
- *---------------------------------------------------------------------------*/
-
-#include 
-#include 
-#include 
-#include 
-#ifdef ENABLE_FITSIO
-#include "fitsio.h"
-#endif
-#include "chealpix.h"
-
-static const double twothird=2.0/3.0;
-static const double pi=3.141592653589793238462643383279502884197;
-static const double twopi=6.283185307179586476925286766559005768394;
-static const double halfpi=1.570796326794896619231321691639751442099;
-static const double inv_halfpi=0.6366197723675813430755350534900574;
-
-static void util_fail_ (const char *file, int line, const char *func,
-  const char *msg)
-  {
-  fprintf(stderr,"%s, %i (%s):\n%s\n",file,line,func,msg);
-  exit(1);
-  }
-
-#if defined (__GNUC__)
-#define UTIL_FUNC_NAME__ __func__
-#else
-#define UTIL_FUNC_NAME__ "unknown"
-#endif
-#define UTIL_ASSERT(cond,msg) \
-  if(!(cond)) util_fail_(__FILE__,__LINE__,UTIL_FUNC_NAME__,msg)
-#define UTIL_FAIL(msg) \
-  util_fail_(__FILE__,__LINE__,UTIL_FUNC_NAME__,msg)
-#define RALLOC(type,num) \
-  ((type *)util_malloc_((num)*sizeof(type)))
-#define DEALLOC(ptr) \
-  do { util_free_(ptr); (ptr)=NULL; } while(0)
-
-static void *util_malloc_ (size_t sz)
-  {
-  void *res;
-  if (sz==0) return NULL;
-  res = malloc(sz);
-  UTIL_ASSERT(res,"malloc() failed");
-  return res;
-  }
-static void util_free_ (void *ptr)
-  { if ((ptr)!=NULL) free(ptr); }
-
-/*! Returns the remainder of the division \a v1/v2.
-    The result is non-negative.
-    \a v1 can be positive or negative; \a v2 must be positive. */
-static double fmodulo (double v1, double v2)
-  {
-  if (v1>=0)
-    return (v1=0) ? ((v1=0) ? v : v+v2; }
-static int isqrt(int v)
-  { return (int)(sqrt(v+0.5)); }
-
-/* ctab[m] = (short)(
-       (m&0x1 )       | ((m&0x2 ) << 7) | ((m&0x4 ) >> 1) | ((m&0x8 ) << 6)
-    | ((m&0x10) >> 2) | ((m&0x20) << 5) | ((m&0x40) >> 3) | ((m&0x80) << 4)); */
-static const short ctab[]={
-  0,1,256,257,2,3,258,259,512,513,768,769,514,515,770,771,4,5,260,261,6,7,262,
-  263,516,517,772,773,518,519,774,775,1024,1025,1280,1281,1026,1027,1282,1283,
-  1536,1537,1792,1793,1538,1539,1794,1795,1028,1029,1284,1285,1030,1031,1286,
-  1287,1540,1541,1796,1797,1542,1543,1798,1799,8,9,264,265,10,11,266,267,520,
-  521,776,777,522,523,778,779,12,13,268,269,14,15,270,271,524,525,780,781,526,
-  527,782,783,1032,1033,1288,1289,1034,1035,1290,1291,1544,1545,1800,1801,1546,
-  1547,1802,1803,1036,1037,1292,1293,1038,1039,1294,1295,1548,1549,1804,1805,
-  1550,1551,1806,1807,2048,2049,2304,2305,2050,2051,2306,2307,2560,2561,2816,
-  2817,2562,2563,2818,2819,2052,2053,2308,2309,2054,2055,2310,2311,2564,2565,
-  2820,2821,2566,2567,2822,2823,3072,3073,3328,3329,3074,3075,3330,3331,3584,
-  3585,3840,3841,3586,3587,3842,3843,3076,3077,3332,3333,3078,3079,3334,3335,
-  3588,3589,3844,3845,3590,3591,3846,3847,2056,2057,2312,2313,2058,2059,2314,
-  2315,2568,2569,2824,2825,2570,2571,2826,2827,2060,2061,2316,2317,2062,2063,
-  2318,2319,2572,2573,2828,2829,2574,2575,2830,2831,3080,3081,3336,3337,3082,
-  3083,3338,3339,3592,3593,3848,3849,3594,3595,3850,3851,3084,3085,3340,3341,
-  3086,3087,3342,3343,3596,3597,3852,3853,3598,3599,3854,3855 };
-/* utab[m] = (short)(
-      (m&0x1 )       | ((m&0x2 ) << 1) | ((m&0x4 ) << 2) | ((m&0x8 ) << 3)
-    | ((m&0x10) << 4) | ((m&0x20) << 5) | ((m&0x40) << 6) | ((m&0x80) << 7)); */
-static const short utab[]={
-  0,1,4,5,16,17,20,21,64,65,68,69,80,81,84,85,256,257,260,261,272,273,276,277,
-  320,321,324,325,336,337,340,341,1024,1025,1028,1029,1040,1041,1044,1045,1088,
-  1089,1092,1093,1104,1105,1108,1109,1280,1281,1284,1285,1296,1297,1300,1301,
-  1344,1345,1348,1349,1360,1361,1364,1365,4096,4097,4100,4101,4112,4113,4116,
-  4117,4160,4161,4164,4165,4176,4177,4180,4181,4352,4353,4356,4357,4368,4369,
-  4372,4373,4416,4417,4420,4421,4432,4433,4436,4437,5120,5121,5124,5125,5136,
-  5137,5140,5141,5184,5185,5188,5189,5200,5201,5204,5205,5376,5377,5380,5381,
-  5392,5393,5396,5397,5440,5441,5444,5445,5456,5457,5460,5461,16384,16385,16388,
-  16389,16400,16401,16404,16405,16448,16449,16452,16453,16464,16465,16468,16469,
-  16640,16641,16644,16645,16656,16657,16660,16661,16704,16705,16708,16709,16720,
-  16721,16724,16725,17408,17409,17412,17413,17424,17425,17428,17429,17472,17473,
-  17476,17477,17488,17489,17492,17493,17664,17665,17668,17669,17680,17681,17684,
-  17685,17728,17729,17732,17733,17744,17745,17748,17749,20480,20481,20484,20485,
-  20496,20497,20500,20501,20544,20545,20548,20549,20560,20561,20564,20565,20736,
-  20737,20740,20741,20752,20753,20756,20757,20800,20801,20804,20805,20816,20817,
-  20820,20821,21504,21505,21508,21509,21520,21521,21524,21525,21568,21569,21572,
-  21573,21584,21585,21588,21589,21760,21761,21764,21765,21776,21777,21780,21781,
-  21824,21825,21828,21829,21840,21841,21844,21845 };
-
-static const int jrll[] = { 2,2,2,2,3,3,3,3,4,4,4,4 };
-static const int jpll[] = { 1,3,5,7,0,2,4,6,1,3,5,7 };
-
-static int xyf2nest (int nside, int ix, int iy, int face_num)
-  {
-  return (face_num*nside*nside) +
-      (utab[ix&0xff] | (utab[ix>>8]<<16)
-    | (utab[iy&0xff]<<1) | (utab[iy>>8]<<17));
-  }
-static void nest2xyf (int nside, int pix, int *ix, int *iy, int *face_num)
-  {
-  int npface_=nside*nside, raw;
-  *face_num = pix/npface_;
-  pix &= (npface_-1);
-  raw = (pix&0x5555) | ((pix&0x55550000)>>15);
-  *ix = ctab[raw&0xff] | (ctab[raw>>8]<<4);
-  pix >>= 1;
-  raw = (pix&0x5555) | ((pix&0x55550000)>>15);
-  *iy = ctab[raw&0xff] | (ctab[raw>>8]<<4);
-  }
-static int xyf2ring (int nside_, int ix, int iy, int face_num)
-  {
-  int nl4 = 4*nside_;
-  int jr = (jrll[face_num]*nside_) - ix - iy  - 1, jp;
-
-  int nr, kshift, n_before;
-  if (jr 3*nside_)
-    {
-    nr = nl4-jr;
-    n_before = 12*nside_*nside_ - 2*(nr+1)*nr;
-    kshift = 0;
-    }
-  else
-    {
-    int ncap_=2*nside_*(nside_-1);
-    nr = nside_;
-    n_before = ncap_ + (jr-nside_)*nl4;
-    kshift = (jr-nside_)&1;
-    }
-
-  jp = (jpll[face_num]*nr + ix - iy + 1 + kshift) / 2;
-  if (jp>nl4)
-    jp-=nl4;
-  else
-    if (jp<1) jp+=nl4;
-
-  return n_before + jp - 1;
-  }
-static void ring2xyf (int nside_, int pix, int *ix, int *iy, int *face_num)
-  {
-  int iring, iphi, kshift, nr, tmp, irt, ipt;
-  int ncap_=2*nside_*(nside_-1);
-  int npix_=12*nside_*nside_;
-  int nl2 = 2*nside_;
-
-  if (pix=(2*iring))
-      {
-      *face_num=2;
-      tmp-=2*iring;
-      }
-    if (tmp>=iring) ++(*face_num);
-    }
-  else if (pix<(npix_-ncap_)) /* Equatorial region */
-    {
-    unsigned int ire, irm;
-    int ifm, ifp;
-    int ip = pix - ncap_;
-    iring = (ip/(4*nside_)) + nside_; /* counted from North pole */
-    iphi  = (ip%(4*nside_)) + 1;
-    kshift = (iring+nside_)&1;
-    nr = nside_;
-    ire = iring-nside_+1;
-    irm = nl2+2-ire;
-    ifm = (iphi - ire/2 + nside_ -1) / nside_;
-    ifp = (iphi - irm/2 + nside_ -1) / nside_;
-    if (ifp == ifm) /* faces 4 to 7 */
-      *face_num = (ifp==4) ? 4 : ifp+4;
-    else if (ifp=(2*nr))
-      {
-      *face_num=10;
-      tmp-=2*nr;
-      }
-    if (tmp>=nr) ++(*face_num);
-    }
-
-  irt = iring - (jrll[*face_num]*nside_) + 1;
-  ipt = 2*iphi- jpll[*face_num]*nr - kshift -1;
-  if (ipt>=nl2) ipt-=8*nside_;
-
-  *ix =  (ipt-irt) >>1;
-  *iy =(-(ipt+irt))>>1;
-  }
-
-static int ang2pix_nest_z_phi (long nside_, double z, double phi)
-  {
-  double za = fabs(z);
-  double tt = fmodulo(phi,twopi) * inv_halfpi; /* in [0,4) */
-  int face_num, ix, iy;
-
-  if (za<=twothird) /* Equatorial region */
-    {
-    double temp1 = nside_*(0.5+tt);
-    double temp2 = nside_*(z*0.75);
-    int jp = (int)(temp1-temp2); /* index of  ascending edge line */
-    int jm = (int)(temp1+temp2); /* index of descending edge line */
-    int ifp = jp/nside_;  /* in {0,4} */
-    int ifm = jm/nside_;
-    if (ifp == ifm)           /* faces 4 to 7 */
-      face_num = (ifp==4) ? 4: ifp+4;
-    else if (ifp < ifm)       /* (half-)faces 0 to 3 */
-      face_num = ifp;
-    else                      /* (half-)faces 8 to 11 */
-      face_num = ifm + 8;
-
-    ix = jm & (nside_-1);
-    iy = nside_ - (jp & (nside_-1)) - 1;
-    }
-  else /* polar region, za > 2/3 */
-    {
-    int ntt = (int)tt, jp, jm;
-    double tp, tmp;
-    if (ntt>=4) ntt=3;
-    tp = tt-ntt;
-    tmp = nside_*sqrt(3*(1-za));
-
-    jp = (int)(tp*tmp); /* increasing edge line index */
-    jm = (int)((1.0-tp)*tmp); /* decreasing edge line index */
-    if (jp>=nside_) jp = nside_-1; /* for points too close to the boundary */
-    if (jm>=nside_) jm = nside_-1;
-    if (z >= 0)
-      {
-      face_num = ntt;  /* in {0,3} */
-      ix = nside_ - jm - 1;
-      iy = nside_ - jp - 1;
-      }
-    else
-      {
-      face_num = ntt + 8; /* in {8,11} */
-      ix =  jp;
-      iy =  jm;
-      }
-    }
-
-  return xyf2nest(nside_,ix,iy,face_num);
-  }
-
-static int ang2pix_ring_z_phi (long nside_, double z, double phi)
-  {
-  double za = fabs(z);
-  double tt = fmodulo(phi,twopi) * inv_halfpi; /* in [0,4) */
-
-  if (za<=twothird) /* Equatorial region */
-    {
-    double temp1 = nside_*(0.5+tt);
-    double temp2 = nside_*z*0.75;
-    int jp = (int)(temp1-temp2); /* index of  ascending edge line */
-    int jm = (int)(temp1+temp2); /* index of descending edge line */
-
-    /* ring number counted from z=2/3 */
-    int ir = nside_ + 1 + jp - jm; /* in {1,2n+1} */
-    int kshift = 1-(ir&1); /* kshift=1 if ir even, 0 otherwise */
-
-    int ip = (jp+jm-nside_+kshift+1)/2; /* in {0,4n-1} */
-    ip = imodulo(ip,4*nside_);
-
-    return nside_*(nside_-1)*2 + (ir-1)*4*nside_ + ip;
-    }
-  else  /* North & South polar caps */
-    {
-    double tp = tt-(int)(tt);
-    double tmp = nside_*sqrt(3*(1-za));
-
-    int jp = (int)(tp*tmp); /* increasing edge line index */
-    int jm = (int)((1.0-tp)*tmp); /* decreasing edge line index */
-
-    int ir = jp+jm+1; /* ring number counted from the closest pole */
-    int ip = (int)(tt*ir); /* in {0,4*ir-1} */
-    ip = imodulo(ip,4*ir);
-
-    if (z>0)
-      return 2*ir*(ir-1) + ip;
-    else
-      return 12*nside_*nside_ - 2*ir*(ir+1) + ip;
-    }
-  }
-
-static void pix2ang_ring_z_phi (int nside_, int pix, double *z, double *phi)
-  {
-  long ncap_=nside_*(nside_-1)*2;
-  long npix_=12*nside_*nside_;
-  double fact2_  = 4./npix_;
-  if (pix 3*nside_)
-    {
-    nr = nl4-jr;
-    *z = nr*nr*fact2_ - 1;
-    kshift = 0;
-    }
-  else
-    {
-    double fact1_ = (nside_<<1)*fact2_;
-    nr = nside_;
-    *z = (2*nside_-jr)*fact1_;
-    kshift = (jr-nside_)&1;
-    }
-
-  jp = (jpll[face_num]*nr + ix -iy + 1 + kshift) / 2;
-  if (jp>nl4) jp-=nl4;
-  if (jp<1) jp+=nl4;
-
-  *phi = (jp-(kshift+1)*0.5)*(halfpi/nr);
-  }
-
-void ang2vec(double theta, double phi, double *vec)
-  {
-  double sz = sin(theta);
-  vec[0] = sz * cos(phi);
-  vec[1] = sz * sin(phi);
-  vec[2] = cos(theta);
-  }
-
-void vec2ang(const double *vec, double *theta, double *phi)
-  {
-  *theta = atan2(sqrt(vec[0]*vec[0]+vec[1]*vec[1]),vec[2]);
-  *phi = atan2 (vec[1],vec[0]);
-  if (*phi<0.) *phi += twopi;
-  }
-
-long npix2nside(long npix)
-  {
-  long res = (long)floor(sqrt(npix/12.)+0.5);
-  return (res*res*12==npix) ? res : -1;
-  }
-
-long nside2npix(const long nside)
-  { return 12*nside*nside; }
-
-void ang2pix_ring(long nside, double theta, double phi, long *ipix)
-  {
-  UTIL_ASSERT((theta>=0)&&(theta<=pi),"theta out of range");
-  *ipix=ang2pix_ring_z_phi (nside,cos(theta),phi);
-  }
-void ang2pix_nest(long nside, double theta, double phi, long *ipix)
-  {
-  UTIL_ASSERT((theta>=0)&&(theta<=pi),"theta out of range");
-  *ipix=ang2pix_nest_z_phi (nside,cos(theta),phi);
-  }
-void vec2pix_ring(long nside, const double *vec, long *ipix)
-  {
-  double vlen=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
-  *ipix=ang2pix_ring_z_phi (nside,vec[2]/vlen, atan2(vec[1],vec[0]));
-  }
-void vec2pix_nest(long nside, const double *vec, long *ipix)
-  {
-  double vlen=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
-  *ipix=ang2pix_nest_z_phi (nside,vec[2]/vlen, atan2(vec[1],vec[0]));
-  }
-void pix2ang_ring(long nside, long ipix, double *theta, double *phi)
-  {
-  double z;
-  pix2ang_ring_z_phi (nside,ipix,&z,phi);
-  *theta=acos(z);
-  }
-void pix2ang_nest(long nside, long ipix, double *theta, double *phi)
-  {
-  double z;
-  pix2ang_nest_z_phi (nside,ipix,&z,phi);
-  *theta=acos(z);
-  }
-void pix2vec_ring(long nside, long ipix, double *vec)
-  {
-  double z, phi, stheta;
-  pix2ang_ring_z_phi (nside,ipix,&z,&phi);
-  stheta=sqrt((1.-z)*(1.+z));
-  vec[0]=stheta*cos(phi);
-  vec[1]=stheta*sin(phi);
-  vec[2]=z;
-  }
-void pix2vec_nest(long nside, long ipix, double *vec)
-  {
-  double z, phi, stheta;
-  pix2ang_nest_z_phi (nside,ipix,&z,&phi);
-  stheta=sqrt((1.-z)*(1.+z));
-  vec[0]=stheta*cos(phi);
-  vec[1]=stheta*sin(phi);
-  vec[2]=z;
-  }
-void nest2ring(long nside, long ipnest, long *ipring)
-  {
-  int ix, iy, face_num;
-  if ((nside&(nside-1))!=0) { *ipring=-1; return; }
-  nest2xyf (nside, ipnest, &ix, &iy, &face_num);
-  *ipring = xyf2ring (nside, ix, iy, face_num);
-  }
-void ring2nest(long nside, long ipring, long *ipnest)
-  {
-  int ix, iy, face_num;
-  if ((nside&(nside-1))!=0) { *ipnest=-1; return; }
-  ring2xyf (nside, ipring, &ix, &iy, &face_num);
-  *ipnest = xyf2nest (nside, ix, iy, face_num);
-  }
-
-/* 64bit functions */
-
-static hpint64 imodulo64 (hpint64 v1, hpint64 v2)
-  { hpint64 v=v1%v2; return (v>=0) ? v : v+v2; }
-static long isqrt64(hpint64 v)
-  {
-  hpint64 res = sqrt(v+0.5);
-  if (v<((hpint64)(1)<<50)) return (long)res;
-  if (res*res>v)
-    --res;
-  else if ((res+1)*(res+1)<=v)
-    ++res;
-  return (long)res;
-  }
-
-static hpint64 spread_bits64 (int v)
-  {
-  return  (hpint64)(utab[ v     &0xff])
-       | ((hpint64)(utab[(v>> 8)&0xff])<<16)
-       | ((hpint64)(utab[(v>>16)&0xff])<<32)
-       | ((hpint64)(utab[(v>>24)&0xff])<<48);
-  }
-
-static hpint64 compress_bits64 (hpint64 v)
-  {
-  hpint64 raw = v&0x5555555555555555ull;
-  raw|=raw>>15;
-  return ctab[ raw     &0xff]      | (ctab[(raw>> 8)&0xff]<< 4)
-      | (ctab[(raw>>32)&0xff]<<16) | (ctab[(raw>>40)&0xff]<<20);
-  }
-
-static hpint64 xyf2nest64 (hpint64 nside, int ix, int iy, int face_num)
-  {
-  return (face_num*nside*nside) + spread_bits64(ix) + (spread_bits64(iy)<<1);
-  }
-
-static void nest2xyf64 (hpint64 nside, hpint64 pix, int *ix, int *iy,
-  int *face_num)
-  {
-  hpint64 npface_=nside*nside;
-  *face_num = pix/npface_;
-  pix &= (npface_-1);
-  *ix = compress_bits64(pix);
-  *iy = compress_bits64(pix>>1);
-  }
-
-static hpint64 xyf2ring64 (hpint64 nside_, int ix, int iy, int face_num)
-  {
-  hpint64 nl4 = 4*nside_;
-  hpint64 jr = (jrll[face_num]*nside_) - ix - iy  - 1, jp;
-
-  hpint64 nr, kshift, n_before;
-  if (jr 3*nside_)
-    {
-    nr = nl4-jr;
-    n_before = 12*nside_*nside_ - 2*(nr+1)*nr;
-    kshift = 0;
-    }
-  else
-    {
-    hpint64 ncap_=2*nside_*(nside_-1);
-    nr = nside_;
-    n_before = ncap_ + (jr-nside_)*nl4;
-    kshift = (jr-nside_)&1;
-    }
-
-  jp = (jpll[face_num]*nr + ix - iy + 1 + kshift) / 2;
-  if (jp>nl4)
-    jp-=nl4;
-  else
-    if (jp<1) jp+=nl4;
-
-  return n_before + jp - 1;
-  }
-static void ring2xyf64 (hpint64 nside_, hpint64 pix, int *ix, int *iy,
-  int *face_num)
-  {
-  hpint64 iring, iphi, kshift, nr, tmp, irt, ipt;
-  hpint64 ncap_=2*nside_*(nside_-1);
-  hpint64 npix_=12*nside_*nside_;
-  hpint64 nl2 = 2*nside_;
-
-  if (pix=(2*iring))
-      {
-      *face_num=2;
-      tmp-=2*iring;
-      }
-    if (tmp>=iring) ++(*face_num);
-    }
-  else if (pix<(npix_-ncap_)) /* Equatorial region */
-    {
-    hpint64 ire, irm;
-    hpint64 ifm, ifp;
-    hpint64 ip = pix - ncap_;
-    iring = (ip/(4*nside_)) + nside_; /* counted from North pole */
-    iphi  = (ip%(4*nside_)) + 1;
-    kshift = (iring+nside_)&1;
-    nr = nside_;
-    ire = iring-nside_+1;
-    irm = nl2+2-ire;
-    ifm = (iphi - ire/2 + nside_ -1) / nside_;
-    ifp = (iphi - irm/2 + nside_ -1) / nside_;
-    if (ifp == ifm) /* faces 4 to 7 */
-      *face_num = (ifp==4) ? 4 : ifp+4;
-    else if (ifp=(2*nr))
-      {
-      *face_num=10;
-      tmp-=2*nr;
-      }
-    if (tmp>=nr) ++(*face_num);
-    }
-
-  irt = iring - (jrll[*face_num]*nside_) + 1;
-  ipt = 2*iphi- jpll[*face_num]*nr - kshift -1;
-  if (ipt>=nl2) ipt-=8*nside_;
-
-  *ix =  (ipt-irt) >>1;
-  *iy =(-(ipt+irt))>>1;
-  }
-
-static hpint64 ang2pix_nest_z_phi64 (hpint64 nside_, double z, double s,
-  double phi)
-  {
-  double za = fabs(z);
-  double tt = fmodulo(phi,twopi) * inv_halfpi; /* in [0,4) */
-  int face_num, ix, iy;
-
-  if (za<=twothird) /* Equatorial region */
-    {
-    double temp1 = nside_*(0.5+tt);
-    double temp2 = nside_*(z*0.75);
-    hpint64 jp = (hpint64)(temp1-temp2); /* index of  ascending edge line */
-    hpint64 jm = (hpint64)(temp1+temp2); /* index of descending edge line */
-    hpint64 ifp = jp/nside_;  /* in {0,4} */
-    hpint64 ifm = jm/nside_;
-    if (ifp == ifm)           /* faces 4 to 7 */
-      face_num = (ifp==4) ? 4: ifp+4;
-    else if (ifp < ifm)       /* (half-)faces 0 to 3 */
-      face_num = ifp;
-    else                      /* (half-)faces 8 to 11 */
-      face_num = ifm + 8;
-
-    ix = jm & (nside_-1);
-    iy = nside_ - (jp & (nside_-1)) - 1;
-    }
-  else /* polar region, za > 2/3 */
-    {
-    int ntt = (int)tt, jp, jm;
-    double tp, tmp;
-    if (ntt>=4) ntt=3;
-    tp = tt-ntt;
-    if (s>-2.)
-      tmp = nside_*s/sqrt((1.+za)/3.);
-    else
-      tmp = nside_*sqrt(3*(1-za));
-
-    jp = (hpint64)(tp*tmp); /* increasing edge line index */
-    jm = (hpint64)((1.0-tp)*tmp); /* decreasing edge line index */
-    if (jp>=nside_) jp = nside_-1; /* for points too close to the boundary */
-    if (jm>=nside_) jm = nside_-1;
-    if (z >= 0)
-      {
-      face_num = ntt;  /* in {0,3} */
-      ix = nside_ - jm - 1;
-      iy = nside_ - jp - 1;
-      }
-    else
-      {
-      face_num = ntt + 8; /* in {8,11} */
-      ix =  jp;
-      iy =  jm;
-      }
-    }
-
-  return xyf2nest64(nside_,ix,iy,face_num);
-  }
-
-static hpint64 ang2pix_ring_z_phi64 (hpint64 nside_, double z, double s,
-  double phi)
-  {
-  double za = fabs(z);
-  double tt = fmodulo(phi,twopi) * inv_halfpi; /* in [0,4) */
-
-  if (za<=twothird) /* Equatorial region */
-    {
-    double temp1 = nside_*(0.5+tt);
-    double temp2 = nside_*z*0.75;
-    hpint64 jp = (hpint64)(temp1-temp2); /* index of  ascending edge line */
-    hpint64 jm = (hpint64)(temp1+temp2); /* index of descending edge line */
-
-    /* ring number counted from z=2/3 */
-    hpint64 ir = nside_ + 1 + jp - jm; /* in {1,2n+1} */
-    int kshift = 1-(ir&1); /* kshift=1 if ir even, 0 otherwise */
-
-    hpint64 ip = (jp+jm-nside_+kshift+1)/2; /* in {0,4n-1} */
-    ip = imodulo64(ip,4*nside_);
-
-    return nside_*(nside_-1)*2 + (ir-1)*4*nside_ + ip;
-    }
-  else  /* North & South polar caps */
-    {
-    double tp = tt-(int)(tt);
-    double tmp = (s>-2.) ? nside_*s/sqrt((1.+za)/3.) : nside_*sqrt(3*(1-za));
-
-    hpint64 jp = (hpint64)(tp*tmp); /* increasing edge line index */
-    hpint64 jm = (hpint64)((1.0-tp)*tmp); /* decreasing edge line index */
-
-    hpint64 ir = jp+jm+1; /* ring number counted from the closest pole */
-    hpint64 ip = (hpint64)(tt*ir); /* in {0,4*ir-1} */
-    ip = imodulo64(ip,4*ir);
-
-    if (z>0)
-      return 2*ir*(ir-1) + ip;
-    else
-      return 12*nside_*nside_ - 2*ir*(ir+1) + ip;
-    }
-  }
-
-static void pix2ang_ring_z_phi64 (hpint64 nside_, hpint64 pix,
-  double *z, double *s, double *phi)
-  {
-  hpint64 ncap_=nside_*(nside_-1)*2;
-  hpint64 npix_=12*nside_*nside_;
-  double fact2_  = 4./npix_;
-  *s=-5;
-  if (pix0.99) *s=sqrt(tmp*(2.-tmp));
-    *phi = (iphi-0.5) * halfpi/iring;
-    }
-  else if (pix<(npix_-ncap_)) /* Equatorial region */
-    {
-    double fact1_  = (nside_<<1)*fact2_;
-    hpint64 ip  = pix - ncap_;
-    hpint64 iring = ip/(4*nside_) + nside_; /* counted from North pole */
-    hpint64 iphi  = ip%(4*nside_) + 1;
-    /* 1 if iring+nside is odd, 1/2 otherwise */
-    double fodd = ((iring+nside_)&1) ? 1 : 0.5;
-
-    hpint64 nl2 = 2*nside_;
-    *z = (nl2-iring)*fact1_;
-    *phi = (iphi-fodd) * pi/nl2;
-    }
-  else /* South Polar cap */
-    {
-    hpint64 ip = npix_ - pix;
-    hpint64 iring = (hpint64)(0.5*(1+isqrt64(2*ip-1))); /* from S pole */
-    hpint64 iphi  = 4*iring + 1 - (ip - 2*iring*(iring-1));
-
-    double tmp=(iring*iring)*fact2_;
-    *z = tmp - 1.0;
-    if (*z<-0.99) *s=sqrt(tmp*(2.-tmp));
-    *phi = (iphi-0.5) * halfpi/iring;
-    }
-  }
-
-static void pix2ang_nest_z_phi64 (hpint64 nside_, hpint64 pix, double *z,
-  double *s, double *phi)
-  {
-  hpint64 nl4 = nside_*4;
-  hpint64 npix_=12*nside_*nside_;
-  double fact2_ = 4./npix_;
-  int face_num, ix, iy;
-  hpint64 jr, nr, kshift, jp;
-  *s=-5;
-
-  nest2xyf64(nside_,pix,&ix,&iy,&face_num);
-  jr = (jrll[face_num]*nside_) - ix - iy - 1;
-
-  if (jr0.99) *s=sqrt(tmp*(2.-tmp));
-    kshift = 0;
-    }
-  else if (jr > 3*nside_)
-    {
-    double tmp;
-    nr = nl4-jr;
-    tmp=(nr*nr)*fact2_;
-    *z = tmp - 1;
-    if (*z<-0.99) *s=sqrt(tmp*(2.-tmp));
-    kshift = 0;
-    }
-  else
-    {
-    double fact1_ = (nside_<<1)*fact2_;
-    nr = nside_;
-    *z = (2*nside_-jr)*fact1_;
-    kshift = (jr-nside_)&1;
-    }
-
-  jp = (jpll[face_num]*nr + ix -iy + 1 + kshift) / 2;
-  if (jp>nl4) jp-=nl4;
-  if (jp<1) jp+=nl4;
-
-  *phi = (jp-(kshift+1)*0.5)*(halfpi/nr);
-  }
-
-long npix2nside64(hpint64 npix)
-  {
-  hpint64 res = isqrt64(npix/12.);
-  return (res*res*12==npix) ? (long)res : -1;
-  }
-
-hpint64 nside2npix64(hpint64 nside)
-  { return 12*nside*nside; }
-
-void ang2pix_ring64(hpint64 nside, double theta, double phi, hpint64 *ipix)
-  {
-  UTIL_ASSERT((theta>=0)&&(theta<=pi),"theta out of range");
-  double cth=cos(theta), sth=(fabs(cth)>0.99) ? sin(theta) : -5;
-  *ipix=ang2pix_ring_z_phi64 (nside,cth,sth,phi);
-  }
-void ang2pix_nest64(hpint64 nside, double theta, double phi, hpint64 *ipix)
-  {
-  UTIL_ASSERT((theta>=0)&&(theta<=pi),"theta out of range");
-  double cth=cos(theta), sth=(fabs(cth)>0.99) ? sin(theta) : -5;
-  *ipix=ang2pix_nest_z_phi64 (nside,cth,sth,phi);
-  }
-void vec2pix_ring64(hpint64 nside, const double *vec, hpint64 *ipix)
-  {
-  double vlen=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
-  double cth = vec[2]/vlen;
-  double sth=(fabs(cth)>0.99) ? sqrt(vec[0]*vec[0]+vec[1]*vec[1])/vlen : -5;
-  *ipix=ang2pix_ring_z_phi64 (nside,cth,sth,atan2(vec[1],vec[0]));
-  }
-void vec2pix_nest64(hpint64 nside, const double *vec, hpint64 *ipix)
-  {
-  double vlen=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
-  double cth = vec[2]/vlen;
-  double sth=(fabs(cth)>0.99) ? sqrt(vec[0]*vec[0]+vec[1]*vec[1])/vlen : -5;
-  *ipix=ang2pix_nest_z_phi64 (nside,cth,sth,atan2(vec[1],vec[0]));
-  }
-void pix2ang_ring64(hpint64 nside, hpint64 ipix, double *theta, double *phi)
-  {
-  double z,s;
-  pix2ang_ring_z_phi64 (nside,ipix,&z,&s,phi);
-  *theta= (s<-2) ? acos(z) : atan2(s,z);
-  }
-void pix2ang_nest64(hpint64 nside, hpint64 ipix, double *theta, double *phi)
-  {
-  double z,s;
-  pix2ang_nest_z_phi64 (nside,ipix,&z,&s,phi);
-  *theta= (s<-2) ? acos(z) : atan2(s,z);
-  }
-void pix2vec_ring64(hpint64 nside, hpint64 ipix, double *vec)
-  {
-  double z, phi, stheta;
-  pix2ang_ring_z_phi64 (nside,ipix,&z,&stheta,&phi);
-  if (stheta<-2) stheta=sqrt((1.-z)*(1.+z));
-  vec[0]=stheta*cos(phi);
-  vec[1]=stheta*sin(phi);
-  vec[2]=z;
-  }
-void pix2vec_nest64(hpint64 nside, hpint64 ipix, double *vec)
-  {
-  double z, phi, stheta;
-  pix2ang_nest_z_phi64 (nside,ipix,&z,&stheta,&phi);
-  if (stheta<-2) stheta=sqrt((1.-z)*(1.+z));
-  vec[0]=stheta*cos(phi);
-  vec[1]=stheta*sin(phi);
-  vec[2]=z;
-  }
-void nest2ring64(hpint64 nside, hpint64 ipnest, hpint64 *ipring)
-  {
-  int ix, iy, face_num;
-  if ((nside&(nside-1))!=0) { *ipring=-1; return; }
-  nest2xyf64 (nside, ipnest, &ix, &iy, &face_num);
-  *ipring = xyf2ring64 (nside, ix, iy, face_num);
-  }
-void ring2nest64(hpint64 nside, hpint64 ipring, hpint64 *ipnest)
-  {
-  int ix, iy, face_num;
-  if ((nside&(nside-1))!=0) { *ipnest=-1; return; }
-  ring2xyf64 (nside, ipring, &ix, &iy, &face_num);
-  *ipnest = xyf2nest64 (nside, ix, iy, face_num);
-  }
-
-#ifdef ENABLE_FITSIO
-
-static void printerror (int status)
-  {
-  if (status==0) return;
-
-  fits_report_error(stderr, status);
-  UTIL_FAIL("FITS error");
-  }
-
-static void setCoordSysHP(char coordsys,char *coordsys9)
-  {
-  strcpy(coordsys9,"C       ");
-  if (coordsys=='G')
-    strcpy (coordsys9,"G       ");
-  else if (coordsys=='E')
-    strcpy (coordsys9,"E       ");
-  else if ((coordsys!='C')&&(coordsys!='Q'))
-    fprintf(stderr, "%s (%d): System Cordinates are not correct"
-                    "(Galactic,Ecliptic,Celestial=Equatorial). "
-                    " Celestial system was set.\n", __FILE__, __LINE__);
-  }
-
-float *read_healpix_map(const char *infile, long *nside, char *coordsys,
-  char *ordering)
-  {
-  /* Local Declarations */
-  long     naxes, *naxis, npix;
-  int      status=0, hdutype, nfound, anynul;
-  float    nulval, *map;
-  fitsfile *fptr;
-
-  fits_open_file(&fptr, infile, READONLY, &status);
-  fits_movabs_hdu(fptr, 2, &hdutype, &status);
-  printerror(status);
-
-  UTIL_ASSERT(hdutype==BINARY_TBL,"Extension is not binary!");
-
-  /* Read the sizes of the array */
-  fits_read_key_lng(fptr, "NAXIS", &naxes, NULL, &status);
-  printerror(status);
-
-  naxis = RALLOC(long,naxes);
-  fits_read_keys_lng(fptr, "NAXIS", 1, naxes, naxis, &nfound, &status);
-  printerror(status);
-  UTIL_ASSERT(nfound==naxes,"nfound!=naxes");
-
-  fits_read_key_lng(fptr, "NSIDE", nside, NULL, &status);
-  printerror(status);
-
-  npix = 12*(*nside)*(*nside);
-  UTIL_ASSERT((npix%naxis[1])==0,"Problem with npix.");
-
-  if (fits_read_key(fptr, TSTRING, "COORDSYS",coordsys, NULL, &status)) {
-    fprintf(stderr, "WARNING: Could not find %s keyword in in file %s\n",
-            "COORDSYS",infile);
-    status = 0;
-  }
-
-  if (fits_read_key(fptr, TSTRING, "ORDERING", ordering, NULL, &status)) {
-    fprintf(stderr, "WARNING: Could not find %s keyword in in file %s\n",
-            "ORDERING",infile);
-    status = 0;
-  }
-
-  /* Read the array */
-  map = RALLOC(float,npix);
-  nulval = HEALPIX_NULLVAL;
-  fits_read_col(fptr, TFLOAT, 1, 1, 1, npix, &nulval, map, &anynul, &status);
-  printerror(status);
-
-  DEALLOC(naxis);
-
-  fits_close_file(fptr, &status);
-  printerror(status);
-
-  return map;
-  }
-
-long get_fits_size(const char *filename, long *nside, char *ordering)
-  {
-  fitsfile *fptr;       /* pointer to the FITS file, defined in fitsio.h */
-  int status=0, hdutype;
-  long obs_npix;
-
-  fits_open_file(&fptr, filename, READONLY, &status);
-  fits_movabs_hdu(fptr, 2, &hdutype, &status); /* move to 2nd HDU */
-
-  fits_read_key(fptr, TSTRING, "ORDERING", ordering, NULL, &status);
-  fits_read_key(fptr, TLONG, "NSIDE", nside, NULL, &status);
-  printerror(status);
-
-  if (fits_read_key(fptr, TLONG, "OBS_NPIX", &obs_npix, NULL, &status)) {
-    obs_npix = 12 * (*nside) * (*nside);
-    status = 0;
-  }
-
-  fits_close_file(fptr, &status);
-  printerror(status);
-  return obs_npix;
-  }
-
-void write_healpix_map (const float *signal, long nside, const char *filename,
-  char nest, const char *coordsys)
-  {
-  fitsfile *fptr;       /* pointer to the FITS file, defined in fitsio.h */
-  int status=0, hdutype;
-
-  long naxes[] = {0,0};
-
-  char order[9];                 /* HEALPix ordering */
-  char *ttype[] = { "SIGNAL" };
-  char *tform[] = { "1E" };
-  char *tunit[] = { " " };
-  char coordsys9[9];
-
-  /* create new FITS file */
-  fits_create_file(&fptr, filename, &status);
-  fits_create_img(fptr, SHORT_IMG, 0, naxes, &status);
-  fits_write_date(fptr, &status);
-  fits_movabs_hdu(fptr, 1, &hdutype, &status);
-  fits_create_tbl( fptr, BINARY_TBL, 12L*nside*nside, 1, ttype, tform,
-                        tunit, "BINTABLE", &status);
-  fits_write_key(fptr, TSTRING, "PIXTYPE", "HEALPIX", "HEALPIX Pixelisation",
-    &status);
-
-  strcpy(order, nest ? "NESTED  " : "RING    ");
-  fits_write_key(fptr, TSTRING, "ORDERING", order,
-    "Pixel ordering scheme, either RING or NESTED", &status);
-  fits_write_key(fptr, TLONG, "NSIDE", &nside,
-    "Resolution parameter for HEALPIX", &status);
-
-  UTIL_ASSERT(strlen(coordsys)>=1,"bad ccordsys value");
-  setCoordSysHP(coordsys[0],coordsys9);
-  fits_write_key(fptr, TSTRING, "COORDSYS", coordsys9,
-    "Pixelisation coordinate system", &status);
-
-  fits_write_comment(fptr,
-    "G = Galactic, E = ecliptic, C = celestial = equatorial", &status);
-
-  fits_write_col(fptr, TFLOAT, 1, 1, 1, 12*nside*nside, (void *)signal,&status);
-  fits_close_file(fptr, &status);
-  printerror(status);
-  }
-
-#endif
diff --git a/src/external/OpenGR/CHANGELOG b/src/external/OpenGR/CHANGELOG
deleted file mode 100644
index 9bab5d6be..000000000
--- a/src/external/OpenGR/CHANGELOG
+++ /dev/null
@@ -1,70 +0,0 @@
-Super4PCS-V1.1.2
-======================
-### Purpose of this release
-Stabilizing building process and source code, and improve compatibility with modern CMake before use in other contexts (wrappers to other libraries, Meshlab plugin, etc...):
- * Add a Super4PCS CMake package exporting the libraries
- * Improve testing (enable testing on windows + test library linking)
-
-### Changelog
- - Improve installation process
-    - Install headers db3457fa4f422ed6b7073ea3d59cc70d7888fecb 7211d7640635dc2fb3592c768178e9a060a9a808
-    - Add proper cmake package 9b92ebbfe6ce08535f1c21f39eeb26f248f14916. Check instructions here: https://github.com/nmellado/Super4PCS/wiki/Compilation#usage
-    - Update CMake minimal version to 3.3 aa21804df523554f66bcbcee8ba8d248aedba584
- - API
-    - Refactor main namespace name as `GlobalRegistration` 036972d4ea7f5c304f6a04c690dfd789b920c656 ba79cae738e8bac8e412971c5875e316fbc558e8
-    - Clean `match4pcsBase` API: keep only `ComputeTransformation` as public method (+ getters), and mark other internal methods as protected. 
-Consequence of this change: the test applications will have to create local classes inheriting from `match4pcsBase` to allow access to these internal routines.  db3d7a06f48900f96a9af9a9fd657993fbe38806
- - Continuous Integration
-    - Update Travis script to cope for new cmake minimal version aa21804df523554f66bcbcee8ba8d248aedba584 f9b654dfd294259b9837628d2286f72660c70a9b 43b23f6ff29d6112dc7afc9bd1e7e5775063cb9c f185cfcc48d8eba5183944779449225c493d6e0d 57aa88896510c257846b434db09c26f37a58f07a 4b78a1798113d2f02a16994610bb8ba59226ab2d
-    - Add new test compiling and running an external application and linking against the Super4PCS library 75671cefddf2b4535cbb1f998a3080090bfaf1f2
-    - [windows] Enable testing (release only, due to bad performances in debug -> hitting timeout)
-    - [windows] Remove support for 32 bits builds 
- - Other fixes and improvements
-    - Remove compilation warnings in IO module (not that this module is not safer than before, but just quiet) 93e9fbf0ea6b5976fbf24487480725614e708ebd c8ad84e0460e0fc8efe8a98b169118590c8fd662
-    - Fix remaining logging commands not using the logging system 61b0fa229b65afee6ef586db6b4be326e8d0ca7d
-    - Add missing file in CMake project (`match4pcsBase.hpp` was not visible in IDEs) 65b8156a8af8cb885a75c31aacade89f099d6fc6
-    - Change `TransformVisitor` default behavior d2048b5534d528df5abb2d4f5c816cf2d462a99a
-
-Super4PCS-V1.1.1
-======================
-Minor release update including:
- - fixes in the deployment system and 
- - fix a compilation error when enabling timings, authored by @xinkang 
-
-Super4PCS-V1.1.0
-======================
-This release introduces new code structure allowing use as an actual library.
-
- - Build system
-   - Add install target in cmake
-   - Save binaries compiled by AppVeyor integration system as Artifacts
- - Demos, scripts and assets
-   - assets are now added to the install folder, including downloaded datasets
-   - demo scripts have been updated to work directly after installation. Windows batch scripts have been added.
- - Dependencies
-   - Chealpix dependency is marked as deprecated: it slows down the approach and reduce it's robustness. Consequently, Chealpix is still built in CI but not tested.
- - Devel
-   - Update include directive relatively to super4pcs root dir.
-   - Add silent mode in matcher to avoid unwanted logging on standard output. This is implemented by adding a visitor in the matcher main loop, and set it as a logger in the Super4pcs main app.
-
-Super4PCS-V1.0.0-alpha
-======================
-
-
- - Dependencies:
-   - remove ANN dependency,
-   - remove dependency to Chealpix. Can be controlled by the option SUPER4PCS_USE_CHEALPIX. This options will be available for some time for experiment purposes. During this time, Chealpix and Cfitsio files will still be shipped with Super4PCS source code.
-   - OpenCV is required only to load meshes textures. This dependency can be removed by switching option IO_USE_OPENCV to FALSE,
- - remove duplicate code between 4PCS and Super4PCS,
- - clean code structure,
- - demo dataset + run script added
-
-
-This release has been tested on:
-    Debian 4.9.30-1
-        clang version 3.8.1-24
-        gcc version 6.3.0 20170516
-    Microsoft Windows 10
-        VS 2017
-
-This release fixes issues 34 and 29.
diff --git a/src/external/OpenGR/CMakeLists.txt b/src/external/OpenGR/CMakeLists.txt
deleted file mode 100644
index 6670f7fd2..000000000
--- a/src/external/OpenGR/CMakeLists.txt
+++ /dev/null
@@ -1,316 +0,0 @@
-cmake_minimum_required (VERSION 3.3)
-project (OpenGR LANGUAGES CXX VERSION 1.1.3)
-
-################################################################################
-## User options
-################################################################################
-# Set option to enable timing recording
-OPTION (OpenGR_COMPILE_TESTS "Enable testing" TRUE)
-OPTION (OpenGR_COMPILE_DEMOS "Compile demo applications (including the Super4PCS standalone)" TRUE)
-OPTION (IO_USE_BOOST "Use boost::filesystem for texture loading" TRUE)
-OPTION (ENABLE_TIMING "Enable computation time recording" FALSE)
-OPTION (OpenGR_USE_CHEALPIX "Use Chealpix for orientation filtering (deprecated)" FALSE)
-OPTION (DL_DATASETS "Download demo datasets and associated run scripts" FALSE)
-OPTION (OpenGR_USE_WEIGHTED_LCP "Use gaussian weights for point samples when computing LCP" FALSE)
-
-################################################################################
-## DO NOT EDIT AFTER THIS LINE
-##
-## Variables configuration
-################################################################################
-set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
-set(SRC_DIR ${PROJECT_SOURCE_DIR}/src/)
-set(ASSETS_DIR ${PROJECT_SOURCE_DIR}/assets)
-set(SCRIPTS_DIR ${PROJECT_SOURCE_DIR}/scripts)
-set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
-
-################################################################################
-## GUARDS
-################################################################################
-
-# guard against in-source builds (source: Eigen)
-if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
-  message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ")
-endif()
-
-# guard against bad build-type strings (source: Eigen)
-if (NOT CMAKE_BUILD_TYPE)
-  set(CMAKE_BUILD_TYPE "Release")
-endif()
-string(TOLOWER "${CMAKE_BUILD_TYPE}" cmake_build_type_tolower)
-if(    NOT cmake_build_type_tolower STREQUAL "debug"
-   AND NOT cmake_build_type_tolower STREQUAL "release"
-   AND NOT cmake_build_type_tolower STREQUAL "relwithdebinfo")
-  message(FATAL_ERROR "Unknown build type \"${CMAKE_BUILD_TYPE}\". Allowed values are Debug, Release, RelWithDebInfo (case-insensitive).")
-endif()
-
-################################################################################
-## Compiler configuration
-################################################################################
-include(cmake/ConfigureCompiler.cmake)
-
-include(cmake/ConfigureRPath.cmake)
-
-################################################################################
-## Apply user-defined configuration
-################################################################################
-if (ENABLE_TIMING)
-    ADD_DEFINITIONS( -DTEST_GLOBAL_TIMINGS )
-    message (STATUS "OPT: Enable timing recording")
-endif (ENABLE_TIMING)
-
-if (OpenGR_USE_WEIGHTED_LCP)
-    ADD_DEFINITIONS( -DOPENGR_USE_WEIGHTED_LCP )
-    message (STATUS "Enable Weighted LCP")
-endif (OpenGR_USE_WEIGHTED_LCP)
-
-if (DL_DATASETS)
-    add_custom_target(dl-datasets)
-    include(ExternalProject)
-
-    ExternalProject_Add(dl-dataset-demo1
-        SOURCE_DIR ${ASSETS_DIR}/demo1
-        URL https://www.irit.fr/~Nicolas.Mellado/dl/datasets/point-clouds/Super4PCS-dataset-demo1.zip
-        URL_MD5 ad1e172902b41a3f17e9b4901adf3ba5
-        CONFIGURE_COMMAND ""
-        BUILD_COMMAND ""
-        INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/"
-        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=
-        INSTALL_COMMAND ""
-    )
-    add_dependencies(dl-datasets dl-dataset-demo1)
-endif (DL_DATASETS)
-
-################################################################################
-## Dependencies
-################################################################################
-
-if(OpenGR_USE_CHEALPIX)
-    include(cmake/ConfigureChealpix.cmake)
-endif(OpenGR_USE_CHEALPIX)
-
-## Eigen: automatic configuration:
-##  1. if EIGEN3_INCLUDE_DIR is set, use it directly
-##  2. if any, and version >= 3.3.x, use system version
-##  3. otherwise, download (if required) and use submodule
-if( NOT EIGEN3_INCLUDE_DIR )
-    find_package(Eigen3 QUIET)
-    if( (NOT Eigen3_FOUND) OR EIGEN_VERSION_NUMBER VERSION_LESS 3.3 )
-
-        set(EIGEN3_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/3rdparty/Eigen")
-
-        if( NOT EXISTS ${EIGEN3_INCLUDE_DIR}/signature_of_eigen3_matrix_library )
-            execute_process(COMMAND git submodule update --init -- ${EIGEN3_INCLUDE_DIR}
-                    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
-        endif( NOT EXISTS ${EIGEN3_INCLUDE_DIR}/signature_of_eigen3_matrix_library )
-    endif()
-endif( NOT EIGEN3_INCLUDE_DIR )
-include_directories(${EIGEN3_INCLUDE_DIR})
-message(STATUS "Eigen3 root path: ${EIGEN3_INCLUDE_DIR}")
-
-## Eigen: automatic configuration:
-##  1. if EIGEN3_INCLUDE_DIR is set, use it directly
-##  2. if any, and version >= 3.3.x, use system version
-##  3. otherwise, download (if required) and use submodule
-if( NOT STB_INCLUDE_DIR )
-    set(STB_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/3rdparty/stb")
-
-    if( NOT EXISTS ${STB_INCLUDE_DIR}/stb.h )
-        execute_process(COMMAND git submodule update --init -- ${STB_INCLUDE_DIR}
-                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
-    endif( NOT EXISTS ${STB_INCLUDE_DIR}/stb.h )
-endif( NOT STB_INCLUDE_DIR )
-include_directories(${STB_INCLUDE_DIR})
-message(STATUS "STB root path: ${STB_INCLUDE_DIR}")
-
-################################################################################
-## OPENGR algo
-################################################################################
-
-include_directories(${SRC_DIR})
-
-add_subdirectory(${SRC_DIR}/gr/io)
-add_subdirectory(${SRC_DIR}/gr/utils)
-add_subdirectory(${SRC_DIR}/gr/accelerators)
-add_subdirectory(${SRC_DIR}/gr/algorithms)
-
-# Add main target
-add_custom_target(opengr DEPENDS opengr_utils opengr_io opengr_accel opengr_algo )
-if(OpenGR_USE_CHEALPIX)
-    add_dependencies(opengr chealpix)
-endif(OpenGR_USE_CHEALPIX)
-
-################################################################################
-## Demos, tests, assets and scripts
-################################################################################
-
-if(OpenGR_COMPILE_TESTS)
-        include(cmake/ConfigureTesting.cmake)
-        add_subdirectory(tests EXCLUDE_FROM_ALL)
-endif(OpenGR_COMPILE_TESTS)
-
-include(cmake/AssetsAndScripts.cmake)
-
-if(OpenGR_COMPILE_DEMOS)
-        add_subdirectory(demos)
-endif(OpenGR_COMPILE_DEMOS)
-
-################################################################################
-# API documentation (generated with Doxygen)                                   #
-################################################################################
-
-find_package(Git)
-
-if(GIT_FOUND)
-    execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
-        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-        OUTPUT_VARIABLE GIT_CHANGESET)
-    if( GIT_CHANGESET )
-        # remove new line sometime appearing in git changeset
-        string(REGEX REPLACE "\n$" "" GIT_CHANGESET "${GIT_CHANGESET}")
-        string(SUBSTRING ${GIT_CHANGESET} 0 7 GIT_CHANGESET_SHORT)
-    endif()
-else()
-    set(GIT_CHANGESET "")
-    set(GIT_CHANGESET_SHORT "")
-endif()
-
-find_package(Doxygen 1.8.0)
-if(DOXYGEN_FOUND)
-
-    set (OpenGR_PROJECT_NUMBER "V${OpenGR_VERSION} (${GIT_CHANGESET_SHORT})")
-    set (OpenGR_DOC_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc)
-    file (GLOB_RECURSE OpenGR_MD_FILES ${CMAKE_CURRENT_SOURCE_DIR}/doc/*.md)
-
-    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doc/dox/Doxyfile.in ${OpenGR_DOC_DIRECTORY}/Doxyfile @ONLY)
-
-    ### Doxygen bootstrap
-    file(MAKE_DIRECTORY ${OpenGR_DOC_DIRECTORY}/)
-    file(MAKE_DIRECTORY ${OpenGR_DOC_DIRECTORY}/html/)
-    file ( DOWNLOAD https://raw.githubusercontent.com/Velron/doxygen-bootstrapped/master/customdoxygen.css
-           ${OpenGR_DOC_DIRECTORY}/html/customdoxygen.css SHOW_PROGRESS)
-    file ( DOWNLOAD https://raw.githubusercontent.com/Velron/doxygen-bootstrapped/master/doxy-boot.js
-           ${OpenGR_DOC_DIRECTORY}/html/doxy-boot.js SHOW_PROGRESS)
-
-    add_custom_target(doc
-        ${CMAKE_COMMAND} -E copy_directory
-        ${CMAKE_CURRENT_SOURCE_DIR}/doc/img/
-        ${OpenGR_DOC_DIRECTORY}/html/img
-        COMMAND ${CMAKE_COMMAND} -E copy_directory
-        ${CMAKE_CURRENT_SOURCE_DIR}/doc/dox/html/
-        ${OpenGR_DOC_DIRECTORY}/html/
-        COMMAND ${CMAKE_COMMAND} -E copy
-        ${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG
-        ${OpenGR_DOC_DIRECTORY}/
-        COMMAND ${DOXYGEN_EXECUTABLE} ${OpenGR_DOC_DIRECTORY}/Doxyfile
-        DEPENDS
-        ${CMAKE_CURRENT_SOURCE_DIR}/doc/dox/Doxyfile.in
-        ${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG
-        ${OpenGR_MD_FILES}
-        SOURCES
-        ${CMAKE_CURRENT_SOURCE_DIR}/doc/dox/Doxyfile.in
-        ${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG
-        ${OpenGR_MD_FILES}
-        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-        COMMENT "Generating API documentation with Doxygen" VERBATIM
-        )
-    install( DIRECTORY ${OpenGR_DOC_DIRECTORY}/ DESTINATION ${CMAKE_INSTALL_PREFIX}/doc )
-endif(DOXYGEN_FOUND)
-
-################################################################################
-# Installation (source: https://github.com/forexample/package-example)
-################################################################################
-
-# add a target allowing to force the installation of the library
-
-set(ForceInstallCommutators "")
-if (MSVC)
-        set(ForceInstallCommutators "/p:Configuration=${CMAKE_BUILD_TYPE}")
-endif(MSVC)
-add_custom_target(ForceOpenGRInstallation
-    COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target install -- ${ForceInstallCommutators}
-    COMMENT "Forcing OpenGR installation")
-
-
-set(config_install_dir "${CMAKE_INSTALL_PREFIX}/lib/cmake/")
-set(include_install_dir "${CMAKE_INSTALL_PREFIX}/include")
-set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
-
-# Configuration
-set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
-set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
-set(targets_export_name "${PROJECT_NAME}Targets")
-set(namespace "${PROJECT_NAME}::")
-
-# Include module with fuction 'write_basic_package_version_file'
-include(CMakePackageConfigHelpers)
-
-# Configure 'ConfigVersion.cmake'
-# Note: PROJECT_VERSION is used as a VERSION
-write_basic_package_version_file(
-    "${version_config}"
-                VERSION ${OpenGR_VERSION}
-                COMPATIBILITY AnyNewerVersion
-)
-
-# Configure 'Config.cmake'
-# version to be installed
-# Use variables:
-#   * targets_export_name
-#   * PROJECT_NAME
-# Used by Config.cmake.in
-set(OpenGR_INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include")
-set(OpenGR_INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
-set (OpenGR_EXPORT_TARGET_DIR \${CMAKE_CURRENT_LIST_DIR})
-configure_package_config_file(
-    "cmake/Config.cmake.in"
-    "${project_config}"
-    INSTALL_DESTINATION "${config_install_dir}"
-)
-
-# Configure 'Config.cmake'
-# version to be used with the current build directory
-# Use variables:
-#   * targets_export_name
-#   * PROJECT_NAME
-# Used by Config.cmake.in
-set(OpenGR_INSTALL_INC_DIR "${CMAKE_SOURCE_DIR}/src")
-set(OpenGR_INSTALL_LIB_DIR "${CMAKE_BINARY_DIR}/src/gr/io")
-set (OpenGR_EXPORT_TARGET_DIR "${CMAKE_BINARY_DIR}/cmake")
-configure_file(
-    "cmake/Config.cmake.in"
-    "${CMAKE_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
-)
-export(TARGETS opengr_io FILE "${CMAKE_BINARY_DIR}/cmake/OpenGR-IOLibTargets.cmake")
-export(TARGETS opengr_algo FILE "${CMAKE_BINARY_DIR}/cmake/OpenGR-AlgoLibTargets.cmake")
-export(TARGETS opengr_accel FILE "${CMAKE_BINARY_DIR}/cmake/OpenGR-AccelLibTargets.cmake")
-export(TARGETS opengr_utils FILE "${CMAKE_BINARY_DIR}/cmake/OpenGR-UtilsLibTargets.cmake")
-if(OpenGR_USE_CHEALPIX)
-    export(TARGETS chealpix FILE "${CMAKE_BINARY_DIR}/cmake/chealpixTargets.cmake")
-endif(OpenGR_USE_CHEALPIX)
-file(COPY "${version_config}" DESTINATION "${CMAKE_BINARY_DIR}/cmake"
-)
-
-
-install(EXPORT OpenGR-IOLibTargets    DESTINATION ${config_install_dir})
-install(EXPORT OpenGR-AlgoLibTargets  DESTINATION ${config_install_dir})
-install(EXPORT OpenGR-AccelLibTargets DESTINATION ${config_install_dir})
-install(EXPORT OpenGR-UtilsLibTargets DESTINATION ${config_install_dir})
-
-if(OpenGR_USE_CHEALPIX)
-    install(EXPORT chealpixTargets DESTINATION ${config_install_dir})
-endif(OpenGR_USE_CHEALPIX)
-
-# Headers:
-#   * Source/foo/Bar.hpp -> /include/foo/Bar.hpp
-install(DIRECTORY ${SRC_DIR}/
-        DESTINATION ${include_install_dir}
-        FILES_MATCHING REGEX ".*(h|hpp)$")
-
-# Config
-#   * /lib/cmake/Foo/FooConfig.cmake
-#   * /lib/cmake/Foo/FooConfigVersion.cmake
-install(
-    FILES "${project_config}" "${version_config}"
-    DESTINATION "${config_install_dir}"
-)
diff --git a/src/external/OpenGR/LICENSE b/src/external/OpenGR/LICENSE
deleted file mode 100644
index 999f206a6..000000000
--- a/src/external/OpenGR/LICENSE
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright [2014] [Nicolas Mellado]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/src/external/OpenGR/README.md b/src/external/OpenGR/README.md
deleted file mode 100644
index 20ab29481..000000000
--- a/src/external/OpenGR/README.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# OpenGR
-OpenGR is a set C++ libraries for 3D Global Registration.
-It is a fork of the [Super4PCS library](https://github.com/nmellado/Super4PCS), and aims at providing several state of the art global registration algorithms for 3d data.
-This fork is maintained by the same authors as the Super4PCS library.
-
-See the offical documentation here: https://storm-irit.github.io/OpenGR/index.html
-
-********
-Here's a BibTeX entry for OpenGR that you can use in your academic publications:
-
-```
- @MISC{openGR,
-  author = {Nicolas Mellado and others},
-  title = {OpenGR: A C++ library for 3D Global Registration},
-  howpublished = {https://storm-irit.github.io/OpenGR/},
-  year = {2017}
- }
- ```
-
-********
diff --git a/src/external/OpenGR/appveyor.yml b/src/external/OpenGR/appveyor.yml
deleted file mode 100644
index 2236f5031..000000000
--- a/src/external/OpenGR/appveyor.yml
+++ /dev/null
@@ -1,81 +0,0 @@
-# Specify version format
-version: "{build}"
-
-# Operating system (build VM template)
-os: Visual Studio 2017
-
-# build platform, i.e. Win32 (instead of x86), x64, Any CPU. This setting is optional.
-platform:
-  - x64
-
-# Do not build feature branch with open Pull Request
-skip_branch_with_pr: true
-
-skip_commits:
-  files:
-    .travis.yml
-    .gitignore
-
-# specify custom environment variables
-environment:
-  MSVC_DEFAULT_OPTIONS: ON
-  OpenGR_REPOSITORY_ROOT: C:\projects\OpenGR
-  OpenGR_BUILD_DIR: C:\projects\OpenGR\build
-  OpenGR_RELEASE_DIR: C:\projects\OpenGR\OpenGR-%platform%-%configuration%
-  OpenGR_RELEASE_NAME: OpenGR-%platform%-%configuration%
-
-# build configuration, i.e. Debug, Release, etc.
-configuration:
-  - Debug
-  - Release
-
-# scripts that are called at very beginning, before repo cloning
-init:
-  - cmd: cmake --version
-  - cmd: msbuild /version
-
-# clone directory
-clone_folder: C:\projects\OpenGR
-
-# branches to build
-branches:
-  # whitelist
-  # only:
-  #   - master
-  # blacklist
-  except:
-    - gh-pages
-
-# scripts that run after cloning repository
-install:
-
-# scripts to run before build
-before_build:
-  - cmd: md %OpenGR_BUILD_DIR%
-  - cmd: cd %OpenGR_BUILD_DIR%
-
-  - cmd: if "%platform%"=="Win32" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
-  - cmd: if "%platform%"=="x64"   set CMAKE_GENERATOR_NAME=Visual Studio 15 2017 Win64
-  - cmd: cmake -G "%CMAKE_GENERATOR_NAME%" -DCMAKE_BUILD_TYPE=%configuration% -DOpenGR_COMPILE_TESTS=TRUE -DIO_USE_BOOST=FALSE -DENABLE_TIMING=FALSE -DOpenGR_USE_CHEALPIX=FALSE -DDL_DATASETS=FALSE  -DCMAKE_INSTALL_PREFIX=%OpenGR_RELEASE_DIR% ..
-  - cmd: dir .
-
-build:
-  project: C:\projects\OpenGR\build\INSTALL.vcxproj  # path to Visual Studio solution or project
-  parallel: true                           # enable MSBuild parallel builds
-  verbosity: quiet                         # MSBuild verbosity level (quiet|minimal|normal|detailed)
-
-after_build:
-  - cmd: cd %OpenGR_REPOSITORY_ROOT%
-  - cmd: dir %OpenGR_RELEASE_DIR%
-
-artifacts:
-  - path: OpenGR-%platform%-%configuration% # use relative path
-    name: OpenGR-%platform%-%configuration%
-    type: zip
-
-test: on
-test_script:
-  - cmd: if "%configuration%"=="Release" msbuild %OpenGR_BUILD_DIR%\buildtests.vcxproj /m /p:Configuration=%configuration%
-  - cmd: if "%configuration%"=="Release" msbuild %OpenGR_BUILD_DIR%\RUN_TESTS.vcxproj  /m /p:Configuration=%configuration%
-#   - cmd: ctest --build-config %configuration% --parallel 4 --output-on-failure
-
diff --git a/src/external/OpenGR/assets/textured_cube.mtl b/src/external/OpenGR/assets/textured_cube.mtl
deleted file mode 100644
index ef7847430..000000000
--- a/src/external/OpenGR/assets/textured_cube.mtl
+++ /dev/null
@@ -1,13 +0,0 @@
-# Blender MTL File: 'None'
-# Material Count: 1
-
-newmtl Material
-Ns 96.078431
-Ka 1.000000 1.000000 1.000000
-Kd 0.640000 0.640000 0.640000
-Ks 0.500000 0.500000 0.500000
-Ke 0.000000 0.000000 0.000000
-Ni 1.000000
-d 1.000000
-illum 2
-map_Kd  textured_cube2.png
diff --git a/src/external/OpenGR/assets/textured_cube2.png b/src/external/OpenGR/assets/textured_cube2.png
deleted file mode 100644
index 63856ada1..000000000
Binary files a/src/external/OpenGR/assets/textured_cube2.png and /dev/null differ
diff --git a/src/external/OpenGR/cmake/AssetsAndScripts.cmake b/src/external/OpenGR/cmake/AssetsAndScripts.cmake
deleted file mode 100644
index 5d9b14f2d..000000000
--- a/src/external/OpenGR/cmake/AssetsAndScripts.cmake
+++ /dev/null
@@ -1,19 +0,0 @@
-
-# SCRIPTS
-file (GLOB Scripts_SRC ${SCRIPTS_DIR}/*.sh
-                       ${SCRIPTS_DIR}/*.bat)
-
-install( FILES ${Scripts_SRC}
-         DESTINATION ${CMAKE_INSTALL_PREFIX}/scripts
-         PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ)
-add_custom_target(opengr_scripts_IDE SOURCES ${Scripts_SRC})
-
-
-# ASSETS
-if (DL_DATASETS)
-    file (GLOB_RECURSE Assets_SRC  ${ASSETS_DIR}/*)
-    add_custom_target(opengr_assets SOURCES ${Assets_SRC}
-                                       DEPENDS dl-datasets)
-endif (DL_DATASETS)
-
-install( DIRECTORY ${ASSETS_DIR}/ DESTINATION ${CMAKE_INSTALL_PREFIX}/assets )
diff --git a/src/external/OpenGR/cmake/Config.cmake.in b/src/external/OpenGR/cmake/Config.cmake.in
deleted file mode 100644
index b037e486e..000000000
--- a/src/external/OpenGR/cmake/Config.cmake.in
+++ /dev/null
@@ -1,43 +0,0 @@
-# - Config file for the OpenGR package
-# It defines the following variables
-#  OPENGR_INCLUDE_DIRS - include directories for OpenGR
-#  OPENGR_LIB_DIR      - libraries to link against
-#  OPENGR_LIBRARIES    - libraries to link against
-#
-#
-# To use
-# ::
-# find_package(OpenGR REQUIRED)
-# include_directories(${OpenGR_INCLUDE_DIR})
-# add_executable(foo foo.cc)
-# target_link_libraries(foo ${OpenGR_LIBRARIES})
-# link_directories(${OpenGR_LIB_DIR})
-#
-# find_package( Eigen3 REQUIRED )
-# include_directories( ${EIGEN3_INCLUDE_DIR} )
-
-
-@PACKAGE_INIT@
-
-if(@OpenGR_USE_CHEALPIX@)
-  include("@OpenGR_EXPORT_TARGET_DIR@/chealpixTargets.cmake")
-endif(@OpenGR_USE_CHEALPIX@)
-
-
-include("@OpenGR_EXPORT_TARGET_DIR@/OpenGR-AccelLibTargets.cmake")
-include("@OpenGR_EXPORT_TARGET_DIR@/OpenGR-IOLibTargets.cmake")
-include("@OpenGR_EXPORT_TARGET_DIR@/OpenGR-AlgoLibTargets.cmake")
-include("@OpenGR_EXPORT_TARGET_DIR@/OpenGR-UtilsLibTargets.cmake")
-include("@OpenGR_EXPORT_TARGET_DIR@/OpenGRConfigVersion.cmake")
-
-
-# Compute paths
-set(OpenGR_INCLUDE_DIR "@OpenGR_INSTALL_INC_DIR@/")
-set(OpenGR_LIB_DIR "@OpenGR_INSTALL_LIB_DIR@/")
-set(OpenGR_LIBRARIES opengr_io)
-
-if(@OpenGR_USE_CHEALPIX@)
-  list(APPEND OpenGR_LIBRARIES chealpix)
-endif(@OpenGR_USE_CHEALPIX@)
-
-set(OpenGR_FOUND 1)
diff --git a/src/external/OpenGR/cmake/ConfigureChealpix.cmake b/src/external/OpenGR/cmake/ConfigureChealpix.cmake
deleted file mode 100644
index b26cb1d11..000000000
--- a/src/external/OpenGR/cmake/ConfigureChealpix.cmake
+++ /dev/null
@@ -1,22 +0,0 @@
-
-# EXTERNALS
-# have ExternalProject available
-include(ExternalProject)
-message(STATUS "[Deps] Use Chealpix")
-
-ExternalProject_Add(
-        cfitsio
-        # where the source will live
-        SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/cfitsio"
-        INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/"
-
-        CMAKE_ARGS
-            -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-
-        # override default behaviours
-        UPDATE_COMMAND ""
-)
-
-add_subdirectory(${PROJECT_SOURCE_DIR}/3rdparty/chealpix)
-add_definitions(-DSUPER4PCS_USE_CHEALPIX)
-include_directories(${Chealpix_INCLUDE_DIR})
diff --git a/src/external/OpenGR/cmake/ConfigureCompiler.cmake b/src/external/OpenGR/cmake/ConfigureCompiler.cmake
deleted file mode 100644
index d1d98a2c9..000000000
--- a/src/external/OpenGR/cmake/ConfigureCompiler.cmake
+++ /dev/null
@@ -1,35 +0,0 @@
-if( NOT cmake_build_type_tolower STREQUAL "release" )
-  add_definitions(-DDEBUG)
-endif()
-
-if (MSVC)
-  if (MSVC_VERSION LESS 1900)
-        message(FATAL_ERROR "Requires Microsoft Visual Studio Compiler version 14.0 or above.")
-  endif()
-
-  # remove exceptions from default args
-  add_definitions(-D_HAS_EXCEPTIONS=0)
-  # disable secure CRT warnings
-  add_definitions(-D_CRT_SECURE_NO_WARNINGS)
-  add_definitions(-D_SCL_SECURE_NO_WARNINGS)
-else()
-  find_package(OpenMP)
-
-  if(OPENMP_FOUND)
-    message(STATUS "Enable OpenMP")
-    add_definitions("-DOpenGR_USE_OPENMP -DEIGEN_DONT_PARALLELIZE")
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
-    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
-  endif(OPENMP_FOUND)
-endif()
-
-set (CMAKE_CXX_STANDARD 11)
-
-find_package(Meshlab QUIET)
-
-if(MESHLAB_FOUND)
-    # To ease use in shared libraries, even compiling statics Sup4pcs libs
-    set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-    message(STATUS "Enable position independent code")
-endif(MESHLAB_FOUND)
diff --git a/src/external/OpenGR/cmake/ConfigureRPath.cmake b/src/external/OpenGR/cmake/ConfigureRPath.cmake
deleted file mode 100644
index 00d8d0b89..000000000
--- a/src/external/OpenGR/cmake/ConfigureRPath.cmake
+++ /dev/null
@@ -1,24 +0,0 @@
-## This script comes from https://cmake.org/Wiki/CMake_RPATH_handling#Always_full_RPATH
-#
-# It is designed 'to make sure that the required libraries are always found
-# independent from LD_LIBRARY_PATH and the install location'
-
-# use, i.e. don't skip the full RPATH for the build tree
-SET(CMAKE_SKIP_BUILD_RPATH  FALSE)
-
-# when building, don't use the install RPATH already
-# (but later on when installing)
-SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
-
-SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
-
-# add the automatically determined parts of the RPATH
-# which point to directories outside the build tree to the install RPATH
-SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
-
-
-# the RPATH to be used when installing, but only if it's not a system directory
-LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
-IF("${isSystemDir}" STREQUAL "-1")
-   SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
-ENDIF("${isSystemDir}" STREQUAL "-1")
diff --git a/src/external/OpenGR/cmake/ConfigureTesting.cmake b/src/external/OpenGR/cmake/ConfigureTesting.cmake
deleted file mode 100644
index a16ae42c8..000000000
--- a/src/external/OpenGR/cmake/ConfigureTesting.cmake
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
-
-add_custom_target(buildtests)
-add_custom_target(check COMMAND "ctest")
-add_dependencies(check buildtests)
-
-# check whether /bin/bash exists
-find_file(OpenGR_BIN_BASH_EXISTS "/bin/bash" PATHS "/" NO_DEFAULT_PATH)
-
-# CMake/Ctest does not allow us to change the build command,
-# so we have to workaround by directly editing the generated DartConfiguration.tcl file
-# save CMAKE_MAKE_PROGRAM
-set(CMAKE_MAKE_PROGRAM_SAVE ${CMAKE_MAKE_PROGRAM})
-# and set a fake one
-set(CMAKE_MAKE_PROGRAM "@OpenGR_MAKECOMMAND_PLACEHOLDER@")
-
-# This call activates testing and generates the DartConfiguration.tcl
-# This adds another build target, which is test for Makefile generators,
-# or RUN_TESTS for integrated development environments (like Visual Studio)
-include(CTest)
-
-set(OpenGR_TEST_BUILD_FLAGS "" CACHE STRING "Options passed to the build command of unit tests")
-
-# overwrite default DartConfiguration.tcl
-# The worarounds are different for each version of the MSVC IDE
-set(OpenGR_TEST_TARGET buildtests)
-if(MSVC_IDE)
-  if(CMAKE_MAKE_PROGRAM_SAVE MATCHES "devenv") # devenv
-    set(OpenGR_BUILD_COMMAND "${CMAKE_MAKE_PROGRAM_SAVE} OpenGR.sln /build Release /project ${OpenGR_TEST_TARGET}")
-  else() # msbuild
-    set(OpenGR_BUILD_COMMAND "${CMAKE_MAKE_PROGRAM_SAVE} ${OpenGR_TEST_TARGET}.vcxproj /p:Configuration=\${CTEST_CONFIGURATION_TYPE}")
-  endif()
-
-  # append the build flags if provided
-  if(NOT "${OpenGR_TEST_BUILD_FLAGS}" MATCHES "^[ \t]*$")
-    set(OpenGR_BUILD_COMMAND "${OpenGR_BUILD_COMMAND} ${OpenGR_TEST_BUILD_FLAGS}")
-  endif()
-
-  # apply the dartconfig hack ...
-  set(OpenGR_MAKECOMMAND_PLACEHOLDER "${OpenGR_BUILD_COMMAND}\n#")
-else()
-  # for make and nmake
-  set(OpenGR_BUILD_COMMAND "${CMAKE_MAKE_PROGRAM_SAVE} ${OpenGR_TEST_TARGET} ${OpenGR_TEST_BUILD_FLAGS}")
-  set(OpenGR_MAKECOMMAND_PLACEHOLDER "${OpenGR_BUILD_COMMAND}")
-endif()
-
-configure_file(${CMAKE_BINARY_DIR}/DartConfiguration.tcl ${CMAKE_BINARY_DIR}/DartConfiguration.tcl)
-
-# restore default CMAKE_MAKE_PROGRAM
-set(CMAKE_MAKE_PROGRAM ${CMAKE_MAKE_PROGRAM_SAVE})
-
-# un-set temporary variables so that it is like they never existed
-unset(CMAKE_MAKE_PROGRAM_SAVE)
-unset(OpenGR_MAKECOMMAND_PLACEHOLDER)
-
-
-## Configure coverage
-#if(CMAKE_COMPILER_IS_GNUCXX)
-#  option(OpenGR_COVERAGE_TESTING "Enable/disable gcov" ON)
-
-#  if(OpenGR_COVERAGE_TESTING)
-#    set(COVERAGE_FLAGS "-fprofile-arcs -ftest-coverage")
-#  else(OpenGR_COVERAGE_TESTING)
-#    set(COVERAGE_FLAGS "")
-#  endif(OpenGR_COVERAGE_TESTING)
-
-#  if(OpenGR_TEST_C++0x)
-#    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
-#  endif(OpenGR_TEST_C++0x)
-
-#  if(CMAKE_SYSTEM_NAME MATCHES Linux)
-#    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_FLAGS} -g2")
-#    set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COVERAGE_FLAGS} -O2 -g2")
-#    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COVERAGE_FLAGS} -fno-inline-functions")
-#    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COVERAGE_FLAGS} -O0 -g3")
-#  endif(CMAKE_SYSTEM_NAME MATCHES Linux)
-
-#elseif(MSVC)
-
-#  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_CRT_SECURE_NO_WARNINGS /D_SCL_SECURE_NO_WARNINGS")
-
-#endif(CMAKE_COMPILER_IS_GNUCXX)
-
diff --git a/src/external/OpenGR/cmake/FindCFITSIO.cmake b/src/external/OpenGR/cmake/FindCFITSIO.cmake
deleted file mode 100644
index 1e547409b..000000000
--- a/src/external/OpenGR/cmake/FindCFITSIO.cmake
+++ /dev/null
@@ -1,54 +0,0 @@
-# - Try to find CFITSIO.
-# Once executed, this module will define:
-# Variables defined by this module:
-#  CFITSIO_FOUND        - system has CFITSIO
-#  CFITSIO_INCLUDE_DIR  - the CFITSIO include directory (cached)
-#  CFITSIO_INCLUDE_DIRS - the CFITSIO include directories
-#                         (identical to CFITSIO_INCLUDE_DIR)
-#  CFITSIO_LIBRARY      - the CFITSIO library (cached)
-#  CFITSIO_LIBRARIES    - the CFITSIO libraries
-#                         (identical to CFITSIO_LIBRARY)
-# 
-# This module will use the following enviornmental variable
-# when searching for CFITSIO:
-#  CFITSIO_ROOT_DIR     - CFITSIO root directory
-#
-
-# 
-#  Copyright (c) 2012 Brian Kloppenborg
-# 
-#  This file is part of the C++ OIFITS Library (CCOIFITS).
-#  
-#  CCOIFITS is free software: you can redistribute it and/or modify
-#  it under the terms of the GNU Lesser General Public License 
-#  as published by the Free Software Foundation, either version 3 
-#  of the License, or (at your option) any later version.
-#  
-#  CCOIFITS is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU Lesser General Public License for more details.
-#  
-#  You should have received a copy of the GNU Lesser General Public 
-#  License along with CCOIFITS.  If not, see .
-# 
-
-if(NOT CFITSIO_FOUND)
-
-    find_path(CFITSIO_INCLUDE_DIR fitsio.h
-        HINTS $ENV{CFITSIO_ROOT_DIR} 
-        PATH_SUFFIXES include include/cfitsio)
-    find_library(CFITSIO_LIBRARY cfitsio
-        HINTS $ENV{CFITSIO_ROOT_DIR} 
-        PATH_SUFFIXES lib)
-  
-    mark_as_advanced(CFITSIO_INCLUDE_DIR CFITSIO_LIBRARY)
-
-    include(FindPackageHandleStandardArgs)
-    find_package_handle_standard_args(CFITSIO DEFAULT_MSG
-        CFITSIO_LIBRARY CFITSIO_INCLUDE_DIR)
-
-    set(CFITSIO_INCLUDE_DIRS ${CFITSIO_INCLUDE_DIR})
-    set(CFITSIO_LIBRARIES ${CFITSIO_LIBRARY})
-
-endif(NOT CFITSIO_FOUND)
diff --git a/src/external/OpenGR/cmake/FindEigen3.cmake b/src/external/OpenGR/cmake/FindEigen3.cmake
deleted file mode 100644
index b80b2293e..000000000
--- a/src/external/OpenGR/cmake/FindEigen3.cmake
+++ /dev/null
@@ -1,82 +0,0 @@
-# - Try to find Eigen3 lib
-#
-# This module supports requiring a minimum version, e.g. you can do
-#   find_package(Eigen3 3.1.2)
-# to require version 3.1.2 or newer of Eigen3.
-#
-# Once done this will define
-#
-#  EIGEN3_FOUND - system has eigen lib with correct version
-#  EIGEN3_INCLUDE_DIR - the eigen include directory
-#  EIGEN3_VERSION - eigen version
-
-# Copyright (c) 2006, 2007 Montel Laurent, 
-# Copyright (c) 2008, 2009 Gael Guennebaud, 
-# Copyright (c) 2009 Benoit Jacob 
-# Redistribution and use is allowed according to the terms of the 2-clause BSD license.
-
-if(NOT Eigen3_FIND_VERSION)
-  if(NOT Eigen3_FIND_VERSION_MAJOR)
-    set(Eigen3_FIND_VERSION_MAJOR 2)
-  endif(NOT Eigen3_FIND_VERSION_MAJOR)
-  if(NOT Eigen3_FIND_VERSION_MINOR)
-    set(Eigen3_FIND_VERSION_MINOR 91)
-  endif(NOT Eigen3_FIND_VERSION_MINOR)
-  if(NOT Eigen3_FIND_VERSION_PATCH)
-    set(Eigen3_FIND_VERSION_PATCH 0)
-  endif(NOT Eigen3_FIND_VERSION_PATCH)
-
-  set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}")
-endif(NOT Eigen3_FIND_VERSION)
-
-macro(_eigen3_check_version)
-  file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
-
-  string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}")
-  set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}")
-  string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}")
-  set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}")
-  string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}")
-  set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}")
-
-  set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION})
-  if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
-    set(EIGEN3_VERSION_OK FALSE)
-  else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
-    set(EIGEN3_VERSION_OK TRUE)
-  endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
-
-  if(NOT EIGEN3_VERSION_OK)
-
-    message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, "
-                   "but at least version ${Eigen3_FIND_VERSION} is required")
-  endif(NOT EIGEN3_VERSION_OK)
-endmacro(_eigen3_check_version)
-
-if (EIGEN3_INCLUDE_DIR)
-
-  # in cache already
-  _eigen3_check_version()
-  set(EIGEN3_FOUND ${EIGEN3_VERSION_OK})
-
-else (EIGEN3_INCLUDE_DIR)
-
-  find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library
-      PATHS
-      ${CMAKE_INSTALL_PREFIX}/include
-      ${KDE4_INCLUDE_DIR}
-      $ENV{EIGEN3_INCLUDE_DIR}
-      PATH_SUFFIXES eigen3 eigen
-    )
-
-  if(EIGEN3_INCLUDE_DIR)
-    _eigen3_check_version()
-  endif(EIGEN3_INCLUDE_DIR)
-
-  include(FindPackageHandleStandardArgs)
-  find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK)
-
-  mark_as_advanced(EIGEN3_INCLUDE_DIR)
-
-endif(EIGEN3_INCLUDE_DIR)
-
diff --git a/src/external/OpenGR/cmake/FindMeshlab.cmake b/src/external/OpenGR/cmake/FindMeshlab.cmake
deleted file mode 100644
index 9c7dc4949..000000000
--- a/src/external/OpenGR/cmake/FindMeshlab.cmake
+++ /dev/null
@@ -1,64 +0,0 @@
-# Try to find the radium engine base folder
-# Will define
-# MESHLAB_SRC_DIR : the root of the Meshlab project
-# MESHLAB_PLUGINS_SOURCE_DIR     : directory where meshlab plugins sources are
-# MESHLAB_PROJECT_FILE           : path of the meshlab_full.pro file
-# MESHLAB_EXTERNAL_DIR           : root dir of meshlab externals
-# MESHLAB_EXTERNAL_INCLUDE_DIR   : path where external include files are installed
-# MESHLAB_EXTERNAL_LIBRARIES_DIR : path where external libraries are installed
-
-
-# MESHLAB_FOUND if found
-if( NOT MESHLAB_SRC_DIR )
-  find_path( MESHLAB_SRC_DIR NAMES meshlab_full.pro
-    PATHS
-    "${CMAKE_SOURCE_DIR}/../meshlab"
-    "${CMAKE_SOURCE_DIR}/../Meshlab"
-    "${CMAKE_SOURCE_DIR}/.."
-    "${CMAKE_SOURCE_DIR}/../.."
-    "${CMAKE_SOURCE_DIR}/../../.."
-    "${CMAKE_CURRENT_SOURCE_DIR}/../meshlab"
-    "${CMAKE_CURRENT_SOURCE_DIR}/../Meshlab"
-    "${CMAKE_CURRENT_SOURCE_DIR}/.."
-    "${CMAKE_CURRENT_SOURCE_DIR}/../.."
-    "${CMAKE_CURRENT_SOURCE_DIR}/../../.."
-    PATH_SUFFIXES src meshlab/src
-    DOC "The Meshlab src folder")
-endif( NOT MESHLAB_SRC_DIR )
-
-if ( MESHLAB_SRC_DIR )
-  set ( MESHLAB_RELATIVE_PLUGINS_SOURCE_DIR "meshlabplugins" )
-  set ( MESHLAB_PLUGINS_SOURCE_DIR          "${MESHLAB_SRC_DIR}/${MESHLAB_RELATIVE_PLUGINS_SOURCE_DIR}" )
-  set ( MESHLAB_PROJECT_FILE                "${MESHLAB_SRC_DIR}/meshlab_full.pro" )
-  set ( MESHLAB_EXTERNAL_DIR                "${MESHLAB_SRC_DIR}/external" )
-
-
-  # Meshlab put include files and libraries in the following plateform dependent
-  # folders:
-  #  - includes:  linux-g++, macx, macx64, win32-gcc, win32-msvc2008
-  #  - libraries: linux-g++, linux-g++-64, macx64 win32-gcc, win32-msvc2008, win32-msvc2015
-  set (INC_PLATEFORM "linux-g++" )
-  set (LIB_PLATEFORM "linux-g++" )
-
-  message(AUTHOR_WARNING "Automatic plateform detection not ready yet. Using ${INC_PLATEFORM}")
-
-
-  set ( MESHLAB_EXTERNAL_LIBRARIES_DIR "${MESHLAB_EXTERNAL_DIR}/lib/${LIB_PLATEFORM}" )
-  set ( MESHLAB_EXTERNAL_INCLUDE_DIR   "${MESHLAB_EXTERNAL_DIR}/inc/${INC_PLATEFORM}" )
-
-  unset ( INC_PLATEFORM )
-  unset ( LIB_PLATEFORM )
-
-  set ( MESHLAB_FOUND TRUE )
-
-endif( MESHLAB_SRC_DIR )
-
-if ( MESHLAB_FOUND )
-  if( NOT MESHLAB_FIND_QUIETLY )
-    message ( STATUS "Found Meshlab: ${MESHLAB_SRC_DIR}")
-  endif( NOT MESHLAB_FIND_QUIETLY )
-else( MESHLAB_FOUND )
-  if( MESHLAB_FIND_REQUIRED )
-    message( FATAL_ERROR "Could not find Meshlab src dir")
-  endif( MESHLAB_FIND_REQUIRED )
-endif( MESHLAB_FOUND )
diff --git a/src/external/OpenGR/demos/CMakeLists.txt b/src/external/OpenGR/demos/CMakeLists.txt
deleted file mode 100644
index 48c39bdcf..000000000
--- a/src/external/OpenGR/demos/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-project (OpenGR-Demos)
-
-add_subdirectory(Super4PCS)
-add_subdirectory(ExtPointBinding)
-add_subdirectory(MeshlabPlugin)
-add_subdirectory(PCLWrapper)
diff --git a/src/external/OpenGR/demos/ExtPointBinding/CMakeLists.txt b/src/external/OpenGR/demos/ExtPointBinding/CMakeLists.txt
deleted file mode 100644
index 8c7acd6dd..000000000
--- a/src/external/OpenGR/demos/ExtPointBinding/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-project(ExtPointBinding)
-
-set(Demo_ExtPointBinding_SRC
-    ${CMAKE_CURRENT_SOURCE_DIR}/external_point_binding_test.cc
-)
-
-add_executable(${PROJECT_NAME} ${Demo_ExtPointBinding_SRC})
-target_link_libraries(${PROJECT_NAME} opengr_utils opengr_io opengr_accel opengr_algo)
-add_dependencies(${PROJECT_NAME} opengr)
-if(OpenGR_USE_CHEALPIX)
-    target_link_libraries(${PROJECT_NAME} chealpix)
-endif(OpenGR_USE_CHEALPIX)
-install( TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin  )
diff --git a/src/external/OpenGR/demos/ExtPointBinding/ext/point_conversion.h b/src/external/OpenGR/demos/ExtPointBinding/ext/point_conversion.h
deleted file mode 100644
index 6ebcd7673..000000000
--- a/src/external/OpenGR/demos/ExtPointBinding/ext/point_conversion.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Created by Necip Fazil Yildiran on 06/20/19.
-//
-
-#ifndef __POINT_CONVERSION_H__
-#define __POINT_CONVERSION_H__
-
-#include 
-
-#include "point_extlib1.hpp"
-#include "point_extlib2.hpp"
-
-#include 
-#include 
-
-// create a vector of extlib1::PointType1 from a vector of gr::Point3D 
-template
-inline std::vector getExtlib1Points(const std::vector >& grPoints)
-{
-  std::vector result;
-
-  for(const auto &p : grPoints)
-  {
-    extlib1::PointType1 newp = { p.pos()(0), p.pos()(1), p.pos()(2),
-                                 p.normal()(0), p.normal()(1), p.normal()(2),
-                                 p.rgb()(0), p.rgb()(1), p.rgb()(2) };
-
-    result.push_back(newp);
-  }
-
-  return result;
-}
-
-// create a list of extlib2::PointType2 from a vector of gr::Point3D 
-template
-inline std::list getExtlib2Points(const std::vector >& grPoints)
-{
-  using PointType2 = extlib2::PointType2;
-
-  std::list result;
-
-  float* posBuffer   = new float[grPoints.size()*3];
-  float* nBuffer     = new float[grPoints.size()*3];
-  float* colorBuffer = new float[grPoints.size()*3];
-
-  int i = 0;
-  for(const auto &p : grPoints)
-  {
-    // fill corresponding section in buffers with p
-    for(int j = 0; j < 3; j++) {
-      posBuffer[i*3 + j]   = p.pos()(j);
-
-      nBuffer[i*3 + j]     = p.normal()(j);
-      colorBuffer[i*3 + j] = p.rgb()(j);
-    }
-
-    result.emplace_back( PointType2 { posBuffer, nBuffer, colorBuffer, i++ } );
-  }
-
-  return result;
-}
-
-#endif
\ No newline at end of file
diff --git a/src/external/OpenGR/demos/ExtPointBinding/ext/point_extlib1.hpp b/src/external/OpenGR/demos/ExtPointBinding/ext/point_extlib1.hpp
deleted file mode 100644
index 135785d81..000000000
--- a/src/external/OpenGR/demos/ExtPointBinding/ext/point_extlib1.hpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __POINT_EXTLIB1_H__
-#define __POINT_EXTLIB1_H__
-
-//! [extlib1::PointType1]
-namespace extlib1
-{
-  struct PointType1 {
-    float pos[3];   // position
-    float n[3];     // normal
-    float color[3]; // color
-  };
-}
-//! [extlib1::PointType1]
-
-#endif
\ No newline at end of file
diff --git a/src/external/OpenGR/demos/ExtPointBinding/ext/point_extlib2.hpp b/src/external/OpenGR/demos/ExtPointBinding/ext/point_extlib2.hpp
deleted file mode 100644
index 8bac472ab..000000000
--- a/src/external/OpenGR/demos/ExtPointBinding/ext/point_extlib2.hpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __POINT_EXTLIB2_H__
-#define __POINT_EXTLIB2_H__
-
-//! [extlib2::PointType2]
-namespace extlib2
-{
-  struct PointType2 {
-    float* posBuffer;   // position buffer
-    float* nBuffer;     // normal buffer
-    float* colorBuffer; // color buffer
-    int id;             // id (or index)
-  };
-}
-//! [extlib2::PointType2]
-
-#endif
\ No newline at end of file
diff --git a/src/external/OpenGR/demos/ExtPointBinding/ext/pointadapter_extlib1.hpp b/src/external/OpenGR/demos/ExtPointBinding/ext/pointadapter_extlib1.hpp
deleted file mode 100644
index 0e5cee5be..000000000
--- a/src/external/OpenGR/demos/ExtPointBinding/ext/pointadapter_extlib1.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef __POINT_ADAPTER_EXTLIB1_H__
-#define __POINT_ADAPTER_EXTLIB1_H__
-
-#include 
-#include 
-#include "point_extlib1.hpp"
-
-//! [extlib1::PointAdapter]
-namespace extlib1
-{
-
-struct PointAdapter {
-  public:
-    enum {Dim = 3};
-    typedef float Scalar;
-    typedef Eigen::Matrix VectorType;
-  
-  private:
-    Eigen::Map m_pos, m_normal, m_color;
-    
-  public:
-    inline PointAdapter(const extlib1::PointType1& p)
-      : m_pos   (Eigen::Map( p.pos )), 
-        m_normal(Eigen::Map( p.n )), 
-        m_color (Eigen::Map( p.color ))
-    { }
-
-
-    inline const Eigen::Map< const VectorType >& pos()    const { return m_pos; }  
-    inline const Eigen::Map< const VectorType >& normal() const { return m_normal; }
-    inline const Eigen::Map< const VectorType >& color()  const { return m_color; }
-    inline const Eigen::Map< const VectorType >& rgb()    const { return m_color; }
-    
-};
-
-}
-//! [extlib1::PointAdapter]
-
-#endif
diff --git a/src/external/OpenGR/demos/ExtPointBinding/ext/pointadapter_extlib2.hpp b/src/external/OpenGR/demos/ExtPointBinding/ext/pointadapter_extlib2.hpp
deleted file mode 100644
index 3e2202e64..000000000
--- a/src/external/OpenGR/demos/ExtPointBinding/ext/pointadapter_extlib2.hpp
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef __POINT_ADAPTER_EXTLIB2_H__
-#define __POINT_ADAPTER_EXTLIB2_H__
-
-
-#include 
-#include "point_extlib2.hpp"
-
-//! [extlib2::PointAdapter]
-namespace extlib2
-{
-
-struct PointAdapter {
-  public:
-    enum {Dim = 3};
-    typedef float Scalar;
-    typedef Eigen::Matrix VectorType;
-  
-  private:
-    Eigen::Map< const VectorType > m_pos, m_normal, m_color;
-  
-  public:
-    inline PointAdapter(const extlib2::PointType2& p)
-      : m_pos   (Eigen::Map< const VectorType >( p.posBuffer + Dim*p.id )), 
-        m_normal(Eigen::Map< const VectorType >( p.nBuffer + Dim*p.id )), 
-        m_color (Eigen::Map< const VectorType >( p.colorBuffer + Dim*p.id ))
-    { }
-
-    inline const Eigen::Map< const VectorType >& pos()    const { return m_pos; }  
-    inline const Eigen::Map< const VectorType >& normal() const { return m_normal; }
-    inline const Eigen::Map< const VectorType >& color()  const { return m_color; }
-    inline const Eigen::Map< const VectorType >& rgb()  const { return m_color; }
-
-};
-
-}
-//! [extlib2::PointAdapter]
-#endif
\ No newline at end of file
diff --git a/src/external/OpenGR/demos/ExtPointBinding/external_point_binding_test.cc b/src/external/OpenGR/demos/ExtPointBinding/external_point_binding_test.cc
deleted file mode 100644
index 982c8fd09..000000000
--- a/src/external/OpenGR/demos/ExtPointBinding/external_point_binding_test.cc
+++ /dev/null
@@ -1,419 +0,0 @@
-#include "gr/io/io.h"
-#include "gr/utils/geometry.h"
-#include "gr/sampling.h"
-#include "gr/algorithms/match4pcsBase.h"
-#include "gr/algorithms/Functor4pcs.h"
-#include "gr/algorithms/FunctorSuper4pcs.h"
-#include "gr/algorithms/FunctorBrute4pcs.h"
-#include 
-
-#include 
-
-#include 
-#include 
-#include 
-
-#include "../demo-utils.h"
-
-#include "ext/point_conversion.h"
-#include "ext/point_extlib1.hpp"
-#include "ext/point_extlib2.hpp"
-#include "ext/pointadapter_extlib1.hpp"
-#include "ext/pointadapter_extlib2.hpp"
-
-#define sqr(x) ((x) * (x))
-
-using namespace std;
-using namespace gr;
-using namespace gr::Demo;
-
-// data IO
-IOManager ioManager;
-
-static inline void printExtPBindingParameterList(){ // TODO: Change name
-    fprintf(stderr, "\t[ -p point_type (%d)]\n", point_type);
-    fprintf(stderr, "\t[ -r result_file_name (%s) ]\n", output.c_str());
-    fprintf(stderr, "\t[ -m output matrix file (%s) ]\n", outputMat.c_str());
-    fprintf(stderr, "\t[ --sampled1 (output sampled cloud 1 -- debug only) ]\n");
-    fprintf(stderr, "\t[ --sampled2 (output sampled cloud 2 -- debug only) ]\n");
-}
-struct TransformVisitor {
-    template 
-    inline void operator()(
-            float fraction,
-            float best_LCP,
-            const Eigen::MatrixBase& /*transformation*/) const {
-      if (fraction >= 0)
-        {
-          printf("done: %d%c best: %f                  \r",
-               static_cast(fraction * 100), '%', best_LCP);
-          fflush(stdout);
-        }
-    }
-    constexpr bool needsGlobalTransformation() const { return false; }
-};
-
-/**
-  * If desired (by setting outputSampled1 and outputSampled2), the clouds could be
-  * exported. The function takes the matcher as parameter, and exports the sampled
-  * clouds of the matcher.
-  */ 
-template
-void exportSampledClouds(const Matcher& matcher, const Utils::Logger& logger)
-{
-  if(! outputSampled1.empty() ){
-    logger.Log( "Exporting Sampled cloud 1 to ",
-                                outputSampled1.c_str(),
-                                " ..." );
-    ioManager.WriteObject((char *)outputSampled1.c_str(),
-                           matcher.getFirstSampled(),
-                           vector(),
-                           vector::VectorType>(), // dummy
-                           vector(),
-                           vector());
-    logger.Log( "Export DONE" );
-  }
-  if(! outputSampled2.empty() ){
-    logger.Log( "Exporting Sampled cloud 2 to ",
-                                outputSampled2.c_str(),
-                                " ..." );
-    ioManager.WriteObject((char *)outputSampled2.c_str(),
-                           matcher.getSecondSampled(),
-                           vector(),
-                           vector::VectorType>(), // dummy
-                           vector(),
-                           vector());
-    logger.Log( "Export DONE" );
-  }
-}
-
-template <
-    typename Matcher,
-    typename PointType,
-    typename Options,
-    typename Range,
-    template typename Sampler,
-    typename TransformVisitor>
-typename PointType::Scalar computeAlignment (
-    const Options& options,
-    const Utils::Logger& logger,
-    const Range& P,
-    const Range& Q,
-    Eigen::Ref> mat,
-    const Sampler& sampler,
-    TransformVisitor& visitor
-    ) {
-  Matcher matcher (options, logger);
-  logger.Log( "Starting registration" );
-  typename PointType::Scalar score = matcher.ComputeTransformation(P, Q, mat, sampler, visitor);
-
-
-  logger.Log( "Score: ", score );
-  logger.Log( "(Homogeneous) Transformation from ",
-                              input2.c_str(),
-                              " to ",
-                              input1.c_str(),
-                              ": \n",
-                              mat);
-
-  if(! outputSampled1.empty() ){
-      logger.Log( "Exporting Sampled cloud 1 to ",
-                                  outputSampled1.c_str(),
-                                  " ..." );
-      ioManager.WriteObject((char *)outputSampled1.c_str(),
-                             matcher.getFirstSampled(),
-                             vector(),
-                             vector::VectorType>(), // dummy
-                             vector(),
-                             vector());
-      logger.Log( "Export DONE" );
-  }
-  if(! outputSampled2.empty() ){
-      logger.Log( "Exporting Sampled cloud 2 to ",
-                                  outputSampled2.c_str(),
-                                  " ..." );
-      ioManager.WriteObject((char *)outputSampled2.c_str(),
-                             matcher.getSecondSampled(),
-                             vector(),
-                             vector::VectorType>(), // dummy
-                             vector(),
-                             vector());
-      logger.Log( "Export DONE" );
-  }
-
-  return score;
-}
-
-int main(int argc, char **argv) {
-  using namespace gr;
-  using Scalar = float;
-
-  /**
-   * Point clouds are read as gr::Point3D, then converted to other types to emulate
-   * PointAdapter usage. This way, we can make use of IOManager to read point cloud
-   * files, and lightweight point converter functions to convert gr points to example
-   * external point type
-   */
-  vector > set1, set2;
-  vector tex_coords1, tex_coords2;
-  vector::VectorType> normals1, normals2;
-  vector tris1, tris2;
-  vector mtls1, mtls2;
-
-  // Match and return the score (estimated overlap or the LCP).
-  typename Point3D::Scalar score = 0;
-
-  constexpr Utils::LogLevel loglvl = Utils::Verbose;
-
-  using TrVisitorType = typename std::conditional ::type;
-  using PairFilter = gr::AdaptivePointFilter;
-
-  TrVisitorType visitor;
-  Utils::Logger logger(loglvl);
-
-  /// TODO Add proper error codes
-  if(argc < 4){
-    Demo::printUsage(argc, argv);
-    printExtPBindingParameterList();
-    exit(-2);
-  }
-  if(int c = Demo::getArgs(argc, argv) != 0)
-  {
-    Demo::printUsage(argc, argv);
-    printExtPBindingParameterList();
-    exit(std::max(c,0));
-  }
-
-  using MatrixType = Eigen::Matrix;
-  MatrixType mat (MatrixType::Identity());
-
-  // Read the inputs.
-  if (!ioManager.ReadObject((char *)input1.c_str(), set1, tex_coords1, normals1, tris1,
-                  mtls1)) {
-    logger.Log("Can't read input set1");
-    exit(-1);
-  }
-
-  if (!ioManager.ReadObject((char *)input2.c_str(), set2, tex_coords2, normals2, tris2,
-                  mtls2)) {
-    logger.Log("Can't read input set2");
-    exit(-1);
-  }
-
-  // clean only when we have pset to avoid wrong face to point indexation
-  if (tris1.size() == 0)
-    Utils::CleanInvalidNormals(set1, normals1);
-  if (tris2.size() == 0)
-    Utils::CleanInvalidNormals(set2, normals2);
-
-  try {
-    if(point_type == 0) // gr::Point3D, directly pass the read sets
-    {
-      logger.Log("Registration on std::vector of gr::Point3D"
-                                 " instances - a point adapter is not required."    );
-
-      using PointType    = gr::Point3D;
-      /**
-       * Here, PointAdapter does not really serve as an adapter since the point type
-       * that we have as the type of the instances of points already comply with
-       * the PointConcept. Therefore, we just pass the point type as the adapter type. 
-       * */
-      using PointAdapter = gr::Point3D;
-      using MatcherType  = gr::Match4pcsBase;
-      using OptionType   = typename MatcherType::OptionsType;
-
-      UniformDistSampler sampler;
-
-      OptionType options;
-      if(! Demo::setOptionsFromArgs(options, logger))
-        exit(-2); /// \FIXME use status codes for error reporting
-
-      // Create a matcher instance
-      MatcherType matcher (options, logger);
-
-      logger.Log( "Starting registration" );
-
-      // Compute transformation: put transformation to mat, return registration score
-      Scalar score = matcher.ComputeTransformation(set1, set2, mat, sampler, visitor);
-
-      logger.Log( "Score: ", score );
-      logger.Log( "(Homogeneous) Transformation from ",
-                              input2.c_str(),
-                              " to ",
-                              input1.c_str(),
-                              ": \n",
-                              mat);
-
-      // Export sampled point clouds - if paths were set
-      exportSampledClouds(matcher, logger);
-    }
-    else if(point_type == 1) /* extlib1::PointType1, convert read sets to vector
-                              * of PointType1 to emulate PointAdapter usage */
-    {
-      logger.Log("Registration on std::vector of extlib1::PointType1"
-                                 "instances using extlib1::PointAdapter"             );
-
-      /**
-       * Convert the vectors of gr::Point3D instances to some containers of 
-       * extlib1::PointType1 instances, so that, we can assume that we have some
-       * containers of extlib1::PointType1 instances in hand to use as input to
-       * gr registration methods.
-       */
-//! [Creating a vector of extlib1::PointType1]
-      std::vector set1_point1 = getExtlib1Points(set1);
-      std::vector set2_point1 = getExtlib1Points(set2);
-//! [Creating a vector of extlib1::PointType1]
-      using PointType    = extlib1::PointType1;
-      /**
-       * Here, extlib1::PointType1 is not a model of gr::PointConcept. Hence, an adapter
-       * type is needed to have registration on this external point type. extlib1::PointAdapter
-       * serves as the adapter. Therefore, whenever gr requires a point type to be passed,
-       * the adapter type will be passed, which it will use to wrap the extlib1::PointType1
-       * instances on-the-fly to reach the information.
-       */
-//! [Point adapter and matcher type]
-      using PointAdapter = extlib1::PointAdapter;
-      using MatcherType = gr::Match4pcsBase;
-//! [Point adapter and matcher type]
-      using OptionType  = typename MatcherType::OptionsType;
-//! [Sampler type]
-      UniformDistSampler sampler;
-//! [Sampler type]
-      OptionType options;
-      if(! Demo::setOptionsFromArgs(options, logger))
-        exit(-2); /// \FIXME use status codes for error reporting
-
-      logger.Log( "Starting registration" );
-//! [Matcher instantiation and computation]
-      // Create a matcher instance
-      MatcherType matcher (options, logger);
-      // Compute transformation: put transformation to mat, return registration score
-      Scalar score = matcher.ComputeTransformation(set1_point1, set2_point1, mat, sampler, visitor);
-//! [Matcher instantiation and computation]
-      logger.Log( "Score: ", score );
-      logger.Log( "(Homogeneous) Transformation from ",
-                              input2.c_str(),
-                              " to ",
-                              input1.c_str(),
-                              ": \n",
-                              mat);
-
-      // Export sampled point clouds - if paths were set
-      exportSampledClouds(matcher, logger);
-    }
-    else if(point_type == 2) /* extlib2::PointType2, convert read sets to lists 
-                              * of PointType2 to emulate PointAdapter usage */
-    {
-      logger.Log("Registration on std::list of extlib2::PointType2"
-                                 " instances using extlib2::PointAdapter");
-
-      /**
-       * Convert the vectors of gr::Point3D instances to some containers of 
-       * extlib2::PointType2 instances, so that, we can assume that we have some
-       * containers of extlib2::PointType2 instances in hand to use as input to
-       * gr registration methods.
-       */
-      std::list set1_point2 = getExtlib2Points(set1);
-      std::list set2_point2 = getExtlib2Points(set2);
-
-      using PointType    = extlib2::PointType2;
-      /**
-       * Here, extlib2::PointType2 is not a model of gr::PointConcept. Hence, an adapter
-       * type is needed to have registration on this external point type. extlib2::PointAdapter
-       * serves as the adapter. Therefore, whenever gr requires a point type to be passed,
-       * the adapter type will be passed, which it will use to wrap the extlib2::PointType2
-       * instances on-the-fly to reach the information.
-       */
-      using PointAdapter = extlib2::PointAdapter;
-      using MatcherType = gr::Match4pcsBase;
-      using OptionType  = typename MatcherType::OptionsType;
-
-      UniformDistSampler sampler;
-
-      OptionType options;
-      if(! Demo::setOptionsFromArgs(options, logger))
-        exit(-2); /// \FIXME use status codes for error reporting
-
-      // Create a matcher instance
-      MatcherType matcher (options, logger);
-
-      logger.Log( "Starting registration" );
-
-      // Compute transformation: put transformation to mat, return registration score
-      Scalar score = matcher.ComputeTransformation(set1_point2, set2_point2, mat, sampler, visitor);
-
-      logger.Log( "Score: ", score );
-      logger.Log( "(Homogeneous) Transformation from ",
-                              input2.c_str(),
-                              " to ",
-                              input1.c_str(),
-                              ": \n",
-                              mat);
-        
-      // Export sampled point clouds - if paths were set
-      exportSampledClouds(matcher, logger);
-
-      // deallocate memory for points2: needed due to internals of extlib2::PointType2
-      if(!set1_point2.empty()) {
-        delete[] set1_point2.front().posBuffer;
-        delete[] set1_point2.front().nBuffer;
-        delete[] set1_point2.front().colorBuffer;
-        set1_point2.clear();
-      }
-
-      if(!set2_point2.empty()) {
-        delete[] set2_point2.front().posBuffer;
-        delete[] set2_point2.front().nBuffer;
-        delete[] set2_point2.front().colorBuffer;
-        set2_point2.clear();
-      }
-    }
-    else
-    {
-      std::cerr << "Invalid point type" << std::endl;
-      exit(-1);
-    }
-  }
-  catch (const std::exception& e) {
-      logger.Log( "[Error]: " , e.what() );
-      logger.Log( "Aborting with code -3 ..." );
-      return -3;
-  }
-  catch (...) {
-      logger.Log( "[Unknown Error]: Aborting with code -4 ..." );
-      return -4;
-  }
-
-  if(! outputMat.empty() ){
-      logger.Log( "Exporting Matrix to ",
-                                  outputMat.c_str(),
-                                  "..." );
-      ioManager.WriteMatrix(outputMat, mat.cast(), IOManager::POLYWORKS);
-      logger.Log( "Export DONE" );
-  }
-
-  if (! output.empty() ){
-
-      logger.Log( "Exporting Registered geometry to ",
-                                  output.c_str(),
-                                  "..." );
-      Utils::TransformPointCloud(set2, mat);
-      ioManager.WriteObject((char *)output.c_str(),
-                             set2,
-                             tex_coords2,
-                             normals2,
-                             tris2,
-                             mtls2);
-      logger.Log( "Export DONE" );
-  }
-
-  return 0;
-}
diff --git a/src/external/OpenGR/demos/MeshlabPlugin/CMakeLists.txt b/src/external/OpenGR/demos/MeshlabPlugin/CMakeLists.txt
deleted file mode 100644
index 33651efde..000000000
--- a/src/external/OpenGR/demos/MeshlabPlugin/CMakeLists.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-project(Meshlab-GlobalRegistrationPlugin)
-
-find_package(Meshlab QUIET)
-
-if(MESHLAB_FOUND)
-    message(STATUS "[Demos] Meshlab found, creating target Meshlab-GlobalRegistrationPlugin")
-
-    set(PLUGIN_NAME "filter_globalregistration")
-    set(PLUGIN_SRC_DIR              "${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN_NAME}")
-    set(PLUGIN_PRO_INC              "${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN_NAME}.pro.in")
-    set(PLUGIN_RDM_INC              "${CMAKE_CURRENT_SOURCE_DIR}/readme.md.in")
-    set(PLUGIN_INSTALL_DIR          "${MESHLAB_PLUGINS_SOURCE_DIR}/${PLUGIN_NAME}")
-    set(PLUGIN_RELATIVE_INSTALL_DIR "${MESHLAB_RELATIVE_PLUGINS_SOURCE_DIR}/${PLUGIN_NAME}")
-    set(PLUGIN_PRO_GEN              "${PLUGIN_INSTALL_DIR}/${PLUGIN_NAME}.pro")
-    set(PLUGIN_RDM_GEN              "${PLUGIN_INSTALL_DIR}/readme.md")
-
-    configure_file(${PLUGIN_PRO_INC} ${PLUGIN_PRO_GEN} @ONLY)
-    configure_file(${PLUGIN_RDM_INC} ${PLUGIN_RDM_GEN} @ONLY)
-
-    add_custom_target(internal_install_opengr_to_meshlab_externals
-       COMMAND ${CMAKE_COMMAND} -E copy_directory "${OpenGR_INSTALL_DIR}/include/" "${MESHLAB_EXTERNAL_INCLUDE_DIR}"
-       COMMAND ${CMAKE_COMMAND} -E copy_directory "${OpenGR_INSTALL_DIR}/lib/"     "${MESHLAB_EXTERNAL_LIBRARIES_DIR}"
-       COMMENT "Install OpenGR library to Meshlab externals (${MESHLAB_EXTERNAL_INCLUDE_DIR})" VERBATIM
-       DEPENDS ForceOpenGRInstallation)
-
-    add_custom_target(internal_install_meshlab_plugin_source
-       COMMAND ${CMAKE_COMMAND} -E copy_directory "${PLUGIN_SRC_DIR}" "${PLUGIN_INSTALL_DIR}"
-       COMMENT "Install plugin sources at ${PLUGIN_INSTALL_DIR}" VERBATIM
-       )
-
-    # Main target visible in the project
-    add_custom_target(Meshlab_install_plugin
-       COMMENT "Performing Meshlab plugin installation (manual compilation is still required. See ${PLUGIN_INSTALL_DIR}/readme.md)"
-       DEPENDS internal_install_opengr_to_meshlab_externals internal_install_meshlab_plugin_source)
-endif(MESHLAB_FOUND)
-
-
diff --git a/src/external/OpenGR/demos/MeshlabPlugin/filter_globalregistration.pro.in b/src/external/OpenGR/demos/MeshlabPlugin/filter_globalregistration.pro.in
deleted file mode 100644
index 09bf98095..000000000
--- a/src/external/OpenGR/demos/MeshlabPlugin/filter_globalregistration.pro.in
+++ /dev/null
@@ -1,10 +0,0 @@
-include (../../shared.pri)
-
-HEADERS       += globalregistration.h
-SOURCES       += globalregistration.cpp
-TARGET         = filter_globalregistration
-
-CONFIG += create_prl
-CONFIG += link_prl
-
-INCLUDEPATH += @MESHLAB_EXTERNAL_INCLUDE_DIR@
diff --git a/src/external/OpenGR/demos/MeshlabPlugin/filter_globalregistration/globalregistration.cpp b/src/external/OpenGR/demos/MeshlabPlugin/filter_globalregistration/globalregistration.cpp
deleted file mode 100644
index 2771f5679..000000000
--- a/src/external/OpenGR/demos/MeshlabPlugin/filter_globalregistration/globalregistration.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/****************************************************************************
-* MeshLab                                                           o o     *
-* A versatile mesh processing toolbox                             o     o   *
-*                                                                _   O  _   *
-* Copyright(C) 2005                                                \/)\/    *
-* Visual Computing Lab                                            /\/|      *
-* ISTI - Italian National Research Council                           |      *
-*                                                                    \      *
-* All rights reserved.                                                      *
-*                                                                           *
-* This program is free software; you can redistribute it and/or modify      *
-* it under the terms of the GNU General Public License as published by      *
-* the Free Software Foundation; either version 2 of the License, or         *
-* (at your option) any later version.                                       *
-*                                                                           *
-* This program is distributed in the hope that it will be useful,           *
-* but WITHOUT ANY WARRANTY; without even the implied warranty of            *
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
-* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
-* for more details.                                                         *
-*                                                                           *
-****************************************************************************/
-
-#include "globalregistration.h"
-#include "gr/algorithms/match4pcsBase.h"
-#include "gr/algorithms/Functor4pcs.h"
-#include "gr/algorithms/FunctorSuper4pcs.h"
-#include "gr/algorithms/PointPairFilter.h"
-#include 
-
-// Constructor usually performs only two simple tasks of filling the two lists
-//  - typeList: with all the possible id of the filtering actions
-//  - actionList with the corresponding actions. If you want to add icons to your filtering actions you can do here by construction the QActions accordingly
-
-GlobalRegistrationPlugin::GlobalRegistrationPlugin()
-{
-    typeList << FP_GLOBAL_REGISTRATION;
-
-  foreach(FilterIDType tt , types())
-      actionList << new QAction(filterName(tt), this);
-}
-
-// ST() must return the very short string describing each filtering action
-// (this string is used also to define the menu entry)
-QString GlobalRegistrationPlugin::filterName(FilterIDType filterId) const
-{
-  switch(filterId) {
-        case FP_GLOBAL_REGISTRATION :  return QString("Global registration");
-        default : assert(0);
-    }
-  return QString();
-}
-
-// Info() must return the longer string describing each filtering action
-// (this string is used in the About plugin dialog)
- QString GlobalRegistrationPlugin::filterInfo(FilterIDType filterId) const
-{
-  switch(filterId) {
-        case FP_GLOBAL_REGISTRATION :  return QString("Compute the rigid transforation aligning two 3d objets.");
-        default : assert(0);
-    }
-    return QString("Unknown Filter");
-}
-
-// The FilterClass describes in which generic class of filters it fits.
-// This choice affect the submenu in which each filter will be placed
-// More than a single class can be choosen.
-GlobalRegistrationPlugin::FilterClass GlobalRegistrationPlugin::getClass(QAction *a)
-{
-  switch(ID(a))
-    {
-        case FP_GLOBAL_REGISTRATION :  return MeshFilterInterface::PointSet;
-        default : assert(0);
-    }
-    return MeshFilterInterface::Generic;
-}
-
-// This function define the needed parameters for each filter. Return true if the filter has some parameters
-// it is called every time, so you can set the default value of parameters according to the mesh
-// For each parameter you need to define,
-// - the name of the parameter,
-// - the string shown in the dialog
-// - the default value
-// - a possibly long string describing the meaning of that parameter (shown as a popup help in the dialog)
-void GlobalRegistrationPlugin::initParameterSet(QAction *action,MeshDocument &md, RichParameterSet & parlst)
-{
-
-     switch(ID(action))	 {
-        case FP_GLOBAL_REGISTRATION :
-
-         parlst.addParam(new RichMesh ("refMesh",md.mm(),&md, "Reference Mesh",	"Reference point-cloud or mesh"));
-         parlst.addParam(new RichMesh ("targetMesh",md.mm(),&md, "Target Mesh",	"Point-cloud or mesh to be aligned to the reference"));
-         parlst.addParam(new RichAbsPerc("overlap", 50, 0, 100, "Overlap Ratio", "Overlap ratio between the two clouds (command line option: -o)"));
-         parlst.addParam(new RichFloat("delta",   0.1, "Registration tolerance", "Tolerance value for the congruent set exploration and LCP computation (command line option: -d)"));
-         parlst.addParam(new RichInt("nbSamples", 200, "Number of samples", "Number of samples used in each mesh (command line option: -n)"));
-         parlst.addParam(new RichFloat("norm_diff", -1, "Filter: difference of normal (degrees)", "Allowed difference of normals allowed between corresponding pairs of points(command line option: -a)"));
-         parlst.addParam(new RichFloat("color_diff", -1, "Filter: difference color", "Allowed difference of colors allowed between corresponding pairs of points(command line option: -c)"));
-         parlst.addParam(new RichInt("max_time_seconds", 10000, "Max. Computation time, in seconds", "Stop the computation before the end of the exploration (command line option: -t)"));
-         parlst.addParam(new RichBool("useSuper4PCS", true, "Use Super4PCS", "When disable, use 4PCS algorithm (command line option: -x"));
-
-         break;
-     default : assert(0);
-    }
-}
-
-
-using MatrixType = Eigen::Matrix;
-
-struct RealTimeTransformVisitor {
-    CMeshO* mesh = nullptr;
-    GlobalRegistrationPlugin* plugin;
-    inline void operator() (
-            float /*fraction*/,
-            float best_LCP,
-            Eigen::Ref mat) {
-        plugin->Log("Found new configuration. LCP = %f", best_LCP);
-
-        mesh->Tr.FromEigenMatrix(mat);
-    }
-    constexpr bool needsGlobalTransformation() { return true; }
-};
-
-struct TransformVisitor {
-    CMeshO* mesh = nullptr;
-    GlobalRegistrationPlugin* plugin;
-    inline void operator() (
-            float /*fraction*/,
-            float best_LCP,
-            Eigen::Ref /*mat*/) const {
-        plugin->Log("Found new configuration. LCP = %f", best_LCP);
-    }
-    constexpr bool needsGlobalTransformation() { return false; }
-};
-
-// init Super4PCS point cloud internal structure
-auto fillPointSet = [] (const CMeshO& m, std::vector& out) {
-    using gr::Point3D;
-    Point3D p;
-    out.clear();
-    out.reserve(m.vert.size());
-
-    // TODO: copy other point-wise information, if any
-    for(size_t i = 0; i< m.vert.size(); i++){
-        const auto& vertex = m.vert[i];
-        vertex.P().ToEigenVector(p.pos());
-        out.push_back(p);
-    }
-};
-
-template 
-float align ( CMeshO* refMesh, CMeshO* trgMesh,
-              RichParameterSet & par,
-              MatrixType & mat,
-              typename MatcherType::TransformVisitor & v) {
-
-    using SamplerType   = gr::UniformDistSampler;
-    using OptionType    = typename MatcherType::OptionsType;
-
-    OptionType opt;
-    opt.configureOverlap(par.getAbsPerc("overlap")/100.f);
-    opt.delta                 = par.getFloat("delta");
-    opt.sample_size           = par.getInt("nbSamples");
-    opt.max_normal_difference = par.getFloat("norm_diff");
-    opt.max_color_distance    = par.getFloat("color_diff");
-    opt.max_time_seconds      = par.getInt("max_time_seconds");
-
-    std::vector set1, set2;
-    fillPointSet(*refMesh, set1);
-    fillPointSet(*trgMesh, set2);
-
-    gr::Utils::Logger logger (gr::Utils::LogLevel::NoLog);
-    SamplerType sampler;
-    MatcherType matcher (opt, logger);
-
-    return matcher.ComputeTransformation(set1, set2, mat, sampler, v);
-}
-
-// The Real Core Function doing the actual mesh processing.
-// Move Vertex of a random quantity
-bool GlobalRegistrationPlugin::applyFilter(QAction */*filter*/,
-                                           MeshDocument &/*md*/,
-                                           const RichParameterSet & par,
-                                           vcg::CallBackPos */*cb*/)
-{
-
-    MeshModel *mmref = par.getMesh("refMesh");
-    MeshModel *mmtrg = par.getMesh("targetMesh");
-    CMeshO *refMesh=&mmref->cm;
-    CMeshO *trgMesh=&mmtrg->cm;
-
-    bool useSuper4PCS         = par.getBool("useSuper4PCS");
-
-    MatrixType mat;
-    float score = -1;
-
-    TransformVisitor v;
-    v.mesh = trgMesh;
-    v.plugin = this;
-
-    if (useSuper4PCS) {
-        using MatcherType = gr::Match4pcsBase;
-        score = align< MatcherType >(refMesh, trgMesh, par, mat, v);
-    } else {
-        using MatcherType = gr::Match4pcsBase;
-        score = align< MatcherType >(refMesh, trgMesh, par, mat, v);
-    }
-
-    // run
-    Log("Final LCP = %f", score);
-    v.mesh->Tr.FromEigenMatrix(mat);
-
-    return true;
-}
-
-MESHLAB_PLUGIN_NAME_EXPORTER(GlobalRegistrationPlugin)
diff --git a/src/external/OpenGR/demos/MeshlabPlugin/readme.md.in b/src/external/OpenGR/demos/MeshlabPlugin/readme.md.in
deleted file mode 100644
index 123f09a2c..000000000
--- a/src/external/OpenGR/demos/MeshlabPlugin/readme.md.in
+++ /dev/null
@@ -1,18 +0,0 @@
-## OpenGR Meshlab plugin
-
-Sources of this plugin has been automatically generated by the OpenGR installer:
-* Sources: `@SRC_DIR@`
-* Installation path: `@OpenGR_INSTALL_DIR@`
-
-To get this plugin working in Meshlab, you need to add it to the main Meshlab project, and compile Meshlab.
-On linux/macOS, this can be done from the command line:
-```bash
-cd @MESHLAB_SRC_DIR@
-echo "@PLUGIN_RELATIVE_INSTALL_DIR@ \\" >> @MESHLAB_PROJECT_FILE@
-qmake @MESHLAB_PROJECT_FILE@
-make
-```
-
-OpenGR libraries and include files have been installed to:
-* `@MESHLAB_EXTERNAL_LIBRARIES_DIR@`, and
-* `@MESHLAB_EXTERNAL_INCLUDE_DIR@`
diff --git a/src/external/OpenGR/demos/PCLWrapper/CMakeLists.txt b/src/external/OpenGR/demos/PCLWrapper/CMakeLists.txt
deleted file mode 100644
index 0437e4278..000000000
--- a/src/external/OpenGR/demos/PCLWrapper/CMakeLists.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-project(OpenGR-PCLWrapper)
-
-file(GLOB_RECURSE Demo_PCL_headers
-                  ${CMAKE_CURRENT_SOURCE_DIR}/*.h
-                  ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp)
-
-find_package( PCL 1.8 QUIET COMPONENTS common io search visualization)
-
-if( PCL_FOUND )
-  message (STATUS "[Demos] PCL found, creating target OpenGR-PCLWrapper")
-  set(Demo_PCL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp )
-
-  include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )
-  add_executable(${PROJECT_NAME} ${Demo_PCL_SRC} ${Demo_PCL_headers})
-  target_link_libraries(${PROJECT_NAME} opengr_algo opengr_utils ${PCL_LIBRARIES})
-
-  # [C/C++]>[General]>[Additional Include Directories]
-  include_directories( ${PCL_INCLUDE_DIRS} )
-
-  # [C/C++]>[Preprocessor]>[Preprocessor Definitions]
-  add_definitions( ${PCL_DEFINITIONS} )
-
-  # For Use Not PreCompiled Features
-  #add_definitions( -DPCL_NO_PRECOMPILE )
-
-  # [Linker]>[General]>[Additional Library Directories]
-  link_directories( ${PCL_LIBRARY_DIRS} )
-
-  install( TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
-
-endif()
-
-
-install( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
-         DESTINATION include
-         FILES_MATCHING REGEX ".*(h|hpp)$")
diff --git a/src/external/OpenGR/demos/PCLWrapper/main.cpp b/src/external/OpenGR/demos/PCLWrapper/main.cpp
deleted file mode 100644
index 906ebc95b..000000000
--- a/src/external/OpenGR/demos/PCLWrapper/main.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-
-#include 
-#include "../demo-utils.h"
-
-// Types
-typedef pcl::PointNormal PointNT;
-typedef pcl::PointCloud PointCloudT;
-typedef pcl::visualization::PointCloudColorHandlerCustom ColorHandlerT;
-
-using namespace gr;
-
-// Align a rigid object to a scene with clutter and occlusions
-int
-main (int argc, char **argv)
-{
-  // Point clouds
-  PointCloudT::Ptr object (new PointCloudT);
-  PointCloudT::Ptr object_aligned (new PointCloudT);
-  PointCloudT::Ptr scene (new PointCloudT);
-
-  // Get input object and scene
-  if (argc < 3)
-  {
-    pcl::console::print_error ("Syntax is: %s scene.obj object.obj [PARAMS]\n", argv[0]);
-    Demo::printParameterList();
-    return (-1);
-  }
-
-  // Load object and scene
-  pcl::console::print_highlight ("Loading point clouds...\n");
-  if (pcl::io::loadOBJFile (argv[2], *object) < 0 ||
-      pcl::io::loadOBJFile (argv[1], *scene) < 0)
-  {
-    pcl::console::print_error ("Error loading object/scene file!\n");
-    return (-1);
-  }
-
-  if(int c = Demo::getArgs(argc, argv) != 0)
-    {
-      Demo::printUsage(argc, argv);
-      exit(std::max(c,0));
-    }
-
-  pcl::Super4PCS align;
-  Demo::setOptionsFromArgs(align.options_);
-
-  // Downsample
-//  pcl::console::print_highlight ("Downsampling...\n");
-//  pcl::VoxelGrid grid;
-//  const float leaf = 0.005f;r
-//  grid.setLeafSize (leaf, leaf, leaf);
-//  grid.setInputCloud (object);
-//  grid.filter (*object);
-//  grid.setInputCloud (scene);
-//  grid.filter (*scene);
-
-  // Perform alignment
-  pcl::console::print_highlight ("Starting alignment...\n");
-  align.setInputSource (object);
-  align.setInputTarget (scene);
-
-  {
-    pcl::ScopeTime t("Alignment");
-    align.align (*object_aligned);
-  }
-
-  if (align.hasConverged ())
-  {
-    // Print results
-    printf ("\n");
-    Eigen::Matrix4f transformation = align.getFinalTransformation ();
-    pcl::console::print_info ("    | %6.3f %6.3f %6.3f | \n", transformation (0,0), transformation (0,1), transformation (0,2));
-    pcl::console::print_info ("R = | %6.3f %6.3f %6.3f | \n", transformation (1,0), transformation (1,1), transformation (1,2));
-    pcl::console::print_info ("    | %6.3f %6.3f %6.3f | \n", transformation (2,0), transformation (2,1), transformation (2,2));
-    pcl::console::print_info ("\n");
-    pcl::console::print_info ("t = < %0.3f, %0.3f, %0.3f >\n", transformation (0,3), transformation (1,3), transformation (2,3));
-    pcl::console::print_info ("\n");
-
-    // Show alignment
-    pcl::visualization::PCLVisualizer visu("Alignment - Super4PCS");
-    visu.addPointCloud (scene, ColorHandlerT (scene, 0.0, 255.0, 0.0), "scene");
-    visu.addPointCloud (object_aligned, ColorHandlerT (object_aligned, 0.0, 0.0, 255.0), "object_aligned");
-    visu.spin ();
-  }
-  else
-  {
-    pcl::console::print_error ("Alignment failed!\n");
-    return (-1);
-  }
-
-  return (0);
-}
diff --git a/src/external/OpenGR/demos/PCLWrapper/pcl/registration/impl/super4pcs.hpp b/src/external/OpenGR/demos/PCLWrapper/pcl/registration/impl/super4pcs.hpp
deleted file mode 100644
index a37f5e8ce..000000000
--- a/src/external/OpenGR/demos/PCLWrapper/pcl/registration/impl/super4pcs.hpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Software License Agreement (BSD License)
- *
- *  Point Cloud Library (PCL) - www.pointclouds.org
- *  Copyright (c) 2010-2012, Willow Garage, Inc.
- *  Copyright (c) 2012-, Open Perception, Inc.
- *
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   * Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the following
- *     disclaimer in the documentation and/or other materials provided
- *     with the distribution.
- *   * Neither the name of the copyright holder(s) nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- *  POSSIBILITY OF SUCH DAMAGE.
- *
- * $Id$
- *
- */
-
-#ifndef PCL_REGISTRATION_OPENGR_HPP_
-#define PCL_REGISTRATION_OPENGR_HPP_
-
-#include 
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-namespace pcl {
-template  void
-pcl::Super4PCS::computeTransformation (PointCloudSource &output, const Eigen::Matrix4f& guess)
-{
-  using namespace gr;
-
-  // Initialize results
-  final_transformation_ = guess;
-
-  constexpr ::gr::Utils::LogLevel loglvl = ::gr::Utils::Verbose;
-
-  gr::Utils::Logger logger(loglvl);
-  MatcherType matcher(options_, logger);
-
-  SamplerType sampler;
-  TransformVisitor visitor;
-
-  std::vector > set1, set2;
-
-  // init Super4PCS point cloud internal structure
-  auto fillPointSet = [] (const PointCloudSource& m, std::vector >& out) {
-      out.clear();
-      out.reserve(m.size());
-
-      // TODO: copy other point-wise information, if any
-      for(size_t i = 0; i< m.size(); i++){
-          const auto& point = m[i];
-          out.emplace_back(point.x, point.y, point.z);
-      }
-  };
-  fillPointSet(*target_, set1);
-  fillPointSet(*input_, set2);;
-
-  float score = matcher.ComputeTransformation(set1, set2, final_transformation_, sampler, visitor);
-
-  transformPointCloud (*input_, output, final_transformation_);
-
-  pcl::console::print_highlight ("Final score: %f\n", fitness_score_);
-
-  converged_ = true;
-}
-}
-
-#endif
-
diff --git a/src/external/OpenGR/demos/PCLWrapper/pcl/registration/super4pcs.h b/src/external/OpenGR/demos/PCLWrapper/pcl/registration/super4pcs.h
deleted file mode 100644
index 2a8899dab..000000000
--- a/src/external/OpenGR/demos/PCLWrapper/pcl/registration/super4pcs.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Software License Agreement (BSD License)
- *
- *  Point Cloud Library (PCL) - www.pointclouds.org
- *  Copyright (c) 2010-2012, Willow Garage, Inc.
- *  Copyright (c) 2012-, Open Perception, Inc.
- *
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   * Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the following
- *     disclaimer in the documentation and/or other materials provided
- *     with the distribution.
- *   * Neither the name of the copyright holder(s) nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- *  POSSIBILITY OF SUCH DAMAGE.
- *
- * $Id$
- *
- */
-
-#ifndef PCL_REGISTRATION_OPENGR_H_
-#define PCL_REGISTRATION_OPENGR_H_
-
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-namespace pcl
-{
-  /** \brief Pose estimation and alignment class using Super4CS routine.
-   *
-   * This class is a wrapper to use the OpenGR library in PCL.
-   * For more info, see Super4PCS library repository: https://github.com/STORM-IRIT/OpenGR
-   *
-   * If you use this in academic work, please cite:
-   *
-   * ```
-   *    N. Mellado, D. Aiger, N. J. Mitra
-   *    SUPER 4PCS: Fast Global Pointcloud Registration via Smart Indexing.
-   *    Computer Graphics Forum, Proceedings of SGP 2014, 2014.
-   * ```
-   *
-   * and
-   * ```
-   *  @MISC{openGR,
-   *    author = {Nicolas Mellado and others},
-   *    title = {OpenGR: A C++ library for 3D Global Registration},
-   *    howpublished = {https://storm-irit.github.io/OpenGR/},
-   *    year = {2017}
-   *   }
-   * ```
-   *
-   * \author Nicolas Mellado (nmellado0@gmail.com)
-   * \ingroup registration
-   */
-  template 
-  class Super4PCS : public Registration
-  {
-    public:
-      typedef typename Registration::Matrix4 Matrix4;
-
-      using Registration::reg_name_;
-      using Registration::getClassName;
-      using Registration::input_;
-      using Registration::target_;
-      using Registration::transformation_estimation_;
-      using Registration::final_transformation_;
-      using Registration::converged_;
-
-      typedef typename Registration::PointCloudSource PointCloudSource;
-      typedef typename PointCloudSource::Ptr PointCloudSourcePtr;
-      typedef typename PointCloudSource::ConstPtr PointCloudSourceConstPtr;
-
-      typedef typename Registration::PointCloudTarget PointCloudTarget;
-
-      typedef PointIndices::Ptr PointIndicesPtr;
-      typedef PointIndices::ConstPtr PointIndicesConstPtr;
-
-
-      struct TransformVisitor {
-          template 
-          inline void operator()(
-                  float fraction,
-                  float best_LCP,
-                  const Eigen::MatrixBase& /*transformation*/) const {
-            if(fraction >= 0)
-              {
-                printf("done: %d%c best: %f                  \r",
-                       static_cast(fraction * 100), '%', best_LCP);
-                fflush(stdout);
-              }
-          }
-          constexpr bool needsGlobalTransformation() const { return false; }
-      };
-
-      using PointType     = gr::Point3D;
-      using SamplerType   = gr::UniformDistSampler;
-      using MatcherType   = gr::Match4pcsBase;
-      using OptionType    = typename MatcherType::OptionsType;
-
-      OptionType options_;
-
-      /** \brief Constructor */
-      Super4PCS ()
-      {
-        reg_name_ = "Super4PCS";
-        transformation_estimation_.reset (new pcl::registration::TransformationEstimationSVD);
-      }
-
-      /** \brief Destructor */
-      virtual ~Super4PCS ()
-      {
-      }
-
-      /** \brief Get the fitness score of alignment. Range from 0-1, higher is better.
-       */
-      inline float getFitnessScore() const { return fitness_score_; }
-
-    protected:
-
-      float fitness_score_;
-
-      /** \brief Rigid transformation computation method.
-        * \param output the transformed input point cloud dataset using the rigid transformation found
-        * \param guess The computed transformation
-        */
-      void
-      computeTransformation (PointCloudSource &output, const Eigen::Matrix4f& guess);
-
-  };
-}
-
-#endif
-
-#include 
-
diff --git a/src/external/OpenGR/demos/Super4PCS/CMakeLists.txt b/src/external/OpenGR/demos/Super4PCS/CMakeLists.txt
deleted file mode 100644
index 0cf21ed81..000000000
--- a/src/external/OpenGR/demos/Super4PCS/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-project(Super4PCS)
-
-set(Demo_Super4PCS_SRC
-    ${CMAKE_CURRENT_SOURCE_DIR}/super4pcs_test.cc
-)
-
-add_executable(${PROJECT_NAME} ${Demo_Super4PCS_SRC})
-target_link_libraries(${PROJECT_NAME} opengr_utils opengr_io opengr_accel opengr_algo)
-add_dependencies(${PROJECT_NAME} opengr)
-if(OpenGR_USE_CHEALPIX)
-    target_link_libraries(${PROJECT_NAME} chealpix)
-endif(OpenGR_USE_CHEALPIX)
-install( TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin  )
diff --git a/src/external/OpenGR/demos/Super4PCS/super4pcs_test.cc b/src/external/OpenGR/demos/Super4PCS/super4pcs_test.cc
deleted file mode 100644
index 3278a66aa..000000000
--- a/src/external/OpenGR/demos/Super4PCS/super4pcs_test.cc
+++ /dev/null
@@ -1,237 +0,0 @@
-#include "gr/io/io.h"
-#include "gr/utils/geometry.h"
-#include "gr/sampling.h"
-#include "gr/algorithms/match4pcsBase.h"
-#include "gr/algorithms/Functor4pcs.h"
-#include "gr/algorithms/FunctorSuper4pcs.h"
-#include "gr/algorithms/FunctorBrute4pcs.h"
-#include 
-
-#include 
-
-#include 
-#include 
-#include 
-
-#include "../demo-utils.h"
-
-#define sqr(x) ((x) * (x))
-
-using namespace std;
-using namespace gr;
-using namespace gr::Demo;
-
-// data IO
-IOManager ioManager;
-
-static inline void printS4PCSParameterList(){
-    fprintf(stderr, "\t[ -r result_file_name (%s) ]\n", output.c_str());
-    fprintf(stderr, "\t[ -m output matrix file (%s) ]\n", outputMat.c_str());
-    fprintf(stderr, "\t[ -x (use 4pcs: false by default) ]\n");
-    fprintf(stderr, "\t[ --sampled1 (output sampled cloud 1 -- debug+super4pcs only) ]\n");
-    fprintf(stderr, "\t[ --sampled2 (output sampled cloud 2 -- debug+super4pcs only) ]\n");
-}
-struct TransformVisitor {
-    template 
-    inline void operator()(
-            float fraction,
-            float best_LCP,
-            const Eigen::MatrixBase& /*transformation*/) const {
-      if (fraction >= 0)
-        {
-          printf("done: %d%c best: %f                  \r",
-               static_cast(fraction * 100), '%', best_LCP);
-          fflush(stdout);
-        }
-    }
-    constexpr bool needsGlobalTransformation() const { return false; }
-};
-
-template <
-    typename Matcher,
-    typename PointType,
-    typename Options,
-    typename Range,
-    template typename Sampler,
-    typename TransformVisitor>
-typename PointType::Scalar computeAlignment (
-    const Options& options,
-    const Utils::Logger& logger,
-    const Range& P,
-    const Range& Q,
-    Eigen::Ref> mat,
-    const Sampler& sampler,
-    TransformVisitor& visitor
-    ) {
-  Matcher matcher (options, logger);
-  logger.Log( "Starting registration" );
-  typename PointType::Scalar score = matcher.ComputeTransformation(P, Q, mat, sampler, visitor);
-
-
-  logger.Log( "Score: ", score );
-  logger.Log( "(Homogeneous) Transformation from ",
-                              input2.c_str(),
-                              " to ",
-                              input1.c_str(),
-                              ": \n",
-                              mat);
-
-  if(! outputSampled1.empty() ){
-      logger.Log( "Exporting Sampled cloud 1 to ",
-                                  outputSampled1.c_str(),
-                                  " ..." );
-      ioManager.WriteObject((char *)outputSampled1.c_str(),
-                             matcher.getFirstSampled(),
-                             vector(),
-                             vector::VectorType>(), // dummy
-                             vector(),
-                             vector());
-      logger.Log( "Export DONE" );
-  }
-  if(! outputSampled2.empty() ){
-      logger.Log( "Exporting Sampled cloud 2 to ",
-                                  outputSampled2.c_str(),
-                                  " ..." );
-      ioManager.WriteObject((char *)outputSampled2.c_str(),
-                             matcher.getSecondSampled(),
-                             vector(),
-                             vector::VectorType>(), // dummy
-                             vector(),
-                             vector());
-      logger.Log( "Export DONE" );
-  }
-
-  return score;
-}
-
-int main(int argc, char **argv) {
-  using namespace gr;
-  using Scalar = float;
-  // Point clouds are read as gr::Point3D, then converted to other types if necessary to
-  // emulate PointAdapter usage
-  vector > set1, set2;
-  vector tex_coords1, tex_coords2;
-  vector::VectorType> normals1, normals2;
-  vector tris1, tris2;
-  vector mtls1, mtls2;
-
-  // Match and return the score (estimated overlap or the LCP).
-  typename Point3D::Scalar score = 0;
-
-  constexpr Utils::LogLevel loglvl = Utils::Verbose;
-
-  using TrVisitorType = typename std::conditional ::type;
-  using PairFilter = gr::AdaptivePointFilter;
-
-  TrVisitorType visitor;
-  Utils::Logger logger(loglvl);
-
-  /// TODO Add proper error codes
-  if(argc < 4){
-    Demo::printUsage(argc, argv);
-    printS4PCSParameterList();
-    exit(-2);
-  }
-  if(int c = Demo::getArgs(argc, argv) != 0)
-  {
-    Demo::printUsage(argc, argv);
-    printS4PCSParameterList();
-    exit(std::max(c,0));
-  }
-
-  // prepare matcher ressourcesoutputSampled2
-  using MatrixType = Eigen::Matrix::Scalar, 4, 4>;
-  MatrixType mat (MatrixType::Identity());
-
-  // Read the inputs.
-  if (!ioManager.ReadObject((char *)input1.c_str(), set1, tex_coords1, normals1, tris1,
-                  mtls1)) {
-    logger.Log("Can't read input set1");
-    exit(-1);
-  }
-
-  if (!ioManager.ReadObject((char *)input2.c_str(), set2, tex_coords2, normals2, tris2,
-                  mtls2)) {
-    logger.Log("Can't read input set2");
-    exit(-1);
-  }
-
-  // clean only when we have pset to avoid wrong face to point indexation
-  if (tris1.size() == 0)
-    Utils::CleanInvalidNormals(set1, normals1);
-  if (tris2.size() == 0)
-    Utils::CleanInvalidNormals(set2, normals2);
-
-  try {
-    if (use_super4pcs) {
-      using PointType    = gr::Point3D;
-      using MatcherType  = gr::Match4pcsBase;
-      using OptionType   = typename MatcherType::OptionsType;
-
-      UniformDistSampler sampler;
-
-      OptionType options;
-      if(! Demo::setOptionsFromArgs(options, logger))
-        exit(-2); /// \FIXME use status codes for error reporting
-
-      score = computeAlignment (options, logger, set1, set2,
-                                                        mat, sampler, visitor);
-    }
-    else {
-      // 4PCS
-      using PointType    = gr::Point3D;
-      using MatcherType  = gr::Match4pcsBase;
-      using OptionType   = typename MatcherType::OptionsType;
-
-      UniformDistSampler sampler;
-
-      OptionType options;
-      if(! Demo::setOptionsFromArgs(options, logger))
-        exit(-2); /// \FIXME use status codes for error reporting
-
-      score = computeAlignment (options, logger, set1, set2,
-                                                        mat, sampler, visitor);
-    }
-  }
-  catch (const std::exception& e) {
-      logger.Log( "[Error]: " , e.what() );
-      logger.Log( "Aborting with code -3 ..." );
-      return -3;
-  }
-  catch (...) {
-      logger.Log( "[Unknown Error]: Aborting with code -4 ..." );
-      return -4;
-  }
-
-
-  if(! outputMat.empty() ){
-      logger.Log( "Exporting Matrix to ",
-                                  outputMat.c_str(),
-                                  "..." );
-      ioManager.WriteMatrix(outputMat, mat.cast(), IOManager::POLYWORKS);
-      logger.Log( "Export DONE" );
-  }
-
-  if (! output.empty() ){
-
-      logger.Log( "Exporting Registered geometry to ",
-                                  output.c_str(),
-                                  "..." );
-      Utils::TransformPointCloud(set2, mat);
-      ioManager.WriteObject((char *)output.c_str(),
-                             set2,
-                             tex_coords2,
-                             normals2,
-                             tris2,
-                             mtls2);
-      logger.Log( "Export DONE" );
-  }
-
-  return 0;
-}
diff --git a/src/external/OpenGR/demos/demo-utils.h b/src/external/OpenGR/demos/demo-utils.h
deleted file mode 100644
index d574a16ba..000000000
--- a/src/external/OpenGR/demos/demo-utils.h
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2017 Nicolas Mellado
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -------------------------------------------------------------------------- //
-//
-// Authors: Nicolas Mellado
-//
-// This file is part of the implementation of the 4-points Congruent Sets (4PCS)
-// algorithm presented in:
-//
-// Super 4PCS: Fast Global Pointcloud Registration via Smart Indexing
-// Nicolas Mellado, Dror Aiger, Niloy J. Mitra
-// Symposium on Geometry Processing 2014.
-//
-// Given two sets of points in 3-space, P and Q, the algorithm applies RANSAC
-// in roughly O(n^2) time instead of O(n^3) for standard RANSAC, using an
-// efficient method based on invariants, to find the set of all 4-points in Q
-// that can be matched by rigid transformation to a given set of 4-points in P
-// called a base. This avoids the need to examine all sets of 3-points in Q
-// against any base of 3-points in P as in standard RANSAC.
-// The algorithm can use colors and normals to speed-up the matching
-// and to improve the quality. It can be easily extended to affine/similarity
-// transformation but then the speed-up is smaller because of the large number
-// of congruent sets. The algorithm can also limit the range of transformations
-// when the application knows something on the initial pose but this is not
-// necessary in general (though can speed the runtime significantly).
-
-// Home page of the 4PCS project (containing the paper, presentations and a
-// demo): http://graphics.stanford.edu/~niloy/research/fpcs/fpcs_sig_08.html
-// Use google search on "4-points congruent sets" to see many related papers
-// and applications.
-
-
-#ifndef _OPENGR_DEMO_UTILS_H_
-#define _OPENGR_DEMO_UTILS_H_
-
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-namespace gr {
-namespace Demo {
-// First input.
-static std::string input1 = "input1.obj";
-
-// Second input.
-static std::string input2 = "input2.obj";
-
-// Output. The transformed second input.
-static std::string output = "";
-// Default name for the '.obj' output file
-static std::string defaultObjOutput = "output.obj";
-// Default name for the '.ply' output file
-static std::string defaultPlyOutput = "output.ply";
-
-// Transformation matrice.
-static std::string outputMat = "";
-
-// Sampled cloud 1
-static std::string outputSampled1 = "";
-
-// Sampled cloud 2
-static std::string outputSampled2 = "";
-
-// Delta (see the paper).
-static double delta = 5.0;
-
-// Estimated overlap (see the paper).
-static double overlap = 0.2;
-
-// Threshold of the computed overlap for termination. 1.0 means don't terminate
-// before the end.
-static double thr = 1.0;
-
-// Maximum norm of RGB values between corresponded points. 1e9 means don't use.
-static double max_color = -1;
-
-// Number of sampled points in both files. The 4PCS allows a very aggressive
-// sampling.
-static int n_points = 200;
-
-// Maximum angle (degrees) between corresponded normals.
-static double norm_diff = -1;
-
-// Maximum allowed computation time.
-static int max_time_seconds = 10;
-
-// Point type to use - ExtPointBinding demo
-static int point_type = 0;
-static int max_point_type = 2; // 0: gr::Point3D, 1: extlib1::PointType1, 2: extlib2::PointType2
-
-static bool use_super4pcs = true;
-
-static inline void printParameterList(){
-    fprintf(stderr, "Parameter list:\n");
-    fprintf(stderr, "\t[ -o overlap (%2.2f) ]\n", overlap);
-    fprintf(stderr, "\t[ -d delta (%2.2f) ]\n", delta);
-    fprintf(stderr, "\t[ -n n_points (%d) ]\n", n_points);
-    fprintf(stderr, "\t[ -a norm_diff (%f) ]\n", norm_diff);
-    fprintf(stderr, "\t[ -c max_color_diff (%f) ]\n", max_color);
-    fprintf(stderr, "\t[ -t max_time_seconds (%d) ]\n", max_time_seconds);
-}
-
-static inline void printUsage(int /*argc*/, char **argv){
-    fprintf(stderr, "\nUsage: %s -i input1 input2\n", argv[0]);
-    printParameterList();
-}
-
-static inline int getArgs(int argc,
-                           char **argv,
-                           const Utils::Logger& logger = Utils::Logger()) {
-  int i = 1;
-  while (i < argc) {
-    if (!strcmp(argv[i], "-i")) {
-      input1 = std::string(argv[++i]);
-      input2 = std::string(argv[++i]);
-    } else if (!strcmp(argv[i], "-o")) {
-      overlap = atof(argv[++i]);
-    } else if (!strcmp(argv[i], "-d")) {
-      delta = atof(argv[++i]);
-    } else if (!strcmp(argv[i], "-c")) {
-      max_color = atof(argv[++i]);
-    } else if (!strcmp(argv[i], "-t")) {
-      max_time_seconds = atoi(argv[++i]);
-    } else if (!strcmp(argv[i], "-a")) {
-      norm_diff = atof(argv[++i]);
-    } else if (!strcmp(argv[i], "-n")) {
-      n_points = atoi(argv[++i]);
-    } else if (!strcmp(argv[i], "-r")) {
-      output = argv[++i];
-    } else if (!strcmp(argv[i], "-m")) {
-      outputMat = argv[++i];
-    } else if (!strcmp(argv[i], "-x")) {
-      use_super4pcs = false;
-    } else if (!strcmp(argv[i], "--sampled1")) {
-      outputSampled1 = argv[++i];
-    } else if (!strcmp(argv[i], "--sampled2")) {
-      outputSampled2 = argv[++i];
-    } else if (!strcmp(argv[i], "-p")) {
-      point_type = atoi(argv[++i]);
-      if(point_type < 0 || point_type > max_point_type) {
-        std::cerr << "Invalid point type: setting to default (0)" << std::endl;
-        point_type = 0;
-      } 
-    } else if (!strcmp(argv[i], "-h")) {
-      return 1;
-    } else if (argv[i][0] == '-') {
-      std::cerr << "Unknown flag\n";
-      return -1;
-    };
-    i++;
-  }
-
-  // if no output file (geometry/matrix) is set, force 3d mesh
-  if (output.empty() && outputMat.empty()) output = defaultObjOutput;
-
-  return 0;
-}
-
-template 
-static inline bool setOptionsFromArgs( OptionType &options,
-                                       const Utils::Logger& logger = Utils::Logger())
-{
-    bool overlapOk = options.configureOverlap(overlap);
-    if(! overlapOk )  {
-        logger.Log("Invalid overlap configuration. ABORT");
-        return false;
-    }
-    options.sample_size = n_points;
-    options.max_normal_difference = norm_diff;
-    options.max_color_distance = max_color;
-    options.max_time_seconds = max_time_seconds;
-    options.delta = delta;
-
-    return true;
-}
-
-} // namespace Demo
-} // namespace gr
-#endif
diff --git a/src/external/OpenGR/doc/Compilation.md b/src/external/OpenGR/doc/Compilation.md
deleted file mode 100644
index 7d5659244..000000000
--- a/src/external/OpenGR/doc/Compilation.md
+++ /dev/null
@@ -1,122 +0,0 @@
-# Compilation  {#compilation}
-Super4PCS is now supported for Linux, MacOS and Windows platforms, with continuous testing.
-This file reviews the following aspects:
-* how to compile and install the library, tests and applications: [here](#library)
-* how to use the library in your own software: [here](#usage)
-* a note about compilation mode and performances: [here](#perfs)
-
-**Note:** Super4PCS relies heavily on CMake for its compilation and use (minimum version: v3.3).
-
-##  Compiling the library, application and tests
-For people in a hurry:
-```bash
-git clone https://github.com/STORM-IRIT/OpenGR.git
-mkdir build
-cd build
-cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./install
-make install
-cd install/scripts/
-./run-example.sh
-```
-
-### Dependencies
-Super4PCS takes care of its own dependencies, and downloads them when required. As a result, **you may need an internet connection for the first compilation**.
-
-The libraries and the standalone application require:
-* [Eigen](http://eigen.tuxfamily.org/). The library is automagically downloaded and configured by the cmake process. If you need to force using Eigen from a specific path, call CMAKE with `-DEIGEN3_INCLUDE_DIR=/path/to/eigen`.
-
-IO and tests:
-* [Boost-filesystem](http://www.boost.org/doc/libs/1_57_0/libs/filesystem/doc/index.htm), used to read dataset folders. Requires Boost version: 1.57 or more.
-
-### CMake Options
-Our CMake scripts can be configured using the following options:
-* Compilation rules
-    * `OPTION (SUPER4PCS_COMPILE_TESTS "Enable testing" TRUE)`
-    * `OPTION (SUPER4PCS_COMPILE_DEMOS "Compile demo applications (including the Super4PCS standalone)" TRUE)`
-    * `OPTION (IO_USE_OPENCV "Use OpenCV for texture loading" TRUE)`
-    * `OPTION (SUPER4PCS_USE_CHEALPIX "Use Chealpix for orientation filtering (deprecated)" FALSE)` We recommend to keep this option to `FALSE`.
-* Advanced functionalities
-    * `+OPTION (SUPER4PCS_USE_WEIGHTED_LCP "Use gaussian weights for point samples when computing LCP" FALSE)` Was implicitely set to `FALSE` in previous release.
-* Extras
-    * `OPTION (DL_DATASETS "Download demo datasets and associated run scripts" FALSE)`
-* Debug options
-    * `OPTION (ENABLE_TIMING "Enable computation time recording" FALSE)`
-
-Options can be set by calling `cmake -DMY_OPTION=TRUE`, or by editing the file [CMakeList.txt](https://github.com/nmellado/Super4PCS/blob/master/CMakeLists.txt) (not recommended).
-
-### Compilation targets
-Our CMAKE scripts provide several targets:
-* `install`: build the libraries, the main application and install them to a dedicated folder alongside with demo scripts and assets. This is **recommended** target. The installation folder is by default: `ROOT_DIR/Super4PCS-${Super4PCS_VERSION_MAJOR}.${Super4PCS_VERSION_MINOR}`.
-It can be customized by calling cmake with `-DINSTALL_DIR=your_path`.
-* `all`/`Super4PCS`: build the libraries and the main Super4PCS application,
-* `buildtests`: compile tests. This target is generated only if `SUPER4PCS_BUILD_TEST` option is set to `TRUE`,
-* `test`: run the tests locally
-* `dl-datasets`: download the demo datasets.
-
-### Installed directories structure:
-After compilation and installation, you should obtain the following structure:
-```
-installation-directory/
-  - assets     -> contains the demo hippo files, and the downloaded datasets if any
-  - bin        -> contains the main Super4PCS application
-  - include    -> header files of the Super4PCS library
-  - lib        -> library binaries: super4pcs_algo and super4pcs_io, and chealpix if compiled
-  - lib/cmake  -> cmake package files
-  - scripts    -> demo scripts allowing to register the hippo meshes
-```
-
-***
-
-### Linux and MacOS Builds
-Nothing specific here, just call:
-```bash
-mkdir build
-cd build
-cmake -DCMAKE_BUILD_TYPE=Release ..
-make install
-```
-
-***
-
-### Windows Builds
-Super4PCS requires c++11 features and CMake support. We recommend to use Microsoft Visual Studio 2017 with [CMake plugin](https://blogs.msdn.microsoft.com/vcblog/2016/10/05/cmake-support-in-visual-studio/). CMake standalone is also supported (and used for Continuous Integration on AppVeyor).
-
-By default, the project can be opened and compiled straight away with no parameter setting.
-
-If you want to compile with OpenCV and/or Boost support, the dependency directories must be properly configured in Visual Studio.
-They can be set either when calling [CMake](https://blogs.msdn.microsoft.com/vcblog/2016/10/05/cmake-support-in-visual-studio/#configure-cmake) or globally by configuring Visual Studio (see how-to [here](https://social.msdn.microsoft.com/Forums/vstudio/en-US/a494abb8-3561-4ebe-9eb0-6f644a679862/visual-studio-2010-professional-how-to-add-include-directory-for-all-projects?forum=vcgeneral#7b5ab5f2-f793-4b0e-a18a-679948d12bdd)).
-![](img/VStudio-globalFolders.jpg)
-
-***
-
-##  Use Super4PCS library in your own application
-**From release v.1.1.2**, Super4PCS provides a CMake package, generated during the installation process.
-To use it in your own application, add the following lines to your project file:
-```cmake
-project(Super4PCS-externalAppTest)
-cmake_minimum_required(VERSION 3.3)
-
-set (CMAKE_CXX_STANDARD 11)
-
-find_package(Super4PCS REQUIRED)
-include_directories(${Super4PCS_INCLUDE_DIR})
-link_directories(${Super4PCS_LIB_DIR})
-
-add_executable(${PROJECT_NAME} main.cpp)
-target_link_libraries(${PROJECT_NAME} ${Super4PCS_LIBRARIES})
-
-# we also need eigen
-find_package( Eigen3 REQUIRED )
-include_directories( ${EIGEN3_INCLUDE_DIR} )
-```
-
-In addition, CMake must be ran so that `CMAKE_PREFIX_PATH` contains `Super4PCS_install_dir/lib/cmake` when compiling `Super4PCS-externalAppTest`.
-
-Super4PCS files will be located in the `super4pcs` folder. For instance, to use the Super4PCS algorithm:
-```c++
-#include 
-```
-This functionality is tested by our continuous integration system. Checkout the [externalAppTest](https://github.com/nmellado/Super4PCS/tree/master/tests/externalAppTest) for a working example.
-
-##  Debug mode and performances
-Note that we heavily use template mechanisms that requires to enable inlining in order to be efficient. Compiling in Debug mode without inlining may result in longer running time than expected.
diff --git a/src/external/OpenGR/doc/Current-release.md b/src/external/OpenGR/doc/Current-release.md
deleted file mode 100644
index c50055f79..000000000
--- a/src/external/OpenGR/doc/Current-release.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Release Notes {#currentrelease}
-## V1.1.x
-This release introduces new code structure allowing use as an actual library.
-
- - Build system
-   - Super4PCS now generates a CMake package, so you just need to call `find_package(Super4PCS)` to work with the library.
-   - Save binaries compiled by AppVeyor integration system as Artifacts.
- - Demos, scripts and assets
-   - assets are now added to the install folder, including downloaded datasets.
-   - demo scripts have been updated to work directly after installation. Windows batch scripts have been added.
- - Dependencies
-   - Chealpix dependency is marked as deprecated: it slows down the approach and reduce it's robustness. Consequently, Chealpix is still built in CI but not tested.
- - Devel
-   - Update include directive relatively to super4pcs root dir. (including fix by @xinkang when enabling timings).
-   - Add silent mode in matcher to avoid unwanted logging on standard output. This is implemented by adding a visitor in the matcher main loop, and set it as a logger in the Super4pcs main app.
-   - Change directories structure with separated library, tests and demos folders.
-
-
-## V1.0.x-alpha
-Pre-release introducing the new version of the Super4PCS library.
-No much changes on the API, but many changes on the code internal structure, tests, etc.
-
-Major changes:
- * Dependencies:
-   * remove ANN dependency,
-   * remove dependency to Chealpix. Can be controlled by the option `SUPER4PCS_USE_CHEALPIX`. This options will be available for some time for experiment purposes. During this time, Chealpix and Cfitsio files will still be shipped with Super4PCS source code.
-   * OpenCV is required only to load meshes textures. This dependency can be removed by switching option `IO_USE_OPENCV` to `FALSE`,
- * remove duplicate code between 4PCS and Super4PCS,
- * clean code structure,
- * demo dataset + run script added.
- * CMake project can now be opened directly with Visual Studio 2017.
-
-## V0.2.x-alpha
-Pre-release including improved compilation system, supporting both windows and linux platforms.
-Binaries are available for x64 Windows platforms (tested with windows 7 and 10, requires Microsoft Visual C++ Redistributable for Visual Studio 2015).
-
-Major changes:
- * Fix segfault reported in issue #11
- * fix IO bug #9
- * add windows support #4. As a side effect, dependencies are now packaged with the library.
- * improved Cmake configuration: c++11 flags check, add option to set/unset timing recording
-
-Compatibility:
- * add compatibility with OpenCV3.0 and greater
- * fix compilation errors with gcc 4.9.1
-
-Minor and devel changes :
- * exploration is now stopped when LCP = 1
- * fix several minor bugs, causing instabilities and reduced performances
- * use functors in several place, to improve code reusability and prepare next milestones
- * removed several compilation warnings
-
-## V0.1-alpha
-Alpha version of the Super4PCS first release, introducing:
-
-* compilation environment using CMake.
-* unit-tests based on CTest: to process both sub-routines and the whole Super4PCS algorithm using an online dataset with ground truth (Standford).
-* improved performances and bugfixes.
-
diff --git a/src/external/OpenGR/doc/Datasets.md b/src/external/OpenGR/doc/Datasets.md
deleted file mode 100644
index bb46c6a18..000000000
--- a/src/external/OpenGR/doc/Datasets.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Datasets {#datasets}
-
-If you want to go further, you can also download the demo datasets, including 3D models from the original paper. To do so, you can either call
-
-    make dl-datasets
-
-if you use Super4PCS from sources, or directly download this [file](https://www.irit.fr/~Nicolas.Mellado/dl/datasets/point-clouds/Super4PCS-dataset-demo1.zip) (MD5: `ad1e172902b41a3f17e9b4901adf3ba5`).
-
-Then, call the registration script:
-
-    cd assets/demo1
-    ./run.sh   # call the run.bat script on windows
-
-The registration output can be easily checked using the meshlab projects (files `*.mlp`) provided in the dataset subfolders.
-
-> Note that this demo does not include local registration, ICP must be ran in post-process to obtain fine alignment.
diff --git a/src/external/OpenGR/doc/Demos.md b/src/external/OpenGR/doc/Demos.md
deleted file mode 100644
index 70f57ab37..000000000
--- a/src/external/OpenGR/doc/Demos.md
+++ /dev/null
@@ -1,122 +0,0 @@
-# Scripts, Demos and wrappers {#demos}
-
-Starting from v1.1.3, the library is shipped with applications demonstrating how to use the library.
-
-
-## Standalone demo
-This is the original command line application, allowing to register two views of the same object or scene.
-It is available at `install_dir/bin/Super4pcs`.
-
-To compile, call:
-
-    make Super4PCS
-
-See the @ref usage page for more details.
-
-## Meshlab Plugin
-> You need to compile the library from source to use this feature.
-
-A Meshlab plugin can be generated from the library.
-Since we do not want to carry the full Meshlab repository, we assume that Meshlab source code can be found somewhere close to the Super4PCS sources (check `cmake/FindMeshlab.cmake` for more details).
-We thus provide a cmake target `Meshlab_install_plugin` that will generate a Meshlab plugin source files, and put them in `meshlab_dir/src/meshlabplugins/filter_globalregistration`:
- - `filter_globalregistration.pro`: which properly set the link and include directories to compile the plugin
- - `globalregistration.h` and `globalregistration.cpp`: the plugin source code
- - `readme.md`: which gives you the instructions to follow to add the GlobalRegistration plugin to the Meshlab plugin compilation list.
-
-Note that we also copy libraries and include files in the `meshlab_dir/src/external folder`.
-
-To compile, call
-
-    make Meshlab_install_plugin
-    cd meshlab_dir/src
-    # Follow instructions from meshlabplugins/filter_globalregistration/readme.md
-    qmake meshlab_full.pro && make
-
-The plugin can be found in Meshlab in `Filter > Point set > Global Registration`, or using the filter search engine.
-
-
-
-## PCLWrapper
-Provides a wrapper to use Super4PCS within the Point Cloud Library, and implementing `pcl::Registration`.
-
-The wrapper source code is available at `install_dir/include/pcl/registration`. Note that our file structure follows the PCL source code organization.
-
-A command line application demonstrating how to use the wrapper is available here: `install_dir/bin/Super4PCS-PCLWrapper`.
-To compile, call:
-
-    make Super4PCS-PCLWrapper
-
-The source code of the demo application is quite simple:
-
-~~~~~~~~~~~~~{.cpp}
-using namespace GlobalRegistration;
-
-// Align a rigid object to a scene with clutter and occlusions
-int
-main (int argc, char **argv)
-{
-  // Point clouds
-  PointCloudT::Ptr object (new PointCloudT);
-  PointCloudT::Ptr object_aligned (new PointCloudT);
-  PointCloudT::Ptr scene (new PointCloudT);
-
-  // Get input object and scene
-  if (argc < 4)
-  {
-    pcl::console::print_error ("Syntax is: %s scene.obj object.obj [PARAMS]\n", argv[0]);
-    Demo::printParameterList();
-    return (-1);
-  }
-
-  // Load object and scene
-  pcl::console::print_highlight ("Loading point clouds...\n");
-  if (pcl::io::loadOBJFile (argv[2], *object) < 0 ||
-      pcl::io::loadOBJFile (argv[1], *scene) < 0)
-  {
-    pcl::console::print_error ("Error loading object/scene file!\n");
-    return (-1);
-  }
-
-  // Load Super4pcs parameters
-  Demo::getArgs(argc, argv);
-
-  pcl::Super4PCS align;
-  Demo::setOptionsFromArgs(align.options_);
-
-  // Perform alignment
-  pcl::console::print_highlight ("Starting alignment...\n");
-  align.setInputSource (object);
-  align.setInputTarget (scene);
-
-  {
-    pcl::ScopeTime t("Alignment");
-    align.align (*object_aligned);
-  }
-
-  if (align.hasConverged ())
-  {
-    // Print results
-    printf ("\n");
-    Eigen::Matrix4f transformation = align.getFinalTransformation ();
-    pcl::console::print_info ("    | %6.3f %6.3f %6.3f | \n", transformation (0,0), transformation (0,1), transformation (0,2));
-    pcl::console::print_info ("R = | %6.3f %6.3f %6.3f | \n", transformation (1,0), transformation (1,1), transformation (1,2));
-    pcl::console::print_info ("    | %6.3f %6.3f %6.3f | \n", transformation (2,0), transformation (2,1), transformation (2,2));
-    pcl::console::print_info ("\n");
-    pcl::console::print_info ("t = < %0.3f, %0.3f, %0.3f >\n", transformation (0,3), transformation (1,3), transformation (2,3));
-    pcl::console::print_info ("\n");
-
-    // Show alignment
-    pcl::visualization::PCLVisualizer visu("Alignment - Super4PCS");
-    visu.addPointCloud (scene, ColorHandlerT (scene, 0.0, 255.0, 0.0), "scene");
-    visu.addPointCloud (object_aligned, ColorHandlerT (object_aligned, 0.0, 0.0, 255.0), "object_aligned");
-    visu.spin ();
-  }
-  else
-  {
-    pcl::console::print_error ("Alignment failed!\n");
-    return (-1);
-  }
-
-  return (0);
-}
-~~~~~~~~~~~~~
diff --git a/src/external/OpenGR/doc/File-formats.md b/src/external/OpenGR/doc/File-formats.md
deleted file mode 100644
index 623030f21..000000000
--- a/src/external/OpenGR/doc/File-formats.md
+++ /dev/null
@@ -1,111 +0,0 @@
-# Supported File Formats {#fileformats}
-
-The Super4PCS library provides its own IO module, to load and save 3D point clouds, meshes and export computed matrices.
-
-## Overview
-|                       |   Input    |  Output   |
-|:---------------------:|:----------:|:---------:|
-| Point-cloud           | ply, ptx   |  ply      |
-| Mesh                  | obj        |  obj      |
-| Transformation Matrix |            |  txt      |
-| Sampled clouds        |            |  ply      |
-
-Input/Output files are specified using the following flags:
-* `-i file1 file2`: two input files,
-* `-r filename`: output file,
-* `-m filename`: output matrix,
-* `--sampled1 filename`: cloud sampled from input 1,
-* `--sampled2 filename`: cloud sampled from input 2.
-
-When neither `-r` nor `-m` are specified, the result is exported to `output.obj/.ply`.
-
-## Parsers specifications
-### Transformation matrices ([2c92b29](http://github.com/nmellado/Super4PCS/commit/2c92b29d796309de3c01a43406b9054df262b84f))
-3D matrices are exported as text files, such as:
-
-    VERSION	=	1
-    MATRIX	=
-     0.952888   0.099464  -0.286551   0.045467
-    -0.096379   0.995034   0.024886  -0.372831
-     0.287603   0.003904   0.957742  -0.447515
-     0.000000   0.000000   0.000000   1.000000
-
-These files can be loaded by Polyworks to transform geometry layers.
-
-
-### PTX ([84d079e](http://github.com/nmellado/Super4PCS/commit/84d079e8ec0b2c79c82e167164d103ffb6e40f18))
-[Cyclone pointcloud export](http://w3.leica-geosystems.com/kb/?guid=5532D590-114C-43CD-A55F-FE79E5937CB2) format, available only to **load** range maps as point-clouds.
-
-The scanner position and the cloud transformations are ignored, and only the first range map is considered.
-
-### PLY
-The [PoLYgon file format](http://en.wikipedia.org/wiki/PLY_%28file_format%29) (.ply) is used to load/save **point-clouds** exclusively. Both ASCII and Binary encoding are supported, but ASCII encoding is in general preferred.
-
-A limited set of property list is supported. Using other formats will **not** trigger any error, but will prevent the algorithm to find a solution.
-
-In ASCII mode only, both float and double properties are supported (files generated by matlab).
-
-The supported property lists are (any other property type will cause the program to run on wrong data!):
-####Position only
-
-    property float x
-    property float y
-    property float z
-
-####Position + Normals
-
-    property float x
-    property float y
-    property float z
-    property float nx
-    property float ny
-    property float nz
-
-####Position + Colors (RGB)
-
-    property float x
-    property float y
-    property float z
-    property uchar red
-    property uchar green
-    property uchar blue
-
-####Position + Colors (RGBA)
-
-    property float x
-    property float y
-    property float z
-    property uchar red
-    property uchar green
-    property uchar blue
-    property uchar alpha
-
-####Position + Normals + Colors (RGB)
-
-    property float x
-    property float y
-    property float z
-    property float nx
-    property float ny
-    property float nz
-    property uchar red
-    property uchar green
-    property uchar blue
-
-####Position + Normals + Colors (RGBA)
-
-    property float x
-    property float y
-    property float z
-    property float nx
-    property float ny
-    property float nz
-    property uchar red
-    property uchar green
-    property uchar blue
-    property uchar alpha
-
-### OBJ
-[Wavefront OBJ](http://en.wikipedia.org/wiki/Wavefront_.obj_file) files are used to load/save meshes.
-Faces lists are required, and textures are supported (per-vertex color fetched from the texture).
-
diff --git a/src/external/OpenGR/doc/Getting-started.md b/src/external/OpenGR/doc/Getting-started.md
deleted file mode 100644
index 14c30caec..000000000
--- a/src/external/OpenGR/doc/Getting-started.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Getting Started {#gettingstarted}
-
-Since Release v1.1.x we improved the usability of Super4PCS as an application or as a library.
-
-To run the application, you just need to:
-
- 1. Compile the source code (checkout the @ref compilation page), or download the latest [release](https://github.com/nmellado/Super4PCS/releases) to obtain the Super4PCS binary.
- 2. Go to the script folder, and run the `run-example` script from there.
-
-Then, depending on plans, you also might want to look at:
- - our @ref demos, the use the library with the Point Cloud Library or with a Meshlab plugin.
- - the @ref datasets page, to *further test the application on real datasets*, including models from the original paper.
- - the @ref usage page for more details on the Super4PCS parameters.
- - the [Match4PCSBase](@ref GlobalRegistration::Match4PCSBase) class, if you plan to *use the library in you own software*.
-   This is the base class for registration algorithms, providing the [ComputeTransformation](@ref GlobalRegistration::Match4PCSBase::ComputeTransformation) method. Two different algorithms are today available: [4PCS](@ref GlobalRegistration::Match4PCS) and its more efficient variant [Super4PCS](@ref GlobalRegistration::MatchSuper4PCS)
-
diff --git a/src/external/OpenGR/doc/Road-map.md b/src/external/OpenGR/doc/Road-map.md
deleted file mode 100644
index e78dd8e70..000000000
--- a/src/external/OpenGR/doc/Road-map.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Roadmap  {#roadmap}
-
-Super4PCS refactoring started with v1.1.x is now almost done.
-Current changes are now focusing on:
-* stabilizing the API
-* improving testing
-* adding wrappers to point-cloud and mesh processing libraries/softwares.
-See the Pull Request to the next release v1.1.3 [here](https://github.com/nmellado/Super4PCS/pull/45).
-
-At long term, our goal is to:
-* implement other approaches such as [Generalized4PCS](http://dl.acm.org/citation.cfm?id=2758287) or the recent [2 -points+normal](http://ieeexplore.ieee.org/abstract/document/7989664/) variant.
-* add bridge to local registration implementation (PCL ?).
-
-In parallel, we also plan to release datasets with ground-truth transformations, to ease comparison between registration techniques.
diff --git a/src/external/OpenGR/doc/Tests.md b/src/external/OpenGR/doc/Tests.md
deleted file mode 100644
index 38cc50b1a..000000000
--- a/src/external/OpenGR/doc/Tests.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# Tests {#tests}
-
-Tests are currently under active development. We use the following tools in this project:
-* [Travis](https://travis-ci.org/STORM-IRIT/OpenGR) : continuous integration for linux and MacOS
-* [AppVeyor](https://ci.appveyor.com/project/nmellado/opengr/) : continuous integration for windows
-
-## Continuous integration
-Continuous Integration status:
-
-[stsimg-linux]: https://api.travis-ci.org/STORM-IRIT/OpenGR.svg?branch=master
-[stsimg-windw]: https://ci.appveyor.com/api/projects/status/wpilmlfk8obuod8b/branch/master?svg=true
-
-| Linux  \& MacOS | Windows         |
-| :----:          | :-----:         |
-| ![stsimg-linux] | ![stsimg-windw] |
-
-
-## Compiling and running tests
-Tests are implemented with CTest. To run the tests, call:
-```{bash}
-make buildtests && make test
-```
-
-
-Tests currently available:
-* `pair_extraction`: generate random point clouds in 2, 3 and 4D, and query the pair generation structure with various radius.
-* `quad_extraction`: generate random point clouds in 3D and query the quad generation structure with various radius. Routines from 4PCS and Super4PCS are then compared. This test is still in development mode and would need some improvements.
-* `matching`: test the whole Super4PCS pipeline by registering range maps from the standford repository. You need an internet connection to build this test, since the datasets are downloaded at this time. Here range maps are registered sequentially, and the test is passed only if the estimated transformation is close enough to the GT provided in the dataset.
diff --git a/src/external/OpenGR/doc/Usage-Part-in-Whole.md b/src/external/OpenGR/doc/Usage-Part-in-Whole.md
deleted file mode 100644
index c051e7a5a..000000000
--- a/src/external/OpenGR/doc/Usage-Part-in-Whole.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# [Usage] Part-in-whole {#usage-partinwhole}
-
-See more details about part-in-whole matching in issue [#46](https://github.com/nmellado/Super4PCS/issues/46).
diff --git a/src/external/OpenGR/doc/Usage.md b/src/external/OpenGR/doc/Usage.md
deleted file mode 100644
index ed1c61f71..000000000
--- a/src/external/OpenGR/doc/Usage.md
+++ /dev/null
@@ -1,89 +0,0 @@
-# Usage {#usage}
-
-In this page we review the main parameters of the Super4PCS algorithm, and how to use them properly to efficiently register point-clouds.
-We also list and describe difficult configurations that may arise sometime, how to detect them and sort them out.
-
-Specific cases are described in dedicated pages:
- - @subpage usage-partinwhole
-
-To get the exhaustive list of Super4PCS parameters, run the executable found in `${CMAKE_INSTALL_PREFIX}/bin/` directory:
-
-    ./Super4PCS -h
-
-In the current version, you should get
-
-    Usage: ./Super4PCS -i input1 input2
-        [ -o overlap (0.20) ]
-        [ -d delta (5.00) ]
-        [ -n n_points (200) ]
-        [ -a norm_diff (90.000000) ]
-        [ -c max_color_diff (150.000000) ]
-        [ -t max_time_seconds (10) ]
-        [ -r result_file_name (output.obj) ]
-        [ -x (use 4pcs: false by default) ]
-
-Each parameter is described by its string identifiers, followed by the default value between (). Note that all parameters string must be followed by a value, except -x, the option to use 4PCS instead of Super4PCS.
-
-**Note for 4PCS users:**
->Super4PCS comes with exactly the same interface than 4PCS. So you can use the same settings, you should get similar results.
->In case you need it, Super4PCS also includes the original 4PCS procedure. You can call it by adding -x to your command line.
-
-## Playing with parameters
-### Parameters overview
-The three main parameters of the algorithm (overlap. number of samples, and accuracy) are described in the following sections.
-
-The `-a` and `-c` parameters defines threshold used to filter pairs according to their consistency, regarding normal angles and rgb values respectively.
-This filtering is enabled only when the associated fields are loaded from the input files.
-
-Super4PCS explores the transformation space to align the two input clouds.
-The maximum time allowed to the process is set using the option `-t`.
-Since the exploration is performed randomly, it is recommended to use a large time value to explore the whole space (e.g., `-t 1000`).
-
-### Overlap estimation (-o)
-This parameter defines the amount of expected overlap between the two clouds: it is ranging between 0 (no overlap) to 1 (100% overlap).
-
-The overlap parameter controls the size of the basis used for registration, as shown in the Figure below:
-
-
-
-Usually, the larger the overlap, the faster the algorithm.
-When the overlap is unknown, a simple way to set this parameter is to start from 100% overlap, and decrease the value until obtaining a good result.
-Using too small values will slow down the algorithm, and reduce the accuracy of the result.
-
-
-### Number of samples (-n)
-Input clouds are sub-sampled prior exploration, to ensure fast computations.
-Super4PCS has a linear complexity wrt the number of input samples, allowing to use larger values than 4PCS.
-Simple geometry with large overlap can be matched with only 200 samples.
-However, with Super4PCS, smaller details can be used during the process by using up to thousands of points.
-There is no theoretical limit to this parameter, however using too large values leads to very a large congruent set, which requires more time and memory to be explored.
-
-Using a large number of samples is recommended when:
-* **geometrical details** are _required_ to perform the matching, for instance to disambiguate between several similar configurations,
-* the clouds have a very low **overlap**: using a too sparse sampling can prevent to have samples in the overlapping area, causing the algorithm to fail,
-* the clouds are very **noisy**, and require a dense sampling.
-
-Note that Super4PCS is a global registration algorithm, which finds a good _approximate_ of the rigid transformation aligning too clouds.
-Increasing the number of samples in order to get a fine registration is not optimal: it is usually faster to use less samples, and refine the transformation using a local algorithm, like the [ICP](http://pointclouds.org/documentation/tutorials/iterative_closest_point.php), or its variant [SparseICP](https://github.com/OpenGP/sparseicp).
-
-### Registration accuracy (-d)
-This parameter controls the registration accuracy (delta in the paper) : setting a small value means that the two clouds needs to be very close to be considered as well aligned. It is expressed in scene units.
-
-A simple way to understand its impact is to consider the computation of the Largest Common Pointset (LCP), the metric used to verify how much the clouds are aligned.
-For each transformation matrix produced by Super4PCS, we compute the LCP measure by considering a shell around the reference cloud, and count the % of points of the target cloud lying in the shell. The thickness of the shell is defined by the parameter delta.
-
-The LCP values are given in the standard output:
-
-        ./run-example.sh
-        Use Super4PCS
-        create tree
-        create tree ... DONE (5281 points)
-        Work with 414 points
-        norm_max_dist: 0.010000
-        Initial LCP: 0.004831
-        Score: 0.748792
-with 0.4% points lying in the shell at the beginning of the process, and 74.8% at the end. (If you want to test the exemple, make sure that you are in `build/install/scripts` directory before running the exemple.sh)
-
-Using too wide values will slow down the algorithm by increasing the size of the congruent set, while using to small values prevents to find a solution.
-This parameter impacts other steps of the algorithm, see the paper for more details.
-
diff --git a/src/external/OpenGR/doc/Using-your-point-type.md b/src/external/OpenGR/doc/Using-your-point-type.md
deleted file mode 100644
index d31b95e82..000000000
--- a/src/external/OpenGR/doc/Using-your-point-type.md
+++ /dev/null
@@ -1,78 +0,0 @@
-# Using Your Point Type {#using-your-point-type}
-
-OpenGR provides gr::PointConcept, which it relies on while operating with the point samples internally. While gr::PointConcept yields the least requirements for any point type that could be used as input to OpenGR, additional features could be introduced to be used as you extend the library, e.g., to employ different point filters while comparing two point instances considering additional features.
-
-When an existing external point type is going to be used as input to OpenGR, gr::PointConcept can be implemented to behave as a wrapper (i.e. adapter) for the external point type. In this case, two types will be in question: the external point type whose instances are available to be passed to OpenGR, and the point type whose implementation is available to work as an adapter of the external point type to provide required interface to OpenGR. For registration, at the sampling stage, points are reinstantiated of the point adapter type which is given as template point type parameter. The requirement with gr::PointConcept for a constructor, which takes an instance of the external point type as input, is handy when the given point adapter type is not the same as the type of the input point instances. In other words, this constructor is used to reinstantiate the point sample with the given point adapter type at the sampling stage, so that, the provided interface could be used internally through the adapter.
-
-In the other case, if the type of the input point instances provides the required interface, the type of input point instances could be passed as the template type parameter. This way, the required constructor turns out to be the copy constructor of the point type. Therefore, the sample points are copied using the copy constructor of the point type at the sampling stage. Although this allows to avoid implementing an additional adapter type, one could consider using an mapper adapter if the copy constructor causes memory duplicates of the underlying point sample data.
-
-Internally, OpenGR uses Eigen for computation, vector representation and vectorization. Therefore, it expects gr::PointConcept::VectorType to be compatible with Eigen::DenseBase, as apparent in gr::PointConcept. To use existing point types without requiring any memory duplication while complying with this requirement, Eigen::Map could be used to map data of existing point types as an Eigen matrix or vector.
-
-For convenience, OpenGR provides an implementation for gr::PointConcept: gr::Point3D. IO methods for gr::Point3D is also provided with the library to use the library on supported point cloud files without needing to implement the point concept and the IO methods. 
-
-Following examples show two simple point type classes demonstrating possible point types external to OpenGR, and the adapters for those point types that allow OpenGR to work on the instances of them without needing any duplication of data while complying with the required interface of the point type concept: gr::PointConcept.
-
-### Example: Using an external point type: `extlib1::PointType1`
-
-\anchor extlib1-pointtype
-\snippet ExtPointBinding/ext/point_extlib1.hpp extlib1::PointType1
-
-Assuming that we have an external point type `extlib1::PointType1` as defined above, 
-which is used by some library ExtLib1, it is sufficient to implement the below point
-adapter `extlib1::PointAdapter`, and pass the type of the point adapter as the point
-type while instantiating any template class or method of OpenGR. OpenGR will wrap
-your point type with the adapter, and use the interface provided by the adapter
-for its computations.
-
-\anchor extlib1-pointadapter
-\snippet ExtPointBinding/ext/pointadapter_extlib1.hpp extlib1::PointAdapter
-
-Note that some members of the point adapter `extlib1::PointAdapter` is not required
-by default, but could be useful when used with point filters that make use of those
-members. For example, the methods `normal()` and `color()` are handful for point
-filters that use normal and color attributes of points while comparing two points,
-such as gr::AdaptivePointFilter. 
-
-The `ExtPointBinding` demo demonstrates the external point binding through point
-adapters by using the above external point type `extlib1::PointType1` together
-with another external point type `extlib2::PointType2`.
-
-#### Registration using Super4PCS
-In this section, registration of points of an example external point type is briefly
-discussed by referring to the point adapter shown. This example is extracted from
-the demo `ExtPointBinding`, for which complete code could be found.
-
-Let's say we have two `std::vector` instances that contain two point clouds with
-point type \ref extlib1-pointtype "extlib1::PointType1", which we would like to compute a registration
-transform using Super4PCS algorithm:
-
-\snippet ExtPointBinding/external_point_binding_test.cc Creating a vector of extlib1::PointType1
-
-In such case, we need to use \ref extlib1-pointadapter "extlib1::PointAdapter" as our point type to allow
-OpenGR retrive the required attributes of our points of type \ref extlib1-pointtype "extlib1::PointType1"
-by wrapping them with \ref extlib1-pointadapter "extlib1::PointAdapter" on-the-fly. Therefore, the type of
-the adapter is used to instantiate the matcher type:
-\snippet ExtPointBinding/external_point_binding_test.cc Point adapter and matcher type
-
-Also, the sampler type is instantiated using the point adapter type as sampler needs
-to retrieve attributes of the point as well:
-\snippet ExtPointBinding/external_point_binding_test.cc Sampler type
-
-And, the rest for the registration transformation computation is as regular, instantiating
-the matcher and computing the registration transformation. Notice that the instances
-of the external point type are directly passed to the matcher, without requiring
-to make any type conversions:
-\snippet ExtPointBinding/external_point_binding_test.cc Matcher instantiation and computation
-
-### Example: Using another external point type: `extlib2::PointType2`
-\snippet ExtPointBinding/ext/point_extlib2.hpp extlib2::PointType2
-
-Here, a different external point type, `extlib2::PointType2`, is shown, for which
-the point binding to OpenGR could be done using the below adapter type, `extlib2::PointAdapter`,
-in an efficient manner thanks to Eigen maps.
-
-\snippet ExtPointBinding/ext/pointadapter_extlib2.hpp extlib2::PointAdapter
-
-For any external point type, when a proper point adapter is defined, which could
-be done with little effort in an efficient manner for most cases, OpenGR could be
-utilized as shown.
\ No newline at end of file
diff --git a/src/external/OpenGR/doc/concepts.dox b/src/external/OpenGR/doc/concepts.dox
deleted file mode 100644
index 2330010f9..000000000
--- a/src/external/OpenGR/doc/concepts.dox
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace gr {
-    struct PairFilterConcept {
-    /// \brief Test if the pair p,q is similar to b0,b1
-    template 
-    inline std::pair operator() (const Point3D& p,
-                                            const Point3D& q,
-                                            typename Point3D::Scalar pair_normals_angle,
-                                            const Point3D& b0,
-                                            const Point3D& b1,
-                                            const OptionType &options)
-
-    };
-} // namespace gr
diff --git a/src/external/OpenGR/doc/dox/Doxyfile.in b/src/external/OpenGR/doc/dox/Doxyfile.in
deleted file mode 100644
index 35d78cd87..000000000
--- a/src/external/OpenGR/doc/dox/Doxyfile.in
+++ /dev/null
@@ -1,2450 +0,0 @@
-# Doxyfile 1.8.15
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project.
-#
-# All text after a double hash (##) is considered a comment and is placed in
-# front of the TAG it is preceding.
-#
-# All text after a single hash (#) is considered a comment and will be ignored.
-# The format is:
-# TAG = value [value, ...]
-# For lists, items can also be appended using:
-# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (\" \").
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all text
-# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
-# built into libc) for the transcoding. See
-# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
-# The default value is: UTF-8.
-
-DOXYFILE_ENCODING      = UTF-8
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
-# double-quotes, unless you are using Doxywizard) that should identify the
-# project for which the documentation is generated. This name is used in the
-# title of most generated pages and in a few other places.
-# The default value is: My Project.
-
-PROJECT_NAME           = "OpenGR"
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
-# could be handy for archiving the generated documentation or if some version
-# control system is used.
-
-PROJECT_NUMBER         = @OpenGR_PROJECT_NUMBER@
-
-# Using the PROJECT_BRIEF tag one can provide an optional one line description
-# for a project that appears at the top of each page and should give viewer a
-# quick idea about the purpose of the project. Keep the description short.
-
-PROJECT_BRIEF          = "A 3D Global Registration Library"
-
-# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
-# in the documentation. The maximum height of the logo should not exceed 55
-# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
-# the logo to the output directory.
-
-PROJECT_LOGO           = @CMAKE_CURRENT_SOURCE_DIR@/doc/img/logo/logo_dox.png
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
-# into which the generated documentation will be written. If a relative path is
-# entered, it will be relative to the location where doxygen was started. If
-# left blank the current directory will be used.
-
-OUTPUT_DIRECTORY       = @CMAKE_CURRENT_BINARY_DIR@/doc
-
-# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
-# directories (in 2 levels) under the output directory of each output format and
-# will distribute the generated files over these directories. Enabling this
-# option can be useful when feeding doxygen a huge amount of source files, where
-# putting all generated files in the same directory would otherwise causes
-# performance problems for the file system.
-# The default value is: NO.
-
-CREATE_SUBDIRS         = NO
-
-# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
-# characters to appear in the names of generated files. If set to NO, non-ASCII
-# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
-# U+3044.
-# The default value is: NO.
-
-ALLOW_UNICODE_NAMES    = NO
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
-# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
-# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
-# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
-# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
-# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
-# Ukrainian and Vietnamese.
-# The default value is: English.
-
-OUTPUT_LANGUAGE        = English
-
-# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
-# descriptions after the members that are listed in the file and class
-# documentation (similar to Javadoc). Set to NO to disable this.
-# The default value is: YES.
-
-BRIEF_MEMBER_DESC      = YES
-
-# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
-# description of a member or function before the detailed description
-#
-# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
-# brief descriptions will be completely suppressed.
-# The default value is: YES.
-
-REPEAT_BRIEF           = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator that is
-# used to form the text in various listings. Each string in this list, if found
-# as the leading text of the brief description, will be stripped from the text
-# and the result, after processing the whole list, is used as the annotated
-# text. Otherwise, the brief description is used as-is. If left blank, the
-# following values are used ($name is automatically replaced with the name of
-# the entity):The $name class, The $name widget, The $name file, is, provides,
-# specifies, contains, represents, a, an and the.
-
-ABBREVIATE_BRIEF       = "The $name class" \
-                         "The $name widget" \
-                         "The $name file" \
-                         is \
-                         provides \
-                         specifies \
-                         contains \
-                         represents \
-                         a \
-                         an \
-                         the
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# doxygen will generate a detailed section even if there is only a brief
-# description.
-# The default value is: NO.
-
-ALWAYS_DETAILED_SEC    = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
-# operators of the base classes will not be shown.
-# The default value is: NO.
-
-INLINE_INHERITED_MEMB  = NO
-
-# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
-# before files name in the file list and in the header files. If set to NO the
-# shortest path that makes the file name unique will be used
-# The default value is: YES.
-
-FULL_PATH_NAMES        = YES
-
-# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
-# Stripping is only done if one of the specified strings matches the left-hand
-# part of the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the path to
-# strip.
-#
-# Note that you can specify absolute paths here, but also relative paths, which
-# will be relative from the directory where doxygen is started.
-# This tag requires that the tag FULL_PATH_NAMES is set to YES.
-
-STRIP_FROM_PATH        =
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
-# path mentioned in the documentation of a class, which tells the reader which
-# header file to include in order to use a class. If left blank only the name of
-# the header file containing the class definition is used. Otherwise one should
-# specify the list of include paths that are normally passed to the compiler
-# using the -I flag.
-
-STRIP_FROM_INC_PATH    =
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
-# less readable) file names. This can be useful is your file systems doesn't
-# support long names like on DOS, Mac, or CD-ROM.
-# The default value is: NO.
-
-SHORT_NAMES            = YES
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
-# first line (until the first dot) of a Javadoc-style comment as the brief
-# description. If set to NO, the Javadoc-style will behave just like regular Qt-
-# style comments (thus requiring an explicit @brief command for a brief
-# description.)
-# The default value is: NO.
-
-JAVADOC_AUTOBRIEF      = YES
-
-# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
-# line (until the first dot) of a Qt-style comment as the brief description. If
-# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
-# requiring an explicit \brief command for a brief description.)
-# The default value is: NO.
-
-QT_AUTOBRIEF           = YES
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
-# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
-# a brief description. This used to be the default behavior. The new default is
-# to treat a multi-line C++ comment block as a detailed description. Set this
-# tag to YES if you prefer the old behavior instead.
-#
-# Note that setting this tag to YES also means that rational rose comments are
-# not recognized any more.
-# The default value is: NO.
-
-MULTILINE_CPP_IS_BRIEF = YES
-
-# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
-# documentation from any documented member that it re-implements.
-# The default value is: YES.
-
-INHERIT_DOCS           = YES
-
-# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
-# page for each member. If set to NO, the documentation of a member will be part
-# of the file/class/namespace that contains it.
-# The default value is: NO.
-
-SEPARATE_MEMBER_PAGES  = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
-# uses this value to replace tabs by spaces in code fragments.
-# Minimum value: 1, maximum value: 16, default value: 4.
-
-TAB_SIZE               = 4
-
-# This tag can be used to specify a number of aliases that act as commands in
-# the documentation. An alias has the form:
-# name=value
-# For example adding
-# "sideeffect=@par Side Effects:\n"
-# will allow you to put the command \sideeffect (or @sideeffect) in the
-# documentation, which will result in a user-defined paragraph with heading
-# "Side Effects:". You can put \n's in the value part of an alias to insert
-# newlines (in the resulting output). You can put ^^ in the value part of an
-# alias to insert a newline as if a physical newline was in the original file.
-
-ALIASES                =
-
-# This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding "class=itcl::class"
-# will allow you to use the command class in the itcl::class meaning.
-
-TCL_SUBST              =
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
-# only. Doxygen will then generate output that is more tailored for C. For
-# instance, some of the names that are used will be different. The list of all
-# members will be omitted, etc.
-# The default value is: NO.
-
-OPTIMIZE_OUTPUT_FOR_C  = NO
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
-# Python sources only. Doxygen will then generate output that is more tailored
-# for that language. For instance, namespaces will be presented as packages,
-# qualified scopes will look different, etc.
-# The default value is: NO.
-
-OPTIMIZE_OUTPUT_JAVA   = NO
-
-# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources. Doxygen will then generate output that is tailored for Fortran.
-# The default value is: NO.
-
-OPTIMIZE_FOR_FORTRAN   = NO
-
-# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for VHDL.
-# The default value is: NO.
-
-OPTIMIZE_OUTPUT_VHDL   = NO
-
-# Doxygen selects the parser to use depending on the extension of the files it
-# parses. With this tag you can assign which parser to use for a given
-# extension. Doxygen has a built-in mapping, but you can override or extend it
-# using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
-# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
-# Fortran. In the later case the parser tries to guess whether the code is fixed
-# or free formatted code, this is the default for Fortran type files), VHDL. For
-# instance to make doxygen treat .inc files as Fortran files (default is PHP),
-# and .f files as C (default is Fortran), use: inc=Fortran f=C.
-#
-# Note: For files without extension you can use no_extension as a placeholder.
-#
-# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
-# the files are not read by doxygen.
-
-EXTENSION_MAPPING      =
-
-# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
-# according to the Markdown format, which allows for more readable
-# documentation. See http://daringfireball.net/projects/markdown/ for details.
-# The output of markdown processing is further processed by doxygen, so you can
-# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
-# case of backward compatibilities issues.
-# The default value is: YES.
-
-MARKDOWN_SUPPORT       = YES
-
-USE_MDFILE_AS_MAINPAGE = @CMAKE_CURRENT_SOURCE_DIR@/doc/overview.md
-
-# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
-# to that level are automatically included in the table of contents, even if
-# they do not have an id attribute.
-# Note: This feature currently applies only to Markdown headings.
-# Minimum value: 0, maximum value: 99, default value: 0.
-# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
-
-TOC_INCLUDE_HEADINGS   = 0
-
-# When enabled doxygen tries to link words that correspond to documented
-# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by putting a % sign in front of the word or
-# globally by setting AUTOLINK_SUPPORT to NO.
-# The default value is: YES.
-
-AUTOLINK_SUPPORT       = YES
-
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should set this
-# tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string);
-# versus func(std::string) {}). This also make the inheritance and collaboration
-# diagrams that involve STL classes more complete and accurate.
-# The default value is: NO.
-
-BUILTIN_STL_SUPPORT    = YES
-
-# If you use Microsoft's C++/CLI language, you should set this option to YES to
-# enable parsing support.
-# The default value is: NO.
-
-CPP_CLI_SUPPORT        = NO
-
-# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
-# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
-# will parse them like normal C++ but will assume all classes use public instead
-# of private inheritance when no explicit protection keyword is present.
-# The default value is: NO.
-
-SIP_SUPPORT            = NO
-
-# For Microsoft's IDL there are propget and propput attributes to indicate
-# getter and setter methods for a property. Setting this option to YES will make
-# doxygen to replace the get and set methods by a property in the documentation.
-# This will only work if the methods are indeed getting or setting a simple
-# type. If this is not the case, or you want to show the methods anyway, you
-# should set this option to NO.
-# The default value is: YES.
-
-IDL_PROPERTY_SUPPORT   = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
-# The default value is: NO.
-
-DISTRIBUTE_GROUP_DOC   = NO
-
-# If one adds a struct or class to a group and this option is enabled, then also
-# any nested class or struct is added to the same group. By default this option
-# is disabled and one has to add nested compounds explicitly via \ingroup.
-# The default value is: NO.
-
-GROUP_NESTED_COMPOUNDS = NO
-
-# Set the SUBGROUPING tag to YES to allow class member groups of the same type
-# (for instance a group of public functions) to be put as a subgroup of that
-# type (e.g. under the Public Functions section). Set it to NO to prevent
-# subgrouping. Alternatively, this can be done per class using the
-# \nosubgrouping command.
-# The default value is: YES.
-
-SUBGROUPING            = YES
-
-# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
-# are shown inside the group in which they are included (e.g. using \ingroup)
-# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
-# and RTF).
-#
-# Note that this feature does not work in combination with
-# SEPARATE_MEMBER_PAGES.
-# The default value is: NO.
-
-INLINE_GROUPED_CLASSES = NO
-
-# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
-# with only public data fields or simple typedef fields will be shown inline in
-# the documentation of the scope in which they are defined (i.e. file,
-# namespace, or group documentation), provided this scope is documented. If set
-# to NO, structs, classes, and unions are shown on a separate page (for HTML and
-# Man pages) or section (for LaTeX and RTF).
-# The default value is: NO.
-
-INLINE_SIMPLE_STRUCTS  = NO
-
-# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
-# enum is documented as struct, union, or enum with the name of the typedef. So
-# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
-# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically be
-# useful for C code in case the coding convention dictates that all compound
-# types are typedef'ed and only the typedef is referenced, never the tag name.
-# The default value is: NO.
-
-TYPEDEF_HIDES_STRUCT   = NO
-
-# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
-# cache is used to resolve symbols given their name and scope. Since this can be
-# an expensive process and often the same symbol appears multiple times in the
-# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
-# doxygen will become slower. If the cache is too large, memory is wasted. The
-# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
-# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
-# symbols. At the end of a run doxygen will report the cache usage and suggest
-# the optimal cache size from a speed point of view.
-# Minimum value: 0, maximum value: 9, default value: 0.
-
-LOOKUP_CACHE_SIZE      = 0
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
-# documentation are documented, even if no documentation was available. Private
-# class members and static file members will be hidden unless the
-# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
-# Note: This will also disable the warnings about undocumented members that are
-# normally produced when WARNINGS is set to YES.
-# The default value is: NO.
-
-EXTRACT_ALL            = YES
-
-# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
-# be included in the documentation.
-# The default value is: NO.
-
-EXTRACT_PRIVATE        = NO
-
-# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
-# scope will be included in the documentation.
-# The default value is: NO.
-
-EXTRACT_PACKAGE        = NO
-
-# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
-# included in the documentation.
-# The default value is: NO.
-
-EXTRACT_STATIC         = NO
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
-# locally in source files will be included in the documentation. If set to NO,
-# only classes defined in header files are included. Does not have any effect
-# for Java sources.
-# The default value is: YES.
-
-EXTRACT_LOCAL_CLASSES  = NO
-
-# This flag is only useful for Objective-C code. If set to YES, local methods,
-# which are defined in the implementation section but not in the interface are
-# included in the documentation. If set to NO, only methods in the interface are
-# included.
-# The default value is: NO.
-
-EXTRACT_LOCAL_METHODS  = NO
-
-# If this flag is set to YES, the members of anonymous namespaces will be
-# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base name of
-# the file that contains the anonymous namespace. By default anonymous namespace
-# are hidden.
-# The default value is: NO.
-
-EXTRACT_ANON_NSPACES   = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
-# undocumented members inside documented classes or files. If set to NO these
-# members will be included in the various overviews, but no documentation
-# section is generated. This option has no effect if EXTRACT_ALL is enabled.
-# The default value is: NO.
-
-HIDE_UNDOC_MEMBERS     = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy. If set
-# to NO, these classes will be included in the various overviews. This option
-# has no effect if EXTRACT_ALL is enabled.
-# The default value is: NO.
-
-HIDE_UNDOC_CLASSES     = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO, these declarations will be
-# included in the documentation.
-# The default value is: NO.
-
-HIDE_FRIEND_COMPOUNDS  = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
-# documentation blocks found inside the body of a function. If set to NO, these
-# blocks will be appended to the function's detailed documentation block.
-# The default value is: NO.
-
-HIDE_IN_BODY_DOCS      = YES
-
-# The INTERNAL_DOCS tag determines if documentation that is typed after a
-# \internal command is included. If the tag is set to NO then the documentation
-# will be excluded. Set it to YES to include the internal documentation.
-# The default value is: NO.
-
-INTERNAL_DOCS          = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES, upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-# The default value is: system dependent.
-
-CASE_SENSE_NAMES       = NO
-
-# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
-# their full class and namespace scopes in the documentation. If set to YES, the
-# scope will be hidden.
-# The default value is: NO.
-
-HIDE_SCOPE_NAMES       = NO
-
-# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
-# append additional text to a page's title, such as Class Reference. If set to
-# YES the compound reference will be hidden.
-# The default value is: NO.
-
-HIDE_COMPOUND_REFERENCE= NO
-
-# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
-# the files that are included by a file in the documentation of that file.
-# The default value is: YES.
-
-SHOW_INCLUDE_FILES     = NO
-
-# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
-# grouped member an include statement to the documentation, telling the reader
-# which file to include in order to use the member.
-# The default value is: NO.
-
-SHOW_GROUPED_MEMB_INC  = NO
-
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
-# files with double quotes in the documentation rather than with sharp brackets.
-# The default value is: NO.
-
-FORCE_LOCAL_INCLUDES   = NO
-
-# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
-# documentation for inline members.
-# The default value is: YES.
-
-INLINE_INFO            = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
-# (detailed) documentation of file and class members alphabetically by member
-# name. If set to NO, the members will appear in declaration order.
-# The default value is: YES.
-
-SORT_MEMBER_DOCS       = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
-# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO, the members will appear in declaration order. Note that
-# this will also influence the order of the classes in the class list.
-# The default value is: NO.
-
-SORT_BRIEF_DOCS        = NO
-
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
-# (brief and detailed) documentation of class members so that constructors and
-# destructors are listed first. If set to NO the constructors will appear in the
-# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
-# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
-# member documentation.
-# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
-# detailed member documentation.
-# The default value is: NO.
-
-SORT_MEMBERS_CTORS_1ST = NO
-
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
-# of group names into alphabetical order. If set to NO the group names will
-# appear in their defined order.
-# The default value is: NO.
-
-SORT_GROUP_NAMES       = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
-# fully-qualified names, including namespaces. If set to NO, the class list will
-# be sorted only by class name, not including the namespace part.
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the alphabetical
-# list.
-# The default value is: NO.
-
-SORT_BY_SCOPE_NAME     = NO
-
-# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
-# type resolution of all parameters of a function it will reject a match between
-# the prototype and the implementation of a member function even if there is
-# only one candidate or it is obvious which candidate to choose by doing a
-# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
-# accept a match between prototype and implementation in such cases.
-# The default value is: NO.
-
-STRICT_PROTO_MATCHING  = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
-# list. This list is created by putting \todo commands in the documentation.
-# The default value is: YES.
-
-GENERATE_TODOLIST      = NO
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
-# list. This list is created by putting \test commands in the documentation.
-# The default value is: YES.
-
-GENERATE_TESTLIST      = NO
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
-# list. This list is created by putting \bug commands in the documentation.
-# The default value is: YES.
-
-GENERATE_BUGLIST       = NO
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
-# the deprecated list. This list is created by putting \deprecated commands in
-# the documentation.
-# The default value is: YES.
-
-GENERATE_DEPRECATEDLIST= NO
-
-# The ENABLED_SECTIONS tag can be used to enable conditional documentation
-# sections, marked by \if  ... \endif and \cond 
-# ... \endcond blocks.
-
-ENABLED_SECTIONS       =
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
-# initial value of a variable or macro / define can have for it to appear in the
-# documentation. If the initializer consists of more lines than specified here
-# it will be hidden. Use a value of 0 to hide initializers completely. The
-# appearance of the value of individual variables and macros / defines can be
-# controlled using \showinitializer or \hideinitializer command in the
-# documentation regardless of this setting.
-# Minimum value: 0, maximum value: 10000, default value: 30.
-
-MAX_INITIALIZER_LINES  = 30
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
-# the bottom of the documentation of classes and structs. If set to YES, the
-# list will mention the files that were used to generate the documentation.
-# The default value is: YES.
-
-SHOW_USED_FILES        = NO
-
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
-# will remove the Files entry from the Quick Index and from the Folder Tree View
-# (if specified).
-# The default value is: YES.
-
-SHOW_FILES             = NO
-
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
-# page. This will remove the Namespaces entry from the Quick Index and from the
-# Folder Tree View (if specified).
-# The default value is: YES.
-
-SHOW_NAMESPACES        = YES
-
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from
-# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command command input-file, where command is the value of the
-# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
-# by doxygen. Whatever the program writes to standard output is used as the file
-# version. For an example see the documentation.
-
-FILE_VERSION_FILTER    =
-
-# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
-# by doxygen. The layout file controls the global structure of the generated
-# output files in an output format independent way. To create the layout file
-# that represents doxygen's defaults, run doxygen with the -l option. You can
-# optionally specify a file name after the option, if omitted DoxygenLayout.xml
-# will be used as the name of the layout file.
-#
-# Note that if you run doxygen from a directory containing a file called
-# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
-# tag is left empty.
-
-LAYOUT_FILE            =
-
-# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
-# the reference definitions. This must be a list of .bib files. The .bib
-# extension is automatically appended if omitted. This requires the bibtex tool
-# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
-# For LaTeX the style of the bibliography can be controlled using
-# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
-# search path. See also \cite for info how to create references.
-
-CITE_BIB_FILES         =
-
-#---------------------------------------------------------------------------
-# Configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated to
-# standard output by doxygen. If QUIET is set to YES this implies that the
-# messages are off.
-# The default value is: NO.
-
-QUIET                  = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
-# this implies that the warnings are on.
-#
-# Tip: Turn warnings on while writing the documentation.
-# The default value is: YES.
-
-WARNINGS               = YES
-
-# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
-# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
-# will automatically be disabled.
-# The default value is: YES.
-
-WARN_IF_UNDOCUMENTED   = YES
-
-# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some parameters
-# in a documented function, or documenting parameters that don't exist or using
-# markup commands wrongly.
-# The default value is: YES.
-
-WARN_IF_DOC_ERROR      = YES
-
-# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
-# are documented, but have no documentation for their parameters or return
-# value. If set to NO, doxygen will only warn about wrong or incomplete
-# parameter documentation, but not about the absence of documentation.
-# The default value is: NO.
-
-WARN_NO_PARAMDOC       = NO
-
-# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
-# a warning is encountered.
-# The default value is: NO.
-
-WARN_AS_ERROR          = NO
-
-# The WARN_FORMAT tag determines the format of the warning messages that doxygen
-# can produce. The string should contain the $file, $line, and $text tags, which
-# will be replaced by the file and line number from which the warning originated
-# and the warning text. Optionally the format may contain $version, which will
-# be replaced by the version of the file (if it could be obtained via
-# FILE_VERSION_FILTER)
-# The default value is: $file:$line: $text.
-
-WARN_FORMAT            = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning and error
-# messages should be written. If left blank the output is written to standard
-# error (stderr).
-
-WARN_LOGFILE           = @CMAKE_CURRENT_BINARY_DIR/doc/doxygen.log
-
-#---------------------------------------------------------------------------
-# Configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag is used to specify the files and/or directories that contain
-# documented source files. You may enter file names like myfile.cpp or
-# directories like /usr/src/myproject. Separate the files or directories with
-# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
-# Note: If this tag is empty the current directory is searched.
-
-INPUT                  = @CMAKE_CURRENT_SOURCE_DIR@/src \
-                         @CMAKE_CURRENT_SOURCE_DIR@/doc
-
-# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
-# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
-# possible encodings.
-# The default value is: UTF-8.
-
-INPUT_ENCODING         = UTF-8
-
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
-# *.h) to filter out the source-files in the directories.
-#
-# Note that for custom extensions or not directly supported extensions you also
-# need to set EXTENSION_MAPPING for the extension otherwise the files are not
-# read by doxygen.
-#
-# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
-# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
-# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
-# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
-# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
-
-FILE_PATTERNS          = *.c \
-                         *.cpp \
-                         *.cc \
-                         *.c++ \
-                         *.inl \
-                         *.h \
-                         *.hpp \
-                         *.h++ \
-                         *.idl \
-                         *.inc \
-                         *.m \
-                         *.markdown \
-                         *.md \
-                         *.dox
-
-# The RECURSIVE tag can be used to specify whether or not subdirectories should
-# be searched for input files as well.
-# The default value is: NO.
-
-RECURSIVE              = YES
-
-# The EXCLUDE tag can be used to specify files and/or directories that should be
-# excluded from the INPUT source files. This way you can easily exclude a
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-#
-# Note that relative paths are relative to the directory from which doxygen is
-# run.
-
-EXCLUDE                =
-
-# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
-# directories that are symbolic links (a Unix file system feature) are excluded
-# from the input.
-# The default value is: NO.
-
-EXCLUDE_SYMLINKS       = NO
-
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories.
-#
-# Note that the wildcards are matched against the file with absolute path, so to
-# exclude all test directories for example use the pattern */test/*
-
-EXCLUDE_PATTERNS       =
-
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
-# (namespaces, classes, functions, etc.) that should be excluded from the
-# output. The symbol name can be a fully qualified name, a word, or if the
-# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
-#
-# Note that the wildcards are matched against the file with absolute path, so to
-# exclude all test directories use the pattern */test/*
-
-EXCLUDE_SYMBOLS        =
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or directories
-# that contain example code fragments that are included (see the \include
-# command).
-
-EXAMPLE_PATH           = @CMAKE_CURRENT_SOURCE_DIR@/demos \
-                         @CMAKE_CURRENT_BINARY_DIR@/doc
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
-# *.h) to filter out the source-files in the directories. If left blank all
-# files are included.
-
-EXAMPLE_PATTERNS       = *.cpp \
-                         *.h
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude commands
-# irrespective of the value of the RECURSIVE tag.
-# The default value is: NO.
-
-EXAMPLE_RECURSIVE      = YES
-
-# The IMAGE_PATH tag can be used to specify one or more files or directories
-# that contain images that are to be included in the documentation (see the
-# \image command).
-
-IMAGE_PATH             = @CMAKE_CURRENT_SOURCE_DIR@/doc/img
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command:
-#
-#  
-#
-# where  is the value of the INPUT_FILTER tag, and  is the
-# name of an input file. Doxygen will then use the output that the filter
-# program writes to standard output. If FILTER_PATTERNS is specified, this tag
-# will be ignored.
-#
-# Note that the filter must not add or remove lines; it is applied before the
-# code is scanned, but not when the output code is generated. If lines are added
-# or removed, the anchors will not be placed correctly.
-#
-# Note that for custom extensions or not directly supported extensions you also
-# need to set EXTENSION_MAPPING for the extension otherwise the files are not
-# properly processed by doxygen.
-
-INPUT_FILTER           =
-
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis. Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match. The filters are a list of the form: pattern=filter
-# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
-# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
-# patterns match the file name, INPUT_FILTER is applied.
-#
-# Note that for custom extensions or not directly supported extensions you also
-# need to set EXTENSION_MAPPING for the extension otherwise the files are not
-# properly processed by doxygen.
-
-FILTER_PATTERNS        =
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will also be used to filter the input files that are used for
-# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
-# The default value is: NO.
-
-FILTER_SOURCE_FILES    = NO
-
-# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
-# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
-# it is also possible to disable source filtering for a specific pattern using
-# *.ext= (so without naming a filter).
-# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
-
-FILTER_SOURCE_PATTERNS =
-
-# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
-# is part of the input, its contents will be placed on the main page
-# (index.html). This can be useful if you have a project on for instance GitHub
-# and want to reuse the introduction page also for the doxygen output.
-
-USE_MDFILE_AS_MAINPAGE =
-
-#---------------------------------------------------------------------------
-# Configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
-# generated. Documented entities will be cross-referenced with these sources.
-#
-# Note: To get rid of all source code in the generated output, make sure that
-# also VERBATIM_HEADERS is set to NO.
-# The default value is: NO.
-
-SOURCE_BROWSER         = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body of functions,
-# classes and enums directly into the documentation.
-# The default value is: NO.
-
-INLINE_SOURCES         = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
-# special comment blocks from generated source code fragments. Normal C, C++ and
-# Fortran comments will always remain visible.
-# The default value is: YES.
-
-STRIP_CODE_COMMENTS    = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
-# entity all documented functions referencing it will be listed.
-# The default value is: NO.
-
-REFERENCED_BY_RELATION = NO
-
-# If the REFERENCES_RELATION tag is set to YES then for each documented function
-# all documented entities called/used by that function will be listed.
-# The default value is: NO.
-
-REFERENCES_RELATION    = NO
-
-# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
-# to YES then the hyperlinks from functions in REFERENCES_RELATION and
-# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
-# link to the documentation.
-# The default value is: YES.
-
-REFERENCES_LINK_SOURCE = YES
-
-# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
-# source code will show a tooltip with additional information such as prototype,
-# brief description and links to the definition and documentation. Since this
-# will make the HTML file larger and loading of large files a bit slower, you
-# can opt to disable this feature.
-# The default value is: YES.
-# This tag requires that the tag SOURCE_BROWSER is set to YES.
-
-SOURCE_TOOLTIPS        = YES
-
-# If the USE_HTAGS tag is set to YES then the references to source code will
-# point to the HTML generated by the htags(1) tool instead of doxygen built-in
-# source browser. The htags tool is part of GNU's global source tagging system
-# (see https://www.gnu.org/software/global/global.html). You will need version
-# 4.8.6 or higher.
-#
-# To use it do the following:
-# - Install the latest version of global
-# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
-# - Make sure the INPUT points to the root of the source tree
-# - Run doxygen as normal
-#
-# Doxygen will invoke htags (and that will in turn invoke gtags), so these
-# tools must be available from the command line (i.e. in the search path).
-#
-# The result: instead of the source browser generated by doxygen, the links to
-# source code will now point to the output of htags.
-# The default value is: NO.
-# This tag requires that the tag SOURCE_BROWSER is set to YES.
-
-USE_HTAGS              = NO
-
-# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
-# verbatim copy of the header file for each class for which an include is
-# specified. Set to NO to disable this.
-# See also: Section \class.
-# The default value is: YES.
-
-VERBATIM_HEADERS       = YES
-
-
-CLANG_ASSISTED_PARSING = true
-
-#---------------------------------------------------------------------------
-# Configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
-# compounds will be generated. Enable this if the project contains a lot of
-# classes, structs, unions or interfaces.
-# The default value is: YES.
-
-ALPHABETICAL_INDEX     = YES
-
-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
-# which the alphabetical index list will be split.
-# Minimum value: 1, maximum value: 20, default value: 5.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-COLS_IN_ALPHA_INDEX    = 2
-
-# In case all classes in a project start with a common prefix, all classes will
-# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
-# can be used to specify a prefix (or a list of prefixes) that should be ignored
-# while generating the index headers.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-IGNORE_PREFIX          =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
-# The default value is: YES.
-
-GENERATE_HTML          = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
-# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
-# it.
-# The default directory is: html.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_OUTPUT            = html
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
-# generated HTML page (for example: .htm, .php, .asp).
-# The default value is: .html.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_FILE_EXTENSION    = .html
-
-# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
-# each generated HTML page. If the tag is left blank doxygen will generate a
-# standard header.
-#
-# To get valid HTML the header file that includes any scripts and style sheets
-# that doxygen needs, which is dependent on the configuration options used (e.g.
-# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
-# default header using
-# doxygen -w html new_header.html new_footer.html new_stylesheet.css
-# YourConfigFile
-# and then modify the file new_header.html. See also section "Doxygen usage"
-# for information on how to generate the default header that doxygen normally
-# uses.
-# Note: The header is subject to change so you typically have to regenerate the
-# default header when upgrading to a newer version of doxygen. For a description
-# of the possible markers and block names see the documentation.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_HEADER            = @OpenGR_DOC_DIRECTORY@/html/header.html
-
-# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
-# generated HTML page. If the tag is left blank doxygen will generate a standard
-# footer. See HTML_HEADER for more information on how to generate a default
-# footer and what special commands can be used inside the footer. See also
-# section "Doxygen usage" for information on how to generate the default footer
-# that doxygen normally uses.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_FOOTER            = @OpenGR_DOC_DIRECTORY@/html/footer.html
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
-# sheet that is used by each HTML page. It can be used to fine-tune the look of
-# the HTML output. If left blank doxygen will generate a default style sheet.
-# See also section "Doxygen usage" for information on how to generate the style
-# sheet that doxygen normally uses.
-# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
-# it is more robust and this tag (HTML_STYLESHEET) will in the future become
-# obsolete.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_STYLESHEET        =
-
-# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
-# cascading style sheets that are included after the standard style sheets
-# created by doxygen. Using this option one can overrule certain style aspects.
-# This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefore more robust against future updates.
-# Doxygen will copy the style sheet files to the output directory.
-# Note: The order of the extra style sheet files is of importance (e.g. the last
-# style sheet in the list overrules the setting of the previous ones in the
-# list). For an example see the documentation.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_EXTRA_STYLESHEET  = @OpenGR_DOC_DIRECTORY@/html/customdoxygen.css
-
-# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
-# other source files which should be copied to the HTML output directory. Note
-# that these files will be copied to the base HTML output directory. Use the
-# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
-# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
-# files will be copied as-is; there are no commands or markers available.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_EXTRA_FILES       = @OpenGR_DOC_DIRECTORY@/html/doxy-boot.js
-
-# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
-# will adjust the colors in the style sheet and background images according to
-# this color. Hue is specified as an angle on a colorwheel, see
-# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
-# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
-# purple, and 360 is red again.
-# Minimum value: 0, maximum value: 359, default value: 220.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_COLORSTYLE_HUE    = 242
-
-# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
-# in the HTML output. For a value of 0 the output will use grayscales only. A
-# value of 255 will produce the most vivid colors.
-# Minimum value: 0, maximum value: 255, default value: 100.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_COLORSTYLE_SAT    = 50
-
-# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
-# luminance component of the colors in the HTML output. Values below 100
-# gradually make the output lighter, whereas values above 100 make the output
-# darker. The value divided by 100 is the actual gamma applied, so 80 represents
-# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
-# change the gamma.
-# Minimum value: 40, maximum value: 240, default value: 80.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_COLORSTYLE_GAMMA  = 80
-
-# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
-# page will contain the date and time when the page was generated. Setting this
-# to YES can help to show when doxygen was last run and thus if the
-# documentation is up to date.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_TIMESTAMP         = YES
-
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_DYNAMIC_SECTIONS  = YES
-
-# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
-# shown in the various tree structured indices initially; the user can expand
-# and collapse entries dynamically later on. Doxygen will expand the tree to
-# such a level that at most the specified number of entries are visible (unless
-# a fully collapsed tree already exceeds this amount). So setting the number of
-# entries 1 will produce a full collapsed tree by default. 0 is a special value
-# representing an infinite number of entries and will result in a full expanded
-# tree by default.
-# Minimum value: 0, maximum value: 9999, default value: 100.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_INDEX_NUM_ENTRIES = 100
-
-# If the GENERATE_DOCSET tag is set to YES, additional index files will be
-# generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: https://developer.apple.com/tools/xcode/), introduced with
-# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
-# Makefile in the HTML output directory. Running make will produce the docset in
-# that directory and running make install will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
-# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_DOCSET        = NO
-
-# This tag determines the name of the docset feed. A documentation feed provides
-# an umbrella under which multiple documentation sets from a single provider
-# (such as a company or product suite) can be grouped.
-# The default value is: Doxygen generated docs.
-# This tag requires that the tag GENERATE_DOCSET is set to YES.
-
-DOCSET_FEEDNAME        = "Doxygen generated docs"
-
-# This tag specifies a string that should uniquely identify the documentation
-# set bundle. This should be a reverse domain-name style string, e.g.
-# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
-# The default value is: org.doxygen.Project.
-# This tag requires that the tag GENERATE_DOCSET is set to YES.
-
-DOCSET_BUNDLE_ID       = org.doxygen.Project
-
-# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
-# the documentation publisher. This should be a reverse domain-name style
-# string, e.g. com.mycompany.MyDocSet.documentation.
-# The default value is: org.doxygen.Publisher.
-# This tag requires that the tag GENERATE_DOCSET is set to YES.
-
-DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
-
-# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
-# The default value is: Publisher.
-# This tag requires that the tag GENERATE_DOCSET is set to YES.
-
-DOCSET_PUBLISHER_NAME  = CNRS
-
-# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
-# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
-# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
-# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
-# Windows.
-#
-# The HTML Help Workshop contains a compiler that can convert all HTML output
-# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
-# files are now used as the Windows 98 help format, and will replace the old
-# Windows help format (.hlp) on all Windows platforms in the future. Compressed
-# HTML files also contain an index, a table of contents, and you can search for
-# words in the documentation. The HTML workshop also contains a viewer for
-# compressed HTML files.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_HTMLHELP      = NO
-
-# The CHM_FILE tag can be used to specify the file name of the resulting .chm
-# file. You can add a path in front of the file if the result should not be
-# written to the html output directory.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-CHM_FILE               =
-
-# The HHC_LOCATION tag can be used to specify the location (absolute path
-# including file name) of the HTML help compiler (hhc.exe). If non-empty,
-# doxygen will try to run the HTML help compiler on the generated index.hhp.
-# The file has to be specified with full path.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-HHC_LOCATION           =
-
-# The GENERATE_CHI flag controls if a separate .chi index file is generated
-# (YES) or that it should be included in the master .chm file (NO).
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-GENERATE_CHI           = NO
-
-# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
-# and project file content.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-CHM_INDEX_ENCODING     =
-
-# The BINARY_TOC flag controls whether a binary table of contents is generated
-# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
-# enables the Previous and Next buttons.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-BINARY_TOC             = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members to
-# the table of contents of the HTML help documentation and to the tree view.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-TOC_EXPAND             = NO
-
-# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
-# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
-# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
-# (.qch) of the generated HTML documentation.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_QHP           = NO
-
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
-# the file name of the resulting .qch file. The path specified is relative to
-# the HTML output folder.
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QCH_FILE               =
-
-# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
-# Project output. For more information please see Qt Help Project / Namespace
-# (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace).
-# The default value is: org.doxygen.Project.
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_NAMESPACE          = org.doxygen.Project
-
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
-# Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders).
-# The default value is: doc.
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_VIRTUAL_FOLDER     = doc
-
-# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
-# filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters).
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_CUST_FILTER_NAME   =
-
-# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters).
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_CUST_FILTER_ATTRS  =
-
-# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
-# project's filter section matches. Qt Help Project / Filter Attributes (see:
-# http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes).
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_SECT_FILTER_ATTRS  =
-
-# The QHG_LOCATION tag can be used to specify the location of Qt's
-# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
-# generated .qhp file.
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHG_LOCATION           =
-
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
-# generated, together with the HTML files, they form an Eclipse help plugin. To
-# install this plugin and make it available under the help contents menu in
-# Eclipse, the contents of the directory containing the HTML and XML files needs
-# to be copied into the plugins directory of eclipse. The name of the directory
-# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
-# After copying Eclipse needs to be restarted before the help appears.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_ECLIPSEHELP   = NO
-
-# A unique identifier for the Eclipse help plugin. When installing the plugin
-# the directory name containing the HTML and XML files should also have this
-# name. Each documentation set should have its own identifier.
-# The default value is: org.doxygen.Project.
-# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
-
-ECLIPSE_DOC_ID         = org.doxygen.Project
-
-# If you want full control over the layout of the generated HTML pages it might
-# be necessary to disable the index and replace it with your own. The
-# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
-# of each HTML page. A value of NO enables the index and the value YES disables
-# it. Since the tabs in the index contain the same information as the navigation
-# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-DISABLE_INDEX          = NO
-
-# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information. If the tag
-# value is set to YES, a side panel will be generated containing a tree-like
-# index structure (just like the one that is generated for HTML Help). For this
-# to work a browser that supports JavaScript, DHTML, CSS and frames is required
-# (i.e. any modern browser). Windows users are probably better off using the
-# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
-# further fine-tune the look of the index. As an example, the default style
-# sheet generated by doxygen has an example that shows how to put an image at
-# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
-# the same information as the tab index, you could consider setting
-# DISABLE_INDEX to YES when enabling this option.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-# GENERATE_TREEVIEW      = NO
-
-# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
-# doxygen will group on one line in the generated HTML documentation.
-#
-# Note that a value of 0 will completely suppress the enum values from appearing
-# in the overview section.
-# Minimum value: 0, maximum value: 20, default value: 4.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-ENUM_VALUES_PER_LINE   = 4
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
-# to set the initial width (in pixels) of the frame in which the tree is shown.
-# Minimum value: 0, maximum value: 1500, default value: 250.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-TREEVIEW_WIDTH         = 250
-
-# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
-# external symbols imported via tag files in a separate window.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-EXT_LINKS_IN_WINDOW    = YES
-
-# Use this tag to change the font size of LaTeX formulas included as images in
-# the HTML documentation. When you change the font size after a successful
-# doxygen run you need to manually remove any form_*.png images from the HTML
-# output directory to force them to be regenerated.
-# Minimum value: 8, maximum value: 50, default value: 10.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-FORMULA_FONTSIZE       = 10
-
-# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are not
-# supported properly for IE 6.0, but are supported on all modern browsers.
-#
-# Note that when changing this option you need to delete any form_*.png files in
-# the HTML output directory before the changes have effect.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-FORMULA_TRANSPARENT    = YES
-
-# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# https://www.mathjax.org) which uses client side Javascript for the rendering
-# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
-# installed or if you want to formulas look prettier in the HTML output. When
-# enabled you may also need to install MathJax separately and configure the path
-# to it using the MATHJAX_RELPATH option.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-USE_MATHJAX            = YES
-
-# When MathJax is enabled you can set the default output format to be used for
-# the MathJax output. See the MathJax site (see:
-# http://docs.mathjax.org/en/latest/output.html) for more details.
-# Possible values are: HTML-CSS (which is slower, but has the best
-# compatibility), NativeMML (i.e. MathML) and SVG.
-# The default value is: HTML-CSS.
-# This tag requires that the tag USE_MATHJAX is set to YES.
-
-MATHJAX_FORMAT         = HTML-CSS
-
-# When MathJax is enabled you need to specify the location relative to the HTML
-# output directory using the MATHJAX_RELPATH option. The destination directory
-# should contain the MathJax.js script. For instance, if the mathjax directory
-# is located at the same level as the HTML output directory, then
-# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
-# Content Delivery Network so you can quickly see the result without installing
-# MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from https://www.mathjax.org before deployment.
-# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/.
-# This tag requires that the tag USE_MATHJAX is set to YES.
-
-MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
-
-# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
-# extension names that should be enabled during MathJax rendering. For example
-# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
-# This tag requires that the tag USE_MATHJAX is set to YES.
-
-MATHJAX_EXTENSIONS     = TeX/AMSsymbols \
-                         TeX/AMSmath
-
-# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
-# of code that will be used on startup of the MathJax code. See the MathJax site
-# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
-# example see the documentation.
-# This tag requires that the tag USE_MATHJAX is set to YES.
-
-MATHJAX_CODEFILE       =
-
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
-# the HTML output. The underlying search engine uses javascript and DHTML and
-# should work on any modern browser. Note that when using HTML help
-# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
-# there is already a search function so this one should typically be disabled.
-# For large projects the javascript based search engine can be slow, then
-# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
-# search using the keyboard; to jump to the search box use  + S
-# (what the  is depends on the OS and browser, but it is typically
-# , /